summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/ata/libata-core.c15
-rw-r--r--drivers/ata/libata-pmp.c12
-rw-r--r--drivers/ata/sata_fsl.c8
-rw-r--r--drivers/cpufreq/Kconfig.powerpc10
-rw-r--r--drivers/cpufreq/Makefile1
-rw-r--r--drivers/cpufreq/mpc85xx-cpufreq.c406
-rw-r--r--drivers/cpufreq/ppc-corenet-cpufreq.c3
-rw-r--r--drivers/crypto/Kconfig12
-rw-r--r--drivers/crypto/caam/Kconfig62
-rw-r--r--drivers/crypto/caam/Makefile13
-rw-r--r--drivers/crypto/caam/caamalg.c1566
-rw-r--r--drivers/crypto/caam/caamalg_qi.c2260
-rw-r--r--drivers/crypto/caam/caamhash.c76
-rw-r--r--drivers/crypto/caam/caampkc.c1496
-rw-r--r--drivers/crypto/caam/caamrng.c32
-rw-r--r--drivers/crypto/caam/compat.h1
-rw-r--r--drivers/crypto/caam/ctrl.c595
-rw-r--r--drivers/crypto/caam/ctrl.h2
-rw-r--r--drivers/crypto/caam/desc.h49
-rw-r--r--drivers/crypto/caam/desc_constr.h34
-rw-r--r--drivers/crypto/caam/fsl_jr_uio.c267
-rw-r--r--drivers/crypto/caam/fsl_jr_uio.h20
-rw-r--r--drivers/crypto/caam/intern.h36
-rw-r--r--drivers/crypto/caam/jr.c557
-rw-r--r--drivers/crypto/caam/jr.h5
-rw-r--r--drivers/crypto/caam/key_gen.h6
-rw-r--r--drivers/crypto/caam/pdb.h222
-rw-r--r--drivers/crypto/caam/pkc_desc.c383
-rw-r--r--drivers/crypto/caam/pkc_desc.h222
-rw-r--r--drivers/crypto/caam/qi.c950
-rw-r--r--drivers/crypto/caam/qi.h157
-rw-r--r--drivers/crypto/caam/regs.h14
-rw-r--r--drivers/crypto/caam/sg_sw_qm.h82
-rw-r--r--drivers/crypto/caam/sg_sw_sec4.h34
-rw-r--r--drivers/crypto/dcp.c49
-rw-r--r--drivers/crypto/talitos.c103
-rw-r--r--drivers/dma/Kconfig36
-rw-r--r--drivers/dma/Makefile2
-rw-r--r--drivers/dma/amba-pl08x.c44
-rw-r--r--drivers/dma/at_hdmac.c28
-rw-r--r--drivers/dma/bestcomm/sram.c1
-rw-r--r--drivers/dma/coh901318.c4
-rw-r--r--drivers/dma/cppi41.c178
-rw-r--r--drivers/dma/dma-jz4740.c2
-rw-r--r--drivers/dma/dmaengine.c264
-rw-r--r--drivers/dma/dmatest.c917
-rw-r--r--drivers/dma/dw/core.c29
-rw-r--r--drivers/dma/dw/platform.c8
-rw-r--r--drivers/dma/edma.c379
-rw-r--r--drivers/dma/ep93xx_dma.c30
-rw-r--r--drivers/dma/fsl_raid.c889
-rw-r--r--drivers/dma/fsl_raid.h319
-rw-r--r--drivers/dma/fsldma.c483
-rw-r--r--drivers/dma/fsldma.h21
-rw-r--r--drivers/dma/imx-dma.c42
-rw-r--r--drivers/dma/imx-sdma.c14
-rw-r--r--drivers/dma/intel_mid_dma.c4
-rw-r--r--drivers/dma/ioat/dma.c53
-rw-r--r--drivers/dma/ioat/dma.h14
-rw-r--r--drivers/dma/ioat/dma_v2.c2
-rw-r--r--drivers/dma/ioat/dma_v2.h1
-rw-r--r--drivers/dma/ioat/dma_v3.c275
-rw-r--r--drivers/dma/ioat/pci.c20
-rw-r--r--drivers/dma/iop-adma.c113
-rw-r--r--drivers/dma/ipu/ipu_idmac.c6
-rw-r--r--drivers/dma/k3dma.c4
-rw-r--r--drivers/dma/mmp_pdma.c7
-rw-r--r--drivers/dma/mmp_tdma.c47
-rw-r--r--drivers/dma/mpc512x_dma.c2
-rw-r--r--drivers/dma/mv_xor.c58
-rw-r--r--drivers/dma/mv_xor.h25
-rw-r--r--drivers/dma/mxs-dma.c178
-rw-r--r--drivers/dma/omap-dma.c2
-rw-r--r--drivers/dma/pl330.c36
-rw-r--r--drivers/dma/ppc4xx/adma.c274
-rw-r--r--drivers/dma/s3c24xx-dma.c1321
-rw-r--r--drivers/dma/sa11x0-dma.c2
-rw-r--r--drivers/dma/sh/shdma-base.c2
-rw-r--r--drivers/dma/sh/shdmac.c4
-rw-r--r--drivers/dma/ste_dma40.c7
-rw-r--r--drivers/dma/tegra20-apb-dma.c6
-rw-r--r--drivers/dma/timb_dma.c37
-rw-r--r--drivers/dma/txx9dmac.c29
-rw-r--r--drivers/edac/Kconfig4
-rw-r--r--drivers/edac/edac_pci.c6
-rw-r--r--drivers/edac/mpc85xx_edac.c107
-rw-r--r--drivers/edac/mpc85xx_edac.h8
-rw-r--r--drivers/i2c/busses/i2c-mpc.c11
-rw-r--r--drivers/iommu/Kconfig12
-rw-r--r--drivers/iommu/fsl_pamu.c228
-rw-r--r--drivers/iommu/fsl_pamu.h9
-rw-r--r--drivers/iommu/fsl_pamu_domain.c370
-rw-r--r--drivers/iommu/fsl_pamu_domain.h14
-rw-r--r--drivers/iommu/iommu.c10
-rw-r--r--drivers/misc/Kconfig43
-rw-r--r--drivers/misc/Makefile5
-rw-r--r--drivers/misc/fsl_dcm.c770
-rw-r--r--drivers/misc/fsl_dcm.h129
-rw-r--r--drivers/mmc/card/block.c77
-rw-r--r--drivers/mmc/card/queue.c102
-rw-r--r--drivers/mmc/card/queue.h5
-rw-r--r--drivers/mmc/core/core.c50
-rw-r--r--drivers/mmc/host/sdhci-esdhc.h29
-rw-r--r--drivers/mmc/host/sdhci-of-esdhc.c255
-rw-r--r--drivers/mmc/host/sdhci-pltfm.c21
-rw-r--r--drivers/mmc/host/sdhci.c53
-rw-r--r--drivers/mmc/host/sdhci.h6
-rw-r--r--drivers/mtd/devices/m25p80.c28
-rw-r--r--drivers/mtd/nand/fsl_ifc_nand.c111
-rw-r--r--drivers/net/Kconfig142
-rw-r--r--drivers/net/ethernet/freescale/Kconfig16
-rw-r--r--drivers/net/ethernet/freescale/Makefile9
-rw-r--r--drivers/net/ethernet/freescale/asf_gianfar.c624
-rw-r--r--drivers/net/ethernet/freescale/asf_gianfar.h58
-rw-r--r--drivers/net/ethernet/freescale/dpa/Kconfig137
-rw-r--r--drivers/net/ethernet/freescale/dpa/Makefile31
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_1588.c591
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_1588.h138
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_debugfs.c280
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_debugfs.h41
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth.c1123
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth.h618
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth_base.c221
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth_base.h46
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth_common.c1682
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth_common.h224
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth_generic.c1508
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth_generic.h82
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth_generic_sysfs.c201
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth_macless.c516
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth_proxy.c372
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth_sg.c941
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth_shared.c885
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth_sysfs.c248
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_eth_trace.h144
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_ethtool.c343
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_generic_debugfs.c283
-rw-r--r--drivers/net/ethernet/freescale/dpa/dpaa_generic_debugfs.h41
-rw-r--r--drivers/net/ethernet/freescale/dpa/mac-api.c775
-rw-r--r--drivers/net/ethernet/freescale/dpa/mac.c462
-rw-r--r--drivers/net/ethernet/freescale/dpa/mac.h127
-rw-r--r--drivers/net/ethernet/freescale/dpa/offline_port.c878
-rw-r--r--drivers/net/ethernet/freescale/dpa/offline_port.h59
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c31
-rw-r--r--drivers/net/ethernet/freescale/fman/Kconfig156
-rw-r--r--drivers/net/ethernet/freescale/fman/Makefile11
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/HC/Makefile15
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/HC/hc.c1225
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/Makefile21
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec.c1516
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec.h228
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec_mii_acc.c97
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec_mii_acc.h42
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fm_mac.c642
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fm_mac.h224
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_crc32.c119
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_crc32.h43
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_dtsec.c846
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_dtsec_mii_acc.c163
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_memac.c504
-rwxr-xr-xdrivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_memac_mii_acc.c213
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_tgec.c367
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac.c1122
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac.h109
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac_mii_acc.c78
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac_mii_acc.h73
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec.c1017
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec.h151
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec_mii_acc.c139
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec_mii_acc.h80
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Makefile22
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/Makefile19
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/crc64.h360
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.c7120
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.h402
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_kg.c3287
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_kg.h206
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_manip.c4218
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_manip.h481
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd.c2117
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd.h540
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd_ipc.h280
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_plcr.c1937
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_plcr.h165
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_prs.c465
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_prs.h193
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_replic.c994
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_replic.h101
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fman_kg.c888
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fman_prs.c129
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/Makefile15
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.c5858
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.h987
-rwxr-xr-xdrivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port_dsar.h494
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port_im.c754
-rwxr-xr-xdrivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fman_port.c1574
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/Makefile15
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/fm_rtc.c711
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/fm_rtc.h96
-rwxr-xr-xdrivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/fman_rtc.c334
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/Makefile15
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/fm_sp.c757
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/fm_sp.h85
-rwxr-xr-xdrivers/net/ethernet/freescale/fman/Peripherals/FM/SP/fman_sp.c197
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.c5227
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.h695
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/fm_ipc.h464
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/fm_muram.c175
-rwxr-xr-xdrivers/net/ethernet/freescale/fman/Peripherals/FM/fman.c1399
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_common.h1165
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_hc.h91
-rw-r--r--drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_sp_common.h117
-rw-r--r--drivers/net/ethernet/freescale/fman/etc/Makefile12
-rw-r--r--drivers/net/ethernet/freescale/fman/etc/error.c95
-rw-r--r--drivers/net/ethernet/freescale/fman/etc/list.c71
-rw-r--r--drivers/net/ethernet/freescale/fman/etc/memcpy.c601
-rw-r--r--drivers/net/ethernet/freescale/fman/etc/mm.c1142
-rw-r--r--drivers/net/ethernet/freescale/fman/etc/mm.h105
-rw-r--r--drivers/net/ethernet/freescale/fman/etc/sprint.c81
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/Peripherals/crc_mac_addr_ext.h364
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/Peripherals/dpaa_ext.h207
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_ext.h1684
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_mac_ext.h846
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_muram_ext.h170
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_pcd_ext.h3714
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_port_ext.h2567
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_rtc_ext.h593
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_vsp_ext.h411
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/Peripherals/mii_acc_ext.h76
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/core_ext.h86
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/cores/e500v2_ext.h476
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/cores/ppc_ext.h141
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/ctype_ext.h94
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/ddr_std_ext.h77
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/debug_ext.h266
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/endian_ext.h447
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/enet_ext.h203
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/error_ext.h529
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/etc/list_ext.h358
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/etc/mem_ext.h318
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/etc/memcpy_ext.h174
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/etc/mm_ext.h310
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/etc/sprint_ext.h118
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/flib/common/arch/ppc_access.h37
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/flib/common/general.h51
-rwxr-xr-xdrivers/net/ethernet/freescale/fman/inc/flib/fman_common.h78
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/flib/fsl_enet.h272
-rwxr-xr-xdrivers/net/ethernet/freescale/fman/inc/flib/fsl_fman.h826
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_dtsec.h1096
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_dtsec_mii_acc.h107
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_kg.h514
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_memac.h425
-rwxr-xr-xdrivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_memac_mii_acc.h78
-rwxr-xr-xdrivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_port.h594
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_prs.h102
-rwxr-xr-xdrivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_rtc.h449
-rwxr-xr-xdrivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_sp.h138
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_tgec.h479
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/integrations/P1023/dpaa_integration_ext.h238
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/integrations/P1023/part_ext.h82
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/integrations/P1023/part_integration_ext.h635
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/integrations/P3040_P4080_P5020/dpaa_integration_ext.h266
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/integrations/P3040_P4080_P5020/part_ext.h83
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/integrations/P3040_P4080_P5020/part_integration_ext.h336
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/integrations/T4240/dpaa_integration_ext.h281
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/integrations/T4240/part_ext.h71
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/integrations/T4240/part_integration_ext.h304
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/math_ext.h99
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/ncsw_ext.h432
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/net_ext.h430
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/std_ext.h48
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/stdarg_ext.h49
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/stdlib_ext.h162
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/string_ext.h56
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/types_ext.h104
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/xx_common.h56
-rw-r--r--drivers/net/ethernet/freescale/fman/inc/xx_ext.h791
-rw-r--r--drivers/net/ethernet/freescale/fman/ncsw_config.mk41
-rw-r--r--drivers/net/ethernet/freescale/fman/p1023_dflags.h65
-rw-r--r--drivers/net/ethernet/freescale/fman/p3040_4080_5020_dflags.h62
-rw-r--r--drivers/net/ethernet/freescale/fman/src/Makefile11
-rw-r--r--drivers/net/ethernet/freescale/fman/src/inc/system/sys_ext.h118
-rw-r--r--drivers/net/ethernet/freescale/fman/src/inc/system/sys_io_ext.h46
-rw-r--r--drivers/net/ethernet/freescale/fman/src/inc/types_linux.h200
-rw-r--r--drivers/net/ethernet/freescale/fman/src/inc/wrapper/fsl_fman_test.h84
-rw-r--r--drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_exp_sym.h127
-rw-r--r--drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fm_ext.h163
-rw-r--r--drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fsl_fman.h657
-rw-r--r--drivers/net/ethernet/freescale/fman/src/inc/xx/xx.h50
-rw-r--r--drivers/net/ethernet/freescale/fman/src/system/Makefile10
-rw-r--r--drivers/net/ethernet/freescale/fman/src/system/sys_io.c171
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/Makefile20
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/fman_test.c1665
-rwxr-xr-xdrivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.c1964
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.h290
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm_port.c1418
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm.c4556
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.c1241
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.h691
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources.c1189
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources.h121
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.c191
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.h144
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.make28
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs.c60
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs.h60
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm.c1809
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm.h136
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.c1242
-rw-r--r--drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.h56
-rw-r--r--drivers/net/ethernet/freescale/fman/src/xx/Makefile12
-rw-r--r--drivers/net/ethernet/freescale/fman/src/xx/module_strings.c45
-rw-r--r--drivers/net/ethernet/freescale/fman/src/xx/stdlib.c264
-rw-r--r--drivers/net/ethernet/freescale/fman/src/xx/udivdi3.c132
-rw-r--r--drivers/net/ethernet/freescale/fman/src/xx/xx_linux.c910
-rw-r--r--drivers/net/ethernet/freescale/fman/t4240_dflags.h57
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c1751
-rw-r--r--drivers/net/ethernet/freescale/gianfar.h479
-rw-r--r--drivers/net/ethernet/freescale/gianfar_1588.c736
-rw-r--r--drivers/net/ethernet/freescale/gianfar_ethtool.c263
-rw-r--r--drivers/net/ethernet/freescale/gianfar_ptp.c2
-rw-r--r--drivers/net/ethernet/freescale/gianfar_sysfs.c341
-rw-r--r--drivers/net/ethernet/freescale/xgmac_mdio.c65
-rw-r--r--drivers/net/phy/Kconfig15
-rw-r--r--drivers/net/phy/Makefile3
-rw-r--r--drivers/net/phy/at803x.c43
-rw-r--r--drivers/net/phy/atheros.c97
-rw-r--r--drivers/net/phy/dp8384x.c93
-rw-r--r--drivers/net/phy/fsl_10gkr.c1263
-rw-r--r--drivers/net/phy/marvell.c12
-rw-r--r--drivers/net/phy/phy_device.c143
-rw-r--r--drivers/net/phy/vitesse.c132
-rw-r--r--drivers/net/ppp/ppp_generic.c28
-rw-r--r--drivers/net/wan/Kconfig10
-rw-r--r--drivers/net/wan/Makefile1
-rw-r--r--drivers/net/wan/fsl_ucc_hdlc.c1404
-rw-r--r--drivers/net/wan/fsl_ucc_hdlc.h191
-rw-r--r--drivers/of/of_mdio.c22
-rw-r--r--drivers/of/platform.c18
-rw-r--r--drivers/pci/msi.c26
-rw-r--r--drivers/platform/Kconfig1
-rw-r--r--drivers/platform/Makefile1
-rw-r--r--drivers/platform/fsl/Kconfig10
-rw-r--r--drivers/platform/fsl/Makefile5
-rw-r--r--drivers/platform/fsl/sleep_fsm.c342
-rw-r--r--drivers/rtc/rtc-ds3232.c6
-rw-r--r--drivers/spi/spi-fsl-espi.c61
-rw-r--r--drivers/staging/Kconfig10
-rw-r--r--drivers/staging/Makefile5
-rw-r--r--drivers/staging/fsl_dce/Kconfig32
-rw-r--r--drivers/staging/fsl_dce/Makefile14
-rw-r--r--drivers/staging/fsl_dce/dce_debugfs.c282
-rw-r--r--drivers/staging/fsl_dce/dce_driver.c347
-rw-r--r--drivers/staging/fsl_dce/dce_sys.c273
-rw-r--r--drivers/staging/fsl_dce/dce_sys.h68
-rw-r--r--drivers/staging/fsl_dce/flib/bitfield_macros.h146
-rw-r--r--drivers/staging/fsl_dce/flib/dce_defs.h1924
-rw-r--r--drivers/staging/fsl_dce/flib/dce_flow.c513
-rw-r--r--drivers/staging/fsl_dce/flib/dce_flow.h447
-rw-r--r--drivers/staging/fsl_dce/flib/dce_gzip_helper.h104
-rw-r--r--drivers/staging/fsl_dce/flib/dce_helper.h111
-rw-r--r--drivers/staging/fsl_dce/flib/dce_regs.h546
-rw-r--r--drivers/staging/fsl_dce/fsl_dce.h60
-rw-r--r--drivers/staging/fsl_dce/fsl_dce_chunk.c154
-rw-r--r--drivers/staging/fsl_dce/fsl_dce_chunk.h86
-rw-r--r--drivers/staging/fsl_dce/fsl_dce_stream.c306
-rw-r--r--drivers/staging/fsl_dce/fsl_dce_stream.h187
-rw-r--r--drivers/staging/fsl_dce/tests/Makefile2
-rw-r--r--drivers/staging/fsl_dce/tests/chunk_comp_def_cf/Makefile3
-rw-r--r--drivers/staging/fsl_dce/tests/chunk_comp_def_cf/dce_chunk_comp_def_cf_test.c694
-rw-r--r--drivers/staging/fsl_dce/tests/common/Makefile7
-rw-r--r--drivers/staging/fsl_dce/tests/common/bible.txt.128b.h14
-rw-r--r--drivers/staging/fsl_dce/tests/common/bible.txt.128k.h10926
-rw-r--r--drivers/staging/fsl_dce/tests/common/bible.txt.16k.h1369
-rw-r--r--drivers/staging/fsl_dce/tests/common/bible.txt.1k.h89
-rw-r--r--drivers/staging/fsl_dce/tests/common/bible.txt.2k.h174
-rw-r--r--drivers/staging/fsl_dce/tests/common/bible.txt.32k.h2734
-rw-r--r--drivers/staging/fsl_dce/tests/common/bible.txt.4k.h345
-rw-r--r--drivers/staging/fsl_dce/tests/common/bible.txt.64k.h5465
-rw-r--r--drivers/staging/fsl_dce/tests/common/bible.txt.8k.h686
-rw-r--r--drivers/staging/fsl_dce/tests/common/paper5_11954.h1000
-rw-r--r--drivers/staging/fsl_dce/tests/common/paper5_2048.h174
-rw-r--r--drivers/staging/fsl_dce/tests/common/paper5_4096.h345
-rw-r--r--drivers/staging/fsl_dce/tests/common/paper5_8192.h686
-rw-r--r--drivers/staging/fsl_dce/tests/common/paper6_12K_compressed.gz.h1029
-rw-r--r--drivers/staging/fsl_dce/tests/common/paper6_2K_compressed.gz.h173
-rw-r--r--drivers/staging/fsl_dce/tests/common/paper6_4K_compressed.gz.h344
-rw-r--r--drivers/staging/fsl_dce/tests/common/paper6_8K_compressed.gz.h682
-rw-r--r--drivers/staging/fsl_dce/tests/common/test_frame_helpers.c723
-rw-r--r--drivers/staging/fsl_dce/tests/common/test_frame_helpers.h172
-rw-r--r--drivers/staging/fsl_dce/tests/performance_simple/Makefile3
-rw-r--r--drivers/staging/fsl_dce/tests/performance_simple/README89
-rw-r--r--drivers/staging/fsl_dce/tests/performance_simple/dce_perf_simple.c985
-rw-r--r--drivers/staging/fsl_dpa_offload/Kconfig17
-rw-r--r--drivers/staging/fsl_dpa_offload/Makefile49
-rw-r--r--drivers/staging/fsl_dpa_offload/cq.c289
-rw-r--r--drivers/staging/fsl_dpa_offload/cq.h141
-rw-r--r--drivers/staging/fsl_dpa_offload/dpa_classifier.c8030
-rw-r--r--drivers/staging/fsl_dpa_offload/dpa_classifier.h708
-rw-r--r--drivers/staging/fsl_dpa_offload/dpa_classifier_ioctl.h847
-rw-r--r--drivers/staging/fsl_dpa_offload/dpa_ipsec.c5882
-rw-r--r--drivers/staging/fsl_dpa_offload/dpa_ipsec.h539
-rw-r--r--drivers/staging/fsl_dpa_offload/dpa_ipsec_desc.c2089
-rw-r--r--drivers/staging/fsl_dpa_offload/dpa_ipsec_desc.h98
-rw-r--r--drivers/staging/fsl_dpa_offload/dpa_ipsec_ioctl.h331
-rw-r--r--drivers/staging/fsl_dpa_offload/dpa_offload_module.c102
-rw-r--r--drivers/staging/fsl_dpa_offload/dpa_offload_module.h46
-rw-r--r--drivers/staging/fsl_dpa_offload/dpa_stats.c4534
-rw-r--r--drivers/staging/fsl_dpa_offload/dpa_stats.h214
-rw-r--r--drivers/staging/fsl_dpa_offload/dpa_stats_ioctl.h312
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/b4420qds-usdpaa-shared-interfaces.dts160
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/b4420qds-usdpaa.dts154
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/b4420si-chosen-offld.dtsi31
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/b4420si-chosen-reass.dtsi29
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/b4420si-pre.dtsi116
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/b4860qds-usdpaa-shared-interfaces.dts187
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/b4860qds-usdpaa-srio-eth-shared-interfaces.dts150
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/b4860qds-usdpaa.dts166
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/b4860si-chosen-offld.dtsi31
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/b4860si-chosen-reass.dtsi29
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/b4860si-pre.dtsi169
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/p2041rdb-usdpaa-shared-interfaces.dts162
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/p2041rdb-usdpaa.dts154
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/p2041si-chosen-offld.dtsi21
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/p2041si-pre.dtsi124
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/p4080ds-usdpaa-shared-interfaces-for-ipsec-multiple-intances.dts218
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/p4080ds-usdpaa-shared-interfaces.dts191
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/p4080ds-usdpaa.dts176
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/p4080si-chosen-offld.dtsi21
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/p4080si-pre.dtsi162
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/p5020ds-usdpaa.dts129
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/p5020si-post.dtsi437
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/t2080qds-usdpaa-shared-interfaces.dts182
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/t2080qds-usdpaa.dts165
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/t2080si-chosen-offld.dtsi31
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/t2080si-chosen-reass.dtsi29
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/t208xsi-pre.dtsi117
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/t4240qds-usdpaa-shared-interfaces.dts184
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/t4240qds-usdpaa-shared-interfaces_for_ipsec_multiple_instances.dts210
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/t4240qds-usdpaa.dts162
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/t4240si-chosen-offld.dtsi32
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/t4240si-chosen-reass.dtsi29
-rw-r--r--drivers/staging/fsl_dpa_offload/dts/t4240si-pre.dtsi175
-rw-r--r--drivers/staging/fsl_dpa_offload/wrp_dpa_classifier.c3032
-rw-r--r--drivers/staging/fsl_dpa_offload/wrp_dpa_classifier.h87
-rw-r--r--drivers/staging/fsl_dpa_offload/wrp_dpa_ipsec.c1643
-rw-r--r--drivers/staging/fsl_dpa_offload/wrp_dpa_ipsec.h60
-rw-r--r--drivers/staging/fsl_dpa_offload/wrp_dpa_stats.c2486
-rw-r--r--drivers/staging/fsl_dpa_offload/wrp_dpa_stats.h113
-rw-r--r--drivers/staging/fsl_pme2/Kconfig226
-rw-r--r--drivers/staging/fsl_pme2/Makefile9
-rw-r--r--drivers/staging/fsl_pme2/pme2_ctrl.c1347
-rw-r--r--drivers/staging/fsl_pme2/pme2_db.c573
-rw-r--r--drivers/staging/fsl_pme2/pme2_high.c1043
-rw-r--r--drivers/staging/fsl_pme2/pme2_low.c277
-rw-r--r--drivers/staging/fsl_pme2/pme2_private.h217
-rw-r--r--drivers/staging/fsl_pme2/pme2_regs.h173
-rw-r--r--drivers/staging/fsl_pme2/pme2_sample_db.c453
-rw-r--r--drivers/staging/fsl_pme2/pme2_scan.c1122
-rw-r--r--drivers/staging/fsl_pme2/pme2_sys.h63
-rw-r--r--drivers/staging/fsl_pme2/pme2_sysfs.c566
-rw-r--r--drivers/staging/fsl_pme2/pme2_test.h74
-rw-r--r--drivers/staging/fsl_pme2/pme2_test_high.c237
-rw-r--r--drivers/staging/fsl_pme2/pme2_test_scan.c653
-rw-r--r--drivers/staging/fsl_qbman/Kconfig209
-rw-r--r--drivers/staging/fsl_qbman/Makefile26
-rw-r--r--drivers/staging/fsl_qbman/bman_config.c726
-rw-r--r--drivers/staging/fsl_qbman/bman_debugfs.c119
-rw-r--r--drivers/staging/fsl_qbman/bman_driver.c547
-rw-r--r--drivers/staging/fsl_qbman/bman_high.c1108
-rw-r--r--drivers/staging/fsl_qbman/bman_low.h524
-rw-r--r--drivers/staging/fsl_qbman/bman_private.h165
-rw-r--r--drivers/staging/fsl_qbman/bman_test.c56
-rw-r--r--drivers/staging/fsl_qbman/bman_test.h44
-rw-r--r--drivers/staging/fsl_qbman/bman_test_high.c181
-rw-r--r--drivers/staging/fsl_qbman/bman_test_thresh.c196
-rw-r--r--drivers/staging/fsl_qbman/dpa_alloc.c699
-rw-r--r--drivers/staging/fsl_qbman/dpa_sys.h301
-rw-r--r--drivers/staging/fsl_qbman/fsl_usdpaa.c1790
-rw-r--r--drivers/staging/fsl_qbman/fsl_usdpaa_irq.c275
-rw-r--r--drivers/staging/fsl_qbman/qbman_driver.c86
-rw-r--r--drivers/staging/fsl_qbman/qman_config.c1146
-rw-r--r--drivers/staging/fsl_qbman/qman_debugfs.c1595
-rw-r--r--drivers/staging/fsl_qbman/qman_driver.c942
-rw-r--r--drivers/staging/fsl_qbman/qman_high.c4948
-rw-r--r--drivers/staging/fsl_qbman/qman_low.h1347
-rw-r--r--drivers/staging/fsl_qbman/qman_private.h379
-rw-r--r--drivers/staging/fsl_qbman/qman_test.c57
-rw-r--r--drivers/staging/fsl_qbman/qman_test.h44
-rw-r--r--drivers/staging/fsl_qbman/qman_test_high.c213
-rw-r--r--drivers/staging/fsl_qbman/qman_test_hotpotato.c497
-rw-r--r--drivers/staging/fsl_qbman/qman_utility.c129
-rw-r--r--drivers/staging/fsl_rman/Kconfig4
-rw-r--r--drivers/staging/fsl_rman/Makefile2
-rw-r--r--drivers/staging/fsl_rman/rman_uio_driver.c349
-rw-r--r--drivers/tdm/Kconfig28
-rw-r--r--drivers/tdm/Makefile8
-rw-r--r--drivers/tdm/device/Kconfig22
-rw-r--r--drivers/tdm/device/Makefile9
-rw-r--r--drivers/tdm/device/fsl_ucc_tdm.c1211
-rw-r--r--drivers/tdm/device/fsl_ucc_tdm.h173
-rw-r--r--drivers/tdm/device/tdm_fsl.c891
-rw-r--r--drivers/tdm/device/tdm_fsl.h444
-rw-r--r--drivers/tdm/line_ctrl/Kconfig18
-rw-r--r--drivers/tdm/line_ctrl/Makefile6
-rw-r--r--drivers/tdm/line_ctrl/pq_mds_t1.c590
-rw-r--r--drivers/tdm/line_ctrl/pq_mds_t1.h424
-rw-r--r--drivers/tdm/line_ctrl/slic_zarlink.c679
-rw-r--r--drivers/tdm/line_ctrl/slic_zarlink.h131
-rw-r--r--drivers/tdm/tdm-core.c1190
-rw-r--r--drivers/tdm/test/Kconfig29
-rw-r--r--drivers/tdm/test/Makefile7
-rw-r--r--drivers/tdm/test/tdm_loopback_test.c251
-rw-r--r--drivers/tdm/test/tdm_test.c251
-rw-r--r--drivers/tdm/test/ucc_tdm_test.c169
-rw-r--r--drivers/tty/serial/8250/8250_core.c20
-rw-r--r--drivers/uio/Kconfig37
-rw-r--r--drivers/uio/Makefile5
-rw-r--r--drivers/uio/fsl_dma_uio.c285
-rw-r--r--drivers/uio/fsl_rmu_uio.c254
-rw-r--r--drivers/uio/fsl_sec_uio.c385
-rw-r--r--drivers/uio/fsl_sram_uio.c330
-rw-r--r--drivers/uio/fsl_srio_uio.c426
-rw-r--r--drivers/uio/uio.c6
-rw-r--r--drivers/usb/core/hub.c2
-rw-r--r--drivers/usb/gadget/fsl_udc_core.c9
-rw-r--r--drivers/usb/host/ehci-fsl.c162
-rw-r--r--drivers/usb/host/ehci-fsl.h3
-rw-r--r--drivers/usb/host/ehci-hub.c9
-rw-r--r--drivers/usb/host/ehci-q.c6
-rw-r--r--drivers/usb/host/ehci.h21
-rw-r--r--drivers/usb/host/fsl-mph-dr-of.c110
-rw-r--r--drivers/usb/phy/phy-fsl-usb.c57
-rw-r--r--drivers/usb/phy/phy-fsl-usb.h8
-rw-r--r--drivers/vfio/Kconfig13
-rw-r--r--drivers/vfio/Makefile3
-rw-r--r--drivers/vfio/fsl_pci_ep/Kconfig8
-rw-r--r--drivers/vfio/fsl_pci_ep/Makefile2
-rw-r--r--drivers/vfio/fsl_pci_ep/fsl_pci_ep.c1661
-rw-r--r--drivers/vfio/fsl_pci_ep/fsl_pci_ep.h94
-rw-r--r--drivers/vfio/fsl_pci_ep/fsl_pci_ep_vfio.c372
-rw-r--r--drivers/vfio/vfio.c4
-rw-r--r--drivers/vfio/vfio_iommu_dummy.c706
-rw-r--r--drivers/vfio/vfio_iommu_fsl_pamu.c1025
-rw-r--r--drivers/video/Kconfig11
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/fsl-diu-fb.c71
-rw-r--r--drivers/video/ssd1289fb.c774
-rw-r--r--drivers/watchdog/Kconfig2
-rw-r--r--drivers/watchdog/booke_wdt.c17
552 files changed, 245713 insertions, 4411 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig
index aa43b91..e82d0ab 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -166,4 +166,6 @@ source "drivers/reset/Kconfig"
source "drivers/fmc/Kconfig"
+source "drivers/tdm/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index ab93de8..1af40e9 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -115,6 +115,7 @@ obj-$(CONFIG_INFINIBAND) += infiniband/
obj-$(CONFIG_SGI_SN) += sn/
obj-y += firmware/
obj-$(CONFIG_CRYPTO) += crypto/
+obj-$(CONFIG_TDM) += tdm/
obj-$(CONFIG_SUPERH) += sh/
obj-$(CONFIG_ARCH_SHMOBILE) += sh/
ifndef CONFIG_ARCH_USES_GETTIMEOFFSET
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index c5d056e..40c6ef3 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2117,6 +2117,21 @@ static int ata_dev_config_ncq(struct ata_device *dev,
dev->flags |= ATA_DFLAG_NCQ;
}
+ if ((ap->flags & ATA_FLAG_BROKENAA) &&
+ (ata_id_has_fpdma_aa(dev->id)) &&
+ (ata_id_enabled_fpdma_aa(dev->id))) {
+ err_mask = ata_dev_set_feature(dev, SETFEATURES_SATA_DISABLE,
+ SATA_FPDMA_AA);
+ if (err_mask) {
+ ata_dev_printk(dev, KERN_ERR, "failed to disable AA"
+ "(error_mask=0x%x)\n", err_mask);
+ /* turn off NCQ if failed disable SATA_FPDMA_AA */
+ hdepth = 1;
+ dev->flags &= ~ATA_DFLAG_NCQ;
+ dev->flags |= ATA_DFLAG_NCQ_OFF;
+ }
+ }
+
if (!(dev->horkage & ATA_HORKAGE_BROKEN_FPDMA_AA) &&
(ap->flags & ATA_FLAG_FPDMA_AA) &&
ata_id_has_fpdma_aa(dev->id)) {
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
index 7ccc084..7700cdf 100644
--- a/drivers/ata/libata-pmp.c
+++ b/drivers/ata/libata-pmp.c
@@ -146,6 +146,13 @@ int sata_pmp_scr_read(struct ata_link *link, int reg, u32 *r_val)
if (reg > SATA_PMP_PSCR_CONTROL)
return -EINVAL;
+ /* For some PMP card, we need delay some time */
+ if (link->flags & ATA_LFLAG_DELAY) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ /* sleep 50 msecond */
+ schedule_timeout(msecs_to_jiffies(50));
+ }
+
err_mask = sata_pmp_read(link, reg, r_val);
if (err_mask) {
ata_link_warn(link, "failed to read SCR %d (Emask=0x%x)\n",
@@ -460,6 +467,11 @@ static void sata_pmp_quirks(struct ata_port *ap)
ATA_LFLAG_NO_SRST |
ATA_LFLAG_ASSUME_ATA;
}
+ } else if (vendor == 0x197b && devid == 0x0325) {
+ /* For jmicron JMB393 card, need some time to ready the PMP */
+ ata_for_each_link(link, ap, EDGE) {
+ link->flags |= ATA_LFLAG_DELAY;
+ }
}
}
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index 851bd3f..1d6d690 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -1512,6 +1512,14 @@ static int sata_fsl_probe(struct platform_device *ofdev)
else
host_priv->data_snoop = DATA_SNOOP_ENABLE_V1;
+ /*
+ * Since erratum A-005636 applies to all platforms, it only be fixed
+ * on T4 rev2.0, we add a flag to identify the erratum in main path.
+ * XXX: for T4 rev2.0 and other new SoCs use same controller as
+ * T4 Rev2.0. this flag should be removed.
+ */
+ pi.flags |= ATA_FLAG_BROKENAA;
+
/* allocate host structure */
host = ata_host_alloc_pinfo(&ofdev->dev, ppi, SATA_FSL_MAX_PORTS);
if (!host) {
diff --git a/drivers/cpufreq/Kconfig.powerpc b/drivers/cpufreq/Kconfig.powerpc
index 25ca9db..e859a1d 100644
--- a/drivers/cpufreq/Kconfig.powerpc
+++ b/drivers/cpufreq/Kconfig.powerpc
@@ -25,6 +25,16 @@ config CPU_FREQ_MAPLE
This adds support for frequency switching on Maple 970FX
Evaluation Board and compatible boards (IBM JS2x blades).
+config MPC85xx_CPUFREQ
+ bool "Support for Freescale MPC85xx CPU freq"
+ depends on PPC_85xx && PPC32 && !PPC_E500MC
+ default n
+ help
+ This adds support for dynamic frequency switching on
+ Freescale MPC85xx by cpufreq interface. MPC8536 and P1022
+ have a JOG feature, which provides a dynamic mechanism
+ to lower or raise the CPU core clock at runtime.
+
config PPC_CORENET_CPUFREQ
tristate "CPU frequency scaling driver for Freescale E500MC SoCs"
depends on PPC_E500MC && OF && COMMON_CLK
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index ad5866c..cc1b57d 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -85,6 +85,7 @@ ppc-cbe-cpufreq-y += ppc_cbe_cpufreq_pervasive.o ppc_cbe_cpufreq.o
obj-$(CONFIG_CPU_FREQ_CBE_PMI) += ppc_cbe_cpufreq_pmi.o
obj-$(CONFIG_CPU_FREQ_MAPLE) += maple-cpufreq.o
obj-$(CONFIG_PPC_CORENET_CPUFREQ) += ppc-corenet-cpufreq.o
+obj-$(CONFIG_MPC85xx_CPUFREQ) += mpc85xx-cpufreq.o
obj-$(CONFIG_CPU_FREQ_PMAC) += pmac32-cpufreq.o
obj-$(CONFIG_CPU_FREQ_PMAC64) += pmac64-cpufreq.o
obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += pasemi-cpufreq.o
diff --git a/drivers/cpufreq/mpc85xx-cpufreq.c b/drivers/cpufreq/mpc85xx-cpufreq.c
new file mode 100644
index 0000000..9b3f7fa
--- /dev/null
+++ b/drivers/cpufreq/mpc85xx-cpufreq.c
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2008-2012 Freescale Semiconductor, Inc.
+ * Author: Dave Liu <daveliu@freescale.com>
+ * Modifier: Chenhui Zhao <chenhui.zhao@freescale.com>
+ *
+ * The cpufreq driver is for Freescale 85xx processor,
+ * based on arch/powerpc/platforms/cell/cbe_cpufreq.c
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007
+ * Christian Krafft <krafft@de.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/cpufreq.h>
+#include <linux/of_platform.h>
+#include <linux/suspend.h>
+#include <linux/cpu.h>
+#include <linux/time.h>
+#include <linux/io.h>
+#include <linux/smp.h>
+
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/reg.h>
+#include <asm/machdep.h>
+
+#include <sysdev/fsl_soc.h>
+
+static DEFINE_MUTEX(mpc85xx_switch_mutex);
+static void __iomem *guts;
+
+static u32 sysfreq;
+static unsigned int max_pll[2];
+static atomic_t in_jog_process;
+static struct cpufreq_frequency_table *mpc85xx_freqs;
+static int (*set_pll)(unsigned int cpu, unsigned int pll);
+
+static struct cpufreq_frequency_table mpc8536_freqs_table[] = {
+ {3, 0},
+ {4, 0},
+ {5, 0},
+ {6, 0},
+ {7, 0},
+ {8, 0},
+ {0, CPUFREQ_TABLE_END},
+};
+
+static struct cpufreq_frequency_table p1022_freqs_table[] = {
+ {2, 0},
+ {3, 0},
+ {4, 0},
+ {5, 0},
+ {6, 0},
+ {7, 0},
+ {8, 0},
+ {0, CPUFREQ_TABLE_END},
+};
+
+#define FREQ_500MHz 500000000
+#define FREQ_800MHz 800000000
+
+#define CORE_RATIO_STRIDE 8
+#define CORE_RATIO_MASK 0x3f
+#define CORE_RATIO_SHIFT 16
+
+#define PORPLLSR 0x0 /* Power-On Reset PLL ratio status register */
+
+#define PMJCR 0x7c /* Power Management Jog Control Register */
+#define PMJCR_CORE0_SPD 0x00001000
+#define PMJCR_CORE_SPD 0x00002000
+
+#define POWMGTCSR 0x80 /* Power management control and status register */
+#define POWMGTCSR_JOG 0x00200000
+#define POWMGTCSR_INT_MASK 0x00000f00
+
+static void spin_while_jogging(void *dummy)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ atomic_inc(&in_jog_process);
+
+ while (atomic_read(&in_jog_process) != 0)
+ barrier();
+
+ local_irq_restore(flags);
+}
+
+static int get_pll(int hw_cpu)
+{
+ int shift;
+ u32 val = in_be32(guts + PORPLLSR);
+
+ shift = hw_cpu * CORE_RATIO_STRIDE + CORE_RATIO_SHIFT;
+
+ return (val >> shift) & CORE_RATIO_MASK;
+}
+
+static int mpc8536_set_pll(unsigned int cpu, unsigned int pll)
+{
+ u32 corefreq, val, mask;
+ unsigned int cur_pll = get_pll(0);
+ unsigned long flags;
+
+ if (pll == cur_pll)
+ return 0;
+
+ val = (pll & CORE_RATIO_MASK) << CORE_RATIO_SHIFT;
+
+ corefreq = sysfreq * pll / 2;
+ /*
+ * Set the COREx_SPD bit if the requested core frequency
+ * is larger than the threshold frequency.
+ */
+ if (corefreq > FREQ_800MHz)
+ val |= PMJCR_CORE_SPD;
+
+ mask = (CORE_RATIO_MASK << CORE_RATIO_SHIFT) | PMJCR_CORE_SPD;
+ clrsetbits_be32(guts + PMJCR, mask, val);
+
+ /* readback to sync write */
+ in_be32(guts + PMJCR);
+
+ local_irq_save(flags);
+ mpc85xx_enter_jog(get_immrbase(), POWMGTCSR_JOG);
+ local_irq_restore(flags);
+
+ /* verify */
+ cur_pll = get_pll(0);
+ if (cur_pll != pll) {
+ pr_err("%s: error. The current PLL of core 0 is %d instead of %d.\n",
+ __func__, cur_pll, pll);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int p1022_set_pll(unsigned int cpu, unsigned int pll)
+{
+ int index, hw_cpu = get_hard_smp_processor_id(cpu);
+ int shift;
+ u32 corefreq, val, mask = 0;
+ unsigned int cur_pll = get_pll(hw_cpu);
+ unsigned long flags;
+ int ret = 0;
+
+ if (pll == cur_pll)
+ return 0;
+
+ shift = hw_cpu * CORE_RATIO_STRIDE + CORE_RATIO_SHIFT;
+ val = (pll & CORE_RATIO_MASK) << shift;
+
+ corefreq = sysfreq * pll / 2;
+ /*
+ * Set the COREx_SPD bit if the requested core frequency
+ * is larger than the threshold frequency.
+ */
+ if (corefreq > FREQ_500MHz)
+ val |= PMJCR_CORE0_SPD << hw_cpu;
+
+ mask = (CORE_RATIO_MASK << shift) | (PMJCR_CORE0_SPD << hw_cpu);
+ clrsetbits_be32(guts + PMJCR, mask, val);
+
+ /* readback to sync write */
+ in_be32(guts + PMJCR);
+
+ cpu_hotplug_disable();
+ /*
+ * A Jog request can not be asserted when any core is in a low
+ * power state on P1022. Before executing a jog request, any
+ * core which is in a low power state must be waked by a
+ * interrupt, and keep waking up until the sequence is
+ * finished.
+ */
+ for_each_present_cpu(index) {
+ if (!cpu_online(index)) {
+ cpu_hotplug_enable();
+ pr_err("%s: error, core%d is down.\n", __func__, index);
+ return -1;
+ }
+ }
+
+ atomic_set(&in_jog_process, 0);
+ smp_call_function(spin_while_jogging, NULL, 0);
+
+ local_irq_save(flags);
+
+ /* Wait for the other core to wake. */
+ if (!spin_event_timeout(atomic_read(&in_jog_process) == 1, 1000, 100)) {
+ pr_err("%s: timeout, the other core is not at running state.\n",
+ __func__);
+ ret = -1;
+ goto err;
+ }
+
+ out_be32(guts + POWMGTCSR, POWMGTCSR_JOG | POWMGTCSR_INT_MASK);
+
+ if (!spin_event_timeout(
+ (in_be32(guts + POWMGTCSR) & POWMGTCSR_JOG) == 0, 1000, 100)) {
+ pr_err("%s: timeout, fail to switch the core frequency.\n",
+ __func__);
+ ret = -1;
+ goto err;
+ }
+
+ clrbits32(guts + POWMGTCSR, POWMGTCSR_INT_MASK);
+ in_be32(guts + POWMGTCSR);
+
+ atomic_set(&in_jog_process, 0);
+err:
+ local_irq_restore(flags);
+ cpu_hotplug_enable();
+
+ /* verify */
+ cur_pll = get_pll(hw_cpu);
+ if (cur_pll != pll) {
+ pr_err("%s: error, the current PLL of core %d is %d instead of %d.\n",
+ __func__, hw_cpu, cur_pll, pll);
+ return -1;
+ }
+
+ return ret;
+}
+
+/*
+ * cpufreq functions
+ */
+static int mpc85xx_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+ unsigned int i, cur_pll;
+ int hw_cpu = get_hard_smp_processor_id(policy->cpu);
+
+ if (!cpu_present(policy->cpu))
+ return -ENODEV;
+
+ /* the latency of a transition, the unit is ns */
+ policy->cpuinfo.transition_latency = 2000;
+
+ cur_pll = get_pll(hw_cpu);
+
+ /* initialize frequency table */
+ pr_debug("core%d frequency table:\n", hw_cpu);
+ for (i = 0; mpc85xx_freqs[i].frequency != CPUFREQ_TABLE_END; i++) {
+ if (mpc85xx_freqs[i].driver_data <= max_pll[hw_cpu]) {
+ /* The frequency unit is kHz. */
+ mpc85xx_freqs[i].frequency =
+ (sysfreq * mpc85xx_freqs[i].driver_data / 2) / 1000;
+ } else {
+ mpc85xx_freqs[i].frequency = CPUFREQ_ENTRY_INVALID;
+ }
+
+ pr_debug("%d: %dkHz\n", i, mpc85xx_freqs[i].frequency);
+
+ if (mpc85xx_freqs[i].driver_data == cur_pll)
+ policy->cur = mpc85xx_freqs[i].frequency;
+ }
+ pr_debug("current pll is at %d, and core freq is%d\n",
+ cur_pll, policy->cur);
+
+ cpufreq_frequency_table_get_attr(mpc85xx_freqs, policy->cpu);
+
+ /*
+ * This ensures that policy->cpuinfo_min
+ * and policy->cpuinfo_max are set correctly.
+ */
+ return cpufreq_frequency_table_cpuinfo(policy, mpc85xx_freqs);
+}
+
+static int mpc85xx_cpufreq_cpu_exit(struct cpufreq_policy *policy)
+{
+ cpufreq_frequency_table_put_attr(policy->cpu);
+
+ return 0;
+}
+
+static int mpc85xx_cpufreq_verify(struct cpufreq_policy *policy)
+{
+ return cpufreq_frequency_table_verify(policy, mpc85xx_freqs);
+}
+
+static int mpc85xx_cpufreq_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ struct cpufreq_freqs freqs;
+ unsigned int new;
+ int ret = 0;
+
+ if (!set_pll)
+ return -ENODEV;
+
+ cpufreq_frequency_table_target(policy,
+ mpc85xx_freqs,
+ target_freq,
+ relation,
+ &new);
+
+ freqs.old = policy->cur;
+ freqs.new = mpc85xx_freqs[new].frequency;
+ freqs.cpu = policy->cpu;
+
+ mutex_lock(&mpc85xx_switch_mutex);
+ cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
+
+ ret = set_pll(policy->cpu, mpc85xx_freqs[new].driver_data);
+ if (!ret) {
+ pr_info("cpufreq: Setting core%d frequency to %d kHz and PLL ratio to %d:2\n",
+ policy->cpu, mpc85xx_freqs[new].frequency,
+ mpc85xx_freqs[new].driver_data);
+
+ ppc_proc_freq = freqs.new * 1000ul;
+ }
+ cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
+ mutex_unlock(&mpc85xx_switch_mutex);
+
+ return ret;
+}
+
+static struct cpufreq_driver mpc85xx_cpufreq_driver = {
+ .verify = mpc85xx_cpufreq_verify,
+ .target = mpc85xx_cpufreq_target,
+ .init = mpc85xx_cpufreq_cpu_init,
+ .exit = mpc85xx_cpufreq_cpu_exit,
+ .name = "mpc85xx-JOG",
+ .flags = CPUFREQ_CONST_LOOPS,
+};
+
+static int mpc85xx_job_probe(struct platform_device *ofdev)
+{
+ struct device_node *np = ofdev->dev.of_node;
+ unsigned int svr;
+
+ if (of_device_is_compatible(np, "fsl,mpc8536-guts")) {
+ svr = mfspr(SPRN_SVR);
+ if ((svr & 0x7fff) == 0x10) {
+ pr_err("MPC8536 Rev 1.0 do not support JOG.\n");
+ return -ENODEV;
+ }
+ mpc85xx_freqs = mpc8536_freqs_table;
+ set_pll = mpc8536_set_pll;
+ } else if (of_device_is_compatible(np, "fsl,p1022-guts")) {
+ mpc85xx_freqs = p1022_freqs_table;
+ set_pll = p1022_set_pll;
+ } else {
+ return -ENODEV;
+ }
+
+ sysfreq = fsl_get_sys_freq();
+
+ guts = of_iomap(np, 0);
+ if (!guts)
+ return -ENODEV;
+
+ max_pll[0] = get_pll(0);
+ if (mpc85xx_freqs == p1022_freqs_table)
+ max_pll[1] = get_pll(1);
+
+ pr_info("Freescale MPC85xx CPU frequency switching(JOG) driver\n");
+
+ return cpufreq_register_driver(&mpc85xx_cpufreq_driver);
+}
+
+static int mpc85xx_jog_remove(struct platform_device *ofdev)
+{
+ iounmap(guts);
+ cpufreq_unregister_driver(&mpc85xx_cpufreq_driver);
+
+ return 0;
+}
+
+static struct of_device_id mpc85xx_jog_ids[] = {
+ { .compatible = "fsl,mpc8536-guts", },
+ { .compatible = "fsl,p1022-guts", },
+ {}
+};
+
+static struct platform_driver mpc85xx_jog_driver = {
+ .driver = {
+ .name = "mpc85xx_cpufreq_jog",
+ .of_match_table = mpc85xx_jog_ids,
+ },
+ .probe = mpc85xx_job_probe,
+ .remove = mpc85xx_jog_remove,
+};
+
+static int __init mpc85xx_jog_init(void)
+{
+ return platform_driver_register(&mpc85xx_jog_driver);
+}
+
+static void __exit mpc85xx_jog_exit(void)
+{
+ platform_driver_unregister(&mpc85xx_jog_driver);
+}
+
+module_init(mpc85xx_jog_init);
+module_exit(mpc85xx_jog_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Dave Liu <daveliu@freescale.com>");
diff --git a/drivers/cpufreq/ppc-corenet-cpufreq.c b/drivers/cpufreq/ppc-corenet-cpufreq.c
index 60e81d5..79173af 100644
--- a/drivers/cpufreq/ppc-corenet-cpufreq.c
+++ b/drivers/cpufreq/ppc-corenet-cpufreq.c
@@ -216,7 +216,8 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy)
for_each_cpu(i, per_cpu(cpu_mask, cpu))
per_cpu(cpu_data, i) = data;
- policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+ policy->cpuinfo.transition_latency =
+ (12 * NSEC_PER_SEC) / fsl_get_sys_freq();
policy->cur = corenet_cpufreq_get_speed(policy->cpu);
cpufreq_frequency_table_get_attr(table, cpu);
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index f4fd837..c73ae6c 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -211,7 +211,7 @@ config CRYPTO_DEV_TALITOS
select CRYPTO_ALGAPI
select CRYPTO_AUTHENC
select HW_RANDOM
- depends on FSL_SOC
+ depends on FSL_SOC && NET
help
Say 'Y' here to use the Freescale Security Engine (SEC)
to offload cryptographic algorithm computation.
@@ -222,6 +222,16 @@ config CRYPTO_DEV_TALITOS
To compile this driver as a module, choose M here: the module
will be called talitos.
+config CRYPTO_DEV_TALITOS_RAIDXOR
+ bool "Talitos RAID5 XOR Calculation Offload"
+ default y
+ select DMA_ENGINE
+ select ASYNC_TX_ENABLE_CHANNEL_SWITCH
+ depends on CRYPTO_DEV_TALITOS
+ help
+ Say 'Y' here to use the Freescale Security Engine (SEC) to
+ offload RAID XOR parity Calculation
+
config CRYPTO_DEV_IXP4XX
tristate "Driver for IXP4xx crypto hardware acceleration"
depends on ARCH_IXP4XX && IXP4XX_QMGR && IXP4XX_NPE
diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
index ca89f6b..d7863d9 100644
--- a/drivers/crypto/caam/Kconfig
+++ b/drivers/crypto/caam/Kconfig
@@ -4,16 +4,29 @@ config CRYPTO_DEV_FSL_CAAM
help
Enables the driver module for Freescale's Cryptographic Accelerator
and Assurance Module (CAAM), also known as the SEC version 4 (SEC4).
- This module adds a job ring operation interface, and configures h/w
+ This module creates job ring devices, and configures h/w
to operate as a DPAA component automatically, depending
on h/w feature availability.
To compile this driver as a module, choose M here: the module
will be called caam.
+config CRYPTO_DEV_FSL_CAAM_JR
+ tristate "Freescale CAAM Job Ring driver backend"
+ depends on CRYPTO_DEV_FSL_CAAM
+ default y
+ help
+ Enables the driver module for Job Rings which are part of
+ Freescale's Cryptographic Accelerator
+ and Assurance Module (CAAM). This module adds a job ring operation
+ interface.
+
+ To compile this driver as a module, choose M here: the module
+ will be called caam_jr.
+
config CRYPTO_DEV_FSL_CAAM_RINGSIZE
int "Job Ring size"
- depends on CRYPTO_DEV_FSL_CAAM
+ depends on CRYPTO_DEV_FSL_CAAM_JR
range 2 9
default "9"
help
@@ -31,7 +44,7 @@ config CRYPTO_DEV_FSL_CAAM_RINGSIZE
config CRYPTO_DEV_FSL_CAAM_INTC
bool "Job Ring interrupt coalescing"
- depends on CRYPTO_DEV_FSL_CAAM
+ depends on CRYPTO_DEV_FSL_CAAM_JR
default n
help
Enable the Job Ring's interrupt coalescing feature.
@@ -62,7 +75,7 @@ config CRYPTO_DEV_FSL_CAAM_INTC_TIME_THLD
config CRYPTO_DEV_FSL_CAAM_CRYPTO_API
tristate "Register algorithm implementations with the Crypto API"
- depends on CRYPTO_DEV_FSL_CAAM
+ depends on CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR && NET
default y
select CRYPTO_ALGAPI
select CRYPTO_AUTHENC
@@ -74,9 +87,40 @@ config CRYPTO_DEV_FSL_CAAM_CRYPTO_API
To compile this as a module, choose M here: the module
will be called caamalg.
+config CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI
+ tristate "Queue Interface as Crypto API backend"
+ depends on CRYPTO_DEV_FSL_CAAM_CRYPTO_API && FSL_QMAN
+ default y
+ help
+ Selecting this will use SEC Queue Interface for sending
+ & receiving crypto jobs to/from SEC. This gives better
+ performance than job ring interface when the number of
+ cores are more than the number of job rings assigned to
+ the kernel. The number of portals assigned to the kernel
+ should also be more than the number of job rings.
+
+ Currently, only AEAD algorithms have been implemented on
+ top of SEC-QI backend interface. The rest of the algorithms
+ use job ring interface.
+
+ To compile this as a module, choose M here: the module
+ will be called caamalg_qi.
+
+config FSL_CAAM_PKC_SUPPORT
+ tristate "Public Key Cryptography Support in CAAM driver"
+ depends on CRYPTO_DEV_FSL_CAAM_CRYPTO_API
+ default y
+ help
+ Selecting this will allow SEC Public key support for
+ RSA, DSA, DH, ECDH, ECDSA. Supported operations includes
+ Keygen, Sign and Verify.
+
+ To compile this as a module, choose M here: the module
+ will be called caam_pkc.
+
config CRYPTO_DEV_FSL_CAAM_AHASH_API
tristate "Register hash algorithm implementations with Crypto API"
- depends on CRYPTO_DEV_FSL_CAAM
+ depends on CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
default y
select CRYPTO_HASH
help
@@ -88,7 +132,7 @@ config CRYPTO_DEV_FSL_CAAM_AHASH_API
config CRYPTO_DEV_FSL_CAAM_RNG_API
tristate "Register caam device for hwrng API"
- depends on CRYPTO_DEV_FSL_CAAM
+ depends on CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
default y
select CRYPTO_RNG
select HW_RANDOM
@@ -106,3 +150,9 @@ config CRYPTO_DEV_FSL_CAAM_DEBUG
help
Selecting this will enable printing of various debug
information in the CAAM driver.
+
+config CRYPTO_DEV_FSL_CAAM_JR_UIO
+ tristate "Freescale Job Ring UIO support"
+ depends on CRYPTO_DEV_FSL_CAAM
+ depends on UIO
+ default y
diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile
index d56bd0e..378798d 100644
--- a/drivers/crypto/caam/Makefile
+++ b/drivers/crypto/caam/Makefile
@@ -6,8 +6,19 @@ ifeq ($(CONFIG_CRYPTO_DEV_FSL_CAAM_DEBUG), y)
endif
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam.o
+obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_JR) += caam_jr.o
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o
+obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_JR_UIO) += fsl_jr_uio.o
-caam-objs := ctrl.o jr.o error.o key_gen.o
+caam-objs := ctrl.o
+caam_jr-objs := jr.o key_gen.o error.o
+ifeq ($(CONFIG_FSL_QMAN), y)
+ caam-objs += qi.o
+endif
+
+obj-$(CONFIG_FSL_CAAM_PKC_SUPPORT) += caam_pkc.o
+caam_pkc-objs := caampkc.o pkc_desc.o
+
+obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += caamalg_qi.o
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index 7c63b72..17ea75f 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -66,10 +66,21 @@
/* length of descriptors text */
#define DESC_AEAD_BASE (4 * CAAM_CMD_SZ)
-#define DESC_AEAD_ENC_LEN (DESC_AEAD_BASE + 16 * CAAM_CMD_SZ)
-#define DESC_AEAD_DEC_LEN (DESC_AEAD_BASE + 21 * CAAM_CMD_SZ)
+#define DESC_AEAD_ENC_LEN (DESC_AEAD_BASE + 15 * CAAM_CMD_SZ)
+#define DESC_AEAD_DEC_LEN (DESC_AEAD_BASE + 18 * CAAM_CMD_SZ)
#define DESC_AEAD_GIVENC_LEN (DESC_AEAD_ENC_LEN + 7 * CAAM_CMD_SZ)
+#define DESC_AEAD_NULL_BASE (3 * CAAM_CMD_SZ)
+#define DESC_AEAD_NULL_ENC_LEN (DESC_AEAD_NULL_BASE + 14 * CAAM_CMD_SZ)
+#define DESC_AEAD_NULL_DEC_LEN (DESC_AEAD_NULL_BASE + 17 * CAAM_CMD_SZ)
+
+#define DESC_TLS_BASE (4 * CAAM_CMD_SZ)
+#define DESC_TLS10_ENC_LEN (DESC_TLS_BASE + 23 * CAAM_CMD_SZ)
+
+#define DESC_GCM_BASE (3 * CAAM_CMD_SZ)
+#define DESC_GCM_ENC_LEN (DESC_GCM_BASE + 23 * CAAM_CMD_SZ)
+#define DESC_GCM_DEC_LEN (DESC_GCM_BASE + 19 * CAAM_CMD_SZ)
+
#define DESC_ABLKCIPHER_BASE (3 * CAAM_CMD_SZ)
#define DESC_ABLKCIPHER_ENC_LEN (DESC_ABLKCIPHER_BASE + \
20 * CAAM_CMD_SZ)
@@ -86,6 +97,7 @@
#else
#define debug(format, arg...)
#endif
+static struct list_head alg_list;
/* Set DK bit in class 1 operation if shared */
static inline void append_dec_op1(u32 *desc, u32 type)
@@ -103,27 +115,14 @@ static inline void append_dec_op1(u32 *desc, u32 type)
}
/*
- * Wait for completion of class 1 key loading before allowing
- * error propagation
- */
-static inline void append_dec_shr_done(u32 *desc)
-{
- u32 *jump_cmd;
-
- jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TEST_ALL);
- set_jump_tgt_here(desc, jump_cmd);
- append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
-}
-
-/*
* For aead functions, read payload and write payload,
* both of which are specified in req->src and req->dst
*/
static inline void aead_append_src_dst(u32 *desc, u32 msg_type)
{
+ append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF);
append_seq_fifo_load(desc, 0, FIFOLD_CLASS_BOTH |
KEY_VLF | msg_type | FIFOLD_TYPE_LASTBOTH);
- append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF);
}
/*
@@ -210,9 +209,196 @@ static void init_sh_desc_key_aead(u32 *desc, struct caam_ctx *ctx,
append_key_aead(desc, ctx, keys_fit_inline);
set_jump_tgt_here(desc, key_jump_cmd);
+}
+
+static int aead_null_set_sh_desc(struct crypto_aead *aead)
+{
+ struct aead_tfm *tfm = &aead->base.crt_aead;
+ struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ struct device *jrdev = ctx->jrdev;
+ bool keys_fit_inline = false;
+ u32 *key_jump_cmd, *jump_cmd, *read_move_cmd, *write_move_cmd;
+ u32 *desc;
+
+ /*
+ * Job Descriptor and Shared Descriptors
+ * must all fit into the 64-word Descriptor h/w Buffer
+ */
+ if (DESC_AEAD_NULL_ENC_LEN + DESC_JOB_IO_LEN +
+ ctx->split_key_pad_len <= CAAM_DESC_BYTES_MAX)
+ keys_fit_inline = true;
+
+ /* aead_encrypt shared descriptor */
+ desc = ctx->sh_desc_enc;
+
+ init_sh_desc(desc, HDR_SHARE_SERIAL);
+
+ /* Skip if already shared */
+ key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+ JUMP_COND_SHRD);
+ if (keys_fit_inline)
+ append_key_as_imm(desc, ctx->key, ctx->split_key_pad_len,
+ ctx->split_key_len, CLASS_2 |
+ KEY_DEST_MDHA_SPLIT | KEY_ENC);
+ else
+ append_key(desc, ctx->key_dma, ctx->split_key_len, CLASS_2 |
+ KEY_DEST_MDHA_SPLIT | KEY_ENC);
+ set_jump_tgt_here(desc, key_jump_cmd);
+
+ /* cryptlen = seqoutlen - authsize */
+ append_math_sub_imm_u32(desc, REG3, SEQOUTLEN, IMM, ctx->authsize);
+
+ /*
+ * NULL encryption; IV is zero
+ * assoclen = (assoclen + cryptlen) - cryptlen
+ */
+ append_math_sub(desc, VARSEQINLEN, SEQINLEN, REG3, CAAM_CMD_SZ);
+
+ /* read assoc before reading payload */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
+ KEY_VLF);
+
+ /* Prepare to read and write cryptlen bytes */
+ append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
+ append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
+
+ /*
+ * MOVE_LEN opcode is not available in all SEC HW revisions,
+ * thus need to do some magic, i.e. self-patch the descriptor
+ * buffer.
+ */
+ read_move_cmd = append_move(desc, MOVE_SRC_DESCBUF |
+ MOVE_DEST_MATH3 |
+ (0x6 << MOVE_LEN_SHIFT));
+ write_move_cmd = append_move(desc, MOVE_SRC_MATH3 |
+ MOVE_DEST_DESCBUF |
+ MOVE_WAITCOMP |
+ (0x8 << MOVE_LEN_SHIFT));
+
+ /* Class 2 operation */
+ append_operation(desc, ctx->class2_alg_type |
+ OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
+
+ /* Read and write cryptlen bytes */
+ aead_append_src_dst(desc, FIFOLD_TYPE_MSG | FIFOLD_TYPE_FLUSH1);
+
+ set_move_tgt_here(desc, read_move_cmd);
+ set_move_tgt_here(desc, write_move_cmd);
+ append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
+ append_move(desc, MOVE_SRC_INFIFO_CL | MOVE_DEST_OUTFIFO |
+ MOVE_AUX_LS);
+
+ /* Write ICV */
+ append_seq_store(desc, ctx->authsize, LDST_CLASS_2_CCB |
+ LDST_SRCDST_BYTE_CONTEXT);
+
+ ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc,
+ desc_bytes(desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_enc_dma)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR,
+ "aead null enc shdesc@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+
+ /*
+ * Job Descriptor and Shared Descriptors
+ * must all fit into the 64-word Descriptor h/w Buffer
+ */
+ if (DESC_AEAD_NULL_DEC_LEN + DESC_JOB_IO_LEN +
+ ctx->split_key_pad_len <= CAAM_DESC_BYTES_MAX)
+ keys_fit_inline = true;
+
+ desc = ctx->sh_desc_dec;
+
+ /* aead_decrypt shared descriptor */
+ init_sh_desc(desc, HDR_SHARE_SERIAL);
+
+ /* Skip if already shared */
+ key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+ JUMP_COND_SHRD);
+ if (keys_fit_inline)
+ append_key_as_imm(desc, ctx->key, ctx->split_key_pad_len,
+ ctx->split_key_len, CLASS_2 |
+ KEY_DEST_MDHA_SPLIT | KEY_ENC);
+ else
+ append_key(desc, ctx->key_dma, ctx->split_key_len, CLASS_2 |
+ KEY_DEST_MDHA_SPLIT | KEY_ENC);
+ set_jump_tgt_here(desc, key_jump_cmd);
- /* Propagate errors from shared to job descriptor */
- append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
+ /* Class 2 operation */
+ append_operation(desc, ctx->class2_alg_type |
+ OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT | OP_ALG_ICV_ON);
+
+ /* assoclen + cryptlen = seqinlen - ivsize - authsize */
+ append_math_sub_imm_u32(desc, REG3, SEQINLEN, IMM,
+ ctx->authsize + tfm->ivsize);
+ /* assoclen = (assoclen + cryptlen) - cryptlen */
+ append_math_sub(desc, REG2, SEQOUTLEN, REG0, CAAM_CMD_SZ);
+ append_math_sub(desc, VARSEQINLEN, REG3, REG2, CAAM_CMD_SZ);
+
+ /* read assoc before reading payload */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
+ KEY_VLF);
+
+ /* Prepare to read and write cryptlen bytes */
+ append_math_add(desc, VARSEQINLEN, ZERO, REG2, CAAM_CMD_SZ);
+ append_math_add(desc, VARSEQOUTLEN, ZERO, REG2, CAAM_CMD_SZ);
+
+ /*
+ * MOVE_LEN opcode is not available in all SEC HW revisions,
+ * thus need to do some magic, i.e. self-patch the descriptor
+ * buffer.
+ */
+ read_move_cmd = append_move(desc, MOVE_SRC_DESCBUF |
+ MOVE_DEST_MATH2 |
+ (0x6 << MOVE_LEN_SHIFT));
+ write_move_cmd = append_move(desc, MOVE_SRC_MATH2 |
+ MOVE_DEST_DESCBUF |
+ MOVE_WAITCOMP |
+ (0x8 << MOVE_LEN_SHIFT));
+
+ /* Read and write cryptlen bytes */
+ aead_append_src_dst(desc, FIFOLD_TYPE_MSG | FIFOLD_TYPE_FLUSH1);
+
+ /*
+ * Insert a NOP here, since we need at least 4 instructions between
+ * code patching the descriptor buffer and the location being patched.
+ */
+ jump_cmd = append_jump(desc, JUMP_TEST_ALL);
+ set_jump_tgt_here(desc, jump_cmd);
+
+ set_move_tgt_here(desc, read_move_cmd);
+ set_move_tgt_here(desc, write_move_cmd);
+ append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
+ append_move(desc, MOVE_SRC_INFIFO_CL | MOVE_DEST_OUTFIFO |
+ MOVE_AUX_LS);
+ append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
+
+ /* Load ICV */
+ append_seq_fifo_load(desc, ctx->authsize, FIFOLD_CLASS_CLASS2 |
+ FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_ICV);
+
+ ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc,
+ desc_bytes(desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_dec_dma)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR,
+ "aead null dec shdesc@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+
+ return 0;
}
static int aead_set_sh_desc(struct crypto_aead *aead)
@@ -221,13 +407,16 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
struct caam_ctx *ctx = crypto_aead_ctx(aead);
struct device *jrdev = ctx->jrdev;
bool keys_fit_inline = false;
- u32 *key_jump_cmd, *jump_cmd;
u32 geniv, moveiv;
u32 *desc;
- if (!ctx->enckeylen || !ctx->authsize)
+ if (!ctx->authsize)
return 0;
+ /* NULL encryption / decryption */
+ if (!ctx->enckeylen)
+ return aead_null_set_sh_desc(aead);
+
/*
* Job Descriptor and Shared Descriptors
* must all fit into the 64-word Descriptor h/w Buffer
@@ -252,7 +441,7 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
/* assoclen + cryptlen = seqinlen - ivsize */
append_math_sub_imm_u32(desc, REG2, SEQINLEN, IMM, tfm->ivsize);
- /* assoclen + cryptlen = (assoclen + cryptlen) - cryptlen */
+ /* assoclen = (assoclen + cryptlen) - cryptlen */
append_math_sub(desc, VARSEQINLEN, REG2, REG3, CAAM_CMD_SZ);
/* read assoc before reading payload */
@@ -295,30 +484,18 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
CAAM_DESC_BYTES_MAX)
keys_fit_inline = true;
- desc = ctx->sh_desc_dec;
-
/* aead_decrypt shared descriptor */
- init_sh_desc(desc, HDR_SHARE_SERIAL);
-
- /* Skip if already shared */
- key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
- JUMP_COND_SHRD);
-
- append_key_aead(desc, ctx, keys_fit_inline);
+ desc = ctx->sh_desc_dec;
- /* Only propagate error immediately if shared */
- jump_cmd = append_jump(desc, JUMP_TEST_ALL);
- set_jump_tgt_here(desc, key_jump_cmd);
- append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
- set_jump_tgt_here(desc, jump_cmd);
+ init_sh_desc_key_aead(desc, ctx, keys_fit_inline);
/* Class 2 operation */
append_operation(desc, ctx->class2_alg_type |
OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT | OP_ALG_ICV_ON);
- /* assoclen + cryptlen = seqinlen - ivsize */
+ /* assoclen + cryptlen = seqinlen - ivsize - authsize */
append_math_sub_imm_u32(desc, REG3, SEQINLEN, IMM,
- ctx->authsize + tfm->ivsize)
+ ctx->authsize + tfm->ivsize);
/* assoclen = (assoclen + cryptlen) - cryptlen */
append_math_sub(desc, REG2, SEQOUTLEN, REG0, CAAM_CMD_SZ);
append_math_sub(desc, VARSEQINLEN, REG3, REG2, CAAM_CMD_SZ);
@@ -339,7 +516,6 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
/* Load ICV */
append_seq_fifo_load(desc, ctx->authsize, FIFOLD_CLASS_CLASS2 |
FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_ICV);
- append_dec_shr_done(desc);
ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc,
desc_bytes(desc),
@@ -451,6 +627,534 @@ static int aead_setauthsize(struct crypto_aead *authenc,
return 0;
}
+static int tls_set_sh_desc(struct crypto_aead *aead)
+{
+ struct aead_tfm *tfm = &aead->base.crt_aead;
+ struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ struct device *jrdev = ctx->jrdev;
+ bool keys_fit_inline = false;
+ u32 *key_jump_cmd, *zero_payload_jump_cmd, *skip_zero_jump_cmd;
+ u32 genpad, clrw, jumpback, stidx;
+ u32 *desc;
+ unsigned int blocksize = crypto_aead_blocksize(aead);
+ /* Associated data length is always = 13 for TLS */
+ unsigned int assoclen = 13;
+
+ if (!ctx->enckeylen || !ctx->authsize)
+ return 0;
+
+ /*
+ * TLS 1.0 encrypt shared descriptor
+ * Job Descriptor and Shared Descriptor
+ * must fit into the 64-word Descriptor h/w Buffer
+ */
+ if (DESC_TLS10_ENC_LEN + DESC_JOB_IO_LEN +
+ ctx->split_key_pad_len + ctx->enckeylen <=
+ CAAM_DESC_BYTES_MAX)
+ keys_fit_inline = true;
+
+ desc = ctx->sh_desc_enc;
+
+ stidx = 1 << HDR_START_IDX_SHIFT;
+ init_sh_desc(desc, HDR_SHARE_SERIAL | stidx);
+
+ /* skip key loading if they are loaded due to sharing */
+ key_jump_cmd = append_jump(desc, JUMP_CLASS_BOTH | JUMP_JSL |
+ JUMP_TEST_ALL | JUMP_COND_SHRD |
+ JUMP_COND_SELF);
+ if (keys_fit_inline) {
+ append_key_as_imm(desc, ctx->key, ctx->split_key_pad_len,
+ ctx->split_key_len, CLASS_2 |
+ KEY_DEST_MDHA_SPLIT | KEY_ENC);
+ append_key_as_imm(desc, (void *)ctx->key +
+ ctx->split_key_pad_len, ctx->enckeylen,
+ ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
+ } else {
+ append_key(desc, ctx->key_dma, ctx->split_key_len, CLASS_2 |
+ KEY_DEST_MDHA_SPLIT | KEY_ENC);
+ append_key(desc, ctx->key_dma + ctx->split_key_pad_len,
+ ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
+ }
+ set_jump_tgt_here(desc, key_jump_cmd);
+
+ /* class 2 operation */
+ append_operation(desc, ctx->class2_alg_type |
+ OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
+ /* class 1 operation */
+ append_operation(desc, ctx->class1_alg_type |
+ OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
+
+ /* payloadlen = input data length - (assoclen + ivlen) */
+ append_math_sub_imm_u32(desc, VARSEQINLEN, SEQINLEN, IMM, assoclen +
+ tfm->ivsize);
+
+ /* math1 = payloadlen + icvlen */
+ append_math_add_imm_u32(desc, REG1, VARSEQINLEN, IMM, ctx->authsize);
+
+ /* padlen = block_size - math1 % block_size */
+ append_math_and_imm_u32(desc, REG3, REG1, IMM, blocksize - 1);
+ append_math_sub_imm_u32(desc, REG2, IMM, REG3, blocksize);
+
+ /* cryptlen = payloadlen + icvlen + padlen */
+ append_math_add(desc, VARSEQOUTLEN, REG1, REG2, 4);
+
+ /* store encrypted payload, icv and padding */
+ append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | LDST_VLF);
+
+ /* if payload length is zero, jump to zero-payload commands */
+ append_math_add(desc, NONE, ZERO, VARSEQINLEN, 4);
+ zero_payload_jump_cmd = append_jump(desc, JUMP_TEST_ALL |
+ JUMP_COND_MATH_Z);
+
+ /* read assoc for authentication */
+ append_seq_fifo_load(desc, assoclen, FIFOLD_CLASS_CLASS2 |
+ FIFOLD_TYPE_MSG);
+ /* load iv in context1 */
+ append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_WORD_CLASS_CTX |
+ LDST_CLASS_1_CCB | tfm->ivsize);
+ /* insnoop payload */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_BOTH | FIFOLD_TYPE_MSG |
+ FIFOLD_TYPE_LAST2 | FIFOLDST_VLF);
+ /* jump the zero-payload commands */
+ append_jump(desc, JUMP_TEST_ALL | 3);
+
+ /* zero-payload commands */
+ set_jump_tgt_here(desc, zero_payload_jump_cmd);
+ /* assoc data is the only data for authentication */
+ append_seq_fifo_load(desc, assoclen, FIFOLD_CLASS_CLASS2 |
+ FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST2);
+ /* load iv in context1 */
+ append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_WORD_CLASS_CTX |
+ LDST_CLASS_1_CCB | tfm->ivsize);
+
+ /* send icv to encryption */
+ append_move(desc, MOVE_SRC_CLASS2CTX | MOVE_DEST_CLASS1INFIFO |
+ ctx->authsize);
+
+ /* generate padding and send it to encryption */
+ genpad = NFIFOENTRY_DEST_CLASS1 | NFIFOENTRY_LC1 | NFIFOENTRY_FC1 |
+ NFIFOENTRY_STYPE_PAD | NFIFOENTRY_DTYPE_MSG | NFIFOENTRY_PTYPE_N;
+ append_load_imm_u32(desc, genpad, LDST_CLASS_IND_CCB |
+ LDST_SRCDST_WORD_INFO_FIFO_SZM | LDST_IMM |
+ (2 & LDST_LEN_MASK));
+
+ ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc,
+ desc_bytes(desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_enc_dma)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "tls enc shdesc@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+
+ /*
+ * TLS 1.0 decrypt shared descriptor
+ * Keys do not fit inline, regardless of algorithms used
+ */
+ desc = ctx->sh_desc_dec;
+
+ stidx = 1 << HDR_START_IDX_SHIFT;
+ init_sh_desc(desc, HDR_SHARE_SERIAL | stidx);
+
+ /* skip key loading if they are loaded due to sharing */
+ key_jump_cmd = append_jump(desc, JUMP_CLASS_BOTH | JUMP_JSL |
+ JUMP_TEST_ALL | JUMP_COND_SHRD |
+ JUMP_COND_SELF);
+ append_key(desc, ctx->key_dma, ctx->split_key_len, CLASS_2 |
+ KEY_DEST_MDHA_SPLIT | KEY_ENC);
+ append_key(desc, ctx->key_dma + ctx->split_key_pad_len,
+ ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
+ set_jump_tgt_here(desc, key_jump_cmd);
+
+ /* class 2 operation */
+ append_operation(desc, ctx->class2_alg_type |
+ OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT | OP_ALG_ICV_ON);
+ /* class 1 operation */
+ append_operation(desc, ctx->class1_alg_type |
+ OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT);
+
+ /* VSIL = input data length - 2 * block_size */
+ append_math_sub_imm_u32(desc, VARSEQINLEN, SEQINLEN, IMM, 2 *
+ blocksize);
+
+ /*
+ * payloadlen + icvlen + padlen = input data length - (assoclen +
+ * ivsize)
+ */
+ append_math_sub_imm_u32(desc, REG3, SEQINLEN, IMM, assoclen +
+ tfm->ivsize);
+
+ /* skip data to the last but one cipher block */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_SKIP | LDST_VLF);
+
+ /* load iv for the last cipher block */
+ append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_WORD_CLASS_CTX |
+ LDST_CLASS_1_CCB | tfm->ivsize);
+
+ /* read last cipher block */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_MSG |
+ FIFOLD_TYPE_LAST1 | blocksize);
+
+ /* move decrypted block into math0 and math1 */
+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_OUTFIFO | MOVE_DEST_MATH0 |
+ blocksize);
+
+ /* clear cha1 specific registers */
+ clrw = CLRW_CLR_C1MODE | CLRW_CLR_C1DATAS | CLRW_CLR_C1CTX |
+ CLRW_RESET_CLS1_CHA;
+ append_load_imm_u32(desc, clrw, LDST_CLASS_IND_CCB |
+ LDST_SRCDST_WORD_CLRW | LDST_IMM);
+
+ /* rewind input sequence */
+ append_seq_in_ptr_intlen(desc, 0, 65535, SQIN_RTO);
+
+ /* key1 is in decryption form */
+ append_operation(desc, ctx->class1_alg_type | OP_ALG_AAI_DK |
+ OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT);
+
+ /* read sequence number */
+ append_seq_fifo_load(desc, 8, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG);
+ /* load Type, Version and Len fields in math0 */
+ append_cmd(desc, CMD_SEQ_LOAD | LDST_CLASS_DECO |
+ LDST_SRCDST_WORD_DECO_MATH0 | 5);
+
+ /* load iv in context1 */
+ append_cmd(desc, CMD_SEQ_LOAD | LDST_CLASS_1_CCB |
+ LDST_SRCDST_WORD_CLASS_CTX | tfm->ivsize);
+
+ /* compute (padlen - 1) */
+ append_math_and_imm_u64(desc, REG1, REG1, IMM, 255);
+
+ /* math2 = icvlen + (padlen - 1) + 1 */
+ append_math_add_imm_u32(desc, REG2, REG1, IMM, ctx->authsize + 1);
+
+ append_jump(desc, JUMP_TEST_ALL | JUMP_COND_CALM | 1);
+
+ /* VSOL = payloadlen + icvlen + padlen */
+ append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, 4);
+
+ /* update Len field */
+ append_math_rshift_imm_u64(desc, REG0, REG0, IMM, 24);
+ append_math_sub(desc, REG0, REG0, REG2, 8);
+
+ /* store decrypted payload, icv and padding */
+ append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | LDST_VLF);
+
+ /* VSIL = (payloadlen + icvlen + padlen) - (icvlen + padlen)*/
+ append_math_sub(desc, VARSEQINLEN, REG3, REG2, 4);
+
+ zero_payload_jump_cmd = append_jump(desc, JUMP_TEST_ALL |
+ JUMP_COND_MATH_Z);
+
+ /* send Type, Version and Len(pre ICV) fields to authentication */
+ append_move(desc, MOVE_WAITCOMP |
+ MOVE_SRC_MATH0 | MOVE_DEST_CLASS2INFIFO |
+ (3 << MOVE_OFFSET_SHIFT) | 5);
+
+ /* outsnooping payload */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_BOTH |
+ FIFOLD_TYPE_MSG1OUT2 | FIFOLD_TYPE_LAST2 |
+ FIFOLDST_VLF);
+ skip_zero_jump_cmd = append_jump(desc, JUMP_TEST_ALL | 2);
+
+ set_jump_tgt_here(desc, zero_payload_jump_cmd);
+ /* send Type, Version and Len(pre ICV) fields to authentication */
+ append_move(desc, MOVE_WAITCOMP | MOVE_AUX_LS |
+ MOVE_SRC_MATH0 | MOVE_DEST_CLASS2INFIFO |
+ (3 << MOVE_OFFSET_SHIFT) | 5);
+
+ set_jump_tgt_here(desc, skip_zero_jump_cmd);
+ append_math_add(desc, VARSEQINLEN, ZERO, REG2, 4);
+
+ /* load icvlen and padlen */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_MSG |
+ FIFOLD_TYPE_LAST1 | FIFOLDST_VLF);
+
+ /* VSIL = (payloadlen + icvlen + padlen) - icvlen + padlen */
+ append_math_sub(desc, VARSEQINLEN, REG3, REG2, 4);
+
+ /* move seqoutptr fields into math registers */
+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_DESCBUF | MOVE_DEST_MATH0 |
+ (55 * 4 << MOVE_OFFSET_SHIFT) | 20);
+ /* seqinptr will point to seqoutptr */
+ append_math_and_imm_u32(desc, REG0, REG0, IMM,
+ ~(CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR));
+ /* Load jump command */
+ jumpback = CMD_JUMP | (char)-9;
+ append_load_imm_u32(desc, jumpback, LDST_CLASS_DECO | LDST_IMM |
+ LDST_SRCDST_WORD_DECO_MATH2 |
+ (4 << LDST_OFFSET_SHIFT));
+ /* move updated seqinptr fields to JD */
+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_MATH0 | MOVE_DEST_DESCBUF |
+ (55 * 4 << MOVE_OFFSET_SHIFT) | 24);
+ /* read updated seqinptr */
+ append_jump(desc, JUMP_TEST_ALL | JUMP_COND_CALM | 6);
+
+ /* skip payload */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_SKIP | FIFOLDST_VLF);
+ /* check icv */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_ICV |
+ FIFOLD_TYPE_LAST2 | ctx->authsize);
+
+ ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc,
+ desc_bytes(desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_dec_dma)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "tls dec shdesc@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+
+ return 0;
+}
+
+static int tls_setauthsize(struct crypto_aead *tls, unsigned int authsize)
+{
+ struct caam_ctx *ctx = crypto_aead_ctx(tls);
+
+ ctx->authsize = authsize;
+
+ return 0;
+}
+
+static int gcm_set_sh_desc(struct crypto_aead *aead)
+{
+ struct aead_tfm *tfm = &aead->base.crt_aead;
+ struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ struct device *jrdev = ctx->jrdev;
+ bool keys_fit_inline = false;
+ u32 *key_jump_cmd, *zero_payload_jump_cmd,
+ *zero_assoc_jump_cmd1, *zero_assoc_jump_cmd2;
+ u32 *desc;
+
+ if (!ctx->enckeylen || !ctx->authsize)
+ return 0;
+
+ /*
+ * AES GCM encrypt shared descriptor
+ * Job Descriptor and Shared Descriptor
+ * must fit into the 64-word Descriptor h/w Buffer
+ */
+ if (DESC_GCM_ENC_LEN + DESC_JOB_IO_LEN +
+ ctx->enckeylen <= CAAM_DESC_BYTES_MAX)
+ keys_fit_inline = true;
+
+ desc = ctx->sh_desc_enc;
+
+ init_sh_desc(desc, HDR_SHARE_SERIAL);
+
+ /* skip key loading if they are loaded due to sharing */
+ key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+ JUMP_COND_SHRD | JUMP_COND_SELF);
+ if (keys_fit_inline)
+ append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen,
+ ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
+ else
+ append_key(desc, ctx->key_dma, ctx->enckeylen,
+ CLASS_1 | KEY_DEST_CLASS_REG);
+ set_jump_tgt_here(desc, key_jump_cmd);
+
+ /* class 1 operation */
+ append_operation(desc, ctx->class1_alg_type |
+ OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
+
+ /* cryptlen = seqoutlen - authsize */
+ append_math_sub_imm_u32(desc, REG3, SEQOUTLEN, IMM, ctx->authsize);
+
+ /* assoclen + cryptlen = seqinlen - ivsize */
+ append_math_sub_imm_u32(desc, REG2, SEQINLEN, IMM, tfm->ivsize);
+
+ /* assoclen = (assoclen + cryptlen) - cryptlen */
+ append_math_sub(desc, REG1, REG2, REG3, CAAM_CMD_SZ);
+
+ /* if cryptlen is ZERO jump to zero-payload commands */
+ append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
+ zero_payload_jump_cmd = append_jump(desc, JUMP_TEST_ALL |
+ JUMP_COND_MATH_Z);
+ /* read IV */
+ append_seq_fifo_load(desc, tfm->ivsize, FIFOLD_CLASS_CLASS1 |
+ FIFOLD_TYPE_IV | FIFOLD_TYPE_FLUSH1);
+
+ /* if assoclen is ZERO, skip reading the assoc data */
+ append_math_add(desc, VARSEQINLEN, ZERO, REG1, CAAM_CMD_SZ);
+ zero_assoc_jump_cmd1 = append_jump(desc, JUMP_TEST_ALL |
+ JUMP_COND_MATH_Z);
+
+ /* read assoc data */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
+ FIFOLD_TYPE_AAD | FIFOLD_TYPE_FLUSH1);
+ set_jump_tgt_here(desc, zero_assoc_jump_cmd1);
+
+ append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
+
+ /* write encrypted data */
+ append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | FIFOLDST_VLF);
+
+ /* read payload data */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
+ FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST1);
+
+ /* jump the zero-payload commands */
+ append_jump(desc, JUMP_TEST_ALL | 7);
+
+ /* zero-payload commands */
+ set_jump_tgt_here(desc, zero_payload_jump_cmd);
+
+ /* if assoclen is ZERO, jump to IV reading - is the only input data */
+ append_math_add(desc, VARSEQINLEN, ZERO, REG1, CAAM_CMD_SZ);
+ zero_assoc_jump_cmd2 = append_jump(desc, JUMP_TEST_ALL |
+ JUMP_COND_MATH_Z);
+ /* read IV */
+ append_seq_fifo_load(desc, tfm->ivsize, FIFOLD_CLASS_CLASS1 |
+ FIFOLD_TYPE_IV | FIFOLD_TYPE_FLUSH1);
+
+ /* read assoc data */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
+ FIFOLD_TYPE_AAD | FIFOLD_TYPE_LAST1);
+
+ /* jump to ICV writing */
+ append_jump(desc, JUMP_TEST_ALL | 2);
+
+ /* read IV - is the only input data */
+ set_jump_tgt_here(desc, zero_assoc_jump_cmd2);
+ append_seq_fifo_load(desc, tfm->ivsize, FIFOLD_CLASS_CLASS1 |
+ FIFOLD_TYPE_IV | FIFOLD_TYPE_FLUSH1 |
+ FIFOLD_TYPE_LAST1);
+
+ /* write ICV */
+ append_seq_store(desc, ctx->authsize, LDST_CLASS_1_CCB |
+ LDST_SRCDST_BYTE_CONTEXT);
+
+ ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc,
+ desc_bytes(desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_enc_dma)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "gcm enc shdesc@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+
+ /*
+ * Job Descriptor and Shared Descriptors
+ * must all fit into the 64-word Descriptor h/w Buffer
+ */
+ if (DESC_GCM_DEC_LEN + DESC_JOB_IO_LEN +
+ ctx->enckeylen <= CAAM_DESC_BYTES_MAX)
+ keys_fit_inline = true;
+
+ desc = ctx->sh_desc_dec;
+
+ init_sh_desc(desc, HDR_SHARE_SERIAL);
+
+ /* skip key loading if they are loaded due to sharing */
+ key_jump_cmd = append_jump(desc, JUMP_JSL |
+ JUMP_TEST_ALL | JUMP_COND_SHRD |
+ JUMP_COND_SELF);
+ if (keys_fit_inline)
+ append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen,
+ ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
+ else
+ append_key(desc, ctx->key_dma, ctx->enckeylen,
+ CLASS_1 | KEY_DEST_CLASS_REG);
+ set_jump_tgt_here(desc, key_jump_cmd);
+
+ /* class 1 operation */
+ append_operation(desc, ctx->class1_alg_type |
+ OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT | OP_ALG_ICV_ON);
+
+ /* assoclen + cryptlen = seqinlen - ivsize - icvsize */
+ append_math_sub_imm_u32(desc, REG3, SEQINLEN, IMM,
+ ctx->authsize + tfm->ivsize);
+
+ /* assoclen = (assoclen + cryptlen) - cryptlen */
+ append_math_sub(desc, REG2, SEQOUTLEN, REG0, CAAM_CMD_SZ);
+ append_math_sub(desc, REG1, REG3, REG2, CAAM_CMD_SZ);
+
+ /* read IV */
+ append_seq_fifo_load(desc, tfm->ivsize, FIFOLD_CLASS_CLASS1 |
+ FIFOLD_TYPE_IV | FIFOLD_TYPE_FLUSH1);
+
+ /* jump to zero-payload command if cryptlen is zero */
+ append_math_add(desc, VARSEQOUTLEN, ZERO, REG2, CAAM_CMD_SZ);
+ zero_payload_jump_cmd = append_jump(desc, JUMP_TEST_ALL |
+ JUMP_COND_MATH_Z);
+
+ append_math_add(desc, VARSEQINLEN, ZERO, REG1, CAAM_CMD_SZ);
+ /* if asoclen is ZERO, skip reading assoc data */
+ zero_assoc_jump_cmd1 = append_jump(desc, JUMP_TEST_ALL |
+ JUMP_COND_MATH_Z);
+ /* read assoc data */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
+ FIFOLD_TYPE_AAD | FIFOLD_TYPE_FLUSH1);
+ set_jump_tgt_here(desc, zero_assoc_jump_cmd1);
+
+ append_math_add(desc, VARSEQINLEN, ZERO, REG2, CAAM_CMD_SZ);
+
+ /* store encrypted data */
+ append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | FIFOLDST_VLF);
+
+ /* read payload data */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
+ FIFOLD_TYPE_MSG | FIFOLD_TYPE_FLUSH1);
+
+ /* jump the zero-payload commands */
+ append_jump(desc, JUMP_TEST_ALL | 4);
+
+ /* zero-payload command */
+ set_jump_tgt_here(desc, zero_payload_jump_cmd);
+
+ /* if assoclen is ZERO, jump to ICV reading */
+ append_math_add(desc, VARSEQINLEN, ZERO, REG1, CAAM_CMD_SZ);
+ zero_assoc_jump_cmd2 = append_jump(desc, JUMP_TEST_ALL |
+ JUMP_COND_MATH_Z);
+ /* read assoc data */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
+ FIFOLD_TYPE_AAD | FIFOLD_TYPE_FLUSH1);
+ set_jump_tgt_here(desc, zero_assoc_jump_cmd2);
+
+ /* read ICV */
+ append_seq_fifo_load(desc, ctx->authsize, FIFOLD_CLASS_CLASS1 |
+ FIFOLD_TYPE_ICV | FIFOLD_TYPE_LAST1);
+
+ ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc,
+ desc_bytes(desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_dec_dma)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "gcm dec shdesc@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+
+ 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 u32 gen_split_aead_key(struct caam_ctx *ctx, const u8 *key_in,
u32 authkeylen)
{
@@ -534,6 +1238,110 @@ badkey:
return -EINVAL;
}
+static int tls_setkey(struct crypto_aead *aead, const u8 *key,
+ unsigned int keylen)
+{
+ /* Sizes for MDHA pads (*not* keys): MD5, SHA1, 224, 256, 384, 512 */
+ static const u8 mdpadlen[] = { 16, 20, 32, 32, 64, 64 };
+ struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ struct device *jrdev = ctx->jrdev;
+ struct rtattr *rta = (void *)key;
+ struct crypto_authenc_key_param *param;
+ unsigned int authkeylen;
+ unsigned int enckeylen;
+ int ret = 0;
+
+ param = RTA_DATA(rta);
+ enckeylen = be32_to_cpu(param->enckeylen);
+
+ key += RTA_ALIGN(rta->rta_len);
+ keylen -= RTA_ALIGN(rta->rta_len);
+
+ if (keylen < enckeylen)
+ goto badkey;
+
+ authkeylen = keylen - enckeylen;
+
+ if (keylen > CAAM_MAX_KEY_SIZE)
+ goto badkey;
+
+ /* Pick class 2 key length from algorithm submask */
+ ctx->split_key_len = mdpadlen[(ctx->alg_op & OP_ALG_ALGSEL_SUBMASK) >>
+ OP_ALG_ALGSEL_SHIFT] * 2;
+ ctx->split_key_pad_len = ALIGN(ctx->split_key_len, 16);
+
+#ifdef DEBUG
+ dev_err(jrdev, "keylen %d enckeylen %d authkeylen %d\n", keylen,
+ enckeylen, authkeylen);
+ dev_err(jrdev, "split_key_len %d split_key_pad_len %d\n",
+ ctx->split_key_len, ctx->split_key_pad_len);
+ print_hex_dump(KERN_ERR, "key in @"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1);
+#endif
+
+ ret = gen_split_aead_key(ctx, key, authkeylen);
+ if (ret)
+ goto badkey;
+
+ /* postpend encryption key to auth split key */
+ memcpy(ctx->key + ctx->split_key_pad_len, key + authkeylen, enckeylen);
+
+ ctx->key_dma = dma_map_single(jrdev, ctx->key, ctx->split_key_pad_len +
+ enckeylen, DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->key_dma)) {
+ dev_err(jrdev, "unable to map key i/o memory\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, ctx->key,
+ ctx->split_key_pad_len + enckeylen, 1);
+#endif
+
+ ctx->enckeylen = enckeylen;
+
+ ret = tls_set_sh_desc(aead);
+ if (ret) {
+ dma_unmap_single(jrdev, ctx->key_dma, ctx->split_key_pad_len +
+ enckeylen, DMA_TO_DEVICE);
+ }
+
+ return ret;
+badkey:
+ crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN);
+ return -EINVAL;
+}
+
+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 = 0;
+
+#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);
+ ctx->key_dma = dma_map_single(jrdev, ctx->key, keylen,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->key_dma)) {
+ dev_err(jrdev, "unable to map key i/o memory\n");
+ return -ENOMEM;
+ }
+ ctx->enckeylen = keylen;
+
+ ret = gcm_set_sh_desc(aead);
+ if (ret) {
+ dma_unmap_single(jrdev, ctx->key_dma, ctx->enckeylen,
+ DMA_TO_DEVICE);
+ }
+
+ return ret;
+}
+
static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
const u8 *key, unsigned int keylen)
{
@@ -541,7 +1349,7 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
struct ablkcipher_tfm *tfm = &ablkcipher->base.crt_ablkcipher;
struct device *jrdev = ctx->jrdev;
int ret = 0;
- u32 *key_jump_cmd, *jump_cmd;
+ u32 *key_jump_cmd;
u32 *desc;
#ifdef DEBUG
@@ -572,9 +1380,6 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
set_jump_tgt_here(desc, key_jump_cmd);
- /* Propagate errors from shared to job descriptor */
- append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
-
/* Load iv */
append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
LDST_CLASS_1_CCB | tfm->ivsize);
@@ -612,11 +1417,7 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
ctx->enckeylen, CLASS_1 |
KEY_DEST_CLASS_REG);
- /* For aead, only propagate error immediately if shared */
- jump_cmd = append_jump(desc, JUMP_TEST_ALL);
set_jump_tgt_here(desc, key_jump_cmd);
- append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
- set_jump_tgt_here(desc, jump_cmd);
/* load IV */
append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
@@ -628,9 +1429,6 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
/* Perform operation */
ablkcipher_append_src_dst(desc);
- /* Wait for key to load before allowing propagating error */
- append_dec_shr_done(desc);
-
ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc,
desc_bytes(desc),
DMA_TO_DEVICE);
@@ -658,10 +1456,10 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
* @dst_nents: number of segments in output scatterlist
* @dst_chained: if destination is chained
* @iv_dma: dma address of iv for checking continuity and link table
- * @desc: h/w descriptor (variable length; must not exceed MAX_CAAM_DESCSIZE)
* @sec4_sg_bytes: length of dma mapped sec4_sg space
* @sec4_sg_dma: bus physical mapped address of h/w link table
* @hw_desc: the h/w job descriptor followed by any referenced link tables
+ * (variable length; must not exceed MAX_CAAM_DESCSIZE)
*/
struct aead_edesc {
int assoc_nents;
@@ -817,7 +1615,7 @@ static void aead_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
ivsize, 1);
print_hex_dump(KERN_ERR, "dst @"__stringify(__LINE__)": ",
DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->dst),
- req->cryptlen, 1);
+ req->cryptlen - ctx->authsize, 1);
#endif
if (err) {
@@ -854,6 +1652,102 @@ static void aead_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
aead_request_complete(req, err);
}
+static void tls_encrypt_done(struct device *jrdev, u32 *desc, u32 err,
+ void *context)
+{
+ struct aead_request *req = context;
+ struct aead_edesc *edesc;
+
+#ifdef DEBUG
+ dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
+#endif
+
+ edesc = (struct aead_edesc *)((char *)desc -
+ offsetof(struct aead_edesc, hw_desc));
+
+ if (err) {
+ char tmp[CAAM_ERROR_STR_MAX];
+
+ dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
+ }
+
+ aead_unmap(jrdev, edesc, req);
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "assoc @"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->assoc),
+ req->assoclen, 1);
+ print_hex_dump(KERN_ERR, "dst @"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->dst),
+ edesc->dst_nents ? 100 : req->cryptlen, 1);
+#endif
+
+ kfree(edesc);
+
+ aead_request_complete(req, err);
+}
+
+static void tls_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
+ void *context)
+{
+ struct aead_request *req = context;
+ struct aead_edesc *edesc;
+ int cryptlen = req->cryptlen;
+ u8 padsize;
+ u8 padding[255]; /* padding can be 0-255 bytes */
+ int i;
+
+#ifdef DEBUG
+ dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
+#endif
+
+ edesc = (struct aead_edesc *)((char *)desc -
+ offsetof(struct aead_edesc, hw_desc));
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "dst @"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->dst),
+ req->cryptlen, 1);
+#endif
+
+ if (err) {
+ char tmp[CAAM_ERROR_STR_MAX];
+
+ dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
+ }
+
+ aead_unmap(jrdev, edesc, req);
+
+ /*
+ * verify hw auth check passed else return -EBADMSG
+ */
+ if ((err & JRSTA_CCBERR_ERRID_MASK) == JRSTA_CCBERR_ERRID_ICVCHK) {
+ err = -EBADMSG;
+ goto out;
+ }
+
+ /* Padding checking */
+ cryptlen -= 1;
+ scatterwalk_map_and_copy(&padsize, req->dst, cryptlen, 1, 0);
+ if (padsize > cryptlen) {
+ err = -EBADMSG;
+ goto out;
+ }
+ cryptlen -= padsize;
+ scatterwalk_map_and_copy(padding, req->dst, cryptlen, padsize, 0);
+ /* the padding content must be equal with padsize */
+ for (i = 0; i < padsize; i++)
+ if (padding[i] != padsize) {
+ err = -EBADMSG;
+ break;
+ }
+
+out:
+ kfree(edesc);
+
+ aead_request_complete(req, err);
+}
+
static void ablkcipher_encrypt_done(struct device *jrdev, u32 *desc, u32 err,
void *context)
{
@@ -971,12 +1865,9 @@ static void init_aead_job(u32 *sh_desc, dma_addr_t ptr,
(edesc->src_nents ? : 1);
in_options = LDST_SGF;
}
- if (encrypt)
- append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize +
- req->cryptlen - authsize, in_options);
- else
- append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize +
- req->cryptlen, in_options);
+
+ append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize + req->cryptlen,
+ in_options);
if (likely(req->src == req->dst)) {
if (all_contig) {
@@ -997,7 +1888,8 @@ static void init_aead_job(u32 *sh_desc, dma_addr_t ptr,
}
}
if (encrypt)
- append_seq_out_ptr(desc, dst_dma, req->cryptlen, out_options);
+ append_seq_out_ptr(desc, dst_dma, req->cryptlen + authsize,
+ out_options);
else
append_seq_out_ptr(desc, dst_dma, req->cryptlen - authsize,
out_options);
@@ -1047,8 +1939,8 @@ static void init_aead_giv_job(u32 *sh_desc, dma_addr_t ptr,
sec4_sg_index += edesc->assoc_nents + 1 + edesc->src_nents;
in_options = LDST_SGF;
}
- append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize +
- req->cryptlen - authsize, in_options);
+ append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize + req->cryptlen,
+ in_options);
if (contig & GIV_DST_CONTIG) {
dst_dma = edesc->iv_dma;
@@ -1065,7 +1957,88 @@ static void init_aead_giv_job(u32 *sh_desc, dma_addr_t ptr,
}
}
- append_seq_out_ptr(desc, dst_dma, ivsize + req->cryptlen, out_options);
+ append_seq_out_ptr(desc, dst_dma, ivsize + req->cryptlen + authsize,
+ out_options);
+}
+
+/*
+ * Fill in tls job descriptor either for encrypt or decrypt
+ */
+static void init_tls_job(u32 *sh_desc, dma_addr_t ptr,
+ struct aead_edesc *edesc,
+ struct aead_request *req,
+ bool all_contig, bool encrypt, unsigned int padsize)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ int ivsize = crypto_aead_ivsize(aead);
+ int authsize = ctx->authsize;
+ u32 *desc = edesc->hw_desc;
+ u32 out_options = 0, in_options;
+ dma_addr_t dst_dma, src_dma;
+ int len, sec4_sg_index = 0;
+
+#ifdef DEBUG
+ debug("assoclen %d cryptlen %d authsize %d\n",
+ req->assoclen, req->cryptlen, authsize);
+ print_hex_dump(KERN_ERR, "assoc @"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->assoc),
+ req->assoclen , 1);
+ print_hex_dump(KERN_ERR, "presciv@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, req->iv,
+ edesc->src_nents ? 100 : ivsize, 1);
+ print_hex_dump(KERN_ERR, "src @"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src),
+ edesc->src_nents ? 100 : req->cryptlen, 1);
+ print_hex_dump(KERN_ERR, "shrdesc@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, sh_desc,
+ desc_bytes(sh_desc), 1);
+#endif
+
+ len = desc_len(sh_desc);
+ init_job_desc_shared(desc, ptr, len, HDR_SHARE_DEFER | HDR_REVERSE);
+
+ if (all_contig) {
+ src_dma = sg_dma_address(req->assoc);
+ in_options = 0;
+ } else {
+ src_dma = edesc->sec4_sg_dma;
+ sec4_sg_index += (edesc->assoc_nents ? : 1) + 1 +
+ (edesc->src_nents ? : 1);
+ in_options = LDST_SGF;
+ }
+
+ if (likely(req->src == req->dst)) {
+ if (all_contig) {
+ dst_dma = sg_dma_address(req->src);
+ } else {
+ dst_dma = src_dma + sizeof(struct sec4_sg_entry) *
+ ((edesc->assoc_nents ? : 1) + 1);
+ out_options = LDST_SGF;
+ }
+ } else {
+ if (!edesc->dst_nents) {
+ dst_dma = sg_dma_address(req->dst);
+ } else {
+ dst_dma = edesc->sec4_sg_dma +
+ sec4_sg_index *
+ sizeof(struct sec4_sg_entry);
+ out_options = LDST_SGF;
+ }
+ }
+
+ /*
+ * For decrypt, do not strip ICV, Padding, Padding length since
+ * upper layer(s) perform padding checking.
+ */
+ if (encrypt)
+ append_seq_out_ptr(desc, dst_dma, req->cryptlen + padsize +
+ authsize, out_options);
+ else
+ append_seq_out_ptr(desc, dst_dma, req->cryptlen, out_options);
+
+ append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize +
+ req->cryptlen, in_options);
}
/*
@@ -1129,7 +2102,8 @@ static void init_ablkcipher_job(u32 *sh_desc, dma_addr_t ptr,
* allocate and map the aead extended descriptor
*/
static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
- int desc_bytes, bool *all_contig_ptr)
+ int desc_bytes, bool *all_contig_ptr,
+ bool encrypt, bool strip_icv)
{
struct crypto_aead *aead = crypto_aead_reqtfm(req);
struct caam_ctx *ctx = crypto_aead_ctx(aead);
@@ -1144,12 +2118,28 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
bool assoc_chained = false, src_chained = false, dst_chained = false;
int ivsize = crypto_aead_ivsize(aead);
int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes;
+ unsigned int authsize = ctx->authsize;
+ bool is_gcm = false;
assoc_nents = sg_count(req->assoc, req->assoclen, &assoc_chained);
- src_nents = sg_count(req->src, req->cryptlen, &src_chained);
- if (unlikely(req->dst != req->src))
- dst_nents = sg_count(req->dst, req->cryptlen, &dst_chained);
+ if (unlikely(req->dst != req->src)) {
+ int extralen;
+
+ src_nents = sg_count(req->src, req->cryptlen, &src_chained);
+
+ if (encrypt)
+ extralen = authsize;
+ else
+ extralen = strip_icv ? (-authsize) : 0;
+ dst_nents = sg_count(req->dst, req->cryptlen + extralen,
+ &dst_chained);
+ } else {
+ src_nents = sg_count(req->src,
+ req->cryptlen +
+ (encrypt ? authsize : 0),
+ &src_chained);
+ }
sgc = dma_map_sg_chained(jrdev, req->assoc, assoc_nents ? : 1,
DMA_TO_DEVICE, assoc_chained);
@@ -1163,16 +2153,32 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
DMA_FROM_DEVICE, dst_chained);
}
- /* Check if data are contiguous */
+ if (((ctx->class1_alg_type & OP_ALG_ALGSEL_MASK) ==
+ OP_ALG_ALGSEL_AES) &&
+ ((ctx->class1_alg_type & OP_ALG_AAI_MASK) == OP_ALG_AAI_GCM))
+ is_gcm = true;
+
+ /*
+ * Check if data are contiguous.
+ * GCM expected input sequence: IV, AAD, text
+ * All other - expected input sequence: AAD, IV, text
+ */
iv_dma = dma_map_single(jrdev, req->iv, ivsize, DMA_TO_DEVICE);
- if (assoc_nents || sg_dma_address(req->assoc) + req->assoclen !=
- iv_dma || src_nents || iv_dma + ivsize !=
- sg_dma_address(req->src)) {
- all_contig = false;
+ if (is_gcm)
+ all_contig = (!assoc_nents &&
+ iv_dma + ivsize == sg_dma_address(req->assoc) &&
+ !src_nents && sg_dma_address(req->assoc) +
+ req->assoclen == sg_dma_address(req->src));
+ else
+ all_contig = (!assoc_nents && sg_dma_address(req->assoc) +
+ req->assoclen == iv_dma && !src_nents &&
+ iv_dma + ivsize == sg_dma_address(req->src));
+ if (!all_contig) {
assoc_nents = assoc_nents ? : 1;
src_nents = src_nents ? : 1;
sec4_sg_len = assoc_nents + 1 + src_nents;
}
+
sec4_sg_len += dst_nents;
sec4_sg_bytes = sec4_sg_len * sizeof(struct sec4_sg_entry);
@@ -1201,14 +2207,26 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
sec4_sg_index = 0;
if (!all_contig) {
- sg_to_sec4_sg(req->assoc,
- (assoc_nents ? : 1),
- edesc->sec4_sg +
- sec4_sg_index, 0);
- sec4_sg_index += assoc_nents ? : 1;
+ if (!is_gcm) {
+ sg_to_sec4_sg(req->assoc,
+ (assoc_nents ? : 1),
+ edesc->sec4_sg +
+ sec4_sg_index, 0);
+ sec4_sg_index += assoc_nents ? : 1;
+ }
+
dma_to_sec4_sg_one(edesc->sec4_sg + sec4_sg_index,
iv_dma, ivsize, 0);
sec4_sg_index += 1;
+
+ if (is_gcm) {
+ sg_to_sec4_sg(req->assoc,
+ (assoc_nents ? : 1),
+ edesc->sec4_sg +
+ sec4_sg_index, 0);
+ sec4_sg_index += assoc_nents ? : 1;
+ }
+
sg_to_sec4_sg_last(req->src,
(src_nents ? : 1),
edesc->sec4_sg +
@@ -1233,11 +2251,9 @@ static int aead_encrypt(struct aead_request *req)
u32 *desc;
int ret = 0;
- req->cryptlen += ctx->authsize;
-
/* allocate extended descriptor */
edesc = aead_edesc_alloc(req, DESC_JOB_IO_LEN *
- CAAM_CMD_SZ, &all_contig);
+ CAAM_CMD_SZ, &all_contig, true, true);
if (IS_ERR(edesc))
return PTR_ERR(edesc);
@@ -1274,7 +2290,7 @@ static int aead_decrypt(struct aead_request *req)
/* allocate extended descriptor */
edesc = aead_edesc_alloc(req, DESC_JOB_IO_LEN *
- CAAM_CMD_SZ, &all_contig);
+ CAAM_CMD_SZ, &all_contig, false, true);
if (IS_ERR(edesc))
return PTR_ERR(edesc);
@@ -1331,7 +2347,8 @@ static struct aead_edesc *aead_giv_edesc_alloc(struct aead_givcrypt_request
src_nents = sg_count(req->src, req->cryptlen, &src_chained);
if (unlikely(req->dst != req->src))
- dst_nents = sg_count(req->dst, req->cryptlen, &dst_chained);
+ dst_nents = sg_count(req->dst, req->cryptlen + ctx->authsize,
+ &dst_chained);
sgc = dma_map_sg_chained(jrdev, req->assoc, assoc_nents ? : 1,
DMA_TO_DEVICE, assoc_chained);
@@ -1425,8 +2442,6 @@ static int aead_givencrypt(struct aead_givcrypt_request *areq)
u32 *desc;
int ret = 0;
- req->cryptlen += ctx->authsize;
-
/* allocate extended descriptor */
edesc = aead_giv_edesc_alloc(areq, DESC_JOB_IO_LEN *
CAAM_CMD_SZ, &contig);
@@ -1461,6 +2476,109 @@ static int aead_givencrypt(struct aead_givcrypt_request *areq)
return ret;
}
+static int aead_null_givencrypt(struct aead_givcrypt_request *areq)
+{
+ return aead_encrypt(&areq->areq);
+}
+
+static int tls_encrypt(struct aead_request *req)
+{
+ struct aead_edesc *edesc;
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ struct device *jrdev = ctx->jrdev;
+ bool all_contig;
+ u32 *desc;
+ int ret = 0;
+ unsigned int blocksize = crypto_aead_blocksize(aead);
+ unsigned int padsize;
+
+ padsize = blocksize - ((req->cryptlen + ctx->authsize) % blocksize);
+
+ /*
+ * allocate extended tls descriptor
+ * TLS 1.0 has no explicit IV in the packet, but it is needed as input
+ * since it is used by CBC.
+ * ctx->authsize is temporary set to include also padlen
+ */
+ ctx->authsize += padsize;
+ edesc = aead_edesc_alloc(req, DESC_JOB_IO_LEN * CAAM_CMD_SZ,
+ &all_contig, true, true);
+ if (IS_ERR(edesc))
+ return PTR_ERR(edesc);
+ ctx->authsize -= padsize;
+
+ /* Create and submit job descriptor */
+ init_tls_job(ctx->sh_desc_enc, ctx->sh_desc_enc_dma, edesc, req,
+ all_contig, true, padsize);
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "tls enc jobdesc@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc,
+ desc_bytes(edesc->hw_desc), 1);
+#endif
+
+ desc = edesc->hw_desc;
+ ret = caam_jr_enqueue(jrdev, desc, tls_encrypt_done, req);
+ if (!ret) {
+ ret = -EINPROGRESS;
+ } else {
+ aead_unmap(jrdev, edesc, req);
+ kfree(edesc);
+ }
+
+ return ret;
+}
+
+static int tls_decrypt(struct aead_request *req)
+{
+ struct aead_edesc *edesc;
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ struct device *jrdev = ctx->jrdev;
+ bool all_contig;
+ u32 *desc;
+ int ret = 0;
+
+ /*
+ * allocate extended tls descriptor
+ * TLS 1.0 has no explicit IV in the packet, but it is needed as input
+ * since it is used by CBC.
+ * Assumption: since padding and ICV are not stripped (upper layer
+ * checks padding), req->dst has to be big enough to hold payloadlen +
+ * padlen + icvlen.
+ */
+ edesc = aead_edesc_alloc(req, DESC_JOB_IO_LEN * CAAM_CMD_SZ,
+ &all_contig, false, false);
+ if (IS_ERR(edesc))
+ return PTR_ERR(edesc);
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "dec src@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(req->src),
+ req->cryptlen, 1);
+#endif
+
+ /* Create and submit job descriptor*/
+ init_tls_job(ctx->sh_desc_dec, ctx->sh_desc_dec_dma, edesc, req,
+ all_contig, false, 0);
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "tls dec jobdesc@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, edesc->hw_desc,
+ desc_bytes(edesc->hw_desc), 1);
+#endif
+
+ desc = edesc->hw_desc;
+ ret = caam_jr_enqueue(jrdev, desc, tls_decrypt_done, req);
+ if (!ret) {
+ ret = -EINPROGRESS;
+ } else {
+ aead_unmap(jrdev, edesc, req);
+ kfree(edesc);
+ }
+
+ return ret;
+}
+
/*
* allocate and map the ablkcipher extended descriptor for ablkcipher
*/
@@ -1645,11 +2763,130 @@ struct caam_alg_template {
u32 class1_alg_type;
u32 class2_alg_type;
u32 alg_op;
+ int min_era;
};
static struct caam_alg_template driver_algs[] = {
/* single-pass ipsec_esp descriptor */
{
+ .name = "authenc(hmac(md5),ecb(cipher_null))",
+ .driver_name = "authenc-hmac-md5-ecb-cipher_null-caam",
+ .blocksize = NULL_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_null_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = NULL_IV_SIZE,
+ .maxauthsize = MD5_DIGEST_SIZE,
+ },
+ .class1_alg_type = 0,
+ .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+ },
+ {
+ .name = "authenc(hmac(sha1),ecb(cipher_null))",
+ .driver_name = "authenc-hmac-sha1-ecb-cipher_null-caam",
+ .blocksize = NULL_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_null_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = NULL_IV_SIZE,
+ .maxauthsize = SHA1_DIGEST_SIZE,
+ },
+ .class1_alg_type = 0,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+ },
+ {
+ .name = "authenc(hmac(sha224),ecb(cipher_null))",
+ .driver_name = "authenc-hmac-sha224-ecb-cipher_null-caam",
+ .blocksize = NULL_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_null_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = NULL_IV_SIZE,
+ .maxauthsize = SHA224_DIGEST_SIZE,
+ },
+ .class1_alg_type = 0,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA224 |
+ OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+ },
+ {
+ .name = "authenc(hmac(sha256),ecb(cipher_null))",
+ .driver_name = "authenc-hmac-sha256-ecb-cipher_null-caam",
+ .blocksize = NULL_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_null_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = NULL_IV_SIZE,
+ .maxauthsize = SHA256_DIGEST_SIZE,
+ },
+ .class1_alg_type = 0,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA256 |
+ OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
+ },
+ {
+ .name = "authenc(hmac(sha384),ecb(cipher_null))",
+ .driver_name = "authenc-hmac-sha384-ecb-cipher_null-caam",
+ .blocksize = NULL_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_null_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = NULL_IV_SIZE,
+ .maxauthsize = SHA384_DIGEST_SIZE,
+ },
+ .class1_alg_type = 0,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA384 |
+ OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+ },
+ {
+ .name = "authenc(hmac(sha512),ecb(cipher_null))",
+ .driver_name = "authenc-hmac-sha512-ecb-cipher_null-caam",
+ .blocksize = NULL_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_null_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = NULL_IV_SIZE,
+ .maxauthsize = SHA512_DIGEST_SIZE,
+ },
+ .class1_alg_type = 0,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA512 |
+ OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
+ },
+ {
.name = "authenc(hmac(md5),cbc(aes))",
.driver_name = "authenc-hmac-md5-cbc-aes-caam",
.blocksize = AES_BLOCK_SIZE,
@@ -1667,6 +2904,7 @@ static struct caam_alg_template driver_algs[] = {
.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
.class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP,
.alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
},
{
.name = "authenc(hmac(sha1),cbc(aes))",
@@ -1686,6 +2924,7 @@ static struct caam_alg_template driver_algs[] = {
.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
.class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP,
.alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
},
{
.name = "authenc(hmac(sha224),cbc(aes))",
@@ -1706,6 +2945,7 @@ static struct caam_alg_template driver_algs[] = {
.class2_alg_type = OP_ALG_ALGSEL_SHA224 |
OP_ALG_AAI_HMAC_PRECOMP,
.alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
},
{
.name = "authenc(hmac(sha256),cbc(aes))",
@@ -1726,6 +2966,7 @@ static struct caam_alg_template driver_algs[] = {
.class2_alg_type = OP_ALG_ALGSEL_SHA256 |
OP_ALG_AAI_HMAC_PRECOMP,
.alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
},
{
.name = "authenc(hmac(sha384),cbc(aes))",
@@ -1746,6 +2987,7 @@ static struct caam_alg_template driver_algs[] = {
.class2_alg_type = OP_ALG_ALGSEL_SHA384 |
OP_ALG_AAI_HMAC_PRECOMP,
.alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
},
{
@@ -1767,6 +3009,7 @@ static struct caam_alg_template driver_algs[] = {
.class2_alg_type = OP_ALG_ALGSEL_SHA512 |
OP_ALG_AAI_HMAC_PRECOMP,
.alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
},
{
.name = "authenc(hmac(md5),cbc(des3_ede))",
@@ -1786,6 +3029,7 @@ static struct caam_alg_template driver_algs[] = {
.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
.class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP,
.alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
},
{
.name = "authenc(hmac(sha1),cbc(des3_ede))",
@@ -1805,6 +3049,7 @@ static struct caam_alg_template driver_algs[] = {
.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
.class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP,
.alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
},
{
.name = "authenc(hmac(sha224),cbc(des3_ede))",
@@ -1825,6 +3070,7 @@ static struct caam_alg_template driver_algs[] = {
.class2_alg_type = OP_ALG_ALGSEL_SHA224 |
OP_ALG_AAI_HMAC_PRECOMP,
.alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
},
{
.name = "authenc(hmac(sha256),cbc(des3_ede))",
@@ -1845,6 +3091,7 @@ static struct caam_alg_template driver_algs[] = {
.class2_alg_type = OP_ALG_ALGSEL_SHA256 |
OP_ALG_AAI_HMAC_PRECOMP,
.alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
},
{
.name = "authenc(hmac(sha384),cbc(des3_ede))",
@@ -1865,6 +3112,7 @@ static struct caam_alg_template driver_algs[] = {
.class2_alg_type = OP_ALG_ALGSEL_SHA384 |
OP_ALG_AAI_HMAC_PRECOMP,
.alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
},
{
.name = "authenc(hmac(sha512),cbc(des3_ede))",
@@ -1885,6 +3133,7 @@ static struct caam_alg_template driver_algs[] = {
.class2_alg_type = OP_ALG_ALGSEL_SHA512 |
OP_ALG_AAI_HMAC_PRECOMP,
.alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
},
{
.name = "authenc(hmac(md5),cbc(des))",
@@ -1904,6 +3153,7 @@ static struct caam_alg_template driver_algs[] = {
.class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
.class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP,
.alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
},
{
.name = "authenc(hmac(sha1),cbc(des))",
@@ -1923,6 +3173,7 @@ static struct caam_alg_template driver_algs[] = {
.class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
.class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP,
.alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
},
{
.name = "authenc(hmac(sha224),cbc(des))",
@@ -1943,6 +3194,7 @@ static struct caam_alg_template driver_algs[] = {
.class2_alg_type = OP_ALG_ALGSEL_SHA224 |
OP_ALG_AAI_HMAC_PRECOMP,
.alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
},
{
.name = "authenc(hmac(sha256),cbc(des))",
@@ -1963,6 +3215,7 @@ static struct caam_alg_template driver_algs[] = {
.class2_alg_type = OP_ALG_ALGSEL_SHA256 |
OP_ALG_AAI_HMAC_PRECOMP,
.alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
},
{
.name = "authenc(hmac(sha384),cbc(des))",
@@ -1983,6 +3236,7 @@ static struct caam_alg_template driver_algs[] = {
.class2_alg_type = OP_ALG_ALGSEL_SHA384 |
OP_ALG_AAI_HMAC_PRECOMP,
.alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
},
{
.name = "authenc(hmac(sha512),cbc(des))",
@@ -2003,6 +3257,47 @@ static struct caam_alg_template driver_algs[] = {
.class2_alg_type = OP_ALG_ALGSEL_SHA512 |
OP_ALG_AAI_HMAC_PRECOMP,
.alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
+ },
+ /* TLS record descriptors */
+ {
+ .name = "tls10(hmac(sha1),cbc(aes))",
+ .driver_name = "tls10-hmac-sha1-cbc-aes-caam",
+ .blocksize = AES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = tls_setkey,
+ .setauthsize = tls_setauthsize,
+ .encrypt = tls_encrypt,
+ .decrypt = tls_decrypt,
+ .givencrypt = NULL,
+ .geniv = "<built-in>",
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = SHA1_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+ .min_era = 4,
+ },
+ /* Galois Counter Mode */
+ {
+ .name = "gcm(aes)",
+ .driver_name = "gcm-aes-caam",
+ .blocksize = AES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = gcm_setkey,
+ .setauthsize = gcm_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = NULL,
+ .geniv = "<built-in>",
+ .ivsize = 12,
+ .maxauthsize = 16,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM,
+ .min_era = 2,
},
/* ablkcipher descriptor */
{
@@ -2020,6 +3315,7 @@ static struct caam_alg_template driver_algs[] = {
.ivsize = AES_BLOCK_SIZE,
},
.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+ .min_era = 2,
},
{
.name = "cbc(des3_ede)",
@@ -2036,6 +3332,7 @@ static struct caam_alg_template driver_algs[] = {
.ivsize = DES3_EDE_BLOCK_SIZE,
},
.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+ .min_era = 2,
},
{
.name = "cbc(des)",
@@ -2052,12 +3349,12 @@ static struct caam_alg_template driver_algs[] = {
.ivsize = DES_BLOCK_SIZE,
},
.class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+ .min_era = 2,
}
};
struct caam_crypto_alg {
struct list_head entry;
- struct device *ctrldev;
int class1_alg_type;
int class2_alg_type;
int alg_op;
@@ -2070,20 +3367,37 @@ static int caam_cra_init(struct crypto_tfm *tfm)
struct caam_crypto_alg *caam_alg =
container_of(alg, struct caam_crypto_alg, crypto_alg);
struct caam_ctx *ctx = crypto_tfm_ctx(tfm);
- struct caam_drv_private *priv = dev_get_drvdata(caam_alg->ctrldev);
- int tgt_jr = atomic_inc_return(&priv->tfm_count);
-
- /*
- * distribute tfms across job rings to ensure in-order
- * crypto request processing per tfm
- */
- ctx->jrdev = priv->jrdev[(tgt_jr / 2) % priv->total_jobrs];
+ /* Digest sizes for MD5, SHA1, SHA-224, SHA-256, SHA-384, SHA-512 */
+ static const u8 digest_size[] = {
+ MD5_DIGEST_SIZE,
+ SHA1_DIGEST_SIZE,
+ SHA224_DIGEST_SIZE,
+ SHA256_DIGEST_SIZE,
+ SHA384_DIGEST_SIZE,
+ SHA512_DIGEST_SIZE
+ };
+
+ ctx->jrdev = caam_jr_alloc();
+ if (IS_ERR(ctx->jrdev)) {
+ pr_err("Job Ring Device allocation for transform failed\n");
+ return PTR_ERR(ctx->jrdev);
+ }
/* copy descriptor header template value */
ctx->class1_alg_type = OP_TYPE_CLASS1_ALG | caam_alg->class1_alg_type;
ctx->class2_alg_type = OP_TYPE_CLASS2_ALG | caam_alg->class2_alg_type;
ctx->alg_op = OP_TYPE_CLASS2_ALG | caam_alg->alg_op;
+ /*
+ * Need authsize, in case setauthsize callback not called
+ * by upper layer (e.g. TLS).
+ */
+ if (caam_alg->alg_op)
+ ctx->authsize = digest_size[(ctx->alg_op &
+ OP_ALG_ALGSEL_SUBMASK) >> OP_ALG_ALGSEL_SHIFT];
+ else
+ ctx->authsize = 0;
+
return 0;
}
@@ -2104,44 +3418,31 @@ static void caam_cra_exit(struct crypto_tfm *tfm)
dma_unmap_single(ctx->jrdev, ctx->sh_desc_givenc_dma,
desc_bytes(ctx->sh_desc_givenc),
DMA_TO_DEVICE);
+ if (ctx->key_dma &&
+ !dma_mapping_error(ctx->jrdev, ctx->key_dma))
+ dma_unmap_single(ctx->jrdev, ctx->key_dma,
+ ctx->enckeylen + ctx->split_key_pad_len,
+ DMA_TO_DEVICE);
+
+ caam_jr_free(ctx->jrdev);
}
static void __exit caam_algapi_exit(void)
{
- struct device_node *dev_node;
- struct platform_device *pdev;
- struct device *ctrldev;
- struct caam_drv_private *priv;
struct caam_crypto_alg *t_alg, *n;
- dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
- if (!dev_node) {
- dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
- if (!dev_node)
- return;
- }
-
- pdev = of_find_device_by_node(dev_node);
- if (!pdev)
+ if (!alg_list.next)
return;
- ctrldev = &pdev->dev;
- of_node_put(dev_node);
- priv = dev_get_drvdata(ctrldev);
-
- if (!priv->alg_list.next)
- return;
-
- list_for_each_entry_safe(t_alg, n, &priv->alg_list, entry) {
+ list_for_each_entry_safe(t_alg, n, &alg_list, entry) {
crypto_unregister_alg(&t_alg->crypto_alg);
list_del(&t_alg->entry);
kfree(t_alg);
}
}
-static struct caam_crypto_alg *caam_alg_alloc(struct device *ctrldev,
- struct caam_alg_template
+static struct caam_crypto_alg *caam_alg_alloc(struct caam_alg_template
*template)
{
struct caam_crypto_alg *t_alg;
@@ -2149,7 +3450,7 @@ static struct caam_crypto_alg *caam_alg_alloc(struct device *ctrldev,
t_alg = kzalloc(sizeof(struct caam_crypto_alg), GFP_KERNEL);
if (!t_alg) {
- dev_err(ctrldev, "failed to allocate t_alg\n");
+ pr_err("failed to allocate t_alg\n");
return ERR_PTR(-ENOMEM);
}
@@ -2181,7 +3482,6 @@ static struct caam_crypto_alg *caam_alg_alloc(struct device *ctrldev,
t_alg->class1_alg_type = template->class1_alg_type;
t_alg->class2_alg_type = template->class2_alg_type;
t_alg->alg_op = template->alg_op;
- t_alg->ctrldev = ctrldev;
return t_alg;
}
@@ -2209,34 +3509,46 @@ static int __init caam_algapi_init(void)
priv = dev_get_drvdata(ctrldev);
of_node_put(dev_node);
- INIT_LIST_HEAD(&priv->alg_list);
+ /*
+ * If priv is NULL, it's probably because the caam driver wasn't
+ * properly initialized (e.g. RNG4 init failed). Thus, bail out here.
+ */
+ if (!priv)
+ return -ENODEV;
+
- atomic_set(&priv->tfm_count, -1);
+ INIT_LIST_HEAD(&alg_list);
/* register crypto algorithms the device supports */
for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
- /* TODO: check if h/w supports alg */
struct caam_crypto_alg *t_alg;
- t_alg = caam_alg_alloc(ctrldev, &driver_algs[i]);
+ /* check if h/w supports alg */
+ if (priv->era > 0 && priv->era < driver_algs[i].min_era) {
+ pr_warn("%s needs Era %d or higher but SEC is Era %d, skipping it\n",
+ driver_algs[i].driver_name,
+ driver_algs[i].min_era, priv->era);
+ continue;
+ }
+
+ t_alg = caam_alg_alloc(&driver_algs[i]);
if (IS_ERR(t_alg)) {
err = PTR_ERR(t_alg);
- dev_warn(ctrldev, "%s alg allocation failed\n",
- driver_algs[i].driver_name);
+ pr_warn("%s alg allocation failed\n",
+ driver_algs[i].driver_name);
continue;
}
err = crypto_register_alg(&t_alg->crypto_alg);
if (err) {
- dev_warn(ctrldev, "%s alg registration failed\n",
+ pr_warn("%s alg registration failed\n",
t_alg->crypto_alg.cra_driver_name);
kfree(t_alg);
} else
- list_add_tail(&t_alg->entry, &priv->alg_list);
+ list_add_tail(&t_alg->entry, &alg_list);
}
- if (!list_empty(&priv->alg_list))
- dev_info(ctrldev, "%s algorithms registered in /proc/crypto\n",
- (char *)of_get_property(dev_node, "compatible", NULL));
+ if (!list_empty(&alg_list))
+ pr_info("caam algorithms registered in /proc/crypto\n");
return err;
}
diff --git a/drivers/crypto/caam/caamalg_qi.c b/drivers/crypto/caam/caamalg_qi.c
new file mode 100644
index 0000000..7eb95b9
--- /dev/null
+++ b/drivers/crypto/caam/caamalg_qi.c
@@ -0,0 +1,2260 @@
+/*
+ * Freescale FSL CAAM support for crypto API over QI backend
+ *
+ * Copyright 2008-2011, 2013 Freescale Semiconductor, Inc.
+ *
+ */
+
+
+#include "compat.h"
+
+#include "regs.h"
+#include "intern.h"
+#include "desc_constr.h"
+#include "error.h"
+#include "sg_sw_sec4.h"
+#include "sg_sw_qm.h"
+#include "key_gen.h"
+#include "qi.h"
+#include "jr.h"
+#include "ctrl.h"
+
+/*
+ * crypto alg
+ */
+#define CAAM_CRA_PRIORITY 4000
+/* max key is sum of AES_MAX_KEY_SIZE, max split key size */
+#define CAAM_MAX_KEY_SIZE (AES_MAX_KEY_SIZE + \
+ SHA512_DIGEST_SIZE * 2)
+/* max IV is max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
+#define CAAM_MAX_IV_LENGTH 16
+
+/* length of descriptors text */
+#define DESC_AEAD_BASE (4 * CAAM_CMD_SZ)
+#define DESC_AEAD_ENC_LEN (DESC_AEAD_BASE + 16 * CAAM_CMD_SZ)
+#define DESC_AEAD_DEC_LEN (DESC_AEAD_BASE + 21 * CAAM_CMD_SZ)
+#define DESC_AEAD_GIVENC_LEN (DESC_AEAD_ENC_LEN + 7 * CAAM_CMD_SZ)
+
+#define DESC_TLS_BASE (4 * CAAM_CMD_SZ)
+#define DESC_TLS10_ENC_LEN (DESC_TLS_BASE + 23 * CAAM_CMD_SZ)
+
+#define DESC_MAX_USED_BYTES (DESC_AEAD_GIVENC_LEN + \
+ CAAM_MAX_KEY_SIZE)
+#define DESC_MAX_USED_LEN (DESC_MAX_USED_BYTES / CAAM_CMD_SZ)
+
+/* Set DK bit in class 1 operation if shared */
+static inline void append_dec_op1(u32 *desc, u32 type)
+{
+ u32 *jump_cmd, *uncond_jump_cmd;
+
+ jump_cmd = append_jump(desc, JUMP_TEST_ALL | JUMP_COND_SHRD);
+ append_operation(desc, type | OP_ALG_AS_INITFINAL |
+ OP_ALG_DECRYPT);
+ uncond_jump_cmd = append_jump(desc, JUMP_TEST_ALL);
+ set_jump_tgt_here(desc, jump_cmd);
+ append_operation(desc, type | OP_ALG_AS_INITFINAL |
+ OP_ALG_DECRYPT | OP_ALG_AAI_DK);
+ set_jump_tgt_here(desc, uncond_jump_cmd);
+}
+
+/*
+ * Wait for completion of class 1 key loading before allowing
+ * error propagation
+ */
+static inline void append_dec_shr_done(u32 *desc)
+{
+ u32 *jump_cmd;
+
+ jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TEST_ALL);
+ set_jump_tgt_here(desc, jump_cmd);
+ append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
+}
+
+/*
+ * For aead functions, read payload and write payload,
+ * both of which are specified in req->src and req->dst
+ */
+static inline void aead_append_src_dst(u32 *desc, u32 msg_type)
+{
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_BOTH |
+ KEY_VLF | msg_type | FIFOLD_TYPE_LASTBOTH);
+ append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF);
+}
+
+/*
+ * For aead encrypt and decrypt, read iv for both classes
+ */
+static inline void aead_append_ld_iv(u32 *desc, int ivsize)
+{
+ append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
+ LDST_CLASS_1_CCB | ivsize);
+ append_move(desc, MOVE_SRC_CLASS1CTX | MOVE_DEST_CLASS2INFIFO | ivsize);
+}
+
+/*
+ * If all data, including src (with assoc and iv) or dst (with iv only) are
+ * contiguous
+ */
+#define GIV_SRC_CONTIG 1
+#define GIV_DST_CONTIG (1 << 1)
+
+enum optype {
+ ENCRYPT,
+ DECRYPT,
+ GIVENCRYPT,
+ NUM_OP
+};
+/*
+ * per-session context
+ */
+struct caam_ctx {
+ struct device *jrdev;
+ u32 sh_desc_enc[DESC_MAX_USED_LEN];
+ u32 sh_desc_dec[DESC_MAX_USED_LEN];
+ u32 sh_desc_givenc[DESC_MAX_USED_LEN];
+ u32 class1_alg_type;
+ u32 class2_alg_type;
+ u32 alg_op;
+ u8 key[CAAM_MAX_KEY_SIZE];
+ dma_addr_t key_dma;
+ unsigned int enckeylen;
+ unsigned int split_key_len;
+ unsigned int split_key_pad_len;
+ unsigned int authsize;
+ struct device *qidev;
+ spinlock_t lock; /* Protects multiple init of driver context */
+ struct caam_drv_ctx *drv_ctx[NUM_OP];
+};
+
+static void append_key_aead(u32 *desc, struct caam_ctx *ctx,
+ int keys_fit_inline)
+{
+ if (keys_fit_inline) {
+ append_key_as_imm(desc, ctx->key, ctx->split_key_pad_len,
+ ctx->split_key_len, CLASS_2 |
+ KEY_DEST_MDHA_SPLIT | KEY_ENC);
+ append_key_as_imm(desc, (void *)ctx->key +
+ ctx->split_key_pad_len, ctx->enckeylen,
+ ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
+ } else {
+ append_key(desc, ctx->key_dma, ctx->split_key_len, CLASS_2 |
+ KEY_DEST_MDHA_SPLIT | KEY_ENC);
+ append_key(desc, ctx->key_dma + ctx->split_key_pad_len,
+ ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
+ }
+}
+
+static void init_sh_desc_key_aead(u32 *desc, struct caam_ctx *ctx,
+ int keys_fit_inline)
+{
+ u32 *key_jump_cmd;
+
+ init_sh_desc(desc, HDR_SHARE_SERIAL);
+
+ /* Skip if already shared */
+ key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+ JUMP_COND_SHRD);
+
+ append_key_aead(desc, ctx, keys_fit_inline);
+
+ set_jump_tgt_here(desc, key_jump_cmd);
+
+ /* Propagate errors from shared to job descriptor */
+ append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
+}
+
+static int aead_set_sh_desc(struct crypto_aead *aead)
+{
+ struct aead_tfm *tfm = &aead->base.crt_aead;
+ struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ bool keys_fit_inline = false;
+ u32 *key_jump_cmd, *jump_cmd;
+ u32 geniv, moveiv;
+ u32 *desc;
+
+ if (!ctx->enckeylen || !ctx->authsize)
+ return 0;
+
+ /*
+ * Job Descriptor and Shared Descriptors
+ * must all fit into the 64-word Descriptor h/w Buffer
+ */
+ if (DESC_AEAD_ENC_LEN + DESC_JOB_IO_LEN +
+ ctx->split_key_pad_len + ctx->enckeylen <=
+ CAAM_DESC_BYTES_MAX)
+ keys_fit_inline = true;
+
+ /* aead_encrypt shared descriptor */
+ desc = ctx->sh_desc_enc;
+
+ init_sh_desc_key_aead(desc, ctx, keys_fit_inline);
+
+ /* Class 2 operation */
+ append_operation(desc, ctx->class2_alg_type |
+ OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
+
+ /* cryptlen = seqoutlen - authsize */
+ append_math_sub_imm_u32(desc, REG3, SEQOUTLEN, IMM, ctx->authsize);
+
+ /* assoclen + cryptlen = seqinlen - ivsize */
+ append_math_sub_imm_u32(desc, REG2, SEQINLEN, IMM, tfm->ivsize);
+
+ /* assoclen + cryptlen = (assoclen + cryptlen) - cryptlen */
+ append_math_sub(desc, VARSEQINLEN, REG2, REG3, CAAM_CMD_SZ);
+
+ /* read assoc before reading payload */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
+ KEY_VLF);
+ aead_append_ld_iv(desc, tfm->ivsize);
+
+ /* Class 1 operation */
+ append_operation(desc, ctx->class1_alg_type |
+ OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
+
+ /* Read and write cryptlen bytes */
+ append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
+ append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
+ aead_append_src_dst(desc, FIFOLD_TYPE_MSG1OUT2);
+
+ /* Write ICV */
+ append_seq_store(desc, ctx->authsize, LDST_CLASS_2_CCB |
+ LDST_SRCDST_BYTE_CONTEXT);
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR,
+ "aead enc shdesc@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+
+ /*
+ * Job Descriptor and Shared Descriptors
+ * must all fit into the 64-word Descriptor h/w Buffer
+ */
+ if (DESC_AEAD_DEC_LEN + DESC_JOB_IO_LEN +
+ ctx->split_key_pad_len + ctx->enckeylen <=
+ CAAM_DESC_BYTES_MAX)
+ keys_fit_inline = true;
+
+ desc = ctx->sh_desc_dec;
+
+ /* aead_decrypt shared descriptor */
+ init_sh_desc(desc, HDR_SHARE_SERIAL);
+
+ /* Skip if already shared */
+ key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+ JUMP_COND_SHRD);
+
+ append_key_aead(desc, ctx, keys_fit_inline);
+
+ /* Only propagate error immediately if shared */
+ jump_cmd = append_jump(desc, JUMP_TEST_ALL);
+ set_jump_tgt_here(desc, key_jump_cmd);
+ append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
+ set_jump_tgt_here(desc, jump_cmd);
+
+ /* Class 2 operation */
+ append_operation(desc, ctx->class2_alg_type |
+ OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT | OP_ALG_ICV_ON);
+
+ /* assoclen + cryptlen = seqinlen - ivsize */
+ append_math_sub_imm_u32(desc, REG3, SEQINLEN, IMM,
+ ctx->authsize + tfm->ivsize);
+ /* assoclen = (assoclen + cryptlen) - cryptlen */
+ append_math_sub(desc, REG2, SEQOUTLEN, REG0, CAAM_CMD_SZ);
+ append_math_sub(desc, VARSEQINLEN, REG3, REG2, CAAM_CMD_SZ);
+
+ /* read assoc before reading payload */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
+ KEY_VLF);
+
+ aead_append_ld_iv(desc, tfm->ivsize);
+
+ append_dec_op1(desc, ctx->class1_alg_type);
+
+ /* Read and write cryptlen bytes */
+ append_math_add(desc, VARSEQINLEN, ZERO, REG2, CAAM_CMD_SZ);
+ append_math_add(desc, VARSEQOUTLEN, ZERO, REG2, CAAM_CMD_SZ);
+ aead_append_src_dst(desc, FIFOLD_TYPE_MSG);
+
+ /* Load ICV */
+ append_seq_fifo_load(desc, ctx->authsize, FIFOLD_CLASS_CLASS2 |
+ FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_ICV);
+ append_dec_shr_done(desc);
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "aead dec shdesc@"
+ __stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+
+ /*
+ * Job Descriptor and Shared Descriptors
+ * must all fit into the 64-word Descriptor h/w Buffer
+ */
+ if (DESC_AEAD_GIVENC_LEN + DESC_JOB_IO_LEN +
+ ctx->split_key_pad_len + ctx->enckeylen <=
+ CAAM_DESC_BYTES_MAX)
+ keys_fit_inline = true;
+
+ /* aead_givencrypt shared descriptor */
+ desc = ctx->sh_desc_givenc;
+
+ init_sh_desc_key_aead(desc, ctx, keys_fit_inline);
+
+ /* Generate IV */
+ geniv = NFIFOENTRY_STYPE_PAD | NFIFOENTRY_DEST_DECO |
+ NFIFOENTRY_DTYPE_MSG | NFIFOENTRY_LC1 |
+ NFIFOENTRY_PTYPE_RND | (tfm->ivsize << NFIFOENTRY_DLEN_SHIFT);
+ append_load_imm_u32(desc, geniv, LDST_CLASS_IND_CCB |
+ LDST_SRCDST_WORD_INFO_FIFO | LDST_IMM);
+ append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
+ append_move(desc, MOVE_SRC_INFIFO |
+ MOVE_DEST_CLASS1CTX | (tfm->ivsize << MOVE_LEN_SHIFT));
+ append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
+
+ /* Copy IV to class 1 context */
+ append_move(desc, MOVE_SRC_CLASS1CTX |
+ MOVE_DEST_OUTFIFO | (tfm->ivsize << MOVE_LEN_SHIFT));
+
+ /* Return to encryption */
+ append_operation(desc, ctx->class2_alg_type |
+ OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
+
+ /* ivsize + cryptlen = seqoutlen - authsize */
+ append_math_sub_imm_u32(desc, REG3, SEQOUTLEN, IMM, ctx->authsize);
+
+ /* assoclen = seqinlen - (ivsize + cryptlen) */
+ append_math_sub(desc, VARSEQINLEN, SEQINLEN, REG3, CAAM_CMD_SZ);
+
+ /* read assoc before reading payload */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
+ KEY_VLF);
+
+ /* Copy iv from class 1 ctx to class 2 fifo*/
+ moveiv = NFIFOENTRY_STYPE_OFIFO | NFIFOENTRY_DEST_CLASS2 |
+ NFIFOENTRY_DTYPE_MSG | (tfm->ivsize << NFIFOENTRY_DLEN_SHIFT);
+ append_load_imm_u32(desc, moveiv, LDST_CLASS_IND_CCB |
+ LDST_SRCDST_WORD_INFO_FIFO | LDST_IMM);
+ append_load_imm_u32(desc, tfm->ivsize, LDST_CLASS_2_CCB |
+ LDST_SRCDST_WORD_DATASZ_REG | LDST_IMM);
+
+ /* Class 1 operation */
+ append_operation(desc, ctx->class1_alg_type |
+ OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
+
+ /* Will write ivsize + cryptlen */
+ append_math_add(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+
+ /* Not need to reload iv */
+ append_seq_fifo_load(desc, tfm->ivsize,
+ FIFOLD_CLASS_SKIP);
+
+ /* Will read cryptlen */
+ append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+ aead_append_src_dst(desc, FIFOLD_TYPE_MSG1OUT2);
+
+ /* Write ICV */
+ append_seq_store(desc, ctx->authsize, LDST_CLASS_2_CCB |
+ LDST_SRCDST_BYTE_CONTEXT);
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR,
+ "aead givenc shdesc@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+
+ return 0;
+}
+
+static int aead_setauthsize(struct crypto_aead *authenc,
+ unsigned int authsize)
+{
+ struct caam_ctx *ctx = crypto_aead_ctx(authenc);
+
+ ctx->authsize = authsize;
+ aead_set_sh_desc(authenc);
+
+ return 0;
+}
+
+static int tls_set_sh_desc(struct crypto_aead *aead)
+{
+ struct aead_tfm *tfm = &aead->base.crt_aead;
+ struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ bool keys_fit_inline = false;
+ u32 *key_jump_cmd, *zero_payload_jump_cmd, *skip_zero_jump_cmd;
+ u32 genpad, clrw, jumpback, stidx;
+ u32 *desc;
+ unsigned int blocksize = crypto_aead_blocksize(aead);
+ /* Associated data length is always = 13 for TLS */
+ unsigned int assoclen = 13;
+
+ if (!ctx->enckeylen || !ctx->authsize)
+ return 0;
+
+ /*
+ * TLS 1.0 encrypt shared descriptor
+ * Job Descriptor and Shared Descriptor
+ * must fit into the 64-word Descriptor h/w Buffer
+ */
+ if (DESC_TLS10_ENC_LEN + DESC_JOB_IO_LEN +
+ ctx->split_key_pad_len + ctx->enckeylen <=
+ CAAM_DESC_BYTES_MAX)
+ keys_fit_inline = true;
+
+ desc = ctx->sh_desc_enc;
+
+ stidx = 1 << HDR_START_IDX_SHIFT;
+ init_sh_desc(desc, HDR_SHARE_SERIAL | stidx);
+
+ /* skip key loading if they are loaded due to sharing */
+ key_jump_cmd = append_jump(desc, JUMP_CLASS_BOTH | JUMP_JSL |
+ JUMP_TEST_ALL | JUMP_COND_SHRD |
+ JUMP_COND_SELF);
+ if (keys_fit_inline) {
+ append_key_as_imm(desc, ctx->key, ctx->split_key_pad_len,
+ ctx->split_key_len, CLASS_2 |
+ KEY_DEST_MDHA_SPLIT | KEY_ENC);
+ append_key_as_imm(desc, (void *)ctx->key +
+ ctx->split_key_pad_len, ctx->enckeylen,
+ ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
+ } else {
+ append_key(desc, ctx->key_dma, ctx->split_key_len, CLASS_2 |
+ KEY_DEST_MDHA_SPLIT | KEY_ENC);
+ append_key(desc, ctx->key_dma + ctx->split_key_pad_len,
+ ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
+ }
+ set_jump_tgt_here(desc, key_jump_cmd);
+
+ /* class 2 operation */
+ append_operation(desc, ctx->class2_alg_type |
+ OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
+ /* class 1 operation */
+ append_operation(desc, ctx->class1_alg_type |
+ OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
+
+ /* payloadlen = input data length - (assoclen + ivlen) */
+ append_math_sub_imm_u32(desc, VARSEQINLEN, SEQINLEN, IMM, assoclen +
+ tfm->ivsize);
+
+ /* math1 = payloadlen + icvlen */
+ append_math_add_imm_u32(desc, REG1, VARSEQINLEN, IMM, ctx->authsize);
+
+ /* padlen = block_size - math1 % block_size */
+ append_math_and_imm_u32(desc, REG3, REG1, IMM, blocksize - 1);
+ append_math_sub_imm_u32(desc, REG2, IMM, REG3, blocksize);
+
+ /* cryptlen = payloadlen + icvlen + padlen */
+ append_math_add(desc, VARSEQOUTLEN, REG1, REG2, 4);
+
+ /* store encrypted payload, icv and padding */
+ append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | LDST_VLF);
+
+ /* if payload length is zero, jump to zero-payload commands */
+ append_math_add(desc, NONE, ZERO, VARSEQINLEN, 4);
+ zero_payload_jump_cmd = append_jump(desc, JUMP_TEST_ALL |
+ JUMP_COND_MATH_Z);
+
+ /* read assoc for authentication */
+ append_seq_fifo_load(desc, assoclen, FIFOLD_CLASS_CLASS2 |
+ FIFOLD_TYPE_MSG);
+ /* load iv in context1 */
+ append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_WORD_CLASS_CTX |
+ LDST_CLASS_1_CCB | tfm->ivsize);
+ /* insnoop payload */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_BOTH | FIFOLD_TYPE_MSG |
+ FIFOLD_TYPE_LAST2 | FIFOLDST_VLF);
+ /* jump the zero-payload commands */
+ append_jump(desc, JUMP_TEST_ALL | 3);
+
+ /* zero-payload commands */
+ set_jump_tgt_here(desc, zero_payload_jump_cmd);
+ /* assoc data is the only data for authentication */
+ append_seq_fifo_load(desc, assoclen, FIFOLD_CLASS_CLASS2 |
+ FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST2);
+ /* load iv in context1 */
+ append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_WORD_CLASS_CTX |
+ LDST_CLASS_1_CCB | tfm->ivsize);
+
+ /* send icv to encryption */
+ append_move(desc, MOVE_SRC_CLASS2CTX | MOVE_DEST_CLASS1INFIFO |
+ ctx->authsize);
+
+ /* generate padding and send it to encryption */
+ genpad = NFIFOENTRY_DEST_CLASS1 | NFIFOENTRY_LC1 | NFIFOENTRY_FC1 |
+ NFIFOENTRY_STYPE_PAD | NFIFOENTRY_DTYPE_MSG | NFIFOENTRY_PTYPE_N;
+ append_load_imm_u32(desc, genpad, LDST_CLASS_IND_CCB |
+ LDST_SRCDST_WORD_INFO_FIFO_SZM | LDST_IMM |
+ (2 & LDST_LEN_MASK));
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "tls enc shdesc@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+
+ /*
+ * TLS 1.0 decrypt shared descriptor
+ * Keys do not fit inline, regardless of algorithms used
+ */
+ desc = ctx->sh_desc_dec;
+
+ stidx = 1 << HDR_START_IDX_SHIFT;
+ init_sh_desc(desc, HDR_SHARE_SERIAL | stidx);
+
+ /* skip key loading if they are loaded due to sharing */
+ key_jump_cmd = append_jump(desc, JUMP_CLASS_BOTH | JUMP_JSL |
+ JUMP_TEST_ALL | JUMP_COND_SHRD |
+ JUMP_COND_SELF);
+ append_key(desc, ctx->key_dma, ctx->split_key_len, CLASS_2 |
+ KEY_DEST_MDHA_SPLIT | KEY_ENC);
+ append_key(desc, ctx->key_dma + ctx->split_key_pad_len,
+ ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
+ set_jump_tgt_here(desc, key_jump_cmd);
+
+ /* class 2 operation */
+ append_operation(desc, ctx->class2_alg_type |
+ OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT | OP_ALG_ICV_ON);
+ /* class 1 operation */
+ append_operation(desc, ctx->class1_alg_type |
+ OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT);
+
+ /* VSIL = input data length - 2 * block_size */
+ append_math_sub_imm_u32(desc, VARSEQINLEN, SEQINLEN, IMM, 2 *
+ blocksize);
+
+ /*
+ * payloadlen + icvlen + padlen = input data length - (assoclen +
+ * ivsize)
+ */
+ append_math_sub_imm_u32(desc, REG3, SEQINLEN, IMM, assoclen +
+ tfm->ivsize);
+
+ /* skip data to the last but one cipher block */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_SKIP | LDST_VLF);
+
+ /* load iv for the last cipher block */
+ append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_WORD_CLASS_CTX |
+ LDST_CLASS_1_CCB | tfm->ivsize);
+
+ /* read last cipher block */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_MSG |
+ FIFOLD_TYPE_LAST1 | blocksize);
+
+ /* move decrypted block into math0 and math1 */
+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_OUTFIFO | MOVE_DEST_MATH0 |
+ blocksize);
+
+ /* clear cha1 specific registers */
+ clrw = CLRW_CLR_C1MODE | CLRW_CLR_C1DATAS | CLRW_CLR_C1CTX |
+ CLRW_RESET_CLS1_CHA;
+ append_load_imm_u32(desc, clrw, LDST_CLASS_IND_CCB |
+ LDST_SRCDST_WORD_CLRW | LDST_IMM);
+
+ /* rewind input sequence */
+ append_seq_in_ptr_intlen(desc, 0, 65535, SQIN_RTO);
+
+ /* key1 is in decryption form */
+ append_operation(desc, ctx->class1_alg_type | OP_ALG_AAI_DK |
+ OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT);
+
+ /* read sequence number */
+ append_seq_fifo_load(desc, 8, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG);
+ /* load Type, Version and Len fields in math0 */
+ append_cmd(desc, CMD_SEQ_LOAD | LDST_CLASS_DECO |
+ LDST_SRCDST_WORD_DECO_MATH0 | 5);
+
+ /* load iv in context1 */
+ append_cmd(desc, CMD_SEQ_LOAD | LDST_CLASS_1_CCB |
+ LDST_SRCDST_WORD_CLASS_CTX | tfm->ivsize);
+
+ /* compute (padlen - 1) */
+ append_math_and_imm_u64(desc, REG1, REG1, IMM, 255);
+
+ /* math2 = icvlen + (padlen - 1) + 1 */
+ append_math_add_imm_u32(desc, REG2, REG1, IMM, ctx->authsize + 1);
+
+ append_jump(desc, JUMP_TEST_ALL | JUMP_COND_CALM | 1);
+
+ /* VSOL = payloadlen + icvlen + padlen */
+ append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, 4);
+
+ /* update Len field */
+ append_math_rshift_imm_u64(desc, REG0, REG0, IMM, 24);
+ append_math_sub(desc, REG0, REG0, REG2, 8);
+
+ /* store decrypted payload, icv and padding */
+ append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | LDST_VLF);
+
+ /* VSIL = (payloadlen + icvlen + padlen) - (icvlen + padlen)*/
+ append_math_sub(desc, VARSEQINLEN, REG3, REG2, 4);
+
+ zero_payload_jump_cmd = append_jump(desc, JUMP_TEST_ALL |
+ JUMP_COND_MATH_Z);
+
+ /* send Type, Version and Len(pre ICV) fields to authentication */
+ append_move(desc, MOVE_WAITCOMP |
+ MOVE_SRC_MATH0 | MOVE_DEST_CLASS2INFIFO |
+ (3 << MOVE_OFFSET_SHIFT) | 5);
+
+ /* outsnooping payload */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_BOTH |
+ FIFOLD_TYPE_MSG1OUT2 | FIFOLD_TYPE_LAST2 |
+ FIFOLDST_VLF);
+ skip_zero_jump_cmd = append_jump(desc, JUMP_TEST_ALL | 2);
+
+ set_jump_tgt_here(desc, zero_payload_jump_cmd);
+ /* send Type, Version and Len(pre ICV) fields to authentication */
+ append_move(desc, MOVE_WAITCOMP | MOVE_AUX_LS |
+ MOVE_SRC_MATH0 | MOVE_DEST_CLASS2INFIFO |
+ (3 << MOVE_OFFSET_SHIFT) | 5);
+
+ set_jump_tgt_here(desc, skip_zero_jump_cmd);
+ append_math_add(desc, VARSEQINLEN, ZERO, REG2, 4);
+
+ /* load icvlen and padlen */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_MSG |
+ FIFOLD_TYPE_LAST1 | FIFOLDST_VLF);
+
+ /* VSIL = (payloadlen + icvlen + padlen) - icvlen + padlen */
+ append_math_sub(desc, VARSEQINLEN, REG3, REG2, 4);
+
+ /* move seqoutptr fields into math registers */
+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_DESCBUF | MOVE_DEST_MATH0 |
+ (55 * 4 << MOVE_OFFSET_SHIFT) | 20);
+ /* seqinptr will point to seqoutptr */
+ append_math_and_imm_u32(desc, REG0, REG0, IMM,
+ ~(CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR));
+ /* Load jump command */
+ jumpback = CMD_JUMP | (char)-9;
+ append_load_imm_u32(desc, jumpback, LDST_CLASS_DECO | LDST_IMM |
+ LDST_SRCDST_WORD_DECO_MATH2 |
+ (4 << LDST_OFFSET_SHIFT));
+ /* move updated seqinptr fields to JD */
+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_MATH0 | MOVE_DEST_DESCBUF |
+ (55 * 4 << MOVE_OFFSET_SHIFT) | 24);
+ /* read updated seqinptr */
+ append_jump(desc, JUMP_TEST_ALL | JUMP_COND_CALM | 6);
+
+ /* skip payload */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_SKIP | FIFOLDST_VLF);
+ /* check icv */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_ICV |
+ FIFOLD_TYPE_LAST2 | ctx->authsize);
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "tls dec shdesc@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+
+ return 0;
+}
+
+static int tls_setauthsize(struct crypto_aead *tls, unsigned int authsize)
+{
+ struct caam_ctx *ctx = crypto_aead_ctx(tls);
+
+ ctx->authsize = authsize;
+
+ return 0;
+}
+
+static u32 gen_split_aead_key(struct caam_ctx *ctx, const u8 *key_in,
+ u32 authkeylen)
+{
+ return gen_split_key(ctx->jrdev, ctx->key, ctx->split_key_len,
+ ctx->split_key_pad_len, key_in, authkeylen,
+ ctx->alg_op);
+}
+
+static int aead_setkey(struct crypto_aead *aead,
+ const u8 *key, unsigned int keylen)
+{
+ /* Sizes for MDHA pads (*not* keys): MD5, SHA1, 224, 256, 384, 512 */
+ static const u8 mdpadlen[] = { 16, 20, 32, 32, 64, 64 };
+ struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ struct device *jrdev = ctx->jrdev;
+ struct rtattr *rta = (void *)key;
+ struct crypto_authenc_key_param *param;
+ unsigned int authkeylen;
+ unsigned int enckeylen;
+ int ret = 0;
+
+ param = RTA_DATA(rta);
+ enckeylen = be32_to_cpu(param->enckeylen);
+
+ key += RTA_ALIGN(rta->rta_len);
+ keylen -= RTA_ALIGN(rta->rta_len);
+
+ if (keylen < enckeylen)
+ goto badkey;
+
+ authkeylen = keylen - enckeylen;
+
+ if (keylen > CAAM_MAX_KEY_SIZE)
+ goto badkey;
+
+ /* Pick class 2 key length from algorithm submask */
+ ctx->split_key_len = mdpadlen[(ctx->alg_op & OP_ALG_ALGSEL_SUBMASK) >>
+ OP_ALG_ALGSEL_SHIFT] * 2;
+ ctx->split_key_pad_len = ALIGN(ctx->split_key_len, 16);
+
+#ifdef DEBUG
+ printk(KERN_ERR "keylen %d enckeylen %d authkeylen %d\n",
+ keylen, enckeylen, authkeylen);
+ printk(KERN_ERR "split_key_len %d split_key_pad_len %d\n",
+ ctx->split_key_len, ctx->split_key_pad_len);
+ print_hex_dump(KERN_ERR,
+ "key in @"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1);
+#endif
+
+ ret = gen_split_aead_key(ctx, key, authkeylen);
+ if (ret)
+ goto badkey;
+
+ /* postpend encryption key to auth split key */
+ memcpy(ctx->key + ctx->split_key_pad_len, key + authkeylen, enckeylen);
+
+ ctx->key_dma = dma_map_single(jrdev, ctx->key, ctx->split_key_pad_len +
+ enckeylen, DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->key_dma)) {
+ dev_err(jrdev, "unable to map key i/o memory\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, ctx->key,
+ ctx->split_key_pad_len + enckeylen, 1);
+#endif
+
+ ctx->enckeylen = enckeylen;
+
+ ret = aead_set_sh_desc(aead);
+ if (ret) {
+ dma_unmap_single(jrdev, ctx->key_dma, ctx->split_key_pad_len +
+ enckeylen, DMA_TO_DEVICE);
+ goto badkey;
+ }
+
+ /* 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");
+ goto badkey;
+ }
+ }
+
+ 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");
+ goto badkey;
+ }
+ }
+
+ if (ctx->drv_ctx[GIVENCRYPT]) {
+ ret = caam_drv_ctx_update(ctx->drv_ctx[GIVENCRYPT],
+ ctx->sh_desc_givenc);
+ if (ret) {
+ dev_err(jrdev, "driver givenc context update failed\n");
+ goto badkey;
+ }
+ }
+
+ return ret;
+badkey:
+ crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN);
+ return -EINVAL;
+}
+
+
+static int tls_setkey(struct crypto_aead *aead, const u8 *key,
+ unsigned int keylen)
+{
+ /* Sizes for MDHA pads (*not* keys): MD5, SHA1, 224, 256, 384, 512 */
+ static const u8 mdpadlen[] = { 16, 20, 32, 32, 64, 64 };
+ struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ struct device *jrdev = ctx->jrdev;
+ struct rtattr *rta = (void *)key;
+ struct crypto_authenc_key_param *param;
+ unsigned int authkeylen;
+ unsigned int enckeylen;
+ int ret = 0;
+
+ param = RTA_DATA(rta);
+ enckeylen = be32_to_cpu(param->enckeylen);
+
+ key += RTA_ALIGN(rta->rta_len);
+ keylen -= RTA_ALIGN(rta->rta_len);
+
+ if (keylen < enckeylen)
+ goto badkey;
+
+ authkeylen = keylen - enckeylen;
+
+ if (keylen > CAAM_MAX_KEY_SIZE)
+ goto badkey;
+
+ /* Pick class 2 key length from algorithm submask */
+ ctx->split_key_len = mdpadlen[(ctx->alg_op & OP_ALG_ALGSEL_SUBMASK) >>
+ OP_ALG_ALGSEL_SHIFT] * 2;
+ ctx->split_key_pad_len = ALIGN(ctx->split_key_len, 16);
+
+#ifdef DEBUG
+ dev_err(jrdev, "keylen %d enckeylen %d authkeylen %d\n", keylen,
+ enckeylen, authkeylen);
+ dev_err(jrdev, "split_key_len %d split_key_pad_len %d\n",
+ ctx->split_key_len, ctx->split_key_pad_len);
+ print_hex_dump(KERN_ERR, "key in @"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1);
+#endif
+
+ ret = gen_split_aead_key(ctx, key, authkeylen);
+ if (ret)
+ goto badkey;
+
+ /* postpend encryption key to auth split key */
+ memcpy(ctx->key + ctx->split_key_pad_len, key + authkeylen, enckeylen);
+
+ ctx->key_dma = dma_map_single(jrdev, ctx->key, ctx->split_key_pad_len +
+ enckeylen, DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->key_dma)) {
+ dev_err(jrdev, "unable to map key i/o memory\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, ctx->key,
+ ctx->split_key_pad_len + enckeylen, 1);
+#endif
+
+ ctx->enckeylen = enckeylen;
+
+ ret = tls_set_sh_desc(aead);
+ if (ret) {
+ dma_unmap_single(jrdev, ctx->key_dma, ctx->split_key_pad_len +
+ enckeylen, DMA_TO_DEVICE);
+ }
+
+ /* 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");
+ goto badkey;
+ }
+ }
+
+ 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");
+ goto badkey;
+ }
+ }
+
+ if (ctx->drv_ctx[GIVENCRYPT]) {
+ ret = caam_drv_ctx_update(ctx->drv_ctx[GIVENCRYPT],
+ ctx->sh_desc_givenc);
+ if (ret) {
+ dev_err(jrdev, "driver givenc context update failed\n");
+ goto badkey;
+ }
+ }
+
+ return ret;
+badkey:
+ crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN);
+ return -EINVAL;
+}
+
+/*
+ * aead_edesc - s/w-extended aead descriptor
+ * @assoc_nents: number of segments in associated data (SPI+Seq) scatterlist
+ * @assoc_chained: if source is chained
+ * @src_nents: number of segments in input scatterlist
+ * @src_chained: if source is chained
+ * @dst_nents: number of segments in output scatterlist
+ * @dst_chained: if destination is chained
+ * @iv_dma: dma address of iv for checking continuity and link table
+ * @desc: h/w descriptor (variable length; must not exceed MAX_CAAM_DESCSIZE)
+ * @qm_sg_bytes: length of dma mapped sec4_sg space
+ * @qm_sg_dma: bus physical mapped address of h/w link table
+ * @hw_desc: the h/w job descriptor followed by any referenced link tables
+ */
+struct aead_edesc {
+ int assoc_nents;
+ bool assoc_chained;
+ int src_nents;
+ bool src_chained;
+ int dst_nents;
+ bool dst_chained;
+ dma_addr_t iv_dma;
+ int qm_sg_bytes;
+ dma_addr_t qm_sg_dma;
+ struct caam_drv_req drv_req;
+ struct qm_sg_entry sgt[0];
+};
+
+
+static void caam_unmap(struct device *dev, struct scatterlist *src,
+ struct scatterlist *dst, int src_nents,
+ bool src_chained, int dst_nents, bool dst_chained,
+ dma_addr_t iv_dma, int ivsize, dma_addr_t qm_sg_dma,
+ int qm_sg_bytes)
+{
+ if (dst != src) {
+ dma_unmap_sg_chained(dev, src, src_nents ? : 1, DMA_TO_DEVICE,
+ src_chained);
+ dma_unmap_sg_chained(dev, dst, dst_nents ? : 1, DMA_FROM_DEVICE,
+ dst_chained);
+ } else {
+ dma_unmap_sg_chained(dev, src, src_nents ? : 1,
+ DMA_BIDIRECTIONAL, src_chained);
+ }
+
+ if (iv_dma)
+ dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
+ if (qm_sg_bytes)
+ dma_unmap_single(dev, qm_sg_dma, qm_sg_bytes, DMA_BIDIRECTIONAL);
+}
+
+static void aead_unmap(struct device *dev,
+ struct aead_edesc *edesc,
+ struct aead_request *req)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ int ivsize = crypto_aead_ivsize(aead);
+
+ dma_unmap_sg_chained(dev, req->assoc, edesc->assoc_nents,
+ DMA_BIDIRECTIONAL, edesc->assoc_chained);
+
+ caam_unmap(dev, req->src, req->dst,
+ edesc->src_nents, edesc->src_chained, edesc->dst_nents,
+ edesc->dst_chained, edesc->iv_dma, ivsize,
+ edesc->qm_sg_dma, edesc->qm_sg_bytes);
+}
+
+static inline void aead_done(struct caam_drv_req *drv_req, u32 status)
+{
+ struct device *qidev;
+ struct aead_edesc *edesc;
+ struct aead_request *aead_req = drv_req->app_ctx;
+ struct crypto_aead *aead = crypto_aead_reqtfm(aead_req);
+ struct caam_ctx *caam_ctx = crypto_aead_ctx(aead);
+ int ecode = 0;
+
+ qidev = caam_ctx->qidev;
+
+ if (status) {
+ char tmp[CAAM_ERROR_STR_MAX];
+ dev_err(qidev, "Rsp status: %#x: %s\n",
+ status, caam_jr_strstatus(tmp, status));
+ ecode = -EIO;
+ }
+
+ edesc = container_of(drv_req, struct aead_edesc, drv_req);
+ aead_unmap(qidev, edesc, aead_req);
+
+ aead_request_complete(aead_req, ecode);
+ kfree(edesc);
+}
+
+/* For now, identical to aead_done */
+static inline void tls_encrypt_done(struct caam_drv_req *drv_req, u32 status)
+{
+ struct device *qidev;
+ struct aead_edesc *edesc;
+ struct aead_request *aead_req = drv_req->app_ctx;
+ struct crypto_aead *aead = crypto_aead_reqtfm(aead_req);
+ struct caam_ctx *caam_ctx = crypto_aead_ctx(aead);
+ int ecode = 0;
+
+ qidev = caam_ctx->qidev;
+
+ if (status) {
+ char tmp[CAAM_ERROR_STR_MAX];
+ dev_err(qidev, "Rsp status: %#x: %s\n",
+ status, caam_jr_strstatus(tmp, status));
+ ecode = -EIO;
+ }
+
+ edesc = container_of(drv_req, struct aead_edesc, drv_req);
+ aead_unmap(qidev, edesc, aead_req);
+
+ aead_request_complete(aead_req, ecode);
+ kfree(edesc);
+}
+
+static inline void tls_decrypt_done(struct caam_drv_req *drv_req, u32 status)
+{
+ struct device *qidev;
+ struct aead_edesc *edesc;
+ struct aead_request *aead_req = drv_req->app_ctx;
+ struct crypto_aead *aead = crypto_aead_reqtfm(aead_req);
+ struct caam_ctx *caam_ctx = crypto_aead_ctx(aead);
+ int ecode = 0;
+ int cryptlen = aead_req->cryptlen;
+ u8 padsize;
+ u8 padding[255]; /* padding can be 0-255 bytes */
+ int i;
+
+ qidev = caam_ctx->qidev;
+
+ if (status) {
+ char tmp[CAAM_ERROR_STR_MAX];
+ dev_err(qidev, "Rsp status: %#x: %s\n",
+ status, caam_jr_strstatus(tmp, status));
+ ecode = -EIO;
+ }
+
+ edesc = container_of(drv_req, struct aead_edesc, drv_req);
+ aead_unmap(qidev, edesc, aead_req);
+
+ /*
+ * verify hw auth check passed else return -EBADMSG
+ */
+ if ((status & JRSTA_CCBERR_ERRID_MASK) == JRSTA_CCBERR_ERRID_ICVCHK) {
+ ecode = -EBADMSG;
+ goto out;
+ }
+
+ /* Padding checking */
+ cryptlen -= 1;
+ scatterwalk_map_and_copy(&padsize, aead_req->dst, cryptlen, 1, 0);
+ if (padsize > cryptlen) {
+ ecode = -EBADMSG;
+ goto out;
+ }
+ cryptlen -= padsize;
+ scatterwalk_map_and_copy(padding, aead_req->dst, cryptlen, padsize, 0);
+ /* the padding content must be equal with padsize */
+ for (i = 0; i < padsize; i++)
+ if (padding[i] != padsize) {
+ ecode = -EBADMSG;
+ break;
+ }
+
+out:
+ aead_request_complete(aead_req, ecode);
+ kfree(edesc);
+}
+
+/*
+ * allocate and map the aead extended descriptor
+ */
+static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
+ bool *all_contig_ptr, bool encrypt,
+ bool strip_icv)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ struct device *qidev = ctx->qidev;
+ gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
+ CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
+ int assoc_nents, src_nents, dst_nents = 0;
+ struct aead_edesc *edesc;
+ dma_addr_t iv_dma = 0, qm_sg_dma;
+ int sgc;
+ bool all_contig = true;
+ bool assoc_chained = false, src_chained = false, dst_chained = false;
+ int ivsize = crypto_aead_ivsize(aead);
+ unsigned int authsize = ctx->authsize;
+
+ int qm_sg_index, qm_sg_ents = 0, qm_sg_bytes;
+ struct qm_sg_entry *sg_table, *fd_sgt;
+ struct caam_drv_req *drv_req;
+
+ assoc_nents = sg_count(req->assoc, req->assoclen, &assoc_chained);
+
+ if (unlikely(req->dst != req->src)) {
+ int extralen;
+
+ src_nents = sg_count(req->src, req->cryptlen, &src_chained);
+
+ if (encrypt)
+ extralen = authsize;
+ else
+ extralen = strip_icv ? (-authsize) : 0;
+ dst_nents = sg_count(req->dst, req->cryptlen + extralen,
+ &dst_chained);
+ } else {
+ src_nents = sg_count(req->src,
+ req->cryptlen +
+ (encrypt ? authsize : 0),
+ &src_chained);
+ }
+
+ sgc = dma_map_sg_chained(qidev, req->assoc, assoc_nents ? : 1,
+ DMA_TO_DEVICE, assoc_chained);
+ if (likely(req->src == req->dst)) {
+ sgc = dma_map_sg_chained(qidev, req->src, src_nents ? : 1,
+ DMA_BIDIRECTIONAL, src_chained);
+ } else {
+ sgc = dma_map_sg_chained(qidev, req->src, src_nents ? : 1,
+ DMA_TO_DEVICE, src_chained);
+ sgc = dma_map_sg_chained(qidev, req->dst, dst_nents ? : 1,
+ DMA_FROM_DEVICE, dst_chained);
+ }
+
+ /* Check if data are contiguous */
+ iv_dma = dma_map_single(qidev, req->iv, ivsize, DMA_TO_DEVICE);
+ if (assoc_nents ||
+ sg_dma_address(req->assoc) + req->assoclen != iv_dma ||
+ src_nents || iv_dma + ivsize != sg_dma_address(req->src)) {
+ all_contig = false;
+ assoc_nents = assoc_nents ? : 1;
+ src_nents = src_nents ? : 1;
+ qm_sg_ents = assoc_nents + 1 + src_nents;
+ }
+
+ qm_sg_ents += dst_nents;
+ qm_sg_bytes = qm_sg_ents * sizeof(struct qm_sg_entry);
+
+ /* allocate space for base edesc and hw desc commands, link tables */
+ edesc = kmalloc(sizeof(struct aead_edesc) + qm_sg_bytes,
+ GFP_DMA | flags);
+ if (!edesc) {
+ dev_err(qidev, "could not allocate extended descriptor\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ qm_sg_index = 0;
+ drv_req = &edesc->drv_req;
+ sg_table = &edesc->sgt[0];
+ fd_sgt = &drv_req->fd_sgt[0];
+
+ qm_sg_dma = dma_map_single(qidev, sg_table,
+ qm_sg_bytes, DMA_BIDIRECTIONAL);
+
+ edesc->assoc_nents = assoc_nents;
+ edesc->assoc_chained = assoc_chained;
+ edesc->src_nents = src_nents;
+ edesc->src_chained = src_chained;
+ edesc->dst_nents = dst_nents;
+ edesc->dst_chained = dst_chained;
+ edesc->iv_dma = iv_dma;
+ edesc->qm_sg_dma = qm_sg_dma;
+ edesc->qm_sg_bytes = qm_sg_bytes;
+
+ *all_contig_ptr = all_contig;
+
+ fd_sgt[0].final = 0;
+ fd_sgt[0].__reserved2 = 0;
+ fd_sgt[0].bpid = 0;
+ fd_sgt[0].__reserved3 = 0;
+ fd_sgt[0].offset = 0;
+
+ fd_sgt[1].final = 1;
+ fd_sgt[1].__reserved2 = 0;
+ fd_sgt[1].bpid = 0;
+ fd_sgt[1].__reserved3 = 0;
+ fd_sgt[1].offset = 0;
+
+ if (!all_contig) {
+ fd_sgt[1].extension = 1;
+ fd_sgt[1].addr = qm_sg_dma;
+
+ sg_to_qm_sg(req->assoc, (assoc_nents ? : 1), sg_table, 0);
+ qm_sg_index += assoc_nents ? : 1;
+
+ dma_to_qm_sg_one(sg_table + qm_sg_index, iv_dma, ivsize, 0);
+ qm_sg_index += 1;
+
+ sg_to_qm_sg_last(req->src, (src_nents ? : 1),
+ sg_table + qm_sg_index, 0);
+ qm_sg_index += src_nents ? : 1;
+
+ } else {
+ fd_sgt[1].extension = 0;
+ fd_sgt[1].addr = sg_dma_address(req->assoc);
+ }
+
+ if (dst_nents)
+ sg_to_qm_sg_last(req->dst, dst_nents,
+ sg_table + qm_sg_index, 0);
+
+ if (req->dst == req->src) {
+ if (src_nents <= 1) {
+ fd_sgt[0].addr = sg_dma_address(req->src);
+ fd_sgt[0].extension = 0;
+ } else {
+ fd_sgt[0].extension = 1;
+ fd_sgt[0].addr = fd_sgt[1].addr +
+ sizeof(struct qm_sg_entry) *
+ ((edesc->assoc_nents ? : 1) + 1);
+ }
+ } else {
+ if (!dst_nents) {
+ fd_sgt[0].addr = sg_dma_address(req->dst);
+ fd_sgt[0].extension = 0;
+ } else {
+ fd_sgt[0].addr = qm_sg_dma +
+ (sizeof(struct qm_sg_entry) * qm_sg_index);
+ fd_sgt[0].extension = 1;
+ }
+ }
+
+ return edesc;
+}
+
+static struct caam_drv_ctx *get_drv_ctx(struct caam_ctx *ctx,
+ enum optype type)
+{
+ struct caam_drv_ctx *drv_ctx = ctx->drv_ctx[type];
+ u32 *desc;
+
+ if (unlikely(!drv_ctx)) {
+ spin_lock(&ctx->lock);
+
+ /* Read again to check if some other core init drv_ctx */
+ drv_ctx = ctx->drv_ctx[type];
+ if (!drv_ctx) {
+ int cpu;
+
+ if (ENCRYPT == type)
+ desc = ctx->sh_desc_enc;
+ else if (DECRYPT == type)
+ desc = ctx->sh_desc_dec;
+ else if (GIVENCRYPT == type)
+ desc = ctx->sh_desc_givenc;
+ else
+ return ERR_PTR(-EINVAL);
+
+ cpu = smp_processor_id();
+ drv_ctx = caam_drv_ctx_init(ctx->qidev, &cpu, desc);
+
+ ctx->drv_ctx[type] = drv_ctx;
+ }
+
+ spin_unlock(&ctx->lock);
+ }
+
+ return drv_ctx;
+}
+
+static int aead_encrypt(struct aead_request *req)
+{
+ struct aead_edesc *edesc;
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ int ivsize = crypto_aead_ivsize(aead);
+ struct device *qidev = ctx->qidev;
+ struct caam_drv_ctx *drv_ctx;
+ struct caam_drv_req *drv_req;
+ bool all_contig;
+ int ret;
+
+ drv_ctx = get_drv_ctx(ctx, ENCRYPT);
+ if (unlikely(IS_ERR_OR_NULL(drv_ctx)))
+ return PTR_ERR(drv_ctx);
+
+ if (unlikely(caam_drv_ctx_busy(drv_ctx)))
+ return -EAGAIN;
+
+ /* allocate extended descriptor */
+ edesc = aead_edesc_alloc(req, &all_contig, true, true);
+ if (IS_ERR(edesc))
+ return PTR_ERR(edesc);
+
+ /* Create and submit job descriptor */
+ drv_req = &edesc->drv_req;
+ drv_req->app_ctx = req;
+ drv_req->cbk = aead_done;
+ drv_req->fd_sgt[0].length = req->cryptlen + ctx->authsize;
+ drv_req->fd_sgt[1].length = req->assoclen + ivsize + req->cryptlen;
+
+ drv_req->drv_ctx = drv_ctx;
+ ret = caam_qi_enqueue(qidev, drv_req);
+ if (!ret) {
+ ret = -EINPROGRESS;
+ } else {
+ aead_unmap(qidev, edesc, req);
+ kfree(edesc);
+ }
+
+ return ret;
+}
+
+static int aead_decrypt(struct aead_request *req)
+{
+ struct aead_edesc *edesc;
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ int ivsize = crypto_aead_ivsize(aead);
+ struct device *qidev = ctx->qidev;
+ struct caam_drv_ctx *drv_ctx;
+ struct caam_drv_req *drv_req;
+ bool all_contig;
+ int ret = 0;
+
+ drv_ctx = get_drv_ctx(ctx, DECRYPT);
+ if (unlikely(IS_ERR_OR_NULL(drv_ctx)))
+ return PTR_ERR(drv_ctx);
+
+ if (unlikely(caam_drv_ctx_busy(drv_ctx)))
+ return -EAGAIN;
+
+ /* allocate extended descriptor */
+ edesc = aead_edesc_alloc(req, &all_contig, false, true);
+ if (IS_ERR(edesc))
+ return PTR_ERR(edesc);
+
+ /* Create and submit job descriptor */
+ drv_req = &edesc->drv_req;
+ drv_req->app_ctx = req;
+ drv_req->cbk = aead_done;
+ drv_req->fd_sgt[0].length = req->cryptlen - ctx->authsize;
+ drv_req->fd_sgt[1].length = req->assoclen + ivsize + req->cryptlen;
+
+ drv_req->drv_ctx = drv_ctx;
+ ret = caam_qi_enqueue(qidev, drv_req);
+ if (!ret) {
+ ret = -EINPROGRESS;
+ } else {
+ aead_unmap(qidev, edesc, req);
+ kfree(edesc);
+ }
+
+ return ret;
+}
+
+static int tls_encrypt(struct aead_request *req)
+{
+ struct aead_edesc *edesc;
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ int ivsize = crypto_aead_ivsize(aead);
+ struct device *qidev = ctx->qidev;
+ struct caam_drv_ctx *drv_ctx;
+ struct caam_drv_req *drv_req;
+ bool all_contig;
+ int ret;
+ unsigned int blocksize = crypto_aead_blocksize(aead);
+ unsigned int padsize;
+
+ drv_ctx = get_drv_ctx(ctx, ENCRYPT);
+ if (unlikely(IS_ERR_OR_NULL(drv_ctx)))
+ return PTR_ERR(drv_ctx);
+
+ if (unlikely(caam_drv_ctx_busy(drv_ctx)))
+ return -EAGAIN;
+
+ padsize = blocksize - ((req->cryptlen + ctx->authsize) % blocksize);
+
+ /*
+ * allocate extended tls descriptor
+ * TLS 1.0 has no explicit IV in the packet, but it is needed as input
+ * since it is used by CBC.
+ * ctx->authsize is temporary set to include also padlen
+ */
+ ctx->authsize += padsize;
+ edesc = aead_edesc_alloc(req, &all_contig, true, true);
+ if (IS_ERR(edesc))
+ return PTR_ERR(edesc);
+ ctx->authsize -= padsize;
+
+ /* Create and submit job descriptor */
+ drv_req = &edesc->drv_req;
+ drv_req->app_ctx = req;
+ drv_req->cbk = tls_encrypt_done;
+ drv_req->fd_sgt[0].length = req->cryptlen + padsize + ctx->authsize;
+ drv_req->fd_sgt[1].length = req->assoclen + ivsize + req->cryptlen;
+
+ drv_req->drv_ctx = drv_ctx;
+ ret = caam_qi_enqueue(qidev, drv_req);
+ if (!ret) {
+ ret = -EINPROGRESS;
+ } else {
+ aead_unmap(qidev, edesc, req);
+ kfree(edesc);
+ }
+
+ return ret;
+}
+
+static int tls_decrypt(struct aead_request *req)
+{
+ struct aead_edesc *edesc;
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ int ivsize = crypto_aead_ivsize(aead);
+ struct device *qidev = ctx->qidev;
+ struct caam_drv_ctx *drv_ctx;
+ struct caam_drv_req *drv_req;
+ bool all_contig;
+ int ret = 0;
+
+ drv_ctx = get_drv_ctx(ctx, DECRYPT);
+ if (unlikely(IS_ERR_OR_NULL(drv_ctx)))
+ return PTR_ERR(drv_ctx);
+
+ if (unlikely(caam_drv_ctx_busy(drv_ctx)))
+ return -EAGAIN;
+
+ /*
+ * allocate extended descriptor
+ * TLS 1.0 has no explicit IV in the packet, but it is needed as input
+ * since it is used by CBC.
+ * Assumption: since padding and ICV are not stripped (upper layer
+ * checks padding), req->dst has to be big enough to hold payloadlen +
+ * padlen + icvlen.
+ */
+ edesc = aead_edesc_alloc(req, &all_contig, false, false);
+ if (IS_ERR(edesc))
+ return PTR_ERR(edesc);
+
+ /* Create and submit job descriptor */
+ drv_req = &edesc->drv_req;
+ drv_req->app_ctx = req;
+ drv_req->cbk = tls_decrypt_done;
+ /*
+ * For decrypt, do not strip ICV, Padding, Padding length since
+ * upper layer(s) perform padding checking.
+ */
+ drv_req->fd_sgt[0].length = req->cryptlen;
+ drv_req->fd_sgt[1].length = req->assoclen + ivsize + req->cryptlen;
+
+ drv_req->drv_ctx = drv_ctx;
+ ret = caam_qi_enqueue(qidev, drv_req);
+ if (!ret) {
+ ret = -EINPROGRESS;
+ } else {
+ aead_unmap(qidev, edesc, req);
+ kfree(edesc);
+ }
+
+ return ret;
+}
+
+/*
+ * allocate and map the aead extended descriptor for aead givencrypt
+ */
+static struct aead_edesc *aead_giv_edesc_alloc(struct aead_givcrypt_request
+ *greq, u32 *contig_ptr)
+{
+ struct aead_request *req = &greq->areq;
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ struct device *qidev = ctx->qidev;
+ gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
+ CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
+ int assoc_nents, src_nents, dst_nents = 0;
+ struct aead_edesc *edesc;
+ dma_addr_t iv_dma = 0, qm_sg_dma;
+ int sgc;
+ u32 contig = GIV_SRC_CONTIG | GIV_DST_CONTIG;
+ int ivsize = crypto_aead_ivsize(aead);
+ bool assoc_chained = false, src_chained = false, dst_chained = false;
+
+ int qm_sg_index, qm_sg_ents = 0, qm_sg_bytes;
+ struct qm_sg_entry *sg_table, *fd_sgt;
+ struct caam_drv_req *drv_req;
+
+ assoc_nents = sg_count(req->assoc, req->assoclen, &assoc_chained);
+ src_nents = sg_count(req->src, req->cryptlen, &src_chained);
+
+ if (unlikely(req->dst != req->src))
+ dst_nents = sg_count(req->dst, req->cryptlen + ctx->authsize,
+ &dst_chained);
+
+ sgc = dma_map_sg_chained(qidev, req->assoc, assoc_nents ? : 1,
+ DMA_TO_DEVICE, assoc_chained);
+ if (likely(req->src == req->dst)) {
+ sgc = dma_map_sg_chained(qidev, req->src, src_nents ? : 1,
+ DMA_BIDIRECTIONAL, src_chained);
+ } else {
+ sgc = dma_map_sg_chained(qidev, req->src, src_nents ? : 1,
+ DMA_TO_DEVICE, src_chained);
+ sgc = dma_map_sg_chained(qidev, req->dst, dst_nents ? : 1,
+ DMA_FROM_DEVICE, dst_chained);
+ }
+
+ /* Check if data are contiguous */
+ iv_dma = dma_map_single(qidev, greq->giv, ivsize, DMA_TO_DEVICE);
+
+ if (assoc_nents ||
+ sg_dma_address(req->assoc) + req->assoclen != iv_dma ||
+ src_nents || iv_dma + ivsize != sg_dma_address(req->src))
+ contig &= ~GIV_SRC_CONTIG;
+
+ if (dst_nents || iv_dma + ivsize != sg_dma_address(req->dst))
+ contig &= ~GIV_DST_CONTIG;
+
+ if (unlikely(req->src != req->dst)) {
+ dst_nents = dst_nents ? : 1;
+ qm_sg_ents += 1;
+ }
+
+ if (!(contig & GIV_SRC_CONTIG)) {
+ assoc_nents = assoc_nents ? : 1;
+ src_nents = src_nents ? : 1;
+ qm_sg_ents += assoc_nents + 1 + src_nents;
+ if (likely(req->src == req->dst))
+ contig &= ~GIV_DST_CONTIG;
+ }
+
+ qm_sg_ents += dst_nents;
+
+ qm_sg_bytes = qm_sg_ents * sizeof(struct qm_sg_entry);
+
+ /* allocate space for base edesc and hw desc commands, link tables */
+ edesc = kmalloc(sizeof(struct aead_edesc) + qm_sg_bytes,
+ GFP_DMA | flags);
+ if (!edesc) {
+ dev_err(qidev, "could not allocate extended descriptor\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ drv_req = &edesc->drv_req;
+ sg_table = &edesc->sgt[0];
+ fd_sgt = &drv_req->fd_sgt[0];
+
+ qm_sg_dma = dma_map_single(qidev, sg_table,
+ qm_sg_bytes, DMA_BIDIRECTIONAL);
+
+ edesc->assoc_nents = assoc_nents;
+ edesc->assoc_chained = assoc_chained;
+ edesc->src_nents = src_nents;
+ edesc->src_chained = src_chained;
+ edesc->dst_nents = dst_nents;
+ edesc->dst_chained = dst_chained;
+ edesc->iv_dma = iv_dma;
+ edesc->qm_sg_bytes = qm_sg_bytes;
+ edesc->qm_sg_dma = qm_sg_dma;
+
+ *contig_ptr = contig;
+
+ memset(&fd_sgt[0], 0, 2 * sizeof(fd_sgt[0]));
+ fd_sgt[1].final = 1;
+
+ qm_sg_index = 0;
+ if (unlikely(!(contig & GIV_SRC_CONTIG))) {
+ fd_sgt[1].extension = 1;
+ fd_sgt[1].addr = qm_sg_dma;
+
+ sg_to_qm_sg(req->assoc, assoc_nents,
+ sg_table + qm_sg_index, 0);
+
+ qm_sg_index += assoc_nents;
+
+ dma_to_qm_sg_one(sg_table + qm_sg_index,
+ iv_dma, ivsize, 0);
+
+ qm_sg_index += 1;
+
+ sg_to_qm_sg_last(req->src, src_nents,
+ sg_table + qm_sg_index, 0);
+
+ qm_sg_index += src_nents;
+ } else {
+ fd_sgt[1].addr = sg_dma_address(req->assoc);
+ }
+
+ if (unlikely(req->src != req->dst && !(contig & GIV_DST_CONTIG))) {
+ fd_sgt[0].addr = qm_sg_dma +
+ (sizeof(struct qm_sg_entry) * qm_sg_index);
+ fd_sgt[0].extension = 1;
+
+ dma_to_qm_sg_one(sg_table + qm_sg_index, iv_dma, ivsize, 0);
+ qm_sg_index += 1;
+ sg_to_qm_sg_last(req->dst, dst_nents,
+ sg_table + qm_sg_index, 0);
+ } else {
+ if (req->src == req->dst && !(contig & GIV_DST_CONTIG)) {
+ fd_sgt[0].extension = 1;
+ fd_sgt[0].addr = edesc->qm_sg_dma +
+ sizeof(struct qm_sg_entry) *
+ edesc->assoc_nents;
+ } else {
+ fd_sgt[0].addr = edesc->iv_dma;
+ }
+ }
+
+ return edesc;
+}
+
+static int aead_givencrypt(struct aead_givcrypt_request *areq)
+{
+ struct aead_request *req = &areq->areq;
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct caam_ctx *ctx = crypto_aead_ctx(aead);
+ struct device *qidev = ctx->qidev;
+ struct caam_drv_ctx *drv_ctx;
+ struct caam_drv_req *drv_req;
+ int ivsize = crypto_aead_ivsize(aead);
+ struct aead_edesc *edesc;
+ u32 contig;
+ int ret;
+
+ drv_ctx = get_drv_ctx(ctx, GIVENCRYPT);
+ if (unlikely(IS_ERR_OR_NULL(drv_ctx)))
+ return PTR_ERR(drv_ctx);
+
+ if (unlikely(caam_drv_ctx_busy(drv_ctx)))
+ return -EAGAIN;
+
+ /* allocate extended descriptor */
+ edesc = aead_giv_edesc_alloc(areq, &contig);
+ if (IS_ERR(edesc))
+ return PTR_ERR(edesc);
+
+ drv_req = &edesc->drv_req;
+ drv_req->app_ctx = req;
+ drv_req->cbk = aead_done;
+ drv_req->fd_sgt[0].length = ivsize + req->cryptlen + ctx->authsize;
+ drv_req->fd_sgt[1].length = req->assoclen + ivsize + req->cryptlen;
+
+ drv_req->drv_ctx = drv_ctx;
+ ret = caam_qi_enqueue(qidev, drv_req);
+ if (!ret) {
+ ret = -EINPROGRESS;
+ } else {
+ aead_unmap(qidev, edesc, req);
+ kfree(edesc);
+ }
+
+ return ret;
+}
+
+#define template_aead template_u.aead
+#define template_ablkcipher template_u.ablkcipher
+struct caam_alg_template {
+ char name[CRYPTO_MAX_ALG_NAME];
+ char driver_name[CRYPTO_MAX_ALG_NAME];
+ unsigned int blocksize;
+ u32 type;
+ union {
+ struct ablkcipher_alg ablkcipher;
+ struct aead_alg aead;
+ struct blkcipher_alg blkcipher;
+ struct cipher_alg cipher;
+ struct compress_alg compress;
+ struct rng_alg rng;
+ } template_u;
+ u32 class1_alg_type;
+ u32 class2_alg_type;
+ u32 alg_op;
+ int min_era;
+};
+
+static struct caam_alg_template driver_algs[] = {
+ /* single-pass ipsec_esp descriptor */
+ {
+ .name = "authenc(hmac(md5),cbc(aes))",
+ .driver_name = "authenc-hmac-md5-cbc-aes-caam-qi",
+ .blocksize = AES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = MD5_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
+ },
+ {
+ .name = "authenc(hmac(sha1),cbc(aes))",
+ .driver_name = "authenc-hmac-sha1-cbc-aes-caam-qi",
+ .blocksize = AES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = SHA1_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
+ },
+ {
+ .name = "authenc(hmac(sha224),cbc(aes))",
+ .driver_name = "authenc-hmac-sha224-cbc-aes-caam-qi",
+ .blocksize = AES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = SHA224_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA224 |
+ OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
+ },
+ {
+ .name = "authenc(hmac(sha256),cbc(aes))",
+ .driver_name = "authenc-hmac-sha256-cbc-aes-caam-qi",
+ .blocksize = AES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = SHA256_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA256 |
+ OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
+ },
+ {
+ .name = "authenc(hmac(sha384),cbc(aes))",
+ .driver_name = "authenc-hmac-sha384-cbc-aes-caam-qi",
+ .blocksize = AES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = SHA384_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA384 |
+ OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
+ },
+
+ {
+ .name = "authenc(hmac(sha512),cbc(aes))",
+ .driver_name = "authenc-hmac-sha512-cbc-aes-caam-qi",
+ .blocksize = AES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = SHA512_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA512 |
+ OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
+ },
+ {
+ .name = "authenc(hmac(md5),cbc(des3_ede))",
+ .driver_name = "authenc-hmac-md5-cbc-des3_ede-caam-qi",
+ .blocksize = DES3_EDE_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .maxauthsize = MD5_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
+ },
+ {
+ .name = "authenc(hmac(sha1),cbc(des3_ede))",
+ .driver_name = "authenc-hmac-sha1-cbc-des3_ede-caam-qi",
+ .blocksize = DES3_EDE_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .maxauthsize = SHA1_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
+ },
+ {
+ .name = "authenc(hmac(sha224),cbc(des3_ede))",
+ .driver_name = "authenc-hmac-sha224-cbc-des3_ede-caam-qi",
+ .blocksize = DES3_EDE_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .maxauthsize = SHA224_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA224 |
+ OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
+ },
+ {
+ .name = "authenc(hmac(sha256),cbc(des3_ede))",
+ .driver_name = "authenc-hmac-sha256-cbc-des3_ede-caam-qi",
+ .blocksize = DES3_EDE_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .maxauthsize = SHA256_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA256 |
+ OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
+ },
+ {
+ .name = "authenc(hmac(sha384),cbc(des3_ede))",
+ .driver_name = "authenc-hmac-sha384-cbc-des3_ede-caam-qi",
+ .blocksize = DES3_EDE_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .maxauthsize = SHA384_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA384 |
+ OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
+ },
+ {
+ .name = "authenc(hmac(sha512),cbc(des3_ede))",
+ .driver_name = "authenc-hmac-sha512-cbc-des3_ede-caam-qi",
+ .blocksize = DES3_EDE_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .maxauthsize = SHA512_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA512 |
+ OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
+ },
+ {
+ .name = "authenc(hmac(md5),cbc(des))",
+ .driver_name = "authenc-hmac-md5-cbc-des-caam-qi",
+ .blocksize = DES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES_BLOCK_SIZE,
+ .maxauthsize = MD5_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
+ },
+ {
+ .name = "authenc(hmac(sha1),cbc(des))",
+ .driver_name = "authenc-hmac-sha1-cbc-des-caam-qi",
+ .blocksize = DES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES_BLOCK_SIZE,
+ .maxauthsize = SHA1_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
+ },
+ {
+ .name = "authenc(hmac(sha224),cbc(des))",
+ .driver_name = "authenc-hmac-sha224-cbc-des-caam-qi",
+ .blocksize = DES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES_BLOCK_SIZE,
+ .maxauthsize = SHA224_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA224 |
+ OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
+ },
+ {
+ .name = "authenc(hmac(sha256),cbc(des))",
+ .driver_name = "authenc-hmac-sha256-cbc-des-caam-qi",
+ .blocksize = DES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES_BLOCK_SIZE,
+ .maxauthsize = SHA256_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA256 |
+ OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
+ },
+ {
+ .name = "authenc(hmac(sha384),cbc(des))",
+ .driver_name = "authenc-hmac-sha384-cbc-des-caam-qi",
+ .blocksize = DES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES_BLOCK_SIZE,
+ .maxauthsize = SHA384_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA384 |
+ OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
+ },
+ {
+ .name = "authenc(hmac(sha512),cbc(des))",
+ .driver_name = "authenc-hmac-sha512-cbc-des-caam-qi",
+ .blocksize = DES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES_BLOCK_SIZE,
+ .maxauthsize = SHA512_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA512 |
+ OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
+ .min_era = 2,
+ },
+ /* TLS record descriptors */
+ {
+ .name = "tls10(hmac(sha1),cbc(aes))",
+ .driver_name = "tls10-hmac-sha1-cbc-aes-caam-qi",
+ .blocksize = AES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = tls_setkey,
+ .setauthsize = tls_setauthsize,
+ .encrypt = tls_encrypt,
+ .decrypt = tls_decrypt,
+ .givencrypt = NULL,
+ .geniv = "<built-in>",
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = SHA1_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+ .min_era = 4,
+ }
+};
+
+struct caam_crypto_alg {
+ struct list_head entry;
+ struct device *ctrldev;
+ int class1_alg_type;
+ int class2_alg_type;
+ int alg_op;
+ struct crypto_alg crypto_alg;
+};
+
+static int caam_cra_init(struct crypto_tfm *tfm)
+{
+ struct crypto_alg *alg = tfm->__crt_alg;
+ struct caam_crypto_alg *caam_alg =
+ container_of(alg, struct caam_crypto_alg, crypto_alg);
+ struct caam_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct caam_drv_private *priv = dev_get_drvdata(caam_alg->ctrldev);
+ /* Digest sizes for MD5, SHA1, SHA-224, SHA-256, SHA-384, SHA-512 */
+ static const u8 digest_size[] = {
+ MD5_DIGEST_SIZE,
+ SHA1_DIGEST_SIZE,
+ SHA224_DIGEST_SIZE,
+ SHA256_DIGEST_SIZE,
+ SHA384_DIGEST_SIZE,
+ SHA512_DIGEST_SIZE
+ };
+
+ /*
+ * distribute tfms across job rings to ensure in-order
+ * crypto request processing per tfm
+ */
+ ctx->jrdev = caam_jr_alloc();
+ if (IS_ERR(ctx->jrdev)) {
+ pr_err("Job Ring Device allocation for transform failed\n");
+ return PTR_ERR(ctx->jrdev);
+ }
+
+ /* copy descriptor header template value */
+ ctx->class1_alg_type = OP_TYPE_CLASS1_ALG | caam_alg->class1_alg_type;
+ ctx->class2_alg_type = OP_TYPE_CLASS2_ALG | caam_alg->class2_alg_type;
+ ctx->alg_op = OP_TYPE_CLASS2_ALG | caam_alg->alg_op;
+
+ /*
+ * Need authsize, in case setauthsize callback not called
+ * by upper layer (e.g. TLS).
+ */
+ if (caam_alg->alg_op)
+ ctx->authsize = digest_size[(ctx->alg_op &
+ OP_ALG_ALGSEL_SUBMASK) >> OP_ALG_ALGSEL_SHIFT];
+ else
+ ctx->authsize = 0;
+
+ ctx->qidev = priv->qidev;
+
+ spin_lock_init(&ctx->lock);
+ ctx->drv_ctx[ENCRYPT] = NULL;
+ ctx->drv_ctx[DECRYPT] = NULL;
+ ctx->drv_ctx[GIVENCRYPT] = NULL;
+
+ return 0;
+}
+
+static void caam_cra_exit(struct crypto_tfm *tfm)
+{
+ struct caam_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ if (ctx->drv_ctx[ENCRYPT])
+ caam_drv_ctx_rel(ctx->drv_ctx[ENCRYPT]);
+
+ if (ctx->drv_ctx[DECRYPT])
+ caam_drv_ctx_rel(ctx->drv_ctx[DECRYPT]);
+
+ if (ctx->drv_ctx[GIVENCRYPT])
+ caam_drv_ctx_rel(ctx->drv_ctx[GIVENCRYPT]);
+
+ caam_jr_free(ctx->jrdev);
+}
+
+static struct list_head alg_list;
+static void __exit caam_qi_algapi_exit(void)
+{
+ struct caam_crypto_alg *t_alg, *n;
+
+ if (!alg_list.next)
+ return;
+
+ list_for_each_entry_safe(t_alg, n, &alg_list, entry) {
+ crypto_unregister_alg(&t_alg->crypto_alg);
+ list_del(&t_alg->entry);
+ kfree(t_alg);
+ }
+}
+
+static struct caam_crypto_alg *caam_alg_alloc(struct device *ctrldev,
+ struct caam_alg_template
+ *template)
+{
+ struct caam_crypto_alg *t_alg;
+ struct crypto_alg *alg;
+
+ t_alg = kzalloc(sizeof(struct caam_crypto_alg), GFP_KERNEL);
+ if (!t_alg) {
+ dev_err(ctrldev, "failed to allocate t_alg\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ alg = &t_alg->crypto_alg;
+
+ snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", template->name);
+ snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
+ template->driver_name);
+ alg->cra_module = THIS_MODULE;
+ alg->cra_init = caam_cra_init;
+ alg->cra_exit = caam_cra_exit;
+ alg->cra_priority = CAAM_CRA_PRIORITY;
+ alg->cra_blocksize = template->blocksize;
+ alg->cra_alignmask = 0;
+ alg->cra_ctxsize = sizeof(struct caam_ctx);
+ alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY |
+ template->type;
+ switch (template->type) {
+ case CRYPTO_ALG_TYPE_ABLKCIPHER:
+ alg->cra_type = &crypto_ablkcipher_type;
+ alg->cra_ablkcipher = template->template_ablkcipher;
+ break;
+ case CRYPTO_ALG_TYPE_AEAD:
+ alg->cra_type = &crypto_aead_type;
+ alg->cra_aead = template->template_aead;
+ break;
+ }
+
+ t_alg->class1_alg_type = template->class1_alg_type;
+ t_alg->class2_alg_type = template->class2_alg_type;
+ t_alg->alg_op = template->alg_op;
+ t_alg->ctrldev = ctrldev;
+
+ return t_alg;
+}
+
+static int __init caam_qi_algapi_init(void)
+{
+ struct device_node *dev_node;
+ struct platform_device *pdev;
+ struct device *ctrldev;
+ struct caam_drv_private *priv;
+ int i = 0, err = 0;
+
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+ if (!dev_node) {
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+ if (!dev_node)
+ return -ENODEV;
+ }
+
+ pdev = of_find_device_by_node(dev_node);
+ if (!pdev)
+ return -ENODEV;
+
+ ctrldev = &pdev->dev;
+ priv = dev_get_drvdata(ctrldev);
+ /*
+ * If priv is NULL, it's probably because the caam driver wasn't
+ * properly initialized (e.g. RNG4 init failed). Thus, bail out here.
+ */
+ if (!priv)
+ return -ENODEV;
+ of_node_put(dev_node);
+
+ INIT_LIST_HEAD(&alg_list);
+
+ /* register crypto algorithms the device supports */
+ for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
+ struct caam_crypto_alg *t_alg;
+
+ /* check if h/w supports alg */
+ if (priv->era > 0 && priv->era < driver_algs[i].min_era) {
+ dev_warn(priv->qidev, "%s needs Era %d or higher but SEC is Era %d, skipping it\n",
+ driver_algs[i].driver_name,
+ driver_algs[i].min_era, priv->era);
+ continue;
+ }
+
+ t_alg = caam_alg_alloc(ctrldev, &driver_algs[i]);
+ if (IS_ERR(t_alg)) {
+ err = PTR_ERR(t_alg);
+ dev_warn(priv->qidev, "%s alg allocation failed\n",
+ driver_algs[i].driver_name);
+ continue;
+ }
+
+ err = crypto_register_alg(&t_alg->crypto_alg);
+ if (err) {
+ dev_warn(priv->qidev, "%s alg registration failed\n",
+ t_alg->crypto_alg.cra_driver_name);
+ kfree(t_alg);
+ } else {
+ list_add_tail(&t_alg->entry, &alg_list);
+ }
+ }
+
+ if (!list_empty(&alg_list))
+ dev_info(priv->qidev, "%s algorithms registered in /proc/crypto\n",
+ (char *)of_get_property(dev_node, "compatible", NULL));
+
+ return err;
+}
+
+module_init(caam_qi_algapi_init);
+module_exit(caam_qi_algapi_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Support for crypto API using CAAM-QI backend");
+MODULE_AUTHOR("Freescale Semiconductor - NMG/STC");
diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c
index e732bd9..5592fec 100644
--- a/drivers/crypto/caam/caamhash.c
+++ b/drivers/crypto/caam/caamhash.c
@@ -94,6 +94,9 @@
#define debug(format, arg...)
#endif
+
+static struct list_head hash_list;
+
/* ahash per-session context */
struct caam_hash_ctx {
struct device *jrdev;
@@ -1653,7 +1656,6 @@ static struct caam_hash_template driver_hash[] = {
struct caam_hash_alg {
struct list_head entry;
- struct device *ctrldev;
int alg_type;
int alg_op;
struct ahash_alg ahash_alg;
@@ -1670,7 +1672,6 @@ static int caam_hash_cra_init(struct crypto_tfm *tfm)
struct caam_hash_alg *caam_hash =
container_of(alg, struct caam_hash_alg, ahash_alg);
struct caam_hash_ctx *ctx = crypto_tfm_ctx(tfm);
- struct caam_drv_private *priv = dev_get_drvdata(caam_hash->ctrldev);
/* Sizes for MDHA running digests: MD5, SHA1, 224, 256, 384, 512 */
static const u8 runninglen[] = { HASH_MSG_LEN + MD5_DIGEST_SIZE,
HASH_MSG_LEN + SHA1_DIGEST_SIZE,
@@ -1678,15 +1679,17 @@ static int caam_hash_cra_init(struct crypto_tfm *tfm)
HASH_MSG_LEN + SHA256_DIGEST_SIZE,
HASH_MSG_LEN + 64,
HASH_MSG_LEN + SHA512_DIGEST_SIZE };
- int tgt_jr = atomic_inc_return(&priv->tfm_count);
int ret = 0;
/*
- * distribute tfms across job rings to ensure in-order
+ * Get a Job ring from Job Ring driver to ensure in-order
* crypto request processing per tfm
*/
- ctx->jrdev = priv->jrdev[tgt_jr % priv->total_jobrs];
-
+ ctx->jrdev = caam_jr_alloc();
+ if (IS_ERR(ctx->jrdev)) {
+ pr_err("Job Ring Device allocation for transform failed\n");
+ return PTR_ERR(ctx->jrdev);
+ }
/* copy descriptor header template value */
ctx->alg_type = OP_TYPE_CLASS2_ALG | caam_hash->alg_type;
ctx->alg_op = OP_TYPE_CLASS2_ALG | caam_hash->alg_op;
@@ -1729,35 +1732,18 @@ static void caam_hash_cra_exit(struct crypto_tfm *tfm)
!dma_mapping_error(ctx->jrdev, ctx->sh_desc_finup_dma))
dma_unmap_single(ctx->jrdev, ctx->sh_desc_finup_dma,
desc_bytes(ctx->sh_desc_finup), DMA_TO_DEVICE);
+
+ caam_jr_free(ctx->jrdev);
}
static void __exit caam_algapi_hash_exit(void)
{
- struct device_node *dev_node;
- struct platform_device *pdev;
- struct device *ctrldev;
- struct caam_drv_private *priv;
struct caam_hash_alg *t_alg, *n;
- dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
- if (!dev_node) {
- dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
- if (!dev_node)
- return;
- }
-
- pdev = of_find_device_by_node(dev_node);
- if (!pdev)
+ if (!hash_list.next)
return;
- ctrldev = &pdev->dev;
- of_node_put(dev_node);
- priv = dev_get_drvdata(ctrldev);
-
- if (!priv->hash_list.next)
- return;
-
- list_for_each_entry_safe(t_alg, n, &priv->hash_list, entry) {
+ list_for_each_entry_safe(t_alg, n, &hash_list, entry) {
crypto_unregister_ahash(&t_alg->ahash_alg);
list_del(&t_alg->entry);
kfree(t_alg);
@@ -1765,7 +1751,7 @@ static void __exit caam_algapi_hash_exit(void)
}
static struct caam_hash_alg *
-caam_hash_alloc(struct device *ctrldev, struct caam_hash_template *template,
+caam_hash_alloc(struct caam_hash_template *template,
bool keyed)
{
struct caam_hash_alg *t_alg;
@@ -1774,7 +1760,7 @@ caam_hash_alloc(struct device *ctrldev, struct caam_hash_template *template,
t_alg = kzalloc(sizeof(struct caam_hash_alg), GFP_KERNEL);
if (!t_alg) {
- dev_err(ctrldev, "failed to allocate t_alg\n");
+ pr_err("failed to allocate t_alg\n");
return ERR_PTR(-ENOMEM);
}
@@ -1805,7 +1791,6 @@ caam_hash_alloc(struct device *ctrldev, struct caam_hash_template *template,
t_alg->alg_type = template->alg_type;
t_alg->alg_op = template->alg_op;
- t_alg->ctrldev = ctrldev;
return t_alg;
}
@@ -1815,7 +1800,7 @@ static int __init caam_algapi_hash_init(void)
struct device_node *dev_node;
struct platform_device *pdev;
struct device *ctrldev;
- struct caam_drv_private *priv;
+ void *priv;
int i = 0, err = 0;
dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
@@ -1833,9 +1818,14 @@ static int __init caam_algapi_hash_init(void)
priv = dev_get_drvdata(ctrldev);
of_node_put(dev_node);
- INIT_LIST_HEAD(&priv->hash_list);
+ /*
+ * If priv is NULL, it's probably because the caam driver wasn't
+ * properly initialized (e.g. RNG4 init failed). Thus, bail out here.
+ */
+ if (!priv)
+ return -ENODEV;
- atomic_set(&priv->tfm_count, -1);
+ INIT_LIST_HEAD(&hash_list);
/* register crypto algorithms the device supports */
for (i = 0; i < ARRAY_SIZE(driver_hash); i++) {
@@ -1843,38 +1833,38 @@ static int __init caam_algapi_hash_init(void)
struct caam_hash_alg *t_alg;
/* register hmac version */
- t_alg = caam_hash_alloc(ctrldev, &driver_hash[i], true);
+ t_alg = caam_hash_alloc(&driver_hash[i], true);
if (IS_ERR(t_alg)) {
err = PTR_ERR(t_alg);
- dev_warn(ctrldev, "%s alg allocation failed\n",
- driver_hash[i].driver_name);
+ pr_warn("%s alg allocation failed\n",
+ driver_hash[i].driver_name);
continue;
}
err = crypto_register_ahash(&t_alg->ahash_alg);
if (err) {
- dev_warn(ctrldev, "%s alg registration failed\n",
+ pr_warn("%s alg registration failed\n",
t_alg->ahash_alg.halg.base.cra_driver_name);
kfree(t_alg);
} else
- list_add_tail(&t_alg->entry, &priv->hash_list);
+ list_add_tail(&t_alg->entry, &hash_list);
/* register unkeyed version */
- t_alg = caam_hash_alloc(ctrldev, &driver_hash[i], false);
+ t_alg = caam_hash_alloc(&driver_hash[i], false);
if (IS_ERR(t_alg)) {
err = PTR_ERR(t_alg);
- dev_warn(ctrldev, "%s alg allocation failed\n",
- driver_hash[i].driver_name);
+ pr_warn("%s alg allocation failed\n",
+ driver_hash[i].driver_name);
continue;
}
err = crypto_register_ahash(&t_alg->ahash_alg);
if (err) {
- dev_warn(ctrldev, "%s alg registration failed\n",
+ pr_warn("%s alg registration failed\n",
t_alg->ahash_alg.halg.base.cra_driver_name);
kfree(t_alg);
} else
- list_add_tail(&t_alg->entry, &priv->hash_list);
+ list_add_tail(&t_alg->entry, &hash_list);
}
return err;
diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c
new file mode 100644
index 0000000..8023e55
--- /dev/null
+++ b/drivers/crypto/caam/caampkc.c
@@ -0,0 +1,1496 @@
+/*
+ * \file - caampkc.c
+ * \brief - Freescale FSL CAAM support for Public Key Cryptography
+ *
+ * Author: Yashpal Dutta <yashpal.dutta@freescale.com>
+ *
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * There is no shared descriptor for PKC but Job descriptor must carry
+ * all the desired key parameters, input and output pointers
+ *
+ */
+
+#include "pkc_desc.h"
+
+/* PKC Priority */
+#define CAAM_PKC_PRIORITY 3000
+
+#ifdef DEBUG
+/* for print_hex_dumps with line references */
+#define debug(format, arg...) pr_debug(format, arg)
+#else
+#define debug(format, arg...)
+#endif
+
+/* Internal context of CAAM driver. May carry session specific
+ PKC information like key */
+struct caam_pkc_context_s {
+ /* Job Ring Device pointer for current request */
+ struct device *dev;
+};
+
+static void rsa_unmap(struct device *dev,
+ struct rsa_edesc *edesc, struct pkc_request *req)
+{
+ switch (req->type) {
+ case RSA_PUB:
+ {
+ struct rsa_pub_req_s *pub_req = &req->req_u.rsa_pub_req;
+ struct rsa_pub_desc_s *rsa_pub_desc =
+ (struct rsa_pub_desc_s *)edesc->hw_desc;
+
+ dma_unmap_single(dev, rsa_pub_desc->n_dma,
+ pub_req->n_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, rsa_pub_desc->e_dma,
+ pub_req->e_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, rsa_pub_desc->g_dma,
+ pub_req->g_len, DMA_FROM_DEVICE);
+ dma_unmap_single(dev, rsa_pub_desc->f_dma,
+ pub_req->f_len, DMA_TO_DEVICE);
+ break;
+ }
+ case RSA_PRIV_FORM1:
+ {
+ struct rsa_priv_frm1_req_s *priv_req =
+ &req->req_u.rsa_priv_f1;
+ struct rsa_priv_frm1_desc_s *rsa_priv_desc =
+ (struct rsa_priv_frm1_desc_s *)edesc->hw_desc;
+
+ dma_unmap_single(dev, rsa_priv_desc->n_dma,
+ priv_req->n_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, rsa_priv_desc->d_dma,
+ priv_req->d_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, rsa_priv_desc->f_dma,
+ priv_req->f_len, DMA_FROM_DEVICE);
+ dma_unmap_single(dev, rsa_priv_desc->g_dma,
+ priv_req->g_len, DMA_TO_DEVICE);
+ break;
+ }
+ case RSA_PRIV_FORM2:
+ {
+ struct rsa_priv_frm2_req_s *priv_req =
+ &req->req_u.rsa_priv_f2;
+ struct rsa_priv_frm2_desc_s *rsa_priv_desc =
+ (struct rsa_priv_frm2_desc_s *)edesc->hw_desc;
+
+ dma_unmap_single(dev, rsa_priv_desc->p_dma,
+ priv_req->p_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, rsa_priv_desc->q_dma,
+ priv_req->q_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, rsa_priv_desc->d_dma,
+ priv_req->d_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, rsa_priv_desc->g_dma,
+ priv_req->g_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, rsa_priv_desc->f_dma,
+ priv_req->f_len, DMA_FROM_DEVICE);
+ dma_unmap_single(dev,
+ edesc->dma_u.rsa_priv_f2_edesc.
+ tmp1_dma, priv_req->p_len,
+ DMA_BIDIRECTIONAL);
+ dma_unmap_single(dev,
+ edesc->dma_u.rsa_priv_f2_edesc.
+ tmp2_dma, priv_req->q_len,
+ DMA_BIDIRECTIONAL);
+ kfree(edesc->dma_u.rsa_priv_f2_edesc.tmp1);
+ kfree(edesc->dma_u.rsa_priv_f2_edesc.tmp2);
+ break;
+ }
+ case RSA_PRIV_FORM3:
+ {
+ struct rsa_priv_frm3_req_s *priv_req =
+ &req->req_u.rsa_priv_f3;
+ struct rsa_priv_frm3_desc_s *rsa_priv_desc =
+ (struct rsa_priv_frm3_desc_s *)edesc->hw_desc;
+
+ dma_unmap_single(dev, rsa_priv_desc->p_dma,
+ priv_req->p_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, rsa_priv_desc->q_dma,
+ priv_req->q_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, rsa_priv_desc->dq_dma,
+ priv_req->dq_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, rsa_priv_desc->dp_dma,
+ priv_req->dp_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, rsa_priv_desc->c_dma,
+ priv_req->c_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, rsa_priv_desc->g_dma,
+ priv_req->g_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, rsa_priv_desc->f_dma,
+ priv_req->f_len, DMA_FROM_DEVICE);
+ dma_unmap_single(dev,
+ edesc->dma_u.rsa_priv_f3_edesc.
+ tmp1_dma, priv_req->p_len,
+ DMA_BIDIRECTIONAL);
+ dma_unmap_single(dev,
+ edesc->dma_u.rsa_priv_f3_edesc.
+ tmp2_dma, priv_req->q_len,
+ DMA_BIDIRECTIONAL);
+ kfree(edesc->dma_u.rsa_priv_f3_edesc.tmp1);
+ kfree(edesc->dma_u.rsa_priv_f3_edesc.tmp2);
+ break;
+ }
+ default:
+ dev_err(dev, "Unable to find request type\n");
+ }
+}
+
+/* RSA Job Completion handler */
+static void rsa_op_done(struct device *dev, u32 *desc, u32 err, void *context)
+{
+ struct pkc_request *req = context;
+ struct rsa_edesc *edesc;
+
+ edesc = (struct rsa_edesc *)((char *)desc -
+ offsetof(struct rsa_edesc, hw_desc));
+
+ if (err) {
+ char tmp[CAAM_ERROR_STR_MAX];
+ dev_err(dev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
+ }
+
+ rsa_unmap(dev, edesc, req);
+ kfree(edesc);
+
+ pkc_request_complete(req, err);
+}
+
+static void dh_unmap(struct device *dev,
+ struct dh_edesc_s *edesc, struct pkc_request *req)
+{
+ struct dh_key_req_s *dh_req = &req->req_u.dh_req;
+ struct dh_key_desc_s *dh_desc =
+ (struct dh_key_desc_s *)edesc->hw_desc;
+ dma_unmap_single(dev, dh_desc->q_dma,
+ dh_req->q_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, dh_desc->w_dma,
+ dh_req->pub_key_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, dh_desc->s_dma,
+ dh_req->s_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, dh_desc->z_dma,
+ dh_req->z_len, DMA_FROM_DEVICE);
+ if (edesc->req_type == ECDH_COMPUTE_KEY)
+ dma_unmap_single(dev, dh_desc->ab_dma,
+ dh_req->ab_len, DMA_TO_DEVICE);
+}
+
+static void dsa_unmap(struct device *dev,
+ struct dsa_edesc_s *edesc, struct pkc_request *req)
+{
+ switch (req->type) {
+ case DSA_SIGN:
+ case ECDSA_SIGN:
+ {
+ struct dsa_sign_req_s *dsa_req = &req->req_u.dsa_sign;
+ struct dsa_sign_desc_s *dsa_desc =
+ (struct dsa_sign_desc_s *)edesc->hw_desc;
+ dma_unmap_single(dev, dsa_desc->q_dma,
+ dsa_req->q_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, dsa_desc->r_dma,
+ dsa_req->r_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, dsa_desc->g_dma,
+ dsa_req->g_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, dsa_desc->s_dma,
+ dsa_req->priv_key_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, dsa_desc->f_dma,
+ dsa_req->m_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, dsa_desc->c_dma,
+ dsa_req->d_len, DMA_FROM_DEVICE);
+ dma_unmap_single(dev, dsa_desc->d_dma,
+ dsa_req->d_len, DMA_FROM_DEVICE);
+ if (req->type == ECDSA_SIGN)
+ dma_unmap_single(dev, edesc->ab_dma,
+ dsa_req->ab_len, DMA_TO_DEVICE);
+ }
+ break;
+ case DSA_VERIFY:
+ case ECDSA_VERIFY:
+ {
+ struct dsa_verify_req_s *dsa_req = &req->req_u.dsa_verify;
+ struct dsa_verify_desc_s *dsa_desc =
+ (struct dsa_verify_desc_s *)edesc->hw_desc;
+ dma_unmap_single(dev, dsa_desc->q_dma,
+ dsa_req->q_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, dsa_desc->r_dma,
+ dsa_req->r_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, dsa_desc->g_dma,
+ dsa_req->g_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, dsa_desc->w_dma,
+ dsa_req->pub_key_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, dsa_desc->f_dma,
+ dsa_req->m_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, dsa_desc->c_dma,
+ dsa_req->d_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, dsa_desc->d_dma,
+ dsa_req->d_len, DMA_TO_DEVICE);
+ if (req->type == ECDSA_VERIFY) {
+ dma_unmap_single(dev, dsa_desc->tmp_dma,
+ 2*edesc->l_len, DMA_BIDIRECTIONAL);
+ dma_unmap_single(dev, edesc->ab_dma,
+ dsa_req->ab_len, DMA_TO_DEVICE);
+ } else {
+ dma_unmap_single(dev, dsa_desc->tmp_dma,
+ edesc->l_len, DMA_BIDIRECTIONAL);
+ }
+ kfree(edesc->tmp);
+ }
+ break;
+ case DLC_KEYGEN:
+ case ECC_KEYGEN:
+ {
+ struct keygen_req_s *key_req = &req->req_u.keygen;
+ struct dlc_keygen_desc_s *key_desc =
+ (struct dlc_keygen_desc_s *)edesc->hw_desc;
+ dma_unmap_single(dev, key_desc->q_dma,
+ key_req->q_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, key_desc->r_dma,
+ key_req->r_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, key_desc->g_dma,
+ key_req->g_len, DMA_TO_DEVICE);
+ dma_unmap_single(dev, key_desc->s_dma,
+ key_req->priv_key_len, DMA_FROM_DEVICE);
+ dma_unmap_single(dev, key_desc->w_dma,
+ key_req->pub_key_len, DMA_FROM_DEVICE);
+ if (req->type == ECC_KEYGEN)
+ dma_unmap_single(dev, edesc->ab_dma,
+ key_req->ab_len, DMA_TO_DEVICE);
+ }
+ break;
+ default:
+ dev_err(dev, "Unable to find request type\n");
+ }
+}
+
+/* DSA Job Completion handler */
+static void dsa_op_done(struct device *dev, u32 *desc, u32 err, void *context)
+{
+ struct pkc_request *req = context;
+ struct dsa_edesc_s *edesc;
+
+ edesc = (struct dsa_edesc_s *)((char *)desc -
+ offsetof(struct dsa_edesc_s, hw_desc));
+
+ if (err) {
+ char tmp[CAAM_ERROR_STR_MAX];
+ dev_err(dev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
+ }
+
+ dsa_unmap(dev, edesc, req);
+ kfree(edesc);
+
+ pkc_request_complete(req, err);
+}
+static int caam_dsa_sign_edesc(struct pkc_request *req,
+ struct dsa_edesc_s *edesc)
+{
+ struct crypto_pkc *tfm = crypto_pkc_reqtfm(req);
+ struct caam_pkc_context_s *ctxt = crypto_pkc_ctx(tfm);
+ struct device *dev = ctxt->dev;
+ struct dsa_sign_req_s *dsa_req = &req->req_u.dsa_sign;
+
+ edesc->l_len = dsa_req->q_len;
+ edesc->n_len = dsa_req->r_len;
+ edesc->req_type = req->type;
+ edesc->curve_type = req->curve_type;
+ edesc->q_dma = dma_map_single(dev, dsa_req->q, dsa_req->q_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, edesc->q_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto q_map_fail;
+ }
+
+ edesc->r_dma = dma_map_single(dev, dsa_req->r, dsa_req->r_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, edesc->r_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto r_map_fail;
+ }
+
+ edesc->g_dma = dma_map_single(dev, dsa_req->g, dsa_req->g_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, edesc->g_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto g_map_fail;
+ }
+
+ edesc->f_dma = dma_map_single(dev, dsa_req->m, dsa_req->m_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, edesc->f_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto m_map_fail;
+ }
+
+ edesc->key_dma = dma_map_single(dev, dsa_req->priv_key,
+ dsa_req->priv_key_len, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, edesc->key_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto key_map_fail;
+ }
+
+ edesc->c_dma = dma_map_single(dev, dsa_req->c, dsa_req->d_len,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(dev, edesc->c_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto c_map_fail;
+ }
+
+ edesc->d_dma = dma_map_single(dev, dsa_req->d, dsa_req->d_len,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(dev, edesc->d_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto d_map_fail;
+ }
+
+ if (edesc->req_type == ECDSA_SIGN) {
+ edesc->ab_dma = dma_map_single(dev, dsa_req->ab,
+ dsa_req->ab_len, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, edesc->ab_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto ab_map_fail;
+ }
+ }
+ return 0;
+ab_map_fail:
+ if (edesc->req_type == ECDSA_SIGN)
+ dma_unmap_single(dev, edesc->d_dma, dsa_req->d_len,
+ DMA_TO_DEVICE);
+d_map_fail:
+ dma_unmap_single(dev, edesc->c_dma, dsa_req->d_len, DMA_FROM_DEVICE);
+c_map_fail:
+ dma_unmap_single(dev, edesc->key_dma, dsa_req->priv_key_len,
+ DMA_TO_DEVICE);
+key_map_fail:
+ dma_unmap_single(dev, edesc->f_dma, dsa_req->m_len, DMA_FROM_DEVICE);
+m_map_fail:
+ dma_unmap_single(dev, edesc->g_dma, dsa_req->g_len, DMA_TO_DEVICE);
+g_map_fail:
+ dma_unmap_single(dev, edesc->r_dma, dsa_req->r_len, DMA_TO_DEVICE);
+r_map_fail:
+ dma_unmap_single(dev, edesc->q_dma, dsa_req->q_len, DMA_TO_DEVICE);
+q_map_fail:
+ return -EINVAL;
+}
+
+static int caam_dsa_verify_edesc(struct pkc_request *req,
+ struct dsa_edesc_s *edesc)
+{
+ struct crypto_pkc *tfm = crypto_pkc_reqtfm(req);
+ struct caam_pkc_context_s *ctxt = crypto_pkc_ctx(tfm);
+ struct device *dev = ctxt->dev;
+ uint32_t tmp_len;
+ struct dsa_verify_req_s *dsa_req = &req->req_u.dsa_verify;
+
+ edesc->l_len = dsa_req->q_len;
+ edesc->n_len = dsa_req->r_len;
+ edesc->req_type = req->type;
+ edesc->curve_type = req->curve_type;
+ if (edesc->req_type == ECDSA_VERIFY)
+ tmp_len = 2*dsa_req->q_len;
+ else
+ tmp_len = dsa_req->q_len;
+
+ edesc->tmp = kzalloc(tmp_len, GFP_DMA);
+ if (!edesc->tmp) {
+ pr_debug("Failed to allocate temp buffer for DSA Verify\n");
+ return -ENOMEM;
+ }
+
+ edesc->tmp_dma = dma_map_single(dev, edesc->tmp, tmp_len,
+ DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(dev, edesc->tmp_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto tmp_map_fail;
+ }
+
+ edesc->q_dma = dma_map_single(dev, dsa_req->q, dsa_req->q_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, edesc->q_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto q_map_fail;
+ }
+
+ edesc->r_dma = dma_map_single(dev, dsa_req->r, dsa_req->r_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, edesc->r_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto r_map_fail;
+ }
+
+ edesc->g_dma = dma_map_single(dev, dsa_req->g, dsa_req->g_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, edesc->g_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto g_map_fail;
+ }
+
+ edesc->f_dma = dma_map_single(dev, dsa_req->m, dsa_req->m_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, edesc->f_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto m_map_fail;
+ }
+
+ edesc->key_dma = dma_map_single(dev, dsa_req->pub_key,
+ dsa_req->pub_key_len, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, edesc->key_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto key_map_fail;
+ }
+
+ edesc->c_dma = dma_map_single(dev, dsa_req->c, dsa_req->d_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, edesc->c_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto c_map_fail;
+ }
+
+ edesc->d_dma = dma_map_single(dev, dsa_req->d, dsa_req->d_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, edesc->d_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto d_map_fail;
+ }
+
+ if (edesc->req_type == ECDSA_VERIFY) {
+ edesc->ab_dma = dma_map_single(dev, dsa_req->ab,
+ dsa_req->ab_len, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, edesc->ab_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto ab_map_fail;
+ }
+ }
+ return 0;
+ab_map_fail:
+ if (edesc->req_type == ECDSA_VERIFY)
+ dma_unmap_single(dev, edesc->d_dma, dsa_req->d_len,
+ DMA_TO_DEVICE);
+d_map_fail:
+ dma_unmap_single(dev, edesc->c_dma, dsa_req->d_len, DMA_TO_DEVICE);
+c_map_fail:
+ dma_unmap_single(dev, edesc->key_dma, dsa_req->pub_key_len,
+ DMA_TO_DEVICE);
+key_map_fail:
+ dma_unmap_single(dev, edesc->f_dma, dsa_req->m_len, DMA_TO_DEVICE);
+m_map_fail:
+ dma_unmap_single(dev, edesc->g_dma, dsa_req->g_len, DMA_TO_DEVICE);
+g_map_fail:
+ dma_unmap_single(dev, edesc->r_dma, dsa_req->r_len, DMA_TO_DEVICE);
+r_map_fail:
+ dma_unmap_single(dev, edesc->q_dma, dsa_req->q_len, DMA_TO_DEVICE);
+q_map_fail:
+ dma_unmap_single(dev, edesc->tmp_dma, tmp_len, DMA_BIDIRECTIONAL);
+tmp_map_fail:
+ kfree(edesc->tmp);
+ return -EINVAL;
+}
+
+static int caam_keygen_edesc(struct pkc_request *req,
+ struct dsa_edesc_s *edesc)
+{
+ struct crypto_pkc *tfm = crypto_pkc_reqtfm(req);
+ struct caam_pkc_context_s *ctxt = crypto_pkc_ctx(tfm);
+ struct device *dev = ctxt->dev;
+ struct keygen_req_s *key_req = &req->req_u.keygen;
+
+ edesc->l_len = key_req->q_len;
+ edesc->n_len = key_req->r_len;
+ edesc->req_type = req->type;
+ edesc->curve_type = req->curve_type;
+
+ edesc->q_dma = dma_map_single(dev, key_req->q, key_req->q_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, edesc->q_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto q_map_fail;
+ }
+
+ edesc->r_dma = dma_map_single(dev, key_req->r, key_req->r_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, edesc->r_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto r_map_fail;
+ }
+
+ edesc->g_dma = dma_map_single(dev, key_req->g, key_req->g_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, edesc->g_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto g_map_fail;
+ }
+
+ edesc->key_dma = dma_map_single(dev, key_req->pub_key,
+ key_req->pub_key_len, DMA_FROM_DEVICE);
+ if (dma_mapping_error(dev, edesc->key_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto key_map_fail;
+ }
+
+ edesc->s_dma = dma_map_single(dev, key_req->priv_key,
+ key_req->priv_key_len, DMA_FROM_DEVICE);
+ if (dma_mapping_error(dev, edesc->s_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto s_map_fail;
+ }
+
+ if (edesc->req_type == ECC_KEYGEN) {
+ edesc->ab_dma = dma_map_single(dev, key_req->ab,
+ key_req->ab_len, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, edesc->ab_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto ab_map_fail;
+ }
+ }
+
+ return 0;
+ab_map_fail:
+ if (edesc->req_type == ECC_KEYGEN)
+ dma_unmap_single(dev, edesc->s_dma, key_req->priv_key_len,
+ DMA_FROM_DEVICE);
+s_map_fail:
+ dma_unmap_single(dev, edesc->key_dma, key_req->pub_key_len,
+ DMA_FROM_DEVICE);
+key_map_fail:
+ dma_unmap_single(dev, edesc->g_dma, key_req->g_len, DMA_TO_DEVICE);
+g_map_fail:
+ dma_unmap_single(dev, edesc->r_dma, key_req->r_len, DMA_TO_DEVICE);
+r_map_fail:
+ dma_unmap_single(dev, edesc->q_dma, key_req->q_len, DMA_TO_DEVICE);
+q_map_fail:
+ return -EINVAL;
+}
+
+static int caam_rsa_pub_edesc(struct pkc_request *req, struct rsa_edesc *edesc)
+{
+ struct crypto_pkc *tfm = crypto_pkc_reqtfm(req);
+ struct caam_pkc_context_s *ctxt = crypto_pkc_ctx(tfm);
+ struct device *dev = ctxt->dev;
+ struct rsa_pub_req_s *pub_req = &req->req_u.rsa_pub_req;
+ struct rsa_pub_edesc_s *pub_edesc = &edesc->dma_u.rsa_pub_edesc;
+
+ if (pub_req->n_len > pub_req->g_len) {
+ pr_err("Output buffer length less than parameter n\n");
+ return -EINVAL;
+ }
+
+ pub_edesc->n_dma = dma_map_single(dev, pub_req->n, pub_req->n_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, pub_edesc->n_dma)) {
+ dev_err(dev, "Unable to map modulus memory\n");
+ goto n_pub_fail;
+ }
+
+ pub_edesc->e_dma = dma_map_single(dev, pub_req->e, pub_req->e_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, pub_edesc->e_dma)) {
+ dev_err(dev, "Unable to map exponent memory\n");
+ goto e_pub_fail;
+ }
+
+ pub_edesc->f_dma = dma_map_single(dev, pub_req->f, pub_req->f_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, pub_edesc->f_dma)) {
+ dev_err(dev, "Unable to map input buffer memory\n");
+ goto f_pub_fail;
+ }
+
+ pub_edesc->g_dma = dma_map_single(dev, pub_req->g, pub_req->g_len,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(dev, pub_edesc->g_dma)) {
+ dev_err(dev, "Unable to map output memory\n");
+ goto g_pub_fail;
+ }
+
+ /* TBD: Set SG flags in case input is SG */
+ pub_edesc->sg_flgs.e_len = pub_req->e_len;
+ pub_edesc->sg_flgs.n_len = pub_req->n_len;
+ pub_edesc->f_len = pub_req->f_len;
+/* Enable once we check SG */
+#ifdef SG_ENABLED
+ pub_edesc->sg_flgs.sg_f = 1;
+ pub_edesc->sg_flgs.sg_g = 1;
+ pub_edesc->sg_flgs.sg_e = 1;
+ pub_edesc->sg_flgs.sg_n = 1;
+#endif
+
+ return 0;
+g_pub_fail:
+ dma_unmap_single(dev, pub_edesc->f_dma, pub_req->f_len, DMA_TO_DEVICE);
+f_pub_fail:
+ dma_unmap_single(dev, pub_edesc->e_dma, pub_req->e_len, DMA_TO_DEVICE);
+e_pub_fail:
+ dma_unmap_single(dev, pub_edesc->n_dma, pub_req->n_len, DMA_TO_DEVICE);
+n_pub_fail:
+ return -EINVAL;
+}
+
+static int caam_rsa_priv_f1_edesc(struct pkc_request *req,
+ struct rsa_edesc *edesc)
+{
+ struct crypto_pkc *tfm = crypto_pkc_reqtfm(req);
+ struct caam_pkc_context_s *ctxt = crypto_pkc_ctx(tfm);
+ struct device *dev = ctxt->dev;
+ struct rsa_priv_frm1_req_s *priv_req = &req->req_u.rsa_priv_f1;
+ struct rsa_priv_frm1_edesc_s *priv_edesc =
+ &edesc->dma_u.rsa_priv_f1_edesc;
+
+ priv_edesc->n_dma = dma_map_single(dev, priv_req->n, priv_req->n_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, priv_edesc->n_dma)) {
+ dev_err(dev, "Unable to map modulus memory\n");
+ goto n_f1_fail;
+ }
+
+ priv_edesc->d_dma = dma_map_single(dev, priv_req->d, priv_req->d_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, priv_edesc->d_dma)) {
+ dev_err(dev, "Unable to map exponent memory\n");
+ goto d_f1_fail;
+ }
+
+ priv_edesc->f_dma = dma_map_single(dev, priv_req->f, priv_req->f_len,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(dev, priv_edesc->f_dma)) {
+ dev_err(dev, "Unable to map output buffer memory\n");
+ goto f_f1_fail;
+ }
+
+ priv_edesc->g_dma = dma_map_single(dev, priv_req->g, priv_req->g_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, priv_edesc->g_dma)) {
+ dev_err(dev, "Unable to map input memory\n");
+ goto g_f1_fail;
+ }
+
+/* Enable once we check SG */
+#ifdef SG_ENABLED
+ priv_edesc->sg_flgs.sg_f = 1;
+ priv_edesc->sg_flgs.sg_g = 1;
+ priv_edesc->sg_flgs.sg_d = 1;
+ priv_edesc->sg_flgs.sg_n = 1;
+#endif
+ priv_edesc->sg_flgs.d_len = priv_req->d_len;
+ priv_edesc->sg_flgs.n_len = priv_req->n_len;
+
+ return 0;
+g_f1_fail:
+ dma_unmap_single(dev, priv_edesc->f_dma, priv_req->f_len,
+ DMA_FROM_DEVICE);
+f_f1_fail:
+ dma_unmap_single(dev, priv_edesc->d_dma, priv_req->d_len,
+ DMA_TO_DEVICE);
+d_f1_fail:
+ dma_unmap_single(dev, priv_edesc->n_dma, priv_req->n_len,
+ DMA_TO_DEVICE);
+n_f1_fail:
+ return -EINVAL;
+}
+
+static int caam_rsa_priv_f2_edesc(struct pkc_request *req,
+ struct rsa_edesc *edesc)
+{
+ struct crypto_pkc *tfm = crypto_pkc_reqtfm(req);
+ struct caam_pkc_context_s *ctxt = crypto_pkc_ctx(tfm);
+ struct device *dev = ctxt->dev;
+ struct rsa_priv_frm2_req_s *priv_req = &req->req_u.rsa_priv_f2;
+ struct rsa_priv_frm2_edesc_s *priv_edesc =
+ &edesc->dma_u.rsa_priv_f2_edesc;
+
+ /* tmp1 must be as long as p */
+ priv_edesc->tmp1 = kzalloc(priv_req->p_len, GFP_DMA);
+
+ if (!priv_edesc->tmp1)
+ return -ENOMEM;
+
+ /* tmp2 must be as long as q */
+ priv_edesc->tmp2 = kzalloc(priv_req->q_len, GFP_DMA);
+ if (!priv_edesc->tmp2) {
+ kfree(priv_edesc->tmp1);
+ return -ENOMEM;
+ }
+
+ priv_edesc->tmp1_dma =
+ dma_map_single(dev, priv_edesc->tmp1, priv_req->p_len,
+ DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(dev, priv_edesc->tmp1_dma)) {
+ dev_err(dev, "Unable to map modulus memory\n");
+ goto tmp1_f2_fail;
+ }
+
+ priv_edesc->tmp2_dma =
+ dma_map_single(dev, priv_edesc->tmp2, priv_req->q_len,
+ DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(dev, priv_edesc->tmp2_dma)) {
+ dev_err(dev, "Unable to map modulus memory\n");
+ goto tmp2_f2_fail;
+ }
+
+ priv_edesc->p_dma = dma_map_single(dev, priv_req->p, priv_req->p_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, priv_edesc->p_dma)) {
+ dev_err(dev, "Unable to map modulus memory\n");
+ goto p_f2_fail;
+ }
+
+ priv_edesc->q_dma = dma_map_single(dev, priv_req->q, priv_req->q_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, priv_edesc->q_dma)) {
+ dev_err(dev, "Unable to map exponent memory\n");
+ goto q_f2_fail;
+ }
+
+ priv_edesc->d_dma = dma_map_single(dev, priv_req->d, priv_req->d_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, priv_edesc->d_dma)) {
+ dev_err(dev, "Unable to map exponent memory\n");
+ goto d_f2_fail;
+ }
+
+ priv_edesc->f_dma = dma_map_single(dev, priv_req->f, priv_req->f_len,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(dev, priv_edesc->f_dma)) {
+ dev_err(dev, "Unable to map output buffer memory\n");
+ goto f_f2_fail;
+ }
+
+ priv_edesc->g_dma = dma_map_single(dev, priv_req->g, priv_req->g_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, priv_edesc->g_dma)) {
+ dev_err(dev, "Unable to map input memory\n");
+ goto g_f2_fail;
+ }
+ priv_edesc->sg_flgs.d_len = priv_req->d_len;
+ priv_edesc->sg_flgs.n_len = priv_req->n_len;
+ priv_edesc->q_len = priv_req->q_len;
+ priv_edesc->p_len = priv_req->p_len;
+
+ /* TBD: Set SG flags in case input is SG */
+ return 0;
+g_f2_fail:
+ dma_unmap_single(dev, priv_edesc->f_dma, priv_req->f_len,
+ DMA_FROM_DEVICE);
+f_f2_fail:
+ dma_unmap_single(dev, priv_edesc->d_dma, priv_req->d_len,
+ DMA_TO_DEVICE);
+d_f2_fail:
+ dma_unmap_single(dev, priv_edesc->q_dma, priv_req->q_len,
+ DMA_TO_DEVICE);
+q_f2_fail:
+ dma_unmap_single(dev, priv_edesc->p_dma, priv_req->p_len,
+ DMA_TO_DEVICE);
+p_f2_fail:
+ dma_unmap_single(dev, priv_edesc->tmp2_dma, priv_req->q_len,
+ DMA_TO_DEVICE);
+tmp2_f2_fail:
+ dma_unmap_single(dev, priv_edesc->tmp1_dma, priv_req->p_len,
+ DMA_BIDIRECTIONAL);
+ kfree(priv_edesc->tmp2);
+tmp1_f2_fail:
+ kfree(priv_edesc->tmp1);
+ return -EINVAL;
+}
+
+static int caam_rsa_priv_f3_edesc(struct pkc_request *req,
+ struct rsa_edesc *edesc)
+{
+ struct crypto_pkc *tfm = crypto_pkc_reqtfm(req);
+ struct caam_pkc_context_s *ctxt = crypto_pkc_ctx(tfm);
+ struct device *dev = ctxt->dev;
+ struct rsa_priv_frm3_req_s *priv_req = &req->req_u.rsa_priv_f3;
+ struct rsa_priv_frm3_edesc_s *priv_edesc =
+ &edesc->dma_u.rsa_priv_f3_edesc;
+
+ priv_edesc->tmp1 = kzalloc(priv_req->p_len, GFP_DMA);
+
+ if (!priv_edesc->tmp1)
+ return -ENOMEM;
+
+ priv_edesc->tmp2 = kzalloc(priv_req->q_len, GFP_DMA);
+ if (!priv_edesc->tmp2) {
+ kfree(priv_edesc->tmp1);
+ return -ENOMEM;
+ }
+
+ priv_edesc->tmp1_dma =
+ dma_map_single(dev, priv_edesc->tmp1, priv_req->p_len,
+ DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(dev, priv_edesc->tmp1_dma)) {
+ dev_err(dev, "Unable to map modulus memory\n");
+ goto tmp1_f2_fail;
+ }
+
+ priv_edesc->tmp2_dma =
+ dma_map_single(dev, priv_edesc->tmp2, priv_req->q_len,
+ DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(dev, priv_edesc->tmp2_dma)) {
+ dev_err(dev, "Unable to map modulus memory\n");
+ goto tmp2_f2_fail;
+ }
+
+ priv_edesc->p_dma = dma_map_single(dev, priv_req->p, priv_req->p_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, priv_edesc->p_dma)) {
+ dev_err(dev, "Unable to map modulus memory\n");
+ goto p_f3_fail;
+ }
+
+ priv_edesc->q_dma = dma_map_single(dev, priv_req->q, priv_req->q_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, priv_edesc->q_dma)) {
+ dev_err(dev, "Unable to map exponent memory\n");
+ goto q_f3_fail;
+ }
+
+ priv_edesc->dp_dma =
+ dma_map_single(dev, priv_req->dp, priv_req->dp_len, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, priv_edesc->dp_dma)) {
+ dev_err(dev, "Unable to map dp memory\n");
+ goto dp_f3_fail;
+ }
+
+ priv_edesc->dq_dma =
+ dma_map_single(dev, priv_req->dq, priv_req->dq_len, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, priv_edesc->dq_dma)) {
+ dev_err(dev, "Unable to map dq memory\n");
+ goto dq_f3_fail;
+ }
+
+ priv_edesc->c_dma = dma_map_single(dev, priv_req->c, priv_req->c_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, priv_edesc->c_dma)) {
+ dev_err(dev, "Unable to map Coefficient memory\n");
+ goto c_f3_fail;
+ }
+
+ priv_edesc->f_dma = dma_map_single(dev, priv_req->f, priv_req->f_len,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(dev, priv_edesc->f_dma)) {
+ dev_err(dev, "Unable to map output buffer memory\n");
+ goto f_f3_fail;
+ }
+
+ priv_edesc->g_dma = dma_map_single(dev, priv_req->g, priv_req->g_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, priv_edesc->g_dma)) {
+ dev_err(dev, "Unable to map input memory\n");
+ goto g_f3_fail;
+ }
+
+ priv_edesc->sg_flgs.n_len = priv_req->f_len;
+ priv_edesc->q_len = priv_req->q_len;
+ priv_edesc->p_len = priv_req->p_len;
+
+ return 0;
+g_f3_fail:
+ dma_unmap_single(dev, priv_edesc->f_dma, priv_req->f_len,
+ DMA_FROM_DEVICE);
+f_f3_fail:
+ dma_unmap_single(dev, priv_edesc->c_dma, priv_req->c_len,
+ DMA_TO_DEVICE);
+c_f3_fail:
+ dma_unmap_single(dev, priv_edesc->dq_dma, priv_req->dq_len,
+ DMA_TO_DEVICE);
+dq_f3_fail:
+ dma_unmap_single(dev, priv_edesc->dp_dma, priv_req->dp_len,
+ DMA_TO_DEVICE);
+dp_f3_fail:
+ dma_unmap_single(dev, priv_edesc->q_dma, priv_req->q_len,
+ DMA_TO_DEVICE);
+q_f3_fail:
+ dma_unmap_single(dev, priv_edesc->p_dma, priv_req->p_len,
+ DMA_TO_DEVICE);
+p_f3_fail:
+ dma_unmap_single(dev, priv_edesc->tmp2_dma, priv_req->q_len,
+ DMA_TO_DEVICE);
+tmp2_f2_fail:
+ dma_unmap_single(dev, priv_edesc->tmp1_dma, priv_req->p_len,
+ DMA_BIDIRECTIONAL);
+ kfree(priv_edesc->tmp2);
+tmp1_f2_fail:
+ kfree(priv_edesc->tmp1);
+
+ return -EINVAL;
+}
+
+/* CAAM Descriptor creator for RSA Public Key operations */
+static void *caam_rsa_desc_init(struct pkc_request *req)
+{
+ void *desc = NULL;
+ struct rsa_edesc *edesc = NULL;
+
+ switch (req->type) {
+ case RSA_PUB:
+ {
+ edesc =
+ kzalloc(sizeof(*edesc) +
+ sizeof(struct rsa_pub_desc_s), GFP_DMA);
+
+ if (!edesc)
+ return NULL;
+
+ if (caam_rsa_pub_edesc(req, edesc)) {
+ kfree(edesc);
+ return NULL;
+ }
+
+ desc = caam_rsa_pub_desc(edesc);
+ break;
+ }
+ case RSA_PRIV_FORM1:
+ {
+ edesc =
+ kzalloc(sizeof(*edesc) +
+ sizeof(struct rsa_priv_frm1_desc_s),
+ GFP_DMA);
+ if (!edesc)
+ return NULL;
+
+ if (caam_rsa_priv_f1_edesc(req, edesc)) {
+ kfree(edesc);
+ return NULL;
+ }
+
+ desc = caam_rsa_priv_f1_desc(edesc);
+ break;
+ }
+ case RSA_PRIV_FORM2:
+ {
+ edesc =
+ kzalloc(sizeof(*edesc) +
+ sizeof(struct rsa_priv_frm2_desc_s),
+ GFP_DMA);
+ if (!edesc)
+ return NULL;
+
+ if (caam_rsa_priv_f2_edesc(req, edesc)) {
+ kfree(edesc);
+ return NULL;
+ }
+
+ desc = caam_rsa_priv_f2_desc(edesc);
+ break;
+ }
+ case RSA_PRIV_FORM3:
+ {
+ edesc = kzalloc(sizeof(*edesc) +
+ sizeof(struct rsa_priv_frm3_desc_s),
+ GFP_DMA);
+ if (!edesc)
+ return NULL;
+
+ if (caam_rsa_priv_f3_edesc(req, edesc)) {
+ kfree(edesc);
+ return NULL;
+ }
+
+ desc = caam_rsa_priv_f3_desc(edesc);
+ break;
+ }
+ default:
+ pr_debug("Unknown request type\n");
+ return NULL;
+ }
+
+ edesc->req_type = req->type;
+ return desc;
+}
+
+/* CAAM Descriptor creator for RSA Public Key operations */
+static void *caam_dsa_desc_init(struct pkc_request *req)
+{
+ void *desc = NULL;
+ struct dsa_edesc_s *edesc = NULL;
+
+ switch (req->type) {
+ case DSA_SIGN:
+ {
+ edesc = kzalloc(sizeof(*edesc) +
+ sizeof(struct dsa_sign_desc_s),
+ GFP_DMA);
+ if (!edesc)
+ return NULL;
+
+ if (caam_dsa_sign_edesc(req, edesc)) {
+ kfree(edesc);
+ return NULL;
+ }
+
+ desc = caam_dsa_sign_desc(edesc);
+ }
+ break;
+ case DSA_VERIFY:
+ {
+ edesc = kzalloc(sizeof(*edesc) +
+ sizeof(struct dsa_verify_desc_s),
+ GFP_DMA);
+ if (!edesc)
+ return NULL;
+
+ if (caam_dsa_verify_edesc(req, edesc)) {
+ kfree(edesc);
+ return NULL;
+ }
+
+ desc = caam_dsa_verify_desc(edesc);
+ }
+ break;
+ case DLC_KEYGEN:
+ {
+ edesc = kzalloc(sizeof(*edesc) +
+ sizeof(struct dlc_keygen_desc_s),
+ GFP_DMA);
+ if (!edesc)
+ return NULL;
+
+ if (caam_keygen_edesc(req, edesc)) {
+ kfree(edesc);
+ return NULL;
+ }
+
+ desc = caam_keygen_desc(edesc);
+ }
+ break;
+ case ECDSA_SIGN:
+ {
+ edesc = kzalloc(sizeof(*edesc) +
+ sizeof(struct ecdsa_sign_desc_s),
+ GFP_DMA);
+ if (!edesc)
+ return NULL;
+
+ if (caam_dsa_sign_edesc(req, edesc)) {
+ kfree(edesc);
+ return NULL;
+ }
+
+ desc = caam_dsa_sign_desc(edesc);
+ }
+ break;
+ case ECDSA_VERIFY:
+ {
+ edesc = kzalloc(sizeof(*edesc) +
+ sizeof(struct ecdsa_verify_desc_s),
+ GFP_DMA);
+ if (!edesc)
+ return NULL;
+
+ if (caam_dsa_verify_edesc(req, edesc)) {
+ kfree(edesc);
+ return NULL;
+ }
+
+ desc = caam_dsa_verify_desc(edesc);
+ }
+ break;
+ case ECC_KEYGEN:
+ {
+ edesc = kzalloc(sizeof(*edesc) +
+ sizeof(struct ecc_keygen_desc_s),
+ GFP_DMA);
+ if (!edesc)
+ return NULL;
+
+ if (caam_keygen_edesc(req, edesc)) {
+ kfree(edesc);
+ return NULL;
+ }
+
+ desc = caam_keygen_desc(edesc);
+ }
+ break;
+ default:
+ pr_debug("Unknown DSA Desc init request\n");
+ return NULL;
+ }
+ edesc->req_type = req->type;
+ return desc;
+}
+
+static int caam_dh_key_edesc(struct pkc_request *req, struct dh_edesc_s *edesc)
+{
+ struct crypto_pkc *tfm = crypto_pkc_reqtfm(req);
+ struct caam_pkc_context_s *ctxt = crypto_pkc_ctx(tfm);
+ struct device *dev = ctxt->dev;
+ struct dh_key_req_s *dh_req = &req->req_u.dh_req;
+
+ edesc->l_len = dh_req->q_len;
+ edesc->n_len = dh_req->s_len;
+ edesc->req_type = req->type;
+ edesc->curve_type = req->curve_type;
+ edesc->q_dma = dma_map_single(dev, dh_req->q, dh_req->q_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, edesc->q_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto q_map_fail;
+ }
+
+ edesc->w_dma = dma_map_single(dev, dh_req->pub_key, dh_req->pub_key_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, edesc->w_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto w_map_fail;
+ }
+
+ edesc->s_dma = dma_map_single(dev, dh_req->s, dh_req->s_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, edesc->s_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto s_map_fail;
+ }
+
+ edesc->z_dma = dma_map_single(dev, dh_req->z, dh_req->z_len,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(dev, edesc->z_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto z_map_fail;
+ }
+ if (req->type == ECDH_COMPUTE_KEY) {
+ edesc->ab_dma = dma_map_single(dev, dh_req->ab, dh_req->ab_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, edesc->ab_dma)) {
+ dev_err(dev, "Unable to map memory\n");
+ goto ab_map_fail;
+ }
+ }
+ return 0;
+ab_map_fail:
+ dma_unmap_single(dev, edesc->z_dma, dh_req->z_len, DMA_FROM_DEVICE);
+z_map_fail:
+ dma_unmap_single(dev, edesc->s_dma, dh_req->s_len, DMA_TO_DEVICE);
+s_map_fail:
+ dma_unmap_single(dev, edesc->w_dma, dh_req->pub_key_len, DMA_TO_DEVICE);
+w_map_fail:
+ dma_unmap_single(dev, edesc->q_dma, dh_req->q_len, DMA_TO_DEVICE);
+q_map_fail:
+ return -EINVAL;
+}
+
+/* DSA operation Handler */
+static int dsa_op(struct pkc_request *req)
+{
+ struct crypto_pkc *pkc_tfm = crypto_pkc_reqtfm(req);
+ struct caam_pkc_context_s *ctxt = crypto_pkc_ctx(pkc_tfm);
+ struct device *dev = ctxt->dev;
+ int ret = 0;
+ void *desc = NULL;
+
+ desc = caam_dsa_desc_init(req);
+ if (!desc) {
+ dev_err(dev, "Unable to allocate descriptor\n");
+ return -ENOMEM;
+ }
+
+ ret = caam_jr_enqueue(dev, desc, dsa_op_done, req);
+ if (!ret)
+ ret = -EINPROGRESS;
+
+ return ret;
+}
+
+/* CAAM Descriptor creator for DH Public Key operations */
+static void *caam_dh_desc_init(struct pkc_request *req)
+{
+ void *desc = NULL;
+ struct dh_edesc_s *edesc = NULL;
+
+ switch (req->type) {
+ case DH_COMPUTE_KEY:
+ case ECDH_COMPUTE_KEY:
+ {
+ edesc = kzalloc(sizeof(*edesc) +
+ sizeof(struct dh_key_desc_s),
+ GFP_DMA);
+ if (!edesc)
+ return NULL;
+
+ if (caam_dh_key_edesc(req, edesc)) {
+ kfree(edesc);
+ return NULL;
+ }
+ desc = caam_dh_key_desc(edesc);
+ }
+ break;
+ default:
+ pr_debug("Unknown DH Desc init request\n");
+ return NULL;
+ }
+ edesc->req_type = req->type;
+ return desc;
+}
+
+/* DH Job Completion handler */
+static void dh_op_done(struct device *dev, u32 *desc, u32 err, void *context)
+{
+ struct pkc_request *req = context;
+ struct dh_edesc_s *edesc;
+
+ edesc = (struct dh_edesc_s *)((char *)desc -
+ offsetof(struct dh_edesc_s, hw_desc));
+
+ if (err) {
+ char tmp[CAAM_ERROR_STR_MAX];
+ dev_err(dev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
+ }
+
+ dh_unmap(dev, edesc, req);
+ kfree(edesc);
+
+ pkc_request_complete(req, err);
+}
+
+static int dh_op(struct pkc_request *req)
+{
+ struct crypto_pkc *pkc_tfm = crypto_pkc_reqtfm(req);
+ struct caam_pkc_context_s *ctxt = crypto_pkc_ctx(pkc_tfm);
+ struct device *dev = ctxt->dev;
+ int ret = 0;
+ void *desc = NULL;
+ desc = caam_dh_desc_init(req);
+ if (!desc) {
+ dev_err(dev, "Unable to allocate descriptor\n");
+ return -ENOMEM;
+ }
+
+ ret = caam_jr_enqueue(dev, desc, dh_op_done, req);
+ if (!ret)
+ ret = -EINPROGRESS;
+
+ return ret;
+}
+
+/* RSA operation Handler */
+static int rsa_op(struct pkc_request *req)
+{
+ struct crypto_pkc *pkc_tfm = crypto_pkc_reqtfm(req);
+ struct caam_pkc_context_s *ctxt = crypto_pkc_ctx(pkc_tfm);
+ struct device *dev = ctxt->dev;
+ int ret = 0;
+ void *desc = NULL;
+
+ desc = caam_rsa_desc_init(req);
+ if (!desc) {
+ dev_err(dev, "Unable to allocate descriptor\n");
+ return -ENOMEM;
+ }
+
+ ret = caam_jr_enqueue(dev, desc, rsa_op_done, req);
+ if (!ret)
+ ret = -EINPROGRESS;
+
+ return ret;
+}
+
+/* PKC Descriptor Template */
+struct caam_pkc_template {
+ char name[CRYPTO_MAX_ALG_NAME];
+ char driver_name[CRYPTO_MAX_ALG_NAME];
+ char pkc_name[CRYPTO_MAX_ALG_NAME];
+ char pkc_driver_name[CRYPTO_MAX_ALG_NAME];
+ u32 type;
+ struct pkc_alg template_pkc;
+};
+
+static struct caam_pkc_template driver_pkc[] = {
+ /* RSA driver registeration hooks */
+ {
+ .name = "rsa",
+ .driver_name = "rsa-caam",
+ .pkc_name = "pkc(rsa)",
+ .pkc_driver_name = "pkc-rsa-caam",
+ .type = CRYPTO_ALG_TYPE_PKC_RSA,
+ .template_pkc = {
+ .pkc_op = rsa_op,
+ .min_keysize = 512,
+ .max_keysize = 4096,
+ },
+ },
+ /* DSA driver registeration hooks */
+ {
+ .name = "dsa",
+ .driver_name = "dsa-caam",
+ .pkc_name = "pkc(dsa)",
+ .pkc_driver_name = "pkc-dsa-caam",
+ .type = CRYPTO_ALG_TYPE_PKC_DSA,
+ .template_pkc = {
+ .pkc_op = dsa_op,
+ .min_keysize = 512,
+ .max_keysize = 4096,
+ },
+ },
+ /* DH driver registeration hooks */
+ {
+ .name = "dh",
+ .driver_name = "dh-caam",
+ .pkc_name = "pkc(dh)",
+ .pkc_driver_name = "pkc-dh-caam",
+ .type = CRYPTO_ALG_TYPE_PKC_DH,
+ .template_pkc = {
+ .pkc_op = dh_op,
+ .min_keysize = 512,
+ .max_keysize = 4096,
+ },
+ }
+};
+
+struct caam_pkc_alg {
+ struct list_head entry;
+ struct device *ctrldev;
+ struct crypto_alg crypto_alg;
+};
+
+/* Per session pkc's driver context creation function */
+static int caam_pkc_cra_init(struct crypto_tfm *tfm)
+{
+ struct caam_pkc_context_s *ctx = crypto_tfm_ctx(tfm);
+
+ ctx->dev = caam_jr_alloc();
+
+ if (IS_ERR(ctx->dev)) {
+ pr_err("Job Ring Device allocation for transform failed\n");
+ return PTR_ERR(ctx->dev);
+ }
+ return 0;
+}
+
+/* Per session pkc's driver context cleanup function */
+static void caam_pkc_cra_exit(struct crypto_tfm *tfm)
+{
+ /* Nothing to cleanup in private context */
+}
+
+static struct caam_pkc_alg *caam_pkc_alloc(struct device *ctrldev,
+ struct caam_pkc_template *template,
+ bool keyed)
+{
+ struct caam_pkc_alg *t_alg;
+ struct crypto_alg *alg;
+
+ t_alg = kzalloc(sizeof(*t_alg), GFP_KERNEL);
+ if (!t_alg) {
+ dev_err(ctrldev, "failed to allocate t_alg\n");
+ return NULL;
+ }
+
+ alg = &t_alg->crypto_alg;
+ alg->cra_pkc = template->template_pkc;
+
+ if (keyed) {
+ snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s",
+ template->pkc_name);
+ snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
+ template->pkc_driver_name);
+ } else {
+ snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s",
+ template->name);
+ snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
+ template->driver_name);
+ }
+ alg->cra_module = THIS_MODULE;
+ alg->cra_init = caam_pkc_cra_init;
+ alg->cra_exit = caam_pkc_cra_exit;
+ alg->cra_ctxsize = sizeof(struct caam_pkc_context_s);
+ alg->cra_priority = CAAM_PKC_PRIORITY;
+ alg->cra_alignmask = 0;
+ alg->cra_flags = CRYPTO_ALG_ASYNC | template->type;
+ alg->cra_type = &crypto_pkc_type;
+ t_alg->ctrldev = ctrldev;
+
+ return t_alg;
+}
+
+/* Public Key Cryptography module initialization handler */
+static int __init caam_pkc_init(void)
+{
+ struct device_node *dev_node;
+ struct platform_device *pdev;
+ struct device *ctrldev;
+ struct caam_drv_private *priv;
+ int i = 0, err = 0;
+
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+ if (!dev_node) {
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+ if (!dev_node)
+ return -ENODEV;
+ }
+
+ pdev = of_find_device_by_node(dev_node);
+ if (!pdev)
+ return -ENODEV;
+
+ ctrldev = &pdev->dev;
+ priv = dev_get_drvdata(ctrldev);
+ of_node_put(dev_node);
+
+ INIT_LIST_HEAD(&priv->pkc_list);
+
+ /* register crypto algorithms the device supports */
+ for (i = 0; i < ARRAY_SIZE(driver_pkc); i++) {
+ /* TODO: check if h/w supports alg */
+ struct caam_pkc_alg *t_alg;
+
+ /* register pkc algorithm */
+ t_alg = caam_pkc_alloc(ctrldev, &driver_pkc[i], true);
+ if (IS_ERR(t_alg)) {
+ err = PTR_ERR(t_alg);
+ dev_warn(ctrldev, "%s alg allocation failed\n",
+ driver_pkc[i].driver_name);
+ continue;
+ }
+
+ err = crypto_register_alg(&t_alg->crypto_alg);
+ if (err) {
+ dev_warn(ctrldev, "%s alg registration failed\n",
+ t_alg->crypto_alg.cra_driver_name);
+ kfree(t_alg);
+ } else {
+ list_add_tail(&t_alg->entry, &priv->pkc_list);
+ }
+ }
+
+ if (!list_empty(&priv->pkc_list))
+ dev_info(ctrldev, "%s algorithms registered in /proc/crypto\n",
+ (char *)of_get_property(dev_node, "compatible", NULL));
+
+ return err;
+}
+
+static void __exit caam_pkc_exit(void)
+{
+ struct device_node *dev_node;
+ struct platform_device *pdev;
+ struct device *ctrldev;
+ struct caam_drv_private *priv;
+ struct caam_pkc_alg *t_alg, *n;
+
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+
+ if (!dev_node) {
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+ if (!dev_node)
+ return;
+ }
+
+ pdev = of_find_device_by_node(dev_node);
+
+ if (!pdev)
+ return;
+
+ ctrldev = &pdev->dev;
+ of_node_put(dev_node);
+ priv = dev_get_drvdata(ctrldev);
+
+ if (!priv->pkc_list.next)
+ return;
+
+ list_for_each_entry_safe(t_alg, n, &priv->pkc_list, entry) {
+ crypto_unregister_alg(&t_alg->crypto_alg);
+ list_del(&t_alg->entry);
+ kfree(t_alg);
+ }
+}
+
+module_init(caam_pkc_init);
+module_exit(caam_pkc_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("FSL CAAM support for PKC functions of crypto API");
+MODULE_AUTHOR("Yashpal Dutta <yashpal.dutta@freescale.com>");
diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c
index d1939a9..466dfe5 100644
--- a/drivers/crypto/caam/caamrng.c
+++ b/drivers/crypto/caam/caamrng.c
@@ -76,7 +76,7 @@ struct caam_rng_ctx {
struct buf_data bufs[2];
};
-static struct caam_rng_ctx rng_ctx;
+static struct caam_rng_ctx *rng_ctx;
static inline void rng_unmap_buf(struct device *jrdev, struct buf_data *bd)
{
@@ -137,7 +137,7 @@ static inline int submit_job(struct caam_rng_ctx *ctx, int to_current)
static int caam_read(struct hwrng *rng, void *data, size_t max, bool wait)
{
- struct caam_rng_ctx *ctx = &rng_ctx;
+ struct caam_rng_ctx *ctx = rng_ctx;
struct buf_data *bd = &ctx->bufs[ctx->current_buf];
int next_buf_idx, copied_idx;
int err;
@@ -237,12 +237,12 @@ static void caam_cleanup(struct hwrng *rng)
struct buf_data *bd;
for (i = 0; i < 2; i++) {
- bd = &rng_ctx.bufs[i];
+ bd = &rng_ctx->bufs[i];
if (atomic_read(&bd->empty) == BUF_PENDING)
wait_for_completion(&bd->filled);
}
- rng_unmap_ctx(&rng_ctx);
+ rng_unmap_ctx(rng_ctx);
}
static void caam_init_buf(struct caam_rng_ctx *ctx, int buf_id)
@@ -273,15 +273,18 @@ static struct hwrng caam_rng = {
static void __exit caam_rng_exit(void)
{
+ caam_jr_free(rng_ctx->jrdev);
hwrng_unregister(&caam_rng);
+ kfree(rng_ctx);
}
static int __init caam_rng_init(void)
{
+ struct device *dev;
struct device_node *dev_node;
struct platform_device *pdev;
struct device *ctrldev;
- struct caam_drv_private *priv;
+ void *priv;
dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
if (!dev_node) {
@@ -298,9 +301,24 @@ static int __init caam_rng_init(void)
priv = dev_get_drvdata(ctrldev);
of_node_put(dev_node);
- caam_init_rng(&rng_ctx, priv->jrdev[0]);
+ /*
+ * If priv is NULL, it's probably because the caam driver wasn't
+ * properly initialized (e.g. RNG4 init failed). Thus, bail out here.
+ */
+ if (!priv)
+ return -ENODEV;
+
+ dev = caam_jr_alloc();
+ if (IS_ERR(dev)) {
+ pr_err("Job Ring Device allocation for transform failed\n");
+ return PTR_ERR(dev);
+ }
+ rng_ctx = kmalloc(sizeof(struct caam_rng_ctx), GFP_DMA);
+ if (!rng_ctx)
+ return -ENOMEM;
+ caam_init_rng(rng_ctx, dev);
- dev_info(priv->jrdev[0], "registering rng-caam\n");
+ dev_info(dev, "registering rng-caam\n");
return hwrng_register(&caam_rng);
}
diff --git a/drivers/crypto/caam/compat.h b/drivers/crypto/caam/compat.h
index 762aeff..f227922 100644
--- a/drivers/crypto/caam/compat.h
+++ b/drivers/crypto/caam/compat.h
@@ -26,6 +26,7 @@
#include <net/xfrm.h>
#include <crypto/algapi.h>
+#include <crypto/null.h>
#include <crypto/aes.h>
#include <crypto/des.h>
#include <crypto/sha.h>
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index b010d42..17805eb 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -11,84 +11,80 @@
#include "jr.h"
#include "desc_constr.h"
#include "error.h"
-#include "ctrl.h"
-static int caam_remove(struct platform_device *pdev)
-{
- struct device *ctrldev;
- struct caam_drv_private *ctrlpriv;
- struct caam_drv_private_jr *jrpriv;
- struct caam_full __iomem *topregs;
- int ring, ret = 0;
-
- ctrldev = &pdev->dev;
- ctrlpriv = dev_get_drvdata(ctrldev);
- topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
-
- /* shut down JobRs */
- for (ring = 0; ring < ctrlpriv->total_jobrs; ring++) {
- ret |= caam_jr_shutdown(ctrlpriv->jrdev[ring]);
- jrpriv = dev_get_drvdata(ctrlpriv->jrdev[ring]);
- irq_dispose_mapping(jrpriv->irq);
- }
-
- /* Shut down debug views */
-#ifdef CONFIG_DEBUG_FS
- debugfs_remove_recursive(ctrlpriv->dfs_root);
+#ifdef CONFIG_FSL_QMAN
+#include "qi.h"
#endif
- /* Unmap controller region */
- iounmap(&topregs->ctrl);
-
- kfree(ctrlpriv->jrdev);
- kfree(ctrlpriv);
-
- return ret;
-}
-
/*
* Descriptor to instantiate RNG State Handle 0 in normal mode and
* load the JDKEK, TDKEK and TDSK registers
*/
-static void build_instantiation_desc(u32 *desc)
+static void build_instantiation_desc(u32 *desc, int handle, int do_sk)
{
- u32 *jump_cmd;
+ u32 *jump_cmd, op_flags;
init_job_desc(desc, 0);
+ op_flags = OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+ (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INIT;
+
/* INIT RNG in non-test mode */
- append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
- OP_ALG_AS_INIT);
+ append_operation(desc, op_flags);
+
+ if (!handle && do_sk) {
+ /*
+ * For SH0, Secure Keys must be generated as well
+ */
+
+ /* wait for done */
+ jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1);
+ set_jump_tgt_here(desc, jump_cmd);
+
+ /*
+ * load 1 to clear written reg:
+ * resets the done interrrupt and returns the RNG to idle.
+ */
+ append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW);
+
+ /* Initialize State Handle */
+ append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+ OP_ALG_AAI_RNG4_SK);
+ }
- /* wait for done */
- jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1);
- set_jump_tgt_here(desc, jump_cmd);
+ append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TYPE_HALT);
+}
- /*
- * load 1 to clear written reg:
- * resets the done interrupt and returns the RNG to idle.
- */
- append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW);
+/* Descriptor for deinstantiation of State Handle 0 of the RNG block. */
+static void build_deinstantiation_desc(u32 *desc, int handle)
+{
+ init_job_desc(desc, 0);
- /* generate secure keys (non-test) */
+ /* Uninstantiate State Handle 0 */
append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
- OP_ALG_RNG4_SK);
+ (handle << OP_ALG_AAI_SHIFT) | OP_ALG_AS_INITFINAL);
+
+ append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TYPE_HALT);
}
-static int instantiate_rng(struct device *ctrldev)
+/*
+ * run_descriptor_deco0 - runs a descriptor on DECO0, under direct control of
+ * the software (no JR/QI used).
+ * @ctrldev - pointer to device
+ * @status - descriptor status, after being run
+ *
+ * Return: - 0 if no error occurred
+ * - -ENODEV if the DECO couldn't be acquired
+ * - -EAGAIN if an error occurred while executing the descriptor
+ */
+static inline int run_descriptor_deco0(struct device *ctrldev, u32 *desc,
+ u32 *status)
{
struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
struct caam_full __iomem *topregs;
unsigned int timeout = 100000;
- u32 *desc;
- int i, ret = 0;
-
- desc = kmalloc(CAAM_CMD_SZ * 6, GFP_KERNEL | GFP_DMA);
- if (!desc) {
- dev_err(ctrldev, "can't allocate RNG init descriptor memory\n");
- return -ENOMEM;
- }
- build_instantiation_desc(desc);
+ u32 deco_dbg_reg, flags;
+ int i;
/* Set the bit to request direct access to DECO0 */
topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
@@ -100,39 +96,225 @@ static int instantiate_rng(struct device *ctrldev)
if (!timeout) {
dev_err(ctrldev, "failed to acquire DECO 0\n");
- ret = -EIO;
- goto out;
+ clrbits32(&topregs->ctrl.deco_rq, DECORR_RQD0ENABLE);
+ return -ENODEV;
}
for (i = 0; i < desc_len(desc); i++)
- topregs->deco.descbuf[i] = *(desc + i);
+ wr_reg32(&topregs->deco.descbuf[i], *(desc + i));
+
+ flags = DECO_JQCR_WHL;
+ /*
+ * If the descriptor length is longer than 4 words, then the
+ * FOUR bit in JRCTRL register must be set.
+ */
+ if (desc_len(desc) >= 4)
+ flags |= DECO_JQCR_FOUR;
- wr_reg32(&topregs->deco.jr_ctl_hi, DECO_JQCR_WHL | DECO_JQCR_FOUR);
+ /* Instruct the DECO to execute it */
+ wr_reg32(&topregs->deco.jr_ctl_hi, flags);
timeout = 10000000;
- while ((rd_reg32(&topregs->deco.desc_dbg) & DECO_DBG_VALID) &&
- --timeout)
+ do {
+ deco_dbg_reg = rd_reg32(&topregs->deco.desc_dbg);
+ /*
+ * If an error occured in the descriptor, then
+ * the DECO status field will be set to 0x0D
+ */
+ if ((deco_dbg_reg & DESC_DBG_DECO_STAT_MASK) ==
+ DESC_DBG_DECO_STAT_HOST_ERR)
+ break;
cpu_relax();
+ } while ((deco_dbg_reg & DESC_DBG_DECO_STAT_VALID) && --timeout);
- if (!timeout) {
- dev_err(ctrldev, "failed to instantiate RNG\n");
- ret = -EIO;
- }
+ *status = rd_reg32(&topregs->deco.op_status_hi) &
+ DECO_OP_STATUS_HI_ERR_MASK;
+ /* Mark the DECO as free */
clrbits32(&topregs->ctrl.deco_rq, DECORR_RQD0ENABLE);
-out:
+
+ if (!timeout)
+ return -EAGAIN;
+
+ return 0;
+}
+
+/*
+ * instantiate_rng - builds and executes a descriptor on DECO0,
+ * which initializes the RNG block.
+ * @ctrldev - pointer to device
+ * @state_handle_mask - bitmask containing the instantiation status
+ * for the RNG4 state handles which exist in
+ * the RNG4 block: 1 if it's been instantiated
+ * by an external entry, 0 otherwise.
+ * @gen_sk - generate data to be loaded into the JDKEK, TDKEK and TDSK;
+ * Caution: this can be done only once; if the keys need to be
+ * regenerated, a POR is required
+ *
+ * Return: - 0 if no error occurred
+ * - -ENOMEM if there isn't enough memory to allocate the descriptor
+ * - -ENODEV if DECO0 couldn't be acquired
+ * - -EAGAIN if an error occurred when executing the descriptor
+ * f.i. there was a RNG hardware error due to not "good enough"
+ * entropy being aquired.
+ */
+static int instantiate_rng(struct device *ctrldev, int state_handle_mask,
+ int gen_sk)
+{
+ struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
+ struct caam_full __iomem *topregs;
+ struct rng4tst __iomem *r4tst;
+ u32 *desc, status, rdsta_val;
+ int ret = 0, sh_idx;
+
+ topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
+ r4tst = &topregs->ctrl.r4tst[0];
+
+ desc = kmalloc(CAAM_CMD_SZ * 7, GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+ for (sh_idx = 0; sh_idx < RNG4_MAX_HANDLES; sh_idx++) {
+ /*
+ * If the corresponding bit is set, this state handle
+ * was initialized by somebody else, so it's left alone.
+ */
+ if ((1 << sh_idx) & state_handle_mask)
+ continue;
+
+ /* Create the descriptor for instantiating RNG State Handle */
+ build_instantiation_desc(desc, sh_idx, gen_sk);
+
+ /* Try to run it through DECO0 */
+ ret = run_descriptor_deco0(ctrldev, desc, &status);
+
+ /*
+ * If ret is not 0, or descriptor status is not 0, then
+ * something went wrong. No need to try the next state
+ * handle (if available), bail out here.
+ * Also, if for some reason, the State Handle didn't get
+ * instantiated although the descriptor has finished
+ * without any error (HW optimizations for later
+ * CAAM eras), then try again.
+ */
+ rdsta_val =
+ rd_reg32(&topregs->ctrl.r4tst[0].rdsta) & RDSTA_IFMASK;
+ if (status || !(rdsta_val & (1 << sh_idx)))
+ ret = -EAGAIN;
+ if (ret)
+ break;
+
+ dev_info(ctrldev, "Instantiated RNG4 SH%d\n", sh_idx);
+ /* Clear the contents before recreating the descriptor */
+ memset(desc, 0x00, CAAM_CMD_SZ * 7);
+ }
+
kfree(desc);
+
return ret;
}
/*
- * By default, the TRNG runs for 200 clocks per sample;
- * 1600 clocks per sample generates better entropy.
+ * deinstantiate_rng - builds and executes a descriptor on DECO0,
+ * which deinitializes the RNG block.
+ * @ctrldev - pointer to device
+ * @state_handle_mask - bitmask containing the instantiation status
+ * for the RNG4 state handles which exist in
+ * the RNG4 block: 1 if it's been instantiated
+ *
+ * Return: - 0 if no error occurred
+ * - -ENOMEM if there isn't enough memory to allocate the descriptor
+ * - -ENODEV if DECO0 couldn't be acquired
+ * - -EAGAIN if an error occurred when executing the descriptor
*/
-static void kick_trng(struct platform_device *pdev)
+static int deinstantiate_rng(struct device *ctrldev, int state_handle_mask)
{
- struct device *ctrldev = &pdev->dev;
- struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
+ u32 *desc, status;
+ int sh_idx, ret = 0;
+
+ desc = kmalloc(CAAM_CMD_SZ * 3, GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+ for (sh_idx = 0; sh_idx < RNG4_MAX_HANDLES; sh_idx++) {
+ /*
+ * If the corresponding bit is set, then it means the state
+ * handle was initialized by us, and thus it needs to be
+ * deintialized as well
+ */
+ if ((1 << sh_idx) & state_handle_mask) {
+ /*
+ * Create the descriptor for deinstantating this state
+ * handle
+ */
+ build_deinstantiation_desc(desc, sh_idx);
+
+ /* Try to run it through DECO0 */
+ ret = run_descriptor_deco0(ctrldev, desc, &status);
+
+ if (ret || status) {
+ dev_err(ctrldev,
+ "Failed to deinstantiate RNG4 SH%d\n",
+ sh_idx);
+ break;
+ }
+ dev_info(ctrldev, "Deinstantiated RNG4 SH%d\n", sh_idx);
+ }
+ }
+
+ kfree(desc);
+
+ return ret;
+}
+
+static int caam_remove(struct platform_device *pdev)
+{
+ struct device *ctrldev;
+ struct caam_drv_private *ctrlpriv;
+ struct caam_full __iomem *topregs;
+ int ring, ret = 0;
+
+ ctrldev = &pdev->dev;
+ ctrlpriv = dev_get_drvdata(ctrldev);
+ topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
+
+ /* Remove platform devices for JobRs */
+ for (ring = 0; ring < ctrlpriv->total_jobrs; ring++) {
+ if (ctrlpriv->jrpdev[ring])
+ of_device_unregister(ctrlpriv->jrpdev[ring]);
+ }
+
+#ifdef CONFIG_FSL_QMAN
+ if (ctrlpriv->qidev)
+ caam_qi_shutdown(ctrlpriv->qidev);
+#endif
+ /* De-initialize RNG state handles initialized by this driver. */
+ if (ctrlpriv->rng4_sh_init)
+ deinstantiate_rng(ctrldev, ctrlpriv->rng4_sh_init);
+
+ /* Shut down debug views */
+#ifdef CONFIG_DEBUG_FS
+ debugfs_remove_recursive(ctrlpriv->dfs_root);
+#endif
+
+ /* Unmap controller region */
+ iounmap(&topregs->ctrl);
+
+ kfree(ctrlpriv->jrpdev);
+ kfree(ctrlpriv);
+
+ return ret;
+}
+
+/*
+ * kick_trng - sets the various parameters for enabling the initialization
+ * of the RNG4 block in CAAM
+ * @pdev - pointer to the caam device
+ * @ent_delay - Defines the length (in system clocks) of each entropy sample.
+ */
+static void kick_trng(struct device *dev, int ent_delay)
+{
+ struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev);
struct caam_full __iomem *topregs;
struct rng4tst __iomem *r4tst;
u32 val;
@@ -142,51 +324,120 @@ static void kick_trng(struct platform_device *pdev)
/* put RNG4 into program mode */
setbits32(&r4tst->rtmctl, RTMCTL_PRGM);
- /* 1600 clocks per sample */
+
+ /*
+ * Performance-wise, it does not make sense to
+ * set the delay to a value that is lower
+ * than the last one that worked (i.e. the state handles
+ * were instantiated properly. Thus, instead of wasting
+ * time trying to set the values controlling the sample
+ * frequency, the function simply returns.
+ */
+ val = (rd_reg32(&r4tst->rtsdctl) & RTSDCTL_ENT_DLY_MASK)
+ >> RTSDCTL_ENT_DLY_SHIFT;
+ if (ent_delay <= val) {
+ /* put RNG4 into run mode */
+ clrbits32(&r4tst->rtmctl, RTMCTL_PRGM);
+ return;
+ }
+
val = rd_reg32(&r4tst->rtsdctl);
- val = (val & ~RTSDCTL_ENT_DLY_MASK) | (1600 << RTSDCTL_ENT_DLY_SHIFT);
+ val = (val & ~RTSDCTL_ENT_DLY_MASK) |
+ (ent_delay << RTSDCTL_ENT_DLY_SHIFT);
wr_reg32(&r4tst->rtsdctl, val);
- /* min. freq. count */
- wr_reg32(&r4tst->rtfrqmin, 400);
- /* max. freq. count */
- wr_reg32(&r4tst->rtfrqmax, 6400);
+ /* min. freq. count, equal to 1/4 of the entropy sample length */
+ wr_reg32(&r4tst->rtfrqmin, ent_delay >> 2);
+ /* max. freq. count, equal to 8 times the entropy sample length */
+ wr_reg32(&r4tst->rtfrqmax, ent_delay << 3);
/* put RNG4 into run mode */
clrbits32(&r4tst->rtmctl, RTMCTL_PRGM);
}
/**
* caam_get_era() - Return the ERA of the SEC on SoC, based
- * on the SEC_VID register.
- * Returns the ERA number (1..4) or -ENOTSUPP if the ERA is unknown.
- * @caam_id - the value of the SEC_VID register
+ * on "sec-era" propery in the DTS. This property is updated by u-boot.
**/
-int caam_get_era(u64 caam_id)
+int caam_get_era(void)
{
- struct sec_vid *sec_vid = (struct sec_vid *)&caam_id;
- static const struct {
- u16 ip_id;
- u8 maj_rev;
- u8 era;
- } caam_eras[] = {
- {0x0A10, 1, 1},
- {0x0A10, 2, 2},
- {0x0A12, 1, 3},
- {0x0A14, 1, 3},
- {0x0A14, 2, 4},
- {0x0A16, 1, 4},
- {0x0A11, 1, 4}
- };
- int i;
-
- for (i = 0; i < ARRAY_SIZE(caam_eras); i++)
- if (caam_eras[i].ip_id == sec_vid->ip_id &&
- caam_eras[i].maj_rev == sec_vid->maj_rev)
- return caam_eras[i].era;
+ struct device_node *caam_node;
+ for_each_compatible_node(caam_node, NULL, "fsl,sec-v4.0") {
+ const uint32_t *prop = (uint32_t *)of_get_property(caam_node,
+ "fsl,sec-era",
+ NULL);
+ return prop ? *prop : -ENOTSUPP;
+ }
return -ENOTSUPP;
}
EXPORT_SYMBOL(caam_get_era);
+static int caam_rng_init(struct device *dev)
+{
+ int gen_sk, ent_delay = RTSDCTL_ENT_DLY_MIN;
+ struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev);
+ u64 cha_vid;
+ struct caam_full __iomem *topregs;
+ int ret = 0;
+
+ topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
+ cha_vid = rd_reg64(&topregs->ctrl.perfmon.cha_id);
+ /*
+ * If SEC has RNG version >= 4 and RNG state handle has not been
+ * already instantiated, do RNG instantiation
+ */
+ if ((cha_vid & CHA_ID_RNG_MASK) >> CHA_ID_RNG_SHIFT >= 4) {
+ ctrlpriv->rng4_sh_init =
+ rd_reg32(&topregs->ctrl.r4tst[0].rdsta);
+ /*
+ * If the secure keys (TDKEK, JDKEK, TDSK), were already
+ * generated, signal this to the function that is instantiating
+ * the state handles. An error would occur if RNG4 attempts
+ * to regenerate these keys before the next POR.
+ */
+ gen_sk = ctrlpriv->rng4_sh_init & RDSTA_SKVN ? 0 : 1;
+ ctrlpriv->rng4_sh_init &= RDSTA_IFMASK;
+ do {
+ int inst_handles =
+ rd_reg32(&topregs->ctrl.r4tst[0].rdsta) &
+ RDSTA_IFMASK;
+ /*
+ * If either SH were instantiated by somebody else
+ * (e.g. u-boot) then it is assumed that the entropy
+ * parameters are properly set and thus the function
+ * setting these (kick_trng(...)) is skipped.
+ * Also, if a handle was instantiated, do not change
+ * the TRNG parameters.
+ */
+ if (!(ctrlpriv->rng4_sh_init || inst_handles)) {
+ kick_trng(dev, ent_delay);
+ ent_delay += 400;
+ }
+ /*
+ * if instantiate_rng(...) fails, the loop will rerun
+ * and the kick_trng(...) function will modfiy the
+ * upper and lower limits of the entropy sampling
+ * interval, leading to a sucessful initialization of
+ * the RNG.
+ */
+ ret = instantiate_rng(dev, inst_handles,
+ gen_sk);
+ } while ((ret == -EAGAIN) && (ent_delay < RTSDCTL_ENT_DLY_MAX));
+ if (ret) {
+ dev_err(dev, "failed to instantiate RNG");
+ return ret;
+ }
+ /*
+ * Set handles init'ed by this module as the complement of the
+ * already initialized ones
+ */
+ ctrlpriv->rng4_sh_init = ~ctrlpriv->rng4_sh_init & RDSTA_IFMASK;
+
+ /* Enable RDB bit so that RNG works faster */
+ setbits32(&topregs->ctrl.scfgr, SCFGR_RDBENABLE);
+ }
+ return 0;
+}
+
/* Probe routine for CAAM top (controller) level */
static int caam_probe(struct platform_device *pdev)
{
@@ -200,7 +451,6 @@ static int caam_probe(struct platform_device *pdev)
#ifdef CONFIG_DEBUG_FS
struct caam_perfmon *perfmon;
#endif
- u64 cha_vid;
ctrlpriv = kzalloc(sizeof(struct caam_drv_private), GFP_KERNEL);
if (!ctrlpriv)
@@ -255,8 +505,9 @@ static int caam_probe(struct platform_device *pdev)
rspec++;
}
- ctrlpriv->jrdev = kzalloc(sizeof(struct device *) * rspec, GFP_KERNEL);
- if (ctrlpriv->jrdev == NULL) {
+ ctrlpriv->jrpdev = kzalloc(sizeof(struct platform_device *) * rspec,
+ GFP_KERNEL);
+ if (ctrlpriv->jrpdev == NULL) {
iounmap(&topregs->ctrl);
return -ENOMEM;
}
@@ -264,13 +515,24 @@ static int caam_probe(struct platform_device *pdev)
ring = 0;
ctrlpriv->total_jobrs = 0;
for_each_compatible_node(np, NULL, "fsl,sec-v4.0-job-ring") {
- caam_jr_probe(pdev, np, ring);
+ ctrlpriv->jrpdev[ring] =
+ of_platform_device_create(np, NULL, dev);
+ if (!ctrlpriv->jrpdev[ring]) {
+ pr_warn("JR%d Platform device creation error\n", ring);
+ continue;
+ }
ctrlpriv->total_jobrs++;
ring++;
}
if (!ring) {
for_each_compatible_node(np, NULL, "fsl,sec4.0-job-ring") {
- caam_jr_probe(pdev, np, ring);
+ ctrlpriv->jrpdev[ring] =
+ of_platform_device_create(np, NULL, dev);
+ if (!ctrlpriv->jrpdev[ring]) {
+ pr_warn("JR%d Platform device creation error\n",
+ ring);
+ continue;
+ }
ctrlpriv->total_jobrs++;
ring++;
}
@@ -283,6 +545,12 @@ static int caam_probe(struct platform_device *pdev)
ctrlpriv->qi = (struct caam_queue_if __force *)&topregs->qi;
/* This is all that's required to physically enable QI */
wr_reg32(&topregs->qi.qi_control_lo, QICTL_DQEN);
+
+ /* If QMAN driver is present, init CAAM-QI backend */
+#ifdef CONFIG_FSL_QMAN
+ if (caam_qi_init(pdev, nprop))
+ dev_err(dev, "caam qi i/f init failed\n");
+#endif
}
/* If no QI and no rings specified, quit and go home */
@@ -292,32 +560,20 @@ static int caam_probe(struct platform_device *pdev)
return -ENOMEM;
}
- cha_vid = rd_reg64(&topregs->ctrl.perfmon.cha_id);
-
- /*
- * If SEC has RNG version >= 4 and RNG state handle has not been
- * already instantiated ,do RNG instantiation
- */
- if ((cha_vid & CHA_ID_RNG_MASK) >> CHA_ID_RNG_SHIFT >= 4 &&
- !(rd_reg32(&topregs->ctrl.r4tst[0].rdsta) & RDSTA_IF0)) {
- kick_trng(pdev);
- ret = instantiate_rng(dev);
- if (ret) {
- caam_remove(pdev);
- return ret;
- }
-
- /* Enable RDB bit so that RNG works faster */
- setbits32(&topregs->ctrl.scfgr, SCFGR_RDBENABLE);
+ ret = caam_rng_init(dev);
+ if (ret) {
+ caam_remove(pdev);
+ return ret;
}
/* NOTE: RTIC detection ought to go here, around Si time */
caam_id = rd_reg64(&topregs->ctrl.perfmon.caam_id);
+ ctrlpriv->era = caam_get_era();
/* Report "alive" for developer to see */
dev_info(dev, "device ID = 0x%016llx (Era %d)\n", caam_id,
- caam_get_era(caam_id));
+ ctrlpriv->era);
dev_info(dev, "job rings = %d, qi = %d\n",
ctrlpriv->total_jobrs, ctrlpriv->qi_present);
@@ -404,6 +660,92 @@ static int caam_probe(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM
+static int caam_stop_qi(struct caam_full __iomem *topregs)
+{
+ int qi_stopped, loop = 0;
+
+ setbits32(&topregs->qi.qi_control_lo, QICTL_STOP);
+
+ /*
+ * Wait till QI Job's in Holding tank/deco are completed.
+ * No dequeue from QI will be happen till QI interface is
+ * reenabled.
+ */
+ while (loop <= 100000) {
+ qi_stopped = rd_reg32(&topregs->qi.qi_status) &
+ QISTA_STOPD;
+ if (qi_stopped) {
+ wr_reg32(&topregs->qi.qi_control_lo,
+ QICTL_STOP);
+ return 0;
+ }
+ loop++;
+ }
+
+ /* Failed to stop QI interface. Reenable QI Interface */
+ wr_reg32(&topregs->qi.qi_control_lo, QICTL_DQEN);
+ return -EBUSY;
+}
+
+/* Suspend handler for caam device */
+static int caam_suspend(struct device *dev)
+{
+ struct caam_drv_private *caam_priv;
+ struct caam_full __iomem *topregs;
+ struct caam_ctrl __iomem *ctrl;
+ int ret = 0;
+
+ caam_priv = dev_get_drvdata(dev);
+ ctrl = caam_priv->ctrl;
+ topregs = (struct caam_full __iomem *)ctrl;
+
+ /* QI Interface graceful stoppping during suspend */
+ if (caam_priv->qi_present) {
+ int qi_dqen;
+
+ qi_dqen = rd_reg32(&topregs->qi.qi_control_lo) &
+ QICTL_DQEN;
+ if (qi_dqen)
+ ret = caam_stop_qi(topregs);
+ }
+
+ return ret;
+}
+
+/* Resume handler for caam device */
+static int caam_resume(struct device *dev)
+{
+ struct caam_drv_private *caam_priv;
+ struct caam_full __iomem *topregs;
+ struct caam_ctrl __iomem *ctrl;
+ int ret;
+
+ caam_priv = dev_get_drvdata(dev);
+ ctrl = caam_priv->ctrl;
+ topregs = (struct caam_full __iomem *)ctrl;
+ /*
+ * Enable DECO watchdogs and, if this is a PHYS_ADDR_T_64BIT kernel,
+ * long pointers in master configuration register
+ */
+ setbits32(&topregs->ctrl.mcr, MCFGR_WDENABLE |
+ (sizeof(dma_addr_t) == sizeof(u64) ? MCFGR_LONG_PTR : 0));
+
+ /* Enable QI interface of SEC */
+ if (caam_priv->qi_present)
+ wr_reg32(&topregs->qi.qi_control_lo, QICTL_DQEN);
+
+ ret = caam_rng_init(dev);
+
+ return ret;
+}
+
+const struct dev_pm_ops caam_pm_ops = {
+ .suspend = caam_suspend,
+ .resume = caam_resume,
+};
+#endif /* CONFIG_PM */
+
static struct of_device_id caam_match[] = {
{
.compatible = "fsl,sec-v4.0",
@@ -420,6 +762,9 @@ static struct platform_driver caam_driver = {
.name = "caam",
.owner = THIS_MODULE,
.of_match_table = caam_match,
+#ifdef CONFIG_PM
+ .pm = &caam_pm_ops,
+#endif
},
.probe = caam_probe,
.remove = caam_remove,
diff --git a/drivers/crypto/caam/ctrl.h b/drivers/crypto/caam/ctrl.h
index 980d44e..cac5402 100644
--- a/drivers/crypto/caam/ctrl.h
+++ b/drivers/crypto/caam/ctrl.h
@@ -8,6 +8,6 @@
#define CTRL_H
/* Prototypes for backend-level services exposed to APIs */
-int caam_get_era(u64 caam_id);
+int caam_get_era(void);
#endif /* CTRL_H */
diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h
index 53b296f..4743d8e 100644
--- a/drivers/crypto/caam/desc.h
+++ b/drivers/crypto/caam/desc.h
@@ -2,7 +2,7 @@
* CAAM descriptor composition header
* Definitions to support CAAM descriptor instruction generation
*
- * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright 2008-2012 Freescale Semiconductor, Inc.
*/
#ifndef DESC_H
@@ -237,6 +237,7 @@ struct sec4_sg_entry {
#define LDST_SRCDST_WORD_DESCBUF_SHARED (0x42 << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_WORD_DESCBUF_JOB_WE (0x45 << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_WORD_DESCBUF_SHARED_WE (0x46 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_INFO_FIFO_SZM (0x71 << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_WORD_INFO_FIFO (0x7a << LDST_SRCDST_SHIFT)
/* Offset in source/destination */
@@ -279,6 +280,28 @@ struct sec4_sg_entry {
#define LDLEN_SET_OFIFO_OFFSET_SHIFT 0
#define LDLEN_SET_OFIFO_OFFSET_MASK (3 << LDLEN_SET_OFIFO_OFFSET_SHIFT)
+/* CCB Clear Written Register bits */
+#define CLRW_CLR_C1MODE 0x1
+#define CLRW_CLR_C1DATAS 0x4
+#define CLRW_CLR_C1ICV 0x8
+#define CLRW_CLR_C1CTX 0x20
+#define CLRW_CLR_C1KEY 0x40
+#define CLRW_CLR_PK_A 0x1000
+#define CLRW_CLR_PK_B 0x2000
+#define CLRW_CLR_PK_N 0x4000
+#define CLRW_CLR_PK_E 0x8000
+#define CLRW_CLR_C2MODE 0x10000
+#define CLRW_CLR_C2KEYS 0x20000
+#define CLRW_CLR_C2DATAS 0x40000
+#define CLRW_CLR_C2CTX 0x200000
+#define CLRW_CLR_C2KEY 0x400000
+#define CLRW_RESET_CLS2_DONE 0x04000000u /* era 4 */
+#define CLRW_RESET_CLS1_DONE 0x08000000u /* era 4 */
+#define CLRW_RESET_CLS2_CHA 0x10000000u /* era 4 */
+#define CLRW_RESET_CLS1_CHA 0x20000000u /* era 4 */
+#define CLRW_RESET_OFIFO 0x40000000u /* era 3 */
+#define CLRW_RESET_IFIFO_DFIFO 0x80000000u /* era 3 */
+
/*
* FIFO_LOAD/FIFO_STORE/SEQ_FIFO_LOAD/SEQ_FIFO_STORE
* Command Constructs
@@ -438,6 +461,9 @@ struct sec4_sg_entry {
#define OP_PCLID_PUBLICKEYPAIR (0x14 << OP_PCLID_SHIFT)
#define OP_PCLID_DSASIGN (0x15 << OP_PCLID_SHIFT)
#define OP_PCLID_DSAVERIFY (0x16 << OP_PCLID_SHIFT)
+#define OP_PCLID_DH (0x17 << OP_PCLID_SHIFT)
+#define OP_PCLID_RSAENC_PUBKEY (0x18 << OP_PCLID_SHIFT)
+#define OP_PCLID_RSADEC_PRVKEY (0x19 << OP_PCLID_SHIFT)
/* Assuming OP_TYPE = OP_TYPE_DECAP_PROTOCOL/ENCAP_PROTOCOL */
#define OP_PCLID_IPSEC (0x01 << OP_PCLID_SHIFT)
@@ -463,6 +489,7 @@ struct sec4_sg_entry {
#define OP_PCL_IPSEC_DES_IV64 0x0100
#define OP_PCL_IPSEC_DES 0x0200
#define OP_PCL_IPSEC_3DES 0x0300
+#define OP_PCL_IPSEC_NULL_ENC 0x0b00
#define OP_PCL_IPSEC_AES_CBC 0x0c00
#define OP_PCL_IPSEC_AES_CTR 0x0d00
#define OP_PCL_IPSEC_AES_XTS 0x1600
@@ -1155,8 +1182,15 @@ struct sec4_sg_entry {
/* randomizer AAI set */
#define OP_ALG_AAI_RNG (0x00 << OP_ALG_AAI_SHIFT)
-#define OP_ALG_AAI_RNG_NOZERO (0x10 << OP_ALG_AAI_SHIFT)
-#define OP_ALG_AAI_RNG_ODD (0x20 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG_NZB (0x10 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG_OBP (0x20 << OP_ALG_AAI_SHIFT)
+
+/* RNG4 AAI set */
+#define OP_ALG_AAI_RNG4_SH_0 (0x00 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG4_SH_1 (0x01 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG4_PS (0x40 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG4_AI (0x80 << OP_ALG_AAI_SHIFT)
+#define OP_ALG_AAI_RNG4_SK (0x100 << OP_ALG_AAI_SHIFT)
/* hmac/smac AAI set */
#define OP_ALG_AAI_HASH (0x00 << OP_ALG_AAI_SHIFT)
@@ -1178,12 +1212,6 @@ struct sec4_sg_entry {
#define OP_ALG_AAI_GSM (0x10 << OP_ALG_AAI_SHIFT)
#define OP_ALG_AAI_EDGE (0x20 << OP_ALG_AAI_SHIFT)
-/* RNG4 set */
-#define OP_ALG_RNG4_SHIFT 4
-#define OP_ALG_RNG4_MASK (0x1f3 << OP_ALG_RNG4_SHIFT)
-
-#define OP_ALG_RNG4_SK (0x100 << OP_ALG_RNG4_SHIFT)
-
#define OP_ALG_AS_SHIFT 2
#define OP_ALG_AS_MASK (0x3 << OP_ALG_AS_SHIFT)
#define OP_ALG_AS_UPDATE (0 << OP_ALG_AS_SHIFT)
@@ -1434,9 +1462,12 @@ struct sec4_sg_entry {
#define MATH_SRC1_REG3 (0x03 << MATH_SRC1_SHIFT)
#define MATH_SRC1_IMM (0x04 << MATH_SRC1_SHIFT)
#define MATH_SRC1_DPOVRD (0x07 << MATH_SRC0_SHIFT)
+#define MATH_SRC1_VARSEQINLEN (0x08 << MATH_SRC1_SHIFT)
+#define MATH_SRC1_VARSEQOUTLEN (0x09 << MATH_SRC1_SHIFT)
#define MATH_SRC1_INFIFO (0x0a << MATH_SRC1_SHIFT)
#define MATH_SRC1_OUTFIFO (0x0b << MATH_SRC1_SHIFT)
#define MATH_SRC1_ONE (0x0c << MATH_SRC1_SHIFT)
+#define MATH_SRC1_ZERO (0x0f << MATH_SRC1_SHIFT)
/* Destination selectors */
#define MATH_DEST_SHIFT 8
diff --git a/drivers/crypto/caam/desc_constr.h b/drivers/crypto/caam/desc_constr.h
index cd5f678..112eb29 100644
--- a/drivers/crypto/caam/desc_constr.h
+++ b/drivers/crypto/caam/desc_constr.h
@@ -4,6 +4,8 @@
* Copyright 2008-2012 Freescale Semiconductor, Inc.
*/
+#ifndef _DESC_CONSTR_H_
+#define _DESC_CONSTR_H_
#include "desc.h"
#define IMMEDIATE (1 << 23)
@@ -155,21 +157,29 @@ static inline void append_cmd_data(u32 *desc, void *data, int len,
append_data(desc, data, len);
}
-static inline u32 *append_jump(u32 *desc, u32 options)
-{
- u32 *cmd = desc_end(desc);
-
- PRINT_POS;
- append_cmd(desc, CMD_JUMP | options);
-
- return cmd;
+#define APPEND_CMD_RET(cmd, op) \
+static inline u32 *append_##cmd(u32 *desc, u32 options) \
+{ \
+ u32 *cmd = desc_end(desc); \
+ PRINT_POS; \
+ append_cmd(desc, CMD_##op | options); \
+ return cmd; \
}
+APPEND_CMD_RET(jump, JUMP)
+APPEND_CMD_RET(move, MOVE)
static inline void set_jump_tgt_here(u32 *desc, u32 *jump_cmd)
{
*jump_cmd = *jump_cmd | (desc_len(desc) - (jump_cmd - desc));
}
+static inline void set_move_tgt_here(u32 *desc, u32 *move_cmd)
+{
+ *move_cmd &= ~MOVE_OFFSET_MASK;
+ *move_cmd = *move_cmd | ((desc_len(desc) << (MOVE_OFFSET_SHIFT + 2)) &
+ MOVE_OFFSET_MASK);
+}
+
#define APPEND_CMD(cmd, op) \
static inline void append_##cmd(u32 *desc, u32 options) \
{ \
@@ -177,7 +187,6 @@ static inline void append_##cmd(u32 *desc, u32 options) \
append_cmd(desc, CMD_##op | options); \
}
APPEND_CMD(operation, OPERATION)
-APPEND_CMD(move, MOVE)
#define APPEND_CMD_LEN(cmd, op) \
static inline void append_##cmd(u32 *desc, unsigned int len, u32 options) \
@@ -188,6 +197,8 @@ static inline void append_##cmd(u32 *desc, unsigned int len, u32 options) \
APPEND_CMD_LEN(seq_store, SEQ_STORE)
APPEND_CMD_LEN(seq_fifo_load, SEQ_FIFO_LOAD)
APPEND_CMD_LEN(seq_fifo_store, SEQ_FIFO_STORE)
+APPEND_CMD_LEN(seq_out_ptr_pre_rto, SEQ_OUT_PTR)
+APPEND_CMD_LEN(seq_in_ptr_pre_rto, SEQ_IN_PTR)
#define APPEND_CMD_PTR(cmd, op) \
static inline void append_##cmd(u32 *desc, dma_addr_t ptr, unsigned int len, \
@@ -320,7 +331,7 @@ append_cmd(desc, CMD_MATH | MATH_FUN_##op | MATH_DEST_##dest | \
APPEND_MATH(LSHIFT, desc, dest, src0, src1, len)
#define append_math_rshift(desc, dest, src0, src1, len) \
APPEND_MATH(RSHIFT, desc, dest, src0, src1, len)
-#define append_math_ldshift(desc, dest, src0, src1, len) \
+#define append_math_shld(desc, dest, src0, src1, len) \
APPEND_MATH(SHLD, desc, dest, src0, src1, len)
/* Exactly one source is IMM. Data is passed in as u32 value */
@@ -328,7 +339,7 @@ append_cmd(desc, CMD_MATH | MATH_FUN_##op | MATH_DEST_##dest | \
do { \
APPEND_MATH(op, desc, dest, src_0, src_1, CAAM_CMD_SZ); \
append_cmd(desc, data); \
-} while (0);
+} while (0)
#define append_math_add_imm_u32(desc, dest, src0, src1, data) \
APPEND_MATH_IMM_u32(ADD, desc, dest, src0, src1, data)
@@ -379,3 +390,4 @@ do { \
APPEND_MATH_IMM_u64(LSHIFT, desc, dest, src0, src1, data)
#define append_math_rshift_imm_u64(desc, dest, src0, src1, data) \
APPEND_MATH_IMM_u64(RSHIFT, desc, dest, src0, src1, data)
+#endif
diff --git a/drivers/crypto/caam/fsl_jr_uio.c b/drivers/crypto/caam/fsl_jr_uio.c
new file mode 100644
index 0000000..b99cb52
--- /dev/null
+++ b/drivers/crypto/caam/fsl_jr_uio.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/io.h>
+#include <linux/uio_driver.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include "regs.h"
+#include "fsl_jr_uio.h"
+
+static const char jr_uio_version[] = "fsl JR UIO driver v1.0";
+
+#define NAME_LENGTH 30
+#define JR_INDEX_OFFSET 12
+
+static const char uio_device_name[] = "fsl-jr";
+static LIST_HEAD(jr_list);
+
+struct jr_uio_info {
+ atomic_t ref; /* exclusive, only one open() at a time */
+ struct uio_info uio;
+ char name[NAME_LENGTH];
+};
+
+struct jr_dev {
+ u32 revision;
+ u32 index;
+ u32 irq;
+ struct caam_job_ring __iomem *global_regs;
+ struct device *dev;
+ struct resource res;
+ struct jr_uio_info info;
+ struct list_head node;
+ struct list_head jr_list;
+};
+
+static int jr_uio_open(struct uio_info *info, struct inode *inode)
+{
+ struct jr_uio_info *uio_info = container_of(info,
+ struct jr_uio_info, uio);
+
+ if (!atomic_dec_and_test(&uio_info->ref)) {
+ pr_err("%s: failing non-exclusive open()\n", uio_info->name);
+ atomic_inc(&uio_info->ref);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int jr_uio_release(struct uio_info *info, struct inode *inode)
+{
+ struct jr_uio_info *uio_info = container_of(info,
+ struct jr_uio_info, uio);
+ atomic_inc(&uio_info->ref);
+
+ return 0;
+}
+
+static irqreturn_t jr_uio_irq_handler(int irq, struct uio_info *dev_info)
+{
+ struct jr_dev *jrdev = dev_info->priv;
+ u32 irqstate;
+ irqstate = rd_reg32(&jrdev->global_regs->jrintstatus);
+ if (!irqstate) {
+ dev_warn(jrdev->dev, "Spurious interrupt received\n");
+ return IRQ_NONE;
+ }
+
+ if (irqstate & JRINT_JR_ERROR)
+ dev_info(jrdev->dev, "uio job ring error - irqstate: %08x\n",
+ irqstate);
+
+ /*mask valid interrupts */
+ setbits32(&jrdev->global_regs->rconfig_lo, JRCFG_IMSK);
+
+ /* Have valid interrupt at this point, just ACK and trigger */
+ wr_reg32(&jrdev->global_regs->jrintstatus, irqstate);
+
+ return IRQ_HANDLED;
+}
+
+static int jr_uio_irqcontrol(struct uio_info *dev_info, int irqon)
+{
+ struct jr_dev *jrdev = dev_info->priv;
+
+ switch (irqon) {
+ case SEC_UIO_SIMULATE_IRQ_CMD:
+ uio_event_notify(dev_info);
+ break;
+ case SEC_UIO_ENABLE_IRQ_CMD:
+ /* Enable Job Ring interrupt */
+ clrbits32(&jrdev->global_regs->rconfig_lo, JRCFG_IMSK);
+ break;
+ case SEC_UIO_DISABLE_IRQ_CMD:
+ /* Disable Job Ring interrupt */
+ setbits32(&jrdev->global_regs->rconfig_lo, JRCFG_IMSK);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int __init jr_uio_init(struct jr_dev *uio_dev)
+{
+ int ret;
+ struct jr_uio_info *info;
+
+ info = &uio_dev->info;
+ atomic_set(&info->ref, 1);
+ info->uio.version = jr_uio_version;
+ info->uio.name = uio_dev->info.name;
+ info->uio.mem[0].name = "JR config space";
+ info->uio.mem[0].addr = uio_dev->res.start;
+ info->uio.mem[0].size = uio_dev->res.end - uio_dev->res.start + 1;
+ info->uio.mem[0].internal_addr = uio_dev->global_regs;
+ info->uio.mem[0].memtype = UIO_MEM_PHYS;
+ info->uio.irq = uio_dev->irq;
+ info->uio.irq_flags = IRQF_SHARED;
+ info->uio.handler = jr_uio_irq_handler;
+ info->uio.irqcontrol = jr_uio_irqcontrol;
+ info->uio.open = jr_uio_open;
+ info->uio.release = jr_uio_release;
+ info->uio.priv = uio_dev;
+
+ ret = uio_register_device(uio_dev->dev, &info->uio);
+ if (ret) {
+ pr_err("jr_uio: UIO registration failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct of_device_id jr_ids[] = {
+ { .compatible = "fsl,sec-v4.0-job-ring", },
+ { .compatible = "fsl,sec-v4.4-job-ring", },
+ { .compatible = "fsl,sec-v5.0-job-ring", },
+ { .compatible = "fsl,sec-v6.0-job-ring", },
+ {},
+};
+
+static int fsl_jr_probe(struct platform_device *dev)
+{
+ struct resource regs;
+ struct jr_dev *jr_dev;
+ struct device_node *jr_node;
+ int ret, count = 0;
+ struct list_head *p;
+
+ jr_node = dev->dev.of_node;
+ if (!jr_node) {
+ dev_err(&dev->dev, "Device OF-Node is NULL\n");
+ return -EFAULT;
+ }
+
+ jr_dev = kzalloc(sizeof(struct jr_dev), GFP_KERNEL);
+ if (!jr_dev) {
+ dev_err(&dev->dev, "kzalloc failed\n");
+ return -ENOMEM;
+ }
+
+ /* Creat name and index */
+ list_for_each(p, &jr_list) {
+ count++;
+ }
+ jr_dev->index = count;
+
+ snprintf(jr_dev->info.name, sizeof(jr_dev->info.name) - 1,
+ "%s%d", uio_device_name, jr_dev->index);
+
+ jr_dev->dev = &dev->dev;
+ platform_set_drvdata(dev, jr_dev);
+
+ /* Get the resource from dtb node */
+ ret = of_address_to_resource(jr_node, 0, &regs);
+ if (unlikely(ret < 0)) {
+ dev_err(&dev->dev, "OF-Address-to-resource Failed\n");
+ ret = -EFAULT;
+ goto abort;
+ }
+
+ jr_dev->res = regs;
+
+ jr_dev->global_regs = of_iomap(jr_node, 0);
+
+ jr_dev->irq = irq_of_parse_and_map(jr_node, 0);
+ dev_dbg(jr_dev->dev, "errirq: %d\n", jr_dev->irq);
+
+ /* Register UIO */
+ ret = jr_uio_init(jr_dev);
+ if (ret) {
+ dev_err(&dev->dev, "UIO init Failed\n");
+ goto abort_iounmap;
+ }
+
+ list_add_tail(&jr_dev->node, &jr_list);
+
+ dev_info(jr_dev->dev, "UIO device full name %s initialized\n",
+ jr_dev->info.name);
+
+ return 0;
+
+abort_iounmap:
+ iounmap(jr_dev->global_regs);
+abort:
+ kfree(jr_dev);
+ return ret;
+}
+
+static int fsl_jr_remove(struct platform_device *dev)
+{
+ struct jr_dev *jr_dev = platform_get_drvdata(dev);
+
+ if (!jr_dev)
+ return 0;
+
+ list_del(&jr_dev->node);
+ uio_unregister_device(&jr_dev->info.uio);
+ platform_set_drvdata(dev, NULL);
+ iounmap(jr_dev->global_regs);
+ kfree(jr_dev);
+
+ return 0;
+}
+
+static struct platform_driver fsl_jr_driver = {
+ .driver = {
+ .name = "fsl-jr-uio",
+ .owner = THIS_MODULE,
+ .of_match_table = jr_ids,
+ },
+ .probe = fsl_jr_probe,
+ .remove = fsl_jr_remove,
+};
+
+static __init int fsl_jr_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&fsl_jr_driver);
+ if (unlikely(ret < 0))
+ pr_warn(": %s:%hu:%s(): platform_driver_register() = %d\n",
+ __FILE__, __LINE__, __func__, ret);
+
+ return ret;
+}
+
+static void __exit fsl_jr_exit(void)
+{
+ platform_driver_unregister(&fsl_jr_driver);
+}
+
+module_init(fsl_jr_init);
+module_exit(fsl_jr_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ruchika Gupta <ruchika.gupta@freescale.com>");
+MODULE_DESCRIPTION("FSL SEC UIO Driver");
diff --git a/drivers/crypto/caam/fsl_jr_uio.h b/drivers/crypto/caam/fsl_jr_uio.h
new file mode 100644
index 0000000..2c4b7c4
--- /dev/null
+++ b/drivers/crypto/caam/fsl_jr_uio.h
@@ -0,0 +1,20 @@
+/*
+ * CAAM Job RING UIO support header file
+ *
+ * Copyright 2013 Freescale Semiconductor, Inc
+ */
+
+#ifndef FSL_JR_UIO_H
+#define FSL_JR_UIO_H
+
+/** UIO command used by user-space driver to request
+ * disabling IRQs on a certain job ring */
+#define SEC_UIO_DISABLE_IRQ_CMD 0
+/** UIO command used by user-space driver to request
+ * enabling IRQs on a certain job ring */
+#define SEC_UIO_ENABLE_IRQ_CMD 1
+/** UIO command used by user-space driver to request SEC kernel driver
+ * to simulate that an IRQ is generated on a certain job ring */
+#define SEC_UIO_SIMULATE_IRQ_CMD 2
+
+#endif
diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h
index 34c4b9f..ed0351d 100644
--- a/drivers/crypto/caam/intern.h
+++ b/drivers/crypto/caam/intern.h
@@ -2,7 +2,7 @@
* CAAM/SEC 4.x driver backend
* Private/internal definitions between modules
*
- * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright 2008-2012 Freescale Semiconductor, Inc.
*
*/
@@ -23,6 +23,8 @@
#define JOBR_INTC_COUNT_THLD 0
#endif
+#define CAAM_NAPI_WEIGHT 63
+
/*
* Storage for tracking each in-process entry moving across a ring
* Each entry on an output ring needs one of these
@@ -37,13 +39,17 @@ struct caam_jrentry_info {
/* Private sub-storage for a single JobR */
struct caam_drv_private_jr {
- struct device *parentdev; /* points back to controller dev */
- struct platform_device *jr_pdev;/* points to platform device for JR */
+ struct list_head list_node; /* Job Ring device list */
+ struct device *dev;
int ridx;
struct caam_job_ring __iomem *rregs; /* JobR's register space */
- struct tasklet_struct irqtask;
+ struct napi_struct __percpu *irqtask;
+ struct net_device __percpu *net_dev;
int irq; /* One per queue */
+ /* Number of scatterlist crypt transforms active on the JobR */
+ atomic_t tfm_count ____cacheline_aligned;
+
/* Job ring info */
int ringsize; /* Size of rings (assume input = output) */
struct caam_jrentry_info *entinfo; /* Alloc'ed 1 per ring entry */
@@ -51,6 +57,8 @@ struct caam_drv_private_jr {
int inp_ring_write_index; /* Input index "tail" */
int head; /* entinfo (s/w ring) head index */
dma_addr_t *inpring; /* Base of input ring, alloc DMA-safe */
+ dma_addr_t inpbusaddr; /* Input ring physical address */
+ dma_addr_t outbusaddr; /* Output ring physical address */
spinlock_t outlock ____cacheline_aligned; /* Output ring index lock */
int out_ring_read_index; /* Output index "tail" */
int tail; /* entinfo (s/w ring) tail index */
@@ -63,7 +71,10 @@ struct caam_drv_private_jr {
struct caam_drv_private {
struct device *dev;
- struct device **jrdev; /* Alloc'ed array per sub-device */
+ struct platform_device **jrpdev; /* Alloc'ed array per sub-device */
+#ifdef CONFIG_FSL_QMAN
+ struct device *qidev;
+#endif
struct platform_device *pdev;
/* Physical-presence section */
@@ -79,13 +90,16 @@ struct caam_drv_private {
u8 total_jobrs; /* Total Job Rings in device */
u8 qi_present; /* Nonzero if QI present in device */
int secvio_irq; /* Security violation interrupt number */
+ /* list of registered pkc algorithms */
+ struct list_head pkc_list;
- /* which jr allocated to scatterlist crypto */
- atomic_t tfm_count ____cacheline_aligned;
- /* list of registered crypto algorithms (mk generic context handle?) */
- struct list_head alg_list;
- /* list of registered hash algorithms (mk generic context handle?) */
- struct list_head hash_list;
+ int era; /* SEC Era */
+
+#define RNG4_MAX_HANDLES 2
+ /* RNG4 block */
+ u32 rng4_sh_init; /* This bitmap shows which of the State
+ Handles of the RNG4 block are initialized
+ by this driver */
/*
* debugfs entries for developer view into driver/device
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index 105ba4d..aa1dd5c 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -5,12 +5,124 @@
* Copyright 2008-2012 Freescale Semiconductor, Inc.
*/
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+
#include "compat.h"
#include "regs.h"
#include "jr.h"
#include "desc.h"
#include "intern.h"
+struct jr_driver_data {
+ /* List of Physical JobR's with the Driver */
+ struct list_head jr_list;
+ spinlock_t jr_alloc_lock; /* jr_list lock */
+} ____cacheline_aligned;
+
+static struct jr_driver_data driver_data;
+
+static int caam_reset_hw_jr(struct device *dev)
+{
+ struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
+ unsigned int timeout = 100000;
+
+ /*
+ * mask interrupts since we are going to poll
+ * for reset completion status
+ */
+ setbits32(&jrp->rregs->rconfig_lo, JRCFG_IMSK);
+
+ /* initiate flush (required prior to reset) */
+ wr_reg32(&jrp->rregs->jrcommand, JRCR_RESET);
+ while (((rd_reg32(&jrp->rregs->jrintstatus) & JRINT_ERR_HALT_MASK) ==
+ JRINT_ERR_HALT_INPROGRESS) && --timeout)
+ cpu_relax();
+
+ if ((rd_reg32(&jrp->rregs->jrintstatus) & JRINT_ERR_HALT_MASK) !=
+ JRINT_ERR_HALT_COMPLETE || timeout == 0) {
+ dev_err(dev, "failed to flush job ring %d\n", jrp->ridx);
+ return -EIO;
+ }
+
+ /* initiate reset */
+ timeout = 100000;
+ wr_reg32(&jrp->rregs->jrcommand, JRCR_RESET);
+ while ((rd_reg32(&jrp->rregs->jrcommand) & JRCR_RESET) && --timeout)
+ cpu_relax();
+
+ if (timeout == 0) {
+ dev_err(dev, "failed to reset job ring %d\n", jrp->ridx);
+ return -EIO;
+ }
+
+ /* unmask interrupts */
+ clrbits32(&jrp->rregs->rconfig_lo, JRCFG_IMSK);
+
+ return 0;
+}
+
+/*
+ * Shutdown JobR independent of platform property code
+ */
+int caam_jr_shutdown(struct device *dev)
+{
+ struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
+ int i, ret;
+
+ ret = caam_reset_hw_jr(dev);
+
+ for_each_possible_cpu(i) {
+ napi_disable(per_cpu_ptr(jrp->irqtask, i));
+ netif_napi_del(per_cpu_ptr(jrp->irqtask, i));
+ }
+
+ free_percpu(jrp->irqtask);
+ free_percpu(jrp->net_dev);
+
+ /* Release interrupt */
+ free_irq(jrp->irq, dev);
+
+ dma_free_coherent(dev, sizeof(dma_addr_t) * JOBR_DEPTH,
+ jrp->inpring, jrp->inpbusaddr);
+ dma_free_coherent(dev, sizeof(struct jr_outentry) * JOBR_DEPTH,
+ jrp->outring, jrp->outbusaddr);
+ kfree(jrp->entinfo);
+
+ return ret;
+}
+
+static int caam_jr_remove(struct platform_device *pdev)
+{
+ int ret;
+ struct device *jrdev;
+ struct caam_drv_private_jr *jrpriv;
+
+ jrdev = &pdev->dev;
+ jrpriv = dev_get_drvdata(jrdev);
+
+ /*
+ * Return EBUSY if job ring already allocated.
+ */
+ if (atomic_read(&jrpriv->tfm_count)) {
+ dev_err(jrdev, "Device is busy\n");
+ return -EBUSY;
+ }
+
+ /* Remove the node from Physical JobR list maintained by driver */
+ spin_lock(&driver_data.jr_alloc_lock);
+ list_del(&jrpriv->list_node);
+ spin_unlock(&driver_data.jr_alloc_lock);
+
+ /* Release ring */
+ ret = caam_jr_shutdown(jrdev);
+ if (ret)
+ dev_err(jrdev, "Failed to shut down job ring\n");
+ irq_dispose_mapping(jrpriv->irq);
+
+ return ret;
+}
+
/* Main per-ring interrupt handler */
static irqreturn_t caam_jr_interrupt(int irq, void *st_dev)
{
@@ -43,87 +155,154 @@ static irqreturn_t caam_jr_interrupt(int irq, void *st_dev)
wr_reg32(&jrp->rregs->jrintstatus, irqstate);
preempt_disable();
- tasklet_schedule(&jrp->irqtask);
+ napi_schedule(per_cpu_ptr(jrp->irqtask, smp_processor_id()));
preempt_enable();
return IRQ_HANDLED;
}
-/* Deferred service handler, run as interrupt-fired tasklet */
-static void caam_jr_dequeue(unsigned long devarg)
+/* Consume the processed output ring Job */
+static inline void caam_jr_consume(struct device *dev)
{
int hw_idx, sw_idx, i, head, tail;
- struct device *dev = (struct device *)devarg;
struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
void (*usercall)(struct device *dev, u32 *desc, u32 status, void *arg);
u32 *userdesc, userstatus;
void *userarg;
- while (rd_reg32(&jrp->rregs->outring_used)) {
+ head = ACCESS_ONCE(jrp->head);
+ spin_lock(&jrp->outlock);
+
+ sw_idx = jrp->tail;
+ tail = jrp->tail;
+ hw_idx = jrp->out_ring_read_index;
+
+ for (i = 0; CIRC_CNT(head, tail + i, JOBR_DEPTH) >= 1; i++) {
+ sw_idx = (tail + i) & (JOBR_DEPTH - 1);
+
+ /* Read Barrier for desc address comparision */
+ smp_read_barrier_depends();
+ if (jrp->outring[hw_idx].desc ==
+ jrp->entinfo[sw_idx].desc_addr_dma)
+ break; /* found */
+ }
+ /* we should never fail to find a matching descriptor */
+ BUG_ON(CIRC_CNT(head, tail + i, JOBR_DEPTH) <= 0);
+
+ /* Unmap just-run descriptor so we can post-process */
+ dma_unmap_single(dev, jrp->outring[hw_idx].desc,
+ jrp->entinfo[sw_idx].desc_size,
+ DMA_TO_DEVICE);
- head = ACCESS_ONCE(jrp->head);
+ /* mark completed, avoid matching on a recycled desc addr */
+ jrp->entinfo[sw_idx].desc_addr_dma = 0;
- spin_lock(&jrp->outlock);
+ /* Stash callback params for use outside of lock */
+ usercall = jrp->entinfo[sw_idx].callbk;
+ userarg = jrp->entinfo[sw_idx].cbkarg;
+ userdesc = jrp->entinfo[sw_idx].desc_addr_virt;
+ userstatus = jrp->outring[hw_idx].jrstatus;
- sw_idx = tail = jrp->tail;
- hw_idx = jrp->out_ring_read_index;
+ /* set done */
+ wr_reg32(&jrp->rregs->outring_rmvd, 1);
- for (i = 0; CIRC_CNT(head, tail + i, JOBR_DEPTH) >= 1; i++) {
- sw_idx = (tail + i) & (JOBR_DEPTH - 1);
+ jrp->out_ring_read_index = (jrp->out_ring_read_index + 1) &
+ (JOBR_DEPTH - 1);
+ /*
+ * if this job completed out-of-order, do not increment
+ * the tail. Otherwise, increment tail by 1 plus the
+ * number of subsequent jobs already completed out-of-order
+ */
+ if (sw_idx == tail) {
+ do {
+ tail = (tail + 1) & (JOBR_DEPTH - 1);
smp_read_barrier_depends();
+ } while (CIRC_CNT(head, tail, JOBR_DEPTH) >= 1 &&
+ jrp->entinfo[tail].desc_addr_dma == 0);
- if (jrp->outring[hw_idx].desc ==
- jrp->entinfo[sw_idx].desc_addr_dma)
- break; /* found */
- }
- /* we should never fail to find a matching descriptor */
- BUG_ON(CIRC_CNT(head, tail + i, JOBR_DEPTH) <= 0);
-
- /* Unmap just-run descriptor so we can post-process */
- dma_unmap_single(dev, jrp->outring[hw_idx].desc,
- jrp->entinfo[sw_idx].desc_size,
- DMA_TO_DEVICE);
-
- /* mark completed, avoid matching on a recycled desc addr */
- jrp->entinfo[sw_idx].desc_addr_dma = 0;
-
- /* Stash callback params for use outside of lock */
- usercall = jrp->entinfo[sw_idx].callbk;
- userarg = jrp->entinfo[sw_idx].cbkarg;
- userdesc = jrp->entinfo[sw_idx].desc_addr_virt;
- userstatus = jrp->outring[hw_idx].jrstatus;
-
- /* set done */
- wr_reg32(&jrp->rregs->outring_rmvd, 1);
-
- jrp->out_ring_read_index = (jrp->out_ring_read_index + 1) &
- (JOBR_DEPTH - 1);
-
- /*
- * if this job completed out-of-order, do not increment
- * the tail. Otherwise, increment tail by 1 plus the
- * number of subsequent jobs already completed out-of-order
- */
- if (sw_idx == tail) {
- do {
- tail = (tail + 1) & (JOBR_DEPTH - 1);
- smp_read_barrier_depends();
- } while (CIRC_CNT(head, tail, JOBR_DEPTH) >= 1 &&
- jrp->entinfo[tail].desc_addr_dma == 0);
-
- jrp->tail = tail;
- }
+ jrp->tail = tail;
+ }
+
+ spin_unlock(&jrp->outlock);
- spin_unlock(&jrp->outlock);
+ /* Finally, execute user's callback */
+ usercall(dev, userdesc, userstatus, userarg);
+}
- /* Finally, execute user's callback */
- usercall(dev, userdesc, userstatus, userarg);
+/* Deferred service handler, run as interrupt-fired tasklet */
+static int caam_jr_dequeue(struct napi_struct *napi, int budget)
+{
+ struct device *dev = &napi->dev->dev;
+ struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
+ int cleaned = 0;
+
+ while (rd_reg32(&jrp->rregs->outring_used) && cleaned < budget) {
+ caam_jr_consume(dev);
+ cleaned++;
}
- /* reenable / unmask IRQs */
- clrbits32(&jrp->rregs->rconfig_lo, JRCFG_IMSK);
+ if (cleaned < budget) {
+ napi_complete(per_cpu_ptr(jrp->irqtask, smp_processor_id()));
+ /* reenable / unmask IRQs */
+ clrbits32(&jrp->rregs->rconfig_lo, JRCFG_IMSK);
+ }
+
+ return cleaned;
+}
+
+/**
+ * caam_jr_alloc() - Alloc a job ring for someone to use as needed.
+ *
+ * returns : pointer to the newly allocated physical
+ * JobR dev can be written to if successful.
+ **/
+struct device *caam_jr_alloc(void)
+{
+ struct caam_drv_private_jr *jrpriv, *min_jrpriv = NULL;
+ struct device *dev = NULL;
+ int min_tfm_cnt = INT_MAX;
+ int tfm_cnt;
+
+ spin_lock(&driver_data.jr_alloc_lock);
+
+ if (list_empty(&driver_data.jr_list)) {
+ spin_unlock(&driver_data.jr_alloc_lock);
+ return ERR_PTR(-ENODEV);
+ }
+
+ list_for_each_entry(jrpriv, &driver_data.jr_list, list_node) {
+ tfm_cnt = atomic_read(&jrpriv->tfm_count);
+ if (tfm_cnt < min_tfm_cnt) {
+ min_tfm_cnt = tfm_cnt;
+ min_jrpriv = jrpriv;
+ }
+ if (!min_tfm_cnt)
+ break;
+ }
+
+ if (min_jrpriv) {
+ atomic_inc(&min_jrpriv->tfm_count);
+ dev = min_jrpriv->dev;
+ }
+ spin_unlock(&driver_data.jr_alloc_lock);
+
+ return dev;
}
+EXPORT_SYMBOL(caam_jr_alloc);
+
+/**
+ * caam_jr_free() - Free the Job Ring
+ * @rdev - points to the dev that identifies the Job ring to
+ * be released.
+ **/
+void caam_jr_free(struct device *rdev)
+{
+ struct caam_drv_private_jr *jrpriv = dev_get_drvdata(rdev);
+
+ atomic_dec(&jrpriv->tfm_count);
+}
+EXPORT_SYMBOL(caam_jr_free);
/**
* caam_jr_enqueue() - Enqueue a job descriptor head. Returns 0 if OK,
@@ -205,10 +384,34 @@ int caam_jr_enqueue(struct device *dev, u32 *desc,
}
EXPORT_SYMBOL(caam_jr_enqueue);
-static int caam_reset_hw_jr(struct device *dev)
+#ifdef CONFIG_PM
+/* Return Failure for Job pending in input ring */
+static void caam_fail_inpjobs(struct device *dev)
+{
+ struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
+ void (*usercall)(struct device *dev, u32 *desc, u32 status, void *arg);
+ u32 *userdesc;
+ void *userarg;
+ int sw_idx;
+
+ /* Check for jobs left after reaching output ring and return error */
+ for (sw_idx = 0; sw_idx < JOBR_DEPTH; sw_idx++) {
+ if (jrp->entinfo[sw_idx].desc_addr_dma) {
+ usercall = jrp->entinfo[sw_idx].callbk;
+ userarg = jrp->entinfo[sw_idx].cbkarg;
+ userdesc = jrp->entinfo[sw_idx].desc_addr_virt;
+ usercall(dev, userdesc, -EIO, userarg);
+ jrp->entinfo[sw_idx].desc_addr_dma = 0;
+ }
+ }
+}
+
+/* Suspend handler for Job Ring */
+static int jr_suspend(struct device *dev)
{
struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
unsigned int timeout = 100000;
+ int ret = 0;
/*
* mask interrupts since we are going to poll
@@ -216,6 +419,14 @@ static int caam_reset_hw_jr(struct device *dev)
*/
setbits32(&jrp->rregs->rconfig_lo, JRCFG_IMSK);
+ /*
+ * Process all the pending completed Jobs to make room for
+ * Job's coming to Outring during flush. This gives caam
+ * some more space in outring and process some more Job's
+ */
+ while (rd_reg32(&jrp->rregs->outring_used))
+ caam_jr_consume(dev);
+
/* initiate flush (required prior to reset) */
wr_reg32(&jrp->rregs->jrcommand, JRCR_RESET);
while (((rd_reg32(&jrp->rregs->jrintstatus) & JRINT_ERR_HALT_MASK) ==
@@ -225,9 +436,23 @@ static int caam_reset_hw_jr(struct device *dev)
if ((rd_reg32(&jrp->rregs->jrintstatus) & JRINT_ERR_HALT_MASK) !=
JRINT_ERR_HALT_COMPLETE || timeout == 0) {
dev_err(dev, "failed to flush job ring %d\n", jrp->ridx);
- return -EIO;
+ ret = -EIO;
+ goto err;
}
+ /*
+ * Disallow any further addition in Job Ring by making input_ring
+ * size ZERO. If output complete ring processing try to enqueue
+ * more Job's back to JR, it will return -EBUSY
+ */
+ wr_reg32(&jrp->rregs->inpring_size, 0);
+
+ while (rd_reg32(&jrp->rregs->outring_used))
+ caam_jr_consume(dev);
+
+ /* Its too late, now newely added jobs will be failed */
+ caam_fail_inpjobs(dev);
+
/* initiate reset */
timeout = 100000;
wr_reg32(&jrp->rregs->jrcommand, JRCR_RESET);
@@ -236,31 +461,85 @@ static int caam_reset_hw_jr(struct device *dev)
if (timeout == 0) {
dev_err(dev, "failed to reset job ring %d\n", jrp->ridx);
- return -EIO;
+ ret = -EIO;
+ goto err;
}
+err:
/* unmask interrupts */
clrbits32(&jrp->rregs->rconfig_lo, JRCFG_IMSK);
+ return ret;
+}
+
+/* Resume handler for Job Ring */
+static int jr_resume(struct device *dev)
+{
+ struct caam_drv_private_jr *jrp;
+ jrp = dev_get_drvdata(dev);
+
+ memset(jrp->entinfo, 0, sizeof(struct caam_jrentry_info) * JOBR_DEPTH);
+
+ /* Setup rings */
+ jrp->inp_ring_write_index = 0;
+ jrp->out_ring_read_index = 0;
+ jrp->head = 0;
+ jrp->tail = 0;
+
+ /* Setup ring base registers */
+ wr_reg64(&jrp->rregs->inpring_base, jrp->inpbusaddr);
+ wr_reg64(&jrp->rregs->outring_base, jrp->outbusaddr);
+ /* Setup ring size */
+ wr_reg32(&jrp->rregs->inpring_size, JOBR_DEPTH);
+ wr_reg32(&jrp->rregs->outring_size, JOBR_DEPTH);
+
+ setbits32(&jrp->rregs->rconfig_lo, JOBR_INTC |
+ (JOBR_INTC_COUNT_THLD << JRCFG_ICDCT_SHIFT) |
+ (JOBR_INTC_TIME_THLD << JRCFG_ICTT_SHIFT));
return 0;
}
+const struct dev_pm_ops jr_pm_ops = {
+ .suspend = jr_suspend,
+ .resume = jr_resume,
+};
+#endif /* CONFIG_PM */
+
/*
* Init JobR independent of platform property detection
*/
static int caam_jr_init(struct device *dev)
{
struct caam_drv_private_jr *jrp;
- dma_addr_t inpbusaddr, outbusaddr;
int i, error;
jrp = dev_get_drvdata(dev);
+ /* Connect job ring interrupt handler. */
+ jrp->irqtask = alloc_percpu(struct napi_struct);
+ if (!jrp->irqtask) {
+ dev_err(dev, "can't allocate percpu irqtask memory\n");
+ return -ENOMEM;
+ }
- tasklet_init(&jrp->irqtask, caam_jr_dequeue, (unsigned long)dev);
+ jrp->net_dev = alloc_percpu(struct net_device);
+ if (!jrp->net_dev) {
+ dev_err(dev, "can't allocate percpu net_dev memory\n");
+ free_percpu(jrp->irqtask);
+ return -ENOMEM;
+ }
+
+ for_each_possible_cpu(i) {
+ (per_cpu_ptr(jrp->net_dev, i))->dev = *dev;
+ INIT_LIST_HEAD(&per_cpu_ptr(jrp->net_dev, i)->napi_list);
+ netif_napi_add(per_cpu_ptr(jrp->net_dev, i),
+ per_cpu_ptr(jrp->irqtask, i),
+ caam_jr_dequeue, CAAM_NAPI_WEIGHT);
+ napi_enable(per_cpu_ptr(jrp->irqtask, i));
+ }
/* Connect job ring interrupt handler. */
error = request_irq(jrp->irq, caam_jr_interrupt, IRQF_SHARED,
- "caam-jobr", dev);
+ dev_name(dev), dev);
if (error) {
dev_err(dev, "can't connect JobR %d interrupt (%d)\n",
jrp->ridx, jrp->irq);
@@ -274,10 +553,11 @@ static int caam_jr_init(struct device *dev)
return error;
jrp->inpring = dma_alloc_coherent(dev, sizeof(dma_addr_t) * JOBR_DEPTH,
- &inpbusaddr, GFP_KERNEL);
+ &jrp->inpbusaddr, GFP_KERNEL);
jrp->outring = dma_alloc_coherent(dev, sizeof(struct jr_outentry) *
- JOBR_DEPTH, &outbusaddr, GFP_KERNEL);
+ JOBR_DEPTH, &jrp->outbusaddr,
+ GFP_KERNEL);
jrp->entinfo = kzalloc(sizeof(struct caam_jrentry_info) * JOBR_DEPTH,
GFP_KERNEL);
@@ -289,17 +569,14 @@ static int caam_jr_init(struct device *dev)
return -ENOMEM;
}
- for (i = 0; i < JOBR_DEPTH; i++)
- jrp->entinfo[i].desc_addr_dma = !0;
-
/* Setup rings */
jrp->inp_ring_write_index = 0;
jrp->out_ring_read_index = 0;
jrp->head = 0;
jrp->tail = 0;
- wr_reg64(&jrp->rregs->inpring_base, inpbusaddr);
- wr_reg64(&jrp->rregs->outring_base, outbusaddr);
+ wr_reg64(&jrp->rregs->inpring_base, jrp->inpbusaddr);
+ wr_reg64(&jrp->rregs->outring_base, jrp->outbusaddr);
wr_reg32(&jrp->rregs->inpring_size, JOBR_DEPTH);
wr_reg32(&jrp->rregs->outring_size, JOBR_DEPTH);
@@ -316,86 +593,43 @@ static int caam_jr_init(struct device *dev)
return 0;
}
-/*
- * Shutdown JobR independent of platform property code
- */
-int caam_jr_shutdown(struct device *dev)
-{
- struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
- dma_addr_t inpbusaddr, outbusaddr;
- int ret;
-
- ret = caam_reset_hw_jr(dev);
-
- tasklet_kill(&jrp->irqtask);
-
- /* Release interrupt */
- free_irq(jrp->irq, dev);
-
- /* Free rings */
- inpbusaddr = rd_reg64(&jrp->rregs->inpring_base);
- outbusaddr = rd_reg64(&jrp->rregs->outring_base);
- dma_free_coherent(dev, sizeof(dma_addr_t) * JOBR_DEPTH,
- jrp->inpring, inpbusaddr);
- dma_free_coherent(dev, sizeof(struct jr_outentry) * JOBR_DEPTH,
- jrp->outring, outbusaddr);
- kfree(jrp->entinfo);
- of_device_unregister(jrp->jr_pdev);
-
- return ret;
-}
/*
- * Probe routine for each detected JobR subsystem. It assumes that
- * property detection was picked up externally.
+ * Probe routine for each detected JobR subsystem.
*/
-int caam_jr_probe(struct platform_device *pdev, struct device_node *np,
- int ring)
+static int caam_jr_probe(struct platform_device *pdev)
{
- struct device *ctrldev, *jrdev;
- struct platform_device *jr_pdev;
- struct caam_drv_private *ctrlpriv;
+ struct device *jrdev;
+ struct device_node *nprop;
+ struct caam_job_ring __iomem *ctrl;
struct caam_drv_private_jr *jrpriv;
- u32 *jroffset;
+ static int total_jobrs;
int error;
- ctrldev = &pdev->dev;
- ctrlpriv = dev_get_drvdata(ctrldev);
-
+ jrdev = &pdev->dev;
jrpriv = kmalloc(sizeof(struct caam_drv_private_jr),
GFP_KERNEL);
- if (jrpriv == NULL) {
- dev_err(ctrldev, "can't alloc private mem for job ring %d\n",
- ring);
+ if (!jrpriv)
return -ENOMEM;
- }
- jrpriv->parentdev = ctrldev; /* point back to parent */
- jrpriv->ridx = ring; /* save ring identity relative to detection */
- /*
- * Derive a pointer to the detected JobRs regs
- * Driver has already iomapped the entire space, we just
- * need to add in the offset to this JobR. Don't know if I
- * like this long-term, but it'll run
- */
- jroffset = (u32 *)of_get_property(np, "reg", NULL);
- jrpriv->rregs = (struct caam_job_ring __iomem *)((void *)ctrlpriv->ctrl
- + *jroffset);
+ dev_set_drvdata(jrdev, jrpriv);
- /* Build a local dev for each detected queue */
- jr_pdev = of_platform_device_create(np, NULL, ctrldev);
- if (jr_pdev == NULL) {
- kfree(jrpriv);
- return -EINVAL;
+ /* save ring identity relative to detection */
+ jrpriv->ridx = total_jobrs++;
+
+ nprop = pdev->dev.of_node;
+ /* Get configuration properties from device tree */
+ /* First, get register page */
+ ctrl = of_iomap(nprop, 0);
+ if (!ctrl) {
+ dev_err(jrdev, "of_iomap() failed\n");
+ return -ENOMEM;
}
- jrpriv->jr_pdev = jr_pdev;
- jrdev = &jr_pdev->dev;
- dev_set_drvdata(jrdev, jrpriv);
- ctrlpriv->jrdev[ring] = jrdev;
+ jrpriv->rregs = (struct caam_job_ring __force *)ctrl;
if (sizeof(dma_addr_t) == sizeof(u64))
- if (of_device_is_compatible(np, "fsl,sec-v5.0-job-ring"))
+ if (of_device_is_compatible(nprop, "fsl,sec-v5.0-job-ring"))
dma_set_mask(jrdev, DMA_BIT_MASK(40));
else
dma_set_mask(jrdev, DMA_BIT_MASK(36));
@@ -403,15 +637,64 @@ int caam_jr_probe(struct platform_device *pdev, struct device_node *np,
dma_set_mask(jrdev, DMA_BIT_MASK(32));
/* Identify the interrupt */
- jrpriv->irq = of_irq_to_resource(np, 0, NULL);
+ jrpriv->irq = of_irq_to_resource(nprop, 0, NULL);
/* Now do the platform independent part */
error = caam_jr_init(jrdev); /* now turn on hardware */
if (error) {
- of_device_unregister(jr_pdev);
kfree(jrpriv);
return error;
}
- return error;
+ jrpriv->dev = jrdev;
+ spin_lock(&driver_data.jr_alloc_lock);
+ list_add_tail(&jrpriv->list_node, &driver_data.jr_list);
+ spin_unlock(&driver_data.jr_alloc_lock);
+
+ atomic_set(&jrpriv->tfm_count, 0);
+
+ return 0;
}
+
+static struct of_device_id caam_jr_match[] = {
+ {
+ .compatible = "fsl,sec-v4.0-job-ring",
+ },
+ {
+ .compatible = "fsl,sec4.0-job-ring",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, caam_jr_match);
+
+static struct platform_driver caam_jr_driver = {
+ .driver = {
+ .name = "caam_jr",
+ .owner = THIS_MODULE,
+ .of_match_table = caam_jr_match,
+#ifdef CONFIG_PM
+ .pm = &jr_pm_ops,
+#endif
+ },
+ .probe = caam_jr_probe,
+ .remove = caam_jr_remove,
+};
+
+static int __init jr_driver_init(void)
+{
+ spin_lock_init(&driver_data.jr_alloc_lock);
+ INIT_LIST_HEAD(&driver_data.jr_list);
+ return platform_driver_register(&caam_jr_driver);
+}
+
+static void __exit jr_driver_exit(void)
+{
+ platform_driver_unregister(&caam_jr_driver);
+}
+
+module_init(jr_driver_init);
+module_exit(jr_driver_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("FSL CAAM JR request backend");
+MODULE_AUTHOR("Freescale Semiconductor - NMG/STC");
diff --git a/drivers/crypto/caam/jr.h b/drivers/crypto/caam/jr.h
index 9d8741a..97113a6 100644
--- a/drivers/crypto/caam/jr.h
+++ b/drivers/crypto/caam/jr.h
@@ -8,12 +8,11 @@
#define JR_H
/* Prototypes for backend-level services exposed to APIs */
+struct device *caam_jr_alloc(void);
+void caam_jr_free(struct device *rdev);
int caam_jr_enqueue(struct device *dev, u32 *desc,
void (*cbk)(struct device *dev, u32 *desc, u32 status,
void *areq),
void *areq);
-extern int caam_jr_probe(struct platform_device *pdev, struct device_node *np,
- int ring);
-extern int caam_jr_shutdown(struct device *dev);
#endif /* JR_H */
diff --git a/drivers/crypto/caam/key_gen.h b/drivers/crypto/caam/key_gen.h
index c5588f6..8ce751b 100644
--- a/drivers/crypto/caam/key_gen.h
+++ b/drivers/crypto/caam/key_gen.h
@@ -1,10 +1,11 @@
/*
* CAAM/SEC 4.x definitions for handling key-generation jobs
*
- * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright 2008-2012 Freescale Semiconductor, Inc.
*
*/
-
+#ifndef _KEY_GEN_H_
+#define _KEY_GEN_H_
struct split_key_result {
struct completion completion;
int err;
@@ -15,3 +16,4 @@ void split_key_done(struct device *dev, u32 *desc, u32 err, void *context);
int gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len,
int split_key_pad_len, const u8 *key_in, u32 keylen,
u32 alg_op);
+#endif
diff --git a/drivers/crypto/caam/pdb.h b/drivers/crypto/caam/pdb.h
index 3a87c0c..0680b30 100644
--- a/drivers/crypto/caam/pdb.h
+++ b/drivers/crypto/caam/pdb.h
@@ -373,30 +373,204 @@ struct srtp_decap_pdb {
#define DSA_PDB_N_MASK 0x7f
-struct dsa_sign_pdb {
- u32 sgf_ln; /* Use DSA_PDB_ defintions per above */
- u8 *q;
- u8 *r;
- u8 *g; /* or Gx,y */
- u8 *s;
- u8 *f;
- u8 *c;
- u8 *d;
- u8 *ab; /* ECC only */
- u8 *u;
-};
+struct dsa_sign_desc_s {
+ uint32_t desc_hdr;
+ uint32_t sgf_ln; /* Use DSA_PDB_ definitions per above */
+ dma_addr_t q_dma;
+ dma_addr_t r_dma;
+ dma_addr_t g_dma; /* or Gx,y */
+ dma_addr_t s_dma;
+ dma_addr_t f_dma;
+ dma_addr_t c_dma;
+ dma_addr_t d_dma;
+ uint32_t op;
+} __packed;
+
+struct dsa_verify_desc_s {
+ uint32_t desc_hdr;
+ uint32_t sgf_ln;
+ dma_addr_t q_dma;
+ dma_addr_t r_dma;
+ dma_addr_t g_dma; /* or Gx,y */
+ dma_addr_t w_dma; /* or Wx,y */
+ dma_addr_t f_dma;
+ dma_addr_t c_dma;
+ dma_addr_t d_dma;
+ dma_addr_t tmp_dma; /* temporary data block */
+ uint32_t op;
+} __packed;
+
+struct dlc_keygen_desc_s {
+ uint32_t desc_hdr;
+ uint32_t sgf_ln;
+ dma_addr_t q_dma;
+ dma_addr_t r_dma;
+ dma_addr_t g_dma;
+ dma_addr_t s_dma;
+ dma_addr_t w_dma;
+ uint32_t op;
+} __packed;
+
+struct ecdsa_sign_desc_s {
+ uint32_t desc_hdr;
+ uint32_t sgf_ln; /* Use ECDSA_PDB_ definitions per above */
+ dma_addr_t q_dma;
+ dma_addr_t r_dma;
+ dma_addr_t g_dma; /* or Gx,y */
+ dma_addr_t s_dma;
+ dma_addr_t f_dma;
+ dma_addr_t c_dma;
+ dma_addr_t d_dma;
+ dma_addr_t ab_dma;
+ uint32_t op;
+} __packed;
+
+struct ecdsa_verify_desc_s {
+ uint32_t desc_hdr;
+ uint32_t sgf_ln;
+ dma_addr_t q_dma;
+ dma_addr_t r_dma;
+ dma_addr_t g_dma; /* or Gx,y */
+ dma_addr_t w_dma; /* or Wx,y */
+ dma_addr_t f_dma;
+ dma_addr_t c_dma;
+ dma_addr_t d_dma;
+ dma_addr_t tmp_dma; /* temporary data block */
+ dma_addr_t ab_dma;
+ uint32_t op;
+} __packed;
+
+struct ecc_keygen_desc_s {
+ uint32_t desc_hdr;
+ uint32_t sgf_ln;
+ dma_addr_t q_dma;
+ dma_addr_t r_dma;
+ dma_addr_t g_dma;
+ dma_addr_t s_dma;
+ dma_addr_t w_dma;
+ dma_addr_t ab_dma;
+ uint32_t op;
+} __packed;
+
+#define DH_PDB_L_SHIFT 7
+#define DH_PDB_L_MASK (0x3ff << DH_PDB_L_SHIFT)
+#define DH_PDB_N_MASK 0x7f
+#define DH_PDB_SGF_SHIFT 24
+#define DH_PDB_SGF_MASK (0xff << DH_PDB_SGF_SHIFT)
+#define DH_PDB_SGF_Q (0x80 << DH_PDB_SGF_SHIFT)
+#define DH_PDB_SGF_R (0x40 << DH_PDB_SGF_SHIFT)
+#define DH_PDB_SGF_W (0x20 << DH_PDB_SGF_SHIFT)
+#define DH_PDB_SGF_S (0x10 << DH_PDB_SGF_SHIFT)
+#define DH_PDB_SGF_Z (0x08 << DH_PDB_SGF_SHIFT)
+#define DH_PDB_SGF_AB (0x04 << DH_PDB_SGF_SHIFT)
+
+struct dh_key_desc_s {
+ uint32_t desc_hdr;
+ uint32_t sgf_ln; /* Use DH_PDB_ definitions per above */
+ dma_addr_t q_dma;
+ dma_addr_t r_dma;
+ dma_addr_t w_dma;
+ dma_addr_t s_dma;
+ dma_addr_t z_dma;
+ dma_addr_t ab_dma;
+ uint32_t op;
+} __packed;
+
+/* DSA/ECDSA Protocol Data Blocks */
+#define RSA_PDB_SGF_SHIFT 28
+#define RSA_PDB_MSG_FMT_SHIFT 12
+#define RSA_PDB_E_SHIFT 12
+#define RSA_PDB_E_MASK (0xFFF << RSA_PDB_E_SHIFT)
+#define RSA_PDB_D_SHIFT 12
+#define RSA_PDB_D_MASK (0xFFF << RSA_PDB_D_SHIFT)
+#define RSA_PDB_Q_SHIFT 12
+#define RSA_PDB_Q_MASK (0xFFF << RSA_PDB_Q_SHIFT)
+
+
+#define RSA_PDB_SGF_F (0x8 << RSA_PDB_SGF_SHIFT)
+#define RSA_PDB_SGF_G (0x4 << RSA_PDB_SGF_SHIFT)
+#define RSA_PDB_SGF_N (0x2 << RSA_PDB_SGF_SHIFT)
+#define RSA_PDB_SGF_E (0x1 << RSA_PDB_SGF_SHIFT)
+
+#define RSA_PRIV_KEY_FRM_1 0
+#define RSA_PRIV_KEY_FRM_2 1
+#define RSA_PRIV_KEY_FRM_3 2
+
+#define RSA_PDB_PVT_FRM1_SGF_SHIFT 28
+#define RSA_PDB_PVT_FRM1_D_SHIFT 10
+
+#define RSA_PDB_PVT_MSG_FMT_SHIFT 12
+#define RSA_PDB_PVT_FRM3_SGF_SHIFT 23
+#define RSA_PDB_PVT_FRM3_Q_SHIFT 12
+
+/* RSA Pub_Key Descriptor */
+struct rsa_pub_desc_s {
+ uint32_t desc_hdr;
+ uint32_t sgf_flg;
+ dma_addr_t f_dma;
+ dma_addr_t g_dma;
+ dma_addr_t n_dma;
+ dma_addr_t e_dma;
+ uint32_t msg_len;
+ uint32_t op;
+} __packed;
-struct dsa_verify_pdb {
- u32 sgf_ln;
- u8 *q;
- u8 *r;
- u8 *g; /* or Gx,y */
- u8 *w; /* or Wx,y */
- u8 *f;
- u8 *c;
- u8 *d;
- u8 *tmp; /* temporary data block */
- u8 *ab; /* only used if ECC processing */
-};
+/*
+ * Form1 Priv_key Decryption Descriptor
+ * Private key is represented by (n,d)
+ * f is decrypted data pointer while g is pointer
+ * of encrypted data
+ */
+struct rsa_priv_frm1_desc_s {
+ uint32_t desc_hdr;
+ uint32_t sgf_flg;
+ dma_addr_t g_dma;
+ dma_addr_t f_dma;
+ dma_addr_t n_dma;
+ dma_addr_t d_dma;
+ uint32_t op;
+} __packed;
+
+/*
+ * Form2 Priv_key Decryption Descriptor
+ * Private key is represented by (p,q,d)
+ * f is decrypted data pointer while g is pointer
+ * of encrypted data
+ */
+struct rsa_priv_frm2_desc_s {
+ uint32_t desc_hdr;
+ uint32_t sgf_flg;
+ dma_addr_t g_dma;
+ dma_addr_t f_dma;
+ dma_addr_t d_dma;
+ dma_addr_t p_dma;
+ dma_addr_t q_dma;
+ dma_addr_t tmp1_dma;
+ dma_addr_t tmp2_dma;
+ uint32_t p_q_len;
+ uint32_t op;
+} __packed;
+
+/*
+ * Form3 Priv_key Decryption Descriptor
+ * Private key is represented by (p,q,dp,dq,c)
+ * f is decrypted data pointer while g is input pointer
+ * of encrypted data
+ */
+struct rsa_priv_frm3_desc_s {
+ uint32_t desc_hdr;
+ uint32_t sgf_flg;
+ dma_addr_t g_dma;
+ dma_addr_t f_dma;
+ dma_addr_t c_dma;
+ dma_addr_t p_dma;
+ dma_addr_t q_dma;
+ dma_addr_t dp_dma;
+ dma_addr_t dq_dma;
+ dma_addr_t tmp1_dma;
+ dma_addr_t tmp2_dma;
+ uint32_t p_q_len;
+ uint32_t op;
+} __packed;
#endif
diff --git a/drivers/crypto/caam/pkc_desc.c b/drivers/crypto/caam/pkc_desc.c
new file mode 100644
index 0000000..5bcf5d3
--- /dev/null
+++ b/drivers/crypto/caam/pkc_desc.c
@@ -0,0 +1,383 @@
+/*
+ * \file - pkc_desc.c
+ * \brief - Freescale FSL CAAM support for Public Key Cryptography descriptor
+ *
+ * Author: Yashpal Dutta <yashpal.dutta@freescale.com>
+ *
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * There is no shared descriptor for PKC but Job descriptor must carry
+ * all the desired key parameters, input and output pointers
+ *
+ */
+#include "pkc_desc.h"
+
+/*#define CAAM_DEBUG */
+/* Descriptor for RSA Public operation */
+void *caam_rsa_pub_desc(struct rsa_edesc *edesc)
+{
+ u32 start_idx, desc_size;
+ struct rsa_pub_desc_s *rsa_pub_desc =
+ (struct rsa_pub_desc_s *)edesc->hw_desc;
+ struct rsa_pub_edesc_s *pub_edesc = &edesc->dma_u.rsa_pub_edesc;
+#ifdef CAAM_DEBUG
+ uint32_t i;
+ uint32_t *buf = (uint32_t *)rsa_pub_desc;
+#endif
+
+ desc_size = sizeof(struct rsa_pub_desc_s) / sizeof(u32);
+ start_idx = desc_size - 1;
+ start_idx &= HDR_START_IDX_MASK;
+ init_job_desc(edesc->hw_desc, (start_idx << HDR_START_IDX_SHIFT) |
+ (start_idx & HDR_DESCLEN_MASK) | HDR_ONE);
+ rsa_pub_desc->n_dma = pub_edesc->n_dma;
+ rsa_pub_desc->e_dma = pub_edesc->e_dma;
+ rsa_pub_desc->f_dma = pub_edesc->f_dma;
+ rsa_pub_desc->g_dma = pub_edesc->g_dma;
+ rsa_pub_desc->sgf_flg = (pub_edesc->sg_flgs.e_len << RSA_PDB_E_SHIFT)
+ | pub_edesc->sg_flgs.n_len;
+ rsa_pub_desc->msg_len = pub_edesc->f_len;
+ rsa_pub_desc->op = CMD_OPERATION | OP_TYPE_UNI_PROTOCOL |
+ OP_PCLID_RSAENC_PUBKEY;
+#ifdef CAAM_DEBUG
+ for (i = 0; i < desc_size; i++)
+ pr_debug("[%d] %x\n", i, buf[i]);
+#endif
+ return rsa_pub_desc;
+}
+
+/* Descriptor for RSA Private operation Form1 */
+void *caam_rsa_priv_f1_desc(struct rsa_edesc *edesc)
+{
+ u32 start_idx, desc_size;
+ struct rsa_priv_frm1_desc_s *rsa_priv_desc =
+ (struct rsa_priv_frm1_desc_s *)edesc->hw_desc;
+ struct rsa_priv_frm1_edesc_s *priv_edesc =
+ &edesc->dma_u.rsa_priv_f1_edesc;
+
+ desc_size = sizeof(struct rsa_priv_frm1_desc_s) / sizeof(u32);
+ start_idx = desc_size - 1;
+ start_idx &= HDR_START_IDX_MASK;
+ init_job_desc(edesc->hw_desc, (start_idx << HDR_START_IDX_SHIFT) |
+ (start_idx & HDR_DESCLEN_MASK) | HDR_ONE);
+ rsa_priv_desc->n_dma = priv_edesc->n_dma;
+ rsa_priv_desc->d_dma = priv_edesc->d_dma;
+ rsa_priv_desc->f_dma = priv_edesc->f_dma;
+ rsa_priv_desc->g_dma = priv_edesc->g_dma;
+ /* TBD. Support SG flags */
+ rsa_priv_desc->sgf_flg = (priv_edesc->sg_flgs.d_len << RSA_PDB_D_SHIFT)
+ | priv_edesc->sg_flgs.n_len;
+ rsa_priv_desc->op = CMD_OPERATION | OP_TYPE_UNI_PROTOCOL |
+ OP_PCLID_RSADEC_PRVKEY | RSA_PRIV_KEY_FRM_1;
+ return rsa_priv_desc;
+}
+
+/* Descriptor for RSA Private operation Form2 */
+void *caam_rsa_priv_f2_desc(struct rsa_edesc *edesc)
+{
+ u32 start_idx, desc_size;
+ struct rsa_priv_frm2_desc_s *rsa_priv_desc =
+ (struct rsa_priv_frm2_desc_s *)edesc->hw_desc;
+ struct rsa_priv_frm2_edesc_s *priv_edesc =
+ &edesc->dma_u.rsa_priv_f2_edesc;
+
+ desc_size = sizeof(struct rsa_priv_frm2_desc_s) / sizeof(u32);
+ start_idx = desc_size - 1;
+ start_idx &= HDR_START_IDX_MASK;
+ init_job_desc(edesc->hw_desc, (start_idx << HDR_START_IDX_SHIFT) |
+ (start_idx & HDR_DESCLEN_MASK) | HDR_ONE);
+ rsa_priv_desc->p_dma = priv_edesc->p_dma;
+ rsa_priv_desc->q_dma = priv_edesc->q_dma;
+ rsa_priv_desc->d_dma = priv_edesc->d_dma;
+ rsa_priv_desc->f_dma = priv_edesc->f_dma;
+ rsa_priv_desc->g_dma = priv_edesc->g_dma;
+ rsa_priv_desc->tmp1_dma = priv_edesc->tmp1_dma;
+ rsa_priv_desc->tmp2_dma = priv_edesc->tmp2_dma;
+ rsa_priv_desc->sgf_flg = (priv_edesc->sg_flgs.d_len << RSA_PDB_D_SHIFT)
+ | priv_edesc->sg_flgs.n_len;
+ rsa_priv_desc->p_q_len = (priv_edesc->q_len << RSA_PDB_Q_SHIFT)
+ | priv_edesc->p_len;
+ rsa_priv_desc->op = CMD_OPERATION | OP_TYPE_UNI_PROTOCOL |
+ OP_PCLID_RSADEC_PRVKEY | RSA_PRIV_KEY_FRM_2;
+ return rsa_priv_desc;
+}
+
+/* Descriptor for RSA Private operation Form3 */
+void *caam_rsa_priv_f3_desc(struct rsa_edesc *edesc)
+{
+ u32 start_idx, desc_size;
+ struct rsa_priv_frm3_desc_s *rsa_priv_desc =
+ (struct rsa_priv_frm3_desc_s *)edesc->hw_desc;
+ struct rsa_priv_frm3_edesc_s *priv_edesc =
+ &edesc->dma_u.rsa_priv_f3_edesc;
+#ifdef CAAM_DEBUG
+ uint32_t *buf = (uint32_t *)rsa_priv_desc;
+ uint32_t i;
+#endif
+
+ desc_size = sizeof(struct rsa_priv_frm3_desc_s) / sizeof(u32);
+ start_idx = desc_size - 1;
+ start_idx &= HDR_START_IDX_MASK;
+ init_job_desc(edesc->hw_desc, (start_idx << HDR_START_IDX_SHIFT) |
+ (start_idx & HDR_DESCLEN_MASK) | HDR_ONE);
+ rsa_priv_desc->p_dma = priv_edesc->p_dma;
+ rsa_priv_desc->q_dma = priv_edesc->q_dma;
+ rsa_priv_desc->dp_dma = priv_edesc->dp_dma;
+ rsa_priv_desc->dq_dma = priv_edesc->dq_dma;
+ rsa_priv_desc->c_dma = priv_edesc->c_dma;
+ rsa_priv_desc->f_dma = priv_edesc->f_dma;
+ rsa_priv_desc->g_dma = priv_edesc->g_dma;
+ rsa_priv_desc->tmp1_dma = priv_edesc->tmp1_dma;
+ rsa_priv_desc->tmp2_dma = priv_edesc->tmp2_dma;
+ rsa_priv_desc->p_q_len = (priv_edesc->q_len << RSA_PDB_Q_SHIFT)
+ | priv_edesc->p_len;
+ /* TBD: SG Flags to be filled */
+ rsa_priv_desc->sgf_flg = priv_edesc->sg_flgs.n_len;
+ rsa_priv_desc->op = CMD_OPERATION | OP_TYPE_UNI_PROTOCOL |
+ OP_PCLID_RSADEC_PRVKEY | RSA_PRIV_KEY_FRM_3;
+#ifdef CAAM_DEBUG
+ for (i = 0; i < desc_size; i++)
+ pr_debug("[%d] %x\n", i, buf[i]);
+#endif
+ return rsa_priv_desc;
+}
+
+/* DH sign CAAM descriptor */
+void *caam_dh_key_desc(struct dh_edesc_s *edesc)
+{
+ u32 start_idx, desc_size;
+ void *desc;
+#ifdef CAAM_DEBUG
+ uint32_t i;
+ uint32_t *buf;
+#endif
+ struct dh_key_desc_s *dh_desc =
+ (struct dh_key_desc_s *)edesc->hw_desc;
+ desc_size = sizeof(struct dh_key_desc_s) / sizeof(u32);
+ start_idx = desc_size - 1;
+ start_idx &= HDR_START_IDX_MASK;
+ init_job_desc(edesc->hw_desc, (start_idx << HDR_START_IDX_SHIFT) |
+ (start_idx & HDR_DESCLEN_MASK) | HDR_ONE);
+ dh_desc->sgf_ln = (edesc->l_len << DH_PDB_L_SHIFT) |
+ ((edesc->n_len & DH_PDB_N_MASK));
+ dh_desc->q_dma = edesc->q_dma;
+ dh_desc->w_dma = edesc->w_dma;
+ dh_desc->s_dma = edesc->s_dma;
+ dh_desc->z_dma = edesc->z_dma;
+ dh_desc->op = CMD_OPERATION | OP_TYPE_UNI_PROTOCOL |
+ OP_PCLID_DH;
+ if (edesc->req_type == ECDH_COMPUTE_KEY) {
+ dh_desc->ab_dma = edesc->ab_dma;
+ dh_desc->op |= OP_PCL_PKPROT_ECC;
+ if (edesc->curve_type == ECC_BINARY)
+ dh_desc->op |= OP_PCL_PKPROT_F2M;
+ }
+
+ desc = dh_desc;
+#ifdef CAAM_DEBUG
+ buf = desc;
+ pr_debug("%d DH Descriptor is:\n", desc_size);
+ for (i = 0; i < desc_size; i++)
+ pr_debug("[%d] %x\n", i, buf[i]);
+#endif
+ return desc;
+}
+
+/* DSA sign CAAM descriptor */
+void *caam_dsa_sign_desc(struct dsa_edesc_s *edesc)
+{
+ u32 start_idx, desc_size;
+ void *desc;
+#ifdef CAAM_DEBUG
+ uint32_t i;
+ uint32_t *buf;
+#endif
+
+ if (edesc->req_type == ECDSA_SIGN) {
+ struct ecdsa_sign_desc_s *ecdsa_desc =
+ (struct ecdsa_sign_desc_s *)edesc->hw_desc;
+ desc_size = sizeof(struct ecdsa_sign_desc_s) / sizeof(u32);
+ start_idx = desc_size - 1;
+ start_idx &= HDR_START_IDX_MASK;
+ init_job_desc(edesc->hw_desc,
+ (start_idx << HDR_START_IDX_SHIFT) |
+ (start_idx & HDR_DESCLEN_MASK) | HDR_ONE);
+ ecdsa_desc->sgf_ln = (edesc->l_len << DSA_PDB_L_SHIFT) |
+ ((edesc->n_len & DSA_PDB_N_MASK));
+ ecdsa_desc->q_dma = edesc->q_dma;
+ ecdsa_desc->r_dma = edesc->r_dma;
+ ecdsa_desc->g_dma = edesc->g_dma;
+ ecdsa_desc->s_dma = edesc->key_dma;
+ ecdsa_desc->f_dma = edesc->f_dma;
+ ecdsa_desc->c_dma = edesc->c_dma;
+ ecdsa_desc->d_dma = edesc->d_dma;
+ ecdsa_desc->ab_dma = edesc->ab_dma;
+ ecdsa_desc->op = CMD_OPERATION | OP_TYPE_UNI_PROTOCOL |
+ OP_PCLID_DSASIGN | OP_PCL_PKPROT_ECC;
+ if (edesc->curve_type == ECC_BINARY)
+ ecdsa_desc->op |= OP_PCL_PKPROT_F2M;
+
+ desc = ecdsa_desc;
+ } else {
+ struct dsa_sign_desc_s *dsa_desc =
+ (struct dsa_sign_desc_s *)edesc->hw_desc;
+ desc_size = sizeof(struct dsa_sign_desc_s) / sizeof(u32);
+ start_idx = desc_size - 1;
+ start_idx &= HDR_START_IDX_MASK;
+ init_job_desc(edesc->hw_desc,
+ (start_idx << HDR_START_IDX_SHIFT) |
+ (start_idx & HDR_DESCLEN_MASK) | HDR_ONE);
+ dsa_desc->sgf_ln = (edesc->l_len << DSA_PDB_L_SHIFT) |
+ ((edesc->n_len & DSA_PDB_N_MASK));
+ dsa_desc->q_dma = edesc->q_dma;
+ dsa_desc->r_dma = edesc->r_dma;
+ dsa_desc->g_dma = edesc->g_dma;
+ dsa_desc->s_dma = edesc->key_dma;
+ dsa_desc->f_dma = edesc->f_dma;
+ dsa_desc->c_dma = edesc->c_dma;
+ dsa_desc->d_dma = edesc->d_dma;
+ dsa_desc->op = CMD_OPERATION | OP_TYPE_UNI_PROTOCOL |
+ OP_PCLID_DSASIGN;
+ desc = dsa_desc;
+ }
+#ifdef CAAM_DEBUG
+ buf = desc;
+ pr_debug("DSA Descriptor is:");
+ for (i = 0; i < desc_size; i++)
+ pr_debug("[%d] %x ", i, buf[i]);
+ pr_debug("\n");
+#endif
+
+ return desc;
+}
+
+/* DSA/ECDSA/DH/ECDH keygen CAAM descriptor */
+void *caam_keygen_desc(struct dsa_edesc_s *edesc)
+{
+ u32 start_idx, desc_size;
+ void *desc;
+#ifdef CAAM_DEBUG
+ uint32_t i;
+ uint32_t *buf;
+#endif
+
+ if (edesc->req_type == ECC_KEYGEN) {
+ struct ecc_keygen_desc_s *ecc_desc =
+ (struct ecc_keygen_desc_s *)edesc->hw_desc;
+ desc_size = sizeof(struct ecc_keygen_desc_s) / sizeof(u32);
+ start_idx = desc_size - 1;
+ start_idx &= HDR_START_IDX_MASK;
+ init_job_desc(edesc->hw_desc,
+ (start_idx << HDR_START_IDX_SHIFT) |
+ (start_idx & HDR_DESCLEN_MASK) | HDR_ONE);
+ ecc_desc->sgf_ln = (edesc->l_len << DSA_PDB_L_SHIFT) |
+ ((edesc->n_len & DSA_PDB_N_MASK));
+ ecc_desc->q_dma = edesc->q_dma;
+ ecc_desc->r_dma = edesc->r_dma;
+ ecc_desc->g_dma = edesc->g_dma;
+ ecc_desc->s_dma = edesc->s_dma;
+ ecc_desc->w_dma = edesc->key_dma;
+ ecc_desc->ab_dma = edesc->ab_dma;
+ ecc_desc->op = CMD_OPERATION | OP_TYPE_UNI_PROTOCOL |
+ OP_PCLID_PUBLICKEYPAIR | OP_PCL_PKPROT_ECC;
+ if (edesc->curve_type == ECC_BINARY)
+ ecc_desc->op |= OP_PCL_PKPROT_F2M;
+
+ desc = ecc_desc;
+ } else {
+ struct dlc_keygen_desc_s *key_desc =
+ (struct dlc_keygen_desc_s *)edesc->hw_desc;
+ desc_size = sizeof(struct dlc_keygen_desc_s) / sizeof(u32);
+ start_idx = desc_size - 1;
+ start_idx &= HDR_START_IDX_MASK;
+ init_job_desc(edesc->hw_desc,
+ (start_idx << HDR_START_IDX_SHIFT) |
+ (start_idx & HDR_DESCLEN_MASK) | HDR_ONE);
+ key_desc->sgf_ln = (edesc->l_len << DSA_PDB_L_SHIFT) |
+ ((edesc->n_len & DSA_PDB_N_MASK));
+ key_desc->q_dma = edesc->q_dma;
+ key_desc->r_dma = edesc->r_dma;
+ key_desc->g_dma = edesc->g_dma;
+ key_desc->s_dma = edesc->s_dma;
+ key_desc->w_dma = edesc->key_dma;
+ key_desc->op = CMD_OPERATION | OP_TYPE_UNI_PROTOCOL |
+ OP_PCLID_PUBLICKEYPAIR;
+ desc = key_desc;
+ }
+#ifdef CAAM_DEBUG
+ buf = desc;
+ pr_debug("DSA Keygen Descriptor is:");
+ for (i = 0; i < desc_size; i++)
+ pr_debug("[%d] %x ", i, buf[i]);
+ pr_debug("\n");
+#endif
+
+ return desc;
+}
+
+/* DSA verify CAAM descriptor */
+void *caam_dsa_verify_desc(struct dsa_edesc_s *edesc)
+{
+ u32 start_idx, desc_size;
+ void *desc;
+#ifdef CAAM_DEBUG
+ uint32_t i;
+ uint32_t *buf;
+#endif
+
+ if (edesc->req_type == ECDSA_VERIFY) {
+ struct ecdsa_verify_desc_s *ecdsa_desc =
+ (struct ecdsa_verify_desc_s *)edesc->hw_desc;
+ desc_size = sizeof(struct ecdsa_verify_desc_s) / sizeof(u32);
+ start_idx = desc_size - 1;
+ start_idx &= HDR_START_IDX_MASK;
+ init_job_desc(edesc->hw_desc,
+ (start_idx << HDR_START_IDX_SHIFT) |
+ (start_idx & HDR_DESCLEN_MASK) | HDR_ONE);
+ ecdsa_desc->sgf_ln = (edesc->l_len << DSA_PDB_L_SHIFT) |
+ ((edesc->n_len & DSA_PDB_N_MASK));
+ ecdsa_desc->q_dma = edesc->q_dma;
+ ecdsa_desc->r_dma = edesc->r_dma;
+ ecdsa_desc->g_dma = edesc->g_dma;
+ ecdsa_desc->w_dma = edesc->key_dma;
+ ecdsa_desc->f_dma = edesc->f_dma;
+ ecdsa_desc->c_dma = edesc->c_dma;
+ ecdsa_desc->d_dma = edesc->d_dma;
+ ecdsa_desc->tmp_dma = edesc->tmp_dma;
+ ecdsa_desc->ab_dma = edesc->ab_dma;
+ ecdsa_desc->op = CMD_OPERATION | OP_TYPE_UNI_PROTOCOL |
+ OP_PCLID_DSAVERIFY | OP_PCL_PKPROT_ECC;
+ if (edesc->curve_type == ECC_BINARY)
+ ecdsa_desc->op |= OP_PCL_PKPROT_F2M;
+ desc = ecdsa_desc;
+ } else {
+ struct dsa_verify_desc_s *dsa_desc =
+ (struct dsa_verify_desc_s *)edesc->hw_desc;
+ desc_size = sizeof(struct dsa_verify_desc_s) / sizeof(u32);
+ start_idx = desc_size - 1;
+ start_idx &= HDR_START_IDX_MASK;
+ init_job_desc(edesc->hw_desc,
+ (start_idx << HDR_START_IDX_SHIFT) |
+ (start_idx & HDR_DESCLEN_MASK) | HDR_ONE);
+ dsa_desc->sgf_ln = (edesc->l_len << DSA_PDB_L_SHIFT) |
+ ((edesc->n_len & DSA_PDB_N_MASK));
+ dsa_desc->q_dma = edesc->q_dma;
+ dsa_desc->r_dma = edesc->r_dma;
+ dsa_desc->g_dma = edesc->g_dma;
+ dsa_desc->w_dma = edesc->key_dma;
+ dsa_desc->f_dma = edesc->f_dma;
+ dsa_desc->c_dma = edesc->c_dma;
+ dsa_desc->d_dma = edesc->d_dma;
+ dsa_desc->tmp_dma = edesc->tmp_dma;
+ dsa_desc->op = CMD_OPERATION | OP_TYPE_UNI_PROTOCOL |
+ OP_PCLID_DSAVERIFY;
+ desc = dsa_desc;
+ }
+#ifdef CAAM_DEBUG
+ buf = desc;
+ pr_debug("DSA Descriptor is:\n");
+ for (i = 0; i < desc_size; i++)
+ pr_debug("[%d] %x\n", i, buf[i]);
+#endif
+ return desc;
+}
diff --git a/drivers/crypto/caam/pkc_desc.h b/drivers/crypto/caam/pkc_desc.h
new file mode 100644
index 0000000..f73ad07
--- /dev/null
+++ b/drivers/crypto/caam/pkc_desc.h
@@ -0,0 +1,222 @@
+/*
+ * \file - pkc_desc.h
+ * \brief - Freescale FSL CAAM support for Public Key Cryptography
+ *
+ * Author: Yashpal Dutta <yashpal.dutta@freescale.com>
+ *
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * There is no shared descriptor for PKC but Job descriptor must carry
+ * all the desired key parameters, input and output pointers
+ *
+ */
+#ifndef _PKC_DESC_H_
+#define _PKC_DESC_H_
+
+#include "compat.h"
+
+#include "regs.h"
+#include "intern.h"
+#include "desc_constr.h"
+#include "jr.h"
+#include "error.h"
+#include "sg_sw_sec4.h"
+#include <linux/crypto.h>
+#include "pdb.h"
+
+/* Public key SG Flags and e, n lengths */
+struct sg_public_flg_s {
+ uint32_t sg_f:1;
+ uint32_t sg_g:1;
+ uint32_t sg_n:1;
+ uint32_t sg_e:1;
+ uint32_t reserved:4;
+ uint32_t e_len:12;
+ uint32_t n_len:12;
+};
+
+/* RSA public Extended Descriptor fields
+ @n_dma - n, e represents the public key
+ @e_dma - Public key exponent, n is modulus
+ @g_dma - Output RSA-encrypted value
+ @f_dma - Input RSA-Plain value
+ @n_len, e_len - Public key param length
+ @ f_len - input data len
+ */
+struct rsa_pub_edesc_s {
+ dma_addr_t n_dma;
+ dma_addr_t e_dma;
+ dma_addr_t g_dma;
+ dma_addr_t f_dma;
+ struct sg_public_flg_s sg_flgs;
+ uint32_t reserved:20;
+ uint32_t f_len:12;
+};
+
+/* Private key Form1 SG Flags and d, n lengths */
+struct sg_priv_f1_flg_s {
+ uint32_t sg_g:1;
+ uint32_t sg_f:1;
+ uint32_t sg_n:1;
+ uint32_t sg_d:1;
+ uint32_t reserved:4;
+ uint32_t d_len:12;
+ uint32_t n_len:12;
+};
+
+/* RSA PrivKey Form1 Extended Descriptor fields
+ @n_dma - n, d represents the private key form1 representation
+ @d_dma - d is the private exponent, n is the modules
+ @g_dma - Input RSA-encrypted value
+ @f_dma - Output RSA-Plain value
+ */
+struct rsa_priv_frm1_edesc_s {
+ dma_addr_t n_dma;
+ dma_addr_t d_dma;
+ dma_addr_t f_dma;
+ dma_addr_t g_dma;
+ struct sg_priv_f1_flg_s sg_flgs;
+};
+
+/* Private key Form2 SG Flags and d, n lengths */
+struct sg_priv_f2_flg_s {
+ uint32_t sg_g:1;
+ uint32_t sg_f:1;
+ uint32_t sg_d:1;
+ uint32_t sg_p:1;
+ uint32_t sg_q:1;
+ uint32_t sg_tmp1:1;
+ uint32_t sg_tmp2:1;
+ uint32_t reserved:1;
+ uint32_t d_len:12;
+ uint32_t n_len:12;
+};
+
+/* RSA PrivKey Form2
+ @p, q, d represents the private key form2 representation
+ @d - d is private exponent, p and q are the two primes
+ @f - output pointer
+ @g - input pointer
+ */
+struct rsa_priv_frm2_edesc_s {
+ dma_addr_t p_dma;
+ dma_addr_t q_dma;
+ dma_addr_t d_dma;
+ dma_addr_t f_dma;
+ dma_addr_t g_dma;
+ int8_t *tmp1;
+ int8_t *tmp2;
+ dma_addr_t tmp1_dma;
+ dma_addr_t tmp2_dma;
+ struct sg_priv_f2_flg_s sg_flgs;
+ uint32_t reserved:8;
+ uint32_t q_len:12;
+ uint32_t p_len:12;
+};
+
+/* Private key Form3 SG Flags and d, n lengths */
+struct sg_priv_f3_flg_s {
+ uint32_t sg_g:1;
+ uint32_t sg_f:1;
+ uint32_t sg_c:1;
+ uint32_t sg_p:1;
+ uint32_t sg_q:1;
+ uint32_t sg_dp:1;
+ uint32_t sg_dq:1;
+ uint32_t sg_tmp1:1;
+ uint32_t sg_tmp2:1;
+ uint32_t reserved:11;
+ uint32_t n_len:12;
+};
+
+/* RSA PrivKey Form3
+ @n - p, q, dp, dq, c represents the private key form3 representation
+ @dp - First CRT exponent factor
+ @dq - Second CRT exponent factor
+ @c - CRT Coefficient
+ @f - output pointer
+ @g - input pointer
+ */
+struct rsa_priv_frm3_edesc_s {
+ dma_addr_t p_dma;
+ dma_addr_t q_dma;
+ dma_addr_t dp_dma;
+ dma_addr_t dq_dma;
+ dma_addr_t c_dma;
+ dma_addr_t f_dma;
+ dma_addr_t g_dma;
+ int8_t *tmp1;
+ int8_t *tmp2;
+ dma_addr_t tmp1_dma;
+ dma_addr_t tmp2_dma;
+ struct sg_priv_f3_flg_s sg_flgs;
+ uint32_t reserved:8;
+ uint32_t q_len:12;
+ uint32_t p_len:12;
+};
+
+/*
+ * rsa_edesc - s/w-extended rsa descriptor
+ * @hw_desc: the h/w job descriptor
+ */
+struct rsa_edesc {
+ enum pkc_req_type req_type;
+ union {
+ struct rsa_pub_edesc_s rsa_pub_edesc;
+ struct rsa_priv_frm1_edesc_s rsa_priv_f1_edesc;
+ struct rsa_priv_frm2_edesc_s rsa_priv_f2_edesc;
+ struct rsa_priv_frm3_edesc_s rsa_priv_f3_edesc;
+ } dma_u;
+ u32 hw_desc[];
+};
+
+/*
+ * dsa_edesc - s/w-extended for dsa and ecdsa descriptors
+ * @hw_desc: the h/w job descriptor
+ */
+struct dsa_edesc_s {
+ enum pkc_req_type req_type;
+ enum curve_t curve_type;
+ uint32_t l_len;
+ uint32_t n_len;
+ dma_addr_t key_dma;
+ dma_addr_t s_dma;
+ dma_addr_t f_dma;
+ dma_addr_t q_dma;
+ dma_addr_t r_dma;
+ dma_addr_t c_dma;
+ dma_addr_t d_dma;
+ dma_addr_t ab_dma;
+ dma_addr_t g_dma;
+ dma_addr_t tmp_dma;
+ uint8_t *tmp; /* Allocate locally for dsa_verify */
+ u32 hw_desc[];
+};
+
+/*
+ * dh_edesc - s/w-extended for dh and ecdh descriptors
+ * @hw_desc: the h/w job descriptor
+ */
+struct dh_edesc_s {
+ enum pkc_req_type req_type;
+ enum curve_t curve_type;
+ uint32_t l_len;
+ uint32_t n_len;
+ dma_addr_t q_dma;
+ dma_addr_t ab_dma;
+ dma_addr_t w_dma;
+ dma_addr_t s_dma;
+ dma_addr_t z_dma;
+ u32 hw_desc[];
+};
+
+void *caam_rsa_pub_desc(struct rsa_edesc *);
+void *caam_rsa_priv_f1_desc(struct rsa_edesc *);
+void *caam_rsa_priv_f2_desc(struct rsa_edesc *);
+void *caam_rsa_priv_f3_desc(struct rsa_edesc *);
+void *caam_dsa_sign_desc(struct dsa_edesc_s *);
+void *caam_dsa_verify_desc(struct dsa_edesc_s *);
+void *caam_keygen_desc(struct dsa_edesc_s *);
+void *caam_dh_key_desc(struct dh_edesc_s *);
+
+#endif
diff --git a/drivers/crypto/caam/qi.c b/drivers/crypto/caam/qi.c
new file mode 100644
index 0000000..40cc64c
--- /dev/null
+++ b/drivers/crypto/caam/qi.c
@@ -0,0 +1,950 @@
+/*
+ * CAAM/SEC 4.x QI transport/backend driver
+ * Queue Interface backend functionality
+ *
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ */
+
+#include <linux/cpumask.h>
+#include <linux/kthread.h>
+#include <linux/fsl_qman.h>
+
+#include "regs.h"
+#include "qi.h"
+#include "desc.h"
+#include "intern.h"
+#include "desc_constr.h"
+
+#define CAAM_REQ_CGR_THRESHOLD 0x1000000
+#define PRE_HDR_LEN 2 /* Length in u32 words */
+#define PREHDR_RSLS_SHIFT 31
+#define PENDING_JOBS_DEPTH 512
+/*
+ * The jobs are processed by the driver against a driver context.
+ * With every cryptographic context, a driver context is attached.
+ * The driver context contains data for private use by driver.
+ * For the applications, this is an opaque structure.
+ */
+
+struct caam_drv_ctx {
+ u32 prehdr[PRE_HDR_LEN]; /* Preheader placed before shrd desc */
+ u32 sh_desc[MAX_SDLEN]; /* Shared descriptor */
+ dma_addr_t context_a; /* shared descriptor dma address */
+ struct qman_fq *req_fq; /* Request frame queue to caam */
+ struct qman_fq *rsp_fq; /* Response frame queue from caam */
+ int cpu; /* cpu on which to recv caam rsp */
+ struct device *qidev; /* device pointer for QI backend */
+} ____cacheline_aligned;
+
+/*
+ * percpu private data structure to main list of pending responses expected
+ * on each cpu.
+ */
+struct caam_qi_pcpu_priv {
+ struct napi_struct irqtask; /* IRQ task for QI backend */
+ struct net_device net_dev; /* netdev used by NAPI */
+ struct qman_fq rsp_fq; /* Response FQ from CAAM */
+ spinlock_t listlock ____cacheline_aligned; /* for protecting
+ * simultaneous access
+ * to bklog_list */
+ struct list_head bklog_list; /* List of pending responses*/
+ atomic_t pending; /* Number of pending responses
+ * from CAAM on this cpu */
+} ____cacheline_aligned;
+
+static DEFINE_PER_CPU(struct caam_qi_pcpu_priv, pcpu_qipriv);
+
+struct caam_qi_priv {
+ bool sec_congested; /* Indicates whether SEC is congested */
+ bool cpu_congested; /* Indicates whether CPU is congested */
+ struct qman_cgr rsp_cgr; /* QMAN response CGR */
+ struct qman_cgr req_cgr; /* QMAN request CGR */
+ struct platform_device *qi_pdev; /* Platform device for QI backend */
+};
+
+static struct caam_qi_priv qipriv ____cacheline_aligned;
+
+/*
+ * CPU from where the module initialised. This is required because
+ * QMAN driver requires CGRs to be removed from same CPU from where
+ * they were originally allocated
+ */
+static int mod_init_cpu;
+
+bool caam_drv_ctx_busy(struct caam_drv_ctx *drv_ctx)
+{
+ int pending;
+
+ if (qipriv.sec_congested)
+ return true;
+
+ pending = atomic_read(&per_cpu(pcpu_qipriv.pending, drv_ctx->cpu));
+ if (pending >= PENDING_JOBS_DEPTH)
+ return true;
+
+ return false;
+}
+EXPORT_SYMBOL(caam_drv_ctx_busy);
+
+int caam_qi_enqueue(struct device *qidev, struct caam_drv_req *req)
+{
+ struct qm_fd fd;
+ int ret;
+ size_t size;
+ struct list_head *list;
+ int num_retries = 0;
+ unsigned long flags;
+
+ fd.cmd = 0;
+ fd.format = qm_fd_compound;
+ fd.cong_weight = req->fd_sgt[1].length;
+
+ size = 2 * sizeof(struct qm_sg_entry);
+
+ fd.addr = dma_map_single(qidev, req->fd_sgt, size , DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(qidev, fd.addr)) {
+ dev_err(qidev, "DMA mapping error for QI enqueue request\n");
+ return -EIO;
+ }
+
+ req->hwaddr = qm_fd_addr(&fd);
+ list = &per_cpu(pcpu_qipriv.bklog_list, req->drv_ctx->cpu);
+
+ spin_lock_irqsave(&per_cpu(pcpu_qipriv.listlock, req->drv_ctx->cpu),
+ flags);
+ list_add_tail(&req->hdr__, list);
+ spin_unlock_irqrestore(&per_cpu(pcpu_qipriv.listlock,
+ req->drv_ctx->cpu), flags);
+ atomic_inc(&per_cpu(pcpu_qipriv.pending, req->drv_ctx->cpu));
+
+ do {
+ ret = qman_enqueue(req->drv_ctx->req_fq, &fd, 0);
+ if (likely(!ret))
+ return 0;
+
+ if (-EBUSY != ret)
+ break;
+ num_retries++;
+ } while (num_retries < 10000);
+
+ dev_err(qidev, "qman_enqueue failed: %d\n", ret);
+
+ spin_lock_irqsave(&per_cpu(pcpu_qipriv.listlock, req->drv_ctx->cpu),
+ flags);
+ list_del(&req->hdr__);
+ spin_unlock_irqrestore(&per_cpu(pcpu_qipriv.listlock,
+ req->drv_ctx->cpu), flags);
+ atomic_dec(&per_cpu(pcpu_qipriv.pending, req->drv_ctx->cpu));
+
+ dma_unmap_single(qidev, fd.addr, size, DMA_BIDIRECTIONAL);
+ return ret;
+}
+EXPORT_SYMBOL(caam_qi_enqueue);
+
+struct caam_drv_req *lookup_drv_req(const struct qm_fd *fd, int cpu)
+{
+ struct list_head *pos, *list, *n;
+ struct caam_drv_req *req;
+ unsigned long flags;
+
+ list = &per_cpu(pcpu_qipriv.bklog_list, cpu);
+ list_for_each_safe(pos, n, list) {
+ req = container_of(pos, struct caam_drv_req, hdr__);
+
+ if (req->hwaddr == qm_fd_addr(fd)) {
+ BUG_ON(req->drv_ctx->cpu != cpu);
+
+ spin_lock_irqsave(&per_cpu(pcpu_qipriv.listlock,
+ req->drv_ctx->cpu), flags);
+ list_del(&req->hdr__);
+ spin_unlock_irqrestore(&per_cpu(pcpu_qipriv.listlock,
+ req->drv_ctx->cpu),
+ flags);
+ atomic_dec(&per_cpu(pcpu_qipriv.pending,
+ req->drv_ctx->cpu));
+ return req;
+ }
+ }
+
+ return NULL;
+}
+
+
+static struct caam_drv_req *fd_to_drv_req(const struct qm_fd *fd)
+{
+ struct caam_drv_req *req;
+ const cpumask_t *cpus = qman_affine_cpus();
+ int i;
+
+ /*
+ * First check on this_cpu since this is likely case of normal caam
+ * response path.
+ */
+ req = lookup_drv_req(fd, smp_processor_id());
+ if (likely(req))
+ return req;
+ /*
+ * If drv_req is not found on this_cpu, then try searching on other
+ * portal owning cpus. This is required to handle ERN callbacks and
+ * volatile dequeues. These may be issued on a CPU which is different
+ * than the one associated with the drv_req's drv_ctx.
+ */
+ for_each_cpu(i, cpus) {
+ if (i == smp_processor_id())
+ continue; /* Already checked */
+ req = lookup_drv_req(fd, i);
+
+ if (req)
+ return req;
+ }
+
+ return NULL;
+}
+
+static void caam_fq_ern_cb(struct qman_portal *qm, struct qman_fq *fq,
+ const struct qm_mr_entry *msg)
+{
+ const struct qm_fd *fd;
+ struct caam_drv_req *drv_req;
+ size_t size;
+ struct device *qidev = &per_cpu(pcpu_qipriv.net_dev,
+ smp_processor_id()).dev;
+
+ fd = &msg->ern.fd;
+
+ if (qm_fd_compound != fd->format) {
+ dev_err(qidev, "Non compound FD from CAAM\n");
+ return;
+ }
+
+ drv_req = fd_to_drv_req(fd);
+ if (!drv_req) {
+ dev_err(qidev,
+ "Can't find original request for caam response\n");
+ return;
+ }
+
+ size = 2 * sizeof(struct qm_sg_entry);
+ dma_unmap_single(drv_req->drv_ctx->qidev, fd->addr,
+ size, DMA_BIDIRECTIONAL);
+
+ drv_req->cbk(drv_req, -EIO);
+}
+
+static enum qman_cb_dqrr_result caam_req_fq_dqrr_cb(struct qman_portal *p,
+ struct qman_fq *req_fq,
+ const struct qm_dqrr_entry *dqrr)
+{
+ struct caam_drv_req *drv_req;
+ const struct qm_fd *fd;
+ size_t size;
+ struct device *qidev = &per_cpu(pcpu_qipriv.net_dev,
+ smp_processor_id()).dev;
+
+ fd = &dqrr->fd;
+
+ drv_req = fd_to_drv_req(fd);
+ if (!drv_req) {
+ dev_err(qidev,
+ "Can't find original request for caam response\n");
+ return qman_cb_dqrr_consume;
+ }
+
+ size = 2 * sizeof(struct qm_sg_entry);
+ dma_unmap_single(drv_req->drv_ctx->qidev, fd->addr,
+ size, DMA_BIDIRECTIONAL);
+
+ drv_req->cbk(drv_req, -EIO);
+
+ return qman_cb_dqrr_consume;
+}
+
+static struct qman_fq *create_caam_req_fq(struct device *qidev,
+ struct qman_fq *rsp_fq,
+ dma_addr_t hwdesc,
+ int fq_sched_flag)
+{
+ int ret, flags;
+ struct qman_fq *req_fq;
+ struct qm_mcc_initfq opts;
+
+ req_fq = kzalloc(sizeof(*req_fq), GFP_ATOMIC);
+ if (!req_fq) {
+ dev_err(qidev, "Mem alloc for CAAM req FQ failed\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ req_fq->cb.dqrr = caam_req_fq_dqrr_cb;
+ req_fq->cb.ern = caam_fq_ern_cb;
+ req_fq->cb.fqs = NULL;
+
+ flags = QMAN_FQ_FLAG_DYNAMIC_FQID |
+ QMAN_FQ_FLAG_TO_DCPORTAL |
+ QMAN_FQ_FLAG_LOCKED;
+
+ ret = qman_create_fq(0, flags, req_fq);
+ if (ret) {
+ dev_err(qidev, "Failed to create session REQ FQ\n");
+ goto create_req_fq_fail;
+ }
+
+ flags = fq_sched_flag;
+ opts.we_mask = QM_INITFQ_WE_FQCTRL | QM_INITFQ_WE_DESTWQ |
+ QM_INITFQ_WE_CONTEXTB | QM_INITFQ_WE_CONTEXTA |
+ QM_INITFQ_WE_CGID;
+
+ opts.fqd.fq_ctrl = QM_FQCTRL_CPCSTASH | QM_FQCTRL_CGE;
+ opts.fqd.dest.channel = qm_channel_caam;
+ opts.fqd.dest.wq = 3;
+ opts.fqd.cgid = qipriv.req_cgr.cgrid;
+ opts.fqd.context_b = qman_fq_fqid(rsp_fq);
+ opts.fqd.context_a.hi = upper_32_bits(hwdesc);
+ opts.fqd.context_a.lo = lower_32_bits(hwdesc);
+
+ ret = qman_init_fq(req_fq, flags, &opts);
+ if (ret) {
+ dev_err(qidev, "Failed to init session req FQ\n");
+ goto init_req_fq_fail;
+ }
+
+ return req_fq;
+
+init_req_fq_fail:
+ qman_destroy_fq(req_fq, 0);
+
+create_req_fq_fail:
+ kfree(req_fq);
+ return ERR_PTR(ret);
+}
+
+static int empty_retired_fq(struct device *qidev, struct qman_fq *fq)
+{
+ int ret;
+ enum qman_fq_state state;
+
+ u32 flags = QMAN_VOLATILE_FLAG_WAIT_INT | QMAN_VOLATILE_FLAG_FINISH;
+ u32 vdqcr = QM_VDQCR_PRECEDENCE_VDQCR | QM_VDQCR_NUMFRAMES_TILLEMPTY;
+
+ ret = qman_volatile_dequeue(fq, flags, vdqcr);
+ if (ret) {
+ dev_err(qidev, "Volatile dequeue fail for FQ: %u\n", fq->fqid);
+ return ret;
+ }
+
+ do {
+ qman_poll_dqrr(16);
+ qman_fq_state(fq, &state, &flags);
+ } while (flags & QMAN_FQ_STATE_NE);
+
+ return 0;
+}
+
+static int kill_fq(struct device *qidev, struct qman_fq *fq)
+{
+ enum qman_fq_state state;
+ u32 flags;
+ int ret;
+
+ ret = qman_retire_fq(fq, &flags);
+ if (ret < 0) {
+ dev_err(qidev, "qman_retire_fq failed\n");
+ return ret;
+ }
+
+ if (!ret)
+ goto empty_fq;
+
+ /* Async FQ retirement condition */
+ if (1 == ret) {
+ /* Retry till FQ gets in retired state */
+ do {
+ msleep(20);
+ qman_fq_state(fq, &state, &flags);
+ } while (qman_fq_state_retired != state);
+
+ WARN_ON(flags & QMAN_FQ_STATE_BLOCKOOS);
+ WARN_ON(flags & QMAN_FQ_STATE_ORL);
+ }
+
+empty_fq:
+ if (flags & QMAN_FQ_STATE_NE) {
+ ret = empty_retired_fq(qidev, fq);
+ if (ret) {
+ dev_err(qidev, "empty_retired_fq fail for FQ: %u\n",
+ fq->fqid);
+ return ret;
+ }
+ }
+
+ ret = qman_oos_fq(fq);
+ if (ret)
+ dev_err(qidev, "OOS of FQID: %u failed\n", fq->fqid);
+
+ return ret;
+}
+
+/*
+ * TODO: This CAAM FQ empty logic can be improved. We can enqueue a NULL
+ * job descriptor to the FQ. This must be the last enqueue request to the
+ * FQ. When the response of this job comes back, the FQ is empty. Also
+ * holding tanks are guaranteed to be not holding any jobs from this FQ.
+ */
+static int empty_caam_fq(struct qman_fq *fq)
+{
+ int ret;
+ struct qm_mcr_queryfq_np np;
+
+ /* Wait till the older CAAM FQ get empty */
+ do {
+ ret = qman_query_fq_np(fq, &np);
+ if (ret)
+ return ret;
+
+ if (!np.frm_cnt)
+ break;
+
+ msleep(20);
+ } while (1);
+
+ /*
+ * Give extra time for pending jobs from this FQ in holding tanks
+ * to get processed
+ */
+ msleep(20);
+ return 0;
+}
+
+int caam_drv_ctx_update(struct caam_drv_ctx *drv_ctx, u32 *sh_desc)
+{
+ size_t size;
+ u32 num_words;
+ int ret;
+ struct qman_fq *new_fq, *old_fq;
+ struct device *qidev = drv_ctx->qidev;
+
+ /* Check the size of new shared descriptor */
+ num_words = desc_len(sh_desc);
+ if (num_words > MAX_SDLEN) {
+ dev_err(qidev, "Invalid descriptor len: %d words\n",
+ num_words);
+ return -EINVAL;
+ }
+
+ /* Note down older req FQ */
+ old_fq = drv_ctx->req_fq;
+
+ /* Create a new req FQ in parked state */
+ new_fq = create_caam_req_fq(drv_ctx->qidev, drv_ctx->rsp_fq,
+ drv_ctx->context_a, 0);
+ if (!new_fq) {
+ dev_err(qidev, "FQ allocation for shdesc update failed\n");
+ return PTR_ERR(new_fq);
+ }
+
+ /* Hook up new FQ to context so that new requests keep queueing */
+ drv_ctx->req_fq = new_fq;
+
+ /* Empty and remove the older FQ */
+ ret = empty_caam_fq(old_fq);
+ if (ret) {
+ dev_err(qidev, "Old SEC FQ empty failed\n");
+
+ /* We can revert to older FQ */
+ drv_ctx->req_fq = old_fq;
+
+ if (kill_fq(qidev, new_fq)) {
+ dev_warn(qidev, "New SEC FQ: %u kill failed\n",
+ new_fq->fqid);
+ }
+
+ return ret;
+ }
+
+ /*
+ * Now update the shared descriptor for driver context.
+ * Re-initialise pre-header. Set RSLS and SDLEN
+ */
+ drv_ctx->prehdr[0] = (1 << PREHDR_RSLS_SHIFT) | num_words;
+
+ /* Copy the new shared descriptor now */
+ memcpy(drv_ctx->sh_desc, sh_desc, desc_bytes(sh_desc));
+
+ size = sizeof(drv_ctx->sh_desc) + sizeof(drv_ctx->prehdr);
+ dma_sync_single_for_device(qidev, drv_ctx->context_a,
+ size, DMA_BIDIRECTIONAL);
+
+ /* Put the new FQ in scheduled state */
+ ret = qman_schedule_fq(new_fq);
+ if (ret) {
+ dev_err(qidev, "Fail to sched new SEC FQ, ecode = %d\n", ret);
+
+ /*
+ * We can kill new FQ and revert to old FQ.
+ * Since the desc is already modified, it is success case
+ */
+
+ drv_ctx->req_fq = old_fq;
+
+ if (kill_fq(qidev, new_fq)) {
+ dev_warn(qidev, "New SEC FQ: %u kill failed\n",
+ new_fq->fqid);
+ }
+ } else {
+ /* Remove older FQ */
+ if (kill_fq(qidev, old_fq)) {
+ dev_warn(qidev, "Old SEC FQ: %u kill failed\n",
+ old_fq->fqid);
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(caam_drv_ctx_update);
+
+
+
+struct caam_drv_ctx *caam_drv_ctx_init(struct device *qidev,
+ int *cpu,
+ u32 *sh_desc)
+{
+ size_t size;
+ u32 num_words;
+ dma_addr_t hwdesc;
+ struct qman_fq *rsp_fq;
+ struct caam_drv_ctx *drv_ctx;
+ const cpumask_t *cpus = qman_affine_cpus();
+ static DEFINE_PER_CPU(int, last_cpu);
+
+ num_words = desc_len(sh_desc);
+ if (num_words > MAX_SDLEN) {
+ dev_err(qidev, "Invalid descriptor len: %d words\n",
+ num_words);
+ return ERR_PTR(-EINVAL);
+ }
+
+ drv_ctx = kzalloc(sizeof(*drv_ctx), GFP_ATOMIC);
+ if (!drv_ctx) {
+ dev_err(qidev, "Mem alloc for driver context failed\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /* Initialise pre-header. Set RSLS and SDLEN */
+ drv_ctx->prehdr[0] = (1 << PREHDR_RSLS_SHIFT) | num_words;
+
+ /* Copy the shared descriptor now */
+ memcpy(drv_ctx->sh_desc, sh_desc, desc_bytes(sh_desc));
+
+ /* Map address for pre-header + descriptor */
+ size = sizeof(drv_ctx->prehdr) + sizeof(drv_ctx->sh_desc);
+ hwdesc = dma_map_single(qidev, drv_ctx->prehdr,
+ size, DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(qidev, hwdesc)) {
+ dev_err(qidev, "DMA map error for preheader+shdesc\n");
+ kfree(drv_ctx);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ drv_ctx->context_a = hwdesc;
+
+ /*
+ * If the given CPU does not own the portal, choose another
+ * one with a portal.
+ */
+ if (!cpumask_test_cpu(*cpu, cpus)) {
+ last_cpu = cpumask_next(last_cpu, cpus);
+ if (last_cpu >= nr_cpu_ids)
+ last_cpu = cpumask_first(cpus);
+ *cpu = last_cpu;
+ }
+
+ drv_ctx->cpu = *cpu;
+
+ /* Find response FQ hooked with this CPU*/
+ rsp_fq = &per_cpu(pcpu_qipriv.rsp_fq, drv_ctx->cpu);
+ drv_ctx->rsp_fq = rsp_fq;
+
+ /*Attach request FQ*/
+ drv_ctx->req_fq = create_caam_req_fq(qidev, rsp_fq,
+ hwdesc, QMAN_INITFQ_FLAG_SCHED);
+ if (!drv_ctx->req_fq) {
+ dev_err(qidev, "create_caam_req_fq failed\n");
+ dma_unmap_single(qidev, hwdesc, size, DMA_BIDIRECTIONAL);
+ kfree(drv_ctx);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ drv_ctx->qidev = qidev;
+ return drv_ctx;
+}
+EXPORT_SYMBOL(caam_drv_ctx_init);
+
+static int caam_qi_poll(struct napi_struct *napi, int budget)
+{
+ int cleaned = qman_poll_dqrr(budget);
+
+ if (cleaned < budget) {
+ napi_complete(napi);
+ qman_irqsource_add(QM_PIRQ_DQRI);
+ }
+
+ return cleaned;
+}
+
+
+void caam_drv_ctx_rel(struct caam_drv_ctx *drv_ctx)
+{
+ size_t size;
+
+ if (!drv_ctx)
+ return;
+
+ size = sizeof(drv_ctx->sh_desc) + sizeof(drv_ctx->prehdr);
+
+ /* Remove request FQ*/
+ if (kill_fq(drv_ctx->qidev, drv_ctx->req_fq))
+ dev_err(drv_ctx->qidev, "Crypto session Req FQ kill failed\n");
+
+ dma_unmap_single(drv_ctx->qidev, drv_ctx->context_a,
+ size, DMA_BIDIRECTIONAL);
+
+ kfree(drv_ctx);
+}
+EXPORT_SYMBOL(caam_drv_ctx_rel);
+
+int caam_qi_shutdown(struct device *qidev)
+{
+ struct caam_qi_priv *priv = dev_get_drvdata(qidev);
+ int i, ret;
+
+ const cpumask_t *cpus = qman_affine_cpus();
+ struct cpumask old_cpumask = *tsk_cpus_allowed(current);
+
+ for_each_cpu(i, cpus) {
+ napi_disable(&per_cpu(pcpu_qipriv.irqtask, i));
+ netif_napi_del(&per_cpu(pcpu_qipriv.irqtask, i));
+ if (kill_fq(qidev, &per_cpu(pcpu_qipriv.rsp_fq, i)))
+ dev_err(qidev, "Rsp FQ kill failed, cpu: %d\n", i);
+ }
+
+ /*
+ * QMAN driver requires CGRs to be deleted from same CPU from where
+ * they were instantiated. Hence we get the module removal execute
+ * from the same CPU from where it was originally inserted.
+ */
+ set_cpus_allowed_ptr(current, get_cpu_mask(mod_init_cpu));
+
+ ret = qman_delete_cgr(&priv->req_cgr);
+ if (ret)
+ dev_err(qidev, "Delete request CGR failed: %d\n", ret);
+ else
+ qman_release_cgrid(priv->req_cgr.cgrid);
+
+ ret = qman_delete_cgr(&priv->rsp_cgr);
+ if (ret)
+ dev_err(qidev, "Delete response CGR failed: %d\n", ret);
+ else
+ qman_release_cgrid(priv->rsp_cgr.cgrid);
+
+ /* Now that we're done with the CGRs, restore the cpus allowed mask */
+ set_cpus_allowed_ptr(current, &old_cpumask);
+
+ platform_device_unregister(priv->qi_pdev);
+ return ret;
+}
+
+static void rsp_cgr_cb(struct qman_portal *qm, struct qman_cgr *cgr,
+ int congested)
+{
+ struct device *qidev = &per_cpu(pcpu_qipriv.net_dev,
+ smp_processor_id()).dev;
+
+ qipriv.cpu_congested = congested;
+
+ if (congested)
+ dev_warn(qidev, "CAAM rsp path congested\n");
+ else
+ dev_info(qidev, "CAAM rsp path congestion state exit\n");
+}
+
+static void req_cgr_cb(struct qman_portal *qm, struct qman_cgr *cgr,
+ int congested)
+{
+ struct device *qidev = &per_cpu(pcpu_qipriv.net_dev,
+ smp_processor_id()).dev;
+
+ qipriv.sec_congested = congested;
+
+ if (congested)
+ dev_warn(qidev, "CAAM req path congested\n");
+ else
+ dev_info(qidev, "CAAM req path congestion state exit\n");
+}
+
+static int caam_qi_napi_schedule(struct napi_struct *napi)
+{
+ /*
+ * In case of threaded ISR for RT enable kernel,
+ * in_irq() does not return appropriate value, so use
+ * in_serving_softirq to distinguish softirq or irq context.
+ */
+ if (unlikely(in_irq() || !in_serving_softirq())) {
+ /* Disable QMan IRQ and invoke NAPI */
+ int ret = qman_irqsource_remove(QM_PIRQ_DQRI);
+ if (likely(!ret)) {
+ napi_schedule(napi);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static enum qman_cb_dqrr_result caam_rsp_fq_dqrr_cb(struct qman_portal *p,
+ struct qman_fq *rsp_fq,
+ const struct qm_dqrr_entry *dqrr)
+{
+ struct napi_struct *napi;
+ struct caam_drv_req *drv_req;
+ const struct qm_fd *fd;
+ size_t size;
+ struct device *qidev = &per_cpu(pcpu_qipriv.net_dev,
+ smp_processor_id()).dev;
+
+ napi = &per_cpu(pcpu_qipriv.irqtask, smp_processor_id());
+ if (caam_qi_napi_schedule(napi))
+ 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 (qm_fd_compound != fd->format) {
+ dev_err(qidev, "Non compound FD from CAAM\n");
+ return qman_cb_dqrr_consume;
+ }
+
+ drv_req = fd_to_drv_req(fd);
+ if (!drv_req) {
+ dev_err(qidev,
+ "Can't find original request for caam response\n");
+ return qman_cb_dqrr_consume;
+ }
+
+ size = 2 * sizeof(struct qm_sg_entry);
+ dma_unmap_single(drv_req->drv_ctx->qidev, fd->addr,
+ size, DMA_BIDIRECTIONAL);
+
+ drv_req->cbk(drv_req, fd->status);
+
+ return qman_cb_dqrr_consume;
+}
+
+static int alloc_rsp_fq_cpu(struct device *qidev, unsigned int cpu)
+{
+ struct qm_mcc_initfq opts;
+ struct qman_fq *fq;
+ int ret;
+ u32 flags;
+
+ fq = &per_cpu(pcpu_qipriv.rsp_fq, cpu);
+
+ fq->cb.dqrr = caam_rsp_fq_dqrr_cb;
+
+ flags = QMAN_FQ_FLAG_NO_ENQUEUE |
+ QMAN_FQ_FLAG_DYNAMIC_FQID;
+
+ ret = qman_create_fq(0, flags, fq);
+ if (ret) {
+ dev_err(qidev, "Rsp FQ create failed\n");
+ return -ENODEV;
+ }
+
+ flags = QMAN_INITFQ_FLAG_SCHED;
+
+ opts.we_mask = QM_INITFQ_WE_FQCTRL | QM_INITFQ_WE_DESTWQ |
+ QM_INITFQ_WE_CONTEXTB | QM_INITFQ_WE_CONTEXTA |
+ QM_INITFQ_WE_CGID;
+
+ opts.fqd.fq_ctrl = QM_FQCTRL_CTXASTASHING |
+ QM_FQCTRL_CPCSTASH |
+ QM_FQCTRL_CGE;
+
+ opts.fqd.dest.channel = qman_affine_channel(cpu);
+ opts.fqd.cgid = qipriv.rsp_cgr.cgrid;
+ opts.fqd.dest.wq = 1;
+ opts.fqd.context_a.stashing.exclusive =
+ QM_STASHING_EXCL_CTX |
+ QM_STASHING_EXCL_DATA;
+
+ opts.fqd.context_a.stashing.data_cl = 1;
+ opts.fqd.context_a.stashing.context_cl = 1;
+
+ ret = qman_init_fq(fq, flags, &opts);
+ if (ret) {
+ dev_err(qidev, "Rsp FQ init failed\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int alloc_cgrs(struct device *qidev)
+{
+ struct qm_mcc_initcgr opts;
+ int ret;
+
+ /*Allocate response CGR*/
+ ret = qman_alloc_cgrid(&qipriv.rsp_cgr.cgrid);
+ if (ret) {
+ dev_err(qidev, "CGR alloc failed for rsp FQs");
+ return ret;
+ }
+
+ qipriv.rsp_cgr.cb = rsp_cgr_cb;
+ memset(&opts, 0, sizeof(opts));
+ opts.we_mask = QM_CGR_WE_CSCN_EN | QM_CGR_WE_CS_THRES |
+ QM_CGR_WE_MODE;
+ opts.cgr.cscn_en = QM_CGR_EN;
+ opts.cgr.mode = QMAN_CGR_MODE_FRAME;
+ qm_cgr_cs_thres_set64(&opts.cgr.cs_thres, 0x400 , 1);
+
+ ret = qman_create_cgr(&qipriv.rsp_cgr,
+ QMAN_CGR_FLAG_USE_INIT, &opts);
+ if (ret) {
+ dev_err(qidev, "Error %d creating CAAM rsp CGRID: %u\n",
+ ret, qipriv.rsp_cgr.cgrid);
+ goto create_rsp_cgr_fail;
+ }
+
+ /*Allocate request CGR*/
+ ret = qman_alloc_cgrid(&qipriv.req_cgr.cgrid);
+ if (ret) {
+ dev_err(qidev, "CGR alloc failed for req FQs");
+ goto alloc_req_cgrid_fail;
+ }
+
+ qipriv.req_cgr.cb = req_cgr_cb;
+ memset(&opts, 0, sizeof(opts));
+ opts.we_mask = QM_CGR_WE_CSCN_EN | QM_CGR_WE_CS_THRES;
+ opts.cgr.cscn_en = QM_CGR_EN;
+ qm_cgr_cs_thres_set64(&opts.cgr.cs_thres, CAAM_REQ_CGR_THRESHOLD , 1);
+
+ ret = qman_create_cgr(&qipriv.req_cgr,
+ QMAN_CGR_FLAG_USE_INIT, &opts);
+ if (ret) {
+ dev_err(qidev, "Error %d creating CAAM req CGRID: %u\n",
+ ret, qipriv.req_cgr.cgrid);
+ goto create_req_cgr_fail;
+ }
+ return 0;
+
+create_req_cgr_fail:
+ qman_release_cgrid(qipriv.req_cgr.cgrid);
+
+alloc_req_cgrid_fail:
+ qman_delete_cgr(&qipriv.rsp_cgr);
+
+create_rsp_cgr_fail:
+ qman_release_cgrid(qipriv.rsp_cgr.cgrid);
+
+ return ret;
+}
+
+static int alloc_rsp_fqs(struct device *qidev)
+{
+ const cpumask_t *cpus = qman_affine_cpus();
+ int ret, i;
+
+ /*Now create response FQs*/
+ for_each_cpu(i, cpus) {
+ ret = alloc_rsp_fq_cpu(qidev, i);
+ if (ret) {
+ dev_err(qidev, "CAAM rsp FQ alloc failed, cpu: %u", i);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+int caam_qi_init(struct platform_device *caam_pdev, struct device_node *np)
+{
+ struct platform_device *qi_pdev;
+ struct device *ctrldev, *qidev;
+ struct caam_drv_private *ctrlpriv;
+ int err, i;
+ const cpumask_t *cpus = qman_affine_cpus();
+ struct cpumask old_cpumask = *tsk_cpus_allowed(current);
+
+ /*
+ * QMAN requires that CGR must be removed from same CPU+portal from
+ * where it was originally allocated. Hence we need to note down
+ * the initialisation CPU and use the same CPU for module exit.
+ * We select the first CPU to from the list of portal owning
+ * CPUs. Then we pin module init to this CPU.
+ */
+ mod_init_cpu = cpumask_first(cpus);
+ set_cpus_allowed_ptr(current, get_cpu_mask(mod_init_cpu));
+
+ qi_pdev = platform_device_register_simple("caam_qi", 0, NULL, 0);
+ if (IS_ERR(qi_pdev))
+ return PTR_ERR(qi_pdev);
+
+ ctrldev = &caam_pdev->dev;
+ ctrlpriv = dev_get_drvdata(ctrldev);
+ qidev = &qi_pdev->dev;
+
+ qipriv.qi_pdev = qi_pdev;
+ dev_set_drvdata(qidev, &qipriv);
+
+ /* Copy dma mask from controlling device */
+ err = dma_set_mask(qidev, dma_get_mask(ctrldev));
+ if (err) {
+ platform_device_unregister(qi_pdev);
+ return -ENODEV;
+ }
+
+ /* Initialise the CGRs congestion detection */
+ err = alloc_cgrs(qidev);
+ if (err) {
+ dev_err(qidev, "Can't allocate CGRs\n");
+ platform_device_unregister(qi_pdev);
+ return err;
+ }
+
+ /* Initialise response FQs */
+ err = alloc_rsp_fqs(qidev);
+ if (err) {
+ dev_err(qidev, "Can't allocate SEC response FQs\n");
+ platform_device_unregister(qi_pdev);
+ return err;
+ }
+
+ /*
+ * Enable the NAPI contexts on each of the core which has a affine
+ * portal.
+ */
+ for_each_cpu(i, cpus) {
+ per_cpu(pcpu_qipriv.net_dev, i).dev = *qidev;
+
+ spin_lock_init(&per_cpu(pcpu_qipriv.listlock, i));
+ INIT_LIST_HEAD(&per_cpu(pcpu_qipriv.bklog_list, i));
+
+ INIT_LIST_HEAD(&per_cpu(pcpu_qipriv.net_dev, i).napi_list);
+
+ netif_napi_add(&per_cpu(pcpu_qipriv.net_dev, i),
+ &per_cpu(pcpu_qipriv.irqtask, i),
+ caam_qi_poll, CAAM_NAPI_WEIGHT);
+
+ napi_enable(&per_cpu(pcpu_qipriv.irqtask, i));
+ }
+
+ /* Hook up QI device to parent controlling caam device */
+ ctrlpriv->qidev = qidev;
+
+ /* Done with the CGRs; restore the cpus allowed mask */
+ set_cpus_allowed_ptr(current, &old_cpumask);
+
+ dev_info(qidev, "Linux CAAM Queue I/F driver initialised\n");
+
+ return 0;
+}
diff --git a/drivers/crypto/caam/qi.h b/drivers/crypto/caam/qi.h
new file mode 100644
index 0000000..109f890
--- /dev/null
+++ b/drivers/crypto/caam/qi.h
@@ -0,0 +1,157 @@
+/*
+ * CAAM public-level include definitions for the QI backend
+ *
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ */
+
+#ifndef __QI_H__
+#define __QI_H__
+
+#include "compat.h"
+#include "desc.h"
+#include "linux/fsl_qman.h"
+
+/*
+ * The CAAM QI hardware constructs a job descriptor which points
+ * to shared descriptor (as pointed by context_a of FQ to CAAM).
+ * When the job descriptor is executed by deco, the whole job
+ * descriptor together with shared descriptor gets loaded in
+ * deco buffer which is 64 words long (each 32-bit).
+ *
+ * The job descriptor constructed by QI hardware has layout:
+ *
+ * HEADER (1 word)
+ * Shdesc ptr (1 or 2 words)
+ * SEQ_OUT_PTR (1 word)
+ * Out ptr (1 or 2 words)
+ * Out length (1 word)
+ * SEQ_IN_PTR (1 word)
+ * In ptr (1 or 2 words)
+ * In length (1 word)
+ *
+ * The shdesc ptr is used to fetch shared descriptor contents
+ * into deco buffer.
+ *
+ * Apart from shdesc contents, the total number of words that
+ * get loaded in deco buffer are '8' or '11'. The remaining words
+ * in deco buffer can be used for storing shared descriptor.
+ */
+#define MAX_SDLEN ((CAAM_DESC_BYTES_MAX - DESC_JOB_IO_LEN)/CAAM_CMD_SZ)
+
+/*
+ * This is the request structure the driver application should fill while
+ * submitting a job to driver.
+ */
+struct caam_drv_req;
+
+/*
+ * Application's callback function invoked by the driver when the request
+ * has been successfully processed.
+ *
+ * drv_req: Original request that was submitted
+ * stats: Completion status of request.
+ * 0 - Success
+ * Non-zero - Error code
+ */
+typedef void (*caam_qi_cbk)(struct caam_drv_req *drv_req,
+ u32 status);
+
+/*
+ * The jobs are processed by the driver against a driver context.
+ * With every cryptographic context, a driver context is attached.
+ * The driver context contains data for private use by driver.
+ * For the applications, this is an opaque structure.
+ */
+struct caam_drv_ctx;
+
+/*
+ * This is the request structure the driver application should fill while
+ * submitting a job to driver.
+ *
+ * fd_sgt[0] - QMAN S/G pointing to output buffer
+ * fd_sgt[1] - QMAN S/G pointing to input buffer
+ * cbk - Callback function to invoke when job is completed
+ * app_ctx - Arbit context attached with request by the application
+ *
+ * The fields mentioned below should not be used by application.
+ * These are for private use by driver.
+ *
+ * hdr__ - Linked list header to maintain list of outstanding requests
+ * to CAAM.
+ * hwaddr - DMA address for the S/G table.
+ */
+struct caam_drv_req {
+ struct qm_sg_entry fd_sgt[2];
+ struct caam_drv_ctx *drv_ctx;
+ caam_qi_cbk cbk;
+ void *app_ctx;
+
+ /* The fields below are for internal use by QI backend driver */
+ struct list_head hdr__;
+ dma_addr_t hwaddr;
+} ____cacheline_aligned;
+
+/*
+ * caam_drv_ctx_init - Initialise a QI drv context.
+ *
+ * A QI driver context must be attached with each cryptographic context.
+ * This function allocates memory for QI context an returns a handle to
+ * the application. This handle must be submitted along with each enqueue
+ * request to the driver by the application.
+ *
+ * cpu - CPU where the application prefers to the driver to receive
+ * CAAM responses. The request completion callback would be
+ * issued from this CPU.
+ * sh_desc - Shared descriptor pointer to be attached with QI driver
+ * context.
+ *
+ * Returns a driver context on success or negative error code on failure.
+ */
+extern struct caam_drv_ctx *caam_drv_ctx_init(struct device *qidev,
+ int *cpu, u32 *sh_desc);
+
+/*
+ * caam_qi_enqueue - Submit a request to QI backend driver.
+ *
+ * The request structure must be properly filled as described above.
+ *
+ * Returns 0 on success or negative error code on failure.
+ */
+extern int caam_qi_enqueue(struct device *qidev, struct caam_drv_req *req);
+
+/*
+ * caam_drv_ctx_busy - Check if there are too many jobs pending with CAAM.
+ * or too many CAAM responses are pending to be processed.
+ *
+ * drv_ctx - Driver context for which job is to be submitted.
+ *
+ * Returns caam congestion status 'true/false'
+ */
+extern bool caam_drv_ctx_busy(struct caam_drv_ctx *drv_ctx);
+
+/*
+ * caam_drv_ctx_update - Upate QI drv context.
+ *
+ * Invoked when shared descriptor is required to be change in driver context.
+ *
+ * drv_ctx - Driver context to be updated
+ *
+ * sh_desc - New shared descriptor pointer to be updated in QI driver
+ * context.
+ *
+ * Returns 0 on success or negative error code on failure.
+ */
+extern int caam_drv_ctx_update(struct caam_drv_ctx *drv_ctx, u32 *sh_desc);
+
+/*
+ * caam_drv_ctx_rel - Release a QI driver context.
+ *
+ * drv_ctx - Context to be released.
+ *
+ */
+extern void caam_drv_ctx_rel(struct caam_drv_ctx *drv_ctx);
+
+extern int caam_qi_init(struct platform_device *pdev, struct device_node *np);
+extern int caam_qi_shutdown(struct device *dev);
+
+#endif /* QI_H */
diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index 4455396..d50174f 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -245,7 +245,7 @@ struct rngtst {
/* RNG4 TRNG test registers */
struct rng4tst {
-#define RTMCTL_PRGM 0x00010000 /* 1 -> program mode, 0 -> run mode */
+#define RTMCTL_PRGM 0x00010000 /* 1 -> program mode, 0 -> run mode */
u32 rtmctl; /* misc. control register */
u32 rtscmisc; /* statistical check misc. register */
u32 rtpkrrng; /* poker range register */
@@ -255,6 +255,8 @@ struct rng4tst {
};
#define RTSDCTL_ENT_DLY_SHIFT 16
#define RTSDCTL_ENT_DLY_MASK (0xffff << RTSDCTL_ENT_DLY_SHIFT)
+#define RTSDCTL_ENT_DLY_MIN 1200
+#define RTSDCTL_ENT_DLY_MAX 12800
u32 rtsdctl; /* seed control register */
union {
u32 rtsblim; /* PRGM=1: sparse bit limit register */
@@ -266,7 +268,11 @@ struct rng4tst {
u32 rtfrqcnt; /* PRGM=0: freq. count register */
};
u32 rsvd1[40];
+#define RDSTA_SKVT 0x80000000
+#define RDSTA_SKVN 0x40000000
#define RDSTA_IF0 0x00000001
+#define RDSTA_IF1 0x00000002
+#define RDSTA_IFMASK (RDSTA_IF1 | RDSTA_IF0)
u32 rdsta;
u32 rsvd2[15];
};
@@ -692,6 +698,7 @@ struct caam_deco {
u32 jr_ctl_hi; /* CxJRR - JobR Control Register @800 */
u32 jr_ctl_lo;
u64 jr_descaddr; /* CxDADR - JobR Descriptor Address */
+#define DECO_OP_STATUS_HI_ERR_MASK 0xF00000FF
u32 op_status_hi; /* DxOPSTA - DECO Operation Status */
u32 op_status_lo;
u32 rsvd24[2];
@@ -706,12 +713,13 @@ struct caam_deco {
u32 rsvd29[48];
u32 descbuf[64]; /* DxDESB - Descriptor buffer */
u32 rscvd30[193];
+#define DESC_DBG_DECO_STAT_HOST_ERR 0x00D00000
+#define DESC_DBG_DECO_STAT_VALID 0x80000000
+#define DESC_DBG_DECO_STAT_MASK 0x00F00000
u32 desc_dbg; /* DxDDR - DECO Debug Register */
u32 rsvd31[126];
};
-/* DECO DBG Register Valid Bit*/
-#define DECO_DBG_VALID 0x80000000
#define DECO_JQCR_WHL 0x20000000
#define DECO_JQCR_FOUR 0x10000000
diff --git a/drivers/crypto/caam/sg_sw_qm.h b/drivers/crypto/caam/sg_sw_qm.h
new file mode 100644
index 0000000..de867ef
--- /dev/null
+++ b/drivers/crypto/caam/sg_sw_qm.h
@@ -0,0 +1,82 @@
+/* Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SG_SW_QM_H
+#define __SG_SW_QM_H
+
+#include "linux/fsl_qman.h"
+
+static inline void dma_to_qm_sg_one(struct qm_sg_entry *qm_sg_ptr,
+ dma_addr_t dma, u32 len, u32 offset)
+{
+ qm_sg_ptr->addr = dma;
+ qm_sg_ptr->extension = 0;
+ qm_sg_ptr->final = 0;
+ qm_sg_ptr->length = len;
+ qm_sg_ptr->__reserved2 = 0;
+ qm_sg_ptr->bpid = 0;
+ qm_sg_ptr->__reserved3 = 0;
+ qm_sg_ptr->offset = offset;
+}
+
+/*
+ * convert scatterlist to h/w link table format
+ * but does not have final bit; instead, returns last entry
+ */
+static inline struct qm_sg_entry *
+sg_to_qm_sg(struct scatterlist *sg, int sg_count,
+ struct qm_sg_entry *qm_sg_ptr, u32 offset)
+{
+ while (sg_count) {
+ dma_to_qm_sg_one(qm_sg_ptr, sg_dma_address(sg),
+ sg_dma_len(sg), offset);
+ qm_sg_ptr++;
+ sg = scatterwalk_sg_next(sg);
+ sg_count--;
+ }
+ return qm_sg_ptr - 1;
+}
+
+
+/*
+ * convert scatterlist to h/w link table format
+ * scatterlist must have been previously dma mapped
+ */
+static inline void sg_to_qm_sg_last(struct scatterlist *sg, int sg_count,
+ struct qm_sg_entry *qm_sg_ptr,
+ u32 offset)
+{
+ qm_sg_ptr = sg_to_qm_sg(sg, sg_count, qm_sg_ptr, offset);
+ qm_sg_ptr->final = 1;
+}
+
+#endif /* __SG_SW_QM_H */
+
diff --git a/drivers/crypto/caam/sg_sw_sec4.h b/drivers/crypto/caam/sg_sw_sec4.h
index e0037c8..b12ff85 100644
--- a/drivers/crypto/caam/sg_sw_sec4.h
+++ b/drivers/crypto/caam/sg_sw_sec4.h
@@ -117,6 +117,21 @@ static int dma_unmap_sg_chained(struct device *dev, struct scatterlist *sg,
return nents;
}
+/* Map SG page in kernel virtual address space and copy */
+static inline void sg_map_copy(u8 *dest, struct scatterlist *sg,
+ int len, int offset)
+{
+ u8 *mapped_addr;
+
+ /*
+ * Page here can be user-space pinned using get_user_pages
+ * Same must be kmapped before use and kunmapped subsequently
+ */
+ mapped_addr = kmap_atomic(sg_page(sg));
+ memcpy(dest, mapped_addr + offset, len);
+ kunmap_atomic(mapped_addr);
+}
+
/* Copy from len bytes of sg to dest, starting from beginning */
static inline void sg_copy(u8 *dest, struct scatterlist *sg, unsigned int len)
{
@@ -124,15 +139,15 @@ static inline void sg_copy(u8 *dest, struct scatterlist *sg, unsigned int len)
int cpy_index = 0, next_cpy_index = current_sg->length;
while (next_cpy_index < len) {
- memcpy(dest + cpy_index, (u8 *) sg_virt(current_sg),
- current_sg->length);
+ sg_map_copy(dest + cpy_index, current_sg, current_sg->length,
+ current_sg->offset);
current_sg = scatterwalk_sg_next(current_sg);
cpy_index = next_cpy_index;
next_cpy_index += current_sg->length;
}
if (cpy_index < len)
- memcpy(dest + cpy_index, (u8 *) sg_virt(current_sg),
- len - cpy_index);
+ sg_map_copy(dest + cpy_index, current_sg, len-cpy_index,
+ current_sg->offset);
}
/* Copy sg data, from to_skip to end, to dest */
@@ -140,7 +155,7 @@ static inline void sg_copy_part(u8 *dest, struct scatterlist *sg,
int to_skip, unsigned int end)
{
struct scatterlist *current_sg = sg;
- int sg_index, cpy_index;
+ int sg_index, cpy_index, offset;
sg_index = current_sg->length;
while (sg_index <= to_skip) {
@@ -148,9 +163,10 @@ static inline void sg_copy_part(u8 *dest, struct scatterlist *sg,
sg_index += current_sg->length;
}
cpy_index = sg_index - to_skip;
- memcpy(dest, (u8 *) sg_virt(current_sg) +
- current_sg->length - cpy_index, cpy_index);
- current_sg = scatterwalk_sg_next(current_sg);
- if (end - sg_index)
+ offset = current_sg->offset + current_sg->length - cpy_index;
+ sg_map_copy(dest, current_sg, cpy_index, offset);
+ if (end - sg_index) {
+ current_sg = scatterwalk_sg_next(current_sg);
sg_copy(dest + cpy_index, current_sg, end - sg_index);
+ }
}
diff --git a/drivers/crypto/dcp.c b/drivers/crypto/dcp.c
index a8a7dd4..247ab80 100644
--- a/drivers/crypto/dcp.c
+++ b/drivers/crypto/dcp.c
@@ -733,12 +733,9 @@ static int dcp_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dev);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!r) {
- dev_err(&pdev->dev, "failed to get IORESOURCE_MEM\n");
- return -ENXIO;
- }
- dev->dcp_regs_base = devm_ioremap(&pdev->dev, r->start,
- resource_size(r));
+ dev->dcp_regs_base = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(dev->dcp_regs_base))
+ return PTR_ERR(dev->dcp_regs_base);
dcp_set(dev, DCP_CTRL_SFRST, DCP_REG_CTRL);
udelay(10);
@@ -762,7 +759,8 @@ static int dcp_probe(struct platform_device *pdev)
return -EIO;
}
dev->dcp_vmi_irq = r->start;
- ret = request_irq(dev->dcp_vmi_irq, dcp_vmi_irq, 0, "dcp", dev);
+ ret = devm_request_irq(&pdev->dev, dev->dcp_vmi_irq, dcp_vmi_irq, 0,
+ "dcp", dev);
if (ret != 0) {
dev_err(&pdev->dev, "can't request_irq (0)\n");
return -EIO;
@@ -771,15 +769,14 @@ static int dcp_probe(struct platform_device *pdev)
r = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
if (!r) {
dev_err(&pdev->dev, "can't get IRQ resource (1)\n");
- ret = -EIO;
- goto err_free_irq0;
+ return -EIO;
}
dev->dcp_irq = r->start;
- ret = request_irq(dev->dcp_irq, dcp_irq, 0, "dcp", dev);
+ ret = devm_request_irq(&pdev->dev, dev->dcp_irq, dcp_irq, 0, "dcp",
+ dev);
if (ret != 0) {
dev_err(&pdev->dev, "can't request_irq (1)\n");
- ret = -EIO;
- goto err_free_irq0;
+ return -EIO;
}
dev->hw_pkg[0] = dma_alloc_coherent(&pdev->dev,
@@ -788,8 +785,7 @@ static int dcp_probe(struct platform_device *pdev)
GFP_KERNEL);
if (!dev->hw_pkg[0]) {
dev_err(&pdev->dev, "Could not allocate hw descriptors\n");
- ret = -ENOMEM;
- goto err_free_irq1;
+ return -ENOMEM;
}
for (i = 1; i < DCP_MAX_PKG; i++) {
@@ -848,16 +844,14 @@ err_unregister:
for (j = 0; j < i; j++)
crypto_unregister_alg(&algs[j]);
err_free_key_iv:
+ tasklet_kill(&dev->done_task);
+ tasklet_kill(&dev->queue_task);
dma_free_coherent(&pdev->dev, 2 * AES_KEYSIZE_128, dev->payload_base,
dev->payload_base_dma);
err_free_hw_packet:
dma_free_coherent(&pdev->dev, DCP_MAX_PKG *
sizeof(struct dcp_hw_packet), dev->hw_pkg[0],
dev->hw_phys_pkg);
-err_free_irq1:
- free_irq(dev->dcp_irq, dev);
-err_free_irq0:
- free_irq(dev->dcp_vmi_irq, dev);
return ret;
}
@@ -868,23 +862,20 @@ static int dcp_remove(struct platform_device *pdev)
int j;
dev = platform_get_drvdata(pdev);
- dma_free_coherent(&pdev->dev,
- DCP_MAX_PKG * sizeof(struct dcp_hw_packet),
- dev->hw_pkg[0], dev->hw_phys_pkg);
-
- dma_free_coherent(&pdev->dev, 2 * AES_KEYSIZE_128, dev->payload_base,
- dev->payload_base_dma);
+ misc_deregister(&dev->dcp_bootstream_misc);
- free_irq(dev->dcp_irq, dev);
- free_irq(dev->dcp_vmi_irq, dev);
+ for (j = 0; j < ARRAY_SIZE(algs); j++)
+ crypto_unregister_alg(&algs[j]);
tasklet_kill(&dev->done_task);
tasklet_kill(&dev->queue_task);
- for (j = 0; j < ARRAY_SIZE(algs); j++)
- crypto_unregister_alg(&algs[j]);
+ dma_free_coherent(&pdev->dev, 2 * AES_KEYSIZE_128, dev->payload_base,
+ dev->payload_base_dma);
- misc_deregister(&dev->dcp_bootstream_misc);
+ dma_free_coherent(&pdev->dev,
+ DCP_MAX_PKG * sizeof(struct dcp_hw_packet),
+ dev->hw_pkg[0], dev->hw_phys_pkg);
return 0;
}
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 661dc3e..30c9c93 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -671,39 +671,20 @@ static int aead_setkey(struct crypto_aead *authenc,
const u8 *key, unsigned int keylen)
{
struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
- struct rtattr *rta = (void *)key;
- struct crypto_authenc_key_param *param;
- unsigned int authkeylen;
- unsigned int enckeylen;
-
- if (!RTA_OK(rta, keylen))
- goto badkey;
+ struct crypto_authenc_keys keys;
- if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
+ if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
goto badkey;
- if (RTA_PAYLOAD(rta) < sizeof(*param))
+ if (keys.authkeylen + keys.enckeylen > TALITOS_MAX_KEY_SIZE)
goto badkey;
- param = RTA_DATA(rta);
- enckeylen = be32_to_cpu(param->enckeylen);
-
- key += RTA_ALIGN(rta->rta_len);
- keylen -= RTA_ALIGN(rta->rta_len);
+ memcpy(ctx->key, keys.authkey, keys.authkeylen);
+ memcpy(&ctx->key[keys.authkeylen], keys.enckey, keys.enckeylen);
- if (keylen < enckeylen)
- goto badkey;
-
- authkeylen = keylen - enckeylen;
-
- if (keylen > TALITOS_MAX_KEY_SIZE)
- goto badkey;
-
- memcpy(&ctx->key, key, keylen);
-
- ctx->keylen = keylen;
- ctx->enckeylen = enckeylen;
- ctx->authkeylen = authkeylen;
+ ctx->keylen = keys.authkeylen + keys.enckeylen;
+ ctx->enckeylen = keys.enckeylen;
+ ctx->authkeylen = keys.authkeylen;
return 0;
@@ -807,7 +788,7 @@ static void ipsec_esp_unmap(struct device *dev,
if (edesc->assoc_chained)
talitos_unmap_sg_chain(dev, areq->assoc, DMA_TO_DEVICE);
- else
+ else if (areq->assoclen)
/* assoc_nents counts also for IV in non-contiguous cases */
dma_unmap_sg(dev, areq->assoc,
edesc->assoc_nents ? edesc->assoc_nents - 1 : 1,
@@ -990,7 +971,11 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
dma_sync_single_for_device(dev, edesc->dma_link_tbl,
edesc->dma_len, DMA_BIDIRECTIONAL);
} else {
- to_talitos_ptr(&desc->ptr[1], sg_dma_address(areq->assoc));
+ if (areq->assoclen)
+ to_talitos_ptr(&desc->ptr[1],
+ sg_dma_address(areq->assoc));
+ else
+ to_talitos_ptr(&desc->ptr[1], edesc->iv_dma);
desc->ptr[1].j_extent = 0;
}
@@ -1125,7 +1110,8 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
unsigned int authsize,
unsigned int ivsize,
int icv_stashing,
- u32 cryptoflags)
+ u32 cryptoflags,
+ bool encrypt)
{
struct talitos_edesc *edesc;
int assoc_nents = 0, src_nents, dst_nents, alloc_len, dma_len;
@@ -1139,10 +1125,10 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
return ERR_PTR(-EINVAL);
}
- if (iv)
+ if (ivsize)
iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
- if (assoc) {
+ if (assoclen) {
/*
* Currently it is assumed that iv is provided whenever assoc
* is.
@@ -1158,19 +1144,17 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
assoc_nents = assoc_nents ? assoc_nents + 1 : 2;
}
- src_nents = sg_count(src, cryptlen + authsize, &src_chained);
- src_nents = (src_nents == 1) ? 0 : src_nents;
-
- if (!dst) {
- dst_nents = 0;
- } else {
- if (dst == src) {
- dst_nents = src_nents;
- } else {
- dst_nents = sg_count(dst, cryptlen + authsize,
- &dst_chained);
- dst_nents = (dst_nents == 1) ? 0 : dst_nents;
- }
+ if (!dst || dst == src) {
+ src_nents = sg_count(src, cryptlen + authsize, &src_chained);
+ src_nents = (src_nents == 1) ? 0 : src_nents;
+ dst_nents = dst ? src_nents : 0;
+ } else { /* dst && dst != src*/
+ src_nents = sg_count(src, cryptlen + (encrypt ? 0 : authsize),
+ &src_chained);
+ src_nents = (src_nents == 1) ? 0 : src_nents;
+ dst_nents = sg_count(dst, cryptlen + (encrypt ? authsize : 0),
+ &dst_chained);
+ dst_nents = (dst_nents == 1) ? 0 : dst_nents;
}
/*
@@ -1190,9 +1174,16 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
edesc = kmalloc(alloc_len, GFP_DMA | flags);
if (!edesc) {
- talitos_unmap_sg_chain(dev, assoc, DMA_TO_DEVICE);
+ if (assoc_chained)
+ talitos_unmap_sg_chain(dev, assoc, DMA_TO_DEVICE);
+ else if (assoclen)
+ dma_unmap_sg(dev, assoc,
+ assoc_nents ? assoc_nents - 1 : 1,
+ DMA_TO_DEVICE);
+
if (iv_dma)
dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
+
dev_err(dev, "could not allocate edescriptor\n");
return ERR_PTR(-ENOMEM);
}
@@ -1214,7 +1205,7 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
}
static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
- int icv_stashing)
+ int icv_stashing, bool encrypt)
{
struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
@@ -1223,7 +1214,7 @@ static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
return talitos_edesc_alloc(ctx->dev, areq->assoc, areq->src, areq->dst,
iv, areq->assoclen, areq->cryptlen,
ctx->authsize, ivsize, icv_stashing,
- areq->base.flags);
+ areq->base.flags, encrypt);
}
static int aead_encrypt(struct aead_request *req)
@@ -1233,7 +1224,7 @@ static int aead_encrypt(struct aead_request *req)
struct talitos_edesc *edesc;
/* allocate extended descriptor */
- edesc = aead_edesc_alloc(req, req->iv, 0);
+ edesc = aead_edesc_alloc(req, req->iv, 0, true);
if (IS_ERR(edesc))
return PTR_ERR(edesc);
@@ -1256,7 +1247,7 @@ static int aead_decrypt(struct aead_request *req)
req->cryptlen -= authsize;
/* allocate extended descriptor */
- edesc = aead_edesc_alloc(req, req->iv, 1);
+ edesc = aead_edesc_alloc(req, req->iv, 1, false);
if (IS_ERR(edesc))
return PTR_ERR(edesc);
@@ -1302,7 +1293,7 @@ static int aead_givencrypt(struct aead_givcrypt_request *req)
struct talitos_edesc *edesc;
/* allocate extended descriptor */
- edesc = aead_edesc_alloc(areq, req->giv, 0);
+ edesc = aead_edesc_alloc(areq, req->giv, 0, true);
if (IS_ERR(edesc))
return PTR_ERR(edesc);
@@ -1458,7 +1449,7 @@ static int common_nonsnoop(struct talitos_edesc *edesc,
}
static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
- areq)
+ areq, bool encrypt)
{
struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(areq);
struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
@@ -1466,7 +1457,7 @@ static struct talitos_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request *
return talitos_edesc_alloc(ctx->dev, NULL, areq->src, areq->dst,
areq->info, 0, areq->nbytes, 0, ivsize, 0,
- areq->base.flags);
+ areq->base.flags, encrypt);
}
static int ablkcipher_encrypt(struct ablkcipher_request *areq)
@@ -1476,7 +1467,7 @@ static int ablkcipher_encrypt(struct ablkcipher_request *areq)
struct talitos_edesc *edesc;
/* allocate extended descriptor */
- edesc = ablkcipher_edesc_alloc(areq);
+ edesc = ablkcipher_edesc_alloc(areq, true);
if (IS_ERR(edesc))
return PTR_ERR(edesc);
@@ -1493,7 +1484,7 @@ static int ablkcipher_decrypt(struct ablkcipher_request *areq)
struct talitos_edesc *edesc;
/* allocate extended descriptor */
- edesc = ablkcipher_edesc_alloc(areq);
+ edesc = ablkcipher_edesc_alloc(areq, false);
if (IS_ERR(edesc))
return PTR_ERR(edesc);
@@ -1645,7 +1636,7 @@ static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,
struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
return talitos_edesc_alloc(ctx->dev, NULL, req_ctx->psrc, NULL, NULL, 0,
- nbytes, 0, 0, 0, areq->base.flags);
+ nbytes, 0, 0, 0, areq->base.flags, false);
}
static int ahash_init(struct ahash_request *areq)
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index b61c5fc..03d3975 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -89,14 +89,15 @@ config AT_HDMAC
Support the Atmel AHB DMA controller.
config FSL_DMA
- tristate "Freescale Elo and Elo Plus DMA support"
+ tristate "Freescale Elo series DMA support"
depends on FSL_SOC
select DMA_ENGINE
select ASYNC_TX_ENABLE_CHANNEL_SWITCH
---help---
- Enable support for the Freescale Elo and Elo Plus DMA controllers.
- The Elo is the DMA controller on some 82xx and 83xx parts, and the
- Elo Plus is the DMA controller on 85xx and 86xx parts.
+ Enable support for the Freescale Elo series DMA controllers.
+ The Elo is the DMA controller on some mpc82xx and mpc83xx parts, the
+ EloPlus is on mpc85xx and mpc86xx and Pxxx parts, and the Elo3 is on
+ some Txxx and Bxxx parts.
config MPC512X_DMA
tristate "Freescale MPC512x built-in DMA engine support"
@@ -154,6 +155,18 @@ config TEGRA20_APB_DMA
This DMA controller transfers data from memory to peripheral fifo
or vice versa. It does not support memory to memory data transfer.
+config S3C24XX_DMAC
+ tristate "Samsung S3C24XX DMA support"
+ depends on ARCH_S3C24XX && !S3C24XX_DMA
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
+ help
+ Support for the Samsung S3C24XX DMA controller driver. The
+ DMA controller is having multiple DMA channels which can be
+ configured for different peripherals like audio, UART, SPI.
+ The DMA controller can transfer data from memory to peripheral,
+ periphal to memory, periphal to periphal and memory to memory.
+
source "drivers/dma/sh/Kconfig"
config COH901318
@@ -195,7 +208,7 @@ config SIRF_DMA
config TI_EDMA
bool "TI EDMA support"
- depends on ARCH_DAVINCI || ARCH_OMAP
+ depends on ARCH_DAVINCI || ARCH_OMAP || ARCH_KEYSTONE
select DMA_ENGINE
select DMA_VIRTUAL_CHANNELS
select TI_PRIV_EDMA
@@ -301,7 +314,7 @@ config MMP_PDMA
depends on (ARCH_MMP || ARCH_PXA)
select DMA_ENGINE
help
- Support the MMP PDMA engine for PXA and MMP platfrom.
+ Support the MMP PDMA engine for PXA and MMP platform.
config DMA_JZ4740
tristate "JZ4740 DMA support"
@@ -318,6 +331,17 @@ config K3_DMA
Support the DMA engine for Hisilicon K3 platform
devices.
+config FSL_RAID
+ tristate "Freescale RAID Engine Device Driver"
+ depends on FSL_SOC && !FSL_DMA
+ select DMA_ENGINE
+ select ASYNC_TX_ENABLE_CHANNEL_SWITCH
+ ---help---
+ Enable support for Freescale RAID Engine. RAID Engine is
+ available on some QorIQ SoCs (like P5020). It has
+ the capability to offload RAID5/RAID6 operations from CPU.
+ RAID5 is XOR and memcpy. RAID6 is P/Q and memcpy
+
config DMA_ENGINE
bool
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index db89035..2d8b4f5 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_DMATEST) += dmatest.o
obj-$(CONFIG_INTEL_IOATDMA) += ioat/
obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
obj-$(CONFIG_FSL_DMA) += fsldma.o
+obj-$(CONFIG_FSL_RAID) += fsl_raid.o
obj-$(CONFIG_MPC512X_DMA) += mpc512x_dma.o
obj-$(CONFIG_PPC_BESTCOMM) += bestcomm/
obj-$(CONFIG_MV_XOR) += mv_xor.o
@@ -30,6 +31,7 @@ obj-$(CONFIG_SIRF_DMA) += sirf-dma.o
obj-$(CONFIG_TI_EDMA) += edma.o
obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o
obj-$(CONFIG_TEGRA20_APB_DMA) += tegra20-apb-dma.o
+obj-$(CONFIG_S3C24XX_DMAC) += s3c24xx-dma.o
obj-$(CONFIG_PL330_DMA) += pl330.o
obj-$(CONFIG_PCH_DMA) += pch_dma.o
obj-$(CONFIG_AMBA_PL08X) += amba-pl08x.o
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index fce46c5..16a2aa2 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -1164,42 +1164,12 @@ static void pl08x_free_txd(struct pl08x_driver_data *pl08x,
kfree(txd);
}
-static void pl08x_unmap_buffers(struct pl08x_txd *txd)
-{
- struct device *dev = txd->vd.tx.chan->device->dev;
- struct pl08x_sg *dsg;
-
- if (!(txd->vd.tx.flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
- if (txd->vd.tx.flags & DMA_COMPL_SRC_UNMAP_SINGLE)
- list_for_each_entry(dsg, &txd->dsg_list, node)
- dma_unmap_single(dev, dsg->src_addr, dsg->len,
- DMA_TO_DEVICE);
- else {
- list_for_each_entry(dsg, &txd->dsg_list, node)
- dma_unmap_page(dev, dsg->src_addr, dsg->len,
- DMA_TO_DEVICE);
- }
- }
- if (!(txd->vd.tx.flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
- if (txd->vd.tx.flags & DMA_COMPL_DEST_UNMAP_SINGLE)
- list_for_each_entry(dsg, &txd->dsg_list, node)
- dma_unmap_single(dev, dsg->dst_addr, dsg->len,
- DMA_FROM_DEVICE);
- else
- list_for_each_entry(dsg, &txd->dsg_list, node)
- dma_unmap_page(dev, dsg->dst_addr, dsg->len,
- DMA_FROM_DEVICE);
- }
-}
-
static void pl08x_desc_free(struct virt_dma_desc *vd)
{
struct pl08x_txd *txd = to_pl08x_txd(&vd->tx);
struct pl08x_dma_chan *plchan = to_pl08x_chan(vd->tx.chan);
- if (!plchan->slave)
- pl08x_unmap_buffers(txd);
-
+ dma_descriptor_unmap(txd);
if (!txd->done)
pl08x_release_mux(plchan);
@@ -1252,7 +1222,7 @@ static enum dma_status pl08x_dma_tx_status(struct dma_chan *chan,
size_t bytes = 0;
ret = dma_cookie_status(chan, cookie, txstate);
- if (ret == DMA_SUCCESS)
+ if (ret == DMA_COMPLETE)
return ret;
/*
@@ -1267,7 +1237,7 @@ static enum dma_status pl08x_dma_tx_status(struct dma_chan *chan,
spin_lock_irqsave(&plchan->vc.lock, flags);
ret = dma_cookie_status(chan, cookie, txstate);
- if (ret != DMA_SUCCESS) {
+ if (ret != DMA_COMPLETE) {
vd = vchan_find_desc(&plchan->vc, cookie);
if (vd) {
/* On the issued list, so hasn't been processed yet */
@@ -2055,6 +2025,11 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
if (ret)
return ret;
+ /* Ensure that we can do DMA */
+ ret = dma_set_mask_and_coherent(&adev->dev, DMA_BIT_MASK(32));
+ if (ret)
+ goto out_no_pl08x;
+
/* Create the driver state holder */
pl08x = kzalloc(sizeof(*pl08x), GFP_KERNEL);
if (!pl08x) {
@@ -2133,8 +2108,7 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
writel(0x000000FF, pl08x->base + PL080_ERR_CLEAR);
writel(0x000000FF, pl08x->base + PL080_TC_CLEAR);
- ret = request_irq(adev->irq[0], pl08x_irq, IRQF_DISABLED,
- DRIVER_NAME, pl08x);
+ ret = request_irq(adev->irq[0], pl08x_irq, 0, DRIVER_NAME, pl08x);
if (ret) {
dev_err(&adev->dev, "%s failed to request interrupt %d\n",
__func__, adev->irq[0]);
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index c787f38..e2c04dc 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -344,31 +344,7 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc)
/* move myself to free_list */
list_move(&desc->desc_node, &atchan->free_list);
- /* unmap dma addresses (not on slave channels) */
- if (!atchan->chan_common.private) {
- struct device *parent = chan2parent(&atchan->chan_common);
- if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
- if (txd->flags & DMA_COMPL_DEST_UNMAP_SINGLE)
- dma_unmap_single(parent,
- desc->lli.daddr,
- desc->len, DMA_FROM_DEVICE);
- else
- dma_unmap_page(parent,
- desc->lli.daddr,
- desc->len, DMA_FROM_DEVICE);
- }
- if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
- if (txd->flags & DMA_COMPL_SRC_UNMAP_SINGLE)
- dma_unmap_single(parent,
- desc->lli.saddr,
- desc->len, DMA_TO_DEVICE);
- else
- dma_unmap_page(parent,
- desc->lli.saddr,
- desc->len, DMA_TO_DEVICE);
- }
- }
-
+ dma_descriptor_unmap(txd);
/* for cyclic transfers,
* no need to replay callback function while stopping */
if (!atc_chan_is_cyclic(atchan)) {
@@ -1102,7 +1078,7 @@ atc_tx_status(struct dma_chan *chan,
int bytes = 0;
ret = dma_cookie_status(chan, cookie, txstate);
- if (ret == DMA_SUCCESS)
+ if (ret == DMA_COMPLETE)
return ret;
/*
* There's no point calculating the residue if there's
diff --git a/drivers/dma/bestcomm/sram.c b/drivers/dma/bestcomm/sram.c
index 5e2ed30..2074e0e 100644
--- a/drivers/dma/bestcomm/sram.c
+++ b/drivers/dma/bestcomm/sram.c
@@ -19,6 +19,7 @@
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <asm/io.h>
#include <asm/mmu.h>
diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c
index 31011d2..3c6716e 100644
--- a/drivers/dma/coh901318.c
+++ b/drivers/dma/coh901318.c
@@ -2369,7 +2369,7 @@ coh901318_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
enum dma_status ret;
ret = dma_cookie_status(chan, cookie, txstate);
- if (ret == DMA_SUCCESS)
+ if (ret == DMA_COMPLETE)
return ret;
dma_set_residue(txstate, coh901318_get_bytes_left(chan));
@@ -2694,7 +2694,7 @@ static int __init coh901318_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
- err = devm_request_irq(&pdev->dev, irq, dma_irq_handler, IRQF_DISABLED,
+ err = devm_request_irq(&pdev->dev, irq, dma_irq_handler, 0,
"coh901318", base);
if (err)
return err;
diff --git a/drivers/dma/cppi41.c b/drivers/dma/cppi41.c
index 7c82b92..c29dacf 100644
--- a/drivers/dma/cppi41.c
+++ b/drivers/dma/cppi41.c
@@ -141,6 +141,9 @@ struct cppi41_dd {
const struct chan_queues *queues_rx;
const struct chan_queues *queues_tx;
struct chan_queues td_queue;
+
+ /* context for suspend/resume */
+ unsigned int dma_tdfdq;
};
#define FIST_COMPLETION_QUEUE 93
@@ -263,6 +266,15 @@ static u32 pd_trans_len(u32 val)
return val & ((1 << (DESC_LENGTH_BITS_NUM + 1)) - 1);
}
+static u32 cppi41_pop_desc(struct cppi41_dd *cdd, unsigned queue_num)
+{
+ u32 desc;
+
+ desc = cppi_readl(cdd->qmgr_mem + QMGR_QUEUE_D(queue_num));
+ desc &= ~0x1f;
+ return desc;
+}
+
static irqreturn_t cppi41_irq(int irq, void *data)
{
struct cppi41_dd *cdd = data;
@@ -300,8 +312,7 @@ static irqreturn_t cppi41_irq(int irq, void *data)
q_num = __fls(val);
val &= ~(1 << q_num);
q_num += 32 * i;
- desc = cppi_readl(cdd->qmgr_mem + QMGR_QUEUE_D(q_num));
- desc &= ~0x1f;
+ desc = cppi41_pop_desc(cdd, q_num);
c = desc_to_chan(cdd, desc);
if (WARN_ON(!c)) {
pr_err("%s() q %d desc %08x\n", __func__,
@@ -353,7 +364,7 @@ static enum dma_status cppi41_dma_tx_status(struct dma_chan *chan,
/* lock */
ret = dma_cookie_status(chan, cookie, txstate);
- if (txstate && ret == DMA_SUCCESS)
+ if (txstate && ret == DMA_COMPLETE)
txstate->residue = c->residue;
/* unlock */
@@ -517,15 +528,6 @@ static void cppi41_compute_td_desc(struct cppi41_desc *d)
d->pd0 = DESC_TYPE_TEARD << DESC_TYPE;
}
-static u32 cppi41_pop_desc(struct cppi41_dd *cdd, unsigned queue_num)
-{
- u32 desc;
-
- desc = cppi_readl(cdd->qmgr_mem + QMGR_QUEUE_D(queue_num));
- desc &= ~0x1f;
- return desc;
-}
-
static int cppi41_tear_down_chan(struct cppi41_channel *c)
{
struct cppi41_dd *cdd = c->cdd;
@@ -561,36 +563,26 @@ static int cppi41_tear_down_chan(struct cppi41_channel *c)
c->td_retry = 100;
}
- if (!c->td_seen) {
- unsigned td_comp_queue;
+ if (!c->td_seen || !c->td_desc_seen) {
- if (c->is_tx)
- td_comp_queue = cdd->td_queue.complete;
- else
- td_comp_queue = c->q_comp_num;
+ desc_phys = cppi41_pop_desc(cdd, cdd->td_queue.complete);
+ if (!desc_phys)
+ desc_phys = cppi41_pop_desc(cdd, c->q_comp_num);
- desc_phys = cppi41_pop_desc(cdd, td_comp_queue);
- if (desc_phys) {
- __iormb();
+ if (desc_phys == c->desc_phys) {
+ c->td_desc_seen = 1;
+
+ } else if (desc_phys == td_desc_phys) {
+ u32 pd0;
- if (desc_phys == td_desc_phys) {
- u32 pd0;
- pd0 = td->pd0;
- WARN_ON((pd0 >> DESC_TYPE) != DESC_TYPE_TEARD);
- WARN_ON(!c->is_tx && !(pd0 & TD_DESC_IS_RX));
- WARN_ON((pd0 & 0x1f) != c->port_num);
- } else {
- WARN_ON_ONCE(1);
- }
- c->td_seen = 1;
- }
- }
- if (!c->td_desc_seen) {
- desc_phys = cppi41_pop_desc(cdd, c->q_comp_num);
- if (desc_phys) {
__iormb();
- WARN_ON(c->desc_phys != desc_phys);
- c->td_desc_seen = 1;
+ pd0 = td->pd0;
+ WARN_ON((pd0 >> DESC_TYPE) != DESC_TYPE_TEARD);
+ WARN_ON(!c->is_tx && !(pd0 & TD_DESC_IS_RX));
+ WARN_ON((pd0 & 0x1f) != c->port_num);
+ c->td_seen = 1;
+ } else if (desc_phys) {
+ WARN_ON_ONCE(1);
}
}
c->td_retry--;
@@ -609,7 +601,7 @@ static int cppi41_tear_down_chan(struct cppi41_channel *c)
WARN_ON(!c->td_retry);
if (!c->td_desc_seen) {
- desc_phys = cppi_readl(cdd->qmgr_mem + QMGR_QUEUE_D(c->q_num));
+ desc_phys = cppi41_pop_desc(cdd, c->q_num);
WARN_ON(!desc_phys);
}
@@ -674,14 +666,14 @@ static void cleanup_chans(struct cppi41_dd *cdd)
}
}
-static int cppi41_add_chans(struct platform_device *pdev, struct cppi41_dd *cdd)
+static int cppi41_add_chans(struct device *dev, struct cppi41_dd *cdd)
{
struct cppi41_channel *cchan;
int i;
int ret;
u32 n_chans;
- ret = of_property_read_u32(pdev->dev.of_node, "#dma-channels",
+ ret = of_property_read_u32(dev->of_node, "#dma-channels",
&n_chans);
if (ret)
return ret;
@@ -719,7 +711,7 @@ err:
return -ENOMEM;
}
-static void purge_descs(struct platform_device *pdev, struct cppi41_dd *cdd)
+static void purge_descs(struct device *dev, struct cppi41_dd *cdd)
{
unsigned int mem_decs;
int i;
@@ -731,7 +723,7 @@ static void purge_descs(struct platform_device *pdev, struct cppi41_dd *cdd)
cppi_writel(0, cdd->qmgr_mem + QMGR_MEMBASE(i));
cppi_writel(0, cdd->qmgr_mem + QMGR_MEMCTRL(i));
- dma_free_coherent(&pdev->dev, mem_decs, cdd->cd,
+ dma_free_coherent(dev, mem_decs, cdd->cd,
cdd->descs_phys);
}
}
@@ -741,19 +733,19 @@ static void disable_sched(struct cppi41_dd *cdd)
cppi_writel(0, cdd->sched_mem + DMA_SCHED_CTRL);
}
-static void deinit_cpii41(struct platform_device *pdev, struct cppi41_dd *cdd)
+static void deinit_cppi41(struct device *dev, struct cppi41_dd *cdd)
{
disable_sched(cdd);
- purge_descs(pdev, cdd);
+ purge_descs(dev, cdd);
cppi_writel(0, cdd->qmgr_mem + QMGR_LRAM0_BASE);
cppi_writel(0, cdd->qmgr_mem + QMGR_LRAM0_BASE);
- dma_free_coherent(&pdev->dev, QMGR_SCRATCH_SIZE, cdd->qmgr_scratch,
+ dma_free_coherent(dev, QMGR_SCRATCH_SIZE, cdd->qmgr_scratch,
cdd->scratch_phys);
}
-static int init_descs(struct platform_device *pdev, struct cppi41_dd *cdd)
+static int init_descs(struct device *dev, struct cppi41_dd *cdd)
{
unsigned int desc_size;
unsigned int mem_decs;
@@ -777,7 +769,7 @@ static int init_descs(struct platform_device *pdev, struct cppi41_dd *cdd)
reg |= ilog2(ALLOC_DECS_NUM) - 5;
BUILD_BUG_ON(DESCS_AREAS != 1);
- cdd->cd = dma_alloc_coherent(&pdev->dev, mem_decs,
+ cdd->cd = dma_alloc_coherent(dev, mem_decs,
&cdd->descs_phys, GFP_KERNEL);
if (!cdd->cd)
return -ENOMEM;
@@ -813,12 +805,12 @@ static void init_sched(struct cppi41_dd *cdd)
cppi_writel(reg, cdd->sched_mem + DMA_SCHED_CTRL);
}
-static int init_cppi41(struct platform_device *pdev, struct cppi41_dd *cdd)
+static int init_cppi41(struct device *dev, struct cppi41_dd *cdd)
{
int ret;
BUILD_BUG_ON(QMGR_SCRATCH_SIZE > ((1 << 14) - 1));
- cdd->qmgr_scratch = dma_alloc_coherent(&pdev->dev, QMGR_SCRATCH_SIZE,
+ cdd->qmgr_scratch = dma_alloc_coherent(dev, QMGR_SCRATCH_SIZE,
&cdd->scratch_phys, GFP_KERNEL);
if (!cdd->qmgr_scratch)
return -ENOMEM;
@@ -827,7 +819,7 @@ static int init_cppi41(struct platform_device *pdev, struct cppi41_dd *cdd)
cppi_writel(QMGR_SCRATCH_SIZE, cdd->qmgr_mem + QMGR_LRAM_SIZE);
cppi_writel(0, cdd->qmgr_mem + QMGR_LRAM1_BASE);
- ret = init_descs(pdev, cdd);
+ ret = init_descs(dev, cdd);
if (ret)
goto err_td;
@@ -835,7 +827,7 @@ static int init_cppi41(struct platform_device *pdev, struct cppi41_dd *cdd)
init_sched(cdd);
return 0;
err_td:
- deinit_cpii41(pdev, cdd);
+ deinit_cppi41(dev, cdd);
return ret;
}
@@ -914,11 +906,11 @@ static const struct of_device_id cppi41_dma_ids[] = {
};
MODULE_DEVICE_TABLE(of, cppi41_dma_ids);
-static const struct cppi_glue_infos *get_glue_info(struct platform_device *pdev)
+static const struct cppi_glue_infos *get_glue_info(struct device *dev)
{
const struct of_device_id *of_id;
- of_id = of_match_node(cppi41_dma_ids, pdev->dev.of_node);
+ of_id = of_match_node(cppi41_dma_ids, dev->of_node);
if (!of_id)
return NULL;
return of_id->data;
@@ -927,11 +919,12 @@ static const struct cppi_glue_infos *get_glue_info(struct platform_device *pdev)
static int cppi41_dma_probe(struct platform_device *pdev)
{
struct cppi41_dd *cdd;
+ struct device *dev = &pdev->dev;
const struct cppi_glue_infos *glue_info;
int irq;
int ret;
- glue_info = get_glue_info(pdev);
+ glue_info = get_glue_info(dev);
if (!glue_info)
return -EINVAL;
@@ -946,14 +939,14 @@ static int cppi41_dma_probe(struct platform_device *pdev)
cdd->ddev.device_issue_pending = cppi41_dma_issue_pending;
cdd->ddev.device_prep_slave_sg = cppi41_dma_prep_slave_sg;
cdd->ddev.device_control = cppi41_dma_control;
- cdd->ddev.dev = &pdev->dev;
+ cdd->ddev.dev = dev;
INIT_LIST_HEAD(&cdd->ddev.channels);
cpp41_dma_info.dma_cap = cdd->ddev.cap_mask;
- cdd->usbss_mem = of_iomap(pdev->dev.of_node, 0);
- cdd->ctrl_mem = of_iomap(pdev->dev.of_node, 1);
- cdd->sched_mem = of_iomap(pdev->dev.of_node, 2);
- cdd->qmgr_mem = of_iomap(pdev->dev.of_node, 3);
+ cdd->usbss_mem = of_iomap(dev->of_node, 0);
+ cdd->ctrl_mem = of_iomap(dev->of_node, 1);
+ cdd->sched_mem = of_iomap(dev->of_node, 2);
+ cdd->qmgr_mem = of_iomap(dev->of_node, 3);
if (!cdd->usbss_mem || !cdd->ctrl_mem || !cdd->sched_mem ||
!cdd->qmgr_mem) {
@@ -961,31 +954,31 @@ static int cppi41_dma_probe(struct platform_device *pdev)
goto err_remap;
}
- pm_runtime_enable(&pdev->dev);
- ret = pm_runtime_get_sync(&pdev->dev);
- if (ret)
+ pm_runtime_enable(dev);
+ ret = pm_runtime_get_sync(dev);
+ if (ret < 0)
goto err_get_sync;
cdd->queues_rx = glue_info->queues_rx;
cdd->queues_tx = glue_info->queues_tx;
cdd->td_queue = glue_info->td_queue;
- ret = init_cppi41(pdev, cdd);
+ ret = init_cppi41(dev, cdd);
if (ret)
goto err_init_cppi;
- ret = cppi41_add_chans(pdev, cdd);
+ ret = cppi41_add_chans(dev, cdd);
if (ret)
goto err_chans;
- irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+ irq = irq_of_parse_and_map(dev->of_node, 0);
if (!irq)
goto err_irq;
cppi_writel(USBSS_IRQ_PD_COMP, cdd->usbss_mem + USBSS_IRQ_ENABLER);
ret = request_irq(irq, glue_info->isr, IRQF_SHARED,
- dev_name(&pdev->dev), cdd);
+ dev_name(dev), cdd);
if (ret)
goto err_irq;
cdd->irq = irq;
@@ -994,7 +987,7 @@ static int cppi41_dma_probe(struct platform_device *pdev)
if (ret)
goto err_dma_reg;
- ret = of_dma_controller_register(pdev->dev.of_node,
+ ret = of_dma_controller_register(dev->of_node,
cppi41_dma_xlate, &cpp41_dma_info);
if (ret)
goto err_of;
@@ -1009,11 +1002,11 @@ err_irq:
cppi_writel(0, cdd->usbss_mem + USBSS_IRQ_CLEARR);
cleanup_chans(cdd);
err_chans:
- deinit_cpii41(pdev, cdd);
+ deinit_cppi41(dev, cdd);
err_init_cppi:
- pm_runtime_put(&pdev->dev);
+ pm_runtime_put(dev);
err_get_sync:
- pm_runtime_disable(&pdev->dev);
+ pm_runtime_disable(dev);
iounmap(cdd->usbss_mem);
iounmap(cdd->ctrl_mem);
iounmap(cdd->sched_mem);
@@ -1033,7 +1026,7 @@ static int cppi41_dma_remove(struct platform_device *pdev)
cppi_writel(0, cdd->usbss_mem + USBSS_IRQ_CLEARR);
free_irq(cdd->irq, cdd);
cleanup_chans(cdd);
- deinit_cpii41(pdev, cdd);
+ deinit_cppi41(&pdev->dev, cdd);
iounmap(cdd->usbss_mem);
iounmap(cdd->ctrl_mem);
iounmap(cdd->sched_mem);
@@ -1044,12 +1037,53 @@ static int cppi41_dma_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int cppi41_suspend(struct device *dev)
+{
+ struct cppi41_dd *cdd = dev_get_drvdata(dev);
+
+ cdd->dma_tdfdq = cppi_readl(cdd->ctrl_mem + DMA_TDFDQ);
+ cppi_writel(0, cdd->usbss_mem + USBSS_IRQ_CLEARR);
+ disable_sched(cdd);
+
+ return 0;
+}
+
+static int cppi41_resume(struct device *dev)
+{
+ struct cppi41_dd *cdd = dev_get_drvdata(dev);
+ struct cppi41_channel *c;
+ int i;
+
+ for (i = 0; i < DESCS_AREAS; i++)
+ cppi_writel(cdd->descs_phys, cdd->qmgr_mem + QMGR_MEMBASE(i));
+
+ list_for_each_entry(c, &cdd->ddev.channels, chan.device_node)
+ if (!c->is_tx)
+ cppi_writel(c->q_num, c->gcr_reg + RXHPCRA0);
+
+ init_sched(cdd);
+
+ cppi_writel(cdd->dma_tdfdq, cdd->ctrl_mem + DMA_TDFDQ);
+ cppi_writel(cdd->scratch_phys, cdd->qmgr_mem + QMGR_LRAM0_BASE);
+ cppi_writel(QMGR_SCRATCH_SIZE, cdd->qmgr_mem + QMGR_LRAM_SIZE);
+ cppi_writel(0, cdd->qmgr_mem + QMGR_LRAM1_BASE);
+
+ cppi_writel(USBSS_IRQ_PD_COMP, cdd->usbss_mem + USBSS_IRQ_ENABLER);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(cppi41_pm_ops, cppi41_suspend, cppi41_resume);
+
static struct platform_driver cpp41_dma_driver = {
.probe = cppi41_dma_probe,
.remove = cppi41_dma_remove,
.driver = {
.name = "cppi41-dma-engine",
.owner = THIS_MODULE,
+ .pm = &cppi41_pm_ops,
.of_match_table = of_match_ptr(cppi41_dma_ids),
},
};
diff --git a/drivers/dma/dma-jz4740.c b/drivers/dma/dma-jz4740.c
index b0c0c82..94c380f 100644
--- a/drivers/dma/dma-jz4740.c
+++ b/drivers/dma/dma-jz4740.c
@@ -491,7 +491,7 @@ static enum dma_status jz4740_dma_tx_status(struct dma_chan *c,
unsigned long flags;
status = dma_cookie_status(c, cookie, state);
- if (status == DMA_SUCCESS || !state)
+ if (status == DMA_COMPLETE || !state)
return status;
spin_lock_irqsave(&chan->vchan.lock, flags);
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 9162ac8..ea806bd 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -65,6 +65,7 @@
#include <linux/acpi.h>
#include <linux/acpi_dma.h>
#include <linux/of_dma.h>
+#include <linux/mempool.h>
static DEFINE_MUTEX(dma_list_mutex);
static DEFINE_IDR(dma_idr);
@@ -901,98 +902,132 @@ void dma_async_device_unregister(struct dma_device *device)
}
EXPORT_SYMBOL(dma_async_device_unregister);
-/**
- * dma_async_memcpy_buf_to_buf - offloaded copy between virtual addresses
- * @chan: DMA channel to offload copy to
- * @dest: destination address (virtual)
- * @src: source address (virtual)
- * @len: length
- *
- * Both @dest and @src must be mappable to a bus address according to the
- * DMA mapping API rules for streaming mappings.
- * Both @dest and @src must stay memory resident (kernel memory or locked
- * user space pages).
- */
-dma_cookie_t
-dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest,
- void *src, size_t len)
-{
- struct dma_device *dev = chan->device;
- struct dma_async_tx_descriptor *tx;
- dma_addr_t dma_dest, dma_src;
- dma_cookie_t cookie;
- unsigned long flags;
+struct dmaengine_unmap_pool {
+ struct kmem_cache *cache;
+ const char *name;
+ mempool_t *pool;
+ size_t size;
+};
- dma_src = dma_map_single(dev->dev, src, len, DMA_TO_DEVICE);
- dma_dest = dma_map_single(dev->dev, dest, len, DMA_FROM_DEVICE);
- flags = DMA_CTRL_ACK |
- DMA_COMPL_SRC_UNMAP_SINGLE |
- DMA_COMPL_DEST_UNMAP_SINGLE;
- tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, flags);
+#define __UNMAP_POOL(x) { .size = x, .name = "dmaengine-unmap-" __stringify(x) }
+static struct dmaengine_unmap_pool unmap_pool[] = {
+ __UNMAP_POOL(2),
+ #if IS_ENABLED(CONFIG_ASYNC_TX_DMA)
+ __UNMAP_POOL(16),
+ __UNMAP_POOL(128),
+ __UNMAP_POOL(256),
+ #endif
+};
- if (!tx) {
- dma_unmap_single(dev->dev, dma_src, len, DMA_TO_DEVICE);
- dma_unmap_single(dev->dev, dma_dest, len, DMA_FROM_DEVICE);
- return -ENOMEM;
+static struct dmaengine_unmap_pool *__get_unmap_pool(int nr)
+{
+ int order = get_count_order(nr);
+
+ switch (order) {
+ case 0 ... 1:
+ return &unmap_pool[0];
+ case 2 ... 4:
+ return &unmap_pool[1];
+ case 5 ... 7:
+ return &unmap_pool[2];
+ case 8:
+ return &unmap_pool[3];
+ default:
+ BUG();
+ return NULL;
}
+}
- tx->callback = NULL;
- cookie = tx->tx_submit(tx);
+static void dmaengine_unmap(struct kref *kref)
+{
+ struct dmaengine_unmap_data *unmap = container_of(kref, typeof(*unmap), kref);
+ struct device *dev = unmap->dev;
+ int cnt, i;
+
+ cnt = unmap->to_cnt;
+ for (i = 0; i < cnt; i++)
+ dma_unmap_page(dev, unmap->addr[i], unmap->len,
+ DMA_TO_DEVICE);
+ cnt += unmap->from_cnt;
+ for (; i < cnt; i++)
+ dma_unmap_page(dev, unmap->addr[i], unmap->len,
+ DMA_FROM_DEVICE);
+ cnt += unmap->bidi_cnt;
+ for (; i < cnt; i++) {
+ if (unmap->addr[i] == 0)
+ continue;
+ dma_unmap_page(dev, unmap->addr[i], unmap->len,
+ DMA_BIDIRECTIONAL);
+ }
+ mempool_free(unmap, __get_unmap_pool(cnt)->pool);
+}
- preempt_disable();
- __this_cpu_add(chan->local->bytes_transferred, len);
- __this_cpu_inc(chan->local->memcpy_count);
- preempt_enable();
+void dmaengine_unmap_put(struct dmaengine_unmap_data *unmap)
+{
+ if (unmap)
+ kref_put(&unmap->kref, dmaengine_unmap);
+}
+EXPORT_SYMBOL_GPL(dmaengine_unmap_put);
- return cookie;
+static void dmaengine_destroy_unmap_pool(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(unmap_pool); i++) {
+ struct dmaengine_unmap_pool *p = &unmap_pool[i];
+
+ if (p->pool)
+ mempool_destroy(p->pool);
+ p->pool = NULL;
+ if (p->cache)
+ kmem_cache_destroy(p->cache);
+ p->cache = NULL;
+ }
}
-EXPORT_SYMBOL(dma_async_memcpy_buf_to_buf);
-/**
- * dma_async_memcpy_buf_to_pg - offloaded copy from address to page
- * @chan: DMA channel to offload copy to
- * @page: destination page
- * @offset: offset in page to copy to
- * @kdata: source address (virtual)
- * @len: length
- *
- * Both @page/@offset and @kdata must be mappable to a bus address according
- * to the DMA mapping API rules for streaming mappings.
- * Both @page/@offset and @kdata must stay memory resident (kernel memory or
- * locked user space pages)
- */
-dma_cookie_t
-dma_async_memcpy_buf_to_pg(struct dma_chan *chan, struct page *page,
- unsigned int offset, void *kdata, size_t len)
+static int __init dmaengine_init_unmap_pool(void)
{
- struct dma_device *dev = chan->device;
- struct dma_async_tx_descriptor *tx;
- dma_addr_t dma_dest, dma_src;
- dma_cookie_t cookie;
- unsigned long flags;
+ int i;
- dma_src = dma_map_single(dev->dev, kdata, len, DMA_TO_DEVICE);
- dma_dest = dma_map_page(dev->dev, page, offset, len, DMA_FROM_DEVICE);
- flags = DMA_CTRL_ACK | DMA_COMPL_SRC_UNMAP_SINGLE;
- tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, flags);
+ for (i = 0; i < ARRAY_SIZE(unmap_pool); i++) {
+ struct dmaengine_unmap_pool *p = &unmap_pool[i];
+ size_t size;
- if (!tx) {
- dma_unmap_single(dev->dev, dma_src, len, DMA_TO_DEVICE);
- dma_unmap_page(dev->dev, dma_dest, len, DMA_FROM_DEVICE);
- return -ENOMEM;
+ size = sizeof(struct dmaengine_unmap_data) +
+ sizeof(dma_addr_t) * p->size;
+
+ p->cache = kmem_cache_create(p->name, size, 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+ if (!p->cache)
+ break;
+ p->pool = mempool_create_slab_pool(1, p->cache);
+ if (!p->pool)
+ break;
}
- tx->callback = NULL;
- cookie = tx->tx_submit(tx);
+ if (i == ARRAY_SIZE(unmap_pool))
+ return 0;
- preempt_disable();
- __this_cpu_add(chan->local->bytes_transferred, len);
- __this_cpu_inc(chan->local->memcpy_count);
- preempt_enable();
+ dmaengine_destroy_unmap_pool();
+ return -ENOMEM;
+}
- return cookie;
+struct dmaengine_unmap_data *
+dmaengine_get_unmap_data(struct device *dev, int nr, gfp_t flags)
+{
+ struct dmaengine_unmap_data *unmap;
+
+ unmap = mempool_alloc(__get_unmap_pool(nr)->pool, flags);
+ if (!unmap)
+ return NULL;
+
+ memset(unmap, 0, sizeof(*unmap));
+ kref_init(&unmap->kref);
+ unmap->dev = dev;
+
+ return unmap;
}
-EXPORT_SYMBOL(dma_async_memcpy_buf_to_pg);
+EXPORT_SYMBOL(dmaengine_get_unmap_data);
/**
* dma_async_memcpy_pg_to_pg - offloaded copy from page to page
@@ -1015,24 +1050,33 @@ dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg,
{
struct dma_device *dev = chan->device;
struct dma_async_tx_descriptor *tx;
- dma_addr_t dma_dest, dma_src;
+ struct dmaengine_unmap_data *unmap;
dma_cookie_t cookie;
unsigned long flags;
- dma_src = dma_map_page(dev->dev, src_pg, src_off, len, DMA_TO_DEVICE);
- dma_dest = dma_map_page(dev->dev, dest_pg, dest_off, len,
- DMA_FROM_DEVICE);
+ unmap = dmaengine_get_unmap_data(dev->dev, 2, GFP_NOIO);
+ if (!unmap)
+ return -ENOMEM;
+
+ unmap->to_cnt = 1;
+ unmap->from_cnt = 1;
+ unmap->addr[0] = dma_map_page(dev->dev, src_pg, src_off, len,
+ DMA_TO_DEVICE);
+ unmap->addr[1] = dma_map_page(dev->dev, dest_pg, dest_off, len,
+ DMA_FROM_DEVICE);
+ unmap->len = len;
flags = DMA_CTRL_ACK;
- tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, flags);
+ tx = dev->device_prep_dma_memcpy(chan, unmap->addr[1], unmap->addr[0],
+ len, flags);
if (!tx) {
- dma_unmap_page(dev->dev, dma_src, len, DMA_TO_DEVICE);
- dma_unmap_page(dev->dev, dma_dest, len, DMA_FROM_DEVICE);
+ dmaengine_unmap_put(unmap);
return -ENOMEM;
}
- tx->callback = NULL;
+ dma_set_unmap(tx, unmap);
cookie = tx->tx_submit(tx);
+ dmaengine_unmap_put(unmap);
preempt_disable();
__this_cpu_add(chan->local->bytes_transferred, len);
@@ -1043,6 +1087,52 @@ dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg,
}
EXPORT_SYMBOL(dma_async_memcpy_pg_to_pg);
+/**
+ * dma_async_memcpy_buf_to_buf - offloaded copy between virtual addresses
+ * @chan: DMA channel to offload copy to
+ * @dest: destination address (virtual)
+ * @src: source address (virtual)
+ * @len: length
+ *
+ * Both @dest and @src must be mappable to a bus address according to the
+ * DMA mapping API rules for streaming mappings.
+ * Both @dest and @src must stay memory resident (kernel memory or locked
+ * user space pages).
+ */
+dma_cookie_t
+dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest,
+ void *src, size_t len)
+{
+ return dma_async_memcpy_pg_to_pg(chan, virt_to_page(dest),
+ (unsigned long) dest & ~PAGE_MASK,
+ virt_to_page(src),
+ (unsigned long) src & ~PAGE_MASK, len);
+}
+EXPORT_SYMBOL(dma_async_memcpy_buf_to_buf);
+
+/**
+ * dma_async_memcpy_buf_to_pg - offloaded copy from address to page
+ * @chan: DMA channel to offload copy to
+ * @page: destination page
+ * @offset: offset in page to copy to
+ * @kdata: source address (virtual)
+ * @len: length
+ *
+ * Both @page/@offset and @kdata must be mappable to a bus address according
+ * to the DMA mapping API rules for streaming mappings.
+ * Both @page/@offset and @kdata must stay memory resident (kernel memory or
+ * locked user space pages)
+ */
+dma_cookie_t
+dma_async_memcpy_buf_to_pg(struct dma_chan *chan, struct page *page,
+ unsigned int offset, void *kdata, size_t len)
+{
+ return dma_async_memcpy_pg_to_pg(chan, page, offset,
+ virt_to_page(kdata),
+ (unsigned long) kdata & ~PAGE_MASK, len);
+}
+EXPORT_SYMBOL(dma_async_memcpy_buf_to_pg);
+
void dma_async_tx_descriptor_init(struct dma_async_tx_descriptor *tx,
struct dma_chan *chan)
{
@@ -1062,7 +1152,7 @@ dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
unsigned long dma_sync_wait_timeout = jiffies + msecs_to_jiffies(5000);
if (!tx)
- return DMA_SUCCESS;
+ return DMA_COMPLETE;
while (tx->cookie == -EBUSY) {
if (time_after_eq(jiffies, dma_sync_wait_timeout)) {
@@ -1116,6 +1206,10 @@ EXPORT_SYMBOL_GPL(dma_run_dependencies);
static int __init dma_bus_init(void)
{
+ int err = dmaengine_init_unmap_pool();
+
+ if (err)
+ return err;
return class_register(&dma_devclass);
}
arch_initcall(dma_bus_init);
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index 92f796c..20f9a3a 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -8,6 +8,8 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
@@ -19,10 +21,6 @@
#include <linux/random.h>
#include <linux/slab.h>
#include <linux/wait.h>
-#include <linux/ctype.h>
-#include <linux/debugfs.h>
-#include <linux/uaccess.h>
-#include <linux/seq_file.h>
static unsigned int test_buf_size = 16384;
module_param(test_buf_size, uint, S_IRUGO | S_IWUSR);
@@ -68,92 +66,13 @@ module_param(timeout, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), "
"Pass -1 for infinite timeout");
-/* Maximum amount of mismatched bytes in buffer to print */
-#define MAX_ERROR_COUNT 32
-
-/*
- * Initialization patterns. All bytes in the source buffer has bit 7
- * set, all bytes in the destination buffer has bit 7 cleared.
- *
- * Bit 6 is set for all bytes which are to be copied by the DMA
- * engine. Bit 5 is set for all bytes which are to be overwritten by
- * the DMA engine.
- *
- * The remaining bits are the inverse of a counter which increments by
- * one for each byte address.
- */
-#define PATTERN_SRC 0x80
-#define PATTERN_DST 0x00
-#define PATTERN_COPY 0x40
-#define PATTERN_OVERWRITE 0x20
-#define PATTERN_COUNT_MASK 0x1f
-
-enum dmatest_error_type {
- DMATEST_ET_OK,
- DMATEST_ET_MAP_SRC,
- DMATEST_ET_MAP_DST,
- DMATEST_ET_PREP,
- DMATEST_ET_SUBMIT,
- DMATEST_ET_TIMEOUT,
- DMATEST_ET_DMA_ERROR,
- DMATEST_ET_DMA_IN_PROGRESS,
- DMATEST_ET_VERIFY,
- DMATEST_ET_VERIFY_BUF,
-};
-
-struct dmatest_verify_buffer {
- unsigned int index;
- u8 expected;
- u8 actual;
-};
-
-struct dmatest_verify_result {
- unsigned int error_count;
- struct dmatest_verify_buffer data[MAX_ERROR_COUNT];
- u8 pattern;
- bool is_srcbuf;
-};
-
-struct dmatest_thread_result {
- struct list_head node;
- unsigned int n;
- unsigned int src_off;
- unsigned int dst_off;
- unsigned int len;
- enum dmatest_error_type type;
- union {
- unsigned long data;
- dma_cookie_t cookie;
- enum dma_status status;
- int error;
- struct dmatest_verify_result *vr;
- };
-};
-
-struct dmatest_result {
- struct list_head node;
- char *name;
- struct list_head results;
-};
-
-struct dmatest_info;
-
-struct dmatest_thread {
- struct list_head node;
- struct dmatest_info *info;
- struct task_struct *task;
- struct dma_chan *chan;
- u8 **srcs;
- u8 **dsts;
- enum dma_transaction_type type;
- bool done;
-};
+static bool noverify;
+module_param(noverify, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(noverify, "Disable random data setup and verification");
-struct dmatest_chan {
- struct list_head node;
- struct dma_chan *chan;
- struct list_head threads;
-};
+static bool verbose;
+module_param(verbose, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(verbose, "Enable \"success\" result messages (default: off)");
/**
* struct dmatest_params - test parameters.
@@ -177,6 +96,7 @@ struct dmatest_params {
unsigned int xor_sources;
unsigned int pq_sources;
int timeout;
+ bool noverify;
};
/**
@@ -184,7 +104,7 @@ struct dmatest_params {
* @params: test parameters
* @lock: access protection to the fields of this structure
*/
-struct dmatest_info {
+static struct dmatest_info {
/* Test parameters */
struct dmatest_params params;
@@ -192,16 +112,95 @@ struct dmatest_info {
struct list_head channels;
unsigned int nr_channels;
struct mutex lock;
+ bool did_init;
+} test_info = {
+ .channels = LIST_HEAD_INIT(test_info.channels),
+ .lock = __MUTEX_INITIALIZER(test_info.lock),
+};
+
+static int dmatest_run_set(const char *val, const struct kernel_param *kp);
+static int dmatest_run_get(char *val, const struct kernel_param *kp);
+static struct kernel_param_ops run_ops = {
+ .set = dmatest_run_set,
+ .get = dmatest_run_get,
+};
+static bool dmatest_run;
+module_param_cb(run, &run_ops, &dmatest_run, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(run, "Run the test (default: false)");
+
+/* Maximum amount of mismatched bytes in buffer to print */
+#define MAX_ERROR_COUNT 32
+
+/*
+ * Initialization patterns. All bytes in the source buffer has bit 7
+ * set, all bytes in the destination buffer has bit 7 cleared.
+ *
+ * Bit 6 is set for all bytes which are to be copied by the DMA
+ * engine. Bit 5 is set for all bytes which are to be overwritten by
+ * the DMA engine.
+ *
+ * The remaining bits are the inverse of a counter which increments by
+ * one for each byte address.
+ */
+#define PATTERN_SRC 0x80
+#define PATTERN_DST 0x00
+#define PATTERN_COPY 0x40
+#define PATTERN_OVERWRITE 0x20
+#define PATTERN_COUNT_MASK 0x1f
- /* debugfs related stuff */
- struct dentry *root;
+struct dmatest_thread {
+ struct list_head node;
+ struct dmatest_info *info;
+ struct task_struct *task;
+ struct dma_chan *chan;
+ u8 **srcs;
+ u8 **dsts;
+ enum dma_transaction_type type;
+ bool done;
+};
- /* Test results */
- struct list_head results;
- struct mutex results_lock;
+struct dmatest_chan {
+ struct list_head node;
+ struct dma_chan *chan;
+ struct list_head threads;
};
-static struct dmatest_info test_info;
+static DECLARE_WAIT_QUEUE_HEAD(thread_wait);
+static bool wait;
+
+static bool is_threaded_test_run(struct dmatest_info *info)
+{
+ struct dmatest_chan *dtc;
+
+ list_for_each_entry(dtc, &info->channels, node) {
+ struct dmatest_thread *thread;
+
+ list_for_each_entry(thread, &dtc->threads, node) {
+ if (!thread->done)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static int dmatest_wait_get(char *val, const struct kernel_param *kp)
+{
+ struct dmatest_info *info = &test_info;
+ struct dmatest_params *params = &info->params;
+
+ if (params->iterations)
+ wait_event(thread_wait, !is_threaded_test_run(info));
+ wait = true;
+ return param_get_bool(val, kp);
+}
+
+static struct kernel_param_ops wait_ops = {
+ .get = dmatest_wait_get,
+ .set = param_set_bool,
+};
+module_param_cb(wait, &wait_ops, &wait, S_IRUGO);
+MODULE_PARM_DESC(wait, "Wait for tests to complete (default: false)");
static bool dmatest_match_channel(struct dmatest_params *params,
struct dma_chan *chan)
@@ -223,7 +222,7 @@ static unsigned long dmatest_random(void)
{
unsigned long buf;
- get_random_bytes(&buf, sizeof(buf));
+ prandom_bytes(&buf, sizeof(buf));
return buf;
}
@@ -262,9 +261,31 @@ static void dmatest_init_dsts(u8 **bufs, unsigned int start, unsigned int len,
}
}
-static unsigned int dmatest_verify(struct dmatest_verify_result *vr, u8 **bufs,
- unsigned int start, unsigned int end, unsigned int counter,
- u8 pattern, bool is_srcbuf)
+static void dmatest_mismatch(u8 actual, u8 pattern, unsigned int index,
+ unsigned int counter, bool is_srcbuf)
+{
+ u8 diff = actual ^ pattern;
+ u8 expected = pattern | (~counter & PATTERN_COUNT_MASK);
+ const char *thread_name = current->comm;
+
+ if (is_srcbuf)
+ pr_warn("%s: srcbuf[0x%x] overwritten! Expected %02x, got %02x\n",
+ thread_name, index, expected, actual);
+ else if ((pattern & PATTERN_COPY)
+ && (diff & (PATTERN_COPY | PATTERN_OVERWRITE)))
+ pr_warn("%s: dstbuf[0x%x] not copied! Expected %02x, got %02x\n",
+ thread_name, index, expected, actual);
+ else if (diff & PATTERN_SRC)
+ pr_warn("%s: dstbuf[0x%x] was copied! Expected %02x, got %02x\n",
+ thread_name, index, expected, actual);
+ else
+ pr_warn("%s: dstbuf[0x%x] mismatch! Expected %02x, got %02x\n",
+ thread_name, index, expected, actual);
+}
+
+static unsigned int dmatest_verify(u8 **bufs, unsigned int start,
+ unsigned int end, unsigned int counter, u8 pattern,
+ bool is_srcbuf)
{
unsigned int i;
unsigned int error_count = 0;
@@ -272,7 +293,6 @@ static unsigned int dmatest_verify(struct dmatest_verify_result *vr, u8 **bufs,
u8 expected;
u8 *buf;
unsigned int counter_orig = counter;
- struct dmatest_verify_buffer *vb;
for (; (buf = *bufs); bufs++) {
counter = counter_orig;
@@ -280,12 +300,9 @@ static unsigned int dmatest_verify(struct dmatest_verify_result *vr, u8 **bufs,
actual = buf[i];
expected = pattern | (~counter & PATTERN_COUNT_MASK);
if (actual != expected) {
- if (error_count < MAX_ERROR_COUNT && vr) {
- vb = &vr->data[error_count];
- vb->index = i;
- vb->expected = expected;
- vb->actual = actual;
- }
+ if (error_count < MAX_ERROR_COUNT)
+ dmatest_mismatch(actual, pattern, i,
+ counter, is_srcbuf);
error_count++;
}
counter++;
@@ -293,7 +310,7 @@ static unsigned int dmatest_verify(struct dmatest_verify_result *vr, u8 **bufs,
}
if (error_count > MAX_ERROR_COUNT)
- pr_warning("%s: %u errors suppressed\n",
+ pr_warn("%s: %u errors suppressed\n",
current->comm, error_count - MAX_ERROR_COUNT);
return error_count;
@@ -313,20 +330,6 @@ static void dmatest_callback(void *arg)
wake_up_all(done->wait);
}
-static inline void unmap_src(struct device *dev, dma_addr_t *addr, size_t len,
- unsigned int count)
-{
- while (count--)
- dma_unmap_single(dev, addr[count], len, DMA_TO_DEVICE);
-}
-
-static inline void unmap_dst(struct device *dev, dma_addr_t *addr, size_t len,
- unsigned int count)
-{
- while (count--)
- dma_unmap_single(dev, addr[count], len, DMA_BIDIRECTIONAL);
-}
-
static unsigned int min_odd(unsigned int x, unsigned int y)
{
unsigned int val = min(x, y);
@@ -334,172 +337,49 @@ static unsigned int min_odd(unsigned int x, unsigned int y)
return val % 2 ? val : val - 1;
}
-static char *verify_result_get_one(struct dmatest_verify_result *vr,
- unsigned int i)
+static void result(const char *err, unsigned int n, unsigned int src_off,
+ unsigned int dst_off, unsigned int len, unsigned long data)
{
- struct dmatest_verify_buffer *vb = &vr->data[i];
- u8 diff = vb->actual ^ vr->pattern;
- static char buf[512];
- char *msg;
-
- if (vr->is_srcbuf)
- msg = "srcbuf overwritten!";
- else if ((vr->pattern & PATTERN_COPY)
- && (diff & (PATTERN_COPY | PATTERN_OVERWRITE)))
- msg = "dstbuf not copied!";
- else if (diff & PATTERN_SRC)
- msg = "dstbuf was copied!";
- else
- msg = "dstbuf mismatch!";
-
- snprintf(buf, sizeof(buf) - 1, "%s [0x%x] Expected %02x, got %02x", msg,
- vb->index, vb->expected, vb->actual);
-
- return buf;
+ pr_info("%s: result #%u: '%s' with src_off=0x%x dst_off=0x%x len=0x%x (%lu)",
+ current->comm, n, err, src_off, dst_off, len, data);
}
-static char *thread_result_get(const char *name,
- struct dmatest_thread_result *tr)
+static void dbg_result(const char *err, unsigned int n, unsigned int src_off,
+ unsigned int dst_off, unsigned int len,
+ unsigned long data)
{
- static const char * const messages[] = {
- [DMATEST_ET_OK] = "No errors",
- [DMATEST_ET_MAP_SRC] = "src mapping error",
- [DMATEST_ET_MAP_DST] = "dst mapping error",
- [DMATEST_ET_PREP] = "prep error",
- [DMATEST_ET_SUBMIT] = "submit error",
- [DMATEST_ET_TIMEOUT] = "test timed out",
- [DMATEST_ET_DMA_ERROR] =
- "got completion callback (DMA_ERROR)",
- [DMATEST_ET_DMA_IN_PROGRESS] =
- "got completion callback (DMA_IN_PROGRESS)",
- [DMATEST_ET_VERIFY] = "errors",
- [DMATEST_ET_VERIFY_BUF] = "verify errors",
- };
- static char buf[512];
-
- snprintf(buf, sizeof(buf) - 1,
- "%s: #%u: %s with src_off=0x%x ""dst_off=0x%x len=0x%x (%lu)",
- name, tr->n, messages[tr->type], tr->src_off, tr->dst_off,
- tr->len, tr->data);
-
- return buf;
+ pr_debug("%s: result #%u: '%s' with src_off=0x%x dst_off=0x%x len=0x%x (%lu)",
+ current->comm, n, err, src_off, dst_off, len, data);
}
-static int thread_result_add(struct dmatest_info *info,
- struct dmatest_result *r, enum dmatest_error_type type,
- unsigned int n, unsigned int src_off, unsigned int dst_off,
- unsigned int len, unsigned long data)
-{
- struct dmatest_thread_result *tr;
-
- tr = kzalloc(sizeof(*tr), GFP_KERNEL);
- if (!tr)
- return -ENOMEM;
-
- tr->type = type;
- tr->n = n;
- tr->src_off = src_off;
- tr->dst_off = dst_off;
- tr->len = len;
- tr->data = data;
+#define verbose_result(err, n, src_off, dst_off, len, data) ({ \
+ if (verbose) \
+ result(err, n, src_off, dst_off, len, data); \
+ else \
+ dbg_result(err, n, src_off, dst_off, len, data); \
+})
- mutex_lock(&info->results_lock);
- list_add_tail(&tr->node, &r->results);
- mutex_unlock(&info->results_lock);
-
- if (tr->type == DMATEST_ET_OK)
- pr_debug("%s\n", thread_result_get(r->name, tr));
- else
- pr_warn("%s\n", thread_result_get(r->name, tr));
-
- return 0;
-}
-
-static unsigned int verify_result_add(struct dmatest_info *info,
- struct dmatest_result *r, unsigned int n,
- unsigned int src_off, unsigned int dst_off, unsigned int len,
- u8 **bufs, int whence, unsigned int counter, u8 pattern,
- bool is_srcbuf)
+static unsigned long long dmatest_persec(s64 runtime, unsigned int val)
{
- struct dmatest_verify_result *vr;
- unsigned int error_count;
- unsigned int buf_off = is_srcbuf ? src_off : dst_off;
- unsigned int start, end;
-
- if (whence < 0) {
- start = 0;
- end = buf_off;
- } else if (whence > 0) {
- start = buf_off + len;
- end = info->params.buf_size;
- } else {
- start = buf_off;
- end = buf_off + len;
- }
+ unsigned long long per_sec = 1000000;
- vr = kmalloc(sizeof(*vr), GFP_KERNEL);
- if (!vr) {
- pr_warn("dmatest: No memory to store verify result\n");
- return dmatest_verify(NULL, bufs, start, end, counter, pattern,
- is_srcbuf);
- }
-
- vr->pattern = pattern;
- vr->is_srcbuf = is_srcbuf;
-
- error_count = dmatest_verify(vr, bufs, start, end, counter, pattern,
- is_srcbuf);
- if (error_count) {
- vr->error_count = error_count;
- thread_result_add(info, r, DMATEST_ET_VERIFY_BUF, n, src_off,
- dst_off, len, (unsigned long)vr);
- return error_count;
- }
-
- kfree(vr);
- return 0;
-}
-
-static void result_free(struct dmatest_info *info, const char *name)
-{
- struct dmatest_result *r, *_r;
-
- mutex_lock(&info->results_lock);
- list_for_each_entry_safe(r, _r, &info->results, node) {
- struct dmatest_thread_result *tr, *_tr;
-
- if (name && strcmp(r->name, name))
- continue;
-
- list_for_each_entry_safe(tr, _tr, &r->results, node) {
- if (tr->type == DMATEST_ET_VERIFY_BUF)
- kfree(tr->vr);
- list_del(&tr->node);
- kfree(tr);
- }
+ if (runtime <= 0)
+ return 0;
- kfree(r->name);
- list_del(&r->node);
- kfree(r);
+ /* drop precision until runtime is 32-bits */
+ while (runtime > UINT_MAX) {
+ runtime >>= 1;
+ per_sec <<= 1;
}
- mutex_unlock(&info->results_lock);
+ per_sec *= val;
+ do_div(per_sec, runtime);
+ return per_sec;
}
-static struct dmatest_result *result_init(struct dmatest_info *info,
- const char *name)
+static unsigned long long dmatest_KBs(s64 runtime, unsigned long long len)
{
- struct dmatest_result *r;
-
- r = kzalloc(sizeof(*r), GFP_KERNEL);
- if (r) {
- r->name = kstrdup(name, GFP_KERNEL);
- INIT_LIST_HEAD(&r->results);
- mutex_lock(&info->results_lock);
- list_add_tail(&r->node, &info->results);
- mutex_unlock(&info->results_lock);
- }
- return r;
+ return dmatest_persec(runtime, len >> 10);
}
/*
@@ -525,7 +405,6 @@ static int dmatest_func(void *data)
struct dmatest_params *params;
struct dma_chan *chan;
struct dma_device *dev;
- const char *thread_name;
unsigned int src_off, dst_off, len;
unsigned int error_count;
unsigned int failed_tests = 0;
@@ -538,9 +417,10 @@ static int dmatest_func(void *data)
int src_cnt;
int dst_cnt;
int i;
- struct dmatest_result *result;
+ ktime_t ktime;
+ s64 runtime = 0;
+ unsigned long long total_len = 0;
- thread_name = current->comm;
set_freezable();
ret = -ENOMEM;
@@ -570,10 +450,6 @@ static int dmatest_func(void *data)
} else
goto err_thread_type;
- result = result_init(info, thread_name);
- if (!result)
- goto err_srcs;
-
thread->srcs = kcalloc(src_cnt+1, sizeof(u8 *), GFP_KERNEL);
if (!thread->srcs)
goto err_srcs;
@@ -597,17 +473,17 @@ static int dmatest_func(void *data)
set_user_nice(current, 10);
/*
- * src buffers are freed by the DMAEngine code with dma_unmap_single()
- * dst buffers are freed by ourselves below
+ * src and dst buffers are freed by ourselves below
*/
- flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT
- | DMA_COMPL_SKIP_DEST_UNMAP | DMA_COMPL_SRC_UNMAP_SINGLE;
+ flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
+ ktime = ktime_get();
while (!kthread_should_stop()
&& !(params->iterations && total_tests >= params->iterations)) {
struct dma_async_tx_descriptor *tx = NULL;
- dma_addr_t dma_srcs[src_cnt];
- dma_addr_t dma_dsts[dst_cnt];
+ struct dmaengine_unmap_data *um;
+ dma_addr_t srcs[src_cnt];
+ dma_addr_t *dsts;
u8 align = 0;
total_tests++;
@@ -626,81 +502,103 @@ static int dmatest_func(void *data)
break;
}
- len = dmatest_random() % params->buf_size + 1;
+ if (params->noverify) {
+ len = params->buf_size;
+ src_off = 0;
+ dst_off = 0;
+ } else {
+ len = dmatest_random() % params->buf_size + 1;
+ len = (len >> align) << align;
+ if (!len)
+ len = 1 << align;
+ src_off = dmatest_random() % (params->buf_size - len + 1);
+ dst_off = dmatest_random() % (params->buf_size - len + 1);
+
+ src_off = (src_off >> align) << align;
+ dst_off = (dst_off >> align) << align;
+
+ dmatest_init_srcs(thread->srcs, src_off, len,
+ params->buf_size);
+ dmatest_init_dsts(thread->dsts, dst_off, len,
+ params->buf_size);
+ }
+
len = (len >> align) << align;
if (!len)
len = 1 << align;
- src_off = dmatest_random() % (params->buf_size - len + 1);
- dst_off = dmatest_random() % (params->buf_size - len + 1);
+ total_len += len;
- src_off = (src_off >> align) << align;
- dst_off = (dst_off >> align) << align;
-
- dmatest_init_srcs(thread->srcs, src_off, len, params->buf_size);
- dmatest_init_dsts(thread->dsts, dst_off, len, params->buf_size);
+ um = dmaengine_get_unmap_data(dev->dev, src_cnt+dst_cnt,
+ GFP_KERNEL);
+ if (!um) {
+ failed_tests++;
+ result("unmap data NULL", total_tests,
+ src_off, dst_off, len, ret);
+ continue;
+ }
+ um->len = params->buf_size;
for (i = 0; i < src_cnt; i++) {
- u8 *buf = thread->srcs[i] + src_off;
-
- dma_srcs[i] = dma_map_single(dev->dev, buf, len,
- DMA_TO_DEVICE);
- ret = dma_mapping_error(dev->dev, dma_srcs[i]);
+ unsigned long buf = (unsigned long) thread->srcs[i];
+ struct page *pg = virt_to_page(buf);
+ unsigned pg_off = buf & ~PAGE_MASK;
+
+ um->addr[i] = dma_map_page(dev->dev, pg, pg_off,
+ um->len, DMA_TO_DEVICE);
+ srcs[i] = um->addr[i] + src_off;
+ ret = dma_mapping_error(dev->dev, um->addr[i]);
if (ret) {
- unmap_src(dev->dev, dma_srcs, len, i);
- thread_result_add(info, result,
- DMATEST_ET_MAP_SRC,
- total_tests, src_off, dst_off,
- len, ret);
+ dmaengine_unmap_put(um);
+ result("src mapping error", total_tests,
+ src_off, dst_off, len, ret);
failed_tests++;
continue;
}
+ um->to_cnt++;
}
/* map with DMA_BIDIRECTIONAL to force writeback/invalidate */
+ dsts = &um->addr[src_cnt];
for (i = 0; i < dst_cnt; i++) {
- dma_dsts[i] = dma_map_single(dev->dev, thread->dsts[i],
- params->buf_size,
- DMA_BIDIRECTIONAL);
- ret = dma_mapping_error(dev->dev, dma_dsts[i]);
+ unsigned long buf = (unsigned long) thread->dsts[i];
+ struct page *pg = virt_to_page(buf);
+ unsigned pg_off = buf & ~PAGE_MASK;
+
+ dsts[i] = dma_map_page(dev->dev, pg, pg_off, um->len,
+ DMA_BIDIRECTIONAL);
+ ret = dma_mapping_error(dev->dev, dsts[i]);
if (ret) {
- unmap_src(dev->dev, dma_srcs, len, src_cnt);
- unmap_dst(dev->dev, dma_dsts, params->buf_size,
- i);
- thread_result_add(info, result,
- DMATEST_ET_MAP_DST,
- total_tests, src_off, dst_off,
- len, ret);
+ dmaengine_unmap_put(um);
+ result("dst mapping error", total_tests,
+ src_off, dst_off, len, ret);
failed_tests++;
continue;
}
+ um->bidi_cnt++;
}
if (thread->type == DMA_MEMCPY)
tx = dev->device_prep_dma_memcpy(chan,
- dma_dsts[0] + dst_off,
- dma_srcs[0], len,
- flags);
+ dsts[0] + dst_off,
+ srcs[0], len, flags);
else if (thread->type == DMA_XOR)
tx = dev->device_prep_dma_xor(chan,
- dma_dsts[0] + dst_off,
- dma_srcs, src_cnt,
+ dsts[0] + dst_off,
+ srcs, src_cnt,
len, flags);
else if (thread->type == DMA_PQ) {
dma_addr_t dma_pq[dst_cnt];
for (i = 0; i < dst_cnt; i++)
- dma_pq[i] = dma_dsts[i] + dst_off;
- tx = dev->device_prep_dma_pq(chan, dma_pq, dma_srcs,
+ dma_pq[i] = dsts[i] + dst_off;
+ tx = dev->device_prep_dma_pq(chan, dma_pq, srcs,
src_cnt, pq_coefs,
len, flags);
}
if (!tx) {
- unmap_src(dev->dev, dma_srcs, len, src_cnt);
- unmap_dst(dev->dev, dma_dsts, params->buf_size,
- dst_cnt);
- thread_result_add(info, result, DMATEST_ET_PREP,
- total_tests, src_off, dst_off,
- len, 0);
+ dmaengine_unmap_put(um);
+ result("prep error", total_tests, src_off,
+ dst_off, len, ret);
msleep(100);
failed_tests++;
continue;
@@ -712,9 +610,9 @@ static int dmatest_func(void *data)
cookie = tx->tx_submit(tx);
if (dma_submit_error(cookie)) {
- thread_result_add(info, result, DMATEST_ET_SUBMIT,
- total_tests, src_off, dst_off,
- len, cookie);
+ dmaengine_unmap_put(um);
+ result("submit error", total_tests, src_off,
+ dst_off, len, ret);
msleep(100);
failed_tests++;
continue;
@@ -735,59 +633,59 @@ static int dmatest_func(void *data)
* free it this time?" dancing. For now, just
* leave it dangling.
*/
- thread_result_add(info, result, DMATEST_ET_TIMEOUT,
- total_tests, src_off, dst_off,
- len, 0);
+ dmaengine_unmap_put(um);
+ result("test timed out", total_tests, src_off, dst_off,
+ len, 0);
failed_tests++;
continue;
- } else if (status != DMA_SUCCESS) {
- enum dmatest_error_type type = (status == DMA_ERROR) ?
- DMATEST_ET_DMA_ERROR : DMATEST_ET_DMA_IN_PROGRESS;
- thread_result_add(info, result, type,
- total_tests, src_off, dst_off,
- len, status);
+ } else if (status != DMA_COMPLETE) {
+ dmaengine_unmap_put(um);
+ result(status == DMA_ERROR ?
+ "completion error status" :
+ "completion busy status", total_tests, src_off,
+ dst_off, len, ret);
failed_tests++;
continue;
}
- /* Unmap by myself (see DMA_COMPL_SKIP_DEST_UNMAP above) */
- unmap_dst(dev->dev, dma_dsts, params->buf_size, dst_cnt);
+ dmaengine_unmap_put(um);
- error_count = 0;
+ if (params->noverify) {
+ verbose_result("test passed", total_tests, src_off,
+ dst_off, len, 0);
+ continue;
+ }
- pr_debug("%s: verifying source buffer...\n", thread_name);
- error_count += verify_result_add(info, result, total_tests,
- src_off, dst_off, len, thread->srcs, -1,
+ pr_debug("%s: verifying source buffer...\n", current->comm);
+ error_count = dmatest_verify(thread->srcs, 0, src_off,
0, PATTERN_SRC, true);
- error_count += verify_result_add(info, result, total_tests,
- src_off, dst_off, len, thread->srcs, 0,
- src_off, PATTERN_SRC | PATTERN_COPY, true);
- error_count += verify_result_add(info, result, total_tests,
- src_off, dst_off, len, thread->srcs, 1,
- src_off + len, PATTERN_SRC, true);
-
- pr_debug("%s: verifying dest buffer...\n", thread_name);
- error_count += verify_result_add(info, result, total_tests,
- src_off, dst_off, len, thread->dsts, -1,
+ error_count += dmatest_verify(thread->srcs, src_off,
+ src_off + len, src_off,
+ PATTERN_SRC | PATTERN_COPY, true);
+ error_count += dmatest_verify(thread->srcs, src_off + len,
+ params->buf_size, src_off + len,
+ PATTERN_SRC, true);
+
+ pr_debug("%s: verifying dest buffer...\n", current->comm);
+ error_count += dmatest_verify(thread->dsts, 0, dst_off,
0, PATTERN_DST, false);
- error_count += verify_result_add(info, result, total_tests,
- src_off, dst_off, len, thread->dsts, 0,
- src_off, PATTERN_SRC | PATTERN_COPY, false);
- error_count += verify_result_add(info, result, total_tests,
- src_off, dst_off, len, thread->dsts, 1,
- dst_off + len, PATTERN_DST, false);
+ error_count += dmatest_verify(thread->dsts, dst_off,
+ dst_off + len, src_off,
+ PATTERN_SRC | PATTERN_COPY, false);
+ error_count += dmatest_verify(thread->dsts, dst_off + len,
+ params->buf_size, dst_off + len,
+ PATTERN_DST, false);
if (error_count) {
- thread_result_add(info, result, DMATEST_ET_VERIFY,
- total_tests, src_off, dst_off,
- len, error_count);
+ result("data error", total_tests, src_off, dst_off,
+ len, error_count);
failed_tests++;
} else {
- thread_result_add(info, result, DMATEST_ET_OK,
- total_tests, src_off, dst_off,
- len, 0);
+ verbose_result("test passed", total_tests, src_off,
+ dst_off, len, 0);
}
}
+ runtime = ktime_us_delta(ktime_get(), ktime);
ret = 0;
for (i = 0; thread->dsts[i]; i++)
@@ -802,20 +700,17 @@ err_srcbuf:
err_srcs:
kfree(pq_coefs);
err_thread_type:
- pr_notice("%s: terminating after %u tests, %u failures (status %d)\n",
- thread_name, total_tests, failed_tests, ret);
+ pr_info("%s: summary %u tests, %u failures %llu iops %llu KB/s (%d)\n",
+ current->comm, total_tests, failed_tests,
+ dmatest_persec(runtime, total_tests),
+ dmatest_KBs(runtime, total_len), ret);
/* terminate all transfers on specified channels */
if (ret)
dmaengine_terminate_all(chan);
thread->done = true;
-
- if (params->iterations > 0)
- while (!kthread_should_stop()) {
- DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit);
- interruptible_sleep_on(&wait_dmatest_exit);
- }
+ wake_up(&thread_wait);
return ret;
}
@@ -828,9 +723,10 @@ static void dmatest_cleanup_channel(struct dmatest_chan *dtc)
list_for_each_entry_safe(thread, _thread, &dtc->threads, node) {
ret = kthread_stop(thread->task);
- pr_debug("dmatest: thread %s exited with status %d\n",
- thread->task->comm, ret);
+ pr_debug("thread %s exited with status %d\n",
+ thread->task->comm, ret);
list_del(&thread->node);
+ put_task_struct(thread->task);
kfree(thread);
}
@@ -861,27 +757,27 @@ static int dmatest_add_threads(struct dmatest_info *info,
for (i = 0; i < params->threads_per_chan; i++) {
thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL);
if (!thread) {
- pr_warning("dmatest: No memory for %s-%s%u\n",
- dma_chan_name(chan), op, i);
-
+ pr_warn("No memory for %s-%s%u\n",
+ dma_chan_name(chan), op, i);
break;
}
thread->info = info;
thread->chan = dtc->chan;
thread->type = type;
smp_wmb();
- thread->task = kthread_run(dmatest_func, thread, "%s-%s%u",
+ thread->task = kthread_create(dmatest_func, thread, "%s-%s%u",
dma_chan_name(chan), op, i);
if (IS_ERR(thread->task)) {
- pr_warning("dmatest: Failed to run thread %s-%s%u\n",
- dma_chan_name(chan), op, i);
+ pr_warn("Failed to create thread %s-%s%u\n",
+ dma_chan_name(chan), op, i);
kfree(thread);
break;
}
/* srcbuf and dstbuf are allocated by the thread itself */
-
+ get_task_struct(thread->task);
list_add_tail(&thread->node, &dtc->threads);
+ wake_up_process(thread->task);
}
return i;
@@ -897,7 +793,7 @@ static int dmatest_add_channel(struct dmatest_info *info,
dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL);
if (!dtc) {
- pr_warning("dmatest: No memory for %s\n", dma_chan_name(chan));
+ pr_warn("No memory for %s\n", dma_chan_name(chan));
return -ENOMEM;
}
@@ -917,7 +813,7 @@ static int dmatest_add_channel(struct dmatest_info *info,
thread_count += cnt > 0 ? cnt : 0;
}
- pr_info("dmatest: Started %u threads using %s\n",
+ pr_info("Started %u threads using %s\n",
thread_count, dma_chan_name(chan));
list_add_tail(&dtc->node, &info->channels);
@@ -937,20 +833,20 @@ static bool filter(struct dma_chan *chan, void *param)
return true;
}
-static int __run_threaded_test(struct dmatest_info *info)
+static void request_channels(struct dmatest_info *info,
+ enum dma_transaction_type type)
{
dma_cap_mask_t mask;
- struct dma_chan *chan;
- struct dmatest_params *params = &info->params;
- int err = 0;
dma_cap_zero(mask);
- dma_cap_set(DMA_MEMCPY, mask);
+ dma_cap_set(type, mask);
for (;;) {
+ struct dmatest_params *params = &info->params;
+ struct dma_chan *chan;
+
chan = dma_request_channel(mask, filter, params);
if (chan) {
- err = dmatest_add_channel(info, chan);
- if (err) {
+ if (dmatest_add_channel(info, chan)) {
dma_release_channel(chan);
break; /* add_channel failed, punt */
}
@@ -960,22 +856,30 @@ static int __run_threaded_test(struct dmatest_info *info)
info->nr_channels >= params->max_channels)
break; /* we have all we need */
}
- return err;
}
-#ifndef MODULE
-static int run_threaded_test(struct dmatest_info *info)
+static void run_threaded_test(struct dmatest_info *info)
{
- int ret;
+ struct dmatest_params *params = &info->params;
- mutex_lock(&info->lock);
- ret = __run_threaded_test(info);
- mutex_unlock(&info->lock);
- return ret;
+ /* Copy test parameters */
+ params->buf_size = test_buf_size;
+ strlcpy(params->channel, strim(test_channel), sizeof(params->channel));
+ strlcpy(params->device, strim(test_device), sizeof(params->device));
+ params->threads_per_chan = threads_per_chan;
+ params->max_channels = max_channels;
+ params->iterations = iterations;
+ params->xor_sources = xor_sources;
+ params->pq_sources = pq_sources;
+ params->timeout = timeout;
+ params->noverify = noverify;
+
+ request_channels(info, DMA_MEMCPY);
+ request_channels(info, DMA_XOR);
+ request_channels(info, DMA_PQ);
}
-#endif
-static void __stop_threaded_test(struct dmatest_info *info)
+static void stop_threaded_test(struct dmatest_info *info)
{
struct dmatest_chan *dtc, *_dtc;
struct dma_chan *chan;
@@ -984,203 +888,86 @@ static void __stop_threaded_test(struct dmatest_info *info)
list_del(&dtc->node);
chan = dtc->chan;
dmatest_cleanup_channel(dtc);
- pr_debug("dmatest: dropped channel %s\n", dma_chan_name(chan));
+ pr_debug("dropped channel %s\n", dma_chan_name(chan));
dma_release_channel(chan);
}
info->nr_channels = 0;
}
-static void stop_threaded_test(struct dmatest_info *info)
+static void restart_threaded_test(struct dmatest_info *info, bool run)
{
- mutex_lock(&info->lock);
- __stop_threaded_test(info);
- mutex_unlock(&info->lock);
-}
-
-static int __restart_threaded_test(struct dmatest_info *info, bool run)
-{
- struct dmatest_params *params = &info->params;
+ /* we might be called early to set run=, defer running until all
+ * parameters have been evaluated
+ */
+ if (!info->did_init)
+ return;
/* Stop any running test first */
- __stop_threaded_test(info);
-
- if (run == false)
- return 0;
-
- /* Clear results from previous run */
- result_free(info, NULL);
-
- /* Copy test parameters */
- params->buf_size = test_buf_size;
- strlcpy(params->channel, strim(test_channel), sizeof(params->channel));
- strlcpy(params->device, strim(test_device), sizeof(params->device));
- params->threads_per_chan = threads_per_chan;
- params->max_channels = max_channels;
- params->iterations = iterations;
- params->xor_sources = xor_sources;
- params->pq_sources = pq_sources;
- params->timeout = timeout;
+ stop_threaded_test(info);
/* Run test with new parameters */
- return __run_threaded_test(info);
-}
-
-static bool __is_threaded_test_run(struct dmatest_info *info)
-{
- struct dmatest_chan *dtc;
-
- list_for_each_entry(dtc, &info->channels, node) {
- struct dmatest_thread *thread;
-
- list_for_each_entry(thread, &dtc->threads, node) {
- if (!thread->done)
- return true;
- }
- }
-
- return false;
+ run_threaded_test(info);
}
-static ssize_t dtf_read_run(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
+static int dmatest_run_get(char *val, const struct kernel_param *kp)
{
- struct dmatest_info *info = file->private_data;
- char buf[3];
+ struct dmatest_info *info = &test_info;
mutex_lock(&info->lock);
-
- if (__is_threaded_test_run(info)) {
- buf[0] = 'Y';
+ if (is_threaded_test_run(info)) {
+ dmatest_run = true;
} else {
- __stop_threaded_test(info);
- buf[0] = 'N';
+ stop_threaded_test(info);
+ dmatest_run = false;
}
-
mutex_unlock(&info->lock);
- buf[1] = '\n';
- buf[2] = 0x00;
- return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
-}
-
-static ssize_t dtf_write_run(struct file *file, const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct dmatest_info *info = file->private_data;
- char buf[16];
- bool bv;
- int ret = 0;
- if (copy_from_user(buf, user_buf, min(count, (sizeof(buf) - 1))))
- return -EFAULT;
-
- if (strtobool(buf, &bv) == 0) {
- mutex_lock(&info->lock);
-
- if (__is_threaded_test_run(info))
- ret = -EBUSY;
- else
- ret = __restart_threaded_test(info, bv);
-
- mutex_unlock(&info->lock);
- }
-
- return ret ? ret : count;
+ return param_get_bool(val, kp);
}
-static const struct file_operations dtf_run_fops = {
- .read = dtf_read_run,
- .write = dtf_write_run,
- .open = simple_open,
- .llseek = default_llseek,
-};
-
-static int dtf_results_show(struct seq_file *sf, void *data)
+static int dmatest_run_set(const char *val, const struct kernel_param *kp)
{
- struct dmatest_info *info = sf->private;
- struct dmatest_result *result;
- struct dmatest_thread_result *tr;
- unsigned int i;
+ struct dmatest_info *info = &test_info;
+ int ret;
- mutex_lock(&info->results_lock);
- list_for_each_entry(result, &info->results, node) {
- list_for_each_entry(tr, &result->results, node) {
- seq_printf(sf, "%s\n",
- thread_result_get(result->name, tr));
- if (tr->type == DMATEST_ET_VERIFY_BUF) {
- for (i = 0; i < tr->vr->error_count; i++) {
- seq_printf(sf, "\t%s\n",
- verify_result_get_one(tr->vr, i));
- }
- }
- }
+ mutex_lock(&info->lock);
+ ret = param_set_bool(val, kp);
+ if (ret) {
+ mutex_unlock(&info->lock);
+ return ret;
}
- mutex_unlock(&info->results_lock);
- return 0;
-}
-
-static int dtf_results_open(struct inode *inode, struct file *file)
-{
- return single_open(file, dtf_results_show, inode->i_private);
-}
-
-static const struct file_operations dtf_results_fops = {
- .open = dtf_results_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int dmatest_register_dbgfs(struct dmatest_info *info)
-{
- struct dentry *d;
-
- d = debugfs_create_dir("dmatest", NULL);
- if (IS_ERR(d))
- return PTR_ERR(d);
- if (!d)
- goto err_root;
+ if (is_threaded_test_run(info))
+ ret = -EBUSY;
+ else if (dmatest_run)
+ restart_threaded_test(info, dmatest_run);
- info->root = d;
-
- /* Run or stop threaded test */
- debugfs_create_file("run", S_IWUSR | S_IRUGO, info->root, info,
- &dtf_run_fops);
-
- /* Results of test in progress */
- debugfs_create_file("results", S_IRUGO, info->root, info,
- &dtf_results_fops);
-
- return 0;
+ mutex_unlock(&info->lock);
-err_root:
- pr_err("dmatest: Failed to initialize debugfs\n");
- return -ENOMEM;
+ return ret;
}
static int __init dmatest_init(void)
{
struct dmatest_info *info = &test_info;
- int ret;
-
- memset(info, 0, sizeof(*info));
+ struct dmatest_params *params = &info->params;
- mutex_init(&info->lock);
- INIT_LIST_HEAD(&info->channels);
+ if (dmatest_run) {
+ mutex_lock(&info->lock);
+ run_threaded_test(info);
+ mutex_unlock(&info->lock);
+ }
- mutex_init(&info->results_lock);
- INIT_LIST_HEAD(&info->results);
+ if (params->iterations && wait)
+ wait_event(thread_wait, !is_threaded_test_run(info));
- ret = dmatest_register_dbgfs(info);
- if (ret)
- return ret;
+ /* module parameters are stable, inittime tests are started,
+ * let userspace take over 'run' control
+ */
+ info->did_init = true;
-#ifdef MODULE
return 0;
-#else
- return run_threaded_test(info);
-#endif
}
/* when compiled-in wait for drivers to load first */
late_initcall(dmatest_init);
@@ -1189,9 +976,9 @@ static void __exit dmatest_exit(void)
{
struct dmatest_info *info = &test_info;
- debugfs_remove_recursive(info->root);
+ mutex_lock(&info->lock);
stop_threaded_test(info);
- result_free(info, NULL);
+ mutex_unlock(&info->lock);
}
module_exit(dmatest_exit);
diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c
index 89eb89f..7516be4 100644
--- a/drivers/dma/dw/core.c
+++ b/drivers/dma/dw/core.c
@@ -85,10 +85,6 @@ static struct device *chan2dev(struct dma_chan *chan)
{
return &chan->dev->device;
}
-static struct device *chan2parent(struct dma_chan *chan)
-{
- return chan->dev->device.parent;
-}
static struct dw_desc *dwc_first_active(struct dw_dma_chan *dwc)
{
@@ -311,26 +307,7 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc,
list_splice_init(&desc->tx_list, &dwc->free_list);
list_move(&desc->desc_node, &dwc->free_list);
- if (!is_slave_direction(dwc->direction)) {
- struct device *parent = chan2parent(&dwc->chan);
- if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
- if (txd->flags & DMA_COMPL_DEST_UNMAP_SINGLE)
- dma_unmap_single(parent, desc->lli.dar,
- desc->total_len, DMA_FROM_DEVICE);
- else
- dma_unmap_page(parent, desc->lli.dar,
- desc->total_len, DMA_FROM_DEVICE);
- }
- if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
- if (txd->flags & DMA_COMPL_SRC_UNMAP_SINGLE)
- dma_unmap_single(parent, desc->lli.sar,
- desc->total_len, DMA_TO_DEVICE);
- else
- dma_unmap_page(parent, desc->lli.sar,
- desc->total_len, DMA_TO_DEVICE);
- }
- }
-
+ dma_descriptor_unmap(txd);
spin_unlock_irqrestore(&dwc->lock, flags);
if (callback)
@@ -1098,13 +1075,13 @@ dwc_tx_status(struct dma_chan *chan,
enum dma_status ret;
ret = dma_cookie_status(chan, cookie, txstate);
- if (ret == DMA_SUCCESS)
+ if (ret == DMA_COMPLETE)
return ret;
dwc_scan_descriptors(to_dw_dma(chan->device), dwc);
ret = dma_cookie_status(chan, cookie, txstate);
- if (ret != DMA_SUCCESS)
+ if (ret != DMA_COMPLETE)
dma_set_residue(txstate, dwc_get_residue(dwc));
if (dwc->paused && ret == DMA_IN_PROGRESS)
diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c
index e35d975..453822c 100644
--- a/drivers/dma/dw/platform.c
+++ b/drivers/dma/dw/platform.c
@@ -191,11 +191,9 @@ static int dw_probe(struct platform_device *pdev)
if (IS_ERR(chip->regs))
return PTR_ERR(chip->regs);
- /* Apply default dma_mask if needed */
- if (!dev->dma_mask) {
- dev->dma_mask = &dev->coherent_dma_mask;
- dev->coherent_dma_mask = DMA_BIT_MASK(32);
- }
+ err = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (err)
+ return err;
pdata = dev_get_platdata(dev);
if (!pdata)
diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
index 10b577f..2539ea0 100644
--- a/drivers/dma/edma.c
+++ b/drivers/dma/edma.c
@@ -46,14 +46,21 @@
#define EDMA_CHANS 64
#endif /* CONFIG_ARCH_DAVINCI_DA8XX */
-/* Max of 16 segments per channel to conserve PaRAM slots */
-#define MAX_NR_SG 16
+/*
+ * Max of 20 segments per channel to conserve PaRAM slots
+ * Also note that MAX_NR_SG should be atleast the no.of periods
+ * that are required for ASoC, otherwise DMA prep calls will
+ * fail. Today davinci-pcm is the only user of this driver and
+ * requires atleast 17 slots, so we setup the default to 20.
+ */
+#define MAX_NR_SG 20
#define EDMA_MAX_SLOTS MAX_NR_SG
#define EDMA_DESCRIPTORS 16
struct edma_desc {
struct virt_dma_desc vdesc;
struct list_head node;
+ int cyclic;
int absync;
int pset_nr;
int processed;
@@ -167,8 +174,13 @@ static void edma_execute(struct edma_chan *echan)
* then setup a link to the dummy slot, this results in all future
* events being absorbed and that's OK because we're done
*/
- if (edesc->processed == edesc->pset_nr)
- edma_link(echan->slot[nslots-1], echan->ecc->dummy_slot);
+ if (edesc->processed == edesc->pset_nr) {
+ if (edesc->cyclic)
+ edma_link(echan->slot[nslots-1], echan->slot[1]);
+ else
+ edma_link(echan->slot[nslots-1],
+ echan->ecc->dummy_slot);
+ }
edma_resume(echan->ch_num);
@@ -250,6 +262,117 @@ static int edma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
return ret;
}
+/*
+ * A PaRAM set configuration abstraction used by other modes
+ * @chan: Channel who's PaRAM set we're configuring
+ * @pset: PaRAM set to initialize and setup.
+ * @src_addr: Source address of the DMA
+ * @dst_addr: Destination address of the DMA
+ * @burst: In units of dev_width, how much to send
+ * @dev_width: How much is the dev_width
+ * @dma_length: Total length of the DMA transfer
+ * @direction: Direction of the transfer
+ */
+static int edma_config_pset(struct dma_chan *chan, struct edmacc_param *pset,
+ dma_addr_t src_addr, dma_addr_t dst_addr, u32 burst,
+ enum dma_slave_buswidth dev_width, unsigned int dma_length,
+ enum dma_transfer_direction direction)
+{
+ struct edma_chan *echan = to_edma_chan(chan);
+ struct device *dev = chan->device->dev;
+ int acnt, bcnt, ccnt, cidx;
+ int src_bidx, dst_bidx, src_cidx, dst_cidx;
+ int absync;
+
+ acnt = dev_width;
+ /*
+ * If the maxburst is equal to the fifo width, use
+ * A-synced transfers. This allows for large contiguous
+ * buffer transfers using only one PaRAM set.
+ */
+ if (burst == 1) {
+ /*
+ * For the A-sync case, bcnt and ccnt are the remainder
+ * and quotient respectively of the division of:
+ * (dma_length / acnt) by (SZ_64K -1). This is so
+ * that in case bcnt over flows, we have ccnt to use.
+ * Note: In A-sync tranfer only, bcntrld is used, but it
+ * only applies for sg_dma_len(sg) >= SZ_64K.
+ * In this case, the best way adopted is- bccnt for the
+ * first frame will be the remainder below. Then for
+ * every successive frame, bcnt will be SZ_64K-1. This
+ * is assured as bcntrld = 0xffff in end of function.
+ */
+ absync = false;
+ ccnt = dma_length / acnt / (SZ_64K - 1);
+ bcnt = dma_length / acnt - ccnt * (SZ_64K - 1);
+ /*
+ * If bcnt is non-zero, we have a remainder and hence an
+ * extra frame to transfer, so increment ccnt.
+ */
+ if (bcnt)
+ ccnt++;
+ else
+ bcnt = SZ_64K - 1;
+ cidx = acnt;
+ } else {
+ /*
+ * If maxburst is greater than the fifo address_width,
+ * use AB-synced transfers where A count is the fifo
+ * address_width and B count is the maxburst. In this
+ * case, we are limited to transfers of C count frames
+ * of (address_width * maxburst) where C count is limited
+ * to SZ_64K-1. This places an upper bound on the length
+ * of an SG segment that can be handled.
+ */
+ absync = true;
+ bcnt = burst;
+ ccnt = dma_length / (acnt * bcnt);
+ if (ccnt > (SZ_64K - 1)) {
+ dev_err(dev, "Exceeded max SG segment size\n");
+ return -EINVAL;
+ }
+ cidx = acnt * bcnt;
+ }
+
+ if (direction == DMA_MEM_TO_DEV) {
+ src_bidx = acnt;
+ src_cidx = cidx;
+ dst_bidx = 0;
+ dst_cidx = 0;
+ } else if (direction == DMA_DEV_TO_MEM) {
+ src_bidx = 0;
+ src_cidx = 0;
+ dst_bidx = acnt;
+ dst_cidx = cidx;
+ } else {
+ dev_err(dev, "%s: direction not implemented yet\n", __func__);
+ return -EINVAL;
+ }
+
+ pset->opt = EDMA_TCC(EDMA_CHAN_SLOT(echan->ch_num));
+ /* Configure A or AB synchronized transfers */
+ if (absync)
+ pset->opt |= SYNCDIM;
+
+ pset->src = src_addr;
+ pset->dst = dst_addr;
+
+ pset->src_dst_bidx = (dst_bidx << 16) | src_bidx;
+ pset->src_dst_cidx = (dst_cidx << 16) | src_cidx;
+
+ pset->a_b_cnt = bcnt << 16 | acnt;
+ pset->ccnt = ccnt;
+ /*
+ * Only time when (bcntrld) auto reload is required is for
+ * A-sync case, and in this case, a requirement of reload value
+ * of SZ_64K-1 only is assured. 'link' is initially set to NULL
+ * and then later will be populated by edma_execute.
+ */
+ pset->link_bcntrld = 0xffffffff;
+ return absync;
+}
+
static struct dma_async_tx_descriptor *edma_prep_slave_sg(
struct dma_chan *chan, struct scatterlist *sgl,
unsigned int sg_len, enum dma_transfer_direction direction,
@@ -258,23 +381,21 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
struct edma_chan *echan = to_edma_chan(chan);
struct device *dev = chan->device->dev;
struct edma_desc *edesc;
- dma_addr_t dev_addr;
+ dma_addr_t src_addr = 0, dst_addr = 0;
enum dma_slave_buswidth dev_width;
u32 burst;
struct scatterlist *sg;
- int acnt, bcnt, ccnt, src, dst, cidx;
- int src_bidx, dst_bidx, src_cidx, dst_cidx;
- int i, nslots;
+ int i, nslots, ret;
if (unlikely(!echan || !sgl || !sg_len))
return NULL;
if (direction == DMA_DEV_TO_MEM) {
- dev_addr = echan->cfg.src_addr;
+ src_addr = echan->cfg.src_addr;
dev_width = echan->cfg.src_addr_width;
burst = echan->cfg.src_maxburst;
} else if (direction == DMA_MEM_TO_DEV) {
- dev_addr = echan->cfg.dst_addr;
+ dst_addr = echan->cfg.dst_addr;
dev_width = echan->cfg.dst_addr_width;
burst = echan->cfg.dst_maxburst;
} else {
@@ -307,7 +428,6 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
if (echan->slot[i] < 0) {
kfree(edesc);
dev_err(dev, "Failed to allocate slot\n");
- kfree(edesc);
return NULL;
}
}
@@ -315,64 +435,21 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
/* Configure PaRAM sets for each SG */
for_each_sg(sgl, sg, sg_len, i) {
-
- acnt = dev_width;
-
- /*
- * If the maxburst is equal to the fifo width, use
- * A-synced transfers. This allows for large contiguous
- * buffer transfers using only one PaRAM set.
- */
- if (burst == 1) {
- edesc->absync = false;
- ccnt = sg_dma_len(sg) / acnt / (SZ_64K - 1);
- bcnt = sg_dma_len(sg) / acnt - ccnt * (SZ_64K - 1);
- if (bcnt)
- ccnt++;
- else
- bcnt = SZ_64K - 1;
- cidx = acnt;
- /*
- * If maxburst is greater than the fifo address_width,
- * use AB-synced transfers where A count is the fifo
- * address_width and B count is the maxburst. In this
- * case, we are limited to transfers of C count frames
- * of (address_width * maxburst) where C count is limited
- * to SZ_64K-1. This places an upper bound on the length
- * of an SG segment that can be handled.
- */
- } else {
- edesc->absync = true;
- bcnt = burst;
- ccnt = sg_dma_len(sg) / (acnt * bcnt);
- if (ccnt > (SZ_64K - 1)) {
- dev_err(dev, "Exceeded max SG segment size\n");
- kfree(edesc);
- return NULL;
- }
- cidx = acnt * bcnt;
- }
-
- if (direction == DMA_MEM_TO_DEV) {
- src = sg_dma_address(sg);
- dst = dev_addr;
- src_bidx = acnt;
- src_cidx = cidx;
- dst_bidx = 0;
- dst_cidx = 0;
- } else {
- src = dev_addr;
- dst = sg_dma_address(sg);
- src_bidx = 0;
- src_cidx = 0;
- dst_bidx = acnt;
- dst_cidx = cidx;
+ /* Get address for each SG */
+ if (direction == DMA_DEV_TO_MEM)
+ dst_addr = sg_dma_address(sg);
+ else
+ src_addr = sg_dma_address(sg);
+
+ ret = edma_config_pset(chan, &edesc->pset[i], src_addr,
+ dst_addr, burst, dev_width,
+ sg_dma_len(sg), direction);
+ if (ret < 0) {
+ kfree(edesc);
+ return NULL;
}
- edesc->pset[i].opt = EDMA_TCC(EDMA_CHAN_SLOT(echan->ch_num));
- /* Configure A or AB synchronized transfers */
- if (edesc->absync)
- edesc->pset[i].opt |= SYNCDIM;
+ edesc->absync = ret;
/* If this is the last in a current SG set of transactions,
enable interrupts so that next set is processed */
@@ -382,17 +459,138 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg(
/* If this is the last set, enable completion interrupt flag */
if (i == sg_len - 1)
edesc->pset[i].opt |= TCINTEN;
+ }
+
+ return vchan_tx_prep(&echan->vchan, &edesc->vdesc, tx_flags);
+}
+
+static struct dma_async_tx_descriptor *edma_prep_dma_cyclic(
+ struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
+ size_t period_len, enum dma_transfer_direction direction,
+ unsigned long tx_flags, void *context)
+{
+ struct edma_chan *echan = to_edma_chan(chan);
+ struct device *dev = chan->device->dev;
+ struct edma_desc *edesc;
+ dma_addr_t src_addr, dst_addr;
+ enum dma_slave_buswidth dev_width;
+ u32 burst;
+ int i, ret, nslots;
+
+ if (unlikely(!echan || !buf_len || !period_len))
+ return NULL;
+
+ if (direction == DMA_DEV_TO_MEM) {
+ src_addr = echan->cfg.src_addr;
+ dst_addr = buf_addr;
+ dev_width = echan->cfg.src_addr_width;
+ burst = echan->cfg.src_maxburst;
+ } else if (direction == DMA_MEM_TO_DEV) {
+ src_addr = buf_addr;
+ dst_addr = echan->cfg.dst_addr;
+ dev_width = echan->cfg.dst_addr_width;
+ burst = echan->cfg.dst_maxburst;
+ } else {
+ dev_err(dev, "%s: bad direction?\n", __func__);
+ return NULL;
+ }
+
+ if (dev_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) {
+ dev_err(dev, "Undefined slave buswidth\n");
+ return NULL;
+ }
+
+ if (unlikely(buf_len % period_len)) {
+ dev_err(dev, "Period should be multiple of Buffer length\n");
+ return NULL;
+ }
+
+ nslots = (buf_len / period_len) + 1;
+
+ /*
+ * Cyclic DMA users such as audio cannot tolerate delays introduced
+ * by cases where the number of periods is more than the maximum
+ * number of SGs the EDMA driver can handle at a time. For DMA types
+ * such as Slave SGs, such delays are tolerable and synchronized,
+ * but the synchronization is difficult to achieve with Cyclic and
+ * cannot be guaranteed, so we error out early.
+ */
+ if (nslots > MAX_NR_SG)
+ return NULL;
+
+ edesc = kzalloc(sizeof(*edesc) + nslots *
+ sizeof(edesc->pset[0]), GFP_ATOMIC);
+ if (!edesc) {
+ dev_dbg(dev, "Failed to allocate a descriptor\n");
+ return NULL;
+ }
+
+ edesc->cyclic = 1;
+ edesc->pset_nr = nslots;
+
+ dev_dbg(dev, "%s: nslots=%d\n", __func__, nslots);
+ dev_dbg(dev, "%s: period_len=%d\n", __func__, period_len);
+ dev_dbg(dev, "%s: buf_len=%d\n", __func__, buf_len);
+
+ for (i = 0; i < nslots; i++) {
+ /* Allocate a PaRAM slot, if needed */
+ if (echan->slot[i] < 0) {
+ echan->slot[i] =
+ edma_alloc_slot(EDMA_CTLR(echan->ch_num),
+ EDMA_SLOT_ANY);
+ if (echan->slot[i] < 0) {
+ dev_err(dev, "Failed to allocate slot\n");
+ return NULL;
+ }
+ }
- edesc->pset[i].src = src;
- edesc->pset[i].dst = dst;
+ if (i == nslots - 1) {
+ memcpy(&edesc->pset[i], &edesc->pset[0],
+ sizeof(edesc->pset[0]));
+ break;
+ }
- edesc->pset[i].src_dst_bidx = (dst_bidx << 16) | src_bidx;
- edesc->pset[i].src_dst_cidx = (dst_cidx << 16) | src_cidx;
+ ret = edma_config_pset(chan, &edesc->pset[i], src_addr,
+ dst_addr, burst, dev_width, period_len,
+ direction);
+ if (ret < 0)
+ return NULL;
- edesc->pset[i].a_b_cnt = bcnt << 16 | acnt;
- edesc->pset[i].ccnt = ccnt;
- edesc->pset[i].link_bcntrld = 0xffffffff;
+ if (direction == DMA_DEV_TO_MEM)
+ dst_addr += period_len;
+ else
+ src_addr += period_len;
+ dev_dbg(dev, "%s: Configure period %d of buf:\n", __func__, i);
+ dev_dbg(dev,
+ "\n pset[%d]:\n"
+ " chnum\t%d\n"
+ " slot\t%d\n"
+ " opt\t%08x\n"
+ " src\t%08x\n"
+ " dst\t%08x\n"
+ " abcnt\t%08x\n"
+ " ccnt\t%08x\n"
+ " bidx\t%08x\n"
+ " cidx\t%08x\n"
+ " lkrld\t%08x\n",
+ i, echan->ch_num, echan->slot[i],
+ edesc->pset[i].opt,
+ edesc->pset[i].src,
+ edesc->pset[i].dst,
+ edesc->pset[i].a_b_cnt,
+ edesc->pset[i].ccnt,
+ edesc->pset[i].src_dst_bidx,
+ edesc->pset[i].src_dst_cidx,
+ edesc->pset[i].link_bcntrld);
+
+ edesc->absync = ret;
+
+ /*
+ * Enable interrupts for every period because callback
+ * has to be called for every period.
+ */
+ edesc->pset[i].opt |= TCINTEN;
}
return vchan_tx_prep(&echan->vchan, &edesc->vdesc, tx_flags);
@@ -406,30 +604,34 @@ static void edma_callback(unsigned ch_num, u16 ch_status, void *data)
unsigned long flags;
struct edmacc_param p;
- /* Pause the channel */
- edma_pause(echan->ch_num);
+ edesc = echan->edesc;
+
+ /* Pause the channel for non-cyclic */
+ if (!edesc || (edesc && !edesc->cyclic))
+ edma_pause(echan->ch_num);
switch (ch_status) {
- case DMA_COMPLETE:
+ case EDMA_DMA_COMPLETE:
spin_lock_irqsave(&echan->vchan.lock, flags);
- edesc = echan->edesc;
if (edesc) {
- if (edesc->processed == edesc->pset_nr) {
+ if (edesc->cyclic) {
+ vchan_cyclic_callback(&edesc->vdesc);
+ } else if (edesc->processed == edesc->pset_nr) {
dev_dbg(dev, "Transfer complete, stopping channel %d\n", ch_num);
edma_stop(echan->ch_num);
vchan_cookie_complete(&edesc->vdesc);
+ edma_execute(echan);
} else {
dev_dbg(dev, "Intermediate transfer complete on channel %d\n", ch_num);
+ edma_execute(echan);
}
-
- edma_execute(echan);
}
spin_unlock_irqrestore(&echan->vchan.lock, flags);
break;
- case DMA_CC_ERROR:
+ case EDMA_DMA_CC_ERROR:
spin_lock_irqsave(&echan->vchan.lock, flags);
edma_read_slot(EDMA_CHAN_SLOT(echan->slot[0]), &p);
@@ -579,7 +781,7 @@ static enum dma_status edma_tx_status(struct dma_chan *chan,
unsigned long flags;
ret = dma_cookie_status(chan, cookie, txstate);
- if (ret == DMA_SUCCESS || !txstate)
+ if (ret == DMA_COMPLETE || !txstate)
return ret;
spin_lock_irqsave(&echan->vchan.lock, flags);
@@ -619,6 +821,7 @@ static void edma_dma_init(struct edma_cc *ecc, struct dma_device *dma,
struct device *dev)
{
dma->device_prep_slave_sg = edma_prep_slave_sg;
+ dma->device_prep_dma_cyclic = edma_prep_dma_cyclic;
dma->device_alloc_chan_resources = edma_alloc_chan_resources;
dma->device_free_chan_resources = edma_free_chan_resources;
dma->device_issue_pending = edma_issue_pending;
@@ -634,6 +837,10 @@ static int edma_probe(struct platform_device *pdev)
struct edma_cc *ecc;
int ret;
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (ret)
+ return ret;
+
ecc = devm_kzalloc(&pdev->dev, sizeof(*ecc), GFP_KERNEL);
if (!ecc) {
dev_err(&pdev->dev, "Can't allocate controller\n");
@@ -705,11 +912,13 @@ static struct platform_device *pdev0, *pdev1;
static const struct platform_device_info edma_dev_info0 = {
.name = "edma-dma-engine",
.id = 0,
+ .dma_mask = DMA_BIT_MASK(32),
};
static const struct platform_device_info edma_dev_info1 = {
.name = "edma-dma-engine",
.id = 1,
+ .dma_mask = DMA_BIT_MASK(32),
};
static int edma_init(void)
@@ -723,8 +932,6 @@ static int edma_init(void)
ret = PTR_ERR(pdev0);
goto out;
}
- pdev0->dev.dma_mask = &pdev0->dev.coherent_dma_mask;
- pdev0->dev.coherent_dma_mask = DMA_BIT_MASK(32);
}
if (EDMA_CTLRS == 2) {
@@ -734,8 +941,6 @@ static int edma_init(void)
platform_device_unregister(pdev0);
ret = PTR_ERR(pdev1);
}
- pdev1->dev.dma_mask = &pdev1->dev.coherent_dma_mask;
- pdev1->dev.coherent_dma_mask = DMA_BIT_MASK(32);
}
out:
diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c
index 591cd8c..cb4bf68 100644
--- a/drivers/dma/ep93xx_dma.c
+++ b/drivers/dma/ep93xx_dma.c
@@ -733,28 +733,6 @@ static void ep93xx_dma_advance_work(struct ep93xx_dma_chan *edmac)
spin_unlock_irqrestore(&edmac->lock, flags);
}
-static void ep93xx_dma_unmap_buffers(struct ep93xx_dma_desc *desc)
-{
- struct device *dev = desc->txd.chan->device->dev;
-
- if (!(desc->txd.flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
- if (desc->txd.flags & DMA_COMPL_SRC_UNMAP_SINGLE)
- dma_unmap_single(dev, desc->src_addr, desc->size,
- DMA_TO_DEVICE);
- else
- dma_unmap_page(dev, desc->src_addr, desc->size,
- DMA_TO_DEVICE);
- }
- if (!(desc->txd.flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
- if (desc->txd.flags & DMA_COMPL_DEST_UNMAP_SINGLE)
- dma_unmap_single(dev, desc->dst_addr, desc->size,
- DMA_FROM_DEVICE);
- else
- dma_unmap_page(dev, desc->dst_addr, desc->size,
- DMA_FROM_DEVICE);
- }
-}
-
static void ep93xx_dma_tasklet(unsigned long data)
{
struct ep93xx_dma_chan *edmac = (struct ep93xx_dma_chan *)data;
@@ -787,13 +765,7 @@ static void ep93xx_dma_tasklet(unsigned long data)
/* Now we can release all the chained descriptors */
list_for_each_entry_safe(desc, d, &list, node) {
- /*
- * For the memcpy channels the API requires us to unmap the
- * buffers unless requested otherwise.
- */
- if (!edmac->chan.private)
- ep93xx_dma_unmap_buffers(desc);
-
+ dma_descriptor_unmap(&desc->txd);
ep93xx_dma_desc_put(edmac, desc);
}
diff --git a/drivers/dma/fsl_raid.c b/drivers/dma/fsl_raid.c
new file mode 100644
index 0000000..df3c9da
--- /dev/null
+++ b/drivers/dma/fsl_raid.c
@@ -0,0 +1,889 @@
+/*
+ * drivers/dma/fsl_raid.c
+ *
+ * Freescale RAID Engine device driver
+ *
+ * Author:
+ * Harninder Rai <harninder.rai@freescale.com>
+ * Naveen Burmi <naveenburmi@freescale.com>
+ *
+ * Copyright (c) 2010-2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Theory of operation:
+ *
+ * General capabilities:
+ * RAID Engine (RE) block is capable of offloading XOR, memcpy and P/Q
+ * calculations required in RAID5 and RAID6 operations. RE driver
+ * registers with Linux's ASYNC layer as dma driver. RE hardware
+ * maintains strict ordering of the requests through chained
+ * command queueing.
+ *
+ * Data flow:
+ * Software RAID layer of Linux (MD layer) maintains RAID partitions,
+ * strips, stripes etc. It sends requests to the underlying AYSNC layer
+ * which further passes it to RE driver. ASYNC layer decides which request
+ * goes to which job ring of RE hardware. For every request processed by
+ * RAID Engine, driver gets an interrupt unless coalescing is set. The
+ * per job ring interrupt handler checks the status register for errors,
+ * clears the interrupt and schedules a tasklet. Main request processing
+ * is done in tasklet. A software shadow copy of the HW ring is kept to
+ * maintain virtual to physical translation. Based on the internal indexes
+ * maintained, the tasklet picks the descriptor address from shadow copy,
+ * updates the corresponding cookie, updates the outbound ring job removed
+ * register in RE hardware and eventually calls the callback function. This
+ * callback function gets passed as part of request from MD layer.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/dmaengine.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+
+#include "dmaengine.h"
+#include "fsl_raid.h"
+
+#define MAX_XOR_SRCS 16
+#define MAX_PQ_SRCS 16
+#define MAX_INITIAL_DESCS 256
+#define FRAME_FORMAT 0x1
+#define MAX_DATA_LENGTH (1024*1024)
+
+#define to_fsl_re_dma_desc(tx) container_of(tx, \
+ struct fsl_re_dma_async_tx_desc, async_tx)
+
+/* Add descriptors into per jr software queue - submit_q */
+static dma_cookie_t re_jr_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+ struct fsl_re_dma_async_tx_desc *desc = NULL;
+ struct re_jr *jr = NULL;
+ dma_cookie_t cookie;
+
+ desc = container_of(tx, struct fsl_re_dma_async_tx_desc, async_tx);
+ jr = container_of(tx->chan, struct re_jr, chan);
+
+ spin_lock_bh(&jr->desc_lock);
+
+ jr->timer.data = (unsigned long)tx->chan;
+ cookie = jr->chan.cookie + 1;
+ if (cookie < 0)
+ cookie = 1;
+
+ desc->async_tx.cookie = cookie;
+ jr->chan.cookie = desc->async_tx.cookie;
+ jr->pend_count++;
+
+ if (!timer_pending(&jr->timer))
+ add_timer(&jr->timer);
+
+ spin_unlock_bh(&jr->desc_lock);
+
+ return cookie;
+}
+
+static void re_jr_desc_done(struct fsl_re_dma_async_tx_desc *desc)
+{
+ struct dma_chan *chan = &desc->jr->chan;
+ dma_async_tx_callback callback;
+ void *callback_param;
+
+ callback = desc->async_tx.callback;
+ callback_param = desc->async_tx.callback_param;
+
+ dma_run_dependencies(&desc->async_tx);
+
+ if (chan->completed_cookie < desc->async_tx.cookie) {
+ chan->completed_cookie = desc->async_tx.cookie;
+ if (chan->completed_cookie == DMA_MAX_COOKIE)
+ chan->completed_cookie = DMA_MIN_COOKIE;
+ }
+
+ if (callback)
+ callback(callback_param);
+}
+
+/*
+ * Get the virtual address of software desc from virt_addr.
+ * Storing the address of software desc like this makes the
+ * order of alogorithm as O(1)
+ */
+static void re_jr_dequeue(unsigned long data)
+{
+ struct device *dev;
+ struct re_jr *jr;
+ struct fsl_re_dma_async_tx_desc *desc;
+ unsigned int count;
+ struct fsl_re_dma_async_tx_desc *ack_desc = NULL, *_ack_desc = NULL;
+
+ dev = (struct device *)data;
+ jr = dev_get_drvdata(dev);
+
+ spin_lock_bh(&jr->desc_lock);
+ count = RE_JR_OUB_SLOT_FULL(in_be32(&jr->jrregs->oubring_slot_full));
+ if (count) {
+ out_be32(&jr->jrregs->oubring_job_rmvd,
+ RE_JR_OUB_JOB_REMOVE(count));
+ while (count--) {
+ jr->oub_count &= RING_SIZE_MASK;
+ desc = &jr->descs[jr->oub_count++];
+ list_add_tail(&desc->node, &jr->ack_q);
+ re_jr_desc_done(desc);
+ }
+ }
+ spin_unlock_bh(&jr->desc_lock);
+
+ /* To save memory, parse the ack_q and free up descs */
+ list_for_each_entry_safe(ack_desc, _ack_desc, &jr->ack_q, node) {
+ if (async_tx_test_ack(&ack_desc->async_tx)) {
+ spin_lock_bh(&jr->desc_lock);
+ list_del(&ack_desc->node);
+ ack_desc->state = RE_DESC_EMPTY;
+ ack_desc->async_tx.flags = 0;
+ spin_unlock_bh(&jr->desc_lock);
+ }
+ }
+}
+
+/* Per Job Ring interrupt handler */
+static irqreturn_t re_jr_interrupt(int irq, void *data)
+{
+ struct device *dev = data;
+ struct re_jr *jr = dev_get_drvdata(dev);
+
+ u32 irqstate, status;
+ irqstate = in_be32(&jr->jrregs->jr_interrupt_status);
+ if (!irqstate)
+ return IRQ_NONE;
+
+ /*
+ * There's no way in upper layer (read MD layer) to recover from
+ * error conditions except restart everything. In long term we
+ * need to do something more than just crashing
+ */
+ if (irqstate & RE_JR_ERROR) {
+ status = in_be32(&jr->jrregs->jr_status);
+ dev_err(dev, "jr error irqstate: %x, status: %x\n", irqstate,
+ status);
+ }
+
+ /* Clear interrupt */
+ out_be32(&jr->jrregs->jr_interrupt_status, RE_JR_CLEAR_INT);
+
+ tasklet_schedule(&jr->irqtask);
+ return IRQ_HANDLED;
+}
+
+static enum dma_status re_jr_tx_status(struct dma_chan *chan,
+ dma_cookie_t cookie, struct dma_tx_state *txstate)
+{
+ return dma_cookie_status(chan, cookie, txstate);
+}
+
+
+/* Copy descriptor from per jr software queue into hardware job ring */
+void re_jr_issue_pending(struct dma_chan *chan)
+{
+ struct re_jr *jr = NULL;
+ int avail = 0;
+
+ jr = container_of(chan, struct re_jr, chan);
+ if (timer_pending(&jr->timer))
+ del_timer_sync(&jr->timer);
+
+ spin_lock_bh(&jr->desc_lock);
+ if (!jr->pend_count)
+ goto out_unlock;
+
+ avail = RE_JR_INB_SLOT_AVAIL(in_be32(&jr->jrregs->inbring_slot_avail));
+ if (!avail)
+ goto out_unlock;
+
+ if (avail > jr->pend_count)
+ avail = jr->pend_count;
+
+ jr->pend_count -= avail;
+ jr->inb_count = (jr->inb_count + avail) & RING_SIZE_MASK;
+
+ /* add jobs into job ring */
+ out_be32(&jr->jrregs->inbring_add_job, RE_JR_INB_JOB_ADD(avail));
+
+out_unlock:
+ spin_unlock_bh(&jr->desc_lock);
+}
+
+/* Per Job Ring timer handler */
+static void raide_timer_handler(unsigned long data)
+{
+ struct dma_chan *chan = NULL;
+ chan = (struct dma_chan *)data;
+
+ re_jr_issue_pending(chan);
+
+ return;
+}
+
+void fill_cfd_frame(struct cmpnd_frame *cf, u8 index,
+ size_t length, dma_addr_t addr, bool final)
+{
+ cf[index].final = final;
+ cf[index].length = length;
+ cf[index].address = addr;
+}
+
+static struct fsl_re_dma_async_tx_desc *re_jr_init_desc(struct re_jr *jr,
+ struct fsl_re_dma_async_tx_desc *desc, void *cf, dma_addr_t paddr)
+{
+ desc->jr = jr;
+ desc->async_tx.tx_submit = re_jr_tx_submit;
+ dma_async_tx_descriptor_init(&desc->async_tx, &jr->chan);
+ INIT_LIST_HEAD(&desc->node);
+
+ desc->hwdesc->format = FRAME_FORMAT;
+ desc->hwdesc->address = paddr;
+ desc->cf_addr = cf;
+
+ desc->cdb_addr = (void *)(cf + RE_CF_DESC_SIZE);
+ desc->cdb_paddr = paddr + RE_CF_DESC_SIZE;
+
+ return desc;
+}
+
+static struct fsl_re_dma_async_tx_desc *re_jr_alloc_desc(struct re_jr *jr,
+ unsigned long flags)
+{
+ struct fsl_re_dma_async_tx_desc *desc;
+
+ spin_lock_bh(&jr->desc_lock);
+ desc = &jr->descs[jr->inb_count];
+ if (desc->state != RE_DESC_EMPTY) {
+ spin_unlock_bh(&jr->desc_lock);
+ re_jr_issue_pending(&jr->chan);
+ return NULL;
+ }
+ desc->state = RE_DESC_ALLOC;
+ desc->async_tx.flags = flags;
+ spin_unlock_bh(&jr->desc_lock);
+
+ return desc;
+}
+
+static struct dma_async_tx_descriptor *re_jr_prep_genq(
+ struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
+ unsigned int src_cnt, const unsigned char *scf, size_t len,
+ unsigned long flags)
+{
+ struct re_jr *jr;
+ struct fsl_re_dma_async_tx_desc *desc;
+ struct xor_cdb *xor;
+ struct cmpnd_frame *cf;
+ unsigned int i, j;
+
+ if (len > MAX_DATA_LENGTH) {
+ pr_err("Length greater than %d not supported\n",
+ MAX_DATA_LENGTH);
+ return NULL;
+ }
+
+ jr = container_of(chan, struct re_jr, chan);
+ desc = re_jr_alloc_desc(jr, flags);
+ if (desc <= 0)
+ return NULL;
+
+ desc->dma_len = len;
+ desc->dest_cnt = 1;
+ desc->src_cnt = src_cnt;
+
+ desc->cdb_opcode = RE_XOR_OPCODE;
+ desc->cdb_len = sizeof(struct xor_cdb);
+
+ /* Filling xor CDB */
+ xor = desc->cdb_addr;
+ xor->opcode = RE_XOR_OPCODE;
+ xor->nrcs = src_cnt - 1;
+ xor->blk_size = RE_BLOCK_SIZE;
+ xor->error_attrib = INTERRUPT_ON_ERROR;
+ xor->data_depend = DATA_DEPENDENCY;
+
+ if (scf != NULL) {
+ /* compute q = src0*coef0^src1*coef1^..., * is GF(8) mult */
+ for (i = 0; i < src_cnt; i++)
+ xor->gfm[i] = scf[i];
+ } else {
+ /* compute P, that is XOR all srcs */
+ for (i = 0; i < src_cnt; i++)
+ xor->gfm[i] = 1;
+ }
+
+ /* Filling frame 0 of compound frame descriptor with CDB */
+ cf = desc->cf_addr;
+ fill_cfd_frame(cf, 0, desc->cdb_len, desc->cdb_paddr, 0);
+
+ /* Fill CFD's 1st frame with dest buffer */
+ fill_cfd_frame(cf, 1, len, dest, 0);
+
+ /* Fill CFD's rest of the frames with source buffers */
+ for (i = 2, j = 0; j < src_cnt; i++, j++)
+ fill_cfd_frame(cf, i, len, src[j], 0);
+
+ /* Setting the final bit in the last source buffer frame in CFD */
+ cf[i - 1].final = 1;
+
+ return &desc->async_tx;
+}
+
+/*
+ * Prep function for P parity calculation.In RAID Engine terminology,
+ * XOR calculation is called GenQ calculation done through GenQ command
+ */
+static struct dma_async_tx_descriptor *re_jr_prep_dma_xor(
+ struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
+ unsigned int src_cnt, size_t len, unsigned long flags)
+{
+ /* NULL let genq take all coef as 1 */
+ return re_jr_prep_genq(chan, dest, src, src_cnt, NULL, len, flags);
+}
+
+/*
+ * Prep function for P/Q parity calculation.In RAID Engine terminology,
+ * P/Q calculation is called GenQQ done through GenQQ command
+ */
+static struct dma_async_tx_descriptor *re_jr_prep_pq(
+ struct dma_chan *chan, dma_addr_t *dest, dma_addr_t *src,
+ unsigned int src_cnt, const unsigned char *scf, size_t len,
+ unsigned long flags)
+{
+ struct re_jr *jr;
+ struct fsl_re_dma_async_tx_desc *desc;
+ struct pq_cdb *pq;
+ struct cmpnd_frame *cf;
+ u8 *p;
+ int gfmq_len, i, j;
+
+ if (len > MAX_DATA_LENGTH) {
+ pr_err("Length greater than %d not supported\n",
+ MAX_DATA_LENGTH);
+ return NULL;
+ }
+
+ /*
+ * RE requires at least 2 sources, if given only one source, we pass the
+ * second source same as the first one.
+ * With only one source, generating P is meaningless, only generate Q.
+ */
+ if (src_cnt == 1) {
+ struct dma_async_tx_descriptor *tx;
+ dma_addr_t dma_src[2];
+ unsigned char coef[2];
+
+ dma_src[0] = *src;
+ coef[0] = *scf;
+ dma_src[1] = *src;
+ coef[1] = 0;
+ tx = re_jr_prep_genq(chan, dest[1], dma_src, 2, coef, len,
+ flags);
+ if (tx) {
+ desc = to_fsl_re_dma_desc(tx);
+ desc->src_cnt = 1;
+ }
+ return tx;
+ }
+
+ /*
+ * During RAID6 array creation, Linux's MD layer gets P and Q
+ * calculated separately in two steps. But our RAID Engine has
+ * the capability to calculate both P and Q with a single command
+ * Hence to merge well with MD layer, we need to provide a hook
+ * here and call re_jq_prep_genq() function
+ */
+
+ if (flags & DMA_PREP_PQ_DISABLE_P)
+ return re_jr_prep_genq(chan, dest[1], src, src_cnt,
+ scf, len, flags);
+
+ jr = container_of(chan, struct re_jr, chan);
+ desc = re_jr_alloc_desc(jr, flags);
+ if (desc <= 0)
+ return NULL;
+
+ desc->dma_len = len;
+ desc->dest_cnt = 2;
+ desc->src_cnt = src_cnt;
+
+ desc->cdb_opcode = RE_PQ_OPCODE;
+ desc->cdb_len = sizeof(struct pq_cdb);
+
+ /* Filling GenQQ CDB */
+ pq = desc->cdb_addr;
+ pq->opcode = RE_PQ_OPCODE;
+ pq->blk_size = RE_BLOCK_SIZE;
+ pq->buffer_attrib = BUFFERABLE_OUTPUT;
+ pq->data_depend = DATA_DEPENDENCY;
+ pq->nrcs = (src_cnt - 1);
+
+ p = pq->gfm_q1;
+ /* Init gfm_q1[] */
+ for (i = 0; i < src_cnt; i++)
+ p[i] = 1;
+
+ /* Align gfm[] to 32bit */
+ gfmq_len = ALIGN(src_cnt, 4);
+
+ /* Init gfm_q2[] */
+ p += gfmq_len;
+ for (i = 0; i < src_cnt; i++)
+ p[i] = scf[i];
+
+ /* Filling frame 0 of compound frame descriptor with CDB */
+ cf = desc->cf_addr;
+ fill_cfd_frame(cf, 0, desc->cdb_len, desc->cdb_paddr, 0);
+
+ /* Fill CFD's 1st & 2nd frame with dest buffers */
+ for (i = 1, j = 0; i < 3; i++, j++)
+ fill_cfd_frame(cf, i, len, dest[j], 0);
+
+ /* Fill CFD's rest of the frames with source buffers */
+ for (i = 3, j = 0; j < src_cnt; i++, j++)
+ fill_cfd_frame(cf, i, len, src[j], 0);
+
+ /* Setting the final bit in the last source buffer frame in CFD */
+ cf[i - 1].final = 1;
+
+ return &desc->async_tx;
+}
+
+/*
+ * Prep function for memcpy. In RAID Engine, memcpy is done through MOVE
+ * command. Logic of this function will need to be modified once multipage
+ * support is added in Linux's MD/ASYNC Layer
+ */
+static struct dma_async_tx_descriptor *re_jr_prep_memcpy(
+ struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+ size_t len, unsigned long flags)
+{
+ struct re_jr *jr;
+ struct fsl_re_dma_async_tx_desc *desc;
+ size_t length;
+ struct cmpnd_frame *cf;
+ struct move_cdb *move;
+
+ jr = container_of(chan, struct re_jr, chan);
+
+ if (len > MAX_DATA_LENGTH) {
+ pr_err("Length greater than %d not supported\n",
+ MAX_DATA_LENGTH);
+ return NULL;
+ }
+
+ desc = re_jr_alloc_desc(jr, flags);
+ if (desc <= 0)
+ return NULL;
+
+ desc->dma_len = len;
+ desc->src_cnt = 1;
+ desc->dest_cnt = 1;
+
+ desc->cdb_opcode = RE_MOVE_OPCODE;
+ desc->cdb_len = sizeof(struct move_cdb);
+
+ /* Filling move CDB */
+ move = desc->cdb_addr;
+ move->opcode = RE_MOVE_OPCODE; /* Unicast move */
+ move->blk_size = RE_BLOCK_SIZE;
+ move->error_attrib = INTERRUPT_ON_ERROR;
+ move->data_depend = DATA_DEPENDENCY;
+
+ /* Filling frame 0 of CFD with move CDB */
+ cf = desc->cf_addr;
+ fill_cfd_frame(cf, 0, desc->cdb_len, desc->cdb_paddr, 0);
+
+ length = min_t(size_t, len, MAX_DATA_LENGTH);
+
+ /* Fill CFD's 1st frame with dest buffer */
+ fill_cfd_frame(cf, 1, length, dest, 0);
+
+ /* Fill CFD's 2nd frame with src buffer */
+ fill_cfd_frame(cf, 2, length, src, 1);
+
+ return &desc->async_tx;
+}
+
+static int re_jr_alloc_chan_resources(struct dma_chan *chan)
+{
+ int i;
+ struct fsl_re_dma_async_tx_desc *desc;
+ struct re_jr *jr = container_of(chan, struct re_jr, chan);
+ void *cf;
+ dma_addr_t paddr;
+
+ jr->descs = kzalloc(sizeof(*desc) * RING_SIZE, GFP_KERNEL);
+ if (!jr->descs) {
+ dev_err(jr->dev, "No memory for sw descriptor ring\n");
+ goto err_free;
+ }
+
+ cf = dma_pool_alloc(jr->re_dev->desc_pool, GFP_ATOMIC, &paddr);
+ if (!cf) {
+ dev_err(jr->dev, "No memory for dma descriptor ring\n");
+ goto err_free;
+ }
+ memset(cf, 0, RE_CF_CDB_SIZE * RING_SIZE);
+ jr->cfs = cf;
+ jr->phys = paddr;
+
+ for (i = 0; i < RING_SIZE; i++) {
+ u32 offset = i * RE_CF_CDB_SIZE;
+ desc = &jr->descs[i];
+ desc->hwdesc = &jr->inb_ring_virt_addr[i];
+ re_jr_init_desc(jr, desc, cf + offset, paddr + offset);
+ desc->state = RE_DESC_EMPTY;
+ }
+ return 0;
+
+err_free:
+ kfree(jr->descs);
+ return -ENOMEM;
+}
+
+static void re_jr_free_chan_resources(struct dma_chan *chan)
+{
+ struct re_jr *jr = container_of(chan, struct re_jr, chan);
+ dma_pool_free(jr->re_dev->desc_pool, jr->cfs, jr->phys);
+ kfree(jr->descs);
+ return;
+}
+
+int re_jr_probe(struct platform_device *ofdev,
+ struct device_node *np, u8 q, u32 off)
+{
+ struct device *dev;
+ struct re_drv_private *repriv;
+ struct re_jr *jr;
+ struct dma_device *dma_dev;
+ u32 ptr;
+ u32 status;
+ int ret = 0, rc;
+ struct platform_device *jr_ofdev;
+
+ dev = &ofdev->dev;
+ repriv = dev_get_drvdata(dev);
+ dma_dev = &repriv->dma_dev;
+
+ jr = kzalloc(sizeof(struct re_jr), GFP_KERNEL);
+ if (!jr) {
+ dev_err(dev, "No free memory for allocating JR struct\n");
+ return -ENOMEM;
+ }
+
+ jr_ofdev = of_platform_device_create(np, NULL, dev);
+ if (jr_ofdev == NULL) {
+ dev_err(dev, "Not able to create ofdev for jr %d\n", q);
+ ret = -EINVAL;
+ goto err_free;
+ }
+ dev_set_drvdata(&jr_ofdev->dev, jr);
+
+ rc = of_property_read_u32(np, "reg", &ptr);
+ if (rc) {
+ dev_err(dev, "Reg property not found in JR number %d\n", q);
+ ret = -ENODEV;
+ goto err_free;
+ }
+
+ jr->jrregs = (struct jr_config_regs *)((u8 *)repriv->re_regs +
+ off + ptr);
+
+ jr->irq = irq_of_parse_and_map(np, 0);
+ if (jr->irq == NO_IRQ) {
+ dev_err(dev, "No IRQ defined for JR %d\n", q);
+ ret = -ENODEV;
+ goto err_free;
+ }
+
+ tasklet_init(&jr->irqtask, re_jr_dequeue,
+ (unsigned long)&jr_ofdev->dev);
+
+ ret = request_irq(jr->irq, re_jr_interrupt, 0, "re-jr", &jr_ofdev->dev);
+ if (ret) {
+ dev_err(dev, "Unable to register JR interrupt for JR %d\n", q);
+ ret = -EINVAL;
+ goto err_free;
+ }
+
+ repriv->re_jrs[q] = jr;
+ jr->chan.device = dma_dev;
+ jr->chan.private = jr;
+ jr->dev = &jr_ofdev->dev;
+ jr->re_dev = repriv;
+ jr->pend_count = 0;
+ INIT_LIST_HEAD(&jr->ack_q);
+ spin_lock_init(&jr->desc_lock);
+
+ init_timer(&jr->timer);
+ jr->timer.expires = jiffies + 10*HZ;
+ jr->timer.function = raide_timer_handler;
+
+ list_add_tail(&jr->chan.device_node, &dma_dev->channels);
+ dma_dev->chancnt++;
+
+ jr->inb_ring_virt_addr = dma_pool_alloc(jr->re_dev->hw_desc_pool,
+ GFP_ATOMIC, &jr->inb_phys_addr);
+
+ if (!jr->inb_ring_virt_addr) {
+ dev_err(dev, "No dma memory for inb_ring_virt_addr\n");
+ ret = -ENOMEM;
+ goto err_free;
+ }
+
+ jr->oub_ring_virt_addr = dma_pool_alloc(jr->re_dev->hw_desc_pool,
+ GFP_ATOMIC, &jr->oub_phys_addr);
+
+ if (!jr->oub_ring_virt_addr) {
+ dev_err(dev, "No dma memory for oub_ring_virt_addr\n");
+ ret = -ENOMEM;
+ goto err_free_1;
+ }
+
+ jr->inb_count = 0;
+ jr->pend_count = 0;
+ jr->oub_count = 0;
+
+ /* Program the Inbound/Outbound ring base addresses and size */
+ out_be32(&jr->jrregs->inbring_base_h,
+ jr->inb_phys_addr & RE_JR_ADDRESS_BIT_MASK);
+ out_be32(&jr->jrregs->oubring_base_h,
+ jr->oub_phys_addr & RE_JR_ADDRESS_BIT_MASK);
+ out_be32(&jr->jrregs->inbring_base_l,
+ jr->inb_phys_addr >> RE_JR_ADDRESS_BIT_SHIFT);
+ out_be32(&jr->jrregs->oubring_base_l,
+ jr->oub_phys_addr >> RE_JR_ADDRESS_BIT_SHIFT);
+ out_be32(&jr->jrregs->inbring_size, RING_SIZE << RING_SIZE_SHIFT);
+ out_be32(&jr->jrregs->oubring_size, RING_SIZE << RING_SIZE_SHIFT);
+
+ /* Read LIODN value from u-boot */
+ status = in_be32(&jr->jrregs->jr_config_1) & RE_JR_REG_LIODN_MASK;
+
+ /* Program the CFG reg */
+ out_be32(&jr->jrregs->jr_config_1,
+ RE_JR_CFG1_CBSI | RE_JR_CFG1_CBS0 | status);
+
+ /* Enable RE/JR */
+ out_be32(&jr->jrregs->jr_command, RE_JR_ENABLE);
+
+ return 0;
+
+err_free_1:
+ dma_pool_free(jr->re_dev->hw_desc_pool, jr->inb_ring_virt_addr,
+ jr->inb_phys_addr);
+err_free:
+ kfree(jr);
+ return ret;
+}
+
+/* Probe function for RAID Engine */
+static int raide_probe(struct platform_device *ofdev)
+{
+ struct re_drv_private *repriv;
+ struct device *dev;
+ struct device_node *np;
+ struct device_node *child;
+ u32 off;
+ u8 ridx = 0;
+ struct dma_device *dma_dev;
+ int ret = 0, rc;
+
+ dev_info(&ofdev->dev, "Freescale RAID Engine driver\n");
+ dev = &ofdev->dev;
+
+ repriv = kzalloc(sizeof(struct re_drv_private), GFP_KERNEL);
+ if (!repriv) {
+ dev_err(dev, "No memory for repriv\n");
+ return -ENOMEM;
+ }
+
+ dev_set_drvdata(dev, repriv);
+
+ /* IOMAP the entire RAID Engine region */
+ repriv->re_regs = of_iomap(ofdev->dev.of_node, 0);
+ if (repriv->re_regs == NULL) {
+ dev_err(dev, "of_iomap failed\n");
+ kfree(repriv);
+ ret = -ENOMEM;
+ goto err_free_4;
+ }
+
+ /* Print the RE version */
+ dev_info(dev, "Ver = %x\n", in_be32(&repriv->re_regs->re_version_id));
+
+ /* Program the RE mode */
+ out_be32(&repriv->re_regs->global_config, RE_NON_DPAA_MODE);
+ dev_info(dev, "RE mode is %x\n",
+ in_be32(&repriv->re_regs->global_config));
+
+ /* Program Galois Field polynomial */
+ out_be32(&repriv->re_regs->galois_field_config, RE_GFM_POLY);
+ dev_info(dev, "Galois Field Polynomial is %x\n",
+ in_be32(&repriv->re_regs->galois_field_config));
+
+ dma_dev = &repriv->dma_dev;
+ dma_dev->dev = dev;
+ INIT_LIST_HEAD(&dma_dev->channels);
+ dma_set_mask(dev, DMA_BIT_MASK(40));
+
+ dma_dev->device_alloc_chan_resources = re_jr_alloc_chan_resources;
+ dma_dev->device_tx_status = re_jr_tx_status;
+ dma_dev->device_issue_pending = re_jr_issue_pending;
+
+ dma_dev->max_xor = MAX_XOR_SRCS;
+ dma_dev->device_prep_dma_xor = re_jr_prep_dma_xor;
+ dma_cap_set(DMA_XOR, dma_dev->cap_mask);
+
+ dma_dev->max_pq = MAX_PQ_SRCS;
+ dma_dev->device_prep_dma_pq = re_jr_prep_pq;
+ dma_cap_set(DMA_PQ, dma_dev->cap_mask);
+
+ dma_dev->device_prep_dma_memcpy = re_jr_prep_memcpy;
+ dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask);
+
+ dma_dev->device_free_chan_resources = re_jr_free_chan_resources;
+
+ repriv->total_jrs = 0;
+
+ repriv->desc_pool = dma_pool_create("re_dma_desc_pool", dev,
+ RE_CF_CDB_SIZE * RING_SIZE,
+ RE_CF_CDB_ALIGN, 0);
+
+ if (!repriv->desc_pool) {
+ pr_err("No memory for dma desc pool\n");
+ ret = -ENOMEM;
+ goto err_free_3;
+ }
+
+ repriv->hw_desc_pool = dma_pool_create("re_hw_desc_pool", dev,
+ sizeof(struct jr_hw_desc) * RING_SIZE,
+ FRAME_DESC_ALIGNMENT, 0);
+ if (!repriv->hw_desc_pool) {
+ pr_err("No memory for hw desc pool\n");
+ ret = -ENOMEM;
+ goto err_free_2;
+ }
+
+ /* Parse Device tree to find out the total number of JQs present */
+ for_each_compatible_node(np, NULL, "fsl,raideng-v1.0-job-queue") {
+ rc = of_property_read_u32(np, "reg", &off);
+ if (rc) {
+ dev_err(dev, "Reg property not found in JQ node\n");
+ return -ENODEV;
+ }
+ /* Find out the Job Rings present under each JQ */
+ for_each_child_of_node(np, child) {
+ rc = of_device_is_compatible(child,
+ "fsl,raideng-v1.0-job-ring");
+ if (rc) {
+ re_jr_probe(ofdev, child, ridx++, off);
+ repriv->total_jrs++;
+ }
+ }
+ }
+
+ dma_async_device_register(dma_dev);
+ return 0;
+
+err_free_2:
+ dma_pool_destroy(repriv->desc_pool);
+err_free_3:
+ iounmap(repriv->re_regs);
+err_free_4:
+ kfree(repriv);
+
+ return ret;
+}
+
+static void release_jr(struct re_jr *jr)
+{
+ /* Free the memory allocated from DMA pools and destroy them */
+ dma_pool_free(jr->re_dev->hw_desc_pool, jr->inb_ring_virt_addr,
+ jr->inb_phys_addr);
+
+ kfree(jr);
+}
+
+static int raide_remove(struct platform_device *ofdev)
+{
+ struct re_drv_private *repriv;
+ struct device *dev;
+ int i;
+
+ dev = &ofdev->dev;
+ repriv = dev_get_drvdata(dev);
+
+ /* Cleanup JR related memory areas */
+ for (i = 0; i < repriv->total_jrs; i++)
+ release_jr(repriv->re_jrs[i]);
+
+ dma_pool_destroy(repriv->hw_desc_pool);
+ dma_pool_destroy(repriv->desc_pool);
+
+ /* Unregister the driver */
+ dma_async_device_unregister(&repriv->dma_dev);
+
+ /* Unmap the RAID Engine region */
+ iounmap(repriv->re_regs);
+
+ kfree(repriv);
+
+ return 0;
+}
+
+static struct of_device_id raide_ids[] = {
+ { .compatible = "fsl,raideng-v1.0", },
+ {}
+};
+
+static struct platform_driver raide_driver = {
+ .driver = {
+ .name = "fsl-raideng",
+ .owner = THIS_MODULE,
+ .of_match_table = raide_ids,
+ },
+ .probe = raide_probe,
+ .remove = raide_remove,
+};
+
+module_platform_driver(raide_driver);
+
+MODULE_AUTHOR("Harninder Rai <harninder.rai@freescale.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Freescale RAID Engine Device Driver");
diff --git a/drivers/dma/fsl_raid.h b/drivers/dma/fsl_raid.h
new file mode 100644
index 0000000..d099f99
--- /dev/null
+++ b/drivers/dma/fsl_raid.h
@@ -0,0 +1,319 @@
+/*
+ * drivers/dma/fsl_raid.h
+ *
+ * Freescale RAID Engine device driver
+ *
+ * Author:
+ * Harninder Rai <harninder.rai@freescale.com>
+ * Naveen Burmi <naveenburmi@freescale.com>
+ *
+ * Copyright (c) 2010-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define RE_DPAA_MODE (1 << 30)
+#define RE_NON_DPAA_MODE (1 << 31)
+#define RE_GFM_POLY 0x1d000000
+#define RE_JR_INB_JOB_ADD(x) ((x) << 16)
+#define RE_JR_OUB_JOB_REMOVE(x) ((x) << 16)
+#define RE_JR_CFG1_CBSI 0x08000000
+#define RE_JR_CFG1_CBS0 0x00080000
+#define RE_JR_OUB_SLOT_FULL_SHIFT 8
+#define RE_JR_OUB_SLOT_FULL(x) ((x) >> RE_JR_OUB_SLOT_FULL_SHIFT)
+#define RE_JR_INB_SLOT_AVAIL_SHIFT 8
+#define RE_JR_INB_SLOT_AVAIL(x) ((x) >> RE_JR_INB_SLOT_AVAIL_SHIFT)
+#define RE_PQ_OPCODE 0x1B
+#define RE_XOR_OPCODE 0x1A
+#define RE_MOVE_OPCODE 0x8
+#define FRAME_DESC_ALIGNMENT 16
+#define RE_BLOCK_SIZE 0x3 /* 4096 bytes */
+#define CACHEABLE_INPUT_OUTPUT 0x0
+#define BUFFERABLE_OUTPUT 0x0
+#define INTERRUPT_ON_ERROR 0x1
+#define DATA_DEPENDENCY 0x1
+#define ENABLE_DPI 0x0
+#define RING_SIZE 0x1000
+#define RING_SIZE_MASK (RING_SIZE - 1)
+#define RING_SIZE_SHIFT 8
+#define RE_JR_ADDRESS_BIT_SHIFT 4
+#define RE_JR_ADDRESS_BIT_MASK ((1 << RE_JR_ADDRESS_BIT_SHIFT) - 1)
+#define RE_JR_ERROR 0x40000000
+#define RE_JR_INTERRUPT 0x80000000
+#define RE_JR_CLEAR_INT 0x80000000
+#define RE_JR_PAUSE 0x80000000
+#define RE_JR_ENABLE 0x80000000
+
+#define RE_JR_REG_LIODN_MASK 0x00000fff
+#define RE_CF_CDB_ALIGN 64
+
+/*
+ * the largest cf block is 19*sizeof(struct cmpnd_frame), which is 304 bytes.
+ * here 19 = 1(cdb)+2(dest)+16(src), align to 64bytes, that is 320 bytes.
+ * the largest cdb block: struct pq_cdb which is 180 bytes, adding to cf block
+ * 320+180=500, align to 64bytes, that is 512 bytes.
+ */
+#define RE_CF_DESC_SIZE 320
+#define RE_CF_CDB_SIZE 512
+
+struct re_ctrl {
+ /* General Configuration Registers */
+ __be32 global_config; /* Global Configuration Register */
+ u8 rsvd1[4];
+ __be32 galois_field_config; /* Galois Field Configuration Register */
+ u8 rsvd2[4];
+ __be32 jq_wrr_config; /* WRR Configuration register */
+ u8 rsvd3[4];
+ __be32 crc_config; /* CRC Configuration register */
+ u8 rsvd4[228];
+ __be32 system_reset; /* System Reset Register */
+ u8 rsvd5[252];
+ __be32 global_status; /* Global Status Register */
+ u8 rsvd6[832];
+ __be32 re_liodn_base; /* LIODN Base Register */
+ u8 rsvd7[1712];
+ __be32 re_version_id; /* Version ID register of RE */
+ __be32 re_version_id_2; /* Version ID 2 register of RE */
+ u8 rsvd8[512];
+ __be32 host_config; /* Host I/F Configuration Register */
+};
+
+struct jr_config_regs {
+ /* Registers for JR interface */
+ __be32 jr_config_0; /* Job Queue Configuration 0 Register */
+ __be32 jr_config_1; /* Job Queue Configuration 1 Register */
+ __be32 jr_interrupt_status; /* Job Queue Interrupt Status Register */
+ u8 rsvd1[4];
+ __be32 jr_command; /* Job Queue Command Register */
+ u8 rsvd2[4];
+ __be32 jr_status; /* Job Queue Status Register */
+ u8 rsvd3[228];
+
+ /* Input Ring */
+ __be32 inbring_base_h; /* Inbound Ring Base Address Register - High */
+ __be32 inbring_base_l; /* Inbound Ring Base Address Register - Low */
+ __be32 inbring_size; /* Inbound Ring Size Register */
+ u8 rsvd4[4];
+ __be32 inbring_slot_avail; /* Inbound Ring Slot Available Register */
+ u8 rsvd5[4];
+ __be32 inbring_add_job; /* Inbound Ring Add Job Register */
+ u8 rsvd6[4];
+ __be32 inbring_cnsmr_indx; /* Inbound Ring Consumer Index Register */
+ u8 rsvd7[220];
+
+ /* Output Ring */
+ __be32 oubring_base_h; /* Outbound Ring Base Address Register - High */
+ __be32 oubring_base_l; /* Outbound Ring Base Address Register - Low */
+ __be32 oubring_size; /* Outbound Ring Size Register */
+ u8 rsvd8[4];
+ __be32 oubring_job_rmvd; /* Outbound Ring Job Removed Register */
+ u8 rsvd9[4];
+ __be32 oubring_slot_full; /* Outbound Ring Slot Full Register */
+ u8 rsvd10[4];
+ __be32 oubring_prdcr_indx; /* Outbound Ring Producer Index */
+};
+
+/*
+ * Command Descriptor Block (CDB) for unicast move command.
+ * In RAID Engine terms, memcpy is done through move command
+ */
+struct move_cdb {
+ u32 opcode:5;
+ u32 rsvd1:11;
+ u32 blk_size:2;
+ u32 cache_attrib:2;
+ u32 buffer_attrib:1;
+ u32 error_attrib:1;
+ u32 rsvd2:6;
+ u32 data_depend:1;
+ u32 dpi:1;
+ u32 rsvd3:2;
+} __packed;
+
+/* Data protection/integrity related fields */
+struct dpi_related {
+ u32 apps_mthd:2;
+ u32 ref_mthd:2;
+ u32 guard_mthd:2;
+ u32 dpi_attr:2;
+ u32 rsvd1:8;
+ u32 meta_tag:16;
+ u32 ref_tag:32;
+} __packed;
+
+/*
+ * CDB for GenQ command. In RAID Engine terminology, XOR is
+ * done through this command
+ */
+struct xor_cdb {
+ u32 opcode:5;
+ u32 rsvd1:11;
+ u32 blk_size:2;
+ u32 cache_attrib:2;
+ u32 buffer_attrib:1;
+ u32 error_attrib:1;
+ u32 nrcs:4;
+ u32 rsvd2:2;
+ u32 data_depend:1;
+ u32 dpi:1;
+ u32 rsvd3:2;
+ u8 gfm[16];
+ struct dpi_related dpi_dest_spec;
+ struct dpi_related dpi_src_spec[16];
+} __packed;
+
+/* CDB for no-op command */
+struct noop_cdb {
+ u32 opcode:5;
+ u32 rsvd1:23;
+ u32 dependency:1;
+ u32 rsvd2:3;
+} __packed;
+
+/*
+ * CDB for GenQQ command. In RAID Engine terminology, P/Q is
+ * done through this command
+ */
+struct pq_cdb {
+ u32 opcode:5;
+ u32 rsvd1:1;
+ u32 excl_enable:2;
+ u32 excl_q1:4;
+ u32 excl_q2:4;
+ u32 blk_size:2;
+ u32 cache_attrib:2;
+ u32 buffer_attrib:1;
+ u32 error_attrib:1;
+ u32 nrcs:4;
+ u32 rsvd2:2;
+ u32 data_depend:1;
+ u32 dpi:1;
+ u32 rsvd3:2;
+
+ u8 gfm_q1[16];
+ u8 gfm_q2[16];
+ struct dpi_related dpi_dest_spec[2];
+ struct dpi_related dpi_src_spec[16];
+} __packed;
+
+/* Compound frame */
+struct cmpnd_frame {
+ u64 rsvd1:24;
+ u64 address:40;
+ u32 extension:1;
+ u32 final:1;
+ u32 rsvd3:10;
+ u32 length:20;
+ u32 rsvd4:8;
+ u32 bpid:8;
+ u32 rsvd5:3;
+ u32 offset:13;
+
+} __packed;
+
+/* Frame descriptor */
+struct jr_hw_desc {
+ u64 debug:2;
+ u64 liodn_off:6;
+ u64 bpid:8;
+ u64 eliodn_off:4;
+ u64 rsvd1:4;
+ u64 address:40;
+ u64 format:3;
+ u64 rsvd2:29;
+ u64 status:32;
+} __packed;
+
+#define MAX_RE_JRS 4
+
+/* Raid Engine device private data */
+struct re_drv_private {
+ u8 total_jrs;
+ struct dma_device dma_dev;
+ struct re_ctrl *re_regs;
+ struct re_jr *re_jrs[MAX_RE_JRS];
+ struct dma_pool *desc_pool;
+ struct dma_pool *hw_desc_pool;
+};
+
+/* Per job ring data structure */
+struct re_jr {
+ dma_cookie_t completed_cookie;
+ spinlock_t desc_lock; /* jr data access lock */
+ struct list_head ack_q;
+ struct device *dev;
+ struct re_drv_private *re_dev;
+ struct dma_chan chan;
+ struct jr_config_regs *jrregs;
+ int irq;
+ struct tasklet_struct irqtask;
+
+ /* hw descriptor ring for inbound queue*/
+ dma_addr_t inb_phys_addr;
+ struct jr_hw_desc *inb_ring_virt_addr;
+ u32 inb_count;
+ u32 pend_count;
+
+ /* hw descriptor ring for outbound queue */
+ dma_addr_t oub_phys_addr;
+ struct jr_hw_desc *oub_ring_virt_addr;
+ u32 oub_count;
+
+ struct fsl_re_dma_async_tx_desc *descs; /* sw descriptor ring */
+ void *cfs; /* dma descriptor ring */
+ dma_addr_t phys; /* phys addr for dma descriptor ring */
+
+ struct timer_list timer;
+};
+
+enum desc_state {
+ RE_DESC_EMPTY,
+ RE_DESC_ALLOC,
+};
+
+/* Async transaction descriptor */
+struct fsl_re_dma_async_tx_desc {
+ struct dma_async_tx_descriptor async_tx;
+ struct list_head node;
+ struct list_head tx_list;
+ struct jr_hw_desc *hwdesc;
+ struct re_jr *jr;
+
+ void *cf_addr;
+ int dma_len;
+ u8 dest_cnt;
+ u8 src_cnt;
+
+ u16 cdb_opcode;
+ void *cdb_addr;
+ dma_addr_t cdb_paddr;
+ int cdb_len;
+
+ enum desc_state state;
+};
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index b3f3e90..b150668 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -33,6 +33,8 @@
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include "dmaengine.h"
@@ -405,10 +407,9 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
struct fsldma_chan *chan = to_fsl_chan(tx->chan);
struct fsl_desc_sw *desc = tx_to_fsl_desc(tx);
struct fsl_desc_sw *child;
- unsigned long flags;
- dma_cookie_t cookie;
+ dma_cookie_t cookie = 0;
- spin_lock_irqsave(&chan->desc_lock, flags);
+ spin_lock_bh(&chan->desc_lock);
/*
* assign cookies to all of the software descriptors
@@ -421,12 +422,27 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
/* put this transaction onto the tail of the pending queue */
append_ld_queue(chan, desc);
- spin_unlock_irqrestore(&chan->desc_lock, flags);
+ spin_unlock_bh(&chan->desc_lock);
return cookie;
}
/**
+ * fsl_dma_free_descriptor - Free descriptor from channel's DMA pool.
+ * @chan : Freescale DMA channel
+ * @desc: descriptor to be freed
+ */
+static void fsl_dma_free_descriptor(struct fsldma_chan *chan,
+ struct fsl_desc_sw *desc)
+{
+ list_del(&desc->node);
+#ifdef FSL_DMA_LD_DEBUG
+ chan_dbg(chan, "LD %p free\n", desc);
+#endif
+ dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
+}
+
+/**
* fsl_dma_alloc_descriptor - Allocate descriptor from channel's DMA pool.
* @chan : Freescale DMA channel
*
@@ -457,6 +473,217 @@ static struct fsl_desc_sw *fsl_dma_alloc_descriptor(struct fsldma_chan *chan)
}
/**
+ * fsldma_clean_completed_descriptor - free all descriptors which
+ * has been completed and acked
+ * @chan: Freescale DMA channel
+ *
+ * This function is used on all completed and acked descriptors.
+ * All descriptors should only be freed in this function.
+ */
+static void
+fsldma_clean_completed_descriptor(struct fsldma_chan *chan)
+{
+ struct fsl_desc_sw *desc, *_desc;
+
+ /* Run the callback for each descriptor, in order */
+ list_for_each_entry_safe(desc, _desc, &chan->ld_completed, node)
+ if (async_tx_test_ack(&desc->async_tx))
+ fsl_dma_free_descriptor(chan, desc);
+}
+
+/**
+ * fsldma_run_tx_complete_actions - cleanup a single link descriptor
+ * @chan: Freescale DMA channel
+ * @desc: descriptor to cleanup and free
+ * @cookie: Freescale DMA transaction identifier
+ *
+ * This function is used on a descriptor which has been executed by the DMA
+ * controller. It will run any callbacks, submit any dependencies.
+ */
+static dma_cookie_t fsldma_run_tx_complete_actions(struct fsldma_chan *chan,
+ struct fsl_desc_sw *desc, dma_cookie_t cookie)
+{
+ struct dma_async_tx_descriptor *txd = &desc->async_tx;
+ struct device *dev = chan->common.device->dev;
+ dma_addr_t src = get_desc_src(chan, desc);
+ dma_addr_t dst = get_desc_dst(chan, desc);
+ u32 len = get_desc_cnt(chan, desc);
+
+ BUG_ON(txd->cookie < 0);
+
+ if (txd->cookie > 0) {
+ cookie = txd->cookie;
+
+ /* Run the link descriptor callback function */
+ if (txd->callback) {
+#ifdef FSL_DMA_LD_DEBUG
+ chan_dbg(chan, "LD %p callback\n", desc);
+#endif
+ txd->callback(txd->callback_param);
+ }
+ }
+
+ /* Run any dependencies */
+ dma_run_dependencies(txd);
+
+ return cookie;
+}
+
+/**
+ * fsldma_clean_running_descriptor - move the completed descriptor from
+ * ld_running to ld_completed
+ * @chan: Freescale DMA channel
+ * @desc: the descriptor which is completed
+ *
+ * Free the descriptor directly if acked by async_tx api, or move it to
+ * queue ld_completed.
+ */
+static void
+fsldma_clean_running_descriptor(struct fsldma_chan *chan,
+ struct fsl_desc_sw *desc)
+{
+ /* Remove from the list of transactions */
+ list_del(&desc->node);
+
+ /*
+ * the client is allowed to attach dependent operations
+ * until 'ack' is set
+ */
+ if (!async_tx_test_ack(&desc->async_tx)) {
+ /*
+ * Move this descriptor to the list of descriptors which is
+ * completed, but still awaiting the 'ack' bit to be set.
+ */
+ list_add_tail(&desc->node, &chan->ld_completed);
+ return;
+ }
+
+ dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
+}
+
+/**
+ * fsl_chan_xfer_ld_queue - transfer any pending transactions
+ * @chan : Freescale DMA channel
+ *
+ * HARDWARE STATE: idle
+ * LOCKING: must hold chan->desc_lock
+ */
+static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
+{
+ struct fsl_desc_sw *desc;
+
+ /*
+ * If the list of pending descriptors is empty, then we
+ * don't need to do any work at all
+ */
+ if (list_empty(&chan->ld_pending)) {
+ chan_dbg(chan, "no pending LDs\n");
+ return;
+ }
+
+ /*
+ * The DMA controller is not idle, which means that the interrupt
+ * handler will start any queued transactions when it runs after
+ * this transaction finishes
+ */
+ if (!chan->idle) {
+ chan_dbg(chan, "DMA controller still busy\n");
+ return;
+ }
+
+ /*
+ * If there are some link descriptors which have not been
+ * transferred, we need to start the controller
+ */
+
+ /*
+ * Move all elements from the queue of pending transactions
+ * onto the list of running transactions
+ */
+ chan_dbg(chan, "idle, starting controller\n");
+ desc = list_first_entry(&chan->ld_pending, struct fsl_desc_sw, node);
+ list_splice_tail_init(&chan->ld_pending, &chan->ld_running);
+
+ /*
+ * The 85xx DMA controller doesn't clear the channel start bit
+ * automatically at the end of a transfer. Therefore we must clear
+ * it in software before starting the transfer.
+ */
+ if ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
+ u32 mode;
+
+ mode = DMA_IN(chan, &chan->regs->mr, 32);
+ mode &= ~FSL_DMA_MR_CS;
+ DMA_OUT(chan, &chan->regs->mr, mode, 32);
+ }
+
+ /*
+ * Program the descriptor's address into the DMA controller,
+ * then start the DMA transaction
+ */
+ set_cdar(chan, desc->async_tx.phys);
+ get_cdar(chan);
+
+ dma_start(chan);
+ chan->idle = false;
+}
+
+/**
+ * fsldma_cleanup_descriptors - cleanup link descriptors which are completed
+ * and move them to ld_completed to free until flag 'ack' is set
+ * @chan: Freescale DMA channel
+ *
+ * This function is used on descriptors which have been executed by the DMA
+ * controller. It will run any callbacks, submit any dependencies, then
+ * free these descriptors if flag 'ack' is set.
+ */
+static void fsldma_cleanup_descriptors(struct fsldma_chan *chan)
+{
+ struct fsl_desc_sw *desc, *_desc;
+ dma_cookie_t cookie = 0;
+ dma_addr_t curr_phys = get_cdar(chan);
+ int seen_current = 0;
+
+ fsldma_clean_completed_descriptor(chan);
+
+ /* Run the callback for each descriptor, in order */
+ list_for_each_entry_safe(desc, _desc, &chan->ld_running, node) {
+ /*
+ * do not advance past the current descriptor loaded into the
+ * hardware channel, subsequent descriptors are either in
+ * process or have not been submitted
+ */
+ if (seen_current)
+ break;
+
+ /*
+ * stop the search if we reach the current descriptor and the
+ * channel is busy
+ */
+ if (desc->async_tx.phys == curr_phys) {
+ seen_current = 1;
+ if (!dma_is_idle(chan))
+ break;
+ }
+
+ cookie = fsldma_run_tx_complete_actions(chan, desc, cookie);
+
+ fsldma_clean_running_descriptor(chan, desc);
+ }
+
+ /*
+ * Start any pending transactions automatically
+ *
+ * In the ideal case, we keep the DMA controller busy while we go
+ * ahead and free the descriptors below.
+ */
+ fsl_chan_xfer_ld_queue(chan);
+
+ if (cookie > 0)
+ chan->common.completed_cookie = cookie;
+}
+
+/**
* fsl_dma_alloc_chan_resources - Allocate resources for DMA channel.
* @chan : Freescale DMA channel
*
@@ -500,13 +727,8 @@ static void fsldma_free_desc_list(struct fsldma_chan *chan,
{
struct fsl_desc_sw *desc, *_desc;
- list_for_each_entry_safe(desc, _desc, list, node) {
- list_del(&desc->node);
-#ifdef FSL_DMA_LD_DEBUG
- chan_dbg(chan, "LD %p free\n", desc);
-#endif
- dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
- }
+ list_for_each_entry_safe(desc, _desc, list, node)
+ fsl_dma_free_descriptor(chan, desc);
}
static void fsldma_free_desc_list_reverse(struct fsldma_chan *chan,
@@ -514,13 +736,8 @@ static void fsldma_free_desc_list_reverse(struct fsldma_chan *chan,
{
struct fsl_desc_sw *desc, *_desc;
- list_for_each_entry_safe_reverse(desc, _desc, list, node) {
- list_del(&desc->node);
-#ifdef FSL_DMA_LD_DEBUG
- chan_dbg(chan, "LD %p free\n", desc);
-#endif
- dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
- }
+ list_for_each_entry_safe_reverse(desc, _desc, list, node)
+ fsl_dma_free_descriptor(chan, desc);
}
/**
@@ -530,48 +747,20 @@ static void fsldma_free_desc_list_reverse(struct fsldma_chan *chan,
static void fsl_dma_free_chan_resources(struct dma_chan *dchan)
{
struct fsldma_chan *chan = to_fsl_chan(dchan);
- unsigned long flags;
chan_dbg(chan, "free all channel resources\n");
- spin_lock_irqsave(&chan->desc_lock, flags);
+ spin_lock_bh(&chan->desc_lock);
+ fsldma_cleanup_descriptors(chan);
fsldma_free_desc_list(chan, &chan->ld_pending);
fsldma_free_desc_list(chan, &chan->ld_running);
- spin_unlock_irqrestore(&chan->desc_lock, flags);
+ fsldma_free_desc_list(chan, &chan->ld_completed);
+ spin_unlock_bh(&chan->desc_lock);
dma_pool_destroy(chan->desc_pool);
chan->desc_pool = NULL;
}
static struct dma_async_tx_descriptor *
-fsl_dma_prep_interrupt(struct dma_chan *dchan, unsigned long flags)
-{
- struct fsldma_chan *chan;
- struct fsl_desc_sw *new;
-
- if (!dchan)
- return NULL;
-
- chan = to_fsl_chan(dchan);
-
- new = fsl_dma_alloc_descriptor(chan);
- if (!new) {
- chan_err(chan, "%s\n", msg_ld_oom);
- return NULL;
- }
-
- new->async_tx.cookie = -EBUSY;
- new->async_tx.flags = flags;
-
- /* Insert the link descriptor to the LD ring */
- list_add_tail(&new->node, &new->tx_list);
-
- /* Set End-of-link to the last link descriptor of new list */
- set_ld_eol(chan, new);
-
- return &new->async_tx;
-}
-
-static struct dma_async_tx_descriptor *
fsl_dma_prep_memcpy(struct dma_chan *dchan,
dma_addr_t dma_dst, dma_addr_t dma_src,
size_t len, unsigned long flags)
@@ -784,7 +973,6 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
{
struct dma_slave_config *config;
struct fsldma_chan *chan;
- unsigned long flags;
int size;
if (!dchan)
@@ -794,7 +982,7 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
switch (cmd) {
case DMA_TERMINATE_ALL:
- spin_lock_irqsave(&chan->desc_lock, flags);
+ spin_lock_bh(&chan->desc_lock);
/* Halt the DMA engine */
dma_halt(chan);
@@ -802,9 +990,10 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
/* Remove and free all of the descriptors in the LD queue */
fsldma_free_desc_list(chan, &chan->ld_pending);
fsldma_free_desc_list(chan, &chan->ld_running);
+ fsldma_free_desc_list(chan, &chan->ld_completed);
chan->idle = true;
- spin_unlock_irqrestore(&chan->desc_lock, flags);
+ spin_unlock_bh(&chan->desc_lock);
return 0;
case DMA_SLAVE_CONFIG:
@@ -840,135 +1029,16 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
}
/**
- * fsldma_cleanup_descriptor - cleanup and free a single link descriptor
- * @chan: Freescale DMA channel
- * @desc: descriptor to cleanup and free
- *
- * This function is used on a descriptor which has been executed by the DMA
- * controller. It will run any callbacks, submit any dependencies, and then
- * free the descriptor.
- */
-static void fsldma_cleanup_descriptor(struct fsldma_chan *chan,
- struct fsl_desc_sw *desc)
-{
- struct dma_async_tx_descriptor *txd = &desc->async_tx;
- struct device *dev = chan->common.device->dev;
- dma_addr_t src = get_desc_src(chan, desc);
- dma_addr_t dst = get_desc_dst(chan, desc);
- u32 len = get_desc_cnt(chan, desc);
-
- /* Run the link descriptor callback function */
- if (txd->callback) {
-#ifdef FSL_DMA_LD_DEBUG
- chan_dbg(chan, "LD %p callback\n", desc);
-#endif
- txd->callback(txd->callback_param);
- }
-
- /* Run any dependencies */
- dma_run_dependencies(txd);
-
- /* Unmap the dst buffer, if requested */
- if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
- if (txd->flags & DMA_COMPL_DEST_UNMAP_SINGLE)
- dma_unmap_single(dev, dst, len, DMA_FROM_DEVICE);
- else
- dma_unmap_page(dev, dst, len, DMA_FROM_DEVICE);
- }
-
- /* Unmap the src buffer, if requested */
- if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
- if (txd->flags & DMA_COMPL_SRC_UNMAP_SINGLE)
- dma_unmap_single(dev, src, len, DMA_TO_DEVICE);
- else
- dma_unmap_page(dev, src, len, DMA_TO_DEVICE);
- }
-
-#ifdef FSL_DMA_LD_DEBUG
- chan_dbg(chan, "LD %p free\n", desc);
-#endif
- dma_pool_free(chan->desc_pool, desc, txd->phys);
-}
-
-/**
- * fsl_chan_xfer_ld_queue - transfer any pending transactions
- * @chan : Freescale DMA channel
- *
- * HARDWARE STATE: idle
- * LOCKING: must hold chan->desc_lock
- */
-static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
-{
- struct fsl_desc_sw *desc;
-
- /*
- * If the list of pending descriptors is empty, then we
- * don't need to do any work at all
- */
- if (list_empty(&chan->ld_pending)) {
- chan_dbg(chan, "no pending LDs\n");
- return;
- }
-
- /*
- * The DMA controller is not idle, which means that the interrupt
- * handler will start any queued transactions when it runs after
- * this transaction finishes
- */
- if (!chan->idle) {
- chan_dbg(chan, "DMA controller still busy\n");
- return;
- }
-
- /*
- * If there are some link descriptors which have not been
- * transferred, we need to start the controller
- */
-
- /*
- * Move all elements from the queue of pending transactions
- * onto the list of running transactions
- */
- chan_dbg(chan, "idle, starting controller\n");
- desc = list_first_entry(&chan->ld_pending, struct fsl_desc_sw, node);
- list_splice_tail_init(&chan->ld_pending, &chan->ld_running);
-
- /*
- * The 85xx DMA controller doesn't clear the channel start bit
- * automatically at the end of a transfer. Therefore we must clear
- * it in software before starting the transfer.
- */
- if ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
- u32 mode;
-
- mode = DMA_IN(chan, &chan->regs->mr, 32);
- mode &= ~FSL_DMA_MR_CS;
- DMA_OUT(chan, &chan->regs->mr, mode, 32);
- }
-
- /*
- * Program the descriptor's address into the DMA controller,
- * then start the DMA transaction
- */
- set_cdar(chan, desc->async_tx.phys);
- get_cdar(chan);
-
- dma_start(chan);
- chan->idle = false;
-}
-
-/**
* fsl_dma_memcpy_issue_pending - Issue the DMA start command
* @chan : Freescale DMA channel
*/
static void fsl_dma_memcpy_issue_pending(struct dma_chan *dchan)
{
struct fsldma_chan *chan = to_fsl_chan(dchan);
- unsigned long flags;
- spin_lock_irqsave(&chan->desc_lock, flags);
+ spin_lock_bh(&chan->desc_lock);
fsl_chan_xfer_ld_queue(chan);
- spin_unlock_irqrestore(&chan->desc_lock, flags);
+ spin_unlock_bh(&chan->desc_lock);
}
/**
@@ -979,6 +1049,17 @@ static enum dma_status fsl_tx_status(struct dma_chan *dchan,
dma_cookie_t cookie,
struct dma_tx_state *txstate)
{
+ struct fsldma_chan *chan = to_fsl_chan(dchan);
+ enum dma_status ret;
+
+ ret = dma_cookie_status(dchan, cookie, txstate);
+ if (ret == DMA_COMPLETE)
+ return ret;
+
+ spin_lock_bh(&chan->desc_lock);
+ fsldma_cleanup_descriptors(chan);
+ spin_unlock_bh(&chan->desc_lock);
+
return dma_cookie_status(dchan, cookie, txstate);
}
@@ -1056,52 +1137,18 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
static void dma_do_tasklet(unsigned long data)
{
struct fsldma_chan *chan = (struct fsldma_chan *)data;
- struct fsl_desc_sw *desc, *_desc;
- LIST_HEAD(ld_cleanup);
- unsigned long flags;
chan_dbg(chan, "tasklet entry\n");
- spin_lock_irqsave(&chan->desc_lock, flags);
-
- /* update the cookie if we have some descriptors to cleanup */
- if (!list_empty(&chan->ld_running)) {
- dma_cookie_t cookie;
-
- desc = to_fsl_desc(chan->ld_running.prev);
- cookie = desc->async_tx.cookie;
- dma_cookie_complete(&desc->async_tx);
-
- chan_dbg(chan, "completed_cookie=%d\n", cookie);
- }
-
- /*
- * move the descriptors to a temporary list so we can drop the lock
- * during the entire cleanup operation
- */
- list_splice_tail_init(&chan->ld_running, &ld_cleanup);
+ spin_lock_bh(&chan->desc_lock);
/* the hardware is now idle and ready for more */
chan->idle = true;
- /*
- * Start any pending transactions automatically
- *
- * In the ideal case, we keep the DMA controller busy while we go
- * ahead and free the descriptors below.
- */
- fsl_chan_xfer_ld_queue(chan);
- spin_unlock_irqrestore(&chan->desc_lock, flags);
-
- /* Run the callback for each descriptor, in order */
- list_for_each_entry_safe(desc, _desc, &ld_cleanup, node) {
-
- /* Remove from the list of transactions */
- list_del(&desc->node);
+ /* Run all cleanup for descriptors which have been completed */
+ fsldma_cleanup_descriptors(chan);
- /* Run all cleanup for this descriptor */
- fsldma_cleanup_descriptor(chan, desc);
- }
+ spin_unlock_bh(&chan->desc_lock);
chan_dbg(chan, "tasklet exit\n");
}
@@ -1253,7 +1300,9 @@ static int fsl_dma_chan_probe(struct fsldma_device *fdev,
WARN_ON(fdev->feature != chan->feature);
chan->dev = fdev->dev;
- chan->id = ((res.start - 0x100) & 0xfff) >> 7;
+ chan->id = (res.start & 0xfff) < 0x300 ?
+ ((res.start - 0x100) & 0xfff) >> 7 :
+ ((res.start - 0x200) & 0xfff) >> 7;
if (chan->id >= FSL_DMA_MAX_CHANS_PER_DEVICE) {
dev_err(fdev->dev, "too many channels for device\n");
err = -EINVAL;
@@ -1283,6 +1332,7 @@ static int fsl_dma_chan_probe(struct fsldma_device *fdev,
spin_lock_init(&chan->desc_lock);
INIT_LIST_HEAD(&chan->ld_pending);
INIT_LIST_HEAD(&chan->ld_running);
+ INIT_LIST_HEAD(&chan->ld_completed);
chan->idle = true;
chan->common.device = &fdev->common;
@@ -1344,12 +1394,10 @@ static int fsldma_of_probe(struct platform_device *op)
fdev->irq = irq_of_parse_and_map(op->dev.of_node, 0);
dma_cap_set(DMA_MEMCPY, fdev->common.cap_mask);
- dma_cap_set(DMA_INTERRUPT, fdev->common.cap_mask);
dma_cap_set(DMA_SG, fdev->common.cap_mask);
dma_cap_set(DMA_SLAVE, fdev->common.cap_mask);
fdev->common.device_alloc_chan_resources = fsl_dma_alloc_chan_resources;
fdev->common.device_free_chan_resources = fsl_dma_free_chan_resources;
- fdev->common.device_prep_dma_interrupt = fsl_dma_prep_interrupt;
fdev->common.device_prep_dma_memcpy = fsl_dma_prep_memcpy;
fdev->common.device_prep_dma_sg = fsl_dma_prep_sg;
fdev->common.device_tx_status = fsl_tx_status;
@@ -1426,6 +1474,7 @@ static int fsldma_of_remove(struct platform_device *op)
}
static const struct of_device_id fsldma_of_ids[] = {
+ { .compatible = "fsl,elo3-dma", },
{ .compatible = "fsl,eloplus-dma", },
{ .compatible = "fsl,elo-dma", },
{}
@@ -1447,7 +1496,7 @@ static struct platform_driver fsldma_of_driver = {
static __init int fsldma_init(void)
{
- pr_info("Freescale Elo / Elo Plus DMA driver\n");
+ pr_info("Freescale Elo series DMA driver\n");
return platform_driver_register(&fsldma_of_driver);
}
@@ -1459,5 +1508,5 @@ static void __exit fsldma_exit(void)
subsys_initcall(fsldma_init);
module_exit(fsldma_exit);
-MODULE_DESCRIPTION("Freescale Elo / Elo Plus DMA driver");
+MODULE_DESCRIPTION("Freescale Elo series DMA driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
index f5c3879..ec19517 100644
--- a/drivers/dma/fsldma.h
+++ b/drivers/dma/fsldma.h
@@ -41,7 +41,7 @@
* channel is allowed to transfer before the DMA engine pauses
* the current channel and switches to the next channel
*/
-#define FSL_DMA_MR_BWC 0x08000000
+#define FSL_DMA_MR_BWC 0x0A000000
/* Special MR definition for MPC8349 */
#define FSL_DMA_MR_EOTIE 0x00000080
@@ -112,7 +112,7 @@ struct fsldma_chan_regs {
};
struct fsldma_chan;
-#define FSL_DMA_MAX_CHANS_PER_DEVICE 4
+#define FSL_DMA_MAX_CHANS_PER_DEVICE 8
struct fsldma_device {
void __iomem *regs; /* DGSR register base */
@@ -138,8 +138,21 @@ struct fsldma_chan {
char name[8]; /* Channel name */
struct fsldma_chan_regs __iomem *regs;
spinlock_t desc_lock; /* Descriptor operation lock */
- struct list_head ld_pending; /* Link descriptors queue */
- struct list_head ld_running; /* Link descriptors queue */
+ /*
+ * Descriptors which are queued to run, but have not yet been
+ * submitted to the hardware for execution
+ */
+ struct list_head ld_pending;
+ /*
+ * Descriptors which are currently being executed by the hardware
+ */
+ struct list_head ld_running;
+ /*
+ * Descriptors which have finished execution by the hardware. These
+ * descriptors have already had their cleanup actions run. They are
+ * waiting for the ACK bit to be set by the async_tx API.
+ */
+ struct list_head ld_completed; /* Link descriptors queue */
struct dma_chan common; /* DMA common channel */
struct dma_pool *desc_pool; /* Descriptors pool */
struct device *dev; /* Channel device */
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index 55852c0..6f9ac20 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -572,9 +572,11 @@ static int imxdma_xfer_desc(struct imxdma_desc *d)
imx_dmav1_writel(imxdma, d->len, DMA_CNTR(imxdmac->channel));
- dev_dbg(imxdma->dev, "%s channel: %d dest=0x%08x src=0x%08x "
- "dma_length=%d\n", __func__, imxdmac->channel,
- d->dest, d->src, d->len);
+ dev_dbg(imxdma->dev,
+ "%s channel: %d dest=0x%08llx src=0x%08llx dma_length=%zu\n",
+ __func__, imxdmac->channel,
+ (unsigned long long)d->dest,
+ (unsigned long long)d->src, d->len);
break;
/* Cyclic transfer is the same as slave_sg with special sg configuration. */
@@ -586,20 +588,22 @@ static int imxdma_xfer_desc(struct imxdma_desc *d)
imx_dmav1_writel(imxdma, imxdmac->ccr_from_device,
DMA_CCR(imxdmac->channel));
- dev_dbg(imxdma->dev, "%s channel: %d sg=%p sgcount=%d "
- "total length=%d dev_addr=0x%08x (dev2mem)\n",
- __func__, imxdmac->channel, d->sg, d->sgcount,
- d->len, imxdmac->per_address);
+ dev_dbg(imxdma->dev,
+ "%s channel: %d sg=%p sgcount=%d total length=%zu dev_addr=0x%08llx (dev2mem)\n",
+ __func__, imxdmac->channel,
+ d->sg, d->sgcount, d->len,
+ (unsigned long long)imxdmac->per_address);
} else if (d->direction == DMA_MEM_TO_DEV) {
imx_dmav1_writel(imxdma, imxdmac->per_address,
DMA_DAR(imxdmac->channel));
imx_dmav1_writel(imxdma, imxdmac->ccr_to_device,
DMA_CCR(imxdmac->channel));
- dev_dbg(imxdma->dev, "%s channel: %d sg=%p sgcount=%d "
- "total length=%d dev_addr=0x%08x (mem2dev)\n",
- __func__, imxdmac->channel, d->sg, d->sgcount,
- d->len, imxdmac->per_address);
+ dev_dbg(imxdma->dev,
+ "%s channel: %d sg=%p sgcount=%d total length=%zu dev_addr=0x%08llx (mem2dev)\n",
+ __func__, imxdmac->channel,
+ d->sg, d->sgcount, d->len,
+ (unsigned long long)imxdmac->per_address);
} else {
dev_err(imxdma->dev, "%s channel: %d bad dma mode\n",
__func__, imxdmac->channel);
@@ -771,7 +775,7 @@ static int imxdma_alloc_chan_resources(struct dma_chan *chan)
desc->desc.tx_submit = imxdma_tx_submit;
/* txd.flags will be overwritten in prep funcs */
desc->desc.flags = DMA_CTRL_ACK;
- desc->status = DMA_SUCCESS;
+ desc->status = DMA_COMPLETE;
list_add_tail(&desc->node, &imxdmac->ld_free);
imxdmac->descs_allocated++;
@@ -870,7 +874,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic(
int i;
unsigned int periods = buf_len / period_len;
- dev_dbg(imxdma->dev, "%s channel: %d buf_len=%d period_len=%d\n",
+ dev_dbg(imxdma->dev, "%s channel: %d buf_len=%zu period_len=%zu\n",
__func__, imxdmac->channel, buf_len, period_len);
if (list_empty(&imxdmac->ld_free) ||
@@ -926,8 +930,9 @@ static struct dma_async_tx_descriptor *imxdma_prep_dma_memcpy(
struct imxdma_engine *imxdma = imxdmac->imxdma;
struct imxdma_desc *desc;
- dev_dbg(imxdma->dev, "%s channel: %d src=0x%x dst=0x%x len=%d\n",
- __func__, imxdmac->channel, src, dest, len);
+ dev_dbg(imxdma->dev, "%s channel: %d src=0x%llx dst=0x%llx len=%zu\n",
+ __func__, imxdmac->channel, (unsigned long long)src,
+ (unsigned long long)dest, len);
if (list_empty(&imxdmac->ld_free) ||
imxdma_chan_is_doing_cyclic(imxdmac))
@@ -956,9 +961,10 @@ static struct dma_async_tx_descriptor *imxdma_prep_dma_interleaved(
struct imxdma_engine *imxdma = imxdmac->imxdma;
struct imxdma_desc *desc;
- dev_dbg(imxdma->dev, "%s channel: %d src_start=0x%x dst_start=0x%x\n"
- " src_sgl=%s dst_sgl=%s numf=%d frame_size=%d\n", __func__,
- imxdmac->channel, xt->src_start, xt->dst_start,
+ dev_dbg(imxdma->dev, "%s channel: %d src_start=0x%llx dst_start=0x%llx\n"
+ " src_sgl=%s dst_sgl=%s numf=%zu frame_size=%zu\n", __func__,
+ imxdmac->channel, (unsigned long long)xt->src_start,
+ (unsigned long long) xt->dst_start,
xt->src_sgl ? "true" : "false", xt->dst_sgl ? "true" : "false",
xt->numf, xt->frame_size);
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index fc43603..c75679d 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -638,7 +638,7 @@ static void mxc_sdma_handle_channel_normal(struct sdma_channel *sdmac)
if (error)
sdmac->status = DMA_ERROR;
else
- sdmac->status = DMA_SUCCESS;
+ sdmac->status = DMA_COMPLETE;
dma_cookie_complete(&sdmac->desc);
if (sdmac->desc.callback)
@@ -1089,8 +1089,8 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
param &= ~BD_CONT;
}
- dev_dbg(sdma->dev, "entry %d: count: %d dma: 0x%08x %s%s\n",
- i, count, sg->dma_address,
+ dev_dbg(sdma->dev, "entry %d: count: %d dma: %#llx %s%s\n",
+ i, count, (u64)sg->dma_address,
param & BD_WRAP ? "wrap" : "",
param & BD_INTR ? " intr" : "");
@@ -1163,8 +1163,8 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
if (i + 1 == num_periods)
param |= BD_WRAP;
- dev_dbg(sdma->dev, "entry %d: count: %d dma: 0x%08x %s%s\n",
- i, period_len, dma_addr,
+ dev_dbg(sdma->dev, "entry %d: count: %d dma: %#llx %s%s\n",
+ i, period_len, (u64)dma_addr,
param & BD_WRAP ? "wrap" : "",
param & BD_INTR ? " intr" : "");
@@ -1432,6 +1432,10 @@ static int __init sdma_probe(struct platform_device *pdev)
return -EINVAL;
}
+ ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (ret)
+ return ret;
+
sdma = kzalloc(sizeof(*sdma), GFP_KERNEL);
if (!sdma)
return -ENOMEM;
diff --git a/drivers/dma/intel_mid_dma.c b/drivers/dma/intel_mid_dma.c
index a975ebe..1aab813 100644
--- a/drivers/dma/intel_mid_dma.c
+++ b/drivers/dma/intel_mid_dma.c
@@ -309,7 +309,7 @@ static void midc_descriptor_complete(struct intel_mid_dma_chan *midc,
callback_txd(param_txd);
}
if (midc->raw_tfr) {
- desc->status = DMA_SUCCESS;
+ desc->status = DMA_COMPLETE;
if (desc->lli != NULL) {
pci_pool_free(desc->lli_pool, desc->lli,
desc->lli_phys);
@@ -481,7 +481,7 @@ static enum dma_status intel_mid_dma_tx_status(struct dma_chan *chan,
enum dma_status ret;
ret = dma_cookie_status(chan, cookie, txstate);
- if (ret != DMA_SUCCESS) {
+ if (ret != DMA_COMPLETE) {
spin_lock_bh(&midc->lock);
midc_scan_descriptors(to_middma_device(chan->device), midc);
spin_unlock_bh(&midc->lock);
diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c
index a6d1177..8383f2b 100644
--- a/drivers/dma/ioat/dma.c
+++ b/drivers/dma/ioat/dma.c
@@ -569,21 +569,6 @@ static void ioat1_cleanup_event(unsigned long data)
writew(IOAT_CHANCTRL_RUN, ioat->base.reg_base + IOAT_CHANCTRL_OFFSET);
}
-void ioat_dma_unmap(struct ioat_chan_common *chan, enum dma_ctrl_flags flags,
- size_t len, struct ioat_dma_descriptor *hw)
-{
- struct pci_dev *pdev = chan->device->pdev;
- size_t offset = len - hw->size;
-
- if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP))
- ioat_unmap(pdev, hw->dst_addr - offset, len,
- PCI_DMA_FROMDEVICE, flags, 1);
-
- if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP))
- ioat_unmap(pdev, hw->src_addr - offset, len,
- PCI_DMA_TODEVICE, flags, 0);
-}
-
dma_addr_t ioat_get_current_completion(struct ioat_chan_common *chan)
{
dma_addr_t phys_complete;
@@ -640,7 +625,7 @@ static void __cleanup(struct ioat_dma_chan *ioat, dma_addr_t phys_complete)
dump_desc_dbg(ioat, desc);
if (tx->cookie) {
dma_cookie_complete(tx);
- ioat_dma_unmap(chan, tx->flags, desc->len, desc->hw);
+ dma_descriptor_unmap(tx);
ioat->active -= desc->hw->tx_cnt;
if (tx->callback) {
tx->callback(tx->callback_param);
@@ -771,7 +756,7 @@ ioat_dma_tx_status(struct dma_chan *c, dma_cookie_t cookie,
enum dma_status ret;
ret = dma_cookie_status(c, cookie, txstate);
- if (ret == DMA_SUCCESS)
+ if (ret == DMA_COMPLETE)
return ret;
device->cleanup_fn((unsigned long) c);
@@ -871,8 +856,7 @@ int ioat_dma_self_test(struct ioatdma_device *device)
dma_src = dma_map_single(dev, src, IOAT_TEST_SIZE, DMA_TO_DEVICE);
dma_dest = dma_map_single(dev, dest, IOAT_TEST_SIZE, DMA_FROM_DEVICE);
- flags = DMA_COMPL_SKIP_SRC_UNMAP | DMA_COMPL_SKIP_DEST_UNMAP |
- DMA_PREP_INTERRUPT;
+ flags = DMA_PREP_INTERRUPT;
tx = device->common.device_prep_dma_memcpy(dma_chan, dma_dest, dma_src,
IOAT_TEST_SIZE, flags);
if (!tx) {
@@ -897,7 +881,7 @@ int ioat_dma_self_test(struct ioatdma_device *device)
if (tmo == 0 ||
dma->device_tx_status(dma_chan, cookie, NULL)
- != DMA_SUCCESS) {
+ != DMA_COMPLETE) {
dev_err(dev, "Self-test copy timed out, disabling\n");
err = -ENODEV;
goto unmap_dma;
@@ -923,8 +907,7 @@ static char ioat_interrupt_style[32] = "msix";
module_param_string(ioat_interrupt_style, ioat_interrupt_style,
sizeof(ioat_interrupt_style), 0644);
MODULE_PARM_DESC(ioat_interrupt_style,
- "set ioat interrupt style: msix (default), "
- "msix-single-vector, msi, intx)");
+ "set ioat interrupt style: msix (default), msi, intx");
/**
* ioat_dma_setup_interrupts - setup interrupt handler
@@ -942,8 +925,6 @@ int ioat_dma_setup_interrupts(struct ioatdma_device *device)
if (!strcmp(ioat_interrupt_style, "msix"))
goto msix;
- if (!strcmp(ioat_interrupt_style, "msix-single-vector"))
- goto msix_single_vector;
if (!strcmp(ioat_interrupt_style, "msi"))
goto msi;
if (!strcmp(ioat_interrupt_style, "intx"))
@@ -958,10 +939,8 @@ msix:
device->msix_entries[i].entry = i;
err = pci_enable_msix(pdev, device->msix_entries, msixcnt);
- if (err < 0)
+ if (err)
goto msi;
- if (err > 0)
- goto msix_single_vector;
for (i = 0; i < msixcnt; i++) {
msix = &device->msix_entries[i];
@@ -975,29 +954,13 @@ msix:
chan = ioat_chan_by_index(device, j);
devm_free_irq(dev, msix->vector, chan);
}
- goto msix_single_vector;
+ goto msi;
}
}
intrctrl |= IOAT_INTRCTRL_MSIX_VECTOR_CONTROL;
device->irq_mode = IOAT_MSIX;
goto done;
-msix_single_vector:
- msix = &device->msix_entries[0];
- msix->entry = 0;
- err = pci_enable_msix(pdev, device->msix_entries, 1);
- if (err)
- goto msi;
-
- err = devm_request_irq(dev, msix->vector, ioat_dma_do_interrupt, 0,
- "ioat-msix", device);
- if (err) {
- pci_disable_msix(pdev);
- goto msi;
- }
- device->irq_mode = IOAT_MSIX_SINGLE;
- goto done;
-
msi:
err = pci_enable_msi(pdev);
if (err)
@@ -1009,7 +972,7 @@ msi:
pci_disable_msi(pdev);
goto intx;
}
- device->irq_mode = IOAT_MSIX;
+ device->irq_mode = IOAT_MSI;
goto done;
intx:
diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h
index a1d7884..e982f00 100644
--- a/drivers/dma/ioat/dma.h
+++ b/drivers/dma/ioat/dma.h
@@ -52,7 +52,6 @@
enum ioat_irq_mode {
IOAT_NOIRQ = 0,
IOAT_MSIX,
- IOAT_MSIX_SINGLE,
IOAT_MSI,
IOAT_INTX
};
@@ -83,7 +82,6 @@ struct ioatdma_device {
struct pci_pool *completion_pool;
#define MAX_SED_POOLS 5
struct dma_pool *sed_hw_pool[MAX_SED_POOLS];
- struct kmem_cache *sed_pool;
struct dma_device common;
u8 version;
struct msix_entry msix_entries[4];
@@ -342,16 +340,6 @@ static inline bool is_ioat_bug(unsigned long err)
return !!err;
}
-static inline void ioat_unmap(struct pci_dev *pdev, dma_addr_t addr, size_t len,
- int direction, enum dma_ctrl_flags flags, bool dst)
-{
- if ((dst && (flags & DMA_COMPL_DEST_UNMAP_SINGLE)) ||
- (!dst && (flags & DMA_COMPL_SRC_UNMAP_SINGLE)))
- pci_unmap_single(pdev, addr, len, direction);
- else
- pci_unmap_page(pdev, addr, len, direction);
-}
-
int ioat_probe(struct ioatdma_device *device);
int ioat_register(struct ioatdma_device *device);
int ioat1_dma_probe(struct ioatdma_device *dev, int dca);
@@ -363,8 +351,6 @@ void ioat_init_channel(struct ioatdma_device *device,
struct ioat_chan_common *chan, int idx);
enum dma_status ioat_dma_tx_status(struct dma_chan *c, dma_cookie_t cookie,
struct dma_tx_state *txstate);
-void ioat_dma_unmap(struct ioat_chan_common *chan, enum dma_ctrl_flags flags,
- size_t len, struct ioat_dma_descriptor *hw);
bool ioat_cleanup_preamble(struct ioat_chan_common *chan,
dma_addr_t *phys_complete);
void ioat_kobject_add(struct ioatdma_device *device, struct kobj_type *type);
diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c
index 1cd7610..8d10580 100644
--- a/drivers/dma/ioat/dma_v2.c
+++ b/drivers/dma/ioat/dma_v2.c
@@ -148,7 +148,7 @@ static void __cleanup(struct ioat2_dma_chan *ioat, dma_addr_t phys_complete)
tx = &desc->txd;
dump_desc_dbg(ioat, desc);
if (tx->cookie) {
- ioat_dma_unmap(chan, tx->flags, desc->len, desc->hw);
+ dma_descriptor_unmap(tx);
dma_cookie_complete(tx);
if (tx->callback) {
tx->callback(tx->callback_param);
diff --git a/drivers/dma/ioat/dma_v2.h b/drivers/dma/ioat/dma_v2.h
index 212d584..4702927 100644
--- a/drivers/dma/ioat/dma_v2.h
+++ b/drivers/dma/ioat/dma_v2.h
@@ -157,7 +157,6 @@ static inline void ioat2_set_chainaddr(struct ioat2_dma_chan *ioat, u64 addr)
int ioat2_dma_probe(struct ioatdma_device *dev, int dca);
int ioat3_dma_probe(struct ioatdma_device *dev, int dca);
-void ioat3_dma_remove(struct ioatdma_device *dev);
struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase);
struct dca_provider *ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase);
int ioat2_check_space_lock(struct ioat2_dma_chan *ioat, int num_descs);
diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c
index 476017f..b9b38a1 100644
--- a/drivers/dma/ioat/dma_v3.c
+++ b/drivers/dma/ioat/dma_v3.c
@@ -67,6 +67,8 @@
#include "dma.h"
#include "dma_v2.h"
+extern struct kmem_cache *ioat3_sed_cache;
+
/* ioat hardware assumes at least two sources for raid operations */
#define src_cnt_to_sw(x) ((x) + 2)
#define src_cnt_to_hw(x) ((x) - 2)
@@ -89,13 +91,6 @@ static const u8 pq16_idx_to_field[] = { 1, 4, 1, 2, 3, 4, 5, 6, 7,
static void ioat3_eh(struct ioat2_dma_chan *ioat);
-static dma_addr_t xor_get_src(struct ioat_raw_descriptor *descs[2], int idx)
-{
- struct ioat_raw_descriptor *raw = descs[xor_idx_to_desc >> idx & 1];
-
- return raw->field[xor_idx_to_field[idx]];
-}
-
static void xor_set_src(struct ioat_raw_descriptor *descs[2],
dma_addr_t addr, u32 offset, int idx)
{
@@ -259,7 +254,7 @@ ioat3_alloc_sed(struct ioatdma_device *device, unsigned int hw_pool)
struct ioat_sed_ent *sed;
gfp_t flags = __GFP_ZERO | GFP_ATOMIC;
- sed = kmem_cache_alloc(device->sed_pool, flags);
+ sed = kmem_cache_alloc(ioat3_sed_cache, flags);
if (!sed)
return NULL;
@@ -267,7 +262,7 @@ ioat3_alloc_sed(struct ioatdma_device *device, unsigned int hw_pool)
sed->hw = dma_pool_alloc(device->sed_hw_pool[hw_pool],
flags, &sed->dma);
if (!sed->hw) {
- kmem_cache_free(device->sed_pool, sed);
+ kmem_cache_free(ioat3_sed_cache, sed);
return NULL;
}
@@ -280,165 +275,7 @@ static void ioat3_free_sed(struct ioatdma_device *device, struct ioat_sed_ent *s
return;
dma_pool_free(device->sed_hw_pool[sed->hw_pool], sed->hw, sed->dma);
- kmem_cache_free(device->sed_pool, sed);
-}
-
-static void ioat3_dma_unmap(struct ioat2_dma_chan *ioat,
- struct ioat_ring_ent *desc, int idx)
-{
- struct ioat_chan_common *chan = &ioat->base;
- struct pci_dev *pdev = chan->device->pdev;
- size_t len = desc->len;
- size_t offset = len - desc->hw->size;
- struct dma_async_tx_descriptor *tx = &desc->txd;
- enum dma_ctrl_flags flags = tx->flags;
-
- switch (desc->hw->ctl_f.op) {
- case IOAT_OP_COPY:
- if (!desc->hw->ctl_f.null) /* skip 'interrupt' ops */
- ioat_dma_unmap(chan, flags, len, desc->hw);
- break;
- case IOAT_OP_XOR_VAL:
- case IOAT_OP_XOR: {
- struct ioat_xor_descriptor *xor = desc->xor;
- struct ioat_ring_ent *ext;
- struct ioat_xor_ext_descriptor *xor_ex = NULL;
- int src_cnt = src_cnt_to_sw(xor->ctl_f.src_cnt);
- struct ioat_raw_descriptor *descs[2];
- int i;
-
- if (src_cnt > 5) {
- ext = ioat2_get_ring_ent(ioat, idx + 1);
- xor_ex = ext->xor_ex;
- }
-
- if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
- descs[0] = (struct ioat_raw_descriptor *) xor;
- descs[1] = (struct ioat_raw_descriptor *) xor_ex;
- for (i = 0; i < src_cnt; i++) {
- dma_addr_t src = xor_get_src(descs, i);
-
- ioat_unmap(pdev, src - offset, len,
- PCI_DMA_TODEVICE, flags, 0);
- }
-
- /* dest is a source in xor validate operations */
- if (xor->ctl_f.op == IOAT_OP_XOR_VAL) {
- ioat_unmap(pdev, xor->dst_addr - offset, len,
- PCI_DMA_TODEVICE, flags, 1);
- break;
- }
- }
-
- if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP))
- ioat_unmap(pdev, xor->dst_addr - offset, len,
- PCI_DMA_FROMDEVICE, flags, 1);
- break;
- }
- case IOAT_OP_PQ_VAL:
- case IOAT_OP_PQ: {
- struct ioat_pq_descriptor *pq = desc->pq;
- struct ioat_ring_ent *ext;
- struct ioat_pq_ext_descriptor *pq_ex = NULL;
- int src_cnt = src_cnt_to_sw(pq->ctl_f.src_cnt);
- struct ioat_raw_descriptor *descs[2];
- int i;
-
- if (src_cnt > 3) {
- ext = ioat2_get_ring_ent(ioat, idx + 1);
- pq_ex = ext->pq_ex;
- }
-
- /* in the 'continue' case don't unmap the dests as sources */
- if (dmaf_p_disabled_continue(flags))
- src_cnt--;
- else if (dmaf_continue(flags))
- src_cnt -= 3;
-
- if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
- descs[0] = (struct ioat_raw_descriptor *) pq;
- descs[1] = (struct ioat_raw_descriptor *) pq_ex;
- for (i = 0; i < src_cnt; i++) {
- dma_addr_t src = pq_get_src(descs, i);
-
- ioat_unmap(pdev, src - offset, len,
- PCI_DMA_TODEVICE, flags, 0);
- }
-
- /* the dests are sources in pq validate operations */
- if (pq->ctl_f.op == IOAT_OP_XOR_VAL) {
- if (!(flags & DMA_PREP_PQ_DISABLE_P))
- ioat_unmap(pdev, pq->p_addr - offset,
- len, PCI_DMA_TODEVICE, flags, 0);
- if (!(flags & DMA_PREP_PQ_DISABLE_Q))
- ioat_unmap(pdev, pq->q_addr - offset,
- len, PCI_DMA_TODEVICE, flags, 0);
- break;
- }
- }
-
- if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
- if (!(flags & DMA_PREP_PQ_DISABLE_P))
- ioat_unmap(pdev, pq->p_addr - offset, len,
- PCI_DMA_BIDIRECTIONAL, flags, 1);
- if (!(flags & DMA_PREP_PQ_DISABLE_Q))
- ioat_unmap(pdev, pq->q_addr - offset, len,
- PCI_DMA_BIDIRECTIONAL, flags, 1);
- }
- break;
- }
- case IOAT_OP_PQ_16S:
- case IOAT_OP_PQ_VAL_16S: {
- struct ioat_pq_descriptor *pq = desc->pq;
- int src_cnt = src16_cnt_to_sw(pq->ctl_f.src_cnt);
- struct ioat_raw_descriptor *descs[4];
- int i;
-
- /* in the 'continue' case don't unmap the dests as sources */
- if (dmaf_p_disabled_continue(flags))
- src_cnt--;
- else if (dmaf_continue(flags))
- src_cnt -= 3;
-
- if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
- descs[0] = (struct ioat_raw_descriptor *)pq;
- descs[1] = (struct ioat_raw_descriptor *)(desc->sed->hw);
- descs[2] = (struct ioat_raw_descriptor *)(&desc->sed->hw->b[0]);
- for (i = 0; i < src_cnt; i++) {
- dma_addr_t src = pq16_get_src(descs, i);
-
- ioat_unmap(pdev, src - offset, len,
- PCI_DMA_TODEVICE, flags, 0);
- }
-
- /* the dests are sources in pq validate operations */
- if (pq->ctl_f.op == IOAT_OP_XOR_VAL) {
- if (!(flags & DMA_PREP_PQ_DISABLE_P))
- ioat_unmap(pdev, pq->p_addr - offset,
- len, PCI_DMA_TODEVICE,
- flags, 0);
- if (!(flags & DMA_PREP_PQ_DISABLE_Q))
- ioat_unmap(pdev, pq->q_addr - offset,
- len, PCI_DMA_TODEVICE,
- flags, 0);
- break;
- }
- }
-
- if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
- if (!(flags & DMA_PREP_PQ_DISABLE_P))
- ioat_unmap(pdev, pq->p_addr - offset, len,
- PCI_DMA_BIDIRECTIONAL, flags, 1);
- if (!(flags & DMA_PREP_PQ_DISABLE_Q))
- ioat_unmap(pdev, pq->q_addr - offset, len,
- PCI_DMA_BIDIRECTIONAL, flags, 1);
- }
- break;
- }
- default:
- dev_err(&pdev->dev, "%s: unknown op type: %#x\n",
- __func__, desc->hw->ctl_f.op);
- }
+ kmem_cache_free(ioat3_sed_cache, sed);
}
static bool desc_has_ext(struct ioat_ring_ent *desc)
@@ -564,7 +401,7 @@ static void __cleanup(struct ioat2_dma_chan *ioat, dma_addr_t phys_complete)
tx = &desc->txd;
if (tx->cookie) {
dma_cookie_complete(tx);
- ioat3_dma_unmap(ioat, desc, idx + i);
+ dma_descriptor_unmap(tx);
if (tx->callback) {
tx->callback(tx->callback_param);
tx->callback = NULL;
@@ -797,7 +634,7 @@ ioat3_tx_status(struct dma_chan *c, dma_cookie_t cookie,
enum dma_status ret;
ret = dma_cookie_status(c, cookie, txstate);
- if (ret == DMA_SUCCESS)
+ if (ret == DMA_COMPLETE)
return ret;
ioat3_cleanup(ioat);
@@ -1433,9 +1270,7 @@ static int ioat_xor_val_self_test(struct ioatdma_device *device)
DMA_TO_DEVICE);
tx = dma->device_prep_dma_xor(dma_chan, dest_dma, dma_srcs,
IOAT_NUM_SRC_TEST, PAGE_SIZE,
- DMA_PREP_INTERRUPT |
- DMA_COMPL_SKIP_SRC_UNMAP |
- DMA_COMPL_SKIP_DEST_UNMAP);
+ DMA_PREP_INTERRUPT);
if (!tx) {
dev_err(dev, "Self-test xor prep failed\n");
@@ -1457,7 +1292,7 @@ static int ioat_xor_val_self_test(struct ioatdma_device *device)
tmo = wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000));
- if (dma->device_tx_status(dma_chan, cookie, NULL) != DMA_SUCCESS) {
+ if (dma->device_tx_status(dma_chan, cookie, NULL) != DMA_COMPLETE) {
dev_err(dev, "Self-test xor timed out\n");
err = -ENODEV;
goto dma_unmap;
@@ -1496,9 +1331,7 @@ static int ioat_xor_val_self_test(struct ioatdma_device *device)
DMA_TO_DEVICE);
tx = dma->device_prep_dma_xor_val(dma_chan, dma_srcs,
IOAT_NUM_SRC_TEST + 1, PAGE_SIZE,
- &xor_val_result, DMA_PREP_INTERRUPT |
- DMA_COMPL_SKIP_SRC_UNMAP |
- DMA_COMPL_SKIP_DEST_UNMAP);
+ &xor_val_result, DMA_PREP_INTERRUPT);
if (!tx) {
dev_err(dev, "Self-test zero prep failed\n");
err = -ENODEV;
@@ -1519,7 +1352,7 @@ static int ioat_xor_val_self_test(struct ioatdma_device *device)
tmo = wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000));
- if (dma->device_tx_status(dma_chan, cookie, NULL) != DMA_SUCCESS) {
+ if (dma->device_tx_status(dma_chan, cookie, NULL) != DMA_COMPLETE) {
dev_err(dev, "Self-test validate timed out\n");
err = -ENODEV;
goto dma_unmap;
@@ -1545,9 +1378,7 @@ static int ioat_xor_val_self_test(struct ioatdma_device *device)
DMA_TO_DEVICE);
tx = dma->device_prep_dma_xor_val(dma_chan, dma_srcs,
IOAT_NUM_SRC_TEST + 1, PAGE_SIZE,
- &xor_val_result, DMA_PREP_INTERRUPT |
- DMA_COMPL_SKIP_SRC_UNMAP |
- DMA_COMPL_SKIP_DEST_UNMAP);
+ &xor_val_result, DMA_PREP_INTERRUPT);
if (!tx) {
dev_err(dev, "Self-test 2nd zero prep failed\n");
err = -ENODEV;
@@ -1568,7 +1399,7 @@ static int ioat_xor_val_self_test(struct ioatdma_device *device)
tmo = wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000));
- if (dma->device_tx_status(dma_chan, cookie, NULL) != DMA_SUCCESS) {
+ if (dma->device_tx_status(dma_chan, cookie, NULL) != DMA_COMPLETE) {
dev_err(dev, "Self-test 2nd validate timed out\n");
err = -ENODEV;
goto dma_unmap;
@@ -1621,52 +1452,36 @@ static int ioat3_dma_self_test(struct ioatdma_device *device)
static int ioat3_irq_reinit(struct ioatdma_device *device)
{
- int msixcnt = device->common.chancnt;
struct pci_dev *pdev = device->pdev;
- int i;
- struct msix_entry *msix;
- struct ioat_chan_common *chan;
- int err = 0;
+ int irq = pdev->irq, i;
+
+ if (!is_bwd_ioat(pdev))
+ return 0;
switch (device->irq_mode) {
case IOAT_MSIX:
+ for (i = 0; i < device->common.chancnt; i++) {
+ struct msix_entry *msix = &device->msix_entries[i];
+ struct ioat_chan_common *chan;
- for (i = 0; i < msixcnt; i++) {
- msix = &device->msix_entries[i];
chan = ioat_chan_by_index(device, i);
devm_free_irq(&pdev->dev, msix->vector, chan);
}
pci_disable_msix(pdev);
break;
-
- case IOAT_MSIX_SINGLE:
- msix = &device->msix_entries[0];
- chan = ioat_chan_by_index(device, 0);
- devm_free_irq(&pdev->dev, msix->vector, chan);
- pci_disable_msix(pdev);
- break;
-
case IOAT_MSI:
- chan = ioat_chan_by_index(device, 0);
- devm_free_irq(&pdev->dev, pdev->irq, chan);
pci_disable_msi(pdev);
- break;
-
+ /* fall through */
case IOAT_INTX:
- chan = ioat_chan_by_index(device, 0);
- devm_free_irq(&pdev->dev, pdev->irq, chan);
+ devm_free_irq(&pdev->dev, irq, device);
break;
-
default:
return 0;
}
-
device->irq_mode = IOAT_NOIRQ;
- err = ioat_dma_setup_interrupts(device);
-
- return err;
+ return ioat_dma_setup_interrupts(device);
}
static int ioat3_reset_hw(struct ioat_chan_common *chan)
@@ -1709,14 +1524,12 @@ static int ioat3_reset_hw(struct ioat_chan_common *chan)
}
err = ioat2_reset_sync(chan, msecs_to_jiffies(200));
- if (err) {
- dev_err(&pdev->dev, "Failed to reset!\n");
- return err;
- }
-
- if (device->irq_mode != IOAT_NOIRQ && is_bwd_ioat(pdev))
+ if (!err)
err = ioat3_irq_reinit(device);
+ if (err)
+ dev_err(&pdev->dev, "Failed to reset: %d\n", err);
+
return err;
}
@@ -1826,21 +1639,15 @@ int ioat3_dma_probe(struct ioatdma_device *device, int dca)
char pool_name[14];
int i;
- /* allocate sw descriptor pool for SED */
- device->sed_pool = kmem_cache_create("ioat_sed",
- sizeof(struct ioat_sed_ent), 0, 0, NULL);
- if (!device->sed_pool)
- return -ENOMEM;
-
for (i = 0; i < MAX_SED_POOLS; i++) {
snprintf(pool_name, 14, "ioat_hw%d_sed", i);
/* allocate SED DMA pool */
- device->sed_hw_pool[i] = dma_pool_create(pool_name,
+ device->sed_hw_pool[i] = dmam_pool_create(pool_name,
&pdev->dev,
SED_SIZE * (i + 1), 64, 0);
if (!device->sed_hw_pool[i])
- goto sed_pool_cleanup;
+ return -ENOMEM;
}
}
@@ -1866,28 +1673,4 @@ int ioat3_dma_probe(struct ioatdma_device *device, int dca)
device->dca = ioat3_dca_init(pdev, device->reg_base);
return 0;
-
-sed_pool_cleanup:
- if (device->sed_pool) {
- int i;
- kmem_cache_destroy(device->sed_pool);
-
- for (i = 0; i < MAX_SED_POOLS; i++)
- if (device->sed_hw_pool[i])
- dma_pool_destroy(device->sed_hw_pool[i]);
- }
-
- return -ENOMEM;
-}
-
-void ioat3_dma_remove(struct ioatdma_device *device)
-{
- if (device->sed_pool) {
- int i;
- kmem_cache_destroy(device->sed_pool);
-
- for (i = 0; i < MAX_SED_POOLS; i++)
- if (device->sed_hw_pool[i])
- dma_pool_destroy(device->sed_hw_pool[i]);
- }
}
diff --git a/drivers/dma/ioat/pci.c b/drivers/dma/ioat/pci.c
index 2c8d560..1d051cd 100644
--- a/drivers/dma/ioat/pci.c
+++ b/drivers/dma/ioat/pci.c
@@ -123,6 +123,7 @@ module_param(ioat_dca_enabled, int, 0644);
MODULE_PARM_DESC(ioat_dca_enabled, "control support of dca service (default: 1)");
struct kmem_cache *ioat2_cache;
+struct kmem_cache *ioat3_sed_cache;
#define DRV_NAME "ioatdma"
@@ -207,9 +208,6 @@ static void ioat_remove(struct pci_dev *pdev)
if (!device)
return;
- if (device->version >= IOAT_VER_3_0)
- ioat3_dma_remove(device);
-
dev_err(&pdev->dev, "Removing dma and dca services\n");
if (device->dca) {
unregister_dca_provider(device->dca, &pdev->dev);
@@ -221,7 +219,7 @@ static void ioat_remove(struct pci_dev *pdev)
static int __init ioat_init_module(void)
{
- int err;
+ int err = -ENOMEM;
pr_info("%s: Intel(R) QuickData Technology Driver %s\n",
DRV_NAME, IOAT_DMA_VERSION);
@@ -231,9 +229,21 @@ static int __init ioat_init_module(void)
if (!ioat2_cache)
return -ENOMEM;
+ ioat3_sed_cache = KMEM_CACHE(ioat_sed_ent, 0);
+ if (!ioat3_sed_cache)
+ goto err_ioat2_cache;
+
err = pci_register_driver(&ioat_pci_driver);
if (err)
- kmem_cache_destroy(ioat2_cache);
+ goto err_ioat3_cache;
+
+ return 0;
+
+ err_ioat3_cache:
+ kmem_cache_destroy(ioat3_sed_cache);
+
+ err_ioat2_cache:
+ kmem_cache_destroy(ioat2_cache);
return err;
}
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index dd8b44a..c56137b 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -61,80 +61,6 @@ static void iop_adma_free_slots(struct iop_adma_desc_slot *slot)
}
}
-static void
-iop_desc_unmap(struct iop_adma_chan *iop_chan, struct iop_adma_desc_slot *desc)
-{
- struct dma_async_tx_descriptor *tx = &desc->async_tx;
- struct iop_adma_desc_slot *unmap = desc->group_head;
- struct device *dev = &iop_chan->device->pdev->dev;
- u32 len = unmap->unmap_len;
- enum dma_ctrl_flags flags = tx->flags;
- u32 src_cnt;
- dma_addr_t addr;
- dma_addr_t dest;
-
- src_cnt = unmap->unmap_src_cnt;
- dest = iop_desc_get_dest_addr(unmap, iop_chan);
- if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
- enum dma_data_direction dir;
-
- if (src_cnt > 1) /* is xor? */
- dir = DMA_BIDIRECTIONAL;
- else
- dir = DMA_FROM_DEVICE;
-
- dma_unmap_page(dev, dest, len, dir);
- }
-
- if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
- while (src_cnt--) {
- addr = iop_desc_get_src_addr(unmap, iop_chan, src_cnt);
- if (addr == dest)
- continue;
- dma_unmap_page(dev, addr, len, DMA_TO_DEVICE);
- }
- }
- desc->group_head = NULL;
-}
-
-static void
-iop_desc_unmap_pq(struct iop_adma_chan *iop_chan, struct iop_adma_desc_slot *desc)
-{
- struct dma_async_tx_descriptor *tx = &desc->async_tx;
- struct iop_adma_desc_slot *unmap = desc->group_head;
- struct device *dev = &iop_chan->device->pdev->dev;
- u32 len = unmap->unmap_len;
- enum dma_ctrl_flags flags = tx->flags;
- u32 src_cnt = unmap->unmap_src_cnt;
- dma_addr_t pdest = iop_desc_get_dest_addr(unmap, iop_chan);
- dma_addr_t qdest = iop_desc_get_qdest_addr(unmap, iop_chan);
- int i;
-
- if (tx->flags & DMA_PREP_CONTINUE)
- src_cnt -= 3;
-
- if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP) && !desc->pq_check_result) {
- dma_unmap_page(dev, pdest, len, DMA_BIDIRECTIONAL);
- dma_unmap_page(dev, qdest, len, DMA_BIDIRECTIONAL);
- }
-
- if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
- dma_addr_t addr;
-
- for (i = 0; i < src_cnt; i++) {
- addr = iop_desc_get_src_addr(unmap, iop_chan, i);
- dma_unmap_page(dev, addr, len, DMA_TO_DEVICE);
- }
- if (desc->pq_check_result) {
- dma_unmap_page(dev, pdest, len, DMA_TO_DEVICE);
- dma_unmap_page(dev, qdest, len, DMA_TO_DEVICE);
- }
- }
-
- desc->group_head = NULL;
-}
-
-
static dma_cookie_t
iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
struct iop_adma_chan *iop_chan, dma_cookie_t cookie)
@@ -152,15 +78,9 @@ iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
if (tx->callback)
tx->callback(tx->callback_param);
- /* unmap dma addresses
- * (unmap_single vs unmap_page?)
- */
- if (desc->group_head && desc->unmap_len) {
- if (iop_desc_is_pq(desc))
- iop_desc_unmap_pq(iop_chan, desc);
- else
- iop_desc_unmap(iop_chan, desc);
- }
+ dma_descriptor_unmap(tx);
+ if (desc->group_head)
+ desc->group_head = NULL;
}
/* run dependent operations */
@@ -591,7 +511,6 @@ iop_adma_prep_dma_interrupt(struct dma_chan *chan, unsigned long flags)
if (sw_desc) {
grp_start = sw_desc->group_head;
iop_desc_init_interrupt(grp_start, iop_chan);
- grp_start->unmap_len = 0;
sw_desc->async_tx.flags = flags;
}
spin_unlock_bh(&iop_chan->lock);
@@ -623,8 +542,6 @@ iop_adma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dma_dest,
iop_desc_set_byte_count(grp_start, iop_chan, len);
iop_desc_set_dest_addr(grp_start, iop_chan, dma_dest);
iop_desc_set_memcpy_src_addr(grp_start, dma_src);
- sw_desc->unmap_src_cnt = 1;
- sw_desc->unmap_len = len;
sw_desc->async_tx.flags = flags;
}
spin_unlock_bh(&iop_chan->lock);
@@ -657,8 +574,6 @@ iop_adma_prep_dma_xor(struct dma_chan *chan, dma_addr_t dma_dest,
iop_desc_init_xor(grp_start, src_cnt, flags);
iop_desc_set_byte_count(grp_start, iop_chan, len);
iop_desc_set_dest_addr(grp_start, iop_chan, dma_dest);
- sw_desc->unmap_src_cnt = src_cnt;
- sw_desc->unmap_len = len;
sw_desc->async_tx.flags = flags;
while (src_cnt--)
iop_desc_set_xor_src_addr(grp_start, src_cnt,
@@ -694,8 +609,6 @@ iop_adma_prep_dma_xor_val(struct dma_chan *chan, dma_addr_t *dma_src,
grp_start->xor_check_result = result;
pr_debug("\t%s: grp_start->xor_check_result: %p\n",
__func__, grp_start->xor_check_result);
- sw_desc->unmap_src_cnt = src_cnt;
- sw_desc->unmap_len = len;
sw_desc->async_tx.flags = flags;
while (src_cnt--)
iop_desc_set_zero_sum_src_addr(grp_start, src_cnt,
@@ -748,8 +661,6 @@ iop_adma_prep_dma_pq(struct dma_chan *chan, dma_addr_t *dst, dma_addr_t *src,
dst[0] = dst[1] & 0x7;
iop_desc_set_pq_addr(g, dst);
- sw_desc->unmap_src_cnt = src_cnt;
- sw_desc->unmap_len = len;
sw_desc->async_tx.flags = flags;
for (i = 0; i < src_cnt; i++)
iop_desc_set_pq_src_addr(g, i, src[i], scf[i]);
@@ -804,8 +715,6 @@ iop_adma_prep_dma_pq_val(struct dma_chan *chan, dma_addr_t *pq, dma_addr_t *src,
g->pq_check_result = pqres;
pr_debug("\t%s: g->pq_check_result: %p\n",
__func__, g->pq_check_result);
- sw_desc->unmap_src_cnt = src_cnt+2;
- sw_desc->unmap_len = len;
sw_desc->async_tx.flags = flags;
while (src_cnt--)
iop_desc_set_pq_zero_sum_src_addr(g, src_cnt,
@@ -864,7 +773,7 @@ static enum dma_status iop_adma_status(struct dma_chan *chan,
int ret;
ret = dma_cookie_status(chan, cookie, txstate);
- if (ret == DMA_SUCCESS)
+ if (ret == DMA_COMPLETE)
return ret;
iop_adma_slot_cleanup(iop_chan);
@@ -983,7 +892,7 @@ static int iop_adma_memcpy_self_test(struct iop_adma_device *device)
msleep(1);
if (iop_adma_status(dma_chan, cookie, NULL) !=
- DMA_SUCCESS) {
+ DMA_COMPLETE) {
dev_err(dma_chan->device->dev,
"Self-test copy timed out, disabling\n");
err = -ENODEV;
@@ -1083,7 +992,7 @@ iop_adma_xor_val_self_test(struct iop_adma_device *device)
msleep(8);
if (iop_adma_status(dma_chan, cookie, NULL) !=
- DMA_SUCCESS) {
+ DMA_COMPLETE) {
dev_err(dma_chan->device->dev,
"Self-test xor timed out, disabling\n");
err = -ENODEV;
@@ -1129,7 +1038,7 @@ iop_adma_xor_val_self_test(struct iop_adma_device *device)
iop_adma_issue_pending(dma_chan);
msleep(8);
- if (iop_adma_status(dma_chan, cookie, NULL) != DMA_SUCCESS) {
+ if (iop_adma_status(dma_chan, cookie, NULL) != DMA_COMPLETE) {
dev_err(dma_chan->device->dev,
"Self-test zero sum timed out, disabling\n");
err = -ENODEV;
@@ -1158,7 +1067,7 @@ iop_adma_xor_val_self_test(struct iop_adma_device *device)
iop_adma_issue_pending(dma_chan);
msleep(8);
- if (iop_adma_status(dma_chan, cookie, NULL) != DMA_SUCCESS) {
+ if (iop_adma_status(dma_chan, cookie, NULL) != DMA_COMPLETE) {
dev_err(dma_chan->device->dev,
"Self-test non-zero sum timed out, disabling\n");
err = -ENODEV;
@@ -1254,7 +1163,7 @@ iop_adma_pq_zero_sum_self_test(struct iop_adma_device *device)
msleep(8);
if (iop_adma_status(dma_chan, cookie, NULL) !=
- DMA_SUCCESS) {
+ DMA_COMPLETE) {
dev_err(dev, "Self-test pq timed out, disabling\n");
err = -ENODEV;
goto free_resources;
@@ -1291,7 +1200,7 @@ iop_adma_pq_zero_sum_self_test(struct iop_adma_device *device)
msleep(8);
if (iop_adma_status(dma_chan, cookie, NULL) !=
- DMA_SUCCESS) {
+ DMA_COMPLETE) {
dev_err(dev, "Self-test pq-zero-sum timed out, disabling\n");
err = -ENODEV;
goto free_resources;
@@ -1323,7 +1232,7 @@ iop_adma_pq_zero_sum_self_test(struct iop_adma_device *device)
msleep(8);
if (iop_adma_status(dma_chan, cookie, NULL) !=
- DMA_SUCCESS) {
+ DMA_COMPLETE) {
dev_err(dev, "Self-test !pq-zero-sum timed out, disabling\n");
err = -ENODEV;
goto free_resources;
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c
index cb9c0bc..128ca14 100644
--- a/drivers/dma/ipu/ipu_idmac.c
+++ b/drivers/dma/ipu/ipu_idmac.c
@@ -1232,8 +1232,10 @@ static irqreturn_t idmac_interrupt(int irq, void *dev_id)
desc = list_entry(ichan->queue.next, struct idmac_tx_desc, list);
descnew = desc;
- dev_dbg(dev, "IDMAC irq %d, dma 0x%08x, next dma 0x%08x, current %d, curbuf 0x%08x\n",
- irq, sg_dma_address(*sg), sgnext ? sg_dma_address(sgnext) : 0, ichan->active_buffer, curbuf);
+ dev_dbg(dev, "IDMAC irq %d, dma %#llx, next dma %#llx, current %d, curbuf %#x\n",
+ irq, (u64)sg_dma_address(*sg),
+ sgnext ? (u64)sg_dma_address(sgnext) : 0,
+ ichan->active_buffer, curbuf);
/* Find the descriptor of sgnext */
sgnew = idmac_sg_next(ichan, &descnew, *sg);
diff --git a/drivers/dma/k3dma.c b/drivers/dma/k3dma.c
index a2c330f..e260754 100644
--- a/drivers/dma/k3dma.c
+++ b/drivers/dma/k3dma.c
@@ -344,7 +344,7 @@ static enum dma_status k3_dma_tx_status(struct dma_chan *chan,
size_t bytes = 0;
ret = dma_cookie_status(&c->vc.chan, cookie, state);
- if (ret == DMA_SUCCESS)
+ if (ret == DMA_COMPLETE)
return ret;
spin_lock_irqsave(&c->vc.lock, flags);
@@ -693,7 +693,7 @@ static int k3_dma_probe(struct platform_device *op)
irq = platform_get_irq(op, 0);
ret = devm_request_irq(&op->dev, irq,
- k3_dma_int_handler, IRQF_DISABLED, DRIVER_NAME, d);
+ k3_dma_int_handler, 0, DRIVER_NAME, d);
if (ret)
return ret;
diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c
index ff8d7827..dcb1e05 100644
--- a/drivers/dma/mmp_pdma.c
+++ b/drivers/dma/mmp_pdma.c
@@ -798,8 +798,7 @@ static void dma_do_tasklet(unsigned long data)
* move the descriptors to a temporary list so we can drop
* the lock during the entire cleanup operation
*/
- list_del(&desc->node);
- list_add(&desc->node, &chain_cleanup);
+ list_move(&desc->node, &chain_cleanup);
/*
* Look for the first list entry which has the ENDIRQEN flag
@@ -863,7 +862,7 @@ static int mmp_pdma_chan_init(struct mmp_pdma_device *pdev,
if (irq) {
ret = devm_request_irq(pdev->dev, irq,
- mmp_pdma_chan_handler, IRQF_DISABLED, "pdma", phy);
+ mmp_pdma_chan_handler, 0, "pdma", phy);
if (ret) {
dev_err(pdev->dev, "channel request irq fail!\n");
return ret;
@@ -970,7 +969,7 @@ static int mmp_pdma_probe(struct platform_device *op)
/* all chan share one irq, demux inside */
irq = platform_get_irq(op, 0);
ret = devm_request_irq(pdev->dev, irq,
- mmp_pdma_int_handler, IRQF_DISABLED, "pdma", pdev);
+ mmp_pdma_int_handler, 0, "pdma", pdev);
if (ret)
return ret;
}
diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c
index 38cb517..3ddacc1 100644
--- a/drivers/dma/mmp_tdma.c
+++ b/drivers/dma/mmp_tdma.c
@@ -62,6 +62,11 @@
#define TDCR_BURSTSZ_16B (0x3 << 6)
#define TDCR_BURSTSZ_32B (0x6 << 6)
#define TDCR_BURSTSZ_64B (0x7 << 6)
+#define TDCR_BURSTSZ_SQU_1B (0x5 << 6)
+#define TDCR_BURSTSZ_SQU_2B (0x6 << 6)
+#define TDCR_BURSTSZ_SQU_4B (0x0 << 6)
+#define TDCR_BURSTSZ_SQU_8B (0x1 << 6)
+#define TDCR_BURSTSZ_SQU_16B (0x3 << 6)
#define TDCR_BURSTSZ_SQU_32B (0x7 << 6)
#define TDCR_BURSTSZ_128B (0x5 << 6)
#define TDCR_DSTDIR_MSK (0x3 << 4) /* Dst Direction */
@@ -158,7 +163,7 @@ static void mmp_tdma_disable_chan(struct mmp_tdma_chan *tdmac)
/* disable irq */
writel(0, tdmac->reg_base + TDIMR);
- tdmac->status = DMA_SUCCESS;
+ tdmac->status = DMA_COMPLETE;
}
static void mmp_tdma_resume_chan(struct mmp_tdma_chan *tdmac)
@@ -228,8 +233,31 @@ static int mmp_tdma_config_chan(struct mmp_tdma_chan *tdmac)
return -EINVAL;
}
} else if (tdmac->type == PXA910_SQU) {
- tdcr |= TDCR_BURSTSZ_SQU_32B;
tdcr |= TDCR_SSPMOD;
+
+ switch (tdmac->burst_sz) {
+ case 1:
+ tdcr |= TDCR_BURSTSZ_SQU_1B;
+ break;
+ case 2:
+ tdcr |= TDCR_BURSTSZ_SQU_2B;
+ break;
+ case 4:
+ tdcr |= TDCR_BURSTSZ_SQU_4B;
+ break;
+ case 8:
+ tdcr |= TDCR_BURSTSZ_SQU_8B;
+ break;
+ case 16:
+ tdcr |= TDCR_BURSTSZ_SQU_16B;
+ break;
+ case 32:
+ tdcr |= TDCR_BURSTSZ_SQU_32B;
+ break;
+ default:
+ dev_err(tdmac->dev, "mmp_tdma: unknown burst size.\n");
+ return -EINVAL;
+ }
}
writel(tdcr, tdmac->reg_base + TDCR);
@@ -324,7 +352,7 @@ static int mmp_tdma_alloc_chan_resources(struct dma_chan *chan)
if (tdmac->irq) {
ret = devm_request_irq(tdmac->dev, tdmac->irq,
- mmp_tdma_chan_handler, IRQF_DISABLED, "tdma", tdmac);
+ mmp_tdma_chan_handler, 0, "tdma", tdmac);
if (ret)
return ret;
}
@@ -350,12 +378,7 @@ struct mmp_tdma_desc *mmp_tdma_alloc_descriptor(struct mmp_tdma_chan *tdmac)
if (!gpool)
return NULL;
- tdmac->desc_arr = (void *)gen_pool_alloc(gpool, size);
- if (!tdmac->desc_arr)
- return NULL;
-
- tdmac->desc_arr_phys = gen_pool_virt_to_phys(gpool,
- (unsigned long)tdmac->desc_arr);
+ tdmac->desc_arr = gen_pool_dma_alloc(gpool, size, &tdmac->desc_arr_phys);
return tdmac->desc_arr;
}
@@ -370,7 +393,7 @@ static struct dma_async_tx_descriptor *mmp_tdma_prep_dma_cyclic(
int num_periods = buf_len / period_len;
int i = 0, buf = 0;
- if (tdmac->status != DMA_SUCCESS)
+ if (tdmac->status != DMA_COMPLETE)
return NULL;
if (period_len > TDMA_MAX_XFER_BYTES) {
@@ -504,7 +527,7 @@ static int mmp_tdma_chan_init(struct mmp_tdma_device *tdev,
tdmac->idx = idx;
tdmac->type = type;
tdmac->reg_base = (unsigned long)tdev->base + idx * 4;
- tdmac->status = DMA_SUCCESS;
+ tdmac->status = DMA_COMPLETE;
tdev->tdmac[tdmac->idx] = tdmac;
tasklet_init(&tdmac->tasklet, dma_do_tasklet, (unsigned long)tdmac);
@@ -559,7 +582,7 @@ static int mmp_tdma_probe(struct platform_device *pdev)
if (irq_num != chan_num) {
irq = platform_get_irq(pdev, 0);
ret = devm_request_irq(&pdev->dev, irq,
- mmp_tdma_int_handler, IRQF_DISABLED, "tdma", tdev);
+ mmp_tdma_int_handler, 0, "tdma", tdev);
if (ret)
return ret;
}
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 2fe4353..448750d 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -39,7 +39,9 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/slab.h>
+#include <linux/of_address.h>
#include <linux/of_device.h>
+#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/random.h>
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index 536dcb8..7807f0e 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -60,14 +60,6 @@ static u32 mv_desc_get_dest_addr(struct mv_xor_desc_slot *desc)
return hw_desc->phy_dest_addr;
}
-static u32 mv_desc_get_src_addr(struct mv_xor_desc_slot *desc,
- int src_idx)
-{
- struct mv_xor_desc *hw_desc = desc->hw_desc;
- return hw_desc->phy_src_addr[mv_phy_src_idx(src_idx)];
-}
-
-
static void mv_desc_set_byte_count(struct mv_xor_desc_slot *desc,
u32 byte_count)
{
@@ -278,42 +270,9 @@ mv_xor_run_tx_complete_actions(struct mv_xor_desc_slot *desc,
desc->async_tx.callback(
desc->async_tx.callback_param);
- /* unmap dma addresses
- * (unmap_single vs unmap_page?)
- */
- if (desc->group_head && desc->unmap_len) {
- struct mv_xor_desc_slot *unmap = desc->group_head;
- struct device *dev = mv_chan_to_devp(mv_chan);
- u32 len = unmap->unmap_len;
- enum dma_ctrl_flags flags = desc->async_tx.flags;
- u32 src_cnt;
- dma_addr_t addr;
- dma_addr_t dest;
-
- src_cnt = unmap->unmap_src_cnt;
- dest = mv_desc_get_dest_addr(unmap);
- if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
- enum dma_data_direction dir;
-
- if (src_cnt > 1) /* is xor ? */
- dir = DMA_BIDIRECTIONAL;
- else
- dir = DMA_FROM_DEVICE;
- dma_unmap_page(dev, dest, len, dir);
- }
-
- if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
- while (src_cnt--) {
- addr = mv_desc_get_src_addr(unmap,
- src_cnt);
- if (addr == dest)
- continue;
- dma_unmap_page(dev, addr, len,
- DMA_TO_DEVICE);
- }
- }
+ dma_descriptor_unmap(&desc->async_tx);
+ if (desc->group_head)
desc->group_head = NULL;
- }
}
/* run dependent operations */
@@ -749,7 +708,7 @@ static enum dma_status mv_xor_status(struct dma_chan *chan,
enum dma_status ret;
ret = dma_cookie_status(chan, cookie, txstate);
- if (ret == DMA_SUCCESS) {
+ if (ret == DMA_COMPLETE) {
mv_xor_clean_completed_slots(mv_chan);
return ret;
}
@@ -874,7 +833,7 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
msleep(1);
if (mv_xor_status(dma_chan, cookie, NULL) !=
- DMA_SUCCESS) {
+ DMA_COMPLETE) {
dev_err(dma_chan->device->dev,
"Self-test copy timed out, disabling\n");
err = -ENODEV;
@@ -968,7 +927,7 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
msleep(8);
if (mv_xor_status(dma_chan, cookie, NULL) !=
- DMA_SUCCESS) {
+ DMA_COMPLETE) {
dev_err(dma_chan->device->dev,
"Self-test xor timed out, disabling\n");
err = -ENODEV;
@@ -1076,10 +1035,7 @@ mv_xor_channel_add(struct mv_xor_device *xordev,
}
mv_chan->mmr_base = xordev->xor_base;
- if (!mv_chan->mmr_base) {
- ret = -ENOMEM;
- goto err_free_dma;
- }
+ mv_chan->mmr_high_base = xordev->xor_high_base;
tasklet_init(&mv_chan->irq_tasklet, mv_xor_tasklet, (unsigned long)
mv_chan);
@@ -1138,7 +1094,7 @@ static void
mv_xor_conf_mbus_windows(struct mv_xor_device *xordev,
const struct mbus_dram_target_info *dram)
{
- void __iomem *base = xordev->xor_base;
+ void __iomem *base = xordev->xor_high_base;
u32 win_enable = 0;
int i;
diff --git a/drivers/dma/mv_xor.h b/drivers/dma/mv_xor.h
index 06b067f..d074922 100644
--- a/drivers/dma/mv_xor.h
+++ b/drivers/dma/mv_xor.h
@@ -34,13 +34,13 @@
#define XOR_OPERATION_MODE_MEMCPY 2
#define XOR_DESCRIPTOR_SWAP BIT(14)
-#define XOR_CURR_DESC(chan) (chan->mmr_base + 0x210 + (chan->idx * 4))
-#define XOR_NEXT_DESC(chan) (chan->mmr_base + 0x200 + (chan->idx * 4))
-#define XOR_BYTE_COUNT(chan) (chan->mmr_base + 0x220 + (chan->idx * 4))
-#define XOR_DEST_POINTER(chan) (chan->mmr_base + 0x2B0 + (chan->idx * 4))
-#define XOR_BLOCK_SIZE(chan) (chan->mmr_base + 0x2C0 + (chan->idx * 4))
-#define XOR_INIT_VALUE_LOW(chan) (chan->mmr_base + 0x2E0)
-#define XOR_INIT_VALUE_HIGH(chan) (chan->mmr_base + 0x2E4)
+#define XOR_CURR_DESC(chan) (chan->mmr_high_base + 0x10 + (chan->idx * 4))
+#define XOR_NEXT_DESC(chan) (chan->mmr_high_base + 0x00 + (chan->idx * 4))
+#define XOR_BYTE_COUNT(chan) (chan->mmr_high_base + 0x20 + (chan->idx * 4))
+#define XOR_DEST_POINTER(chan) (chan->mmr_high_base + 0xB0 + (chan->idx * 4))
+#define XOR_BLOCK_SIZE(chan) (chan->mmr_high_base + 0xC0 + (chan->idx * 4))
+#define XOR_INIT_VALUE_LOW(chan) (chan->mmr_high_base + 0xE0)
+#define XOR_INIT_VALUE_HIGH(chan) (chan->mmr_high_base + 0xE4)
#define XOR_CONFIG(chan) (chan->mmr_base + 0x10 + (chan->idx * 4))
#define XOR_ACTIVATION(chan) (chan->mmr_base + 0x20 + (chan->idx * 4))
@@ -50,11 +50,11 @@
#define XOR_ERROR_ADDR(chan) (chan->mmr_base + 0x60)
#define XOR_INTR_MASK_VALUE 0x3F5
-#define WINDOW_BASE(w) (0x250 + ((w) << 2))
-#define WINDOW_SIZE(w) (0x270 + ((w) << 2))
-#define WINDOW_REMAP_HIGH(w) (0x290 + ((w) << 2))
-#define WINDOW_BAR_ENABLE(chan) (0x240 + ((chan) << 2))
-#define WINDOW_OVERRIDE_CTRL(chan) (0x2A0 + ((chan) << 2))
+#define WINDOW_BASE(w) (0x50 + ((w) << 2))
+#define WINDOW_SIZE(w) (0x70 + ((w) << 2))
+#define WINDOW_REMAP_HIGH(w) (0x90 + ((w) << 2))
+#define WINDOW_BAR_ENABLE(chan) (0x40 + ((chan) << 2))
+#define WINDOW_OVERRIDE_CTRL(chan) (0xA0 + ((chan) << 2))
struct mv_xor_device {
void __iomem *xor_base;
@@ -82,6 +82,7 @@ struct mv_xor_chan {
int pending;
spinlock_t lock; /* protects the descriptor slot pool */
void __iomem *mmr_base;
+ void __iomem *mmr_high_base;
unsigned int idx;
int irq;
enum dma_transaction_type current_type;
diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
index ccd13df..ead4913 100644
--- a/drivers/dma/mxs-dma.c
+++ b/drivers/dma/mxs-dma.c
@@ -27,6 +27,7 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_dma.h>
+#include <linux/list.h>
#include <asm/irq.h>
@@ -57,6 +58,9 @@
(((dma_is_apbh(d) && apbh_is_old(d)) ? 0x050 : 0x110) + (n) * 0x70)
#define HW_APBHX_CHn_SEMA(d, n) \
(((dma_is_apbh(d) && apbh_is_old(d)) ? 0x080 : 0x140) + (n) * 0x70)
+#define HW_APBHX_CHn_BAR(d, n) \
+ (((dma_is_apbh(d) && apbh_is_old(d)) ? 0x070 : 0x130) + (n) * 0x70)
+#define HW_APBX_CHn_DEBUG1(d, n) (0x150 + (n) * 0x70)
/*
* ccw bits definitions
@@ -115,7 +119,9 @@ struct mxs_dma_chan {
int desc_count;
enum dma_status status;
unsigned int flags;
+ bool reset;
#define MXS_DMA_SG_LOOP (1 << 0)
+#define MXS_DMA_USE_SEMAPHORE (1 << 1)
};
#define MXS_DMA_CHANNELS 16
@@ -201,12 +207,47 @@ static void mxs_dma_reset_chan(struct mxs_dma_chan *mxs_chan)
struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
int chan_id = mxs_chan->chan.chan_id;
- if (dma_is_apbh(mxs_dma) && apbh_is_old(mxs_dma))
+ /*
+ * mxs dma channel resets can cause a channel stall. To recover from a
+ * channel stall, we have to reset the whole DMA engine. To avoid this,
+ * we use cyclic DMA with semaphores, that are enhanced in
+ * mxs_dma_int_handler. To reset the channel, we can simply stop writing
+ * into the semaphore counter.
+ */
+ if (mxs_chan->flags & MXS_DMA_USE_SEMAPHORE &&
+ mxs_chan->flags & MXS_DMA_SG_LOOP) {
+ mxs_chan->reset = true;
+ } else if (dma_is_apbh(mxs_dma) && apbh_is_old(mxs_dma)) {
writel(1 << (chan_id + BP_APBH_CTRL0_RESET_CHANNEL),
mxs_dma->base + HW_APBHX_CTRL0 + STMP_OFFSET_REG_SET);
- else
+ } else {
+ unsigned long elapsed = 0;
+ const unsigned long max_wait = 50000; /* 50ms */
+ void __iomem *reg_dbg1 = mxs_dma->base +
+ HW_APBX_CHn_DEBUG1(mxs_dma, chan_id);
+
+ /*
+ * On i.MX28 APBX, the DMA channel can stop working if we reset
+ * the channel while it is in READ_FLUSH (0x08) state.
+ * We wait here until we leave the state. Then we trigger the
+ * reset. Waiting a maximum of 50ms, the kernel shouldn't crash
+ * because of this.
+ */
+ while ((readl(reg_dbg1) & 0xf) == 0x8 && elapsed < max_wait) {
+ udelay(100);
+ elapsed += 100;
+ }
+
+ if (elapsed >= max_wait)
+ dev_err(&mxs_chan->mxs_dma->pdev->dev,
+ "Failed waiting for the DMA channel %d to leave state READ_FLUSH, trying to reset channel in READ_FLUSH state now\n",
+ chan_id);
+
writel(1 << (chan_id + BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL),
mxs_dma->base + HW_APBHX_CHANNEL_CTRL + STMP_OFFSET_REG_SET);
+ }
+
+ mxs_chan->status = DMA_COMPLETE;
}
static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan)
@@ -219,12 +260,21 @@ static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan)
mxs_dma->base + HW_APBHX_CHn_NXTCMDAR(mxs_dma, chan_id));
/* write 1 to SEMA to kick off the channel */
- writel(1, mxs_dma->base + HW_APBHX_CHn_SEMA(mxs_dma, chan_id));
+ if (mxs_chan->flags & MXS_DMA_USE_SEMAPHORE &&
+ mxs_chan->flags & MXS_DMA_SG_LOOP) {
+ /* A cyclic DMA consists of at least 2 segments, so initialize
+ * the semaphore with 2 so we have enough time to add 1 to the
+ * semaphore if we need to */
+ writel(2, mxs_dma->base + HW_APBHX_CHn_SEMA(mxs_dma, chan_id));
+ } else {
+ writel(1, mxs_dma->base + HW_APBHX_CHn_SEMA(mxs_dma, chan_id));
+ }
+ mxs_chan->reset = false;
}
static void mxs_dma_disable_chan(struct mxs_dma_chan *mxs_chan)
{
- mxs_chan->status = DMA_SUCCESS;
+ mxs_chan->status = DMA_COMPLETE;
}
static void mxs_dma_pause_chan(struct mxs_dma_chan *mxs_chan)
@@ -272,58 +322,88 @@ static void mxs_dma_tasklet(unsigned long data)
mxs_chan->desc.callback(mxs_chan->desc.callback_param);
}
+static int mxs_dma_irq_to_chan(struct mxs_dma_engine *mxs_dma, int irq)
+{
+ int i;
+
+ for (i = 0; i != mxs_dma->nr_channels; ++i)
+ if (mxs_dma->mxs_chans[i].chan_irq == irq)
+ return i;
+
+ return -EINVAL;
+}
+
static irqreturn_t mxs_dma_int_handler(int irq, void *dev_id)
{
struct mxs_dma_engine *mxs_dma = dev_id;
- u32 stat1, stat2;
+ struct mxs_dma_chan *mxs_chan;
+ u32 completed;
+ u32 err;
+ int chan = mxs_dma_irq_to_chan(mxs_dma, irq);
+
+ if (chan < 0)
+ return IRQ_NONE;
/* completion status */
- stat1 = readl(mxs_dma->base + HW_APBHX_CTRL1);
- stat1 &= MXS_DMA_CHANNELS_MASK;
- writel(stat1, mxs_dma->base + HW_APBHX_CTRL1 + STMP_OFFSET_REG_CLR);
+ completed = readl(mxs_dma->base + HW_APBHX_CTRL1);
+ completed = (completed >> chan) & 0x1;
+
+ /* Clear interrupt */
+ writel((1 << chan),
+ mxs_dma->base + HW_APBHX_CTRL1 + STMP_OFFSET_REG_CLR);
/* error status */
- stat2 = readl(mxs_dma->base + HW_APBHX_CTRL2);
- writel(stat2, mxs_dma->base + HW_APBHX_CTRL2 + STMP_OFFSET_REG_CLR);
+ err = readl(mxs_dma->base + HW_APBHX_CTRL2);
+ err &= (1 << (MXS_DMA_CHANNELS + chan)) | (1 << chan);
+
+ /*
+ * error status bit is in the upper 16 bits, error irq bit in the lower
+ * 16 bits. We transform it into a simpler error code:
+ * err: 0x00 = no error, 0x01 = TERMINATION, 0x02 = BUS_ERROR
+ */
+ err = (err >> (MXS_DMA_CHANNELS + chan)) + (err >> chan);
+
+ /* Clear error irq */
+ writel((1 << chan),
+ mxs_dma->base + HW_APBHX_CTRL2 + STMP_OFFSET_REG_CLR);
/*
* When both completion and error of termination bits set at the
* same time, we do not take it as an error. IOW, it only becomes
- * an error we need to handle here in case of either it's (1) a bus
- * error or (2) a termination error with no completion.
+ * an error we need to handle here in case of either it's a bus
+ * error or a termination error with no completion. 0x01 is termination
+ * error, so we can subtract err & completed to get the real error case.
*/
- stat2 = ((stat2 >> MXS_DMA_CHANNELS) & stat2) | /* (1) */
- (~(stat2 >> MXS_DMA_CHANNELS) & stat2 & ~stat1); /* (2) */
-
- /* combine error and completion status for checking */
- stat1 = (stat2 << MXS_DMA_CHANNELS) | stat1;
- while (stat1) {
- int channel = fls(stat1) - 1;
- struct mxs_dma_chan *mxs_chan =
- &mxs_dma->mxs_chans[channel % MXS_DMA_CHANNELS];
-
- if (channel >= MXS_DMA_CHANNELS) {
- dev_dbg(mxs_dma->dma_device.dev,
- "%s: error in channel %d\n", __func__,
- channel - MXS_DMA_CHANNELS);
- mxs_chan->status = DMA_ERROR;
- mxs_dma_reset_chan(mxs_chan);
- } else {
- if (mxs_chan->flags & MXS_DMA_SG_LOOP)
- mxs_chan->status = DMA_IN_PROGRESS;
- else
- mxs_chan->status = DMA_SUCCESS;
- }
+ err -= err & completed;
- stat1 &= ~(1 << channel);
+ mxs_chan = &mxs_dma->mxs_chans[chan];
- if (mxs_chan->status == DMA_SUCCESS)
- dma_cookie_complete(&mxs_chan->desc);
+ if (err) {
+ dev_dbg(mxs_dma->dma_device.dev,
+ "%s: error in channel %d\n", __func__,
+ chan);
+ mxs_chan->status = DMA_ERROR;
+ mxs_dma_reset_chan(mxs_chan);
+ } else if (mxs_chan->status != DMA_COMPLETE) {
+ if (mxs_chan->flags & MXS_DMA_SG_LOOP) {
+ mxs_chan->status = DMA_IN_PROGRESS;
+ if (mxs_chan->flags & MXS_DMA_USE_SEMAPHORE)
+ writel(1, mxs_dma->base +
+ HW_APBHX_CHn_SEMA(mxs_dma, chan));
+ } else {
+ mxs_chan->status = DMA_COMPLETE;
+ }
+ }
- /* schedule tasklet on this channel */
- tasklet_schedule(&mxs_chan->tasklet);
+ if (mxs_chan->status == DMA_COMPLETE) {
+ if (mxs_chan->reset)
+ return IRQ_HANDLED;
+ dma_cookie_complete(&mxs_chan->desc);
}
+ /* schedule tasklet on this channel */
+ tasklet_schedule(&mxs_chan->tasklet);
+
return IRQ_HANDLED;
}
@@ -523,6 +603,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic(
mxs_chan->status = DMA_IN_PROGRESS;
mxs_chan->flags |= MXS_DMA_SG_LOOP;
+ mxs_chan->flags |= MXS_DMA_USE_SEMAPHORE;
if (num_periods > NUM_CCW) {
dev_err(mxs_dma->dma_device.dev,
@@ -554,6 +635,7 @@ static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic(
ccw->bits |= CCW_IRQ;
ccw->bits |= CCW_HALT_ON_TERM;
ccw->bits |= CCW_TERM_FLUSH;
+ ccw->bits |= CCW_DEC_SEM;
ccw->bits |= BF_CCW(direction == DMA_DEV_TO_MEM ?
MXS_DMA_CMD_WRITE : MXS_DMA_CMD_READ, COMMAND);
@@ -599,8 +681,24 @@ static enum dma_status mxs_dma_tx_status(struct dma_chan *chan,
dma_cookie_t cookie, struct dma_tx_state *txstate)
{
struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
+ struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+ u32 residue = 0;
+
+ if (mxs_chan->status == DMA_IN_PROGRESS &&
+ mxs_chan->flags & MXS_DMA_SG_LOOP) {
+ struct mxs_dma_ccw *last_ccw;
+ u32 bar;
+
+ last_ccw = &mxs_chan->ccw[mxs_chan->desc_count - 1];
+ residue = last_ccw->xfer_bytes + last_ccw->bufaddr;
+
+ bar = readl(mxs_dma->base +
+ HW_APBHX_CHn_BAR(mxs_dma, chan->chan_id));
+ residue -= bar;
+ }
- dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie, 0);
+ dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie,
+ residue);
return mxs_chan->status;
}
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index ec3fc4f..2f66cf4 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -248,7 +248,7 @@ static enum dma_status omap_dma_tx_status(struct dma_chan *chan,
unsigned long flags;
ret = dma_cookie_status(chan, cookie, txstate);
- if (ret == DMA_SUCCESS || !txstate)
+ if (ret == DMA_COMPLETE || !txstate)
return ret;
spin_lock_irqsave(&c->vc.lock, flags);
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index a562d24..cdf0483 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -2268,6 +2268,8 @@ static void pl330_tasklet(unsigned long data)
list_move_tail(&desc->node, &pch->dmac->desc_pool);
}
+ dma_descriptor_unmap(&desc->txd);
+
if (callback) {
spin_unlock_irqrestore(&pch->lock, flags);
callback(callback_param);
@@ -2314,7 +2316,7 @@ bool pl330_filter(struct dma_chan *chan, void *param)
return false;
peri_id = chan->private;
- return *peri_id == (unsigned)param;
+ return *peri_id == (unsigned long)param;
}
EXPORT_SYMBOL(pl330_filter);
@@ -2903,6 +2905,10 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
pdat = dev_get_platdata(&adev->dev);
+ ret = dma_set_mask_and_coherent(&adev->dev, DMA_BIT_MASK(32));
+ if (ret)
+ return ret;
+
/* Allocate a new DMAC and its Channels */
pdmac = devm_kzalloc(&adev->dev, sizeof(*pdmac), GFP_KERNEL);
if (!pdmac) {
@@ -2922,16 +2928,23 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
amba_set_drvdata(adev, pdmac);
- irq = adev->irq[0];
- ret = request_irq(irq, pl330_irq_handler, 0,
- dev_name(&adev->dev), pi);
- if (ret)
- return ret;
+ for (i = 0; i < AMBA_NR_IRQS; i++) {
+ irq = adev->irq[i];
+ if (irq) {
+ ret = devm_request_irq(&adev->dev, irq,
+ pl330_irq_handler, 0,
+ dev_name(&adev->dev), pi);
+ if (ret)
+ return ret;
+ } else {
+ break;
+ }
+ }
pi->pcfg.periph_id = adev->periphid;
ret = pl330_add(pi);
if (ret)
- goto probe_err1;
+ return ret;
INIT_LIST_HEAD(&pdmac->desc_pool);
spin_lock_init(&pdmac->pool_lock);
@@ -3029,8 +3042,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
return 0;
probe_err3:
- amba_set_drvdata(adev, NULL);
-
/* Idle the DMAC */
list_for_each_entry_safe(pch, _p, &pdmac->ddma.channels,
chan.device_node) {
@@ -3044,8 +3055,6 @@ probe_err3:
}
probe_err2:
pl330_del(pi);
-probe_err1:
- free_irq(irq, pi);
return ret;
}
@@ -3055,7 +3064,6 @@ static int pl330_remove(struct amba_device *adev)
struct dma_pl330_dmac *pdmac = amba_get_drvdata(adev);
struct dma_pl330_chan *pch, *_p;
struct pl330_info *pi;
- int irq;
if (!pdmac)
return 0;
@@ -3064,7 +3072,6 @@ static int pl330_remove(struct amba_device *adev)
of_dma_controller_free(adev->dev.of_node);
dma_async_device_unregister(&pdmac->ddma);
- amba_set_drvdata(adev, NULL);
/* Idle the DMAC */
list_for_each_entry_safe(pch, _p, &pdmac->ddma.channels,
@@ -3082,9 +3089,6 @@ static int pl330_remove(struct amba_device *adev)
pl330_del(pi);
- irq = adev->irq[0];
- free_irq(irq, pi);
-
return 0;
}
diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c
index 370ff82..8da48c6 100644
--- a/drivers/dma/ppc4xx/adma.c
+++ b/drivers/dma/ppc4xx/adma.c
@@ -42,6 +42,8 @@
#include <linux/uaccess.h>
#include <linux/proc_fs.h>
#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <asm/dcr.h>
#include <asm/dcr-regs.h>
@@ -802,218 +804,6 @@ static void ppc440spe_desc_set_link(struct ppc440spe_adma_chan *chan,
}
/**
- * ppc440spe_desc_get_src_addr - extract the source address from the descriptor
- */
-static u32 ppc440spe_desc_get_src_addr(struct ppc440spe_adma_desc_slot *desc,
- struct ppc440spe_adma_chan *chan, int src_idx)
-{
- struct dma_cdb *dma_hw_desc;
- struct xor_cb *xor_hw_desc;
-
- switch (chan->device->id) {
- case PPC440SPE_DMA0_ID:
- case PPC440SPE_DMA1_ID:
- dma_hw_desc = desc->hw_desc;
- /* May have 0, 1, 2, or 3 sources */
- switch (dma_hw_desc->opc) {
- case DMA_CDB_OPC_NO_OP:
- case DMA_CDB_OPC_DFILL128:
- return 0;
- case DMA_CDB_OPC_DCHECK128:
- if (unlikely(src_idx)) {
- printk(KERN_ERR "%s: try to get %d source for"
- " DCHECK128\n", __func__, src_idx);
- BUG();
- }
- return le32_to_cpu(dma_hw_desc->sg1l);
- case DMA_CDB_OPC_MULTICAST:
- case DMA_CDB_OPC_MV_SG1_SG2:
- if (unlikely(src_idx > 2)) {
- printk(KERN_ERR "%s: try to get %d source from"
- " DMA descr\n", __func__, src_idx);
- BUG();
- }
- if (src_idx) {
- if (le32_to_cpu(dma_hw_desc->sg1u) &
- DMA_CUED_XOR_WIN_MSK) {
- u8 region;
-
- if (src_idx == 1)
- return le32_to_cpu(
- dma_hw_desc->sg1l) +
- desc->unmap_len;
-
- region = (le32_to_cpu(
- dma_hw_desc->sg1u)) >>
- DMA_CUED_REGION_OFF;
-
- region &= DMA_CUED_REGION_MSK;
- switch (region) {
- case DMA_RXOR123:
- return le32_to_cpu(
- dma_hw_desc->sg1l) +
- (desc->unmap_len << 1);
- case DMA_RXOR124:
- return le32_to_cpu(
- dma_hw_desc->sg1l) +
- (desc->unmap_len * 3);
- case DMA_RXOR125:
- return le32_to_cpu(
- dma_hw_desc->sg1l) +
- (desc->unmap_len << 2);
- default:
- printk(KERN_ERR
- "%s: try to"
- " get src3 for region %02x"
- "PPC440SPE_DESC_RXOR12?\n",
- __func__, region);
- BUG();
- }
- } else {
- printk(KERN_ERR
- "%s: try to get %d"
- " source for non-cued descr\n",
- __func__, src_idx);
- BUG();
- }
- }
- return le32_to_cpu(dma_hw_desc->sg1l);
- default:
- printk(KERN_ERR "%s: unknown OPC 0x%02x\n",
- __func__, dma_hw_desc->opc);
- BUG();
- }
- return le32_to_cpu(dma_hw_desc->sg1l);
- case PPC440SPE_XOR_ID:
- /* May have up to 16 sources */
- xor_hw_desc = desc->hw_desc;
- return xor_hw_desc->ops[src_idx].l;
- }
- return 0;
-}
-
-/**
- * ppc440spe_desc_get_dest_addr - extract the destination address from the
- * descriptor
- */
-static u32 ppc440spe_desc_get_dest_addr(struct ppc440spe_adma_desc_slot *desc,
- struct ppc440spe_adma_chan *chan, int idx)
-{
- struct dma_cdb *dma_hw_desc;
- struct xor_cb *xor_hw_desc;
-
- switch (chan->device->id) {
- case PPC440SPE_DMA0_ID:
- case PPC440SPE_DMA1_ID:
- dma_hw_desc = desc->hw_desc;
-
- if (likely(!idx))
- return le32_to_cpu(dma_hw_desc->sg2l);
- return le32_to_cpu(dma_hw_desc->sg3l);
- case PPC440SPE_XOR_ID:
- xor_hw_desc = desc->hw_desc;
- return xor_hw_desc->cbtal;
- }
- return 0;
-}
-
-/**
- * ppc440spe_desc_get_src_num - extract the number of source addresses from
- * the descriptor
- */
-static u32 ppc440spe_desc_get_src_num(struct ppc440spe_adma_desc_slot *desc,
- struct ppc440spe_adma_chan *chan)
-{
- struct dma_cdb *dma_hw_desc;
- struct xor_cb *xor_hw_desc;
-
- switch (chan->device->id) {
- case PPC440SPE_DMA0_ID:
- case PPC440SPE_DMA1_ID:
- dma_hw_desc = desc->hw_desc;
-
- switch (dma_hw_desc->opc) {
- case DMA_CDB_OPC_NO_OP:
- case DMA_CDB_OPC_DFILL128:
- return 0;
- case DMA_CDB_OPC_DCHECK128:
- return 1;
- case DMA_CDB_OPC_MV_SG1_SG2:
- case DMA_CDB_OPC_MULTICAST:
- /*
- * Only for RXOR operations we have more than
- * one source
- */
- if (le32_to_cpu(dma_hw_desc->sg1u) &
- DMA_CUED_XOR_WIN_MSK) {
- /* RXOR op, there are 2 or 3 sources */
- if (((le32_to_cpu(dma_hw_desc->sg1u) >>
- DMA_CUED_REGION_OFF) &
- DMA_CUED_REGION_MSK) == DMA_RXOR12) {
- /* RXOR 1-2 */
- return 2;
- } else {
- /* RXOR 1-2-3/1-2-4/1-2-5 */
- return 3;
- }
- }
- return 1;
- default:
- printk(KERN_ERR "%s: unknown OPC 0x%02x\n",
- __func__, dma_hw_desc->opc);
- BUG();
- }
- case PPC440SPE_XOR_ID:
- /* up to 16 sources */
- xor_hw_desc = desc->hw_desc;
- return xor_hw_desc->cbc & XOR_CDCR_OAC_MSK;
- default:
- BUG();
- }
- return 0;
-}
-
-/**
- * ppc440spe_desc_get_dst_num - get the number of destination addresses in
- * this descriptor
- */
-static u32 ppc440spe_desc_get_dst_num(struct ppc440spe_adma_desc_slot *desc,
- struct ppc440spe_adma_chan *chan)
-{
- struct dma_cdb *dma_hw_desc;
-
- switch (chan->device->id) {
- case PPC440SPE_DMA0_ID:
- case PPC440SPE_DMA1_ID:
- /* May be 1 or 2 destinations */
- dma_hw_desc = desc->hw_desc;
- switch (dma_hw_desc->opc) {
- case DMA_CDB_OPC_NO_OP:
- case DMA_CDB_OPC_DCHECK128:
- return 0;
- case DMA_CDB_OPC_MV_SG1_SG2:
- case DMA_CDB_OPC_DFILL128:
- return 1;
- case DMA_CDB_OPC_MULTICAST:
- if (desc->dst_cnt == 2)
- return 2;
- else
- return 1;
- default:
- printk(KERN_ERR "%s: unknown OPC 0x%02x\n",
- __func__, dma_hw_desc->opc);
- BUG();
- }
- case PPC440SPE_XOR_ID:
- /* Always only 1 destination */
- return 1;
- default:
- BUG();
- }
- return 0;
-}
-
-/**
* ppc440spe_desc_get_link - get the address of the descriptor that
* follows this one
*/
@@ -1705,43 +1495,6 @@ static void ppc440spe_adma_free_slots(struct ppc440spe_adma_desc_slot *slot,
}
}
-static void ppc440spe_adma_unmap(struct ppc440spe_adma_chan *chan,
- struct ppc440spe_adma_desc_slot *desc)
-{
- u32 src_cnt, dst_cnt;
- dma_addr_t addr;
-
- /*
- * get the number of sources & destination
- * included in this descriptor and unmap
- * them all
- */
- src_cnt = ppc440spe_desc_get_src_num(desc, chan);
- dst_cnt = ppc440spe_desc_get_dst_num(desc, chan);
-
- /* unmap destinations */
- if (!(desc->async_tx.flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
- while (dst_cnt--) {
- addr = ppc440spe_desc_get_dest_addr(
- desc, chan, dst_cnt);
- dma_unmap_page(chan->device->dev,
- addr, desc->unmap_len,
- DMA_FROM_DEVICE);
- }
- }
-
- /* unmap sources */
- if (!(desc->async_tx.flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
- while (src_cnt--) {
- addr = ppc440spe_desc_get_src_addr(
- desc, chan, src_cnt);
- dma_unmap_page(chan->device->dev,
- addr, desc->unmap_len,
- DMA_TO_DEVICE);
- }
- }
-}
-
/**
* ppc440spe_adma_run_tx_complete_actions - call functions to be called
* upon completion
@@ -1765,26 +1518,7 @@ static dma_cookie_t ppc440spe_adma_run_tx_complete_actions(
desc->async_tx.callback(
desc->async_tx.callback_param);
- /* unmap dma addresses
- * (unmap_single vs unmap_page?)
- *
- * actually, ppc's dma_unmap_page() functions are empty, so
- * the following code is just for the sake of completeness
- */
- if (chan && chan->needs_unmap && desc->group_head &&
- desc->unmap_len) {
- struct ppc440spe_adma_desc_slot *unmap =
- desc->group_head;
- /* assume 1 slot per op always */
- u32 slot_count = unmap->slot_cnt;
-
- /* Run through the group list and unmap addresses */
- for (i = 0; i < slot_count; i++) {
- BUG_ON(!unmap);
- ppc440spe_adma_unmap(chan, unmap);
- unmap = unmap->hw_next;
- }
- }
+ dma_descriptor_unmap(&desc->async_tx);
}
/* run dependent operations */
@@ -3891,7 +3625,7 @@ static enum dma_status ppc440spe_adma_tx_status(struct dma_chan *chan,
ppc440spe_chan = to_ppc440spe_adma_chan(chan);
ret = dma_cookie_status(chan, cookie, txstate);
- if (ret == DMA_SUCCESS)
+ if (ret == DMA_COMPLETE)
return ret;
ppc440spe_adma_slot_cleanup(ppc440spe_chan);
diff --git a/drivers/dma/s3c24xx-dma.c b/drivers/dma/s3c24xx-dma.c
new file mode 100644
index 0000000..19f6d6a
--- /dev/null
+++ b/drivers/dma/s3c24xx-dma.c
@@ -0,0 +1,1321 @@
+/*
+ * S3C24XX DMA handling
+ *
+ * Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
+ *
+ * based on amba-pl08x.c
+ *
+ * Copyright (c) 2006 ARM Ltd.
+ * Copyright (c) 2010 ST-Ericsson SA
+ *
+ * Author: Peter Pearse <peter.pearse@arm.com>
+ * Author: Linus Walleij <linus.walleij@stericsson.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * The DMA controllers in S3C24XX SoCs have a varying number of DMA signals
+ * that can be routed to any of the 4 to 8 hardware-channels.
+ *
+ * Therefore on these DMA controllers the number of channels
+ * and the number of incoming DMA signals are two totally different things.
+ * It is usually not possible to theoretically handle all physical signals,
+ * so a multiplexing scheme with possible denial of use is necessary.
+ *
+ * Open items:
+ * - bursts
+ */
+
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_data/dma-s3c24xx.h>
+
+#include "dmaengine.h"
+#include "virt-dma.h"
+
+#define MAX_DMA_CHANNELS 8
+
+#define S3C24XX_DISRC 0x00
+#define S3C24XX_DISRCC 0x04
+#define S3C24XX_DISRCC_INC_INCREMENT 0
+#define S3C24XX_DISRCC_INC_FIXED BIT(0)
+#define S3C24XX_DISRCC_LOC_AHB 0
+#define S3C24XX_DISRCC_LOC_APB BIT(1)
+
+#define S3C24XX_DIDST 0x08
+#define S3C24XX_DIDSTC 0x0c
+#define S3C24XX_DIDSTC_INC_INCREMENT 0
+#define S3C24XX_DIDSTC_INC_FIXED BIT(0)
+#define S3C24XX_DIDSTC_LOC_AHB 0
+#define S3C24XX_DIDSTC_LOC_APB BIT(1)
+#define S3C24XX_DIDSTC_INT_TC0 0
+#define S3C24XX_DIDSTC_INT_RELOAD BIT(2)
+
+#define S3C24XX_DCON 0x10
+
+#define S3C24XX_DCON_TC_MASK 0xfffff
+#define S3C24XX_DCON_DSZ_BYTE (0 << 20)
+#define S3C24XX_DCON_DSZ_HALFWORD (1 << 20)
+#define S3C24XX_DCON_DSZ_WORD (2 << 20)
+#define S3C24XX_DCON_DSZ_MASK (3 << 20)
+#define S3C24XX_DCON_DSZ_SHIFT 20
+#define S3C24XX_DCON_AUTORELOAD 0
+#define S3C24XX_DCON_NORELOAD BIT(22)
+#define S3C24XX_DCON_HWTRIG BIT(23)
+#define S3C24XX_DCON_HWSRC_SHIFT 24
+#define S3C24XX_DCON_SERV_SINGLE 0
+#define S3C24XX_DCON_SERV_WHOLE BIT(27)
+#define S3C24XX_DCON_TSZ_UNIT 0
+#define S3C24XX_DCON_TSZ_BURST4 BIT(28)
+#define S3C24XX_DCON_INT BIT(29)
+#define S3C24XX_DCON_SYNC_PCLK 0
+#define S3C24XX_DCON_SYNC_HCLK BIT(30)
+#define S3C24XX_DCON_DEMAND 0
+#define S3C24XX_DCON_HANDSHAKE BIT(31)
+
+#define S3C24XX_DSTAT 0x14
+#define S3C24XX_DSTAT_STAT_BUSY BIT(20)
+#define S3C24XX_DSTAT_CURRTC_MASK 0xfffff
+
+#define S3C24XX_DMASKTRIG 0x20
+#define S3C24XX_DMASKTRIG_SWTRIG BIT(0)
+#define S3C24XX_DMASKTRIG_ON BIT(1)
+#define S3C24XX_DMASKTRIG_STOP BIT(2)
+
+#define S3C24XX_DMAREQSEL 0x24
+#define S3C24XX_DMAREQSEL_HW BIT(0)
+
+/*
+ * S3C2410, S3C2440 and S3C2442 SoCs cannot select any physical channel
+ * for a DMA source. Instead only specific channels are valid.
+ * All of these SoCs have 4 physical channels and the number of request
+ * source bits is 3. Additionally we also need 1 bit to mark the channel
+ * as valid.
+ * Therefore we separate the chansel element of the channel data into 4
+ * parts of 4 bits each, to hold the information if the channel is valid
+ * and the hw request source to use.
+ *
+ * Example:
+ * SDI is valid on channels 0, 2 and 3 - with varying hw request sources.
+ * For it the chansel field would look like
+ *
+ * ((BIT(3) | 1) << 3 * 4) | // channel 3, with request source 1
+ * ((BIT(3) | 2) << 2 * 4) | // channel 2, with request source 2
+ * ((BIT(3) | 2) << 0 * 4) // channel 0, with request source 2
+ */
+#define S3C24XX_CHANSEL_WIDTH 4
+#define S3C24XX_CHANSEL_VALID BIT(3)
+#define S3C24XX_CHANSEL_REQ_MASK 7
+
+/*
+ * struct soc_data - vendor-specific config parameters for individual SoCs
+ * @stride: spacing between the registers of each channel
+ * @has_reqsel: does the controller use the newer requestselection mechanism
+ * @has_clocks: are controllable dma-clocks present
+ */
+struct soc_data {
+ int stride;
+ bool has_reqsel;
+ bool has_clocks;
+};
+
+/*
+ * enum s3c24xx_dma_chan_state - holds the virtual channel states
+ * @S3C24XX_DMA_CHAN_IDLE: the channel is idle
+ * @S3C24XX_DMA_CHAN_RUNNING: the channel has allocated a physical transport
+ * channel and is running a transfer on it
+ * @S3C24XX_DMA_CHAN_WAITING: the channel is waiting for a physical transport
+ * channel to become available (only pertains to memcpy channels)
+ */
+enum s3c24xx_dma_chan_state {
+ S3C24XX_DMA_CHAN_IDLE,
+ S3C24XX_DMA_CHAN_RUNNING,
+ S3C24XX_DMA_CHAN_WAITING,
+};
+
+/*
+ * struct s3c24xx_sg - structure containing data per sg
+ * @src_addr: src address of sg
+ * @dst_addr: dst address of sg
+ * @len: transfer len in bytes
+ * @node: node for txd's dsg_list
+ */
+struct s3c24xx_sg {
+ dma_addr_t src_addr;
+ dma_addr_t dst_addr;
+ size_t len;
+ struct list_head node;
+};
+
+/*
+ * struct s3c24xx_txd - wrapper for struct dma_async_tx_descriptor
+ * @vd: virtual DMA descriptor
+ * @dsg_list: list of children sg's
+ * @at: sg currently being transfered
+ * @width: transfer width
+ * @disrcc: value for source control register
+ * @didstc: value for destination control register
+ * @dcon: base value for dcon register
+ */
+struct s3c24xx_txd {
+ struct virt_dma_desc vd;
+ struct list_head dsg_list;
+ struct list_head *at;
+ u8 width;
+ u32 disrcc;
+ u32 didstc;
+ u32 dcon;
+};
+
+struct s3c24xx_dma_chan;
+
+/*
+ * struct s3c24xx_dma_phy - holder for the physical channels
+ * @id: physical index to this channel
+ * @valid: does the channel have all required elements
+ * @base: virtual memory base (remapped) for the this channel
+ * @irq: interrupt for this channel
+ * @clk: clock for this channel
+ * @lock: a lock to use when altering an instance of this struct
+ * @serving: virtual channel currently being served by this physicalchannel
+ * @host: a pointer to the host (internal use)
+ */
+struct s3c24xx_dma_phy {
+ unsigned int id;
+ bool valid;
+ void __iomem *base;
+ unsigned int irq;
+ struct clk *clk;
+ spinlock_t lock;
+ struct s3c24xx_dma_chan *serving;
+ struct s3c24xx_dma_engine *host;
+};
+
+/*
+ * struct s3c24xx_dma_chan - this structure wraps a DMA ENGINE channel
+ * @id: the id of the channel
+ * @name: name of the channel
+ * @vc: wrappped virtual channel
+ * @phy: the physical channel utilized by this channel, if there is one
+ * @runtime_addr: address for RX/TX according to the runtime config
+ * @at: active transaction on this channel
+ * @lock: a lock for this channel data
+ * @host: a pointer to the host (internal use)
+ * @state: whether the channel is idle, running etc
+ * @slave: whether this channel is a device (slave) or for memcpy
+ */
+struct s3c24xx_dma_chan {
+ int id;
+ const char *name;
+ struct virt_dma_chan vc;
+ struct s3c24xx_dma_phy *phy;
+ struct dma_slave_config cfg;
+ struct s3c24xx_txd *at;
+ struct s3c24xx_dma_engine *host;
+ enum s3c24xx_dma_chan_state state;
+ bool slave;
+};
+
+/*
+ * struct s3c24xx_dma_engine - the local state holder for the S3C24XX
+ * @pdev: the corresponding platform device
+ * @pdata: platform data passed in from the platform/machine
+ * @base: virtual memory base (remapped)
+ * @slave: slave engine for this instance
+ * @memcpy: memcpy engine for this instance
+ * @phy_chans: array of data for the physical channels
+ */
+struct s3c24xx_dma_engine {
+ struct platform_device *pdev;
+ const struct s3c24xx_dma_platdata *pdata;
+ struct soc_data *sdata;
+ void __iomem *base;
+ struct dma_device slave;
+ struct dma_device memcpy;
+ struct s3c24xx_dma_phy *phy_chans;
+};
+
+/*
+ * Physical channel handling
+ */
+
+/*
+ * Check whether a certain channel is busy or not.
+ */
+static int s3c24xx_dma_phy_busy(struct s3c24xx_dma_phy *phy)
+{
+ unsigned int val = readl(phy->base + S3C24XX_DSTAT);
+ return val & S3C24XX_DSTAT_STAT_BUSY;
+}
+
+static bool s3c24xx_dma_phy_valid(struct s3c24xx_dma_chan *s3cchan,
+ struct s3c24xx_dma_phy *phy)
+{
+ struct s3c24xx_dma_engine *s3cdma = s3cchan->host;
+ const struct s3c24xx_dma_platdata *pdata = s3cdma->pdata;
+ struct s3c24xx_dma_channel *cdata = &pdata->channels[s3cchan->id];
+ int phyvalid;
+
+ /* every phy is valid for memcopy channels */
+ if (!s3cchan->slave)
+ return true;
+
+ /* On newer variants all phys can be used for all virtual channels */
+ if (s3cdma->sdata->has_reqsel)
+ return true;
+
+ phyvalid = (cdata->chansel >> (phy->id * S3C24XX_CHANSEL_WIDTH));
+ return (phyvalid & S3C24XX_CHANSEL_VALID) ? true : false;
+}
+
+/*
+ * Allocate a physical channel for a virtual channel
+ *
+ * Try to locate a physical channel to be used for this transfer. If all
+ * are taken return NULL and the requester will have to cope by using
+ * some fallback PIO mode or retrying later.
+ */
+static
+struct s3c24xx_dma_phy *s3c24xx_dma_get_phy(struct s3c24xx_dma_chan *s3cchan)
+{
+ struct s3c24xx_dma_engine *s3cdma = s3cchan->host;
+ const struct s3c24xx_dma_platdata *pdata = s3cdma->pdata;
+ struct s3c24xx_dma_channel *cdata;
+ struct s3c24xx_dma_phy *phy = NULL;
+ unsigned long flags;
+ int i;
+ int ret;
+
+ if (s3cchan->slave)
+ cdata = &pdata->channels[s3cchan->id];
+
+ for (i = 0; i < s3cdma->pdata->num_phy_channels; i++) {
+ phy = &s3cdma->phy_chans[i];
+
+ if (!phy->valid)
+ continue;
+
+ if (!s3c24xx_dma_phy_valid(s3cchan, phy))
+ continue;
+
+ spin_lock_irqsave(&phy->lock, flags);
+
+ if (!phy->serving) {
+ phy->serving = s3cchan;
+ spin_unlock_irqrestore(&phy->lock, flags);
+ break;
+ }
+
+ spin_unlock_irqrestore(&phy->lock, flags);
+ }
+
+ /* No physical channel available, cope with it */
+ if (i == s3cdma->pdata->num_phy_channels) {
+ dev_warn(&s3cdma->pdev->dev, "no phy channel available\n");
+ return NULL;
+ }
+
+ /* start the phy clock */
+ if (s3cdma->sdata->has_clocks) {
+ ret = clk_enable(phy->clk);
+ if (ret) {
+ dev_err(&s3cdma->pdev->dev, "could not enable clock for channel %d, err %d\n",
+ phy->id, ret);
+ phy->serving = NULL;
+ return NULL;
+ }
+ }
+
+ return phy;
+}
+
+/*
+ * Mark the physical channel as free.
+ *
+ * This drops the link between the physical and virtual channel.
+ */
+static inline void s3c24xx_dma_put_phy(struct s3c24xx_dma_phy *phy)
+{
+ struct s3c24xx_dma_engine *s3cdma = phy->host;
+
+ if (s3cdma->sdata->has_clocks)
+ clk_disable(phy->clk);
+
+ phy->serving = NULL;
+}
+
+/*
+ * Stops the channel by writing the stop bit.
+ * This should not be used for an on-going transfer, but as a method of
+ * shutting down a channel (eg, when it's no longer used) or terminating a
+ * transfer.
+ */
+static void s3c24xx_dma_terminate_phy(struct s3c24xx_dma_phy *phy)
+{
+ writel(S3C24XX_DMASKTRIG_STOP, phy->base + S3C24XX_DMASKTRIG);
+}
+
+/*
+ * Virtual channel handling
+ */
+
+static inline
+struct s3c24xx_dma_chan *to_s3c24xx_dma_chan(struct dma_chan *chan)
+{
+ return container_of(chan, struct s3c24xx_dma_chan, vc.chan);
+}
+
+static u32 s3c24xx_dma_getbytes_chan(struct s3c24xx_dma_chan *s3cchan)
+{
+ struct s3c24xx_dma_phy *phy = s3cchan->phy;
+ struct s3c24xx_txd *txd = s3cchan->at;
+ u32 tc = readl(phy->base + S3C24XX_DSTAT) & S3C24XX_DSTAT_CURRTC_MASK;
+
+ return tc * txd->width;
+}
+
+static int s3c24xx_dma_set_runtime_config(struct s3c24xx_dma_chan *s3cchan,
+ struct dma_slave_config *config)
+{
+ if (!s3cchan->slave)
+ return -EINVAL;
+
+ /* Reject definitely invalid configurations */
+ if (config->src_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES ||
+ config->dst_addr_width == DMA_SLAVE_BUSWIDTH_8_BYTES)
+ return -EINVAL;
+
+ s3cchan->cfg = *config;
+
+ return 0;
+}
+
+/*
+ * Transfer handling
+ */
+
+static inline
+struct s3c24xx_txd *to_s3c24xx_txd(struct dma_async_tx_descriptor *tx)
+{
+ return container_of(tx, struct s3c24xx_txd, vd.tx);
+}
+
+static struct s3c24xx_txd *s3c24xx_dma_get_txd(void)
+{
+ struct s3c24xx_txd *txd = kzalloc(sizeof(*txd), GFP_NOWAIT);
+
+ if (txd) {
+ INIT_LIST_HEAD(&txd->dsg_list);
+ txd->dcon = S3C24XX_DCON_INT | S3C24XX_DCON_NORELOAD;
+ }
+
+ return txd;
+}
+
+static void s3c24xx_dma_free_txd(struct s3c24xx_txd *txd)
+{
+ struct s3c24xx_sg *dsg, *_dsg;
+
+ list_for_each_entry_safe(dsg, _dsg, &txd->dsg_list, node) {
+ list_del(&dsg->node);
+ kfree(dsg);
+ }
+
+ kfree(txd);
+}
+
+static void s3c24xx_dma_start_next_sg(struct s3c24xx_dma_chan *s3cchan,
+ struct s3c24xx_txd *txd)
+{
+ struct s3c24xx_dma_engine *s3cdma = s3cchan->host;
+ struct s3c24xx_dma_phy *phy = s3cchan->phy;
+ const struct s3c24xx_dma_platdata *pdata = s3cdma->pdata;
+ struct s3c24xx_sg *dsg = list_entry(txd->at, struct s3c24xx_sg, node);
+ u32 dcon = txd->dcon;
+ u32 val;
+
+ /* transfer-size and -count from len and width */
+ switch (txd->width) {
+ case 1:
+ dcon |= S3C24XX_DCON_DSZ_BYTE | dsg->len;
+ break;
+ case 2:
+ dcon |= S3C24XX_DCON_DSZ_HALFWORD | (dsg->len / 2);
+ break;
+ case 4:
+ dcon |= S3C24XX_DCON_DSZ_WORD | (dsg->len / 4);
+ break;
+ }
+
+ if (s3cchan->slave) {
+ struct s3c24xx_dma_channel *cdata =
+ &pdata->channels[s3cchan->id];
+
+ if (s3cdma->sdata->has_reqsel) {
+ writel_relaxed((cdata->chansel << 1) |
+ S3C24XX_DMAREQSEL_HW,
+ phy->base + S3C24XX_DMAREQSEL);
+ } else {
+ int csel = cdata->chansel >> (phy->id *
+ S3C24XX_CHANSEL_WIDTH);
+
+ csel &= S3C24XX_CHANSEL_REQ_MASK;
+ dcon |= csel << S3C24XX_DCON_HWSRC_SHIFT;
+ dcon |= S3C24XX_DCON_HWTRIG;
+ }
+ } else {
+ if (s3cdma->sdata->has_reqsel)
+ writel_relaxed(0, phy->base + S3C24XX_DMAREQSEL);
+ }
+
+ writel_relaxed(dsg->src_addr, phy->base + S3C24XX_DISRC);
+ writel_relaxed(txd->disrcc, phy->base + S3C24XX_DISRCC);
+ writel_relaxed(dsg->dst_addr, phy->base + S3C24XX_DIDST);
+ writel_relaxed(txd->didstc, phy->base + S3C24XX_DIDSTC);
+ writel_relaxed(dcon, phy->base + S3C24XX_DCON);
+
+ val = readl_relaxed(phy->base + S3C24XX_DMASKTRIG);
+ val &= ~S3C24XX_DMASKTRIG_STOP;
+ val |= S3C24XX_DMASKTRIG_ON;
+
+ /* trigger the dma operation for memcpy transfers */
+ if (!s3cchan->slave)
+ val |= S3C24XX_DMASKTRIG_SWTRIG;
+
+ writel(val, phy->base + S3C24XX_DMASKTRIG);
+}
+
+/*
+ * Set the initial DMA register values and start first sg.
+ */
+static void s3c24xx_dma_start_next_txd(struct s3c24xx_dma_chan *s3cchan)
+{
+ struct s3c24xx_dma_phy *phy = s3cchan->phy;
+ struct virt_dma_desc *vd = vchan_next_desc(&s3cchan->vc);
+ struct s3c24xx_txd *txd = to_s3c24xx_txd(&vd->tx);
+
+ list_del(&txd->vd.node);
+
+ s3cchan->at = txd;
+
+ /* Wait for channel inactive */
+ while (s3c24xx_dma_phy_busy(phy))
+ cpu_relax();
+
+ /* point to the first element of the sg list */
+ txd->at = txd->dsg_list.next;
+ s3c24xx_dma_start_next_sg(s3cchan, txd);
+}
+
+static void s3c24xx_dma_free_txd_list(struct s3c24xx_dma_engine *s3cdma,
+ struct s3c24xx_dma_chan *s3cchan)
+{
+ LIST_HEAD(head);
+
+ vchan_get_all_descriptors(&s3cchan->vc, &head);
+ vchan_dma_desc_free_list(&s3cchan->vc, &head);
+}
+
+/*
+ * Try to allocate a physical channel. When successful, assign it to
+ * this virtual channel, and initiate the next descriptor. The
+ * virtual channel lock must be held at this point.
+ */
+static void s3c24xx_dma_phy_alloc_and_start(struct s3c24xx_dma_chan *s3cchan)
+{
+ struct s3c24xx_dma_engine *s3cdma = s3cchan->host;
+ struct s3c24xx_dma_phy *phy;
+
+ phy = s3c24xx_dma_get_phy(s3cchan);
+ if (!phy) {
+ dev_dbg(&s3cdma->pdev->dev, "no physical channel available for xfer on %s\n",
+ s3cchan->name);
+ s3cchan->state = S3C24XX_DMA_CHAN_WAITING;
+ return;
+ }
+
+ dev_dbg(&s3cdma->pdev->dev, "allocated physical channel %d for xfer on %s\n",
+ phy->id, s3cchan->name);
+
+ s3cchan->phy = phy;
+ s3cchan->state = S3C24XX_DMA_CHAN_RUNNING;
+
+ s3c24xx_dma_start_next_txd(s3cchan);
+}
+
+static void s3c24xx_dma_phy_reassign_start(struct s3c24xx_dma_phy *phy,
+ struct s3c24xx_dma_chan *s3cchan)
+{
+ struct s3c24xx_dma_engine *s3cdma = s3cchan->host;
+
+ dev_dbg(&s3cdma->pdev->dev, "reassigned physical channel %d for xfer on %s\n",
+ phy->id, s3cchan->name);
+
+ /*
+ * We do this without taking the lock; we're really only concerned
+ * about whether this pointer is NULL or not, and we're guaranteed
+ * that this will only be called when it _already_ is non-NULL.
+ */
+ phy->serving = s3cchan;
+ s3cchan->phy = phy;
+ s3cchan->state = S3C24XX_DMA_CHAN_RUNNING;
+ s3c24xx_dma_start_next_txd(s3cchan);
+}
+
+/*
+ * Free a physical DMA channel, potentially reallocating it to another
+ * virtual channel if we have any pending.
+ */
+static void s3c24xx_dma_phy_free(struct s3c24xx_dma_chan *s3cchan)
+{
+ struct s3c24xx_dma_engine *s3cdma = s3cchan->host;
+ struct s3c24xx_dma_chan *p, *next;
+
+retry:
+ next = NULL;
+
+ /* Find a waiting virtual channel for the next transfer. */
+ list_for_each_entry(p, &s3cdma->memcpy.channels, vc.chan.device_node)
+ if (p->state == S3C24XX_DMA_CHAN_WAITING) {
+ next = p;
+ break;
+ }
+
+ if (!next) {
+ list_for_each_entry(p, &s3cdma->slave.channels,
+ vc.chan.device_node)
+ if (p->state == S3C24XX_DMA_CHAN_WAITING &&
+ s3c24xx_dma_phy_valid(p, s3cchan->phy)) {
+ next = p;
+ break;
+ }
+ }
+
+ /* Ensure that the physical channel is stopped */
+ s3c24xx_dma_terminate_phy(s3cchan->phy);
+
+ if (next) {
+ bool success;
+
+ /*
+ * Eww. We know this isn't going to deadlock
+ * but lockdep probably doesn't.
+ */
+ spin_lock(&next->vc.lock);
+ /* Re-check the state now that we have the lock */
+ success = next->state == S3C24XX_DMA_CHAN_WAITING;
+ if (success)
+ s3c24xx_dma_phy_reassign_start(s3cchan->phy, next);
+ spin_unlock(&next->vc.lock);
+
+ /* If the state changed, try to find another channel */
+ if (!success)
+ goto retry;
+ } else {
+ /* No more jobs, so free up the physical channel */
+ s3c24xx_dma_put_phy(s3cchan->phy);
+ }
+
+ s3cchan->phy = NULL;
+ s3cchan->state = S3C24XX_DMA_CHAN_IDLE;
+}
+
+static void s3c24xx_dma_desc_free(struct virt_dma_desc *vd)
+{
+ struct s3c24xx_txd *txd = to_s3c24xx_txd(&vd->tx);
+ struct s3c24xx_dma_chan *s3cchan = to_s3c24xx_dma_chan(vd->tx.chan);
+
+ if (!s3cchan->slave)
+ dma_descriptor_unmap(&vd->tx);
+
+ s3c24xx_dma_free_txd(txd);
+}
+
+static irqreturn_t s3c24xx_dma_irq(int irq, void *data)
+{
+ struct s3c24xx_dma_phy *phy = data;
+ struct s3c24xx_dma_chan *s3cchan = phy->serving;
+ struct s3c24xx_txd *txd;
+
+ dev_dbg(&phy->host->pdev->dev, "interrupt on channel %d\n", phy->id);
+
+ /*
+ * Interrupts happen to notify the completion of a transfer and the
+ * channel should have moved into its stop state already on its own.
+ * Therefore interrupts on channels not bound to a virtual channel
+ * should never happen. Nevertheless send a terminate command to the
+ * channel if the unlikely case happens.
+ */
+ if (unlikely(!s3cchan)) {
+ dev_err(&phy->host->pdev->dev, "interrupt on unused channel %d\n",
+ phy->id);
+
+ s3c24xx_dma_terminate_phy(phy);
+
+ return IRQ_HANDLED;
+ }
+
+ spin_lock(&s3cchan->vc.lock);
+ txd = s3cchan->at;
+ if (txd) {
+ /* when more sg's are in this txd, start the next one */
+ if (!list_is_last(txd->at, &txd->dsg_list)) {
+ txd->at = txd->at->next;
+ s3c24xx_dma_start_next_sg(s3cchan, txd);
+ } else {
+ s3cchan->at = NULL;
+ vchan_cookie_complete(&txd->vd);
+
+ /*
+ * And start the next descriptor (if any),
+ * otherwise free this channel.
+ */
+ if (vchan_next_desc(&s3cchan->vc))
+ s3c24xx_dma_start_next_txd(s3cchan);
+ else
+ s3c24xx_dma_phy_free(s3cchan);
+ }
+ }
+ spin_unlock(&s3cchan->vc.lock);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * The DMA ENGINE API
+ */
+
+static int s3c24xx_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+ unsigned long arg)
+{
+ struct s3c24xx_dma_chan *s3cchan = to_s3c24xx_dma_chan(chan);
+ struct s3c24xx_dma_engine *s3cdma = s3cchan->host;
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&s3cchan->vc.lock, flags);
+
+ switch (cmd) {
+ case DMA_SLAVE_CONFIG:
+ ret = s3c24xx_dma_set_runtime_config(s3cchan,
+ (struct dma_slave_config *)arg);
+ break;
+ case DMA_TERMINATE_ALL:
+ if (!s3cchan->phy && !s3cchan->at) {
+ dev_err(&s3cdma->pdev->dev, "trying to terminate already stopped channel %d\n",
+ s3cchan->id);
+ ret = -EINVAL;
+ break;
+ }
+
+ s3cchan->state = S3C24XX_DMA_CHAN_IDLE;
+
+ /* Mark physical channel as free */
+ if (s3cchan->phy)
+ s3c24xx_dma_phy_free(s3cchan);
+
+ /* Dequeue current job */
+ if (s3cchan->at) {
+ s3c24xx_dma_desc_free(&s3cchan->at->vd);
+ s3cchan->at = NULL;
+ }
+
+ /* Dequeue jobs not yet fired as well */
+ s3c24xx_dma_free_txd_list(s3cdma, s3cchan);
+ break;
+ default:
+ /* Unknown command */
+ ret = -ENXIO;
+ break;
+ }
+
+ spin_unlock_irqrestore(&s3cchan->vc.lock, flags);
+
+ return ret;
+}
+
+static int s3c24xx_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+ return 0;
+}
+
+static void s3c24xx_dma_free_chan_resources(struct dma_chan *chan)
+{
+ /* Ensure all queued descriptors are freed */
+ vchan_free_chan_resources(to_virt_chan(chan));
+}
+
+static enum dma_status s3c24xx_dma_tx_status(struct dma_chan *chan,
+ dma_cookie_t cookie, struct dma_tx_state *txstate)
+{
+ struct s3c24xx_dma_chan *s3cchan = to_s3c24xx_dma_chan(chan);
+ struct s3c24xx_txd *txd;
+ struct s3c24xx_sg *dsg;
+ struct virt_dma_desc *vd;
+ unsigned long flags;
+ enum dma_status ret;
+ size_t bytes = 0;
+
+ spin_lock_irqsave(&s3cchan->vc.lock, flags);
+ ret = dma_cookie_status(chan, cookie, txstate);
+ if (ret == DMA_SUCCESS) {
+ spin_unlock_irqrestore(&s3cchan->vc.lock, flags);
+ return ret;
+ }
+
+ /*
+ * There's no point calculating the residue if there's
+ * no txstate to store the value.
+ */
+ if (!txstate) {
+ spin_unlock_irqrestore(&s3cchan->vc.lock, flags);
+ return ret;
+ }
+
+ vd = vchan_find_desc(&s3cchan->vc, cookie);
+ if (vd) {
+ /* On the issued list, so hasn't been processed yet */
+ txd = to_s3c24xx_txd(&vd->tx);
+
+ list_for_each_entry(dsg, &txd->dsg_list, node)
+ bytes += dsg->len;
+ } else {
+ /*
+ * Currently running, so sum over the pending sg's and
+ * the currently active one.
+ */
+ txd = s3cchan->at;
+
+ dsg = list_entry(txd->at, struct s3c24xx_sg, node);
+ list_for_each_entry_from(dsg, &txd->dsg_list, node)
+ bytes += dsg->len;
+
+ bytes += s3c24xx_dma_getbytes_chan(s3cchan);
+ }
+ spin_unlock_irqrestore(&s3cchan->vc.lock, flags);
+
+ /*
+ * This cookie not complete yet
+ * Get number of bytes left in the active transactions and queue
+ */
+ dma_set_residue(txstate, bytes);
+
+ /* Whether waiting or running, we're in progress */
+ return ret;
+}
+
+/*
+ * Initialize a descriptor to be used by memcpy submit
+ */
+static struct dma_async_tx_descriptor *s3c24xx_dma_prep_memcpy(
+ struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+ size_t len, unsigned long flags)
+{
+ struct s3c24xx_dma_chan *s3cchan = to_s3c24xx_dma_chan(chan);
+ struct s3c24xx_dma_engine *s3cdma = s3cchan->host;
+ struct s3c24xx_txd *txd;
+ struct s3c24xx_sg *dsg;
+ int src_mod, dest_mod;
+
+ dev_dbg(&s3cdma->pdev->dev, "prepare memcpy of %d bytes from %s\n",
+ len, s3cchan->name);
+
+ if ((len & S3C24XX_DCON_TC_MASK) != len) {
+ dev_err(&s3cdma->pdev->dev, "memcpy size %d to large\n", len);
+ return NULL;
+ }
+
+ txd = s3c24xx_dma_get_txd();
+ if (!txd)
+ return NULL;
+
+ dsg = kzalloc(sizeof(*dsg), GFP_NOWAIT);
+ if (!dsg) {
+ s3c24xx_dma_free_txd(txd);
+ return NULL;
+ }
+ list_add_tail(&dsg->node, &txd->dsg_list);
+
+ dsg->src_addr = src;
+ dsg->dst_addr = dest;
+ dsg->len = len;
+
+ /*
+ * Determine a suitable transfer width.
+ * The DMA controller cannot fetch/store information which is not
+ * naturally aligned on the bus, i.e., a 4 byte fetch must start at
+ * an address divisible by 4 - more generally addr % width must be 0.
+ */
+ src_mod = src % 4;
+ dest_mod = dest % 4;
+ switch (len % 4) {
+ case 0:
+ txd->width = (src_mod == 0 && dest_mod == 0) ? 4 : 1;
+ break;
+ case 2:
+ txd->width = ((src_mod == 2 || src_mod == 0) &&
+ (dest_mod == 2 || dest_mod == 0)) ? 2 : 1;
+ break;
+ default:
+ txd->width = 1;
+ break;
+ }
+
+ txd->disrcc = S3C24XX_DISRCC_LOC_AHB | S3C24XX_DISRCC_INC_INCREMENT;
+ txd->didstc = S3C24XX_DIDSTC_LOC_AHB | S3C24XX_DIDSTC_INC_INCREMENT;
+ txd->dcon |= S3C24XX_DCON_DEMAND | S3C24XX_DCON_SYNC_HCLK |
+ S3C24XX_DCON_SERV_WHOLE;
+
+ return vchan_tx_prep(&s3cchan->vc, &txd->vd, flags);
+}
+
+static struct dma_async_tx_descriptor *s3c24xx_dma_prep_slave_sg(
+ struct dma_chan *chan, struct scatterlist *sgl,
+ unsigned int sg_len, enum dma_transfer_direction direction,
+ unsigned long flags, void *context)
+{
+ struct s3c24xx_dma_chan *s3cchan = to_s3c24xx_dma_chan(chan);
+ struct s3c24xx_dma_engine *s3cdma = s3cchan->host;
+ const struct s3c24xx_dma_platdata *pdata = s3cdma->pdata;
+ struct s3c24xx_dma_channel *cdata = &pdata->channels[s3cchan->id];
+ struct s3c24xx_txd *txd;
+ struct s3c24xx_sg *dsg;
+ struct scatterlist *sg;
+ dma_addr_t slave_addr;
+ u32 hwcfg = 0;
+ int tmp;
+
+ dev_dbg(&s3cdma->pdev->dev, "prepare transaction of %d bytes from %s\n",
+ sg_dma_len(sgl), s3cchan->name);
+
+ txd = s3c24xx_dma_get_txd();
+ if (!txd)
+ return NULL;
+
+ if (cdata->handshake)
+ txd->dcon |= S3C24XX_DCON_HANDSHAKE;
+
+ switch (cdata->bus) {
+ case S3C24XX_DMA_APB:
+ txd->dcon |= S3C24XX_DCON_SYNC_PCLK;
+ hwcfg |= S3C24XX_DISRCC_LOC_APB;
+ break;
+ case S3C24XX_DMA_AHB:
+ txd->dcon |= S3C24XX_DCON_SYNC_HCLK;
+ hwcfg |= S3C24XX_DISRCC_LOC_AHB;
+ break;
+ }
+
+ /*
+ * Always assume our peripheral desintation is a fixed
+ * address in memory.
+ */
+ hwcfg |= S3C24XX_DISRCC_INC_FIXED;
+
+ /*
+ * Individual dma operations are requested by the slave,
+ * so serve only single atomic operations (S3C24XX_DCON_SERV_SINGLE).
+ */
+ txd->dcon |= S3C24XX_DCON_SERV_SINGLE;
+
+ if (direction == DMA_MEM_TO_DEV) {
+ txd->disrcc = S3C24XX_DISRCC_LOC_AHB |
+ S3C24XX_DISRCC_INC_INCREMENT;
+ txd->didstc = hwcfg;
+ slave_addr = s3cchan->cfg.dst_addr;
+ txd->width = s3cchan->cfg.dst_addr_width;
+ } else if (direction == DMA_DEV_TO_MEM) {
+ txd->disrcc = hwcfg;
+ txd->didstc = S3C24XX_DIDSTC_LOC_AHB |
+ S3C24XX_DIDSTC_INC_INCREMENT;
+ slave_addr = s3cchan->cfg.src_addr;
+ txd->width = s3cchan->cfg.src_addr_width;
+ } else {
+ s3c24xx_dma_free_txd(txd);
+ dev_err(&s3cdma->pdev->dev,
+ "direction %d unsupported\n", direction);
+ return NULL;
+ }
+
+ for_each_sg(sgl, sg, sg_len, tmp) {
+ dsg = kzalloc(sizeof(*dsg), GFP_NOWAIT);
+ if (!dsg) {
+ s3c24xx_dma_free_txd(txd);
+ return NULL;
+ }
+ list_add_tail(&dsg->node, &txd->dsg_list);
+
+ dsg->len = sg_dma_len(sg);
+ if (direction == DMA_MEM_TO_DEV) {
+ dsg->src_addr = sg_dma_address(sg);
+ dsg->dst_addr = slave_addr;
+ } else { /* DMA_DEV_TO_MEM */
+ dsg->src_addr = slave_addr;
+ dsg->dst_addr = sg_dma_address(sg);
+ }
+ break;
+ }
+
+ return vchan_tx_prep(&s3cchan->vc, &txd->vd, flags);
+}
+
+/*
+ * Slave transactions callback to the slave device to allow
+ * synchronization of slave DMA signals with the DMAC enable
+ */
+static void s3c24xx_dma_issue_pending(struct dma_chan *chan)
+{
+ struct s3c24xx_dma_chan *s3cchan = to_s3c24xx_dma_chan(chan);
+ unsigned long flags;
+
+ spin_lock_irqsave(&s3cchan->vc.lock, flags);
+ if (vchan_issue_pending(&s3cchan->vc)) {
+ if (!s3cchan->phy && s3cchan->state != S3C24XX_DMA_CHAN_WAITING)
+ s3c24xx_dma_phy_alloc_and_start(s3cchan);
+ }
+ spin_unlock_irqrestore(&s3cchan->vc.lock, flags);
+}
+
+/*
+ * Bringup and teardown
+ */
+
+/*
+ * Initialise the DMAC memcpy/slave channels.
+ * Make a local wrapper to hold required data
+ */
+static int s3c24xx_dma_init_virtual_channels(struct s3c24xx_dma_engine *s3cdma,
+ struct dma_device *dmadev, unsigned int channels, bool slave)
+{
+ struct s3c24xx_dma_chan *chan;
+ int i;
+
+ INIT_LIST_HEAD(&dmadev->channels);
+
+ /*
+ * Register as many many memcpy as we have physical channels,
+ * we won't always be able to use all but the code will have
+ * to cope with that situation.
+ */
+ for (i = 0; i < channels; i++) {
+ chan = devm_kzalloc(dmadev->dev, sizeof(*chan), GFP_KERNEL);
+ if (!chan) {
+ dev_err(dmadev->dev,
+ "%s no memory for channel\n", __func__);
+ return -ENOMEM;
+ }
+
+ chan->id = i;
+ chan->host = s3cdma;
+ chan->state = S3C24XX_DMA_CHAN_IDLE;
+
+ if (slave) {
+ chan->slave = true;
+ chan->name = kasprintf(GFP_KERNEL, "slave%d", i);
+ if (!chan->name)
+ return -ENOMEM;
+ } else {
+ chan->name = kasprintf(GFP_KERNEL, "memcpy%d", i);
+ if (!chan->name)
+ return -ENOMEM;
+ }
+ dev_dbg(dmadev->dev,
+ "initialize virtual channel \"%s\"\n",
+ chan->name);
+
+ chan->vc.desc_free = s3c24xx_dma_desc_free;
+ vchan_init(&chan->vc, dmadev);
+ }
+ dev_info(dmadev->dev, "initialized %d virtual %s channels\n",
+ i, slave ? "slave" : "memcpy");
+ return i;
+}
+
+static void s3c24xx_dma_free_virtual_channels(struct dma_device *dmadev)
+{
+ struct s3c24xx_dma_chan *chan = NULL;
+ struct s3c24xx_dma_chan *next;
+
+ list_for_each_entry_safe(chan,
+ next, &dmadev->channels, vc.chan.device_node)
+ list_del(&chan->vc.chan.device_node);
+}
+
+/* s3c2410, s3c2440 and s3c2442 have a 0x40 stride without separate clocks */
+static struct soc_data soc_s3c2410 = {
+ .stride = 0x40,
+ .has_reqsel = false,
+ .has_clocks = false,
+};
+
+/* s3c2412 and s3c2413 have a 0x40 stride and dmareqsel mechanism */
+static struct soc_data soc_s3c2412 = {
+ .stride = 0x40,
+ .has_reqsel = true,
+ .has_clocks = true,
+};
+
+/* s3c2443 and following have a 0x100 stride and dmareqsel mechanism */
+static struct soc_data soc_s3c2443 = {
+ .stride = 0x100,
+ .has_reqsel = true,
+ .has_clocks = true,
+};
+
+static struct platform_device_id s3c24xx_dma_driver_ids[] = {
+ {
+ .name = "s3c2410-dma",
+ .driver_data = (kernel_ulong_t)&soc_s3c2410,
+ }, {
+ .name = "s3c2412-dma",
+ .driver_data = (kernel_ulong_t)&soc_s3c2412,
+ }, {
+ .name = "s3c2443-dma",
+ .driver_data = (kernel_ulong_t)&soc_s3c2443,
+ },
+ { },
+};
+
+static struct soc_data *s3c24xx_dma_get_soc_data(struct platform_device *pdev)
+{
+ return (struct soc_data *)
+ platform_get_device_id(pdev)->driver_data;
+}
+
+static int s3c24xx_dma_probe(struct platform_device *pdev)
+{
+ const struct s3c24xx_dma_platdata *pdata = dev_get_platdata(&pdev->dev);
+ struct s3c24xx_dma_engine *s3cdma;
+ struct soc_data *sdata;
+ struct resource *res;
+ int ret;
+ int i;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "platform data missing\n");
+ return -ENODEV;
+ }
+
+ /* Basic sanity check */
+ if (pdata->num_phy_channels > MAX_DMA_CHANNELS) {
+ dev_err(&pdev->dev, "to many dma channels %d, max %d\n",
+ pdata->num_phy_channels, MAX_DMA_CHANNELS);
+ return -EINVAL;
+ }
+
+ sdata = s3c24xx_dma_get_soc_data(pdev);
+ if (!sdata)
+ return -EINVAL;
+
+ s3cdma = devm_kzalloc(&pdev->dev, sizeof(*s3cdma), GFP_KERNEL);
+ if (!s3cdma)
+ return -ENOMEM;
+
+ s3cdma->pdev = pdev;
+ s3cdma->pdata = pdata;
+ s3cdma->sdata = sdata;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ s3cdma->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(s3cdma->base))
+ return PTR_ERR(s3cdma->base);
+
+ s3cdma->phy_chans = devm_kzalloc(&pdev->dev,
+ sizeof(struct s3c24xx_dma_phy) *
+ pdata->num_phy_channels,
+ GFP_KERNEL);
+ if (!s3cdma->phy_chans)
+ return -ENOMEM;
+
+ /* aquire irqs and clocks for all physical channels */
+ for (i = 0; i < pdata->num_phy_channels; i++) {
+ struct s3c24xx_dma_phy *phy = &s3cdma->phy_chans[i];
+ char clk_name[6];
+
+ phy->id = i;
+ phy->base = s3cdma->base + (i * sdata->stride);
+ phy->host = s3cdma;
+
+ phy->irq = platform_get_irq(pdev, i);
+ if (phy->irq < 0) {
+ dev_err(&pdev->dev, "failed to get irq %d, err %d\n",
+ i, phy->irq);
+ continue;
+ }
+
+ ret = devm_request_irq(&pdev->dev, phy->irq, s3c24xx_dma_irq,
+ 0, pdev->name, phy);
+ if (ret) {
+ dev_err(&pdev->dev, "Unable to request irq for channel %d, error %d\n",
+ i, ret);
+ continue;
+ }
+
+ if (sdata->has_clocks) {
+ sprintf(clk_name, "dma.%d", i);
+ phy->clk = devm_clk_get(&pdev->dev, clk_name);
+ if (IS_ERR(phy->clk) && sdata->has_clocks) {
+ dev_err(&pdev->dev, "unable to aquire clock for channel %d, error %lu",
+ i, PTR_ERR(phy->clk));
+ continue;
+ }
+
+ ret = clk_prepare(phy->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "clock for phy %d failed, error %d\n",
+ i, ret);
+ continue;
+ }
+ }
+
+ spin_lock_init(&phy->lock);
+ phy->valid = true;
+
+ dev_dbg(&pdev->dev, "physical channel %d is %s\n",
+ i, s3c24xx_dma_phy_busy(phy) ? "BUSY" : "FREE");
+ }
+
+ /* Initialize memcpy engine */
+ dma_cap_set(DMA_MEMCPY, s3cdma->memcpy.cap_mask);
+ dma_cap_set(DMA_PRIVATE, s3cdma->memcpy.cap_mask);
+ s3cdma->memcpy.dev = &pdev->dev;
+ s3cdma->memcpy.device_alloc_chan_resources =
+ s3c24xx_dma_alloc_chan_resources;
+ s3cdma->memcpy.device_free_chan_resources =
+ s3c24xx_dma_free_chan_resources;
+ s3cdma->memcpy.device_prep_dma_memcpy = s3c24xx_dma_prep_memcpy;
+ s3cdma->memcpy.device_tx_status = s3c24xx_dma_tx_status;
+ s3cdma->memcpy.device_issue_pending = s3c24xx_dma_issue_pending;
+ s3cdma->memcpy.device_control = s3c24xx_dma_control;
+
+ /* Initialize slave engine for SoC internal dedicated peripherals */
+ dma_cap_set(DMA_SLAVE, s3cdma->slave.cap_mask);
+ dma_cap_set(DMA_PRIVATE, s3cdma->slave.cap_mask);
+ s3cdma->slave.dev = &pdev->dev;
+ s3cdma->slave.device_alloc_chan_resources =
+ s3c24xx_dma_alloc_chan_resources;
+ s3cdma->slave.device_free_chan_resources =
+ s3c24xx_dma_free_chan_resources;
+ s3cdma->slave.device_tx_status = s3c24xx_dma_tx_status;
+ s3cdma->slave.device_issue_pending = s3c24xx_dma_issue_pending;
+ s3cdma->slave.device_prep_slave_sg = s3c24xx_dma_prep_slave_sg;
+ s3cdma->slave.device_control = s3c24xx_dma_control;
+
+ /* Register as many memcpy channels as there are physical channels */
+ ret = s3c24xx_dma_init_virtual_channels(s3cdma, &s3cdma->memcpy,
+ pdata->num_phy_channels, false);
+ if (ret <= 0) {
+ dev_warn(&pdev->dev,
+ "%s failed to enumerate memcpy channels - %d\n",
+ __func__, ret);
+ goto err_memcpy;
+ }
+
+ /* Register slave channels */
+ ret = s3c24xx_dma_init_virtual_channels(s3cdma, &s3cdma->slave,
+ pdata->num_channels, true);
+ if (ret <= 0) {
+ dev_warn(&pdev->dev,
+ "%s failed to enumerate slave channels - %d\n",
+ __func__, ret);
+ goto err_slave;
+ }
+
+ ret = dma_async_device_register(&s3cdma->memcpy);
+ if (ret) {
+ dev_warn(&pdev->dev,
+ "%s failed to register memcpy as an async device - %d\n",
+ __func__, ret);
+ goto err_memcpy_reg;
+ }
+
+ ret = dma_async_device_register(&s3cdma->slave);
+ if (ret) {
+ dev_warn(&pdev->dev,
+ "%s failed to register slave as an async device - %d\n",
+ __func__, ret);
+ goto err_slave_reg;
+ }
+
+ platform_set_drvdata(pdev, s3cdma);
+ dev_info(&pdev->dev, "Loaded dma driver with %d physical channels\n",
+ pdata->num_phy_channels);
+
+ return 0;
+
+err_slave_reg:
+ dma_async_device_unregister(&s3cdma->memcpy);
+err_memcpy_reg:
+ s3c24xx_dma_free_virtual_channels(&s3cdma->slave);
+err_slave:
+ s3c24xx_dma_free_virtual_channels(&s3cdma->memcpy);
+err_memcpy:
+ if (sdata->has_clocks)
+ for (i = 0; i < pdata->num_phy_channels; i++) {
+ struct s3c24xx_dma_phy *phy = &s3cdma->phy_chans[i];
+ if (phy->valid)
+ clk_unprepare(phy->clk);
+ }
+
+ return ret;
+}
+
+static int s3c24xx_dma_remove(struct platform_device *pdev)
+{
+ const struct s3c24xx_dma_platdata *pdata = dev_get_platdata(&pdev->dev);
+ struct s3c24xx_dma_engine *s3cdma = platform_get_drvdata(pdev);
+ struct soc_data *sdata = s3c24xx_dma_get_soc_data(pdev);
+ int i;
+
+ dma_async_device_unregister(&s3cdma->slave);
+ dma_async_device_unregister(&s3cdma->memcpy);
+
+ s3c24xx_dma_free_virtual_channels(&s3cdma->slave);
+ s3c24xx_dma_free_virtual_channels(&s3cdma->memcpy);
+
+ if (sdata->has_clocks)
+ for (i = 0; i < pdata->num_phy_channels; i++) {
+ struct s3c24xx_dma_phy *phy = &s3cdma->phy_chans[i];
+ if (phy->valid)
+ clk_unprepare(phy->clk);
+ }
+
+ return 0;
+}
+
+static struct platform_driver s3c24xx_dma_driver = {
+ .driver = {
+ .name = "s3c24xx-dma",
+ .owner = THIS_MODULE,
+ },
+ .id_table = s3c24xx_dma_driver_ids,
+ .probe = s3c24xx_dma_probe,
+ .remove = s3c24xx_dma_remove,
+};
+
+module_platform_driver(s3c24xx_dma_driver);
+
+bool s3c24xx_dma_filter(struct dma_chan *chan, void *param)
+{
+ struct s3c24xx_dma_chan *s3cchan;
+
+ if (chan->device->dev->driver != &s3c24xx_dma_driver.driver)
+ return false;
+
+ s3cchan = to_s3c24xx_dma_chan(chan);
+
+ return s3cchan->id == (int)param;
+}
+EXPORT_SYMBOL(s3c24xx_dma_filter);
+
+MODULE_DESCRIPTION("S3C24XX DMA Driver");
+MODULE_AUTHOR("Heiko Stuebner");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/dma/sa11x0-dma.c b/drivers/dma/sa11x0-dma.c
index 461a91a..ab26d46 100644
--- a/drivers/dma/sa11x0-dma.c
+++ b/drivers/dma/sa11x0-dma.c
@@ -436,7 +436,7 @@ static enum dma_status sa11x0_dma_tx_status(struct dma_chan *chan,
enum dma_status ret;
ret = dma_cookie_status(&c->vc.chan, cookie, state);
- if (ret == DMA_SUCCESS)
+ if (ret == DMA_COMPLETE)
return ret;
if (!state)
diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
index d94ab59..2e7b394 100644
--- a/drivers/dma/sh/shdma-base.c
+++ b/drivers/dma/sh/shdma-base.c
@@ -724,7 +724,7 @@ static enum dma_status shdma_tx_status(struct dma_chan *chan,
* If we don't find cookie on the queue, it has been aborted and we have
* to report error
*/
- if (status != DMA_SUCCESS) {
+ if (status != DMA_COMPLETE) {
struct shdma_desc *sdesc;
status = DMA_ERROR;
list_for_each_entry(sdesc, &schan->ld_queue, node)
diff --git a/drivers/dma/sh/shdmac.c b/drivers/dma/sh/shdmac.c
index 1069e88..0d765c0 100644
--- a/drivers/dma/sh/shdmac.c
+++ b/drivers/dma/sh/shdmac.c
@@ -685,7 +685,7 @@ MODULE_DEVICE_TABLE(of, sh_dmae_of_match);
static int sh_dmae_probe(struct platform_device *pdev)
{
const struct sh_dmae_pdata *pdata;
- unsigned long irqflags = IRQF_DISABLED,
+ unsigned long irqflags = 0,
chan_flag[SH_DMAE_MAX_CHANNELS] = {};
int errirq, chan_irq[SH_DMAE_MAX_CHANNELS];
int err, i, irq_cnt = 0, irqres = 0, irq_cap = 0;
@@ -838,7 +838,7 @@ static int sh_dmae_probe(struct platform_device *pdev)
IORESOURCE_IRQ_SHAREABLE)
chan_flag[irq_cnt] = IRQF_SHARED;
else
- chan_flag[irq_cnt] = IRQF_DISABLED;
+ chan_flag[irq_cnt] = 0;
dev_dbg(&pdev->dev,
"Found IRQ %d for channel %d\n",
i, irq_cnt);
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 20f22ec..b940340 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -14,6 +14,7 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/log2.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/err.h>
@@ -2628,7 +2629,7 @@ static enum dma_status d40_tx_status(struct dma_chan *chan,
}
ret = dma_cookie_status(chan, cookie, txstate);
- if (ret != DMA_SUCCESS)
+ if (ret != DMA_COMPLETE)
dma_set_residue(txstate, stedma40_residue(chan));
if (d40_is_paused(d40c))
@@ -2798,8 +2799,8 @@ static int d40_set_runtime_config(struct dma_chan *chan,
src_addr_width > DMA_SLAVE_BUSWIDTH_8_BYTES ||
dst_addr_width <= DMA_SLAVE_BUSWIDTH_UNDEFINED ||
dst_addr_width > DMA_SLAVE_BUSWIDTH_8_BYTES ||
- ((src_addr_width > 1) && (src_addr_width & 1)) ||
- ((dst_addr_width > 1) && (dst_addr_width & 1)))
+ !is_power_of_2(src_addr_width) ||
+ !is_power_of_2(dst_addr_width))
return -EINVAL;
cfg->src_info.data_width = src_addr_width;
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
index 5d4986e..73654e3 100644
--- a/drivers/dma/tegra20-apb-dma.c
+++ b/drivers/dma/tegra20-apb-dma.c
@@ -570,7 +570,7 @@ static void handle_once_dma_done(struct tegra_dma_channel *tdc,
list_del(&sgreq->node);
if (sgreq->last_sg) {
- dma_desc->dma_status = DMA_SUCCESS;
+ dma_desc->dma_status = DMA_COMPLETE;
dma_cookie_complete(&dma_desc->txd);
if (!dma_desc->cb_count)
list_add_tail(&dma_desc->cb_node, &tdc->cb_desc);
@@ -768,7 +768,7 @@ static enum dma_status tegra_dma_tx_status(struct dma_chan *dc,
unsigned int residual;
ret = dma_cookie_status(dc, cookie, txstate);
- if (ret == DMA_SUCCESS)
+ if (ret == DMA_COMPLETE)
return ret;
spin_lock_irqsave(&tdc->lock, flags);
@@ -1018,7 +1018,7 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg(
return &dma_desc->txd;
}
-struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic(
+static struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic(
struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_len,
size_t period_len, enum dma_transfer_direction direction,
unsigned long flags, void *context)
diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c
index 28af214..4506a7b 100644
--- a/drivers/dma/timb_dma.c
+++ b/drivers/dma/timb_dma.c
@@ -154,38 +154,6 @@ static bool __td_dma_done_ack(struct timb_dma_chan *td_chan)
return done;
}
-static void __td_unmap_desc(struct timb_dma_chan *td_chan, const u8 *dma_desc,
- bool single)
-{
- dma_addr_t addr;
- int len;
-
- addr = (dma_desc[7] << 24) | (dma_desc[6] << 16) | (dma_desc[5] << 8) |
- dma_desc[4];
-
- len = (dma_desc[3] << 8) | dma_desc[2];
-
- if (single)
- dma_unmap_single(chan2dev(&td_chan->chan), addr, len,
- DMA_TO_DEVICE);
- else
- dma_unmap_page(chan2dev(&td_chan->chan), addr, len,
- DMA_TO_DEVICE);
-}
-
-static void __td_unmap_descs(struct timb_dma_desc *td_desc, bool single)
-{
- struct timb_dma_chan *td_chan = container_of(td_desc->txd.chan,
- struct timb_dma_chan, chan);
- u8 *descs;
-
- for (descs = td_desc->desc_list; ; descs += TIMB_DMA_DESC_SIZE) {
- __td_unmap_desc(td_chan, descs, single);
- if (descs[0] & 0x02)
- break;
- }
-}
-
static int td_fill_desc(struct timb_dma_chan *td_chan, u8 *dma_desc,
struct scatterlist *sg, bool last)
{
@@ -293,10 +261,7 @@ static void __td_finish(struct timb_dma_chan *td_chan)
list_move(&td_desc->desc_node, &td_chan->free_list);
- if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP))
- __td_unmap_descs(td_desc,
- txd->flags & DMA_COMPL_SRC_UNMAP_SINGLE);
-
+ dma_descriptor_unmap(txd);
/*
* The API requires that no submissions are done from a
* callback, so we don't need to drop the lock here
diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c
index 71e8e77..bae6c29 100644
--- a/drivers/dma/txx9dmac.c
+++ b/drivers/dma/txx9dmac.c
@@ -419,30 +419,7 @@ txx9dmac_descriptor_complete(struct txx9dmac_chan *dc,
list_splice_init(&desc->tx_list, &dc->free_list);
list_move(&desc->desc_node, &dc->free_list);
- if (!ds) {
- dma_addr_t dmaaddr;
- if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
- dmaaddr = is_dmac64(dc) ?
- desc->hwdesc.DAR : desc->hwdesc32.DAR;
- if (txd->flags & DMA_COMPL_DEST_UNMAP_SINGLE)
- dma_unmap_single(chan2parent(&dc->chan),
- dmaaddr, desc->len, DMA_FROM_DEVICE);
- else
- dma_unmap_page(chan2parent(&dc->chan),
- dmaaddr, desc->len, DMA_FROM_DEVICE);
- }
- if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
- dmaaddr = is_dmac64(dc) ?
- desc->hwdesc.SAR : desc->hwdesc32.SAR;
- if (txd->flags & DMA_COMPL_SRC_UNMAP_SINGLE)
- dma_unmap_single(chan2parent(&dc->chan),
- dmaaddr, desc->len, DMA_TO_DEVICE);
- else
- dma_unmap_page(chan2parent(&dc->chan),
- dmaaddr, desc->len, DMA_TO_DEVICE);
- }
- }
-
+ dma_descriptor_unmap(txd);
/*
* The API requires that no submissions are done from a
* callback, so we don't need to drop the lock here
@@ -962,8 +939,8 @@ txx9dmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
enum dma_status ret;
ret = dma_cookie_status(chan, cookie, txstate);
- if (ret == DMA_SUCCESS)
- return DMA_SUCCESS;
+ if (ret == DMA_COMPLETE)
+ return DMA_COMPLETE;
spin_lock_bh(&dc->lock);
txx9dmac_scan_descriptors(dc);
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 878f090..53bf163 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -254,10 +254,10 @@ config EDAC_SBRIDGE
config EDAC_MPC85XX
tristate "Freescale MPC83xx / MPC85xx"
- depends on EDAC_MM_EDAC && FSL_SOC && (PPC_83xx || PPC_85xx)
+ depends on EDAC_MM_EDAC && FSL_SOC
help
Support for error detection and correction on the Freescale
- MPC8349, MPC8560, MPC8540, MPC8548
+ MPC8349, MPC8560, MPC8540, MPC8548, T4240
config EDAC_MV64X60
tristate "Marvell MV64x60"
diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c
index dd370f9..ce1e97f 100644
--- a/drivers/edac/edac_pci.c
+++ b/drivers/edac/edac_pci.c
@@ -392,6 +392,7 @@ EXPORT_SYMBOL_GPL(edac_pci_add_device);
struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev)
{
struct edac_pci_ctl_info *pci;
+ int op_state;
edac_dbg(0, "\n");
@@ -406,6 +407,8 @@ struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev)
return NULL;
}
+ op_state = pci->op_state;
+
pci->op_state = OP_OFFLINE;
del_edac_pci_from_global_list(pci);
@@ -413,7 +416,8 @@ struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev)
mutex_unlock(&edac_pci_ctls_mutex);
/* stop the workq timer */
- edac_pci_workq_teardown(pci);
+ if (op_state == OP_RUNNING_POLL)
+ edac_pci_workq_teardown(pci);
edac_printk(KERN_INFO, EDAC_PCI,
"Removed device %d for %s %s: DEV %s\n",
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index 3eb32f6..939ea18 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -1,5 +1,6 @@
/*
* Freescale MPC85xx Memory Controller kenel module
+ * Copyright (c) 2013 Freescale Semiconductor, Inc.
*
* Author: Dave Jiang <djiang@mvista.com>
*
@@ -196,6 +197,42 @@ static void mpc85xx_pci_check(struct edac_pci_ctl_info *pci)
edac_pci_handle_npe(pci, pci->ctl_name);
}
+static void mpc85xx_pcie_check(struct edac_pci_ctl_info *pci)
+{
+ struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
+ u32 err_detect;
+
+ err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR);
+
+ pr_err("PCIE error(s) detected\n");
+ pr_err("PCIE ERR_DR register: 0x%08x\n", err_detect);
+ pr_err("PCIE ERR_CAP_STAT register: 0x%08x\n",
+ in_be32(pdata->pci_vbase + MPC85XX_PCI_GAS_TIMR));
+ pr_err("PCIE ERR_CAP_R0 register: 0x%08x\n",
+ in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R0));
+ pr_err("PCIE ERR_CAP_R1 register: 0x%08x\n",
+ in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R1));
+ pr_err("PCIE ERR_CAP_R2 register: 0x%08x\n",
+ in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R2));
+ pr_err("PCIE ERR_CAP_R3 register: 0x%08x\n",
+ in_be32(pdata->pci_vbase + MPC85XX_PCIE_ERR_CAP_R3));
+
+ /* clear error bits */
+ out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect);
+}
+
+static int mpc85xx_pcie_find_capability(struct device_node *np)
+{
+ struct pci_controller *hose;
+
+ if (!np)
+ return -EINVAL;
+
+ hose = pci_find_hose_for_OF_device(np);
+
+ return early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP);
+}
+
static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
{
struct edac_pci_ctl_info *pci = dev_id;
@@ -207,7 +244,10 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
if (!err_detect)
return IRQ_NONE;
- mpc85xx_pci_check(pci);
+ if (pdata->is_pcie)
+ mpc85xx_pcie_check(pci);
+ else
+ mpc85xx_pci_check(pci);
return IRQ_HANDLED;
}
@@ -239,14 +279,23 @@ int mpc85xx_pci_err_probe(struct platform_device *op)
pdata = pci->pvt_info;
pdata->name = "mpc85xx_pci_err";
pdata->irq = NO_IRQ;
+ if (mpc85xx_pcie_find_capability(op->dev.of_node) > 0)
+ pdata->is_pcie = 1;
+ else
+ pdata->is_pcie = 0;
+
dev_set_drvdata(&op->dev, pci);
pci->dev = &op->dev;
pci->mod_name = EDAC_MOD_STR;
pci->ctl_name = pdata->name;
pci->dev_name = dev_name(&op->dev);
- if (edac_op_state == EDAC_OPSTATE_POLL)
- pci->edac_check = mpc85xx_pci_check;
+ if (edac_op_state == EDAC_OPSTATE_POLL) {
+ if (pdata->is_pcie)
+ pci->edac_check = mpc85xx_pcie_check;
+ else
+ pci->edac_check = mpc85xx_pci_check;
+ }
pdata->edac_idx = edac_pci_idx++;
@@ -275,16 +324,26 @@ int mpc85xx_pci_err_probe(struct platform_device *op)
goto err;
}
- orig_pci_err_cap_dr =
- in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR);
+ if (pdata->is_pcie) {
+ orig_pci_err_cap_dr =
+ in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR);
+ out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR, ~0);
+ orig_pci_err_en =
+ in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN);
+ out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, 0);
+ } else {
+ orig_pci_err_cap_dr =
+ in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR);
- /* PCI master abort is expected during config cycles */
- out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR, 0x40);
+ /* PCI master abort is expected during config cycles */
+ out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR, 0x40);
- orig_pci_err_en = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN);
+ orig_pci_err_en =
+ in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN);
- /* disable master abort reporting */
- out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0x40);
+ /* disable master abort reporting */
+ out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0x40);
+ }
/* clear error bits */
out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, ~0);
@@ -297,7 +356,8 @@ int mpc85xx_pci_err_probe(struct platform_device *op)
if (edac_op_state == EDAC_OPSTATE_INT) {
pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
res = devm_request_irq(&op->dev, pdata->irq,
- mpc85xx_pci_isr, IRQF_DISABLED,
+ mpc85xx_pci_isr,
+ IRQF_DISABLED | IRQF_SHARED,
"[EDAC] PCI err", pci);
if (res < 0) {
printk(KERN_ERR
@@ -312,6 +372,19 @@ int mpc85xx_pci_err_probe(struct platform_device *op)
pdata->irq);
}
+ if (pdata->is_pcie) {
+ /* enable all pcie error interrupt & error detect
+ * except invalid PEX_CONFIG_ADDR/PEX_CONFIG_DATA
+ * access interrupt generation enable bit and
+ * invalid PEX_CONFIG_ADDR/PEX_CONFIG_DATA access
+ * detection enable bit.
+ */
+ out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0
+ & ~PEX_ERR_ICCAIE_EN_BIT);
+ out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR, 0
+ | PEX_ERR_ICCAD_DISR_BIT);
+ }
+
devres_remove_group(&op->dev, mpc85xx_pci_err_probe);
edac_dbg(3, "success\n");
printk(KERN_INFO EDAC_MOD_STR " PCI err registered\n");
@@ -579,7 +652,7 @@ static int mpc85xx_l2_err_probe(struct platform_device *op)
if (edac_op_state == EDAC_OPSTATE_INT) {
pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
res = devm_request_irq(&op->dev, pdata->irq,
- mpc85xx_l2_isr, IRQF_DISABLED,
+ mpc85xx_l2_isr, IRQF_SHARED,
"[EDAC] L2 err", edac_dev);
if (res < 0) {
printk(KERN_ERR
@@ -773,6 +846,8 @@ static void sbe_ecc_decode(u32 cap_high, u32 cap_low, u32 cap_ecc,
}
}
+#define make64(high, low) (((u64)(high) << 32) | (low))
+
static void mpc85xx_mc_check(struct mem_ctl_info *mci)
{
struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
@@ -780,7 +855,7 @@ static void mpc85xx_mc_check(struct mem_ctl_info *mci)
u32 bus_width;
u32 err_detect;
u32 syndrome;
- u32 err_addr;
+ u64 err_addr;
u32 pfn;
int row_index;
u32 cap_high;
@@ -811,7 +886,9 @@ static void mpc85xx_mc_check(struct mem_ctl_info *mci)
else
syndrome &= 0xffff;
- err_addr = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_ADDRESS);
+ err_addr = make64(
+ in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_EXT_ADDRESS),
+ in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_ADDRESS));
pfn = err_addr >> PAGE_SHIFT;
for (row_index = 0; row_index < mci->nr_csrows; row_index++) {
@@ -848,7 +925,7 @@ static void mpc85xx_mc_check(struct mem_ctl_info *mci)
mpc85xx_mc_printk(mci, KERN_ERR,
"Captured Data / ECC:\t%#8.8x_%08x / %#2.2x\n",
cap_high, cap_low, syndrome);
- mpc85xx_mc_printk(mci, KERN_ERR, "Err addr: %#8.8x\n", err_addr);
+ mpc85xx_mc_printk(mci, KERN_ERR, "Err addr: %#8.8llx\n", err_addr);
mpc85xx_mc_printk(mci, KERN_ERR, "PFN: %#8.8x\n", pfn);
/* we are out of range */
diff --git a/drivers/edac/mpc85xx_edac.h b/drivers/edac/mpc85xx_edac.h
index 932016f..ffc1b23 100644
--- a/drivers/edac/mpc85xx_edac.h
+++ b/drivers/edac/mpc85xx_edac.h
@@ -43,6 +43,7 @@
#define MPC85XX_MC_ERR_INT_EN 0x0e48
#define MPC85XX_MC_CAPTURE_ATRIBUTES 0x0e4c
#define MPC85XX_MC_CAPTURE_ADDRESS 0x0e50
+#define MPC85XX_MC_CAPTURE_EXT_ADDRESS 0x0e54
#define MPC85XX_MC_ERR_SBE 0x0e58
#define DSC_MEM_EN 0x80000000
@@ -134,13 +135,19 @@
#define MPC85XX_PCI_ERR_DR 0x0000
#define MPC85XX_PCI_ERR_CAP_DR 0x0004
#define MPC85XX_PCI_ERR_EN 0x0008
+#define PEX_ERR_ICCAIE_EN_BIT 0x00020000
#define MPC85XX_PCI_ERR_ATTRIB 0x000c
#define MPC85XX_PCI_ERR_ADDR 0x0010
+#define PEX_ERR_ICCAD_DISR_BIT 0x00020000
#define MPC85XX_PCI_ERR_EXT_ADDR 0x0014
#define MPC85XX_PCI_ERR_DL 0x0018
#define MPC85XX_PCI_ERR_DH 0x001c
#define MPC85XX_PCI_GAS_TIMR 0x0020
#define MPC85XX_PCI_PCIX_TIMR 0x0024
+#define MPC85XX_PCIE_ERR_CAP_R0 0x0028
+#define MPC85XX_PCIE_ERR_CAP_R1 0x002c
+#define MPC85XX_PCIE_ERR_CAP_R2 0x0030
+#define MPC85XX_PCIE_ERR_CAP_R3 0x0034
struct mpc85xx_mc_pdata {
char *name;
@@ -158,6 +165,7 @@ struct mpc85xx_l2_pdata {
struct mpc85xx_pci_pdata {
char *name;
+ char is_pcie;
int edac_idx;
void __iomem *pci_vbase;
int irq;
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index b80c768..55dce43 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -106,7 +106,12 @@ static irqreturn_t mpc_i2c_isr(int irq, void *dev_id)
static void mpc_i2c_fixup(struct mpc_i2c *i2c)
{
int k;
- u32 delay_val = 1000000 / i2c->real_clk + 1;
+ u32 delay_val;
+#ifdef CONFIG_PPC_85xx
+ delay_val = 65536 / (fsl_get_sys_freq() / 2000000); /* 64K cycle */
+#else
+ delay_val = 1000000 / i2c->real_clk + 1;
+#endif
if (delay_val < 2)
delay_val = 2;
@@ -116,7 +121,11 @@ static void mpc_i2c_fixup(struct mpc_i2c *i2c)
writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN);
udelay(delay_val);
writeccr(i2c, CCR_MEN);
+#ifdef CONFIG_PPC_85xx
+ udelay(delay_val);
+#else
udelay(delay_val << 1);
+#endif
}
}
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index c880eba..3466972 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -17,6 +17,18 @@ config OF_IOMMU
def_bool y
depends on OF
+config DUMMY_IOMMU
+ bool "Dummy IOMMU support for VFIO (UNSAFE)"
+ select IOMMU_API
+ help
+ WARNING: Dummy IOMMU driver, only for platforms that don't have a
+ hardware IOMMU. This option does allow you to use VFIO device
+ assignment, but does not provide DMA memory isolation.
+ Only use this if you trust all VFIO users completely.
+ The dummy vfio iommu driver can be enabled via
+ /sys/kernel/vfio_iommu_dummy/enable_iommu_dummy attribute.
+ If unsure, say N.
+
config FSL_PAMU
bool "Freescale IOMMU support"
depends on PPC_E500MC
diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c
index cba0498..e7b3d45 100644
--- a/drivers/iommu/fsl_pamu.c
+++ b/drivers/iommu/fsl_pamu.c
@@ -32,6 +32,7 @@
#include <asm/io.h>
#include <asm/bitops.h>
#include <asm/fsl_guts.h>
+#include <asm/fsl_kibo.h>
#include "fsl_pamu.h"
@@ -81,6 +82,13 @@ static const struct of_device_id l3_device_ids[] = {
{}
};
+/* Table for matching FMAN rx port compatible */
+static const struct of_device_id fman_device_ids[] = {
+ { .compatible = "fsl,fman-port-10g-rx", },
+ { .compatible = "fsl,fman-port-1g-rx", },
+ {}
+};
+
/* maximum subwindows permitted per liodn */
static u32 max_subwindow_count;
@@ -170,10 +178,10 @@ int pamu_disable_liodn(int liodn)
static unsigned int map_addrspace_size_to_wse(phys_addr_t addrspace_size)
{
/* Bug if not a power of 2 */
- BUG_ON(!is_power_of_2(addrspace_size));
+ BUG_ON((addrspace_size & (addrspace_size - 1)));
/* window size is 2^(WSE+1) bytes */
- return __ffs(addrspace_size) - 1;
+ return fls64(addrspace_size) - 1 - 1;
}
/* Derive the PAACE window count encoding for the subwindow count */
@@ -253,6 +261,42 @@ static unsigned long pamu_get_fspi_and_allocate(u32 subwin_cnt)
return (spaace_addr - (unsigned long)spaact) / (sizeof(struct paace));
}
+/*
+ * Default PPAACE settings for an LIODN.
+ */
+static void setup_default_ppaace(struct paace *ppaace)
+{
+ pamu_init_ppaace(ppaace);
+ /* window size is 2^(WSE+1) bytes */
+ set_bf(ppaace->addr_bitfields, PPAACE_AF_WSE, 35);
+ ppaace->wbah = 0;
+ set_bf(ppaace->addr_bitfields, PPAACE_AF_WBAL, 0);
+ set_bf(ppaace->impl_attr, PAACE_IA_ATM,
+ PAACE_ATM_NO_XLATE);
+ set_bf(ppaace->addr_bitfields, PAACE_AF_AP,
+ PAACE_AP_PERMS_ALL);
+}
+
+/* Reset the PAACE entry to the default state */
+void enable_default_dma_window(int liodn)
+{
+ struct paace *ppaace;
+
+ ppaace = pamu_get_ppaace(liodn);
+ if (!ppaace) {
+ pr_debug("Invalid liodn entry\n");
+ return;
+ }
+
+ memset(ppaace, 0, sizeof(struct paace));
+
+ setup_default_ppaace(ppaace);
+
+ /* Ensure that all other stores to the ppaace complete first */
+ mb();
+ pamu_enable_liodn(liodn);
+}
+
/* Release the subwindows reserved for a particular LIODN */
void pamu_free_subwins(int liodn)
{
@@ -274,16 +318,16 @@ void pamu_free_subwins(int liodn)
}
/*
- * Function used for updating stash destination for the coressponding
+ * Function used for updating a specifc PAACE field for the coressponding
* LIODN.
*/
-int pamu_update_paace_stash(int liodn, u32 subwin, u32 value)
+int pamu_update_paace_field(int liodn, u32 subwin, int field, u32 value)
{
struct paace *paace;
paace = pamu_get_ppaace(liodn);
if (!paace) {
- pr_debug("Invalid liodn entry\n");
+ pr_err("Invalid liodn entry\n");
return -ENOENT;
}
if (subwin) {
@@ -292,8 +336,19 @@ int pamu_update_paace_stash(int liodn, u32 subwin, u32 value)
return -ENOENT;
}
}
- set_bf(paace->impl_attr, PAACE_IA_CID, value);
+ switch (field) {
+ case PAACE_STASH_FIELD:
+ set_bf(paace->impl_attr, PAACE_IA_CID, value);
+ break;
+ case PAACE_OMI_FIELD:
+ set_bf(paace->impl_attr, PAACE_IA_OTM, PAACE_OTM_INDEXED);
+ paace->op_encode.index_ot.omi = value;
+ break;
+ default:
+ pr_debug("Invalid field, can't update\n");
+ return -EINVAL;
+ }
mb();
return 0;
@@ -351,7 +406,7 @@ int pamu_config_ppaace(int liodn, phys_addr_t win_addr, phys_addr_t win_size,
struct paace *ppaace;
unsigned long fspi;
- if (!is_power_of_2(win_size) || win_size < PAMU_PAGE_SIZE) {
+ if ((win_size & (win_size - 1)) || win_size < PAMU_PAGE_SIZE) {
pr_debug("window size too small or not a power of two %llx\n", win_size);
return -EINVAL;
}
@@ -464,7 +519,7 @@ int pamu_config_spaace(int liodn, u32 subwin_cnt, u32 subwin,
return -ENOENT;
}
- if (!is_power_of_2(subwin_size) || subwin_size < PAMU_PAGE_SIZE) {
+ if ((subwin_size & (subwin_size - 1)) || subwin_size < PAMU_PAGE_SIZE) {
pr_debug("subwindow size out of range, or not a power of 2\n");
return -EINVAL;
}
@@ -523,6 +578,63 @@ void get_ome_index(u32 *omi_index, struct device *dev)
*omi_index = OMI_QMAN_PRIV;
}
+/*
+ * We get the stash id programmed by SDOS from the shared
+ * cluster L2 l2csr1 register.
+ */
+static u32 get_dsp_l2_stash_id(u32 vcpu)
+{
+ const u32 *prop;
+ struct device_node *node;
+ struct ccsr_cluster_l2 *l2cache_regs;
+ u32 stash_id;
+
+ for_each_compatible_node(node, NULL, "fsl,sc3900") {
+ prop = of_get_property(node, "reg", 0);
+ if (!prop) {
+ pr_err("missing reg property in dsp cpu node %s\n",
+ node->full_name);
+ of_node_put(node);
+ return ~(u32)0;
+ }
+
+ if (*prop != vcpu)
+ continue;
+
+ prop = of_get_property(node, "next-level-cache", 0);
+ if (!prop) {
+ pr_err("missing next level cache property in dsp cpu %s\n",
+ node->full_name);
+ of_node_put(node);
+ return ~(u32)0;
+ }
+ of_node_put(node);
+
+ node = of_find_node_by_phandle(*prop);
+ if (!node) {
+ pr_err("Invalid node for cache hierarchy %s\n",
+ node->full_name);
+ return ~(u32)0;
+ }
+
+ l2cache_regs = of_iomap(node, 0);
+ if (!l2cache_regs) {
+ pr_err("failed to map cluster l2 cache registers %s\n",
+ node->full_name);
+ of_node_put(node);
+ return ~(u32)0;
+ }
+
+ stash_id = in_be32(&l2cache_regs->l2csr1) &
+ CLUSTER_L2_STASH_MASK;
+ of_node_put(node);
+ iounmap(l2cache_regs);
+
+ return stash_id;
+ }
+ return ~(u32)0;
+}
+
/**
* get_stash_id - Returns stash destination id corresponding to a
* cache type and vcpu.
@@ -540,6 +652,11 @@ u32 get_stash_id(u32 stash_dest_hint, u32 vcpu)
int len, found = 0;
int i;
+ /* check for DSP L2 cache */
+ if (stash_dest_hint == PAMU_ATTR_CACHE_DSP_L2) {
+ return get_dsp_l2_stash_id(vcpu);
+ }
+
/* Fastpath, exit early if L3/CPC cache is target for stashing */
if (stash_dest_hint == PAMU_ATTR_CACHE_L3) {
node = of_find_matching_node(NULL, l3_device_ids);
@@ -607,13 +724,16 @@ found_cpu_node:
#define QMAN_PAACE 1
#define QMAN_PORTAL_PAACE 2
#define BMAN_PAACE 3
+#define FMAN_PAACE 4
+#define PMAN_PAACE 5
/**
- * Setup operation mapping and stash destinations for QMAN and QMAN portal.
+ * Setup operation mapping and stash destinations for DPAA (QMAN, QMAN portal
+ * FMAN, BMAN) and PMAN.
* Memory accesses to QMAN and BMAN private memory need not be coherent, so
* clear the PAACE entry coherency attribute for them.
*/
-static void setup_qbman_paace(struct paace *ppaace, int paace_type)
+static void setup_dpaa_paace(struct paace *ppaace, int paace_type)
{
switch (paace_type) {
case QMAN_PAACE:
@@ -634,6 +754,17 @@ static void setup_qbman_paace(struct paace *ppaace, int paace_type)
set_bf(ppaace->domain_attr.to_host.coherency_required, PAACE_DA_HOST_CR,
0);
break;
+ case FMAN_PAACE:
+ set_bf(ppaace->impl_attr, PAACE_IA_OTM, PAACE_OTM_INDEXED);
+ ppaace->op_encode.index_ot.omi = OMI_FMAN;
+ /*Set frame stashing for the L3 cache */
+ set_bf(ppaace->impl_attr, PAACE_IA_CID,
+ get_stash_id(PAMU_ATTR_CACHE_L3, 0));
+ break;
+ case PMAN_PAACE:
+ set_bf(ppaace->impl_attr, PAACE_IA_OTM, PAACE_OTM_INDEXED);
+ ppaace->op_encode.index_ot.omi = OMI_PMAN;
+ break;
}
}
@@ -674,6 +805,18 @@ static void __init setup_omt(struct ome *omt)
ome = &omt[OMI_CAAM];
ome->moe[IOE_READ_IDX] = EOE_VALID | EOE_READI;
ome->moe[IOE_WRITE_IDX] = EOE_VALID | EOE_WRITE;
+
+ /* Configure OMI_PMAN */
+ ome = &omt[OMI_PMAN];
+ ome->moe[IOE_DIRECT0_IDX] = EOE_LDEC | EOE_VALID;
+ ome->moe[IOE_DIRECT1_IDX] = EOE_LDEC | EOE_VALID;
+
+ /* Configure OMI_DSP */
+ ome = &omt[OMI_DSP];
+ ome->moe[IOE_READ_IDX] = EOE_VALID | EOE_RWNITC;
+ ome->moe[IOE_EREAD0_IDX] = EOE_VALID | EOE_RWNITC;
+ ome->moe[IOE_WRITE_IDX] = EOE_VALID | EOE_WWSAO;
+ ome->moe[IOE_EWRITE0_IDX] = EOE_VALID | EOE_WWSAO;
}
/*
@@ -701,6 +844,16 @@ int setup_one_pamu(unsigned long pamu_reg_base, unsigned long pamu_reg_size,
pamu_regs = (struct pamu_mmap_regs *)
(pamu_reg_base + PAMU_MMAP_REGS_BASE);
+ /*
+ * As per PAMU errata A-005982, writing the PAACT and SPAACT
+ * base address registers wouldn't invalidate the corresponding
+ * caches if the OMT cache is disabled. The workaround is to
+ * enable the OMT cache before setting the base registers.
+ * This can be done without actually enabling PAMU.
+ */
+
+ out_be32(pc, PAMU_PC_OCE);
+
/* set up pointers to corenet control blocks */
out_be32(&pamu_regs->ppbah, upper_32_bits(ppaact_phys));
@@ -733,6 +886,28 @@ int setup_one_pamu(unsigned long pamu_reg_base, unsigned long pamu_reg_size,
return 0;
}
+/*
+ * Primarily to Enable LIODNs which u-boot didn't update in the device tree.
+ */
+static void __init enable_remaining_liodns(void)
+{
+ int liodn;
+ struct paace *ppaace;
+
+ for (liodn = 0; liodn < PAACE_NUMBER_ENTRIES; liodn++) {
+ ppaace = pamu_get_ppaace(liodn);
+ if (!get_bf(ppaace->addr_bitfields, PAACE_AF_V)) {
+ setup_default_ppaace(ppaace);
+ /*
+ * Ensure that all stores to the ppaace
+ * complete first.
+ */
+ mb();
+ pamu_enable_liodn(liodn);
+ }
+ }
+}
+
/* Enable all device LIODNS */
static void __init setup_liodns(void)
{
@@ -752,25 +927,34 @@ static void __init setup_liodns(void)
continue;
}
ppaace = pamu_get_ppaace(liodn);
- pamu_init_ppaace(ppaace);
- /* window size is 2^(WSE+1) bytes */
- set_bf(ppaace->addr_bitfields, PPAACE_AF_WSE, 35);
- ppaace->wbah = 0;
- set_bf(ppaace->addr_bitfields, PPAACE_AF_WBAL, 0);
- set_bf(ppaace->impl_attr, PAACE_IA_ATM,
- PAACE_ATM_NO_XLATE);
- set_bf(ppaace->addr_bitfields, PAACE_AF_AP,
- PAACE_AP_PERMS_ALL);
+ setup_default_ppaace(ppaace);
+
if (of_device_is_compatible(node, "fsl,qman-portal"))
- setup_qbman_paace(ppaace, QMAN_PORTAL_PAACE);
+ setup_dpaa_paace(ppaace, QMAN_PORTAL_PAACE);
if (of_device_is_compatible(node, "fsl,qman"))
- setup_qbman_paace(ppaace, QMAN_PAACE);
+ setup_dpaa_paace(ppaace, QMAN_PAACE);
if (of_device_is_compatible(node, "fsl,bman"))
- setup_qbman_paace(ppaace, BMAN_PAACE);
+ setup_dpaa_paace(ppaace, BMAN_PAACE);
+ if (of_device_is_compatible(node, "fsl,pman"))
+ setup_dpaa_paace(ppaace, PMAN_PAACE);
+#ifdef CONFIG_FSL_FMAN_CPC_STASH
+ if (of_match_node(fman_device_ids, node))
+ setup_dpaa_paace(ppaace, FMAN_PAACE);
+#endif
mb();
pamu_enable_liodn(liodn);
}
}
+
+ /*
+ * Currently u-boot doesn't fixup LIODNs for cases
+ * where a frame is passed to a hardware block from
+ * another hardware block. For example, frame can
+ * be passed from FMAN rx port to SEC or RMAN. So,
+ * as a work around we enable all the possible LIODN
+ * values.
+ */
+ enable_remaining_liodns();
}
irqreturn_t pamu_av_isr(int irq, void *arg)
diff --git a/drivers/iommu/fsl_pamu.h b/drivers/iommu/fsl_pamu.h
index 8fc1a12..89940fa 100644
--- a/drivers/iommu/fsl_pamu.h
+++ b/drivers/iommu/fsl_pamu.h
@@ -321,6 +321,12 @@ struct paace {
u32 reserved[8]; /* not currently implemented */
};
+enum paace_field {
+ PAACE_STASH_FIELD,
+ PAACE_OMI_FIELD,
+ PAACE_FIELD_MAX,
+};
+
/* OME : Operation mapping entry
* MOE : Mapped Operation Encodings
* The operation mapping table is table containing operation mapping entries (OME).
@@ -403,8 +409,9 @@ int pamu_config_spaace(int liodn, u32 subwin_cnt, u32 subwin_addr,
u32 get_stash_id(u32 stash_dest_hint, u32 vcpu);
void get_ome_index(u32 *omi_index, struct device *dev);
-int pamu_update_paace_stash(int liodn, u32 subwin, u32 value);
+int pamu_update_paace_field(int liodn, u32 subwin, int field, u32 value);
int pamu_disable_spaace(int liodn, u32 subwin);
u32 pamu_get_max_subwin_cnt(void);
+void enable_default_dma_window(int liodn);
#endif /* __FSL_PAMU_H */
diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c
index c857c30..e62048b 100644
--- a/drivers/iommu/fsl_pamu_domain.c
+++ b/drivers/iommu/fsl_pamu_domain.c
@@ -123,10 +123,10 @@ static int map_subwins(int liodn, struct fsl_dma_domain *dma_domain)
spin_lock_irqsave(&iommu_lock, flags);
ret = pamu_config_spaace(liodn, dma_domain->win_cnt, i,
sub_win_ptr[i].size,
- ~(u32)0,
+ sub_win_ptr[i].omi,
rpn,
dma_domain->snoop_id,
- dma_domain->stash_id,
+ sub_win_ptr[i].stash_id,
(i > 0) ? 1 : 0,
sub_win_ptr[i].prot);
spin_unlock_irqrestore(&iommu_lock, flags);
@@ -151,9 +151,9 @@ static int map_win(int liodn, struct fsl_dma_domain *dma_domain)
spin_lock_irqsave(&iommu_lock, flags);
ret = pamu_config_ppaace(liodn, wnd_addr,
wnd->size,
- ~(u32)0,
+ wnd->omi,
wnd->paddr >> PAMU_PAGE_SHIFT,
- dma_domain->snoop_id, dma_domain->stash_id,
+ dma_domain->snoop_id, wnd->stash_id,
0, wnd->prot);
spin_unlock_irqrestore(&iommu_lock, flags);
if (ret)
@@ -184,10 +184,10 @@ static int update_liodn(int liodn, struct fsl_dma_domain *dma_domain, u32 wnd_nr
if (dma_domain->win_cnt > 1) {
ret = pamu_config_spaace(liodn, dma_domain->win_cnt, wnd_nr,
wnd->size,
- ~(u32)0,
+ wnd->omi,
wnd->paddr >> PAMU_PAGE_SHIFT,
dma_domain->snoop_id,
- dma_domain->stash_id,
+ wnd->stash_id,
(wnd_nr > 0) ? 1 : 0,
wnd->prot);
if (ret)
@@ -199,9 +199,9 @@ static int update_liodn(int liodn, struct fsl_dma_domain *dma_domain, u32 wnd_nr
ret = pamu_config_ppaace(liodn, wnd_addr,
wnd->size,
- ~(u32)0,
+ wnd->omi,
wnd->paddr >> PAMU_PAGE_SHIFT,
- dma_domain->snoop_id, dma_domain->stash_id,
+ dma_domain->snoop_id, wnd->stash_id,
0, wnd->prot);
if (ret)
pr_debug("Window reconfiguration failed for liodn %d\n", liodn);
@@ -212,29 +212,56 @@ static int update_liodn(int liodn, struct fsl_dma_domain *dma_domain, u32 wnd_nr
return ret;
}
-static int update_liodn_stash(int liodn, struct fsl_dma_domain *dma_domain,
- u32 val)
+struct pamu_attr_info {
+ u32 window;
+ int field;
+ u32 value;
+};
+
+static int update_liodn_attr(int liodn, struct fsl_dma_domain *dma_domain,
+ struct pamu_attr_info *attr_info)
{
int ret = 0, i;
- unsigned long flags;
- spin_lock_irqsave(&iommu_lock, flags);
- if (!dma_domain->win_arr) {
- pr_debug("Windows not configured, stash destination update failed for liodn %d\n", liodn);
- spin_unlock_irqrestore(&iommu_lock, flags);
- return -EINVAL;
- }
+ spin_lock(&iommu_lock);
- for (i = 0; i < dma_domain->win_cnt; i++) {
- ret = pamu_update_paace_stash(liodn, i, val);
- if (ret) {
- pr_debug("Failed to update SPAACE %d field for liodn %d\n ", i, liodn);
- spin_unlock_irqrestore(&iommu_lock, flags);
- return ret;
+
+ if (~attr_info->window == 0) {
+ for (i = 0; i < dma_domain->win_cnt; i++) {
+ ret = pamu_update_paace_field(liodn, i,
+ attr_info->field,
+ attr_info->value);
+ if (ret)
+ break;
}
- }
+ } else
+ ret = pamu_update_paace_field(liodn, attr_info->window,
+ attr_info->field,
+ attr_info->value);
- spin_unlock_irqrestore(&iommu_lock, flags);
+ spin_unlock(&iommu_lock);
+
+ return ret;
+}
+
+/*
+ * Update attribute for all LIODNs associated with the domain
+ *
+ */
+static int update_domain_attr(struct fsl_dma_domain *dma_domain,
+ struct pamu_attr_info *attr_info)
+{
+ struct device_domain_info *info;
+ int ret = 0;
+
+ if (!list_empty(&dma_domain->devices)) {
+ list_for_each_entry(info, &dma_domain->devices, link) {
+ ret = update_liodn_attr(info->liodn, dma_domain,
+ attr_info);
+ if (ret)
+ break;
+ }
+ }
return ret;
}
@@ -266,7 +293,7 @@ static int pamu_set_liodn(int liodn, struct device *dev,
if (!ret)
ret = pamu_config_ppaace(liodn, window_addr, window_size, omi_index,
0, dma_domain->snoop_id,
- dma_domain->stash_id, win_cnt, 0);
+ ~(u32)0, win_cnt, 0);
spin_unlock_irqrestore(&iommu_lock, flags);
if (ret) {
pr_debug("PAMU PAACE configuration failed for liodn %d, win_cnt =%d\n", liodn, win_cnt);
@@ -282,7 +309,7 @@ static int pamu_set_liodn(int liodn, struct device *dev,
ret = pamu_config_spaace(liodn, win_cnt, i,
subwin_size, omi_index,
0, dma_domain->snoop_id,
- dma_domain->stash_id,
+ ~(u32)0,
0, 0);
spin_unlock_irqrestore(&iommu_lock, flags);
if (ret) {
@@ -301,7 +328,7 @@ static int check_size(u64 size, dma_addr_t iova)
* Size must be a power of two and at least be equal
* to PAMU page size.
*/
- if (!is_power_of_2(size) || size < PAMU_PAGE_SIZE) {
+ if ((size & (size - 1)) || size < PAMU_PAGE_SIZE) {
pr_debug("%s: size too small or not a power of two\n", __func__);
return -EINVAL;
}
@@ -323,7 +350,6 @@ static struct fsl_dma_domain *iommu_alloc_dma_domain(void)
if (!domain)
return NULL;
- domain->stash_id = ~(u32)0;
domain->snoop_id = ~(u32)0;
domain->win_cnt = pamu_get_max_subwin_cnt();
domain->geom_size = 0;
@@ -340,17 +366,63 @@ static inline struct device_domain_info *find_domain(struct device *dev)
return dev->archdata.iommu_domain;
}
+/* Disable device DMA capability and enable default DMA window */
+static void disable_device_dma(struct device_domain_info *info,
+ int enable_dma_window)
+{
+#ifdef CONFIG_PCI
+ if (info->dev->bus == &pci_bus_type) {
+ struct pci_dev *pdev = NULL;
+ u16 pci_command;
+
+ pdev = to_pci_dev(info->dev);
+ pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
+ /* disable device bus master capability */
+ if (pci_command & PCI_COMMAND_MASTER) {
+ pci_command &= ~PCI_COMMAND_MASTER;
+ pci_write_config_word(pdev, PCI_COMMAND, pci_command);
+ }
+ }
+#endif
+
+ if (enable_dma_window)
+ enable_default_dma_window(info->liodn);
+}
+
+static int check_for_shared_liodn(struct device_domain_info *info)
+{
+ struct device_domain_info *tmp;
+
+ /*
+ * Sanity check, to ensure that this is not a
+ * shared LIODN. In case of a PCIe controller
+ * it's possible that all PCIe devices share
+ * the same LIODN.
+ */
+ list_for_each_entry(tmp, &info->domain->devices, link) {
+ if (info->liodn == tmp->liodn)
+ return 1;
+ }
+
+ return 0;
+}
+
static void remove_device_ref(struct device_domain_info *info, u32 win_cnt)
{
unsigned long flags;
+ int enable_dma_window = 0;
list_del(&info->link);
spin_lock_irqsave(&iommu_lock, flags);
- if (win_cnt > 1)
- pamu_free_subwins(info->liodn);
- pamu_disable_liodn(info->liodn);
+ if (!check_for_shared_liodn(info)) {
+ if (win_cnt > 1)
+ pamu_free_subwins(info->liodn);
+ pamu_disable_liodn(info->liodn);
+ enable_dma_window = 1;
+ }
spin_unlock_irqrestore(&iommu_lock, flags);
spin_lock_irqsave(&device_domain_lock, flags);
+ disable_device_dma(info, enable_dma_window);
info->dev->archdata.iommu_domain = NULL;
kmem_cache_free(iommu_devinfo_cache, info);
spin_unlock_irqrestore(&device_domain_lock, flags);
@@ -475,21 +547,6 @@ static int pamu_set_domain_geometry(struct fsl_dma_domain *dma_domain,
return ret;
}
-/* Update stash destination for all LIODNs associated with the domain */
-static int update_domain_stash(struct fsl_dma_domain *dma_domain, u32 val)
-{
- struct device_domain_info *info;
- int ret = 0;
-
- list_for_each_entry(info, &dma_domain->devices, link) {
- ret = update_liodn_stash(info->liodn, dma_domain, val);
- if (ret)
- break;
- }
-
- return ret;
-}
-
/* Update domain mappings for all LIODNs associated with the domain */
static int update_domain_mapping(struct fsl_dma_domain *dma_domain, u32 wnd_nr)
{
@@ -677,21 +734,15 @@ static int handle_attach_device(struct fsl_dma_domain *dma_domain,
return ret;
}
-static int fsl_pamu_attach_device(struct iommu_domain *domain,
- struct device *dev)
+static struct device *get_dma_device(struct device *dev)
{
- struct fsl_dma_domain *dma_domain = domain->priv;
- const u32 *liodn;
- u32 liodn_cnt;
- int len, ret = 0;
- struct pci_dev *pdev = NULL;
- struct pci_controller *pci_ctl;
+ struct device *dma_dev = dev;
+#ifdef CONFIG_PCI
- /*
- * Use LIODN of the PCI controller while attaching a
- * PCI device.
- */
if (dev->bus == &pci_bus_type) {
+ struct pci_controller *pci_ctl;
+ struct pci_dev *pdev;
+
pdev = to_pci_dev(dev);
pci_ctl = pci_bus_to_host(pdev->bus);
/*
@@ -699,17 +750,31 @@ static int fsl_pamu_attach_device(struct iommu_domain *domain,
* so we can get the LIODN programmed by
* u-boot.
*/
- dev = pci_ctl->parent;
+ dma_dev = pci_ctl->parent;
}
+#endif
+ return dma_dev;
+}
+
+static int fsl_pamu_attach_device(struct iommu_domain *domain,
+ struct device *dev)
+{
+ struct fsl_dma_domain *dma_domain = domain->priv;
+ struct device *dma_dev;
+ const u32 *liodn;
+ u32 liodn_cnt;
+ int len, ret = 0;
- liodn = of_get_property(dev->of_node, "fsl,liodn", &len);
+ dma_dev = get_dma_device(dev);
+
+ liodn = of_get_property(dma_dev->of_node, "fsl,liodn", &len);
if (liodn) {
liodn_cnt = len / sizeof(u32);
ret = handle_attach_device(dma_domain, dev,
liodn, liodn_cnt);
} else {
pr_debug("missing fsl,liodn property at %s\n",
- dev->of_node->full_name);
+ dma_dev->of_node->full_name);
ret = -EINVAL;
}
@@ -720,32 +785,18 @@ static void fsl_pamu_detach_device(struct iommu_domain *domain,
struct device *dev)
{
struct fsl_dma_domain *dma_domain = domain->priv;
+ struct device *dma_dev;
const u32 *prop;
int len;
- struct pci_dev *pdev = NULL;
- struct pci_controller *pci_ctl;
- /*
- * Use LIODN of the PCI controller while detaching a
- * PCI device.
- */
- if (dev->bus == &pci_bus_type) {
- pdev = to_pci_dev(dev);
- pci_ctl = pci_bus_to_host(pdev->bus);
- /*
- * make dev point to pci controller device
- * so we can get the LIODN programmed by
- * u-boot.
- */
- dev = pci_ctl->parent;
- }
+ dma_dev = get_dma_device(dev);
- prop = of_get_property(dev->of_node, "fsl,liodn", &len);
+ prop = of_get_property(dma_dev->of_node, "fsl,liodn", &len);
if (prop)
detach_device(dev, dma_domain);
else
pr_debug("missing fsl,liodn property at %s\n",
- dev->of_node->full_name);
+ dma_dev->of_node->full_name);
}
static int configure_domain_geometry(struct iommu_domain *domain, void *data)
@@ -783,27 +834,101 @@ static int configure_domain_geometry(struct iommu_domain *domain, void *data)
return 0;
}
+static inline int check_attr_window(u32 wnd, struct fsl_dma_domain *dma_domain)
+{
+ return (~wnd != 0) && (wnd >= dma_domain->win_cnt);
+}
+
+/* Set the domain operation mapping attribute */
+static int configure_domain_op_map(struct fsl_dma_domain *dma_domain,
+ void *data)
+{
+ struct dma_window *wnd;
+ unsigned long flags;
+ struct pamu_attr_info attr_info;
+ int ret, i;
+ struct pamu_omi_attribute *omi_attr = data;
+
+ spin_lock_irqsave(&dma_domain->domain_lock, flags);
+
+ if (!dma_domain->win_arr) {
+ pr_err("Number of windows not configured\n");
+ spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
+ return -ENODEV;
+ }
+
+ if (omi_attr->omi >= OMI_MAX ||
+ check_attr_window(omi_attr->window, dma_domain)) {
+ pr_err("Invalid operation mapping index\n");
+ spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
+ return -EINVAL;
+ }
+
+ if (~omi_attr->window == 0) {
+ wnd = &dma_domain->win_arr[0];
+ for (i = 0; i < dma_domain->win_cnt; i++)
+ wnd[i].omi = omi_attr->omi;
+ } else {
+ wnd = &dma_domain->win_arr[omi_attr->window];
+ wnd->omi = omi_attr->omi;
+ }
+
+ attr_info.window = omi_attr->window;
+ attr_info.field = PAACE_OMI_FIELD;
+ attr_info.value = omi_attr->omi;
+ ret = update_domain_attr(dma_domain, &attr_info);
+
+ spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
+
+ return ret;
+}
+
/* Set the domain stash attribute */
static int configure_domain_stash(struct fsl_dma_domain *dma_domain, void *data)
{
struct pamu_stash_attribute *stash_attr = data;
+ struct dma_window *wnd;
unsigned long flags;
- int ret;
+ u32 stash_id;
+ int ret, i;
+ struct pamu_attr_info attr_info;
spin_lock_irqsave(&dma_domain->domain_lock, flags);
- memcpy(&dma_domain->dma_stash, stash_attr,
- sizeof(struct pamu_stash_attribute));
+ if (!dma_domain->win_arr) {
+ pr_err("Number of windows not configured\n");
+ spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
+ return -ENODEV;
+ }
- dma_domain->stash_id = get_stash_id(stash_attr->cache,
+ stash_id = get_stash_id(stash_attr->cache,
stash_attr->cpu);
- if (dma_domain->stash_id == ~(u32)0) {
- pr_debug("Invalid stash attributes\n");
+ if ((~stash_id == 0) ||
+ check_attr_window(stash_attr->window, dma_domain)) {
+ pr_err("Invalid stash attributes\n");
spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
return -EINVAL;
}
- ret = update_domain_stash(dma_domain, dma_domain->stash_id);
+ if (~stash_attr->window == 0) {
+ wnd = &dma_domain->win_arr[0];
+ for (i = 0; i < dma_domain->win_cnt; i++) {
+ wnd[i].stash_id = stash_id;
+ memcpy(&wnd[i].stash_attr, stash_attr,
+ sizeof(struct pamu_stash_attribute));
+ wnd[i].stash_attr.window = i;
+ }
+ } else {
+ wnd = &dma_domain->win_arr[stash_attr->window];
+ wnd->stash_id = stash_id;
+ memcpy(&wnd->stash_attr,
+ stash_attr, sizeof(struct pamu_stash_attribute));
+ }
+
+ attr_info.window = stash_attr->window;
+ attr_info.field = PAACE_STASH_FIELD;
+ attr_info.value = stash_id;
+ ret = update_domain_attr(dma_domain, &attr_info);
spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
@@ -856,6 +981,9 @@ static int fsl_pamu_set_domain_attr(struct iommu_domain *domain,
case DOMAIN_ATTR_FSL_PAMU_ENABLE:
ret = configure_domain_dma_state(dma_domain, *(int *)data);
break;
+ case DOMAIN_ATTR_FSL_PAMU_OP_MAP:
+ ret = configure_domain_op_map(dma_domain, data);
+ break;
default:
pr_debug("Unsupported attribute type\n");
ret = -EINVAL;
@@ -873,16 +1001,37 @@ static int fsl_pamu_get_domain_attr(struct iommu_domain *domain,
switch (attr_type) {
- case DOMAIN_ATTR_FSL_PAMU_STASH:
- memcpy((struct pamu_stash_attribute *) data, &dma_domain->dma_stash,
- sizeof(struct pamu_stash_attribute));
- break;
case DOMAIN_ATTR_FSL_PAMU_ENABLE:
*(int *)data = dma_domain->enabled;
break;
case DOMAIN_ATTR_FSL_PAMUV1:
*(int *)data = DOMAIN_ATTR_FSL_PAMUV1;
break;
+ case DOMAIN_ATTR_FSL_PAMU_STASH: {
+ struct pamu_stash_attribute *stash_attr = data;
+ struct dma_window *wnd;
+
+ if (stash_attr->window >= dma_domain->win_cnt ||
+ ~stash_attr->window == 0)
+ return -EINVAL;
+
+ wnd = &dma_domain->win_arr[stash_attr->window];
+ memcpy(stash_attr, &wnd->stash_attr,
+ sizeof(struct pamu_stash_attribute));
+ break;
+ }
+ case DOMAIN_ATTR_FSL_PAMU_OP_MAP: {
+ struct pamu_omi_attribute *omi_attr = data;
+ struct dma_window *wnd;
+
+ if (omi_attr->window >= dma_domain->win_cnt ||
+ ~omi_attr->window == 0)
+ return -EINVAL;
+
+ wnd = &dma_domain->win_arr[omi_attr->window];
+ omi_attr->omi = wnd->omi;
+ break;
+ }
default:
pr_debug("Unsupported attribute type\n");
ret = -EINVAL;
@@ -905,6 +1054,7 @@ static struct iommu_group *get_device_iommu_group(struct device *dev)
return group;
}
+#ifdef CONFIG_PCI
static bool check_pci_ctl_endpt_part(struct pci_controller *pci_ctl)
{
u32 version;
@@ -945,13 +1095,18 @@ static struct iommu_group *get_shared_pci_device_group(struct pci_dev *pdev)
return NULL;
}
-static struct iommu_group *get_pci_device_group(struct pci_dev *pdev)
+static struct iommu_group *get_pci_device_group(struct device *dev)
{
struct pci_controller *pci_ctl;
bool pci_endpt_partioning;
struct iommu_group *group = NULL;
- struct pci_dev *bridge, *dma_pdev = NULL;
+ struct pci_dev *bridge, *pdev;
+ struct pci_dev *dma_pdev = NULL;
+ pdev = to_pci_dev(dev);
+ /* Don't create device groups for virtual PCI bridges */
+ if (pdev->subordinate)
+ return NULL;
pci_ctl = pci_bus_to_host(pdev->bus);
pci_endpt_partioning = check_pci_ctl_endpt_part(pci_ctl);
/* We can partition PCIe devices so assign device group to the device */
@@ -1044,11 +1199,11 @@ root_bus:
return group;
}
+#endif
static int fsl_pamu_add_device(struct device *dev)
{
struct iommu_group *group = NULL;
- struct pci_dev *pdev;
const u32 *prop;
int ret, len;
@@ -1056,19 +1211,15 @@ static int fsl_pamu_add_device(struct device *dev)
* For platform devices we allocate a separate group for
* each of the devices.
*/
- if (dev->bus == &pci_bus_type) {
- pdev = to_pci_dev(dev);
- /* Don't create device groups for virtual PCI bridges */
- if (pdev->subordinate)
- return 0;
-
- group = get_pci_device_group(pdev);
-
- } else {
+ if (dev->bus == &platform_bus_type) {
prop = of_get_property(dev->of_node, "fsl,liodn", &len);
if (prop)
group = get_device_iommu_group(dev);
}
+#ifdef CONFIG_PCI
+ else
+ group = get_pci_device_group(dev);
+#endif
if (!group || IS_ERR(group))
return PTR_ERR(group);
@@ -1084,6 +1235,16 @@ static void fsl_pamu_remove_device(struct device *dev)
iommu_group_remove_device(dev);
}
+static void dma_domain_init_windows(struct fsl_dma_domain *dma_domain)
+{
+ int i;
+
+ for (i = 0; i < dma_domain->win_cnt; i++) {
+ dma_domain->win_arr[i].stash_id = ~(u32)0;
+ dma_domain->win_arr[i].omi = ~(u32)0;
+ }
+}
+
static int fsl_pamu_set_windows(struct iommu_domain *domain, u32 w_count)
{
struct fsl_dma_domain *dma_domain = domain->priv;
@@ -1127,6 +1288,7 @@ static int fsl_pamu_set_windows(struct iommu_domain *domain, u32 w_count)
return -ENOMEM;
}
dma_domain->win_cnt = w_count;
+ dma_domain_init_windows(dma_domain);
}
spin_unlock_irqrestore(&dma_domain->domain_lock, flags);
@@ -1166,7 +1328,9 @@ int pamu_domain_init()
return ret;
bus_set_iommu(&platform_bus_type, &fsl_pamu_ops);
+#ifdef CONFIG_PCI
bus_set_iommu(&pci_bus_type, &fsl_pamu_ops);
+#endif
return ret;
}
diff --git a/drivers/iommu/fsl_pamu_domain.h b/drivers/iommu/fsl_pamu_domain.h
index c90293f..60a8452 100644
--- a/drivers/iommu/fsl_pamu_domain.h
+++ b/drivers/iommu/fsl_pamu_domain.h
@@ -22,10 +22,13 @@
#include "fsl_pamu.h"
struct dma_window {
- phys_addr_t paddr;
- u64 size;
- int valid;
- int prot;
+ phys_addr_t paddr;
+ u64 size;
+ int valid;
+ int prot;
+ struct pamu_stash_attribute stash_attr;
+ u32 stash_id;
+ u32 omi;
};
struct fsl_dma_domain {
@@ -67,9 +70,6 @@ struct fsl_dma_domain {
*/
int mapped;
int enabled;
- /* stash_id obtained from the stash attribute details */
- u32 stash_id;
- struct pamu_stash_attribute dma_stash;
u32 snoop_id;
struct iommu_domain *iommu_domain;
spinlock_t domain_lock;
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index fbe9ca7..6ac5f50 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -696,6 +696,16 @@ void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
}
EXPORT_SYMBOL_GPL(iommu_detach_device);
+struct iommu_domain *iommu_get_dev_domain(struct device *dev)
+{
+ struct iommu_ops *ops = dev->bus->iommu_ops;
+
+ if (unlikely(ops == NULL || ops->get_dev_iommu_domain == NULL))
+ return NULL;
+
+ return ops->get_dev_iommu_domain(dev);
+}
+EXPORT_SYMBOL_GPL(iommu_get_dev_domain);
/*
* IOMMU groups are really the natrual working unit of the IOMMU, but
* the IOMMU API works on domains and devices. Bridge that gap by
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 8dacd4c..4dc11ca 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -56,7 +56,7 @@ config ATMEL_PWM
depends on HAVE_CLK
help
This option enables device driver support for the PWM channels
- on certain Atmel processors. Pulse Width Modulation is used for
+ on certain Atmel processors. Pulse Width Modulation is used for
purposes including software controlled power-efficient backlights
on LCD displays, motor control, and waveform generation.
@@ -219,6 +219,35 @@ config ENCLOSURE_SERVICES
driver (SCSI/ATA) which supports enclosures
or a SCSI enclosure device (SES) to use these services.
+config FSL_DCM
+ tristate "Freescale Data Collection Manager (DCM) driver"
+ depends on FSL_SOC
+ help
+ Inside the FPGA of some Freescale QorIQ (PowerPC) reference boards
+ is a microcontroller called the General Purpose Processor (GSMA).
+ Running on the GSMA is the Data Collection Manager (DCM), which is
+ used to periodically read and tally voltage, current, and temperature
+ measurements from the on-board sensors. You can use this feature to
+ measure power consumption while running tests, without having the
+ host CPU perform those measurements.
+
+config FSL_USDPAA
+ bool "Freescale USDPAA process driver"
+ depends on FSL_DPA
+ default y
+ help
+ This driver provides user-space access to kernel-managed
+ resource interfaces for USDPAA applications, on the assumption
+ that each process will open this device once. Specifically, this
+ device exposes functionality that would be awkward if exposed
+ via the portal devices - ie. this device exposes functionality
+ that is inherently process-wide rather than portal-specific.
+ This device is necessary for obtaining access to DMA memory and
+ for allocation of Qman and Bman resources. In short, if you wish
+ to use USDPAA applications, you need this.
+
+ If unsure, say Y.
+
config SGI_XP
tristate "Support communication between SGI SSIs"
depends on NET
@@ -354,14 +383,14 @@ config SENSORS_BH1780
will be called bh1780gli.
config SENSORS_BH1770
- tristate "BH1770GLC / SFH7770 combined ALS - Proximity sensor"
- depends on I2C
- ---help---
- Say Y here if you want to build a driver for BH1770GLC (ROHM) or
+ tristate "BH1770GLC / SFH7770 combined ALS - Proximity sensor"
+ depends on I2C
+ ---help---
+ Say Y here if you want to build a driver for BH1770GLC (ROHM) or
SFH7770 (Osram) combined ambient light and proximity sensor chip.
- To compile this driver as a module, choose M here: the
- module will be called bh1770glc. If unsure, say N here.
+ To compile this driver as a module, choose M here: the
+ module will be called bh1770glc. If unsure, say N here.
config SENSORS_APDS990X
tristate "APDS990X combined als and proximity sensors"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index c235d5b..20a9129 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -16,8 +16,8 @@ obj-$(CONFIG_BMP085_SPI) += bmp085-spi.o
obj-$(CONFIG_DUMMY_IRQ) += dummy-irq.o
obj-$(CONFIG_ICS932S401) += ics932s401.o
obj-$(CONFIG_LKDTM) += lkdtm.o
-obj-$(CONFIG_TIFM_CORE) += tifm_core.o
-obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o
+obj-$(CONFIG_TIFM_CORE) += tifm_core.o
+obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o
obj-$(CONFIG_PHANTOM) += phantom.o
obj-$(CONFIG_SENSORS_BH1780) += bh1780gli.o
obj-$(CONFIG_SENSORS_BH1770) += bh1770glc.o
@@ -53,3 +53,4 @@ obj-$(CONFIG_INTEL_MEI) += mei/
obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci/
obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lattice-ecp3-config.o
obj-$(CONFIG_SRAM) += sram.o
+obj-$(CONFIG_FSL_DCM) += fsl_dcm.o
diff --git a/drivers/misc/fsl_dcm.c b/drivers/misc/fsl_dcm.c
new file mode 100644
index 0000000..1af2800
--- /dev/null
+++ b/drivers/misc/fsl_dcm.c
@@ -0,0 +1,770 @@
+/*
+ * Freescale Data Collection Manager (DCM) device driver
+ *
+ * Copyright (C) 2011 Freescale Semiconductor, Inc.
+ * Author: Timur Tabi <timur@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.
+ *
+ * Inside the FPGA of some Freescale QorIQ (PowerPC) reference boards is a
+ * microprocessor called the General Purpose Processor (GSMA). Running on
+ * the GSMA is the Data Collection Manager (DCM), which is used to
+ * periodically read and tally voltage, current, and temperature measurements
+ * from the on-board sensors. You can use this feature to measure power
+ * consumption while running tests, without having the host CPU perform those
+ * measurements.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include "fsl_dcm.h"
+
+/*
+ * Converts a 16-bit VOUT value from the Zilker ZL6100 into a voltage value,
+ * in millivolts.
+ */
+static unsigned int voltage_from_zl6100(u16 vout)
+{
+ return (1000UL * vout) / (1 << 13);
+}
+
+/* unit is mv */
+static unsigned int voltage_from_ina220(u16 vout)
+{
+ return (vout >> 3) * 4;
+}
+
+/*
+ * Converts a 16-bit IOUT from the Texas Instruments INA220 chip into a
+ * current value, in milliamps. 'shunt' is a board-specific shunt.
+ */
+static unsigned int current_from_ina220(u16 sv, unsigned int shunt)
+{
+ unsigned long c;
+
+ /*
+ * Current = ShuntVoltage * CalibrationRegister / 4096
+ * = ShuntVoltage * 40,960,000 / shunt(uOhms) / 4096
+ * = ShuntVoltage * 10000 / shunt
+ */
+ c = sv * 10000;
+ c /= shunt;
+
+ return c;
+}
+
+/*
+ * Converts a 16-bit TOUT value from the sensor device into a temperature
+ * value, in degrees Celsius.
+ */
+static unsigned int temp_from_u16(u16 tout)
+{
+ return tout;
+}
+
+/*
+ * Write a byte to an address in SRAM
+ */
+static void write_sram(struct fsl_dcm_data *dcm, u8 offset, u8 v)
+{
+ out_8(dcm->addr, offset);
+ out_8(dcm->data, v);
+}
+
+/*
+ * Read a byte from an address in SRAM
+ */
+static u8 read_sram(struct fsl_dcm_data *dcm, u8 offset)
+{
+ out_8(dcm->addr, offset);
+
+ return in_8(dcm->data);
+}
+
+/*
+ * True TRUE if we can read/write SRAM, FALSE otherwise.
+ *
+ * If the SRAM is unavailable, it's probably because the DCM is busy with it.
+ */
+static int is_sram_available(struct fsl_dcm_data *dcm)
+{
+ u8 ack, cmd;
+
+ cmd = in_8(dcm->ocmd);
+ ack = in_8(dcm->mack);
+
+ if ((cmd & PX_OCMD_MSG) || (ack & PX_OACK_ACK)) {
+ dev_dbg(dcm->dev, "dcm is not ready (cmd=%02X mack=%02X)\n",
+ cmd, ack);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Loads and program into SRAM, then tells the DCM to run it, and then waits
+ * for it to finish.
+ */
+static int run_program(struct fsl_dcm_data *dcm, u8 addr,
+ unsigned int len, ...)
+{
+ u8 v, n;
+ va_list args;
+
+ if (addr + len > 0xff) {
+ dev_err(dcm->dev, "address/length of %u/%u is out of bounds\n",
+ addr, len);
+ return -EBUSY;
+ }
+
+ /* load the program into SRAM */
+ va_start(args, len);
+ for (n = addr; n < addr + len; n++) {
+ v = va_arg(args, int);
+ write_sram(dcm, n, v);
+ }
+ va_end(args);
+
+ /* start the DCM */
+ out_8(dcm->omsg, addr);
+ out_8(dcm->ocmd, PX_OCMD_MSG);
+
+ /* wait for ack or error */
+ v = spin_event_timeout(in_8(dcm->mack) & (PX_OACK_ERR | PX_OACK_ACK),
+ 50000, 1000);
+ if ((!v) || (v & PX_OACK_ERR)) {
+ dev_err(dcm->dev, "timeout or error waiting for start ack\n");
+ return -EBUSY;
+ }
+
+ /* 4. allow the host to read SRAM */
+ out_8(dcm->ocmd, 0);
+
+ /* 5. wait for DCM to stop (ack == 0) or error (err == 1) */
+ spin_event_timeout(
+ ((v = in_8(dcm->mack)) & (PX_OACK_ERR | PX_OACK_ACK))
+ != PX_OACK_ACK, 50000, 1000);
+
+ /* 6. check for error or timeout */
+ if (v & (PX_OACK_ERR | PX_OACK_ACK)) {
+ dev_err(dcm->dev, "timeout or error waiting for stop ack\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+#define TRATE0 241122 /* t-rate if prescale==0, in millihertz */
+#define TRATE1 38579330 /* t-rate if prescale==1, in millihertz */
+/*
+ * Empirical tests show that any frequency higher than 48Hz is unreliable.
+ */
+static int set_dcm_frequency(struct fsl_dcm_data *dcm,
+ unsigned long frequency)
+{
+ unsigned long timer;
+
+ if (!is_sram_available(dcm)) {
+ dev_err(dcm->dev, "dcm is busy\n");
+ return -EBUSY;
+ }
+
+ /* Restrict the frequency to a supported range. */
+ frequency = clamp_t(unsigned long, frequency, 1, MAX_FREQUENCY);
+
+ /* We only support prescale == 0 */
+ timer = TRATE0 / frequency;
+ dcm->timer = ((timer / 1000) - 1) & 0xff;
+
+ return run_program(dcm, 0, 6, OM_TIMER, 0, dcm->timer, 0, 0, OM_END);
+}
+
+static int copy_from_sram(struct fsl_dcm_data *dcm, unsigned int addr,
+ void *buf, unsigned int len)
+{
+ u8 *p = buf;
+ unsigned int i;
+
+ if (addr + len > 0xff) {
+ dev_err(dcm->dev, "address/length of %u/%u is out of bounds\n",
+ addr, len);
+ return -EBUSY;
+ }
+
+ for (i = 0; i < len; i++)
+ p[i] = read_sram(dcm, addr + i);
+
+ return 0;
+}
+
+/*
+ * Tells the DCM which channels to collect data on.
+ */
+static int select_dcm_channels(struct fsl_dcm_data *dcm, u16 mask)
+{
+ if (!is_sram_available(dcm)) {
+ dev_err(dcm->dev, "dcm is busy\n");
+ return -EBUSY;
+ }
+
+ return run_program(dcm, 0, 4, OM_ENABLE,
+ ((mask >> 8) & 0xFF), mask & 0xFF, OM_END);
+}
+
+/*
+ * Tells the DCM to start data collection. If the DCM is currently running,
+ * it is restarted. Any currently collected data is cleared.
+ */
+int start_data_collection(struct fsl_dcm_data *dcm)
+{
+ if (!is_sram_available(dcm)) {
+ dev_err(dcm->dev, "dcm is busy\n");
+ return -EBUSY;
+ }
+
+ if (dcm->running)
+ dev_dbg(dcm->dev, "restarting\n");
+
+ dcm->running = true;
+
+ return run_program(dcm, 0, 4, OM_STOP, OM_SCLR, OM_START, OM_END);
+}
+
+/* Tells the DCM to stop data collection. */
+int stop_data_collection(struct fsl_dcm_data *dcm)
+{
+ if (!dcm->running) {
+ dev_dbg(dcm->dev, "dcm is already stopped\n");
+ return 0;
+ }
+
+ if (!is_sram_available(dcm)) {
+ dev_err(dcm->dev, "dcm is busy\n");
+ return -EBUSY;
+ }
+
+ if (run_program(dcm, 0, 2, OM_STOP, OM_END)) {
+ dev_err(dcm->dev, "could not stop monitoring\n");
+ return -EBUSY;
+ }
+
+ dcm->running = false;
+
+ return 0;
+}
+
+static ssize_t dcm_get_info(struct device *dev)
+{
+ struct fsl_dcm_data *dcm = dev_get_drvdata(dev);
+
+ if (!is_sram_available(dcm)) {
+ dev_err(dev, "dcm is busy\n");
+ return -EBUSY;
+ }
+
+ if (run_program(dcm, 0, 3, OM_INFO, DATA_ADDR, OM_END)) {
+ dev_err(dev, "could not run 'info' program\n");
+ return -EBUSY;
+ }
+
+ if (copy_from_sram(dcm, DATA_ADDR, &dcm->board.info,
+ sizeof(struct om_info))) {
+ dev_err(dev, "could not copy 'info' data\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+ssize_t fsl_dcm_sysfs_control_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fsl_dcm_data *dcm = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%s\n", dcm->running ? "running" : "stoppped");
+}
+
+ssize_t fsl_dcm_sysfs_control_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct fsl_dcm_data *dcm = dev_get_drvdata(dev);
+ unsigned long pm_cmd;
+ int ret;
+
+ ret = kstrtoul(buf, 10, &pm_cmd);
+ if (ret)
+ return ret;
+
+ switch (pm_cmd) {
+ case SYSFS_DCM_CMD_START:
+ ret = start_data_collection(dcm);
+ if (ret)
+ dev_err(dev, "failed to start power monitoring.\n");
+ break;
+ case SYSFS_DCM_CMD_STOP:
+ ret = stop_data_collection(dcm);
+ if (ret)
+ dev_err(dev, "failed to stop power monitoring\n");
+ break;
+ default:
+ return -EIO;
+ }
+
+ return count;
+}
+
+static int get_crecords(struct fsl_dcm_data *dcm)
+{
+ int len;
+ u8 addr1, addr2;
+ struct crecord *crec = dcm->board.crec;
+ struct om_info *info = &dcm->board.info;
+
+ /* get CRECORDs from ocm sram */
+ if (!is_sram_available(dcm)) {
+ dev_err(dcm->dev, "dcm is busy\n");
+ return -EBUSY;
+ }
+
+ len = sizeof(struct crecord) * info->count;
+ addr1 = (info->addr >> 8) & 0xff;
+ addr2 = info->addr & 0xff;
+
+ if (run_program(dcm, 0, 6, OM_GETMEMX, addr1,
+ addr2, len, DATA_ADDR, OM_END)) {
+ dev_err(dcm->dev, "could not stop monitoring\n");
+ return -EBUSY;
+ }
+
+ if (copy_from_sram(dcm, DATA_ADDR, crec, len)) {
+ dev_err(dcm->dev, "could not copy sensor data\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+/* Calculate the average, even if 'count' is zero */
+#define AVG(sum, count) ((sum) / ((count) ?: 1))
+#define MAX_RECORD 9
+static ssize_t fsl_dcm_sysfs_result(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fsl_dcm_data *dcm = dev_get_drvdata(dev);
+ struct record *rec = dcm->board.rec;
+ struct crecord *crec = dcm->board.crec;
+ ssize_t len;
+ int i, avg, num, val;
+
+ if (get_crecords(dcm))
+ return sprintf(buf, "Get record error\n");
+
+ len = sprintf(buf,
+ "Name Average\n"
+ "==================== ================\n");
+
+ for (i = 0; i < dcm->board.info.count; i++) {
+ num = (crec->num1 << 8) | (crec->num2);
+ val = AVG(crec->accum, num);
+
+ if (crec->ctl & CRCTL_GET_V) {
+ avg = voltage_from_zl6100(val);
+ } else if (crec->ctl & CRCTL_GET_T) {
+ avg = temp_from_u16(val);
+ } else if (crec->ctl & CRCTL_GET_V2) {
+ avg = voltage_from_ina220(val);
+ } else if (crec->ctl & CRCTL_GET_I2) {
+ avg = current_from_ina220(val, dcm->board.shunt);
+ } else {
+ dev_err(dev, "Unknown record\n");
+ return -EBUSY;
+ }
+
+ len += sprintf(buf + len,
+ "%-8s %-6d %s\n",
+ rec->name, avg, rec->unit);
+ crec++;
+ rec++;
+ }
+
+ return len;
+}
+
+ssize_t fsl_dcm_sysfs_info(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct fsl_dcm_data *dcm = dev_get_drvdata(dev);
+ struct om_info *info = &dcm->board.info;
+ ssize_t len;
+
+ len = sprintf(buf, "DCM Version: 0x%02x\n", info->ver);
+ len += sprintf(buf + len, "Prescale: %u\n", info->prescale);
+ len += sprintf(buf + len, "Timer: %u\n", info->timer);
+ len += sprintf(buf + len, "Number of CRECORDs: %u\n", info->count);
+ len += sprintf(buf + len, "CRECORD Address: 0x%04x\n", info->addr);
+
+ return len;
+}
+
+ssize_t fsl_dcm_sysfs_frequency_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct fsl_dcm_data *dcm = dev_get_drvdata(dev);
+ unsigned long frequency;
+
+ frequency = TRATE0 / (dcm->timer + 1);
+
+ return sprintf(buf, "%lu Hz\n", frequency / 1000);
+}
+
+ssize_t fsl_dcm_sysfs_frequency_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct fsl_dcm_data *dcm = dev_get_drvdata(dev);
+ unsigned long frequency;
+ int ret;
+
+ ret = kstrtoul(buf, 10, &frequency);
+ if (ret)
+ return ret;
+
+ set_dcm_frequency(dcm, frequency);
+
+ return count;
+}
+
+static DEVICE_ATTR(control, 0666, fsl_dcm_sysfs_control_show,
+ fsl_dcm_sysfs_control_store);
+static DEVICE_ATTR(result, 0444, fsl_dcm_sysfs_result, NULL);
+static DEVICE_ATTR(info, 0444, fsl_dcm_sysfs_info, NULL);
+static DEVICE_ATTR(frequency, 0666, fsl_dcm_sysfs_frequency_show,
+ fsl_dcm_sysfs_frequency_store);
+
+static const struct attribute_group fsl_dcm_attr_group = {
+ .attrs = (struct attribute * []) {
+ &dev_attr_control.attr,
+ &dev_attr_result.attr,
+ &dev_attr_info.attr,
+ &dev_attr_frequency.attr,
+ NULL,
+ },
+};
+
+static int board_data_init(struct fsl_dcm_data *dcm)
+{
+ int i, len;
+ u8 addr1, addr2;
+ struct record *rec = dcm->board.rec;
+ struct crecord *crec = dcm->board.crec;
+ struct om_info *info = &dcm->board.info;
+ struct om_xinfo xinfo;
+ char name[MAX_NAME_LEN + 1];
+
+ /* 1. get CRECORD array from ocm */
+ if (get_crecords(dcm))
+ return -EBUSY;
+
+ /* 2. get xinfo located in CRECORD.xinfo_addr */
+ for (i = 0; i < info->count; i++) {
+ if (!is_sram_available(dcm)) {
+ dev_err(dcm->dev, "dcm is busy\n");
+ return -EBUSY;
+ }
+
+ addr1 = (crec->xinfo_addr >> 8) & 0xff;
+ addr2 = (crec->xinfo_addr) & 0xff;
+ len = sizeof(struct om_xinfo);
+
+ if (run_program(dcm, 0, 6, OM_GETMEMX, addr1,
+ addr2, len, DATA_ADDR, OM_END)) {
+ dev_err(dcm->dev, "get xinfo error\n");
+ return -EBUSY;
+ }
+
+ if (copy_from_sram(dcm, DATA_ADDR, &xinfo, len)) {
+ dev_err(dcm->dev, "could not copy xinfo data\n");
+ return -EBUSY;
+ }
+
+ /* 3. get record name in struct xinfo */
+ if (!is_sram_available(dcm)) {
+ dev_err(dcm->dev, "dcm is busy\n");
+ return -EBUSY;
+ }
+
+ addr1 = (xinfo.name_addr >> 8) & 0xff;
+ addr2 = (xinfo.name_addr) & 0xff;
+ len = MAX_NAME_LEN;
+
+ if (run_program(dcm, 0, 6, OM_GETMEMX, addr1,
+ addr2, len, DATA_ADDR, OM_END)) {
+ dev_err(dcm->dev, "\n");
+ return -EBUSY;
+ }
+
+ if (copy_from_sram(dcm, DATA_ADDR, name, len)) {
+ dev_err(dcm->dev, "could not copy record name data\n");
+ return -EBUSY;
+ }
+
+ name[MAX_NAME_LEN] = 0;
+ rec->name = kstrdup(name, GFP_KERNEL);
+
+ /* assign the unit according record type */
+ if ((crec->ctl & CRCTL_GET_V) || (crec->ctl & CRCTL_GET_V2)) {
+ rec->unit = "mV";
+ } else if (crec->ctl & CRCTL_GET_T) {
+ rec->unit = "C ";
+ } else if (crec->ctl & CRCTL_GET_I2) {
+ rec->unit = "mA";
+ } else {
+ dev_err(dcm->dev, "Unknown record\n");
+ return -EBUSY;
+ }
+
+ /* deal with next record */
+ rec++;
+ crec++;
+ }
+
+ return 0;
+}
+
+/* .data is shunt value(in uOhms) of ina220 */
+static struct of_device_id fsl_dcm_ids[] = {
+ { .compatible = "fsl,p1022ds-fpga", .data = 0},
+ { .compatible = "fsl,p5020ds-fpga", .data = (void *)2106},
+ { .compatible = "fsl,tetra-fpga", .data = (void *)1000},
+ {}
+};
+
+static int fsl_dcm_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct fsl_dcm_data *dcm;
+ const struct of_device_id *match;
+ int ret;
+ u8 ver;
+
+ dcm = kzalloc(sizeof(*dcm), GFP_KERNEL);
+ if (!dcm)
+ return -ENOMEM;
+
+ dcm->base = of_iomap(np, 0);
+ if (!dcm->base) {
+ dev_err(&pdev->dev, "could not map fpga node\n");
+ ret = -ENOMEM;
+ goto err_kzalloc;
+ }
+
+ /*
+ * Get GMSA version
+ *
+ * write 0x1F to GDC register then read GDD register
+ * 0x00: v1 -> pixis
+ * 0x01: v2 -> qixis
+ */
+ out_8(dcm->base + 0x16, 0x1F);
+ ver = in_8(dcm->base + 0x17);
+ if (ver == 0x0) {
+ dcm->addr = dcm->base + 0x0a;
+ dcm->data = dcm->base + 0x0d;
+ } else if (ver == 0x01) {
+ dcm->addr = dcm->base + 0x12;
+ dcm->data = dcm->base + 0x13;
+ }
+ dcm->ocmd = dcm->base + 0x14;
+ dcm->omsg = dcm->base + 0x15;
+ dcm->mack = dcm->base + 0x18;
+
+ /* Check to make sure the DCM is enable and working */
+ if (!is_sram_available(dcm)) {
+ dev_err(&pdev->dev, "dcm is not responding\n");
+ ret = -EBUSY;
+ goto err_iomap;
+ }
+
+ dcm->dev = &pdev->dev;
+ dev_set_drvdata(&pdev->dev, dcm);
+
+ /* get the struct om_info */
+ if (dcm_get_info(&pdev->dev)) {
+ dev_err(&pdev->dev, "could not get struct om_info\n");
+ ret = -EBUSY;
+ goto err_iomap;
+ }
+
+ /* only support v41 or later */
+ if (dcm->board.info.ver < 41 || dcm->board.info.ver == 0xff) {
+ dev_err(&pdev->dev, "dcm is invalid or needs to update\n");
+ ret = -ENODEV;
+ goto err_iomap;
+ }
+
+ dcm->board.rec = kzalloc(sizeof(*dcm->board.rec) *
+ dcm->board.info.count, GFP_KERNEL);
+ if (!dcm->board.rec) {
+ dev_err(&pdev->dev, "no memory\n");
+ ret = -ENOMEM;
+ goto err_iomap;
+ }
+
+ dcm->board.crec = kzalloc(sizeof(*dcm->board.crec) *
+ dcm->board.info.count, GFP_KERNEL);
+ if (!dcm->board.crec) {
+ dev_err(&pdev->dev, "no memory\n");
+ ret = -ENOMEM;
+ goto err_kzall;
+ }
+
+ /* get the shunt value */
+ match = of_match_node(fsl_dcm_ids, np);
+ dcm->board.shunt = (long)match->data;
+
+ /* enable all the channel */
+ dcm->board.mask = 0x1FF;
+
+ /* init all the board specific data */
+ ret = board_data_init(dcm);
+ if (ret) {
+ dev_err(&pdev->dev, "could not create sysfs group\n");
+ ret = -ENODEV;
+ goto err_kzall2;
+ }
+
+ /* enable all the channel */
+ if (select_dcm_channels(dcm, dcm->board.mask)) {
+ dev_err(&pdev->dev, "could not set crecord mask\n");
+ ret = -ENODEV;
+ goto err_kzall2;
+ }
+
+ /* Set the timer to the 1 Hz */
+ if (set_dcm_frequency(dcm, 1)) {
+ dev_err(&pdev->dev, "could not set frequency\n");
+ ret = -ENODEV;
+ goto err_kzall2;
+ }
+
+ /* create sysfs interface */
+ ret = sysfs_create_group(&pdev->dev.kobj, &fsl_dcm_attr_group);
+ if (ret) {
+ dev_err(&pdev->dev, "could not create sysfs group\n");
+ goto err_kzall2;
+ }
+
+ return 0;
+
+err_kzall2:
+ kfree(dcm->board.crec);
+
+err_kzall:
+ kfree(dcm->board.rec);
+
+err_iomap:
+ iounmap(dcm->base);
+
+err_kzalloc:
+ kfree(dcm);
+
+ return ret;
+}
+
+static int fsl_dcm_remove(struct platform_device *pdev)
+{
+ struct fsl_dcm_data *dcm = dev_get_drvdata(&pdev->dev);
+
+ stop_data_collection(dcm);
+ sysfs_remove_group(&pdev->dev.kobj, &fsl_dcm_attr_group);
+ iounmap(dcm->base);
+ kfree(dcm->board.rec);
+ kfree(dcm->board.crec);
+ kfree(dcm);
+
+ return 0;
+}
+
+static struct platform_driver fsl_dcm_driver = {
+ .driver = {
+ .name = "fsl-dcm-driver",
+ .owner = THIS_MODULE,
+ },
+ .probe = fsl_dcm_probe,
+ .remove = fsl_dcm_remove,
+};
+
+static int __init fsl_dcm_init(void)
+{
+ struct device_node *np;
+ struct platform_device *pdev;
+ int ret;
+
+ np = of_find_matching_node(NULL, fsl_dcm_ids);
+ if (!np)
+ return -ENODEV;
+
+ /* We found a supported platform, so register a platform driver */
+ ret = platform_driver_register(&fsl_dcm_driver);
+ if (ret) {
+ pr_err("fsl-dcm: could not register platform driver\n");
+ goto err_np;
+ }
+
+ /* We need to create a device and add the data for this platform */
+ pdev = platform_device_alloc(fsl_dcm_driver.driver.name, 0);
+ if (!pdev) {
+ ret = -ENOMEM;
+ goto err_drv;
+ }
+
+ /* Pass the device_node pointer to the probe function */
+ pdev->dev.of_node = np;
+
+ /* This will call the probe function */
+ ret = platform_device_add(pdev);
+ if (ret) {
+ pr_err("fsl-dcm: could not register platform driver\n");
+ goto err_dev;
+ }
+
+ pr_info("Freescale Data Collection Module is installed.\n");
+
+ return 0;
+
+err_dev:
+ platform_device_unregister(pdev);
+
+err_drv:
+ platform_driver_unregister(&fsl_dcm_driver);
+
+err_np:
+ of_node_put(np);
+
+ return ret;
+}
+
+static void __exit fsl_dcm_exit(void)
+{
+ platform_driver_unregister(&fsl_dcm_driver);
+}
+
+MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
+MODULE_DESCRIPTION("Freescale Data Collection Manager driver");
+MODULE_LICENSE("GPL v2");
+
+module_init(fsl_dcm_init);
+module_exit(fsl_dcm_exit);
diff --git a/drivers/misc/fsl_dcm.h b/drivers/misc/fsl_dcm.h
new file mode 100644
index 0000000..722ac28
--- /dev/null
+++ b/drivers/misc/fsl_dcm.h
@@ -0,0 +1,129 @@
+#ifndef _FSL_DCM_H
+#define _FSL_DCM_H
+
+/* sysfs commands for 'control' */
+#define SYSFS_DCM_CMD_STOP 0
+#define SYSFS_DCM_CMD_START 1
+
+#define MAX_NAME_LEN 10
+#define MAX_FREQUENCY 48 /* max freq the DCM supports */
+#define DATA_ADDR 0x20 /* data address in DCM SRAM */
+#define CHAN_MASK 0x1FF /* 9 channel is enabled */
+
+/* PIXIS register status bits */
+#define PX_OCMD_MSG (1 << 0)
+#define PX_OACK_ERR (1 << 1)
+#define PX_OACK_ACK (1 << 0) /* OACK is sometimes called MACK */
+
+/* DCM commands */
+#define OM_END 0x00
+#define OM_SETDLY 0x01
+#define OM_RST0 0x02
+#define OM_RST1 0x03
+#define OM_CHKDLY 0x04
+#define OM_PWR 0x05
+#define OM_WAKE 0x07
+#define OM_GETMEM 0x08
+#define OM_SETMEM 0x09
+#define OM_SCLR 0x10
+#define OM_START 0x11
+#define OM_STOP 0x12
+#define OM_GET 0x13
+#define OM_ENABLE 0x14
+#define OM_TIMER 0x15
+#define OM_SNAP 0x16
+#define OM_GETMEMX 0x18
+#define OM_AVGOFF 0x19
+#define OM_AVGON 0x1A
+#define OM_SETV 0x30
+#define OM_INFO 0x31
+#define OM_XINFO 0x32
+
+/* Support definitions */
+#define CRCTLBIT_ENA (7) /* Set to enable collection */
+#define CRCTLBIT_IGNORE (6) /* Ignore record for voltage mangement */
+#define CRCTLBIT_FILTER (5) /* Set to enable data filtering */
+#define CRCTLBIT_GET_V2 (4) /* Record type: voltage via INA220 */
+#define CRCTLBIT_GET_I2 (3) /* Record type: current via INA220 */
+#define CRCTLBIT_GET_T (2) /* Record type: temperature via ADT7461 */
+#define CRCTLBIT_GET_I (1) /* Record type: current via PMBus device */
+#define CRCTLBIT_GET_V (0) /* Record type: voltage via PMBus device */
+
+/* Bitmasks */
+#define CRCTL_ENA (1 << CRCTLBIT_ENA)
+#define CRCTL_IGNORE (1 << CRCTLBIT_IGNORE)
+#define CRCTL_FILTER (1 << CRCTLBIT_FILTER)
+#define CRCTL_GET_V2 (1 << CRCTLBIT_GET_V2)
+#define CRCTL_GET_I2 (1 << CRCTLBIT_GET_I2)
+#define CRCTL_GET_T (1 << CRCTLBIT_GET_T)
+#define CRCTL_GET_I (1 << CRCTLBIT_GET_I)
+#define CRCTL_GET_V (1 << CRCTLBIT_GET_V)
+
+/* Handy definitions */
+#define CR_VOLT_PMB (CRCTL_ENA|CRCTL_FILTER|CRCTL_GET_V)
+#define CR_VOLT_PMB_X (CRCTL_ENA|CRCTL_FILTER|CRCTL_GET_V|CRCTL_IGNORE)
+#define CR_CURR_PMB (CRCTL_ENA|CRCTL_FILTER|CRCTL_GET_I)
+#define CR_VOLT_INA (CRCTL_ENA|CRCTL_GET_V2)
+#define CR_CURR_INA (CRCTL_ENA|CRCTL_GET_I2)
+#define CR_TEMP (CRCTL_ENA|CRCTL_FILTER|CRCTL_GET_T)
+
+struct crecord {
+ u8 ctl; /* enabled, data type */
+ u8 i2c_addr; /* target i2c address */
+ u8 port; /* target port(channel) */
+ __be16 curr; /* most recent sample */
+ __be16 max; /* maximum value */
+ __be16 num1; /* number of samples taken */
+ u8 num2;
+ __be32 accum; /* sum of samples */
+ __be16 xinfo_addr; /* pointer to XINFO structure */
+} __packed;
+
+struct om_info {
+ __be16 ver; /* DCM version number */
+ u8 prescale; /* prescale value used */
+ u8 timer; /* timer */
+ u8 count; /* number of CRECORDS */
+ __be16 addr; /* address of CRECORD array in SRAM */
+ u8 res[3];
+} __packed;
+
+struct om_xinfo {
+ __be16 name_addr; /* descriptive name */
+ __be16 def; /* SW-defined default */
+ __be16 curr; /* SW-obtained value */
+ __be16 cal; /* calibration factor */
+ u8 flags;
+ u8 method;
+ __be16 get; /* get current value */
+ __be16 set; /* set voltage to value */
+ __be16 init; /* initialize device */
+} __packed;
+
+struct record {
+ char *name; /* record name */
+ char *unit; /* record unit */
+};
+
+struct dcm_board {
+ struct om_info info;
+ struct record *rec; /* per record struct */
+ struct crecord *crec; /* all the collected records */
+ u32 shunt; /* shunt for ina220 current */
+ u32 mask; /* channel mask */
+};
+
+struct fsl_dcm_data {
+ void __iomem *base; /* PIXIS/QIXIS base address */
+ struct device *dev;
+ u8 __iomem *addr; /* SRAM address */
+ u8 __iomem *data; /* SRAM data */
+ u8 __iomem *ocmd; /* DCM command/status */
+ u8 __iomem *omsg; /* DCM message */
+ u8 __iomem *mack; /* DCM acknowledge */
+ u8 timer;
+ int running;
+ struct dcm_board board;
+};
+
+#endif
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 4e8212c..3241cb7 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -59,6 +59,8 @@ MODULE_ALIAS("mmc:block");
#define INAND_CMD38_ARG_SECTRIM1 0x81
#define INAND_CMD38_ARG_SECTRIM2 0x88
#define MMC_BLK_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */
+#define MMC_MIN_QUEUE_BOUNCESZ 4096
+#define MMC_MAX_QUEUE_BOUNCESZ 4194304
#define MMC_SANITIZE_REQ_TIMEOUT 240000
#define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16)
@@ -118,6 +120,7 @@ struct mmc_blk_data {
unsigned int part_curr;
struct device_attribute force_ro;
struct device_attribute power_ro_lock;
+ struct device_attribute bouncesz;
int area_type;
};
@@ -1961,9 +1964,20 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
unsigned long flags;
unsigned int cmd_flags = req ? req->cmd_flags : 0;
- if (req && !mq->mqrq_prev->req)
+ if (req && !mq->mqrq_prev->req) {
+ /*
+ * When we are here, card polling task will be blocked.
+ * So disable it to avoid this useless schedule.
+ */
+ if (host->caps & MMC_CAP_NEEDS_POLL) {
+ spin_lock_irqsave(&host->lock, flags);
+ host->rescan_disable = 1;
+ spin_unlock_irqrestore(&host->lock, flags);
+ }
+
/* claim host only for the first request */
mmc_get_card(card);
+ }
ret = mmc_blk_part_switch(card, md);
if (ret) {
@@ -2000,7 +2014,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
out:
if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) ||
- (cmd_flags & MMC_REQ_SPECIAL_MASK))
+ (cmd_flags & MMC_REQ_SPECIAL_MASK)) {
/*
* Release host when there are no more requests
* and after special request(discard, flush) is done.
@@ -2008,6 +2022,18 @@ out:
* the 'mmc_blk_issue_rq' with 'mqrq_prev->req'.
*/
mmc_put_card(card);
+ /*
+ * Detecting card status immediately in case card being
+ * removed just after the request is complete.
+ */
+ if (host->caps & MMC_CAP_NEEDS_POLL) {
+ spin_lock_irqsave(&host->lock, flags);
+ host->rescan_disable = 0;
+ spin_unlock_irqrestore(&host->lock, flags);
+ mmc_detect_change(host, 0);
+ }
+ }
+
return ret;
}
@@ -2237,6 +2263,7 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md)
mmc_packed_clean(&md->queue);
if (md->disk->flags & GENHD_FL_UP) {
device_remove_file(disk_to_dev(md->disk), &md->force_ro);
+ device_remove_file(disk_to_dev(md->disk), &md->bouncesz);
if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
card->ext_csd.boot_ro_lockable)
device_remove_file(disk_to_dev(md->disk),
@@ -2248,6 +2275,33 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md)
}
}
+#ifdef CONFIG_MMC_BLOCK_BOUNCE
+static ssize_t mmc_bouncesz_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", mmc_queue_bouncesz);
+}
+
+static ssize_t mmc_bouncesz_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned int bouncesz;
+ struct mmc_blk_data *md;
+
+ if ((sscanf(buf, "%d", &bouncesz) != 1) ||
+ (bouncesz < MMC_MIN_QUEUE_BOUNCESZ) ||
+ (bouncesz > MMC_MAX_QUEUE_BOUNCESZ) ||
+ (bouncesz % 512 != 0))
+ return -EINVAL;
+
+ md = mmc_blk_get(dev_to_disk(dev));
+ mmc_reinit_bounce_queue(&md->queue, md->queue.card, bouncesz);
+ mmc_blk_put(md);
+ return mmc_queue_bouncesz;
+}
+#endif
+
static void mmc_blk_remove_parts(struct mmc_card *card,
struct mmc_blk_data *md)
{
@@ -2333,6 +2387,10 @@ static const struct mmc_fixup blk_fixups[] =
*
* N.B. This doesn't affect SD cards.
*/
+ MMC_FIXUP("SDMB-32", CID_MANFID_SANDISK, CID_OEMID_ANY, add_quirk_mmc,
+ MMC_QUIRK_BLK_NO_CMD23),
+ MMC_FIXUP("SDM032", CID_MANFID_SANDISK, CID_OEMID_ANY, add_quirk_mmc,
+ MMC_QUIRK_BLK_NO_CMD23),
MMC_FIXUP("MMC08G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
MMC_QUIRK_BLK_NO_CMD23),
MMC_FIXUP("MMC16G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
@@ -2375,6 +2433,7 @@ static const struct mmc_fixup blk_fixups[] =
static int mmc_blk_probe(struct mmc_card *card)
{
struct mmc_blk_data *md, *part_md;
+ int err;
char cap_str[10];
/*
@@ -2407,6 +2466,17 @@ static int mmc_blk_probe(struct mmc_card *card)
goto out;
}
+#ifdef CONFIG_MMC_BLOCK_BOUNCE
+ md->bouncesz.show = mmc_bouncesz_show;
+ md->bouncesz.store = mmc_bouncesz_store;
+ sysfs_attr_init(&md->bouncesz.attr);
+ md->bouncesz.attr.name = "bouncesz";
+ md->bouncesz.attr.mode = S_IRUGO | S_IWUSR;
+ err = device_create_file(disk_to_dev(md->disk), &md->bouncesz);
+ if (err)
+ goto out;
+#endif
+
pm_runtime_set_autosuspend_delay(&card->dev, 3000);
pm_runtime_use_autosuspend(&card->dev);
@@ -2422,6 +2492,9 @@ static int mmc_blk_probe(struct mmc_card *card)
return 0;
out:
+#ifdef CONFIG_MMC_BLOCK_BOUNCE
+ device_remove_file(disk_to_dev(md->disk), &md->bouncesz);
+#endif
mmc_blk_remove_parts(card, md);
mmc_blk_remove_req(md);
return 0;
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index fa9632e..b0f6bfd 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -22,6 +22,10 @@
#define MMC_QUEUE_BOUNCESZ 65536
+#ifdef CONFIG_MMC_BLOCK_BOUNCE
+unsigned mmc_queue_bouncesz = MMC_QUEUE_BOUNCESZ;
+#endif
+
/*
* Prepare a MMC request. This just filters out odd stuff.
*/
@@ -216,7 +220,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
if (host->max_segs == 1) {
unsigned int bouncesz;
- bouncesz = MMC_QUEUE_BOUNCESZ;
+ bouncesz = mmc_queue_bouncesz;
if (bouncesz > host->max_req_size)
bouncesz = host->max_req_size;
@@ -403,6 +407,102 @@ void mmc_packed_clean(struct mmc_queue *mq)
}
/**
+ * mmc_reinit_bounce_queue - re-initialise a bounce buffer.
+ * @mq: mmc queue
+ * @card: mmc card to attach this queue
+ * @bouncesz: the bounce size that need re-initializing
+ *
+ * Initialise a MMC card request queue.
+ */
+#ifdef CONFIG_MMC_BLOCK_BOUNCE
+int mmc_reinit_bounce_queue(struct mmc_queue *mq, struct mmc_card *card,
+ unsigned int bouncesz)
+{
+ struct mmc_host *host = card->host;
+ struct mmc_queue_req *mqrq_cur = &mq->mqrq[0];
+ struct mmc_queue_req *mqrq_prev = &mq->mqrq[1];
+ int ret;
+ struct scatterlist *curr_bounce_sg, *prev_bounce_sg;
+ char *curr_bounce_buf, *prev_bounce_buf;
+
+ mmc_claim_host(card->host);
+
+ bouncesz = min(bouncesz, host->max_req_size);
+ bouncesz = min(bouncesz, host->max_seg_size);
+ bouncesz = min(bouncesz, host->max_blk_count * 512);
+
+ /* store current using addr of bounce_buf and bounce_sg */
+ curr_bounce_sg = mqrq_cur->bounce_sg;
+ prev_bounce_sg = mqrq_prev->bounce_sg;
+ curr_bounce_buf = mqrq_cur->bounce_buf;
+ prev_bounce_buf = mqrq_prev->bounce_buf;
+
+ if (host->max_segs != 1)
+ goto restore_queue;
+
+ /* realloc bounce queue use given bounce size */
+ mqrq_cur->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
+ if (!mqrq_cur->bounce_buf) {
+ printk(KERN_WARNING "%s: unable to "
+ "allocate bounce cur buffer\n",
+ mmc_card_name(card));
+ ret = -ENOMEM;
+ goto restore_queue;
+ }
+
+ mqrq_prev->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
+ if (!mqrq_prev->bounce_buf) {
+ printk(KERN_WARNING "%s: unable to "
+ "allocate bounce prev buffer\n",
+ mmc_card_name(card));
+ kfree(mqrq_cur->bounce_buf);
+ mqrq_cur->bounce_buf = NULL;
+ ret = -ENOMEM;
+ goto restore_queue;
+ }
+
+ mqrq_cur->bounce_sg =
+ mmc_alloc_sg(bouncesz / 512, &ret);
+ if (ret)
+ goto cleanup_queue;
+
+ mqrq_prev->bounce_sg =
+ mmc_alloc_sg(bouncesz / 512, &ret);
+ if (ret)
+ goto cleanup_queue;
+
+ blk_queue_max_hw_sectors(mq->queue, bouncesz / 512);
+ blk_queue_max_segments(mq->queue, bouncesz / 512);
+ blk_queue_max_segment_size(mq->queue, bouncesz);
+ mmc_queue_bouncesz = bouncesz;
+
+ kfree(curr_bounce_sg);
+ kfree(prev_bounce_sg);
+ kfree(curr_bounce_buf);
+ kfree(prev_bounce_buf);
+
+ mmc_release_host(card->host);
+ return 0;
+
+cleanup_queue:
+ /* cleanup bounce queue first */
+ kfree(mqrq_cur->sg);
+ kfree(mqrq_cur->bounce_buf);
+ kfree(mqrq_prev->sg);
+ kfree(mqrq_prev->bounce_buf);
+
+restore_queue:
+ mqrq_cur->bounce_buf = curr_bounce_buf;
+ mqrq_prev->bounce_buf = prev_bounce_buf;
+ mqrq_cur->bounce_sg = curr_bounce_sg;
+ mqrq_prev->bounce_sg = prev_bounce_sg;
+
+ mmc_release_host(card->host);
+ return ret;
+}
+#endif
+
+/**
* mmc_queue_suspend - suspend a MMC request queue
* @mq: MMC queue to suspend
*
diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h
index 5752d50..d96cb0f 100644
--- a/drivers/mmc/card/queue.h
+++ b/drivers/mmc/card/queue.h
@@ -67,6 +67,11 @@ extern void mmc_queue_resume(struct mmc_queue *);
extern unsigned int mmc_queue_map_sg(struct mmc_queue *,
struct mmc_queue_req *);
+#ifdef CONFIG_MMC_BLOCK_BOUNCE
+extern int mmc_reinit_bounce_queue(struct mmc_queue *, struct mmc_card *,
+ unsigned int);
+extern unsigned mmc_queue_bouncesz;
+#endif
extern void mmc_queue_bounce_pre(struct mmc_queue_req *);
extern void mmc_queue_bounce_post(struct mmc_queue_req *);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index bf18b6b..59cf22a 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -757,6 +757,7 @@ EXPORT_SYMBOL(mmc_read_bkops_status);
*/
void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
{
+ struct mmc_host *host = card->host;
unsigned int mult;
/*
@@ -780,7 +781,12 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
if (data->flags & MMC_DATA_WRITE)
mult <<= card->csd.r2w_factor;
- data->timeout_ns = card->csd.tacc_ns * mult;
+ /* Avoid over flow for some crappy cards. */
+ if ((UINT_MAX / mult) < card->csd.tacc_ns)
+ data->timeout_ns = UINT_MAX;
+ else
+ data->timeout_ns = card->csd.tacc_ns * mult;
+
data->timeout_clks = card->csd.tacc_clks * mult;
/*
@@ -842,6 +848,12 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
data->timeout_ns = 100000000; /* 100ms */
}
}
+
+ if (host->max_discard_to &&
+ (host->max_discard_to <
+ (data->timeout_ns / 1000000)))
+ data->timeout_ns = host->max_discard_to * 1000000;
+
}
EXPORT_SYMBOL(mmc_set_data_timeout);
@@ -1816,11 +1828,14 @@ static unsigned int mmc_mmc_erase_timeout(struct mmc_card *card,
unsigned int timeout_clks = card->csd.tacc_clks * mult;
unsigned int timeout_us;
- /* Avoid overflow: e.g. tacc_ns=80000000 mult=1280 */
- if (card->csd.tacc_ns < 1000000)
- timeout_us = (card->csd.tacc_ns * mult) / 1000;
- else
+ /*
+ * Avoid over flow for some crappy cards.
+ * e.g. tacc_ns=80000000 mult=1280
+ */
+ if ((UINT_MAX / mult) < card->csd.tacc_ns)
timeout_us = (card->csd.tacc_ns / 1000) * mult;
+ else
+ timeout_us = (card->csd.tacc_ns * mult) / 1000;
/*
* ios.clock is only a target. The real clock rate might be
@@ -2185,16 +2200,18 @@ unsigned int mmc_calc_max_discard(struct mmc_card *card)
struct mmc_host *host = card->host;
unsigned int max_discard, max_trim;
- if (!host->max_discard_to)
- return UINT_MAX;
+ if (!host->max_discard_to) {
- /*
- * Without erase_group_def set, MMC erase timeout depends on clock
- * frequence which can change. In that case, the best choice is
- * just the preferred erase size.
- */
- if (mmc_card_mmc(card) && !(card->ext_csd.erase_group_def & 1))
- return card->pref_erase;
+ /*
+ * Without erase_group_def set, MMC erase timeout depends
+ * on clock frequence which can change. In that case, the
+ * best choice is just the preferred erase size.
+ */
+ if (mmc_card_mmc(card) && !(card->ext_csd.erase_group_def & 1))
+ return card->pref_erase;
+ else
+ return UINT_MAX;
+ }
max_discard = mmc_do_calc_max_discard(card, MMC_ERASE_ARG);
if (mmc_can_trim(card)) {
@@ -2400,6 +2417,7 @@ int mmc_detect_card_removed(struct mmc_host *host)
{
struct mmc_card *card = host->card;
int ret;
+ unsigned long flags;
WARN_ON(!host->claimed);
@@ -2422,6 +2440,10 @@ int mmc_detect_card_removed(struct mmc_host *host)
* Schedule a detect work as soon as possible to let a
* rescan handle the card removal.
*/
+ spin_lock_irqsave(&host->lock, flags);
+ host->rescan_disable = 0;
+ spin_unlock_irqrestore(&host->lock, flags);
+
cancel_delayed_work(&host->detect);
mmc_detect_change(host, 0);
}
diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h
index a2a0642..7725160 100644
--- a/drivers/mmc/host/sdhci-esdhc.h
+++ b/drivers/mmc/host/sdhci-esdhc.h
@@ -23,16 +23,22 @@
SDHCI_QUIRK_NONSTANDARD_CLOCK | \
SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \
SDHCI_QUIRK_PIO_NEEDS_DELAY | \
- SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
+ SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET | \
+ SDHCI_QUIRK_NO_HISPD_BIT)
#define ESDHC_SYSTEM_CONTROL 0x2c
#define ESDHC_CLOCK_MASK 0x0000fff0
#define ESDHC_PREDIV_SHIFT 8
#define ESDHC_DIVIDER_SHIFT 4
+#define ESDHC_CLOCK_CRDEN 0x00000008
#define ESDHC_CLOCK_PEREN 0x00000004
#define ESDHC_CLOCK_HCKEN 0x00000002
#define ESDHC_CLOCK_IPGEN 0x00000001
+
+#define ESDHCI_PRESENT_STATE 0x24
+#define ESDHC_CLK_STABLE 0x00000008
+
/* pltfm-specific */
#define ESDHC_HOST_CONTROL_LE 0x20
@@ -46,12 +52,15 @@
/* OF-specific */
#define ESDHC_DMA_SYSCTL 0x40c
#define ESDHC_DMA_SNOOP 0x00000040
+#define ESDHC_INT_DMA_ERROR 0x10000000
-#define ESDHC_HOST_CONTROL_RES 0x05
+#define ESDHC_HOST_CONTROL_RES 0x01
+#define ESDHC_VOL_SEL 0x04
static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock,
unsigned int host_clock)
{
+ u32 timeout;
int pre_div = 2;
int div = 1;
u32 temp;
@@ -81,6 +90,22 @@ static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock,
| (div << ESDHC_DIVIDER_SHIFT)
| (pre_div << ESDHC_PREDIV_SHIFT));
sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
+
+ /* Wait max 20 ms */
+ timeout = 20;
+ while (!(sdhci_readl(host, ESDHCI_PRESENT_STATE) & ESDHC_CLK_STABLE)) {
+ if (timeout == 0) {
+ pr_err("%s: Internal clock never "
+ "stabilised.\n", mmc_hostname(host->mmc));
+ return;
+ }
+ timeout--;
+ mdelay(1);
+ }
+
+ temp |= ESDHC_CLOCK_CRDEN;
+ sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
+
mdelay(1);
out:
host->clock = clock;
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index e328252..0f9f36b 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -21,9 +21,13 @@
#include <linux/mmc/host.h>
#include "sdhci-pltfm.h"
#include "sdhci-esdhc.h"
+#include <asm/mpc85xx.h>
#define VENDOR_V_22 0x12
#define VENDOR_V_23 0x13
+
+static u32 svr;
+
static u32 esdhc_readl(struct sdhci_host *host, int reg)
{
u32 ret;
@@ -46,6 +50,14 @@ static u32 esdhc_readl(struct sdhci_host *host, int reg)
ret |= SDHCI_CAN_DO_ADMA2;
}
+ /*
+ * Clock of eSDHC host don't support to be disabled and enabled.
+ * So clock stable bit doesn't behave as it mean, So fix it to
+ * '1' to avoid misreading.
+ */
+ if (reg == SDHCI_PRESENT_STATE)
+ ret |= ESDHC_CLK_STABLE;
+
return ret;
}
@@ -59,6 +71,13 @@ static u16 esdhc_readw(struct sdhci_host *host, int reg)
ret = in_be32(host->ioaddr + base) & 0xffff;
else
ret = (in_be32(host->ioaddr + base) >> shift) & 0xffff;
+
+ /* T4240-R1.0-R2.0 had a incorrect vendor version and spec version */
+ if ((reg == SDHCI_HOST_VERSION) &&
+ ((SVR_SOC_VER(svr) == SVR_T4240) &&
+ (SVR_REV(svr) <= 0x20)))
+ ret = (VENDOR_V_23 << SDHCI_VENDOR_VER_SHIFT) | SDHCI_SPEC_200;
+
return ret;
}
@@ -139,6 +158,47 @@ static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg)
/* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */
if (reg == SDHCI_HOST_CONTROL)
val &= ~ESDHC_HOST_CONTROL_RES;
+
+ /*
+ * If we have this quirk:
+ * 1. Disabled the clock.
+ * 2. Perform reset all command.
+ * 3. Enable the clock.
+ */
+ if ((reg == SDHCI_SOFTWARE_RESET) &&
+ (host->quirks2 & SDHCI_QUIRK2_BROKEN_RESET_ALL) &&
+ (val & SDHCI_RESET_ALL)) {
+ u32 temp;
+
+ temp = esdhc_readl(host, ESDHC_SYSTEM_CONTROL);
+ temp &= ~ESDHC_CLOCK_CRDEN;
+ esdhc_writel(host, temp, ESDHC_SYSTEM_CONTROL);
+
+ sdhci_be32bs_writeb(host, val, reg);
+
+ temp |= ESDHC_CLOCK_CRDEN;
+ esdhc_writel(host, temp, ESDHC_SYSTEM_CONTROL);
+
+ return;
+ }
+
+ if (reg == SDHCI_POWER_CONTROL) {
+ /* eSDHC don't support gate off power */
+ if (!host->pwr || !val)
+ return;
+
+ if (SVR_SOC_VER(svr) == SVR_T4240) {
+ u8 vol;
+
+ vol = sdhci_be32bs_readb(host, reg);
+ if (host->pwr == SDHCI_POWER_180)
+ vol &= ~ESDHC_VOL_SEL;
+ else
+ vol |= ESDHC_VOL_SEL;
+ } else
+ return;
+ }
+
sdhci_be32bs_writeb(host, val, reg);
}
@@ -162,19 +222,96 @@ static void esdhci_of_adma_workaround(struct sdhci_host *host, u32 intmask)
applicable = (intmask & SDHCI_INT_DATA_END) &&
(intmask & SDHCI_INT_BLK_GAP) &&
(tmp == VENDOR_V_23);
- if (!applicable)
+ if (applicable) {
+
+ sdhci_reset(host, SDHCI_RESET_DATA);
+ host->data->error = 0;
+ dmastart = sg_dma_address(host->data->sg);
+ dmanow = dmastart + host->data->bytes_xfered;
+ /*
+ * Force update to the next DMA block boundary.
+ */
+ dmanow = (dmanow & ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) +
+ SDHCI_DEFAULT_BOUNDARY_SIZE;
+ host->data->bytes_xfered = dmanow - dmastart;
+ sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS);
+
return;
+ }
- host->data->error = 0;
- dmastart = sg_dma_address(host->data->sg);
- dmanow = dmastart + host->data->bytes_xfered;
/*
- * Force update to the next DMA block boundary.
+ * Check for A-004388: eSDHC DMA might not stop if error
+ * occurs on system transaction
+ * Impact list:
+ * T4240-4160-R1.0 B4860-4420-R1.0-R2.0 P1010-1014-R1.0
+ * P3041-R1.0-R2.0-R1.1 P2041-2040-R1.0-R1.1-R2.0
+ * P5020-5010-R2.0-R1.0 P5040-5021-R2.0-R2.1
*/
- dmanow = (dmanow & ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) +
- SDHCI_DEFAULT_BOUNDARY_SIZE;
- host->data->bytes_xfered = dmanow - dmastart;
- sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS);
+ if (!(((SVR_SOC_VER(svr) == SVR_T4240) && (SVR_REV(svr) == 0x10)) ||
+ ((SVR_SOC_VER(svr) == SVR_T4160) && (SVR_REV(svr) == 0x10)) ||
+ ((SVR_SOC_VER(svr) == SVR_B4420) && (SVR_REV(svr) == 0x10)) ||
+ ((SVR_SOC_VER(svr) == SVR_B4420) && (SVR_REV(svr) == 0x20)) ||
+ ((SVR_SOC_VER(svr) == SVR_B4860) && (SVR_REV(svr) == 0x10)) ||
+ ((SVR_SOC_VER(svr) == SVR_B4860) && (SVR_REV(svr) == 0x20)) ||
+ ((SVR_SOC_VER(svr) == SVR_P1010) && (SVR_REV(svr) == 0x10)) ||
+ ((SVR_SOC_VER(svr) == SVR_P1014) && (SVR_REV(svr) == 0x10)) ||
+ ((SVR_SOC_VER(svr) == SVR_P3041) && (SVR_REV(svr) <= 0x20)) ||
+ ((SVR_SOC_VER(svr) == SVR_P2041) && (SVR_REV(svr) <= 0x20)) ||
+ ((SVR_SOC_VER(svr) == SVR_P2040) && (SVR_REV(svr) <= 0x20)) ||
+ ((SVR_SOC_VER(svr) == SVR_P5020) && (SVR_REV(svr) <= 0x20)) ||
+ ((SVR_SOC_VER(svr) == SVR_P5010) && (SVR_REV(svr) <= 0x20)) ||
+ ((SVR_SOC_VER(svr) == SVR_P5021) && (SVR_REV(svr) <= 0x21)) ||
+ ((SVR_SOC_VER(svr) == SVR_P5040) && (SVR_REV(svr) <= 0x21))))
+ return;
+
+ sdhci_reset(host, SDHCI_RESET_DATA);
+
+ if (host->flags & SDHCI_USE_ADMA) {
+ u32 mod, i, offset;
+ u8 *desc;
+ dma_addr_t addr;
+ struct scatterlist *sg;
+ __le32 *dataddr;
+ __le32 *cmdlen;
+
+ /*
+ * If block count was enabled, in case read transfer there
+ * is no data was corrupted
+ */
+ mod = esdhc_readl(host, SDHCI_TRANSFER_MODE);
+ if ((mod & SDHCI_TRNS_BLK_CNT_EN) &&
+ (host->data->flags & MMC_DATA_READ))
+ host->data->error = 0;
+
+ BUG_ON(!host->data);
+ desc = host->adma_desc;
+ for_each_sg(host->data->sg, sg, host->sg_count, i) {
+ addr = sg_dma_address(sg);
+ offset = (4 - (addr & 0x3)) & 0x3;
+ if (offset)
+ desc += 8;
+ desc += 8;
+ }
+
+ /*
+ * Add an extra zero descriptor next to the
+ * terminating descriptor.
+ */
+ desc += 8;
+ WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4);
+
+ dataddr = (__le32 __force *)(desc + 4);
+ cmdlen = (__le32 __force *)desc;
+
+ cmdlen[0] = cpu_to_le32(0);
+ dataddr[0] = cpu_to_le32(0);
+ }
+
+ if ((host->flags & SDHCI_USE_SDMA) &&
+ (host->data->flags & MMC_DATA_READ))
+ host->data->error = 0;
+
+ return;
}
static int esdhc_of_enable_dma(struct sdhci_host *host)
@@ -220,15 +357,39 @@ static void esdhc_of_suspend(struct sdhci_host *host)
static void esdhc_of_resume(struct sdhci_host *host)
{
- esdhc_of_enable_dma(host);
sdhci_be32bs_writel(host, esdhc_proctl, SDHCI_HOST_CONTROL);
}
#endif
+static void esdhc_of_platform_reset_enter(struct sdhci_host *host, u8 mask)
+{
+ if ((host->quirks2 & SDHCI_QUIRK2_DISABLE_CLOCK_BEFORE_RESET) &&
+ (mask & SDHCI_RESET_ALL)) {
+ u16 clk;
+
+ clk = esdhc_readw(host, SDHCI_CLOCK_CONTROL);
+ clk &= ~ESDHC_CLOCK_CRDEN;
+ esdhc_writew(host, clk, SDHCI_CLOCK_CONTROL);
+ }
+}
+
+static void esdhc_of_platform_reset_exit(struct sdhci_host *host, u8 mask)
+{
+ if ((host->quirks2 & SDHCI_QUIRK2_DISABLE_CLOCK_BEFORE_RESET) &&
+ (mask & SDHCI_RESET_ALL)) {
+ u16 clk;
+
+ clk = esdhc_readw(host, SDHCI_CLOCK_CONTROL);
+ clk |= ESDHC_CLOCK_CRDEN;
+ esdhc_writew(host, clk, SDHCI_CLOCK_CONTROL);
+ }
+}
+
static void esdhc_of_platform_init(struct sdhci_host *host)
{
u32 vvn;
+ svr = mfspr(SPRN_SVR);
vvn = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
vvn = (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
if (vvn == VENDOR_V_22)
@@ -236,6 +397,75 @@ static void esdhc_of_platform_init(struct sdhci_host *host)
if (vvn > VENDOR_V_22)
host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
+
+ /*
+ * Check for A-005055: A glitch is generated on the card clock
+ * due to software reset or a clock change
+ * Impact list:
+ * T4240-4160-R1.0 B4860-4420-R1.0-R2.0 P3041-R1.0-R1.1-R2.0
+ * P2041-2040-R1.0-R1.1-R2.0 P1010-1014-R1.0 P5020-5010-R1.0-R2.0
+ * P5040-5021-R1.0-R2.0-R2.1
+ */
+ if (((SVR_SOC_VER(svr) == SVR_T4240) && (SVR_REV(svr) == 0x10)) ||
+ ((SVR_SOC_VER(svr) == SVR_T4240) && (SVR_REV(svr) == 0x20)) ||
+ ((SVR_SOC_VER(svr) == SVR_T4160) && (SVR_REV(svr) == 0x10)) ||
+ ((SVR_SOC_VER(svr) == SVR_T4160) && (SVR_REV(svr) == 0x20)) ||
+ ((SVR_SOC_VER(svr) == SVR_B4860) && (SVR_REV(svr) == 0x10)) ||
+ ((SVR_SOC_VER(svr) == SVR_B4860) && (SVR_REV(svr) == 0x20)) ||
+ ((SVR_SOC_VER(svr) == SVR_B4420) && (SVR_REV(svr) == 0x10)) ||
+ ((SVR_SOC_VER(svr) == SVR_B4420) && (SVR_REV(svr) == 0x20)) ||
+ ((SVR_SOC_VER(svr) == SVR_P5040) && (SVR_REV(svr) <= 0x21)) ||
+ ((SVR_SOC_VER(svr) == SVR_P5020) && (SVR_REV(svr) <= 0x20)) ||
+ ((SVR_SOC_VER(svr) == SVR_P5021) && (SVR_REV(svr) <= 0x21)) ||
+ ((SVR_SOC_VER(svr) == SVR_P5010) && (SVR_REV(svr) <= 0x20)) ||
+ ((SVR_SOC_VER(svr) == SVR_P3041) && (SVR_REV(svr) <= 0x20)) ||
+ ((SVR_SOC_VER(svr) == SVR_P2041) && (SVR_REV(svr) <= 0x20)) ||
+ ((SVR_SOC_VER(svr) == SVR_P2040) && (SVR_REV(svr) <= 0x20)) ||
+ ((SVR_SOC_VER(svr) == SVR_P1014) && (SVR_REV(svr) == 0x10)) ||
+ ((SVR_SOC_VER(svr) == SVR_P1010) && (SVR_REV(svr) == 0x10)))
+ host->quirks2 |= SDHCI_QUIRK2_DISABLE_CLOCK_BEFORE_RESET;
+}
+
+/* Return: 1 - the card is present; 0 - card is absent */
+static int esdhc_of_get_cd(struct sdhci_host *host)
+{
+ u32 present;
+ u32 sysctl;
+
+ if (host->flags & SDHCI_DEVICE_DEAD)
+ return 0;
+ if (host->quirks2 & SDHCI_QUIRK2_FORCE_CMD13_DETECT_CARD)
+ return -ENOSYS;
+
+ sysctl = sdhci_be32bs_readl(host, SDHCI_CLOCK_CONTROL);
+
+ /* Enable the controller clock to update the present state */
+ sdhci_be32bs_writel(host, sysctl | SDHCI_CLOCK_INT_EN,
+ SDHCI_CLOCK_CONTROL);
+
+ /* Detect the card present or absent */
+ present = sdhci_be32bs_readl(host, SDHCI_PRESENT_STATE);
+ present &= (SDHCI_CARD_PRESENT | SDHCI_CARD_CDPL);
+
+ /* Resave the previous to System control register */
+ sdhci_be32bs_writel(host, sysctl, SDHCI_CLOCK_CONTROL);
+
+ return !!present;
+}
+
+static void esdhc_get_pltfm_irq(struct sdhci_host *host, u32 *irq)
+{
+ *irq |= ESDHC_INT_DMA_ERROR;
+}
+
+static void esdhc_pltfm_irq_handler(struct sdhci_host *host, u32 intmask)
+{
+ if (intmask & (ESDHC_INT_DMA_ERROR | SDHCI_INT_ADMA_ERROR)) {
+ host->data->error = -EIO;
+ pr_err("%s: ADMA error\n", mmc_hostname(host->mmc));
+ sdhci_show_adma_error(host);
+ esdhci_of_adma_workaround(host, intmask);
+ }
}
static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width)
@@ -273,7 +503,12 @@ static const struct sdhci_ops sdhci_esdhc_ops = {
.enable_dma = esdhc_of_enable_dma,
.get_max_clock = esdhc_of_get_max_clock,
.get_min_clock = esdhc_of_get_min_clock,
+ .get_platform_irq = esdhc_get_pltfm_irq,
+ .handle_platform_irq = esdhc_pltfm_irq_handler,
+ .platform_reset_enter = esdhc_of_platform_reset_enter,
+ .platform_reset_exit = esdhc_of_platform_reset_exit,
.platform_init = esdhc_of_platform_init,
+ .get_cd = esdhc_of_get_cd,
#ifdef CONFIG_PM
.platform_suspend = esdhc_of_suspend,
.platform_resume = esdhc_of_resume,
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index e2065a4..fb3eecc 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -83,9 +83,6 @@ void sdhci_get_of_property(struct platform_device *pdev)
if (sdhci_of_wp_inverted(np))
host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
- if (of_get_property(np, "broken-cd", NULL))
- host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
-
if (of_get_property(np, "no-1-8-v", NULL))
host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
@@ -98,6 +95,21 @@ void sdhci_get_of_property(struct platform_device *pdev)
of_device_is_compatible(np, "fsl,mpc8536-esdhc"))
host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+ if (of_device_is_compatible(np, "fsl,t4240-esdhc")) {
+ host->quirks2 |= SDHCI_QUIRK2_LONG_TIME_CMD_COMPLETE_IRQ;
+ host->quirks2 |= SDHCI_QUIRK2_FORCE_CMD13_DETECT_CARD;
+ host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
+ }
+
+ if (of_device_is_compatible(np, "fsl,p5020-esdhc"))
+ host->quirks2 |= SDHCI_QUIRK2_LONG_TIME_CMD_COMPLETE_IRQ;
+
+ if (of_device_is_compatible(np, "fsl,p5040-esdhc") ||
+ of_device_is_compatible(np, "fsl,p5020-esdhc") ||
+ of_device_is_compatible(np, "fsl,p4080-esdhc") ||
+ of_device_is_compatible(np, "fsl,p1020-esdhc"))
+ host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+
clk = of_get_property(np, "clock-frequency", &size);
if (clk && size == sizeof(*clk) && *clk)
pltfm_host->clock = be32_to_cpup(clk);
@@ -208,13 +220,16 @@ int sdhci_pltfm_register(struct platform_device *pdev,
size_t priv_size)
{
struct sdhci_host *host;
+ struct device_node *np;
int ret = 0;
+ np = pdev->dev.of_node;
host = sdhci_pltfm_init(pdev, pdata, priv_size);
if (IS_ERR(host))
return PTR_ERR(host);
sdhci_get_of_property(pdev);
+ mmc_of_parse_voltage(np, &host->ocr_mask);
ret = sdhci_add_host(host);
if (ret)
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 7a7fb4f..c76dab0 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -181,7 +181,7 @@ static void sdhci_disable_card_detection(struct sdhci_host *host)
sdhci_set_card_detection(host, false);
}
-static void sdhci_reset(struct sdhci_host *host, u8 mask)
+void sdhci_reset(struct sdhci_host *host, u8 mask)
{
unsigned long timeout;
u32 uninitialized_var(ier);
@@ -238,16 +238,25 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios);
static void sdhci_init(struct sdhci_host *host, int soft)
{
+ u32 pltm_irq = 0, irq = 0;
+
if (soft)
sdhci_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA);
else
sdhci_reset(host, SDHCI_RESET_ALL);
- sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK,
- SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
+ irq = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX |
SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
- SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE);
+ SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE;
+
+ if (pltm_irq)
+ irq |= pltm_irq;
+
+ if (host->flags & SDHCI_AUTO_CMD12)
+ irq |= SDHCI_INT_ACMD12ERR;
+
+ sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, irq);
if (soft) {
/* force clock reconfiguration */
@@ -986,6 +995,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
int flags;
u32 mask;
unsigned long timeout;
+ int timer = 10;
WARN_ON(host->cmd);
@@ -1014,7 +1024,13 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
mdelay(1);
}
- mod_timer(&host->timer, jiffies + 10 * HZ);
+ /* In case some controller need long time to generate command
+ * interrupt, 1000 * HZ will be enough.
+ */
+ if (host->quirks2 & SDHCI_QUIRK2_LONG_TIME_CMD_COMPLETE_IRQ)
+ timer = 1000;
+
+ mod_timer(&host->timer, jiffies + timer * HZ);
host->cmd = cmd;
@@ -2238,9 +2254,12 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
if (intmask & SDHCI_INT_TIMEOUT)
host->cmd->error = -ETIMEDOUT;
else if (intmask & (SDHCI_INT_CRC | SDHCI_INT_END_BIT |
- SDHCI_INT_INDEX))
+ SDHCI_INT_INDEX | SDHCI_INT_ACMD12ERR))
host->cmd->error = -EILSEQ;
+ if (host->ops->handle_platform_irq)
+ host->ops->handle_platform_irq(host, intmask);
+
if (host->cmd->error) {
tasklet_schedule(&host->finish_tasklet);
return;
@@ -2273,7 +2292,7 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
}
#ifdef CONFIG_MMC_DEBUG
-static void sdhci_show_adma_error(struct sdhci_host *host)
+void sdhci_show_adma_error(struct sdhci_host *host)
{
const char *name = mmc_hostname(host->mmc);
u8 *desc = host->adma_desc;
@@ -2298,7 +2317,7 @@ static void sdhci_show_adma_error(struct sdhci_host *host)
}
}
#else
-static void sdhci_show_adma_error(struct sdhci_host *host) { }
+void sdhci_show_adma_error(struct sdhci_host *host) { }
#endif
static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
@@ -2350,10 +2369,11 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
pr_err("%s: ADMA error\n", mmc_hostname(host->mmc));
sdhci_show_adma_error(host);
host->data->error = -EIO;
- if (host->ops->adma_workaround)
- host->ops->adma_workaround(host, intmask);
}
+ if (host->ops->handle_platform_irq)
+ host->ops->handle_platform_irq(host, intmask);
+
if (host->data->error)
sdhci_finish_data(host);
else {
@@ -2408,6 +2428,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
struct sdhci_host *host = dev_id;
u32 intmask, unexpected = 0;
int cardint = 0, max_loops = 16;
+ u32 cmd_mask = SDHCI_INT_CMD_MASK;
spin_lock(&host->lock);
@@ -2454,10 +2475,9 @@ again:
tasklet_schedule(&host->card_tasklet);
}
- if (intmask & SDHCI_INT_CMD_MASK) {
- sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK,
- SDHCI_INT_STATUS);
- sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
+ if (intmask & cmd_mask) {
+ sdhci_writel(host, intmask & cmd_mask, SDHCI_INT_STATUS);
+ sdhci_cmd_irq(host, intmask & cmd_mask);
}
if (intmask & SDHCI_INT_DATA_MASK) {
@@ -2466,7 +2486,7 @@ again:
sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
}
- intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK);
+ intmask &= ~(cmd_mask | SDHCI_INT_DATA_MASK);
intmask &= ~SDHCI_INT_ERROR;
@@ -2797,6 +2817,9 @@ int sdhci_add_host(struct sdhci_host *host)
host->caps1 :
sdhci_readl(host, SDHCI_CAPABILITIES_1);
+ if (host->quirks2 & SDHCI_QUIRK2_CIRCUIT_SUPPORT_VS33)
+ caps[0] = caps[0] | SDHCI_CAN_VDD_330;
+
if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
host->flags |= SDHCI_USE_SDMA;
else if (!(caps[0] & SDHCI_CAN_DO_SDMA))
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index b037f18..096b203 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -69,6 +69,7 @@
#define SDHCI_SPACE_AVAILABLE 0x00000400
#define SDHCI_DATA_AVAILABLE 0x00000800
#define SDHCI_CARD_PRESENT 0x00010000
+#define SDHCI_CARD_CDPL 0x00040000
#define SDHCI_WRITE_PROTECT 0x00080000
#define SDHCI_DATA_LVL_MASK 0x00F00000
#define SDHCI_DATA_LVL_SHIFT 20
@@ -277,6 +278,7 @@ struct sdhci_ops {
void (*set_clock)(struct sdhci_host *host, unsigned int clock);
+ int (*get_cd)(struct sdhci_host *host);
int (*enable_dma)(struct sdhci_host *host);
unsigned int (*get_max_clock)(struct sdhci_host *host);
unsigned int (*get_min_clock)(struct sdhci_host *host);
@@ -292,6 +294,8 @@ struct sdhci_ops {
void (*hw_reset)(struct sdhci_host *host);
void (*platform_suspend)(struct sdhci_host *host);
void (*platform_resume)(struct sdhci_host *host);
+ void (*get_platform_irq)(struct sdhci_host *host, u32 *irq);
+ void (*handle_platform_irq)(struct sdhci_host *host, u32 intmask);
void (*adma_workaround)(struct sdhci_host *host, u32 intmask);
void (*platform_init)(struct sdhci_host *host);
void (*card_event)(struct sdhci_host *host);
@@ -390,6 +394,7 @@ static inline void *sdhci_priv(struct sdhci_host *host)
return (void *)host->private;
}
+extern void sdhci_reset(struct sdhci_host *host, u8 mask);
extern void sdhci_card_detect(struct sdhci_host *host);
extern int sdhci_add_host(struct sdhci_host *host);
extern void sdhci_remove_host(struct sdhci_host *host, int dead);
@@ -405,4 +410,5 @@ extern int sdhci_runtime_suspend_host(struct sdhci_host *host);
extern int sdhci_runtime_resume_host(struct sdhci_host *host);
#endif
+extern void sdhci_show_adma_error(struct sdhci_host *host);
#endif /* __SDHCI_HW_H */
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index f111f04..77083c6 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -30,6 +30,7 @@
#include <linux/mtd/cfi.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
+#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/spi/spi.h>
@@ -783,10 +784,12 @@ static const struct spi_device_id m25p_ids[] = {
{ "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, 0) },
/* Micron */
- { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) },
- { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) },
- { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) },
- { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) },
+ { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) },
+ { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) },
+ { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) },
+ { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) },
+ { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K) },
+ { "n25q512a", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K) },
/* PMC */
{ "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) },
@@ -938,9 +941,11 @@ static int m25p_probe(struct spi_device *spi)
struct flash_platform_data *data;
struct m25p *flash;
struct flash_info *info;
- unsigned i;
+ unsigned i, ret;
struct mtd_part_parser_data ppdata;
struct device_node __maybe_unused *np = spi->dev.of_node;
+ struct resource res;
+ struct device_node *mnp = spi->master->dev.of_node;
#ifdef CONFIG_MTD_OF_PARTS
if (!of_device_is_available(np))
@@ -1018,8 +1023,17 @@ static int m25p_probe(struct spi_device *spi)
if (data && data->name)
flash->mtd.name = data->name;
- else
- flash->mtd.name = dev_name(&spi->dev);
+ else {
+ ret = of_address_to_resource(mnp, 0, &res);
+ if (ret) {
+ dev_err(&spi->dev, "failed to get spi master resource\n");
+ return ret;
+ }
+ flash->mtd.name = kasprintf(GFP_KERNEL, "spi%x.%d",
+ (unsigned)res.start, spi->chip_select);
+ if (!flash->mtd.name)
+ return -ENOMEM;
+ }
flash->mtd.type = MTD_NORFLASH;
flash->mtd.writesize = 1;
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
index 317a771..eb150f1 100644
--- a/drivers/mtd/nand/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/fsl_ifc_nand.c
@@ -135,6 +135,69 @@ static struct nand_ecclayout oob_4096_ecc8 = {
.oobfree = { {2, 6}, {136, 82} },
};
+/* 8192-byte page size with 4-bit ECC */
+static struct nand_ecclayout oob_8192_ecc4 = {
+ .eccbytes = 128,
+ .eccpos = {
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, 135,
+ },
+ .oobfree = { {2, 6}, {136, 208} },
+};
+
+/* 8192-byte page size with 8-bit ECC -- requires 218-byte OOB */
+static struct nand_ecclayout oob_8192_ecc8 = {
+ .eccbytes = 256,
+ .eccpos = {
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63,
+ 64, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87,
+ 88, 89, 90, 91, 92, 93, 94, 95,
+ 96, 97, 98, 99, 100, 101, 102, 103,
+ 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119,
+ 120, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, 135,
+ 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151,
+ 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167,
+ 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183,
+ 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199,
+ 200, 201, 202, 203, 204, 205, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215,
+ 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228, 229, 230, 231,
+ 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247,
+ 248, 249, 250, 251, 252, 253, 254, 255,
+ 256, 257, 258, 259, 260, 261, 262, 263,
+ },
+ .oobfree = { {2, 6}, {264, 80} },
+};
/*
* Generic flash bbt descriptors
@@ -441,20 +504,29 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
if (mtd->writesize > 512) {
nand_fcr0 =
(NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) |
- (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD1_SHIFT);
+ (NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) |
+ (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT);
iowrite32be(
- (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
- (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
- (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
- (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP3_SHIFT) |
- (IFC_FIR_OP_CW1 << IFC_NAND_FIR0_OP4_SHIFT),
- &ifc->ifc_nand.nand_fir0);
+ (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
+ (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) |
+ (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) |
+ (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP3_SHIFT) |
+ (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT),
+ &ifc->ifc_nand.nand_fir0);
+ iowrite32be(
+ (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) |
+ (IFC_FIR_OP_RDSTAT <<
+ IFC_NAND_FIR1_OP6_SHIFT) |
+ (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT),
+ &ifc->ifc_nand.nand_fir1);
} else {
nand_fcr0 = ((NAND_CMD_PAGEPROG <<
IFC_NAND_FCR0_CMD1_SHIFT) |
(NAND_CMD_SEQIN <<
- IFC_NAND_FCR0_CMD2_SHIFT));
+ IFC_NAND_FCR0_CMD2_SHIFT) |
+ (NAND_CMD_STATUS <<
+ IFC_NAND_FCR0_CMD3_SHIFT));
iowrite32be(
(IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) |
@@ -463,8 +535,13 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command,
(IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) |
(IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT),
&ifc->ifc_nand.nand_fir0);
- iowrite32be(IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT,
- &ifc->ifc_nand.nand_fir1);
+ iowrite32be(
+ (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) |
+ (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) |
+ (IFC_FIR_OP_RDSTAT <<
+ IFC_NAND_FIR1_OP7_SHIFT) |
+ (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT),
+ &ifc->ifc_nand.nand_fir1);
if (column >= mtd->writesize)
nand_fcr0 |=
@@ -872,11 +949,25 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv)
} else {
layout = &oob_4096_ecc8;
chip->ecc.bytes = 16;
+ chip->ecc.strength = 8;
}
priv->bufnum_mask = 1;
break;
+ case CSOR_NAND_PGS_8K:
+ if ((csor & CSOR_NAND_ECC_MODE_MASK) ==
+ CSOR_NAND_ECC_MODE_4) {
+ layout = &oob_8192_ecc4;
+ } else {
+ layout = &oob_8192_ecc8;
+ chip->ecc.bytes = 16;
+ chip->ecc.strength = 8;
+ }
+
+ priv->bufnum_mask = 0;
+ break;
+
default:
dev_err(priv->dev, "bad csor %#x: bad page size\n", csor);
return -ENODEV;
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index b45b240..dfe8a62 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -24,6 +24,148 @@ menuconfig NETDEVICES
# All the following symbols are dependent on NETDEVICES - do not repeat
# that for each of the symbols.
if NETDEVICES
+config AS_FASTPATH
+ default n
+ bool "Application Specific FastPath"
+ select NAMESPACES
+ select NET_NS
+ select NETFILTER
+ select NETFILTER_ADVANCED
+ select NF_CONNTRACK
+ select NF_CONNTRACK_EVENTS
+ select NF_CONNTRACK_FTP
+ select NF_CONNTRACK_TFTP
+ select NETFILTER_XTABLES
+ select NF_CONNTRACK_IPV4
+ select NF_CONNTRACK_PROC_COMPAT
+ select IP_NF_IPTABLES
+ select IP_NF_MATCH_ADDRTYPE
+ select IP_NF_FILTER
+ select NF_NAT_IPV4
+ select IP_NF_TARGET_REJECT
+ select NF_NAT_NEEDED
+ select IP_NF_TARGET_MASQUERADE
+ select IP_NF_TARGET_REDIRECT
+ select NF_NAT_FTP
+ select NF_NAT_TFTP
+ select IP_NF_MANGLE
+ select VLAN_8021Q
+ select INET_AH
+ select PPP
+ select PPPOE
+ ---help---
+ Enables application specific fastpath n/w stack that
+ accelerates the throughput for forwarding, firewall, NAT and IPsec
+ over native Linux stack.
+
+if AS_FASTPATH
+config FSL_DPAA_ETH_MAX_BUF_COUNT
+ int
+ depends on FSL_DPAA_ETH
+ range 64 2048
+ default "256"
+ ---help---
+ The maximum number of buffers to be by default allocated in the DPAA-Ethernet private port's
+ buffer pool. One needn't normally modify this, as it has probably been tuned for performance
+ already. This cannot be lower than DPAA_ETH_REFILL_THRESHOLD.
+endif
+config ASF_IPV6
+ default y
+ bool "IPv6 Support in ASF"
+ depends on AS_FASTPATH
+ select IPV6
+ select IPV6_SIT
+ select IPV6_TUNNEL
+ select INET6_TUNNEL
+ select INET6_ESP
+ select INET6_AH
+ select INET6_XFRM_TUNNEL
+ select NF_CONNTRACK_IPV6
+ select INET6_XFRM_MODE_TUNNEL
+ select IP6_NF_IPTABLES
+ select IP6_NF_FILTER
+ select IP6_NF_RAW
+ ---help---
+ This option compiles the ASF for IPV6
+ Firewall and IPsec.
+
+config ASF_QOS
+ default y
+ bool "ASF QoS Support"
+ depends on AS_FASTPATH
+ select NETFILTER_XT_TARGET_DSCP
+ select NET_SCHED
+ select NET_SCH_PRIO
+ select NET_SCH_TBF
+ select NET_SCH_DRR
+ select NET_CLS
+ select NET_CLS_BASIC
+ select NET_CLS_U32
+ select NET_CLS_FLOW
+ select NET_SCH_FIFO
+ select IP_NF_MANGLE
+ select IP6_NF_MANGLE
+
+config ASF_EGRESS_QOS
+ default y
+ bool
+ depends on ASF_QOS
+
+config ASF_INGRESS_MARKER
+ default y
+ bool "DSCP Marking Support"
+ depends on ASF_QOS && ASF_EGRESS_QOS
+ ---help---
+ Choose this option if you wish to utilize ASF Marking support.
+ Currently only DSCP marking is supported.
+
+config ASF_EGRESS_SCH
+ default y
+ bool "S/W Scheduler Support"
+ depends on ASF_QOS && ASF_EGRESS_QOS && !DPA_ETH
+ ---help---
+ Choose this option if you wish to utilize ASF S/W based Scheduler support.
+
+config ASF_EGRESS_SHAPER
+ default y
+ bool "S/W Shaper Support"
+ depends on ASF_QOS && ASF_EGRESS_QOS && ASF_EGRESS_SCH && !DPA_ETH
+
+ ---help---
+ Choose this option if you wish to utilize ASF S/W based Shaping support.
+ The S/W Shaper can be used only if S/W Scheduler is enabled.
+
+config ASF_HW_SCH
+ default y
+ bool "ASF H/W Scheduler Support"
+ depends on ASF_QOS && ASF_EGRESS_QOS && !ASF_EGRESS_SCH
+ ---help---
+ Choose this option if you wish to utilize eTSEC(NON-DPAA) / DPAA TX Scheduler.
+choice
+ prompt "Select Scheduling Algorithm"
+ depends on ASF_HW_SCH && !DPA_ETH
+ default ASF_SCH_PRIO
+
+config ASF_SCH_PRIO
+ bool "Strict Priority (PRIO)"
+ ---help---
+ This option compiles the ASF to utilize eTSEC(NON-DPAA)
+ H/W Scheduler with PRIORITY algorithm.
+
+config ASF_SCH_MWRR
+ bool "Modified Weighted Round-Robin (MWRR)"
+ ---help---
+ This option compiles the ASF to utilize eTSEC(NON-DPAA)
+ H/W Scheduler with Modified Weighted Round-Robin algorithm.
+
+endchoice
+
+config ASF_HW_SHAPER
+ default y
+ bool "ASF H/W Shaper Support"
+ depends on ASF_QOS && ASF_EGRESS_QOS && DPA_ETH
+ ---help---
+ Choose this option if you wish to utilize DPAA TX Shaper.
config MII
tristate
diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig
index 6048dc8..80c9bb7 100644
--- a/drivers/net/ethernet/freescale/Kconfig
+++ b/drivers/net/ethernet/freescale/Kconfig
@@ -67,8 +67,10 @@ config FSL_XGMAC_MDIO
tristate "Freescale XGMAC MDIO"
depends on FSL_SOC
select PHYLIB
+ select OF_MDIO
---help---
- This driver supports the MDIO bus on the Fman 10G Ethernet MACs.
+ This driver supports the MDIO bus on the Fman 10G Ethernet MACs, and
+ on the FMan mEMAC (which supports both Clauses 22 and 45)
config UCC_GETH
tristate "Freescale QE Gigabit Ethernet"
@@ -93,4 +95,16 @@ config GIANFAR
This driver supports the Gigabit TSEC on the MPC83xx, MPC85xx,
and MPC86xx family of chips, and the FEC on the 8540.
+config FSL_GIANFAR_1588
+ bool "Gianfar 1588"
+ depends on GIANFAR
+ ---help---
+ This driver supports Freescale eTSEC 1588 function.
+ Integrate the IEEE 1588 specification v2 ioctls with the gianfar driver.
+ The user space application should be IXXAT IEEE 1588 stack v1.04 or above.
+ Say Y here if you want to use IXXAT 1588 stack.
+
+source "drivers/net/ethernet/freescale/fman/Kconfig"
+source "drivers/net/ethernet/freescale/dpa/Kconfig"
+
endif # NET_VENDOR_FREESCALE
diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile
index 549ce13..4fff029 100644
--- a/drivers/net/ethernet/freescale/Makefile
+++ b/drivers/net/ethernet/freescale/Makefile
@@ -12,9 +12,14 @@ obj-$(CONFIG_FS_ENET) += fs_enet/
obj-$(CONFIG_FSL_PQ_MDIO) += fsl_pq_mdio.o
obj-$(CONFIG_FSL_XGMAC_MDIO) += xgmac_mdio.o
obj-$(CONFIG_GIANFAR) += gianfar_driver.o
+obj-$(if $(CONFIG_FSL_FMAN),y) += fman/
+obj-$(if $(CONFIG_FSL_DPAA_ETH),y) += dpa/
obj-$(CONFIG_PTP_1588_CLOCK_GIANFAR) += gianfar_ptp.o
gianfar_driver-objs := gianfar.o \
- gianfar_ethtool.o \
- gianfar_sysfs.o
+ gianfar_ethtool.o
+ifeq ($(CONFIG_GIANFAR),y)
+ obj-$(CONFIG_AS_FASTPATH) += asf_gianfar.o
+endif
+gianfar_driver-$(CONFIG_FSL_GIANFAR_1588) += gianfar_1588.o
obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o
ucc_geth_driver-objs := ucc_geth.o ucc_geth_ethtool.o
diff --git a/drivers/net/ethernet/freescale/asf_gianfar.c b/drivers/net/ethernet/freescale/asf_gianfar.c
new file mode 100644
index 0000000..af7f205
--- /dev/null
+++ b/drivers/net/ethernet/freescale/asf_gianfar.c
@@ -0,0 +1,624 @@
+/* drivers/net/ethernet/freescale/asf_gianfar.c
+ *
+ * Gianfar ASF function
+ *
+ * Description : This file is designed to add ASF functionality to gianfar.c
+ * This functionalities includes tx_hook for asf and some
+ * optimization for packet xmit.
+ *
+ * Author : Alok Makhariya
+ *
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/if_vlan.h>
+#include "gianfar.h"
+#include "asf_gianfar.h"
+
+#define RT_PKT_ID 0xff
+#define KER_PKT_ID 0xfe
+
+#define GFAR_RXB_REC_SZ (DEFAULT_RX_BUFFER_SIZE + RXBUF_ALIGNMENT)
+
+devfp_hook_t devfp_rx_hook;
+EXPORT_SYMBOL(devfp_rx_hook);
+
+devfp_hook_t devfp_tx_hook;
+EXPORT_SYMBOL(devfp_tx_hook);
+
+static inline void gfar_asf_reclaim_skb(struct sk_buff *skb)
+{
+ /* Just reset the fields used in software DPA */
+ skb->next = skb->prev = NULL;
+ skb->dev = NULL;
+ skb->len = 0;
+ skb->ip_summed = 0;
+ skb->transport_header = 0;
+ skb->mac_header = 0;
+ skb->network_header = 0;
+ skb->pkt_type = 0;
+ skb->mac_len = 0;
+ skb->protocol = 0;
+ skb->vlan_tci = 0;
+ skb->data = 0;
+ /* reset data and tail pointers */
+ skb->data = skb->head + NET_SKB_PAD;
+ skb_reset_tail_pointer(skb);
+}
+
+static inline void gfar_recycle_skb(struct sk_buff *skb)
+{
+ struct sk_buff_head *h = &__get_cpu_var(skb_recycle_list);
+ int skb_size = SKB_DATA_ALIGN(GFAR_RXB_REC_SZ + NET_SKB_PAD);
+
+ if (skb_queue_len(h) < DEFAULT_RX_RING_SIZE &&
+ !skb_cloned(skb) && !skb_is_nonlinear(skb) &&
+ skb->fclone == SKB_FCLONE_UNAVAILABLE && !skb_shared(skb) &&
+ skb_end_offset(skb) == skb_size) {
+
+ if (skb->pkt_type == PACKET_FASTROUTE)
+ gfar_asf_reclaim_skb(skb);
+ else
+ skb_recycle(skb);
+
+ gfar_align_skb(skb);
+
+ __skb_queue_head(h, skb);
+
+ return;
+ }
+
+ dev_kfree_skb_any(skb);
+}
+
+/* gfar_process_frame() -- handle one incoming packet if skb isn't NULL. */
+static void gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
+ int amount_pull, struct napi_struct *napi)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct rxfcb *fcb = NULL;
+
+ /* fcb is at the beginning if exists */
+ fcb = (struct rxfcb *)skb->data;
+
+ /* Remove the FCB from the skb
+ * Remove the padded bytes, if there are any
+ */
+ if (amount_pull) {
+ skb_record_rx_queue(skb, fcb->rq);
+ skb_pull(skb, amount_pull);
+ }
+
+ /* Get receive timestamp from the skb */
+ if (priv->hwts_rx_en) {
+ struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
+ u64 *ns = (u64 *) skb->data;
+
+ memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+ shhwtstamps->hwtstamp = ns_to_ktime(*ns);
+ }
+
+ if (priv->padding)
+ skb_pull(skb, priv->padding);
+
+ if (dev->features & NETIF_F_RXCSUM)
+ gfar_rx_checksum(skb, fcb);
+
+ if (devfp_rx_hook) {
+ /* Drop the packet silently if IP Checksum is not correct */
+ if ((fcb->flags & RXFCB_CIP) && (fcb->flags & RXFCB_EIP)) {
+ dev_kfree_skb_any(skb);
+ return;
+ }
+ if (dev->features & NETIF_F_HW_VLAN_CTAG_RX &&
+ fcb->flags & RXFCB_VLN)
+ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), fcb->vlctl);
+
+ skb->dev = dev;
+ if (devfp_rx_hook(skb, dev) == AS_FP_STOLEN)
+ return;
+ }
+
+ /* Tell the skb what kind of packet this is */
+ skb->protocol = eth_type_trans(skb, dev);
+
+ /* There's need to check for NETIF_F_HW_VLAN_CTAG_RX here.
+ * Even if vlan rx accel is disabled, on some chips
+ * RXFCB_VLN is pseudo randomly set.
+ */
+ if (dev->features & NETIF_F_HW_VLAN_CTAG_RX &&
+ fcb->flags & RXFCB_VLN)
+ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), fcb->vlctl);
+
+ /* Send the packet up the stack */
+ napi_gro_receive(napi, skb);
+
+}
+
+int gfar_asf_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct gfar_priv_tx_q *tx_queue = NULL;
+ struct netdev_queue *txq;
+ struct gfar __iomem *regs = NULL;
+ struct txfcb *fcb = NULL;
+ struct txbd8 *txbdp, *txbdp_start, *base, *txbdp_tstamp = NULL;
+ u32 lstatus;
+ int i, rq = 0;
+ int do_tstamp, do_csum, do_vlan;
+ u32 bufaddr;
+ int skb_curtx = 0;
+ unsigned int nr_frags, nr_txbds, bytes_sent, fcb_len = 0;
+
+ if (devfp_tx_hook && (skb->pkt_type != PACKET_FASTROUTE))
+ if (devfp_tx_hook(skb, dev) == AS_FP_STOLEN)
+ return 0;
+
+ rq = smp_processor_id();
+
+ tx_queue = priv->tx_queue[rq];
+ txq = netdev_get_tx_queue(dev, rq);
+ base = tx_queue->tx_bd_base;
+ regs = tx_queue->grp->regs;
+ do_csum = (CHECKSUM_PARTIAL == skb->ip_summed);
+ do_vlan = vlan_tx_tag_present(skb);
+ do_tstamp = (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
+ priv->hwts_tx_en;
+ if (do_csum || do_vlan)
+ fcb_len = GMAC_FCB_LEN;
+ /* check if time stamp should be generated */
+ if (unlikely(do_tstamp))
+ fcb_len = GMAC_FCB_LEN + GMAC_TXPAL_LEN;
+
+ /* make space for additional header when fcb is needed */
+ if (fcb_len && unlikely(skb_headroom(skb) < fcb_len)) {
+ struct sk_buff *skb_new;
+ skb_new = skb_realloc_headroom(skb, fcb_len);
+ if (!skb_new) {
+ dev->stats.tx_errors++;
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ if (skb->sk)
+ skb_set_owner_w(skb_new, skb->sk);
+ consume_skb(skb);
+ skb = skb_new;
+ }
+
+ /* total number of fragments in the SKB */
+ nr_frags = skb_shinfo(skb)->nr_frags;
+
+ /* calculate the required number of TxBDs for this skb */
+ if (unlikely(do_tstamp))
+ nr_txbds = nr_frags + 2;
+ else
+ nr_txbds = nr_frags + 1;
+
+ txbdp = tx_queue->cur_tx;
+ skb_curtx = tx_queue->skb_curtx;
+ do {
+ lstatus = txbdp->lstatus;
+ if ((lstatus & BD_LFLAG(TXBD_READY))) {
+ u32 imask;
+ /* BD not free for tx */
+ netif_tx_stop_queue(txq);
+ dev->stats.tx_fifo_errors++;
+ spin_lock_irq(&tx_queue->grp->grplock);
+ imask = gfar_read(&regs->imask);
+ imask |= IMASK_TX_DEFAULT;
+ gfar_write(&regs->imask, imask);
+ spin_unlock_irq(&tx_queue->grp->grplock);
+ return NETDEV_TX_BUSY;
+ }
+
+ /* BD is free to be used by s/w */
+ /* Free skb for this BD if not recycled */
+
+ txbdp->lstatus &= BD_LFLAG(TXBD_WRAP);
+ skb_curtx = (skb_curtx + 1)
+ & TX_RING_MOD_MASK(tx_queue->tx_ring_size);
+ nr_txbds--;
+
+ if (!nr_txbds)
+ break;
+
+ txbdp = next_txbd(txbdp, base, tx_queue->tx_ring_size);
+ } while (1);
+
+ /* Update transmit stats */
+ bytes_sent = skb->len;
+ tx_queue->stats.tx_bytes += bytes_sent;
+ /* keep Tx bytes on wire for BQL accounting */
+ GFAR_CB(skb)->bytes_sent = bytes_sent;
+ tx_queue->stats.tx_packets++;
+
+ txbdp = txbdp_start = tx_queue->cur_tx;
+ lstatus = txbdp->lstatus;
+
+ /* Time stamp insertion requires one additional TxBD */
+ if (unlikely(do_tstamp))
+ txbdp_tstamp = txbdp = next_txbd(txbdp, base,
+ tx_queue->tx_ring_size);
+
+ if (nr_frags == 0) {
+ if (unlikely(do_tstamp))
+ txbdp_tstamp->lstatus |= BD_LFLAG(TXBD_LAST |
+ TXBD_INTERRUPT);
+ else
+ lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT);
+ } else {
+ /* Place the fragment addresses and lengths into the TxBDs */
+ for (i = 0; i < nr_frags; i++) {
+ unsigned int frag_len;
+ /* Point at the next BD, wrapping as needed */
+ txbdp = next_txbd(txbdp, base, tx_queue->tx_ring_size);
+ frag_len = skb_shinfo(skb)->frags[i].size;
+ lstatus = txbdp->lstatus | frag_len |
+ BD_LFLAG(TXBD_READY);
+
+ /* Handle the last BD specially */
+ if (i == nr_frags - 1)
+ lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT);
+
+ bufaddr = skb_frag_dma_map(priv->dev,
+ &skb_shinfo(skb)->frags[i],
+ 0,
+ frag_len,
+ DMA_TO_DEVICE);
+
+ /* set the TxBD length and buffer pointer */
+ txbdp->bufPtr = bufaddr;
+ txbdp->lstatus = lstatus;
+ }
+
+ lstatus = txbdp_start->lstatus;
+ }
+
+ /* Add TxPAL between FCB and frame if required */
+ if (unlikely(do_tstamp)) {
+ skb_push(skb, GMAC_TXPAL_LEN);
+ memset(skb->data, 0, GMAC_TXPAL_LEN);
+ }
+
+ /* Add TxFCB if required */
+ if (fcb_len) {
+ fcb = gfar_add_fcb(skb);
+ lstatus |= BD_LFLAG(TXBD_TOE);
+ }
+
+ /* Set up checksumming */
+ if (do_csum) {
+ gfar_tx_checksum(skb, fcb, fcb_len);
+
+ if (unlikely(gfar_csum_errata_12(priv, (unsigned long)fcb)) ||
+ unlikely(gfar_csum_errata_76(priv, skb->len))) {
+ __skb_pull(skb, GMAC_FCB_LEN);
+ skb_checksum_help(skb);
+ if (do_vlan || do_tstamp) {
+ /* put back a new fcb for vlan/tstamp TOE */
+ fcb = gfar_add_fcb(skb);
+ } else {
+ /* Tx TOE not used */
+ lstatus &= ~(BD_LFLAG(TXBD_TOE));
+ fcb = NULL;
+ }
+ }
+ }
+
+ if (do_vlan)
+ gfar_tx_vlan(skb, fcb);
+
+ /* Setup tx hardware time stamping if requested */
+ if (unlikely(do_tstamp)) {
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+ fcb->ptp = 1;
+ }
+
+ txbdp_start->bufPtr = dma_map_single(priv->dev, skb->data,
+ skb_headlen(skb), DMA_TO_DEVICE);
+
+ /* If time stamping is requested one additional TxBD must be set up. The
+ * first TxBD points to the FCB and must have a data length of
+ * GMAC_FCB_LEN. The second TxBD points to the actual frame data with
+ * the full frame length.
+ */
+ if (unlikely(do_tstamp)) {
+ txbdp_tstamp->bufPtr = txbdp_start->bufPtr + fcb_len;
+ txbdp_tstamp->lstatus |= BD_LFLAG(TXBD_READY) |
+ (skb_headlen(skb) - fcb_len);
+ lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | GMAC_FCB_LEN;
+ } else {
+ lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | skb_headlen(skb);
+ }
+
+ /* We can work in parallel with gfar_clean_tx_ring(), except
+ * when modifying num_txbdfree. Note that we didn't grab the lock
+ * when we were reading the num_txbdfree and checking for available
+ * space, that's because outside of this function it can only grow,
+ * and once we've got needed space, it cannot suddenly disappear.
+ *
+ * The lock also protects us from gfar_error(), which can modify
+ * regs->tstat and thus retrigger the transfers, which is why we
+ * also must grab the lock before setting ready bit for the first
+ * to be transmitted BD.
+ */
+
+ /* The powerpc-specific eieio() is used, as wmb() has too strong
+ * semantics (it requires synchronization between cacheable and
+ * uncacheable mappings, which eieio doesn't provide and which we
+ * don't need), thus requiring a more expensive sync instruction. At
+ * some point, the set of architecture-independent barrier functions
+ * should be expanded to include weaker barriers.
+ */
+ eieio();
+
+ txbdp_start->lstatus = lstatus;
+
+ eieio(); /* force lstatus write before tx_skbuff */
+
+ skb_curtx = tx_queue->skb_curtx;
+
+ /* Update the current skb pointer to the next entry we will use
+ * (wrapping if necessary)
+ */
+ tx_queue->skb_curtx = (tx_queue->skb_curtx + 1) &
+ TX_RING_MOD_MASK(tx_queue->tx_ring_size);
+
+ tx_queue->cur_tx = next_txbd(txbdp, base, tx_queue->tx_ring_size);
+
+
+ /* Tell the DMA to go go go */
+ gfar_write(&regs->tstat, TSTAT_CLEAR_THALT >> tx_queue->qindex);
+
+ if ((skb->owner != RT_PKT_ID) ||
+ (!skb_is_recycleable(skb, DEFAULT_RX_BUFFER_SIZE +
+ RXBUF_ALIGNMENT))) {
+ skb->new_skb = NULL;
+ gfar_recycle_skb(skb);
+ } else {
+ if (skb->pkt_type == PACKET_FASTROUTE)
+ gfar_asf_reclaim_skb(skb);
+ else
+ skb_recycle(skb);
+ gfar_align_skb(skb);
+ skb->new_skb = skb;
+ }
+ txq->trans_start = jiffies;
+
+ return NETDEV_TX_OK;
+}
+
+irqreturn_t gfar_enable_tx_queue(int irq, void *grp_id)
+{
+ struct gfar_priv_grp *grp = (struct gfar_priv_grp *)grp_id;
+ struct gfar_private *priv = priv = grp->priv;
+ struct gfar_priv_tx_q *tx_queue = NULL;
+ u32 tstat, mask;
+ int i;
+ unsigned long flags;
+
+ struct net_device *dev = NULL;
+ tstat = gfar_read(&grp->regs->tstat);
+ tstat = tstat & TSTAT_TXF_MASK_ALL;
+
+ /* Clear IEVENT */
+ gfar_write(&grp->regs->ievent, IEVENT_TX_MASK);
+
+ for_each_set_bit(i, &grp->tx_bit_map, priv->num_tx_queues) {
+ mask = TSTAT_TXF0_MASK >> i;
+ if (tstat & mask) {
+ tx_queue = priv->tx_queue[i];
+ dev = tx_queue->dev;
+ if (__netif_subqueue_stopped(dev, tx_queue->qindex))
+ netif_wake_subqueue(dev, tx_queue->qindex);
+ }
+ }
+
+ spin_lock_irqsave(&grp->grplock, flags);
+ mask = gfar_read(&grp->regs->imask);
+ mask = mask & IMASK_TX_DISABLED;
+ gfar_write(&grp->regs->imask, mask);
+ spin_unlock_irqrestore(&grp->grplock, flags);
+
+ return IRQ_HANDLED;
+}
+
+/* gfar_asf_clean_rx_ring() -- Processes each frame in the rx ring
+ * until the budget/quota has been reached. Returns the number
+ * of frames handled
+ */
+int gfar_asf_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
+{
+ struct net_device *dev = rx_queue->dev;
+ struct rxbd8 *bdp, *base;
+ struct sk_buff *skb;
+ int pkt_len;
+ int amount_pull;
+ int howmany = 0;
+ struct gfar_private *priv = netdev_priv(dev);
+
+ /* Get the first full descriptor */
+ bdp = rx_queue->cur_rx;
+ base = rx_queue->rx_bd_base;
+
+ amount_pull = priv->uses_rxfcb ? GMAC_FCB_LEN : 0;
+
+ while (!((bdp->status & RXBD_EMPTY) || (--rx_work_limit < 0))) {
+ struct sk_buff *newskb = NULL;
+
+ /* Adding memory barrier */
+ rmb();
+
+ skb = rx_queue->rx_skbuff[rx_queue->skb_currx];
+
+ dma_unmap_single(priv->dev, bdp->bufPtr,
+ priv->rx_buffer_size, DMA_FROM_DEVICE);
+
+ if (unlikely(!(bdp->status & RXBD_ERR) &&
+ bdp->length > priv->rx_buffer_size))
+ bdp->status = RXBD_LARGE;
+
+ if (unlikely(!(bdp->status & RXBD_LAST) ||
+ bdp->status & RXBD_ERR)) {
+ count_errors(bdp->status, dev);
+ newskb = skb;
+ } else {
+ /* Increment the number of packets */
+ rx_queue->stats.rx_packets++;
+ howmany++;
+
+ if (likely(skb)) {
+ pkt_len = bdp->length - ETH_FCS_LEN;
+ /* Remove the FCS from the packet length */
+ skb_put(skb, pkt_len);
+ rx_queue->stats.rx_bytes += pkt_len;
+ skb_record_rx_queue(skb, rx_queue->qindex);
+ skb->owner = RT_PKT_ID;
+ gfar_process_frame(dev, skb, amount_pull,
+ &rx_queue->grp->napi_rx);
+ newskb = skb->new_skb;
+ skb->owner = 0;
+ skb->new_skb = NULL;
+ } else {
+ netif_warn(priv, rx_err, dev, "Missing skb!\n");
+ rx_queue->stats.rx_dropped++;
+ atomic64_inc(&priv->extra_stats.rx_skbmissing);
+ }
+
+ }
+
+ if (!newskb) {
+ /* Allocate new skb for Rx ring */
+ newskb = gfar_new_skb(dev);
+ }
+ if (!newskb)
+ /* All memory Exhausted,a BUG */
+ BUG();
+ rx_queue->rx_skbuff[rx_queue->skb_currx] = newskb;
+
+ /* Setup the new bdp */
+ gfar_new_rxbdp(rx_queue, bdp, newskb);
+
+ /* Update to the next pointer */
+ bdp = next_bd(bdp, base, rx_queue->rx_ring_size);
+
+ /* update to point at the next skb */
+ rx_queue->skb_currx = (rx_queue->skb_currx + 1) &
+ RX_RING_MOD_MASK(rx_queue->rx_ring_size);
+ }
+
+ /* Update the current rxbd pointer to be the next one */
+ rx_queue->cur_rx = bdp;
+
+ return howmany;
+}
+
+/* This is function is called directly by ASF when ASF runs in Minimal mode
+* transmission.
+*/
+
+int gfar_fast_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct gfar_priv_tx_q *tx_queue = NULL;
+ struct netdev_queue *txq;
+ struct gfar __iomem *regs = NULL;
+ struct txbd8 *txbdp, *txbdp_start, *base;
+ u32 lstatus;
+ int rq = 0;
+ int skb_curtx = 0;
+ unsigned int fcb_length = GMAC_FCB_LEN;
+
+ rq = smp_processor_id();
+ tx_queue = priv->tx_queue[rq];
+ txq = netdev_get_tx_queue(dev, rq);
+ base = tx_queue->tx_bd_base;
+ regs = tx_queue->grp->regs;
+
+ txbdp = tx_queue->cur_tx;
+ skb_curtx = tx_queue->skb_curtx;
+
+ lstatus = txbdp->lstatus;
+ if ((lstatus & BD_LFLAG(TXBD_READY))) {
+ u32 imask;
+ /* BD not free for tx */
+ netif_tx_stop_queue(txq);
+ dev->stats.tx_fifo_errors++;
+ spin_lock_irq(&tx_queue->grp->grplock);
+ imask = gfar_read(&regs->imask);
+ imask |= IMASK_TX_DEFAULT;
+ gfar_write(&regs->imask, imask);
+ spin_unlock_irq(&tx_queue->grp->grplock);
+ return NETDEV_TX_BUSY;
+ }
+
+ /* BD is free to be used by s/w */
+ /* Free skb for this BD if not recycled */
+ txbdp->lstatus &= BD_LFLAG(TXBD_WRAP);
+ /* Update transmit stats */
+ tx_queue->stats.tx_bytes += skb->len;
+ tx_queue->stats.tx_packets++;
+
+ txbdp = txbdp_start = tx_queue->cur_tx;
+ lstatus = txbdp->lstatus | BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT);
+
+ /* Set up checksumming */
+
+ if (CHECKSUM_PARTIAL == skb->ip_summed) {
+ struct txfcb *fcb = NULL;
+ fcb = gfar_add_fcb(skb);
+ lstatus |= BD_LFLAG(TXBD_TOE);
+ gfar_tx_checksum(skb, fcb, fcb_length);
+ }
+
+ txbdp_start->bufPtr = dma_map_single(priv->dev, skb->data,
+ skb_headlen(skb), DMA_TO_DEVICE);
+
+ lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | skb_headlen(skb);
+ /* The powerpc-specific eieio() is used, as wmb() has too strong
+ * semantics (it requires synchronization between cacheable and
+ * uncacheable mappings, which eieio doesn't provide and which we
+ * don't need), thus requiring a more expensive sync instruction. At
+ * some point, the set of architecture-independent barrier functions
+ * should be expanded to include weaker barriers.
+ */
+ eieio();
+
+ txbdp_start->lstatus = lstatus;
+
+ eieio(); /* force lstatus write before tx_skbuff */
+
+ skb_curtx = tx_queue->skb_curtx;
+
+ /* Update the current skb pointer to the next entry we will use
+ * (wrapping if necessary)
+ */
+ tx_queue->skb_curtx = (tx_queue->skb_curtx + 1) &
+ TX_RING_MOD_MASK(tx_queue->tx_ring_size);
+
+ tx_queue->cur_tx = next_txbd(txbdp, base, tx_queue->tx_ring_size);
+
+ /* Tell the DMA to go go go */
+ gfar_write(&regs->tstat, TSTAT_CLEAR_THALT >> tx_queue->qindex);
+
+ if ((skb->owner != RT_PKT_ID) ||
+ (!skb_is_recycleable(skb, DEFAULT_RX_BUFFER_SIZE +
+ RXBUF_ALIGNMENT))) {
+ skb->new_skb = NULL;
+ gfar_recycle_skb(skb);
+ } else {
+ gfar_asf_reclaim_skb(skb);
+ gfar_align_skb(skb);
+ skb->new_skb = skb;
+ }
+ txq->trans_start = jiffies;
+ return NETDEV_TX_OK;
+}
+EXPORT_SYMBOL(gfar_fast_xmit);
diff --git a/drivers/net/ethernet/freescale/asf_gianfar.h b/drivers/net/ethernet/freescale/asf_gianfar.h
new file mode 100644
index 0000000..3abb1ea
--- /dev/null
+++ b/drivers/net/ethernet/freescale/asf_gianfar.h
@@ -0,0 +1,58 @@
+/* drivers/net/ethernet/freescale/asf_gianfar.h
+ *
+ * ASF Specific Gianfar Ethernet Driver
+ *
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#ifndef __ASF_GIANFAR_H
+#define __ASF_GIANFAR_H
+
+#define TSTAT_TXF_MASK_ALL 0x0000FF00
+#define TSTAT_TXF0_MASK 0x00008000
+
+
+#ifdef IMASK_DEFAULT
+#undef IMASK_DEFAULT
+#endif
+
+#define IMASK_DEFAULT (IMASK_TXEEN | \
+ IMASK_RXFEN0 | IMASK_BSY | IMASK_EBERR | IMASK_BABR | \
+ IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_DPE \
+ | IMASK_PERR)
+
+extern DEFINE_PER_CPU(struct sk_buff_head, skb_recycle_list);
+extern irqreturn_t gfar_enable_tx_queue(int irq, void *dev_id);
+extern void gfar_tx_vlan(struct sk_buff *skb, struct txfcb *fcb);
+extern int gfar_asf_start_xmit(struct sk_buff *skb, struct net_device *dev);
+extern struct sk_buff *gfar_new_skb(struct net_device *dev);
+int gfar_asf_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit);
+extern void gfar_asf_process_frame(struct net_device *dev, struct sk_buff *skb,
+ int amount_pull, struct napi_struct *napi);
+
+#define AS_FP_PROCEED 1
+#define AS_FP_STOLEN 2
+typedef int (*devfp_hook_t)(struct sk_buff *skb, struct net_device *dev);
+extern devfp_hook_t devfp_rx_hook;
+extern devfp_hook_t devfp_tx_hook;
+
+/* Overwrite the Rx/Tx Hooks pointers
+ * if already configured.
+ */
+static inline int devfp_register_rx_hook(devfp_hook_t hook)
+{
+ devfp_rx_hook = hook;
+ return 0;
+}
+
+static inline int devfp_register_tx_hook(devfp_hook_t hook)
+{
+ devfp_tx_hook = hook;
+ return 0;
+}
+#endif /* __ASF_GIANFAR_H */
diff --git a/drivers/net/ethernet/freescale/dpa/Kconfig b/drivers/net/ethernet/freescale/dpa/Kconfig
new file mode 100644
index 0000000..3d4347b
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/Kconfig
@@ -0,0 +1,137 @@
+menuconfig FSL_DPAA_ETH
+ bool "DPAA Ethernet"
+ depends on FSL_SOC && FSL_BMAN && FSL_QMAN && FSL_FMAN
+ select PHYLIB
+ ---help---
+ Data Path Acceleration Architecture Ethernet driver,
+ supporting the Freescale QorIQ chips.
+ Depends on Freescale Buffer Manager and Queue Manager
+ driver and Frame Manager Driver.
+
+if FSL_DPAA_ETH
+
+config FSL_DPAA_OFFLINE_PORTS
+ bool "Offline Ports support"
+ depends on FSL_DPAA_ETH
+ default y
+ ---help---
+ The Offline Parsing / Host Command ports (short: OH ports, of Offline ports) provide
+ most of the functionality of the regular, online ports, except they receive their
+ frames from a core or an accelerator on the SoC, via QMan frame queues,
+ rather than directly from the network.
+ Offline ports are configured via PCD (Parse-Classify-Distribute) schemes, just like
+ any online FMan port. They deliver the processed frames to frame queues, according
+ to the applied PCD configurations.
+
+ Choosing this feature will not impact the functionality and/or performance of the system,
+ so it is safe to have it.
+
+config FSL_DPAA_ETH_JUMBO_FRAME
+ bool "Optimize for jumbo frames"
+ select FMAN_RESOURCE_ALLOCATION_ALGORITHM if (FMAN_P3040_P4080_P5020 || FMAN_P1023)
+ default n
+ ---help---
+ Optimize the DPAA Ethernet driver throughput for large frames
+ termination traffic (e.g. 4K and above).
+ NOTE: This option can only be used if FSL_FM_MAX_FRAME_SIZE
+ is set to 9600 bytes.
+ Using this option in combination with small frames increases
+ significantly the driver's memory footprint and may even deplete
+ the system memory.
+
+config FSL_DPAA_TS
+ tristate "Linux compliant timestamping"
+ depends on FSL_DPAA_ETH
+ default n
+ ---help---
+ Enable Linux API compliant timestamping support.
+
+config FSL_DPAA_1588
+ tristate "IEEE 1588-compliant timestamping"
+ depends on FSL_DPAA_ETH
+ select FSL_DPAA_TS
+ default n
+ ---help---
+ Enable IEEE1588 support code.
+
+config FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE
+ bool "Use driver's Tx queue selection mechanism"
+ default y
+ depends on FSL_DPAA_ETH
+ ---help---
+ The DPAA-Ethernet driver defines a ndo_select_queue() callback for optimal selection
+ of the egress FQ. That will override the XPS support for this netdevice.
+ If for whatever reason you want to be in control of the egress FQ-to-CPU selection and mapping,
+ or simply don't want to use the driver's ndo_select_queue() callback, then unselect this
+ and use the standard XPS support instead.
+
+config FSL_DPAA_ETH_MAX_BUF_COUNT
+ int "Maximum nuber of buffers in private bpool"
+ depends on FSL_DPAA_ETH
+ range 64 2048
+ default "128"
+ ---help---
+ The maximum number of buffers to be by default allocated in the DPAA-Ethernet private port's
+ buffer pool. One needn't normally modify this, as it has probably been tuned for performance
+ already. This cannot be lower than DPAA_ETH_REFILL_THRESHOLD.
+
+config FSL_DPAA_ETH_REFILL_THRESHOLD
+ int "Private bpool refill threshold"
+ depends on FSL_DPAA_ETH
+ range 32 FSL_DPAA_ETH_MAX_BUF_COUNT
+ default "80"
+ ---help---
+ The DPAA-Ethernet driver will start replenishing buffer pools whose count
+ falls below this threshold. This must be related to DPAA_ETH_MAX_BUF_COUNT. One needn't normally
+ modify this value unless one has very specific performance reasons.
+
+config FSL_DPAA_CS_THRESHOLD_1G
+ hex "Egress congestion threshold on 1G ports"
+ depends on FSL_DPAA_ETH
+ range 0x1000 0x10000000
+ default "0x06000000"
+ ---help---
+ The size in bytes of the egress Congestion State notification threshold on 1G ports.
+ The 1G dTSECs can quite easily be flooded by cores doing Tx in a tight loop
+ (e.g. by sending UDP datagrams at "while(1) speed"),
+ and the larger the frame size, the more acute the problem.
+ So we have to find a balance between these factors:
+ - avoiding the device staying congested for a prolonged time (risking
+ the netdev watchdog to fire - see also the tx_timeout module param);
+ - affecting performance of protocols such as TCP, which otherwise
+ behave well under the congestion notification mechanism;
+ - preventing the Tx cores from tightly-looping (as if the congestion
+ threshold was too low to be effective);
+ - running out of memory if the CS threshold is set too high.
+
+config FSL_DPAA_CS_THRESHOLD_10G
+ hex "Egress congestion threshold on 10G ports"
+ depends on FSL_DPAA_ETH
+ range 0x1000 0x20000000
+ default "0x10000000"
+ ---help ---
+ The size in bytes of the egress Congestion State notification threshold on 10G ports.
+
+config FSL_DPAA_INGRESS_CS_THRESHOLD
+ hex "Ingress congestion threshold on FMan ports"
+ depends on FSL_DPAA_ETH
+ default "0x10000000"
+ ---help---
+ The size in bytes of the ingress tail-drop threshold on FMan ports.
+ Traffic piling up above this value will be rejected by QMan and discarded by FMan.
+
+config FSL_DPAA_ETH_DEBUGFS
+ tristate "DPAA Ethernet debugfs interface"
+ depends on DEBUG_FS && FSL_DPAA_ETH
+ default y
+ ---help---
+ This option compiles debugfs code for the DPAA Ethernet driver.
+
+config FSL_DPAA_ETH_DEBUG
+ bool "DPAA Ethernet Debug Support"
+ depends on FSL_DPAA_ETH
+ default n
+ ---help---
+ This option compiles debug code for the DPAA Ethernet driver.
+
+endif # FSL_DPAA_ETH
diff --git a/drivers/net/ethernet/freescale/dpa/Makefile b/drivers/net/ethernet/freescale/dpa/Makefile
new file mode 100644
index 0000000..2693e49
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/Makefile
@@ -0,0 +1,31 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+ccflags-y += -DVERSION=\"\"
+#
+# Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+
+ccflags-y += -I$(NET_DPA)
+
+obj-$(CONFIG_FSL_DPAA_1588) += dpaa_1588.o
+# dpaa_debugfs needs to be initialized before dpaa_eth
+obj-$(CONFIG_FSL_DPAA_ETH_DEBUGFS) += dpaa_debugfs.o dpaa_generic_debugfs.o
+obj-$(CONFIG_FSL_DPAA_ETH) += fsl-mac.o fsl-dpa.o fsl-dpa-common.o \
+ fsl-dpa-base.o fsl-dpa-shared.o fsl-dpa-proxy.o fsl-dpa-macless.o \
+ fsl-dpa-generic.o
+obj-$(CONFIG_FSL_DPAA_OFFLINE_PORTS) += fsl-oh.o
+
+fsl-dpa-objs := dpaa_ethtool.o dpaa_eth_sysfs.o \
+ dpaa_eth.o dpaa_eth_sg.o
+fsl-dpa-common-objs := dpaa_eth_common.o
+fsl-dpa-base-objs := dpaa_eth_base.o
+fsl-dpa-shared-objs := dpaa_eth_shared.o
+fsl-dpa-proxy-objs := dpaa_eth_proxy.o
+fsl-dpa-macless-objs := dpaa_eth_macless.o
+fsl-dpa-generic-objs := dpaa_eth_generic.o dpaa_eth_generic_sysfs.o
+fsl-mac-objs := mac.o mac-api.o
+fsl-oh-objs := offline_port.o
+
+# Needed by the tracing framework
+CFLAGS_dpaa_eth.o := -I$(src)
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_1588.c b/drivers/net/ethernet/freescale/dpa/dpaa_1588.c
new file mode 100644
index 0000000..9f66640
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_1588.c
@@ -0,0 +1,591 @@
+/* Copyright (C) 2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2009 IXXAT Automation, GmbH
+ *
+ * DPAA Ethernet Driver -- IEEE 1588 interface functionality
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#include <linux/io.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+#include <linux/spinlock.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/udp.h>
+#include <asm/div64.h>
+#include "dpaa_eth.h"
+#include "dpaa_eth_common.h"
+#include "dpaa_1588.h"
+#include "mac.h"
+
+static int dpa_ptp_init_circ(struct dpa_ptp_circ_buf *ptp_buf, u32 size)
+{
+ struct circ_buf *circ_buf = &ptp_buf->circ_buf;
+
+ circ_buf->buf = vmalloc(sizeof(struct dpa_ptp_data) * size);
+ if (!circ_buf->buf)
+ return 1;
+
+ circ_buf->head = 0;
+ circ_buf->tail = 0;
+ ptp_buf->size = size;
+ spin_lock_init(&ptp_buf->ptp_lock);
+
+ return 0;
+}
+
+static void dpa_ptp_reset_circ(struct dpa_ptp_circ_buf *ptp_buf, u32 size)
+{
+ struct circ_buf *circ_buf = &ptp_buf->circ_buf;
+
+ circ_buf->head = 0;
+ circ_buf->tail = 0;
+ ptp_buf->size = size;
+}
+
+static int dpa_ptp_insert(struct dpa_ptp_circ_buf *ptp_buf,
+ struct dpa_ptp_data *data)
+{
+ struct circ_buf *circ_buf = &ptp_buf->circ_buf;
+ int size = ptp_buf->size;
+ struct dpa_ptp_data *tmp;
+ unsigned long flags;
+ int head, tail;
+
+ spin_lock_irqsave(&ptp_buf->ptp_lock, flags);
+
+ head = circ_buf->head;
+ tail = circ_buf->tail;
+
+ if (CIRC_SPACE(head, tail, size) <= 0)
+ circ_buf->tail = (tail + 1) & (size - 1);
+
+ tmp = (struct dpa_ptp_data *)(circ_buf->buf) + head;
+ memcpy(tmp, data, sizeof(struct dpa_ptp_data));
+
+ circ_buf->head = (head + 1) & (size - 1);
+
+ spin_unlock_irqrestore(&ptp_buf->ptp_lock, flags);
+
+ return 0;
+}
+
+static int dpa_ptp_is_ident_match(struct dpa_ptp_ident *dst,
+ struct dpa_ptp_ident *src)
+{
+ int ret;
+
+ if ((dst->version != src->version) || (dst->msg_type != src->msg_type))
+ return 0;
+
+ if ((dst->netw_prot == src->netw_prot)
+ || src->netw_prot == DPA_PTP_PROT_DONTCARE) {
+ if (dst->seq_id != src->seq_id)
+ return 0;
+
+ ret = memcmp(dst->snd_port_id, src->snd_port_id,
+ DPA_PTP_SOURCE_PORT_LENGTH);
+ if (ret)
+ return 0;
+ else
+ return 1;
+ }
+
+ return 0;
+}
+
+static int dpa_ptp_find_and_remove(struct dpa_ptp_circ_buf *ptp_buf,
+ struct dpa_ptp_ident *ident,
+ struct dpa_ptp_time *ts)
+{
+ struct circ_buf *circ_buf = &ptp_buf->circ_buf;
+ int size = ptp_buf->size;
+ int head, tail, idx;
+ unsigned long flags;
+ struct dpa_ptp_data *tmp, *tmp2;
+ struct dpa_ptp_ident *tmp_ident;
+
+ spin_lock_irqsave(&ptp_buf->ptp_lock, flags);
+
+ head = circ_buf->head;
+ tail = idx = circ_buf->tail;
+
+ if (CIRC_CNT(head, tail, size) == 0) {
+ spin_unlock_irqrestore(&ptp_buf->ptp_lock, flags);
+ return 1;
+ }
+
+ while (idx != head) {
+ tmp = (struct dpa_ptp_data *)(circ_buf->buf) + idx;
+ tmp_ident = &tmp->ident;
+ if (dpa_ptp_is_ident_match(tmp_ident, ident))
+ break;
+ idx = (idx + 1) & (size - 1);
+ }
+
+ if (idx == head) {
+ spin_unlock_irqrestore(&ptp_buf->ptp_lock, flags);
+ return 1;
+ }
+
+ ts->sec = tmp->ts.sec;
+ ts->nsec = tmp->ts.nsec;
+
+ if (idx != tail) {
+ if (CIRC_CNT(idx, tail, size) > TS_ACCUMULATION_THRESHOLD) {
+ tail = circ_buf->tail =
+ (idx - TS_ACCUMULATION_THRESHOLD) & (size - 1);
+ }
+
+ while (CIRC_CNT(idx, tail, size) > 0) {
+ tmp = (struct dpa_ptp_data *)(circ_buf->buf) + idx;
+ idx = (idx - 1) & (size - 1);
+ tmp2 = (struct dpa_ptp_data *)(circ_buf->buf) + idx;
+ *tmp = *tmp2;
+ }
+ }
+ circ_buf->tail = (tail + 1) & (size - 1);
+
+ spin_unlock_irqrestore(&ptp_buf->ptp_lock, flags);
+
+ return 0;
+}
+
+/* Parse the PTP packets
+ *
+ * The PTP header can be found in an IPv4 packet, IPv6 patcket or in
+ * an IEEE802.3 ethernet frame. This function returns the position of
+ * the PTP packet or NULL if no PTP found
+ */
+static u8 *dpa_ptp_parse_packet(struct sk_buff *skb, u16 *eth_type)
+{
+ u8 *pos = skb->data + ETH_ALEN + ETH_ALEN;
+ u8 *ptp_loc = NULL;
+ u8 msg_type;
+ u32 access_len = ETH_ALEN + ETH_ALEN + DPA_ETYPE_LEN;
+ struct iphdr *iph;
+ struct udphdr *udph;
+ struct ipv6hdr *ipv6h;
+
+ /* when we can receive S/G frames we need to check the data we want to
+ * access is in the linear skb buffer
+ */
+ if (!pskb_may_pull(skb, access_len))
+ return NULL;
+
+ *eth_type = *((u16 *)pos);
+
+ /* Check if inner tag is here */
+ if (*eth_type == ETH_P_8021Q) {
+ access_len += DPA_VLAN_TAG_LEN;
+
+ if (!pskb_may_pull(skb, access_len))
+ return NULL;
+
+ pos += DPA_VLAN_TAG_LEN;
+ *eth_type = *((u16 *)pos);
+ }
+
+ pos += DPA_ETYPE_LEN;
+
+ switch (*eth_type) {
+ /* Transport of PTP over Ethernet */
+ case ETH_P_1588:
+ ptp_loc = pos;
+
+ if (!pskb_may_pull(skb, access_len + PTP_OFFS_MSG_TYPE + 1))
+ return NULL;
+
+ msg_type = *((u8 *)(ptp_loc + PTP_OFFS_MSG_TYPE)) & 0xf;
+ if ((msg_type == PTP_MSGTYPE_SYNC)
+ || (msg_type == PTP_MSGTYPE_DELREQ)
+ || (msg_type == PTP_MSGTYPE_PDELREQ)
+ || (msg_type == PTP_MSGTYPE_PDELRESP))
+ return ptp_loc;
+ break;
+ /* Transport of PTP over IPv4 */
+ case ETH_P_IP:
+ iph = (struct iphdr *)pos;
+ access_len += sizeof(struct iphdr);
+
+ if (!pskb_may_pull(skb, access_len))
+ return NULL;
+
+ if (ntohs(iph->protocol) != IPPROTO_UDP)
+ return NULL;
+
+ access_len += iph->ihl * 4 - sizeof(struct iphdr) +
+ sizeof(struct udphdr);
+
+ if (!pskb_may_pull(skb, access_len))
+ return NULL;
+
+ pos += iph->ihl * 4;
+ udph = (struct udphdr *)pos;
+ if (ntohs(udph->dest) != 319)
+ return NULL;
+ ptp_loc = pos + sizeof(struct udphdr);
+ break;
+ /* Transport of PTP over IPv6 */
+ case ETH_P_IPV6:
+ ipv6h = (struct ipv6hdr *)pos;
+
+ access_len += sizeof(struct ipv6hdr) + sizeof(struct udphdr);
+
+ if (ntohs(ipv6h->nexthdr) != IPPROTO_UDP)
+ return NULL;
+
+ pos += sizeof(struct ipv6hdr);
+ udph = (struct udphdr *)pos;
+ if (ntohs(udph->dest) != 319)
+ return NULL;
+ ptp_loc = pos + sizeof(struct udphdr);
+ break;
+ default:
+ break;
+ }
+
+ return ptp_loc;
+}
+
+static int dpa_ptp_store_stamp(const struct dpa_priv_s *priv,
+ struct sk_buff *skb, void *data, enum port_type rx_tx,
+ struct dpa_ptp_data *ptp_data)
+{
+ u64 nsec;
+ u32 mod;
+ u8 *ptp_loc;
+ u16 eth_type;
+
+ ptp_loc = dpa_ptp_parse_packet(skb, &eth_type);
+ if (!ptp_loc)
+ return -EINVAL;
+
+ switch (eth_type) {
+ case ETH_P_IP:
+ ptp_data->ident.netw_prot = DPA_PTP_PROT_IPV4;
+ break;
+ case ETH_P_IPV6:
+ ptp_data->ident.netw_prot = DPA_PTP_PROT_IPV6;
+ break;
+ case ETH_P_1588:
+ ptp_data->ident.netw_prot = DPA_PTP_PROT_802_3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (!pskb_may_pull(skb, ptp_loc - skb->data + PTP_OFFS_SEQ_ID + 2))
+ return -EINVAL;
+
+ ptp_data->ident.version = *(ptp_loc + PTP_OFFS_VER_PTP) & 0xf;
+ ptp_data->ident.msg_type = *(ptp_loc + PTP_OFFS_MSG_TYPE) & 0xf;
+ ptp_data->ident.seq_id = *((u16 *)(ptp_loc + PTP_OFFS_SEQ_ID));
+ memcpy(ptp_data->ident.snd_port_id, ptp_loc + PTP_OFFS_SRCPRTID,
+ DPA_PTP_SOURCE_PORT_LENGTH);
+
+ nsec = dpa_get_timestamp_ns(priv, rx_tx, data);
+ mod = do_div(nsec, NANOSEC_PER_SECOND);
+ ptp_data->ts.sec = nsec;
+ ptp_data->ts.nsec = mod;
+
+ return 0;
+}
+
+void dpa_ptp_store_txstamp(const struct dpa_priv_s *priv,
+ struct sk_buff *skb, void *data)
+{
+ struct dpa_ptp_tsu *tsu = priv->tsu;
+ struct dpa_ptp_data ptp_tx_data;
+
+ if (dpa_ptp_store_stamp(priv, skb, data, TX, &ptp_tx_data))
+ return;
+
+ dpa_ptp_insert(&tsu->tx_timestamps, &ptp_tx_data);
+}
+
+void dpa_ptp_store_rxstamp(const struct dpa_priv_s *priv,
+ struct sk_buff *skb, void *data)
+{
+ struct dpa_ptp_tsu *tsu = priv->tsu;
+ struct dpa_ptp_data ptp_rx_data;
+
+ if (dpa_ptp_store_stamp(priv, skb, data, RX, &ptp_rx_data))
+ return;
+
+ dpa_ptp_insert(&tsu->rx_timestamps, &ptp_rx_data);
+}
+
+static uint8_t dpa_get_tx_timestamp(struct dpa_ptp_tsu *ptp_tsu,
+ struct dpa_ptp_ident *ident,
+ struct dpa_ptp_time *ts)
+{
+ struct dpa_ptp_tsu *tsu = ptp_tsu;
+ struct dpa_ptp_time tmp;
+ int flag;
+
+ flag = dpa_ptp_find_and_remove(&tsu->tx_timestamps, ident, &tmp);
+ if (!flag) {
+ ts->sec = tmp.sec;
+ ts->nsec = tmp.nsec;
+ return 0;
+ }
+
+ return -1;
+}
+
+static uint8_t dpa_get_rx_timestamp(struct dpa_ptp_tsu *ptp_tsu,
+ struct dpa_ptp_ident *ident,
+ struct dpa_ptp_time *ts)
+{
+ struct dpa_ptp_tsu *tsu = ptp_tsu;
+ struct dpa_ptp_time tmp;
+ int flag;
+
+ flag = dpa_ptp_find_and_remove(&tsu->rx_timestamps, ident, &tmp);
+ if (!flag) {
+ ts->sec = tmp.sec;
+ ts->nsec = tmp.nsec;
+ return 0;
+ }
+
+ return -1;
+}
+
+static void dpa_set_fiper_alarm(struct dpa_ptp_tsu *tsu,
+ struct dpa_ptp_time *cnt_time)
+{
+ struct mac_device *mac_dev = tsu->dpa_priv->mac_dev;
+ u64 tmp, fiper;
+
+ if (mac_dev->fm_rtc_disable)
+ mac_dev->fm_rtc_disable(get_fm_handle(tsu->dpa_priv->net_dev));
+
+ /* TMR_FIPER1 will pulse every second after ALARM1 expired */
+ tmp = (u64)cnt_time->sec * NANOSEC_PER_SECOND + (u64)cnt_time->nsec;
+ fiper = NANOSEC_PER_SECOND - DPA_PTP_NOMINAL_FREQ_PERIOD_NS;
+ if (mac_dev->fm_rtc_set_alarm)
+ mac_dev->fm_rtc_set_alarm(get_fm_handle(tsu->dpa_priv->net_dev),
+ 0, tmp);
+ if (mac_dev->fm_rtc_set_fiper)
+ mac_dev->fm_rtc_set_fiper(get_fm_handle(tsu->dpa_priv->net_dev),
+ 0, fiper);
+
+ if (mac_dev->fm_rtc_enable)
+ mac_dev->fm_rtc_enable(get_fm_handle(tsu->dpa_priv->net_dev));
+}
+
+static void dpa_get_curr_cnt(struct dpa_ptp_tsu *tsu,
+ struct dpa_ptp_time *curr_time)
+{
+ struct mac_device *mac_dev = tsu->dpa_priv->mac_dev;
+ u64 tmp;
+ u32 mod;
+
+ if (mac_dev->fm_rtc_get_cnt)
+ mac_dev->fm_rtc_get_cnt(get_fm_handle(tsu->dpa_priv->net_dev),
+ &tmp);
+
+ mod = do_div(tmp, NANOSEC_PER_SECOND);
+ curr_time->sec = (u32)tmp;
+ curr_time->nsec = mod;
+}
+
+static void dpa_set_1588cnt(struct dpa_ptp_tsu *tsu,
+ struct dpa_ptp_time *cnt_time)
+{
+ struct mac_device *mac_dev = tsu->dpa_priv->mac_dev;
+ u64 tmp;
+
+ tmp = (u64)cnt_time->sec * NANOSEC_PER_SECOND + (u64)cnt_time->nsec;
+
+ if (mac_dev->fm_rtc_set_cnt)
+ mac_dev->fm_rtc_set_cnt(get_fm_handle(tsu->dpa_priv->net_dev),
+ tmp);
+
+ /* Restart fiper two seconds later */
+ cnt_time->sec += 2;
+ cnt_time->nsec = 0;
+ dpa_set_fiper_alarm(tsu, cnt_time);
+}
+
+static void dpa_get_drift(struct dpa_ptp_tsu *tsu, u32 *addend)
+{
+ struct mac_device *mac_dev = tsu->dpa_priv->mac_dev;
+ u32 drift;
+
+ if (mac_dev->fm_rtc_get_drift)
+ mac_dev->fm_rtc_get_drift(get_fm_handle(tsu->dpa_priv->net_dev),
+ &drift);
+
+ *addend = drift;
+}
+
+static void dpa_set_drift(struct dpa_ptp_tsu *tsu, u32 addend)
+{
+ struct mac_device *mac_dev = tsu->dpa_priv->mac_dev;
+
+ if (mac_dev->fm_rtc_set_drift)
+ mac_dev->fm_rtc_set_drift(get_fm_handle(tsu->dpa_priv->net_dev),
+ addend);
+}
+
+static void dpa_flush_timestamp(struct dpa_ptp_tsu *tsu)
+{
+ dpa_ptp_reset_circ(&tsu->rx_timestamps, DEFAULT_PTP_RX_BUF_SZ);
+ dpa_ptp_reset_circ(&tsu->tx_timestamps, DEFAULT_PTP_TX_BUF_SZ);
+}
+
+int dpa_ioctl_1588(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ struct dpa_priv_s *priv = netdev_priv(dev);
+ struct dpa_ptp_tsu *tsu = priv->tsu;
+ struct mac_device *mac_dev = priv->mac_dev;
+ struct dpa_ptp_data ptp_data;
+ struct dpa_ptp_data *ptp_data_user;
+ struct dpa_ptp_time act_time;
+ u32 addend;
+ int retval = 0;
+
+ if (!tsu || !tsu->valid)
+ return -ENODEV;
+
+ switch (cmd) {
+ case PTP_ENBL_TXTS_IOCTL:
+ tsu->hwts_tx_en_ioctl = 1;
+ if (mac_dev->fm_rtc_enable)
+ mac_dev->fm_rtc_enable(get_fm_handle(dev));
+ if (mac_dev->ptp_enable)
+ mac_dev->ptp_enable(mac_dev->get_mac_handle(mac_dev));
+ break;
+ case PTP_DSBL_TXTS_IOCTL:
+ tsu->hwts_tx_en_ioctl = 0;
+ if (mac_dev->fm_rtc_disable)
+ mac_dev->fm_rtc_disable(get_fm_handle(dev));
+ if (mac_dev->ptp_disable)
+ mac_dev->ptp_disable(mac_dev->get_mac_handle(mac_dev));
+ break;
+ case PTP_ENBL_RXTS_IOCTL:
+ tsu->hwts_rx_en_ioctl = 1;
+ break;
+ case PTP_DSBL_RXTS_IOCTL:
+ tsu->hwts_rx_en_ioctl = 0;
+ break;
+ case PTP_GET_RX_TIMESTAMP:
+ ptp_data_user = (struct dpa_ptp_data *)ifr->ifr_data;
+ if (copy_from_user(&ptp_data.ident,
+ &ptp_data_user->ident, sizeof(ptp_data.ident)))
+ return -EINVAL;
+
+ if (dpa_get_rx_timestamp(tsu, &ptp_data.ident, &ptp_data.ts))
+ return -EAGAIN;
+
+ if (copy_to_user((void __user *)&ptp_data_user->ts,
+ &ptp_data.ts, sizeof(ptp_data.ts)))
+ return -EFAULT;
+ break;
+ case PTP_GET_TX_TIMESTAMP:
+ ptp_data_user = (struct dpa_ptp_data *)ifr->ifr_data;
+ if (copy_from_user(&ptp_data.ident,
+ &ptp_data_user->ident, sizeof(ptp_data.ident)))
+ return -EINVAL;
+
+ if (dpa_get_tx_timestamp(tsu, &ptp_data.ident, &ptp_data.ts))
+ return -EAGAIN;
+
+ if (copy_to_user((void __user *)&ptp_data_user->ts,
+ &ptp_data.ts, sizeof(ptp_data.ts)))
+ return -EFAULT;
+ break;
+ case PTP_GET_TIME:
+ dpa_get_curr_cnt(tsu, &act_time);
+ if (copy_to_user(ifr->ifr_data, &act_time, sizeof(act_time)))
+ return -EFAULT;
+ break;
+ case PTP_SET_TIME:
+ if (copy_from_user(&act_time, ifr->ifr_data, sizeof(act_time)))
+ return -EINVAL;
+ dpa_set_1588cnt(tsu, &act_time);
+ break;
+ case PTP_GET_ADJ:
+ dpa_get_drift(tsu, &addend);
+ if (copy_to_user(ifr->ifr_data, &addend, sizeof(addend)))
+ return -EFAULT;
+ break;
+ case PTP_SET_ADJ:
+ if (copy_from_user(&addend, ifr->ifr_data, sizeof(addend)))
+ return -EINVAL;
+ dpa_set_drift(tsu, addend);
+ break;
+ case PTP_SET_FIPER_ALARM:
+ if (copy_from_user(&act_time, ifr->ifr_data, sizeof(act_time)))
+ return -EINVAL;
+ dpa_set_fiper_alarm(tsu, &act_time);
+ break;
+ case PTP_CLEANUP_TS:
+ dpa_flush_timestamp(tsu);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return retval;
+}
+
+int dpa_ptp_init(struct dpa_priv_s *priv)
+{
+ struct dpa_ptp_tsu *tsu;
+
+ /* Allocate memory for PTP structure */
+ tsu = kzalloc(sizeof(struct dpa_ptp_tsu), GFP_KERNEL);
+ if (!tsu)
+ return -ENOMEM;
+
+ tsu->valid = TRUE;
+ tsu->dpa_priv = priv;
+
+ dpa_ptp_init_circ(&tsu->rx_timestamps, DEFAULT_PTP_RX_BUF_SZ);
+ dpa_ptp_init_circ(&tsu->tx_timestamps, DEFAULT_PTP_TX_BUF_SZ);
+
+ priv->tsu = tsu;
+
+ return 0;
+}
+EXPORT_SYMBOL(dpa_ptp_init);
+
+void dpa_ptp_cleanup(struct dpa_priv_s *priv)
+{
+ struct dpa_ptp_tsu *tsu = priv->tsu;
+
+ tsu->valid = FALSE;
+ vfree(tsu->rx_timestamps.circ_buf.buf);
+ vfree(tsu->tx_timestamps.circ_buf.buf);
+
+ kfree(tsu);
+}
+EXPORT_SYMBOL(dpa_ptp_cleanup);
+
+static int __init __cold dpa_ptp_load(void)
+{
+ return 0;
+}
+module_init(dpa_ptp_load);
+
+static void __exit __cold dpa_ptp_unload(void)
+{
+}
+module_exit(dpa_ptp_unload);
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_1588.h b/drivers/net/ethernet/freescale/dpa/dpaa_1588.h
new file mode 100644
index 0000000..7339016
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_1588.h
@@ -0,0 +1,138 @@
+/* Copyright (C) 2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#ifndef __DPAA_1588_H__
+#define __DPAA_1588_H__
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/circ_buf.h>
+#include <linux/fsl_qman.h>
+
+#define DEFAULT_PTP_RX_BUF_SZ 256
+#define DEFAULT_PTP_TX_BUF_SZ 256
+
+/* 1588 private ioctl calls */
+#define PTP_ENBL_TXTS_IOCTL SIOCDEVPRIVATE
+#define PTP_DSBL_TXTS_IOCTL (SIOCDEVPRIVATE + 1)
+#define PTP_ENBL_RXTS_IOCTL (SIOCDEVPRIVATE + 2)
+#define PTP_DSBL_RXTS_IOCTL (SIOCDEVPRIVATE + 3)
+#define PTP_GET_TX_TIMESTAMP (SIOCDEVPRIVATE + 4)
+#define PTP_GET_RX_TIMESTAMP (SIOCDEVPRIVATE + 5)
+#define PTP_SET_TIME (SIOCDEVPRIVATE + 6)
+#define PTP_GET_TIME (SIOCDEVPRIVATE + 7)
+#define PTP_SET_FIPER_ALARM (SIOCDEVPRIVATE + 8)
+#define PTP_SET_ADJ (SIOCDEVPRIVATE + 9)
+#define PTP_GET_ADJ (SIOCDEVPRIVATE + 10)
+#define PTP_CLEANUP_TS (SIOCDEVPRIVATE + 11)
+
+/* PTP V2 message type */
+enum {
+ PTP_MSGTYPE_SYNC = 0x0,
+ PTP_MSGTYPE_DELREQ = 0x1,
+ PTP_MSGTYPE_PDELREQ = 0x2,
+ PTP_MSGTYPE_PDELRESP = 0x3,
+ PTP_MSGTYPE_FLWUP = 0x8,
+ PTP_MSGTYPE_DELRESP = 0x9,
+ PTP_MSGTYPE_PDELRES_FLWUP = 0xA,
+ PTP_MSGTYPE_ANNOUNCE = 0xB,
+ PTP_MSGTYPE_SGNLNG = 0xC,
+ PTP_MSGTYPE_MNGMNT = 0xD,
+};
+
+/* Byte offset of data in the PTP V2 headers */
+#define PTP_OFFS_MSG_TYPE 0
+#define PTP_OFFS_VER_PTP 1
+#define PTP_OFFS_MSG_LEN 2
+#define PTP_OFFS_DOM_NMB 4
+#define PTP_OFFS_FLAGS 6
+#define PTP_OFFS_CORFIELD 8
+#define PTP_OFFS_SRCPRTID 20
+#define PTP_OFFS_SEQ_ID 30
+#define PTP_OFFS_CTRL 32
+#define PTP_OFFS_LOGMEAN 33
+
+#define PTP_IP_OFFS 14
+#define PTP_UDP_OFFS 34
+#define PTP_HEADER_OFFS 42
+#define PTP_MSG_TYPE_OFFS (PTP_HEADER_OFFS + PTP_OFFS_MSG_TYPE)
+#define PTP_SPORT_ID_OFFS (PTP_HEADER_OFFS + PTP_OFFS_SRCPRTID)
+#define PTP_SEQ_ID_OFFS (PTP_HEADER_OFFS + PTP_OFFS_SEQ_ID)
+#define PTP_CTRL_OFFS (PTP_HEADER_OFFS + PTP_OFFS_CTRL)
+
+/* 1588-2008 network protocol enumeration values */
+#define DPA_PTP_PROT_IPV4 1
+#define DPA_PTP_PROT_IPV6 2
+#define DPA_PTP_PROT_802_3 3
+#define DPA_PTP_PROT_DONTCARE 0xFFFF
+
+#define DPA_PTP_SOURCE_PORT_LENGTH 10
+#define DPA_PTP_HEADER_SZE 34
+#define DPA_ETYPE_LEN 2
+#define DPA_VLAN_TAG_LEN 4
+#define NANOSEC_PER_SECOND 1000000000
+
+/* The threshold between the current found one and the oldest one */
+#define TS_ACCUMULATION_THRESHOLD 50
+
+/* Struct needed to identify a timestamp */
+struct dpa_ptp_ident {
+ u8 version;
+ u8 msg_type;
+ u16 netw_prot;
+ u16 seq_id;
+ u8 snd_port_id[DPA_PTP_SOURCE_PORT_LENGTH];
+};
+
+/* Timestamp format in 1588-2008 */
+struct dpa_ptp_time {
+ u64 sec; /* just 48 bit used */
+ u32 nsec;
+};
+
+/* needed for timestamp data over ioctl */
+struct dpa_ptp_data {
+ struct dpa_ptp_ident ident;
+ struct dpa_ptp_time ts;
+};
+
+struct dpa_ptp_circ_buf {
+ struct circ_buf circ_buf;
+ u32 size;
+ spinlock_t ptp_lock;
+};
+
+/* PTP TSU control structure */
+struct dpa_ptp_tsu {
+ struct dpa_priv_s *dpa_priv;
+ bool valid;
+ struct dpa_ptp_circ_buf rx_timestamps;
+ struct dpa_ptp_circ_buf tx_timestamps;
+
+ /* HW timestamping over ioctl enabled flag */
+ int hwts_tx_en_ioctl;
+ int hwts_rx_en_ioctl;
+};
+
+extern int dpa_ptp_init(struct dpa_priv_s *priv);
+extern void dpa_ptp_cleanup(struct dpa_priv_s *priv);
+extern void dpa_ptp_store_txstamp(const struct dpa_priv_s *priv,
+ struct sk_buff *skb, void *data);
+extern void dpa_ptp_store_rxstamp(const struct dpa_priv_s *priv,
+ struct sk_buff *skb, void *data);
+extern int dpa_ioctl_1588(struct net_device *dev, struct ifreq *ifr, int cmd);
+#endif
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_debugfs.c b/drivers/net/ethernet/freescale/dpa/dpaa_debugfs.c
new file mode 100644
index 0000000..0c884a5
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_debugfs.c
@@ -0,0 +1,280 @@
+/* Copyright 2008-2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/module.h>
+#include <linux/fsl_qman.h> /* struct qm_mcr_querycgr */
+#include <linux/debugfs.h>
+#include <asm/debug.h>
+#include "dpaa_debugfs.h"
+#include "dpaa_eth.h" /* struct dpa_priv_s, dpa_percpu_priv_s, dpa_bp */
+
+#define DPA_DEBUGFS_DESCRIPTION "FSL DPAA Ethernet debugfs entries"
+#define DPA_ETH_DEBUGFS_ROOT "fsl_dpa"
+
+static int __cold dpa_debugfs_open(struct inode *inode, struct file *file);
+
+static struct dentry *dpa_debugfs_root;
+static const struct file_operations dpa_debugfs_fops = {
+ .open = dpa_debugfs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int dpa_debugfs_show(struct seq_file *file, void *offset)
+{
+ int i;
+ struct dpa_priv_s *priv;
+ struct dpa_percpu_priv_s *percpu_priv, total;
+ struct dpa_bp *dpa_bp;
+ unsigned int dpa_bp_count = 0;
+ unsigned int count_total = 0;
+ struct qm_mcr_querycgr query_cgr;
+
+ BUG_ON(offset == NULL);
+
+ priv = netdev_priv((struct net_device *)file->private);
+
+ dpa_bp = priv->dpa_bp;
+
+ memset(&total, 0, sizeof(total));
+
+ /* "Standard" counters */
+ seq_printf(file, "\nDPA counters for %s:\n", priv->net_dev->name);
+ seq_puts(file, "CPU irqs rx tx recycle ");
+ seq_puts(file, "confirm tx sg tx err rx err bp count\n");
+
+
+ for_each_online_cpu(i) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+
+ if (dpa_bp->percpu_count)
+ dpa_bp_count = *(per_cpu_ptr(dpa_bp->percpu_count, i));
+
+ total.in_interrupt += percpu_priv->in_interrupt;
+ total.stats.rx_packets += percpu_priv->stats.rx_packets;
+ total.stats.tx_packets += percpu_priv->stats.tx_packets;
+ total.tx_returned += percpu_priv->tx_returned;
+ total.tx_confirm += percpu_priv->tx_confirm;
+ total.tx_frag_skbuffs += percpu_priv->tx_frag_skbuffs;
+ total.stats.tx_errors += percpu_priv->stats.tx_errors;
+ total.stats.rx_errors += percpu_priv->stats.rx_errors;
+ count_total += dpa_bp_count;
+
+ seq_printf(file, " %hu %8llu %8llu %8llu %8llu ",
+ i,
+ percpu_priv->in_interrupt,
+ percpu_priv->stats.rx_packets,
+ percpu_priv->stats.tx_packets,
+ percpu_priv->tx_returned);
+ seq_printf(file, "%8llu %8llu %8llu %8llu %8d\n",
+ percpu_priv->tx_confirm,
+ percpu_priv->tx_frag_skbuffs,
+ percpu_priv->stats.tx_errors,
+ percpu_priv->stats.rx_errors,
+ dpa_bp_count);
+ }
+ seq_printf(file, "Total %8llu %8llu %8llu %8llu ",
+ total.in_interrupt,
+ total.stats.rx_packets,
+ total.stats.tx_packets,
+ total.tx_returned);
+ seq_printf(file, "%8llu %8llu %8llu %8llu %8d\n",
+ total.tx_confirm,
+ total.tx_frag_skbuffs,
+ total.stats.tx_errors,
+ total.stats.rx_errors,
+ count_total);
+
+ /* Congestion stats */
+ seq_puts(file, "\nDevice congestion stats:\n");
+ seq_printf(file, "Device has been congested for %d ms.\n",
+ jiffies_to_msecs(priv->cgr_data.congested_jiffies));
+
+ qman_query_cgr(&priv->cgr_data.cgr, &query_cgr);
+ seq_printf(file, "CGR id %d avg count: %llu\n",
+ priv->cgr_data.cgr.cgrid, qm_mcr_querycgr_a_get64(&query_cgr));
+ seq_printf(file, "Device entered congestion %u times. ",
+ priv->cgr_data.cgr_congested_count);
+ seq_printf(file, "Current congestion state is: %s.\n",
+ query_cgr.cgr.cs ? "congested" : "not congested");
+ /* Reset congestion stats (like QMan CGR API does) */
+ priv->cgr_data.congested_jiffies = 0;
+ priv->cgr_data.cgr_congested_count = 0;
+
+ /* Rx Errors demultiplexing */
+ seq_puts(file, "\nDPA RX Errors:\nCPU dma err phys err");
+ seq_puts(file, " size err hdr err csum err\n");
+ for_each_online_cpu(i) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+
+ total.rx_errors.dme += percpu_priv->rx_errors.dme;
+ total.rx_errors.fpe += percpu_priv->rx_errors.fpe;
+ total.rx_errors.fse += percpu_priv->rx_errors.fse;
+ total.rx_errors.phe += percpu_priv->rx_errors.phe;
+ total.rx_errors.cse += percpu_priv->rx_errors.cse;
+
+ seq_printf(file, " %hu %8llu %8llu ",
+ i,
+ percpu_priv->rx_errors.dme,
+ percpu_priv->rx_errors.fpe);
+ seq_printf(file, "%8llu %8llu %8llu\n",
+ percpu_priv->rx_errors.fse,
+ percpu_priv->rx_errors.phe,
+ percpu_priv->rx_errors.cse);
+ }
+ seq_printf(file, "Total %8llu %8llu %8llu %8llu %8llu\n",
+ total.rx_errors.dme,
+ total.rx_errors.fpe,
+ total.rx_errors.fse,
+ total.rx_errors.phe,
+ total.rx_errors.cse);
+
+ /* ERN demultiplexing */
+ seq_puts(file, "\nDPA ERN counters:\n CPU cg_td wred ");
+ seq_puts(file, "err_cond early_w late_w fq_td fq_ret");
+ seq_puts(file, " orp_z\n");
+ for_each_online_cpu(i) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+
+ total.ern_cnt.cg_tdrop += percpu_priv->ern_cnt.cg_tdrop;
+ total.ern_cnt.wred += percpu_priv->ern_cnt.wred;
+ total.ern_cnt.err_cond += percpu_priv->ern_cnt.err_cond;
+ total.ern_cnt.early_window += percpu_priv->ern_cnt.early_window;
+ total.ern_cnt.late_window += percpu_priv->ern_cnt.late_window;
+ total.ern_cnt.fq_tdrop += percpu_priv->ern_cnt.fq_tdrop;
+ total.ern_cnt.fq_retired += percpu_priv->ern_cnt.fq_retired;
+ total.ern_cnt.orp_zero += percpu_priv->ern_cnt.orp_zero;
+
+ seq_printf(file, " %hu %8llu %8llu %8llu %8llu ",
+ i,
+ percpu_priv->ern_cnt.cg_tdrop,
+ percpu_priv->ern_cnt.wred,
+ percpu_priv->ern_cnt.err_cond,
+ percpu_priv->ern_cnt.early_window);
+ seq_printf(file, "%8llu %8llu %8llu %8llu\n",
+ percpu_priv->ern_cnt.late_window,
+ percpu_priv->ern_cnt.fq_tdrop,
+ percpu_priv->ern_cnt.fq_retired,
+ percpu_priv->ern_cnt.orp_zero);
+ }
+ seq_printf(file, "Total %8llu %8llu %8llu %8llu ",
+ total.ern_cnt.cg_tdrop,
+ total.ern_cnt.wred,
+ total.ern_cnt.err_cond,
+ total.ern_cnt.early_window);
+ seq_printf(file, "%8llu %8llu %8llu %8llu\n",
+ total.ern_cnt.late_window,
+ total.ern_cnt.fq_tdrop,
+ total.ern_cnt.fq_retired,
+ total.ern_cnt.orp_zero);
+
+ return 0;
+}
+
+static int __cold dpa_debugfs_open(struct inode *inode, struct file *file)
+{
+ int _errno;
+ const struct net_device *net_dev;
+
+ _errno = single_open(file, dpa_debugfs_show, inode->i_private);
+ if (unlikely(_errno < 0)) {
+ net_dev = (struct net_device *)inode->i_private;
+
+ if (netif_msg_drv((struct dpa_priv_s *)netdev_priv(net_dev)))
+ netdev_err(net_dev, "single_open() = %d\n",
+ _errno);
+ }
+ return _errno;
+}
+
+int dpa_netdev_debugfs_create(struct net_device *net_dev)
+{
+ struct dpa_priv_s *priv = netdev_priv(net_dev);
+
+ if (unlikely(dpa_debugfs_root == NULL)) {
+ pr_err(KBUILD_MODNAME ": %s:%hu:%s(): \t%s\n",
+ KBUILD_BASENAME".c", __LINE__, __func__,
+ "root debugfs missing, possible module ordering issue");
+ return -ENOMEM;
+ }
+
+ priv->debugfs_file = debugfs_create_file(net_dev->name,
+ S_IRUGO,
+ dpa_debugfs_root,
+ net_dev,
+ &dpa_debugfs_fops);
+ if (unlikely(priv->debugfs_file == NULL)) {
+ netdev_err(net_dev, "debugfs_create_file(%s/%s/%s)",
+ powerpc_debugfs_root->d_iname,
+ dpa_debugfs_root->d_iname,
+ net_dev->name);
+
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+void dpa_netdev_debugfs_remove(struct net_device *net_dev)
+{
+ struct dpa_priv_s *priv = netdev_priv(net_dev);
+
+ debugfs_remove(priv->debugfs_file);
+}
+
+static int __init dpa_debugfs_module_init(void)
+{
+ int _errno = 0;
+
+ pr_info(KBUILD_MODNAME ": " DPA_DEBUGFS_DESCRIPTION " (" VERSION ")\n");
+
+ dpa_debugfs_root = debugfs_create_dir(DPA_ETH_DEBUGFS_ROOT,
+ powerpc_debugfs_root);
+ if (unlikely(dpa_debugfs_root == NULL)) {
+ _errno = -ENOMEM;
+ pr_err(KBUILD_MODNAME ": %s:%hu:%s():\n",
+ KBUILD_BASENAME".c", __LINE__, __func__);
+ pr_err("\tdebugfs_create_dir(%s/"KBUILD_MODNAME") = %d\n",
+ powerpc_debugfs_root->d_iname, _errno);
+ }
+
+ return _errno;
+}
+
+static void __exit dpa_debugfs_module_exit(void)
+{
+ debugfs_remove(dpa_debugfs_root);
+}
+
+module_init(dpa_debugfs_module_init);
+module_exit(dpa_debugfs_module_exit);
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_debugfs.h b/drivers/net/ethernet/freescale/dpa/dpaa_debugfs.h
new file mode 100644
index 0000000..f82cde5
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_debugfs.h
@@ -0,0 +1,41 @@
+/* Copyright 2008-2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DPAA_DEBUGFS_H_
+#define DPAA_DEBUGFS_H_
+
+#include <linux/netdevice.h>
+#include <linux/dcache.h> /* struct dentry needed in dpaa_eth.h */
+
+int dpa_netdev_debugfs_create(struct net_device *net_dev);
+void dpa_netdev_debugfs_remove(struct net_device *net_dev);
+
+#endif /* DPAA_DEBUGFS_H_ */
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpa/dpaa_eth.c
new file mode 100644
index 0000000..862357a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth.c
@@ -0,0 +1,1123 @@
+/* Copyright 2008-2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef CONFIG_FSL_DPAA_ETH_DEBUG
+#define pr_fmt(fmt) \
+ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \
+ KBUILD_BASENAME".c", __LINE__, __func__
+#else
+#define pr_fmt(fmt) \
+ KBUILD_MODNAME ": " fmt
+#endif
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
+#include <linux/kthread.h>
+#include <linux/io.h>
+#include <linux/if_arp.h> /* arp_hdr_len() */
+#include <linux/if_vlan.h> /* VLAN_HLEN */
+#include <linux/icmp.h> /* struct icmphdr */
+#include <linux/ip.h> /* struct iphdr */
+#include <linux/ipv6.h> /* struct ipv6hdr */
+#include <linux/udp.h> /* struct udphdr */
+#include <linux/tcp.h> /* struct tcphdr */
+#include <linux/net.h> /* net_ratelimit() */
+#include <linux/if_ether.h> /* ETH_P_IP and ETH_P_IPV6 */
+#include <linux/highmem.h>
+#include <linux/percpu.h>
+#include <linux/dma-mapping.h>
+#include <linux/fsl_bman.h>
+
+#include "fsl_fman.h"
+#include "fm_ext.h"
+#include "fm_port_ext.h"
+
+#include "mac.h"
+#include "dpaa_eth.h"
+#include "dpaa_eth_common.h"
+#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS
+#include "dpaa_debugfs.h"
+#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */
+
+/* CREATE_TRACE_POINTS only needs to be defined once. Other dpa files
+ * using trace events only need to #include <trace/events/sched.h>
+ */
+#define CREATE_TRACE_POINTS
+#include "dpaa_eth_trace.h"
+
+#define DPA_NAPI_WEIGHT 64
+
+/* Valid checksum indication */
+#define DPA_CSUM_VALID 0xFFFF
+
+#define DPA_DESCRIPTION "FSL DPAA Ethernet driver"
+
+MODULE_LICENSE("Dual BSD/GPL");
+
+MODULE_AUTHOR("Andy Fleming <afleming@freescale.com>");
+
+MODULE_DESCRIPTION(DPA_DESCRIPTION);
+
+static uint8_t debug = -1;
+module_param(debug, byte, S_IRUGO);
+MODULE_PARM_DESC(debug, "Module/Driver verbosity level");
+
+/* This has to work in tandem with the DPA_CS_THRESHOLD_xxx values. */
+static uint16_t tx_timeout = 1000;
+module_param(tx_timeout, ushort, S_IRUGO);
+MODULE_PARM_DESC(tx_timeout, "The Tx timeout in ms");
+
+static const char rtx[][3] = {
+ [RX] = "RX",
+ [TX] = "TX"
+};
+
+/* BM */
+
+#define DPAA_ETH_MAX_PAD (L1_CACHE_BYTES * 8)
+
+static uint8_t dpa_priv_common_bpid;
+
+#ifdef CONFIG_PM
+
+static int dpaa_suspend_noirq(struct device *dev)
+{
+ struct net_device *net_dev;
+ struct dpa_priv_s *priv;
+ struct mac_device *mac_dev;
+ int err = 0;
+
+ net_dev = dev_get_drvdata(dev);
+
+ if (net_dev->flags & IFF_UP) {
+ priv = netdev_priv(net_dev);
+ mac_dev = priv->mac_dev;
+
+ err = fm_port_suspend(mac_dev->port_dev[RX]);
+ if (err)
+ goto port_suspend_failed;
+
+ err = fm_port_suspend(mac_dev->port_dev[TX]);
+ if (err)
+ err = fm_port_resume(mac_dev->port_dev[RX]);
+
+ if (priv->wol & DPAA_WOL_MAGIC) {
+ err = priv->mac_dev->set_wol(mac_dev->port_dev[RX],
+ priv->mac_dev->get_mac_handle(mac_dev), true);
+ if (unlikely(err < 0))
+ netdev_err(net_dev, "set_wol() = %d\n", err);
+ }
+ }
+
+port_suspend_failed:
+ return err;
+}
+
+static int dpaa_resume_noirq(struct device *dev)
+{
+ struct net_device *net_dev;
+ struct dpa_priv_s *priv;
+ struct mac_device *mac_dev;
+ int err = 0;
+
+ net_dev = dev_get_drvdata(dev);
+
+ if (net_dev->flags & IFF_UP) {
+ priv = netdev_priv(net_dev);
+ mac_dev = priv->mac_dev;
+
+ if (priv->wol & DPAA_WOL_MAGIC) {
+ err = priv->mac_dev->set_wol(mac_dev->port_dev[RX],
+ priv->mac_dev->get_mac_handle(mac_dev), false);
+ if (unlikely(err < 0))
+ netdev_err(net_dev, "set_wol() = %d\n", err);
+ }
+
+ err = fm_port_resume(mac_dev->port_dev[TX]);
+ if (err)
+ goto port_resume_failed;
+
+ err = fm_port_resume(mac_dev->port_dev[RX]);
+ if (err)
+ err = fm_port_suspend(mac_dev->port_dev[TX]);
+ }
+
+port_resume_failed:
+ return err;
+}
+
+static const struct dev_pm_ops dpaa_pm_ops = {
+ .suspend_noirq = dpaa_suspend_noirq,
+ .resume_noirq = dpaa_resume_noirq,
+};
+
+#define DPAA_PM_OPS (&dpaa_pm_ops)
+
+#else /* CONFIG_PM */
+
+#define DPAA_PM_OPS NULL
+
+#endif /* CONFIG_PM */
+
+/* Checks whether the checksum field in Parse Results array is valid
+ * (equals 0xFFFF) and increments the .cse counter otherwise
+ */
+static inline void
+dpa_csum_validation(const struct dpa_priv_s *priv,
+ struct dpa_percpu_priv_s *percpu_priv,
+ const struct qm_fd *fd)
+{
+ dma_addr_t addr = qm_fd_addr(fd);
+ struct dpa_bp *dpa_bp = priv->dpa_bp;
+ void *frm = phys_to_virt(addr);
+ fm_prs_result_t *parse_result;
+
+ if (unlikely(!frm))
+ return;
+
+ dma_unmap_single(dpa_bp->dev, addr, dpa_bp->size, DMA_BIDIRECTIONAL);
+
+ parse_result = (fm_prs_result_t *)(frm + DPA_RX_PRIV_DATA_SIZE);
+
+ if (parse_result->cksum != DPA_CSUM_VALID)
+ percpu_priv->rx_errors.cse++;
+}
+
+static void _dpa_rx_error(struct net_device *net_dev,
+ const struct dpa_priv_s *priv,
+ struct dpa_percpu_priv_s *percpu_priv,
+ const struct qm_fd *fd,
+ u32 fqid)
+{
+ /* limit common, possibly innocuous Rx FIFO Overflow errors'
+ * interference with zero-loss convergence benchmark results.
+ */
+ if (likely(fd->status & FM_FD_STAT_ERR_PHYSICAL))
+ pr_warn_once("fsl-dpa: non-zero error counters in fman statistics (sysfs)\n");
+ else
+ if (netif_msg_hw(priv) && net_ratelimit())
+ netdev_err(net_dev, "Err FD status = 0x%08x\n",
+ fd->status & FM_FD_STAT_RX_ERRORS);
+#if defined(CONFIG_AS_FASTPATH) || defined(CONFIG_FSL_FMAN_TEST)
+ if (dpaa_eth_hooks.rx_error &&
+ dpaa_eth_hooks.rx_error(net_dev, fd, fqid) == DPAA_ETH_STOLEN)
+ /* it's up to the hook to perform resource cleanup */
+ return;
+#endif
+ percpu_priv->stats.rx_errors++;
+
+ if (fd->status & FM_PORT_FRM_ERR_DMA)
+ percpu_priv->rx_errors.dme++;
+ if (fd->status & FM_PORT_FRM_ERR_PHYSICAL)
+ percpu_priv->rx_errors.fpe++;
+ if (fd->status & FM_PORT_FRM_ERR_SIZE)
+ percpu_priv->rx_errors.fse++;
+ if (fd->status & FM_PORT_FRM_ERR_PRS_HDR_ERR)
+ percpu_priv->rx_errors.phe++;
+ if (fd->status & FM_FD_STAT_L4CV)
+ dpa_csum_validation(priv, percpu_priv, fd);
+
+ dpa_fd_release(net_dev, fd);
+}
+
+static void _dpa_tx_error(struct net_device *net_dev,
+ const struct dpa_priv_s *priv,
+ struct dpa_percpu_priv_s *percpu_priv,
+ const struct qm_fd *fd,
+ u32 fqid)
+{
+ struct sk_buff *skb;
+
+ if (netif_msg_hw(priv) && net_ratelimit())
+ netdev_warn(net_dev, "FD status = 0x%08x\n",
+ fd->status & FM_FD_STAT_TX_ERRORS);
+#if defined(CONFIG_AS_FASTPATH) || defined(CONFIG_FSL_FMAN_TEST)
+ if (dpaa_eth_hooks.tx_error &&
+ dpaa_eth_hooks.tx_error(net_dev, fd, fqid) == DPAA_ETH_STOLEN)
+ /* now the hook must ensure proper cleanup */
+ return;
+#endif
+ percpu_priv->stats.tx_errors++;
+
+ /* If we intended the buffers from this frame to go into the bpools
+ * when the FMan transmit was done, we need to put it in manually.
+ */
+ if (fd->cmd & FM_FD_CMD_FCO) {
+ dpa_fd_release(net_dev, fd);
+ return;
+ }
+
+ skb = _dpa_cleanup_tx_fd(priv, fd);
+ dev_kfree_skb(skb);
+}
+
+/* Helper function to factor out frame validation logic on all Rx paths. Its
+ * purpose is to extract from the Parse Results structure information about
+ * the integrity of the frame, its checksum, the length of the parsed headers
+ * and whether the frame is suitable for GRO.
+ *
+ * Assumes no parser errors, since any error frame is dropped before this
+ * function is called.
+ *
+ * @skb will have its ip_summed field overwritten;
+ * @use_gro will only be written with 0, if the frame is definitely not
+ * GRO-able; otherwise, it will be left unchanged;
+ * @hdr_size will be written with a safe value, at least the size of the
+ * headers' length.
+ */
+void __hot _dpa_process_parse_results(const fm_prs_result_t *parse_results,
+ const struct qm_fd *fd,
+ struct sk_buff *skb, int *use_gro)
+{
+ if (fd->status & FM_FD_STAT_L4CV) {
+ /* The parser has run and performed L4 checksum validation.
+ * We know there were no parser errors (and implicitly no
+ * L4 csum error), otherwise we wouldn't be here.
+ */
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ /* Don't go through GRO for certain types of traffic that
+ * we know are not GRO-able, such as dgram-based protocols.
+ * In the worst-case scenarios, such as small-pkt terminating
+ * UDP, the extra GRO processing would be overkill.
+ *
+ * The only protocol the Parser supports that is also GRO-able
+ * is currently TCP.
+ */
+ if (!fm_l4_frame_is_tcp(parse_results))
+ *use_gro = 0;
+
+ return;
+ }
+
+ /* We're here because either the parser didn't run or the L4 checksum
+ * was not verified. This may include the case of a UDP frame with
+ * checksum zero or an L4 proto other than TCP/UDP
+ */
+ skb->ip_summed = CHECKSUM_NONE;
+
+ /* Bypass GRO for unknown traffic or if no PCDs are applied */
+ *use_gro = 0;
+}
+
+int dpaa_eth_poll(struct napi_struct *napi, int budget)
+{
+ struct dpa_napi_portal *np =
+ container_of(napi, struct dpa_napi_portal, napi);
+
+ int cleaned = qman_p_poll_dqrr(np->p, budget);
+
+ if (cleaned < budget) {
+ int tmp;
+ napi_complete(napi);
+ tmp = qman_p_irqsource_add(np->p, QM_PIRQ_DQRI);
+ DPA_BUG_ON(tmp);
+ }
+
+ return cleaned;
+}
+
+static void __hot _dpa_tx_conf(struct net_device *net_dev,
+ const struct dpa_priv_s *priv,
+ struct dpa_percpu_priv_s *percpu_priv,
+ const struct qm_fd *fd,
+ u32 fqid)
+{
+ struct sk_buff *skb;
+
+ /* do we need the timestamp for the error frames? */
+
+ if (unlikely(fd->status & FM_FD_STAT_TX_ERRORS) != 0) {
+ if (netif_msg_hw(priv) && net_ratelimit())
+ netdev_warn(net_dev, "FD status = 0x%08x\n",
+ fd->status & FM_FD_STAT_TX_ERRORS);
+
+ percpu_priv->stats.tx_errors++;
+ }
+
+ /* hopefully we need not get the timestamp before the hook */
+#if defined(CONFIG_AS_FASTPATH) || defined(CONFIG_FSL_FMAN_TEST)
+ if (dpaa_eth_hooks.tx_confirm && dpaa_eth_hooks.tx_confirm(net_dev,
+ fd, fqid) == DPAA_ETH_STOLEN)
+ /* it's the hook that must now perform cleanup */
+ return;
+#endif
+ /* This might not perfectly reflect the reality, if the core dequeuing
+ * the Tx confirmation is different from the one that did the enqueue,
+ * but at least it'll show up in the total count.
+ */
+ percpu_priv->tx_confirm++;
+
+ skb = _dpa_cleanup_tx_fd(priv, fd);
+
+ dev_kfree_skb(skb);
+}
+
+static enum qman_cb_dqrr_result
+priv_rx_error_dqrr(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry *dq)
+{
+ struct net_device *net_dev;
+ struct dpa_priv_s *priv;
+ struct dpa_percpu_priv_s *percpu_priv;
+ int *count_ptr;
+
+ net_dev = ((struct dpa_fq *)fq)->net_dev;
+ priv = netdev_priv(net_dev);
+
+ percpu_priv = __this_cpu_ptr(priv->percpu_priv);
+ count_ptr = __this_cpu_ptr(priv->dpa_bp->percpu_count);
+
+ if (dpaa_eth_napi_schedule(percpu_priv, portal))
+ return qman_cb_dqrr_stop;
+
+ if (unlikely(dpaa_eth_refill_bpools(priv->dpa_bp, count_ptr)))
+ /* Unable to refill the buffer pool due to insufficient
+ * system memory. Just release the frame back into the pool,
+ * otherwise we'll soon end up with an empty buffer pool.
+ */
+ dpa_fd_release(net_dev, &dq->fd);
+ else
+ _dpa_rx_error(net_dev, priv, percpu_priv, &dq->fd, fq->fqid);
+
+ return qman_cb_dqrr_consume;
+}
+
+
+static enum qman_cb_dqrr_result __hot
+priv_rx_default_dqrr(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry *dq)
+{
+ struct net_device *net_dev;
+ struct dpa_priv_s *priv;
+ struct dpa_percpu_priv_s *percpu_priv;
+ int *count_ptr;
+ struct dpa_bp *dpa_bp;
+
+ net_dev = ((struct dpa_fq *)fq)->net_dev;
+ priv = netdev_priv(net_dev);
+ dpa_bp = priv->dpa_bp;
+
+ /* Trace the Rx fd */
+ trace_dpa_rx_fd(net_dev, fq, &dq->fd);
+
+ /* IRQ handler, non-migratable; safe to use __this_cpu_ptr here */
+ percpu_priv = __this_cpu_ptr(priv->percpu_priv);
+ count_ptr = __this_cpu_ptr(dpa_bp->percpu_count);
+
+ if (unlikely(dpaa_eth_napi_schedule(percpu_priv, portal)))
+ return qman_cb_dqrr_stop;
+
+ /* Vale of plenty: make sure we didn't run out of buffers */
+
+ if (unlikely(dpaa_eth_refill_bpools(dpa_bp, count_ptr)))
+ /* Unable to refill the buffer pool due to insufficient
+ * system memory. Just release the frame back into the pool,
+ * otherwise we'll soon end up with an empty buffer pool.
+ */
+ dpa_fd_release(net_dev, &dq->fd);
+ else
+ _dpa_rx(net_dev, portal, priv, percpu_priv, &dq->fd, fq->fqid,
+ count_ptr);
+
+ return qman_cb_dqrr_consume;
+}
+
+static enum qman_cb_dqrr_result
+priv_tx_conf_error_dqrr(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry *dq)
+{
+ struct net_device *net_dev;
+ struct dpa_priv_s *priv;
+ struct dpa_percpu_priv_s *percpu_priv;
+
+ net_dev = ((struct dpa_fq *)fq)->net_dev;
+ priv = netdev_priv(net_dev);
+
+ percpu_priv = __this_cpu_ptr(priv->percpu_priv);
+
+ if (dpaa_eth_napi_schedule(percpu_priv, portal))
+ return qman_cb_dqrr_stop;
+
+ _dpa_tx_error(net_dev, priv, percpu_priv, &dq->fd, fq->fqid);
+
+ return qman_cb_dqrr_consume;
+}
+
+static enum qman_cb_dqrr_result __hot
+priv_tx_conf_default_dqrr(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry *dq)
+{
+ struct net_device *net_dev;
+ struct dpa_priv_s *priv;
+ struct dpa_percpu_priv_s *percpu_priv;
+
+ net_dev = ((struct dpa_fq *)fq)->net_dev;
+ priv = netdev_priv(net_dev);
+
+ /* Trace the fd */
+ trace_dpa_tx_conf_fd(net_dev, fq, &dq->fd);
+
+ /* Non-migratable context, safe to use __this_cpu_ptr */
+ percpu_priv = __this_cpu_ptr(priv->percpu_priv);
+
+ if (dpaa_eth_napi_schedule(percpu_priv, portal))
+ return qman_cb_dqrr_stop;
+
+ _dpa_tx_conf(net_dev, priv, percpu_priv, &dq->fd, fq->fqid);
+
+ return qman_cb_dqrr_consume;
+}
+
+static void priv_ern(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_mr_entry *msg)
+{
+ struct net_device *net_dev;
+ const struct dpa_priv_s *priv;
+ struct sk_buff *skb;
+ struct dpa_percpu_priv_s *percpu_priv;
+ struct qm_fd fd = msg->ern.fd;
+
+ net_dev = ((struct dpa_fq *)fq)->net_dev;
+ priv = netdev_priv(net_dev);
+ /* Non-migratable context, safe to use __this_cpu_ptr */
+ percpu_priv = __this_cpu_ptr(priv->percpu_priv);
+
+ percpu_priv->stats.tx_dropped++;
+ percpu_priv->stats.tx_fifo_errors++;
+ count_ern(percpu_priv, msg);
+
+ /* If we intended this buffer to go into the pool
+ * when the FM was done, we need to put it in
+ * manually.
+ */
+ if (msg->ern.fd.cmd & FM_FD_CMD_FCO) {
+ dpa_fd_release(net_dev, &fd);
+ return;
+ }
+
+ skb = _dpa_cleanup_tx_fd(priv, &fd);
+ dev_kfree_skb_any(skb);
+}
+
+static const struct dpa_fq_cbs_t private_fq_cbs = {
+ .rx_defq = { .cb = { .dqrr = priv_rx_default_dqrr } },
+ .tx_defq = { .cb = { .dqrr = priv_tx_conf_default_dqrr } },
+ .rx_errq = { .cb = { .dqrr = priv_rx_error_dqrr } },
+ .tx_errq = { .cb = { .dqrr = priv_tx_conf_error_dqrr } },
+ .egress_ern = { .cb = { .ern = priv_ern } }
+};
+
+static void dpaa_eth_napi_enable(struct dpa_priv_s *priv)
+{
+ struct dpa_percpu_priv_s *percpu_priv;
+ int i, j;
+
+ for_each_possible_cpu(i) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+
+ for (j = 0; j < qman_portal_max; j++)
+ napi_enable(&percpu_priv->np[j].napi);
+ }
+}
+
+static void dpaa_eth_napi_disable(struct dpa_priv_s *priv)
+{
+ struct dpa_percpu_priv_s *percpu_priv;
+ int i, j;
+
+ for_each_possible_cpu(i) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+
+ for (j = 0; j < qman_portal_max; j++)
+ napi_disable(&percpu_priv->np[j].napi);
+ }
+}
+
+static int __cold dpa_eth_priv_start(struct net_device *net_dev)
+{
+ int err;
+ struct dpa_priv_s *priv;
+
+ priv = netdev_priv(net_dev);
+
+ dpaa_eth_napi_enable(priv);
+
+ err = dpa_start(net_dev);
+ if (err < 0)
+ dpaa_eth_napi_disable(priv);
+
+ return err;
+}
+
+
+
+static int __cold dpa_eth_priv_stop(struct net_device *net_dev)
+{
+ int _errno;
+ struct dpa_priv_s *priv;
+
+ _errno = dpa_stop(net_dev);
+ /* Allow NAPI to consume any frame still in the Rx/TxConfirm
+ * ingress queues. This is to avoid a race between the current
+ * context and ksoftirqd which could leave NAPI disabled while
+ * in fact there's still Rx traffic to be processed.
+ */
+ usleep_range(5000, 10000);
+
+ priv = netdev_priv(net_dev);
+ dpaa_eth_napi_disable(priv);
+
+ return _errno;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void dpaa_eth_poll_controller(struct net_device *net_dev)
+{
+ struct dpa_priv_s *priv = netdev_priv(net_dev);
+ struct dpa_percpu_priv_s *percpu_priv =
+ __this_cpu_ptr(priv->percpu_priv);
+ struct qman_portal *p;
+ const struct qman_portal_config *pc;
+ struct dpa_napi_portal *np;
+
+ p = (struct qman_portal *)qman_get_affine_portal(smp_processor_id());
+ pc = qman_p_get_portal_config(p);
+ np = &percpu_priv->np[pc->index];
+
+ qman_p_irqsource_remove(np->p, QM_PIRQ_DQRI);
+ qman_p_poll_dqrr(np->p, np->napi.weight);
+ qman_p_irqsource_add(np->p, QM_PIRQ_DQRI);
+}
+#endif
+
+static const struct net_device_ops dpa_private_ops = {
+ .ndo_open = dpa_eth_priv_start,
+ .ndo_start_xmit = dpa_tx,
+ .ndo_stop = dpa_eth_priv_stop,
+ .ndo_tx_timeout = dpa_timeout,
+ .ndo_get_stats64 = dpa_get_stats64,
+ .ndo_set_mac_address = dpa_set_mac_address,
+ .ndo_validate_addr = eth_validate_addr,
+#ifdef CONFIG_FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE
+ .ndo_select_queue = dpa_select_queue,
+#endif
+ .ndo_change_mtu = dpa_change_mtu,
+ .ndo_set_rx_mode = dpa_set_rx_mode,
+ .ndo_init = dpa_ndo_init,
+ .ndo_set_features = dpa_set_features,
+ .ndo_fix_features = dpa_fix_features,
+ .ndo_do_ioctl = dpa_ioctl,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = dpaa_eth_poll_controller,
+#endif
+};
+
+static int dpa_private_napi_add(struct net_device *net_dev)
+{
+ struct dpa_priv_s *priv = netdev_priv(net_dev);
+ struct dpa_percpu_priv_s *percpu_priv;
+ int i, cpu;
+
+ for_each_possible_cpu(cpu) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, cpu);
+
+ percpu_priv->np = devm_kzalloc(net_dev->dev.parent,
+ qman_portal_max * sizeof(struct dpa_napi_portal),
+ GFP_KERNEL);
+
+ if (unlikely(percpu_priv->np == NULL)) {
+ dev_err(net_dev->dev.parent, "devm_kzalloc() failed\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < qman_portal_max; i++)
+ netif_napi_add(net_dev, &percpu_priv->np[i].napi,
+ dpaa_eth_poll, DPA_NAPI_WEIGHT);
+ }
+
+ return 0;
+}
+
+void dpa_private_napi_del(struct net_device *net_dev)
+{
+ struct dpa_priv_s *priv = netdev_priv(net_dev);
+ struct dpa_percpu_priv_s *percpu_priv;
+ int i, cpu;
+
+ for_each_possible_cpu(cpu) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, cpu);
+
+ if (percpu_priv->np) {
+ for (i = 0; i < qman_portal_max; i++)
+ netif_napi_del(&percpu_priv->np[i].napi);
+
+ devm_kfree(net_dev->dev.parent, percpu_priv->np);
+ }
+ }
+}
+
+static int dpa_private_netdev_init(struct device_node *dpa_node,
+ struct net_device *net_dev)
+{
+ int i;
+ struct dpa_priv_s *priv = netdev_priv(net_dev);
+ struct dpa_percpu_priv_s *percpu_priv;
+ const uint8_t *mac_addr;
+
+ /* Although we access another CPU's private data here
+ * we do it at initialization so it is safe
+ */
+ for_each_possible_cpu(i) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+ percpu_priv->net_dev = net_dev;
+ }
+
+ net_dev->netdev_ops = &dpa_private_ops;
+ mac_addr = priv->mac_dev->addr;
+
+ net_dev->mem_start = priv->mac_dev->res->start;
+ net_dev->mem_end = priv->mac_dev->res->end;
+
+ net_dev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+ NETIF_F_LLTX);
+
+ /* Advertise S/G and HIGHDMA support for private interfaces */
+ net_dev->hw_features |= NETIF_F_SG | NETIF_F_HIGHDMA;
+ /* Recent kernels enable GSO automatically, if
+ * we declare NETIF_F_SG. For conformity, we'll
+ * still declare GSO explicitly.
+ */
+ net_dev->features |= NETIF_F_GSO;
+
+ /* Advertise GRO support */
+ net_dev->features |= NETIF_F_GRO;
+
+ return dpa_netdev_init(dpa_node, net_dev, mac_addr, tx_timeout);
+}
+
+static struct dpa_bp * __cold
+dpa_priv_bp_probe(struct device *dev)
+{
+ struct dpa_bp *dpa_bp;
+
+ dpa_bp = devm_kzalloc(dev, sizeof(*dpa_bp), GFP_KERNEL);
+ if (unlikely(dpa_bp == NULL)) {
+ dev_err(dev, "devm_kzalloc() failed\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ dpa_bp->percpu_count = alloc_percpu(*dpa_bp->percpu_count);
+ dpa_bp->target_count = CONFIG_FSL_DPAA_ETH_MAX_BUF_COUNT;
+
+ dpa_bp->seed_cb = dpa_bp_priv_seed;
+ dpa_bp->free_buf_cb = _dpa_bp_free_pf;
+
+ return dpa_bp;
+}
+
+/* Place all ingress FQs (Rx Default, Rx Error, PCD FQs) in a dedicated CGR.
+ * We won't be sending congestion notifications to FMan; for now, we just use
+ * this CGR to generate enqueue rejections to FMan in order to drop the frames
+ * before they reach our ingress queues and eat up memory.
+ */
+static int dpaa_eth_priv_ingress_cgr_init(struct dpa_priv_s *priv)
+{
+ struct qm_mcc_initcgr initcgr;
+ u32 cs_th;
+ int err;
+
+ err = qman_alloc_cgrid(&priv->ingress_cgr.cgrid);
+ if (err < 0) {
+ pr_err("Error %d allocating CGR ID\n", err);
+ goto out_error;
+ }
+
+ /* Enable CS TD, but disable Congestion State Change Notifications. */
+ initcgr.we_mask = QM_CGR_WE_CS_THRES;
+ initcgr.cgr.cscn_en = QM_CGR_EN;
+ cs_th = CONFIG_FSL_DPAA_INGRESS_CS_THRESHOLD;
+ qm_cgr_cs_thres_set64(&initcgr.cgr.cs_thres, cs_th, 1);
+
+ initcgr.we_mask |= QM_CGR_WE_CSTD_EN;
+ initcgr.cgr.cstd_en = QM_CGR_EN;
+
+ /* This is actually a hack, because this CGR will be associated with
+ * our affine SWP. However, we'll place our ingress FQs in it.
+ */
+ err = qman_create_cgr(&priv->ingress_cgr, QMAN_CGR_FLAG_USE_INIT,
+ &initcgr);
+ if (err < 0) {
+ pr_err("Error %d creating ingress CGR with ID %d\n", err,
+ priv->ingress_cgr.cgrid);
+ qman_release_cgrid(priv->ingress_cgr.cgrid);
+ goto out_error;
+ }
+ pr_debug("Created ingress CGR %d for netdev with hwaddr %pM\n",
+ priv->ingress_cgr.cgrid, priv->mac_dev->addr);
+
+ /* struct qman_cgr allows special cgrid values (i.e. outside the 0..255
+ * range), but we have no common initialization path between the
+ * different variants of the DPAA Eth driver, so we do it here rather
+ * than modifying every other variant than "private Eth".
+ */
+ priv->use_ingress_cgr = true;
+
+out_error:
+ return err;
+}
+
+static int dpa_priv_bp_create(struct net_device *net_dev, struct dpa_bp *dpa_bp,
+ size_t count)
+{
+ struct dpa_priv_s *priv = netdev_priv(net_dev);
+ int i;
+
+ if (netif_msg_probe(priv))
+ dev_dbg(net_dev->dev.parent,
+ "Using private BM buffer pools\n");
+
+ priv->bp_count = count;
+
+ for (i = 0; i < count; i++) {
+ int err;
+ err = dpa_bp_alloc(&dpa_bp[i]);
+ if (err < 0) {
+ dpa_bp_free(priv, dpa_bp);
+ priv->dpa_bp = NULL;
+ return err;
+ }
+
+ priv->dpa_bp = &dpa_bp[i];
+ }
+
+ dpa_priv_common_bpid = priv->dpa_bp->bpid;
+ return 0;
+}
+
+static const struct of_device_id dpa_match[];
+
+static int
+dpaa_eth_priv_probe(struct platform_device *_of_dev)
+{
+ int err = 0, i, channel;
+ struct device *dev;
+ struct device_node *dpa_node;
+ struct dpa_bp *dpa_bp;
+ struct dpa_fq *dpa_fq, *tmp;
+ size_t count = 1;
+ struct net_device *net_dev = NULL;
+ struct dpa_priv_s *priv = NULL;
+ struct dpa_percpu_priv_s *percpu_priv;
+ struct fm_port_fqs port_fqs;
+ struct dpa_buffer_layout_s *buf_layout = NULL;
+ struct mac_device *mac_dev;
+ struct task_struct *kth;
+
+ dev = &_of_dev->dev;
+
+ dpa_node = dev->of_node;
+
+ if (!of_device_is_available(dpa_node))
+ return -ENODEV;
+
+ /* Get the buffer pools assigned to this interface;
+ * run only once the default pool probing code
+ */
+ dpa_bp = (dpa_bpid2pool(dpa_priv_common_bpid)) ? :
+ dpa_priv_bp_probe(dev);
+ if (IS_ERR(dpa_bp))
+ return PTR_ERR(dpa_bp);
+
+ /* Allocate this early, so we can store relevant information in
+ * the private area (needed by 1588 code in dpa_mac_probe)
+ */
+ net_dev = alloc_etherdev_mq(sizeof(*priv), DPAA_ETH_TX_QUEUES);
+ if (!net_dev) {
+ dev_err(dev, "alloc_etherdev_mq() failed\n");
+ goto alloc_etherdev_mq_failed;
+ }
+
+ /* Do this here, so we can be verbose early */
+ SET_NETDEV_DEV(net_dev, dev);
+ dev_set_drvdata(dev, net_dev);
+
+ priv = netdev_priv(net_dev);
+ priv->net_dev = net_dev;
+ strcpy(priv->if_type, "private");
+
+ priv->msg_enable = netif_msg_init(debug, -1);
+
+ mac_dev = dpa_mac_probe(_of_dev);
+ if (IS_ERR(mac_dev) || !mac_dev) {
+ err = PTR_ERR(mac_dev);
+ goto mac_probe_failed;
+ }
+
+ /* We have physical ports, so we need to establish
+ * the buffer layout.
+ */
+ buf_layout = devm_kzalloc(dev, 2 * sizeof(*buf_layout),
+ GFP_KERNEL);
+ if (!buf_layout) {
+ dev_err(dev, "devm_kzalloc() failed\n");
+ goto alloc_failed;
+ }
+ dpa_set_buffers_layout(mac_dev, buf_layout);
+
+ /* For private ports, need to compute the size of the default
+ * buffer pool, based on FMan port buffer layout;also update
+ * the maximum buffer size for private ports if necessary
+ */
+ dpa_bp->size = dpa_bp_size(&buf_layout[RX]);
+
+#ifdef CONFIG_FSL_DPAA_ETH_JUMBO_FRAME
+ /* We only want to use jumbo frame optimization if we actually have
+ * L2 MAX FRM set for jumbo frames as well.
+ */
+ if (fm_get_max_frm() < 9600)
+ dev_warn(dev,
+ "Invalid configuration: if jumbo frames support is on, FSL_FM_MAX_FRAME_SIZE should be set to 9600\n");
+#endif
+
+ INIT_LIST_HEAD(&priv->dpa_fq_list);
+
+ memset(&port_fqs, 0, sizeof(port_fqs));
+
+ err = dpa_fq_probe_mac(dev, &priv->dpa_fq_list, &port_fqs, true, RX);
+ if (!err)
+ err = dpa_fq_probe_mac(dev, &priv->dpa_fq_list,
+ &port_fqs, true, TX);
+
+ if (err < 0)
+ goto fq_probe_failed;
+
+ /* bp init */
+
+ err = dpa_priv_bp_create(net_dev, dpa_bp, count);
+
+ if (err < 0)
+ goto bp_create_failed;
+
+ priv->mac_dev = mac_dev;
+
+ channel = dpa_get_channel();
+
+ if (channel < 0) {
+ err = channel;
+ goto get_channel_failed;
+ }
+
+ priv->channel = (uint16_t)channel;
+
+ /* Start a thread that will walk the cpus with affine portals
+ * and add this pool channel to each's dequeue mask.
+ */
+ kth = kthread_run(dpaa_eth_add_channel,
+ (void *)(unsigned long)priv->channel,
+ "dpaa_%p:%d", net_dev, priv->channel);
+ if (!kth) {
+ err = -ENOMEM;
+ goto add_channel_failed;
+ }
+
+ dpa_fq_setup(priv, &private_fq_cbs, priv->mac_dev->port_dev[TX]);
+
+ /* Create a congestion group for this netdev, with
+ * dynamically-allocated CGR ID.
+ * Must be executed after probing the MAC, but before
+ * assigning the egress FQs to the CGRs.
+ */
+ err = dpaa_eth_cgr_init(priv);
+ if (err < 0) {
+ dev_err(dev, "Error initializing CGR\n");
+ goto tx_cgr_init_failed;
+ }
+ err = dpaa_eth_priv_ingress_cgr_init(priv);
+ if (err < 0) {
+ dev_err(dev, "Error initializing ingress CGR\n");
+ goto rx_cgr_init_failed;
+ }
+
+ /* Add the FQs to the interface, and make them active */
+ list_for_each_entry_safe(dpa_fq, tmp, &priv->dpa_fq_list, list) {
+ err = dpa_fq_init(dpa_fq, false);
+ if (err < 0)
+ goto fq_alloc_failed;
+ }
+
+ priv->buf_layout = buf_layout;
+ priv->tx_headroom = dpa_get_headroom(&priv->buf_layout[TX]);
+ priv->rx_headroom = dpa_get_headroom(&priv->buf_layout[RX]);
+
+ /* All real interfaces need their ports initialized */
+ dpaa_eth_init_ports(mac_dev, dpa_bp, count, &port_fqs,
+ buf_layout, dev);
+
+#ifdef CONFIG_FMAN_PFC
+ for (i = 0; i < CONFIG_FMAN_PFC_COS_COUNT; i++) {
+ err = fm_port_set_pfc_priorities_mapping_to_qman_wq(
+ mac_dev->port_dev[TX], i, i);
+ if (unlikely(err != 0)) {
+ dev_err(dev, "Error maping PFC %u to WQ %u\n", i, i);
+ goto pfc_mapping_failed;
+ }
+ }
+#endif
+
+ priv->percpu_priv = alloc_percpu(*priv->percpu_priv);
+
+ if (priv->percpu_priv == NULL) {
+ dev_err(dev, "alloc_percpu() failed\n");
+ err = -ENOMEM;
+ goto alloc_percpu_failed;
+ }
+ for_each_possible_cpu(i) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+ memset(percpu_priv, 0, sizeof(*percpu_priv));
+ }
+
+ /* Initialize NAPI */
+ err = dpa_private_napi_add(net_dev);
+
+ if (err < 0)
+ goto napi_add_failed;
+
+ err = dpa_private_netdev_init(dpa_node, net_dev);
+
+ if (err < 0)
+ goto netdev_init_failed;
+
+ dpaa_eth_sysfs_init(&net_dev->dev);
+
+#ifdef CONFIG_PM
+ device_set_wakeup_capable(dev, true);
+#endif
+
+ pr_info("fsl_dpa: Probed interface %s\n", net_dev->name);
+
+ return 0;
+
+netdev_init_failed:
+napi_add_failed:
+ dpa_private_napi_del(net_dev);
+ free_percpu(priv->percpu_priv);
+#ifdef CONFIG_FMAN_PFC
+pfc_mapping_failed:
+#endif
+alloc_percpu_failed:
+ dpa_fq_free(dev, &priv->dpa_fq_list);
+fq_alloc_failed:
+ qman_release_cgrid(priv->ingress_cgr.cgrid);
+ qman_delete_cgr(&priv->ingress_cgr);
+rx_cgr_init_failed:
+ qman_release_cgrid(priv->cgr_data.cgr.cgrid);
+ qman_delete_cgr(&priv->cgr_data.cgr);
+tx_cgr_init_failed:
+add_channel_failed:
+get_channel_failed:
+ dpa_bp_free(priv, priv->dpa_bp);
+bp_create_failed:
+fq_probe_failed:
+ devm_kfree(dev, buf_layout);
+alloc_failed:
+mac_probe_failed:
+ dev_set_drvdata(dev, NULL);
+ free_netdev(net_dev);
+alloc_etherdev_mq_failed:
+ if (atomic_read(&dpa_bp->refs) == 0)
+ devm_kfree(dev, dpa_bp);
+
+ return err;
+}
+
+static const struct of_device_id dpa_match[] = {
+ {
+ .compatible = "fsl,dpa-ethernet"
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, dpa_match);
+
+static struct platform_driver dpa_driver = {
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .of_match_table = dpa_match,
+ .owner = THIS_MODULE,
+ .pm = DPAA_PM_OPS,
+ },
+ .probe = dpaa_eth_priv_probe,
+ .remove = dpa_remove
+};
+
+static int __init __cold dpa_load(void)
+{
+ int _errno;
+
+ pr_info(DPA_DESCRIPTION " (" VERSION ")\n");
+
+ /* initialise dpaa_eth mirror values */
+ dpa_rx_extra_headroom = fm_get_rx_extra_headroom();
+ dpa_max_frm = fm_get_max_frm();
+ dpa_num_cpus = num_possible_cpus();
+
+ _errno = platform_driver_register(&dpa_driver);
+ if (unlikely(_errno < 0)) {
+ pr_err(KBUILD_MODNAME
+ ": %s:%hu:%s(): platform_driver_register() = %d\n",
+ KBUILD_BASENAME".c", __LINE__, __func__, _errno);
+ }
+
+ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n",
+ KBUILD_BASENAME".c", __func__);
+
+ return _errno;
+}
+module_init(dpa_load);
+
+static void __exit __cold dpa_unload(void)
+{
+ pr_debug(KBUILD_MODNAME ": -> %s:%s()\n",
+ KBUILD_BASENAME".c", __func__);
+
+ platform_driver_unregister(&dpa_driver);
+
+ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n",
+ KBUILD_BASENAME".c", __func__);
+}
+module_exit(dpa_unload);
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth.h b/drivers/net/ethernet/freescale/dpa/dpaa_eth.h
new file mode 100644
index 0000000..8511826
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth.h
@@ -0,0 +1,618 @@
+/* Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DPA_H
+#define __DPA_H
+
+#include <linux/netdevice.h>
+#include <linux/fsl_qman.h> /* struct qman_fq */
+
+#include "fm_ext.h"
+#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS
+#include "dpaa_debugfs.h"
+#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */
+#include "dpaa_eth_trace.h"
+
+extern int dpa_rx_extra_headroom;
+extern int dpa_max_frm;
+extern int dpa_num_cpus;
+
+#define dpa_get_rx_extra_headroom() dpa_rx_extra_headroom
+#define dpa_get_max_frm() dpa_max_frm
+
+/* Currently we have the same max_frm on all interfaces, so these macros
+ * don't get a net_device argument. This will change in the future.
+ */
+#define dpa_get_min_mtu() 64
+#define dpa_get_max_mtu() \
+ (dpa_get_max_frm() - (VLAN_ETH_HLEN + ETH_FCS_LEN))
+
+#define __hot
+
+/* Simple enum of FQ types - used for array indexing */
+enum port_type {RX, TX};
+
+/* TODO: This structure should be renamed & moved to the FMD wrapper */
+struct dpa_buffer_layout_s {
+ uint16_t priv_data_size;
+ bool parse_results;
+ bool time_stamp;
+ bool hash_results;
+ uint8_t manip_extra_space;
+ uint16_t data_align;
+};
+
+#ifdef CONFIG_FSL_DPAA_ETH_DEBUG
+#define DPA_BUG_ON(cond) BUG_ON(cond)
+#else
+#define DPA_BUG_ON(cond)
+#endif
+
+#define DPA_TX_PRIV_DATA_SIZE 16
+#define DPA_PARSE_RESULTS_SIZE sizeof(fm_prs_result_t)
+#define DPA_TIME_STAMP_SIZE 8
+#define DPA_HASH_RESULTS_SIZE 8
+#define DPA_RX_PRIV_DATA_SIZE (DPA_TX_PRIV_DATA_SIZE + \
+ dpa_get_rx_extra_headroom())
+
+#define FM_FD_STAT_RX_ERRORS \
+ (FM_PORT_FRM_ERR_DMA | FM_PORT_FRM_ERR_PHYSICAL | \
+ FM_PORT_FRM_ERR_SIZE | FM_PORT_FRM_ERR_CLS_DISCARD | \
+ FM_PORT_FRM_ERR_EXTRACTION | FM_PORT_FRM_ERR_NO_SCHEME | \
+ FM_PORT_FRM_ERR_ILL_PLCR | FM_PORT_FRM_ERR_PRS_TIMEOUT | \
+ FM_PORT_FRM_ERR_PRS_ILL_INSTRUCT | FM_PORT_FRM_ERR_PRS_HDR_ERR)
+
+#define FM_FD_STAT_TX_ERRORS \
+ (FM_PORT_FRM_ERR_UNSUPPORTED_FORMAT | \
+ FM_PORT_FRM_ERR_LENGTH | FM_PORT_FRM_ERR_DMA)
+
+#ifndef CONFIG_FSL_DPAA_ETH_JUMBO_FRAME
+/* The raw buffer size must be cacheline aligned.
+ * Normally we use 2K buffers.
+ */
+#define DPA_BP_RAW_SIZE 2048
+#else
+/* For jumbo frame optimizations, use buffers large enough to accommodate
+ * 9.6K frames, FD maximum offset, skb sh_info overhead and some extra
+ * space to account for further alignments.
+ */
+#define DPA_MAX_FRM_SIZE 9600
+#define DPA_BP_RAW_SIZE \
+ ((DPA_MAX_FRM_SIZE + DPA_MAX_FD_OFFSET + \
+ sizeof(struct skb_shared_info) + 128) & ~(SMP_CACHE_BYTES - 1))
+#endif
+
+/* This is what FMan is ever allowed to use.
+ * FMan-DMA requires 16-byte alignment for Rx buffers, but SKB_DATA_ALIGN is
+ * even stronger (SMP_CACHE_BYTES-aligned), so we just get away with that,
+ * via SKB_WITH_OVERHEAD(). We can't rely on netdev_alloc_frag() giving us
+ * half-page-aligned buffers (can we?), so we reserve some more space
+ * for start-of-buffer alignment.
+ */
+#define dpa_bp_size(buffer_layout) (SKB_WITH_OVERHEAD(DPA_BP_RAW_SIZE) - \
+ SMP_CACHE_BYTES)
+/* We must ensure that skb_shinfo is always cacheline-aligned. */
+#define DPA_SKB_SIZE(size) ((size) & ~(SMP_CACHE_BYTES - 1))
+
+/* Maximum size of a buffer for which recycling is allowed.
+ * We need an upper limit such that forwarded skbs that get reallocated on Tx
+ * aren't allowed to grow unboundedly. On the other hand, we need to make sure
+ * that skbs allocated by us will not fail to be recycled due to their size.
+ *
+ * For a requested size, the kernel allocator provides the next power of two
+ * sized block, which the stack will use as is, regardless of the actual size
+ * it required; since we must accommodate at most 9.6K buffers (L2 maximum
+ * supported frame size), set the recycling upper limit to 16K.
+ */
+#define DPA_RECYCLE_MAX_SIZE 16384
+
+#if defined(CONFIG_FSL_FMAN_TEST)
+/*TODO: temporary for fman pcd testing */
+#define FMAN_PCD_TESTS_MAX_NUM_RANGES 20
+#endif
+
+#define DPAA_ETH_PCD_FQ_BASE(device_addr) \
+ (((device_addr) & 0x1fffff) >> 6)
+
+/* Largest value that the FQD's OAL field can hold.
+ * This is DPAA-1.x specific.
+ * TODO: This rather belongs in fsl_qman.h
+ */
+#define FSL_QMAN_MAX_OAL 127
+
+/* Maximum offset value for a contig or sg FD (represented on 9 bits) */
+#define DPA_MAX_FD_OFFSET ((1 << 9) - 1)
+
+/* Default alignment for start of data in an Rx FD */
+#define DPA_FD_DATA_ALIGNMENT 16
+
+/* Values for the L3R field of the FM Parse Results
+ */
+/* L3 Type field: First IP Present IPv4 */
+#define FM_L3_PARSE_RESULT_IPV4 0x8000
+/* L3 Type field: First IP Present IPv6 */
+#define FM_L3_PARSE_RESULT_IPV6 0x4000
+
+/* Values for the L4R field of the FM Parse Results
+ * See $8.8.4.7.20 - L4 HXS - L4 Results from DPAA-Rev2 Reference Manual.
+ */
+/* L4 Type field: UDP */
+#define FM_L4_PARSE_RESULT_UDP 0x40
+/* L4 Type field: TCP */
+#define FM_L4_PARSE_RESULT_TCP 0x20
+/* FD status field indicating whether the FM Parser has attempted to validate
+ * the L4 csum of the frame.
+ * Note that having this bit set doesn't necessarily imply that the checksum
+ * is valid. One would have to check the parse results to find that out.
+ */
+#define FM_FD_STAT_L4CV 0x00000004
+
+
+#define FM_FD_STAT_ERR_PHYSICAL FM_PORT_FRM_ERR_PHYSICAL
+
+/* Check if the parsed frame was found to be a TCP segment.
+ *
+ * @parse_result_ptr must be of type (fm_prs_result_t *).
+ */
+#define fm_l4_frame_is_tcp(parse_result_ptr) \
+ ((parse_result_ptr)->l4r & FM_L4_PARSE_RESULT_TCP)
+
+/* number of Tx queues to FMan */
+#ifdef CONFIG_FMAN_PFC
+#define DPAA_ETH_TX_QUEUES (NR_CPUS * CONFIG_FMAN_PFC_COS_COUNT)
+#else
+#define DPAA_ETH_TX_QUEUES NR_CPUS
+#endif
+
+#define DPAA_ETH_RX_QUEUES 128
+
+#ifdef CONFIG_PM
+/* Magic Packet wakeup */
+#define DPAA_WOL_MAGIC 0x00000001
+#endif
+
+#if defined(CONFIG_FSL_FMAN_TEST)
+struct pcd_range {
+ uint32_t base;
+ uint32_t count;
+};
+#endif
+
+/* More detailed FQ types - used for fine-grained WQ assignments */
+enum dpa_fq_type {
+ FQ_TYPE_RX_DEFAULT = 1, /* Rx Default FQs */
+ FQ_TYPE_RX_ERROR, /* Rx Error FQs */
+ FQ_TYPE_RX_PCD, /* User-defined PCDs */
+ FQ_TYPE_TX, /* "Real" Tx FQs */
+ FQ_TYPE_TX_CONFIRM, /* Tx default Conf FQ (actually an Rx FQ) */
+ FQ_TYPE_TX_CONF_MQ, /* Tx conf FQs (one for each Tx FQ) */
+ FQ_TYPE_TX_ERROR, /* Tx Error FQs (these are actually Rx FQs) */
+#ifdef CONFIG_FMAN_T4240
+ FQ_TYPE_TX_RECYCLE, /* Tx FQs for recycleable frames only */
+#endif
+};
+
+struct dpa_fq {
+ struct qman_fq fq_base;
+ struct list_head list;
+ struct net_device *net_dev;
+ bool init;
+ uint32_t fqid;
+ uint32_t flags;
+ uint16_t channel;
+ uint8_t wq;
+ enum dpa_fq_type fq_type;
+};
+
+struct dpa_fq_cbs_t {
+ struct qman_fq rx_defq;
+ struct qman_fq tx_defq;
+ struct qman_fq rx_errq;
+ struct qman_fq tx_errq;
+ struct qman_fq egress_ern;
+};
+
+struct fqid_cell {
+ uint32_t start;
+ uint32_t count;
+};
+
+struct dpa_bp {
+ struct bman_pool *pool;
+ uint8_t bpid;
+ struct device *dev;
+ union {
+ /* The buffer pools used for the private ports are initialized
+ * with target_count buffers for each CPU; at runtime the
+ * number of buffers per CPU is constantly brought back to this
+ * level
+ */
+ int target_count;
+ /* The configured value for the number of buffers in the pool,
+ * used for shared port buffer pools
+ */
+ int config_count;
+ };
+ size_t size;
+ bool seed_pool;
+ /* physical address of the contiguous memory used by the pool to store
+ * the buffers
+ */
+ dma_addr_t paddr;
+ /* virtual address of the contiguous memory used by the pool to store
+ * the buffers
+ */
+ void __iomem *vaddr;
+ /* current number of buffers in the bpool alloted to this CPU */
+ int __percpu *percpu_count;
+ atomic_t refs;
+ /* some bpools need to be seeded before use by this cb */
+ int (*seed_cb)(struct dpa_bp *);
+ /* some bpools need to be emptied before freeing; this cb is used
+ * for freeing of individual buffers taken from the pool
+ */
+ void (*free_buf_cb)(void *addr);
+};
+
+struct dpa_rx_errors {
+ u64 dme; /* DMA Error */
+ u64 fpe; /* Frame Physical Error */
+ u64 fse; /* Frame Size Error */
+ u64 phe; /* Header Error */
+ u64 cse; /* Checksum Validation Error */
+};
+
+/* Counters for QMan ERN frames - one counter per rejection code */
+struct dpa_ern_cnt {
+ u64 cg_tdrop; /* Congestion group taildrop */
+ u64 wred; /* WRED congestion */
+ u64 err_cond; /* Error condition */
+ u64 early_window; /* Order restoration, frame too early */
+ u64 late_window; /* Order restoration, frame too late */
+ u64 fq_tdrop; /* FQ taildrop */
+ u64 fq_retired; /* FQ is retired */
+ u64 orp_zero; /* ORP disabled */
+};
+
+struct dpa_napi_portal {
+ struct napi_struct napi;
+ struct qman_portal *p;
+};
+
+struct dpa_percpu_priv_s {
+ struct net_device *net_dev;
+ struct dpa_napi_portal *np;
+ u64 in_interrupt;
+ u64 tx_returned;
+ u64 tx_confirm;
+ /* fragmented (non-linear) skbuffs received from the stack */
+ u64 tx_frag_skbuffs;
+ struct rtnl_link_stats64 stats;
+ struct dpa_rx_errors rx_errors;
+ struct dpa_ern_cnt ern_cnt;
+};
+
+struct dpa_priv_s {
+ struct dpa_percpu_priv_s __percpu *percpu_priv;
+ struct dpa_bp *dpa_bp;
+ /* Store here the needed Tx headroom for convenience and speed
+ * (even though it can be computed based on the fields of buf_layout)
+ */
+ uint16_t tx_headroom;
+ struct net_device *net_dev;
+ struct mac_device *mac_dev;
+ struct qman_fq *egress_fqs[DPAA_ETH_TX_QUEUES];
+ struct qman_fq *conf_fqs[DPAA_ETH_TX_QUEUES];
+
+ size_t bp_count;
+
+ uint16_t channel; /* "fsl,qman-channel-id" */
+ struct list_head dpa_fq_list;
+#ifdef CONFIG_FMAN_T4240
+ struct qman_fq *recycle_fqs[DPAA_ETH_TX_QUEUES];
+#endif
+
+#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS
+ struct dentry *debugfs_file;
+#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */
+
+ uint32_t msg_enable; /* net_device message level */
+#ifdef CONFIG_FSL_DPAA_1588
+ struct dpa_ptp_tsu *tsu;
+#endif
+
+#if defined(CONFIG_FSL_FMAN_TEST)
+/* TODO: this is temporary until pcd support is implemented in dpaa */
+ int priv_pcd_num_ranges;
+ struct pcd_range priv_pcd_ranges[FMAN_PCD_TESTS_MAX_NUM_RANGES];
+#endif
+
+ struct {
+ /**
+ * All egress queues to a given net device belong to one
+ * (and the same) congestion group.
+ */
+ struct qman_cgr cgr;
+ /* If congested, when it began. Used for performance stats. */
+ u32 congestion_start_jiffies;
+ /* Number of jiffies the Tx port was congested. */
+ u32 congested_jiffies;
+ /**
+ * Counter for the number of times the CGR
+ * entered congestion state
+ */
+ u32 cgr_congested_count;
+ } cgr_data;
+ /* Use a per-port CGR for ingress traffic. */
+ bool use_ingress_cgr;
+ struct qman_cgr ingress_cgr;
+
+#ifdef CONFIG_FSL_DPAA_TS
+ bool ts_tx_en; /* Tx timestamping enabled */
+ bool ts_rx_en; /* Rx timestamping enabled */
+#endif /* CONFIG_FSL_DPAA_TS */
+
+ struct dpa_buffer_layout_s *buf_layout;
+ uint16_t rx_headroom;
+ char if_type[30];
+
+ void *peer;
+#ifdef CONFIG_PM
+ u32 wol;
+#endif
+};
+
+struct fm_port_fqs {
+ struct dpa_fq *tx_defq;
+ struct dpa_fq *tx_errq;
+ struct dpa_fq *rx_defq;
+ struct dpa_fq *rx_errq;
+};
+
+/* functions with different implementation for SG and non-SG: */
+int dpa_bp_priv_seed(struct dpa_bp *dpa_bp);
+int dpaa_eth_refill_bpools(struct dpa_bp *dpa_bp, int *count_ptr);
+void __hot _dpa_rx(struct net_device *net_dev,
+ struct qman_portal *portal,
+ const struct dpa_priv_s *priv,
+ struct dpa_percpu_priv_s *percpu_priv,
+ const struct qm_fd *fd,
+ u32 fqid,
+ int *count_ptr);
+int __hot dpa_tx(struct sk_buff *skb, struct net_device *net_dev);
+struct sk_buff *_dpa_cleanup_tx_fd(const struct dpa_priv_s *priv,
+ const struct qm_fd *fd);
+void __hot _dpa_process_parse_results(const fm_prs_result_t *parse_results,
+ const struct qm_fd *fd,
+ struct sk_buff *skb,
+ int *use_gro);
+
+/* Turn on HW checksum computation for this outgoing frame.
+ * If the current protocol is not something we support in this regard
+ * (or if the stack has already computed the SW checksum), we do nothing.
+ *
+ * Returns 0 if all goes well (or HW csum doesn't apply), and a negative value
+ * otherwise.
+ *
+ * Note that this function may modify the fd->cmd field and the skb data buffer
+ * (the Parse Results area).
+ */
+int dpa_enable_tx_csum(struct dpa_priv_s *priv,
+ struct sk_buff *skb, struct qm_fd *fd, char *parse_results);
+
+static inline int dpaa_eth_napi_schedule(struct dpa_percpu_priv_s *percpu_priv,
+ struct qman_portal *portal)
+{
+ /* In case of threaded ISR for RT enable kernel,
+ * in_irq() does not return appropriate value, so use
+ * in_serving_softirq to distinguish softirq or irq context.
+ */
+ if (unlikely(in_irq() || !in_serving_softirq())) {
+ /* Disable QMan IRQ and invoke NAPI */
+ int ret = qman_p_irqsource_remove(portal, QM_PIRQ_DQRI);
+ if (likely(!ret)) {
+ const struct qman_portal_config *pc =
+ qman_p_get_portal_config(portal);
+ struct dpa_napi_portal *np =
+ &percpu_priv->np[pc->index];
+
+ np->p = portal;
+ napi_schedule(&np->napi);
+ percpu_priv->in_interrupt++;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static inline ssize_t __const __must_check __attribute__((nonnull))
+dpa_fd_length(const struct qm_fd *fd)
+{
+ return fd->length20;
+}
+
+static inline ssize_t __const __must_check __attribute__((nonnull))
+dpa_fd_offset(const struct qm_fd *fd)
+{
+ return fd->offset;
+}
+
+/* Verifies if the skb length is below the interface MTU */
+static inline int dpa_check_rx_mtu(struct sk_buff *skb, int mtu)
+{
+ if (unlikely(skb->len > mtu))
+ if ((skb->protocol != ETH_P_8021Q) || (skb->len > mtu + 4))
+ return -1;
+
+ return 0;
+}
+
+static inline uint16_t dpa_get_headroom(struct dpa_buffer_layout_s *bl)
+{
+ uint16_t headroom;
+ /* The frame headroom must accommodate:
+ * - the driver private data area
+ * - parse results, hash results, timestamp if selected
+ * - manip extra space
+ * If either hash results or time stamp are selected, both will
+ * be copied to/from the frame headroom, as TS is located between PR and
+ * HR in the IC and IC copy size has a granularity of 16bytes
+ * (see description of FMBM_RICP and FMBM_TICP registers in DPAARM)
+ *
+ * Also make sure the headroom is a multiple of data_align bytes
+ */
+ headroom = bl->priv_data_size +
+ (bl->parse_results ? DPA_PARSE_RESULTS_SIZE : 0) +
+ (bl->hash_results || bl->time_stamp ?
+ DPA_TIME_STAMP_SIZE + DPA_HASH_RESULTS_SIZE : 0) +
+ bl->manip_extra_space;
+
+ return bl->data_align ? ALIGN(headroom, bl->data_align) : headroom;
+}
+
+int fm_mac_dump_regs(struct mac_device *h_dev, char *buf, int n);
+
+void dpaa_eth_sysfs_remove(struct device *dev);
+void dpaa_eth_sysfs_init(struct device *dev);
+int dpaa_eth_poll(struct napi_struct *napi, int budget);
+
+void dpa_private_napi_del(struct net_device *net_dev);
+
+/* Equivalent to a memset(0), but works faster */
+static inline void clear_fd(struct qm_fd *fd)
+{
+ fd->opaque_addr = 0;
+ fd->opaque = 0;
+ fd->cmd = 0;
+}
+
+static inline int __hot dpa_xmit(struct dpa_priv_s *priv,
+ struct rtnl_link_stats64 *percpu_stats, int queue,
+ struct qm_fd *fd)
+{
+ int err, i;
+ struct qman_fq *egress_fq;
+
+#ifdef CONFIG_FMAN_T4240
+ /* Choose egress fq based on whether we want
+ * to recycle the frame or not
+ */
+ if (fd->cmd & FM_FD_CMD_FCO)
+ egress_fq = priv->recycle_fqs[queue];
+ else
+ egress_fq = priv->egress_fqs[queue];
+#else
+ egress_fq = priv->egress_fqs[queue];
+#endif
+
+ /* Trace this Tx fd */
+ trace_dpa_tx_fd(priv->net_dev, egress_fq, fd);
+
+ for (i = 0; i < 100000; i++) {
+ err = qman_enqueue(egress_fq, fd, 0);
+ if (err != -EBUSY)
+ break;
+ }
+
+ if (unlikely(err < 0)) {
+ /* TODO differentiate b/w -EBUSY (EQCR full) and other codes? */
+ percpu_stats->tx_errors++;
+ percpu_stats->tx_fifo_errors++;
+ return err;
+ }
+
+ percpu_stats->tx_packets++;
+ percpu_stats->tx_bytes += dpa_fd_length(fd);
+
+ return 0;
+}
+
+/* Use multiple WQs for FQ assignment:
+ * - Tx Confirmation queues go to WQ1.
+ * - Rx Default, Tx and PCD queues go to WQ3 (no differentiation between
+ * Rx and Tx traffic, or between Rx Default and Rx PCD frames).
+ * - Rx Error and Tx Error queues go to WQ2 (giving them a better chance
+ * to be scheduled, in case there are many more FQs in WQ3).
+ * This ensures that Tx-confirmed buffers are timely released. In particular,
+ * it avoids congestion on the Tx Confirm FQs, which can pile up PFDRs if they
+ * are greatly outnumbered by other FQs in the system (usually PCDs), while
+ * dequeue scheduling is round-robin.
+ */
+static inline void _dpa_assign_wq(struct dpa_fq *fq)
+{
+ switch (fq->fq_type) {
+ case FQ_TYPE_TX_CONFIRM:
+ case FQ_TYPE_TX_CONF_MQ:
+ fq->wq = 1;
+ break;
+ case FQ_TYPE_RX_DEFAULT:
+ case FQ_TYPE_TX:
+#ifdef CONFIG_FMAN_T4240
+ case FQ_TYPE_TX_RECYCLE:
+#endif
+ case FQ_TYPE_RX_PCD:
+ fq->wq = 3;
+ break;
+ case FQ_TYPE_RX_ERROR:
+ case FQ_TYPE_TX_ERROR:
+ fq->wq = 2;
+ break;
+ default:
+ WARN(1, "Invalid FQ type %d for FQID %d!\n",
+ fq->fq_type, fq->fqid);
+ }
+}
+
+#ifdef CONFIG_FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE
+/* Use in lieu of skb_get_queue_mapping() */
+#ifdef CONFIG_FMAN_PFC
+#define dpa_get_queue_mapping(skb) \
+ (((skb)->priority < CONFIG_FMAN_PFC_COS_COUNT) ? \
+ ((skb)->priority * dpa_num_cpus + smp_processor_id()) : \
+ ((CONFIG_FMAN_PFC_COS_COUNT - 1) * \
+ dpa_num_cpus + smp_processor_id()));
+
+#else
+#define dpa_get_queue_mapping(skb) \
+ smp_processor_id()
+#endif
+#else
+/* Use the queue selected by XPS */
+#define dpa_get_queue_mapping(skb) \
+ skb_get_queue_mapping(skb)
+#endif
+
+static inline void _dpa_bp_free_pf(void *addr)
+{
+ put_page(virt_to_head_page(addr));
+}
+
+#endif /* __DPA_H */
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth_base.c b/drivers/net/ethernet/freescale/dpa/dpaa_eth_base.c
new file mode 100644
index 0000000..2a744e5
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth_base.c
@@ -0,0 +1,221 @@
+/* Copyright 2008-2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_net.h>
+#include <linux/etherdevice.h>
+#include <linux/kthread.h>
+#include <linux/percpu.h>
+#include <linux/highmem.h>
+#include <linux/sort.h>
+#include <linux/fsl_qman.h>
+#include "dpaa_eth.h"
+#include "dpaa_eth_common.h"
+#include "dpaa_eth_base.h"
+
+static int dpa_bp_cmp(const void *dpa_bp0, const void *dpa_bp1)
+{
+ return ((struct dpa_bp *)dpa_bp0)->size -
+ ((struct dpa_bp *)dpa_bp1)->size;
+}
+
+struct dpa_bp * __cold __must_check /* __attribute__((nonnull)) */
+dpa_bp_probe(struct platform_device *_of_dev, size_t *count)
+{
+ int i, lenp, na, ns;
+ struct device *dev;
+ struct device_node *dev_node;
+ const phandle *phandle_prop;
+ const uint32_t *bpid;
+ const uint32_t *bpool_cfg;
+ struct dpa_bp *dpa_bp;
+
+ dev = &_of_dev->dev;
+
+ /* The default is one, if there's no property */
+ *count = 1;
+
+ /* Get the buffer pools to be used */
+ phandle_prop = of_get_property(dev->of_node,
+ "fsl,bman-buffer-pools", &lenp);
+
+ if (phandle_prop)
+ *count = lenp / sizeof(phandle);
+ else {
+ dev_err(dev,
+ "missing fsl,bman-buffer-pools device tree entry\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ dpa_bp = devm_kzalloc(dev, *count * sizeof(*dpa_bp), GFP_KERNEL);
+ if (unlikely(dpa_bp == NULL)) {
+ dev_err(dev, "devm_kzalloc() failed\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ dev_node = of_find_node_by_path("/");
+ if (unlikely(dev_node == NULL)) {
+ dev_err(dev, "of_find_node_by_path(/) failed\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ na = of_n_addr_cells(dev_node);
+ ns = of_n_size_cells(dev_node);
+
+ for (i = 0; i < *count && phandle_prop; i++) {
+ of_node_put(dev_node);
+ dev_node = of_find_node_by_phandle(phandle_prop[i]);
+ if (unlikely(dev_node == NULL)) {
+ dev_err(dev, "of_find_node_by_phandle() failed\n");
+ return ERR_PTR(-EFAULT);
+ }
+
+ if (unlikely(!of_device_is_compatible(dev_node, "fsl,bpool"))) {
+ dev_err(dev,
+ "!of_device_is_compatible(%s, fsl,bpool)\n",
+ dev_node->full_name);
+ dpa_bp = ERR_PTR(-EINVAL);
+ goto _return_of_node_put;
+ }
+
+ bpid = of_get_property(dev_node, "fsl,bpid", &lenp);
+ if ((bpid == NULL) || (lenp != sizeof(*bpid))) {
+ dev_err(dev, "fsl,bpid property not found.\n");
+ dpa_bp = ERR_PTR(-EINVAL);
+ goto _return_of_node_put;
+ }
+ dpa_bp[i].bpid = (uint8_t)*bpid;
+
+ bpool_cfg = of_get_property(dev_node, "fsl,bpool-ethernet-cfg",
+ &lenp);
+ if (bpool_cfg && (lenp == (2 * ns + na) * sizeof(*bpool_cfg))) {
+ const uint32_t *seed_pool;
+
+ dpa_bp[i].config_count =
+ (int)of_read_number(bpool_cfg, ns);
+ dpa_bp[i].size =
+ (size_t)of_read_number(bpool_cfg + ns, ns);
+ dpa_bp[i].paddr =
+ of_read_number(bpool_cfg + 2 * ns, na);
+
+ seed_pool = of_get_property(dev_node,
+ "fsl,bpool-ethernet-seeds", &lenp);
+ dpa_bp[i].seed_pool = !!seed_pool;
+
+ } else {
+ dev_err(dev,
+ "Missing/invalid fsl,bpool-ethernet-cfg device tree entry for node %s\n",
+ dev_node->full_name);
+ dpa_bp = ERR_PTR(-EINVAL);
+ goto _return_of_node_put;
+ }
+ }
+
+ sort(dpa_bp, *count, sizeof(*dpa_bp), dpa_bp_cmp, NULL);
+
+ return dpa_bp;
+
+_return_of_node_put:
+ if (dev_node)
+ of_node_put(dev_node);
+
+ return dpa_bp;
+}
+
+int dpa_bp_shared_port_seed(struct dpa_bp *bp)
+{
+ /* In MAC-less and Shared-MAC scenarios the physical
+ * address of the buffer pool in device tree is set
+ * to 0 to specify that another entity (USDPAA) will
+ * allocate and seed the buffers
+ */
+ if (!bp->paddr)
+ return 0;
+
+ /* allocate memory region for buffers */
+ devm_request_mem_region(bp->dev, bp->paddr,
+ bp->size * bp->config_count, KBUILD_MODNAME);
+ bp->vaddr = devm_ioremap_prot(bp->dev, bp->paddr,
+ bp->size * bp->config_count, 0);
+ if (bp->vaddr == NULL) {
+ pr_err("Could not map memory for pool %d\n", bp->bpid);
+ return -EIO;
+ }
+
+ /* seed pool with buffers from that memory region */
+ if (bp->seed_pool) {
+ int count = bp->target_count;
+ size_t addr = bp->paddr;
+
+ while (count) {
+ struct bm_buffer bufs[8];
+ uint8_t num_bufs = 0;
+
+ do {
+ BUG_ON(addr > 0xffffffffffffull);
+ bufs[num_bufs].bpid = bp->bpid;
+ bm_buffer_set64(&bufs[num_bufs++], addr);
+ addr += bp->size;
+
+ } while (--count && (num_bufs < 8));
+
+ while (bman_release(bp->pool, bufs, num_bufs, 0))
+ cpu_relax();
+ }
+ }
+
+ return 0;
+}
+
+int dpa_bp_create(struct net_device *net_dev, struct dpa_bp *dpa_bp,
+ size_t count)
+{
+ struct dpa_priv_s *priv = netdev_priv(net_dev);
+ int i;
+
+ priv->dpa_bp = dpa_bp;
+ priv->bp_count = count;
+
+ for (i = 0; i < count; i++) {
+ int err;
+ err = dpa_bp_alloc(&dpa_bp[i]);
+ if (err < 0) {
+ dpa_bp_free(priv, dpa_bp);
+ priv->dpa_bp = NULL;
+ return err;
+ }
+ }
+
+ return 0;
+}
+
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth_base.h b/drivers/net/ethernet/freescale/dpa/dpaa_eth_base.h
new file mode 100644
index 0000000..5b5ef1e
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth_base.h
@@ -0,0 +1,46 @@
+/* Copyright 2008-2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DPAA_ETH_BASE_H
+#define __DPAA_ETH_BASE_H
+
+#include <linux/etherdevice.h> /* struct net_device */
+#include <linux/fsl_bman.h> /* struct bm_buffer */
+#include <linux/of_platform.h> /* struct platform_device */
+#include <linux/net_tstamp.h> /* struct hwtstamp_config */
+
+struct dpa_bp * __cold __must_check /* __attribute__((nonnull)) */
+dpa_bp_probe(struct platform_device *_of_dev, size_t *count);
+int dpa_bp_create(struct net_device *net_dev, struct dpa_bp *dpa_bp,
+ size_t count);
+int dpa_bp_shared_port_seed(struct dpa_bp *bp);
+
+#endif /* __DPAA_ETH_BASE_H */
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth_common.c b/drivers/net/ethernet/freescale/dpa/dpaa_eth_common.c
new file mode 100644
index 0000000..5a899b7
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth_common.c
@@ -0,0 +1,1682 @@
+/* Copyright 2008-2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_net.h>
+#include <linux/etherdevice.h>
+#include <linux/kthread.h>
+#include <linux/percpu.h>
+#include <linux/highmem.h>
+#include <linux/sort.h>
+#include <linux/fsl_qman.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/if_vlan.h> /* vlan_eth_hdr */
+#include "dpaa_eth.h"
+#include "dpaa_eth_common.h"
+#ifdef CONFIG_FSL_DPAA_1588
+#include "dpaa_1588.h"
+#endif
+#include "mac.h"
+
+/* DPAA platforms benefit from hardware-assisted queue management */
+#ifdef CONFIG_AS_FASTPATH
+#define DPA_NETIF_FEATURES (NETIF_F_HW_QDISC | NETIF_F_HW_ACCEL_MQ)
+#else
+#define DPA_NETIF_FEATURES NETIF_F_HW_ACCEL_MQ
+#endif
+
+/* Size in bytes of the FQ taildrop threshold */
+#define DPA_FQ_TD 0x200000
+
+static struct dpa_bp *dpa_bp_array[64];
+
+int dpa_max_frm;
+int dpa_rx_extra_headroom;
+int dpa_num_cpus = NR_CPUS;
+
+static const struct fqid_cell tx_confirm_fqids[] = {
+ {0, DPAA_ETH_TX_QUEUES}
+};
+
+#ifdef CONFIG_FMAN_T4240
+static const struct fqid_cell tx_recycle_fqids[] = {
+ {0, DPAA_ETH_TX_QUEUES}
+};
+#endif
+
+static const struct fqid_cell default_fqids[][3] = {
+ [RX] = { {0, 1}, {0, 1}, {0, DPAA_ETH_RX_QUEUES} },
+ [TX] = { {0, 1}, {0, 1}, {0, DPAA_ETH_TX_QUEUES} }
+};
+
+static const char fsl_qman_frame_queues[][25] = {
+ [RX] = "fsl,qman-frame-queues-rx",
+ [TX] = "fsl,qman-frame-queues-tx"
+};
+#if defined(CONFIG_AS_FASTPATH) || defined(CONFIG_FSL_FMAN_TEST)
+/* A set of callbacks for hooking into the fastpath at different points. */
+struct dpaa_eth_hooks_s dpaa_eth_hooks;
+/* This function should only be called on the probe paths, since it makes no
+ * effort to guarantee consistency of the destination hooks structure.
+ */
+void fsl_dpaa_eth_set_hooks(struct dpaa_eth_hooks_s *hooks)
+{
+ if (hooks)
+ dpaa_eth_hooks = *hooks;
+ else
+ pr_err("NULL pointer to hooks!\n");
+}
+EXPORT_SYMBOL(fsl_dpaa_eth_set_hooks);
+#endif
+
+int dpa_netdev_init(struct device_node *dpa_node,
+ struct net_device *net_dev,
+ const uint8_t *mac_addr,
+ uint16_t tx_timeout)
+{
+ int err;
+ struct dpa_priv_s *priv = netdev_priv(net_dev);
+ struct device *dev = net_dev->dev.parent;
+
+ net_dev->hw_features |= DPA_NETIF_FEATURES;
+
+ net_dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
+
+ net_dev->features |= net_dev->hw_features;
+ net_dev->vlan_features = net_dev->features;
+
+ memcpy(net_dev->perm_addr, mac_addr, net_dev->addr_len);
+ memcpy(net_dev->dev_addr, mac_addr, net_dev->addr_len);
+
+ SET_ETHTOOL_OPS(net_dev, &dpa_ethtool_ops);
+
+ net_dev->needed_headroom = priv->tx_headroom;
+ net_dev->watchdog_timeo = msecs_to_jiffies(tx_timeout);
+
+ err = register_netdev(net_dev);
+ if (err < 0) {
+ dev_err(dev, "register_netdev() = %d\n", err);
+ return err;
+ }
+
+#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS
+ /* create debugfs entry for this net_device */
+ err = dpa_netdev_debugfs_create(net_dev);
+ if (err) {
+ unregister_netdev(net_dev);
+ return err;
+ }
+#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */
+
+ return 0;
+}
+
+int __cold dpa_start(struct net_device *net_dev)
+{
+ int err, i;
+ struct dpa_priv_s *priv;
+ struct mac_device *mac_dev;
+
+ priv = netdev_priv(net_dev);
+ mac_dev = priv->mac_dev;
+
+ err = mac_dev->init_phy(net_dev, priv->mac_dev);
+ if (err < 0) {
+ if (netif_msg_ifup(priv))
+ netdev_err(net_dev, "init_phy() = %d\n", err);
+ return err;
+ }
+
+ for_each_port_device(i, mac_dev->port_dev) {
+ err = fm_port_enable(mac_dev->port_dev[i]);
+ if (err)
+ goto mac_start_failed;
+ }
+
+ err = priv->mac_dev->start(mac_dev);
+ if (err < 0) {
+ if (netif_msg_ifup(priv))
+ netdev_err(net_dev, "mac_dev->start() = %d\n", err);
+ goto mac_start_failed;
+ }
+
+ netif_tx_start_all_queues(net_dev);
+
+ return 0;
+
+mac_start_failed:
+ for_each_port_device(i, mac_dev->port_dev)
+ fm_port_disable(mac_dev->port_dev[i]);
+
+ return err;
+}
+
+int __cold dpa_stop(struct net_device *net_dev)
+{
+ int _errno, i, err;
+ struct dpa_priv_s *priv;
+ struct mac_device *mac_dev;
+
+ priv = netdev_priv(net_dev);
+ mac_dev = priv->mac_dev;
+
+ netif_tx_stop_all_queues(net_dev);
+ /* Allow the Fman (Tx) port to process in-flight frames before we
+ * try switching it off.
+ */
+ usleep_range(5000, 10000);
+
+ _errno = mac_dev->stop(mac_dev);
+ if (unlikely(_errno < 0))
+ if (netif_msg_ifdown(priv))
+ netdev_err(net_dev, "mac_dev->stop() = %d\n",
+ _errno);
+
+ for_each_port_device(i, mac_dev->port_dev) {
+ err = fm_port_disable(mac_dev->port_dev[i]);
+ _errno = err ? err : _errno;
+ }
+
+ if (mac_dev->phy_dev)
+ phy_disconnect(mac_dev->phy_dev);
+ mac_dev->phy_dev = NULL;
+
+ return _errno;
+}
+
+void __cold dpa_timeout(struct net_device *net_dev)
+{
+ const struct dpa_priv_s *priv;
+ struct dpa_percpu_priv_s *percpu_priv;
+
+ priv = netdev_priv(net_dev);
+ percpu_priv = __this_cpu_ptr(priv->percpu_priv);
+
+ if (netif_msg_timer(priv))
+ netdev_crit(net_dev, "Transmit timeout latency: %u ms\n",
+ jiffies_to_msecs(jiffies - net_dev->trans_start));
+
+ percpu_priv->stats.tx_errors++;
+}
+
+/* net_device */
+
+/**
+ * @param net_dev the device for which statistics are calculated
+ * @param stats the function fills this structure with the device's statistics
+ * @return the address of the structure containing the statistics
+ *
+ * Calculates the statistics for the given device by adding the statistics
+ * collected by each CPU.
+ */
+struct rtnl_link_stats64 * __cold
+dpa_get_stats64(struct net_device *net_dev,
+ struct rtnl_link_stats64 *stats)
+{
+ struct dpa_priv_s *priv = netdev_priv(net_dev);
+ u64 *cpustats;
+ u64 *netstats = (u64 *)stats;
+ int i, j;
+ struct dpa_percpu_priv_s *percpu_priv;
+ int numstats = sizeof(struct rtnl_link_stats64) / sizeof(u64);
+
+ for_each_possible_cpu(i) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+
+ cpustats = (u64 *)&percpu_priv->stats;
+
+ for (j = 0; j < numstats; j++)
+ netstats[j] += cpustats[j];
+ }
+
+ return stats;
+}
+
+int dpa_change_mtu(struct net_device *net_dev, int new_mtu)
+{
+ const int max_mtu = dpa_get_max_mtu();
+ const int min_mtu = dpa_get_min_mtu();
+
+ /* Make sure we don't exceed the Ethernet controller's MAXFRM */
+ if (new_mtu < min_mtu || new_mtu > max_mtu) {
+ netdev_err(net_dev, "Invalid L3 mtu %d (must be between %d and %d).\n",
+ new_mtu, min_mtu, max_mtu);
+ return -EINVAL;
+ }
+ net_dev->mtu = new_mtu;
+
+ return 0;
+}
+
+/* .ndo_init callback */
+int dpa_ndo_init(struct net_device *net_dev)
+{
+ /* If fsl_fm_max_frm is set to a higher value than the all-common 1500,
+ * we choose conservatively and let the user explicitly set a higher
+ * MTU via ifconfig. Otherwise, the user may end up with different MTUs
+ * in the same LAN.
+ * If on the other hand fsl_fm_max_frm has been chosen below 1500,
+ * start with the maximum allowed.
+ */
+ int init_mtu = min(dpa_get_max_mtu(), ETH_DATA_LEN);
+
+ pr_debug("Setting initial MTU on net device: %d\n", init_mtu);
+ net_dev->mtu = init_mtu;
+
+ return 0;
+}
+
+int dpa_set_features(struct net_device *dev, netdev_features_t features)
+{
+ /* Not much to do here for now */
+ dev->features = features;
+ return 0;
+}
+
+netdev_features_t dpa_fix_features(struct net_device *dev,
+ netdev_features_t features)
+{
+ netdev_features_t unsupported_features = 0;
+
+ /* In theory we should never be requested to enable features that
+ * we didn't set in netdev->features and netdev->hw_features at probe
+ * time, but double check just to be on the safe side.
+ * We don't support enabling Rx csum through ethtool yet
+ */
+ unsupported_features |= NETIF_F_RXCSUM;
+
+ features &= ~unsupported_features;
+
+ return features;
+}
+
+#ifdef CONFIG_FSL_DPAA_TS
+u64 dpa_get_timestamp_ns(const struct dpa_priv_s *priv, enum port_type rx_tx,
+ const void *data)
+{
+ u64 *ts, ns;
+
+ ts = fm_port_get_buffer_time_stamp(priv->mac_dev->port_dev[rx_tx],
+ data);
+
+ if (!ts || *ts == 0)
+ return 0;
+
+ /* multiple DPA_PTP_NOMINAL_FREQ_PERIOD_NS for case of non power of 2 */
+ ns = *ts << DPA_PTP_NOMINAL_FREQ_PERIOD_SHIFT;
+
+ return ns;
+}
+
+int dpa_get_ts(const struct dpa_priv_s *priv, enum port_type rx_tx,
+ struct skb_shared_hwtstamps *shhwtstamps, const void *data)
+{
+ u64 ns;
+
+ ns = dpa_get_timestamp_ns(priv, rx_tx, data);
+
+ if (ns == 0)
+ return -EINVAL;
+
+ memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+ shhwtstamps->hwtstamp = ns_to_ktime(ns);
+
+ return 0;
+}
+
+static void dpa_ts_tx_enable(struct net_device *dev)
+{
+ struct dpa_priv_s *priv = netdev_priv(dev);
+ struct mac_device *mac_dev = priv->mac_dev;
+
+ if (mac_dev->fm_rtc_enable)
+ mac_dev->fm_rtc_enable(get_fm_handle(dev));
+ if (mac_dev->ptp_enable)
+ mac_dev->ptp_enable(mac_dev->get_mac_handle(mac_dev));
+
+ priv->ts_tx_en = true;
+}
+
+static void dpa_ts_tx_disable(struct net_device *dev)
+{
+ struct dpa_priv_s *priv = netdev_priv(dev);
+
+#if 0
+/* the RTC might be needed by the Rx Ts, cannot disable here
+ * no separate ptp_disable API for Rx/Tx, cannot disable here
+ */
+ struct mac_device *mac_dev = priv->mac_dev;
+
+ if (mac_dev->fm_rtc_disable)
+ mac_dev->fm_rtc_disable(get_fm_handle(dev));
+
+ if (mac_dev->ptp_disable)
+ mac_dev->ptp_disable(mac_dev->get_mac_handle(mac_dev));
+#endif
+
+ priv->ts_tx_en = false;
+}
+
+static void dpa_ts_rx_enable(struct net_device *dev)
+{
+ struct dpa_priv_s *priv = netdev_priv(dev);
+ struct mac_device *mac_dev = priv->mac_dev;
+
+ if (mac_dev->fm_rtc_enable)
+ mac_dev->fm_rtc_enable(get_fm_handle(dev));
+ if (mac_dev->ptp_enable)
+ mac_dev->ptp_enable(mac_dev->get_mac_handle(mac_dev));
+
+ priv->ts_rx_en = true;
+}
+
+static void dpa_ts_rx_disable(struct net_device *dev)
+{
+ struct dpa_priv_s *priv = netdev_priv(dev);
+
+#if 0
+/* the RTC might be needed by the Tx Ts, cannot disable here
+ * no separate ptp_disable API for Rx/Tx, cannot disable here
+ */
+ struct mac_device *mac_dev = priv->mac_dev;
+
+ if (mac_dev->fm_rtc_disable)
+ mac_dev->fm_rtc_disable(get_fm_handle(dev));
+
+ if (mac_dev->ptp_disable)
+ mac_dev->ptp_disable(mac_dev->get_mac_handle(mac_dev));
+#endif
+
+ priv->ts_rx_en = false;
+}
+
+static int dpa_ts_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ struct hwtstamp_config config;
+
+ if (copy_from_user(&config, rq->ifr_data, sizeof(config)))
+ return -EFAULT;
+
+ switch (config.tx_type) {
+ case HWTSTAMP_TX_OFF:
+ dpa_ts_tx_disable(dev);
+ break;
+ case HWTSTAMP_TX_ON:
+ dpa_ts_tx_enable(dev);
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ if (config.rx_filter == HWTSTAMP_FILTER_NONE)
+ dpa_ts_rx_disable(dev);
+ else {
+ dpa_ts_rx_enable(dev);
+ /* TS is set for all frame types, not only those requested */
+ config.rx_filter = HWTSTAMP_FILTER_ALL;
+ }
+
+ return copy_to_user(rq->ifr_data, &config, sizeof(config)) ?
+ -EFAULT : 0;
+}
+#endif /* CONFIG_FSL_DPAA_TS */
+
+int dpa_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+#ifdef CONFIG_FSL_DPAA_1588
+ struct dpa_priv_s *priv = netdev_priv(dev);
+#endif
+ int ret = 0;
+
+ /* at least one timestamping feature must be enabled */
+#ifdef CONFIG_FSL_DPAA_TS
+ if (!netif_running(dev))
+#endif
+ return -EINVAL;
+
+#ifdef CONFIG_FSL_DPAA_TS
+ if (cmd == SIOCSHWTSTAMP)
+ return dpa_ts_ioctl(dev, rq, cmd);
+#endif /* CONFIG_FSL_DPAA_TS */
+
+#ifdef CONFIG_FSL_DPAA_1588
+ if ((cmd >= PTP_ENBL_TXTS_IOCTL) && (cmd <= PTP_CLEANUP_TS)) {
+ if (priv->tsu && priv->tsu->valid)
+ ret = dpa_ioctl_1588(dev, rq, cmd);
+ else
+ ret = -ENODEV;
+ }
+#endif
+
+ return ret;
+}
+
+int __cold dpa_remove(struct platform_device *of_dev)
+{
+ int err;
+ struct device *dev;
+ struct net_device *net_dev;
+ struct dpa_priv_s *priv;
+
+ dev = &of_dev->dev;
+ net_dev = dev_get_drvdata(dev);
+
+ priv = netdev_priv(net_dev);
+
+ dpaa_eth_sysfs_remove(dev);
+
+ dev_set_drvdata(dev, NULL);
+ unregister_netdev(net_dev);
+
+ err = dpa_fq_free(dev, &priv->dpa_fq_list);
+
+ dpa_private_napi_del(net_dev);
+ free_percpu(priv->percpu_priv);
+
+ dpa_bp_free(priv, priv->dpa_bp);
+ devm_kfree(dev, priv->dpa_bp);
+
+ if (priv->buf_layout)
+ devm_kfree(dev, priv->buf_layout);
+
+#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS
+ /* remove debugfs entry for this net_device */
+ dpa_netdev_debugfs_remove(net_dev);
+#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */
+
+#ifdef CONFIG_FSL_DPAA_1588
+ if (priv->tsu && priv->tsu->valid)
+ dpa_ptp_cleanup(priv);
+#endif
+
+ free_netdev(net_dev);
+
+ return err;
+}
+
+struct mac_device * __cold __must_check
+__attribute__((nonnull))
+dpa_mac_probe(struct platform_device *_of_dev)
+{
+ struct device *dpa_dev, *dev;
+ struct device_node *mac_node;
+ int lenp;
+ const phandle *phandle_prop;
+ struct platform_device *of_dev;
+ struct mac_device *mac_dev;
+#ifdef CONFIG_FSL_DPAA_1588
+ struct net_device *net_dev = NULL;
+ struct dpa_priv_s *priv = NULL;
+ struct device_node *timer_node;
+#endif
+
+ phandle_prop = of_get_property(_of_dev->dev.of_node,
+ "fsl,fman-mac", &lenp);
+ if (phandle_prop == NULL)
+ return NULL;
+
+ BUG_ON(lenp != sizeof(phandle));
+
+ dpa_dev = &_of_dev->dev;
+
+ mac_node = of_find_node_by_phandle(*phandle_prop);
+ if (unlikely(mac_node == NULL)) {
+ dev_err(dpa_dev, "of_find_node_by_phandle() failed\n");
+ return ERR_PTR(-EFAULT);
+ }
+
+ of_dev = of_find_device_by_node(mac_node);
+ if (unlikely(of_dev == NULL)) {
+ dev_err(dpa_dev, "of_find_device_by_node(%s) failed\n",
+ mac_node->full_name);
+ of_node_put(mac_node);
+ return ERR_PTR(-EINVAL);
+ }
+ of_node_put(mac_node);
+
+ dev = &of_dev->dev;
+
+ mac_dev = dev_get_drvdata(dev);
+ if (unlikely(mac_dev == NULL)) {
+ dev_err(dpa_dev, "dev_get_drvdata(%s) failed\n",
+ dev_name(dev));
+ return ERR_PTR(-EINVAL);
+ }
+
+#ifdef CONFIG_FSL_DPAA_1588
+ phandle_prop = of_get_property(mac_node, "ptimer-handle", &lenp);
+ if (phandle_prop && ((mac_dev->phy_if != PHY_INTERFACE_MODE_SGMII) ||
+ ((mac_dev->phy_if == PHY_INTERFACE_MODE_SGMII) &&
+ (mac_dev->speed == SPEED_1000)))) {
+ timer_node = of_find_node_by_phandle(*phandle_prop);
+ if (timer_node)
+ net_dev = dev_get_drvdata(dpa_dev);
+ if (timer_node && net_dev) {
+ priv = netdev_priv(net_dev);
+ if (!dpa_ptp_init(priv))
+ dev_info(dev, "%s: ptp 1588 is initialized.\n",
+ mac_node->full_name);
+ }
+ }
+#endif
+
+ return mac_dev;
+}
+
+int dpa_set_mac_address(struct net_device *net_dev, void *addr)
+{
+ const struct dpa_priv_s *priv;
+ int _errno;
+ struct mac_device *mac_dev;
+
+ priv = netdev_priv(net_dev);
+
+ _errno = eth_mac_addr(net_dev, addr);
+ if (_errno < 0) {
+ if (netif_msg_drv(priv))
+ netdev_err(net_dev,
+ "eth_mac_addr() = %d\n",
+ _errno);
+ return _errno;
+ }
+
+ mac_dev = priv->mac_dev;
+
+ _errno = mac_dev->change_addr(mac_dev->get_mac_handle(mac_dev),
+ net_dev->dev_addr);
+ if (_errno < 0) {
+ if (netif_msg_drv(priv))
+ netdev_err(net_dev,
+ "mac_dev->change_addr() = %d\n",
+ _errno);
+ return _errno;
+ }
+
+ return 0;
+}
+
+void dpa_set_rx_mode(struct net_device *net_dev)
+{
+ int _errno;
+ const struct dpa_priv_s *priv;
+
+ priv = netdev_priv(net_dev);
+
+ if (!!(net_dev->flags & IFF_PROMISC) != priv->mac_dev->promisc) {
+ priv->mac_dev->promisc = !priv->mac_dev->promisc;
+ _errno = priv->mac_dev->set_promisc(
+ priv->mac_dev->get_mac_handle(priv->mac_dev),
+ priv->mac_dev->promisc);
+ if (unlikely(_errno < 0) && netif_msg_drv(priv))
+ netdev_err(net_dev,
+ "mac_dev->set_promisc() = %d\n",
+ _errno);
+ }
+
+ _errno = priv->mac_dev->set_multi(net_dev, priv->mac_dev);
+ if (unlikely(_errno < 0) && netif_msg_drv(priv))
+ netdev_err(net_dev, "mac_dev->set_multi() = %d\n", _errno);
+}
+
+void dpa_set_buffers_layout(struct mac_device *mac_dev,
+ struct dpa_buffer_layout_s *layout)
+{
+ struct fm_port_params params;
+
+ /* Rx */
+ layout[RX].priv_data_size = (uint16_t)DPA_RX_PRIV_DATA_SIZE;
+ layout[RX].parse_results = true;
+ layout[RX].hash_results = true;
+#ifdef CONFIG_FSL_DPAA_TS
+ layout[RX].time_stamp = true;
+#endif
+ fm_port_get_buff_layout_ext_params(mac_dev->port_dev[RX], &params);
+ layout[RX].manip_extra_space = params.manip_extra_space;
+ /* a value of zero for data alignment means "don't care", so align to
+ * a non-zero value to prevent FMD from using its own default
+ */
+ layout[RX].data_align = params.data_align ? : DPA_FD_DATA_ALIGNMENT;
+
+ /* Tx */
+ layout[TX].priv_data_size = DPA_TX_PRIV_DATA_SIZE;
+ layout[TX].parse_results = true;
+ layout[TX].hash_results = true;
+#ifdef CONFIG_FSL_DPAA_TS
+ layout[TX].time_stamp = true;
+#endif
+ fm_port_get_buff_layout_ext_params(mac_dev->port_dev[TX], &params);
+ layout[TX].manip_extra_space = params.manip_extra_space;
+ layout[TX].data_align = params.data_align ? : DPA_FD_DATA_ALIGNMENT;
+}
+
+int __attribute__((nonnull))
+dpa_bp_alloc(struct dpa_bp *dpa_bp)
+{
+ int err;
+ struct bman_pool_params bp_params;
+ struct platform_device *pdev;
+
+ if (dpa_bp->size == 0 || dpa_bp->config_count == 0) {
+ pr_err("Buffer pool is not properly initialized! Missing size or initial number of buffers");
+ return -EINVAL;
+ }
+
+ memset(&bp_params, 0, sizeof(struct bman_pool_params));
+#ifdef CONFIG_FMAN_PFC
+ bp_params.flags = BMAN_POOL_FLAG_THRESH;
+ bp_params.thresholds[0] = bp_params.thresholds[2] =
+ CONFIG_FSL_DPAA_ETH_REFILL_THRESHOLD;
+ bp_params.thresholds[1] = bp_params.thresholds[3] =
+ CONFIG_FSL_DPAA_ETH_MAX_BUF_COUNT;
+#endif
+
+ /* If the pool is already specified, we only create one per bpid */
+ if (dpa_bpid2pool_use(dpa_bp->bpid))
+ return 0;
+
+ if (dpa_bp->bpid == 0)
+ bp_params.flags |= BMAN_POOL_FLAG_DYNAMIC_BPID;
+ else
+ bp_params.bpid = dpa_bp->bpid;
+
+ dpa_bp->pool = bman_new_pool(&bp_params);
+ if (unlikely(dpa_bp->pool == NULL)) {
+ pr_err("bman_new_pool() failed\n");
+ return -ENODEV;
+ }
+
+ dpa_bp->bpid = (uint8_t)bman_get_params(dpa_bp->pool)->bpid;
+
+ pdev = platform_device_register_simple("dpaa_eth_bpool",
+ dpa_bp->bpid, NULL, 0);
+ if (IS_ERR(pdev)) {
+ err = PTR_ERR(pdev);
+ goto pdev_register_failed;
+ }
+
+ err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(40));
+ if (err)
+ goto pdev_mask_failed;
+
+ dpa_bp->dev = &pdev->dev;
+
+ if (dpa_bp->seed_cb) {
+ err = dpa_bp->seed_cb(dpa_bp);
+ if (err)
+ goto pool_seed_failed;
+ }
+
+ dpa_bpid2pool_map(dpa_bp->bpid, dpa_bp);
+
+ return 0;
+
+pool_seed_failed:
+pdev_mask_failed:
+ platform_device_unregister(pdev);
+pdev_register_failed:
+ bman_free_pool(dpa_bp->pool);
+
+ return err;
+}
+
+void dpa_bp_drain(struct dpa_bp *bp)
+{
+ int ret, num = 8;
+
+ do {
+ struct bm_buffer bmb[8];
+ int i;
+
+ ret = bman_acquire(bp->pool, bmb, 8, 0);
+ if (ret < 0) {
+ if (num == 8) {
+ /* we have less than 8 buffers left;
+ * drain them one by one
+ */
+ num = 1;
+ continue;
+ } else {
+ /* Pool is fully drained */
+ break;
+ }
+ }
+
+ for (i = 0; i < num; i++) {
+ dma_addr_t addr = bm_buf_addr(&bmb[i]);
+
+ dma_unmap_single(bp->dev, addr, bp->size,
+ DMA_BIDIRECTIONAL);
+
+ bp->free_buf_cb(phys_to_virt(addr));
+ }
+ } while (ret > 0);
+}
+
+static void __cold __attribute__((nonnull))
+_dpa_bp_free(struct dpa_bp *dpa_bp)
+{
+ struct dpa_bp *bp = dpa_bpid2pool(dpa_bp->bpid);
+
+ /* the mapping between bpid and dpa_bp is done very late in the
+ * allocation procedure; if something failed before the mapping, the bp
+ * was not configured, therefore we don't need the below instructions
+ */
+ if (!bp)
+ return;
+
+ if (!atomic_dec_and_test(&bp->refs))
+ return;
+
+ if (bp->free_buf_cb)
+ dpa_bp_drain(bp);
+
+ dpa_bp_array[bp->bpid] = NULL;
+ bman_free_pool(bp->pool);
+
+ if (bp->dev)
+ platform_device_unregister(to_platform_device(bp->dev));
+}
+
+void __cold __attribute__((nonnull))
+dpa_bp_free(struct dpa_priv_s *priv, struct dpa_bp *dpa_bp)
+{
+ int i;
+
+ for (i = 0; i < priv->bp_count; i++)
+ _dpa_bp_free(&priv->dpa_bp[i]);
+}
+
+struct dpa_bp *dpa_bpid2pool(int bpid)
+{
+ return dpa_bp_array[bpid];
+}
+
+void dpa_bpid2pool_map(int bpid, struct dpa_bp *dpa_bp)
+{
+ dpa_bp_array[bpid] = dpa_bp;
+ atomic_set(&dpa_bp->refs, 1);
+}
+
+bool dpa_bpid2pool_use(int bpid)
+{
+ if (dpa_bpid2pool(bpid)) {
+ atomic_inc(&dpa_bp_array[bpid]->refs);
+ return true;
+ }
+
+ return false;
+}
+
+#ifdef CONFIG_FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE
+u16 dpa_select_queue(struct net_device *net_dev, struct sk_buff *skb)
+{
+ return dpa_get_queue_mapping(skb);
+}
+#endif
+
+struct dpa_fq *dpa_fq_alloc(struct device *dev,
+ const struct fqid_cell *fqids,
+ struct list_head *list,
+ enum dpa_fq_type fq_type)
+{
+ int i;
+ struct dpa_fq *dpa_fq;
+
+ dpa_fq = devm_kzalloc(dev, sizeof(*dpa_fq) * fqids->count, GFP_KERNEL);
+ if (dpa_fq == NULL)
+ return NULL;
+
+ for (i = 0; i < fqids->count; i++) {
+ dpa_fq[i].fq_type = fq_type;
+ dpa_fq[i].fqid = fqids->start ? fqids->start + i : 0;
+ list_add_tail(&dpa_fq[i].list, list);
+ }
+
+#ifdef CONFIG_FMAN_PFC
+ if (fq_type == FQ_TYPE_TX ||
+ fq_type == FQ_TYPE_TX_RECYCLE)
+ for (i = 0; i < fqids->count; i++)
+ dpa_fq[i].wq = i / dpa_num_cpus;
+ else
+#endif
+ for (i = 0; i < fqids->count; i++)
+ _dpa_assign_wq(dpa_fq + i);
+
+ return dpa_fq;
+}
+
+/* Probing of FQs for MACful ports */
+int dpa_fq_probe_mac(struct device *dev, struct list_head *list,
+ struct fm_port_fqs *port_fqs,
+ bool alloc_tx_conf_fqs,
+ enum port_type ptype)
+{
+ const struct fqid_cell *fqids;
+ struct dpa_fq *dpa_fq;
+ struct device_node *np = dev->of_node;
+ int num_ranges;
+ int i, lenp;
+
+ if (ptype == TX && alloc_tx_conf_fqs) {
+ if (!dpa_fq_alloc(dev, tx_confirm_fqids, list,
+ FQ_TYPE_TX_CONF_MQ))
+ goto fq_alloc_failed;
+
+#ifdef CONFIG_FMAN_T4240
+ /* per-core Tx queues for recyclable frames (FManv3 only) */
+ if (!dpa_fq_alloc(dev, tx_recycle_fqids, list,
+ FQ_TYPE_TX_RECYCLE))
+ goto fq_alloc_failed;
+#endif
+ }
+
+ fqids = of_get_property(np, fsl_qman_frame_queues[ptype], &lenp);
+ if (fqids == NULL) {
+ /* No dts definition, so use the defaults. */
+ fqids = default_fqids[ptype];
+ num_ranges = 3;
+ } else {
+ num_ranges = lenp / sizeof(*fqids);
+ }
+
+ for (i = 0; i < num_ranges; i++) {
+ switch (i) {
+ case 0:
+ /* The first queue is the error queue */
+ if (fqids[i].count != 1)
+ goto invalid_error_queue;
+
+ dpa_fq = dpa_fq_alloc(dev, &fqids[i], list,
+ ptype == RX ?
+ FQ_TYPE_RX_ERROR :
+ FQ_TYPE_TX_ERROR);
+ if (dpa_fq == NULL)
+ goto fq_alloc_failed;
+
+ if (ptype == RX)
+ port_fqs->rx_errq = &dpa_fq[0];
+ else
+ port_fqs->tx_errq = &dpa_fq[0];
+ break;
+ case 1:
+ /* the second queue is the default queue */
+ if (fqids[i].count != 1)
+ goto invalid_default_queue;
+
+ dpa_fq = dpa_fq_alloc(dev, &fqids[i], list,
+ ptype == RX ?
+ FQ_TYPE_RX_DEFAULT :
+ FQ_TYPE_TX_CONFIRM);
+ if (dpa_fq == NULL)
+ goto fq_alloc_failed;
+
+ if (ptype == RX)
+ port_fqs->rx_defq = &dpa_fq[0];
+ else
+ port_fqs->tx_defq = &dpa_fq[0];
+ break;
+ default:
+ /* all subsequent queues are either RX PCD or Tx */
+ if (!dpa_fq_alloc(dev, &fqids[i], list, ptype == RX ?
+ FQ_TYPE_RX_PCD : FQ_TYPE_TX))
+ goto fq_alloc_failed;
+ break;
+ }
+ }
+
+ return 0;
+
+fq_alloc_failed:
+ dev_err(dev, "dpa_fq_alloc() failed\n");
+ return -ENOMEM;
+
+invalid_default_queue:
+invalid_error_queue:
+ dev_err(dev, "Too many default or error queues\n");
+ return -EINVAL;
+}
+
+static u32 rx_pool_channel;
+static DEFINE_SPINLOCK(rx_pool_channel_init);
+
+int dpa_get_channel(void)
+{
+ spin_lock(&rx_pool_channel_init);
+ if (!rx_pool_channel) {
+ u32 pool;
+ int ret = qman_alloc_pool(&pool);
+ if (!ret)
+ rx_pool_channel = pool;
+ }
+ spin_unlock(&rx_pool_channel_init);
+ if (!rx_pool_channel)
+ return -ENOMEM;
+ return rx_pool_channel;
+}
+
+int dpaa_eth_add_channel(void *__arg)
+{
+ const cpumask_t *cpus = qman_affine_cpus();
+ u32 pool = QM_SDQCR_CHANNELS_POOL_CONV((u16)(unsigned long)__arg);
+ int cpu;
+ struct qman_portal *portal;
+
+ for_each_cpu(cpu, cpus) {
+ portal = (struct qman_portal *)qman_get_affine_portal(cpu);
+ qman_p_static_dequeue_add(portal, pool);
+ }
+ return 0;
+}
+
+/**
+ * Congestion group state change notification callback.
+ * Stops the device's egress queues while they are congested and
+ * wakes them upon exiting congested state.
+ * Also updates some CGR-related stats.
+ */
+static void dpaa_eth_cgscn(struct qman_portal *qm, struct qman_cgr *cgr,
+ int congested)
+{
+ struct dpa_priv_s *priv = (struct dpa_priv_s *)container_of(cgr,
+ struct dpa_priv_s, cgr_data.cgr);
+
+ if (congested) {
+ priv->cgr_data.congestion_start_jiffies = jiffies;
+ netif_tx_stop_all_queues(priv->net_dev);
+ priv->cgr_data.cgr_congested_count++;
+ } else {
+ priv->cgr_data.congested_jiffies +=
+ (jiffies - priv->cgr_data.congestion_start_jiffies);
+ netif_tx_wake_all_queues(priv->net_dev);
+ }
+}
+
+int dpaa_eth_cgr_init(struct dpa_priv_s *priv)
+{
+ struct qm_mcc_initcgr initcgr;
+ u32 cs_th;
+ int err;
+
+ err = qman_alloc_cgrid(&priv->cgr_data.cgr.cgrid);
+ if (err < 0) {
+ pr_err("Error %d allocating CGR ID\n", err);
+ goto out_error;
+ }
+ priv->cgr_data.cgr.cb = dpaa_eth_cgscn;
+
+ /* Enable Congestion State Change Notifications and CS taildrop */
+ initcgr.we_mask = QM_CGR_WE_CSCN_EN | QM_CGR_WE_CS_THRES;
+ initcgr.cgr.cscn_en = QM_CGR_EN;
+
+ /* Set different thresholds based on the MAC speed.
+ * TODO: this may turn suboptimal if the MAC is reconfigured at a speed
+ * lower than its max, e.g. if a dTSEC later negotiates a 100Mbps link.
+ * In such cases, we ought to reconfigure the threshold, too.
+ */
+ if (priv->mac_dev->if_support & SUPPORTED_10000baseT_Full)
+ cs_th = CONFIG_FSL_DPAA_CS_THRESHOLD_10G;
+ else
+ cs_th = CONFIG_FSL_DPAA_CS_THRESHOLD_1G;
+ qm_cgr_cs_thres_set64(&initcgr.cgr.cs_thres, cs_th, 1);
+
+ initcgr.we_mask |= QM_CGR_WE_CSTD_EN;
+ initcgr.cgr.cstd_en = QM_CGR_EN;
+
+ err = qman_create_cgr(&priv->cgr_data.cgr, QMAN_CGR_FLAG_USE_INIT,
+ &initcgr);
+ if (err < 0) {
+ pr_err("Error %d creating CGR with ID %d\n", err,
+ priv->cgr_data.cgr.cgrid);
+ qman_release_cgrid(priv->cgr_data.cgr.cgrid);
+ goto out_error;
+ }
+ pr_debug("Created CGR %d for netdev with hwaddr %pM on QMan channel %d\n",
+ priv->cgr_data.cgr.cgrid, priv->mac_dev->addr,
+ priv->cgr_data.cgr.chan);
+
+out_error:
+ return err;
+}
+
+static inline void dpa_setup_ingress(const struct dpa_priv_s *priv,
+ struct dpa_fq *fq,
+ const struct qman_fq *template)
+{
+ fq->fq_base = *template;
+ fq->net_dev = priv->net_dev;
+
+ fq->flags = QMAN_FQ_FLAG_NO_ENQUEUE;
+ fq->channel = priv->channel;
+}
+
+static inline void dpa_setup_egress(const struct dpa_priv_s *priv,
+ struct dpa_fq *fq,
+ struct fm_port *port,
+ const struct qman_fq *template)
+{
+ fq->fq_base = *template;
+ fq->net_dev = priv->net_dev;
+
+ if (port) {
+ fq->flags = QMAN_FQ_FLAG_TO_DCPORTAL;
+ fq->channel = (uint16_t)fm_get_tx_port_channel(port);
+ } else {
+ fq->flags = QMAN_FQ_FLAG_NO_MODIFY;
+ }
+}
+
+void dpa_fq_setup(struct dpa_priv_s *priv, const struct dpa_fq_cbs_t *fq_cbs,
+ struct fm_port *tx_port)
+{
+ struct dpa_fq *fq;
+ uint16_t portals[NR_CPUS];
+ int cpu, portal_cnt = 0, num_portals = 0;
+ uint32_t pcd_fqid;
+ const cpumask_t *affine_cpus = qman_affine_cpus();
+ int egress_cnt = 0, conf_cnt = 0;
+#ifdef CONFIG_FMAN_T4240
+ int recycle_cnt = 0;
+#endif
+
+ /* Prepare for PCD FQs init */
+ for_each_cpu(cpu, affine_cpus)
+ portals[num_portals++] = qman_affine_channel(cpu);
+ if (num_portals == 0)
+ dev_err(priv->net_dev->dev.parent,
+ "No Qman software (affine) channels found");
+
+ pcd_fqid = (priv->mac_dev) ?
+ DPAA_ETH_PCD_FQ_BASE(priv->mac_dev->res->start) : 0;
+
+ /* Initialize each FQ in the list */
+ list_for_each_entry(fq, &priv->dpa_fq_list, list) {
+ switch (fq->fq_type) {
+ case FQ_TYPE_RX_DEFAULT:
+ BUG_ON(!priv->mac_dev);
+ dpa_setup_ingress(priv, fq, &fq_cbs->rx_defq);
+ break;
+ case FQ_TYPE_RX_ERROR:
+ BUG_ON(!priv->mac_dev);
+ dpa_setup_ingress(priv, fq, &fq_cbs->rx_errq);
+ break;
+ case FQ_TYPE_RX_PCD:
+ /* For MACless we can't have dynamic Rx queues */
+ BUG_ON(!priv->mac_dev && !fq->fqid);
+ dpa_setup_ingress(priv, fq, &fq_cbs->rx_defq);
+ if (!fq->fqid)
+ fq->fqid = pcd_fqid++;
+ fq->channel = portals[portal_cnt];
+ portal_cnt = (portal_cnt + 1) % num_portals;
+ break;
+ case FQ_TYPE_TX:
+ dpa_setup_egress(priv, fq, tx_port,
+ &fq_cbs->egress_ern);
+ /* If we have more Tx queues than the number of cores,
+ * just ignore the extra ones.
+ */
+ if (egress_cnt < DPAA_ETH_TX_QUEUES)
+ priv->egress_fqs[egress_cnt++] = &fq->fq_base;
+ break;
+ case FQ_TYPE_TX_CONFIRM:
+ BUG_ON(!priv->mac_dev);
+ dpa_setup_ingress(priv, fq, &fq_cbs->tx_defq);
+ break;
+ case FQ_TYPE_TX_CONF_MQ:
+ BUG_ON(!priv->mac_dev);
+ dpa_setup_ingress(priv, fq, &fq_cbs->tx_defq);
+ priv->conf_fqs[conf_cnt++] = &fq->fq_base;
+ break;
+ case FQ_TYPE_TX_ERROR:
+ BUG_ON(!priv->mac_dev);
+ dpa_setup_ingress(priv, fq, &fq_cbs->tx_errq);
+ break;
+#ifdef CONFIG_FMAN_T4240
+ case FQ_TYPE_TX_RECYCLE:
+ BUG_ON(!priv->mac_dev);
+ dpa_setup_egress(priv, fq, tx_port,
+ &fq_cbs->egress_ern);
+ priv->recycle_fqs[recycle_cnt++] = &fq->fq_base;
+ break;
+#endif
+ default:
+ dev_warn(priv->net_dev->dev.parent,
+ "Unknown FQ type detected!\n");
+ break;
+ }
+ }
+
+ /* The number of Tx queues may be smaller than the number of cores, if
+ * the Tx queue range is specified in the device tree instead of being
+ * dynamically allocated.
+ * Make sure all CPUs receive a corresponding Tx queue.
+ */
+ while (egress_cnt < DPAA_ETH_TX_QUEUES) {
+ list_for_each_entry(fq, &priv->dpa_fq_list, list) {
+ if (fq->fq_type != FQ_TYPE_TX)
+ continue;
+ priv->egress_fqs[egress_cnt++] = &fq->fq_base;
+ if (egress_cnt == DPAA_ETH_TX_QUEUES)
+ break;
+ }
+ }
+}
+
+static struct qman_fq *_dpa_get_tx_conf_queue(const struct dpa_priv_s *priv,
+ struct qman_fq *tx_fq)
+{
+ int i;
+
+ for (i = 0; i < DPAA_ETH_TX_QUEUES; i++)
+ if (priv->egress_fqs[i] == tx_fq)
+ return priv->conf_fqs[i];
+
+ return NULL;
+}
+
+int dpa_fq_init(struct dpa_fq *dpa_fq, bool td_enable)
+{
+ int _errno;
+ const struct dpa_priv_s *priv;
+ struct device *dev;
+ struct qman_fq *fq;
+ struct qm_mcc_initfq initfq;
+ struct qman_fq *confq;
+
+ priv = netdev_priv(dpa_fq->net_dev);
+ dev = dpa_fq->net_dev->dev.parent;
+
+ if (dpa_fq->fqid == 0)
+ dpa_fq->flags |= QMAN_FQ_FLAG_DYNAMIC_FQID;
+
+ dpa_fq->init = !(dpa_fq->flags & QMAN_FQ_FLAG_NO_MODIFY);
+
+ _errno = qman_create_fq(dpa_fq->fqid, dpa_fq->flags, &dpa_fq->fq_base);
+ if (_errno) {
+ dev_err(dev, "qman_create_fq() failed\n");
+ return _errno;
+ }
+ fq = &dpa_fq->fq_base;
+
+ if (dpa_fq->init) {
+ initfq.we_mask = QM_INITFQ_WE_FQCTRL;
+ /* FIXME: why would we want to keep an empty FQ in cache? */
+ initfq.fqd.fq_ctrl = QM_FQCTRL_PREFERINCACHE;
+
+ /* Try to reduce the number of portal interrupts for
+ * Tx Confirmation FQs.
+ */
+ if (dpa_fq->fq_type == FQ_TYPE_TX_CONFIRM)
+ initfq.fqd.fq_ctrl |= QM_FQCTRL_HOLDACTIVE;
+
+ /* FQ placement */
+ initfq.we_mask |= QM_INITFQ_WE_DESTWQ;
+
+ initfq.fqd.dest.channel = dpa_fq->channel;
+ initfq.fqd.dest.wq = dpa_fq->wq;
+
+ /* Put all egress queues in a congestion group of their own.
+ * Sensu stricto, the Tx confirmation queues are Rx FQs,
+ * rather than Tx - but they nonetheless account for the
+ * memory footprint on behalf of egress traffic. We therefore
+ * place them in the netdev's CGR, along with the Tx FQs.
+ */
+ if (dpa_fq->fq_type == FQ_TYPE_TX ||
+ dpa_fq->fq_type == FQ_TYPE_TX_CONFIRM ||
+ dpa_fq->fq_type == FQ_TYPE_TX_CONF_MQ) {
+ initfq.we_mask |= QM_INITFQ_WE_CGID;
+ initfq.fqd.fq_ctrl |= QM_FQCTRL_CGE;
+ initfq.fqd.cgid = priv->cgr_data.cgr.cgrid;
+ /* Set a fixed overhead accounting, in an attempt to
+ * reduce the impact of fixed-size skb shells and the
+ * driver's needed headroom on system memory. This is
+ * especially the case when the egress traffic is
+ * composed of small datagrams.
+ * Unfortunately, QMan's OAL value is capped to an
+ * insufficient value, but even that is better than
+ * no overhead accounting at all.
+ */
+ initfq.we_mask |= QM_INITFQ_WE_OAC;
+ initfq.fqd.oac_init.oac = QM_OAC_CG;
+ initfq.fqd.oac_init.oal =
+ (signed char)(min(sizeof(struct sk_buff) +
+ priv->tx_headroom, (size_t)FSL_QMAN_MAX_OAL));
+ }
+
+ if (td_enable) {
+ initfq.we_mask |= QM_INITFQ_WE_TDTHRESH;
+ qm_fqd_taildrop_set(&initfq.fqd.td,
+ DPA_FQ_TD, 1);
+ initfq.fqd.fq_ctrl = QM_FQCTRL_TDE;
+ }
+
+ /* Configure the Tx confirmation queue, now that we know
+ * which Tx queue it pairs with.
+ */
+ if (dpa_fq->fq_type == FQ_TYPE_TX) {
+ confq = _dpa_get_tx_conf_queue(priv, &dpa_fq->fq_base);
+ if (confq) {
+ initfq.we_mask |= QM_INITFQ_WE_CONTEXTA |
+ QM_INITFQ_WE_CONTEXTB;
+ /* CTXA[OVFQ] = 1 */
+ initfq.fqd.context_a.hi = 0x80000000;
+ initfq.fqd.context_a.lo = 0x0;
+ initfq.fqd.context_b = qman_fq_fqid(confq);
+ }
+ }
+
+#ifdef CONFIG_FMAN_T4240
+ /* Configure the Tx queues for recycled frames, such that the
+ * buffers are released by FMan and no confirmation is sent
+ */
+ if (dpa_fq->fq_type == FQ_TYPE_TX_RECYCLE) {
+ initfq.we_mask |= QM_INITFQ_WE_CONTEXTA |
+ QM_INITFQ_WE_CONTEXTB;
+ /* ContextA: OVFQ=1 (use ContextB FQID for confirmation)
+ * OVOM=1 (use contextA2 bits instead of ICAD)
+ * A2V=1 (contextA A2 field is valid)
+ * B0V=1 (contextB field is valid)
+ * ContextA A2: EBD=1 (deallocate buffers inside FMan)
+ * ContextB: Confirmation FQID = 0
+ */
+ initfq.fqd.context_a.hi = 0x96000000;
+ initfq.fqd.context_a.lo = 0x80000000;
+ initfq.fqd.context_b = 0;
+ }
+#endif
+
+ /* Put all *private* ingress queues in our "ingress CGR". */
+ if (priv->use_ingress_cgr &&
+ (dpa_fq->fq_type == FQ_TYPE_RX_DEFAULT ||
+ dpa_fq->fq_type == FQ_TYPE_RX_ERROR ||
+ dpa_fq->fq_type == FQ_TYPE_RX_PCD)) {
+ initfq.we_mask |= QM_INITFQ_WE_CGID;
+ initfq.fqd.fq_ctrl |= QM_FQCTRL_CGE;
+ initfq.fqd.cgid = priv->ingress_cgr.cgrid;
+ /* Set a fixed overhead accounting, just like for the
+ * egress CGR.
+ */
+ initfq.we_mask |= QM_INITFQ_WE_OAC;
+ initfq.fqd.oac_init.oac = QM_OAC_CG;
+ initfq.fqd.oac_init.oal =
+ (signed char)(min(sizeof(struct sk_buff) +
+ priv->tx_headroom, (size_t)FSL_QMAN_MAX_OAL));
+ }
+
+ /* Initialization common to all ingress queues */
+ if (dpa_fq->flags & QMAN_FQ_FLAG_NO_ENQUEUE) {
+ initfq.we_mask |= QM_INITFQ_WE_CONTEXTA;
+ initfq.fqd.fq_ctrl |=
+ QM_FQCTRL_CTXASTASHING | QM_FQCTRL_AVOIDBLOCK;
+ initfq.fqd.context_a.stashing.exclusive =
+ QM_STASHING_EXCL_DATA | QM_STASHING_EXCL_CTX |
+ QM_STASHING_EXCL_ANNOTATION;
+ initfq.fqd.context_a.stashing.data_cl = 2;
+ initfq.fqd.context_a.stashing.annotation_cl = 1;
+ initfq.fqd.context_a.stashing.context_cl =
+ DIV_ROUND_UP(sizeof(struct qman_fq), 64);
+ };
+
+ _errno = qman_init_fq(fq, QMAN_INITFQ_FLAG_SCHED, &initfq);
+ if (_errno < 0) {
+ dev_err(dev, "qman_init_fq(%u) = %d\n",
+ qman_fq_fqid(fq), _errno);
+ qman_destroy_fq(fq, 0);
+ return _errno;
+ }
+ }
+
+ dpa_fq->fqid = qman_fq_fqid(fq);
+
+ return 0;
+}
+
+static int __cold __attribute__((nonnull))
+_dpa_fq_free(struct device *dev, struct qman_fq *fq)
+{
+ int _errno, __errno;
+ struct dpa_fq *dpa_fq;
+ const struct dpa_priv_s *priv;
+
+ _errno = 0;
+
+ dpa_fq = container_of(fq, struct dpa_fq, fq_base);
+ priv = netdev_priv(dpa_fq->net_dev);
+
+ if (dpa_fq->init) {
+ _errno = qman_retire_fq(fq, NULL);
+ if (unlikely(_errno < 0) && netif_msg_drv(priv))
+ dev_err(dev, "qman_retire_fq(%u) = %d\n",
+ qman_fq_fqid(fq), _errno);
+
+ __errno = qman_oos_fq(fq);
+ if (unlikely(__errno < 0) && netif_msg_drv(priv)) {
+ dev_err(dev, "qman_oos_fq(%u) = %d\n",
+ qman_fq_fqid(fq), __errno);
+ if (_errno >= 0)
+ _errno = __errno;
+ }
+ }
+
+ qman_destroy_fq(fq, 0);
+ list_del(&dpa_fq->list);
+
+ return _errno;
+}
+
+int __cold __attribute__((nonnull))
+dpa_fq_free(struct device *dev, struct list_head *list)
+{
+ int _errno, __errno;
+ struct dpa_fq *dpa_fq, *tmp;
+
+ _errno = 0;
+ list_for_each_entry_safe(dpa_fq, tmp, list, list) {
+ __errno = _dpa_fq_free(dev, (struct qman_fq *)dpa_fq);
+ if (unlikely(__errno < 0) && _errno >= 0)
+ _errno = __errno;
+ }
+
+ return _errno;
+}
+
+static void
+dpaa_eth_init_tx_port(struct fm_port *port, struct dpa_fq *errq,
+ struct dpa_fq *defq, struct dpa_buffer_layout_s *buf_layout)
+{
+ struct fm_port_params tx_port_param;
+ bool frag_enabled = false;
+
+ memset(&tx_port_param, 0, sizeof(tx_port_param));
+ dpaa_eth_init_port(tx, port, tx_port_param, errq->fqid, defq->fqid,
+ buf_layout, frag_enabled);
+}
+
+static void
+dpaa_eth_init_rx_port(struct fm_port *port, struct dpa_bp *bp, size_t count,
+ struct dpa_fq *errq, struct dpa_fq *defq,
+ struct dpa_buffer_layout_s *buf_layout)
+{
+ struct fm_port_params rx_port_param;
+ int i;
+ bool frag_enabled = false;
+
+ memset(&rx_port_param, 0, sizeof(rx_port_param));
+ count = min(ARRAY_SIZE(rx_port_param.pool_param), count);
+ rx_port_param.num_pools = (uint8_t)count;
+ for (i = 0; i < count; i++) {
+ if (i >= rx_port_param.num_pools)
+ break;
+ rx_port_param.pool_param[i].id = bp[i].bpid;
+ rx_port_param.pool_param[i].size = (uint16_t)bp[i].size;
+ }
+
+ dpaa_eth_init_port(rx, port, rx_port_param, errq->fqid, defq->fqid,
+ buf_layout, frag_enabled);
+}
+
+#if defined(CONFIG_FSL_FMAN_TEST)
+/* Defined as weak, to be implemented by fman pcd tester. */
+int dpa_alloc_pcd_fqids(struct device *, uint32_t, uint8_t, uint32_t *)
+__attribute__((weak));
+
+int dpa_free_pcd_fqids(struct device *, uint32_t) __attribute__((weak));
+#else
+int dpa_alloc_pcd_fqids(struct device *, uint32_t, uint8_t, uint32_t *);
+
+int dpa_free_pcd_fqids(struct device *, uint32_t);
+
+#endif /* CONFIG_FSL_FMAN_TEST */
+
+
+int dpa_alloc_pcd_fqids(struct device *dev, uint32_t num,
+ uint8_t alignment, uint32_t *base_fqid)
+{
+ dev_crit(dev, "callback not implemented!\n");
+
+ return 0;
+}
+
+int dpa_free_pcd_fqids(struct device *dev, uint32_t base_fqid)
+{
+
+ dev_crit(dev, "callback not implemented!\n");
+
+ return 0;
+}
+
+void dpaa_eth_init_ports(struct mac_device *mac_dev,
+ struct dpa_bp *bp, size_t count,
+ struct fm_port_fqs *port_fqs,
+ struct dpa_buffer_layout_s *buf_layout,
+ struct device *dev)
+{
+ struct fm_port_pcd_param rx_port_pcd_param;
+ struct fm_port *rxport = mac_dev->port_dev[RX];
+ struct fm_port *txport = mac_dev->port_dev[TX];
+
+ dpaa_eth_init_tx_port(txport, port_fqs->tx_errq,
+ port_fqs->tx_defq, &buf_layout[TX]);
+ dpaa_eth_init_rx_port(rxport, bp, count, port_fqs->rx_errq,
+ port_fqs->rx_defq, &buf_layout[RX]);
+
+ rx_port_pcd_param.cba = dpa_alloc_pcd_fqids;
+ rx_port_pcd_param.cbf = dpa_free_pcd_fqids;
+ rx_port_pcd_param.dev = dev;
+ fm_port_pcd_bind(rxport, &rx_port_pcd_param);
+}
+
+void dpa_release_sgt(struct qm_sg_entry *sgt)
+{
+ struct dpa_bp *dpa_bp;
+ struct bm_buffer bmb[DPA_BUFF_RELEASE_MAX];
+ uint8_t i = 0, j;
+
+ do {
+ dpa_bp = dpa_bpid2pool(sgt[i].bpid);
+ DPA_BUG_ON(!dpa_bp);
+
+ j = 0;
+ do {
+ DPA_BUG_ON(sgt[i].extension);
+
+ bmb[j].hi = sgt[i].addr_hi;
+ bmb[j].lo = sgt[i].addr_lo;
+
+ j++; i++;
+ } while (j < ARRAY_SIZE(bmb) &&
+ !sgt[i-1].final &&
+ sgt[i-1].bpid == sgt[i].bpid);
+
+ while (bman_release(dpa_bp->pool, bmb, j, 0))
+ cpu_relax();
+ } while (!sgt[i-1].final);
+}
+
+void __attribute__((nonnull))
+dpa_fd_release(const struct net_device *net_dev, const struct qm_fd *fd)
+{
+ struct qm_sg_entry *sgt;
+ struct dpa_bp *_dpa_bp;
+ struct bm_buffer _bmb;
+
+ _bmb.hi = fd->addr_hi;
+ _bmb.lo = fd->addr_lo;
+
+ _dpa_bp = dpa_bpid2pool(fd->bpid);
+ DPA_BUG_ON(!_dpa_bp);
+
+ if (fd->format == qm_fd_sg) {
+ sgt = (phys_to_virt(bm_buf_addr(&_bmb)) + dpa_fd_offset(fd));
+ dpa_release_sgt(sgt);
+ }
+
+ while (bman_release(_dpa_bp->pool, &_bmb, 1, 0))
+ cpu_relax();
+}
+EXPORT_SYMBOL(dpa_fd_release);
+
+void count_ern(struct dpa_percpu_priv_s *percpu_priv,
+ const struct qm_mr_entry *msg)
+{
+ switch (msg->ern.rc & QM_MR_RC_MASK) {
+ case QM_MR_RC_CGR_TAILDROP:
+ percpu_priv->ern_cnt.cg_tdrop++;
+ break;
+ case QM_MR_RC_WRED:
+ percpu_priv->ern_cnt.wred++;
+ break;
+ case QM_MR_RC_ERROR:
+ percpu_priv->ern_cnt.err_cond++;
+ break;
+ case QM_MR_RC_ORPWINDOW_EARLY:
+ percpu_priv->ern_cnt.early_window++;
+ break;
+ case QM_MR_RC_ORPWINDOW_LATE:
+ percpu_priv->ern_cnt.late_window++;
+ break;
+ case QM_MR_RC_FQ_TAILDROP:
+ percpu_priv->ern_cnt.fq_tdrop++;
+ break;
+ case QM_MR_RC_ORPWINDOW_RETIRED:
+ percpu_priv->ern_cnt.fq_retired++;
+ break;
+ case QM_MR_RC_ORP_ZERO:
+ percpu_priv->ern_cnt.orp_zero++;
+ break;
+ }
+}
+
+
+/**
+ * Turn on HW checksum computation for this outgoing frame.
+ * If the current protocol is not something we support in this regard
+ * (or if the stack has already computed the SW checksum), we do nothing.
+ *
+ * Returns 0 if all goes well (or HW csum doesn't apply), and a negative value
+ * otherwise.
+ *
+ * Note that this function may modify the fd->cmd field and the skb data buffer
+ * (the Parse Results area).
+ */
+int dpa_enable_tx_csum(struct dpa_priv_s *priv,
+ struct sk_buff *skb, struct qm_fd *fd, char *parse_results)
+{
+ fm_prs_result_t *parse_result;
+ struct iphdr *iph;
+ struct ipv6hdr *ipv6h = NULL;
+ int l4_proto;
+ int ethertype = ntohs(skb->protocol);
+ int retval = 0;
+
+ if (skb->ip_summed != CHECKSUM_PARTIAL)
+ return 0;
+
+ /* Note: L3 csum seems to be already computed in sw, but we can't choose
+ * L4 alone from the FM configuration anyway.
+ */
+
+ /* Fill in some fields of the Parse Results array, so the FMan
+ * can find them as if they came from the FMan Parser.
+ */
+ parse_result = (fm_prs_result_t *)parse_results;
+
+ /* If we're dealing with VLAN, get the real Ethernet type */
+ if (ethertype == ETH_P_8021Q) {
+ /* We can't always assume the MAC header is set correctly
+ * by the stack, so reset to beginning of skb->data
+ */
+ skb_reset_mac_header(skb);
+ ethertype = ntohs(vlan_eth_hdr(skb)->h_vlan_encapsulated_proto);
+ }
+
+ /* Fill in the relevant L3 parse result fields
+ * and read the L4 protocol type
+ */
+ switch (ethertype) {
+ case ETH_P_IP:
+ parse_result->l3r = FM_L3_PARSE_RESULT_IPV4;
+ iph = ip_hdr(skb);
+ DPA_BUG_ON(iph == NULL);
+ l4_proto = ntohs(iph->protocol);
+ break;
+ case ETH_P_IPV6:
+ parse_result->l3r = FM_L3_PARSE_RESULT_IPV6;
+ ipv6h = ipv6_hdr(skb);
+ DPA_BUG_ON(ipv6h == NULL);
+ l4_proto = ntohs(ipv6h->nexthdr);
+ break;
+ default:
+ /* We shouldn't even be here */
+ if (netif_msg_tx_err(priv) && net_ratelimit())
+ netdev_alert(priv->net_dev,
+ "Can't compute HW csum for L3 proto 0x%x\n",
+ ntohs(skb->protocol));
+ retval = -EIO;
+ goto return_error;
+ }
+
+ /* Fill in the relevant L4 parse result fields */
+ switch (l4_proto) {
+ case IPPROTO_UDP:
+ parse_result->l4r = FM_L4_PARSE_RESULT_UDP;
+ break;
+ case IPPROTO_TCP:
+ parse_result->l4r = FM_L4_PARSE_RESULT_TCP;
+ break;
+ default:
+ /* This can as well be a BUG() */
+ if (netif_msg_tx_err(priv) && net_ratelimit())
+ netdev_alert(priv->net_dev,
+ "Can't compute HW csum for L4 proto 0x%x\n",
+ l4_proto);
+ retval = -EIO;
+ goto return_error;
+ }
+
+ /* At index 0 is IPOffset_1 as defined in the Parse Results */
+ parse_result->ip_off[0] = (uint8_t)skb_network_offset(skb);
+ parse_result->l4_off = (uint8_t)skb_transport_offset(skb);
+
+ /* Enable L3 (and L4, if TCP or UDP) HW checksum. */
+ fd->cmd |= FM_FD_CMD_RPD | FM_FD_CMD_DTC;
+
+ /* On P1023 and similar platforms fd->cmd interpretation could
+ * be disabled by setting CONTEXT_A bit ICMD; currently this bit
+ * is not set so we do not need to check; in the future, if/when
+ * using context_a we need to check this bit
+ */
+
+return_error:
+ return retval;
+}
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth_common.h b/drivers/net/ethernet/freescale/dpa/dpaa_eth_common.h
new file mode 100644
index 0000000..5d9feae
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth_common.h
@@ -0,0 +1,224 @@
+/* Copyright 2008-2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DPAA_ETH_COMMON_H
+#define __DPAA_ETH_COMMON_H
+
+#include <linux/etherdevice.h> /* struct net_device */
+#include <linux/fsl_bman.h> /* struct bm_buffer */
+#include <linux/of_platform.h> /* struct platform_device */
+#include <linux/net_tstamp.h> /* struct hwtstamp_config */
+
+#include "dpaa_eth.h"
+#include "lnxwrp_fsl_fman.h"
+
+/* make dpaa_eth code compile without the FMD AR code */
+#ifdef CONFIG_PM
+#ifndef fm_port_suspend
+#define fm_port_suspend(x) (0)
+#warning fm_port_suspend missing
+#endif
+#ifndef fm_port_resume
+#define fm_port_resume(x) (0)
+#endif
+#endif /* CONFIG_PM */
+
+#define dpaa_eth_init_port(type, port, param, errq_id, defq_id, buf_layout,\
+ frag_enabled) \
+{ \
+ param.errq = errq_id; \
+ param.defq = defq_id; \
+ param.priv_data_size = buf_layout->priv_data_size; \
+ param.parse_results = buf_layout->parse_results; \
+ param.hash_results = buf_layout->hash_results; \
+ param.frag_enable = frag_enabled; \
+ param.time_stamp = buf_layout->time_stamp; \
+ param.manip_extra_space = buf_layout->manip_extra_space; \
+ param.data_align = buf_layout->data_align; \
+ fm_set_##type##_port_params(port, &param); \
+}
+
+#define DPA_SGT_MAX_ENTRIES 16 /* maximum number of entries in SG Table */
+#define DPA_BUFF_RELEASE_MAX 8 /* maximum number of buffers released at once */
+
+/* return codes for the dpaa-eth hooks */
+enum dpaa_eth_hook_result {
+ /* fd/skb was retained by the hook.
+ *
+ * On the Rx path, this means the Ethernet driver will _not_
+ * deliver the skb to the stack. Instead, the hook implementation
+ * is expected to properly dispose of the skb.
+ *
+ * On the Tx path, the Ethernet driver's dpa_tx() function will
+ * immediately return NETDEV_TX_OK. The hook implementation is expected
+ * to free the skb. *DO*NOT* release it to BMan, or enqueue it to FMan,
+ * unless you know exactly what you're doing!
+ *
+ * On the confirmation/error paths, the Ethernet driver will _not_
+ * perform any fd cleanup, nor update the interface statistics.
+ */
+ DPAA_ETH_STOLEN,
+ /* fd/skb was returned to the Ethernet driver for regular processing.
+ * The hook is not allowed to, for instance, reallocate the skb (as if
+ * by linearizing, copying, cloning or reallocating the headroom).
+ */
+ DPAA_ETH_CONTINUE
+};
+
+typedef enum dpaa_eth_hook_result (*dpaa_eth_ingress_hook_t)(
+ struct sk_buff *skb, struct net_device *net_dev, u32 fqid);
+typedef enum dpaa_eth_hook_result (*dpaa_eth_egress_hook_t)(
+ struct sk_buff *skb, struct net_device *net_dev);
+typedef enum dpaa_eth_hook_result (*dpaa_eth_confirm_hook_t)(
+ struct net_device *net_dev, const struct qm_fd *fd, u32 fqid);
+
+/* used in napi related functions */
+extern u16 qman_portal_max;
+
+/* from dpa_ethtool.c */
+extern const struct ethtool_ops dpa_ethtool_ops;
+
+#if defined(CONFIG_AS_FASTPATH) || defined(CONFIG_FSL_FMAN_TEST)
+/* Various hooks used for unit-testing and/or fastpath optimizations.
+ * Currently only one set of such hooks is supported.
+ */
+struct dpaa_eth_hooks_s {
+ /* Invoked on the Tx private path, immediately after receiving the skb
+ * from the stack.
+ */
+ dpaa_eth_egress_hook_t tx;
+
+ /* Invoked on the Rx private path, right before passing the skb
+ * up the stack. At that point, the packet's protocol id has already
+ * been set. The skb's data pointer is now at the L3 header, and
+ * skb->mac_header points to the L2 header. skb->len has been adjusted
+ * to be the length of L3+payload (i.e., the length of the
+ * original frame minus the L2 header len).
+ * For more details on what the skb looks like, see eth_type_trans().
+ */
+ dpaa_eth_ingress_hook_t rx_default;
+
+ /* Driver hook for the Rx error private path. */
+ dpaa_eth_confirm_hook_t rx_error;
+ /* Driver hook for the Tx confirmation private path. */
+ dpaa_eth_confirm_hook_t tx_confirm;
+ /* Driver hook for the Tx error private path. */
+ dpaa_eth_confirm_hook_t tx_error;
+};
+
+void fsl_dpaa_eth_set_hooks(struct dpaa_eth_hooks_s *hooks);
+
+extern struct dpaa_eth_hooks_s dpaa_eth_hooks;
+#endif
+
+int dpa_netdev_init(struct device_node *dpa_node,
+ struct net_device *net_dev,
+ const uint8_t *mac_addr,
+ uint16_t tx_timeout);
+int __cold dpa_start(struct net_device *net_dev);
+int __cold dpa_stop(struct net_device *net_dev);
+void __cold dpa_timeout(struct net_device *net_dev);
+struct rtnl_link_stats64 * __cold
+dpa_get_stats64(struct net_device *net_dev,
+ struct rtnl_link_stats64 *stats);
+int dpa_change_mtu(struct net_device *net_dev, int new_mtu);
+int dpa_ndo_init(struct net_device *net_dev);
+int dpa_set_features(struct net_device *dev, netdev_features_t features);
+netdev_features_t dpa_fix_features(struct net_device *dev,
+ netdev_features_t features);
+#ifdef CONFIG_FSL_DPAA_TS
+u64 dpa_get_timestamp_ns(const struct dpa_priv_s *priv,
+ enum port_type rx_tx, const void *data);
+/* Updates the skb shared hw timestamp from the hardware timestamp */
+int dpa_get_ts(const struct dpa_priv_s *priv, enum port_type rx_tx,
+ struct skb_shared_hwtstamps *shhwtstamps, const void *data);
+#endif /* CONFIG_FSL_DPAA_TS */
+int dpa_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+int __cold dpa_remove(struct platform_device *of_dev);
+struct mac_device * __cold __must_check
+__attribute__((nonnull)) dpa_mac_probe(struct platform_device *_of_dev);
+int dpa_set_mac_address(struct net_device *net_dev, void *addr);
+void dpa_set_rx_mode(struct net_device *net_dev);
+void dpa_set_buffers_layout(struct mac_device *mac_dev,
+ struct dpa_buffer_layout_s *layout);
+int __attribute__((nonnull))
+dpa_bp_alloc(struct dpa_bp *dpa_bp);
+void __cold __attribute__((nonnull))
+dpa_bp_free(struct dpa_priv_s *priv, struct dpa_bp *dpa_bp);
+struct dpa_bp *dpa_bpid2pool(int bpid);
+void dpa_bpid2pool_map(int bpid, struct dpa_bp *dpa_bp);
+bool dpa_bpid2pool_use(int bpid);
+void dpa_bp_drain(struct dpa_bp *bp);
+#ifdef CONFIG_FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE
+u16 dpa_select_queue(struct net_device *net_dev, struct sk_buff *skb);
+#endif
+struct dpa_fq *dpa_fq_alloc(struct device *dev,
+ const struct fqid_cell *fqids,
+ struct list_head *list,
+ enum dpa_fq_type fq_type);
+int dpa_fq_probe_mac(struct device *dev, struct list_head *list,
+ struct fm_port_fqs *port_fqs,
+ bool tx_conf_fqs_per_core,
+ enum port_type ptype);
+int dpa_get_channel(void);
+int dpaa_eth_add_channel(void *__arg);
+int dpaa_eth_cgr_init(struct dpa_priv_s *priv);
+void dpa_fq_setup(struct dpa_priv_s *priv, const struct dpa_fq_cbs_t *fq_cbs,
+ struct fm_port *tx_port);
+int dpa_fq_init(struct dpa_fq *dpa_fq, bool td_enable);
+int __cold __attribute__((nonnull))
+dpa_fq_free(struct device *dev, struct list_head *list);
+void dpaa_eth_init_ports(struct mac_device *mac_dev,
+ struct dpa_bp *bp, size_t count,
+ struct fm_port_fqs *port_fqs,
+ struct dpa_buffer_layout_s *buf_layout,
+ struct device *dev);
+void dpa_release_sgt(struct qm_sg_entry *sgt);
+void __attribute__((nonnull))
+dpa_fd_release(const struct net_device *net_dev, const struct qm_fd *fd);
+void count_ern(struct dpa_percpu_priv_s *percpu_priv,
+ const struct qm_mr_entry *msg);
+int dpa_enable_tx_csum(struct dpa_priv_s *priv,
+ struct sk_buff *skb, struct qm_fd *fd, char *parse_results);
+
+struct proxy_device {
+ struct mac_device *mac_dev;
+};
+
+/* mac device control functions exposed by proxy interface*/
+int dpa_proxy_start(struct net_device *net_dev);
+int dpa_proxy_stop(struct proxy_device *proxy_dev, struct net_device *net_dev);
+int dpa_proxy_set_mac_address(struct proxy_device *proxy_dev,
+ struct net_device *net_dev);
+int dpa_proxy_set_rx_mode(struct proxy_device *proxy_dev,
+ struct net_device *net_dev);
+
+#endif /* __DPAA_ETH_COMMON_H */
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth_generic.c b/drivers/net/ethernet/freescale/dpa/dpaa_eth_generic.c
new file mode 100644
index 0000000..7e58fa3
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth_generic.c
@@ -0,0 +1,1508 @@
+/* Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* "generic" flavour of DPAA Ethernet driver, called oNIC
+ *
+ * TODO:
+ * 1. This file should be conditionally compiled. For the moment it is
+ * compiled by default.
+ * 2. Tx multiqueues (ndo_select queue, alloc_etherdev_mq)
+ * 3. Fetch the buffer layouts from OH ports.
+ * 4. Make the drive generic (can connect with multiple OH ports,
+ * remove '2' hardcode from oh_ports, buffer_layout, etc.).
+ * 5. Multiple buffer pools for RX (up to 4 supported on HW)
+ * 6. Different queue initializations (enable taildrop)
+ * 7. ethtool
+ * 8. Recycling (draining buffer pool = default buffer pool)
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kthread.h>
+#include <linux/of_net.h>
+#include <linux/if_vlan.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+
+#include "dpaa_eth.h"
+#include "dpaa_eth_common.h"
+#include "dpaa_eth_base.h"
+#include "dpaa_eth_generic.h"
+#include "dpaa_generic_debugfs.h"
+
+#define DPA_DEFAULT_TX_HEADROOM 64
+#define DPA_GENERIC_SKB_COPY_MAX_SIZE 256
+#define DPA_GENERIC_NAPI_WEIGHT 64
+#define DPA_GENERIC_DESCRIPTION "FSL DPAA Generic Ethernet driver"
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION(DPA_GENERIC_DESCRIPTION);
+
+static uint8_t debug = -1;
+module_param(debug, byte, S_IRUGO);
+MODULE_PARM_DESC(debug, "Module/Driver verbosity level");
+
+/* This has to work in tandem with the DPA_CS_THRESHOLD_xxx values. */
+static uint16_t tx_timeout = 1000;
+module_param(tx_timeout, ushort, S_IRUGO);
+MODULE_PARM_DESC(tx_timeout, "The Tx timeout in ms");
+
+struct rtnl_link_stats64 *__cold
+dpa_generic_get_stats64(struct net_device *netdev,
+ struct rtnl_link_stats64 *stats);
+static int dpa_generic_set_mac_address(struct net_device *net_dev,
+ void *addr);
+static int __cold dpa_generic_start(struct net_device *netdev);
+static int __cold dpa_generic_stop(struct net_device *netdev);
+static int dpa_generic_eth_probe(struct platform_device *_of_dev);
+static int dpa_generic_remove(struct platform_device *of_dev);
+static void dpa_generic_ern(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_mr_entry *msg);
+static int __hot dpa_generic_tx(struct sk_buff *skb,
+ struct net_device *netdev);
+
+static const struct net_device_ops dpa_generic_ops = {
+ .ndo_open = dpa_generic_start,
+ .ndo_start_xmit = dpa_generic_tx,
+ .ndo_stop = dpa_generic_stop,
+ .ndo_set_mac_address = dpa_generic_set_mac_address,
+ .ndo_tx_timeout = dpa_timeout,
+ .ndo_get_stats64 = dpa_generic_get_stats64,
+ .ndo_init = dpa_ndo_init,
+ .ndo_set_features = dpa_set_features,
+ .ndo_fix_features = dpa_fix_features,
+};
+
+struct rtnl_link_stats64 *__cold
+dpa_generic_get_stats64(struct net_device *netdev,
+ struct rtnl_link_stats64 *stats)
+{
+ struct dpa_generic_priv_s *priv = netdev_priv(netdev);
+ u64 *cpustats;
+ u64 *netstats = (u64 *)stats;
+ int i, j;
+ struct dpa_percpu_priv_s *percpu_priv;
+ int numstats = sizeof(struct rtnl_link_stats64) / sizeof(u64);
+
+ for_each_online_cpu(i) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+
+ cpustats = (u64 *)&percpu_priv->stats;
+
+ for (j = 0; j < numstats; j++)
+ netstats[j] += cpustats[j];
+ }
+
+ return stats;
+}
+
+static int dpa_generic_set_mac_address(struct net_device *net_dev,
+ void *addr)
+{
+ const struct dpa_generic_priv_s *priv = netdev_priv(net_dev);
+ int _errno;
+
+ _errno = eth_mac_addr(net_dev, addr);
+ if (_errno < 0) {
+ if (netif_msg_drv(priv))
+ netdev_err(net_dev, "eth_mac_addr() = %d\n", _errno);
+ return _errno;
+ }
+
+ return 0;
+}
+
+static const struct of_device_id dpa_generic_match[] = {
+ {
+ .compatible = "fsl,dpa-ethernet-generic"
+ },
+ {}
+};
+
+MODULE_DEVICE_TABLE(of, dpa_generic_match);
+
+static struct platform_driver dpa_generic_driver = {
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .of_match_table = dpa_generic_match,
+ .owner = THIS_MODULE,
+ },
+ .probe = dpa_generic_eth_probe,
+ .remove = dpa_generic_remove
+};
+
+int get_port_ref(struct device_node dev_node,
+ struct fm_port **port)
+{
+ const phandle *dpa_port_ref_node = NULL;
+ struct platform_device *dpa_port_of_dev = NULL;
+ struct device *op_dev = NULL;
+ struct device_node *dpa_port_node = NULL;
+ int lenp = 0;
+
+ dpa_port_ref_node = of_get_property(&dev_node,
+ "fsl,fman-oh-port", &lenp);
+ if (dpa_port_ref_node == NULL)
+ return -EINVAL;
+
+ dpa_port_node = of_find_node_by_phandle(*dpa_port_ref_node);
+ if (dpa_port_node == NULL)
+ return -EINVAL;
+
+ dpa_port_of_dev = of_find_device_by_node(dpa_port_node);
+ of_node_put(dpa_port_node);
+ if (dpa_port_of_dev == NULL)
+ return -EINVAL;
+
+ op_dev = &dpa_port_of_dev->dev;
+ *port = fm_port_bind(op_dev);
+ if (*port == NULL)
+ return -EINVAL;
+
+ return 0;
+}
+
+static void dpaa_generic_napi_enable(struct dpa_generic_priv_s *priv)
+{
+ struct dpa_percpu_priv_s *percpu_priv;
+ int i, j;
+
+ for_each_possible_cpu(i) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+
+ for (j = 0; j < qman_portal_max; j++)
+ napi_enable(&percpu_priv->np[j].napi);
+ }
+}
+
+static void dpaa_generic_napi_disable(struct dpa_generic_priv_s *priv)
+{
+ struct dpa_percpu_priv_s *percpu_priv;
+ int i, j;
+
+ for_each_possible_cpu(i) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+
+ for (j = 0; j < qman_portal_max; j++)
+ napi_disable(&percpu_priv->np[j].napi);
+ }
+}
+
+static struct device_node *get_rx_op_port_node(struct platform_device *_of_dev)
+{
+ struct device *dev = &_of_dev->dev;
+ struct device_node *dev_node = NULL;
+ const phandle *ports_handle = NULL;
+ int num_ports = 0;
+ int lenp = 0;
+
+ ports_handle = of_get_property(dev->of_node,
+ "fsl,oh-ports", &lenp);
+ if (ports_handle == NULL) {
+ dev_err(dev, "Cannot find node fsl,oh-ports property in device tree\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ num_ports = lenp / sizeof(*ports_handle);
+ if (num_ports < 1) {
+ dev_err(dev, "There should be at least one O/H port in device tree\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ dev_node = of_find_node_by_phandle(*ports_handle);
+ if (unlikely(dev_node == NULL)) {
+ dev_err(dev, "Cannot find node oh port node in device tree\n");
+ return ERR_PTR(-EFAULT);
+ }
+
+ return dev_node;
+}
+
+static int __cold dpa_generic_start(struct net_device *netdev)
+{
+ struct dpa_generic_priv_s *priv = netdev_priv(netdev);
+
+ /* seed default buffer pool */
+ dpa_bp_priv_seed(priv->rx_bp);
+
+ dpaa_generic_napi_enable(priv);
+ netif_tx_start_all_queues(netdev);
+
+ return 0;
+}
+
+static int __cold dpa_generic_stop(struct net_device *netdev)
+{
+ struct dpa_generic_priv_s *priv = netdev_priv(netdev);
+
+ netif_tx_stop_all_queues(netdev);
+ dpaa_generic_napi_disable(priv);
+
+ return 0;
+}
+
+static enum qman_cb_dqrr_result __hot
+dpa_generic_rx_err_dqrr(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry *dq)
+{
+ struct net_device *netdev;
+ struct dpa_generic_priv_s *priv;
+ struct dpa_percpu_priv_s *percpu_priv;
+ const struct qm_fd *fd;
+ int *countptr;
+
+ netdev = ((struct dpa_fq *)fq)->net_dev;
+ priv = netdev_priv(netdev);
+ percpu_priv = __this_cpu_ptr(priv->percpu_priv);
+ countptr = __this_cpu_ptr(priv->rx_bp->percpu_count);
+ fd = &dq->fd;
+
+ /* TODO: extract bpid from the fd; when multiple bps are supported
+ * there won't be a default bp
+ */
+
+ if (dpaa_eth_napi_schedule(percpu_priv, portal))
+ return qman_cb_dqrr_stop;
+
+ if (unlikely(dpaa_eth_refill_bpools(priv->rx_bp, countptr))) {
+ /* Unable to refill the buffer pool due to insufficient
+ * system memory. Just release the frame back into the pool,
+ * otherwise we'll soon end up with an empty buffer pool.
+ */
+ dpa_fd_release(netdev, fd);
+ goto qman_consume;
+ }
+
+ /* limit common, possibly innocuous Rx FIFO Overflow errors'
+ * interference with zero-loss convergence benchmark results.
+ */
+ if (likely(fd->status & FM_FD_STAT_ERR_PHYSICAL))
+ pr_warn_once("fsl-dpa: non-zero error counters in fman statistics (sysfs)\n");
+ else
+ if (netif_msg_hw(priv) && net_ratelimit())
+ netdev_err(netdev, "Err FD status 2 = 0x%08x\n",
+ fd->status & FM_FD_STAT_RX_ERRORS);
+
+
+ percpu_priv->stats.rx_errors++;
+
+ if (fd->status & FM_PORT_FRM_ERR_DMA)
+ percpu_priv->rx_errors.dme++;
+ if (fd->status & FM_PORT_FRM_ERR_PHYSICAL)
+ percpu_priv->rx_errors.fpe++;
+ if (fd->status & FM_PORT_FRM_ERR_SIZE)
+ percpu_priv->rx_errors.fse++;
+ if (fd->status & FM_PORT_FRM_ERR_PRS_HDR_ERR)
+ percpu_priv->rx_errors.phe++;
+
+ /* TODO dpa_csum_validation */
+
+ dpa_fd_release(netdev, fd);
+
+qman_consume:
+ return qman_cb_dqrr_consume;
+}
+
+
+static enum qman_cb_dqrr_result __hot
+dpa_generic_rx_dqrr(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry *dq)
+{
+ struct net_device *netdev;
+ struct dpa_generic_priv_s *priv;
+ struct dpa_bp *bp;
+ struct dpa_percpu_priv_s *percpu_priv;
+ struct sk_buff **skbh;
+ struct sk_buff *skb;
+ const struct qm_fd *fd = &dq->fd;
+ unsigned int skb_len;
+ u32 fd_status = fd->status;
+ u64 pad;
+ dma_addr_t addr = qm_fd_addr(fd);
+ unsigned int data_start;
+ unsigned long skb_addr;
+ int *countptr;
+
+ netdev = ((struct dpa_fq *)fq)->net_dev;
+ priv = netdev_priv(netdev);
+ percpu_priv = __this_cpu_ptr(priv->percpu_priv);
+ countptr = __this_cpu_ptr(priv->rx_bp->percpu_count);
+
+ if (unlikely(dpaa_eth_napi_schedule(percpu_priv, portal)))
+ return qman_cb_dqrr_stop;
+
+ if (unlikely(dpaa_eth_refill_bpools(priv->rx_bp, countptr))) {
+ /* Unable to refill the buffer pool due to insufficient
+ * system memory. Just release the frame back into the pool,
+ * otherwise we'll soon end up with an empty buffer pool.
+ */
+ dpa_fd_release(netdev, fd);
+ goto qman_consume;
+ }
+
+ skbh = (struct sk_buff **)phys_to_virt(addr);
+ /* according to the last common code (bp refill) the skb pointer is set
+ * to another address shifted by sizeof(struct sk_buff) to the left
+ */
+ skb = *(skbh - 1);
+
+ if (unlikely(fd_status & FM_FD_STAT_RX_ERRORS) != 0) {
+ if (netif_msg_hw(priv) && net_ratelimit())
+ netdev_warn(netdev, "FD status = 0x%08x\n",
+ fd->status & FM_FD_STAT_RX_ERRORS);
+
+ percpu_priv->stats.rx_errors++;
+ dpa_fd_release(netdev, fd);
+ goto qman_consume;
+ }
+ if (unlikely(fd->format != qm_fd_contig)) {
+ percpu_priv->stats.rx_dropped++;
+ if (netif_msg_rx_status(priv) && net_ratelimit())
+ netdev_warn(netdev, "Dropping a SG frame\n");
+ dpa_fd_release(netdev, fd);
+ goto qman_consume;
+ }
+
+ bp = dpa_bpid2pool(fd->bpid);
+ /* TODO add bp check on hot path? */
+
+ /* find out the pad */
+ skb_addr = virt_to_phys(skb->head);
+ pad = addr - skb_addr;
+
+ dma_unmap_single(bp->dev, addr, bp->size, DMA_BIDIRECTIONAL);
+
+ countptr = __this_cpu_ptr(bp->percpu_count);
+ (*countptr)--;
+
+ /* The skb is currently pointed at head + headroom. The packet
+ * starts at skb->head + pad + fd offset.
+ */
+ data_start = pad + dpa_fd_offset(fd) - skb_headroom(skb);
+ skb_put(skb, dpa_fd_length(fd) + data_start);
+ skb_pull(skb, data_start);
+ skb->protocol = eth_type_trans(skb, netdev);
+ if (unlikely(dpa_check_rx_mtu(skb, netdev->mtu))) {
+ percpu_priv->stats.rx_dropped++;
+ dev_kfree_skb(skb);
+ goto qman_consume;
+ }
+
+ skb_len = skb->len;
+
+ if (fd->status & FM_FD_STAT_L4CV)
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb->ip_summed = CHECKSUM_NONE;
+
+ if (unlikely(netif_receive_skb(skb) == NET_RX_DROP))
+ goto qman_consume;
+
+ percpu_priv->stats.rx_packets++;
+ percpu_priv->stats.rx_bytes += skb_len;
+
+qman_consume:
+ return qman_cb_dqrr_consume;
+}
+
+static void dpa_generic_drain_bp(struct dpa_bp *bp)
+{
+ int i, num;
+ struct bm_buffer bmb[8];
+ dma_addr_t addr;
+ int *countptr = __this_cpu_ptr(bp->percpu_count);
+ int count = *countptr;
+ struct sk_buff **skbh;
+
+ while (count >= 8) {
+ num = bman_acquire(bp->pool, bmb, 8, 0);
+ /* There may still be up to 7 buffers in the pool;
+ * just leave them there until more arrive
+ */
+ if (num < 0)
+ break;
+ for (i = 0; i < num; i++) {
+ addr = bm_buf_addr(&bmb[i]);
+ /* bp->free_buf_cb(phys_to_virt(addr)); */
+ skbh = (struct sk_buff **)phys_to_virt(addr);
+ dma_unmap_single(bp->dev, addr, bp->size,
+ DMA_TO_DEVICE);
+ dev_kfree_skb(*skbh);
+ }
+ count -= num;
+ }
+ *countptr = count;
+}
+
+/**
+ * Turn on HW checksum computation for this outgoing frame.
+ * If the current protocol is not something we support in this regard
+ * (or if the stack has already computed the SW checksum), we do nothing.
+ *
+ * Returns 0 if all goes well (or HW csum doesn't apply), and a negative value
+ * otherwise.
+ *
+ * Note that this function may modify the fd->cmd field and the skb data buffer
+ * (the Parse Results area).
+ */
+int dpa_generic_tx_csum(struct dpa_generic_priv_s *priv,
+ struct sk_buff *skb,
+ struct qm_fd *fd,
+ char *parse_results)
+{
+ fm_prs_result_t *parse_result;
+ struct iphdr *iph;
+ struct ipv6hdr *ipv6h = NULL;
+ int l4_proto;
+ int ethertype = ntohs(skb->protocol);
+ int retval = 0;
+
+ if (skb->ip_summed != CHECKSUM_PARTIAL)
+ return 0;
+
+ /* Note: L3 csum seems to be already computed in sw, but we can't choose
+ * L4 alone from the FM configuration anyway.
+ */
+
+ /* Fill in some fields of the Parse Results array, so the FMan
+ * can find them as if they came from the FMan Parser.
+ */
+ parse_result = (fm_prs_result_t *)parse_results;
+
+ /* If we're dealing with VLAN, get the real Ethernet type */
+ if (ethertype == ETH_P_8021Q) {
+ /* We can't always assume the MAC header is set correctly
+ * by the stack, so reset to beginning of skb->data
+ */
+ skb_reset_mac_header(skb);
+ ethertype = ntohs(vlan_eth_hdr(skb)->h_vlan_encapsulated_proto);
+ }
+
+ /* Fill in the relevant L3 parse result fields
+ * and read the L4 protocol type
+ */
+ switch (ethertype) {
+ case ETH_P_IP:
+ parse_result->l3r = FM_L3_PARSE_RESULT_IPV4;
+ iph = ip_hdr(skb);
+ BUG_ON(iph == NULL);
+ l4_proto = ntohs(iph->protocol);
+ break;
+ case ETH_P_IPV6:
+ parse_result->l3r = FM_L3_PARSE_RESULT_IPV6;
+ ipv6h = ipv6_hdr(skb);
+ BUG_ON(ipv6h == NULL);
+ l4_proto = ntohs(ipv6h->nexthdr);
+ break;
+ default:
+ /* We shouldn't even be here */
+ if (netif_msg_tx_err(priv) && net_ratelimit())
+ netdev_alert(priv->net_dev,
+ "Can't compute HW csum for L3 proto 0x%x\n",
+ ntohs(skb->protocol));
+ retval = -EIO;
+ goto return_error;
+ }
+
+ /* Fill in the relevant L4 parse result fields */
+ switch (l4_proto) {
+ case IPPROTO_UDP:
+ parse_result->l4r = FM_L4_PARSE_RESULT_UDP;
+ break;
+ case IPPROTO_TCP:
+ parse_result->l4r = FM_L4_PARSE_RESULT_TCP;
+ break;
+ default:
+ /* This can as well be a BUG() */
+ if (netif_msg_tx_err(priv) && net_ratelimit())
+ netdev_alert(priv->net_dev,
+ "Can't compute HW csum for L4 proto 0x%x\n",
+ l4_proto);
+ retval = -EIO;
+ goto return_error;
+ }
+
+ /* At index 0 is IPOffset_1 as defined in the Parse Results */
+ parse_result->ip_off[0] = skb_network_offset(skb);
+ parse_result->l4_off = skb_transport_offset(skb);
+
+ /* Enable L3 (and L4, if TCP or UDP) HW checksum. */
+ fd->cmd |= FM_FD_CMD_RPD | FM_FD_CMD_DTC;
+
+ /* On P1023 and similar platforms fd->cmd interpretation could
+ * be disabled by setting CONTEXT_A bit ICMD; currently this bit
+ * is not set so we do not need to check; in the future, if/when
+ * using context_a we need to check this bit
+ */
+
+return_error:
+ return retval;
+}
+
+static int __hot dpa_generic_tx(struct sk_buff *skb, struct net_device *netdev)
+{
+ struct dpa_generic_priv_s *priv = netdev_priv(netdev);
+ struct dpa_percpu_priv_s *percpu_priv =
+ __this_cpu_ptr(priv->percpu_priv);
+ struct rtnl_link_stats64 *percpu_stats = &percpu_priv->stats;
+ struct dpa_bp *bp = priv->draining_tx_bp;
+ struct sk_buff **skbh = NULL;
+ dma_addr_t addr;
+ struct qm_fd fd;
+ int queue_mapping;
+ struct qman_fq *egress_fq;
+ int i = 0, err = 0;
+ int *countptr;
+
+ if (unlikely(skb_headroom(skb) < priv->tx_headroom)) {
+ struct sk_buff *skb_new;
+
+ skb_new = skb_realloc_headroom(skb, priv->tx_headroom);
+ if (unlikely(!skb_new)) {
+ percpu_stats->tx_errors++;
+ kfree_skb(skb);
+ goto done;
+ }
+ kfree_skb(skb);
+ skb = skb_new;
+ }
+
+ clear_fd(&fd);
+
+ /* store skb backpointer to release the skb later */
+ skbh = (struct sk_buff **)(skb->data - priv->tx_headroom);
+ *skbh = skb;
+
+ /* TODO check if skb->len + priv->tx_headroom < bp->size */
+
+ /* Enable L3/L4 hardware checksum computation.
+ *
+ * We must do this before dma_map_single(), because we may
+ * need to write into the skb.
+ */
+ err = dpa_generic_tx_csum(priv, skb, &fd,
+ ((char *)skbh) + DPA_TX_PRIV_DATA_SIZE);
+ if (unlikely(err < 0)) {
+ if (netif_msg_tx_err(priv) && net_ratelimit())
+ netdev_err(netdev, "HW csum error: %d\n", err);
+ return err;
+ }
+
+ addr = dma_map_single(bp->dev, skbh,
+ skb->len + priv->tx_headroom, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(bp->dev, addr))) {
+ if (netif_msg_tx_err(priv) && net_ratelimit())
+ netdev_err(netdev, "dma_map_single() failed\n");
+ goto dma_mapping_failed;
+ }
+
+ fd.format = qm_fd_contig;
+ fd.length20 = skb->len;
+ fd.offset = priv->tx_headroom;
+ fd.addr_hi = upper_32_bits(addr);
+ fd.addr_lo = lower_32_bits(addr);
+ /* fd.cmd |= FM_FD_CMD_FCO; */
+ fd.bpid = bp->bpid;
+
+ /* (Partially) drain the Draining Buffer Pool pool; each core
+ * acquires at most the number of buffers it put there; since
+ * BMan allows for up to 8 buffers to be acquired at one time,
+ * work in batches of 8 for efficiency reasons
+ */
+ dpa_generic_drain_bp(bp);
+
+ queue_mapping = dpa_get_queue_mapping(skb);
+ egress_fq = priv->egress_fqs[queue_mapping];
+
+ for (i = 0; i < 100000; i++) {
+ err = qman_enqueue(egress_fq, &fd, 0);
+ if (err != -EBUSY)
+ break;
+ }
+
+ if (unlikely(err < 0)) {
+ percpu_stats->tx_fifo_errors++;
+ goto xmit_failed;
+ }
+
+ countptr = __this_cpu_ptr(bp->percpu_count);
+ (*countptr)++;
+
+ percpu_stats->tx_packets++;
+ percpu_stats->tx_bytes += fd.length20;
+ netdev->trans_start = jiffies;
+
+ goto done;
+
+xmit_failed:
+ dma_unmap_single(bp->dev, addr, fd.offset + fd.length20, DMA_TO_DEVICE);
+dma_mapping_failed:
+ percpu_stats->tx_errors++;
+ dev_kfree_skb(skb);
+done:
+ return NETDEV_TX_OK;
+}
+
+static int dpa_generic_napi_add(struct net_device *net_dev)
+{
+ struct dpa_generic_priv_s *priv = netdev_priv(net_dev);
+ struct dpa_percpu_priv_s *percpu_priv;
+ int i, cpu;
+
+ for_each_possible_cpu(cpu) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, cpu);
+
+ percpu_priv->np = devm_kzalloc(net_dev->dev.parent,
+ qman_portal_max * sizeof(struct dpa_napi_portal),
+ GFP_KERNEL);
+
+ if (unlikely(percpu_priv->np == NULL)) {
+ dev_err(net_dev->dev.parent, "devm_kzalloc() failed\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < qman_portal_max; i++)
+ netif_napi_add(net_dev, &percpu_priv->np[i].napi,
+ dpaa_eth_poll, DPA_GENERIC_NAPI_WEIGHT);
+ }
+
+ return 0;
+}
+
+void dpa_generic_napi_del(struct net_device *net_dev)
+{
+ struct dpa_generic_priv_s *priv = netdev_priv(net_dev);
+ struct dpa_percpu_priv_s *percpu_priv;
+ int i, cpu;
+
+ for_each_possible_cpu(cpu) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, cpu);
+
+ if (percpu_priv->np) {
+ for (i = 0; i < qman_portal_max; i++)
+ netif_napi_del(&percpu_priv->np[i].napi);
+
+ devm_kfree(net_dev->dev.parent, percpu_priv->np);
+ }
+ }
+}
+
+
+static int dpa_generic_netdev_init(struct device_node *dpa_node,
+ struct net_device *netdev)
+{
+ struct dpa_generic_priv_s *priv = netdev_priv(netdev);
+ struct device *dev = netdev->dev.parent;
+ const uint8_t *mac_addr;
+ int err;
+
+ netdev->netdev_ops = &dpa_generic_ops;
+
+ mac_addr = of_get_mac_address(dpa_node);
+ if (mac_addr == NULL) {
+ if (netif_msg_probe(priv))
+ dev_err(dev, "No virtual MAC address found!\n");
+ return -EINVAL;
+ }
+
+ netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+ netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
+ netdev->features |= netdev->hw_features;
+ netdev->vlan_features = netdev->features;
+
+ memcpy(netdev->perm_addr, mac_addr, netdev->addr_len);
+ memcpy(netdev->dev_addr, mac_addr, netdev->addr_len);
+
+ /* TODO: ethtool support */
+
+ netdev->needed_headroom = priv->tx_headroom;
+ netdev->watchdog_timeo = msecs_to_jiffies(tx_timeout);
+
+ err = register_netdev(netdev);
+ if (err < 0) {
+ dev_err(dev, "register_netdev() = %d\n", err);
+ return err;
+ }
+
+#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS
+ /* create debugfs entry for this net_device */
+ err = dpa_generic_debugfs_create(netdev);
+ if (err) {
+ unregister_netdev(netdev);
+ return err;
+ }
+#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */
+
+ return 0;
+}
+
+struct dpa_fq_cbs_t generic_fq_cbs = {
+ .rx_defq = { .cb = { .dqrr = dpa_generic_rx_dqrr } },
+ /* for OH ports Rx Error queues = Tx Error queues */
+ .rx_errq = { .cb = { .dqrr = dpa_generic_rx_err_dqrr } },
+ .egress_ern = { .cb = { .ern = dpa_generic_ern } }
+};
+
+struct list_head *dpa_generic_fq_probe(struct platform_device *_of_dev,
+ struct fm_port *tx_port)
+{
+ struct device *dev = &_of_dev->dev;
+ struct device_node *dev_node = NULL;
+ const struct fqid_cell *fqids;
+ struct dpa_fq *fq, *tmp;
+ struct list_head *list;
+ int num_ranges;
+ int i, lenp;
+
+ /* RX queues (RX error, RX default) are specified in Rx O/H port node */
+ dev_node = get_rx_op_port_node(_of_dev);
+
+ fqids = of_get_property(dev_node, "fsl,qman-frame-queues-oh", &lenp);
+ if (fqids == NULL) {
+ dev_err(dev, "Need Rx FQ definition in dts for generic devices\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ of_node_put(dev_node);
+ num_ranges = lenp / sizeof(*fqids);
+ if (num_ranges != 2) {
+ dev_err(dev, "Need 2 Rx FQ definitions in dts for generic devices\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ list = devm_kzalloc(dev, sizeof(*list), GFP_KERNEL);
+ if (!list) {
+ dev_err(dev, "devm_kzalloc() failed\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ INIT_LIST_HEAD(list);
+
+ if (!dpa_fq_alloc(dev, &fqids[0], list, FQ_TYPE_RX_ERROR) ||
+ !dpa_fq_alloc(dev, &fqids[1], list,
+ FQ_TYPE_RX_DEFAULT)) {
+ dev_err(dev, "_dpa_fq_alloc() failed\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /* TX queues */
+ fqids = of_get_property(dev->of_node,
+ "fsl,qman-frame-queues-tx", &lenp);
+ if (fqids == NULL) {
+ dev_err(dev, "Need Tx FQ definition in dts for generic devices\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ num_ranges = lenp / sizeof(*fqids);
+ for (i = 0; i < num_ranges; i++) {
+ if (!dpa_fq_alloc(dev, &fqids[i], list, FQ_TYPE_TX)) {
+ dev_err(dev, "_dpa_fq_alloc() failed\n");
+ return ERR_PTR(-ENOMEM);
+ }
+ }
+
+ /* optional RX PCD queues */
+ lenp = 0;
+ fqids = of_get_property(dev->of_node,
+ "fsl,qman-frame-queues-rx", &lenp);
+
+ num_ranges = lenp / sizeof(*fqids);
+ for (i = 0; i < num_ranges; i++) {
+ if (!dpa_fq_alloc(dev, &fqids[i], list, FQ_TYPE_RX_PCD)) {
+ dev_err(dev, "_dpa_fq_alloc() failed\n");
+ return ERR_PTR(-ENOMEM);
+ }
+ }
+
+ list_for_each_entry_safe(fq, tmp, list, list) {
+ if (fq->fq_type == FQ_TYPE_TX)
+ fq->channel = fm_get_tx_port_channel(tx_port);
+ }
+
+ return list;
+}
+
+static void dpa_generic_ern(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_mr_entry *msg)
+{
+ struct net_device *netdev;
+ const struct dpa_generic_priv_s *priv;
+ struct dpa_percpu_priv_s *percpu_priv;
+ struct qm_fd fd = msg->ern.fd;
+
+ netdev = ((struct dpa_fq *)fq)->net_dev;
+ priv = netdev_priv(netdev);
+ /* Non-migratable context, safe to use __this_cpu_ptr */
+ percpu_priv = __this_cpu_ptr(priv->percpu_priv);
+ percpu_priv->stats.tx_dropped++;
+ percpu_priv->stats.tx_fifo_errors++;
+ count_ern(percpu_priv, msg);
+
+ /* release this buffer into the draining buffer pool */
+ dpa_fd_release(netdev, &fd);
+}
+
+static int dpa_generic_rx_bp_probe(struct platform_device *_of_dev,
+ struct fm_port *rx_port,
+ int *rx_bp_count,
+ struct dpa_bp **rx_bp,
+ struct dpa_buffer_layout_s **rx_buf_layout)
+{
+ struct device *dev = &_of_dev->dev;
+ const phandle *phandle_prop = NULL;
+ struct fm_port_params params;
+ struct dpa_bp *bp = NULL;
+ int bp_count = 0;
+ const uint32_t *bpid = NULL;
+ const uint32_t *bpool_cfg = NULL;
+ struct device_node *dev_node = NULL;
+ struct dpa_buffer_layout_s *buf_layout = NULL;
+ int lenp = 0;
+ int na = 0, ns = 0;
+ int err = 0, i = 0;
+
+ dev_node = get_rx_op_port_node(_of_dev);
+
+ phandle_prop = of_get_property(dev_node,
+ "fsl,bman-buffer-pools", &lenp);
+ if (!phandle_prop) {
+ dev_err(dev, "missing fsl,bman-buffer-pools property from device tree\n");
+ return -EINVAL;
+ }
+
+ bp_count = lenp / sizeof(*phandle_prop);
+
+ bp = devm_kzalloc(dev, bp_count * sizeof(*bp), GFP_KERNEL);
+ if (unlikely(bp == NULL)) {
+ dev_err(dev, "devm_kzalloc() failed\n");
+ return -ENOMEM;
+ }
+
+ of_node_put(dev_node);
+ dev_node = of_find_node_by_path("/");
+ if (unlikely(dev_node == NULL)) {
+ dev_err(dev, "of_find_node_by_path(/) failed\n");
+ return -EINVAL;
+ }
+
+ na = of_n_addr_cells(dev_node);
+ ns = of_n_size_cells(dev_node);
+
+ of_node_put(dev_node);
+
+ for (i = 0; i < bp_count; i++) {
+ dev_node = of_find_node_by_phandle(phandle_prop[i]);
+ if (unlikely(dev_node == NULL)) {
+ dev_err(dev, "of_find_node_by_phandle() failed\n");
+ return -EFAULT;
+ }
+
+ if (unlikely(!of_device_is_compatible(dev_node, "fsl,bpool"))) {
+ dev_err(dev, "!of_device_is_compatible(%s, fsl,bpool)\n",
+ dev_node->full_name);
+ err = -EINVAL;
+ goto _return_of_node_put;
+ }
+
+ bpid = of_get_property(dev_node, "fsl,bpid", &lenp);
+ if ((bpid == NULL) || (lenp != sizeof(*bpid))) {
+ dev_err(dev, "fsl,bpid property not found.\n");
+ err = -EINVAL;
+ goto _return_of_node_put;
+ }
+
+ bp[i].bpid = *bpid;
+
+ bpool_cfg = of_get_property(dev_node, "fsl,bpool-ethernet-cfg",
+ &lenp);
+ if (bpool_cfg && (lenp == (2 * ns + na) * sizeof(*bpool_cfg))) {
+ bp[i].config_count = (int)of_read_number(bpool_cfg, ns);
+ bp[i].size = of_read_number(bpool_cfg + ns, ns);
+ bp[i].paddr = 0;
+ bp[i].seed_pool = false;
+ } else {
+ dev_err(dev, "Missing/invalid fsl,bpool-ethernet-cfg device tree entry for node %s\n",
+ dev_node->full_name);
+ err = -EINVAL;
+ goto _return_of_node_put;
+ }
+
+ bp[i].percpu_count = alloc_percpu(*(bp[i].percpu_count));
+ }
+
+ buf_layout = devm_kzalloc(dev, sizeof(*buf_layout), GFP_KERNEL);
+ if (!buf_layout) {
+ dev_err(dev, "devm_kzalloc() failed\n");
+ err = -ENOMEM;
+ goto _return_of_node_put;
+ }
+
+ buf_layout->priv_data_size = DPA_TX_PRIV_DATA_SIZE;
+ buf_layout->parse_results = false;
+ buf_layout->hash_results = false;
+ buf_layout->time_stamp = false;
+ fm_port_get_buff_layout_ext_params(rx_port, &params);
+ buf_layout->manip_extra_space = params.manip_extra_space;
+ /* a value of zero for data alignment means "don't care", so align to
+ * a non-zero value to prevent FMD from using its own default
+ */
+ buf_layout->data_align = params.data_align ? : DPA_FD_DATA_ALIGNMENT;
+
+ *rx_buf_layout = buf_layout;
+ *rx_bp = bp;
+ *rx_bp_count = bp_count;
+
+ return 0;
+
+_return_of_node_put:
+ if (dev_node)
+ of_node_put(dev_node);
+
+ return err;
+}
+
+int dpa_generic_tx_bp_probe(struct platform_device *_of_dev,
+ struct fm_port *tx_port,
+ struct dpa_bp **draining_tx_bp,
+ struct dpa_buffer_layout_s **tx_buf_layout)
+{
+ struct device *dev = &_of_dev->dev;
+ struct fm_port_params params;
+ struct dpa_bp *bp = NULL;
+ struct dpa_buffer_layout_s *buf_layout = NULL;
+
+ buf_layout = devm_kzalloc(dev, sizeof(*buf_layout), GFP_KERNEL);
+ if (!buf_layout) {
+ dev_err(dev, "devm_kzalloc() failed\n");
+ return -ENOMEM;
+ }
+
+ buf_layout->priv_data_size = DPA_TX_PRIV_DATA_SIZE;
+ buf_layout->parse_results = true;
+ buf_layout->hash_results = true;
+ buf_layout->time_stamp = false;
+
+ fm_port_get_buff_layout_ext_params(tx_port, &params);
+ buf_layout->manip_extra_space = params.manip_extra_space;
+ buf_layout->data_align = params.data_align ? : DPA_FD_DATA_ALIGNMENT;
+
+ bp = devm_kzalloc(dev, sizeof(*bp), GFP_KERNEL);
+ if (unlikely(bp == NULL)) {
+ dev_err(dev, "devm_kzalloc() failed\n");
+ return -ENOMEM;
+ }
+
+ bp->size = dpa_bp_size(buf_layout);
+ bp->percpu_count = alloc_percpu(*bp->percpu_count);
+ bp->target_count = CONFIG_FSL_DPAA_ETH_MAX_BUF_COUNT;
+
+ *draining_tx_bp = bp;
+ *tx_buf_layout = buf_layout;
+
+ return 0;
+}
+
+int dpa_generic_port_probe(struct platform_device *_of_dev,
+ struct fm_port **rx_port,
+ struct fm_port **tx_port)
+{
+ struct device *dev = &_of_dev->dev;
+ struct device_node *dev_node = NULL;
+ const phandle *ports_handle = NULL;
+ int num_ports = 0;
+ int lenp = 0;
+ int err = 0;
+
+ ports_handle = of_get_property(dev->of_node,
+ "fsl,oh-ports", &lenp);
+ if (ports_handle == NULL) {
+ dev_err(dev, "Cannot find fsl,oh-ports property in device tree\n");
+ return -EINVAL;
+ }
+
+ num_ports = lenp / sizeof(*ports_handle);
+ if (num_ports != 2) {
+ /* for the moment, only two ports are supported */
+ dev_err(dev, "There should be two OH ports in device tree (one for RX, one for TX\n");
+ return -EINVAL;
+ }
+
+ dev_node = of_find_node_by_phandle(ports_handle[RX]);
+ if (unlikely(dev_node == NULL)) {
+ dev_err(dev, "Cannot find OH port node in device tree\n");
+ return -EFAULT;
+ }
+
+ err = get_port_ref(*dev_node, rx_port);
+ if (err < 0) {
+ dev_err(dev, "Cannot read OH port node in device tree\n");
+ return err;
+ }
+
+ dev_node = of_find_node_by_phandle(ports_handle[TX]);
+ if (unlikely(dev_node == NULL)) {
+ dev_err(dev, "Cannot find OH port node in device tree\n");
+ return -EFAULT;
+ }
+
+ err = get_port_ref(*dev_node, tx_port);
+ if (err < 0) {
+ dev_err(dev, "Cannot read OH port node in device tree\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static inline void dpa_generic_setup_ingress(
+ const struct dpa_generic_priv_s *priv,
+ struct dpa_fq *fq,
+ const struct qman_fq *template)
+{
+ fq->fq_base = *template;
+ fq->net_dev = priv->net_dev;
+
+ fq->flags = QMAN_FQ_FLAG_NO_ENQUEUE;
+ fq->channel = priv->channel;
+}
+
+static inline void dpa_generic_setup_egress(
+ const struct dpa_generic_priv_s *priv,
+ struct dpa_fq *fq,
+ struct fm_port *port,
+ const struct qman_fq *template)
+{
+ fq->fq_base = *template;
+ fq->net_dev = priv->net_dev;
+
+ if (port) {
+ fq->flags = QMAN_FQ_FLAG_TO_DCPORTAL;
+ fq->channel = fm_get_tx_port_channel(port);
+ } else {
+ fq->flags = QMAN_FQ_FLAG_NO_MODIFY;
+ }
+}
+
+static void dpa_generic_fq_setup(struct dpa_generic_priv_s *priv,
+ const struct dpa_fq_cbs_t *fq_cbs,
+ struct fm_port *tx_port)
+{
+ struct dpa_fq *fq;
+ int egress_cnt = 0;
+
+ /* Initialize each FQ in the list */
+ list_for_each_entry(fq, &priv->dpa_fq_list, list) {
+ switch (fq->fq_type) {
+ case FQ_TYPE_RX_DEFAULT:
+ dpa_generic_setup_ingress(priv, fq, &fq_cbs->rx_defq);
+ break;
+ case FQ_TYPE_RX_ERROR:
+ dpa_generic_setup_ingress(priv, fq, &fq_cbs->rx_errq);
+ break;
+ case FQ_TYPE_RX_PCD:
+ dpa_generic_setup_ingress(priv, fq, &fq_cbs->rx_errq);
+ break;
+ case FQ_TYPE_TX:
+ dpa_generic_setup_egress(priv, fq,
+ tx_port, &fq_cbs->egress_ern);
+ /* If we have more Tx queues than the number of cores,
+ * just ignore the extra ones.
+ */
+ if (egress_cnt < DPAA_ETH_TX_QUEUES)
+ priv->egress_fqs[egress_cnt++] = &fq->fq_base;
+ break;
+ default:
+ dev_warn(priv->net_dev->dev.parent,
+ "Unknown FQ type detected!\n");
+ break;
+ }
+ }
+
+ /* The number of Tx queues may be smaller than the number of cores, if
+ * the Tx queue range is specified in the device tree instead of being
+ * dynamically allocated.
+ * Make sure all CPUs receive a corresponding Tx queue.
+ */
+ while (egress_cnt < DPAA_ETH_TX_QUEUES) {
+ list_for_each_entry(fq, &priv->dpa_fq_list, list) {
+ if (fq->fq_type != FQ_TYPE_TX)
+ continue;
+ priv->egress_fqs[egress_cnt++] = &fq->fq_base;
+ if (egress_cnt == DPAA_ETH_TX_QUEUES)
+ break;
+ }
+ }
+}
+
+static int dpa_generic_fq_init(struct dpa_fq *dpa_fq, bool td_enable)
+{
+ int _errno;
+ struct device *dev;
+ struct qman_fq *fq;
+ struct qm_mcc_initfq initfq;
+
+ dev = dpa_fq->net_dev->dev.parent;
+
+ if (dpa_fq->fqid == 0)
+ dpa_fq->flags |= QMAN_FQ_FLAG_DYNAMIC_FQID;
+
+ dpa_fq->init = !(dpa_fq->flags & QMAN_FQ_FLAG_NO_MODIFY);
+
+ _errno = qman_create_fq(dpa_fq->fqid, dpa_fq->flags, &dpa_fq->fq_base);
+ if (_errno) {
+ dev_err(dev, "qman_create_fq() failed\n");
+ return _errno;
+ }
+ fq = &dpa_fq->fq_base;
+
+ if (dpa_fq->init) {
+ initfq.we_mask = QM_INITFQ_WE_FQCTRL;
+ /* FIXME: why would we want to keep an empty FQ in cache? */
+ initfq.fqd.fq_ctrl = QM_FQCTRL_PREFERINCACHE;
+
+ /* FQ placement */
+ initfq.we_mask |= QM_INITFQ_WE_DESTWQ;
+
+ initfq.fqd.dest.channel = dpa_fq->channel;
+ initfq.fqd.dest.wq = dpa_fq->wq;
+
+ if (dpa_fq->fq_type == FQ_TYPE_TX) {
+ initfq.we_mask |= QM_INITFQ_WE_CONTEXTA;
+ /* CTXA[A2V] = 1 */
+ initfq.fqd.context_a.hi = 0x10000000;
+ initfq.fqd.context_a.lo = 0x80000000;
+ /* initfq.fqd.context_b = qman_fq_fqid(confq); */
+ }
+
+ /* Initialization common to all ingress queues */
+ if (dpa_fq->flags & QMAN_FQ_FLAG_NO_ENQUEUE) {
+ initfq.we_mask |= QM_INITFQ_WE_CONTEXTA;
+ initfq.fqd.fq_ctrl |=
+ QM_FQCTRL_CTXASTASHING | QM_FQCTRL_AVOIDBLOCK;
+ initfq.fqd.context_a.stashing.exclusive =
+ QM_STASHING_EXCL_DATA | QM_STASHING_EXCL_CTX |
+ QM_STASHING_EXCL_ANNOTATION;
+ initfq.fqd.context_a.stashing.data_cl = 2;
+ initfq.fqd.context_a.stashing.annotation_cl = 1;
+ initfq.fqd.context_a.stashing.context_cl =
+ DIV_ROUND_UP(sizeof(struct qman_fq), 64);
+ };
+
+ _errno = qman_init_fq(fq, QMAN_INITFQ_FLAG_SCHED, &initfq);
+ if (_errno < 0) {
+ dev_err(dev, "qman_init_fq(%u) = %d\n",
+ qman_fq_fqid(fq), _errno);
+ qman_destroy_fq(fq, 0);
+ return _errno;
+ }
+ }
+
+ dpa_fq->fqid = qman_fq_fqid(fq);
+
+ return 0;
+}
+
+static int dpa_generic_fq_create(struct net_device *netdev,
+ struct list_head *dpa_fq_list,
+ struct fm_port *tx_port)
+{
+ struct dpa_generic_priv_s *priv = netdev_priv(netdev);
+ struct dpa_fq *fqs = NULL, *tmp = NULL;
+ struct task_struct *kth;
+ int err = 0;
+
+ INIT_LIST_HEAD(&priv->dpa_fq_list);
+
+ list_replace_init(dpa_fq_list, &priv->dpa_fq_list);
+
+ priv->channel = dpa_get_channel();
+ if (priv->channel < 0) {
+ err = priv->channel;
+ return err;
+ }
+
+ /* Start a thread that will walk the cpus with affine portals
+ * and add this pool channel to each's dequeue mask.
+ */
+ kth = kthread_run(dpaa_eth_add_channel,
+ (void *)(unsigned long)priv->channel,
+ "dpaa_%p:%d", netdev, priv->channel);
+ if (!kth)
+ return -ENOMEM;
+
+ dpa_generic_fq_setup(priv, &generic_fq_cbs, tx_port);
+
+ /* Add the FQs to the interface, and make them active */
+ list_for_each_entry_safe(fqs, tmp, &priv->dpa_fq_list, list) {
+ err = dpa_generic_fq_init(fqs, false);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+int dpa_generic_bp_create(struct net_device *net_dev,
+ int rx_bp_count,
+ struct dpa_bp *rx_bp,
+ struct dpa_buffer_layout_s *rx_buf_layout,
+ struct dpa_bp *draining_tx_bp,
+ struct dpa_buffer_layout_s *tx_buf_layout)
+{
+ struct dpa_generic_priv_s *priv = netdev_priv(net_dev);
+ int err = 0;
+
+ /* TODO: multiple Rx bps */
+ priv->rx_bp_count = rx_bp_count;
+ priv->rx_bp = rx_bp;
+ priv->rx_buf_layout = rx_buf_layout;
+ priv->draining_tx_bp = draining_tx_bp;
+ priv->tx_buf_layout = tx_buf_layout;
+
+ err = dpa_bp_alloc(priv->rx_bp);
+ if (err < 0) {
+ /* _dpa_bp_free(priv->rx_bp); */
+ priv->rx_bp = NULL;
+ return err;
+ }
+
+ err = dpa_bp_alloc(priv->draining_tx_bp);
+ if (err < 0) {
+ /* _dpa_bp_free(priv->draining_tx_bp); */
+ priv->draining_tx_bp = NULL;
+ return err;
+ }
+
+ return 0;
+}
+
+static int dpa_generic_remove(struct platform_device *of_dev)
+{
+ int err;
+ struct device *dev;
+ struct net_device *net_dev;
+ struct dpa_generic_priv_s *priv;
+
+ dev = &of_dev->dev;
+ net_dev = dev_get_drvdata(dev);
+ priv = netdev_priv(net_dev);
+
+ dpaa_eth_generic_sysfs_remove(dev);
+
+ dev_set_drvdata(dev, NULL);
+ unregister_netdev(net_dev);
+
+ /* TODO: this is for private driver; make it generic */
+ err = 0;
+#if 0
+ err = dpa_fq_free(dev, &priv->dpa_fq_list);
+#endif
+
+ dpa_private_napi_del(net_dev);
+ free_percpu(priv->percpu_priv);
+
+ /* TODO: this is for private dirver also; make generic */
+#if 0
+ dpa_bp_free(priv, priv->dpa_bp);
+ devm_kfree(dev, priv->dpa_bp);
+
+ if (priv->buf_layout)
+ devm_kfree(dev, priv->buf_layout);
+#endif
+
+#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS
+ dpa_generic_debugfs_remove(net_dev);
+#endif
+ free_netdev(net_dev);
+
+ return err;
+}
+
+static int dpa_generic_eth_probe(struct platform_device *_of_dev)
+{
+ struct device *dev = &_of_dev->dev;
+ struct device_node *dpa_node = dev->of_node;
+ struct net_device *netdev = NULL;
+ struct dpa_generic_priv_s *priv;
+ struct fm_port *rx_port = NULL;
+ struct fm_port *tx_port = NULL;
+ struct dpa_percpu_priv_s *percpu_priv;
+ int rx_bp_count = 0;
+ struct dpa_bp *rx_bp = NULL, *draining_tx_bp = NULL;
+ struct dpa_buffer_layout_s *rx_buf_layout = NULL, *tx_buf_layout = NULL;
+ struct list_head *dpa_fq_list;
+ static u8 generic_idx;
+ int err = 0;
+ int i = 0;
+
+ if (!of_device_is_available(dpa_node))
+ return -ENODEV;
+
+ err = dpa_generic_port_probe(_of_dev, &tx_port, &rx_port);
+ if (err < 0)
+ return err;
+
+ err = dpa_generic_rx_bp_probe(_of_dev, rx_port, &rx_bp_count,
+ &rx_bp, &rx_buf_layout);
+ if (err < 0)
+ return err;
+
+ err = dpa_generic_tx_bp_probe(_of_dev, tx_port, &draining_tx_bp,
+ &tx_buf_layout);
+ if (err < 0)
+ return err;
+
+ dpa_fq_list = dpa_generic_fq_probe(_of_dev, tx_port);
+ if (IS_ERR(dpa_fq_list))
+ return PTR_ERR(dpa_fq_list);
+
+ /* just one queue for now */
+ netdev = alloc_etherdev_mq(sizeof(*priv), 1);
+ if (!netdev) {
+ dev_err(dev, "alloc_etherdev_mq() failed\n");
+ return -ENOMEM;
+ }
+
+ SET_NETDEV_DEV(netdev, dev);
+ dev_set_drvdata(dev, netdev);
+ priv = netdev_priv(netdev);
+ priv->net_dev = netdev;
+ sprintf(priv->if_type, "generic%d", generic_idx++);
+ priv->msg_enable = netif_msg_init(debug, -1);
+ priv->tx_headroom = DPA_DEFAULT_TX_HEADROOM;
+
+ err = dpa_generic_bp_create(netdev, rx_bp_count, rx_bp, rx_buf_layout,
+ draining_tx_bp, tx_buf_layout);
+ if (err < 0)
+ goto bp_create_failed;
+
+ err = dpa_generic_fq_create(netdev, dpa_fq_list, rx_port);
+ if (err < 0)
+ goto fq_create_failed;
+
+ priv->tx_headroom = dpa_get_headroom(tx_buf_layout);
+ priv->rx_headroom = dpa_get_headroom(rx_buf_layout);
+ priv->rx_port = rx_port;
+ priv->tx_port = tx_port;
+ priv->mac_dev = NULL;
+
+ priv->percpu_priv = alloc_percpu(*priv->percpu_priv);
+ if (priv->percpu_priv == NULL) {
+ dev_err(dev, "alloc_percpu() failed\n");
+ err = -ENOMEM;
+ goto alloc_percpu_failed;
+ }
+ for_each_online_cpu(i) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+ memset(percpu_priv, 0, sizeof(*percpu_priv));
+ }
+
+ /* Initialize NAPI */
+ err = dpa_generic_napi_add(netdev);
+ if (err < 0)
+ goto napi_add_failed;
+
+
+ err = dpa_generic_netdev_init(dpa_node, netdev);
+ if (err < 0)
+ goto netdev_init_failed;
+
+ dpaa_eth_generic_sysfs_init(&netdev->dev);
+
+ pr_info("fsl_dpa_generic: Probed %s interface as %s\n",
+ priv->if_type, netdev->name);
+
+ return 0;
+
+netdev_init_failed:
+napi_add_failed:
+ dpa_generic_napi_del(netdev);
+ if (netdev)
+ free_percpu(priv->percpu_priv);
+alloc_percpu_failed:
+ if (netdev)
+ dpa_fq_free(dev, &priv->dpa_fq_list);
+fq_create_failed:
+ if (netdev) {
+ /* _dpa_bp_free(priv->rx_bp); */
+ /* _dpa_bp_free(priv->draining_tx_bp); */
+ }
+bp_create_failed:
+ dev_set_drvdata(dev, NULL);
+ if (netdev)
+ free_netdev(netdev);
+
+ return err;
+}
+
+static int __init __cold dpa_generic_load(void)
+{
+ int _errno;
+
+ pr_info(KBUILD_MODNAME ": " DPA_GENERIC_DESCRIPTION " (" VERSION ")\n");
+
+ /* initialise dpaa_eth mirror values */
+ dpa_rx_extra_headroom = fm_get_rx_extra_headroom();
+ dpa_max_frm = fm_get_max_frm();
+
+ _errno = platform_driver_register(&dpa_generic_driver);
+ if (unlikely(_errno < 0)) {
+ pr_err(KBUILD_MODNAME
+ ": %s:%hu:%s(): platform_driver_register() = %d\n",
+ KBUILD_BASENAME".c", __LINE__, __func__, _errno);
+ }
+
+ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n",
+ KBUILD_BASENAME".c", __func__);
+
+ return _errno;
+}
+
+/* waiting for all referenced ports to be initialized
+ * by other kernel modules (proxy ethernet, offline_port)
+ */
+late_initcall(dpa_generic_load);
+
+static void __exit __cold dpa_generic_unload(void)
+{
+ pr_debug(KBUILD_MODNAME ": -> %s:%s()\n",
+ KBUILD_BASENAME".c", __func__);
+
+ platform_driver_unregister(&dpa_generic_driver);
+
+ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n",
+ KBUILD_BASENAME".c", __func__);
+}
+module_exit(dpa_generic_unload);
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth_generic.h b/drivers/net/ethernet/freescale/dpa/dpaa_eth_generic.h
new file mode 100644
index 0000000..ea54c74
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth_generic.h
@@ -0,0 +1,82 @@
+/* Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DPA_ETH_GENERIC_H
+#define __DPA_ETH_GENERIC_H
+
+#include "lnxwrp_fsl_fman.h"
+#include "dpaa_eth.h"
+
+struct dpa_generic_priv_s {
+ struct net_device *net_dev;
+ /* use the same percpu_priv as other DPAA Ethernet drivers */
+ struct dpa_percpu_priv_s *percpu_priv;
+
+ /* up to 4 bps supported for RX */
+ int rx_bp_count;
+ struct dpa_bp *rx_bp;
+ struct dpa_buffer_layout_s *rx_buf_layout;
+
+ struct dpa_bp *draining_tx_bp;
+ struct dpa_buffer_layout_s *tx_buf_layout;
+
+ /* Store here the needed Tx headroom for convenience and speed
+ * (even though it can be computed based on the fields of buf_layout)
+ */
+ uint16_t tx_headroom;
+ uint16_t rx_headroom;
+
+ struct qman_fq *egress_fqs[DPAA_ETH_TX_QUEUES];
+
+ struct fm_port *rx_port;
+ struct fm_port *tx_port;
+
+ /* oNIC can have limited control capabilities over a MAC device */
+ struct mac_device *mac_dev;
+
+ uint16_t channel; /* "fsl,qman-channel-id" */
+ struct list_head dpa_fq_list;
+
+#ifdef CONFIG_FSL_DPAA_ETH_DEBUGFS
+ struct dentry *debugfs_file;
+#endif /* CONFIG_FSL_DPAA_ETH_DEBUGFS */
+
+ uint32_t msg_enable; /* net_device message level */
+
+ struct dpa_buffer_layout_s *buf_layout;
+ char if_type[30];
+};
+
+
+void dpaa_eth_generic_sysfs_init(struct device *dev);
+void dpaa_eth_generic_sysfs_remove(struct device *dev);
+
+#endif /* __DPA_ETH_GENERIC_H */
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth_generic_sysfs.c b/drivers/net/ethernet/freescale/dpa/dpaa_eth_generic_sysfs.c
new file mode 100644
index 0000000..912f615
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth_generic_sysfs.c
@@ -0,0 +1,201 @@
+/* Copyright 2014 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kthread.h>
+#include <linux/io.h>
+#include <linux/of_net.h>
+
+#include "dpaa_eth_generic.h"
+#include "mac.h" /* struct mac_device */
+
+static ssize_t dpaa_eth_generic_show_addr(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dpa_generic_priv_s *priv = netdev_priv(to_net_dev(dev));
+ struct mac_device *mac_dev = priv->mac_dev;
+
+ if (mac_dev)
+ return sprintf(buf, "%llx\n",
+ (unsigned long long)mac_dev->res->start);
+ else
+ return sprintf(buf, "none\n");
+}
+
+static ssize_t dpaa_eth_generic_show_type(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t res = 0;
+ res = sprintf(buf, "generic\n");
+
+ return res;
+}
+
+static ssize_t dpaa_eth_generic_show_fqids(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dpa_generic_priv_s *priv = netdev_priv(to_net_dev(dev));
+ ssize_t bytes = 0;
+ int i = 0;
+ char *str;
+ struct dpa_fq *fq;
+ struct dpa_fq *tmp;
+ struct dpa_fq *prev = NULL;
+ u32 first_fqid = 0;
+ u32 last_fqid = 0;
+ char *prevstr = NULL;
+
+ list_for_each_entry_safe(fq, tmp, &priv->dpa_fq_list, list) {
+ switch (fq->fq_type) {
+ case FQ_TYPE_RX_DEFAULT:
+ str = "Rx default";
+ break;
+ case FQ_TYPE_RX_ERROR:
+ str = "Rx error";
+ break;
+ case FQ_TYPE_RX_PCD:
+ str = "Rx PCD";
+ break;
+ case FQ_TYPE_TX_CONFIRM:
+ str = "Tx default confirmation";
+ break;
+ case FQ_TYPE_TX_CONF_MQ:
+ str = "Tx confirmation (mq)";
+ break;
+ case FQ_TYPE_TX_ERROR:
+ str = "Tx error";
+ break;
+ case FQ_TYPE_TX:
+ str = "Tx";
+ break;
+ default:
+ str = "Unknown";
+ }
+
+ if (prev && (abs(fq->fqid - prev->fqid) != 1 ||
+ str != prevstr)) {
+ if (last_fqid == first_fqid)
+ bytes += sprintf(buf + bytes,
+ "%s: %d\n", prevstr, prev->fqid);
+ else
+ bytes += sprintf(buf + bytes,
+ "%s: %d - %d\n", prevstr,
+ first_fqid, last_fqid);
+ }
+
+ if (prev && abs(fq->fqid - prev->fqid) == 1 && str == prevstr)
+ last_fqid = fq->fqid;
+ else
+ first_fqid = last_fqid = fq->fqid;
+
+ prev = fq;
+ prevstr = str;
+ i++;
+ }
+
+ if (prev) {
+ if (last_fqid == first_fqid)
+ bytes += sprintf(buf + bytes, "%s: %d\n", prevstr,
+ prev->fqid);
+ else
+ bytes += sprintf(buf + bytes, "%s: %d - %d\n", prevstr,
+ first_fqid, last_fqid);
+ }
+
+ return bytes;
+}
+
+static ssize_t dpaa_eth_generic_show_bpids(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t bytes = 0;
+ struct dpa_generic_priv_s *priv = netdev_priv(to_net_dev(dev));
+ struct dpa_bp *rx_bp = priv->rx_bp;
+ struct dpa_bp *draining_tx_bp = priv->draining_tx_bp;
+ int i = 0;
+
+ bytes += snprintf(buf + bytes, PAGE_SIZE, "Rx buffer pools:\n");
+ for (i = 0; i < priv->rx_bp_count; i++)
+ bytes += snprintf(buf + bytes, PAGE_SIZE, "%u ",
+ rx_bp[i].bpid);
+
+ bytes += snprintf(buf + bytes, PAGE_SIZE, "\n");
+ bytes += snprintf(buf + bytes, PAGE_SIZE, "Draining buffer pool:\n");
+ bytes += snprintf(buf + bytes, PAGE_SIZE, "%u\n", draining_tx_bp->bpid);
+
+ return bytes;
+}
+
+static ssize_t dpaa_eth_generic_show_mac_regs(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dpa_generic_priv_s *priv = netdev_priv(to_net_dev(dev));
+ struct mac_device *mac_dev = priv->mac_dev;
+ int n = 0;
+
+ if (mac_dev)
+ n = fm_mac_dump_regs(mac_dev, buf, n);
+ else
+ return sprintf(buf, "no mac control\n");
+
+ return n;
+}
+
+static struct device_attribute dpaa_eth_generic_attrs[] = {
+ __ATTR(device_addr, S_IRUGO, dpaa_eth_generic_show_addr, NULL),
+ __ATTR(device_type, S_IRUGO, dpaa_eth_generic_show_type, NULL),
+ __ATTR(fqids, S_IRUGO, dpaa_eth_generic_show_fqids, NULL),
+ __ATTR(bpids, S_IRUGO, dpaa_eth_generic_show_bpids, NULL),
+ __ATTR(mac_regs, S_IRUGO, dpaa_eth_generic_show_mac_regs, NULL),
+};
+
+void dpaa_eth_generic_sysfs_init(struct device *dev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(dpaa_eth_generic_attrs); i++)
+ if (device_create_file(dev, &dpaa_eth_generic_attrs[i])) {
+ dev_err(dev, "Error creating sysfs file\n");
+ while (i > 0)
+ device_remove_file(dev,
+ &dpaa_eth_generic_attrs[--i]);
+ return;
+ }
+}
+
+void dpaa_eth_generic_sysfs_remove(struct device *dev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(dpaa_eth_generic_attrs); i++)
+ device_remove_file(dev, &dpaa_eth_generic_attrs[i]);
+}
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth_macless.c b/drivers/net/ethernet/freescale/dpa/dpaa_eth_macless.c
new file mode 100644
index 0000000..56bf16b
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth_macless.c
@@ -0,0 +1,516 @@
+/* Copyright 2008-2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef CONFIG_FSL_DPAA_ETH_DEBUG
+#define pr_fmt(fmt) \
+ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \
+ KBUILD_BASENAME".c", __LINE__, __func__
+#else
+#define pr_fmt(fmt) \
+ KBUILD_MODNAME ": " fmt
+#endif
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_net.h>
+#include <linux/etherdevice.h>
+#include <linux/kthread.h>
+#include <linux/percpu.h>
+#include <linux/highmem.h>
+#include <linux/fsl_qman.h>
+#include "dpaa_eth.h"
+#include "dpaa_eth_common.h"
+#include "dpaa_eth_base.h"
+#include "lnxwrp_fsl_fman.h" /* fm_get_rx_extra_headroom(), fm_get_max_frm() */
+#include "mac.h"
+
+/* For MAC-based interfaces, we compute the tx needed headroom from the
+ * associated Tx port's buffer layout settings.
+ * For MACless interfaces just use a default value.
+ */
+#define DPA_DEFAULT_TX_HEADROOM 64
+
+#define DPA_DESCRIPTION "FSL DPAA MACless Ethernet driver"
+
+MODULE_LICENSE("Dual BSD/GPL");
+
+MODULE_DESCRIPTION(DPA_DESCRIPTION);
+
+static uint8_t debug = -1;
+module_param(debug, byte, S_IRUGO);
+MODULE_PARM_DESC(debug, "Module/Driver verbosity level");
+
+/* This has to work in tandem with the DPA_CS_THRESHOLD_xxx values. */
+static uint16_t tx_timeout = 1000;
+module_param(tx_timeout, ushort, S_IRUGO);
+MODULE_PARM_DESC(tx_timeout, "The Tx timeout in ms");
+
+/* reused from the shared driver */
+extern const struct dpa_fq_cbs_t shared_fq_cbs;
+int __hot dpa_shared_tx(struct sk_buff *skb, struct net_device *net_dev);
+
+/* forward declarations */
+static int __cold dpa_macless_start(struct net_device *net_dev);
+static int __cold dpa_macless_stop(struct net_device *net_dev);
+static int __cold dpa_macless_set_address(struct net_device *net_dev,
+ void *addr);
+static void __cold dpa_macless_set_rx_mode(struct net_device *net_dev);
+
+static int dpaa_eth_macless_probe(struct platform_device *_of_dev);
+static netdev_features_t
+dpa_macless_fix_features(struct net_device *dev, netdev_features_t features);
+static int dpa_macless_netdev_init(struct device_node *dpa_node,
+ struct net_device *net_dev);
+
+static const struct net_device_ops dpa_macless_ops = {
+ .ndo_open = dpa_macless_start,
+ .ndo_start_xmit = dpa_shared_tx,
+ .ndo_stop = dpa_macless_stop,
+ .ndo_tx_timeout = dpa_timeout,
+ .ndo_get_stats64 = dpa_get_stats64,
+ .ndo_set_mac_address = dpa_macless_set_address,
+ .ndo_set_rx_mode = dpa_macless_set_rx_mode,
+ .ndo_validate_addr = eth_validate_addr,
+#ifdef CONFIG_FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE
+ .ndo_select_queue = dpa_select_queue,
+#endif
+ .ndo_change_mtu = dpa_change_mtu,
+ .ndo_init = dpa_ndo_init,
+ .ndo_set_features = dpa_set_features,
+ .ndo_fix_features = dpa_macless_fix_features,
+};
+
+static const struct of_device_id dpa_macless_match[] = {
+ {
+ .compatible = "fsl,dpa-ethernet-macless"
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, dpa_macless_match);
+
+static struct platform_driver dpa_macless_driver = {
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .of_match_table = dpa_macless_match,
+ .owner = THIS_MODULE,
+ },
+ .probe = dpaa_eth_macless_probe,
+ .remove = dpa_remove
+};
+
+static const char macless_frame_queues[][25] = {
+ [RX] = "fsl,qman-frame-queues-rx",
+ [TX] = "fsl,qman-frame-queues-tx"
+};
+
+static int __cold dpa_macless_start(struct net_device *net_dev)
+{
+ const struct dpa_priv_s *priv = netdev_priv(net_dev);
+ struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer;
+
+ netif_tx_start_all_queues(net_dev);
+
+ if (proxy_dev)
+ dpa_proxy_start(net_dev);
+
+
+ return 0;
+}
+
+static int __cold dpa_macless_stop(struct net_device *net_dev)
+{
+ const struct dpa_priv_s *priv = netdev_priv(net_dev);
+ struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer;
+
+ netif_tx_stop_all_queues(net_dev);
+
+ if (proxy_dev)
+ dpa_proxy_stop(proxy_dev, net_dev);
+
+ return 0;
+}
+
+static int dpa_macless_set_address(struct net_device *net_dev, void *addr)
+{
+ const struct dpa_priv_s *priv = netdev_priv(net_dev);
+ struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer;
+ int _errno;
+
+ _errno = eth_mac_addr(net_dev, addr);
+ if (_errno < 0) {
+ if (netif_msg_drv(priv))
+ netdev_err(net_dev, "eth_mac_addr() = %d\n", _errno);
+ return _errno;
+ }
+
+ if (proxy_dev) {
+ _errno = dpa_proxy_set_mac_address(proxy_dev, net_dev);
+ if (_errno < 0) {
+ if (netif_msg_drv(priv))
+ netdev_err(net_dev, "proxy_set_mac_address() = %d\n",
+ _errno);
+ return _errno;
+ }
+ }
+
+ return 0;
+}
+
+static void __cold dpa_macless_set_rx_mode(struct net_device *net_dev)
+{
+ const struct dpa_priv_s *priv = netdev_priv(net_dev);
+ struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer;
+
+ if (proxy_dev)
+ dpa_proxy_set_rx_mode(proxy_dev, net_dev);
+}
+
+static netdev_features_t
+dpa_macless_fix_features(struct net_device *dev, netdev_features_t features)
+{
+ netdev_features_t unsupported_features = 0;
+
+ /* In theory we should never be requested to enable features that
+ * we didn't set in netdev->features and netdev->hw_features at probe
+ * time, but double check just to be on the safe side.
+ */
+ unsupported_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+ /* We don't support enabling Rx csum through ethtool yet */
+ unsupported_features |= NETIF_F_RXCSUM;
+
+ features &= ~unsupported_features;
+
+ return features;
+}
+
+static int dpa_macless_netdev_init(struct device_node *dpa_node,
+ struct net_device *net_dev)
+{
+ struct dpa_priv_s *priv = netdev_priv(net_dev);
+ struct proxy_device *proxy_dev = (struct proxy_device *)priv->peer;
+ struct device *dev = net_dev->dev.parent;
+ const uint8_t *mac_addr;
+
+ net_dev->netdev_ops = &dpa_macless_ops;
+
+ if (proxy_dev) {
+ struct mac_device *mac_dev = proxy_dev->mac_dev;
+ net_dev->mem_start = mac_dev->res->start;
+ net_dev->mem_end = mac_dev->res->end;
+
+ return dpa_netdev_init(dpa_node, net_dev, mac_dev->addr,
+ tx_timeout);
+ } else {
+ /* Get the MAC address from device tree */
+ mac_addr = of_get_mac_address(dpa_node);
+
+ if (mac_addr == NULL) {
+ if (netif_msg_probe(priv))
+ dev_err(dev, "No MAC address found!\n");
+ return -EINVAL;
+ }
+
+ return dpa_netdev_init(dpa_node, net_dev, mac_addr,
+ tx_timeout);
+ }
+}
+
+/* Probing of FQs for MACless ports */
+static int dpa_fq_probe_macless(struct device *dev, struct list_head *list,
+ enum port_type ptype)
+{
+ struct device_node *np = dev->of_node;
+ const struct fqid_cell *fqids;
+ int num_ranges;
+ int i, lenp;
+
+ fqids = of_get_property(np, macless_frame_queues[ptype], &lenp);
+ if (fqids == NULL) {
+ dev_err(dev, "Need FQ definition in dts for MACless devices\n");
+ return -EINVAL;
+ }
+
+ num_ranges = lenp / sizeof(*fqids);
+
+ /* All ranges defined in the device tree are used as Rx/Tx queues */
+ for (i = 0; i < num_ranges; i++) {
+ if (!dpa_fq_alloc(dev, &fqids[i], list, ptype == RX ?
+ FQ_TYPE_RX_PCD : FQ_TYPE_TX)) {
+ dev_err(dev, "_dpa_fq_alloc() failed\n");
+ return -ENOMEM;
+ }
+ }
+
+ return 0;
+}
+
+struct proxy_device *dpa_macless_proxy_probe(struct platform_device *_of_dev)
+{
+ struct device *dev;
+ const phandle *proxy_prop;
+ struct proxy_device *proxy_dev;
+ struct device_node *proxy_node;
+ struct platform_device *proxy_pdev;
+ int lenp;
+
+ dev = &_of_dev->dev;
+
+ proxy_prop = of_get_property(dev->of_node, "proxy", &lenp);
+ if (!proxy_prop)
+ return NULL;
+
+ proxy_node = of_find_node_by_phandle(*proxy_prop);
+ if (!proxy_node) {
+ dev_err(dev, "Cannot find proxy node\n");
+ return NULL;
+ }
+
+ proxy_pdev = of_find_device_by_node(proxy_node);
+ if (!proxy_pdev) {
+ of_node_put(proxy_node);
+ dev_err(dev, "Cannot find device represented by proxy node\n");
+ return NULL;
+ }
+
+ proxy_dev = dev_get_drvdata(&proxy_pdev->dev);
+
+ of_node_put(proxy_node);
+
+ return proxy_dev;
+}
+
+static int dpaa_eth_macless_probe(struct platform_device *_of_dev)
+{
+ int err = 0, i;
+ struct device *dev;
+ struct device_node *dpa_node;
+ struct dpa_bp *dpa_bp;
+ struct dpa_fq *dpa_fq, *tmp;
+ size_t count;
+ struct net_device *net_dev = NULL;
+ struct dpa_priv_s *priv = NULL;
+ struct dpa_percpu_priv_s *percpu_priv;
+ static struct proxy_device *proxy_dev;
+ struct fm_port_fqs port_fqs;
+ struct task_struct *kth;
+ static u8 macless_idx;
+
+ dev = &_of_dev->dev;
+
+ dpa_node = dev->of_node;
+
+ if (!of_device_is_available(dpa_node))
+ return -ENODEV;
+
+ /* Get the buffer pools assigned to this interface */
+ dpa_bp = dpa_bp_probe(_of_dev, &count);
+ if (IS_ERR(dpa_bp))
+ return PTR_ERR(dpa_bp);
+
+ for (i = 0; i < count; i++)
+ dpa_bp[i].seed_cb = dpa_bp_shared_port_seed;
+
+ proxy_dev = dpa_macless_proxy_probe(_of_dev);
+
+
+ /* Allocate this early, so we can store relevant information in
+ * the private area (needed by 1588 code in dpa_mac_probe)
+ */
+ net_dev = alloc_etherdev_mq(sizeof(*priv), DPAA_ETH_TX_QUEUES);
+ if (!net_dev) {
+ dev_err(dev, "alloc_etherdev_mq() failed\n");
+ return -ENOMEM;
+ }
+
+ /* Do this here, so we can be verbose early */
+ SET_NETDEV_DEV(net_dev, dev);
+ dev_set_drvdata(dev, net_dev);
+
+ priv = netdev_priv(net_dev);
+ priv->net_dev = net_dev;
+ sprintf(priv->if_type, "macless%d", macless_idx++);
+
+ priv->msg_enable = netif_msg_init(debug, -1);
+
+ priv->peer = NULL;
+ priv->mac_dev = NULL;
+ if (proxy_dev) {
+ /* This is a temporary solution for the need of
+ * having main driver upstreamability: adjust_link
+ * is a general function that should work for both
+ * private driver and macless driver with MAC device
+ * control capabilities even if the last will not be
+ * upstreamable.
+ * TODO: find a convenient solution (wrapper over
+ * main priv structure, etc.)
+ */
+ priv->mac_dev = proxy_dev->mac_dev;
+
+ /* control over proxy's mac device */
+ priv->peer = (void *)proxy_dev;
+ }
+
+ INIT_LIST_HEAD(&priv->dpa_fq_list);
+
+ memset(&port_fqs, 0, sizeof(port_fqs));
+
+ err = dpa_fq_probe_macless(dev, &priv->dpa_fq_list, RX);
+ if (!err)
+ err = dpa_fq_probe_macless(dev, &priv->dpa_fq_list,
+ TX);
+ if (err < 0)
+ goto fq_probe_failed;
+
+ /* bp init */
+ priv->bp_count = count;
+ err = dpa_bp_create(net_dev, dpa_bp, count);
+ if (err < 0)
+ goto bp_create_failed;
+
+ priv->channel = dpa_get_channel();
+
+ if (priv->channel < 0) {
+ err = priv->channel;
+ goto get_channel_failed;
+ }
+
+ /* Start a thread that will walk the cpus with affine portals
+ * and add this pool channel to each's dequeue mask.
+ */
+ kth = kthread_run(dpaa_eth_add_channel,
+ (void *)(unsigned long)priv->channel,
+ "dpaa_%p:%d", net_dev, priv->channel);
+ if (!kth) {
+ err = -ENOMEM;
+ goto add_channel_failed;
+ }
+
+ dpa_fq_setup(priv, &shared_fq_cbs, NULL);
+
+ /* Add the FQs to the interface, and make them active */
+ list_for_each_entry_safe(dpa_fq, tmp, &priv->dpa_fq_list, list) {
+ /* For MAC-less devices we only get here for RX frame queues
+ * initialization, which are the TX queues of the other
+ * partition.
+ * It is safe to rely on one partition to set the FQ taildrop
+ * threshold for the TX queues of the other partition
+ * because the ERN notifications will be received by the
+ * partition doing qman_enqueue.
+ */
+ err = dpa_fq_init(dpa_fq, true);
+ if (err < 0)
+ goto fq_alloc_failed;
+ }
+
+ priv->tx_headroom = DPA_DEFAULT_TX_HEADROOM;
+
+ priv->percpu_priv = alloc_percpu(*priv->percpu_priv);
+
+ if (priv->percpu_priv == NULL) {
+ dev_err(dev, "alloc_percpu() failed\n");
+ err = -ENOMEM;
+ goto alloc_percpu_failed;
+ }
+ for_each_possible_cpu(i) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+ memset(percpu_priv, 0, sizeof(*percpu_priv));
+ }
+
+ err = dpa_macless_netdev_init(dpa_node, net_dev);
+ if (err < 0)
+ goto netdev_init_failed;
+
+ dpaa_eth_sysfs_init(&net_dev->dev);
+
+ pr_info("fsl_dpa_macless: Probed %s interface as %s\n",
+ priv->if_type, net_dev->name);
+
+ return 0;
+
+netdev_init_failed:
+ if (net_dev)
+ free_percpu(priv->percpu_priv);
+alloc_percpu_failed:
+fq_alloc_failed:
+ if (net_dev) {
+ dpa_fq_free(dev, &priv->dpa_fq_list);
+ qman_release_cgrid(priv->cgr_data.cgr.cgrid);
+ qman_delete_cgr(&priv->cgr_data.cgr);
+ }
+add_channel_failed:
+get_channel_failed:
+ if (net_dev)
+ dpa_bp_free(priv, priv->dpa_bp);
+bp_create_failed:
+fq_probe_failed:
+ dev_set_drvdata(dev, NULL);
+ if (net_dev)
+ free_netdev(net_dev);
+
+ return err;
+}
+
+static int __init __cold dpa_macless_load(void)
+{
+ int _errno;
+
+ pr_info(DPA_DESCRIPTION " (" VERSION ")\n");
+
+ /* Initialize dpaa_eth mirror values */
+ dpa_rx_extra_headroom = fm_get_rx_extra_headroom();
+ dpa_max_frm = fm_get_max_frm();
+
+ _errno = platform_driver_register(&dpa_macless_driver);
+ if (unlikely(_errno < 0)) {
+ pr_err(KBUILD_MODNAME
+ ": %s:%hu:%s(): platform_driver_register() = %d\n",
+ KBUILD_BASENAME".c", __LINE__, __func__, _errno);
+ }
+
+ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n",
+ KBUILD_BASENAME".c", __func__);
+
+ return _errno;
+}
+/* waits for proxy to initialize first, in case MAC device reference
+ * is needed
+ */
+late_initcall(dpa_macless_load);
+
+static void __exit __cold dpa_macless_unload(void)
+{
+ platform_driver_unregister(&dpa_macless_driver);
+
+ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n",
+ KBUILD_BASENAME".c", __func__);
+}
+module_exit(dpa_macless_unload);
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth_proxy.c b/drivers/net/ethernet/freescale/dpa/dpaa_eth_proxy.c
new file mode 100644
index 0000000..a06465a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth_proxy.c
@@ -0,0 +1,372 @@
+/* Copyright 2008-2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef CONFIG_FSL_DPAA_ETH_DEBUG
+#define pr_fmt(fmt) \
+ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \
+ KBUILD_BASENAME".c", __LINE__, __func__
+#else
+#define pr_fmt(fmt) \
+ KBUILD_MODNAME ": " fmt
+#endif
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include "dpaa_eth.h"
+#include "dpaa_eth_common.h"
+#include "dpaa_eth_base.h"
+#include "lnxwrp_fsl_fman.h" /* fm_get_rx_extra_headroom(), fm_get_max_frm() */
+#include "mac.h"
+
+#define DPA_DESCRIPTION "FSL DPAA Proxy initialization driver"
+
+MODULE_LICENSE("Dual BSD/GPL");
+
+MODULE_DESCRIPTION(DPA_DESCRIPTION);
+
+static uint8_t debug = -1;
+module_param(debug, byte, S_IRUGO);
+MODULE_PARM_DESC(debug, "Module/Driver verbosity level");
+
+static int __cold dpa_eth_proxy_remove(struct platform_device *of_dev);
+#ifdef CONFIG_PM
+
+static int proxy_suspend_noirq(struct device *dev)
+{
+ struct proxy_device *proxy_dev = dev_get_drvdata(dev);
+ struct mac_device *mac_dev = proxy_dev->mac_dev;
+ int err = 0;
+
+ err = fm_port_suspend(mac_dev->port_dev[RX]);
+ if (err)
+ goto port_suspend_failed;
+
+ err = fm_port_suspend(mac_dev->port_dev[TX]);
+ if (err)
+ err = fm_port_resume(mac_dev->port_dev[RX]);
+
+port_suspend_failed:
+ return err;
+}
+
+static int proxy_resume_noirq(struct device *dev)
+{
+ struct proxy_device *proxy_dev = dev_get_drvdata(dev);
+ struct mac_device *mac_dev = proxy_dev->mac_dev;
+ int err = 0;
+
+ err = fm_port_resume(mac_dev->port_dev[TX]);
+ if (err)
+ goto port_resume_failed;
+
+ err = fm_port_resume(mac_dev->port_dev[RX]);
+ if (err)
+ err = fm_port_suspend(mac_dev->port_dev[TX]);
+
+port_resume_failed:
+ return err;
+}
+
+static const struct dev_pm_ops proxy_pm_ops = {
+ .suspend_noirq = proxy_suspend_noirq,
+ .resume_noirq = proxy_resume_noirq,
+};
+
+#define PROXY_PM_OPS (&proxy_pm_ops)
+
+#else /* CONFIG_PM */
+
+#define PROXY_PM_OPS NULL
+
+#endif /* CONFIG_PM */
+
+static int dpaa_eth_proxy_probe(struct platform_device *_of_dev)
+{
+ int err = 0, i;
+ struct device *dev;
+ struct device_node *dpa_node;
+ struct dpa_bp *dpa_bp;
+ struct list_head proxy_fq_list;
+ size_t count;
+ struct fm_port_fqs port_fqs;
+ struct dpa_buffer_layout_s *buf_layout = NULL;
+ struct mac_device *mac_dev;
+ struct proxy_device *proxy_dev;
+
+ dev = &_of_dev->dev;
+
+ dpa_node = dev->of_node;
+
+ if (!of_device_is_available(dpa_node))
+ return -ENODEV;
+
+ /* Get the buffer pools assigned to this interface */
+ dpa_bp = dpa_bp_probe(_of_dev, &count);
+ if (IS_ERR(dpa_bp))
+ return PTR_ERR(dpa_bp);
+
+ mac_dev = dpa_mac_probe(_of_dev);
+ if (IS_ERR(mac_dev))
+ return PTR_ERR(mac_dev);
+
+ proxy_dev = devm_kzalloc(dev, sizeof(*proxy_dev), GFP_KERNEL);
+ if (!proxy_dev) {
+ dev_err(dev, "devm_kzalloc() failed\n");
+ return -ENOMEM;
+ }
+
+ proxy_dev->mac_dev = mac_dev;
+ dev_set_drvdata(dev, proxy_dev);
+
+ /* We have physical ports, so we need to establish
+ * the buffer layout.
+ */
+ buf_layout = devm_kzalloc(dev, 2 * sizeof(*buf_layout),
+ GFP_KERNEL);
+ if (!buf_layout) {
+ dev_err(dev, "devm_kzalloc() failed\n");
+ return -ENOMEM;
+ }
+ dpa_set_buffers_layout(mac_dev, buf_layout);
+
+ INIT_LIST_HEAD(&proxy_fq_list);
+
+ memset(&port_fqs, 0, sizeof(port_fqs));
+
+ err = dpa_fq_probe_mac(dev, &proxy_fq_list, &port_fqs, true, RX);
+ if (!err)
+ err = dpa_fq_probe_mac(dev, &proxy_fq_list, &port_fqs, true,
+ TX);
+ if (err < 0) {
+ devm_kfree(dev, buf_layout);
+ return err;
+ }
+
+ /* Proxy initializer - Just configures the MAC on behalf of
+ * another partition.
+ */
+ dpaa_eth_init_ports(mac_dev, dpa_bp, count, &port_fqs,
+ buf_layout, dev);
+
+ /* Proxy interfaces need to be started, and the allocated
+ * memory freed
+ */
+ devm_kfree(dev, buf_layout);
+ devm_kfree(dev, dpa_bp);
+
+ /* Free FQ structures */
+ devm_kfree(dev, port_fqs.rx_defq);
+ devm_kfree(dev, port_fqs.rx_errq);
+ devm_kfree(dev, port_fqs.tx_defq);
+ devm_kfree(dev, port_fqs.tx_errq);
+
+ for_each_port_device(i, mac_dev->port_dev) {
+ err = fm_port_enable(mac_dev->port_dev[i]);
+ if (err)
+ goto port_enable_fail;
+ }
+
+ dev_info(dev, "probed MAC device with MAC address: %02hx:%02hx:%02hx:%02hx:%02hx:%02hx\n",
+ mac_dev->addr[0], mac_dev->addr[1], mac_dev->addr[2],
+ mac_dev->addr[3], mac_dev->addr[4], mac_dev->addr[5]);
+
+ return 0; /* Proxy interface initialization ended */
+
+port_enable_fail:
+ for_each_port_device(i, mac_dev->port_dev)
+ fm_port_disable(mac_dev->port_dev[i]);
+ dpa_eth_proxy_remove(_of_dev);
+
+ return err;
+}
+
+int dpa_proxy_set_mac_address(struct proxy_device *proxy_dev,
+ struct net_device *net_dev)
+{
+ struct mac_device *mac_dev;
+ int _errno;
+
+ mac_dev = proxy_dev->mac_dev;
+
+ _errno = mac_dev->change_addr(mac_dev->get_mac_handle(mac_dev),
+ net_dev->dev_addr);
+ if (_errno < 0)
+ return _errno;
+
+ return 0;
+}
+
+int dpa_proxy_set_rx_mode(struct proxy_device *proxy_dev,
+ struct net_device *net_dev)
+{
+ struct mac_device *mac_dev = proxy_dev->mac_dev;
+ int _errno;
+
+ _errno = mac_dev->set_multi(net_dev, mac_dev);
+ if (unlikely(_errno < 0))
+ return _errno;
+
+ return 0;
+}
+
+int dpa_proxy_start(struct net_device *net_dev)
+{
+ struct mac_device *mac_dev;
+ const struct dpa_priv_s *priv;
+ struct proxy_device *proxy_dev;
+ int _errno;
+ int i;
+
+ priv = netdev_priv(net_dev);
+ proxy_dev = (struct proxy_device *)priv->peer;
+ mac_dev = proxy_dev->mac_dev;
+
+ _errno = mac_dev->init_phy(net_dev, mac_dev);
+ if (_errno < 0) {
+ if (netif_msg_drv(priv))
+ netdev_err(net_dev, "init_phy() = %d\n",
+ _errno);
+ return _errno;
+ }
+
+ for_each_port_device(i, mac_dev->port_dev) {
+ _errno = fm_port_enable(mac_dev->port_dev[i]);
+ if (_errno)
+ goto port_enable_fail;
+ }
+
+ _errno = mac_dev->start(mac_dev);
+ if (_errno < 0) {
+ if (netif_msg_drv(priv))
+ netdev_err(net_dev, "mac_dev->start() = %d\n",
+ _errno);
+ goto port_enable_fail;
+ }
+
+ return _errno;
+
+port_enable_fail:
+ for_each_port_device(i, mac_dev->port_dev)
+ fm_port_disable(mac_dev->port_dev[i]);
+
+ return _errno;
+}
+
+int dpa_proxy_stop(struct proxy_device *proxy_dev, struct net_device *net_dev)
+{
+ struct mac_device *mac_dev = proxy_dev->mac_dev;
+ const struct dpa_priv_s *priv = netdev_priv(net_dev);
+ int _errno, i, err;
+
+ _errno = mac_dev->stop(mac_dev);
+ if (_errno < 0) {
+ if (netif_msg_drv(priv))
+ netdev_err(net_dev, "mac_dev->stop() = %d\n",
+ _errno);
+ return _errno;
+ }
+
+ for_each_port_device(i, mac_dev->port_dev) {
+ err = fm_port_disable(mac_dev->port_dev[i]);
+ _errno = err ? err : _errno;
+ }
+
+ if (mac_dev->phy_dev)
+ phy_disconnect(mac_dev->phy_dev);
+ mac_dev->phy_dev = NULL;
+
+ return _errno;
+}
+
+static int __cold dpa_eth_proxy_remove(struct platform_device *of_dev)
+{
+ struct device *dev = &of_dev->dev;
+ struct proxy_device *proxy_dev = dev_get_drvdata(dev);
+
+ kfree(proxy_dev);
+
+ dev_set_drvdata(dev, NULL);
+
+ return 0;
+}
+
+static const struct of_device_id dpa_proxy_match[] = {
+ {
+ .compatible = "fsl,dpa-ethernet-init"
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, dpa_proxy_match);
+
+static struct platform_driver dpa_proxy_driver = {
+ .driver = {
+ .name = KBUILD_MODNAME"-proxy",
+ .of_match_table = dpa_proxy_match,
+ .owner = THIS_MODULE,
+ .pm = PROXY_PM_OPS,
+ },
+ .probe = dpaa_eth_proxy_probe,
+ .remove = dpa_eth_proxy_remove
+};
+
+static int __init __cold dpa_proxy_load(void)
+{
+ int _errno;
+
+ pr_info(DPA_DESCRIPTION " (" VERSION ")\n");
+
+ /* Initialize dpaa_eth mirror values */
+ dpa_rx_extra_headroom = fm_get_rx_extra_headroom();
+ dpa_max_frm = fm_get_max_frm();
+
+ _errno = platform_driver_register(&dpa_proxy_driver);
+ if (unlikely(_errno < 0)) {
+ pr_err(KBUILD_MODNAME
+ ": %s:%hu:%s(): platform_driver_register() = %d\n",
+ KBUILD_BASENAME".c", __LINE__, __func__, _errno);
+ }
+
+ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n",
+ KBUILD_BASENAME".c", __func__);
+
+ return _errno;
+}
+module_init(dpa_proxy_load);
+
+static void __exit __cold dpa_proxy_unload(void)
+{
+ platform_driver_unregister(&dpa_proxy_driver);
+
+ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n",
+ KBUILD_BASENAME".c", __func__);
+}
+module_exit(dpa_proxy_unload);
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth_sg.c b/drivers/net/ethernet/freescale/dpa/dpaa_eth_sg.c
new file mode 100644
index 0000000..7e15013
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth_sg.c
@@ -0,0 +1,941 @@
+/* Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef CONFIG_FSL_DPAA_ETH_DEBUG
+#define pr_fmt(fmt) \
+ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \
+ KBUILD_BASENAME".c", __LINE__, __func__
+#else
+#define pr_fmt(fmt) \
+ KBUILD_MODNAME ": " fmt
+#endif
+
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/highmem.h>
+#include <linux/fsl_bman.h>
+
+#include "dpaa_eth.h"
+#include "dpaa_eth_common.h"
+#ifdef CONFIG_FSL_DPAA_1588
+#include "dpaa_1588.h"
+#endif
+
+/* Convenience macros for storing/retrieving the skb back-pointers. They must
+ * accommodate both recycling and confirmation paths - i.e. cases when the buf
+ * was allocated by ourselves, respectively by the stack. In the former case,
+ * we could store the skb at negative offset; in the latter case, we can't,
+ * so we'll use 0 as offset.
+ *
+ * NB: @off is an offset from a (struct sk_buff **) pointer!
+ */
+#define DPA_WRITE_SKB_PTR(skb, skbh, addr, off) \
+ { \
+ skbh = (struct sk_buff **)addr; \
+ *(skbh + (off)) = skb; \
+ }
+#define DPA_READ_SKB_PTR(skb, skbh, addr, off) \
+ { \
+ skbh = (struct sk_buff **)addr; \
+ skb = *(skbh + (off)); \
+ }
+
+/* DMA map and add a page frag back into the bpool.
+ * @vaddr fragment must have been allocated with netdev_alloc_frag(),
+ * specifically for fitting into @dpa_bp.
+ */
+static void dpa_bp_recycle_frag(struct dpa_bp *dpa_bp, unsigned long vaddr,
+ int *count_ptr)
+{
+ struct bm_buffer bmb;
+ dma_addr_t addr;
+
+ addr = dma_map_single(dpa_bp->dev, (void *)vaddr, dpa_bp->size,
+ DMA_BIDIRECTIONAL);
+ if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) {
+ dev_err(dpa_bp->dev, "DMA mapping failed");
+ return;
+ }
+
+ bm_buffer_set64(&bmb, addr);
+
+ while (bman_release(dpa_bp->pool, &bmb, 1, 0))
+ cpu_relax();
+
+ (*count_ptr)++;
+}
+
+static int _dpa_bp_add_8_bufs(const struct dpa_bp *dpa_bp)
+{
+ struct bm_buffer bmb[8];
+ void *new_buf;
+ dma_addr_t addr;
+ uint8_t i;
+ struct device *dev = dpa_bp->dev;
+ struct sk_buff *skb, **skbh;
+
+ for (i = 0; i < 8; i++) {
+ /* We'll prepend the skb back-pointer; can't use the DPA
+ * priv space, because FMan will overwrite it (from offset 0)
+ * if it ends up being the second, third, etc. fragment
+ * in a S/G frame.
+ *
+ * We only need enough space to store a pointer, but allocate
+ * an entire cacheline for performance reasons.
+ */
+ new_buf = netdev_alloc_frag(SMP_CACHE_BYTES + DPA_BP_RAW_SIZE);
+ if (unlikely(!new_buf))
+ goto netdev_alloc_failed;
+ new_buf = PTR_ALIGN(new_buf + SMP_CACHE_BYTES, SMP_CACHE_BYTES);
+
+ skb = build_skb(new_buf, DPA_SKB_SIZE(dpa_bp->size) +
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info)));
+ if (unlikely(!skb)) {
+ put_page(virt_to_head_page(new_buf));
+ goto build_skb_failed;
+ }
+ DPA_WRITE_SKB_PTR(skb, skbh, new_buf, -1);
+
+ addr = dma_map_single(dev, new_buf,
+ dpa_bp->size, DMA_BIDIRECTIONAL);
+ if (unlikely(dma_mapping_error(dev, addr)))
+ goto dma_map_failed;
+
+ bm_buffer_set64(&bmb[i], addr);
+ }
+
+release_bufs:
+ /* Release the buffers. In case bman is busy, keep trying
+ * until successful. bman_release() is guaranteed to succeed
+ * in a reasonable amount of time
+ */
+ while (unlikely(bman_release(dpa_bp->pool, bmb, i, 0)))
+ cpu_relax();
+ return i;
+
+dma_map_failed:
+ kfree_skb(skb);
+
+build_skb_failed:
+netdev_alloc_failed:
+ net_err_ratelimited("dpa_bp_add_8_bufs() failed\n");
+ WARN_ONCE(1, "Memory allocation failure on Rx\n");
+
+ bm_buffer_set64(&bmb[i], 0);
+ /* Avoid releasing a completely null buffer; bman_release() requires
+ * at least one buffer.
+ */
+ if (likely(i))
+ goto release_bufs;
+
+ return 0;
+}
+
+/* Cold path wrapper over _dpa_bp_add_8_bufs(). */
+static void dpa_bp_add_8_bufs(const struct dpa_bp *dpa_bp, int cpu)
+{
+ int *count_ptr = per_cpu_ptr(dpa_bp->percpu_count, cpu);
+ *count_ptr += _dpa_bp_add_8_bufs(dpa_bp);
+}
+
+int dpa_bp_priv_seed(struct dpa_bp *dpa_bp)
+{
+ int i;
+
+ /* Give each CPU an allotment of "config_count" buffers */
+ for_each_possible_cpu(i) {
+ int j;
+
+ /* Although we access another CPU's counters here
+ * we do it at boot time so it is safe
+ */
+ for (j = 0; j < dpa_bp->config_count; j += 8)
+ dpa_bp_add_8_bufs(dpa_bp, i);
+ }
+ return 0;
+}
+
+/* Add buffers/(pages) for Rx processing whenever bpool count falls below
+ * REFILL_THRESHOLD.
+ */
+int dpaa_eth_refill_bpools(struct dpa_bp *dpa_bp, int *countptr)
+{
+ int count = *countptr;
+ int new_bufs;
+
+ if (unlikely(count < CONFIG_FSL_DPAA_ETH_REFILL_THRESHOLD)) {
+ do {
+ new_bufs = _dpa_bp_add_8_bufs(dpa_bp);
+ if (unlikely(!new_bufs)) {
+ /* Avoid looping forever if we've temporarily
+ * run out of memory. We'll try again at the
+ * next NAPI cycle.
+ */
+ break;
+ }
+ count += new_bufs;
+ } while (count < CONFIG_FSL_DPAA_ETH_MAX_BUF_COUNT);
+
+ *countptr = count;
+ if (unlikely(count < CONFIG_FSL_DPAA_ETH_MAX_BUF_COUNT))
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+/* Cleanup function for outgoing frame descriptors that were built on Tx path,
+ * either contiguous frames or scatter/gather ones.
+ * Skb freeing is not handled here.
+ *
+ * This function may be called on error paths in the Tx function, so guard
+ * against cases when not all fd relevant fields were filled in.
+ *
+ * Return the skb backpointer, since for S/G frames the buffer containing it
+ * gets freed here.
+ */
+struct sk_buff *_dpa_cleanup_tx_fd(const struct dpa_priv_s *priv,
+ const struct qm_fd *fd)
+{
+ const struct qm_sg_entry *sgt;
+ int i;
+ struct dpa_bp *dpa_bp = priv->dpa_bp;
+ dma_addr_t addr = qm_fd_addr(fd);
+ struct sk_buff **skbh;
+ struct sk_buff *skb = NULL;
+ const enum dma_data_direction dma_dir = DMA_TO_DEVICE;
+ int nr_frags;
+
+ DPA_BUG_ON(fd->cmd & FM_FD_CMD_FCO);
+ dma_unmap_single(dpa_bp->dev, addr, dpa_bp->size, dma_dir);
+
+ /* retrieve skb back pointer */
+ DPA_READ_SKB_PTR(skb, skbh, phys_to_virt(addr), 0);
+ nr_frags = skb_shinfo(skb)->nr_frags;
+
+ if (fd->format == qm_fd_sg) {
+ /* The sgt buffer has been allocated with netdev_alloc_frag(),
+ * it's from lowmem.
+ */
+ sgt = phys_to_virt(addr + dpa_fd_offset(fd));
+#ifdef CONFIG_FSL_DPAA_1588
+ if (priv->tsu && priv->tsu->valid &&
+ priv->tsu->hwts_tx_en_ioctl)
+ dpa_ptp_store_txstamp(priv, skb, (void *)skbh);
+#endif
+#ifdef CONFIG_FSL_DPAA_TS
+ if (unlikely(priv->ts_tx_en &&
+ skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
+ struct skb_shared_hwtstamps shhwtstamps;
+
+ dpa_get_ts(priv, TX, &shhwtstamps, (void *)skbh);
+ skb_tstamp_tx(skb, &shhwtstamps);
+ }
+#endif /* CONFIG_FSL_DPAA_TS */
+
+ /* sgt[0] is from lowmem, was dma_map_single()-ed */
+ dma_unmap_single(dpa_bp->dev, sgt[0].addr,
+ sgt[0].length, dma_dir);
+
+ /* remaining pages were mapped with dma_map_page() */
+ for (i = 1; i < nr_frags; i++) {
+ DPA_BUG_ON(sgt[i].extension);
+
+ dma_unmap_page(dpa_bp->dev, sgt[i].addr,
+ sgt[i].length, dma_dir);
+ }
+
+ /* Free the page frag that we allocated on Tx */
+ put_page(virt_to_head_page(sgt));
+ }
+#ifdef CONFIG_FSL_DPAA_TS
+ else {
+ /* get the timestamp for non-SG frames */
+#ifdef CONFIG_FSL_DPAA_1588
+ if (priv->tsu && priv->tsu->valid &&
+ priv->tsu->hwts_tx_en_ioctl)
+ dpa_ptp_store_txstamp(priv, skb, (void *)skbh);
+#endif
+ if (unlikely(priv->ts_tx_en &&
+ skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
+ struct skb_shared_hwtstamps shhwtstamps;
+
+ dpa_get_ts(priv, TX, &shhwtstamps, (void *)skbh);
+ skb_tstamp_tx(skb, &shhwtstamps);
+ }
+ }
+#endif
+
+ return skb;
+}
+
+#ifndef CONFIG_FSL_DPAA_TS
+static bool dpa_skb_is_recyclable(struct sk_buff *skb)
+{
+ /* No recycling possible if skb buffer is kmalloc'ed */
+ if (skb->head_frag == 0)
+ return false;
+
+ /* or if it's an userspace buffer */
+ if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY)
+ return false;
+
+ /* or if it's cloned or shared */
+ if (skb_shared(skb) || skb_cloned(skb) ||
+ skb->fclone != SKB_FCLONE_UNAVAILABLE)
+ return false;
+
+ return true;
+}
+
+static bool dpa_buf_is_recyclable(struct sk_buff *skb,
+ uint32_t min_size,
+ uint16_t min_offset,
+ unsigned char **new_buf_start)
+{
+ unsigned char *new;
+
+ /* In order to recycle a buffer, the following conditions must be met:
+ * - buffer size no less than the buffer pool size
+ * - buffer size no higher than an upper limit (to avoid moving too much
+ * system memory to the buffer pools)
+ * - buffer address aligned to cacheline bytes
+ * - offset of data from start of buffer no lower than a minimum value
+ * - offset of data from start of buffer no higher than a maximum value
+ */
+ new = min(skb_end_pointer(skb) - min_size, skb->data - min_offset);
+
+ /* left align to the nearest cacheline */
+ new = (unsigned char *)((unsigned long)new & ~(SMP_CACHE_BYTES - 1));
+
+ if (likely(new >= skb->head &&
+ new >= (skb->data - DPA_MAX_FD_OFFSET) &&
+ skb_end_pointer(skb) - new <= DPA_RECYCLE_MAX_SIZE)) {
+ *new_buf_start = new;
+ return true;
+ }
+
+ return false;
+}
+#endif
+
+/* Build a linear skb around the received buffer.
+ * We are guaranteed there is enough room at the end of the data buffer to
+ * accommodate the shared info area of the skb.
+ */
+static struct sk_buff *__hot contig_fd_to_skb(const struct dpa_priv_s *priv,
+ const struct qm_fd *fd, int *use_gro)
+{
+ dma_addr_t addr = qm_fd_addr(fd);
+ ssize_t fd_off = dpa_fd_offset(fd);
+ void *vaddr;
+ const fm_prs_result_t *parse_results;
+ struct sk_buff *skb = NULL, **skbh;
+
+ vaddr = phys_to_virt(addr);
+ DPA_BUG_ON(!IS_ALIGNED((unsigned long)vaddr, SMP_CACHE_BYTES));
+
+ /* Retrieve the skb and adjust data and tail pointers, to make sure
+ * forwarded skbs will have enough space on Tx if extra headers
+ * are added.
+ */
+ DPA_READ_SKB_PTR(skb, skbh, vaddr, -1);
+
+#ifdef CONFIG_FSL_DPAA_ETH_JUMBO_FRAME
+ /* When using jumbo Rx buffers, we risk having frames dropped due to
+ * the socket backlog reaching its maximum allowed size.
+ * Use the frame length for the skb truesize instead of the buffer
+ * size, as this is the size of the data that actually gets copied to
+ * userspace.
+ */
+ skb->truesize = SKB_TRUESIZE(dpa_fd_length(fd));
+#endif
+
+ DPA_BUG_ON(fd_off != priv->rx_headroom);
+ skb_reserve(skb, fd_off);
+ skb_put(skb, dpa_fd_length(fd));
+
+ /* Peek at the parse results for csum validation */
+ parse_results = (const fm_prs_result_t *)(vaddr +
+ DPA_RX_PRIV_DATA_SIZE);
+ _dpa_process_parse_results(parse_results, fd, skb, use_gro);
+
+#ifdef CONFIG_FSL_DPAA_1588
+ if (priv->tsu && priv->tsu->valid && priv->tsu->hwts_rx_en_ioctl)
+ dpa_ptp_store_rxstamp(priv, skb, vaddr);
+#endif
+#ifdef CONFIG_FSL_DPAA_TS
+ if (priv->ts_rx_en)
+ dpa_get_ts(priv, RX, skb_hwtstamps(skb), vaddr);
+#endif /* CONFIG_FSL_DPAA_TS */
+
+ return skb;
+}
+
+
+/* Build an skb with the data of the first S/G entry in the linear portion and
+ * the rest of the frame as skb fragments.
+ *
+ * The page fragment holding the S/G Table is recycled here.
+ */
+static struct sk_buff *__hot sg_fd_to_skb(const struct dpa_priv_s *priv,
+ const struct qm_fd *fd, int *use_gro,
+ int *count_ptr)
+{
+ const struct qm_sg_entry *sgt;
+ dma_addr_t addr = qm_fd_addr(fd);
+ ssize_t fd_off = dpa_fd_offset(fd);
+ dma_addr_t sg_addr;
+ void *vaddr, *sg_vaddr;
+ struct dpa_bp *dpa_bp;
+ struct page *page, *head_page;
+ int frag_offset, frag_len;
+ int page_offset;
+ int i;
+ const fm_prs_result_t *parse_results;
+ struct sk_buff *skb = NULL, *skb_tmp, **skbh;
+
+ vaddr = phys_to_virt(addr);
+ DPA_BUG_ON(!IS_ALIGNED((unsigned long)vaddr, SMP_CACHE_BYTES));
+
+ dpa_bp = priv->dpa_bp;
+ /* Iterate through the SGT entries and add data buffers to the skb */
+ sgt = vaddr + fd_off;
+ for (i = 0; i < DPA_SGT_MAX_ENTRIES; i++) {
+ /* Extension bit is not supported */
+ DPA_BUG_ON(sgt[i].extension);
+
+ /* We use a single global Rx pool */
+ DPA_BUG_ON(dpa_bp != dpa_bpid2pool(sgt[i].bpid));
+
+ sg_addr = qm_sg_addr(&sgt[i]);
+ sg_vaddr = phys_to_virt(sg_addr);
+ DPA_BUG_ON(!IS_ALIGNED((unsigned long)sg_vaddr,
+ SMP_CACHE_BYTES));
+
+ dma_unmap_single(dpa_bp->dev, sg_addr, dpa_bp->size,
+ DMA_BIDIRECTIONAL);
+ if (i == 0) {
+ DPA_READ_SKB_PTR(skb, skbh, sg_vaddr, -1);
+ DPA_BUG_ON(skb->head != sg_vaddr);
+#ifdef CONFIG_FSL_DPAA_1588
+ if (priv->tsu && priv->tsu->valid &&
+ priv->tsu->hwts_rx_en_ioctl)
+ dpa_ptp_store_rxstamp(priv, skb, vaddr);
+#endif
+#ifdef CONFIG_FSL_DPAA_TS
+ if (priv->ts_rx_en)
+ dpa_get_ts(priv, RX, skb_hwtstamps(skb), vaddr);
+#endif /* CONFIG_FSL_DPAA_TS */
+
+ /* In the case of a SG frame, FMan stores the Internal
+ * Context in the buffer containing the sgt.
+ * Inspect the parse results before anything else.
+ */
+ parse_results = (const fm_prs_result_t *)(vaddr +
+ DPA_RX_PRIV_DATA_SIZE);
+ _dpa_process_parse_results(parse_results, fd, skb,
+ use_gro);
+
+ /* Make sure forwarded skbs will have enough space
+ * on Tx, if extra headers are added.
+ */
+ DPA_BUG_ON(fd_off != priv->rx_headroom);
+ skb_reserve(skb, fd_off);
+ skb_put(skb, sgt[i].length);
+ } else {
+ /* Not the first S/G entry; all data from buffer will
+ * be added in an skb fragment; fragment index is offset
+ * by one since first S/G entry was incorporated in the
+ * linear part of the skb.
+ *
+ * Caution: 'page' may be a tail page.
+ */
+ DPA_READ_SKB_PTR(skb_tmp, skbh, sg_vaddr, -1);
+ page = virt_to_page(sg_vaddr);
+ head_page = virt_to_head_page(sg_vaddr);
+
+ /* Free (only) the skbuff shell because its data buffer
+ * is already a frag in the main skb.
+ */
+ get_page(head_page);
+ dev_kfree_skb(skb_tmp);
+
+ /* Compute offset in (possibly tail) page */
+ page_offset = ((unsigned long)sg_vaddr &
+ (PAGE_SIZE - 1)) +
+ (page_address(page) - page_address(head_page));
+ /* page_offset only refers to the beginning of sgt[i];
+ * but the buffer itself may have an internal offset.
+ */
+ frag_offset = sgt[i].offset + page_offset;
+ frag_len = sgt[i].length;
+ /* skb_add_rx_frag() does no checking on the page; if
+ * we pass it a tail page, we'll end up with
+ * bad page accounting and eventually with segafults.
+ */
+ skb_add_rx_frag(skb, i - 1, head_page, frag_offset,
+ frag_len, dpa_bp->size);
+ }
+ /* Update the pool count for the current {cpu x bpool} */
+ (*count_ptr)--;
+
+ if (sgt[i].final)
+ break;
+ }
+ WARN_ONCE(i == DPA_SGT_MAX_ENTRIES, "No final bit on SGT\n");
+
+ /* recycle the SGT fragment */
+ DPA_BUG_ON(dpa_bp != dpa_bpid2pool(fd->bpid));
+ dpa_bp_recycle_frag(dpa_bp, (unsigned long)vaddr, count_ptr);
+ return skb;
+}
+
+void __hot _dpa_rx(struct net_device *net_dev,
+ struct qman_portal *portal,
+ const struct dpa_priv_s *priv,
+ struct dpa_percpu_priv_s *percpu_priv,
+ const struct qm_fd *fd,
+ u32 fqid,
+ int *count_ptr)
+{
+ struct dpa_bp *dpa_bp;
+ struct sk_buff *skb;
+ dma_addr_t addr = qm_fd_addr(fd);
+ u32 fd_status = fd->status;
+ unsigned int skb_len;
+ struct rtnl_link_stats64 *percpu_stats = &percpu_priv->stats;
+ int use_gro = net_dev->features & NETIF_F_GRO;
+
+ if (unlikely(fd_status & FM_FD_STAT_RX_ERRORS) != 0) {
+ if (netif_msg_hw(priv) && net_ratelimit())
+ netdev_warn(net_dev, "FD status = 0x%08x\n",
+ fd_status & FM_FD_STAT_RX_ERRORS);
+
+ percpu_stats->rx_errors++;
+ goto _release_frame;
+ }
+
+ dpa_bp = priv->dpa_bp;
+ DPA_BUG_ON(dpa_bp != dpa_bpid2pool(fd->bpid));
+
+ /* prefetch the first 64 bytes of the frame or the SGT start */
+ dma_unmap_single(dpa_bp->dev, addr, dpa_bp->size, DMA_BIDIRECTIONAL);
+ prefetch(phys_to_virt(addr) + dpa_fd_offset(fd));
+
+ /* The only FD types that we may receive are contig and S/G */
+ DPA_BUG_ON((fd->format != qm_fd_contig) && (fd->format != qm_fd_sg));
+
+ if (likely(fd->format == qm_fd_contig)) {
+#if defined(CONFIG_AS_FASTPATH) || defined(CONFIG_FSL_FMAN_TEST)
+ /* Execute the Rx processing hook, if it exists. */
+ if (dpaa_eth_hooks.rx_default &&
+ dpaa_eth_hooks.rx_default((void *)fd, net_dev, fqid)
+ == DPAA_ETH_STOLEN) {
+ /* won't count the rx bytes in */
+ return;
+ }
+#endif
+ skb = contig_fd_to_skb(priv, fd, &use_gro);
+ } else
+ skb = sg_fd_to_skb(priv, fd, &use_gro, count_ptr);
+
+ /* Account for either the contig buffer or the SGT buffer (depending on
+ * which case we were in) having been removed from the pool.
+ */
+ (*count_ptr)--;
+ skb->protocol = eth_type_trans(skb, net_dev);
+
+ /* IP Reassembled frames are allowed to be larger than MTU */
+ if (unlikely(dpa_check_rx_mtu(skb, net_dev->mtu) &&
+ !(fd_status & FM_FD_IPR))) {
+ percpu_stats->rx_dropped++;
+ goto drop_bad_frame;
+ }
+
+ skb_len = skb->len;
+
+ if (use_gro) {
+ gro_result_t gro_result;
+ const struct qman_portal_config *pc =
+ qman_p_get_portal_config(portal);
+ struct dpa_napi_portal *np = &percpu_priv->np[pc->index];
+
+ np->p = portal;
+ gro_result = napi_gro_receive(&np->napi, skb);
+ /* If frame is dropped by the stack, rx_dropped counter is
+ * incremented automatically, so no need for us to update it
+ */
+ if (unlikely(gro_result == GRO_DROP))
+ goto packet_dropped;
+ } else if (unlikely(netif_receive_skb(skb) == NET_RX_DROP))
+ goto packet_dropped;
+
+ percpu_stats->rx_packets++;
+ percpu_stats->rx_bytes += skb_len;
+
+packet_dropped:
+ return;
+
+drop_bad_frame:
+ dev_kfree_skb(skb);
+ return;
+
+_release_frame:
+ dpa_fd_release(net_dev, fd);
+}
+
+static int __hot skb_to_contig_fd(struct dpa_priv_s *priv,
+ struct sk_buff *skb, struct qm_fd *fd,
+ int *count_ptr)
+{
+ struct sk_buff **skbh;
+ dma_addr_t addr;
+ struct dpa_bp *dpa_bp = priv->dpa_bp;
+ struct net_device *net_dev = priv->net_dev;
+ int err;
+ enum dma_data_direction dma_dir;
+ unsigned char *buffer_start;
+
+#ifndef CONFIG_FSL_DPAA_TS
+ /* Check recycling conditions; only if timestamp support is not
+ * enabled, otherwise we need the fd back on tx confirmation
+ */
+
+ /* We can recycle the buffer if:
+ * - the pool is not full
+ * - the buffer meets the skb recycling conditions
+ * - the buffer meets our own (size, offset, align) conditions
+ */
+ if (likely((*count_ptr < dpa_bp->target_count) &&
+ dpa_skb_is_recyclable(skb) &&
+ dpa_buf_is_recyclable(skb, dpa_bp->size,
+ priv->tx_headroom, &buffer_start))) {
+ /* Buffer is recyclable; use the new start address
+ * and set fd parameters and DMA mapping direction
+ */
+ fd->cmd |= FM_FD_CMD_FCO;
+ fd->bpid = dpa_bp->bpid;
+ DPA_BUG_ON(skb->data - buffer_start > DPA_MAX_FD_OFFSET);
+ fd->offset = (uint16_t)(skb->data - buffer_start);
+ dma_dir = DMA_BIDIRECTIONAL;
+
+ DPA_WRITE_SKB_PTR(skb, skbh, buffer_start, -1);
+ } else
+#endif
+ {
+ /* Not recyclable.
+ * We are guaranteed to have at least tx_headroom bytes
+ * available, so just use that for offset.
+ */
+ buffer_start = skb->data - priv->tx_headroom;
+ fd->offset = priv->tx_headroom;
+ dma_dir = DMA_TO_DEVICE;
+
+ /* The buffer will be Tx-confirmed, but the TxConf cb must
+ * necessarily look at our Tx private data to retrieve the
+ * skbuff. (In short: can't use DPA_WRITE_SKB_PTR() here.)
+ */
+ DPA_WRITE_SKB_PTR(skb, skbh, buffer_start, 0);
+ }
+
+ /* Enable L3/L4 hardware checksum computation.
+ *
+ * We must do this before dma_map_single(DMA_TO_DEVICE), because we may
+ * need to write into the skb.
+ */
+ err = dpa_enable_tx_csum(priv, skb, fd,
+ ((char *)skbh) + DPA_TX_PRIV_DATA_SIZE);
+ if (unlikely(err < 0)) {
+ if (netif_msg_tx_err(priv) && net_ratelimit())
+ netdev_err(net_dev, "HW csum error: %d\n", err);
+ return err;
+ }
+
+ /* Fill in the rest of the FD fields */
+ fd->format = qm_fd_contig;
+ fd->length20 = skb->len;
+
+ /* Map the entire buffer size that may be seen by FMan, but no more */
+ addr = dma_map_single(dpa_bp->dev, skbh,
+ skb_end_pointer(skb) - buffer_start, dma_dir);
+ if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) {
+ if (netif_msg_tx_err(priv) && net_ratelimit())
+ netdev_err(net_dev, "dma_map_single() failed\n");
+ return -EINVAL;
+ }
+ fd->addr_hi = (uint8_t)upper_32_bits(addr);
+ fd->addr_lo = lower_32_bits(addr);
+
+ return 0;
+}
+
+static int __hot skb_to_sg_fd(struct dpa_priv_s *priv,
+ struct sk_buff *skb, struct qm_fd *fd)
+{
+ struct dpa_bp *dpa_bp = priv->dpa_bp;
+ dma_addr_t addr;
+ struct sk_buff **skbh;
+ struct net_device *net_dev = priv->net_dev;
+ int err;
+
+ struct qm_sg_entry *sgt;
+ void *sgt_buf;
+ void *buffer_start;
+ skb_frag_t *frag;
+ int i, j;
+ const enum dma_data_direction dma_dir = DMA_TO_DEVICE;
+ const int nr_frags = skb_shinfo(skb)->nr_frags;
+
+ fd->format = qm_fd_sg;
+
+ /* get a page frag to store the SGTable */
+ sgt_buf = netdev_alloc_frag(priv->tx_headroom +
+ sizeof(struct qm_sg_entry) * (1 + nr_frags));
+ if (unlikely(!sgt_buf)) {
+ dev_err(dpa_bp->dev, "netdev_alloc_frag() failed\n");
+ return -ENOMEM;
+ }
+
+ /* Enable L3/L4 hardware checksum computation.
+ *
+ * We must do this before dma_map_single(DMA_TO_DEVICE), because we may
+ * need to write into the skb.
+ */
+ err = dpa_enable_tx_csum(priv, skb, fd,
+ sgt_buf + DPA_TX_PRIV_DATA_SIZE);
+ if (unlikely(err < 0)) {
+ if (netif_msg_tx_err(priv) && net_ratelimit())
+ netdev_err(net_dev, "HW csum error: %d\n", err);
+ goto csum_failed;
+ }
+
+ sgt = (struct qm_sg_entry *)(sgt_buf + priv->tx_headroom);
+ sgt[0].bpid = dpa_bp->bpid;
+ sgt[0].offset = 0;
+ sgt[0].length = skb_headlen(skb);
+ sgt[0].extension = 0;
+ sgt[0].final = 0;
+ addr = dma_map_single(dpa_bp->dev, skb->data, sgt[0].length, dma_dir);
+ if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) {
+ dev_err(dpa_bp->dev, "DMA mapping failed");
+ err = -EINVAL;
+ goto sg0_map_failed;
+
+ }
+ sgt[0].addr_hi = upper_32_bits(addr);
+ sgt[0].addr_lo = lower_32_bits(addr);
+
+ /* populate the rest of SGT entries */
+ for (i = 1; i <= nr_frags; i++) {
+ frag = &skb_shinfo(skb)->frags[i - 1];
+ sgt[i].bpid = dpa_bp->bpid;
+
+ sgt[i].offset = 0;
+ sgt[i].length = frag->size;
+ sgt[i].extension = 0;
+ sgt[i].final = 0;
+
+ DPA_BUG_ON(!skb_frag_page(frag));
+ addr = skb_frag_dma_map(dpa_bp->dev, frag, 0, sgt[i].length,
+ dma_dir);
+ if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) {
+ dev_err(dpa_bp->dev, "DMA mapping failed");
+ err = -EINVAL;
+ goto sg_map_failed;
+ }
+
+ /* keep the offset in the address */
+ sgt[i].addr_hi = upper_32_bits(addr);
+ sgt[i].addr_lo = lower_32_bits(addr);
+ }
+ sgt[i - 1].final = 1;
+
+ fd->length20 = skb->len;
+ fd->offset = priv->tx_headroom;
+
+ /* DMA map the SGT page */
+ buffer_start = (void *)sgt - dpa_fd_offset(fd);
+ /* Can't write at "negative" offset in buffer_start, because this skb
+ * may not have been allocated by us.
+ */
+ DPA_WRITE_SKB_PTR(skb, skbh, buffer_start, 0);
+
+ addr = dma_map_single(dpa_bp->dev, buffer_start,
+ skb_end_pointer(skb) - (unsigned char *)buffer_start, dma_dir);
+ if (unlikely(dma_mapping_error(dpa_bp->dev, addr))) {
+ dev_err(dpa_bp->dev, "DMA mapping failed");
+ err = -EINVAL;
+ goto sgt_map_failed;
+ }
+ fd->addr_hi = upper_32_bits(addr);
+ fd->addr_lo = lower_32_bits(addr);
+
+ return 0;
+
+sgt_map_failed:
+sg_map_failed:
+ for (j = 0; j < i; j++)
+ dma_unmap_page(dpa_bp->dev, qm_sg_addr(&sgt[j]),
+ sgt[j].length, dma_dir);
+sg0_map_failed:
+csum_failed:
+ put_page(virt_to_head_page(sgt_buf));
+
+ return err;
+}
+
+int __hot dpa_tx(struct sk_buff *skb, struct net_device *net_dev)
+{
+ struct dpa_priv_s *priv;
+ struct qm_fd fd;
+ struct dpa_percpu_priv_s *percpu_priv;
+ struct rtnl_link_stats64 *percpu_stats;
+ int err = 0;
+ const int queue_mapping = dpa_get_queue_mapping(skb);
+ const bool nonlinear = skb_is_nonlinear(skb);
+ int *countptr;
+#if defined(CONFIG_AS_FASTPATH) || defined(CONFIG_FSL_FMAN_TEST)
+ /* If there is a Tx hook, run it. */
+ if (dpaa_eth_hooks.tx &&
+ dpaa_eth_hooks.tx(skb, net_dev) == DPAA_ETH_STOLEN)
+ /* won't update any Tx stats */
+ return NETDEV_TX_OK;
+#endif
+ priv = netdev_priv(net_dev);
+ /* Non-migratable context, safe to use __this_cpu_ptr */
+ percpu_priv = __this_cpu_ptr(priv->percpu_priv);
+ percpu_stats = &percpu_priv->stats;
+ countptr = __this_cpu_ptr(priv->dpa_bp->percpu_count);
+
+ clear_fd(&fd);
+
+#ifdef CONFIG_FSL_DPAA_1588
+ if (priv->tsu && priv->tsu->valid && priv->tsu->hwts_tx_en_ioctl)
+ fd.cmd |= FM_FD_CMD_UPD;
+#endif
+#ifdef CONFIG_FSL_DPAA_TS
+ if (unlikely(priv->ts_tx_en &&
+ skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))
+ fd.cmd |= FM_FD_CMD_UPD;
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+#endif /* CONFIG_FSL_DPAA_TS */
+
+ /* MAX_SKB_FRAGS is larger than our DPA_SGT_MAX_ENTRIES; make sure
+ * we don't feed FMan with more fragments than it supports.
+ * Btw, we're using the first sgt entry to store the linear part of
+ * the skb, so we're one extra frag short.
+ */
+ if (nonlinear &&
+ likely(skb_shinfo(skb)->nr_frags < DPA_SGT_MAX_ENTRIES)) {
+ /* Just create a S/G fd based on the skb */
+ err = skb_to_sg_fd(priv, skb, &fd);
+ percpu_priv->tx_frag_skbuffs++;
+ } else {
+ /* Make sure we have enough headroom to accommodate private
+ * data, parse results, etc. Normally this shouldn't happen if
+ * we're here via the standard kernel stack.
+ */
+ if (unlikely(skb_headroom(skb) < priv->tx_headroom)) {
+ struct sk_buff *skb_new;
+
+ skb_new = skb_realloc_headroom(skb, priv->tx_headroom);
+ if (unlikely(!skb_new)) {
+ dev_kfree_skb(skb);
+ percpu_stats->tx_errors++;
+ return NETDEV_TX_OK;
+ }
+ dev_kfree_skb(skb);
+ skb = skb_new;
+ }
+
+ /* We're going to store the skb backpointer at the beginning
+ * of the data buffer, so we need a privately owned skb
+ */
+
+ /* Code borrowed from skb_unshare(). */
+ if (skb_cloned(skb)) {
+ struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC);
+ kfree_skb(skb);
+ skb = nskb;
+ /* skb_copy() has now linearized the skbuff. */
+ } else if (unlikely(nonlinear)) {
+ /* We are here because the egress skb contains
+ * more fragments than we support. In this case,
+ * we have no choice but to linearize it ourselves.
+ */
+ err = __skb_linearize(skb);
+ }
+ if (unlikely(!skb || err < 0))
+ /* Common out-of-memory error path */
+ goto enomem;
+
+ /* Finally, create a contig FD from this skb */
+ err = skb_to_contig_fd(priv, skb, &fd, countptr);
+ }
+ if (unlikely(err < 0))
+ goto skb_to_fd_failed;
+
+ if (fd.cmd & FM_FD_CMD_FCO) {
+ skb_recycle(skb);
+ /* skb_recycle() reserves NET_SKB_PAD as skb headroom,
+ * but we need the skb to look as if returned by build_skb().
+ * We need to manually adjust the tailptr as well.
+ */
+ skb->data = skb->head;
+ skb_reset_tail_pointer(skb);
+
+ (*countptr)++;
+ percpu_priv->tx_returned++;
+ }
+
+ if (unlikely(dpa_xmit(priv, percpu_stats, queue_mapping, &fd) < 0))
+ goto xmit_failed;
+
+ net_dev->trans_start = jiffies;
+ return NETDEV_TX_OK;
+
+xmit_failed:
+ if (fd.cmd & FM_FD_CMD_FCO) {
+ (*countptr)--;
+ percpu_priv->tx_returned--;
+ dpa_fd_release(net_dev, &fd);
+ percpu_stats->tx_errors++;
+ return NETDEV_TX_OK;
+ }
+ _dpa_cleanup_tx_fd(priv, &fd);
+skb_to_fd_failed:
+enomem:
+ percpu_stats->tx_errors++;
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+}
+
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth_shared.c b/drivers/net/ethernet/freescale/dpa/dpaa_eth_shared.c
new file mode 100644
index 0000000..f6671f9
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth_shared.c
@@ -0,0 +1,885 @@
+/* Copyright 2008-2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef CONFIG_FSL_DPAA_ETH_DEBUG
+#define pr_fmt(fmt) \
+ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \
+ KBUILD_BASENAME".c", __LINE__, __func__
+#else
+#define pr_fmt(fmt) \
+ KBUILD_MODNAME ": " fmt
+#endif
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/etherdevice.h>
+#include <linux/kthread.h>
+#include <linux/percpu.h>
+#include <linux/highmem.h>
+#include <linux/fsl_qman.h>
+#include "dpaa_eth.h"
+#include "dpaa_eth_common.h"
+#include "dpaa_eth_base.h"
+#include "lnxwrp_fsl_fman.h" /* fm_get_rx_extra_headroom(), fm_get_max_frm() */
+#include "mac.h"
+
+/* forward declarations */
+static enum qman_cb_dqrr_result __hot
+shared_rx_dqrr(struct qman_portal *portal, struct qman_fq *fq,
+ const struct qm_dqrr_entry *dq);
+static enum qman_cb_dqrr_result __hot
+shared_tx_default_dqrr(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry *dq);
+static enum qman_cb_dqrr_result
+shared_tx_error_dqrr(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry *dq);
+static void shared_ern(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_mr_entry *msg);
+int __hot dpa_shared_tx(struct sk_buff *skb, struct net_device *net_dev);
+
+#define DPA_DESCRIPTION "FSL DPAA Shared Ethernet driver"
+
+MODULE_LICENSE("Dual BSD/GPL");
+
+MODULE_DESCRIPTION(DPA_DESCRIPTION);
+
+static uint8_t debug = -1;
+module_param(debug, byte, S_IRUGO);
+MODULE_PARM_DESC(debug, "Module/Driver verbosity level");
+
+/* This has to work in tandem with the DPA_CS_THRESHOLD_xxx values. */
+static uint16_t tx_timeout = 1000;
+module_param(tx_timeout, ushort, S_IRUGO);
+MODULE_PARM_DESC(tx_timeout, "The Tx timeout in ms");
+
+static const struct of_device_id dpa_shared_match[];
+
+static const struct net_device_ops dpa_shared_ops = {
+ .ndo_open = dpa_start,
+ .ndo_start_xmit = dpa_shared_tx,
+ .ndo_stop = dpa_stop,
+ .ndo_tx_timeout = dpa_timeout,
+ .ndo_get_stats64 = dpa_get_stats64,
+ .ndo_set_mac_address = dpa_set_mac_address,
+ .ndo_validate_addr = eth_validate_addr,
+#ifdef CONFIG_FSL_DPAA_ETH_USE_NDO_SELECT_QUEUE
+ .ndo_select_queue = dpa_select_queue,
+#endif
+ .ndo_change_mtu = dpa_change_mtu,
+ .ndo_set_rx_mode = dpa_set_rx_mode,
+ .ndo_init = dpa_ndo_init,
+ .ndo_set_features = dpa_set_features,
+ .ndo_fix_features = dpa_fix_features,
+ .ndo_do_ioctl = dpa_ioctl,
+};
+
+const struct dpa_fq_cbs_t shared_fq_cbs = {
+ .rx_defq = { .cb = { .dqrr = shared_rx_dqrr } },
+ .tx_defq = { .cb = { .dqrr = shared_tx_default_dqrr } },
+ .rx_errq = { .cb = { .dqrr = shared_rx_dqrr } },
+ .tx_errq = { .cb = { .dqrr = shared_tx_error_dqrr } },
+ .egress_ern = { .cb = { .ern = shared_ern } }
+};
+
+static inline void * __must_check __attribute__((nonnull))
+dpa_phys2virt(const struct dpa_bp *dpa_bp, dma_addr_t addr)
+{
+ return dpa_bp->vaddr + (addr - dpa_bp->paddr);
+}
+
+static struct dpa_bp *dpa_size2pool(struct dpa_priv_s *priv, size_t size)
+{
+ int i;
+
+ for (i = 0; i < priv->bp_count; i++)
+ if ((size + priv->tx_headroom) <= priv->dpa_bp[i].size)
+ return dpa_bpid2pool(priv->dpa_bp[i].bpid);
+ return ERR_PTR(-ENODEV);
+}
+
+/* Copy to a memory region that requires kmapping from a linear buffer,
+ * taking into account page boundaries in the destination
+ */
+static void
+copy_to_unmapped_area(dma_addr_t phys_start, void *src, size_t buf_size)
+{
+ struct page *page;
+ size_t size, offset;
+ void *page_vaddr;
+
+ while (buf_size > 0) {
+ offset = offset_in_page(phys_start);
+ size = (offset + buf_size > PAGE_SIZE) ?
+ PAGE_SIZE - offset : buf_size;
+
+ page = pfn_to_page(phys_start >> PAGE_SHIFT);
+ page_vaddr = kmap_atomic(page);
+
+ memcpy(page_vaddr + offset, src, size);
+
+ kunmap_atomic(page_vaddr);
+
+ phys_start += size;
+ src += size;
+ buf_size -= size;
+ }
+}
+
+/* Copy from a memory region that requires kmapping to a linear buffer,
+ * taking into account page boundaries in the source
+ */
+static void
+copy_from_unmapped_area(void *dest, dma_addr_t phys_start, size_t buf_size)
+{
+ struct page *page;
+ size_t size, offset;
+ void *page_vaddr;
+
+ while (buf_size > 0) {
+ offset = offset_in_page(phys_start);
+ size = (offset + buf_size > PAGE_SIZE) ?
+ PAGE_SIZE - offset : buf_size;
+
+ page = pfn_to_page(phys_start >> PAGE_SHIFT);
+ page_vaddr = kmap_atomic(page);
+
+ memcpy(dest, page_vaddr + offset, size);
+
+ kunmap_atomic(page_vaddr);
+
+ phys_start += size;
+ dest += size;
+ buf_size -= size;
+ }
+}
+
+static void
+dpa_fd_release_sg(const struct net_device *net_dev,
+ const struct qm_fd *fd)
+{
+ const struct dpa_priv_s *priv;
+ struct qm_sg_entry *sgt;
+ struct dpa_bp *_dpa_bp;
+ struct bm_buffer _bmb;
+
+ priv = netdev_priv(net_dev);
+
+ _bmb.hi = fd->addr_hi;
+ _bmb.lo = fd->addr_lo;
+
+ _dpa_bp = dpa_bpid2pool(fd->bpid);
+ BUG_ON(!_dpa_bp);
+
+ if (_dpa_bp->vaddr) {
+ sgt = dpa_phys2virt(_dpa_bp, bm_buf_addr(&_bmb)) +
+ dpa_fd_offset(fd);
+ dpa_release_sgt(sgt);
+ } else {
+ sgt = kmalloc(DPA_SGT_MAX_ENTRIES * sizeof(*sgt), GFP_ATOMIC);
+ if (sgt == NULL) {
+ if (netif_msg_tx_err(priv) && net_ratelimit())
+ netdev_err(net_dev,
+ "Memory allocation failed\n");
+ return;
+ }
+
+ copy_from_unmapped_area(sgt, bm_buf_addr(&_bmb) +
+ dpa_fd_offset(fd),
+ min(DPA_SGT_MAX_ENTRIES * sizeof(*sgt),
+ _dpa_bp->size));
+ dpa_release_sgt(sgt);
+ kfree(sgt);
+ }
+
+ while (bman_release(_dpa_bp->pool, &_bmb, 1, 0))
+ cpu_relax();
+}
+
+static enum qman_cb_dqrr_result __hot
+shared_rx_dqrr(struct qman_portal *portal, struct qman_fq *fq,
+ const struct qm_dqrr_entry *dq)
+{
+ struct net_device *net_dev;
+ struct dpa_priv_s *priv;
+ struct dpa_percpu_priv_s *percpu_priv;
+ const struct qm_fd *fd = &dq->fd;
+ struct dpa_bp *dpa_bp;
+ struct sk_buff *skb;
+ struct qm_sg_entry *sgt;
+ int i;
+
+ net_dev = ((struct dpa_fq *)fq)->net_dev;
+ priv = netdev_priv(net_dev);
+
+ percpu_priv = __this_cpu_ptr(priv->percpu_priv);
+
+ dpa_bp = dpa_bpid2pool(fd->bpid);
+ BUG_ON(!dpa_bp);
+
+ if (unlikely(fd->status & FM_FD_STAT_RX_ERRORS) != 0) {
+ if (netif_msg_hw(priv) && net_ratelimit())
+ netdev_warn(net_dev, "FD status = 0x%08x\n",
+ fd->status & FM_FD_STAT_RX_ERRORS);
+
+ percpu_priv->stats.rx_errors++;
+
+ goto out;
+ }
+
+ skb = __netdev_alloc_skb(net_dev,
+ priv->tx_headroom + dpa_fd_length(fd),
+ GFP_ATOMIC);
+ if (unlikely(skb == NULL)) {
+ if (netif_msg_rx_err(priv) && net_ratelimit())
+ netdev_err(net_dev, "Could not alloc skb\n");
+
+ percpu_priv->stats.rx_dropped++;
+
+ goto out;
+ }
+
+ skb_reserve(skb, priv->tx_headroom);
+
+ if (fd->format == qm_fd_sg) {
+ if (dpa_bp->vaddr) {
+ sgt = dpa_phys2virt(dpa_bp,
+ qm_fd_addr(fd)) + dpa_fd_offset(fd);
+
+ for (i = 0; i < DPA_SGT_MAX_ENTRIES; i++) {
+ BUG_ON(sgt[i].extension);
+
+ /* copy from sgt[i] */
+ memcpy(skb_put(skb, sgt[i].length),
+ dpa_phys2virt(dpa_bp,
+ qm_sg_addr(&sgt[i]) +
+ sgt[i].offset),
+ sgt[i].length);
+ if (sgt[i].final)
+ break;
+ }
+ } else {
+ sgt = kmalloc(DPA_SGT_MAX_ENTRIES * sizeof(*sgt),
+ GFP_ATOMIC);
+ if (unlikely(sgt == NULL)) {
+ if (netif_msg_tx_err(priv) && net_ratelimit())
+ netdev_err(net_dev,
+ "Memory allocation failed\n");
+ return -ENOMEM;
+ }
+
+ copy_from_unmapped_area(sgt,
+ qm_fd_addr(fd) + dpa_fd_offset(fd),
+ min(DPA_SGT_MAX_ENTRIES * sizeof(*sgt),
+ dpa_bp->size));
+
+ for (i = 0; i < DPA_SGT_MAX_ENTRIES; i++) {
+ BUG_ON(sgt[i].extension);
+
+ copy_from_unmapped_area(
+ skb_put(skb, sgt[i].length),
+ qm_sg_addr(&sgt[i]) + sgt[i].offset,
+ sgt[i].length);
+
+ if (sgt[i].final)
+ break;
+ }
+
+ kfree(sgt);
+ }
+ goto skb_copied;
+ }
+
+ /* otherwise fd->format == qm_fd_contig */
+ if (dpa_bp->vaddr) {
+ /* Fill the SKB */
+ memcpy(skb_put(skb, dpa_fd_length(fd)),
+ dpa_phys2virt(dpa_bp, qm_fd_addr(fd)) +
+ dpa_fd_offset(fd), dpa_fd_length(fd));
+ } else {
+ copy_from_unmapped_area(skb_put(skb, dpa_fd_length(fd)),
+ qm_fd_addr(fd) + dpa_fd_offset(fd),
+ dpa_fd_length(fd));
+ }
+
+skb_copied:
+ skb->protocol = eth_type_trans(skb, net_dev);
+
+ /* IP Reassembled frames are allowed to be larger than MTU */
+ if (unlikely(dpa_check_rx_mtu(skb, net_dev->mtu) &&
+ !(fd->status & FM_FD_IPR))) {
+ percpu_priv->stats.rx_dropped++;
+ dev_kfree_skb_any(skb);
+ goto out;
+ }
+
+ if (unlikely(netif_rx(skb) != NET_RX_SUCCESS))
+ goto out;
+ else {
+ percpu_priv->stats.rx_packets++;
+ percpu_priv->stats.rx_bytes += dpa_fd_length(fd);
+ }
+
+out:
+ if (fd->format == qm_fd_sg)
+ dpa_fd_release_sg(net_dev, fd);
+ else
+ dpa_fd_release(net_dev, fd);
+
+ return qman_cb_dqrr_consume;
+}
+
+static enum qman_cb_dqrr_result
+shared_tx_error_dqrr(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry *dq)
+{
+ struct net_device *net_dev;
+ struct dpa_priv_s *priv;
+ struct dpa_percpu_priv_s *percpu_priv;
+ struct dpa_bp *dpa_bp;
+ const struct qm_fd *fd = &dq->fd;
+
+ net_dev = ((struct dpa_fq *)fq)->net_dev;
+ priv = netdev_priv(net_dev);
+
+ dpa_bp = dpa_bpid2pool(fd->bpid);
+ BUG_ON(!dpa_bp);
+
+ percpu_priv = __this_cpu_ptr(priv->percpu_priv);
+
+ if (netif_msg_hw(priv) && net_ratelimit())
+ netdev_warn(net_dev, "FD status = 0x%08x\n",
+ fd->status & FM_FD_STAT_TX_ERRORS);
+
+ if ((fd->format == qm_fd_sg) && (!dpa_bp->vaddr))
+ dpa_fd_release_sg(net_dev, fd);
+ else
+ dpa_fd_release(net_dev, fd);
+
+ percpu_priv->stats.tx_errors++;
+
+ return qman_cb_dqrr_consume;
+}
+
+static enum qman_cb_dqrr_result __hot
+shared_tx_default_dqrr(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry *dq)
+{
+ struct net_device *net_dev;
+ struct dpa_priv_s *priv;
+ struct dpa_percpu_priv_s *percpu_priv;
+ struct dpa_bp *dpa_bp;
+ const struct qm_fd *fd = &dq->fd;
+
+ net_dev = ((struct dpa_fq *)fq)->net_dev;
+ priv = netdev_priv(net_dev);
+
+ dpa_bp = dpa_bpid2pool(fd->bpid);
+ BUG_ON(!dpa_bp);
+
+ percpu_priv = __this_cpu_ptr(priv->percpu_priv);
+
+ if (unlikely(fd->status & FM_FD_STAT_TX_ERRORS) != 0) {
+ if (netif_msg_hw(priv) && net_ratelimit())
+ netdev_warn(net_dev, "FD status = 0x%08x\n",
+ fd->status & FM_FD_STAT_TX_ERRORS);
+
+ percpu_priv->stats.tx_errors++;
+ }
+
+ if ((fd->format == qm_fd_sg) && (!dpa_bp->vaddr))
+ dpa_fd_release_sg(net_dev, fd);
+ else
+ dpa_fd_release(net_dev, fd);
+
+ percpu_priv->tx_confirm++;
+
+ return qman_cb_dqrr_consume;
+}
+
+static void shared_ern(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_mr_entry *msg)
+{
+ struct net_device *net_dev;
+ const struct dpa_priv_s *priv;
+ struct dpa_percpu_priv_s *percpu_priv;
+ struct dpa_fq *dpa_fq = (struct dpa_fq *)fq;
+
+ net_dev = dpa_fq->net_dev;
+ priv = netdev_priv(net_dev);
+ percpu_priv = __this_cpu_ptr(priv->percpu_priv);
+
+ dpa_fd_release(net_dev, &msg->ern.fd);
+
+ percpu_priv->stats.tx_dropped++;
+ percpu_priv->stats.tx_fifo_errors++;
+ count_ern(percpu_priv, msg);
+}
+
+int __hot dpa_shared_tx(struct sk_buff *skb, struct net_device *net_dev)
+{
+ struct dpa_bp *dpa_bp;
+ struct bm_buffer bmb;
+ struct dpa_percpu_priv_s *percpu_priv;
+ struct dpa_priv_s *priv;
+ struct qm_fd fd;
+ int queue_mapping;
+ int err;
+ void *dpa_bp_vaddr;
+ fm_prs_result_t parse_results;
+
+ priv = netdev_priv(net_dev);
+ percpu_priv = __this_cpu_ptr(priv->percpu_priv);
+
+ memset(&fd, 0, sizeof(fd));
+ fd.format = qm_fd_contig;
+
+ queue_mapping = smp_processor_id();
+
+ dpa_bp = dpa_size2pool(priv, skb_headlen(skb));
+ if (unlikely(!dpa_bp)) {
+ percpu_priv->stats.tx_errors++;
+ err = PTR_ERR(dpa_bp);
+ goto bpools_too_small_error;
+ }
+
+ err = bman_acquire(dpa_bp->pool, &bmb, 1, 0);
+ if (unlikely(err <= 0)) {
+ percpu_priv->stats.tx_errors++;
+ if (err == 0)
+ err = -ENOMEM;
+ goto buf_acquire_failed;
+ }
+ fd.bpid = dpa_bp->bpid;
+
+ fd.length20 = skb_headlen(skb);
+ fd.addr_hi = bmb.hi;
+ fd.addr_lo = bmb.lo;
+ fd.offset = priv->tx_headroom;
+
+ /* The virtual address of the buffer pool is expected to be NULL
+ * in scenarios like MAC-less or Shared-MAC between Linux and
+ * USDPAA. In this case the buffers are dynamically mapped/unmapped.
+ */
+ if (dpa_bp->vaddr) {
+ dpa_bp_vaddr = dpa_phys2virt(dpa_bp, bm_buf_addr(&bmb));
+
+ /* Copy the packet payload */
+ skb_copy_from_linear_data(skb,
+ dpa_bp_vaddr + dpa_fd_offset(&fd),
+ dpa_fd_length(&fd));
+
+ /* if no mac device or peer set it's macless */
+ if (!priv->mac_dev || priv->peer)
+ fd.cmd |= FM_FD_CMD_DTC;
+ else {
+ /* Enable L3/L4 hardware checksum computation,
+ * if applicable
+ */
+ err = dpa_enable_tx_csum(priv, skb, &fd,
+ dpa_bp_vaddr + DPA_TX_PRIV_DATA_SIZE);
+
+ if (unlikely(err < 0)) {
+ if (netif_msg_tx_err(priv) && net_ratelimit())
+ netdev_err(net_dev,
+ "Tx HW csum error: %d\n", err);
+ percpu_priv->stats.tx_errors++;
+ goto l3_l4_csum_failed;
+ }
+ }
+
+ } else {
+ if (!priv->mac_dev || priv->peer)
+ fd.cmd |= FM_FD_CMD_DTC;
+ else {
+ /* Enable L3/L4 hardware checksum computation,
+ * if applicable
+ */
+ err = dpa_enable_tx_csum(priv, skb, &fd,
+ (char *)&parse_results);
+
+ if (unlikely(err < 0)) {
+ if (netif_msg_tx_err(priv) && net_ratelimit())
+ netdev_err(net_dev,
+ "Tx HW csum error: %d\n", err);
+ percpu_priv->stats.tx_errors++;
+ goto l3_l4_csum_failed;
+ }
+
+ }
+
+ copy_to_unmapped_area(bm_buf_addr(&bmb) + DPA_TX_PRIV_DATA_SIZE,
+ &parse_results,
+ DPA_PARSE_RESULTS_SIZE);
+
+ copy_to_unmapped_area(bm_buf_addr(&bmb) + dpa_fd_offset(&fd),
+ skb->data,
+ dpa_fd_length(&fd));
+ }
+
+ err = dpa_xmit(priv, &percpu_priv->stats, queue_mapping, &fd);
+
+l3_l4_csum_failed:
+bpools_too_small_error:
+buf_acquire_failed:
+ /* We're done with the skb */
+ dev_kfree_skb(skb);
+
+ return NETDEV_TX_OK;
+}
+
+static int dpa_shared_netdev_init(struct device_node *dpa_node,
+ struct net_device *net_dev)
+{
+ struct dpa_priv_s *priv = netdev_priv(net_dev);
+ const uint8_t *mac_addr;
+
+ net_dev->netdev_ops = &dpa_shared_ops;
+
+ net_dev->mem_start = priv->mac_dev->res->start;
+ net_dev->mem_end = priv->mac_dev->res->end;
+
+ mac_addr = priv->mac_dev->addr;
+
+ net_dev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+ NETIF_F_LLTX);
+
+ return dpa_netdev_init(dpa_node, net_dev, mac_addr, tx_timeout);
+}
+
+#ifdef CONFIG_PM
+
+static int dpa_shared_suspend_noirq(struct device *dev)
+{
+ struct net_device *net_dev;
+ struct dpa_priv_s *priv;
+ struct mac_device *mac_dev;
+ int err = 0;
+
+ net_dev = dev_get_drvdata(dev);
+ if (net_dev->flags & IFF_UP) {
+ priv = netdev_priv(net_dev);
+ mac_dev = priv->mac_dev;
+
+ err = fm_port_suspend(mac_dev->port_dev[RX]);
+ if (err)
+ goto port_suspend_failed;
+
+ err = fm_port_suspend(mac_dev->port_dev[TX]);
+ if (err)
+ err = fm_port_resume(mac_dev->port_dev[RX]);
+ }
+
+port_suspend_failed:
+ return err;
+}
+
+static int dpa_shared_resume_noirq(struct device *dev)
+{
+ struct net_device *net_dev;
+ struct dpa_priv_s *priv;
+ struct mac_device *mac_dev;
+ int err = 0;
+
+ net_dev = dev_get_drvdata(dev);
+ if (net_dev->flags & IFF_UP) {
+ priv = netdev_priv(net_dev);
+ mac_dev = priv->mac_dev;
+
+ err = fm_port_resume(mac_dev->port_dev[TX]);
+ if (err)
+ goto port_resume_failed;
+
+ err = fm_port_resume(mac_dev->port_dev[RX]);
+ if (err)
+ err = fm_port_suspend(mac_dev->port_dev[TX]);
+ }
+
+port_resume_failed:
+ return err;
+}
+
+static const struct dev_pm_ops shared_pm_ops = {
+ .suspend_noirq = dpa_shared_suspend_noirq,
+ .resume_noirq = dpa_shared_resume_noirq,
+};
+
+#define SHARED_PM_OPS (&shared_pm_ops)
+
+#else /* CONFIG_PM */
+
+#define SHARED_PM_OPS NULL
+
+#endif /* CONFIG_PM */
+
+static int
+dpaa_eth_shared_probe(struct platform_device *_of_dev)
+{
+ int err = 0, i;
+ struct device *dev;
+ struct device_node *dpa_node;
+ struct dpa_bp *dpa_bp;
+ struct dpa_fq *dpa_fq, *tmp;
+ size_t count;
+ struct net_device *net_dev = NULL;
+ struct dpa_priv_s *priv = NULL;
+ struct dpa_percpu_priv_s *percpu_priv;
+ struct fm_port_fqs port_fqs;
+ struct dpa_buffer_layout_s *buf_layout = NULL;
+ struct mac_device *mac_dev;
+ struct task_struct *kth;
+
+ dev = &_of_dev->dev;
+
+ dpa_node = dev->of_node;
+
+ if (!of_device_is_available(dpa_node))
+ return -ENODEV;
+
+ /* Get the buffer pools assigned to this interface */
+ dpa_bp = dpa_bp_probe(_of_dev, &count);
+ if (IS_ERR(dpa_bp))
+ return PTR_ERR(dpa_bp);
+
+ for (i = 0; i < count; i++)
+ dpa_bp[i].seed_cb = dpa_bp_shared_port_seed;
+
+ /* Allocate this early, so we can store relevant information in
+ * the private area (needed by 1588 code in dpa_mac_probe)
+ */
+ net_dev = alloc_etherdev_mq(sizeof(*priv), DPAA_ETH_TX_QUEUES);
+ if (!net_dev) {
+ dev_err(dev, "alloc_etherdev_mq() failed\n");
+ return -ENOMEM;
+ }
+
+ /* Do this here, so we can be verbose early */
+ SET_NETDEV_DEV(net_dev, dev);
+ dev_set_drvdata(dev, net_dev);
+
+ priv = netdev_priv(net_dev);
+ priv->net_dev = net_dev;
+ strcpy(priv->if_type, "shared");
+
+ priv->msg_enable = netif_msg_init(debug, -1);
+
+ mac_dev = dpa_mac_probe(_of_dev);
+ if (IS_ERR(mac_dev) || !mac_dev) {
+ err = PTR_ERR(mac_dev);
+ goto mac_probe_failed;
+ }
+
+ /* We have physical ports, so we need to establish
+ * the buffer layout.
+ */
+ buf_layout = devm_kzalloc(dev, 2 * sizeof(*buf_layout),
+ GFP_KERNEL);
+ if (!buf_layout) {
+ dev_err(dev, "devm_kzalloc() failed\n");
+ goto alloc_failed;
+ }
+ dpa_set_buffers_layout(mac_dev, buf_layout);
+
+ INIT_LIST_HEAD(&priv->dpa_fq_list);
+
+ memset(&port_fqs, 0, sizeof(port_fqs));
+
+ err = dpa_fq_probe_mac(dev, &priv->dpa_fq_list, &port_fqs,
+ false, RX);
+ if (!err)
+ err = dpa_fq_probe_mac(dev, &priv->dpa_fq_list,
+ &port_fqs, false, TX);
+ if (err < 0)
+ goto fq_probe_failed;
+
+ /* bp init */
+ priv->bp_count = count;
+ err = dpa_bp_create(net_dev, dpa_bp, count);
+ if (err < 0)
+ goto bp_create_failed;
+
+ priv->mac_dev = mac_dev;
+
+ priv->channel = dpa_get_channel();
+
+ if (priv->channel < 0) {
+ err = priv->channel;
+ goto get_channel_failed;
+ }
+
+ /* Start a thread that will walk the cpus with affine portals
+ * and add this pool channel to each's dequeue mask.
+ */
+ kth = kthread_run(dpaa_eth_add_channel,
+ (void *)(unsigned long)priv->channel,
+ "dpaa_%p:%d", net_dev, priv->channel);
+ if (!kth) {
+ err = -ENOMEM;
+ goto add_channel_failed;
+ }
+
+ dpa_fq_setup(priv, &shared_fq_cbs, priv->mac_dev->port_dev[TX]);
+
+ /* Create a congestion group for this netdev, with
+ * dynamically-allocated CGR ID.
+ * Must be executed after probing the MAC, but before
+ * assigning the egress FQs to the CGRs.
+ */
+ err = dpaa_eth_cgr_init(priv);
+ if (err < 0) {
+ dev_err(dev, "Error initializing CGR\n");
+ goto cgr_init_failed;
+ }
+
+ /* Add the FQs to the interface, and make them active */
+ list_for_each_entry_safe(dpa_fq, tmp, &priv->dpa_fq_list, list) {
+ err = dpa_fq_init(dpa_fq, false);
+ if (err < 0)
+ goto fq_alloc_failed;
+ }
+
+ priv->buf_layout = buf_layout;
+ priv->tx_headroom =
+ dpa_get_headroom(&priv->buf_layout[TX]);
+
+ /* All real interfaces need their ports initialized */
+ dpaa_eth_init_ports(mac_dev, dpa_bp, count, &port_fqs,
+ buf_layout, dev);
+
+ /* Now we need to initialize either a private or shared interface */
+ priv->percpu_priv = alloc_percpu(*priv->percpu_priv);
+
+ if (priv->percpu_priv == NULL) {
+ dev_err(dev, "alloc_percpu() failed\n");
+ err = -ENOMEM;
+ goto alloc_percpu_failed;
+ }
+ for_each_possible_cpu(i) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+ memset(percpu_priv, 0, sizeof(*percpu_priv));
+ }
+
+ err = dpa_shared_netdev_init(dpa_node, net_dev);
+
+ if (err < 0)
+ goto netdev_init_failed;
+
+ dpaa_eth_sysfs_init(&net_dev->dev);
+
+ pr_info("fsl_dpa_shared: Probed shared interface %s\n",
+ net_dev->name);
+
+ return 0;
+
+netdev_init_failed:
+ if (net_dev)
+ free_percpu(priv->percpu_priv);
+alloc_percpu_failed:
+fq_alloc_failed:
+ if (net_dev) {
+ dpa_fq_free(dev, &priv->dpa_fq_list);
+ qman_release_cgrid(priv->cgr_data.cgr.cgrid);
+ qman_delete_cgr(&priv->cgr_data.cgr);
+ }
+cgr_init_failed:
+add_channel_failed:
+get_channel_failed:
+ if (net_dev)
+ dpa_bp_free(priv, priv->dpa_bp);
+bp_create_failed:
+fq_probe_failed:
+ devm_kfree(dev, buf_layout);
+alloc_failed:
+mac_probe_failed:
+ dev_set_drvdata(dev, NULL);
+ if (net_dev)
+ free_netdev(net_dev);
+
+ return err;
+}
+
+static const struct of_device_id dpa_shared_match[] = {
+ {
+ .compatible = "fsl,dpa-ethernet-shared"
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, dpa_shared_match);
+
+static struct platform_driver dpa_shared_driver = {
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .of_match_table = dpa_shared_match,
+ .owner = THIS_MODULE,
+ .pm = SHARED_PM_OPS,
+ },
+ .probe = dpaa_eth_shared_probe,
+ .remove = dpa_remove
+};
+
+static int __init __cold dpa_shared_load(void)
+{
+ int _errno;
+
+ pr_info(DPA_DESCRIPTION " (" VERSION ")\n");
+
+ /* Initialize dpaa_eth mirror values */
+ dpa_rx_extra_headroom = fm_get_rx_extra_headroom();
+ dpa_max_frm = fm_get_max_frm();
+
+ _errno = platform_driver_register(&dpa_shared_driver);
+ if (unlikely(_errno < 0)) {
+ pr_err(KBUILD_MODNAME
+ ": %s:%hu:%s(): platform_driver_register() = %d\n",
+ KBUILD_BASENAME".c", __LINE__, __func__, _errno);
+ }
+
+ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n",
+ KBUILD_BASENAME".c", __func__);
+
+ return _errno;
+}
+module_init(dpa_shared_load);
+
+static void __exit __cold dpa_shared_unload(void)
+{
+ pr_debug(KBUILD_MODNAME ": -> %s:%s()\n",
+ KBUILD_BASENAME".c", __func__);
+
+ platform_driver_unregister(&dpa_shared_driver);
+}
+module_exit(dpa_shared_unload);
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth_sysfs.c b/drivers/net/ethernet/freescale/dpa/dpaa_eth_sysfs.c
new file mode 100644
index 0000000..bf01677
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth_sysfs.c
@@ -0,0 +1,248 @@
+/* Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kthread.h>
+#include <linux/io.h>
+#include <linux/of_net.h>
+#include "dpaa_eth.h"
+#include "mac.h" /* struct mac_device */
+#ifdef CONFIG_FSL_DPAA_1588
+#include "dpaa_1588.h"
+#endif
+
+static ssize_t dpaa_eth_show_addr(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dpa_priv_s *priv = netdev_priv(to_net_dev(dev));
+ struct mac_device *mac_dev = priv->mac_dev;
+
+ if (mac_dev)
+ return sprintf(buf, "%llx",
+ (unsigned long long)mac_dev->res->start);
+ else
+ return sprintf(buf, "none");
+}
+
+static ssize_t dpaa_eth_show_type(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dpa_priv_s *priv = netdev_priv(to_net_dev(dev));
+ ssize_t res = 0;
+
+ if (priv)
+ res = sprintf(buf, "%s", priv->if_type);
+
+ return res;
+}
+
+static ssize_t dpaa_eth_show_fqids(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dpa_priv_s *priv = netdev_priv(to_net_dev(dev));
+ ssize_t bytes = 0;
+ int i = 0;
+ char *str;
+ struct dpa_fq *fq;
+ struct dpa_fq *tmp;
+ struct dpa_fq *prev = NULL;
+ u32 first_fqid = 0;
+ u32 last_fqid = 0;
+ char *prevstr = NULL;
+
+ list_for_each_entry_safe(fq, tmp, &priv->dpa_fq_list, list) {
+ switch (fq->fq_type) {
+ case FQ_TYPE_RX_DEFAULT:
+ str = "Rx default";
+ break;
+ case FQ_TYPE_RX_ERROR:
+ str = "Rx error";
+ break;
+ case FQ_TYPE_RX_PCD:
+ str = "Rx PCD";
+ break;
+ case FQ_TYPE_TX_CONFIRM:
+ str = "Tx default confirmation";
+ break;
+ case FQ_TYPE_TX_CONF_MQ:
+ str = "Tx confirmation (mq)";
+ break;
+ case FQ_TYPE_TX_ERROR:
+ str = "Tx error";
+ break;
+ case FQ_TYPE_TX:
+ str = "Tx";
+ break;
+#ifdef CONFIG_FMAN_T4240
+ case FQ_TYPE_TX_RECYCLE:
+ str = "Tx(recycling)";
+ break;
+#endif
+ default:
+ str = "Unknown";
+ }
+
+ if (prev && (abs(fq->fqid - prev->fqid) != 1 ||
+ str != prevstr)) {
+ if (last_fqid == first_fqid)
+ bytes += sprintf(buf + bytes,
+ "%s: %d\n", prevstr, prev->fqid);
+ else
+ bytes += sprintf(buf + bytes,
+ "%s: %d - %d\n", prevstr,
+ first_fqid, last_fqid);
+ }
+
+ if (prev && abs(fq->fqid - prev->fqid) == 1 && str == prevstr)
+ last_fqid = fq->fqid;
+ else
+ first_fqid = last_fqid = fq->fqid;
+
+ prev = fq;
+ prevstr = str;
+ i++;
+ }
+
+ if (prev) {
+ if (last_fqid == first_fqid)
+ bytes += sprintf(buf + bytes, "%s: %d\n", prevstr,
+ prev->fqid);
+ else
+ bytes += sprintf(buf + bytes, "%s: %d - %d\n", prevstr,
+ first_fqid, last_fqid);
+ }
+
+ return bytes;
+}
+
+static ssize_t dpaa_eth_show_bpids(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t bytes = 0;
+ struct dpa_priv_s *priv = netdev_priv(to_net_dev(dev));
+ struct dpa_bp *dpa_bp = priv->dpa_bp;
+ int i = 0;
+
+ for (i = 0; i < priv->bp_count; i++)
+ bytes += snprintf(buf + bytes, PAGE_SIZE, "%u\n",
+ dpa_bp[i].bpid);
+
+ return bytes;
+}
+
+static ssize_t dpaa_eth_show_mac_regs(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dpa_priv_s *priv = netdev_priv(to_net_dev(dev));
+ struct mac_device *mac_dev = priv->mac_dev;
+ int n = 0;
+
+ if (mac_dev)
+ n = fm_mac_dump_regs(mac_dev, buf, n);
+ else
+ return sprintf(buf, "no mac registers\n");
+
+ return n;
+}
+
+
+#ifdef CONFIG_FSL_DPAA_1588
+static ssize_t dpaa_eth_show_ptp_1588(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dpa_priv_s *priv = netdev_priv(to_net_dev(dev));
+
+ if (priv->tsu && priv->tsu->valid)
+ return sprintf(buf, "1\n");
+ else
+ return sprintf(buf, "0\n");
+}
+
+static ssize_t dpaa_eth_set_ptp_1588(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct dpa_priv_s *priv = netdev_priv(to_net_dev(dev));
+ unsigned int num;
+ unsigned long flags;
+
+ if (kstrtouint(buf, 0, &num) < 0)
+ return -EINVAL;
+
+ local_irq_save(flags);
+
+ if (num) {
+ if (priv->tsu)
+ priv->tsu->valid = TRUE;
+ } else {
+ if (priv->tsu)
+ priv->tsu->valid = FALSE;
+ }
+
+ local_irq_restore(flags);
+
+ return count;
+}
+#endif
+
+static struct device_attribute dpaa_eth_attrs[] = {
+ __ATTR(device_addr, S_IRUGO, dpaa_eth_show_addr, NULL),
+ __ATTR(device_type, S_IRUGO, dpaa_eth_show_type, NULL),
+ __ATTR(fqids, S_IRUGO, dpaa_eth_show_fqids, NULL),
+ __ATTR(bpids, S_IRUGO, dpaa_eth_show_bpids, NULL),
+ __ATTR(mac_regs, S_IRUGO, dpaa_eth_show_mac_regs, NULL),
+#ifdef CONFIG_FSL_DPAA_1588
+ __ATTR(ptp_1588, S_IRUGO | S_IWUSR, dpaa_eth_show_ptp_1588,
+ dpaa_eth_set_ptp_1588),
+#endif
+};
+
+void dpaa_eth_sysfs_init(struct device *dev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(dpaa_eth_attrs); i++)
+ if (device_create_file(dev, &dpaa_eth_attrs[i])) {
+ dev_err(dev, "Error creating sysfs file\n");
+ while (i > 0)
+ device_remove_file(dev, &dpaa_eth_attrs[--i]);
+ return;
+ }
+}
+
+void dpaa_eth_sysfs_remove(struct device *dev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(dpaa_eth_attrs); i++)
+ device_remove_file(dev, &dpaa_eth_attrs[i]);
+}
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_eth_trace.h b/drivers/net/ethernet/freescale/dpa/dpaa_eth_trace.h
new file mode 100644
index 0000000..30069ef
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_eth_trace.h
@@ -0,0 +1,144 @@
+/* Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM dpaa_eth
+
+#if !defined(_DPAA_ETH_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _DPAA_ETH_TRACE_H
+
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include "dpaa_eth.h"
+#include <linux/tracepoint.h>
+
+#define fd_format_name(format) { qm_fd_##format, #format }
+#define fd_format_list \
+ fd_format_name(contig), \
+ fd_format_name(sg)
+#define TR_FMT "[%s] fqid=%d, fd: addr=0x%llx, format=%s, off=%u, len=%u," \
+ " status=0x%08x"
+
+/* This is used to declare a class of events.
+ * individual events of this type will be defined below.
+ */
+
+/* Store details about a frame descriptor and the FQ on which it was
+ * transmitted/received.
+ */
+DECLARE_EVENT_CLASS(dpaa_eth_fd,
+ /* Trace function prototype */
+ TP_PROTO(struct net_device *netdev,
+ struct qman_fq *fq,
+ const struct qm_fd *fd),
+
+ /* Repeat argument list here */
+ TP_ARGS(netdev, fq, fd),
+
+ /* A structure containing the relevant information we want to record.
+ * Declare name and type for each normal element, name, type and size
+ * for arrays. Use __string for variable length strings.
+ */
+ TP_STRUCT__entry(
+ __field(u32, fqid)
+ __field(u64, fd_addr)
+ __field(u8, fd_format)
+ __field(u16, fd_offset)
+ __field(u32, fd_length)
+ __field(u32, fd_status)
+ __string(name, netdev->name)
+ ),
+
+ /* The function that assigns values to the above declared fields */
+ TP_fast_assign(
+ __entry->fqid = fq->fqid;
+ __entry->fd_addr = qm_fd_addr_get64(fd);
+ __entry->fd_format = fd->format;
+ __entry->fd_offset = dpa_fd_offset(fd);
+ __entry->fd_length = dpa_fd_length(fd);
+ __entry->fd_status = fd->status;
+ __assign_str(name, netdev->name);
+ ),
+
+ /* This is what gets printed when the trace event is triggered */
+ /* TODO: print the status using __print_flags() */
+ TP_printk(TR_FMT,
+ __get_str(name), __entry->fqid, __entry->fd_addr,
+ __print_symbolic(__entry->fd_format, fd_format_list),
+ __entry->fd_offset, __entry->fd_length, __entry->fd_status)
+);
+
+/* Now declare events of the above type. Format is:
+ * DEFINE_EVENT(class, name, proto, args), with proto and args same as for class
+ */
+
+/* Tx (egress) fd */
+DEFINE_EVENT(dpaa_eth_fd, dpa_tx_fd,
+
+ TP_PROTO(struct net_device *netdev,
+ struct qman_fq *fq,
+ const struct qm_fd *fd),
+
+ TP_ARGS(netdev, fq, fd)
+);
+
+/* Rx fd */
+DEFINE_EVENT(dpaa_eth_fd, dpa_rx_fd,
+
+ TP_PROTO(struct net_device *netdev,
+ struct qman_fq *fq,
+ const struct qm_fd *fd),
+
+ TP_ARGS(netdev, fq, fd)
+);
+
+/* Tx confirmation fd */
+DEFINE_EVENT(dpaa_eth_fd, dpa_tx_conf_fd,
+
+ TP_PROTO(struct net_device *netdev,
+ struct qman_fq *fq,
+ const struct qm_fd *fd),
+
+ TP_ARGS(netdev, fq, fd)
+);
+
+/* If only one event of a certain type needs to be declared, use TRACE_EVENT().
+ * The syntax is the same as for DECLARE_EVENT_CLASS().
+ */
+
+#endif /* _DPAA_ETH_TRACE_H */
+
+/* This must be outside ifdef _DPAA_ETH_TRACE_H */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE dpaa_eth_trace
+#include <trace/define_trace.h>
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_ethtool.c b/drivers/net/ethernet/freescale/dpa/dpaa_ethtool.c
new file mode 100644
index 0000000..d36930e
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_ethtool.c
@@ -0,0 +1,343 @@
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef CONFIG_FSL_DPAA_ETH_DEBUG
+#define pr_fmt(fmt) \
+ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \
+ KBUILD_BASENAME".c", __LINE__, __func__
+#else
+#define pr_fmt(fmt) \
+ KBUILD_MODNAME ": " fmt
+#endif
+
+#include <linux/string.h>
+
+#include "dpaa_eth.h"
+#include "mac.h" /* struct mac_device */
+#include "dpaa_eth_common.h"
+
+static int __cold dpa_get_settings(struct net_device *net_dev,
+ struct ethtool_cmd *et_cmd)
+{
+ int _errno;
+ struct dpa_priv_s *priv;
+
+ priv = netdev_priv(net_dev);
+
+ if (priv->mac_dev == NULL) {
+ netdev_info(net_dev, "This is a MAC-less interface\n");
+ return -ENODEV;
+ }
+ if (unlikely(priv->mac_dev->phy_dev == NULL)) {
+ netdev_dbg(net_dev, "phy device not initialized\n");
+ return 0;
+ }
+
+ _errno = phy_ethtool_gset(priv->mac_dev->phy_dev, et_cmd);
+ if (unlikely(_errno < 0))
+ netdev_err(net_dev, "phy_ethtool_gset() = %d\n", _errno);
+
+ return _errno;
+}
+
+static int __cold dpa_set_settings(struct net_device *net_dev,
+ struct ethtool_cmd *et_cmd)
+{
+ int _errno;
+ struct dpa_priv_s *priv;
+
+ priv = netdev_priv(net_dev);
+
+ if (priv->mac_dev == NULL) {
+ netdev_info(net_dev, "This is a MAC-less interface\n");
+ return -ENODEV;
+ }
+ if (unlikely(priv->mac_dev->phy_dev == NULL)) {
+ netdev_err(net_dev, "phy device not initialized\n");
+ return -ENODEV;
+ }
+
+ _errno = phy_ethtool_sset(priv->mac_dev->phy_dev, et_cmd);
+ if (unlikely(_errno < 0))
+ netdev_err(net_dev, "phy_ethtool_sset() = %d\n", _errno);
+
+ return _errno;
+}
+
+static void __cold dpa_get_drvinfo(struct net_device *net_dev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ int _errno;
+
+ strncpy(drvinfo->driver, KBUILD_MODNAME,
+ sizeof(drvinfo->driver) - 1)[sizeof(drvinfo->driver)-1] = 0;
+ strncpy(drvinfo->version, VERSION,
+ sizeof(drvinfo->driver) - 1)[sizeof(drvinfo->version)-1] = 0;
+ _errno = snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
+ "%X", 0);
+
+ if (unlikely(_errno >= sizeof(drvinfo->fw_version))) {
+ /* Truncated output */
+ netdev_notice(net_dev, "snprintf() = %d\n", _errno);
+ } else if (unlikely(_errno < 0)) {
+ netdev_warn(net_dev, "snprintf() = %d\n", _errno);
+ memset(drvinfo->fw_version, 0, sizeof(drvinfo->fw_version));
+ }
+ strncpy(drvinfo->bus_info, dev_name(net_dev->dev.parent->parent),
+ sizeof(drvinfo->bus_info)-1)[sizeof(drvinfo->bus_info)-1] = 0;
+}
+
+static uint32_t __cold dpa_get_msglevel(struct net_device *net_dev)
+{
+ return ((struct dpa_priv_s *)netdev_priv(net_dev))->msg_enable;
+}
+
+static void __cold dpa_set_msglevel(struct net_device *net_dev,
+ uint32_t msg_enable)
+{
+ ((struct dpa_priv_s *)netdev_priv(net_dev))->msg_enable = msg_enable;
+}
+
+static int __cold dpa_nway_reset(struct net_device *net_dev)
+{
+ int _errno;
+ struct dpa_priv_s *priv;
+
+ priv = netdev_priv(net_dev);
+
+ if (priv->mac_dev == NULL) {
+ netdev_info(net_dev, "This is a MAC-less interface\n");
+ return -ENODEV;
+ }
+ if (unlikely(priv->mac_dev->phy_dev == NULL)) {
+ netdev_err(net_dev, "phy device not initialized\n");
+ return -ENODEV;
+ }
+
+ _errno = 0;
+ if (priv->mac_dev->phy_dev->autoneg) {
+ _errno = phy_start_aneg(priv->mac_dev->phy_dev);
+ if (unlikely(_errno < 0))
+ netdev_err(net_dev, "phy_start_aneg() = %d\n",
+ _errno);
+ }
+
+ return _errno;
+}
+
+static void __cold dpa_get_ringparam(struct net_device *net_dev,
+ struct ethtool_ringparam *et_ringparam)
+{
+ et_ringparam->rx_max_pending = 0;
+ et_ringparam->rx_mini_max_pending = 0;
+ et_ringparam->rx_jumbo_max_pending = 0;
+ et_ringparam->tx_max_pending = 0;
+
+ et_ringparam->rx_pending = 0;
+ et_ringparam->rx_mini_pending = 0;
+ et_ringparam->rx_jumbo_pending = 0;
+ et_ringparam->tx_pending = 0;
+}
+
+static void __cold dpa_get_pauseparam(struct net_device *net_dev,
+ struct ethtool_pauseparam *epause)
+{
+ struct dpa_priv_s *priv;
+ struct mac_device *mac_dev;
+ struct phy_device *phy_dev;
+
+ priv = netdev_priv(net_dev);
+ mac_dev = priv->mac_dev;
+
+ if (mac_dev == NULL) {
+ netdev_info(net_dev, "This is a MAC-less interface\n");
+ return;
+ }
+
+ phy_dev = mac_dev->phy_dev;
+ if (unlikely(phy_dev == NULL)) {
+ netdev_err(net_dev, "phy device not initialized\n");
+ return;
+ }
+
+ epause->autoneg = mac_dev->autoneg_pause;
+ epause->rx_pause = mac_dev->rx_pause;
+ epause->tx_pause = mac_dev->tx_pause;
+}
+
+static int __cold dpa_set_pauseparam(struct net_device *net_dev,
+ struct ethtool_pauseparam *epause)
+{
+ struct dpa_priv_s *priv;
+ struct mac_device *mac_dev;
+ struct phy_device *phy_dev;
+ int _errno;
+ u32 newadv, oldadv;
+
+ priv = netdev_priv(net_dev);
+ mac_dev = priv->mac_dev;
+
+ if (mac_dev == NULL) {
+ netdev_info(net_dev, "This is a MAC-less interface\n");
+ return -ENODEV;
+ }
+
+ phy_dev = mac_dev->phy_dev;
+ if (unlikely(phy_dev == NULL)) {
+ netdev_err(net_dev, "phy device not initialized\n");
+ return -ENODEV;
+ }
+
+ if (!(phy_dev->supported & SUPPORTED_Pause) ||
+ (!(phy_dev->supported & SUPPORTED_Asym_Pause) &&
+ (epause->rx_pause != epause->tx_pause)))
+ return -EINVAL;
+
+ /* The MAC should know how to handle PAUSE frame autonegotiation before
+ * adjust_link is triggered by a forced renegotiation of sym/asym PAUSE
+ * settings.
+ */
+ mac_dev->autoneg_pause = epause->autoneg;
+
+ /* Determine the sym/asym advertised PAUSE capabilities from the desired
+ * rx/tx pause settings.
+ */
+ newadv = 0;
+ if (epause->rx_pause)
+ newadv = ADVERTISED_Pause | ADVERTISED_Asym_Pause;
+ if (epause->tx_pause)
+ newadv |= ADVERTISED_Asym_Pause;
+
+ oldadv = phy_dev->advertising &
+ (ADVERTISED_Pause | ADVERTISED_Asym_Pause);
+
+ /* If there are differences between the old and the new advertised
+ * values, restart PHY autonegotiation and advertise the new values.
+ */
+ if (oldadv != newadv) {
+ phy_dev->advertising &= ~(ADVERTISED_Pause
+ | ADVERTISED_Asym_Pause);
+ phy_dev->advertising |= newadv;
+ if (phy_dev->autoneg) {
+ _errno = phy_start_aneg(phy_dev);
+ if (unlikely(_errno < 0))
+ netdev_err(net_dev, "phy_start_aneg() = %d\n",
+ _errno);
+ }
+ }
+
+ if (epause->autoneg)
+ return 0;
+
+ /* If PAUSE frame autonegotiation is disabled,
+ * ethtool rx/tx settings are enforced.
+ */
+ _errno = set_mac_rx_pause(mac_dev, !!epause->rx_pause);
+ if (unlikely(_errno < 0)) {
+ netdev_err(net_dev, "set_mac_rx_pause() = %d\n", _errno);
+ return _errno;
+ }
+
+ _errno = set_mac_tx_pause(mac_dev, !!epause->tx_pause);
+ if (unlikely(_errno < 0)) {
+ netdev_err(net_dev, "set_mac_tx_pause() = %d\n", _errno);
+ return _errno;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static void dpa_get_wol(struct net_device *net_dev, struct ethtool_wolinfo *wol)
+{
+ struct dpa_priv_s *priv = netdev_priv(net_dev);
+
+ wol->supported = 0;
+ wol->wolopts = 0;
+
+ if (!priv->wol || !device_can_wakeup(net_dev->dev.parent))
+ return;
+
+ if (priv->wol & DPAA_WOL_MAGIC) {
+ wol->supported = WAKE_MAGIC;
+ wol->wolopts = WAKE_MAGIC;
+ }
+}
+
+static int dpa_set_wol(struct net_device *net_dev, struct ethtool_wolinfo *wol)
+{
+ struct dpa_priv_s *priv = netdev_priv(net_dev);
+
+ if (priv->mac_dev == NULL) {
+ netdev_info(net_dev, "This is a MAC-less interface\n");
+ return -ENODEV;
+ }
+
+ if (unlikely(priv->mac_dev->phy_dev == NULL)) {
+ netdev_dbg(net_dev, "phy device not initialized\n");
+ return -ENODEV;
+ }
+
+ if (!device_can_wakeup(net_dev->dev.parent) ||
+ (wol->wolopts & ~WAKE_MAGIC))
+ return -EOPNOTSUPP;
+
+ priv->wol = 0;
+
+ if (wol->wolopts & WAKE_MAGIC) {
+ priv->wol = DPAA_WOL_MAGIC;
+ device_set_wakeup_enable(net_dev->dev.parent, 1);
+ } else {
+ device_set_wakeup_enable(net_dev->dev.parent, 0);
+ }
+
+ return 0;
+}
+#endif
+
+const struct ethtool_ops dpa_ethtool_ops = {
+ .get_settings = dpa_get_settings,
+ .set_settings = dpa_set_settings,
+ .get_drvinfo = dpa_get_drvinfo,
+ .get_msglevel = dpa_get_msglevel,
+ .set_msglevel = dpa_set_msglevel,
+ .nway_reset = dpa_nway_reset,
+ .get_ringparam = dpa_get_ringparam,
+ .get_pauseparam = dpa_get_pauseparam,
+ .set_pauseparam = dpa_set_pauseparam,
+ .self_test = NULL, /* TODO invoke the cold-boot unit-test? */
+ .get_ethtool_stats = NULL, /* TODO other stats, currently in debugfs */
+ .get_link = ethtool_op_get_link,
+#ifdef CONFIG_PM
+ .get_wol = dpa_get_wol,
+ .set_wol = dpa_set_wol,
+#endif
+};
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_generic_debugfs.c b/drivers/net/ethernet/freescale/dpa/dpaa_generic_debugfs.c
new file mode 100644
index 0000000..6ab1ade
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_generic_debugfs.c
@@ -0,0 +1,283 @@
+/* Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/module.h>
+#include <linux/fsl_qman.h>
+#include <linux/debugfs.h>
+#include <asm/debug.h>
+
+#include "dpaa_eth_generic.h"
+
+#define DPA_DEBUGFS_DESCRIPTION "FSL DPAA Ethernet debugfs entries"
+#define DPA_GENERIC_ETH_DEBUGFS_ROOT "fsl_generic_dpa"
+
+static int __cold dpa_generic_debugfs_open(struct inode *inode,
+ struct file *file);
+
+static struct dentry *dpa_debugfs_root;
+static const struct file_operations dpa_debugfs_fops = {
+ .open = dpa_generic_debugfs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int dpa_generic_debugfs_show(struct seq_file *file, void *offset)
+{
+ int i;
+ struct dpa_generic_priv_s *priv;
+ struct dpa_percpu_priv_s *percpu_priv, total;
+ struct dpa_bp *bp;
+ unsigned int dpa_bp_count = 0;
+ unsigned int count_total = 0;
+
+ BUG_ON(offset == NULL);
+
+ priv = netdev_priv((struct net_device *)file->private);
+
+ bp = priv->rx_bp;
+
+ memset(&total, 0, sizeof(total));
+
+ /* "Standard" counters */
+ seq_printf(file, "\nDPA counters for %s:\n", priv->net_dev->name);
+ seq_puts(file, "CPU irqs rx tx recycle ");
+ seq_puts(file, "confirm tx sg tx err rx err bp count\n");
+
+
+ for_each_online_cpu(i) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+
+ if (bp->percpu_count)
+ dpa_bp_count = *(per_cpu_ptr(bp->percpu_count, i));
+
+ total.in_interrupt += percpu_priv->in_interrupt;
+ total.stats.rx_packets += percpu_priv->stats.rx_packets;
+ total.stats.tx_packets += percpu_priv->stats.tx_packets;
+ total.tx_returned += percpu_priv->tx_returned;
+ total.tx_confirm += percpu_priv->tx_confirm;
+ total.tx_frag_skbuffs += percpu_priv->tx_frag_skbuffs;
+ total.stats.tx_errors += percpu_priv->stats.tx_errors;
+ total.stats.rx_errors += percpu_priv->stats.rx_errors;
+ count_total += dpa_bp_count;
+
+ seq_printf(file, " %hu %8llu %8llu %8llu %8llu ",
+ i,
+ percpu_priv->in_interrupt,
+ percpu_priv->stats.rx_packets,
+ percpu_priv->stats.tx_packets,
+ percpu_priv->tx_returned);
+ seq_printf(file, "%8llu %8llu %8llu %8llu %8d\n",
+ percpu_priv->tx_confirm,
+ percpu_priv->tx_frag_skbuffs,
+ percpu_priv->stats.tx_errors,
+ percpu_priv->stats.rx_errors,
+ dpa_bp_count);
+ }
+ seq_printf(file, "Total %8llu %8llu %8llu %8llu ",
+ total.in_interrupt,
+ total.stats.rx_packets,
+ total.stats.tx_packets,
+ total.tx_returned);
+ seq_printf(file, "%8llu %8llu %8llu %8llu %8d\n",
+ total.tx_confirm,
+ total.tx_frag_skbuffs,
+ total.stats.tx_errors,
+ total.stats.rx_errors,
+ count_total);
+
+ /* Draining Buffer Pool counters */
+ seq_printf(file, "\nCounters for Draining Buffer Pool (bpid:%d) %s:\n",
+ bp->bpid, priv->net_dev->name);
+ seq_puts(file, "CPU bp count\n");
+
+ bp = priv->draining_tx_bp;
+ dpa_bp_count = 0;
+ count_total = 0;
+
+ for_each_online_cpu(i) {
+ if (bp->percpu_count)
+ dpa_bp_count = *(per_cpu_ptr(bp->percpu_count, i));
+ count_total += dpa_bp_count;
+
+ seq_printf(file, " %hu %8d\n", i, dpa_bp_count);
+ }
+ seq_printf(file, "Total %8d\n", count_total);
+
+
+ /* Rx Errors demultiplexing */
+ seq_puts(file, "\nDPA RX Errors:\nCPU dma err phys err");
+ seq_puts(file, " size err hdr err csum err\n");
+ for_each_online_cpu(i) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+
+ total.rx_errors.dme += percpu_priv->rx_errors.dme;
+ total.rx_errors.fpe += percpu_priv->rx_errors.fpe;
+ total.rx_errors.fse += percpu_priv->rx_errors.fse;
+ total.rx_errors.phe += percpu_priv->rx_errors.phe;
+ total.rx_errors.cse += percpu_priv->rx_errors.cse;
+
+ seq_printf(file, " %hu %8llu %8llu ",
+ i,
+ percpu_priv->rx_errors.dme,
+ percpu_priv->rx_errors.fpe);
+ seq_printf(file, "%8llu %8llu %8llu\n",
+ percpu_priv->rx_errors.fse,
+ percpu_priv->rx_errors.phe,
+ percpu_priv->rx_errors.cse);
+ }
+ seq_printf(file, "Total %8llu %8llu %8llu %8llu %8llu\n",
+ total.rx_errors.dme,
+ total.rx_errors.fpe,
+ total.rx_errors.fse,
+ total.rx_errors.phe,
+ total.rx_errors.cse);
+
+ /* ERN demultiplexing */
+ seq_puts(file, "\nDPA ERN counters:\n CPU cg_td wred ");
+ seq_puts(file, "err_cond early_w late_w fq_td fq_ret");
+ seq_puts(file, " orp_z\n");
+ for_each_online_cpu(i) {
+ percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+
+ total.ern_cnt.cg_tdrop += percpu_priv->ern_cnt.cg_tdrop;
+ total.ern_cnt.wred += percpu_priv->ern_cnt.wred;
+ total.ern_cnt.err_cond += percpu_priv->ern_cnt.err_cond;
+ total.ern_cnt.early_window += percpu_priv->ern_cnt.early_window;
+ total.ern_cnt.late_window += percpu_priv->ern_cnt.late_window;
+ total.ern_cnt.fq_tdrop += percpu_priv->ern_cnt.fq_tdrop;
+ total.ern_cnt.fq_retired += percpu_priv->ern_cnt.fq_retired;
+ total.ern_cnt.orp_zero += percpu_priv->ern_cnt.orp_zero;
+
+ seq_printf(file, " %hu %8llu %8llu %8llu %8llu ",
+ i,
+ percpu_priv->ern_cnt.cg_tdrop,
+ percpu_priv->ern_cnt.wred,
+ percpu_priv->ern_cnt.err_cond,
+ percpu_priv->ern_cnt.early_window);
+ seq_printf(file, "%8llu %8llu %8llu %8llu\n",
+ percpu_priv->ern_cnt.late_window,
+ percpu_priv->ern_cnt.fq_tdrop,
+ percpu_priv->ern_cnt.fq_retired,
+ percpu_priv->ern_cnt.orp_zero);
+ }
+ seq_printf(file, "Total%8llu %8llu %8llu %8llu ",
+ total.ern_cnt.cg_tdrop,
+ total.ern_cnt.wred,
+ total.ern_cnt.err_cond,
+ total.ern_cnt.early_window);
+ seq_printf(file, "%8llu %8llu %8llu %8llu\n",
+ total.ern_cnt.late_window,
+ total.ern_cnt.fq_tdrop,
+ total.ern_cnt.fq_retired,
+ total.ern_cnt.orp_zero);
+
+ return 0;
+}
+
+static int __cold dpa_generic_debugfs_open(struct inode *inode,
+ struct file *file)
+{
+ int _errno;
+ const struct net_device *net_dev =
+ (struct net_device *)inode->i_private;
+
+ _errno = single_open(file, dpa_generic_debugfs_show, inode->i_private);
+ if (unlikely(_errno < 0))
+ if (netif_msg_drv((struct dpa_generic_priv_s *)
+ netdev_priv(net_dev)))
+ netdev_err(net_dev, "single_open() = %d\n", _errno);
+
+ return _errno;
+}
+
+int dpa_generic_debugfs_create(struct net_device *net_dev)
+{
+ struct dpa_generic_priv_s *priv = netdev_priv(net_dev);
+
+ if (unlikely(dpa_debugfs_root == NULL)) {
+ pr_err(KBUILD_MODNAME ": %s:%hu:%s(): \t%s\n",
+ KBUILD_BASENAME".c", __LINE__, __func__,
+ "root debugfs missing, possible module ordering issue");
+ return -ENOMEM;
+ }
+
+ priv->debugfs_file = debugfs_create_file(net_dev->name,
+ S_IRUGO,
+ dpa_debugfs_root,
+ net_dev,
+ &dpa_debugfs_fops);
+ if (unlikely(priv->debugfs_file == NULL)) {
+ netdev_err(net_dev, "debugfs_create_file(%s/%s/%s)",
+ powerpc_debugfs_root->d_iname,
+ dpa_debugfs_root->d_iname,
+ net_dev->name);
+
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+void dpa_generic_debugfs_remove(struct net_device *net_dev)
+{
+ struct dpa_priv_s *priv = netdev_priv(net_dev);
+
+ debugfs_remove(priv->debugfs_file);
+}
+
+static int __init dpa_generic_debugfs_module_init(void)
+{
+ int _errno = 0;
+
+ pr_info(KBUILD_MODNAME ": " DPA_DEBUGFS_DESCRIPTION " (" VERSION ")\n");
+
+ dpa_debugfs_root = debugfs_create_dir(DPA_GENERIC_ETH_DEBUGFS_ROOT,
+ powerpc_debugfs_root);
+ if (unlikely(dpa_debugfs_root == NULL)) {
+ _errno = -ENOMEM;
+ pr_err(KBUILD_MODNAME ": %s:%hu:%s():\n",
+ KBUILD_BASENAME".c", __LINE__, __func__);
+ pr_err("\tdebugfs_create_dir(%s/"KBUILD_MODNAME") = %d\n",
+ powerpc_debugfs_root->d_iname, _errno);
+ }
+
+ return _errno;
+}
+
+static void __exit dpa_generic_debugfs_module_exit(void)
+{
+ debugfs_remove(dpa_debugfs_root);
+}
+
+module_init(dpa_generic_debugfs_module_init);
+module_exit(dpa_generic_debugfs_module_exit);
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/ethernet/freescale/dpa/dpaa_generic_debugfs.h b/drivers/net/ethernet/freescale/dpa/dpaa_generic_debugfs.h
new file mode 100644
index 0000000..56e7fb3
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/dpaa_generic_debugfs.h
@@ -0,0 +1,41 @@
+/* Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DPAA_GENERIC_DEBUGFS_H_
+#define DPAA_GENERIC_DEBUGFS_H_
+
+#include <linux/netdevice.h>
+#include <linux/dcache.h>
+
+int dpa_generic_debugfs_create(struct net_device *net_dev);
+void dpa_generic_debugfs_remove(struct net_device *net_dev);
+
+#endif /* DPAA_GENERIC_DEBUGFS_H_ */
diff --git a/drivers/net/ethernet/freescale/dpa/mac-api.c b/drivers/net/ethernet/freescale/dpa/mac-api.c
new file mode 100644
index 0000000..a8b4704
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/mac-api.c
@@ -0,0 +1,775 @@
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef CONFIG_FSL_DPAA_ETH_DEBUG
+#define pr_fmt(fmt) \
+ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \
+ KBUILD_BASENAME".c", __LINE__, __func__
+#else
+#define pr_fmt(fmt) \
+ KBUILD_MODNAME ": " fmt
+#endif
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_mdio.h>
+#include <linux/phy.h>
+#include <linux/netdevice.h>
+
+#include "dpaa_eth.h"
+#include "mac.h"
+#include "lnxwrp_fsl_fman.h"
+
+#include "error_ext.h" /* GET_ERROR_TYPE, E_OK */
+
+#include "../fman/inc/flib/fsl_fman_dtsec.h"
+#include "../fman/inc/flib/fsl_fman_tgec.h"
+#include "../fman/inc/flib/fsl_fman_memac.h"
+#include "../fman/src/wrapper/lnxwrp_sysfs_fm.h"
+
+#define MAC_DESCRIPTION "FSL FMan MAC API based driver"
+
+MODULE_LICENSE("Dual BSD/GPL");
+
+MODULE_AUTHOR("Emil Medve <Emilian.Medve@Freescale.com>");
+
+MODULE_DESCRIPTION(MAC_DESCRIPTION);
+
+struct mac_priv_s {
+ struct fm_mac_dev *fm_mac;
+};
+
+const char *mac_driver_description __initconst = MAC_DESCRIPTION;
+const size_t mac_sizeof_priv[] = {
+ [DTSEC] = sizeof(struct mac_priv_s),
+ [XGMAC] = sizeof(struct mac_priv_s),
+ [MEMAC] = sizeof(struct mac_priv_s)
+};
+
+static const enet_mode_t _100[] = {
+ [PHY_INTERFACE_MODE_MII] = e_ENET_MODE_MII_100,
+ [PHY_INTERFACE_MODE_RMII] = e_ENET_MODE_RMII_100
+};
+
+static const enet_mode_t _1000[] = {
+ [PHY_INTERFACE_MODE_GMII] = e_ENET_MODE_GMII_1000,
+ [PHY_INTERFACE_MODE_SGMII] = e_ENET_MODE_SGMII_1000,
+ [PHY_INTERFACE_MODE_TBI] = e_ENET_MODE_TBI_1000,
+ [PHY_INTERFACE_MODE_RGMII] = e_ENET_MODE_RGMII_1000,
+ [PHY_INTERFACE_MODE_RGMII_ID] = e_ENET_MODE_RGMII_1000,
+ [PHY_INTERFACE_MODE_RGMII_RXID] = e_ENET_MODE_RGMII_1000,
+ [PHY_INTERFACE_MODE_RGMII_TXID] = e_ENET_MODE_RGMII_1000,
+ [PHY_INTERFACE_MODE_RTBI] = e_ENET_MODE_RTBI_1000
+};
+
+static enet_mode_t __cold __attribute__((nonnull))
+macdev2enetinterface(const struct mac_device *mac_dev)
+{
+ switch (mac_dev->max_speed) {
+ case SPEED_100:
+ return _100[mac_dev->phy_if];
+ case SPEED_1000:
+ return _1000[mac_dev->phy_if];
+ case SPEED_10000:
+ return e_ENET_MODE_XGMII_10000;
+ default:
+ return e_ENET_MODE_MII_100;
+ }
+}
+
+static void mac_exception(handle_t _mac_dev, e_FmMacExceptions exception)
+{
+ struct mac_device *mac_dev;
+
+ mac_dev = (struct mac_device *)_mac_dev;
+
+ if (e_FM_MAC_EX_10G_RX_FIFO_OVFL == exception) {
+ /* don't flag RX FIFO after the first */
+ fm_mac_set_exception(mac_dev->get_mac_handle(mac_dev),
+ e_FM_MAC_EX_10G_RX_FIFO_OVFL, false);
+ dev_err(mac_dev->dev, "10G MAC got RX FIFO Error = %x\n",
+ exception);
+ }
+
+ dev_dbg(mac_dev->dev, "%s:%s() -> %d\n", KBUILD_BASENAME".c", __func__,
+ exception);
+}
+
+static int __cold init(struct mac_device *mac_dev)
+{
+ int _errno;
+ struct mac_priv_s *priv;
+ t_FmMacParams param;
+ uint32_t version;
+
+ priv = macdev_priv(mac_dev);
+
+ param.baseAddr = (typeof(param.baseAddr))(uintptr_t)devm_ioremap(
+ mac_dev->dev, mac_dev->res->start, 0x2000);
+ param.enetMode = macdev2enetinterface(mac_dev);
+ memcpy(&param.addr, mac_dev->addr, min(sizeof(param.addr),
+ sizeof(mac_dev->addr)));
+ param.macId = mac_dev->cell_index;
+ param.h_Fm = (handle_t)mac_dev->fm;
+ param.mdioIrq = NO_IRQ;
+ param.f_Exception = mac_exception;
+ param.f_Event = mac_exception;
+ param.h_App = mac_dev;
+
+ priv->fm_mac = fm_mac_config(&param);
+ if (unlikely(priv->fm_mac == NULL)) {
+ _errno = -EINVAL;
+ goto _return;
+ }
+
+ fm_mac_set_handle(mac_dev->fm_dev, priv->fm_mac,
+ (macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000) ?
+ param.macId : param.macId + FM_MAX_NUM_OF_1G_MACS);
+
+ _errno = fm_mac_config_max_frame_length(priv->fm_mac,
+ fm_get_max_frm());
+ if (unlikely(_errno < 0))
+ goto _return_fm_mac_free;
+
+ if (macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000) {
+ /* 10G always works with pad and CRC */
+ _errno = fm_mac_config_pad_and_crc(priv->fm_mac, true);
+ if (unlikely(_errno < 0))
+ goto _return_fm_mac_free;
+
+ _errno = fm_mac_config_half_duplex(priv->fm_mac,
+ mac_dev->half_duplex);
+ if (unlikely(_errno < 0))
+ goto _return_fm_mac_free;
+ } else {
+ _errno = fm_mac_config_reset_on_init(priv->fm_mac, true);
+ if (unlikely(_errno < 0))
+ goto _return_fm_mac_free;
+ }
+
+ _errno = fm_mac_init(priv->fm_mac);
+ if (unlikely(_errno < 0))
+ goto _return_fm_mac_free;
+
+#ifndef CONFIG_FMAN_MIB_CNT_OVF_IRQ_EN
+ /* For 1G MAC, disable by default the MIB counters overflow interrupt */
+ if (macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000) {
+ _errno = fm_mac_set_exception(mac_dev->get_mac_handle(mac_dev),
+ e_FM_MAC_EX_1G_RX_MIB_CNT_OVFL, FALSE);
+ if (unlikely(_errno < 0))
+ goto _return_fm_mac_free;
+ }
+#endif /* !CONFIG_FMAN_MIB_CNT_OVF_IRQ_EN */
+
+ /* For 10G MAC, disable Tx ECC exception */
+ if (macdev2enetinterface(mac_dev) == e_ENET_MODE_XGMII_10000) {
+ _errno = fm_mac_set_exception(mac_dev->get_mac_handle(mac_dev),
+ e_FM_MAC_EX_10G_1TX_ECC_ER, FALSE);
+ if (unlikely(_errno < 0))
+ goto _return_fm_mac_free;
+ }
+
+ _errno = fm_mac_get_version(priv->fm_mac, &version);
+ if (unlikely(_errno < 0))
+ goto _return_fm_mac_free;
+
+ dev_info(mac_dev->dev, "FMan %s version: 0x%08x\n",
+ ((macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000) ?
+ "dTSEC" : "XGEC"), version);
+
+ goto _return;
+
+
+_return_fm_mac_free:
+ fm_mac_free(mac_dev->get_mac_handle(mac_dev));
+
+_return:
+ return _errno;
+}
+
+static int __cold memac_init(struct mac_device *mac_dev)
+{
+ int _errno;
+ struct mac_priv_s *priv;
+ t_FmMacParams param;
+
+ priv = macdev_priv(mac_dev);
+
+ param.baseAddr = (typeof(param.baseAddr))(uintptr_t)devm_ioremap(
+ mac_dev->dev, mac_dev->res->start, 0x2000);
+ param.enetMode = macdev2enetinterface(mac_dev);
+ memcpy(&param.addr, mac_dev->addr, sizeof(mac_dev->addr));
+ param.macId = mac_dev->cell_index;
+ param.h_Fm = (handle_t)mac_dev->fm;
+ param.mdioIrq = NO_IRQ;
+ param.f_Exception = mac_exception;
+ param.f_Event = mac_exception;
+ param.h_App = mac_dev;
+
+ priv->fm_mac = fm_mac_config(&param);
+ if (unlikely(priv->fm_mac == NULL)) {
+ _errno = -EINVAL;
+ goto _return;
+ }
+
+ _errno = fm_mac_config_max_frame_length(priv->fm_mac, fm_get_max_frm());
+ if (unlikely(_errno < 0))
+ goto _return_fm_mac_free;
+
+ _errno = fm_mac_config_reset_on_init(priv->fm_mac, true);
+ if (unlikely(_errno < 0))
+ goto _return_fm_mac_free;
+
+ _errno = fm_mac_init(priv->fm_mac);
+ if (unlikely(_errno < 0))
+ goto _return_fm_mac_free;
+
+ dev_info(mac_dev->dev, "FMan MEMAC\n");
+
+ goto _return;
+
+_return_fm_mac_free:
+ fm_mac_free(priv->fm_mac);
+
+_return:
+ return _errno;
+}
+
+static int __cold start(struct mac_device *mac_dev)
+{
+ int _errno;
+ struct phy_device *phy_dev = mac_dev->phy_dev;
+
+ _errno = fm_mac_enable(mac_dev->get_mac_handle(mac_dev));
+
+ if (!_errno && phy_dev) {
+ if (macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000)
+ phy_start(phy_dev);
+ else if (phy_dev->drv->read_status)
+ phy_dev->drv->read_status(phy_dev);
+ }
+
+ return _errno;
+}
+
+static int __cold stop(struct mac_device *mac_dev)
+{
+ if (mac_dev->phy_dev &&
+ (macdev2enetinterface(mac_dev) != e_ENET_MODE_XGMII_10000))
+ phy_stop(mac_dev->phy_dev);
+
+ return fm_mac_disable(mac_dev->get_mac_handle(mac_dev));
+}
+
+static int __cold set_multi(struct net_device *net_dev,
+ struct mac_device *mac_dev)
+{
+ struct mac_priv_s *mac_priv;
+ struct mac_address *old_addr, *tmp;
+ struct netdev_hw_addr *ha;
+ int _errno;
+
+ mac_priv = macdev_priv(mac_dev);
+
+ /* Clear previous address list */
+ list_for_each_entry_safe(old_addr, tmp, &mac_dev->mc_addr_list, list) {
+ _errno = fm_mac_remove_hash_mac_addr(mac_priv->fm_mac,
+ (t_EnetAddr *)old_addr->addr);
+ if (_errno < 0)
+ return _errno;
+
+ list_del(&old_addr->list);
+ kfree(old_addr);
+ }
+
+ /* Add all the addresses from the new list */
+ netdev_for_each_mc_addr(ha, net_dev) {
+ _errno = fm_mac_add_hash_mac_addr(mac_priv->fm_mac,
+ (t_EnetAddr *)ha->addr);
+ if (_errno < 0)
+ return _errno;
+
+ tmp = kmalloc(sizeof(struct mac_address), GFP_ATOMIC);
+ if (!tmp) {
+ dev_err(mac_dev->dev, "Out of memory\n");
+ return -ENOMEM;
+ }
+ memcpy(tmp->addr, ha->addr, ETH_ALEN);
+ list_add(&tmp->list, &mac_dev->mc_addr_list);
+ }
+ return 0;
+}
+
+/* Avoid redundant calls to FMD, if the MAC driver already contains the desired
+ * settings. Otherwise, the new MAC settings should be reflected in FMan.
+ */
+int set_mac_rx_pause(struct mac_device *mac_dev, bool en)
+{
+ struct fm_mac_dev *fm_mac_dev;
+ int _errno = 0;
+
+ if (unlikely(en != mac_dev->rx_pause)) {
+ fm_mac_dev = mac_dev->get_mac_handle(mac_dev);
+ _errno = fm_mac_set_rx_pause_frames(fm_mac_dev, en);
+ if (likely(_errno == 0))
+ mac_dev->rx_pause = en;
+ }
+
+ return _errno;
+}
+
+int set_mac_tx_pause(struct mac_device *mac_dev, bool en)
+{
+ int _errno = 0;
+ struct fm_mac_dev *fm_mac_dev;
+
+ if (unlikely(en != mac_dev->tx_pause)) {
+ fm_mac_dev = mac_dev->get_mac_handle(mac_dev);
+ _errno = fm_mac_set_tx_pause_frames(fm_mac_dev, en);
+ if (likely(_errno == 0))
+ mac_dev->tx_pause = en;
+ }
+
+ return _errno;
+}
+
+/* Determine the MAC RX/TX PAUSE frames settings based on PHY
+ * autonegotiation or values set by eththool.
+ */
+static void get_pause_cfg(struct mac_device *mac_dev,
+ bool *rx_pause, bool *tx_pause)
+{
+ struct phy_device *phy_dev = mac_dev->phy_dev;
+ u16 lcl_adv, rmt_adv;
+ u8 flowctrl;
+
+ *rx_pause = *tx_pause = false;
+
+ if (!phy_dev->duplex)
+ return;
+
+ /* If PAUSE autonegotiation is disabled, the TX/RX PAUSE settings
+ * are those set by ethtool.
+ */
+ if (!mac_dev->autoneg_pause) {
+ *rx_pause = !!mac_dev->rx_pause;
+ *tx_pause = !!mac_dev->tx_pause;
+ return;
+ }
+
+ /* Else if PAUSE autonegotiation is enabled, the TX/RX PAUSE
+ * settings depend on the result of the link negotiation.
+ */
+
+ /* get local capabilities */
+ lcl_adv = 0;
+ if (phy_dev->advertising & ADVERTISED_Pause)
+ lcl_adv |= ADVERTISE_PAUSE_CAP;
+ if (phy_dev->advertising & ADVERTISED_Asym_Pause)
+ lcl_adv |= ADVERTISE_PAUSE_ASYM;
+
+ /* get link partner capabilities */
+ rmt_adv = 0;
+ if (phy_dev->pause)
+ rmt_adv |= LPA_PAUSE_CAP;
+ if (phy_dev->asym_pause)
+ rmt_adv |= LPA_PAUSE_ASYM;
+
+ /* Calculate TX/RX settings based on local and peer advertised
+ * symmetric/asymmetric PAUSE capabilities.
+ */
+ flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
+ if (flowctrl & FLOW_CTRL_RX)
+ *rx_pause = true;
+ if (flowctrl & FLOW_CTRL_TX)
+ *tx_pause = true;
+}
+
+static void adjust_link(struct net_device *net_dev)
+{
+ struct dpa_priv_s *priv = netdev_priv(net_dev);
+ struct mac_device *mac_dev = priv->mac_dev;
+ struct phy_device *phy_dev = mac_dev->phy_dev;
+ struct fm_mac_dev *fm_mac_dev;
+ bool rx_pause, tx_pause;
+ int _errno;
+
+ fm_mac_dev = mac_dev->get_mac_handle(mac_dev);
+ fm_mac_adjust_link(fm_mac_dev, phy_dev->link, phy_dev->speed,
+ phy_dev->duplex);
+
+ get_pause_cfg(mac_dev, &rx_pause, &tx_pause);
+
+ _errno = set_mac_rx_pause(mac_dev, rx_pause);
+ if (unlikely(_errno < 0))
+ netdev_err(net_dev, "set_rx_pause() = %d\n", _errno);
+ _errno = set_mac_tx_pause(mac_dev, tx_pause);
+ if (unlikely(_errno < 0))
+ netdev_err(net_dev, "set_tx_pause() = %d\n", _errno);
+}
+
+/* Initializes driver's PHY state, and attaches to the PHY.
+ * Returns 0 on success.
+ */
+static int dtsec_init_phy(struct net_device *net_dev,
+ struct mac_device *mac_dev)
+{
+ struct phy_device *phy_dev;
+
+ if (!mac_dev->phy_node)
+ phy_dev = phy_connect(net_dev, mac_dev->fixed_bus_id,
+ &adjust_link, mac_dev->phy_if);
+ else
+ phy_dev = of_phy_connect(net_dev, mac_dev->phy_node,
+ &adjust_link, 0, mac_dev->phy_if);
+ if (unlikely(phy_dev == NULL) || IS_ERR(phy_dev)) {
+ netdev_err(net_dev, "Could not connect to PHY %s\n",
+ mac_dev->phy_node ?
+ mac_dev->phy_node->full_name :
+ mac_dev->fixed_bus_id);
+ return phy_dev == NULL ? -ENODEV : PTR_ERR(phy_dev);
+ }
+
+ /* Remove any features not supported by the controller */
+ phy_dev->supported &= mac_dev->if_support;
+ /* Enable the symmetric and asymmetric PAUSE frame advertisments,
+ * as most of the PHY drivers do not enable them by default.
+ */
+ phy_dev->supported |= (SUPPORTED_Pause | SUPPORTED_Asym_Pause);
+ phy_dev->advertising = phy_dev->supported;
+
+ mac_dev->phy_dev = phy_dev;
+
+ return 0;
+}
+
+static int xgmac_init_phy(struct net_device *net_dev,
+ struct mac_device *mac_dev)
+{
+ struct phy_device *phy_dev;
+
+ if (!mac_dev->phy_node)
+ phy_dev = phy_attach(net_dev, mac_dev->fixed_bus_id,
+ mac_dev->phy_if);
+ else
+ phy_dev = of_phy_attach(net_dev, mac_dev->phy_node, 0,
+ mac_dev->phy_if);
+ if (unlikely(phy_dev == NULL) || IS_ERR(phy_dev)) {
+ netdev_err(net_dev, "Could not attach to PHY %s\n",
+ mac_dev->phy_node ?
+ mac_dev->phy_node->full_name :
+ mac_dev->fixed_bus_id);
+ return phy_dev == NULL ? -ENODEV : PTR_ERR(phy_dev);
+ }
+
+ phy_dev->supported &= mac_dev->if_support;
+ /* Enable the symmetric and asymmetric PAUSE frame advertisments,
+ * as most of the PHY drivers do not enable them by default.
+ */
+ phy_dev->supported |= (SUPPORTED_Pause | SUPPORTED_Asym_Pause);
+ phy_dev->advertising = phy_dev->supported;
+
+ mac_dev->phy_dev = phy_dev;
+
+ return 0;
+}
+
+static int memac_init_phy(struct net_device *net_dev,
+ struct mac_device *mac_dev)
+{
+ struct phy_device *phy_dev;
+
+ if (macdev2enetinterface(mac_dev) == e_ENET_MODE_XGMII_10000) {
+ if (!mac_dev->phy_node) {
+ mac_dev->phy_dev = NULL;
+ return 0;
+ } else
+ phy_dev = of_phy_attach(net_dev, mac_dev->phy_node, 0,
+ mac_dev->phy_if);
+ } else {
+ if (!mac_dev->phy_node)
+ phy_dev = phy_connect(net_dev, mac_dev->fixed_bus_id,
+ &adjust_link, mac_dev->phy_if);
+ else
+ phy_dev = of_phy_connect(net_dev, mac_dev->phy_node,
+ &adjust_link, 0,
+ mac_dev->phy_if);
+ }
+
+ if (unlikely(phy_dev == NULL) || IS_ERR(phy_dev)) {
+ netdev_err(net_dev, "Could not connect to PHY %s\n",
+ mac_dev->phy_node ?
+ mac_dev->phy_node->full_name :
+ mac_dev->fixed_bus_id);
+ return phy_dev == NULL ? -ENODEV : PTR_ERR(phy_dev);
+ }
+
+ /* Remove any features not supported by the controller */
+ phy_dev->supported &= mac_dev->if_support;
+ /* Enable the symmetric and asymmetric PAUSE frame advertisments,
+ * as most of the PHY drivers do not enable them by default.
+ */
+ phy_dev->supported |= (SUPPORTED_Pause | SUPPORTED_Asym_Pause);
+ phy_dev->advertising = phy_dev->supported;
+
+ mac_dev->phy_dev = phy_dev;
+
+ return 0;
+}
+
+static int __cold uninit(struct fm_mac_dev *fm_mac_dev)
+{
+ int _errno, __errno;
+
+ _errno = fm_mac_disable(fm_mac_dev);
+ __errno = fm_mac_free(fm_mac_dev);
+
+ if (unlikely(__errno < 0))
+ _errno = __errno;
+
+ return _errno;
+}
+
+static struct fm_mac_dev *get_mac_handle(struct mac_device *mac_dev)
+{
+ const struct mac_priv_s *priv;
+ priv = macdev_priv(mac_dev);
+ return priv->fm_mac;
+}
+
+static int dtsec_dump_regs(struct mac_device *h_mac, char *buf, int nn)
+{
+ struct dtsec_regs *p_mm = (struct dtsec_regs *) h_mac->vaddr;
+ int i = 0, n = nn;
+
+ FM_DMP_SUBTITLE(buf, n, "\n");
+
+ FM_DMP_TITLE(buf, n, p_mm, "FM MAC - DTSEC-%d", h_mac->cell_index);
+
+ FM_DMP_V32(buf, n, p_mm, tsec_id);
+ FM_DMP_V32(buf, n, p_mm, tsec_id2);
+ FM_DMP_V32(buf, n, p_mm, ievent);
+ FM_DMP_V32(buf, n, p_mm, imask);
+ FM_DMP_V32(buf, n, p_mm, ecntrl);
+ FM_DMP_V32(buf, n, p_mm, ptv);
+ FM_DMP_V32(buf, n, p_mm, tmr_ctrl);
+ FM_DMP_V32(buf, n, p_mm, tmr_pevent);
+ FM_DMP_V32(buf, n, p_mm, tmr_pemask);
+ FM_DMP_V32(buf, n, p_mm, tctrl);
+ FM_DMP_V32(buf, n, p_mm, rctrl);
+ FM_DMP_V32(buf, n, p_mm, maccfg1);
+ FM_DMP_V32(buf, n, p_mm, maccfg2);
+ FM_DMP_V32(buf, n, p_mm, ipgifg);
+ FM_DMP_V32(buf, n, p_mm, hafdup);
+ FM_DMP_V32(buf, n, p_mm, maxfrm);
+
+ FM_DMP_V32(buf, n, p_mm, macstnaddr1);
+ FM_DMP_V32(buf, n, p_mm, macstnaddr2);
+
+ for (i = 0; i < 7; ++i) {
+ FM_DMP_V32(buf, n, p_mm, macaddr[i].exact_match1);
+ FM_DMP_V32(buf, n, p_mm, macaddr[i].exact_match2);
+ }
+
+ FM_DMP_V32(buf, n, p_mm, car1);
+ FM_DMP_V32(buf, n, p_mm, car2);
+
+ return n;
+}
+
+static int xgmac_dump_regs(struct mac_device *h_mac, char *buf, int nn)
+{
+ struct tgec_regs *p_mm = (struct tgec_regs *) h_mac->vaddr;
+ int n = nn;
+
+ FM_DMP_SUBTITLE(buf, n, "\n");
+ FM_DMP_TITLE(buf, n, p_mm, "FM MAC - TGEC -%d", h_mac->cell_index);
+
+ FM_DMP_V32(buf, n, p_mm, tgec_id);
+ FM_DMP_V32(buf, n, p_mm, command_config);
+ FM_DMP_V32(buf, n, p_mm, mac_addr_0);
+ FM_DMP_V32(buf, n, p_mm, mac_addr_1);
+ FM_DMP_V32(buf, n, p_mm, maxfrm);
+ FM_DMP_V32(buf, n, p_mm, pause_quant);
+ FM_DMP_V32(buf, n, p_mm, rx_fifo_sections);
+ FM_DMP_V32(buf, n, p_mm, tx_fifo_sections);
+ FM_DMP_V32(buf, n, p_mm, rx_fifo_almost_f_e);
+ FM_DMP_V32(buf, n, p_mm, tx_fifo_almost_f_e);
+ FM_DMP_V32(buf, n, p_mm, hashtable_ctrl);
+ FM_DMP_V32(buf, n, p_mm, mdio_cfg_status);
+ FM_DMP_V32(buf, n, p_mm, mdio_command);
+ FM_DMP_V32(buf, n, p_mm, mdio_data);
+ FM_DMP_V32(buf, n, p_mm, mdio_regaddr);
+ FM_DMP_V32(buf, n, p_mm, status);
+ FM_DMP_V32(buf, n, p_mm, tx_ipg_len);
+ FM_DMP_V32(buf, n, p_mm, mac_addr_2);
+ FM_DMP_V32(buf, n, p_mm, mac_addr_3);
+ FM_DMP_V32(buf, n, p_mm, rx_fifo_ptr_rd);
+ FM_DMP_V32(buf, n, p_mm, rx_fifo_ptr_wr);
+ FM_DMP_V32(buf, n, p_mm, tx_fifo_ptr_rd);
+ FM_DMP_V32(buf, n, p_mm, tx_fifo_ptr_wr);
+ FM_DMP_V32(buf, n, p_mm, imask);
+ FM_DMP_V32(buf, n, p_mm, ievent);
+
+ return n;
+}
+
+static int memac_dump_regs(struct mac_device *h_mac, char *buf, int nn)
+{
+ struct memac_regs *p_mm = (struct memac_regs *) h_mac->vaddr;
+ int i = 0, n = nn;
+
+ FM_DMP_SUBTITLE(buf, n, "\n");
+ FM_DMP_TITLE(buf, n, p_mm, "FM MAC - MEMAC -%d", h_mac->cell_index);
+
+ FM_DMP_V32(buf, n, p_mm, command_config);
+ FM_DMP_V32(buf, n, p_mm, mac_addr0.mac_addr_l);
+ FM_DMP_V32(buf, n, p_mm, mac_addr0.mac_addr_u);
+ FM_DMP_V32(buf, n, p_mm, maxfrm);
+ FM_DMP_V32(buf, n, p_mm, hashtable_ctrl);
+ FM_DMP_V32(buf, n, p_mm, ievent);
+ FM_DMP_V32(buf, n, p_mm, tx_ipg_length);
+ FM_DMP_V32(buf, n, p_mm, imask);
+
+ for (i = 0; i < 4; ++i)
+ FM_DMP_V32(buf, n, p_mm, pause_quanta[i]);
+
+ for (i = 0; i < 4; ++i)
+ FM_DMP_V32(buf, n, p_mm, pause_thresh[i]);
+
+ FM_DMP_V32(buf, n, p_mm, rx_pause_status);
+
+ for (i = 0; i < MEMAC_NUM_OF_PADDRS; ++i) {
+ FM_DMP_V32(buf, n, p_mm, mac_addr[i].mac_addr_l);
+ FM_DMP_V32(buf, n, p_mm, mac_addr[i].mac_addr_u);
+ }
+
+ FM_DMP_V32(buf, n, p_mm, lpwake_timer);
+ FM_DMP_V32(buf, n, p_mm, sleep_timer);
+ FM_DMP_V32(buf, n, p_mm, statn_config);
+ FM_DMP_V32(buf, n, p_mm, if_mode);
+ FM_DMP_V32(buf, n, p_mm, if_status);
+ FM_DMP_V32(buf, n, p_mm, hg_config);
+ FM_DMP_V32(buf, n, p_mm, hg_pause_quanta);
+ FM_DMP_V32(buf, n, p_mm, hg_pause_thresh);
+ FM_DMP_V32(buf, n, p_mm, hgrx_pause_status);
+ FM_DMP_V32(buf, n, p_mm, hg_fifos_status);
+ FM_DMP_V32(buf, n, p_mm, rhm);
+ FM_DMP_V32(buf, n, p_mm, thm);
+
+ return n;
+}
+
+int fm_mac_dump_regs(struct mac_device *h_mac, char *buf, int nn)
+{
+ int n = nn;
+
+ n = h_mac->dump_mac_regs(h_mac, buf, n);
+
+ return n;
+}
+
+
+static void __cold setup_dtsec(struct mac_device *mac_dev)
+{
+ mac_dev->init_phy = dtsec_init_phy;
+ mac_dev->init = init;
+ mac_dev->start = start;
+ mac_dev->stop = stop;
+ mac_dev->set_promisc = fm_mac_set_promiscuous;
+ mac_dev->change_addr = fm_mac_modify_mac_addr;
+ mac_dev->set_multi = set_multi;
+ mac_dev->uninit = uninit;
+ mac_dev->ptp_enable = fm_mac_enable_1588_time_stamp;
+ mac_dev->ptp_disable = fm_mac_disable_1588_time_stamp;
+ mac_dev->get_mac_handle = get_mac_handle;
+ mac_dev->set_tx_pause = fm_mac_set_tx_pause_frames;
+ mac_dev->set_rx_pause = fm_mac_set_rx_pause_frames;
+ mac_dev->fm_rtc_enable = fm_rtc_enable;
+ mac_dev->fm_rtc_disable = fm_rtc_disable;
+ mac_dev->fm_rtc_get_cnt = fm_rtc_get_cnt;
+ mac_dev->fm_rtc_set_cnt = fm_rtc_set_cnt;
+ mac_dev->fm_rtc_get_drift = fm_rtc_get_drift;
+ mac_dev->fm_rtc_set_drift = fm_rtc_set_drift;
+ mac_dev->fm_rtc_set_alarm = fm_rtc_set_alarm;
+ mac_dev->fm_rtc_set_fiper = fm_rtc_set_fiper;
+ mac_dev->set_wol = fm_mac_set_wol;
+ mac_dev->dump_mac_regs = dtsec_dump_regs;
+}
+
+static void __cold setup_xgmac(struct mac_device *mac_dev)
+{
+ mac_dev->init_phy = xgmac_init_phy;
+ mac_dev->init = init;
+ mac_dev->start = start;
+ mac_dev->stop = stop;
+ mac_dev->set_promisc = fm_mac_set_promiscuous;
+ mac_dev->change_addr = fm_mac_modify_mac_addr;
+ mac_dev->set_multi = set_multi;
+ mac_dev->uninit = uninit;
+ mac_dev->get_mac_handle = get_mac_handle;
+ mac_dev->set_tx_pause = fm_mac_set_tx_pause_frames;
+ mac_dev->set_rx_pause = fm_mac_set_rx_pause_frames;
+ mac_dev->set_wol = fm_mac_set_wol;
+ mac_dev->dump_mac_regs = xgmac_dump_regs;
+}
+
+static void __cold setup_memac(struct mac_device *mac_dev)
+{
+ mac_dev->init_phy = memac_init_phy;
+ mac_dev->init = memac_init;
+ mac_dev->start = start;
+ mac_dev->stop = stop;
+ mac_dev->set_promisc = fm_mac_set_promiscuous;
+ mac_dev->change_addr = fm_mac_modify_mac_addr;
+ mac_dev->set_multi = set_multi;
+ mac_dev->uninit = uninit;
+ mac_dev->get_mac_handle = get_mac_handle;
+ mac_dev->set_tx_pause = fm_mac_set_tx_pause_frames;
+ mac_dev->set_rx_pause = fm_mac_set_rx_pause_frames;
+ mac_dev->fm_rtc_enable = fm_rtc_enable;
+ mac_dev->fm_rtc_disable = fm_rtc_disable;
+ mac_dev->fm_rtc_get_cnt = fm_rtc_get_cnt;
+ mac_dev->fm_rtc_set_cnt = fm_rtc_set_cnt;
+ mac_dev->fm_rtc_get_drift = fm_rtc_get_drift;
+ mac_dev->fm_rtc_set_drift = fm_rtc_set_drift;
+ mac_dev->fm_rtc_set_alarm = fm_rtc_set_alarm;
+ mac_dev->fm_rtc_set_fiper = fm_rtc_set_fiper;
+ mac_dev->set_wol = fm_mac_set_wol;
+ mac_dev->dump_mac_regs = memac_dump_regs;
+}
+
+void (*const mac_setup[])(struct mac_device *mac_dev) = {
+ [DTSEC] = setup_dtsec,
+ [XGMAC] = setup_xgmac,
+ [MEMAC] = setup_memac
+};
diff --git a/drivers/net/ethernet/freescale/dpa/mac.c b/drivers/net/ethernet/freescale/dpa/mac.c
new file mode 100644
index 0000000..20994d4
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/mac.c
@@ -0,0 +1,462 @@
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef CONFIG_FSL_DPAA_ETH_DEBUG
+#define pr_fmt(fmt) \
+ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \
+ KBUILD_BASENAME".c", __LINE__, __func__
+#else
+#define pr_fmt(fmt) \
+ KBUILD_MODNAME ": " fmt
+#endif
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/of_net.h>
+#include <linux/device.h>
+#include <linux/phy.h>
+
+#include "lnxwrp_fm_ext.h"
+
+#include "mac.h"
+
+#define DTSEC_SUPPORTED \
+ (SUPPORTED_10baseT_Half \
+ | SUPPORTED_10baseT_Full \
+ | SUPPORTED_100baseT_Half \
+ | SUPPORTED_100baseT_Full \
+ | SUPPORTED_Autoneg \
+ | SUPPORTED_Pause \
+ | SUPPORTED_Asym_Pause \
+ | SUPPORTED_MII)
+
+static const char phy_str[][11] = {
+ [PHY_INTERFACE_MODE_MII] = "mii",
+ [PHY_INTERFACE_MODE_GMII] = "gmii",
+ [PHY_INTERFACE_MODE_SGMII] = "sgmii",
+ [PHY_INTERFACE_MODE_TBI] = "tbi",
+ [PHY_INTERFACE_MODE_RMII] = "rmii",
+ [PHY_INTERFACE_MODE_RGMII] = "rgmii",
+ [PHY_INTERFACE_MODE_RGMII_ID] = "rgmii-id",
+ [PHY_INTERFACE_MODE_RGMII_RXID] = "rgmii-rxid",
+ [PHY_INTERFACE_MODE_RGMII_TXID] = "rgmii-txid",
+ [PHY_INTERFACE_MODE_RTBI] = "rtbi",
+ [PHY_INTERFACE_MODE_XGMII] = "xgmii"
+};
+
+static phy_interface_t __pure __attribute__((nonnull)) str2phy(const char *str)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(phy_str); i++)
+ if (strcmp(str, phy_str[i]) == 0)
+ return (phy_interface_t)i;
+
+ return PHY_INTERFACE_MODE_MII;
+}
+
+static const uint16_t phy2speed[] = {
+ [PHY_INTERFACE_MODE_MII] = SPEED_100,
+ [PHY_INTERFACE_MODE_GMII] = SPEED_1000,
+ [PHY_INTERFACE_MODE_SGMII] = SPEED_1000,
+ [PHY_INTERFACE_MODE_TBI] = SPEED_1000,
+ [PHY_INTERFACE_MODE_RMII] = SPEED_100,
+ [PHY_INTERFACE_MODE_RGMII] = SPEED_1000,
+ [PHY_INTERFACE_MODE_RGMII_ID] = SPEED_1000,
+ [PHY_INTERFACE_MODE_RGMII_RXID] = SPEED_1000,
+ [PHY_INTERFACE_MODE_RGMII_TXID] = SPEED_1000,
+ [PHY_INTERFACE_MODE_RTBI] = SPEED_1000,
+ [PHY_INTERFACE_MODE_XGMII] = SPEED_10000
+};
+
+static struct mac_device * __cold
+alloc_macdev(struct device *dev, size_t sizeof_priv,
+ void (*setup)(struct mac_device *mac_dev))
+{
+ struct mac_device *mac_dev;
+
+ mac_dev = devm_kzalloc(dev, sizeof(*mac_dev) + sizeof_priv, GFP_KERNEL);
+ if (unlikely(mac_dev == NULL))
+ mac_dev = ERR_PTR(-ENOMEM);
+ else {
+ mac_dev->dev = dev;
+ dev_set_drvdata(dev, mac_dev);
+ setup(mac_dev);
+ }
+
+ return mac_dev;
+}
+
+static int __cold free_macdev(struct mac_device *mac_dev)
+{
+ dev_set_drvdata(mac_dev->dev, NULL);
+
+ return mac_dev->uninit(mac_dev->get_mac_handle(mac_dev));
+}
+
+static const struct of_device_id mac_match[] = {
+ [DTSEC] = {
+ .compatible = "fsl,fman-1g-mac"
+ },
+ [XGMAC] = {
+ .compatible = "fsl,fman-10g-mac"
+ },
+ [MEMAC] = {
+ .compatible = "fsl,fman-memac"
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, mac_match);
+
+static int __cold mac_probe(struct platform_device *_of_dev)
+{
+ int _errno, i, lenp;
+ struct device *dev;
+ struct device_node *mac_node, *dev_node;
+ struct mac_device *mac_dev;
+ struct platform_device *of_dev;
+ struct resource res;
+ const uint8_t *mac_addr;
+ const char *char_prop;
+ const phandle *phandle_prop;
+ const uint32_t *uint32_prop;
+ const struct of_device_id *match;
+
+ dev = &_of_dev->dev;
+ mac_node = dev->of_node;
+
+ match = of_match_device(mac_match, dev);
+ if (!match)
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(mac_match) - 1 && match != mac_match + i;
+ i++)
+ ;
+ BUG_ON(i >= ARRAY_SIZE(mac_match) - 1);
+
+ mac_dev = alloc_macdev(dev, mac_sizeof_priv[i], mac_setup[i]);
+ if (IS_ERR(mac_dev)) {
+ _errno = PTR_ERR(mac_dev);
+ dev_err(dev, "alloc_macdev() = %d\n", _errno);
+ goto _return;
+ }
+
+ INIT_LIST_HEAD(&mac_dev->mc_addr_list);
+
+ /* Get the FM node */
+ dev_node = of_get_parent(mac_node);
+ if (unlikely(dev_node == NULL)) {
+ dev_err(dev, "of_get_parent(%s) failed\n",
+ mac_node->full_name);
+ _errno = -EINVAL;
+ goto _return_dev_set_drvdata;
+ }
+
+ of_dev = of_find_device_by_node(dev_node);
+ if (unlikely(of_dev == NULL)) {
+ dev_err(dev, "of_find_device_by_node(%s) failed\n",
+ dev_node->full_name);
+ _errno = -EINVAL;
+ goto _return_of_node_put;
+ }
+
+ mac_dev->fm_dev = fm_bind(&of_dev->dev);
+ if (unlikely(mac_dev->fm_dev == NULL)) {
+ dev_err(dev, "fm_bind(%s) failed\n", dev_node->full_name);
+ _errno = -ENODEV;
+ goto _return_of_node_put;
+ }
+
+ mac_dev->fm = (void *)fm_get_handle(mac_dev->fm_dev);
+ of_node_put(dev_node);
+
+ /* Get the address of the memory mapped registers */
+ _errno = of_address_to_resource(mac_node, 0, &res);
+ if (unlikely(_errno < 0)) {
+ dev_err(dev, "of_address_to_resource(%s) = %d\n",
+ mac_node->full_name, _errno);
+ goto _return_dev_set_drvdata;
+ }
+
+ mac_dev->res = __devm_request_region(
+ dev,
+ fm_get_mem_region(mac_dev->fm_dev),
+ res.start, res.end + 1 - res.start, "mac");
+ if (unlikely(mac_dev->res == NULL)) {
+ dev_err(dev, "__devm_request_mem_region(mac) failed\n");
+ _errno = -EBUSY;
+ goto _return_dev_set_drvdata;
+ }
+
+ mac_dev->vaddr = devm_ioremap(dev, mac_dev->res->start,
+ mac_dev->res->end + 1
+ - mac_dev->res->start);
+ if (unlikely(mac_dev->vaddr == NULL)) {
+ dev_err(dev, "devm_ioremap() failed\n");
+ _errno = -EIO;
+ goto _return_dev_set_drvdata;
+ }
+
+#define TBIPA_OFFSET 0x1c
+#define TBIPA_DEFAULT_ADDR 5 /* override if used as external PHY addr. */
+ mac_dev->tbi_node = of_parse_phandle(mac_node, "tbi-handle", 0);
+ if (mac_dev->tbi_node) {
+ u32 tbiaddr = TBIPA_DEFAULT_ADDR;
+
+ uint32_prop = of_get_property(mac_dev->tbi_node, "reg", NULL);
+ if (uint32_prop)
+ tbiaddr = *uint32_prop;
+ out_be32(mac_dev->vaddr + TBIPA_OFFSET, tbiaddr);
+ }
+
+ if (!of_device_is_available(mac_node)) {
+ devm_iounmap(dev, mac_dev->vaddr);
+ __devm_release_region(dev, fm_get_mem_region(mac_dev->fm_dev),
+ res.start, res.end + 1 - res.start);
+ fm_unbind(mac_dev->fm_dev);
+ devm_kfree(dev, mac_dev);
+ dev_set_drvdata(dev, NULL);
+ return -ENODEV;
+ }
+
+ /* Get the cell-index */
+ uint32_prop = of_get_property(mac_node, "cell-index", &lenp);
+ if (unlikely(uint32_prop == NULL)) {
+ dev_err(dev, "of_get_property(%s, cell-index) failed\n",
+ mac_node->full_name);
+ _errno = -EINVAL;
+ goto _return_dev_set_drvdata;
+ }
+ BUG_ON(lenp != sizeof(uint32_t));
+ mac_dev->cell_index = *uint32_prop;
+
+ /* Get the MAC address */
+ mac_addr = of_get_mac_address(mac_node);
+ if (unlikely(mac_addr == NULL)) {
+ dev_err(dev, "of_get_mac_address(%s) failed\n",
+ mac_node->full_name);
+ _errno = -EINVAL;
+ goto _return_dev_set_drvdata;
+ }
+ memcpy(mac_dev->addr, mac_addr, sizeof(mac_dev->addr));
+
+ /* Get the port handles */
+ phandle_prop = of_get_property(mac_node, "fsl,port-handles", &lenp);
+ if (unlikely(phandle_prop == NULL)) {
+ dev_err(dev, "of_get_property(%s, port-handles) failed\n",
+ mac_node->full_name);
+ _errno = -EINVAL;
+ goto _return_dev_set_drvdata;
+ }
+ BUG_ON(lenp != sizeof(phandle) * ARRAY_SIZE(mac_dev->port_dev));
+
+ for_each_port_device(i, mac_dev->port_dev) {
+ /* Find the port node */
+ dev_node = of_find_node_by_phandle(phandle_prop[i]);
+ if (unlikely(dev_node == NULL)) {
+ dev_err(dev, "of_find_node_by_phandle() failed\n");
+ _errno = -EINVAL;
+ goto _return_of_node_put;
+ }
+
+ of_dev = of_find_device_by_node(dev_node);
+ if (unlikely(of_dev == NULL)) {
+ dev_err(dev, "of_find_device_by_node(%s) failed\n",
+ dev_node->full_name);
+ _errno = -EINVAL;
+ goto _return_of_node_put;
+ }
+
+ mac_dev->port_dev[i] = fm_port_bind(&of_dev->dev);
+ if (unlikely(mac_dev->port_dev[i] == NULL)) {
+ dev_err(dev, "dev_get_drvdata(%s) failed\n",
+ dev_node->full_name);
+ _errno = -EINVAL;
+ goto _return_of_node_put;
+ }
+ of_node_put(dev_node);
+ }
+
+ /* Get the PHY connection type */
+ char_prop = (const char *)of_get_property(mac_node,
+ "phy-connection-type", NULL);
+ if (unlikely(char_prop == NULL)) {
+ dev_warn(dev,
+ "of_get_property(%s, phy-connection-type) failed. Defaulting to MII\n",
+ mac_node->full_name);
+ mac_dev->phy_if = PHY_INTERFACE_MODE_MII;
+ } else
+ mac_dev->phy_if = str2phy(char_prop);
+
+ mac_dev->link = false;
+ mac_dev->half_duplex = false;
+ mac_dev->speed = phy2speed[mac_dev->phy_if];
+ mac_dev->max_speed = mac_dev->speed;
+ mac_dev->if_support = DTSEC_SUPPORTED;
+ /* We don't support half-duplex in SGMII mode */
+ if (strstr(char_prop, "sgmii"))
+ mac_dev->if_support &= ~(SUPPORTED_10baseT_Half |
+ SUPPORTED_100baseT_Half);
+
+ /* Gigabit support (no half-duplex) */
+ if (mac_dev->max_speed == 1000)
+ mac_dev->if_support |= SUPPORTED_1000baseT_Full;
+
+ /* The 10G interface only supports one mode */
+ if (strstr(char_prop, "xgmii"))
+ mac_dev->if_support = SUPPORTED_10000baseT_Full;
+
+ /* Get the rest of the PHY information */
+ mac_dev->phy_node = of_parse_phandle(mac_node, "phy-handle", 0);
+ if (mac_dev->phy_node == NULL) {
+ int sz;
+ const u32 *phy_id = of_get_property(mac_node, "fixed-link",
+ &sz);
+ if (!phy_id || sz < sizeof(*phy_id)) {
+ dev_err(dev, "No PHY (or fixed link) found\n");
+ _errno = -EINVAL;
+ goto _return_dev_set_drvdata;
+ }
+
+ sprintf(mac_dev->fixed_bus_id, PHY_ID_FMT, "fixed-0",
+ phy_id[0]);
+ }
+
+ _errno = mac_dev->init(mac_dev);
+ if (unlikely(_errno < 0)) {
+ dev_err(dev, "mac_dev->init() = %d\n", _errno);
+ goto _return_dev_set_drvdata;
+ }
+
+ /* pause frame autonegotiation enabled*/
+ mac_dev->autoneg_pause = true;
+
+ /* by intializing the values to false, force FMD to enable PAUSE frames
+ * on RX and TX
+ */
+ mac_dev->rx_pause = mac_dev->tx_pause = false;
+ /* does not ignore PAUSE frames */
+ _errno = set_mac_rx_pause(mac_dev, true);
+ if (unlikely(_errno < 0)) {
+ dev_err(dev, "set_mac_rx_pause() = %d\n", _errno);
+ return _errno;
+ }
+ /* transmits PAUSE frames when congested */
+ _errno = set_mac_tx_pause(mac_dev, true);
+ if (unlikely(_errno < 0)) {
+ dev_err(dev, "set_mac_tx_pause() = %d\n", _errno);
+ return _errno;
+ }
+
+ dev_info(dev,
+ "FMan MAC address: %02hx:%02hx:%02hx:%02hx:%02hx:%02hx\n",
+ mac_dev->addr[0], mac_dev->addr[1], mac_dev->addr[2],
+ mac_dev->addr[3], mac_dev->addr[4], mac_dev->addr[5]);
+
+ goto _return;
+
+_return_of_node_put:
+ of_node_put(dev_node);
+_return_dev_set_drvdata:
+ dev_set_drvdata(dev, NULL);
+_return:
+ return _errno;
+}
+
+static int __cold mac_remove(struct platform_device *of_dev)
+{
+ int i, _errno;
+ struct device *dev;
+ struct mac_device *mac_dev;
+
+ dev = &of_dev->dev;
+ mac_dev = (struct mac_device *)dev_get_drvdata(dev);
+
+ for_each_port_device(i, mac_dev->port_dev)
+ fm_port_unbind(mac_dev->port_dev[i]);
+
+ fm_unbind(mac_dev->fm_dev);
+
+ _errno = free_macdev(mac_dev);
+
+ return _errno;
+}
+
+static struct platform_driver mac_driver = {
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .of_match_table = mac_match,
+ .owner = THIS_MODULE,
+ },
+ .probe = mac_probe,
+ .remove = mac_remove
+};
+
+static int __init __cold mac_load(void)
+{
+ int _errno;
+
+ pr_debug(KBUILD_MODNAME ": -> %s:%s()\n",
+ KBUILD_BASENAME".c", __func__);
+
+ pr_info(KBUILD_MODNAME ": %s (" VERSION ")\n",
+ mac_driver_description);
+
+ _errno = platform_driver_register(&mac_driver);
+ if (unlikely(_errno < 0)) {
+ pr_err(KBUILD_MODNAME ": %s:%hu:%s(): platform_driver_register() = %d\n",
+ KBUILD_BASENAME".c", __LINE__, __func__, _errno);
+ goto _return;
+ }
+
+ goto _return;
+
+_return:
+ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n",
+ KBUILD_BASENAME".c", __func__);
+
+ return _errno;
+}
+module_init(mac_load);
+
+static void __exit __cold mac_unload(void)
+{
+ pr_debug(KBUILD_MODNAME ": -> %s:%s()\n",
+ KBUILD_BASENAME".c", __func__);
+
+ platform_driver_unregister(&mac_driver);
+
+ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n",
+ KBUILD_BASENAME".c", __func__);
+}
+module_exit(mac_unload);
diff --git a/drivers/net/ethernet/freescale/dpa/mac.h b/drivers/net/ethernet/freescale/dpa/mac.h
new file mode 100644
index 0000000..785877f
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/mac.h
@@ -0,0 +1,127 @@
+/* Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MAC_H
+#define __MAC_H
+
+#include <linux/device.h> /* struct device, BUS_ID_SIZE */
+#include <linux/if_ether.h> /* ETH_ALEN */
+#include <linux/phy.h> /* phy_interface_t, struct phy_device */
+#include <linux/list.h>
+
+#include "lnxwrp_fsl_fman.h" /* struct port_device */
+
+enum {DTSEC, XGMAC, MEMAC};
+
+struct mac_device {
+ struct device *dev;
+ void *priv;
+ uint8_t cell_index;
+ struct resource *res;
+ void __iomem *vaddr;
+ uint8_t addr[ETH_ALEN];
+ bool promisc;
+
+ struct fm *fm_dev;
+ struct fm_port *port_dev[2];
+
+ phy_interface_t phy_if;
+ u32 if_support;
+ bool link;
+ bool half_duplex;
+ uint16_t speed;
+ uint16_t max_speed;
+ struct device_node *phy_node;
+ char fixed_bus_id[MII_BUS_ID_SIZE + 3];
+ struct device_node *tbi_node;
+ struct phy_device *phy_dev;
+ void *fm;
+ /* List of multicast addresses */
+ struct list_head mc_addr_list;
+
+ u32 autoneg_pause;
+ u32 rx_pause;
+ u32 tx_pause;
+
+ struct fm_mac_dev *(*get_mac_handle)(struct mac_device *mac_dev);
+ int (*init_phy)(struct net_device *net_dev, struct mac_device *mac_dev);
+ int (*init)(struct mac_device *mac_dev);
+ int (*start)(struct mac_device *mac_dev);
+ int (*stop)(struct mac_device *mac_dev);
+ int (*set_promisc)(struct fm_mac_dev *fm_mac_dev, bool enable);
+ int (*change_addr)(struct fm_mac_dev *fm_mac_dev, uint8_t *addr);
+ int (*set_multi)(struct net_device *net_dev,
+ struct mac_device *mac_dev);
+ int (*uninit)(struct fm_mac_dev *fm_mac_dev);
+ int (*ptp_enable)(struct fm_mac_dev *fm_mac_dev);
+ int (*ptp_disable)(struct fm_mac_dev *fm_mac_dev);
+ int (*set_rx_pause)(struct fm_mac_dev *fm_mac_dev, bool en);
+ int (*set_tx_pause)(struct fm_mac_dev *fm_mac_dev, bool en);
+ int (*fm_rtc_enable)(struct fm *fm_dev);
+ int (*fm_rtc_disable)(struct fm *fm_dev);
+ int (*fm_rtc_get_cnt)(struct fm *fm_dev, uint64_t *ts);
+ int (*fm_rtc_set_cnt)(struct fm *fm_dev, uint64_t ts);
+ int (*fm_rtc_get_drift)(struct fm *fm_dev, uint32_t *drift);
+ int (*fm_rtc_set_drift)(struct fm *fm_dev, uint32_t drift);
+ int (*fm_rtc_set_alarm)(struct fm *fm_dev, uint32_t id, uint64_t time);
+ int (*fm_rtc_set_fiper)(struct fm *fm_dev, uint32_t id,
+ uint64_t fiper);
+ int (*set_wol)(struct fm_port *port, struct fm_mac_dev *fm_mac_dev,
+ bool en);
+ int (*dump_mac_regs)(struct mac_device *h_mac, char *buf, int nn);
+
+};
+
+struct mac_address {
+ uint8_t addr[ETH_ALEN];
+ struct list_head list;
+};
+
+#define get_fm_handle(net_dev) \
+ (((struct dpa_priv_s *)netdev_priv(net_dev))->mac_dev->fm_dev)
+
+#define for_each_port_device(i, port_dev) \
+ for (i = 0; i < ARRAY_SIZE(port_dev); i++)
+
+static inline __attribute((nonnull)) void *macdev_priv(
+ const struct mac_device *mac_dev)
+{
+ return (void *)mac_dev + sizeof(*mac_dev);
+}
+
+extern const char *mac_driver_description;
+extern const size_t mac_sizeof_priv[];
+extern void (*const mac_setup[])(struct mac_device *mac_dev);
+
+int set_mac_rx_pause(struct mac_device *mac_dev, bool en);
+int set_mac_tx_pause(struct mac_device *mac_dev, bool en);
+
+#endif /* __MAC_H */
diff --git a/drivers/net/ethernet/freescale/dpa/offline_port.c b/drivers/net/ethernet/freescale/dpa/offline_port.c
new file mode 100644
index 0000000..17ed9af
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/offline_port.c
@@ -0,0 +1,878 @@
+/* Copyright 2011-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Offline Parsing / Host Command port driver for FSL QorIQ FMan.
+ * Validates device-tree configuration and sets up the offline ports.
+ */
+
+#ifdef CONFIG_FSL_DPAA_ETH_DEBUG
+#define pr_fmt(fmt) \
+ KBUILD_MODNAME ": %s:%hu:%s() " fmt, \
+ KBUILD_BASENAME".c", __LINE__, __func__
+#else
+#define pr_fmt(fmt) \
+ KBUILD_MODNAME ": " fmt
+#endif
+
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/fsl_qman.h>
+
+#include "offline_port.h"
+#include "dpaa_eth.h"
+#include "dpaa_eth_common.h"
+
+#define OH_MOD_DESCRIPTION "FSL FMan Offline Parsing port driver"
+/* Manip extra space and data alignment for fragmentation */
+#define FRAG_MANIP_SPACE 128
+#define FRAG_DATA_ALIGN 64
+
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Bogdan Hamciuc <bogdan.hamciuc@freescale.com>");
+MODULE_DESCRIPTION(OH_MOD_DESCRIPTION);
+
+
+static const struct of_device_id oh_port_match_table[] = {
+ {
+ .compatible = "fsl,dpa-oh"
+ },
+ {
+ .compatible = "fsl,dpa-oh-shared"
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, oh_port_match_table);
+
+#ifdef CONFIG_PM
+
+static int oh_suspend_noirq(struct device *dev)
+{
+ struct dpa_oh_config_s *oh_config;
+
+ oh_config = dev_get_drvdata(dev);
+ return fm_port_suspend(oh_config->oh_port);
+}
+
+static int oh_resume_noirq(struct device *dev)
+{
+ struct dpa_oh_config_s *oh_config;
+
+ oh_config = dev_get_drvdata(dev);
+ return fm_port_resume(oh_config->oh_port);
+}
+
+static const struct dev_pm_ops oh_pm_ops = {
+ .suspend_noirq = oh_suspend_noirq,
+ .resume_noirq = oh_resume_noirq,
+};
+
+#define OH_PM_OPS (&oh_pm_ops)
+
+#else /* CONFIG_PM */
+
+#define OH_PM_OPS NULL
+
+#endif /* CONFIG_PM */
+
+/* Creates Frame Queues */
+static uint32_t oh_fq_create(struct qman_fq *fq,
+ uint32_t fq_id, uint16_t channel,
+ uint16_t wq_id)
+{
+ struct qm_mcc_initfq fq_opts;
+ uint32_t create_flags, init_flags;
+ uint32_t ret = 0;
+
+ if (fq == NULL)
+ return 1;
+
+ /* Set flags for FQ create */
+ create_flags = QMAN_FQ_FLAG_LOCKED | QMAN_FQ_FLAG_TO_DCPORTAL;
+
+ /* Create frame queue */
+ ret = qman_create_fq(fq_id, create_flags, fq);
+ if (ret != 0)
+ return 1;
+
+ /* Set flags for FQ init */
+ init_flags = QMAN_INITFQ_FLAG_SCHED;
+
+ /* Set FQ init options. Specify destination WQ ID and channel */
+ fq_opts.we_mask = QM_INITFQ_WE_DESTWQ;
+ fq_opts.fqd.dest.wq = wq_id;
+ fq_opts.fqd.dest.channel = channel;
+
+ /* Initialize frame queue */
+ ret = qman_init_fq(fq, init_flags, &fq_opts);
+ if (ret != 0) {
+ qman_destroy_fq(fq, 0);
+ return 1;
+ }
+
+ return 0;
+}
+
+void dump_fq(struct device *dev, int fqid, int channel)
+{
+ if (channel) {
+ /* display fqs with a valid (!= 0) destination channel */
+ dev_info(dev, "FQ ID:%d Channel ID:%d\n", fqid, channel);
+ }
+}
+
+void dump_fq_duple(struct device *dev, struct qman_fq *fqs, int fqs_count,
+ int channel_id)
+{
+ int i;
+ for (i = 0; i < fqs_count; i++)
+ dump_fq(dev, (fqs + i)->fqid, channel_id);
+}
+
+void dump_oh_config(struct device *dev, struct dpa_oh_config_s *conf)
+{
+ struct list_head *fq_list;
+ struct fq_duple *fqd;
+ int i;
+
+ dev_info(dev, "Default egress frame queue: %d\n", conf->default_fqid);
+ dev_info(dev, "Default error frame queue: %d\n", conf->error_fqid);
+
+ /* TX queues (old initialization) */
+ dev_info(dev, "Initialized queues:");
+ for (i = 0; i < conf->egress_cnt; i++)
+ dump_fq_duple(dev, conf->egress_fqs, conf->egress_cnt,
+ conf->channel);
+
+ /* initialized ingress queues */
+ list_for_each(fq_list, &conf->fqs_ingress_list) {
+ fqd = list_entry(fq_list, struct fq_duple, fq_list);
+ dump_fq_duple(dev, fqd->fqs, fqd->fqs_count, fqd->channel_id);
+ }
+
+ /* initialized egress queues */
+ list_for_each(fq_list, &conf->fqs_egress_list) {
+ fqd = list_entry(fq_list, struct fq_duple, fq_list);
+ dump_fq_duple(dev, fqd->fqs, fqd->fqs_count, fqd->channel_id);
+ }
+}
+
+/* Destroys Frame Queues */
+static void oh_fq_destroy(struct qman_fq *fq)
+{
+ int _errno = 0;
+
+ _errno = qman_retire_fq(fq, NULL);
+ if (unlikely(_errno < 0))
+ pr_err(KBUILD_MODNAME": %s:%hu:%s(): qman_retire_fq(%u)=%d\n",
+ KBUILD_BASENAME".c", __LINE__, __func__,
+ qman_fq_fqid(fq), _errno);
+
+ _errno = qman_oos_fq(fq);
+ if (unlikely(_errno < 0)) {
+ pr_err(KBUILD_MODNAME": %s:%hu:%s(): qman_oos_fq(%u)=%d\n",
+ KBUILD_BASENAME".c", __LINE__, __func__,
+ qman_fq_fqid(fq), _errno);
+ }
+
+ qman_destroy_fq(fq, 0);
+}
+
+/* Allocation code for the OH port's PCD frame queues */
+static int __cold oh_alloc_pcd_fqids(struct device *dev,
+ uint32_t num,
+ uint8_t alignment,
+ uint32_t *base_fqid)
+{
+ dev_crit(dev, "callback not implemented!\n");
+ BUG();
+
+ return 0;
+}
+
+static int __cold oh_free_pcd_fqids(struct device *dev, uint32_t base_fqid)
+{
+ dev_crit(dev, "callback not implemented!\n");
+ BUG();
+
+ return 0;
+}
+
+static void oh_set_buffer_layout(struct fm_port *port,
+ struct dpa_buffer_layout_s *layout)
+{
+ struct fm_port_params params;
+
+ layout->priv_data_size = DPA_TX_PRIV_DATA_SIZE;
+ layout->parse_results = true;
+ layout->hash_results = true;
+ layout->time_stamp = false;
+
+ fm_port_get_buff_layout_ext_params(port, &params);
+ layout->manip_extra_space = params.manip_extra_space;
+ layout->data_align = params.data_align;
+}
+
+static int
+oh_port_probe(struct platform_device *_of_dev)
+{
+ struct device *dpa_oh_dev;
+ struct device_node *dpa_oh_node;
+ int lenp, _errno = 0, fq_idx, duple_idx;
+ int n_size, i, j, ret, duples_count;
+ const phandle *oh_port_handle, *bpool_handle;
+ struct platform_device *oh_of_dev;
+ struct device_node *oh_node, *bpool_node = NULL, *root_node;
+ struct device *oh_dev;
+ struct dpa_oh_config_s *oh_config = NULL;
+ uint32_t *oh_all_queues;
+ uint32_t *channel_ids;
+ uint32_t *oh_tx_queues;
+ uint32_t queues_count;
+ uint32_t crt_fqid_base;
+ uint32_t crt_fq_count;
+ bool frag_enabled = false;
+ struct fm_port_params oh_port_tx_params;
+ struct fm_port_pcd_param oh_port_pcd_params;
+ struct dpa_buffer_layout_s buf_layout;
+
+ /* True if the current partition owns the OH port. */
+ bool init_oh_port;
+
+ const struct of_device_id *match;
+ uint32_t crt_ext_pools_count, ext_pool_size;
+ const unsigned int *port_id;
+ const unsigned int *channel_id;
+
+ int channel_ids_count;
+ int channel_idx;
+ struct fq_duple *fqd;
+ struct list_head *fq_list, *fq_list_tmp;
+
+ const uint32_t *bpool_cfg;
+ const uint32_t *bpid;
+
+ memset(&oh_port_tx_params, 0, sizeof(oh_port_tx_params));
+ dpa_oh_dev = &_of_dev->dev;
+ dpa_oh_node = dpa_oh_dev->of_node;
+ BUG_ON(dpa_oh_node == NULL);
+
+ match = of_match_device(oh_port_match_table, dpa_oh_dev);
+ if (!match)
+ return -EINVAL;
+
+ dev_dbg(dpa_oh_dev, "Probing OH port...\n");
+
+ /* Find the referenced OH node */
+
+ oh_port_handle = of_get_property(dpa_oh_node,
+ "fsl,fman-oh-port", &lenp);
+ if (oh_port_handle == NULL) {
+ dev_err(dpa_oh_dev, "No OH port handle found in node %s\n",
+ dpa_oh_node->full_name);
+ return -EINVAL;
+ }
+
+ BUG_ON(lenp % sizeof(*oh_port_handle));
+ if (lenp != sizeof(*oh_port_handle)) {
+ dev_err(dpa_oh_dev,
+ "Found %lu OH port bindings in node %s, only 1 phandle is allowed.\n",
+ (unsigned long int)(lenp / sizeof(*oh_port_handle)),
+ dpa_oh_node->full_name);
+ return -EINVAL;
+ }
+
+ /* Read configuration for the OH port */
+ oh_node = of_find_node_by_phandle(*oh_port_handle);
+ if (oh_node == NULL) {
+ dev_err(dpa_oh_dev,
+ "Can't find OH node referenced from node %s\n",
+ dpa_oh_node->full_name);
+ return -EINVAL;
+ }
+ dev_info(dpa_oh_dev, "Found OH node handle compatible with %s.\n",
+ match->compatible);
+
+ port_id = of_get_property(oh_node, "cell-index", &lenp);
+ if (port_id == NULL) {
+ dev_err(dpa_oh_dev, "No port id found in node %s\n",
+ dpa_oh_node->full_name);
+ _errno = -EINVAL;
+ goto return_kfree;
+ }
+ BUG_ON(lenp % sizeof(*port_id));
+
+ channel_id = of_get_property(oh_node, "fsl,qman-channel-id", &lenp);
+ if (channel_id == NULL) {
+ dev_err(dpa_oh_dev, "No channel id found in node %s\n",
+ dpa_oh_node->full_name);
+ _errno = -EINVAL;
+ goto return_kfree;
+ }
+
+ oh_of_dev = of_find_device_by_node(oh_node);
+ BUG_ON(oh_of_dev == NULL);
+ oh_dev = &oh_of_dev->dev;
+
+ /* The OH port must be initialized exactly once.
+ * The following scenarios are of interest:
+ * - the node is Linux-private (will always initialize it);
+ * - the node is shared between two Linux partitions
+ * (only one of them will initialize it);
+ * - the node is shared between a Linux and a LWE partition
+ * (Linux will initialize it) - "fsl,dpa-oh-shared"
+ */
+
+ /* Check if the current partition owns the OH port
+ * and ought to initialize it. It may be the case that we leave this
+ * to another (also Linux) partition.
+ */
+ init_oh_port = strcmp(match->compatible, "fsl,dpa-oh-shared");
+
+ /* If we aren't the "owner" of the OH node, we're done here. */
+ if (!init_oh_port) {
+ dev_dbg(dpa_oh_dev,
+ "Not owning the shared OH port %s, will not initialize it.\n",
+ oh_node->full_name);
+ of_node_put(oh_node);
+ return 0;
+ }
+
+ /* Allocate OH dev private data */
+ oh_config = devm_kzalloc(dpa_oh_dev, sizeof(*oh_config), GFP_KERNEL);
+ if (oh_config == NULL) {
+ dev_err(dpa_oh_dev,
+ "Can't allocate private data for OH node %s referenced from node %s!\n",
+ oh_node->full_name, dpa_oh_node->full_name);
+ _errno = -ENOMEM;
+ goto return_kfree;
+ }
+
+ INIT_LIST_HEAD(&oh_config->fqs_ingress_list);
+ INIT_LIST_HEAD(&oh_config->fqs_egress_list);
+
+ /* FQs that enter OH port */
+ lenp = 0;
+ oh_all_queues = (uint32_t *)of_get_property(dpa_oh_node,
+ "fsl,qman-frame-queues-ingress", &lenp);
+ if (lenp % (2 * sizeof(*oh_all_queues))) {
+ dev_warn(dpa_oh_dev,
+ "Wrong ingress queues format for OH node %s referenced from node %s!\n",
+ oh_node->full_name, dpa_oh_node->full_name);
+ /* just ignore the last unpaired value */
+ }
+
+ duples_count = lenp / (2 * sizeof(*oh_all_queues));
+ dev_err(dpa_oh_dev, "Allocating %d ingress frame queues duples\n",
+ duples_count);
+ for (duple_idx = 0; duple_idx < duples_count; duple_idx++) {
+ crt_fqid_base = oh_all_queues[2 * duple_idx];
+ crt_fq_count = oh_all_queues[2 * duple_idx + 1];
+
+ fqd = devm_kzalloc(dpa_oh_dev,
+ sizeof(struct fq_duple), GFP_KERNEL);
+ if (!fqd) {
+ dev_err(dpa_oh_dev, "Can't allocate structures for ingress frame queues for OH node %s referenced from node %s!\n",
+ oh_node->full_name,
+ dpa_oh_node->full_name);
+ _errno = -ENOMEM;
+ goto return_kfree;
+ }
+
+ fqd->fqs = devm_kzalloc(dpa_oh_dev,
+ crt_fq_count * sizeof(struct qman_fq),
+ GFP_KERNEL);
+ if (!fqd->fqs) {
+ dev_err(dpa_oh_dev, "Can't allocate structures for ingress frame queues for OH node %s referenced from node %s!\n",
+ oh_node->full_name,
+ dpa_oh_node->full_name);
+ _errno = -ENOMEM;
+ goto return_kfree;
+ }
+
+ for (j = 0; j < crt_fq_count; j++)
+ (fqd->fqs + j)->fqid = crt_fqid_base + j;
+ fqd->fqs_count = crt_fq_count;
+ fqd->channel_id = *channel_id;
+ list_add(&fqd->fq_list, &oh_config->fqs_ingress_list);
+ }
+
+ /* create the ingress queues */
+ list_for_each(fq_list, &oh_config->fqs_ingress_list) {
+ fqd = list_entry(fq_list, struct fq_duple, fq_list);
+
+ for (j = 0; j < fqd->fqs_count; j++) {
+ ret = oh_fq_create(fqd->fqs + j,
+ (fqd->fqs + j)->fqid,
+ fqd->channel_id, 3);
+ if (ret != 0) {
+ dev_err(dpa_oh_dev, "Unable to create ingress frame queue %d for OH node %s referenced from node %s!\n",
+ (fqd->fqs + j)->fqid,
+ oh_node->full_name,
+ dpa_oh_node->full_name);
+ _errno = -EINVAL;
+ goto return_kfree;
+ }
+ }
+ }
+
+ /* FQs that exit OH port */
+ lenp = 0;
+ oh_all_queues = (uint32_t *)of_get_property(dpa_oh_node,
+ "fsl,qman-frame-queues-egress", &lenp);
+ if (lenp % (2 * sizeof(*oh_all_queues))) {
+ dev_warn(dpa_oh_dev,
+ "Wrong egress queues format for OH node %s referenced from node %s!\n",
+ oh_node->full_name, dpa_oh_node->full_name);
+ /* just ignore the last unpaired value */
+ }
+
+ duples_count = lenp / (2 * sizeof(*oh_all_queues));
+ dev_dbg(dpa_oh_dev, "Allocating %d egress frame queues duples\n",
+ duples_count);
+ for (duple_idx = 0; duple_idx < duples_count; duple_idx++) {
+ crt_fqid_base = oh_all_queues[2 * duple_idx];
+ crt_fq_count = oh_all_queues[2 * duple_idx + 1];
+
+ fqd = devm_kzalloc(dpa_oh_dev,
+ sizeof(struct fq_duple), GFP_KERNEL);
+ if (!fqd) {
+ dev_err(dpa_oh_dev, "Can't allocate structures for egress frame queues for OH node %s referenced from node %s!\n",
+ oh_node->full_name,
+ dpa_oh_node->full_name);
+ _errno = -ENOMEM;
+ goto return_kfree;
+ }
+
+ fqd->fqs = devm_kzalloc(dpa_oh_dev,
+ crt_fq_count * sizeof(struct qman_fq),
+ GFP_KERNEL);
+ if (!fqd->fqs) {
+ dev_err(dpa_oh_dev,
+ "Can't allocate structures for egress frame queues for OH node %s referenced from node %s!\n",
+ oh_node->full_name,
+ dpa_oh_node->full_name);
+ _errno = -ENOMEM;
+ goto return_kfree;
+ }
+
+ for (j = 0; j < crt_fq_count; j++)
+ (fqd->fqs + j)->fqid = crt_fqid_base + j;
+ fqd->fqs_count = crt_fq_count;
+ /* channel ID is specified in another attribute */
+ fqd->channel_id = 0;
+ list_add(&fqd->fq_list, &oh_config->fqs_egress_list);
+
+ /* allocate the queue */
+
+ }
+
+ /* channel_ids for FQs that exit OH port */
+ lenp = 0;
+ channel_ids = (uint32_t *)of_get_property(dpa_oh_node,
+ "fsl,qman-channel-ids-egress", &lenp);
+
+ channel_ids_count = lenp / (sizeof(*channel_ids));
+ if (channel_ids_count != duples_count) {
+ dev_warn(dpa_oh_dev,
+ "Not all egress queues have a channel id for OH node %s referenced from node %s!\n",
+ oh_node->full_name, dpa_oh_node->full_name);
+ /* just ignore the queues that do not have a Channel ID */
+ }
+
+ channel_idx = 0;
+ list_for_each(fq_list, &oh_config->fqs_egress_list) {
+ if (channel_idx + 1 > channel_ids_count)
+ break;
+ fqd = list_entry(fq_list, struct fq_duple, fq_list);
+ fqd->channel_id = channel_ids[channel_idx++];
+ }
+
+ /* create egress queues */
+ list_for_each(fq_list, &oh_config->fqs_egress_list) {
+ fqd = list_entry(fq_list, struct fq_duple, fq_list);
+
+ if (fqd->channel_id == 0) {
+ /* missing channel id in dts */
+ continue;
+ }
+
+ for (j = 0; j < fqd->fqs_count; j++) {
+ ret = oh_fq_create(fqd->fqs + j,
+ (fqd->fqs + j)->fqid,
+ fqd->channel_id, 3);
+ if (ret != 0) {
+ dev_err(dpa_oh_dev, "Unable to create egress frame queue %d for OH node %s referenced from node %s!\n",
+ (fqd->fqs + j)->fqid,
+ oh_node->full_name,
+ dpa_oh_node->full_name);
+ _errno = -EINVAL;
+ goto return_kfree;
+ }
+ }
+ }
+
+ /* Read FQ ids/nums for the DPA OH node */
+ oh_all_queues = (uint32_t *)of_get_property(dpa_oh_node,
+ "fsl,qman-frame-queues-oh", &lenp);
+ if (oh_all_queues == NULL) {
+ dev_err(dpa_oh_dev,
+ "No frame queues have been defined for OH node %s referenced from node %s\n",
+ oh_node->full_name, dpa_oh_node->full_name);
+ _errno = -EINVAL;
+ goto return_kfree;
+ }
+
+ /* Check that the OH error and default FQs are there */
+ BUG_ON(lenp % (2 * sizeof(*oh_all_queues)));
+ queues_count = lenp / (2 * sizeof(*oh_all_queues));
+ if (queues_count != 2) {
+ dev_err(dpa_oh_dev,
+ "Error and Default queues must be defined for OH node %s referenced from node %s\n",
+ oh_node->full_name, dpa_oh_node->full_name);
+ _errno = -EINVAL;
+ goto return_kfree;
+ }
+
+ /* Read the FQIDs defined for this OH port */
+ dev_dbg(dpa_oh_dev, "Reading %d queues...\n", queues_count);
+ fq_idx = 0;
+
+ /* Error FQID - must be present */
+ crt_fqid_base = oh_all_queues[fq_idx++];
+ crt_fq_count = oh_all_queues[fq_idx++];
+ if (crt_fq_count != 1) {
+ dev_err(dpa_oh_dev,
+ "Only 1 Error FQ allowed in OH node %s referenced from node %s (read: %d FQIDs).\n",
+ oh_node->full_name, dpa_oh_node->full_name,
+ crt_fq_count);
+ _errno = -EINVAL;
+ goto return_kfree;
+ }
+ oh_config->error_fqid = crt_fqid_base;
+ dev_dbg(dpa_oh_dev, "Read Error FQID 0x%x for OH port %s.\n",
+ oh_config->error_fqid, oh_node->full_name);
+
+ /* Default FQID - must be present */
+ crt_fqid_base = oh_all_queues[fq_idx++];
+ crt_fq_count = oh_all_queues[fq_idx++];
+ if (crt_fq_count != 1) {
+ dev_err(dpa_oh_dev,
+ "Only 1 Default FQ allowed in OH node %s referenced from %s (read: %d FQIDs).\n",
+ oh_node->full_name, dpa_oh_node->full_name,
+ crt_fq_count);
+ _errno = -EINVAL;
+ goto return_kfree;
+ }
+ oh_config->default_fqid = crt_fqid_base;
+ dev_dbg(dpa_oh_dev, "Read Default FQID 0x%x for OH port %s.\n",
+ oh_config->default_fqid, oh_node->full_name);
+
+ /* TX FQID - presence is optional */
+ oh_tx_queues = (uint32_t *)of_get_property(dpa_oh_node,
+ "fsl,qman-frame-queues-tx", &lenp);
+ if (oh_tx_queues == NULL) {
+ dev_dbg(dpa_oh_dev,
+ "No tx queues have been defined for OH node %s referenced from node %s\n",
+ oh_node->full_name, dpa_oh_node->full_name);
+ goto config_port;
+ }
+
+ /* Check that queues-tx has only a base and a count defined */
+ BUG_ON(lenp % (2 * sizeof(*oh_tx_queues)));
+ queues_count = lenp / (2 * sizeof(*oh_tx_queues));
+ if (queues_count != 1) {
+ dev_err(dpa_oh_dev,
+ "TX queues must be defined in only one <base count> tuple for OH node %s referenced from node %s\n",
+ oh_node->full_name, dpa_oh_node->full_name);
+ _errno = -EINVAL;
+ goto return_kfree;
+ }
+
+ /* Read channel id for the queues */
+ channel_id = of_get_property(oh_node, "fsl,qman-channel-id", &lenp);
+ if (channel_id == NULL) {
+ dev_err(dpa_oh_dev, "No channel id found in node %s\n",
+ dpa_oh_node->full_name);
+ _errno = -EINVAL;
+ goto return_kfree;
+ }
+ BUG_ON(lenp % sizeof(*channel_id));
+
+ fq_idx = 0;
+ crt_fqid_base = oh_tx_queues[fq_idx++];
+ crt_fq_count = oh_tx_queues[fq_idx++];
+ oh_config->egress_cnt = crt_fq_count;
+
+ /* Allocate TX queues */
+ dev_dbg(dpa_oh_dev, "Allocating %d queues for TX...\n", crt_fq_count);
+ oh_config->egress_fqs = devm_kzalloc(dpa_oh_dev,
+ crt_fq_count * sizeof(struct qman_fq), GFP_KERNEL);
+ if (oh_config->egress_fqs == NULL) {
+ dev_err(dpa_oh_dev,
+ "Can't allocate private data for TX queues for OH node %s referenced from node %s!\n",
+ oh_node->full_name, dpa_oh_node->full_name);
+ _errno = -ENOMEM;
+ goto return_kfree;
+ }
+
+ /* Create TX queues */
+ for (i = 0; i < crt_fq_count; i++) {
+ ret = oh_fq_create(oh_config->egress_fqs + i,
+ crt_fqid_base + i, *channel_id, 3);
+ if (ret != 0) {
+ dev_err(dpa_oh_dev,
+ "Unable to create TX frame queue %d for OH node %s referenced from node %s!\n",
+ crt_fqid_base + i, oh_node->full_name,
+ dpa_oh_node->full_name);
+ _errno = -EINVAL;
+ goto return_kfree;
+ }
+ }
+
+config_port:
+ /* Get a handle to the fm_port so we can set
+ * its configuration params
+ */
+ oh_config->oh_port = fm_port_bind(oh_dev);
+ if (oh_config->oh_port == NULL) {
+ dev_err(dpa_oh_dev, "NULL drvdata from fm port dev %s!\n",
+ oh_node->full_name);
+ _errno = -EINVAL;
+ goto return_kfree;
+ }
+
+ oh_set_buffer_layout(oh_config->oh_port, &buf_layout);
+ bpool_handle = of_get_property(dpa_oh_node,
+ "fsl,bman-buffer-pools", &lenp);
+
+ if (bpool_handle == NULL) {
+ dev_info(dpa_oh_dev,
+ "OH port %s has no buffer pool. Fragmentation will not be enabled\n",
+ oh_node->full_name);
+ goto init_port;
+ }
+
+ /* used for reading ext_pool_size*/
+ root_node = of_find_node_by_path("/");
+ if (root_node == NULL) {
+ dev_err(dpa_oh_dev, "of_find_node_by_path(/) failed\n");
+ _errno = -EINVAL;
+ goto return_kfree;
+ }
+
+ n_size = of_n_size_cells(root_node);
+ of_node_put(root_node);
+
+ crt_ext_pools_count = lenp / sizeof(phandle);
+ dev_dbg(dpa_oh_dev, "OH port number of pools = %u\n",
+ crt_ext_pools_count);
+
+ oh_port_tx_params.num_pools = crt_ext_pools_count;
+
+ for (i = 0; i < crt_ext_pools_count; i++) {
+ bpool_node = of_find_node_by_phandle(bpool_handle[i]);
+ if (bpool_node == NULL) {
+ dev_err(dpa_oh_dev, "Invalid Buffer pool node\n");
+ _errno = -EINVAL;
+ goto return_kfree;
+ }
+
+ bpid = of_get_property(bpool_node, "fsl,bpid", &lenp);
+ if ((bpid == NULL) || (lenp != sizeof(*bpid))) {
+ dev_err(dpa_oh_dev, "Invalid Buffer pool Id\n");
+ _errno = -EINVAL;
+ goto return_kfree;
+ }
+
+ oh_port_tx_params.pool_param[i].id = *bpid;
+ dev_dbg(dpa_oh_dev, "OH port bpool id = %u\n", *bpid);
+
+ bpool_cfg = of_get_property(bpool_node,
+ "fsl,bpool-ethernet-cfg", &lenp);
+ if (bpool_cfg == NULL) {
+ dev_err(dpa_oh_dev, "Invalid Buffer pool config params\n");
+ _errno = -EINVAL;
+ goto return_kfree;
+ }
+
+ of_read_number(bpool_cfg, n_size);
+ ext_pool_size = of_read_number(bpool_cfg + n_size, n_size);
+ oh_port_tx_params.pool_param[i].size = ext_pool_size;
+ dev_dbg(dpa_oh_dev, "OH port bpool size = %u\n",
+ ext_pool_size);
+ of_node_put(bpool_node);
+
+ }
+
+ if (buf_layout.data_align != FRAG_DATA_ALIGN ||
+ buf_layout.manip_extra_space != FRAG_MANIP_SPACE)
+ goto init_port;
+
+ frag_enabled = true;
+ dev_info(dpa_oh_dev, "IP Fragmentation enabled for OH port %d",
+ *port_id);
+
+init_port:
+ of_node_put(oh_node);
+ /* Set Tx params */
+ dpaa_eth_init_port(tx, oh_config->oh_port, oh_port_tx_params,
+ oh_config->error_fqid, oh_config->default_fqid, (&buf_layout),
+ frag_enabled);
+ /* Set PCD params */
+ oh_port_pcd_params.cba = oh_alloc_pcd_fqids;
+ oh_port_pcd_params.cbf = oh_free_pcd_fqids;
+ oh_port_pcd_params.dev = dpa_oh_dev;
+ fm_port_pcd_bind(oh_config->oh_port, &oh_port_pcd_params);
+
+ dev_set_drvdata(dpa_oh_dev, oh_config);
+
+ /* Enable the OH port */
+ _errno = fm_port_enable(oh_config->oh_port);
+ if (_errno)
+ goto return_kfree;
+
+ dev_info(dpa_oh_dev, "OH port %s enabled.\n", oh_node->full_name);
+
+ /* print of all referenced & created queues */
+ dump_oh_config(dpa_oh_dev, oh_config);
+
+ return 0;
+
+return_kfree:
+ if (bpool_node)
+ of_node_put(bpool_node);
+ if (oh_node)
+ of_node_put(oh_node);
+ if (oh_config && oh_config->egress_fqs)
+ devm_kfree(dpa_oh_dev, oh_config->egress_fqs);
+
+ list_for_each_safe(fq_list, fq_list_tmp, &oh_config->fqs_ingress_list) {
+ fqd = list_entry(fq_list, struct fq_duple, fq_list);
+ list_del(fq_list);
+ devm_kfree(dpa_oh_dev, fqd->fqs);
+ devm_kfree(dpa_oh_dev, fqd);
+ }
+
+ list_for_each_safe(fq_list, fq_list_tmp, &oh_config->fqs_egress_list) {
+ fqd = list_entry(fq_list, struct fq_duple, fq_list);
+ list_del(fq_list);
+ devm_kfree(dpa_oh_dev, fqd->fqs);
+ devm_kfree(dpa_oh_dev, fqd);
+ }
+
+ devm_kfree(dpa_oh_dev, oh_config);
+ return _errno;
+}
+
+static int __cold oh_port_remove(struct platform_device *_of_dev)
+{
+ int _errno = 0, i;
+ struct dpa_oh_config_s *oh_config;
+
+ pr_info("Removing OH port...\n");
+
+ oh_config = dev_get_drvdata(&_of_dev->dev);
+ if (oh_config == NULL) {
+ pr_err(KBUILD_MODNAME
+ ": %s:%hu:%s(): No OH config in device private data!\n",
+ KBUILD_BASENAME".c", __LINE__, __func__);
+ _errno = -ENODEV;
+ goto return_error;
+ }
+
+ if (oh_config->egress_fqs)
+ for (i = 0; i < oh_config->egress_cnt; i++)
+ oh_fq_destroy(oh_config->egress_fqs + i);
+
+ if (oh_config->oh_port == NULL) {
+ pr_err(KBUILD_MODNAME
+ ": %s:%hu:%s(): No fm port in device private data!\n",
+ KBUILD_BASENAME".c", __LINE__, __func__);
+ _errno = -EINVAL;
+ goto free_egress_fqs;
+ }
+
+ _errno = fm_port_disable(oh_config->oh_port);
+
+free_egress_fqs:
+ if (oh_config->egress_fqs)
+ devm_kfree(&_of_dev->dev, oh_config->egress_fqs);
+ devm_kfree(&_of_dev->dev, oh_config);
+ dev_set_drvdata(&_of_dev->dev, NULL);
+
+return_error:
+ return _errno;
+}
+
+static struct platform_driver oh_port_driver = {
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .of_match_table = oh_port_match_table,
+ .owner = THIS_MODULE,
+ .pm = OH_PM_OPS,
+ },
+ .probe = oh_port_probe,
+ .remove = oh_port_remove
+};
+
+static int __init __cold oh_port_load(void)
+{
+ int _errno;
+
+ pr_info(OH_MOD_DESCRIPTION " (" VERSION ")\n");
+
+ _errno = platform_driver_register(&oh_port_driver);
+ if (_errno < 0) {
+ pr_err(KBUILD_MODNAME
+ ": %s:%hu:%s(): platform_driver_register() = %d\n",
+ KBUILD_BASENAME".c", __LINE__, __func__, _errno);
+ }
+
+ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n",
+ KBUILD_BASENAME".c", __func__);
+ return _errno;
+}
+module_init(oh_port_load);
+
+static void __exit __cold oh_port_unload(void)
+{
+ pr_debug(KBUILD_MODNAME ": -> %s:%s()\n",
+ KBUILD_BASENAME".c", __func__);
+
+ platform_driver_unregister(&oh_port_driver);
+
+ pr_debug(KBUILD_MODNAME ": %s:%s() ->\n",
+ KBUILD_BASENAME".c", __func__);
+}
+module_exit(oh_port_unload);
diff --git a/drivers/net/ethernet/freescale/dpa/offline_port.h b/drivers/net/ethernet/freescale/dpa/offline_port.h
new file mode 100644
index 0000000..54b0fe4
--- /dev/null
+++ b/drivers/net/ethernet/freescale/dpa/offline_port.h
@@ -0,0 +1,59 @@
+/* Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __OFFLINE_PORT_H
+#define __OFFLINE_PORT_H
+
+struct fm_port;
+struct qman_fq;
+
+/* fqs are defined in duples (base_fq, fq_count) */
+struct fq_duple {
+ struct qman_fq *fqs;
+ int fqs_count;
+ int channel_id;
+ struct list_head fq_list;
+};
+
+/* OH port configuration */
+struct dpa_oh_config_s {
+ uint32_t error_fqid;
+ uint32_t default_fqid;
+ struct fm_port *oh_port;
+ uint32_t egress_cnt;
+ struct qman_fq *egress_fqs;
+ uint16_t channel;
+
+ struct list_head fqs_ingress_list;
+ struct list_head fqs_egress_list;
+};
+
+#endif /* __OFFLINE_PORT_H */
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 63090c0..28f9835 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -386,7 +386,14 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
*/
bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr,
FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
-
+ if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
+ bdp->cbd_bufaddr = 0;
+ fep->tx_skbuff[index] = NULL;
+ dev_kfree_skb_any(skb);
+ if (net_ratelimit())
+ netdev_err(ndev, "Tx DMA memory map failed\n");
+ return NETDEV_TX_OK;
+ }
/* Send it on its way. Tell FEC it's ready, interrupt when done,
* it's the last BD of the frame, and to put the CRC on the end.
*/
@@ -861,6 +868,7 @@ fec_enet_rx(struct net_device *ndev, int budget)
struct bufdesc_ex *ebdp = NULL;
bool vlan_packet_rcvd = false;
u16 vlan_tag;
+ int index = 0;
#ifdef CONFIG_M532x
flush_cache_all();
@@ -916,10 +924,15 @@ fec_enet_rx(struct net_device *ndev, int budget)
ndev->stats.rx_packets++;
pkt_len = bdp->cbd_datlen;
ndev->stats.rx_bytes += pkt_len;
- data = (__u8*)__va(bdp->cbd_bufaddr);
- dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
- FEC_ENET_TX_FRSIZE, DMA_FROM_DEVICE);
+ if (fep->bufdesc_ex)
+ index = (struct bufdesc_ex *)bdp -
+ (struct bufdesc_ex *)fep->rx_bd_base;
+ else
+ index = bdp - fep->rx_bd_base;
+ data = fep->rx_skbuff[index]->data;
+ dma_sync_single_for_cpu(&fep->pdev->dev, bdp->cbd_bufaddr,
+ FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME)
swap_buffer(data, pkt_len);
@@ -999,8 +1012,8 @@ fec_enet_rx(struct net_device *ndev, int budget)
napi_gro_receive(&fep->napi, skb);
}
- bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, data,
- FEC_ENET_TX_FRSIZE, DMA_FROM_DEVICE);
+ dma_sync_single_for_device(&fep->pdev->dev, bdp->cbd_bufaddr,
+ FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
rx_processing_done:
/* Clear the status flags for this buffer */
status &= ~BD_ENET_RX_STATS;
@@ -1719,6 +1732,12 @@ static int fec_enet_alloc_buffers(struct net_device *ndev)
bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data,
FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
+ if (dma_mapping_error(&fep->pdev->dev, bdp->cbd_bufaddr)) {
+ fec_enet_free_buffers(ndev);
+ if (net_ratelimit())
+ netdev_err(ndev, "Rx DMA memory map failed\n");
+ return -ENOMEM;
+ }
bdp->cbd_sc = BD_ENET_RX_EMPTY;
if (fep->bufdesc_ex) {
diff --git a/drivers/net/ethernet/freescale/fman/Kconfig b/drivers/net/ethernet/freescale/fman/Kconfig
new file mode 100644
index 0000000..a6ecb1a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Kconfig
@@ -0,0 +1,156 @@
+menu "Frame Manager support"
+
+menuconfig FSL_FMAN
+ bool "Freescale Frame Manager (datapath) support"
+ depends on FSL_SOC && FSL_BMAN && FSL_QMAN
+ default y
+ ---help---
+ If unsure, say Y.
+
+if FSL_FMAN
+
+config FSL_FMAN_TEST
+ bool "FMan test module"
+ default n
+ ---help---
+ This option compiles test code for FMan.
+
+menu "FMAN Processor support"
+choice
+ depends on FSL_FMAN
+ prompt "Processor Type"
+
+config FMAN_P3040_P4080_P5020
+ bool "P3040 P4080 5020"
+
+config FMAN_P1023
+ bool "P1023"
+
+config FMAN_T4240
+ bool "T4240"
+
+endchoice
+endmenu
+
+config FMAN_RESOURCE_ALLOCATION_ALGORITHM
+ bool "Enable FMan dynamic resource allocation algorithm"
+ default y if (FMAN_P3040_P4080_P5020 || FMAN_P1023)
+ ---help---
+ Enables algorithm for dynamic resource allocation
+
+config FMAN_DISABLE_OH_TO_REUSE_RESOURCES
+ depends on FMAN_RESOURCE_ALLOCATION_ALGORITHM
+ bool "Disable offline parsing ports to reuse resources"
+ default n
+ ---help---
+ Redistributes FMan OH's resources to all other ports,
+ thus enabling other configurations.
+
+config FMAN_MIB_CNT_OVF_IRQ_EN
+ bool "Enable the dTSEC MIB counters overflow interrupt"
+ default n
+ ---help---
+ Enable the dTSEC MIB counters overflow interrupt to get
+ accurate MIB counters values. Enabled it compensates
+ for the counters overflow but reduces performance and
+ triggers error messages in HV setups.
+
+config FSL_FM_MAX_FRAME_SIZE
+ int "Maximum L2 frame size"
+ depends on FSL_FMAN
+ range 64 9600
+ default "1522"
+ help
+ Configure this in relation to the maximum possible MTU of your
+ network configuration. In particular, one would need to
+ increase this value in order to use jumbo frames.
+ FSL_FM_MAX_FRAME_SIZE must accommodate the Ethernet FCS (4 bytes)
+ and one ETH+VLAN header (18 bytes), to a total of 22 bytes in
+ excess of the desired L3 MTU.
+
+ Note that having too large a FSL_FM_MAX_FRAME_SIZE (much larger
+ than the actual MTU) may lead to buffer exhaustion, especially
+ in the case of badly fragmented datagrams on the Rx path.
+ Conversely, having a FSL_FM_MAX_FRAME_SIZE smaller than the actual
+ MTU will lead to frames being dropped.
+
+ This can be overridden by specifying "fsl_fm_max_frm" in
+ the kernel bootargs:
+ * in Hypervisor-based scenarios, by adding a "chosen" node
+ with the "bootargs" property specifying
+ "fsl_fm_max_frm=<YourValue>";
+ * in non-Hypervisor-based scenarios, via u-boot's env, by
+ modifying the "bootargs" env variable.
+
+config FSL_FM_RX_EXTRA_HEADROOM
+ int "Add extra headroom at beginning of data buffers"
+ depends on FSL_FMAN
+ range 16 384
+ default "64"
+ help
+ Configure this to tell the Frame Manager to reserve some extra
+ space at the beginning of a data buffer on the receive path,
+ before Internal Context fields are copied. This is in addition
+ to the private data area already reserved for driver internal
+ use. The provided value must be a multiple of 16.
+
+ This option does not affect in any way the layout of
+ transmitted buffers. You may be required to enable the config
+ option FMAN_RESOURCE_ALLOCATION_ALGORITHM and also
+ FMAN_DISABLE_OH_TO_REUSE_RESOURCES to have enough resources
+ when using this option and also supporting jumbo frames.
+
+ This setting can be overridden by specifying
+ "fsl_fm_rx_extra_headroom" in the kernel bootargs:
+ * in Hypervisor-based scenarios, by adding a "chosen" node
+ with the "bootargs" property specifying
+ "fsl_fm_rx_extra_headroom=<YourValue>";
+ * in non-Hypervisor-based scenarios, via u-boot's env, by
+ modifying the "bootargs" env variable.
+
+config FMAN_PFC
+ bool "FMan PFC support (EXPERIMENTAL)"
+ depends on FMAN_T4240 && FSL_FMAN
+ default n
+ ---help---
+ This option enables PFC support on FMan v3 ports.
+ Data Center Bridging defines Classes of Service that are
+ flow-controlled using PFC pause frames.
+
+if FMAN_PFC
+config FMAN_PFC_COS_COUNT
+ int "Number of PFC Classes of Service"
+ depends on FMAN_PFC && FSL_FMAN
+ range 1 4
+ default "3"
+ ---help ---
+ The number of Classes of Service controlled by PFC.
+
+config FMAN_PFC_QUANTA_0
+ int "The pause quanta for PFC CoS 0"
+ depends on FMAN_PFC && FSL_FMAN
+ range 0 65535
+ default "65535"
+
+config FMAN_PFC_QUANTA_1
+ int "The pause quanta for PFC CoS 1"
+ depends on FMAN_PFC && FSL_FMAN
+ range 0 65535
+ default "65535"
+
+config FMAN_PFC_QUANTA_2
+ int "The pause quanta for PFC CoS 2"
+ depends on FMAN_PFC && FSL_FMAN
+ range 0 65535
+ default "65535"
+
+config FMAN_PFC_QUANTA_3
+ int "The pause quanta for PFC CoS 3"
+ depends on FMAN_PFC && FSL_FMAN
+ range 0 65535
+ default "65535"
+endif
+
+endif # FSL_FMAN
+
+endmenu
diff --git a/drivers/net/ethernet/freescale/fman/Makefile b/drivers/net/ethernet/freescale/fman/Makefile
new file mode 100644
index 0000000..7115296
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+#
+obj-y += etc/
+obj-y += Peripherals/FM/
+obj-y += src/
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/HC/Makefile b/drivers/net/ethernet/freescale/fman/Peripherals/FM/HC/Makefile
new file mode 100644
index 0000000..bcbc72e
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/HC/Makefile
@@ -0,0 +1,15 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+
+NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc
+
+EXTRA_CFLAGS += -I$(NCSW_FM_INC)
+
+obj-y += fsl-ncsw-Hc.o
+
+fsl-ncsw-Hc-objs := hc.o
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/HC/hc.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/HC/hc.c
new file mode 100644
index 0000000..74047dd
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/HC/hc.c
@@ -0,0 +1,1225 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "sprint_ext.h"
+#include "string_ext.h"
+
+#include "fm_common.h"
+#include "fm_hc.h"
+
+
+/**************************************************************************//**
+ @Description defaults
+*//***************************************************************************/
+#define DEFAULT_dataMemId 0
+
+#define HC_HCOR_OPCODE_PLCR_PRFL 0x0
+#define HC_HCOR_OPCODE_KG_SCM 0x1
+#define HC_HCOR_OPCODE_SYNC 0x2
+#define HC_HCOR_OPCODE_CC 0x3
+#define HC_HCOR_OPCODE_CC_CAPWAP_REASSM_TIMEOUT 0x5
+#define HC_HCOR_OPCODE_CC_IP_REASSM_TIMEOUT 0x10
+#define HC_HCOR_OPCODE_CC_IP_FRAG_INITIALIZATION 0x11
+#define HC_HCOR_ACTION_REG_IP_REASSM_TIMEOUT_ACTIVE_SHIFT 24
+#define HC_HCOR_EXTRA_REG_IP_REASSM_TIMEOUT_TSBS_SHIFT 24
+#define HC_HCOR_ACTION_REG_IP_REASSM_TIMEOUT_RES_SHIFT 16
+#define HC_HCOR_ACTION_REG_IP_REASSM_TIMEOUT_RES_MASK 0xF
+#define HC_HCOR_ACTION_REG_IP_FRAG_SCRATCH_POOL_CMD_SHIFT 24
+#define HC_HCOR_ACTION_REG_IP_FRAG_SCRATCH_POOL_BPID 16
+
+#define HC_HCOR_GBL 0x20000000
+
+#define HC_HCOR_KG_SCHEME_COUNTER 0x00000400
+
+#if (DPAA_VERSION == 10)
+#define HC_HCOR_KG_SCHEME_REGS_MASK 0xFFFFF800
+#else
+#define HC_HCOR_KG_SCHEME_REGS_MASK 0xFFFFFE00
+#endif /* (DPAA_VERSION == 10) */
+
+#define SIZE_OF_HC_FRAME_PORT_REGS (sizeof(t_HcFrame)-sizeof(struct fman_kg_scheme_regs)+sizeof(t_FmPcdKgPortRegs))
+#define SIZE_OF_HC_FRAME_SCHEME_REGS sizeof(t_HcFrame)
+#define SIZE_OF_HC_FRAME_PROFILES_REGS (sizeof(t_HcFrame)-sizeof(struct fman_kg_scheme_regs)+sizeof(t_FmPcdPlcrProfileRegs))
+#define SIZE_OF_HC_FRAME_PROFILE_CNT (sizeof(t_HcFrame)-sizeof(t_FmPcdPlcrProfileRegs)+sizeof(uint32_t))
+#define SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC 16
+
+#define HC_CMD_POOL_SIZE (INTG_MAX_NUM_OF_CORES)
+
+#define BUILD_FD(len) \
+do { \
+ memset(&fmFd, 0, sizeof(t_DpaaFD)); \
+ DPAA_FD_SET_ADDR(&fmFd, p_HcFrame); \
+ DPAA_FD_SET_OFFSET(&fmFd, 0); \
+ DPAA_FD_SET_LENGTH(&fmFd, len); \
+} while (0)
+
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+typedef _Packed struct t_FmPcdKgPortRegs {
+ volatile uint32_t spReg;
+ volatile uint32_t cppReg;
+} _PackedType t_FmPcdKgPortRegs;
+
+typedef _Packed struct t_HcFrame {
+ volatile uint32_t opcode;
+ volatile uint32_t actionReg;
+ volatile uint32_t extraReg;
+ volatile uint32_t commandSequence;
+ union {
+ struct fman_kg_scheme_regs schemeRegs;
+ struct fman_kg_scheme_regs schemeRegsWithoutCounter;
+ t_FmPcdPlcrProfileRegs profileRegs;
+ volatile uint32_t singleRegForWrite; /* for writing SP, CPP, profile counter */
+ t_FmPcdKgPortRegs portRegsForRead;
+ volatile uint32_t clsPlanEntries[CLS_PLAN_NUM_PER_GRP];
+ t_FmPcdCcCapwapReassmTimeoutParams ccCapwapReassmTimeout;
+ t_FmPcdCcIpReassmTimeoutParams ccIpReassmTimeout;
+ } hcSpecificData;
+} _PackedType t_HcFrame;
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+typedef struct t_FmHc {
+ t_Handle h_FmPcd;
+ t_Handle h_HcPortDev;
+ t_FmPcdQmEnqueueCallback *f_QmEnqueue; /**< A callback for enqueuing frames to the QM */
+ t_Handle h_QmArg; /**< A handle to the QM module */
+ uint8_t dataMemId; /**< Memory partition ID for data buffers */
+
+ uint32_t seqNum[HC_CMD_POOL_SIZE]; /* FIFO of seqNum to use when
+ taking buffer */
+ uint32_t nextSeqNumLocation; /* seqNum location in seqNum[] for next buffer */
+ volatile bool enqueued[HC_CMD_POOL_SIZE]; /* HC is active - frame is enqueued
+ and not confirmed yet */
+ t_HcFrame *p_Frm[HC_CMD_POOL_SIZE];
+} t_FmHc;
+
+
+static t_Error FillBufPool(t_FmHc *p_FmHc)
+{
+ uint32_t i;
+
+ ASSERT_COND(p_FmHc);
+
+ for (i = 0; i < HC_CMD_POOL_SIZE; i++)
+ {
+#ifdef FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004
+ p_FmHc->p_Frm[i] = (t_HcFrame *)XX_MallocSmart((sizeof(t_HcFrame) + (16 - (sizeof(t_FmHc) % 16))),
+ p_FmHc->dataMemId,
+ 16);
+#else
+ p_FmHc->p_Frm[i] = (t_HcFrame *)XX_MallocSmart(sizeof(t_HcFrame),
+ p_FmHc->dataMemId,
+ 16);
+#endif /* FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 */
+ if (!p_FmHc->p_Frm[i])
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM HC frames!"));
+ }
+
+ /* Initialize FIFO of seqNum to use during GetBuf */
+ for (i = 0; i < HC_CMD_POOL_SIZE; i++)
+ {
+ p_FmHc->seqNum[i] = i;
+ }
+ p_FmHc->nextSeqNumLocation = 0;
+
+ return E_OK;
+}
+
+static __inline__ t_HcFrame * GetBuf(t_FmHc *p_FmHc, uint32_t *p_SeqNum)
+{
+ uint32_t intFlags;
+
+ ASSERT_COND(p_FmHc);
+
+ intFlags = FmPcdLock(p_FmHc->h_FmPcd);
+
+ if (p_FmHc->nextSeqNumLocation == HC_CMD_POOL_SIZE)
+ {
+ /* No more buffers */
+ FmPcdUnlock(p_FmHc->h_FmPcd, intFlags);
+ return NULL;
+ }
+
+ *p_SeqNum = p_FmHc->seqNum[p_FmHc->nextSeqNumLocation];
+ p_FmHc->nextSeqNumLocation++;
+
+ FmPcdUnlock(p_FmHc->h_FmPcd, intFlags);
+ return p_FmHc->p_Frm[*p_SeqNum];
+}
+
+static __inline__ void PutBuf(t_FmHc *p_FmHc, t_HcFrame *p_Buf, uint32_t seqNum)
+{
+ uint32_t intFlags;
+
+ UNUSED(p_Buf);
+
+ intFlags = FmPcdLock(p_FmHc->h_FmPcd);
+ ASSERT_COND(p_FmHc->nextSeqNumLocation);
+ p_FmHc->nextSeqNumLocation--;
+ p_FmHc->seqNum[p_FmHc->nextSeqNumLocation] = seqNum;
+ FmPcdUnlock(p_FmHc->h_FmPcd, intFlags);
+}
+
+static __inline__ t_Error EnQFrm(t_FmHc *p_FmHc, t_DpaaFD *p_FmFd, uint32_t seqNum)
+{
+ t_Error err = E_OK;
+ uint32_t intFlags;
+ uint32_t timeout=100;
+
+ intFlags = FmPcdLock(p_FmHc->h_FmPcd);
+ ASSERT_COND(!p_FmHc->enqueued[seqNum]);
+ p_FmHc->enqueued[seqNum] = TRUE;
+ FmPcdUnlock(p_FmHc->h_FmPcd, intFlags);
+ DBG(TRACE, ("Send Hc, SeqNum %d, buff@0x%x, fd offset 0x%x",
+ seqNum,
+ DPAA_FD_GET_ADDR(p_FmFd),
+ DPAA_FD_GET_OFFSET(p_FmFd)));
+ err = p_FmHc->f_QmEnqueue(p_FmHc->h_QmArg, (void *)p_FmFd);
+ if (err)
+ RETURN_ERROR(MINOR, err, ("HC enqueue failed"));
+
+ while (p_FmHc->enqueued[seqNum] && --timeout)
+ XX_UDelay(100);
+
+ if (!timeout)
+ RETURN_ERROR(MINOR, E_TIMEOUT, ("HC Callback, timeout exceeded"));
+
+ return err;
+}
+
+
+t_Handle FmHcConfigAndInit(t_FmHcParams *p_FmHcParams)
+{
+ t_FmHc *p_FmHc;
+ t_FmPortParams fmPortParam;
+ t_Error err;
+
+ p_FmHc = (t_FmHc *)XX_Malloc(sizeof(t_FmHc));
+ if (!p_FmHc)
+ {
+ REPORT_ERROR(MINOR, E_NO_MEMORY, ("HC obj"));
+ return NULL;
+ }
+ memset(p_FmHc,0,sizeof(t_FmHc));
+
+ p_FmHc->h_FmPcd = p_FmHcParams->h_FmPcd;
+ p_FmHc->f_QmEnqueue = p_FmHcParams->params.f_QmEnqueue;
+ p_FmHc->h_QmArg = p_FmHcParams->params.h_QmArg;
+ p_FmHc->dataMemId = DEFAULT_dataMemId;
+
+ err = FillBufPool(p_FmHc);
+ if (err != E_OK)
+ {
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ FmHcFree(p_FmHc);
+ return NULL;
+ }
+
+ if (!FmIsMaster(p_FmHcParams->h_Fm))
+ return (t_Handle)p_FmHc;
+
+ memset(&fmPortParam, 0, sizeof(fmPortParam));
+ fmPortParam.baseAddr = p_FmHcParams->params.portBaseAddr;
+ fmPortParam.portType = e_FM_PORT_TYPE_OH_HOST_COMMAND;
+ fmPortParam.portId = p_FmHcParams->params.portId;
+ fmPortParam.liodnBase = p_FmHcParams->params.liodnBase;
+ fmPortParam.h_Fm = p_FmHcParams->h_Fm;
+
+ fmPortParam.specificParams.nonRxParams.errFqid = p_FmHcParams->params.errFqid;
+ fmPortParam.specificParams.nonRxParams.dfltFqid = p_FmHcParams->params.confFqid;
+ fmPortParam.specificParams.nonRxParams.qmChannel = p_FmHcParams->params.qmChannel;
+
+ p_FmHc->h_HcPortDev = FM_PORT_Config(&fmPortParam);
+ if (!p_FmHc->h_HcPortDev)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_HANDLE, ("FM HC port!"));
+ XX_Free(p_FmHc);
+ return NULL;
+ }
+
+ err = FM_PORT_ConfigMaxFrameLength(p_FmHc->h_HcPortDev, sizeof(t_HcFrame));
+ if (err != E_OK)
+ {
+ REPORT_ERROR(MAJOR, err, ("FM HC port init!"));
+ FmHcFree(p_FmHc);
+ return NULL;
+ }
+
+ /* final init */
+ err = FM_PORT_Init(p_FmHc->h_HcPortDev);
+ if (err != E_OK)
+ {
+ REPORT_ERROR(MAJOR, err, ("FM HC port init!"));
+ FmHcFree(p_FmHc);
+ return NULL;
+ }
+
+ err = FM_PORT_Enable(p_FmHc->h_HcPortDev);
+ if (err != E_OK)
+ {
+ REPORT_ERROR(MAJOR, err, ("FM HC port enable!"));
+ FmHcFree(p_FmHc);
+ return NULL;
+ }
+
+ return (t_Handle)p_FmHc;
+}
+
+void FmHcFree(t_Handle h_FmHc)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ int i;
+
+ if (!p_FmHc)
+ return;
+
+ for (i=0; i<HC_CMD_POOL_SIZE; i++)
+ if (p_FmHc->p_Frm[i])
+ XX_FreeSmart(p_FmHc->p_Frm[i]);
+ else
+ break;
+
+ if (p_FmHc->h_HcPortDev)
+ FM_PORT_Free(p_FmHc->h_HcPortDev);
+
+ XX_Free(p_FmHc);
+}
+
+/*****************************************************************************/
+t_Error FmHcSetFramesDataMemory(t_Handle h_FmHc,
+ uint8_t memId)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ int i;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmHc, E_INVALID_HANDLE);
+
+ p_FmHc->dataMemId = memId;
+
+ for (i=0; i<HC_CMD_POOL_SIZE; i++)
+ if (p_FmHc->p_Frm[i])
+ XX_FreeSmart(p_FmHc->p_Frm[i]);
+
+ return FillBufPool(p_FmHc);
+}
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+t_Error FmHcDumpRegs(t_Handle h_FmHc)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmHc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmHc->h_HcPortDev, E_INVALID_HANDLE);
+
+ return FM_PORT_DumpRegs(p_FmHc->h_HcPortDev);
+
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+void FmHcTxConf(t_Handle h_FmHc, t_DpaaFD *p_Fd)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_HcFrame *p_HcFrame;
+ uint32_t intFlags;
+
+ ASSERT_COND(p_FmHc);
+
+ intFlags = FmPcdLock(p_FmHc->h_FmPcd);
+ p_HcFrame = (t_HcFrame *)PTR_MOVE(DPAA_FD_GET_ADDR(p_Fd), DPAA_FD_GET_OFFSET(p_Fd));
+
+ DBG(TRACE, ("Hc Conf, SeqNum %d, FD@0x%x, fd offset 0x%x",
+ p_HcFrame->commandSequence, DPAA_FD_GET_ADDR(p_Fd), DPAA_FD_GET_OFFSET(p_Fd)));
+
+ if (!(p_FmHc->enqueued[p_HcFrame->commandSequence]))
+ REPORT_ERROR(MINOR, E_INVALID_FRAME, ("Not an Host-Command frame received!"));
+ else
+ p_FmHc->enqueued[p_HcFrame->commandSequence] = FALSE;
+ FmPcdUnlock(p_FmHc->h_FmPcd, intFlags);
+}
+
+t_Error FmHcPcdKgSetScheme(t_Handle h_FmHc,
+ t_Handle h_Scheme,
+ struct fman_kg_scheme_regs *p_SchemeRegs,
+ bool updateCounter)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_Error err = E_OK;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ uint8_t physicalSchemeId;
+ uint32_t seqNum;
+
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+
+ physicalSchemeId = FmPcdKgGetSchemeId(h_Scheme);
+
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM);
+ p_HcFrame->actionReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, updateCounter);
+ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK;
+ memcpy(&p_HcFrame->hcSpecificData.schemeRegs, p_SchemeRegs, sizeof(struct fman_kg_scheme_regs));
+ if (!updateCounter)
+ {
+ p_HcFrame->hcSpecificData.schemeRegs.kgse_dv0 = p_SchemeRegs->kgse_dv0;
+ p_HcFrame->hcSpecificData.schemeRegs.kgse_dv1 = p_SchemeRegs->kgse_dv1;
+ p_HcFrame->hcSpecificData.schemeRegs.kgse_ccbs = p_SchemeRegs->kgse_ccbs;
+ p_HcFrame->hcSpecificData.schemeRegs.kgse_mv = p_SchemeRegs->kgse_mv;
+ }
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(sizeof(t_HcFrame));
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+t_Error FmHcPcdKgDeleteScheme(t_Handle h_FmHc, t_Handle h_Scheme)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_Error err = E_OK;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ uint8_t physicalSchemeId = FmPcdKgGetSchemeId(h_Scheme);
+ uint32_t seqNum;
+
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM);
+ p_HcFrame->actionReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, TRUE);
+ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK;
+ memset(&p_HcFrame->hcSpecificData.schemeRegs, 0, sizeof(struct fman_kg_scheme_regs));
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(sizeof(t_HcFrame));
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+t_Error FmHcPcdKgCcGetSetParams(t_Handle h_FmHc, t_Handle h_Scheme, uint32_t requiredAction, uint32_t value)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_Error err = E_OK;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ uint8_t relativeSchemeId;
+ uint8_t physicalSchemeId = FmPcdKgGetSchemeId(h_Scheme);
+ uint32_t tmpReg32 = 0;
+ uint32_t seqNum;
+
+ /* Scheme is locked by calling routine */
+ /* WARNING - this lock will not be efficient if other HC routine will attempt to change
+ * "kgse_mode" or "kgse_om" without locking scheme !
+ */
+
+ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmHc->h_FmPcd, physicalSchemeId);
+ if ( relativeSchemeId == FM_PCD_KG_NUM_OF_SCHEMES)
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
+
+ if (!FmPcdKgGetRequiredActionFlag(p_FmHc->h_FmPcd, relativeSchemeId) ||
+ !(FmPcdKgGetRequiredAction(p_FmHc->h_FmPcd, relativeSchemeId) & requiredAction))
+ {
+ if ((requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) &&
+ (FmPcdKgGetNextEngine(p_FmHc->h_FmPcd, relativeSchemeId) == e_FM_PCD_PLCR))
+ {
+ if ((FmPcdKgIsDirectPlcr(p_FmHc->h_FmPcd, relativeSchemeId) == FALSE) ||
+ (FmPcdKgIsDistrOnPlcrProfile(p_FmHc->h_FmPcd, relativeSchemeId) == TRUE))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("In this situation PP can not be with distribution and has to be shared"));
+ err = FmPcdPlcrCcGetSetParams(p_FmHc->h_FmPcd, FmPcdKgGetRelativeProfileId(p_FmHc->h_FmPcd, relativeSchemeId), requiredAction);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ else /* From here we deal with KG-Schemes only */
+ {
+ /* Pre change general code */
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM);
+ p_HcFrame->actionReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
+ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK;
+ p_HcFrame->commandSequence = seqNum;
+ BUILD_FD(SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC);
+ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK)
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ /* specific change */
+ if ((requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) &&
+ ((FmPcdKgGetNextEngine(p_FmHc->h_FmPcd, relativeSchemeId) == e_FM_PCD_DONE) &&
+ (FmPcdKgGetDoneAction(p_FmHc->h_FmPcd, relativeSchemeId) == e_FM_PCD_ENQ_FRAME)))
+ {
+ tmpReg32 = p_HcFrame->hcSpecificData.schemeRegs.kgse_mode;
+ ASSERT_COND(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME));
+ p_HcFrame->hcSpecificData.schemeRegs.kgse_mode = tmpReg32 | NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA;
+ }
+
+ if ((requiredAction & UPDATE_KG_NIA_CC_WA) &&
+ (FmPcdKgGetNextEngine(p_FmHc->h_FmPcd, relativeSchemeId) == e_FM_PCD_CC))
+ {
+ tmpReg32 = p_HcFrame->hcSpecificData.schemeRegs.kgse_mode;
+ ASSERT_COND(tmpReg32 & (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC));
+ tmpReg32 &= ~NIA_FM_CTL_AC_CC;
+ p_HcFrame->hcSpecificData.schemeRegs.kgse_mode = tmpReg32 | NIA_FM_CTL_AC_PRE_CC;
+ }
+
+ if (requiredAction & UPDATE_KG_OPT_MODE)
+ p_HcFrame->hcSpecificData.schemeRegs.kgse_om = value;
+
+ if (requiredAction & UPDATE_KG_NIA)
+ {
+ tmpReg32 = p_HcFrame->hcSpecificData.schemeRegs.kgse_mode;
+ tmpReg32 &= ~(NIA_ENG_MASK | NIA_AC_MASK);
+ tmpReg32 |= value;
+ p_HcFrame->hcSpecificData.schemeRegs.kgse_mode = tmpReg32;
+ }
+
+ /* Post change general code */
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM);
+ p_HcFrame->actionReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE);
+ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK;
+
+ BUILD_FD(sizeof(t_HcFrame));
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+ }
+
+ return E_OK;
+}
+
+uint32_t FmHcPcdKgGetSchemeCounter(t_Handle h_FmHc, t_Handle h_Scheme)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_Error err;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ uint32_t retVal;
+ uint8_t relativeSchemeId;
+ uint8_t physicalSchemeId = FmPcdKgGetSchemeId(h_Scheme);
+ uint32_t seqNum;
+
+ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmHc->h_FmPcd, physicalSchemeId);
+ if ( relativeSchemeId == FM_PCD_KG_NUM_OF_SCHEMES)
+ {
+ REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
+ return 0;
+ }
+
+ /* first read scheme and check that it is valid */
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ {
+ REPORT_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+ return 0;
+ }
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM);
+ p_HcFrame->actionReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
+ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK;
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC);
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+ if (err != E_OK)
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ return 0;
+ }
+
+ if (!FmPcdKgHwSchemeIsValid(p_HcFrame->hcSpecificData.schemeRegs.kgse_mode))
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ("Scheme is invalid"));
+ return 0;
+ }
+
+ retVal = p_HcFrame->hcSpecificData.schemeRegs.kgse_spc;
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+
+ return retVal;
+}
+
+t_Error FmHcPcdKgSetSchemeCounter(t_Handle h_FmHc, t_Handle h_Scheme, uint32_t value)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_Error err = E_OK;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ uint8_t relativeSchemeId, physicalSchemeId;
+ uint32_t seqNum;
+
+ physicalSchemeId = FmPcdKgGetSchemeId(h_Scheme);
+ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmHc->h_FmPcd, physicalSchemeId);
+ if ( relativeSchemeId == FM_PCD_KG_NUM_OF_SCHEMES)
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
+
+ /* first read scheme and check that it is valid */
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM);
+ p_HcFrame->actionReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, TRUE);
+ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_COUNTER;
+ /* write counter */
+ p_HcFrame->hcSpecificData.singleRegForWrite = value;
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(sizeof(t_HcFrame));
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ return err;
+}
+
+t_Error FmHcPcdKgSetClsPlan(t_Handle h_FmHc, t_FmPcdKgInterModuleClsPlanSet *p_Set)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ uint32_t i;
+ uint32_t seqNum;
+ t_Error err = E_OK;
+
+ ASSERT_COND(p_FmHc);
+
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+
+ for (i = p_Set->baseEntry; i < (p_Set->baseEntry+p_Set->numOfClsPlanEntries); i+=8)
+ {
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM);
+ p_HcFrame->actionReg = FmPcdKgBuildWriteClsPlanBlockActionReg((uint8_t)(i / CLS_PLAN_NUM_PER_GRP));
+ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK;
+ memcpy((void*)&p_HcFrame->hcSpecificData.clsPlanEntries, (void *)&p_Set->vectors[i-p_Set->baseEntry], CLS_PLAN_NUM_PER_GRP*sizeof(uint32_t));
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(sizeof(t_HcFrame));
+
+ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK)
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+ }
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ return err;
+}
+
+t_Error FmHcPcdKgDeleteClsPlan(t_Handle h_FmHc, uint8_t grpId)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet;
+
+ p_ClsPlanSet = (t_FmPcdKgInterModuleClsPlanSet *)XX_Malloc(sizeof(t_FmPcdKgInterModuleClsPlanSet));
+ if (!p_ClsPlanSet)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Classification plan set"));
+
+ memset(p_ClsPlanSet, 0, sizeof(t_FmPcdKgInterModuleClsPlanSet));
+
+ p_ClsPlanSet->baseEntry = FmPcdKgGetClsPlanGrpBase(p_FmHc->h_FmPcd, grpId);
+ p_ClsPlanSet->numOfClsPlanEntries = FmPcdKgGetClsPlanGrpSize(p_FmHc->h_FmPcd, grpId);
+ ASSERT_COND(p_ClsPlanSet->numOfClsPlanEntries <= FM_PCD_MAX_NUM_OF_CLS_PLANS);
+
+ if (FmHcPcdKgSetClsPlan(p_FmHc, p_ClsPlanSet) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+ XX_Free(p_ClsPlanSet);
+
+ FmPcdKgDestroyClsPlanGrp(p_FmHc->h_FmPcd, grpId);
+
+ return E_OK;
+}
+
+t_Error FmHcPcdCcCapwapTimeoutReassm(t_Handle h_FmHc, t_FmPcdCcCapwapReassmTimeoutParams *p_CcCapwapReassmTimeoutParams )
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ t_Error err;
+ uint32_t seqNum;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmHc, E_INVALID_HANDLE,0);
+
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_CC_CAPWAP_REASSM_TIMEOUT);
+ memcpy(&p_HcFrame->hcSpecificData.ccCapwapReassmTimeout, p_CcCapwapReassmTimeoutParams, sizeof(t_FmPcdCcCapwapReassmTimeoutParams));
+ p_HcFrame->commandSequence = seqNum;
+ BUILD_FD(sizeof(t_HcFrame));
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ return err;
+}
+
+t_Error FmHcPcdCcIpFragScratchPollCmd(t_Handle h_FmHc, bool fill, t_FmPcdCcFragScratchPoolCmdParams *p_FmPcdCcFragScratchPoolCmdParams)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ t_Error err;
+ uint32_t seqNum;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmHc, E_INVALID_HANDLE,0);
+
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_CC_IP_FRAG_INITIALIZATION);
+ p_HcFrame->actionReg = (uint32_t)(((fill == TRUE) ? 0 : 1) << HC_HCOR_ACTION_REG_IP_FRAG_SCRATCH_POOL_CMD_SHIFT);
+ p_HcFrame->actionReg |= p_FmPcdCcFragScratchPoolCmdParams->bufferPoolId << HC_HCOR_ACTION_REG_IP_FRAG_SCRATCH_POOL_BPID;
+ if (fill == TRUE)
+ {
+ p_HcFrame->extraReg = p_FmPcdCcFragScratchPoolCmdParams->numOfBuffers;
+ }
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(sizeof(t_HcFrame));
+ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK)
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ p_FmPcdCcFragScratchPoolCmdParams->numOfBuffers = p_HcFrame->extraReg;
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ return E_OK;
+}
+
+t_Error FmHcPcdCcIpTimeoutReassm(t_Handle h_FmHc, t_FmPcdCcIpReassmTimeoutParams *p_CcIpReassmTimeoutParams, uint8_t *p_Result)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ t_Error err;
+ uint32_t seqNum;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmHc, E_INVALID_HANDLE,0);
+
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_CC_IP_REASSM_TIMEOUT);
+ p_HcFrame->actionReg = (uint32_t)((p_CcIpReassmTimeoutParams->activate ? 0 : 1) << HC_HCOR_ACTION_REG_IP_REASSM_TIMEOUT_ACTIVE_SHIFT);
+ p_HcFrame->extraReg = (p_CcIpReassmTimeoutParams->tsbs << HC_HCOR_EXTRA_REG_IP_REASSM_TIMEOUT_TSBS_SHIFT) | p_CcIpReassmTimeoutParams->iprcpt;
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(sizeof(t_HcFrame));
+ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK)
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ *p_Result = (uint8_t)
+ ((p_HcFrame->actionReg >> HC_HCOR_ACTION_REG_IP_REASSM_TIMEOUT_RES_SHIFT) & HC_HCOR_ACTION_REG_IP_REASSM_TIMEOUT_RES_MASK);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ return E_OK;
+}
+
+t_Error FmHcPcdPlcrCcGetSetParams(t_Handle h_FmHc,uint16_t absoluteProfileId, uint32_t requiredAction)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ t_Error err;
+ uint32_t tmpReg32 = 0;
+ uint32_t requiredActionTmp, requiredActionFlag;
+ uint32_t seqNum;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmHc, E_INVALID_HANDLE,0);
+
+ /* Profile is locked by calling routine */
+ /* WARNING - this lock will not be efficient if other HC routine will attempt to change
+ * "fmpl_pegnia" "fmpl_peynia" or "fmpl_pernia" without locking Profile !
+ */
+
+ requiredActionTmp = FmPcdPlcrGetRequiredAction(p_FmHc->h_FmPcd, absoluteProfileId);
+ requiredActionFlag = FmPcdPlcrGetRequiredActionFlag(p_FmHc->h_FmPcd, absoluteProfileId);
+
+ if (!requiredActionFlag || !(requiredActionTmp & requiredAction))
+ {
+ if (requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA)
+ {
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+ /* first read scheme and check that it is valid */
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL);
+ p_HcFrame->actionReg = FmPcdPlcrBuildReadPlcrActionReg(absoluteProfileId);
+ p_HcFrame->extraReg = 0x00008000;
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC);
+
+ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK)
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ tmpReg32 = p_HcFrame->hcSpecificData.profileRegs.fmpl_pegnia;
+ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)))
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,
+ ("Next engine of this policer profile has to be assigned to FM_PCD_DONE"));
+ }
+
+ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA;
+
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL);
+ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionReg(absoluteProfileId);
+ p_HcFrame->actionReg |= FmPcdPlcrBuildNiaProfileReg(TRUE, FALSE, FALSE);
+ p_HcFrame->extraReg = 0x00008000;
+ p_HcFrame->hcSpecificData.singleRegForWrite = tmpReg32;
+
+ BUILD_FD(SIZE_OF_HC_FRAME_PROFILE_CNT);
+
+ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK)
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ tmpReg32 = p_HcFrame->hcSpecificData.profileRegs.fmpl_peynia;
+ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)))
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE"));
+ }
+
+ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA;
+
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL);
+ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionReg(absoluteProfileId);
+ p_HcFrame->actionReg |= FmPcdPlcrBuildNiaProfileReg(FALSE, TRUE, FALSE);
+ p_HcFrame->extraReg = 0x00008000;
+ p_HcFrame->hcSpecificData.singleRegForWrite = tmpReg32;
+
+ BUILD_FD(SIZE_OF_HC_FRAME_PROFILE_CNT);
+
+ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK)
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ tmpReg32 = p_HcFrame->hcSpecificData.profileRegs.fmpl_pernia;
+ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)))
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE"));
+ }
+
+ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA;
+
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL);
+ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionReg(absoluteProfileId);
+ p_HcFrame->actionReg |= FmPcdPlcrBuildNiaProfileReg(FALSE, FALSE, TRUE);
+ p_HcFrame->extraReg = 0x00008000;
+ p_HcFrame->hcSpecificData.singleRegForWrite = tmpReg32;
+
+ BUILD_FD(SIZE_OF_HC_FRAME_PROFILE_CNT);
+
+ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK)
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ }
+ }
+
+ return E_OK;
+}
+
+t_Error FmHcPcdPlcrSetProfile(t_Handle h_FmHc, t_Handle h_Profile, t_FmPcdPlcrProfileRegs *p_PlcrRegs)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_Error err = E_OK;
+ uint16_t profileIndx;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ uint32_t seqNum;
+
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+
+ profileIndx = FmPcdPlcrProfileGetAbsoluteId(h_Profile);
+
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL);
+ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionRegs(profileIndx);
+ p_HcFrame->extraReg = 0x00008000;
+ memcpy(&p_HcFrame->hcSpecificData.profileRegs, p_PlcrRegs, sizeof(t_FmPcdPlcrProfileRegs));
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(sizeof(t_HcFrame));
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+t_Error FmHcPcdPlcrDeleteProfile(t_Handle h_FmHc, t_Handle h_Profile)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ uint16_t absoluteProfileId = FmPcdPlcrProfileGetAbsoluteId(h_Profile);
+ t_Error err = E_OK;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ uint32_t seqNum;
+
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL);
+ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionReg(absoluteProfileId);
+ p_HcFrame->actionReg |= 0x00008000;
+ p_HcFrame->extraReg = 0x00008000;
+ memset(&p_HcFrame->hcSpecificData.profileRegs, 0, sizeof(t_FmPcdPlcrProfileRegs));
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(sizeof(t_HcFrame));
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+t_Error FmHcPcdPlcrSetProfileCounter(t_Handle h_FmHc, t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter, uint32_t value)
+{
+
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ uint16_t absoluteProfileId = FmPcdPlcrProfileGetAbsoluteId(h_Profile);
+ t_Error err = E_OK;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ uint32_t seqNum;
+
+ /* first read scheme and check that it is valid */
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL);
+ p_HcFrame->actionReg = FmPcdPlcrBuildWritePlcrActionReg(absoluteProfileId);
+ p_HcFrame->actionReg |= FmPcdPlcrBuildCounterProfileReg(counter);
+ p_HcFrame->extraReg = 0x00008000;
+ p_HcFrame->hcSpecificData.singleRegForWrite = value;
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(SIZE_OF_HC_FRAME_PROFILE_CNT);
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+uint32_t FmHcPcdPlcrGetProfileCounter(t_Handle h_FmHc, t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ uint16_t absoluteProfileId = FmPcdPlcrProfileGetAbsoluteId(h_Profile);
+ t_Error err;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ uint32_t retVal = 0;
+ uint32_t seqNum;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmHc, E_INVALID_HANDLE,0);
+
+ /* first read scheme and check that it is valid */
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ {
+ REPORT_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+ return 0;
+ }
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_PLCR_PRFL);
+ p_HcFrame->actionReg = FmPcdPlcrBuildReadPlcrActionReg(absoluteProfileId);
+ p_HcFrame->extraReg = 0x00008000;
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC);
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+ if (err != E_OK)
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ return 0;
+ }
+
+ switch (counter)
+ {
+ case e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER:
+ retVal = p_HcFrame->hcSpecificData.profileRegs.fmpl_pegpc;
+ break;
+ case e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER:
+ retVal = p_HcFrame->hcSpecificData.profileRegs.fmpl_peypc;
+ break;
+ case e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER:
+ retVal = p_HcFrame->hcSpecificData.profileRegs.fmpl_perpc;
+ break;
+ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER:
+ retVal = p_HcFrame->hcSpecificData.profileRegs.fmpl_perypc;
+ break;
+ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER:
+ retVal = p_HcFrame->hcSpecificData.profileRegs.fmpl_perrpc;
+ break;
+ default:
+ REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ return retVal;
+}
+
+t_Error FmHcKgWriteSp(t_Handle h_FmHc, uint8_t hardwarePortId, uint32_t spReg, bool add)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ t_Error err = E_OK;
+ uint32_t seqNum;
+
+ ASSERT_COND(p_FmHc);
+
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ /* first read SP register */
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM);
+ p_HcFrame->actionReg = FmPcdKgBuildReadPortSchemeBindActionReg(hardwarePortId);
+ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK;
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(SIZE_OF_HC_FRAME_PORT_REGS);
+
+ if ((err = EnQFrm(p_FmHc, &fmFd, seqNum)) != E_OK)
+ {
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ /* spReg is the first reg, so we can use it both for read and for write */
+ if (add)
+ p_HcFrame->hcSpecificData.portRegsForRead.spReg |= spReg;
+ else
+ p_HcFrame->hcSpecificData.portRegsForRead.spReg &= ~spReg;
+
+ p_HcFrame->actionReg = FmPcdKgBuildWritePortSchemeBindActionReg(hardwarePortId);
+
+ BUILD_FD(sizeof(t_HcFrame));
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+t_Error FmHcKgWriteCpp(t_Handle h_FmHc, uint8_t hardwarePortId, uint32_t cppReg)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ t_Error err = E_OK;
+ uint32_t seqNum;
+
+ ASSERT_COND(p_FmHc);
+
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ /* first read SP register */
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_KG_SCM);
+ p_HcFrame->actionReg = FmPcdKgBuildWritePortClsPlanBindActionReg(hardwarePortId);
+ p_HcFrame->extraReg = HC_HCOR_KG_SCHEME_REGS_MASK;
+ p_HcFrame->hcSpecificData.singleRegForWrite = cppReg;
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(sizeof(t_HcFrame));
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+t_Error FmHcPcdCcDoDynamicChange(t_Handle h_FmHc, uint32_t oldAdAddrOffset, uint32_t newAdAddrOffset)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ t_Error err = E_OK;
+ uint32_t seqNum;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmHc, E_INVALID_HANDLE);
+
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_CC);
+ p_HcFrame->actionReg = newAdAddrOffset;
+ p_HcFrame->actionReg |= 0xc0000000;
+ p_HcFrame->extraReg = oldAdAddrOffset;
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(SIZE_OF_HC_FRAME_READ_OR_CC_DYNAMIC);
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+t_Error FmHcPcdSync(t_Handle h_FmHc)
+{
+ t_FmHc *p_FmHc = (t_FmHc*)h_FmHc;
+ t_HcFrame *p_HcFrame;
+ t_DpaaFD fmFd;
+ t_Error err = E_OK;
+ uint32_t seqNum;
+
+ ASSERT_COND(p_FmHc);
+
+ p_HcFrame = GetBuf(p_FmHc, &seqNum);
+ if (!p_HcFrame)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("HC Frame object"));
+ memset(p_HcFrame, 0, sizeof(t_HcFrame));
+ /* first read SP register */
+ p_HcFrame->opcode = (uint32_t)(HC_HCOR_GBL | HC_HCOR_OPCODE_SYNC);
+ p_HcFrame->actionReg = 0;
+ p_HcFrame->extraReg = 0;
+ p_HcFrame->commandSequence = seqNum;
+
+ BUILD_FD(sizeof(t_HcFrame));
+
+ err = EnQFrm(p_FmHc, &fmFd, seqNum);
+
+ PutBuf(p_FmHc, p_HcFrame, seqNum);
+
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ return E_OK;
+}
+
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/Makefile b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/Makefile
new file mode 100644
index 0000000..f89b563
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/Makefile
@@ -0,0 +1,21 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+
+NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc
+
+EXTRA_CFLAGS += -I$(NCSW_FM_INC)
+
+obj-y += fsl-ncsw-MAC.o
+
+fsl-ncsw-MAC-objs := dtsec.o dtsec_mii_acc.o fm_mac.o tgec.o tgec_mii_acc.o \
+ fman_dtsec.o fman_dtsec_mii_acc.o fman_memac.o \
+ fman_tgec.o fman_crc32.o
+
+ifeq ($(CONFIG_FMAN_T4240),y)
+fsl-ncsw-MAC-objs += memac.o memac_mii_acc.o fman_memac_mii_acc.o
+endif
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec.c
new file mode 100644
index 0000000..42c8e78
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec.c
@@ -0,0 +1,1516 @@
+/*
+ * Copyright 2008-2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/******************************************************************************
+ @File dtsec.c
+
+ @Description FMan dTSEC driver
+*//***************************************************************************/
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "string_ext.h"
+#include "xx_ext.h"
+#include "endian_ext.h"
+#include "debug_ext.h"
+#include "crc_mac_addr_ext.h"
+
+#include "fm_common.h"
+#include "dtsec.h"
+#include "fsl_fman_dtsec.h"
+#include "fsl_fman_dtsec_mii_acc.h"
+
+/*****************************************************************************/
+/* Internal routines */
+/*****************************************************************************/
+
+static t_Error CheckInitParameters(t_Dtsec *p_Dtsec)
+{
+ if (ENET_SPEED_FROM_MODE(p_Dtsec->enetMode) >= e_ENET_SPEED_10000)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet 1G MAC driver only supports 1G or lower speeds"));
+ if (p_Dtsec->macId >= FM_MAX_NUM_OF_1G_MACS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("macId can not be greater than the number of 1G MACs"));
+ if (p_Dtsec->addr == 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet MAC Must have a valid MAC Address"));
+ if ((ENET_SPEED_FROM_MODE(p_Dtsec->enetMode) >= e_ENET_SPEED_1000) &&
+ p_Dtsec->p_DtsecDriverParam->halfdup_on)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet MAC 1G can't work in half duplex"));
+ if (p_Dtsec->p_DtsecDriverParam->halfdup_on && (p_Dtsec->p_DtsecDriverParam)->loopback)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("LoopBack is not supported in halfDuplex mode"));
+#ifdef FM_RX_PREAM_4_ERRATA_DTSEC_A001
+ if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev <= 6) /* fixed for rev3 */
+ if (p_Dtsec->p_DtsecDriverParam->rx_preamble)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("preambleRxEn"));
+#endif /* FM_RX_PREAM_4_ERRATA_DTSEC_A001 */
+ if (((p_Dtsec->p_DtsecDriverParam)->tx_preamble || (p_Dtsec->p_DtsecDriverParam)->rx_preamble) &&( (p_Dtsec->p_DtsecDriverParam)->preamble_len != 0x7))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Preamble length should be 0x7 bytes"));
+ if ((p_Dtsec->p_DtsecDriverParam)->halfdup_on &&
+ (p_Dtsec->p_DtsecDriverParam->tx_time_stamp_en || p_Dtsec->p_DtsecDriverParam->rx_time_stamp_en))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dTSEC in half duplex mode has to be with 1588 timeStamping diable"));
+ if ((p_Dtsec->p_DtsecDriverParam)->rx_flow && (p_Dtsec->p_DtsecDriverParam)->rx_ctrl_acc )
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Receive control frame are not passed to the system memory so it can not be accept "));
+ if ((p_Dtsec->p_DtsecDriverParam)->rx_prepend > MAX_PACKET_ALIGNMENT)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("packetAlignmentPadding can't be greater than %d ",MAX_PACKET_ALIGNMENT ));
+ if (((p_Dtsec->p_DtsecDriverParam)->non_back_to_back_ipg1 > MAX_INTER_PACKET_GAP) ||
+ ((p_Dtsec->p_DtsecDriverParam)->non_back_to_back_ipg2 > MAX_INTER_PACKET_GAP) ||
+ ((p_Dtsec->p_DtsecDriverParam)->back_to_back_ipg > MAX_INTER_PACKET_GAP))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inter packet gap can't be greater than %d ",MAX_INTER_PACKET_GAP ));
+ if ((p_Dtsec->p_DtsecDriverParam)->halfdup_alt_backoff_val > MAX_INTER_PALTERNATE_BEB)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("alternateBackoffVal can't be greater than %d ",MAX_INTER_PALTERNATE_BEB ));
+ if ((p_Dtsec->p_DtsecDriverParam)->halfdup_retransmit > MAX_RETRANSMISSION)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("maxRetransmission can't be greater than %d ",MAX_RETRANSMISSION ));
+ if ((p_Dtsec->p_DtsecDriverParam)->halfdup_coll_window > MAX_COLLISION_WINDOW)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("collisionWindow can't be greater than %d ",MAX_COLLISION_WINDOW ));
+
+ /* If Auto negotiation process is disabled, need to */
+ /* Set up the PHY using the MII Management Interface */
+ if (p_Dtsec->p_DtsecDriverParam->tbipa > MAX_PHYS)
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ("PHY address (should be 0-%d)", MAX_PHYS));
+ if (!p_Dtsec->f_Exception)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("uninitialized f_Exception"));
+ if (!p_Dtsec->f_Event)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("uninitialized f_Event"));
+
+#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002
+ if (p_Dtsec->p_DtsecDriverParam->rx_len_check)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("LengthCheck!"));
+#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static uint32_t GetMacAddrHashCode(uint64_t ethAddr)
+{
+ uint32_t crc;
+
+ /* CRC calculation */
+ GET_MAC_ADDR_CRC(ethAddr, crc);
+
+ crc = GetMirror32(crc);
+
+ return crc;
+}
+
+/* ......................................................................... */
+
+static void UpdateStatistics(t_Dtsec *p_Dtsec)
+{
+ uint32_t car1, car2;
+
+ fman_dtsec_get_clear_carry_regs(p_Dtsec->p_MemMap, &car1, &car2);
+
+ if (car1)
+ {
+ if (car1 & CAR1_TR64)
+ p_Dtsec->internalStatistics.tr64 += VAL22BIT;
+ if (car1 & CAR1_TR127)
+ p_Dtsec->internalStatistics.tr127 += VAL22BIT;
+ if (car1 & CAR1_TR255)
+ p_Dtsec->internalStatistics.tr255 += VAL22BIT;
+ if (car1 & CAR1_TR511)
+ p_Dtsec->internalStatistics.tr511 += VAL22BIT;
+ if (car1 & CAR1_TRK1)
+ p_Dtsec->internalStatistics.tr1k += VAL22BIT;
+ if (car1 & CAR1_TRMAX)
+ p_Dtsec->internalStatistics.trmax += VAL22BIT;
+ if (car1 & CAR1_TRMGV)
+ p_Dtsec->internalStatistics.trmgv += VAL22BIT;
+ if (car1 & CAR1_RBYT)
+ p_Dtsec->internalStatistics.rbyt += (uint64_t)VAL32BIT;
+ if (car1 & CAR1_RPKT)
+ p_Dtsec->internalStatistics.rpkt += VAL22BIT;
+ if (car1 & CAR1_RMCA)
+ p_Dtsec->internalStatistics.rmca += VAL22BIT;
+ if (car1 & CAR1_RBCA)
+ p_Dtsec->internalStatistics.rbca += VAL22BIT;
+ if (car1 & CAR1_RXPF)
+ p_Dtsec->internalStatistics.rxpf += VAL16BIT;
+ if (car1 & CAR1_RALN)
+ p_Dtsec->internalStatistics.raln += VAL16BIT;
+ if (car1 & CAR1_RFLR)
+ p_Dtsec->internalStatistics.rflr += VAL16BIT;
+ if (car1 & CAR1_RCDE)
+ p_Dtsec->internalStatistics.rcde += VAL16BIT;
+ if (car1 & CAR1_RCSE)
+ p_Dtsec->internalStatistics.rcse += VAL16BIT;
+ if (car1 & CAR1_RUND)
+ p_Dtsec->internalStatistics.rund += VAL16BIT;
+ if (car1 & CAR1_ROVR)
+ p_Dtsec->internalStatistics.rovr += VAL16BIT;
+ if (car1 & CAR1_RFRG)
+ p_Dtsec->internalStatistics.rfrg += VAL16BIT;
+ if (car1 & CAR1_RJBR)
+ p_Dtsec->internalStatistics.rjbr += VAL16BIT;
+ if (car1 & CAR1_RDRP)
+ p_Dtsec->internalStatistics.rdrp += VAL16BIT;
+ }
+ if (car2)
+ {
+ if (car2 & CAR2_TFCS)
+ p_Dtsec->internalStatistics.tfcs += VAL12BIT;
+ if (car2 & CAR2_TBYT)
+ p_Dtsec->internalStatistics.tbyt += (uint64_t)VAL32BIT;
+ if (car2 & CAR2_TPKT)
+ p_Dtsec->internalStatistics.tpkt += VAL22BIT;
+ if (car2 & CAR2_TMCA)
+ p_Dtsec->internalStatistics.tmca += VAL22BIT;
+ if (car2 & CAR2_TBCA)
+ p_Dtsec->internalStatistics.tbca += VAL22BIT;
+ if (car2 & CAR2_TXPF)
+ p_Dtsec->internalStatistics.txpf += VAL16BIT;
+ if (car2 & CAR2_TDRP)
+ p_Dtsec->internalStatistics.tdrp += VAL16BIT;
+ }
+}
+
+/* .............................................................................. */
+
+static uint16_t DtsecGetMaxFrameLength(t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_VALUE(p_Dtsec, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_VALUE(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE, 0);
+
+ return fman_dtsec_get_max_frame_len(p_Dtsec->p_MemMap);
+}
+
+/* .............................................................................. */
+
+static void DtsecIsr(t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ uint32_t event;
+ struct dtsec_regs *p_DtsecMemMap = p_Dtsec->p_MemMap;
+
+ /* do not handle MDIO events */
+ event = fman_dtsec_get_event(p_DtsecMemMap, (uint32_t)(~(DTSEC_IMASK_MMRDEN | DTSEC_IMASK_MMWREN)));
+
+ event &= fman_dtsec_get_interrupt_mask(p_DtsecMemMap);
+
+ fman_dtsec_ack_event(p_DtsecMemMap, event);
+
+ if (event & DTSEC_IMASK_BREN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_BAB_RX);
+ if (event & DTSEC_IMASK_RXCEN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_RX_CTL);
+ if (event & DTSEC_IMASK_MSROEN)
+ UpdateStatistics(p_Dtsec);
+ if (event & DTSEC_IMASK_GTSCEN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET);
+ if (event & DTSEC_IMASK_BTEN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_BAB_TX);
+ if (event & DTSEC_IMASK_TXCEN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_CTL);
+ if (event & DTSEC_IMASK_TXEEN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_ERR);
+ if (event & DTSEC_IMASK_LCEN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_LATE_COL);
+ if (event & DTSEC_IMASK_CRLEN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_COL_RET_LMT);
+ if (event & DTSEC_IMASK_XFUNEN)
+ {
+#ifdef FM_TX_LOCKUP_ERRATA_DTSEC6
+ if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2)
+ {
+ uint32_t tpkt1, tmpReg1, tpkt2, tmpReg2, i;
+ /* a. Write 0x00E0_0C00 to DTSEC_ID */
+ /* This is a read only regidter */
+
+ /* b. Read and save the value of TPKT */
+ tpkt1 = GET_UINT32(p_DtsecMemMap->tpkt);
+
+ /* c. Read the register at dTSEC address offset 0x32C */
+ tmpReg1 = GET_UINT32(*(uint32_t*)((uint8_t*)p_DtsecMemMap + 0x32c));
+
+ /* d. Compare bits [9:15] to bits [25:31] of the register at address offset 0x32C. */
+ if ((tmpReg1 & 0x007F0000) != (tmpReg1 & 0x0000007F))
+ {
+ /* If they are not equal, save the value of this register and wait for at least
+ * MAXFRM*16 ns */
+ XX_UDelay((uint32_t)(MIN(DtsecGetMaxFrameLength(p_Dtsec)*16/1000, 1)));
+ }
+
+ /* e. Read and save TPKT again and read the register at dTSEC address offset
+ 0x32C again*/
+ tpkt2 = GET_UINT32(p_DtsecMemMap->tpkt);
+ tmpReg2 = GET_UINT32(*(uint32_t*)((uint8_t*)p_DtsecMemMap + 0x32c));
+
+ /* f. Compare the value of TPKT saved in step b to value read in step e. Also
+ compare bits [9:15] of the register at offset 0x32C saved in step d to the value
+ of bits [9:15] saved in step e. If the two registers values are unchanged, then
+ the transmit portion of the dTSEC controller is locked up and the user should
+ proceed to the recover sequence. */
+ if ((tpkt1 == tpkt2) && ((tmpReg1 & 0x007F0000) == (tmpReg2 & 0x007F0000)))
+ {
+ /* recover sequence */
+
+ /* a.Write a 1 to RCTRL[GRS]*/
+
+ WRITE_UINT32(p_DtsecMemMap->rctrl, GET_UINT32(p_DtsecMemMap->rctrl) | RCTRL_GRS);
+
+ /* b.Wait until IEVENT[GRSC]=1, or at least 100 us has elapsed. */
+ for (i = 0 ; i < 100 ; i++ )
+ {
+ if (GET_UINT32(p_DtsecMemMap->ievent) & DTSEC_IMASK_GRSCEN)
+ break;
+ XX_UDelay(1);
+ }
+ if (GET_UINT32(p_DtsecMemMap->ievent) & DTSEC_IMASK_GRSCEN)
+ WRITE_UINT32(p_DtsecMemMap->ievent, DTSEC_IMASK_GRSCEN);
+ else
+ DBG(INFO,("Rx lockup due to dTSEC Tx lockup"));
+
+ /* c.Write a 1 to bit n of FM_RSTC (offset 0x0CC of FPM)*/
+ FmResetMac(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MAC_1G, p_Dtsec->fmMacControllerDriver.macId);
+
+ /* d.Wait 4 Tx clocks (32 ns) */
+ XX_UDelay(1);
+
+ /* e.Write a 0 to bit n of FM_RSTC. */
+ /* cleared by FMAN */
+ }
+ }
+#endif /* FM_TX_LOCKUP_ERRATA_DTSEC6 */
+
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_FIFO_UNDRN);
+ }
+ if (event & DTSEC_IMASK_MAGEN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_MAG_PCKT);
+ if (event & DTSEC_IMASK_GRSCEN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET);
+ if (event & DTSEC_IMASK_TDPEEN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_DATA_ERR);
+ if (event & DTSEC_IMASK_RDPEEN)
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_RX_DATA_ERR);
+
+ /* - masked interrupts */
+ ASSERT_COND(!(event & DTSEC_IMASK_ABRTEN));
+ ASSERT_COND(!(event & DTSEC_IMASK_IFERREN));
+}
+
+static void DtsecMdioIsr(t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ uint32_t event;
+ struct dtsec_regs *p_DtsecMemMap = p_Dtsec->p_MemMap;
+
+ event = GET_UINT32(p_DtsecMemMap->ievent);
+ /* handle only MDIO events */
+ event &= (DTSEC_IMASK_MMRDEN | DTSEC_IMASK_MMWREN);
+ if (event)
+ {
+ event &= GET_UINT32(p_DtsecMemMap->imask);
+
+ WRITE_UINT32(p_DtsecMemMap->ievent, event);
+
+ if (event & DTSEC_IMASK_MMRDEN)
+ p_Dtsec->f_Event(p_Dtsec->h_App, e_FM_MAC_EX_1G_MII_MNG_RD_COMPLET);
+ if (event & DTSEC_IMASK_MMWREN)
+ p_Dtsec->f_Event(p_Dtsec->h_App, e_FM_MAC_EX_1G_MII_MNG_WR_COMPLET);
+ }
+}
+
+static void Dtsec1588Isr(t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ uint32_t event;
+ struct dtsec_regs *p_DtsecMemMap = p_Dtsec->p_MemMap;
+
+ if (p_Dtsec->ptpTsuEnabled)
+ {
+ event = fman_dtsec_check_and_clear_tmr_event(p_DtsecMemMap);
+
+ if (event)
+ {
+ ASSERT_COND(event & TMR_PEVENT_TSRE);
+ p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_1588_TS_RX_ERR);
+ }
+ }
+}
+
+/* ........................................................................... */
+
+static void FreeInitResources(t_Dtsec *p_Dtsec)
+{
+ /*TODO - need to ask why with mdioIrq != 0*/
+ if ((p_Dtsec->mdioIrq != 0) && (p_Dtsec->mdioIrq != NO_IRQ))
+ {
+ XX_DisableIntr(p_Dtsec->mdioIrq);
+ XX_FreeIntr(p_Dtsec->mdioIrq);
+ }
+ FmUnregisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MOD_1G_MAC, p_Dtsec->macId, e_FM_INTR_TYPE_ERR);
+ FmUnregisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MOD_1G_MAC, p_Dtsec->macId, e_FM_INTR_TYPE_NORMAL);
+
+ /* release the driver's group hash table */
+ FreeHashTable(p_Dtsec->p_MulticastAddrHash);
+ p_Dtsec->p_MulticastAddrHash = NULL;
+
+ /* release the driver's individual hash table */
+ FreeHashTable(p_Dtsec->p_UnicastAddrHash);
+ p_Dtsec->p_UnicastAddrHash = NULL;
+}
+
+/* ........................................................................... */
+
+static t_Error GracefulStop(t_Dtsec *p_Dtsec, e_CommMode mode)
+{
+ struct dtsec_regs *p_MemMap;
+
+ ASSERT_COND(p_Dtsec);
+
+ p_MemMap = p_Dtsec->p_MemMap;
+ ASSERT_COND(p_MemMap);
+
+ /* Assert the graceful transmit stop bit */
+ if (mode & e_COMM_MODE_RX)
+ {
+ fman_dtsec_stop_rx(p_MemMap);
+
+#ifdef FM_GRS_ERRATA_DTSEC_A002
+ if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2)
+ XX_UDelay(100);
+#else /* FM_GRS_ERRATA_DTSEC_A002 */
+#ifdef FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839
+ XX_UDelay(10);
+#endif /* FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839 */
+#endif /* FM_GRS_ERRATA_DTSEC_A002 */
+ }
+
+ if (mode & e_COMM_MODE_TX)
+#if defined(FM_GTS_ERRATA_DTSEC_A004) || defined(FM_GTS_AFTER_MAC_ABORTED_FRAME_ERRATA_DTSEC_A0012)
+ if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2)
+ DBG(INFO, ("GTS not supported due to DTSEC_A004 errata."));
+#else /* not defined(FM_GTS_ERRATA_DTSEC_A004) ||... */
+#ifdef FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014
+ DBG(INFO, ("GTS not supported due to DTSEC_A0014 errata."));
+#else /* FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 */
+ fman_dtsec_stop_tx(p_MemMap);
+#endif /* FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 */
+#endif /* defined(FM_GTS_ERRATA_DTSEC_A004) ||... */
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error GracefulRestart(t_Dtsec *p_Dtsec, e_CommMode mode)
+{
+ struct dtsec_regs *p_MemMap;
+
+ ASSERT_COND(p_Dtsec);
+ p_MemMap = p_Dtsec->p_MemMap;
+ ASSERT_COND(p_MemMap);
+
+ /* clear the graceful receive stop bit */
+ if (mode & e_COMM_MODE_TX)
+ fman_dtsec_start_tx(p_MemMap);
+
+ if (mode & e_COMM_MODE_RX)
+ fman_dtsec_start_rx(p_MemMap);
+
+ return E_OK;
+}
+
+
+/*****************************************************************************/
+/* dTSEC Configs modification functions */
+/*****************************************************************************/
+
+/* .............................................................................. */
+
+static t_Error DtsecConfigLoopback(t_Handle h_Dtsec, bool newVal)
+{
+
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ p_Dtsec->p_DtsecDriverParam->loopback = newVal;
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecConfigMaxFrameLength(t_Handle h_Dtsec, uint16_t newVal)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ p_Dtsec->p_DtsecDriverParam->maximum_frame = newVal;
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecConfigPadAndCrc(t_Handle h_Dtsec, bool newVal)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ p_Dtsec->p_DtsecDriverParam->tx_pad_crc = newVal;
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecConfigHalfDuplex(t_Handle h_Dtsec, bool newVal)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ p_Dtsec->p_DtsecDriverParam->halfdup_on = newVal;
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecConfigTbiPhyAddr(t_Handle h_Dtsec, uint8_t newVal)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ p_Dtsec->p_DtsecDriverParam->tbi_phy_addr = newVal;
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecConfigLengthCheck(t_Handle h_Dtsec, bool newVal)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ p_Dtsec->p_DtsecDriverParam->rx_len_check = newVal;
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecConfigException(t_Handle h_Dtsec, e_FmMacExceptions exception, bool enable)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ uint32_t bitMask = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ if (exception != e_FM_MAC_EX_1G_1588_TS_RX_ERR)
+ {
+ GET_EXCEPTION_FLAG(bitMask, exception);
+ if (bitMask)
+ {
+ if (enable)
+ p_Dtsec->exceptions |= bitMask;
+ else
+ p_Dtsec->exceptions &= ~bitMask;
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
+ }
+ else
+ {
+ if (!p_Dtsec->ptpTsuEnabled)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exception valid for 1588 only"));
+ switch (exception){
+ case (e_FM_MAC_EX_1G_1588_TS_RX_ERR):
+ if (enable)
+ p_Dtsec->enTsuErrExeption = TRUE;
+ else
+ p_Dtsec->enTsuErrExeption = FALSE;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
+ }
+ }
+ return E_OK;
+}
+
+
+/*****************************************************************************/
+/* dTSEC Run Time API functions */
+/*****************************************************************************/
+
+/* .............................................................................. */
+
+static t_Error DtsecEnable(t_Handle h_Dtsec, e_CommMode mode)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ fman_dtsec_enable(p_Dtsec->p_MemMap,
+ (bool)!!(mode & e_COMM_MODE_RX),
+ (bool)!!(mode & e_COMM_MODE_TX));
+
+ GracefulRestart(p_Dtsec, mode);
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecDisable (t_Handle h_Dtsec, e_CommMode mode)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ GracefulStop(p_Dtsec, mode);
+
+ fman_dtsec_disable(p_Dtsec->p_MemMap,
+ (bool)!!(mode & e_COMM_MODE_RX),
+ (bool)!!(mode & e_COMM_MODE_TX));
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecSetTxPauseFrames(t_Handle h_Dtsec,
+ uint8_t priority,
+ uint16_t pauseTime,
+ uint16_t threshTime)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ UNUSED(priority);UNUSED(threshTime);
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+#ifdef FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003
+ if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2)
+ if (0 < pauseTime && pauseTime <= 320)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE,
+ ("This pause-time value of %d is illegal due to errata dTSEC-A003!"
+ " value should be greater than 320."));
+#endif /* FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 */
+
+ fman_dtsec_set_tx_pause_frames(p_Dtsec->p_MemMap, pauseTime);
+ return E_OK;
+}
+
+/* .............................................................................. */
+/* backward compatibility. will be removed in the future. */
+static t_Error DtsecTxMacPause(t_Handle h_Dtsec, uint16_t pauseTime)
+{
+ return DtsecSetTxPauseFrames(h_Dtsec, 0, pauseTime, 0);
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecRxIgnoreMacPause(t_Handle h_Dtsec, bool en)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ bool accept_pause = !en;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ fman_dtsec_handle_rx_pause(p_Dtsec->p_MemMap, accept_pause);
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecEnable1588TimeStamp(t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ p_Dtsec->ptpTsuEnabled = TRUE;
+ fman_dtsec_set_ts(p_Dtsec->p_MemMap, TRUE);
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecDisable1588TimeStamp(t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ p_Dtsec->ptpTsuEnabled = FALSE;
+ fman_dtsec_set_ts(p_Dtsec->p_MemMap, FALSE);
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecGetStatistics(t_Handle h_Dtsec, t_FmMacStatistics *p_Statistics)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ struct dtsec_regs *p_DtsecMemMap;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_Statistics, E_NULL_POINTER);
+
+ p_DtsecMemMap = p_Dtsec->p_MemMap;
+
+ if (p_Dtsec->statisticsLevel == e_FM_MAC_NONE_STATISTICS)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Statistics disabled"));
+
+ memset(p_Statistics, 0xff, sizeof(t_FmMacStatistics));
+
+ if (p_Dtsec->statisticsLevel == e_FM_MAC_FULL_STATISTICS)
+ {
+ p_Statistics->eStatPkts64 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR64)
+ + p_Dtsec->internalStatistics.tr64;
+ p_Statistics->eStatPkts65to127 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR127)
+ + p_Dtsec->internalStatistics.tr127;
+ p_Statistics->eStatPkts128to255 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR255)
+ + p_Dtsec->internalStatistics.tr255;
+ p_Statistics->eStatPkts256to511 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR511)
+ + p_Dtsec->internalStatistics.tr511;
+ p_Statistics->eStatPkts512to1023 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR1K)
+ + p_Dtsec->internalStatistics.tr1k;
+ p_Statistics->eStatPkts1024to1518 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TRMAX)
+ + p_Dtsec->internalStatistics.trmax;
+ p_Statistics->eStatPkts1519to1522 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TRMGV)
+ + p_Dtsec->internalStatistics.trmgv;
+
+ /* MIB II */
+ p_Statistics->ifInOctets = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RBYT)
+ + p_Dtsec->internalStatistics.rbyt;
+ p_Statistics->ifInPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RPKT)
+ + p_Dtsec->internalStatistics.rpkt;
+ p_Statistics->ifInUcastPkts = 0;
+ p_Statistics->ifInMcastPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RMCA)
+ + p_Dtsec->internalStatistics.rmca;
+ p_Statistics->ifInBcastPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RBCA)
+ + p_Dtsec->internalStatistics.rbca;
+ p_Statistics->ifOutOctets = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TBYT)
+ + p_Dtsec->internalStatistics.tbyt;
+ p_Statistics->ifOutPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TPKT)
+ + p_Dtsec->internalStatistics.tpkt;
+ p_Statistics->ifOutUcastPkts = 0;
+ p_Statistics->ifOutMcastPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TMCA)
+ + p_Dtsec->internalStatistics.tmca;
+ p_Statistics->ifOutBcastPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TBCA)
+ + p_Dtsec->internalStatistics.tbca;
+ }
+
+ p_Statistics->eStatFragments = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RFRG)
+ + p_Dtsec->internalStatistics.rfrg;
+ p_Statistics->eStatJabbers = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RJBR)
+ + p_Dtsec->internalStatistics.rjbr;
+ p_Statistics->eStatsDropEvents = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RDRP)
+ + p_Dtsec->internalStatistics.rdrp;
+ p_Statistics->eStatCRCAlignErrors = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RALN)
+ + p_Dtsec->internalStatistics.raln;
+ p_Statistics->eStatUndersizePkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RUND)
+ + p_Dtsec->internalStatistics.rund;
+ p_Statistics->eStatOversizePkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_ROVR)
+ + p_Dtsec->internalStatistics.rovr;
+ p_Statistics->reStatPause = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RXPF)
+ + p_Dtsec->internalStatistics.rxpf;
+ p_Statistics->teStatPause = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TXPF)
+ + p_Dtsec->internalStatistics.txpf;
+ p_Statistics->ifInDiscards = p_Statistics->eStatsDropEvents;
+ p_Statistics->ifInErrors = p_Statistics->eStatsDropEvents + p_Statistics->eStatCRCAlignErrors
+ + fman_dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_RFLR) + p_Dtsec->internalStatistics.rflr
+ + fman_dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_RCDE) + p_Dtsec->internalStatistics.rcde
+ + fman_dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_RCSE) + p_Dtsec->internalStatistics.rcse;
+
+ p_Statistics->ifOutDiscards = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TDRP)
+ + p_Dtsec->internalStatistics.tdrp;
+ p_Statistics->ifOutErrors = p_Statistics->ifOutDiscards /**< Number of frames transmitted with error: */
+ + fman_dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_TFCS)
+ + p_Dtsec->internalStatistics.tfcs;
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecModifyMacAddress (t_Handle h_Dtsec, t_EnetAddr *p_EnetAddr)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ /* Initialize MAC Station Address registers (1 & 2) */
+ /* Station address have to be swapped (big endian to little endian */
+ p_Dtsec->addr = ENET_ADDR_TO_UINT64(*p_EnetAddr);
+ fman_dtsec_set_mac_address(p_Dtsec->p_MemMap, (uint8_t *)(*p_EnetAddr));
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecResetCounters (t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ /* clear HW counters */
+ fman_dtsec_reset_stat(p_Dtsec->p_MemMap);
+
+ /* clear SW counters holding carries */
+ memset(&p_Dtsec->internalStatistics, 0, sizeof(t_InternalStatistics));
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecAddExactMatchMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *) h_Dtsec;
+ uint64_t ethAddr;
+ uint8_t paddrNum;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
+
+ if (ethAddr & GROUP_ADDRESS)
+ /* Multicast address has no effect in PADDR */
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Multicast address"));
+
+ /* Make sure no PADDR contains this address */
+ for (paddrNum = 0; paddrNum < DTSEC_NUM_OF_PADDRS; paddrNum++)
+ if (p_Dtsec->indAddrRegUsed[paddrNum])
+ if (p_Dtsec->paddr[paddrNum] == ethAddr)
+ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG);
+
+ /* Find first unused PADDR */
+ for (paddrNum = 0; paddrNum < DTSEC_NUM_OF_PADDRS; paddrNum++)
+ if (!(p_Dtsec->indAddrRegUsed[paddrNum]))
+ {
+ /* mark this PADDR as used */
+ p_Dtsec->indAddrRegUsed[paddrNum] = TRUE;
+ /* store address */
+ p_Dtsec->paddr[paddrNum] = ethAddr;
+
+ /* put in hardware */
+ fman_dtsec_add_addr_in_paddr(p_Dtsec->p_MemMap, (uint64_t)PTR_TO_UINT(&ethAddr), paddrNum);
+ p_Dtsec->numOfIndAddrInRegs++;
+
+ return E_OK;
+ }
+
+ /* No free PADDR */
+ RETURN_ERROR(MAJOR, E_FULL, NO_MSG);
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecDelExactMatchMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *) h_Dtsec;
+ uint64_t ethAddr;
+ uint8_t paddrNum;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
+
+ /* Find used PADDR containing this address */
+ for (paddrNum = 0; paddrNum < DTSEC_NUM_OF_PADDRS; paddrNum++)
+ {
+ if ((p_Dtsec->indAddrRegUsed[paddrNum]) &&
+ (p_Dtsec->paddr[paddrNum] == ethAddr))
+ {
+ /* mark this PADDR as not used */
+ p_Dtsec->indAddrRegUsed[paddrNum] = FALSE;
+ /* clear in hardware */
+ fman_dtsec_clear_addr_in_paddr(p_Dtsec->p_MemMap, paddrNum);
+ p_Dtsec->numOfIndAddrInRegs--;
+
+ return E_OK;
+ }
+ }
+
+ RETURN_ERROR(MAJOR, E_NOT_FOUND, NO_MSG);
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecAddHashMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ t_EthHashEntry *p_HashEntry;
+ uint64_t ethAddr;
+ int32_t bucket;
+ uint32_t crc;
+ bool mcast, ghtx;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
+
+ ghtx = (bool)((fman_dtsec_get_rctrl(p_Dtsec->p_MemMap) & RCTRL_GHTX) ? TRUE : FALSE);
+ mcast = (bool)((ethAddr & MAC_GROUP_ADDRESS) ? TRUE : FALSE);
+
+ if (ghtx && !mcast) /* Cannot handle unicast mac addr when GHTX is on */
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Could not compute hash bucket"));
+
+ crc = GetMacAddrHashCode(ethAddr);
+
+ /* considering the 9 highest order bits in crc H[8:0]:
+ * if ghtx = 0 H[8:6] (highest order 3 bits) identify the hash register
+ * and H[5:1] (next 5 bits) identify the hash bit
+ * if ghts = 1 H[8:5] (highest order 4 bits) identify the hash register
+ * and H[4:0] (next 5 bits) identify the hash bit.
+ *
+ * In bucket index output the low 5 bits identify the hash register bit,
+ * while the higher 4 bits identify the hash register
+ */
+
+ if (ghtx)
+ bucket = (int32_t)((crc >> 23) & 0x1ff);
+ else {
+ bucket = (int32_t)((crc >> 24) & 0xff);
+ /* if !ghtx and mcast the bit must be set in gaddr instead of igaddr. */
+ if (mcast)
+ bucket += 0x100;
+ }
+
+ fman_dtsec_set_bucket(p_Dtsec->p_MemMap, bucket, TRUE);
+
+ /* Create element to be added to the driver hash table */
+ p_HashEntry = (t_EthHashEntry *)XX_Malloc(sizeof(t_EthHashEntry));
+ p_HashEntry->addr = ethAddr;
+ INIT_LIST(&p_HashEntry->node);
+
+ if (ethAddr & MAC_GROUP_ADDRESS)
+ /* Group Address */
+ LIST_AddToTail(&(p_HashEntry->node), &(p_Dtsec->p_MulticastAddrHash->p_Lsts[bucket]));
+ else
+ LIST_AddToTail(&(p_HashEntry->node), &(p_Dtsec->p_UnicastAddrHash->p_Lsts[bucket]));
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecDelHashMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ t_List *p_Pos;
+ t_EthHashEntry *p_HashEntry = NULL;
+ uint64_t ethAddr;
+ int32_t bucket;
+ uint32_t crc;
+ bool mcast, ghtx;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
+
+ ghtx = (bool)((fman_dtsec_get_rctrl(p_Dtsec->p_MemMap) & RCTRL_GHTX) ? TRUE : FALSE);
+ mcast = (bool)((ethAddr & MAC_GROUP_ADDRESS) ? TRUE : FALSE);
+
+ if (ghtx && !mcast) /* Cannot handle unicast mac addr when GHTX is on */
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Could not compute hash bucket"));
+
+ crc = GetMacAddrHashCode(ethAddr);
+
+ if (ghtx)
+ bucket = (int32_t)((crc >> 23) & 0x1ff);
+ else {
+ bucket = (int32_t)((crc >> 24) & 0xff);
+ /* if !ghtx and mcast the bit must be set in gaddr instead of igaddr. */
+ if (mcast)
+ bucket += 0x100;
+ }
+
+ if (ethAddr & MAC_GROUP_ADDRESS)
+ {
+ /* Group Address */
+ LIST_FOR_EACH(p_Pos, &(p_Dtsec->p_MulticastAddrHash->p_Lsts[bucket]))
+ {
+ p_HashEntry = ETH_HASH_ENTRY_OBJ(p_Pos);
+ if (p_HashEntry->addr == ethAddr)
+ {
+ LIST_DelAndInit(&p_HashEntry->node);
+ XX_Free(p_HashEntry);
+ break;
+ }
+ }
+ if (LIST_IsEmpty(&p_Dtsec->p_MulticastAddrHash->p_Lsts[bucket]))
+ fman_dtsec_set_bucket(p_Dtsec->p_MemMap, bucket, FALSE);
+ }
+ else
+ {
+ /* Individual Address */
+ LIST_FOR_EACH(p_Pos, &(p_Dtsec->p_UnicastAddrHash->p_Lsts[bucket]))
+ {
+ p_HashEntry = ETH_HASH_ENTRY_OBJ(p_Pos);
+ if (p_HashEntry->addr == ethAddr)
+ {
+ LIST_DelAndInit(&p_HashEntry->node);
+ XX_Free(p_HashEntry);
+ break;
+ }
+ }
+ if (LIST_IsEmpty(&p_Dtsec->p_UnicastAddrHash->p_Lsts[bucket]))
+ fman_dtsec_set_bucket(p_Dtsec->p_MemMap, bucket, FALSE);
+ }
+
+ /* address does not exist */
+ ASSERT_COND(p_HashEntry != NULL);
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecSetPromiscuous(t_Handle h_Dtsec, bool newVal)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ fman_dtsec_set_uc_promisc(p_Dtsec->p_MemMap, newVal);
+ fman_dtsec_set_mc_promisc(p_Dtsec->p_MemMap, newVal);
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecSetStatistics(t_Handle h_Dtsec, e_FmMacStatisticsLevel statisticsLevel)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ p_Dtsec->statisticsLevel = statisticsLevel;
+
+ err = (t_Error)fman_dtsec_set_stat_level(p_Dtsec->p_MemMap,
+ (enum dtsec_stat_level)statisticsLevel);
+ if (err != E_OK)
+ return err;
+
+ switch (statisticsLevel)
+ {
+ case (e_FM_MAC_NONE_STATISTICS):
+ p_Dtsec->exceptions &= ~DTSEC_IMASK_MSROEN;
+ break;
+ case (e_FM_MAC_PARTIAL_STATISTICS):
+ p_Dtsec->exceptions |= DTSEC_IMASK_MSROEN;
+ break;
+ case (e_FM_MAC_FULL_STATISTICS):
+ p_Dtsec->exceptions |= DTSEC_IMASK_MSROEN;
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, NO_MSG);
+ }
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecSetWakeOnLan(t_Handle h_Dtsec, bool en)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ fman_dtsec_set_wol(p_Dtsec->p_MemMap, en);
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecAdjustLink(t_Handle h_Dtsec, e_EnetSpeed speed, bool fullDuplex)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ t_Error err;
+ enum enet_interface enet_interface;
+ enum enet_speed enet_speed;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ p_Dtsec->enetMode = MAKE_ENET_MODE(ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode), speed);
+ enet_interface = (enum enet_interface) ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode);
+ enet_speed = (enum enet_speed) ENET_SPEED_FROM_MODE(p_Dtsec->enetMode);
+ p_Dtsec->halfDuplex = !fullDuplex;
+
+ err = (t_Error)fman_dtsec_adjust_link(p_Dtsec->p_MemMap, enet_interface, enet_speed, fullDuplex);
+
+ if (err == E_CONFLICT)
+ RETURN_ERROR(MAJOR, E_CONFLICT, ("Ethernet interface does not support Half Duplex mode"));
+
+ return err;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecRestartAutoneg(t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ uint16_t tmpReg16;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ DTSEC_MII_ReadPhyReg(p_Dtsec, p_Dtsec->tbi_phy_addr, 0, &tmpReg16);
+
+ tmpReg16 &= ~( PHY_CR_SPEED0 | PHY_CR_SPEED1 );
+ tmpReg16 |= (PHY_CR_ANE | PHY_CR_RESET_AN | PHY_CR_FULLDUPLEX | PHY_CR_SPEED1);
+
+ DTSEC_MII_WritePhyReg(p_Dtsec, p_Dtsec->tbi_phy_addr, 0, tmpReg16);
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecGetId(t_Handle h_Dtsec, uint32_t *macId)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ *macId = p_Dtsec->macId;
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecGetVersion(t_Handle h_Dtsec, uint32_t *macVersion)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ *macVersion = fman_dtsec_get_revision(p_Dtsec->p_MemMap);
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error DtsecSetException(t_Handle h_Dtsec, e_FmMacExceptions exception, bool enable)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ uint32_t bitMask = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+
+ if (exception != e_FM_MAC_EX_1G_1588_TS_RX_ERR)
+ {
+ GET_EXCEPTION_FLAG(bitMask, exception);
+ if (bitMask)
+ {
+ if (enable)
+ p_Dtsec->exceptions |= bitMask;
+ else
+ p_Dtsec->exceptions &= ~bitMask;
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
+
+ if (enable)
+ fman_dtsec_enable_interrupt(p_Dtsec->p_MemMap, bitMask);
+ else
+ fman_dtsec_disable_interrupt(p_Dtsec->p_MemMap, bitMask);
+ }
+ else
+ {
+ if (!p_Dtsec->ptpTsuEnabled)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exception valid for 1588 only"));
+ switch (exception)
+ {
+ case (e_FM_MAC_EX_1G_1588_TS_RX_ERR):
+ if (enable)
+ {
+ p_Dtsec->enTsuErrExeption = TRUE;
+ fman_dtsec_enable_tmr_interrupt(p_Dtsec->p_MemMap);
+ } else {
+ p_Dtsec->enTsuErrExeption = FALSE;
+ fman_dtsec_disable_tmr_interrupt(p_Dtsec->p_MemMap);
+ }
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
+ }
+ }
+
+ return E_OK;
+}
+
+/* ........................................................................... */
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+static t_Error DtsecDumpRegs(t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ int i = 0;
+
+ DECLARE_DUMP;
+
+ if (p_Dtsec->p_MemMap)
+ {
+ DUMP_TITLE(p_Dtsec->p_MemMap, ("dTSEC %d: ", p_Dtsec->macId));
+ DUMP_VAR(p_Dtsec->p_MemMap, tsec_id);
+ DUMP_VAR(p_Dtsec->p_MemMap, tsec_id2);
+ DUMP_VAR(p_Dtsec->p_MemMap, ievent);
+ DUMP_VAR(p_Dtsec->p_MemMap, imask);
+ DUMP_VAR(p_Dtsec->p_MemMap, ecntrl);
+ DUMP_VAR(p_Dtsec->p_MemMap, ptv);
+ DUMP_VAR(p_Dtsec->p_MemMap, tmr_ctrl);
+ DUMP_VAR(p_Dtsec->p_MemMap, tmr_pevent);
+ DUMP_VAR(p_Dtsec->p_MemMap, tmr_pemask);
+ DUMP_VAR(p_Dtsec->p_MemMap, tctrl);
+ DUMP_VAR(p_Dtsec->p_MemMap, rctrl);
+ DUMP_VAR(p_Dtsec->p_MemMap, maccfg1);
+ DUMP_VAR(p_Dtsec->p_MemMap, maccfg2);
+ DUMP_VAR(p_Dtsec->p_MemMap, ipgifg);
+ DUMP_VAR(p_Dtsec->p_MemMap, hafdup);
+ DUMP_VAR(p_Dtsec->p_MemMap, maxfrm);
+
+ DUMP_VAR(p_Dtsec->p_MemMap, macstnaddr1);
+ DUMP_VAR(p_Dtsec->p_MemMap, macstnaddr2);
+
+ DUMP_SUBSTRUCT_ARRAY(i, 8)
+ {
+ DUMP_VAR(p_Dtsec->p_MemMap, macaddr[i].exact_match1);
+ DUMP_VAR(p_Dtsec->p_MemMap, macaddr[i].exact_match2);
+ }
+ DUMP_VAR(p_Dtsec->p_MemMap, car1);
+ DUMP_VAR(p_Dtsec->p_MemMap, car2);
+ }
+
+ return E_OK;
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+
+/*****************************************************************************/
+/* dTSEC Init & Free API */
+/*****************************************************************************/
+
+/* .............................................................................. */
+
+static t_Error DtsecInit(t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ struct dtsec_cfg *p_DtsecDriverParam;
+ t_Error err;
+ uint16_t maxFrmLn;
+ enum enet_interface enet_interface;
+ enum enet_speed enet_speed;
+ t_EnetAddr ethAddr;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec->fmMacControllerDriver.h_Fm, E_INVALID_HANDLE);
+
+ FM_GetRevision(p_Dtsec->fmMacControllerDriver.h_Fm, &p_Dtsec->fmMacControllerDriver.fmRevInfo);
+ CHECK_INIT_PARAMETERS(p_Dtsec, CheckInitParameters);
+
+ p_DtsecDriverParam = p_Dtsec->p_DtsecDriverParam;
+ p_Dtsec->halfDuplex = p_DtsecDriverParam->halfdup_on;
+
+ enet_interface = (enum enet_interface)ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode);
+ enet_speed = (enum enet_speed)ENET_SPEED_FROM_MODE(p_Dtsec->enetMode);
+ MAKE_ENET_ADDR_FROM_UINT64(p_Dtsec->addr, ethAddr);
+
+ err = (t_Error)fman_dtsec_init(p_Dtsec->p_MemMap,
+ p_DtsecDriverParam,
+ enet_interface,
+ enet_speed,
+ (uint8_t*)ethAddr,
+ p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev,
+ p_Dtsec->fmMacControllerDriver.fmRevInfo.minorRev,
+ p_Dtsec->exceptions);
+ if (err)
+ {
+ FreeInitResources(p_Dtsec);
+ RETURN_ERROR(MAJOR, err, ("This DTSEC version does not support the required i/f mode"));
+ }
+
+ if (ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode) == e_ENET_IF_SGMII)
+ {
+ uint16_t tmpReg16;
+
+ /* Configure the TBI PHY Control Register */
+ tmpReg16 = PHY_TBICON_CLK_SEL | PHY_TBICON_SRESET;
+ DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 17, tmpReg16);
+
+ tmpReg16 = PHY_TBICON_CLK_SEL;
+ DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 17, tmpReg16);
+
+ tmpReg16 = (PHY_CR_PHY_RESET | PHY_CR_ANE | PHY_CR_FULLDUPLEX | PHY_CR_SPEED1);
+ DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 0, tmpReg16);
+
+ if (p_Dtsec->enetMode & ENET_IF_SGMII_BASEX)
+ tmpReg16 = PHY_TBIANA_1000X;
+ else
+ tmpReg16 = PHY_TBIANA_SGMII;
+ DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 4, tmpReg16);
+
+ tmpReg16 = (PHY_CR_ANE | PHY_CR_RESET_AN | PHY_CR_FULLDUPLEX | PHY_CR_SPEED1);
+
+ DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 0, tmpReg16);
+ }
+
+ /* Max Frame Length */
+ maxFrmLn = fman_dtsec_get_max_frame_len(p_Dtsec->p_MemMap);
+ err = FmSetMacMaxFrame(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MAC_1G,
+ p_Dtsec->fmMacControllerDriver.macId, maxFrmLn);
+
+ p_Dtsec->p_MulticastAddrHash = AllocHashTable(EXTENDED_HASH_TABLE_SIZE);
+ if (!p_Dtsec->p_MulticastAddrHash) {
+ FreeInitResources(p_Dtsec);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MC hash table is FAILED"));
+ }
+
+ p_Dtsec->p_UnicastAddrHash = AllocHashTable(HASH_TABLE_SIZE);
+ if (!p_Dtsec->p_UnicastAddrHash)
+ {
+ FreeInitResources(p_Dtsec);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("UC hash table is FAILED"));
+ }
+
+ /* register err intr handler for dtsec to FPM (err)*/
+ FmRegisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm,
+ e_FM_MOD_1G_MAC,
+ p_Dtsec->macId,
+ e_FM_INTR_TYPE_ERR,
+ DtsecIsr,
+ p_Dtsec);
+ /* register 1588 intr handler for TMR to FPM (normal)*/
+ FmRegisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm,
+ e_FM_MOD_1G_MAC,
+ p_Dtsec->macId,
+ e_FM_INTR_TYPE_NORMAL,
+ Dtsec1588Isr,
+ p_Dtsec);
+ /* register normal intr handler for dtsec to main interrupt controller. */
+ if (p_Dtsec->mdioIrq != NO_IRQ)
+ {
+ XX_SetIntr(p_Dtsec->mdioIrq, DtsecMdioIsr, p_Dtsec);
+ XX_EnableIntr(p_Dtsec->mdioIrq);
+ }
+
+ XX_Free(p_DtsecDriverParam);
+ p_Dtsec->p_DtsecDriverParam = NULL;
+
+ err = DtsecSetStatistics(h_Dtsec, e_FM_MAC_FULL_STATISTICS);
+ if (err)
+ {
+ FreeInitResources(p_Dtsec);
+ RETURN_ERROR(MAJOR, err, ("Undefined statistics level"));
+ }
+
+ return E_OK;
+}
+
+/* ........................................................................... */
+
+static t_Error DtsecFree(t_Handle h_Dtsec)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+
+ FreeInitResources(p_Dtsec);
+
+ if (p_Dtsec->p_DtsecDriverParam)
+ {
+ XX_Free(p_Dtsec->p_DtsecDriverParam);
+ p_Dtsec->p_DtsecDriverParam = NULL;
+ }
+ XX_Free (h_Dtsec);
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static void InitFmMacControllerDriver(t_FmMacControllerDriver *p_FmMacControllerDriver)
+{
+ p_FmMacControllerDriver->f_FM_MAC_Init = DtsecInit;
+ p_FmMacControllerDriver->f_FM_MAC_Free = DtsecFree;
+
+ p_FmMacControllerDriver->f_FM_MAC_SetStatistics = DtsecSetStatistics;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback = DtsecConfigLoopback;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength = DtsecConfigMaxFrameLength;
+
+ p_FmMacControllerDriver->f_FM_MAC_ConfigWan = NULL; /* Not supported on dTSEC */
+
+ p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc = DtsecConfigPadAndCrc;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex = DtsecConfigHalfDuplex;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck = DtsecConfigLengthCheck;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigTbiPhyAddr = DtsecConfigTbiPhyAddr;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigException = DtsecConfigException;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit = NULL;
+
+ p_FmMacControllerDriver->f_FM_MAC_Enable = DtsecEnable;
+ p_FmMacControllerDriver->f_FM_MAC_Disable = DtsecDisable;
+
+ p_FmMacControllerDriver->f_FM_MAC_SetException = DtsecSetException;
+
+ p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous = DtsecSetPromiscuous;
+ p_FmMacControllerDriver->f_FM_MAC_AdjustLink = DtsecAdjustLink;
+ p_FmMacControllerDriver->f_FM_MAC_SetWakeOnLan = DtsecSetWakeOnLan;
+ p_FmMacControllerDriver->f_FM_MAC_RestartAutoneg = DtsecRestartAutoneg;
+
+ p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp = DtsecEnable1588TimeStamp;
+ p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp = DtsecDisable1588TimeStamp;
+
+ p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames = DtsecTxMacPause;
+ p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames = DtsecSetTxPauseFrames;
+ p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames = DtsecRxIgnoreMacPause;
+
+ p_FmMacControllerDriver->f_FM_MAC_ResetCounters = DtsecResetCounters;
+ p_FmMacControllerDriver->f_FM_MAC_GetStatistics = DtsecGetStatistics;
+
+ p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr = DtsecModifyMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr = DtsecAddHashMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr = DtsecDelHashMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr = DtsecAddExactMatchMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr = DtsecDelExactMatchMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_GetId = DtsecGetId;
+ p_FmMacControllerDriver->f_FM_MAC_GetVersion = DtsecGetVersion;
+ p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength = DtsecGetMaxFrameLength;
+
+ p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg = DTSEC_MII_WritePhyReg;
+ p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg = DTSEC_MII_ReadPhyReg;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ p_FmMacControllerDriver->f_FM_MAC_DumpRegs = DtsecDumpRegs;
+#endif /* (defined(DEBUG_ERRORS) && ... */
+}
+
+
+/*****************************************************************************/
+/* dTSEC Config Main Entry */
+/*****************************************************************************/
+
+/* .............................................................................. */
+
+t_Handle DTSEC_Config(t_FmMacParams *p_FmMacParam)
+{
+ t_Dtsec *p_Dtsec;
+ struct dtsec_cfg *p_DtsecDriverParam;
+ uintptr_t baseAddr;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmMacParam, E_NULL_POINTER, NULL);
+
+ baseAddr = p_FmMacParam->baseAddr;
+
+ /* allocate memory for the UCC GETH data structure. */
+ p_Dtsec = (t_Dtsec *)XX_Malloc(sizeof(t_Dtsec));
+ if (!p_Dtsec)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("dTSEC driver structure"));
+ return NULL;
+ }
+ memset(p_Dtsec, 0, sizeof(t_Dtsec));
+ InitFmMacControllerDriver(&p_Dtsec->fmMacControllerDriver);
+
+ /* allocate memory for the dTSEC driver parameters data structure. */
+ p_DtsecDriverParam = (struct dtsec_cfg *) XX_Malloc(sizeof(struct dtsec_cfg));
+ if (!p_DtsecDriverParam)
+ {
+ XX_Free(p_Dtsec);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("dTSEC driver parameters"));
+ return NULL;
+ }
+ memset(p_DtsecDriverParam, 0, sizeof(struct dtsec_cfg));
+
+ /* Plant parameter structure pointer */
+ p_Dtsec->p_DtsecDriverParam = p_DtsecDriverParam;
+
+ fman_dtsec_defconfig(p_DtsecDriverParam);
+
+ p_Dtsec->p_MemMap = (struct dtsec_regs *)UINT_TO_PTR(baseAddr);
+ p_Dtsec->p_MiiMemMap = (struct dtsec_mii_reg *)UINT_TO_PTR(baseAddr + DTSEC_TO_MII_OFFSET);
+ p_Dtsec->addr = ENET_ADDR_TO_UINT64(p_FmMacParam->addr);
+ p_Dtsec->enetMode = p_FmMacParam->enetMode;
+ p_Dtsec->macId = p_FmMacParam->macId;
+ p_Dtsec->exceptions = DEFAULT_exceptions;
+ p_Dtsec->mdioIrq = p_FmMacParam->mdioIrq;
+ p_Dtsec->f_Exception = p_FmMacParam->f_Exception;
+ p_Dtsec->f_Event = p_FmMacParam->f_Event;
+ p_Dtsec->h_App = p_FmMacParam->h_App;
+ p_Dtsec->ptpTsuEnabled = p_Dtsec->p_DtsecDriverParam->ptp_tsu_en;
+ p_Dtsec->enTsuErrExeption = p_Dtsec->p_DtsecDriverParam->ptp_exception_en;
+ p_Dtsec->tbi_phy_addr = p_Dtsec->p_DtsecDriverParam->tbi_phy_addr;
+
+ return p_Dtsec;
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec.h
new file mode 100644
index 0000000..c26f40c
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec.h
@@ -0,0 +1,228 @@
+/*
+ * Copyright 2008-2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/******************************************************************************
+ @File dtsec.h
+
+ @Description FM dTSEC ...
+*//***************************************************************************/
+#ifndef __DTSEC_H
+#define __DTSEC_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "list_ext.h"
+#include "enet_ext.h"
+
+#include "dtsec_mii_acc.h"
+#include "fm_mac.h"
+
+
+#define DEFAULT_exceptions \
+ ((uint32_t)(DTSEC_IMASK_BREN | \
+ DTSEC_IMASK_RXCEN | \
+ DTSEC_IMASK_BTEN | \
+ DTSEC_IMASK_TXCEN | \
+ DTSEC_IMASK_TXEEN | \
+ DTSEC_IMASK_ABRTEN | \
+ DTSEC_IMASK_LCEN | \
+ DTSEC_IMASK_CRLEN | \
+ DTSEC_IMASK_XFUNEN | \
+ DTSEC_IMASK_IFERREN | \
+ DTSEC_IMASK_MAGEN | \
+ DTSEC_IMASK_TDPEEN | \
+ DTSEC_IMASK_RDPEEN))
+
+#define GET_EXCEPTION_FLAG(bitMask, exception) switch (exception){ \
+ case e_FM_MAC_EX_1G_BAB_RX: \
+ bitMask = DTSEC_IMASK_BREN; break; \
+ case e_FM_MAC_EX_1G_RX_CTL: \
+ bitMask = DTSEC_IMASK_RXCEN; break; \
+ case e_FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET: \
+ bitMask = DTSEC_IMASK_GTSCEN ; break; \
+ case e_FM_MAC_EX_1G_BAB_TX: \
+ bitMask = DTSEC_IMASK_BTEN ; break; \
+ case e_FM_MAC_EX_1G_TX_CTL: \
+ bitMask = DTSEC_IMASK_TXCEN ; break; \
+ case e_FM_MAC_EX_1G_TX_ERR: \
+ bitMask = DTSEC_IMASK_TXEEN ; break; \
+ case e_FM_MAC_EX_1G_LATE_COL: \
+ bitMask = DTSEC_IMASK_LCEN ; break; \
+ case e_FM_MAC_EX_1G_COL_RET_LMT: \
+ bitMask = DTSEC_IMASK_CRLEN ; break; \
+ case e_FM_MAC_EX_1G_TX_FIFO_UNDRN: \
+ bitMask = DTSEC_IMASK_XFUNEN ; break; \
+ case e_FM_MAC_EX_1G_MAG_PCKT: \
+ bitMask = DTSEC_IMASK_MAGEN ; break; \
+ case e_FM_MAC_EX_1G_MII_MNG_RD_COMPLET: \
+ bitMask = DTSEC_IMASK_MMRDEN; break; \
+ case e_FM_MAC_EX_1G_MII_MNG_WR_COMPLET: \
+ bitMask = DTSEC_IMASK_MMWREN ; break; \
+ case e_FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET: \
+ bitMask = DTSEC_IMASK_GRSCEN; break; \
+ case e_FM_MAC_EX_1G_TX_DATA_ERR: \
+ bitMask = DTSEC_IMASK_TDPEEN; break; \
+ case e_FM_MAC_EX_1G_RX_MIB_CNT_OVFL: \
+ bitMask = DTSEC_IMASK_MSROEN ; break; \
+ default: bitMask = 0;break;}
+
+
+#define MAX_PACKET_ALIGNMENT 31
+#define MAX_INTER_PACKET_GAP 0x7f
+#define MAX_INTER_PALTERNATE_BEB 0x0f
+#define MAX_RETRANSMISSION 0x0f
+#define MAX_COLLISION_WINDOW 0x03ff
+
+
+/********************* From mac ext ******************************************/
+typedef uint32_t t_ErrorDisable;
+
+#define ERROR_DISABLE_TRANSMIT 0x00400000
+#define ERROR_DISABLE_LATE_COLLISION 0x00040000
+#define ERROR_DISABLE_COLLISION_RETRY_LIMIT 0x00020000
+#define ERROR_DISABLE_TxFIFO_UNDERRUN 0x00010000
+#define ERROR_DISABLE_TxABORT 0x00008000
+#define ERROR_DISABLE_INTERFACE 0x00004000
+#define ERROR_DISABLE_TxDATA_PARITY 0x00000002
+#define ERROR_DISABLE_RxDATA_PARITY 0x00000001
+
+/*****************************************************************************/
+#define DTSEC_NUM_OF_PADDRS 15 /* number of pattern match registers (entries) */
+
+#define GROUP_ADDRESS 0x0000010000000000LL /* Group address bit indication */
+
+#define HASH_TABLE_SIZE 256 /* Hash table size (= 32 bits * 8 regs) */
+
+#define HASH_TABLE_SIZE 256 /* Hash table size (32 bits * 8 regs) */
+#define EXTENDED_HASH_TABLE_SIZE 512 /* Extended Hash table size (32 bits * 16 regs) */
+
+#define DTSEC_TO_MII_OFFSET 0x1000 /* number of pattern match registers (entries) */
+
+#define MAX_PHYS 32 /* maximum number of phys */
+
+#define VAL32BIT 0x100000000LL
+#define VAL22BIT 0x00400000
+#define VAL16BIT 0x00010000
+#define VAL12BIT 0x00001000
+
+/* CAR1/2 bits */
+#define CAR1_TR64 0x80000000
+#define CAR1_TR127 0x40000000
+#define CAR1_TR255 0x20000000
+#define CAR1_TR511 0x10000000
+#define CAR1_TRK1 0x08000000
+#define CAR1_TRMAX 0x04000000
+#define CAR1_TRMGV 0x02000000
+
+#define CAR1_RBYT 0x00010000
+#define CAR1_RPKT 0x00008000
+#define CAR1_RMCA 0x00002000
+#define CAR1_RBCA 0x00001000
+#define CAR1_RXPF 0x00000400
+#define CAR1_RALN 0x00000100
+#define CAR1_RFLR 0x00000080
+#define CAR1_RCDE 0x00000040
+#define CAR1_RCSE 0x00000020
+#define CAR1_RUND 0x00000010
+#define CAR1_ROVR 0x00000008
+#define CAR1_RFRG 0x00000004
+#define CAR1_RJBR 0x00000002
+#define CAR1_RDRP 0x00000001
+
+#define CAR2_TFCS 0x00040000
+#define CAR2_TBYT 0x00002000
+#define CAR2_TPKT 0x00001000
+#define CAR2_TMCA 0x00000800
+#define CAR2_TBCA 0x00000400
+#define CAR2_TXPF 0x00000200
+#define CAR2_TDRP 0x00000001
+
+typedef struct t_InternalStatistics
+{
+ uint64_t tr64;
+ uint64_t tr127;
+ uint64_t tr255;
+ uint64_t tr511;
+ uint64_t tr1k;
+ uint64_t trmax;
+ uint64_t trmgv;
+ uint64_t rfrg;
+ uint64_t rjbr;
+ uint64_t rdrp;
+ uint64_t raln;
+ uint64_t rund;
+ uint64_t rovr;
+ uint64_t rxpf;
+ uint64_t txpf;
+ uint64_t rbyt;
+ uint64_t rpkt;
+ uint64_t rmca;
+ uint64_t rbca;
+ uint64_t rflr;
+ uint64_t rcde;
+ uint64_t rcse;
+ uint64_t tbyt;
+ uint64_t tpkt;
+ uint64_t tmca;
+ uint64_t tbca;
+ uint64_t tdrp;
+ uint64_t tfcs;
+} t_InternalStatistics;
+
+typedef struct {
+ t_FmMacControllerDriver fmMacControllerDriver;
+ t_Handle h_App; /**< Handle to the upper layer application */
+ struct dtsec_regs *p_MemMap; /**< pointer to dTSEC memory mapped registers. */
+ struct dtsec_mii_reg *p_MiiMemMap; /**< pointer to dTSEC MII memory mapped registers. */
+ uint64_t addr; /**< MAC address of device; */
+ e_EnetMode enetMode; /**< Ethernet physical interface */
+ t_FmMacExceptionCallback *f_Exception;
+ int mdioIrq;
+ t_FmMacExceptionCallback *f_Event;
+ bool indAddrRegUsed[DTSEC_NUM_OF_PADDRS]; /**< Whether a particular individual address recognition register is being used */
+ uint64_t paddr[DTSEC_NUM_OF_PADDRS]; /**< MAC address for particular individual address recognition register */
+ uint8_t numOfIndAddrInRegs; /**< Number of individual addresses in registers for this station. */
+ bool halfDuplex;
+ t_InternalStatistics internalStatistics;
+ t_EthHash *p_MulticastAddrHash; /* pointer to driver's global address hash table */
+ t_EthHash *p_UnicastAddrHash; /* pointer to driver's individual address hash table */
+ uint8_t macId;
+ uint8_t tbi_phy_addr;
+ uint32_t exceptions;
+ bool ptpTsuEnabled;
+ bool enTsuErrExeption;
+ e_FmMacStatisticsLevel statisticsLevel;
+ struct dtsec_cfg *p_DtsecDriverParam;
+} t_Dtsec;
+
+
+#endif /* __DTSEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec_mii_acc.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec_mii_acc.c
new file mode 100644
index 0000000..f9dff6f
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec_mii_acc.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2008-2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File dtsec_mii_acc.c
+
+ @Description FM dtsec MII register access MAC ...
+*//***************************************************************************/
+
+#include "error_ext.h"
+#include "std_ext.h"
+#include "fm_mac.h"
+#include "dtsec.h"
+#include "fsl_fman_dtsec_mii_acc.h"
+
+
+/*****************************************************************************/
+t_Error DTSEC_MII_WritePhyReg(t_Handle h_Dtsec,
+ uint8_t phyAddr,
+ uint8_t reg,
+ uint16_t data)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ struct dtsec_mii_reg *miiregs;
+ uint16_t dtsec_freq;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_MiiMemMap, E_INVALID_HANDLE);
+
+ dtsec_freq = (uint16_t)(p_Dtsec->fmMacControllerDriver.clkFreq >> 1);
+ miiregs = p_Dtsec->p_MiiMemMap;
+
+ err = (t_Error)fman_dtsec_mii_write_reg(miiregs, phyAddr, reg, data, dtsec_freq);
+
+ return err;
+}
+
+/*****************************************************************************/
+t_Error DTSEC_MII_ReadPhyReg(t_Handle h_Dtsec,
+ uint8_t phyAddr,
+ uint8_t reg,
+ uint16_t *p_Data)
+{
+ t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
+ struct dtsec_mii_reg *miiregs;
+ uint16_t dtsec_freq;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_MiiMemMap, E_INVALID_HANDLE);
+
+ dtsec_freq = (uint16_t)(p_Dtsec->fmMacControllerDriver.clkFreq >> 1);
+ miiregs = p_Dtsec->p_MiiMemMap;
+
+ err = (t_Error)fman_dtsec_mii_read_reg(miiregs, phyAddr, reg, p_Data, dtsec_freq);
+
+ if (*p_Data == 0xffff)
+ RETURN_ERROR(MINOR, E_NO_DEVICE,
+ ("Read wrong data (0xffff): phyAddr 0x%x, reg 0x%x",
+ phyAddr, reg));
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ return err;
+}
+
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec_mii_acc.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec_mii_acc.h
new file mode 100644
index 0000000..75cc658
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/dtsec_mii_acc.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2008-2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DTSEC_MII_ACC_H
+#define __DTSEC_MII_ACC_H
+
+#include "std_ext.h"
+
+
+t_Error DTSEC_MII_WritePhyReg(t_Handle h_Dtsec, uint8_t phyAddr, uint8_t reg, uint16_t data);
+t_Error DTSEC_MII_ReadPhyReg(t_Handle h_Dtsec, uint8_t phyAddr, uint8_t reg, uint16_t *p_Data);
+
+#endif /* __DTSEC_MII_ACC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fm_mac.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fm_mac.c
new file mode 100644
index 0000000..e992f1a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fm_mac.c
@@ -0,0 +1,642 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_mac.c
+
+ @Description FM MAC ...
+*//***************************************************************************/
+#include "std_ext.h"
+#include "string_ext.h"
+#include "sprint_ext.h"
+#include "error_ext.h"
+#include "fm_ext.h"
+
+#include "fm_common.h"
+#include "fm_mac.h"
+
+
+/* ......................................................................... */
+
+t_Handle FM_MAC_Config (t_FmMacParams *p_FmMacParam)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmMacParam, E_INVALID_HANDLE, NULL);
+
+#if (DPAA_VERSION == 10)
+ if (ENET_SPEED_FROM_MODE(p_FmMacParam->enetMode) < e_ENET_SPEED_10000)
+ p_FmMacControllerDriver = (t_FmMacControllerDriver *)DTSEC_Config(p_FmMacParam);
+ else
+#if FM_MAX_NUM_OF_10G_MACS > 0
+ p_FmMacControllerDriver = (t_FmMacControllerDriver *)TGEC_Config(p_FmMacParam);
+#else
+ p_FmMacControllerDriver = NULL;
+#endif /* FM_MAX_NUM_OF_10G_MACS > 0 */
+#else
+ p_FmMacControllerDriver = (t_FmMacControllerDriver *)MEMAC_Config(p_FmMacParam);
+#endif /* (DPAA_VERSION == 10) */
+
+ if (!p_FmMacControllerDriver)
+ return NULL;
+
+ p_FmMacControllerDriver->h_Fm = p_FmMacParam->h_Fm;
+ p_FmMacControllerDriver->enetMode = p_FmMacParam->enetMode;
+ p_FmMacControllerDriver->macId = p_FmMacParam->macId;
+ p_FmMacControllerDriver->resetOnInit = DEFAULT_resetOnInit;
+
+ if ((p_FmMacControllerDriver->clkFreq = FmGetClockFreq(p_FmMacControllerDriver->h_Fm)) == 0)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Can't get clock for MAC!"));
+ return NULL;
+ }
+
+ return (t_Handle)p_FmMacControllerDriver;
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_Init (t_Handle h_FmMac)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->resetOnInit &&
+ !p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit &&
+ (FmResetMac(p_FmMacControllerDriver->h_Fm,
+ ((ENET_INTERFACE_FROM_MODE(p_FmMacControllerDriver->enetMode) == e_ENET_IF_XGMII) ?
+ e_FM_MAC_10G : e_FM_MAC_1G),
+ p_FmMacControllerDriver->macId) != E_OK))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Can't reset MAC!"));
+
+ if (p_FmMacControllerDriver->f_FM_MAC_Init)
+ return p_FmMacControllerDriver->f_FM_MAC_Init(h_FmMac);
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_Free (t_Handle h_FmMac)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_Free)
+ return p_FmMacControllerDriver->f_FM_MAC_Free(h_FmMac);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_ConfigResetOnInit (t_Handle h_FmMac, bool enable)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit)
+ return p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit(h_FmMac, enable);
+
+ p_FmMacControllerDriver->resetOnInit = enable;
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_ConfigLoopback (t_Handle h_FmMac, bool newVal)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback)
+ return p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback(h_FmMac, newVal);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_ConfigMaxFrameLength (t_Handle h_FmMac, uint16_t newVal)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength)
+ return p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength(h_FmMac, newVal);
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_ConfigWan (t_Handle h_FmMac, bool flag)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ConfigWan)
+ return p_FmMacControllerDriver->f_FM_MAC_ConfigWan(h_FmMac, flag);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_ConfigPadAndCrc (t_Handle h_FmMac, bool newVal)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc)
+ return p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc(h_FmMac, newVal);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_ConfigHalfDuplex (t_Handle h_FmMac, bool newVal)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex)
+ return p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex(h_FmMac,newVal);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_ConfigTbiPhyAddr (t_Handle h_FmMac, uint8_t newVal)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ConfigTbiPhyAddr)
+ return p_FmMacControllerDriver->f_FM_MAC_ConfigTbiPhyAddr(h_FmMac,newVal);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_ConfigLengthCheck (t_Handle h_FmMac, bool newVal)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck)
+ return p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck(h_FmMac,newVal);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_ConfigException (t_Handle h_FmMac, e_FmMacExceptions ex, bool enable)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ConfigException)
+ return p_FmMacControllerDriver->f_FM_MAC_ConfigException(h_FmMac, ex, enable);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+/* ......................................................................... */
+
+t_Error FM_MAC_ConfigSkipFman11Workaround (t_Handle h_FmMac)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ConfigSkipFman11Workaround)
+ return p_FmMacControllerDriver->f_FM_MAC_ConfigSkipFman11Workaround(h_FmMac);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+
+/*****************************************************************************/
+/* Run Time Control */
+/*****************************************************************************/
+
+/* ......................................................................... */
+
+t_Error FM_MAC_Enable (t_Handle h_FmMac, e_CommMode mode)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_Enable)
+ return p_FmMacControllerDriver->f_FM_MAC_Enable(h_FmMac, mode);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_Disable (t_Handle h_FmMac, e_CommMode mode)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_Disable)
+ return p_FmMacControllerDriver->f_FM_MAC_Disable(h_FmMac, mode);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_Enable1588TimeStamp (t_Handle h_FmMac)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp)
+ return p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp(h_FmMac);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_Disable1588TimeStamp (t_Handle h_FmMac)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp)
+ return p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp(h_FmMac);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_SetTxAutoPauseFrames(t_Handle h_FmMac,
+ uint16_t pauseTime)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames)
+ return p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames(h_FmMac,
+ pauseTime);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_SetTxPauseFrames(t_Handle h_FmMac,
+ uint8_t priority,
+ uint16_t pauseTime,
+ uint16_t threshTime)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames)
+ return p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames(h_FmMac,
+ priority,
+ pauseTime,
+ threshTime);
+
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_SetRxIgnorePauseFrames (t_Handle h_FmMac, bool en)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames)
+ return p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames(h_FmMac, en);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_SetWakeOnLan (t_Handle h_FmMac, bool en)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_SetWakeOnLan)
+ return p_FmMacControllerDriver->f_FM_MAC_SetWakeOnLan(h_FmMac, en);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_ResetCounters (t_Handle h_FmMac)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ResetCounters)
+ return p_FmMacControllerDriver->f_FM_MAC_ResetCounters(h_FmMac);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_SetException(t_Handle h_FmMac, e_FmMacExceptions ex, bool enable)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_SetException)
+ return p_FmMacControllerDriver->f_FM_MAC_SetException(h_FmMac, ex, enable);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_SetStatistics (t_Handle h_FmMac, e_FmMacStatisticsLevel statisticsLevel)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_SetStatistics)
+ return p_FmMacControllerDriver->f_FM_MAC_SetStatistics(h_FmMac, statisticsLevel);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_GetStatistics (t_Handle h_FmMac, t_FmMacStatistics *p_Statistics)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_GetStatistics)
+ return p_FmMacControllerDriver->f_FM_MAC_GetStatistics(h_FmMac, p_Statistics);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_ModifyMacAddr (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr)
+ return p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr(h_FmMac, p_EnetAddr);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_AddHashMacAddr (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr)
+ return p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr(h_FmMac, p_EnetAddr);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_RemoveHashMacAddr (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr)
+ return p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr(h_FmMac, p_EnetAddr);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_AddExactMatchMacAddr (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr)
+ return p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr(h_FmMac, p_EnetAddr);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_RemovelExactMatchMacAddr (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr)
+ return p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr(h_FmMac, p_EnetAddr);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_GetVesrion (t_Handle h_FmMac, uint32_t *macVresion)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_GetVersion)
+ return p_FmMacControllerDriver->f_FM_MAC_GetVersion(h_FmMac, macVresion);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_GetId (t_Handle h_FmMac, uint32_t *macId)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_GetId)
+ return p_FmMacControllerDriver->f_FM_MAC_GetId(h_FmMac, macId);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_SetPromiscuous (t_Handle h_FmMac, bool newVal)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous)
+ return p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous(h_FmMac, newVal);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_AdjustLink(t_Handle h_FmMac, e_EnetSpeed speed, bool fullDuplex)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_AdjustLink)
+ return p_FmMacControllerDriver->f_FM_MAC_AdjustLink(h_FmMac, speed, fullDuplex);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_RestartAutoneg(t_Handle h_FmMac)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_RestartAutoneg)
+ return p_FmMacControllerDriver->f_FM_MAC_RestartAutoneg(h_FmMac);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_MII_WritePhyReg (t_Handle h_FmMac, uint8_t phyAddr, uint8_t reg, uint16_t data)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg)
+ return p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg(h_FmMac, phyAddr, reg, data);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+t_Error FM_MAC_MII_ReadPhyReg(t_Handle h_FmMac, uint8_t phyAddr, uint8_t reg, uint16_t *p_Data)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg)
+ return p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg(h_FmMac, phyAddr, reg, p_Data);
+
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+
+/* ......................................................................... */
+
+uint16_t FM_MAC_GetMaxFrameLength(t_Handle h_FmMac)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmMacControllerDriver, E_INVALID_HANDLE, 0);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength)
+ return p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength(h_FmMac);
+
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+ return 0;
+}
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+/*****************************************************************************/
+t_Error FM_MAC_DumpRegs(t_Handle h_FmMac)
+{
+ t_FmMacControllerDriver *p_FmMacControllerDriver = (t_FmMacControllerDriver *)h_FmMac;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmMacControllerDriver, E_INVALID_HANDLE);
+
+ if (p_FmMacControllerDriver->f_FM_MAC_DumpRegs)
+ return p_FmMacControllerDriver->f_FM_MAC_DumpRegs(h_FmMac);
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fm_mac.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fm_mac.h
new file mode 100644
index 0000000..05ccd7e
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fm_mac.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_mac.h
+
+ @Description FM MAC ...
+*//***************************************************************************/
+#ifndef __FM_MAC_H
+#define __FM_MAC_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "list_ext.h"
+#include "fm_mac_ext.h"
+#include "fm_common.h"
+
+
+#define __ERR_MODULE__ MODULE_FM_MAC
+
+/**************************************************************************//**
+ @Description defaults
+*//***************************************************************************/
+
+
+#define DEFAULT_halfDuplex FALSE
+#define DEFAULT_padAndCrcEnable TRUE
+#define DEFAULT_resetOnInit FALSE
+
+
+typedef struct {
+ uint64_t addr; /* Ethernet Address */
+ t_List node;
+} t_EthHashEntry;
+#define ETH_HASH_ENTRY_OBJ(ptr) LIST_OBJECT(ptr, t_EthHashEntry, node)
+
+typedef struct {
+ uint16_t size;
+ t_List *p_Lsts;
+} t_EthHash;
+
+typedef struct {
+ t_Error (*f_FM_MAC_Init) (t_Handle h_FmMac);
+ t_Error (*f_FM_MAC_Free) (t_Handle h_FmMac);
+
+ t_Error (*f_FM_MAC_SetStatistics) (t_Handle h_FmMac, e_FmMacStatisticsLevel statisticsLevel);
+ t_Error (*f_FM_MAC_ConfigLoopback) (t_Handle h_FmMac, bool newVal);
+ t_Error (*f_FM_MAC_ConfigMaxFrameLength) (t_Handle h_FmMac, uint16_t newVal);
+ t_Error (*f_FM_MAC_ConfigWan) (t_Handle h_FmMac, bool flag);
+ t_Error (*f_FM_MAC_ConfigPadAndCrc) (t_Handle h_FmMac, bool newVal);
+ t_Error (*f_FM_MAC_ConfigHalfDuplex) (t_Handle h_FmMac, bool newVal);
+ t_Error (*f_FM_MAC_ConfigLengthCheck) (t_Handle h_FmMac, bool newVal);
+ t_Error (*f_FM_MAC_ConfigTbiPhyAddr) (t_Handle h_FmMac, uint8_t newVal);
+ t_Error (*f_FM_MAC_ConfigException) (t_Handle h_FmMac, e_FmMacExceptions, bool enable);
+ t_Error (*f_FM_MAC_ConfigResetOnInit) (t_Handle h_FmMac, bool enable);
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+ t_Error (*f_FM_MAC_ConfigSkipFman11Workaround) (t_Handle h_FmMac);
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+ t_Error (*f_FM_MAC_SetException) (t_Handle h_FmMac, e_FmMacExceptions ex, bool enable);
+
+ t_Error (*f_FM_MAC_Enable) (t_Handle h_FmMac, e_CommMode mode);
+ t_Error (*f_FM_MAC_Disable) (t_Handle h_FmMac, e_CommMode mode);
+ t_Error (*f_FM_MAC_Enable1588TimeStamp) (t_Handle h_FmMac);
+ t_Error (*f_FM_MAC_Disable1588TimeStamp) (t_Handle h_FmMac);
+ t_Error (*f_FM_MAC_Reset) (t_Handle h_FmMac, bool wait);
+
+ t_Error (*f_FM_MAC_SetTxAutoPauseFrames) (t_Handle h_FmMac,
+ uint16_t pauseTime);
+ t_Error (*f_FM_MAC_SetTxPauseFrames) (t_Handle h_FmMac,
+ uint8_t priority,
+ uint16_t pauseTime,
+ uint16_t threshTime);
+ t_Error (*f_FM_MAC_SetRxIgnorePauseFrames) (t_Handle h_FmMac, bool en);
+
+ t_Error (*f_FM_MAC_ResetCounters) (t_Handle h_FmMac);
+ t_Error (*f_FM_MAC_GetStatistics) (t_Handle h_FmMac, t_FmMacStatistics *p_Statistics);
+
+ t_Error (*f_FM_MAC_ModifyMacAddr) (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr);
+ t_Error (*f_FM_MAC_AddHashMacAddr) (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr);
+ t_Error (*f_FM_MAC_RemoveHashMacAddr) (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr);
+ t_Error (*f_FM_MAC_AddExactMatchMacAddr) (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr);
+ t_Error (*f_FM_MAC_RemovelExactMatchMacAddr) (t_Handle h_FmMac, t_EnetAddr *p_EnetAddr);
+
+ t_Error (*f_FM_MAC_SetPromiscuous) (t_Handle h_FmMac, bool newVal);
+ t_Error (*f_FM_MAC_AdjustLink) (t_Handle h_FmMac, e_EnetSpeed speed, bool fullDuplex);
+ t_Error (*f_FM_MAC_RestartAutoneg) (t_Handle h_FmMac);
+
+ t_Error (*f_FM_MAC_SetWakeOnLan) (t_Handle h_FmMac, bool en);
+
+ t_Error (*f_FM_MAC_GetId) (t_Handle h_FmMac, uint32_t *macId);
+
+ t_Error (*f_FM_MAC_GetVersion) (t_Handle h_FmMac, uint32_t *macVersion);
+
+ uint16_t (*f_FM_MAC_GetMaxFrameLength) (t_Handle h_FmMac);
+
+ t_Error (*f_FM_MAC_MII_WritePhyReg)(t_Handle h_FmMac, uint8_t phyAddr, uint8_t reg, uint16_t data);
+ t_Error (*f_FM_MAC_MII_ReadPhyReg)(t_Handle h_FmMac, uint8_t phyAddr, uint8_t reg, uint16_t *p_Data);
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ t_Error (*f_FM_MAC_DumpRegs) (t_Handle h_FmMac);
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+ t_Handle h_Fm;
+ t_FmRevisionInfo fmRevInfo;
+ e_EnetMode enetMode;
+ uint8_t macId;
+ bool resetOnInit;
+ uint16_t clkFreq;
+} t_FmMacControllerDriver;
+
+
+#if (DPAA_VERSION == 10)
+t_Handle DTSEC_Config(t_FmMacParams *p_FmMacParam);
+t_Handle TGEC_Config(t_FmMacParams *p_FmMacParams);
+#else
+t_Handle MEMAC_Config(t_FmMacParams *p_FmMacParam);
+#endif /* (DPAA_VERSION == 10) */
+uint16_t FM_MAC_GetMaxFrameLength(t_Handle FmMac);
+
+
+/* ........................................................................... */
+
+static __inline__ t_EthHashEntry *DequeueAddrFromHashEntry(t_List *p_AddrLst)
+{
+ t_EthHashEntry *p_HashEntry = NULL;
+ if (!LIST_IsEmpty(p_AddrLst))
+ {
+ p_HashEntry = ETH_HASH_ENTRY_OBJ(p_AddrLst->p_Next);
+ LIST_DelAndInit(&p_HashEntry->node);
+ }
+ return p_HashEntry;
+}
+
+/* ........................................................................... */
+
+static __inline__ void FreeHashTable(t_EthHash *p_Hash)
+{
+ t_EthHashEntry *p_HashEntry;
+ int i = 0;
+
+ if (p_Hash)
+ {
+ if (p_Hash->p_Lsts)
+ {
+ for (i=0; i<p_Hash->size; i++)
+ {
+ p_HashEntry = DequeueAddrFromHashEntry(&p_Hash->p_Lsts[i]);
+ while (p_HashEntry)
+ {
+ XX_Free(p_HashEntry);
+ p_HashEntry = DequeueAddrFromHashEntry(&p_Hash->p_Lsts[i]);
+ }
+ }
+
+ XX_Free(p_Hash->p_Lsts);
+ }
+
+ XX_Free(p_Hash);
+ }
+}
+
+/* ........................................................................... */
+
+static __inline__ t_EthHash * AllocHashTable(uint16_t size)
+{
+ uint32_t i;
+ t_EthHash *p_Hash;
+
+ /* Allocate address hash table */
+ p_Hash = (t_EthHash *)XX_Malloc(size*sizeof(t_EthHash *));
+ if (!p_Hash)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Address hash table"));
+ return NULL;
+ }
+ p_Hash->size = size;
+
+ p_Hash->p_Lsts = (t_List *)XX_Malloc(p_Hash->size*sizeof(t_List));
+ if (!p_Hash->p_Lsts)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Address hash table"));
+ XX_Free(p_Hash);
+ return NULL;
+ }
+
+ for (i=0 ; i<p_Hash->size; i++)
+ INIT_LIST(&p_Hash->p_Lsts[i]);
+
+ return p_Hash;
+}
+
+
+#endif /* __FM_MAC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_crc32.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_crc32.c
new file mode 100644
index 0000000..b6a4ca2
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_crc32.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "fman_crc32.h"
+#include "common/general.h"
+
+
+/* precomputed CRC values for address hashing */
+static const uint32_t crc_tbl[256] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+ 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+ 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+ 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+ 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+ 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+ 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+ 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+ 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+ 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+ 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+ 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+ 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+ 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+ 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+ 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+ 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+ 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+/* Get the mirrored value of a byte size number. (0x11010011 --> 0x11001011) */
+static inline uint8_t get_mirror8(uint8_t n)
+{
+ uint8_t mirror[16] = {
+ 0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e,
+ 0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f
+ };
+ return (uint8_t)(((mirror[n & 0x0f] << 4) | (mirror[n >> 4])));
+}
+
+static inline uint32_t get_mirror32(uint32_t n)
+{
+ return ((uint32_t)get_mirror8((uint8_t)(n))<<24) |
+ ((uint32_t)get_mirror8((uint8_t)(n>>8))<<16) |
+ ((uint32_t)get_mirror8((uint8_t)(n>>16))<<8) |
+ ((uint32_t)get_mirror8((uint8_t)(n>>24)));
+}
+
+uint32_t get_mac_addr_crc(uint64_t _addr)
+{
+ uint32_t i;
+ uint8_t data;
+ uint32_t crc;
+
+ /* CRC calculation */
+ crc = 0xffffffff;
+ for (i = 0; i < 6; i++) {
+ data = (uint8_t)(_addr >> ((5-i)*8));
+ crc = crc ^ data;
+ crc = crc_tbl[crc&0xff] ^ (crc>>8);
+ }
+
+ crc = get_mirror32(crc);
+ return crc;
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_crc32.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_crc32.h
new file mode 100644
index 0000000..6e32fdc
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_crc32.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __FMAN_CRC32_H
+#define __FMAN_CRC32_H
+
+#include "common/general.h"
+
+
+uint32_t get_mac_addr_crc(uint64_t _addr);
+
+
+#endif /* __FMAN_CRC32_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_dtsec.c
new file mode 100644
index 0000000..d88291e
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_dtsec.c
@@ -0,0 +1,846 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "fsl_fman_dtsec.h"
+
+
+void fman_dtsec_stop_rx(struct dtsec_regs *regs)
+{
+ /* Assert the graceful stop bit */
+ iowrite32be(ioread32be(&regs->rctrl) | RCTRL_GRS, &regs->rctrl);
+}
+
+void fman_dtsec_stop_tx(struct dtsec_regs *regs)
+{
+ /* Assert the graceful stop bit */
+ iowrite32be(ioread32be(&regs->tctrl) | DTSEC_TCTRL_GTS, &regs->tctrl);
+}
+
+void fman_dtsec_start_tx(struct dtsec_regs *regs)
+{
+ /* clear the graceful stop bit */
+ iowrite32be(ioread32be(&regs->tctrl) & ~DTSEC_TCTRL_GTS, &regs->tctrl);
+}
+
+void fman_dtsec_start_rx(struct dtsec_regs *regs)
+{
+ /* clear the graceful stop bit */
+ iowrite32be(ioread32be(&regs->rctrl) & ~RCTRL_GRS, &regs->rctrl);
+}
+
+void fman_dtsec_defconfig(struct dtsec_cfg *cfg)
+{
+ cfg->halfdup_on = DEFAULT_HALFDUP_ON;
+ cfg->halfdup_retransmit = DEFAULT_HALFDUP_RETRANSMIT;
+ cfg->halfdup_coll_window = DEFAULT_HALFDUP_COLL_WINDOW;
+ cfg->halfdup_excess_defer = DEFAULT_HALFDUP_EXCESS_DEFER;
+ cfg->halfdup_no_backoff = DEFAULT_HALFDUP_NO_BACKOFF;
+ cfg->halfdup_bp_no_backoff = DEFAULT_HALFDUP_BP_NO_BACKOFF;
+ cfg->halfdup_alt_backoff_val = DEFAULT_HALFDUP_ALT_BACKOFF_VAL;
+ cfg->halfdup_alt_backoff_en = DEFAULT_HALFDUP_ALT_BACKOFF_EN;
+ cfg->rx_drop_bcast = DEFAULT_RX_DROP_BCAST;
+ cfg->rx_short_frm = DEFAULT_RX_SHORT_FRM;
+ cfg->rx_len_check = DEFAULT_RX_LEN_CHECK;
+ cfg->tx_pad_crc = DEFAULT_TX_PAD_CRC;
+ cfg->tx_crc = DEFAULT_TX_CRC;
+ cfg->rx_ctrl_acc = DEFAULT_RX_CTRL_ACC;
+ cfg->tx_pause_time = DEFAULT_TX_PAUSE_TIME;
+ cfg->tbipa = DEFAULT_TBIPA; /* PHY address 0 is reserved (DPAA RM)*/
+ cfg->rx_prepend = DEFAULT_RX_PREPEND;
+ cfg->ptp_tsu_en = DEFAULT_PTP_TSU_EN;
+ cfg->ptp_exception_en = DEFAULT_PTP_EXCEPTION_EN;
+ cfg->preamble_len = DEFAULT_PREAMBLE_LEN;
+ cfg->rx_preamble = DEFAULT_RX_PREAMBLE;
+ cfg->tx_preamble = DEFAULT_TX_PREAMBLE;
+ cfg->loopback = DEFAULT_LOOPBACK;
+ cfg->rx_time_stamp_en = DEFAULT_RX_TIME_STAMP_EN;
+ cfg->tx_time_stamp_en = DEFAULT_TX_TIME_STAMP_EN;
+ cfg->rx_flow = DEFAULT_RX_FLOW;
+ cfg->tx_flow = DEFAULT_TX_FLOW;
+ cfg->rx_group_hash_exd = DEFAULT_RX_GROUP_HASH_EXD;
+ cfg->tx_pause_time_extd = DEFAULT_TX_PAUSE_TIME_EXTD;
+ cfg->rx_promisc = DEFAULT_RX_PROMISC;
+ cfg->non_back_to_back_ipg1 = DEFAULT_NON_BACK_TO_BACK_IPG1;
+ cfg->non_back_to_back_ipg2 = DEFAULT_NON_BACK_TO_BACK_IPG2;
+ cfg->min_ifg_enforcement = DEFAULT_MIN_IFG_ENFORCEMENT;
+ cfg->back_to_back_ipg = DEFAULT_BACK_TO_BACK_IPG;
+ cfg->maximum_frame = DEFAULT_MAXIMUM_FRAME;
+ cfg->tbi_phy_addr = DEFAULT_TBI_PHY_ADDR;
+ cfg->wake_on_lan = DEFAULT_WAKE_ON_LAN;
+}
+
+int fman_dtsec_init(struct dtsec_regs *regs, struct dtsec_cfg *cfg,
+ enum enet_interface iface_mode,
+ enum enet_speed iface_speed,
+ uint8_t *macaddr,
+ uint8_t fm_rev_maj,
+ uint8_t fm_rev_min,
+ uint32_t exception_mask)
+{
+ bool is_rgmii = FALSE;
+ bool is_sgmii = FALSE;
+ bool is_qsgmii = FALSE;
+ int i;
+ uint32_t tmp;
+
+UNUSED(fm_rev_maj);UNUSED(fm_rev_min);
+
+ /* let's start with a soft reset */
+ iowrite32be(MACCFG1_SOFT_RESET, &regs->maccfg1);
+ iowrite32be(0, &regs->maccfg1);
+
+ /*************dtsec_id2******************/
+ tmp = ioread32be(&regs->tsec_id2);
+
+ /* check RGMII support */
+ if (iface_mode == E_ENET_IF_RGMII ||
+ iface_mode == E_ENET_IF_RMII)
+ if (tmp & DTSEC_ID2_INT_REDUCED_OFF)
+ return -EINVAL;
+
+ if (iface_mode == E_ENET_IF_SGMII ||
+ iface_mode == E_ENET_IF_MII)
+ if (tmp & DTSEC_ID2_INT_REDUCED_OFF)
+ return -EINVAL;
+
+ /***************ECNTRL************************/
+
+ is_rgmii = (bool)((iface_mode == E_ENET_IF_RGMII) ? TRUE : FALSE);
+ is_sgmii = (bool)((iface_mode == E_ENET_IF_SGMII) ? TRUE : FALSE);
+ is_qsgmii = (bool)((iface_mode == E_ENET_IF_QSGMII) ? TRUE : FALSE);
+
+ tmp = 0;
+ if (is_rgmii || iface_mode == E_ENET_IF_GMII)
+ tmp |= DTSEC_ECNTRL_GMIIM;
+ if (is_sgmii)
+ tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM);
+ if (is_qsgmii)
+ tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM |
+ DTSEC_ECNTRL_QSGMIIM);
+ if (is_rgmii)
+ tmp |= DTSEC_ECNTRL_RPM;
+ if (iface_speed == E_ENET_SPEED_100)
+ tmp |= DTSEC_ECNTRL_R100M;
+
+ iowrite32be(tmp, &regs->ecntrl);
+ /***************ECNTRL************************/
+
+ /***************TCTRL************************/
+ tmp = 0;
+ if (cfg->halfdup_on)
+ tmp |= DTSEC_TCTRL_THDF;
+ if (cfg->tx_time_stamp_en)
+ tmp |= DTSEC_TCTRL_TTSE;
+
+ iowrite32be(tmp, &regs->tctrl);
+
+ /***************TCTRL************************/
+
+ /***************PTV************************/
+ tmp = 0;
+
+#ifdef FM_SHORT_PAUSE_TIME_ERRATA_DTSEC1
+ if ((fm_rev_maj == 1) && (fm_rev_min == 0))
+ cfg->tx_pause_time += 2;
+#endif /* FM_SHORT_PAUSE_TIME_ERRATA_DTSEC1 */
+
+ if (cfg->tx_pause_time)
+ tmp |= cfg->tx_pause_time;
+ if (cfg->tx_pause_time_extd)
+ tmp |= cfg->tx_pause_time_extd << PTV_PTE_OFST;
+ iowrite32be(tmp, &regs->ptv);
+
+ /***************RCTRL************************/
+ tmp = 0;
+ tmp |= ((uint32_t)(cfg->rx_prepend & 0x0000001f)) << 16;
+ if (cfg->rx_ctrl_acc)
+ tmp |= RCTRL_CFA;
+ if (cfg->rx_group_hash_exd)
+ tmp |= RCTRL_GHTX;
+ if (cfg->rx_time_stamp_en)
+ tmp |= RCTRL_RTSE;
+ if (cfg->rx_drop_bcast)
+ tmp |= RCTRL_BC_REJ;
+ if (cfg->rx_short_frm)
+ tmp |= RCTRL_RSF;
+ if (cfg->rx_promisc)
+ tmp |= RCTRL_PROM;
+
+ iowrite32be(tmp, &regs->rctrl);
+ /***************RCTRL************************/
+
+ /*
+ * Assign a Phy Address to the TBI (TBIPA).
+ * Done also in cases where TBI is not selected to avoid conflict with
+ * the external PHY's Physical address
+ */
+ iowrite32be(cfg->tbipa, &regs->tbipa);
+
+ /***************TMR_CTL************************/
+ iowrite32be(0, &regs->tmr_ctrl);
+
+ if (cfg->ptp_tsu_en) {
+ tmp = 0;
+ tmp |= TMR_PEVENT_TSRE;
+ iowrite32be(tmp, &regs->tmr_pevent);
+
+ if (cfg->ptp_exception_en) {
+ tmp = 0;
+ tmp |= TMR_PEMASK_TSREEN;
+ iowrite32be(tmp, &regs->tmr_pemask);
+ }
+ }
+
+ /***************MACCFG1***********************/
+ tmp = 0;
+ if (cfg->loopback)
+ tmp |= MACCFG1_LOOPBACK;
+ if (cfg->rx_flow)
+ tmp |= MACCFG1_RX_FLOW;
+ if (cfg->tx_flow)
+ tmp |= MACCFG1_TX_FLOW;
+ iowrite32be(tmp, &regs->maccfg1);
+
+ /***************MACCFG1***********************/
+
+ /***************MACCFG2***********************/
+ tmp = 0;
+
+ if (iface_speed < E_ENET_SPEED_1000)
+ tmp |= MACCFG2_NIBBLE_MODE;
+ else if (iface_speed == E_ENET_SPEED_1000)
+ tmp |= MACCFG2_BYTE_MODE;
+
+ tmp |= ((uint32_t) cfg->preamble_len & 0x0000000f)
+ << PREAMBLE_LENGTH_SHIFT;
+
+ if (cfg->rx_preamble)
+ tmp |= MACCFG2_PRE_AM_Rx_EN;
+ if (cfg->tx_preamble)
+ tmp |= MACCFG2_PRE_AM_Tx_EN;
+ if (cfg->rx_len_check)
+ tmp |= MACCFG2_LENGTH_CHECK;
+ if (cfg->tx_pad_crc)
+ tmp |= MACCFG2_PAD_CRC_EN;
+ if (cfg->tx_crc)
+ tmp |= MACCFG2_CRC_EN;
+ if (!cfg->halfdup_on)
+ tmp |= MACCFG2_FULL_DUPLEX;
+ iowrite32be(tmp, &regs->maccfg2);
+
+ /***************MACCFG2***********************/
+
+ /***************IPGIFG************************/
+ tmp = 0;
+ tmp = (((cfg->non_back_to_back_ipg1 <<
+ IPGIFG_NON_BACK_TO_BACK_IPG_1_SHIFT)
+ & IPGIFG_NON_BACK_TO_BACK_IPG_1)
+ | ((cfg->non_back_to_back_ipg2 <<
+ IPGIFG_NON_BACK_TO_BACK_IPG_2_SHIFT)
+ & IPGIFG_NON_BACK_TO_BACK_IPG_2)
+ | ((cfg->min_ifg_enforcement <<
+ IPGIFG_MIN_IFG_ENFORCEMENT_SHIFT)
+ & IPGIFG_MIN_IFG_ENFORCEMENT)
+ | (cfg->back_to_back_ipg & IPGIFG_BACK_TO_BACK_IPG));
+ iowrite32be(tmp, &regs->ipgifg);
+
+ /***************IPGIFG************************/
+
+ /***************HAFDUP************************/
+ tmp = 0;
+
+ if (cfg->halfdup_alt_backoff_en)
+ tmp = (uint32_t)(HAFDUP_ALT_BEB |
+ ((cfg->halfdup_alt_backoff_val & 0x0000000f)
+ << HAFDUP_ALTERNATE_BEB_TRUNCATION_SHIFT));
+ if (cfg->halfdup_bp_no_backoff)
+ tmp |= HAFDUP_BP_NO_BACKOFF;
+ if (cfg->halfdup_no_backoff)
+ tmp |= HAFDUP_NO_BACKOFF;
+ if (cfg->halfdup_excess_defer)
+ tmp |= HAFDUP_EXCESS_DEFER;
+ tmp |= ((cfg->halfdup_retransmit << HAFDUP_RETRANSMISSION_MAX_SHIFT)
+ & HAFDUP_RETRANSMISSION_MAX);
+ tmp |= (cfg->halfdup_coll_window & HAFDUP_COLLISION_WINDOW);
+
+ iowrite32be(tmp, &regs->hafdup);
+ /***************HAFDUP************************/
+
+ /***************MAXFRM************************/
+ /* Initialize MAXFRM */
+ iowrite32be(cfg->maximum_frame, &regs->maxfrm);
+
+ /***************MAXFRM************************/
+
+ /***************CAM1************************/
+ iowrite32be(0xffffffff, &regs->cam1);
+ iowrite32be(0xffffffff, &regs->cam2);
+
+ /***************IMASK************************/
+ iowrite32be(exception_mask, &regs->imask);
+ /***************IMASK************************/
+
+ /***************IEVENT************************/
+ iowrite32be(0xffffffff, &regs->ievent);
+
+ /***************MACSTNADDR1/2*****************/
+
+ tmp = (uint32_t)((macaddr[5] << 24) |
+ (macaddr[4] << 16) |
+ (macaddr[3] << 8) |
+ macaddr[2]);
+ iowrite32be(tmp, &regs->macstnaddr1);
+
+ tmp = (uint32_t)((macaddr[1] << 24) |
+ (macaddr[0] << 16));
+ iowrite32be(tmp, &regs->macstnaddr2);
+
+ /***************MACSTNADDR1/2*****************/
+
+ /*****************HASH************************/
+ for (i = 0; i < NUM_OF_HASH_REGS ; i++) {
+ /* Initialize IADDRx */
+ iowrite32be(0, &regs->igaddr[i]);
+ /* Initialize GADDRx */
+ iowrite32be(0, &regs->gaddr[i]);
+ }
+
+ fman_dtsec_reset_stat(regs);
+
+ return 0;
+}
+
+uint16_t fman_dtsec_get_max_frame_len(struct dtsec_regs *regs)
+{
+ return (uint16_t)ioread32be(&regs->maxfrm);
+}
+
+void fman_dtsec_set_max_frame_len(struct dtsec_regs *regs, uint16_t length)
+{
+ iowrite32be(length, &regs->maxfrm);
+}
+
+void fman_dtsec_set_mac_address(struct dtsec_regs *regs, uint8_t *adr)
+{
+ uint32_t tmp;
+
+ tmp = (uint32_t)((adr[5] << 24) |
+ (adr[4] << 16) |
+ (adr[3] << 8) |
+ adr[2]);
+ iowrite32be(tmp, &regs->macstnaddr1);
+
+ tmp = (uint32_t)((adr[1] << 24) |
+ (adr[0] << 16));
+ iowrite32be(tmp, &regs->macstnaddr2);
+}
+
+void fman_dtsec_get_mac_address(struct dtsec_regs *regs, uint8_t *macaddr)
+{
+ uint32_t tmp1, tmp2;
+
+ tmp1 = ioread32be(&regs->macstnaddr1);
+ tmp2 = ioread32be(&regs->macstnaddr2);
+
+ macaddr[0] = (uint8_t)((tmp2 & 0x00ff0000) >> 16);
+ macaddr[1] = (uint8_t)((tmp2 & 0xff000000) >> 24);
+ macaddr[2] = (uint8_t)(tmp1 & 0x000000ff);
+ macaddr[3] = (uint8_t)((tmp1 & 0x0000ff00) >> 8);
+ macaddr[4] = (uint8_t)((tmp1 & 0x00ff0000) >> 16);
+ macaddr[5] = (uint8_t)((tmp1 & 0xff000000) >> 24);
+}
+
+void fman_dtsec_set_hash_table(struct dtsec_regs *regs, uint32_t crc, bool mcast, bool ghtx)
+{
+ int32_t bucket;
+ if (ghtx)
+ bucket = (int32_t)((crc >> 23) & 0x1ff);
+ else {
+ bucket = (int32_t)((crc >> 24) & 0xff);
+ /* if !ghtx and mcast the bit must be set in gaddr instead of igaddr. */
+ if (mcast)
+ bucket += 0x100;
+ }
+ fman_dtsec_set_bucket(regs, bucket, TRUE);
+}
+
+void fman_dtsec_set_bucket(struct dtsec_regs *regs, int bucket, bool enable)
+{
+ int reg_idx = (bucket >> 5) & 0xf;
+ int bit_idx = bucket & 0x1f;
+ uint32_t bit_mask = 0x80000000 >> bit_idx;
+ uint32_t *reg;
+
+ if (reg_idx > 7)
+ reg = &regs->gaddr[reg_idx-8];
+ else
+ reg = &regs->igaddr[reg_idx];
+
+ if (enable)
+ iowrite32be(ioread32be(reg) | bit_mask, reg);
+ else
+ iowrite32be(ioread32be(reg) & (~bit_mask), reg);
+}
+
+void fman_dtsec_reset_filter_table(struct dtsec_regs *regs, bool mcast, bool ucast)
+{
+ int i;
+ bool ghtx;
+
+ ghtx = (bool)((ioread32be(&regs->rctrl) & RCTRL_GHTX) ? TRUE : FALSE);
+
+ if (ucast || (ghtx && mcast)) {
+ for (i = 0; i < NUM_OF_HASH_REGS; i++)
+ iowrite32be(0, &regs->igaddr[i]);
+ }
+ if (mcast) {
+ for (i = 0; i < NUM_OF_HASH_REGS; i++)
+ iowrite32be(0, &regs->gaddr[i]);
+ }
+}
+
+int fman_dtsec_set_tbi_phy_addr(struct dtsec_regs *regs,
+ uint8_t addr)
+{
+ if (addr > 0 && addr < 32)
+ iowrite32be(addr, &regs->tbipa);
+ else
+ return -EINVAL;
+
+ return 0;
+}
+
+void fman_dtsec_set_wol(struct dtsec_regs *regs, bool en)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->maccfg2);
+ if (en)
+ tmp |= MACCFG2_MAGIC_PACKET_EN;
+ else
+ tmp &= ~MACCFG2_MAGIC_PACKET_EN;
+ iowrite32be(tmp, &regs->maccfg2);
+}
+
+int fman_dtsec_adjust_link(struct dtsec_regs *regs,
+ enum enet_interface iface_mode,
+ enum enet_speed speed, bool full_dx)
+{
+ uint32_t tmp;
+
+ UNUSED(iface_mode);
+
+ if ((speed == E_ENET_SPEED_1000) && !full_dx)
+ return -EINVAL;
+
+ tmp = ioread32be(&regs->maccfg2);
+ if (!full_dx)
+ tmp &= ~MACCFG2_FULL_DUPLEX;
+ else
+ tmp |= MACCFG2_FULL_DUPLEX;
+
+ tmp &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE);
+ if (speed < E_ENET_SPEED_1000)
+ tmp |= MACCFG2_NIBBLE_MODE;
+ else if (speed == E_ENET_SPEED_1000)
+ tmp |= MACCFG2_BYTE_MODE;
+ iowrite32be(tmp, &regs->maccfg2);
+
+ tmp = ioread32be(&regs->ecntrl);
+ if (speed == E_ENET_SPEED_100)
+ tmp |= DTSEC_ECNTRL_R100M;
+ else
+ tmp &= ~DTSEC_ECNTRL_R100M;
+ iowrite32be(tmp, &regs->ecntrl);
+
+ return 0;
+}
+
+void fman_dtsec_set_uc_promisc(struct dtsec_regs *regs, bool enable)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->rctrl);
+
+ if (enable)
+ tmp |= RCTRL_UPROM;
+ else
+ tmp &= ~RCTRL_UPROM;
+
+ iowrite32be(tmp, &regs->rctrl);
+}
+
+void fman_dtsec_set_mc_promisc(struct dtsec_regs *regs, bool enable)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->rctrl);
+
+ if (enable)
+ tmp |= RCTRL_MPROM;
+ else
+ tmp &= ~RCTRL_MPROM;
+
+ iowrite32be(tmp, &regs->rctrl);
+}
+
+bool fman_dtsec_get_clear_carry_regs(struct dtsec_regs *regs,
+ uint32_t *car1, uint32_t *car2)
+{
+ /* read carry registers */
+ *car1 = ioread32be(&regs->car1);
+ *car2 = ioread32be(&regs->car2);
+ /* clear carry registers */
+ if (*car1)
+ iowrite32be(*car1, &regs->car1);
+ if (*car2)
+ iowrite32be(*car2, &regs->car2);
+
+ return (bool)((*car1 | *car2) ? TRUE : FALSE);
+}
+
+void fman_dtsec_reset_stat(struct dtsec_regs *regs)
+{
+ /* clear HW counters */
+ iowrite32be(ioread32be(&regs->ecntrl) |
+ DTSEC_ECNTRL_CLRCNT, &regs->ecntrl);
+}
+
+int fman_dtsec_set_stat_level(struct dtsec_regs *regs, enum dtsec_stat_level level)
+{
+ switch (level) {
+ case E_MAC_STAT_NONE:
+ iowrite32be(0xffffffff, &regs->cam1);
+ iowrite32be(0xffffffff, &regs->cam2);
+ iowrite32be(ioread32be(&regs->ecntrl) & ~DTSEC_ECNTRL_STEN,
+ &regs->ecntrl);
+ iowrite32be(ioread32be(&regs->imask) & ~DTSEC_IMASK_MSROEN,
+ &regs->imask);
+ break;
+ case E_MAC_STAT_PARTIAL:
+ iowrite32be(CAM1_ERRORS_ONLY, &regs->cam1);
+ iowrite32be(CAM2_ERRORS_ONLY, &regs->cam2);
+ iowrite32be(ioread32be(&regs->ecntrl) | DTSEC_ECNTRL_STEN,
+ &regs->ecntrl);
+ iowrite32be(ioread32be(&regs->imask) | DTSEC_IMASK_MSROEN,
+ &regs->imask);
+ break;
+ case E_MAC_STAT_MIB_GRP1:
+ iowrite32be((uint32_t)~CAM1_MIB_GRP_1, &regs->cam1);
+ iowrite32be((uint32_t)~CAM2_MIB_GRP_1, &regs->cam2);
+ iowrite32be(ioread32be(&regs->ecntrl) | DTSEC_ECNTRL_STEN,
+ &regs->ecntrl);
+ iowrite32be(ioread32be(&regs->imask) | DTSEC_IMASK_MSROEN,
+ &regs->imask);
+ break;
+ case E_MAC_STAT_FULL:
+ iowrite32be(0, &regs->cam1);
+ iowrite32be(0, &regs->cam2);
+ iowrite32be(ioread32be(&regs->ecntrl) | DTSEC_ECNTRL_STEN,
+ &regs->ecntrl);
+ iowrite32be(ioread32be(&regs->imask) | DTSEC_IMASK_MSROEN,
+ &regs->imask);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void fman_dtsec_set_ts(struct dtsec_regs *regs, bool en)
+{
+ if (en) {
+ iowrite32be(ioread32be(&regs->rctrl) | RCTRL_RTSE,
+ &regs->rctrl);
+ iowrite32be(ioread32be(&regs->tctrl) | DTSEC_TCTRL_TTSE,
+ &regs->tctrl);
+ } else {
+ iowrite32be(ioread32be(&regs->rctrl) & ~RCTRL_RTSE,
+ &regs->rctrl);
+ iowrite32be(ioread32be(&regs->tctrl) & ~DTSEC_TCTRL_TTSE,
+ &regs->tctrl);
+ }
+}
+
+void fman_dtsec_enable(struct dtsec_regs *regs, bool apply_rx, bool apply_tx)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->maccfg1);
+
+ if (apply_rx)
+ tmp |= MACCFG1_RX_EN ;
+
+ if (apply_tx)
+ tmp |= MACCFG1_TX_EN ;
+
+ iowrite32be(tmp, &regs->maccfg1);
+}
+
+void fman_dtsec_clear_addr_in_paddr(struct dtsec_regs *regs, uint8_t paddr_num)
+{
+ iowrite32be(0, &regs->macaddr[paddr_num].exact_match1);
+ iowrite32be(0, &regs->macaddr[paddr_num].exact_match2);
+}
+
+void fman_dtsec_add_addr_in_paddr(struct dtsec_regs *regs,
+ uint64_t addr,
+ uint8_t paddr_num)
+{
+ uint32_t tmp;
+
+ tmp = (uint32_t)(addr);
+ /* swap */
+ tmp = (((tmp & 0x000000FF) << 24) |
+ ((tmp & 0x0000FF00) << 8) |
+ ((tmp & 0x00FF0000) >> 8) |
+ ((tmp & 0xFF000000) >> 24));
+ iowrite32be(tmp, &regs->macaddr[paddr_num].exact_match1);
+
+ tmp = (uint32_t)(addr>>32);
+ /* swap */
+ tmp = (((tmp & 0x000000FF) << 24) |
+ ((tmp & 0x0000FF00) << 8) |
+ ((tmp & 0x00FF0000) >> 8) |
+ ((tmp & 0xFF000000) >> 24));
+ iowrite32be(tmp, &regs->macaddr[paddr_num].exact_match2);
+}
+
+void fman_dtsec_disable(struct dtsec_regs *regs, bool apply_rx, bool apply_tx)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->maccfg1);
+
+ if (apply_rx)
+ tmp &= ~MACCFG1_RX_EN;
+
+ if (apply_tx)
+ tmp &= ~MACCFG1_TX_EN;
+
+ iowrite32be(tmp, &regs->maccfg1);
+}
+
+void fman_dtsec_set_tx_pause_frames(struct dtsec_regs *regs, uint16_t time)
+{
+ uint32_t ptv = 0;
+
+ /* fixme: don't enable tx pause for half-duplex */
+
+ if (time) {
+ ptv = ioread32be(&regs->ptv);
+ ptv &= 0xffff0000;
+ ptv |= time & 0x0000ffff;
+ iowrite32be(ptv, &regs->ptv);
+
+ /* trigger the transmission of a flow-control pause frame */
+ iowrite32be(ioread32be(&regs->maccfg1) | MACCFG1_TX_FLOW,
+ &regs->maccfg1);
+ } else
+ iowrite32be(ioread32be(&regs->maccfg1) & ~MACCFG1_TX_FLOW,
+ &regs->maccfg1);
+}
+
+void fman_dtsec_handle_rx_pause(struct dtsec_regs *regs, bool en)
+{
+ uint32_t tmp;
+
+ /* todo: check if mac is set to full-duplex */
+
+ tmp = ioread32be(&regs->maccfg1);
+ if (en)
+ tmp |= MACCFG1_RX_FLOW;
+ else
+ tmp &= ~MACCFG1_RX_FLOW;
+ iowrite32be(tmp, &regs->maccfg1);
+}
+
+uint32_t fman_dtsec_get_rctrl(struct dtsec_regs *regs)
+{
+ return ioread32be(&regs->rctrl);
+}
+
+uint32_t fman_dtsec_get_revision(struct dtsec_regs *regs)
+{
+ return ioread32be(&regs->tsec_id);
+}
+
+uint32_t fman_dtsec_get_event(struct dtsec_regs *regs, uint32_t ev_mask)
+{
+ return ioread32be(&regs->ievent) & ev_mask;
+}
+
+void fman_dtsec_ack_event(struct dtsec_regs *regs, uint32_t ev_mask)
+{
+ iowrite32be(ev_mask, &regs->ievent);
+}
+
+uint32_t fman_dtsec_get_interrupt_mask(struct dtsec_regs *regs)
+{
+ return ioread32be(&regs->imask);
+}
+
+uint32_t fman_dtsec_check_and_clear_tmr_event(struct dtsec_regs *regs)
+{
+ uint32_t event;
+
+ event = ioread32be(&regs->tmr_pevent);
+ event &= ioread32be(&regs->tmr_pemask);
+
+ if (event)
+ iowrite32be(event, &regs->tmr_pevent);
+ return event;
+}
+
+void fman_dtsec_enable_tmr_interrupt(struct dtsec_regs *regs)
+{
+ iowrite32be(ioread32be(&regs->tmr_pemask) | TMR_PEMASK_TSREEN,
+ &regs->tmr_pemask);
+}
+
+void fman_dtsec_disable_tmr_interrupt(struct dtsec_regs *regs)
+{
+ iowrite32be(ioread32be(&regs->tmr_pemask) & ~TMR_PEMASK_TSREEN,
+ &regs->tmr_pemask);
+}
+
+void fman_dtsec_enable_interrupt(struct dtsec_regs *regs, uint32_t ev_mask)
+{
+ iowrite32be(ioread32be(&regs->imask) | ev_mask, &regs->imask);
+}
+
+void fman_dtsec_disable_interrupt(struct dtsec_regs *regs, uint32_t ev_mask)
+{
+ iowrite32be(ioread32be(&regs->imask) & ~ev_mask, &regs->imask);
+}
+
+uint32_t fman_dtsec_get_stat_counter(struct dtsec_regs *regs,
+ enum dtsec_stat_counters reg_name)
+{
+ uint32_t ret_val;
+
+ switch (reg_name) {
+ case E_DTSEC_STAT_TR64:
+ ret_val = ioread32be(&regs->tr64);
+ break;
+ case E_DTSEC_STAT_TR127:
+ ret_val = ioread32be(&regs->tr127);
+ break;
+ case E_DTSEC_STAT_TR255:
+ ret_val = ioread32be(&regs->tr255);
+ break;
+ case E_DTSEC_STAT_TR511:
+ ret_val = ioread32be(&regs->tr511);
+ break;
+ case E_DTSEC_STAT_TR1K:
+ ret_val = ioread32be(&regs->tr1k);
+ break;
+ case E_DTSEC_STAT_TRMAX:
+ ret_val = ioread32be(&regs->trmax);
+ break;
+ case E_DTSEC_STAT_TRMGV:
+ ret_val = ioread32be(&regs->trmgv);
+ break;
+ case E_DTSEC_STAT_RBYT:
+ ret_val = ioread32be(&regs->rbyt);
+ break;
+ case E_DTSEC_STAT_RPKT:
+ ret_val = ioread32be(&regs->rpkt);
+ break;
+ case E_DTSEC_STAT_RMCA:
+ ret_val = ioread32be(&regs->rmca);
+ break;
+ case E_DTSEC_STAT_RBCA:
+ ret_val = ioread32be(&regs->rbca);
+ break;
+ case E_DTSEC_STAT_RXPF:
+ ret_val = ioread32be(&regs->rxpf);
+ break;
+ case E_DTSEC_STAT_RALN:
+ ret_val = ioread32be(&regs->raln);
+ break;
+ case E_DTSEC_STAT_RFLR:
+ ret_val = ioread32be(&regs->rflr);
+ break;
+ case E_DTSEC_STAT_RCDE:
+ ret_val = ioread32be(&regs->rcde);
+ break;
+ case E_DTSEC_STAT_RCSE:
+ ret_val = ioread32be(&regs->rcse);
+ break;
+ case E_DTSEC_STAT_RUND:
+ ret_val = ioread32be(&regs->rund);
+ break;
+ case E_DTSEC_STAT_ROVR:
+ ret_val = ioread32be(&regs->rovr);
+ break;
+ case E_DTSEC_STAT_RFRG:
+ ret_val = ioread32be(&regs->rfrg);
+ break;
+ case E_DTSEC_STAT_RJBR:
+ ret_val = ioread32be(&regs->rjbr);
+ break;
+ case E_DTSEC_STAT_RDRP:
+ ret_val = ioread32be(&regs->rdrp);
+ break;
+ case E_DTSEC_STAT_TFCS:
+ ret_val = ioread32be(&regs->tfcs);
+ break;
+ case E_DTSEC_STAT_TBYT:
+ ret_val = ioread32be(&regs->tbyt);
+ break;
+ case E_DTSEC_STAT_TPKT:
+ ret_val = ioread32be(&regs->tpkt);
+ break;
+ case E_DTSEC_STAT_TMCA:
+ ret_val = ioread32be(&regs->tmca);
+ break;
+ case E_DTSEC_STAT_TBCA:
+ ret_val = ioread32be(&regs->tbca);
+ break;
+ case E_DTSEC_STAT_TXPF:
+ ret_val = ioread32be(&regs->txpf);
+ break;
+ case E_DTSEC_STAT_TNCL:
+ ret_val = ioread32be(&regs->tncl);
+ break;
+ case E_DTSEC_STAT_TDRP:
+ ret_val = ioread32be(&regs->tdrp);
+ break;
+ default:
+ ret_val = 0;
+ }
+
+ return ret_val;
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_dtsec_mii_acc.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_dtsec_mii_acc.c
new file mode 100644
index 0000000..8819f8f
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_dtsec_mii_acc.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2008-2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "common/general.h"
+#include "fsl_fman_dtsec_mii_acc.h"
+
+
+/**
+ * dtsec_mii_get_div() - calculates the value of the dtsec mii divider
+ * @dtsec_freq: dtsec clock frequency (in Mhz)
+ *
+ * This function calculates the dtsec mii clock divider that determines
+ * the MII MDC clock. MII MDC clock will be set to work in the range
+ * of 1.5 to 2.5Mhz
+ * The output of this function is the value of MIIMCFG[MgmtClk] which
+ * implicitly determines the divider value.
+ * Note: the dTSEC system clock is equal to 1/2 of the FMan clock.
+ *
+ * The table below which reflects dtsec_mii_get_div() functionality
+ * shows the relations among dtsec_freq, MgmtClk, actual divider
+ * and the MII frequency:
+ *
+ * dtsec freq MgmtClk div MII freq Mhz
+ * [0.....80] 1 (1/4)(1/8) [0 to 2.5]
+ * [81...120] 2 (1/6)(1/8) [1.6 to 2.5]
+ * [121..160] 3 (1/8)(1/8) [1.8 to 2.5]
+ * [161..200] 4 (1/10)(1/8) [2.0 to 2.5]
+ * [201..280] 5 (1/14)(1/8) [1.8 to 2.5]
+ * [281..400] 6 (1/20)(1/8) [1.1 to 2.5]
+ * [401..560] 7 (1/28)(1/8) [1.8 to 2.5]
+ * [560..frq] 7 (1/28)(1/8) [frq/224]
+ *
+ * Returns: the MIIMCFG[MgmtClk] appropriate value
+ */
+
+static uint8_t dtsec_mii_get_div(uint16_t dtsec_freq)
+{
+ uint16_t mgmt_clk;
+
+ if (dtsec_freq < 80) mgmt_clk = 1;
+ else if (dtsec_freq < 120) mgmt_clk = 2;
+ else if (dtsec_freq < 160) mgmt_clk = 3;
+ else if (dtsec_freq < 200) mgmt_clk = 4;
+ else if (dtsec_freq < 280) mgmt_clk = 5;
+ else if (dtsec_freq < 400) mgmt_clk = 6;
+ else mgmt_clk = 7;
+
+ return (uint8_t)mgmt_clk;
+}
+
+void fman_dtsec_mii_reset(struct dtsec_mii_reg *regs)
+{
+ /* Reset the management interface */
+ iowrite32be(ioread32be(&regs->miimcfg) | MIIMCFG_RESET_MGMT,
+ &regs->miimcfg);
+ iowrite32be(ioread32be(&regs->miimcfg) & ~MIIMCFG_RESET_MGMT,
+ &regs->miimcfg);
+}
+
+
+int fman_dtsec_mii_write_reg(struct dtsec_mii_reg *regs, uint8_t addr,
+ uint8_t reg, uint16_t data, uint16_t dtsec_freq)
+{
+ uint32_t tmp;
+
+ /* Setup the MII Mgmt clock speed */
+ iowrite32be((uint32_t)dtsec_mii_get_div(dtsec_freq), &regs->miimcfg);
+ wmb();
+
+ /* Stop the MII management read cycle */
+ iowrite32be(0, &regs->miimcom);
+ /* Dummy read to make sure MIIMCOM is written */
+ tmp = ioread32be(&regs->miimcom);
+ wmb();
+
+ /* Setting up MII Management Address Register */
+ tmp = (uint32_t)((addr << MIIMADD_PHY_ADDR_SHIFT) | reg);
+ iowrite32be(tmp, &regs->miimadd);
+ wmb();
+
+ /* Setting up MII Management Control Register with data */
+ iowrite32be((uint32_t)data, &regs->miimcon);
+ /* Dummy read to make sure MIIMCON is written */
+ tmp = ioread32be(&regs->miimcon);
+ wmb();
+
+ /* Wait until MII management write is complete */
+ /* todo: a timeout could be useful here */
+ while ((ioread32be(&regs->miimind)) & MIIMIND_BUSY)
+ /* busy wait */;
+
+ return 0;
+}
+
+int fman_dtsec_mii_read_reg(struct dtsec_mii_reg *regs, uint8_t addr,
+ uint8_t reg, uint16_t *data, uint16_t dtsec_freq)
+{
+ uint32_t tmp;
+
+ /* Setup the MII Mgmt clock speed */
+ iowrite32be((uint32_t)dtsec_mii_get_div(dtsec_freq), &regs->miimcfg);
+ wmb();
+
+ /* Setting up the MII Management Address Register */
+ tmp = (uint32_t)((addr << MIIMADD_PHY_ADDR_SHIFT) | reg);
+ iowrite32be(tmp, &regs->miimadd);
+ wmb();
+
+ /* Perform an MII management read cycle */
+ iowrite32be(MIIMCOM_READ_CYCLE, &regs->miimcom);
+ /* Dummy read to make sure MIIMCOM is written */
+ tmp = ioread32be(&regs->miimcom);
+ wmb();
+
+ /* Wait until MII management read is complete */
+ /* todo: a timeout could be useful here */
+ while ((ioread32be(&regs->miimind)) & MIIMIND_BUSY)
+ /* busy wait */;
+
+ /* Read MII management status */
+ *data = (uint16_t)ioread32be(&regs->miimstat);
+ wmb();
+
+ iowrite32be(0, &regs->miimcom);
+ /* Dummy read to make sure MIIMCOM is written */
+ tmp = ioread32be(&regs->miimcom);
+
+ if (*data == 0xffff)
+ return -ENXIO;
+
+ return 0;
+}
+
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_memac.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_memac.c
new file mode 100644
index 0000000..1fcb1ee
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_memac.c
@@ -0,0 +1,504 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "fsl_fman_memac.h"
+
+
+uint32_t fman_memac_get_event(struct memac_regs *regs, uint32_t ev_mask)
+{
+ return ioread32be(&regs->ievent) & ev_mask;
+}
+
+uint32_t fman_memac_get_interrupt_mask(struct memac_regs *regs)
+{
+ return ioread32be(&regs->imask);
+}
+
+void fman_memac_ack_event(struct memac_regs *regs, uint32_t ev_mask)
+{
+ iowrite32be(ev_mask, &regs->ievent);
+}
+
+void fman_memac_set_promiscuous(struct memac_regs *regs, bool val)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->command_config);
+
+ if (val)
+ tmp |= CMD_CFG_PROMIS_EN;
+ else
+ tmp &= ~CMD_CFG_PROMIS_EN;
+
+ iowrite32be(tmp, &regs->command_config);
+}
+
+void fman_memac_clear_addr_in_paddr(struct memac_regs *regs,
+ uint8_t paddr_num)
+{
+ if (paddr_num == 0) {
+ iowrite32be(0, &regs->mac_addr0.mac_addr_l);
+ iowrite32be(0, &regs->mac_addr0.mac_addr_u);
+ } else {
+ iowrite32be(0x0, &regs->mac_addr[paddr_num - 1].mac_addr_l);
+ iowrite32be(0x0, &regs->mac_addr[paddr_num - 1].mac_addr_u);
+ }
+}
+
+void fman_memac_add_addr_in_paddr(struct memac_regs *regs,
+ uint8_t *adr,
+ uint8_t paddr_num)
+{
+ uint32_t tmp0, tmp1;
+
+ tmp0 = (uint32_t)(adr[0] |
+ adr[1] << 8 |
+ adr[2] << 16 |
+ adr[3] << 24);
+ tmp1 = (uint32_t)(adr[4] | adr[5] << 8);
+
+ if (paddr_num == 0) {
+ iowrite32be(tmp0, &regs->mac_addr0.mac_addr_l);
+ iowrite32be(tmp1, &regs->mac_addr0.mac_addr_u);
+ } else {
+ iowrite32be(tmp0, &regs->mac_addr[paddr_num-1].mac_addr_l);
+ iowrite32be(tmp1, &regs->mac_addr[paddr_num-1].mac_addr_u);
+ }
+}
+
+void fman_memac_enable(struct memac_regs *regs, bool apply_rx, bool apply_tx)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->command_config);
+
+ if (apply_rx)
+ tmp |= CMD_CFG_RX_EN;
+
+ if (apply_tx)
+ tmp |= CMD_CFG_TX_EN;
+
+ iowrite32be(tmp, &regs->command_config);
+}
+
+void fman_memac_disable(struct memac_regs *regs, bool apply_rx, bool apply_tx)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->command_config);
+
+ if (apply_rx)
+ tmp &= ~CMD_CFG_RX_EN;
+
+ if (apply_tx)
+ tmp &= ~CMD_CFG_TX_EN;
+
+ iowrite32be(tmp, &regs->command_config);
+}
+
+void fman_memac_reset_stat(struct memac_regs *regs)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->statn_config);
+
+ tmp |= STATS_CFG_CLR;
+
+ iowrite32be(tmp, &regs->statn_config);
+
+ while (ioread32be(&regs->statn_config) & STATS_CFG_CLR);
+}
+
+void fman_memac_reset(struct memac_regs *regs)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->command_config);
+
+ tmp |= CMD_CFG_SW_RESET;
+
+ iowrite32be(tmp, &regs->command_config);
+
+ while (ioread32be(&regs->command_config) & CMD_CFG_SW_RESET);
+}
+
+int fman_memac_init(struct memac_regs *regs,
+ struct memac_cfg *cfg,
+ enum enet_interface enet_interface,
+ enum enet_speed enet_speed,
+ uint32_t exceptions)
+{
+ uint32_t tmp;
+
+ /* Config */
+ tmp = 0;
+ if (cfg->wan_mode_enable)
+ tmp |= CMD_CFG_WAN_MODE;
+ if (cfg->promiscuous_mode_enable)
+ tmp |= CMD_CFG_PROMIS_EN;
+ if (cfg->pause_forward_enable)
+ tmp |= CMD_CFG_PAUSE_FWD;
+ if (cfg->pause_ignore)
+ tmp |= CMD_CFG_PAUSE_IGNORE;
+ if (cfg->tx_addr_ins_enable)
+ tmp |= CMD_CFG_TX_ADDR_INS;
+ if (cfg->loopback_enable)
+ tmp |= CMD_CFG_LOOPBACK_EN;
+ if (cfg->cmd_frame_enable)
+ tmp |= CMD_CFG_CNT_FRM_EN;
+ if (cfg->send_idle_enable)
+ tmp |= CMD_CFG_SEND_IDLE;
+ if (cfg->no_length_check_enable)
+ tmp |= CMD_CFG_NO_LEN_CHK;
+ if (cfg->rx_sfd_any)
+ tmp |= CMD_CFG_SFD_ANY;
+ if (cfg->pad_enable)
+ tmp |= CMD_CFG_TX_PAD_EN;
+ if (cfg->wake_on_lan)
+ tmp |= CMD_CFG_MG;
+
+ tmp |= CMD_CFG_CRC_FWD;
+
+ iowrite32be(tmp, &regs->command_config);
+
+ /* Max Frame Length */
+ iowrite32be((uint32_t)cfg->max_frame_length, &regs->maxfrm);
+
+ /* Pause Time */
+ iowrite32be((uint32_t)cfg->pause_quanta, &regs->pause_quanta[0]);
+ iowrite32be((uint32_t)0, &regs->pause_thresh[0]);
+
+ /* IF_MODE */
+ tmp = 0;
+ switch (enet_interface) {
+ case E_ENET_IF_XGMII:
+ case E_ENET_IF_XFI:
+ tmp |= IF_MODE_XGMII;
+ break;
+ default:
+ tmp |= IF_MODE_GMII;
+ if (enet_interface == E_ENET_IF_RGMII && !cfg->loopback_enable)
+ tmp |= IF_MODE_RGMII | IF_MODE_RGMII_AUTO;
+ }
+ iowrite32be(tmp, &regs->if_mode);
+
+ /* TX_FIFO_SECTIONS */
+ tmp = 0;
+ if (enet_interface == E_ENET_IF_XGMII ||
+ enet_interface == E_ENET_IF_XFI) {
+ tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_10G |
+ TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G);
+ } else {
+ tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_1G |
+ TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G);
+ }
+ iowrite32be(tmp, &regs->tx_fifo_sections);
+
+ /* clear all pending events and set-up interrupts */
+ fman_memac_ack_event(regs, 0xffffffff);
+ fman_memac_set_exception(regs, exceptions, TRUE);
+
+ return 0;
+}
+
+void fman_memac_set_exception(struct memac_regs *regs, uint32_t val, bool enable)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->imask);
+ if (enable)
+ tmp |= val;
+ else
+ tmp &= ~val;
+
+ iowrite32be(tmp, &regs->imask);
+}
+
+void fman_memac_reset_filter_table(struct memac_regs *regs)
+{
+ uint32_t i;
+ for (i = 0; i < 64; i++)
+ iowrite32be(i & ~HASH_CTRL_MCAST_EN, &regs->hashtable_ctrl);
+}
+
+void fman_memac_set_hash_table_entry(struct memac_regs *regs, uint32_t crc)
+{
+ iowrite32be(crc | HASH_CTRL_MCAST_EN, &regs->hashtable_ctrl);
+}
+
+void fman_memac_set_hash_table(struct memac_regs *regs, uint32_t val)
+{
+ iowrite32be(val, &regs->hashtable_ctrl);
+}
+
+uint16_t fman_memac_get_max_frame_len(struct memac_regs *regs)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->maxfrm);
+
+ return(uint16_t)tmp;
+}
+
+
+void fman_memac_set_tx_pause_frames(struct memac_regs *regs,
+ uint8_t priority,
+ uint16_t pause_time,
+ uint16_t thresh_time)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->tx_fifo_sections);
+
+ if (priority == 0xff) {
+ GET_TX_EMPTY_DEFAULT_VALUE(tmp);
+ iowrite32be(tmp, &regs->tx_fifo_sections);
+
+ tmp &= ~CMD_CFG_PFC_MODE;
+ priority = 0;
+ } else {
+ GET_TX_EMPTY_PFC_VALUE(tmp);
+ iowrite32be(tmp, &regs->tx_fifo_sections);
+
+ tmp = ioread32be(&regs->command_config);
+ tmp |= CMD_CFG_PFC_MODE;
+ }
+
+ iowrite32be(tmp, &regs->command_config);
+
+ tmp = ioread32be(&regs->pause_quanta[priority / 2]);
+ if (priority % 2)
+ tmp &= 0x0000FFFF;
+ else
+ tmp &= 0xFFFF0000;
+ tmp |= ((uint32_t)pause_time << (16 * (priority % 2)));
+ iowrite32be(tmp, &regs->pause_quanta[priority / 2]);
+
+ tmp = ioread32be(&regs->pause_thresh[priority / 2]);
+ if (priority % 2)
+ tmp &= 0x0000FFFF;
+ else
+ tmp &= 0xFFFF0000;
+ tmp |= ((uint32_t)thresh_time<<(16 * (priority % 2)));
+ iowrite32be(tmp, &regs->pause_thresh[priority / 2]);
+}
+
+void fman_memac_set_rx_ignore_pause_frames(struct memac_regs *regs,bool enable)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->command_config);
+ if (enable)
+ tmp |= CMD_CFG_PAUSE_IGNORE;
+ else
+ tmp &= ~CMD_CFG_PAUSE_IGNORE;
+
+ iowrite32be(tmp, &regs->command_config);
+}
+
+void fman_memac_set_wol(struct memac_regs *regs, bool enable)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->command_config);
+
+ if (enable)
+ tmp |= CMD_CFG_MG;
+ else
+ tmp &= ~CMD_CFG_MG;
+
+ iowrite32be(tmp, &regs->command_config);
+}
+
+#define GET_MEMAC_CNTR_64(bn) \
+ (ioread32be(&regs->bn ## _l) | \
+ ((uint64_t)ioread32be(&regs->bn ## _u) << 32))
+
+uint64_t fman_memac_get_counter(struct memac_regs *regs,
+ enum memac_counters reg_name)
+{
+ uint64_t ret_val;
+
+ switch (reg_name) {
+ case E_MEMAC_COUNTER_R64:
+ ret_val = GET_MEMAC_CNTR_64(r64);
+ break;
+ case E_MEMAC_COUNTER_R127:
+ ret_val = GET_MEMAC_CNTR_64(r127);
+ break;
+ case E_MEMAC_COUNTER_R255:
+ ret_val = GET_MEMAC_CNTR_64(r255);
+ break;
+ case E_MEMAC_COUNTER_R511:
+ ret_val = GET_MEMAC_CNTR_64(r511);
+ break;
+ case E_MEMAC_COUNTER_R1023:
+ ret_val = GET_MEMAC_CNTR_64(r1023);
+ break;
+ case E_MEMAC_COUNTER_R1518:
+ ret_val = GET_MEMAC_CNTR_64(r1518);
+ break;
+ case E_MEMAC_COUNTER_R1519X:
+ ret_val = GET_MEMAC_CNTR_64(r1519x);
+ break;
+ case E_MEMAC_COUNTER_RFRG:
+ ret_val = GET_MEMAC_CNTR_64(rfrg);
+ break;
+ case E_MEMAC_COUNTER_RJBR:
+ ret_val = GET_MEMAC_CNTR_64(rjbr);
+ break;
+ case E_MEMAC_COUNTER_RDRP:
+ ret_val = GET_MEMAC_CNTR_64(rdrp);
+ break;
+ case E_MEMAC_COUNTER_RALN:
+ ret_val = GET_MEMAC_CNTR_64(raln);
+ break;
+ case E_MEMAC_COUNTER_TUND:
+ ret_val = GET_MEMAC_CNTR_64(tund);
+ break;
+ case E_MEMAC_COUNTER_ROVR:
+ ret_val = GET_MEMAC_CNTR_64(rovr);
+ break;
+ case E_MEMAC_COUNTER_RXPF:
+ ret_val = GET_MEMAC_CNTR_64(rxpf);
+ break;
+ case E_MEMAC_COUNTER_TXPF:
+ ret_val = GET_MEMAC_CNTR_64(txpf);
+ break;
+ case E_MEMAC_COUNTER_ROCT:
+ ret_val = GET_MEMAC_CNTR_64(roct);
+ break;
+ case E_MEMAC_COUNTER_RMCA:
+ ret_val = GET_MEMAC_CNTR_64(rmca);
+ break;
+ case E_MEMAC_COUNTER_RBCA:
+ ret_val = GET_MEMAC_CNTR_64(rbca);
+ break;
+ case E_MEMAC_COUNTER_RPKT:
+ ret_val = GET_MEMAC_CNTR_64(rpkt);
+ break;
+ case E_MEMAC_COUNTER_RUCA:
+ ret_val = GET_MEMAC_CNTR_64(ruca);
+ break;
+ case E_MEMAC_COUNTER_RERR:
+ ret_val = GET_MEMAC_CNTR_64(rerr);
+ break;
+ case E_MEMAC_COUNTER_TOCT:
+ ret_val = GET_MEMAC_CNTR_64(toct);
+ break;
+ case E_MEMAC_COUNTER_TMCA:
+ ret_val = GET_MEMAC_CNTR_64(tmca);
+ break;
+ case E_MEMAC_COUNTER_TBCA:
+ ret_val = GET_MEMAC_CNTR_64(tbca);
+ break;
+ case E_MEMAC_COUNTER_TUCA:
+ ret_val = GET_MEMAC_CNTR_64(tuca);
+ break;
+ case E_MEMAC_COUNTER_TERR:
+ ret_val = GET_MEMAC_CNTR_64(terr);
+ break;
+ default:
+ ret_val = 0;
+ }
+
+ return ret_val;
+}
+
+void fman_memac_adjust_link(struct memac_regs *regs,
+ enum enet_interface iface_mode,
+ enum enet_speed speed, bool full_dx)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->if_mode);
+
+ if (full_dx)
+ tmp &= ~IF_MODE_HD;
+ else
+ tmp |= IF_MODE_HD;
+
+ if (iface_mode == E_ENET_IF_RGMII) {
+ /* Configure RGMII in manual mode */
+ tmp &= ~IF_MODE_RGMII_AUTO;
+ tmp &= ~IF_MODE_RGMII_SP_MASK;
+
+ if (full_dx)
+ tmp |= IF_MODE_RGMII_FD;
+ else
+ tmp &= ~IF_MODE_RGMII_FD;
+
+ switch (speed) {
+ case E_ENET_SPEED_1000:
+ tmp |= IF_MODE_RGMII_1000;
+ break;
+ case E_ENET_SPEED_100:
+ tmp |= IF_MODE_RGMII_100;
+ break;
+ case E_ENET_SPEED_10:
+ tmp |= IF_MODE_RGMII_10;
+ break;
+ default:
+ break;
+ }
+ }
+
+ iowrite32be(tmp, &regs->if_mode);
+}
+
+void fman_memac_defconfig(struct memac_cfg *cfg)
+{
+ cfg->reset_on_init = FALSE;
+ cfg->wan_mode_enable = FALSE;
+ cfg->promiscuous_mode_enable = FALSE;
+ cfg->pause_forward_enable = FALSE;
+ cfg->pause_ignore = FALSE;
+ cfg->tx_addr_ins_enable = FALSE;
+ cfg->loopback_enable = FALSE;
+ cfg->cmd_frame_enable = FALSE;
+ cfg->rx_error_discard = FALSE;
+ cfg->send_idle_enable = FALSE;
+ cfg->no_length_check_enable = TRUE;
+ cfg->lgth_check_nostdr = FALSE;
+ cfg->time_stamp_enable = FALSE;
+ cfg->tx_ipg_length = DEFAULT_TX_IPG_LENGTH;
+ cfg->max_frame_length = DEFAULT_FRAME_LENGTH;
+ cfg->pause_quanta = DEFAULT_PAUSE_QUANTA;
+ cfg->pad_enable = TRUE;
+ cfg->phy_tx_ena_on = FALSE;
+ cfg->rx_sfd_any = FALSE;
+ cfg->rx_pbl_fwd = FALSE;
+ cfg->tx_pbl_fwd = FALSE;
+ cfg->debug_mode = FALSE;
+ cfg->wake_on_lan = FALSE;
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_memac_mii_acc.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_memac_mii_acc.c
new file mode 100755
index 0000000..ccda11e
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_memac_mii_acc.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2008-2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "fsl_fman_memac_mii_acc.h"
+
+static void write_phy_reg_10g(struct memac_mii_access_mem_map *mii_regs,
+ uint8_t phy_addr, uint8_t reg, uint16_t data)
+{
+ uint32_t tmp_reg;
+
+ tmp_reg = ioread32be(&mii_regs->mdio_cfg);
+ /* Leave only MDIO_CLK_DIV bits set on */
+ tmp_reg &= MDIO_CFG_CLK_DIV_MASK;
+ /* Set maximum MDIO_HOLD value to allow phy to see
+ change of data signal */
+ tmp_reg |= MDIO_CFG_HOLD_MASK;
+ /* Add 10G interface mode */
+ tmp_reg |= MDIO_CFG_ENC45;
+ iowrite32be(tmp_reg, &mii_regs->mdio_cfg);
+
+ /* Wait for command completion */
+ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+ udelay(1);
+
+ /* Specify phy and register to be accessed */
+ iowrite32be(phy_addr, &mii_regs->mdio_ctrl);
+ iowrite32be(reg, &mii_regs->mdio_addr);
+ wmb();
+
+ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+ udelay(1);
+
+ /* Write data */
+ iowrite32be(data, &mii_regs->mdio_data);
+ wmb();
+
+ /* Wait for write transaction end */
+ while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY)
+ udelay(1);
+}
+
+static uint32_t read_phy_reg_10g(struct memac_mii_access_mem_map *mii_regs,
+ uint8_t phy_addr, uint8_t reg, uint16_t *data)
+{
+ uint32_t tmp_reg;
+
+ tmp_reg = ioread32be(&mii_regs->mdio_cfg);
+ /* Leave only MDIO_CLK_DIV bits set on */
+ tmp_reg &= MDIO_CFG_CLK_DIV_MASK;
+ /* Set maximum MDIO_HOLD value to allow phy to see
+ change of data signal */
+ tmp_reg |= MDIO_CFG_HOLD_MASK;
+ /* Add 10G interface mode */
+ tmp_reg |= MDIO_CFG_ENC45;
+ iowrite32be(tmp_reg, &mii_regs->mdio_cfg);
+
+ /* Wait for command completion */
+ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+ udelay(1);
+
+ /* Specify phy and register to be accessed */
+ iowrite32be(phy_addr, &mii_regs->mdio_ctrl);
+ iowrite32be(reg, &mii_regs->mdio_addr);
+ wmb();
+
+ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+ udelay(1);
+
+ /* Read cycle */
+ tmp_reg = phy_addr;
+ tmp_reg |= MDIO_CTL_READ;
+ iowrite32be(tmp_reg, &mii_regs->mdio_ctrl);
+ wmb();
+
+ /* Wait for data to be available */
+ while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY)
+ udelay(1);
+
+ *data = (uint16_t)ioread32be(&mii_regs->mdio_data);
+
+ /* Check if there was an error */
+ return ioread32be(&mii_regs->mdio_cfg);
+}
+
+static void write_phy_reg_1g(struct memac_mii_access_mem_map *mii_regs,
+ uint8_t phy_addr, uint8_t reg, uint16_t data)
+{
+ uint32_t tmp_reg;
+
+ /* Leave only MDIO_CLK_DIV and MDIO_HOLD bits set on */
+ tmp_reg = ioread32be(&mii_regs->mdio_cfg);
+ tmp_reg &= (MDIO_CFG_CLK_DIV_MASK | MDIO_CFG_HOLD_MASK);
+ iowrite32be(tmp_reg, &mii_regs->mdio_cfg);
+
+ /* Wait for command completion */
+ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+ udelay(1);
+
+ /* Write transaction */
+ tmp_reg = (phy_addr << MDIO_CTL_PHY_ADDR_SHIFT);
+ tmp_reg |= reg;
+ iowrite32be(tmp_reg, &mii_regs->mdio_ctrl);
+
+ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+ udelay(1);
+
+ iowrite32be(data, &mii_regs->mdio_data);
+
+ wmb();
+
+ /* Wait for write transaction to end */
+ while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY)
+ udelay(1);
+}
+
+static uint32_t read_phy_reg_1g(struct memac_mii_access_mem_map *mii_regs,
+ uint8_t phy_addr, uint8_t reg, uint16_t *data)
+{
+ uint32_t tmp_reg;
+
+ /* Leave only MDIO_CLK_DIV and MDIO_HOLD bits set on */
+ tmp_reg = ioread32be(&mii_regs->mdio_cfg);
+ tmp_reg &= (MDIO_CFG_CLK_DIV_MASK | MDIO_CFG_HOLD_MASK);
+ iowrite32be(tmp_reg, &mii_regs->mdio_cfg);
+
+ /* Wait for command completion */
+ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+ udelay(1);
+
+ /* Read transaction */
+ tmp_reg = (phy_addr << MDIO_CTL_PHY_ADDR_SHIFT);
+ tmp_reg |= reg;
+ tmp_reg |= MDIO_CTL_READ;
+ iowrite32be(tmp_reg, &mii_regs->mdio_ctrl);
+
+ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+ udelay(1);
+
+ /* Wait for data to be available */
+ while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY)
+ udelay(1);
+
+ *data = (uint16_t)ioread32be(&mii_regs->mdio_data);
+
+ /* Check error */
+ return ioread32be(&mii_regs->mdio_cfg);
+}
+
+/*****************************************************************************/
+int fman_memac_mii_write_phy_reg(struct memac_mii_access_mem_map *mii_regs,
+ uint8_t phy_addr, uint8_t reg, uint16_t data,
+ enum enet_speed enet_speed)
+{
+ /* Figure out interface type - 10G vs 1G.
+ In 10G interface both phy_addr and devAddr present. */
+ if (enet_speed == E_ENET_SPEED_10000)
+ write_phy_reg_10g(mii_regs, phy_addr, reg, data);
+ else
+ write_phy_reg_1g(mii_regs, phy_addr, reg, data);
+
+ return 0;
+}
+
+/*****************************************************************************/
+int fman_memac_mii_read_phy_reg(struct memac_mii_access_mem_map *mii_regs,
+ uint8_t phy_addr, uint8_t reg, uint16_t *data,
+ enum enet_speed enet_speed)
+{
+ uint32_t ans;
+ /* Figure out interface type - 10G vs 1G.
+ In 10G interface both phy_addr and devAddr present. */
+ if (enet_speed == E_ENET_SPEED_10000)
+ ans = read_phy_reg_10g(mii_regs, phy_addr, reg, data);
+ else
+ ans = read_phy_reg_1g(mii_regs, phy_addr, reg, data);
+
+ if (ans & MDIO_CFG_READ_ERR)
+ return -EINVAL;
+ return 0;
+}
+
+/* ......................................................................... */
+
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_tgec.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_tgec.c
new file mode 100644
index 0000000..fff9d5d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/fman_tgec.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "fsl_fman_tgec.h"
+
+
+void fman_tgec_set_mac_address(struct tgec_regs *regs, uint8_t *adr)
+{
+ uint32_t tmp0, tmp1;
+
+ tmp0 = (uint32_t)(adr[0] |
+ adr[1] << 8 |
+ adr[2] << 16 |
+ adr[3] << 24);
+ tmp1 = (uint32_t)(adr[4] | adr[5] << 8);
+ iowrite32be(tmp0, &regs->mac_addr_0);
+ iowrite32be(tmp1, &regs->mac_addr_1);
+}
+
+void fman_tgec_reset_stat(struct tgec_regs *regs)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->command_config);
+
+ tmp |= CMD_CFG_STAT_CLR;
+
+ iowrite32be(tmp, &regs->command_config);
+
+ while (ioread32be(&regs->command_config) & CMD_CFG_STAT_CLR) ;
+}
+
+#define GET_TGEC_CNTR_64(bn) \
+ (((uint64_t)ioread32be(&regs->bn ## _u) << 32) | \
+ ioread32be(&regs->bn ## _l))
+
+uint64_t fman_tgec_get_counter(struct tgec_regs *regs, enum tgec_counters reg_name)
+{
+ uint64_t ret_val;
+
+ switch (reg_name) {
+ case E_TGEC_COUNTER_R64:
+ ret_val = GET_TGEC_CNTR_64(r64);
+ break;
+ case E_TGEC_COUNTER_R127:
+ ret_val = GET_TGEC_CNTR_64(r127);
+ break;
+ case E_TGEC_COUNTER_R255:
+ ret_val = GET_TGEC_CNTR_64(r255);
+ break;
+ case E_TGEC_COUNTER_R511:
+ ret_val = GET_TGEC_CNTR_64(r511);
+ break;
+ case E_TGEC_COUNTER_R1023:
+ ret_val = GET_TGEC_CNTR_64(r1023);
+ break;
+ case E_TGEC_COUNTER_R1518:
+ ret_val = GET_TGEC_CNTR_64(r1518);
+ break;
+ case E_TGEC_COUNTER_R1519X:
+ ret_val = GET_TGEC_CNTR_64(r1519x);
+ break;
+ case E_TGEC_COUNTER_TRFRG:
+ ret_val = GET_TGEC_CNTR_64(trfrg);
+ break;
+ case E_TGEC_COUNTER_TRJBR:
+ ret_val = GET_TGEC_CNTR_64(trjbr);
+ break;
+ case E_TGEC_COUNTER_RDRP:
+ ret_val = GET_TGEC_CNTR_64(rdrp);
+ break;
+ case E_TGEC_COUNTER_RALN:
+ ret_val = GET_TGEC_CNTR_64(raln);
+ break;
+ case E_TGEC_COUNTER_TRUND:
+ ret_val = GET_TGEC_CNTR_64(trund);
+ break;
+ case E_TGEC_COUNTER_TROVR:
+ ret_val = GET_TGEC_CNTR_64(trovr);
+ break;
+ case E_TGEC_COUNTER_RXPF:
+ ret_val = GET_TGEC_CNTR_64(rxpf);
+ break;
+ case E_TGEC_COUNTER_TXPF:
+ ret_val = GET_TGEC_CNTR_64(txpf);
+ break;
+ case E_TGEC_COUNTER_ROCT:
+ ret_val = GET_TGEC_CNTR_64(roct);
+ break;
+ case E_TGEC_COUNTER_RMCA:
+ ret_val = GET_TGEC_CNTR_64(rmca);
+ break;
+ case E_TGEC_COUNTER_RBCA:
+ ret_val = GET_TGEC_CNTR_64(rbca);
+ break;
+ case E_TGEC_COUNTER_RPKT:
+ ret_val = GET_TGEC_CNTR_64(rpkt);
+ break;
+ case E_TGEC_COUNTER_RUCA:
+ ret_val = GET_TGEC_CNTR_64(ruca);
+ break;
+ case E_TGEC_COUNTER_RERR:
+ ret_val = GET_TGEC_CNTR_64(rerr);
+ break;
+ case E_TGEC_COUNTER_TOCT:
+ ret_val = GET_TGEC_CNTR_64(toct);
+ break;
+ case E_TGEC_COUNTER_TMCA:
+ ret_val = GET_TGEC_CNTR_64(tmca);
+ break;
+ case E_TGEC_COUNTER_TBCA:
+ ret_val = GET_TGEC_CNTR_64(tbca);
+ break;
+ case E_TGEC_COUNTER_TUCA:
+ ret_val = GET_TGEC_CNTR_64(tuca);
+ break;
+ case E_TGEC_COUNTER_TERR:
+ ret_val = GET_TGEC_CNTR_64(terr);
+ break;
+ default:
+ ret_val = 0;
+ }
+
+ return ret_val;
+}
+
+void fman_tgec_enable(struct tgec_regs *regs, bool apply_rx, bool apply_tx)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->command_config);
+ if (apply_rx)
+ tmp |= CMD_CFG_RX_EN;
+ if (apply_tx)
+ tmp |= CMD_CFG_TX_EN;
+ iowrite32be(tmp, &regs->command_config);
+}
+
+void fman_tgec_disable(struct tgec_regs *regs, bool apply_rx, bool apply_tx)
+{
+ uint32_t tmp_reg_32;
+
+ tmp_reg_32 = ioread32be(&regs->command_config);
+ if (apply_rx)
+ tmp_reg_32 &= ~CMD_CFG_RX_EN;
+ if (apply_tx)
+ tmp_reg_32 &= ~CMD_CFG_TX_EN;
+ iowrite32be(tmp_reg_32, &regs->command_config);
+}
+
+void fman_tgec_set_promiscuous(struct tgec_regs *regs, bool val)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->command_config);
+ if (val)
+ tmp |= CMD_CFG_PROMIS_EN;
+ else
+ tmp &= ~CMD_CFG_PROMIS_EN;
+ iowrite32be(tmp, &regs->command_config);
+}
+
+void fman_tgec_reset_filter_table(struct tgec_regs *regs)
+{
+ uint32_t i;
+ for (i = 0; i < 512; i++)
+ iowrite32be(i & ~TGEC_HASH_MCAST_EN, &regs->hashtable_ctrl);
+}
+
+void fman_tgec_set_hash_table_entry(struct tgec_regs *regs, uint32_t crc)
+{
+ uint32_t hash = (crc >> TGEC_HASH_MCAST_SHIFT) & TGEC_HASH_ADR_MSK; /* Take 9 MSB bits */
+ iowrite32be(hash | TGEC_HASH_MCAST_EN, &regs->hashtable_ctrl);
+}
+
+void fman_tgec_set_hash_table(struct tgec_regs *regs, uint32_t value)
+{
+ iowrite32be(value, &regs->hashtable_ctrl);
+}
+
+void fman_tgec_set_tx_pause_frames(struct tgec_regs *regs, uint16_t pause_time)
+{
+ iowrite32be((uint32_t)pause_time, &regs->pause_quant);
+}
+
+void fman_tgec_set_rx_ignore_pause_frames(struct tgec_regs *regs, bool en)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->command_config);
+ if (en)
+ tmp |= CMD_CFG_PAUSE_IGNORE;
+ else
+ tmp &= ~CMD_CFG_PAUSE_IGNORE;
+ iowrite32be(tmp, &regs->command_config);
+}
+
+void fman_tgec_enable_1588_time_stamp(struct tgec_regs *regs, bool en)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->command_config);
+ if (en)
+ tmp |= CMD_CFG_EN_TIMESTAMP;
+ else
+ tmp &= ~CMD_CFG_EN_TIMESTAMP;
+ iowrite32be(tmp, &regs->command_config);
+}
+
+uint32_t fman_tgec_get_event(struct tgec_regs *regs, uint32_t ev_mask)
+{
+ return ioread32be(&regs->ievent) & ev_mask;
+}
+
+void fman_tgec_ack_event(struct tgec_regs *regs, uint32_t ev_mask)
+{
+ iowrite32be(ev_mask, &regs->ievent);
+}
+
+uint32_t fman_tgec_get_interrupt_mask(struct tgec_regs *regs)
+{
+ return ioread32be(&regs->imask);
+}
+
+void fman_tgec_add_addr_in_paddr(struct tgec_regs *regs, uint8_t *adr)
+{
+ uint32_t tmp0, tmp1;
+
+ tmp0 = (uint32_t)(adr[0] |
+ adr[1] << 8 |
+ adr[2] << 16 |
+ adr[3] << 24);
+ tmp1 = (uint32_t)(adr[4] | adr[5] << 8);
+ iowrite32be(tmp0, &regs->mac_addr_2);
+ iowrite32be(tmp1, &regs->mac_addr_3);
+}
+
+void fman_tgec_clear_addr_in_paddr(struct tgec_regs *regs)
+{
+ iowrite32be(0, &regs->mac_addr_2);
+ iowrite32be(0, &regs->mac_addr_3);
+}
+
+uint32_t fman_tgec_get_revision(struct tgec_regs *regs)
+{
+ return ioread32be(&regs->tgec_id);
+}
+
+void fman_tgec_enable_interrupt(struct tgec_regs *regs, uint32_t ev_mask)
+{
+ iowrite32be(ioread32be(&regs->imask) | ev_mask, &regs->imask);
+}
+
+void fman_tgec_disable_interrupt(struct tgec_regs *regs, uint32_t ev_mask)
+{
+ iowrite32be(ioread32be(&regs->imask) & ~ev_mask, &regs->imask);
+}
+
+uint16_t fman_tgec_get_max_frame_len(struct tgec_regs *regs)
+{
+ return (uint16_t) ioread32be(&regs->maxfrm);
+}
+
+void fman_tgec_defconfig(struct tgec_cfg *cfg)
+{
+ cfg->wan_mode_enable = DEFAULT_WAN_MODE_ENABLE;
+ cfg->promiscuous_mode_enable = DEFAULT_PROMISCUOUS_MODE_ENABLE;
+ cfg->pause_forward_enable = DEFAULT_PAUSE_FORWARD_ENABLE;
+ cfg->pause_ignore = DEFAULT_PAUSE_IGNORE;
+ cfg->tx_addr_ins_enable = DEFAULT_TX_ADDR_INS_ENABLE;
+ cfg->loopback_enable = DEFAULT_LOOPBACK_ENABLE;
+ cfg->cmd_frame_enable = DEFAULT_CMD_FRAME_ENABLE;
+ cfg->rx_error_discard = DEFAULT_RX_ERROR_DISCARD;
+ cfg->send_idle_enable = DEFAULT_SEND_IDLE_ENABLE;
+ cfg->no_length_check_enable = DEFAULT_NO_LENGTH_CHECK_ENABLE;
+ cfg->lgth_check_nostdr = DEFAULT_LGTH_CHECK_NOSTDR;
+ cfg->time_stamp_enable = DEFAULT_TIME_STAMP_ENABLE;
+ cfg->tx_ipg_length = DEFAULT_TX_IPG_LENGTH;
+ cfg->max_frame_length = DEFAULT_MAX_FRAME_LENGTH;
+ cfg->pause_quant = DEFAULT_PAUSE_QUANT;
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+ cfg->skip_fman11_workaround = FALSE;
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+}
+
+int fman_tgec_init(struct tgec_regs *regs, struct tgec_cfg *cfg,
+ uint32_t exception_mask)
+{
+ uint32_t tmp;
+
+ /* Config */
+ tmp = 0x40; /* CRC forward */
+ if (cfg->wan_mode_enable)
+ tmp |= CMD_CFG_WAN_MODE;
+ if (cfg->promiscuous_mode_enable)
+ tmp |= CMD_CFG_PROMIS_EN;
+ if (cfg->pause_forward_enable)
+ tmp |= CMD_CFG_PAUSE_FWD;
+ if (cfg->pause_ignore)
+ tmp |= CMD_CFG_PAUSE_IGNORE;
+ if (cfg->tx_addr_ins_enable)
+ tmp |= CMD_CFG_TX_ADDR_INS;
+ if (cfg->loopback_enable)
+ tmp |= CMD_CFG_LOOPBACK_EN;
+ if (cfg->cmd_frame_enable)
+ tmp |= CMD_CFG_CMD_FRM_EN;
+ if (cfg->rx_error_discard)
+ tmp |= CMD_CFG_RX_ER_DISC;
+ if (cfg->send_idle_enable)
+ tmp |= CMD_CFG_SEND_IDLE;
+ if (cfg->no_length_check_enable)
+ tmp |= CMD_CFG_NO_LEN_CHK;
+ if (cfg->time_stamp_enable)
+ tmp |= CMD_CFG_EN_TIMESTAMP;
+ iowrite32be(tmp, &regs->command_config);
+
+ /* Max Frame Length */
+ iowrite32be((uint32_t)cfg->max_frame_length, &regs->maxfrm);
+ /* Pause Time */
+ iowrite32be(cfg->pause_quant, &regs->pause_quant);
+
+ /* clear all pending events and set-up interrupts */
+ fman_tgec_ack_event(regs, 0xffffffff);
+ fman_tgec_enable_interrupt(regs, exception_mask);
+
+ return 0;
+}
+
+void fman_tgec_set_erratum_tx_fifo_corruption_10gmac_a007(struct tgec_regs *regs)
+{
+ uint32_t tmp;
+
+ /* restore the default tx ipg Length */
+ tmp = (ioread32be(&regs->tx_ipg_len) & ~TGEC_TX_IPG_LENGTH_MASK) | 12;
+
+ iowrite32be(tmp, &regs->tx_ipg_len);
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac.c
new file mode 100644
index 0000000..9169ff7
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac.c
@@ -0,0 +1,1122 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File memac.c
+
+ @Description FM mEMAC driver
+*//***************************************************************************/
+
+#include "std_ext.h"
+#include "string_ext.h"
+#include "error_ext.h"
+#include "xx_ext.h"
+#include "endian_ext.h"
+#include "debug_ext.h"
+
+#include "fm_common.h"
+#include "memac.h"
+
+
+/*****************************************************************************/
+/* Internal routines */
+/*****************************************************************************/
+
+/* ......................................................................... */
+
+static uint32_t GetMacAddrHashCode(uint64_t ethAddr)
+{
+ uint64_t mask1, mask2;
+ uint32_t xorVal = 0;
+ uint8_t i, j;
+
+ for (i=0; i<6; i++)
+ {
+ mask1 = ethAddr & (uint64_t)0x01;
+ ethAddr >>= 1;
+
+ for (j=0; j<7; j++)
+ {
+ mask2 = ethAddr & (uint64_t)0x01;
+ mask1 ^= mask2;
+ ethAddr >>= 1;
+ }
+
+ xorVal |= (mask1 << (5-i));
+ }
+
+ return xorVal;
+}
+
+/* ......................................................................... */
+
+static void SetupSgmiiInternalPhy(t_Memac *p_Memac, uint8_t phyAddr)
+{
+ uint16_t tmpReg16;
+ e_EnetMode enetMode;
+
+ /* In case the higher MACs are used (i.e. the MACs that should support 10G),
+ speed=10000 is provided for SGMII ports. Temporary modify enet mode
+ to 1G one, so MII functions can work correctly. */
+ enetMode = p_Memac->enetMode;
+ p_Memac->enetMode = MAKE_ENET_MODE(ENET_INTERFACE_FROM_MODE(p_Memac->enetMode), e_ENET_SPEED_1000);
+
+ /* SGMII mode + AN enable */
+ tmpReg16 = PHY_SGMII_IF_MODE_AN | PHY_SGMII_IF_MODE_SGMII;
+ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x14, tmpReg16);
+
+ /* Device ability according to SGMII specification */
+ tmpReg16 = PHY_SGMII_DEV_ABILITY_SGMII;
+ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x4, tmpReg16);
+
+ /* Adjust link timer for SGMII -
+ According to Cisco SGMII specification the timer should be 1.6 ms.
+ The link_timer register is configured in units of the clock.
+ - When running as 1G SGMII, Serdes clock is 125 MHz, so
+ unit = 1 / (125*10^6 Hz) = 8 ns.
+ 1.6 ms in units of 8 ns = 1.6ms / 8ns = 2 * 10^5 = 0x30d40
+ - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so
+ unit = 1 / (312.5*10^6 Hz) = 3.2 ns.
+ 1.6 ms in units of 3.2 ns = 1.6ms / 3.2ns = 5 * 10^5 = 0x7a120.
+ Since link_timer value of 1G SGMII will be too short for 2.5 SGMII,
+ we always set up here a value of 2.5 SGMII. */
+ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x13, 0x0007);
+ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x12, 0xa120);
+
+ /* Restart AN */
+ tmpReg16 = PHY_SGMII_CR_DEF_VAL | PHY_SGMII_CR_RESET_AN;
+ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x0, tmpReg16);
+
+ /* Restore original enet mode */
+ p_Memac->enetMode = enetMode;
+}
+
+/* ......................................................................... */
+
+static void SetupSgmiiInternalPhyBaseX(t_Memac *p_Memac, uint8_t phyAddr)
+{
+ uint16_t tmpReg16;
+ e_EnetMode enetMode;
+
+ /* In case the higher MACs are used (i.e. the MACs that should support 10G),
+ speed=10000 is provided for SGMII ports. Temporary modify enet mode
+ to 1G one, so MII functions can work correctly. */
+ enetMode = p_Memac->enetMode;
+ p_Memac->enetMode = MAKE_ENET_MODE(ENET_INTERFACE_FROM_MODE(p_Memac->enetMode), e_ENET_SPEED_1000);
+
+ /* 1000BaseX mode */
+ tmpReg16 = PHY_SGMII_IF_MODE_1000X;
+ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x14, tmpReg16);
+
+ /* AN Device capability */
+ tmpReg16 = PHY_SGMII_DEV_ABILITY_1000X;
+ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x4, tmpReg16);
+
+ /* Adjust link timer for SGMII -
+ For Serdes 1000BaseX auto-negotiation the timer should be 10 ms.
+ The link_timer register is configured in units of the clock.
+ - When running as 1G SGMII, Serdes clock is 125 MHz, so
+ unit = 1 / (125*10^6 Hz) = 8 ns.
+ 10 ms in units of 8 ns = 10ms / 8ns = 1250000 = 0x1312d0
+ - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so
+ unit = 1 / (312.5*10^6 Hz) = 3.2 ns.
+ 10 ms in units of 3.2 ns = 10ms / 3.2ns = 3125000 = 0x2faf08.
+ Since link_timer value of 1G SGMII will be too short for 2.5 SGMII,
+ we always set up here a value of 2.5 SGMII. */
+ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x13, 0x002f);
+ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x12, 0xaf08);
+
+ /* Restart AN */
+ tmpReg16 = PHY_SGMII_CR_DEF_VAL | PHY_SGMII_CR_RESET_AN;
+ MEMAC_MII_WritePhyReg(p_Memac, phyAddr, 0x0, tmpReg16);
+
+ /* Restore original enet mode */
+ p_Memac->enetMode = enetMode;
+}
+
+/* ......................................................................... */
+
+static t_Error CheckInitParameters(t_Memac *p_Memac)
+{
+ e_FmMacType portType;
+
+ portType = ((ENET_SPEED_FROM_MODE(p_Memac->enetMode) < e_ENET_SPEED_10000) ? e_FM_MAC_1G : e_FM_MAC_10G);
+
+#if (FM_MAX_NUM_OF_10G_MACS > 0)
+ if ((portType == e_FM_MAC_10G) && (p_Memac->macId >= FM_MAX_NUM_OF_10G_MACS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("10G MAC ID must be less than %d", FM_MAX_NUM_OF_10G_MACS));
+#endif /* (FM_MAX_NUM_OF_10G_MACS > 0) */
+
+ if ((portType == e_FM_MAC_1G) && (p_Memac->macId >= FM_MAX_NUM_OF_1G_MACS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("1G MAC ID must be less than %d", FM_MAX_NUM_OF_1G_MACS));
+ if (p_Memac->addr == 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet MAC must have a valid MAC address"));
+ if (!p_Memac->f_Exception)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Uninitialized f_Exception"));
+ if (!p_Memac->f_Event)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Uninitialized f_Event"));
+#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002
+ if (!p_Memac->p_MemacDriverParam->no_length_check_enable)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("LengthCheck!"));
+#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */
+
+ return E_OK;
+}
+
+/* ........................................................................... */
+
+static void MemacErrException(t_Handle h_Memac)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+ uint32_t event, imask;
+
+ event = fman_memac_get_event(p_Memac->p_MemMap, 0xffffffff);
+ imask = fman_memac_get_interrupt_mask(p_Memac->p_MemMap);
+
+ /* Imask include both error and notification/event bits.
+ Leaving only error bits enabled by imask.
+ The imask error bits are shifted by 16 bits offset from
+ their corresponding location in the ievent - hence the >> 16 */
+ event &= ((imask & MEMAC_ALL_ERRS_IMASK) >> 16);
+
+ fman_memac_ack_event(p_Memac->p_MemMap, event);
+
+ if (event & MEMAC_IEVNT_TS_ECC_ER)
+ p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_TS_FIFO_ECC_ERR);
+ if (event & MEMAC_IEVNT_TX_ECC_ER)
+ p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_10G_1TX_ECC_ER);
+ if (event & MEMAC_IEVNT_RX_ECC_ER)
+ p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_10G_RX_ECC_ER);
+}
+
+static void MemacException(t_Handle h_Memac)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+ uint32_t event, imask;
+
+ event = fman_memac_get_event(p_Memac->p_MemMap, 0xffffffff);
+ imask = fman_memac_get_interrupt_mask(p_Memac->p_MemMap);
+
+ /* Imask include both error and notification/event bits.
+ Leaving only error bits enabled by imask.
+ The imask error bits are shifted by 16 bits offset from
+ their corresponding location in the ievent - hence the >> 16 */
+ event &= ((imask & MEMAC_ALL_ERRS_IMASK) >> 16);
+
+ fman_memac_ack_event(p_Memac->p_MemMap, event);
+
+ if (event & MEMAC_IEVNT_MGI)
+ p_Memac->f_Exception(p_Memac->h_App, e_FM_MAC_EX_MAGIC_PACKET_INDICATION);
+}
+
+/* ......................................................................... */
+
+static void FreeInitResources(t_Memac *p_Memac)
+{
+ e_FmMacType portType;
+
+ portType =
+ ((ENET_SPEED_FROM_MODE(p_Memac->enetMode) < e_ENET_SPEED_10000) ? e_FM_MAC_1G : e_FM_MAC_10G);
+
+ if (portType == e_FM_MAC_10G)
+ FmUnregisterIntr(p_Memac->fmMacControllerDriver.h_Fm, e_FM_MOD_10G_MAC, p_Memac->macId, e_FM_INTR_TYPE_ERR);
+ else
+ FmUnregisterIntr(p_Memac->fmMacControllerDriver.h_Fm, e_FM_MOD_1G_MAC, p_Memac->macId, e_FM_INTR_TYPE_ERR);
+
+ /* release the driver's group hash table */
+ FreeHashTable(p_Memac->p_MulticastAddrHash);
+ p_Memac->p_MulticastAddrHash = NULL;
+
+ /* release the driver's individual hash table */
+ FreeHashTable(p_Memac->p_UnicastAddrHash);
+ p_Memac->p_UnicastAddrHash = NULL;
+}
+
+
+/*****************************************************************************/
+/* mEMAC API routines */
+/*****************************************************************************/
+
+/* ......................................................................... */
+
+static t_Error MemacEnable(t_Handle h_Memac, e_CommMode mode)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ fman_memac_enable(p_Memac->p_MemMap, (mode & e_COMM_MODE_RX), (mode & e_COMM_MODE_TX));
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacDisable (t_Handle h_Memac, e_CommMode mode)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ fman_memac_disable(p_Memac->p_MemMap, (mode & e_COMM_MODE_RX), (mode & e_COMM_MODE_TX));
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacSetPromiscuous(t_Handle h_Memac, bool newVal)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ fman_memac_set_promiscuous(p_Memac->p_MemMap, newVal);
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error MemacAdjustLink(t_Handle h_Memac, e_EnetSpeed speed, bool fullDuplex)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ if ((speed >= e_ENET_SPEED_1000) && (!fullDuplex))
+ RETURN_ERROR(MAJOR, E_CONFLICT,
+ ("Ethernet MAC 1G or 10G does not support half-duplex"));
+
+ fman_memac_adjust_link(p_Memac->p_MemMap,
+ (enum enet_interface)ENET_INTERFACE_FROM_MODE(p_Memac->enetMode),
+ (enum enet_speed)speed,
+ fullDuplex);
+ return E_OK;
+}
+
+
+/*****************************************************************************/
+/* Memac Configs modification functions */
+/*****************************************************************************/
+
+/* ......................................................................... */
+
+static t_Error MemacConfigLoopback(t_Handle h_Memac, bool newVal)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ p_Memac->p_MemacDriverParam->loopback_enable = newVal;
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacConfigWan(t_Handle h_Memac, bool newVal)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ p_Memac->p_MemacDriverParam->wan_mode_enable = newVal;
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacConfigMaxFrameLength(t_Handle h_Memac, uint16_t newVal)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ p_Memac->p_MemacDriverParam->max_frame_length = newVal;
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacConfigPad(t_Handle h_Memac, bool newVal)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ p_Memac->p_MemacDriverParam->pad_enable = newVal;
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacConfigLengthCheck(t_Handle h_Memac, bool newVal)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ p_Memac->p_MemacDriverParam->no_length_check_enable = !newVal;
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacConfigException(t_Handle h_Memac, e_FmMacExceptions exception, bool enable)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+ uint32_t bitMask = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ GET_EXCEPTION_FLAG(bitMask, exception);
+ if (bitMask)
+ {
+ if (enable)
+ p_Memac->exceptions |= bitMask;
+ else
+ p_Memac->exceptions &= ~bitMask;
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacConfigResetOnInit(t_Handle h_Memac, bool enable)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ p_Memac->p_MemacDriverParam->reset_on_init = enable;
+
+ return E_OK;
+}
+
+
+/*****************************************************************************/
+/* Memac Run Time API functions */
+/*****************************************************************************/
+
+/* ......................................................................... */
+
+static t_Error MemacSetTxPauseFrames(t_Handle h_Memac,
+ uint8_t priority,
+ uint16_t pauseTime,
+ uint16_t threshTime)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ if (priority != 0xFF)
+ {
+ bool PortConfigured, PreFetchEnabled;
+
+ if (FmGetTnumAgingPeriod(p_Memac->fmMacControllerDriver.h_Fm) == 0)
+ RETURN_ERROR(MAJOR, E_CONFLICT, ("For PFC operation, TNUM aging must be enabled"));
+
+ FmGetPortPreFetchConfiguration(p_Memac->fmMacControllerDriver.h_Fm,
+ p_Memac->fmMacControllerDriver.macId,
+ &PortConfigured,
+ &PreFetchEnabled);
+
+ if ((ENET_SPEED_FROM_MODE(p_Memac->fmMacControllerDriver.enetMode) == e_ENET_SPEED_1000) && !PortConfigured)
+ DBG(INFO, ("For PFC correct operation, prefetch must be configured on the FM Tx PORT"));
+
+ if ((ENET_SPEED_FROM_MODE(p_Memac->fmMacControllerDriver.enetMode) == e_ENET_SPEED_1000) && PortConfigured && !PreFetchEnabled)
+ DBG(WARNING, ("For PFC correct operation, prefetch must be configured on the FM Tx PORT"));
+ }
+
+ fman_memac_set_tx_pause_frames(p_Memac->p_MemMap, priority, pauseTime, threshTime);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacSetTxAutoPauseFrames(t_Handle h_Memac,
+ uint16_t pauseTime)
+{
+ return MemacSetTxPauseFrames(h_Memac, FM_MAC_NO_PFC, pauseTime, 0);
+}
+
+/* ......................................................................... */
+
+static t_Error MemacSetRxIgnorePauseFrames(t_Handle h_Memac, bool en)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ fman_memac_set_rx_ignore_pause_frames(p_Memac->p_MemMap, en);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacSetWakeOnLan(t_Handle h_Memac, bool en)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ fman_memac_set_wol(p_Memac->p_MemMap, en);
+
+ return E_OK;
+}
+
+/* .............................................................................. */
+
+static t_Error MemacEnable1588TimeStamp(t_Handle h_Memac)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+UNUSED(p_Memac);
+DBG(WARNING, ("mEMAC has 1588 always enabled!"));
+
+ return E_OK;
+}
+
+/* Counters handling */
+/* ......................................................................... */
+
+static t_Error MemacGetStatistics(t_Handle h_Memac, t_FmMacStatistics *p_Statistics)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_Statistics, E_NULL_POINTER);
+
+ p_Statistics->eStatPkts64 = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R64);
+ p_Statistics->eStatPkts65to127 = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R127);
+ p_Statistics->eStatPkts128to255 = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R255);
+ p_Statistics->eStatPkts256to511 = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R511);
+ p_Statistics->eStatPkts512to1023 = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R1023);
+ p_Statistics->eStatPkts1024to1518 = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R1518);
+ p_Statistics->eStatPkts1519to1522 = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_R1519X);
+/* */
+ p_Statistics->eStatFragments = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RFRG);
+ p_Statistics->eStatJabbers = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RJBR);
+
+ p_Statistics->eStatsDropEvents = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RDRP);
+ p_Statistics->eStatCRCAlignErrors = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RALN);
+
+ p_Statistics->eStatUndersizePkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TUND);
+ p_Statistics->eStatOversizePkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_ROVR);
+/* Pause */
+ p_Statistics->reStatPause = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RXPF);
+ p_Statistics->teStatPause = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TXPF);
+
+/* MIB II */
+ p_Statistics->ifInOctets = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_ROCT);
+ p_Statistics->ifInUcastPkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RUCA);
+ p_Statistics->ifInMcastPkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RMCA);
+ p_Statistics->ifInBcastPkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RBCA);
+ p_Statistics->ifInPkts = p_Statistics->ifInUcastPkts
+ + p_Statistics->ifInMcastPkts
+ + p_Statistics->ifInBcastPkts;
+ p_Statistics->ifInDiscards = 0;
+ p_Statistics->ifInErrors = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_RERR);
+
+ p_Statistics->ifOutOctets = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TOCT);
+ p_Statistics->ifOutUcastPkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TUCA);
+ p_Statistics->ifOutMcastPkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TMCA);
+ p_Statistics->ifOutBcastPkts = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TBCA);
+ p_Statistics->ifOutPkts = p_Statistics->ifOutUcastPkts
+ + p_Statistics->ifOutMcastPkts
+ + p_Statistics->ifOutBcastPkts;
+ p_Statistics->ifOutDiscards = 0;
+ p_Statistics->ifOutErrors = fman_memac_get_counter(p_Memac->p_MemMap, E_MEMAC_COUNTER_TERR);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacModifyMacAddress (t_Handle h_Memac, t_EnetAddr *p_EnetAddr)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ fman_memac_add_addr_in_paddr(p_Memac->p_MemMap, (uint8_t *)(*p_EnetAddr), 0);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacResetCounters (t_Handle h_Memac)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ fman_memac_reset_stat(p_Memac->p_MemMap);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacAddExactMatchMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr)
+{
+ t_Memac *p_Memac = (t_Memac *) h_Memac;
+ uint64_t ethAddr;
+ uint8_t paddrNum;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
+
+ if (ethAddr & GROUP_ADDRESS)
+ /* Multicast address has no effect in PADDR */
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Multicast address"));
+
+ /* Make sure no PADDR contains this address */
+ for (paddrNum = 0; paddrNum < MEMAC_NUM_OF_PADDRS; paddrNum++)
+ if (p_Memac->indAddrRegUsed[paddrNum])
+ if (p_Memac->paddr[paddrNum] == ethAddr)
+ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG);
+
+ /* Find first unused PADDR */
+ for (paddrNum = 0; paddrNum < MEMAC_NUM_OF_PADDRS; paddrNum++)
+ if (!(p_Memac->indAddrRegUsed[paddrNum]))
+ {
+ /* mark this PADDR as used */
+ p_Memac->indAddrRegUsed[paddrNum] = TRUE;
+ /* store address */
+ p_Memac->paddr[paddrNum] = ethAddr;
+
+ /* put in hardware */
+ fman_memac_add_addr_in_paddr(p_Memac->p_MemMap, (uint8_t*)(*p_EthAddr), paddrNum);
+ p_Memac->numOfIndAddrInRegs++;
+
+ return E_OK;
+ }
+
+ /* No free PADDR */
+ RETURN_ERROR(MAJOR, E_FULL, NO_MSG);
+}
+
+/* ......................................................................... */
+
+static t_Error MemacDelExactMatchMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr)
+{
+ t_Memac *p_Memac = (t_Memac *) h_Memac;
+ uint64_t ethAddr;
+ uint8_t paddrNum;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
+
+ /* Find used PADDR containing this address */
+ for (paddrNum = 0; paddrNum < MEMAC_NUM_OF_PADDRS; paddrNum++)
+ {
+ if ((p_Memac->indAddrRegUsed[paddrNum]) &&
+ (p_Memac->paddr[paddrNum] == ethAddr))
+ {
+ /* mark this PADDR as not used */
+ p_Memac->indAddrRegUsed[paddrNum] = FALSE;
+ /* clear in hardware */
+ fman_memac_clear_addr_in_paddr(p_Memac->p_MemMap, paddrNum);
+ p_Memac->numOfIndAddrInRegs--;
+
+ return E_OK;
+ }
+ }
+
+ RETURN_ERROR(MAJOR, E_NOT_FOUND, NO_MSG);
+}
+
+/* ......................................................................... */
+
+static t_Error MemacAddHashMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+ t_EthHashEntry *p_HashEntry;
+ uint32_t hash;
+ uint64_t ethAddr;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
+
+ if (!(ethAddr & GROUP_ADDRESS))
+ /* Unicast addresses not supported in hash */
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unicast Address"));
+
+ hash = GetMacAddrHashCode(ethAddr) & HASH_CTRL_ADDR_MASK;
+
+ /* Create element to be added to the driver hash table */
+ p_HashEntry = (t_EthHashEntry *)XX_Malloc(sizeof(t_EthHashEntry));
+ p_HashEntry->addr = ethAddr;
+ INIT_LIST(&p_HashEntry->node);
+
+ LIST_AddToTail(&(p_HashEntry->node), &(p_Memac->p_MulticastAddrHash->p_Lsts[hash]));
+ fman_memac_set_hash_table(p_Memac->p_MemMap, (hash | HASH_CTRL_MCAST_EN));
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacDelHashMacAddress(t_Handle h_Memac, t_EnetAddr *p_EthAddr)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+ t_EthHashEntry *p_HashEntry = NULL;
+ t_List *p_Pos;
+ uint32_t hash;
+ uint64_t ethAddr;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
+
+ hash = GetMacAddrHashCode(ethAddr) & HASH_CTRL_ADDR_MASK;
+
+ LIST_FOR_EACH(p_Pos, &(p_Memac->p_MulticastAddrHash->p_Lsts[hash]))
+ {
+ p_HashEntry = ETH_HASH_ENTRY_OBJ(p_Pos);
+ if (p_HashEntry->addr == ethAddr)
+ {
+ LIST_DelAndInit(&p_HashEntry->node);
+ XX_Free(p_HashEntry);
+ break;
+ }
+ }
+ if (LIST_IsEmpty(&p_Memac->p_MulticastAddrHash->p_Lsts[hash]))
+ fman_memac_set_hash_table(p_Memac->p_MemMap, (hash & ~HASH_CTRL_MCAST_EN));
+
+ return E_OK;
+}
+
+
+/* ......................................................................... */
+
+static t_Error MemacSetException(t_Handle h_Memac, e_FmMacExceptions exception, bool enable)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+ uint32_t bitMask = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+
+ GET_EXCEPTION_FLAG(bitMask, exception);
+ if (bitMask)
+ {
+ if (enable)
+ p_Memac->exceptions |= bitMask;
+ else
+ p_Memac->exceptions &= ~bitMask;
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
+
+ fman_memac_set_exception(p_Memac->p_MemMap, bitMask, enable);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static uint16_t MemacGetMaxFrameLength(t_Handle h_Memac)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_VALUE(p_Memac, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_VALUE(!p_Memac->p_MemacDriverParam, E_INVALID_STATE, 0);
+
+ return fman_memac_get_max_frame_len(p_Memac->p_MemMap);
+}
+
+/* ......................................................................... */
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+static t_Error MemacDumpRegs(t_Handle h_Memac)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+ int i = 0;
+
+ DECLARE_DUMP;
+
+ if (p_Memac->p_MemMap)
+ {
+ DUMP_TITLE(p_Memac->p_MemMap, ("mEMAC %d: ", p_Memac->macId));
+ DUMP_VAR(p_Memac->p_MemMap, command_config);
+ DUMP_VAR(p_Memac->p_MemMap, mac_addr0.mac_addr_l);
+ DUMP_VAR(p_Memac->p_MemMap, mac_addr0.mac_addr_u);
+ DUMP_VAR(p_Memac->p_MemMap, maxfrm);
+ DUMP_VAR(p_Memac->p_MemMap, hashtable_ctrl);
+ DUMP_VAR(p_Memac->p_MemMap, ievent);
+ DUMP_VAR(p_Memac->p_MemMap, tx_ipg_length);
+ DUMP_VAR(p_Memac->p_MemMap, imask);
+
+ DUMP_SUBSTRUCT_ARRAY(i, 4)
+ {
+ DUMP_VAR(p_Memac->p_MemMap, pause_quanta[i]);
+ }
+ DUMP_SUBSTRUCT_ARRAY(i, 4)
+ {
+ DUMP_VAR(p_Memac->p_MemMap, pause_thresh[i]);
+ }
+
+ DUMP_VAR(p_Memac->p_MemMap, rx_pause_status);
+
+ DUMP_SUBSTRUCT_ARRAY(i, MEMAC_NUM_OF_PADDRS)
+ {
+ DUMP_VAR(p_Memac->p_MemMap, mac_addr[i].mac_addr_l);
+ DUMP_VAR(p_Memac->p_MemMap, mac_addr[i].mac_addr_u);
+ }
+
+ DUMP_VAR(p_Memac->p_MemMap, lpwake_timer);
+ DUMP_VAR(p_Memac->p_MemMap, sleep_timer);
+ DUMP_VAR(p_Memac->p_MemMap, statn_config);
+ DUMP_VAR(p_Memac->p_MemMap, if_mode);
+ DUMP_VAR(p_Memac->p_MemMap, if_status);
+ DUMP_VAR(p_Memac->p_MemMap, hg_config);
+ DUMP_VAR(p_Memac->p_MemMap, hg_pause_quanta);
+ DUMP_VAR(p_Memac->p_MemMap, hg_pause_thresh);
+ DUMP_VAR(p_Memac->p_MemMap, hgrx_pause_status);
+ DUMP_VAR(p_Memac->p_MemMap, hg_fifos_status);
+ DUMP_VAR(p_Memac->p_MemMap, rhm);
+ DUMP_VAR(p_Memac->p_MemMap, thm);
+ }
+
+ return E_OK;
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+
+/*****************************************************************************/
+/* mEMAC Init & Free API */
+/*****************************************************************************/
+
+/* ......................................................................... */
+
+static t_Error MemacInit(t_Handle h_Memac)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+ struct memac_cfg *p_MemacDriverParam;
+ enum enet_interface enet_interface;
+ enum enet_speed enet_speed;
+ uint8_t i, phyAddr;
+ t_EnetAddr ethAddr;
+ e_FmMacType portType;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_Memac->fmMacControllerDriver.h_Fm, E_INVALID_HANDLE);
+
+ /* not needed! */
+ /*FM_GetRevision(p_Memac->fmMacControllerDriver.h_Fm, &p_Memac->fmMacControllerDriver.fmRevInfo);*/
+
+ CHECK_INIT_PARAMETERS(p_Memac, CheckInitParameters);
+
+ p_MemacDriverParam = p_Memac->p_MemacDriverParam;
+
+ portType =
+ ((ENET_SPEED_FROM_MODE(p_Memac->enetMode) < e_ENET_SPEED_10000) ? e_FM_MAC_1G : e_FM_MAC_10G);
+
+ /* First, reset the MAC if desired. */
+ if (p_MemacDriverParam->reset_on_init)
+ fman_memac_reset(p_Memac->p_MemMap);
+
+ /* MAC Address */
+ MAKE_ENET_ADDR_FROM_UINT64(p_Memac->addr, ethAddr);
+ fman_memac_add_addr_in_paddr(p_Memac->p_MemMap, (uint8_t*)ethAddr, 0);
+
+ enet_interface = (enum enet_interface) ENET_INTERFACE_FROM_MODE(p_Memac->enetMode);
+ enet_speed = (enum enet_speed) ENET_SPEED_FROM_MODE(p_Memac->enetMode);
+
+ fman_memac_init(p_Memac->p_MemMap,
+ p_Memac->p_MemacDriverParam,
+ enet_interface,
+ enet_speed,
+ p_Memac->exceptions);
+
+#ifdef FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320
+ {
+ uint32_t tmpReg = 0;
+
+ FM_GetRevision(p_Memac->fmMacControllerDriver.h_Fm, &p_Memac->fmMacControllerDriver.fmRevInfo);
+ /* check the FMAN version - the bug exists only in rev1 */
+ if ((p_Memac->fmMacControllerDriver.fmRevInfo.majorRev == 6) &&
+ (p_Memac->fmMacControllerDriver.fmRevInfo.minorRev == 0))
+ {
+ /* MAC strips CRC from received frames - this workaround should
+ decrease the likelihood of bug appearance
+ */
+ tmpReg = GET_UINT32(p_Memac->p_MemMap->command_config);
+ tmpReg &= ~CMD_CFG_CRC_FWD;
+ WRITE_UINT32(p_Memac->p_MemMap->command_config, tmpReg);
+ /* DBG(WARNING, ("mEMAC strips CRC from received frames as part of A006320 errata workaround"));*/
+ }
+ }
+#endif /* FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320 */
+
+ if (ENET_INTERFACE_FROM_MODE(p_Memac->enetMode) == e_ENET_IF_SGMII)
+ {
+ /* Configure internal SGMII PHY */
+ if (p_Memac->enetMode & ENET_IF_SGMII_BASEX)
+ SetupSgmiiInternalPhyBaseX(p_Memac, PHY_MDIO_ADDR);
+ else
+ SetupSgmiiInternalPhy(p_Memac, PHY_MDIO_ADDR);
+ }
+ else if (ENET_INTERFACE_FROM_MODE(p_Memac->enetMode) == e_ENET_IF_QSGMII)
+ {
+ /* Configure 4 internal SGMII PHYs */
+ for (i = 0; i < 4; i++)
+ {
+ /* QSGMII PHY address occupies 3 upper bits of 5-bit
+ phyAddress; the lower 2 bits are used to extend
+ register address space and access each one of 4
+ ports inside QSGMII. */
+ phyAddr = (uint8_t)((PHY_MDIO_ADDR << 2) | i);
+ if (p_Memac->enetMode & ENET_IF_SGMII_BASEX)
+ SetupSgmiiInternalPhyBaseX(p_Memac, phyAddr);
+ else
+ SetupSgmiiInternalPhy(p_Memac, phyAddr);
+ }
+ }
+
+ /* Max Frame Length */
+ err = FmSetMacMaxFrame(p_Memac->fmMacControllerDriver.h_Fm,
+ portType,
+ p_Memac->fmMacControllerDriver.macId,
+ p_MemacDriverParam->max_frame_length);
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("settings Mac max frame length is FAILED"));
+
+ p_Memac->p_MulticastAddrHash = AllocHashTable(HASH_TABLE_SIZE);
+ if (!p_Memac->p_MulticastAddrHash)
+ {
+ FreeInitResources(p_Memac);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("allocation hash table is FAILED"));
+ }
+
+ p_Memac->p_UnicastAddrHash = AllocHashTable(HASH_TABLE_SIZE);
+ if (!p_Memac->p_UnicastAddrHash)
+ {
+ FreeInitResources(p_Memac);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("allocation hash table is FAILED"));
+ }
+
+ FmRegisterIntr(p_Memac->fmMacControllerDriver.h_Fm,
+ (portType == e_FM_MAC_10G) ? e_FM_MOD_10G_MAC : e_FM_MOD_1G_MAC,
+ p_Memac->macId,
+ e_FM_INTR_TYPE_ERR,
+ MemacErrException,
+ p_Memac);
+
+ FmRegisterIntr(p_Memac->fmMacControllerDriver.h_Fm,
+ (portType == e_FM_MAC_10G) ? e_FM_MOD_10G_MAC : e_FM_MOD_1G_MAC,
+ p_Memac->macId,
+ e_FM_INTR_TYPE_NORMAL,
+ MemacException,
+ p_Memac);
+
+ XX_Free(p_MemacDriverParam);
+ p_Memac->p_MemacDriverParam = NULL;
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error MemacFree(t_Handle h_Memac)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+
+ FreeInitResources(p_Memac);
+
+ if (p_Memac->p_MemacDriverParam)
+ {
+ XX_Free(p_Memac->p_MemacDriverParam);
+ p_Memac->p_MemacDriverParam = NULL;
+ }
+ XX_Free(p_Memac);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static void InitFmMacControllerDriver(t_FmMacControllerDriver *p_FmMacControllerDriver)
+{
+ p_FmMacControllerDriver->f_FM_MAC_Init = MemacInit;
+ p_FmMacControllerDriver->f_FM_MAC_Free = MemacFree;
+
+ p_FmMacControllerDriver->f_FM_MAC_SetStatistics = NULL;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback = MemacConfigLoopback;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength = MemacConfigMaxFrameLength;
+
+ p_FmMacControllerDriver->f_FM_MAC_ConfigWan = MemacConfigWan;
+
+ p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc = MemacConfigPad;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex = NULL; /* half-duplex is detected automatically */
+ p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck = MemacConfigLengthCheck;
+
+ p_FmMacControllerDriver->f_FM_MAC_ConfigException = MemacConfigException;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit = MemacConfigResetOnInit;
+
+ p_FmMacControllerDriver->f_FM_MAC_SetException = MemacSetException;
+
+ p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp = MemacEnable1588TimeStamp; /* always enabled */
+ p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp = NULL;
+
+ p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous = MemacSetPromiscuous;
+ p_FmMacControllerDriver->f_FM_MAC_AdjustLink = MemacAdjustLink;
+ p_FmMacControllerDriver->f_FM_MAC_RestartAutoneg = NULL;
+
+ p_FmMacControllerDriver->f_FM_MAC_Enable = MemacEnable;
+ p_FmMacControllerDriver->f_FM_MAC_Disable = MemacDisable;
+
+ p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames = MemacSetTxAutoPauseFrames;
+ p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames = MemacSetTxPauseFrames;
+ p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames = MemacSetRxIgnorePauseFrames;
+
+ p_FmMacControllerDriver->f_FM_MAC_SetWakeOnLan = MemacSetWakeOnLan;
+
+ p_FmMacControllerDriver->f_FM_MAC_ResetCounters = MemacResetCounters;
+ p_FmMacControllerDriver->f_FM_MAC_GetStatistics = MemacGetStatistics;
+
+ p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr = MemacModifyMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr = MemacAddHashMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr = MemacDelHashMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr = MemacAddExactMatchMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr = MemacDelExactMatchMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_GetId = NULL;
+ p_FmMacControllerDriver->f_FM_MAC_GetVersion = NULL;
+ p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength = MemacGetMaxFrameLength;
+
+ p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg = MEMAC_MII_WritePhyReg;
+ p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg = MEMAC_MII_ReadPhyReg;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ p_FmMacControllerDriver->f_FM_MAC_DumpRegs = MemacDumpRegs;
+#endif /* (defined(DEBUG_ERRORS) && ... */
+}
+
+
+/*****************************************************************************/
+/* mEMAC Config Main Entry */
+/*****************************************************************************/
+
+/* ......................................................................... */
+
+t_Handle MEMAC_Config(t_FmMacParams *p_FmMacParam)
+{
+ t_Memac *p_Memac;
+ struct memac_cfg *p_MemacDriverParam;
+ uintptr_t baseAddr;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmMacParam, E_NULL_POINTER, NULL);
+
+ baseAddr = p_FmMacParam->baseAddr;
+ /* Allocate memory for the mEMAC data structure */
+ p_Memac = (t_Memac *)XX_Malloc(sizeof(t_Memac));
+ if (!p_Memac)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("mEMAC driver structure"));
+ return NULL;
+ }
+ memset(p_Memac, 0, sizeof(t_Memac));
+ InitFmMacControllerDriver(&p_Memac->fmMacControllerDriver);
+
+ /* Allocate memory for the mEMAC driver parameters data structure */
+ p_MemacDriverParam = (struct memac_cfg *) XX_Malloc(sizeof(struct memac_cfg));
+ if (!p_MemacDriverParam)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("mEMAC driver parameters"));
+ MemacFree(p_Memac);
+ return NULL;
+ }
+ memset(p_MemacDriverParam, 0, sizeof(struct memac_cfg));
+
+ /* Plant parameter structure pointer */
+ p_Memac->p_MemacDriverParam = p_MemacDriverParam;
+
+ fman_memac_defconfig(p_MemacDriverParam);
+
+ p_Memac->addr = ENET_ADDR_TO_UINT64(p_FmMacParam->addr);
+
+ p_Memac->p_MemMap = (struct memac_regs *)UINT_TO_PTR(baseAddr);
+ p_Memac->p_MiiMemMap = (struct memac_mii_access_mem_map*)UINT_TO_PTR(baseAddr + MEMAC_TO_MII_OFFSET);
+
+ p_Memac->enetMode = p_FmMacParam->enetMode;
+ p_Memac->macId = p_FmMacParam->macId;
+ p_Memac->exceptions = MEMAC_default_exceptions;
+ p_Memac->f_Exception = p_FmMacParam->f_Exception;
+ p_Memac->f_Event = p_FmMacParam->f_Event;
+ p_Memac->h_App = p_FmMacParam->h_App;
+
+ return p_Memac;
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac.h
new file mode 100644
index 0000000..4bb09d6
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File memac.h
+
+ @Description FM Multirate Ethernet MAC (mEMAC)
+*//***************************************************************************/
+#ifndef __MEMAC_H
+#define __MEMAC_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "list_ext.h"
+
+#include "fsl_fman_memac_mii_acc.h"
+#include "fm_mac.h"
+#include "fsl_fman_memac.h"
+
+
+#define MEMAC_default_exceptions \
+ ((uint32_t)(MEMAC_IMASK_TSECC_ER | MEMAC_IMASK_TECC_ER | MEMAC_IMASK_RECC_ER | MEMAC_IMASK_MGI))
+
+#define GET_EXCEPTION_FLAG(bitMask, exception) switch (exception){ \
+ case e_FM_MAC_EX_10G_1TX_ECC_ER: \
+ bitMask = MEMAC_IMASK_TECC_ER; break; \
+ case e_FM_MAC_EX_10G_RX_ECC_ER: \
+ bitMask = MEMAC_IMASK_RECC_ER; break; \
+ case e_FM_MAC_EX_TS_FIFO_ECC_ERR: \
+ bitMask = MEMAC_IMASK_TSECC_ER; break; \
+ case e_FM_MAC_EX_MAGIC_PACKET_INDICATION: \
+ bitMask = MEMAC_IMASK_MGI; break; \
+ default: bitMask = 0;break;}
+
+
+typedef struct
+{
+ t_FmMacControllerDriver fmMacControllerDriver; /**< Upper Mac control block */
+ t_Handle h_App; /**< Handle to the upper layer application */
+ struct memac_regs *p_MemMap; /**< Pointer to MAC memory mapped registers */
+ struct memac_mii_access_mem_map *p_MiiMemMap; /**< Pointer to MII memory mapped registers */
+ uint64_t addr; /**< MAC address of device */
+ e_EnetMode enetMode; /**< Ethernet physical interface */
+ t_FmMacExceptionCallback *f_Exception;
+ int mdioIrq;
+ t_FmMacExceptionCallback *f_Event;
+ bool indAddrRegUsed[MEMAC_NUM_OF_PADDRS]; /**< Whether a particular individual address recognition register is being used */
+ uint64_t paddr[MEMAC_NUM_OF_PADDRS]; /**< MAC address for particular individual address recognition register */
+ uint8_t numOfIndAddrInRegs; /**< Number of individual addresses in registers for this station. */
+ t_EthHash *p_MulticastAddrHash; /**< Pointer to driver's global address hash table */
+ t_EthHash *p_UnicastAddrHash; /**< Pointer to driver's individual address hash table */
+ bool debugMode;
+ uint8_t macId;
+ uint32_t exceptions;
+ struct memac_cfg *p_MemacDriverParam;
+} t_Memac;
+
+
+/* Internal PHY access */
+#define PHY_MDIO_ADDR 0
+
+/* Internal PHY Registers - SGMII */
+#define PHY_SGMII_CR_PHY_RESET 0x8000
+#define PHY_SGMII_CR_RESET_AN 0x0200
+#define PHY_SGMII_CR_DEF_VAL 0x1140
+#define PHY_SGMII_DEV_ABILITY_SGMII 0x4001
+#define PHY_SGMII_DEV_ABILITY_1000X 0x01A0
+#define PHY_SGMII_IF_MODE_AN 0x0002
+#define PHY_SGMII_IF_MODE_SGMII 0x0001
+#define PHY_SGMII_IF_MODE_1000X 0x0000
+
+
+#define MEMAC_TO_MII_OFFSET 0x030 /* Offset from the MEM map to the MDIO mem map */
+
+t_Error MEMAC_MII_WritePhyReg(t_Handle h_Memac, uint8_t phyAddr, uint8_t reg, uint16_t data);
+t_Error MEMAC_MII_ReadPhyReg(t_Handle h_Memac, uint8_t phyAddr, uint8_t reg, uint16_t *p_Data);
+
+
+#endif /* __MEMAC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac_mii_acc.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac_mii_acc.c
new file mode 100644
index 0000000..56eaffb
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac_mii_acc.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "error_ext.h"
+#include "std_ext.h"
+#include "fm_mac.h"
+#include "memac.h"
+#include "xx_ext.h"
+
+#include "fm_common.h"
+#include "memac_mii_acc.h"
+
+
+/*****************************************************************************/
+t_Error MEMAC_MII_WritePhyReg(t_Handle h_Memac,
+ uint8_t phyAddr,
+ uint8_t reg,
+ uint16_t data)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MiiMemMap, E_INVALID_HANDLE);
+
+ return (t_Error)fman_memac_mii_write_phy_reg(p_Memac->p_MiiMemMap,
+ phyAddr,
+ reg,
+ data,
+ (enum enet_speed)ENET_SPEED_FROM_MODE(p_Memac->enetMode));
+}
+
+/*****************************************************************************/
+t_Error MEMAC_MII_ReadPhyReg(t_Handle h_Memac,
+ uint8_t phyAddr,
+ uint8_t reg,
+ uint16_t *p_Data)
+{
+ t_Memac *p_Memac = (t_Memac *)h_Memac;
+
+ SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Memac->p_MiiMemMap, E_INVALID_HANDLE);
+
+ return fman_memac_mii_read_phy_reg(p_Memac->p_MiiMemMap,
+ phyAddr,
+ reg,
+ p_Data,
+ (enum enet_speed)ENET_SPEED_FROM_MODE(p_Memac->enetMode));
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac_mii_acc.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac_mii_acc.h
new file mode 100644
index 0000000..a8824ef
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac_mii_acc.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MEMAC_MII_ACC_H
+#define __MEMAC_MII_ACC_H
+
+#include "std_ext.h"
+
+
+/* MII Management Registers */
+#define MDIO_CFG_CLK_DIV_MASK 0x0080ff80
+#define MDIO_CFG_CLK_DIV_SHIFT 7
+#define MDIO_CFG_HOLD_MASK 0x0000001c
+#define MDIO_CFG_ENC45 0x00000040
+#define MDIO_CFG_READ_ERR 0x00000002
+#define MDIO_CFG_BSY 0x00000001
+
+#define MDIO_CTL_PHY_ADDR_SHIFT 5
+#define MDIO_CTL_READ 0x00008000
+
+#define MDIO_DATA_BSY 0x80000000
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+/*----------------------------------------------------*/
+/* MII Configuration Control Memory Map Registers */
+/*----------------------------------------------------*/
+typedef _Packed struct t_MemacMiiAccessMemMap
+{
+ volatile uint32_t mdio_cfg; /* 0x030 */
+ volatile uint32_t mdio_ctrl; /* 0x034 */
+ volatile uint32_t mdio_data; /* 0x038 */
+ volatile uint32_t mdio_addr; /* 0x03c */
+} _PackedType t_MemacMiiAccessMemMap ;
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+#endif /* __MEMAC_MII_ACC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec.c
new file mode 100644
index 0000000..8089b46
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec.c
@@ -0,0 +1,1017 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File tgec.c
+
+ @Description FM 10G MAC ...
+*//***************************************************************************/
+
+#include "std_ext.h"
+#include "string_ext.h"
+#include "error_ext.h"
+#include "xx_ext.h"
+#include "endian_ext.h"
+#include "debug_ext.h"
+#include "crc_mac_addr_ext.h"
+
+#include "fm_common.h"
+#include "fsl_fman_tgec.h"
+#include "tgec.h"
+
+
+/*****************************************************************************/
+/* Internal routines */
+/*****************************************************************************/
+
+static t_Error CheckInitParameters(t_Tgec *p_Tgec)
+{
+ if (ENET_SPEED_FROM_MODE(p_Tgec->enetMode) < e_ENET_SPEED_10000)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet 10G MAC driver only support 10G speed"));
+#if (FM_MAX_NUM_OF_10G_MACS > 0)
+ if (p_Tgec->macId >= FM_MAX_NUM_OF_10G_MACS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("macId of 10G can not be greater than 0"));
+#endif /* (FM_MAX_NUM_OF_10G_MACS > 0) */
+
+ if (p_Tgec->addr == 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet 10G MAC Must have a valid MAC Address"));
+ if (!p_Tgec->f_Exception)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("uninitialized f_Exception"));
+ if (!p_Tgec->f_Event)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("uninitialized f_Event"));
+#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002
+ if (!p_Tgec->p_TgecDriverParam->no_length_check_enable)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("LengthCheck!"));
+#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static uint32_t GetMacAddrHashCode(uint64_t ethAddr)
+{
+ uint32_t crc;
+
+ /* CRC calculation */
+ GET_MAC_ADDR_CRC(ethAddr, crc);
+
+ crc = GetMirror32(crc);
+
+ return crc;
+}
+
+/* ......................................................................... */
+
+static void TgecErrException(t_Handle h_Tgec)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+ uint32_t event;
+ struct tgec_regs *p_TgecMemMap = p_Tgec->p_MemMap;
+
+ /* do not handle MDIO events */
+ event = fman_tgec_get_event(p_TgecMemMap, ~(TGEC_IMASK_MDIO_SCAN_EVENT | TGEC_IMASK_MDIO_CMD_CMPL));
+ event &= fman_tgec_get_interrupt_mask(p_TgecMemMap);
+
+ fman_tgec_ack_event(p_TgecMemMap, event);
+
+ if (event & TGEC_IMASK_REM_FAULT)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_REM_FAULT);
+ if (event & TGEC_IMASK_LOC_FAULT)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_LOC_FAULT);
+ if (event & TGEC_IMASK_TX_ECC_ER)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_1TX_ECC_ER);
+ if (event & TGEC_IMASK_TX_FIFO_UNFL)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_TX_FIFO_UNFL);
+ if (event & TGEC_IMASK_TX_FIFO_OVFL)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_TX_FIFO_OVFL);
+ if (event & TGEC_IMASK_TX_ER)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_TX_ER);
+ if (event & TGEC_IMASK_RX_FIFO_OVFL)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_FIFO_OVFL);
+ if (event & TGEC_IMASK_RX_ECC_ER)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_ECC_ER);
+ if (event & TGEC_IMASK_RX_JAB_FRM)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_JAB_FRM);
+ if (event & TGEC_IMASK_RX_OVRSZ_FRM)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_OVRSZ_FRM);
+ if (event & TGEC_IMASK_RX_RUNT_FRM)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_RUNT_FRM);
+ if (event & TGEC_IMASK_RX_FRAG_FRM)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_FRAG_FRM);
+ if (event & TGEC_IMASK_RX_LEN_ER)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_LEN_ER);
+ if (event & TGEC_IMASK_RX_CRC_ER)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_CRC_ER);
+ if (event & TGEC_IMASK_RX_ALIGN_ER)
+ p_Tgec->f_Exception(p_Tgec->h_App, e_FM_MAC_EX_10G_RX_ALIGN_ER);
+}
+
+/* ......................................................................... */
+
+static void TgecException(t_Handle h_Tgec)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+ uint32_t event;
+ struct tgec_regs *p_TgecMemMap = p_Tgec->p_MemMap;
+
+ /* handle only MDIO events */
+ event = fman_tgec_get_event(p_TgecMemMap, (TGEC_IMASK_MDIO_SCAN_EVENT | TGEC_IMASK_MDIO_CMD_CMPL));
+ event &= fman_tgec_get_interrupt_mask(p_TgecMemMap);
+
+ fman_tgec_ack_event(p_TgecMemMap, event);
+
+ if (event & TGEC_IMASK_MDIO_SCAN_EVENT)
+ p_Tgec->f_Event(p_Tgec->h_App, e_FM_MAC_EX_10G_MDIO_SCAN_EVENTMDIO);
+ if (event & TGEC_IMASK_MDIO_CMD_CMPL)
+ p_Tgec->f_Event(p_Tgec->h_App, e_FM_MAC_EX_10G_MDIO_CMD_CMPL);
+}
+
+/* ......................................................................... */
+
+static void FreeInitResources(t_Tgec *p_Tgec)
+{
+ if ((p_Tgec->mdioIrq != 0) && (p_Tgec->mdioIrq != NO_IRQ))
+ {
+ XX_DisableIntr(p_Tgec->mdioIrq);
+ XX_FreeIntr(p_Tgec->mdioIrq);
+ }
+ else if (p_Tgec->mdioIrq == 0)
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+ FmUnregisterIntr(p_Tgec->fmMacControllerDriver.h_Fm, e_FM_MOD_10G_MAC, p_Tgec->macId, e_FM_INTR_TYPE_ERR);
+
+ /* release the driver's group hash table */
+ FreeHashTable(p_Tgec->p_MulticastAddrHash);
+ p_Tgec->p_MulticastAddrHash = NULL;
+
+ /* release the driver's individual hash table */
+ FreeHashTable(p_Tgec->p_UnicastAddrHash);
+ p_Tgec->p_UnicastAddrHash = NULL;
+}
+
+
+/*****************************************************************************/
+/* 10G MAC API routines */
+/*****************************************************************************/
+
+/* ......................................................................... */
+
+static t_Error TgecEnable(t_Handle h_Tgec, e_CommMode mode)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ fman_tgec_enable(p_Tgec->p_MemMap, (mode & e_COMM_MODE_RX), (mode & e_COMM_MODE_TX));
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecDisable (t_Handle h_Tgec, e_CommMode mode)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ fman_tgec_disable(p_Tgec->p_MemMap, (mode & e_COMM_MODE_RX), (mode & e_COMM_MODE_TX));
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecSetPromiscuous(t_Handle h_Tgec, bool newVal)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ fman_tgec_set_promiscuous(p_Tgec->p_MemMap, newVal);
+
+ return E_OK;
+}
+
+
+/*****************************************************************************/
+/* Tgec Configs modification functions */
+/*****************************************************************************/
+
+/* ......................................................................... */
+
+static t_Error TgecConfigLoopback(t_Handle h_Tgec, bool newVal)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ p_Tgec->p_TgecDriverParam->loopback_enable = newVal;
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecConfigWan(t_Handle h_Tgec, bool newVal)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ p_Tgec->p_TgecDriverParam->wan_mode_enable = newVal;
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecConfigMaxFrameLength(t_Handle h_Tgec, uint16_t newVal)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ p_Tgec->p_TgecDriverParam->max_frame_length = newVal;
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecConfigLengthCheck(t_Handle h_Tgec, bool newVal)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ UNUSED(newVal);
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ p_Tgec->p_TgecDriverParam->no_length_check_enable = !newVal;
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecConfigException(t_Handle h_Tgec, e_FmMacExceptions exception, bool enable)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+ uint32_t bitMask = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ GET_EXCEPTION_FLAG(bitMask, exception);
+ if (bitMask)
+ {
+ if (enable)
+ p_Tgec->exceptions |= bitMask;
+ else
+ p_Tgec->exceptions &= ~bitMask;
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
+
+ return E_OK;
+}
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+/* ......................................................................... */
+
+static t_Error TgecConfigSkipFman11Workaround(t_Handle h_Tgec)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ p_Tgec->p_TgecDriverParam->skip_fman11_workaround = TRUE;
+
+ return E_OK;
+}
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+
+/*****************************************************************************/
+/* Tgec Run Time API functions */
+/*****************************************************************************/
+
+/* ......................................................................... */
+/* backward compatibility. will be removed in the future. */
+static t_Error TgecTxMacPause(t_Handle h_Tgec, uint16_t pauseTime)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+ fman_tgec_set_tx_pause_frames(p_Tgec->p_MemMap, pauseTime);
+
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecSetTxPauseFrames(t_Handle h_Tgec,
+ uint8_t priority,
+ uint16_t pauseTime,
+ uint16_t threshTime)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ UNUSED(priority); UNUSED(threshTime);
+
+ fman_tgec_set_tx_pause_frames(p_Tgec->p_MemMap, pauseTime);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecRxIgnoreMacPause(t_Handle h_Tgec, bool en)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ fman_tgec_set_rx_ignore_pause_frames(p_Tgec->p_MemMap, en);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecGetStatistics(t_Handle h_Tgec, t_FmMacStatistics *p_Statistics)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+ struct tgec_regs *p_TgecMemMap;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_Statistics, E_NULL_POINTER);
+
+ p_TgecMemMap = p_Tgec->p_MemMap;
+
+ p_Statistics->eStatPkts64 = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R64);
+ p_Statistics->eStatPkts65to127 = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R127);
+ p_Statistics->eStatPkts128to255 = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R255);
+ p_Statistics->eStatPkts256to511 = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R511);
+ p_Statistics->eStatPkts512to1023 = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R1023);
+ p_Statistics->eStatPkts1024to1518 = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R1518);
+ p_Statistics->eStatPkts1519to1522 = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_R1519X);
+/* */
+ p_Statistics->eStatFragments = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TRFRG);
+ p_Statistics->eStatJabbers = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TRJBR);
+
+ p_Statistics->eStatsDropEvents = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RDRP);
+ p_Statistics->eStatCRCAlignErrors = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RALN);
+
+ p_Statistics->eStatUndersizePkts = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TRUND);
+ p_Statistics->eStatOversizePkts = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TROVR);
+/* Pause */
+ p_Statistics->reStatPause = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RXPF);
+ p_Statistics->teStatPause = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TXPF);
+
+/* MIB II */
+ p_Statistics->ifInOctets = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_ROCT);
+ p_Statistics->ifInUcastPkts = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RUCA);
+ p_Statistics->ifInMcastPkts = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RMCA);
+ p_Statistics->ifInBcastPkts = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RBCA);
+ p_Statistics->ifInPkts = p_Statistics->ifInUcastPkts
+ + p_Statistics->ifInMcastPkts
+ + p_Statistics->ifInBcastPkts;
+ p_Statistics->ifInDiscards = 0;
+ p_Statistics->ifInErrors = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_RERR);
+
+ p_Statistics->ifOutOctets = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TOCT);
+ p_Statistics->ifOutUcastPkts = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TUCA);
+ p_Statistics->ifOutMcastPkts = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TMCA);
+ p_Statistics->ifOutBcastPkts = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TBCA);
+ p_Statistics->ifOutPkts = p_Statistics->ifOutUcastPkts
+ + p_Statistics->ifOutMcastPkts
+ + p_Statistics->ifOutBcastPkts;
+ p_Statistics->ifOutDiscards = 0;
+ p_Statistics->ifOutErrors = fman_tgec_get_counter(p_TgecMemMap, E_TGEC_COUNTER_TERR);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecEnable1588TimeStamp(t_Handle h_Tgec)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ fman_tgec_enable_1588_time_stamp(p_Tgec->p_MemMap, 1);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecDisable1588TimeStamp(t_Handle h_Tgec)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ fman_tgec_enable_1588_time_stamp(p_Tgec->p_MemMap, 0);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecModifyMacAddress (t_Handle h_Tgec, t_EnetAddr *p_EnetAddr)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ p_Tgec->addr = ENET_ADDR_TO_UINT64(*p_EnetAddr);
+ fman_tgec_set_mac_address(p_Tgec->p_MemMap, (uint8_t *)(*p_EnetAddr));
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecResetCounters (t_Handle h_Tgec)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ fman_tgec_reset_stat(p_Tgec->p_MemMap);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecAddExactMatchMacAddress(t_Handle h_Tgec, t_EnetAddr *p_EthAddr)
+{
+ t_Tgec *p_Tgec = (t_Tgec *) h_Tgec;
+ uint64_t ethAddr;
+ uint8_t paddrNum;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
+
+ if (ethAddr & GROUP_ADDRESS)
+ /* Multicast address has no effect in PADDR */
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Multicast address"));
+
+ /* Make sure no PADDR contains this address */
+ for (paddrNum = 0; paddrNum < TGEC_NUM_OF_PADDRS; paddrNum++)
+ if (p_Tgec->indAddrRegUsed[paddrNum])
+ if (p_Tgec->paddr[paddrNum] == ethAddr)
+ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG);
+
+ /* Find first unused PADDR */
+ for (paddrNum = 0; paddrNum < TGEC_NUM_OF_PADDRS; paddrNum++)
+ {
+ if (!(p_Tgec->indAddrRegUsed[paddrNum]))
+ {
+ /* mark this PADDR as used */
+ p_Tgec->indAddrRegUsed[paddrNum] = TRUE;
+ /* store address */
+ p_Tgec->paddr[paddrNum] = ethAddr;
+
+ /* put in hardware */
+ fman_tgec_add_addr_in_paddr(p_Tgec->p_MemMap, (uint8_t*)(*p_EthAddr)/* , paddrNum */);
+ p_Tgec->numOfIndAddrInRegs++;
+
+ return E_OK;
+ }
+ }
+
+ /* No free PADDR */
+ RETURN_ERROR(MAJOR, E_FULL, NO_MSG);
+}
+
+/* ......................................................................... */
+
+static t_Error TgecDelExactMatchMacAddress(t_Handle h_Tgec, t_EnetAddr *p_EthAddr)
+{
+ t_Tgec *p_Tgec = (t_Tgec *) h_Tgec;
+ uint64_t ethAddr;
+ uint8_t paddrNum;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
+
+ /* Find used PADDR containing this address */
+ for (paddrNum = 0; paddrNum < TGEC_NUM_OF_PADDRS; paddrNum++)
+ {
+ if ((p_Tgec->indAddrRegUsed[paddrNum]) &&
+ (p_Tgec->paddr[paddrNum] == ethAddr))
+ {
+ /* mark this PADDR as not used */
+ p_Tgec->indAddrRegUsed[paddrNum] = FALSE;
+ /* clear in hardware */
+ fman_tgec_clear_addr_in_paddr(p_Tgec->p_MemMap /*, paddrNum */);
+ p_Tgec->numOfIndAddrInRegs--;
+
+ return E_OK;
+ }
+ }
+
+ RETURN_ERROR(MAJOR, E_NOT_FOUND, NO_MSG);
+}
+
+/* ......................................................................... */
+
+static t_Error TgecAddHashMacAddress(t_Handle h_Tgec, t_EnetAddr *p_EthAddr)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+ t_EthHashEntry *p_HashEntry;
+ uint32_t crc;
+ uint32_t hash;
+ uint64_t ethAddr;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
+
+ if (!(ethAddr & GROUP_ADDRESS))
+ /* Unicast addresses not supported in hash */
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unicast Address"));
+
+ /* CRC calculation */
+ crc = GetMacAddrHashCode(ethAddr);
+
+ hash = (crc >> TGEC_HASH_MCAST_SHIFT) & TGEC_HASH_ADR_MSK; /* Take 9 MSB bits */
+
+ /* Create element to be added to the driver hash table */
+ p_HashEntry = (t_EthHashEntry *)XX_Malloc(sizeof(t_EthHashEntry));
+ p_HashEntry->addr = ethAddr;
+ INIT_LIST(&p_HashEntry->node);
+
+ LIST_AddToTail(&(p_HashEntry->node), &(p_Tgec->p_MulticastAddrHash->p_Lsts[hash]));
+ fman_tgec_set_hash_table(p_Tgec->p_MemMap, (hash | TGEC_HASH_MCAST_EN));
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecDelHashMacAddress(t_Handle h_Tgec, t_EnetAddr *p_EthAddr)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+ t_EthHashEntry *p_HashEntry = NULL;
+ t_List *p_Pos;
+ uint32_t crc;
+ uint32_t hash;
+ uint64_t ethAddr;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ ethAddr = ((*(uint64_t *)p_EthAddr) >> 16);
+
+ /* CRC calculation */
+ crc = GetMacAddrHashCode(ethAddr);
+
+ hash = (crc >> TGEC_HASH_MCAST_SHIFT) & TGEC_HASH_ADR_MSK; /* Take 9 MSB bits */
+
+ LIST_FOR_EACH(p_Pos, &(p_Tgec->p_MulticastAddrHash->p_Lsts[hash]))
+ {
+ p_HashEntry = ETH_HASH_ENTRY_OBJ(p_Pos);
+ if (p_HashEntry->addr == ethAddr)
+ {
+ LIST_DelAndInit(&p_HashEntry->node);
+ XX_Free(p_HashEntry);
+ break;
+ }
+ }
+ if (LIST_IsEmpty(&p_Tgec->p_MulticastAddrHash->p_Lsts[hash]))
+ fman_tgec_set_hash_table(p_Tgec->p_MemMap, (hash & ~TGEC_HASH_MCAST_EN));
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecGetId(t_Handle h_Tgec, uint32_t *macId)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ UNUSED(p_Tgec);
+ UNUSED(macId);
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("TgecGetId Not Supported"));
+}
+
+/* ......................................................................... */
+
+static t_Error TgecGetVersion(t_Handle h_Tgec, uint32_t *macVersion)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ *macVersion = fman_tgec_get_revision(p_Tgec->p_MemMap);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecSetExcpetion(t_Handle h_Tgec, e_FmMacExceptions exception, bool enable)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+ uint32_t bitMask = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+
+ GET_EXCEPTION_FLAG(bitMask, exception);
+ if (bitMask)
+ {
+ if (enable)
+ p_Tgec->exceptions |= bitMask;
+ else
+ p_Tgec->exceptions &= ~bitMask;
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
+
+ if (enable)
+ fman_tgec_enable_interrupt(p_Tgec->p_MemMap, bitMask);
+ else
+ fman_tgec_disable_interrupt(p_Tgec->p_MemMap, bitMask);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static uint16_t TgecGetMaxFrameLength(t_Handle h_Tgec)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ SANITY_CHECK_RETURN_VALUE(p_Tgec, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_VALUE(!p_Tgec->p_TgecDriverParam, E_INVALID_STATE, 0);
+
+ return fman_tgec_get_max_frame_len(p_Tgec->p_MemMap);
+}
+
+/* ......................................................................... */
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+static t_Error TgecTxEccWorkaround(t_Tgec *p_Tgec)
+{
+ t_Error err;
+
+#if defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)
+ XX_Print("Applying 10G TX ECC workaround (10GMAC-A004) ... ");
+#endif /* (DEBUG_ERRORS > 0) */
+ /* enable and set promiscuous */
+ fman_tgec_enable(p_Tgec->p_MemMap, TRUE, TRUE);
+ fman_tgec_set_promiscuous(p_Tgec->p_MemMap, TRUE);
+ err = Fm10GTxEccWorkaround(p_Tgec->fmMacControllerDriver.h_Fm, p_Tgec->macId);
+ /* disable */
+ fman_tgec_set_promiscuous(p_Tgec->p_MemMap, FALSE);
+ fman_tgec_enable(p_Tgec->p_MemMap, FALSE, FALSE);
+ fman_tgec_reset_stat(p_Tgec->p_MemMap);
+ fman_tgec_ack_event(p_Tgec->p_MemMap, 0xffffffff);
+#if defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)
+ if (err)
+ XX_Print("FAILED!\n");
+ else
+ XX_Print("done.\n");
+#endif /* (DEBUG_ERRORS > 0) */
+
+ return err;
+}
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+/* ......................................................................... */
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+static t_Error TgecDumpRegs(t_Handle h_Tgec)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ DECLARE_DUMP;
+
+ if (p_Tgec->p_MemMap)
+ {
+ DUMP_TITLE(p_Tgec->p_MemMap, ("10G MAC %d: ", p_Tgec->macId));
+ DUMP_VAR(p_Tgec->p_MemMap, tgec_id);
+ DUMP_VAR(p_Tgec->p_MemMap, command_config);
+ DUMP_VAR(p_Tgec->p_MemMap, mac_addr_0);
+ DUMP_VAR(p_Tgec->p_MemMap, mac_addr_1);
+ DUMP_VAR(p_Tgec->p_MemMap, maxfrm);
+ DUMP_VAR(p_Tgec->p_MemMap, pause_quant);
+ DUMP_VAR(p_Tgec->p_MemMap, rx_fifo_sections);
+ DUMP_VAR(p_Tgec->p_MemMap, tx_fifo_sections);
+ DUMP_VAR(p_Tgec->p_MemMap, rx_fifo_almost_f_e);
+ DUMP_VAR(p_Tgec->p_MemMap, tx_fifo_almost_f_e);
+ DUMP_VAR(p_Tgec->p_MemMap, hashtable_ctrl);
+ DUMP_VAR(p_Tgec->p_MemMap, mdio_cfg_status);
+ DUMP_VAR(p_Tgec->p_MemMap, mdio_command);
+ DUMP_VAR(p_Tgec->p_MemMap, mdio_data);
+ DUMP_VAR(p_Tgec->p_MemMap, mdio_regaddr);
+ DUMP_VAR(p_Tgec->p_MemMap, status);
+ DUMP_VAR(p_Tgec->p_MemMap, tx_ipg_len);
+ DUMP_VAR(p_Tgec->p_MemMap, mac_addr_2);
+ DUMP_VAR(p_Tgec->p_MemMap, mac_addr_3);
+ DUMP_VAR(p_Tgec->p_MemMap, rx_fifo_ptr_rd);
+ DUMP_VAR(p_Tgec->p_MemMap, rx_fifo_ptr_wr);
+ DUMP_VAR(p_Tgec->p_MemMap, tx_fifo_ptr_rd);
+ DUMP_VAR(p_Tgec->p_MemMap, tx_fifo_ptr_wr);
+ DUMP_VAR(p_Tgec->p_MemMap, imask);
+ DUMP_VAR(p_Tgec->p_MemMap, ievent);
+ }
+
+ return E_OK;
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+
+/*****************************************************************************/
+/* FM Init & Free API */
+/*****************************************************************************/
+
+/* ......................................................................... */
+
+static t_Error TgecInit(t_Handle h_Tgec)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+ struct tgec_cfg *p_TgecDriverParam;
+ t_EnetAddr ethAddr;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_TgecDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_Tgec->fmMacControllerDriver.h_Fm, E_INVALID_HANDLE);
+
+ FM_GetRevision(p_Tgec->fmMacControllerDriver.h_Fm, &p_Tgec->fmMacControllerDriver.fmRevInfo);
+ CHECK_INIT_PARAMETERS(p_Tgec, CheckInitParameters);
+
+ p_TgecDriverParam = p_Tgec->p_TgecDriverParam;
+
+ MAKE_ENET_ADDR_FROM_UINT64(p_Tgec->addr, ethAddr);
+ fman_tgec_set_mac_address(p_Tgec->p_MemMap, (uint8_t *)ethAddr);
+
+ /* interrupts */
+#ifdef FM_10G_REM_N_LCL_FLT_EX_10GMAC_ERRATA_SW005
+ {
+ if (p_Tgec->fmMacControllerDriver.fmRevInfo.majorRev <=2)
+ p_Tgec->exceptions &= ~(TGEC_IMASK_REM_FAULT | TGEC_IMASK_LOC_FAULT);
+ }
+#endif /* FM_10G_REM_N_LCL_FLT_EX_10GMAC_ERRATA_SW005 */
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+ if (!p_Tgec->p_TgecDriverParam->skip_fman11_workaround &&
+ ((err = TgecTxEccWorkaround(p_Tgec)) != E_OK))
+ {
+ FreeInitResources(p_Tgec);
+ REPORT_ERROR(MINOR, err, ("TgecTxEccWorkaround FAILED"));
+ }
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+ err = fman_tgec_init(p_Tgec->p_MemMap, p_TgecDriverParam, p_Tgec->exceptions);
+ if (err)
+ {
+ FreeInitResources(p_Tgec);
+ RETURN_ERROR(MAJOR, err, ("This TGEC version does not support the required i/f mode"));
+ }
+
+ /* Max Frame Length */
+ err = FmSetMacMaxFrame(p_Tgec->fmMacControllerDriver.h_Fm,
+ e_FM_MAC_10G,
+ p_Tgec->fmMacControllerDriver.macId,
+ p_TgecDriverParam->max_frame_length);
+ /* we consider having no IPC a non crasher... */
+
+#ifdef FM_TX_FIFO_CORRUPTION_ERRATA_10GMAC_A007
+ if (p_Tgec->fmMacControllerDriver.fmRevInfo.majorRev == 2)
+ fman_tgec_set_erratum_tx_fifo_corruption_10gmac_a007(p_Tgec->p_MemMap);
+#endif /* FM_TX_FIFO_CORRUPTION_ERRATA_10GMAC_A007 */
+
+ p_Tgec->p_MulticastAddrHash = AllocHashTable(HASH_TABLE_SIZE);
+ if (!p_Tgec->p_MulticastAddrHash)
+ {
+ FreeInitResources(p_Tgec);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("allocation hash table is FAILED"));
+ }
+
+ p_Tgec->p_UnicastAddrHash = AllocHashTable(HASH_TABLE_SIZE);
+ if (!p_Tgec->p_UnicastAddrHash)
+ {
+ FreeInitResources(p_Tgec);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("allocation hash table is FAILED"));
+ }
+
+ FmRegisterIntr(p_Tgec->fmMacControllerDriver.h_Fm,
+ e_FM_MOD_10G_MAC,
+ p_Tgec->macId,
+ e_FM_INTR_TYPE_ERR,
+ TgecErrException,
+ p_Tgec);
+ if ((p_Tgec->mdioIrq != 0) && (p_Tgec->mdioIrq != NO_IRQ))
+ {
+ XX_SetIntr(p_Tgec->mdioIrq, TgecException, p_Tgec);
+ XX_EnableIntr(p_Tgec->mdioIrq);
+ }
+ else if (p_Tgec->mdioIrq == 0)
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED, (NO_MSG));
+
+ XX_Free(p_TgecDriverParam);
+ p_Tgec->p_TgecDriverParam = NULL;
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static t_Error TgecFree(t_Handle h_Tgec)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+
+ FreeInitResources(p_Tgec);
+
+ if (p_Tgec->p_TgecDriverParam)
+ {
+ XX_Free(p_Tgec->p_TgecDriverParam);
+ p_Tgec->p_TgecDriverParam = NULL;
+ }
+ XX_Free (p_Tgec);
+
+ return E_OK;
+}
+
+/* ......................................................................... */
+
+static void InitFmMacControllerDriver(t_FmMacControllerDriver *p_FmMacControllerDriver)
+{
+ p_FmMacControllerDriver->f_FM_MAC_Init = TgecInit;
+ p_FmMacControllerDriver->f_FM_MAC_Free = TgecFree;
+
+ p_FmMacControllerDriver->f_FM_MAC_SetStatistics = NULL;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback = TgecConfigLoopback;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength = TgecConfigMaxFrameLength;
+
+ p_FmMacControllerDriver->f_FM_MAC_ConfigWan = TgecConfigWan;
+
+ p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc = NULL; /* TGEC always works with pad+crc */
+ p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex = NULL; /* half-duplex is not supported in xgec */
+ p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck = TgecConfigLengthCheck;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigException = TgecConfigException;
+ p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit = NULL;
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+ p_FmMacControllerDriver->f_FM_MAC_ConfigSkipFman11Workaround= TgecConfigSkipFman11Workaround;
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+ p_FmMacControllerDriver->f_FM_MAC_SetException = TgecSetExcpetion;
+
+ p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp = TgecEnable1588TimeStamp;
+ p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp = TgecDisable1588TimeStamp;
+
+ p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous = TgecSetPromiscuous;
+ p_FmMacControllerDriver->f_FM_MAC_AdjustLink = NULL;
+ p_FmMacControllerDriver->f_FM_MAC_SetWakeOnLan = NULL;
+ p_FmMacControllerDriver->f_FM_MAC_RestartAutoneg = NULL;
+
+ p_FmMacControllerDriver->f_FM_MAC_Enable = TgecEnable;
+ p_FmMacControllerDriver->f_FM_MAC_Disable = TgecDisable;
+
+ p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames = TgecTxMacPause;
+ p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames = TgecSetTxPauseFrames;
+ p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames = TgecRxIgnoreMacPause;
+
+ p_FmMacControllerDriver->f_FM_MAC_ResetCounters = TgecResetCounters;
+ p_FmMacControllerDriver->f_FM_MAC_GetStatistics = TgecGetStatistics;
+
+ p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr = TgecModifyMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr = TgecAddHashMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr = TgecDelHashMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr = TgecAddExactMatchMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr = TgecDelExactMatchMacAddress;
+ p_FmMacControllerDriver->f_FM_MAC_GetId = TgecGetId;
+ p_FmMacControllerDriver->f_FM_MAC_GetVersion = TgecGetVersion;
+ p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength = TgecGetMaxFrameLength;
+
+ p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg = TGEC_MII_WritePhyReg;
+ p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg = TGEC_MII_ReadPhyReg;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ p_FmMacControllerDriver->f_FM_MAC_DumpRegs = TgecDumpRegs;
+#endif /* (defined(DEBUG_ERRORS) && ... */
+}
+
+
+/*****************************************************************************/
+/* Tgec Config Main Entry */
+/*****************************************************************************/
+
+/* ......................................................................... */
+
+t_Handle TGEC_Config(t_FmMacParams *p_FmMacParam)
+{
+ t_Tgec *p_Tgec;
+ struct tgec_cfg *p_TgecDriverParam;
+ uintptr_t baseAddr;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmMacParam, E_NULL_POINTER, NULL);
+
+ baseAddr = p_FmMacParam->baseAddr;
+ /* allocate memory for the UCC GETH data structure. */
+ p_Tgec = (t_Tgec *)XX_Malloc(sizeof(t_Tgec));
+ if (!p_Tgec)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("10G MAC driver structure"));
+ return NULL;
+ }
+ memset(p_Tgec, 0, sizeof(t_Tgec));
+ InitFmMacControllerDriver(&p_Tgec->fmMacControllerDriver);
+
+ /* allocate memory for the 10G MAC driver parameters data structure. */
+ p_TgecDriverParam = (struct tgec_cfg *) XX_Malloc(sizeof(struct tgec_cfg));
+ if (!p_TgecDriverParam)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("10G MAC driver parameters"));
+ TgecFree(p_Tgec);
+ return NULL;
+ }
+ memset(p_TgecDriverParam, 0, sizeof(struct tgec_cfg));
+
+ /* Plant parameter structure pointer */
+ p_Tgec->p_TgecDriverParam = p_TgecDriverParam;
+
+ fman_tgec_defconfig(p_TgecDriverParam);
+
+ p_Tgec->p_MemMap = (struct tgec_regs *)UINT_TO_PTR(baseAddr);
+ p_Tgec->p_MiiMemMap = (t_TgecMiiAccessMemMap *)UINT_TO_PTR(baseAddr + TGEC_TO_MII_OFFSET);
+ p_Tgec->addr = ENET_ADDR_TO_UINT64(p_FmMacParam->addr);
+ p_Tgec->enetMode = p_FmMacParam->enetMode;
+ p_Tgec->macId = p_FmMacParam->macId;
+ p_Tgec->exceptions = DEFAULT_exceptions;
+ p_Tgec->mdioIrq = p_FmMacParam->mdioIrq;
+ p_Tgec->f_Exception = p_FmMacParam->f_Exception;
+ p_Tgec->f_Event = p_FmMacParam->f_Event;
+ p_Tgec->h_App = p_FmMacParam->h_App;
+
+ return p_Tgec;
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec.h
new file mode 100644
index 0000000..2aa3923
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File tgec.h
+
+ @Description FM 10G MAC ...
+*//***************************************************************************/
+#ifndef __TGEC_H
+#define __TGEC_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "list_ext.h"
+#include "enet_ext.h"
+
+#include "tgec_mii_acc.h"
+#include "fm_mac.h"
+
+
+#define DEFAULT_exceptions \
+ ((uint32_t)(TGEC_IMASK_MDIO_SCAN_EVENT | \
+ TGEC_IMASK_REM_FAULT | \
+ TGEC_IMASK_LOC_FAULT | \
+ TGEC_IMASK_TX_ECC_ER | \
+ TGEC_IMASK_TX_FIFO_UNFL | \
+ TGEC_IMASK_TX_FIFO_OVFL | \
+ TGEC_IMASK_TX_ER | \
+ TGEC_IMASK_RX_FIFO_OVFL | \
+ TGEC_IMASK_RX_ECC_ER | \
+ TGEC_IMASK_RX_JAB_FRM | \
+ TGEC_IMASK_RX_OVRSZ_FRM | \
+ TGEC_IMASK_RX_RUNT_FRM | \
+ TGEC_IMASK_RX_FRAG_FRM | \
+ TGEC_IMASK_RX_CRC_ER | \
+ TGEC_IMASK_RX_ALIGN_ER))
+
+#define GET_EXCEPTION_FLAG(bitMask, exception) switch (exception){ \
+ case e_FM_MAC_EX_10G_MDIO_SCAN_EVENTMDIO: \
+ bitMask = TGEC_IMASK_MDIO_SCAN_EVENT ; break; \
+ case e_FM_MAC_EX_10G_MDIO_CMD_CMPL: \
+ bitMask = TGEC_IMASK_MDIO_CMD_CMPL ; break; \
+ case e_FM_MAC_EX_10G_REM_FAULT: \
+ bitMask = TGEC_IMASK_REM_FAULT ; break; \
+ case e_FM_MAC_EX_10G_LOC_FAULT: \
+ bitMask = TGEC_IMASK_LOC_FAULT ; break; \
+ case e_FM_MAC_EX_10G_1TX_ECC_ER: \
+ bitMask = TGEC_IMASK_TX_ECC_ER ; break; \
+ case e_FM_MAC_EX_10G_TX_FIFO_UNFL: \
+ bitMask = TGEC_IMASK_TX_FIFO_UNFL ; break; \
+ case e_FM_MAC_EX_10G_TX_FIFO_OVFL: \
+ bitMask = TGEC_IMASK_TX_FIFO_OVFL ; break; \
+ case e_FM_MAC_EX_10G_TX_ER: \
+ bitMask = TGEC_IMASK_TX_ER ; break; \
+ case e_FM_MAC_EX_10G_RX_FIFO_OVFL: \
+ bitMask = TGEC_IMASK_RX_FIFO_OVFL ; break; \
+ case e_FM_MAC_EX_10G_RX_ECC_ER: \
+ bitMask = TGEC_IMASK_RX_ECC_ER ; break; \
+ case e_FM_MAC_EX_10G_RX_JAB_FRM: \
+ bitMask = TGEC_IMASK_RX_JAB_FRM ; break; \
+ case e_FM_MAC_EX_10G_RX_OVRSZ_FRM: \
+ bitMask = TGEC_IMASK_RX_OVRSZ_FRM ; break; \
+ case e_FM_MAC_EX_10G_RX_RUNT_FRM: \
+ bitMask = TGEC_IMASK_RX_RUNT_FRM ; break; \
+ case e_FM_MAC_EX_10G_RX_FRAG_FRM: \
+ bitMask = TGEC_IMASK_RX_FRAG_FRM ; break; \
+ case e_FM_MAC_EX_10G_RX_LEN_ER: \
+ bitMask = TGEC_IMASK_RX_LEN_ER ; break; \
+ case e_FM_MAC_EX_10G_RX_CRC_ER: \
+ bitMask = TGEC_IMASK_RX_CRC_ER ; break; \
+ case e_FM_MAC_EX_10G_RX_ALIGN_ER: \
+ bitMask = TGEC_IMASK_RX_ALIGN_ER ; break; \
+ default: bitMask = 0;break;}
+
+#define MAX_PACKET_ALIGNMENT 31
+#define MAX_INTER_PACKET_GAP 0x7f
+#define MAX_INTER_PALTERNATE_BEB 0x0f
+#define MAX_RETRANSMISSION 0x0f
+#define MAX_COLLISION_WINDOW 0x03ff
+
+#define TGEC_NUM_OF_PADDRS 1 /* number of pattern match registers (entries) */
+
+#define GROUP_ADDRESS 0x0000010000000000LL /* Group address bit indication */
+
+#define HASH_TABLE_SIZE 512 /* Hash table size (= 32 bits * 8 regs) */
+
+#define TGEC_TO_MII_OFFSET 0x1030 /* Offset from the MEM map to the MDIO mem map */
+
+/* 10-gigabit Ethernet MAC Controller ID (10GEC_ID) */
+#define TGEC_ID_ID 0xffff0000
+#define TGEC_ID_MAC_VERSION 0x0000FF00
+#define TGEC_ID_MAC_REV 0x000000ff
+
+
+typedef struct {
+ t_FmMacControllerDriver fmMacControllerDriver; /**< Upper Mac control block */
+ t_Handle h_App; /**< Handle to the upper layer application */
+ struct tgec_regs *p_MemMap; /**< pointer to 10G memory mapped registers. */
+ t_TgecMiiAccessMemMap *p_MiiMemMap; /**< pointer to MII memory mapped registers. */
+ uint64_t addr; /**< MAC address of device; */
+ e_EnetMode enetMode; /**< Ethernet physical interface */
+ t_FmMacExceptionCallback *f_Exception;
+ int mdioIrq;
+ t_FmMacExceptionCallback *f_Event;
+ bool indAddrRegUsed[TGEC_NUM_OF_PADDRS]; /**< Whether a particular individual address recognition register is being used */
+ uint64_t paddr[TGEC_NUM_OF_PADDRS]; /**< MAC address for particular individual address recognition register */
+ uint8_t numOfIndAddrInRegs; /**< Number of individual addresses in registers for this station. */
+ t_EthHash *p_MulticastAddrHash; /**< pointer to driver's global address hash table */
+ t_EthHash *p_UnicastAddrHash; /**< pointer to driver's individual address hash table */
+ bool debugMode;
+ uint8_t macId;
+ uint32_t exceptions;
+ struct tgec_cfg *p_TgecDriverParam;
+} t_Tgec;
+
+
+t_Error TGEC_MII_WritePhyReg(t_Handle h_Tgec, uint8_t phyAddr, uint8_t reg, uint16_t data);
+t_Error TGEC_MII_ReadPhyReg(t_Handle h_Tgec, uint8_t phyAddr, uint8_t reg, uint16_t *p_Data);
+
+
+#endif /* __TGEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec_mii_acc.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec_mii_acc.c
new file mode 100644
index 0000000..e0fafd1
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec_mii_acc.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+#include "error_ext.h"
+#include "std_ext.h"
+#include "fm_mac.h"
+#include "tgec.h"
+#include "xx_ext.h"
+
+#include "fm_common.h"
+
+
+/*****************************************************************************/
+t_Error TGEC_MII_WritePhyReg(t_Handle h_Tgec,
+ uint8_t phyAddr,
+ uint8_t reg,
+ uint16_t data)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+ t_TgecMiiAccessMemMap *p_MiiAccess;
+ uint32_t cfgStatusReg;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_MiiMemMap, E_INVALID_HANDLE);
+
+ p_MiiAccess = p_Tgec->p_MiiMemMap;
+
+ /* Configure MII */
+ cfgStatusReg = GET_UINT32(p_MiiAccess->mdio_cfg_status);
+ cfgStatusReg &= ~MIIMCOM_DIV_MASK;
+ /* (one half of fm clock => 2.5Mhz) */
+ cfgStatusReg |=((((p_Tgec->fmMacControllerDriver.clkFreq*10)/2)/25) << MIIMCOM_DIV_SHIFT);
+ WRITE_UINT32(p_MiiAccess->mdio_cfg_status, cfgStatusReg);
+
+ while ((GET_UINT32(p_MiiAccess->mdio_cfg_status)) & MIIMIND_BUSY)
+ XX_UDelay (1);
+
+ WRITE_UINT32(p_MiiAccess->mdio_command, phyAddr);
+
+ WRITE_UINT32(p_MiiAccess->mdio_regaddr, reg);
+
+ CORE_MemoryBarrier();
+
+ while ((GET_UINT32(p_MiiAccess->mdio_cfg_status)) & MIIMIND_BUSY)
+ XX_UDelay (1);
+
+ WRITE_UINT32(p_MiiAccess->mdio_data, data);
+
+ CORE_MemoryBarrier();
+
+ while ((GET_UINT32(p_MiiAccess->mdio_data)) & MIIDATA_BUSY)
+ XX_UDelay (1);
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error TGEC_MII_ReadPhyReg(t_Handle h_Tgec,
+ uint8_t phyAddr,
+ uint8_t reg,
+ uint16_t *p_Data)
+{
+ t_Tgec *p_Tgec = (t_Tgec *)h_Tgec;
+ t_TgecMiiAccessMemMap *p_MiiAccess;
+ uint32_t cfgStatusReg;
+
+ SANITY_CHECK_RETURN_ERROR(p_Tgec, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Tgec->p_MiiMemMap, E_INVALID_HANDLE);
+
+ p_MiiAccess = p_Tgec->p_MiiMemMap;
+
+ /* Configure MII */
+ cfgStatusReg = GET_UINT32(p_MiiAccess->mdio_cfg_status);
+ cfgStatusReg &= ~MIIMCOM_DIV_MASK;
+ /* (one half of fm clock => 2.5Mhz) */
+ cfgStatusReg |=((((p_Tgec->fmMacControllerDriver.clkFreq*10)/2)/25) << MIIMCOM_DIV_SHIFT);
+ WRITE_UINT32(p_MiiAccess->mdio_cfg_status, cfgStatusReg);
+
+ while ((GET_UINT32(p_MiiAccess->mdio_cfg_status)) & MIIMIND_BUSY)
+ XX_UDelay (1);
+
+ WRITE_UINT32(p_MiiAccess->mdio_command, phyAddr);
+
+ WRITE_UINT32(p_MiiAccess->mdio_regaddr, reg);
+
+ CORE_MemoryBarrier();
+
+ while ((GET_UINT32(p_MiiAccess->mdio_cfg_status)) & MIIMIND_BUSY)
+ XX_UDelay (1);
+
+ WRITE_UINT32(p_MiiAccess->mdio_command, (uint32_t)(phyAddr | MIIMCOM_READ_CYCLE));
+
+ CORE_MemoryBarrier();
+
+ while ((GET_UINT32(p_MiiAccess->mdio_data)) & MIIDATA_BUSY)
+ XX_UDelay (1);
+
+ *p_Data = (uint16_t)GET_UINT32(p_MiiAccess->mdio_data);
+
+ cfgStatusReg = GET_UINT32(p_MiiAccess->mdio_cfg_status);
+
+ if (cfgStatusReg & MIIMIND_READ_ERROR)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE,
+ ("Read Error: phyAddr 0x%x, dev 0x%x, reg 0x%x, cfgStatusReg 0x%x",
+ ((phyAddr & 0xe0)>>5), (phyAddr & 0x1f), reg, cfgStatusReg));
+
+ return E_OK;
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec_mii_acc.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec_mii_acc.h
new file mode 100644
index 0000000..645cdde
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/tgec_mii_acc.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __TGEC_MII_ACC_H
+#define __TGEC_MII_ACC_H
+
+#include "std_ext.h"
+
+
+/* MII Management Command Register */
+#define MIIMCOM_READ_POST_INCREMENT 0x00004000
+#define MIIMCOM_READ_CYCLE 0x00008000
+#define MIIMCOM_SCAN_CYCLE 0x00000800
+#define MIIMCOM_PREAMBLE_DISABLE 0x00000400
+
+#define MIIMCOM_MDIO_HOLD_1_REG_CLK 0
+#define MIIMCOM_MDIO_HOLD_2_REG_CLK 1
+#define MIIMCOM_MDIO_HOLD_3_REG_CLK 2
+#define MIIMCOM_MDIO_HOLD_4_REG_CLK 3
+
+#define MIIMCOM_DIV_MASK 0x0000ff00
+#define MIIMCOM_DIV_SHIFT 8
+
+/* MII Management Indicator Register */
+#define MIIMIND_BUSY 0x00000001
+#define MIIMIND_READ_ERROR 0x00000002
+
+#define MIIDATA_BUSY 0x80000000
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+/*----------------------------------------------------*/
+/* MII Configuration Control Memory Map Registers */
+/*----------------------------------------------------*/
+typedef _Packed struct t_TgecMiiAccessMemMap
+{
+ volatile uint32_t mdio_cfg_status; /* 0x030 */
+ volatile uint32_t mdio_command; /* 0x034 */
+ volatile uint32_t mdio_data; /* 0x038 */
+ volatile uint32_t mdio_regaddr; /* 0x03c */
+} _PackedType t_TgecMiiAccessMemMap ;
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+#endif /* __TGEC_MII_ACC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Makefile b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Makefile
new file mode 100644
index 0000000..e02b57e
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Makefile
@@ -0,0 +1,22 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc
+
+EXTRA_CFLAGS += -I$(NCSW_FM_INC)
+
+
+obj-y += fsl-ncsw-PFM1.o
+
+fsl-ncsw-PFM1-objs := fm.o fm_muram.o fman.o
+
+obj-y += MAC/
+obj-y += Pcd/
+obj-y += SP/
+obj-y += Port/
+obj-y += HC/
+obj-y += Rtc/
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/Makefile b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/Makefile
new file mode 100644
index 0000000..70c7d7e
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/Makefile
@@ -0,0 +1,19 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+
+NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc
+
+EXTRA_CFLAGS += -I$(NCSW_FM_INC)
+
+obj-y += fsl-ncsw-Pcd.o
+
+fsl-ncsw-Pcd-objs := fman_kg.o fman_prs.o fm_cc.o fm_kg.o fm_pcd.o fm_plcr.o fm_prs.o fm_manip.o
+
+ifeq ($(CONFIG_FMAN_T4240),y)
+fsl-ncsw-Pcd-objs += fm_replic.o
+endif
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/crc64.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/crc64.h
new file mode 100644
index 0000000..335ee68
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/crc64.h
@@ -0,0 +1,360 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+ /**************************************************************************//**
+ @File crc64.h
+
+ @Description brief This file contains the CRC64 Table, and __inline__
+ functions used for calculating crc.
+*//***************************************************************************/
+#ifndef __CRC64_H
+#define __CRC64_H
+
+#include "std_ext.h"
+
+
+#define BITS_PER_BYTE 8
+
+#define CRC64_EXPON_ECMA_182 0xC96C5795D7870F42ULL
+#define CRC64_DEFAULT_INITVAL 0xFFFFFFFFFFFFFFFFULL
+
+#define CRC64_BYTE_MASK 0xFF
+#define CRC64_TABLE_ENTRIES ( 1 << BITS_PER_BYTE )
+#define CRC64_ODD_MASK 1
+
+
+/**
+ \brief '64 bit crc' Table
+ */
+struct crc64_t {
+ uint64_t initial; /**< Initial seed */
+ uint64_t table[CRC64_TABLE_ENTRIES]; /**< CRC table entries */
+};
+
+
+static struct crc64_t CRC64_ECMA_182 = {
+ CRC64_DEFAULT_INITVAL,
+ {
+ 0x0000000000000000ULL,
+ 0xb32e4cbe03a75f6fULL,
+ 0xf4843657a840a05bULL,
+ 0x47aa7ae9abe7ff34ULL,
+ 0x7bd0c384ff8f5e33ULL,
+ 0xc8fe8f3afc28015cULL,
+ 0x8f54f5d357cffe68ULL,
+ 0x3c7ab96d5468a107ULL,
+ 0xf7a18709ff1ebc66ULL,
+ 0x448fcbb7fcb9e309ULL,
+ 0x0325b15e575e1c3dULL,
+ 0xb00bfde054f94352ULL,
+ 0x8c71448d0091e255ULL,
+ 0x3f5f08330336bd3aULL,
+ 0x78f572daa8d1420eULL,
+ 0xcbdb3e64ab761d61ULL,
+ 0x7d9ba13851336649ULL,
+ 0xceb5ed8652943926ULL,
+ 0x891f976ff973c612ULL,
+ 0x3a31dbd1fad4997dULL,
+ 0x064b62bcaebc387aULL,
+ 0xb5652e02ad1b6715ULL,
+ 0xf2cf54eb06fc9821ULL,
+ 0x41e11855055bc74eULL,
+ 0x8a3a2631ae2dda2fULL,
+ 0x39146a8fad8a8540ULL,
+ 0x7ebe1066066d7a74ULL,
+ 0xcd905cd805ca251bULL,
+ 0xf1eae5b551a2841cULL,
+ 0x42c4a90b5205db73ULL,
+ 0x056ed3e2f9e22447ULL,
+ 0xb6409f5cfa457b28ULL,
+ 0xfb374270a266cc92ULL,
+ 0x48190ecea1c193fdULL,
+ 0x0fb374270a266cc9ULL,
+ 0xbc9d3899098133a6ULL,
+ 0x80e781f45de992a1ULL,
+ 0x33c9cd4a5e4ecdceULL,
+ 0x7463b7a3f5a932faULL,
+ 0xc74dfb1df60e6d95ULL,
+ 0x0c96c5795d7870f4ULL,
+ 0xbfb889c75edf2f9bULL,
+ 0xf812f32ef538d0afULL,
+ 0x4b3cbf90f69f8fc0ULL,
+ 0x774606fda2f72ec7ULL,
+ 0xc4684a43a15071a8ULL,
+ 0x83c230aa0ab78e9cULL,
+ 0x30ec7c140910d1f3ULL,
+ 0x86ace348f355aadbULL,
+ 0x3582aff6f0f2f5b4ULL,
+ 0x7228d51f5b150a80ULL,
+ 0xc10699a158b255efULL,
+ 0xfd7c20cc0cdaf4e8ULL,
+ 0x4e526c720f7dab87ULL,
+ 0x09f8169ba49a54b3ULL,
+ 0xbad65a25a73d0bdcULL,
+ 0x710d64410c4b16bdULL,
+ 0xc22328ff0fec49d2ULL,
+ 0x85895216a40bb6e6ULL,
+ 0x36a71ea8a7ace989ULL,
+ 0x0adda7c5f3c4488eULL,
+ 0xb9f3eb7bf06317e1ULL,
+ 0xfe5991925b84e8d5ULL,
+ 0x4d77dd2c5823b7baULL,
+ 0x64b62bcaebc387a1ULL,
+ 0xd7986774e864d8ceULL,
+ 0x90321d9d438327faULL,
+ 0x231c512340247895ULL,
+ 0x1f66e84e144cd992ULL,
+ 0xac48a4f017eb86fdULL,
+ 0xebe2de19bc0c79c9ULL,
+ 0x58cc92a7bfab26a6ULL,
+ 0x9317acc314dd3bc7ULL,
+ 0x2039e07d177a64a8ULL,
+ 0x67939a94bc9d9b9cULL,
+ 0xd4bdd62abf3ac4f3ULL,
+ 0xe8c76f47eb5265f4ULL,
+ 0x5be923f9e8f53a9bULL,
+ 0x1c4359104312c5afULL,
+ 0xaf6d15ae40b59ac0ULL,
+ 0x192d8af2baf0e1e8ULL,
+ 0xaa03c64cb957be87ULL,
+ 0xeda9bca512b041b3ULL,
+ 0x5e87f01b11171edcULL,
+ 0x62fd4976457fbfdbULL,
+ 0xd1d305c846d8e0b4ULL,
+ 0x96797f21ed3f1f80ULL,
+ 0x2557339fee9840efULL,
+ 0xee8c0dfb45ee5d8eULL,
+ 0x5da24145464902e1ULL,
+ 0x1a083bacedaefdd5ULL,
+ 0xa9267712ee09a2baULL,
+ 0x955cce7fba6103bdULL,
+ 0x267282c1b9c65cd2ULL,
+ 0x61d8f8281221a3e6ULL,
+ 0xd2f6b4961186fc89ULL,
+ 0x9f8169ba49a54b33ULL,
+ 0x2caf25044a02145cULL,
+ 0x6b055fede1e5eb68ULL,
+ 0xd82b1353e242b407ULL,
+ 0xe451aa3eb62a1500ULL,
+ 0x577fe680b58d4a6fULL,
+ 0x10d59c691e6ab55bULL,
+ 0xa3fbd0d71dcdea34ULL,
+ 0x6820eeb3b6bbf755ULL,
+ 0xdb0ea20db51ca83aULL,
+ 0x9ca4d8e41efb570eULL,
+ 0x2f8a945a1d5c0861ULL,
+ 0x13f02d374934a966ULL,
+ 0xa0de61894a93f609ULL,
+ 0xe7741b60e174093dULL,
+ 0x545a57dee2d35652ULL,
+ 0xe21ac88218962d7aULL,
+ 0x5134843c1b317215ULL,
+ 0x169efed5b0d68d21ULL,
+ 0xa5b0b26bb371d24eULL,
+ 0x99ca0b06e7197349ULL,
+ 0x2ae447b8e4be2c26ULL,
+ 0x6d4e3d514f59d312ULL,
+ 0xde6071ef4cfe8c7dULL,
+ 0x15bb4f8be788911cULL,
+ 0xa6950335e42fce73ULL,
+ 0xe13f79dc4fc83147ULL,
+ 0x521135624c6f6e28ULL,
+ 0x6e6b8c0f1807cf2fULL,
+ 0xdd45c0b11ba09040ULL,
+ 0x9aefba58b0476f74ULL,
+ 0x29c1f6e6b3e0301bULL,
+ 0xc96c5795d7870f42ULL,
+ 0x7a421b2bd420502dULL,
+ 0x3de861c27fc7af19ULL,
+ 0x8ec62d7c7c60f076ULL,
+ 0xb2bc941128085171ULL,
+ 0x0192d8af2baf0e1eULL,
+ 0x4638a2468048f12aULL,
+ 0xf516eef883efae45ULL,
+ 0x3ecdd09c2899b324ULL,
+ 0x8de39c222b3eec4bULL,
+ 0xca49e6cb80d9137fULL,
+ 0x7967aa75837e4c10ULL,
+ 0x451d1318d716ed17ULL,
+ 0xf6335fa6d4b1b278ULL,
+ 0xb199254f7f564d4cULL,
+ 0x02b769f17cf11223ULL,
+ 0xb4f7f6ad86b4690bULL,
+ 0x07d9ba1385133664ULL,
+ 0x4073c0fa2ef4c950ULL,
+ 0xf35d8c442d53963fULL,
+ 0xcf273529793b3738ULL,
+ 0x7c0979977a9c6857ULL,
+ 0x3ba3037ed17b9763ULL,
+ 0x888d4fc0d2dcc80cULL,
+ 0x435671a479aad56dULL,
+ 0xf0783d1a7a0d8a02ULL,
+ 0xb7d247f3d1ea7536ULL,
+ 0x04fc0b4dd24d2a59ULL,
+ 0x3886b22086258b5eULL,
+ 0x8ba8fe9e8582d431ULL,
+ 0xcc0284772e652b05ULL,
+ 0x7f2cc8c92dc2746aULL,
+ 0x325b15e575e1c3d0ULL,
+ 0x8175595b76469cbfULL,
+ 0xc6df23b2dda1638bULL,
+ 0x75f16f0cde063ce4ULL,
+ 0x498bd6618a6e9de3ULL,
+ 0xfaa59adf89c9c28cULL,
+ 0xbd0fe036222e3db8ULL,
+ 0x0e21ac88218962d7ULL,
+ 0xc5fa92ec8aff7fb6ULL,
+ 0x76d4de52895820d9ULL,
+ 0x317ea4bb22bfdfedULL,
+ 0x8250e80521188082ULL,
+ 0xbe2a516875702185ULL,
+ 0x0d041dd676d77eeaULL,
+ 0x4aae673fdd3081deULL,
+ 0xf9802b81de97deb1ULL,
+ 0x4fc0b4dd24d2a599ULL,
+ 0xfceef8632775faf6ULL,
+ 0xbb44828a8c9205c2ULL,
+ 0x086ace348f355aadULL,
+ 0x34107759db5dfbaaULL,
+ 0x873e3be7d8faa4c5ULL,
+ 0xc094410e731d5bf1ULL,
+ 0x73ba0db070ba049eULL,
+ 0xb86133d4dbcc19ffULL,
+ 0x0b4f7f6ad86b4690ULL,
+ 0x4ce50583738cb9a4ULL,
+ 0xffcb493d702be6cbULL,
+ 0xc3b1f050244347ccULL,
+ 0x709fbcee27e418a3ULL,
+ 0x3735c6078c03e797ULL,
+ 0x841b8ab98fa4b8f8ULL,
+ 0xadda7c5f3c4488e3ULL,
+ 0x1ef430e13fe3d78cULL,
+ 0x595e4a08940428b8ULL,
+ 0xea7006b697a377d7ULL,
+ 0xd60abfdbc3cbd6d0ULL,
+ 0x6524f365c06c89bfULL,
+ 0x228e898c6b8b768bULL,
+ 0x91a0c532682c29e4ULL,
+ 0x5a7bfb56c35a3485ULL,
+ 0xe955b7e8c0fd6beaULL,
+ 0xaeffcd016b1a94deULL,
+ 0x1dd181bf68bdcbb1ULL,
+ 0x21ab38d23cd56ab6ULL,
+ 0x9285746c3f7235d9ULL,
+ 0xd52f0e859495caedULL,
+ 0x6601423b97329582ULL,
+ 0xd041dd676d77eeaaULL,
+ 0x636f91d96ed0b1c5ULL,
+ 0x24c5eb30c5374ef1ULL,
+ 0x97eba78ec690119eULL,
+ 0xab911ee392f8b099ULL,
+ 0x18bf525d915feff6ULL,
+ 0x5f1528b43ab810c2ULL,
+ 0xec3b640a391f4fadULL,
+ 0x27e05a6e926952ccULL,
+ 0x94ce16d091ce0da3ULL,
+ 0xd3646c393a29f297ULL,
+ 0x604a2087398eadf8ULL,
+ 0x5c3099ea6de60cffULL,
+ 0xef1ed5546e415390ULL,
+ 0xa8b4afbdc5a6aca4ULL,
+ 0x1b9ae303c601f3cbULL,
+ 0x56ed3e2f9e224471ULL,
+ 0xe5c372919d851b1eULL,
+ 0xa26908783662e42aULL,
+ 0x114744c635c5bb45ULL,
+ 0x2d3dfdab61ad1a42ULL,
+ 0x9e13b115620a452dULL,
+ 0xd9b9cbfcc9edba19ULL,
+ 0x6a978742ca4ae576ULL,
+ 0xa14cb926613cf817ULL,
+ 0x1262f598629ba778ULL,
+ 0x55c88f71c97c584cULL,
+ 0xe6e6c3cfcadb0723ULL,
+ 0xda9c7aa29eb3a624ULL,
+ 0x69b2361c9d14f94bULL,
+ 0x2e184cf536f3067fULL,
+ 0x9d36004b35545910ULL,
+ 0x2b769f17cf112238ULL,
+ 0x9858d3a9ccb67d57ULL,
+ 0xdff2a94067518263ULL,
+ 0x6cdce5fe64f6dd0cULL,
+ 0x50a65c93309e7c0bULL,
+ 0xe388102d33392364ULL,
+ 0xa4226ac498dedc50ULL,
+ 0x170c267a9b79833fULL,
+ 0xdcd7181e300f9e5eULL,
+ 0x6ff954a033a8c131ULL,
+ 0x28532e49984f3e05ULL,
+ 0x9b7d62f79be8616aULL,
+ 0xa707db9acf80c06dULL,
+ 0x14299724cc279f02ULL,
+ 0x5383edcd67c06036ULL,
+ 0xe0ada17364673f59ULL
+ }
+};
+
+
+/**
+ \brief Initializes the crc seed
+ */
+static __inline__ uint64_t crc64_init(void)
+{
+ return CRC64_ECMA_182.initial;
+}
+
+/**
+ \brief Computes 64 bit the crc
+ \param[in] data Pointer to the Data in the frame
+ \param[in] len Length of the Data
+ \param[in] crc seed
+ \return calculated crc
+ */
+static __inline__ uint64_t crc64_compute(void const *data,
+ uint32_t len,
+ uint64_t seed)
+{
+ uint32_t i;
+ uint64_t crc = seed;
+ uint8_t *bdata = (uint8_t *) data;
+
+ for (i = 0; i < len; i++)
+ crc =
+ CRC64_ECMA_182.
+ table[(crc ^ *bdata++) & CRC64_BYTE_MASK] ^ (crc >> 8);
+
+ return crc;
+}
+
+
+#endif /* __CRC64_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.c
new file mode 100644
index 0000000..fa17dc7
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.c
@@ -0,0 +1,7120 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_cc.c
+
+ @Description FM Coarse Classifier implementation
+*//***************************************************************************/
+#include "std_ext.h"
+#include "error_ext.h"
+#include "string_ext.h"
+#include "debug_ext.h"
+#include "fm_pcd_ext.h"
+#include "fm_muram_ext.h"
+
+#include "fm_common.h"
+#include "fm_pcd.h"
+#include "fm_hc.h"
+#include "fm_cc.h"
+#include "crc64.h"
+
+
+/****************************************/
+/* static functions */
+/****************************************/
+
+
+static t_Error CcRootTryLock(t_Handle h_FmPcdCcTree)
+{
+ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree;
+
+ ASSERT_COND(h_FmPcdCcTree);
+
+ if (FmPcdLockTryLock(p_FmPcdCcTree->p_Lock))
+ return E_OK;
+
+ return ERROR_CODE(E_BUSY);
+}
+
+static void CcRootReleaseLock(t_Handle h_FmPcdCcTree)
+{
+ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree;
+
+ ASSERT_COND(h_FmPcdCcTree);
+
+ FmPcdLockUnlock(p_FmPcdCcTree->p_Lock);
+}
+
+static void UpdateNodeOwner(t_FmPcdCcNode *p_CcNode, bool add)
+{
+ uint32_t intFlags;
+
+ ASSERT_COND(p_CcNode);
+
+ intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock);
+
+ if (add)
+ p_CcNode->owners++;
+ else
+ {
+ ASSERT_COND(p_CcNode->owners);
+ p_CcNode->owners--;
+ }
+
+ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
+}
+
+static __inline__ t_FmPcdStatsObj* DequeueStatsObj(t_List *p_List)
+{
+ t_FmPcdStatsObj *p_StatsObj = NULL;
+ t_List *p_Next;
+
+ if (!LIST_IsEmpty(p_List))
+ {
+ p_Next = LIST_FIRST(p_List);
+ p_StatsObj = LIST_OBJECT(p_Next, t_FmPcdStatsObj, node);
+ ASSERT_COND(p_StatsObj);
+ LIST_DelAndInit(p_Next);
+ }
+
+ return p_StatsObj;
+}
+
+static __inline__ void EnqueueStatsObj(t_List *p_List,
+ t_FmPcdStatsObj *p_StatsObj)
+{
+ LIST_AddToTail(&p_StatsObj->node, p_List);
+}
+
+static void FreeStatObjects(t_List *p_List,
+ t_Handle h_FmMuram)
+{
+ t_FmPcdStatsObj *p_StatsObj;
+
+ while (!LIST_IsEmpty(p_List))
+ {
+ p_StatsObj = DequeueStatsObj(p_List);
+ ASSERT_COND(p_StatsObj);
+
+ FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsAd);
+ FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsCounters);
+
+ XX_Free(p_StatsObj);
+ }
+}
+
+static t_FmPcdStatsObj* GetStatsObj(t_FmPcdCcNode *p_CcNode)
+{
+ t_FmPcdStatsObj* p_StatsObj;
+ t_Handle h_FmMuram;
+
+ ASSERT_COND(p_CcNode);
+
+ /* If 'maxNumOfKeys' was passed, all statistics object were preallocated
+ upon node initialization */
+ if (p_CcNode->maxNumOfKeys)
+ {
+ p_StatsObj = DequeueStatsObj(&p_CcNode->availableStatsLst);
+ }
+ else
+ {
+ h_FmMuram = ((t_FmPcd *)(p_CcNode->h_FmPcd))->h_FmMuram;
+ ASSERT_COND(h_FmMuram);
+
+ p_StatsObj = XX_Malloc(sizeof(t_FmPcdStatsObj));
+ if (!p_StatsObj)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("statistics object"));
+ return NULL;
+ }
+
+ p_StatsObj->h_StatsAd = (t_Handle)FM_MURAM_AllocMem(h_FmMuram,
+ FM_PCD_CC_AD_ENTRY_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!p_StatsObj->h_StatsAd)
+ {
+ XX_Free(p_StatsObj);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for statistics ADs"));
+ return NULL;
+ }
+ IOMemSet32(p_StatsObj->h_StatsAd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ p_StatsObj->h_StatsCounters = (t_Handle)FM_MURAM_AllocMem(h_FmMuram,
+ p_CcNode->countersArraySize,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!p_StatsObj->h_StatsCounters)
+ {
+ FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsAd);
+ XX_Free(p_StatsObj);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for statistics counters"));
+ return NULL;
+ }
+ IOMemSet32(p_StatsObj->h_StatsCounters, 0, p_CcNode->countersArraySize);
+ }
+
+ return p_StatsObj;
+}
+
+static void PutStatsObj(t_FmPcdCcNode *p_CcNode,
+ t_FmPcdStatsObj *p_StatsObj)
+{
+ t_Handle h_FmMuram;
+
+ ASSERT_COND(p_CcNode);
+ ASSERT_COND(p_StatsObj);
+
+ /* If 'maxNumOfKeys' was passed, all statistics object were preallocated
+ upon node initialization and now will be enqueued back to the list */
+ if (p_CcNode->maxNumOfKeys)
+ {
+ /* Nullify counters */
+ IOMemSet32(p_StatsObj->h_StatsCounters, 0, p_CcNode->countersArraySize);
+
+ EnqueueStatsObj(&p_CcNode->availableStatsLst, p_StatsObj);
+ }
+ else
+ {
+ h_FmMuram = ((t_FmPcd *)(p_CcNode->h_FmPcd))->h_FmMuram;
+ ASSERT_COND(h_FmMuram);
+
+ FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsAd);
+ FM_MURAM_FreeMem(h_FmMuram, p_StatsObj->h_StatsCounters);
+
+ XX_Free(p_StatsObj);
+ }
+}
+
+static void SetStatsCounters(t_AdOfTypeStats *p_StatsAd,
+ uint32_t statsCountersAddr)
+{
+ uint32_t tmp = (statsCountersAddr & FM_PCD_AD_STATS_COUNTERS_ADDR_MASK);
+
+ WRITE_UINT32(p_StatsAd->statsTableAddr, tmp);
+}
+
+
+static void UpdateStatsAd(t_FmPcdCcStatsParams *p_FmPcdCcStatsParams,
+ t_Handle h_Ad,
+ uint64_t physicalMuramBase)
+{
+ t_AdOfTypeStats *p_StatsAd;
+ uint32_t statsCountersAddr, nextActionAddr, tmp;
+#if (DPAA_VERSION >= 11)
+ uint32_t frameLengthRangesAddr;
+#endif /* (DPAA_VERSION >= 11) */
+
+ p_StatsAd = (t_AdOfTypeStats *)p_FmPcdCcStatsParams->h_StatsAd;
+
+ tmp = FM_PCD_AD_STATS_TYPE;
+
+#if (DPAA_VERSION >= 11)
+ if (p_FmPcdCcStatsParams->h_StatsFLRs)
+ {
+ frameLengthRangesAddr = (uint32_t)((XX_VirtToPhys(p_FmPcdCcStatsParams->h_StatsFLRs) - physicalMuramBase));
+ tmp |= (frameLengthRangesAddr & FM_PCD_AD_STATS_FLR_ADDR_MASK);
+ }
+#endif /* (DPAA_VERSION >= 11) */
+ WRITE_UINT32(p_StatsAd->profileTableAddr, tmp);
+
+ nextActionAddr = (uint32_t)((XX_VirtToPhys(h_Ad) - physicalMuramBase));
+ tmp = 0;
+ tmp |= (uint32_t)((nextActionAddr << FM_PCD_AD_STATS_NEXT_ACTION_SHIFT) & FM_PCD_AD_STATS_NEXT_ACTION_MASK);
+ tmp |= (FM_PCD_AD_STATS_NAD_EN | FM_PCD_AD_STATS_OP_CODE);
+
+#if (DPAA_VERSION >= 11)
+ if (p_FmPcdCcStatsParams->h_StatsFLRs)
+ tmp |= FM_PCD_AD_STATS_FLR_EN;
+#endif /* (DPAA_VERSION >= 11) */
+
+ WRITE_UINT32(p_StatsAd->nextActionIndx, tmp);
+
+ statsCountersAddr = (uint32_t)((XX_VirtToPhys(p_FmPcdCcStatsParams->h_StatsCounters) - physicalMuramBase));
+ SetStatsCounters(p_StatsAd, statsCountersAddr);
+}
+
+static void FillAdOfTypeContLookup(t_Handle h_Ad,
+ t_FmPcdCcStatsParams *p_FmPcdCcStatsParams,
+ t_Handle h_FmPcd,
+ t_Handle p_CcNode,
+ t_Handle h_Manip,
+ t_Handle h_FrmReplic)
+{
+ t_FmPcdCcNode *p_Node = (t_FmPcdCcNode *)p_CcNode;
+ t_AdOfTypeContLookup *p_AdContLookup = (t_AdOfTypeContLookup *)h_Ad;
+ t_Handle h_TmpAd;
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t tmpReg32;
+ t_Handle p_AdNewPtr = NULL;
+
+ UNUSED(h_Manip);
+ UNUSED(h_FrmReplic);
+
+ /* there are 3 cases handled in this routine of building a "Continue lookup" type AD.
+ * Case 1: No Manip. The action descriptor is built within the match table.
+ * p_AdResult = p_AdNewPtr;
+ * Case 2: Manip exists. A new AD is created - p_AdNewPtr. It is initialized
+ * either in the FmPcdManipUpdateAdResultForCc routine or it was already
+ * initialized and returned here.
+ * p_AdResult (within the match table) will be initialized after
+ * this routine returns and point to the existing AD.
+ * Case 3: Manip exists. The action descriptor is built within the match table.
+ * FmPcdManipUpdateAdContLookupForCc returns a NULL p_AdNewPtr.
+ */
+
+ /* As default, the "new" ptr is the current one. i.e. the content of the result
+ * AD will be written into the match table itself (case (1))*/
+ p_AdNewPtr = p_AdContLookup;
+
+ /* Initialize an action descriptor, if current statistics mode requires an Ad */
+ if (p_FmPcdCcStatsParams)
+ {
+ ASSERT_COND(p_FmPcdCcStatsParams->h_StatsAd);
+ ASSERT_COND(p_FmPcdCcStatsParams->h_StatsCounters);
+
+ /* Swapping addresses between statistics Ad and the current lookup AD */
+ h_TmpAd = p_FmPcdCcStatsParams->h_StatsAd;
+ p_FmPcdCcStatsParams->h_StatsAd = h_Ad;
+ h_Ad = h_TmpAd;
+
+ p_AdNewPtr = h_Ad;
+ p_AdContLookup = h_Ad;
+
+ /* Init statistics Ad and connect current lookup AD as 'next action' from statistics Ad */
+ UpdateStatsAd(p_FmPcdCcStatsParams,
+ h_Ad,
+ p_FmPcd->physicalMuramBase);
+ }
+
+#if DPAA_VERSION >= 11
+ if (h_Manip && h_FrmReplic)
+ FmPcdManipUpdateAdContLookupForCc(h_Manip,
+ h_Ad,
+ &p_AdNewPtr,
+ (uint32_t)((XX_VirtToPhys(FrmReplicGroupGetSourceTableDescriptor(h_FrmReplic)) - p_FmPcd->physicalMuramBase)));
+ else if (h_FrmReplic)
+ FrmReplicGroupUpdateAd(h_FrmReplic, h_Ad, &p_AdNewPtr);
+ else
+#endif /* (DPAA_VERSION >= 11) */
+ if (h_Manip)
+ FmPcdManipUpdateAdContLookupForCc(h_Manip,
+ h_Ad,
+ &p_AdNewPtr,
+
+#ifdef FM_CAPWAP_SUPPORT
+ /*no check for opcode of manip - this step can be reached only with capwap_applic_specific*/
+ (uint32_t)((XX_VirtToPhys(p_Node->h_AdTable) - p_FmPcd->physicalMuramBase))
+#else /* not FM_CAPWAP_SUPPORT */
+ (uint32_t)((XX_VirtToPhys(p_Node->h_Ad) - p_FmPcd->physicalMuramBase))
+#endif /* not FM_CAPWAP_SUPPORT */
+ );
+
+ /* if (p_AdNewPtr = NULL) --> Done. (case (3)) */
+ if (p_AdNewPtr)
+ {
+ /* cases (1) & (2) */
+ tmpReg32 = 0;
+ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE;
+ tmpReg32 |= p_Node->sizeOfExtraction ? ((p_Node->sizeOfExtraction - 1) << 24) : 0;
+ tmpReg32 |= (uint32_t)(XX_VirtToPhys(p_Node->h_AdTable) - p_FmPcd->physicalMuramBase);
+ WRITE_UINT32(p_AdContLookup->ccAdBase, tmpReg32);
+
+ tmpReg32 = 0;
+ tmpReg32 |= p_Node->numOfKeys << 24;
+ tmpReg32 |= (p_Node->lclMask ? FM_PCD_AD_CONT_LOOKUP_LCL_MASK : 0);
+ tmpReg32 |= p_Node->h_KeysMatchTable ?
+ (uint32_t)(XX_VirtToPhys(p_Node->h_KeysMatchTable) - p_FmPcd->physicalMuramBase) : 0;
+ WRITE_UINT32(p_AdContLookup->matchTblPtr, tmpReg32);
+
+ tmpReg32 = 0;
+ tmpReg32 |= p_Node->prsArrayOffset << 24;
+ tmpReg32 |= p_Node->offset << 16;
+ tmpReg32 |= p_Node->parseCode;
+ WRITE_UINT32(p_AdContLookup->pcAndOffsets, tmpReg32);
+
+ Mem2IOCpy32((void*)&p_AdContLookup->gmask, p_Node->p_GlblMask, CC_GLBL_MASK_SIZE);
+ }
+}
+
+static t_Error AllocAndFillAdForContLookupManip(t_Handle h_CcNode)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ uint32_t intFlags;
+
+ ASSERT_COND(p_CcNode);
+
+ intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock);
+
+ if (!p_CcNode->h_Ad)
+ {
+ if (p_CcNode->maxNumOfKeys)
+ p_CcNode->h_Ad = p_CcNode->h_TmpAd;
+ else
+ p_CcNode->h_Ad = (t_Handle)FM_MURAM_AllocMem(((t_FmPcd *)(p_CcNode->h_FmPcd))->h_FmMuram,
+ FM_PCD_CC_AD_ENTRY_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+
+ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
+
+ if (!p_CcNode->h_Ad)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC action descriptor"));
+
+ IOMemSet32(p_CcNode->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ FillAdOfTypeContLookup(p_CcNode->h_Ad,
+ NULL,
+ p_CcNode->h_FmPcd,
+ p_CcNode,
+ NULL,
+ NULL);
+ }
+ else
+ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
+
+ return E_OK;
+}
+
+static t_Error SetRequiredAction(t_Handle h_FmPcd,
+ uint32_t requiredAction,
+ t_FmPcdCcKeyAndNextEngineParams *p_CcKeyAndNextEngineParamsTmp,
+ t_Handle h_AdTmp,
+ uint16_t numOfEntries,
+ t_Handle h_Tree)
+{
+ t_AdOfTypeResult *p_AdTmp = (t_AdOfTypeResult *)h_AdTmp;
+ uint32_t tmpReg32;
+ t_Error err;
+ t_FmPcdCcNode *p_CcNode;
+ int i = 0;
+ uint16_t tmp = 0;
+ uint16_t profileId;
+ uint8_t relativeSchemeId, physicalSchemeId;
+ t_CcNodeInformation ccNodeInfo;
+
+ for (i = 0; i < numOfEntries; i++)
+ {
+ if (i == 0)
+ h_AdTmp = PTR_MOVE(h_AdTmp, i*FM_PCD_CC_AD_ENTRY_SIZE);
+ else
+ h_AdTmp = PTR_MOVE(h_AdTmp, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ switch (p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.nextEngine)
+ {
+ case (e_FM_PCD_CC):
+ if (requiredAction)
+ {
+ p_CcNode = p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.ccParams.h_CcNode;
+ ASSERT_COND(p_CcNode);
+ if (p_CcNode->shadowAction == requiredAction)
+ break;
+ if ((requiredAction & UPDATE_CC_WITH_TREE) && !(p_CcNode->shadowAction & UPDATE_CC_WITH_TREE))
+ {
+
+ ASSERT_COND(LIST_NumOfObjs(&p_CcNode->ccTreesLst) == 0);
+ if (p_CcNode->shadowAction & UPDATE_CC_WITH_DELETE_TREE)
+ p_CcNode->shadowAction &= ~UPDATE_CC_WITH_DELETE_TREE;
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ ccNodeInfo.h_CcNode = h_Tree;
+ EnqueueNodeInfoToRelevantLst(&p_CcNode->ccTreesLst, &ccNodeInfo, NULL);
+ p_CcKeyAndNextEngineParamsTmp[i].shadowAction |= UPDATE_CC_WITH_TREE;
+ }
+ if ((requiredAction & UPDATE_CC_WITH_DELETE_TREE) && !(p_CcNode->shadowAction & UPDATE_CC_WITH_DELETE_TREE))
+ {
+ ASSERT_COND(LIST_NumOfObjs(&p_CcNode->ccTreesLst) == 1);
+ if (p_CcNode->shadowAction & UPDATE_CC_WITH_TREE)
+ p_CcNode->shadowAction &= ~UPDATE_CC_WITH_TREE;
+ DequeueNodeInfoFromRelevantLst(&p_CcNode->ccTreesLst, h_Tree, NULL);
+ p_CcKeyAndNextEngineParamsTmp[i].shadowAction |= UPDATE_CC_WITH_DELETE_TREE;
+ }
+ if (p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.nextEngine != e_FM_PCD_INVALID)
+ tmp = (uint8_t)(p_CcNode->numOfKeys + 1);
+ else
+ tmp = p_CcNode->numOfKeys;
+ err = SetRequiredAction(h_FmPcd,
+ requiredAction,
+ p_CcNode->keyAndNextEngineParams,
+ p_CcNode->h_AdTable,
+ tmp,
+ h_Tree);
+ if (err != E_OK)
+ return err;
+ p_CcNode->shadowAction |= requiredAction;
+ }
+ break;
+
+ case (e_FM_PCD_KG):
+ if ((requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) && !(p_CcKeyAndNextEngineParamsTmp[i].shadowAction & UPDATE_NIA_ENQ_WITHOUT_DMA))
+ {
+ physicalSchemeId = FmPcdKgGetSchemeId(p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.kgParams.h_DirectScheme);
+ relativeSchemeId = FmPcdKgGetRelativeSchemeId(h_FmPcd, physicalSchemeId);
+ if (relativeSchemeId == FM_PCD_KG_NUM_OF_SCHEMES)
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
+ if (!FmPcdKgIsSchemeValidSw(p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.kgParams.h_DirectScheme))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid direct scheme."));
+ if (!KgIsSchemeAlwaysDirect(h_FmPcd, relativeSchemeId))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For this action scheme has to be direct."));
+ err = FmPcdKgCcGetSetParams(h_FmPcd, p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.kgParams.h_DirectScheme, requiredAction, 0);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ p_CcKeyAndNextEngineParamsTmp[i].shadowAction |= requiredAction;
+ }
+ break;
+
+ case (e_FM_PCD_PLCR):
+ if ((requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) && !(p_CcKeyAndNextEngineParamsTmp[i].shadowAction & UPDATE_NIA_ENQ_WITHOUT_DMA))
+ {
+ if (!p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.plcrParams.overrideParams)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("In this initialization only overrideFqid can be initialized"));
+ if (!p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.plcrParams.sharedProfile)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("In this initialization only overrideFqid can be initialized"));
+ err = FmPcdPlcrGetAbsoluteIdByProfileParams(h_FmPcd, e_FM_PCD_PLCR_SHARED, NULL, p_CcKeyAndNextEngineParamsTmp[i].nextEngineParams.params.plcrParams.newRelativeProfileId, &profileId);
+ if (err!= E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ err = FmPcdPlcrCcGetSetParams(h_FmPcd, profileId, requiredAction);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ p_CcKeyAndNextEngineParamsTmp[i].shadowAction |= requiredAction;
+ }
+ break;
+
+ case (e_FM_PCD_DONE):
+ if ((requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA) && !(p_CcKeyAndNextEngineParamsTmp[i].shadowAction & UPDATE_NIA_ENQ_WITHOUT_DMA))
+ {
+ tmpReg32 = GET_UINT32(p_AdTmp->nia);
+ if ((tmpReg32 & GET_NIA_BMI_AC_ENQ_FRAME(h_FmPcd)) != GET_NIA_BMI_AC_ENQ_FRAME(h_FmPcd))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine was previously assigned not as PCD_DONE"));
+ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA;
+ WRITE_UINT32(p_AdTmp->nia, tmpReg32);
+ p_CcKeyAndNextEngineParamsTmp[i].shadowAction |= requiredAction;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return E_OK;
+}
+
+static t_Error ReleaseModifiedDataStructure(t_Handle h_FmPcd,
+ t_List *h_FmPcdOldPointersLst,
+ t_List *h_FmPcdNewPointersLst,
+ uint16_t numOfGoodChanges,
+ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalParams,
+ bool useShadowStructs)
+{
+ t_List *p_Pos;
+ t_Error err = E_OK;
+ t_CcNodeInformation ccNodeInfo, *p_CcNodeInformation;
+ t_Handle h_Muram;
+ t_FmPcdCcNode *p_FmPcdCcNextNode;
+ t_List *p_UpdateLst;
+ uint32_t intFlags;
+
+ UNUSED(numOfGoodChanges);
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_AdditionalParams->h_CurrentNode,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(h_FmPcdOldPointersLst,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(h_FmPcdNewPointersLst,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((numOfGoodChanges == LIST_NumOfObjs(h_FmPcdOldPointersLst)),E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR((1 == LIST_NumOfObjs(h_FmPcdNewPointersLst)),E_INVALID_STATE);
+
+ /* We don't update subtree of the new node with new tree because it was done in the previous stage */
+ if (p_AdditionalParams->h_NodeForAdd)
+ {
+ p_FmPcdCcNextNode = (t_FmPcdCcNode*)p_AdditionalParams->h_NodeForAdd;
+
+ if (!p_AdditionalParams->tree)
+ p_UpdateLst = &p_FmPcdCcNextNode->ccPrevNodesLst;
+ else
+ p_UpdateLst = &p_FmPcdCcNextNode->ccTreeIdLst;
+
+ p_CcNodeInformation = FindNodeInfoInReleventLst(p_UpdateLst,
+ p_AdditionalParams->h_CurrentNode,
+ p_FmPcdCcNextNode->h_Spinlock);
+
+ if (p_CcNodeInformation)
+ p_CcNodeInformation->index++;
+ else
+ {
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ ccNodeInfo.h_CcNode = (t_Handle)p_AdditionalParams->h_CurrentNode;
+ ccNodeInfo.index = 1;
+ EnqueueNodeInfoToRelevantLst(p_UpdateLst,
+ &ccNodeInfo,
+ p_FmPcdCcNextNode->h_Spinlock);
+ }
+ if (p_AdditionalParams->h_ManipForAdd)
+ {
+ p_CcNodeInformation = FindNodeInfoInReleventLst(FmPcdManipGetNodeLstPointedOnThisManip(p_AdditionalParams->h_ManipForAdd),
+ p_AdditionalParams->h_CurrentNode,
+ FmPcdManipGetSpinlock(p_AdditionalParams->h_ManipForAdd));
+
+ if (p_CcNodeInformation)
+ p_CcNodeInformation->index++;
+ else
+ {
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ ccNodeInfo.h_CcNode = (t_Handle)p_AdditionalParams->h_CurrentNode;
+ ccNodeInfo.index = 1;
+ EnqueueNodeInfoToRelevantLst(FmPcdManipGetNodeLstPointedOnThisManip(p_AdditionalParams->h_ManipForAdd),
+ &ccNodeInfo,
+ FmPcdManipGetSpinlock(p_AdditionalParams->h_ManipForAdd));
+ }
+ }
+ }
+
+ if (p_AdditionalParams->h_NodeForRmv)
+ {
+ p_FmPcdCcNextNode = (t_FmPcdCcNode*)p_AdditionalParams->h_NodeForRmv;
+
+ if (!p_AdditionalParams->tree)
+ {
+ p_UpdateLst = &p_FmPcdCcNextNode->ccPrevNodesLst;
+
+ while (!LIST_IsEmpty(&p_FmPcdCcNextNode->ccTreesLst))
+ {
+ p_Pos = LIST_NEXT(&p_FmPcdCcNextNode->ccTreesLst);
+ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos);
+
+ ASSERT_COND(p_CcNodeInformation->h_CcNode);
+
+ err = SetRequiredAction(h_FmPcd,
+ UPDATE_CC_WITH_DELETE_TREE,
+ &((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->keyAndNextEngineParams[p_AdditionalParams->savedKeyIndex],
+ PTR_MOVE(((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_AdTable, p_AdditionalParams->savedKeyIndex*FM_PCD_CC_AD_ENTRY_SIZE),
+ 1,
+ p_CcNodeInformation->h_CcNode);
+ }
+ }
+ else
+ {
+ p_UpdateLst = &p_FmPcdCcNextNode->ccTreeIdLst;
+
+ err = SetRequiredAction(h_FmPcd,
+ UPDATE_CC_WITH_DELETE_TREE,
+ &((t_FmPcdCcTree *)(p_AdditionalParams->h_CurrentNode))->keyAndNextEngineParams[p_AdditionalParams->savedKeyIndex],
+ UINT_TO_PTR(((t_FmPcdCcTree *)(p_AdditionalParams->h_CurrentNode))->ccTreeBaseAddr + p_AdditionalParams->savedKeyIndex*FM_PCD_CC_AD_ENTRY_SIZE),
+ 1,
+ p_AdditionalParams->h_CurrentNode);
+ }
+ if (err)
+ return err;
+
+ /* We remove from the subtree of the removed node tree because it wasn't done in the previous stage
+ Update ccPrevNodesLst or ccTreeIdLst of the removed node
+ Update of the node owner */
+ p_CcNodeInformation = FindNodeInfoInReleventLst(p_UpdateLst,
+ p_AdditionalParams->h_CurrentNode,
+ p_FmPcdCcNextNode->h_Spinlock);
+
+ ASSERT_COND(p_CcNodeInformation);
+ ASSERT_COND(p_CcNodeInformation->index);
+
+ p_CcNodeInformation->index--;
+
+ if (p_CcNodeInformation->index == 0)
+ DequeueNodeInfoFromRelevantLst(p_UpdateLst,
+ p_AdditionalParams->h_CurrentNode,
+ p_FmPcdCcNextNode->h_Spinlock);
+
+ UpdateNodeOwner(p_FmPcdCcNextNode, FALSE);
+
+ if (p_AdditionalParams->h_ManipForRmv)
+ {
+ p_CcNodeInformation = FindNodeInfoInReleventLst(FmPcdManipGetNodeLstPointedOnThisManip(p_AdditionalParams->h_ManipForRmv),
+ p_AdditionalParams->h_CurrentNode,
+ FmPcdManipGetSpinlock(p_AdditionalParams->h_ManipForRmv));
+
+ ASSERT_COND(p_CcNodeInformation);
+ ASSERT_COND(p_CcNodeInformation->index);
+
+ p_CcNodeInformation->index--;
+
+ if (p_CcNodeInformation->index == 0)
+ DequeueNodeInfoFromRelevantLst(FmPcdManipGetNodeLstPointedOnThisManip(p_AdditionalParams->h_ManipForRmv),
+ p_AdditionalParams->h_CurrentNode,
+ FmPcdManipGetSpinlock(p_AdditionalParams->h_ManipForRmv));
+ }
+ }
+
+ if (p_AdditionalParams->h_ManipForRmv)
+ FmPcdManipUpdateOwner(p_AdditionalParams->h_ManipForRmv, FALSE);
+
+ if (p_AdditionalParams->p_StatsObjForRmv)
+ PutStatsObj((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode),
+ p_AdditionalParams->p_StatsObjForRmv);
+
+#if (DPAA_VERSION >= 11)
+ if (p_AdditionalParams->h_FrmReplicForRmv)
+ FrmReplicGroupUpdateOwner(p_AdditionalParams->h_FrmReplicForRmv,
+ FALSE/* remove */);
+#endif /* (DPAA_VERSION >= 11) */
+
+ if (!useShadowStructs)
+ {
+ h_Muram = FmPcdGetMuramHandle(h_FmPcd);
+ ASSERT_COND(h_Muram);
+
+ if ((p_AdditionalParams->tree &&
+ !((t_FmPcd *)h_FmPcd)->p_CcShadow) ||
+ (!p_AdditionalParams->tree &&
+ !((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->maxNumOfKeys))
+ {
+ /* We release new AD which was allocated and updated for copy from to actual AD */
+ p_Pos = LIST_FIRST(h_FmPcdNewPointersLst);
+ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos);
+ ASSERT_COND(p_CcNodeInformation->h_CcNode);
+ FM_MURAM_FreeMem(h_Muram, p_CcNodeInformation->h_CcNode);
+ }
+
+ /* Free Old data structure if it has to be freed - new data structure was allocated*/
+ if (p_AdditionalParams->p_AdTableOld)
+ FM_MURAM_FreeMem(h_Muram,p_AdditionalParams->p_AdTableOld);
+
+ if (p_AdditionalParams->p_KeysMatchTableOld)
+ FM_MURAM_FreeMem(h_Muram,p_AdditionalParams->p_KeysMatchTableOld);
+ }
+
+ /* Update current modified node with changed fields if it's required*/
+ if (!p_AdditionalParams->tree)
+ {
+ if (p_AdditionalParams->p_AdTableNew)
+ ((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_AdTable = p_AdditionalParams->p_AdTableNew;
+
+ if (p_AdditionalParams->p_KeysMatchTableNew)
+ ((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_KeysMatchTable = p_AdditionalParams->p_KeysMatchTableNew;
+
+ /* Locking node's spinlock before updating 'keys and next engine' structure,
+ as it maybe used to retrieve keys statistics */
+ intFlags = XX_LockIntrSpinlock(((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_Spinlock);
+
+ ((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->numOfKeys = p_AdditionalParams->numOfKeys;
+
+ memcpy(((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->keyAndNextEngineParams,
+ &p_AdditionalParams->keyAndNextEngineParams,
+ sizeof(t_FmPcdCcKeyAndNextEngineParams) * (CC_MAX_NUM_OF_KEYS));
+
+ XX_UnlockIntrSpinlock(((t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode))->h_Spinlock, intFlags);
+ }
+ else
+ {
+ uint8_t numEntries = ((t_FmPcdCcTree *)(p_AdditionalParams->h_CurrentNode))->numOfEntries;
+ ASSERT_COND(numEntries < FM_PCD_MAX_NUM_OF_CC_GROUPS);
+ memcpy(&((t_FmPcdCcTree *)(p_AdditionalParams->h_CurrentNode))->keyAndNextEngineParams,
+ &p_AdditionalParams->keyAndNextEngineParams,
+ sizeof(t_FmPcdCcKeyAndNextEngineParams) * numEntries);
+ }
+
+ ReleaseLst(h_FmPcdOldPointersLst);
+ ReleaseLst(h_FmPcdNewPointersLst);
+
+ XX_Free(p_AdditionalParams);
+
+ return E_OK;
+}
+
+static t_Handle BuildNewAd(t_Handle h_Ad,
+ t_FmPcdModifyCcKeyAdditionalParams *p_FmPcdModifyCcKeyAdditionalParams,
+ t_FmPcdCcNode *p_CcNode,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcdCcNode *p_FmPcdCcNodeTmp;
+
+ p_FmPcdCcNodeTmp = (t_FmPcdCcNode*)XX_Malloc(sizeof(t_FmPcdCcNode));
+ if (!p_FmPcdCcNodeTmp)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("p_FmPcdCcNodeTmp"));
+ return NULL;
+ }
+ memset(p_FmPcdCcNodeTmp, 0, sizeof(t_FmPcdCcNode));
+
+ p_FmPcdCcNodeTmp->numOfKeys = p_FmPcdModifyCcKeyAdditionalParams->numOfKeys;
+ p_FmPcdCcNodeTmp->h_KeysMatchTable = p_FmPcdModifyCcKeyAdditionalParams->p_KeysMatchTableNew;
+ p_FmPcdCcNodeTmp->h_AdTable = p_FmPcdModifyCcKeyAdditionalParams->p_AdTableNew;
+
+ p_FmPcdCcNodeTmp->lclMask = p_CcNode->lclMask;
+ p_FmPcdCcNodeTmp->parseCode = p_CcNode->parseCode;
+ p_FmPcdCcNodeTmp->offset = p_CcNode->offset;
+ p_FmPcdCcNodeTmp->prsArrayOffset = p_CcNode->prsArrayOffset;
+ p_FmPcdCcNodeTmp->ctrlFlow = p_CcNode->ctrlFlow;
+ p_FmPcdCcNodeTmp->ccKeySizeAccExtraction = p_CcNode->ccKeySizeAccExtraction;
+ p_FmPcdCcNodeTmp->sizeOfExtraction = p_CcNode->sizeOfExtraction;
+ p_FmPcdCcNodeTmp->glblMaskSize = p_CcNode->glblMaskSize;
+ p_FmPcdCcNodeTmp->p_GlblMask = p_CcNode->p_GlblMask;
+
+ if (p_FmPcdCcNextEngineParams->nextEngine == e_FM_PCD_CC)
+ {
+ if (p_FmPcdCcNextEngineParams->h_Manip)
+ {
+ if (AllocAndFillAdForContLookupManip(p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode)!= E_OK)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+ return NULL;
+ }
+ }
+ FillAdOfTypeContLookup(h_Ad,
+ NULL,
+ p_CcNode->h_FmPcd,
+ p_FmPcdCcNodeTmp,
+ p_FmPcdCcNextEngineParams->h_Manip,
+ NULL);
+ }
+
+#if (DPAA_VERSION >= 11)
+ if ((p_FmPcdCcNextEngineParams->nextEngine == e_FM_PCD_FR) &&
+ (p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic))
+ {
+ FillAdOfTypeContLookup(h_Ad,
+ NULL,
+ p_CcNode->h_FmPcd,
+ p_FmPcdCcNodeTmp,
+ p_FmPcdCcNextEngineParams->h_Manip,
+ p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic);
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ XX_Free(p_FmPcdCcNodeTmp);
+
+ return E_OK;
+}
+
+static t_Error DynamicChangeHc(t_Handle h_FmPcd,
+ t_List *h_OldPointersLst,
+ t_List *h_NewPointersLst,
+ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalParams,
+ bool useShadowStructs)
+{
+ t_List *p_PosOld, *p_PosNew;
+ uint32_t oldAdAddrOffset, newAdAddrOffset;
+ uint16_t i = 0;
+ t_Error err = E_OK;
+ uint8_t numOfModifiedPtr;
+
+ ASSERT_COND(h_FmPcd);
+ ASSERT_COND(h_OldPointersLst);
+ ASSERT_COND(h_NewPointersLst);
+
+ numOfModifiedPtr = (uint8_t)LIST_NumOfObjs(h_OldPointersLst);
+
+ p_PosNew = LIST_FIRST(h_NewPointersLst);
+ p_PosOld = LIST_FIRST(h_OldPointersLst);
+
+ /* Retrieve address of new AD */
+ newAdAddrOffset = FmPcdCcGetNodeAddrOffsetFromNodeInfo(h_FmPcd, p_PosNew);
+ if (newAdAddrOffset == (uint32_t)ILLEGAL_BASE)
+ {
+ ReleaseModifiedDataStructure(h_FmPcd,
+ h_OldPointersLst,
+ h_NewPointersLst,
+ 0,
+ p_AdditionalParams,
+ useShadowStructs);
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("New AD address"));
+ }
+
+ for (i=0; i<numOfModifiedPtr; i++)
+ {
+ /* Retrieve address of current AD */
+ oldAdAddrOffset = FmPcdCcGetNodeAddrOffsetFromNodeInfo(h_FmPcd, p_PosOld);
+ if (oldAdAddrOffset == (uint32_t)ILLEGAL_BASE)
+ {
+ ReleaseModifiedDataStructure(h_FmPcd,
+ h_OldPointersLst,
+ h_NewPointersLst,
+ i,
+ p_AdditionalParams,
+ useShadowStructs);
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Old AD address"));
+ }
+
+ /* Invoke host command to copy from new AD to old AD */
+ err = FmHcPcdCcDoDynamicChange(((t_FmPcd *)h_FmPcd)->h_Hc, oldAdAddrOffset, newAdAddrOffset);
+ if (err)
+ {
+ ReleaseModifiedDataStructure(h_FmPcd,
+ h_OldPointersLst,
+ h_NewPointersLst,
+ i,
+ p_AdditionalParams,
+ useShadowStructs);
+ RETURN_ERROR(MAJOR, err, ("For part of nodes changes are done - situation is danger"));
+ }
+
+ p_PosOld = LIST_NEXT(p_PosOld);
+ }
+
+ return E_OK;
+}
+
+static t_Error DoDynamicChange(t_Handle h_FmPcd,
+ t_List *h_OldPointersLst,
+ t_List *h_NewPointersLst,
+ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalParams,
+ bool useShadowStructs)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)(p_AdditionalParams->h_CurrentNode);
+ t_List *p_PosNew;
+ t_CcNodeInformation *p_CcNodeInfo;
+ t_FmPcdCcNextEngineParams nextEngineParams;
+ t_Handle h_Ad;
+ uint32_t keySize;
+ t_Error err = E_OK;
+ uint8_t numOfModifiedPtr;
+
+ ASSERT_COND(h_FmPcd);
+
+ SANITY_CHECK_RETURN_ERROR((LIST_NumOfObjs(h_OldPointersLst) >= 1),E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR((LIST_NumOfObjs(h_NewPointersLst) == 1),E_INVALID_STATE);
+
+ memset(&nextEngineParams, 0, sizeof(t_FmPcdCcNextEngineParams));
+
+ numOfModifiedPtr = (uint8_t)LIST_NumOfObjs(h_OldPointersLst);
+
+ p_PosNew = LIST_FIRST(h_NewPointersLst);
+
+ /* Invoke host-command to copy from the new Ad to existing Ads */
+ err = DynamicChangeHc(h_FmPcd, h_OldPointersLst, h_NewPointersLst, p_AdditionalParams, useShadowStructs);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (useShadowStructs)
+ {
+ /* When the host-command above has ended, the old structures are 'free'and we can update
+ them by copying from the new shadow structures. */
+ if (p_CcNode->lclMask)
+ keySize = (uint32_t)(2 * p_CcNode->ccKeySizeAccExtraction);
+ else
+ keySize = p_CcNode->ccKeySizeAccExtraction;
+
+ IO2IOCpy32(p_AdditionalParams->p_KeysMatchTableOld,
+ p_AdditionalParams->p_KeysMatchTableNew,
+ p_CcNode->maxNumOfKeys * keySize * sizeof (uint8_t));
+
+ IO2IOCpy32(p_AdditionalParams->p_AdTableOld,
+ p_AdditionalParams->p_AdTableNew,
+ (uint32_t)((p_CcNode->maxNumOfKeys + 1) * FM_PCD_CC_AD_ENTRY_SIZE));
+
+ /* Retrieve the address of the allocated Ad */
+ p_CcNodeInfo = CC_NODE_F_OBJECT(p_PosNew);
+ h_Ad = p_CcNodeInfo->h_CcNode;
+
+ /* Build a new Ad that holds the old (now updated) structures */
+ p_AdditionalParams->p_KeysMatchTableNew = p_AdditionalParams->p_KeysMatchTableOld;
+ p_AdditionalParams->p_AdTableNew = p_AdditionalParams->p_AdTableOld;
+
+ nextEngineParams.nextEngine = e_FM_PCD_CC;
+ nextEngineParams.params.ccParams.h_CcNode = (t_Handle)p_CcNode;
+
+ BuildNewAd(h_Ad, p_AdditionalParams, p_CcNode, &nextEngineParams);
+
+ /* HC to copy from the new Ad (old updated structures) to current Ad (uses shadow structures) */
+ err = DynamicChangeHc(h_FmPcd, h_OldPointersLst, h_NewPointersLst, p_AdditionalParams, useShadowStructs);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = ReleaseModifiedDataStructure(h_FmPcd,
+ h_OldPointersLst,
+ h_NewPointersLst,
+ numOfModifiedPtr,
+ p_AdditionalParams,
+ useShadowStructs);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+#ifdef FM_CAPWAP_SUPPORT
+static bool IsCapwapApplSpecific(t_Handle h_Node)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_Node;
+ bool isManipForCapwapApplSpecificBuild = FALSE;
+ int i = 0;
+
+ ASSERT_COND(h_Node);
+ /* assumption that this function called only for INDEXED_FLOW_ID - so no miss*/
+ for (i = 0; i < p_CcNode->numOfKeys; i++)
+ {
+ if ( p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip &&
+ FmPcdManipIsCapwapApplSpecific(p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip))
+ {
+ isManipForCapwapApplSpecificBuild = TRUE;
+ break;
+ }
+ }
+ return isManipForCapwapApplSpecificBuild;
+
+}
+#endif /* FM_CAPWAP_SUPPORT */
+
+static t_Error CcUpdateParam(t_Handle h_FmPcd,
+ t_Handle h_PcdParams,
+ t_Handle h_FmPort,
+ t_FmPcdCcKeyAndNextEngineParams *p_CcKeyAndNextEngineParams,
+ uint16_t numOfEntries,
+ t_Handle h_Ad,
+ bool validate,
+ uint16_t level,
+ t_Handle h_FmTree,
+ bool modify)
+{
+ t_FmPcdCcNode *p_CcNode;
+ t_Error err;
+ uint16_t tmp = 0;
+ int i = 0;
+ t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *) h_FmTree;
+
+ level++;
+
+ if (p_CcTree->h_IpReassemblyManip)
+ {
+ err = FmPcdManipUpdate(h_FmPcd,
+ h_PcdParams,
+ h_FmPort,
+ p_CcTree->h_IpReassemblyManip,
+ NULL,
+ validate,
+ level,
+ h_FmTree,
+ modify);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ if (numOfEntries)
+ {
+ for (i=0; i<numOfEntries; i++)
+ {
+ if (i == 0)
+ h_Ad = PTR_MOVE(h_Ad, i*FM_PCD_CC_AD_ENTRY_SIZE);
+ else
+ h_Ad = PTR_MOVE(h_Ad, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ if (p_CcKeyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ {
+ p_CcNode = p_CcKeyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode;
+ ASSERT_COND(p_CcNode);
+
+ if (p_CcKeyAndNextEngineParams[i].nextEngineParams.h_Manip)
+ {
+ err = FmPcdManipUpdate(h_FmPcd,
+ NULL,
+ h_FmPort,
+ p_CcKeyAndNextEngineParams[i].nextEngineParams.h_Manip,
+ h_Ad,
+ validate,
+ level,
+ h_FmTree,
+ modify);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ if (p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.nextEngine != e_FM_PCD_INVALID)
+ tmp = (uint8_t)(p_CcNode->numOfKeys + 1);
+ else
+ tmp = p_CcNode->numOfKeys;
+
+ err = CcUpdateParam(h_FmPcd,
+ h_PcdParams,
+ h_FmPort,
+ p_CcNode->keyAndNextEngineParams,
+ tmp,
+ p_CcNode->h_AdTable,
+ validate,
+ level,
+ h_FmTree,
+ modify);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ else
+ {
+ if (p_CcKeyAndNextEngineParams[i].nextEngineParams.h_Manip)
+ {
+ err = FmPcdManipUpdate(h_FmPcd,
+ NULL,
+ h_FmPort,
+ p_CcKeyAndNextEngineParams[i].nextEngineParams.h_Manip,
+ h_Ad,
+ validate,
+ level,
+ h_FmTree,
+ modify);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ }
+ }
+ }
+
+ return E_OK;
+}
+
+static ccPrivateInfo_t IcDefineCode(t_FmPcdCcNodeParams *p_CcNodeParam)
+{
+ switch (p_CcNodeParam->extractCcParams.extractNonHdr.action)
+ {
+ case (e_FM_PCD_ACTION_EXACT_MATCH):
+ switch (p_CcNodeParam->extractCcParams.extractNonHdr.src)
+ {
+ case (e_FM_PCD_EXTRACT_FROM_KEY):
+ return CC_PRIVATE_INFO_IC_KEY_EXACT_MATCH;
+ case (e_FM_PCD_EXTRACT_FROM_HASH):
+ return CC_PRIVATE_INFO_IC_HASH_EXACT_MATCH;
+ default:
+ return CC_PRIVATE_INFO_NONE;
+ }
+
+ case (e_FM_PCD_ACTION_INDEXED_LOOKUP):
+ switch (p_CcNodeParam->extractCcParams.extractNonHdr.src)
+ {
+ case (e_FM_PCD_EXTRACT_FROM_HASH):
+ return CC_PRIVATE_INFO_IC_HASH_INDEX_LOOKUP;
+ case (e_FM_PCD_EXTRACT_FROM_FLOW_ID):
+ return CC_PRIVATE_INFO_IC_DEQ_FQID_INDEX_LOOKUP;
+ default:
+ return CC_PRIVATE_INFO_NONE;
+ }
+
+ default:
+ break;
+ }
+
+ return CC_PRIVATE_INFO_NONE;
+}
+
+static t_CcNodeInformation * DequeueAdditionalInfoFromRelevantLst(t_List *p_List)
+{
+ t_CcNodeInformation *p_CcNodeInfo = NULL;
+
+ if (!LIST_IsEmpty(p_List))
+ {
+ p_CcNodeInfo = CC_NODE_F_OBJECT(p_List->p_Next);
+ LIST_DelAndInit(&p_CcNodeInfo->node);
+ }
+
+ return p_CcNodeInfo;
+}
+
+void ReleaseLst(t_List *p_List)
+{
+ t_CcNodeInformation *p_CcNodeInfo = NULL;
+
+ if (!LIST_IsEmpty(p_List))
+ {
+ p_CcNodeInfo = DequeueAdditionalInfoFromRelevantLst(p_List);
+ while (p_CcNodeInfo)
+ {
+ XX_Free(p_CcNodeInfo);
+ p_CcNodeInfo = DequeueAdditionalInfoFromRelevantLst(p_List);
+ }
+ }
+
+ LIST_Del(p_List);
+}
+
+static void DeleteNode(t_FmPcdCcNode *p_CcNode)
+{
+ uint32_t i;
+
+ if (!p_CcNode)
+ return;
+
+ if (p_CcNode->p_GlblMask)
+ {
+ XX_Free(p_CcNode->p_GlblMask);
+ p_CcNode->p_GlblMask = NULL;
+ }
+
+ if (p_CcNode->h_KeysMatchTable)
+ {
+ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd), p_CcNode->h_KeysMatchTable);
+ p_CcNode->h_KeysMatchTable = NULL;
+ }
+
+ if (p_CcNode->h_AdTable)
+ {
+ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd), p_CcNode->h_AdTable);
+ p_CcNode->h_AdTable = NULL;
+ }
+
+ if (p_CcNode->h_Ad)
+ {
+ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd), p_CcNode->h_Ad);
+ p_CcNode->h_Ad = NULL;
+ p_CcNode->h_TmpAd = NULL;
+ }
+
+ if (p_CcNode->h_StatsFLRs)
+ {
+ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd), p_CcNode->h_StatsFLRs);
+ p_CcNode->h_StatsFLRs = NULL;
+ }
+
+ if (p_CcNode->h_Spinlock)
+ {
+ XX_FreeSpinlock(p_CcNode->h_Spinlock);
+ p_CcNode->h_Spinlock = NULL;
+ }
+
+ /* Restore the original counters pointer instead of the mutual pointer (mutual to all hash buckets) */
+ if (p_CcNode->isHashBucket && (p_CcNode->statisticsMode != e_FM_PCD_CC_STATS_MODE_NONE))
+ p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].p_StatsObj->h_StatsCounters = p_CcNode->h_PrivMissStatsCounters;
+
+ /* Releasing all currently used statistics objects, including 'miss' entry */
+ for (i = 0; i < p_CcNode->numOfKeys + 1; i++)
+ if (p_CcNode->keyAndNextEngineParams[i].p_StatsObj)
+ PutStatsObj(p_CcNode, p_CcNode->keyAndNextEngineParams[i].p_StatsObj);
+
+ if (!LIST_IsEmpty(&p_CcNode->availableStatsLst))
+ {
+ t_Handle h_FmMuram = FmPcdGetMuramHandle(p_CcNode->h_FmPcd);
+ ASSERT_COND(h_FmMuram);
+
+ FreeStatObjects(&p_CcNode->availableStatsLst, h_FmMuram);
+ }
+
+ LIST_Del(&p_CcNode->availableStatsLst);
+
+ ReleaseLst(&p_CcNode->ccPrevNodesLst);
+ ReleaseLst(&p_CcNode->ccTreeIdLst);
+ ReleaseLst(&p_CcNode->ccTreesLst);
+
+ XX_Free(p_CcNode);
+}
+
+static void DeleteTree(t_FmPcdCcTree *p_FmPcdTree, t_FmPcd *p_FmPcd)
+{
+ if (p_FmPcdTree)
+ {
+ if (p_FmPcdTree->ccTreeBaseAddr)
+ {
+ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_FmPcd), UINT_TO_PTR(p_FmPcdTree->ccTreeBaseAddr));
+ p_FmPcdTree->ccTreeBaseAddr = 0;
+ }
+
+ ReleaseLst(&p_FmPcdTree->fmPortsLst);
+
+ XX_Free(p_FmPcdTree);
+ }
+}
+
+static void GetCcExtractKeySize(uint8_t parseCodeRealSize, uint8_t *parseCodeCcSize)
+{
+ if ((parseCodeRealSize > 0) && (parseCodeRealSize < 2))
+ *parseCodeCcSize = 1;
+ else if (parseCodeRealSize == 2)
+ *parseCodeCcSize = 2;
+ else if ((parseCodeRealSize > 2) && (parseCodeRealSize <= 4))
+ *parseCodeCcSize = 4;
+ else if ((parseCodeRealSize > 4) && (parseCodeRealSize <= 8))
+ *parseCodeCcSize = 8;
+ else if ((parseCodeRealSize > 8) && (parseCodeRealSize <= 16))
+ *parseCodeCcSize = 16;
+ else if ((parseCodeRealSize > 16) && (parseCodeRealSize <= 24))
+ *parseCodeCcSize = 24;
+ else if ((parseCodeRealSize > 24) && (parseCodeRealSize <= 32))
+ *parseCodeCcSize = 32;
+ else if ((parseCodeRealSize > 32) && (parseCodeRealSize <= 40))
+ *parseCodeCcSize = 40;
+ else if ((parseCodeRealSize > 40) && (parseCodeRealSize <= 48))
+ *parseCodeCcSize = 48;
+ else if ((parseCodeRealSize > 48) && (parseCodeRealSize <= 56))
+ *parseCodeCcSize = 56;
+ else
+ *parseCodeCcSize = 0;
+}
+
+static void GetSizeHeaderField(e_NetHeaderType hdr,
+ e_FmPcdHdrIndex index,
+ t_FmPcdFields field,
+ uint8_t *parseCodeRealSize)
+{
+ UNUSED(index);
+ switch (hdr)
+ {
+ case (HEADER_TYPE_ETH):
+ switch (field.eth)
+ {
+ case (NET_HEADER_FIELD_ETH_DA):
+ *parseCodeRealSize = 6;
+ break;
+
+ case (NET_HEADER_FIELD_ETH_SA):
+ *parseCodeRealSize = 6;
+ break;
+
+ case (NET_HEADER_FIELD_ETH_TYPE):
+ *parseCodeRealSize = 2;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported1"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+ break;
+
+ case (HEADER_TYPE_PPPoE):
+ switch (field.pppoe)
+ {
+ case (NET_HEADER_FIELD_PPPoE_PID):
+ *parseCodeRealSize = 2;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported1"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+ break;
+
+ case (HEADER_TYPE_VLAN):
+ switch (field.vlan)
+ {
+ case (NET_HEADER_FIELD_VLAN_TCI):
+ *parseCodeRealSize = 2;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported2"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+ break;
+
+ case (HEADER_TYPE_MPLS):
+ switch (field.mpls)
+ {
+ case (NET_HEADER_FIELD_MPLS_LABEL_STACK):
+ *parseCodeRealSize = 4;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported3"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+ break;
+
+ case (HEADER_TYPE_IPv4):
+ switch (field.ipv4)
+ {
+ case (NET_HEADER_FIELD_IPv4_DST_IP):
+ case (NET_HEADER_FIELD_IPv4_SRC_IP):
+ *parseCodeRealSize = 4;
+ break;
+
+ case (NET_HEADER_FIELD_IPv4_TOS):
+ case (NET_HEADER_FIELD_IPv4_PROTO):
+ *parseCodeRealSize = 1;
+ break;
+
+ case (NET_HEADER_FIELD_IPv4_DST_IP | NET_HEADER_FIELD_IPv4_SRC_IP):
+ *parseCodeRealSize = 8;
+ break;
+
+ case (NET_HEADER_FIELD_IPv4_TTL):
+ *parseCodeRealSize = 1;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported4"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+ break;
+
+ case (HEADER_TYPE_IPv6):
+ switch (field.ipv6)
+ {
+ case (NET_HEADER_FIELD_IPv6_VER | NET_HEADER_FIELD_IPv6_FL | NET_HEADER_FIELD_IPv6_TC):
+ *parseCodeRealSize = 4;
+ break;
+
+ case (NET_HEADER_FIELD_IPv6_NEXT_HDR):
+ case (NET_HEADER_FIELD_IPv6_HOP_LIMIT):
+ *parseCodeRealSize = 1;
+ break;
+
+ case (NET_HEADER_FIELD_IPv6_DST_IP):
+ case (NET_HEADER_FIELD_IPv6_SRC_IP):
+ *parseCodeRealSize = 16;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported5"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+ break;
+
+ case (HEADER_TYPE_IP):
+ switch (field.ip)
+ {
+ case (NET_HEADER_FIELD_IP_DSCP):
+ case (NET_HEADER_FIELD_IP_PROTO):
+ *parseCodeRealSize = 1;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported5"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+ break;
+
+ case (HEADER_TYPE_GRE):
+ switch (field.gre)
+ {
+ case ( NET_HEADER_FIELD_GRE_TYPE):
+ *parseCodeRealSize = 2;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported6"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+ break;
+
+ case (HEADER_TYPE_MINENCAP):
+ switch (field.minencap)
+ {
+ case (NET_HEADER_FIELD_MINENCAP_TYPE):
+ *parseCodeRealSize = 1;
+ break;
+
+ case (NET_HEADER_FIELD_MINENCAP_DST_IP):
+ case (NET_HEADER_FIELD_MINENCAP_SRC_IP):
+ *parseCodeRealSize = 4;
+ break;
+
+ case (NET_HEADER_FIELD_MINENCAP_SRC_IP | NET_HEADER_FIELD_MINENCAP_DST_IP):
+ *parseCodeRealSize = 8;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported7"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+ break;
+
+ case (HEADER_TYPE_TCP):
+ switch (field.tcp)
+ {
+ case (NET_HEADER_FIELD_TCP_PORT_SRC):
+ case (NET_HEADER_FIELD_TCP_PORT_DST):
+ *parseCodeRealSize = 2;
+ break;
+
+ case (NET_HEADER_FIELD_TCP_PORT_SRC | NET_HEADER_FIELD_TCP_PORT_DST):
+ *parseCodeRealSize = 4;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported8"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+ break;
+
+ case (HEADER_TYPE_UDP):
+ switch (field.udp)
+ {
+ case (NET_HEADER_FIELD_UDP_PORT_SRC):
+ case (NET_HEADER_FIELD_UDP_PORT_DST):
+ *parseCodeRealSize = 2;
+ break;
+
+ case (NET_HEADER_FIELD_UDP_PORT_SRC | NET_HEADER_FIELD_UDP_PORT_DST):
+ *parseCodeRealSize = 4;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported9"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported10"));
+ *parseCodeRealSize = CC_SIZE_ILLEGAL;
+ break;
+ }
+}
+
+t_Error ValidateNextEngineParams(t_Handle h_FmPcd,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams,
+ e_FmPcdCcStatsMode statsMode)
+{
+ uint16_t absoluteProfileId;
+ t_Error err = E_OK;
+ uint8_t relativeSchemeId;
+
+ if ((statsMode == e_FM_PCD_CC_STATS_MODE_NONE) &&
+ (p_FmPcdCcNextEngineParams->statisticsEn))
+ RETURN_ERROR(MAJOR, E_CONFLICT,
+ ("Statistics are requested for a key, but statistics mode was set"
+ "to 'NONE' upon initialization"));
+
+ switch (p_FmPcdCcNextEngineParams->nextEngine)
+ {
+ case (e_FM_PCD_INVALID):
+ err = E_NOT_SUPPORTED;
+ break;
+
+ case (e_FM_PCD_DONE):
+ if ((p_FmPcdCcNextEngineParams->params.enqueueParams.action == e_FM_PCD_ENQ_FRAME) &&
+ p_FmPcdCcNextEngineParams->params.enqueueParams.overrideFqid)
+ {
+ if (!p_FmPcdCcNextEngineParams->params.enqueueParams.newFqid)
+ RETURN_ERROR(MAJOR, E_CONFLICT, ("When overrideFqid is set, newFqid must not be zero"));
+ if (p_FmPcdCcNextEngineParams->params.enqueueParams.newFqid & ~0x00FFFFFF)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fqidForCtrlFlow must be between 1 and 2^24-1"));
+ }
+ break;
+
+ case (e_FM_PCD_KG):
+ relativeSchemeId = FmPcdKgGetRelativeSchemeId(h_FmPcd,
+ FmPcdKgGetSchemeId(p_FmPcdCcNextEngineParams->params.kgParams.h_DirectScheme));
+ if (relativeSchemeId == FM_PCD_KG_NUM_OF_SCHEMES)
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
+ if (!FmPcdKgIsSchemeValidSw(p_FmPcdCcNextEngineParams->params.kgParams.h_DirectScheme))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("not valid schemeIndex in KG next engine param"));
+ if (!KgIsSchemeAlwaysDirect(h_FmPcd, relativeSchemeId))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("CC Node may point only to a scheme that is always direct."));
+ break;
+
+ case (e_FM_PCD_PLCR):
+ if (p_FmPcdCcNextEngineParams->params.plcrParams.overrideParams)
+ {
+ /* if private policer profile, it may be uninitialized yet, therefore no checks are done at this stage */
+ if (p_FmPcdCcNextEngineParams->params.plcrParams.sharedProfile)
+ {
+ err = FmPcdPlcrGetAbsoluteIdByProfileParams(h_FmPcd,
+ e_FM_PCD_PLCR_SHARED,
+ NULL,
+ p_FmPcdCcNextEngineParams->params.plcrParams.newRelativeProfileId,
+ &absoluteProfileId);
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("Shared profile offset is out of range"));
+ if (!FmPcdPlcrIsProfileValid(h_FmPcd, absoluteProfileId))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid profile"));
+ }
+ }
+ break;
+
+ case (e_FM_PCD_HASH):
+ p_FmPcdCcNextEngineParams->nextEngine = e_FM_PCD_CC;
+ case (e_FM_PCD_CC):
+ if (!p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode)
+ RETURN_ERROR(MAJOR, E_NULL_POINTER, ("handler to next Node is NULL"));
+ break;
+
+#if (DPAA_VERSION >= 11)
+ case (e_FM_PCD_FR):
+ if (!p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic)
+ err = E_NOT_SUPPORTED;
+ break;
+#endif /* (DPAA_VERSION >= 11) */
+
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine is not correct"));
+ }
+
+
+ return err;
+}
+
+static uint8_t GetGenParseCode(t_Handle h_FmPcd,
+ e_FmPcdExtractFrom src,
+ uint32_t offset,
+ bool glblMask,
+ uint8_t *parseArrayOffset,
+ bool fromIc,
+ ccPrivateInfo_t icCode)
+{
+ UNUSED(h_FmPcd);
+
+ if (!fromIc)
+ {
+ switch (src)
+ {
+ case (e_FM_PCD_EXTRACT_FROM_FRAME_START):
+ if (glblMask)
+ return CC_PC_GENERIC_WITH_MASK ;
+ else
+ return CC_PC_GENERIC_WITHOUT_MASK;
+
+ case (e_FM_PCD_EXTRACT_FROM_CURR_END_OF_PARSE):
+ *parseArrayOffset = CC_PC_PR_NEXT_HEADER_OFFSET;
+ if (offset)
+ return CC_PR_OFFSET;
+ else
+ return CC_PR_WITHOUT_OFFSET;
+
+ default:
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 'extract from' src"));
+ return CC_PC_ILLEGAL;
+ }
+ }
+ else
+ {
+ switch (icCode)
+ {
+ case (CC_PRIVATE_INFO_IC_KEY_EXACT_MATCH):
+ *parseArrayOffset = 0x50;
+ return CC_PC_GENERIC_IC_GMASK;
+
+ case (CC_PRIVATE_INFO_IC_HASH_EXACT_MATCH):
+ *parseArrayOffset = 0x48;
+ return CC_PC_GENERIC_IC_GMASK;
+
+ case (CC_PRIVATE_INFO_IC_HASH_INDEX_LOOKUP):
+ *parseArrayOffset = 0x48;
+ return CC_PC_GENERIC_IC_HASH_INDEXED;
+
+ case (CC_PRIVATE_INFO_IC_DEQ_FQID_INDEX_LOOKUP):
+ *parseArrayOffset = 0x16;
+ return CC_PC_GENERIC_IC_HASH_INDEXED;
+
+ default:
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 'extract from' src"));
+ break;
+ }
+ }
+
+ return CC_PC_ILLEGAL;
+}
+
+static uint8_t GetFullFieldParseCode(e_NetHeaderType hdr,
+ e_FmPcdHdrIndex index,
+ t_FmPcdFields field)
+{
+ switch (hdr)
+ {
+ case (HEADER_TYPE_NONE):
+ ASSERT_COND(FALSE);
+ return CC_PC_ILLEGAL;
+
+ case (HEADER_TYPE_ETH):
+ switch (field.eth)
+ {
+ case (NET_HEADER_FIELD_ETH_DA):
+ return CC_PC_FF_MACDST;
+ case (NET_HEADER_FIELD_ETH_SA):
+ return CC_PC_FF_MACSRC;
+ case (NET_HEADER_FIELD_ETH_TYPE):
+ return CC_PC_FF_ETYPE;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+
+ case (HEADER_TYPE_VLAN):
+ switch (field.vlan)
+ {
+ case (NET_HEADER_FIELD_VLAN_TCI):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_TCI1;
+ if (index == e_FM_PCD_HDR_INDEX_LAST)
+ return CC_PC_FF_TCI2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+
+ case (HEADER_TYPE_MPLS):
+ switch (field.mpls)
+ {
+ case (NET_HEADER_FIELD_MPLS_LABEL_STACK):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_MPLS1;
+ if (index == e_FM_PCD_HDR_INDEX_LAST)
+ return CC_PC_FF_MPLS_LAST;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal MPLS index"));
+ return CC_PC_ILLEGAL;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+
+ case (HEADER_TYPE_IPv4):
+ switch (field.ipv4)
+ {
+ case (NET_HEADER_FIELD_IPv4_DST_IP):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_IPV4DST1;
+ if (index == e_FM_PCD_HDR_INDEX_2)
+ return CC_PC_FF_IPV4DST2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
+ return CC_PC_ILLEGAL;
+ case (NET_HEADER_FIELD_IPv4_TOS):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_IPV4IPTOS_TC1;
+ if (index == e_FM_PCD_HDR_INDEX_2)
+ return CC_PC_FF_IPV4IPTOS_TC2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
+ return CC_PC_ILLEGAL;
+ case (NET_HEADER_FIELD_IPv4_PROTO):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_IPV4PTYPE1;
+ if(index == e_FM_PCD_HDR_INDEX_2)
+ return CC_PC_FF_IPV4PTYPE2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
+ return CC_PC_ILLEGAL;
+ case (NET_HEADER_FIELD_IPv4_SRC_IP):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_IPV4SRC1;
+ if (index == e_FM_PCD_HDR_INDEX_2)
+ return CC_PC_FF_IPV4SRC2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
+ return CC_PC_ILLEGAL;
+ case (NET_HEADER_FIELD_IPv4_SRC_IP | NET_HEADER_FIELD_IPv4_DST_IP):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_IPV4SRC1_IPV4DST1;
+ if (index == e_FM_PCD_HDR_INDEX_2)
+ return CC_PC_FF_IPV4SRC2_IPV4DST2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
+ return CC_PC_ILLEGAL;
+ case (NET_HEADER_FIELD_IPv4_TTL):
+ return CC_PC_FF_IPV4TTL;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+
+ case (HEADER_TYPE_IPv6):
+ switch (field.ipv6)
+ {
+ case (NET_HEADER_FIELD_IPv6_VER | NET_HEADER_FIELD_IPv6_FL | NET_HEADER_FIELD_IPv6_TC):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_IPTOS_IPV6TC1_IPV6FLOW1;
+ if (index == e_FM_PCD_HDR_INDEX_2)
+ return CC_PC_FF_IPTOS_IPV6TC2_IPV6FLOW2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
+ return CC_PC_ILLEGAL;
+
+ case (NET_HEADER_FIELD_IPv6_NEXT_HDR):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_IPV6PTYPE1;
+ if (index == e_FM_PCD_HDR_INDEX_2)
+ return CC_PC_FF_IPV6PTYPE2;
+ if (index == e_FM_PCD_HDR_INDEX_LAST)
+ return CC_PC_FF_IPPID;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
+ return CC_PC_ILLEGAL;
+
+ case (NET_HEADER_FIELD_IPv6_DST_IP):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_IPV6DST1;
+ if (index == e_FM_PCD_HDR_INDEX_2)
+ return CC_PC_FF_IPV6DST2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
+ return CC_PC_ILLEGAL;
+
+ case (NET_HEADER_FIELD_IPv6_SRC_IP):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_IPV6SRC1;
+ if (index == e_FM_PCD_HDR_INDEX_2)
+ return CC_PC_FF_IPV6SRC2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
+ return CC_PC_ILLEGAL;
+
+ case (NET_HEADER_FIELD_IPv6_HOP_LIMIT):
+ return CC_PC_FF_IPV6HOP_LIMIT;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+
+ case (HEADER_TYPE_IP):
+ switch (field.ip)
+ {
+ case (NET_HEADER_FIELD_IP_DSCP):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return CC_PC_FF_IPDSCP;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP index"));
+ return CC_PC_ILLEGAL;
+
+ case (NET_HEADER_FIELD_IP_PROTO):
+ if (index == e_FM_PCD_HDR_INDEX_LAST)
+ return CC_PC_FF_IPPID;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP index"));
+ return CC_PC_ILLEGAL;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+
+ case (HEADER_TYPE_GRE):
+ switch (field.gre)
+ {
+ case (NET_HEADER_FIELD_GRE_TYPE):
+ return CC_PC_FF_GREPTYPE;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+
+ case (HEADER_TYPE_MINENCAP):
+ switch (field.minencap)
+ {
+ case (NET_HEADER_FIELD_MINENCAP_TYPE):
+ return CC_PC_FF_MINENCAP_PTYPE;
+
+ case (NET_HEADER_FIELD_MINENCAP_DST_IP):
+ return CC_PC_FF_MINENCAP_IPDST;
+
+ case (NET_HEADER_FIELD_MINENCAP_SRC_IP):
+ return CC_PC_FF_MINENCAP_IPSRC;
+
+ case (NET_HEADER_FIELD_MINENCAP_SRC_IP | NET_HEADER_FIELD_MINENCAP_DST_IP):
+ return CC_PC_FF_MINENCAP_IPSRC_IPDST;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+
+ case (HEADER_TYPE_TCP):
+ switch (field.tcp)
+ {
+ case (NET_HEADER_FIELD_TCP_PORT_SRC):
+ return CC_PC_FF_L4PSRC;
+
+ case (NET_HEADER_FIELD_TCP_PORT_DST):
+ return CC_PC_FF_L4PDST;
+
+ case (NET_HEADER_FIELD_TCP_PORT_DST | NET_HEADER_FIELD_TCP_PORT_SRC):
+ return CC_PC_FF_L4PSRC_L4PDST;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+
+ case (HEADER_TYPE_PPPoE):
+ switch (field.pppoe)
+ {
+ case (NET_HEADER_FIELD_PPPoE_PID):
+ return CC_PC_FF_PPPPID;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+
+ case (HEADER_TYPE_UDP):
+ switch (field.udp)
+ {
+ case (NET_HEADER_FIELD_UDP_PORT_SRC):
+ return CC_PC_FF_L4PSRC;
+
+ case (NET_HEADER_FIELD_UDP_PORT_DST):
+ return CC_PC_FF_L4PDST;
+
+ case (NET_HEADER_FIELD_UDP_PORT_DST | NET_HEADER_FIELD_UDP_PORT_SRC):
+ return CC_PC_FF_L4PSRC_L4PDST;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+}
+
+static uint8_t GetPrParseCode(e_NetHeaderType hdr,
+ e_FmPcdHdrIndex hdrIndex,
+ uint32_t offset,
+ bool glblMask,
+ uint8_t *parseArrayOffset)
+{
+ bool offsetRelevant = FALSE;
+
+ if (offset)
+ offsetRelevant = TRUE;
+
+ switch (hdr)
+ {
+ case (HEADER_TYPE_NONE):
+ ASSERT_COND(FALSE);
+ return CC_PC_ILLEGAL;
+
+ case (HEADER_TYPE_ETH):
+ *parseArrayOffset = (uint8_t)CC_PC_PR_ETH_OFFSET;
+ break;
+
+ case (HEADER_TYPE_USER_DEFINED_SHIM1):
+ if (offset || glblMask)
+ *parseArrayOffset = (uint8_t)CC_PC_PR_USER_DEFINED_SHIM1_OFFSET;
+ else
+ return CC_PC_PR_SHIM1;
+ break;
+
+ case (HEADER_TYPE_USER_DEFINED_SHIM2):
+ if (offset || glblMask)
+ *parseArrayOffset = (uint8_t)CC_PC_PR_USER_DEFINED_SHIM2_OFFSET;
+ else
+ return CC_PC_PR_SHIM2;
+ break;
+
+ case (HEADER_TYPE_LLC_SNAP):
+ *parseArrayOffset = CC_PC_PR_USER_LLC_SNAP_OFFSET;
+ break;
+
+ case (HEADER_TYPE_PPPoE):
+ *parseArrayOffset = CC_PC_PR_PPPOE_OFFSET;
+ break;
+
+ case (HEADER_TYPE_MPLS):
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ *parseArrayOffset = CC_PC_PR_MPLS1_OFFSET;
+ else if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
+ *parseArrayOffset = CC_PC_PR_MPLS_LAST_OFFSET;
+ else
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal MPLS header index"));
+ return CC_PC_ILLEGAL;
+ }
+ break;
+
+ case (HEADER_TYPE_IPv4):
+ case (HEADER_TYPE_IPv6):
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ *parseArrayOffset = CC_PC_PR_IP1_OFFSET;
+ else if (hdrIndex == e_FM_PCD_HDR_INDEX_2)
+ *parseArrayOffset = CC_PC_PR_IP_LAST_OFFSET;
+ else
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP header index"));
+ return CC_PC_ILLEGAL;
+ }
+ break;
+
+ case (HEADER_TYPE_MINENCAP):
+ *parseArrayOffset = CC_PC_PR_MINENC_OFFSET;
+ break;
+
+ case (HEADER_TYPE_GRE):
+ *parseArrayOffset = CC_PC_PR_GRE_OFFSET;
+ break;
+
+ case (HEADER_TYPE_TCP):
+ case (HEADER_TYPE_UDP):
+ case (HEADER_TYPE_IPSEC_AH):
+ case (HEADER_TYPE_IPSEC_ESP):
+ case (HEADER_TYPE_DCCP):
+ case (HEADER_TYPE_SCTP):
+ *parseArrayOffset = CC_PC_PR_L4_OFFSET;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP header for this type of operation"));
+ return CC_PC_ILLEGAL;
+ }
+
+ if (offsetRelevant)
+ return CC_PR_OFFSET;
+ else
+ return CC_PR_WITHOUT_OFFSET;
+}
+
+static uint8_t GetFieldParseCode(e_NetHeaderType hdr,
+ t_FmPcdFields field,
+ uint32_t offset,
+ uint8_t *parseArrayOffset,
+ e_FmPcdHdrIndex hdrIndex)
+{
+ bool offsetRelevant = FALSE;
+
+ if (offset)
+ offsetRelevant = TRUE;
+
+ switch (hdr)
+ {
+ case (HEADER_TYPE_NONE):
+ ASSERT_COND(FALSE);
+ case (HEADER_TYPE_ETH):
+ switch (field.eth)
+ {
+ case (NET_HEADER_FIELD_ETH_TYPE):
+ *parseArrayOffset = CC_PC_PR_ETYPE_LAST_OFFSET;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+ break;
+
+ case (HEADER_TYPE_VLAN):
+ switch (field.vlan)
+ {
+ case (NET_HEADER_FIELD_VLAN_TCI):
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ *parseArrayOffset = CC_PC_PR_VLAN1_OFFSET;
+ else if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
+ *parseArrayOffset = CC_PC_PR_VLAN2_OFFSET;
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return CC_PC_ILLEGAL;
+ }
+ break;
+
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal header "));
+ return CC_PC_ILLEGAL;
+ }
+
+ if (offsetRelevant)
+ return CC_PR_OFFSET;
+ else
+ return CC_PR_WITHOUT_OFFSET;
+}
+
+static void FillAdOfTypeResult(t_Handle h_Ad,
+ t_FmPcdCcStatsParams *p_FmPcdCcStatsParams,
+ t_FmPcd *p_FmPcd,
+ t_FmPcdCcNextEngineParams *p_CcNextEngineParams)
+{
+ t_AdOfTypeResult *p_AdResult = (t_AdOfTypeResult *)h_Ad;
+ t_Handle h_TmpAd;
+ uint32_t tmp = 0, tmpNia = 0;
+ uint16_t profileId;
+ t_Handle p_AdNewPtr = NULL;
+
+ /* There are 3 cases handled in this routine of building a "result" type AD.
+ * Case 1: No Manip. The action descriptor is built within the match table.
+ * Case 2: Manip exists. A new AD is created - p_AdNewPtr. It is initialized
+ * either in the FmPcdManipUpdateAdResultForCc routine or it was already
+ * initialized and returned here.
+ * p_AdResult (within the match table) will be initialized after
+ * this routine returns and point to the existing AD.
+ * Case 3: Manip exists. The action descriptor is built within the match table.
+ * FmPcdManipUpdateAdResultForCc returns a NULL p_AdNewPtr.
+ *
+ * If statistics were enabled and the statistics mode of this node requires
+ * a statistics Ad, it will be placed after the result Ad and before the
+ * manip Ad, if manip Ad exists here.
+ */
+
+ /* As default, the "new" ptr is the current one. i.e. the content of the result
+ * AD will be written into the match table itself (case (1))*/
+ p_AdNewPtr = p_AdResult;
+
+ /* Initialize an action descriptor, if current statistics mode requires an Ad */
+ if (p_FmPcdCcStatsParams)
+ {
+ ASSERT_COND(p_FmPcdCcStatsParams->h_StatsAd);
+ ASSERT_COND(p_FmPcdCcStatsParams->h_StatsCounters);
+
+ /* Swapping addresses between statistics Ad and the current lookup AD addresses */
+ h_TmpAd = p_FmPcdCcStatsParams->h_StatsAd;
+ p_FmPcdCcStatsParams->h_StatsAd = h_Ad;
+ h_Ad = h_TmpAd;
+
+ p_AdNewPtr = h_Ad;
+ p_AdResult = h_Ad;
+
+ /* Init statistics Ad and connect current lookup AD as 'next action' from statistics Ad */
+ UpdateStatsAd(p_FmPcdCcStatsParams,
+ h_Ad,
+ p_FmPcd->physicalMuramBase);
+ }
+
+ /* Create manip and return p_AdNewPtr to either a new descriptor or NULL */
+ if (p_CcNextEngineParams->h_Manip)
+ FmPcdManipUpdateAdResultForCc(p_CcNextEngineParams->h_Manip,
+ p_CcNextEngineParams,
+ h_Ad,
+ &p_AdNewPtr);
+
+ /* if (p_AdNewPtr = NULL) --> Done. (case (3)) */
+ if (p_AdNewPtr)
+ {
+ /* case (1) and (2) */
+ switch (p_CcNextEngineParams->nextEngine)
+ {
+ case (e_FM_PCD_DONE):
+ if (p_CcNextEngineParams->params.enqueueParams.action == e_FM_PCD_ENQ_FRAME)
+ {
+ if (p_CcNextEngineParams->params.enqueueParams.overrideFqid)
+ {
+ tmp = FM_PCD_AD_RESULT_CONTRL_FLOW_TYPE;
+ tmp |= p_CcNextEngineParams->params.enqueueParams.newFqid;
+#if (DPAA_VERSION >= 11)
+ tmp |= (p_CcNextEngineParams->params.enqueueParams.newRelativeStorageProfileId & FM_PCD_AD_RESULT_VSP_MASK) << FM_PCD_AD_RESULT_VSP_SHIFT;
+#endif /* (DPAA_VERSION >= 11) */
+ }
+ else
+ {
+ tmp = FM_PCD_AD_RESULT_DATA_FLOW_TYPE;
+ tmp |= FM_PCD_AD_RESULT_PLCR_DIS;
+ }
+ }
+
+ if (p_CcNextEngineParams->params.enqueueParams.action == e_FM_PCD_DROP_FRAME)
+ tmpNia |= GET_NIA_BMI_AC_DISCARD_FRAME(p_FmPcd);
+ else
+ tmpNia |= GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd);
+ break;
+
+ case (e_FM_PCD_KG):
+ if (p_CcNextEngineParams->params.kgParams.overrideFqid)
+ {
+ tmp = FM_PCD_AD_RESULT_CONTRL_FLOW_TYPE;
+ tmp |= p_CcNextEngineParams->params.kgParams.newFqid;
+#if (DPAA_VERSION >= 11)
+ tmp |= (p_CcNextEngineParams->params.kgParams.newRelativeStorageProfileId & FM_PCD_AD_RESULT_VSP_MASK) << FM_PCD_AD_RESULT_VSP_SHIFT;
+#endif /* (DPAA_VERSION >= 11) */
+ }
+ else
+ {
+ tmp = FM_PCD_AD_RESULT_DATA_FLOW_TYPE;
+ tmp |= FM_PCD_AD_RESULT_PLCR_DIS;
+ }
+ tmpNia = NIA_KG_DIRECT;
+ tmpNia |= NIA_ENG_KG;
+ tmpNia |= NIA_KG_CC_EN;
+ tmpNia |= FmPcdKgGetSchemeId(p_CcNextEngineParams->params.kgParams.h_DirectScheme);
+ break;
+
+ case (e_FM_PCD_PLCR):
+ tmp = 0;
+ if (p_CcNextEngineParams->params.plcrParams.overrideParams)
+ {
+ tmp = FM_PCD_AD_RESULT_CONTRL_FLOW_TYPE;
+
+ /* if private policer profile, it may be uninitialized yet, therefore no checks are done at this stage */
+ if (p_CcNextEngineParams->params.plcrParams.sharedProfile)
+ {
+ tmpNia |= NIA_PLCR_ABSOLUTE;
+ FmPcdPlcrGetAbsoluteIdByProfileParams((t_Handle)p_FmPcd,
+ e_FM_PCD_PLCR_SHARED,
+ NULL,
+ p_CcNextEngineParams->params.plcrParams.newRelativeProfileId,
+ &profileId);
+ }
+ else
+ profileId = p_CcNextEngineParams->params.plcrParams.newRelativeProfileId;
+
+ tmp |= p_CcNextEngineParams->params.plcrParams.newFqid;
+#if (DPAA_VERSION >= 11)
+ tmp |= (p_CcNextEngineParams->params.plcrParams.newRelativeStorageProfileId & FM_PCD_AD_RESULT_VSP_MASK)<< FM_PCD_AD_RESULT_VSP_SHIFT;
+#endif /* (DPAA_VERSION >= 11) */
+ WRITE_UINT32(p_AdResult->plcrProfile,(uint32_t)((uint32_t)profileId << FM_PCD_AD_PROFILEID_FOR_CNTRL_SHIFT));
+ }
+ else
+ tmp = FM_PCD_AD_RESULT_DATA_FLOW_TYPE;
+
+ tmpNia |= NIA_ENG_PLCR | p_CcNextEngineParams->params.plcrParams.newRelativeProfileId;
+ break;
+
+ default:
+ return;
+ }
+ WRITE_UINT32(p_AdResult->fqid, tmp);
+
+ if (p_CcNextEngineParams->h_Manip)
+ {
+ tmp = GET_UINT32(p_AdResult->plcrProfile);
+ tmp |= (uint32_t)(XX_VirtToPhys(p_AdNewPtr) - (p_FmPcd->physicalMuramBase)) >> 4;
+ WRITE_UINT32(p_AdResult->plcrProfile, tmp);
+
+ tmpNia |= FM_PCD_AD_RESULT_EXTENDED_MODE;
+ tmpNia |= FM_PCD_AD_RESULT_NADEN;
+ }
+
+#if (DPAA_VERSION >= 11)
+ tmpNia |= FM_PCD_AD_RESULT_NO_OM_VSPE;
+#endif /* (DPAA_VERSION >= 11) */
+ WRITE_UINT32(p_AdResult->nia, tmpNia);
+ }
+}
+
+static t_Error CcUpdateParams(t_Handle h_FmPcd,
+ t_Handle h_PcdParams,
+ t_Handle h_FmPort,
+ t_Handle h_FmTree,
+ bool validate)
+{
+ t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *) h_FmTree;
+
+ return CcUpdateParam(h_FmPcd,
+ h_PcdParams,
+ h_FmPort,
+ p_CcTree->keyAndNextEngineParams,
+ p_CcTree->numOfEntries,
+ UINT_TO_PTR(p_CcTree->ccTreeBaseAddr),
+ validate,
+ 0,
+ h_FmTree,
+ FALSE);
+}
+
+
+static void ReleaseNewNodeCommonPart(t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo)
+{
+ if (p_AdditionalInfo->p_AdTableNew)
+ FM_MURAM_FreeMem(FmPcdGetMuramHandle(((t_FmPcdCcNode *)(p_AdditionalInfo->h_CurrentNode))->h_FmPcd),
+ p_AdditionalInfo->p_AdTableNew);
+
+ if (p_AdditionalInfo->p_KeysMatchTableNew)
+ FM_MURAM_FreeMem(FmPcdGetMuramHandle(((t_FmPcdCcNode *)(p_AdditionalInfo->h_CurrentNode))->h_FmPcd),
+ p_AdditionalInfo->p_KeysMatchTableNew);
+}
+
+static t_Error UpdateGblMask(t_FmPcdCcNode *p_CcNode,
+ uint8_t keySize,
+ uint8_t *p_Mask)
+{
+ uint8_t prvGlblMaskSize = p_CcNode->glblMaskSize;
+
+ if (p_Mask &&
+ !p_CcNode->glblMaskUpdated &&
+ (keySize <= 4) &&
+ !p_CcNode->lclMask)
+ {
+ if (p_CcNode->parseCode &&
+ (p_CcNode->parseCode != CC_PC_FF_TCI1) &&
+ (p_CcNode->parseCode != CC_PC_FF_TCI2) &&
+ (p_CcNode->parseCode != CC_PC_FF_MPLS1) &&
+ (p_CcNode->parseCode != CC_PC_FF_MPLS_LAST) &&
+ (p_CcNode->parseCode != CC_PC_FF_IPV4IPTOS_TC1) &&
+ (p_CcNode->parseCode != CC_PC_FF_IPV4IPTOS_TC2) &&
+ (p_CcNode->parseCode != CC_PC_FF_IPTOS_IPV6TC1_IPV6FLOW1) &&
+ (p_CcNode->parseCode != CC_PC_FF_IPDSCP) &&
+ (p_CcNode->parseCode != CC_PC_FF_IPTOS_IPV6TC2_IPV6FLOW2) )
+ {
+ p_CcNode->glblMaskSize = 0;
+ p_CcNode->lclMask = TRUE;
+ }
+ else
+ {
+ memcpy(p_CcNode->p_GlblMask, p_Mask, (sizeof(uint8_t))*keySize);
+ p_CcNode->glblMaskUpdated = TRUE;
+ p_CcNode->glblMaskSize = 4;
+ }
+ }
+ else if (p_Mask &&
+ (keySize <= 4) &&
+ !p_CcNode->lclMask)
+ {
+ if (memcmp(p_CcNode->p_GlblMask, p_Mask, keySize) != 0)
+ {
+ p_CcNode->lclMask = TRUE;
+ p_CcNode->glblMaskSize = 0;
+ }
+ }
+ else if (!p_Mask && p_CcNode->glblMaskUpdated && (keySize <= 4))
+ {
+ uint32_t tmpMask = 0xffffffff;
+ if (memcmp(p_CcNode->p_GlblMask, &tmpMask, 4) != 0)
+ {
+ p_CcNode->lclMask = TRUE;
+ p_CcNode->glblMaskSize = 0;
+ }
+ }
+ else if (p_Mask)
+ {
+ p_CcNode->lclMask = TRUE;
+ p_CcNode->glblMaskSize = 0;
+ }
+
+ /* In static mode (maxNumOfKeys > 0), local mask is supported
+ only is mask support was enabled at initialization */
+ if (p_CcNode->maxNumOfKeys && (!p_CcNode->maskSupport) && p_CcNode->lclMask)
+ {
+ p_CcNode->lclMask = FALSE;
+ p_CcNode->glblMaskSize = prvGlblMaskSize;
+ return ERROR_CODE(E_NOT_SUPPORTED);
+ }
+
+ return E_OK;
+}
+
+static __inline__ t_Handle GetNewAd(t_Handle h_FmPcdCcNodeOrTree, bool isTree)
+{
+ t_FmPcd *p_FmPcd;
+ t_Handle h_Ad;
+
+ if (isTree)
+ p_FmPcd = (t_FmPcd *)(((t_FmPcdCcTree *)h_FmPcdCcNodeOrTree)->h_FmPcd);
+ else
+ p_FmPcd = (t_FmPcd *)(((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->h_FmPcd);
+
+ if ((isTree && p_FmPcd->p_CcShadow) ||
+ (!isTree && ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->maxNumOfKeys))
+ {
+ /* The allocated shadow is divided as follows:
+ 0 . . . 16 . . .
+ ---------------------------------------------------
+ | Shadow | Shadow Keys | Shadow Next |
+ | Ad | Match Table | Engine Table |
+ | (16 bytes) | (maximal size) | (maximal size) |
+ ---------------------------------------------------
+ */
+ if (!p_FmPcd->p_CcShadow)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("CC Shadow not allocated"));
+ return NULL;
+ }
+
+ h_Ad = p_FmPcd->p_CcShadow;
+ }
+ else
+ {
+ h_Ad = (t_Handle)FM_MURAM_AllocMem(FmPcdGetMuramHandle(p_FmPcd),
+ FM_PCD_CC_AD_ENTRY_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!h_Ad)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node action descriptor"));
+ return NULL;
+ }
+ }
+
+ return h_Ad;
+}
+
+static t_Error BuildNewNodeCommonPart(t_FmPcdCcNode *p_CcNode,
+ int *size,
+ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+
+ if (p_CcNode->lclMask)
+ *size = 2 * p_CcNode->ccKeySizeAccExtraction;
+ else
+ *size = p_CcNode->ccKeySizeAccExtraction;
+
+ if (p_CcNode->maxNumOfKeys == 0)
+ {
+ p_AdditionalInfo->p_AdTableNew =
+ (t_Handle)FM_MURAM_AllocMem(FmPcdGetMuramHandle(p_FmPcd),
+ (uint32_t)( (p_AdditionalInfo->numOfKeys+1) * FM_PCD_CC_AD_ENTRY_SIZE),
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!p_AdditionalInfo->p_AdTableNew)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node action descriptors table"));
+
+ p_AdditionalInfo->p_KeysMatchTableNew =
+ (t_Handle)FM_MURAM_AllocMem(FmPcdGetMuramHandle(p_FmPcd),
+ (uint32_t)(*size * sizeof(uint8_t) * (p_AdditionalInfo->numOfKeys + 1)),
+ FM_PCD_CC_KEYS_MATCH_TABLE_ALIGN);
+ if (!p_AdditionalInfo->p_KeysMatchTableNew)
+ {
+ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_CcNode->h_FmPcd), p_AdditionalInfo->p_AdTableNew);
+ p_AdditionalInfo->p_AdTableNew = NULL;
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node key match table"));
+ }
+
+ IOMemSet32((uint8_t*)p_AdditionalInfo->p_AdTableNew, 0, (uint32_t)((p_AdditionalInfo->numOfKeys+1) * FM_PCD_CC_AD_ENTRY_SIZE));
+ IOMemSet32((uint8_t*)p_AdditionalInfo->p_KeysMatchTableNew, 0, *size * sizeof(uint8_t) * (p_AdditionalInfo->numOfKeys + 1));
+ }
+ else
+ {
+ /* The allocated shadow is divided as follows:
+ 0 . . . 16 . . .
+ ---------------------------------------------------
+ | Shadow | Shadow Keys | Shadow Next |
+ | Ad | Match Table | Engine Table |
+ | (16 bytes) | (maximal size) | (maximal size) |
+ ---------------------------------------------------
+ */
+
+ if (!p_FmPcd->p_CcShadow)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("CC Shadow not allocated"));
+
+ p_AdditionalInfo->p_KeysMatchTableNew = PTR_MOVE(p_FmPcd->p_CcShadow, FM_PCD_CC_AD_ENTRY_SIZE);
+ p_AdditionalInfo->p_AdTableNew = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, p_CcNode->keysMatchTableMaxSize);
+
+ IOMemSet32((uint8_t*)p_AdditionalInfo->p_AdTableNew, 0, (uint32_t)((p_CcNode->maxNumOfKeys + 1) * FM_PCD_CC_AD_ENTRY_SIZE));
+ IOMemSet32((uint8_t*)p_AdditionalInfo->p_KeysMatchTableNew, 0, (*size) * sizeof(uint8_t) * (p_CcNode->maxNumOfKeys));
+ }
+
+ p_AdditionalInfo->p_AdTableOld = p_CcNode->h_AdTable;
+ p_AdditionalInfo->p_KeysMatchTableOld = p_CcNode->h_KeysMatchTable;
+
+ return E_OK;
+}
+
+static t_Error BuildNewNodeAddOrMdfyKeyAndNextEngine(t_Handle h_FmPcd,
+ t_FmPcdCcNode *p_CcNode,
+ uint16_t keyIndex,
+ t_FmPcdCcKeyParams *p_KeyParams,
+ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo,
+ bool add)
+{
+ t_Error err = E_OK;
+ t_Handle p_AdTableNewTmp, p_KeysMatchTableNewTmp;
+ t_Handle p_KeysMatchTableOldTmp, p_AdTableOldTmp;
+ int size;
+ int i = 0, j = 0;
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t requiredAction = 0;
+ bool prvLclMask;
+ t_CcNodeInformation *p_CcNodeInformation;
+ t_FmPcdCcStatsParams statsParams = {0};
+ t_List *p_Pos;
+ t_FmPcdStatsObj *p_StatsObj;
+
+ /* Check that new NIA is legal */
+ err = ValidateNextEngineParams(h_FmPcd,
+ &p_KeyParams->ccNextEngineParams,
+ p_CcNode->statisticsMode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ prvLclMask = p_CcNode->lclMask;
+
+ /* Check that new key is not require update of localMask */
+ err = UpdateGblMask(p_CcNode,
+ p_CcNode->ccKeySizeAccExtraction,
+ p_KeyParams->p_Mask);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+
+ /* Update internal data structure with new next engine for the given index */
+ memcpy(&p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams,
+ &p_KeyParams->ccNextEngineParams,
+ sizeof(t_FmPcdCcNextEngineParams));
+
+ memcpy(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].key,
+ p_KeyParams->p_Key,
+ p_CcNode->userSizeOfExtraction);
+
+ if ((p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ && p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip)
+ {
+ err = AllocAndFillAdForContLookupManip(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+
+ if (p_KeyParams->p_Mask)
+ memcpy(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].mask,
+ p_KeyParams->p_Mask,
+ p_CcNode->userSizeOfExtraction);
+ else
+ memset(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].mask,
+ 0xFF,
+ p_CcNode->userSizeOfExtraction);
+
+ /* Update numOfKeys */
+ if (add)
+ p_AdditionalInfo->numOfKeys = (uint8_t)(p_CcNode->numOfKeys + 1);
+ else
+ p_AdditionalInfo->numOfKeys = (uint8_t)p_CcNode->numOfKeys;
+
+ /* Allocate new tables in MURAM: keys match table and action descriptors table */
+ err = BuildNewNodeCommonPart(p_CcNode, &size, p_AdditionalInfo);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ /* Check that manip is legal and what requiredAction is necessary for this manip */
+ if (p_KeyParams->ccNextEngineParams.h_Manip)
+ {
+ err = FmPcdManipCheckParamsForCcNextEngine(&p_KeyParams->ccNextEngineParams,&requiredAction);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+
+ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction = requiredAction;
+ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction |= UPDATE_CC_WITH_TREE;
+
+ /* Update new Ad and new Key Table according to new requirement */
+ i = 0;
+ for (j = 0; j < p_AdditionalInfo->numOfKeys; j++)
+ {
+ p_AdTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableNew, j*FM_PCD_CC_AD_ENTRY_SIZE);
+
+ if (j == keyIndex)
+ {
+ if (p_KeyParams->ccNextEngineParams.statisticsEn)
+ {
+ /* Allocate a statistics object that holds statistics AD and counters.
+ - For added key - New statistics AD and counters pointer need to be allocated
+ new statistics object. If statistics were enabled, we need to replace the
+ existing descriptor with a new descriptor with nullified counters.
+ */
+ p_StatsObj = GetStatsObj(p_CcNode);
+ ASSERT_COND(p_StatsObj);
+
+ /* Store allocated statistics object */
+ ASSERT_COND(keyIndex < CC_MAX_NUM_OF_KEYS);
+ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].p_StatsObj = p_StatsObj;
+
+ statsParams.h_StatsAd = p_StatsObj->h_StatsAd;
+ statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters;
+#if (DPAA_VERSION >= 11)
+ statsParams.h_StatsFLRs = p_CcNode->h_StatsFLRs;
+
+#endif /* (DPAA_VERSION >= 11) */
+
+ /* Building action descriptor for the received new key */
+ NextStepAd(p_AdTableNewTmp,
+ &statsParams,
+ &p_KeyParams->ccNextEngineParams,
+ p_FmPcd);
+ }
+ else
+ {
+ /* Building action descriptor for the received new key */
+ NextStepAd(p_AdTableNewTmp,
+ NULL,
+ &p_KeyParams->ccNextEngineParams,
+ p_FmPcd);
+ }
+
+ /* Copy the received new key into keys match table */
+ p_KeysMatchTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, j*size*sizeof(uint8_t));
+
+ Mem2IOCpy32((void*)p_KeysMatchTableNewTmp, p_KeyParams->p_Key, p_CcNode->userSizeOfExtraction);
+
+ /* Update mask for the received new key */
+ if (p_CcNode->lclMask)
+ {
+ if (p_KeyParams->p_Mask)
+ {
+ Mem2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp,
+ p_CcNode->ccKeySizeAccExtraction),
+ p_KeyParams->p_Mask,
+ p_CcNode->userSizeOfExtraction);
+ }
+ else if (p_CcNode->ccKeySizeAccExtraction > 4)
+ {
+ IOMemSet32(PTR_MOVE(p_KeysMatchTableNewTmp,
+ p_CcNode->ccKeySizeAccExtraction),
+ 0xff,
+ p_CcNode->userSizeOfExtraction);
+ }
+ else
+ {
+ Mem2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp,
+ p_CcNode->ccKeySizeAccExtraction),
+ p_CcNode->p_GlblMask,
+ p_CcNode->userSizeOfExtraction);
+ }
+ }
+
+ /* If key modification requested, the old entry is omitted and replaced by the new parameters */
+ if (!add)
+ i++;
+ }
+ else
+ {
+ /* Copy existing action descriptors to the newly allocated Ad table */
+ p_AdTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableOld, i*FM_PCD_CC_AD_ENTRY_SIZE);
+ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ /* Copy existing keys and their masks to the newly allocated keys match table */
+ p_KeysMatchTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, j * size * sizeof(uint8_t));
+ p_KeysMatchTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableOld, i * size * sizeof(uint8_t));
+
+ if (p_CcNode->lclMask)
+ {
+ if (prvLclMask)
+ {
+ IO2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, p_CcNode->ccKeySizeAccExtraction),
+ PTR_MOVE(p_KeysMatchTableOldTmp, p_CcNode->ccKeySizeAccExtraction),
+ p_CcNode->ccKeySizeAccExtraction);
+ }
+ else
+ {
+ p_KeysMatchTableOldTmp = PTR_MOVE(p_CcNode->h_KeysMatchTable,
+ i * p_CcNode->ccKeySizeAccExtraction*sizeof(uint8_t));
+
+ if (p_CcNode->ccKeySizeAccExtraction > 4)
+ {
+ IOMemSet32(PTR_MOVE(p_KeysMatchTableNewTmp,
+ p_CcNode->ccKeySizeAccExtraction),
+ 0xff,
+ p_CcNode->userSizeOfExtraction);
+ }
+ else
+ {
+ IO2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp,
+ p_CcNode->ccKeySizeAccExtraction),
+ p_CcNode->p_GlblMask,
+ p_CcNode->userSizeOfExtraction);
+ }
+ }
+ }
+
+ IO2IOCpy32(p_KeysMatchTableNewTmp, p_KeysMatchTableOldTmp, p_CcNode->ccKeySizeAccExtraction);
+
+ i++;
+ }
+ }
+
+ /* Miss action descriptor */
+ p_AdTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableNew, j * FM_PCD_CC_AD_ENTRY_SIZE);
+ p_AdTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableOld, i * FM_PCD_CC_AD_ENTRY_SIZE);
+ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ if (!LIST_IsEmpty(&p_CcNode->ccTreesLst))
+ {
+ LIST_FOR_EACH(p_Pos, &p_CcNode->ccTreesLst)
+ {
+ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos);
+ ASSERT_COND(p_CcNodeInformation->h_CcNode);
+ /* Update the manipulation which has to be updated from parameters of the port */
+ /* It's has to be updated with restrictions defined in the function */
+ err = SetRequiredAction(p_CcNode->h_FmPcd,
+ p_CcNode->shadowAction | p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction,
+ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex],
+ PTR_MOVE(p_AdditionalInfo->p_AdTableNew, keyIndex*FM_PCD_CC_AD_ENTRY_SIZE),
+ 1,
+ p_CcNodeInformation->h_CcNode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+
+ err = CcUpdateParam(p_CcNode->h_FmPcd,
+ NULL,
+ NULL,
+ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex],
+ 1,
+ PTR_MOVE(p_AdditionalInfo->p_AdTableNew, keyIndex*FM_PCD_CC_AD_ENTRY_SIZE),
+ TRUE,
+ p_CcNodeInformation->index,
+ p_CcNodeInformation->h_CcNode,
+ TRUE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+ }
+
+ if (p_CcNode->lclMask)
+ memset(p_CcNode->p_GlblMask, 0xff, CC_GLBL_MASK_SIZE * sizeof(uint8_t));
+
+ if (p_KeyParams->ccNextEngineParams.nextEngine == e_FM_PCD_CC)
+ p_AdditionalInfo->h_NodeForAdd = p_KeyParams->ccNextEngineParams.params.ccParams.h_CcNode;
+ if (p_KeyParams->ccNextEngineParams.h_Manip)
+ p_AdditionalInfo->h_ManipForAdd = p_KeyParams->ccNextEngineParams.h_Manip;
+
+#if (DPAA_VERSION >= 11)
+ if ((p_KeyParams->ccNextEngineParams.nextEngine == e_FM_PCD_FR) &&
+ (p_KeyParams->ccNextEngineParams.params.frParams.h_FrmReplic))
+ p_AdditionalInfo->h_FrmReplicForAdd = p_KeyParams->ccNextEngineParams.params.frParams.h_FrmReplic;
+#endif /* (DPAA_VERSION >= 11) */
+
+ if (!add)
+ {
+ if (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ p_AdditionalInfo->h_NodeForRmv = p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode;
+
+ if (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip)
+ p_AdditionalInfo->h_ManipForRmv = p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip;
+
+ /* If statistics were previously enabled, store the old statistics object to be released */
+ if (p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj)
+ {
+ p_AdditionalInfo->p_StatsObjForRmv = p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj;
+ }
+
+#if (DPAA_VERSION >= 11)
+ if ((p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_FR) &&
+ (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic))
+ p_AdditionalInfo->h_FrmReplicForRmv = p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic;
+#endif /* (DPAA_VERSION >= 11) */
+ }
+
+ return E_OK;
+}
+
+static t_Error BuildNewNodeRemoveKey(t_FmPcdCcNode *p_CcNode,
+ uint16_t keyIndex,
+ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo)
+{
+ int i = 0, j = 0;
+ t_Handle p_AdTableNewTmp,p_KeysMatchTableNewTmp;
+ t_Handle p_KeysMatchTableOldTmp, p_AdTableOldTmp;
+ int size;
+ t_Error err = E_OK;
+
+ /*save new numOfKeys*/
+ p_AdditionalInfo->numOfKeys = (uint16_t)(p_CcNode->numOfKeys - 1);
+
+ /*function which allocates in the memory new KeyTbl, AdTbl*/
+ err = BuildNewNodeCommonPart(p_CcNode, &size, p_AdditionalInfo);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ /*update new Ad and new Key Table according to new requirement*/
+ for (i=0, j=0; j<p_CcNode->numOfKeys; i++, j++)
+ {
+ if (j == keyIndex)
+ {
+ p_AdTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableOld, j * FM_PCD_CC_AD_ENTRY_SIZE);
+ j++;
+ }
+ if (j == p_CcNode->numOfKeys)
+ break;
+ p_AdTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableNew, i * FM_PCD_CC_AD_ENTRY_SIZE);
+ p_AdTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableOld, j * FM_PCD_CC_AD_ENTRY_SIZE);
+ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ p_KeysMatchTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableOld, j * size * sizeof(uint8_t));
+ p_KeysMatchTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, i * size * sizeof(uint8_t));
+ IO2IOCpy32(p_KeysMatchTableNewTmp, p_KeysMatchTableOldTmp, size * sizeof(uint8_t));
+ }
+
+ p_AdTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableNew, i * FM_PCD_CC_AD_ENTRY_SIZE);
+ p_AdTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableOld, j * FM_PCD_CC_AD_ENTRY_SIZE);
+ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ if (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ p_AdditionalInfo->h_NodeForRmv =
+ p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode;
+
+ if (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip)
+ p_AdditionalInfo->h_ManipForRmv =
+ p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip;
+
+ /* If statistics were previously enabled, store the old statistics object to be released */
+ if (p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj)
+ {
+ p_AdditionalInfo->p_StatsObjForRmv = p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj;
+ }
+
+#if (DPAA_VERSION >= 11)
+ if ((p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_FR) &&
+ (p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic))
+ p_AdditionalInfo->h_FrmReplicForRmv =
+ p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic;
+#endif /* (DPAA_VERSION >= 11) */
+
+ return E_OK;
+}
+
+static t_Error BuildNewNodeModifyKey(t_FmPcdCcNode *p_CcNode,
+ uint16_t keyIndex,
+ uint8_t *p_Key,
+ uint8_t *p_Mask,
+ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ t_Error err = E_OK;
+ t_Handle p_AdTableNewTmp, p_KeysMatchTableNewTmp;
+ t_Handle p_KeysMatchTableOldTmp, p_AdTableOldTmp;
+ int size;
+ int i = 0, j = 0;
+ bool prvLclMask;
+ t_FmPcdStatsObj *p_StatsObj, tmpStatsObj;
+ p_AdditionalInfo->numOfKeys = p_CcNode->numOfKeys;
+
+ prvLclMask = p_CcNode->lclMask;
+
+ /* Check that new key is not require update of localMask */
+ err = UpdateGblMask(p_CcNode,
+ p_CcNode->ccKeySizeAccExtraction,
+ p_Mask);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+
+ /* Update internal data structure with new next engine for the given index */
+ memcpy(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].key,
+ p_Key,
+ p_CcNode->userSizeOfExtraction);
+
+ if (p_Mask)
+ memcpy(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].mask,
+ p_Mask,
+ p_CcNode->userSizeOfExtraction);
+ else
+ memset(p_AdditionalInfo->keyAndNextEngineParams[keyIndex].mask,
+ 0xFF,
+ p_CcNode->userSizeOfExtraction);
+
+ /*function which build in the memory new KeyTbl, AdTbl*/
+ err = BuildNewNodeCommonPart(p_CcNode, &size, p_AdditionalInfo);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ /*fill the New AdTable and New KeyTable*/
+ for (j=0, i=0; j<p_AdditionalInfo->numOfKeys; j++, i++)
+ {
+ p_AdTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableNew, j*FM_PCD_CC_AD_ENTRY_SIZE);
+ p_AdTableOldTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableOld, i*FM_PCD_CC_AD_ENTRY_SIZE);
+
+ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ if (j == keyIndex)
+ {
+ ASSERT_COND(keyIndex < CC_MAX_NUM_OF_KEYS);
+ if (p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj)
+ {
+ /* As statistics were enabled, we need to update the existing
+ statistics descriptor with a new nullified counters. */
+ p_StatsObj = GetStatsObj(p_CcNode);
+ ASSERT_COND(p_StatsObj);
+
+ SetStatsCounters(p_AdTableNewTmp,
+ (uint32_t)((XX_VirtToPhys(p_StatsObj->h_StatsCounters) - p_FmPcd->physicalMuramBase)));
+
+ tmpStatsObj.h_StatsAd = p_StatsObj->h_StatsAd;
+ tmpStatsObj.h_StatsCounters = p_StatsObj->h_StatsCounters;
+
+ /* As we need to replace only the counters, we build a new statistics
+ object that holds the old AD and the new counters - this will be the
+ currently used statistics object.
+ The newly allocated AD is not required and may be released back to
+ the available objects with the previous counters pointer. */
+ p_StatsObj->h_StatsAd = p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsAd;
+
+ p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsAd = tmpStatsObj.h_StatsAd;
+
+ /* Store allocated statistics object */
+ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].p_StatsObj = p_StatsObj;
+
+ /* As statistics were previously enabled, store the old statistics object to be released */
+ p_AdditionalInfo->p_StatsObjForRmv = p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj;
+ }
+
+ p_KeysMatchTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, j * size * sizeof(uint8_t));
+
+ Mem2IOCpy32(p_KeysMatchTableNewTmp, p_Key, p_CcNode->userSizeOfExtraction);
+
+ if (p_CcNode->lclMask)
+ {
+ if (p_Mask)
+ Mem2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp,
+ p_CcNode->ccKeySizeAccExtraction),
+ p_Mask,
+ p_CcNode->userSizeOfExtraction);
+ else if (p_CcNode->ccKeySizeAccExtraction > 4)
+ IOMemSet32(PTR_MOVE(p_KeysMatchTableNewTmp,
+ p_CcNode->ccKeySizeAccExtraction),
+ 0xff,
+ p_CcNode->userSizeOfExtraction);
+ else
+ Mem2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp,
+ p_CcNode->ccKeySizeAccExtraction),
+ p_CcNode->p_GlblMask,
+ p_CcNode->userSizeOfExtraction);
+ }
+ }
+ else
+ {
+ p_KeysMatchTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_KeysMatchTableNew, j * size * sizeof(uint8_t));
+ p_KeysMatchTableOldTmp = PTR_MOVE(p_CcNode->h_KeysMatchTable, i * size * sizeof(uint8_t));
+
+ if (p_CcNode->lclMask)
+ {
+ if (prvLclMask)
+ IO2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, p_CcNode->ccKeySizeAccExtraction),
+ PTR_MOVE(p_KeysMatchTableOldTmp, p_CcNode->ccKeySizeAccExtraction),
+ p_CcNode->userSizeOfExtraction);
+ else
+ {
+ p_KeysMatchTableOldTmp = PTR_MOVE(p_CcNode->h_KeysMatchTable, i * p_CcNode->ccKeySizeAccExtraction * sizeof(uint8_t));
+
+ if (p_CcNode->ccKeySizeAccExtraction > 4)
+ IOMemSet32(PTR_MOVE(p_KeysMatchTableNewTmp,
+ p_CcNode->ccKeySizeAccExtraction),
+ 0xff,
+ p_CcNode->userSizeOfExtraction);
+ else
+ IO2IOCpy32(PTR_MOVE(p_KeysMatchTableNewTmp, p_CcNode->ccKeySizeAccExtraction),
+ p_CcNode->p_GlblMask,
+ p_CcNode->userSizeOfExtraction);
+ }
+ }
+ IO2IOCpy32((void*)p_KeysMatchTableNewTmp,
+ p_KeysMatchTableOldTmp,
+ p_CcNode->ccKeySizeAccExtraction);
+ }
+ }
+
+ p_AdTableNewTmp = PTR_MOVE(p_AdditionalInfo->p_AdTableNew, j * FM_PCD_CC_AD_ENTRY_SIZE);
+ p_AdTableOldTmp = PTR_MOVE(p_CcNode->h_AdTable, i * FM_PCD_CC_AD_ENTRY_SIZE);
+
+ IO2IOCpy32(p_AdTableNewTmp, p_AdTableOldTmp, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ return E_OK;
+}
+
+static t_Error BuildNewNodeModifyNextEngine(t_Handle h_FmPcd,
+ t_Handle h_FmPcdCcNodeOrTree,
+ uint16_t keyIndex,
+ t_FmPcdCcNextEngineParams *p_CcNextEngineParams,
+ t_List *h_OldLst,
+ t_List *h_NewLst,
+ t_FmPcdModifyCcKeyAdditionalParams *p_AdditionalInfo)
+{
+ t_Error err = E_OK;
+ uint32_t requiredAction = 0;
+ t_List *p_Pos;
+ t_CcNodeInformation *p_CcNodeInformation, ccNodeInfo;
+ t_Handle p_Ad;
+ t_FmPcdCcNode *p_FmPcdCcNode1 = NULL;
+ t_FmPcdCcTree *p_FmPcdCcTree = NULL;
+ t_FmPcdStatsObj *p_StatsObj;
+ t_FmPcdCcStatsParams statsParams = {0};
+
+ ASSERT_COND(p_CcNextEngineParams);
+
+ /* check that new NIA is legal */
+ if (!p_AdditionalInfo->tree)
+ err = ValidateNextEngineParams(h_FmPcd,
+ p_CcNextEngineParams,
+ ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->statisticsMode);
+ else
+ /* Statistics are not supported for CC root */
+ err = ValidateNextEngineParams(h_FmPcd,
+ p_CcNextEngineParams,
+ e_FM_PCD_CC_STATS_MODE_NONE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ /* Update internal data structure for next engine per index (index - key) */
+ memcpy(&p_AdditionalInfo->keyAndNextEngineParams[keyIndex].nextEngineParams,
+ p_CcNextEngineParams,
+ sizeof(t_FmPcdCcNextEngineParams));
+
+ /* Check that manip is legal and what requiredAction is necessary for this manip */
+ if (p_CcNextEngineParams->h_Manip)
+ {
+ err = FmPcdManipCheckParamsForCcNextEngine(p_CcNextEngineParams, &requiredAction);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+
+ if (!p_AdditionalInfo->tree)
+ {
+ p_FmPcdCcNode1 = (t_FmPcdCcNode *)h_FmPcdCcNodeOrTree;
+ p_AdditionalInfo->numOfKeys = p_FmPcdCcNode1->numOfKeys;
+ p_Ad = p_FmPcdCcNode1->h_AdTable;
+
+ if (p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ p_AdditionalInfo->h_NodeForRmv = p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode;
+
+ if (p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip)
+ p_AdditionalInfo->h_ManipForRmv = p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip;
+
+#if (DPAA_VERSION >= 11)
+ if ((p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_FR) &&
+ (p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic))
+ p_AdditionalInfo->h_FrmReplicForRmv = p_FmPcdCcNode1->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic;
+#endif /* (DPAA_VERSION >= 11) */
+ }
+ else
+ {
+ p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcNodeOrTree;
+ p_Ad = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr);
+
+ if (p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ p_AdditionalInfo->h_NodeForRmv = p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.params.ccParams.h_CcNode;
+
+ if (p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip)
+ p_AdditionalInfo->h_ManipForRmv = p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.h_Manip;
+
+#if (DPAA_VERSION >= 11)
+ if ((p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.nextEngine == e_FM_PCD_FR) &&
+ (p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic))
+ p_AdditionalInfo->h_FrmReplicForRmv = p_FmPcdCcTree->keyAndNextEngineParams[keyIndex].nextEngineParams.params.frParams.h_FrmReplic;
+#endif /* (DPAA_VERSION >= 11) */
+ }
+
+ if ((p_CcNextEngineParams->nextEngine == e_FM_PCD_CC)
+ && p_CcNextEngineParams->h_Manip)
+ {
+ err = AllocAndFillAdForContLookupManip(p_CcNextEngineParams->params.ccParams.h_CcNode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+
+ ASSERT_COND(p_Ad);
+
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ ccNodeInfo.h_CcNode = PTR_MOVE(p_Ad, keyIndex * FM_PCD_CC_AD_ENTRY_SIZE);
+
+ /* If statistics were enabled, this Ad is the statistics Ad. Need to follow its
+ nextAction to retrieve the actual Nia-Ad. If statistics should remain enabled,
+ only the actual Nia-Ad should be modified. */
+ if ((!p_AdditionalInfo->tree) &&
+ (((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj) &&
+ (p_CcNextEngineParams->statisticsEn))
+ ccNodeInfo.h_CcNode = ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsAd;
+
+ EnqueueNodeInfoToRelevantLst(h_OldLst, &ccNodeInfo, NULL);
+
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ p_Ad = GetNewAd(h_FmPcdCcNodeOrTree, p_AdditionalInfo->tree);
+ if (!p_Ad)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node action descriptor"));
+ IOMemSet32((uint8_t *)p_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ /* If statistics were not enabled before, but requested now - Allocate a statistics
+ object that holds statistics AD and counters. */
+ if ((!p_AdditionalInfo->tree) &&
+ (!((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj) &&
+ (p_CcNextEngineParams->statisticsEn))
+ {
+ p_StatsObj = GetStatsObj((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree);
+ ASSERT_COND(p_StatsObj);
+
+ /* Store allocated statistics object */
+ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].p_StatsObj = p_StatsObj;
+
+ statsParams.h_StatsAd = p_StatsObj->h_StatsAd;
+ statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters;
+
+#if (DPAA_VERSION >= 11)
+ statsParams.h_StatsFLRs = ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->h_StatsFLRs;
+
+#endif /* (DPAA_VERSION >= 11) */
+
+ NextStepAd(p_Ad,
+ &statsParams,
+ p_CcNextEngineParams,
+ h_FmPcd);
+ }
+ else
+ NextStepAd(p_Ad,
+ NULL,
+ p_CcNextEngineParams,
+ h_FmPcd);
+
+ ccNodeInfo.h_CcNode = p_Ad;
+ EnqueueNodeInfoToRelevantLst(h_NewLst, &ccNodeInfo, NULL);
+
+ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction = requiredAction;
+ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction |= UPDATE_CC_WITH_TREE;
+
+ if (!p_AdditionalInfo->tree)
+ {
+ ASSERT_COND(p_FmPcdCcNode1);
+ if (!LIST_IsEmpty(&p_FmPcdCcNode1->ccTreesLst))
+ {
+ LIST_FOR_EACH(p_Pos, &p_FmPcdCcNode1->ccTreesLst)
+ {
+ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos);
+
+ ASSERT_COND(p_CcNodeInformation->h_CcNode);
+ /* Update the manipulation which has to be updated from parameters of the port
+ it's has to be updated with restrictions defined in the function */
+
+ err = SetRequiredAction(p_FmPcdCcNode1->h_FmPcd,
+ p_FmPcdCcNode1->shadowAction | p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction,
+ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex],
+ p_Ad,
+ 1,
+ p_CcNodeInformation->h_CcNode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+
+ err = CcUpdateParam(p_FmPcdCcNode1->h_FmPcd,
+ NULL,
+ NULL,
+ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex],
+ 1,
+ p_Ad,
+ TRUE,
+ p_CcNodeInformation->index,
+ p_CcNodeInformation->h_CcNode,
+ TRUE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+ }
+ }
+ else
+ {
+ ASSERT_COND(p_FmPcdCcTree);
+
+ err = SetRequiredAction(h_FmPcd,
+ p_FmPcdCcTree->requiredAction | p_AdditionalInfo->keyAndNextEngineParams[keyIndex].requiredAction,
+ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex],
+ p_Ad,
+ 1,
+ (t_Handle)p_FmPcdCcTree);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+
+ err = CcUpdateParam(h_FmPcd,
+ NULL,
+ NULL,
+ &p_AdditionalInfo->keyAndNextEngineParams[keyIndex],
+ 1,
+ p_Ad,
+ TRUE,
+ 0,
+ (t_Handle)p_FmPcdCcTree, TRUE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+
+ if (p_CcNextEngineParams->nextEngine == e_FM_PCD_CC)
+ p_AdditionalInfo->h_NodeForAdd = p_CcNextEngineParams->params.ccParams.h_CcNode;
+ if (p_CcNextEngineParams->h_Manip)
+ p_AdditionalInfo->h_ManipForAdd = p_CcNextEngineParams->h_Manip;
+
+ /* If statistics were previously enabled, but now are disabled,
+ store the old statistics object to be released */
+ if ((!p_AdditionalInfo->tree) &&
+ (((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj) &&
+ (!p_CcNextEngineParams->statisticsEn))
+ {
+ p_AdditionalInfo->p_StatsObjForRmv =
+ ((t_FmPcdCcNode *)h_FmPcdCcNodeOrTree)->keyAndNextEngineParams[keyIndex].p_StatsObj;
+
+
+ p_AdditionalInfo->keyAndNextEngineParams[keyIndex].p_StatsObj = NULL;
+ }
+#if (DPAA_VERSION >= 11)
+ if ((p_CcNextEngineParams->nextEngine == e_FM_PCD_FR) &&
+ (p_CcNextEngineParams->params.frParams.h_FrmReplic))
+ p_AdditionalInfo->h_FrmReplicForAdd = p_CcNextEngineParams->params.frParams.h_FrmReplic;
+#endif /* (DPAA_VERSION >= 11) */
+
+ return E_OK;
+}
+
+static void UpdateAdPtrOfNodesWhichPointsOnCrntMdfNode(t_FmPcdCcNode *p_CrntMdfNode,
+ t_List *h_OldLst,
+ t_FmPcdCcNextEngineParams **p_NextEngineParams)
+{
+ t_CcNodeInformation *p_CcNodeInformation;
+ t_FmPcdCcNode *p_NodePtrOnCurrentMdfNode = NULL;
+ t_List *p_Pos;
+ int i = 0;
+ t_Handle p_AdTablePtOnCrntCurrentMdfNode/*, p_AdTableNewModified*/;
+ t_CcNodeInformation ccNodeInfo;
+
+ LIST_FOR_EACH(p_Pos, &p_CrntMdfNode->ccPrevNodesLst)
+ {
+ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos);
+ p_NodePtrOnCurrentMdfNode = (t_FmPcdCcNode *)p_CcNodeInformation->h_CcNode;
+
+ ASSERT_COND(p_NodePtrOnCurrentMdfNode);
+
+ /* Search in the previous node which exact index points on this current modified node for getting AD */
+ for (i = 0; i < p_NodePtrOnCurrentMdfNode->numOfKeys + 1; i++)
+ {
+ if (p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ {
+ if (p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode == (t_Handle)p_CrntMdfNode)
+ {
+ if (p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip)
+ p_AdTablePtOnCrntCurrentMdfNode = p_CrntMdfNode->h_Ad;
+ else if (p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].p_StatsObj)
+ p_AdTablePtOnCrntCurrentMdfNode =
+ p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].p_StatsObj->h_StatsAd;
+ else
+ p_AdTablePtOnCrntCurrentMdfNode =
+ PTR_MOVE(p_NodePtrOnCurrentMdfNode->h_AdTable, i*FM_PCD_CC_AD_ENTRY_SIZE);
+
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ ccNodeInfo.h_CcNode = p_AdTablePtOnCrntCurrentMdfNode;
+ EnqueueNodeInfoToRelevantLst(h_OldLst, &ccNodeInfo, NULL);
+
+ if (!(*p_NextEngineParams))
+ *p_NextEngineParams = &p_NodePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams;
+ }
+ }
+ }
+
+ ASSERT_COND(i != p_NodePtrOnCurrentMdfNode->numOfKeys);
+ }
+}
+
+static void UpdateAdPtrOfTreesWhichPointsOnCrntMdfNode(t_FmPcdCcNode *p_CrntMdfNode,
+ t_List *h_OldLst,
+ t_FmPcdCcNextEngineParams **p_NextEngineParams)
+{
+ t_CcNodeInformation *p_CcNodeInformation;
+ t_FmPcdCcTree *p_TreePtrOnCurrentMdfNode = NULL;
+ t_List *p_Pos;
+ int i = 0;
+ t_Handle p_AdTableTmp;
+ t_CcNodeInformation ccNodeInfo;
+
+ LIST_FOR_EACH(p_Pos, &p_CrntMdfNode->ccTreeIdLst)
+ {
+ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos);
+ p_TreePtrOnCurrentMdfNode = (t_FmPcdCcTree *)p_CcNodeInformation->h_CcNode;
+
+ ASSERT_COND(p_TreePtrOnCurrentMdfNode);
+
+ /*search in the trees which exact index points on this current modified node for getting AD */
+ for (i = 0; i < p_TreePtrOnCurrentMdfNode->numOfEntries; i++)
+ {
+ if (p_TreePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ {
+ if (p_TreePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode == (t_Handle)p_CrntMdfNode)
+ {
+ p_AdTableTmp = UINT_TO_PTR(p_TreePtrOnCurrentMdfNode->ccTreeBaseAddr + i*FM_PCD_CC_AD_ENTRY_SIZE);
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ ccNodeInfo.h_CcNode = p_AdTableTmp;
+ EnqueueNodeInfoToRelevantLst(h_OldLst, &ccNodeInfo, NULL);
+
+ if (!(*p_NextEngineParams))
+ *p_NextEngineParams = &p_TreePtrOnCurrentMdfNode->keyAndNextEngineParams[i].nextEngineParams;
+ }
+ }
+ }
+
+ ASSERT_COND(i == p_TreePtrOnCurrentMdfNode->numOfEntries);
+ }
+}
+
+static t_FmPcdModifyCcKeyAdditionalParams * ModifyNodeCommonPart(t_Handle h_FmPcdCcNodeOrTree,
+ uint16_t keyIndex,
+ e_ModifyState modifyState,
+ bool ttlCheck,
+ bool hashCheck,
+ bool tree)
+{
+ t_FmPcdModifyCcKeyAdditionalParams *p_FmPcdModifyCcKeyAdditionalParams;
+ int i = 0, j = 0;
+ bool wasUpdate = FALSE;
+ t_FmPcdCcNode *p_CcNode = NULL;
+ t_FmPcdCcTree *p_FmPcdCcTree;
+ uint16_t numOfKeys;
+ t_FmPcdCcKeyAndNextEngineParams *p_KeyAndNextEngineParams;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcdCcNodeOrTree, E_INVALID_HANDLE, NULL);
+
+ if (!tree)
+ {
+ p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNodeOrTree;
+ numOfKeys = p_CcNode->numOfKeys;
+
+ /* node has to be pointed by another node or tree */
+ if (!LIST_NumOfObjs(&p_CcNode->ccPrevNodesLst) &&
+ !LIST_NumOfObjs(&p_CcNode->ccTreeIdLst))
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("node has to be pointed by node or tree"));
+ return NULL;
+ }
+
+ if (!LIST_NumOfObjs(&p_CcNode->ccTreesLst) ||
+ (LIST_NumOfObjs(&p_CcNode->ccTreesLst) != 1))
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("node has to be belonging to some tree and only to one tree"));
+ return NULL;
+ }
+
+ p_KeyAndNextEngineParams = (t_FmPcdCcKeyAndNextEngineParams *)XX_Malloc(sizeof(t_FmPcdCcKeyAndNextEngineParams)*(numOfKeys+1));
+ if (!p_KeyAndNextEngineParams)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Next engine and required action structure"));
+ return NULL;
+ }
+ memcpy(p_KeyAndNextEngineParams,
+ p_CcNode->keyAndNextEngineParams,
+ (numOfKeys+1) * sizeof(t_FmPcdCcKeyAndNextEngineParams));
+
+ if (ttlCheck)
+ {
+ if ((p_CcNode->parseCode == CC_PC_FF_IPV4TTL) ||
+ (p_CcNode->parseCode == CC_PC_FF_IPV6HOP_LIMIT))
+ {
+ XX_Free(p_KeyAndNextEngineParams);
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("nodeId of CC_PC_FF_IPV4TTL or CC_PC_FF_IPV6HOP_LIMIT can not be used for this operation"));
+ return NULL;
+ }
+ }
+
+ if (hashCheck)
+ {
+ if (p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED)
+ {
+ XX_Free(p_KeyAndNextEngineParams);
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("nodeId of CC_PC_GENERIC_IC_HASH_INDEXED can not be used for this operation"));
+ return NULL;
+ }
+ }
+ }
+ else
+ {
+ p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcNodeOrTree;
+ numOfKeys = p_FmPcdCcTree->numOfEntries;
+
+ p_KeyAndNextEngineParams = (t_FmPcdCcKeyAndNextEngineParams *)XX_Malloc(sizeof(t_FmPcdCcKeyAndNextEngineParams)*FM_PCD_MAX_NUM_OF_CC_GROUPS);
+ if (!p_KeyAndNextEngineParams)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Next engine and required action structure"));
+ return NULL;
+ }
+ memcpy(p_KeyAndNextEngineParams,
+ p_FmPcdCcTree->keyAndNextEngineParams,
+ FM_PCD_MAX_NUM_OF_CC_GROUPS * sizeof(t_FmPcdCcKeyAndNextEngineParams));
+ }
+
+ p_FmPcdModifyCcKeyAdditionalParams =
+ (t_FmPcdModifyCcKeyAdditionalParams *)XX_Malloc(sizeof(t_FmPcdModifyCcKeyAdditionalParams));
+ if (!p_FmPcdModifyCcKeyAdditionalParams)
+ {
+ XX_Free(p_KeyAndNextEngineParams);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of internal data structure FAILED"));
+ return NULL;
+ }
+ memset(p_FmPcdModifyCcKeyAdditionalParams, 0, sizeof(t_FmPcdModifyCcKeyAdditionalParams));
+
+ p_FmPcdModifyCcKeyAdditionalParams->h_CurrentNode = h_FmPcdCcNodeOrTree;
+ p_FmPcdModifyCcKeyAdditionalParams->savedKeyIndex = keyIndex;
+
+ while (i < numOfKeys)
+ {
+ if ((j == keyIndex) && !wasUpdate)
+ {
+ if (modifyState == e_MODIFY_STATE_ADD)
+ j++;
+ else if (modifyState == e_MODIFY_STATE_REMOVE)
+ i++;
+ wasUpdate = TRUE;
+ }
+ else
+ {
+ memcpy(&p_FmPcdModifyCcKeyAdditionalParams->keyAndNextEngineParams[j],
+ p_KeyAndNextEngineParams + i,
+ sizeof(t_FmPcdCcKeyAndNextEngineParams));
+ i++;
+ j++;
+ }
+ }
+
+ if (keyIndex == numOfKeys)
+ {
+ if (modifyState == e_MODIFY_STATE_ADD)
+ j++;
+ else if (modifyState == e_MODIFY_STATE_REMOVE)
+ i++;
+ }
+
+ memcpy(&p_FmPcdModifyCcKeyAdditionalParams->keyAndNextEngineParams[j],
+ p_KeyAndNextEngineParams + numOfKeys,
+ sizeof(t_FmPcdCcKeyAndNextEngineParams));
+
+ XX_Free(p_KeyAndNextEngineParams);
+
+ return p_FmPcdModifyCcKeyAdditionalParams;
+}
+
+static t_Error UpdatePtrWhichPointOnCrntMdfNode(t_FmPcdCcNode *p_CcNode,
+ t_FmPcdModifyCcKeyAdditionalParams *p_FmPcdModifyCcKeyAdditionalParams,
+ t_List *h_OldLst,
+ t_List *h_NewLst)
+{
+ t_FmPcdCcNextEngineParams *p_NextEngineParams = NULL;
+ t_CcNodeInformation ccNodeInfo = {0};
+ t_Handle h_NewAd;
+
+ /* Building a list of all action descriptors that point to the previous node */
+ if (!LIST_IsEmpty(&p_CcNode->ccPrevNodesLst))
+ UpdateAdPtrOfNodesWhichPointsOnCrntMdfNode(p_CcNode, h_OldLst, &p_NextEngineParams);
+
+ if (!LIST_IsEmpty(&p_CcNode->ccTreeIdLst))
+ UpdateAdPtrOfTreesWhichPointsOnCrntMdfNode(p_CcNode, h_OldLst, &p_NextEngineParams);
+
+ /* This node must be found as next engine of one of its previous nodes or trees*/
+ ASSERT_COND(p_NextEngineParams);
+
+ /* Building a new action descriptor that points to the modified node */
+ h_NewAd = GetNewAd(p_CcNode, FALSE);
+ if (!h_NewAd)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+ IOMemSet32(h_NewAd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ BuildNewAd(h_NewAd,
+ p_FmPcdModifyCcKeyAdditionalParams,
+ p_CcNode,
+ p_NextEngineParams);
+
+ ccNodeInfo.h_CcNode = h_NewAd;
+ EnqueueNodeInfoToRelevantLst(h_NewLst, &ccNodeInfo, NULL);
+
+ return E_OK;
+}
+
+static void UpdateCcRootOwner(t_FmPcdCcTree *p_FmPcdCcTree, bool add)
+{
+ ASSERT_COND(p_FmPcdCcTree);
+
+ /* this routine must be protected by the calling routine! */
+
+ if (add)
+ p_FmPcdCcTree->owners++;
+ else
+ {
+ ASSERT_COND(p_FmPcdCcTree->owners);
+ p_FmPcdCcTree->owners--;
+ }
+}
+
+static t_Error CheckAndSetManipParamsWithCcNodeParams(t_FmPcdCcNode *p_CcNode)
+{
+ t_Error err = E_OK;
+ int i = 0;
+
+ for (i = 0; i < p_CcNode->numOfKeys; i++)
+ {
+ if (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip)
+ {
+ err = FmPcdManipCheckParamsWithCcNodeParams(p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip,
+ (t_Handle)p_CcNode);
+ if (err)
+ return err;
+ }
+ }
+
+ return err;
+}
+static t_Error ValidateAndCalcStatsParams(t_FmPcdCcNode *p_CcNode,
+ t_FmPcdCcNodeParams *p_CcNodeParam,
+ uint32_t *p_NumOfRanges,
+ uint32_t *p_CountersArraySize)
+{
+ e_FmPcdCcStatsMode statisticsMode = p_CcNode->statisticsMode;
+ uint32_t i;
+
+ UNUSED(p_CcNodeParam);
+
+ switch (statisticsMode)
+ {
+ case e_FM_PCD_CC_STATS_MODE_NONE:
+ for (i = 0; i < p_CcNode->numOfKeys; i++)
+ if (p_CcNodeParam->keysParams.keyParams[i].ccNextEngineParams.statisticsEn)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("Statistics cannot be enabled for key %d when statistics mode was set to 'NONE'", i));
+ return E_OK;
+
+ case e_FM_PCD_CC_STATS_MODE_FRAME:
+ case e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME:
+ *p_NumOfRanges = 1;
+ *p_CountersArraySize = 2 * FM_PCD_CC_STATS_COUNTER_SIZE;
+ return E_OK;
+
+#if (DPAA_VERSION >= 11)
+ case e_FM_PCD_CC_STATS_MODE_RMON:
+ {
+ uint16_t *p_FrameLengthRanges = p_CcNodeParam->keysParams.frameLengthRanges;
+ uint32_t i;
+
+ if (p_FrameLengthRanges[0] <= 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Statistics mode"));
+
+ if (p_FrameLengthRanges[0] == 0xFFFF)
+ {
+ *p_NumOfRanges = 1;
+ *p_CountersArraySize = 2 * FM_PCD_CC_STATS_COUNTER_SIZE;
+ return E_OK;
+ }
+
+ for (i = 1; i < FM_PCD_CC_STATS_MAX_NUM_OF_FLR; i++)
+ {
+ if (p_FrameLengthRanges[i-1] >= p_FrameLengthRanges[i])
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("Frame length range must be larger at least by 1 from preceding range"));
+
+ /* Stop when last range is reached */
+ if (p_FrameLengthRanges[i] == 0xFFFF)
+ break;
+ }
+
+ if ((i >= FM_PCD_CC_STATS_MAX_NUM_OF_FLR) ||
+ (p_FrameLengthRanges[i] != 0xFFFF))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Last Frame length range must be 0xFFFF"));
+
+ *p_NumOfRanges = i+1;
+
+ /* Allocate an extra counter for byte count, as counters
+ array always begins with byte count */
+ *p_CountersArraySize = (*p_NumOfRanges + 1) * FM_PCD_CC_STATS_COUNTER_SIZE;
+
+ }
+ return E_OK;
+#endif /* (DPAA_VERSION >= 11) */
+
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Statistics mode"));
+ }
+}
+
+static t_Error CheckParams(t_Handle h_FmPcd,
+ t_FmPcdCcNodeParams *p_CcNodeParam,
+ t_FmPcdCcNode *p_CcNode,
+ bool *isKeyTblAlloc)
+{
+ int tmp = 0;
+ t_FmPcdCcKeyParams *p_KeyParams;
+ t_Error err;
+ uint32_t requiredAction = 0;
+
+ /* Validate statistics parameters */
+ err = ValidateAndCalcStatsParams(p_CcNode,
+ p_CcNodeParam,
+ &(p_CcNode->numOfStatsFLRs),
+ &(p_CcNode->countersArraySize));
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("Invalid statistics parameters"));
+
+ /* Validate next engine parameters on Miss */
+ err = ValidateNextEngineParams(h_FmPcd,
+ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss,
+ p_CcNode->statisticsMode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("For this node MissNextEngineParams are not valid"));
+
+ if (p_CcNodeParam->keysParams.ccNextEngineParamsForMiss.h_Manip)
+ {
+ err = FmPcdManipCheckParamsForCcNextEngine(&p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, &requiredAction);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+
+ memcpy(&p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams,
+ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss,
+ sizeof(t_FmPcdCcNextEngineParams));
+
+ p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].requiredAction = requiredAction;
+
+ if ((p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ && p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.h_Manip)
+ {
+ err = AllocAndFillAdForContLookupManip(p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.params.ccParams.h_CcNode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+
+ for (tmp = 0; tmp < p_CcNode->numOfKeys; tmp++)
+ {
+ p_KeyParams = &p_CcNodeParam->keysParams.keyParams[tmp];
+
+ if (!p_KeyParams->p_Key)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("p_Key is not initialized"));
+
+ err = ValidateNextEngineParams(h_FmPcd,
+ &p_KeyParams->ccNextEngineParams,
+ p_CcNode->statisticsMode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+
+ err = UpdateGblMask(p_CcNode,
+ p_CcNodeParam->keysParams.keySize,
+ p_KeyParams->p_Mask);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+
+ if (p_KeyParams->ccNextEngineParams.h_Manip)
+ {
+ err = FmPcdManipCheckParamsForCcNextEngine(&p_KeyParams->ccNextEngineParams, &requiredAction);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+
+ /* Store 'key' parameters - key, mask (if passed by the user) */
+ memcpy(p_CcNode->keyAndNextEngineParams[tmp].key, p_KeyParams->p_Key, p_CcNodeParam->keysParams.keySize);
+
+ if (p_KeyParams->p_Mask)
+ memcpy(p_CcNode->keyAndNextEngineParams[tmp].mask,
+ p_KeyParams->p_Mask,
+ p_CcNodeParam->keysParams.keySize);
+ else
+ memset((void *)(p_CcNode->keyAndNextEngineParams[tmp].mask),
+ 0xFF,
+ p_CcNodeParam->keysParams.keySize);
+
+ /* Store next engine parameters */
+ memcpy(&p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams,
+ &p_KeyParams->ccNextEngineParams,
+ sizeof(t_FmPcdCcNextEngineParams));
+
+ p_CcNode->keyAndNextEngineParams[tmp].requiredAction = requiredAction;
+
+ if ((p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ && p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip)
+ {
+ err = AllocAndFillAdForContLookupManip(p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.params.ccParams.h_CcNode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+ }
+
+ if (p_CcNode->maxNumOfKeys)
+ {
+ if (p_CcNode->maxNumOfKeys < p_CcNode->numOfKeys)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Number of keys exceed the provided maximal number of keys"));
+ }
+
+ *isKeyTblAlloc = TRUE;
+
+ return E_OK;
+}
+
+static t_Error Ipv4TtlOrIpv6HopLimitCheckParams(t_Handle h_FmPcd,
+ t_FmPcdCcNodeParams *p_CcNodeParam,
+ t_FmPcdCcNode *p_CcNode,
+ bool *isKeyTblAlloc)
+{
+ int tmp = 0;
+ t_FmPcdCcKeyParams *p_KeyParams;
+ t_Error err;
+ uint8_t key = 0x01;
+ uint32_t requiredAction = 0;
+
+ if (p_CcNode->numOfKeys != 1)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For node of the type IPV4_TTL or IPV6_HOP_LIMIT the maximal supported 'numOfKeys' is 1"));
+
+ if ((p_CcNodeParam->keysParams.maxNumOfKeys) && (p_CcNodeParam->keysParams.maxNumOfKeys != 1))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For node of the type IPV4_TTL or IPV6_HOP_LIMIT the maximal supported 'maxNumOfKeys' is 1"));
+
+ /* Validate statistics parameters */
+ err = ValidateAndCalcStatsParams(p_CcNode,
+ p_CcNodeParam,
+ &(p_CcNode->numOfStatsFLRs),
+ &(p_CcNode->countersArraySize));
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("Invalid statistics parameters"));
+
+ err = ValidateNextEngineParams(h_FmPcd,
+ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss,
+ p_CcNodeParam->keysParams.statisticsMode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("For this node MissNextEngineParams are not valid"));
+
+ if (p_CcNodeParam->keysParams.ccNextEngineParamsForMiss.h_Manip)
+ {
+ err = FmPcdManipCheckParamsForCcNextEngine(&p_CcNodeParam->keysParams.ccNextEngineParamsForMiss, &requiredAction);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+
+ memcpy(&p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams,
+ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss,
+ sizeof(t_FmPcdCcNextEngineParams));
+
+ p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].requiredAction = requiredAction;
+
+ if ((p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ && p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.h_Manip)
+ {
+ err = AllocAndFillAdForContLookupManip(p_CcNode->keyAndNextEngineParams[p_CcNode->numOfKeys].nextEngineParams.params.ccParams.h_CcNode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+
+ for (tmp = 0; tmp < p_CcNode->numOfKeys; tmp++)
+ {
+ p_KeyParams = &p_CcNodeParam->keysParams.keyParams[tmp];
+
+ if (p_KeyParams->p_Mask)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For node of the type IPV4_TTL or IPV6_HOP_LIMIT p_Mask can not be initialized"));
+
+ if (memcmp(p_KeyParams->p_Key, &key, 1) != 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For node of the type IPV4_TTL or IPV6_HOP_LIMIT p_Key has to be 1"));
+
+ err = ValidateNextEngineParams(h_FmPcd,
+ &p_KeyParams->ccNextEngineParams,
+ p_CcNode->statisticsMode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+
+ if (p_KeyParams->ccNextEngineParams.h_Manip)
+ {
+ err = FmPcdManipCheckParamsForCcNextEngine(&p_KeyParams->ccNextEngineParams, &requiredAction);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+
+ /* Store 'key' parameters - key (fixed to 0x01), key size of 1 byte and full mask */
+ p_CcNode->keyAndNextEngineParams[tmp].key[0] = key;
+ p_CcNode->keyAndNextEngineParams[tmp].mask[0] = 0xFF;
+
+ /* Store NextEngine parameters */
+ memcpy(&p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams,
+ &p_KeyParams->ccNextEngineParams,
+ sizeof(t_FmPcdCcNextEngineParams));
+
+ if ((p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ && p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip)
+ {
+ err = AllocAndFillAdForContLookupManip(p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.params.ccParams.h_CcNode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+ p_CcNode->keyAndNextEngineParams[tmp].requiredAction = requiredAction;
+ }
+
+ *isKeyTblAlloc = FALSE;
+
+ return E_OK;
+}
+
+static t_Error IcHashIndexedCheckParams(t_Handle h_FmPcd,
+ t_FmPcdCcNodeParams *p_CcNodeParam,
+ t_FmPcdCcNode *p_CcNode,
+ bool *isKeyTblAlloc)
+{
+ int tmp = 0, countOnes = 0;
+ t_FmPcdCcKeyParams *p_KeyParams;
+ t_Error err;
+ uint16_t glblMask = p_CcNodeParam->extractCcParams.extractNonHdr.icIndxMask;
+ uint16_t countMask = (uint16_t)(glblMask >> 4);
+ uint32_t requiredAction = 0;
+
+ if (glblMask & 0x000f)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("icIndxMask has to be with last nibble 0"));
+
+ while (countMask)
+ {
+ countOnes++;
+ countMask = (uint16_t)(countMask >> 1);
+ }
+
+ if (!POWER_OF_2(p_CcNode->numOfKeys))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For Node of the type INDEXED numOfKeys has to be powerOfTwo"));
+
+ if (p_CcNode->numOfKeys != ((uint32_t)1 << countOnes))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For Node of the type IC_HASH_INDEXED numOfKeys has to be powerOfTwo"));
+
+ if (p_CcNodeParam->keysParams.maxNumOfKeys &&
+ (p_CcNodeParam->keysParams.maxNumOfKeys != p_CcNode->numOfKeys))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For Node of the type INDEXED 'maxNumOfKeys' should be 0 or equal 'numOfKeys'"));
+
+ /* Validate statistics parameters */
+ err = ValidateAndCalcStatsParams(p_CcNode,
+ p_CcNodeParam,
+ &(p_CcNode->numOfStatsFLRs),
+ &(p_CcNode->countersArraySize));
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("Invalid statistics parameters"));
+
+ err = ValidateNextEngineParams(h_FmPcd,
+ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss,
+ p_CcNode->statisticsMode);
+ if (GET_ERROR_TYPE(err)!= E_NOT_SUPPORTED)
+ RETURN_ERROR(MAJOR, err, ("MissNextEngineParams for the node of the type IC_INDEX_HASH has to be UnInitialized"));
+
+ for (tmp = 0; tmp < p_CcNode->numOfKeys; tmp++)
+ {
+ p_KeyParams = &p_CcNodeParam->keysParams.keyParams[tmp];
+
+ if (p_KeyParams->p_Mask || p_KeyParams->p_Key)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For Node of the type IC_HASH_INDEXED p_Key or p_Mask has to be NULL"));
+
+ if ((glblMask & (tmp * 16)) == (tmp * 16))
+ {
+ err = ValidateNextEngineParams(h_FmPcd,
+ &p_KeyParams->ccNextEngineParams,
+ p_CcNode->statisticsMode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("This index has to be initialized for the node of the type IC_INDEX_HASH according to settings of GlobalMask "));
+
+ if (p_KeyParams->ccNextEngineParams.h_Manip)
+ {
+ err = FmPcdManipCheckParamsForCcNextEngine(&p_KeyParams->ccNextEngineParams, &requiredAction);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ p_CcNode->keyAndNextEngineParams[tmp].requiredAction = requiredAction;
+ }
+
+ memcpy(&p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams,
+ &p_KeyParams->ccNextEngineParams,
+ sizeof(t_FmPcdCcNextEngineParams));
+
+ if ((p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ && p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip)
+ {
+ err = AllocAndFillAdForContLookupManip(p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.params.ccParams.h_CcNode);
+ if (err)
+ RETURN_ERROR(MAJOR, err, (NO_MSG));
+ }
+ }
+ else
+ {
+ err = ValidateNextEngineParams(h_FmPcd,
+ &p_KeyParams->ccNextEngineParams,
+ p_CcNode->statisticsMode);
+ if (GET_ERROR_TYPE(err)!= E_NOT_SUPPORTED)
+ RETURN_ERROR(MAJOR, err, ("This index has to be UnInitialized for the node of the type IC_INDEX_HASH according to settings of GlobalMask"));
+ }
+ }
+
+ *isKeyTblAlloc = FALSE;
+ memcpy(PTR_MOVE(p_CcNode->p_GlblMask, 2), &glblMask, 2);
+
+ return E_OK;
+}
+
+static t_Error ModifyNextEngineParamNode(t_Handle h_FmPcd,
+ t_Handle h_FmPcdCcNode,
+ uint16_t keyIndex,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode;
+ t_FmPcd *p_FmPcd;
+ t_List h_OldPointersLst, h_NewPointersLst;
+ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd,E_INVALID_VALUE);
+ SANITY_CHECK_RETURN_ERROR(p_CcNode,E_INVALID_HANDLE);
+
+ if (keyIndex >= p_CcNode->numOfKeys)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("keyIndex > previously cleared last index + 1"));
+
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+
+ INIT_LIST(&h_OldPointersLst);
+ INIT_LIST(&h_NewPointersLst);
+
+ p_ModifyKeyParams = ModifyNodeCommonPart(p_CcNode, keyIndex, e_MODIFY_STATE_CHANGE, FALSE, FALSE, FALSE);
+ if (!p_ModifyKeyParams)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ if (p_CcNode->maxNumOfKeys &&
+ !TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
+ {
+ XX_Free(p_ModifyKeyParams);
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = BuildNewNodeModifyNextEngine(h_FmPcd,
+ p_CcNode,
+ keyIndex,
+ p_FmPcdCcNextEngineParams,
+ &h_OldPointersLst,
+ &h_NewPointersLst,
+ p_ModifyKeyParams);
+ if (err)
+ {
+ XX_Free(p_ModifyKeyParams);
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = DoDynamicChange(p_FmPcd, &h_OldPointersLst, &h_NewPointersLst, p_ModifyKeyParams, FALSE);
+
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+
+ return err;
+}
+
+static t_Error FindKeyIndex(t_Handle h_CcNode,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t *p_Mask,
+ uint16_t *p_KeyIndex)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ uint8_t tmpMask[FM_PCD_MAX_SIZE_OF_KEY];
+ uint16_t i;
+
+ ASSERT_COND(p_Key);
+ ASSERT_COND(p_KeyIndex);
+ ASSERT_COND(keySize < FM_PCD_MAX_SIZE_OF_KEY);
+
+ if (keySize != p_CcNode->userSizeOfExtraction)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Key size doesn't match the extraction size of the node"));
+
+ /* If user didn't pass a mask for this key, we'll look for full extraction mask */
+ if (!p_Mask)
+ memset(tmpMask, 0xFF, keySize);
+
+ for (i = 0 ; i < p_CcNode->numOfKeys; i++)
+ {
+ /* Comparing received key */
+ if (memcmp(p_Key, p_CcNode->keyAndNextEngineParams[i].key, keySize) == 0)
+ {
+ if (p_Mask)
+ {
+ /* If a user passed a mask for this key, it must match to the existing key's mask for a correct match */
+ if (memcmp(p_Mask, p_CcNode->keyAndNextEngineParams[i].mask, keySize) == 0)
+ {
+ *p_KeyIndex = i;
+ return E_OK;
+ }
+ }
+ else
+ {
+ /* If user didn't pass a mask for this key, check if the existing key mask is full extraction */
+ if (memcmp(tmpMask, p_CcNode->keyAndNextEngineParams[i].mask, keySize) == 0)
+ {
+ *p_KeyIndex = i;
+ return E_OK;
+ }
+ }
+ }
+ }
+
+ return ERROR_CODE(E_NOT_FOUND);
+}
+
+static t_Error CalcAndUpdateCcShadow(t_FmPcdCcNode *p_CcNode,
+ bool isKeyTblAlloc,
+ uint32_t *p_MatchTableSize,
+ uint32_t *p_AdTableSize)
+{
+ uint32_t shadowSize;
+ t_Error err;
+
+ /* Calculate keys table maximal size - each entry consists of a key and a mask,
+ (if local mask support is requested) */
+ *p_MatchTableSize = p_CcNode->ccKeySizeAccExtraction * sizeof(uint8_t) * p_CcNode->maxNumOfKeys;
+
+ if (p_CcNode->maskSupport)
+ *p_MatchTableSize *= 2;
+
+ /* Calculate next action descriptors table, including one more entry for miss */
+ *p_AdTableSize = (uint32_t)((p_CcNode->maxNumOfKeys + 1) * FM_PCD_CC_AD_ENTRY_SIZE);
+
+ /* Calculate maximal shadow size of this node.
+ All shadow structures will be used for runtime modifications host command. If
+ keys table was allocated for this node, the keys table and next engines table may
+ be modified in run time (entries added or removed), so shadow tables are requires.
+ Otherwise, the only supported runtime modification is a specific next engine update
+ and this requires shadow memory of a single AD */
+
+ /* Shadow size should be enough to hold the following 3 structures:
+ * 1 - an action descriptor */
+ shadowSize = FM_PCD_CC_AD_ENTRY_SIZE;
+
+ /* 2 - keys match table, if was allocated for the current node */
+ if (isKeyTblAlloc)
+ shadowSize += *p_MatchTableSize;
+
+ /* 3 - next action descriptors table */
+ shadowSize += *p_AdTableSize;
+
+ /* Update shadow to the calculated size */
+ err = FmPcdUpdateCcShadow (p_CcNode->h_FmPcd, (uint32_t)shadowSize, FM_PCD_CC_AD_TABLE_ALIGN);
+ if (err != E_OK)
+ {
+ DeleteNode(p_CcNode);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node shadow"));
+ }
+
+ return E_OK;
+}
+
+static t_Error AllocStatsObjs(t_FmPcdCcNode *p_CcNode)
+{
+ t_FmPcdStatsObj *p_StatsObj;
+ t_Handle h_FmMuram, h_StatsAd, h_StatsCounters;
+ uint32_t i;
+
+ h_FmMuram = FmPcdGetMuramHandle(p_CcNode->h_FmPcd);
+ if (!h_FmMuram)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM MURAM"));
+
+ /* Allocate statistics ADs and statistics counter. An extra pair (AD + counters)
+ will be allocated to support runtime modifications */
+ for (i = 0; i < p_CcNode->maxNumOfKeys + 2; i++)
+ {
+ /* Allocate list object structure */
+ p_StatsObj = XX_Malloc(sizeof(t_FmPcdStatsObj));
+ if (!p_StatsObj)
+ {
+ FreeStatObjects(&p_CcNode->availableStatsLst, h_FmMuram);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Statistics object"));
+ }
+ memset(p_StatsObj, 0, sizeof(t_FmPcdStatsObj));
+
+ /* Allocate statistics AD from MURAM */
+ h_StatsAd = (t_Handle)FM_MURAM_AllocMem(h_FmMuram,
+ FM_PCD_CC_AD_ENTRY_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!h_StatsAd)
+ {
+ FreeStatObjects(&p_CcNode->availableStatsLst, h_FmMuram);
+ XX_Free(p_StatsObj);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for statistics ADs"));
+ }
+ IOMemSet32(h_StatsAd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ /* Allocate statistics counters from MURAM */
+ h_StatsCounters = (t_Handle)FM_MURAM_AllocMem(h_FmMuram,
+ p_CcNode->countersArraySize,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!h_StatsCounters)
+ {
+ FreeStatObjects(&p_CcNode->availableStatsLst, h_FmMuram);
+ FM_MURAM_FreeMem(h_FmMuram, h_StatsAd);
+ XX_Free(p_StatsObj);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for statistics counters"));
+ }
+ IOMemSet32(h_StatsCounters, 0, p_CcNode->countersArraySize);
+
+ p_StatsObj->h_StatsAd = h_StatsAd;
+ p_StatsObj->h_StatsCounters = h_StatsCounters;
+
+ EnqueueStatsObj(&p_CcNode->availableStatsLst, p_StatsObj);
+ }
+
+ return E_OK;
+}
+
+static t_Error MatchTableGetKeyStatistics(t_FmPcdCcNode *p_CcNode,
+ uint16_t keyIndex,
+ t_FmPcdCcKeyStatistics *p_KeyStatistics)
+{
+ uint32_t *p_StatsCounters, i;
+
+ if (p_CcNode->statisticsMode == e_FM_PCD_CC_STATS_MODE_NONE)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Statistics were not enabled for this match table"));
+
+ if (!p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Statistics were not enabled for this key"));
+
+ memset(p_KeyStatistics, 0, sizeof (t_FmPcdCcKeyStatistics));
+
+ p_StatsCounters = p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsCounters;
+ ASSERT_COND(p_StatsCounters);
+
+ p_KeyStatistics->byteCount = GET_UINT32(*p_StatsCounters);
+
+ for (i = 1; i <= p_CcNode->numOfStatsFLRs; i++)
+ {
+ p_StatsCounters = PTR_MOVE(p_StatsCounters, FM_PCD_CC_STATS_COUNTER_SIZE);
+
+ p_KeyStatistics->frameCount += GET_UINT32(*p_StatsCounters);
+
+#if (DPAA_VERSION >= 11)
+ p_KeyStatistics->frameLengthRangeCount[i-1] = GET_UINT32(*p_StatsCounters);
+#endif /* (DPAA_VERSION >= 11) */
+ }
+
+ return E_OK;
+}
+
+static t_Error MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNode *p_CcNode, t_FmPcdCcNodeParams *p_CcNodeParam)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *) h_FmPcd;
+ t_FmPcdCcNode *p_FmPcdCcNextNode;
+ t_Error err = E_OK;
+ uint32_t tmp, keySize;
+ bool glblMask = FALSE;
+ t_FmPcdCcKeyParams *p_KeyParams;
+ t_Handle h_FmMuram, p_KeysMatchTblTmp, p_AdTableTmp;
+#if (DPAA_VERSION >= 11)
+ t_Handle h_StatsFLRs;
+#endif /* (DPAA_VERSION >= 11) */
+ bool fullField = FALSE;
+ ccPrivateInfo_t icCode = CC_PRIVATE_INFO_NONE;
+ bool isKeyTblAlloc, fromIc = FALSE;
+ uint32_t matchTableSize, adTableSize;
+ t_CcNodeInformation ccNodeInfo, *p_CcInformation;
+ t_FmPcdStatsObj *p_StatsObj;
+ t_FmPcdCcStatsParams statsParams = {0};
+ t_Handle h_Manip;
+
+ ASSERT_COND(h_FmPcd);
+ ASSERT_COND(p_CcNode);
+ ASSERT_COND(p_CcNodeParam);
+
+ p_CcNode->p_GlblMask = (t_Handle)XX_Malloc(CC_GLBL_MASK_SIZE * sizeof(uint8_t));
+ memset(p_CcNode->p_GlblMask, 0, CC_GLBL_MASK_SIZE * sizeof(uint8_t));
+
+ p_CcNode->h_FmPcd = h_FmPcd;
+ p_CcNode->numOfKeys = p_CcNodeParam->keysParams.numOfKeys;
+ p_CcNode->maxNumOfKeys = p_CcNodeParam->keysParams.maxNumOfKeys;
+ p_CcNode->maskSupport = p_CcNodeParam->keysParams.maskSupport;
+ p_CcNode->statisticsMode = p_CcNodeParam->keysParams.statisticsMode;
+
+ /* For backward compatibility - even if statistics mode is nullified,
+ we'll fix it to frame mode so we can support per-key request for
+ statistics using 'statisticsEn' in next engine parameters */
+ if (!p_CcNode->maxNumOfKeys &&
+ (p_CcNode->statisticsMode == e_FM_PCD_CC_STATS_MODE_NONE))
+ p_CcNode->statisticsMode = e_FM_PCD_CC_STATS_MODE_FRAME;
+
+ h_FmMuram = FmPcdGetMuramHandle(h_FmPcd);
+ if (!h_FmMuram)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM MURAM"));
+
+ INIT_LIST(&p_CcNode->ccPrevNodesLst);
+ INIT_LIST(&p_CcNode->ccTreeIdLst);
+ INIT_LIST(&p_CcNode->ccTreesLst);
+ INIT_LIST(&p_CcNode->availableStatsLst);
+
+ p_CcNode->h_Spinlock = XX_InitSpinlock();
+ if (!p_CcNode->h_Spinlock)
+ {
+ DeleteNode(p_CcNode);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("CC node spinlock"));
+ }
+
+ if ((p_CcNodeParam->extractCcParams.type == e_FM_PCD_EXTRACT_BY_HDR) &&
+ ((p_CcNodeParam->extractCcParams.extractByHdr.hdr == HEADER_TYPE_IPv4) ||
+ (p_CcNodeParam->extractCcParams.extractByHdr.hdr == HEADER_TYPE_IPv6)) &&
+ (p_CcNodeParam->extractCcParams.extractByHdr.type == e_FM_PCD_EXTRACT_FULL_FIELD) &&
+ ((p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField.ipv6 == NET_HEADER_FIELD_IPv6_HOP_LIMIT) ||
+ (p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField.ipv4 == NET_HEADER_FIELD_IPv4_TTL)))
+ {
+ err = Ipv4TtlOrIpv6HopLimitCheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, &isKeyTblAlloc);
+ glblMask = FALSE;
+ }
+ else if ((p_CcNodeParam->extractCcParams.type == e_FM_PCD_EXTRACT_NON_HDR) &&
+ ((p_CcNodeParam->extractCcParams.extractNonHdr.src == e_FM_PCD_EXTRACT_FROM_KEY) ||
+ (p_CcNodeParam->extractCcParams.extractNonHdr.src == e_FM_PCD_EXTRACT_FROM_HASH) ||
+ (p_CcNodeParam->extractCcParams.extractNonHdr.src == e_FM_PCD_EXTRACT_FROM_FLOW_ID)))
+ {
+ if ((p_CcNodeParam->extractCcParams.extractNonHdr.src == e_FM_PCD_EXTRACT_FROM_FLOW_ID) &&
+ (p_CcNodeParam->extractCcParams.extractNonHdr.offset != 0))
+ {
+ DeleteNode(p_CcNode);
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("In the case of the extraction from e_FM_PCD_EXTRACT_FROM_FLOW_ID offset has to be 0"));
+ }
+
+ icCode = IcDefineCode(p_CcNodeParam);
+ fromIc = TRUE;
+ if (icCode == CC_PRIVATE_INFO_NONE)
+ {
+ DeleteNode(p_CcNode);
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,
+ ("user asked extraction from IC and field in internal context or action wasn't initialized in the right way"));
+ }
+
+ if ((icCode == CC_PRIVATE_INFO_IC_DEQ_FQID_INDEX_LOOKUP) ||
+ (icCode == CC_PRIVATE_INFO_IC_HASH_INDEX_LOOKUP))
+ {
+ err = IcHashIndexedCheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, &isKeyTblAlloc);
+ glblMask = TRUE;
+ }
+ else
+ {
+ err = CheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, &isKeyTblAlloc);
+ if (p_CcNode->glblMaskSize)
+ glblMask = TRUE;
+ }
+ }
+ else
+ {
+ err = CheckParams(h_FmPcd, p_CcNodeParam, p_CcNode, &isKeyTblAlloc);
+ if (p_CcNode->glblMaskSize)
+ glblMask = TRUE;
+ }
+
+ if (err)
+ {
+ DeleteNode(p_CcNode);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ switch (p_CcNodeParam->extractCcParams.type)
+ {
+ case (e_FM_PCD_EXTRACT_BY_HDR):
+ switch (p_CcNodeParam->extractCcParams.extractByHdr.type)
+ {
+ case (e_FM_PCD_EXTRACT_FULL_FIELD):
+ p_CcNode->parseCode =
+ GetFullFieldParseCode(p_CcNodeParam->extractCcParams.extractByHdr.hdr,
+ p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex,
+ p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField);
+ GetSizeHeaderField(p_CcNodeParam->extractCcParams.extractByHdr.hdr,
+ p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex,
+ p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fullField,
+ &p_CcNode->sizeOfExtraction);
+ fullField = TRUE;
+ if ((p_CcNode->parseCode != CC_PC_FF_TCI1) &&
+ (p_CcNode->parseCode != CC_PC_FF_TCI2) &&
+ (p_CcNode->parseCode != CC_PC_FF_MPLS1) &&
+ (p_CcNode->parseCode != CC_PC_FF_MPLS_LAST) &&
+ (p_CcNode->parseCode != CC_PC_FF_IPV4IPTOS_TC1) &&
+ (p_CcNode->parseCode != CC_PC_FF_IPV4IPTOS_TC2) &&
+ (p_CcNode->parseCode != CC_PC_FF_IPTOS_IPV6TC1_IPV6FLOW1) &&
+ (p_CcNode->parseCode != CC_PC_FF_IPDSCP) &&
+ (p_CcNode->parseCode != CC_PC_FF_IPTOS_IPV6TC2_IPV6FLOW2) &&
+ glblMask)
+ {
+ glblMask = FALSE;
+ p_CcNode->glblMaskSize = 4;
+ p_CcNode->lclMask = TRUE;
+ }
+ break;
+
+ case (e_FM_PCD_EXTRACT_FROM_HDR):
+ p_CcNode->sizeOfExtraction = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromHdr.size;
+ p_CcNode->offset = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromHdr.offset;
+ p_CcNode->userOffset = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromHdr.offset;
+ p_CcNode->parseCode =
+ GetPrParseCode(p_CcNodeParam->extractCcParams.extractByHdr.hdr,
+ p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex,
+ p_CcNode->offset,glblMask,
+ &p_CcNode->prsArrayOffset);
+ break;
+
+ case (e_FM_PCD_EXTRACT_FROM_FIELD):
+ p_CcNode->offset = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.offset;
+ p_CcNode->userOffset = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.offset;
+ p_CcNode->sizeOfExtraction = p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.size;
+ p_CcNode->parseCode =
+ GetFieldParseCode(p_CcNodeParam->extractCcParams.extractByHdr.hdr,
+ p_CcNodeParam->extractCcParams.extractByHdr.extractByHdrType.fromField.field,
+ p_CcNode->offset,
+ &p_CcNode->prsArrayOffset,
+ p_CcNodeParam->extractCcParams.extractByHdr.hdrIndex);
+ break;
+
+ default:
+ DeleteNode(p_CcNode);
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+ break;
+
+ case (e_FM_PCD_EXTRACT_NON_HDR):
+ /* get the field code for the generic extract */
+ p_CcNode->sizeOfExtraction = p_CcNodeParam->extractCcParams.extractNonHdr.size;
+ p_CcNode->offset = p_CcNodeParam->extractCcParams.extractNonHdr.offset;
+ p_CcNode->userOffset = p_CcNodeParam->extractCcParams.extractNonHdr.offset;
+ p_CcNode->parseCode =
+ GetGenParseCode(h_FmPcd,
+ p_CcNodeParam->extractCcParams.extractNonHdr.src,
+ p_CcNode->offset,
+ glblMask,
+ &p_CcNode->prsArrayOffset,
+ fromIc,icCode);
+
+ if (p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED)
+ {
+ if ((p_CcNode->offset + p_CcNode->sizeOfExtraction) > 8)
+ {
+ DeleteNode(p_CcNode);
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION,("when node of the type CC_PC_GENERIC_IC_HASH_INDEXED offset + size can not be bigger then size of HASH 64 bits (8 bytes)"));
+ }
+ }
+ if ((p_CcNode->parseCode == CC_PC_GENERIC_IC_GMASK) ||
+ (p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED))
+ {
+ p_CcNode->offset += p_CcNode->prsArrayOffset;
+ p_CcNode->prsArrayOffset = 0;
+ }
+ break;
+
+ default:
+ DeleteNode(p_CcNode);
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+
+ if (p_CcNode->parseCode == CC_PC_ILLEGAL)
+ {
+ DeleteNode(p_CcNode);
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("illegal extraction type"));
+ }
+
+ if ((p_CcNode->sizeOfExtraction > FM_PCD_MAX_SIZE_OF_KEY) ||
+ !p_CcNode->sizeOfExtraction)
+ {
+ DeleteNode(p_CcNode);
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("sizeOfExatrction can not be greater than 56 and not 0"));
+ }
+
+ if (p_CcNodeParam->keysParams.keySize != p_CcNode->sizeOfExtraction)
+ {
+ DeleteNode(p_CcNode);
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("keySize has to be equal to sizeOfExtraction"));
+ }
+
+ p_CcNode->userSizeOfExtraction = p_CcNode->sizeOfExtraction;
+
+ if (!glblMask)
+ memset(p_CcNode->p_GlblMask, 0xff, CC_GLBL_MASK_SIZE * sizeof(uint8_t));
+
+ err = CheckAndSetManipParamsWithCcNodeParams(p_CcNode);
+ if (err != E_OK)
+ {
+ DeleteNode(p_CcNode);
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("keySize has to be equal to sizeOfExtraction"));
+ }
+
+ /* Calculating matching table entry size by rounding up the user-defined size of extraction to valid entry size */
+ GetCcExtractKeySize(p_CcNode->sizeOfExtraction, &p_CcNode->ccKeySizeAccExtraction);
+
+ /* If local mask is used, it is stored next to each key in the keys match table */
+ if (p_CcNode->lclMask)
+ keySize = (uint32_t)(2 * p_CcNode->ccKeySizeAccExtraction);
+ else
+ keySize = p_CcNode->ccKeySizeAccExtraction;
+
+ /* Update CC shadow with maximal size required by this node */
+ if (p_CcNode->maxNumOfKeys)
+ {
+ err = CalcAndUpdateCcShadow(p_CcNode,
+ isKeyTblAlloc,
+ &matchTableSize,
+ &adTableSize);
+ if (err != E_OK)
+ {
+ DeleteNode(p_CcNode);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ p_CcNode->keysMatchTableMaxSize = matchTableSize;
+
+ if (p_CcNode->statisticsMode != e_FM_PCD_CC_STATS_MODE_NONE)
+ {
+ err = AllocStatsObjs(p_CcNode);
+ if (err != E_OK)
+ {
+ DeleteNode(p_CcNode);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ }
+
+ /* If manipulation will be initialized before this node, it will use the table
+ descriptor in the AD table of previous node and this node will need an extra
+ AD as his table descriptor. */
+ p_CcNode->h_TmpAd = (t_Handle)FM_MURAM_AllocMem(h_FmMuram,
+ FM_PCD_CC_AD_ENTRY_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!p_CcNode->h_TmpAd)
+ {
+ DeleteNode(p_CcNode);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC action descriptor"));
+ }
+ }
+ else
+ {
+ matchTableSize = (uint32_t)(keySize * sizeof(uint8_t) * (p_CcNode->numOfKeys + 1));
+ adTableSize = (uint32_t)(FM_PCD_CC_AD_ENTRY_SIZE * (p_CcNode->numOfKeys + 1));
+ }
+
+#if (DPAA_VERSION >= 11)
+ switch (p_CcNode->statisticsMode)
+ {
+
+ case e_FM_PCD_CC_STATS_MODE_RMON:
+ /* If RMON statistics or RMON conditional statistics modes are requested,
+ allocate frame length ranges array */
+ p_CcNode->h_StatsFLRs =
+ FM_MURAM_AllocMem(h_FmMuram,
+ (uint32_t)(p_CcNode->numOfStatsFLRs) * FM_PCD_CC_STATS_FLR_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+
+ if (!p_CcNode->h_StatsFLRs)
+ {
+ DeleteNode(p_CcNode);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC frame length ranges array"));
+ }
+
+ /* Initialize using value received from the user */
+ for (tmp = 0; tmp < p_CcNode->numOfStatsFLRs; tmp++)
+ {
+ h_StatsFLRs = PTR_MOVE(p_CcNode->h_StatsFLRs, tmp * FM_PCD_CC_STATS_FLR_SIZE);
+
+ Mem2IOCpy32(h_StatsFLRs,
+ &(p_CcNodeParam->keysParams.frameLengthRanges[tmp]),
+ FM_PCD_CC_STATS_FLR_SIZE);
+ }
+ break;
+
+ default:
+ break;
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+
+ /* Allocate keys match table. Not required for some CC nodes, for example for IPv4 TTL
+ identification, IPv6 hop count identification, etc. */
+ if (isKeyTblAlloc)
+ {
+ p_CcNode->h_KeysMatchTable =
+ (t_Handle)FM_MURAM_AllocMem(h_FmMuram,
+ matchTableSize,
+ FM_PCD_CC_KEYS_MATCH_TABLE_ALIGN);
+ if (!p_CcNode->h_KeysMatchTable)
+ {
+ DeleteNode(p_CcNode);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node key match table"));
+ }
+ IOMemSet32((uint8_t *)p_CcNode->h_KeysMatchTable,
+ 0,
+ matchTableSize);
+ }
+
+ /* Allocate action descriptors table */
+ p_CcNode->h_AdTable =
+ (t_Handle)FM_MURAM_AllocMem(h_FmMuram,
+ adTableSize,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!p_CcNode->h_AdTable)
+ {
+ DeleteNode(p_CcNode);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC node action descriptors table"));
+ }
+ IOMemSet32((uint8_t *)p_CcNode->h_AdTable, 0, adTableSize);
+
+ p_KeysMatchTblTmp = p_CcNode->h_KeysMatchTable;
+ p_AdTableTmp = p_CcNode->h_AdTable;
+
+ /* For each key, create the key and the next step AD */
+ for (tmp = 0; tmp < p_CcNode->numOfKeys; tmp++)
+ {
+ p_KeyParams = &p_CcNodeParam->keysParams.keyParams[tmp];
+
+ if (p_KeysMatchTblTmp)
+ {
+ /* Copy the key */
+ Mem2IOCpy32((void*)p_KeysMatchTblTmp, p_KeyParams->p_Key, p_CcNode->sizeOfExtraction);
+
+ /* Copy the key mask or initialize it to 0xFF..F */
+ if (p_CcNode->lclMask && p_KeyParams->p_Mask)
+ {
+ Mem2IOCpy32(PTR_MOVE(p_KeysMatchTblTmp,
+ p_CcNode->ccKeySizeAccExtraction), /* User's size of extraction rounded up to a valid matching table entry size */
+ p_KeyParams->p_Mask,
+ p_CcNode->sizeOfExtraction); /* Exact size of extraction as received from the user */
+ }
+ else if (p_CcNode->lclMask)
+ {
+ IOMemSet32(PTR_MOVE(p_KeysMatchTblTmp,
+ p_CcNode->ccKeySizeAccExtraction), /* User's size of extraction rounded up to a valid matching table entry size */
+ 0xff,
+ p_CcNode->sizeOfExtraction); /* Exact size of extraction as received from the user */
+ }
+
+ p_KeysMatchTblTmp = PTR_MOVE(p_KeysMatchTblTmp, keySize * sizeof(uint8_t));
+ }
+
+ /* Create the next action descriptor in the match table */
+ if (p_KeyParams->ccNextEngineParams.statisticsEn)
+ {
+ p_StatsObj = GetStatsObj(p_CcNode);
+ ASSERT_COND(p_StatsObj);
+
+ statsParams.h_StatsAd = p_StatsObj->h_StatsAd;
+ statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters;
+#if (DPAA_VERSION >= 11)
+ statsParams.h_StatsFLRs = p_CcNode->h_StatsFLRs;
+
+#endif /* (DPAA_VERSION >= 11) */
+ NextStepAd(p_AdTableTmp,
+ &statsParams,
+ &p_KeyParams->ccNextEngineParams,
+ p_FmPcd);
+
+ p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = p_StatsObj;
+ }
+ else
+ {
+ NextStepAd(p_AdTableTmp,
+ NULL,
+ &p_KeyParams->ccNextEngineParams,
+ p_FmPcd);
+
+ p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = NULL;
+ }
+
+ p_AdTableTmp = PTR_MOVE(p_AdTableTmp, FM_PCD_CC_AD_ENTRY_SIZE);
+ }
+
+ /* Update next engine for the 'miss' entry */
+ if (p_CcNodeParam->keysParams.ccNextEngineParamsForMiss.statisticsEn)
+ {
+ p_StatsObj = GetStatsObj(p_CcNode);
+ ASSERT_COND(p_StatsObj);
+
+ /* All 'bucket' nodes of a hash table should share the same statistics counters,
+ allocated by the hash table. So, if this node is a bucket of a hash table,
+ we'll replace the locally allocated counters with the shared counters. */
+ if (p_CcNode->isHashBucket)
+ {
+ ASSERT_COND(p_CcNode->h_MissStatsCounters);
+
+ /* Store original counters pointer and replace it with mutual preallocated pointer */
+ p_CcNode->h_PrivMissStatsCounters = p_StatsObj->h_StatsCounters;
+ p_StatsObj->h_StatsCounters = p_CcNode->h_MissStatsCounters;
+ }
+
+ statsParams.h_StatsAd = p_StatsObj->h_StatsAd;
+ statsParams.h_StatsCounters = p_StatsObj->h_StatsCounters;
+#if (DPAA_VERSION >= 11)
+ statsParams.h_StatsFLRs = p_CcNode->h_StatsFLRs;
+
+#endif /* (DPAA_VERSION >= 11) */
+
+ NextStepAd(p_AdTableTmp,
+ &statsParams,
+ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss,
+ p_FmPcd);
+
+ p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = p_StatsObj;
+ }
+ else
+ {
+ NextStepAd(p_AdTableTmp,
+ NULL,
+ &p_CcNodeParam->keysParams.ccNextEngineParamsForMiss,
+ p_FmPcd);
+
+ p_CcNode->keyAndNextEngineParams[tmp].p_StatsObj = NULL;
+ }
+
+ /* This parameter will be used to initialize the "key length" field in the action descriptor
+ that points to this node and it should be 0 for full field extraction */
+ if (fullField == TRUE)
+ p_CcNode->sizeOfExtraction = 0;
+
+ for (tmp = 0; tmp < MIN(p_CcNode->numOfKeys + 1, CC_MAX_NUM_OF_KEYS); tmp++)
+ {
+ if (p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ {
+ p_FmPcdCcNextNode = (t_FmPcdCcNode*)p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.params.ccParams.h_CcNode;
+ p_CcInformation = FindNodeInfoInReleventLst(&p_FmPcdCcNextNode->ccPrevNodesLst,
+ (t_Handle)p_CcNode,
+ p_FmPcdCcNextNode->h_Spinlock);
+ if (!p_CcInformation)
+ {
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ ccNodeInfo.h_CcNode = (t_Handle)p_CcNode;
+ ccNodeInfo.index = 1;
+ EnqueueNodeInfoToRelevantLst(&p_FmPcdCcNextNode->ccPrevNodesLst,
+ &ccNodeInfo,
+ p_FmPcdCcNextNode->h_Spinlock);
+ }
+ else
+ p_CcInformation->index++;
+
+ if (p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip)
+ {
+ h_Manip = p_CcNode->keyAndNextEngineParams[tmp].nextEngineParams.h_Manip;
+ p_CcInformation = FindNodeInfoInReleventLst(FmPcdManipGetNodeLstPointedOnThisManip(h_Manip),
+ (t_Handle)p_CcNode,
+ FmPcdManipGetSpinlock(h_Manip));
+ if (!p_CcInformation)
+ {
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ ccNodeInfo.h_CcNode = (t_Handle)p_CcNode;
+ ccNodeInfo.index = 1;
+ EnqueueNodeInfoToRelevantLst(FmPcdManipGetNodeLstPointedOnThisManip(h_Manip),
+ &ccNodeInfo,
+ FmPcdManipGetSpinlock(h_Manip));
+ }
+ else
+ p_CcInformation->index++;
+ }
+ }
+ }
+
+ p_AdTableTmp = p_CcNode->h_AdTable;
+
+ if (!FmPcdLockTryLockAll(h_FmPcd))
+ {
+ FM_PCD_MatchTableDelete((t_Handle)p_CcNode);
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ /* Required action for each next engine */
+ for (tmp = 0; tmp < MIN(p_CcNode->numOfKeys + 1, CC_MAX_NUM_OF_KEYS); tmp++)
+ {
+ if (p_CcNode->keyAndNextEngineParams[tmp].requiredAction)
+ {
+ err = SetRequiredAction(h_FmPcd,
+ p_CcNode->keyAndNextEngineParams[tmp].requiredAction,
+ &p_CcNode->keyAndNextEngineParams[tmp],
+ p_AdTableTmp,
+ 1,
+ NULL);
+ if (err)
+ {
+ FmPcdLockUnlockAll(h_FmPcd);
+ FM_PCD_MatchTableDelete((t_Handle)p_CcNode);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ p_AdTableTmp = PTR_MOVE(p_AdTableTmp, FM_PCD_CC_AD_ENTRY_SIZE);
+ }
+ }
+
+ FmPcdLockUnlockAll(h_FmPcd);
+
+ return E_OK;
+}
+/************************** End of static functions **************************/
+
+
+/*****************************************************************************/
+/* Inter-module API routines */
+/*****************************************************************************/
+
+t_CcNodeInformation* FindNodeInfoInReleventLst(t_List *p_List, t_Handle h_Info, t_Handle h_Spinlock)
+{
+ t_CcNodeInformation *p_CcInformation;
+ t_List *p_Pos;
+ uint32_t intFlags;
+
+ intFlags = XX_LockIntrSpinlock(h_Spinlock);
+
+ for (p_Pos = LIST_FIRST(p_List); p_Pos != (p_List); p_Pos = LIST_NEXT(p_Pos))
+ {
+ p_CcInformation = CC_NODE_F_OBJECT(p_Pos);
+
+ ASSERT_COND(p_CcInformation->h_CcNode);
+
+ if (p_CcInformation->h_CcNode == h_Info)
+ {
+ XX_UnlockIntrSpinlock(h_Spinlock, intFlags);
+ return p_CcInformation;
+ }
+ }
+
+ XX_UnlockIntrSpinlock(h_Spinlock, intFlags);
+
+ return NULL;
+}
+
+void EnqueueNodeInfoToRelevantLst(t_List *p_List, t_CcNodeInformation *p_CcInfo, t_Handle h_Spinlock)
+{
+ t_CcNodeInformation *p_CcInformation;
+ uint32_t intFlags = 0;
+
+ p_CcInformation = (t_CcNodeInformation *)XX_Malloc(sizeof(t_CcNodeInformation));
+
+ if (p_CcInformation)
+ {
+ memset(p_CcInformation, 0, sizeof(t_CcNodeInformation));
+ memcpy(p_CcInformation, p_CcInfo, sizeof(t_CcNodeInformation));
+ INIT_LIST(&p_CcInformation->node);
+
+ if (h_Spinlock)
+ intFlags = XX_LockIntrSpinlock(h_Spinlock);
+
+ LIST_AddToTail(&p_CcInformation->node, p_List);
+
+ if (h_Spinlock)
+ XX_UnlockIntrSpinlock(h_Spinlock, intFlags);
+ }
+ else
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("CC Node Information"));
+}
+
+void DequeueNodeInfoFromRelevantLst(t_List *p_List, t_Handle h_Info, t_Handle h_Spinlock)
+{
+ t_CcNodeInformation *p_CcInformation = NULL;
+ uint32_t intFlags = 0;
+ t_List *p_Pos;
+
+ if (h_Spinlock)
+ intFlags = XX_LockIntrSpinlock(h_Spinlock);
+
+ if (LIST_IsEmpty(p_List))
+ {
+ XX_RestoreAllIntr(intFlags);
+ return;
+ }
+
+ for (p_Pos = LIST_FIRST(p_List); p_Pos != (p_List); p_Pos = LIST_NEXT(p_Pos))
+ {
+ p_CcInformation = CC_NODE_F_OBJECT(p_Pos);
+ ASSERT_COND(p_CcInformation);
+ ASSERT_COND(p_CcInformation->h_CcNode);
+ if (p_CcInformation->h_CcNode == h_Info)
+ break;
+ }
+
+ if (p_CcInformation)
+ {
+ LIST_DelAndInit(&p_CcInformation->node);
+ XX_Free(p_CcInformation);
+ }
+
+ if (h_Spinlock)
+ XX_UnlockIntrSpinlock(h_Spinlock, intFlags);
+}
+
+void NextStepAd(t_Handle h_Ad,
+ t_FmPcdCcStatsParams *p_FmPcdCcStatsParams,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams,
+ t_FmPcd *p_FmPcd)
+{
+ switch (p_FmPcdCcNextEngineParams->nextEngine)
+ {
+ case (e_FM_PCD_KG):
+ case (e_FM_PCD_PLCR):
+ case (e_FM_PCD_DONE):
+ /* if NIA is not CC, create a "result" type AD */
+ FillAdOfTypeResult(h_Ad,
+ p_FmPcdCcStatsParams,
+ p_FmPcd,
+ p_FmPcdCcNextEngineParams);
+ break;
+#if (DPAA_VERSION >= 11)
+ case (e_FM_PCD_FR):
+ if (p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic)
+ {
+ FillAdOfTypeContLookup(h_Ad,
+ p_FmPcdCcStatsParams,
+ p_FmPcd,
+ p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode,
+ p_FmPcdCcNextEngineParams->h_Manip,
+ p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic);
+ FrmReplicGroupUpdateOwner(p_FmPcdCcNextEngineParams->params.frParams.h_FrmReplic,
+ TRUE/* add */);
+ }
+ break;
+#endif /* (DPAA_VERSION >= 11) */
+
+ case (e_FM_PCD_CC):
+ /* if NIA is not CC, create a TD to continue the CC lookup */
+ FillAdOfTypeContLookup(h_Ad,
+ p_FmPcdCcStatsParams,
+ p_FmPcd,
+ p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode,
+ p_FmPcdCcNextEngineParams->h_Manip,
+ NULL);
+
+ UpdateNodeOwner(p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode, TRUE);
+ break;
+
+ default:
+ return;
+ }
+}
+
+t_Error FmPcdCcTreeAddIPR(t_Handle h_FmPcd,
+ t_Handle h_FmTree,
+ t_Handle h_NetEnv,
+ t_Handle h_IpReassemblyManip,
+ bool createSchemes)
+{
+ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmTree;
+ t_FmPcdCcNextEngineParams nextEngineParams;
+ t_NetEnvParams netEnvParams;
+ t_Handle h_Ad;
+ bool isIpv6Present;
+ uint8_t ipv4GroupId, ipv6GroupId;
+ t_Error err;
+
+ ASSERT_COND(p_FmPcdCcTree);
+
+ /* this routine must be protected by the calling routine! */
+
+ memset(&nextEngineParams, 0, sizeof(t_FmPcdCcNextEngineParams));
+ memset(&netEnvParams, 0, sizeof(t_NetEnvParams));
+
+ h_Ad = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr);
+
+ isIpv6Present = FmPcdManipIpReassmIsIpv6Hdr(h_IpReassemblyManip);
+
+ if (isIpv6Present && (p_FmPcdCcTree->numOfEntries > (FM_PCD_MAX_NUM_OF_CC_GROUPS-2)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("need two free entries for IPR"));
+
+ if (p_FmPcdCcTree->numOfEntries > (FM_PCD_MAX_NUM_OF_CC_GROUPS-1))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("need two free entries for IPR"));
+
+ nextEngineParams.nextEngine = e_FM_PCD_DONE;
+ nextEngineParams.h_Manip = h_IpReassemblyManip;
+
+ /* Lock tree */
+ err = CcRootTryLock(p_FmPcdCcTree);
+ if (err)
+ return ERROR_CODE(E_BUSY);
+
+ if (p_FmPcdCcTree->h_IpReassemblyManip == h_IpReassemblyManip)
+ {
+ CcRootReleaseLock(p_FmPcdCcTree);
+ return E_OK;
+ }
+
+ if ((p_FmPcdCcTree->h_IpReassemblyManip) &&
+ (p_FmPcdCcTree->h_IpReassemblyManip != h_IpReassemblyManip))
+ {
+ CcRootReleaseLock(p_FmPcdCcTree);
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("This tree was previously updated with different IPR"));
+ }
+
+ /* Initialize IPR for the first time for this tree */
+ if (isIpv6Present)
+ {
+ ipv6GroupId = p_FmPcdCcTree->numOfGrps++;
+ p_FmPcdCcTree->fmPcdGroupParam[ipv6GroupId].baseGroupEntry = (FM_PCD_MAX_NUM_OF_CC_GROUPS-2);
+
+ if (createSchemes)
+ {
+ err = FmPcdManipBuildIpReassmScheme(h_FmPcd, h_NetEnv, p_FmPcdCcTree, h_IpReassemblyManip, FALSE, ipv6GroupId);
+ if (err)
+ {
+ p_FmPcdCcTree->numOfGrps--;
+ CcRootReleaseLock(p_FmPcdCcTree);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ }
+
+ NextStepAd(PTR_MOVE(h_Ad, (FM_PCD_MAX_NUM_OF_CC_GROUPS-2) * FM_PCD_CC_AD_ENTRY_SIZE),
+ NULL,
+ &nextEngineParams,
+ h_FmPcd);
+ }
+
+ ipv4GroupId = p_FmPcdCcTree->numOfGrps++;
+ p_FmPcdCcTree->fmPcdGroupParam[ipv4GroupId].totalBitsMask = 0;
+ p_FmPcdCcTree->fmPcdGroupParam[ipv4GroupId].baseGroupEntry = (FM_PCD_MAX_NUM_OF_CC_GROUPS-1);
+
+ if (createSchemes)
+ {
+ err = FmPcdManipBuildIpReassmScheme(h_FmPcd, h_NetEnv, p_FmPcdCcTree, h_IpReassemblyManip, TRUE, ipv4GroupId);
+ if (err)
+ {
+ p_FmPcdCcTree->numOfGrps--;
+ if (isIpv6Present)
+ {
+ p_FmPcdCcTree->numOfGrps--;
+ FmPcdManipDeleteIpReassmSchemes(h_IpReassemblyManip);
+ }
+ CcRootReleaseLock(p_FmPcdCcTree);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ }
+
+ NextStepAd(PTR_MOVE(h_Ad, (FM_PCD_MAX_NUM_OF_CC_GROUPS-1) * FM_PCD_CC_AD_ENTRY_SIZE),
+ NULL,
+ &nextEngineParams,
+ h_FmPcd);
+
+ p_FmPcdCcTree->h_IpReassemblyManip = h_IpReassemblyManip;
+
+ CcRootReleaseLock(p_FmPcdCcTree);
+
+ return E_OK;
+}
+
+t_Handle FmPcdCcTreeGetSavedManipParams(t_Handle h_FmTree)
+{
+ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmTree;
+
+ ASSERT_COND(p_FmPcdCcTree);
+
+ return p_FmPcdCcTree->h_FmPcdCcSavedManipParams;
+}
+
+void FmPcdCcTreeSetSavedManipParams(t_Handle h_FmTree, t_Handle h_SavedManipParams)
+{
+ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmTree;
+
+ ASSERT_COND(p_FmPcdCcTree);
+
+ p_FmPcdCcTree->h_FmPcdCcSavedManipParams = h_SavedManipParams;
+}
+
+uint8_t FmPcdCcGetParseCode(t_Handle h_CcNode)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+
+ ASSERT_COND(p_CcNode);
+
+ return p_CcNode->parseCode;
+}
+
+uint8_t FmPcdCcGetOffset(t_Handle h_CcNode)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+
+ ASSERT_COND(p_CcNode);
+
+ return p_CcNode->offset;
+}
+
+uint16_t FmPcdCcGetNumOfKeys(t_Handle h_CcNode)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+
+ ASSERT_COND(p_CcNode);
+
+ return p_CcNode->numOfKeys;
+}
+
+t_Error FmPcdCcModifyNextEngineParamTree(t_Handle h_FmPcd,
+ t_Handle h_FmPcdCcTree,
+ uint8_t grpId,
+ uint8_t index,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree;
+ t_FmPcd *p_FmPcd;
+ t_List h_OldPointersLst, h_NewPointersLst;
+ uint16_t keyIndex;
+ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(h_FmPcdCcTree,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((grpId <= 7),E_INVALID_VALUE);
+
+ if (grpId >= p_FmPcdCcTree->numOfGrps)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("grpId you asked > numOfGroup of relevant tree"));
+
+ if (index >= p_FmPcdCcTree->fmPcdGroupParam[grpId].numOfEntriesInGroup)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("index > numOfEntriesInGroup"));
+
+ p_FmPcd = (t_FmPcd *)h_FmPcd;
+
+ INIT_LIST(&h_OldPointersLst);
+ INIT_LIST(&h_NewPointersLst);
+
+ keyIndex = (uint16_t)(p_FmPcdCcTree->fmPcdGroupParam[grpId].baseGroupEntry + index);
+
+ p_ModifyKeyParams = ModifyNodeCommonPart(p_FmPcdCcTree, keyIndex, e_MODIFY_STATE_CHANGE, FALSE, FALSE, TRUE);
+ if (!p_ModifyKeyParams)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ p_ModifyKeyParams->tree = TRUE;
+
+ if (p_FmPcd->p_CcShadow &&
+ !TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
+ {
+ XX_Free(p_ModifyKeyParams);
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = BuildNewNodeModifyNextEngine(p_FmPcd,
+ p_FmPcdCcTree,
+ keyIndex,
+ p_FmPcdCcNextEngineParams,
+ &h_OldPointersLst,
+ &h_NewPointersLst,
+ p_ModifyKeyParams);
+ if (err)
+ {
+ XX_Free(p_ModifyKeyParams);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = DoDynamicChange(p_FmPcd, &h_OldPointersLst, &h_NewPointersLst, p_ModifyKeyParams, FALSE);
+
+ if (p_FmPcd->p_CcShadow)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+
+ return err;
+
+}
+
+t_Error FmPcdCcRemoveKey(t_Handle h_FmPcd,
+ t_Handle h_FmPcdCcNode,
+ uint16_t keyIndex)
+{
+
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *) h_FmPcdCcNode;
+ t_FmPcd *p_FmPcd;
+ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams;
+ t_List h_OldPointersLst, h_NewPointersLst;
+ bool useShadowStructs = FALSE;
+ t_Error err = E_OK;
+
+ if (keyIndex >= p_CcNode->numOfKeys)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("impossible to remove key when numOfKeys <= keyIndex"));
+
+ if (!p_CcNode->numOfKeys)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("keyIndex you asked > numOfKeys of relevant node that was initialized"));
+
+ if (p_CcNode->h_FmPcd != h_FmPcd)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("handler to FmPcd is different from the handle provided at node initialization time"));
+
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+
+ INIT_LIST(&h_OldPointersLst);
+ INIT_LIST(&h_NewPointersLst);
+
+ p_ModifyKeyParams = ModifyNodeCommonPart(p_CcNode, keyIndex, e_MODIFY_STATE_REMOVE, TRUE, TRUE, FALSE);
+ if (!p_ModifyKeyParams)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ if (p_CcNode->maxNumOfKeys)
+ {
+ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
+ {
+ XX_Free(p_ModifyKeyParams);
+ return ERROR_CODE(E_BUSY);
+ }
+
+ useShadowStructs = TRUE;
+ }
+
+ err = BuildNewNodeRemoveKey(p_CcNode, keyIndex, p_ModifyKeyParams);
+ if (err)
+ {
+ XX_Free(p_ModifyKeyParams);
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = UpdatePtrWhichPointOnCrntMdfNode(p_CcNode,
+ p_ModifyKeyParams,
+ &h_OldPointersLst,
+ &h_NewPointersLst);
+ if (err)
+ {
+ ReleaseNewNodeCommonPart(p_ModifyKeyParams);
+ XX_Free(p_ModifyKeyParams);
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = DoDynamicChange(p_FmPcd,
+ &h_OldPointersLst,
+ &h_NewPointersLst,
+ p_ModifyKeyParams,
+ useShadowStructs);
+
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+
+ return err;
+}
+
+t_Error FmPcdCcModifyKey(t_Handle h_FmPcd,
+ t_Handle h_FmPcdCcNode,
+ uint16_t keyIndex,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t *p_Mask)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode;
+ t_FmPcd *p_FmPcd;
+ t_List h_OldPointersLst, h_NewPointersLst;
+ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams;
+ uint16_t tmpKeyIndex;
+ bool useShadowStructs = FALSE;
+ t_Error err = E_OK;
+
+ if (keyIndex >= p_CcNode->numOfKeys)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("keyIndex > previously cleared last index + 1"));
+
+ if (keySize != p_CcNode->userSizeOfExtraction)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("size for ModifyKey has to be the same as defined in SetNode"));
+
+ if (p_CcNode->h_FmPcd != h_FmPcd)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("handler to FmPcd is different from the handle provided at node initialization time"));
+
+ err = FindKeyIndex(h_FmPcdCcNode,
+ keySize,
+ p_Key,
+ p_Mask,
+ &tmpKeyIndex);
+ if (GET_ERROR_TYPE(err) != E_NOT_FOUND)
+ RETURN_ERROR(MINOR, E_ALREADY_EXISTS,
+ ("The received key and mask pair was already found in the match table of the provided node"));
+
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+
+ INIT_LIST(&h_OldPointersLst);
+ INIT_LIST(&h_NewPointersLst);
+
+ p_ModifyKeyParams = ModifyNodeCommonPart(p_CcNode, keyIndex, e_MODIFY_STATE_CHANGE, TRUE, TRUE, FALSE);
+ if (!p_ModifyKeyParams)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ if (p_CcNode->maxNumOfKeys)
+ {
+ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
+ {
+ XX_Free(p_ModifyKeyParams);
+ return ERROR_CODE(E_BUSY);
+ }
+
+ useShadowStructs = TRUE;
+ }
+
+ err = BuildNewNodeModifyKey(p_CcNode,
+ keyIndex,
+ p_Key,
+ p_Mask,
+ p_ModifyKeyParams);
+ if (err)
+ {
+ XX_Free(p_ModifyKeyParams);
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = UpdatePtrWhichPointOnCrntMdfNode(p_CcNode,
+ p_ModifyKeyParams,
+ &h_OldPointersLst,
+ &h_NewPointersLst);
+ if (err)
+ {
+ ReleaseNewNodeCommonPart(p_ModifyKeyParams);
+ XX_Free(p_ModifyKeyParams);
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = DoDynamicChange(p_FmPcd,
+ &h_OldPointersLst,
+ &h_NewPointersLst,
+ p_ModifyKeyParams,
+ useShadowStructs);
+
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+
+ return err;
+}
+
+t_Error FmPcdCcModifyMissNextEngineParamNode(t_Handle h_FmPcd,
+ t_Handle h_FmPcdCcNode,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode;
+ t_FmPcd *p_FmPcd;
+ t_List h_OldPointersLst, h_NewPointersLst;
+ uint16_t keyIndex;
+ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(p_CcNode,E_INVALID_VALUE);
+
+ keyIndex = p_CcNode->numOfKeys;
+
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+
+ INIT_LIST(&h_OldPointersLst);
+ INIT_LIST(&h_NewPointersLst);
+
+ p_ModifyKeyParams = ModifyNodeCommonPart(p_CcNode, keyIndex, e_MODIFY_STATE_CHANGE, FALSE, TRUE, FALSE);
+ if (!p_ModifyKeyParams)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ if (p_CcNode->maxNumOfKeys &&
+ !TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
+ {
+ XX_Free(p_ModifyKeyParams);
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = BuildNewNodeModifyNextEngine(h_FmPcd,
+ p_CcNode,
+ keyIndex,
+ p_FmPcdCcNextEngineParams,
+ &h_OldPointersLst,
+ &h_NewPointersLst,
+ p_ModifyKeyParams);
+ if (err)
+ {
+ XX_Free(p_ModifyKeyParams);
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = DoDynamicChange(p_FmPcd, &h_OldPointersLst, &h_NewPointersLst, p_ModifyKeyParams, FALSE);
+
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+
+ return err;
+}
+
+t_Error FmPcdCcAddKey(t_Handle h_FmPcd,
+ t_Handle h_FmPcdCcNode,
+ uint16_t keyIndex,
+ uint8_t keySize,
+ t_FmPcdCcKeyParams *p_FmPcdCcKeyParams)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode;
+ t_FmPcd *p_FmPcd;
+ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams;
+ t_List h_OldPointersLst, h_NewPointersLst;
+ bool useShadowStructs = FALSE;
+ uint16_t tmpKeyIndex;
+ t_Error err = E_OK;
+
+ if (keyIndex > p_CcNode->numOfKeys)
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ("keyIndex > previously cleared last index + 1"));
+
+ if (keySize != p_CcNode->userSizeOfExtraction)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("keySize has to be defined as it was defined in initialization step"));
+
+ if (p_CcNode->h_FmPcd != h_FmPcd)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("handler to FmPcd is different from the handle provided at node initialization time"));
+
+ if (p_CcNode->maxNumOfKeys)
+ {
+ if (p_CcNode->numOfKeys == p_CcNode->maxNumOfKeys)
+ RETURN_ERROR(MAJOR, E_FULL, ("number of keys exceeds the maximal number of keys provided at node initialization time"));
+ }
+ else if (p_CcNode->numOfKeys == FM_PCD_MAX_NUM_OF_KEYS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("number of keys can not be larger than %d", FM_PCD_MAX_NUM_OF_KEYS));
+
+ err = FindKeyIndex(h_FmPcdCcNode,
+ keySize,
+ p_FmPcdCcKeyParams->p_Key,
+ p_FmPcdCcKeyParams->p_Mask,
+ &tmpKeyIndex);
+ if (GET_ERROR_TYPE(err) != E_NOT_FOUND)
+ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS,
+ ("The received key and mask pair was already found in the match table of the provided node"));
+
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+
+ INIT_LIST(&h_OldPointersLst);
+ INIT_LIST(&h_NewPointersLst);
+
+ p_ModifyKeyParams = ModifyNodeCommonPart(p_CcNode,
+ keyIndex,
+ e_MODIFY_STATE_ADD,
+ TRUE,
+ TRUE,
+ FALSE);
+ if (!p_ModifyKeyParams)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ if (p_CcNode->maxNumOfKeys)
+ {
+ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
+ {
+ XX_Free(p_ModifyKeyParams);
+ return ERROR_CODE(E_BUSY);
+ }
+
+ useShadowStructs = TRUE;
+ }
+
+ err = BuildNewNodeAddOrMdfyKeyAndNextEngine (h_FmPcd,
+ p_CcNode,
+ keyIndex,
+ p_FmPcdCcKeyParams,
+ p_ModifyKeyParams,
+ TRUE);
+ if (err)
+ {
+ ReleaseNewNodeCommonPart(p_ModifyKeyParams);
+ XX_Free(p_ModifyKeyParams);
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = UpdatePtrWhichPointOnCrntMdfNode(p_CcNode,
+ p_ModifyKeyParams,
+ &h_OldPointersLst,
+ &h_NewPointersLst);
+ if (err)
+ {
+ ReleaseNewNodeCommonPart(p_ModifyKeyParams);
+ XX_Free(p_ModifyKeyParams);
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = DoDynamicChange(p_FmPcd,
+ &h_OldPointersLst,
+ &h_NewPointersLst,
+ p_ModifyKeyParams,
+ useShadowStructs);
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+
+ return err;
+}
+
+t_Error FmPcdCcModifyKeyAndNextEngine(t_Handle h_FmPcd,
+ t_Handle h_FmPcdCcNode,
+ uint16_t keyIndex,
+ uint8_t keySize,
+ t_FmPcdCcKeyParams *p_FmPcdCcKeyParams)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode;
+ t_FmPcd *p_FmPcd;
+ t_List h_OldPointersLst, h_NewPointersLst;
+ t_FmPcdModifyCcKeyAdditionalParams *p_ModifyKeyParams;
+ uint16_t tmpKeyIndex;
+ bool useShadowStructs = FALSE;
+ t_Error err = E_OK;
+
+ if (keyIndex > p_CcNode->numOfKeys)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("keyIndex > previously cleared last index + 1"));
+
+ if (keySize != p_CcNode->userSizeOfExtraction)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("keySize has to be defined as it was defined in initialization step"));
+
+ if (p_CcNode->h_FmPcd != h_FmPcd)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("handler to FmPcd is different from the handle provided at node initialization time"));
+
+ err = FindKeyIndex(h_FmPcdCcNode,
+ keySize,
+ p_FmPcdCcKeyParams->p_Key,
+ p_FmPcdCcKeyParams->p_Mask,
+ &tmpKeyIndex);
+ if (GET_ERROR_TYPE(err) != E_NOT_FOUND)
+ RETURN_ERROR(MINOR, E_ALREADY_EXISTS,
+ ("The received key and mask pair was already found in the match table of the provided node"));
+
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+
+ INIT_LIST(&h_OldPointersLst);
+ INIT_LIST(&h_NewPointersLst);
+
+ p_ModifyKeyParams = ModifyNodeCommonPart(p_CcNode, keyIndex, e_MODIFY_STATE_CHANGE, TRUE, TRUE, FALSE);
+ if (!p_ModifyKeyParams)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ if (p_CcNode->maxNumOfKeys)
+ {
+ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
+ {
+ XX_Free(p_ModifyKeyParams);
+ return ERROR_CODE(E_BUSY);
+ }
+
+ useShadowStructs = TRUE;
+ }
+
+ err = BuildNewNodeAddOrMdfyKeyAndNextEngine (h_FmPcd,
+ p_CcNode,
+ keyIndex,
+ p_FmPcdCcKeyParams,
+ p_ModifyKeyParams,
+ FALSE);
+ if (err)
+ {
+ ReleaseNewNodeCommonPart(p_ModifyKeyParams);
+ XX_Free(p_ModifyKeyParams);
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = UpdatePtrWhichPointOnCrntMdfNode(p_CcNode,
+ p_ModifyKeyParams,
+ &h_OldPointersLst,
+ &h_NewPointersLst);
+ if (err)
+ {
+ ReleaseNewNodeCommonPart(p_ModifyKeyParams);
+ XX_Free(p_ModifyKeyParams);
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = DoDynamicChange(p_FmPcd,
+ &h_OldPointersLst,
+ &h_NewPointersLst,
+ p_ModifyKeyParams,
+ useShadowStructs);
+
+ if (p_CcNode->maxNumOfKeys)
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+
+ return err;
+}
+
+uint32_t FmPcdCcGetNodeAddrOffsetFromNodeInfo(t_Handle h_FmPcd, t_Handle h_Pointer)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ t_CcNodeInformation *p_CcNodeInfo;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcd,E_INVALID_HANDLE, (uint32_t)ILLEGAL_BASE);
+
+ p_CcNodeInfo = CC_NODE_F_OBJECT(h_Pointer);
+
+ return (uint32_t)(XX_VirtToPhys(p_CcNodeInfo->h_CcNode) - p_FmPcd->physicalMuramBase);
+}
+
+t_Error FmPcdCcGetGrpParams(t_Handle h_FmPcdCcTree, uint8_t grpId, uint32_t *p_GrpBits, uint8_t *p_GrpBase)
+{
+ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *) h_FmPcdCcTree;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcdCcTree, E_INVALID_HANDLE);
+
+ if (grpId >= p_FmPcdCcTree->numOfGrps)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("grpId you asked > numOfGroup of relevant tree"));
+
+ *p_GrpBits = p_FmPcdCcTree->fmPcdGroupParam[grpId].totalBitsMask;
+ *p_GrpBase = p_FmPcdCcTree->fmPcdGroupParam[grpId].baseGroupEntry;
+
+ return E_OK;
+}
+
+t_Error FmPcdCcBindTree(t_Handle h_FmPcd,
+ t_Handle h_PcdParams,
+ t_Handle h_FmPcdCcTree,
+ uint32_t *p_Offset,
+ t_Handle h_FmPort)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(h_FmPcdCcTree, E_INVALID_HANDLE);
+
+ /* this routine must be protected by the calling routine by locking all PCD modules! */
+
+ err = CcUpdateParams(h_FmPcd, h_PcdParams, h_FmPort, h_FmPcdCcTree, TRUE);
+
+ if (err == E_OK)
+ UpdateCcRootOwner(p_FmPcdCcTree, TRUE);
+
+ *p_Offset = (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr)) -
+ p_FmPcd->physicalMuramBase);
+
+ return err;
+}
+
+t_Error FmPcdCcUnbindTree(t_Handle h_FmPcd, t_Handle h_FmPcdCcTree)
+{
+ t_FmPcdCcTree *p_FmPcdCcTree = (t_FmPcdCcTree *)h_FmPcdCcTree;
+
+ /* this routine must be protected by the calling routine by locking all PCD modules! */
+
+ UNUSED(h_FmPcd);
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcdCcTree,E_INVALID_HANDLE);
+
+ UpdateCcRootOwner(p_FmPcdCcTree, FALSE);
+
+ return E_OK;
+}
+
+t_Error FmPcdCcNodeTreeTryLock(t_Handle h_FmPcd,t_Handle h_FmPcdCcNode, t_List *p_List)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_FmPcdCcNode;
+ t_List *p_Pos, *p_Tmp;
+ t_CcNodeInformation *p_CcNodeInfo, nodeInfo;
+ uint32_t intFlags;
+ t_Error err = E_OK;
+
+ intFlags = FmPcdLock(h_FmPcd);
+
+ if (LIST_IsEmpty(&p_CcNode->ccTreesLst))
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("asked for more nodes in CC than MAX"));
+
+ LIST_FOR_EACH(p_Pos, &p_CcNode->ccTreesLst)
+ {
+ p_CcNodeInfo = CC_NODE_F_OBJECT(p_Pos);
+ ASSERT_COND(p_CcNodeInfo->h_CcNode);
+
+ err = CcRootTryLock(p_CcNodeInfo->h_CcNode);
+
+ if (err)
+ {
+ LIST_FOR_EACH(p_Tmp, &p_CcNode->ccTreesLst)
+ {
+ if (p_Tmp == p_Pos)
+ break;
+
+ CcRootReleaseLock(p_CcNodeInfo->h_CcNode);
+ }
+ break;
+ }
+
+ memset(&nodeInfo, 0, sizeof(t_CcNodeInformation));
+ nodeInfo.h_CcNode = p_CcNodeInfo->h_CcNode;
+ EnqueueNodeInfoToRelevantLst(p_List, &nodeInfo, NULL);
+ }
+
+ FmPcdUnlock(h_FmPcd, intFlags);
+ CORE_MemoryBarrier();
+
+ return err;
+}
+
+void FmPcdCcNodeTreeReleaseLock(t_Handle h_FmPcd, t_List *p_List)
+{
+ t_List *p_Pos;
+ t_CcNodeInformation *p_CcNodeInfo;
+ t_Handle h_FmPcdCcTree;
+ uint32_t intFlags;
+
+ intFlags = FmPcdLock(h_FmPcd);
+
+ LIST_FOR_EACH(p_Pos, p_List)
+ {
+ p_CcNodeInfo = CC_NODE_F_OBJECT(p_Pos);
+ h_FmPcdCcTree = p_CcNodeInfo->h_CcNode;
+ CcRootReleaseLock(h_FmPcdCcTree);
+ }
+
+ ReleaseLst(p_List);
+
+ FmPcdUnlock(h_FmPcd, intFlags);
+ CORE_MemoryBarrier();
+}
+
+
+t_Error FmPcdUpdateCcShadow (t_FmPcd *p_FmPcd, uint32_t size, uint32_t align)
+{
+ uint32_t intFlags;
+ uint32_t newSize = 0, newAlign = 0;
+ bool allocFail = FALSE;
+
+ ASSERT_COND(p_FmPcd);
+
+ if (!size)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("size must be larger then 0"));
+
+ if (!POWER_OF_2(align))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("alignment must be power of 2"));
+
+ newSize = p_FmPcd->ccShadowSize;
+ newAlign = p_FmPcd->ccShadowAlign;
+
+ /* Check if current shadow is large enough to hold the requested size */
+ if (size > p_FmPcd->ccShadowSize)
+ newSize = size;
+
+ /* Check if current shadow matches the requested alignment */
+ if (align > p_FmPcd->ccShadowAlign)
+ newAlign = align;
+
+ /* If a bigger shadow size or bigger shadow alignment are required,
+ a new shadow will be allocated */
+ if ((newSize != p_FmPcd->ccShadowSize) || (newAlign != p_FmPcd->ccShadowAlign))
+ {
+ intFlags = FmPcdLock(p_FmPcd);
+
+ if (p_FmPcd->p_CcShadow)
+ {
+ FM_MURAM_FreeMem(FmPcdGetMuramHandle(p_FmPcd), p_FmPcd->p_CcShadow);
+ p_FmPcd->ccShadowSize = 0;
+ p_FmPcd->ccShadowAlign = 0;
+ }
+
+ p_FmPcd->p_CcShadow = FM_MURAM_AllocMem(FmPcdGetMuramHandle(p_FmPcd),
+ newSize,
+ newAlign);
+ if (!p_FmPcd->p_CcShadow)
+ {
+ allocFail = TRUE;
+
+ /* If new shadow size allocation failed,
+ re-allocate with previous parameters */
+ p_FmPcd->p_CcShadow = FM_MURAM_AllocMem(FmPcdGetMuramHandle(p_FmPcd),
+ p_FmPcd->ccShadowSize,
+ p_FmPcd->ccShadowAlign);
+ }
+
+ FmPcdUnlock(p_FmPcd, intFlags);
+
+ if (allocFail)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC Shadow memory"));
+
+ p_FmPcd->ccShadowSize = newSize;
+ p_FmPcd->ccShadowAlign = newAlign;
+ }
+
+ return E_OK;
+}
+
+#if (DPAA_VERSION >= 11)
+void FmPcdCcGetAdTablesThatPointOnReplicGroup(t_Handle h_Node,
+ t_Handle h_ReplicGroup,
+ t_List *p_AdTables,
+ uint32_t *p_NumOfAdTables)
+{
+ t_FmPcdCcNode *p_CurrentNode = (t_FmPcdCcNode *)h_Node;
+ int i = 0;
+ void * p_AdTable;
+ t_CcNodeInformation ccNodeInfo;
+
+ ASSERT_COND(h_Node);
+ *p_NumOfAdTables = 0;
+
+ /* search in the current node which exact index points on this current replicator group for getting AD */
+ for (i = 0; i < p_CurrentNode->numOfKeys + 1; i++)
+ {
+ if ((p_CurrentNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_FR) &&
+ ((p_CurrentNode->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic == (t_Handle)h_ReplicGroup)))
+ {
+ /* save the current ad table in the list */
+ /* this entry uses the input replicator group */
+ p_AdTable = PTR_MOVE(p_CurrentNode->h_AdTable, i*FM_PCD_CC_AD_ENTRY_SIZE);
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ ccNodeInfo.h_CcNode = p_AdTable;
+ EnqueueNodeInfoToRelevantLst(p_AdTables, &ccNodeInfo, NULL);
+ (*p_NumOfAdTables)++;
+ }
+ }
+
+ ASSERT_COND(i != p_CurrentNode->numOfKeys);
+}
+#endif /* (DPAA_VERSION >= 11) */
+/*********************** End of inter-module routines ************************/
+
+
+/****************************************/
+/* API Init unit functions */
+/****************************************/
+
+t_Handle FM_PCD_CcRootBuild(t_Handle h_FmPcd, t_FmPcdCcTreeParams *p_PcdGroupsParam)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ t_Error err = E_OK;
+ int i = 0, j = 0, k = 0;
+ t_FmPcdCcTree *p_FmPcdCcTree;
+ uint8_t numOfEntries;
+ t_Handle p_CcTreeTmp;
+ t_FmPcdCcGrpParams *p_FmPcdCcGroupParams;
+ t_FmPcdCcKeyAndNextEngineParams *p_Params, *p_KeyAndNextEngineParams;
+ t_NetEnvParams netEnvParams;
+ uint8_t lastOne = 0;
+ uint32_t requiredAction = 0;
+ t_FmPcdCcNode *p_FmPcdCcNextNode;
+ t_CcNodeInformation ccNodeInfo, *p_CcInformation;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcd,E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(p_PcdGroupsParam,E_INVALID_HANDLE, NULL);
+
+ if (p_PcdGroupsParam->numOfGrps > FM_PCD_MAX_NUM_OF_CC_GROUPS)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("numOfGrps should not exceed %d", FM_PCD_MAX_NUM_OF_CC_GROUPS));
+ return NULL;
+ }
+
+ p_FmPcdCcTree = (t_FmPcdCcTree*)XX_Malloc(sizeof(t_FmPcdCcTree));
+ if (!p_FmPcdCcTree)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("PCD tree structure"));
+ return NULL;
+ }
+ memset(p_FmPcdCcTree, 0, sizeof(t_FmPcdCcTree));
+ p_FmPcdCcTree->h_FmPcd = h_FmPcd;
+
+ p_Params = (t_FmPcdCcKeyAndNextEngineParams*)XX_Malloc(FM_PCD_MAX_NUM_OF_CC_GROUPS * sizeof(t_FmPcdCcKeyAndNextEngineParams));
+ memset(p_Params, 0, FM_PCD_MAX_NUM_OF_CC_GROUPS * sizeof(t_FmPcdCcKeyAndNextEngineParams));
+
+ INIT_LIST(&p_FmPcdCcTree->fmPortsLst);
+
+#ifdef FM_CAPWAP_SUPPORT
+ if ((p_PcdGroupsParam->numOfGrps == 1) &&
+ (p_PcdGroupsParam->ccGrpParams[0].numOfDistinctionUnits == 0) &&
+ (p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].nextEngine == e_FM_PCD_CC) &&
+ p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].params.ccParams.h_CcNode &&
+ IsCapwapApplSpecific(p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].params.ccParams.h_CcNode))
+ {
+ p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].h_Manip = FmPcdManipApplSpecificBuild();
+ if (!p_PcdGroupsParam->ccGrpParams[0].nextEnginePerEntriesInGrp[0].h_Manip)
+ {
+ DeleteTree(p_FmPcdCcTree,p_FmPcd);
+ XX_Free(p_Params);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+ return NULL;
+ }
+ }
+#endif /* FM_CAPWAP_SUPPORT */
+
+ numOfEntries = 0;
+ p_FmPcdCcTree->netEnvId = FmPcdGetNetEnvId(p_PcdGroupsParam->h_NetEnv);
+
+ for (i = 0; i < p_PcdGroupsParam->numOfGrps; i++)
+ {
+ p_FmPcdCcGroupParams = &p_PcdGroupsParam->ccGrpParams[i];
+
+ if (p_FmPcdCcGroupParams->numOfDistinctionUnits > FM_PCD_MAX_NUM_OF_CC_UNITS)
+ {
+ DeleteTree(p_FmPcdCcTree,p_FmPcd);
+ XX_Free(p_Params);
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("numOfDistinctionUnits (group %d) should not exceed %d", i, FM_PCD_MAX_NUM_OF_CC_UNITS));
+ return NULL;
+ }
+
+ p_FmPcdCcTree->fmPcdGroupParam[i].baseGroupEntry = numOfEntries;
+ p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup =(uint8_t)( 0x01 << p_FmPcdCcGroupParams->numOfDistinctionUnits);
+ numOfEntries += p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup;
+ if (numOfEntries > FM_PCD_MAX_NUM_OF_CC_GROUPS)
+ {
+ DeleteTree(p_FmPcdCcTree,p_FmPcd);
+ XX_Free(p_Params);
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("numOfEntries can not be larger than %d", FM_PCD_MAX_NUM_OF_CC_GROUPS));
+ return NULL;
+ }
+
+ if (lastOne)
+ {
+ if (p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup > lastOne)
+ {
+ DeleteTree(p_FmPcdCcTree,p_FmPcd);
+ XX_Free(p_Params);
+ REPORT_ERROR(MAJOR, E_CONFLICT, ("numOfEntries per group must be set in descending order"));
+ return NULL;
+ }
+ }
+
+ lastOne = p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup;
+
+ netEnvParams.netEnvId = p_FmPcdCcTree->netEnvId;
+ netEnvParams.numOfDistinctionUnits = p_FmPcdCcGroupParams->numOfDistinctionUnits;
+
+ memcpy(netEnvParams.unitIds,
+ &p_FmPcdCcGroupParams->unitIds,
+ (sizeof(uint8_t)) * p_FmPcdCcGroupParams->numOfDistinctionUnits);
+
+ err = PcdGetUnitsVector(p_FmPcd, &netEnvParams);
+ if (err)
+ {
+ DeleteTree(p_FmPcdCcTree,p_FmPcd);
+ XX_Free(p_Params);
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ return NULL;
+ }
+
+ p_FmPcdCcTree->fmPcdGroupParam[i].totalBitsMask = netEnvParams.vector;
+ for (j = 0; j < p_FmPcdCcTree->fmPcdGroupParam[i].numOfEntriesInGroup; j++)
+ {
+ err = ValidateNextEngineParams(h_FmPcd,
+ &p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j],
+ e_FM_PCD_CC_STATS_MODE_NONE);
+ if (err)
+ {
+ DeleteTree(p_FmPcdCcTree,p_FmPcd);
+ XX_Free(p_Params);
+ REPORT_ERROR(MAJOR, err, (NO_MSG));
+ return NULL;
+ }
+
+ if (p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j].h_Manip)
+ {
+ err = FmPcdManipCheckParamsForCcNextEngine(&p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j], &requiredAction);
+ if (err)
+ {
+ DeleteTree(p_FmPcdCcTree,p_FmPcd);
+ XX_Free(p_Params);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+ return NULL;
+ }
+ }
+ p_KeyAndNextEngineParams = p_Params+k;
+
+ memcpy(&p_KeyAndNextEngineParams->nextEngineParams,
+ &p_FmPcdCcGroupParams->nextEnginePerEntriesInGrp[j],
+ sizeof(t_FmPcdCcNextEngineParams));
+
+ if ((p_KeyAndNextEngineParams->nextEngineParams.nextEngine == e_FM_PCD_CC)
+ && p_KeyAndNextEngineParams->nextEngineParams.h_Manip)
+ {
+ err = AllocAndFillAdForContLookupManip(p_KeyAndNextEngineParams->nextEngineParams.params.ccParams.h_CcNode);
+ if (err)
+ {
+ DeleteTree(p_FmPcdCcTree,p_FmPcd);
+ XX_Free(p_Params);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC Tree"));
+ return NULL;
+ }
+ }
+
+ requiredAction |= UPDATE_CC_WITH_TREE;
+ p_KeyAndNextEngineParams->requiredAction = requiredAction;
+
+ k++;
+ }
+ }
+
+ p_FmPcdCcTree->numOfEntries = (uint8_t)k;
+ p_FmPcdCcTree->numOfGrps = p_PcdGroupsParam->numOfGrps;
+
+ p_FmPcdCcTree->ccTreeBaseAddr =
+ PTR_TO_UINT(FM_MURAM_AllocMem(FmPcdGetMuramHandle(h_FmPcd),
+ (uint32_t)( FM_PCD_MAX_NUM_OF_CC_GROUPS * FM_PCD_CC_AD_ENTRY_SIZE),
+ FM_PCD_CC_TREE_ADDR_ALIGN));
+ if (!p_FmPcdCcTree->ccTreeBaseAddr)
+ {
+ DeleteTree(p_FmPcdCcTree,p_FmPcd);
+ XX_Free(p_Params);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for CC Tree"));
+ return NULL;
+ }
+ IOMemSet32(UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr), 0, (uint32_t)(FM_PCD_MAX_NUM_OF_CC_GROUPS * FM_PCD_CC_AD_ENTRY_SIZE));
+
+ p_CcTreeTmp = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr);
+
+ j = 0;
+ for (i = 0; i < numOfEntries; i++)
+ {
+ p_KeyAndNextEngineParams = p_Params + i;
+
+ NextStepAd(p_CcTreeTmp,
+ NULL,
+ &p_KeyAndNextEngineParams->nextEngineParams,
+ p_FmPcd);
+
+ p_CcTreeTmp = PTR_MOVE(p_CcTreeTmp, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ memcpy(&p_FmPcdCcTree->keyAndNextEngineParams[i],
+ p_KeyAndNextEngineParams,
+ sizeof(t_FmPcdCcKeyAndNextEngineParams));
+
+ if (p_FmPcdCcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine== e_FM_PCD_CC)
+ {
+ p_FmPcdCcNextNode = (t_FmPcdCcNode*)p_FmPcdCcTree->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode;
+ p_CcInformation = FindNodeInfoInReleventLst(&p_FmPcdCcNextNode->ccTreeIdLst,
+ (t_Handle)p_FmPcdCcTree,
+ p_FmPcdCcNextNode->h_Spinlock);
+
+ if (!p_CcInformation)
+ {
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ ccNodeInfo.h_CcNode = (t_Handle)p_FmPcdCcTree;
+ ccNodeInfo.index = 1;
+ EnqueueNodeInfoToRelevantLst(&p_FmPcdCcNextNode->ccTreeIdLst,
+ &ccNodeInfo,
+ p_FmPcdCcNextNode->h_Spinlock);
+ }
+ else
+ p_CcInformation->index++;
+ }
+ }
+
+ FmPcdIncNetEnvOwners(h_FmPcd, p_FmPcdCcTree->netEnvId);
+ p_CcTreeTmp = UINT_TO_PTR(p_FmPcdCcTree->ccTreeBaseAddr);
+
+ if (!FmPcdLockTryLockAll(p_FmPcd))
+ {
+ FM_PCD_CcRootDelete(p_FmPcdCcTree);
+ XX_Free(p_Params);
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return NULL;
+ }
+
+ for (i = 0; i < numOfEntries; i++)
+ {
+ if (p_FmPcdCcTree->keyAndNextEngineParams[i].requiredAction)
+ {
+ err = SetRequiredAction(h_FmPcd,
+ p_FmPcdCcTree->keyAndNextEngineParams[i].requiredAction,
+ &p_FmPcdCcTree->keyAndNextEngineParams[i],
+ p_CcTreeTmp,
+ 1,
+ p_FmPcdCcTree);
+ if (err)
+ {
+ FmPcdLockUnlockAll(p_FmPcd);
+ FM_PCD_CcRootDelete(p_FmPcdCcTree);
+ XX_Free(p_Params);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory"));
+ return NULL;
+ }
+ p_CcTreeTmp = PTR_MOVE(p_CcTreeTmp, FM_PCD_CC_AD_ENTRY_SIZE);
+ }
+ }
+
+ FmPcdLockUnlockAll(p_FmPcd);
+ p_FmPcdCcTree->p_Lock = FmPcdAcquireLock(p_FmPcd);
+ if (!p_FmPcdCcTree->p_Lock)
+ {
+ FM_PCD_CcRootDelete(p_FmPcdCcTree);
+ XX_Free(p_Params);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM CC lock"));
+ return NULL;
+ }
+
+ XX_Free(p_Params);
+
+ return p_FmPcdCcTree;
+}
+
+t_Error FM_PCD_CcRootDelete(t_Handle h_CcTree)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *)h_CcTree;
+ int i= 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_CcTree,E_INVALID_STATE);
+ p_FmPcd = (t_FmPcd *)p_CcTree->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+
+ FmPcdDecNetEnvOwners(p_FmPcd, p_CcTree->netEnvId);
+
+ if (p_CcTree->owners)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("the tree with this ID can not be removed because this tree is occupied, first - unbind this tree"));
+
+ /* Delete reassembly schemes if exist */
+ if (p_CcTree->h_IpReassemblyManip)
+ {
+ FmPcdManipDeleteIpReassmSchemes(p_CcTree->h_IpReassemblyManip);
+ FmPcdManipUpdateOwner(p_CcTree->h_IpReassemblyManip, FALSE);
+ }
+
+ for (i = 0; i <p_CcTree->numOfEntries; i++)
+ {
+ if (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ UpdateNodeOwner(p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode, FALSE);
+
+ if (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.h_Manip)
+ FmPcdManipUpdateOwner(p_CcTree->keyAndNextEngineParams[i].nextEngineParams.h_Manip, FALSE);
+
+#ifdef FM_CAPWAP_SUPPORT
+ if ((p_CcTree->numOfGrps == 1) &&
+ (p_CcTree->fmPcdGroupParam[0].numOfEntriesInGroup == 1) &&
+ (p_CcTree->keyAndNextEngineParams[0].nextEngineParams.nextEngine == e_FM_PCD_CC) &&
+ p_CcTree->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode &&
+ IsCapwapApplSpecific(p_CcTree->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode))
+ {
+ if (FM_PCD_ManipNodeDelete(p_CcTree->keyAndNextEngineParams[0].nextEngineParams.h_Manip) != E_OK)
+ return E_INVALID_STATE;
+ }
+#endif /* FM_CAPWAP_SUPPORT */
+
+#if (DPAA_VERSION >= 11)
+ if ((p_CcTree->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_FR) &&
+ (p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic))
+ FrmReplicGroupUpdateOwner(p_CcTree->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic,
+ FALSE);
+#endif /* (DPAA_VERSION >= 11) */
+ }
+
+ if (p_CcTree->p_Lock)
+ FmPcdReleaseLock(p_CcTree->h_FmPcd, p_CcTree->p_Lock);
+
+ DeleteTree(p_CcTree, p_FmPcd);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_CcRootModifyNextEngine(t_Handle h_CcTree,
+ uint8_t grpId,
+ uint8_t index,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcTree *p_CcTree = (t_FmPcdCcTree *)h_CcTree;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_CcTree,E_INVALID_STATE);
+ p_FmPcd = (t_FmPcd *)p_CcTree->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+
+ if (!FmPcdLockTryLockAll(p_FmPcd))
+ {
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FmPcdCcModifyNextEngineParamTree(p_FmPcd,
+ p_CcTree,
+ grpId,
+ index,
+ p_FmPcdCcNextEngineParams);
+ FmPcdLockUnlockAll(p_FmPcd);
+
+ if (err)
+ {
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ return E_OK;
+}
+
+t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_CcNodeParam)
+{
+ t_FmPcdCcNode *p_CcNode;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(p_CcNodeParam, E_NULL_POINTER, NULL);
+
+ p_CcNode = (t_FmPcdCcNode*)XX_Malloc(sizeof(t_FmPcdCcNode));
+ if (!p_CcNode)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory"));
+ return NULL;
+ }
+ memset(p_CcNode, 0, sizeof(t_FmPcdCcNode));
+
+ err = MatchTableSet(h_FmPcd, p_CcNode, p_CcNodeParam);
+
+ switch (GET_ERROR_TYPE(err))
+ {
+ case E_OK:
+ break;
+
+ case E_BUSY:
+ DBG(TRACE, ("E_BUSY error"));
+ return NULL;
+
+ default:
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ return NULL;
+ }
+
+ return p_CcNode;
+}
+
+t_Error FM_PCD_MatchTableDelete(t_Handle h_CcNode)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ int i = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+
+ UNUSED(p_FmPcd);
+
+ if (p_CcNode->owners)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("This node cannot be removed because it is occupied; first unbind this node"));
+
+ for (i = 0; i < p_CcNode->numOfKeys; i++)
+ if (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ UpdateNodeOwner(p_CcNode->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode, FALSE);
+
+ if (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ UpdateNodeOwner(p_CcNode->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode, FALSE);
+
+ /* Handle also Miss entry */
+ for (i = 0; i < p_CcNode->numOfKeys + 1; i++)
+ {
+ if (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip)
+ FmPcdManipUpdateOwner(p_CcNode->keyAndNextEngineParams[i].nextEngineParams.h_Manip, FALSE);
+
+#if (DPAA_VERSION >= 11)
+ if ((p_CcNode->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_FR) &&
+ (p_CcNode->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic))
+ {
+ FrmReplicGroupUpdateOwner(p_CcNode->keyAndNextEngineParams[i].nextEngineParams.params.frParams.h_FrmReplic,
+ FALSE);
+ }
+#endif /* (DPAA_VERSION >= 11) */
+ }
+
+ DeleteNode(p_CcNode);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_MatchTableAddKey(t_Handle h_CcNode,
+ uint16_t keyIndex,
+ uint8_t keySize,
+ t_FmPcdCcKeyParams *p_KeyParams)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(p_KeyParams, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ if (keyIndex == FM_PCD_LAST_KEY_INDEX)
+ keyIndex = p_CcNode->numOfKeys;
+
+ if (!FmPcdLockTryLockAll(p_FmPcd))
+ {
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FmPcdCcAddKey(p_FmPcd,
+ p_CcNode,
+ keyIndex,
+ keySize,
+ p_KeyParams);
+
+ FmPcdLockUnlockAll(p_FmPcd);
+
+ switch (GET_ERROR_TYPE(err))
+ {
+ case E_OK:
+ return E_OK;
+
+ case E_BUSY:
+ DBG(TRACE, ("E_BUSY error"));
+ return ERROR_CODE(E_BUSY);
+
+ default:
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+}
+
+t_Error FM_PCD_MatchTableRemoveKey(t_Handle h_CcNode, uint16_t keyIndex)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ if (!FmPcdLockTryLockAll(p_FmPcd))
+ {
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FmPcdCcRemoveKey(p_FmPcd, p_CcNode, keyIndex);
+
+ FmPcdLockUnlockAll(p_FmPcd);
+
+ switch (GET_ERROR_TYPE(err))
+ {
+ case E_OK:
+ return E_OK;
+
+ case E_BUSY:
+ DBG(TRACE, ("E_BUSY error"));
+ return ERROR_CODE(E_BUSY);
+
+ default:
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ return E_OK;
+}
+
+t_Error FM_PCD_MatchTableModifyKey(t_Handle h_CcNode,
+ uint16_t keyIndex,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t *p_Mask)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ t_List h_List;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ INIT_LIST(&h_List);
+
+ err = FmPcdCcNodeTreeTryLock(p_FmPcd, p_CcNode, &h_List);
+ if (err)
+ {
+ DBG(TRACE, ("Node's trees lock failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FmPcdCcModifyKey(p_FmPcd,
+ p_CcNode,
+ keyIndex,
+ keySize,
+ p_Key,
+ p_Mask);
+
+ FmPcdCcNodeTreeReleaseLock(p_FmPcd, &h_List);
+
+ switch (GET_ERROR_TYPE(err))
+ {
+ case E_OK:
+ return E_OK;
+
+ case E_BUSY:
+ DBG(TRACE, ("E_BUSY error"));
+ return ERROR_CODE(E_BUSY);
+
+ default:
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+}
+
+t_Error FM_PCD_MatchTableModifyNextEngine(t_Handle h_CcNode,
+ uint16_t keyIndex,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ if (!FmPcdLockTryLockAll(p_FmPcd))
+ {
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = ModifyNextEngineParamNode(p_FmPcd,
+ p_CcNode,
+ keyIndex,
+ p_FmPcdCcNextEngineParams);
+
+ FmPcdLockUnlockAll(p_FmPcd);
+
+ switch (GET_ERROR_TYPE(err))
+ {
+ case E_OK:
+ return E_OK;
+
+ case E_BUSY:
+ DBG(TRACE, ("E_BUSY error"));
+ return ERROR_CODE(E_BUSY);
+
+ default:
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+}
+
+t_Error FM_PCD_MatchTableModifyMissNextEngine(t_Handle h_CcNode,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ if (!FmPcdLockTryLockAll(p_FmPcd))
+ {
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FmPcdCcModifyMissNextEngineParamNode(p_FmPcd,
+ p_CcNode,
+ p_FmPcdCcNextEngineParams);
+
+ FmPcdLockUnlockAll(p_FmPcd);
+
+ switch (GET_ERROR_TYPE(err))
+ {
+ case E_OK:
+ return E_OK;
+
+ case E_BUSY:
+ DBG(TRACE, ("E_BUSY error"));
+ return ERROR_CODE(E_BUSY);
+
+ default:
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+}
+
+t_Error FM_PCD_MatchTableModifyKeyAndNextEngine(t_Handle h_CcNode,
+ uint16_t keyIndex,
+ uint8_t keySize,
+ t_FmPcdCcKeyParams *p_KeyParams)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(p_KeyParams, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ if (!FmPcdLockTryLockAll(p_FmPcd))
+ {
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FmPcdCcModifyKeyAndNextEngine(p_FmPcd,
+ p_CcNode,
+ keyIndex,
+ keySize,
+ p_KeyParams);
+
+ FmPcdLockUnlockAll(p_FmPcd);
+
+ switch (GET_ERROR_TYPE(err))
+ {
+ case E_OK:
+ return E_OK;
+
+ case E_BUSY:
+ DBG(TRACE, ("E_BUSY error"));
+ return ERROR_CODE(E_BUSY);
+
+ default:
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+}
+
+
+t_Error FM_PCD_MatchTableFindNRemoveKey(t_Handle h_CcNode,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t *p_Mask)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ uint16_t keyIndex;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ if (!FmPcdLockTryLockAll(p_FmPcd))
+ {
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex);
+ if (GET_ERROR_TYPE(err) != E_OK)
+ {
+ FmPcdLockUnlockAll(p_FmPcd);
+ RETURN_ERROR(MAJOR, err, ("The received key and mask pair was not found in the match table of the provided node"));
+ }
+
+ err = FmPcdCcRemoveKey(p_FmPcd, p_CcNode, keyIndex);
+
+ FmPcdLockUnlockAll(p_FmPcd);
+
+ switch (GET_ERROR_TYPE(err))
+ {
+ case E_OK:
+ return E_OK;
+
+ case E_BUSY:
+ DBG(TRACE, ("E_BUSY error"));
+ return ERROR_CODE(E_BUSY);
+
+ default:
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+}
+
+
+t_Error FM_PCD_MatchTableFindNModifyNextEngine(t_Handle h_CcNode,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t *p_Mask,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ uint16_t keyIndex;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ if (!FmPcdLockTryLockAll(p_FmPcd))
+ {
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex);
+ if (GET_ERROR_TYPE(err) != E_OK)
+ {
+ FmPcdLockUnlockAll(p_FmPcd);
+ RETURN_ERROR(MAJOR, err, ("The received key and mask pair was not found in the match table of the provided node"));
+ }
+
+ err = ModifyNextEngineParamNode(p_FmPcd,
+ p_CcNode,
+ keyIndex,
+ p_FmPcdCcNextEngineParams);
+
+ FmPcdLockUnlockAll(p_FmPcd);
+
+ switch (GET_ERROR_TYPE(err))
+ {
+ case E_OK:
+ return E_OK;
+
+ case E_BUSY:
+ DBG(TRACE, ("E_BUSY error"));
+ return ERROR_CODE(E_BUSY);
+
+ default:
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+}
+
+t_Error FM_PCD_MatchTableFindNModifyKeyAndNextEngine(t_Handle h_CcNode,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t *p_Mask,
+ t_FmPcdCcKeyParams *p_KeyParams)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ uint16_t keyIndex;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_KeyParams, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ if (!FmPcdLockTryLockAll(p_FmPcd))
+ {
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex);
+ if (GET_ERROR_TYPE(err) != E_OK)
+ {
+ FmPcdLockUnlockAll(p_FmPcd);
+ RETURN_ERROR(MAJOR, err, ("The received key and mask pair was not found in the match table of the provided node"));
+ }
+
+ err = FmPcdCcModifyKeyAndNextEngine(p_FmPcd,
+ h_CcNode,
+ keyIndex,
+ keySize,
+ p_KeyParams);
+
+ FmPcdLockUnlockAll(p_FmPcd);
+
+ switch (GET_ERROR_TYPE(err))
+ {
+ case E_OK:
+ return E_OK;
+
+ case E_BUSY:
+ DBG(TRACE, ("E_BUSY error"));
+ return ERROR_CODE(E_BUSY);
+
+ default:
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+}
+
+t_Error FM_PCD_MatchTableFindNModifyKey(t_Handle h_CcNode,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t *p_Mask,
+ uint8_t *p_NewKey,
+ uint8_t *p_NewMask)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ t_List h_List;
+ uint16_t keyIndex;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_NewKey, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ p_FmPcd = (t_FmPcd *)p_CcNode->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ INIT_LIST(&h_List);
+
+ err = FmPcdCcNodeTreeTryLock(p_FmPcd, p_CcNode, &h_List);
+ if (err)
+ {
+ DBG(TRACE, ("Node's trees lock failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex);
+ if (GET_ERROR_TYPE(err) != E_OK)
+ {
+ FmPcdCcNodeTreeReleaseLock(p_FmPcd, &h_List);
+ RETURN_ERROR(MAJOR, err, ("The received key and mask pair was not found in the "
+ "match table of the provided node"));
+ }
+
+ err = FmPcdCcModifyKey(p_FmPcd,
+ p_CcNode,
+ keyIndex,
+ keySize,
+ p_NewKey,
+ p_NewMask);
+
+ FmPcdCcNodeTreeReleaseLock(p_FmPcd, &h_List);
+
+ switch (GET_ERROR_TYPE(err))
+ {
+ case E_OK:
+ return E_OK;
+
+ case E_BUSY:
+ DBG(TRACE, ("E_BUSY error"));
+ return ERROR_CODE(E_BUSY);
+
+ default:
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+}
+
+t_Error FM_PCD_MatchTableGetNextEngine(t_Handle h_CcNode,
+ uint16_t keyIndex,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+
+ SANITY_CHECK_RETURN_ERROR(p_CcNode, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER);
+
+ if (keyIndex >= p_CcNode->numOfKeys)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("keyIndex exceeds current number of keys"));
+
+ if (keyIndex > (FM_PCD_MAX_NUM_OF_KEYS - 1))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("keyIndex can not be larger than %d", (FM_PCD_MAX_NUM_OF_KEYS - 1)));
+
+ memcpy(p_FmPcdCcNextEngineParams,
+ &p_CcNode->keyAndNextEngineParams[keyIndex].nextEngineParams,
+ sizeof(t_FmPcdCcNextEngineParams));
+
+ return E_OK;
+}
+
+
+uint32_t FM_PCD_MatchTableGetKeyCounter(t_Handle h_CcNode, uint16_t keyIndex)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ uint32_t *p_StatsCounters, frameCount;
+ uint32_t intFlags;
+
+ SANITY_CHECK_RETURN_VALUE(p_CcNode, E_INVALID_HANDLE, 0);
+
+ if (p_CcNode->statisticsMode == e_FM_PCD_CC_STATS_MODE_NONE)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Statistics were not enabled for this match table"));
+ return 0;
+ }
+
+ if ((p_CcNode->statisticsMode != e_FM_PCD_CC_STATS_MODE_FRAME) &&
+ (p_CcNode->statisticsMode != e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME))
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Frame count is not supported in the statistics mode of this match table"));
+ return 0;
+ }
+
+ intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock);
+
+ if (keyIndex >= p_CcNode->numOfKeys)
+ {
+ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("The provided keyIndex exceeds the number of keys in this match table"));
+ return 0;
+ }
+
+ if (!p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj)
+ {
+ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Statistics were not enabled for this key"));
+ return 0;
+ }
+
+ p_StatsCounters = p_CcNode->keyAndNextEngineParams[keyIndex].p_StatsObj->h_StatsCounters;
+ ASSERT_COND(p_StatsCounters);
+
+ /* The first counter is byte counter, so we need to advance to the next counter */
+ frameCount = GET_UINT32(*(uint32_t *)(PTR_MOVE(p_StatsCounters,
+ FM_PCD_CC_STATS_COUNTER_SIZE)));
+
+ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
+
+ return frameCount;
+}
+
+t_Error FM_PCD_MatchTableGetKeyStatistics(t_Handle h_CcNode,
+ uint16_t keyIndex,
+ t_FmPcdCcKeyStatistics *p_KeyStatistics)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ uint32_t intFlags;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(h_CcNode, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_KeyStatistics, E_NULL_POINTER);
+
+ intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock);
+
+ if (keyIndex >= p_CcNode->numOfKeys)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("The provided keyIndex exceeds the number of keys in this match table"));
+
+ err = MatchTableGetKeyStatistics(p_CcNode,
+ keyIndex,
+ p_KeyStatistics);
+
+ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
+
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_MatchTableGetMissStatistics(t_Handle h_CcNode,
+ t_FmPcdCcKeyStatistics *p_MissStatistics)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ uint32_t intFlags;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(h_CcNode, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_MissStatistics, E_NULL_POINTER);
+
+ intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock);
+
+ err = MatchTableGetKeyStatistics(p_CcNode,
+ p_CcNode->numOfKeys,
+ p_MissStatistics);
+
+ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
+
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_MatchTableFindNGetKeyStatistics(t_Handle h_CcNode,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t *p_Mask,
+ t_FmPcdCcKeyStatistics *p_KeyStatistics)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ uint16_t keyIndex;
+ uint32_t intFlags;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_KeyStatistics, E_NULL_POINTER);
+
+ intFlags = XX_LockIntrSpinlock(p_CcNode->h_Spinlock);
+
+ err = FindKeyIndex(p_CcNode, keySize, p_Key, p_Mask, &keyIndex);
+ if (GET_ERROR_TYPE(err) != E_OK)
+ {
+ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
+ RETURN_ERROR(MAJOR, err, ("The received key and mask pair was not found in the "
+ "match table of the provided node"));
+ }
+
+ ASSERT_COND(keyIndex < p_CcNode->numOfKeys);
+
+ err = MatchTableGetKeyStatistics(p_CcNode,
+ keyIndex,
+ p_KeyStatistics);
+
+ XX_UnlockIntrSpinlock(p_CcNode->h_Spinlock, intFlags);
+
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_MatchTableGetIndexedHashBucket(t_Handle h_CcNode,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t hashShift,
+ t_Handle *p_CcNodeBucketHandle,
+ uint8_t *p_BucketIndex,
+ uint16_t *p_LastIndex)
+{
+ t_FmPcdCcNode *p_CcNode = (t_FmPcdCcNode *)h_CcNode;
+ uint16_t glblMask;
+ uint64_t crc64 = 0;
+
+ SANITY_CHECK_RETURN_ERROR(h_CcNode, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_CcNode->parseCode == CC_PC_GENERIC_IC_HASH_INDEXED, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_CcNodeBucketHandle, E_NULL_POINTER);
+
+ memcpy(&glblMask, PTR_MOVE(p_CcNode->p_GlblMask, 2), 2);
+
+ crc64 = crc64_init();
+ crc64 = crc64_compute(p_Key, keySize, crc64);
+ crc64 >>= hashShift;
+
+ *p_BucketIndex = (uint8_t)(((crc64 >> (8 * (6 - p_CcNode->userOffset))) & glblMask) >> 4);
+ if (*p_BucketIndex >= p_CcNode->numOfKeys)
+ RETURN_ERROR(MINOR, E_NOT_IN_RANGE, ("bucket index!"));
+
+ *p_CcNodeBucketHandle = p_CcNode->keyAndNextEngineParams[*p_BucketIndex].nextEngineParams.params.ccParams.h_CcNode;
+ if (!*p_CcNodeBucketHandle)
+ RETURN_ERROR(MINOR, E_NOT_FOUND, ("bucket!"));
+
+ *p_LastIndex = ((t_FmPcdCcNode *)*p_CcNodeBucketHandle)->numOfKeys;
+
+ return E_OK;
+}
+
+t_Handle FM_PCD_HashTableSet(t_Handle h_FmPcd, t_FmPcdHashTableParams *p_Param)
+{
+ t_FmPcdCcNode *p_CcNodeHashTbl;
+ t_FmPcdCcNodeParams *p_IndxHashCcNodeParam, *p_ExactMatchCcNodeParam;
+ t_FmPcdCcNode *p_CcNode;
+ t_Handle h_MissStatsCounters = NULL;
+ t_FmPcdCcKeyParams *p_HashKeyParams;
+ int i;
+ uint16_t numOfSets, numOfWays, countMask, onesCount = 0;
+ bool statsEnForMiss = FALSE;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(p_Param, E_NULL_POINTER, NULL);
+
+ if (p_Param->maxNumOfKeys == 0)
+ {
+ REPORT_ERROR(MINOR, E_INVALID_VALUE, ("Max number of keys must be higher then 0"));
+ return NULL;
+ }
+
+ if (p_Param->hashResMask == 0)
+ {
+ REPORT_ERROR(MINOR, E_INVALID_VALUE, ("Hash result mask must differ from 0"));
+ return NULL;
+ }
+
+#if (DPAA_VERSION >= 11)
+ if (p_Param->statisticsMode == e_FM_PCD_CC_STATS_MODE_RMON)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("RMON statistics mode is not supported for hash table"));
+ return NULL;
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ p_ExactMatchCcNodeParam = (t_FmPcdCcNodeParams*)XX_Malloc(sizeof(t_FmPcdCcNodeParams));
+ if (!p_ExactMatchCcNodeParam)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("p_ExactMatchCcNodeParam"));
+ return NULL;
+ }
+ memset(p_ExactMatchCcNodeParam, 0, sizeof(t_FmPcdCcNodeParams));
+
+ p_IndxHashCcNodeParam = (t_FmPcdCcNodeParams*)XX_Malloc(sizeof(t_FmPcdCcNodeParams));
+ if (!p_IndxHashCcNodeParam)
+ {
+ XX_Free(p_ExactMatchCcNodeParam);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("p_IndxHashCcNodeParam"));
+ return NULL;
+ }
+ memset(p_IndxHashCcNodeParam, 0, sizeof(t_FmPcdCcNodeParams));
+
+ /* Calculate number of sets and number of ways of the hash table */
+ countMask = (uint16_t)(p_Param->hashResMask >> 4);
+ while (countMask)
+ {
+ onesCount++;
+ countMask = (uint16_t)(countMask >> 1);
+ }
+
+ numOfSets = (uint16_t)(1 << onesCount);
+ numOfWays = (uint16_t)DIV_CEIL(p_Param->maxNumOfKeys, numOfSets);
+
+ if (p_Param->maxNumOfKeys % numOfSets)
+ DBG(INFO, ("'maxNumOfKeys' is not a multiple of hash number of ways, so number of ways will be rounded up"));
+
+ if ((p_Param->statisticsMode == e_FM_PCD_CC_STATS_MODE_FRAME) ||
+ (p_Param->statisticsMode == e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME))
+ {
+ /* Allocating a statistics counters table that will be used by all
+ 'miss' entries of the hash table */
+ h_MissStatsCounters = (t_Handle)FM_MURAM_AllocMem(FmPcdGetMuramHandle(h_FmPcd),
+ 2 * FM_PCD_CC_STATS_COUNTER_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!h_MissStatsCounters)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for statistics table for hash miss"));
+ return NULL;
+ }
+ memset(h_MissStatsCounters, 0, (2 * FM_PCD_CC_STATS_COUNTER_SIZE));
+
+ /* Always enable statistics for 'miss', so that a statistics AD will be
+ initialized from the start. We'll store the requested 'statistics enable'
+ value and it will be used when statistics are read by the user. */
+ statsEnForMiss = p_Param->ccNextEngineParamsForMiss.statisticsEn;
+ p_Param->ccNextEngineParamsForMiss.statisticsEn = TRUE;
+ }
+
+ /* Building exact-match node params, will be used to create the hash buckets */
+ p_ExactMatchCcNodeParam->extractCcParams.type = e_FM_PCD_EXTRACT_NON_HDR;
+
+ p_ExactMatchCcNodeParam->extractCcParams.extractNonHdr.src = e_FM_PCD_EXTRACT_FROM_KEY;
+ p_ExactMatchCcNodeParam->extractCcParams.extractNonHdr.action = e_FM_PCD_ACTION_EXACT_MATCH;
+ p_ExactMatchCcNodeParam->extractCcParams.extractNonHdr.offset = 0;
+ p_ExactMatchCcNodeParam->extractCcParams.extractNonHdr.size = p_Param->matchKeySize;
+
+ p_ExactMatchCcNodeParam->keysParams.maxNumOfKeys = numOfWays;
+ p_ExactMatchCcNodeParam->keysParams.maskSupport = FALSE;
+ p_ExactMatchCcNodeParam->keysParams.statisticsMode = p_Param->statisticsMode;
+ p_ExactMatchCcNodeParam->keysParams.numOfKeys = 0;
+ p_ExactMatchCcNodeParam->keysParams.keySize = p_Param->matchKeySize;
+ p_ExactMatchCcNodeParam->keysParams.ccNextEngineParamsForMiss = p_Param->ccNextEngineParamsForMiss;
+
+ p_HashKeyParams = p_IndxHashCcNodeParam->keysParams.keyParams;
+
+ for (i = 0; i < numOfSets; i++)
+ {
+ /* Each exact-match node will be marked as a 'bucket' and provided with a pointer to statistics counters,
+ to be used for 'miss' entry statistics */
+ p_CcNode = (t_FmPcdCcNode *)XX_Malloc(sizeof(t_FmPcdCcNode));
+ if (!p_CcNode)
+ break;
+ memset(p_CcNode, 0, sizeof(t_FmPcdCcNode));
+
+ p_CcNode->isHashBucket = TRUE;
+ p_CcNode->h_MissStatsCounters = h_MissStatsCounters;
+
+ err = MatchTableSet(h_FmPcd, p_CcNode, p_ExactMatchCcNodeParam);
+ if (err)
+ break;
+
+ p_HashKeyParams[i].ccNextEngineParams.nextEngine = e_FM_PCD_CC;
+ p_HashKeyParams[i].ccNextEngineParams.statisticsEn = FALSE;
+ p_HashKeyParams[i].ccNextEngineParams.params.ccParams.h_CcNode = p_CcNode;
+ }
+
+ if (i < numOfSets)
+ {
+ for (i = i-1; i >=0; i--)
+ FM_PCD_MatchTableDelete(p_HashKeyParams[i].ccNextEngineParams.params.ccParams.h_CcNode);
+
+ FM_MURAM_FreeMem(FmPcdGetMuramHandle(h_FmPcd), h_MissStatsCounters);
+
+ REPORT_ERROR(MAJOR, E_NULL_POINTER, NO_MSG);
+ XX_Free(p_IndxHashCcNodeParam);
+ XX_Free(p_ExactMatchCcNodeParam);
+ return NULL;
+ }
+
+ /* Creating indexed-hash CC node */
+ p_IndxHashCcNodeParam->extractCcParams.type = e_FM_PCD_EXTRACT_NON_HDR;
+ p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.src = e_FM_PCD_EXTRACT_FROM_HASH;
+ p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.action = e_FM_PCD_ACTION_INDEXED_LOOKUP;
+ p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.icIndxMask = p_Param->hashResMask;
+ p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.offset = p_Param->hashShift;
+ p_IndxHashCcNodeParam->extractCcParams.extractNonHdr.size = 2;
+
+ p_IndxHashCcNodeParam->keysParams.maxNumOfKeys = numOfSets;
+ p_IndxHashCcNodeParam->keysParams.maskSupport = FALSE;
+ p_IndxHashCcNodeParam->keysParams.statisticsMode = e_FM_PCD_CC_STATS_MODE_NONE;
+ p_IndxHashCcNodeParam->keysParams.numOfKeys = numOfSets; /* Number of keys of this node is number of sets of the hash */
+ p_IndxHashCcNodeParam->keysParams.keySize = 2;
+
+ p_CcNodeHashTbl = FM_PCD_MatchTableSet(h_FmPcd, p_IndxHashCcNodeParam);
+
+ if (p_CcNodeHashTbl)
+ {
+ p_CcNodeHashTbl->kgHashShift = p_Param->kgHashShift;
+
+ /* Storing the allocated counters for buckets 'miss' in the hash table
+ and is statistics for miss wre enabled. */
+ p_CcNodeHashTbl->h_MissStatsCounters = h_MissStatsCounters;
+ p_CcNodeHashTbl->statsEnForMiss = statsEnForMiss;
+ }
+
+ XX_Free(p_IndxHashCcNodeParam);
+ XX_Free(p_ExactMatchCcNodeParam);
+
+ return p_CcNodeHashTbl;
+}
+
+t_Error FM_PCD_HashTableDelete(t_Handle h_HashTbl)
+{
+ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl;
+ t_Handle h_FmPcd;
+ t_Handle *p_HashBuckets, h_MissStatsCounters;
+ uint16_t i, numOfBuckets;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE);
+
+ /* Store all hash buckets before the hash is freed */
+ numOfBuckets = p_HashTbl->numOfKeys;
+
+ p_HashBuckets = (t_Handle *)XX_Malloc(numOfBuckets * sizeof(t_Handle));
+ if (!p_HashBuckets)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+
+ for (i = 0; i < numOfBuckets; i++)
+ p_HashBuckets[i] = p_HashTbl->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode;
+
+ h_FmPcd = p_HashTbl->h_FmPcd;
+ h_MissStatsCounters = p_HashTbl->h_MissStatsCounters;
+
+ /* Free the hash */
+ err = FM_PCD_MatchTableDelete(p_HashTbl);
+
+ /* Free each hash bucket */
+ for (i = 0; i < numOfBuckets; i++)
+ err |= FM_PCD_MatchTableDelete(p_HashBuckets[i]);
+
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ /* Free statistics counters for 'miss', id these were allocated */
+ if (h_MissStatsCounters)
+ FM_MURAM_FreeMem(FmPcdGetMuramHandle(h_FmPcd), h_MissStatsCounters);
+
+ XX_Free(p_HashBuckets);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_HashTableAddKey(t_Handle h_HashTbl,
+ uint8_t keySize,
+ t_FmPcdCcKeyParams *p_KeyParams)
+{
+ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl;
+ t_Handle h_HashBucket;
+ uint8_t bucketIndex;
+ uint16_t lastIndex;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_KeyParams, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_KeyParams->p_Key, E_NULL_POINTER);
+
+ if (p_KeyParams->p_Mask)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Keys masks not supported for hash table"));
+
+ err = FM_PCD_MatchTableGetIndexedHashBucket(p_HashTbl,
+ keySize,
+ p_KeyParams->p_Key,
+ p_HashTbl->kgHashShift,
+ &h_HashBucket,
+ &bucketIndex,
+ &lastIndex);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ return FM_PCD_MatchTableAddKey(h_HashBucket,
+ FM_PCD_LAST_KEY_INDEX,
+ keySize,
+ p_KeyParams);
+}
+
+t_Error FM_PCD_HashTableRemoveKey(t_Handle h_HashTbl,
+ uint8_t keySize,
+ uint8_t *p_Key)
+{
+ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl;
+ t_Handle h_HashBucket;
+ uint8_t bucketIndex;
+ uint16_t lastIndex;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
+
+ err = FM_PCD_MatchTableGetIndexedHashBucket(p_HashTbl,
+ keySize,
+ p_Key,
+ p_HashTbl->kgHashShift,
+ &h_HashBucket,
+ &bucketIndex,
+ &lastIndex);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ return FM_PCD_MatchTableFindNRemoveKey(h_HashBucket,
+ keySize,
+ p_Key,
+ NULL);
+}
+
+t_Error FM_PCD_HashTableModifyNextEngine(t_Handle h_HashTbl,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl;
+ t_Handle h_HashBucket;
+ uint8_t bucketIndex;
+ uint16_t lastIndex;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER);
+
+ err = FM_PCD_MatchTableGetIndexedHashBucket(p_HashTbl,
+ keySize,
+ p_Key,
+ p_HashTbl->kgHashShift,
+ &h_HashBucket,
+ &bucketIndex,
+ &lastIndex);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ return FM_PCD_MatchTableFindNModifyNextEngine(h_HashBucket,
+ keySize,
+ p_Key,
+ NULL,
+ p_FmPcdCcNextEngineParams);
+}
+
+t_Error FM_PCD_HashTableModifyMissNextEngine(t_Handle h_HashTbl,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl;
+ t_Handle h_HashBucket;
+ uint8_t i;
+ bool nullifyMissStats = FALSE;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(h_HashTbl, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER);
+
+ if ((!p_HashTbl->h_MissStatsCounters) && (p_FmPcdCcNextEngineParams->statisticsEn))
+ RETURN_ERROR(MAJOR, E_CONFLICT,
+ ("Statistics are requested for a key, but statistics mode was set"
+ "to 'NONE' upon initialization"));
+
+ if (p_HashTbl->h_MissStatsCounters)
+ {
+ if ((!p_HashTbl->statsEnForMiss) && (p_FmPcdCcNextEngineParams->statisticsEn))
+ nullifyMissStats = TRUE;
+
+ if ((p_HashTbl->statsEnForMiss) && (!p_FmPcdCcNextEngineParams->statisticsEn))
+ {
+ p_HashTbl->statsEnForMiss = FALSE;
+ p_FmPcdCcNextEngineParams->statisticsEn = TRUE;
+ }
+ }
+
+ for (i = 0; i < p_HashTbl->numOfKeys; i++)
+ {
+ h_HashBucket = p_HashTbl->keyAndNextEngineParams[i].nextEngineParams.params.ccParams.h_CcNode;
+
+ err = FM_PCD_MatchTableModifyMissNextEngine(h_HashBucket,
+ p_FmPcdCcNextEngineParams);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ if (nullifyMissStats)
+ {
+ memset(p_HashTbl->h_MissStatsCounters, 0, (2 * FM_PCD_CC_STATS_COUNTER_SIZE));
+ memset(p_HashTbl->h_MissStatsCounters, 0, (2 * FM_PCD_CC_STATS_COUNTER_SIZE));
+ p_HashTbl->statsEnForMiss = TRUE;
+ }
+
+ return E_OK;
+}
+
+
+t_Error FM_PCD_HashTableGetMissNextEngine(t_Handle h_HashTbl,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams)
+{
+ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl;
+ t_FmPcdCcNode *p_HashBucket;
+
+ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE);
+
+ /* Miss next engine of each bucket was initialized with the next engine of the hash table */
+ p_HashBucket = p_HashTbl->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode;
+
+ memcpy(p_FmPcdCcNextEngineParams,
+ &p_HashBucket->keyAndNextEngineParams[p_HashBucket->numOfKeys].nextEngineParams,
+ sizeof(t_FmPcdCcNextEngineParams));
+
+ return E_OK;
+}
+
+t_Error FM_PCD_HashTableFindNGetKeyStatistics(t_Handle h_HashTbl,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ t_FmPcdCcKeyStatistics *p_KeyStatistics)
+{
+ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl;
+ t_Handle h_HashBucket;
+ uint8_t bucketIndex;
+ uint16_t lastIndex;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Key, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_KeyStatistics, E_NULL_POINTER);
+
+ err = FM_PCD_MatchTableGetIndexedHashBucket(p_HashTbl,
+ keySize,
+ p_Key,
+ p_HashTbl->kgHashShift,
+ &h_HashBucket,
+ &bucketIndex,
+ &lastIndex);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ return FM_PCD_MatchTableFindNGetKeyStatistics(h_HashBucket,
+ keySize,
+ p_Key,
+ NULL,
+ p_KeyStatistics);
+}
+
+t_Error FM_PCD_HashTableGetMissStatistics(t_Handle h_HashTbl,
+ t_FmPcdCcKeyStatistics *p_MissStatistics)
+{
+ t_FmPcdCcNode *p_HashTbl = (t_FmPcdCcNode *)h_HashTbl;
+ t_Handle h_HashBucket;
+
+ SANITY_CHECK_RETURN_ERROR(p_HashTbl, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_MissStatistics, E_NULL_POINTER);
+
+ if (!p_HashTbl->statsEnForMiss)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Statistics were not enabled for miss"));
+
+ h_HashBucket = p_HashTbl->keyAndNextEngineParams[0].nextEngineParams.params.ccParams.h_CcNode;
+
+ return FM_PCD_MatchTableGetMissStatistics(h_HashBucket,
+ p_MissStatistics);
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.h
new file mode 100644
index 0000000..ab2e50c
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_cc.h
@@ -0,0 +1,402 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_cc.h
+
+ @Description FM PCD CC ...
+*//***************************************************************************/
+#ifndef __FM_CC_H
+#define __FM_CC_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "list_ext.h"
+
+#include "fm_pcd.h"
+
+
+/***********************************************************************/
+/* Coarse classification defines */
+/***********************************************************************/
+
+#define CC_MAX_NUM_OF_KEYS MAX(FM_PCD_MAX_NUM_OF_KEYS + 1, FM_PCD_MAX_NUM_OF_FLOWS)
+
+#define CC_PC_FF_MACDST 0x00
+#define CC_PC_FF_MACSRC 0x01
+#define CC_PC_FF_ETYPE 0x02
+
+#define CC_PC_FF_TCI1 0x03
+#define CC_PC_FF_TCI2 0x04
+
+#define CC_PC_FF_MPLS1 0x06
+#define CC_PC_FF_MPLS_LAST 0x07
+
+#define CC_PC_FF_IPV4DST1 0x08
+#define CC_PC_FF_IPV4DST2 0x16
+#define CC_PC_FF_IPV4IPTOS_TC1 0x09
+#define CC_PC_FF_IPV4IPTOS_TC2 0x17
+#define CC_PC_FF_IPV4PTYPE1 0x0A
+#define CC_PC_FF_IPV4PTYPE2 0x18
+#define CC_PC_FF_IPV4SRC1 0x0b
+#define CC_PC_FF_IPV4SRC2 0x19
+#define CC_PC_FF_IPV4SRC1_IPV4DST1 0x0c
+#define CC_PC_FF_IPV4SRC2_IPV4DST2 0x1a
+#define CC_PC_FF_IPV4TTL 0x29
+
+
+#define CC_PC_FF_IPTOS_IPV6TC1_IPV6FLOW1 0x0d /*TODO - CLASS - what is it? TOS*/
+#define CC_PC_FF_IPTOS_IPV6TC2_IPV6FLOW2 0x1b
+#define CC_PC_FF_IPV6PTYPE1 0x0e
+#define CC_PC_FF_IPV6PTYPE2 0x1c
+#define CC_PC_FF_IPV6DST1 0x0f
+#define CC_PC_FF_IPV6DST2 0x1d
+#define CC_PC_FF_IPV6SRC1 0x10
+#define CC_PC_FF_IPV6SRC2 0x1e
+#define CC_PC_FF_IPV6HOP_LIMIT 0x2a
+#define CC_PC_FF_IPPID 0x24
+#define CC_PC_FF_IPDSCP 0x76
+
+#define CC_PC_FF_GREPTYPE 0x11
+
+#define CC_PC_FF_MINENCAP_PTYPE 0x12
+#define CC_PC_FF_MINENCAP_IPDST 0x13
+#define CC_PC_FF_MINENCAP_IPSRC 0x14
+#define CC_PC_FF_MINENCAP_IPSRC_IPDST 0x15
+
+#define CC_PC_FF_L4PSRC 0x1f
+#define CC_PC_FF_L4PDST 0x20
+#define CC_PC_FF_L4PSRC_L4PDST 0x21
+
+#define CC_PC_FF_PPPPID 0x05
+
+#define CC_PC_PR_SHIM1 0x22
+#define CC_PC_PR_SHIM2 0x23
+
+#define CC_PC_GENERIC_WITHOUT_MASK 0x27
+#define CC_PC_GENERIC_WITH_MASK 0x28
+#define CC_PC_GENERIC_IC_GMASK 0x2B
+#define CC_PC_GENERIC_IC_HASH_INDEXED 0x2C
+
+#define CC_PR_OFFSET 0x25
+#define CC_PR_WITHOUT_OFFSET 0x26
+
+#define CC_PC_PR_ETH_OFFSET 19
+#define CC_PC_PR_USER_DEFINED_SHIM1_OFFSET 16
+#define CC_PC_PR_USER_DEFINED_SHIM2_OFFSET 17
+#define CC_PC_PR_USER_LLC_SNAP_OFFSET 20
+#define CC_PC_PR_VLAN1_OFFSET 21
+#define CC_PC_PR_VLAN2_OFFSET 22
+#define CC_PC_PR_PPPOE_OFFSET 24
+#define CC_PC_PR_MPLS1_OFFSET 25
+#define CC_PC_PR_MPLS_LAST_OFFSET 26
+#define CC_PC_PR_IP1_OFFSET 27
+#define CC_PC_PR_IP_LAST_OFFSET 28
+#define CC_PC_PR_MINENC_OFFSET 28
+#define CC_PC_PR_L4_OFFSET 30
+#define CC_PC_PR_GRE_OFFSET 29
+#define CC_PC_PR_ETYPE_LAST_OFFSET 23
+#define CC_PC_PR_NEXT_HEADER_OFFSET 31
+
+#define CC_PC_ILLEGAL 0xff
+#define CC_SIZE_ILLEGAL 0
+
+#define FM_PCD_CC_KEYS_MATCH_TABLE_ALIGN 16
+#define FM_PCD_CC_AD_TABLE_ALIGN 16
+#define FM_PCD_CC_AD_ENTRY_SIZE 16
+#define FM_PCD_CC_NUM_OF_KEYS 255
+#define FM_PCD_CC_TREE_ADDR_ALIGN 256
+
+#define FM_PCD_AD_RESULT_CONTRL_FLOW_TYPE 0x00000000
+#define FM_PCD_AD_RESULT_DATA_FLOW_TYPE 0x80000000
+#define FM_PCD_AD_RESULT_PLCR_DIS 0x20000000
+#define FM_PCD_AD_RESULT_EXTENDED_MODE 0x80000000
+#define FM_PCD_AD_RESULT_NADEN 0x20000000
+#define FM_PCD_AD_RESULT_STATISTICS_EN 0x40000000
+
+#define FM_PCD_AD_CONT_LOOKUP_TYPE 0x40000000
+#define FM_PCD_AD_CONT_LOOKUP_LCL_MASK 0x00800000
+
+#define FM_PCD_AD_STATS_TYPE 0x40000000
+#define FM_PCD_AD_STATS_FLR_ADDR_MASK 0x00FFFFFF
+#define FM_PCD_AD_STATS_COUNTERS_ADDR_MASK 0x00FFFFFF
+#define FM_PCD_AD_STATS_NEXT_ACTION_MASK 0xFFFF0000
+#define FM_PCD_AD_STATS_NEXT_ACTION_SHIFT 12
+#define FM_PCD_AD_STATS_NAD_EN 0x00008000
+#define FM_PCD_AD_STATS_OP_CODE 0x00000036
+#define FM_PCD_AD_STATS_FLR_EN 0x00004000
+#define FM_PCD_AD_STATS_COND_EN 0x00002000
+
+
+
+#define FM_PCD_AD_BYPASS_TYPE 0xc0000000
+
+#define FM_PCD_AD_TYPE_MASK 0xc0000000
+#define FM_PCD_AD_OPCODE_MASK 0x0000000f
+
+#define FM_PCD_AD_PROFILEID_FOR_CNTRL_SHIFT 16
+#if (DPAA_VERSION >= 11)
+#define FM_PCD_AD_RESULT_VSP_SHIFT 24
+#define FM_PCD_AD_RESULT_NO_OM_VSPE 0x02000000
+#define FM_PCD_AD_RESULT_VSP_MASK 0x3f
+#define FM_PCD_AD_NCSPFQIDM_MASK 0x80000000
+#endif /* (DPAA_VERSION >= 11) */
+
+#define GLBL_MASK_FOR_HASH_INDEXED 0xfff00000
+#define CC_GLBL_MASK_SIZE 4
+
+typedef uint32_t ccPrivateInfo_t; /**< private info of CC: */
+
+#define CC_PRIVATE_INFO_NONE 0
+#define CC_PRIVATE_INFO_IC_HASH_INDEX_LOOKUP 0x80000000
+#define CC_PRIVATE_INFO_IC_HASH_EXACT_MATCH 0x40000000
+#define CC_PRIVATE_INFO_IC_KEY_EXACT_MATCH 0x20000000
+#define CC_PRIVATE_INFO_IC_DEQ_FQID_INDEX_LOOKUP 0x10000000
+
+/***********************************************************************/
+/* Memory map */
+/***********************************************************************/
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+typedef _Packed struct
+{
+ volatile uint32_t fqid;
+ volatile uint32_t plcrProfile;
+ volatile uint32_t nia;
+ volatile uint32_t res;
+} _PackedType t_AdOfTypeResult;
+
+typedef _Packed struct
+{
+ volatile uint32_t ccAdBase;
+ volatile uint32_t matchTblPtr;
+ volatile uint32_t pcAndOffsets;
+ volatile uint32_t gmask;
+} _PackedType t_AdOfTypeContLookup;
+
+typedef _Packed struct
+{
+ volatile uint32_t profileTableAddr;
+ volatile uint32_t reserved;
+ volatile uint32_t nextActionIndx;
+ volatile uint32_t statsTableAddr;
+} _PackedType t_AdOfTypeStats;
+
+typedef _Packed union
+{
+ volatile t_AdOfTypeResult adResult;
+ volatile t_AdOfTypeContLookup adContLookup;
+} _PackedType t_Ad;
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+/***********************************************************************/
+/* Driver's internal structures */
+/***********************************************************************/
+
+typedef enum e_ModifyState
+{
+ e_MODIFY_STATE_ADD = 0,
+ e_MODIFY_STATE_REMOVE,
+ e_MODIFY_STATE_CHANGE
+} e_ModifyState;
+
+typedef struct t_FmPcdStatsObj
+{
+ t_Handle h_StatsAd;
+ t_Handle h_StatsCounters;
+ t_List node;
+} t_FmPcdStatsObj;
+
+typedef struct
+{
+ uint8_t key[FM_PCD_MAX_SIZE_OF_KEY];
+ uint8_t mask[FM_PCD_MAX_SIZE_OF_KEY];
+
+ t_FmPcdCcNextEngineParams nextEngineParams;
+ uint32_t requiredAction;
+ uint32_t shadowAction;
+
+ t_FmPcdStatsObj *p_StatsObj;
+
+} t_FmPcdCcKeyAndNextEngineParams;
+
+typedef struct
+{
+ t_Handle p_Ad;
+ e_FmPcdEngine fmPcdEngine;
+ bool adAllocated;
+ bool isTree;
+
+ uint32_t myInfo;
+ t_List *h_CcNextNodesLst;
+ t_Handle h_AdditionalInfo;
+ t_Handle h_Node;
+} t_FmPcdModifyCcAdditionalParams;
+
+typedef struct
+{
+ t_Handle p_AdTableNew;
+ t_Handle p_KeysMatchTableNew;
+ t_Handle p_AdTableOld;
+ t_Handle p_KeysMatchTableOld;
+ uint16_t numOfKeys;
+ t_Handle h_CurrentNode;
+ uint16_t savedKeyIndex;
+ t_Handle h_NodeForAdd;
+ t_Handle h_NodeForRmv;
+ t_Handle h_ManipForRmv;
+ t_Handle h_ManipForAdd;
+ t_FmPcdStatsObj *p_StatsObjForRmv;
+#if (DPAA_VERSION >= 11)
+ t_Handle h_FrmReplicForAdd;
+ t_Handle h_FrmReplicForRmv;
+#endif /* (DPAA_VERSION >= 11) */
+ bool tree;
+
+ t_FmPcdCcKeyAndNextEngineParams keyAndNextEngineParams[CC_MAX_NUM_OF_KEYS];
+} t_FmPcdModifyCcKeyAdditionalParams;
+
+typedef struct
+{
+ t_Handle h_Manip;
+ t_Handle h_CcNode;
+} t_CcNextEngineInfo;
+
+typedef struct
+{
+ uint16_t numOfKeys;
+ uint16_t maxNumOfKeys;
+
+ bool maskSupport;
+ uint32_t keysMatchTableMaxSize;
+
+ e_FmPcdCcStatsMode statisticsMode;
+ uint32_t numOfStatsFLRs;
+ uint32_t countersArraySize;
+
+ bool isHashBucket; /**< Valid for match table node that is a bucket of a hash table only */
+ t_Handle h_MissStatsCounters; /**< Valid for hash table node and match table that is a bucket;
+ Holds the statistics counters allocated by the hash table and
+ are shared by all hash table buckets; */
+ t_Handle h_PrivMissStatsCounters; /**< Valid for match table node that is a bucket of a hash table only;
+ Holds the statistics counters that were allocated for this node
+ and replaced by the shared counters (allocated by the hash table); */
+ bool statsEnForMiss; /**< Valid for hash table node only; TRUE is statistics are currently
+ enabled for hash 'miss', FALSE otherwise; This parameter effects the
+ returned statistics count to user, statistics AD always present for 'miss'
+ for all hash buckets; */
+ bool glblMaskUpdated;
+ t_Handle p_GlblMask;
+ bool lclMask;
+ uint8_t parseCode;
+ uint8_t offset;
+ uint8_t prsArrayOffset;
+ bool ctrlFlow;
+ uint8_t owners;
+
+ uint8_t ccKeySizeAccExtraction;
+ uint8_t sizeOfExtraction;
+ uint8_t glblMaskSize;
+
+ t_Handle h_KeysMatchTable;
+ t_Handle h_AdTable;
+ t_Handle h_StatsAds;
+ t_Handle h_TmpAd;
+ t_Handle h_Ad;
+ t_Handle h_StatsFLRs;
+
+ t_List availableStatsLst;
+
+ t_List ccPrevNodesLst;
+
+ t_List ccTreeIdLst;
+ t_List ccTreesLst;
+
+ t_Handle h_FmPcd;
+ uint32_t shadowAction;
+ uint8_t userSizeOfExtraction;
+ uint8_t userOffset;
+ uint8_t kgHashShift; /* used in hash-table */
+
+ t_Handle h_Spinlock;
+
+ t_FmPcdCcKeyAndNextEngineParams keyAndNextEngineParams[CC_MAX_NUM_OF_KEYS];
+} t_FmPcdCcNode;
+
+typedef struct
+{
+ t_FmPcdCcNode *p_FmPcdCcNode;
+ bool occupied;
+ uint8_t owners;
+ volatile bool lock;
+} t_FmPcdCcNodeArray;
+
+typedef struct
+{
+ uint8_t numOfEntriesInGroup;
+ uint32_t totalBitsMask;
+ uint8_t baseGroupEntry;
+} t_FmPcdCcGroupParam;
+
+typedef struct
+{
+ t_Handle h_FmPcd;
+ uint8_t netEnvId;
+ uintptr_t ccTreeBaseAddr;
+ uint8_t numOfGrps;
+ t_FmPcdCcGroupParam fmPcdGroupParam[FM_PCD_MAX_NUM_OF_CC_GROUPS];
+ t_List fmPortsLst;
+ t_FmPcdLock *p_Lock;
+ uint8_t numOfEntries;
+ uint8_t owners;
+ t_Handle h_FmPcdCcSavedManipParams;
+ bool modifiedState;
+ uint32_t requiredAction;
+ t_Handle h_IpReassemblyManip;
+
+ t_FmPcdCcKeyAndNextEngineParams keyAndNextEngineParams[FM_PCD_MAX_NUM_OF_CC_GROUPS];
+} t_FmPcdCcTree;
+
+
+t_Error FmPcdCcNodeTreeTryLock(t_Handle h_FmPcd,t_Handle h_FmPcdCcNode, t_List *p_List);
+void FmPcdCcNodeTreeReleaseLock(t_Handle h_FmPcd, t_List *p_List);
+t_Error FmPcdUpdateCcShadow (t_FmPcd *p_FmPcd, uint32_t size, uint32_t align);
+
+
+#endif /* __FM_CC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_kg.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_kg.c
new file mode 100644
index 0000000..769a7ab
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_kg.c
@@ -0,0 +1,3287 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_kg.c
+
+ @Description FM PCD ...
+*//***************************************************************************/
+#include "std_ext.h"
+#include "error_ext.h"
+#include "string_ext.h"
+#include "debug_ext.h"
+#include "net_ext.h"
+#include "fm_port_ext.h"
+
+#include "fm_common.h"
+#include "fm_pcd.h"
+#include "fm_hc.h"
+#include "fm_pcd_ipc.h"
+#include "fm_kg.h"
+#include "fsl_fman_kg.h"
+
+
+/****************************************/
+/* static functions */
+/****************************************/
+
+static uint32_t KgHwLock(t_Handle h_FmPcdKg)
+{
+ ASSERT_COND(h_FmPcdKg);
+ return XX_LockIntrSpinlock(((t_FmPcdKg *)h_FmPcdKg)->h_HwSpinlock);
+}
+
+static void KgHwUnlock(t_Handle h_FmPcdKg, uint32_t intFlags)
+{
+ ASSERT_COND(h_FmPcdKg);
+ XX_UnlockIntrSpinlock(((t_FmPcdKg *)h_FmPcdKg)->h_HwSpinlock, intFlags);
+}
+
+static uint32_t KgSchemeLock(t_Handle h_Scheme)
+{
+ ASSERT_COND(h_Scheme);
+ return FmPcdLockSpinlock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock);
+}
+
+static void KgSchemeUnlock(t_Handle h_Scheme, uint32_t intFlags)
+{
+ ASSERT_COND(h_Scheme);
+ FmPcdUnlockSpinlock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock, intFlags);
+}
+
+static bool KgSchemeFlagTryLock(t_Handle h_Scheme)
+{
+ ASSERT_COND(h_Scheme);
+ return FmPcdLockTryLock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock);
+}
+
+static void KgSchemeFlagUnlock(t_Handle h_Scheme)
+{
+ ASSERT_COND(h_Scheme);
+ FmPcdLockUnlock(((t_FmPcdKgScheme *)h_Scheme)->p_Lock);
+}
+
+static t_Error WriteKgarWait(t_FmPcd *p_FmPcd, uint32_t fmkg_ar)
+{
+
+ struct fman_kg_regs *regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
+
+ if (fman_kg_write_ar_wait(regs, fmkg_ar))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Keygen scheme access violation"));
+
+ return E_OK;
+}
+
+static e_FmPcdKgExtractDfltSelect GetGenericSwDefault(t_FmPcdKgExtractDflt swDefaults[], uint8_t numOfSwDefaults, uint8_t code)
+{
+ int i;
+
+ switch (code)
+ {
+ case (KG_SCH_GEN_PARSE_RESULT_N_FQID):
+ case (KG_SCH_GEN_DEFAULT):
+ case (KG_SCH_GEN_NEXTHDR):
+ for (i=0 ; i<numOfSwDefaults ; i++)
+ if (swDefaults[i].type == e_FM_PCD_KG_GENERIC_NOT_FROM_DATA)
+ return swDefaults[i].dfltSelect;
+ ASSERT_COND(FALSE);
+ case (KG_SCH_GEN_SHIM1):
+ case (KG_SCH_GEN_SHIM2):
+ case (KG_SCH_GEN_IP_PID_NO_V):
+ case (KG_SCH_GEN_ETH_NO_V):
+ case (KG_SCH_GEN_SNAP_NO_V):
+ case (KG_SCH_GEN_VLAN1_NO_V):
+ case (KG_SCH_GEN_VLAN2_NO_V):
+ case (KG_SCH_GEN_ETH_TYPE_NO_V):
+ case (KG_SCH_GEN_PPP_NO_V):
+ case (KG_SCH_GEN_MPLS1_NO_V):
+ case (KG_SCH_GEN_MPLS_LAST_NO_V):
+ case (KG_SCH_GEN_L3_NO_V):
+ case (KG_SCH_GEN_IP2_NO_V):
+ case (KG_SCH_GEN_GRE_NO_V):
+ case (KG_SCH_GEN_L4_NO_V):
+ for (i=0 ; i<numOfSwDefaults ; i++)
+ if (swDefaults[i].type == e_FM_PCD_KG_GENERIC_FROM_DATA_NO_V)
+ return swDefaults[i].dfltSelect;
+
+ case (KG_SCH_GEN_START_OF_FRM):
+ case (KG_SCH_GEN_ETH):
+ case (KG_SCH_GEN_SNAP):
+ case (KG_SCH_GEN_VLAN1):
+ case (KG_SCH_GEN_VLAN2):
+ case (KG_SCH_GEN_ETH_TYPE):
+ case (KG_SCH_GEN_PPP):
+ case (KG_SCH_GEN_MPLS1):
+ case (KG_SCH_GEN_MPLS2):
+ case (KG_SCH_GEN_MPLS3):
+ case (KG_SCH_GEN_MPLS_LAST):
+ case (KG_SCH_GEN_IPV4):
+ case (KG_SCH_GEN_IPV6):
+ case (KG_SCH_GEN_IPV4_TUNNELED):
+ case (KG_SCH_GEN_IPV6_TUNNELED):
+ case (KG_SCH_GEN_MIN_ENCAP):
+ case (KG_SCH_GEN_GRE):
+ case (KG_SCH_GEN_TCP):
+ case (KG_SCH_GEN_UDP):
+ case (KG_SCH_GEN_IPSEC_AH):
+ case (KG_SCH_GEN_SCTP):
+ case (KG_SCH_GEN_DCCP):
+ case (KG_SCH_GEN_IPSEC_ESP):
+ for (i=0 ; i<numOfSwDefaults ; i++)
+ if (swDefaults[i].type == e_FM_PCD_KG_GENERIC_FROM_DATA)
+ return swDefaults[i].dfltSelect;
+ default:
+ return e_FM_PCD_KG_DFLT_ILLEGAL;
+ }
+}
+
+static uint8_t GetGenCode(e_FmPcdExtractFrom src, uint8_t *p_Offset)
+{
+ *p_Offset = 0;
+
+ switch (src)
+ {
+ case (e_FM_PCD_EXTRACT_FROM_FRAME_START):
+ return KG_SCH_GEN_START_OF_FRM;
+ case (e_FM_PCD_EXTRACT_FROM_DFLT_VALUE):
+ return KG_SCH_GEN_DEFAULT;
+ case (e_FM_PCD_EXTRACT_FROM_PARSE_RESULT):
+ return KG_SCH_GEN_PARSE_RESULT_N_FQID;
+ case (e_FM_PCD_EXTRACT_FROM_ENQ_FQID):
+ *p_Offset = 32;
+ return KG_SCH_GEN_PARSE_RESULT_N_FQID;
+ case (e_FM_PCD_EXTRACT_FROM_CURR_END_OF_PARSE):
+ return KG_SCH_GEN_NEXTHDR;
+ default:
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 'extract from' src"));
+ return 0;
+ }
+}
+
+static uint8_t GetGenHdrCode(e_NetHeaderType hdr, e_FmPcdHdrIndex hdrIndex, bool ignoreProtocolValidation)
+{
+ if (!ignoreProtocolValidation)
+ switch (hdr)
+ {
+ case (HEADER_TYPE_NONE):
+ ASSERT_COND(FALSE);
+ case (HEADER_TYPE_ETH):
+ return KG_SCH_GEN_ETH;
+ case (HEADER_TYPE_LLC_SNAP):
+ return KG_SCH_GEN_SNAP;
+ case (HEADER_TYPE_PPPoE):
+ return KG_SCH_GEN_PPP;
+ case (HEADER_TYPE_MPLS):
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_GEN_MPLS1;
+ if (hdrIndex == e_FM_PCD_HDR_INDEX_2)
+ return KG_SCH_GEN_MPLS2;
+ if (hdrIndex == e_FM_PCD_HDR_INDEX_3)
+ return KG_SCH_GEN_MPLS3;
+ if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
+ return KG_SCH_GEN_MPLS_LAST;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal MPLS header index"));
+ return 0;
+ case (HEADER_TYPE_IPv4):
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_GEN_IPV4;
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_2) || (hdrIndex == e_FM_PCD_HDR_INDEX_LAST))
+ return KG_SCH_GEN_IPV4_TUNNELED;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 header index"));
+ return 0;
+ case (HEADER_TYPE_IPv6):
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_GEN_IPV6;
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_2) || (hdrIndex == e_FM_PCD_HDR_INDEX_LAST))
+ return KG_SCH_GEN_IPV6_TUNNELED;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 header index"));
+ return 0;
+ case (HEADER_TYPE_GRE):
+ return KG_SCH_GEN_GRE;
+ case (HEADER_TYPE_TCP):
+ return KG_SCH_GEN_TCP;
+ case (HEADER_TYPE_UDP):
+ return KG_SCH_GEN_UDP;
+ case (HEADER_TYPE_IPSEC_AH):
+ return KG_SCH_GEN_IPSEC_AH;
+ case (HEADER_TYPE_IPSEC_ESP):
+ return KG_SCH_GEN_IPSEC_ESP;
+ case (HEADER_TYPE_SCTP):
+ return KG_SCH_GEN_SCTP;
+ case (HEADER_TYPE_DCCP):
+ return KG_SCH_GEN_DCCP;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ else
+ switch (hdr)
+ {
+ case (HEADER_TYPE_NONE):
+ ASSERT_COND(FALSE);
+ case (HEADER_TYPE_ETH):
+ return KG_SCH_GEN_ETH_NO_V;
+ case (HEADER_TYPE_LLC_SNAP):
+ return KG_SCH_GEN_SNAP_NO_V;
+ case (HEADER_TYPE_PPPoE):
+ return KG_SCH_GEN_PPP_NO_V;
+ case (HEADER_TYPE_MPLS):
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_GEN_MPLS1_NO_V;
+ if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
+ return KG_SCH_GEN_MPLS_LAST_NO_V;
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_2) || (hdrIndex == e_FM_PCD_HDR_INDEX_3) )
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Indexed MPLS Extraction not supported"));
+ else
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal MPLS header index"));
+ return 0;
+ case (HEADER_TYPE_IPv4):
+ case (HEADER_TYPE_IPv6):
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_GEN_L3_NO_V;
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_2) || (hdrIndex == e_FM_PCD_HDR_INDEX_LAST))
+ return KG_SCH_GEN_IP2_NO_V;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IP header index"));
+ case (HEADER_TYPE_MINENCAP):
+ return KG_SCH_GEN_IP2_NO_V;
+ case (HEADER_TYPE_USER_DEFINED_L3):
+ return KG_SCH_GEN_L3_NO_V;
+ case (HEADER_TYPE_GRE):
+ return KG_SCH_GEN_GRE_NO_V;
+ case (HEADER_TYPE_TCP):
+ case (HEADER_TYPE_UDP):
+ case (HEADER_TYPE_IPSEC_AH):
+ case (HEADER_TYPE_IPSEC_ESP):
+ case (HEADER_TYPE_SCTP):
+ case (HEADER_TYPE_DCCP):
+ return KG_SCH_GEN_L4_NO_V;
+ case (HEADER_TYPE_USER_DEFINED_SHIM1):
+ return KG_SCH_GEN_SHIM1;
+ case (HEADER_TYPE_USER_DEFINED_SHIM2):
+ return KG_SCH_GEN_SHIM2;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+}
+static t_GenericCodes GetGenFieldCode(e_NetHeaderType hdr, t_FmPcdFields field, bool ignoreProtocolValidation, e_FmPcdHdrIndex hdrIndex)
+{
+ if (!ignoreProtocolValidation)
+ switch (hdr)
+ {
+ case (HEADER_TYPE_NONE):
+ ASSERT_COND(FALSE);
+ case (HEADER_TYPE_ETH):
+ switch (field.eth)
+ {
+ case (NET_HEADER_FIELD_ETH_TYPE):
+ return KG_SCH_GEN_ETH_TYPE;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_VLAN):
+ switch (field.vlan)
+ {
+ case (NET_HEADER_FIELD_VLAN_TCI):
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_GEN_VLAN1;
+ if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
+ return KG_SCH_GEN_VLAN2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal VLAN header index"));
+ return 0;
+ }
+ case (HEADER_TYPE_MPLS):
+ case (HEADER_TYPE_IPSEC_AH):
+ case (HEADER_TYPE_IPSEC_ESP):
+ case (HEADER_TYPE_LLC_SNAP):
+ case (HEADER_TYPE_PPPoE):
+ case (HEADER_TYPE_IPv4):
+ case (HEADER_TYPE_IPv6):
+ case (HEADER_TYPE_GRE):
+ case (HEADER_TYPE_MINENCAP):
+ case (HEADER_TYPE_USER_DEFINED_L3):
+ case (HEADER_TYPE_TCP):
+ case (HEADER_TYPE_UDP):
+ case (HEADER_TYPE_SCTP):
+ case (HEADER_TYPE_DCCP):
+ case (HEADER_TYPE_USER_DEFINED_L4):
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Header not supported"));
+ return 0;
+ }
+ else
+ switch (hdr)
+ {
+ case (HEADER_TYPE_NONE):
+ ASSERT_COND(FALSE);
+ case (HEADER_TYPE_ETH):
+ switch (field.eth)
+ {
+ case (NET_HEADER_FIELD_ETH_TYPE):
+ return KG_SCH_GEN_ETH_TYPE_NO_V;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_VLAN):
+ switch (field.vlan)
+ {
+ case (NET_HEADER_FIELD_VLAN_TCI) :
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_GEN_VLAN1_NO_V;
+ if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
+ return KG_SCH_GEN_VLAN2_NO_V;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal VLAN header index"));
+ return 0;
+ }
+ case (HEADER_TYPE_IPv4):
+ switch (field.ipv4)
+ {
+ case (NET_HEADER_FIELD_IPv4_PROTO):
+ return KG_SCH_GEN_IP_PID_NO_V;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_IPv6):
+ switch (field.ipv6)
+ {
+ case (NET_HEADER_FIELD_IPv6_NEXT_HDR):
+ return KG_SCH_GEN_IP_PID_NO_V;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_MPLS):
+ case (HEADER_TYPE_LLC_SNAP):
+ case (HEADER_TYPE_PPPoE):
+ case (HEADER_TYPE_GRE):
+ case (HEADER_TYPE_MINENCAP):
+ case (HEADER_TYPE_USER_DEFINED_L3):
+ case (HEADER_TYPE_TCP):
+ case (HEADER_TYPE_UDP):
+ case (HEADER_TYPE_IPSEC_AH):
+ case (HEADER_TYPE_IPSEC_ESP):
+ case (HEADER_TYPE_SCTP):
+ case (HEADER_TYPE_DCCP):
+ case (HEADER_TYPE_USER_DEFINED_L4):
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Header not supported"));
+ return 0;
+ }
+}
+
+static t_KnownFieldsMasks GetKnownProtMask(t_FmPcd *p_FmPcd, e_NetHeaderType hdr, e_FmPcdHdrIndex index, t_FmPcdFields field)
+{
+ UNUSED(p_FmPcd);
+
+ switch (hdr)
+ {
+ case (HEADER_TYPE_NONE):
+ ASSERT_COND(FALSE);
+ case (HEADER_TYPE_ETH):
+ switch (field.eth)
+ {
+ case (NET_HEADER_FIELD_ETH_DA):
+ return KG_SCH_KN_MACDST;
+ case (NET_HEADER_FIELD_ETH_SA):
+ return KG_SCH_KN_MACSRC;
+ case (NET_HEADER_FIELD_ETH_TYPE):
+ return KG_SCH_KN_ETYPE;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_LLC_SNAP):
+ switch (field.llcSnap)
+ {
+ case (NET_HEADER_FIELD_LLC_SNAP_TYPE):
+ return KG_SCH_KN_ETYPE;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_VLAN):
+ switch (field.vlan)
+ {
+ case (NET_HEADER_FIELD_VLAN_TCI):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_KN_TCI1;
+ if (index == e_FM_PCD_HDR_INDEX_LAST)
+ return KG_SCH_KN_TCI2;
+ else
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_MPLS):
+ switch (field.mpls)
+ {
+ case (NET_HEADER_FIELD_MPLS_LABEL_STACK):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_KN_MPLS1;
+ if (index == e_FM_PCD_HDR_INDEX_2)
+ return KG_SCH_KN_MPLS2;
+ if (index == e_FM_PCD_HDR_INDEX_LAST)
+ return KG_SCH_KN_MPLS_LAST;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal MPLS index"));
+ return 0;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_IPv4):
+ switch (field.ipv4)
+ {
+ case (NET_HEADER_FIELD_IPv4_SRC_IP):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_KN_IPSRC1;
+ if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
+ return KG_SCH_KN_IPSRC2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
+ return 0;
+ case (NET_HEADER_FIELD_IPv4_DST_IP):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_KN_IPDST1;
+ if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
+ return KG_SCH_KN_IPDST2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
+ return 0;
+ case (NET_HEADER_FIELD_IPv4_PROTO):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_KN_PTYPE1;
+ if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
+ return KG_SCH_KN_PTYPE2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
+ return 0;
+ case (NET_HEADER_FIELD_IPv4_TOS):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_KN_IPTOS_TC1;
+ if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
+ return KG_SCH_KN_IPTOS_TC2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv4 index"));
+ return 0;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_IPv6):
+ switch (field.ipv6)
+ {
+ case (NET_HEADER_FIELD_IPv6_SRC_IP):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_KN_IPSRC1;
+ if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
+ return KG_SCH_KN_IPSRC2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
+ return 0;
+ case (NET_HEADER_FIELD_IPv6_DST_IP):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_KN_IPDST1;
+ if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
+ return KG_SCH_KN_IPDST2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
+ return 0;
+ case (NET_HEADER_FIELD_IPv6_NEXT_HDR):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_KN_PTYPE1;
+ if (index == e_FM_PCD_HDR_INDEX_2)
+ return KG_SCH_KN_PTYPE2;
+ if (index == e_FM_PCD_HDR_INDEX_LAST)
+#ifdef FM_KG_NO_IPPID_SUPPORT
+ if (p_FmPcd->fmRevInfo.majorRev < 6)
+ return KG_SCH_KN_PTYPE2;
+#endif /* FM_KG_NO_IPPID_SUPPORT */
+ return KG_SCH_KN_IPPID;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
+ return 0;
+ case (NET_HEADER_FIELD_IPv6_VER | NET_HEADER_FIELD_IPv6_FL | NET_HEADER_FIELD_IPv6_TC):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return (KG_SCH_KN_IPV6FL1 | KG_SCH_KN_IPTOS_TC1);
+ if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
+ return (KG_SCH_KN_IPV6FL2 | KG_SCH_KN_IPTOS_TC2);
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
+ return 0;
+ case (NET_HEADER_FIELD_IPv6_VER | NET_HEADER_FIELD_IPv6_TC):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_KN_IPTOS_TC1;
+ if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
+ return KG_SCH_KN_IPTOS_TC2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
+ return 0;
+ case (NET_HEADER_FIELD_IPv6_FL):
+ if ((index == e_FM_PCD_HDR_INDEX_NONE) || (index == e_FM_PCD_HDR_INDEX_1))
+ return KG_SCH_KN_IPV6FL1;
+ if ((index == e_FM_PCD_HDR_INDEX_2) || (index == e_FM_PCD_HDR_INDEX_LAST))
+ return KG_SCH_KN_IPV6FL2;
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal IPv6 index"));
+ return 0;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_GRE):
+ switch (field.gre)
+ {
+ case (NET_HEADER_FIELD_GRE_TYPE):
+ return KG_SCH_KN_GREPTYPE;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_MINENCAP):
+ switch (field.minencap)
+ {
+ case (NET_HEADER_FIELD_MINENCAP_SRC_IP):
+ return KG_SCH_KN_IPSRC2;
+ case (NET_HEADER_FIELD_MINENCAP_DST_IP):
+ return KG_SCH_KN_IPDST2;
+ case (NET_HEADER_FIELD_MINENCAP_TYPE):
+ return KG_SCH_KN_PTYPE2;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_TCP):
+ switch (field.tcp)
+ {
+ case (NET_HEADER_FIELD_TCP_PORT_SRC):
+ return KG_SCH_KN_L4PSRC;
+ case (NET_HEADER_FIELD_TCP_PORT_DST):
+ return KG_SCH_KN_L4PDST;
+ case (NET_HEADER_FIELD_TCP_FLAGS):
+ return KG_SCH_KN_TFLG;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_UDP):
+ switch (field.udp)
+ {
+ case (NET_HEADER_FIELD_UDP_PORT_SRC):
+ return KG_SCH_KN_L4PSRC;
+ case (NET_HEADER_FIELD_UDP_PORT_DST):
+ return KG_SCH_KN_L4PDST;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_IPSEC_AH):
+ switch (field.ipsecAh)
+ {
+ case (NET_HEADER_FIELD_IPSEC_AH_SPI):
+ return KG_SCH_KN_IPSEC_SPI;
+ case (NET_HEADER_FIELD_IPSEC_AH_NH):
+ return KG_SCH_KN_IPSEC_NH;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_IPSEC_ESP):
+ switch (field.ipsecEsp)
+ {
+ case (NET_HEADER_FIELD_IPSEC_ESP_SPI):
+ return KG_SCH_KN_IPSEC_SPI;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_SCTP):
+ switch (field.sctp)
+ {
+ case (NET_HEADER_FIELD_SCTP_PORT_SRC):
+ return KG_SCH_KN_L4PSRC;
+ case (NET_HEADER_FIELD_SCTP_PORT_DST):
+ return KG_SCH_KN_L4PDST;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_DCCP):
+ switch (field.dccp)
+ {
+ case (NET_HEADER_FIELD_DCCP_PORT_SRC):
+ return KG_SCH_KN_L4PSRC;
+ case (NET_HEADER_FIELD_DCCP_PORT_DST):
+ return KG_SCH_KN_L4PDST;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ case (HEADER_TYPE_PPPoE):
+ switch (field.pppoe)
+ {
+ case (NET_HEADER_FIELD_PPPoE_PID):
+ return KG_SCH_KN_PPPID;
+ case (NET_HEADER_FIELD_PPPoE_SID):
+ return KG_SCH_KN_PPPSID;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Extraction not supported"));
+ return 0;
+ }
+}
+
+
+static uint8_t GetKnownFieldId(uint32_t bitMask)
+{
+ uint8_t cnt = 0;
+
+ while (bitMask)
+ if (bitMask & 0x80000000)
+ break;
+ else
+ {
+ cnt++;
+ bitMask <<= 1;
+ }
+ return cnt;
+
+}
+
+static uint8_t GetExtractedOrMask(uint8_t bitOffset, bool fqid)
+{
+ uint8_t i, mask, numOfOnesToClear, walking1Mask = 1;
+
+ /* bitOffset 1-7 --> mask 0x1-0x7F */
+ if (bitOffset<8)
+ {
+ mask = 0;
+ for (i = 0 ; i < bitOffset ; i++, walking1Mask <<= 1)
+ mask |= walking1Mask;
+ }
+ else
+ {
+ mask = 0xFF;
+ numOfOnesToClear = 0;
+ if (fqid && bitOffset>24)
+ /* bitOffset 25-31 --> mask 0xFE-0x80 */
+ numOfOnesToClear = (uint8_t)(bitOffset-24);
+ else
+ /* bitOffset 9-15 --> mask 0xFE-0x80 */
+ if (!fqid && bitOffset>8)
+ numOfOnesToClear = (uint8_t)(bitOffset-8);
+ for (i = 0 ; i < numOfOnesToClear ; i++, walking1Mask <<= 1)
+ mask &= ~walking1Mask;
+ /* bitOffset 8-24 for FQID, 8 for PP --> no mask (0xFF)*/
+ }
+ return mask;
+}
+
+static void IncSchemeOwners(t_FmPcd *p_FmPcd, t_FmPcdKgInterModuleBindPortToSchemes *p_BindPort)
+{
+ t_FmPcdKg *p_FmPcdKg;
+ t_FmPcdKgScheme *p_Scheme;
+ uint32_t intFlags;
+ uint8_t relativeSchemeId;
+ int i;
+
+ p_FmPcdKg = p_FmPcd->p_FmPcdKg;
+
+ /* for each scheme - update owners counters */
+ for (i = 0; i < p_BindPort->numOfSchemes; i++)
+ {
+ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, p_BindPort->schemesIds[i]);
+ ASSERT_COND(relativeSchemeId < FM_PCD_KG_NUM_OF_SCHEMES);
+
+ p_Scheme = &p_FmPcdKg->schemes[relativeSchemeId];
+
+ /* increment owners number */
+ intFlags = KgSchemeLock(p_Scheme);
+ p_Scheme->owners++;
+ KgSchemeUnlock(p_Scheme, intFlags);
+ }
+}
+
+static void DecSchemeOwners(t_FmPcd *p_FmPcd, t_FmPcdKgInterModuleBindPortToSchemes *p_BindPort)
+{
+ t_FmPcdKg *p_FmPcdKg;
+ t_FmPcdKgScheme *p_Scheme;
+ uint32_t intFlags;
+ uint8_t relativeSchemeId;
+ int i;
+
+ p_FmPcdKg = p_FmPcd->p_FmPcdKg;
+
+ /* for each scheme - update owners counters */
+ for (i = 0; i < p_BindPort->numOfSchemes; i++)
+ {
+ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, p_BindPort->schemesIds[i]);
+ ASSERT_COND(relativeSchemeId < FM_PCD_KG_NUM_OF_SCHEMES);
+
+ p_Scheme = &p_FmPcdKg->schemes[relativeSchemeId];
+
+ /* increment owners number */
+ ASSERT_COND(p_Scheme->owners);
+ intFlags = KgSchemeLock(p_Scheme);
+ p_Scheme->owners--;
+ KgSchemeUnlock(p_Scheme, intFlags);
+ }
+}
+
+static void UpdateRequiredActionFlag(t_FmPcdKgScheme *p_Scheme, bool set)
+{
+ /* this routine is locked by the calling routine */
+ ASSERT_COND(p_Scheme);
+ ASSERT_COND(p_Scheme->valid);
+
+ if (set)
+ p_Scheme->requiredActionFlag = TRUE;
+ else
+ {
+ p_Scheme->requiredAction = 0;
+ p_Scheme->requiredActionFlag = FALSE;
+ }
+}
+
+static t_Error KgWriteSp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, uint32_t spReg, bool add)
+{
+ struct fman_kg_regs *p_KgRegs;
+
+ uint32_t tmpKgarReg = 0, intFlags;
+ t_Error err = E_OK;
+
+ /* The calling routine had locked the port, so for each port only one core can access
+ * (so we don't need a lock here) */
+
+ if (p_FmPcd->h_Hc)
+ return FmHcKgWriteSp(p_FmPcd->h_Hc, hardwarePortId, spReg, add);
+
+ p_KgRegs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
+
+ tmpKgarReg = FmPcdKgBuildReadPortSchemeBindActionReg(hardwarePortId);
+ /* lock a common KG reg */
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ err = WriteKgarWait(p_FmPcd, tmpKgarReg);
+ if (err)
+ {
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ fman_kg_write_sp(p_KgRegs, spReg, add);
+
+ tmpKgarReg = FmPcdKgBuildWritePortSchemeBindActionReg(hardwarePortId);
+
+ err = WriteKgarWait(p_FmPcd, tmpKgarReg);
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+ return err;
+}
+
+static t_Error KgWriteCpp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, uint32_t cppReg)
+{
+ struct fman_kg_regs *p_KgRegs;
+ uint32_t tmpKgarReg, intFlags;
+ t_Error err;
+
+ p_KgRegs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
+
+ if (p_FmPcd->h_Hc)
+ {
+ err = FmHcKgWriteCpp(p_FmPcd->h_Hc, hardwarePortId, cppReg);
+ return err;
+ }
+
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ fman_kg_write_cpp(p_KgRegs, cppReg);
+ tmpKgarReg = FmPcdKgBuildWritePortClsPlanBindActionReg(hardwarePortId);
+ err = WriteKgarWait(p_FmPcd, tmpKgarReg);
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+
+ return err;
+}
+
+static uint32_t BuildCppReg(t_FmPcd *p_FmPcd, uint8_t clsPlanGrpId)
+{
+ uint32_t tmpKgpeCpp;
+
+ tmpKgpeCpp = (uint32_t)(p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].baseEntry / 8);
+ tmpKgpeCpp |= (uint32_t)(((p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].sizeOfGrp / 8) - 1) << FM_KG_PE_CPP_MASK_SHIFT);
+
+ return tmpKgpeCpp;
+}
+
+static t_Error BindPortToClsPlanGrp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, uint8_t clsPlanGrpId)
+{
+ uint32_t tmpKgpeCpp = 0;
+
+ tmpKgpeCpp = BuildCppReg(p_FmPcd, clsPlanGrpId);
+ return KgWriteCpp(p_FmPcd, hardwarePortId, tmpKgpeCpp);
+}
+
+static void UnbindPortToClsPlanGrp(t_FmPcd *p_FmPcd, uint8_t hardwarePortId)
+{
+ KgWriteCpp(p_FmPcd, hardwarePortId, 0);
+}
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+static uint32_t ReadClsPlanBlockActionReg(uint8_t grpId)
+{
+ return (uint32_t)(FM_KG_KGAR_GO |
+ FM_KG_KGAR_READ |
+ FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY |
+ DUMMY_PORT_ID |
+ ((uint32_t)grpId << FM_PCD_KG_KGAR_NUM_SHIFT) |
+ FM_PCD_KG_KGAR_WSEL_MASK);
+
+ /* if we ever want to write 1 by 1, use:
+ sel = (uint8_t)(0x01 << (7- (entryId % CLS_PLAN_NUM_PER_GRP)));
+ */
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+static void PcdKgErrorException(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint32_t event,schemeIndexes = 0, index = 0;
+ struct fman_kg_regs *p_KgRegs;
+
+ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));
+ p_KgRegs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
+ fman_kg_get_event(p_KgRegs, &event, &schemeIndexes);
+
+ if (event & FM_EX_KG_DOUBLE_ECC)
+ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC);
+ if (event & FM_EX_KG_KEYSIZE_OVERFLOW)
+ {
+ if (schemeIndexes)
+ {
+ while (schemeIndexes)
+ {
+ if (schemeIndexes & 0x1)
+ p_FmPcd->f_FmPcdIndexedException(p_FmPcd->h_App,e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW, (uint16_t)(31 - index));
+ schemeIndexes >>= 1;
+ index+=1;
+ }
+ }
+ else /* this should happen only when interrupt is forced. */
+ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW);
+ }
+}
+
+static t_Error KgInitGuest(t_FmPcd *p_FmPcd)
+{
+ t_Error err = E_OK;
+ t_FmPcdIpcKgSchemesParams kgAlloc;
+ uint32_t replyLength;
+ t_FmPcdIpcReply reply;
+ t_FmPcdIpcMsg msg;
+
+ ASSERT_COND(p_FmPcd->guestId != NCSW_MASTER_ID);
+
+ /* in GUEST_PARTITION, we use the IPC */
+ memset(&reply, 0, sizeof(reply));
+ memset(&msg, 0, sizeof(msg));
+ memset(&kgAlloc, 0, sizeof(t_FmPcdIpcKgSchemesParams));
+ kgAlloc.numOfSchemes = p_FmPcd->p_FmPcdKg->numOfSchemes;
+ kgAlloc.guestId = p_FmPcd->guestId;
+ msg.msgId = FM_PCD_ALLOC_KG_SCHEMES;
+ memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc));
+ replyLength = sizeof(uint32_t) + p_FmPcd->p_FmPcdKg->numOfSchemes*sizeof(uint8_t);
+ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(kgAlloc),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if (replyLength != (sizeof(uint32_t) + p_FmPcd->p_FmPcdKg->numOfSchemes*sizeof(uint8_t)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ memcpy(p_FmPcd->p_FmPcdKg->schemesIds, (uint8_t*)(reply.replyBody),p_FmPcd->p_FmPcdKg->numOfSchemes*sizeof(uint8_t));
+
+ return (t_Error)reply.error;
+}
+
+static t_Error KgInitMaster(t_FmPcd *p_FmPcd)
+{
+ t_Error err = E_OK;
+ struct fman_kg_regs *p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
+
+ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID);
+
+ if (p_FmPcd->exceptions & FM_EX_KG_DOUBLE_ECC)
+ FmEnableRamsEcc(p_FmPcd->h_Fm);
+
+ fman_kg_init(p_Regs, p_FmPcd->exceptions, GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd));
+
+ /* register even if no interrupts enabled, to allow future enablement */
+ FmRegisterIntr(p_FmPcd->h_Fm,
+ e_FM_MOD_KG,
+ 0,
+ e_FM_INTR_TYPE_ERR,
+ PcdKgErrorException,
+ p_FmPcd);
+
+ fman_kg_enable_scheme_interrupts(p_Regs);
+
+ if (p_FmPcd->p_FmPcdKg->numOfSchemes)
+ {
+ err = FmPcdKgAllocSchemes(p_FmPcd,
+ p_FmPcd->p_FmPcdKg->numOfSchemes,
+ p_FmPcd->guestId,
+ p_FmPcd->p_FmPcdKg->schemesIds);
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ return E_OK;
+}
+
+static void ValidateSchemeSw(t_FmPcdKgScheme *p_Scheme)
+{
+ ASSERT_COND(!p_Scheme->valid);
+ if (p_Scheme->netEnvId != ILLEGAL_NETENV)
+ FmPcdIncNetEnvOwners(p_Scheme->h_FmPcd, p_Scheme->netEnvId);
+ p_Scheme->valid = TRUE;
+}
+
+static t_Error InvalidateSchemeSw(t_FmPcdKgScheme *p_Scheme)
+{
+ if (p_Scheme->owners)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Trying to delete a scheme that has ports bound to"));
+
+ if (p_Scheme->netEnvId != ILLEGAL_NETENV)
+ FmPcdDecNetEnvOwners(p_Scheme->h_FmPcd, p_Scheme->netEnvId);
+ p_Scheme->valid = FALSE;
+
+ return E_OK;
+}
+
+static t_Error BuildSchemeRegs(t_FmPcdKgScheme *p_Scheme,
+ t_FmPcdKgSchemeParams *p_SchemeParams,
+ struct fman_kg_scheme_regs *p_SchemeRegs)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)(p_Scheme->h_FmPcd);
+ uint32_t grpBits = 0;
+ uint8_t grpBase;
+ bool direct=TRUE, absolute=FALSE;
+ uint16_t profileId=0, numOfProfiles=0, relativeProfileId;
+ t_Error err = E_OK;
+ int i = 0;
+ t_NetEnvParams netEnvParams;
+ uint32_t tmpReg, fqbTmp = 0, ppcTmp = 0, selectTmp, maskTmp, knownTmp, genTmp;
+ t_FmPcdKgKeyExtractAndHashParams *p_KeyAndHash = NULL;
+ uint8_t j, curr, idx;
+ uint8_t id, shift=0, code=0, offset=0, size=0;
+ t_FmPcdExtractEntry *p_Extract = NULL;
+ t_FmPcdKgExtractedOrParams *p_ExtractOr;
+ bool generic = FALSE;
+ t_KnownFieldsMasks bitMask;
+ e_FmPcdKgExtractDfltSelect swDefault = (e_FmPcdKgExtractDfltSelect)0;
+ t_FmPcdKgSchemesExtracts *p_LocalExtractsArray;
+ uint8_t numOfSwDefaults = 0;
+ t_FmPcdKgExtractDflt swDefaults[NUM_OF_SW_DEFAULTS];
+ uint8_t currGenId = 0;
+
+ memset(swDefaults, 0, NUM_OF_SW_DEFAULTS*sizeof(t_FmPcdKgExtractDflt));
+ memset(p_SchemeRegs, 0, sizeof(struct fman_kg_scheme_regs));
+
+ if (p_SchemeParams->netEnvParams.numOfDistinctionUnits > FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("numOfDistinctionUnits should not exceed %d", FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS));
+
+ /* by netEnv parameters, get match vector */
+ if (!p_SchemeParams->alwaysDirect)
+ {
+ p_Scheme->netEnvId = FmPcdGetNetEnvId(p_SchemeParams->netEnvParams.h_NetEnv);
+ netEnvParams.netEnvId = p_Scheme->netEnvId;
+ netEnvParams.numOfDistinctionUnits = p_SchemeParams->netEnvParams.numOfDistinctionUnits;
+ memcpy(netEnvParams.unitIds, p_SchemeParams->netEnvParams.unitIds, (sizeof(uint8_t))*p_SchemeParams->netEnvParams.numOfDistinctionUnits);
+ err = PcdGetUnitsVector(p_FmPcd, &netEnvParams);
+ if (err)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+ p_Scheme->matchVector = netEnvParams.vector;
+ }
+ else
+ {
+ p_Scheme->matchVector = SCHEME_ALWAYS_DIRECT;
+ p_Scheme->netEnvId = ILLEGAL_NETENV;
+ }
+
+ if (p_SchemeParams->nextEngine == e_FM_PCD_INVALID)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next Engine of the scheme is not Valid"));
+
+ if (p_SchemeParams->bypassFqidGeneration)
+ {
+#ifdef FM_KG_NO_BYPASS_FQID_GEN
+ if ((p_FmPcd->fmRevInfo.majorRev != 4) && (p_FmPcd->fmRevInfo.majorRev < 6))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("bypassFqidGeneration."));
+#endif /* FM_KG_NO_BYPASS_FQID_GEN */
+ if (p_SchemeParams->baseFqid)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("baseFqid set for a scheme that does not generate an FQID"));
+ }
+ else
+ if (!p_SchemeParams->baseFqid)
+ DBG(WARNING, ("baseFqid is 0."));
+
+ if (p_SchemeParams->nextEngine == e_FM_PCD_PLCR)
+ {
+ direct = p_SchemeParams->kgNextEngineParams.plcrProfile.direct;
+ p_Scheme->directPlcr = direct;
+ absolute = (bool)(p_SchemeParams->kgNextEngineParams.plcrProfile.sharedProfile ? TRUE : FALSE);
+ if (!direct && absolute)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Indirect policing is not available when profile is shared."));
+
+ if (direct)
+ {
+ profileId = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.directRelativeProfileId;
+ numOfProfiles = 1;
+ }
+ else
+ {
+ profileId = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.indirectProfile.fqidOffsetRelativeProfileIdBase;
+ shift = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.indirectProfile.fqidOffsetShift;
+ numOfProfiles = p_SchemeParams->kgNextEngineParams.plcrProfile.profileSelect.indirectProfile.numOfProfiles;
+ }
+ }
+
+ if (p_SchemeParams->nextEngine == e_FM_PCD_CC)
+ {
+#ifdef FM_KG_NO_BYPASS_PLCR_PROFILE_GEN
+ if ((p_SchemeParams->kgNextEngineParams.cc.plcrNext) && (p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration))
+ {
+ if ((p_FmPcd->fmRevInfo.majorRev != 4) && (p_FmPcd->fmRevInfo.majorRev < 6))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("bypassPlcrProfileGeneration."));
+ }
+#endif /* FM_KG_NO_BYPASS_PLCR_PROFILE_GEN */
+
+ err = FmPcdCcGetGrpParams(p_SchemeParams->kgNextEngineParams.cc.h_CcTree,
+ p_SchemeParams->kgNextEngineParams.cc.grpId,
+ &grpBits,
+ &grpBase);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ p_Scheme->ccUnits = grpBits;
+
+ if ((p_SchemeParams->kgNextEngineParams.cc.plcrNext) &&
+ (!p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration))
+ {
+ if (p_SchemeParams->kgNextEngineParams.cc.plcrProfile.sharedProfile)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Shared profile may not be used after Coarse classification."));
+ absolute = FALSE;
+ direct = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.direct;
+ if (direct)
+ {
+ profileId = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.directRelativeProfileId;
+ numOfProfiles = 1;
+ }
+ else
+ {
+ profileId = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.indirectProfile.fqidOffsetRelativeProfileIdBase;
+ shift = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.indirectProfile.fqidOffsetShift;
+ numOfProfiles = p_SchemeParams->kgNextEngineParams.cc.plcrProfile.profileSelect.indirectProfile.numOfProfiles;
+ }
+ }
+ }
+
+ /* if policer is used directly after KG, or after CC */
+ if ((p_SchemeParams->nextEngine == e_FM_PCD_PLCR) ||
+ ((p_SchemeParams->nextEngine == e_FM_PCD_CC) &&
+ (p_SchemeParams->kgNextEngineParams.cc.plcrNext) &&
+ (!p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration)))
+ {
+ /* if private policer profile, it may be uninitialized yet, therefore no checks are done at this stage */
+ if (absolute)
+ {
+ /* for absolute direct policy only, */
+ relativeProfileId = profileId;
+ err = FmPcdPlcrGetAbsoluteIdByProfileParams((t_Handle)p_FmPcd,e_FM_PCD_PLCR_SHARED,NULL, relativeProfileId, &profileId);
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("Shared profile not valid offset"));
+ if (!FmPcdPlcrIsProfileValid(p_FmPcd, profileId))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Shared profile not valid."));
+ p_Scheme->relativeProfileId = profileId;
+ }
+ else
+ {
+ /* save relative profile id's for later check */
+ p_Scheme->nextRelativePlcrProfile = TRUE;
+ p_Scheme->relativeProfileId = profileId;
+ p_Scheme->numOfProfiles = numOfProfiles;
+ }
+ }
+ else
+ {
+ /* if policer is NOT going to be used after KG at all than if bypassFqidGeneration
+ is set, we do not need numOfUsedExtractedOrs and hashDistributionNumOfFqids */
+ if (p_SchemeParams->bypassFqidGeneration && p_SchemeParams->numOfUsedExtractedOrs)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,
+ ("numOfUsedExtractedOrs is set in a scheme that does not generate FQID or policer profile ID"));
+ if (p_SchemeParams->bypassFqidGeneration &&
+ p_SchemeParams->useHash &&
+ p_SchemeParams->keyExtractAndHashParams.hashDistributionNumOfFqids)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,
+ ("hashDistributionNumOfFqids is set in a scheme that does not generate FQID or policer profile ID"));
+ }
+
+ /* configure all 21 scheme registers */
+ tmpReg = KG_SCH_MODE_EN;
+ switch (p_SchemeParams->nextEngine)
+ {
+ case (e_FM_PCD_PLCR):
+ /* add to mode register - NIA */
+ tmpReg |= KG_SCH_MODE_NIA_PLCR;
+ tmpReg |= NIA_ENG_PLCR;
+ tmpReg |= (uint32_t)(p_SchemeParams->kgNextEngineParams.plcrProfile.sharedProfile ? NIA_PLCR_ABSOLUTE:0);
+ /* initialize policer profile command - */
+ /* configure kgse_ppc */
+ if (direct)
+ /* use profileId as base, other fields are 0 */
+ p_SchemeRegs->kgse_ppc = (uint32_t)profileId;
+ else
+ {
+ if (shift > MAX_PP_SHIFT)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fqidOffsetShift may not be larger than %d", MAX_PP_SHIFT));
+
+ if (!numOfProfiles || !POWER_OF_2(numOfProfiles))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfProfiles must not be 0 and must be a power of 2"));
+
+ ppcTmp = ((uint32_t)shift << KG_SCH_PP_SHIFT_HIGH_SHIFT) & KG_SCH_PP_SHIFT_HIGH;
+ ppcTmp |= ((uint32_t)shift << KG_SCH_PP_SHIFT_LOW_SHIFT) & KG_SCH_PP_SHIFT_LOW;
+ ppcTmp |= ((uint32_t)(numOfProfiles-1) << KG_SCH_PP_MASK_SHIFT);
+ ppcTmp |= (uint32_t)profileId;
+
+ p_SchemeRegs->kgse_ppc = ppcTmp;
+ }
+ break;
+ case (e_FM_PCD_CC):
+ /* mode reg - define NIA */
+ tmpReg |= (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC);
+
+ p_SchemeRegs->kgse_ccbs = grpBits;
+ tmpReg |= (uint32_t)(grpBase << KG_SCH_MODE_CCOBASE_SHIFT);
+
+ if (p_SchemeParams->kgNextEngineParams.cc.plcrNext)
+ {
+ if (!p_SchemeParams->kgNextEngineParams.cc.bypassPlcrProfileGeneration)
+ {
+ /* find out if absolute or relative */
+ if (absolute)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("It is illegal to request a shared profile in a scheme that is in a KG->CC->PLCR flow"));
+ if (direct)
+ {
+ /* mask = 0, base = directProfileId */
+ p_SchemeRegs->kgse_ppc = (uint32_t)profileId;
+ }
+ else
+ {
+ if (shift > MAX_PP_SHIFT)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fqidOffsetShift may not be larger than %d", MAX_PP_SHIFT));
+ if (!numOfProfiles || !POWER_OF_2(numOfProfiles))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfProfiles must not be 0 and must be a power of 2"));
+
+ ppcTmp = ((uint32_t)shift << KG_SCH_PP_SHIFT_HIGH_SHIFT) & KG_SCH_PP_SHIFT_HIGH;
+ ppcTmp |= ((uint32_t)shift << KG_SCH_PP_SHIFT_LOW_SHIFT) & KG_SCH_PP_SHIFT_LOW;
+ ppcTmp |= ((uint32_t)(numOfProfiles-1) << KG_SCH_PP_MASK_SHIFT);
+ ppcTmp |= (uint32_t)profileId;
+
+ p_SchemeRegs->kgse_ppc = ppcTmp;
+ }
+ }
+ else
+ ppcTmp = KG_SCH_PP_NO_GEN;
+ }
+ break;
+ case (e_FM_PCD_DONE):
+ if (p_SchemeParams->kgNextEngineParams.doneAction == e_FM_PCD_DROP_FRAME)
+ tmpReg |= GET_NIA_BMI_AC_DISCARD_FRAME(p_FmPcd);
+ else
+ tmpReg |= GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd);
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Next engine not supported"));
+ }
+ p_SchemeRegs->kgse_mode = tmpReg;
+
+ p_SchemeRegs->kgse_mv = p_Scheme->matchVector;
+
+#if (DPAA_VERSION >= 11)
+ if (p_SchemeParams->overrideStorageProfile)
+ {
+ p_SchemeRegs->kgse_om |= KG_SCH_OM_VSPE;
+
+ tmpReg = 0;
+ if (p_SchemeParams->storageProfile.direct)
+ {
+ profileId = p_SchemeParams->storageProfile.profileSelect.directRelativeProfileId;
+ shift = 0;
+ numOfProfiles = 1;
+ }
+ else
+ {
+ profileId = p_SchemeParams->storageProfile.profileSelect.indirectProfile.fqidOffsetRelativeProfileIdBase;
+ shift = p_SchemeParams->storageProfile.profileSelect.indirectProfile.fqidOffsetShift;
+ numOfProfiles = p_SchemeParams->storageProfile.profileSelect.indirectProfile.numOfProfiles;
+ }
+ if (shift > MAX_SP_SHIFT)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fqidOffsetShift may not be larger than %d", MAX_SP_SHIFT));
+
+ if (!numOfProfiles || !POWER_OF_2(numOfProfiles))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfProfiles must not be 0 and must be a power of 2"));
+
+ tmpReg = (uint32_t)shift << KG_SCH_VSP_SHIFT;
+ tmpReg |= ((uint32_t)(numOfProfiles-1) << KG_SCH_VSP_MASK_SHIFT);
+ tmpReg |= (uint32_t)profileId;
+
+
+ p_SchemeRegs->kgse_vsp = tmpReg;
+
+ p_Scheme->vspe = TRUE;
+
+ }
+ else
+ p_SchemeRegs->kgse_vsp = KG_SCH_VSP_NO_KSP_EN;
+#endif /* (DPAA_VERSION >= 11) */
+
+ if (p_SchemeParams->useHash)
+ {
+ p_KeyAndHash = &p_SchemeParams->keyExtractAndHashParams;
+
+ if (p_KeyAndHash->numOfUsedExtracts >= FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfUsedExtracts out of range"));
+
+ /* configure kgse_dv0 */
+ p_SchemeRegs->kgse_dv0 = p_KeyAndHash->privateDflt0;
+
+ /* configure kgse_dv1 */
+ p_SchemeRegs->kgse_dv1 = p_KeyAndHash->privateDflt1;
+
+ if (!p_SchemeParams->bypassFqidGeneration)
+ {
+ if (!p_KeyAndHash->hashDistributionNumOfFqids || !POWER_OF_2(p_KeyAndHash->hashDistributionNumOfFqids))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("hashDistributionNumOfFqids must not be 0 and must be a power of 2"));
+ if ((p_KeyAndHash->hashDistributionNumOfFqids-1) & p_SchemeParams->baseFqid)
+ DBG(WARNING, ("baseFqid unaligned. Distribution may result in less than hashDistributionNumOfFqids queues."));
+ }
+
+ /* configure kgse_ekdv */
+ tmpReg = 0;
+ for ( i=0 ;i<p_KeyAndHash->numOfUsedDflts ; i++)
+ {
+ switch (p_KeyAndHash->dflts[i].type)
+ {
+ case (e_FM_PCD_KG_MAC_ADDR):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_MAC_ADDR_SHIFT);
+ break;
+ case (e_FM_PCD_KG_TCI):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_TCI_SHIFT);
+ break;
+ case (e_FM_PCD_KG_ENET_TYPE):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_ENET_TYPE_SHIFT);
+ break;
+ case (e_FM_PCD_KG_PPP_SESSION_ID):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_PPP_SESSION_ID_SHIFT);
+ break;
+ case (e_FM_PCD_KG_PPP_PROTOCOL_ID):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_PPP_PROTOCOL_ID_SHIFT);
+ break;
+ case (e_FM_PCD_KG_MPLS_LABEL):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_MPLS_LABEL_SHIFT);
+ break;
+ case (e_FM_PCD_KG_IP_ADDR):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_IP_ADDR_SHIFT);
+ break;
+ case (e_FM_PCD_KG_PROTOCOL_TYPE):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_PROTOCOL_TYPE_SHIFT);
+ break;
+ case (e_FM_PCD_KG_IP_TOS_TC):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_IP_TOS_TC_SHIFT);
+ break;
+ case (e_FM_PCD_KG_IPV6_FLOW_LABEL):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_L4_PORT_SHIFT);
+ break;
+ case (e_FM_PCD_KG_IPSEC_SPI):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_IPSEC_SPI_SHIFT);
+ break;
+ case (e_FM_PCD_KG_L4_PORT):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_L4_PORT_SHIFT);
+ break;
+ case (e_FM_PCD_KG_TCP_FLAG):
+ tmpReg |= (p_KeyAndHash->dflts[i].dfltSelect << KG_SCH_DEF_TCP_FLAG_SHIFT);
+ break;
+ case (e_FM_PCD_KG_GENERIC_FROM_DATA):
+ swDefaults[numOfSwDefaults].type = e_FM_PCD_KG_GENERIC_FROM_DATA;
+ swDefaults[numOfSwDefaults].dfltSelect = p_KeyAndHash->dflts[i].dfltSelect;
+ numOfSwDefaults ++;
+ break;
+ case (e_FM_PCD_KG_GENERIC_FROM_DATA_NO_V):
+ swDefaults[numOfSwDefaults].type = e_FM_PCD_KG_GENERIC_FROM_DATA_NO_V;
+ swDefaults[numOfSwDefaults].dfltSelect = p_KeyAndHash->dflts[i].dfltSelect;
+ numOfSwDefaults ++;
+ break;
+ case (e_FM_PCD_KG_GENERIC_NOT_FROM_DATA):
+ swDefaults[numOfSwDefaults].type = e_FM_PCD_KG_GENERIC_NOT_FROM_DATA;
+ swDefaults[numOfSwDefaults].dfltSelect = p_KeyAndHash->dflts[i].dfltSelect;
+ numOfSwDefaults ++;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+ }
+ p_SchemeRegs->kgse_ekdv = tmpReg;
+
+ p_LocalExtractsArray = (t_FmPcdKgSchemesExtracts *)XX_Malloc(sizeof(t_FmPcdKgSchemesExtracts));
+ if (!p_LocalExtractsArray)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("No memory"));
+
+ /* configure kgse_ekfc and kgse_gec */
+ knownTmp = 0;
+ for ( i=0 ;i<p_KeyAndHash->numOfUsedExtracts ; i++)
+ {
+ p_Extract = &p_KeyAndHash->extractArray[i];
+ switch (p_Extract->type)
+ {
+ case (e_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO):
+ knownTmp |= KG_SCH_KN_PORT_ID;
+ /* save in driver structure */
+ p_LocalExtractsArray->extractsArray[i].id = GetKnownFieldId(KG_SCH_KN_PORT_ID);
+ p_LocalExtractsArray->extractsArray[i].known = TRUE;
+ break;
+ case (e_FM_PCD_EXTRACT_BY_HDR):
+ switch (p_Extract->extractByHdr.hdr)
+ {
+
+#ifdef FM_CAPWAP_SUPPORT
+ case (HEADER_TYPE_UDP_LITE):
+ p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP;
+ break;
+#endif
+ case (HEADER_TYPE_UDP_ENCAP_ESP):
+ switch (p_Extract->extractByHdr.type)
+ {
+ case (e_FM_PCD_EXTRACT_FROM_HDR):
+ /* case where extraction from ESP only */
+ if (p_Extract->extractByHdr.extractByHdrType.fromHdr.offset >= UDP_HEADER_SIZE)
+ {
+ p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP);
+ p_Extract->extractByHdr.extractByHdrType.fromHdr.offset -= UDP_HEADER_SIZE;
+ p_Extract->extractByHdr.ignoreProtocolValidation = TRUE;
+ }
+ else
+ {
+ p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP;
+ p_Extract->extractByHdr.ignoreProtocolValidation = FALSE;
+ }
+ break;
+ case (e_FM_PCD_EXTRACT_FROM_FIELD):
+ switch (p_Extract->extractByHdr.extractByHdrType.fromField.field.udpEncapEsp)
+ {
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC):
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_DST):
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_LEN):
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_CKSUM):
+ p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP;
+ break;
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI):
+ p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR;
+ p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP);
+ p_Extract->extractByHdr.extractByHdrType.fromField.size = p_Extract->extractByHdr.extractByHdrType.fromField.size;
+ /*p_Extract->extractByHdr.extractByHdrType.fromField.offset += ESP_SPI_OFFSET;*/
+ p_Extract->extractByHdr.ignoreProtocolValidation = TRUE;
+ break;
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SEQUENCE_NUM):
+ p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR;
+ p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP);
+ p_Extract->extractByHdr.extractByHdrType.fromField.size = p_Extract->extractByHdr.extractByHdrType.fromField.size;
+ p_Extract->extractByHdr.extractByHdrType.fromField.offset += ESP_SEQ_NUM_OFFSET;
+ p_Extract->extractByHdr.ignoreProtocolValidation = TRUE;
+ break;
+ }
+ break;
+ case (e_FM_PCD_EXTRACT_FULL_FIELD):
+ switch (p_Extract->extractByHdr.extractByHdrType.fullField.udpEncapEsp)
+ {
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC):
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_DST):
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_LEN):
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_CKSUM):
+ p_Extract->extractByHdr.hdr = HEADER_TYPE_UDP;
+ break;
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI):
+ p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR;
+ p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP);
+ p_Extract->extractByHdr.extractByHdrType.fromHdr.size = ESP_SPI_SIZE;
+ p_Extract->extractByHdr.extractByHdrType.fromHdr.offset = ESP_SPI_OFFSET;
+ p_Extract->extractByHdr.ignoreProtocolValidation = TRUE;
+ break;
+ case (NET_HEADER_FIELD_UDP_ENCAP_ESP_SEQUENCE_NUM):
+ p_Extract->extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR;
+ p_Extract->extractByHdr.hdr = FmPcdGetAliasHdr(p_FmPcd, p_Scheme->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP);
+ p_Extract->extractByHdr.extractByHdrType.fromHdr.size = ESP_SEQ_NUM_SIZE;
+ p_Extract->extractByHdr.extractByHdrType.fromHdr.offset = ESP_SEQ_NUM_OFFSET;
+ p_Extract->extractByHdr.ignoreProtocolValidation = TRUE;
+ break;
+ }
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ switch (p_Extract->extractByHdr.type)
+ {
+ case (e_FM_PCD_EXTRACT_FROM_HDR):
+ generic = TRUE;
+ /* get the header code for the generic extract */
+ code = GetGenHdrCode(p_Extract->extractByHdr.hdr, p_Extract->extractByHdr.hdrIndex, p_Extract->extractByHdr.ignoreProtocolValidation);
+ /* set generic register fields */
+ offset = p_Extract->extractByHdr.extractByHdrType.fromHdr.offset;
+ size = p_Extract->extractByHdr.extractByHdrType.fromHdr.size;
+ break;
+ case (e_FM_PCD_EXTRACT_FROM_FIELD):
+ generic = TRUE;
+ /* get the field code for the generic extract */
+ code = GetGenFieldCode(p_Extract->extractByHdr.hdr,
+ p_Extract->extractByHdr.extractByHdrType.fromField.field, p_Extract->extractByHdr.ignoreProtocolValidation,p_Extract->extractByHdr.hdrIndex);
+ offset = p_Extract->extractByHdr.extractByHdrType.fromField.offset;
+ size = p_Extract->extractByHdr.extractByHdrType.fromField.size;
+ break;
+ case (e_FM_PCD_EXTRACT_FULL_FIELD):
+ if (!p_Extract->extractByHdr.ignoreProtocolValidation)
+ {
+ /* if we have a known field for it - use it, otherwise use generic */
+ bitMask = GetKnownProtMask(p_FmPcd, p_Extract->extractByHdr.hdr, p_Extract->extractByHdr.hdrIndex,
+ p_Extract->extractByHdr.extractByHdrType.fullField);
+ if (bitMask)
+ {
+ knownTmp |= bitMask;
+ /* save in driver structure */
+ p_LocalExtractsArray->extractsArray[i].id = GetKnownFieldId(bitMask);
+ p_LocalExtractsArray->extractsArray[i].known = TRUE;
+ }
+ else
+ generic = TRUE;
+
+ }
+ else
+ generic = TRUE;
+ if (generic)
+ {
+ /* tmp - till we cover more headers under generic */
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Full header selection not supported"));
+ }
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+ break;
+ case (e_FM_PCD_EXTRACT_NON_HDR):
+ /* use generic */
+ generic = TRUE;
+ offset = 0;
+ /* get the field code for the generic extract */
+ code = GetGenCode(p_Extract->extractNonHdr.src, &offset);
+ offset += p_Extract->extractNonHdr.offset;
+ size = p_Extract->extractNonHdr.size;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+
+ if (generic)
+ {
+ /* set generic register fields */
+ if (currGenId >= FM_KG_NUM_OF_GENERIC_REGS)
+ RETURN_ERROR(MAJOR, E_FULL, ("Generic registers are fully used"));
+ if (!code)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, NO_MSG);
+
+ genTmp = KG_SCH_GEN_VALID;
+ genTmp |= (uint32_t)(code << KG_SCH_GEN_HT_SHIFT);
+ genTmp |= offset;
+ if ((size > MAX_KG_SCH_SIZE) || (size < 1))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Illegal extraction (size out of range)"));
+ genTmp |= (uint32_t)((size - 1) << KG_SCH_GEN_SIZE_SHIFT);
+ swDefault = GetGenericSwDefault(swDefaults, numOfSwDefaults, code);
+ if (swDefault == e_FM_PCD_KG_DFLT_ILLEGAL)
+ DBG(WARNING, ("No sw default configured"));
+ else
+ genTmp |= swDefault << KG_SCH_GEN_DEF_SHIFT;
+
+ genTmp |= KG_SCH_GEN_MASK;
+ p_SchemeRegs->kgse_gec[currGenId] = genTmp;
+ /* save in driver structure */
+ p_LocalExtractsArray->extractsArray[i].id = currGenId++;
+ p_LocalExtractsArray->extractsArray[i].known = FALSE;
+ generic = FALSE;
+ }
+ }
+ p_SchemeRegs->kgse_ekfc = knownTmp;
+
+ selectTmp = 0;
+ maskTmp = 0xFFFFFFFF;
+ /* configure kgse_bmch, kgse_bmcl and kgse_fqb */
+
+ if (p_KeyAndHash->numOfUsedMasks >= FM_PCD_KG_NUM_OF_EXTRACT_MASKS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Only %d masks supported", FM_PCD_KG_NUM_OF_EXTRACT_MASKS));
+ for ( i=0 ;i<p_KeyAndHash->numOfUsedMasks ; i++)
+ {
+ /* Get the relative id of the extract (for known 0-0x1f, for generic 0-7) */
+ id = p_LocalExtractsArray->extractsArray[p_KeyAndHash->masks[i].extractArrayIndex].id;
+ /* Get the shift of the select field (depending on i) */
+ GET_MASK_SEL_SHIFT(shift,i);
+ if (p_LocalExtractsArray->extractsArray[p_KeyAndHash->masks[i].extractArrayIndex].known)
+ selectTmp |= id << shift;
+ else
+ selectTmp |= (id + MASK_FOR_GENERIC_BASE_ID) << shift;
+
+ /* Get the shift of the offset field (depending on i) - may
+ be in kgse_bmch or in kgse_fqb (depending on i) */
+ GET_MASK_OFFSET_SHIFT(shift,i);
+ if (i<=1)
+ selectTmp |= p_KeyAndHash->masks[i].offset << shift;
+ else
+ fqbTmp |= p_KeyAndHash->masks[i].offset << shift;
+
+ /* Get the shift of the mask field (depending on i) */
+ GET_MASK_SHIFT(shift,i);
+ /* pass all bits */
+ maskTmp |= KG_SCH_BITMASK_MASK << shift;
+ /* clear bits that need masking */
+ maskTmp &= ~(0xFF << shift) ;
+ /* set mask bits */
+ maskTmp |= (p_KeyAndHash->masks[i].mask << shift) ;
+ }
+ p_SchemeRegs->kgse_bmch = selectTmp;
+ p_SchemeRegs->kgse_bmcl = maskTmp;
+ /* kgse_fqb will be written t the end of the routine */
+
+ /* configure kgse_hc */
+ if (p_KeyAndHash->hashShift > MAX_HASH_SHIFT)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("hashShift must not be larger than %d", MAX_HASH_SHIFT));
+ if (p_KeyAndHash->hashDistributionFqidsShift > MAX_DIST_FQID_SHIFT)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("hashDistributionFqidsShift must not be larger than %d", MAX_DIST_FQID_SHIFT));
+
+ tmpReg = 0;
+
+ tmpReg |= ((p_KeyAndHash->hashDistributionNumOfFqids - 1) << p_KeyAndHash->hashDistributionFqidsShift);
+ tmpReg |= p_KeyAndHash->hashShift << KG_SCH_HASH_CONFIG_SHIFT_SHIFT;
+
+ if (p_KeyAndHash->symmetricHash)
+ {
+ if ((!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_MACSRC) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_MACDST)) ||
+ (!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPSRC1) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPDST1)) ||
+ (!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPSRC2) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_IPDST2)) ||
+ (!!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_L4PSRC) != !!(p_SchemeRegs->kgse_ekfc & KG_SCH_KN_L4PDST)))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("symmetricHash set but src/dest extractions missing"));
+ tmpReg |= KG_SCH_HASH_CONFIG_SYM;
+ }
+ p_SchemeRegs->kgse_hc = tmpReg;
+
+ /* build the return array describing the order of the extractions */
+
+ /* the last currGenId places of the array
+ are for generic extracts that are always last.
+ We now sort for the calculation of the order of the known
+ extractions we sort the known extracts between orderedArray[0] and
+ orderedArray[p_KeyAndHash->numOfUsedExtracts - currGenId - 1].
+ for the calculation of the order of the generic extractions we use:
+ num_of_generic - currGenId
+ num_of_known - p_KeyAndHash->numOfUsedExtracts - currGenId
+ first_generic_index = num_of_known */
+ curr = 0;
+ for (i=0;i<p_KeyAndHash->numOfUsedExtracts ; i++)
+ {
+ if (p_LocalExtractsArray->extractsArray[i].known)
+ {
+ ASSERT_COND(curr<(p_KeyAndHash->numOfUsedExtracts - currGenId));
+ j = curr;
+ /* id is the extract id (port id = 0, mac src = 1 etc.). the value in the array is the original
+ index in the user's extractions array */
+ /* we compare the id of the current extract with the id of the extract in the orderedArray[j-1]
+ location */
+ while ((j > 0) && (p_LocalExtractsArray->extractsArray[i].id <
+ p_LocalExtractsArray->extractsArray[p_Scheme->orderedArray[j-1]].id))
+ {
+ p_Scheme->orderedArray[j] =
+ p_Scheme->orderedArray[j-1];
+ j--;
+ }
+ p_Scheme->orderedArray[j] = (uint8_t)i;
+ curr++;
+ }
+ else
+ {
+ /* index is first_generic_index + generic index (id) */
+ idx = (uint8_t)(p_KeyAndHash->numOfUsedExtracts - currGenId + p_LocalExtractsArray->extractsArray[i].id);
+ ASSERT_COND(idx < FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY);
+ p_Scheme->orderedArray[idx]= (uint8_t)i;
+ }
+ }
+ XX_Free(p_LocalExtractsArray);
+ p_LocalExtractsArray = NULL;
+
+ }
+ else
+ {
+ /* clear all unused registers: */
+ p_SchemeRegs->kgse_ekfc = 0;
+ p_SchemeRegs->kgse_ekdv = 0;
+ p_SchemeRegs->kgse_bmch = 0;
+ p_SchemeRegs->kgse_bmcl = 0;
+ p_SchemeRegs->kgse_hc = 0;
+ p_SchemeRegs->kgse_dv0 = 0;
+ p_SchemeRegs->kgse_dv1 = 0;
+ }
+
+ if (p_SchemeParams->bypassFqidGeneration)
+ p_SchemeRegs->kgse_hc |= KG_SCH_HASH_CONFIG_NO_FQID;
+
+ /* configure kgse_spc */
+ if ( p_SchemeParams->schemeCounter.update)
+ p_SchemeRegs->kgse_spc = p_SchemeParams->schemeCounter.value;
+
+
+ /* check that are enough generic registers */
+ if (p_SchemeParams->numOfUsedExtractedOrs + currGenId > FM_KG_NUM_OF_GENERIC_REGS)
+ RETURN_ERROR(MAJOR, E_FULL, ("Generic registers are fully used"));
+
+ /* extracted OR mask on Qid */
+ for ( i=0 ;i<p_SchemeParams->numOfUsedExtractedOrs ; i++)
+ {
+
+ p_Scheme->extractedOrs = TRUE;
+ /* configure kgse_gec[i] */
+ p_ExtractOr = &p_SchemeParams->extractedOrs[i];
+ switch (p_ExtractOr->type)
+ {
+ case (e_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO):
+ code = KG_SCH_GEN_PARSE_RESULT_N_FQID;
+ offset = 0;
+ break;
+ case (e_FM_PCD_EXTRACT_BY_HDR):
+ /* get the header code for the generic extract */
+ code = GetGenHdrCode(p_ExtractOr->extractByHdr.hdr, p_ExtractOr->extractByHdr.hdrIndex, p_ExtractOr->extractByHdr.ignoreProtocolValidation);
+ /* set generic register fields */
+ offset = p_ExtractOr->extractionOffset;
+ break;
+ case (e_FM_PCD_EXTRACT_NON_HDR):
+ /* get the field code for the generic extract */
+ offset = 0;
+ code = GetGenCode(p_ExtractOr->src, &offset);
+ offset += p_ExtractOr->extractionOffset;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+
+ /* set generic register fields */
+ if (!code)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, NO_MSG);
+ genTmp = KG_SCH_GEN_EXTRACT_TYPE | KG_SCH_GEN_VALID;
+ genTmp |= (uint32_t)(code << KG_SCH_GEN_HT_SHIFT);
+ genTmp |= offset;
+ if (!!p_ExtractOr->bitOffsetInFqid == !!p_ExtractOr->bitOffsetInPlcrProfile)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, (" extracted byte must effect either FQID or Policer profile"));
+
+ /************************************************************************************
+ bitOffsetInFqid and bitOffsetInPolicerProfile are translated to rotate parameter
+ in the following way:
+
+ Driver API and implementation:
+ ==============================
+ FQID: extracted OR byte may be shifted right 1-31 bits to effect parts of the FQID.
+ if shifted less than 8 bits, or more than 24 bits a mask is set on the bits that
+ are not overlapping FQID.
+ ------------------------
+ | FQID (24) |
+ ------------------------
+ --------
+ | | extracted OR byte
+ --------
+
+ Policer Profile: extracted OR byte may be shifted right 1-15 bits to effect parts of the
+ PP id. Unless shifted exactly 8 bits to overlap the PP id, a mask is set on the bits that
+ are not overlapping PP id.
+
+ --------
+ | PP (8) |
+ --------
+ --------
+ | | extracted OR byte
+ --------
+
+ HW implementation
+ =================
+ FQID and PP construct a 32 bit word in the way describe below. Extracted byte is located
+ as the highest byte of that word and may be rotated to effect any part os the FQID or
+ the PP.
+ ------------------------ --------
+ | FQID (24) || PP (8) |
+ ------------------------ --------
+ --------
+ | | extracted OR byte
+ --------
+
+ ************************************************************************************/
+
+ if (p_ExtractOr->bitOffsetInFqid)
+ {
+ if (p_ExtractOr->bitOffsetInFqid > MAX_KG_SCH_FQID_BIT_OFFSET )
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal extraction (bitOffsetInFqid out of range)"));
+ if (p_ExtractOr->bitOffsetInFqid<8)
+ genTmp |= (uint32_t)((p_ExtractOr->bitOffsetInFqid+24) << KG_SCH_GEN_SIZE_SHIFT);
+ else
+ genTmp |= (uint32_t)((p_ExtractOr->bitOffsetInFqid-8) << KG_SCH_GEN_SIZE_SHIFT);
+ p_ExtractOr->mask &= GetExtractedOrMask(p_ExtractOr->bitOffsetInFqid, TRUE);
+ }
+ else /* effect policer profile */
+ {
+ if (p_ExtractOr->bitOffsetInPlcrProfile > MAX_KG_SCH_PP_BIT_OFFSET )
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal extraction (bitOffsetInPlcrProfile out of range)"));
+ p_Scheme->bitOffsetInPlcrProfile = p_ExtractOr->bitOffsetInPlcrProfile;
+ genTmp |= (uint32_t)((p_ExtractOr->bitOffsetInPlcrProfile+16) << KG_SCH_GEN_SIZE_SHIFT);
+ p_ExtractOr->mask &= GetExtractedOrMask(p_ExtractOr->bitOffsetInPlcrProfile, FALSE);
+ }
+
+ genTmp |= (uint32_t)(p_ExtractOr->extractionOffset << KG_SCH_GEN_DEF_SHIFT);
+ /* clear bits that need masking */
+ genTmp &= ~KG_SCH_GEN_MASK ;
+ /* set mask bits */
+ genTmp |= (uint32_t)(p_ExtractOr->mask << KG_SCH_GEN_MASK_SHIFT);
+ p_SchemeRegs->kgse_gec[currGenId++] = genTmp;
+
+ }
+ /* clear all unused GEC registers */
+ for ( i=currGenId ;i<FM_KG_NUM_OF_GENERIC_REGS ; i++)
+ p_SchemeRegs->kgse_gec[i] = 0;
+
+ /* add base Qid for this scheme */
+ /* add configuration for kgse_fqb */
+ if (p_SchemeParams->baseFqid & ~0x00FFFFFF)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("baseFqid must be between 1 and 2^24-1"));
+
+ fqbTmp |= p_SchemeParams->baseFqid;
+ p_SchemeRegs->kgse_fqb = fqbTmp;
+
+ p_Scheme->nextEngine = p_SchemeParams->nextEngine;
+ p_Scheme->doneAction = p_SchemeParams->kgNextEngineParams.doneAction;
+
+ return E_OK;
+}
+
+
+/*****************************************************************************/
+/* Inter-module API routines */
+/*****************************************************************************/
+
+t_Error FmPcdKgBuildClsPlanGrp(t_Handle h_FmPcd, t_FmPcdKgInterModuleClsPlanGrpParams *p_Grp, t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_FmPcdKgClsPlanGrp *p_ClsPlanGrp;
+ t_FmPcdIpcKgClsPlanParams kgAlloc;
+ t_Error err = E_OK;
+ uint32_t oredVectors = 0;
+ int i, j;
+
+ /* this routine is protected by the calling routine ! */
+ if (p_Grp->numOfOptions >= FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("Too many classification plan basic options selected."));
+
+ /* find a new clsPlan group */
+ for (i = 0; i < FM_MAX_NUM_OF_PORTS; i++)
+ if (!p_FmPcd->p_FmPcdKg->clsPlanGrps[i].used)
+ break;
+ if (i == FM_MAX_NUM_OF_PORTS)
+ RETURN_ERROR(MAJOR, E_FULL,("No classification plan groups available."));
+
+ p_FmPcd->p_FmPcdKg->clsPlanGrps[i].used = TRUE;
+
+ p_Grp->clsPlanGrpId = (uint8_t)i;
+
+ if (p_Grp->numOfOptions == 0)
+ p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId = (uint8_t)i;
+
+ p_ClsPlanGrp = &p_FmPcd->p_FmPcdKg->clsPlanGrps[i];
+ p_ClsPlanGrp->netEnvId = p_Grp->netEnvId;
+ p_ClsPlanGrp->owners = 0;
+ FmPcdSetClsPlanGrpId(p_FmPcd, p_Grp->netEnvId, p_Grp->clsPlanGrpId);
+ if (p_Grp->numOfOptions != 0)
+ FmPcdIncNetEnvOwners(p_FmPcd, p_Grp->netEnvId);
+
+ p_ClsPlanGrp->sizeOfGrp = (uint16_t)(1 << p_Grp->numOfOptions);
+ /* a minimal group of 8 is required */
+ if (p_ClsPlanGrp->sizeOfGrp < CLS_PLAN_NUM_PER_GRP)
+ p_ClsPlanGrp->sizeOfGrp = CLS_PLAN_NUM_PER_GRP;
+ if (p_FmPcd->guestId == NCSW_MASTER_ID)
+ {
+ err = KgAllocClsPlanEntries(h_FmPcd, p_ClsPlanGrp->sizeOfGrp, p_FmPcd->guestId, &p_ClsPlanGrp->baseEntry);
+
+ if (err)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, NO_MSG);
+ }
+ else
+ {
+ t_FmPcdIpcMsg msg;
+ uint32_t replyLength;
+ t_FmPcdIpcReply reply;
+
+ /* in GUEST_PARTITION, we use the IPC, to also set a private driver group if required */
+ memset(&reply, 0, sizeof(reply));
+ memset(&msg, 0, sizeof(msg));
+ memset(&kgAlloc, 0, sizeof(kgAlloc));
+ kgAlloc.guestId = p_FmPcd->guestId;
+ kgAlloc.numOfClsPlanEntries = p_ClsPlanGrp->sizeOfGrp;
+ msg.msgId = FM_PCD_ALLOC_KG_CLSPLAN;
+ memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc));
+ replyLength = (sizeof(uint32_t) + sizeof(p_ClsPlanGrp->baseEntry));
+ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(kgAlloc),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (replyLength != (sizeof(uint32_t) + sizeof(p_ClsPlanGrp->baseEntry)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ if ((t_Error)reply.error != E_OK)
+ RETURN_ERROR(MINOR, (t_Error)reply.error, NO_MSG);
+
+ p_ClsPlanGrp->baseEntry = *(uint8_t*)(reply.replyBody);
+ }
+
+ /* build classification plan entries parameters */
+ p_ClsPlanSet->baseEntry = p_ClsPlanGrp->baseEntry;
+ p_ClsPlanSet->numOfClsPlanEntries = p_ClsPlanGrp->sizeOfGrp;
+
+ oredVectors = 0;
+ for (i = 0; i<p_Grp->numOfOptions; i++)
+ {
+ oredVectors |= p_Grp->optVectors[i];
+ /* save an array of used options - the indexes represent the power of 2 index */
+ p_ClsPlanGrp->optArray[i] = p_Grp->options[i];
+ }
+ /* set the classification plan relevant entries so that all bits
+ * relevant to the list of options is cleared
+ */
+ for (j = 0; j<p_ClsPlanGrp->sizeOfGrp; j++)
+ p_ClsPlanSet->vectors[j] = ~oredVectors;
+
+ for (i = 0; i<p_Grp->numOfOptions; i++)
+ {
+ /* option i got the place 2^i in the clsPlan array. all entries that
+ * have bit i set, should have the vector bit cleared. So each option
+ * has one location that it is exclusive (1,2,4,8...) and represent the
+ * presence of that option only, and other locations that represent a
+ * combination of options.
+ * e.g:
+ * If ethernet-BC is option 1 it gets entry 2 in the table. Entry 2
+ * now represents a frame with ethernet-BC header - so the bit
+ * representing ethernet-BC should be set and all other option bits
+ * should be cleared.
+ * Entries 2,3,6,7,10... also have ethernet-BC and therefore have bit
+ * vector[1] set, but they also have other bits set:
+ * 3=1+2, options 0 and 1
+ * 6=2+4, options 1 and 2
+ * 7=1+2+4, options 0,1,and 2
+ * 10=2+8, options 1 and 3
+ * etc.
+ * */
+
+ /* now for each option (i), we set their bits in all entries (j)
+ * that contain bit 2^i.
+ */
+ for (j = 0; j<p_ClsPlanGrp->sizeOfGrp; j++)
+ {
+ if (j & (1<<i))
+ p_ClsPlanSet->vectors[j] |= p_Grp->optVectors[i];
+ }
+ }
+
+ return E_OK;
+}
+
+void FmPcdKgDestroyClsPlanGrp(t_Handle h_FmPcd, uint8_t grpId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_FmPcdIpcKgClsPlanParams kgAlloc;
+ t_Error err;
+ t_FmPcdIpcMsg msg;
+ uint32_t replyLength;
+ t_FmPcdIpcReply reply;
+
+ /* check that no port is bound to this clsPlan */
+ if (p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].owners)
+ {
+ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Trying to delete a clsPlan grp that has ports bound to"));
+ return;
+ }
+
+ FmPcdSetClsPlanGrpId(p_FmPcd, p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].netEnvId, ILLEGAL_CLS_PLAN);
+
+ if (grpId == p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId)
+ p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId = ILLEGAL_CLS_PLAN;
+ else
+ FmPcdDecNetEnvOwners(p_FmPcd, p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].netEnvId);
+
+ /* free blocks */
+ if (p_FmPcd->guestId == NCSW_MASTER_ID)
+ KgFreeClsPlanEntries(h_FmPcd,
+ p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].sizeOfGrp,
+ p_FmPcd->guestId,
+ p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].baseEntry);
+ else /* in GUEST_PARTITION, we use the IPC, to also set a private driver group if required */
+ {
+ memset(&reply, 0, sizeof(reply));
+ memset(&msg, 0, sizeof(msg));
+ kgAlloc.guestId = p_FmPcd->guestId;
+ kgAlloc.numOfClsPlanEntries = p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].sizeOfGrp;
+ kgAlloc.clsPlanBase = p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId].baseEntry;
+ msg.msgId = FM_PCD_FREE_KG_CLSPLAN;
+ memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc));
+ replyLength = sizeof(uint32_t);
+ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(kgAlloc),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ {
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ return;
+ }
+ if (replyLength != sizeof(uint32_t))
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ return;
+ }
+ if ((t_Error)reply.error != E_OK)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Free KG clsPlan failed"));
+ return;
+ }
+ }
+
+ /* clear clsPlan driver structure */
+ memset(&p_FmPcd->p_FmPcdKg->clsPlanGrps[grpId], 0, sizeof(t_FmPcdKgClsPlanGrp));
+}
+
+t_Error FmPcdKgBuildBindPortToSchemes(t_Handle h_FmPcd , t_FmPcdKgInterModuleBindPortToSchemes *p_BindPort, uint32_t *p_SpReg, bool add)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t j, schemesPerPortVector = 0;
+ t_FmPcdKgScheme *p_Scheme;
+ uint8_t i, relativeSchemeId;
+ uint32_t tmp, walking1Mask;
+ uint8_t swPortIndex = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+
+ /* for each scheme */
+ for (i = 0; i<p_BindPort->numOfSchemes; i++)
+ {
+ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, p_BindPort->schemesIds[i]);
+ if (relativeSchemeId >= FM_PCD_KG_NUM_OF_SCHEMES)
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
+
+ if (add)
+ {
+ p_Scheme = &p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId];
+ if (!FmPcdKgIsSchemeValidSw(p_Scheme))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Requested scheme is invalid."));
+ /* check netEnvId of the port against the scheme netEnvId */
+ if ((p_Scheme->netEnvId != p_BindPort->netEnvId) && (p_Scheme->netEnvId != ILLEGAL_NETENV))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Port may not be bound to requested scheme - differ in netEnvId"));
+
+ /* if next engine is private port policer profile, we need to check that it is valid */
+ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, p_BindPort->hardwarePortId);
+ if (p_Scheme->nextRelativePlcrProfile)
+ {
+ for (j = 0;j<p_Scheme->numOfProfiles;j++)
+ {
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].h_FmPort);
+ if (p_Scheme->relativeProfileId+j >= p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Relative profile not in range"));
+ if (!FmPcdPlcrIsProfileValid(p_FmPcd, (uint16_t)(p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase + p_Scheme->relativeProfileId + j)))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Relative profile not valid."));
+ }
+ }
+ if (!p_BindPort->useClsPlan)
+ {
+ /* This check may be redundant as port is a assigned to the whole NetEnv */
+
+ /* if this port does not use clsPlan, it may not be bound to schemes with units that contain
+ cls plan options. Schemes that are used only directly, should not be checked.
+ it also may not be bound to schemes that go to CC with units that are options - so we OR
+ the match vector and the grpBits (= ccUnits) */
+ if ((p_Scheme->matchVector != SCHEME_ALWAYS_DIRECT) || p_Scheme->ccUnits)
+ {
+ walking1Mask = 0x80000000;
+ tmp = (p_Scheme->matchVector == SCHEME_ALWAYS_DIRECT)? 0:p_Scheme->matchVector;
+ tmp |= p_Scheme->ccUnits;
+ while (tmp)
+ {
+ if (tmp & walking1Mask)
+ {
+ tmp &= ~walking1Mask;
+ if (!PcdNetEnvIsUnitWithoutOpts(p_FmPcd, p_Scheme->netEnvId, walking1Mask))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Port (without clsPlan) may not be bound to requested scheme - uses clsPlan options"));
+ }
+ walking1Mask >>= 1;
+ }
+ }
+ }
+ }
+ /* build vector */
+ schemesPerPortVector |= 1 << (31 - p_BindPort->schemesIds[i]);
+ }
+
+ *p_SpReg = schemesPerPortVector;
+
+ return E_OK;
+}
+
+t_Error FmPcdKgBindPortToSchemes(t_Handle h_FmPcd , t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t spReg;
+ t_Error err = E_OK;
+
+ err = FmPcdKgBuildBindPortToSchemes(h_FmPcd, p_SchemeBind, &spReg, TRUE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ err = KgWriteSp(p_FmPcd, p_SchemeBind->hardwarePortId, spReg, TRUE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ IncSchemeOwners(p_FmPcd, p_SchemeBind);
+
+ return E_OK;
+}
+
+t_Error FmPcdKgUnbindPortToSchemes(t_Handle h_FmPcd, t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t spReg;
+ t_Error err = E_OK;
+
+ err = FmPcdKgBuildBindPortToSchemes(p_FmPcd, p_SchemeBind, &spReg, FALSE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ err = KgWriteSp(p_FmPcd, p_SchemeBind->hardwarePortId, spReg, FALSE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ DecSchemeOwners(p_FmPcd, p_SchemeBind);
+
+ return E_OK;
+}
+
+bool FmPcdKgIsSchemeValidSw(t_Handle h_Scheme)
+{
+ t_FmPcdKgScheme *p_Scheme = (t_FmPcdKgScheme*)h_Scheme;
+
+ return p_Scheme->valid;
+}
+
+bool KgIsSchemeAlwaysDirect(t_Handle h_FmPcd, uint8_t schemeId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ if (p_FmPcd->p_FmPcdKg->schemes[schemeId].matchVector == SCHEME_ALWAYS_DIRECT)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+t_Error FmPcdKgAllocSchemes(t_Handle h_FmPcd, uint8_t numOfSchemes, uint8_t guestId, uint8_t *p_SchemesIds)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint8_t i, j;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE);
+
+ /* This routine is issued only on master core of master partition -
+ either directly or through IPC, so no need for lock */
+
+ for (j = 0, i = 0; i < FM_PCD_KG_NUM_OF_SCHEMES && j < numOfSchemes; i++)
+ {
+ if (!p_FmPcd->p_FmPcdKg->schemesMng[i].allocated)
+ {
+ p_FmPcd->p_FmPcdKg->schemesMng[i].allocated = TRUE;
+ p_FmPcd->p_FmPcdKg->schemesMng[i].ownerId = guestId;
+ p_SchemesIds[j] = i;
+ j++;
+ }
+ }
+
+ if (j != numOfSchemes)
+ {
+ /* roll back */
+ for (j--; j; j--)
+ {
+ p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[j]].allocated = FALSE;
+ p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[j]].ownerId = 0;
+ p_SchemesIds[j] = 0;
+ }
+
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("No schemes found"));
+ }
+
+ return E_OK;
+}
+
+t_Error FmPcdKgFreeSchemes(t_Handle h_FmPcd, uint8_t numOfSchemes, uint8_t guestId, uint8_t *p_SchemesIds)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint8_t i;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE);
+
+ /* This routine is issued only on master core of master partition -
+ either directly or through IPC */
+
+ for (i = 0; i < numOfSchemes; i++)
+ {
+ if (!p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].allocated)
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Scheme was not previously allocated"));
+ }
+ if (p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].ownerId != guestId)
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Scheme is not owned by caller. "));
+ }
+ p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].allocated = FALSE;
+ p_FmPcd->p_FmPcdKg->schemesMng[p_SchemesIds[i]].ownerId = 0;
+ }
+
+ return E_OK;
+}
+
+t_Error KgAllocClsPlanEntries(t_Handle h_FmPcd, uint16_t numOfClsPlanEntries, uint8_t guestId, uint8_t *p_First)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint8_t numOfBlocks, blocksFound=0, first=0;
+ uint8_t i, j;
+
+ /* This routine is issued only on master core of master partition -
+ either directly or through IPC, so no need for lock */
+
+ if (!numOfClsPlanEntries)
+ return E_OK;
+
+ if ((numOfClsPlanEntries % CLS_PLAN_NUM_PER_GRP) || (!POWER_OF_2(numOfClsPlanEntries)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfClsPlanEntries must be a power of 2 and divisible by 8"));
+
+ numOfBlocks = (uint8_t)(numOfClsPlanEntries/CLS_PLAN_NUM_PER_GRP);
+
+ /* try to find consequent blocks */
+ first = 0;
+ for (i = 0; i < FM_PCD_MAX_NUM_OF_CLS_PLANS/CLS_PLAN_NUM_PER_GRP;)
+ {
+ if (!p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].allocated)
+ {
+ blocksFound++;
+ i++;
+ if (blocksFound == numOfBlocks)
+ break;
+ }
+ else
+ {
+ blocksFound = 0;
+ /* advance i to the next aligned address */
+ first = i = (uint8_t)(first + numOfBlocks);
+ }
+ }
+
+ if (blocksFound == numOfBlocks)
+ {
+ *p_First = (uint8_t)(first * CLS_PLAN_NUM_PER_GRP);
+ for (j = first; j < (first + numOfBlocks); j++)
+ {
+ p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[j].allocated = TRUE;
+ p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[j].ownerId = guestId;
+ }
+ return E_OK;
+ }
+ else
+ RETURN_ERROR(MINOR, E_FULL, ("No resources for clsPlan"));
+}
+
+void KgFreeClsPlanEntries(t_Handle h_FmPcd, uint16_t numOfClsPlanEntries, uint8_t guestId, uint8_t base)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint8_t numOfBlocks;
+ uint8_t i, baseBlock;
+
+#ifdef DISABLE_ASSERTIONS
+UNUSED(guestId);
+#endif /* DISABLE_ASSERTIONS */
+
+ /* This routine is issued only on master core of master partition -
+ either directly or through IPC, so no need for lock */
+
+ numOfBlocks = (uint8_t)(numOfClsPlanEntries/CLS_PLAN_NUM_PER_GRP);
+ ASSERT_COND(!(base%CLS_PLAN_NUM_PER_GRP));
+
+ baseBlock = (uint8_t)(base/CLS_PLAN_NUM_PER_GRP);
+ for (i=baseBlock;i<baseBlock+numOfBlocks;i++)
+ {
+ ASSERT_COND(p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].allocated);
+ ASSERT_COND(guestId == p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].ownerId);
+ p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].allocated = FALSE;
+ p_FmPcd->p_FmPcdKg->clsPlanBlocksMng[i].ownerId = 0;
+ }
+}
+
+void KgEnable(t_FmPcd *p_FmPcd)
+{
+ struct fman_kg_regs *p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
+
+ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));
+ fman_kg_enable(p_Regs);
+}
+
+void KgDisable(t_FmPcd *p_FmPcd)
+{
+ struct fman_kg_regs *p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
+
+ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));
+ fman_kg_disable(p_Regs);
+}
+
+void KgSetClsPlan(t_Handle h_FmPcd, t_FmPcdKgInterModuleClsPlanSet *p_Set)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ struct fman_kg_cp_regs *p_FmPcdKgPortRegs;
+ uint32_t tmpKgarReg = 0, intFlags;
+ uint16_t i, j;
+
+ /* This routine is protected by the calling routine ! */
+ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));
+ p_FmPcdKgPortRegs = &p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->clsPlanRegs;
+
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ for (i=p_Set->baseEntry;i<p_Set->baseEntry+p_Set->numOfClsPlanEntries;i+=8)
+ {
+ tmpKgarReg = FmPcdKgBuildWriteClsPlanBlockActionReg((uint8_t)(i / CLS_PLAN_NUM_PER_GRP));
+
+ for (j = i; j < i+8; j++)
+ {
+ ASSERT_COND(IN_RANGE(0, (j - p_Set->baseEntry), FM_PCD_MAX_NUM_OF_CLS_PLANS-1));
+ WRITE_UINT32(p_FmPcdKgPortRegs->kgcpe[j % CLS_PLAN_NUM_PER_GRP],p_Set->vectors[j - p_Set->baseEntry]);
+ }
+
+ if (WriteKgarWait(p_FmPcd, tmpKgarReg) != E_OK)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("WriteKgarWait FAILED"));
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+ return;
+ }
+ }
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+}
+
+t_Handle KgConfig( t_FmPcd *p_FmPcd, t_FmPcdParams *p_FmPcdParams)
+{
+ t_FmPcdKg *p_FmPcdKg;
+
+ UNUSED(p_FmPcd);
+
+ if (p_FmPcdParams->numOfSchemes > FM_PCD_KG_NUM_OF_SCHEMES)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("numOfSchemes should not exceed %d", FM_PCD_KG_NUM_OF_SCHEMES));
+ return NULL;
+ }
+
+ p_FmPcdKg = (t_FmPcdKg *)XX_Malloc(sizeof(t_FmPcdKg));
+ if (!p_FmPcdKg)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Keygen allocation FAILED"));
+ return NULL;
+ }
+ memset(p_FmPcdKg, 0, sizeof(t_FmPcdKg));
+
+
+ if (FmIsMaster(p_FmPcd->h_Fm))
+ {
+ p_FmPcdKg->p_FmPcdKgRegs = (struct fman_kg_regs *)UINT_TO_PTR(FmGetPcdKgBaseAddr(p_FmPcdParams->h_Fm));
+ p_FmPcd->exceptions |= DEFAULT_fmPcdKgErrorExceptions;
+ p_FmPcdKg->p_IndirectAccessRegs = (u_FmPcdKgIndirectAccessRegs *)&p_FmPcdKg->p_FmPcdKgRegs->fmkg_indirect[0];
+ }
+
+ p_FmPcdKg->numOfSchemes = p_FmPcdParams->numOfSchemes;
+ if ((p_FmPcd->guestId == NCSW_MASTER_ID) && !p_FmPcdKg->numOfSchemes)
+ {
+ p_FmPcdKg->numOfSchemes = FM_PCD_KG_NUM_OF_SCHEMES;
+ DBG(WARNING, ("numOfSchemes was defined 0 by user, re-defined by driver to FM_PCD_KG_NUM_OF_SCHEMES"));
+ }
+
+ p_FmPcdKg->emptyClsPlanGrpId = ILLEGAL_CLS_PLAN;
+
+ return p_FmPcdKg;
+}
+
+t_Error KgInit(t_FmPcd *p_FmPcd)
+{
+ t_Error err = E_OK;
+
+ p_FmPcd->p_FmPcdKg->h_HwSpinlock = XX_InitSpinlock();
+ if (!p_FmPcd->p_FmPcdKg->h_HwSpinlock)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM KG HW spinlock"));
+
+ if (p_FmPcd->guestId == NCSW_MASTER_ID)
+ err = KgInitMaster(p_FmPcd);
+ else
+ err = KgInitGuest(p_FmPcd);
+
+ if (err != E_OK)
+ {
+ if (p_FmPcd->p_FmPcdKg->h_HwSpinlock)
+ XX_FreeSpinlock(p_FmPcd->p_FmPcdKg->h_HwSpinlock);
+ }
+
+ return err;
+}
+
+t_Error KgFree(t_FmPcd *p_FmPcd)
+{
+ t_FmPcdIpcKgSchemesParams kgAlloc;
+ t_Error err = E_OK;
+ t_FmPcdIpcMsg msg;
+ uint32_t replyLength;
+ t_FmPcdIpcReply reply;
+
+ FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_KG, 0, e_FM_INTR_TYPE_ERR);
+
+ if (p_FmPcd->guestId == NCSW_MASTER_ID)
+ {
+ err = FmPcdKgFreeSchemes(p_FmPcd,
+ p_FmPcd->p_FmPcdKg->numOfSchemes,
+ p_FmPcd->guestId,
+ p_FmPcd->p_FmPcdKg->schemesIds);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (p_FmPcd->p_FmPcdKg->h_HwSpinlock)
+ XX_FreeSpinlock(p_FmPcd->p_FmPcdKg->h_HwSpinlock);
+
+ return E_OK;
+ }
+
+ /* guest */
+ memset(&reply, 0, sizeof(reply));
+ memset(&msg, 0, sizeof(msg));
+ kgAlloc.numOfSchemes = p_FmPcd->p_FmPcdKg->numOfSchemes;
+ kgAlloc.guestId = p_FmPcd->guestId;
+ ASSERT_COND(kgAlloc.numOfSchemes < FM_PCD_KG_NUM_OF_SCHEMES);
+ memcpy(kgAlloc.schemesIds, p_FmPcd->p_FmPcdKg->schemesIds, (sizeof(uint8_t))*kgAlloc.numOfSchemes);
+ msg.msgId = FM_PCD_FREE_KG_SCHEMES;
+ memcpy(msg.msgBody, &kgAlloc, sizeof(kgAlloc));
+ replyLength = sizeof(uint32_t);
+ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(kgAlloc),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+
+ if (p_FmPcd->p_FmPcdKg->h_HwSpinlock)
+ XX_FreeSpinlock(p_FmPcd->p_FmPcdKg->h_HwSpinlock);
+
+ return (t_Error)reply.error;
+}
+
+t_Error FmPcdKgSetOrBindToClsPlanGrp(t_Handle h_FmPcd, uint8_t hardwarePortId, uint8_t netEnvId, protocolOpt_t *p_OptArray, uint8_t *p_ClsPlanGrpId, bool *p_IsEmptyClsPlanGrp)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ t_FmPcdKgInterModuleClsPlanGrpParams grpParams, *p_GrpParams;
+ t_FmPcdKgClsPlanGrp *p_ClsPlanGrp;
+ t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet;
+ t_Error err;
+
+ /* This function is issued only from FM_PORT_SetPcd which locked all PCD modules,
+ so no need for lock here */
+
+ memset(&grpParams, 0, sizeof(grpParams));
+ grpParams.clsPlanGrpId = ILLEGAL_CLS_PLAN;
+ p_GrpParams = &grpParams;
+
+ p_GrpParams->netEnvId = netEnvId;
+
+ /* Get from the NetEnv the information of the clsPlan (can be already created,
+ * or needs to build) */
+ err = PcdGetClsPlanGrpParams(h_FmPcd, p_GrpParams);
+ if (err)
+ RETURN_ERROR(MINOR,err,NO_MSG);
+
+ if (p_GrpParams->grpExists)
+ {
+ /* this group was already updated (at least) in SW */
+ *p_ClsPlanGrpId = p_GrpParams->clsPlanGrpId;
+ }
+ else
+ {
+ p_ClsPlanSet = (t_FmPcdKgInterModuleClsPlanSet *)XX_Malloc(sizeof(t_FmPcdKgInterModuleClsPlanSet));
+ if (!p_ClsPlanSet)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Classification plan set"));
+ memset(p_ClsPlanSet, 0, sizeof(t_FmPcdKgInterModuleClsPlanSet));
+ /* Build (in SW) the clsPlan parameters, including the vectors to be written to HW */
+ err = FmPcdKgBuildClsPlanGrp(h_FmPcd, p_GrpParams, p_ClsPlanSet);
+ if (err)
+ {
+ XX_Free(p_ClsPlanSet);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+ *p_ClsPlanGrpId = p_GrpParams->clsPlanGrpId;
+
+ if (p_FmPcd->h_Hc)
+ {
+ /* write clsPlan entries to memory */
+ err = FmHcPcdKgSetClsPlan(p_FmPcd->h_Hc, p_ClsPlanSet);
+ if (err)
+ {
+ XX_Free(p_ClsPlanSet);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ }
+ else
+ /* write clsPlan entries to memory */
+ KgSetClsPlan(p_FmPcd, p_ClsPlanSet);
+
+ XX_Free(p_ClsPlanSet);
+ }
+
+ /* Set caller parameters */
+
+ /* mark if this is an empty classification group */
+ if (*p_ClsPlanGrpId == p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId)
+ *p_IsEmptyClsPlanGrp = TRUE;
+ else
+ *p_IsEmptyClsPlanGrp = FALSE;
+
+ p_ClsPlanGrp = &p_FmPcd->p_FmPcdKg->clsPlanGrps[*p_ClsPlanGrpId];
+
+ /* increment owners number */
+ p_ClsPlanGrp->owners++;
+
+ /* copy options array for port */
+ memcpy(p_OptArray, &p_FmPcd->p_FmPcdKg->clsPlanGrps[*p_ClsPlanGrpId].optArray, FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)*sizeof(protocolOpt_t));
+
+ /* bind port to the new or existing group */
+ err = BindPortToClsPlanGrp(p_FmPcd, hardwarePortId, p_GrpParams->clsPlanGrpId);
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+t_Error FmPcdKgDeleteOrUnbindPortToClsPlanGrp(t_Handle h_FmPcd, uint8_t hardwarePortId, uint8_t clsPlanGrpId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ t_FmPcdKgClsPlanGrp *p_ClsPlanGrp = &p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId];
+ t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet;
+ t_Error err;
+
+ /* This function is issued only from FM_PORT_DeletePcd which locked all PCD modules,
+ so no need for lock here */
+
+ UnbindPortToClsPlanGrp(p_FmPcd, hardwarePortId);
+
+ /* decrement owners number */
+ ASSERT_COND(p_ClsPlanGrp->owners);
+ p_ClsPlanGrp->owners--;
+
+ if (!p_ClsPlanGrp->owners)
+ {
+ if (p_FmPcd->h_Hc)
+ {
+ err = FmHcPcdKgDeleteClsPlan(p_FmPcd->h_Hc, clsPlanGrpId);
+ return err;
+ }
+ else
+ {
+ /* clear clsPlan entries in memory */
+ p_ClsPlanSet = (t_FmPcdKgInterModuleClsPlanSet *)XX_Malloc(sizeof(t_FmPcdKgInterModuleClsPlanSet));
+ if (!p_ClsPlanSet)
+ {
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Classification plan set"));
+ }
+ memset(p_ClsPlanSet, 0, sizeof(t_FmPcdKgInterModuleClsPlanSet));
+
+ p_ClsPlanSet->baseEntry = p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].baseEntry;
+ p_ClsPlanSet->numOfClsPlanEntries = p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrpId].sizeOfGrp;
+ KgSetClsPlan(p_FmPcd, p_ClsPlanSet);
+ XX_Free(p_ClsPlanSet);
+
+ FmPcdKgDestroyClsPlanGrp(h_FmPcd, clsPlanGrpId);
+ }
+ }
+ return E_OK;
+}
+
+uint32_t FmPcdKgGetRequiredAction(t_Handle h_FmPcd, uint8_t schemeId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
+
+ return p_FmPcd->p_FmPcdKg->schemes[schemeId].requiredAction;
+}
+
+uint32_t FmPcdKgGetRequiredActionFlag(t_Handle h_FmPcd, uint8_t schemeId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
+
+ return p_FmPcd->p_FmPcdKg->schemes[schemeId].requiredActionFlag;
+}
+
+bool FmPcdKgIsDirectPlcr(t_Handle h_FmPcd, uint8_t schemeId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
+
+ return p_FmPcd->p_FmPcdKg->schemes[schemeId].directPlcr;
+}
+
+
+uint16_t FmPcdKgGetRelativeProfileId(t_Handle h_FmPcd, uint8_t schemeId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
+
+ return p_FmPcd->p_FmPcdKg->schemes[schemeId].relativeProfileId;
+}
+
+bool FmPcdKgIsDistrOnPlcrProfile(t_Handle h_FmPcd, uint8_t schemeId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
+
+ if ((p_FmPcd->p_FmPcdKg->schemes[schemeId].extractedOrs &&
+ p_FmPcd->p_FmPcdKg->schemes[schemeId].bitOffsetInPlcrProfile) ||
+ p_FmPcd->p_FmPcdKg->schemes[schemeId].nextRelativePlcrProfile)
+ return TRUE;
+ else
+ return FALSE;
+
+}
+
+e_FmPcdEngine FmPcdKgGetNextEngine(t_Handle h_FmPcd, uint8_t relativeSchemeId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].valid);
+
+ return p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextEngine;
+}
+
+e_FmPcdDoneAction FmPcdKgGetDoneAction(t_Handle h_FmPcd, uint8_t schemeId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ ASSERT_COND(p_FmPcd->p_FmPcdKg->schemes[schemeId].valid);
+
+ return p_FmPcd->p_FmPcdKg->schemes[schemeId].doneAction;
+}
+
+void FmPcdKgUpdateRequiredAction(t_Handle h_Scheme, uint32_t requiredAction)
+{
+ t_FmPcdKgScheme *p_Scheme = (t_FmPcdKgScheme *)h_Scheme;
+
+ /* this routine is protected by calling routine */
+
+ ASSERT_COND(p_Scheme->valid);
+
+ p_Scheme->requiredAction |= requiredAction;
+}
+
+bool FmPcdKgHwSchemeIsValid(uint32_t schemeModeReg)
+{
+ return (bool)!!(schemeModeReg & KG_SCH_MODE_EN);
+}
+
+uint32_t FmPcdKgBuildWriteSchemeActionReg(uint8_t schemeId, bool updateCounter)
+{
+ return (uint32_t)(((uint32_t)schemeId << FM_PCD_KG_KGAR_NUM_SHIFT) |
+ FM_KG_KGAR_GO |
+ FM_KG_KGAR_WRITE |
+ FM_KG_KGAR_SEL_SCHEME_ENTRY |
+ DUMMY_PORT_ID |
+ (updateCounter ? FM_KG_KGAR_SCM_WSEL_UPDATE_CNT:0));
+}
+
+uint32_t FmPcdKgBuildReadSchemeActionReg(uint8_t schemeId)
+{
+ return (uint32_t)(((uint32_t)schemeId << FM_PCD_KG_KGAR_NUM_SHIFT) |
+ FM_KG_KGAR_GO |
+ FM_KG_KGAR_READ |
+ FM_KG_KGAR_SEL_SCHEME_ENTRY |
+ DUMMY_PORT_ID |
+ FM_KG_KGAR_SCM_WSEL_UPDATE_CNT);
+
+}
+
+uint32_t FmPcdKgBuildWriteClsPlanBlockActionReg(uint8_t grpId)
+{
+ return (uint32_t)(FM_KG_KGAR_GO |
+ FM_KG_KGAR_WRITE |
+ FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY |
+ DUMMY_PORT_ID |
+ ((uint32_t)grpId << FM_PCD_KG_KGAR_NUM_SHIFT) |
+ FM_PCD_KG_KGAR_WSEL_MASK);
+
+ /* if we ever want to write 1 by 1, use:
+ sel = (uint8_t)(0x01 << (7- (entryId % CLS_PLAN_NUM_PER_GRP)));
+ */
+}
+
+uint32_t FmPcdKgBuildWritePortSchemeBindActionReg(uint8_t hardwarePortId)
+{
+
+ return (uint32_t)(FM_KG_KGAR_GO |
+ FM_KG_KGAR_WRITE |
+ FM_PCD_KG_KGAR_SEL_PORT_ENTRY |
+ hardwarePortId |
+ FM_PCD_KG_KGAR_SEL_PORT_WSEL_SP);
+}
+
+uint32_t FmPcdKgBuildReadPortSchemeBindActionReg(uint8_t hardwarePortId)
+{
+
+ return (uint32_t)(FM_KG_KGAR_GO |
+ FM_KG_KGAR_READ |
+ FM_PCD_KG_KGAR_SEL_PORT_ENTRY |
+ hardwarePortId |
+ FM_PCD_KG_KGAR_SEL_PORT_WSEL_SP);
+}
+
+uint32_t FmPcdKgBuildWritePortClsPlanBindActionReg(uint8_t hardwarePortId)
+{
+
+ return (uint32_t)(FM_KG_KGAR_GO |
+ FM_KG_KGAR_WRITE |
+ FM_PCD_KG_KGAR_SEL_PORT_ENTRY |
+ hardwarePortId |
+ FM_PCD_KG_KGAR_SEL_PORT_WSEL_CPP);
+}
+
+uint8_t FmPcdKgGetClsPlanGrpBase(t_Handle h_FmPcd, uint8_t clsPlanGrp)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ return p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrp].baseEntry;
+}
+
+uint16_t FmPcdKgGetClsPlanGrpSize(t_Handle h_FmPcd, uint8_t clsPlanGrp)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ return p_FmPcd->p_FmPcdKg->clsPlanGrps[clsPlanGrp].sizeOfGrp;
+}
+
+
+uint8_t FmPcdKgGetSchemeId(t_Handle h_Scheme)
+{
+ return ((t_FmPcdKgScheme*)h_Scheme)->schemeId;
+
+}
+
+#if (DPAA_VERSION >= 11)
+bool FmPcdKgGetVspe(t_Handle h_Scheme)
+{
+ return ((t_FmPcdKgScheme*)h_Scheme)->vspe;
+
+}
+#endif /* (DPAA_VERSION >= 11) */
+
+uint8_t FmPcdKgGetRelativeSchemeId(t_Handle h_FmPcd, uint8_t schemeId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint8_t i;
+
+ for (i = 0;i<p_FmPcd->p_FmPcdKg->numOfSchemes;i++)
+ if (p_FmPcd->p_FmPcdKg->schemesIds[i] == schemeId)
+ return i;
+
+ if (i == p_FmPcd->p_FmPcdKg->numOfSchemes)
+ REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, ("Scheme is out of partition range"));
+
+ return FM_PCD_KG_NUM_OF_SCHEMES;
+}
+
+t_Error FmPcdKgCcGetSetParams(t_Handle h_FmPcd, t_Handle h_Scheme, uint32_t requiredAction, uint32_t value)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint8_t relativeSchemeId, physicalSchemeId;
+ uint32_t tmpKgarReg, tmpReg32 = 0, intFlags;
+ t_Error err;
+ t_FmPcdKgScheme *p_Scheme = (t_FmPcdKgScheme*)h_Scheme;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE, 0);
+
+ /* Calling function locked all PCD modules, so no need to lock here */
+
+ if (!FmPcdKgIsSchemeValidSw(h_Scheme))
+ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, ("Scheme is Invalid"));
+
+ if (p_FmPcd->h_Hc)
+ {
+ err = FmHcPcdKgCcGetSetParams(p_FmPcd->h_Hc, h_Scheme, requiredAction, value);
+
+ UpdateRequiredActionFlag(h_Scheme,TRUE);
+ FmPcdKgUpdateRequiredAction(h_Scheme,requiredAction);
+ return err;
+ }
+
+ physicalSchemeId = p_Scheme->schemeId;
+
+ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId);
+ if (relativeSchemeId >= FM_PCD_KG_NUM_OF_SCHEMES)
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
+
+ if (!p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].requiredActionFlag ||
+ !(p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].requiredAction & requiredAction))
+ {
+ if (requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA)
+ {
+ switch (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextEngine)
+ {
+ case (e_FM_PCD_DONE):
+ if (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].doneAction == e_FM_PCD_ENQ_FRAME)
+ {
+ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode);
+ ASSERT_COND(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME));
+ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, tmpReg32 | NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA);
+ /* call indirect command for scheme write */
+ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE);
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+ }
+ break;
+ case (e_FM_PCD_PLCR):
+ if (!p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].directPlcr ||
+ (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].extractedOrs &&
+ p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].bitOffsetInPlcrProfile) ||
+ p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextRelativePlcrProfile)
+ {
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("In this situation PP can not be with distribution and has to be shared"));
+ }
+ err = FmPcdPlcrCcGetSetParams(h_FmPcd, p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].relativeProfileId, requiredAction);
+ if (err)
+ {
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("in this situation the next engine after scheme can be or PLCR or ENQ_FRAME"));
+ }
+ }
+ if (requiredAction & UPDATE_KG_NIA_CC_WA)
+ {
+ if (p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId].nextEngine == e_FM_PCD_CC)
+ {
+ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode);
+ ASSERT_COND(tmpReg32 & (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC));
+ tmpReg32 &= ~NIA_FM_CTL_AC_CC;
+ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, tmpReg32 | NIA_FM_CTL_AC_PRE_CC);
+ /* call indirect command for scheme write */
+ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE);
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+ }
+ }
+ if (requiredAction & UPDATE_KG_OPT_MODE)
+ {
+ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_om, value);
+ /* call indirect command for scheme write */
+ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE);
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+ }
+ if (requiredAction & UPDATE_KG_NIA)
+ {
+ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode);
+ tmpReg32 &= ~(NIA_ENG_MASK | NIA_AC_MASK);
+ tmpReg32 |= value;
+ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, tmpReg32);
+ /* call indirect command for scheme write */
+ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE);
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+ }
+ }
+
+ UpdateRequiredActionFlag(h_Scheme, TRUE);
+ FmPcdKgUpdateRequiredAction(h_Scheme, requiredAction);
+
+ return E_OK;
+}
+/*********************** End of inter-module routines ************************/
+
+
+/****************************************/
+/* API routines */
+/****************************************/
+
+t_Handle FM_PCD_KgSchemeSet(t_Handle h_FmPcd, t_FmPcdKgSchemeParams *p_SchemeParams)
+{
+ t_FmPcd *p_FmPcd;
+ struct fman_kg_scheme_regs schemeRegs;
+ struct fman_kg_scheme_regs *p_MemRegs;
+ uint8_t i;
+ t_Error err = E_OK;
+ uint32_t tmpKgarReg;
+ uint32_t intFlags;
+ uint8_t physicalSchemeId, relativeSchemeId = 0;
+ t_FmPcdKgScheme *p_Scheme;
+
+ if (p_SchemeParams->modify)
+ {
+ p_Scheme = (t_FmPcdKgScheme *)p_SchemeParams->id.h_Scheme;
+ p_FmPcd = p_Scheme->h_FmPcd;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE, NULL);
+
+ if (!FmPcdKgIsSchemeValidSw(p_Scheme))
+ {
+ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS,
+ ("Scheme is invalid"));
+ return NULL;
+ }
+
+ if (!KgSchemeFlagTryLock(p_Scheme))
+ {
+ DBG(TRACE, ("Scheme Try Lock - BUSY"));
+ /* Signal to caller BUSY condition */
+ p_SchemeParams->id.h_Scheme = NULL;
+ return NULL;
+ }
+ }
+ else
+ {
+ p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE, NULL);
+
+ relativeSchemeId = p_SchemeParams->id.relativeSchemeId;
+ /* check that schemeId is in range */
+ if (relativeSchemeId >= p_FmPcd->p_FmPcdKg->numOfSchemes)
+ {
+ REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, ("relative-scheme-id %d!", relativeSchemeId));
+ return NULL;
+ }
+
+ p_Scheme = &p_FmPcd->p_FmPcdKg->schemes[relativeSchemeId];
+ if (FmPcdKgIsSchemeValidSw(p_Scheme))
+ {
+ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS,
+ ("Scheme id (%d)!", relativeSchemeId));
+ return NULL;
+ }
+ /* Clear all fields, scheme may have beed previously used */
+ memset(p_Scheme, 0, sizeof(t_FmPcdKgScheme));
+
+ p_Scheme->schemeId = p_FmPcd->p_FmPcdKg->schemesIds[relativeSchemeId];
+ p_Scheme->h_FmPcd = p_FmPcd;
+
+ p_Scheme->p_Lock = FmPcdAcquireLock(p_FmPcd);
+ if (!p_Scheme->p_Lock)
+ REPORT_ERROR(MAJOR, E_NOT_AVAILABLE, ("FM KG Scheme lock obj!"));
+ }
+
+ err = BuildSchemeRegs((t_Handle)p_Scheme, p_SchemeParams, &schemeRegs);
+ if (err)
+ {
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ if (p_SchemeParams->modify)
+ KgSchemeFlagUnlock(p_Scheme);
+ if (!p_SchemeParams->modify &&
+ p_Scheme->p_Lock)
+ FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock);
+ return NULL;
+ }
+
+ if (p_FmPcd->h_Hc)
+ {
+ err = FmHcPcdKgSetScheme(p_FmPcd->h_Hc,
+ (t_Handle)p_Scheme,
+ &schemeRegs,
+ p_SchemeParams->schemeCounter.update);
+ if (p_SchemeParams->modify)
+ KgSchemeFlagUnlock(p_Scheme);
+ if (err)
+ {
+ if (!p_SchemeParams->modify &&
+ p_Scheme->p_Lock)
+ FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock);
+ return NULL;
+ }
+ if (!p_SchemeParams->modify)
+ ValidateSchemeSw(p_Scheme);
+ return (t_Handle)p_Scheme;
+ }
+
+ physicalSchemeId = p_Scheme->schemeId;
+
+ /* configure all 21 scheme registers */
+ p_MemRegs = &p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs;
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ WRITE_UINT32(p_MemRegs->kgse_ppc, schemeRegs.kgse_ppc);
+ WRITE_UINT32(p_MemRegs->kgse_ccbs, schemeRegs.kgse_ccbs);
+ WRITE_UINT32(p_MemRegs->kgse_mode, schemeRegs.kgse_mode);
+ WRITE_UINT32(p_MemRegs->kgse_mv, schemeRegs.kgse_mv);
+ WRITE_UINT32(p_MemRegs->kgse_dv0, schemeRegs.kgse_dv0);
+ WRITE_UINT32(p_MemRegs->kgse_dv1, schemeRegs.kgse_dv1);
+ WRITE_UINT32(p_MemRegs->kgse_ekdv, schemeRegs.kgse_ekdv);
+ WRITE_UINT32(p_MemRegs->kgse_ekfc, schemeRegs.kgse_ekfc);
+ WRITE_UINT32(p_MemRegs->kgse_bmch, schemeRegs.kgse_bmch);
+ WRITE_UINT32(p_MemRegs->kgse_bmcl, schemeRegs.kgse_bmcl);
+ WRITE_UINT32(p_MemRegs->kgse_hc, schemeRegs.kgse_hc);
+ WRITE_UINT32(p_MemRegs->kgse_spc, schemeRegs.kgse_spc);
+ WRITE_UINT32(p_MemRegs->kgse_fqb, schemeRegs.kgse_fqb);
+ WRITE_UINT32(p_MemRegs->kgse_om, schemeRegs.kgse_om);
+ WRITE_UINT32(p_MemRegs->kgse_vsp, schemeRegs.kgse_vsp);
+ for (i=0 ; i<FM_KG_NUM_OF_GENERIC_REGS ; i++)
+ WRITE_UINT32(p_MemRegs->kgse_gec[i], schemeRegs.kgse_gec[i]);
+
+ /* call indirect command for scheme write */
+ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, p_SchemeParams->schemeCounter.update);
+
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+
+ if (!p_SchemeParams->modify)
+ ValidateSchemeSw(p_Scheme);
+ else
+ KgSchemeFlagUnlock(p_Scheme);
+
+ return (t_Handle)p_Scheme;
+}
+
+t_Error FM_PCD_KgSchemeDelete(t_Handle h_Scheme)
+{
+ t_FmPcd *p_FmPcd;
+ uint8_t physicalSchemeId;
+ uint32_t tmpKgarReg, intFlags;
+ t_Error err = E_OK;
+ t_FmPcdKgScheme *p_Scheme = (t_FmPcdKgScheme *)h_Scheme;
+
+ SANITY_CHECK_RETURN_ERROR(h_Scheme, E_INVALID_HANDLE);
+
+ p_FmPcd = (t_FmPcd*)(p_Scheme->h_FmPcd);
+
+ UpdateRequiredActionFlag(h_Scheme, FALSE);
+
+ /* check that no port is bound to this scheme */
+ err = InvalidateSchemeSw(h_Scheme);
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ if (p_FmPcd->h_Hc)
+ {
+ err = FmHcPcdKgDeleteScheme(p_FmPcd->h_Hc, h_Scheme);
+ if (p_Scheme->p_Lock)
+ FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock);
+ return err;
+ }
+
+ physicalSchemeId = ((t_FmPcdKgScheme *)h_Scheme)->schemeId;
+
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ /* clear mode register, including enable bit */
+ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode, 0);
+
+ /* call indirect command for scheme write */
+ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, FALSE);
+
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+
+ if (p_Scheme->p_Lock)
+ FmPcdReleaseLock(p_FmPcd, p_Scheme->p_Lock);
+
+ return E_OK;
+}
+
+uint32_t FM_PCD_KgSchemeGetCounter(t_Handle h_Scheme)
+{
+ t_FmPcd *p_FmPcd;
+ uint32_t tmpKgarReg, spc, intFlags;
+ uint8_t physicalSchemeId;
+
+ SANITY_CHECK_RETURN_VALUE(h_Scheme, E_INVALID_HANDLE, 0);
+
+ p_FmPcd = (t_FmPcd*)(((t_FmPcdKgScheme *)h_Scheme)->h_FmPcd);
+ if (p_FmPcd->h_Hc)
+ return FmHcPcdKgGetSchemeCounter(p_FmPcd->h_Hc, h_Scheme);
+
+ physicalSchemeId = ((t_FmPcdKgScheme *)h_Scheme)->schemeId;
+
+ if (FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId) == FM_PCD_KG_NUM_OF_SCHEMES)
+ REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
+
+ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ if (!(GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode) & KG_SCH_MODE_EN))
+ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ("Scheme is Invalid"));
+ spc = GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_spc);
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+
+ return spc;
+}
+
+t_Error FM_PCD_KgSchemeSetCounter(t_Handle h_Scheme, uint32_t value)
+{
+ t_FmPcd *p_FmPcd;
+ uint32_t tmpKgarReg, intFlags;
+ uint8_t physicalSchemeId;
+
+ SANITY_CHECK_RETURN_VALUE(h_Scheme, E_INVALID_HANDLE, 0);
+
+ p_FmPcd = (t_FmPcd*)(((t_FmPcdKgScheme *)h_Scheme)->h_FmPcd);
+
+ if (!FmPcdKgIsSchemeValidSw(h_Scheme))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Requested scheme is invalid."));
+
+ if (p_FmPcd->h_Hc)
+ return FmHcPcdKgSetSchemeCounter(p_FmPcd->h_Hc, h_Scheme, value);
+
+ physicalSchemeId = ((t_FmPcdKgScheme *)h_Scheme)->schemeId;
+ /* check that schemeId is in range */
+ if (FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId) == FM_PCD_KG_NUM_OF_SCHEMES)
+ REPORT_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
+
+ /* read specified scheme into scheme registers */
+ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg(physicalSchemeId);
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ if (!(GET_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_mode) & KG_SCH_MODE_EN))
+ {
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, ("Scheme is Invalid"));
+ }
+
+ /* change counter value */
+ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_spc, value);
+
+ /* call indirect command for scheme write */
+ tmpKgarReg = FmPcdKgBuildWriteSchemeActionReg(physicalSchemeId, TRUE);
+
+ WriteKgarWait(p_FmPcd, tmpKgarReg);
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_KgSetAdditionalDataAfterParsing(t_Handle h_FmPcd, uint8_t payloadOffset)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ struct fman_kg_regs *p_Regs;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs, E_NULL_POINTER);
+
+ p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
+ if (!FmIsMaster(p_FmPcd->h_Fm))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_KgSetAdditionalDataAfterParsing - guest mode!"));
+
+ WRITE_UINT32(p_Regs->fmkg_fdor,payloadOffset);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_KgSetDfltValue(t_Handle h_FmPcd, uint8_t valueId, uint32_t value)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ struct fman_kg_regs *p_Regs;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(((valueId == 0) || (valueId == 1)), E_INVALID_VALUE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs, E_NULL_POINTER);
+
+ p_Regs = p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs;
+
+ if (!FmIsMaster(p_FmPcd->h_Fm))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_KgSetDfltValue - guest mode!"));
+
+ if (valueId == 0)
+ WRITE_UINT32(p_Regs->fmkg_gdv0r,value);
+ else
+ WRITE_UINT32(p_Regs->fmkg_gdv1r,value);
+ return E_OK;
+}
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+t_Error FM_PCD_KgDumpRegs(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ int i = 0, j = 0;
+ uint8_t hardwarePortId = 0;
+ uint32_t tmpKgarReg, intFlags;
+ t_Error err = E_OK;
+
+ DECLARE_DUMP;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdKg, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(((p_FmPcd->guestId == NCSW_MASTER_ID) ||
+ p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs), E_INVALID_OPERATION);
+
+ DUMP_SUBTITLE(("\n"));
+ DUMP_TITLE(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs, ("FmPcdKgRegs Regs"));
+
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_gcr);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_eer);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_eeer);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_seer);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_seeer);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_gsr);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_tpc);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_serc);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_fdor);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_gdv0r);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_gdv1r);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_feer);
+ DUMP_VAR(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs,fmkg_ar);
+
+ DUMP_SUBTITLE(("\n"));
+ intFlags = KgHwLock(p_FmPcd->p_FmPcdKg);
+ for (j = 0;j<FM_PCD_KG_NUM_OF_SCHEMES;j++)
+ {
+ tmpKgarReg = FmPcdKgBuildReadSchemeActionReg((uint8_t)j);
+ if (WriteKgarWait(p_FmPcd, tmpKgarReg) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ DUMP_TITLE(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs, ("FmPcdKgIndirectAccessSchemeRegs Scheme %d Regs", j));
+
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_mode);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_ekfc);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_ekdv);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_bmch);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_bmcl);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_fqb);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_hc);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_ppc);
+
+ DUMP_TITLE(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_gec, ("kgse_gec"));
+ DUMP_SUBSTRUCT_ARRAY(i, FM_KG_NUM_OF_GENERIC_REGS)
+ {
+ DUMP_MEMORY(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs.kgse_gec[i], sizeof(uint32_t));
+ }
+
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_spc);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_dv0);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_dv1);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_ccbs);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->schemeRegs,kgse_mv);
+ }
+ DUMP_SUBTITLE(("\n"));
+
+ for (i=0;i<FM_MAX_NUM_OF_PORTS;i++)
+ {
+ SW_PORT_INDX_TO_HW_PORT_ID(hardwarePortId, i);
+
+ tmpKgarReg = FmPcdKgBuildReadPortSchemeBindActionReg(hardwarePortId);
+
+ err = WriteKgarWait(p_FmPcd, tmpKgarReg);
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ DUMP_TITLE(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->portRegs, ("FmPcdKgIndirectAccessPortRegs PCD Port %d regs", hardwarePortId));
+
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->portRegs, fmkg_pe_sp);
+ DUMP_VAR(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->portRegs, fmkg_pe_cpp);
+ }
+
+ DUMP_SUBTITLE(("\n"));
+ for (j=0;j<FM_PCD_MAX_NUM_OF_CLS_PLANS/CLS_PLAN_NUM_PER_GRP;j++)
+ {
+ DUMP_TITLE(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->clsPlanRegs, ("FmPcdKgIndirectAccessClsPlanRegs Regs group %d", j));
+ DUMP_TITLE(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->clsPlanRegs.kgcpe, ("kgcpe"));
+
+ tmpKgarReg = ReadClsPlanBlockActionReg((uint8_t)j);
+ err = WriteKgarWait(p_FmPcd, tmpKgarReg);
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ DUMP_SUBSTRUCT_ARRAY(i, 8)
+ DUMP_MEMORY(&p_FmPcd->p_FmPcdKg->p_IndirectAccessRegs->clsPlanRegs.kgcpe[i], sizeof(uint32_t));
+ }
+ KgHwUnlock(p_FmPcd->p_FmPcdKg, intFlags);
+
+ return E_OK;
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_kg.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_kg.h
new file mode 100644
index 0000000..cb7521a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_kg.h
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_kg.h
+
+ @Description FM KG private header
+*//***************************************************************************/
+#ifndef __FM_KG_H
+#define __FM_KG_H
+
+#include "std_ext.h"
+
+/***********************************************************************/
+/* Keygen defines */
+/***********************************************************************/
+/* maskes */
+#if (DPAA_VERSION >= 11)
+#define KG_SCH_VSP_SHIFT_MASK 0x0003f000
+#define KG_SCH_OM_VSPE 0x00000001
+#define KG_SCH_VSP_NO_KSP_EN 0x80000000
+
+#define MAX_SP_SHIFT 23
+#define KG_SCH_VSP_MASK_SHIFT 12
+#define KG_SCH_VSP_SHIFT 24
+#endif /* (DPAA_VERSION >= 11) */
+
+typedef uint32_t t_KnownFieldsMasks;
+#define KG_SCH_KN_PORT_ID 0x80000000
+#define KG_SCH_KN_MACDST 0x40000000
+#define KG_SCH_KN_MACSRC 0x20000000
+#define KG_SCH_KN_TCI1 0x10000000
+#define KG_SCH_KN_TCI2 0x08000000
+#define KG_SCH_KN_ETYPE 0x04000000
+#define KG_SCH_KN_PPPSID 0x02000000
+#define KG_SCH_KN_PPPID 0x01000000
+#define KG_SCH_KN_MPLS1 0x00800000
+#define KG_SCH_KN_MPLS2 0x00400000
+#define KG_SCH_KN_MPLS_LAST 0x00200000
+#define KG_SCH_KN_IPSRC1 0x00100000
+#define KG_SCH_KN_IPDST1 0x00080000
+#define KG_SCH_KN_PTYPE1 0x00040000
+#define KG_SCH_KN_IPTOS_TC1 0x00020000
+#define KG_SCH_KN_IPV6FL1 0x00010000
+#define KG_SCH_KN_IPSRC2 0x00008000
+#define KG_SCH_KN_IPDST2 0x00004000
+#define KG_SCH_KN_PTYPE2 0x00002000
+#define KG_SCH_KN_IPTOS_TC2 0x00001000
+#define KG_SCH_KN_IPV6FL2 0x00000800
+#define KG_SCH_KN_GREPTYPE 0x00000400
+#define KG_SCH_KN_IPSEC_SPI 0x00000200
+#define KG_SCH_KN_IPSEC_NH 0x00000100
+#define KG_SCH_KN_IPPID 0x00000080
+#define KG_SCH_KN_L4PSRC 0x00000004
+#define KG_SCH_KN_L4PDST 0x00000002
+#define KG_SCH_KN_TFLG 0x00000001
+
+typedef uint8_t t_GenericCodes;
+#define KG_SCH_GEN_SHIM1 0x70
+#define KG_SCH_GEN_DEFAULT 0x10
+#define KG_SCH_GEN_PARSE_RESULT_N_FQID 0x20
+#define KG_SCH_GEN_START_OF_FRM 0x40
+#define KG_SCH_GEN_SHIM2 0x71
+#define KG_SCH_GEN_IP_PID_NO_V 0x72
+#define KG_SCH_GEN_ETH 0x03
+#define KG_SCH_GEN_ETH_NO_V 0x73
+#define KG_SCH_GEN_SNAP 0x04
+#define KG_SCH_GEN_SNAP_NO_V 0x74
+#define KG_SCH_GEN_VLAN1 0x05
+#define KG_SCH_GEN_VLAN1_NO_V 0x75
+#define KG_SCH_GEN_VLAN2 0x06
+#define KG_SCH_GEN_VLAN2_NO_V 0x76
+#define KG_SCH_GEN_ETH_TYPE 0x07
+#define KG_SCH_GEN_ETH_TYPE_NO_V 0x77
+#define KG_SCH_GEN_PPP 0x08
+#define KG_SCH_GEN_PPP_NO_V 0x78
+#define KG_SCH_GEN_MPLS1 0x09
+#define KG_SCH_GEN_MPLS2 0x19
+#define KG_SCH_GEN_MPLS3 0x29
+#define KG_SCH_GEN_MPLS1_NO_V 0x79
+#define KG_SCH_GEN_MPLS_LAST 0x0a
+#define KG_SCH_GEN_MPLS_LAST_NO_V 0x7a
+#define KG_SCH_GEN_IPV4 0x0b
+#define KG_SCH_GEN_IPV6 0x1b
+#define KG_SCH_GEN_L3_NO_V 0x7b
+#define KG_SCH_GEN_IPV4_TUNNELED 0x0c
+#define KG_SCH_GEN_IPV6_TUNNELED 0x1c
+#define KG_SCH_GEN_MIN_ENCAP 0x2c
+#define KG_SCH_GEN_IP2_NO_V 0x7c
+#define KG_SCH_GEN_GRE 0x0d
+#define KG_SCH_GEN_GRE_NO_V 0x7d
+#define KG_SCH_GEN_TCP 0x0e
+#define KG_SCH_GEN_UDP 0x1e
+#define KG_SCH_GEN_IPSEC_AH 0x2e
+#define KG_SCH_GEN_SCTP 0x3e
+#define KG_SCH_GEN_DCCP 0x4e
+#define KG_SCH_GEN_IPSEC_ESP 0x6e
+#define KG_SCH_GEN_L4_NO_V 0x7e
+#define KG_SCH_GEN_NEXTHDR 0x7f
+/* shifts */
+#define KG_SCH_PP_SHIFT_HIGH_SHIFT 27
+#define KG_SCH_PP_SHIFT_LOW_SHIFT 12
+#define KG_SCH_PP_MASK_SHIFT 16
+#define KG_SCH_MODE_CCOBASE_SHIFT 24
+#define KG_SCH_DEF_MAC_ADDR_SHIFT 30
+#define KG_SCH_DEF_TCI_SHIFT 28
+#define KG_SCH_DEF_ENET_TYPE_SHIFT 26
+#define KG_SCH_DEF_PPP_SESSION_ID_SHIFT 24
+#define KG_SCH_DEF_PPP_PROTOCOL_ID_SHIFT 22
+#define KG_SCH_DEF_MPLS_LABEL_SHIFT 20
+#define KG_SCH_DEF_IP_ADDR_SHIFT 18
+#define KG_SCH_DEF_PROTOCOL_TYPE_SHIFT 16
+#define KG_SCH_DEF_IP_TOS_TC_SHIFT 14
+#define KG_SCH_DEF_IPV6_FLOW_LABEL_SHIFT 12
+#define KG_SCH_DEF_IPSEC_SPI_SHIFT 10
+#define KG_SCH_DEF_L4_PORT_SHIFT 8
+#define KG_SCH_DEF_TCP_FLAG_SHIFT 6
+#define KG_SCH_HASH_CONFIG_SHIFT_SHIFT 24
+#define KG_SCH_GEN_MASK_SHIFT 16
+#define KG_SCH_GEN_HT_SHIFT 8
+#define KG_SCH_GEN_SIZE_SHIFT 24
+#define KG_SCH_GEN_DEF_SHIFT 29
+#define FM_PCD_KG_KGAR_NUM_SHIFT 16
+
+/* others */
+#define NUM_OF_SW_DEFAULTS 3
+#define MAX_PP_SHIFT 23
+#define MAX_KG_SCH_SIZE 16
+#define MASK_FOR_GENERIC_BASE_ID 0x20
+#define MAX_HASH_SHIFT 40
+#define MAX_KG_SCH_FQID_BIT_OFFSET 31
+#define MAX_KG_SCH_PP_BIT_OFFSET 15
+#define MAX_DIST_FQID_SHIFT 23
+
+#define GET_MASK_SEL_SHIFT(shift,i) \
+switch (i) { \
+ case (0):shift = 26;break; \
+ case (1):shift = 20;break; \
+ case (2):shift = 10;break; \
+ case (3):shift = 4;break; \
+ default: \
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); \
+}
+
+#define GET_MASK_OFFSET_SHIFT(shift,i) \
+switch (i) { \
+ case (0):shift = 16;break; \
+ case (1):shift = 0;break; \
+ case (2):shift = 28;break; \
+ case (3):shift = 24;break; \
+ default: \
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); \
+}
+
+#define GET_MASK_SHIFT(shift,i) \
+switch (i) { \
+ case (0):shift = 24;break; \
+ case (1):shift = 16;break; \
+ case (2):shift = 8;break; \
+ case (3):shift = 0;break; \
+ default: \
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG); \
+}
+
+/***********************************************************************/
+/* Keygen defines */
+/***********************************************************************/
+
+#define KG_DOUBLE_MEANING_REGS_OFFSET 0x100
+#define NO_VALIDATION 0x70
+#define KG_ACTION_REG_TO 1024
+#define KG_MAX_PROFILE 255
+#define SCHEME_ALWAYS_DIRECT 0xFFFFFFFF
+
+
+#endif /* __FM_KG_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_manip.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_manip.c
new file mode 100644
index 0000000..1027783
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_manip.c
@@ -0,0 +1,4218 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_manip.c
+
+ @Description FM PCD manip ...
+*//***************************************************************************/
+#include "std_ext.h"
+#include "error_ext.h"
+#include "string_ext.h"
+#include "debug_ext.h"
+#include "fm_pcd_ext.h"
+#include "fm_port_ext.h"
+#include "fm_muram_ext.h"
+#include "memcpy_ext.h"
+
+#include "fm_common.h"
+#include "fm_hc.h"
+#include "fm_manip.h"
+
+
+/****************************************/
+/* static functions */
+/****************************************/
+static t_Handle GetManipInfo(t_FmPcdManip *p_Manip, e_ManipInfo manipInfo)
+{
+ t_FmPcdManip *p_CurManip = p_Manip;
+
+ if (!MANIP_IS_UNIFIED(p_Manip))
+ p_CurManip = p_Manip;
+ else
+ {
+ /* go to first unified */
+ while (MANIP_IS_UNIFIED_NON_FIRST(p_CurManip))
+ p_CurManip = p_CurManip->h_PrevManip;
+ }
+
+ switch (manipInfo)
+ {
+ case (e_MANIP_HMCT):
+ return p_CurManip->p_Hmct;
+ case (e_MANIP_HMTD):
+ return p_CurManip->h_Ad;
+ case (e_MANIP_HANDLER_TABLE_OWNER):
+ return (t_Handle)p_CurManip;
+ default:
+ return NULL;
+ }
+}
+static uint16_t GetHmctSize(t_FmPcdManip *p_Manip)
+{
+ uint16_t size = 0;
+ t_FmPcdManip *p_CurManip = p_Manip;
+
+ if (!MANIP_IS_UNIFIED(p_Manip))
+ return p_Manip->tableSize;
+
+ /* accumulate sizes, starting with the first node */
+ while (MANIP_IS_UNIFIED_NON_FIRST(p_CurManip))
+ p_CurManip = p_CurManip->h_PrevManip;
+
+ while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip))
+ {
+ size += p_CurManip->tableSize;
+ p_CurManip = (t_FmPcdManip *)p_CurManip->h_NextManip;
+ }
+ size += p_CurManip->tableSize; /* add last size */
+
+ return(size);
+}
+static uint16_t GetDataSize(t_FmPcdManip *p_Manip)
+{
+ uint16_t size = 0;
+ t_FmPcdManip *p_CurManip = p_Manip;
+
+ if (!MANIP_IS_UNIFIED(p_Manip))
+ return p_Manip->dataSize;
+
+ /* accumulate sizes, starting with the first node */
+ while (MANIP_IS_UNIFIED_NON_FIRST(p_CurManip))
+ p_CurManip = p_CurManip->h_PrevManip;
+
+ while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip))
+ {
+ size += p_CurManip->dataSize;
+ p_CurManip = (t_FmPcdManip *)p_CurManip->h_NextManip;
+ }
+ size += p_CurManip->dataSize; /* add last size */
+
+ return(size);
+}
+static t_Error CalculateTableSize(t_FmPcdManipParams *p_FmPcdManipParams, uint16_t *p_TableSize, uint8_t *p_DataSize)
+{
+ uint8_t localDataSize, remain, tableSize = 0, dataSize = 0;
+
+ if (p_FmPcdManipParams->u.hdr.rmv)
+ {
+ switch (p_FmPcdManipParams->u.hdr.rmvParams.type){
+ case (e_FM_PCD_MANIP_RMV_GENERIC):
+ case (e_FM_PCD_MANIP_RMV_BY_HDR):
+ /* As long as the only rmv command is the L2, no check on type is required */
+ tableSize += HMCD_BASIC_SIZE;
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown rmvParams.type"));
+ }
+ }
+
+ if (p_FmPcdManipParams->u.hdr.insrt)
+ {
+ switch (p_FmPcdManipParams->u.hdr.insrtParams.type){
+ case (e_FM_PCD_MANIP_INSRT_GENERIC):
+ remain = (uint8_t)(p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size % 4);
+ if (remain)
+ localDataSize = (uint8_t)(p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size + 4 - remain);
+ else
+ localDataSize = p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size;
+ tableSize += (uint8_t)(HMCD_BASIC_SIZE + localDataSize);
+ break;
+ case (e_FM_PCD_MANIP_INSRT_BY_HDR):
+ /* As long as the only insert command is the internal L2, no check on type is required */
+ tableSize += HMCD_BASIC_SIZE+HMCD_PTR_SIZE;
+ if (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.type == e_FM_PCD_MANIP_INSRT_BY_HDR_SPECIFIC_L2)
+ switch (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.specificL2)
+ {
+ case (e_FM_PCD_MANIP_HDR_INSRT_MPLS):
+ dataSize += p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.size;
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+ }
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown insrtParams.type"));
+ }
+ }
+ if (p_FmPcdManipParams->u.hdr.fieldUpdate)
+ {
+ switch (p_FmPcdManipParams->u.hdr.fieldUpdateParams.type){
+ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN):
+ tableSize += HMCD_BASIC_SIZE;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType ==
+ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN)
+ {
+ tableSize += HMCD_PTR_SIZE;
+ dataSize += DSCP_TO_VLAN_TABLE_SIZE;
+ }
+ break;
+ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV4):
+ tableSize += HMCD_BASIC_SIZE;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_ID)
+ {
+ tableSize += HMCD_PARAM_SIZE;
+ dataSize += 2;
+ }
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_SRC)
+ tableSize += HMCD_IPV4_ADDR_SIZE;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_DST)
+ tableSize += HMCD_IPV4_ADDR_SIZE;
+ break;
+ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV6):
+ tableSize += HMCD_BASIC_SIZE;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV6_SRC)
+ tableSize += HMCD_IPV6_ADDR_SIZE;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV6_DST)
+ tableSize += HMCD_IPV6_ADDR_SIZE;
+ break;
+ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_TCP_UDP):
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates == HDR_MANIP_TCP_UDP_CHECKSUM)
+ /* we implement this case with the update-checksum descriptor */
+ tableSize += HMCD_BASIC_SIZE;
+ else
+ /* we implement this case with the TCP/UDP-update descriptor */
+ tableSize += HMCD_BASIC_SIZE + HMCD_PARAM_SIZE;
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown fieldUpdateParams.type"));
+ }
+ }
+
+ if (p_FmPcdManipParams->u.hdr.custom)
+ {
+ switch (p_FmPcdManipParams->u.hdr.customParams.type){
+ case (e_FM_PCD_MANIP_HDR_CUSTOM_IP_REPLACE):
+ {
+ tableSize += HMCD_BASIC_SIZE + HMCD_PARAM_SIZE + HMCD_PARAM_SIZE;
+ dataSize += p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.hdrSize;
+ if ((p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.replaceType == e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4) &&
+ (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.updateIpv4Id))
+ dataSize += 2;
+ }
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown customParams.type"));
+ }
+ }
+
+ *p_TableSize = tableSize;
+ *p_DataSize = dataSize;
+
+ return E_OK;
+}
+
+static t_Error BuildHmct(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_FmPcdManipParams, uint8_t *p_DestHmct, uint8_t *p_DestData, bool new)
+{
+ uint32_t *p_TmpHmct = (uint32_t*)p_DestHmct, *p_LocalData;
+ uint32_t tmpReg=0, *p_Last = NULL;
+ uint8_t remain, i, size=0, origSize, *p_UsrData = NULL, *p_TmpData = p_DestData;
+ t_Handle h_FmPcd = p_Manip->h_FmPcd;
+ uint8_t j=0;
+
+ if (p_FmPcdManipParams->u.hdr.rmv)
+ {
+ if (p_FmPcdManipParams->u.hdr.rmvParams.type == e_FM_PCD_MANIP_RMV_GENERIC)
+ {
+ /* initialize HMCD */
+ tmpReg = (uint32_t)(HMCD_OPCODE_GENERIC_RMV) << HMCD_OC_SHIFT;
+ /* tmp, should be conditional */
+ tmpReg |= p_FmPcdManipParams->u.hdr.rmvParams.u.generic.offset << HMCD_RMV_OFFSET_SHIFT;
+ tmpReg |= p_FmPcdManipParams->u.hdr.rmvParams.u.generic.size << HMCD_RMV_SIZE_SHIFT;
+ }
+ else if (p_FmPcdManipParams->u.hdr.rmvParams.type == e_FM_PCD_MANIP_RMV_BY_HDR)
+ {
+ uint8_t hmcdOpt;
+ if (!p_FmPcdManipParams->u.hdr.rmvParams.u.byHdr.type == e_FM_PCD_MANIP_RMV_BY_HDR_SPECIFIC_L2)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+
+ /* initialize HMCD */
+ tmpReg = (uint32_t)(HMCD_OPCODE_L2_RMV) << HMCD_OC_SHIFT;
+
+ switch (p_FmPcdManipParams->u.hdr.rmvParams.u.byHdr.u.specificL2)
+ {
+ case (e_FM_PCD_MANIP_HDR_RMV_ETHERNET):
+ hmcdOpt = HMCD_RMV_L2_ETHERNET;
+ break;
+ case (e_FM_PCD_MANIP_HDR_RMV_STACKED_QTAGS):
+ hmcdOpt = HMCD_RMV_L2_STACKED_QTAGS;
+ break;
+ case (e_FM_PCD_MANIP_HDR_RMV_ETHERNET_AND_MPLS):
+ hmcdOpt = HMCD_RMV_L2_ETHERNET_AND_MPLS;
+ break;
+ case (e_FM_PCD_MANIP_HDR_RMV_MPLS):
+ hmcdOpt = HMCD_RMV_L2_MPLS;
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+ }
+ tmpReg |= hmcdOpt << HMCD_L2_MODE_SHIFT;
+ }
+ else
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("manip header remove type!"));
+
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ /* save a pointer to the "last" indication word */
+ p_Last = p_TmpHmct;
+ /* advance to next command */
+ p_TmpHmct += HMCD_BASIC_SIZE/4;
+ }
+
+ if (p_FmPcdManipParams->u.hdr.insrt)
+ {
+ if (p_FmPcdManipParams->u.hdr.insrtParams.type == e_FM_PCD_MANIP_INSRT_GENERIC)
+ {
+ /* initialize HMCD */
+ if (p_FmPcdManipParams->u.hdr.insrtParams.u.generic.replace)
+ tmpReg = (uint32_t)(HMCD_OPCODE_GENERIC_REPLACE) << HMCD_OC_SHIFT;
+ else
+ tmpReg = (uint32_t)(HMCD_OPCODE_GENERIC_INSRT) << HMCD_OC_SHIFT;
+
+ tmpReg |= p_FmPcdManipParams->u.hdr.insrtParams.u.generic.offset << HMCD_INSRT_OFFSET_SHIFT;
+ tmpReg |= p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size << HMCD_INSRT_SIZE_SHIFT;
+
+ size = p_FmPcdManipParams->u.hdr.insrtParams.u.generic.size;
+ p_UsrData = p_FmPcdManipParams->u.hdr.insrtParams.u.generic.p_Data;
+
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ /* save a pointer to the "last" indication word */
+ p_Last = p_TmpHmct;
+
+ p_TmpHmct += HMCD_BASIC_SIZE/4;
+
+ /* initialize data to be inserted */
+ /* if size is not a multiple of 4, padd with 0's */
+ origSize = size;
+ remain = (uint8_t)(size % 4);
+ if (remain)
+ {
+ size += (uint8_t)(4 - remain);
+ p_LocalData = (uint32_t *)XX_Malloc(size);
+ memset((uint8_t *)p_LocalData, 0, size);
+ memcpy((uint8_t *)p_LocalData, p_UsrData, origSize);
+ }
+ else
+ p_LocalData = (uint32_t*)p_UsrData;
+
+ /* initialize data and advance pointer to next command */
+ for (i = 0; i<size/4 ; i++, p_TmpHmct += HMCD_BASIC_SIZE/4)
+ WRITE_UINT32(*p_TmpHmct, *(p_LocalData+i));
+
+ if (remain)
+ XX_Free(p_LocalData);
+ }
+
+ else if (p_FmPcdManipParams->u.hdr.insrtParams.type == e_FM_PCD_MANIP_INSRT_BY_HDR)
+ {
+ uint8_t hmcdOpt;
+ if (!p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.type == e_FM_PCD_MANIP_INSRT_BY_HDR_SPECIFIC_L2)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+
+ /* initialize HMCD */
+ tmpReg = (uint32_t)(HMCD_OPCODE_L2_INSRT) << HMCD_OC_SHIFT;
+
+ switch (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.specificL2)
+ {
+ case (e_FM_PCD_MANIP_HDR_INSRT_MPLS):
+ if (p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.update)
+ hmcdOpt = HMCD_INSRT_N_UPDATE_L2_MPLS;
+ else
+ hmcdOpt = HMCD_INSRT_L2_MPLS;
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, NO_MSG);
+ }
+ tmpReg |= hmcdOpt << HMCD_L2_MODE_SHIFT;
+
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ /* save a pointer to the "last" indication word */
+ p_Last = p_TmpHmct;
+
+ p_TmpHmct += HMCD_BASIC_SIZE/4;
+
+ /* set size and pointer of user's data */
+ size = (uint8_t)p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.size;
+
+ ASSERT_COND(p_TmpData);
+ Mem2IOCpy32(p_TmpData, p_FmPcdManipParams->u.hdr.insrtParams.u.byHdr.u.specificL2Params.p_Data, size);
+ tmpReg = (size << HMCD_INSRT_L2_SIZE_SHIFT) | (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)h_FmPcd)->physicalMuramBase));
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ p_TmpHmct += HMCD_PTR_SIZE/4;
+ p_TmpData += size;
+ }
+ else
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("manip header insert type!"));
+ }
+
+ if (p_FmPcdManipParams->u.hdr.fieldUpdate)
+ {
+ switch (p_FmPcdManipParams->u.hdr.fieldUpdateParams.type){
+ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN):
+ /* set opcode */
+ tmpReg = (uint32_t)(HMCD_OPCODE_VLAN_PRI_UPDATE) << HMCD_OC_SHIFT;
+
+ /* set mode & table pointer */
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType ==
+ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN)
+ {
+ /* set Mode */
+ tmpReg |= (uint32_t)(HMCD_VLAN_PRI_UPDATE_DSCP_TO_VPRI) << HMCD_VLAN_PRI_REP_MODE_SHIFT;
+ /* set VPRI default */
+ tmpReg |= p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.u.dscpToVpri.vpriDefVal;
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ /* save a pointer to the "last" indication word */
+ p_Last = p_TmpHmct;
+ /* write the table pointer into the Manip descriptor */
+ p_TmpHmct += HMCD_BASIC_SIZE/4;
+
+ tmpReg = 0;
+ ASSERT_COND(p_TmpData);
+ for (i=0; i<HMCD_DSCP_VALUES; i++)
+ {
+ /* first we build from each 8 values a 32bit register */
+ tmpReg |= (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.u.dscpToVpri.dscpToVpriTable[i]) << (32-4*(j+1));
+ j++;
+ /* Than we write this register to the next table word
+ * (i=7-->word 0, i=15-->word 1,... i=63-->word 7) */
+ if ((i%8) == 7)
+ {
+ WRITE_UINT32(*((uint32_t*)p_TmpData + (i+1)/8-1), tmpReg);
+ tmpReg = 0;
+ j = 0;
+ }
+ }
+ WRITE_UINT32(*p_TmpHmct, (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)h_FmPcd)->physicalMuramBase)));
+ p_TmpHmct += HMCD_PTR_SIZE/4;
+
+ p_TmpData += DSCP_TO_VLAN_TABLE_SIZE;
+ }
+ else if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType ==
+ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN_VPRI)
+ {
+ /* set Mode */
+ /* line commented out as it has no-side-effect ('0' value). */
+ /*tmpReg |= HMCD_VLAN_PRI_UPDATE << HMCD_VLAN_PRI_REP_MODE_SHIFT*/;
+ /* set VPRI parameter */
+ tmpReg |= p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.vlan.u.vpri;
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ /* save a pointer to the "last" indication word */
+ p_Last = p_TmpHmct;
+ p_TmpHmct += HMCD_BASIC_SIZE/4;
+ }
+ break;
+
+ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV4):
+ /* set opcode */
+ tmpReg = (uint32_t)(HMCD_OPCODE_IPV4_UPDATE) << HMCD_OC_SHIFT;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_TTL)
+ tmpReg |= HMCD_IPV4_UPDATE_TTL;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_TOS)
+ {
+ tmpReg |= HMCD_IPV4_UPDATE_TOS;
+ tmpReg |= p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.tos << HMCD_IPV4_UPDATE_TOS_SHIFT;
+ }
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_ID)
+ tmpReg |= HMCD_IPV4_UPDATE_ID;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_SRC)
+ tmpReg |= HMCD_IPV4_UPDATE_SRC;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_DST)
+ tmpReg |= HMCD_IPV4_UPDATE_DST;
+ /* write the first 4 bytes of the descriptor */
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ /* save a pointer to the "last" indication word */
+ p_Last = p_TmpHmct;
+
+ p_TmpHmct += HMCD_BASIC_SIZE/4;
+
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_ID)
+ {
+ ASSERT_COND(p_TmpData);
+ WRITE_UINT16(*(uint16_t*)p_TmpData, p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.id);
+ WRITE_UINT32(*p_TmpHmct, (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)p_Manip->h_FmPcd)->physicalMuramBase)));
+ p_TmpData += 2;
+ p_TmpHmct += HMCD_PTR_SIZE/4;
+ }
+
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_SRC)
+ {
+ WRITE_UINT32(*p_TmpHmct, p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.src);
+ p_TmpHmct += HMCD_IPV4_ADDR_SIZE/4;
+ }
+
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.validUpdates & HDR_MANIP_IPV4_DST)
+ {
+ WRITE_UINT32(*p_TmpHmct, p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv4.dst);
+ p_TmpHmct += HMCD_IPV4_ADDR_SIZE/4;
+ }
+ break;
+
+ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV6):
+ /* set opcode */
+ tmpReg = (uint32_t)(HMCD_OPCODE_IPV6_UPDATE) << HMCD_OC_SHIFT;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_HL)
+ tmpReg |= HMCD_IPV6_UPDATE_HL;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_TC)
+ {
+ tmpReg |= HMCD_IPV6_UPDATE_TC;
+ tmpReg |= p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.trafficClass << HMCD_IPV6_UPDATE_TC_SHIFT;
+ }
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_SRC)
+ tmpReg |= HMCD_IPV6_UPDATE_SRC;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_DST)
+ tmpReg |= HMCD_IPV6_UPDATE_DST;
+ /* write the first 4 bytes of the descriptor */
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ /* save a pointer to the "last" indication word */
+ p_Last = p_TmpHmct;
+
+ p_TmpHmct += HMCD_BASIC_SIZE/4;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_SRC)
+ for (i = 0 ; i < NET_HEADER_FIELD_IPv6_ADDR_SIZE ; i+=4)
+ {
+ WRITE_UINT32(*p_TmpHmct, *(uint32_t*)&p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.src[i]);
+ p_TmpHmct += HMCD_PTR_SIZE/4;
+ }
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.validUpdates & HDR_MANIP_IPV6_DST)
+ for (i = 0 ; i < NET_HEADER_FIELD_IPv6_ADDR_SIZE ; i+=4)
+ {
+ WRITE_UINT32(*p_TmpHmct, *(uint32_t*)&p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.ipv6.dst[i]);
+ p_TmpHmct += HMCD_PTR_SIZE/4;
+ }
+ break;
+
+ case (e_FM_PCD_MANIP_HDR_FIELD_UPDATE_TCP_UDP):
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates == HDR_MANIP_TCP_UDP_CHECKSUM)
+ {
+ /* we implement this case with the update-checksum descriptor */
+ /* set opcode */
+ tmpReg = (uint32_t)(HMCD_OPCODE_TCP_UDP_CHECKSUM) << HMCD_OC_SHIFT;
+ /* write the first 4 bytes of the descriptor */
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ /* save a pointer to the "last" indication word */
+ p_Last = p_TmpHmct;
+
+ p_TmpHmct += HMCD_BASIC_SIZE/4;
+ }
+ else
+ {
+ /* we implement this case with the TCP/UDP update descriptor */
+ /* set opcode */
+ tmpReg = (uint32_t)(HMCD_OPCODE_TCP_UDP_UPDATE) << HMCD_OC_SHIFT;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates & HDR_MANIP_TCP_UDP_DST)
+ tmpReg |= HMCD_TCP_UDP_UPDATE_DST;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates & HDR_MANIP_TCP_UDP_SRC)
+ tmpReg |= HMCD_TCP_UDP_UPDATE_SRC;
+ /* write the first 4 bytes of the descriptor */
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ /* save a pointer to the "last" indication word */
+ p_Last = p_TmpHmct;
+
+ p_TmpHmct += HMCD_BASIC_SIZE/4;
+
+ tmpReg = 0;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates & HDR_MANIP_TCP_UDP_SRC)
+ tmpReg |= ((uint32_t)p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.src) << HMCD_TCP_UDP_UPDATE_SRC_SHIFT;
+ if (p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.validUpdates & HDR_MANIP_TCP_UDP_DST)
+ tmpReg |= ((uint32_t)p_FmPcdManipParams->u.hdr.fieldUpdateParams.u.tcpUdp.dst);
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ p_TmpHmct += HMCD_PTR_SIZE/4;
+ }
+ break;
+
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown fieldUpdateParams.type"));
+ }
+ }
+
+ if (p_FmPcdManipParams->u.hdr.custom)
+ {
+ switch (p_FmPcdManipParams->u.hdr.customParams.type)
+ {
+ case (e_FM_PCD_MANIP_HDR_CUSTOM_IP_REPLACE):
+ /* set opcode */
+ tmpReg = (uint32_t)(HMCD_OPCODE_REPLACE_IP) << HMCD_OC_SHIFT;
+
+ if (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.decTtlHl)
+ tmpReg |= HMCD_IP_REPLACE_TTL_HL;
+ if (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.replaceType == e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV4_BY_IPV6)
+ /* line commented out as it has no-side-effect ('0' value). */
+ /*tmpReg |= HMCD_IP_REPLACE_REPLACE_IPV4*/;
+ else if (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.replaceType == e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4)
+ {
+ tmpReg |= HMCD_IP_REPLACE_REPLACE_IPV6;
+ if (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.updateIpv4Id)
+ tmpReg |= HMCD_IP_REPLACE_ID;
+ }
+ else
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("One flag out of HDR_MANIP_IP_REPLACE_IPV4, HDR_MANIP_IP_REPLACE_IPV6 - must be set."));
+
+ /* write the first 4 bytes of the descriptor */
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ /* save a pointer to the "last" indication word */
+ p_Last = p_TmpHmct;
+
+ p_TmpHmct += HMCD_BASIC_SIZE/4;
+
+ size = p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.hdrSize;
+ ASSERT_COND(p_TmpData);
+ Mem2IOCpy32(p_TmpData, p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.hdr, size);
+ tmpReg = (uint32_t)(size << HMCD_IP_REPLACE_L3HDRSIZE_SHIFT);
+ tmpReg |= (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)h_FmPcd)->physicalMuramBase));
+ WRITE_UINT32(*p_TmpHmct, tmpReg);
+ p_TmpHmct += HMCD_PTR_SIZE/4;
+ p_TmpData += size;
+
+ if ((p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.replaceType == e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4) &&
+ (p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.updateIpv4Id))
+ {
+ WRITE_UINT16(*(uint16_t*)p_TmpData, p_FmPcdManipParams->u.hdr.customParams.u.ipHdrReplace.id);
+ WRITE_UINT32(*p_TmpHmct, (uint32_t)(XX_VirtToPhys(p_TmpData) - (((t_FmPcd*)h_FmPcd)->physicalMuramBase)));
+ p_TmpData += 2;
+ }
+ p_TmpHmct += HMCD_PTR_SIZE/4;
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Unknown customParams.type"));
+ }
+ }
+
+
+ /* If this node has a nextManip, and no parsing is required after it, the old table must be copied to the new table
+ the old table and should be freed */
+ if (p_FmPcdManipParams->h_NextManip &&
+ (MANIP_DONT_REPARSE(p_FmPcdManipParams->h_NextManip)))
+ {
+ if (new)
+ {
+ /* If this is the first time this manip is created we need to free unused memory. If it
+ * is a dynamic changes case, the memory used is either the CC shadow or the existing
+ * table - no allocation, no free */
+ MANIP_UPDATE_UNIFIED_POSITION(p_FmPcdManipParams->h_NextManip);
+
+ p_Manip->unifiedPosition = e_MANIP_UNIFIED_FIRST;
+
+ /* The HMTD of the next Manip is never going to be used */
+ if (((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->muramAllocate)
+ FM_MURAM_FreeMem(((t_FmPcd *)((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->h_FmPcd)->h_FmMuram, ((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->h_Ad);
+ else
+ XX_Free(((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->h_Ad);
+ ((t_FmPcdManip *)p_FmPcdManipParams->h_NextManip)->h_Ad = NULL;
+
+ /* advance pointer */
+ p_TmpHmct += MANIP_GET_HMCT_SIZE(p_FmPcdManipParams->h_NextManip)/4;
+ }
+ }
+ else
+ {
+ ASSERT_COND(p_Last);
+ /* set the "last" indication on the last command of the current table */
+ WRITE_UINT32(*p_Last, GET_UINT32(*p_Last) | HMCD_LAST);
+ }
+
+ return E_OK;
+}
+
+static t_Error CreateManipActionNew(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_FmPcdManipParams)
+{
+ t_FmPcdManip *p_CurManip;
+ t_Error err;
+ uint32_t nextSize = 0, totalSize;
+ uint16_t tmpReg;
+ uint8_t *p_OldHmct, *p_TmpHmctPtr, *p_TmpDataPtr;
+
+ /* set Manip structure */
+ if (p_FmPcdManipParams->h_NextManip)
+ {
+ if (MANIP_DONT_REPARSE(p_FmPcdManipParams->h_NextManip))
+ nextSize = (uint32_t)(GetHmctSize(p_FmPcdManipParams->h_NextManip) + GetDataSize(p_FmPcdManipParams->h_NextManip));
+ else
+ p_Manip->cascadedNext = TRUE;
+ }
+ p_Manip->dontParseAfterManip = p_FmPcdManipParams->u.hdr.dontParseAfterManip;
+
+ /* Allocate new table */
+ /* calculate table size according to manip parameters */
+ err = CalculateTableSize(p_FmPcdManipParams, &p_Manip->tableSize, &p_Manip->dataSize);
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ totalSize =(uint16_t)(p_Manip->tableSize + p_Manip->dataSize + nextSize);
+
+ p_Manip->p_Hmct = (uint8_t*)FM_MURAM_AllocMem(((t_FmPcd *)p_Manip->h_FmPcd)->h_FmMuram, totalSize, 4);
+ if (!p_Manip->p_Hmct)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc failed"));
+
+ if (p_Manip->dataSize)
+ p_Manip->p_Data = (uint8_t*)PTR_MOVE(p_Manip->p_Hmct, (p_Manip->tableSize + nextSize));
+
+ /* update shadow size to allow runtime replacement of Header manipulation */
+ /* The allocated shadow is divided as follows:
+ 0 . . . 16 . . .
+ --------------------------------
+ | Shadow | Shadow HMTD |
+ | HMTD | Match Table |
+ | (16 bytes) | (maximal size) |
+ --------------------------------
+ */
+
+ err = FmPcdUpdateCcShadow (p_Manip->h_FmPcd, (uint32_t)(totalSize + 16), (uint16_t)FM_PCD_CC_AD_TABLE_ALIGN);
+ if (err != E_OK)
+ {
+ FM_MURAM_FreeMem(p_Manip->h_FmPcd, p_Manip->p_Hmct);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for HdrManip node shadow"));
+ }
+
+
+ if (p_FmPcdManipParams->h_NextManip &&
+ (MANIP_DONT_REPARSE(p_FmPcdManipParams->h_NextManip)))
+ {
+ p_OldHmct = (uint8_t *)GetManipInfo(p_FmPcdManipParams->h_NextManip, e_MANIP_HMCT);
+ p_CurManip = p_FmPcdManipParams->h_NextManip;
+ /* Run till the last Manip (which is the first to configure) */
+ while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip))
+ p_CurManip = p_CurManip->h_NextManip;
+
+ while (p_CurManip)
+ {
+ /* If this is a unified table, point to the part of the table
+ * which is the relative offset in HMCT.
+ */
+ p_TmpHmctPtr = (uint8_t*)PTR_MOVE(p_Manip->p_Hmct,
+ (p_Manip->tableSize +
+ (PTR_TO_UINT(p_CurManip->p_Hmct) -
+ PTR_TO_UINT(p_OldHmct))));
+ if (p_CurManip->p_Data)
+ p_TmpDataPtr = (uint8_t*)PTR_MOVE(p_Manip->p_Hmct,
+ (p_Manip->tableSize +
+ (PTR_TO_UINT(p_CurManip->p_Data) -
+ PTR_TO_UINT(p_OldHmct))));
+ else
+ p_TmpDataPtr = NULL;
+
+ BuildHmct(p_CurManip, &p_CurManip->manipParams, p_TmpHmctPtr, p_TmpDataPtr, FALSE);
+ /* update old manip table pointer */
+ MANIP_SET_HMCT_PTR(p_CurManip, p_TmpHmctPtr);
+ MANIP_SET_DATA_PTR(p_CurManip, p_TmpDataPtr);
+
+ p_CurManip = p_CurManip->h_PrevManip;
+ }
+ /* We copied the HMCT to create a new large HMCT so we can free the old one */
+ FM_MURAM_FreeMem(MANIP_GET_MURAM(p_FmPcdManipParams->h_NextManip), p_OldHmct);
+ }
+
+ /* Fill table */
+ err = BuildHmct(p_Manip, p_FmPcdManipParams, p_Manip->p_Hmct, p_Manip->p_Data, TRUE);
+ if (err)
+ {
+ FM_MURAM_FreeMem(p_Manip->h_FmPcd, p_Manip->p_Hmct);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ /* Build HMTD (table descriptor) */
+ tmpReg = HMTD_CFG_TYPE; /* NADEN = 0 */
+ /* add parseAfterManip */
+ if (!p_Manip->dontParseAfterManip)
+ tmpReg |= HMTD_CFG_PRS_AFTER_HM;
+ /* create cascade */
+ if (p_FmPcdManipParams->h_NextManip &&
+ !MANIP_DONT_REPARSE(p_FmPcdManipParams->h_NextManip))
+ {
+ /* indicate that there's another HM table descriptor */
+ tmpReg |= HMTD_CFG_NEXT_AD_EN;
+ WRITE_UINT16(((t_Hmtd *)p_Manip->h_Ad)->nextAdIdx,
+ (uint16_t)((uint32_t)(XX_VirtToPhys(MANIP_GET_HMTD_PTR(p_FmPcdManipParams->h_NextManip)) -
+ (((t_FmPcd*)p_Manip->h_FmPcd)->physicalMuramBase)) >> 4));
+ }
+
+ WRITE_UINT16(((t_Hmtd *)p_Manip->h_Ad)->cfg, tmpReg);
+ WRITE_UINT32(((t_Hmtd *)p_Manip->h_Ad)->hmcdBasePtr,
+ (uint32_t)(XX_VirtToPhys(p_Manip->p_Hmct) - (((t_FmPcd*)p_Manip->h_FmPcd)->physicalMuramBase)));
+
+ WRITE_UINT8(((t_Hmtd *)p_Manip->h_Ad)->opCode, HMAN_OC);
+
+ return E_OK;
+}
+
+static t_Error CreateManipActionShadow(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_FmPcdManipParams)
+{
+ uint8_t *p_WholeHmct, *p_TmpHmctPtr, newDataSize, *p_TmpDataPtr = NULL;
+ uint16_t newSize;
+ t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd;
+ t_Error err;
+ t_FmPcdManip *p_CurManip = p_Manip;
+
+ err = CalculateTableSize(p_FmPcdManipParams, &newSize, &newDataSize);
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ /* check coherency of new table parameters */
+ if (newSize > p_Manip->tableSize)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("New Hdr Manip configuration requires larger size than current one (command table)."));
+ if (newDataSize > p_Manip->dataSize)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("New Hdr Manip configuration requires larger size than current one (data)."));
+ if (p_FmPcdManipParams->h_NextManip)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("New Hdr Manip configuration can not contain h_NextManip."));
+ if (MANIP_IS_UNIFIED(p_Manip) && (newSize != p_Manip->tableSize))
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("New Hdr Manip configuration in a chained manipulation requires different size than current one."));
+ if (p_Manip->dontParseAfterManip != p_FmPcdManipParams->u.hdr.dontParseAfterManip)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("New Hdr Manip configuration differs in dontParseAfterManip value."));
+
+ p_Manip->tableSize = newSize;
+ p_Manip->dataSize = newDataSize;
+
+
+ /* Build the new table in the shadow */
+ if (!MANIP_IS_UNIFIED(p_Manip))
+ {
+ p_TmpHmctPtr = (uint8_t*)PTR_MOVE(p_FmPcd->p_CcShadow, 16);
+ if (p_Manip->p_Data)
+ p_TmpDataPtr = (uint8_t*)PTR_MOVE(p_TmpHmctPtr,
+ (PTR_TO_UINT(p_Manip->p_Data) - PTR_TO_UINT(p_Manip->p_Hmct)));
+
+ BuildHmct(p_Manip, p_FmPcdManipParams, p_TmpHmctPtr, p_Manip->p_Data, FALSE);
+ }
+ else
+ {
+ p_WholeHmct = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMCT);
+ ASSERT_COND(p_WholeHmct);
+
+ /* Run till the last Manip (which is the first to configure) */
+ while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip))
+ p_CurManip = p_CurManip->h_NextManip;
+
+ while (p_CurManip)
+ {
+ /* If this is a non-head node in a unified table, point to the part of the shadow
+ * which is the relative offset in HMCT.
+ * else, point to the beginning of the
+ * shadow table (we save 16 for the HMTD.
+ */
+ p_TmpHmctPtr = (uint8_t*)PTR_MOVE(p_FmPcd->p_CcShadow,
+ (16 + PTR_TO_UINT(p_CurManip->p_Hmct) - PTR_TO_UINT(p_WholeHmct)));
+ if (p_CurManip->p_Data)
+ p_TmpDataPtr = (uint8_t*)PTR_MOVE(p_FmPcd->p_CcShadow,
+ (16 + PTR_TO_UINT(p_CurManip->p_Data) - PTR_TO_UINT(p_WholeHmct)));
+
+ BuildHmct(p_CurManip, &p_CurManip->manipParams, p_TmpHmctPtr, p_TmpDataPtr, FALSE);
+ p_CurManip = p_CurManip->h_PrevManip;
+ }
+ }
+
+ return E_OK;
+}
+
+static t_Error CreateManipActionBackToOrig(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_FmPcdManipParams)
+{
+ uint8_t *p_WholeHmct = NULL, *p_TmpHmctPtr, *p_TmpDataPtr;
+ t_FmPcdManip *p_CurManip = p_Manip;
+
+ UNUSED(p_WholeHmct);
+
+ /* Build the new table in the shadow */
+ if (!MANIP_IS_UNIFIED(p_Manip))
+ BuildHmct(p_Manip, p_FmPcdManipParams, p_Manip->p_Hmct, p_Manip->p_Data, FALSE);
+ else
+ {
+ p_WholeHmct = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMCT);
+ ASSERT_COND(p_WholeHmct);
+
+ /* Run till the last Manip (which is the first to configure) */
+ while (MANIP_IS_UNIFIED_NON_LAST(p_CurManip))
+ p_CurManip = p_CurManip->h_NextManip;
+
+ while (p_CurManip)
+ {
+ /* If this is a unified table, point to the part of the table
+ * which is the relative offset in HMCT.
+ */
+ p_TmpHmctPtr = p_CurManip->p_Hmct; /*- (uint32_t)p_WholeHmct*/
+ p_TmpDataPtr = p_CurManip->p_Data; /*- (uint32_t)p_WholeHmct*/
+
+ BuildHmct(p_CurManip, &p_CurManip->manipParams, p_TmpHmctPtr, p_TmpDataPtr, FALSE);
+
+ p_CurManip = p_CurManip->h_PrevManip;
+ }
+ }
+
+ return E_OK;
+}
+
+static t_Error UpdateManipIc(t_Handle h_Manip, uint8_t icOffset)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
+ t_Handle p_Ad;
+ uint32_t tmpReg32 = 0;
+ SANITY_CHECK_RETURN_ERROR(h_Manip,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad, E_INVALID_HANDLE);
+
+ switch (p_Manip->opcode)
+ {
+ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX):
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
+ if (p_Manip->updateParams & INTERNAL_CONTEXT_OFFSET)
+ {
+ tmpReg32 = *(uint32_t *)&((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets;
+ tmpReg32 |= (uint32_t)((uint32_t)icOffset << 16);
+ *(uint32_t *)&((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets = tmpReg32;
+ p_Manip->updateParams &= ~INTERNAL_CONTEXT_OFFSET;
+ p_Manip->icOffset = icOffset;
+ }
+ else
+ {
+ if (p_Manip->icOffset != icOffset)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("this manipulation was updated previously by different value"););
+ }
+ break;
+#ifdef FM_CAPWAP_SUPPORT
+ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST):
+ if (p_Manip->h_Frag)
+ {
+ if (p_Manip->updateParams & INTERNAL_CONTEXT_OFFSET)
+ {
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
+ tmpReg32 |= GET_UINT32(((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets);
+ tmpReg32 |= (uint32_t)((uint32_t)icOffset << 16);
+ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets, tmpReg32);
+ p_Manip->updateParams &= ~INTERNAL_CONTEXT_OFFSET;
+ p_Manip->icOffset = icOffset;
+ }
+ else
+ {
+ if (p_Manip->icOffset != icOffset)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("this manipulation was updated previousely by different value"););
+ }
+ }
+ break;
+#endif /* FM_CAPWAP_SUPPORT */
+ }
+
+ return E_OK;
+}
+
+static t_Error UpdateInitMvIntFrameHeaderFromFrameToBufferPrefix(t_Handle h_FmPort, t_FmPcdManip *p_Manip, t_Handle h_Ad, bool validate)
+{
+
+ t_AdOfTypeContLookup *p_Ad = (t_AdOfTypeContLookup *)h_Ad;
+ t_FmPortGetSetCcParams fmPortGetSetCcParams;
+ t_Error err;
+ uint32_t tmpReg32;
+
+ memset(&fmPortGetSetCcParams, 0, sizeof(t_FmPortGetSetCcParams));
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Manip->opcode & HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX), E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_Manip->muramAllocate, E_INVALID_STATE);
+
+ if (p_Manip->updateParams)
+ {
+ if ((!(p_Manip->updateParams & OFFSET_OF_PR)) ||
+ (p_Manip->shadowUpdateParams & OFFSET_OF_PR))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated"));
+
+ fmPortGetSetCcParams.getCcParams.type = p_Manip->updateParams;
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_PSO;
+ fmPortGetSetCcParams.setCcParams.psoSize = 16;
+
+ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_PR)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Parser result offset wasn't configured previousely"));
+#ifdef FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004
+ ASSERT_COND(!(fmPortGetSetCcParams.getCcParams.prOffset % 16));
+#endif
+ }
+ else if (validate)
+ {
+ if ((!(p_Manip->shadowUpdateParams & OFFSET_OF_PR)) ||
+ (p_Manip->updateParams & OFFSET_OF_PR))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has be updated"));
+ fmPortGetSetCcParams.getCcParams.type = p_Manip->shadowUpdateParams;
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_PSO;
+ fmPortGetSetCcParams.setCcParams.psoSize = 16;
+
+ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_PR)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Parser result offset wasn't configured previousely"));
+
+ }
+
+ ASSERT_COND(p_Ad);
+
+ if (p_Manip->updateParams & OFFSET_OF_PR)
+ {
+ tmpReg32 = 0;
+ tmpReg32 |= fmPortGetSetCcParams.getCcParams.prOffset;
+ WRITE_UINT32(p_Ad->matchTblPtr, (GET_UINT32(p_Ad->matchTblPtr) | tmpReg32));
+ p_Manip->updateParams &= ~OFFSET_OF_PR;
+ p_Manip->shadowUpdateParams |= OFFSET_OF_PR;
+ }
+ else if (validate)
+ {
+ tmpReg32 = GET_UINT32(p_Ad->matchTblPtr);
+ if ((uint8_t)tmpReg32 != fmPortGetSetCcParams.getCcParams.prOffset)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("this manipulation was updated previousely by different value"););
+ }
+
+ return E_OK;
+}
+
+#ifdef FM_CAPWAP_SUPPORT
+static t_Error UpdateModifyCapwapFragmenation(t_FmPcdManip *p_Manip, t_Handle h_Ad, bool validate,t_Handle h_FmTree)
+{
+ t_AdOfTypeContLookup *p_Ad = (t_AdOfTypeContLookup *)h_Ad;
+ t_FmPcdCcSavedManipParams *p_SavedManipParams = NULL;
+ uint32_t tmpReg32 = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Frag,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Manip->frag,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(((p_Manip->opcode == HMAN_OC_CAPWAP_FRAGMENTATION) || (p_Manip->opcode == HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER)), E_INVALID_STATE);
+
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Frag;
+
+ if (p_Manip->updateParams)
+ {
+
+ if ((!(p_Manip->updateParams & OFFSET_OF_DATA)) ||
+ ((p_Manip->shadowUpdateParams & OFFSET_OF_DATA)))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated"));
+ p_SavedManipParams = FmPcdCcTreeGetSavedManipParams(h_FmTree);
+ if (!p_SavedManipParams)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("for this manipulation tree has to be configured previosely with this type"));
+ p_Manip->fragParams.dataOffset = p_SavedManipParams->capwapParams.dataOffset;
+
+ tmpReg32 = GET_UINT32(p_Ad->pcAndOffsets);
+ tmpReg32 |= ((uint32_t)p_Manip->fragParams.dataOffset<< 16);
+ WRITE_UINT32(p_Ad->pcAndOffsets,tmpReg32);
+
+ p_Manip->updateParams &= ~OFFSET_OF_DATA;
+ p_Manip->shadowUpdateParams |= OFFSET_OF_DATA;
+ }
+ else if (validate)
+ {
+
+ p_SavedManipParams = FmPcdCcTreeGetSavedManipParams(h_FmTree);
+ if (!p_SavedManipParams)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("for this manipulation tree has to be configured previosely with this type"));
+ if (p_Manip->fragParams.dataOffset != p_SavedManipParams->capwapParams.dataOffset)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("this manipulation was updated previousely by different value"));
+ }
+
+ return E_OK;
+}
+
+static t_Error UpdateInitCapwapFragmentation(t_Handle h_FmPort,
+ t_FmPcdManip *p_Manip,
+ t_Handle h_Ad,
+ bool validate,
+ t_Handle h_FmTree)
+{
+ t_AdOfTypeContLookup *p_Ad;
+ t_FmPortGetSetCcParams fmPortGetSetCcParams;
+ t_Error err;
+ uint32_t tmpReg32 = 0;
+ t_FmPcdCcSavedManipParams *p_SavedManipParams;
+
+ UNUSED(h_Ad);
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Frag,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Manip->frag,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(((p_Manip->opcode == HMAN_OC_CAPWAP_FRAGMENTATION) ||
+ (p_Manip->opcode == HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER)), E_INVALID_STATE);
+
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Frag;
+
+ if (p_Manip->updateParams)
+ {
+ if ((!(p_Manip->updateParams & OFFSET_OF_DATA)) ||
+ ((p_Manip->shadowUpdateParams & OFFSET_OF_DATA)))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated"));
+ fmPortGetSetCcParams.getCcParams.type = p_Manip->updateParams;
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN | UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY;
+ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_POP_TO_N_STEP | NIA_ENG_FM_CTL;
+ /* For CAPWAP Rassembly used FMAN_CTRL2 hardcoded - so for fragmentation its better to use FMAN_CTRL1 */
+ fmPortGetSetCcParams.setCcParams.orFmanCtrl = FPM_PORT_FM_CTL1;
+
+ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_DATA)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Data offset wasn't configured previousely"));
+
+ p_SavedManipParams = (t_FmPcdCcSavedManipParams *)XX_Malloc(sizeof(t_FmPcdCcSavedManipParams));
+ p_SavedManipParams->capwapParams.dataOffset = fmPortGetSetCcParams.getCcParams.dataOffset;
+
+#ifdef FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004
+ ASSERT_COND(!(p_SavedManipParams->capwapParams.dataOffset % 16));
+#endif /* FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 */
+
+ FmPcdCcTreeSetSavedManipParams(h_FmTree, (t_Handle)p_SavedManipParams);
+ }
+ else if (validate)
+ {
+ if ((!(p_Manip->shadowUpdateParams & OFFSET_OF_DATA)) ||
+ ((p_Manip->updateParams & OFFSET_OF_DATA)))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has be updated"));
+ fmPortGetSetCcParams.getCcParams.type = p_Manip->shadowUpdateParams;
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN | UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY;
+ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_POP_TO_N_STEP | NIA_ENG_FM_CTL;
+ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_DATA)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Data offset wasn't configured previousely"));
+ }
+
+ if (p_Manip->updateParams)
+ {
+ tmpReg32 = GET_UINT32(p_Ad->pcAndOffsets);
+ tmpReg32 |= ((uint32_t)fmPortGetSetCcParams.getCcParams.dataOffset<< 16);
+ WRITE_UINT32(p_Ad->pcAndOffsets,tmpReg32);
+
+ p_Manip->updateParams &= ~OFFSET_OF_DATA;
+ p_Manip->shadowUpdateParams |= OFFSET_OF_DATA;
+ p_Manip->fragParams.dataOffset = fmPortGetSetCcParams.getCcParams.dataOffset;
+ }
+ else if (validate)
+ {
+ if (p_Manip->fragParams.dataOffset != fmPortGetSetCcParams.getCcParams.dataOffset)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("this manipulation was updated previousely by different value"));
+ }
+
+ return E_OK;
+}
+
+static t_Error UpdateInitCapwapReasm(t_Handle h_FmPcd,
+ t_Handle h_FmPort,
+ t_FmPcdManip *p_Manip,
+ t_Handle h_Ad,
+ bool validate)
+{
+ t_CapwapReasmPram *p_ReassmTbl;
+ t_Error err;
+ t_FmPortGetSetCcParams fmPortGetSetCcParams;
+ uint8_t i = 0;
+ uint16_t size;
+ uint32_t tmpReg32;
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ t_FmPcdCcCapwapReassmTimeoutParams ccCapwapReassmTimeoutParams;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Frag,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Manip->frag,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Manip->opcode == HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST), E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc,E_INVALID_HANDLE);
+
+ if (p_Manip->h_FmPcd != h_FmPcd)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,
+ ("handler of PCD previously was initiated by different value"));
+
+ UNUSED(h_Ad);
+
+ memset(&fmPortGetSetCcParams, 0, sizeof(t_FmPortGetSetCcParams));
+ p_ReassmTbl = (t_CapwapReasmPram *)p_Manip->h_Frag;
+
+ if (p_Manip->updateParams)
+ {
+ if ((!(p_Manip->updateParams & NUM_OF_TASKS) &&
+ !(p_Manip->updateParams & OFFSET_OF_DATA) &&
+ !(p_Manip->updateParams & OFFSET_OF_PR) &&
+ !(p_Manip->updateParams & HW_PORT_ID)) ||
+ ((p_Manip->shadowUpdateParams & NUM_OF_TASKS) ||
+ (p_Manip->shadowUpdateParams & OFFSET_OF_DATA) || (p_Manip->shadowUpdateParams & OFFSET_OF_PR) ||
+ (p_Manip->shadowUpdateParams & HW_PORT_ID)))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated"));
+
+ fmPortGetSetCcParams.getCcParams.type = p_Manip->updateParams;
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN;
+ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_POP_TO_N_STEP | NIA_ENG_FM_CTL;
+
+ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (fmPortGetSetCcParams.getCcParams.type & NUM_OF_TASKS)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Num of tasks wasn't configured previousely"));
+ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_DATA)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("offset of the data wasn't configured previousely"));
+ if (fmPortGetSetCcParams.getCcParams.type & HW_PORT_ID)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("hwPortId wasn't updated"));
+#ifdef FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004
+ ASSERT_COND((fmPortGetSetCcParams.getCcParams.dataOffset % 16) == 0);
+#endif /* FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004 */
+ }
+ else if (validate)
+ {
+ if ((!(p_Manip->shadowUpdateParams & NUM_OF_TASKS) &&
+ !(p_Manip->shadowUpdateParams & OFFSET_OF_DATA) &&
+ !(p_Manip->shadowUpdateParams & OFFSET_OF_PR) &&
+ !(p_Manip->shadowUpdateParams & HW_PORT_ID)) &&
+ ((p_Manip->updateParams & NUM_OF_TASKS) ||
+ (p_Manip->updateParams & OFFSET_OF_DATA) || (p_Manip->updateParams & OFFSET_OF_PR) ||
+ (p_Manip->updateParams & HW_PORT_ID)))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has be updated"));
+
+ fmPortGetSetCcParams.getCcParams.type = p_Manip->shadowUpdateParams;
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN;
+ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_POP_TO_N_STEP | NIA_ENG_FM_CTL;
+
+ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (fmPortGetSetCcParams.getCcParams.type & NUM_OF_TASKS)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("NumOfTasks wasn't configured previously"));
+ if (fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_DATA)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("offset of the data wasn't configured previously"));
+ if (fmPortGetSetCcParams.getCcParams.type & HW_PORT_ID)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("hwPortId wasn't updated"));
+ }
+
+ if (p_Manip->updateParams)
+ {
+ if (p_Manip->updateParams & NUM_OF_TASKS)
+ {
+ /*recommendation of Microcode team - (maxNumFramesInProcess * 2) */
+ size = (uint16_t)(p_Manip->fragParams.maxNumFramesInProcess*2 + fmPortGetSetCcParams.getCcParams.numOfTasks);
+ if (size > 255)
+ RETURN_ERROR(MAJOR,E_INVALID_VALUE, ("numOfOpenReassmEntries + numOfTasks per port can not be greater than 256"));
+
+ p_Manip->fragParams.numOfTasks = fmPortGetSetCcParams.getCcParams.numOfTasks;
+
+ /*p_ReassmFrmDescrIndxPoolTbl*/
+ p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl =
+ (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ (uint32_t)(size + 1),
+ 4);
+ if (!p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP Reassembly frame buffer index pool table"));
+
+ IOMemSet32(p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl, 0, (uint32_t)(size + 1));
+
+ for ( i = 0; i < size; i++)
+ WRITE_UINT8(*(uint8_t *)PTR_MOVE(p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl, i), (uint8_t)(i+1));
+
+ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl) - p_FmPcd->physicalMuramBase);
+
+ WRITE_UINT32(p_ReassmTbl->reasmFrmDescIndexPoolTblPtr, tmpReg32);
+
+ /*p_ReassmFrmDescrPoolTbl*/
+ p_Manip->fragParams.p_ReassmFrmDescrPoolTbl =
+ (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ (uint32_t)((size + 1) * FM_PCD_MANIP_CAPWAP_REASM_RFD_SIZE),
+ 4);
+
+ if (!p_Manip->fragParams.p_ReassmFrmDescrPoolTbl)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP Reassembly frame buffer pool table"));
+
+ IOMemSet32(p_Manip->fragParams.p_ReassmFrmDescrPoolTbl, 0, (uint32_t)((size +1)* FM_PCD_MANIP_CAPWAP_REASM_RFD_SIZE));
+
+ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->fragParams.p_ReassmFrmDescrPoolTbl) - p_FmPcd->physicalMuramBase);
+
+ WRITE_UINT32(p_ReassmTbl->reasmFrmDescPoolTblPtr, tmpReg32);
+
+ /*p_TimeOutTbl*/
+
+ p_Manip->fragParams.p_TimeOutTbl =
+ (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ (uint32_t)((size + 1)* FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_ENTRY_SIZE),
+ 4);
+
+ if (!p_Manip->fragParams.p_TimeOutTbl)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP Reassembly timeout table"));
+
+ IOMemSet32(p_Manip->fragParams.p_TimeOutTbl, 0, (uint16_t)((size + 1)*FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_ENTRY_SIZE));
+
+ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->fragParams.p_TimeOutTbl) - p_FmPcd->physicalMuramBase);
+ WRITE_UINT32(p_ReassmTbl->timeOutTblPtr, tmpReg32);
+
+ p_Manip->updateParams &= ~NUM_OF_TASKS;
+ p_Manip->shadowUpdateParams |= NUM_OF_TASKS;
+ }
+
+ if (p_Manip->updateParams & OFFSET_OF_DATA)
+ {
+ p_Manip->fragParams.dataOffset = fmPortGetSetCcParams.getCcParams.dataOffset;
+ tmpReg32 = GET_UINT32(p_ReassmTbl->mode);
+ tmpReg32|= p_Manip->fragParams.dataOffset;
+ WRITE_UINT32(p_ReassmTbl->mode, tmpReg32);
+ p_Manip->updateParams &= ~OFFSET_OF_DATA;
+ p_Manip->shadowUpdateParams |= OFFSET_OF_DATA;
+ }
+
+ if (!(fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_PR))
+ {
+ p_Manip->fragParams.prOffset = fmPortGetSetCcParams.getCcParams.prOffset;
+
+ tmpReg32 = GET_UINT32(p_ReassmTbl->mode);
+ tmpReg32|= FM_PCD_MANIP_CAPWAP_REASM_PR_COPY;
+ WRITE_UINT32(p_ReassmTbl->mode, tmpReg32);
+
+ tmpReg32 = GET_UINT32(p_ReassmTbl->intStatsTblPtr);
+ tmpReg32 |= (uint32_t)p_Manip->fragParams.prOffset << 24;
+ WRITE_UINT32(p_ReassmTbl->intStatsTblPtr, tmpReg32);
+ p_Manip->updateParams &= ~OFFSET_OF_PR;
+ p_Manip->shadowUpdateParams |= OFFSET_OF_PR;
+ }
+ else
+ {
+ p_Manip->fragParams.prOffset = 0xff;
+ p_Manip->updateParams &= ~OFFSET_OF_PR;
+ p_Manip->shadowUpdateParams |= OFFSET_OF_PR;
+ }
+
+ p_Manip->fragParams.hwPortId = fmPortGetSetCcParams.getCcParams.hardwarePortId;
+ p_Manip->updateParams &= ~HW_PORT_ID;
+ p_Manip->shadowUpdateParams |= HW_PORT_ID;
+
+ /*timeout hc */
+ ccCapwapReassmTimeoutParams.fqidForTimeOutFrames = p_Manip->fragParams.fqidForTimeOutFrames;
+ ccCapwapReassmTimeoutParams.portIdAndCapwapReassmTbl = (uint32_t)p_Manip->fragParams.hwPortId << 24;
+ ccCapwapReassmTimeoutParams.portIdAndCapwapReassmTbl |= (uint32_t)((XX_VirtToPhys(p_ReassmTbl) - p_FmPcd->physicalMuramBase));
+ ccCapwapReassmTimeoutParams.timeoutRequestTime = (((uint32_t)1<<p_Manip->fragParams.bitFor1Micro) * p_Manip->fragParams.timeoutRoutineRequestTime)/2;
+ return FmHcPcdCcCapwapTimeoutReassm(p_FmPcd->h_Hc,&ccCapwapReassmTimeoutParams);
+ }
+
+ else if (validate)
+ {
+ if (fmPortGetSetCcParams.getCcParams.hardwarePortId != p_Manip->fragParams.hwPortId)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Reassembly manipulation previously was assigned to another port"));
+ if (fmPortGetSetCcParams.getCcParams.numOfTasks != p_Manip->fragParams.numOfTasks)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfTasks for this manipulation previously was defined by another value "));
+
+
+ if (!(fmPortGetSetCcParams.getCcParams.type & OFFSET_OF_PR))
+ {
+ if (p_Manip->fragParams.prOffset != fmPortGetSetCcParams.getCcParams.prOffset)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Parse result offset previously was defined by another value "));
+ }
+ else
+ {
+ if (p_Manip->fragParams.prOffset != 0xff)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Parse result offset previously was defined by another value "));
+ }
+ if (fmPortGetSetCcParams.getCcParams.dataOffset != p_Manip->fragParams.dataOffset)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Data offset previously was defined by another value "));
+ }
+
+ return E_OK;
+}
+#endif /* FM_CAPWAP_SUPPORT */
+
+t_Error FmPcdRegisterReassmPort(t_Handle h_FmPcd, t_Handle h_IpReasmCommonPramTbl)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_FmPcdCcIpReassmTimeoutParams ccIpReassmTimeoutParams = {0};
+ t_Error err = E_OK;
+ uint8_t result;
+ uint32_t bitFor1Micro, tsbs, log2num;
+
+ ASSERT_COND(p_FmPcd);
+ ASSERT_COND(h_IpReasmCommonPramTbl);
+
+ bitFor1Micro = FmGetTimeStampScale(p_FmPcd->h_Fm);
+ bitFor1Micro = 32 - bitFor1Micro;
+ LOG2(FM_PCD_MANIP_IP_REASSM_TIMEOUT_THREAD_THRESH, log2num);
+ tsbs = bitFor1Micro - log2num;
+
+ ccIpReassmTimeoutParams.iprcpt = (uint32_t)(XX_VirtToPhys(h_IpReasmCommonPramTbl) - p_FmPcd->physicalMuramBase);
+ ccIpReassmTimeoutParams.tsbs = (uint8_t)tsbs;
+ ccIpReassmTimeoutParams.activate = TRUE;
+ if ((err = FmHcPcdCcIpTimeoutReassm(p_FmPcd->h_Hc, &ccIpReassmTimeoutParams, &result)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ switch (result)
+ {
+ case (0):
+ return E_OK;
+ case (1):
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("failed to allocate TNUM"));
+ case (2):
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("failed to allocate internal buffer from the HC-Port"));
+ case (3):
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("'Disable Timeout Task' with invalid IPRCPT"));
+ case (4):
+ RETURN_ERROR(MAJOR, E_FULL, ("too many timeout tasks"));
+ case (5):
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("invalid sub command"));
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
+ }
+ return E_OK;
+}
+
+static t_Error CreateIpReassCommonTable(t_FmPcdManip *p_Manip)
+{
+ uint32_t tmpReg32 = 0, i;
+ uint64_t tmpReg64, size;
+ t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd;
+ t_Error err = E_OK;
+
+ /* Allocation of the IP Reassembly Common Parameters table. This table is located in the
+ MURAM. Its size is 64 bytes and its base address should be 8-byte aligned.
+ It contains parameters that are common to both the IPv4 reassembly function and IPv6
+ reassembly function.*/
+ p_Manip->ipReassmParams.p_IpReassCommonTbl =
+ (t_IpReassCommonTbl *)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ FM_PCD_MANIP_IP_REASM_COMMON_PARAM_TABLE_SIZE,
+ FM_PCD_MANIP_IP_REASM_COMMON_PARAM_TABLE_ALIGN);
+
+ if (!p_Manip->ipReassmParams.p_IpReassCommonTbl)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly common parameters table"));
+
+ IOMemSet32(p_Manip->ipReassmParams.p_IpReassCommonTbl, 0, FM_PCD_MANIP_IP_REASM_COMMON_PARAM_TABLE_SIZE);
+
+ /* Setting the TimeOut Mode.*/
+ tmpReg32 = 0;
+ if (p_Manip->ipReassmParams.timeOutMode == e_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAMES)
+ tmpReg32 |= FM_PCD_MANIP_IP_REASM_TIME_OUT_BETWEEN_FRAMES;
+
+ /* Setting TimeOut FQID - Frames that time out are enqueued to this FQID.
+ In order to cause TimeOut frames to be discarded, this queue should be configured accordingly*/
+ tmpReg32 |= p_Manip->ipReassmParams.fqidForTimeOutFrames;
+ WRITE_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->timeoutModeAndFqid, tmpReg32);
+
+ /* Calculation the size of IP Reassembly Frame Descriptor - number of frames that are allowed to be reassembled simultaneously + 129.*/
+ size = p_Manip->ipReassmParams.maxNumFramesInProcess + 129;
+
+ /*Allocation of IP Reassembly Frame Descriptor Indexes Pool - This pool resides in the MURAM */
+ p_Manip->ipReassmParams.reassFrmDescrIndxPoolTblAddr =
+ PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ (uint32_t)(size * 2),
+ 256));
+ if (!p_Manip->ipReassmParams.reassFrmDescrIndxPoolTblAddr)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly frame descriptor indexes pool"));
+
+ IOMemSet32(UINT_TO_PTR(p_Manip->ipReassmParams.reassFrmDescrIndxPoolTblAddr), 0, (uint32_t)(size * 2));
+
+ /* The entries in IP Reassembly Frame Descriptor Indexes Pool contains indexes starting with 1 up to
+ the maximum number of frames that are allowed to be reassembled simultaneously + 128.
+ The last entry in this pool must contain the index zero*/
+ for (i=0; i<(size-1); i++)
+ WRITE_UINT16(*(uint16_t *)PTR_MOVE(UINT_TO_PTR(p_Manip->ipReassmParams.reassFrmDescrIndxPoolTblAddr), (i<<1)),
+ (uint16_t)(i+1));
+
+ /* Sets the IP Reassembly Frame Descriptor Indexes Pool offset from MURAM */
+ tmpReg32 = (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Manip->ipReassmParams.reassFrmDescrIndxPoolTblAddr)) - p_FmPcd->physicalMuramBase);
+ WRITE_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->reassFrmDescIndexPoolTblPtr, tmpReg32);
+
+ /* Allocation of the Reassembly Frame Descriptors Pool - This pool resides in external memory.
+ The number of entries in this pool should be equal to the number of entries in IP Reassembly Frame Descriptor Indexes Pool.*/
+ p_Manip->ipReassmParams.reassFrmDescrPoolTblAddr =
+ PTR_TO_UINT(XX_MallocSmart((uint32_t)(size * 64), p_Manip->ipReassmParams.dataMemId, 64));
+
+ if (!p_Manip->ipReassmParams.reassFrmDescrPoolTblAddr)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation FAILED"));
+
+ IOMemSet32(UINT_TO_PTR(p_Manip->ipReassmParams.reassFrmDescrPoolTblAddr), 0, (uint32_t)(size * 64));
+
+ /* Sets the Reassembly Frame Descriptors Pool and liodn offset*/
+ tmpReg64 = (uint64_t)(XX_VirtToPhys(UINT_TO_PTR(p_Manip->ipReassmParams.reassFrmDescrPoolTblAddr)));
+ tmpReg64 |= ((uint64_t)(p_Manip->ipReassmParams.dataLiodnOffset & FM_PCD_MANIP_IP_REASM_LIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_LIODN_SHIFT);
+ tmpReg64 |= ((uint64_t)(p_Manip->ipReassmParams.dataLiodnOffset & FM_PCD_MANIP_IP_REASM_ELIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_ELIODN_SHIFT);
+ WRITE_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->liodnAndReassFrmDescPoolPtrHi, (uint32_t)(tmpReg64 >> 32));
+ WRITE_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->reassFrmDescPoolPtrLow, (uint32_t)tmpReg64);
+
+ /*Allocation of the TimeOut table - This table resides in the MURAM.
+ The number of entries in this table is identical to the number of entries in the Reassembly Frame Descriptors Pool*/
+ p_Manip->ipReassmParams.timeOutTblAddr =
+ PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, (uint32_t)(size * 8),8));
+
+ if (!p_Manip->ipReassmParams.timeOutTblAddr)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly timeout table"));
+
+ IOMemSet32(UINT_TO_PTR(p_Manip->ipReassmParams.timeOutTblAddr), 0, (uint16_t)(size * 8));
+
+ /* Sets the TimeOut table offset from MURAM */
+ tmpReg32 = (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Manip->ipReassmParams.timeOutTblAddr)) - p_FmPcd->physicalMuramBase);
+ WRITE_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->timeOutTblPtr, tmpReg32);
+
+ /* Sets the Expiration Delay */
+ tmpReg32 = 0;
+ tmpReg32 |= (((uint32_t)(1 << FmGetTimeStampScale(p_FmPcd->h_Fm))) * p_Manip->ipReassmParams.timeoutThresholdForReassmProcess);
+ WRITE_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->expirationDelay, tmpReg32);
+
+ err = FmPcdRegisterReassmPort(p_FmPcd, p_Manip->ipReassmParams.p_IpReassCommonTbl);
+ if (err != E_OK)
+ {
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipReassmParams.p_IpReassCommonTbl);
+ RETURN_ERROR(MAJOR, err, ("port registration"));
+ }
+
+ return err;
+}
+
+static t_Error CreateIpReassTable(t_FmPcdManip *p_Manip, bool ipv4)
+{
+ t_FmPcd *p_FmPcd = p_Manip->h_FmPcd;
+ uint32_t tmpReg32, autoLearnHashTblSize;
+ uint32_t numOfWays, setSize, setSizeCode, keySize;
+ uint32_t waySize, numOfSets, numOfEntries;
+ uint64_t tmpReg64;
+ uint16_t minFragSize;
+ uintptr_t *p_AutoLearnHashTblAddr, *p_AutoLearnSetLockTblAddr;
+ t_IpReassTbl **p_IpReassTbl;
+
+ if (ipv4)
+ {
+ p_IpReassTbl = &p_Manip->ipReassmParams.p_Ipv4ReassTbl;
+ p_AutoLearnHashTblAddr = &p_Manip->ipReassmParams.ipv4AutoLearnHashTblAddr;
+ p_AutoLearnSetLockTblAddr = &p_Manip->ipReassmParams.ipv4AutoLearnSetLockTblAddr;
+ minFragSize = p_Manip->ipReassmParams.minFragSize[0];
+ numOfWays = p_Manip->ipReassmParams.numOfFramesPerHashEntry[0];
+ keySize = 4 + 4 + 1 + 2; /* 3-tuple + IP-Id */
+ }
+ else
+ {
+ p_IpReassTbl = &p_Manip->ipReassmParams.p_Ipv6ReassTbl;
+ p_AutoLearnHashTblAddr = &p_Manip->ipReassmParams.ipv6AutoLearnHashTblAddr;
+ p_AutoLearnSetLockTblAddr = &p_Manip->ipReassmParams.ipv6AutoLearnSetLockTblAddr;
+ minFragSize = p_Manip->ipReassmParams.minFragSize[1];
+ numOfWays = p_Manip->ipReassmParams.numOfFramesPerHashEntry[1];
+ keySize = 16 + 16 + 4; /* 2-tuple + IP-Id */
+ if (numOfWays > e_FM_PCD_MANIP_SIX_WAYS_HASH)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("num of ways"));
+ }
+ keySize += 2; /* 2 bytes reserved for RFDIndex */
+#if (DPAA_VERSION >= 11)
+ keySize += 2; /* 2 bytes reserved */
+#endif /* (DPAA_VERSION >= 11) */
+ waySize = ROUND_UP(keySize, 8);
+
+ /* Allocates the IP Reassembly Parameters Table - This table is located in the MURAM.*/
+ *p_IpReassTbl = (t_IpReassTbl *)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ FM_PCD_MANIP_IP_REASM_TABLE_SIZE,
+ FM_PCD_MANIP_IP_REASM_TABLE_ALIGN);
+ if (!*p_IpReassTbl)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly IPv4/IPv6 specific parameters table"));
+ memset(*p_IpReassTbl, 0, sizeof(t_IpReassTbl));
+
+ /* Sets the IP Reassembly common Parameters table offset from MURAM in the IP Reassembly Table descriptor*/
+ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->ipReassmParams.p_IpReassCommonTbl) - p_FmPcd->physicalMuramBase);
+ WRITE_UINT32((*p_IpReassTbl)->ipReassCommonPrmTblPtr, tmpReg32);
+
+ /* Calculate set size (set size is rounded-up to next power of 2) */
+ NEXT_POWER_OF_2(numOfWays * waySize, setSize);
+
+ /* Get set size code */
+ LOG2(setSize, setSizeCode);
+
+ /* Sets ways number and set size code */
+ WRITE_UINT16((*p_IpReassTbl)->waysNumAndSetSize, (uint16_t)((numOfWays << 8) | setSizeCode));
+
+ /* It is recommended that the total number of entries in this table
+ (number of sets * number of ways) will be twice the number of frames that
+ are expected to be reassembled simultaneously.*/
+ numOfEntries = (uint32_t)(p_Manip->ipReassmParams.maxNumFramesInProcess * 2);
+
+ /* sets number calculation - number of entries = number of sets * number of ways */
+ numOfSets = numOfEntries / numOfWays;
+
+ /* Sets AutoLearnHashKeyMask*/
+ NEXT_POWER_OF_2(numOfSets, numOfSets);
+
+ WRITE_UINT16((*p_IpReassTbl)->autoLearnHashKeyMask, (uint16_t)(numOfSets - 1));
+
+ /* Allocation of IP Reassembly Automatic Learning Hash Table - This table resides in external memory.
+ The size of this table is determined by the number of sets and the set size.
+ Table size = set size * number of sets
+ This table base address should be aligned to SetSize.*/
+ autoLearnHashTblSize = numOfSets * setSize;
+
+ *p_AutoLearnHashTblAddr = PTR_TO_UINT(XX_MallocSmart(autoLearnHashTblSize, p_Manip->ipReassmParams.dataMemId, setSize));
+ if (!*p_AutoLearnHashTblAddr)
+ {
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, *p_IpReassTbl);
+ *p_IpReassTbl = NULL;
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation FAILED"));
+ }
+ IOMemSet32(UINT_TO_PTR(*p_AutoLearnHashTblAddr), 0, autoLearnHashTblSize);
+
+ /* Sets the IP Reassembly Automatic Learning Hash Table and liodn offset */
+ tmpReg64 = ((uint64_t)(p_Manip->ipReassmParams.dataLiodnOffset & FM_PCD_MANIP_IP_REASM_LIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_LIODN_SHIFT);
+ tmpReg64 |= ((uint64_t)(p_Manip->ipReassmParams.dataLiodnOffset & FM_PCD_MANIP_IP_REASM_ELIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_ELIODN_SHIFT);
+ tmpReg64 |= XX_VirtToPhys(UINT_TO_PTR(*p_AutoLearnHashTblAddr));
+ WRITE_UINT32((*p_IpReassTbl)->liodnAlAndAutoLearnHashTblPtrHi, (uint32_t)(tmpReg64 >> 32));
+ WRITE_UINT32((*p_IpReassTbl)->autoLearnHashTblPtrLow, (uint32_t)tmpReg64);
+
+ /* Allocation of the Set Lock table - This table resides in external memory
+ The size of this table is (number of sets in the IP Reassembly Automatic Learning Hash table)*4 bytes.
+ This table resides in external memory and its base address should be 4-byte aligned */
+ *p_AutoLearnSetLockTblAddr = PTR_TO_UINT(XX_MallocSmart((uint32_t)(numOfSets * 4), p_Manip->ipReassmParams.dataMemId, 4));
+ if (!*p_AutoLearnSetLockTblAddr)
+ {
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, *p_IpReassTbl);
+ *p_IpReassTbl = NULL;
+ XX_FreeSmart(UINT_TO_PTR(*p_AutoLearnHashTblAddr));
+ *p_AutoLearnHashTblAddr = 0;
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation FAILED"));
+ }
+ IOMemSet32(UINT_TO_PTR(*p_AutoLearnSetLockTblAddr), 0, (numOfSets * 4));
+
+ /* sets Set Lock table pointer and liodn offset*/
+ tmpReg64 = ((uint64_t)(p_Manip->ipReassmParams.dataLiodnOffset & FM_PCD_MANIP_IP_REASM_LIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_LIODN_SHIFT);
+ tmpReg64 |= ((uint64_t)(p_Manip->ipReassmParams.dataLiodnOffset & FM_PCD_MANIP_IP_REASM_ELIODN_MASK) << (uint64_t)FM_PCD_MANIP_IP_REASM_ELIODN_SHIFT);
+ tmpReg64 |= XX_VirtToPhys(UINT_TO_PTR(*p_AutoLearnSetLockTblAddr));
+ WRITE_UINT32((*p_IpReassTbl)->liodnSlAndAutoLearnSetLockTblPtrHi, (uint32_t)(tmpReg64 >> 32));
+ WRITE_UINT32((*p_IpReassTbl)->autoLearnSetLockTblPtrLow, (uint32_t)tmpReg64);
+
+ /* Sets user's requested minimum fragment size (in Bytes) for First/Middle fragment */
+ WRITE_UINT16((*p_IpReassTbl)->minFragSize, minFragSize);
+
+ return E_OK;
+}
+
+static t_Error UpdateInitIpReasm(t_Handle h_FmPcd,
+ t_Handle h_PcdParams,
+ t_Handle h_FmPort,
+ t_FmPcdManip *p_Manip,
+ t_Handle h_Ad,
+ bool validate)
+{
+ t_FmPortGetSetCcParams fmPortGetSetCcParams;
+ uint32_t tmpReg32;
+ t_Error err;
+ t_FmPortPcdParams *p_PcdParams = (t_FmPortPcdParams *)h_PcdParams;
+#if (DPAA_VERSION >= 11)
+ t_FmPcdCtrlParamsPage *p_ParamsPage;
+#endif /* (DPAA_VERSION >= 11) */
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Manip->frag, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Manip->opcode == HMAN_OC_IP_REASSEMBLY), E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Manip->updateParams || h_PcdParams, E_INVALID_HANDLE);
+
+ UNUSED(h_Ad);
+
+ if (!p_Manip->updateParams)
+ return E_OK;
+
+ if (p_Manip->h_FmPcd != h_FmPcd)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("handler of PCD previously was initiated by different value"));
+
+ if (p_Manip->updateParams)
+ {
+ if ((!(p_Manip->updateParams & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS | DISCARD_MASK))) ||
+ ((p_Manip->shadowUpdateParams & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS | DISCARD_MASK))))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has not be updated"));
+
+ fmPortGetSetCcParams.setCcParams.type = 0;
+ fmPortGetSetCcParams.getCcParams.type = p_Manip->updateParams | FM_REV;
+ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if (fmPortGetSetCcParams.getCcParams.type & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS | DISCARD_MASK | FM_REV))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("offset of the data wasn't configured previously"));
+ }
+ else if (validate)
+ {
+ if ((!(p_Manip->shadowUpdateParams & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS | DISCARD_MASK))) ||
+ ((p_Manip->updateParams & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS | DISCARD_MASK))))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("in this stage parameters from Port has be updated"));
+
+ fmPortGetSetCcParams.setCcParams.type = 0;
+ fmPortGetSetCcParams.getCcParams.type = p_Manip->shadowUpdateParams;
+ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if (fmPortGetSetCcParams.getCcParams.type & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS | DISCARD_MASK))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("offset of the data wasn't configured previously"));
+ }
+
+ if (p_Manip->updateParams)
+ {
+ if (p_Manip->updateParams & (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS | DISCARD_MASK))
+ {
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint8_t *p_Ptr, i, totalNumOfTnums;
+
+ totalNumOfTnums = (uint8_t)(fmPortGetSetCcParams.getCcParams.numOfTasks +
+ fmPortGetSetCcParams.getCcParams.numOfExtraTasks);
+
+ p_Manip->ipReassmParams.internalBufferPoolAddr =
+ PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ (uint32_t)(totalNumOfTnums * BMI_FIFO_UNITS),
+ BMI_FIFO_UNITS));
+ if (!p_Manip->ipReassmParams.internalBufferPoolAddr)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly internal buffers pool"));
+ IOMemSet32(UINT_TO_PTR(p_Manip->ipReassmParams.internalBufferPoolAddr),
+ 0,
+ (uint32_t)(totalNumOfTnums * BMI_FIFO_UNITS));
+
+ p_Manip->ipReassmParams.internalBufferPoolManagementIndexAddr =
+ PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ (uint32_t)(5 + totalNumOfTnums),
+ 4));
+ if (!p_Manip->ipReassmParams.internalBufferPoolManagementIndexAddr)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Reassembly internal buffers management"));
+
+ p_Ptr = (uint8_t*)UINT_TO_PTR(p_Manip->ipReassmParams.internalBufferPoolManagementIndexAddr);
+ WRITE_UINT32(*(uint32_t*)p_Ptr, (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Manip->ipReassmParams.internalBufferPoolAddr)) - p_FmPcd->physicalMuramBase));
+ for (i=0, p_Ptr += 4; i < totalNumOfTnums; i++, p_Ptr++)
+ WRITE_UINT8(*p_Ptr, i);
+ WRITE_UINT8(*p_Ptr, 0xFF);
+
+ tmpReg32 = (4 << FM_PCD_MANIP_IP_REASM_COMMON_INT_BUFFER_IDX_SHIFT) |
+ ((uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Manip->ipReassmParams.internalBufferPoolManagementIndexAddr)) - p_FmPcd->physicalMuramBase));
+ WRITE_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->internalBufferManagement, tmpReg32);
+
+ p_Manip->updateParams &= ~(NUM_OF_TASKS | NUM_OF_EXTRA_TASKS | DISCARD_MASK);
+ p_Manip->shadowUpdateParams |= (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS | DISCARD_MASK);
+ }
+ }
+
+ if (p_Manip->ipReassmParams.h_Ipv4Scheme)
+ {
+ p_PcdParams->p_KgParams->h_Schemes[p_PcdParams->p_KgParams->numOfSchemes] = p_Manip->ipReassmParams.h_Ipv4Scheme;
+ p_PcdParams->p_KgParams->numOfSchemes++;
+ }
+ if (p_Manip->ipReassmParams.h_Ipv6Scheme)
+ {
+ p_PcdParams->p_KgParams->h_Schemes[p_PcdParams->p_KgParams->numOfSchemes] = p_Manip->ipReassmParams.h_Ipv6Scheme;
+ p_PcdParams->p_KgParams->numOfSchemes++;
+ }
+
+#if (DPAA_VERSION >= 11)
+ if (fmPortGetSetCcParams.getCcParams.revInfo.majorRev >= 6)
+ {
+ if ((err = FmPortSetGprFunc(h_FmPort, e_FM_PORT_GPR_MURAM_PAGE, (void**)&p_ParamsPage)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ tmpReg32 = NIA_ENG_KG;
+ if (p_Manip->ipReassmParams.h_Ipv4Scheme)
+ {
+ tmpReg32 |= NIA_KG_DIRECT;
+ tmpReg32 |= NIA_KG_CC_EN;
+ tmpReg32 |= FmPcdKgGetSchemeId(p_Manip->ipReassmParams.h_Ipv4Scheme);
+ WRITE_UINT32(p_ParamsPage->iprIpv4Nia, tmpReg32);
+ }
+ if (p_Manip->ipReassmParams.h_Ipv6Scheme)
+ {
+ tmpReg32 &= ~NIA_AC_MASK;
+ tmpReg32 |= NIA_KG_DIRECT;
+ tmpReg32 |= NIA_KG_CC_EN;
+ tmpReg32 |= FmPcdKgGetSchemeId(p_Manip->ipReassmParams.h_Ipv6Scheme);
+ WRITE_UINT32(p_ParamsPage->iprIpv6Nia, tmpReg32);
+ }
+ }
+#else
+ if (fmPortGetSetCcParams.getCcParams.revInfo.majorRev < 6)
+ {
+ WRITE_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->discardMask,
+ fmPortGetSetCcParams.getCcParams.discardMask);
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ return E_OK;
+}
+
+#if (DPAA_VERSION == 10)
+static t_Error FmPcdFragHcScratchPoolFill(t_Handle h_FmPcd, uint8_t scratchBpid)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_FmPcdCcFragScratchPoolCmdParams fmPcdCcFragScratchPoolCmdParams;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+
+ memset(&fmPcdCcFragScratchPoolCmdParams, 0, sizeof(t_FmPcdCcFragScratchPoolCmdParams));
+
+ fmPcdCcFragScratchPoolCmdParams.numOfBuffers = NUM_OF_SCRATCH_POOL_BUFFERS;
+ fmPcdCcFragScratchPoolCmdParams.bufferPoolId = scratchBpid;
+ if ((err = FmHcPcdCcIpFragScratchPollCmd(p_FmPcd->h_Hc, TRUE, &fmPcdCcFragScratchPoolCmdParams)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (fmPcdCcFragScratchPoolCmdParams.numOfBuffers != 0)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Fill scratch pool failed,"
+ "Failed to release %d buffers to the BM (missing FBPRs)",
+ fmPcdCcFragScratchPoolCmdParams.numOfBuffers));
+
+ return E_OK;
+}
+
+static t_Error FmPcdFragHcScratchPoolEmpty(t_Handle h_FmPcd, uint8_t scratchBpid)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_FmPcdCcFragScratchPoolCmdParams fmPcdCcFragScratchPoolCmdParams;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+
+ memset(&fmPcdCcFragScratchPoolCmdParams, 0, sizeof(t_FmPcdCcFragScratchPoolCmdParams));
+
+ fmPcdCcFragScratchPoolCmdParams.bufferPoolId = scratchBpid;
+ if ((err = FmHcPcdCcIpFragScratchPollCmd(p_FmPcd->h_Hc, FALSE, &fmPcdCcFragScratchPoolCmdParams)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ return E_OK;
+}
+#endif /* (DPAA_VERSION == 10) */
+
+static void ReleaseManipHandler(t_FmPcdManip *p_Manip, t_FmPcd *p_FmPcd)
+{
+ if (p_Manip->h_Ad)
+ {
+ if (p_Manip->muramAllocate)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->h_Ad);
+ else
+ XX_Free(p_Manip->h_Ad);
+ p_Manip->h_Ad = NULL;
+ }
+ if (p_Manip->p_Template)
+ {
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->p_Template);
+ p_Manip->p_Template = NULL;
+ }
+ if (p_Manip->h_Frag)
+ {
+ if (p_Manip->fragParams.p_AutoLearnHashTbl)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->fragParams.p_AutoLearnHashTbl);
+ if (p_Manip->fragParams.p_ReassmFrmDescrPoolTbl)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->fragParams.p_ReassmFrmDescrPoolTbl);
+ if (p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->fragParams.p_ReassmFrmDescrIndxPoolTbl);
+ if (p_Manip->fragParams.p_TimeOutTbl)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->fragParams.p_TimeOutTbl);
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->h_Frag);
+
+ }
+ if (p_Manip->frag)
+ {
+ if (p_Manip->ipFragParams.p_Frag)
+ {
+#if (DPAA_VERSION == 10)
+ FmPcdFragHcScratchPoolEmpty((t_Handle)p_FmPcd, p_Manip->ipFragParams.scratchBpid);
+#endif /* (DPAA_VERSION == 10) */
+
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipFragParams.p_Frag);
+ }
+ }
+ else if (p_Manip->reassm)
+ {
+ FmPcdUnregisterReassmPort(p_FmPcd, p_Manip->ipReassmParams.p_IpReassCommonTbl);
+
+ if (p_Manip->ipReassmParams.timeOutTblAddr)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, UINT_TO_PTR(p_Manip->ipReassmParams.timeOutTblAddr));
+ if (p_Manip->ipReassmParams.reassFrmDescrPoolTblAddr)
+ XX_FreeSmart(UINT_TO_PTR(p_Manip->ipReassmParams.reassFrmDescrPoolTblAddr));
+
+ if (p_Manip->ipReassmParams.ipv4AutoLearnHashTblAddr)
+ XX_FreeSmart(UINT_TO_PTR(p_Manip->ipReassmParams.ipv4AutoLearnHashTblAddr));
+ if (p_Manip->ipReassmParams.ipv6AutoLearnHashTblAddr)
+ XX_FreeSmart(UINT_TO_PTR(p_Manip->ipReassmParams.ipv6AutoLearnHashTblAddr));
+ if (p_Manip->ipReassmParams.ipv4AutoLearnSetLockTblAddr)
+ XX_FreeSmart(UINT_TO_PTR(p_Manip->ipReassmParams.ipv4AutoLearnSetLockTblAddr));
+ if (p_Manip->ipReassmParams.ipv6AutoLearnSetLockTblAddr)
+ XX_FreeSmart(UINT_TO_PTR(p_Manip->ipReassmParams.ipv6AutoLearnSetLockTblAddr));
+ if (p_Manip->ipReassmParams.p_Ipv4ReassTbl)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipReassmParams.p_Ipv4ReassTbl);
+ if (p_Manip->ipReassmParams.p_Ipv6ReassTbl)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipReassmParams.p_Ipv6ReassTbl);
+ if (p_Manip->ipReassmParams.p_IpReassCommonTbl)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipReassmParams.p_IpReassCommonTbl);
+ if (p_Manip->ipReassmParams.reassFrmDescrIndxPoolTblAddr)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, UINT_TO_PTR(p_Manip->ipReassmParams.reassFrmDescrIndxPoolTblAddr));
+ if (p_Manip->ipReassmParams.internalBufferPoolManagementIndexAddr)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, UINT_TO_PTR(p_Manip->ipReassmParams.internalBufferPoolManagementIndexAddr));
+ if (p_Manip->ipReassmParams.internalBufferPoolAddr)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, UINT_TO_PTR(p_Manip->ipReassmParams.internalBufferPoolAddr));
+
+ if (p_Manip->ipReassmParams.h_Ipv6Ad)
+ XX_FreeSmart(p_Manip->ipReassmParams.h_Ipv6Ad);
+ if (p_Manip->ipReassmParams.h_Ipv4Ad)
+ XX_FreeSmart(p_Manip->ipReassmParams.h_Ipv4Ad);
+ }
+
+ if (p_Manip->p_StatsTbl)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->p_StatsTbl);
+}
+
+#ifdef FM_CAPWAP_SUPPORT
+static t_Error CheckManipParamsAndSetType(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_ManipParams)
+{
+ if (p_ManipParams->u.hdr.rmv)
+ {
+ switch (p_ManipParams->u.hdr.rmvParams.type)
+ {
+ case (e_FM_PCD_MANIP_RMV_BY_HDR):
+ switch (p_ManipParams->u.hdr.rmvParams.u.byHdr.type)
+ {
+ case (e_FM_PCD_MANIP_RMV_BY_HDR_FROM_START) :
+ if (p_ManipParams->u.hdr.rmvParams.u.byHdr.u.fromStartByHdr.include)
+ {
+ switch (p_ManipParams->u.hdr.rmvParams.u.byHdr.u.fromStartByHdr.hdrInfo.hdr)
+ {
+ case (HEADER_TYPE_CAPWAP_DTLS) :
+ p_Manip->opcode = HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST;
+ p_Manip->muramAllocate = TRUE;
+ if (p_ManipParams->u.hdr.insrt)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for CAPWAP_DTLS_HDR remove can not be insrt manipualtion after"));
+ if (p_ManipParams->fragOrReasm)
+ {
+ if (!p_ManipParams->fragOrReasmParams.frag)
+ {
+ switch (p_ManipParams->fragOrReasmParams.hdr)
+ {
+ case (HEADER_TYPE_CAPWAP):
+ p_Manip->opcode = HMAN_OC_CAPWAP_REASSEMBLY;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("unsupported header for Reassembly"));
+ }
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for this type of manipulation frag can not be TRUE"));
+ }
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("non valid net header of remove location"));
+ }
+ }
+ else
+ {
+ switch (p_ManipParams->u.hdr.rmvParams.u.byHdr.u.fromStartByHdr.hdrInfo.hdr)
+ {
+ case (HEADER_TYPE_CAPWAP_DTLS) :
+ case (HEADER_TYPE_CAPWAP) :
+ if (p_ManipParams->fragOrReasm || p_ManipParams->u.hdr.insrt)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for the type of remove e_FM_PCD_MANIP_RMV_FROM_START_OF_FRAME_TILL_CAPWAP can not be insert or fragOrReasm TRUE"));
+ p_Manip->opcode = HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR;
+ p_Manip->muramAllocate = TRUE;
+ p_ManipParams->u.hdr.insrt = TRUE; //internal frame header
+ break;
+ default :
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation"));
+ }
+ }
+ break;
+ default :
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation"));
+ }
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation"));
+ }
+ }
+ else if (p_ManipParams->u.hdr.insrt)
+ {
+ switch (p_ManipParams->u.hdr.insrtParams.type)
+ {
+ case (e_FM_PCD_MANIP_INSRT_BY_TEMPLATE) :
+
+ p_Manip->opcode = HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER;
+ p_Manip->muramAllocate = FALSE;
+ if (p_ManipParams->fragOrReasm)
+ {
+ if (p_ManipParams->fragOrReasmParams.frag)
+ {
+ switch (p_ManipParams->fragOrReasmParams.hdr)
+ {
+ case (HEADER_TYPE_CAPWAP):
+ p_Manip->opcode = HMAN_OC_CAPWAP_FRAGMENTATION;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid header for fragmentation"));
+ }
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,("can not reach this point"));
+ }
+ break;
+
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for only isert manipulation unsupported type"));
+ }
+ }
+ else if (p_ManipParams->fragOrReasm)
+ {
+ if (p_ManipParams->fragOrReasmParams.frag)
+ {
+ switch (p_ManipParams->fragOrReasmParams.hdr)
+ {
+ case (HEADER_TYPE_CAPWAP):
+ p_Manip->opcode = HMAN_OC_CAPWAP_FRAGMENTATION;
+ p_Manip->muramAllocate = FALSE;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported header for fragmentation"));
+ }
+ }
+ else
+ {
+ switch (p_ManipParams->fragOrReasmParams.hdr)
+ {
+ case (HEADER_TYPE_CAPWAP):
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Reassembly has to be with additional operation - rmv = TRUE, type of remove - e_FM_PCD_MANIP_RMV_FROM_START_OF_FRAME_INCLUDE_SPECIFIC_LOCATION,type = e_FM_PCD_MANIP_LOC_BY_HDR, hdr = HEADER_TYPE_CAPWAP_DTLS"));
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported header for reassembly"));
+ }
+ }
+
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("User didn't ask for any manipulation"));
+
+ p_Manip->insrt = p_ManipParams->u.hdr.insrt;
+ p_Manip->rmv = p_ManipParams->u.hdr.rmv;
+
+ return E_OK;
+}
+
+#else /* not FM_CAPWAP_SUPPORT */
+static t_Error CheckManipParamsAndSetType(t_FmPcdManip *p_Manip, t_FmPcdManipParams *p_ManipParams)
+{
+ switch (p_ManipParams->type)
+ {
+ case e_FM_PCD_MANIP_HDR :
+ /* Check that next-manip is not already used */
+ if (p_ManipParams->h_NextManip)
+ {
+ if (!MANIP_IS_FIRST(p_ManipParams->h_NextManip))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("h_NextManip is already a part of another chain"));
+ if (MANIP_GET_TYPE(p_ManipParams->h_NextManip) != e_FM_PCD_MANIP_HDR)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("For a Header Manipulation node - no support of h_NextManip of type other than Header Manipulation."));
+ }
+
+ if (p_ManipParams->u.hdr.rmv)
+ {
+ switch (p_ManipParams->u.hdr.rmvParams.type)
+ {
+ case (e_FM_PCD_MANIP_RMV_BY_HDR):
+ switch (p_ManipParams->u.hdr.rmvParams.u.byHdr.type)
+ {
+ case (e_FM_PCD_MANIP_RMV_BY_HDR_SPECIFIC_L2) :
+ p_Manip->opcode = HMAN_OC;
+ p_Manip->muramAllocate = TRUE;
+ break;
+ default :
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation"));
+ }
+ break;
+ case (e_FM_PCD_MANIP_RMV_GENERIC):
+ p_Manip->opcode = HMAN_OC;
+ p_Manip->muramAllocate = TRUE;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid type of remove manipulation"));
+ }
+ p_Manip->rmv = TRUE;
+ }
+ else if (p_ManipParams->u.hdr.insrt)
+ {
+ switch (p_ManipParams->u.hdr.insrtParams.type)
+ {
+ case (e_FM_PCD_MANIP_INSRT_BY_HDR) :
+ case (e_FM_PCD_MANIP_INSRT_GENERIC):
+ p_Manip->opcode = HMAN_OC;
+ p_Manip->muramAllocate = TRUE;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("for only isert manipulation unsupported type"));
+ }
+ p_Manip->insrt = TRUE;
+ }
+ else if (p_ManipParams->u.hdr.fieldUpdate)
+ {
+ /* Check parameters */
+ if (p_ManipParams->u.hdr.fieldUpdateParams.type == e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN)
+ {
+ if ((p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType == e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN_VPRI)
+ && (p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.u.vpri > 7))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("vpri should get values of 0-7 "));
+ if (p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.updateType == e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN)
+ {
+ int i;
+
+ if (p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.u.dscpToVpri.vpriDefVal > 7)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("vpriDefVal should get values of 0-7 "));
+ for (i = 0 ; i < FM_PCD_MANIP_DSCP_TO_VLAN_TRANS ; i++)
+ if (p_ManipParams->u.hdr.fieldUpdateParams.u.vlan.u.dscpToVpri.dscpToVpriTable[i] & 0xf0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dscpToVpriTabl value out of range (0-15)"));
+ }
+
+ }
+
+ p_Manip->opcode = HMAN_OC;
+ p_Manip->muramAllocate = TRUE;
+ p_Manip->fieldUpdate = TRUE;
+ }
+ else if (p_ManipParams->u.hdr.custom)
+ {
+ p_Manip->opcode = HMAN_OC;
+ p_Manip->muramAllocate = TRUE;
+ p_Manip->custom = TRUE;
+ }
+ break;
+ case e_FM_PCD_MANIP_REASSEM :
+ if (p_ManipParams->h_NextManip)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("next manip with reassembly"));
+ switch (p_ManipParams->u.reassem.hdr)
+ {
+ case (HEADER_TYPE_IPv4):
+ p_Manip->ipReassmParams.hdr = HEADER_TYPE_IPv4;
+ break;
+ case (HEADER_TYPE_IPv6):
+ p_Manip->ipReassmParams.hdr = HEADER_TYPE_IPv6;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("header for reassembly"));
+ }
+ p_Manip->opcode = HMAN_OC_IP_REASSEMBLY;
+ break;
+ case e_FM_PCD_MANIP_FRAG :
+ if (p_ManipParams->h_NextManip)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("next manip with fragmentation"));
+ switch (p_ManipParams->u.frag.hdr)
+ {
+ case (HEADER_TYPE_IPv4):
+ case (HEADER_TYPE_IPv6):
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("header for fragmentation"));
+ }
+ p_Manip->opcode = HMAN_OC_IP_FRAGMENTATION;
+ p_Manip->muramAllocate = TRUE;
+ break;
+ case e_FM_PCD_MANIP_SPECIAL_OFFLOAD :
+ switch (p_ManipParams->u.specialOffload.type)
+ {
+ case (e_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC):
+ p_Manip->opcode = HMAN_OC_IPSEC_MANIP;
+ p_Manip->muramAllocate = TRUE;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("special offload type"));
+ }
+ break;
+ default :
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("manip type"));
+ }
+
+ return E_OK;
+}
+#endif /* not FM_CAPWAP_SUPPORT */
+
+#ifdef FM_CAPWAP_SUPPORT
+static t_Error UpdateIndxStats(t_Handle h_FmPcd,
+ t_Handle h_FmPort,
+ t_FmPcdManip *p_Manip)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint32_t tmpReg32 = 0;
+ t_AdOfTypeContLookup *p_Ad;
+ t_FmPortGetSetCcParams fmPortGetSetCcParams;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE);
+
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
+ if (p_Manip->h_FmPcd != h_FmPcd)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,
+ ("handler of PCD previously was initiated by different value"));
+
+ memset(&fmPortGetSetCcParams, 0, sizeof(t_FmPortGetSetCcParams));
+
+ if (!p_Manip->p_StatsTbl)
+ {
+
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNDN;
+ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_CC;
+ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ tmpReg32 = GET_UINT32(p_Ad->ccAdBase);
+
+ p_Manip->p_StatsTbl =
+ (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ (uint32_t)p_Manip->owner * FM_PCD_MANIP_INDEXED_STATS_ENTRY_SIZE,
+ 4);
+ if (!p_Manip->p_StatsTbl)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Manipulation indexed statistics table"));
+
+ IOMemSet32(p_Manip->p_StatsTbl, 0, (uint32_t)(p_Manip->owner * 4));
+
+ tmpReg32 |= (uint32_t)(XX_VirtToPhys(p_Manip->p_StatsTbl) - p_FmPcd->physicalMuramBase);
+
+ if (p_Manip->cnia)
+ tmpReg32 |= FM_PCD_MANIP_INDEXED_STATS_CNIA;
+
+ tmpReg32 |= FM_PCD_MANIP_INDEXED_STATS_DPD;
+ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32);
+ }
+ else
+ {
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNDN;
+ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_CC;
+ err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ return E_OK;
+}
+
+static t_Error GetPrOffsetByHeaderOrField(t_FmManipHdrInfo *p_HdrInfo, uint8_t *parseArrayOffset)
+{
+ e_NetHeaderType hdr = p_HdrInfo->hdr;
+ e_FmPcdHdrIndex hdrIndex = p_HdrInfo->hdrIndex;
+ bool byField = p_HdrInfo->byField;
+ t_FmPcdFields field;
+
+ if (byField)
+ field = p_HdrInfo->fullField;
+
+ if (byField)
+ {
+ switch (hdr)
+ {
+ case (HEADER_TYPE_ETH):
+ switch (field.eth)
+ {
+ case (NET_HEADER_FIELD_ETH_TYPE):
+ *parseArrayOffset = CC_PC_PR_ETYPE_LAST_OFFSET;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Header manipulation of the type Ethernet with this field not supported"));
+ }
+ break;
+ case (HEADER_TYPE_VLAN):
+ switch (field.vlan)
+ {
+ case (NET_HEADER_FIELD_VLAN_TCI) :
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ *parseArrayOffset = CC_PC_PR_VLAN1_OFFSET;
+ else if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
+ *parseArrayOffset = CC_PC_PR_VLAN2_OFFSET;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Header manipulation of the type VLAN with this field not supported"));
+ }
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Header manipulation of this header by field not supported"));
+ }
+ }
+ else
+ {
+ switch (hdr){
+ case (HEADER_TYPE_ETH):
+ *parseArrayOffset = (uint8_t)CC_PC_PR_ETH_OFFSET;
+ break;
+ case (HEADER_TYPE_USER_DEFINED_SHIM1):
+ *parseArrayOffset = (uint8_t)CC_PC_PR_USER_DEFINED_SHIM1_OFFSET;
+ break;
+ case (HEADER_TYPE_USER_DEFINED_SHIM2):
+ *parseArrayOffset = (uint8_t)CC_PC_PR_USER_DEFINED_SHIM2_OFFSET;
+ break;
+ case (HEADER_TYPE_LLC_SNAP):
+ *parseArrayOffset = CC_PC_PR_USER_LLC_SNAP_OFFSET;
+ break;
+ case (HEADER_TYPE_PPPoE):
+ *parseArrayOffset = CC_PC_PR_PPPOE_OFFSET;
+ break;
+ case (HEADER_TYPE_MPLS):
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ *parseArrayOffset = CC_PC_PR_MPLS1_OFFSET;
+ else if (hdrIndex == e_FM_PCD_HDR_INDEX_LAST)
+ *parseArrayOffset = CC_PC_PR_MPLS_LAST_OFFSET;
+ break;
+ case (HEADER_TYPE_IPv4):
+ case (HEADER_TYPE_IPv6):
+ if ((hdrIndex == e_FM_PCD_HDR_INDEX_NONE) || (hdrIndex == e_FM_PCD_HDR_INDEX_1))
+ *parseArrayOffset = CC_PC_PR_IP1_OFFSET;
+ else if (hdrIndex == e_FM_PCD_HDR_INDEX_2)
+ *parseArrayOffset = CC_PC_PR_IP_LAST_OFFSET;
+ break;
+ case (HEADER_TYPE_MINENCAP):
+ *parseArrayOffset = CC_PC_PR_MINENC_OFFSET;
+ break;
+ case (HEADER_TYPE_GRE):
+ *parseArrayOffset = CC_PC_PR_GRE_OFFSET;
+ break;
+ case (HEADER_TYPE_TCP):
+ case (HEADER_TYPE_UDP):
+ case (HEADER_TYPE_IPSEC_AH):
+ case (HEADER_TYPE_IPSEC_ESP):
+ case (HEADER_TYPE_DCCP):
+ case (HEADER_TYPE_SCTP):
+ *parseArrayOffset = CC_PC_PR_L4_OFFSET;
+ break;
+ case (HEADER_TYPE_CAPWAP):
+ case (HEADER_TYPE_CAPWAP_DTLS):
+ *parseArrayOffset = CC_PC_PR_NEXT_HEADER_OFFSET;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Header manipulation of this header is not supported"));
+ }
+ }
+ return E_OK;
+}
+
+static t_Error RmvHdrTillSpecLocNOrInsrtIntFrmHdr(t_FmPcdManipHdrRmvParams *p_ManipParams, t_FmPcdManip *p_Manip)
+{
+ t_AdOfTypeContLookup *p_Ad;
+ uint32_t tmpReg32 = 0;
+ uint8_t prsArrayOffset = 0;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip,E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_ManipParams,E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE);
+
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
+ if (p_Manip->rmv)
+ {
+ err = GetPrOffsetByHeaderOrField(&p_ManipParams->u.byHdr.u.fromStartByHdr.hdrInfo, &prsArrayOffset);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ tmpReg32 |= (uint32_t)prsArrayOffset << 24;
+ tmpReg32 |= HMAN_RMV_HDR;
+ }
+
+ if (p_Manip->insrt)
+ tmpReg32 |= HMAN_INSRT_INT_FRM_HDR;
+
+ tmpReg32 |= (uint32_t)HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR;
+
+ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32);
+
+ tmpReg32 = 0;
+ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE;
+ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32);
+
+ return E_OK;
+}
+#endif /* FM_CAPWAP_SUPPORT */
+
+static t_Error MvIntFrameHeaderFromFrameToBufferPrefix(t_FmPcdManip *p_Manip, bool caamUsed)
+{
+ t_AdOfTypeContLookup *p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
+ uint32_t tmpReg32 = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Ad,E_INVALID_HANDLE);
+
+ p_Manip->updateParams |= OFFSET_OF_PR | INTERNAL_CONTEXT_OFFSET;
+
+ tmpReg32 = 0;
+ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE;
+ *(uint32_t *)&p_Ad->ccAdBase = tmpReg32;
+
+ tmpReg32 = 0;
+ tmpReg32 |= HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX;
+ tmpReg32 |= (uint32_t)0x16 << 16;
+ *(uint32_t *)&p_Ad->pcAndOffsets = tmpReg32;
+
+ if (caamUsed)
+ *(uint32_t *)&p_Ad->gmask = 0xf0000000;
+
+ return E_OK;
+}
+
+#ifdef FM_CAPWAP_SUPPORT
+static t_Error CapwapRmvDtlsHdr(t_FmPcd *p_FmPcd, t_FmPcdManip *p_Manip)
+{
+ t_AdOfTypeContLookup *p_Ad;
+ uint32_t tmpReg32 = 0;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE);
+
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
+
+ tmpReg32 = 0;
+ tmpReg32 |= (uint32_t)HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST;
+ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32);
+
+ tmpReg32 = 0;
+ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE;
+
+
+ if (p_Manip->h_Frag)
+ {
+ p_Manip->updateParams |= INTERNAL_CONTEXT_OFFSET;
+ tmpReg32 |= (uint32_t)(XX_VirtToPhys(p_Manip->h_Frag) - (p_FmPcd->physicalMuramBase));
+ }
+
+ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32);
+
+ return err;
+}
+
+static t_Error CapwapReassembly(t_CapwapReassemblyParams *p_ManipParams,
+ t_FmPcdManip *p_Manip,
+ t_FmPcd *p_FmPcd,
+ uint8_t poolId)
+{
+ t_Handle p_Table;
+ uint32_t tmpReg32 = 0;
+ int i = 0;
+ uint8_t log2Num;
+ uint8_t numOfSets;
+ uint32_t j = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ if (!p_FmPcd->h_Hc)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("hc port has to be initialized in this mode"));
+ if (!POWER_OF_2(p_ManipParams->timeoutRoutineRequestTime))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("timeoutRoutineRequestTime has to be power of 2"));
+ if (!POWER_OF_2(p_ManipParams->maxNumFramesInProcess))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("maxNumFramesInProcess has to be power of 2"));
+ if (!p_ManipParams->timeoutRoutineRequestTime && p_ManipParams->timeoutThresholdForReassmProcess)
+ DBG(WARNING, ("if timeoutRoutineRequestTime 0, timeoutThresholdForReassmProcess is uselessly"));
+ if (p_ManipParams->numOfFramesPerHashEntry == e_FM_PCD_MANIP_FOUR_WAYS_HASH)
+ {
+ if ((p_ManipParams->maxNumFramesInProcess < 4) ||
+ (p_ManipParams->maxNumFramesInProcess > 512))
+ RETURN_ERROR(MAJOR,E_INVALID_VALUE, ("In the case of numOfFramesPerHashEntry = e_FM_PCD_MANIP_EIGHT_WAYS_HASH maxNumFramesInProcess has to be in the range 4-512"));
+ }
+ else
+ {
+ if ((p_ManipParams->maxNumFramesInProcess < 8) ||
+ (p_ManipParams->maxNumFramesInProcess > 2048))
+ RETURN_ERROR(MAJOR,E_INVALID_VALUE, ("In the case of numOfFramesPerHashEntry = e_FM_PCD_MANIP_FOUR_WAYS_HASH maxNumFramesInProcess has to be in the range 8-2048"));
+ }
+
+ p_Manip->updateParams |= (NUM_OF_TASKS | OFFSET_OF_PR | OFFSET_OF_DATA | HW_PORT_ID);
+
+ p_Manip->h_Frag = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ FM_PCD_MANIP_CAPWAP_REASM_TABLE_SIZE,
+ FM_PCD_MANIP_CAPWAP_REASM_TABLE_ALIGN);
+ if (!p_Manip->h_Frag)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc CAPWAP reassembly parameters table"));
+
+ IOMemSet32(p_Manip->h_Frag, 0, FM_PCD_MANIP_CAPWAP_REASM_TABLE_SIZE);
+
+ p_Table = (t_CapwapReasmPram *)p_Manip->h_Frag;
+
+ p_Manip->fragParams.p_AutoLearnHashTbl =
+ (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ (uint32_t)(p_ManipParams->maxNumFramesInProcess * 2 * FM_PCD_MANIP_CAPWAP_REASM_AUTO_LEARNING_HASH_ENTRY_SIZE),
+ FM_PCD_MANIP_CAPWAP_REASM_TABLE_ALIGN);
+
+ if (!p_Manip->fragParams.p_AutoLearnHashTbl)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY,("MURAM alloc for CAPWAP automatic learning hash table"));
+
+ IOMemSet32(p_Manip->fragParams.p_AutoLearnHashTbl, 0, (uint32_t)(p_ManipParams->maxNumFramesInProcess * 2 * FM_PCD_MANIP_CAPWAP_REASM_AUTO_LEARNING_HASH_ENTRY_SIZE));
+
+
+ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->fragParams.p_AutoLearnHashTbl) - p_FmPcd->physicalMuramBase);
+
+ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->autoLearnHashTblPtr, tmpReg32);
+
+ tmpReg32 = 0;
+ if (p_ManipParams->timeOutMode == e_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAMES)
+ tmpReg32 |= FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_BETWEEN_FRAMES;
+ if (p_ManipParams->haltOnDuplicationFrag)
+ tmpReg32 |= FM_PCD_MANIP_CAPWAP_REASM_HALT_ON_DUPLICATE_FRAG;
+ if (p_ManipParams->numOfFramesPerHashEntry == e_FM_PCD_MANIP_EIGHT_WAYS_HASH)
+ {
+ i = 8;
+ tmpReg32 |= FM_PCD_MANIP_CAPWAP_REASM_AUTOMATIC_LEARNIN_HASH_8_WAYS;
+ }
+ else
+ i = 4;
+
+ numOfSets = (uint8_t)((p_ManipParams->maxNumFramesInProcess * 2) / i);
+ LOG2(numOfSets, log2Num);
+ tmpReg32 |= (uint32_t)(log2Num - 1) << 24;
+
+ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->mode, tmpReg32);
+
+ for (j=0; j<p_ManipParams->maxNumFramesInProcess*2; j++)
+ if (((j / i) % 2)== 0)
+ WRITE_UINT32(*(uint32_t *)PTR_MOVE(p_Manip->fragParams.p_AutoLearnHashTbl, j * FM_PCD_MANIP_CAPWAP_REASM_AUTO_LEARNING_HASH_ENTRY_SIZE), 0x80000000);
+
+ tmpReg32 = 0x00008000;
+ tmpReg32 |= (uint32_t)poolId << 16;
+ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->bufferPoolIdAndRisc1SetIndexes, tmpReg32);
+ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->risc23SetIndexes, 0x80008000);
+ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->risc4SetIndexesAndExtendedStatsTblPtr, 0x80000000);
+
+ p_Manip->fragParams.maxNumFramesInProcess = p_ManipParams->maxNumFramesInProcess;
+
+ p_Manip->fragParams.sgBpid = poolId;
+
+ p_Manip->fragParams.fqidForTimeOutFrames = p_ManipParams->fqidForTimeOutFrames;
+ p_Manip->fragParams.timeoutRoutineRequestTime = p_ManipParams->timeoutRoutineRequestTime;
+ p_Manip->fragParams.bitFor1Micro = FmGetTimeStampScale(p_FmPcd->h_Fm);
+
+ tmpReg32 = 0;
+ tmpReg32 |= (((uint32_t)1<<p_Manip->fragParams.bitFor1Micro) * p_ManipParams->timeoutThresholdForReassmProcess);
+ WRITE_UINT32(((t_CapwapReasmPram *)p_Table)->expirationDelay, tmpReg32);
+
+ return E_OK;
+}
+
+static t_Error CapwapFragmentation(t_CapwapFragmentationParams *p_ManipParams,
+ t_FmPcdManip *p_Manip,
+ t_FmPcd *p_FmPcd,
+ uint8_t poolId)
+{
+ t_AdOfTypeContLookup *p_Ad;
+ uint32_t tmpReg32 = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE);
+
+ p_Manip->updateParams |= OFFSET_OF_DATA;
+
+ p_Manip->frag = TRUE;
+
+ p_Manip->h_Frag = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ FM_PCD_CC_AD_ENTRY_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!p_Manip->h_Frag)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for CAPWAP fragmentation table descriptor"));
+
+ IOMemSet32(p_Manip->h_Frag, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Frag;
+
+ tmpReg32 = 0;
+ tmpReg32 |= (uint32_t)HMAN_OC_CAPWAP_FRAGMENTATION;
+
+ if (p_ManipParams->headerOptionsCompr)
+ tmpReg32 |= FM_PCD_MANIP_CAPWAP_FRAG_COMPR_OPTION_FIELD_EN;
+ tmpReg32 |= ((uint32_t)poolId << 8);
+ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32);
+
+ tmpReg32 = 0;
+ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE;
+ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32);
+
+ p_Manip->sizeForFragmentation = p_ManipParams->sizeForFragmentation;
+ p_Manip->fragParams.sgBpid = poolId;
+
+ return E_OK;
+}
+#endif /* FM_CAPWAP_SUPPORT */
+
+static t_Error FillReassmManipParams(t_FmPcdManip *p_Manip, bool ipv4)
+{
+ t_AdOfTypeContLookup *p_Ad;
+ t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd;
+ uint32_t tmpReg32;
+ t_Error err = E_OK;
+
+ /* Creates the IP Reassembly Parameters table. It contains parameters that are specific to either the IPv4 reassembly
+ function or to the IPv6 reassembly function. If both IPv4 reassembly and IPv6 reassembly are required, then
+ two separate IP Reassembly Parameter tables are required.*/
+ if ((err = CreateIpReassTable(p_Manip, ipv4)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ /* Sets the first Ad register (ccAdBase) - Action Descriptor Type and Pointer to the IP Reassembly Parameters Table offset from MURAM*/
+ tmpReg32 = 0;
+ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE;
+
+ /* Gets the required Action descriptor table pointer */
+ if (ipv4)
+ {
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->ipReassmParams.h_Ipv4Ad;
+ tmpReg32 |= (uint32_t)(XX_VirtToPhys(p_Manip->ipReassmParams.p_Ipv4ReassTbl) - (p_FmPcd->physicalMuramBase));
+ }
+ else
+ {
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->ipReassmParams.h_Ipv6Ad;
+ tmpReg32 |= (uint32_t)(XX_VirtToPhys(p_Manip->ipReassmParams.p_Ipv6ReassTbl) - (p_FmPcd->physicalMuramBase));
+ }
+
+ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32);
+
+ /* Sets the second Ad register (matchTblPtr) - Buffer pool ID (BPID for V2) and Scatter/Gather table offset*/
+ /* mark the Scatter/Gather table offset to be set later on when the port will be known */
+ p_Manip->updateParams = (NUM_OF_TASKS | NUM_OF_EXTRA_TASKS | DISCARD_MASK);
+
+#if (DPAA_VERSION == 10)
+ tmpReg32 = (uint32_t)(p_Manip->ipReassmParams.sgBpid << 8);
+ WRITE_UINT32(p_Ad->matchTblPtr, tmpReg32);
+#endif /* (DPAA_VERSION == 10) */
+#if (DPAA_VERSION >= 11)
+ if (p_Manip->ipReassmParams.nonConsistentSpFqid != 0)
+ {
+ tmpReg32 = FM_PCD_AD_NCSPFQIDM_MASK | (uint32_t)(p_Manip->ipReassmParams.nonConsistentSpFqid);
+ WRITE_UINT32(p_Ad->gmask, tmpReg32);
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ /* Sets the third Ad register (pcAndOffsets)- IP Reassemble Operation Code*/
+ tmpReg32 = 0;
+ tmpReg32 |= (uint32_t)HMAN_OC_IP_REASSEMBLY;
+ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32);
+
+ p_Manip->reassm = TRUE;
+
+ return E_OK;
+}
+
+static t_Error SetIpv4ReassmManip(t_FmPcdManip *p_Manip)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd;
+
+ /* Allocation if IPv4 Action descriptor */
+ p_Manip->ipReassmParams.h_Ipv4Ad =
+ (t_Handle)XX_MallocSmart(FM_PCD_CC_AD_ENTRY_SIZE,
+ p_Manip->ipReassmParams.dataMemId,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!p_Manip->ipReassmParams.h_Ipv4Ad)
+ {
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of IPv4 table descriptor"));
+ }
+
+ memset(p_Manip->ipReassmParams.h_Ipv4Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ /* Fill reassembly manipulation parameter in the IP Reassembly Action Descriptor */
+ return FillReassmManipParams(p_Manip, TRUE);
+}
+
+static t_Error SetIpv6ReassmManip(t_FmPcdManip *p_Manip)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)p_Manip->h_FmPcd;
+
+ /* Allocation if IPv6 Action descriptor */
+ p_Manip->ipReassmParams.h_Ipv6Ad =
+ (t_Handle)XX_MallocSmart(FM_PCD_CC_AD_ENTRY_SIZE,
+ p_Manip->ipReassmParams.dataMemId,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!p_Manip->ipReassmParams.h_Ipv6Ad)
+ {
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of IPv6 table descriptor"));
+ }
+
+ memset(p_Manip->ipReassmParams.h_Ipv6Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ /* Fill reassembly manipulation parameter in the IP Reassembly Action Descriptor */
+ return FillReassmManipParams(p_Manip, FALSE);
+}
+
+static t_Error IpReassembly(t_FmPcdManipReassemParams *p_ManipReassmParams,
+ t_FmPcdManip *p_Manip)
+{
+ uint32_t maxSetNumber = 10000;
+ t_FmPcdManipReassemIpParams reassmManipParams = p_ManipReassmParams->u.ipReassem;
+ t_Error res;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(((t_FmPcd *)p_Manip->h_FmPcd)->h_Hc, E_INVALID_HANDLE);
+
+ /* Check validation of user's parameter.*/
+ if ((reassmManipParams.timeoutThresholdForReassmProcess < 1000) ||
+ (reassmManipParams.timeoutThresholdForReassmProcess > 8000000))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("timeoutThresholdForReassmProcess should be 1msec - 8sec"));
+ /* It is recommended that the total number of entries in this table (number of sets * number of ways)
+ will be twice the number of frames that are expected to be reassembled simultaneously.*/
+ if (reassmManipParams.maxNumFramesInProcess >
+ (reassmManipParams.maxNumFramesInProcess * maxSetNumber / 2))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("maxNumFramesInProcess has to be less than (maximun set number * number of ways / 2)"));
+
+ if ((p_ManipReassmParams->hdr == HEADER_TYPE_IPv6) &&
+ (reassmManipParams.minFragSize[1] < 256))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("minFragSize[1] must be >= 256"));
+
+ /* Saves user's reassembly manipulation parameters */
+ p_Manip->ipReassmParams.relativeSchemeId[0] = reassmManipParams.relativeSchemeId[0];
+ p_Manip->ipReassmParams.relativeSchemeId[1] = reassmManipParams.relativeSchemeId[1];
+ p_Manip->ipReassmParams.numOfFramesPerHashEntry[0] = reassmManipParams.numOfFramesPerHashEntry[0];
+ p_Manip->ipReassmParams.numOfFramesPerHashEntry[1] = reassmManipParams.numOfFramesPerHashEntry[1];
+ p_Manip->ipReassmParams.minFragSize[0] = reassmManipParams.minFragSize[0];
+ p_Manip->ipReassmParams.minFragSize[1] = reassmManipParams.minFragSize[1];
+ p_Manip->ipReassmParams.maxNumFramesInProcess = reassmManipParams.maxNumFramesInProcess;
+ p_Manip->ipReassmParams.timeOutMode = reassmManipParams.timeOutMode;
+ p_Manip->ipReassmParams.fqidForTimeOutFrames = reassmManipParams.fqidForTimeOutFrames;
+ p_Manip->ipReassmParams.timeoutThresholdForReassmProcess = reassmManipParams.timeoutThresholdForReassmProcess;
+ p_Manip->ipReassmParams.dataMemId = reassmManipParams.dataMemId;
+ p_Manip->ipReassmParams.dataLiodnOffset = reassmManipParams.dataLiodnOffset;
+#if (DPAA_VERSION == 10)
+ p_Manip->ipReassmParams.sgBpid = reassmManipParams.sgBpid;
+#endif /* (DPAA_VERSION == 10) */
+#if (DPAA_VERSION >= 11)
+ if (reassmManipParams.nonConsistentSpFqid != 0)
+ {
+ p_Manip->ipReassmParams.nonConsistentSpFqid = reassmManipParams.nonConsistentSpFqid;
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ /* Creates and initializes the IP Reassembly common parameter table */
+ CreateIpReassCommonTable(p_Manip);
+
+ /* Creation of IPv4 reassembly manipulation */
+ if ((p_Manip->ipReassmParams.hdr == HEADER_TYPE_IPv6) || (p_Manip->ipReassmParams.hdr == HEADER_TYPE_IPv4))
+ {
+ res = SetIpv4ReassmManip(p_Manip);
+ if (res != E_OK)
+ return res;
+ }
+
+ /* Creation of IPv6 reassembly manipulation */
+ if (p_Manip->ipReassmParams.hdr == HEADER_TYPE_IPv6)
+ {
+ res = SetIpv6ReassmManip(p_Manip);
+ if (res != E_OK)
+ return res;
+ }
+
+ return E_OK;
+}
+
+static void setReassmSchemeParams(t_FmPcd* p_FmPcd, t_FmPcdKgSchemeParams *p_Scheme, t_Handle h_CcTree, bool ipv4, uint8_t groupId)
+{
+ uint32_t j;
+ uint8_t res;
+
+ /* Configures scheme's network environment parameters */
+ p_Scheme->netEnvParams.numOfDistinctionUnits = 2;
+ if (ipv4)
+ res = FmPcdNetEnvGetUnitId(p_FmPcd, FmPcdGetNetEnvId(p_Scheme->netEnvParams.h_NetEnv), HEADER_TYPE_IPv4, FALSE, 0);
+ else
+ res = FmPcdNetEnvGetUnitId(p_FmPcd, FmPcdGetNetEnvId(p_Scheme->netEnvParams.h_NetEnv), HEADER_TYPE_IPv6, FALSE, 0);
+ ASSERT_COND(res != FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS);
+ p_Scheme->netEnvParams.unitIds[0] = res;
+
+ res = FmPcdNetEnvGetUnitId(p_FmPcd, FmPcdGetNetEnvId(p_Scheme->netEnvParams.h_NetEnv), HEADER_TYPE_USER_DEFINED_SHIM2, FALSE, 0);
+ ASSERT_COND(res != FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS);
+ p_Scheme->netEnvParams.unitIds[1] = res;
+
+ /* Configures scheme's next engine parameters*/
+ p_Scheme->nextEngine = e_FM_PCD_CC;
+ p_Scheme->kgNextEngineParams.cc.h_CcTree = h_CcTree;
+ p_Scheme->kgNextEngineParams.cc.grpId = groupId;
+ p_Scheme->useHash = TRUE;
+
+ /* Configures scheme's key*/
+ if (ipv4 == TRUE)
+ {
+ p_Scheme->keyExtractAndHashParams.numOfUsedExtracts = 4;
+ p_Scheme->keyExtractAndHashParams.extractArray[0].type = e_FM_PCD_EXTRACT_BY_HDR;
+ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.type = e_FM_PCD_EXTRACT_FULL_FIELD;
+ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.hdr = HEADER_TYPE_IPv4 ;
+ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.extractByHdrType.fullField.ipv4 = NET_HEADER_FIELD_IPv4_DST_IP;
+ p_Scheme->keyExtractAndHashParams.extractArray[1].type = e_FM_PCD_EXTRACT_BY_HDR;
+ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.type = e_FM_PCD_EXTRACT_FULL_FIELD;
+ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.hdr = HEADER_TYPE_IPv4;
+ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.extractByHdrType.fullField.ipv4 = NET_HEADER_FIELD_IPv4_SRC_IP;
+ p_Scheme->keyExtractAndHashParams.extractArray[2].type = e_FM_PCD_EXTRACT_BY_HDR;
+ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.type = e_FM_PCD_EXTRACT_FULL_FIELD;
+ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.hdr = HEADER_TYPE_IPv4;
+ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.extractByHdrType.fullField.ipv4 = NET_HEADER_FIELD_IPv4_PROTO;
+ p_Scheme->keyExtractAndHashParams.extractArray[3].type = e_FM_PCD_EXTRACT_BY_HDR;
+ p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.hdr = HEADER_TYPE_IPv4;
+ p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR;
+ p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.ignoreProtocolValidation = FALSE;
+ p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.extractByHdrType.fromHdr.size = 2;
+ p_Scheme->keyExtractAndHashParams.extractArray[3].extractByHdr.extractByHdrType.fromHdr.offset = 4;
+ }
+ else /* IPv6 */
+ {
+ p_Scheme->keyExtractAndHashParams.numOfUsedExtracts = 3;
+ p_Scheme->keyExtractAndHashParams.extractArray[0].type = e_FM_PCD_EXTRACT_BY_HDR;
+ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.type = e_FM_PCD_EXTRACT_FULL_FIELD;
+ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.hdr = HEADER_TYPE_IPv6 ;
+ p_Scheme->keyExtractAndHashParams.extractArray[0].extractByHdr.extractByHdrType.fullField.ipv6 = NET_HEADER_FIELD_IPv6_DST_IP;
+ p_Scheme->keyExtractAndHashParams.extractArray[1].type = e_FM_PCD_EXTRACT_BY_HDR;
+ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.type = e_FM_PCD_EXTRACT_FULL_FIELD;
+ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.hdr = HEADER_TYPE_IPv6;
+ p_Scheme->keyExtractAndHashParams.extractArray[1].extractByHdr.extractByHdrType.fullField.ipv6 = NET_HEADER_FIELD_IPv6_SRC_IP;
+ p_Scheme->keyExtractAndHashParams.extractArray[2].type = e_FM_PCD_EXTRACT_BY_HDR;
+ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.hdr = HEADER_TYPE_USER_DEFINED_SHIM2;
+ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.type = e_FM_PCD_EXTRACT_FROM_HDR;
+ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.extractByHdrType.fromHdr.size = 4;
+ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.extractByHdrType.fromHdr.offset = 4;
+ p_Scheme->keyExtractAndHashParams.extractArray[2].extractByHdr.ignoreProtocolValidation = TRUE;
+ }
+
+ p_Scheme->keyExtractAndHashParams.privateDflt0 = 0x01020304;
+ p_Scheme->keyExtractAndHashParams.privateDflt1 = 0x11121314;
+ p_Scheme->keyExtractAndHashParams.numOfUsedDflts = FM_PCD_KG_NUM_OF_DEFAULT_GROUPS;
+ for (j=0; j<FM_PCD_KG_NUM_OF_DEFAULT_GROUPS; j++)
+ {
+ p_Scheme->keyExtractAndHashParams.dflts[j].type = (e_FmPcdKgKnownFieldsDfltTypes)j; /* all types */
+ p_Scheme->keyExtractAndHashParams.dflts[j].dfltSelect = e_FM_PCD_KG_DFLT_GBL_0;
+ }
+}
+
+static t_Error IpReassemblyStats(t_FmPcdManip *p_Manip, t_FmPcdManipReassemIpStats *p_Stats)
+{
+ ASSERT_COND(p_Manip);
+ ASSERT_COND(p_Stats);
+ ASSERT_COND(p_Manip->ipReassmParams.p_IpReassCommonTbl);
+
+ p_Stats->timeout = GET_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->totalTimeOutCounter);
+ p_Stats->rfdPoolBusy = GET_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->totalRfdPoolBusyCounter);
+ p_Stats->internalBufferBusy = GET_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->totalInternalBufferBusy);
+ p_Stats->externalBufferBusy = GET_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->totalExternalBufferBusy);
+ p_Stats->sgFragments = GET_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->totalSgFragmentCounter);
+ p_Stats->dmaSemaphoreDepletion = GET_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->totalDmaSemaphoreDepletionCounter);
+#if (DPAA_VERSION >= 11)
+ p_Stats->nonConsistentSp = GET_UINT32(p_Manip->ipReassmParams.p_IpReassCommonTbl->totalNCSPCounter);
+#endif /* (DPAA_VERSION >= 11) */
+
+ if (p_Manip->ipReassmParams.p_Ipv4ReassTbl)
+ {
+ p_Stats->specificHdrStatistics[0].successfullyReassembled = GET_UINT32(p_Manip->ipReassmParams.p_Ipv4ReassTbl->totalSuccessfullyReasmFramesCounter);
+ p_Stats->specificHdrStatistics[0].validFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv4ReassTbl->totalValidFragmentCounter);
+ p_Stats->specificHdrStatistics[0].processedFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv4ReassTbl->totalProcessedFragCounter);
+ p_Stats->specificHdrStatistics[0].malformedFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv4ReassTbl->totalMalformdFragCounter);
+ p_Stats->specificHdrStatistics[0].autoLearnBusy = GET_UINT32(p_Manip->ipReassmParams.p_Ipv4ReassTbl->totalSetBusyCounter);
+ p_Stats->specificHdrStatistics[0].discardedFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv4ReassTbl->totalDiscardedFragsCounter);
+ p_Stats->specificHdrStatistics[0].moreThan16Fragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv4ReassTbl->totalMoreThan16FramesCounter);
+ }
+ if (p_Manip->ipReassmParams.p_Ipv6ReassTbl)
+ {
+ p_Stats->specificHdrStatistics[1].successfullyReassembled = GET_UINT32(p_Manip->ipReassmParams.p_Ipv6ReassTbl->totalSuccessfullyReasmFramesCounter);
+ p_Stats->specificHdrStatistics[1].validFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv6ReassTbl->totalValidFragmentCounter);
+ p_Stats->specificHdrStatistics[1].processedFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv6ReassTbl->totalProcessedFragCounter);
+ p_Stats->specificHdrStatistics[1].malformedFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv6ReassTbl->totalMalformdFragCounter);
+ p_Stats->specificHdrStatistics[1].autoLearnBusy = GET_UINT32(p_Manip->ipReassmParams.p_Ipv6ReassTbl->totalSetBusyCounter);
+ p_Stats->specificHdrStatistics[1].discardedFragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv6ReassTbl->totalDiscardedFragsCounter);
+ p_Stats->specificHdrStatistics[1].moreThan16Fragments = GET_UINT32(p_Manip->ipReassmParams.p_Ipv6ReassTbl->totalMoreThan16FramesCounter);
+ }
+ return E_OK;
+}
+
+#ifdef FM_CAPWAP_SUPPORT
+static t_Error IndxStats(t_FmPcdStatsParams *p_StatsParams,t_FmPcdManip *p_Manip,t_FmPcd *p_FmPcd)
+{
+ t_AdOfTypeContLookup *p_Ad;
+ uint32_t tmpReg32 = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE);
+
+ UNUSED(p_FmPcd);
+
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
+
+ tmpReg32 = 0;
+ tmpReg32 |= (uint32_t)HMAN_OC_CAPWAP_INDEXED_STATS;
+ if (p_StatsParams->type == e_FM_PCD_STATS_PER_FLOWID)
+ tmpReg32 |= (uint32_t)0x16 << 16;
+ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32);
+
+ tmpReg32 = 0;
+ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE;
+ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32);
+
+ return E_OK;
+}
+
+static t_Error InsrtHdrByTempl(t_FmPcdManipHdrInsrtParams *p_ManipParams, t_FmPcdManip *p_Manip, t_FmPcd *p_FmPcd)
+{
+ t_FmPcdManipHdrInsrtByTemplateParams *p_InsrtByTemplate = &p_ManipParams->u.byTemplate;
+ uint8_t tmpReg8 = 0xff;
+ t_AdOfTypeContLookup *p_Ad;
+ bool ipModify = FALSE;
+ uint32_t tmpReg32 = 0, tmpRegNia = 0;
+ uint16_t tmpReg16 = 0;
+ t_Error err = E_OK;
+ uint8_t extraAddedBytes = 0, blockSize = 0, extraAddedBytesAlignedToBlockSize = 0, log2Num = 0;
+ uint8_t *p_Template = NULL;
+
+ SANITY_CHECK_RETURN_ERROR(p_ManipParams,E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_Manip,E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd,E_NULL_POINTER);
+
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
+ if (p_Manip->insrt)
+ {
+ if ((!p_InsrtByTemplate->size && p_InsrtByTemplate->modifyOuterIp) ||
+ (!p_InsrtByTemplate->size && p_InsrtByTemplate->modifyOuterVlan))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : asking for header template modifications with no template for insertion (template size)"));
+
+ if (p_InsrtByTemplate->size && p_InsrtByTemplate->modifyOuterIp && (p_InsrtByTemplate->size <= p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : size of template < ipOuterOffset"));
+
+ if (p_InsrtByTemplate->size > 128)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Size of header template for insertion can not be more than 128"));
+
+ if (p_InsrtByTemplate->size)
+ {
+ p_Manip->p_Template = (uint8_t *)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ p_InsrtByTemplate->size,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if(!p_Manip->p_Template)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation in MURAM FAILED"));
+
+ tmpReg32 = (uint32_t)(XX_VirtToPhys(p_Manip->p_Template) - (p_FmPcd->physicalMuramBase));
+ tmpReg32 |= (uint32_t)p_InsrtByTemplate->size << 24;
+ *(uint32_t *)&p_Ad->matchTblPtr = tmpReg32;
+ }
+
+ tmpReg32 = 0;
+
+ p_Template = (uint8_t *)XX_Malloc(p_InsrtByTemplate->size * sizeof(uint8_t));
+
+ if (!p_Template)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("XX_Malloc allocation FAILED"));
+
+ memcpy(p_Template, p_InsrtByTemplate->hdrTemplate, p_InsrtByTemplate->size * sizeof(uint8_t));
+
+
+ if (p_InsrtByTemplate->modifyOuterIp)
+ {
+ ipModify = TRUE;
+
+ tmpReg8 = (uint8_t)p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset];
+
+ if((tmpReg8 & 0xf0) == 0x40)
+ tmpReg8 = 4;
+ else if((tmpReg8 & 0xf0) == 0x60)
+ tmpReg8 = 6;
+ else
+ tmpReg8 = 0xff;
+
+ if (tmpReg8 != 0xff)
+ {
+ if(p_InsrtByTemplate->modifyOuterIpParams.dscpEcn & 0xff00)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : IPV4 present in header template, dscpEcn has to be only 1 byte"));
+ if(p_InsrtByTemplate->modifyOuterIpParams.recalculateLength)
+ {
+
+ if((p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedAlignedToBlockSize + p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedNotAlignedToBlockSize) > 255)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("extra Byte added can not be more than 256 bytes"));
+ extraAddedBytes = (uint8_t) (p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedAlignedToBlockSize + p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedNotAlignedToBlockSize);
+ blockSize = p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.blockSize;
+ extraAddedBytesAlignedToBlockSize = p_InsrtByTemplate->modifyOuterIpParams.recalculateLengthParams.extraBytesAddedAlignedToBlockSize;
+ /*IP header template - IP totalLength -
+ (1 byte) extraByteForIp = headerTemplateSize - ipOffset + insertedBytesAfterThisStage ,
+ in the case of SEC insertedBytesAfterThisStage - SEC trailer (21/31) + header(13)
+ second byte - extraByteForIp = headerTemplate - ipOffset + insertedBytesAfterThisStage*/
+ }
+ if (blockSize)
+ {
+ if (!POWER_OF_2(blockSize))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("inputFrmPaddingUpToBlockSize has to be power of 2"));
+ }
+
+ }
+ if (tmpReg8 == 4)
+ {
+ if ((IPv4_HDRCHECKSUM_FIELD_OFFSET_FROM_IP + p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset) > p_InsrtByTemplate->size)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : IP present in header template, user asked for IP modifications but ipOffset + ipTotalLengthFieldOffset in header template bigger than template size"));
+
+
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_DSCECN_FIELD_OFFSET_FROM_IP] = (uint8_t)p_InsrtByTemplate->modifyOuterIpParams.dscpEcn;
+
+ if (blockSize)
+ blockSize -= 1;
+
+ if ((p_InsrtByTemplate->size - p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + extraAddedBytes) > 255)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("p_InsrtByTemplate->size - p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + extraAddedBytes has to be less than 255"));
+
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_TOTALLENGTH_FIELD_OFFSET_FROM_IP + 1] = blockSize;// IPV6 - in AD instead of SEQ IND
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_TOTALLENGTH_FIELD_OFFSET_FROM_IP] = (uint8_t)(p_InsrtByTemplate->size - p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + extraAddedBytes);// for IPV6 decrement additional 40 bytes of IPV6 heade size
+
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_ID_FIELD_OFFSET_FROM_IP] = 0x00;
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_ID_FIELD_OFFSET_FROM_IP + 1] = extraAddedBytesAlignedToBlockSize;
+
+
+
+ /*IP header template - relevant only for ipv4 CheckSum = 0*/
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_HDRCHECKSUM_FIELD_OFFSET_FROM_IP] = 0x00;
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv4_HDRCHECKSUM_FIELD_OFFSET_FROM_IP + 1] = 0x00;
+
+
+ /*UDP checksum has to be 0*/
+ if (p_InsrtByTemplate->modifyOuterIpParams.udpPresent)
+ {
+ if ((p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP + UDP_CHECKSUM_FIELD_SIZE) > p_InsrtByTemplate->size)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : UDP present according to user but (UDP offset + UDP header size) < size of header template"));
+
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP ] = 0x00;
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP + 1] = 0x00;
+
+ }
+
+ if (p_InsrtByTemplate->modifyOuterIpParams.ipIdentGenId > 7)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("ipIdentGenId has to be one out of 8 sequence number generators (0 - 7) for IP identification field"));
+
+ tmpRegNia |= (uint32_t)p_InsrtByTemplate->modifyOuterIpParams.ipIdentGenId<<24;
+ }
+ else if (tmpReg8 == 6)
+ {
+ /*TODO - add check for maximum value of blockSize;*/
+ if (blockSize)
+ LOG2(blockSize, log2Num);
+ tmpRegNia |= (uint32_t)log2Num << 24;
+
+ // for IPV6 decrement additional 40 bytes of IPV6 heade size - because IPV6 header size is not included in payloadLength
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv6_PAYLOAD_LENGTH_OFFSET_FROM_IP] = (uint8_t)(p_InsrtByTemplate->size - p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + extraAddedBytes - 40);
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv6_PAYLOAD_LENGTH_OFFSET_FROM_IP + 1] = extraAddedBytesAlignedToBlockSize;
+ if (p_InsrtByTemplate->modifyOuterIpParams.udpPresent)
+ {
+ if ((p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP + UDP_CHECKSUM_FIELD_SIZE) > p_InsrtByTemplate->size)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inconsistent parameters : UDP present according to user but (UDP offset + UDP header size) < size of header template"));
+ if (p_Template[p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset + IPv6_NEXT_HEADER_OFFSET_FROM_IP] != 0x88)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("OUr suppport is only IPv6/UDPLite"));
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_LENGTH_FIELD_OFFSET_FROM_UDP] = 0x00;
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_LENGTH_FIELD_OFFSET_FROM_UDP + 1] = 0x08;
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP] = 0x00;
+ p_Template[p_InsrtByTemplate->modifyOuterIpParams.udpOffset + UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP + 1] = 0x00;
+ }
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("IP version supported only IPV4"));
+ }
+
+ tmpReg32 = tmpReg16 = tmpReg8 = 0;
+ /*TODO - check it*/
+ if (p_InsrtByTemplate->modifyOuterVlan)
+ {
+ if (p_InsrtByTemplate->modifyOuterVlanParams.vpri & ~0x07)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,("Inconsistent parameters : user asked for VLAN modifications but VPRI more than 3 bits"));
+
+ memcpy(&tmpReg16, &p_Template[VLAN_TAG_FIELD_OFFSET_FROM_ETH], 2*(sizeof(uint8_t)));
+ if ((tmpReg16 != 0x9100) && (tmpReg16!= 0x9200) && (tmpReg16 != 0x8100))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,("Inconsistent parameters : user asked for VLAN modifications but Tag Protocol identifier is not VLAN "));
+
+ memcpy(&tmpReg8, &p_Template[14],1*(sizeof(uint8_t)));
+ tmpReg8 &= 0x1f;
+ tmpReg8 |= (uint8_t)(p_InsrtByTemplate->modifyOuterVlanParams.vpri << 5);
+
+ p_Template[14] = tmpReg8;
+ }
+
+ Mem2IOCpy32(p_Manip->p_Template, p_Template, p_InsrtByTemplate->size);
+
+ XX_Free(p_Template);
+ }
+
+ tmpReg32 = 0;
+ if (p_Manip->h_Frag)
+ {
+ tmpRegNia |= (uint32_t)(XX_VirtToPhys(p_Manip->h_Frag) - (p_FmPcd->physicalMuramBase));
+ tmpReg32 |= (uint32_t)p_Manip->sizeForFragmentation << 16;
+ }
+ else
+ tmpReg32 = 0xffff0000;
+
+ if (ipModify)
+ tmpReg32 |= (uint32_t)p_InsrtByTemplate->modifyOuterIpParams.ipOuterOffset << 8;
+ else
+ tmpReg32 |= (uint32_t)0x0000ff00;
+
+ tmpReg32 |= (uint32_t)HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER;
+ *(uint32_t *)&p_Ad->pcAndOffsets = tmpReg32;
+
+ tmpRegNia |= FM_PCD_AD_CONT_LOOKUP_TYPE;
+ *(uint32_t *)&p_Ad->ccAdBase = tmpRegNia;
+
+ return err;
+}
+#endif /* FM_CAPWAP_SUPPORT */
+
+static t_Error IpFragmentationStats(t_FmPcdManip *p_Manip, t_FmPcdManipFragIpStats *p_Stats)
+{
+ t_AdOfTypeContLookup *p_Ad;
+
+ ASSERT_COND(p_Manip);
+ ASSERT_COND(p_Stats);
+ ASSERT_COND(p_Manip->h_Ad);
+ ASSERT_COND(p_Manip->ipFragParams.p_Frag);
+
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
+
+ p_Stats->totalFrames = GET_UINT32(p_Ad->gmask);
+ p_Stats->fragmentedFrames = GET_UINT32(p_Manip->ipFragParams.p_Frag->ccAdBase) & 0x00ffffff;
+ p_Stats->generatedFragments = GET_UINT32(p_Manip->ipFragParams.p_Frag->matchTblPtr);
+
+ return E_OK;
+}
+
+static t_Error IpFragmentation(t_FmPcdManipFragIpParams *p_ManipParams, t_FmPcdManip *p_Manip)
+{
+ uint32_t pcAndOffsetsReg = 0, ccAdBaseReg = 0, gmaskReg = 0;
+ t_FmPcd *p_FmPcd;
+#if (DPAA_VERSION == 10)
+ t_Error err = E_OK;
+#endif /* (DPAA_VERSION == 10) */
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip->h_Ad,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_ManipParams->sizeForFragmentation != 0xFFFF, E_INVALID_VALUE);
+
+ p_FmPcd = p_Manip->h_FmPcd;
+ /* Allocation of fragmentation Action Descriptor */
+ p_Manip->ipFragParams.p_Frag = (t_AdOfTypeContLookup *)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ FM_PCD_CC_AD_ENTRY_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!p_Manip->ipFragParams.p_Frag)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Fragmentation table descriptor"));
+ IOMemSet32( p_Manip->ipFragParams.p_Frag, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ /* Prepare the third Ad register (pcAndOffsets)- OperationCode */
+ pcAndOffsetsReg = (uint32_t)HMAN_OC_IP_FRAGMENTATION;
+
+ /* Prepare the first Ad register (ccAdBase) - Don't frag action and Action descriptor type*/
+ ccAdBaseReg = FM_PCD_AD_CONT_LOOKUP_TYPE;
+ ccAdBaseReg |= (p_ManipParams->dontFragAction << FM_PCD_MANIP_IP_FRAG_DF_SHIFT);
+
+
+ /* Set Scatter/Gather BPid */
+ if (p_ManipParams->sgBpidEn)
+ {
+ ccAdBaseReg |= FM_PCD_MANIP_IP_FRAG_SG_BDID_EN;
+ pcAndOffsetsReg |= ((p_ManipParams->sgBpid << FM_PCD_MANIP_IP_FRAG_SG_BDID_SHIFT) & FM_PCD_MANIP_IP_FRAG_SG_BDID_MASK);
+ }
+
+ /* Prepare the first Ad register (gmask) - scratch buffer pool id and Pointer to fragment ID */
+ gmaskReg = (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_FmPcd->ipv6FrameIdAddr)) - p_FmPcd->physicalMuramBase);
+#if (DPAA_VERSION == 10)
+ gmaskReg |= p_ManipParams->scratchBpid << FM_PCD_MANIP_IP_FRAG_SCRATCH_BPID;
+#else
+ gmaskReg |= (0xFF) << FM_PCD_MANIP_IP_FRAG_SCRATCH_BPID;
+#endif /* (DPAA_VERSION == 10) */
+
+ /* Set all Ad registers */
+ WRITE_UINT32(p_Manip->ipFragParams.p_Frag->pcAndOffsets, pcAndOffsetsReg);
+ WRITE_UINT32(p_Manip->ipFragParams.p_Frag->ccAdBase, ccAdBaseReg);
+ WRITE_UINT32(p_Manip->ipFragParams.p_Frag->gmask, gmaskReg);
+
+ /* Saves user's fragmentation manipulation parameters */
+ p_Manip->frag = TRUE;
+ p_Manip->sizeForFragmentation = p_ManipParams->sizeForFragmentation;
+
+#if (DPAA_VERSION == 10)
+ p_Manip->ipFragParams.scratchBpid = p_ManipParams->scratchBpid;
+
+ /* scratch buffer pool initialization */
+ if ((err = FmPcdFragHcScratchPoolFill((t_Handle)p_FmPcd, p_ManipParams->scratchBpid)) != E_OK)
+ {
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, p_Manip->ipFragParams.p_Frag);
+ p_Manip->ipFragParams.p_Frag = NULL;
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+#endif /* (DPAA_VERSION == 10) */
+
+ return E_OK;
+}
+
+static t_Error IPManip(t_FmPcdManip *p_Manip)
+{
+ t_Error err = E_OK;
+ t_FmPcd *p_FmPcd;
+ t_AdOfTypeContLookup *p_Ad;
+ uint32_t tmpReg32 = 0, tmpRegNia = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE);
+ p_FmPcd = p_Manip->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd,E_INVALID_HANDLE);
+
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
+
+ tmpReg32 = FM_PCD_MANIP_IP_NO_FRAGMENTATION;
+ if (p_Manip->frag == TRUE)
+ {
+ tmpRegNia = (uint32_t)(XX_VirtToPhys(p_Manip->ipFragParams.p_Frag) - (p_FmPcd->physicalMuramBase));
+ tmpReg32 = (uint32_t)p_Manip->sizeForFragmentation << FM_PCD_MANIP_IP_MTU_SHIFT;
+ }
+
+ tmpRegNia |= FM_PCD_AD_CONT_LOOKUP_TYPE;
+ tmpReg32 |= HMAN_OC_IP_MANIP;
+
+#if (DPAA_VERSION >= 11)
+ tmpRegNia |= FM_PCD_MANIP_IP_CNIA;
+#endif /* (DPAA_VERSION >= 11) */
+
+ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32);
+ WRITE_UINT32(p_Ad->ccAdBase, tmpRegNia);
+ WRITE_UINT32(p_Ad->gmask, 0); /* Total frame counter - MUST be initialized to zero.*/
+
+ return err;
+}
+
+static t_Error UpdateInitIpFrag(t_Handle h_FmPcd,
+ t_Handle h_PcdParams,
+ t_Handle h_FmPort,
+ t_FmPcdManip *p_Manip,
+ t_Handle h_Ad,
+ bool validate)
+{
+ t_FmPortGetSetCcParams fmPortGetSetCcParams;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Manip->opcode == HMAN_OC_IP_FRAGMENTATION), E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE);
+
+ UNUSED(h_FmPcd);
+ UNUSED(h_Ad);
+ UNUSED(h_PcdParams);
+ UNUSED(validate);
+ UNUSED(p_Manip);
+
+ fmPortGetSetCcParams.setCcParams.type = 0;
+ fmPortGetSetCcParams.getCcParams.type = MANIP_EXTRA_SPACE;
+ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (!fmPortGetSetCcParams.getCcParams.internalBufferOffset)
+ DBG(WARNING, ("manipExtraSpace must be larger than '0'"));
+
+ return E_OK;
+}
+
+static t_Error IPSecManip(t_FmPcdManipParams *p_ManipParams,
+ t_FmPcdManip *p_Manip)
+{
+ t_AdOfTypeContLookup *p_Ad;
+ t_FmPcdManipSpecialOffloadIPSecParams *p_IPSecParams;
+ t_Error err = E_OK;
+ uint32_t tmpReg32 = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_ManipParams,E_INVALID_HANDLE);
+
+ p_IPSecParams = &p_ManipParams->u.specialOffload.u.ipsec;
+
+ SANITY_CHECK_RETURN_ERROR(!p_IPSecParams->variableIpHdrLen ||
+ p_IPSecParams->decryption, E_INVALID_VALUE);
+ SANITY_CHECK_RETURN_ERROR(!p_IPSecParams->variableIpVersion ||
+ !p_IPSecParams->decryption, E_INVALID_VALUE);
+ SANITY_CHECK_RETURN_ERROR(!p_IPSecParams->variableIpVersion ||
+ p_IPSecParams->outerIPHdrLen, E_INVALID_VALUE);
+
+ p_Ad = (t_AdOfTypeContLookup *)p_Manip->h_Ad;
+
+ tmpReg32 |= FM_PCD_AD_CONT_LOOKUP_TYPE;
+ tmpReg32 |= (p_IPSecParams->decryption)?FM_PCD_MANIP_IPSEC_DEC:0;
+ tmpReg32 |= (p_IPSecParams->ecnCopy)?FM_PCD_MANIP_IPSEC_ECN_EN:0;
+ tmpReg32 |= (p_IPSecParams->dscpCopy)?FM_PCD_MANIP_IPSEC_DSCP_EN:0;
+ tmpReg32 |= (p_IPSecParams->variableIpHdrLen)?FM_PCD_MANIP_IPSEC_VIPL_EN:0;
+ tmpReg32 |= (p_IPSecParams->variableIpVersion)?FM_PCD_MANIP_IPSEC_VIPV_EN:0;
+ WRITE_UINT32(p_Ad->ccAdBase, tmpReg32);
+
+ tmpReg32 = HMAN_OC_IPSEC_MANIP;
+ tmpReg32 |= p_IPSecParams->outerIPHdrLen << FM_PCD_MANIP_IPSEC_IP_HDR_LEN_SHIFT;
+ if (p_ManipParams->h_NextManip)
+ {
+ WRITE_UINT32(p_Ad->matchTblPtr,
+ (uint32_t)(XX_VirtToPhys(((t_FmPcdManip *)p_ManipParams->h_NextManip)->h_Ad)-
+ (((t_FmPcd *)p_Manip->h_FmPcd)->physicalMuramBase)) >> 4);
+
+ tmpReg32 |= FM_PCD_MANIP_IPSEC_NADEN;
+ }
+ WRITE_UINT32(p_Ad->pcAndOffsets, tmpReg32);
+
+ return err;
+}
+
+#ifdef FM_CAPWAP_SUPPORT
+static t_Error CheckStatsParamsAndSetType(t_FmPcdManip *p_Manip, t_FmPcdStatsParams *p_StatsParams)
+{
+
+ switch (p_StatsParams->type)
+ {
+ case (e_FM_PCD_STATS_PER_FLOWID):
+ p_Manip->opcode = HMAN_OC_CAPWAP_INDEXED_STATS;
+ p_Manip->muramAllocate = TRUE;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported statistics type"));
+ }
+
+ return E_OK;
+}
+#endif /* FM_CAPWAP_SUPPORT */
+
+static t_Handle ManipOrStatsSetNode(t_Handle h_FmPcd, t_Handle *p_Params, bool stats)
+{
+ t_FmPcdManip *p_Manip;
+ t_Error err;
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+
+ p_Manip = (t_FmPcdManip*)XX_Malloc(sizeof(t_FmPcdManip));
+ if (!p_Manip)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory"));
+ return NULL;
+ }
+ memset(p_Manip, 0, sizeof(t_FmPcdManip));
+
+ p_Manip->type = ((t_FmPcdManipParams *)p_Params)->type;
+ memcpy((uint8_t*)&p_Manip->manipParams, p_Params, sizeof(p_Manip->manipParams));
+
+ if (!stats)
+ err = CheckManipParamsAndSetType(p_Manip, (t_FmPcdManipParams *)p_Params);
+#ifdef FM_CAPWAP_SUPPORT
+ else
+ err = CheckStatsParamsAndSetType(p_Manip, (t_FmPcdStatsParams *)p_Params);
+#else
+ else
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Statistics node!"));
+ return NULL;
+ }
+#endif /* FM_CAPWAP_SUPPORT */
+ if (err)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("INVALID HEADER MANIPULATION TYPE"));
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ XX_Free(p_Manip);
+ return NULL;
+ }
+
+ if (p_Manip->opcode != HMAN_OC_IP_REASSEMBLY)
+ {
+ /* In Case of IP reassembly manipulation the IPv4/IPv6 reassembly action descriptor will
+ be defines later on */
+ if (p_Manip->muramAllocate)
+ {
+ p_Manip->h_Ad = (t_Handle)FM_MURAM_AllocMem(p_FmPcd->h_FmMuram,
+ FM_PCD_CC_AD_ENTRY_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!p_Manip->h_Ad)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for Manipulation action descriptor"));
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ XX_Free(p_Manip);
+ return NULL;
+ }
+
+ IOMemSet32(p_Manip->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+ }
+ else
+ {
+ p_Manip->h_Ad = (t_Handle)XX_Malloc(FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t));
+ if (!p_Manip->h_Ad)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of Manipulation action descriptor"));
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ XX_Free(p_Manip);
+ return NULL;
+ }
+
+ memset(p_Manip->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t));
+ }
+ }
+
+ p_Manip->h_FmPcd = h_FmPcd;
+
+ return p_Manip;
+}
+
+static void UpdateAdPtrOfNodesWhichPointsOnCrntMdfManip(t_FmPcdManip *p_CrntMdfManip,
+ t_List *h_NodesLst)
+{
+ t_CcNodeInformation *p_CcNodeInformation;
+ t_FmPcdCcNode *p_NodePtrOnCurrentMdfManip = NULL;
+ t_List *p_Pos;
+ int i = 0;
+ t_Handle p_AdTablePtOnCrntCurrentMdfNode/*, p_AdTableNewModified*/;
+ t_CcNodeInformation ccNodeInfo;
+
+ LIST_FOR_EACH(p_Pos, &p_CrntMdfManip->nodesLst)
+ {
+ p_CcNodeInformation = CC_NODE_F_OBJECT(p_Pos);
+ p_NodePtrOnCurrentMdfManip = (t_FmPcdCcNode *)p_CcNodeInformation->h_CcNode;
+
+ ASSERT_COND(p_NodePtrOnCurrentMdfManip);
+
+ /* Search in the previous node which exact index points on this current modified node for getting AD */
+ for (i = 0; i < p_NodePtrOnCurrentMdfManip->numOfKeys + 1; i++)
+ {
+ if (p_NodePtrOnCurrentMdfManip->keyAndNextEngineParams[i].nextEngineParams.nextEngine == e_FM_PCD_CC)
+ {
+ if (p_NodePtrOnCurrentMdfManip->keyAndNextEngineParams[i].nextEngineParams.h_Manip == (t_Handle)p_CrntMdfManip)
+ {
+ if (p_NodePtrOnCurrentMdfManip->keyAndNextEngineParams[i].p_StatsObj)
+ p_AdTablePtOnCrntCurrentMdfNode =
+ p_NodePtrOnCurrentMdfManip->keyAndNextEngineParams[i].p_StatsObj->h_StatsAd;
+ else
+ p_AdTablePtOnCrntCurrentMdfNode =
+ PTR_MOVE(p_NodePtrOnCurrentMdfManip->h_AdTable, i*FM_PCD_CC_AD_ENTRY_SIZE);
+
+ memset(&ccNodeInfo, 0, sizeof(t_CcNodeInformation));
+ ccNodeInfo.h_CcNode = p_AdTablePtOnCrntCurrentMdfNode;
+ EnqueueNodeInfoToRelevantLst(h_NodesLst, &ccNodeInfo, NULL);
+ }
+ }
+ }
+
+ ASSERT_COND(i != p_NodePtrOnCurrentMdfManip->numOfKeys);
+ }
+}
+
+static void BuildHmtd(uint8_t *p_Dest, uint8_t *p_Src, uint8_t *p_Hmcd, t_FmPcd *p_FmPcd)
+{
+ t_Error err;
+
+ /* Copy the HMTD */
+ IO2IOCpy32(p_Dest, (uint8_t*)p_Src, 16);
+ /* Replace the HMCT table pointer */
+ WRITE_UINT32(((t_Hmtd *)p_Dest)->hmcdBasePtr,
+ (uint32_t)(XX_VirtToPhys(p_Hmcd) - ((t_FmPcd*)p_FmPcd)->physicalMuramBase));
+ /* Call Host Command to replace HMTD by a new HMTD */
+ err = FmHcPcdCcDoDynamicChange(p_FmPcd->h_Hc,
+ (uint32_t)(XX_VirtToPhys(p_Src) - p_FmPcd->physicalMuramBase),
+ (uint32_t)(XX_VirtToPhys(p_Dest) - p_FmPcd->physicalMuramBase));
+ if (err)
+ REPORT_ERROR(MINOR, err, ("Failed in dynamic manip change, continued to the rest of the owners."));
+}
+
+static t_Error FmPcdManipInitUpdate(t_Handle h_FmPcd,
+ t_Handle h_PcdParams,
+ t_Handle h_FmPort,
+ t_Handle h_Manip,
+ t_Handle h_Ad,
+ bool validate,
+ int level,
+ t_Handle h_FmTree)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(h_Manip,E_INVALID_HANDLE);
+
+ UNUSED(level);
+ UNUSED(h_FmPcd);
+ UNUSED(h_FmTree);
+
+ switch (p_Manip->opcode)
+ {
+ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX):
+ err = UpdateInitMvIntFrameHeaderFromFrameToBufferPrefix(h_FmPort, p_Manip, h_Ad, validate);
+ break;
+#ifdef FM_CAPWAP_SUPPORT
+ case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER):
+ if (!p_Manip->h_Frag)
+ break;
+ case (HMAN_OC_CAPWAP_FRAGMENTATION):
+ err = UpdateInitCapwapFragmentation(h_FmPort, p_Manip, h_Ad, validate, h_FmTree);
+ break;
+ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST):
+ if (p_Manip->h_Frag)
+ err = UpdateInitCapwapReasm(h_FmPcd, h_FmPort, p_Manip, h_Ad, validate);
+ break;
+ case (HMAN_OC_CAPWAP_INDEXED_STATS):
+ err = UpdateIndxStats(h_FmPcd, h_FmPort, p_Manip);
+ break;
+#endif /* FM_CAPWAP_SUPPORT */
+ case (HMAN_OC_IP_REASSEMBLY):
+ err = UpdateInitIpReasm(h_FmPcd, h_PcdParams, h_FmPort, p_Manip, h_Ad, validate);
+ break;
+ case (HMAN_OC_IP_FRAGMENTATION):
+ err = UpdateInitIpFrag(h_FmPcd, h_PcdParams, h_FmPort, p_Manip, h_Ad, validate);
+ break;
+ default:
+ return E_OK;
+ }
+
+ return err;
+}
+
+static t_Error FmPcdManipModifyUpdate(t_Handle h_Manip, t_Handle h_Ad, bool validate, int level, t_Handle h_FmTree)
+{
+
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
+ t_Error err = E_OK;
+
+ UNUSED(level);
+
+ switch (p_Manip->opcode)
+ {
+ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX):
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("modify node with this type of manipulation is not suppported"));
+ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST):
+
+ if (p_Manip->h_Frag)
+ {
+ if (!(p_Manip->shadowUpdateParams & NUM_OF_TASKS) &&
+ !(p_Manip->shadowUpdateParams & OFFSET_OF_DATA) &&
+ !(p_Manip->shadowUpdateParams & OFFSET_OF_PR))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("modify node with this type of manipulation requires manipulation be updated previously in SetPcd function"));
+ }
+ break;
+#ifdef FM_CAPWAP_SUPPORT
+ case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER):
+ if (p_Manip->h_Frag)
+ err = UpdateModifyCapwapFragmenation(p_Manip, h_Ad, validate, h_FmTree);
+ break;
+#endif /* FM_CAPWAP_SUPPORT */
+ default:
+ return E_OK;
+ }
+
+ return err;
+}
+
+/*****************************************************************************/
+/* Inter-module API routines */
+/*****************************************************************************/
+
+t_Error FmPcdManipUpdate(t_Handle h_FmPcd,
+ t_Handle h_PcdParams,
+ t_Handle h_FmPort,
+ t_Handle h_Manip,
+ t_Handle h_Ad,
+ bool validate,
+ int level,
+ t_Handle h_FmTree,
+ bool modify)
+{
+ t_Error err;
+
+ if (!modify)
+ err = FmPcdManipInitUpdate(h_FmPcd, h_PcdParams, h_FmPort, h_Manip, h_Ad, validate, level, h_FmTree);
+ else
+ err = FmPcdManipModifyUpdate(h_Manip, h_Ad, validate, level, h_FmTree);
+
+ return err;
+}
+
+uint32_t FmPcdManipGetRequiredAction (t_Handle h_Manip)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
+
+ ASSERT_COND(h_Manip);
+
+ switch (p_Manip->opcode)
+ {
+ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST):
+ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX):
+ return UPDATE_NIA_ENQ_WITHOUT_DMA;
+ default:
+ return 0;
+ }
+}
+
+void FmPcdManipUpdateOwner(t_Handle h_Manip, bool add)
+{
+
+ uint32_t intFlags;
+
+ intFlags = XX_LockIntrSpinlock(((t_FmPcdManip *)h_Manip)->h_Spinlock);
+ if (add)
+ ((t_FmPcdManip *)h_Manip)->owner++;
+ else
+ {
+ ASSERT_COND(((t_FmPcdManip *)h_Manip)->owner);
+ ((t_FmPcdManip *)h_Manip)->owner--;
+ }
+ XX_UnlockIntrSpinlock(((t_FmPcdManip *)h_Manip)->h_Spinlock, intFlags);
+}
+
+t_List *FmPcdManipGetNodeLstPointedOnThisManip(t_Handle h_Manip)
+{
+ ASSERT_COND(h_Manip);
+ return &((t_FmPcdManip *)h_Manip)->nodesLst;
+}
+
+t_List *FmPcdManipGetSpinlock(t_Handle h_Manip)
+{
+ ASSERT_COND(h_Manip);
+ return ((t_FmPcdManip *)h_Manip)->h_Spinlock;
+}
+
+t_Error FmPcdManipCheckParamsForCcNextEngine(t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams, uint32_t *requiredAction)
+{
+ t_FmPcdManip *p_Manip;
+ t_Error err;
+ bool pointFromCc = TRUE;
+
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams, E_NULL_POINTER);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcdCcNextEngineParams->h_Manip, E_NULL_POINTER);
+
+ p_Manip = (t_FmPcdManip *)(p_FmPcdCcNextEngineParams->h_Manip);
+ *requiredAction = 0;
+
+ while (p_Manip)
+ {
+ switch (p_Manip->opcode)
+ {
+ case (HMAN_OC_CAPWAP_INDEXED_STATS):
+ if (p_FmPcdCcNextEngineParams->nextEngine != e_FM_PCD_DONE)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For this type of header manipulation has to be nextEngine e_FM_PCD_DONE"));
+ if (p_FmPcdCcNextEngineParams->params.enqueueParams.overrideFqid)
+ p_Manip->cnia = TRUE;
+ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST):
+ *requiredAction = UPDATE_NIA_ENQ_WITHOUT_DMA;
+ case (HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR):
+ p_Manip->ownerTmp++;
+ break;
+ case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER):
+ if ((p_FmPcdCcNextEngineParams->nextEngine != e_FM_PCD_DONE) &&
+ !p_FmPcdCcNextEngineParams->params.enqueueParams.overrideFqid)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For this type of header manipulation has to be nextEngine e_FM_PCD_DONE with fqidForCtrlFlow FALSE"));
+ p_Manip->ownerTmp++;
+ break;
+ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX):
+ if ((p_FmPcdCcNextEngineParams->nextEngine != e_FM_PCD_CC) &&
+ (FmPcdCcGetParseCode(p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode) != CC_PC_GENERIC_IC_HASH_INDEXED))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For this type of header manipulation next engine has to be CC and action = e_FM_PCD_ACTION_INDEXED_LOOKUP"));
+ err = UpdateManipIc(p_FmPcdCcNextEngineParams->h_Manip, FmPcdCcGetOffset(p_FmPcdCcNextEngineParams->params.ccParams.h_CcNode));
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ *requiredAction = UPDATE_NIA_ENQ_WITHOUT_DMA;
+ break;
+ case (HMAN_OC_IP_FRAGMENTATION):
+ case (HMAN_OC_IP_REASSEMBLY):
+ if (p_FmPcdCcNextEngineParams->nextEngine != e_FM_PCD_DONE)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("For this type of header manipulation has to be nextEngine e_FM_PCD_DONE"));
+ p_Manip->ownerTmp++;
+ break;
+ case (HMAN_OC_IPSEC_MANIP):
+ p_Manip->ownerTmp++;
+ break;
+ case (HMAN_OC):
+ if (( p_FmPcdCcNextEngineParams->nextEngine == e_FM_PCD_CC) && MANIP_IS_CASCADE_NEXT(p_Manip))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't have a cascaded manipulation when and Next Engine is CC"));
+ if (!MANIP_IS_FIRST(p_Manip) && pointFromCc)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("h_Manip is already used and may not be shared (no sharing of non-head manip nodes)"));
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,("invalid type of header manipulation for this state"));
+ }
+ p_Manip = p_Manip->h_NextManip;
+ pointFromCc = FALSE;
+ }
+ return E_OK;
+}
+
+
+t_Error FmPcdManipCheckParamsWithCcNodeParams(t_Handle h_Manip, t_Handle h_FmPcdCcNode)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(h_Manip, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(h_FmPcdCcNode, E_INVALID_HANDLE);
+
+ switch (p_Manip->opcode)
+ {
+ case (HMAN_OC_CAPWAP_INDEXED_STATS):
+ if (p_Manip->ownerTmp != FmPcdCcGetNumOfKeys(h_FmPcdCcNode))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("The manipulation of the type statistics flowId if exist has to be pointed by all numOfKeys"));
+ break;
+ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST):
+ if (p_Manip->h_Frag)
+ {
+ if (p_Manip->ownerTmp != FmPcdCcGetNumOfKeys(h_FmPcdCcNode))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("The manipulation of the type remove DTLS if exist has to be pointed by all numOfKeys"));
+ err = UpdateManipIc(h_Manip, FmPcdCcGetOffset(h_FmPcdCcNode));
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return err;
+}
+
+void FmPcdManipUpdateAdResultForCc(t_Handle h_Manip,
+ t_FmPcdCcNextEngineParams *p_CcNextEngineParams,
+ t_Handle p_Ad,
+ t_Handle *p_AdNewPtr)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
+
+
+ /* This routine creates a Manip AD and can return in "p_AdNewPtr"
+ * either the new descriptor or NULL if it writes the Manip AD into p_AD (into the match table) */
+
+ ASSERT_COND(p_Manip);
+ ASSERT_COND(p_CcNextEngineParams);
+ ASSERT_COND(p_Ad);
+ ASSERT_COND(p_AdNewPtr);
+
+ FmPcdManipUpdateOwner(h_Manip, TRUE);
+
+ /* According to "type", either build & initialize a new AD (p_AdNew) or initialize
+ * p_Ad ( the AD in the match table) and set p_AdNew = NULL. */
+ switch (p_Manip->opcode)
+ {
+ case (HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR):
+ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST):
+ case (HMAN_OC_CAPWAP_INDEXED_STATS):
+ *p_AdNewPtr = p_Manip->h_Ad;
+ break;
+ case (HMAN_OC_IPSEC_MANIP):
+ *p_AdNewPtr = p_Manip->h_Ad;
+ break;
+ case (HMAN_OC_IP_FRAGMENTATION):
+ if ((p_CcNextEngineParams->nextEngine == e_FM_PCD_DONE) &&
+ (!p_CcNextEngineParams->params.enqueueParams.overrideFqid))
+ {
+ memcpy((uint8_t *)p_Ad, (uint8_t *)p_Manip->h_Ad, sizeof(t_AdOfTypeContLookup));
+#if (DPAA_VERSION >= 11)
+ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->ccAdBase,
+ GET_UINT32(((t_AdOfTypeContLookup *)p_Ad)->ccAdBase) & ~FM_PCD_MANIP_IP_CNIA);
+#endif /* (DPAA_VERSION >= 11) */
+ *p_AdNewPtr = NULL;
+ }
+ else
+ *p_AdNewPtr = p_Manip->h_Ad;
+ break;
+ case (HMAN_OC_IP_REASSEMBLY):
+ if (FmPcdManipIpReassmIsIpv6Hdr(p_Manip))
+ {
+ if (!p_Manip->ipReassmParams.ipv6Assigned)
+ {
+ *p_AdNewPtr = p_Manip->ipReassmParams.h_Ipv6Ad;
+ p_Manip->ipReassmParams.ipv6Assigned = TRUE;
+ FmPcdManipUpdateOwner(h_Manip, FALSE);
+ }
+ else
+ {
+ *p_AdNewPtr = p_Manip->ipReassmParams.h_Ipv4Ad;
+ p_Manip->ipReassmParams.ipv6Assigned = FALSE;
+ }
+ }
+ else
+ *p_AdNewPtr = p_Manip->ipReassmParams.h_Ipv4Ad;
+ memcpy((uint8_t *)p_Ad, (uint8_t *)*p_AdNewPtr, sizeof(t_AdOfTypeContLookup));
+ *p_AdNewPtr = NULL;
+ break;
+ case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER):
+ case (HMAN_OC_CAPWAP_FRAGMENTATION):
+ WRITE_UINT32(((t_AdOfTypeResult *)p_Ad)->fqid, ((t_AdOfTypeResult *)(p_Manip->h_Ad))->fqid);
+ WRITE_UINT32(((t_AdOfTypeResult *)p_Ad)->plcrProfile, ((t_AdOfTypeResult *)(p_Manip->h_Ad))->plcrProfile);
+ WRITE_UINT32(((t_AdOfTypeResult *)p_Ad)->nia, ((t_AdOfTypeResult *)(p_Manip->h_Ad))->nia);
+ *p_AdNewPtr = NULL;
+ break;
+ case (HMAN_OC):
+ /* Allocate and initialize HMTD */
+ *p_AdNewPtr = p_Manip->h_Ad;
+ break;
+ default:
+ break;
+ }
+}
+
+void FmPcdManipUpdateAdContLookupForCc(t_Handle h_Manip, t_Handle p_Ad, t_Handle *p_AdNewPtr, uint32_t adTableOffset)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
+
+ /* This routine creates a Manip AD and can return in "p_AdNewPtr"
+ * either the new descriptor or NULL if it writes the Manip AD into p_AD (into the match table) */
+ ASSERT_COND(p_Manip);
+
+ FmPcdManipUpdateOwner(h_Manip, TRUE);
+
+ switch (p_Manip->opcode)
+ {
+ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX):
+ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->ccAdBase, ((t_AdOfTypeContLookup *)(p_Manip->h_Ad))->ccAdBase);
+ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->matchTblPtr, ((t_AdOfTypeContLookup *)(p_Manip->h_Ad))->matchTblPtr);
+ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->pcAndOffsets, ((t_AdOfTypeContLookup *)(p_Manip->h_Ad))->pcAndOffsets);
+ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->gmask, ((t_AdOfTypeContLookup *)(p_Manip->h_Ad))->gmask);
+ WRITE_UINT32(((t_AdOfTypeContLookup *)p_Ad)->ccAdBase, (GET_UINT32(((t_AdOfTypeContLookup *)p_Ad)->ccAdBase) | adTableOffset));
+ *p_AdNewPtr = NULL;
+ break;
+
+ case (HMAN_OC):
+ /* Initialize HMTD within the match table*/
+ IOMemSet32(p_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+ /* copy the existing HMTD */ /* ask Alla - memcpy??? */
+ memcpy((uint8_t*)p_Ad, p_Manip->h_Ad, sizeof(t_Hmtd));
+ /* update NADEN to be "1"*/
+ WRITE_UINT16(((t_Hmtd *)p_Ad)->cfg,
+ (uint16_t)(GET_UINT16(((t_Hmtd *)p_Ad)->cfg) | HMTD_CFG_NEXT_AD_EN));
+ /* update next action descriptor */
+ WRITE_UINT16(((t_Hmtd *)p_Ad)->nextAdIdx, (uint16_t)(adTableOffset >> 4));
+ /* mark that Manip's HMTD is not used */
+ *p_AdNewPtr = NULL;
+ break;
+
+ default:
+ break;
+ }
+}
+
+t_Error FmPcdManipBuildIpReassmScheme(t_FmPcd *p_FmPcd, t_Handle h_NetEnv, t_Handle h_CcTree, t_Handle h_Manip, bool isIpv4, uint8_t groupId)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
+ t_FmPcdKgSchemeParams *p_SchemeParams = NULL;
+
+ ASSERT_COND(p_FmPcd);
+ ASSERT_COND(h_NetEnv);
+ ASSERT_COND(p_Manip);
+
+ /* scheme was already build, no need to check for IPv6 */
+ if (p_Manip->ipReassmParams.h_Ipv4Scheme)
+ return E_OK;
+
+ p_SchemeParams = XX_Malloc(sizeof(t_FmPcdKgSchemeParams));
+ if (!p_SchemeParams)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Memory allocation failed for scheme"));
+
+ /* Configures the IPv4 or IPv6 scheme*/
+ memset(p_SchemeParams, 0, sizeof(t_FmPcdKgSchemeParams));
+ p_SchemeParams->netEnvParams.h_NetEnv = h_NetEnv;
+ p_SchemeParams->id.relativeSchemeId =
+ (uint8_t)((isIpv4 == TRUE) ?
+ p_Manip->ipReassmParams.relativeSchemeId[0] :
+ p_Manip->ipReassmParams.relativeSchemeId[1]);
+ p_SchemeParams->schemeCounter.update = TRUE;
+#if (DPAA_VERSION >= 11)
+ p_SchemeParams->alwaysDirect = TRUE;
+ p_SchemeParams->bypassFqidGeneration = TRUE;
+#else
+ p_SchemeParams->keyExtractAndHashParams.hashDistributionNumOfFqids = 1;
+ p_SchemeParams->baseFqid = 0xFFFFFF; /*TODO- baseFqid*/
+#endif /* (DPAA_VERSION >= 11) */
+
+ setReassmSchemeParams(p_FmPcd, p_SchemeParams, h_CcTree, isIpv4, groupId);
+
+ /* Sets the new scheme */
+ if (isIpv4)
+ p_Manip->ipReassmParams.h_Ipv4Scheme = FM_PCD_KgSchemeSet(p_FmPcd, p_SchemeParams);
+ else
+ p_Manip->ipReassmParams.h_Ipv6Scheme = FM_PCD_KgSchemeSet(p_FmPcd, p_SchemeParams);
+
+ XX_Free(p_SchemeParams);
+
+ return E_OK;
+}
+
+t_Error FmPcdManipDeleteIpReassmSchemes(t_Handle h_Manip)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
+
+ ASSERT_COND(p_Manip);
+
+ if (p_Manip->ipReassmParams.h_Ipv4Scheme)
+ FM_PCD_KgSchemeDelete(p_Manip->ipReassmParams.h_Ipv4Scheme);
+
+ if (p_Manip->ipReassmParams.h_Ipv6Scheme)
+ FM_PCD_KgSchemeDelete(p_Manip->ipReassmParams.h_Ipv6Scheme);
+
+ return E_OK;
+}
+
+bool FmPcdManipIpReassmIsIpv6Hdr(t_Handle h_Manip)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
+
+ ASSERT_COND(p_Manip);
+
+ return (p_Manip->ipReassmParams.hdr == HEADER_TYPE_IPv6);
+}
+
+#ifdef FM_CAPWAP_SUPPORT
+t_Handle FmPcdManipApplSpecificBuild(void)
+{
+ t_FmPcdManip *p_Manip;
+
+ p_Manip = (t_FmPcdManip*)XX_Malloc(sizeof(t_FmPcdManip));
+ if (!p_Manip)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory"));
+ return NULL;
+ }
+ memset(p_Manip, 0, sizeof(t_FmPcdManip));
+
+ p_Manip->opcode = HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX;
+ p_Manip->muramAllocate = FALSE;
+
+ p_Manip->h_Ad = (t_Handle)XX_Malloc(FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t));
+ if (!p_Manip->h_Ad)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Allocation of Manipulation action descriptor"));
+ XX_Free(p_Manip);
+ return NULL;
+ }
+
+ memset(p_Manip->h_Ad, 0, FM_PCD_CC_AD_ENTRY_SIZE * sizeof(uint8_t));
+
+ /*treatFdStatusFieldsAsErrors = TRUE hardcoded - assumption its always come after CAAM*/
+ /*Application specific = type of flowId index, move internal frame header from data to IC,
+ SEC errors check*/
+ if (MvIntFrameHeaderFromFrameToBufferPrefix(p_Manip, TRUE)!= E_OK)
+ {
+ XX_Free(p_Manip->h_Ad);
+ XX_Free(p_Manip);
+ return NULL;
+ }
+ return p_Manip;
+}
+
+bool FmPcdManipIsCapwapApplSpecific(t_Handle h_Manip)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip;
+ ASSERT_COND(h_Manip);
+
+ return (bool)((p_Manip->opcode == HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST) ? TRUE : FALSE);
+}
+#endif /* FM_CAPWAP_SUPPORT */
+/*********************** End of inter-module routines ************************/
+
+
+/****************************************/
+/* API Init unit functions */
+/****************************************/
+
+t_Handle FM_PCD_ManipNodeSet(t_Handle h_FmPcd, t_FmPcdManipParams *p_ManipParams)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ t_FmPcdManip *p_Manip;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcd,E_INVALID_HANDLE,NULL);
+ SANITY_CHECK_RETURN_VALUE(p_ManipParams,E_INVALID_HANDLE,NULL);
+
+ p_Manip = ManipOrStatsSetNode(h_FmPcd, (t_Handle)p_ManipParams, FALSE);
+ if (!p_Manip)
+ return NULL;
+
+ if (((p_Manip->opcode == HMAN_OC_IP_REASSEMBLY) ||
+ (p_Manip->opcode == HMAN_OC_IP_FRAGMENTATION) ||
+ (p_Manip->opcode == HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX) ||
+ (p_Manip->opcode == HMAN_OC) ||
+ (p_Manip->opcode == HMAN_OC_IPSEC_MANIP)) &&
+ (!FmPcdIsAdvancedOffloadSupported(p_FmPcd)))
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Advanced-offload must be enabled"));
+ XX_Free(p_Manip);
+ return NULL;
+ }
+ p_Manip->h_Spinlock = XX_InitSpinlock();
+ if (!p_Manip->h_Spinlock)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED HEADER MANIPULATION TYPE"));
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ XX_Free(p_Manip);
+ return NULL;
+ }
+ INIT_LIST(&p_Manip->nodesLst);
+
+ switch (p_Manip->opcode)
+ {
+ case (HMAN_OC_IP_REASSEMBLY):
+ /* IpReassembly */
+ err = IpReassembly(&p_ManipParams->u.reassem, p_Manip);
+ break;
+ case (HMAN_OC_IP_FRAGMENTATION):
+ /* IpFragmentation */
+ err = IpFragmentation(&p_ManipParams->u.frag.u.ipFrag ,p_Manip);
+ if (err)
+ break;
+ err = IPManip(p_Manip);
+ break;
+ case (HMAN_OC_IPSEC_MANIP) :
+ err = IPSecManip(p_ManipParams, p_Manip);
+ break;
+#ifdef FM_CAPWAP_SUPPORT
+ case (HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR):
+ /* HmanType1 */
+ err = RmvHdrTillSpecLocNOrInsrtIntFrmHdr(&p_ManipParams->u.hdr.rmvParams, p_Manip);
+ break;
+ case (HMAN_OC_CAPWAP_FRAGMENTATION):
+ err = CapwapFragmentation(&p_ManipParams->fragOrReasmParams.u.capwapFragParams,
+ p_Manip,
+ p_FmPcd,
+ p_ManipParams->fragOrReasmParams.sgBpid);
+ if (err)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED HEADER MANIPULATION TYPE"));
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ XX_Free(p_Manip);
+ return NULL;
+ }
+ if (p_Manip->insrt)
+ p_Manip->opcode = HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER;
+ case (HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER):
+ /* HmanType2 + if user asked only for fragmentation still need to allocate HmanType2 */
+ err = InsrtHdrByTempl(&p_ManipParams->u.hdr.insrtParams, p_Manip, p_FmPcd);
+ break;
+ case (HMAN_OC_CAPWAP_REASSEMBLY):
+ err = CapwapReassembly(&p_ManipParams->fragOrReasmParams.u.capwapReasmParams,
+ p_Manip,
+ p_FmPcd,
+ p_ManipParams->fragOrReasmParams.sgBpid);
+ if (err)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED HEADER MANIPULATION TYPE"));
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ XX_Free(p_Manip);
+ return NULL;
+ }
+ if (p_Manip->rmv)
+ p_Manip->opcode = HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST;
+ case (HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST):
+ /*CAPWAP decapsulation + if user asked only for reassembly still need to allocate CAPWAP decapsulation*/
+ err = CapwapRmvDtlsHdr(p_FmPcd, p_Manip);
+ break;
+#endif /* FM_CAPWAP_SUPPORT */
+ case (HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX):
+ /*Application Specific type 1*/
+ err = MvIntFrameHeaderFromFrameToBufferPrefix(p_Manip, TRUE);
+ break;
+ case (HMAN_OC):
+ /* New Manip */
+ err = CreateManipActionNew(p_Manip, p_ManipParams);
+ break;
+ default:
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED HEADER MANIPULATION TYPE"));
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ XX_Free(p_Manip);
+ return NULL;
+ }
+
+ if (err)
+ {
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ XX_Free(p_Manip);
+ return NULL;
+ }
+
+ if (p_ManipParams->h_NextManip)
+ {
+ /* in the check routine we've verified that h_NextManip has no owners
+ * and that only supported types are allowed. */
+ p_Manip->h_NextManip = p_ManipParams->h_NextManip;
+ /* save a "prev" pointer in h_NextManip */
+ MANIP_SET_PREV(p_Manip->h_NextManip, p_Manip);
+ FmPcdManipUpdateOwner(p_Manip->h_NextManip, TRUE);
+ }
+
+ return p_Manip;
+}
+
+t_Error FM_PCD_ManipNodeReplace(t_Handle h_Manip, t_FmPcdManipParams *p_ManipParams)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_Manip, *p_FirstManip;
+ t_FmPcd *p_FmPcd = (t_FmPcd *)(p_Manip->h_FmPcd);
+ t_Error err;
+ uint8_t *p_WholeHmct = NULL, *p_ShadowHmct = NULL, *p_Hmtd = NULL;
+ t_List lstOfNodeshichPointsOnCrntMdfManip, *p_Pos;
+ t_CcNodeInformation *p_CcNodeInfo;
+ SANITY_CHECK_RETURN_ERROR(h_Manip,E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_ManipParams,E_INVALID_HANDLE);
+
+ INIT_LIST(&lstOfNodeshichPointsOnCrntMdfManip);
+
+ if ((p_ManipParams->type != e_FM_PCD_MANIP_HDR) ||
+ (p_Manip->type != e_FM_PCD_MANIP_HDR))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("FM_PCD_ManipNodeReplace Functionality supported only for Header Manipulation."));
+
+ ASSERT_COND(p_Manip->opcode == HMAN_OC);
+ ASSERT_COND(p_Manip->manipParams.h_NextManip == p_Manip->h_NextManip);
+ memcpy((uint8_t*)&p_Manip->manipParams, p_ManipParams, sizeof(p_Manip->manipParams));
+ p_Manip->manipParams.h_NextManip = p_Manip->h_NextManip;
+
+ /* The replacement of the HdrManip depends on the node type.*/
+ /*
+ * (1) If this is an independent node, all its owners should be updated.
+ *
+ * (2) If it is the head of a cascaded chain (it does not have a "prev" but
+ * it has a "next" and it has a "cascaded-next" indication), the next
+ * node remains unchanged, and the behavior is as in (1).
+ *
+ * (3) If it is not the head, but a part of a cascaded chain, in can be
+ * also replaced as a regular node with just one owner.
+ *
+ * (4) If it is a part of a chain implemented as a unified table, the
+ * whole table is replaced and the owners of the head node must be updated.
+ *
+ */
+ /* lock shadow */
+ if (!p_FmPcd->p_CcShadow)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("CC Shadow not allocated"));
+
+ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
+ return ERROR_CODE(E_BUSY);
+
+ /* this routine creates a new manip action in the CC Shadow. */
+ err = CreateManipActionShadow(p_Manip, p_ManipParams);
+ if (err)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ /* If the owners list is empty (these are NOT the "owners" counter, but pointers from CC)
+ * replace only HMTD and no lcok is required. Otherwise
+ * lock the whole PCD
+ * In case 4 MANIP_IS_UNIFIED_NON_FIRST(p_Manip) - Use the head node instead. */
+ if (!FmPcdLockTryLockAll(p_FmPcd))
+ {
+ DBG(TRACE, ("FmPcdLockTryLockAll failed"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ p_ShadowHmct = (uint8_t*)PTR_MOVE(p_FmPcd->p_CcShadow, 16);
+
+ p_FirstManip = (t_FmPcdManip*)GetManipInfo(p_Manip, e_MANIP_HANDLER_TABLE_OWNER);
+ ASSERT_COND(p_FirstManip);
+
+ if (!LIST_IsEmpty(&p_FirstManip->nodesLst))
+ UpdateAdPtrOfNodesWhichPointsOnCrntMdfManip(p_FirstManip, &lstOfNodeshichPointsOnCrntMdfManip);
+
+ p_Hmtd = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMTD);
+ ASSERT_COND(p_Hmtd);
+ BuildHmtd(p_FmPcd->p_CcShadow, (uint8_t *)p_Hmtd, p_ShadowHmct, ((t_FmPcd*)(p_Manip->h_FmPcd)));
+
+ LIST_FOR_EACH(p_Pos, &lstOfNodeshichPointsOnCrntMdfManip)
+ {
+ p_CcNodeInfo = CC_NODE_F_OBJECT(p_Pos);
+ BuildHmtd(p_FmPcd->p_CcShadow, (uint8_t *)p_CcNodeInfo->h_CcNode, p_ShadowHmct, ((t_FmPcd*)(p_Manip->h_FmPcd)));
+ }
+
+ p_WholeHmct = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMCT);
+ ASSERT_COND(p_WholeHmct);
+
+ /* re-build the HMCT n the original location */
+ err = CreateManipActionBackToOrig(p_Manip, p_ManipParams);
+ if (err)
+ {
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ p_Hmtd = (uint8_t *)GetManipInfo(p_Manip, e_MANIP_HMTD);
+ ASSERT_COND(p_Hmtd);
+ BuildHmtd(p_FmPcd->p_CcShadow, (uint8_t *)p_Hmtd, p_WholeHmct,((t_FmPcd*)p_Manip->h_FmPcd));
+
+ /* If LIST > 0, create a list of p_Ad's that point to the HMCT. Join also t_HMTD to this list.
+ * For each p_Hmct (from list+fixed):
+ * call Host Command to replace HMTD by a new one */
+ LIST_FOR_EACH(p_Pos, &lstOfNodeshichPointsOnCrntMdfManip)
+ {
+ p_CcNodeInfo = CC_NODE_F_OBJECT(p_Pos);
+ BuildHmtd(p_FmPcd->p_CcShadow, (uint8_t *)p_CcNodeInfo->h_CcNode, p_WholeHmct, ((t_FmPcd*)(p_Manip->h_FmPcd)));
+ }
+
+
+ ReleaseLst(&lstOfNodeshichPointsOnCrntMdfManip);
+
+ FmPcdLockUnlockAll(p_FmPcd);
+
+ /* unlock shadow */
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_ManipNodeDelete(t_Handle h_ManipNode)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_ManipNode;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip,E_INVALID_HANDLE);
+
+ if (p_Manip->owner)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("This manipulation node not be removed because this node is occupied, first - unbind this node "));
+
+ if (p_Manip->h_NextManip)
+ {
+ MANIP_SET_PREV(p_Manip->h_NextManip, NULL);
+ FmPcdManipUpdateOwner(p_Manip->h_NextManip, FALSE);
+ }
+
+ if (p_Manip->p_Hmct && (MANIP_IS_UNIFIED_FIRST(p_Manip) || !MANIP_IS_UNIFIED(p_Manip)))
+ FM_MURAM_FreeMem(((t_FmPcd *)p_Manip->h_FmPcd)->h_FmMuram, p_Manip->p_Hmct);
+
+ if (p_Manip->h_Spinlock)
+ {
+ XX_FreeSpinlock(p_Manip->h_Spinlock);
+ p_Manip->h_Spinlock = NULL;
+ }
+
+ ReleaseManipHandler(p_Manip, p_Manip->h_FmPcd);
+
+ XX_Free(h_ManipNode);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_ManipGetStatistics(t_Handle h_ManipNode, t_FmPcdManipStats *p_FmPcdManipStats)
+{
+ t_FmPcdManip *p_Manip = (t_FmPcdManip *)h_ManipNode;
+
+ SANITY_CHECK_RETURN_ERROR(p_Manip, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcdManipStats, E_NULL_POINTER);
+
+ switch (p_Manip->opcode)
+ {
+ case (HMAN_OC_IP_REASSEMBLY):
+ return IpReassemblyStats(p_Manip, &p_FmPcdManipStats->u.reassem.u.ipReassem);
+ case (HMAN_OC_IP_FRAGMENTATION):
+ return IpFragmentationStats(p_Manip, &p_FmPcdManipStats->u.frag.u.ipFrag);
+ default:
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("no statistics to this type of manip"));
+ }
+
+ return E_OK;
+}
+
+#ifdef FM_CAPWAP_SUPPORT
+t_Handle FM_PCD_StatisticsSetNode(t_Handle h_FmPcd, t_FmPcdStatsParams *p_StatsParams)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ t_FmPcdManip *p_Manip;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcd,E_INVALID_HANDLE,NULL);
+ SANITY_CHECK_RETURN_VALUE(p_StatsParams,E_INVALID_HANDLE,NULL);
+
+ p_Manip = ManipOrStatsSetNode(h_FmPcd, (t_Handle)p_StatsParams, TRUE);
+ if (!p_Manip)
+ return NULL;
+
+ switch (p_Manip->opcode)
+ {
+ case (HMAN_OC_CAPWAP_INDEXED_STATS):
+ /* Indexed statistics */
+ err = IndxStats(p_StatsParams, p_Manip, p_FmPcd);
+ break;
+ default:
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("UNSUPPORTED Statistics type"));
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ XX_Free(p_Manip);
+ return NULL;
+ }
+
+ if (err)
+ {
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ ReleaseManipHandler(p_Manip, p_FmPcd);
+ XX_Free(p_Manip);
+ return NULL;
+ }
+
+ return p_Manip;
+}
+#endif /* FM_CAPWAP_SUPPORT */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_manip.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_manip.h
new file mode 100644
index 0000000..f770c0f
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_manip.h
@@ -0,0 +1,481 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_manip.h
+
+ @Description FM PCD manip...
+*//***************************************************************************/
+#ifndef __FM_MANIP_H
+#define __FM_MANIP_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "list_ext.h"
+
+#include "fm_cc.h"
+
+
+/***********************************************************************/
+/* Header manipulations defines */
+/***********************************************************************/
+
+#define NUM_OF_SCRATCH_POOL_BUFFERS 1000 /*TODO - Change it!!*/
+
+#define HMAN_OC_RMV_N_OR_INSRT_INT_FRM_HDR 0x2e
+#define HMAN_OC_INSRT_HDR_BY_TEMPL_N_OR_FRAG_AFTER 0x31
+#define HMAN_OC_CAPWAP_FRAGMENTATION 0x33
+#define HMAN_OC_IP_MANIP 0x34
+#define HMAN_OC_IP_FRAGMENTATION 0x74
+#define HMAN_OC_IP_REASSEMBLY 0xB4
+#define HMAN_OC_IPSEC_MANIP 0xF4
+#define HMAN_OC_MV_INT_FRAME_HDR_FROM_FRM_TO_BUFFER_PREFFIX 0x2f
+#define HMAN_OC_CAPWAP_RMV_DTLS_IF_EXIST 0x30
+#define HMAN_OC_CAPWAP_REASSEMBLY 0x11 /* dummy */
+#define HMAN_OC_CAPWAP_INDEXED_STATS 0x32 /* dummy */
+#define HMAN_OC 0x35
+
+#define HMAN_RMV_HDR 0x80000000
+#define HMAN_INSRT_INT_FRM_HDR 0x40000000
+
+#define UDP_CHECKSUM_FIELD_OFFSET_FROM_UDP 6
+#define UDP_CHECKSUM_FIELD_SIZE 2
+#define UDP_LENGTH_FIELD_OFFSET_FROM_UDP 4
+
+#define IPv4_DSCECN_FIELD_OFFSET_FROM_IP 1
+#define IPv4_TOTALLENGTH_FIELD_OFFSET_FROM_IP 2
+#define IPv4_HDRCHECKSUM_FIELD_OFFSET_FROM_IP 10
+#define VLAN_TAG_FIELD_OFFSET_FROM_ETH 12
+#define IPv4_ID_FIELD_OFFSET_FROM_IP 4
+
+#define IPv6_PAYLOAD_LENGTH_OFFSET_FROM_IP 4
+#define IPv6_NEXT_HEADER_OFFSET_FROM_IP 6
+
+#define FM_PCD_MANIP_CAPWAP_REASM_TABLE_SIZE 0x80
+#define FM_PCD_MANIP_CAPWAP_REASM_TABLE_ALIGN 8
+#define FM_PCD_MANIP_CAPWAP_REASM_RFD_SIZE 32
+#define FM_PCD_MANIP_CAPWAP_REASM_AUTO_LEARNING_HASH_ENTRY_SIZE 4
+#define FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_ENTRY_SIZE 8
+
+
+#define FM_PCD_MANIP_CAPWAP_REASM_TIME_OUT_BETWEEN_FRAMES 0x40000000
+#define FM_PCD_MANIP_CAPWAP_REASM_HALT_ON_DUPLICATE_FRAG 0x10000000
+#define FM_PCD_MANIP_CAPWAP_REASM_AUTOMATIC_LEARNIN_HASH_8_WAYS 0x08000000
+#define FM_PCD_MANIP_CAPWAP_REASM_PR_COPY 0x00800000
+
+#define FM_PCD_MANIP_CAPWAP_FRAG_COMPR_OPTION_FIELD_EN 0x80000000
+
+#define FM_PCD_MANIP_INDEXED_STATS_ENTRY_SIZE 4
+#define FM_PCD_MANIP_INDEXED_STATS_CNIA 0x20000000
+#define FM_PCD_MANIP_INDEXED_STATS_DPD 0x10000000
+
+#define FM_PCD_MANIP_IP_REASM_TABLE_SIZE 0x40
+#define FM_PCD_MANIP_IP_REASM_TABLE_ALIGN 8
+
+#define FM_PCD_MANIP_IP_REASM_COMMON_PARAM_TABLE_SIZE 64
+#define FM_PCD_MANIP_IP_REASM_COMMON_PARAM_TABLE_ALIGN 8
+#define FM_PCD_MANIP_IP_REASM_TIME_OUT_BETWEEN_FRAMES 0x80000000
+#define FM_PCD_MANIP_IP_REASM_COUPLING_ENABLE 0x40000000
+#define FM_PCD_MANIP_IP_REASM_COUPLING_MASK 0xFF000000
+#define FM_PCD_MANIP_IP_REASM_COUPLING_SHIFT 24
+#define FM_PCD_MANIP_IP_REASM_LIODN_MASK 0x0000003F
+#define FM_PCD_MANIP_IP_REASM_LIODN_SHIFT 56
+#define FM_PCD_MANIP_IP_REASM_ELIODN_MASK 0x000003c0
+#define FM_PCD_MANIP_IP_REASM_ELIODN_SHIFT 38
+#define FM_PCD_MANIP_IP_REASM_COMMON_INT_BUFFER_IDX_MASK 0x000000FF
+#define FM_PCD_MANIP_IP_REASM_COMMON_INT_BUFFER_IDX_SHIFT 24
+
+#define FM_PCD_MANIP_IP_MTU_SHIFT 16
+#define FM_PCD_MANIP_IP_NO_FRAGMENTATION 0xFFFF0000
+#define FM_PCD_MANIP_IP_CNIA 0x20000000
+
+#define FM_PCD_MANIP_IP_REASSM_TIMEOUT_THREAD_THRESH 1024
+#define FM_PCD_MANIP_IP_FRAG_DF_SHIFT 28
+#define FM_PCD_MANIP_IP_FRAG_SCRATCH_BPID 24
+#define FM_PCD_MANIP_IP_FRAG_SG_BDID_EN 0x08000000
+#define FM_PCD_MANIP_IP_FRAG_SG_BDID_MASK 0xFF000000
+#define FM_PCD_MANIP_IP_FRAG_SG_BDID_SHIFT 24
+
+#define FM_PCD_MANIP_IPSEC_DEC 0x10000000
+#define FM_PCD_MANIP_IPSEC_VIPV_EN 0x08000000
+#define FM_PCD_MANIP_IPSEC_ECN_EN 0x04000000
+#define FM_PCD_MANIP_IPSEC_DSCP_EN 0x02000000
+#define FM_PCD_MANIP_IPSEC_VIPL_EN 0x01000000
+#define FM_PCD_MANIP_IPSEC_NADEN 0x20000000
+
+#define FM_PCD_MANIP_IPSEC_IP_HDR_LEN_MASK 0x00FF0000
+#define FM_PCD_MANIP_IPSEC_IP_HDR_LEN_SHIFT 16
+
+#define e_FM_MANIP_IP_INDX 1
+
+#define HMCD_OPCODE_GENERIC_RMV 0x01
+#define HMCD_OPCODE_GENERIC_INSRT 0x02
+#define HMCD_OPCODE_GENERIC_REPLACE 0x05
+#define HMCD_OPCODE_L2_RMV 0x08
+#define HMCD_OPCODE_L2_INSRT 0x09
+#define HMCD_OPCODE_VLAN_PRI_UPDATE 0x0B
+#define HMCD_OPCODE_IPV4_UPDATE 0x0C
+#define HMCD_OPCODE_IPV6_UPDATE 0x10
+#define HMCD_OPCODE_TCP_UDP_UPDATE 0x0E
+#define HMCD_OPCODE_TCP_UDP_CHECKSUM 0x14
+#define HMCD_OPCODE_REPLACE_IP 0x12
+
+#define HMCD_DSCP_VALUES 64
+
+#define HMCD_BASIC_SIZE 4
+#define HMCD_PTR_SIZE 4
+#define HMCD_PARAM_SIZE 4
+#define HMCD_IPV4_ADDR_SIZE 4
+#define HMCD_IPV6_ADDR_SIZE 0x10
+
+#define HMCD_LAST 0x00800000
+
+#define HMCD_OC_SHIFT 24
+
+#define HMCD_RMV_OFFSET_SHIFT 0
+#define HMCD_RMV_SIZE_SHIFT 8
+
+#define HMCD_INSRT_OFFSET_SHIFT 0
+#define HMCD_INSRT_SIZE_SHIFT 8
+
+#define HMTD_CFG_TYPE 0x4000
+#define HMTD_CFG_EXT_HMCT 0x0080
+#define HMTD_CFG_PRS_AFTER_HM 0x0040
+#define HMTD_CFG_NEXT_AD_EN 0x0020
+
+#define HMCD_RMV_L2_ETHERNET 0
+#define HMCD_RMV_L2_STACKED_QTAGS 1
+#define HMCD_RMV_L2_ETHERNET_AND_MPLS 2
+#define HMCD_RMV_L2_MPLS 3
+
+#define HMCD_INSRT_L2_MPLS 0
+#define HMCD_INSRT_N_UPDATE_L2_MPLS 1
+#define HMCD_INSRT_L2_SIZE_SHIFT 24
+
+#define HMCD_L2_MODE_SHIFT 16
+
+#define HMCD_VLAN_PRI_REP_MODE_SHIFT 16
+#define HMCD_VLAN_PRI_UPDATE 0
+#define HMCD_VLAN_PRI_UPDATE_DSCP_TO_VPRI 1
+
+#define HMCD_IPV4_UPDATE_TTL 0x00000001
+#define HMCD_IPV4_UPDATE_TOS 0x00000002
+#define HMCD_IPV4_UPDATE_DST 0x00000020
+#define HMCD_IPV4_UPDATE_SRC 0x00000040
+#define HMCD_IPV4_UPDATE_ID 0x00000080
+#define HMCD_IPV4_UPDATE_TOS_SHIFT 8
+
+#define HMCD_IPV6_UPDATE_HL 0x00000001
+#define HMCD_IPV6_UPDATE_TC 0x00000002
+#define HMCD_IPV6_UPDATE_DST 0x00000040
+#define HMCD_IPV6_UPDATE_SRC 0x00000080
+#define HMCD_IPV6_UPDATE_TC_SHIFT 8
+
+#define HMCD_TCP_UDP_UPDATE_DST 0x00004000
+#define HMCD_TCP_UDP_UPDATE_SRC 0x00008000
+#define HMCD_TCP_UDP_UPDATE_SRC_SHIFT 16
+
+#define HMCD_IP_REPLACE_REPLACE_IPV4 0x00000000
+#define HMCD_IP_REPLACE_REPLACE_IPV6 0x00010000
+#define HMCD_IP_REPLACE_TTL_HL 0x00200000
+#define HMCD_IP_REPLACE_ID 0x00400000
+
+#define HMCD_IP_REPLACE_L3HDRSIZE_SHIFT 24
+
+#define DSCP_TO_VLAN_TABLE_SIZE 32
+
+#define MANIP_GET_HMCT_SIZE(h_Manip) (((t_FmPcdManip *)h_Manip)->tableSize)
+#define MANIP_GET_DATA_SIZE(h_Manip) (((t_FmPcdManip *)h_Manip)->dataSize)
+
+#define MANIP_GET_HMCT_PTR(h_Manip) (((t_FmPcdManip *)h_Manip)->p_Hmct)
+#define MANIP_GET_DATA_PTR(h_Manip) (((t_FmPcdManip *)h_Manip)->p_Data)
+
+#define MANIP_SET_HMCT_PTR(h_Manip, h_NewPtr) (((t_FmPcdManip *)h_Manip)->p_Hmct = h_NewPtr)
+#define MANIP_SET_DATA_PTR(h_Manip, h_NewPtr) (((t_FmPcdManip *)h_Manip)->p_Data = h_NewPtr)
+
+#define MANIP_GET_HMTD_PTR(h_Manip) (((t_FmPcdManip *)h_Manip)->h_Ad)
+#define MANIP_DONT_REPARSE(h_Manip) (((t_FmPcdManip *)h_Manip)->dontParseAfterManip)
+#define MANIP_SET_PREV(h_Manip, h_Prev) (((t_FmPcdManip *)h_Manip)->h_PrevManip = h_Prev)
+#define MANIP_GET_OWNERS(h_Manip) (((t_FmPcdManip *)h_Manip)->owner)
+#define MANIP_GET_TYPE(h_Manip) (((t_FmPcdManip *)h_Manip)->type)
+#define MANIP_SET_UNIFIED_TBL_PTR_INDICATION(h_Manip) (((t_FmPcdManip *)h_Manip)->unifiedTablePtr = TRUE)
+#define MANIP_GET_MURAM(h_Manip) (((t_FmPcd *)((t_FmPcdManip *)h_Manip)->h_FmPcd)->h_FmMuram)
+#define MANIP_FREE_HMTD(h_Manip) \
+ {if (((t_FmPcdManip *)h_Manip)->muramAllocate) \
+ FM_MURAM_FreeMem(((t_FmPcd *)((t_FmPcdManip *)h_Manip)->h_FmPcd)->h_FmMuram, ((t_FmPcdManip *)h_Manip)->h_Ad);\
+ else \
+ XX_Free(((t_FmPcdManip *)h_Manip)->h_Ad); \
+ ((t_FmPcdManip *)h_Manip)->h_Ad = NULL; \
+ }
+/* position regarding Manip SW structure */
+#define MANIP_IS_FIRST(h_Manip) (!(((t_FmPcdManip *)h_Manip)->h_PrevManip))
+#define MANIP_IS_CASCADE_NEXT(h_Manip) (((t_FmPcdManip *)h_Manip)->cascadedNext)
+#define MANIP_IS_UNIFIED(h_Manip) (!(((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_NONE))
+#define MANIP_IS_UNIFIED_NON_FIRST(h_Manip) ((((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_MID) || \
+ (((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_LAST))
+#define MANIP_IS_UNIFIED_NON_LAST(h_Manip) ((((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_FIRST) ||\
+ (((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_MID))
+#define MANIP_IS_UNIFIED_FIRST(h_Manip) (((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_FIRST)
+#define MANIP_IS_UNIFIED_LAST(h_Manip) (((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_LAST)
+
+#define MANIP_UPDATE_UNIFIED_POSITION(h_Manip) (((t_FmPcdManip *)h_Manip)->unifiedPosition = \
+ (((t_FmPcdManip *)h_Manip)->unifiedPosition == e_MANIP_UNIFIED_NONE)? \
+ e_MANIP_UNIFIED_LAST : e_MANIP_UNIFIED_MID)
+
+typedef enum e_ManipUnifiedPosition {
+ e_MANIP_UNIFIED_NONE = 0,
+ e_MANIP_UNIFIED_FIRST,
+ e_MANIP_UNIFIED_MID,
+ e_MANIP_UNIFIED_LAST
+} e_ManipUnifiedPosition;
+
+typedef enum e_ManipInfo {
+ e_MANIP_HMTD,
+ e_MANIP_HMCT,
+ e_MANIP_HANDLER_TABLE_OWNER
+}e_ManipInfo;
+/***********************************************************************/
+/* Memory map */
+/***********************************************************************/
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+typedef _Packed struct t_CapwapReasmPram {
+ volatile uint32_t mode;
+ volatile uint32_t autoLearnHashTblPtr;
+ volatile uint32_t intStatsTblPtr;
+ volatile uint32_t reasmFrmDescPoolTblPtr;
+ volatile uint32_t reasmFrmDescIndexPoolTblPtr;
+ volatile uint32_t timeOutTblPtr;
+ volatile uint32_t bufferPoolIdAndRisc1SetIndexes;
+ volatile uint32_t risc23SetIndexes;
+ volatile uint32_t risc4SetIndexesAndExtendedStatsTblPtr;
+ volatile uint32_t extendedStatsTblPtr;
+ volatile uint32_t expirationDelay;
+ volatile uint32_t totalProcessedFragCounter;
+ volatile uint32_t totalUnsuccessfulReasmFramesCounter;
+ volatile uint32_t totalDuplicatedFragCounter;
+ volatile uint32_t totalMalformdFragCounter;
+ volatile uint32_t totalTimeOutCounter;
+ volatile uint32_t totalSetBusyCounter;
+ volatile uint32_t totalRfdPoolBusyCounter;
+ volatile uint32_t totalDiscardedFragsCounter;
+ volatile uint32_t totalMoreThan16FramesCounter;
+ volatile uint32_t internalBufferBusy;
+ volatile uint32_t externalBufferBusy;
+ volatile uint32_t reserved1[4];
+} _PackedType t_CapwapReasmPram;
+
+typedef _Packed struct t_IpReassTbl {
+ volatile uint16_t waysNumAndSetSize;
+ volatile uint16_t autoLearnHashKeyMask;
+ volatile uint32_t ipReassCommonPrmTblPtr;
+ volatile uint32_t liodnAlAndAutoLearnHashTblPtrHi;
+ volatile uint32_t autoLearnHashTblPtrLow;
+ volatile uint32_t liodnSlAndAutoLearnSetLockTblPtrHi;
+ volatile uint32_t autoLearnSetLockTblPtrLow;
+ volatile uint16_t minFragSize;
+ volatile uint16_t reserved1;
+ volatile uint32_t totalSuccessfullyReasmFramesCounter;
+ volatile uint32_t totalValidFragmentCounter;
+ volatile uint32_t totalProcessedFragCounter;
+ volatile uint32_t totalMalformdFragCounter;
+ volatile uint32_t totalSetBusyCounter;
+ volatile uint32_t totalDiscardedFragsCounter;
+ volatile uint32_t totalMoreThan16FramesCounter;
+ volatile uint32_t reserved2[2];
+} _PackedType t_IpReassTbl;
+
+typedef _Packed struct t_IpReassCommonTbl {
+ volatile uint32_t timeoutModeAndFqid;
+ volatile uint32_t reassFrmDescIndexPoolTblPtr;
+ volatile uint32_t liodnAndReassFrmDescPoolPtrHi;
+ volatile uint32_t reassFrmDescPoolPtrLow;
+ volatile uint32_t timeOutTblPtr;
+ volatile uint32_t expirationDelay;
+ volatile uint32_t internalBufferManagement;
+ volatile uint32_t reserved2;
+ volatile uint32_t totalTimeOutCounter;
+ volatile uint32_t totalRfdPoolBusyCounter;
+ volatile uint32_t totalInternalBufferBusy;
+ volatile uint32_t totalExternalBufferBusy;
+ volatile uint32_t totalSgFragmentCounter;
+ volatile uint32_t totalDmaSemaphoreDepletionCounter;
+ volatile uint32_t totalNCSPCounter;
+ volatile uint32_t discardMask;
+} _PackedType t_IpReassCommonTbl;
+
+typedef _Packed struct t_Hmtd {
+ volatile uint16_t cfg;
+ volatile uint8_t eliodnOffset;
+ volatile uint8_t extHmcdBasePtrHi;
+ volatile uint32_t hmcdBasePtr;
+ volatile uint16_t nextAdIdx;
+ volatile uint8_t res1;
+ volatile uint8_t opCode;
+ volatile uint32_t res2;
+} _PackedType t_Hmtd;
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+/***********************************************************************/
+/* Driver's internal structures */
+/***********************************************************************/
+typedef struct
+{
+ t_Handle p_AutoLearnHashTbl;
+ t_Handle p_ReassmFrmDescrPoolTbl;
+ t_Handle p_ReassmFrmDescrIndxPoolTbl;
+ t_Handle p_TimeOutTbl;
+ uint16_t maxNumFramesInProcess;
+ uint8_t numOfTasks;
+ //uint8_t poolId;
+ uint8_t prOffset;
+ uint16_t dataOffset;
+ uint8_t sgBpid;
+ uint8_t hwPortId;
+ uint32_t fqidForTimeOutFrames;
+ uint32_t timeoutRoutineRequestTime;
+ uint32_t bitFor1Micro;
+} t_FragParams;
+
+typedef struct
+{
+ t_AdOfTypeContLookup *p_Frag;
+#if (DPAA_VERSION == 10)
+ uint8_t scratchBpid;
+#endif /* (DPAA_VERSION == 10) */
+} t_IpFragParams;
+
+typedef struct t_IpReassmParams
+{
+ t_Handle h_Ipv4Ad;
+ t_Handle h_Ipv6Ad;
+ bool ipv6Assigned;
+ e_NetHeaderType hdr; /* Header selection */
+ t_IpReassCommonTbl *p_IpReassCommonTbl;
+ t_IpReassTbl *p_Ipv4ReassTbl;
+ t_IpReassTbl *p_Ipv6ReassTbl;
+ uintptr_t ipv4AutoLearnHashTblAddr;
+ uintptr_t ipv6AutoLearnHashTblAddr;
+ uintptr_t ipv4AutoLearnSetLockTblAddr;
+ uintptr_t ipv6AutoLearnSetLockTblAddr;
+ uintptr_t reassFrmDescrIndxPoolTblAddr;
+ uintptr_t reassFrmDescrPoolTblAddr;
+ uintptr_t timeOutTblAddr;
+ uintptr_t internalBufferPoolManagementIndexAddr;
+ uintptr_t internalBufferPoolAddr;
+ uint32_t maxNumFramesInProcess;
+ uint8_t sgBpid;
+ uint8_t dataMemId;
+ uint16_t dataLiodnOffset;
+ uint32_t fqidForTimeOutFrames;
+ e_FmPcdManipReassemTimeOutMode timeOutMode;
+ uint32_t timeoutThresholdForReassmProcess;
+ uint16_t minFragSize[2];
+ e_FmPcdManipReassemWaysNumber numOfFramesPerHashEntry[2];
+ uint8_t relativeSchemeId[2];
+ t_Handle h_Ipv4Scheme;
+ t_Handle h_Ipv6Scheme;
+ uint32_t nonConsistentSpFqid;
+} t_IpReassmParams;
+
+
+typedef struct{
+ e_FmPcdManipType type;
+ t_FmPcdManipParams manipParams;
+ bool muramAllocate;
+ t_Handle h_Ad;
+ uint32_t opcode;
+ bool rmv;
+ bool insrt;
+ t_Handle h_NextManip;
+ t_Handle h_PrevManip;
+ /* HdrManip parameters*/
+ uint8_t *p_Hmct;
+ uint8_t *p_Data;
+ bool dontParseAfterManip;
+ bool fieldUpdate;
+ bool custom;
+ uint16_t tableSize;
+ uint8_t dataSize;
+ bool cascadedNext;
+ e_ManipUnifiedPosition unifiedPosition;
+ /* end HdrManip */
+ uint8_t *p_Template;
+ t_Handle h_Frag;
+ bool frag;
+ bool reassm;
+ uint16_t sizeForFragmentation;
+ uint8_t owner;
+ uint32_t updateParams;
+ uint32_t shadowUpdateParams;
+ t_FragParams fragParams;
+ union {
+ t_IpReassmParams ipReassmParams;
+ t_IpFragParams ipFragParams;
+ };
+ uint8_t icOffset;
+ uint16_t ownerTmp;
+ bool cnia;
+ t_Handle p_StatsTbl;
+ t_Handle h_FmPcd;
+ t_List nodesLst;
+ t_Handle h_Spinlock;
+
+} t_FmPcdManip;
+
+typedef struct t_FmPcdCcSavedManipParams
+{
+ union
+ {
+ struct
+ {
+ uint16_t dataOffset;
+ //uint8_t poolId;
+ }capwapParams;
+ struct
+ {
+ uint16_t dataOffset;
+ uint8_t poolId;
+ }ipParams;
+ };
+
+} t_FmPcdCcSavedManipParams;
+
+
+#endif /* __FM_MANIP_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd.c
new file mode 100644
index 0000000..37ff0fd
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd.c
@@ -0,0 +1,2117 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_pcd.c
+
+ @Description FM PCD ...
+*//***************************************************************************/
+#include "std_ext.h"
+#include "error_ext.h"
+#include "string_ext.h"
+#include "xx_ext.h"
+#include "sprint_ext.h"
+#include "debug_ext.h"
+#include "net_ext.h"
+#include "fm_ext.h"
+#include "fm_pcd_ext.h"
+
+#include "fm_common.h"
+#include "fm_pcd.h"
+#include "fm_pcd_ipc.h"
+#include "fm_hc.h"
+#include "fm_muram_ext.h"
+
+
+/****************************************/
+/* static functions */
+/****************************************/
+
+static t_Error CheckFmPcdParameters(t_FmPcd *p_FmPcd)
+{
+ if (!p_FmPcd->h_Fm)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("h_Fm has to be initialized"));
+
+ if (p_FmPcd->guestId == NCSW_MASTER_ID)
+ {
+ if (p_FmPcd->p_FmPcdKg && !p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Something WRONG"));
+
+ if (p_FmPcd->p_FmPcdPlcr && !p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Something WRONG"));
+
+ if (!p_FmPcd->f_Exception)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("f_FmPcdExceptions has to be initialized"));
+
+ if ((!p_FmPcd->f_FmPcdIndexedException) && (p_FmPcd->p_FmPcdPlcr || p_FmPcd->p_FmPcdKg))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("f_FmPcdIndexedException has to be initialized"));
+
+ if (p_FmPcd->p_FmPcdDriverParam->prsMaxParseCycleLimit > PRS_MAX_CYCLE_LIMIT)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("prsMaxParseCycleLimit has to be less than 8191"));
+ }
+
+ return E_OK;
+}
+
+static volatile bool blockingFlag = FALSE;
+static void IpcMsgCompletionCB(t_Handle h_FmPcd,
+ uint8_t *p_Msg,
+ uint8_t *p_Reply,
+ uint32_t replyLength,
+ t_Error status)
+{
+ UNUSED(h_FmPcd);UNUSED(p_Msg);UNUSED(p_Reply);UNUSED(replyLength);UNUSED(status);
+ blockingFlag = FALSE;
+}
+
+static t_Error IpcMsgHandlerCB(t_Handle h_FmPcd,
+ uint8_t *p_Msg,
+ uint32_t msgLength,
+ uint8_t *p_Reply,
+ uint32_t *p_ReplyLength)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_Error err = E_OK;
+ t_FmPcdIpcMsg *p_IpcMsg = (t_FmPcdIpcMsg*)p_Msg;
+ t_FmPcdIpcReply *p_IpcReply = (t_FmPcdIpcReply*)p_Reply;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((msgLength >= sizeof(uint32_t)), E_INVALID_VALUE);
+
+#ifdef DISABLE_SANITY_CHECKS
+ UNUSED(msgLength);
+#endif /* DISABLE_SANITY_CHECKS */
+
+ ASSERT_COND(p_Msg);
+
+ memset(p_IpcReply, 0, (sizeof(uint8_t) * FM_PCD_MAX_REPLY_SIZE));
+ *p_ReplyLength = 0;
+
+ switch (p_IpcMsg->msgId)
+ {
+ case (FM_PCD_MASTER_IS_ALIVE):
+ *(uint8_t*)(p_IpcReply->replyBody) = 1;
+ p_IpcReply->error = E_OK;
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ break;
+ case (FM_PCD_MASTER_IS_ENABLED):
+ /* count partitions registrations */
+ if (p_FmPcd->enabled)
+ p_FmPcd->numOfEnabledGuestPartitionsPcds++;
+ *(uint8_t*)(p_IpcReply->replyBody) = (uint8_t)p_FmPcd->enabled;
+ p_IpcReply->error = E_OK;
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ break;
+ case (FM_PCD_GUEST_DISABLE):
+ if (p_FmPcd->numOfEnabledGuestPartitionsPcds)
+ {
+ p_FmPcd->numOfEnabledGuestPartitionsPcds--;
+ p_IpcReply->error = E_OK;
+ }
+ else
+ {
+ REPORT_ERROR(MINOR, E_INVALID_STATE,("Trying to disable an unregistered partition"));
+ p_IpcReply->error = E_INVALID_STATE;
+ }
+ *p_ReplyLength = sizeof(uint32_t);
+ break;
+ case (FM_PCD_GET_COUNTER):
+ {
+ e_FmPcdCounters inCounter;
+ uint32_t outCounter;
+
+ memcpy((uint8_t*)&inCounter, p_IpcMsg->msgBody, sizeof(uint32_t));
+ outCounter = FM_PCD_GetCounter(h_FmPcd, inCounter);
+ memcpy(p_IpcReply->replyBody, (uint8_t*)&outCounter, sizeof(uint32_t));
+ p_IpcReply->error = E_OK;
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t);
+ break;
+ }
+ case (FM_PCD_ALLOC_KG_SCHEMES):
+ {
+ t_FmPcdIpcKgSchemesParams ipcSchemesParams;
+
+ memcpy((uint8_t*)&ipcSchemesParams, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcKgSchemesParams));
+ err = FmPcdKgAllocSchemes(h_FmPcd,
+ ipcSchemesParams.numOfSchemes,
+ ipcSchemesParams.guestId,
+ p_IpcReply->replyBody);
+ p_IpcReply->error = err;
+ *p_ReplyLength = sizeof(uint32_t) + ipcSchemesParams.numOfSchemes*sizeof(uint8_t);
+ break;
+ }
+ case (FM_PCD_FREE_KG_SCHEMES):
+ {
+ t_FmPcdIpcKgSchemesParams ipcSchemesParams;
+
+ memcpy((uint8_t*)&ipcSchemesParams, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcKgSchemesParams));
+ err = FmPcdKgFreeSchemes(h_FmPcd,
+ ipcSchemesParams.numOfSchemes,
+ ipcSchemesParams.guestId,
+ ipcSchemesParams.schemesIds);
+ p_IpcReply->error = err;
+ *p_ReplyLength = sizeof(uint32_t);
+ break;
+ }
+ case (FM_PCD_ALLOC_KG_CLSPLAN):
+ {
+ t_FmPcdIpcKgClsPlanParams ipcKgClsPlanParams;
+
+ memcpy((uint8_t*)&ipcKgClsPlanParams, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcKgClsPlanParams));
+ err = KgAllocClsPlanEntries(h_FmPcd,
+ ipcKgClsPlanParams.numOfClsPlanEntries,
+ ipcKgClsPlanParams.guestId,
+ p_IpcReply->replyBody);
+ p_IpcReply->error = err;
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ break;
+ }
+ case (FM_PCD_FREE_KG_CLSPLAN):
+ {
+ t_FmPcdIpcKgClsPlanParams ipcKgClsPlanParams;
+
+ memcpy((uint8_t*)&ipcKgClsPlanParams, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcKgClsPlanParams));
+ KgFreeClsPlanEntries(h_FmPcd,
+ ipcKgClsPlanParams.numOfClsPlanEntries,
+ ipcKgClsPlanParams.guestId,
+ ipcKgClsPlanParams.clsPlanBase);
+ *p_ReplyLength = sizeof(uint32_t);
+ break;
+ }
+ case (FM_PCD_ALLOC_PROFILES):
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ uint16_t base;
+ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams));
+ base = PlcrAllocProfilesForPartition(h_FmPcd,
+ ipcAllocParams.base,
+ ipcAllocParams.num,
+ ipcAllocParams.guestId);
+ memcpy(p_IpcReply->replyBody, (uint16_t*)&base, sizeof(uint16_t));
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint16_t);
+ break;
+ }
+ case (FM_PCD_FREE_PROFILES):
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams));
+ PlcrFreeProfilesForPartition(h_FmPcd,
+ ipcAllocParams.base,
+ ipcAllocParams.num,
+ ipcAllocParams.guestId);
+ break;
+ }
+ case (FM_PCD_SET_PORT_PROFILES):
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams));
+ PlcrSetPortProfiles(h_FmPcd,
+ ipcAllocParams.guestId,
+ ipcAllocParams.num,
+ ipcAllocParams.base);
+ break;
+ }
+ case (FM_PCD_CLEAR_PORT_PROFILES):
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams));
+ PlcrClearPortProfiles(h_FmPcd,
+ ipcAllocParams.guestId);
+ break;
+ }
+ case (FM_PCD_GET_SW_PRS_OFFSET):
+ {
+ t_FmPcdIpcSwPrsLable ipcSwPrsLable;
+ uint32_t swPrsOffset;
+
+ memcpy((uint8_t*)&ipcSwPrsLable, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcSwPrsLable));
+ swPrsOffset =
+ FmPcdGetSwPrsOffset(h_FmPcd,
+ (e_NetHeaderType)ipcSwPrsLable.enumHdr,
+ ipcSwPrsLable.indexPerHdr);
+ memcpy(p_IpcReply->replyBody, (uint8_t*)&swPrsOffset, sizeof(uint32_t));
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t);
+ break;
+ }
+ case (FM_PCD_PRS_INC_PORT_STATS):
+ {
+ t_FmPcdIpcPrsIncludePort ipcPrsIncludePort;
+
+ memcpy((uint8_t*)&ipcPrsIncludePort, p_IpcMsg->msgBody, sizeof(t_FmPcdIpcPrsIncludePort));
+ PrsIncludePortInStatistics(h_FmPcd,
+ ipcPrsIncludePort.hardwarePortId,
+ ipcPrsIncludePort.include);
+ break;
+ }
+ default:
+ *p_ReplyLength = 0;
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("command not found!!!"));
+ }
+ return E_OK;
+}
+
+static uint32_t NetEnvLock(t_Handle h_NetEnv)
+{
+ ASSERT_COND(h_NetEnv);
+ return XX_LockIntrSpinlock(((t_FmPcdNetEnv*)h_NetEnv)->h_Spinlock);
+}
+
+static void NetEnvUnlock(t_Handle h_NetEnv, uint32_t intFlags)
+{
+ ASSERT_COND(h_NetEnv);
+ XX_UnlockIntrSpinlock(((t_FmPcdNetEnv*)h_NetEnv)->h_Spinlock, intFlags);
+}
+
+static void EnqueueLockToFreeLst(t_FmPcd *p_FmPcd, t_FmPcdLock *p_Lock)
+{
+ uint32_t intFlags;
+
+ intFlags = XX_LockIntrSpinlock(p_FmPcd->h_Spinlock);
+ LIST_AddToTail(&p_Lock->node, &p_FmPcd->freeLocksLst);
+ XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags);
+}
+
+static t_FmPcdLock * DequeueLockFromFreeLst(t_FmPcd *p_FmPcd)
+{
+ t_FmPcdLock *p_Lock = NULL;
+ uint32_t intFlags;
+
+ intFlags = XX_LockIntrSpinlock(p_FmPcd->h_Spinlock);
+ if (!LIST_IsEmpty(&p_FmPcd->freeLocksLst))
+ {
+ p_Lock = FM_PCD_LOCK_OBJ(p_FmPcd->freeLocksLst.p_Next);
+ LIST_DelAndInit(&p_Lock->node);
+ }
+ XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags);
+
+ return p_Lock;
+}
+
+static void EnqueueLockToAcquiredLst(t_FmPcd *p_FmPcd, t_FmPcdLock *p_Lock)
+{
+ uint32_t intFlags;
+
+ intFlags = XX_LockIntrSpinlock(p_FmPcd->h_Spinlock);
+ LIST_AddToTail(&p_Lock->node, &p_FmPcd->acquiredLocksLst);
+ XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags);
+}
+
+static t_Error FillFreeLocksLst(t_FmPcd *p_FmPcd)
+{
+ t_FmPcdLock *p_Lock;
+ int i;
+
+ for (i=0; i<10; i++)
+ {
+ p_Lock = (t_FmPcdLock *)XX_Malloc(sizeof(t_FmPcdLock));
+ if (!p_Lock)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("FM-PCD lock obj!"));
+ memset(p_Lock, 0, sizeof(t_FmPcdLock));
+ INIT_LIST(&p_Lock->node);
+ p_Lock->h_Spinlock = XX_InitSpinlock();
+ if (!p_Lock->h_Spinlock)
+ {
+ XX_Free(p_Lock);
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("FM-PCD spinlock obj!"));
+ }
+ EnqueueLockToFreeLst(p_FmPcd, p_Lock);
+ }
+
+ return E_OK;
+}
+
+static void ReleaseFreeLocksLst(t_FmPcd *p_FmPcd)
+{
+ t_FmPcdLock *p_Lock;
+
+ p_Lock = DequeueLockFromFreeLst(p_FmPcd);
+ while (p_Lock)
+ {
+ XX_FreeSpinlock(p_Lock->h_Spinlock);
+ XX_Free(p_Lock);
+ p_Lock = DequeueLockFromFreeLst(p_FmPcd);
+ }
+}
+
+
+
+/*****************************************************************************/
+/* Inter-module API routines */
+/*****************************************************************************/
+
+void FmPcdSetClsPlanGrpId(t_FmPcd *p_FmPcd, uint8_t netEnvId, uint8_t clsPlanGrpId)
+{
+ ASSERT_COND(p_FmPcd);
+ p_FmPcd->netEnvs[netEnvId].clsPlanGrpId = clsPlanGrpId;
+}
+
+t_Error PcdGetClsPlanGrpParams(t_FmPcd *p_FmPcd, t_FmPcdKgInterModuleClsPlanGrpParams *p_GrpParams)
+{
+ uint8_t netEnvId = p_GrpParams->netEnvId;
+ int i, k, j;
+
+ ASSERT_COND(p_FmPcd);
+ if (p_FmPcd->netEnvs[netEnvId].clsPlanGrpId != ILLEGAL_CLS_PLAN)
+ {
+ p_GrpParams->grpExists = TRUE;
+ p_GrpParams->clsPlanGrpId = p_FmPcd->netEnvs[netEnvId].clsPlanGrpId;
+ return E_OK;
+ }
+
+ for (i=0; ((i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) &&
+ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE)); i++)
+ {
+ for (k=0; ((k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) &&
+ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE)); k++)
+ {
+ /* if an option exists, add it to the opts list */
+ if (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].opt)
+ {
+ /* check if this option already exists, add if it doesn't */
+ for (j = 0;j<p_GrpParams->numOfOptions;j++)
+ {
+ if (p_GrpParams->options[j] == p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].opt)
+ break;
+ }
+ p_GrpParams->optVectors[j] |= p_FmPcd->netEnvs[netEnvId].unitsVectors[i];
+ if (j == p_GrpParams->numOfOptions)
+ {
+ p_GrpParams->options[p_GrpParams->numOfOptions] = p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].opt;
+ p_GrpParams->numOfOptions++;
+ }
+ }
+ }
+ }
+
+ if (p_GrpParams->numOfOptions == 0)
+ {
+ if (p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId != ILLEGAL_CLS_PLAN)
+ {
+ p_GrpParams->grpExists = TRUE;
+ p_GrpParams->clsPlanGrpId = p_FmPcd->p_FmPcdKg->emptyClsPlanGrpId;
+ }
+ }
+
+ return E_OK;
+
+}
+
+t_Error PcdGetVectorForOpt(t_FmPcd *p_FmPcd, uint8_t netEnvId, protocolOpt_t opt, uint32_t *p_Vector)
+{
+ uint8_t j,k;
+
+ *p_Vector = 0;
+
+ ASSERT_COND(p_FmPcd);
+ for (j=0; ((j < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) &&
+ (p_FmPcd->netEnvs[netEnvId].units[j].hdrs[0].hdr != HEADER_TYPE_NONE)); j++)
+ {
+ for (k=0; ((k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) &&
+ (p_FmPcd->netEnvs[netEnvId].units[j].hdrs[k].hdr != HEADER_TYPE_NONE)); k++)
+ {
+ if (p_FmPcd->netEnvs[netEnvId].units[j].hdrs[k].opt == opt)
+ *p_Vector |= p_FmPcd->netEnvs[netEnvId].unitsVectors[j];
+ }
+ }
+
+ if (!*p_Vector)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Requested option was not defined for this Network Environment Characteristics module"));
+ else
+ return E_OK;
+}
+
+t_Error PcdGetUnitsVector(t_FmPcd *p_FmPcd, t_NetEnvParams *p_Params)
+{
+ int i;
+
+ ASSERT_COND(p_FmPcd);
+ ASSERT_COND(p_Params->netEnvId < FM_MAX_NUM_OF_PORTS);
+
+ p_Params->vector = 0;
+ for (i=0; i<p_Params->numOfDistinctionUnits ;i++)
+ {
+ if (p_FmPcd->netEnvs[p_Params->netEnvId].units[p_Params->unitIds[i]].hdrs[0].hdr == HEADER_TYPE_NONE)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Requested unit was not defined for this Network Environment Characteristics module"));
+ ASSERT_COND(p_FmPcd->netEnvs[p_Params->netEnvId].unitsVectors[p_Params->unitIds[i]]);
+ p_Params->vector |= p_FmPcd->netEnvs[p_Params->netEnvId].unitsVectors[p_Params->unitIds[i]];
+ }
+
+ return E_OK;
+}
+
+bool PcdNetEnvIsUnitWithoutOpts(t_FmPcd *p_FmPcd, uint8_t netEnvId, uint32_t unitVector)
+{
+ int i=0, k;
+
+ ASSERT_COND(p_FmPcd);
+ /* check whether a given unit may be used by non-clsPlan users. */
+ /* first, recognize the unit by its vector */
+ while (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE)
+ {
+ if (p_FmPcd->netEnvs[netEnvId].unitsVectors[i] == unitVector)
+ {
+ for (k=0;
+ ((k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) &&
+ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE));
+ k++)
+ /* check that no option exists */
+ if ((protocolOpt_t)p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].opt)
+ return FALSE;
+ break;
+ }
+ i++;
+ }
+ /* assert that a unit was found to mach the vector */
+ ASSERT_COND(p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE);
+
+ return TRUE;
+}
+bool FmPcdNetEnvIsHdrExist(t_Handle h_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ int i, k;
+
+ ASSERT_COND(p_FmPcd);
+
+ for (i=0; ((i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) &&
+ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE)); i++)
+ {
+ for (k=0; ((k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) &&
+ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE)); k++)
+ if (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr == hdr)
+ return TRUE;
+ }
+ for (i=0; ((i < FM_PCD_MAX_NUM_OF_ALIAS_HDRS) &&
+ (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr != HEADER_TYPE_NONE)); i++)
+ {
+ if (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr == hdr)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+uint8_t FmPcdNetEnvGetUnitId(t_FmPcd *p_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr, bool interchangeable, protocolOpt_t opt)
+{
+ uint8_t i, k;
+
+ ASSERT_COND(p_FmPcd);
+
+ if (interchangeable)
+ {
+ for (i=0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) &&
+ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++)
+ {
+ for (k=0; (k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS) &&
+ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE); k++)
+ {
+ if ((p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].hdr == hdr) &&
+ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[k].opt == opt))
+
+ return i;
+ }
+ }
+ }
+ else
+ {
+ for (i=0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS) &&
+ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++)
+ if ((p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].hdr == hdr) &&
+ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[0].opt == opt) &&
+ (p_FmPcd->netEnvs[netEnvId].units[i].hdrs[1].hdr == HEADER_TYPE_NONE))
+ return i;
+
+ for (i=0; (i < FM_PCD_MAX_NUM_OF_ALIAS_HDRS) &&
+ (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr != HEADER_TYPE_NONE); i++)
+ if ((p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr == hdr) &&
+ (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].opt == opt))
+ return p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].aliasHdr;
+ }
+
+ return FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS;
+}
+
+t_Error FmPcdUnregisterReassmPort(t_Handle h_FmPcd, t_Handle h_IpReasmCommonPramTbl)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_FmPcdCcIpReassmTimeoutParams ccIpReassmTimeoutParams = {0};
+ uint8_t result;
+ t_Error err = E_OK;
+
+ ASSERT_COND(p_FmPcd);
+ ASSERT_COND(h_IpReasmCommonPramTbl);
+
+ ccIpReassmTimeoutParams.iprcpt = (uint32_t)(XX_VirtToPhys(h_IpReasmCommonPramTbl) - p_FmPcd->physicalMuramBase);
+ ccIpReassmTimeoutParams.activate = FALSE; /*Disable Timeout Task*/
+
+ if ((err = FmHcPcdCcIpTimeoutReassm(p_FmPcd->h_Hc, &ccIpReassmTimeoutParams, &result)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ switch (result)
+ {
+ case (0):
+ return E_OK;
+ case (1):
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, (""));
+ case (2):
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, (""));
+ case (3):
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("Disable Timeout Task with invalid IPRCPT"));
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
+ }
+
+ return E_OK;
+}
+
+e_NetHeaderType FmPcdGetAliasHdr(t_FmPcd *p_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr)
+{
+ int i;
+
+ ASSERT_COND(p_FmPcd);
+ ASSERT_COND(netEnvId < FM_MAX_NUM_OF_PORTS);
+
+ for (i=0; (i < FM_PCD_MAX_NUM_OF_ALIAS_HDRS)
+ && (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr != HEADER_TYPE_NONE); i++)
+ {
+ if (p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].hdr == hdr)
+ return p_FmPcd->netEnvs[netEnvId].aliasHdrs[i].aliasHdr;
+ }
+
+ return HEADER_TYPE_NONE;
+}
+
+void FmPcdPortRegister(t_Handle h_FmPcd, t_Handle h_FmPort, uint8_t hardwarePortId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint16_t swPortIndex = 0;
+
+ ASSERT_COND(h_FmPcd);
+ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId);
+ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].h_FmPort = h_FmPort;
+}
+
+uint32_t FmPcdGetLcv(t_Handle h_FmPcd, uint32_t netEnvId, uint8_t hdrNum)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ ASSERT_COND(h_FmPcd);
+ return p_FmPcd->netEnvs[netEnvId].lcvs[hdrNum];
+}
+
+uint32_t FmPcdGetMacsecLcv(t_Handle h_FmPcd, uint32_t netEnvId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ ASSERT_COND(h_FmPcd);
+ return p_FmPcd->netEnvs[netEnvId].macsecVector;
+}
+
+uint8_t FmPcdGetNetEnvId(t_Handle h_NetEnv)
+{
+ return ((t_FmPcdNetEnv*)h_NetEnv)->netEnvId;
+}
+
+void FmPcdIncNetEnvOwners(t_Handle h_FmPcd, uint8_t netEnvId)
+{
+ uint32_t intFlags;
+
+ ASSERT_COND(h_FmPcd);
+
+ intFlags = NetEnvLock(&((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId]);
+ ((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId].owners++;
+ NetEnvUnlock(&((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId], intFlags);
+}
+
+void FmPcdDecNetEnvOwners(t_Handle h_FmPcd, uint8_t netEnvId)
+{
+ uint32_t intFlags;
+
+ ASSERT_COND(h_FmPcd);
+ ASSERT_COND(((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId].owners);
+
+ intFlags = NetEnvLock(&((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId]);
+ ((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId].owners--;
+ NetEnvUnlock(&((t_FmPcd*)h_FmPcd)->netEnvs[netEnvId], intFlags);
+}
+
+uint32_t FmPcdLock(t_Handle h_FmPcd)
+{
+ ASSERT_COND(h_FmPcd);
+ return XX_LockIntrSpinlock(((t_FmPcd*)h_FmPcd)->h_Spinlock);
+}
+
+void FmPcdUnlock(t_Handle h_FmPcd, uint32_t intFlags)
+{
+ ASSERT_COND(h_FmPcd);
+ XX_UnlockIntrSpinlock(((t_FmPcd*)h_FmPcd)->h_Spinlock, intFlags);
+}
+
+t_FmPcdLock * FmPcdAcquireLock(t_Handle h_FmPcd)
+{
+ t_FmPcdLock *p_Lock;
+ ASSERT_COND(h_FmPcd);
+ p_Lock = DequeueLockFromFreeLst((t_FmPcd*)h_FmPcd);
+ if (!p_Lock)
+ {
+ FillFreeLocksLst(h_FmPcd);
+ p_Lock = DequeueLockFromFreeLst((t_FmPcd*)h_FmPcd);
+ }
+
+ if (p_Lock)
+ EnqueueLockToAcquiredLst((t_FmPcd*)h_FmPcd, p_Lock);
+ return p_Lock;
+}
+
+void FmPcdReleaseLock(t_Handle h_FmPcd, t_FmPcdLock *p_Lock)
+{
+ uint32_t intFlags;
+ ASSERT_COND(h_FmPcd);
+ intFlags = FmPcdLock(h_FmPcd);
+ LIST_DelAndInit(&p_Lock->node);
+ FmPcdUnlock(h_FmPcd, intFlags);
+ EnqueueLockToFreeLst((t_FmPcd*)h_FmPcd, p_Lock);
+}
+
+bool FmPcdLockTryLockAll(t_Handle h_FmPcd)
+{
+ uint32_t intFlags;
+ t_List *p_Pos, *p_SavedPos=NULL;
+
+ ASSERT_COND(h_FmPcd);
+ intFlags = FmPcdLock(h_FmPcd);
+ LIST_FOR_EACH(p_Pos, &((t_FmPcd*)h_FmPcd)->acquiredLocksLst)
+ {
+ t_FmPcdLock *p_Lock = FM_PCD_LOCK_OBJ(p_Pos);
+ if (!FmPcdLockTryLock(p_Lock))
+ {
+ p_SavedPos = p_Pos;
+ break;
+ }
+ }
+ if (p_SavedPos)
+ {
+ LIST_FOR_EACH(p_Pos, &((t_FmPcd*)h_FmPcd)->acquiredLocksLst)
+ {
+ t_FmPcdLock *p_Lock = FM_PCD_LOCK_OBJ(p_Pos);
+ if (p_Pos == p_SavedPos)
+ break;
+ FmPcdLockUnlock(p_Lock);
+ }
+ }
+ FmPcdUnlock(h_FmPcd, intFlags);
+
+ CORE_MemoryBarrier();
+
+ if (p_SavedPos)
+ return FALSE;
+
+ return TRUE;
+}
+
+void FmPcdLockUnlockAll(t_Handle h_FmPcd)
+{
+ uint32_t intFlags;
+ t_List *p_Pos;
+
+ ASSERT_COND(h_FmPcd);
+ intFlags = FmPcdLock(h_FmPcd);
+ LIST_FOR_EACH(p_Pos, &((t_FmPcd*)h_FmPcd)->acquiredLocksLst)
+ {
+ t_FmPcdLock *p_Lock = FM_PCD_LOCK_OBJ(p_Pos);
+ p_Lock->flag = FALSE;
+ }
+ FmPcdUnlock(h_FmPcd, intFlags);
+
+ CORE_MemoryBarrier();
+}
+
+t_Error FmPcdHcSync(t_Handle h_FmPcd)
+{
+ ASSERT_COND(h_FmPcd);
+ ASSERT_COND(((t_FmPcd*)h_FmPcd)->h_Hc);
+
+ return FmHcPcdSync(((t_FmPcd*)h_FmPcd)->h_Hc);
+}
+
+t_Handle FmPcdGetHcHandle(t_Handle h_FmPcd)
+{
+ ASSERT_COND(h_FmPcd);
+ return ((t_FmPcd*)h_FmPcd)->h_Hc;
+}
+
+bool FmPcdIsAdvancedOffloadSupported(t_Handle h_FmPcd)
+{
+ ASSERT_COND(h_FmPcd);
+ return ((t_FmPcd*)h_FmPcd)->advancedOffloadSupport;
+}
+/*********************** End of inter-module routines ************************/
+
+
+/****************************************/
+/* API Init unit functions */
+/****************************************/
+
+t_Handle FM_PCD_Config(t_FmPcdParams *p_FmPcdParams)
+{
+ t_FmPcd *p_FmPcd = NULL;
+ t_FmPhysAddr physicalMuramBase;
+ uint8_t i;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPcdParams, E_INVALID_HANDLE,NULL);
+
+ p_FmPcd = (t_FmPcd *) XX_Malloc(sizeof(t_FmPcd));
+ if (!p_FmPcd)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD"));
+ return NULL;
+ }
+ memset(p_FmPcd, 0, sizeof(t_FmPcd));
+
+ p_FmPcd->p_FmPcdDriverParam = (t_FmPcdDriverParam *) XX_Malloc(sizeof(t_FmPcdDriverParam));
+ if (!p_FmPcd->p_FmPcdDriverParam)
+ {
+ XX_Free(p_FmPcd);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD Driver Param"));
+ return NULL;
+ }
+ memset(p_FmPcd->p_FmPcdDriverParam, 0, sizeof(t_FmPcdDriverParam));
+
+ p_FmPcd->h_Fm = p_FmPcdParams->h_Fm;
+ p_FmPcd->guestId = FmGetGuestId(p_FmPcd->h_Fm);
+ p_FmPcd->h_FmMuram = FmGetMuramHandle(p_FmPcd->h_Fm);
+ if (p_FmPcd->h_FmMuram)
+ {
+ FmGetPhysicalMuramBase(p_FmPcdParams->h_Fm, &physicalMuramBase);
+ p_FmPcd->physicalMuramBase = (uint64_t)((uint64_t)(&physicalMuramBase)->low | ((uint64_t)(&physicalMuramBase)->high << 32));
+ }
+
+ for (i = 0; i<FM_MAX_NUM_OF_PORTS; i++)
+ p_FmPcd->netEnvs[i].clsPlanGrpId = ILLEGAL_CLS_PLAN;
+
+ if (p_FmPcdParams->useHostCommand)
+ {
+ t_FmHcParams hcParams;
+
+ memset(&hcParams, 0, sizeof(hcParams));
+ hcParams.h_Fm = p_FmPcd->h_Fm;
+ hcParams.h_FmPcd = (t_Handle)p_FmPcd;
+ memcpy((uint8_t*)&hcParams.params, (uint8_t*)&p_FmPcdParams->hc, sizeof(t_FmPcdHcParams));
+ p_FmPcd->h_Hc = FmHcConfigAndInit(&hcParams);
+ if (!p_FmPcd->h_Hc)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD HC"));
+ FM_PCD_Free(p_FmPcd);
+ return NULL;
+ }
+ }
+ else if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("No Host Command defined for a guest partition."));
+
+ if (p_FmPcdParams->kgSupport)
+ {
+ p_FmPcd->p_FmPcdKg = (t_FmPcdKg *)KgConfig(p_FmPcd, p_FmPcdParams);
+ if (!p_FmPcd->p_FmPcdKg)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD Keygen"));
+ FM_PCD_Free(p_FmPcd);
+ return NULL;
+ }
+ }
+
+ if (p_FmPcdParams->plcrSupport)
+ {
+ p_FmPcd->p_FmPcdPlcr = (t_FmPcdPlcr *)PlcrConfig(p_FmPcd, p_FmPcdParams);
+ if (!p_FmPcd->p_FmPcdPlcr)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD Policer"));
+ FM_PCD_Free(p_FmPcd);
+ return NULL;
+ }
+ }
+
+ if (p_FmPcdParams->prsSupport)
+ {
+ p_FmPcd->p_FmPcdPrs = (t_FmPcdPrs *)PrsConfig(p_FmPcd, p_FmPcdParams);
+ if (!p_FmPcd->p_FmPcdPrs)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD Parser"));
+ FM_PCD_Free(p_FmPcd);
+ return NULL;
+ }
+ }
+
+ p_FmPcd->h_Spinlock = XX_InitSpinlock();
+ if (!p_FmPcd->h_Spinlock)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD spinlock"));
+ FM_PCD_Free(p_FmPcd);
+ return NULL;
+ }
+ INIT_LIST(&p_FmPcd->freeLocksLst);
+ INIT_LIST(&p_FmPcd->acquiredLocksLst);
+
+ p_FmPcd->numOfEnabledGuestPartitionsPcds = 0;
+
+ p_FmPcd->f_Exception = p_FmPcdParams->f_Exception;
+ p_FmPcd->f_FmPcdIndexedException = p_FmPcdParams->f_ExceptionId;
+ p_FmPcd->h_App = p_FmPcdParams->h_App;
+
+ p_FmPcd->p_CcShadow = NULL;
+ p_FmPcd->ccShadowSize = 0;
+ p_FmPcd->ccShadowAlign = 0;
+
+ p_FmPcd->h_ShadowSpinlock = XX_InitSpinlock();
+ if (!p_FmPcd->h_ShadowSpinlock)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM PCD shadow spinlock"));
+ FM_PCD_Free(p_FmPcd);
+ return NULL;
+ }
+
+ return p_FmPcd;
+}
+
+t_Error FM_PCD_Init(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_Error err = E_OK;
+ t_FmPcdIpcMsg msg;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE);
+
+ FM_GetRevision(p_FmPcd->h_Fm, &p_FmPcd->fmRevInfo);
+
+ if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ {
+ memset(p_FmPcd->fmPcdIpcHandlerModuleName, 0, (sizeof(char)) * MODULE_NAME_SIZE);
+ if (Sprint (p_FmPcd->fmPcdIpcHandlerModuleName, "FM_PCD_%d_%d", FmGetId(p_FmPcd->h_Fm), NCSW_MASTER_ID) != 10)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
+ memset(p_FmPcd->fmPcdModuleName, 0, (sizeof(char)) * MODULE_NAME_SIZE);
+ if (Sprint (p_FmPcd->fmPcdModuleName, "FM_PCD_%d_%d",FmGetId(p_FmPcd->h_Fm), p_FmPcd->guestId) != (p_FmPcd->guestId<10 ? 10:11))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
+
+ p_FmPcd->h_IpcSession = XX_IpcInitSession(p_FmPcd->fmPcdIpcHandlerModuleName, p_FmPcd->fmPcdModuleName);
+ if (p_FmPcd->h_IpcSession)
+ {
+ t_FmPcdIpcReply reply;
+ uint32_t replyLength;
+ uint8_t isMasterAlive = 0;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_PCD_MASTER_IS_ALIVE;
+ msg.msgBody[0] = p_FmPcd->guestId;
+ blockingFlag = TRUE;
+
+ do
+ {
+ replyLength = sizeof(uint32_t) + sizeof(isMasterAlive);
+ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId)+sizeof(p_FmPcd->guestId),
+ (uint8_t*)&reply,
+ &replyLength,
+ IpcMsgCompletionCB,
+ h_FmPcd)) != E_OK)
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ while (blockingFlag) ;
+ if (replyLength != (sizeof(uint32_t) + sizeof(isMasterAlive)))
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ isMasterAlive = *(uint8_t*)(reply.replyBody);
+ } while (!isMasterAlive);
+ }
+ }
+
+ CHECK_INIT_PARAMETERS(p_FmPcd, CheckFmPcdParameters);
+
+ if (p_FmPcd->p_FmPcdKg)
+ {
+ err = KgInit(p_FmPcd);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ if (p_FmPcd->p_FmPcdPlcr)
+ {
+ err = PlcrInit(p_FmPcd);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ if (p_FmPcd->p_FmPcdPrs)
+ {
+ err = PrsInit(p_FmPcd);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ if (p_FmPcd->guestId == NCSW_MASTER_ID)
+ {
+ /* register to inter-core messaging mechanism */
+ memset(p_FmPcd->fmPcdModuleName, 0, (sizeof(char)) * MODULE_NAME_SIZE);
+ if (Sprint (p_FmPcd->fmPcdModuleName, "FM_PCD_%d_%d",FmGetId(p_FmPcd->h_Fm),NCSW_MASTER_ID) != 10)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
+ err = XX_IpcRegisterMsgHandler(p_FmPcd->fmPcdModuleName, IpcMsgHandlerCB, p_FmPcd, FM_PCD_MAX_REPLY_SIZE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ /* IPv6 Frame-Id used for fragmentation */
+ p_FmPcd->ipv6FrameIdAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_FmPcd->h_FmMuram, 4, 4));
+ if (!p_FmPcd->ipv6FrameIdAddr)
+ {
+ FM_PCD_Free(p_FmPcd);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM allocation for IPv6 Frame-Id"));
+ }
+ IOMemSet32(UINT_TO_PTR(p_FmPcd->ipv6FrameIdAddr), 0, 4);
+
+ XX_Free(p_FmPcd->p_FmPcdDriverParam);
+ p_FmPcd->p_FmPcdDriverParam = NULL;
+
+ FmRegisterPcd(p_FmPcd->h_Fm, p_FmPcd);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_Free(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd =(t_FmPcd *)h_FmPcd;
+ t_Error err = E_OK;
+
+ if (p_FmPcd->ipv6FrameIdAddr)
+ FM_MURAM_FreeMem(p_FmPcd->h_FmMuram, UINT_TO_PTR(p_FmPcd->ipv6FrameIdAddr));
+
+ if (p_FmPcd->enabled)
+ FM_PCD_Disable(p_FmPcd);
+
+ if (p_FmPcd->p_FmPcdDriverParam)
+ {
+ XX_Free(p_FmPcd->p_FmPcdDriverParam);
+ p_FmPcd->p_FmPcdDriverParam = NULL;
+ }
+
+ if (p_FmPcd->p_FmPcdKg)
+ {
+ if ((err = KgFree(p_FmPcd)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ XX_Free(p_FmPcd->p_FmPcdKg);
+ p_FmPcd->p_FmPcdKg = NULL;
+ }
+
+ if (p_FmPcd->p_FmPcdPlcr)
+ {
+ if ((err = PlcrFree(p_FmPcd)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ XX_Free(p_FmPcd->p_FmPcdPlcr);
+ p_FmPcd->p_FmPcdPlcr = NULL;
+ }
+
+ if (p_FmPcd->p_FmPcdPrs)
+ {
+ if (p_FmPcd->guestId == NCSW_MASTER_ID)
+ PrsFree(p_FmPcd);
+ XX_Free(p_FmPcd->p_FmPcdPrs);
+ p_FmPcd->p_FmPcdPrs = NULL;
+ }
+
+ if (p_FmPcd->h_Hc)
+ {
+ FmHcFree(p_FmPcd->h_Hc);
+ p_FmPcd->h_Hc = NULL;
+ }
+
+ XX_IpcUnregisterMsgHandler(p_FmPcd->fmPcdModuleName);
+
+ FmUnregisterPcd(p_FmPcd->h_Fm);
+
+ ReleaseFreeLocksLst(p_FmPcd);
+
+ if (p_FmPcd->h_Spinlock)
+ XX_FreeSpinlock(p_FmPcd->h_Spinlock);
+
+ if (p_FmPcd->h_ShadowSpinlock)
+ XX_FreeSpinlock(p_FmPcd->h_ShadowSpinlock);
+
+ XX_Free(p_FmPcd);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_ConfigException(t_Handle h_FmPcd, e_FmPcdExceptions exception, bool enable)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t bitMask = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+
+ if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ConfigException - guest mode!"));
+
+ GET_FM_PCD_EXCEPTION_FLAG(bitMask, exception);
+ if (bitMask)
+ {
+ if (enable)
+ p_FmPcd->exceptions |= bitMask;
+ else
+ p_FmPcd->exceptions &= ~bitMask;
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
+
+ return E_OK;
+}
+
+t_Error FM_PCD_ConfigHcFramesDataMemory(t_Handle h_FmPcd, uint8_t memId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_HANDLE);
+
+ return FmHcSetFramesDataMemory(p_FmPcd->h_Hc, memId);
+}
+
+t_Error FM_PCD_Enable(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE);
+
+ if (p_FmPcd->enabled)
+ return E_OK;
+
+ if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&
+ p_FmPcd->h_IpcSession)
+ {
+ uint8_t enabled;
+ t_FmPcdIpcMsg msg;
+ t_FmPcdIpcReply reply;
+ uint32_t replyLength;
+
+ memset(&reply, 0, sizeof(reply));
+ memset(&msg, 0, sizeof(msg));
+ msg.msgId = FM_PCD_MASTER_IS_ENABLED;
+ replyLength = sizeof(uint32_t) + sizeof(enabled);
+ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t) + sizeof(enabled))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ p_FmPcd->enabled = (bool)!!(*(uint8_t*)(reply.replyBody));
+ if (!p_FmPcd->enabled)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM-PCD master should be enabled first!"));
+
+ return E_OK;
+ }
+ else if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without IPC!"));
+
+ if (p_FmPcd->p_FmPcdKg)
+ KgEnable(p_FmPcd);
+
+ if (p_FmPcd->p_FmPcdPlcr)
+ PlcrEnable(p_FmPcd);
+
+ if (p_FmPcd->p_FmPcdPrs)
+ PrsEnable(p_FmPcd);
+
+ p_FmPcd->enabled = TRUE;
+
+ return E_OK;
+}
+
+t_Error FM_PCD_Disable(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE);
+
+ if (!p_FmPcd->enabled)
+ return E_OK;
+
+ if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&
+ p_FmPcd->h_IpcSession)
+ {
+ t_FmPcdIpcMsg msg;
+ t_FmPcdIpcReply reply;
+ uint32_t replyLength;
+
+ memset(&reply, 0, sizeof(reply));
+ memset(&msg, 0, sizeof(msg));
+ msg.msgId = FM_PCD_GUEST_DISABLE;
+ replyLength = sizeof(uint32_t);
+ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ if (reply.error == E_OK)
+ p_FmPcd->enabled = FALSE;
+
+ return (t_Error)(reply.error);
+ }
+ else if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without IPC!"));
+
+ if (p_FmPcd->numOfEnabledGuestPartitionsPcds != 0)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,
+ ("Trying to disable a master partition PCD while"
+ "guest partitions are still enabled!"));
+
+ if (p_FmPcd->p_FmPcdKg)
+ KgDisable(p_FmPcd);
+
+ if (p_FmPcd->p_FmPcdPlcr)
+ PlcrDisable(p_FmPcd);
+
+ if (p_FmPcd->p_FmPcdPrs)
+ PrsDisable(p_FmPcd);
+
+ p_FmPcd->enabled = FALSE;
+
+ return E_OK;
+}
+
+t_Handle FM_PCD_NetEnvCharacteristicsSet(t_Handle h_FmPcd, t_FmPcdNetEnvParams *p_NetEnvParams)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t intFlags, specialUnits = 0;
+ uint8_t bitId = 0;
+ uint8_t i, j, k;
+ uint8_t netEnvCurrId;
+ uint8_t ipsecAhUnit = 0,ipsecEspUnit = 0;
+ bool ipsecAhExists = FALSE, ipsecEspExists = FALSE, shim1Selected = FALSE;
+ uint8_t hdrNum;
+ t_FmPcdNetEnvParams *p_ModifiedNetEnvParams;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_STATE, NULL);
+ SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE, NULL);
+ SANITY_CHECK_RETURN_VALUE(p_NetEnvParams, E_NULL_POINTER, NULL);
+
+ intFlags = FmPcdLock(p_FmPcd);
+
+ /* find a new netEnv */
+ for (i = 0; i < FM_MAX_NUM_OF_PORTS; i++)
+ if (!p_FmPcd->netEnvs[i].used)
+ break;
+
+ if (i== FM_MAX_NUM_OF_PORTS)
+ {
+ REPORT_ERROR(MAJOR, E_FULL,("No more than %d netEnv's allowed.", FM_MAX_NUM_OF_PORTS));
+ FmPcdUnlock(p_FmPcd, intFlags);
+ return NULL;
+ }
+
+ p_FmPcd->netEnvs[i].used = TRUE;
+ FmPcdUnlock(p_FmPcd, intFlags);
+
+ /* As anyone doesn't have handle of this netEnv yet, no need
+ to protect it with spinlocks */
+
+ p_ModifiedNetEnvParams = (t_FmPcdNetEnvParams *)XX_Malloc(sizeof(t_FmPcdNetEnvParams));
+ if (!p_ModifiedNetEnvParams)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FmPcdNetEnvParams"));
+ return NULL;
+ }
+
+ memcpy(p_ModifiedNetEnvParams, p_NetEnvParams, sizeof(t_FmPcdNetEnvParams));
+ p_NetEnvParams = p_ModifiedNetEnvParams;
+
+ netEnvCurrId = (uint8_t)i;
+
+ /* clear from previous use */
+ memset(&p_FmPcd->netEnvs[netEnvCurrId].units, 0, FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS * sizeof(t_FmPcdIntDistinctionUnit));
+ memset(&p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs, 0, FM_PCD_MAX_NUM_OF_ALIAS_HDRS * sizeof(t_FmPcdNetEnvAliases));
+ memcpy(&p_FmPcd->netEnvs[netEnvCurrId].units, p_NetEnvParams->units, p_NetEnvParams->numOfDistinctionUnits*sizeof(t_FmPcdIntDistinctionUnit));
+
+ p_FmPcd->netEnvs[netEnvCurrId].netEnvId = netEnvCurrId;
+ p_FmPcd->netEnvs[netEnvCurrId].h_FmPcd = p_FmPcd;
+
+ p_FmPcd->netEnvs[netEnvCurrId].clsPlanGrpId = ILLEGAL_CLS_PLAN;
+
+ /* check that header with opt is not interchanged with the same header */
+ for (i = 0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS)
+ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++)
+ {
+ for (k = 0; (k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS)
+ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE); k++)
+ {
+ /* if an option exists, check that other headers are not the same header
+ without option */
+ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt)
+ {
+ for (j = 0; (j < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS)
+ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[j].hdr != HEADER_TYPE_NONE); j++)
+ {
+ if ((p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[j].hdr == p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr) &&
+ !p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[j].opt)
+ {
+ REPORT_ERROR(MINOR, E_FULL,
+ ("Illegal unit - header with opt may not be interchangeable with the same header without opt"));
+ XX_Free(p_ModifiedNetEnvParams);
+ return NULL;
+ }
+ }
+ }
+ }
+ }
+
+ /* Specific headers checking */
+ for (i = 0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS)
+ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++)
+ {
+ for (k = 0; (k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS)
+ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE); k++)
+ {
+ /* Some headers pairs may not be defined on different units as the parser
+ doesn't distinguish */
+ /* IPSEC_AH and IPSEC_SPI can't be 2 units, */
+ /* check that header with opt is not interchanged with the same header */
+ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_IPSEC_AH)
+ {
+ if (ipsecEspExists && (ipsecEspUnit != i))
+ {
+ REPORT_ERROR(MINOR, E_INVALID_STATE, ("HEADER_TYPE_IPSEC_AH and HEADER_TYPE_IPSEC_ESP may not be defined in separate units"));
+ XX_Free(p_ModifiedNetEnvParams);
+ return NULL;
+ }
+ else
+ {
+ ipsecAhUnit = i;
+ ipsecAhExists = TRUE;
+ }
+ }
+ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_IPSEC_ESP)
+ {
+ if (ipsecAhExists && (ipsecAhUnit != i))
+ {
+ REPORT_ERROR(MINOR, E_INVALID_STATE, ("HEADER_TYPE_IPSEC_AH and HEADER_TYPE_IPSEC_ESP may not be defined in separate units"));
+ XX_Free(p_ModifiedNetEnvParams);
+ return NULL;
+ }
+ else
+ {
+ ipsecEspUnit = i;
+ ipsecEspExists = TRUE;
+ }
+ }
+ /* ENCAP_ESP */
+ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_UDP_ENCAP_ESP)
+ {
+ /* IPSec UDP encapsulation is currently set to use SHIM1 */
+ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].hdr = HEADER_TYPE_UDP_ENCAP_ESP;
+ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits++].aliasHdr = HEADER_TYPE_USER_DEFINED_SHIM1;
+ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr = HEADER_TYPE_USER_DEFINED_SHIM1;
+ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt = 0;
+ }
+#ifdef FM_CAPWAP_SUPPORT
+ /* UDP_LITE */
+ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_UDP_LITE)
+ {
+ /* IPSec UDP encapsulation is currently set to use SHIM1 */
+ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].hdr = HEADER_TYPE_UDP_LITE;
+ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits++].aliasHdr = HEADER_TYPE_UDP;
+ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr = HEADER_TYPE_UDP;
+ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt = 0;
+ }
+#endif /* FM_CAPWAP_SUPPORT */
+
+ /* IP FRAG */
+ if ((p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_IPv4) &&
+ (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt == IPV4_FRAG_1))
+ {
+ /* If IPv4+Frag, we need to set 2 units - SHIM 2 and IPv4. We first set SHIM2, and than check if
+ * IPv4 exists. If so we don't need to set an extra unit
+ * We consider as "having IPv4" any IPv4 without interchangeable headers
+ * but including any options. */
+ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].hdr = HEADER_TYPE_IPv4;
+ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].opt = IPV4_FRAG_1;
+ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits++].aliasHdr = HEADER_TYPE_USER_DEFINED_SHIM2;
+ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr = HEADER_TYPE_USER_DEFINED_SHIM2;
+ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt = 0;
+
+ /* check if IPv4 header exists by itself */
+ if (FmPcdNetEnvGetUnitId(p_FmPcd, netEnvCurrId, HEADER_TYPE_IPv4, FALSE, 0) == FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS)
+ {
+ p_FmPcd->netEnvs[netEnvCurrId].units[p_NetEnvParams->numOfDistinctionUnits].hdrs[0].hdr = HEADER_TYPE_IPv4;
+ p_FmPcd->netEnvs[netEnvCurrId].units[p_NetEnvParams->numOfDistinctionUnits++].hdrs[0].opt = 0;
+ }
+ }
+ if ((p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr == HEADER_TYPE_IPv6) &&
+ (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt == IPV6_FRAG_1))
+ {
+ /* If IPv6+Frag, we need to set 2 units - SHIM 2 and IPv6. We first set SHIM2, and than check if
+ * IPv4 exists. If so we don't need to set an extra unit
+ * We consider as "having IPv6" any IPv6 without interchangeable headers
+ * but including any options. */
+ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].hdr = HEADER_TYPE_IPv6;
+ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits].opt = IPV6_FRAG_1;
+ p_FmPcd->netEnvs[netEnvCurrId].aliasHdrs[specialUnits++].aliasHdr = HEADER_TYPE_USER_DEFINED_SHIM2;
+ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr = HEADER_TYPE_USER_DEFINED_SHIM2;
+ p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].opt = 0;
+
+ /* check if IPv6 header exists by itself */
+ if (FmPcdNetEnvGetUnitId(p_FmPcd, netEnvCurrId, HEADER_TYPE_IPv6, FALSE, 0) == FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS)
+ {
+ p_FmPcd->netEnvs[netEnvCurrId].units[p_NetEnvParams->numOfDistinctionUnits].hdrs[0].hdr = HEADER_TYPE_IPv6;
+ p_FmPcd->netEnvs[netEnvCurrId].units[p_NetEnvParams->numOfDistinctionUnits++].hdrs[0].opt = 0;
+ }
+ }
+ }
+ }
+
+ /* if private header (shim), check that no other headers specified */
+ for (i = 0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS)
+ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++)
+ {
+ if (IS_PRIVATE_HEADER(p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr))
+ if (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[1].hdr != HEADER_TYPE_NONE)
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("SHIM header may not be interchanged with other headers"));
+ XX_Free(p_ModifiedNetEnvParams);
+ return NULL;
+ }
+ }
+
+ for (i = 0; i < p_NetEnvParams->numOfDistinctionUnits; i++)
+ {
+ if (IS_PRIVATE_HEADER(p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr))
+ switch (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr)
+ {
+ case (HEADER_TYPE_USER_DEFINED_SHIM1):
+ if (shim1Selected)
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("SHIM header cannot be selected with UDP_IPSEC_ESP"));
+ XX_Free(p_ModifiedNetEnvParams);
+ return NULL;
+ }
+ shim1Selected = TRUE;
+ p_FmPcd->netEnvs[netEnvCurrId].unitsVectors[i] = 0x00000001;
+ break;
+ case (HEADER_TYPE_USER_DEFINED_SHIM2):
+ p_FmPcd->netEnvs[netEnvCurrId].unitsVectors[i] = 0x00000002;
+ break;
+ default:
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Requested SHIM not supported"));
+ }
+ else
+ {
+ p_FmPcd->netEnvs[netEnvCurrId].unitsVectors[i] = (uint32_t)(0x80000000 >> bitId++);
+
+ if (IS_SPECIAL_HEADER(p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr))
+ p_FmPcd->netEnvs[netEnvCurrId].macsecVector = p_FmPcd->netEnvs[netEnvCurrId].unitsVectors[i];
+ }
+ }
+
+ /* define a set of hardware parser LCV's according to the defined netenv */
+
+ /* set an array of LCV's for each header in the netEnv */
+ for (i = 0; (i < FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS)
+ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr != HEADER_TYPE_NONE); i++)
+ {
+ /* private headers have no LCV in the hard parser */
+ if (!IS_PRIVATE_HEADER(p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[0].hdr))
+ {
+ for (k = 0; (k < FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS)
+ && (p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr != HEADER_TYPE_NONE); k++)
+ {
+ GET_PRS_HDR_NUM(hdrNum, p_FmPcd->netEnvs[netEnvCurrId].units[i].hdrs[k].hdr);
+ if ((hdrNum == ILLEGAL_HDR_NUM) || (hdrNum == NO_HDR_NUM))
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, NO_MSG);
+ XX_Free(p_ModifiedNetEnvParams);
+ return NULL;
+ }
+ p_FmPcd->netEnvs[netEnvCurrId].lcvs[hdrNum] |= p_FmPcd->netEnvs[netEnvCurrId].unitsVectors[i];
+ }
+ }
+ }
+ XX_Free(p_ModifiedNetEnvParams);
+
+ p_FmPcd->netEnvs[netEnvCurrId].h_Spinlock = XX_InitSpinlock();
+ if (!p_FmPcd->netEnvs[netEnvCurrId].h_Spinlock)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Pcd NetEnv spinlock"));
+ return NULL;
+ }
+ return &p_FmPcd->netEnvs[netEnvCurrId];
+}
+
+t_Error FM_PCD_NetEnvCharacteristicsDelete(t_Handle h_NetEnv)
+{
+ t_FmPcdNetEnv *p_NetEnv = (t_FmPcdNetEnv*)h_NetEnv;
+ t_FmPcd *p_FmPcd = p_NetEnv->h_FmPcd;
+ uint32_t intFlags;
+ uint8_t netEnvId = p_NetEnv->netEnvId;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+
+ /* check that no port is bound to this netEnv */
+ if (p_FmPcd->netEnvs[netEnvId].owners)
+ {
+ RETURN_ERROR(MINOR, E_INVALID_STATE,
+ ("Trying to delete a netEnv that has ports/schemes/trees/clsPlanGrps bound to"));
+ }
+
+ intFlags = FmPcdLock(p_FmPcd);
+
+ p_FmPcd->netEnvs[netEnvId].used = FALSE;
+ p_FmPcd->netEnvs[netEnvId].clsPlanGrpId = ILLEGAL_CLS_PLAN;
+
+ memset(p_FmPcd->netEnvs[netEnvId].units, 0, sizeof(t_FmPcdIntDistinctionUnit)*FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS);
+ memset(p_FmPcd->netEnvs[netEnvId].unitsVectors, 0, sizeof(uint32_t)*FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS);
+ memset(p_FmPcd->netEnvs[netEnvId].lcvs, 0, sizeof(uint32_t)*FM_PCD_PRS_NUM_OF_HDRS);
+
+ if (p_FmPcd->netEnvs[netEnvId].h_Spinlock)
+ XX_FreeSpinlock(p_FmPcd->netEnvs[netEnvId].h_Spinlock);
+
+ FmPcdUnlock(p_FmPcd, intFlags);
+ return E_OK;
+}
+
+void FM_PCD_HcTxConf(t_Handle h_FmPcd, t_DpaaFD *p_Fd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ SANITY_CHECK_RETURN(h_FmPcd, E_INVALID_STATE);
+
+ FmHcTxConf(p_FmPcd->h_Hc, p_Fd);
+}
+
+t_Error FM_PCD_SetAdvancedOffloadSupport(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_FmCtrlCodeRevisionInfo revInfo;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->enabled, E_INVALID_STATE);
+
+ if ((err = FM_GetFmanCtrlCodeRevision(p_FmPcd->h_Fm, &revInfo)) != E_OK)
+ {
+ DBG(WARNING, ("FM in guest-mode without IPC, can't validate firmware revision."));
+ revInfo.packageRev = IP_OFFLOAD_PACKAGE_NUMBER;
+ }
+ if (revInfo.packageRev != IP_OFFLOAD_PACKAGE_NUMBER)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Fman ctrl code package"));
+
+ if (!p_FmPcd->h_Hc)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("HC must be initialized in this mode"));
+
+ p_FmPcd->advancedOffloadSupport = TRUE;
+
+ return E_OK;
+}
+
+uint32_t FM_PCD_GetCounter(t_Handle h_FmPcd, e_FmPcdCounters counter)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t outCounter = 0;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE, 0);
+
+ switch (counter)
+ {
+ case (e_FM_PCD_KG_COUNTERS_TOTAL):
+ if (!p_FmPcd->p_FmPcdKg)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("KeyGen is not activated"));
+ return 0;
+ }
+ if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&
+ !p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs &&
+ !p_FmPcd->h_IpcSession)
+ {
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without neither IPC nor mapped register!"));
+ return 0;
+ }
+ break;
+
+ case (e_FM_PCD_PLCR_COUNTERS_YELLOW):
+ case (e_FM_PCD_PLCR_COUNTERS_RED):
+ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED):
+ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW):
+ case (e_FM_PCD_PLCR_COUNTERS_TOTAL):
+ case (e_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH):
+ if (!p_FmPcd->p_FmPcdPlcr)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Policer is not activated"));
+ return 0;
+ }
+ if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&
+ !p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs &&
+ !p_FmPcd->h_IpcSession)
+ {
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in \"guest-mode\" without neither IPC nor mapped register!"));
+ return 0;
+ }
+
+ /* check that counters are enabled */
+ if (p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs &&
+ !(GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_gcr) & FM_PCD_PLCR_GCR_STEN))
+ {
+ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled"));
+ return 0;
+ }
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs ||
+ ((p_FmPcd->guestId != NCSW_MASTER_ID) && p_FmPcd->h_IpcSession));
+ break;
+
+ case (e_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH):
+ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED):
+ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED):
+ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED):
+ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED):
+ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR):
+ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR):
+ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR):
+ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR):
+ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES):
+ if (!p_FmPcd->p_FmPcdPrs)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Parser is not activated"));
+ return 0;
+ }
+ if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&
+ !p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs &&
+ !p_FmPcd->h_IpcSession)
+ {
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without neither IPC nor mapped register!"));
+ return 0;
+ }
+ break;
+ default:
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported type of counter"));
+ return 0;
+ }
+
+ if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&
+ p_FmPcd->h_IpcSession)
+ {
+ t_FmPcdIpcMsg msg;
+ t_FmPcdIpcReply reply;
+ uint32_t replyLength;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_PCD_GET_COUNTER;
+ memcpy(msg.msgBody, (uint8_t *)&counter, sizeof(uint32_t));
+ replyLength = sizeof(uint32_t) + sizeof(uint32_t);
+ if ((err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) +sizeof(uint32_t),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t) + sizeof(uint32_t))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+
+ memcpy((uint8_t*)&outCounter, reply.replyBody, sizeof(uint32_t));
+ return outCounter;
+ }
+
+ switch (counter)
+ {
+ /* Parser statistics */
+ case (e_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_pds);
+ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l2rrs);
+ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l3rrs);
+ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l4rrs);
+ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_srrs);
+ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l2rres);
+ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l3rres);
+ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l4rres);
+ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_srres);
+ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_spcs);
+ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_spscs);
+ case (e_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_hxscs);
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mrcs);
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mrscs);
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mwcs);
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mwscs);
+ case (e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES):
+ return GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_fcscs);
+ case (e_FM_PCD_KG_COUNTERS_TOTAL):
+ return GET_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_tpc);
+
+ /* Policer statistics */
+ case (e_FM_PCD_PLCR_COUNTERS_YELLOW):
+ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ypcnt);
+ case (e_FM_PCD_PLCR_COUNTERS_RED):
+ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rpcnt);
+ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED):
+ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rrpcnt);
+ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW):
+ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rypcnt);
+ case (e_FM_PCD_PLCR_COUNTERS_TOTAL):
+ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_tpcnt);
+ case (e_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH):
+ return GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_flmcnt);
+
+ default:
+ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Unsupported type of counter"));
+ return 0;
+ }
+}
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+t_Error FM_PCD_DumpRegs(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_Error err = E_OK;
+
+ DECLARE_DUMP;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+
+ if (p_FmPcd->p_FmPcdKg)
+ err |= FM_PCD_KgDumpRegs(h_FmPcd);
+ if (p_FmPcd->p_FmPcdPlcr)
+ err |= FM_PCD_PlcrDumpRegs(h_FmPcd);
+ if (p_FmPcd->p_FmPcdPrs)
+ err |= FM_PCD_PrsDumpRegs(h_FmPcd);
+
+ return err;
+}
+
+t_Error FM_PCD_HcDumpRegs(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ DECLARE_DUMP;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->h_Hc, E_INVALID_STATE);
+
+ return FmHcDumpRegs(p_FmPcd->h_Hc);
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+t_Error FM_PCD_SetException(t_Handle h_FmPcd, e_FmPcdExceptions exception, bool enable)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t bitMask = 0, tmpReg;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+
+ if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_SetException - guest mode!"));
+
+ GET_FM_PCD_EXCEPTION_FLAG(bitMask, exception);
+
+ if (bitMask)
+ {
+ if (enable)
+ p_FmPcd->exceptions |= bitMask;
+ else
+ p_FmPcd->exceptions &= ~bitMask;
+
+ switch (exception)
+ {
+ case (e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC):
+ case (e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW):
+ if (!p_FmPcd->p_FmPcdKg)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt - keygen is not working"));
+ break;
+ case (e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC):
+ case (e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR):
+ case (e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE):
+ case (e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE):
+ if (!p_FmPcd->p_FmPcdPlcr)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt - policer is not working"));
+ break;
+ case (e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC):
+ case (e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC):
+ if (!p_FmPcd->p_FmPcdPrs)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt - parser is not working"));
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Unsupported exception"));
+
+ }
+
+ switch (exception)
+ {
+ case (e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC):
+ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_eeer);
+ if (enable)
+ tmpReg |= FM_EX_KG_DOUBLE_ECC;
+ else
+ tmpReg &= ~FM_EX_KG_DOUBLE_ECC;
+ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_eeer, tmpReg);
+ break;
+ case (e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW):
+ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_eeer);
+ if (enable)
+ tmpReg |= FM_EX_KG_KEYSIZE_OVERFLOW;
+ else
+ tmpReg &= ~FM_EX_KG_KEYSIZE_OVERFLOW;
+ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_eeer, tmpReg);
+ break;
+ case (e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC):
+ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_perer);
+ if (enable)
+ tmpReg |= FM_PCD_PRS_DOUBLE_ECC;
+ else
+ tmpReg &= ~FM_PCD_PRS_DOUBLE_ECC;
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_perer, tmpReg);
+ break;
+ case (e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC):
+ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_pever);
+ if (enable)
+ tmpReg |= FM_PCD_PRS_SINGLE_ECC;
+ else
+ tmpReg &= ~FM_PCD_PRS_SINGLE_ECC;
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_pever, tmpReg);
+ break;
+ case (e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC):
+ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eier);
+ if (enable)
+ tmpReg |= FM_PCD_PLCR_DOUBLE_ECC;
+ else
+ tmpReg &= ~FM_PCD_PLCR_DOUBLE_ECC;
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eier, tmpReg);
+ break;
+ case (e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR):
+ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eier);
+ if (enable)
+ tmpReg |= FM_PCD_PLCR_INIT_ENTRY_ERROR;
+ else
+ tmpReg &= ~FM_PCD_PLCR_INIT_ENTRY_ERROR;
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eier, tmpReg);
+ break;
+ case (e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE):
+ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ier);
+ if (enable)
+ tmpReg |= FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE;
+ else
+ tmpReg &= ~FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE;
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ier, tmpReg);
+ break;
+ case (e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE):
+ tmpReg = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ier);
+ if (enable)
+ tmpReg |= FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE;
+ else
+ tmpReg &= ~FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE;
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ier, tmpReg);
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Unsupported exception"));
+ }
+ /* for ECC exceptions driver automatically enables ECC mechanism, if disabled.
+ Driver may disable them automatically, depending on driver's status */
+ if (enable && ( (exception == e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC) |
+ (exception == e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC) |
+ (exception == e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC) |
+ (exception == e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC)))
+ FmEnableRamsEcc(p_FmPcd->h_Fm);
+ if (!enable && ( (exception == e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC) |
+ (exception == e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC) |
+ (exception == e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC) |
+ (exception == e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC)))
+ FmDisableRamsEcc(p_FmPcd->h_Fm);
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
+
+ return E_OK;
+}
+
+t_Error FM_PCD_ForceIntr (t_Handle h_FmPcd, e_FmPcdExceptions exception)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+
+ if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ForceIntr - guest mode!"));
+
+ switch (exception)
+ {
+ case (e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC):
+ case (e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW):
+ if (!p_FmPcd->p_FmPcdKg)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt - keygen is not working"));
+ break;
+ case (e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC):
+ case (e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR):
+ case (e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE):
+ case (e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE):
+ if (!p_FmPcd->p_FmPcdPlcr)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt - policer is not working"));
+ break;
+ case (e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC):
+ case (e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC):
+ if (!p_FmPcd->p_FmPcdPrs)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Can't ask for this interrupt -parsrer is not working"));
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Invalid interrupt requested"));
+
+ }
+ switch (exception)
+ {
+ case e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC:
+ if (!(p_FmPcd->exceptions & FM_PCD_EX_PRS_DOUBLE_ECC))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ break;
+ case e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC:
+ if (!(p_FmPcd->exceptions & FM_PCD_EX_PRS_SINGLE_ECC))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ break;
+ case e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC:
+ if (!(p_FmPcd->exceptions & FM_EX_KG_DOUBLE_ECC))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_feer, FM_EX_KG_DOUBLE_ECC);
+ break;
+ case e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW:
+ if (!(p_FmPcd->exceptions & FM_EX_KG_KEYSIZE_OVERFLOW))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_feer, FM_EX_KG_KEYSIZE_OVERFLOW);
+ break;
+ case e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC:
+ if (!(p_FmPcd->exceptions & FM_PCD_EX_PLCR_DOUBLE_ECC))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eifr, FM_PCD_PLCR_DOUBLE_ECC);
+ break;
+ case e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR:
+ if (!(p_FmPcd->exceptions & FM_PCD_EX_PLCR_INIT_ENTRY_ERROR))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eifr, FM_PCD_PLCR_INIT_ENTRY_ERROR);
+ break;
+ case e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE:
+ if (!(p_FmPcd->exceptions & FM_PCD_EX_PLCR_PRAM_SELF_INIT_COMPLETE))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ifr, FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE);
+ break;
+ case e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE:
+ if (!(p_FmPcd->exceptions & FM_PCD_EX_PLCR_ATOMIC_ACTION_COMPLETE))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ifr, FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE);
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception may not be forced"));
+ }
+
+ return E_OK;
+}
+
+
+t_Error FM_PCD_ModifyCounter(t_Handle h_FmPcd, e_FmPcdCounters counter, uint32_t value)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+
+ if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ModifyCounter - guest mode!"));
+
+ switch (counter)
+ {
+ case (e_FM_PCD_KG_COUNTERS_TOTAL):
+ if (!p_FmPcd->p_FmPcdKg)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Invalid counters - KeyGen is not working"));
+ break;
+ case (e_FM_PCD_PLCR_COUNTERS_YELLOW):
+ case (e_FM_PCD_PLCR_COUNTERS_RED):
+ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED):
+ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW):
+ case (e_FM_PCD_PLCR_COUNTERS_TOTAL):
+ case (e_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH):
+ if (!p_FmPcd->p_FmPcdPlcr)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Invalid counters - Policer is not working"));
+ if (!(GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_gcr) & FM_PCD_PLCR_GCR_STEN))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled"));
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH):
+ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED):
+ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED):
+ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED):
+ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED):
+ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR):
+ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR):
+ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR):
+ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR):
+ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES):
+ case (e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES):
+ if (!p_FmPcd->p_FmPcdPrs)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Unsupported type of counter"));
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Unsupported type of counter"));
+ }
+ switch (counter)
+ {
+ case (e_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_pds, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l2rrs, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l3rrs, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l4rrs, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_srrs, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l2rres, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l3rres, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_l4rres, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_srres, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_spcs, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_spscs, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_hxscs, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mrcs, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mrscs, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mwcs, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_mwscs, value);
+ break;
+ case (e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs->fmpr_fcscs, value);
+ break;
+ case (e_FM_PCD_KG_COUNTERS_TOTAL):
+ WRITE_UINT32(p_FmPcd->p_FmPcdKg->p_FmPcdKgRegs->fmkg_tpc,value);
+ break;
+
+ /*Policer counters*/
+ case (e_FM_PCD_PLCR_COUNTERS_YELLOW):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ypcnt, value);
+ break;
+ case (e_FM_PCD_PLCR_COUNTERS_RED):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rpcnt, value);
+ break;
+ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rrpcnt, value);
+ break;
+ case (e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_rypcnt, value);
+ break;
+ case (e_FM_PCD_PLCR_COUNTERS_TOTAL):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_tpcnt, value);
+ break;
+ case (e_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH):
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_flmcnt, value);
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Unsupported type of counter"));
+ }
+
+return E_OK;
+}
+
+
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd.h
new file mode 100644
index 0000000..ca0fb81
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd.h
@@ -0,0 +1,540 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_pcd.h
+
+ @Description FM PCD ...
+*//***************************************************************************/
+#ifndef __FM_PCD_H
+#define __FM_PCD_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "list_ext.h"
+#include "fm_pcd_ext.h"
+#include "fm_common.h"
+#include "fsl_fman_prs.h"
+#include "fsl_fman_kg.h"
+
+#define __ERR_MODULE__ MODULE_FM_PCD
+
+
+/****************************/
+/* Defaults */
+/****************************/
+#define DEFAULT_plcrAutoRefresh FALSE
+#define DEFAULT_fmPcdKgErrorExceptions (FM_EX_KG_DOUBLE_ECC | FM_EX_KG_KEYSIZE_OVERFLOW)
+#define DEFAULT_fmPcdPlcrErrorExceptions (FM_PCD_EX_PLCR_DOUBLE_ECC | FM_PCD_EX_PLCR_INIT_ENTRY_ERROR)
+#define DEFAULT_fmPcdPlcrExceptions 0
+#define DEFAULT_fmPcdPrsErrorExceptions (FM_PCD_EX_PRS_DOUBLE_ECC)
+
+#define DEFAULT_fmPcdPrsExceptions FM_PCD_EX_PRS_SINGLE_ECC
+#define DEFAULT_numOfUsedProfilesPerWindow 16
+#define DEFAULT_numOfSharedPlcrProfiles 4
+
+/****************************/
+/* Network defines */
+/****************************/
+#define UDP_HEADER_SIZE 8
+
+#define ESP_SPI_OFFSET 0
+#define ESP_SPI_SIZE 4
+#define ESP_SEQ_NUM_OFFSET ESP_SPI_SIZE
+#define ESP_SEQ_NUM_SIZE 4
+
+/****************************/
+/* General defines */
+/****************************/
+#define ILLEGAL_CLS_PLAN 0xff
+#define ILLEGAL_NETENV 0xff
+
+#define FM_PCD_MAX_NUM_OF_ALIAS_HDRS 3
+
+/****************************/
+/* Error defines */
+/****************************/
+
+#define FM_PCD_EX_PLCR_DOUBLE_ECC 0x20000000
+#define FM_PCD_EX_PLCR_INIT_ENTRY_ERROR 0x10000000
+#define FM_PCD_EX_PLCR_PRAM_SELF_INIT_COMPLETE 0x08000000
+#define FM_PCD_EX_PLCR_ATOMIC_ACTION_COMPLETE 0x04000000
+
+#define GET_FM_PCD_EXCEPTION_FLAG(bitMask, exception) \
+switch (exception){ \
+ case e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC: \
+ bitMask = FM_EX_KG_DOUBLE_ECC; break; \
+ case e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC: \
+ bitMask = FM_PCD_EX_PLCR_DOUBLE_ECC; break; \
+ case e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW: \
+ bitMask = FM_EX_KG_KEYSIZE_OVERFLOW; break; \
+ case e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR: \
+ bitMask = FM_PCD_EX_PLCR_INIT_ENTRY_ERROR; break; \
+ case e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE: \
+ bitMask = FM_PCD_EX_PLCR_PRAM_SELF_INIT_COMPLETE; break; \
+ case e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE: \
+ bitMask = FM_PCD_EX_PLCR_ATOMIC_ACTION_COMPLETE; break; \
+ case e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC: \
+ bitMask = FM_PCD_EX_PRS_DOUBLE_ECC; break; \
+ case e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC: \
+ bitMask = FM_PCD_EX_PRS_SINGLE_ECC; break; \
+ default: bitMask = 0;break;}
+
+/***********************************************************************/
+/* Policer defines */
+/***********************************************************************/
+#define FM_PCD_PLCR_GCR_STEN 0x40000000
+#define FM_PCD_PLCR_DOUBLE_ECC 0x80000000
+#define FM_PCD_PLCR_INIT_ENTRY_ERROR 0x40000000
+#define FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE 0x80000000
+#define FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE 0x40000000
+
+/***********************************************************************/
+/* Memory map */
+/***********************************************************************/
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+
+typedef _Packed struct {
+/* General Configuration and Status Registers */
+ volatile uint32_t fmpl_gcr; /* 0x000 FMPL_GCR - FM Policer General Configuration */
+ volatile uint32_t fmpl_gsr; /* 0x004 FMPL_GSR - FM Policer Global Status Register */
+ volatile uint32_t fmpl_evr; /* 0x008 FMPL_EVR - FM Policer Event Register */
+ volatile uint32_t fmpl_ier; /* 0x00C FMPL_IER - FM Policer Interrupt Enable Register */
+ volatile uint32_t fmpl_ifr; /* 0x010 FMPL_IFR - FM Policer Interrupt Force Register */
+ volatile uint32_t fmpl_eevr; /* 0x014 FMPL_EEVR - FM Policer Error Event Register */
+ volatile uint32_t fmpl_eier; /* 0x018 FMPL_EIER - FM Policer Error Interrupt Enable Register */
+ volatile uint32_t fmpl_eifr; /* 0x01C FMPL_EIFR - FM Policer Error Interrupt Force Register */
+/* Global Statistic Counters */
+ volatile uint32_t fmpl_rpcnt; /* 0x020 FMPL_RPC - FM Policer RED Packets Counter */
+ volatile uint32_t fmpl_ypcnt; /* 0x024 FMPL_YPC - FM Policer YELLOW Packets Counter */
+ volatile uint32_t fmpl_rrpcnt; /* 0x028 FMPL_RRPC - FM Policer Recolored RED Packet Counter */
+ volatile uint32_t fmpl_rypcnt; /* 0x02C FMPL_RYPC - FM Policer Recolored YELLOW Packet Counter */
+ volatile uint32_t fmpl_tpcnt; /* 0x030 FMPL_TPC - FM Policer Total Packet Counter */
+ volatile uint32_t fmpl_flmcnt; /* 0x034 FMPL_FLMC - FM Policer Frame Length Mismatch Counter */
+ volatile uint32_t fmpl_res0[21]; /* 0x038 - 0x08B Reserved */
+/* Profile RAM Access Registers */
+ volatile uint32_t fmpl_par; /* 0x08C FMPL_PAR - FM Policer Profile Action Register*/
+ t_FmPcdPlcrProfileRegs profileRegs;
+/* Error Capture Registers */
+ volatile uint32_t fmpl_serc; /* 0x100 FMPL_SERC - FM Policer Soft Error Capture */
+ volatile uint32_t fmpl_upcr; /* 0x104 FMPL_UPCR - FM Policer Uninitialized Profile Capture Register */
+ volatile uint32_t fmpl_res2; /* 0x108 Reserved */
+/* Debug Registers */
+ volatile uint32_t fmpl_res3[61]; /* 0x10C-0x200 Reserved Debug*/
+/* Profile Selection Mapping Registers Per Port-ID (n=1-11, 16) */
+ volatile uint32_t fmpl_dpmr; /* 0x200 FMPL_DPMR - FM Policer Default Mapping Register */
+ volatile uint32_t fmpl_pmr[63]; /*+default 0x204-0x2FF FMPL_PMR1 - FMPL_PMR63, - FM Policer Profile Mapping Registers.
+ (for port-ID 1-11, only for supported Port-ID registers) */
+} _PackedType t_FmPcdPlcrRegs;
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+/***********************************************************************/
+/* Driver's internal structures */
+/***********************************************************************/
+
+typedef struct {
+ bool known;
+ uint8_t id;
+} t_FmPcdKgSchemesExtractsEntry;
+
+typedef struct {
+ t_FmPcdKgSchemesExtractsEntry extractsArray[FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY];
+} t_FmPcdKgSchemesExtracts;
+
+typedef struct {
+ t_Handle h_Manip;
+ bool keepRes;
+ e_FmPcdEngine nextEngine;
+ uint8_t parseCode;
+} t_FmPcdInfoForManip;
+
+/**************************************************************************//**
+ @Description A structure of parameters to communicate
+ between the port and PCD regarding the KG scheme.
+*//***************************************************************************/
+typedef struct {
+ uint8_t netEnvId; /* in */
+ uint8_t numOfDistinctionUnits; /* in */
+ uint8_t unitIds[FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS]; /* in */
+ uint32_t vector; /* out */
+} t_NetEnvParams;
+
+typedef struct {
+ bool allocated;
+ uint8_t ownerId; /* guestId for KG in multi-partition only.
+ portId for PLCR in any environment */
+} t_FmPcdAllocMng;
+
+typedef struct {
+ volatile bool lock;
+ bool used;
+ uint8_t owners;
+ uint8_t netEnvId;
+ uint8_t guestId;
+ uint8_t baseEntry;
+ uint16_t sizeOfGrp;
+ protocolOpt_t optArray[FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)];
+} t_FmPcdKgClsPlanGrp;
+
+typedef struct {
+ t_Handle h_FmPcd;
+ uint8_t schemeId;
+ t_FmPcdLock *p_Lock;
+ bool valid;
+ uint8_t netEnvId;
+ uint8_t owners;
+ uint32_t matchVector;
+ uint32_t ccUnits;
+ bool nextRelativePlcrProfile;
+ uint16_t relativeProfileId;
+ uint16_t numOfProfiles;
+ t_FmPcdKgKeyOrder orderedArray;
+ e_FmPcdEngine nextEngine;
+ e_FmPcdDoneAction doneAction;
+ bool requiredActionFlag;
+ uint32_t requiredAction;
+ bool extractedOrs;
+ uint8_t bitOffsetInPlcrProfile;
+ bool directPlcr;
+#if (DPAA_VERSION >= 11)
+ bool vspe;
+#endif
+} t_FmPcdKgScheme;
+
+typedef _Packed union {
+ struct fman_kg_scheme_regs schemeRegs;
+ struct fman_kg_pe_regs portRegs;
+ struct fman_kg_cp_regs clsPlanRegs;
+} _PackedType u_FmPcdKgIndirectAccessRegs;
+
+typedef struct {
+ struct fman_kg_regs *p_FmPcdKgRegs;
+ uint32_t schemeExceptionsBitMask;
+ uint8_t numOfSchemes;
+ t_Handle h_HwSpinlock;
+ uint8_t schemesIds[FM_PCD_KG_NUM_OF_SCHEMES];
+ t_FmPcdKgScheme schemes[FM_PCD_KG_NUM_OF_SCHEMES];
+ t_FmPcdKgClsPlanGrp clsPlanGrps[FM_MAX_NUM_OF_PORTS];
+ uint8_t emptyClsPlanGrpId;
+ t_FmPcdAllocMng schemesMng[FM_PCD_KG_NUM_OF_SCHEMES]; /* only for MASTER ! */
+ t_FmPcdAllocMng clsPlanBlocksMng[FM_PCD_MAX_NUM_OF_CLS_PLANS/CLS_PLAN_NUM_PER_GRP];
+ u_FmPcdKgIndirectAccessRegs *p_IndirectAccessRegs;
+} t_FmPcdKg;
+
+typedef struct {
+ uint16_t profilesBase;
+ uint16_t numOfProfiles;
+ t_Handle h_FmPort;
+} t_FmPcdPlcrMapParam;
+
+typedef struct {
+ uint16_t absoluteProfileId;
+ t_Handle h_FmPcd;
+ bool valid;
+ t_FmPcdLock *p_Lock;
+ t_FmPcdAllocMng profilesMng;
+ bool requiredActionFlag;
+ uint32_t requiredAction;
+ e_FmPcdEngine nextEngineOnGreen; /**< Green next engine type */
+ u_FmPcdPlcrNextEngineParams paramsOnGreen; /**< Green next engine params */
+
+ e_FmPcdEngine nextEngineOnYellow; /**< Yellow next engine type */
+ u_FmPcdPlcrNextEngineParams paramsOnYellow; /**< Yellow next engine params */
+
+ e_FmPcdEngine nextEngineOnRed; /**< Red next engine type */
+ u_FmPcdPlcrNextEngineParams paramsOnRed; /**< Red next engine params */
+} t_FmPcdPlcrProfile;
+
+typedef struct {
+ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs;
+ uint16_t partPlcrProfilesBase;
+ uint16_t partNumOfPlcrProfiles;
+ t_FmPcdPlcrProfile profiles[FM_PCD_PLCR_NUM_ENTRIES];
+ uint16_t numOfSharedProfiles;
+ uint16_t sharedProfilesIds[FM_PCD_PLCR_NUM_ENTRIES];
+ t_FmPcdPlcrMapParam portsMapping[FM_MAX_NUM_OF_PORTS];
+ t_Handle h_HwSpinlock;
+ t_Handle h_SwSpinlock;
+} t_FmPcdPlcr;
+
+typedef struct {
+ uint32_t *p_SwPrsCode;
+ uint32_t *p_CurrSwPrs;
+ uint8_t currLabel;
+ struct fman_prs_regs *p_FmPcdPrsRegs;
+ t_FmPcdPrsLabelParams labelsTable[FM_PCD_PRS_NUM_OF_LABELS];
+ uint32_t fmPcdPrsPortIdStatistics;
+} t_FmPcdPrs;
+
+typedef struct {
+ struct {
+ e_NetHeaderType hdr;
+ protocolOpt_t opt; /* only one option !! */
+ } hdrs[FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS];
+} t_FmPcdIntDistinctionUnit;
+
+typedef struct {
+ e_NetHeaderType hdr;
+ protocolOpt_t opt; /* only one option !! */
+ e_NetHeaderType aliasHdr;
+} t_FmPcdNetEnvAliases;
+
+typedef struct {
+ uint8_t netEnvId;
+ t_Handle h_FmPcd;
+ t_Handle h_Spinlock;
+ bool used;
+ uint8_t owners;
+ uint8_t clsPlanGrpId;
+ t_FmPcdIntDistinctionUnit units[FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS];
+ uint32_t unitsVectors[FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS];
+ uint32_t lcvs[FM_PCD_PRS_NUM_OF_HDRS];
+ uint32_t macsecVector;
+ t_FmPcdNetEnvAliases aliasHdrs[FM_PCD_MAX_NUM_OF_ALIAS_HDRS];
+} t_FmPcdNetEnv;
+
+typedef struct {
+ struct fman_prs_cfg dfltCfg;
+ bool plcrAutoRefresh;
+ uint16_t prsMaxParseCycleLimit;
+} t_FmPcdDriverParam;
+
+typedef struct {
+ t_Handle h_Fm;
+ t_Handle h_FmMuram;
+ t_FmRevisionInfo fmRevInfo;
+
+ uint64_t physicalMuramBase;
+
+ t_Handle h_Spinlock;
+ t_List freeLocksLst;
+ t_List acquiredLocksLst;
+
+ t_Handle h_IpcSession; /* relevant for guest only */
+ bool enabled;
+ uint8_t guestId; /**< Guest Partition Id */
+ uint8_t numOfEnabledGuestPartitionsPcds;
+ char fmPcdModuleName[MODULE_NAME_SIZE];
+ char fmPcdIpcHandlerModuleName[MODULE_NAME_SIZE]; /* relevant for guest only - this is the master's name */
+ t_FmPcdNetEnv netEnvs[FM_MAX_NUM_OF_PORTS];
+ t_FmPcdKg *p_FmPcdKg;
+ t_FmPcdPlcr *p_FmPcdPlcr;
+ t_FmPcdPrs *p_FmPcdPrs;
+
+ void *p_CcShadow; /**< CC MURAM shadow */
+ uint32_t ccShadowSize;
+ uint32_t ccShadowAlign;
+ volatile bool shadowLock;
+ t_Handle h_ShadowSpinlock;
+
+ t_Handle h_Hc;
+
+ uint32_t exceptions;
+ t_FmPcdExceptionCallback *f_Exception;
+ t_FmPcdIdExceptionCallback *f_FmPcdIndexedException;
+ t_Handle h_App;
+ uintptr_t ipv6FrameIdAddr;
+ bool advancedOffloadSupport;
+
+ t_FmPcdDriverParam *p_FmPcdDriverParam;
+} t_FmPcd;
+
+#if (DPAA_VERSION >= 11)
+typedef uint8_t t_FmPcdFrmReplicUpdateType;
+#define FRM_REPLIC_UPDATE_COUNTER 0x01
+#define FRM_REPLIC_UPDATE_INFO 0x02
+#endif /* (DPAA_VERSION >= 11) */
+/***********************************************************************/
+/* PCD internal routines */
+/***********************************************************************/
+
+t_Error PcdGetVectorForOpt(t_FmPcd *p_FmPcd, uint8_t netEnvId, protocolOpt_t opt, uint32_t *p_Vector);
+t_Error PcdGetUnitsVector(t_FmPcd *p_FmPcd, t_NetEnvParams *p_Params);
+bool PcdNetEnvIsUnitWithoutOpts(t_FmPcd *p_FmPcd, uint8_t netEnvId, uint32_t unitVector);
+t_Error PcdGetClsPlanGrpParams(t_FmPcd *p_FmPcd, t_FmPcdKgInterModuleClsPlanGrpParams *p_GrpParams);
+void FmPcdSetClsPlanGrpId(t_FmPcd *p_FmPcd, uint8_t netEnvId, uint8_t clsPlanGrpId);
+e_NetHeaderType FmPcdGetAliasHdr(t_FmPcd *p_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr);
+uint8_t FmPcdNetEnvGetUnitIdForSingleHdr(t_FmPcd *p_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr);
+uint8_t FmPcdNetEnvGetUnitId(t_FmPcd *p_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr, bool interchangeable, protocolOpt_t opt);
+
+t_Error FmPcdManipBuildIpReassmScheme(t_FmPcd *p_FmPcd, t_Handle h_NetEnv, t_Handle h_CcTree, t_Handle h_Manip, bool isIpv4, uint8_t groupId);
+t_Error FmPcdManipDeleteIpReassmSchemes(t_Handle h_Manip);
+bool FmPcdManipIpReassmIsIpv6Hdr(t_Handle h_Manip);
+
+t_Handle KgConfig( t_FmPcd *p_FmPcd, t_FmPcdParams *p_FmPcdParams);
+t_Error KgInit(t_FmPcd *p_FmPcd);
+t_Error KgFree(t_FmPcd *p_FmPcd);
+void KgSetClsPlan(t_Handle h_FmPcd, t_FmPcdKgInterModuleClsPlanSet *p_Set);
+bool KgIsSchemeAlwaysDirect(t_Handle h_FmPcd, uint8_t schemeId);
+void KgEnable(t_FmPcd *p_FmPcd);
+void KgDisable(t_FmPcd *p_FmPcd);
+t_Error KgAllocClsPlanEntries(t_Handle h_FmPcd, uint16_t numOfClsPlanEntries, uint8_t guestId, uint8_t *p_First);
+void KgFreeClsPlanEntries(t_Handle h_FmPcd, uint16_t numOfClsPlanEntries, uint8_t guestId, uint8_t base);
+
+/* only for MULTI partittion */
+t_Error FmPcdKgAllocSchemes(t_Handle h_FmPcd, uint8_t numOfSchemes, uint8_t guestId, uint8_t *p_SchemesIds);
+t_Error FmPcdKgFreeSchemes(t_Handle h_FmPcd, uint8_t numOfSchemes, uint8_t guestId, uint8_t *p_SchemesIds);
+/* only for SINGLE partittion */
+t_Error KgBindPortToSchemes(t_Handle h_FmPcd , uint8_t hardwarePortId, uint32_t spReg);
+
+t_FmPcdLock *FmPcdAcquireLock(t_Handle h_FmPcd);
+void FmPcdReleaseLock(t_Handle h_FmPcd, t_FmPcdLock *p_Lock);
+
+t_Handle PlcrConfig(t_FmPcd *p_FmPcd, t_FmPcdParams *p_FmPcdParams);
+t_Error PlcrInit(t_FmPcd *p_FmPcd);
+t_Error PlcrFree(t_FmPcd *p_FmPcd);
+void PlcrEnable(t_FmPcd *p_FmPcd);
+void PlcrDisable(t_FmPcd *p_FmPcd);
+uint16_t PlcrAllocProfilesForPartition(t_FmPcd *p_FmPcd, uint16_t base, uint16_t numOfProfiles, uint8_t guestId);
+void PlcrFreeProfilesForPartition(t_FmPcd *p_FmPcd, uint16_t base, uint16_t numOfProfiles, uint8_t guestId);
+t_Error PlcrSetPortProfiles(t_FmPcd *p_FmPcd,
+ uint8_t hardwarePortId,
+ uint16_t numOfProfiles,
+ uint16_t base);
+t_Error PlcrClearPortProfiles(t_FmPcd *p_FmPcd, uint8_t hardwarePortId);
+
+t_Handle PrsConfig(t_FmPcd *p_FmPcd,t_FmPcdParams *p_FmPcdParams);
+t_Error PrsInit(t_FmPcd *p_FmPcd);
+void PrsEnable(t_FmPcd *p_FmPcd);
+void PrsDisable(t_FmPcd *p_FmPcd);
+void PrsFree(t_FmPcd *p_FmPcd );
+t_Error PrsIncludePortInStatistics(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, bool include);
+
+t_Error FmPcdCcGetGrpParams(t_Handle treeId, uint8_t grpId, uint32_t *p_GrpBits, uint8_t *p_GrpBase);
+uint8_t FmPcdCcGetOffset(t_Handle h_CcNode);
+uint8_t FmPcdCcGetParseCode(t_Handle h_CcNode);
+uint16_t FmPcdCcGetNumOfKeys(t_Handle h_CcNode);
+t_Error ValidateNextEngineParams(t_Handle h_FmPcd, t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams, e_FmPcdCcStatsMode supportedStatsMode);
+
+void FmPcdManipUpdateOwner(t_Handle h_Manip, bool add);
+t_Error FmPcdManipCheckParamsForCcNextEngine(t_FmPcdCcNextEngineParams *p_InfoForManip, uint32_t *requiredAction);
+void FmPcdManipUpdateAdResultForCc(t_Handle h_Manip,
+ t_FmPcdCcNextEngineParams *p_CcNextEngineParams,
+ t_Handle p_Ad,
+ t_Handle *p_AdNewPtr);
+void FmPcdManipUpdateAdContLookupForCc(t_Handle h_Manip, t_Handle p_Ad, t_Handle *p_AdNew, uint32_t adTableOffset);
+void FmPcdManipUpdateOwner(t_Handle h_Manip, bool add);
+t_Error FmPcdManipCheckParamsWithCcNodeParams(t_Handle h_Manip, t_Handle h_FmPcdCcNode);
+#ifdef FM_CAPWAP_SUPPORT
+t_Handle FmPcdManipApplSpecificBuild(void);
+bool FmPcdManipIsCapwapApplSpecific(t_Handle h_Manip);
+#endif /* FM_CAPWAP_SUPPORT */
+#if (DPAA_VERSION >= 11)
+void * FrmReplicGroupGetSourceTableDescriptor(t_Handle h_ReplicGroup);
+void FrmReplicGroupUpdateOwner(t_Handle h_ReplicGroup, bool add);
+void FrmReplicGroupUpdateAd(t_Handle h_ReplicGroup, void *p_Ad, t_Handle *h_AdNew);
+
+void FmPcdCcGetAdTablesThatPointOnReplicGroup(t_Handle h_Node,
+ t_Handle h_ReplicGroup,
+ t_List *p_AdTables,
+ uint32_t *p_NumOfAdTables);
+#endif /* (DPAA_VERSION >= 11) */
+
+void EnqueueNodeInfoToRelevantLst(t_List *p_List, t_CcNodeInformation *p_CcInfo, t_Handle h_Spinlock);
+void DequeueNodeInfoFromRelevantLst(t_List *p_List, t_Handle h_Info, t_Handle h_Spinlock);
+t_CcNodeInformation* FindNodeInfoInReleventLst(t_List *p_List, t_Handle h_Info, t_Handle h_Spinlock);
+t_List *FmPcdManipGetSpinlock(t_Handle h_Manip);
+t_List *FmPcdManipGetNodeLstPointedOnThisManip(t_Handle h_Manip);
+
+typedef struct
+{
+ t_Handle h_StatsAd;
+ t_Handle h_StatsCounters;
+#if (DPAA_VERSION >= 11)
+ t_Handle h_StatsFLRs;
+#endif /* (DPAA_VERSION >= 11) */
+} t_FmPcdCcStatsParams;
+
+void NextStepAd(t_Handle h_Ad,
+ t_FmPcdCcStatsParams *p_FmPcdCcStatsParams,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams,
+ t_FmPcd *p_FmPcd);
+void ReleaseLst(t_List *p_List);
+
+static __inline__ t_Handle FmPcdGetMuramHandle(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ ASSERT_COND(p_FmPcd);
+ return p_FmPcd->h_FmMuram;
+}
+
+static __inline__ uint64_t FmPcdGetMuramPhysBase(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ ASSERT_COND(p_FmPcd);
+ return p_FmPcd->physicalMuramBase;
+}
+
+static __inline__ uint32_t FmPcdLockSpinlock(t_FmPcdLock *p_Lock)
+{
+ ASSERT_COND(p_Lock);
+ return XX_LockIntrSpinlock(p_Lock->h_Spinlock);
+}
+
+static __inline__ void FmPcdUnlockSpinlock(t_FmPcdLock *p_Lock, uint32_t flags)
+{
+ ASSERT_COND(p_Lock);
+ XX_UnlockIntrSpinlock(p_Lock->h_Spinlock, flags);
+}
+
+static __inline__ bool FmPcdLockTryLock(t_FmPcdLock *p_Lock)
+{
+ uint32_t intFlags;
+
+ ASSERT_COND(p_Lock);
+ intFlags = XX_LockIntrSpinlock(p_Lock->h_Spinlock);
+ if (p_Lock->flag)
+ {
+ XX_UnlockIntrSpinlock(p_Lock->h_Spinlock, intFlags);
+ return FALSE;
+ }
+ p_Lock->flag = TRUE;
+ XX_UnlockIntrSpinlock(p_Lock->h_Spinlock, intFlags);
+ return TRUE;
+}
+
+static __inline__ void FmPcdLockUnlock(t_FmPcdLock *p_Lock)
+{
+ ASSERT_COND(p_Lock);
+ p_Lock->flag = FALSE;
+}
+
+
+#endif /* __FM_PCD_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd_ipc.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd_ipc.h
new file mode 100644
index 0000000..325d3e3
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd_ipc.h
@@ -0,0 +1,280 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File fm_pcd_ipc.h
+
+ @Description FM PCD Inter-Partition prototypes, structures and definitions.
+*//***************************************************************************/
+#ifndef __FM_PCD_IPC_H
+#define __FM_PCD_IPC_H
+
+#include "std_ext.h"
+
+
+/**************************************************************************//**
+ @Group FM_grp Frame Manager API
+
+ @Description FM API functions, definitions and enums
+
+ @{
+*//***************************************************************************/
+
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+/**************************************************************************//**
+ @Description Structure for getting a sw parser address according to a label
+ Fields commented 'IN' are passed by the port module to be used
+ by the FM module.
+ Fields commented 'OUT' will be filled by FM before returning to port.
+*//***************************************************************************/
+typedef _Packed struct t_FmPcdIpcSwPrsLable
+{
+ uint32_t enumHdr; /**< IN. The existence of this header will invoke
+ the sw parser code. */
+ uint8_t indexPerHdr; /**< IN. Normally 0, if more than one sw parser
+ attachments for the same header, use this
+
+ index to distinguish between them. */
+} _PackedType t_FmPcdIpcSwPrsLable;
+
+/**************************************************************************//**
+ @Description Structure for port-PCD communication.
+ Fields commented 'IN' are passed by the port module to be used
+ by the FM module.
+ Fields commented 'OUT' will be filled by FM before returning to port.
+ Some fields are optional (depending on configuration) and
+ will be analized by the port and FM modules accordingly.
+*//***************************************************************************/
+
+typedef struct t_FmPcdIpcKgSchemesParams
+{
+ uint8_t guestId;
+ uint8_t numOfSchemes;
+ uint8_t schemesIds[FM_PCD_KG_NUM_OF_SCHEMES];
+} _PackedType t_FmPcdIpcKgSchemesParams;
+
+typedef struct t_FmPcdIpcKgClsPlanParams
+{
+ uint8_t guestId;
+ uint16_t numOfClsPlanEntries;
+ uint8_t clsPlanBase;
+} _PackedType t_FmPcdIpcKgClsPlanParams;
+
+typedef _Packed struct t_FmPcdIpcPrsIncludePort
+{
+ uint8_t hardwarePortId;
+ bool include;
+} _PackedType t_FmPcdIpcPrsIncludePort;
+
+
+#define FM_PCD_MAX_REPLY_SIZE 16
+#define FM_PCD_MAX_MSG_SIZE 36
+#define FM_PCD_MAX_REPLY_BODY_SIZE 36
+
+typedef _Packed struct {
+ uint32_t msgId;
+ uint8_t msgBody[FM_PCD_MAX_MSG_SIZE];
+} _PackedType t_FmPcdIpcMsg;
+
+typedef _Packed struct t_FmPcdIpcReply {
+ uint32_t error;
+ uint8_t replyBody[FM_PCD_MAX_REPLY_BODY_SIZE];
+} _PackedType t_FmPcdIpcReply;
+
+typedef _Packed struct t_FmIpcResourceAllocParams {
+ uint8_t guestId;
+ uint16_t base;
+ uint16_t num;
+}_PackedType t_FmIpcResourceAllocParams;
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+
+/**************************************************************************//**
+ @Function FM_PCD_ALLOC_KG_SCHEMES
+
+ @Description Used by FM PCD front-end in order to allocate KG resources
+
+ @Param[in/out] t_FmPcdIpcKgAllocParams Pointer
+*//***************************************************************************/
+#define FM_PCD_ALLOC_KG_SCHEMES 3
+
+/**************************************************************************//**
+ @Function FM_PCD_FREE_KG_SCHEMES
+
+ @Description Used by FM PCD front-end in order to Free KG resources
+
+ @Param[in/out] t_FmPcdIpcKgSchemesParams Pointer
+*//***************************************************************************/
+#define FM_PCD_FREE_KG_SCHEMES 4
+
+/**************************************************************************//**
+ @Function FM_PCD_ALLOC_PROFILES
+
+ @Description Used by FM PCD front-end in order to allocate Policer profiles
+
+ @Param[in/out] t_FmIpcResourceAllocParams Pointer
+*//***************************************************************************/
+#define FM_PCD_ALLOC_PROFILES 5
+
+/**************************************************************************//**
+ @Function FM_PCD_FREE_PROFILES
+
+ @Description Used by FM PCD front-end in order to Free Policer profiles
+
+ @Param[in/out] t_FmIpcResourceAllocParams Pointer
+*//***************************************************************************/
+#define FM_PCD_FREE_PROFILES 6
+
+/**************************************************************************//**
+ @Function FM_PCD_SET_PORT_PROFILES
+
+ @Description Used by FM PCD front-end in order to allocate Policer profiles
+ for specific port
+
+ @Param[in/out] t_FmIpcResourceAllocParams Pointer
+*//***************************************************************************/
+#define FM_PCD_SET_PORT_PROFILES 7
+
+/**************************************************************************//**
+ @Function FM_PCD_CLEAR_PORT_PROFILES
+
+ @Description Used by FM PCD front-end in order to allocate Policer profiles
+ for specific port
+
+ @Param[in/out] t_FmIpcResourceAllocParams Pointer
+*//***************************************************************************/
+#define FM_PCD_CLEAR_PORT_PROFILES 8
+
+/**************************************************************************//**
+ @Function FM_PCD_GET_PHYS_MURAM_BASE
+
+ @Description Used by FM PCD front-end in order to get MURAM base address
+
+ @Param[in/out] t_FmPcdIcPhysAddr Pointer
+*//***************************************************************************/
+#define FM_PCD_GET_PHYS_MURAM_BASE 9
+
+/**************************************************************************//**
+ @Function FM_PCD_GET_SW_PRS_OFFSET
+
+ @Description Used by FM front-end to get the SW parser offset of the start of
+ code relevant to a given label.
+
+ @Param[in/out] t_FmPcdIpcSwPrsLable Pointer
+*//***************************************************************************/
+#define FM_PCD_GET_SW_PRS_OFFSET 10
+
+/**************************************************************************//**
+ @Function FM_PCD_MASTER_IS_ENABLED
+
+ @Description Used by FM front-end in order to verify
+ PCD enablement.
+
+ @Param[in] bool Pointer
+*//***************************************************************************/
+#define FM_PCD_MASTER_IS_ENABLED 15
+
+/**************************************************************************//**
+ @Function FM_PCD_GUEST_DISABLE
+
+ @Description Used by FM front-end to inform back-end when
+ front-end PCD is disabled
+
+ @Param[in] None
+*//***************************************************************************/
+#define FM_PCD_GUEST_DISABLE 16
+
+/**************************************************************************//**
+ @Function FM_PCD_FREE_KG_CLSPLAN
+
+ @Description Used by FM PCD front-end in order to Free KG classification plan entries
+
+ @Param[in/out] t_FmPcdIpcKgClsPlanParams Pointer
+*//***************************************************************************/
+#define FM_PCD_FREE_KG_CLSPLAN 22
+
+/**************************************************************************//**
+ @Function FM_PCD_ALLOC_KG_CLSPLAN
+
+ @Description Used by FM PCD front-end in order to allocate KG classification plan entries
+
+ @Param[in/out] t_FmPcdIpcKgClsPlanParams Pointer
+*//***************************************************************************/
+#define FM_PCD_ALLOC_KG_CLSPLAN 23
+
+/**************************************************************************//**
+ @Function FM_PCD_MASTER_IS_ALIVE
+
+ @Description Used by FM front-end to check that back-end exists
+
+ @Param[in] None
+*//***************************************************************************/
+#define FM_PCD_MASTER_IS_ALIVE 24
+
+/**************************************************************************//**
+ @Function FM_PCD_GET_COUNTER
+
+ @Description Used by FM front-end to read PCD counters
+
+ @Param[in/out] t_FmPcdIpcGetCounter Pointer
+*//***************************************************************************/
+#define FM_PCD_GET_COUNTER 25
+
+/**************************************************************************//**
+ @Function FM_PCD_PRS_INC_PORT_STATS
+
+ @Description Used by FM front-end to set/clear statistics for port
+
+ @Param[in/out] t_FmPcdIpcPrsIncludePort Pointer
+*//***************************************************************************/
+#define FM_PCD_PRS_INC_PORT_STATS 26
+
+#if (DPAA_VERSION >= 11)
+/* TODO - doc */
+#define FM_PCD_ALLOC_SP 27
+#endif /* (DPAA_VERSION >= 11) */
+
+
+/** @} */ /* end of FM_PCD_IPC_grp group */
+/** @} */ /* end of FM_grp group */
+
+
+#endif /* __FM_PCD_IPC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_plcr.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_plcr.c
new file mode 100644
index 0000000..e4eeddc
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_plcr.c
@@ -0,0 +1,1937 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_plcr.c
+
+ @Description FM PCD POLICER...
+*//***************************************************************************/
+#include "std_ext.h"
+#include "error_ext.h"
+#include "string_ext.h"
+#include "debug_ext.h"
+#include "net_ext.h"
+#include "fm_ext.h"
+
+#include "fm_common.h"
+#include "fm_pcd.h"
+#include "fm_hc.h"
+#include "fm_pcd_ipc.h"
+#include "fm_plcr.h"
+
+
+/****************************************/
+/* static functions */
+/****************************************/
+
+static uint32_t PlcrProfileLock(t_Handle h_Profile)
+{
+ ASSERT_COND(h_Profile);
+ return FmPcdLockSpinlock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock);
+}
+
+static void PlcrProfileUnlock(t_Handle h_Profile, uint32_t intFlags)
+{
+ ASSERT_COND(h_Profile);
+ FmPcdUnlockSpinlock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock, intFlags);
+}
+
+static bool PlcrProfileFlagTryLock(t_Handle h_Profile)
+{
+ ASSERT_COND(h_Profile);
+ return FmPcdLockTryLock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock);
+}
+
+static void PlcrProfileFlagUnlock(t_Handle h_Profile)
+{
+ ASSERT_COND(h_Profile);
+ FmPcdLockUnlock(((t_FmPcdPlcrProfile *)h_Profile)->p_Lock);
+}
+
+static uint32_t PlcrHwLock(t_Handle h_FmPcdPlcr)
+{
+ ASSERT_COND(h_FmPcdPlcr);
+ return XX_LockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_HwSpinlock);
+}
+
+static void PlcrHwUnlock(t_Handle h_FmPcdPlcr, uint32_t intFlags)
+{
+ ASSERT_COND(h_FmPcdPlcr);
+ XX_UnlockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_HwSpinlock, intFlags);
+}
+
+static uint32_t PlcrSwLock(t_Handle h_FmPcdPlcr)
+{
+ ASSERT_COND(h_FmPcdPlcr);
+ return XX_LockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_SwSpinlock);
+}
+
+static void PlcrSwUnlock(t_Handle h_FmPcdPlcr, uint32_t intFlags)
+{
+ ASSERT_COND(h_FmPcdPlcr);
+ XX_UnlockIntrSpinlock(((t_FmPcdPlcr*)h_FmPcdPlcr)->h_SwSpinlock, intFlags);
+}
+
+static bool IsProfileShared(t_Handle h_FmPcd, uint16_t absoluteProfileId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint16_t i;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, FALSE);
+
+ for (i=0;i<p_FmPcd->p_FmPcdPlcr->numOfSharedProfiles;i++)
+ if (p_FmPcd->p_FmPcdPlcr->sharedProfilesIds[i] == absoluteProfileId)
+ return TRUE;
+ return FALSE;
+}
+
+static t_Error SetProfileNia(t_FmPcd *p_FmPcd, e_FmPcdEngine nextEngine, u_FmPcdPlcrNextEngineParams *p_NextEngineParams, uint32_t *nextAction)
+{
+ uint32_t nia;
+ uint16_t absoluteProfileId;
+ uint8_t relativeSchemeId, physicalSchemeId;
+
+ nia = FM_PCD_PLCR_NIA_VALID;
+
+ switch (nextEngine)
+ {
+ case e_FM_PCD_DONE :
+ switch (p_NextEngineParams->action)
+ {
+ case e_FM_PCD_DROP_FRAME :
+ nia |= GET_NIA_BMI_AC_DISCARD_FRAME(p_FmPcd);
+ break;
+ case e_FM_PCD_ENQ_FRAME:
+ nia |= GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd);
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+ break;
+ case e_FM_PCD_KG:
+ physicalSchemeId = FmPcdKgGetSchemeId(p_NextEngineParams->h_DirectScheme);
+ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPcd, physicalSchemeId);
+ if (relativeSchemeId >= FM_PCD_KG_NUM_OF_SCHEMES)
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, NO_MSG);
+ if (!FmPcdKgIsSchemeValidSw(p_NextEngineParams->h_DirectScheme))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid direct scheme."));
+ if (!KgIsSchemeAlwaysDirect(p_FmPcd, relativeSchemeId))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Policer Profile may point only to a scheme that is always direct."));
+ nia |= NIA_ENG_KG | NIA_KG_DIRECT | physicalSchemeId;
+ break;
+ case e_FM_PCD_PLCR:
+ absoluteProfileId = ((t_FmPcdPlcrProfile *)p_NextEngineParams->h_Profile)->absoluteProfileId;
+ if (!IsProfileShared(p_FmPcd, absoluteProfileId))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next profile must be a shared profile"));
+ if (!FmPcdPlcrIsProfileValid(p_FmPcd, absoluteProfileId))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid profile "));
+ nia |= NIA_ENG_PLCR | NIA_PLCR_ABSOLUTE | absoluteProfileId;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+
+ *nextAction = nia;
+
+ return E_OK;
+}
+
+static uint32_t CalcFPP(uint32_t fpp)
+{
+ if (fpp > 15)
+ return 15 - (0x1f - fpp);
+ else
+ return 16 + fpp;
+}
+
+static void GetInfoRateReg(e_FmPcdPlcrRateMode rateMode,
+ uint32_t rate,
+ uint64_t tsuInTenthNano,
+ uint32_t fppShift,
+ uint64_t *p_Integer,
+ uint64_t *p_Fraction)
+{
+ uint64_t tmp, div;
+
+ if (rateMode == e_FM_PCD_PLCR_BYTE_MODE)
+ {
+ /* now we calculate the initial integer for the bigger rate */
+ /* from Kbps to Bytes/TSU */
+ tmp = (uint64_t)rate;
+ tmp *= 1000; /* kb --> b */
+ tmp *= tsuInTenthNano; /* bps --> bpTsu(in 10nano) */
+
+ div = 1000000000; /* nano */
+ div *= 10; /* 10 nano */
+ div *= 8; /* bit to byte */
+ }
+ else
+ {
+ /* now we calculate the initial integer for the bigger rate */
+ /* from Kbps to Bytes/TSU */
+ tmp = (uint64_t)rate;
+ tmp *= tsuInTenthNano; /* bps --> bpTsu(in 10nano) */
+
+ div = 1000000000; /* nano */
+ div *= 10; /* 10 nano */
+ }
+ *p_Integer = (tmp<<fppShift)/div;
+
+ /* for calculating the fraction, we will recalculate cir and deduct the integer.
+ * For precision, we will multiply by 2^16. we do not divid back, since we write
+ * this value as fraction - see spec.
+ */
+ *p_Fraction = (((tmp<<fppShift)<<16) - ((*p_Integer<<16)*div))/div;
+}
+
+/* .......... */
+
+static void CalcRates(t_Handle h_FmPcd,
+ t_FmPcdPlcrNonPassthroughAlgParams *p_NonPassthroughAlgParam,
+ uint32_t *cir,
+ uint32_t *cbs,
+ uint32_t *pir_eir,
+ uint32_t *pbs_ebs,
+ uint32_t *fpp)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint64_t integer, fraction;
+ uint32_t temp, tsuInTenthNanos, bitFor1Micro;
+ uint8_t fppShift=0;
+
+ bitFor1Micro = FmGetTimeStampScale(p_FmPcd->h_Fm); /* TimeStamp per nano seconds units */
+ /* we want the tsu to count 10 nano for better precision normally tsu is 3.9 nano, now we will get 39 */
+ tsuInTenthNanos = (uint32_t)(1000*10/(1<<bitFor1Micro));
+
+ /* we choose the faster rate to calibrate fpp */
+ /* The meaning of this step:
+ * when fppShift is 0 it means all TS bits are treated as integer and TSU is the TS LSB count.
+ * In this configuration we calculate the integer and fraction that represent the higher infoRate
+ * When this is done, we can tell where we have "spare" unused bits and optimize the division of TS
+ * into "integer" and "fraction" where the logic is - as many bits as possible for integer at
+ * high rate, as many bits as possible for fraction at low rate.
+ */
+ if (p_NonPassthroughAlgParam->comittedInfoRate > p_NonPassthroughAlgParam->peakOrAccessiveInfoRate)
+ GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->comittedInfoRate, tsuInTenthNanos, 0, &integer, &fraction);
+ else
+ GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->peakOrAccessiveInfoRate, tsuInTenthNanos, 0, &integer, &fraction);
+
+ /* we shift integer, as in cir/pir it is represented by the MSB 16 bits, and
+ * the LSB bits are for the fraction */
+ temp = (uint32_t)((integer<<16) & 0x00000000FFFFFFFF);
+ /* temp is effected by the rate. For low rates it may be as low as 0, and then we'll
+ * take max FP = 31.
+ * For high rates it will never exceed the 32 bit reg (after the 16 shift), as it is
+ * limited by the 10G physical port.
+ */
+ if (temp != 0)
+ {
+ /* In this case, the largest rate integer is non 0, if it does not occupy all (high) 16
+ * bits of the PIR_EIR we can use this fact and enlarge it to occupy all 16 bits.
+ * The logic is to have as many bits for integer in the higher rates, but if we have "0"s
+ * in the integer part of the cir/pir register, than these bits are wasted. So we want
+ * to use these bits for the fraction. in this way we will have for fraction - the number
+ * of "0" bits and the rest - for integer.
+ * In other words: For each bit we shift it in PIR_EIR, we move the FP in the TS
+ * one bit to the left - preserving the relationship and achieving more bits
+ * for integer in the TS.
+ */
+
+ /* count zeroes left of the higher used bit (in order to shift the value such that
+ * unused bits may be used for fraction).
+ */
+ while ((temp & 0x80000000) == 0)
+ {
+ temp = temp << 1;
+ fppShift++;
+ }
+ if (fppShift > 15)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_SELECTION, ("timeStampPeriod to Information rate ratio is too small"));
+ return;
+ }
+ }
+ else
+ {
+ temp = (uint32_t)fraction; /* fraction will alyas be smaller than 2^16 */
+ if (!temp)
+ /* integer and fraction are 0, we set FP to its max val */
+ fppShift = 31;
+ else
+ {
+ /* integer was 0 but fraction is not. FP is 16 for the fraction,
+ * + all left zeroes of the fraction. */
+ fppShift=16;
+ /* count zeroes left of the higher used bit (in order to shift the value such that
+ * unused bits may be used for fraction).
+ */
+ while ((temp & 0x8000) == 0)
+ {
+ temp = temp << 1;
+ fppShift++;
+ }
+ }
+ }
+
+ /*
+ * This means that the FM TS register will now be used so that 'fppShift' bits are for
+ * fraction and the rest for integer */
+ /* now we re-calculate cir and pir_eir with the calculated FP */
+ GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->comittedInfoRate, tsuInTenthNanos, fppShift, &integer, &fraction);
+ *cir = (uint32_t)(integer << 16 | (fraction & 0xFFFF));
+ GetInfoRateReg(p_NonPassthroughAlgParam->rateMode, p_NonPassthroughAlgParam->peakOrAccessiveInfoRate, tsuInTenthNanos, fppShift, &integer, &fraction);
+ *pir_eir = (uint32_t)(integer << 16 | (fraction & 0xFFFF));
+
+ *cbs = p_NonPassthroughAlgParam->comittedBurstSize;
+ *pbs_ebs = p_NonPassthroughAlgParam->peakOrAccessiveBurstSize;
+
+ /* convert FP as it should be written to reg.
+ * 0-15 --> 16-31
+ * 16-31 --> 0-15
+ */
+ *fpp = CalcFPP(fppShift);
+}
+
+static void WritePar(t_FmPcd *p_FmPcd, uint32_t par)
+{
+ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;
+
+ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));
+ WRITE_UINT32(p_FmPcdPlcrRegs->fmpl_par, par);
+
+ while (GET_UINT32(p_FmPcdPlcrRegs->fmpl_par) & FM_PCD_PLCR_PAR_GO) ;
+}
+
+static t_Error BuildProfileRegs(t_FmPcd *p_FmPcd,
+ t_FmPcdPlcrProfileParams *p_ProfileParams,
+ t_FmPcdPlcrProfileRegs *p_PlcrRegs)
+{
+ t_Error err = E_OK;
+ uint32_t pemode, gnia, ynia, rnia;
+
+ ASSERT_COND(p_FmPcd);
+
+/* Set G, Y, R Nia */
+ err = SetProfileNia(p_FmPcd, p_ProfileParams->nextEngineOnGreen, &(p_ProfileParams->paramsOnGreen), &gnia);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ err = SetProfileNia(p_FmPcd, p_ProfileParams->nextEngineOnYellow, &(p_ProfileParams->paramsOnYellow), &ynia);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ err = SetProfileNia(p_FmPcd, p_ProfileParams->nextEngineOnRed, &(p_ProfileParams->paramsOnRed), &rnia);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+/* Mode fmpl_pemode */
+ pemode = FM_PCD_PLCR_PEMODE_PI;
+
+ switch (p_ProfileParams->algSelection)
+ {
+ case e_FM_PCD_PLCR_PASS_THROUGH:
+ p_PlcrRegs->fmpl_pecir = 0;
+ p_PlcrRegs->fmpl_pecbs = 0;
+ p_PlcrRegs->fmpl_pepepir_eir = 0;
+ p_PlcrRegs->fmpl_pepbs_ebs = 0;
+ p_PlcrRegs->fmpl_pelts = 0;
+ p_PlcrRegs->fmpl_pects = 0;
+ p_PlcrRegs->fmpl_pepts_ets = 0;
+ pemode &= ~FM_PCD_PLCR_PEMODE_ALG_MASK;
+ switch (p_ProfileParams->colorMode)
+ {
+ case e_FM_PCD_PLCR_COLOR_BLIND:
+ pemode |= FM_PCD_PLCR_PEMODE_CBLND;
+ switch (p_ProfileParams->color.dfltColor)
+ {
+ case e_FM_PCD_PLCR_GREEN:
+ pemode &= ~FM_PCD_PLCR_PEMODE_DEFC_MASK;
+ break;
+ case e_FM_PCD_PLCR_YELLOW:
+ pemode |= FM_PCD_PLCR_PEMODE_DEFC_Y;
+ break;
+ case e_FM_PCD_PLCR_RED:
+ pemode |= FM_PCD_PLCR_PEMODE_DEFC_R;
+ break;
+ case e_FM_PCD_PLCR_OVERRIDE:
+ pemode |= FM_PCD_PLCR_PEMODE_DEFC_OVERRIDE;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+
+ break;
+ case e_FM_PCD_PLCR_COLOR_AWARE:
+ pemode &= ~FM_PCD_PLCR_PEMODE_CBLND;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+ break;
+
+ case e_FM_PCD_PLCR_RFC_2698:
+ /* Select algorithm MODE[ALG] = "01" */
+ pemode |= FM_PCD_PLCR_PEMODE_ALG_RFC2698;
+ if (p_ProfileParams->nonPassthroughAlgParams.comittedInfoRate > p_ProfileParams->nonPassthroughAlgParams.peakOrAccessiveInfoRate)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("in RFC2698 Peak rate must be equal or larger than comittedInfoRate."));
+ goto cont_rfc;
+ case e_FM_PCD_PLCR_RFC_4115:
+ /* Select algorithm MODE[ALG] = "10" */
+ pemode |= FM_PCD_PLCR_PEMODE_ALG_RFC4115;
+cont_rfc:
+ /* Select Color-Blind / Color-Aware operation (MODE[CBLND]) */
+ switch (p_ProfileParams->colorMode)
+ {
+ case e_FM_PCD_PLCR_COLOR_BLIND:
+ pemode |= FM_PCD_PLCR_PEMODE_CBLND;
+ break;
+ case e_FM_PCD_PLCR_COLOR_AWARE:
+ pemode &= ~FM_PCD_PLCR_PEMODE_CBLND;
+ /*In color aware more select override color interpretation (MODE[OVCLR]) */
+ switch (p_ProfileParams->color.override)
+ {
+ case e_FM_PCD_PLCR_GREEN:
+ pemode &= ~FM_PCD_PLCR_PEMODE_OVCLR_MASK;
+ break;
+ case e_FM_PCD_PLCR_YELLOW:
+ pemode |= FM_PCD_PLCR_PEMODE_OVCLR_Y;
+ break;
+ case e_FM_PCD_PLCR_RED:
+ pemode |= FM_PCD_PLCR_PEMODE_OVCLR_R;
+ break;
+ case e_FM_PCD_PLCR_OVERRIDE:
+ pemode |= FM_PCD_PLCR_PEMODE_OVCLR_G_NC;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+ /* Select Measurement Unit Mode to BYTE or PACKET (MODE[PKT]) */
+ switch (p_ProfileParams->nonPassthroughAlgParams.rateMode)
+ {
+ case e_FM_PCD_PLCR_BYTE_MODE :
+ pemode &= ~FM_PCD_PLCR_PEMODE_PKT;
+ switch (p_ProfileParams->nonPassthroughAlgParams.byteModeParams.frameLengthSelection)
+ {
+ case e_FM_PCD_PLCR_L2_FRM_LEN:
+ pemode |= FM_PCD_PLCR_PEMODE_FLS_L2;
+ break;
+ case e_FM_PCD_PLCR_L3_FRM_LEN:
+ pemode |= FM_PCD_PLCR_PEMODE_FLS_L3;
+ break;
+ case e_FM_PCD_PLCR_L4_FRM_LEN:
+ pemode |= FM_PCD_PLCR_PEMODE_FLS_L4;
+ break;
+ case e_FM_PCD_PLCR_FULL_FRM_LEN:
+ pemode |= FM_PCD_PLCR_PEMODE_FLS_FULL;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+ switch (p_ProfileParams->nonPassthroughAlgParams.byteModeParams.rollBackFrameSelection)
+ {
+ case e_FM_PCD_PLCR_ROLLBACK_L2_FRM_LEN:
+ pemode &= ~FM_PCD_PLCR_PEMODE_RBFLS;
+ break;
+ case e_FM_PCD_PLCR_ROLLBACK_FULL_FRM_LEN:
+ pemode |= FM_PCD_PLCR_PEMODE_RBFLS;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+ break;
+ case e_FM_PCD_PLCR_PACKET_MODE :
+ pemode |= FM_PCD_PLCR_PEMODE_PKT;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+ /* Select timeStamp floating point position (MODE[FPP]) to fit the actual traffic rates. For PACKET
+ mode with low traffic rates move the fixed point to the left to increase fraction accuracy. For BYTE
+ mode with high traffic rates move the fixed point to the right to increase integer accuracy. */
+
+ /* Configure Traffic Parameters*/
+ {
+ uint32_t cir=0, cbs=0, pir_eir=0, pbs_ebs=0, fpp=0;
+
+ CalcRates(p_FmPcd, &p_ProfileParams->nonPassthroughAlgParams, &cir, &cbs, &pir_eir, &pbs_ebs, &fpp);
+
+ /* Set Committed Information Rate (CIR) */
+ p_PlcrRegs->fmpl_pecir = cir;
+ /* Set Committed Burst Size (CBS). */
+ p_PlcrRegs->fmpl_pecbs = cbs;
+ /* Set Peak Information Rate (PIR_EIR used as PIR) */
+ p_PlcrRegs->fmpl_pepepir_eir = pir_eir;
+ /* Set Peak Burst Size (PBS_EBS used as PBS) */
+ p_PlcrRegs->fmpl_pepbs_ebs = pbs_ebs;
+
+ /* Initialize the Metering Buckets to be full (write them with 0xFFFFFFFF. */
+ /* Peak Rate Token Bucket Size (PTS_ETS used as PTS) */
+ p_PlcrRegs->fmpl_pepts_ets = 0xFFFFFFFF;
+ /* Committed Rate Token Bucket Size (CTS) */
+ p_PlcrRegs->fmpl_pects = 0xFFFFFFFF;
+
+ /* Set the FPP based on calculation */
+ pemode |= (fpp << FM_PCD_PLCR_PEMODE_FPP_SHIFT);
+ }
+ break; /* FM_PCD_PLCR_PEMODE_ALG_RFC2698 , FM_PCD_PLCR_PEMODE_ALG_RFC4115 */
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+
+ p_PlcrRegs->fmpl_pemode = pemode;
+
+ p_PlcrRegs->fmpl_pegnia = gnia;
+ p_PlcrRegs->fmpl_peynia = ynia;
+ p_PlcrRegs->fmpl_pernia = rnia;
+
+ /* Zero Counters */
+ p_PlcrRegs->fmpl_pegpc = 0;
+ p_PlcrRegs->fmpl_peypc = 0;
+ p_PlcrRegs->fmpl_perpc = 0;
+ p_PlcrRegs->fmpl_perypc = 0;
+ p_PlcrRegs->fmpl_perrpc = 0;
+
+ return E_OK;
+}
+
+static t_Error AllocSharedProfiles(t_FmPcd *p_FmPcd, uint16_t numOfProfiles, uint16_t *profilesIds)
+{
+ uint32_t profilesFound;
+ uint16_t i, k=0;
+ uint32_t intFlags;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+
+ if (!numOfProfiles)
+ return E_OK;
+
+ if (numOfProfiles>FM_PCD_PLCR_NUM_ENTRIES)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("numProfiles is too big."));
+
+ intFlags = PlcrSwLock(p_FmPcd->p_FmPcdPlcr);
+ /* Find numOfProfiles free profiles (may be spread) */
+ profilesFound = 0;
+ for (i=0;i<FM_PCD_PLCR_NUM_ENTRIES; i++)
+ if (!p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated)
+ {
+ profilesFound++;
+ profilesIds[k] = i;
+ k++;
+ if (profilesFound == numOfProfiles)
+ break;
+ }
+
+ if (profilesFound != numOfProfiles)
+ {
+ PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,NO_MSG);
+ }
+
+ for (i = 0;i<k;i++)
+ {
+ p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.allocated = TRUE;
+ p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.ownerId = 0;
+ }
+ PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);
+
+ return E_OK;
+}
+
+static void FreeSharedProfiles(t_FmPcd *p_FmPcd, uint16_t numOfProfiles, uint16_t *profilesIds)
+{
+ uint16_t i;
+
+ SANITY_CHECK_RETURN(p_FmPcd, E_INVALID_HANDLE);
+
+ ASSERT_COND(numOfProfiles);
+
+ for (i=0; i < numOfProfiles; i++)
+ {
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.allocated);
+ p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.allocated = FALSE;
+ p_FmPcd->p_FmPcdPlcr->profiles[profilesIds[i]].profilesMng.ownerId = p_FmPcd->guestId;
+ }
+}
+
+static void UpdateRequiredActionFlag(t_Handle h_FmPcd, uint16_t absoluteProfileId, bool set)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ /* this routine is protected by calling routine */
+
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid);
+
+ if (set)
+ p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredActionFlag = TRUE;
+ else
+ {
+ p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredAction = 0;
+ p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredActionFlag = FALSE;
+ }
+}
+
+/*********************************************/
+/*............Policer Exception..............*/
+/*********************************************/
+static void EventsCB(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint32_t event, mask, force;
+
+ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));
+ event = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_evr);
+ mask = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ier);
+
+ event &= mask;
+
+ /* clear the forced events */
+ force = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ifr);
+ if (force & event)
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_ifr, force & ~event);
+
+
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_evr, event);
+
+ if (event & FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE)
+ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE);
+ if (event & FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE)
+ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE);
+}
+
+/* ..... */
+
+static void ErrorExceptionsCB(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint32_t event, force, captureReg, mask;
+
+ ASSERT_COND(FmIsMaster(p_FmPcd->h_Fm));
+ event = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eevr);
+ mask = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eier);
+
+ event &= mask;
+
+ /* clear the forced events */
+ force = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eifr);
+ if (force & event)
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eifr, force & ~event);
+
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_eevr, event);
+
+ if (event & FM_PCD_PLCR_DOUBLE_ECC)
+ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC);
+ if (event & FM_PCD_PLCR_INIT_ENTRY_ERROR)
+ {
+ captureReg = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_upcr);
+ /*ASSERT_COND(captureReg & PLCR_ERR_UNINIT_CAP);
+ p_UnInitCapt->profileNum = (uint8_t)(captureReg & PLCR_ERR_UNINIT_NUM_MASK);
+ p_UnInitCapt->portId = (uint8_t)((captureReg & PLCR_ERR_UNINIT_PID_MASK) >>PLCR_ERR_UNINIT_PID_SHIFT) ;
+ p_UnInitCapt->absolute = (bool)(captureReg & PLCR_ERR_UNINIT_ABSOLUTE_MASK);*/
+ p_FmPcd->f_FmPcdIndexedException(p_FmPcd->h_App,e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR,(uint16_t)(captureReg & PLCR_ERR_UNINIT_NUM_MASK));
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_upcr, PLCR_ERR_UNINIT_CAP);
+ }
+}
+
+
+/*****************************************************************************/
+/* Inter-module API routines */
+/*****************************************************************************/
+
+t_Handle PlcrConfig(t_FmPcd *p_FmPcd, t_FmPcdParams *p_FmPcdParams)
+{
+ t_FmPcdPlcr *p_FmPcdPlcr;
+ uint16_t i=0;
+
+ UNUSED(p_FmPcd);
+ UNUSED(p_FmPcdParams);
+
+ p_FmPcdPlcr = (t_FmPcdPlcr *) XX_Malloc(sizeof(t_FmPcdPlcr));
+ if (!p_FmPcdPlcr)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Policer structure allocation FAILED"));
+ return NULL;
+ }
+ memset(p_FmPcdPlcr, 0, sizeof(t_FmPcdPlcr));
+ if (p_FmPcd->guestId == NCSW_MASTER_ID)
+ {
+ p_FmPcdPlcr->p_FmPcdPlcrRegs = (t_FmPcdPlcrRegs *)UINT_TO_PTR(FmGetPcdPlcrBaseAddr(p_FmPcdParams->h_Fm));
+ p_FmPcd->p_FmPcdDriverParam->plcrAutoRefresh = DEFAULT_plcrAutoRefresh;
+ p_FmPcd->exceptions |= (DEFAULT_fmPcdPlcrExceptions | DEFAULT_fmPcdPlcrErrorExceptions);
+ }
+
+ p_FmPcdPlcr->numOfSharedProfiles = DEFAULT_numOfSharedPlcrProfiles;
+
+ p_FmPcdPlcr->partPlcrProfilesBase = p_FmPcdParams->partPlcrProfilesBase;
+ p_FmPcdPlcr->partNumOfPlcrProfiles = p_FmPcdParams->partNumOfPlcrProfiles;
+ /* for backward compatabilty. if no policer profile, will set automatically to the max */
+ if ((p_FmPcd->guestId == NCSW_MASTER_ID) &&
+ (p_FmPcdPlcr->partNumOfPlcrProfiles == 0))
+ p_FmPcdPlcr->partNumOfPlcrProfiles = FM_PCD_PLCR_NUM_ENTRIES;
+
+ for (i=0; i<FM_PCD_PLCR_NUM_ENTRIES; i++)
+ p_FmPcdPlcr->profiles[i].profilesMng.ownerId = (uint8_t)ILLEGAL_BASE;
+
+ return p_FmPcdPlcr;
+}
+
+t_Error PlcrInit(t_FmPcd *p_FmPcd)
+{
+ t_FmPcdDriverParam *p_Param = p_FmPcd->p_FmPcdDriverParam;
+ t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr;
+ t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;
+ t_Error err = E_OK;
+ uint32_t tmpReg32 = 0;
+ uint16_t base;
+
+ if ((p_FmPcdPlcr->partPlcrProfilesBase + p_FmPcdPlcr->partNumOfPlcrProfiles) > FM_PCD_PLCR_NUM_ENTRIES)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("partPlcrProfilesBase+partNumOfPlcrProfiles out of range!!!"));
+
+ p_FmPcdPlcr->h_HwSpinlock = XX_InitSpinlock();
+ if (!p_FmPcdPlcr->h_HwSpinlock)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM Policer HW spinlock"));
+
+ p_FmPcdPlcr->h_SwSpinlock = XX_InitSpinlock();
+ if (!p_FmPcdPlcr->h_SwSpinlock)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("FM Policer SW spinlock"));
+
+ base = PlcrAllocProfilesForPartition(p_FmPcd,
+ p_FmPcdPlcr->partPlcrProfilesBase,
+ p_FmPcdPlcr->partNumOfPlcrProfiles,
+ p_FmPcd->guestId);
+ if (base == (uint16_t)ILLEGAL_BASE)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
+
+ if (p_FmPcdPlcr->numOfSharedProfiles)
+ {
+ err = AllocSharedProfiles(p_FmPcd,
+ p_FmPcdPlcr->numOfSharedProfiles,
+ p_FmPcdPlcr->sharedProfilesIds);
+ if (err)
+ RETURN_ERROR(MAJOR, err,NO_MSG);
+ }
+
+ if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ return E_OK;
+
+ /**********************FMPL_GCR******************/
+ tmpReg32 = 0;
+ tmpReg32 |= FM_PCD_PLCR_GCR_STEN;
+ if (p_Param->plcrAutoRefresh)
+ tmpReg32 |= FM_PCD_PLCR_GCR_DAR;
+ tmpReg32 |= GET_NIA_BMI_AC_ENQ_FRAME(p_FmPcd);
+
+ WRITE_UINT32(p_Regs->fmpl_gcr, tmpReg32);
+ /**********************FMPL_GCR******************/
+
+ /**********************FMPL_EEVR******************/
+ WRITE_UINT32(p_Regs->fmpl_eevr, (FM_PCD_PLCR_DOUBLE_ECC | FM_PCD_PLCR_INIT_ENTRY_ERROR));
+ /**********************FMPL_EEVR******************/
+ /**********************FMPL_EIER******************/
+ tmpReg32 = 0;
+ if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_DOUBLE_ECC)
+ {
+ FmEnableRamsEcc(p_FmPcd->h_Fm);
+ tmpReg32 |= FM_PCD_PLCR_DOUBLE_ECC;
+ }
+ if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_INIT_ENTRY_ERROR)
+ tmpReg32 |= FM_PCD_PLCR_INIT_ENTRY_ERROR;
+ WRITE_UINT32(p_Regs->fmpl_eier, tmpReg32);
+ /**********************FMPL_EIER******************/
+
+ /**********************FMPL_EVR******************/
+ WRITE_UINT32(p_Regs->fmpl_evr, (FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE | FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE));
+ /**********************FMPL_EVR******************/
+ /**********************FMPL_IER******************/
+ tmpReg32 = 0;
+ if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_PRAM_SELF_INIT_COMPLETE)
+ tmpReg32 |= FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE;
+ if (p_FmPcd->exceptions & FM_PCD_EX_PLCR_ATOMIC_ACTION_COMPLETE)
+ tmpReg32 |= FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE;
+ WRITE_UINT32(p_Regs->fmpl_ier, tmpReg32);
+ /**********************FMPL_IER******************/
+
+ /* register even if no interrupts enabled, to allow future enablement */
+ FmRegisterIntr(p_FmPcd->h_Fm,
+ e_FM_MOD_PLCR,
+ 0,
+ e_FM_INTR_TYPE_ERR,
+ ErrorExceptionsCB,
+ p_FmPcd);
+ FmRegisterIntr(p_FmPcd->h_Fm,
+ e_FM_MOD_PLCR,
+ 0,
+ e_FM_INTR_TYPE_NORMAL,
+ EventsCB,
+ p_FmPcd);
+
+ /* driver initializes one DFLT profile at the last entry*/
+ /**********************FMPL_DPMR******************/
+ tmpReg32 = 0;
+ WRITE_UINT32(p_Regs->fmpl_dpmr, tmpReg32);
+ p_FmPcd->p_FmPcdPlcr->profiles[0].profilesMng.allocated = TRUE;
+
+ return E_OK;
+}
+
+t_Error PlcrFree(t_FmPcd *p_FmPcd)
+{
+ FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PLCR, 0, e_FM_INTR_TYPE_ERR);
+ FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PLCR, 0, e_FM_INTR_TYPE_NORMAL);
+
+ if (p_FmPcd->p_FmPcdPlcr->numOfSharedProfiles)
+ FreeSharedProfiles(p_FmPcd,
+ p_FmPcd->p_FmPcdPlcr->numOfSharedProfiles,
+ p_FmPcd->p_FmPcdPlcr->sharedProfilesIds);
+
+ if (p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles)
+ PlcrFreeProfilesForPartition(p_FmPcd,
+ p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase,
+ p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles,
+ p_FmPcd->guestId);
+
+ if (p_FmPcd->p_FmPcdPlcr->h_SwSpinlock)
+ XX_FreeSpinlock(p_FmPcd->p_FmPcdPlcr->h_SwSpinlock);
+
+ if (p_FmPcd->p_FmPcdPlcr->h_HwSpinlock)
+ XX_FreeSpinlock(p_FmPcd->p_FmPcdPlcr->h_HwSpinlock);
+
+ return E_OK;
+}
+
+void PlcrEnable(t_FmPcd *p_FmPcd)
+{
+ t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;
+
+ WRITE_UINT32(p_Regs->fmpl_gcr, GET_UINT32(p_Regs->fmpl_gcr) | FM_PCD_PLCR_GCR_EN);
+}
+
+void PlcrDisable(t_FmPcd *p_FmPcd)
+{
+ t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;
+
+ WRITE_UINT32(p_Regs->fmpl_gcr, GET_UINT32(p_Regs->fmpl_gcr) & ~FM_PCD_PLCR_GCR_EN);
+}
+
+uint16_t PlcrAllocProfilesForPartition(t_FmPcd *p_FmPcd, uint16_t base, uint16_t numOfProfiles, uint8_t guestId)
+{
+ uint32_t intFlags;
+ uint16_t profilesFound = 0;
+ int i = 0;
+
+ ASSERT_COND(p_FmPcd);
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr);
+
+ if (!numOfProfiles)
+ return 0;
+
+ if ((numOfProfiles > FM_PCD_PLCR_NUM_ENTRIES) ||
+ (base + numOfProfiles > FM_PCD_PLCR_NUM_ENTRIES))
+ return (uint16_t)ILLEGAL_BASE;
+
+ if (p_FmPcd->h_IpcSession)
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ t_FmPcdIpcMsg msg;
+ t_FmPcdIpcReply reply;
+ t_Error err;
+ uint32_t replyLength;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams));
+ ipcAllocParams.guestId = p_FmPcd->guestId;
+ ipcAllocParams.num = p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles;
+ ipcAllocParams.base = p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase;
+ msg.msgId = FM_PCD_ALLOC_PROFILES;
+ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams));
+ replyLength = sizeof(uint32_t) + sizeof(uint16_t);
+ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if ((err != E_OK) ||
+ (replyLength != (sizeof(uint32_t) + sizeof(uint16_t))))
+ {
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ return (uint16_t)ILLEGAL_BASE;
+ }
+ else
+ memcpy((uint8_t*)&p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase, reply.replyBody, sizeof(uint16_t));
+ if (p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase == (uint16_t)ILLEGAL_BASE)
+ {
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ return (uint16_t)ILLEGAL_BASE;
+ }
+ }
+ else if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ {
+ DBG(WARNING, ("FM Guest mode, without IPC - can't validate Policer-profiles range!"));
+ return (uint16_t)ILLEGAL_BASE;
+ }
+
+ intFlags = XX_LockIntrSpinlock(p_FmPcd->h_Spinlock);
+ for (i=base; i<(base+numOfProfiles); i++)
+ if (p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId == (uint8_t)ILLEGAL_BASE)
+ profilesFound++;
+ else
+ break;
+
+ if (profilesFound == numOfProfiles)
+ for (i=base; i<(base+numOfProfiles); i++)
+ p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = guestId;
+ else
+ {
+ XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags);
+ return (uint16_t)ILLEGAL_BASE;
+ }
+ XX_UnlockIntrSpinlock(p_FmPcd->h_Spinlock, intFlags);
+
+ return base;
+}
+
+void PlcrFreeProfilesForPartition(t_FmPcd *p_FmPcd, uint16_t base, uint16_t numOfProfiles, uint8_t guestId)
+{
+ int i = 0;
+
+ ASSERT_COND(p_FmPcd);
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr);
+
+ if (p_FmPcd->h_IpcSession)
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ t_FmPcdIpcMsg msg;
+ t_Error err;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams));
+ ipcAllocParams.guestId = p_FmPcd->guestId;
+ ipcAllocParams.num = p_FmPcd->p_FmPcdPlcr->partNumOfPlcrProfiles;
+ ipcAllocParams.base = p_FmPcd->p_FmPcdPlcr->partPlcrProfilesBase;
+ msg.msgId = FM_PCD_FREE_PROFILES;
+ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams));
+ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ return;
+ }
+ else if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ {
+ DBG(WARNING, ("FM Guest mode, without IPC - can't validate Policer-profiles range!"));
+ return;
+ }
+
+ for (i=base; i<(base+numOfProfiles); i++)
+ {
+ if (p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId == guestId)
+ p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = (uint8_t)ILLEGAL_BASE;
+ else
+ DBG(WARNING, ("Request for freeing storage profile window which wasn't allocated to this partition"));
+ }
+}
+
+t_Error PlcrSetPortProfiles(t_FmPcd *p_FmPcd,
+ uint8_t hardwarePortId,
+ uint16_t numOfProfiles,
+ uint16_t base)
+{
+ t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;
+ uint32_t log2Num, tmpReg32;
+
+ if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&
+ !p_Regs &&
+ p_FmPcd->h_IpcSession)
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ t_FmPcdIpcMsg msg;
+ t_Error err;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams));
+ ipcAllocParams.guestId = hardwarePortId;
+ ipcAllocParams.num = numOfProfiles;
+ ipcAllocParams.base = base;
+ msg.msgId = FM_PCD_SET_PORT_PROFILES;
+ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams));
+ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ return E_OK;
+ }
+ else if (!p_Regs)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("Either IPC or 'baseAddress' is required!"));
+
+ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));
+
+ if (GET_UINT32(p_Regs->fmpl_pmr[hardwarePortId-1]) & FM_PCD_PLCR_PMR_V)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("The requesting port has already an allocated profiles window."));
+
+ /**********************FMPL_PMRx******************/
+ LOG2((uint64_t)numOfProfiles, log2Num);
+ tmpReg32 = base;
+ tmpReg32 |= log2Num << 16;
+ tmpReg32 |= FM_PCD_PLCR_PMR_V;
+ WRITE_UINT32(p_Regs->fmpl_pmr[hardwarePortId-1], tmpReg32);
+
+ return E_OK;
+}
+
+t_Error PlcrClearPortProfiles(t_FmPcd *p_FmPcd, uint8_t hardwarePortId)
+{
+ t_FmPcdPlcrRegs *p_Regs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;
+
+ if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&
+ !p_Regs &&
+ p_FmPcd->h_IpcSession)
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ t_FmPcdIpcMsg msg;
+ t_Error err;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams));
+ ipcAllocParams.guestId = hardwarePortId;
+ msg.msgId = FM_PCD_CLEAR_PORT_PROFILES;
+ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams));
+ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ return E_OK;
+ }
+ else if (!p_Regs)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("Either IPC or 'baseAddress' is required!"));
+
+ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));
+ WRITE_UINT32(p_Regs->fmpl_pmr[hardwarePortId-1], 0);
+
+ return E_OK;
+}
+
+t_Error FmPcdPlcrAllocProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId, uint16_t numOfProfiles)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_Error err = E_OK;
+ uint32_t profilesFound;
+ uint32_t intFlags;
+ uint16_t i, first, swPortIndex = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+
+ if (!numOfProfiles)
+ return E_OK;
+
+ ASSERT_COND(hardwarePortId);
+
+ if (numOfProfiles>FM_PCD_PLCR_NUM_ENTRIES)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("numProfiles is too big."));
+
+ if (!POWER_OF_2(numOfProfiles))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numProfiles must be a power of 2."));
+
+ first = 0;
+ profilesFound = 0;
+ intFlags = PlcrSwLock(p_FmPcd->p_FmPcdPlcr);
+
+ for (i=0; i<FM_PCD_PLCR_NUM_ENTRIES; )
+ {
+ if (!p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated)
+ {
+ profilesFound++;
+ i++;
+ if (profilesFound == numOfProfiles)
+ break;
+ }
+ else
+ {
+ profilesFound = 0;
+ /* advance i to the next aligned address */
+ i = first = (uint16_t)(first + numOfProfiles);
+ }
+ }
+
+ if (profilesFound == numOfProfiles)
+ {
+ for (i=first; i<first + numOfProfiles; i++)
+ {
+ p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated = TRUE;
+ p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = hardwarePortId;
+ }
+ }
+ else
+ {
+ PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);
+ RETURN_ERROR(MINOR, E_FULL, ("No profiles."));
+ }
+ PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);
+
+ err = PlcrSetPortProfiles(p_FmPcd, hardwarePortId, numOfProfiles, first);
+ if (err)
+ {
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId);
+
+ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles = numOfProfiles;
+ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase = first;
+
+ return E_OK;
+}
+
+t_Error FmPcdPlcrFreeProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_Error err = E_OK;
+ uint32_t intFlags;
+ uint16_t i, swPortIndex = 0;
+
+ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE);
+
+ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId);
+
+ err = PlcrClearPortProfiles(p_FmPcd, hardwarePortId);
+ if (err)
+ RETURN_ERROR(MAJOR, err,NO_MSG);
+
+ intFlags = PlcrSwLock(p_FmPcd->p_FmPcdPlcr);
+ for (i=p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase;
+ i<(p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase +
+ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles);
+ i++)
+ {
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId == hardwarePortId);
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated);
+
+ p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.allocated = FALSE;
+ p_FmPcd->p_FmPcdPlcr->profiles[i].profilesMng.ownerId = p_FmPcd->guestId;
+ }
+ PlcrSwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);
+
+ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles = 0;
+ p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase = 0;
+
+ return E_OK;
+}
+
+t_Error FmPcdPlcrCcGetSetParams(t_Handle h_FmPcd, uint16_t profileIndx ,uint32_t requiredAction)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr;
+ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs = p_FmPcdPlcr->p_FmPcdPlcrRegs;
+ uint32_t tmpReg32, intFlags;
+ t_Error err;
+
+ /* Calling function locked all PCD modules, so no need to lock here */
+
+ if (profileIndx >= FM_PCD_PLCR_NUM_ENTRIES)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("Policer profile out of range"));
+
+ if (!FmPcdPlcrIsProfileValid(p_FmPcd, profileIndx))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,("Policer profile is not valid"));
+
+ /*intFlags = PlcrProfileLock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx]);*/
+
+ if (p_FmPcd->h_Hc)
+ {
+ err = FmHcPcdPlcrCcGetSetParams(p_FmPcd->h_Hc, profileIndx, requiredAction);
+
+ UpdateRequiredActionFlag(p_FmPcd, profileIndx, TRUE);
+ FmPcdPlcrUpdateRequiredAction(p_FmPcd, profileIndx, requiredAction);
+
+ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/
+ return err;
+ }
+
+ /* lock the HW because once we read the registers we don't want them to be changed
+ * by another access. (We can copy to a tmp location and release the lock!) */
+
+ intFlags = PlcrHwLock(p_FmPcdPlcr);
+ WritePar(p_FmPcd, FmPcdPlcrBuildReadPlcrActionReg(profileIndx));
+
+ if (!p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].requiredActionFlag ||
+ !(p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].requiredAction & requiredAction))
+ {
+ if (requiredAction & UPDATE_NIA_ENQ_WITHOUT_DMA)
+ {
+ if ((p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].nextEngineOnGreen!= e_FM_PCD_DONE) ||
+ (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].nextEngineOnYellow!= e_FM_PCD_DONE) ||
+ (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].nextEngineOnRed!= e_FM_PCD_DONE))
+ {
+ PlcrHwUnlock(p_FmPcdPlcr, intFlags);
+ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/
+ RETURN_ERROR (MAJOR, E_OK, ("In this case the next engine can be e_FM_PCD_DONE"));
+ }
+
+ if (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].paramsOnGreen.action == e_FM_PCD_ENQ_FRAME)
+ {
+ tmpReg32 = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegnia);
+ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)))
+ {
+ PlcrHwUnlock(p_FmPcdPlcr, intFlags);
+ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE"));
+ }
+ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA;
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegnia, tmpReg32);
+ tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx);
+ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEGNIA;
+ WritePar(p_FmPcd, tmpReg32);
+ }
+
+ if (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].paramsOnYellow.action == e_FM_PCD_ENQ_FRAME)
+ {
+ tmpReg32 = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peynia);
+ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)))
+ {
+ PlcrHwUnlock(p_FmPcdPlcr, intFlags);
+ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE"));
+ }
+ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA;
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peynia, tmpReg32);
+ tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx);
+ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEYNIA;
+ WritePar(p_FmPcd, tmpReg32);
+ PlcrHwUnlock(p_FmPcdPlcr, intFlags);
+ }
+
+ if (p_FmPcd->p_FmPcdPlcr->profiles[profileIndx].paramsOnRed.action == e_FM_PCD_ENQ_FRAME)
+ {
+ tmpReg32 = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pernia);
+ if (!(tmpReg32 & (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)))
+ {
+ PlcrHwUnlock(p_FmPcdPlcr, intFlags);
+ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Next engine of this policer profile has to be assigned to FM_PCD_DONE"));
+ }
+ tmpReg32 |= NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA;
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pernia, tmpReg32);
+ tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx);
+ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PERNIA;
+ WritePar(p_FmPcd, tmpReg32);
+
+ }
+ }
+ }
+ PlcrHwUnlock(p_FmPcdPlcr, intFlags);
+
+ UpdateRequiredActionFlag(p_FmPcd, profileIndx, TRUE);
+ FmPcdPlcrUpdateRequiredAction(p_FmPcd, profileIndx, requiredAction);
+
+ /*PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[profileIndx], intFlags);*/
+
+ return E_OK;
+}
+
+uint32_t FmPcdPlcrGetRequiredActionFlag(t_Handle h_FmPcd, uint16_t absoluteProfileId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid);
+
+ return p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredActionFlag;
+}
+
+uint32_t FmPcdPlcrGetRequiredAction(t_Handle h_FmPcd, uint16_t absoluteProfileId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid);
+
+ return p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredAction;
+}
+
+bool FmPcdPlcrIsProfileValid(t_Handle h_FmPcd, uint16_t absoluteProfileId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr;
+
+ ASSERT_COND(absoluteProfileId < FM_PCD_PLCR_NUM_ENTRIES);
+
+ return p_FmPcdPlcr->profiles[absoluteProfileId].valid;
+}
+
+void FmPcdPlcrValidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t intFlags;
+
+ ASSERT_COND(!p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid);
+
+ intFlags = PlcrProfileLock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId]);
+ p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid = TRUE;
+ PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId], intFlags);
+}
+
+void FmPcdPlcrInvalidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t intFlags;
+
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid);
+
+ intFlags = PlcrProfileLock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId]);
+ p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid = FALSE;
+ PlcrProfileUnlock(&p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId], intFlags);
+}
+
+uint16_t FmPcdPlcrProfileGetAbsoluteId(t_Handle h_Profile)
+{
+ return ((t_FmPcdPlcrProfile*)h_Profile)->absoluteProfileId;
+}
+
+t_Error FmPcdPlcrGetAbsoluteIdByProfileParams(t_Handle h_FmPcd,
+ e_FmPcdProfileTypeSelection profileType,
+ t_Handle h_FmPort,
+ uint16_t relativeProfile,
+ uint16_t *p_AbsoluteId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ t_FmPcdPlcr *p_FmPcdPlcr = p_FmPcd->p_FmPcdPlcr;
+ uint8_t i;
+
+ switch (profileType)
+ {
+ case e_FM_PCD_PLCR_PORT_PRIVATE:
+ /* get port PCD id from port handle */
+ for (i=0;i<FM_MAX_NUM_OF_PORTS;i++)
+ if (p_FmPcd->p_FmPcdPlcr->portsMapping[i].h_FmPort == h_FmPort)
+ break;
+ if (i == FM_MAX_NUM_OF_PORTS)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE , ("Invalid port handle."));
+
+ if (!p_FmPcd->p_FmPcdPlcr->portsMapping[i].numOfProfiles)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION , ("Port has no allocated profiles"));
+ if (relativeProfile >= p_FmPcd->p_FmPcdPlcr->portsMapping[i].numOfProfiles)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION , ("Profile id is out of range"));
+ *p_AbsoluteId = (uint16_t)(p_FmPcd->p_FmPcdPlcr->portsMapping[i].profilesBase + relativeProfile);
+ break;
+ case e_FM_PCD_PLCR_SHARED:
+ if (relativeProfile >= p_FmPcdPlcr->numOfSharedProfiles)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION , ("Profile id is out of range"));
+ *p_AbsoluteId = (uint16_t)(p_FmPcdPlcr->sharedProfilesIds[relativeProfile]);
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Invalid policer profile type"));
+ }
+
+ return E_OK;
+}
+
+uint16_t FmPcdPlcrGetPortProfilesBase(t_Handle h_FmPcd, uint8_t hardwarePortId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint16_t swPortIndex = 0;
+
+ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId);
+
+ return p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].profilesBase;
+}
+
+uint16_t FmPcdPlcrGetPortNumOfProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint16_t swPortIndex = 0;
+
+ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId);
+
+ return p_FmPcd->p_FmPcdPlcr->portsMapping[swPortIndex].numOfProfiles;
+
+}
+uint32_t FmPcdPlcrBuildWritePlcrActionReg(uint16_t absoluteProfileId)
+{
+ return (uint32_t)(FM_PCD_PLCR_PAR_GO |
+ ((uint32_t)absoluteProfileId << FM_PCD_PLCR_PAR_PNUM_SHIFT));
+}
+
+uint32_t FmPcdPlcrBuildWritePlcrActionRegs(uint16_t absoluteProfileId)
+{
+ return (uint32_t)(FM_PCD_PLCR_PAR_GO |
+ ((uint32_t)absoluteProfileId << FM_PCD_PLCR_PAR_PNUM_SHIFT) |
+ FM_PCD_PLCR_PAR_PWSEL_MASK);
+}
+
+bool FmPcdPlcrHwProfileIsValid(uint32_t profileModeReg)
+{
+
+ if (profileModeReg & FM_PCD_PLCR_PEMODE_PI)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+uint32_t FmPcdPlcrBuildReadPlcrActionReg(uint16_t absoluteProfileId)
+{
+ return (uint32_t)(FM_PCD_PLCR_PAR_GO |
+ FM_PCD_PLCR_PAR_R |
+ ((uint32_t)absoluteProfileId << FM_PCD_PLCR_PAR_PNUM_SHIFT) |
+ FM_PCD_PLCR_PAR_PWSEL_MASK);
+}
+
+uint32_t FmPcdPlcrBuildCounterProfileReg(e_FmPcdPlcrProfileCounters counter)
+{
+ switch (counter)
+ {
+ case (e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER):
+ return FM_PCD_PLCR_PAR_PWSEL_PEGPC;
+ case (e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER):
+ return FM_PCD_PLCR_PAR_PWSEL_PEYPC;
+ case (e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER) :
+ return FM_PCD_PLCR_PAR_PWSEL_PERPC;
+ case (e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER) :
+ return FM_PCD_PLCR_PAR_PWSEL_PERYPC;
+ case (e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER) :
+ return FM_PCD_PLCR_PAR_PWSEL_PERRPC;
+ default:
+ REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ return 0;
+ }
+}
+
+uint32_t FmPcdPlcrBuildNiaProfileReg(bool green, bool yellow, bool red)
+{
+
+ uint32_t tmpReg32 = 0;
+
+ if (green)
+ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEGNIA;
+ if (yellow)
+ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PEYNIA;
+ if (red)
+ tmpReg32 |= FM_PCD_PLCR_PAR_PWSEL_PERNIA;
+
+ return tmpReg32;
+}
+
+void FmPcdPlcrUpdateRequiredAction(t_Handle h_FmPcd, uint16_t absoluteProfileId, uint32_t requiredAction)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ /* this routine is protected by calling routine */
+
+ ASSERT_COND(p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].valid);
+
+ p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId].requiredAction |= requiredAction;
+}
+
+/*********************** End of inter-module routines ************************/
+
+
+/**************************************************/
+/*............Policer API.........................*/
+/**************************************************/
+
+t_Error FM_PCD_ConfigPlcrAutoRefreshMode(t_Handle h_FmPcd, bool enable)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE);
+
+ if (!FmIsMaster(p_FmPcd->h_Fm))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ConfigPlcrAutoRefreshMode - guest mode!"));
+
+ p_FmPcd->p_FmPcdDriverParam->plcrAutoRefresh = enable;
+
+ return E_OK;
+}
+
+t_Error FM_PCD_ConfigPlcrNumOfSharedProfiles(t_Handle h_FmPcd, uint16_t numOfSharedPlcrProfiles)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE);
+
+ p_FmPcd->p_FmPcdPlcr->numOfSharedProfiles = numOfSharedPlcrProfiles;
+
+ return E_OK;
+}
+
+t_Error FM_PCD_SetPlcrStatistics(t_Handle h_FmPcd, bool enable)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t tmpReg32;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE);
+
+ if (!FmIsMaster(p_FmPcd->h_Fm))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_SetPlcrStatistics - guest mode!"));
+
+ tmpReg32 = GET_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_gcr);
+ if (enable)
+ tmpReg32 |= FM_PCD_PLCR_GCR_STEN;
+ else
+ tmpReg32 &= ~FM_PCD_PLCR_GCR_STEN;
+
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_gcr, tmpReg32);
+ return E_OK;
+}
+
+/* ... */
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+t_Error FM_PCD_PlcrDumpRegs(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ int i = 0;
+
+ DECLARE_DUMP;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(((p_FmPcd->guestId == NCSW_MASTER_ID) ||
+ p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs), E_INVALID_OPERATION);
+
+ DUMP_SUBTITLE(("\n"));
+ DUMP_TITLE(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, ("FM-PCD policer regs"));
+
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_gcr);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_gsr);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_evr);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_ier);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_ifr);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_eevr);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_eier);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_eifr);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_rpcnt);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_ypcnt);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_rrpcnt);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_rypcnt);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_tpcnt);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_flmcnt);
+
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_serc);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_upcr);
+ DUMP_VAR(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,fmpl_dpmr);
+
+ DUMP_TITLE(&p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_pmr, ("fmpl_pmr"));
+ DUMP_SUBSTRUCT_ARRAY(i, 63)
+ {
+ DUMP_MEMORY(&p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_pmr[i], sizeof(uint32_t));
+ }
+
+ return E_OK;
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+t_Handle FM_PCD_PlcrProfileSet(t_Handle h_FmPcd,
+ t_FmPcdPlcrProfileParams *p_ProfileParams)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs;
+ t_FmPcdPlcrProfileRegs plcrProfileReg;
+ uint32_t intFlags;
+ uint16_t absoluteProfileId;
+ t_Error err = E_OK;
+ uint32_t tmpReg32;
+ t_FmPcdPlcrProfile *p_Profile;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL);
+
+ if (p_ProfileParams->modify)
+ {
+ p_Profile = (t_FmPcdPlcrProfile *)p_ProfileParams->id.h_Profile;
+ p_FmPcd = p_Profile->h_FmPcd;
+ absoluteProfileId = p_Profile->absoluteProfileId;
+ if (absoluteProfileId >= FM_PCD_PLCR_NUM_ENTRIES)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("profileId too Big "));
+ return NULL;
+ }
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE, NULL);
+
+ /* Try lock profile using flag */
+ if (!PlcrProfileFlagTryLock(p_Profile))
+ {
+ DBG(TRACE, ("Profile Try Lock - BUSY"));
+ /* Signal to caller BUSY condition */
+ p_ProfileParams->id.h_Profile = NULL;
+ return NULL;
+ }
+ }
+ else
+ {
+ p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE, NULL);
+
+ /* SMP: needs to be protected only if another core now changes the windows */
+ err = FmPcdPlcrGetAbsoluteIdByProfileParams(h_FmPcd,
+ p_ProfileParams->id.newParams.profileType,
+ p_ProfileParams->id.newParams.h_FmPort,
+ p_ProfileParams->id.newParams.relativeProfileId,
+ &absoluteProfileId);
+
+ if (absoluteProfileId >= FM_PCD_PLCR_NUM_ENTRIES)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("profileId too Big "));
+ return NULL;
+ }
+
+ if (FmPcdPlcrIsProfileValid(p_FmPcd, absoluteProfileId))
+ {
+ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ("Policer Profile is already used"));
+ return NULL;
+ }
+
+ /* initialize profile struct */
+ p_Profile = &p_FmPcd->p_FmPcdPlcr->profiles[absoluteProfileId];
+
+ p_Profile->h_FmPcd = p_FmPcd;
+ p_Profile->absoluteProfileId = absoluteProfileId;
+
+ p_Profile->p_Lock = FmPcdAcquireLock(p_FmPcd);
+ if (!p_Profile->p_Lock)
+ REPORT_ERROR(MAJOR, E_NOT_AVAILABLE, ("FM Policer Profile lock obj!"));
+ }
+
+ SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE, NULL);
+
+ p_Profile->nextEngineOnGreen = p_ProfileParams->nextEngineOnGreen;
+ memcpy(&p_Profile->paramsOnGreen, &(p_ProfileParams->paramsOnGreen), sizeof(u_FmPcdPlcrNextEngineParams));
+
+ p_Profile->nextEngineOnYellow = p_ProfileParams->nextEngineOnYellow;
+ memcpy(&p_Profile->paramsOnYellow, &(p_ProfileParams->paramsOnYellow), sizeof(u_FmPcdPlcrNextEngineParams));
+
+ p_Profile->nextEngineOnRed = p_ProfileParams->nextEngineOnRed;
+ memcpy(&p_Profile->paramsOnRed, &(p_ProfileParams->paramsOnRed), sizeof(u_FmPcdPlcrNextEngineParams));
+
+ memset(&plcrProfileReg, 0, sizeof(t_FmPcdPlcrProfileRegs));
+
+ /* build the policer profile registers */
+ err = BuildProfileRegs(h_FmPcd, p_ProfileParams, &plcrProfileReg);
+ if (err)
+ {
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ if (p_ProfileParams->modify)
+ /* unlock */
+ PlcrProfileFlagUnlock(p_Profile);
+ if (!p_ProfileParams->modify &&
+ p_Profile->p_Lock)
+ /* release allocated Profile lock */
+ FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock);
+ return NULL;
+ }
+
+ if (p_FmPcd->h_Hc)
+ {
+ err = FmHcPcdPlcrSetProfile(p_FmPcd->h_Hc, (t_Handle)p_Profile, &plcrProfileReg);
+ if (p_ProfileParams->modify)
+ PlcrProfileFlagUnlock(p_Profile);
+ if (err)
+ {
+ /* release the allocated scheme lock */
+ if (!p_ProfileParams->modify &&
+ p_Profile->p_Lock)
+ FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock);
+
+ return NULL;
+ }
+ if (!p_ProfileParams->modify)
+ FmPcdPlcrValidateProfileSw(p_FmPcd,absoluteProfileId);
+ return (t_Handle)p_Profile;
+ }
+
+ p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;
+ SANITY_CHECK_RETURN_VALUE(p_FmPcdPlcrRegs, E_INVALID_HANDLE, NULL);
+
+ intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pemode , plcrProfileReg.fmpl_pemode);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegnia , plcrProfileReg.fmpl_pegnia);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peynia , plcrProfileReg.fmpl_peynia);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pernia , plcrProfileReg.fmpl_pernia);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pecir , plcrProfileReg.fmpl_pecir);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pecbs , plcrProfileReg.fmpl_pecbs);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pepepir_eir,plcrProfileReg.fmpl_pepepir_eir);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pepbs_ebs,plcrProfileReg.fmpl_pepbs_ebs);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pelts , plcrProfileReg.fmpl_pelts);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pects , plcrProfileReg.fmpl_pects);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pepts_ets,plcrProfileReg.fmpl_pepts_ets);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegpc , plcrProfileReg.fmpl_pegpc);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peypc , plcrProfileReg.fmpl_peypc);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perpc , plcrProfileReg.fmpl_perpc);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perypc , plcrProfileReg.fmpl_perypc);
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perrpc , plcrProfileReg.fmpl_perrpc);
+
+ tmpReg32 = FmPcdPlcrBuildWritePlcrActionRegs(absoluteProfileId);
+ WritePar(p_FmPcd, tmpReg32);
+
+ PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);
+
+ if (!p_ProfileParams->modify)
+ FmPcdPlcrValidateProfileSw(p_FmPcd,absoluteProfileId);
+ else
+ PlcrProfileFlagUnlock(p_Profile);
+
+ return (t_Handle)p_Profile;
+}
+
+t_Error FM_PCD_PlcrProfileDelete(t_Handle h_Profile)
+{
+ t_FmPcdPlcrProfile *p_Profile = (t_FmPcdPlcrProfile*)h_Profile;
+ t_FmPcd *p_FmPcd;
+ uint16_t profileIndx;
+ uint32_t tmpReg32, intFlags;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Profile, E_INVALID_HANDLE);
+ p_FmPcd = p_Profile->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+
+ profileIndx = p_Profile->absoluteProfileId;
+
+ UpdateRequiredActionFlag(p_FmPcd, profileIndx, FALSE);
+
+ FmPcdPlcrInvalidateProfileSw(p_FmPcd,profileIndx);
+
+ if (p_FmPcd->h_Hc)
+ {
+ err = FmHcPcdPlcrDeleteProfile(p_FmPcd->h_Hc, h_Profile);
+ if (p_Profile->p_Lock)
+ /* release allocated Profile lock */
+ FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock);
+
+ return err;
+ }
+
+ intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr);
+ WRITE_UINT32(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->profileRegs.fmpl_pemode, ~FM_PCD_PLCR_PEMODE_PI);
+
+ tmpReg32 = FmPcdPlcrBuildWritePlcrActionRegs(profileIndx);
+ WritePar(p_FmPcd, tmpReg32);
+ PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);
+
+
+ if (p_Profile->p_Lock)
+ /* release allocated Profile lock */
+ FmPcdReleaseLock(p_FmPcd, p_Profile->p_Lock);
+
+ /* we do not memset profile as all its fields are being re-initialized at "set",
+ * plus its allocation information is still valid. */
+ return E_OK;
+}
+
+/***************************************************/
+/*............Policer Profile Counter..............*/
+/***************************************************/
+uint32_t FM_PCD_PlcrProfileGetCounter(t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter)
+{
+ t_FmPcdPlcrProfile *p_Profile = (t_FmPcdPlcrProfile*)h_Profile;
+ t_FmPcd *p_FmPcd;
+ uint16_t profileIndx;
+ uint32_t intFlags, counterVal = 0;
+ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs;
+
+ SANITY_CHECK_RETURN_ERROR(p_Profile, E_INVALID_HANDLE);
+ p_FmPcd = p_Profile->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+
+ if (p_FmPcd->h_Hc)
+ return FmHcPcdPlcrGetProfileCounter(p_FmPcd->h_Hc, h_Profile, counter);
+
+ p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;
+ SANITY_CHECK_RETURN_VALUE(p_FmPcdPlcrRegs, E_INVALID_HANDLE, 0);
+
+ profileIndx = p_Profile->absoluteProfileId;
+
+ if (profileIndx >= FM_PCD_PLCR_NUM_ENTRIES)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("profileId too Big "));
+ return 0;
+ }
+ intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr);
+ WritePar(p_FmPcd, FmPcdPlcrBuildReadPlcrActionReg(profileIndx));
+
+ switch (counter)
+ {
+ case e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER:
+ counterVal = (GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegpc));
+ break;
+ case e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER:
+ counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peypc);
+ break;
+ case e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER:
+ counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perpc);
+ break;
+ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER:
+ counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perypc);
+ break;
+ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER:
+ counterVal = GET_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perrpc);
+ break;
+ default:
+ REPORT_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ break;
+ }
+ PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);
+
+ return counterVal;
+}
+
+t_Error FM_PCD_PlcrProfileSetCounter(t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter, uint32_t value)
+{
+ t_FmPcdPlcrProfile *p_Profile = (t_FmPcdPlcrProfile*)h_Profile;
+ t_FmPcd *p_FmPcd;
+ uint16_t profileIndx;
+ uint32_t tmpReg32, intFlags;
+ t_FmPcdPlcrRegs *p_FmPcdPlcrRegs;
+
+ SANITY_CHECK_RETURN_ERROR(p_Profile, E_INVALID_HANDLE);
+
+ p_FmPcd = p_Profile->h_FmPcd;
+ profileIndx = p_Profile->absoluteProfileId;
+
+ if (p_FmPcd->h_Hc)
+ return FmHcPcdPlcrSetProfileCounter(p_FmPcd->h_Hc, h_Profile, counter, value);
+
+ p_FmPcdPlcrRegs = p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcdPlcrRegs, E_INVALID_HANDLE);
+
+ intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr);
+ switch (counter)
+ {
+ case e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER:
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_pegpc, value);
+ break;
+ case e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER:
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_peypc, value);
+ break;
+ case e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER:
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perpc, value);
+ break;
+ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER:
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perypc ,value);
+ break;
+ case e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER:
+ WRITE_UINT32(p_FmPcdPlcrRegs->profileRegs.fmpl_perrpc ,value);
+ break;
+ default:
+ PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+
+ /* Activate the atomic write action by writing FMPL_PAR with: GO=1, RW=1, PSI=0, PNUM =
+ * Profile Number, PWSEL=0xFFFF (select all words).
+ */
+ tmpReg32 = FmPcdPlcrBuildWritePlcrActionReg(profileIndx);
+ tmpReg32 |= FmPcdPlcrBuildCounterProfileReg(counter);
+ WritePar(p_FmPcd, tmpReg32);
+ PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);
+
+ return E_OK;
+}
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+t_Error FM_PCD_PlcrProfileDumpRegs(t_Handle h_Profile)
+{
+ t_FmPcdPlcrProfile *p_Profile = (t_FmPcdPlcrProfile*)h_Profile;
+ t_FmPcd *p_FmPcd;
+ t_FmPcdPlcrProfileRegs *p_ProfilesRegs;
+ uint16_t profileIndx;
+ uint32_t tmpReg, intFlags;
+
+ DECLARE_DUMP;
+
+ SANITY_CHECK_RETURN_ERROR(p_Profile, E_INVALID_HANDLE);
+ p_FmPcd = p_Profile->h_FmPcd;
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPlcr, E_INVALID_HANDLE);
+
+ profileIndx = p_Profile->absoluteProfileId;
+
+ DUMP_SUBTITLE(("\n"));
+ DUMP_TITLE(p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, ("FM-PCD policer-profile regs"));
+
+ p_ProfilesRegs = &p_FmPcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->profileRegs;
+
+ tmpReg = FmPcdPlcrBuildReadPlcrActionReg((uint16_t)profileIndx);
+ intFlags = PlcrHwLock(p_FmPcd->p_FmPcdPlcr);
+ WritePar(p_FmPcd, tmpReg);
+
+ DUMP_TITLE(p_ProfilesRegs, ("Profile %d regs", profileIndx));
+
+ DUMP_VAR(p_ProfilesRegs, fmpl_pemode);
+ DUMP_VAR(p_ProfilesRegs, fmpl_pegnia);
+ DUMP_VAR(p_ProfilesRegs, fmpl_peynia);
+ DUMP_VAR(p_ProfilesRegs, fmpl_pernia);
+ DUMP_VAR(p_ProfilesRegs, fmpl_pecir);
+ DUMP_VAR(p_ProfilesRegs, fmpl_pecbs);
+ DUMP_VAR(p_ProfilesRegs, fmpl_pepepir_eir);
+ DUMP_VAR(p_ProfilesRegs, fmpl_pepbs_ebs);
+ DUMP_VAR(p_ProfilesRegs, fmpl_pelts);
+ DUMP_VAR(p_ProfilesRegs, fmpl_pects);
+ DUMP_VAR(p_ProfilesRegs, fmpl_pepts_ets);
+ DUMP_VAR(p_ProfilesRegs, fmpl_pegpc);
+ DUMP_VAR(p_ProfilesRegs, fmpl_peypc);
+ DUMP_VAR(p_ProfilesRegs, fmpl_perpc);
+ DUMP_VAR(p_ProfilesRegs, fmpl_perypc);
+ DUMP_VAR(p_ProfilesRegs, fmpl_perrpc);
+ PlcrHwUnlock(p_FmPcd->p_FmPcdPlcr, intFlags);
+
+ return E_OK;
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_plcr.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_plcr.h
new file mode 100644
index 0000000..2bb8b96
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_plcr.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_plcr.h
+
+ @Description FM Policer private header
+*//***************************************************************************/
+#ifndef __FM_PLCR_H
+#define __FM_PLCR_H
+
+#include "std_ext.h"
+
+
+/***********************************************************************/
+/* Policer defines */
+/***********************************************************************/
+
+#define FM_PCD_PLCR_PAR_GO 0x80000000
+#define FM_PCD_PLCR_PAR_PWSEL_MASK 0x0000FFFF
+#define FM_PCD_PLCR_PAR_R 0x40000000
+
+/* shifts */
+#define FM_PCD_PLCR_PAR_PNUM_SHIFT 16
+
+/* masks */
+#define FM_PCD_PLCR_PEMODE_PI 0x80000000
+#define FM_PCD_PLCR_PEMODE_CBLND 0x40000000
+#define FM_PCD_PLCR_PEMODE_ALG_MASK 0x30000000
+#define FM_PCD_PLCR_PEMODE_ALG_RFC2698 0x10000000
+#define FM_PCD_PLCR_PEMODE_ALG_RFC4115 0x20000000
+#define FM_PCD_PLCR_PEMODE_DEFC_MASK 0x0C000000
+#define FM_PCD_PLCR_PEMODE_DEFC_Y 0x04000000
+#define FM_PCD_PLCR_PEMODE_DEFC_R 0x08000000
+#define FM_PCD_PLCR_PEMODE_DEFC_OVERRIDE 0x0C000000
+#define FM_PCD_PLCR_PEMODE_OVCLR_MASK 0x03000000
+#define FM_PCD_PLCR_PEMODE_OVCLR_Y 0x01000000
+#define FM_PCD_PLCR_PEMODE_OVCLR_R 0x02000000
+#define FM_PCD_PLCR_PEMODE_OVCLR_G_NC 0x03000000
+#define FM_PCD_PLCR_PEMODE_PKT 0x00800000
+#define FM_PCD_PLCR_PEMODE_FPP_MASK 0x001F0000
+#define FM_PCD_PLCR_PEMODE_FPP_SHIFT 16
+#define FM_PCD_PLCR_PEMODE_FLS_MASK 0x0000F000
+#define FM_PCD_PLCR_PEMODE_FLS_L2 0x00003000
+#define FM_PCD_PLCR_PEMODE_FLS_L3 0x0000B000
+#define FM_PCD_PLCR_PEMODE_FLS_L4 0x0000E000
+#define FM_PCD_PLCR_PEMODE_FLS_FULL 0x0000F000
+#define FM_PCD_PLCR_PEMODE_RBFLS 0x00000800
+#define FM_PCD_PLCR_PEMODE_TRA 0x00000004
+#define FM_PCD_PLCR_PEMODE_TRB 0x00000002
+#define FM_PCD_PLCR_PEMODE_TRC 0x00000001
+#define FM_PCD_PLCR_DOUBLE_ECC 0x80000000
+#define FM_PCD_PLCR_INIT_ENTRY_ERROR 0x40000000
+#define FM_PCD_PLCR_PRAM_SELF_INIT_COMPLETE 0x80000000
+#define FM_PCD_PLCR_ATOMIC_ACTION_COMPLETE 0x40000000
+
+#define FM_PCD_PLCR_NIA_VALID 0x80000000
+
+#define FM_PCD_PLCR_GCR_EN 0x80000000
+#define FM_PCD_PLCR_GCR_STEN 0x40000000
+#define FM_PCD_PLCR_GCR_DAR 0x20000000
+#define FM_PCD_PLCR_GCR_DEFNIA 0x00FFFFFF
+#define FM_PCD_PLCR_NIA_ABS 0x00000100
+
+#define FM_PCD_PLCR_GSR_BSY 0x80000000
+#define FM_PCD_PLCR_GSR_DQS 0x60000000
+#define FM_PCD_PLCR_GSR_RPB 0x20000000
+#define FM_PCD_PLCR_GSR_FQS 0x0C000000
+#define FM_PCD_PLCR_GSR_LPALG 0x0000C000
+#define FM_PCD_PLCR_GSR_LPCA 0x00003000
+#define FM_PCD_PLCR_GSR_LPNUM 0x000000FF
+
+#define FM_PCD_PLCR_EVR_PSIC 0x80000000
+#define FM_PCD_PLCR_EVR_AAC 0x40000000
+
+#define FM_PCD_PLCR_PAR_PSI 0x20000000
+#define FM_PCD_PLCR_PAR_PNUM 0x00FF0000
+/* PWSEL Selctive select options */
+#define FM_PCD_PLCR_PAR_PWSEL_PEMODE 0x00008000 /* 0 */
+#define FM_PCD_PLCR_PAR_PWSEL_PEGNIA 0x00004000 /* 1 */
+#define FM_PCD_PLCR_PAR_PWSEL_PEYNIA 0x00002000 /* 2 */
+#define FM_PCD_PLCR_PAR_PWSEL_PERNIA 0x00001000 /* 3 */
+#define FM_PCD_PLCR_PAR_PWSEL_PECIR 0x00000800 /* 4 */
+#define FM_PCD_PLCR_PAR_PWSEL_PECBS 0x00000400 /* 5 */
+#define FM_PCD_PLCR_PAR_PWSEL_PEPIR_EIR 0x00000200 /* 6 */
+#define FM_PCD_PLCR_PAR_PWSEL_PEPBS_EBS 0x00000100 /* 7 */
+#define FM_PCD_PLCR_PAR_PWSEL_PELTS 0x00000080 /* 8 */
+#define FM_PCD_PLCR_PAR_PWSEL_PECTS 0x00000040 /* 9 */
+#define FM_PCD_PLCR_PAR_PWSEL_PEPTS_ETS 0x00000020 /* 10 */
+#define FM_PCD_PLCR_PAR_PWSEL_PEGPC 0x00000010 /* 11 */
+#define FM_PCD_PLCR_PAR_PWSEL_PEYPC 0x00000008 /* 12 */
+#define FM_PCD_PLCR_PAR_PWSEL_PERPC 0x00000004 /* 13 */
+#define FM_PCD_PLCR_PAR_PWSEL_PERYPC 0x00000002 /* 14 */
+#define FM_PCD_PLCR_PAR_PWSEL_PERRPC 0x00000001 /* 15 */
+
+#define FM_PCD_PLCR_PAR_PMR_BRN_1TO1 0x0000 /* - Full bit replacement. {PBNUM[0:N-1]
+ 1-> 2^N specific locations. */
+#define FM_PCD_PLCR_PAR_PMR_BRN_2TO2 0x1 /* - {PBNUM[0:N-2],PNUM[N-1]}.
+ 2-> 2^(N-1) base locations. */
+#define FM_PCD_PLCR_PAR_PMR_BRN_4TO4 0x2 /* - {PBNUM[0:N-3],PNUM[N-2:N-1]}.
+ 4-> 2^(N-2) base locations. */
+#define FM_PCD_PLCR_PAR_PMR_BRN_8TO8 0x3 /* - {PBNUM[0:N-4],PNUM[N-3:N-1]}.
+ 8->2^(N-3) base locations. */
+#define FM_PCD_PLCR_PAR_PMR_BRN_16TO16 0x4 /* - {PBNUM[0:N-5],PNUM[N-4:N-1]}.
+ 16-> 2^(N-4) base locations. */
+#define FM_PCD_PLCR_PAR_PMR_BRN_32TO32 0x5 /* {PBNUM[0:N-6],PNUM[N-5:N-1]}.
+ 32-> 2^(N-5) base locations. */
+#define FM_PCD_PLCR_PAR_PMR_BRN_64TO64 0x6 /* {PBNUM[0:N-7],PNUM[N-6:N-1]}.
+ 64-> 2^(N-6) base locations. */
+#define FM_PCD_PLCR_PAR_PMR_BRN_128TO128 0x7 /* {PBNUM[0:N-8],PNUM[N-7:N-1]}.
+ 128-> 2^(N-7) base locations. */
+#define FM_PCD_PLCR_PAR_PMR_BRN_256TO256 0x8 /* - No bit replacement for N=8. {PNUM[N-8:N-1]}.
+ When N=8 this option maps all 256 profiles by the DISPATCH bus into one group. */
+
+#define FM_PCD_PLCR_PMR_V 0x80000000
+#define PLCR_ERR_ECC_CAP 0x80000000
+#define PLCR_ERR_ECC_TYPE_DOUBLE 0x40000000
+#define PLCR_ERR_ECC_PNUM_MASK 0x00000FF0
+#define PLCR_ERR_ECC_OFFSET_MASK 0x0000000F
+
+#define PLCR_ERR_UNINIT_CAP 0x80000000
+#define PLCR_ERR_UNINIT_NUM_MASK 0x000000FF
+#define PLCR_ERR_UNINIT_PID_MASK 0x003f0000
+#define PLCR_ERR_UNINIT_ABSOLUTE_MASK 0x00008000
+
+/* shifts */
+#define PLCR_ERR_ECC_PNUM_SHIFT 4
+#define PLCR_ERR_UNINIT_PID_SHIFT 16
+
+#define FM_PCD_PLCR_PMR_BRN_SHIFT 16
+
+#define PLCR_PORT_WINDOW_SIZE(hardwarePortId)
+
+
+#endif /* __FM_PLCR_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_prs.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_prs.c
new file mode 100644
index 0000000..1666865
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_prs.c
@@ -0,0 +1,465 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_pcd.c
+
+ @Description FM PCD ...
+*//***************************************************************************/
+#include "std_ext.h"
+#include "error_ext.h"
+#include "string_ext.h"
+#include "debug_ext.h"
+#include "net_ext.h"
+
+#include "fm_common.h"
+#include "fm_pcd.h"
+#include "fm_pcd_ipc.h"
+#include "fm_prs.h"
+#include "fsl_fman_prs.h"
+
+
+static void PcdPrsErrorException(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint32_t event, ev_mask;
+ struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs;
+
+ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID);
+ ev_mask = fman_prs_get_err_ev_mask(PrsRegs);
+
+ event = fman_prs_get_err_event(PrsRegs, ev_mask);
+
+ fman_prs_ack_err_event(PrsRegs, event);
+
+ DBG(TRACE, ("parser error - 0x%08x\n",event));
+
+ if(event & FM_PCD_PRS_DOUBLE_ECC)
+ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC);
+}
+
+static void PcdPrsException(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ uint32_t event, ev_mask;
+ struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs;
+
+ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID);
+ ev_mask = fman_prs_get_expt_ev_mask(PrsRegs);
+ event = fman_prs_get_expt_event(PrsRegs, ev_mask);
+
+ ASSERT_COND(event & FM_PCD_PRS_SINGLE_ECC);
+
+ DBG(TRACE, ("parser event - 0x%08x\n",event));
+
+ fman_prs_ack_expt_event(PrsRegs, event);
+
+ p_FmPcd->f_Exception(p_FmPcd->h_App,e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC);
+}
+
+t_Handle PrsConfig(t_FmPcd *p_FmPcd,t_FmPcdParams *p_FmPcdParams)
+{
+ t_FmPcdPrs *p_FmPcdPrs;
+ uintptr_t baseAddr;
+
+ UNUSED(p_FmPcd);
+ UNUSED(p_FmPcdParams);
+
+ p_FmPcdPrs = (t_FmPcdPrs *) XX_Malloc(sizeof(t_FmPcdPrs));
+ if (!p_FmPcdPrs)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Parser structure allocation FAILED"));
+ return NULL;
+ }
+ memset(p_FmPcdPrs, 0, sizeof(t_FmPcdPrs));
+ fman_prs_defconfig(&p_FmPcd->p_FmPcdDriverParam->dfltCfg);
+
+ if (p_FmPcd->guestId == NCSW_MASTER_ID)
+ {
+ baseAddr = FmGetPcdPrsBaseAddr(p_FmPcdParams->h_Fm);
+ p_FmPcdPrs->p_SwPrsCode = (uint32_t *)UINT_TO_PTR(baseAddr);
+ p_FmPcdPrs->p_FmPcdPrsRegs = (struct fman_prs_regs *)UINT_TO_PTR(baseAddr + PRS_REGS_OFFSET);
+ }
+
+ p_FmPcdPrs->fmPcdPrsPortIdStatistics = p_FmPcd->p_FmPcdDriverParam->dfltCfg.port_id_stat;
+ p_FmPcd->p_FmPcdDriverParam->prsMaxParseCycleLimit = p_FmPcd->p_FmPcdDriverParam->dfltCfg.max_prs_cyc_lim;
+ p_FmPcd->exceptions |= p_FmPcd->p_FmPcdDriverParam->dfltCfg.prs_exceptions;
+
+ return p_FmPcdPrs;
+}
+
+t_Error PrsInit(t_FmPcd *p_FmPcd)
+{
+ t_FmPcdDriverParam *p_Param = p_FmPcd->p_FmPcdDriverParam;
+ uint32_t *p_TmpCode;
+ uint32_t *p_LoadTarget = (uint32_t *)PTR_MOVE(p_FmPcd->p_FmPcdPrs->p_SwPrsCode,
+ FM_PCD_SW_PRS_SIZE-FM_PCD_PRS_SW_PATCHES_SIZE);
+ struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs;
+#ifdef FM_CAPWAP_SUPPORT
+ uint8_t swPrsPatch[] = SW_PRS_UDP_LITE_PATCH;
+#else
+ uint8_t swPrsPatch[] = SW_PRS_IP_FRAG_PATCH;
+#endif /* FM_CAPWAP_SUPPORT */
+ uint32_t i;
+
+ ASSERT_COND(sizeof(swPrsPatch) <= (FM_PCD_PRS_SW_PATCHES_SIZE-FM_PCD_PRS_SW_TAIL_SIZE));
+
+ /* nothing to do in guest-partition */
+ if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ return E_OK;
+
+ p_TmpCode = (uint32_t *)XX_MallocSmart(ROUND_UP(sizeof(swPrsPatch),4), 0, sizeof(uint32_t));
+ if (!p_TmpCode)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Tmp Sw-Parser code allocation FAILED"));
+ memset((uint8_t *)p_TmpCode, 0, ROUND_UP(sizeof(swPrsPatch),4));
+ memcpy((uint8_t *)p_TmpCode, (uint8_t *)swPrsPatch, sizeof(swPrsPatch));
+
+ fman_prs_init(PrsRegs, &p_Param->dfltCfg);
+
+ /* register even if no interrupts enabled, to allow future enablement */
+ FmRegisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_ERR, PcdPrsErrorException, p_FmPcd);
+
+ /* register even if no interrupts enabled, to allow future enablement */
+ FmRegisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_NORMAL, PcdPrsException, p_FmPcd);
+
+ if(p_FmPcd->exceptions & FM_PCD_EX_PRS_SINGLE_ECC)
+ FmEnableRamsEcc(p_FmPcd->h_Fm);
+
+ if(p_FmPcd->exceptions & FM_PCD_EX_PRS_DOUBLE_ECC)
+ FmEnableRamsEcc(p_FmPcd->h_Fm);
+
+ /* load sw parser Ip-Frag patch */
+ for (i=0; i<DIV_CEIL(sizeof(swPrsPatch),4); i++)
+ WRITE_UINT32(p_LoadTarget[i], p_TmpCode[i]);
+
+ XX_FreeSmart(p_TmpCode);
+
+ return E_OK;
+}
+
+void PrsFree(t_FmPcd *p_FmPcd)
+{
+ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID);
+ FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_ERR);
+ /* register even if no interrupts enabled, to allow future enablement */
+ FmUnregisterIntr(p_FmPcd->h_Fm, e_FM_MOD_PRS, 0, e_FM_INTR_TYPE_NORMAL);
+}
+
+void PrsEnable(t_FmPcd *p_FmPcd)
+{
+ struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs;
+
+ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID);
+ fman_prs_enable(PrsRegs);
+}
+
+void PrsDisable(t_FmPcd *p_FmPcd)
+{
+ struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs;
+
+ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID);
+ fman_prs_disable(PrsRegs);
+}
+
+int PrsIsEnabled(t_FmPcd *p_FmPcd)
+{
+ struct fman_prs_regs *PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs;
+
+ ASSERT_COND(p_FmPcd->guestId == NCSW_MASTER_ID);
+ return fman_prs_is_enabled(PrsRegs);
+}
+
+t_Error PrsIncludePortInStatistics(t_FmPcd *p_FmPcd, uint8_t hardwarePortId, bool include)
+{
+ struct fman_prs_regs *PrsRegs;
+ uint32_t bitMask = 0;
+ uint8_t prsPortId;
+
+ SANITY_CHECK_RETURN_ERROR((hardwarePortId >=1 && hardwarePortId <= 16), E_INVALID_VALUE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPrs, E_INVALID_HANDLE);
+
+ PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs;
+
+ GET_FM_PCD_PRS_PORT_ID(prsPortId, hardwarePortId);
+ GET_FM_PCD_INDEX_FLAG(bitMask, prsPortId);
+
+ if (include)
+ p_FmPcd->p_FmPcdPrs->fmPcdPrsPortIdStatistics |= bitMask;
+ else
+ p_FmPcd->p_FmPcdPrs->fmPcdPrsPortIdStatistics &= ~bitMask;
+
+ fman_prs_set_stst_port_msk(PrsRegs,
+ p_FmPcd->p_FmPcdPrs->fmPcdPrsPortIdStatistics);
+
+ return E_OK;
+}
+
+t_Error FmPcdPrsIncludePortInStatistics(t_Handle h_FmPcd, uint8_t hardwarePortId, bool include)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR((hardwarePortId >=1 && hardwarePortId <= 16), E_INVALID_VALUE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPrs, E_INVALID_HANDLE);
+
+ if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&
+ p_FmPcd->h_IpcSession)
+ {
+ t_FmPcdIpcPrsIncludePort prsIncludePortParams;
+ t_FmPcdIpcMsg msg;
+
+ prsIncludePortParams.hardwarePortId = hardwarePortId;
+ prsIncludePortParams.include = include;
+ memset(&msg, 0, sizeof(msg));
+ msg.msgId = FM_PCD_PRS_INC_PORT_STATS;
+ memcpy(msg.msgBody, &prsIncludePortParams, sizeof(prsIncludePortParams));
+ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) +sizeof(prsIncludePortParams),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ return E_OK;
+ }
+ else if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without IPC!"));
+
+ return PrsIncludePortInStatistics(p_FmPcd, hardwarePortId, include);
+}
+
+uint32_t FmPcdGetSwPrsOffset(t_Handle h_FmPcd, e_NetHeaderType hdr, uint8_t indexPerHdr)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd *)h_FmPcd;
+ t_FmPcdPrsLabelParams *p_Label;
+ int i;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPcd, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_VALUE(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE, 0);
+
+ if ((p_FmPcd->guestId != NCSW_MASTER_ID) &&
+ p_FmPcd->h_IpcSession)
+ {
+ t_Error err = E_OK;
+ t_FmPcdIpcSwPrsLable labelParams;
+ t_FmPcdIpcMsg msg;
+ uint32_t prsOffset = 0;
+ t_FmPcdIpcReply reply;
+ uint32_t replyLength;
+
+ memset(&reply, 0, sizeof(reply));
+ memset(&msg, 0, sizeof(msg));
+ labelParams.enumHdr = (uint32_t)hdr;
+ labelParams.indexPerHdr = indexPerHdr;
+ msg.msgId = FM_PCD_GET_SW_PRS_OFFSET;
+ memcpy(msg.msgBody, &labelParams, sizeof(labelParams));
+ replyLength = sizeof(uint32_t) + sizeof(uint32_t);
+ err = XX_IpcSendMessage(p_FmPcd->h_IpcSession,
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) +sizeof(labelParams),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t) + sizeof(uint32_t))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+
+ memcpy((uint8_t*)&prsOffset, reply.replyBody, sizeof(uint32_t));
+ return prsOffset;
+ }
+ else if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without IPC!"));
+
+ ASSERT_COND(p_FmPcd->p_FmPcdPrs->currLabel < FM_PCD_PRS_NUM_OF_LABELS);
+
+ for (i=0; i<p_FmPcd->p_FmPcdPrs->currLabel; i++)
+ {
+ p_Label = &p_FmPcd->p_FmPcdPrs->labelsTable[i];
+
+ if ((hdr == p_Label->hdr) && (indexPerHdr == p_Label->indexPerHdr))
+ return p_Label->instructionOffset;
+ }
+
+ REPORT_ERROR(MAJOR, E_NOT_FOUND, ("Sw Parser attachment Not found"));
+ return (uint32_t)ILLEGAL_BASE;
+}
+
+void FM_PCD_SetPrsStatistics(t_Handle h_FmPcd, bool enable)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ struct fman_prs_regs *PrsRegs;
+
+ SANITY_CHECK_RETURN(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN(p_FmPcd->p_FmPcdPrs, E_INVALID_HANDLE);
+
+ PrsRegs = (struct fman_prs_regs *)p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs;
+
+
+ if(p_FmPcd->guestId != NCSW_MASTER_ID)
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_SetPrsStatistics - guest mode!"));
+ return;
+ }
+
+ fman_prs_set_stst(PrsRegs, enable);
+}
+
+t_Error FM_PCD_PrsLoadSw(t_Handle h_FmPcd, t_FmPcdPrsSwParams *p_SwPrs)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+ uint32_t *p_LoadTarget;
+ uint32_t *p_TmpCode;
+ int i;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPrs, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_SwPrs, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->enabled, E_INVALID_HANDLE);
+
+ if (p_FmPcd->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM in guest-mode!"));
+
+ if (!p_SwPrs->override)
+ {
+ if(p_FmPcd->p_FmPcdPrs->p_CurrSwPrs > p_FmPcd->p_FmPcdPrs->p_SwPrsCode + p_SwPrs->base*2/4)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("SW parser base must be larger than current loaded code"));
+ }
+ else
+ p_FmPcd->p_FmPcdPrs->currLabel = 0;
+
+ if (p_SwPrs->size > FM_PCD_SW_PRS_SIZE - FM_PCD_PRS_SW_TAIL_SIZE - p_SwPrs->base*2)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("p_SwPrs->size may not be larger than MAX_SW_PRS_CODE_SIZE"));
+
+ if (p_FmPcd->p_FmPcdPrs->currLabel + p_SwPrs->numOfLabels > FM_PCD_PRS_NUM_OF_LABELS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exceeded number of labels allowed "));
+
+ p_TmpCode = (uint32_t *)XX_MallocSmart(ROUND_UP(p_SwPrs->size,4), 0, sizeof(uint32_t));
+ if (!p_TmpCode)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Tmp Sw-Parser code allocation FAILED"));
+ memset((uint8_t *)p_TmpCode, 0, ROUND_UP(p_SwPrs->size,4));
+ memcpy((uint8_t *)p_TmpCode, p_SwPrs->p_Code, p_SwPrs->size);
+
+ /* save sw parser labels */
+ memcpy(&p_FmPcd->p_FmPcdPrs->labelsTable[p_FmPcd->p_FmPcdPrs->currLabel],
+ p_SwPrs->labelsTable,
+ p_SwPrs->numOfLabels*sizeof(t_FmPcdPrsLabelParams));
+ p_FmPcd->p_FmPcdPrs->currLabel += p_SwPrs->numOfLabels;
+
+ /* load sw parser code */
+ p_LoadTarget = p_FmPcd->p_FmPcdPrs->p_SwPrsCode + p_SwPrs->base*2/4;
+ for(i=0; i<DIV_CEIL(p_SwPrs->size,4); i++)
+ WRITE_UINT32(p_LoadTarget[i], p_TmpCode[i]);
+ p_FmPcd->p_FmPcdPrs->p_CurrSwPrs =
+ p_FmPcd->p_FmPcdPrs->p_SwPrsCode + p_SwPrs->base*2/4 + ROUND_UP(p_SwPrs->size,4);
+
+ /* copy data parameters */
+ for (i=0;i<FM_PCD_PRS_NUM_OF_HDRS;i++)
+ WRITE_UINT32(*(p_FmPcd->p_FmPcdPrs->p_SwPrsCode+PRS_SW_DATA/4+i), p_SwPrs->swPrsDataParams[i]);
+
+ /* Clear last 4 bytes */
+ WRITE_UINT32(*(p_FmPcd->p_FmPcdPrs->p_SwPrsCode+(PRS_SW_DATA-FM_PCD_PRS_SW_TAIL_SIZE)/4), 0);
+
+ XX_FreeSmart(p_TmpCode);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_ConfigPrsMaxCycleLimit(t_Handle h_FmPcd,uint16_t value)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdDriverParam, E_INVALID_HANDLE);
+
+ if(p_FmPcd->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PCD_ConfigPrsMaxCycleLimit - guest mode!"));
+
+ p_FmPcd->p_FmPcdDriverParam->prsMaxParseCycleLimit = value;
+
+ return E_OK;
+}
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+t_Error FM_PCD_PrsDumpRegs(t_Handle h_FmPcd)
+{
+ t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd;
+
+ DECLARE_DUMP;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPcd->p_FmPcdPrs, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPcd->p_FmPcdDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(((p_FmPcd->guestId == NCSW_MASTER_ID) ||
+ p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs), E_INVALID_OPERATION);
+
+ DUMP_SUBTITLE(("\n"));
+ DUMP_TITLE(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs, ("FM-PCD parser regs"));
+
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_rpclim);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_rpimac);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,pmeec);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_pevr);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_pever);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_perr);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_perer);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_ppsc);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_pds);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_l2rrs);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_l3rrs);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_l4rrs);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_srrs);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_l2rres);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_l3rres);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_l4rres);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_srres);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_spcs);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_spscs);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_hxscs);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_mrcs);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_mwcs);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_mrscs);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_mwscs);
+ DUMP_VAR(p_FmPcd->p_FmPcdPrs->p_FmPcdPrsRegs,fmpr_fcscs);
+
+ return E_OK;
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_prs.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_prs.h
new file mode 100644
index 0000000..3e5974c5
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_prs.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_prs.h
+
+ @Description FM Parser private header
+*//***************************************************************************/
+#ifndef __FM_PRS_H
+#define __FM_PRS_H
+
+#include "std_ext.h"
+
+
+/***********************************************************************/
+/* SW parser IP_FRAG patch */
+/***********************************************************************/
+
+
+#ifdef FM_CAPWAP_SUPPORT
+#define SW_PRS_UDP_LITE_PATCH \
+{\
+ 0x31,0x92,0x50,0x29,0x00,0x88,0x08,0x16,0x00,0x00, \
+ 0x00,0x01,0x00,0x05,0x00,0x81,0x1C,0x0B,0x00,0x01, \
+ 0x1B,0xFF, \
+}
+#endif /* FM_CAPWAP_SUPPORT */
+
+#if (DPAA_VERSION == 10)
+/* Version: 106.1.9 */
+#define SW_PRS_IP_FRAG_PATCH \
+{ \
+ 0x31,0x52,0x00,0xDA,0x0A,0x00,0x00,0x00,0x00,0x00, \
+ 0x00,0x00,0x43,0x0A,0x00,0x00,0x00,0x01,0x1B,0xFE, \
+ 0x00,0x00,0x99,0x00,0x53,0x13,0x00,0x00,0x00,0x00, \
+ 0x9F,0x98,0x53,0x13,0x00,0x00,0x1B,0x23,0x33,0xF1, \
+ 0x00,0xF9,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00, \
+ 0x28,0x7F,0x00,0x03,0x00,0x02,0x00,0x00,0x00,0x01, \
+ 0x32,0xC1,0x32,0xF0,0x00,0x4A,0x00,0x80,0x1F,0xFF, \
+ 0x00,0x01,0x1B,0xFE,0x31,0x52,0x00,0xDA,0x06,0x00, \
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x2F,0x00,0x00, \
+ 0x00,0x01,0x1B,0xFE,0x31,0x52,0x00,0xDA,0x00,0x40, \
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x95,0x00,0x00, \
+ 0x00,0x00,0x9B,0x8F,0x2F,0x0F,0x32,0xC1,0x00,0x55, \
+ 0x00,0x28,0x28,0x43,0x30,0x7E,0x43,0x45,0x00,0x00, \
+ 0x30,0x7E,0x43,0x45,0x00,0x3C,0x1B,0x5D,0x32,0x11, \
+ 0x32,0xC0,0x00,0x4F,0x00,0x81,0x00,0x00,0x83,0x8F, \
+ 0x2F,0x0F,0x06,0x00,0x32,0x11,0x32,0xC0,0x00,0x4F, \
+ 0x00,0x55,0x00,0x01,0x00,0x81,0x32,0x11,0x00,0x00, \
+ 0x83,0x8E,0x00,0x50,0x00,0x01,0x01,0x04,0x00,0x4D, \
+ 0x28,0x43,0x06,0x00,0x1B,0x3E,0x30,0x7E,0x53,0x79, \
+ 0x00,0x2B,0x32,0x11,0x32,0xC0,0x00,0x4F,0x00,0x81, \
+ 0x00,0x00,0x87,0x8F,0x28,0x23,0x06,0x00,0x32,0x11, \
+ 0x32,0xC0,0x00,0x4F,0x00,0x55,0x00,0x01,0x00,0x81, \
+ 0x32,0x11,0x00,0x00,0x83,0x8E,0x00,0x50,0x00,0x01, \
+ 0x01,0x04,0x00,0x4D,0x28,0x43,0x06,0x00,0x00,0x01, \
+ 0x1B,0xFE,0x00,0x00,0x9B,0x8E,0x53,0x90,0x00,0x00, \
+ 0x06,0x29,0x00,0x00,0x83,0x8F,0x28,0x23,0x06,0x00, \
+ 0x06,0x29,0x32,0xC1,0x00,0x55,0x00,0x28,0x00,0x00, \
+ 0x83,0x8E,0x00,0x50,0x00,0x01,0x01,0x04,0x00,0x4D, \
+ 0x28,0x43,0x06,0x00,0x00,0x01,0x1B,0xFE,0x32,0xC1, \
+ 0x00,0x55,0x00,0x28,0x28,0x43,0x1B,0xCF,0x00,0x00, \
+ 0x9B,0x8F,0x2F,0x0F,0x32,0xC1,0x00,0x55,0x00,0x28, \
+ 0x28,0x43,0x30,0x7E,0x43,0xBF,0x00,0x2C,0x32,0x11, \
+ 0x32,0xC0,0x00,0x4F,0x00,0x81,0x00,0x00,0x87,0x8F, \
+ 0x28,0x23,0x06,0x00,0x32,0x11,0x32,0xC0,0x00,0x4F, \
+ 0x00,0x81,0x00,0x00,0x83,0x8F,0x2F,0x0F,0x06,0x00, \
+ 0x32,0x11,0x32,0xC0,0x00,0x4F,0x00,0x55,0x00,0x01, \
+ 0x00,0x81,0x32,0x11,0x00,0x00,0x83,0x8E,0x00,0x50, \
+ 0x00,0x01,0x01,0x04,0x00,0x4D,0x28,0x43,0x06,0x00, \
+ 0x1B,0x9C,0x33,0xF1,0x00,0xF9,0x00,0x01,0x00,0x00, \
+ 0x00,0x00,0x00,0x00,0x28,0x7F,0x00,0x03,0x00,0x02, \
+ 0x00,0x00,0x00,0x01,0x32,0xC1,0x32,0xF0,0x00,0x4A, \
+ 0x00,0x80,0x1F,0xFF,0x00,0x01,0x1B,0xFE, \
+}
+
+#else
+/* version: 106.3.13 */
+#define SW_PRS_IP_FRAG_PATCH \
+{ \
+ 0x31,0x52,0x00,0xDA,0x0E,0x4F,0x00,0x00,0x00,0x00, \
+ 0x00,0x00,0x52,0xF6,0x08,0x4B,0x31,0x53,0x00,0xFB, \
+ 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x29,0x2B, \
+ 0x33,0xF1,0x00,0xFB,0x00,0xDF,0x00,0x00,0x00,0x00, \
+ 0x00,0x00,0x28,0x7F,0x31,0x52,0x00,0xDA,0x0A,0x00, \
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x00,0x00,0x00, \
+ 0x00,0x01,0x1B,0xFE,0x00,0x00,0x99,0x00,0x53,0x09, \
+ 0x00,0x00,0x00,0x00,0x9F,0x98,0x53,0x09,0x00,0x00, \
+ 0x1B,0x24,0x09,0x5F,0x00,0x20,0x00,0x00,0x09,0x4F, \
+ 0x00,0x20,0x00,0x00,0x34,0xB7,0x00,0xF9,0x00,0x00, \
+ 0x01,0x00,0x00,0x00,0x00,0x00,0x2B,0x97,0x31,0xB3, \
+ 0x29,0x8F,0x33,0xF1,0x00,0xF9,0x00,0x01,0x00,0x00, \
+ 0x00,0x00,0x00,0x00,0x28,0x7F,0x00,0x03,0x00,0x02, \
+ 0x00,0x00,0x00,0x01,0x1B,0xFE,0x00,0x01,0x1B,0xFE, \
+ 0x31,0x52,0x00,0xDA,0x0E,0x4F,0x00,0x00,0x00,0x00, \
+ 0x00,0x00,0x53,0x3C,0x04,0x4B,0x31,0x53,0x00,0xFB, \
+ 0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x29,0x2B, \
+ 0x33,0xF1,0x00,0xFB,0x00,0xDF,0x00,0x00,0x00,0x00, \
+ 0x00,0x00,0x28,0x7F,0x31,0x52,0x00,0xDA,0x06,0x00, \
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x46,0x00,0x00, \
+ 0x00,0x01,0x1B,0xFE,0x31,0x52,0x00,0xDA,0x00,0x40, \
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x53,0xAC,0x00,0x00, \
+ 0x00,0x00,0x9B,0x8F,0x2F,0x0F,0x32,0xC1,0x00,0x55, \
+ 0x00,0x28,0x28,0x43,0x30,0x7E,0x43,0x5C,0x00,0x00, \
+ 0x30,0x7E,0x43,0x5C,0x00,0x3C,0x1B,0x74,0x32,0x11, \
+ 0x32,0xC0,0x00,0x4F,0x00,0x81,0x00,0x00,0x83,0x8F, \
+ 0x2F,0x0F,0x06,0x00,0x32,0x11,0x32,0xC0,0x00,0x4F, \
+ 0x00,0x55,0x00,0x01,0x00,0x81,0x32,0x11,0x00,0x00, \
+ 0x83,0x8E,0x00,0x50,0x00,0x01,0x01,0x04,0x00,0x4D, \
+ 0x28,0x43,0x06,0x00,0x1B,0x55,0x30,0x7E,0x53,0x90, \
+ 0x00,0x2B,0x32,0x11,0x32,0xC0,0x00,0x4F,0x00,0x81, \
+ 0x00,0x00,0x87,0x8F,0x28,0x23,0x06,0x00,0x32,0x11, \
+ 0x32,0xC0,0x00,0x4F,0x00,0x55,0x00,0x01,0x00,0x81, \
+ 0x32,0x11,0x00,0x00,0x83,0x8E,0x00,0x50,0x00,0x01, \
+ 0x01,0x04,0x00,0x4D,0x28,0x43,0x06,0x00,0x00,0x01, \
+ 0x1B,0xFE,0x00,0x00,0x9B,0x8E,0x53,0xA7,0x00,0x00, \
+ 0x06,0x29,0x00,0x00,0x83,0x8F,0x28,0x23,0x06,0x00, \
+ 0x06,0x29,0x32,0xC1,0x00,0x55,0x00,0x28,0x00,0x00, \
+ 0x83,0x8E,0x00,0x50,0x00,0x01,0x01,0x04,0x00,0x4D, \
+ 0x28,0x43,0x06,0x00,0x00,0x01,0x1B,0xFE,0x32,0xC1, \
+ 0x00,0x55,0x00,0x28,0x28,0x43,0x1B,0xF1,0x00,0x00, \
+ 0x9B,0x8F,0x2F,0x0F,0x32,0xC1,0x00,0x55,0x00,0x28, \
+ 0x28,0x43,0x30,0x7E,0x43,0xD6,0x00,0x2C,0x32,0x11, \
+ 0x32,0xC0,0x00,0x4F,0x00,0x81,0x00,0x00,0x87,0x8F, \
+ 0x28,0x23,0x06,0x00,0x32,0x11,0x32,0xC0,0x00,0x4F, \
+ 0x00,0x81,0x00,0x00,0x83,0x8F,0x2F,0x0F,0x06,0x00, \
+ 0x32,0x11,0x32,0xC0,0x00,0x4F,0x00,0x55,0x00,0x01, \
+ 0x00,0x81,0x32,0x11,0x00,0x00,0x83,0x8E,0x00,0x50, \
+ 0x00,0x01,0x01,0x04,0x00,0x4D,0x28,0x43,0x06,0x00, \
+ 0x1B,0xB3,0x09,0x5F,0x00,0x20,0x00,0x00,0x09,0x4F, \
+ 0x00,0x20,0x00,0x00,0x34,0xB7,0x00,0xF9,0x00,0x00, \
+ 0x01,0x00,0x00,0x00,0x00,0x00,0x2B,0x97,0x31,0xB3, \
+ 0x29,0x8F,0x33,0xF1,0x00,0xF9,0x00,0x01,0x00,0x00, \
+ 0x00,0x00,0x00,0x00,0x28,0x7F,0x00,0x03,0x00,0x02, \
+ 0x00,0x00,0x00,0x01,0x1B,0xFE,0x00,0x01,0x1B,0xFE, \
+}
+#endif /* (DPAA_VERSION == 10) */
+
+/****************************/
+/* Parser defines */
+/****************************/
+#define FM_PCD_PRS_SW_TAIL_SIZE 4 /**< Number of bytes that must be cleared at
+ the end of the SW parser area */
+
+/* masks */
+#define PRS_ERR_CAP 0x80000000
+#define PRS_ERR_TYPE_DOUBLE 0x40000000
+#define PRS_ERR_SINGLE_ECC_CNT_MASK 0x00FF0000
+#define PRS_ERR_ADDR_MASK 0x000001FF
+
+/* others */
+#define PRS_MAX_CYCLE_LIMIT 8191
+#define PRS_SW_DATA 0x00000800
+#define PRS_REGS_OFFSET 0x00000840
+
+#define GET_FM_PCD_PRS_PORT_ID(prsPortId,hardwarePortId) \
+ prsPortId = (uint8_t)(hardwarePortId & 0x0f)
+
+#define GET_FM_PCD_INDEX_FLAG(bitMask, prsPortId) \
+ bitMask = 0x80000000>>prsPortId
+
+
+#endif /* __FM_PRS_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_replic.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_replic.c
new file mode 100644
index 0000000..7f84080
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_replic.c
@@ -0,0 +1,994 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_replic.c
+
+ @Description FM frame replicator
+*//***************************************************************************/
+#include "std_ext.h"
+#include "error_ext.h"
+#include "string_ext.h"
+#include "debug_ext.h"
+#include "fm_pcd_ext.h"
+#include "fm_muram_ext.h"
+#include "fm_common.h"
+#include "fm_hc.h"
+#include "fm_replic.h"
+#include "fm_cc.h"
+#include "list_ext.h"
+
+
+/****************************************/
+/* static functions */
+/****************************************/
+static uint8_t GetMemberPosition(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ uint32_t memberIndex,
+ bool isAddOperation)
+{
+ uint8_t memberPosition;
+ uint32_t lastMemberIndex;
+
+ ASSERT_COND(p_ReplicGroup);
+
+ /* the last member index is different between add and remove operation -
+ in case of remove - this is exactly the last member index
+ in case of add - this is the last member index + 1 - e.g.
+ if we have 4 members, the index of the actual last member is 3(because the
+ index starts from 0) therefore in order to add a new member as the last
+ member we shall use memberIndex = 4 and not 3
+ */
+ if (isAddOperation)
+ lastMemberIndex = p_ReplicGroup->numOfEntries;
+ else
+ lastMemberIndex = p_ReplicGroup->numOfEntries-1;
+
+ /* last */
+ if (memberIndex == lastMemberIndex)
+ memberPosition = FRM_REPLIC_LAST_MEMBER_INDEX;
+ else
+ {
+ /* first */
+ if (memberIndex == 0)
+ memberPosition = FRM_REPLIC_FIRST_MEMBER_INDEX;
+ else
+ {
+ /* middle */
+ ASSERT_COND(memberIndex < lastMemberIndex);
+ memberPosition = FRM_REPLIC_MIDDLE_MEMBER_INDEX;
+ }
+ }
+ return memberPosition;
+}
+
+static t_Error MemberCheckParams(t_Handle h_FmPcd,
+ t_FmPcdCcNextEngineParams *p_MemberParams)
+{
+ t_Error err;
+
+
+ if ((p_MemberParams->nextEngine != e_FM_PCD_DONE) &&
+ (p_MemberParams->nextEngine != e_FM_PCD_KG) &&
+ (p_MemberParams->nextEngine != e_FM_PCD_PLCR))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Next engine of a member should be MatchTable(cc) or Done or Policer"));
+
+ /* check the regular parameters of the next engine */
+ err = ValidateNextEngineParams(h_FmPcd, p_MemberParams, e_FM_PCD_CC_STATS_MODE_NONE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("member next engine parameters"));
+
+ return E_OK;
+}
+
+static t_Error CheckParams(t_Handle h_FmPcd,
+ t_FmPcdFrmReplicGroupParams *p_ReplicGroupParam)
+{
+ int i;
+ t_Error err;
+
+ /* check that max num of entries is at least 2 */
+ if (!IN_RANGE(2, p_ReplicGroupParam->maxNumOfEntries, FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES))
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ("maxNumOfEntries in the frame replicator parameters should be 2-%d",FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES));
+
+ /* check that number of entries is greater than zero */
+ if (!p_ReplicGroupParam->numOfEntries)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOFEntries in the frame replicator group should be greater than zero"));
+
+ /* check that max num of entries is equal or greater than number of entries */
+ if (p_ReplicGroupParam->maxNumOfEntries < p_ReplicGroupParam->numOfEntries)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("maxNumOfEntries should be equal or greater than numOfEntries"));
+
+ for (i=0; i<p_ReplicGroupParam->numOfEntries; i++)
+ {
+ err = MemberCheckParams(h_FmPcd, &p_ReplicGroupParam->nextEngineParams[i]);
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("member check parameters"));
+ }
+ return E_OK;
+}
+
+static t_FmPcdFrmReplicMember *GetAvailableMember(t_FmPcdFrmReplicGroup *p_ReplicGroup)
+{
+ t_FmPcdFrmReplicMember *p_ReplicMember = NULL;
+ t_List *p_Next;
+
+ if (!LIST_IsEmpty(&p_ReplicGroup->availableMembersList))
+ {
+ p_Next = LIST_FIRST(&p_ReplicGroup->availableMembersList);
+ p_ReplicMember = LIST_OBJECT(p_Next, t_FmPcdFrmReplicMember, node);
+ ASSERT_COND(p_ReplicMember);
+ LIST_DelAndInit(p_Next);
+ }
+ return p_ReplicMember;
+}
+
+static void PutAvailableMember(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ t_FmPcdFrmReplicMember *p_ReplicMember)
+{
+ LIST_AddToTail(&p_ReplicMember->node, &p_ReplicGroup->availableMembersList);
+}
+
+static void AddMemberToList(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ t_FmPcdFrmReplicMember *p_CurrentMember,
+ t_List *p_ListHead)
+{
+ LIST_Add(&p_CurrentMember->node, p_ListHead);
+
+ p_ReplicGroup->numOfEntries++;
+}
+
+static void RemoveMemberFromList(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ t_FmPcdFrmReplicMember *p_CurrentMember)
+{
+ ASSERT_COND(p_ReplicGroup->numOfEntries);
+ LIST_DelAndInit(&p_CurrentMember->node);
+ p_ReplicGroup->numOfEntries--;
+}
+
+static void LinkSourceToMember(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ t_AdOfTypeContLookup *p_SourceTd,
+ t_FmPcdFrmReplicMember *p_ReplicMember)
+{
+ t_FmPcd *p_FmPcd;
+
+ ASSERT_COND(p_SourceTd);
+ ASSERT_COND(p_ReplicMember);
+ ASSERT_COND(p_ReplicGroup);
+ ASSERT_COND(p_ReplicGroup->h_FmPcd);
+
+ /* Link the first member in the group to the source TD */
+ p_FmPcd = p_ReplicGroup->h_FmPcd;
+
+ WRITE_UINT32(p_SourceTd->matchTblPtr,
+ (uint32_t)(XX_VirtToPhys(p_ReplicMember->p_MemberAd) -
+ p_FmPcd->physicalMuramBase));
+}
+
+static void LinkMemberToMember(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ t_FmPcdFrmReplicMember *p_CurrentMember,
+ t_FmPcdFrmReplicMember *p_NextMember)
+{
+ t_AdOfTypeResult *p_CurrReplicAd = (t_AdOfTypeResult*)p_CurrentMember->p_MemberAd;
+ t_AdOfTypeResult *p_NextReplicAd = NULL;
+ t_FmPcd *p_FmPcd;
+ uint32_t offset = 0;
+
+ /* Check if the next member exists or it's NULL (- means that this is the last member) */
+ if (p_NextMember)
+ {
+ p_NextReplicAd = (t_AdOfTypeResult*)p_NextMember->p_MemberAd;
+ p_FmPcd = p_ReplicGroup->h_FmPcd;
+ offset = (XX_VirtToPhys(p_NextReplicAd) - (p_FmPcd->physicalMuramBase));
+ offset = ((offset>>NEXT_FRM_REPLIC_ADDR_SHIFT)<< NEXT_FRM_REPLIC_MEMBER_INDEX_SHIFT);
+ }
+
+ /* link the current AD to point to the AD of the next member */
+ WRITE_UINT32(p_CurrReplicAd->res, offset);
+}
+
+static t_Error ModifyDescriptor(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ void *p_OldDescriptor,
+ void *p_NewDescriptor)
+{
+ t_Handle h_Hc;
+ t_Error err;
+ t_FmPcd *p_FmPcd;
+
+ ASSERT_COND(p_ReplicGroup);
+ ASSERT_COND(p_ReplicGroup->h_FmPcd);
+ ASSERT_COND(p_OldDescriptor);
+ ASSERT_COND(p_NewDescriptor);
+
+ p_FmPcd = p_ReplicGroup->h_FmPcd;
+ h_Hc = FmPcdGetHcHandle(p_FmPcd);
+ if (!h_Hc)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("Host command"));
+
+ err = FmHcPcdCcDoDynamicChange(h_Hc,
+ (uint32_t)(XX_VirtToPhys(p_OldDescriptor) - p_FmPcd->physicalMuramBase),
+ (uint32_t)(XX_VirtToPhys(p_NewDescriptor) - p_FmPcd->physicalMuramBase));
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("Dynamic change host command"));
+
+ return E_OK;
+}
+
+static void FillReplicAdOfTypeResult(void *p_ReplicAd, bool last)
+{
+ t_AdOfTypeResult *p_CurrReplicAd = (t_AdOfTypeResult*)p_ReplicAd;
+ uint32_t tmp;
+
+ tmp = GET_UINT32(p_CurrReplicAd->plcrProfile);
+ if (last)
+ /* clear the NL bit in case it's the last member in the group*/
+ WRITE_UINT32(p_CurrReplicAd->plcrProfile,(tmp & ~FRM_REPLIC_NL_BIT));
+ else
+ /* set the NL bit in case it's not the last member in the group */
+ WRITE_UINT32(p_CurrReplicAd->plcrProfile, (tmp |FRM_REPLIC_NL_BIT));
+
+ /* set FR bit in the action descriptor */
+ tmp = GET_UINT32(p_CurrReplicAd->nia);
+ WRITE_UINT32(p_CurrReplicAd->nia,
+ (tmp | FRM_REPLIC_FR_BIT | FM_PCD_AD_RESULT_EXTENDED_MODE ));
+}
+
+static void BuildSourceTd(void *p_Ad)
+{
+ t_AdOfTypeContLookup *p_SourceTd;
+
+ ASSERT_COND(p_Ad);
+
+ p_SourceTd = (t_AdOfTypeContLookup *)p_Ad;
+
+ IOMemSet32((uint8_t*)p_SourceTd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ /* initialize the source table descriptor */
+ WRITE_UINT32(p_SourceTd->ccAdBase, FM_PCD_AD_CONT_LOOKUP_TYPE);
+ WRITE_UINT32(p_SourceTd->pcAndOffsets, FRM_REPLIC_SOURCE_TD_OPCODE);
+}
+
+static t_Error BuildShadowAndModifyDescriptor(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ t_FmPcdFrmReplicMember *p_NextMember,
+ t_FmPcdFrmReplicMember *p_CurrentMember,
+ bool sourceDescriptor,
+ bool last)
+{
+ t_FmPcd *p_FmPcd;
+ t_FmPcdFrmReplicMember shadowMember;
+ t_Error err;
+
+ ASSERT_COND(p_ReplicGroup);
+ ASSERT_COND(p_ReplicGroup->h_FmPcd);
+
+ p_FmPcd = p_ReplicGroup->h_FmPcd;
+ ASSERT_COND(p_FmPcd->p_CcShadow);
+
+ if (!TRY_LOCK(p_FmPcd->h_ShadowSpinlock, &p_FmPcd->shadowLock))
+ return ERROR_CODE(E_BUSY);
+
+ if (sourceDescriptor)
+ {
+ BuildSourceTd(p_FmPcd->p_CcShadow);
+ LinkSourceToMember(p_ReplicGroup, p_FmPcd->p_CcShadow, p_NextMember);
+
+ /* Modify the source table descriptor according to the prepared shadow descriptor */
+ err = ModifyDescriptor(p_ReplicGroup,
+ p_ReplicGroup->p_SourceTd,
+ p_FmPcd->p_CcShadow/* new prepared source td */);
+
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("Modify source Descriptor in BuildShadowAndModifyDescriptor"));
+
+ }
+ else
+ {
+ IO2IOCpy32(p_FmPcd->p_CcShadow,
+ p_CurrentMember->p_MemberAd,
+ FM_PCD_CC_AD_ENTRY_SIZE);
+
+ /* update the last bit in the shadow ad */
+ FillReplicAdOfTypeResult(p_FmPcd->p_CcShadow, last);
+
+ shadowMember.p_MemberAd = p_FmPcd->p_CcShadow;
+
+ /* update the next FR member index */
+ LinkMemberToMember(p_ReplicGroup, &shadowMember, p_NextMember);
+
+ /* Modify the next member according to the prepared shadow descriptor */
+ err = ModifyDescriptor(p_ReplicGroup,
+ p_CurrentMember->p_MemberAd,
+ p_FmPcd->p_CcShadow);
+
+ RELEASE_LOCK(p_FmPcd->shadowLock);
+ if (err)
+ RETURN_ERROR(MAJOR, err, ("Modify Descriptor in BuildShadowAndModifyDescriptor"));
+ }
+
+
+ return E_OK;
+}
+
+static t_FmPcdFrmReplicMember* GetMemberByIndex(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ uint16_t memberIndex)
+{
+ int i=0;
+ t_List *p_Pos;
+ t_FmPcdFrmReplicMember *p_Member = NULL;
+
+ LIST_FOR_EACH(p_Pos, &p_ReplicGroup->membersList)
+ {
+ if (i == memberIndex)
+ {
+ p_Member = LIST_OBJECT(p_Pos, t_FmPcdFrmReplicMember, node);
+ return p_Member;
+ }
+ i++;
+ }
+ return p_Member;
+}
+
+static t_Error AllocMember(t_FmPcdFrmReplicGroup *p_ReplicGroup)
+{
+ t_FmPcdFrmReplicMember *p_CurrentMember;
+ t_Handle h_Muram;
+
+ ASSERT_COND(p_ReplicGroup);
+
+ h_Muram = FmPcdGetMuramHandle(p_ReplicGroup->h_FmPcd);
+ ASSERT_COND(h_Muram);
+
+ /* Initialize an internal structure of a member to add to the available members list */
+ p_CurrentMember = (t_FmPcdFrmReplicMember *)XX_Malloc(sizeof(t_FmPcdFrmReplicMember));
+ if (!p_CurrentMember)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Frame replicator member"));
+
+ memset(p_CurrentMember, 0 ,sizeof(t_FmPcdFrmReplicMember));
+
+ /* Allocate the member AD */
+ p_CurrentMember->p_MemberAd =
+ (t_AdOfTypeResult*)FM_MURAM_AllocMem(h_Muram,
+ FM_PCD_CC_AD_ENTRY_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+
+ if (!p_CurrentMember->p_MemberAd)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("member AD table"));
+
+ IOMemSet32((uint8_t*)p_CurrentMember->p_MemberAd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ /* Add the new member to the available members list */
+ LIST_AddToTail(&p_CurrentMember->node, &(p_ReplicGroup->availableMembersList));
+
+ return E_OK;
+}
+
+static t_FmPcdFrmReplicMember* InitMember(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ t_FmPcdCcNextEngineParams *p_MemberParams,
+ bool last)
+{
+ t_FmPcdFrmReplicMember *p_CurrentMember = NULL;
+
+ ASSERT_COND(p_ReplicGroup);
+
+ /* Get an available member from the internal members list */
+ p_CurrentMember = GetAvailableMember(p_ReplicGroup);
+ if (!p_CurrentMember)
+ {
+ REPORT_ERROR(MAJOR, E_NOT_FOUND, ("Available member"));
+ return NULL;
+ }
+ p_CurrentMember->h_Manip = NULL;
+
+ /* clear the Ad of the new member */
+ IOMemSet32((uint8_t*)p_CurrentMember->p_MemberAd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+ INIT_LIST(&p_CurrentMember->node);
+
+ /* Initialize the Ad of the member */
+ NextStepAd(p_CurrentMember->p_MemberAd,
+ NULL,
+ p_MemberParams,
+ p_ReplicGroup->h_FmPcd);
+
+ /* save Manip handle (for free needs) */
+ if (p_MemberParams->h_Manip)
+ p_CurrentMember->h_Manip = p_MemberParams->h_Manip;
+
+ /* Initialize the relevant frame replicator fields in the AD */
+ FillReplicAdOfTypeResult(p_CurrentMember->p_MemberAd, last);
+
+ return p_CurrentMember;
+}
+
+static void FreeMember(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ t_FmPcdFrmReplicMember *p_Member)
+{
+ /* Note: Can't free the member AD just returns the member to the available
+ member list - therefore only memset the AD */
+
+ /* zero the AD */
+ IOMemSet32(p_Member->p_MemberAd, 0, FM_PCD_CC_AD_ENTRY_SIZE);
+
+
+ /* return the member to the available members list */
+ PutAvailableMember(p_ReplicGroup, p_Member);
+}
+
+static t_Error RemoveMember(t_FmPcdFrmReplicGroup *p_ReplicGroup,
+ uint16_t memberIndex)
+{
+ t_FmPcd *p_FmPcd = NULL;
+ t_FmPcdFrmReplicMember *p_CurrentMember = NULL, *p_PreviousMember = NULL, *p_NextMember = NULL;
+ t_Error err;
+ uint8_t memberPosition;
+
+ p_FmPcd = p_ReplicGroup->h_FmPcd;
+ ASSERT_COND(p_FmPcd);
+ UNUSED(p_FmPcd);
+
+ p_CurrentMember = GetMemberByIndex(p_ReplicGroup, memberIndex);
+ ASSERT_COND(p_CurrentMember);
+
+ /* determine the member position in the group */
+ memberPosition = GetMemberPosition(p_ReplicGroup,
+ memberIndex,
+ FALSE/*remove operation*/);
+
+ switch (memberPosition)
+ {
+ case FRM_REPLIC_FIRST_MEMBER_INDEX:
+ p_NextMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex+1));
+ ASSERT_COND(p_NextMember);
+
+ /* update the source td itself by using a host command */
+ err = BuildShadowAndModifyDescriptor(p_ReplicGroup,
+ p_NextMember,
+ NULL,
+ TRUE/*sourceDescriptor*/,
+ FALSE/*last*/);
+ break;
+
+ case FRM_REPLIC_MIDDLE_MEMBER_INDEX:
+ p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1));
+ ASSERT_COND(p_PreviousMember);
+
+ p_NextMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex+1));
+ ASSERT_COND(p_NextMember);
+
+ err = BuildShadowAndModifyDescriptor(p_ReplicGroup,
+ p_NextMember,
+ p_PreviousMember,
+ FALSE/*sourceDescriptor*/,
+ FALSE/*last*/);
+
+ break;
+
+ case FRM_REPLIC_LAST_MEMBER_INDEX:
+ p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1));
+ ASSERT_COND(p_PreviousMember);
+
+ err = BuildShadowAndModifyDescriptor(p_ReplicGroup,
+ NULL,
+ p_PreviousMember,
+ FALSE/*sourceDescriptor*/,
+ TRUE/*last*/);
+ break;
+
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("member position in remove member"));
+ }
+
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (p_CurrentMember->h_Manip)
+ {
+ FmPcdManipUpdateOwner(p_CurrentMember->h_Manip, FALSE);
+ p_CurrentMember->h_Manip = NULL;
+ }
+
+ /* remove the member from the driver internal members list */
+ RemoveMemberFromList(p_ReplicGroup, p_CurrentMember);
+
+ /* return the member to the available members list */
+ FreeMember(p_ReplicGroup, p_CurrentMember);
+
+ return E_OK;
+}
+
+static void DeleteGroup(t_FmPcdFrmReplicGroup *p_ReplicGroup)
+{
+ int i, j;
+ t_Handle h_Muram;
+ t_FmPcdFrmReplicMember *p_Member, *p_CurrentMember;
+
+ if (p_ReplicGroup)
+ {
+ ASSERT_COND(p_ReplicGroup->h_FmPcd);
+ h_Muram = FmPcdGetMuramHandle(p_ReplicGroup->h_FmPcd);
+ ASSERT_COND(h_Muram);
+
+ /* free the source table descriptor */
+ if (p_ReplicGroup->p_SourceTd)
+ {
+ FM_MURAM_FreeMem(h_Muram, p_ReplicGroup->p_SourceTd);
+ p_ReplicGroup->p_SourceTd = NULL;
+ }
+
+ /* Remove all members from the members linked list (hw and sw) and
+ return the members to the available members list */
+ if (p_ReplicGroup->numOfEntries)
+ {
+ j = p_ReplicGroup->numOfEntries-1;
+
+ /* manually removal of the member because there are no owners of
+ this group */
+ for (i=j; i>=0; i--)
+ {
+ p_CurrentMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)i/*memberIndex*/);
+ ASSERT_COND(p_CurrentMember);
+
+ if (p_CurrentMember->h_Manip)
+ {
+ FmPcdManipUpdateOwner(p_CurrentMember->h_Manip, FALSE);
+ p_CurrentMember->h_Manip = NULL;
+ }
+
+ /* remove the member from the internal driver members list */
+ RemoveMemberFromList(p_ReplicGroup, p_CurrentMember);
+
+ /* return the member to the available members list */
+ FreeMember(p_ReplicGroup, p_CurrentMember);
+ }
+ }
+
+ /* Free members AD */
+ for (i=0; i<p_ReplicGroup->maxNumOfEntries; i++)
+ {
+ p_Member = GetAvailableMember(p_ReplicGroup);
+ ASSERT_COND(p_Member);
+ if (p_Member->p_MemberAd)
+ {
+ FM_MURAM_FreeMem(h_Muram, p_Member->p_MemberAd);
+ p_Member->p_MemberAd = NULL;
+ }
+ XX_Free(p_Member);
+ }
+
+ /* release the group lock */
+ if (p_ReplicGroup->p_Lock)
+ FmPcdReleaseLock(p_ReplicGroup->h_FmPcd, p_ReplicGroup->p_Lock);
+
+ /* free the replicator group */
+ XX_Free(p_ReplicGroup);
+ p_ReplicGroup = NULL;
+ }
+}
+
+
+/*****************************************************************************/
+/* Inter-module API routines */
+/*****************************************************************************/
+
+/* NOTE: the inter-module routines are locked by cc in case of using them */
+void * FrmReplicGroupGetSourceTableDescriptor(t_Handle h_ReplicGroup)
+{
+ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
+ ASSERT_COND(p_ReplicGroup);
+
+ return (p_ReplicGroup->p_SourceTd);
+}
+
+void FrmReplicGroupUpdateAd(t_Handle h_ReplicGroup,
+ void *p_Ad,
+ t_Handle *h_AdNew)
+{
+ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
+ t_AdOfTypeResult *p_AdResult = (t_AdOfTypeResult*)p_Ad;
+ t_FmPcd *p_FmPcd;
+
+ ASSERT_COND(p_ReplicGroup);
+ p_FmPcd = p_ReplicGroup->h_FmPcd;
+
+ /* build a bypass ad */
+ WRITE_UINT32(p_AdResult->fqid, FM_PCD_AD_BYPASS_TYPE |
+ (uint32_t)((XX_VirtToPhys(p_ReplicGroup->p_SourceTd)) - p_FmPcd->physicalMuramBase));
+
+ *h_AdNew = NULL;
+}
+
+void FrmReplicGroupUpdateOwner(t_Handle h_ReplicGroup,
+ bool add)
+{
+ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
+ ASSERT_COND(p_ReplicGroup);
+
+ /* update the group owner counter */
+ if (add)
+ p_ReplicGroup->owners++;
+ else
+ {
+ ASSERT_COND(p_ReplicGroup->owners);
+ p_ReplicGroup->owners--;
+ }
+}
+
+t_Error FrmReplicGroupTryLock(t_Handle h_ReplicGroup)
+{
+ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
+
+ ASSERT_COND(h_ReplicGroup);
+
+ if (FmPcdLockTryLock(p_ReplicGroup->p_Lock))
+ return E_OK;
+
+ return ERROR_CODE(E_BUSY);
+}
+
+void FrmReplicGroupUnlock(t_Handle h_ReplicGroup)
+{
+ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
+
+ ASSERT_COND(h_ReplicGroup);
+
+ FmPcdLockUnlock(p_ReplicGroup->p_Lock);
+}
+/*********************** End of inter-module routines ************************/
+
+
+/****************************************/
+/* API Init unit functions */
+/****************************************/
+t_Handle FM_PCD_FrmReplicSetGroup(t_Handle h_FmPcd,
+ t_FmPcdFrmReplicGroupParams *p_ReplicGroupParam)
+{
+ t_FmPcdFrmReplicGroup *p_ReplicGroup;
+ t_FmPcdFrmReplicMember *p_CurrentMember, *p_NextMember = NULL;
+ int i;
+ t_Error err;
+ bool last = FALSE;
+ t_Handle h_Muram;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmPcd, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(p_ReplicGroupParam, E_INVALID_HANDLE, NULL);
+
+ if (!FmPcdIsAdvancedOffloadSupported(h_FmPcd))
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Advanced-offload must be enabled"));
+ return NULL;
+ }
+
+ err = CheckParams(h_FmPcd, p_ReplicGroupParam);
+ if (err)
+ {
+ REPORT_ERROR(MAJOR, err, (NO_MSG));
+ return NULL;
+ }
+
+ p_ReplicGroup = (t_FmPcdFrmReplicGroup*)XX_Malloc(sizeof(t_FmPcdFrmReplicGroup));
+ if (!p_ReplicGroup)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("No memory"));
+ return NULL;
+ }
+ memset(p_ReplicGroup, 0, sizeof(t_FmPcdFrmReplicGroup));
+
+ /* initialize lists for internal driver use */
+ INIT_LIST(&p_ReplicGroup->availableMembersList);
+ INIT_LIST(&p_ReplicGroup->membersList);
+
+ p_ReplicGroup->h_FmPcd = h_FmPcd;
+
+ h_Muram = FmPcdGetMuramHandle(p_ReplicGroup->h_FmPcd);
+ ASSERT_COND(h_Muram);
+
+ /* initialize the group lock */
+ p_ReplicGroup->p_Lock = FmPcdAcquireLock(p_ReplicGroup->h_FmPcd);
+ if (!p_ReplicGroup->p_Lock)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("Replic group lock"));
+ DeleteGroup(p_ReplicGroup);
+ return NULL;
+ }
+
+ /* Allocate the frame replicator source table descriptor */
+ p_ReplicGroup->p_SourceTd =
+ (t_Handle)FM_MURAM_AllocMem(h_Muram,
+ FM_PCD_CC_AD_ENTRY_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (!p_ReplicGroup->p_SourceTd)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("frame replicator source table descriptor"));
+ DeleteGroup(p_ReplicGroup);
+ return NULL;
+ }
+
+ /* update the shadow size - required for the host commands */
+ err = FmPcdUpdateCcShadow(p_ReplicGroup->h_FmPcd,
+ FM_PCD_CC_AD_ENTRY_SIZE,
+ FM_PCD_CC_AD_TABLE_ALIGN);
+ if (err)
+ {
+ REPORT_ERROR(MAJOR, err, ("Update CC shadow"));
+ DeleteGroup(p_ReplicGroup);
+ return NULL;
+ }
+
+ p_ReplicGroup->maxNumOfEntries = p_ReplicGroupParam->maxNumOfEntries;
+
+ /* Allocate the maximal number of members ADs and Statistics AD for the group
+ It prevents allocation of Muram in run-time */
+ for (i=0; i<p_ReplicGroup->maxNumOfEntries; i++)
+ {
+ err = AllocMember(p_ReplicGroup);
+ if (err)
+ {
+ REPORT_ERROR(MAJOR, err, ("allocate a new member"));
+ DeleteGroup(p_ReplicGroup);
+ return NULL;
+ }
+ }
+
+ /* Initialize the members linked lists:
+ (hw - the one that is used by the FMan controller and
+ sw - the one that is managed by the driver internally) */
+ for (i=(p_ReplicGroupParam->numOfEntries-1); i>=0; i--)
+ {
+ /* check if this is the last member in the group */
+ if (i == (p_ReplicGroupParam->numOfEntries-1))
+ last = TRUE;
+ else
+ last = FALSE;
+
+ /* Initialize a new member */
+ p_CurrentMember = InitMember(p_ReplicGroup,
+ &(p_ReplicGroupParam->nextEngineParams[i]),
+ last);
+ if (!p_CurrentMember)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_HANDLE, ("No available member"));
+ DeleteGroup(p_ReplicGroup);
+ return NULL;
+ }
+
+ /* Build the members group - link two consecutive members in the hw linked list */
+ LinkMemberToMember(p_ReplicGroup, p_CurrentMember, p_NextMember);
+
+ /* update the driver internal members list to be compatible to the hw members linked list */
+ AddMemberToList(p_ReplicGroup, p_CurrentMember, &p_ReplicGroup->membersList);
+
+ p_NextMember = p_CurrentMember;
+ }
+
+ /* initialize the source table descriptor */
+ BuildSourceTd(p_ReplicGroup->p_SourceTd);
+
+ /* link the source table descriptor to point to the first member in the group */
+ LinkSourceToMember(p_ReplicGroup, p_ReplicGroup->p_SourceTd, p_NextMember);
+
+ return p_ReplicGroup;
+}
+
+t_Error FM_PCD_FrmReplicDeleteGroup(t_Handle h_ReplicGroup)
+{
+ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup *)h_ReplicGroup;
+
+ SANITY_CHECK_RETURN_ERROR(p_ReplicGroup, E_INVALID_HANDLE);
+
+ if (p_ReplicGroup->owners)
+ RETURN_ERROR(MAJOR,
+ E_INVALID_STATE,
+ ("the group has owners and can't be deleted"));
+
+ DeleteGroup(p_ReplicGroup);
+
+ return E_OK;
+}
+
+
+/*****************************************************************************/
+/* API Run-time Frame replicator Control unit functions */
+/*****************************************************************************/
+t_Error FM_PCD_FrmReplicAddMember(t_Handle h_ReplicGroup,
+ uint16_t memberIndex,
+ t_FmPcdCcNextEngineParams *p_MemberParams)
+{
+ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup*) h_ReplicGroup;
+ t_FmPcdFrmReplicMember *p_NewMember, *p_CurrentMember = NULL, *p_PreviousMember = NULL;
+ t_Error err;
+ uint8_t memberPosition;
+
+ SANITY_CHECK_RETURN_ERROR(p_ReplicGroup, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_MemberParams, E_INVALID_HANDLE);
+
+ /* group lock */
+ err = FrmReplicGroupTryLock(p_ReplicGroup);
+ if (err)
+ {
+ if (GET_ERROR_TYPE(err) == E_BUSY)
+ return ERROR_CODE(E_BUSY);
+ else
+ RETURN_ERROR(MAJOR, err, ("try lock in Add member"));
+ }
+
+ if (memberIndex > p_ReplicGroup->numOfEntries)
+ {
+ /* unlock */
+ FrmReplicGroupUnlock(p_ReplicGroup);
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION,
+ ("memberIndex is greater than the members in the list"));
+ }
+
+ if (memberIndex >= p_ReplicGroup->maxNumOfEntries)
+ {
+ /* unlock */
+ FrmReplicGroupUnlock(p_ReplicGroup);
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("memberIndex is greater than the allowed number of members in the group"));
+ }
+
+ if ((p_ReplicGroup->numOfEntries + 1) > FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES)
+ {
+ /* unlock */
+ FrmReplicGroupUnlock(p_ReplicGroup);
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("numOfEntries with new entry can not be larger than %d\n",
+ FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES));
+ }
+
+ err = MemberCheckParams(p_ReplicGroup->h_FmPcd, p_MemberParams);
+ if (err)
+ {
+ /* unlock */
+ FrmReplicGroupUnlock(p_ReplicGroup);
+ RETURN_ERROR(MAJOR, err, ("member check parameters in add operation"));
+ }
+ /* determine the member position in the group */
+ memberPosition = GetMemberPosition(p_ReplicGroup,
+ memberIndex,
+ TRUE/* add operation */);
+
+ /* Initialize a new member */
+ p_NewMember = InitMember(p_ReplicGroup,
+ p_MemberParams,
+ (memberPosition == FRM_REPLIC_LAST_MEMBER_INDEX ? TRUE : FALSE));
+ if (!p_NewMember)
+ {
+ /* unlock */
+ FrmReplicGroupUnlock(p_ReplicGroup);
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("No available member"));
+ }
+
+ switch (memberPosition)
+ {
+ case FRM_REPLIC_FIRST_MEMBER_INDEX:
+ p_CurrentMember = GetMemberByIndex(p_ReplicGroup, memberIndex);
+ ASSERT_COND(p_CurrentMember);
+
+ LinkMemberToMember(p_ReplicGroup, p_NewMember, p_CurrentMember);
+
+ /* update the internal group source TD */
+ LinkSourceToMember(p_ReplicGroup,
+ p_ReplicGroup->p_SourceTd,
+ p_NewMember);
+
+ /* add member to the internal sw member list */
+ AddMemberToList(p_ReplicGroup,
+ p_NewMember,
+ &p_ReplicGroup->membersList);
+ break;
+
+ case FRM_REPLIC_MIDDLE_MEMBER_INDEX:
+ p_CurrentMember = GetMemberByIndex(p_ReplicGroup, memberIndex);
+ ASSERT_COND(p_CurrentMember);
+
+ p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1));
+ ASSERT_COND(p_PreviousMember);
+
+ LinkMemberToMember(p_ReplicGroup, p_NewMember, p_CurrentMember);
+ LinkMemberToMember(p_ReplicGroup, p_PreviousMember, p_NewMember);
+
+ AddMemberToList(p_ReplicGroup, p_NewMember, &p_PreviousMember->node);
+ break;
+
+ case FRM_REPLIC_LAST_MEMBER_INDEX:
+ p_PreviousMember = GetMemberByIndex(p_ReplicGroup, (uint16_t)(memberIndex-1));
+ ASSERT_COND(p_PreviousMember);
+
+ LinkMemberToMember(p_ReplicGroup, p_PreviousMember, p_NewMember);
+ FillReplicAdOfTypeResult(p_PreviousMember->p_MemberAd, FALSE/*last*/);
+
+ /* add the new member to the internal sw member list */
+ AddMemberToList(p_ReplicGroup, p_NewMember, &p_PreviousMember->node);
+ break;
+
+ default:
+ /* unlock */
+ FrmReplicGroupUnlock(p_ReplicGroup);
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("member position in add member"));
+
+ }
+
+ /* unlock */
+ FrmReplicGroupUnlock(p_ReplicGroup);
+
+ return E_OK;
+}
+
+t_Error FM_PCD_FrmReplicRemoveMember(t_Handle h_ReplicGroup,
+ uint16_t memberIndex)
+{
+ t_FmPcdFrmReplicGroup *p_ReplicGroup = (t_FmPcdFrmReplicGroup*) h_ReplicGroup;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_ReplicGroup, E_INVALID_HANDLE);
+
+ /* lock */
+ err = FrmReplicGroupTryLock(p_ReplicGroup);
+ if (err)
+ {
+ if (GET_ERROR_TYPE(err) == E_BUSY)
+ return ERROR_CODE(E_BUSY);
+ else
+ RETURN_ERROR(MAJOR, err, ("try lock in Remove member"));
+ }
+
+ if (memberIndex >= p_ReplicGroup->numOfEntries)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("member index to remove"));
+
+ /* Design decision: group must contain at least one member
+ No possibility to remove the last member from the group */
+ if (p_ReplicGroup->numOfEntries == 1)
+ RETURN_ERROR(MAJOR, E_CONFLICT, ("Can't remove the last member. At least one member should be related to a group."));
+
+ err = RemoveMember(p_ReplicGroup, memberIndex);
+
+ /* unlock */
+ FrmReplicGroupUnlock(p_ReplicGroup);
+
+ switch (GET_ERROR_TYPE(err))
+ {
+ case E_OK:
+ return E_OK;
+
+ case E_BUSY:
+ DBG(TRACE, ("E_BUSY error"));
+ return ERROR_CODE(E_BUSY);
+
+ default:
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+}
+
+/*********************** End of API routines ************************/
+
+
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_replic.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_replic.h
new file mode 100644
index 0000000..7e4224b
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_replic.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_replic.h
+
+ @Description FM frame replicator
+*//***************************************************************************/
+#ifndef __FM_REPLIC_H
+#define __FM_REPLIC_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+
+
+#define FRM_REPLIC_SOURCE_TD_OPCODE 0x75
+#define NEXT_FRM_REPLIC_ADDR_SHIFT 4
+#define NEXT_FRM_REPLIC_MEMBER_INDEX_SHIFT 16
+#define FRM_REPLIC_FR_BIT 0x08000000
+#define FRM_REPLIC_NL_BIT 0x10000000
+#define FRM_REPLIC_INVALID_MEMBER_INDEX 0xffff
+#define FRM_REPLIC_FIRST_MEMBER_INDEX 0
+
+#define FRM_REPLIC_MIDDLE_MEMBER_INDEX 1
+#define FRM_REPLIC_LAST_MEMBER_INDEX 2
+
+#define SOURCE_TD_ITSELF_OPTION 0x01
+#define SOURCE_TD_COPY_OPTION 0x02
+#define SOURCE_TD_ITSELF_AND_COPY_OPTION SOURCE_TD_ITSELF_OPTION | SOURCE_TD_COPY_OPTION
+#define SOURCE_TD_NONE 0x04
+
+/*typedef enum e_SourceTdOption
+{
+ e_SOURCE_TD_NONE = 0,
+ e_SOURCE_TD_ITSELF_OPTION = 1,
+ e_SOURCE_TD_COPY_OPTION = 2,
+ e_SOURCE_TD_ITSELF_AND_COPY_OPTION = e_SOURCE_TD_ITSELF_OPTION | e_SOURCE_TD_COPY_OPTION
+} e_SourceTdOption;
+*/
+
+typedef _Packed struct
+{
+ volatile uint32_t type;
+ volatile uint32_t frGroupPointer;
+ volatile uint32_t operationCode;
+ volatile uint32_t reserved;
+} _PackedType t_FrmReplicGroupSourceAd;
+
+typedef struct t_FmPcdFrmReplicMember
+{
+ void *p_MemberAd; /**< pointer to the member AD */
+ void *p_StatisticsAd;/**< pointer to the statistics AD of the member */
+ t_Handle h_Manip; /**< manip handle - need for free routines */
+ t_List node;
+} t_FmPcdFrmReplicMember;
+
+typedef struct t_FmPcdFrmReplicGroup
+{
+ t_Handle h_FmPcd;
+
+ uint8_t maxNumOfEntries;/**< maximal number of members in the group */
+ uint8_t numOfEntries; /**< actual number of members in the group */
+ uint16_t owners; /**< how many keys share this frame replicator group */
+ void *p_SourceTd; /**< pointer to the frame replicator source table descriptor */
+ t_List membersList; /**< the members list - should reflect the order of the members as in the hw linked list*/
+ t_List availableMembersList;/**< list of all the available members in the group */
+ t_FmPcdLock *p_Lock;
+} t_FmPcdFrmReplicGroup;
+
+
+#endif /* __FM_REPLIC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fman_kg.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fman_kg.c
new file mode 100644
index 0000000..6e77c9386
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fman_kg.c
@@ -0,0 +1,888 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "fsl_fman_kg.h"
+
+/****************************************/
+/* static functions */
+/****************************************/
+
+
+static uint32_t build_ar_bind_scheme(uint8_t hwport_id, bool write)
+{
+ uint32_t rw;
+
+ rw = write ? (uint32_t)FM_KG_KGAR_WRITE : (uint32_t)FM_KG_KGAR_READ;
+
+ return (uint32_t)(FM_KG_KGAR_GO |
+ rw |
+ FM_PCD_KG_KGAR_SEL_PORT_ENTRY |
+ hwport_id |
+ FM_PCD_KG_KGAR_SEL_PORT_WSEL_SP);
+}
+
+static void clear_pe_all_scheme(struct fman_kg_regs *regs, uint8_t hwport_id)
+{
+ uint32_t ar;
+
+ fman_kg_write_sp(regs, 0xffffffff, 0);
+
+ ar = build_ar_bind_scheme(hwport_id, TRUE);
+ fman_kg_write_ar_wait(regs, ar);
+}
+
+static uint32_t build_ar_bind_cls_plan(uint8_t hwport_id, bool write)
+{
+ uint32_t rw;
+
+ rw = write ? (uint32_t)FM_KG_KGAR_WRITE : (uint32_t)FM_KG_KGAR_READ;
+
+ return (uint32_t)(FM_KG_KGAR_GO |
+ rw |
+ FM_PCD_KG_KGAR_SEL_PORT_ENTRY |
+ hwport_id |
+ FM_PCD_KG_KGAR_SEL_PORT_WSEL_CPP);
+}
+
+static void clear_pe_all_cls_plan(struct fman_kg_regs *regs, uint8_t hwport_id)
+{
+ uint32_t ar;
+
+ fman_kg_write_cpp(regs, 0);
+
+ ar = build_ar_bind_cls_plan(hwport_id, TRUE);
+ fman_kg_write_ar_wait(regs, ar);
+}
+
+static uint8_t get_gen_ht_code(enum fman_kg_gen_extract_src src,
+ bool no_validation,
+ uint8_t *offset)
+{
+ int code;
+
+ switch (src) {
+ case E_FMAN_KG_GEN_EXTRACT_ETH:
+ code = no_validation ? 0x73 : 0x3;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_ETYPE:
+ code = no_validation ? 0x77 : 0x7;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_SNAP:
+ code = no_validation ? 0x74 : 0x4;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_VLAN_TCI_1:
+ code = no_validation ? 0x75 : 0x5;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_VLAN_TCI_N:
+ code = no_validation ? 0x76 : 0x6;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_PPPoE:
+ code = no_validation ? 0x78 : 0x8;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_MPLS_1:
+ code = no_validation ? 0x79 : 0x9;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_MPLS_2:
+ code = no_validation ? FM_KG_SCH_GEN_HT_INVALID : 0x19;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_MPLS_3:
+ code = no_validation ? FM_KG_SCH_GEN_HT_INVALID : 0x29;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_MPLS_N:
+ code = no_validation ? 0x7a : 0xa;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_IPv4_1:
+ code = no_validation ? 0x7b : 0xb;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_IPv6_1:
+ code = no_validation ? 0x7b : 0x1b;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_IPv4_2:
+ code = no_validation ? 0x7c : 0xc;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_IPv6_2:
+ code = no_validation ? 0x7c : 0x1c;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_MINENCAP:
+ code = no_validation ? 0x7c : 0x2c;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_IP_PID:
+ code = no_validation ? 0x72 : 0x2;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_GRE:
+ code = no_validation ? 0x7d : 0xd;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_TCP:
+ code = no_validation ? 0x7e : 0xe;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_UDP:
+ code = no_validation ? 0x7e : 0x1e;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_SCTP:
+ code = no_validation ? 0x7e : 0x3e;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_DCCP:
+ code = no_validation ? 0x7e : 0x4e;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_IPSEC_AH:
+ code = no_validation ? 0x7e : 0x2e;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_IPSEC_ESP:
+ code = no_validation ? 0x7e : 0x6e;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_SHIM_1:
+ code = 0x70;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_SHIM_2:
+ code = 0x71;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_FROM_DFLT:
+ code = 0x10;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_FROM_FRAME_START:
+ code = 0x40;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_FROM_PARSE_RESULT:
+ code = 0x20;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_FROM_END_OF_PARSE:
+ code = 0x7f;
+ break;
+
+ case E_FMAN_KG_GEN_EXTRACT_FROM_FQID:
+ code = 0x20;
+ *offset += 0x20;
+ break;
+
+ default:
+ code = FM_KG_SCH_GEN_HT_INVALID;
+ }
+
+ return (uint8_t)code;
+}
+
+static uint32_t build_ar_scheme(uint8_t scheme,
+ uint8_t hwport_id,
+ bool update_counter,
+ bool write)
+{
+ uint32_t rw;
+
+ rw = (uint32_t)(write ? FM_KG_KGAR_WRITE : FM_KG_KGAR_READ);
+
+ return (uint32_t)(FM_KG_KGAR_GO |
+ rw |
+ FM_KG_KGAR_SEL_SCHEME_ENTRY |
+ hwport_id |
+ ((uint32_t)scheme << FM_KG_KGAR_NUM_SHIFT) |
+ (update_counter ? FM_KG_KGAR_SCM_WSEL_UPDATE_CNT : 0));
+}
+
+static uint32_t build_ar_cls_plan(uint8_t grp,
+ uint8_t entries_mask,
+ uint8_t hwport_id,
+ bool write)
+{
+ uint32_t rw;
+
+ rw = (uint32_t)(write ? FM_KG_KGAR_WRITE : FM_KG_KGAR_READ);
+
+ return (uint32_t)(FM_KG_KGAR_GO |
+ rw |
+ FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY |
+ hwport_id |
+ ((uint32_t)grp << FM_KG_KGAR_NUM_SHIFT) |
+ ((uint32_t)entries_mask << FM_KG_KGAR_WSEL_SHIFT));
+}
+
+int fman_kg_write_ar_wait(struct fman_kg_regs *regs, uint32_t fmkg_ar)
+{
+ iowrite32be(fmkg_ar, &regs->fmkg_ar);
+ /* Wait for GO to be idle and read error */
+ while ((fmkg_ar = ioread32be(&regs->fmkg_ar)) & FM_KG_KGAR_GO) ;
+ if (fmkg_ar & FM_PCD_KG_KGAR_ERR)
+ return -EINVAL;
+ return 0;
+}
+
+void fman_kg_write_sp(struct fman_kg_regs *regs, uint32_t sp, bool add)
+{
+
+ struct fman_kg_pe_regs *kgpe_regs;
+ uint32_t tmp;
+
+ kgpe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]);
+ tmp = ioread32be(&kgpe_regs->fmkg_pe_sp);
+
+ if (add)
+ tmp |= sp;
+ else /* clear */
+ tmp &= ~sp;
+
+ iowrite32be(tmp, &kgpe_regs->fmkg_pe_sp);
+
+}
+
+void fman_kg_write_cpp(struct fman_kg_regs *regs, uint32_t cpp)
+{
+ struct fman_kg_pe_regs *kgpe_regs;
+
+ kgpe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]);
+
+ iowrite32be(cpp, &kgpe_regs->fmkg_pe_cpp);
+}
+
+void fman_kg_get_event(struct fman_kg_regs *regs,
+ uint32_t *event,
+ uint32_t *scheme_idx)
+{
+ uint32_t mask, force;
+
+ *event = ioread32be(&regs->fmkg_eer);
+ mask = ioread32be(&regs->fmkg_eeer);
+ *scheme_idx = ioread32be(&regs->fmkg_seer);
+ *scheme_idx &= ioread32be(&regs->fmkg_seeer);
+
+ *event &= mask;
+
+ /* clear the forced events */
+ force = ioread32be(&regs->fmkg_feer);
+ if (force & *event)
+ iowrite32be(force & ~*event ,&regs->fmkg_feer);
+
+ iowrite32be(*event, &regs->fmkg_eer);
+ iowrite32be(*scheme_idx, &regs->fmkg_seer);
+}
+
+
+void fman_kg_init(struct fman_kg_regs *regs,
+ uint32_t exceptions,
+ uint32_t dflt_nia)
+{
+ uint32_t tmp;
+ int i;
+
+ iowrite32be(FM_EX_KG_DOUBLE_ECC | FM_EX_KG_KEYSIZE_OVERFLOW,
+ &regs->fmkg_eer);
+
+ tmp = 0;
+ if (exceptions & FM_EX_KG_DOUBLE_ECC)
+ tmp |= FM_EX_KG_DOUBLE_ECC;
+
+ if (exceptions & FM_EX_KG_KEYSIZE_OVERFLOW)
+ tmp |= FM_EX_KG_KEYSIZE_OVERFLOW;
+
+ iowrite32be(tmp, &regs->fmkg_eeer);
+ iowrite32be(0, &regs->fmkg_fdor);
+ iowrite32be(0, &regs->fmkg_gdv0r);
+ iowrite32be(0, &regs->fmkg_gdv1r);
+ iowrite32be(dflt_nia, &regs->fmkg_gcr);
+
+ /* Clear binding between ports to schemes and classification plans
+ * so that all ports are not bound to any scheme/classification plan */
+ for (i = 0; i < FMAN_MAX_NUM_OF_HW_PORTS; i++) {
+ clear_pe_all_scheme(regs, (uint8_t)i);
+ clear_pe_all_cls_plan(regs, (uint8_t)i);
+ }
+}
+
+void fman_kg_enable_scheme_interrupts(struct fman_kg_regs *regs)
+{
+ /* enable and enable all scheme interrupts */
+ iowrite32be(0xFFFFFFFF, &regs->fmkg_seer);
+ iowrite32be(0xFFFFFFFF, &regs->fmkg_seeer);
+}
+
+void fman_kg_enable(struct fman_kg_regs *regs)
+{
+ iowrite32be(ioread32be(&regs->fmkg_gcr) | FM_KG_KGGCR_EN,
+ &regs->fmkg_gcr);
+}
+
+void fman_kg_disable(struct fman_kg_regs *regs)
+{
+ iowrite32be(ioread32be(&regs->fmkg_gcr) & ~FM_KG_KGGCR_EN,
+ &regs->fmkg_gcr);
+}
+
+void fman_kg_set_data_after_prs(struct fman_kg_regs *regs, uint8_t offset)
+{
+ iowrite32be(offset, &regs->fmkg_fdor);
+}
+
+void fman_kg_set_dflt_val(struct fman_kg_regs *regs,
+ uint8_t def_id,
+ uint32_t val)
+{
+ if(def_id == 0)
+ iowrite32be(val, &regs->fmkg_gdv0r);
+ else
+ iowrite32be(val, &regs->fmkg_gdv1r);
+}
+
+
+void fman_kg_set_exception(struct fman_kg_regs *regs,
+ uint32_t exception,
+ bool enable)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->fmkg_eeer);
+
+ if (enable) {
+ tmp |= exception;
+ } else {
+ tmp &= ~exception;
+ }
+
+ iowrite32be(tmp, &regs->fmkg_eeer);
+}
+
+void fman_kg_get_exception(struct fman_kg_regs *regs,
+ uint32_t *events,
+ uint32_t *scheme_ids,
+ bool clear)
+{
+ uint32_t mask;
+
+ *events = ioread32be(&regs->fmkg_eer);
+ mask = ioread32be(&regs->fmkg_eeer);
+ *events &= mask;
+
+ *scheme_ids = 0;
+
+ if (*events & FM_EX_KG_KEYSIZE_OVERFLOW) {
+ *scheme_ids = ioread32be(&regs->fmkg_seer);
+ mask = ioread32be(&regs->fmkg_seeer);
+ *scheme_ids &= mask;
+ }
+
+ if (clear) {
+ iowrite32be(*scheme_ids, &regs->fmkg_seer);
+ iowrite32be(*events, &regs->fmkg_eer);
+ }
+}
+
+void fman_kg_get_capture(struct fman_kg_regs *regs,
+ struct fman_kg_ex_ecc_attr *ecc_attr,
+ bool clear)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->fmkg_serc);
+
+ if (tmp & KG_FMKG_SERC_CAP) {
+ /* Captured data is valid */
+ ecc_attr->valid = TRUE;
+ ecc_attr->double_ecc =
+ (bool)((tmp & KG_FMKG_SERC_CET) ? TRUE : FALSE);
+ ecc_attr->single_ecc_count =
+ (uint8_t)((tmp & KG_FMKG_SERC_CNT_MSK) >>
+ KG_FMKG_SERC_CNT_SHIFT);
+ ecc_attr->addr = (uint16_t)(tmp & KG_FMKG_SERC_ADDR_MSK);
+
+ if (clear)
+ iowrite32be(KG_FMKG_SERC_CAP, &regs->fmkg_serc);
+ } else {
+ /* No ECC error is captured */
+ ecc_attr->valid = FALSE;
+ }
+}
+
+int fman_kg_build_scheme(struct fman_kg_scheme_params *params,
+ struct fman_kg_scheme_regs *scheme_regs)
+{
+ struct fman_kg_extract_params *extract_params;
+ struct fman_kg_gen_extract_params *gen_params;
+ uint32_t tmp_reg, i, select, mask, fqb;
+ uint8_t offset, shift, ht;
+
+ /* Zero out all registers so no need to care about unused ones */
+ memset(scheme_regs, 0, sizeof(struct fman_kg_scheme_regs));
+
+ /* Mode register */
+ tmp_reg = fm_kg_build_nia(params->next_engine,
+ params->next_engine_action);
+ if (tmp_reg == KG_NIA_INVALID) {
+ return -EINVAL;
+ }
+
+ if (params->next_engine == E_FMAN_PCD_PLCR) {
+ tmp_reg |= FMAN_KG_SCH_MODE_NIA_PLCR;
+ }
+ else if (params->next_engine == E_FMAN_PCD_CC) {
+ tmp_reg |= (uint32_t)params->cc_params.base_offset <<
+ FMAN_KG_SCH_MODE_CCOBASE_SHIFT;
+ }
+
+ tmp_reg |= FMAN_KG_SCH_MODE_EN;
+ scheme_regs->kgse_mode = tmp_reg;
+
+ /* Match vector */
+ scheme_regs->kgse_mv = params->match_vector;
+
+ extract_params = &params->extract_params;
+
+ /* Scheme default values registers */
+ scheme_regs->kgse_dv0 = extract_params->def_scheme_0;
+ scheme_regs->kgse_dv1 = extract_params->def_scheme_1;
+
+ /* Extract Known Fields Command register */
+ scheme_regs->kgse_ekfc = extract_params->known_fields;
+
+ /* Entry Extract Known Default Value register */
+ tmp_reg = 0;
+ tmp_reg |= extract_params->known_fields_def.mac_addr <<
+ FMAN_KG_SCH_DEF_MAC_ADDR_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.vlan_tci <<
+ FMAN_KG_SCH_DEF_VLAN_TCI_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.etype <<
+ FMAN_KG_SCH_DEF_ETYPE_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.ppp_sid <<
+ FMAN_KG_SCH_DEF_PPP_SID_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.ppp_pid <<
+ FMAN_KG_SCH_DEF_PPP_PID_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.mpls <<
+ FMAN_KG_SCH_DEF_MPLS_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.ip_addr <<
+ FMAN_KG_SCH_DEF_IP_ADDR_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.ptype <<
+ FMAN_KG_SCH_DEF_PTYPE_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.ip_tos_tc <<
+ FMAN_KG_SCH_DEF_IP_TOS_TC_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.ipv6_fl <<
+ FMAN_KG_SCH_DEF_IPv6_FL_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.ipsec_spi <<
+ FMAN_KG_SCH_DEF_IPSEC_SPI_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.l4_port <<
+ FMAN_KG_SCH_DEF_L4_PORT_SHIFT;
+ tmp_reg |= extract_params->known_fields_def.tcp_flg <<
+ FMAN_KG_SCH_DEF_TCP_FLG_SHIFT;
+
+ scheme_regs->kgse_ekdv = tmp_reg;
+
+ /* Generic extract registers */
+ if (extract_params->gen_extract_num > FM_KG_NUM_OF_GENERIC_REGS) {
+ return -EINVAL;
+ }
+
+ for (i = 0; i < extract_params->gen_extract_num; i++) {
+ gen_params = extract_params->gen_extract + i;
+
+ tmp_reg = FMAN_KG_SCH_GEN_VALID;
+ tmp_reg |= (uint32_t)gen_params->def_val <<
+ FMAN_KG_SCH_GEN_DEF_SHIFT;
+
+ if (gen_params->type == E_FMAN_KG_HASH_EXTRACT) {
+ if ((gen_params->extract > FMAN_KG_SCH_GEN_SIZE_MAX) ||
+ (gen_params->extract == 0)) {
+ return -EINVAL;
+ }
+ } else {
+ tmp_reg |= FMAN_KG_SCH_GEN_OR;
+ }
+
+ tmp_reg |= (uint32_t)gen_params->extract <<
+ FMAN_KG_SCH_GEN_SIZE_SHIFT;
+ tmp_reg |= (uint32_t)gen_params->mask <<
+ FMAN_KG_SCH_GEN_MASK_SHIFT;
+
+ offset = gen_params->offset;
+ ht = get_gen_ht_code(gen_params->src,
+ gen_params->no_validation,
+ &offset);
+ tmp_reg |= (uint32_t)ht << FMAN_KG_SCH_GEN_HT_SHIFT;
+ tmp_reg |= offset;
+
+ scheme_regs->kgse_gec[i] = tmp_reg;
+ }
+
+ /* Masks registers */
+ if (extract_params->masks_num > FM_KG_EXTRACT_MASKS_NUM) {
+ return -EINVAL;
+ }
+
+ select = 0;
+ mask = 0;
+ fqb = 0;
+ for (i = 0; i < extract_params->masks_num; i++) {
+ /* MCSx fields */
+ KG_GET_MASK_SEL_SHIFT(shift, i);
+ if (extract_params->masks[i].is_known) {
+ /* Mask known field */
+ select |= extract_params->masks[i].field_or_gen_idx <<
+ shift;
+ } else {
+ /* Mask generic extract */
+ select |= (extract_params->masks[i].field_or_gen_idx +
+ FM_KG_MASK_SEL_GEN_BASE) << shift;
+ }
+
+ /* MOx fields - spread between se_bmch and se_fqb registers */
+ KG_GET_MASK_OFFSET_SHIFT(shift, i);
+ if (i < 2) {
+ select |= (uint32_t)extract_params->masks[i].offset <<
+ shift;
+ } else {
+ fqb |= (uint32_t)extract_params->masks[i].offset <<
+ shift;
+ }
+
+ /* BMx fields */
+ KG_GET_MASK_SHIFT(shift, i);
+ mask |= (uint32_t)extract_params->masks[i].mask << shift;
+ }
+
+ /* Finish with rest of BMx fileds -
+ * don't mask bits for unused masks by setting
+ * corresponding BMx field = 0xFF */
+ for (i = extract_params->masks_num; i < FM_KG_EXTRACT_MASKS_NUM; i++) {
+ KG_GET_MASK_SHIFT(shift, i);
+ mask |= 0xFF << shift;
+ }
+
+ scheme_regs->kgse_bmch = select;
+ scheme_regs->kgse_bmcl = mask;
+
+ /* Finish with FQB register initialization.
+ * Check fqid is 24-bit value. */
+ if (params->base_fqid & ~0x00FFFFFF) {
+ return -EINVAL;
+ }
+
+ fqb |= params->base_fqid;
+ scheme_regs->kgse_fqb = fqb;
+
+ /* Hash Configuration register */
+ tmp_reg = 0;
+ if (params->hash_params.use_hash) {
+ /* Check hash mask is 24-bit value */
+ if (params->hash_params.mask & ~0x00FFFFFF) {
+ return -EINVAL;
+ }
+
+ /* Hash function produces 64-bit value, 24 bits of that
+ * are used to generate fq_id and policer profile.
+ * Thus, maximal shift is 40 bits to allow 24 bits out of 64.
+ */
+ if (params->hash_params.shift_r > FMAN_KG_SCH_HASH_HSHIFT_MAX) {
+ return -EINVAL;
+ }
+
+ tmp_reg |= params->hash_params.mask;
+ tmp_reg |= (uint32_t)params->hash_params.shift_r <<
+ FMAN_KG_SCH_HASH_HSHIFT_SHIFT;
+
+ if (params->hash_params.sym) {
+ tmp_reg |= FMAN_KG_SCH_HASH_SYM;
+ }
+
+ }
+
+ if (params->bypass_fqid_gen) {
+ tmp_reg |= FMAN_KG_SCH_HASH_NO_FQID_GEN;
+ }
+
+ scheme_regs->kgse_hc = tmp_reg;
+
+ /* Policer Profile register */
+ if (params->policer_params.bypass_pp_gen) {
+ tmp_reg = FMAN_KG_SCH_PP_NO_GEN;
+ } else {
+ /* Lower 8 bits of 24-bits extracted from hash result
+ * are used for policer profile generation.
+ * That leaves maximum shift value = 23. */
+ if (params->policer_params.shift > FMAN_KG_SCH_PP_SHIFT_MAX) {
+ return -EINVAL;
+ }
+
+ tmp_reg = params->policer_params.base;
+ tmp_reg |= ((uint32_t)params->policer_params.shift <<
+ FMAN_KG_SCH_PP_SH_SHIFT) &
+ FMAN_KG_SCH_PP_SH_MASK;
+ tmp_reg |= ((uint32_t)params->policer_params.shift <<
+ FMAN_KG_SCH_PP_SL_SHIFT) &
+ FMAN_KG_SCH_PP_SL_MASK;
+ tmp_reg |= (uint32_t)params->policer_params.mask <<
+ FMAN_KG_SCH_PP_MASK_SHIFT;
+ }
+
+ scheme_regs->kgse_ppc = tmp_reg;
+
+ /* Coarse Classification Bit Select register */
+ if (params->next_engine == E_FMAN_PCD_CC) {
+ scheme_regs->kgse_ccbs = params->cc_params.qlcv_bits_sel;
+ }
+
+ /* Packets Counter register */
+ if (params->update_counter) {
+ scheme_regs->kgse_spc = params->counter_value;
+ }
+
+ return 0;
+}
+
+int fman_kg_write_scheme(struct fman_kg_regs *regs,
+ uint8_t scheme_id,
+ uint8_t hwport_id,
+ struct fman_kg_scheme_regs *scheme_regs,
+ bool update_counter)
+{
+ struct fman_kg_scheme_regs *kgse_regs;
+ uint32_t tmp_reg;
+ int err, i;
+
+ /* Write indirect scheme registers */
+ kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]);
+
+ iowrite32be(scheme_regs->kgse_mode, &kgse_regs->kgse_mode);
+ iowrite32be(scheme_regs->kgse_ekfc, &kgse_regs->kgse_ekfc);
+ iowrite32be(scheme_regs->kgse_ekdv, &kgse_regs->kgse_ekdv);
+ iowrite32be(scheme_regs->kgse_bmch, &kgse_regs->kgse_bmch);
+ iowrite32be(scheme_regs->kgse_bmcl, &kgse_regs->kgse_bmcl);
+ iowrite32be(scheme_regs->kgse_fqb, &kgse_regs->kgse_fqb);
+ iowrite32be(scheme_regs->kgse_hc, &kgse_regs->kgse_hc);
+ iowrite32be(scheme_regs->kgse_ppc, &kgse_regs->kgse_ppc);
+ iowrite32be(scheme_regs->kgse_spc, &kgse_regs->kgse_spc);
+ iowrite32be(scheme_regs->kgse_dv0, &kgse_regs->kgse_dv0);
+ iowrite32be(scheme_regs->kgse_dv1, &kgse_regs->kgse_dv1);
+ iowrite32be(scheme_regs->kgse_ccbs, &kgse_regs->kgse_ccbs);
+ iowrite32be(scheme_regs->kgse_mv, &kgse_regs->kgse_mv);
+
+ for (i = 0 ; i < FM_KG_NUM_OF_GENERIC_REGS ; i++)
+ iowrite32be(scheme_regs->kgse_gec[i], &kgse_regs->kgse_gec[i]);
+
+ /* Write AR (Action register) */
+ tmp_reg = build_ar_scheme(scheme_id, hwport_id, update_counter, TRUE);
+ err = fman_kg_write_ar_wait(regs, tmp_reg);
+ return err;
+}
+
+int fman_kg_delete_scheme(struct fman_kg_regs *regs,
+ uint8_t scheme_id,
+ uint8_t hwport_id)
+{
+ struct fman_kg_scheme_regs *kgse_regs;
+ uint32_t tmp_reg;
+ int err, i;
+
+ kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]);
+
+ /* Clear all registers including enable bit in mode register */
+ for (i = 0; i < (sizeof(struct fman_kg_scheme_regs)) / 4; ++i) {
+ iowrite32be(0, ((uint32_t *)kgse_regs + i));
+ }
+
+ /* Write AR (Action register) */
+ tmp_reg = build_ar_scheme(scheme_id, hwport_id, FALSE, TRUE);
+ err = fman_kg_write_ar_wait(regs, tmp_reg);
+ return err;
+}
+
+int fman_kg_get_scheme_counter(struct fman_kg_regs *regs,
+ uint8_t scheme_id,
+ uint8_t hwport_id,
+ uint32_t *counter)
+{
+ struct fman_kg_scheme_regs *kgse_regs;
+ uint32_t tmp_reg;
+ int err;
+
+ kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]);
+
+ tmp_reg = build_ar_scheme(scheme_id, hwport_id, TRUE, FALSE);
+ err = fman_kg_write_ar_wait(regs, tmp_reg);
+
+ if (err != 0)
+ return err;
+
+ *counter = ioread32be(&kgse_regs->kgse_spc);
+
+ return 0;
+}
+
+int fman_kg_set_scheme_counter(struct fman_kg_regs *regs,
+ uint8_t scheme_id,
+ uint8_t hwport_id,
+ uint32_t counter)
+{
+ struct fman_kg_scheme_regs *kgse_regs;
+ uint32_t tmp_reg;
+ int err;
+
+ kgse_regs = (struct fman_kg_scheme_regs *)&(regs->fmkg_indirect[0]);
+
+ tmp_reg = build_ar_scheme(scheme_id, hwport_id, TRUE, FALSE);
+
+ err = fman_kg_write_ar_wait(regs, tmp_reg);
+ if (err != 0)
+ return err;
+
+ /* Keygen indirect access memory contains all scheme_id registers
+ * by now. Change only counter value. */
+ iowrite32be(counter, &kgse_regs->kgse_spc);
+
+ /* Write back scheme registers */
+ tmp_reg = build_ar_scheme(scheme_id, hwport_id, TRUE, TRUE);
+ err = fman_kg_write_ar_wait(regs, tmp_reg);
+
+ return err;
+}
+
+uint32_t fman_kg_get_schemes_total_counter(struct fman_kg_regs *regs)
+{
+ return ioread32be(&regs->fmkg_tpc);
+}
+
+int fman_kg_build_cls_plan(struct fman_kg_cls_plan_params *params,
+ struct fman_kg_cp_regs *cls_plan_regs)
+{
+ uint8_t entries_set, entry_bit;
+ int i;
+
+ /* Zero out all group's register */
+ memset(cls_plan_regs, 0, sizeof(struct fman_kg_cp_regs));
+
+ /* Go over all classification entries in params->entries_mask and
+ * configure the corresponding cpe register */
+ entries_set = params->entries_mask;
+ for (i = 0; entries_set; i++) {
+ entry_bit = (uint8_t)(0x80 >> i);
+ if ((entry_bit & entries_set) == 0)
+ continue;
+ entries_set ^= entry_bit;
+ cls_plan_regs->kgcpe[i] = params->mask_vector[i];
+ }
+
+ return 0;
+}
+
+int fman_kg_write_cls_plan(struct fman_kg_regs *regs,
+ uint8_t grp_id,
+ uint8_t entries_mask,
+ uint8_t hwport_id,
+ struct fman_kg_cp_regs *cls_plan_regs)
+{
+ struct fman_kg_cp_regs *kgcpe_regs;
+ uint32_t tmp_reg;
+ int i, err;
+
+ /* Check group index is valid and the group isn't empty */
+ if (grp_id >= FM_KG_CLS_PLAN_GRPS_NUM)
+ return -EINVAL;
+
+ /* Write indirect classification plan registers */
+ kgcpe_regs = (struct fman_kg_cp_regs *)&(regs->fmkg_indirect[0]);
+
+ for (i = 0; i < FM_KG_NUM_CLS_PLAN_ENTR; i++) {
+ iowrite32be(cls_plan_regs->kgcpe[i], &kgcpe_regs->kgcpe[i]);
+ }
+
+ tmp_reg = build_ar_cls_plan(grp_id, entries_mask, hwport_id, TRUE);
+ err = fman_kg_write_ar_wait(regs, tmp_reg);
+ return err;
+}
+
+int fman_kg_write_bind_schemes(struct fman_kg_regs *regs,
+ uint8_t hwport_id,
+ uint32_t schemes)
+{
+ struct fman_kg_pe_regs *kg_pe_regs;
+ uint32_t tmp_reg;
+ int err;
+
+ kg_pe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]);
+
+ iowrite32be(schemes, &kg_pe_regs->fmkg_pe_sp);
+
+ tmp_reg = build_ar_bind_scheme(hwport_id, TRUE);
+ err = fman_kg_write_ar_wait(regs, tmp_reg);
+ return err;
+}
+
+int fman_kg_build_bind_cls_plans(uint8_t grp_base,
+ uint8_t grp_mask,
+ uint32_t *bind_cls_plans)
+{
+ /* Check grp_base and grp_mask are 5-bits values */
+ if ((grp_base & ~0x0000001F) || (grp_mask & !0x0000001F))
+ return -EINVAL;
+
+ *bind_cls_plans = (uint32_t) ((grp_mask << FMAN_KG_PE_CPP_MASK_SHIFT) | grp_base);
+ return 0;
+}
+
+
+int fman_kg_write_bind_cls_plans(struct fman_kg_regs *regs,
+ uint8_t hwport_id,
+ uint32_t bind_cls_plans)
+{
+ struct fman_kg_pe_regs *kg_pe_regs;
+ uint32_t tmp_reg;
+ int err;
+
+ kg_pe_regs = (struct fman_kg_pe_regs *)&(regs->fmkg_indirect[0]);
+
+ iowrite32be(bind_cls_plans, &kg_pe_regs->fmkg_pe_cpp);
+
+ tmp_reg = build_ar_bind_cls_plan(hwport_id, TRUE);
+ err = fman_kg_write_ar_wait(regs, tmp_reg);
+ return err;
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fman_prs.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fman_prs.c
new file mode 100644
index 0000000..108779d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fman_prs.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "fsl_fman_prs.h"
+
+uint32_t fman_prs_get_err_event(struct fman_prs_regs *regs, uint32_t ev_mask)
+{
+ return ioread32be(&regs->fmpr_perr) & ev_mask;
+}
+
+uint32_t fman_prs_get_err_ev_mask(struct fman_prs_regs *regs)
+{
+ return ioread32be(&regs->fmpr_perer);
+}
+
+void fman_prs_ack_err_event(struct fman_prs_regs *regs, uint32_t event)
+{
+ iowrite32be(event, &regs->fmpr_perr);
+}
+
+uint32_t fman_prs_get_expt_event(struct fman_prs_regs *regs, uint32_t ev_mask)
+{
+ return ioread32be(&regs->fmpr_pevr) & ev_mask;
+}
+
+uint32_t fman_prs_get_expt_ev_mask(struct fman_prs_regs *regs)
+{
+ return ioread32be(&regs->fmpr_pever);
+}
+
+void fman_prs_ack_expt_event(struct fman_prs_regs *regs, uint32_t event)
+{
+ iowrite32be(event, &regs->fmpr_pevr);
+}
+
+void fman_prs_defconfig(struct fman_prs_cfg *cfg)
+{
+ cfg->port_id_stat = 0;
+ cfg->max_prs_cyc_lim = DEFAULT_MAX_PRS_CYC_LIM;
+ cfg->prs_exceptions = 0x03000000;
+}
+
+int fman_prs_init(struct fman_prs_regs *regs, struct fman_prs_cfg *cfg)
+{
+ uint32_t tmp;
+
+ iowrite32be(cfg->max_prs_cyc_lim, &regs->fmpr_rpclim);
+ iowrite32be((FM_PCD_PRS_SINGLE_ECC | FM_PCD_PRS_PORT_IDLE_STS),
+ &regs->fmpr_pevr);
+
+ if (cfg->prs_exceptions & FM_PCD_EX_PRS_SINGLE_ECC)
+ iowrite32be(FM_PCD_PRS_SINGLE_ECC, &regs->fmpr_pever);
+ else
+ iowrite32be(0, &regs->fmpr_pever);
+
+ iowrite32be(FM_PCD_PRS_DOUBLE_ECC, &regs->fmpr_perr);
+
+ tmp = 0;
+ if (cfg->prs_exceptions & FM_PCD_EX_PRS_DOUBLE_ECC)
+ tmp |= FM_PCD_PRS_DOUBLE_ECC;
+ iowrite32be(tmp, &regs->fmpr_perer);
+
+ iowrite32be(cfg->port_id_stat, &regs->fmpr_ppsc);
+
+ return 0;
+}
+
+void fman_prs_enable(struct fman_prs_regs *regs)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->fmpr_rpimac) | FM_PCD_PRS_RPIMAC_EN;
+ iowrite32be(tmp, &regs->fmpr_rpimac);
+}
+
+void fman_prs_disable(struct fman_prs_regs *regs)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&regs->fmpr_rpimac) & ~FM_PCD_PRS_RPIMAC_EN;
+ iowrite32be(tmp, &regs->fmpr_rpimac);
+}
+
+int fman_prs_is_enabled(struct fman_prs_regs *regs)
+{
+ return ioread32be(&regs->fmpr_rpimac) & FM_PCD_PRS_RPIMAC_EN;
+}
+
+void fman_prs_set_stst_port_msk(struct fman_prs_regs *regs, uint32_t pid_msk)
+{
+ iowrite32be(pid_msk, &regs->fmpr_ppsc);
+}
+
+void fman_prs_set_stst(struct fman_prs_regs *regs, bool enable)
+{
+ if (enable)
+ iowrite32be(FM_PCD_PRS_PPSC_ALL_PORTS, &regs->fmpr_ppsc);
+ else
+ iowrite32be(0, &regs->fmpr_ppsc);
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/Makefile b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/Makefile
new file mode 100644
index 0000000..c94c54c
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/Makefile
@@ -0,0 +1,15 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+
+NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc
+
+EXTRA_CFLAGS += -I$(NCSW_FM_INC)
+
+obj-y += fsl-ncsw-Pcd.o
+
+fsl-ncsw-Pcd-objs := fm_port.o fm_port_im.o fman_port.o
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.c
new file mode 100644
index 0000000..00a3489
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.c
@@ -0,0 +1,5858 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_port.c
+
+ @Description FM driver routines implementation.
+*//***************************************************************************/
+#include "error_ext.h"
+#include "std_ext.h"
+#include "string_ext.h"
+#include "sprint_ext.h"
+#include "debug_ext.h"
+#include "fm_muram_ext.h"
+
+#include "fman_common.h"
+#include "fm_port.h"
+#include "fm_port_dsar.h"
+#include "common/general.h"
+
+/****************************************/
+/* static functions */
+/****************************************/
+static t_Error FmPortConfigAutoResForDeepSleepSupport1(t_FmPort *p_FmPort);
+
+static t_Error CheckInitParameters(t_FmPort *p_FmPort)
+{
+ t_FmPortDriverParam *p_Params = p_FmPort->p_FmPortDriverParam;
+ struct fman_port_cfg *p_DfltConfig = &p_Params->dfltCfg;
+ t_Error ans = E_OK;
+ uint32_t unusedMask;
+
+ if (p_FmPort->imEn)
+ {
+ if (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)
+ if (p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth > 2)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fifoDeqPipelineDepth for IM 10G can't be larger than 2"));
+
+ if ((ans = FmPortImCheckInitParameters(p_FmPort)) != E_OK)
+ return ERROR_CODE(ans);
+ }
+ else
+ {
+ /****************************************/
+ /* Rx only */
+ /****************************************/
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
+ {
+ /* external buffer pools */
+ if (!p_Params->extBufPools.numOfPoolsUsed)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("extBufPools.numOfPoolsUsed=0. At least one buffer pool must be defined"));
+
+ if (FmSpCheckBufPoolsParams(&p_Params->extBufPools,
+ p_Params->p_BackupBmPools,
+ &p_Params->bufPoolDepletion)!= E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
+
+ /* Check that part of IC that needs copying is small enough to enter start margin */
+ if (p_Params->intContext.size && (p_Params->intContext.size + p_Params->intContext.extBufOffset > p_Params->bufMargins.startMargins))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.size is larger than start margins"));
+
+ if ((p_Params->liodnOffset != DPAA_LIODN_DONT_OVERRIDE) &&
+ (p_Params->liodnOffset & ~FM_LIODN_OFFSET_MASK))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("liodnOffset is larger than %d", FM_LIODN_OFFSET_MASK+1));
+
+#ifdef FM_NO_BACKUP_POOLS
+ if ((p_FmPort->fmRevInfo.majorRev != 4) && (p_FmPort->fmRevInfo.majorRev < 6))
+ if (p_FmPort->p_FmPortDriverParam->p_BackupBmPools)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("BackupBmPools"));
+#endif /* FM_NO_BACKUP_POOLS */
+ }
+
+ /****************************************/
+ /* Non Rx ports */
+ /****************************************/
+ else
+ {
+ if (p_Params->deqSubPortal >= FM_MAX_NUM_OF_SUB_PORTALS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, (" deqSubPortal has to be in the range of 0 - %d", FM_MAX_NUM_OF_SUB_PORTALS));
+
+ /* to protect HW internal-context from overwrite */
+ if ((p_Params->intContext.size) &&
+ (p_Params->intContext.intContextOffset < MIN_TX_INT_OFFSET))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("non-Rx intContext.intContextOffset can't be smaller than %d", MIN_TX_INT_OFFSET));
+
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G)
+ /* in O/H DEFAULT_notSupported indicates that it is not supported and should not be checked */
+ || (p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth != DEFAULT_notSupported))
+ {
+ /* Check that not larger than 8 */
+ if ((!p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth) ||
+ ( p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth > MAX_FIFO_PIPELINE_DEPTH))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fifoDeqPipelineDepth can't be larger than %d", MAX_FIFO_PIPELINE_DEPTH));
+ }
+ }
+
+ /****************************************/
+ /* Rx Or Offline Parsing */
+ /****************************************/
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
+ {
+ if (!p_Params->dfltFqid)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dfltFqid must be between 1 and 2^24-1"));
+#if defined(FM_CAPWAP_SUPPORT) && defined(FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004)
+ if (p_FmPort->p_FmPortDriverParam->bufferPrefixContent.manipExtraSpace % 16)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufferPrefixContent.manipExtraSpace has to be devidable by 16"));
+#endif /* defined(FM_CAPWAP_SUPPORT) && ... */
+ }
+
+ /****************************************/
+ /* All ports */
+ /****************************************/
+ /* common BMI registers values */
+ /* Check that Queue Id is not larger than 2^24, and is not 0 */
+ if ((p_Params->errFqid & ~0x00FFFFFF) || !p_Params->errFqid)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("errFqid must be between 1 and 2^24-1"));
+ if (p_Params->dfltFqid & ~0x00FFFFFF)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dfltFqid must be between 1 and 2^24-1"));
+ }
+
+ /****************************************/
+ /* Rx only */
+ /****************************************/
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
+ {
+ if (p_DfltConfig->rx_pri_elevation % BMI_FIFO_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("rxFifoPriElevationLevel has to be divisible by %d", BMI_FIFO_UNITS));
+ if ((p_DfltConfig->rx_pri_elevation < BMI_FIFO_UNITS) || (p_DfltConfig->rx_pri_elevation > MAX_PORT_FIFO_SIZE))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("rxFifoPriElevationLevel has to be in the range of 256 - %d", MAX_PORT_FIFO_SIZE));
+ if (p_DfltConfig->rx_fifo_thr % BMI_FIFO_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("rxFifoThreshold has to be divisible by %d", BMI_FIFO_UNITS));
+ if ((p_DfltConfig->rx_fifo_thr < BMI_FIFO_UNITS) ||(p_DfltConfig->rx_fifo_thr > MAX_PORT_FIFO_SIZE))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("rxFifoThreshold has to be in the range of 256 - %d", MAX_PORT_FIFO_SIZE));
+
+ /* Check that not larger than 16 */
+ if (p_DfltConfig->rx_cut_end_bytes > FRAME_END_DATA_SIZE)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("cutBytesFromEnd can't be larger than %d", FRAME_END_DATA_SIZE));
+
+ if (FmSpCheckBufMargins(&p_Params->bufMargins)!= E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
+
+ /* extra FIFO size (allowed only to Rx ports) */
+ if (p_Params->setSizeOfFifo && (p_FmPort->fifoBufs.extra % BMI_FIFO_UNITS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fifoBufs.extra has to be divisible by %d", BMI_FIFO_UNITS));
+
+ if (p_Params->bufPoolDepletion.poolsGrpModeEnable &&
+ !p_Params->bufPoolDepletion.numOfPools)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufPoolDepletion.numOfPools can not be 0 when poolsGrpModeEnable=TRUE"));
+#ifdef FM_CSI_CFED_LIMIT
+ if (p_FmPort->fmRevInfo.majorRev == 4)
+ {
+ /* Check that not larger than 16 */
+ if (p_DfltConfig->rx_cut_end_bytes + p_DfltConfig->checksum_bytes_ignore > FRAME_END_DATA_SIZE)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("cheksumLastBytesIgnore + cutBytesFromEnd can't be larger than %d", FRAME_END_DATA_SIZE));
+ }
+#endif /* FM_CSI_CFED_LIMIT */
+ }
+
+ /****************************************/
+ /* Non Rx ports */
+ /****************************************/
+ /* extra FIFO size (allowed only to Rx ports) */
+ else if (p_FmPort->fifoBufs.extra)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, (" No fifoBufs.extra for non Rx ports"));
+
+ /****************************************/
+ /* Tx only */
+ /****************************************/
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G))
+ {
+ if (p_DfltConfig->tx_fifo_min_level % BMI_FIFO_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("txFifoMinFillLevel has to be divisible by %d", BMI_FIFO_UNITS));
+ if (p_DfltConfig->tx_fifo_min_level > (MAX_PORT_FIFO_SIZE - 256))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("txFifoMinFillLevel has to be in the range of 0 - %d", (MAX_PORT_FIFO_SIZE - 256)));
+ if (p_DfltConfig->tx_fifo_low_comf_level % BMI_FIFO_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("txFifoLowComfLevel has to be divisible by %d", BMI_FIFO_UNITS));
+ if ((p_DfltConfig->tx_fifo_low_comf_level < BMI_FIFO_UNITS) || (p_DfltConfig->tx_fifo_low_comf_level > MAX_PORT_FIFO_SIZE))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("txFifoLowComfLevel has to be in the range of 256 - %d", MAX_PORT_FIFO_SIZE));
+
+ if (p_FmPort->portType == e_FM_PORT_TYPE_TX)
+ if (p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth > 2)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fifoDeqPipelineDepth for 1G can't be larger than 2"));
+ }
+
+ /****************************************/
+ /* Non Tx Ports */
+ /****************************************/
+ /* If discard override was selected , no frames may be discarded. */
+ else if (p_DfltConfig->discard_override && p_Params->errorsToDiscard)
+ RETURN_ERROR(MAJOR, E_CONFLICT,
+ ("errorsToDiscard is not empty, but frmDiscardOverride selected (all discarded frames to be enqueued to error queue)."));
+
+ /****************************************/
+ /* Rx and Offline parsing */
+ /****************************************/
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
+ {
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ unusedMask = BMI_STATUS_OP_MASK_UNUSED;
+ else
+ unusedMask = BMI_STATUS_RX_MASK_UNUSED;
+
+ /* Check that no common bits with BMI_STATUS_MASK_UNUSED */
+ if (p_Params->errorsToDiscard & unusedMask)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("errorsToDiscard contains undefined bits"));
+ }
+
+ /****************************************/
+ /* Offline Ports */
+ /****************************************/
+#ifdef FM_OP_OPEN_DMA_MIN_LIMIT
+ if ((p_FmPort->fmRevInfo.majorRev >= 6) &&
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) &&
+ p_Params->setNumOfOpenDmas &&
+ (p_FmPort->openDmas.num < MIN_NUM_OF_OP_DMAS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For Offline port, openDmas.num can't be smaller than %d", MIN_NUM_OF_OP_DMAS));
+#endif /* FM_OP_OPEN_DMA_MIN_LIMIT */
+
+ /****************************************/
+ /* Offline & HC Ports */
+ /****************************************/
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND))
+ {
+#ifndef FM_FRAME_END_PARAMS_FOR_OP
+ if ((p_FmPort->fmRevInfo.majorRev < 6) &&
+ (p_FmPort->p_FmPortDriverParam->cheksumLastBytesIgnore != DEFAULT_notSupported))
+ /* this is an indication that user called config for this mode which is not supported in this integration */
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("cheksumLastBytesIgnore is available for Rx & Tx ports only"));
+#endif /* !FM_FRAME_END_PARAMS_FOR_OP */
+
+#ifndef FM_DEQ_PIPELINE_PARAMS_FOR_OP
+ if ((!((p_FmPort->fmRevInfo.majorRev == 4) ||
+ (p_FmPort->fmRevInfo.majorRev >= 6))) &&
+ (p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth != DEFAULT_notSupported))
+ /* this is an indication that user called config for this mode which is not supported in this integration */
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("fifoDeqPipelineDepth is available for Tx ports only"));
+#endif /* !FM_DEQ_PIPELINE_PARAMS_FOR_OP */
+ }
+
+ /****************************************/
+ /* All ports */
+ /****************************************/
+ /* Check that not larger than 16 */
+ if ((p_Params->cheksumLastBytesIgnore > FRAME_END_DATA_SIZE) &&
+ ((p_Params->cheksumLastBytesIgnore != DEFAULT_notSupported)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("cheksumLastBytesIgnore can't be larger than %d", FRAME_END_DATA_SIZE));
+
+ if (FmSpCheckIntContextParams(&p_Params->intContext)!= E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
+
+ /* common BMI registers values */
+ if (p_Params->setNumOfTasks && ((!p_FmPort->tasks.num) || (p_FmPort->tasks.num > MAX_NUM_OF_TASKS)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("tasks.num can't be larger than %d", MAX_NUM_OF_TASKS));
+ if (p_Params->setNumOfTasks && (p_FmPort->tasks.extra > MAX_NUM_OF_EXTRA_TASKS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("tasks.extra can't be larger than %d", MAX_NUM_OF_EXTRA_TASKS));
+ if (p_Params->setNumOfOpenDmas && ((!p_FmPort->openDmas.num) || (p_FmPort->openDmas.num > MAX_NUM_OF_DMAS)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("openDmas.num can't be larger than %d", MAX_NUM_OF_DMAS));
+ if (p_Params->setNumOfOpenDmas && (p_FmPort->openDmas.extra > MAX_NUM_OF_EXTRA_DMAS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("openDmas.extra can't be larger than %d", MAX_NUM_OF_EXTRA_DMAS));
+ if (p_Params->setSizeOfFifo && (!p_FmPort->fifoBufs.num || (p_FmPort->fifoBufs.num > MAX_PORT_FIFO_SIZE)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fifoBufs.num has to be in the range of 256 - %d", MAX_PORT_FIFO_SIZE));
+ if (p_Params->setSizeOfFifo && (p_FmPort->fifoBufs.num % BMI_FIFO_UNITS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fifoBufs.num has to be divisible by %d", BMI_FIFO_UNITS));
+
+#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+ if (p_FmPort->fmRevInfo.majorRev == 4)
+ if (p_FmPort->p_FmPortDriverParam->deqPrefetchOption != DEFAULT_notSupported)
+ /* this is an indication that user called config for this mode which is not supported in this integration */
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("deqPrefetchOption"));
+#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */
+
+ return E_OK;
+}
+
+static t_Error VerifySizeOfFifo(t_FmPort *p_FmPort)
+{
+ uint32_t minFifoSizeRequired = 0, optFifoSizeForB2B = 0;
+
+ /*************************/
+ /* TX PORTS */
+ /*************************/
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G))
+ {
+ minFifoSizeRequired = (uint32_t)
+ (ROUND_UP(p_FmPort->maxFrameLength, BMI_FIFO_UNITS) + (3*BMI_FIFO_UNITS));
+ if (!p_FmPort->imEn)
+ minFifoSizeRequired += p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth * BMI_FIFO_UNITS;
+
+ optFifoSizeForB2B = minFifoSizeRequired;
+
+ /* Add some margin for back-to-back capability to improve performance,
+ allows the hardware to pipeline new frame dma while the previous
+ frame not yet transmitted. */
+ if (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G)
+ optFifoSizeForB2B += 3*BMI_FIFO_UNITS;
+ else
+ optFifoSizeForB2B += 2*BMI_FIFO_UNITS;
+ }
+
+ /*************************/
+ /* RX IM PORTS */
+ /*************************/
+ else if (((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) &&
+ p_FmPort->imEn)
+ {
+ optFifoSizeForB2B = minFifoSizeRequired = (uint32_t)
+ (ROUND_UP(p_FmPort->maxFrameLength, BMI_FIFO_UNITS) + (4*BMI_FIFO_UNITS));
+ }
+
+ /*************************/
+ /* RX non-IM PORTS */
+ /*************************/
+ else if (((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)) &&
+ !p_FmPort->imEn)
+ {
+ if (p_FmPort->fmRevInfo.majorRev == 4)
+ {
+ if (p_FmPort->rxPoolsParams.numOfPools == 1)
+ minFifoSizeRequired = 8*BMI_FIFO_UNITS;
+ else
+ minFifoSizeRequired = (uint32_t)
+ (ROUND_UP(p_FmPort->rxPoolsParams.secondLargestBufSize, BMI_FIFO_UNITS) + (7*BMI_FIFO_UNITS));
+ }
+ else
+ {
+#if (DPAA_VERSION >= 11)
+ minFifoSizeRequired = (uint32_t)
+ (ROUND_UP(p_FmPort->maxFrameLength, BMI_FIFO_UNITS) + (5*BMI_FIFO_UNITS));
+ /* 4 according to spec + 1 for FOF>0 */
+#else
+ minFifoSizeRequired = (uint32_t)
+ (ROUND_UP(MIN(p_FmPort->maxFrameLength, p_FmPort->rxPoolsParams.largestBufSize), BMI_FIFO_UNITS)
+ + (7*BMI_FIFO_UNITS));
+#endif /* (DPAA_VERSION >= 11) */
+ }
+
+ optFifoSizeForB2B = minFifoSizeRequired;
+
+ /* Add some margin for back-to-back capability to improve performance,
+ allows the hardware to pipeline new frame dma while the previous
+ frame not yet transmitted. */
+ if (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G)
+ optFifoSizeForB2B += 8*BMI_FIFO_UNITS;
+ else
+ optFifoSizeForB2B += 3*BMI_FIFO_UNITS;
+ }
+
+ /* For O/H ports, check fifo size and update if necessary */
+ else if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND))
+ {
+#if (DPAA_VERSION >= 11)
+ optFifoSizeForB2B = minFifoSizeRequired = (uint32_t)
+ (ROUND_UP(p_FmPort->maxFrameLength, BMI_FIFO_UNITS) + ((p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth + 5) * BMI_FIFO_UNITS));
+ /* 4 according to spec + 1 for FOF>0 */
+#else
+ optFifoSizeForB2B = minFifoSizeRequired = (uint32_t)((p_FmPort->tasks.num + 2) * BMI_FIFO_UNITS);
+#endif /* (DPAA_VERSION >= 11) */
+ }
+
+ ASSERT_COND(minFifoSizeRequired > 0);
+ ASSERT_COND(optFifoSizeForB2B >= minFifoSizeRequired);
+
+ /* Verify the size */
+ if (p_FmPort->fifoBufs.num < minFifoSizeRequired)
+ DBG(INFO, ("FIFO size should be enlarged to %d bytes", minFifoSizeRequired));
+ else if (p_FmPort->fifoBufs.num < optFifoSizeForB2B)
+ DBG(INFO, ("For back-to-back frames processing, FIFO size may need to be enlarged to %d bytes", optFifoSizeForB2B));
+
+
+ return E_OK;
+}
+
+static void FmPortDriverParamFree(t_FmPort *p_FmPort)
+{
+ if (p_FmPort->p_FmPortDriverParam)
+ {
+ XX_Free(p_FmPort->p_FmPortDriverParam);
+ p_FmPort->p_FmPortDriverParam = NULL;
+ }
+}
+
+static t_Error SetExtBufferPools(t_FmPort *p_FmPort)
+{
+ t_FmExtPools *p_ExtBufPools = &p_FmPort->p_FmPortDriverParam->extBufPools;
+ t_FmBufPoolDepletion *p_BufPoolDepletion = &p_FmPort->p_FmPortDriverParam->bufPoolDepletion;
+ uint8_t orderedArray[FM_PORT_MAX_NUM_OF_EXT_POOLS];
+ uint16_t sizesArray[BM_MAX_NUM_OF_POOLS];
+ int i=0, j=0, err;
+ struct fman_port_bpools bpools;
+
+ memset(&orderedArray, 0, sizeof(uint8_t) * FM_PORT_MAX_NUM_OF_EXT_POOLS);
+ memset(&sizesArray, 0, sizeof(uint16_t) * BM_MAX_NUM_OF_POOLS);
+ memcpy(&p_FmPort->extBufPools, p_ExtBufPools, sizeof(t_FmExtPools));
+
+ FmSpSetBufPoolsInAscOrderOfBufSizes(p_ExtBufPools, orderedArray, sizesArray);
+
+ /* Prepare flibs bpools structure */
+ memset(&bpools, 0, sizeof(struct fman_port_bpools));
+ bpools.count = p_ExtBufPools->numOfPoolsUsed;
+ bpools.counters_enable = TRUE;
+ for (i=0; i<p_ExtBufPools->numOfPoolsUsed; i++)
+ {
+ bpools.bpool[i].bpid = orderedArray[i];
+ bpools.bpool[i].size = sizesArray[orderedArray[i]];
+ /* functionality available only for some derivatives (limited by config) */
+ if (p_FmPort->p_FmPortDriverParam->p_BackupBmPools)
+ for (j=0; j<p_FmPort->p_FmPortDriverParam->p_BackupBmPools->numOfBackupPools; j++)
+ if (orderedArray[i] == p_FmPort->p_FmPortDriverParam->p_BackupBmPools->poolIds[j])
+ {
+ bpools.bpool[i].is_backup = TRUE;
+ break;
+ }
+ }
+
+ /* save pools parameters for later use */
+ p_FmPort->rxPoolsParams.numOfPools = p_ExtBufPools->numOfPoolsUsed;
+ p_FmPort->rxPoolsParams.largestBufSize = sizesArray[orderedArray[p_ExtBufPools->numOfPoolsUsed-1]];
+ p_FmPort->rxPoolsParams.secondLargestBufSize = sizesArray[orderedArray[p_ExtBufPools->numOfPoolsUsed-2]];
+
+ /* FMBM_RMPD reg. - pool depletion */
+ if (p_BufPoolDepletion->poolsGrpModeEnable)
+ {
+ bpools.grp_bp_depleted_num = p_BufPoolDepletion->numOfPools;
+ for (i=0;i<BM_MAX_NUM_OF_POOLS;i++)
+ {
+ if (p_BufPoolDepletion->poolsToConsider[i])
+ {
+ for (j=0;j<p_ExtBufPools->numOfPoolsUsed;j++)
+ {
+ if (i == orderedArray[j])
+ {
+ bpools.bpool[j].grp_bp_depleted = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (p_BufPoolDepletion->singlePoolModeEnable)
+ {
+ for (i=0;i<BM_MAX_NUM_OF_POOLS;i++)
+ {
+ if (p_BufPoolDepletion->poolsToConsiderForSingleMode[i])
+ {
+ for (j=0;j<p_ExtBufPools->numOfPoolsUsed;j++)
+ {
+ if (i == orderedArray[j])
+ {
+ bpools.bpool[j].single_bp_depleted = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+#if (DPAA_VERSION >= 11)
+ /* fill QbbPEV */
+ if (p_BufPoolDepletion->poolsGrpModeEnable ||
+ p_BufPoolDepletion->singlePoolModeEnable)
+ {
+ for (i=0; i<FM_MAX_NUM_OF_PFC_PRIORITIES; i++)
+ {
+ if (p_BufPoolDepletion->pfcPrioritiesEn[i] == TRUE)
+ {
+ bpools.bpool[i].pfc_priorities_en = TRUE;
+ }
+ }
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ /* Issue flibs function */
+ err = fman_port_set_bpools(&p_FmPort->port, &bpools);
+ if (err != 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_set_bpools"));
+
+ if (p_FmPort->p_FmPortDriverParam->p_BackupBmPools)
+ XX_Free(p_FmPort->p_FmPortDriverParam->p_BackupBmPools);
+
+ return E_OK;
+}
+
+static t_Error ClearPerfCnts(t_FmPort *p_FmPort)
+{
+ if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ FM_PORT_ModifyCounter(p_FmPort, e_FM_PORT_COUNTERS_QUEUE_UTIL, 0);
+ FM_PORT_ModifyCounter(p_FmPort, e_FM_PORT_COUNTERS_TASK_UTIL, 0);
+ FM_PORT_ModifyCounter(p_FmPort, e_FM_PORT_COUNTERS_DMA_UTIL, 0);
+ FM_PORT_ModifyCounter(p_FmPort, e_FM_PORT_COUNTERS_FIFO_UTIL, 0);
+ return E_OK;
+}
+
+
+static t_Error InitLowLevelDriver(t_FmPort *p_FmPort)
+{
+ t_FmPortDriverParam *p_DriverParams = p_FmPort->p_FmPortDriverParam;
+ struct fman_port_params portParams;
+ uint32_t tmpVal;
+ t_Error err;
+
+ /* Set up flibs parameters and issue init function */
+
+ memset(&portParams, 0, sizeof(struct fman_port_params));
+ portParams.discard_mask = p_DriverParams->errorsToDiscard;
+ portParams.dflt_fqid = p_DriverParams->dfltFqid;
+ portParams.err_fqid = p_DriverParams->errFqid;
+ portParams.deq_sp = p_DriverParams->deqSubPortal;
+ portParams.dont_release_buf = p_DriverParams->dontReleaseBuf;
+ switch (p_FmPort->portType)
+ {
+ case(e_FM_PORT_TYPE_RX_10G):
+ case(e_FM_PORT_TYPE_RX):
+ portParams.err_mask = (RX_ERRS_TO_ENQ & ~portParams.discard_mask);
+ if (!p_FmPort->imEn)
+ {
+ if (p_DriverParams->forwardReuseIntContext)
+ p_DriverParams->dfltCfg.rx_fd_bits = (uint8_t)(BMI_PORT_RFNE_FRWD_RPD >> 24);
+ }
+ break;
+
+ case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ portParams.err_mask = (OP_ERRS_TO_ENQ & ~portParams.discard_mask);
+ break;
+ break;
+
+ default:
+ break;
+ }
+
+ tmpVal = (uint32_t)((p_FmPort->internalBufferOffset % OFFSET_UNITS) ?
+ (p_FmPort->internalBufferOffset/OFFSET_UNITS + 1):
+ (p_FmPort->internalBufferOffset/OFFSET_UNITS));
+ p_FmPort->internalBufferOffset = (uint8_t)(tmpVal * OFFSET_UNITS);
+ p_DriverParams->dfltCfg.int_buf_start_margin = p_FmPort->internalBufferOffset;
+
+ p_DriverParams->dfltCfg.ext_buf_start_margin = p_DriverParams->bufMargins.startMargins;
+ p_DriverParams->dfltCfg.ext_buf_end_margin = p_DriverParams->bufMargins.endMargins;
+
+ p_DriverParams->dfltCfg.ic_ext_offset = p_DriverParams->intContext.extBufOffset;
+ p_DriverParams->dfltCfg.ic_int_offset = p_DriverParams->intContext.intContextOffset;
+ p_DriverParams->dfltCfg.ic_size = p_DriverParams->intContext.size;
+
+ p_DriverParams->dfltCfg.stats_counters_enable = TRUE;
+ p_DriverParams->dfltCfg.perf_counters_enable = TRUE;
+ p_DriverParams->dfltCfg.queue_counters_enable = TRUE;
+
+ p_DriverParams->dfltCfg.perf_cnt_params.task_val = (uint8_t)p_FmPort->tasks.num;
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING ||
+ p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)
+ p_DriverParams->dfltCfg.perf_cnt_params.queue_val = 0;
+ else
+ p_DriverParams->dfltCfg.perf_cnt_params.queue_val = 1;
+ p_DriverParams->dfltCfg.perf_cnt_params.dma_val =(uint8_t) p_FmPort->openDmas.num;
+ p_DriverParams->dfltCfg.perf_cnt_params.fifo_val = p_FmPort->fifoBufs.num;
+
+ if (0 != fman_port_init(&p_FmPort->port, &p_DriverParams->dfltCfg, &portParams))
+ RETURN_ERROR(MAJOR, E_NO_DEVICE, ("fman_port_init"));
+
+ if (p_FmPort->imEn && ((err = FmPortImInit(p_FmPort)) != E_OK))
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ else
+ {
+ // from QMIInit
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ {
+ if (p_DriverParams->deqPrefetchOption == e_FM_PORT_DEQ_NO_PREFETCH)
+ FmSetPortPreFetchConfiguration(p_FmPort->h_Fm, p_FmPort->portId, FALSE);
+ else
+ FmSetPortPreFetchConfiguration(p_FmPort->h_Fm, p_FmPort->portId, TRUE);
+ }
+ }
+ /* The code bellow is a trick so the FM will not release the buffer
+ to BM nor will try to enqueue the frame to QM */
+ if (((p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_TX)) &&
+ (!p_FmPort->imEn))
+ {
+ if (!p_DriverParams->dfltFqid && p_DriverParams->dontReleaseBuf)
+ {
+ /* override fmbm_tcfqid 0 with a false non-0 value. This will force FM to
+ * act according to tfene. Otherwise, if fmbm_tcfqid is 0 the FM will release
+ * buffers to BM regardless of fmbm_tfene
+ */
+ WRITE_UINT32(p_FmPort->port.bmi_regs->tx.fmbm_tcfqid, 0xFFFFFF);
+ WRITE_UINT32(p_FmPort->port.bmi_regs->tx.fmbm_tfene, NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE);
+ }
+ }
+
+ return E_OK;
+}
+
+
+static bool CheckRxBmiCounter(t_FmPort *p_FmPort, e_FmPortCounters counter)
+{
+ UNUSED(p_FmPort);
+
+ switch (counter)
+ {
+ case(e_FM_PORT_COUNTERS_CYCLE):
+ case(e_FM_PORT_COUNTERS_TASK_UTIL):
+ case(e_FM_PORT_COUNTERS_QUEUE_UTIL):
+ case(e_FM_PORT_COUNTERS_DMA_UTIL):
+ case(e_FM_PORT_COUNTERS_FIFO_UTIL):
+ case(e_FM_PORT_COUNTERS_RX_PAUSE_ACTIVATION):
+ case(e_FM_PORT_COUNTERS_FRAME):
+ case(e_FM_PORT_COUNTERS_DISCARD_FRAME):
+ case(e_FM_PORT_COUNTERS_RX_BAD_FRAME):
+ case(e_FM_PORT_COUNTERS_RX_LARGE_FRAME):
+ case(e_FM_PORT_COUNTERS_RX_FILTER_FRAME):
+ case(e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR):
+ case(e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD):
+ case(e_FM_PORT_COUNTERS_DEALLOC_BUF):
+ case(e_FM_PORT_COUNTERS_PREPARE_TO_ENQUEUE_COUNTER):
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+static bool CheckTxBmiCounter(t_FmPort *p_FmPort, e_FmPortCounters counter)
+{
+ UNUSED(p_FmPort);
+
+ switch (counter)
+ {
+ case(e_FM_PORT_COUNTERS_CYCLE):
+ case(e_FM_PORT_COUNTERS_TASK_UTIL):
+ case(e_FM_PORT_COUNTERS_QUEUE_UTIL):
+ case(e_FM_PORT_COUNTERS_DMA_UTIL):
+ case(e_FM_PORT_COUNTERS_FIFO_UTIL):
+ case(e_FM_PORT_COUNTERS_FRAME):
+ case(e_FM_PORT_COUNTERS_DISCARD_FRAME):
+ case(e_FM_PORT_COUNTERS_LENGTH_ERR):
+ case(e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT):
+ case(e_FM_PORT_COUNTERS_DEALLOC_BUF):
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+static bool CheckOhBmiCounter(t_FmPort *p_FmPort, e_FmPortCounters counter)
+{
+ switch (counter)
+ {
+ case(e_FM_PORT_COUNTERS_CYCLE):
+ case(e_FM_PORT_COUNTERS_TASK_UTIL):
+ case(e_FM_PORT_COUNTERS_DMA_UTIL):
+ case(e_FM_PORT_COUNTERS_FIFO_UTIL):
+ case(e_FM_PORT_COUNTERS_FRAME):
+ case(e_FM_PORT_COUNTERS_DISCARD_FRAME):
+ case(e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR):
+ case(e_FM_PORT_COUNTERS_WRED_DISCARD):
+ case(e_FM_PORT_COUNTERS_LENGTH_ERR):
+ case(e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT):
+ case(e_FM_PORT_COUNTERS_DEALLOC_BUF):
+ return TRUE;
+ case(e_FM_PORT_COUNTERS_RX_FILTER_FRAME):
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)
+ return FALSE;
+ else
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+static t_Error BmiPortCheckAndGetCounterType(t_FmPort *p_FmPort,
+ e_FmPortCounters counter,
+ enum fman_port_stats_counters *p_StatsType,
+ enum fman_port_perf_counters *p_PerfType,
+ bool *p_IsStats)
+{
+ volatile uint32_t *p_Reg;
+ bool isValid;
+
+ switch (p_FmPort->portType)
+ {
+ case(e_FM_PORT_TYPE_RX_10G):
+ case(e_FM_PORT_TYPE_RX):
+ p_Reg = &p_FmPort->port.bmi_regs->rx.fmbm_rstc;
+ isValid = CheckRxBmiCounter(p_FmPort, counter);
+ break;
+ case(e_FM_PORT_TYPE_TX_10G):
+ case(e_FM_PORT_TYPE_TX):
+ p_Reg = &p_FmPort->port.bmi_regs->tx.fmbm_tstc;
+ isValid = CheckTxBmiCounter(p_FmPort, counter);
+ break;
+ case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ case(e_FM_PORT_TYPE_OH_HOST_COMMAND):
+ p_Reg = &p_FmPort->port.bmi_regs->oh.fmbm_ostc;
+ isValid = CheckOhBmiCounter(p_FmPort, counter);
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Unsupported port type"));
+ }
+
+ if (!isValid)
+ RETURN_ERROR(MINOR, E_INVALID_STATE,
+ ("Requested counter is not available for this port type"));
+
+ /* check that counters are enabled */
+ switch (counter)
+ {
+ case(e_FM_PORT_COUNTERS_CYCLE):
+ case(e_FM_PORT_COUNTERS_TASK_UTIL):
+ case(e_FM_PORT_COUNTERS_QUEUE_UTIL):
+ case(e_FM_PORT_COUNTERS_DMA_UTIL):
+ case(e_FM_PORT_COUNTERS_FIFO_UTIL):
+ case(e_FM_PORT_COUNTERS_RX_PAUSE_ACTIVATION):
+ /* performance counters - may be read when disabled */
+ break;
+ case(e_FM_PORT_COUNTERS_FRAME):
+ case(e_FM_PORT_COUNTERS_DISCARD_FRAME):
+ case(e_FM_PORT_COUNTERS_DEALLOC_BUF):
+ case(e_FM_PORT_COUNTERS_RX_BAD_FRAME):
+ case(e_FM_PORT_COUNTERS_RX_LARGE_FRAME):
+ case(e_FM_PORT_COUNTERS_RX_FILTER_FRAME):
+ case(e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR):
+ case(e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD):
+ case(e_FM_PORT_COUNTERS_LENGTH_ERR):
+ case(e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT):
+ case(e_FM_PORT_COUNTERS_WRED_DISCARD):
+ if (!(GET_UINT32(*p_Reg) & BMI_COUNTERS_EN))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled"));
+ break;
+ default:
+ break;
+ }
+
+ /* Set counter */
+ switch (counter)
+ {
+ case(e_FM_PORT_COUNTERS_CYCLE):
+ *p_PerfType = E_FMAN_PORT_PERF_CNT_CYCLE;
+ *p_IsStats = FALSE;
+ break;
+ case(e_FM_PORT_COUNTERS_TASK_UTIL):
+ *p_PerfType = E_FMAN_PORT_PERF_CNT_TASK_UTIL;
+ break;
+ case(e_FM_PORT_COUNTERS_QUEUE_UTIL):
+ *p_PerfType = E_FMAN_PORT_PERF_CNT_QUEUE_UTIL;
+ *p_IsStats = FALSE;
+ break;
+ case(e_FM_PORT_COUNTERS_DMA_UTIL):
+ *p_PerfType = E_FMAN_PORT_PERF_CNT_DMA_UTIL;
+ *p_IsStats = FALSE;
+ break;
+ case(e_FM_PORT_COUNTERS_FIFO_UTIL):
+ *p_PerfType = E_FMAN_PORT_PERF_CNT_FIFO_UTIL;
+ *p_IsStats = FALSE;
+ break;
+ case(e_FM_PORT_COUNTERS_RX_PAUSE_ACTIVATION):
+ *p_PerfType = E_FMAN_PORT_PERF_CNT_RX_PAUSE;
+ *p_IsStats = FALSE;
+ break;
+ case(e_FM_PORT_COUNTERS_FRAME):
+ *p_StatsType = E_FMAN_PORT_STATS_CNT_FRAME;
+ *p_IsStats = TRUE;
+ break;
+ case(e_FM_PORT_COUNTERS_DISCARD_FRAME):
+ *p_StatsType = E_FMAN_PORT_STATS_CNT_DISCARD;
+ *p_IsStats = TRUE;
+ break;
+ case(e_FM_PORT_COUNTERS_DEALLOC_BUF):
+ *p_StatsType = E_FMAN_PORT_STATS_CNT_DEALLOC_BUF;
+ *p_IsStats = TRUE;
+ break;
+ case(e_FM_PORT_COUNTERS_RX_BAD_FRAME):
+ *p_StatsType = E_FMAN_PORT_STATS_CNT_RX_BAD_FRAME;
+ *p_IsStats = TRUE;
+ break;
+ case(e_FM_PORT_COUNTERS_RX_LARGE_FRAME):
+ *p_StatsType = E_FMAN_PORT_STATS_CNT_RX_LARGE_FRAME;
+ *p_IsStats = TRUE;
+ break;
+ case(e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD):
+ *p_StatsType = E_FMAN_PORT_STATS_CNT_RX_OUT_OF_BUF;
+ *p_IsStats = TRUE;
+ break;
+ case(e_FM_PORT_COUNTERS_RX_FILTER_FRAME):
+ *p_StatsType = E_FMAN_PORT_STATS_CNT_FILTERED_FRAME;
+ break;
+ case(e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR):
+ *p_StatsType = E_FMAN_PORT_STATS_CNT_DMA_ERR;
+ *p_IsStats = TRUE;
+ break;
+ case(e_FM_PORT_COUNTERS_WRED_DISCARD):
+ *p_StatsType = E_FMAN_PORT_STATS_CNT_WRED_DISCARD;
+ *p_IsStats = TRUE;
+ case(e_FM_PORT_COUNTERS_LENGTH_ERR):
+ *p_StatsType = E_FMAN_PORT_STATS_CNT_LEN_ERR;
+ *p_IsStats = TRUE;
+ case(e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT):
+ *p_StatsType = E_FMAN_PORT_STATS_CNT_UNSUPPORTED_FORMAT;
+ *p_IsStats = TRUE;
+ default:
+ break;
+ }
+
+ return E_OK;
+}
+
+
+static t_Error AdditionalPrsParams(t_FmPort *p_FmPort, t_FmPcdPrsAdditionalHdrParams *p_HdrParams, uint32_t *p_SoftSeqAttachReg)
+{
+ uint8_t hdrNum, Ipv4HdrNum;
+ u_FmPcdHdrPrsOpts *p_prsOpts;
+ uint32_t tmpReg = *p_SoftSeqAttachReg, tmpPrsOffset;
+
+ if (IS_PRIVATE_HEADER(p_HdrParams->hdr) || IS_SPECIAL_HEADER(p_HdrParams->hdr))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("No additional parameters for private or special headers."));
+
+ if (p_HdrParams->errDisable)
+ tmpReg |= PRS_HDR_ERROR_DIS;
+
+ /* Set parser options */
+ if (p_HdrParams->usePrsOpts)
+ {
+ p_prsOpts = &p_HdrParams->prsOpts;
+ switch (p_HdrParams->hdr)
+ {
+ case (HEADER_TYPE_MPLS):
+ if (p_prsOpts->mplsPrsOptions.labelInterpretationEnable)
+ tmpReg |= PRS_HDR_MPLS_LBL_INTER_EN;
+ GET_PRS_HDR_NUM(hdrNum, p_prsOpts->mplsPrsOptions.nextParse);
+ if (hdrNum == ILLEGAL_HDR_NUM)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
+ GET_PRS_HDR_NUM(Ipv4HdrNum, HEADER_TYPE_IPv4);
+ if (hdrNum < Ipv4HdrNum)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("Header must be equal or higher than IPv4"));
+ tmpReg |= ((uint32_t)hdrNum * PRS_HDR_ENTRY_SIZE) << PRS_HDR_MPLS_NEXT_HDR_SHIFT;
+ break;
+ case (HEADER_TYPE_PPPoE):
+ if (p_prsOpts->pppoePrsOptions.enableMTUCheck)
+ tmpReg |= PRS_HDR_PPPOE_MTU_CHECK_EN;
+ break;
+ case (HEADER_TYPE_IPv6):
+ if (p_prsOpts->ipv6PrsOptions.routingHdrEnable)
+ tmpReg |= PRS_HDR_IPV6_ROUTE_HDR_EN;
+ break;
+ case (HEADER_TYPE_TCP):
+ if (p_prsOpts->tcpPrsOptions.padIgnoreChecksum)
+ tmpReg |= PRS_HDR_TCP_PAD_REMOVAL;
+ else
+ tmpReg &= ~PRS_HDR_TCP_PAD_REMOVAL;
+ break;
+ case (HEADER_TYPE_UDP):
+ if (p_prsOpts->udpPrsOptions.padIgnoreChecksum)
+ tmpReg |= PRS_HDR_UDP_PAD_REMOVAL;
+ else
+ tmpReg &= ~PRS_HDR_UDP_PAD_REMOVAL;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid header"));
+ }
+ }
+
+ /* set software parsing (address is divided in 2 since parser uses 2 byte access. */
+ if (p_HdrParams->swPrsEnable)
+ {
+ tmpPrsOffset = FmPcdGetSwPrsOffset(p_FmPort->h_FmPcd, p_HdrParams->hdr, p_HdrParams->indexPerHdr);
+ if (tmpPrsOffset == ILLEGAL_BASE)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
+ tmpReg |= (PRS_HDR_SW_PRS_EN | tmpPrsOffset);
+ }
+ *p_SoftSeqAttachReg = tmpReg;
+
+ return E_OK;
+}
+
+static uint32_t GetPortSchemeBindParams(t_Handle h_FmPort, t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ uint32_t walking1Mask = 0x80000000, tmp;
+ uint8_t idx = 0;
+
+ p_SchemeBind->netEnvId = p_FmPort->netEnvId;
+ p_SchemeBind->hardwarePortId = p_FmPort->hardwarePortId;
+ p_SchemeBind->useClsPlan = p_FmPort->useClsPlan;
+ p_SchemeBind->numOfSchemes = 0;
+ tmp = p_FmPort->schemesPerPortVector;
+ if (tmp)
+ {
+ while (tmp)
+ {
+ if (tmp & walking1Mask)
+ {
+ p_SchemeBind->schemesIds[p_SchemeBind->numOfSchemes] = idx;
+ p_SchemeBind->numOfSchemes++;
+ tmp &= ~walking1Mask;
+ }
+ walking1Mask >>= 1;
+ idx++;
+ }
+ }
+
+ return tmp;
+}
+
+static t_Error SetPcd(t_FmPort *p_FmPort, t_FmPortPcdParams *p_PcdParams)
+{
+ t_Error err = E_OK;
+ uint32_t tmpReg;
+ volatile uint32_t *p_BmiNia=NULL;
+ volatile uint32_t *p_BmiPrsNia=NULL;
+ volatile uint32_t *p_BmiPrsStartOffset=NULL;
+ volatile uint32_t *p_BmiInitPrsResult=NULL;
+ volatile uint32_t *p_BmiCcBase=NULL;
+ uint8_t hdrNum, L3HdrNum, greHdrNum;
+ int i;
+ bool isEmptyClsPlanGrp;
+ uint32_t tmpHxs[FM_PCD_PRS_NUM_OF_HDRS];
+ uint16_t absoluteProfileId;
+ uint8_t physicalSchemeId;
+ uint32_t ccTreePhysOffset;
+ t_FmPcdKgInterModuleBindPortToSchemes schemeBind;
+
+ ASSERT_COND(p_FmPort);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if (p_FmPort->imEn)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independant mode ports only"));
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_RX) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+
+ p_FmPort->netEnvId = FmPcdGetNetEnvId(p_PcdParams->h_NetEnv);
+
+ p_FmPort->pcdEngines = 0;
+
+ /* initialize p_FmPort->pcdEngines field in port's structure */
+ switch (p_PcdParams->pcdSupport)
+ {
+ case (e_FM_PORT_PCD_SUPPORT_NONE):
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("No PCD configuration required if e_FM_PORT_PCD_SUPPORT_NONE selected"));
+ case (e_FM_PORT_PCD_SUPPORT_PRS_ONLY):
+ p_FmPort->pcdEngines |= FM_PCD_PRS;
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_PLCR_ONLY):
+ p_FmPort->pcdEngines |= FM_PCD_PLCR;
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR):
+ p_FmPort->pcdEngines |= FM_PCD_PRS;
+ p_FmPort->pcdEngines |= FM_PCD_PLCR;
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG):
+ p_FmPort->pcdEngines |= FM_PCD_PRS;
+ p_FmPort->pcdEngines |= FM_PCD_KG;
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC):
+ p_FmPort->pcdEngines |= FM_PCD_PRS;
+ p_FmPort->pcdEngines |= FM_PCD_CC;
+ p_FmPort->pcdEngines |= FM_PCD_KG;
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC_AND_PLCR):
+ p_FmPort->pcdEngines |= FM_PCD_PRS;
+ p_FmPort->pcdEngines |= FM_PCD_KG;
+ p_FmPort->pcdEngines |= FM_PCD_CC;
+ p_FmPort->pcdEngines |= FM_PCD_PLCR;
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_CC):
+ p_FmPort->pcdEngines |= FM_PCD_PRS;
+ p_FmPort->pcdEngines |= FM_PCD_CC;
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_CC_AND_PLCR):
+ p_FmPort->pcdEngines |= FM_PCD_PRS;
+ p_FmPort->pcdEngines |= FM_PCD_CC;
+ p_FmPort->pcdEngines |= FM_PCD_PLCR;
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR):
+ p_FmPort->pcdEngines |= FM_PCD_PRS;
+ p_FmPort->pcdEngines |= FM_PCD_KG;
+ p_FmPort->pcdEngines |= FM_PCD_PLCR;
+ break;
+#ifdef FM_CAPWAP_SUPPORT
+ case (e_FM_PORT_PCD_SUPPORT_CC_ONLY):
+ p_FmPort->pcdEngines |= FM_PCD_CC;
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_CC_AND_KG):
+ p_FmPort->pcdEngines |= FM_PCD_CC;
+ p_FmPort->pcdEngines |= FM_PCD_KG;
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_CC_AND_KG_AND_PLCR):
+ p_FmPort->pcdEngines |= FM_PCD_CC;
+ p_FmPort->pcdEngines |= FM_PCD_KG;
+ p_FmPort->pcdEngines |= FM_PCD_PLCR;
+ break;
+#endif /* FM_CAPWAP_SUPPORT */
+
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("invalid pcdSupport"));
+ }
+
+ if ((p_FmPort->pcdEngines & FM_PCD_PRS) &&
+ (p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams > FM_PCD_PRS_NUM_OF_HDRS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Port parser numOfHdrsWithAdditionalParams may not exceed %d", FM_PCD_PRS_NUM_OF_HDRS));
+
+ /* check that parameters exist for each and only each defined engine */
+ if ((!!(p_FmPort->pcdEngines & FM_PCD_PRS) != !!p_PcdParams->p_PrsParams) ||
+ (!!(p_FmPort->pcdEngines & FM_PCD_KG) != !!p_PcdParams->p_KgParams) ||
+ (!!(p_FmPort->pcdEngines & FM_PCD_CC) != !!p_PcdParams->p_CcParams))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("PCD initialization structure is not consistent with pcdSupport"));
+
+ /* get PCD registers pointers */
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiNia = &p_FmPort->port.bmi_regs->rx.fmbm_rfne;
+ p_BmiPrsNia = &p_FmPort->port.bmi_regs->rx.fmbm_rfpne;
+ p_BmiPrsStartOffset = &p_FmPort->port.bmi_regs->rx.fmbm_rpso;
+ p_BmiInitPrsResult = &p_FmPort->port.bmi_regs->rx.fmbm_rprai[0];
+ p_BmiCcBase = &p_FmPort->port.bmi_regs->rx.fmbm_rccb;
+ break;
+ case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_BmiNia = &p_FmPort->port.bmi_regs->oh.fmbm_ofne;
+ p_BmiPrsNia = &p_FmPort->port.bmi_regs->oh.fmbm_ofpne;
+ p_BmiPrsStartOffset = &p_FmPort->port.bmi_regs->oh.fmbm_opso;
+ p_BmiInitPrsResult = &p_FmPort->port.bmi_regs->oh.fmbm_oprai[0];
+ p_BmiCcBase = &p_FmPort->port.bmi_regs->oh.fmbm_occb;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ }
+
+ /* set PCD port parameter */
+ if (p_FmPort->pcdEngines & FM_PCD_CC)
+ {
+ err = FmPcdCcBindTree(p_FmPort->h_FmPcd,
+ p_PcdParams,
+ p_PcdParams->p_CcParams->h_CcTree,
+ &ccTreePhysOffset,
+ p_FmPort);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ WRITE_UINT32(*p_BmiCcBase, ccTreePhysOffset);
+ p_FmPort->ccTreeId = p_PcdParams->p_CcParams->h_CcTree;
+ }
+
+ if (p_FmPort->pcdEngines & FM_PCD_KG)
+ {
+ if (p_PcdParams->p_KgParams->numOfSchemes == 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("For ports using Keygen, at least one scheme must be bound. "));
+
+ err = FmPcdKgSetOrBindToClsPlanGrp(p_FmPort->h_FmPcd,
+ p_FmPort->hardwarePortId,
+ p_FmPort->netEnvId,
+ p_FmPort->optArray,
+ &p_FmPort->clsPlanGrpId,
+ &isEmptyClsPlanGrp);
+ if (err)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("FmPcdKgSetOrBindToClsPlanGrp failed. "));
+
+ p_FmPort->useClsPlan = !isEmptyClsPlanGrp;
+
+ schemeBind.netEnvId = p_FmPort->netEnvId;
+ schemeBind.hardwarePortId = p_FmPort->hardwarePortId;
+ schemeBind.numOfSchemes = p_PcdParams->p_KgParams->numOfSchemes;
+ schemeBind.useClsPlan = p_FmPort->useClsPlan;
+
+ /* for each scheme */
+ for (i=0; i<p_PcdParams->p_KgParams->numOfSchemes; i++)
+ {
+ ASSERT_COND(p_PcdParams->p_KgParams->h_Schemes[i]);
+ physicalSchemeId = FmPcdKgGetSchemeId(p_PcdParams->p_KgParams->h_Schemes[i]);
+ schemeBind.schemesIds[i] = physicalSchemeId;
+ /* build vector */
+ p_FmPort->schemesPerPortVector |= 1 << (31 - (uint32_t)physicalSchemeId);
+#if (DPAA_VERSION >= 11)
+ /*because of the state that VSPE is defined per port - all PCD path should be according to this requirement
+ if !VSPE - in port, for relevant scheme VSPE can not be set*/
+ if (!p_FmPort->vspe && FmPcdKgGetVspe((p_PcdParams->p_KgParams->h_Schemes[i])))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("VSPE is not at port level"));
+#endif /* (DPAA_VERSION >= 11) */
+ }
+
+ err = FmPcdKgBindPortToSchemes(p_FmPort->h_FmPcd, &schemeBind);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ /***************************/
+ /* configure NIA after BMI */
+ /***************************/
+ /* rfne may contain FDCS bits, so first we read them. */
+ p_FmPort->savedBmiNia = GET_UINT32(*p_BmiNia) & BMI_RFNE_FDCS_MASK;
+
+ /* If policer is used directly after BMI or PRS */
+ if ((p_FmPort->pcdEngines & FM_PCD_PLCR) &&
+ ((p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_PLCR_ONLY) ||
+ (p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR)))
+ {
+ if (!p_PcdParams->p_PlcrParams->h_Profile)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Profile should be initialized"));
+
+ absoluteProfileId = (uint16_t)FmPcdPlcrProfileGetAbsoluteId(p_PcdParams->p_PlcrParams->h_Profile);
+
+ if (!FmPcdPlcrIsProfileValid(p_FmPort->h_FmPcd, absoluteProfileId))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Private port profile not valid."));
+
+ tmpReg = (uint32_t)(absoluteProfileId | NIA_PLCR_ABSOLUTE);
+
+ if (p_FmPort->pcdEngines & FM_PCD_PRS) /* e_FM_PCD_SUPPORT_PRS_AND_PLCR */
+ /* update BMI HPNIA */
+ WRITE_UINT32(*p_BmiPrsNia, (uint32_t)(NIA_ENG_PLCR | tmpReg));
+ else /* e_FM_PCD_SUPPORT_PLCR_ONLY */
+ /* update BMI NIA */
+ p_FmPort->savedBmiNia |= (uint32_t)(NIA_ENG_PLCR);
+ }
+
+#ifdef FM_CAPWAP_SUPPORT
+ /* if CC is used directly after BMI */
+ if ((p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_CC_ONLY) ||
+ (p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_CC_AND_KG) ||
+ (p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_CC_AND_KG_AND_PLCR))
+ {
+ if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("e_FM_PORT_PCD_SUPPORT_CC_xx available for offline parsing ports only"));
+ p_FmPort->savedBmiNia |= (uint32_t)(NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC);
+ /* check that prs start offset == RIM[FOF] */
+ }
+#endif /* FM_CAPWAP_SUPPORT */
+
+ if (p_FmPort->pcdEngines & FM_PCD_PRS)
+ {
+ ASSERT_COND(p_PcdParams->p_PrsParams);
+ /* if PRS is used it is always first */
+ GET_PRS_HDR_NUM(hdrNum, p_PcdParams->p_PrsParams->firstPrsHdr);
+ if (hdrNum == ILLEGAL_HDR_NUM)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unsupported header."));
+ p_FmPort->savedBmiNia |= (uint32_t)(NIA_ENG_PRS | (uint32_t)(hdrNum));
+ /* set after parser NIA */
+ tmpReg = 0;
+ switch (p_PcdParams->pcdSupport)
+ {
+ case (e_FM_PORT_PCD_SUPPORT_PRS_ONLY):
+ WRITE_UINT32(*p_BmiPrsNia, GET_NIA_BMI_AC_ENQ_FRAME(p_FmPort->h_FmPcd));
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC):
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC_AND_PLCR):
+ tmpReg = NIA_KG_CC_EN;
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG):
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR):
+ if (p_PcdParams->p_KgParams->directScheme)
+ {
+ physicalSchemeId = FmPcdKgGetSchemeId(p_PcdParams->p_KgParams->h_DirectScheme);
+ /* check that this scheme was bound to this port */
+ for (i=0 ; i<p_PcdParams->p_KgParams->numOfSchemes; i++)
+ if (p_PcdParams->p_KgParams->h_DirectScheme == p_PcdParams->p_KgParams->h_Schemes[i])
+ break;
+ if (i == p_PcdParams->p_KgParams->numOfSchemes)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Direct scheme is not one of the port selected schemes."));
+ tmpReg |= (uint32_t)(NIA_KG_DIRECT | physicalSchemeId);
+ }
+ WRITE_UINT32(*p_BmiPrsNia, NIA_ENG_KG | tmpReg);
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_CC):
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_CC_AND_PLCR):
+ WRITE_UINT32(*p_BmiPrsNia, (uint32_t)(NIA_ENG_FM_CTL | NIA_FM_CTL_AC_CC));
+ break;
+ case (e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR):
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid PCD support"));
+ }
+
+ /* set start parsing offset */
+ WRITE_UINT32(*p_BmiPrsStartOffset, p_PcdParams->p_PrsParams->parsingOffset);
+
+ /************************************/
+ /* Parser port parameters */
+ /************************************/
+ /* stop before configuring */
+ WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->pcac, PRS_CAC_STOP);
+ /* wait for parser to be in idle state */
+ while (GET_UINT32(p_FmPort->p_FmPortPrsRegs->pcac) & PRS_CAC_ACTIVE) ;
+
+ /* set soft seq attachment register */
+ memset(tmpHxs, 0, FM_PCD_PRS_NUM_OF_HDRS*sizeof(uint32_t));
+
+ /* set protocol options */
+ for (i=0;p_FmPort->optArray[i];i++)
+ switch (p_FmPort->optArray[i])
+ {
+ case (ETH_BROADCAST):
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_ETH)
+ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_ETH_BC_SHIFT;
+ break;
+ case (ETH_MULTICAST):
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_ETH)
+ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_ETH_MC_SHIFT;
+ break;
+ case (VLAN_STACKED):
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_VLAN)
+ tmpHxs[hdrNum] |= (i+1)<< PRS_HDR_VLAN_STACKED_SHIFT;
+ break;
+ case (MPLS_STACKED):
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_MPLS)
+ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_MPLS_STACKED_SHIFT;
+ break;
+ case (IPV4_BROADCAST_1):
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv4)
+ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV4_1_BC_SHIFT;
+ break;
+ case (IPV4_MULTICAST_1):
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv4)
+ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV4_1_MC_SHIFT;
+ break;
+ case (IPV4_UNICAST_2):
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv4)
+ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV4_2_UC_SHIFT;
+ break;
+ case (IPV4_MULTICAST_BROADCAST_2):
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv4)
+ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV4_2_MC_BC_SHIFT;
+ break;
+ case (IPV6_MULTICAST_1):
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv6)
+ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV6_1_MC_SHIFT;
+ break;
+ case (IPV6_UNICAST_2):
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv6)
+ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV6_2_UC_SHIFT;
+ break;
+ case (IPV6_MULTICAST_2):
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv6)
+ tmpHxs[hdrNum] |= (i+1) << PRS_HDR_IPV6_2_MC_SHIFT;
+ break;
+ }
+
+ if (FmPcdNetEnvIsHdrExist(p_FmPort->h_FmPcd,
+ p_FmPort->netEnvId, HEADER_TYPE_UDP_ENCAP_ESP))
+ {
+ p_PcdParams->p_PrsParams->additionalParams
+ [p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams].hdr = HEADER_TYPE_UDP;
+ p_PcdParams->p_PrsParams->additionalParams
+ [p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams].swPrsEnable = TRUE;
+ p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams++;
+ }
+
+ /* set MPLS default next header - HW reset workaround */
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_MPLS)
+ tmpHxs[hdrNum] |= PRS_HDR_MPLS_LBL_INTER_EN;
+ GET_PRS_HDR_NUM(L3HdrNum, HEADER_TYPE_USER_DEFINED_L3);
+ tmpHxs[hdrNum] |= (uint32_t)L3HdrNum << PRS_HDR_MPLS_NEXT_HDR_SHIFT;
+
+ /* for GRE, disable errors */
+ GET_PRS_HDR_NUM(greHdrNum, HEADER_TYPE_GRE);
+ tmpHxs[greHdrNum] |= PRS_HDR_ERROR_DIS;
+
+ /* For UDP remove PAD from L4 checksum calculation */
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_UDP);
+ tmpHxs[hdrNum] |= PRS_HDR_UDP_PAD_REMOVAL;
+ /* For TCP remove PAD from L4 checksum calculation */
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_TCP);
+ tmpHxs[hdrNum] |= PRS_HDR_TCP_PAD_REMOVAL;
+
+ /* config additional params for specific headers */
+ for (i=0; i<p_PcdParams->p_PrsParams->numOfHdrsWithAdditionalParams; i++)
+ {
+ GET_PRS_HDR_NUM(hdrNum, p_PcdParams->p_PrsParams->additionalParams[i].hdr);
+ if (hdrNum== ILLEGAL_HDR_NUM)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
+ if (hdrNum==NO_HDR_NUM)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Private headers may not use additional parameters"));
+
+ err = AdditionalPrsParams(p_FmPort, &p_PcdParams->p_PrsParams->additionalParams[i], &tmpHxs[hdrNum]);
+ if (err)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
+ }
+
+ /* Check if ip-reassembly port - need to update NIAs */
+ if (p_FmPort->h_IpReassemblyManip)
+ {
+ /* link to sw parser code for IP Frag - only if no other code is applied. */
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv4)
+ if (!(tmpHxs[hdrNum] & PRS_HDR_SW_PRS_EN))
+ tmpHxs[hdrNum] |= (PRS_HDR_SW_PRS_EN | IP_FRAG_SW_PATCH_IPv4_LABEL);
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv6)
+ if (!(tmpHxs[hdrNum] & PRS_HDR_SW_PRS_EN))
+ tmpHxs[hdrNum] |= (PRS_HDR_SW_PRS_EN | IP_FRAG_SW_PATCH_IPv6_LABEL);
+ }
+
+ if (FmPcdIsAdvancedOffloadSupported(p_FmPort->h_FmPcd) &&
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
+ {
+ /* link to sw parser code for IP Frag - only if no other code is applied. */
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_IPv6)
+ if (!(tmpHxs[hdrNum] & PRS_HDR_SW_PRS_EN))
+ tmpHxs[hdrNum] |= (PRS_HDR_SW_PRS_EN | IP_FRAG_SW_PATCH_IPv6_LABEL);
+ }
+
+#ifdef FM_CAPWAP_SUPPORT
+ if (FmPcdNetEnvIsHdrExist(p_FmPort->h_FmPcd,
+ p_FmPort->netEnvId, HEADER_TYPE_UDP_LITE))
+ {
+ /* link to sw parser code for udp lite - only if no other code is applied. */
+ GET_PRS_HDR_NUM(hdrNum, HEADER_TYPE_USER_DEFINED_L4)
+ if (!(tmpHxs[hdrNum] & PRS_HDR_SW_PRS_EN))
+ tmpHxs[hdrNum] |= (PRS_HDR_SW_PRS_EN | UDP_LITE_SW_PATCH_LABEL);
+ }
+#endif /* FM_CAPWAP_SUPPORT */
+ for (i=0 ; i<FM_PCD_PRS_NUM_OF_HDRS ; i++)
+ {
+ /* For all header set LCV as taken from netEnv*/
+ WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->hdrs[i].lcv,
+ FmPcdGetLcv(p_FmPort->h_FmPcd, p_FmPort->netEnvId, (uint8_t)i));
+ /* set HXS register according to default+Additional params+protocol options */
+ WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->hdrs[i].softSeqAttach, tmpHxs[i]);
+ }
+
+ /* set tpid. */
+ tmpReg = PRS_TPID_DFLT;
+ if (p_PcdParams->p_PrsParams->setVlanTpid1)
+ {
+ tmpReg &= PRS_TPID2_MASK;
+ tmpReg |= (uint32_t)p_PcdParams->p_PrsParams->vlanTpid1 << PRS_PCTPID_SHIFT;
+ }
+ if (p_PcdParams->p_PrsParams->setVlanTpid2)
+ {
+ tmpReg &= PRS_TPID1_MASK;
+ tmpReg |= (uint32_t)p_PcdParams->p_PrsParams->vlanTpid2;
+ }
+ WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->pctpid, tmpReg);
+
+ /* enable parser */
+ WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->pcac, 0);
+
+ if (p_PcdParams->p_PrsParams->prsResultPrivateInfo)
+ p_FmPort->privateInfo = p_PcdParams->p_PrsParams->prsResultPrivateInfo;
+
+ } /* end parser */
+ else
+ p_FmPort->privateInfo = 0;
+
+ WRITE_UINT32(*p_BmiPrsStartOffset, GET_UINT32(*p_BmiPrsStartOffset) + p_FmPort->internalBufferOffset);
+
+ /* set initial parser result - used for all engines */
+ for (i=0;i<FM_PORT_PRS_RESULT_NUM_OF_WORDS;i++)
+ {
+ if (!i)
+ WRITE_UINT32(*(p_BmiInitPrsResult),
+ (uint32_t)(((uint32_t)p_FmPort->privateInfo << BMI_PR_PORTID_SHIFT)
+ | BMI_PRS_RESULT_HIGH));
+ else
+ {
+ if (i< FM_PORT_PRS_RESULT_NUM_OF_WORDS/2)
+ WRITE_UINT32(*(p_BmiInitPrsResult+i), BMI_PRS_RESULT_HIGH);
+ else
+ WRITE_UINT32(*(p_BmiInitPrsResult+i), BMI_PRS_RESULT_LOW);
+ }
+ }
+
+ return E_OK;
+}
+
+static t_Error DeletePcd(t_FmPort *p_FmPort)
+{
+ t_Error err = E_OK;
+ volatile uint32_t *p_BmiNia=NULL;
+ volatile uint32_t *p_BmiPrsStartOffset = NULL;
+
+ ASSERT_COND(p_FmPort);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if (p_FmPort->imEn)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independant mode ports only"));
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_RX) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+
+ if (!p_FmPort->pcdEngines)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("called for non PCD port"));
+
+ /* get PCD registers pointers */
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiNia = &p_FmPort->port.bmi_regs->rx.fmbm_rfne;
+ p_BmiPrsStartOffset = &p_FmPort->port.bmi_regs->rx.fmbm_rpso;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_BmiNia = &p_FmPort->port.bmi_regs->oh.fmbm_ofne;
+ p_BmiPrsStartOffset = &p_FmPort->port.bmi_regs->oh.fmbm_opso;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ }
+
+ if ((GET_UINT32(*p_BmiNia) & GET_NO_PCD_NIA_BMI_AC_ENQ_FRAME()) !=
+ GET_NO_PCD_NIA_BMI_AC_ENQ_FRAME())
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("port has to be detached previousely"));
+
+ /* "cut" PCD out of the port's flow - go to BMI */
+ /* WRITE_UINT32(*p_BmiNia, (p_FmPort->savedBmiNia & BMI_RFNE_FDCS_MASK) | (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)); */
+
+ if (p_FmPort->pcdEngines | FM_PCD_PRS)
+ {
+ WRITE_UINT32(*p_BmiPrsStartOffset, 0);
+
+ /* stop parser */
+ WRITE_UINT32(p_FmPort->p_FmPortPrsRegs->pcac, PRS_CAC_STOP);
+ /* wait for parser to be in idle state */
+ while (GET_UINT32(p_FmPort->p_FmPortPrsRegs->pcac) & PRS_CAC_ACTIVE) ;
+ }
+
+ if (p_FmPort->pcdEngines & FM_PCD_KG)
+ {
+ t_FmPcdKgInterModuleBindPortToSchemes schemeBind;
+
+ /* unbind all schemes */
+ p_FmPort->schemesPerPortVector = GetPortSchemeBindParams(p_FmPort, &schemeBind);
+
+ err = FmPcdKgUnbindPortToSchemes(p_FmPort->h_FmPcd, &schemeBind);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ err = FmPcdKgDeleteOrUnbindPortToClsPlanGrp(p_FmPort->h_FmPcd, p_FmPort->hardwarePortId, p_FmPort->clsPlanGrpId);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ p_FmPort->useClsPlan = FALSE;
+ }
+
+ if (p_FmPort->pcdEngines & FM_PCD_CC)
+ {
+ /* unbind - we need to get the treeId too */
+ err = FmPcdCcUnbindTree(p_FmPort->h_FmPcd, p_FmPort->ccTreeId);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ p_FmPort->pcdEngines = 0;
+
+ return E_OK;
+}
+
+static t_Error AttachPCD(t_FmPort *p_FmPort)
+{
+ volatile uint32_t *p_BmiNia=NULL;
+
+ ASSERT_COND(p_FmPort);
+
+ /* get PCD registers pointers */
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ p_BmiNia = &p_FmPort->port.bmi_regs->oh.fmbm_ofne;
+ else
+ p_BmiNia = &p_FmPort->port.bmi_regs->rx.fmbm_rfne;
+
+ /* check that current NIA is BMI to BMI */
+ if ((GET_UINT32(*p_BmiNia) & ~BMI_RFNE_FDCS_MASK) != GET_NO_PCD_NIA_BMI_AC_ENQ_FRAME())
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION,
+ ("may be called only for ports in BMI-to-BMI state."));
+
+ if (p_FmPort->requiredAction & UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY)
+ if (FmSetNumOfRiscsPerPort(p_FmPort->h_Fm, p_FmPort->hardwarePortId, 1, p_FmPort->orFmanCtrl)!= E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ if (p_FmPort->requiredAction & UPDATE_NIA_CMNE)
+ {
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ WRITE_UINT32(p_FmPort->port.bmi_regs->oh.fmbm_ocmne, p_FmPort->savedBmiCmne);
+ else
+ WRITE_UINT32(p_FmPort->port.bmi_regs->rx.fmbm_rcmne, p_FmPort->savedBmiCmne);
+ }
+
+ if (p_FmPort->requiredAction & UPDATE_NIA_PNEN)
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->fmqm_pnen, p_FmPort->savedQmiPnen);
+
+ if (p_FmPort->requiredAction & UPDATE_NIA_FENE)
+ {
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ WRITE_UINT32(p_FmPort->port.bmi_regs->oh.fmbm_ofene, p_FmPort->savedBmiFene);
+ else
+ WRITE_UINT32(p_FmPort->port.bmi_regs->rx.fmbm_rfene, p_FmPort->savedBmiFene);
+ }
+
+ if (p_FmPort->requiredAction & UPDATE_NIA_FPNE)
+ {
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ WRITE_UINT32(p_FmPort->port.bmi_regs->oh.fmbm_ofpne, p_FmPort->savedBmiFpne);
+ else
+ WRITE_UINT32(p_FmPort->port.bmi_regs->rx.fmbm_rfpne, p_FmPort->savedBmiFpne);
+ }
+
+ WRITE_UINT32(*p_BmiNia, p_FmPort->savedBmiNia);
+
+ if (p_FmPort->requiredAction & UPDATE_NIA_PNDN)
+ {
+ p_FmPort->origNonRxQmiRegsPndn = GET_UINT32(p_FmPort->port.qmi_regs->fmqm_pndn);
+ WRITE_UINT32(p_FmPort->port.qmi_regs->fmqm_pndn, p_FmPort->savedNonRxQmiRegsPndn);
+ }
+
+ return E_OK;
+}
+
+static t_Error DetachPCD(t_FmPort *p_FmPort)
+{
+ volatile uint32_t *p_BmiNia=NULL;
+
+ ASSERT_COND(p_FmPort);
+
+ /* get PCD registers pointers */
+ if (p_FmPort->requiredAction & UPDATE_NIA_PNDN)
+ WRITE_UINT32(p_FmPort->port.qmi_regs->fmqm_pndn, p_FmPort->origNonRxQmiRegsPndn);
+
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ p_BmiNia = &p_FmPort->port.bmi_regs->oh.fmbm_ofne;
+ else
+ p_BmiNia = &p_FmPort->port.bmi_regs->rx.fmbm_rfne;
+
+ WRITE_UINT32(*p_BmiNia, (p_FmPort->savedBmiNia & BMI_RFNE_FDCS_MASK) |
+ GET_NO_PCD_NIA_BMI_AC_ENQ_FRAME());
+
+ if (FmPcdGetHcHandle(p_FmPort->h_FmPcd))
+ FmPcdHcSync(p_FmPort->h_FmPcd);
+
+ if (p_FmPort->requiredAction & UPDATE_NIA_FENE)
+ {
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ WRITE_UINT32(p_FmPort->port.bmi_regs->oh.fmbm_ofene, NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR);
+ else
+ WRITE_UINT32(p_FmPort->port.bmi_regs->rx.fmbm_rfene, NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR);
+ }
+
+ if (p_FmPort->requiredAction & UPDATE_NIA_PNEN)
+ WRITE_UINT32(p_FmPort->port.qmi_regs->fmqm_pnen, NIA_ENG_BMI | NIA_BMI_AC_RELEASE);
+
+ if (p_FmPort->requiredAction & UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY)
+ if (FmSetNumOfRiscsPerPort(p_FmPort->h_Fm, p_FmPort->hardwarePortId, 2, p_FmPort->orFmanCtrl)!= E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ p_FmPort->requiredAction = 0;
+
+ return E_OK;
+}
+
+
+/*****************************************************************************/
+/* Inter-module API routines */
+/*****************************************************************************/
+
+void FmPortSetMacsecLcv(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ volatile uint32_t *p_BmiCfgReg = NULL;
+ uint32_t macsecEn = BMI_PORT_CFG_EN_MACSEC;
+ uint32_t lcv, walking1Mask = 0x80000000;
+ uint8_t cnt = 0;
+
+ SANITY_CHECK_RETURN(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_OPERATION, ("The routine is relevant for Rx ports only"));
+ return;
+ }
+
+ p_BmiCfgReg = &p_FmPort->port.bmi_regs->rx.fmbm_rcfg;
+ /* get LCV for MACSEC */
+ if ((p_FmPort->h_FmPcd) && ((lcv = FmPcdGetMacsecLcv(p_FmPort->h_FmPcd, p_FmPort->netEnvId))!= 0))
+ {
+ while (!(lcv & walking1Mask))
+ {
+ cnt++;
+ walking1Mask >>= 1;
+ }
+
+ macsecEn |= (uint32_t)cnt << BMI_PORT_CFG_MS_SEL_SHIFT;
+ }
+
+ WRITE_UINT32(*p_BmiCfgReg, GET_UINT32(*p_BmiCfgReg) | macsecEn);
+}
+
+void FmPortSetMacsecCmd(t_Handle h_FmPort, uint8_t dfltSci)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ volatile uint32_t *p_BmiCfgReg = NULL;
+ uint32_t tmpReg;
+
+ SANITY_CHECK_RETURN(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN(p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_TX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_TX))
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_OPERATION, ("The routine is relevant for Tx ports only"));
+ return;
+ }
+
+ p_BmiCfgReg = &p_FmPort->port.bmi_regs->tx.fmbm_tfca;
+ tmpReg = GET_UINT32(*p_BmiCfgReg) & ~BMI_CMD_ATTR_MACCMD_MASK;
+ tmpReg |= BMI_CMD_ATTR_MACCMD_SECURED;
+ tmpReg |= (((uint32_t)dfltSci << BMI_CMD_ATTR_MACCMD_SC_SHIFT) & BMI_CMD_ATTR_MACCMD_SC_MASK);
+
+ WRITE_UINT32(*p_BmiCfgReg, tmpReg);
+}
+
+uint8_t FmPortGetNetEnvId(t_Handle h_FmPort)
+{
+ return ((t_FmPort*)h_FmPort)->netEnvId;
+}
+
+uint8_t FmPortGetHardwarePortId(t_Handle h_FmPort)
+{
+ return ((t_FmPort*)h_FmPort)->hardwarePortId;
+}
+
+uint32_t FmPortGetPcdEngines(t_Handle h_FmPort)
+{
+ return ((t_FmPort*)h_FmPort)->pcdEngines;
+}
+
+#if (DPAA_VERSION >= 11)
+t_Error FmPortSetGprFunc(t_Handle h_FmPort, e_FmPortGprFuncType gprFunc, void **p_Value)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ uint32_t muramPageOffset;
+
+ ASSERT_COND(p_FmPort);
+ ASSERT_COND(p_Value);
+
+ if (p_FmPort->gprFunc != e_FM_PORT_GPR_EMPTY)
+ {
+ if (p_FmPort->gprFunc != gprFunc)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("gpr was assigned with different func"));
+ }
+ else
+ {
+ switch (gprFunc)
+ {
+ case (e_FM_PORT_GPR_MURAM_PAGE):
+ p_FmPort->p_ParamsPage = FM_MURAM_AllocMem(p_FmPort->h_FmMuram,
+ 256,
+ 8);
+ if (!p_FmPort->p_ParamsPage)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for page"));
+
+ IOMemSet32(p_FmPort->p_ParamsPage, 0, 256);
+ muramPageOffset = (uint32_t)(XX_VirtToPhys(p_FmPort->p_ParamsPage) -
+ p_FmPort->fmMuramPhysBaseAddr);
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr, muramPageOffset);
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ogpr, muramPageOffset);
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ }
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+ p_FmPort->gprFunc = gprFunc;
+ }
+
+ switch (p_FmPort->gprFunc)
+ {
+ case (e_FM_PORT_GPR_MURAM_PAGE):
+ *p_Value = p_FmPort->p_ParamsPage;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, NO_MSG);
+ }
+
+ return E_OK;
+}
+#endif /* (DPAA_VERSION >= 11) */
+
+t_Error FmPortGetSetCcParams(t_Handle h_FmPort, t_FmPortGetSetCcParams *p_CcParams)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ int tmpInt;
+ volatile uint32_t *p_BmiPrsStartOffset = NULL;
+
+ /* this function called from Cc for pass and receive parameters port params between CC and PORT*/
+
+ if ((p_CcParams->getCcParams.type & OFFSET_OF_PR) &&
+ (p_FmPort->bufferOffsets.prsResultOffset != ILLEGAL_BASE))
+ {
+ p_CcParams->getCcParams.prOffset = (uint8_t)p_FmPort->bufferOffsets.prsResultOffset;
+ p_CcParams->getCcParams.type &= ~OFFSET_OF_PR;
+ }
+ if (p_CcParams->getCcParams.type & HW_PORT_ID)
+ {
+ p_CcParams->getCcParams.hardwarePortId = (uint8_t)p_FmPort->hardwarePortId;
+ p_CcParams->getCcParams.type &= ~HW_PORT_ID;
+ }
+ if ((p_CcParams->getCcParams.type & OFFSET_OF_DATA) &&
+ (p_FmPort->bufferOffsets.dataOffset != ILLEGAL_BASE))
+ {
+ p_CcParams->getCcParams.dataOffset = (uint16_t)p_FmPort->bufferOffsets.dataOffset;
+ p_CcParams->getCcParams.type &= ~OFFSET_OF_DATA;
+ }
+ if (p_CcParams->getCcParams.type & NUM_OF_TASKS)
+ {
+ p_CcParams->getCcParams.numOfTasks = (uint8_t)p_FmPort->tasks.num;
+ p_CcParams->getCcParams.type &= ~NUM_OF_TASKS;
+ }
+ if (p_CcParams->getCcParams.type & NUM_OF_EXTRA_TASKS)
+ {
+ p_CcParams->getCcParams.numOfExtraTasks = (uint8_t)p_FmPort->tasks.extra;
+ p_CcParams->getCcParams.type &= ~NUM_OF_EXTRA_TASKS;
+ }
+ if (p_CcParams->getCcParams.type & FM_REV)
+ {
+ p_CcParams->getCcParams.revInfo.majorRev = p_FmPort->fmRevInfo.majorRev;
+ p_CcParams->getCcParams.revInfo.minorRev = p_FmPort->fmRevInfo.minorRev;
+ p_CcParams->getCcParams.type &= ~FM_REV;
+ }
+ if (p_CcParams->getCcParams.type & DISCARD_MASK)
+ {
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ p_CcParams->getCcParams.discardMask =
+ GET_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofsdm);
+ else
+ p_CcParams->getCcParams.discardMask =
+ GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfsdm);
+ p_CcParams->getCcParams.type &= ~DISCARD_MASK;
+ }
+ if (p_CcParams->getCcParams.type & MANIP_EXTRA_SPACE)
+ {
+ p_CcParams->getCcParams.internalBufferOffset = p_FmPort->internalBufferOffset;
+ p_CcParams->getCcParams.type &= ~MANIP_EXTRA_SPACE;
+ }
+ if (p_CcParams->getCcParams.type & GET_NIA_FPNE)
+ {
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ p_CcParams->getCcParams.nia = GET_UINT32(p_FmPort->port.bmi_regs->oh.fmbm_ofpne);
+ else
+ p_CcParams->getCcParams.nia = GET_UINT32(p_FmPort->port.bmi_regs->rx.fmbm_rfpne);
+ p_CcParams->getCcParams.type &= ~GET_NIA_FPNE;
+ }
+ if (p_CcParams->getCcParams.type & GET_NIA_PNDN)
+ {
+ if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ p_CcParams->getCcParams.nia = GET_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndn);
+ p_CcParams->getCcParams.type &= ~GET_NIA_PNDN;
+ }
+
+ if ((p_CcParams->setCcParams.type & UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY) &&
+ !(p_FmPort->requiredAction & UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY))
+ {
+ p_FmPort->requiredAction |= UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY;
+ p_FmPort->orFmanCtrl = p_CcParams->setCcParams.orFmanCtrl;
+ }
+
+ if ((p_CcParams->setCcParams.type & UPDATE_NIA_PNEN) &&
+ !(p_FmPort->requiredAction & UPDATE_NIA_PNEN))
+ {
+ p_FmPort->savedQmiPnen = p_CcParams->setCcParams.nia;
+ p_FmPort->requiredAction |= UPDATE_NIA_PNEN;
+ }
+ else if (p_CcParams->setCcParams.type & UPDATE_NIA_PNEN)
+ {
+ if (p_FmPort->savedQmiPnen != p_CcParams->setCcParams.nia)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("PNEN was defined previously different"));
+ }
+
+ if ((p_CcParams->setCcParams.type & UPDATE_NIA_PNDN) &&
+ !(p_FmPort->requiredAction & UPDATE_NIA_PNDN))
+ {
+ p_FmPort->savedNonRxQmiRegsPndn = p_CcParams->setCcParams.nia;
+ p_FmPort->requiredAction |= UPDATE_NIA_PNDN;
+ }
+ else if (p_CcParams->setCcParams.type & UPDATE_NIA_PNDN)
+ {
+ if (p_FmPort->savedNonRxQmiRegsPndn != p_CcParams->setCcParams.nia)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("PNDN was defined previously different"));
+ }
+
+ if ((p_CcParams->setCcParams.type & UPDATE_NIA_FENE) &&
+ (p_CcParams->setCcParams.overwrite ||
+ !(p_FmPort->requiredAction & UPDATE_NIA_FENE)))
+ {
+ p_FmPort->savedBmiFene = p_CcParams->setCcParams.nia;
+ p_FmPort->requiredAction |= UPDATE_NIA_FENE;
+ }
+ else if (p_CcParams->setCcParams.type & UPDATE_NIA_FENE)
+ {
+ if (p_FmPort->savedBmiFene != p_CcParams->setCcParams.nia)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("xFENE was defined previously different"));
+ }
+
+ if ((p_CcParams->setCcParams.type & UPDATE_NIA_FPNE) &&
+ !(p_FmPort->requiredAction & UPDATE_NIA_FPNE))
+ {
+ p_FmPort->savedBmiFpne = p_CcParams->setCcParams.nia;
+ p_FmPort->requiredAction |= UPDATE_NIA_FPNE;
+ }
+ else if (p_CcParams->setCcParams.type & UPDATE_NIA_FPNE)
+ {
+ if (p_FmPort->savedBmiFpne != p_CcParams->setCcParams.nia)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("xFPNE was defined previously different"));
+ }
+
+ if ((p_CcParams->setCcParams.type & UPDATE_NIA_CMNE) &&
+ !(p_FmPort->requiredAction & UPDATE_NIA_CMNE))
+ {
+ p_FmPort->savedBmiCmne = p_CcParams->setCcParams.nia;
+ p_FmPort->requiredAction |= UPDATE_NIA_CMNE;
+ }
+ else if (p_CcParams->setCcParams.type & UPDATE_NIA_CMNE)
+ {
+ if (p_FmPort->savedBmiCmne != p_CcParams->setCcParams.nia)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("xCMNE was defined previously different"));
+ }
+
+ if ((p_CcParams->setCcParams.type & UPDATE_PSO) &&
+ !(p_FmPort->requiredAction & UPDATE_PSO))
+ {
+ /* get PCD registers pointers */
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiPrsStartOffset = &p_FmPort->port.bmi_regs->rx.fmbm_rpso;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_BmiPrsStartOffset = &p_FmPort->port.bmi_regs->oh.fmbm_opso;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ }
+
+ /* set start parsing offset */
+ tmpInt = (int)GET_UINT32(*p_BmiPrsStartOffset)+ p_CcParams->setCcParams.psoSize;
+ if (tmpInt>0)
+ WRITE_UINT32(*p_BmiPrsStartOffset, (uint32_t)tmpInt);
+
+ p_FmPort->requiredAction |= UPDATE_PSO;
+ p_FmPort->savedPrsStartOffset = p_CcParams->setCcParams.psoSize;
+ }
+ else if (p_CcParams->setCcParams.type & UPDATE_PSO)
+ {
+ if (p_FmPort->savedPrsStartOffset != p_CcParams->setCcParams.psoSize)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("parser start offset was defoned previousley different"));
+ }
+
+ return E_OK;
+}
+/*********************** End of inter-module routines ************************/
+
+
+/****************************************/
+/* API Init unit functions */
+/****************************************/
+
+t_Handle FM_PORT_Config(t_FmPortParams *p_FmPortParams)
+{
+ t_FmPort *p_FmPort;
+ uintptr_t baseAddr = p_FmPortParams->baseAddr;
+ uint32_t tmpReg;
+
+ /* Allocate FM structure */
+ p_FmPort = (t_FmPort *) XX_Malloc(sizeof(t_FmPort));
+ if (!p_FmPort)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Port driver structure"));
+ return NULL;
+ }
+ memset(p_FmPort, 0, sizeof(t_FmPort));
+
+ /* Allocate the FM driver's parameters structure */
+ p_FmPort->p_FmPortDriverParam = (t_FmPortDriverParam *)XX_Malloc(sizeof(t_FmPortDriverParam));
+ if (!p_FmPort->p_FmPortDriverParam)
+ {
+ XX_Free(p_FmPort);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Port driver parameters"));
+ return NULL;
+ }
+ memset(p_FmPort->p_FmPortDriverParam, 0, sizeof(t_FmPortDriverParam));
+
+ /* Initialize FM port parameters which will be kept by the driver */
+ p_FmPort->portType = p_FmPortParams->portType;
+ p_FmPort->portId = p_FmPortParams->portId;
+ p_FmPort->pcdEngines = FM_PCD_NONE;
+ p_FmPort->f_Exception = p_FmPortParams->f_Exception;
+ p_FmPort->h_App = p_FmPortParams->h_App;
+ p_FmPort->h_Fm = p_FmPortParams->h_Fm;
+
+ /* get FM revision */
+ FM_GetRevision(p_FmPort->h_Fm, &p_FmPort->fmRevInfo);
+
+ /* calculate global portId number */
+ SW_PORT_ID_TO_HW_PORT_ID(p_FmPort->hardwarePortId, p_FmPort->portType, p_FmPortParams->portId);
+
+ if (p_FmPort->fmRevInfo.majorRev >= 6)
+ {
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND) &&
+ (p_FmPortParams->portId != FM_OH_PORT_ID))
+ DBG(WARNING,
+ ("Port ID %d is recommended for HC port. Overwriting HW defaults to be suitable for HC.",
+ FM_OH_PORT_ID));
+
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) &&
+ (p_FmPortParams->portId == FM_OH_PORT_ID))
+ DBG(WARNING, ("Use non-zero portId for OP port due to insufficient resources on portId 0."));
+ }
+
+ /* Set up FM port parameters for initialization phase only */
+
+ /* First, fill in flibs struct */
+ fman_port_defconfig(&p_FmPort->p_FmPortDriverParam->dfltCfg, (enum fman_port_type)p_FmPort->portType);
+ /* Overwrite some integration specific parameters */
+ p_FmPort->p_FmPortDriverParam->dfltCfg.rx_pri_elevation = DEFAULT_PORT_rxFifoPriElevationLevel;
+ p_FmPort->p_FmPortDriverParam->dfltCfg.rx_fifo_thr = DEFAULT_PORT_rxFifoThreshold;
+
+#if defined(FM_OP_NO_VSP_NO_RELEASE_ERRATA_FMAN_A006675) || defined(FM_ERROR_VSP_NO_MATCH_SW006)
+ p_FmPort->p_FmPortDriverParam->dfltCfg.errata_A006675 = TRUE;
+#else
+ p_FmPort->p_FmPortDriverParam->dfltCfg.errata_A006675 = FALSE;
+#endif
+ if ((p_FmPort->fmRevInfo.majorRev == 6) && (p_FmPort->fmRevInfo.minorRev == 0))
+ p_FmPort->p_FmPortDriverParam->dfltCfg.errata_A006320 = TRUE;
+ else
+ p_FmPort->p_FmPortDriverParam->dfltCfg.errata_A006320 = FALSE;
+
+ /* Excessive Threshold register - exists for pre-FMv3 chips only */
+ if (p_FmPort->fmRevInfo.majorRev < 6)
+ {
+#ifdef FM_NO_RESTRICT_ON_ACCESS_RSRC
+ p_FmPort->p_FmPortDriverParam->dfltCfg.excessive_threshold_register = TRUE;
+#endif
+ p_FmPort->p_FmPortDriverParam->dfltCfg.fmbm_rebm_has_sgd = FALSE;
+ p_FmPort->p_FmPortDriverParam->dfltCfg.fmbm_tfne_has_features = FALSE;
+ }
+ else
+ {
+ p_FmPort->p_FmPortDriverParam->dfltCfg.excessive_threshold_register = FALSE;
+ p_FmPort->p_FmPortDriverParam->dfltCfg.fmbm_rebm_has_sgd = TRUE;
+ p_FmPort->p_FmPortDriverParam->dfltCfg.fmbm_tfne_has_features = TRUE;
+ }
+ if (p_FmPort->fmRevInfo.majorRev == 4)
+ p_FmPort->p_FmPortDriverParam->dfltCfg.qmi_deq_options_support = FALSE;
+ else
+ p_FmPort->p_FmPortDriverParam->dfltCfg.qmi_deq_options_support = TRUE;
+
+ /* Continue with other parameters */
+ p_FmPort->p_FmPortDriverParam->baseAddr = baseAddr;
+ /* set memory map pointers */
+ p_FmPort->p_FmPortQmiRegs = (t_FmPortQmiRegs *)UINT_TO_PTR(baseAddr + QMI_PORT_REGS_OFFSET);
+ p_FmPort->p_FmPortBmiRegs = (u_FmPortBmiRegs *)UINT_TO_PTR(baseAddr + BMI_PORT_REGS_OFFSET);
+ p_FmPort->p_FmPortPrsRegs = (t_FmPortPrsRegs *)UINT_TO_PTR(baseAddr + PRS_PORT_REGS_OFFSET);
+
+ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.privDataSize = DEFAULT_PORT_bufferPrefixContent_privDataSize;
+ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passPrsResult= DEFAULT_PORT_bufferPrefixContent_passPrsResult;
+ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passTimeStamp= DEFAULT_PORT_bufferPrefixContent_passTimeStamp;
+ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.passAllOtherPCDInfo
+ = DEFAULT_PORT_bufferPrefixContent_passTimeStamp;
+ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.dataAlign = DEFAULT_PORT_bufferPrefixContent_dataAlign;
+/* p_FmPort->p_FmPortDriverParam->dmaSwapData = (e_FmDmaSwapOption)DEFAULT_PORT_dmaSwapData;
+ p_FmPort->p_FmPortDriverParam->dmaIntContextCacheAttr = (e_FmDmaCacheOption)DEFAULT_PORT_dmaIntContextCacheAttr;
+ p_FmPort->p_FmPortDriverParam->dmaHeaderCacheAttr = (e_FmDmaCacheOption)DEFAULT_PORT_dmaHeaderCacheAttr;
+ p_FmPort->p_FmPortDriverParam->dmaScatterGatherCacheAttr = (e_FmDmaCacheOption)DEFAULT_PORT_dmaScatterGatherCacheAttr;
+ p_FmPort->p_FmPortDriverParam->dmaWriteOptimize = DEFAULT_PORT_dmaWriteOptimize;
+*/ p_FmPort->p_FmPortDriverParam->liodnBase = p_FmPortParams->liodnBase;
+ p_FmPort->p_FmPortDriverParam->cheksumLastBytesIgnore = DEFAULT_PORT_cheksumLastBytesIgnore;
+
+ p_FmPort->maxFrameLength = DEFAULT_PORT_maxFrameLength;
+ /* resource distribution. */
+#ifdef FM_NO_GUARANTEED_RESET_VALUES
+ if (1) /* if (p_FmPort->fmRevInfo.majorRev < 6) */
+ {
+ p_FmPort->fifoBufs.num = DEFAULT_PORT_numOfFifoBufs(p_FmPort->portType)*BMI_FIFO_UNITS;
+ p_FmPort->fifoBufs.extra = DEFAULT_PORT_extraNumOfFifoBufs*BMI_FIFO_UNITS;
+ p_FmPort->openDmas.num = DEFAULT_PORT_numOfOpenDmas(p_FmPort->portType);
+ p_FmPort->openDmas.extra = DEFAULT_PORT_extraNumOfOpenDmas(p_FmPort->portType);
+ p_FmPort->tasks.num = DEFAULT_PORT_numOfTasks(p_FmPort->portType);
+ p_FmPort->tasks.extra = DEFAULT_PORT_extraNumOfTasks(p_FmPort->portType);
+ }
+ else
+#endif /* FM_NO_GUARANTEED_RESET_VALUES */
+ {
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND) &&
+ (p_FmPortParams->portId != FM_OH_PORT_ID))
+ {
+ /* Overwrite HC defaults */
+ p_FmPort->fifoBufs.num = DEFAULT_PORT_numOfFifoBufs(p_FmPort->portType)*BMI_FIFO_UNITS;
+ p_FmPort->fifoBufs.extra = DEFAULT_PORT_extraNumOfFifoBufs*BMI_FIFO_UNITS;
+ p_FmPort->openDmas.num = DEFAULT_PORT_numOfOpenDmas(p_FmPort->portType);
+ p_FmPort->openDmas.extra = DEFAULT_PORT_extraNumOfOpenDmas(p_FmPort->portType);
+ p_FmPort->tasks.num = DEFAULT_PORT_numOfTasks(p_FmPort->portType);
+ p_FmPort->tasks.extra = DEFAULT_PORT_extraNumOfTasks(p_FmPort->portType);
+ }
+ else
+ {
+ p_FmPort->fifoBufs.num = 0;
+ p_FmPort->fifoBufs.extra = 0;
+ p_FmPort->openDmas.num = 0;
+ p_FmPort->openDmas.extra = 0;
+ p_FmPort->tasks.num = 0;
+ p_FmPort->tasks.extra = 0;
+ }
+ }
+
+#ifdef FM_HEAVY_TRAFFIC_SEQUENCER_HANG_ERRATA_FMAN_A006981
+ if ((p_FmPort->fmRevInfo.majorRev == 6) &&
+ (p_FmPort->fmRevInfo.minorRev == 0) &&
+ ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_TX)))
+ {
+ p_FmPort->openDmas.num = 16;
+ p_FmPort->openDmas.extra = 0;
+ }
+#endif /* FM_HEAVY_TRAFFIC_SEQUENCER_HANG_ERRATA_FMAN_A006981 */
+
+ /* Port type specific initialization: */
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX):
+ case (e_FM_PORT_TYPE_RX_10G):
+ /* Initialize FM port parameters for initialization phase only */
+ p_FmPort->p_FmPortDriverParam->cutBytesFromEnd = DEFAULT_PORT_cutBytesFromEnd;
+ p_FmPort->p_FmPortDriverParam->enBufPoolDepletion = FALSE;
+ p_FmPort->p_FmPortDriverParam->frmDiscardOverride = DEFAULT_PORT_frmDiscardOverride;
+#ifdef FM_NO_GUARANTEED_RESET_VALUES
+ if (1) /* if (p_FmPort->fmRevInfo.majorRev < 6) */
+ {
+ p_FmPort->p_FmPortDriverParam->rxFifoPriElevationLevel = DEFAULT_PORT_rxFifoPriElevationLevel;
+ p_FmPort->p_FmPortDriverParam->rxFifoThreshold = DEFAULT_PORT_rxFifoThreshold;
+ }
+ else
+#endif /* FM_NO_GUARANTEED_RESET_VALUES */
+ {
+ tmpReg = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfp);
+ p_FmPort->p_FmPortDriverParam->rxFifoPriElevationLevel = (((tmpReg & BMI_RX_FIFO_PRI_ELEVATION_MASK) >> BMI_RX_FIFO_PRI_ELEVATION_SHIFT) + 1) * BMI_FIFO_UNITS ;
+ p_FmPort->p_FmPortDriverParam->rxFifoThreshold = (((tmpReg & BMI_RX_FIFO_THRESHOLD_MASK) >> BMI_RX_FIFO_THRESHOLD_SHIFT) + 1) * BMI_FIFO_UNITS;
+ }
+
+ p_FmPort->p_FmPortDriverParam->bufMargins.endMargins = DEFAULT_PORT_BufMargins_endMargins;
+ p_FmPort->p_FmPortDriverParam->errorsToDiscard = DEFAULT_PORT_errorsToDiscard;
+ p_FmPort->p_FmPortDriverParam->forwardReuseIntContext = DEFAULT_PORT_forwardIntContextReuse;
+#if (DPAA_VERSION >= 11)
+ p_FmPort->p_FmPortDriverParam->noScatherGather = DEFAULT_PORT_noScatherGather;
+#endif /* (DPAA_VERSION >= 11) */
+ break;
+
+ case (e_FM_PORT_TYPE_TX):
+ p_FmPort->p_FmPortDriverParam->dontReleaseBuf = FALSE;
+#ifdef FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127
+ tmpReg = 0x00001013;
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tfp, tmpReg);
+#endif /* FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127 */
+ case (e_FM_PORT_TYPE_TX_10G):
+#ifdef FM_NO_GUARANTEED_RESET_VALUES
+ if (1) /* if (p_FmPort->fmRevInfo.majorRev < 6) */
+ {
+ p_FmPort->p_FmPortDriverParam->txFifoMinFillLevel = DEFAULT_PORT_txFifoMinFillLevel;
+ p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth =
+ (uint8_t)((p_FmPort->portType == e_FM_PORT_TYPE_TX) ?
+ DEFAULT_PORT_fifoDeqPipelineDepth_1G :
+ DEFAULT_PORT_fifoDeqPipelineDepth_10G);
+ p_FmPort->p_FmPortDriverParam->txFifoLowComfLevel = DEFAULT_PORT_txFifoLowComfLevel;
+ }
+ else
+#endif /* FM_NO_GUARANTEED_RESET_VALUES */
+ {
+ tmpReg = GET_UINT32(p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tfp);
+ p_FmPort->p_FmPortDriverParam->txFifoMinFillLevel =
+ ((tmpReg & BMI_TX_FIFO_MIN_FILL_MASK) >> BMI_TX_FIFO_MIN_FILL_SHIFT) * BMI_FIFO_UNITS ;
+ p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth =
+ (uint8_t)(((tmpReg & BMI_FIFO_PIPELINE_DEPTH_MASK) >> BMI_FIFO_PIPELINE_DEPTH_SHIFT) + 1);
+ p_FmPort->p_FmPortDriverParam->txFifoLowComfLevel =
+ (((tmpReg & BMI_TX_LOW_COMF_MASK) >> BMI_TX_LOW_COMF_SHIFT) + 1) * BMI_FIFO_UNITS;
+ }
+
+ p_FmPort->p_FmPortDriverParam->deqType = DEFAULT_PORT_deqType;
+ p_FmPort->p_FmPortDriverParam->deqPrefetchOption = DEFAULT_PORT_deqPrefetchOption;
+ p_FmPort->p_FmPortDriverParam->deqHighPriority =
+ (bool)((p_FmPort->portType == e_FM_PORT_TYPE_TX) ?
+ DEFAULT_PORT_deqHighPriority_1G :
+ DEFAULT_PORT_deqHighPriority_10G);
+ p_FmPort->p_FmPortDriverParam->deqByteCnt =
+ (uint16_t)((p_FmPort->portType == e_FM_PORT_TYPE_TX) ?
+ DEFAULT_PORT_deqByteCnt_1G :
+ DEFAULT_PORT_deqByteCnt_10G);
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_FmPort->p_FmPortDriverParam->errorsToDiscard = DEFAULT_PORT_errorsToDiscard;
+#if (DPAA_VERSION >= 11)
+ p_FmPort->p_FmPortDriverParam->noScatherGather = DEFAULT_PORT_noScatherGather;
+#endif /* (DPAA_VERSION >= 11) */
+ case (e_FM_PORT_TYPE_OH_HOST_COMMAND):
+ p_FmPort->p_FmPortDriverParam->deqPrefetchOption = DEFAULT_PORT_deqPrefetchOption_HC;
+ p_FmPort->p_FmPortDriverParam->deqHighPriority = DEFAULT_PORT_deqHighPriority_1G;
+ p_FmPort->p_FmPortDriverParam->deqType = DEFAULT_PORT_deqType;
+ p_FmPort->p_FmPortDriverParam->deqByteCnt = DEFAULT_PORT_deqByteCnt_1G;
+
+#ifdef FM_NO_GUARANTEED_RESET_VALUES
+ if (1) /* if (p_FmPort->fmRevInfo.majorRev < 6) */
+ p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth = DEFAULT_PORT_fifoDeqPipelineDepth_OH;
+ else
+#endif /* FM_NO_GUARANTEED_RESET_VALUES */
+ {
+ tmpReg = GET_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofp);
+ p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth =
+ (uint8_t)(((tmpReg & BMI_FIFO_PIPELINE_DEPTH_MASK) >> BMI_FIFO_PIPELINE_DEPTH_SHIFT) + 1);
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND) &&
+ (p_FmPortParams->portId != FM_OH_PORT_ID))
+ {
+ /* Overwrite HC defaults */
+ p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth = DEFAULT_PORT_fifoDeqPipelineDepth_OH;
+ }
+ }
+
+#ifndef FM_FRAME_END_PARAMS_FOR_OP
+ if (p_FmPort->fmRevInfo.majorRev < 6)
+ p_FmPort->p_FmPortDriverParam->cheksumLastBytesIgnore = DEFAULT_notSupported;
+#endif /* !FM_FRAME_END_PARAMS_FOR_OP */
+
+#ifndef FM_DEQ_PIPELINE_PARAMS_FOR_OP
+ if (!((p_FmPort->fmRevInfo.majorRev == 4) ||
+ (p_FmPort->fmRevInfo.majorRev >= 6)))
+ p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth = DEFAULT_notSupported;
+#endif /* !FM_DEQ_PIPELINE_PARAMS_FOR_OP */
+ break;
+
+ default:
+ XX_Free(p_FmPort->p_FmPortDriverParam);
+ XX_Free(p_FmPort);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ return NULL;
+ }
+#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+ if (p_FmPort->fmRevInfo.majorRev == 4)
+ p_FmPort->p_FmPortDriverParam->deqPrefetchOption = (e_FmPortDeqPrefetchOption)DEFAULT_notSupported;
+#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */
+
+ p_FmPort->imEn = p_FmPortParams->independentModeEnable;
+
+ if (p_FmPort->imEn)
+ {
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_TX_10G))
+ p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth = DEFAULT_PORT_fifoDeqPipelineDepth_IM;
+ FmPortConfigIM(p_FmPort, p_FmPortParams);
+ }
+ else
+ {
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX):
+ case (e_FM_PORT_TYPE_RX_10G):
+ /* Initialize FM port parameters for initialization phase only */
+ memcpy(&p_FmPort->p_FmPortDriverParam->extBufPools,
+ &p_FmPortParams->specificParams.rxParams.extBufPools,
+ sizeof(t_FmExtPools));
+ p_FmPort->p_FmPortDriverParam->errFqid = p_FmPortParams->specificParams.rxParams.errFqid;
+ p_FmPort->p_FmPortDriverParam->dfltFqid = p_FmPortParams->specificParams.rxParams.dfltFqid;
+ p_FmPort->p_FmPortDriverParam->liodnOffset = p_FmPortParams->specificParams.rxParams.liodnOffset;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ case (e_FM_PORT_TYPE_TX):
+ case (e_FM_PORT_TYPE_TX_10G):
+ case (e_FM_PORT_TYPE_OH_HOST_COMMAND):
+ p_FmPort->p_FmPortDriverParam->errFqid = p_FmPortParams->specificParams.nonRxParams.errFqid;
+ p_FmPort->p_FmPortDriverParam->deqSubPortal =
+ (uint8_t)(p_FmPortParams->specificParams.nonRxParams.qmChannel & QMI_DEQ_CFG_SUBPORTAL_MASK);
+ p_FmPort->p_FmPortDriverParam->dfltFqid = p_FmPortParams->specificParams.nonRxParams.dfltFqid;
+ break;
+ default:
+ XX_Free(p_FmPort->p_FmPortDriverParam);
+ XX_Free(p_FmPort);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ return NULL;
+ }
+ }
+
+ memset(p_FmPort->name, 0, (sizeof(char)) * MODULE_NAME_SIZE);
+ if (Sprint (p_FmPort->name, "FM-%d-port-%s-%d",
+ FmGetId(p_FmPort->h_Fm),
+ ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)) ?
+ "OH" : (p_FmPort->portType == e_FM_PORT_TYPE_RX ?
+ "1g-RX" : (p_FmPort->portType == e_FM_PORT_TYPE_TX ?
+ "1g-TX" : (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G ?
+ "10g-RX" : "10g-TX")))),
+ p_FmPort->portId) == 0)
+ {
+ XX_Free(p_FmPort->p_FmPortDriverParam);
+ XX_Free(p_FmPort);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
+ return NULL;
+ }
+
+ p_FmPort->h_Spinlock = XX_InitSpinlock();
+ if (!p_FmPort->h_Spinlock)
+ {
+ XX_Free(p_FmPort->p_FmPortDriverParam);
+ XX_Free(p_FmPort);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
+ return NULL;
+ }
+
+ return p_FmPort;
+}
+
+t_FmPort *rx_port = 0;
+t_FmPort *tx_port = 0;
+
+/**************************************************************************//**
+ @Function FM_PORT_Init
+
+ @Description Initializes the FM module
+
+ @Param[in] h_FmPort - FM module descriptor
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_PORT_Init(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_FmPortDriverParam *p_DriverParams;
+ t_Error errCode;
+ t_FmInterModulePortInitParams fmParams;
+ t_FmRevisionInfo revInfo;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ errCode = FmSpBuildBufferStructure(&p_FmPort->p_FmPortDriverParam->intContext,
+ &p_FmPort->p_FmPortDriverParam->bufferPrefixContent,
+ &p_FmPort->p_FmPortDriverParam->bufMargins,
+ &p_FmPort->bufferOffsets,
+ &p_FmPort->internalBufferOffset);
+ if (errCode != E_OK)
+ RETURN_ERROR(MAJOR, errCode, NO_MSG);
+#ifdef FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669
+ if ((p_FmPort->p_FmPortDriverParam->bcbWorkaround) &&
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX))
+ {
+ p_FmPort->p_FmPortDriverParam->errorsToDiscard |= FM_PORT_FRM_ERR_PHYSICAL;
+ if (!p_FmPort->fifoBufs.num)
+ p_FmPort->fifoBufs.num = DEFAULT_PORT_numOfFifoBufs(p_FmPort->portType)*BMI_FIFO_UNITS;
+ p_FmPort->fifoBufs.num += 4*KILOBYTE;
+ }
+#endif /* FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 */
+
+ CHECK_INIT_PARAMETERS(p_FmPort, CheckInitParameters);
+
+ p_DriverParams = p_FmPort->p_FmPortDriverParam;
+
+ /* Set up flibs port structure */
+ memset(&p_FmPort->port, 0, sizeof(struct fman_port));
+ p_FmPort->port.type = (enum fman_port_type)p_FmPort->portType;
+ FM_GetRevision(p_FmPort->h_Fm, &revInfo);
+ p_FmPort->port.fm_rev_maj = revInfo.majorRev;
+ p_FmPort->port.fm_rev_min = revInfo.minorRev;
+ p_FmPort->port.bmi_regs = (union fman_port_bmi_regs *)
+ UINT_TO_PTR(p_DriverParams->baseAddr + BMI_PORT_REGS_OFFSET);
+ p_FmPort->port.qmi_regs = (struct fman_port_qmi_regs *)
+ UINT_TO_PTR(p_DriverParams->baseAddr + QMI_PORT_REGS_OFFSET);
+ p_FmPort->port.ext_pools_num = (uint8_t)((revInfo.majorRev == 4) ? 4 : 8);
+ p_FmPort->port.im_en = p_FmPort->imEn;
+ p_FmPort->p_FmPortPrsRegs = (t_FmPortPrsRegs *)UINT_TO_PTR(p_DriverParams->baseAddr + PRS_PORT_REGS_OFFSET);
+
+ if (((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX))
+ && !p_FmPort->imEn)
+ {
+ /* Call the external Buffer routine which also checks fifo
+ size and updates it if necessary */
+ /* define external buffer pools and pool depletion*/
+ errCode = SetExtBufferPools(p_FmPort);
+ if (errCode)
+ RETURN_ERROR(MAJOR, errCode, NO_MSG);
+ /* check if the largest external buffer pool is large enough */
+ if (p_DriverParams->bufMargins.startMargins + MIN_EXT_BUF_SIZE + p_DriverParams->bufMargins.endMargins >
+ p_FmPort->rxPoolsParams.largestBufSize)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("bufMargins.startMargins (%d) + minimum buf size (64) + bufMargins.endMargins (%d) is larger than maximum external buffer size (%d)",
+ p_DriverParams->bufMargins.startMargins,
+ p_DriverParams->bufMargins.endMargins,
+ p_FmPort->rxPoolsParams.largestBufSize));
+ }
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ {
+ {
+#ifdef FM_NO_OP_OBSERVED_POOLS
+ t_FmRevisionInfo revInfo;
+
+ FM_GetRevision(p_FmPort->h_Fm, &revInfo);
+ if ((revInfo.majorRev == 4) && (p_DriverParams->enBufPoolDepletion))
+#endif /* FM_NO_OP_OBSERVED_POOLS */
+ {
+ /* define external buffer pools */
+ errCode = SetExtBufferPools(p_FmPort);
+ if (errCode)
+ RETURN_ERROR(MAJOR, errCode, NO_MSG);
+ }
+ }
+ }
+
+ /************************************************************/
+ /* Call FM module routine for communicating parameters */
+ /************************************************************/
+ memset(&fmParams, 0, sizeof(fmParams));
+ fmParams.hardwarePortId = p_FmPort->hardwarePortId;
+ fmParams.portType = (e_FmPortType)p_FmPort->portType;
+ fmParams.numOfTasks = (uint8_t)p_FmPort->tasks.num;
+ fmParams.numOfExtraTasks = (uint8_t)p_FmPort->tasks.extra;
+ fmParams.numOfOpenDmas = (uint8_t)p_FmPort->openDmas.num;
+ fmParams.numOfExtraOpenDmas = (uint8_t)p_FmPort->openDmas.extra;
+
+ if (p_FmPort->fifoBufs.num)
+ {
+ errCode = VerifySizeOfFifo(p_FmPort);
+ if (errCode != E_OK)
+ RETURN_ERROR(MAJOR, errCode, NO_MSG);
+ }
+ fmParams.sizeOfFifo = p_FmPort->fifoBufs.num;
+ fmParams.extraSizeOfFifo = p_FmPort->fifoBufs.extra;
+ fmParams.independentMode = p_FmPort->imEn;
+ fmParams.liodnOffset = p_DriverParams->liodnOffset;
+ fmParams.liodnBase = p_DriverParams->liodnBase;
+ fmParams.deqPipelineDepth = p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth;
+ fmParams.maxFrameLength = p_FmPort->maxFrameLength;
+#ifndef FM_DEQ_PIPELINE_PARAMS_FOR_OP
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND))
+ {
+ if (!((p_FmPort->fmRevInfo.majorRev == 4) ||
+ (p_FmPort->fmRevInfo.majorRev >= 6)))
+ /* HC ports do not have fifoDeqPipelineDepth, but it is needed only
+ * for deq threshold calculation.
+ */
+ fmParams.deqPipelineDepth = 2;
+ }
+#endif /* !FM_DEQ_PIPELINE_PARAMS_FOR_OP */
+
+
+ errCode = FmGetSetPortParams(p_FmPort->h_Fm, &fmParams);
+ if (errCode)
+ RETURN_ERROR(MAJOR, errCode, NO_MSG);
+
+ /* get params for use in init */
+ p_FmPort->fmMuramPhysBaseAddr =
+ (uint64_t)((uint64_t)(fmParams.fmMuramPhysBaseAddr.low) |
+ ((uint64_t)(fmParams.fmMuramPhysBaseAddr.high) << 32));
+ p_FmPort->h_FmMuram = FmGetMuramHandle(p_FmPort->h_Fm);
+
+#ifndef FM_NO_GUARANTEED_RESET_VALUES
+ if (p_FmPort->fmRevInfo.majorRev >= 6)
+ {
+ p_FmPort->tasks.num = fmParams.numOfTasks;
+ p_FmPort->tasks.extra = fmParams.numOfExtraTasks;
+ p_FmPort->openDmas.num = fmParams.numOfOpenDmas;
+ p_FmPort->openDmas.extra = fmParams.numOfExtraOpenDmas;
+ p_FmPort->fifoBufs.num = fmParams.sizeOfFifo;
+ p_FmPort->fifoBufs.extra = fmParams.extraSizeOfFifo;
+ }
+#endif /* FM_NO_GUARANTEED_RESET_VALUES */
+
+ errCode = InitLowLevelDriver(p_FmPort);
+ if (errCode != E_OK)
+ RETURN_ERROR(MAJOR, errCode, NO_MSG);
+
+ FmPortDriverParamFree(p_FmPort);
+
+#if (DPAA_VERSION >= 11)
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
+ {
+ t_FmPcdCtrlParamsPage *p_ParamsPage;
+
+ FmPortSetGprFunc(p_FmPort, e_FM_PORT_GPR_MURAM_PAGE, (void**)&p_ParamsPage);
+ ASSERT_COND(p_ParamsPage);
+
+ WRITE_UINT32(p_ParamsPage->misc, FM_CTL_PARAMS_PAGE_ALWAYS_ON);
+#ifdef FM_OP_NO_VSP_NO_RELEASE_ERRATA_FMAN_A006675
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ {
+ WRITE_UINT32(p_ParamsPage->misc,
+ (GET_UINT32(p_ParamsPage->misc) | FM_CTL_PARAMS_PAGE_OP_FIX_EN));
+ WRITE_UINT32(p_ParamsPage->discardMask,
+ GET_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofsdm));
+ }
+#endif /* FM_OP_NO_VSP_NO_RELEASE_ERRATA_FMAN_A006675 */
+#ifdef FM_ERROR_VSP_NO_MATCH_SW006
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ WRITE_UINT32(p_ParamsPage->errorsDiscardMask,
+ (GET_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofsdm) |
+ GET_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofsem)));
+ else
+ WRITE_UINT32(p_ParamsPage->errorsDiscardMask,
+ (GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfsdm) |
+ GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfsem)));
+#endif /* FM_ERROR_VSP_NO_MATCH_SW006 */
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ if (p_FmPort->deepSleepVars.autoResMaxSizes)
+ FmPortConfigAutoResForDeepSleepSupport1(p_FmPort);
+
+ return E_OK;
+}
+
+/**************************************************************************//**
+ @Function FM_PORT_Free
+
+ @Description Frees all resources that were assigned to FM module.
+
+ Calling this routine invalidates the descriptor.
+
+ @Param[in] h_FmPort - FM module descriptor
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_PORT_Free(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_FmInterModulePortFreeParams fmParams;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+
+ if (p_FmPort->pcdEngines)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Trying to free a port with PCD. FM_PORT_DeletePCD must be called first."));
+
+ if (p_FmPort->enabled)
+ {
+ if (FM_PORT_Disable(p_FmPort) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM_PORT_Disable FAILED"));
+ }
+
+ if (p_FmPort->imEn)
+ FmPortImFree(p_FmPort);
+
+ FmPortDriverParamFree(p_FmPort);
+
+ fmParams.hardwarePortId = p_FmPort->hardwarePortId;
+ fmParams.portType = (e_FmPortType)p_FmPort->portType;
+ fmParams.deqPipelineDepth = p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth;
+
+ FmFreePortParams(p_FmPort->h_Fm, &fmParams);
+
+#if (DPAA_VERSION >= 11)
+ if (FmVSPFreeForPort(p_FmPort->h_Fm,
+ p_FmPort->portType,
+ p_FmPort->portId) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("VSP free of port FAILED"));
+
+ if (p_FmPort->p_ParamsPage)
+ FM_MURAM_FreeMem(p_FmPort->h_FmMuram, p_FmPort->p_ParamsPage);
+#endif /* (DPAA_VERSION >= 11) */
+
+ if (p_FmPort->h_Spinlock)
+ XX_FreeSpinlock(p_FmPort->h_Spinlock);
+
+ XX_Free(p_FmPort);
+
+ return E_OK;
+}
+
+
+/*************************************************/
+/* API Advanced Init unit functions */
+/*************************************************/
+
+t_Error FM_PORT_ConfigNumOfOpenDmas(t_Handle h_FmPort, t_FmPortRsrc *p_OpenDmas)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->p_FmPortDriverParam->setNumOfOpenDmas = TRUE;
+ memcpy(&p_FmPort->openDmas, p_OpenDmas, sizeof(t_FmPortRsrc));
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigNumOfTasks(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfTasks)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ memcpy(&p_FmPort->tasks, p_NumOfTasks, sizeof(t_FmPortRsrc));
+ p_FmPort->p_FmPortDriverParam->setNumOfTasks = TRUE;
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigSizeOfFifo(t_Handle h_FmPort, t_FmPortRsrc *p_SizeOfFifo)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->p_FmPortDriverParam->setSizeOfFifo = TRUE;
+ memcpy(&p_FmPort->fifoBufs, p_SizeOfFifo, sizeof(t_FmPortRsrc));
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigDeqHighPriority(t_Handle h_FmPort, bool highPri)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("not available for Rx ports"));
+
+ p_FmPort->p_FmPortDriverParam->dfltCfg.deq_high_pri = highPri;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigDeqType(t_Handle h_FmPort, e_FmPortDeqType deqType)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("not available for Rx ports"));
+
+ p_FmPort->p_FmPortDriverParam->dfltCfg.deq_type = (enum fman_port_deq_type)deqType;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigDeqPrefetchOption(t_Handle h_FmPort, e_FmPortDeqPrefetchOption deqPrefetchOption)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("not available for Rx ports"));
+ p_FmPort->p_FmPortDriverParam->dfltCfg.deq_prefetch_opt = (enum fman_port_deq_prefetch)deqPrefetchOption;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigBackupPools(t_Handle h_FmPort, t_FmBackupBmPools *p_BackupBmPools)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
+
+ p_FmPort->p_FmPortDriverParam->p_BackupBmPools = (t_FmBackupBmPools *)XX_Malloc(sizeof(t_FmBackupBmPools));
+ if (!p_FmPort->p_FmPortDriverParam->p_BackupBmPools)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("p_BackupBmPools allocation failed"));
+ memcpy(p_FmPort->p_FmPortDriverParam->p_BackupBmPools, p_BackupBmPools, sizeof(t_FmBackupBmPools));
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigDeqByteCnt(t_Handle h_FmPort, uint16_t deqByteCnt)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("not available for Rx ports"));
+
+ p_FmPort->p_FmPortDriverParam->dfltCfg.deq_byte_cnt = deqByteCnt;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigBufferPrefixContent(t_Handle h_FmPort, t_FmBufferPrefixContent *p_FmBufferPrefixContent)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ memcpy(&p_FmPort->p_FmPortDriverParam->bufferPrefixContent, p_FmBufferPrefixContent, sizeof(t_FmBufferPrefixContent));
+ /* if dataAlign was not initialized by user, we return to driver's default */
+ if (!p_FmPort->p_FmPortDriverParam->bufferPrefixContent.dataAlign)
+ p_FmPort->p_FmPortDriverParam->bufferPrefixContent.dataAlign = DEFAULT_PORT_bufferPrefixContent_dataAlign;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigCheksumLastBytesIgnore(t_Handle h_FmPort, uint8_t checksumLastBytesIgnore)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->p_FmPortDriverParam->dfltCfg.checksum_bytes_ignore = checksumLastBytesIgnore;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigCutBytesFromEnd(t_Handle h_FmPort, uint8_t cutBytesFromEnd)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
+
+ p_FmPort->p_FmPortDriverParam->dfltCfg.rx_cut_end_bytes = cutBytesFromEnd;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigPoolDepletion(t_Handle h_FmPort, t_FmBufPoolDepletion *p_BufPoolDepletion)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
+
+ p_FmPort->p_FmPortDriverParam->enBufPoolDepletion = TRUE;
+ memcpy(&p_FmPort->p_FmPortDriverParam->bufPoolDepletion, p_BufPoolDepletion, sizeof(t_FmBufPoolDepletion));
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigObservedPoolDepletion(t_Handle h_FmPort, t_FmPortObservedBufPoolDepletion *p_FmPortObservedBufPoolDepletion)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for OP ports only"));
+
+ p_FmPort->p_FmPortDriverParam->enBufPoolDepletion = TRUE;
+ memcpy(&p_FmPort->p_FmPortDriverParam->bufPoolDepletion,
+ &p_FmPortObservedBufPoolDepletion->poolDepletionParams,
+ sizeof(t_FmBufPoolDepletion));
+ memcpy(&p_FmPort->p_FmPortDriverParam->extBufPools,
+ &p_FmPortObservedBufPoolDepletion->poolsParams,
+ sizeof(t_FmExtPools));
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigExtBufPools(t_Handle h_FmPort, t_FmExtPools *p_FmExtPools)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ if (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for OP ports only"));
+
+ memcpy(&p_FmPort->p_FmPortDriverParam->extBufPools, p_FmExtPools, sizeof(t_FmExtPools));
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigDontReleaseTxBufToBM(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_TX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_TX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Tx ports only"));
+
+ p_FmPort->p_FmPortDriverParam->dontReleaseBuf = TRUE;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigDfltColor(t_Handle h_FmPort, e_FmPortColor color)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ p_FmPort->p_FmPortDriverParam->dfltCfg.color = (enum fman_port_color)color;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigSyncReq(t_Handle h_FmPort, bool syncReq)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) && (p_FmPort->portType == e_FM_PORT_TYPE_TX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Not available for Tx ports"));
+
+ p_FmPort->p_FmPortDriverParam->dfltCfg.sync_req = syncReq;
+
+ return E_OK;
+}
+
+
+t_Error FM_PORT_ConfigFrmDiscardOverride(t_Handle h_FmPort, bool override)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) && (p_FmPort->portType == e_FM_PORT_TYPE_TX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("not available for Tx ports"));
+
+ p_FmPort->p_FmPortDriverParam->dfltCfg.discard_override = override;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigErrorsToDiscard(t_Handle h_FmPort, fmPortFrameErrSelect_t errs)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+
+ p_FmPort->p_FmPortDriverParam->errorsToDiscard = errs;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigDmaSwapData(t_Handle h_FmPort, e_FmDmaSwapOption swapData)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->p_FmPortDriverParam->dfltCfg.dma_swap_data = (enum fman_port_dma_swap)swapData;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigDmaIcCacheAttr(t_Handle h_FmPort, e_FmDmaCacheOption intContextCacheAttr)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->p_FmPortDriverParam->dfltCfg.dma_ic_stash_on =
+ (bool)(intContextCacheAttr == e_FM_DMA_STASH);
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigDmaHdrAttr(t_Handle h_FmPort, e_FmDmaCacheOption headerCacheAttr)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->p_FmPortDriverParam->dfltCfg.dma_header_stash_on =
+ (bool)(headerCacheAttr == e_FM_DMA_STASH);
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigDmaScatterGatherAttr(t_Handle h_FmPort, e_FmDmaCacheOption scatterGatherCacheAttr)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->p_FmPortDriverParam->dfltCfg.dma_sg_stash_on =
+ (bool)(scatterGatherCacheAttr == e_FM_DMA_STASH);
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigDmaWriteOptimize(t_Handle h_FmPort, bool optimize)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_TX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_TX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Not available for Tx ports"));
+
+ p_FmPort->p_FmPortDriverParam->dfltCfg.dma_write_optimize = optimize;
+
+ return E_OK;
+}
+
+#if (DPAA_VERSION >= 11)
+t_Error FM_PORT_ConfigNoScatherGather(t_Handle h_FmPort, bool noScatherGather)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ UNUSED(noScatherGather);
+ UNUSED(p_FmPort);
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->p_FmPortDriverParam->noScatherGather = noScatherGather;
+
+ return E_OK;
+}
+#endif /* (DPAA_VERSION >= 11) */
+
+t_Error FM_PORT_ConfigForwardReuseIntContext(t_Handle h_FmPort, bool forwardReuse)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
+
+ p_FmPort->p_FmPortDriverParam->forwardReuseIntContext = forwardReuse;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigMaxFrameLength(t_Handle h_FmPort, uint16_t length)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->maxFrameLength = length;
+
+ return E_OK;
+}
+
+#ifdef FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669
+t_Error FM_PORT_ConfigBCBWorkaround(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->p_FmPortDriverParam->bcbWorkaround = TRUE;
+
+ return E_OK;
+}
+#endif /* FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 */
+
+/****************************************************/
+/* Hidden-DEBUG Only API */
+/****************************************************/
+
+t_Error FM_PORT_ConfigTxFifoMinFillLevel(t_Handle h_FmPort, uint32_t minFillLevel)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_TX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_TX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Tx ports only"));
+
+ p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_min_level = minFillLevel;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigFifoDeqPipelineDepth(t_Handle h_FmPort, uint8_t deqPipelineDepth)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) || (p_FmPort->portType == e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Not available for Rx ports"));
+
+ if (p_FmPort->imEn)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Not available for IM ports!"));
+
+ p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_deq_pipeline_depth = deqPipelineDepth;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigTxFifoLowComfLevel(t_Handle h_FmPort, uint32_t fifoLowComfLevel)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_TX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_TX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Tx ports only"));
+
+ p_FmPort->p_FmPortDriverParam->dfltCfg.tx_fifo_low_comf_level = fifoLowComfLevel;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigRxFifoThreshold(t_Handle h_FmPort, uint32_t fifoThreshold)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
+
+ p_FmPort->p_FmPortDriverParam->dfltCfg.rx_fifo_thr = fifoThreshold;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigRxFifoPriElevationLevel(t_Handle h_FmPort, uint32_t priElevationLevel)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
+
+ p_FmPort->p_FmPortDriverParam->dfltCfg.rx_pri_elevation = priElevationLevel;
+
+ return E_OK;
+}
+/****************************************************/
+/* API Run-time Control unit functions */
+/****************************************************/
+
+t_Error FM_PORT_SetNumOfOpenDmas(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfOpenDmas)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ if ((!p_NumOfOpenDmas->num) || (p_NumOfOpenDmas->num > MAX_NUM_OF_DMAS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("openDmas-num can't be larger than %d", MAX_NUM_OF_DMAS));
+ if (p_NumOfOpenDmas->extra > MAX_NUM_OF_EXTRA_DMAS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("openDmas-extra can't be larger than %d", MAX_NUM_OF_EXTRA_DMAS));
+ err = FmSetNumOfOpenDmas(p_FmPort->h_Fm, p_FmPort->hardwarePortId, (uint8_t*)&p_NumOfOpenDmas->num, (uint8_t*)&p_NumOfOpenDmas->extra, FALSE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ memcpy(&p_FmPort->openDmas, p_NumOfOpenDmas, sizeof(t_FmPortRsrc));
+
+ return E_OK;
+}
+
+t_Error FM_PORT_SetNumOfTasks(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfTasks)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ /* only driver uses host command port, so ASSERT rather than RETURN_ERROR */
+ ASSERT_COND(p_FmPort->portType != e_FM_PORT_TYPE_OH_HOST_COMMAND);
+
+ if ((!p_NumOfTasks->num) || (p_NumOfTasks->num > MAX_NUM_OF_TASKS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("NumOfTasks-num can't be larger than %d", MAX_NUM_OF_TASKS));
+ if (p_NumOfTasks->extra > MAX_NUM_OF_EXTRA_TASKS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("NumOfTasks-extra can't be larger than %d", MAX_NUM_OF_EXTRA_TASKS));
+
+ err = FmSetNumOfTasks(p_FmPort->h_Fm, p_FmPort->hardwarePortId, (uint8_t*)&p_NumOfTasks->num, (uint8_t*)&p_NumOfTasks->extra, FALSE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ /* update driver's struct */
+ memcpy(&p_FmPort->tasks, p_NumOfTasks, sizeof(t_FmPortRsrc));
+ return E_OK;
+}
+
+t_Error FM_PORT_SetSizeOfFifo(t_Handle h_FmPort, t_FmPortRsrc *p_SizeOfFifo)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ if (!p_SizeOfFifo->num || (p_SizeOfFifo->num > MAX_PORT_FIFO_SIZE))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("SizeOfFifo-num has to be in the range of 256 - %d", MAX_PORT_FIFO_SIZE));
+ if (p_SizeOfFifo->num % BMI_FIFO_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("SizeOfFifo-num has to be divisible by %d", BMI_FIFO_UNITS));
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) || (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
+ {
+ /* extra FIFO size (allowed only to Rx ports) */
+ if (p_SizeOfFifo->extra % BMI_FIFO_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("SizeOfFifo-extra has to be divisible by %d", BMI_FIFO_UNITS));
+ }
+ else
+ if (p_SizeOfFifo->extra)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, (" No SizeOfFifo-extra for non Rx ports"));
+
+ memcpy(&p_FmPort->fifoBufs, p_SizeOfFifo, sizeof(t_FmPortRsrc));
+
+ /* we do not change user's parameter */
+ err = VerifySizeOfFifo(p_FmPort);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ err = FmSetSizeOfFifo(p_FmPort->h_Fm,
+ p_FmPort->hardwarePortId,
+ &p_SizeOfFifo->num,
+ &p_SizeOfFifo->extra,
+ FALSE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ return E_OK;
+}
+
+uint32_t FM_PORT_GetBufferDataOffset(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, 0);
+
+ return p_FmPort->bufferOffsets.dataOffset;
+}
+
+uint8_t * FM_PORT_GetBufferICInfo(t_Handle h_FmPort, char *p_Data)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, NULL);
+
+ if (p_FmPort->bufferOffsets.pcdInfoOffset == ILLEGAL_BASE)
+ return NULL;
+
+ return (uint8_t *)PTR_MOVE(p_Data, p_FmPort->bufferOffsets.pcdInfoOffset);
+}
+
+t_FmPrsResult * FM_PORT_GetBufferPrsResult(t_Handle h_FmPort, char *p_Data)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, NULL);
+
+ if (p_FmPort->bufferOffsets.prsResultOffset == ILLEGAL_BASE)
+ return NULL;
+
+ return (t_FmPrsResult *)PTR_MOVE(p_Data, p_FmPort->bufferOffsets.prsResultOffset);
+}
+
+uint64_t * FM_PORT_GetBufferTimeStamp(t_Handle h_FmPort, char *p_Data)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, NULL);
+
+ if (p_FmPort->bufferOffsets.timeStampOffset == ILLEGAL_BASE)
+ return NULL;
+
+ return (uint64_t *)PTR_MOVE(p_Data, p_FmPort->bufferOffsets.timeStampOffset);
+}
+
+uint8_t * FM_PORT_GetBufferHashResult(t_Handle h_FmPort, char *p_Data)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, NULL);
+
+ if (p_FmPort->bufferOffsets.hashResultOffset == ILLEGAL_BASE)
+ return NULL;
+
+ return (uint8_t *)PTR_MOVE(p_Data, p_FmPort->bufferOffsets.hashResultOffset);
+}
+
+t_Error FM_PORT_Disable(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ int err;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if (p_FmPort->imEn)
+ FmPortImDisable(p_FmPort);
+
+ err = fman_port_disable(&p_FmPort->port);
+ if (err == -EBUSY)
+ {
+ fman_port_enable(&p_FmPort->port);
+ RETURN_ERROR(MINOR, E_BUSY, ("%s: can't disable! BMI or QMI is Busy", p_FmPort->name));
+ }
+ else if (err != 0)
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_disable"));
+ }
+
+ p_FmPort->enabled = FALSE;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_Enable(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ int err;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ /* Used by FM_PORT_Free routine as indication
+ if to disable port. Thus set it to TRUE prior
+ to enabling itself. This way if part of enable
+ process fails there will be still things
+ to disable during Free. For example, if BMI
+ enable succeeded but QMI failed, still BMI
+ needs to be disabled by Free. */
+ p_FmPort->enabled = TRUE;
+
+ if (p_FmPort->imEn)
+ FmPortImEnable(p_FmPort);
+
+ err = fman_port_enable(&p_FmPort->port);
+ if (err != 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_enable"));
+
+ return E_OK;
+}
+
+t_Error FM_PORT_SetRateLimit(t_Handle h_FmPort, t_FmPortRateLimit *p_RateLimit)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ uint8_t factor, countUnitBit;
+ uint16_t baseGran;
+ struct fman_port_rate_limiter params;
+ int err;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ switch(p_FmPort->portType)
+ {
+ case(e_FM_PORT_TYPE_TX_10G):
+ case(e_FM_PORT_TYPE_TX):
+ baseGran = BMI_RATE_LIMIT_GRAN_TX;
+ break;
+ case(e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ baseGran = BMI_RATE_LIMIT_GRAN_OP;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Tx and Offline parsing ports only"));
+ }
+
+ countUnitBit = (uint8_t)FmGetTimeStampScale(p_FmPort->h_Fm); /* TimeStamp per nano seconds units */
+ /* normally, we use 1 usec as the reference count */
+ factor = 1;
+ /* if ratelimit is too small for a 1usec factor, multiply the factor */
+ while (p_RateLimit->rateLimit < baseGran/factor)
+ {
+ if (countUnitBit==31)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Rate limit is too small"));
+
+ countUnitBit++;
+ factor <<= 1;
+ }
+ /* if ratelimit is too large for a 1usec factor, it is also larger than max rate*/
+ if (p_RateLimit->rateLimit > ((uint32_t)baseGran * (1<<10) * (uint32_t)factor))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Rate limit is too large"));
+
+ if (!p_RateLimit->maxBurstSize || (p_RateLimit->maxBurstSize > BMI_RATE_LIMIT_MAX_BURST_SIZE))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("maxBurstSize must be between 1K and %dk", BMI_RATE_LIMIT_MAX_BURST_SIZE));
+
+ params.count_1micro_bit = (uint8_t)FmGetTimeStampScale(p_FmPort->h_Fm);
+ params.high_burst_size_gran = FALSE;
+ params.burst_size = p_RateLimit->maxBurstSize;
+ params.rate = p_RateLimit->rateLimit;
+ params.rate_factor = E_FMAN_PORT_RATE_DOWN_NONE;
+
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ {
+#ifndef FM_NO_ADVANCED_RATE_LIMITER
+
+ if ((p_FmPort->fmRevInfo.majorRev == 4) || (p_FmPort->fmRevInfo.majorRev >= 6))
+ {
+ params.high_burst_size_gran = TRUE;
+ }
+ else
+#endif /* ! FM_NO_ADVANCED_RATE_LIMITER */
+ {
+ if (p_RateLimit->rateLimitDivider != e_FM_PORT_DUAL_RATE_LIMITER_NONE)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM_PORT_ConfigDualRateLimitScaleDown"));
+
+ if (p_RateLimit->maxBurstSize % 1000)
+ {
+ p_RateLimit->maxBurstSize = (uint16_t)((p_RateLimit->maxBurstSize/1000)+1);
+ DBG(WARNING, ("rateLimit.maxBurstSize rounded up to %d", (p_RateLimit->maxBurstSize/1000+1)*1000));
+ }
+ else
+ p_RateLimit->maxBurstSize = (uint16_t)(p_RateLimit->maxBurstSize/1000);
+ }
+ params.rate_factor = (enum fman_port_rate_limiter_scale_down)p_RateLimit->rateLimitDivider;
+ params.burst_size = p_RateLimit->maxBurstSize;
+ }
+
+ err = fman_port_set_rate_limiter(&p_FmPort->port, &params);
+ if (err != 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_set_rate_limiter"));
+
+ return E_OK;
+}
+
+t_Error FM_PORT_DeleteRateLimit(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ int err;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION,
+ ("available for Tx and Offline parsing ports only"));
+
+ err = fman_port_delete_rate_limiter(&p_FmPort->port);
+ if (err != 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_set_rate_limiter"));
+ return E_OK;
+}
+
+t_Error FM_PORT_SetPfcPrioritiesMappingToQmanWQ(t_Handle h_FmPort, uint8_t prio, uint8_t wq)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ uint32_t tmpReg;
+ uint32_t wqTmpReg;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_TX) && (p_FmPort->portType != e_FM_PORT_TYPE_TX_10G))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("PFC mapping is available for Tx ports only"));
+
+ if (prio > 7)
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ("PFC priority (%d) is out of range (0-7)", prio));
+ if (wq > 7)
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ("WQ (%d) is out of range (0-7)", wq));
+
+ tmpReg = GET_UINT32(p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tpfcm[0]);
+ tmpReg &= ~(0xf << ((7-prio)*4));
+ wqTmpReg = ((uint32_t)wq << ((7-prio)*4));
+ tmpReg |= wqTmpReg;
+
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tpfcm[0], tmpReg);
+
+ return E_OK;
+}
+
+t_Error FM_PORT_SetFrameQueueCounters(t_Handle h_FmPort, bool enable)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ int err;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ err = fman_port_set_queue_cnt_mode(&p_FmPort->port, enable);
+ if (err != 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_set_perf_cnt_mode"));
+ return E_OK;
+}
+
+t_Error FM_PORT_SetPerformanceCounters(t_Handle h_FmPort, bool enable)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ int err;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ err = fman_port_set_perf_cnt_mode(&p_FmPort->port, enable);
+ if (err != 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_set_perf_cnt_mode"));
+ return E_OK;
+}
+
+t_Error FM_PORT_SetPerformanceCountersParams(t_Handle h_FmPort, t_FmPortPerformanceCnt *p_FmPortPerformanceCnt)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ struct fman_port_perf_cnt_params params;
+ int err;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+
+ /* check parameters */
+ if (!p_FmPortPerformanceCnt->taskCompVal ||
+ (p_FmPortPerformanceCnt->taskCompVal > p_FmPort->tasks.num))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("taskCompVal (%d) has to be in the range of 1 - %d (current value)!",
+ p_FmPortPerformanceCnt->taskCompVal,
+ p_FmPort->tasks.num));
+ if (!p_FmPortPerformanceCnt->dmaCompVal ||
+ (p_FmPortPerformanceCnt->dmaCompVal > p_FmPort->openDmas.num))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("dmaCompVal (%d) has to be in the range of 1 - %d (current value)!",
+ p_FmPortPerformanceCnt->dmaCompVal,
+ p_FmPort->openDmas.num));
+ if (!p_FmPortPerformanceCnt->fifoCompVal ||
+ (p_FmPortPerformanceCnt->fifoCompVal > p_FmPort->fifoBufs.num))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("fifoCompVal (%d) has to be in the range of 256 - %d (current value)!",
+ p_FmPortPerformanceCnt->fifoCompVal,
+ p_FmPort->fifoBufs.num));
+ if (p_FmPortPerformanceCnt->fifoCompVal % BMI_FIFO_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("fifoCompVal (%d) has to be divisible by %d",
+ p_FmPortPerformanceCnt->fifoCompVal,
+ BMI_FIFO_UNITS));
+
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ if (!p_FmPortPerformanceCnt->queueCompVal ||
+ (p_FmPortPerformanceCnt->queueCompVal > MAX_PERFORMANCE_RX_QUEUE_COMP))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("performanceCnt.queueCompVal for Rx has to be in the range of 1 - %d",
+ MAX_PERFORMANCE_RX_QUEUE_COMP));
+ break;
+ case (e_FM_PORT_TYPE_TX_10G):
+ case (e_FM_PORT_TYPE_TX):
+ if (!p_FmPortPerformanceCnt->queueCompVal ||
+ (p_FmPortPerformanceCnt->queueCompVal > MAX_PERFORMANCE_TX_QUEUE_COMP))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("performanceCnt.queueCompVal for Tx has to be in the range of 1 - %d",
+ MAX_PERFORMANCE_TX_QUEUE_COMP));
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ case (e_FM_PORT_TYPE_OH_HOST_COMMAND):
+ if (p_FmPortPerformanceCnt->queueCompVal)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("performanceCnt.queueCompVal is not relevant for H/O ports."));
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ }
+
+ params.task_val = p_FmPortPerformanceCnt->taskCompVal;
+ params.queue_val = p_FmPortPerformanceCnt->queueCompVal;
+ params.dma_val = p_FmPortPerformanceCnt->dmaCompVal;
+ params.fifo_val = p_FmPortPerformanceCnt->fifoCompVal;
+
+ err = fman_port_set_perf_cnt_params(&p_FmPort->port, &params);
+ if (err != 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_set_perf_cnt_params"));
+
+ return E_OK;
+}
+
+t_Error FM_PORT_AnalyzePerformanceParams(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_FmPortPerformanceCnt currParams, savedParams;
+ t_Error err;
+ bool underTest, failed = FALSE;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+
+ XX_Print("Analyzing Performance parameters for port (type %d, id%d)\n",
+ p_FmPort->portType, p_FmPort->portId);
+
+ currParams.taskCompVal = (uint8_t)p_FmPort->tasks.num;
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND))
+ currParams.queueCompVal = 0;
+ else
+ currParams.queueCompVal = 1;
+ currParams.dmaCompVal =(uint8_t) p_FmPort->openDmas.num;
+ currParams.fifoCompVal = p_FmPort->fifoBufs.num;
+
+ FM_PORT_SetPerformanceCounters(p_FmPort, FALSE);
+ ClearPerfCnts(p_FmPort);
+ if ((err = FM_PORT_SetPerformanceCountersParams(p_FmPort, &currParams)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ FM_PORT_SetPerformanceCounters(p_FmPort, TRUE);
+ XX_UDelay(1000000);
+ FM_PORT_SetPerformanceCounters(p_FmPort, FALSE);
+ if (FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_TASK_UTIL))
+ {
+ XX_Print ("Max num of defined port tasks (%d) utilized - Please enlarge\n",p_FmPort->tasks.num);
+ failed = TRUE;
+ }
+ if (FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_DMA_UTIL))
+ {
+ XX_Print ("Max num of defined port openDmas (%d) utilized - Please enlarge\n",p_FmPort->openDmas.num);
+ failed = TRUE;
+ }
+ if (FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_FIFO_UTIL))
+ {
+ XX_Print("Max size of defined port fifo (%d) utilized - Please enlarge\n",p_FmPort->fifoBufs.num);
+ failed = TRUE;
+ }
+ if (failed)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ memset(&savedParams, 0, sizeof(savedParams));
+ while (TRUE)
+ {
+ underTest = FALSE;
+ if ((currParams.taskCompVal != 1) && !savedParams.taskCompVal)
+ {
+ currParams.taskCompVal--;
+ underTest = TRUE;
+ }
+ if ((currParams.dmaCompVal != 1) && !savedParams.dmaCompVal)
+ {
+ currParams.dmaCompVal--;
+ underTest = TRUE;
+ }
+ if ((currParams.fifoCompVal != BMI_FIFO_UNITS) && !savedParams.fifoCompVal)
+ {
+ currParams.fifoCompVal -= BMI_FIFO_UNITS;
+ underTest = TRUE;
+ }
+ if (!underTest)
+ break;
+
+ ClearPerfCnts(p_FmPort);
+ if ((err = FM_PORT_SetPerformanceCountersParams(p_FmPort, &currParams)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ FM_PORT_SetPerformanceCounters(p_FmPort, TRUE);
+ XX_UDelay(1000000);
+ FM_PORT_SetPerformanceCounters(p_FmPort, FALSE);
+
+ if (!savedParams.taskCompVal && FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_TASK_UTIL))
+ savedParams.taskCompVal = (uint8_t)(currParams.taskCompVal+2);
+ if (!savedParams.dmaCompVal && FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_DMA_UTIL))
+ savedParams.dmaCompVal = (uint8_t)(currParams.dmaCompVal+2);
+ if (!savedParams.fifoCompVal && FM_PORT_GetCounter(p_FmPort, e_FM_PORT_COUNTERS_FIFO_UTIL))
+ savedParams.fifoCompVal = currParams.fifoCompVal+(2*BMI_FIFO_UNITS);
+ }
+
+ XX_Print("best vals: tasks %d, dmas %d, fifos %d\n",
+ savedParams.taskCompVal, savedParams.dmaCompVal, savedParams.fifoCompVal);
+ return E_OK;
+}
+
+t_Error FM_PORT_SetStatisticsCounters(t_Handle h_FmPort, bool enable)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ int err;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ err = fman_port_set_stats_cnt_mode(&p_FmPort->port, enable);
+ if (err != 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_set_stats_cnt_mode"));
+ return E_OK;
+}
+
+t_Error FM_PORT_SetErrorsRoute(t_Handle h_FmPort, fmPortFrameErrSelect_t errs)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ volatile uint32_t *p_ErrDiscard = NULL;
+ int err;
+
+ UNUSED(p_ErrDiscard);
+ err = fman_port_set_err_mask(&p_FmPort->port, (uint32_t)errs);
+ if (err != 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_set_err_mask"));
+
+#ifdef FM_ERROR_VSP_NO_MATCH_SW006
+ if (p_FmPort->fmRevInfo.majorRev >= 6)
+ {
+ t_FmPcdCtrlParamsPage *p_ParamsPage;
+
+ FmPortSetGprFunc(p_FmPort, e_FM_PORT_GPR_MURAM_PAGE, (void**)&p_ParamsPage);
+ ASSERT_COND(p_ParamsPage);
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_ErrDiscard = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfsdm;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_ErrDiscard = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofsdm;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+ }
+ WRITE_UINT32(p_ParamsPage->errorsDiscardMask, GET_UINT32(*p_ErrDiscard) | errs);
+ }
+#endif /* FM_ERROR_VSP_NO_MATCH_SW006 */
+
+ return E_OK;
+}
+
+t_Error FM_PORT_SetAllocBufCounter(t_Handle h_FmPort, uint8_t poolId, bool enable)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ int err;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(poolId<BM_MAX_NUM_OF_POOLS, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
+
+ err = fman_port_set_bpool_cnt_mode(&p_FmPort->port, poolId, enable);
+ if (err != 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_set_bpool_cnt_mode"));
+ return E_OK;
+}
+
+uint32_t FM_PORT_GetCounter(t_Handle h_FmPort, e_FmPortCounters counter)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ bool bmiCounter = FALSE;
+ enum fman_port_stats_counters statsType;
+ enum fman_port_perf_counters perfType;
+ enum fman_port_qmi_counters queueType;
+ bool isStats;
+ t_Error errCode;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ switch (counter)
+ {
+ case(e_FM_PORT_COUNTERS_DEQ_TOTAL):
+ case(e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT):
+ case(e_FM_PORT_COUNTERS_DEQ_CONFIRM ):
+ /* check that counter is available for the port type */
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
+ {
+ REPORT_ERROR(MINOR, E_INVALID_STATE,
+ ("Requested counter is not available for Rx ports"));
+ return 0;
+ }
+ bmiCounter = FALSE;
+ case(e_FM_PORT_COUNTERS_ENQ_TOTAL):
+ bmiCounter = FALSE;
+ break;
+ default: /* BMI counters (or error - will be checked in BMI routine )*/
+ bmiCounter = TRUE;
+ break;
+ }
+
+ if (bmiCounter)
+ {
+ errCode = BmiPortCheckAndGetCounterType(p_FmPort, counter, &statsType, &perfType, &isStats);
+ if (errCode != E_OK)
+ {
+ REPORT_ERROR(MINOR, errCode, NO_MSG);
+ return 0;
+ }
+ if (isStats)
+ return fman_port_get_stats_counter(&p_FmPort->port, statsType);
+ else
+ return fman_port_get_perf_counter(&p_FmPort->port, perfType);
+ }
+ else /* QMI counter */
+ {
+ /* check that counters are enabled */
+ if (!(GET_UINT32(p_FmPort->port.qmi_regs->fmqm_pnc) & QMI_PORT_CFG_EN_COUNTERS))
+
+ {
+ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled"));
+ return 0;
+ }
+
+ /* Set counter */
+ switch (counter)
+ {
+ case(e_FM_PORT_COUNTERS_ENQ_TOTAL):
+ queueType = E_FMAN_PORT_ENQ_TOTAL;
+ break;
+ case(e_FM_PORT_COUNTERS_DEQ_TOTAL):
+ queueType = E_FMAN_PORT_DEQ_TOTAL;
+ break;
+ case(e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT):
+ queueType = E_FMAN_PORT_DEQ_FROM_DFLT;
+ break;
+ case(e_FM_PORT_COUNTERS_DEQ_CONFIRM):
+ queueType = E_FMAN_PORT_DEQ_CONFIRM;
+ break;
+ default:
+ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available"));
+ return 0;
+ }
+
+ return fman_port_get_qmi_counter(&p_FmPort->port, queueType);
+ }
+
+ return 0;
+}
+
+t_Error FM_PORT_ModifyCounter(t_Handle h_FmPort, e_FmPortCounters counter, uint32_t value)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ bool bmiCounter = FALSE;
+ enum fman_port_stats_counters statsType;
+ enum fman_port_perf_counters perfType;
+ enum fman_port_qmi_counters queueType;
+ bool isStats;
+ t_Error errCode;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ switch (counter)
+ {
+ case(e_FM_PORT_COUNTERS_DEQ_TOTAL):
+ case(e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT):
+ case(e_FM_PORT_COUNTERS_DEQ_CONFIRM ):
+ /* check that counter is available for the port type */
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for Rx ports"));
+ case(e_FM_PORT_COUNTERS_ENQ_TOTAL):
+ bmiCounter = FALSE;
+ break;
+ default: /* BMI counters (or error - will be checked in BMI routine )*/
+ bmiCounter = TRUE;
+ break;
+ }
+
+ if (bmiCounter)
+ {
+ errCode = BmiPortCheckAndGetCounterType(p_FmPort, counter, &statsType, &perfType, &isStats);
+ if (errCode != E_OK)
+ {
+ RETURN_ERROR(MINOR, errCode, NO_MSG);
+ }
+ if (isStats)
+ fman_port_set_stats_counter(&p_FmPort->port, statsType, value);
+ else
+ fman_port_set_perf_counter(&p_FmPort->port, perfType, value);
+ }
+ else /* QMI counter */
+ {
+ /* check that counters are enabled */
+ if (!(GET_UINT32(p_FmPort->port.qmi_regs->fmqm_pnc) & QMI_PORT_CFG_EN_COUNTERS))
+ {
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter was not enabled"));
+ }
+
+ /* Set counter */
+ switch (counter)
+ {
+ case(e_FM_PORT_COUNTERS_ENQ_TOTAL):
+ queueType = E_FMAN_PORT_ENQ_TOTAL;
+ break;
+ case(e_FM_PORT_COUNTERS_DEQ_TOTAL):
+ queueType = E_FMAN_PORT_DEQ_TOTAL;
+ break;
+ case(e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT):
+ queueType = E_FMAN_PORT_DEQ_FROM_DFLT;
+ break;
+ case(e_FM_PORT_COUNTERS_DEQ_CONFIRM):
+ queueType = E_FMAN_PORT_DEQ_CONFIRM;
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available"));
+ }
+
+ fman_port_set_qmi_counter(&p_FmPort->port, queueType, value);
+ }
+
+ return E_OK;
+}
+
+
+uint32_t FM_PORT_GetAllocBufCounter(t_Handle h_FmPort, uint8_t poolId)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX) && (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
+ {
+ REPORT_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for non-Rx ports"));
+ return 0;
+ }
+ return fman_port_get_bpool_counter(&p_FmPort->port, poolId);
+}
+
+t_Error FM_PORT_ModifyAllocBufCounter(t_Handle h_FmPort, uint8_t poolId, uint32_t value)
+{
+ t_FmPort *p_FmPort = (t_FmPort *)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX) && (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Requested counter is not available for non-Rx ports"));
+
+ fman_port_set_bpool_counter(&p_FmPort->port, poolId, value);
+ return E_OK;
+}
+bool FM_PORT_IsStalled(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err;
+ bool isStalled;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmPort, E_INVALID_HANDLE, FALSE);
+ SANITY_CHECK_RETURN_VALUE(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE, FALSE);
+
+ err = FmIsPortStalled(p_FmPort->h_Fm, p_FmPort->hardwarePortId, &isStalled);
+ if (err != E_OK)
+ {
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ return TRUE;
+ }
+ return isStalled;
+}
+
+t_Error FM_PORT_ReleaseStalled(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ return FmResumeStalledPort(p_FmPort->h_Fm, p_FmPort->hardwarePortId);
+}
+
+t_Error FM_PORT_SetRxL4ChecksumVerify(t_Handle h_FmPort, bool l4Checksum)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ int err;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx ports only"));
+
+ if (l4Checksum)
+ err = fman_port_modify_rx_fd_bits(&p_FmPort->port,
+ (uint8_t)(BMI_PORT_RFNE_FRWD_DCL4C >> 24),
+ TRUE);
+ else
+ err = fman_port_modify_rx_fd_bits(&p_FmPort->port,
+ (uint8_t)(BMI_PORT_RFNE_FRWD_DCL4C >> 24),
+ FALSE);
+ if (err != 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_modify_rx_fd_bits"));
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+/* API Run-time PCD Control unit functions */
+/*****************************************************************************/
+
+#if (DPAA_VERSION >= 11)
+t_Error FM_PORT_VSPAlloc(t_Handle h_FmPort, t_FmPortVSPAllocParams *p_VSPParams)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err = E_OK;
+ volatile uint32_t *p_BmiStorageProfileId = NULL, *p_BmiVspe = NULL;
+ uint32_t tmpReg = 0, tmp = 0;
+ uint16_t hwStoragePrflId;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->h_Fm, E_INVALID_HANDLE);
+ /*for numOfProfiles = 0 don't call this function*/
+ SANITY_CHECK_RETURN_ERROR(p_VSPParams->numOfProfiles, E_INVALID_VALUE);
+ /*dfltRelativeId should be in the range of numOfProfiles*/
+ SANITY_CHECK_RETURN_ERROR(IN_RANGE(0, p_VSPParams->dfltRelativeId, (p_VSPParams->numOfProfiles - 1)), E_INVALID_VALUE);
+ /*p_FmPort should be from Rx type or OP*/
+ SANITY_CHECK_RETURN_ERROR(((p_FmPort->portType == e_FM_PORT_TYPE_RX_10G) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)), E_INVALID_VALUE);
+ /*port should be disabled*/
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->enabled, E_INVALID_STATE);
+ /*if its called for Rx port relevant Tx Port should be passed (initialized) too and it should be disabled*/
+ SANITY_CHECK_RETURN_ERROR(((p_VSPParams->h_FmTxPort &&
+ !((t_FmPort *)(p_VSPParams->h_FmTxPort))->enabled) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)), E_INVALID_VALUE);
+ /*should be called before SetPCD - this port should be without PCD*/
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->pcdEngines, E_INVALID_STATE);
+
+ /*alloc window of VSPs for this port*/
+ err = FmVSPAllocForPort(p_FmPort->h_Fm,
+ p_FmPort->portType,
+ p_FmPort->portId,
+ p_VSPParams->numOfProfiles);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ /*get absolute VSP ID for dfltRelative*/
+ err = FmVSPGetAbsoluteProfileId(p_FmPort->h_Fm,
+ p_FmPort->portType,
+ p_FmPort->portId,
+ p_VSPParams->dfltRelativeId,
+ &hwStoragePrflId);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err,NO_MSG);
+
+ /*fill relevant registers for p_FmPort and relative TxPort in the case p_FmPort from Rx type*/
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiStorageProfileId = &(((t_FmPort *)(p_VSPParams->h_FmTxPort))->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfqid);
+ p_BmiVspe = &(((t_FmPort *)(p_VSPParams->h_FmTxPort))->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tfne);
+
+ tmpReg = GET_UINT32(*p_BmiStorageProfileId) & ~BMI_SP_ID_MASK;
+ tmpReg |= (uint32_t)hwStoragePrflId<<BMI_SP_ID_SHIFT;
+ WRITE_UINT32(*p_BmiStorageProfileId, tmpReg);
+
+ tmpReg = GET_UINT32(*p_BmiVspe);
+ WRITE_UINT32(*p_BmiVspe, tmpReg | BMI_SP_EN);
+
+ p_BmiStorageProfileId = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfqid;
+ p_BmiVspe = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rpp;
+ hwStoragePrflId = p_VSPParams->dfltRelativeId;
+ break;
+
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ tmpReg = NIA_ENG_BMI | NIA_BMI_AC_FETCH_ALL_FRAME;
+ WRITE_UINT32(p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs.fmqm_pndn,tmpReg);
+
+ p_BmiStorageProfileId = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofqid;
+ p_BmiVspe = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_opp;
+ tmp |= BMI_EBD_EN;
+ break;
+
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+ }
+
+ p_FmPort->vspe = TRUE;
+ p_FmPort->dfltRelativeId = p_VSPParams->dfltRelativeId;
+
+ tmpReg = GET_UINT32(*p_BmiStorageProfileId) & ~BMI_SP_ID_MASK;
+ tmpReg |= (uint32_t)hwStoragePrflId<<BMI_SP_ID_SHIFT;
+ WRITE_UINT32(*p_BmiStorageProfileId, tmpReg);
+
+ tmpReg = GET_UINT32(*p_BmiVspe);
+ WRITE_UINT32(*p_BmiVspe, tmpReg | BMI_SP_EN | tmp);
+ return E_OK;
+}
+#endif /* (DPAA_VERSION >= 11) */
+
+t_Error FM_PORT_PcdPlcrAllocProfiles(t_Handle h_FmPort, uint16_t numOfProfiles)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err = E_OK;
+
+ p_FmPort->h_FmPcd = FmGetPcdHandle(p_FmPort->h_Fm);
+ ASSERT_COND(p_FmPort->h_FmPcd);
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ if (numOfProfiles)
+ {
+ err = FmPcdPlcrAllocProfiles(p_FmPort->h_FmPcd, p_FmPort->hardwarePortId, numOfProfiles);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ /* set the port handle within the PCD policer, even if no profiles defined */
+ FmPcdPortRegister(p_FmPort->h_FmPcd, h_FmPort, p_FmPort->hardwarePortId);
+
+ RELEASE_LOCK(p_FmPort->lock);
+
+ return E_OK;
+}
+
+t_Error FM_PORT_PcdPlcrFreeProfiles(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err = E_OK;
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FmPcdPlcrFreeProfiles(p_FmPort->h_FmPcd, p_FmPort->hardwarePortId);
+
+ RELEASE_LOCK(p_FmPort->lock);
+
+ if (err)
+ RETURN_ERROR(MAJOR, err,NO_MSG);
+
+ return E_OK;
+}
+
+t_Error FM_PORT_PcdKgModifyInitialScheme (t_Handle h_FmPort, t_FmPcdKgSchemeSelect *p_FmPcdKgScheme)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ volatile uint32_t *p_BmiHpnia = NULL;
+ uint32_t tmpReg;
+ uint8_t relativeSchemeId;
+ uint8_t physicalSchemeId;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_KG , E_INVALID_STATE);
+
+ tmpReg = (uint32_t)((p_FmPort->pcdEngines & FM_PCD_CC)? NIA_KG_CC_EN:0);
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiHpnia = &p_FmPort->port.bmi_regs->rx.fmbm_rfpne;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_BmiHpnia = &p_FmPort->port.bmi_regs->oh.fmbm_ofpne;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+ }
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ /* if we want to change to direct scheme, we need to check that this scheme is valid */
+ if (p_FmPcdKgScheme->direct)
+ {
+ physicalSchemeId = FmPcdKgGetSchemeId(p_FmPcdKgScheme->h_DirectScheme);
+ /* check that this scheme is bound to this port */
+ if (!(p_FmPort->schemesPerPortVector & (uint32_t)(1 << (31 - (uint32_t)physicalSchemeId))))
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("called with a scheme that is not bound to this port"));
+ }
+
+ relativeSchemeId = FmPcdKgGetRelativeSchemeId(p_FmPort->h_FmPcd, physicalSchemeId);
+ if (relativeSchemeId >= FM_PCD_KG_NUM_OF_SCHEMES)
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ("called with invalid Scheme "));
+ }
+
+ if (!FmPcdKgIsSchemeValidSw(p_FmPcdKgScheme->h_DirectScheme))
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("called with uninitialized Scheme "));
+ }
+
+ WRITE_UINT32(*p_BmiHpnia, NIA_ENG_KG | tmpReg | NIA_KG_DIRECT | (uint32_t)physicalSchemeId);
+ }
+ else /* change to indirect scheme */
+ WRITE_UINT32(*p_BmiHpnia, NIA_ENG_KG | tmpReg);
+ RELEASE_LOCK(p_FmPort->lock);
+
+ return E_OK;
+}
+
+t_Error FM_PORT_PcdPlcrModifyInitialProfile (t_Handle h_FmPort, t_Handle h_Profile)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ volatile uint32_t *p_BmiNia;
+ volatile uint32_t *p_BmiHpnia;
+ uint32_t tmpReg;
+ uint16_t absoluteProfileId = FmPcdPlcrProfileGetAbsoluteId(h_Profile);
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_PLCR , E_INVALID_STATE);
+
+ /* check relevance of this routine - only when policer is used
+ directly after BMI or Parser */
+ if ((p_FmPort->pcdEngines & FM_PCD_KG) || (p_FmPort->pcdEngines & FM_PCD_CC))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("relevant only when PCD support mode is e_FM_PCD_SUPPORT_PLCR_ONLY or e_FM_PCD_SUPPORT_PRS_AND_PLCR"));
+
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiNia = &p_FmPort->port.bmi_regs->rx.fmbm_rfne;
+ p_BmiHpnia = &p_FmPort->port.bmi_regs->rx.fmbm_rfpne;
+ tmpReg = GET_UINT32(*p_BmiNia) & BMI_RFNE_FDCS_MASK;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_BmiNia = &p_FmPort->port.bmi_regs->oh.fmbm_ofne;
+ p_BmiHpnia = &p_FmPort->port.bmi_regs->oh.fmbm_ofpne;
+ tmpReg = 0;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+ }
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ if (!FmPcdPlcrIsProfileValid(p_FmPort->h_FmPcd, absoluteProfileId))
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Invalid profile"));
+ }
+
+ tmpReg = (uint32_t)(NIA_ENG_PLCR | NIA_PLCR_ABSOLUTE | absoluteProfileId);
+
+ if (p_FmPort->pcdEngines & FM_PCD_PRS) /* e_FM_PCD_SUPPORT_PRS_AND_PLCR */
+ {
+ /* update BMI HPNIA */
+ WRITE_UINT32(*p_BmiHpnia, tmpReg);
+ }
+ else /* e_FM_PCD_SUPPORT_PLCR_ONLY */
+ {
+ /* rfne may contain FDCS bits, so first we read them. */
+ tmpReg |= (GET_UINT32(*p_BmiNia) & BMI_RFNE_FDCS_MASK);
+ /* update BMI NIA */
+ WRITE_UINT32(*p_BmiNia, tmpReg);
+ }
+ RELEASE_LOCK(p_FmPort->lock);
+
+ return E_OK;
+}
+
+t_Error FM_PORT_PcdCcModifyTree (t_Handle h_FmPort, t_Handle h_CcTree)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err = E_OK;
+ volatile uint32_t *p_BmiCcBase=NULL;
+ volatile uint32_t *p_BmiNia=NULL;
+ uint32_t ccTreePhysOffset;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_VALUE);
+
+ if (p_FmPort->imEn)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independent mode ports only"));
+
+ /* get PCD registers pointers */
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiNia = &p_FmPort->port.bmi_regs->rx.fmbm_rfne;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_BmiNia = &p_FmPort->port.bmi_regs->oh.fmbm_ofne;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+ }
+
+ /* check that current NIA is BMI to BMI */
+ if ((GET_UINT32(*p_BmiNia) & ~BMI_RFNE_FDCS_MASK) != GET_NIA_BMI_AC_ENQ_FRAME(p_FmPort->h_FmPcd))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("may be called only for ports in BMI-to-BMI state."));
+
+ if (p_FmPort->pcdEngines & FM_PCD_CC)
+ {
+ if (p_FmPort->h_IpReassemblyManip)
+ {
+ err = FmPcdCcTreeAddIPR(p_FmPort->h_FmPcd,
+ h_CcTree,
+ NULL,
+ p_FmPort->h_IpReassemblyManip,
+ FALSE);
+ if (err != E_OK)
+ {
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ }
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiCcBase = &p_FmPort->port.bmi_regs->rx.fmbm_rccb;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_BmiCcBase = &p_FmPort->port.bmi_regs->oh.fmbm_occb;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid port type"));
+ }
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+ err = FmPcdCcBindTree(p_FmPort->h_FmPcd, NULL, h_CcTree, &ccTreePhysOffset, h_FmPort);
+ if (err)
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ WRITE_UINT32(*p_BmiCcBase, ccTreePhysOffset);
+
+ p_FmPort->ccTreeId = h_CcTree;
+ RELEASE_LOCK(p_FmPort->lock);
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Coarse Classification not defined for this port."));
+
+ return E_OK;
+}
+
+t_Error FM_PORT_AttachPCD(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if (p_FmPort->imEn)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independent mode ports only"));
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_RX) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ if (p_FmPort->h_IpReassemblyTree)
+ p_FmPort->pcdEngines |= FM_PCD_CC;
+
+ err = AttachPCD(h_FmPort);
+ RELEASE_LOCK(p_FmPort->lock);
+
+ return err;
+}
+
+t_Error FM_PORT_DetachPCD(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if (p_FmPort->imEn)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independent mode ports only"));
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_RX) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = DetachPCD(h_FmPort);
+ if (err != E_OK)
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ if (p_FmPort->h_IpReassemblyTree)
+ p_FmPort->pcdEngines &= ~FM_PCD_CC;
+ RELEASE_LOCK(p_FmPort->lock);
+
+ return E_OK;
+}
+
+t_Error FM_PORT_SetPCD(t_Handle h_FmPort, t_FmPortPcdParams *p_PcdParam)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err = E_OK;
+ t_FmPortPcdParams modifiedPcdParams, *p_PcdParams;
+ t_FmPcdCcTreeParams *p_FmPcdCcTreeParams;
+ t_FmPortPcdCcParams fmPortPcdCcParams;
+ t_FmPortGetSetCcParams fmPortGetSetCcParams;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if (p_FmPort->imEn)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independent mode ports only"));
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_RX) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ p_FmPort->h_FmPcd = FmGetPcdHandle(p_FmPort->h_Fm);
+ ASSERT_COND(p_FmPort->h_FmPcd);
+
+ memcpy(&modifiedPcdParams, p_PcdParam, sizeof(t_FmPortPcdParams));
+ p_PcdParams = &modifiedPcdParams;
+ if (p_PcdParams->h_IpReassemblyManip)
+ {
+ if ((p_PcdParams->pcdSupport != e_FM_PORT_PCD_SUPPORT_PRS_AND_KG) &&
+ (p_PcdParams->pcdSupport != e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC) &&
+ (p_PcdParams->pcdSupport != e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC_AND_PLCR) &&
+ (p_PcdParams->pcdSupport != e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR))
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("pcdSupport must have KG for supporting IPR"));
+ }
+ p_FmPort->h_IpReassemblyManip = p_PcdParams->h_IpReassemblyManip;
+ if (!p_PcdParams->p_CcParams)
+ {
+ if (!((p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_PRS_AND_KG) ||
+ (p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR)))
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("PCD initialization structure is not consistent with pcdSupport"));
+ }
+
+ /* No user-tree, need to build internal tree */
+ p_FmPcdCcTreeParams = (t_FmPcdCcTreeParams*)XX_Malloc(sizeof(t_FmPcdCcTreeParams));
+ if (!p_FmPcdCcTreeParams)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("p_FmPcdCcTreeParams"));
+ memset(p_FmPcdCcTreeParams, 0, sizeof(t_FmPcdCcTreeParams));
+ p_FmPcdCcTreeParams->h_NetEnv = p_PcdParams->h_NetEnv;
+ p_FmPort->h_IpReassemblyTree = FM_PCD_CcRootBuild(p_FmPort->h_FmPcd, p_FmPcdCcTreeParams);
+
+ if (!p_FmPort->h_IpReassemblyTree)
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ XX_Free(p_FmPcdCcTreeParams);
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM_PCD_CcBuildTree for IPR failed"));
+ }
+ if (p_PcdParams->pcdSupport == e_FM_PORT_PCD_SUPPORT_PRS_AND_KG)
+ p_PcdParams->pcdSupport = e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC;
+ else
+ p_PcdParams->pcdSupport = e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC_AND_PLCR;
+
+ memset(&fmPortPcdCcParams, 0, sizeof(t_FmPortPcdCcParams));
+ fmPortPcdCcParams.h_CcTree = p_FmPort->h_IpReassemblyTree;
+ p_PcdParams->p_CcParams = &fmPortPcdCcParams;
+ XX_Free(p_FmPcdCcTreeParams);
+ }
+
+ err = FmPcdCcTreeAddIPR(p_FmPort->h_FmPcd,
+ p_PcdParams->p_CcParams->h_CcTree,
+ p_PcdParams->h_NetEnv,
+ p_FmPort->h_IpReassemblyManip,
+ TRUE);
+ if (err != E_OK)
+ {
+ if (p_FmPort->h_IpReassemblyTree)
+ {
+ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree);
+ p_FmPort->h_IpReassemblyTree = NULL;
+ }
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ }
+
+ if (!FmPcdLockTryLockAll(p_FmPort->h_FmPcd))
+ {
+ if (p_FmPort->h_IpReassemblyTree)
+ {
+ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree);
+ p_FmPort->h_IpReassemblyTree = NULL;
+ }
+ RELEASE_LOCK(p_FmPort->lock);
+ DBG(TRACE, ("Try LockAll - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = SetPcd(h_FmPort, p_PcdParams);
+ if (err)
+ {
+ if (p_FmPort->h_IpReassemblyTree)
+ {
+ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree);
+ p_FmPort->h_IpReassemblyTree = NULL;
+ }
+ FmPcdLockUnlockAll(p_FmPort->h_FmPcd);
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ if ((p_FmPort->pcdEngines & FM_PCD_PRS) &&
+ (p_PcdParams->p_PrsParams->includeInPrsStatistics))
+ {
+ err = FmPcdPrsIncludePortInStatistics(p_FmPort->h_FmPcd, p_FmPort->hardwarePortId, TRUE);
+ if (err)
+ {
+ DeletePcd(p_FmPort);
+ if (p_FmPort->h_IpReassemblyTree)
+ {
+ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree);
+ p_FmPort->h_IpReassemblyTree = NULL;
+ }
+ FmPcdLockUnlockAll(p_FmPort->h_FmPcd);
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ p_FmPort->includeInPrsStatistics = TRUE;
+ }
+
+ FmPcdIncNetEnvOwners(p_FmPort->h_FmPcd, p_FmPort->netEnvId);
+
+ if (FmPcdIsAdvancedOffloadSupported(p_FmPort->h_FmPcd))
+ {
+ memset(&fmPortGetSetCcParams, 0, sizeof(t_FmPortGetSetCcParams));
+
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ {
+#ifdef FM_KG_ERASE_FLOW_ID_ERRATA_FMAN_SW004
+ if ((p_FmPort->fmRevInfo.majorRev < 6) &&
+ (p_FmPort->pcdEngines & FM_PCD_KG))
+ {
+ int i;
+ for (i = 0; i<p_PcdParams->p_KgParams->numOfSchemes; i++)
+ /* The following function must be locked */
+ FmPcdKgCcGetSetParams(p_FmPort->h_FmPcd,
+ p_PcdParams->p_KgParams->h_Schemes[i],
+ UPDATE_KG_NIA_CC_WA,
+ 0);
+ }
+#endif /* FM_KG_ERASE_FLOW_ID_ERRATA_FMAN_SW004 */
+
+ /* Set post-bmi-fetch nia */
+ p_FmPort->savedBmiNia &= BMI_RFNE_FDCS_MASK;
+ p_FmPort->savedBmiNia |= (NIA_FM_CTL_AC_POST_BMI_FETCH | NIA_ENG_FM_CTL);
+
+ /* Set pre-bmi-fetch nia */
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNDN;
+#if (DPAA_VERSION >= 11)
+ fmPortGetSetCcParams.setCcParams.nia = (NIA_FM_CTL_AC_PRE_BMI_FETCH_FULL_FRAME | NIA_ENG_FM_CTL);
+#else
+ fmPortGetSetCcParams.setCcParams.nia = (NIA_FM_CTL_AC_PRE_BMI_FETCH_HEADER | NIA_ENG_FM_CTL);
+#endif /* (DPAA_VERSION >= 11) */
+ if ((err = FmPortGetSetCcParams(p_FmPort, &fmPortGetSetCcParams)) != E_OK)
+ {
+ DeletePcd(p_FmPort);
+ if (p_FmPort->h_IpReassemblyTree)
+ {
+ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree);
+ p_FmPort->h_IpReassemblyTree = NULL;
+ }
+ FmPcdLockUnlockAll(p_FmPort->h_FmPcd);
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ }
+
+ FmPcdLockUnlockAll(p_FmPort->h_FmPcd);
+
+ /* Set pop-to-next-step nia */
+#if (DPAA_VERSION == 10)
+ if (p_FmPort->fmRevInfo.majorRev < 6)
+ {
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_PNEN;
+ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_POP_TO_N_STEP | NIA_ENG_FM_CTL;
+ }
+ else
+ {
+#endif /* (DPAA_VERSION == 10) */
+ fmPortGetSetCcParams.getCcParams.type = GET_NIA_FPNE;
+#if (DPAA_VERSION == 10)
+ }
+#endif /* (DPAA_VERSION == 10) */
+ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK)
+ {
+ DeletePcd(p_FmPort);
+ if (p_FmPort->h_IpReassemblyTree)
+ {
+ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree);
+ p_FmPort->h_IpReassemblyTree = NULL;
+ }
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ /* Set post-bmi-prepare-to-enq nia */
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_FENE;
+ fmPortGetSetCcParams.setCcParams.nia = (NIA_FM_CTL_AC_POST_BMI_ENQ | NIA_ENG_FM_CTL);
+ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK)
+ {
+ DeletePcd(p_FmPort);
+ if (p_FmPort->h_IpReassemblyTree)
+ {
+ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree);
+ p_FmPort->h_IpReassemblyTree = NULL;
+ }
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ if (p_FmPort->h_IpReassemblyManip)
+ {
+#if (DPAA_VERSION == 10)
+ if (p_FmPort->fmRevInfo.majorRev < 6)
+ {
+ /* Overwrite post-bmi-prepare-to-enq nia */
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_FENE;
+ fmPortGetSetCcParams.setCcParams.nia = (NIA_FM_CTL_AC_POST_BMI_ENQ_ORR | NIA_ENG_FM_CTL | NIA_ORDER_RESTOR);
+ fmPortGetSetCcParams.setCcParams.overwrite = TRUE;
+ }
+ else
+ {
+#endif /* (DPAA_VERSION == 10) */
+ /* Set the ORR bit (for order-restoration) */
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_FPNE;
+ fmPortGetSetCcParams.setCcParams.nia = fmPortGetSetCcParams.getCcParams.nia | NIA_ORDER_RESTOR;
+#if (DPAA_VERSION == 10)
+ }
+#endif /* (DPAA_VERSION == 10) */
+ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK)
+ {
+ DeletePcd(p_FmPort);
+ if (p_FmPort->h_IpReassemblyTree)
+ {
+ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree);
+ p_FmPort->h_IpReassemblyTree = NULL;
+ }
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ }
+ }
+ else
+ FmPcdLockUnlockAll(p_FmPort->h_FmPcd);
+
+#if (DPAA_VERSION >= 11)
+ {
+ t_FmPcdCtrlParamsPage *p_ParamsPage;
+
+ memset(&fmPortGetSetCcParams, 0, sizeof(t_FmPortGetSetCcParams));
+
+ fmPortGetSetCcParams.setCcParams.type = UPDATE_NIA_CMNE;
+ if (FmPcdIsAdvancedOffloadSupported(p_FmPort->h_FmPcd))
+ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_POP_TO_N_STEP | NIA_ENG_FM_CTL;
+ else
+ fmPortGetSetCcParams.setCcParams.nia = NIA_FM_CTL_AC_NO_IPACC_POP_TO_N_STEP | NIA_ENG_FM_CTL;
+ if ((err = FmPortGetSetCcParams(h_FmPort, &fmPortGetSetCcParams)) != E_OK)
+ {
+ DeletePcd(p_FmPort);
+ if (p_FmPort->h_IpReassemblyTree)
+ {
+ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree);
+ p_FmPort->h_IpReassemblyTree = NULL;
+ }
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ FmPortSetGprFunc(p_FmPort, e_FM_PORT_GPR_MURAM_PAGE, (void**)&p_ParamsPage);
+ ASSERT_COND(p_ParamsPage);
+
+ if (FmPcdIsAdvancedOffloadSupported(p_FmPort->h_FmPcd))
+ WRITE_UINT32(p_ParamsPage->misc, GET_UINT32(p_ParamsPage->misc) | FM_CTL_PARAMS_PAGE_OFFLOAD_SUPPORT_EN);
+
+ if (p_FmPort->h_IpReassemblyManip)
+ {
+ if (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ WRITE_UINT32(p_ParamsPage->discardMask,
+ GET_UINT32(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofsdm));
+ else
+ WRITE_UINT32(p_ParamsPage->discardMask,
+ GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfsdm));
+ }
+#ifdef FM_ERROR_VSP_NO_MATCH_SW006
+ if (p_FmPort->vspe)
+ WRITE_UINT32(p_ParamsPage->misc,
+ GET_UINT32(p_ParamsPage->misc) | (p_FmPort->dfltRelativeId & FM_CTL_PARAMS_PAGE_ERROR_VSP_MASK));
+#endif /* FM_ERROR_VSP_NO_MATCH_SW006 */
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ err = AttachPCD(h_FmPort);
+ if (err)
+ {
+ DeletePcd(p_FmPort);
+ if (p_FmPort->h_IpReassemblyTree)
+ {
+ FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree);
+ p_FmPort->h_IpReassemblyTree = NULL;
+ }
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ RELEASE_LOCK(p_FmPort->lock);
+
+ return err;
+}
+
+t_Error FM_PORT_DeletePCD(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+
+ if (p_FmPort->imEn)
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for non-independant mode ports only"));
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_RX) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = DetachPCD(h_FmPort);
+ if (err)
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ FmPcdDecNetEnvOwners(p_FmPort->h_FmPcd, p_FmPort->netEnvId);
+
+ /* we do it anyway, instead of checking if included */
+ if ((p_FmPort->pcdEngines & FM_PCD_PRS) &&
+ p_FmPort->includeInPrsStatistics)
+ {
+ FmPcdPrsIncludePortInStatistics(p_FmPort->h_FmPcd, p_FmPort->hardwarePortId, FALSE);
+ p_FmPort->includeInPrsStatistics = FALSE;
+ }
+
+ if (!FmPcdLockTryLockAll(p_FmPort->h_FmPcd))
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ DBG(TRACE, ("Try LockAll - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = DeletePcd(h_FmPort);
+ FmPcdLockUnlockAll(p_FmPort->h_FmPcd);
+ if (err)
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ if (p_FmPort->h_IpReassemblyTree)
+ {
+ err = FM_PCD_CcRootDelete(p_FmPort->h_IpReassemblyTree);
+ if (err)
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ p_FmPort->h_IpReassemblyTree = NULL;
+ }
+ RELEASE_LOCK(p_FmPort->lock);
+
+ return err;
+}
+
+t_Error FM_PORT_PcdKgBindSchemes (t_Handle h_FmPort, t_FmPcdPortSchemesParams *p_PortScheme)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_FmPcdKgInterModuleBindPortToSchemes schemeBind;
+ t_Error err = E_OK;
+ uint32_t tmpScmVec=0;
+ int i;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_KG , E_INVALID_STATE);
+
+ schemeBind.netEnvId = p_FmPort->netEnvId;
+ schemeBind.hardwarePortId = p_FmPort->hardwarePortId;
+ schemeBind.numOfSchemes = p_PortScheme->numOfSchemes;
+ schemeBind.useClsPlan = p_FmPort->useClsPlan;
+ for (i=0; i<schemeBind.numOfSchemes; i++)
+ {
+ schemeBind.schemesIds[i] = FmPcdKgGetSchemeId(p_PortScheme->h_Schemes[i]);
+ /* build vector */
+ tmpScmVec |= 1 << (31 - (uint32_t)schemeBind.schemesIds[i]);
+ }
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FmPcdKgBindPortToSchemes(p_FmPort->h_FmPcd, &schemeBind);
+ if (err == E_OK)
+ p_FmPort->schemesPerPortVector |= tmpScmVec;
+
+#ifdef FM_KG_ERASE_FLOW_ID_ERRATA_FMAN_SW004
+ if ((FmPcdIsAdvancedOffloadSupported(p_FmPort->h_FmPcd)) &&
+ (p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) &&
+ (p_FmPort->fmRevInfo.majorRev < 6))
+ {
+ for (i=0; i<p_PortScheme->numOfSchemes; i++)
+ FmPcdKgCcGetSetParams(p_FmPort->h_FmPcd, p_PortScheme->h_Schemes[i], UPDATE_KG_NIA_CC_WA, 0);
+ }
+#endif /* FM_KG_ERASE_FLOW_ID_ERRATA_FMAN_SW004 */
+
+ RELEASE_LOCK(p_FmPort->lock);
+
+ return err;
+}
+
+t_Error FM_PORT_PcdKgUnbindSchemes (t_Handle h_FmPort, t_FmPcdPortSchemesParams *p_PortScheme)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_FmPcdKgInterModuleBindPortToSchemes schemeBind;
+ t_Error err = E_OK;
+ uint32_t tmpScmVec=0;
+ int i;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_KG , E_INVALID_STATE);
+
+ schemeBind.netEnvId = p_FmPort->netEnvId;
+ schemeBind.hardwarePortId = p_FmPort->hardwarePortId;
+ schemeBind.numOfSchemes = p_PortScheme->numOfSchemes;
+ for (i=0; i<schemeBind.numOfSchemes; i++)
+ {
+ schemeBind.schemesIds[i] = FmPcdKgGetSchemeId(p_PortScheme->h_Schemes[i]);
+ /* build vector */
+ tmpScmVec |= 1 << (31 - (uint32_t)schemeBind.schemesIds[i]);
+ }
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ err = FmPcdKgUnbindPortToSchemes(p_FmPort->h_FmPcd, &schemeBind);
+ if (err == E_OK)
+ p_FmPort->schemesPerPortVector &= ~tmpScmVec;
+ RELEASE_LOCK(p_FmPort->lock);
+
+ return err;
+}
+
+t_Error FM_PORT_PcdPrsModifyStartOffset (t_Handle h_FmPort, t_FmPcdPrsStart *p_FmPcdPrsStart)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ volatile uint32_t *p_BmiPrsStartOffset = NULL;
+ volatile uint32_t *p_BmiNia = NULL;
+ uint32_t tmpReg;
+ uint8_t hdrNum;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->pcdEngines & FM_PCD_PRS , E_INVALID_STATE);
+
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_RX_10G):
+ case (e_FM_PORT_TYPE_RX):
+ p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rpso;
+ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne;
+ tmpReg = GET_UINT32(*p_BmiNia) & BMI_RFNE_FDCS_MASK;
+ break;
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ p_BmiPrsStartOffset = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_opso;
+ p_BmiNia = &p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_ofne;
+ tmpReg = 0;
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("available for Rx and offline parsing ports only"));
+ }
+
+ /* check that current NIA is BMI to BMI */
+ if ((GET_UINT32(*p_BmiNia) & ~BMI_RFNE_FDCS_MASK) !=
+ GET_NIA_BMI_AC_ENQ_FRAME(p_FmPort->h_FmPcd))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("may be called only for ports in BMI-to-BMI state."));
+
+ if (!TRY_LOCK(p_FmPort->h_Spinlock, &p_FmPort->lock))
+ {
+ DBG(TRACE, ("FM Port Try Lock - BUSY"));
+ return ERROR_CODE(E_BUSY);
+ }
+
+ /* set the first header */
+ GET_PRS_HDR_NUM(hdrNum, p_FmPcdPrsStart->firstPrsHdr);
+ if ((hdrNum == ILLEGAL_HDR_NUM) || (hdrNum == NO_HDR_NUM))
+ {
+ RELEASE_LOCK(p_FmPort->lock);
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unsupported header."));
+ }
+ WRITE_UINT32(*p_BmiNia, (uint32_t)(NIA_ENG_PRS | (uint32_t)hdrNum | tmpReg));
+
+ /* set start parsing offset */
+ WRITE_UINT32(*p_BmiPrsStartOffset,
+ (uint32_t)(p_FmPcdPrsStart->parsingOffset +
+ p_FmPort->internalBufferOffset));
+ RELEASE_LOCK(p_FmPort->lock);
+
+ return E_OK;
+}
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+t_Error FM_PORT_DumpRegs(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err = E_OK;
+ char arr[20];
+ uint8_t flag;
+ int i=0;
+
+ DECLARE_DUMP;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortQmiRegs, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortBmiRegs, E_INVALID_HANDLE);
+
+ memset(arr, 0, sizeof(arr));
+ switch (p_FmPort->portType)
+ {
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ strcpy(arr, "OFFLINE-PARSING");
+ flag = 0;
+ break;
+ case (e_FM_PORT_TYPE_OH_HOST_COMMAND):
+ strcpy(arr, "HOST-COMMAND");
+ flag = 0;
+ break;
+ case (e_FM_PORT_TYPE_RX):
+ strcpy(arr, "RX");
+ flag = 1;
+ break;
+ case (e_FM_PORT_TYPE_RX_10G):
+ strcpy(arr, "RX-10G");
+ flag = 1;
+ break;
+ case (e_FM_PORT_TYPE_TX):
+ strcpy(arr, "TX");
+ flag = 2;
+ break;
+ case (e_FM_PORT_TYPE_TX_10G):
+ strcpy(arr, "TX-10G");
+ flag = 2;
+ break;
+ default:
+ return ERROR_CODE(E_INVALID_VALUE);
+ }
+
+ DUMP_TITLE(NULL,
+ ("FMan-Port (%s #%d) registers:",
+ arr, p_FmPort->portId));
+
+ err = FmDumpPortRegs(p_FmPort->h_Fm, p_FmPort->hardwarePortId);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ DUMP_TITLE(p_FmPort->p_FmPortBmiRegs, ("Bmi Port Regs"));
+
+ switch (flag)
+ {
+ case (0):
+
+ DUMP_SUBTITLE(("\n"));
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ocfg);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ost);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_oda);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_oicp);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofdne);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofne);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofca);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofpne);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_opso);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_opp);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_occb);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_oim);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofp);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofed);
+
+ DUMP_TITLE(&(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_oprai), ("fmbm_oprai"));
+ DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_PRS_RESULT_NUM_OF_WORDS)
+ {
+ DUMP_MEMORY(&(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_oprai[i]), sizeof(uint32_t));
+ }
+ DUMP_SUBTITLE(("\n"));
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofqid );
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_oefqid);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofsdm );
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofsem );
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofene );
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_orlmts);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_orlmt);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ocmne);
+ {
+#ifndef FM_NO_OP_OBSERVED_POOLS
+ if (p_FmPort->fmRevInfo.majorRev == 4)
+ {
+ DUMP_TITLE(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_oebmpi, ("fmbm_oebmpi"));
+
+ DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_MAX_NUM_OF_OBSERVED_EXT_POOLS)
+ {
+ DUMP_MEMORY(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_oebmpi[i], sizeof(uint32_t));
+ }
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ocgm);
+ }
+#endif /* !FM_NO_OP_OBSERVED_POOLS */
+ }
+
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ostc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofrc );
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofdc );
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofledc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofufdc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_offc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofwdc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofldec);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_opc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_opcp);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_occn);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_otuc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_oduc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ofuc);
+ DUMP_TITLE(&(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_odcfg), ("fmbm_odcfg"));
+ DUMP_SUBSTRUCT_ARRAY(i, 3)
+ {
+ DUMP_MEMORY(&(p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs.fmbm_odcfg[i]), sizeof(uint32_t));
+ }
+ DUMP_SUBTITLE(("\n"));
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->ohPortBmiRegs,fmbm_ogpr);
+ break;
+ case (1):
+ DUMP_SUBTITLE(("\n"));
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rcfg);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rst);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rda);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfp);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_reth);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfed);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_ricp);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rebm);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfne);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfca);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfpne);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rpso);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rpp);
+
+ DUMP_TITLE(&(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rprai), ("fmbm_rprai"));
+ DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_PRS_RESULT_NUM_OF_WORDS)
+ {
+ DUMP_MEMORY(&(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rprai[i]), sizeof(uint32_t));
+ }
+ DUMP_SUBTITLE(("\n"));
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfqid);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_refqid);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfsdm);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfsem);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfene);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rcmne);
+ DUMP_TITLE(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_ebmpi, ("fmbm_ebmpi"));
+ DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_MAX_NUM_OF_EXT_POOLS)
+ {
+ DUMP_MEMORY(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_ebmpi[i], sizeof(uint32_t));
+ }
+ DUMP_TITLE(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_acnt, ("fmbm_acnt"));
+ DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_MAX_NUM_OF_EXT_POOLS)
+ {
+ DUMP_MEMORY(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_acnt[i], sizeof(uint32_t));
+ }
+ DUMP_TITLE(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcgm, ("fmbm_rcgm"));
+ DUMP_SUBSTRUCT_ARRAY(i, FM_PORT_NUM_OF_CONGESTION_GRPS/32)
+ {
+ DUMP_MEMORY(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcgm[i], sizeof(uint32_t));
+ }
+ DUMP_SUBTITLE(("\n"));
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rmpd);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rstc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfrc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfbc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rlfc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rffc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfcd);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfldec);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rodc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rpc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rpcp);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rccn);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rtuc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rrquc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rduc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rfuc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rpac);
+ DUMP_TITLE(&(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rdcfg), ("fmbm_rdcfg"));
+ DUMP_SUBSTRUCT_ARRAY(i, 3)
+ {
+ DUMP_MEMORY(&(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rdcfg[i]), sizeof(uint32_t));
+ }
+ DUMP_SUBTITLE(("\n"));
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs,fmbm_rgpr);
+ break;
+ case (2):
+
+ DUMP_SUBTITLE(("\n"));
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tcfg);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tst);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tda);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfp);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfed);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_ticp);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfdne);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfca);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tcfqid);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfeqid);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfene);
+#if (DPAA_VERSION >= 11)
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfne);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tcmne);
+#endif /* (DPAA_VERSION >= 11) */
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_trlmts);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_trlmt);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tstc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfrc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfdc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfledc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfufdc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tpc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tpcp);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tccn);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_ttuc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_ttcquc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tduc);
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tfuc);
+ DUMP_TITLE(&(p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tdcfg), ("fmbm_tdcfg"));
+ DUMP_SUBSTRUCT_ARRAY(i, 3)
+ {
+ DUMP_MEMORY(&(p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tdcfg[i]), sizeof(uint32_t));
+ }
+ DUMP_SUBTITLE(("\n"));
+ DUMP_VAR(&p_FmPort->p_FmPortBmiRegs->txPortBmiRegs,fmbm_tgpr);
+ break;
+
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Invalid flag"));
+ }
+
+ DUMP_TITLE(p_FmPort->p_FmPortQmiRegs, ("Qmi Port Regs"));
+
+ DUMP_VAR(p_FmPort->p_FmPortQmiRegs,fmqm_pnc);
+ DUMP_VAR(p_FmPort->p_FmPortQmiRegs,fmqm_pns);
+ DUMP_VAR(p_FmPort->p_FmPortQmiRegs,fmqm_pnts);
+ DUMP_VAR(p_FmPort->p_FmPortQmiRegs,fmqm_pnen);
+ DUMP_VAR(p_FmPort->p_FmPortQmiRegs,fmqm_pnetfc);
+
+ if (flag !=1)
+ {
+ DUMP_VAR(&p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs,fmqm_pndn);
+ DUMP_VAR(&p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs,fmqm_pndc);
+ DUMP_VAR(&p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs,fmqm_pndtfc);
+ DUMP_VAR(&p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs,fmqm_pndfdc);
+ DUMP_VAR(&p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs,fmqm_pndcc);
+ }
+
+ return E_OK;
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+t_Error FM_PORT_AddCongestionGrps(t_Handle h_FmPort, t_FmPortCongestionGrps *p_CongestionGrps)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ uint8_t priorityTmpArray[FM_PORT_NUM_OF_CONGESTION_GRPS];
+ uint8_t mod, index;
+ uint32_t i, grpsMap[FMAN_PORT_CG_MAP_NUM];
+ int err;
+#if (DPAA_VERSION >= 11)
+ int j;
+#endif /* (DPAA_VERSION >= 11) */
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+
+ /* un-necessary check of the indexes; probably will be needed in the future when there
+ will be more CGs available ....
+ for (i=0; i<p_CongestionGrps->numOfCongestionGrpsToConsider; i++)
+ if (p_CongestionGrps->congestionGrpsToConsider[i] >= FM_PORT_NUM_OF_CONGESTION_GRPS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("CG id!"));
+ */
+
+#ifdef FM_NO_OP_OBSERVED_CGS
+ if ((p_FmPort->fmRevInfo.majorRev != 4) &&
+ (p_FmPort->fmRevInfo.majorRev < 6))
+ {
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Available for Rx ports only"));
+ }
+ else
+#endif /* FM_NO_OP_OBSERVED_CGS */
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_RX) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Available for Rx & OP ports only"));
+
+ /* Prepare groups map array */
+ memset(grpsMap, 0, FMAN_PORT_CG_MAP_NUM * sizeof(uint32_t));
+ for (i = 0; i < p_CongestionGrps->numOfCongestionGrpsToConsider; i++)
+ {
+ index = (uint8_t)(p_CongestionGrps->congestionGrpsToConsider[i] / 32);
+ mod = (uint8_t)(p_CongestionGrps->congestionGrpsToConsider[i] % 32);
+ if (p_FmPort->fmRevInfo.majorRev != 4)
+ grpsMap[7 - index] |= (uint32_t)(1 << mod);
+ else
+ grpsMap[0] |= (uint32_t)(1 << mod);
+ }
+
+ memset(&priorityTmpArray, 0, FM_PORT_NUM_OF_CONGESTION_GRPS*sizeof(uint8_t));
+
+ for (i=0; i<p_CongestionGrps->numOfCongestionGrpsToConsider; i++)
+ {
+#if (DPAA_VERSION >= 11)
+ for (j=0;j<FM_MAX_NUM_OF_PFC_PRIORITIES;j++)
+ if (p_CongestionGrps->pfcPrioritiesEn[i][j])
+ priorityTmpArray[p_CongestionGrps->congestionGrpsToConsider[i]] |= (0x01 <<(FM_MAX_NUM_OF_PFC_PRIORITIES-j-1));
+#endif /* (DPAA_VERSION >= 11) */
+ }
+
+#if (DPAA_VERSION >= 11)
+ for (i=0; i<FM_PORT_NUM_OF_CONGESTION_GRPS; i++)
+ {
+ err = FmSetCongestionGroupPFCpriority(p_FmPort->h_Fm,i,priorityTmpArray[i]);
+ if (err)
+ return err;
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ err = fman_port_add_congestion_grps(&p_FmPort->port, grpsMap);
+ if (err != 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_add_congestion_grps"));
+
+ return E_OK;
+}
+
+t_Error FM_PORT_RemoveCongestionGrps(t_Handle h_FmPort, t_FmPortCongestionGrps *p_CongestionGrps)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ uint8_t mod, index;
+ uint32_t i, grpsMap[FMAN_PORT_CG_MAP_NUM];
+ int err;
+
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+
+ {
+#ifdef FM_NO_OP_OBSERVED_CGS
+ t_FmRevisionInfo revInfo;
+
+ FM_GetRevision(p_FmPort->h_Fm, &revInfo);
+ if (revInfo.majorRev != 4)
+ {
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Available for Rx ports only"));
+ }
+ else
+#endif /* FM_NO_OP_OBSERVED_CGS */
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_RX) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Available for Rx & OP ports only"));
+ }
+
+ /* Prepare groups map array */
+ memset(grpsMap, 0, FMAN_PORT_CG_MAP_NUM * sizeof(uint32_t));
+ for (i = 0; i < p_CongestionGrps->numOfCongestionGrpsToConsider; i++)
+ {
+ index = (uint8_t)(p_CongestionGrps->congestionGrpsToConsider[i] / 32);
+ mod = (uint8_t)(p_CongestionGrps->congestionGrpsToConsider[i] % 32);
+ if (p_FmPort->fmRevInfo.majorRev != 4)
+ grpsMap[7 - index] |= (uint32_t)(1 << mod);
+ else
+ grpsMap[0] |= (uint32_t)(1 << mod);
+ }
+
+#if (DPAA_VERSION >= 11)
+ for (i=0; i<p_CongestionGrps->numOfCongestionGrpsToConsider; i++)
+ {
+ t_Error err = FmSetCongestionGroupPFCpriority(p_FmPort->h_Fm,
+ p_CongestionGrps->congestionGrpsToConsider[i], 0);
+ if (err)
+ return err;
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ err = fman_port_remove_congestion_grps(&p_FmPort->port, grpsMap);
+ if (err != 0)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fman_port_remove_congestion_grps"));
+ return E_OK;
+}
+
+#if (DPAA_VERSION >= 11)
+t_Error FM_PORT_GetIPv4OptionsCount(t_Handle h_FmPort, uint32_t *p_Ipv4OptionsCount)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_FmPort->portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING), E_INVALID_VALUE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_ParamsPage, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_Ipv4OptionsCount, E_NULL_POINTER);
+
+ *p_Ipv4OptionsCount = GET_UINT32(p_FmPort->p_ParamsPage->ipfOptionsCounter);
+
+ return E_OK;
+}
+#endif /* (DPAA_VERSION >= 11) */
+
+t_Error FM_PORT_ConfigDsarSupport(t_Handle h_FmPortRx, t_FmPortDsarTablesSizes *params)
+{
+ t_FmPort *p_FmPort= (t_FmPort *)h_FmPortRx;
+ p_FmPort->deepSleepVars.autoResMaxSizes = XX_Malloc(sizeof(struct t_FmPortDsarTablesSizes));
+ memcpy(p_FmPort->deepSleepVars.autoResMaxSizes, params, sizeof(struct t_FmPortDsarTablesSizes));
+ return E_OK;
+}
+
+static t_Error FmPortConfigAutoResForDeepSleepSupport1(t_FmPort *p_FmPort)
+{
+ uint32_t *param_page;
+ t_FmPortDsarTablesSizes *params = p_FmPort->deepSleepVars.autoResMaxSizes;
+ t_ArCommonDesc *ArCommonDescPtr;
+ uint32_t size = sizeof(t_ArCommonDesc);
+ // ARP
+ // should put here if (params->max_num_of_arp_entries)?
+ size = ROUND_UP(size,4);
+ size += sizeof(t_DsarArpDescriptor);
+ size += sizeof(t_DsarArpBindingEntry) * params->maxNumOfArpEntries;
+ size += sizeof(t_DsarArpStatistics);
+ //ICMPV4
+ size = ROUND_UP(size,4);
+ size += sizeof(t_DsarIcmpV4Descriptor);
+ size += sizeof(t_DsarIcmpV4BindingEntry) * params->maxNumOfEchoIpv4Entries;
+ size += sizeof(t_DsarIcmpV4Statistics);
+ //ICMPV6
+ size = ROUND_UP(size,4);
+ size += sizeof(t_DsarIcmpV6Descriptor);
+ size += sizeof(t_DsarIcmpV6BindingEntry) * params->maxNumOfEchoIpv6Entries;
+ size += sizeof(t_DsarIcmpV6Statistics);
+ //ND
+ size = ROUND_UP(size,4);
+ size += sizeof(t_DsarNdDescriptor);
+ size += sizeof(t_DsarIcmpV6BindingEntry) * params->maxNumOfNdpEntries;
+ size += sizeof(t_DsarIcmpV6Statistics);
+ //SNMP
+ size = ROUND_UP(size,4);
+ size += sizeof(t_DsarSnmpDescriptor);
+ size += sizeof(t_DsarSnmpIpv4AddrTblEntry) * params->maxNumOfSnmpIPV4Entries;
+ size += sizeof(t_DsarSnmpIpv6AddrTblEntry) * params->maxNumOfSnmpIPV6Entries;
+ size += sizeof(t_OidsTblEntry) * params->maxNumOfSnmpOidEntries;
+ size += params->maxNumOfSnmpOidChar;
+ size += sizeof(t_DsarIcmpV6Statistics);
+ //filters
+ size = ROUND_UP(size,4);
+ size += params->maxNumOfIpProtFiltering;
+ size = ROUND_UP(size,4);
+ size += params->maxNumOfUdpPortFiltering * sizeof(t_PortTblEntry);
+ size = ROUND_UP(size,4);
+ size += params->maxNumOfTcpPortFiltering * sizeof(t_PortTblEntry);
+
+ // add here for more protocols
+
+ // statistics
+ size = ROUND_UP(size,4);
+ size += sizeof(t_ArStatistics);
+
+ ArCommonDescPtr = FM_MURAM_AllocMem(p_FmPort->h_FmMuram, size, 0x10);
+
+ param_page = XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr + GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr));
+ WRITE_UINT32(*param_page,
+ (uint32_t)(XX_VirtToPhys(ArCommonDescPtr) - p_FmPort->fmMuramPhysBaseAddr));
+ return E_OK;
+}
+
+t_FmPortDsarTablesSizes* FM_PORT_GetDsarTablesMaxSizes(t_Handle h_FmPortRx)
+{
+ t_FmPort *p_FmPort= (t_FmPort *)h_FmPortRx;
+ return p_FmPort->deepSleepVars.autoResMaxSizes;
+}
+
+struct arOffsets
+{
+ uint32_t arp;
+ uint32_t nd;
+ uint32_t icmpv4;
+ uint32_t icmpv6;
+ uint32_t snmp;
+ uint32_t stats;
+ uint32_t filtIp;
+ uint32_t filtUdp;
+ uint32_t filtTcp;
+};
+
+static uint32_t AR_ComputeOffsets(struct arOffsets* of, struct t_FmPortDsarParams *params, t_FmPort *p_FmPort)
+{
+ uint32_t size = sizeof(t_ArCommonDesc);
+ // ARP
+ if (params->p_AutoResArpInfo)
+ {
+ size = ROUND_UP(size,4);
+ of->arp = size;
+ size += sizeof(t_DsarArpDescriptor);
+ size += sizeof(t_DsarArpBindingEntry) * params->p_AutoResArpInfo->tableSize;
+ size += sizeof(t_DsarArpStatistics);
+ }
+ // ICMPV4
+ if (params->p_AutoResEchoIpv4Info)
+ {
+ size = ROUND_UP(size,4);
+ of->icmpv4 = size;
+ size += sizeof(t_DsarIcmpV4Descriptor);
+ size += sizeof(t_DsarIcmpV4BindingEntry) * params->p_AutoResEchoIpv4Info->tableSize;
+ size += sizeof(t_DsarIcmpV4Statistics);
+ }
+ // ICMPV6
+ if (params->p_AutoResEchoIpv6Info)
+ {
+ size = ROUND_UP(size,4);
+ of->icmpv6 = size;
+ size += sizeof(t_DsarIcmpV6Descriptor);
+ size += sizeof(t_DsarIcmpV6BindingEntry) * params->p_AutoResEchoIpv6Info->tableSize;
+ size += sizeof(t_DsarIcmpV6Statistics);
+ }
+ // ND
+ if (params->p_AutoResNdpInfo)
+ {
+ size = ROUND_UP(size,4);
+ of->nd = size;
+ size += sizeof(t_DsarNdDescriptor);
+ size += sizeof(t_DsarIcmpV6BindingEntry) *
+ (params->p_AutoResNdpInfo->tableSizeAssigned + params->p_AutoResNdpInfo->tableSizeTmp);
+ size += sizeof(t_DsarIcmpV6Statistics);
+ }
+ // SNMP
+ if (params->p_AutoResSnmpInfo)
+ {
+ size = ROUND_UP(size,4);
+ of->snmp = size;
+ size += sizeof(t_DsarSnmpDescriptor);
+ size += sizeof(t_DsarSnmpIpv4AddrTblEntry) * params->p_AutoResSnmpInfo->numOfIpv4Addresses;
+ size += sizeof(t_DsarSnmpIpv6AddrTblEntry) * params->p_AutoResSnmpInfo->numOfIpv6Addresses;
+ size += sizeof(t_OidsTblEntry) * params->p_AutoResSnmpInfo->oidsTblSize;
+ size += p_FmPort->deepSleepVars.autoResMaxSizes->maxNumOfSnmpOidChar;
+ size += sizeof(t_DsarIcmpV6Statistics);
+ }
+ //filters
+ size = ROUND_UP(size,4);
+ if (params->p_AutoResFilteringInfo)
+ {
+ of->filtIp = size;
+ size += params->p_AutoResFilteringInfo->ipProtTableSize;
+ size = ROUND_UP(size,4);
+ of->filtUdp = size;
+ size += params->p_AutoResFilteringInfo->udpPortsTableSize * sizeof(t_PortTblEntry);
+ size = ROUND_UP(size,4);
+ of->filtTcp = size;
+ size += params->p_AutoResFilteringInfo->tcpPortsTableSize * sizeof(t_PortTblEntry);
+ }
+ // add here for more protocols
+ // statistics
+ size = ROUND_UP(size,4);
+ of->stats = size;
+ size += sizeof(t_ArStatistics);
+ return size;
+}
+
+uint32_t* ARDesc;
+void PrsEnable(t_Handle p_FmPcd);
+void PrsDisable(t_Handle p_FmPcd);
+int PrsIsEnabled(t_Handle p_FmPcd);
+
+static t_Error DsarCheckParams(t_FmPortDsarParams *params, t_FmPortDsarTablesSizes *sizes)
+{
+ bool macInit = FALSE;
+ uint8_t mac[6];
+ int i;
+
+ // check table sizes
+ if (params->p_AutoResArpInfo && sizes->maxNumOfArpEntries < params->p_AutoResArpInfo->tableSize)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Arp table size exceeds the configured maximum size."));
+ if (params->p_AutoResEchoIpv4Info && sizes->maxNumOfEchoIpv4Entries < params->p_AutoResEchoIpv4Info->tableSize)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: EchoIpv4 table size exceeds the configured maximum size."));
+ if (params->p_AutoResNdpInfo && sizes->maxNumOfNdpEntries < params->p_AutoResNdpInfo->tableSizeAssigned + params->p_AutoResNdpInfo->tableSizeTmp)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: NDP table size exceeds the configured maximum size."));
+ if (params->p_AutoResEchoIpv6Info && sizes->maxNumOfEchoIpv6Entries < params->p_AutoResEchoIpv6Info->tableSize)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: EchoIpv6 table size exceeds the configured maximum size."));
+ if (params->p_AutoResSnmpInfo && sizes->maxNumOfSnmpOidEntries < params->p_AutoResSnmpInfo->oidsTblSize)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Snmp Oid table size exceeds the configured maximum size."));
+ if (params->p_AutoResSnmpInfo && sizes->maxNumOfSnmpIPV4Entries < params->p_AutoResSnmpInfo->numOfIpv4Addresses)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Snmp ipv4 table size exceeds the configured maximum size."));
+ if (params->p_AutoResSnmpInfo && sizes->maxNumOfSnmpIPV6Entries < params->p_AutoResSnmpInfo->numOfIpv6Addresses)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Snmp ipv6 table size exceeds the configured maximum size."));
+ if (params->p_AutoResFilteringInfo)
+ {
+ if (sizes->maxNumOfIpProtFiltering < params->p_AutoResFilteringInfo->ipProtTableSize)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: ip filter table size exceeds the configured maximum size."));
+ if (sizes->maxNumOfTcpPortFiltering < params->p_AutoResFilteringInfo->udpPortsTableSize)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: udp filter table size exceeds the configured maximum size."));
+ if (sizes->maxNumOfUdpPortFiltering < params->p_AutoResFilteringInfo->tcpPortsTableSize)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: tcp filter table size exceeds the configured maximum size."));
+ }
+ // check only 1 MAC address is configured (this is what ucode currently supports)
+ if (params->p_AutoResArpInfo && params->p_AutoResArpInfo->tableSize)
+ {
+ i = 0;
+ if (!macInit)
+ {
+ memcpy(mac, params->p_AutoResArpInfo->p_AutoResTable[0].mac, 6);
+ i = 1;
+ macInit = TRUE;
+ }
+ for (; i < params->p_AutoResArpInfo->tableSize; i++)
+ if (memcmp(mac, params->p_AutoResArpInfo->p_AutoResTable[i].mac, 6))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Only 1 mac address is currently supported."));
+ }
+ if (params->p_AutoResEchoIpv4Info && params->p_AutoResEchoIpv4Info->tableSize)
+ {
+ i = 0;
+ if (!macInit)
+ {
+ memcpy(mac, params->p_AutoResEchoIpv4Info->p_AutoResTable[0].mac, 6);
+ i = 1;
+ macInit = TRUE;
+ }
+ for (; i < params->p_AutoResEchoIpv4Info->tableSize; i++)
+ if (memcmp(mac, params->p_AutoResEchoIpv4Info->p_AutoResTable[i].mac, 6))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Only 1 mac address is currently supported."));
+ }
+ if (params->p_AutoResEchoIpv6Info && params->p_AutoResEchoIpv6Info->tableSize)
+ {
+ i = 0;
+ if (!macInit)
+ {
+ memcpy(mac, params->p_AutoResEchoIpv6Info->p_AutoResTable[0].mac, 6);
+ i = 1;
+ macInit = TRUE;
+ }
+ for (; i < params->p_AutoResEchoIpv6Info->tableSize; i++)
+ if (memcmp(mac, params->p_AutoResEchoIpv6Info->p_AutoResTable[i].mac, 6))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Only 1 mac address is currently supported."));
+ }
+ if (params->p_AutoResNdpInfo && params->p_AutoResNdpInfo->tableSizeAssigned)
+ {
+ i = 0;
+ if (!macInit)
+ {
+ memcpy(mac, params->p_AutoResNdpInfo->p_AutoResTableAssigned[0].mac, 6);
+ i = 1;
+ macInit = TRUE;
+ }
+ for (; i < params->p_AutoResNdpInfo->tableSizeAssigned; i++)
+ if (memcmp(mac, params->p_AutoResNdpInfo->p_AutoResTableAssigned[i].mac, 6))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Only 1 mac address is currently supported."));
+ }
+ if (params->p_AutoResNdpInfo && params->p_AutoResNdpInfo->tableSizeTmp)
+ {
+ i = 0;
+ if (!macInit)
+ {
+ memcpy(mac, params->p_AutoResNdpInfo->p_AutoResTableTmp[0].mac, 6);
+ i = 1;
+ macInit = TRUE;
+ }
+ for (; i < params->p_AutoResNdpInfo->tableSizeTmp; i++)
+ if (memcmp(mac, params->p_AutoResNdpInfo->p_AutoResTableTmp[i].mac, 6))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("DSAR: Only 1 mac address is currently supported."));
+ }
+ return E_OK;
+}
+
+static int GetBERLen(uint8_t* buf)
+{
+ if (*buf & 0x80)
+ {
+ if ((*buf & 0x7F) == 1)
+ return buf[1];
+ else
+ return *(uint16_t*)&buf[1]; // assuming max len is 2
+ }
+ else
+ return buf[0];
+}
+#define TOTAL_BER_LEN(len) (len < 128) ? len + 2 : len + 3
+
+t_Error FM_PORT_EnterDsar(t_Handle h_FmPortRx, t_FmPortDsarParams *params)
+{
+ int i,j;
+ t_Error err;
+ uint32_t nia;
+ t_FmPort *p_FmPort= (t_FmPort *)h_FmPortRx;
+ t_FmPort *p_FmPortTx = (t_FmPort *)params->h_FmPortTx;
+ t_DsarArpDescriptor *ArpDescriptor;
+ t_DsarIcmpV4Descriptor* ICMPV4Descriptor;
+ t_DsarIcmpV6Descriptor* ICMPV6Descriptor;
+ t_DsarNdDescriptor* NDDescriptor;
+ uint64_t fmMuramVirtBaseAddr = (uint64_t)PTR_TO_UINT(XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr));
+ uint32_t *param_page = XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr + GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr));
+ t_ArCommonDesc *ArCommonDescPtr = (t_ArCommonDesc*)(XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr + GET_UINT32(*param_page)));
+ struct arOffsets* of;
+ uint8_t tmp = 0;
+ t_Handle *h_FmPcd;
+ t_FmGetSetParams fmGetSetParams;
+ memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams));
+ fmGetSetParams.setParams.type = UPDATE_FPM_BRKC_SLP;
+ fmGetSetParams.setParams.sleep = 1;
+
+ err = DsarCheckParams(params, p_FmPort->deepSleepVars.autoResMaxSizes);
+ if (err != E_OK)
+ return err;
+
+ p_FmPort->deepSleepVars.autoResOffsets = XX_Malloc(sizeof(struct arOffsets));
+ of = (struct arOffsets *)p_FmPort->deepSleepVars.autoResOffsets;
+ IOMemSet32(ArCommonDescPtr, 0, AR_ComputeOffsets(of, params, p_FmPort));
+
+ // common
+ WRITE_UINT8(ArCommonDescPtr->arTxPort, p_FmPortTx->hardwarePortId);
+ nia = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne); // bmi nia
+ if ((nia & 0x007C0000) == 0x00440000) // bmi nia is parser
+ WRITE_UINT32(ArCommonDescPtr->activeHPNIA, GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne));
+ else
+ WRITE_UINT32(ArCommonDescPtr->activeHPNIA, nia);
+ WRITE_UINT16(ArCommonDescPtr->snmpPort, 161);
+
+ // ARP
+ if (params->p_AutoResArpInfo)
+ {
+ t_DsarArpBindingEntry* arp_bindings;
+ ArpDescriptor = (t_DsarArpDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->arp);
+ WRITE_UINT32(ArCommonDescPtr->p_ArpDescriptor, PTR_TO_UINT(ArpDescriptor) - fmMuramVirtBaseAddr);
+ arp_bindings = (t_DsarArpBindingEntry*)(PTR_TO_UINT(ArpDescriptor) + sizeof(t_DsarArpDescriptor));
+ WRITE_UINT16(ArpDescriptor->control, 0);
+ if (params->p_AutoResArpInfo->tableSize)
+ {
+ t_FmPortDsarArpEntry* arp_entry = params->p_AutoResArpInfo->p_AutoResTable;
+ WRITE_UINT16(*(uint16_t*)&ArCommonDescPtr->macStationAddr[0], *(uint16_t*)&arp_entry[0].mac[0]);
+ WRITE_UINT32(*(uint32_t*)&ArCommonDescPtr->macStationAddr[2], *(uint32_t*)&arp_entry[0].mac[2]);
+ WRITE_UINT16(ArpDescriptor->numOfBindings, params->p_AutoResArpInfo->tableSize);
+
+ for (i = 0; i < params->p_AutoResArpInfo->tableSize; i++)
+ {
+ WRITE_UINT32(arp_bindings[i].ipv4Addr, arp_entry[i].ipAddress);
+ if (arp_entry[i].isVlan)
+ WRITE_UINT16(arp_bindings[i].vlanId, arp_entry[i].vid & 0xFFF);
+ }
+ WRITE_UINT32(ArpDescriptor->p_Bindings, PTR_TO_UINT(arp_bindings) - fmMuramVirtBaseAddr);
+ }
+ WRITE_UINT32(ArpDescriptor->p_Statistics, PTR_TO_UINT(arp_bindings) +
+ sizeof(t_DsarArpBindingEntry) * params->p_AutoResArpInfo->tableSize - fmMuramVirtBaseAddr);
+ }
+
+ // ICMPV4
+ if (params->p_AutoResEchoIpv4Info)
+ {
+ t_DsarIcmpV4BindingEntry* icmpv4_bindings;
+ ICMPV4Descriptor = (t_DsarIcmpV4Descriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->icmpv4);
+ WRITE_UINT32(ArCommonDescPtr->p_IcmpV4Descriptor, PTR_TO_UINT(ICMPV4Descriptor) - fmMuramVirtBaseAddr);
+ icmpv4_bindings = (t_DsarIcmpV4BindingEntry*)(PTR_TO_UINT(ICMPV4Descriptor) + sizeof(t_DsarIcmpV4Descriptor));
+ WRITE_UINT16(ICMPV4Descriptor->control, 0);
+ if (params->p_AutoResEchoIpv4Info->tableSize)
+ {
+ t_FmPortDsarArpEntry* arp_entry = params->p_AutoResEchoIpv4Info->p_AutoResTable;
+ WRITE_UINT16(*(uint16_t*)&ArCommonDescPtr->macStationAddr[0], *(uint16_t*)&arp_entry[0].mac[0]);
+ WRITE_UINT32(*(uint32_t*)&ArCommonDescPtr->macStationAddr[2], *(uint32_t*)&arp_entry[0].mac[2]);
+ WRITE_UINT16(ICMPV4Descriptor->numOfBindings, params->p_AutoResEchoIpv4Info->tableSize);
+
+ for (i = 0; i < params->p_AutoResEchoIpv4Info->tableSize; i++)
+ {
+ WRITE_UINT32(icmpv4_bindings[i].ipv4Addr, arp_entry[i].ipAddress);
+ if (arp_entry[i].isVlan)
+ WRITE_UINT16(icmpv4_bindings[i].vlanId, arp_entry[i].vid & 0xFFF);
+ }
+ WRITE_UINT32(ICMPV4Descriptor->p_Bindings, PTR_TO_UINT(icmpv4_bindings) - fmMuramVirtBaseAddr);
+ }
+ WRITE_UINT32(ICMPV4Descriptor->p_Statistics, PTR_TO_UINT(icmpv4_bindings) +
+ sizeof(t_DsarIcmpV4BindingEntry) * params->p_AutoResEchoIpv4Info->tableSize - fmMuramVirtBaseAddr);
+ }
+
+ // ICMPV6
+ if (params->p_AutoResEchoIpv6Info)
+ {
+ t_DsarIcmpV6BindingEntry* icmpv6_bindings;
+ ICMPV6Descriptor = (t_DsarIcmpV6Descriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->icmpv6);
+ WRITE_UINT32(ArCommonDescPtr->p_IcmpV6Descriptor, PTR_TO_UINT(ICMPV6Descriptor) - fmMuramVirtBaseAddr);
+ icmpv6_bindings = (t_DsarIcmpV6BindingEntry*)(PTR_TO_UINT(ICMPV6Descriptor) + sizeof(t_DsarIcmpV6Descriptor));
+ WRITE_UINT16(ICMPV6Descriptor->control, 0);
+ if (params->p_AutoResEchoIpv6Info->tableSize)
+ {
+ t_FmPortDsarNdpEntry* ndp_entry = params->p_AutoResEchoIpv6Info->p_AutoResTable;
+ WRITE_UINT16(*(uint16_t*)&ArCommonDescPtr->macStationAddr[0], *(uint16_t*)&ndp_entry[0].mac[0]);
+ WRITE_UINT32(*(uint32_t*)&ArCommonDescPtr->macStationAddr[2], *(uint32_t*)&ndp_entry[0].mac[2]);
+ WRITE_UINT16(ICMPV6Descriptor->numOfBindings, params->p_AutoResEchoIpv6Info->tableSize);
+
+ for (i = 0; i < params->p_AutoResEchoIpv6Info->tableSize; i++)
+ {
+ for (j = 0; j < 4; j++)
+ WRITE_UINT32(icmpv6_bindings[i].ipv6Addr[j], ndp_entry[i].ipAddress[j]);
+ if (ndp_entry[i].isVlan)
+ WRITE_UINT16(*(uint16_t*)&icmpv6_bindings[i].ipv6Addr[4], ndp_entry[i].vid & 0xFFF); // writing vlan
+ }
+ WRITE_UINT32(ICMPV6Descriptor->p_Bindings, PTR_TO_UINT(icmpv6_bindings) - fmMuramVirtBaseAddr);
+ }
+ WRITE_UINT32(ICMPV6Descriptor->p_Statistics, PTR_TO_UINT(icmpv6_bindings) +
+ sizeof(t_DsarIcmpV6BindingEntry) * params->p_AutoResEchoIpv6Info->tableSize - fmMuramVirtBaseAddr);
+ }
+
+ // ND
+ if (params->p_AutoResNdpInfo)
+ {
+ t_DsarIcmpV6BindingEntry* icmpv6_bindings;
+ NDDescriptor = (t_DsarNdDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->nd);
+ WRITE_UINT32(ArCommonDescPtr->p_NdDescriptor, PTR_TO_UINT(NDDescriptor) - fmMuramVirtBaseAddr);
+ icmpv6_bindings = (t_DsarIcmpV6BindingEntry*)(PTR_TO_UINT(NDDescriptor) + sizeof(t_DsarNdDescriptor));
+ WRITE_UINT16(NDDescriptor->control, 0);
+ if (params->p_AutoResNdpInfo->tableSizeAssigned + params->p_AutoResNdpInfo->tableSizeTmp)
+ {
+ t_FmPortDsarNdpEntry* ndp_entry = params->p_AutoResNdpInfo->p_AutoResTableAssigned;
+ WRITE_UINT16(*(uint16_t*)&ArCommonDescPtr->macStationAddr[0], *(uint16_t*)&ndp_entry[0].mac[0]);
+ WRITE_UINT32(*(uint32_t*)&ArCommonDescPtr->macStationAddr[2], *(uint32_t*)&ndp_entry[0].mac[2]);
+ WRITE_UINT16(NDDescriptor->numOfBindings, params->p_AutoResNdpInfo->tableSizeAssigned
+ + params->p_AutoResNdpInfo->tableSizeTmp);
+
+ for (i = 0; i < params->p_AutoResNdpInfo->tableSizeAssigned; i++)
+ {
+ for (j = 0; j < 4; j++)
+ WRITE_UINT32(icmpv6_bindings[i].ipv6Addr[j], ndp_entry[i].ipAddress[j]);
+ if (ndp_entry[i].isVlan)
+ WRITE_UINT16(*(uint16_t*)&icmpv6_bindings[i].ipv6Addr[4], ndp_entry[i].vid & 0xFFF); // writing vlan
+ }
+ ndp_entry = params->p_AutoResNdpInfo->p_AutoResTableTmp;
+ for (i = 0; i < params->p_AutoResNdpInfo->tableSizeTmp; i++)
+ {
+ for (j = 0; j < 4; j++)
+ WRITE_UINT32(icmpv6_bindings[i + params->p_AutoResNdpInfo->tableSizeAssigned].ipv6Addr[j], ndp_entry[i].ipAddress[j]);
+ if (ndp_entry[i].isVlan)
+ WRITE_UINT16(*(uint16_t*)&icmpv6_bindings[i + params->p_AutoResNdpInfo->tableSizeAssigned].ipv6Addr[4], ndp_entry[i].vid & 0xFFF); // writing vlan
+ }
+ WRITE_UINT32(NDDescriptor->p_Bindings, PTR_TO_UINT(icmpv6_bindings) - fmMuramVirtBaseAddr);
+ }
+ WRITE_UINT32(NDDescriptor->p_Statistics, PTR_TO_UINT(icmpv6_bindings) + sizeof(t_DsarIcmpV6BindingEntry)
+ * (params->p_AutoResNdpInfo->tableSizeAssigned + params->p_AutoResNdpInfo->tableSizeTmp)
+ - fmMuramVirtBaseAddr);
+ WRITE_UINT32(NDDescriptor->solicitedAddr, 0xFFFFFFFF);
+ }
+
+ // SNMP
+ if (params->p_AutoResSnmpInfo)
+ {
+ t_FmPortDsarSnmpInfo *snmpSrc = params->p_AutoResSnmpInfo;
+ t_DsarSnmpIpv4AddrTblEntry* snmpIpv4Addr;
+ t_DsarSnmpIpv6AddrTblEntry* snmpIpv6Addr;
+ t_OidsTblEntry* snmpOid;
+ uint8_t *charPointer;
+ int len;
+ t_DsarSnmpDescriptor* SnmpDescriptor = (t_DsarSnmpDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->snmp);
+ WRITE_UINT32(ArCommonDescPtr->p_SnmpDescriptor, PTR_TO_UINT(SnmpDescriptor) - fmMuramVirtBaseAddr);
+ WRITE_UINT16(SnmpDescriptor->control, snmpSrc->control);
+ WRITE_UINT16(SnmpDescriptor->maxSnmpMsgLength, snmpSrc->maxSnmpMsgLength);
+ snmpIpv4Addr = (t_DsarSnmpIpv4AddrTblEntry*)(PTR_TO_UINT(SnmpDescriptor) + sizeof(t_DsarSnmpDescriptor));
+ if (snmpSrc->numOfIpv4Addresses)
+ {
+ t_FmPortDsarSnmpIpv4AddrTblEntry* snmpIpv4AddrSrc = snmpSrc->p_Ipv4AddrTbl;
+ WRITE_UINT16(SnmpDescriptor->numOfIpv4Addresses, snmpSrc->numOfIpv4Addresses);
+ for (i = 0; i < snmpSrc->numOfIpv4Addresses; i++)
+ {
+ WRITE_UINT32(snmpIpv4Addr[i].ipv4Addr, snmpIpv4AddrSrc[i].ipv4Addr);
+ if (snmpIpv4AddrSrc[i].isVlan)
+ WRITE_UINT16(snmpIpv4Addr[i].vlanId, snmpIpv4AddrSrc[i].vid & 0xFFF);
+ }
+ WRITE_UINT32(SnmpDescriptor->p_Ipv4AddrTbl, PTR_TO_UINT(snmpIpv4Addr) - fmMuramVirtBaseAddr);
+ }
+ snmpIpv6Addr = (t_DsarSnmpIpv6AddrTblEntry*)(PTR_TO_UINT(snmpIpv4Addr)
+ + sizeof(t_DsarSnmpIpv4AddrTblEntry) * snmpSrc->numOfIpv4Addresses);
+ if (snmpSrc->numOfIpv6Addresses)
+ {
+ t_FmPortDsarSnmpIpv6AddrTblEntry* snmpIpv6AddrSrc = snmpSrc->p_Ipv6AddrTbl;
+ WRITE_UINT16(SnmpDescriptor->numOfIpv6Addresses, snmpSrc->numOfIpv6Addresses);
+ for (i = 0; i < snmpSrc->numOfIpv6Addresses; i++)
+ {
+ for (j = 0; j < 4; j++)
+ WRITE_UINT32(snmpIpv6Addr[i].ipv6Addr[j], snmpIpv6AddrSrc[i].ipv6Addr[j]);
+ if (snmpIpv6AddrSrc[i].isVlan)
+ WRITE_UINT16(snmpIpv6Addr[i].vlanId, snmpIpv6AddrSrc[i].vid & 0xFFF);
+ }
+ WRITE_UINT32(SnmpDescriptor->p_Ipv6AddrTbl, PTR_TO_UINT(snmpIpv6Addr) - fmMuramVirtBaseAddr);
+ }
+ snmpOid = (t_OidsTblEntry*)(PTR_TO_UINT(snmpIpv6Addr)
+ + sizeof(t_DsarSnmpIpv6AddrTblEntry) * snmpSrc->numOfIpv6Addresses);
+ charPointer = (uint8_t*)(PTR_TO_UINT(snmpOid)
+ + sizeof(t_OidsTblEntry) * snmpSrc->oidsTblSize);
+ len = TOTAL_BER_LEN(GetBERLen(&snmpSrc->p_RdOnlyCommunityStr[1]));
+ Mem2IOCpy32(charPointer, snmpSrc->p_RdOnlyCommunityStr, len);
+ WRITE_UINT32(SnmpDescriptor->p_RdOnlyCommunityStr, PTR_TO_UINT(charPointer) - fmMuramVirtBaseAddr);
+ charPointer += len;
+ len = TOTAL_BER_LEN(GetBERLen(&snmpSrc->p_RdWrCommunityStr[1]));
+ Mem2IOCpy32(charPointer, snmpSrc->p_RdWrCommunityStr, len);
+ WRITE_UINT32(SnmpDescriptor->p_RdWrCommunityStr, PTR_TO_UINT(charPointer) - fmMuramVirtBaseAddr);
+ charPointer += len;
+ WRITE_UINT32(SnmpDescriptor->oidsTblSize, snmpSrc->oidsTblSize);
+ WRITE_UINT32(SnmpDescriptor->p_OidsTbl, PTR_TO_UINT(snmpOid) - fmMuramVirtBaseAddr);
+ for (i = 0; i < snmpSrc->oidsTblSize; i++)
+ {
+ WRITE_UINT16(snmpOid->oidSize, snmpSrc->p_OidsTbl[i].oidSize);
+ WRITE_UINT16(snmpOid->resSize, snmpSrc->p_OidsTbl[i].resSize);
+ Mem2IOCpy32(charPointer, snmpSrc->p_OidsTbl[i].p_Oid, snmpSrc->p_OidsTbl[i].oidSize);
+ WRITE_UINT32(snmpOid->p_Oid, PTR_TO_UINT(charPointer) - fmMuramVirtBaseAddr);
+ charPointer += snmpSrc->p_OidsTbl[i].oidSize;
+ if (snmpSrc->p_OidsTbl[i].resSize <= 4)
+ WRITE_UINT32(snmpOid->resValOrPtr, snmpSrc->p_OidsTbl[i].resValOrPtr);
+ else
+ {
+ Mem2IOCpy32(charPointer, UINT_TO_PTR(snmpSrc->p_OidsTbl[i].resValOrPtr), snmpSrc->p_OidsTbl[i].resSize);
+ WRITE_UINT32(snmpOid->resValOrPtr, PTR_TO_UINT(charPointer) - fmMuramVirtBaseAddr);
+ charPointer += snmpSrc->p_OidsTbl[i].resSize;
+ }
+ snmpOid++;
+ }
+ charPointer = UINT_TO_PTR(ROUND_UP(PTR_TO_UINT(charPointer),4));
+ WRITE_UINT32(SnmpDescriptor->p_Statistics, PTR_TO_UINT(charPointer) - fmMuramVirtBaseAddr);
+ }
+
+ // filtering
+ if (params->p_AutoResFilteringInfo)
+ {
+ if (params->p_AutoResFilteringInfo->ipProtDropOnHit)
+ tmp |= IP_PROT_TBL_PASS_MASK;
+ if (params->p_AutoResFilteringInfo->udpPortDropOnHit)
+ tmp |= UDP_PORT_TBL_PASS_MASK;
+ if (params->p_AutoResFilteringInfo->tcpPortDropOnHit)
+ tmp |= TCP_PORT_TBL_PASS_MASK;
+ WRITE_UINT8(ArCommonDescPtr->filterControl, tmp);
+
+ // ip filtering
+ if (params->p_AutoResFilteringInfo->ipProtTableSize)
+ {
+ uint8_t* ip_tbl = (uint8_t*)(PTR_TO_UINT(ArCommonDescPtr) + of->filtIp);
+ WRITE_UINT8(ArCommonDescPtr->ipProtocolTblSize, params->p_AutoResFilteringInfo->ipProtTableSize);
+ for (i = 0; i < params->p_AutoResFilteringInfo->ipProtTableSize; i++)
+ WRITE_UINT8(ip_tbl[i], params->p_AutoResFilteringInfo->p_IpProtTablePtr[i]);
+ WRITE_UINT32(ArCommonDescPtr->p_IpProtocolFiltTbl, PTR_TO_UINT(ip_tbl) - fmMuramVirtBaseAddr);
+ }
+
+ // udp filtering
+ if (params->p_AutoResFilteringInfo->udpPortsTableSize)
+ {
+ t_PortTblEntry* udp_tbl = (t_PortTblEntry*)(PTR_TO_UINT(ArCommonDescPtr) + of->filtUdp);
+ WRITE_UINT8(ArCommonDescPtr->udpPortTblSize, params->p_AutoResFilteringInfo->udpPortsTableSize);
+ for (i = 0; i < params->p_AutoResFilteringInfo->udpPortsTableSize; i++)
+ {
+ WRITE_UINT32(udp_tbl[i].Ports,
+ (params->p_AutoResFilteringInfo->p_UdpPortsTablePtr[i].srcPort << 16) +
+ params->p_AutoResFilteringInfo->p_UdpPortsTablePtr[i].dstPort);
+ WRITE_UINT32(udp_tbl[i].PortsMask,
+ (params->p_AutoResFilteringInfo->p_UdpPortsTablePtr[i].srcPortMask << 16) +
+ params->p_AutoResFilteringInfo->p_UdpPortsTablePtr[i].dstPortMask);
+ }
+ WRITE_UINT32(ArCommonDescPtr->p_UdpPortFiltTbl, PTR_TO_UINT(udp_tbl) - fmMuramVirtBaseAddr);
+ }
+
+ // tcp filtering
+ if (params->p_AutoResFilteringInfo->tcpPortsTableSize)
+ {
+ t_PortTblEntry* tcp_tbl = (t_PortTblEntry*)(PTR_TO_UINT(ArCommonDescPtr) + of->filtTcp);
+ WRITE_UINT8(ArCommonDescPtr->tcpPortTblSize, params->p_AutoResFilteringInfo->tcpPortsTableSize);
+ for (i = 0; i < params->p_AutoResFilteringInfo->tcpPortsTableSize; i++)
+ {
+ WRITE_UINT32(tcp_tbl[i].Ports,
+ (params->p_AutoResFilteringInfo->p_TcpPortsTablePtr[i].srcPort << 16) +
+ params->p_AutoResFilteringInfo->p_TcpPortsTablePtr[i].dstPort);
+ WRITE_UINT32(tcp_tbl[i].PortsMask,
+ (params->p_AutoResFilteringInfo->p_TcpPortsTablePtr[i].srcPortMask << 16) +
+ params->p_AutoResFilteringInfo->p_TcpPortsTablePtr[i].dstPortMask);
+ }
+ WRITE_UINT32(ArCommonDescPtr->p_TcpPortFiltTbl, PTR_TO_UINT(tcp_tbl) - fmMuramVirtBaseAddr);
+ }
+ }
+ // common stats
+ WRITE_UINT32(ArCommonDescPtr->p_ArStats, PTR_TO_UINT(ArCommonDescPtr) + of->stats - fmMuramVirtBaseAddr);
+
+ // get into Deep Sleep sequence:
+ // Stage 6: configure tx port to im
+ p_FmPort->deepSleepVars.fmbm_tcfg = GET_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg);
+ WRITE_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg, GET_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg) | BMI_PORT_CFG_IM);
+ // ????
+ p_FmPort->deepSleepVars.fmbm_tcmne = GET_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcmne);
+ WRITE_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcmne, 0xE);
+ // Stage 7:echo
+ p_FmPort->deepSleepVars.fmbm_rfne = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne);
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne, 0x440000);
+ p_FmPort->deepSleepVars.fmbm_rfpne = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne);
+ h_FmPcd = FmGetPcd(p_FmPort->h_Fm);
+ if (!PrsIsEnabled(h_FmPcd))
+ {
+ p_FmPort->deepSleepVars.dsarEnabledParser = TRUE;
+ PrsEnable(h_FmPcd);
+ }
+ else
+ p_FmPort->deepSleepVars.dsarEnabledParser = FALSE;
+
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne, 0x2E);
+ // Stage 8: We don't support magic packet for now.
+ // Stage 9: Accumulate mode
+ p_FmPort->deepSleepVars.fmbm_rcfg = GET_UINT32(p_FmPort->port.bmi_regs->rx.fmbm_rcfg);
+ WRITE_UINT32(p_FmPort->port.bmi_regs->rx.fmbm_rcfg, p_FmPort->deepSleepVars.fmbm_rcfg | BMI_PORT_CFG_AM);
+ FmGetSetParams(p_FmPort->h_Fm, &fmGetSetParams);
+
+ ARDesc = UINT_TO_PTR(XX_VirtToPhys(ArCommonDescPtr));
+ return E_OK;
+}
+
+void FM_PORT_Dsar_DumpRegs()
+{
+ uint32_t* hh = XX_PhysToVirt(PTR_TO_UINT(ARDesc));
+ DUMP_MEMORY(hh, 0x180);
+}
+
+void FM_PORT_ExitDsar(t_Handle h_FmPortRx, t_Handle h_FmPortTx)
+{
+ t_FmPort *p_FmPort = (t_FmPort *)h_FmPortRx;
+ t_FmPort *p_FmPortTx = (t_FmPort *)h_FmPortTx;
+ t_FmGetSetParams fmGetSetParams;
+ memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams));
+ fmGetSetParams.setParams.type = UPDATE_FPM_BRKC_SLP;
+ fmGetSetParams.setParams.sleep = 0;
+ if (p_FmPort->deepSleepVars.autoResOffsets)
+ {
+ XX_Free(p_FmPort->deepSleepVars.autoResOffsets);
+ p_FmPort->deepSleepVars.autoResOffsets = 0;
+ }
+ if (p_FmPort->deepSleepVars.autoResMaxSizes)
+ {
+ XX_Free(p_FmPort->deepSleepVars.autoResMaxSizes);
+ p_FmPort->deepSleepVars.autoResMaxSizes = 0;
+ }
+
+ if (p_FmPort->deepSleepVars.dsarEnabledParser)
+ PrsDisable(FmGetPcd(p_FmPort->h_Fm));
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne, p_FmPort->deepSleepVars.fmbm_rfpne);
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne, p_FmPort->deepSleepVars.fmbm_rfne);
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rcfg, p_FmPort->deepSleepVars.fmbm_rcfg);
+ FmGetSetParams(p_FmPort->h_Fm, &fmGetSetParams);
+ WRITE_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcmne, p_FmPort->deepSleepVars.fmbm_tcmne);
+ WRITE_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg, p_FmPort->deepSleepVars.fmbm_tcfg);
+}
+
+bool FM_PORT_IsInDsar(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort *)h_FmPort;
+ return PTR_TO_UINT(p_FmPort->deepSleepVars.autoResOffsets);
+}
+
+t_Error FM_PORT_GetDsarStats(t_Handle h_FmPortRx, t_FmPortDsarStats *stats)
+{
+ t_FmPort *p_FmPort = (t_FmPort *)h_FmPortRx;
+ struct arOffsets *of = (struct arOffsets*)p_FmPort->deepSleepVars.autoResOffsets;
+ uint8_t* fmMuramVirtBaseAddr = XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr);
+ uint32_t *param_page = XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr + GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr));
+ t_ArCommonDesc *ArCommonDescPtr = (t_ArCommonDesc*)(XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr + GET_UINT32(*param_page)));
+ t_DsarArpDescriptor *ArpDescriptor = (t_DsarArpDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->arp);
+ t_DsarArpStatistics* arp_stats = (t_DsarArpStatistics*)(PTR_TO_UINT(ArpDescriptor->p_Statistics) + fmMuramVirtBaseAddr);
+ t_DsarIcmpV4Descriptor* ICMPV4Descriptor = (t_DsarIcmpV4Descriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->icmpv4);
+ t_DsarIcmpV4Statistics* icmpv4_stats = (t_DsarIcmpV4Statistics*)(PTR_TO_UINT(ICMPV4Descriptor->p_Statistics) + fmMuramVirtBaseAddr);
+ t_DsarNdDescriptor* NDDescriptor = (t_DsarNdDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->nd);
+ t_NdStatistics* nd_stats = (t_NdStatistics*)(PTR_TO_UINT(NDDescriptor->p_Statistics) + fmMuramVirtBaseAddr);
+ t_DsarIcmpV6Descriptor* ICMPV6Descriptor = (t_DsarIcmpV6Descriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->icmpv6);
+ t_DsarIcmpV6Statistics* icmpv6_stats = (t_DsarIcmpV6Statistics*)(PTR_TO_UINT(ICMPV6Descriptor->p_Statistics) + fmMuramVirtBaseAddr);
+ t_DsarSnmpDescriptor* SnmpDescriptor = (t_DsarSnmpDescriptor*)(PTR_TO_UINT(ArCommonDescPtr) + of->snmp);
+ t_DsarSnmpStatistics* snmp_stats = (t_DsarSnmpStatistics*)(PTR_TO_UINT(SnmpDescriptor->p_Statistics) + fmMuramVirtBaseAddr);
+ stats->arpArCnt = arp_stats->arCnt;
+ stats->echoIcmpv4ArCnt = icmpv4_stats->arCnt;
+ stats->ndpArCnt = nd_stats->arCnt;
+ stats->echoIcmpv6ArCnt = icmpv6_stats->arCnt;
+ stats->snmpGetCnt = snmp_stats->snmpGetReqCnt;
+ stats->snmpGetNextCnt = snmp_stats->snmpGetNextReqCnt;
+ return E_OK;
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.h
new file mode 100644
index 0000000..75f117f
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.h
@@ -0,0 +1,987 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_port.h
+
+ @Description FM Port internal structures and definitions.
+*//***************************************************************************/
+#ifndef __FM_PORT_H
+#define __FM_PORT_H
+
+#include "error_ext.h"
+#include "std_ext.h"
+#include "fm_port_ext.h"
+
+#include "fm_common.h"
+#include "fm_sp_common.h"
+#include "fsl_fman_sp.h"
+#include "fm_port_ext.h"
+#include "fsl_fman_port.h"
+
+#define __ERR_MODULE__ MODULE_FM_PORT
+
+
+#define MIN_EXT_BUF_SIZE 64
+#define DATA_ALIGNMENT 64
+#define MAX_LIODN_OFFSET 64
+#define MAX_PORT_FIFO_SIZE MIN(BMI_MAX_FIFO_SIZE, 1024*BMI_FIFO_UNITS)
+
+/**************************************************************************//**
+ @Description Memory Map defines
+*//***************************************************************************/
+#define BMI_PORT_REGS_OFFSET 0
+#define QMI_PORT_REGS_OFFSET 0x400
+#define PRS_PORT_REGS_OFFSET 0x800
+
+/**************************************************************************//**
+ @Description defaults
+*//***************************************************************************/
+#define DEFAULT_PORT_deqHighPriority_1G FALSE
+#define DEFAULT_PORT_deqHighPriority_10G TRUE
+#define DEFAULT_PORT_deqType e_FM_PORT_DEQ_TYPE1
+#define DEFAULT_PORT_deqPrefetchOption e_FM_PORT_DEQ_FULL_PREFETCH
+#define DEFAULT_PORT_deqPrefetchOption_HC e_FM_PORT_DEQ_NO_PREFETCH
+#define DEFAULT_PORT_deqByteCnt_10G 0x1400
+#define DEFAULT_PORT_deqByteCnt_1G 0x400
+#define DEFAULT_PORT_bufferPrefixContent_privDataSize DEFAULT_FM_SP_bufferPrefixContent_privDataSize
+#define DEFAULT_PORT_bufferPrefixContent_passPrsResult DEFAULT_FM_SP_bufferPrefixContent_passPrsResult
+#define DEFAULT_PORT_bufferPrefixContent_passTimeStamp DEFAULT_FM_SP_bufferPrefixContent_passTimeStamp
+#define DEFAULT_PORT_bufferPrefixContent_allOtherPCDInfo DEFAULT_FM_SP_bufferPrefixContent_allOtherPCDInfo
+#define DEFAULT_PORT_bufferPrefixContent_dataAlign DEFAULT_FM_SP_bufferPrefixContent_dataAlign
+#define DEFAULT_PORT_cheksumLastBytesIgnore 0
+#define DEFAULT_PORT_cutBytesFromEnd 4
+#define DEFAULT_PORT_fifoDeqPipelineDepth_IM 2
+
+#define DEFAULT_PORT_frmDiscardOverride FALSE
+
+#define DEFAULT_PORT_dmaSwapData (e_FmDmaSwapOption)DEFAULT_FMAN_SP_DMA_SWAP_DATA
+#define DEFAULT_PORT_dmaIntContextCacheAttr (e_FmDmaCacheOption)DEFAULT_FMAN_SP_DMA_INT_CONTEXT_CACHE_ATTR
+#define DEFAULT_PORT_dmaHeaderCacheAttr (e_FmDmaCacheOption)DEFAULT_FMAN_SP_DMA_HEADER_CACHE_ATTR
+#define DEFAULT_PORT_dmaScatterGatherCacheAttr (e_FmDmaCacheOption)DEFAULT_FMAN_SP_DMA_SCATTER_GATHER_CACHE_ATTR
+#define DEFAULT_PORT_dmaWriteOptimize DEFAULT_FMAN_SP_DMA_WRITE_OPTIMIZE
+
+#define DEFAULT_PORT_noScatherGather DEFAULT_FMAN_SP_NO_SCATTER_GATHER
+#define DEFAULT_PORT_forwardIntContextReuse FALSE
+#define DEFAULT_PORT_BufMargins_startMargins 32
+#define DEFAULT_PORT_BufMargins_endMargins 0
+#define DEFAULT_PORT_syncReq TRUE
+#define DEFAULT_PORT_syncReqForHc FALSE
+#define DEFAULT_PORT_color e_FM_PORT_COLOR_GREEN
+#define DEFAULT_PORT_errorsToDiscard FM_PORT_FRM_ERR_CLS_DISCARD
+/* #define DEFAULT_PORT_dualRateLimitScaleDown e_FM_PORT_DUAL_RATE_LIMITER_NONE */
+/* #define DEFAULT_PORT_rateLimitBurstSizeHighGranularity FALSE */
+#define DEFAULT_PORT_exception IM_EV_BSY
+#define DEFAULT_PORT_maxFrameLength 9600
+
+#define DEFAULT_notSupported 0xff
+
+#if (DPAA_VERSION < 11)
+#define DEFAULT_PORT_rxFifoPriElevationLevel MAX_PORT_FIFO_SIZE
+#define DEFAULT_PORT_rxFifoThreshold (MAX_PORT_FIFO_SIZE*3/4)
+
+#define DEFAULT_PORT_txFifoMinFillLevel 0
+#define DEFAULT_PORT_txFifoLowComfLevel (5*KILOBYTE)
+#define DEFAULT_PORT_fifoDeqPipelineDepth_1G 1
+#define DEFAULT_PORT_fifoDeqPipelineDepth_10G 4
+
+#define DEFAULT_PORT_fifoDeqPipelineDepth_OH 2
+
+/* Host command port MUST NOT be changed to more than 1 !!! */
+#define DEFAULT_PORT_numOfTasks(type) \
+ (uint32_t)((((type) == e_FM_PORT_TYPE_RX_10G) || \
+ ((type) == e_FM_PORT_TYPE_TX_10G)) ? 16 : \
+ ((((type) == e_FM_PORT_TYPE_RX) || \
+ ((type) == e_FM_PORT_TYPE_TX) || \
+ ((type) == e_FM_PORT_TYPE_OH_OFFLINE_PARSING)) ? 3 : 1))
+
+#define DEFAULT_PORT_extraNumOfTasks(type) \
+ (uint32_t)(((type) == e_FM_PORT_TYPE_RX_10G) ? 8 : \
+ (((type) == e_FM_PORT_TYPE_RX) ? 2 : 0))
+
+#define DEFAULT_PORT_numOfOpenDmas(type) \
+ (uint32_t)((((type) == e_FM_PORT_TYPE_TX_10G) || \
+ ((type) == e_FM_PORT_TYPE_RX_10G)) ? 8 : 1 )
+
+#define DEFAULT_PORT_extraNumOfOpenDmas(type) \
+ (uint32_t)(((type) == e_FM_PORT_TYPE_RX_10G) ? 8 : \
+ (((type) == e_FM_PORT_TYPE_RX) ? 1 : 0))
+
+#define DEFAULT_PORT_numOfFifoBufs(type) \
+ (uint32_t)((((type) == e_FM_PORT_TYPE_RX_10G) || \
+ ((type) == e_FM_PORT_TYPE_TX_10G)) ? 48 : \
+ ((type) == e_FM_PORT_TYPE_RX) ? 45 : \
+ ((type) == e_FM_PORT_TYPE_TX) ? 44 : 8)
+
+#define DEFAULT_PORT_extraNumOfFifoBufs 0
+
+#else /* (DPAA_VERSION < 11) */
+/* Defaults are registers' reset values */
+#define DEFAULT_PORT_rxFifoPriElevationLevel MAX_PORT_FIFO_SIZE
+#define DEFAULT_PORT_rxFifoThreshold MAX_PORT_FIFO_SIZE
+
+#define DEFAULT_PORT_txFifoMinFillLevel 0
+#define DEFAULT_PORT_txFifoLowComfLevel (5 * KILOBYTE)
+#define DEFAULT_PORT_fifoDeqPipelineDepth_1G 2
+#define DEFAULT_PORT_fifoDeqPipelineDepth_10G 4
+
+#define DEFAULT_PORT_fifoDeqPipelineDepth_OH 2
+
+#define DEFAULT_PORT_numOfTasks(type) \
+ (uint32_t)((((type) == e_FM_PORT_TYPE_RX_10G) || \
+ ((type) == e_FM_PORT_TYPE_TX_10G)) ? 14 : \
+ (((type) == e_FM_PORT_TYPE_RX) || \
+ ((type) == e_FM_PORT_TYPE_TX)) ? 4 : \
+ ((type) == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) ? 6 : 1)
+
+#define DEFAULT_PORT_extraNumOfTasks(type) 0
+
+#define DEFAULT_PORT_numOfOpenDmas(type) \
+ (uint32_t)(((type) == e_FM_PORT_TYPE_RX_10G) ? 8 : \
+ ((type) == e_FM_PORT_TYPE_TX_10G) ? 12 : \
+ ((type) == e_FM_PORT_TYPE_RX) ? 2 : \
+ ((type) == e_FM_PORT_TYPE_TX) ? 3 : \
+ ((type) == e_FM_PORT_TYPE_OH_HOST_COMMAND) ? 2 : 4)
+
+#define DEFAULT_PORT_extraNumOfOpenDmas(type) 0
+
+#define DEFAULT_PORT_numOfFifoBufs(type) \
+ (uint32_t) (((type) == e_FM_PORT_TYPE_RX_10G) ? 96 : \
+ ((type) == e_FM_PORT_TYPE_TX_10G) ? 64 : \
+ ((type) == e_FM_PORT_TYPE_OH_HOST_COMMAND) ? 10 : 50)
+
+#define DEFAULT_PORT_extraNumOfFifoBufs 0
+
+#endif /* (DPAA_VERSION < 11) */
+
+#define DEFAULT_PORT_txBdRingLength 16
+#define DEFAULT_PORT_rxBdRingLength 128
+#define DEFAULT_PORT_ImfwExtStructsMemId 0
+#define DEFAULT_PORT_ImfwExtStructsMemAttr MEMORY_ATTR_CACHEABLE
+
+#define FM_PORT_CG_REG_NUM(_cgId) (((FM_PORT_NUM_OF_CONGESTION_GRPS/32)-1)-_cgId/32)
+
+/**************************************************************************//**
+ @Collection PCD Engines
+*//***************************************************************************/
+typedef uint32_t fmPcdEngines_t; /**< options as defined below: */
+
+#define FM_PCD_NONE 0 /**< No PCD Engine indicated */
+#define FM_PCD_PRS 0x80000000 /**< Parser indicated */
+#define FM_PCD_KG 0x40000000 /**< Keygen indicated */
+#define FM_PCD_CC 0x20000000 /**< Coarse classification indicated */
+#define FM_PCD_PLCR 0x10000000 /**< Policer indicated */
+#define FM_PCD_MANIP 0x08000000 /**< Manipulation indicated */
+/* @} */
+
+#define FM_PORT_MAX_NUM_OF_EXT_POOLS_ALL_INTEGRATIONS 8
+#define FM_PORT_MAX_NUM_OF_CONGESTION_GRPS_ALL_INTEGRATIONS 256
+#define FM_PORT_CG_REG_NUM(_cgId) (((FM_PORT_NUM_OF_CONGESTION_GRPS/32)-1)-_cgId/32)
+
+#define FM_OH_PORT_ID 0
+
+/***********************************************************************/
+/* SW parser IP-fragmentation labels (offsets) */
+/***********************************************************************/
+#if (DPAA_VERSION == 10)
+#define IP_FRAG_SW_PATCH_IPv4_SIZE 0x025
+#define IP_FRAG_SW_PATCH_IPv4_LABEL 0x300
+#else
+#define IP_FRAG_SW_PATCH_IPv4_SIZE 0x046
+#define IP_FRAG_SW_PATCH_IPv4_LABEL 0x2E0
+#endif /* (DPAA_VERSION == 10) */
+#define IP_FRAG_SW_PATCH_IPv6_LABEL \
+ (IP_FRAG_SW_PATCH_IPv4_LABEL + IP_FRAG_SW_PATCH_IPv4_SIZE)
+
+#ifdef FM_CAPWAP_SUPPORT
+#define UDP_LITE_SW_PATCH_LABEL 0x2E0
+#endif /* FM_CAPWAP_SUPPORT */
+
+/**************************************************************************//**
+ @Description Memory Mapped Registers
+*//***************************************************************************/
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+typedef _Packed struct
+{
+ volatile uint32_t fmbm_rcfg; /**< Rx Configuration */
+ volatile uint32_t fmbm_rst; /**< Rx Status */
+ volatile uint32_t fmbm_rda; /**< Rx DMA attributes*/
+ volatile uint32_t fmbm_rfp; /**< Rx FIFO Parameters*/
+ volatile uint32_t fmbm_rfed; /**< Rx Frame End Data*/
+ volatile uint32_t fmbm_ricp; /**< Rx Internal Context Parameters*/
+ volatile uint32_t fmbm_rim; /**< Rx Internal Buffer Margins*/
+ volatile uint32_t fmbm_rebm; /**< Rx External Buffer Margins*/
+ volatile uint32_t fmbm_rfne; /**< Rx Frame Next Engine*/
+ volatile uint32_t fmbm_rfca; /**< Rx Frame Command Attributes.*/
+ volatile uint32_t fmbm_rfpne; /**< Rx Frame Parser Next Engine*/
+ volatile uint32_t fmbm_rpso; /**< Rx Parse Start Offset*/
+ volatile uint32_t fmbm_rpp; /**< Rx Policer Profile */
+ volatile uint32_t fmbm_rccb; /**< Rx Coarse Classification Base */
+ volatile uint32_t fmbm_reth; /**< Rx Excessive Threshold */
+ volatile uint32_t reserved1[0x01];/**< (0x03C) */
+ volatile uint32_t fmbm_rprai[FM_PORT_PRS_RESULT_NUM_OF_WORDS];
+ /**< Rx Parse Results Array Initialization*/
+ volatile uint32_t fmbm_rfqid; /**< Rx Frame Queue ID*/
+ volatile uint32_t fmbm_refqid; /**< Rx Error Frame Queue ID*/
+ volatile uint32_t fmbm_rfsdm; /**< Rx Frame Status Discard Mask*/
+ volatile uint32_t fmbm_rfsem; /**< Rx Frame Status Error Mask*/
+ volatile uint32_t fmbm_rfene; /**< Rx Frame Enqueue Next Engine */
+ volatile uint32_t reserved2[0x02];/**< (0x074-0x078) */
+ volatile uint32_t fmbm_rcmne; /**< Rx Frame Continuous Mode Next Engine */
+ volatile uint32_t reserved3[0x20];/**< (0x080 0x0FF) */
+ volatile uint32_t fmbm_ebmpi[FM_PORT_MAX_NUM_OF_EXT_POOLS_ALL_INTEGRATIONS];
+ /**< Buffer Manager pool Information-*/
+ volatile uint32_t fmbm_acnt[FM_PORT_MAX_NUM_OF_EXT_POOLS_ALL_INTEGRATIONS];
+ /**< Allocate Counter-*/
+ volatile uint32_t reserved4[0x08];
+ /**< 0x130/0x140 - 0x15F reserved -*/
+ volatile uint32_t fmbm_rcgm[FM_PORT_MAX_NUM_OF_CONGESTION_GRPS_ALL_INTEGRATIONS/32];
+ /**< Congestion Group Map*/
+ volatile uint32_t fmbm_rmpd; /**< BM Pool Depletion */
+ volatile uint32_t reserved5[0x1F];/**< (0x184 0x1FF) */
+ volatile uint32_t fmbm_rstc; /**< Rx Statistics Counters*/
+ volatile uint32_t fmbm_rfrc; /**< Rx Frame Counter*/
+ volatile uint32_t fmbm_rfbc; /**< Rx Bad Frames Counter*/
+ volatile uint32_t fmbm_rlfc; /**< Rx Large Frames Counter*/
+ volatile uint32_t fmbm_rffc; /**< Rx Filter Frames Counter*/
+ volatile uint32_t fmbm_rfcd; /**< Rx Frame Discard Counter*/
+ volatile uint32_t fmbm_rfldec; /**< Rx Frames List DMA Error Counter*/
+ volatile uint32_t fmbm_rodc; /**< Rx Out of Buffers Discard Counter-*/
+ volatile uint32_t fmbm_rbdc; /**< Rx Buffers Deallocate Counter-*/
+ volatile uint32_t fmbm_rpec; /**< Rx RX Prepare to enqueue Counter-*/
+ volatile uint32_t reserved6[0x16];/**< (0x228 0x27F) */
+ volatile uint32_t fmbm_rpc; /**< Rx Performance Counters*/
+ volatile uint32_t fmbm_rpcp; /**< Rx Performance Count Parameters*/
+ volatile uint32_t fmbm_rccn; /**< Rx Cycle Counter*/
+ volatile uint32_t fmbm_rtuc; /**< Rx Tasks Utilization Counter*/
+ volatile uint32_t fmbm_rrquc; /**< Rx Receive Queue Utilization Counter*/
+ volatile uint32_t fmbm_rduc; /**< Rx DMA Utilization Counter*/
+ volatile uint32_t fmbm_rfuc; /**< Rx FIFO Utilization Counter*/
+ volatile uint32_t fmbm_rpac; /**< Rx Pause Activation Counter*/
+ volatile uint32_t reserved7[0x18];/**< (0x2A0-0x2FF) */
+ volatile uint32_t fmbm_rdcfg[0x3];/**< Rx Debug-*/
+ volatile uint32_t fmbm_rgpr; /**< Rx General Purpose Register. */
+ volatile uint32_t reserved8[0x3a];/**< (0x310-0x3FF) */
+} _PackedType t_FmPortRxBmiRegs;
+
+typedef _Packed struct
+{
+ volatile uint32_t fmbm_tcfg; /**< Tx Configuration */
+ volatile uint32_t fmbm_tst; /**< Tx Status */
+ volatile uint32_t fmbm_tda; /**< Tx DMA attributes */
+ volatile uint32_t fmbm_tfp; /**< Tx FIFO Parameters */
+ volatile uint32_t fmbm_tfed; /**< Tx Frame End Data */
+ volatile uint32_t fmbm_ticp; /**< Tx Internal Context Parameters */
+ volatile uint32_t fmbm_tfdne; /**< Tx Frame Dequeue Next Engine. */
+ volatile uint32_t fmbm_tfca; /**< Tx Frame Command attribute. */
+ volatile uint32_t fmbm_tcfqid; /**< Tx Confirmation Frame Queue ID. */
+ volatile uint32_t fmbm_tfeqid; /**< Tx Frame Error Queue ID */
+ volatile uint32_t fmbm_tfene; /**< Tx Frame Enqueue Next Engine */
+ volatile uint32_t fmbm_trlmts; /**< Tx Rate Limiter Scale */
+ volatile uint32_t fmbm_trlmt; /**< Tx Rate Limiter */
+ volatile uint32_t fmbm_tccb; /**< Tx Coarse Classification Base */
+ volatile uint32_t reserved0[0x0e];/**< (0x038-0x070) */
+ volatile uint32_t fmbm_tfne; /**< Tx Frame Next Engine */
+ volatile uint32_t fmbm_tpfcm[0x02];/**< Tx Priority based Flow Control (PFC) Mapping */
+ volatile uint32_t fmbm_tcmne; /**< Tx Frame Continuous Mode Next Engine */
+ volatile uint32_t reserved2[0x60];/**< (0x080-0x200) */
+ volatile uint32_t fmbm_tstc; /**< Tx Statistics Counters */
+ volatile uint32_t fmbm_tfrc; /**< Tx Frame Counter */
+ volatile uint32_t fmbm_tfdc; /**< Tx Frames Discard Counter */
+ volatile uint32_t fmbm_tfledc; /**< Tx Frame Length error discard counter */
+ volatile uint32_t fmbm_tfufdc; /**< Tx Frame unsupported format discard Counter */
+ volatile uint32_t fmbm_tbdc; /**< Tx Buffers Deallocate Counter */
+ volatile uint32_t reserved3[0x1A];/**< (0x218-0x280) */
+ volatile uint32_t fmbm_tpc; /**< Tx Performance Counters*/
+ volatile uint32_t fmbm_tpcp; /**< Tx Performance Count Parameters*/
+ volatile uint32_t fmbm_tccn; /**< Tx Cycle Counter*/
+ volatile uint32_t fmbm_ttuc; /**< Tx Tasks Utilization Counter*/
+ volatile uint32_t fmbm_ttcquc; /**< Tx Transmit Confirm Queue Utilization Counter*/
+ volatile uint32_t fmbm_tduc; /**< Tx DMA Utilization Counter*/
+ volatile uint32_t fmbm_tfuc; /**< Tx FIFO Utilization Counter*/
+ volatile uint32_t reserved4[16]; /**< (0x29C-0x2FF) */
+ volatile uint32_t fmbm_tdcfg[0x3];/**< Tx Debug-*/
+ volatile uint32_t fmbm_tgpr; /**< O/H General Purpose Register */
+ volatile uint32_t reserved5[0x3a];/**< (0x310-0x3FF) */
+} _PackedType t_FmPortTxBmiRegs;
+
+typedef _Packed struct
+{
+ volatile uint32_t fmbm_ocfg; /**< O/H Configuration */
+ volatile uint32_t fmbm_ost; /**< O/H Status */
+ volatile uint32_t fmbm_oda; /**< O/H DMA attributes */
+ volatile uint32_t fmbm_oicp; /**< O/H Internal Context Parameters */
+ volatile uint32_t fmbm_ofdne; /**< O/H Frame Dequeue Next Engine */
+ volatile uint32_t fmbm_ofne; /**< O/H Frame Next Engine */
+ volatile uint32_t fmbm_ofca; /**< O/H Frame Command Attributes. */
+ volatile uint32_t fmbm_ofpne; /**< O/H Frame Parser Next Engine */
+ volatile uint32_t fmbm_opso; /**< O/H Parse Start Offset */
+ volatile uint32_t fmbm_opp; /**< O/H Policer Profile */
+ volatile uint32_t fmbm_occb; /**< O/H Coarse Classification base */
+ volatile uint32_t fmbm_oim; /**< O/H Internal margins*/
+ volatile uint32_t fmbm_ofp; /**< O/H Fifo Parameters*/
+ volatile uint32_t fmbm_ofed; /**< O/H Frame End Data*/
+ volatile uint32_t reserved0[2]; /**< (0x038 - 0x03F) */
+ volatile uint32_t fmbm_oprai[FM_PORT_PRS_RESULT_NUM_OF_WORDS];
+ /**< O/H Parse Results Array Initialization */
+ volatile uint32_t fmbm_ofqid; /**< O/H Frame Queue ID */
+ volatile uint32_t fmbm_oefqid; /**< O/H Error Frame Queue ID */
+ volatile uint32_t fmbm_ofsdm; /**< O/H Frame Status Discard Mask */
+ volatile uint32_t fmbm_ofsem; /**< O/H Frame Status Error Mask */
+ volatile uint32_t fmbm_ofene; /**< O/H Frame Enqueue Next Engine */
+ volatile uint32_t fmbm_orlmts; /**< O/H Rate Limiter Scale */
+ volatile uint32_t fmbm_orlmt; /**< O/H Rate Limiter */
+ volatile uint32_t fmbm_ocmne; /**< O/H Continuous Mode Next Engine */
+ volatile uint32_t reserved1[0x20];/**< (0x080 - 0x0FF) */
+ volatile uint32_t fmbm_oebmpi[2]; /**< Buffer Manager Observed Pool Information */
+ volatile uint32_t reserved2[0x16];/**< (0x108 - 0x15F) */
+ volatile uint32_t fmbm_ocgm; /**< Observed Congestion Group Map */
+ volatile uint32_t reserved3[0x7]; /**< (0x164 - 0x17F) */
+ volatile uint32_t fmbm_ompd; /**< Observed BMan Pool Depletion */
+ volatile uint32_t reserved4[0x1F];/**< (0x184 - 0x1FF) */
+ volatile uint32_t fmbm_ostc; /**< O/H Statistics Counters */
+ volatile uint32_t fmbm_ofrc; /**< O/H Frame Counter */
+ volatile uint32_t fmbm_ofdc; /**< O/H Frames Discard Counter */
+ volatile uint32_t fmbm_ofledc; /**< O/H Frames Length Error Discard Counter */
+ volatile uint32_t fmbm_ofufdc; /**< O/H Frames Unsupported Format Discard Counter */
+ volatile uint32_t fmbm_offc; /**< O/H Filter Frames Counter */
+ volatile uint32_t fmbm_ofwdc; /**< - Rx Frames WRED Discard Counter */
+ volatile uint32_t fmbm_ofldec; /**< O/H Frames List DMA Error Counter */
+ volatile uint32_t fmbm_obdc; /**< O/H Buffers Deallocate Counter */
+ volatile uint32_t fmbm_oodc; /**< O/H Out of Buffers Discard Counter */
+ volatile uint32_t fmbm_opec; /**< O/H Prepare to enqueue Counter */
+ volatile uint32_t reserved5[0x15];/**< ( - 0x27F) */
+ volatile uint32_t fmbm_opc; /**< O/H Performance Counters */
+ volatile uint32_t fmbm_opcp; /**< O/H Performance Count Parameters */
+ volatile uint32_t fmbm_occn; /**< O/H Cycle Counter */
+ volatile uint32_t fmbm_otuc; /**< O/H Tasks Utilization Counter */
+ volatile uint32_t fmbm_oduc; /**< O/H DMA Utilization Counter */
+ volatile uint32_t fmbm_ofuc; /**< O/H FIFO Utilization Counter */
+ volatile uint32_t reserved6[26]; /**< (0x298-0x2FF) */
+ volatile uint32_t fmbm_odcfg[0x3];/**< O/H Debug (only 1 in P1023) */
+ volatile uint32_t fmbm_ogpr; /**< O/H General Purpose Register. */
+ volatile uint32_t reserved7[0x3a];/**< (0x310 0x3FF) */
+} _PackedType t_FmPortOhBmiRegs;
+
+typedef _Packed union
+{
+ t_FmPortRxBmiRegs rxPortBmiRegs;
+ t_FmPortTxBmiRegs txPortBmiRegs;
+ t_FmPortOhBmiRegs ohPortBmiRegs;
+} _PackedType u_FmPortBmiRegs;
+
+typedef _Packed struct
+{
+ volatile uint32_t reserved1[2]; /**< 0xn024 - 0x02B */
+ volatile uint32_t fmqm_pndn; /**< PortID n Dequeue NIA Register */
+ volatile uint32_t fmqm_pndc; /**< PortID n Dequeue Config Register */
+ volatile uint32_t fmqm_pndtfc; /**< PortID n Dequeue Total Frame Counter */
+ volatile uint32_t fmqm_pndfdc; /**< PortID n Dequeue FQID from Default Counter */
+ volatile uint32_t fmqm_pndcc; /**< PortID n Dequeue Confirm Counter */
+} _PackedType t_FmPortNonRxQmiRegs;
+
+typedef _Packed struct
+{
+ volatile uint32_t fmqm_pnc; /**< PortID n Configuration Register */
+ volatile uint32_t fmqm_pns; /**< PortID n Status Register */
+ volatile uint32_t fmqm_pnts; /**< PortID n Task Status Register */
+ volatile uint32_t reserved0[4]; /**< 0xn00C - 0xn01B */
+ volatile uint32_t fmqm_pnen; /**< PortID n Enqueue NIA Register */
+ volatile uint32_t fmqm_pnetfc; /**< PortID n Enqueue Total Frame Counter */
+ t_FmPortNonRxQmiRegs nonRxQmiRegs; /**< Registers for Tx Hc & Op ports */
+} _PackedType t_FmPortQmiRegs;
+
+typedef _Packed struct
+{
+ _Packed struct
+ {
+ volatile uint32_t softSeqAttach; /**< Soft Sequence Attachment */
+ volatile uint32_t lcv; /**< Line-up Enable Confirmation Mask */
+ } _PackedType hdrs[FM_PCD_PRS_NUM_OF_HDRS];
+ volatile uint8_t reserved0[0x378];
+ volatile uint32_t pcac; /**< Parse Internal Memory Configuration Access Control Register */
+ volatile uint32_t pctpid; /**< Parse Internal Memory Configured TPID Register */
+} _PackedType t_FmPortPrsRegs;
+
+/**************************************************************************//*
+ @Description Basic buffer descriptor (BD) structure
+*//***************************************************************************/
+typedef _Packed struct
+{
+ volatile uint16_t status;
+ volatile uint16_t length;
+ volatile uint8_t reserved0[0x6];
+ volatile uint8_t reserved1[0x1];
+ volatile t_FmPhysAddr buff;
+} _PackedType t_FmImBd;
+
+typedef _Packed struct
+{
+ volatile uint16_t gen; /**< tbd */
+ volatile uint8_t reserved0[0x1];
+ volatile t_FmPhysAddr bdRingBase; /**< tbd */
+ volatile uint16_t bdRingSize; /**< tbd */
+ volatile uint16_t offsetIn; /**< tbd */
+ volatile uint16_t offsetOut; /**< tbd */
+ volatile uint8_t reserved1[0x12]; /**< 0x0e - 0x1f */
+} _PackedType t_FmPortImQd;
+
+typedef _Packed struct
+{
+ volatile uint32_t mode; /**< Mode register */
+ volatile uint32_t rxQdPtr; /**< tbd */
+ volatile uint32_t txQdPtr; /**< tbd */
+ volatile uint16_t mrblr; /**< tbd */
+ volatile uint16_t rxQdBsyCnt; /**< tbd */
+ volatile uint8_t reserved0[0x10]; /**< 0x10 - 0x1f */
+ t_FmPortImQd rxQd;
+ t_FmPortImQd txQd;
+ volatile uint8_t reserved1[0xa0]; /**< 0x60 - 0xff */
+} _PackedType t_FmPortImPram;
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+/**************************************************************************//**
+ @Description Registers bit fields
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Description BMI defines
+*//***************************************************************************/
+#if (DPAA_VERSION >= 11)
+#define BMI_SP_ID_MASK 0xff000000
+#define BMI_SP_ID_SHIFT 24
+#define BMI_SP_EN 0x01000000
+#endif /* (DPAA_VERSION >= 11) */
+
+#define BMI_PORT_CFG_EN 0x80000000
+#define BMI_PORT_CFG_EN_MACSEC 0x00800000
+#define BMI_PORT_CFG_FDOVR 0x02000000
+#define BMI_PORT_CFG_IM 0x01000000
+#define BMI_PORT_CFG_AM 0x00000040
+#define BMI_PORT_STATUS_BSY 0x80000000
+#define BMI_COUNTERS_EN 0x80000000
+
+#define BMI_PORT_RFNE_FRWD_DCL4C 0x10000000
+#define BMI_PORT_RFNE_FRWD_RPD 0x40000000
+#define BMI_RFNE_FDCS_MASK 0xFF000000
+
+#define BMI_CMD_MR_LEAC 0x00200000
+#define BMI_CMD_MR_SLEAC 0x00100000
+#define BMI_CMD_MR_MA 0x00080000
+#define BMI_CMD_MR_DEAS 0x00040000
+#define BMI_CMD_RX_MR_DEF (BMI_CMD_MR_LEAC | \
+ BMI_CMD_MR_SLEAC | \
+ BMI_CMD_MR_MA | \
+ BMI_CMD_MR_DEAS)
+#define BMI_CMD_ATTR_ORDER 0x80000000
+#define BMI_CMD_ATTR_SYNC 0x02000000
+#define BMI_CMD_ATTR_MODE_MISS_ALLIGN_ADDR_EN 0x00080000
+#define BMI_CMD_ATTR_MACCMD_MASK 0x0000ff00
+#define BMI_CMD_ATTR_MACCMD_OVERRIDE 0x00008000
+#define BMI_CMD_ATTR_MACCMD_SECURED 0x00001000
+#define BMI_CMD_ATTR_MACCMD_SC_MASK 0x00000f00
+
+#define BMI_EXT_BUF_POOL_ID_MASK 0x003F0000
+#define BMI_STATUS_RX_MASK_UNUSED (uint32_t)(~(FM_PORT_FRM_ERR_DMA | \
+ FM_PORT_FRM_ERR_PHYSICAL | \
+ FM_PORT_FRM_ERR_SIZE | \
+ FM_PORT_FRM_ERR_CLS_DISCARD | \
+ FM_PORT_FRM_ERR_EXTRACTION | \
+ FM_PORT_FRM_ERR_NO_SCHEME | \
+ FM_PORT_FRM_ERR_COLOR_RED | \
+ FM_PORT_FRM_ERR_COLOR_YELLOW | \
+ FM_PORT_FRM_ERR_ILL_PLCR | \
+ FM_PORT_FRM_ERR_PLCR_FRAME_LEN | \
+ FM_PORT_FRM_ERR_PRS_TIMEOUT | \
+ FM_PORT_FRM_ERR_PRS_ILL_INSTRUCT | \
+ FM_PORT_FRM_ERR_BLOCK_LIMIT_EXCEEDED | \
+ FM_PORT_FRM_ERR_PRS_HDR_ERR | \
+ FM_PORT_FRM_ERR_IPRE | \
+ FM_PORT_FRM_ERR_IPR_NCSP | \
+ FM_PORT_FRM_ERR_KEYSIZE_OVERFLOW))
+
+#define BMI_STATUS_OP_MASK_UNUSED (uint32_t)(BMI_STATUS_RX_MASK_UNUSED & \
+ ~(FM_PORT_FRM_ERR_LENGTH | \
+ FM_PORT_FRM_ERR_NON_FM | \
+ FM_PORT_FRM_ERR_UNSUPPORTED_FORMAT))
+
+#define BMI_RATE_LIMIT_EN 0x80000000
+#define BMI_RATE_LIMIT_BURST_SIZE_GRAN 0x80000000
+#define BMI_RATE_LIMIT_SCALE_BY_2 0x00000001
+#define BMI_RATE_LIMIT_SCALE_BY_4 0x00000002
+#define BMI_RATE_LIMIT_SCALE_BY_8 0x00000003
+
+#define BMI_RX_FIFO_THRESHOLD_BC 0x80000000
+
+#define BMI_PRS_RESULT_HIGH 0x00000000
+#define BMI_PRS_RESULT_LOW 0xFFFFFFFF
+
+
+#define RX_ERRS_TO_ENQ (FM_PORT_FRM_ERR_DMA | \
+ FM_PORT_FRM_ERR_PHYSICAL | \
+ FM_PORT_FRM_ERR_SIZE | \
+ FM_PORT_FRM_ERR_EXTRACTION | \
+ FM_PORT_FRM_ERR_NO_SCHEME | \
+ FM_PORT_FRM_ERR_ILL_PLCR | \
+ FM_PORT_FRM_ERR_PLCR_FRAME_LEN | \
+ FM_PORT_FRM_ERR_PRS_TIMEOUT | \
+ FM_PORT_FRM_ERR_PRS_ILL_INSTRUCT | \
+ FM_PORT_FRM_ERR_BLOCK_LIMIT_EXCEEDED | \
+ FM_PORT_FRM_ERR_PRS_HDR_ERR | \
+ FM_PORT_FRM_ERR_KEYSIZE_OVERFLOW | \
+ FM_PORT_FRM_ERR_IPRE)
+
+#define OP_ERRS_TO_ENQ (RX_ERRS_TO_ENQ | \
+ FM_PORT_FRM_ERR_LENGTH | \
+ FM_PORT_FRM_ERR_NON_FM | \
+ FM_PORT_FRM_ERR_UNSUPPORTED_FORMAT)
+
+
+#define BMI_RX_FIFO_PRI_ELEVATION_MASK 0x03FF0000
+#define BMI_RX_FIFO_THRESHOLD_MASK 0x000003FF
+#define BMI_TX_FIFO_MIN_FILL_MASK 0x03FF0000
+#define BMI_FIFO_PIPELINE_DEPTH_MASK 0x0000F000
+#define BMI_TX_LOW_COMF_MASK 0x000003FF
+
+/* shifts */
+#define BMI_PORT_CFG_MS_SEL_SHIFT 16
+#define BMI_DMA_ATTR_IC_CACHE_SHIFT FMAN_SP_DMA_ATTR_IC_CACHE_SHIFT
+#define BMI_DMA_ATTR_HDR_CACHE_SHIFT FMAN_SP_DMA_ATTR_HDR_CACHE_SHIFT
+#define BMI_DMA_ATTR_SG_CACHE_SHIFT FMAN_SP_DMA_ATTR_SG_CACHE_SHIFT
+
+#define BMI_IM_FOF_SHIFT 28
+#define BMI_PR_PORTID_SHIFT 24
+
+#define BMI_RX_FIFO_PRI_ELEVATION_SHIFT 16
+#define BMI_RX_FIFO_THRESHOLD_SHIFT 0
+
+#define BMI_RX_FRAME_END_CS_IGNORE_SHIFT 24
+#define BMI_RX_FRAME_END_CUT_SHIFT 16
+
+#define BMI_IC_SIZE_SHIFT FMAN_SP_IC_SIZE_SHIFT
+
+#define BMI_INT_BUF_MARG_SHIFT 28
+
+#define BMI_EXT_BUF_MARG_END_SHIFT FMAN_SP_EXT_BUF_MARG_END_SHIFT
+
+#define BMI_CMD_ATTR_COLOR_SHIFT 26
+#define BMI_CMD_ATTR_COM_MODE_SHIFT 16
+#define BMI_CMD_ATTR_MACCMD_SHIFT 8
+#define BMI_CMD_ATTR_MACCMD_OVERRIDE_SHIFT 15
+#define BMI_CMD_ATTR_MACCMD_SECURED_SHIFT 12
+#define BMI_CMD_ATTR_MACCMD_SC_SHIFT 8
+
+#define BMI_POOL_DEP_NUM_OF_POOLS_VECTOR_SHIFT 24
+
+#define BMI_TX_FIFO_MIN_FILL_SHIFT 16
+#define BMI_TX_LOW_COMF_SHIFT 0
+
+#define BMI_PERFORMANCE_TASK_COMP_SHIFT 24
+#define BMI_PERFORMANCE_PORT_COMP_SHIFT 16
+#define BMI_PERFORMANCE_DMA_COMP_SHIFT 12
+#define BMI_PERFORMANCE_FIFO_COMP_SHIFT 0
+
+#define BMI_MAX_BURST_SHIFT 16
+#define BMI_COUNT_RATE_UNIT_SHIFT 16
+
+/* sizes */
+#define FRAME_END_DATA_SIZE 16
+#define FRAME_OFFSET_UNITS 16
+#define MIN_TX_INT_OFFSET 16
+#define MAX_FRAME_OFFSET 64
+#define MAX_FIFO_PIPELINE_DEPTH 8
+#define MAX_PERFORMANCE_TASK_COMP 64
+#define MAX_PERFORMANCE_TX_QUEUE_COMP 8
+#define MAX_PERFORMANCE_RX_QUEUE_COMP 64
+#define MAX_PERFORMANCE_DMA_COMP 16
+#define MAX_NUM_OF_TASKS 64
+#define MAX_NUM_OF_EXTRA_TASKS 8
+#define MAX_NUM_OF_DMAS 16
+#define MAX_NUM_OF_EXTRA_DMAS 8
+#define MAX_BURST_SIZE 1024
+#define MIN_NUM_OF_OP_DMAS 2
+
+
+/**************************************************************************//**
+ @Description QMI defines
+*//***************************************************************************/
+/* masks */
+#define QMI_PORT_CFG_EN 0x80000000
+#define QMI_PORT_CFG_EN_COUNTERS 0x10000000
+#define QMI_PORT_STATUS_DEQ_TNUM_BSY 0x80000000
+#define QMI_PORT_STATUS_DEQ_FD_BSY 0x20000000
+
+#define QMI_DEQ_CFG_PREFETCH_NO_TNUM 0x02000000
+#define QMI_DEQ_CFG_PREFETCH_WAITING_TNUM 0
+#define QMI_DEQ_CFG_PREFETCH_1_FRAME 0
+#define QMI_DEQ_CFG_PREFETCH_3_FRAMES 0x01000000
+
+#define QMI_DEQ_CFG_PRI 0x80000000
+#define QMI_DEQ_CFG_TYPE1 0x10000000
+#define QMI_DEQ_CFG_TYPE2 0x20000000
+#define QMI_DEQ_CFG_TYPE3 0x30000000
+
+#define QMI_DEQ_CFG_SUBPORTAL_MASK 0x1f
+#define QMI_DEQ_CFG_SUBPORTAL_SHIFT 20
+
+/**************************************************************************//**
+ @Description PARSER defines
+*//***************************************************************************/
+/* masks */
+#define PRS_HDR_ERROR_DIS 0x00000800
+#define PRS_HDR_SW_PRS_EN 0x00000400
+#define PRS_CP_OFFSET_MASK 0x0000000F
+#define PRS_TPID1_MASK 0xFFFF0000
+#define PRS_TPID2_MASK 0x0000FFFF
+#define PRS_TPID_DFLT 0x91009100
+
+#define PRS_HDR_MPLS_LBL_INTER_EN 0x00200000
+#define PRS_HDR_IPV6_ROUTE_HDR_EN 0x00008000
+#define PRS_HDR_PPPOE_MTU_CHECK_EN 0x80000000
+#define PRS_HDR_UDP_PAD_REMOVAL 0x80000000
+#define PRS_HDR_TCP_PAD_REMOVAL 0x80000000
+#define PRS_CAC_STOP 0x00000001
+#define PRS_CAC_ACTIVE 0x00000100
+
+/* shifts */
+#define PRS_PCTPID_SHIFT 16
+#define PRS_HDR_MPLS_NEXT_HDR_SHIFT 22
+#define PRS_HDR_ETH_BC_SHIFT 28
+#define PRS_HDR_ETH_MC_SHIFT 24
+#define PRS_HDR_VLAN_STACKED_SHIFT 16
+#define PRS_HDR_MPLS_STACKED_SHIFT 16
+#define PRS_HDR_IPV4_1_BC_SHIFT 28
+#define PRS_HDR_IPV4_1_MC_SHIFT 24
+#define PRS_HDR_IPV4_2_UC_SHIFT 20
+#define PRS_HDR_IPV4_2_MC_BC_SHIFT 16
+#define PRS_HDR_IPV6_1_MC_SHIFT 24
+#define PRS_HDR_IPV6_2_UC_SHIFT 20
+#define PRS_HDR_IPV6_2_MC_SHIFT 16
+
+#define PRS_HDR_ETH_BC_MASK 0x0fffffff
+#define PRS_HDR_ETH_MC_MASK 0xf0ffffff
+#define PRS_HDR_VLAN_STACKED_MASK 0xfff0ffff
+#define PRS_HDR_MPLS_STACKED_MASK 0xfff0ffff
+#define PRS_HDR_IPV4_1_BC_MASK 0x0fffffff
+#define PRS_HDR_IPV4_1_MC_MASK 0xf0ffffff
+#define PRS_HDR_IPV4_2_UC_MASK 0xff0fffff
+#define PRS_HDR_IPV4_2_MC_BC_MASK 0xfff0ffff
+#define PRS_HDR_IPV6_1_MC_MASK 0xf0ffffff
+#define PRS_HDR_IPV6_2_UC_MASK 0xff0fffff
+#define PRS_HDR_IPV6_2_MC_MASK 0xfff0ffff
+
+/* others */
+#define PRS_HDR_ENTRY_SIZE 8
+#define DEFAULT_CLS_PLAN_VECTOR 0xFFFFFFFF
+
+#define IPSEC_SW_PATCH_START 0x20
+#define SCTP_SW_PATCH_START 0x4D
+#define DCCP_SW_PATCH_START 0x41
+
+/**************************************************************************//**
+ @Description IM defines
+*//***************************************************************************/
+#define BD_R_E 0x80000000
+#define BD_L 0x08000000
+
+#define BD_RX_CRE 0x00080000
+#define BD_RX_FTL 0x00040000
+#define BD_RX_FTS 0x00020000
+#define BD_RX_OV 0x00010000
+
+#define BD_RX_ERRORS (BD_RX_CRE | BD_RX_FTL | BD_RX_FTS | BD_RX_OV)
+#define BD_ERROR_PASS_FRAME BD_RX_ERRORS
+
+#define FM_IM_SIZEOF_BD sizeof(t_FmImBd)
+
+#define BD_STATUS_MASK 0xffff0000
+#define BD_LENGTH_MASK 0x0000ffff
+
+#define BD_STATUS_AND_LENGTH_SET(bd, val) WRITE_UINT32(*(volatile uint32_t*)(bd), (val))
+
+#define BD_STATUS_AND_LENGTH(bd) GET_UINT32(*(volatile uint32_t*)(bd))
+
+#define BD_GET(id) &p_FmPort->im.p_BdRing[id]
+
+#define IM_ILEGAL_BD_ID 0xffff
+
+/* others */
+#define IM_PRAM_ALIGN 0x100
+
+/* masks */
+#define IM_MODE_GBL 0x20000000
+#define IM_MODE_BO_MASK 0x18000000
+#define IM_MODE_BO_SHIFT 3
+#define IM_MODE_GRC_STP 0x00800000
+
+#define IM_MODE_SET_BO(val) (uint32_t)((val << (31-IM_MODE_BO_SHIFT)) & IM_MODE_BO_MASK)
+
+#define IM_RXQD_BSYINTM 0x0008
+#define IM_RXQD_RXFINTM 0x0010
+#define IM_RXQD_FPMEVT_SEL_MASK 0x0003
+
+#define IM_EV_BSY 0x40000000
+#define IM_EV_RX 0x80000000
+
+
+/**************************************************************************//**
+ @Description Additional defines
+*//***************************************************************************/
+
+typedef struct {
+ t_Handle h_FmMuram;
+ t_FmPortImPram *p_FmPortImPram;
+ uint8_t fwExtStructsMemId;
+ uint32_t fwExtStructsMemAttr;
+ uint16_t bdRingSize;
+ t_FmImBd *p_BdRing;
+ t_Handle *p_BdShadow;
+ uint16_t currBdId;
+ uint16_t firstBdOfFrameId;
+
+ /* Rx port parameters */
+ uint8_t dataMemId; /**< Memory partition ID for data buffers */
+ uint32_t dataMemAttributes; /**< Memory attributes for data buffers */
+ t_BufferPoolInfo rxPool;
+ uint16_t mrblr;
+ uint16_t rxFrameAccumLength;
+ t_FmPortImRxStoreCallback *f_RxStore;
+
+ /* Tx port parameters */
+ uint32_t txFirstBdStatus;
+ t_FmPortImTxConfCallback *f_TxConf;
+} t_FmMacIm;
+
+
+typedef struct {
+ struct fman_port_cfg dfltCfg;
+ uint32_t dfltFqid;
+ uint32_t confFqid;
+ uint32_t errFqid;
+ uintptr_t baseAddr;
+ uint8_t deqSubPortal;
+ bool deqHighPriority;
+ e_FmPortDeqType deqType;
+ e_FmPortDeqPrefetchOption deqPrefetchOption;
+ uint16_t deqByteCnt;
+ uint8_t cheksumLastBytesIgnore;
+ uint8_t cutBytesFromEnd;
+ t_FmBufPoolDepletion bufPoolDepletion;
+ uint8_t pipelineDepth;
+ uint16_t fifoLowComfLevel;
+ bool frmDiscardOverride;
+ bool enRateLimit;
+ t_FmPortRateLimit rateLimit;
+ e_FmPortDualRateLimiterScaleDown rateLimitDivider;
+ bool enBufPoolDepletion;
+ uint16_t liodnOffset;
+ uint16_t liodnBase;
+ t_FmExtPools extBufPools;
+ e_FmDmaSwapOption dmaSwapData;
+ e_FmDmaCacheOption dmaIntContextCacheAttr;
+ e_FmDmaCacheOption dmaHeaderCacheAttr;
+ e_FmDmaCacheOption dmaScatterGatherCacheAttr;
+ bool dmaReadOptimize;
+ bool dmaWriteOptimize;
+ uint32_t txFifoMinFillLevel;
+ uint32_t txFifoLowComfLevel;
+ uint32_t rxFifoPriElevationLevel;
+ uint32_t rxFifoThreshold;
+ t_FmSpBufMargins bufMargins;
+ t_FmSpIntContextDataCopy intContext;
+ bool syncReq;
+ e_FmPortColor color;
+ fmPortFrameErrSelect_t errorsToDiscard;
+ fmPortFrameErrSelect_t errorsToEnq;
+ bool forwardReuseIntContext;
+ t_FmBufferPrefixContent bufferPrefixContent;
+ t_FmBackupBmPools *p_BackupBmPools;
+ bool dontReleaseBuf;
+ bool setNumOfTasks;
+ bool setNumOfOpenDmas;
+ bool setSizeOfFifo;
+#if (DPAA_VERSION >= 11)
+ bool noScatherGather;
+#endif /* (DPAA_VERSION >= 11) */
+
+#ifdef FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669
+ bool bcbWorkaround;
+#endif /* FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 */
+} t_FmPortDriverParam;
+
+
+typedef struct t_FmPortRxPoolsParams
+{
+ uint8_t numOfPools;
+ uint16_t secondLargestBufSize;
+ uint16_t largestBufSize;
+} t_FmPortRxPoolsParams;
+
+typedef struct t_FmPortDsarVars {
+ t_Handle *autoResOffsets;
+ t_FmPortDsarTablesSizes *autoResMaxSizes;
+ uint32_t fmbm_tcfg;
+ uint32_t fmbm_tcmne;
+ uint32_t fmbm_rfne;
+ uint32_t fmbm_rfpne;
+ uint32_t fmbm_rcfg;
+ bool dsarEnabledParser;
+} t_FmPortDsarVars;
+typedef struct {
+ struct fman_port port;
+ t_Handle h_Fm;
+ t_Handle h_FmPcd;
+ t_Handle h_FmMuram;
+ t_FmRevisionInfo fmRevInfo;
+ uint8_t portId;
+ e_FmPortType portType;
+ int enabled;
+ char name[MODULE_NAME_SIZE];
+ uint8_t hardwarePortId;
+ uint16_t fmClkFreq;
+ t_FmPortQmiRegs *p_FmPortQmiRegs;
+ u_FmPortBmiRegs *p_FmPortBmiRegs;
+ t_FmPortPrsRegs *p_FmPortPrsRegs;
+ fmPcdEngines_t pcdEngines;
+ uint32_t savedBmiNia;
+ uint8_t netEnvId;
+ uint32_t optArray[FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)];
+ uint32_t lcvs[FM_PCD_PRS_NUM_OF_HDRS];
+ uint8_t privateInfo;
+ uint32_t schemesPerPortVector;
+ bool useClsPlan;
+ uint8_t clsPlanGrpId;
+ t_Handle ccTreeId;
+ t_Handle completeArg;
+ void (*f_Complete)(t_Handle arg);
+ t_FmSpBufferOffsets bufferOffsets;
+ /* Independent-Mode parameters support */
+ bool imEn;
+ t_FmMacIm im;
+ volatile bool lock;
+ t_Handle h_Spinlock;
+ t_FmPortExceptionCallback *f_Exception;
+ t_Handle h_App;
+ uint8_t internalBufferOffset;
+ uint8_t fmanCtrlEventId;
+ uint32_t exceptions;
+ bool polling;
+ t_FmExtPools extBufPools;
+ uint32_t requiredAction;
+ uint32_t savedQmiPnen;
+ uint32_t savedBmiFene;
+ uint32_t savedBmiFpne;
+ uint32_t savedBmiCmne;
+ uint32_t savedNonRxQmiRegsPndn;
+ uint32_t origNonRxQmiRegsPndn;
+ int savedPrsStartOffset;
+ bool includeInPrsStatistics;
+ uint16_t maxFrameLength;
+ t_FmFmanCtrl orFmanCtrl;
+ t_FmPortRsrc openDmas;
+ t_FmPortRsrc tasks;
+ t_FmPortRsrc fifoBufs;
+ t_FmPortRxPoolsParams rxPoolsParams;
+// bool explicitUserSizeOfFifo;
+ t_Handle h_IpReassemblyManip;
+ t_Handle h_IpReassemblyTree;
+ uint64_t fmMuramPhysBaseAddr;
+#if (DPAA_VERSION >= 11)
+ bool vspe;
+ uint8_t dfltRelativeId;
+ e_FmPortGprFuncType gprFunc;
+ t_FmPcdCtrlParamsPage *p_ParamsPage;
+#endif /* (DPAA_VERSION >= 11) */
+ t_FmPortDsarVars deepSleepVars;
+ t_FmPortDriverParam *p_FmPortDriverParam;
+} t_FmPort;
+
+
+void FmPortConfigIM (t_FmPort *p_FmPort, t_FmPortParams *p_FmPortParams);
+t_Error FmPortImCheckInitParameters(t_FmPort *p_FmPort);
+
+t_Error FmPortImInit(t_FmPort *p_FmPort);
+void FmPortImFree(t_FmPort *p_FmPort);
+
+t_Error FmPortImEnable (t_FmPort *p_FmPort);
+t_Error FmPortImDisable (t_FmPort *p_FmPort);
+t_Error FmPortImRx (t_FmPort *p_FmPort);
+
+void FmPortSetMacsecLcv(t_Handle h_FmPort);
+void FmPortSetMacsecCmd(t_Handle h_FmPort, uint8_t dfltSci);
+
+
+t_Error FM_PORT_SetNumOfOpenDmas(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfOpenDmas);
+t_Error FM_PORT_SetNumOfTasks(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfTasks);
+t_Error FM_PORT_SetSizeOfFifo(t_Handle h_FmPort, t_FmPortRsrc *p_SizeOfFifo);
+
+static __inline__ uint8_t * BdBufferGet (t_PhysToVirt *f_PhysToVirt, t_FmImBd *p_Bd)
+{
+ uint64_t physAddr = (uint64_t)((uint64_t)GET_UINT8(p_Bd->buff.high) << 32);
+ physAddr |= GET_UINT32(p_Bd->buff.low);
+
+ return (uint8_t *)f_PhysToVirt((physAddress_t)(physAddr));
+}
+
+static __inline__ void SET_ADDR(volatile t_FmPhysAddr *fmPhysAddr, uint64_t value)
+{
+ WRITE_UINT8(fmPhysAddr->high,(uint8_t)((value & 0x000000ff00000000LL) >> 32));
+ WRITE_UINT32(fmPhysAddr->low,(uint32_t)value);
+}
+
+static __inline__ void BdBufferSet(t_VirtToPhys *f_VirtToPhys, t_FmImBd *p_Bd, uint8_t *p_Buffer)
+{
+ uint64_t physAddr = (uint64_t)(f_VirtToPhys(p_Buffer));
+ SET_ADDR(&p_Bd->buff, physAddr);
+}
+
+static __inline__ uint16_t GetNextBdId(t_FmPort *p_FmPort, uint16_t id)
+{
+ if (id < p_FmPort->im.bdRingSize-1)
+ return (uint16_t)(id+1);
+ else
+ return 0;
+}
+
+void FM_PORT_Dsar_DumpRegs(void);
+
+
+#endif /* __FM_PORT_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port_dsar.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port_dsar.h
new file mode 100755
index 0000000..95619ef
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port_dsar.h
@@ -0,0 +1,494 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**************************************************************************//**
+ @File fm_port_dsar.h
+
+ @Description Deep Sleep Auto Response project - common module header file.
+
+ Author - Eyal Harari
+
+ @Cautions See the FMan Controller spec and design document for more information.
+*//***************************************************************************/
+
+#ifndef __FM_PORT_DSAR_H_
+#define __FM_PORT_DSAR_H_
+
+#define DSAR_GETSER_MASK 0xFF0000FF
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+/**************************************************************************//**
+ @Description Deep Sleep Auto Response VLAN-IPv4 Binding Table (for ARP/ICMPv4)
+ Refer to the FMan Controller spec for more details.
+*//***************************************************************************/
+typedef _Packed struct
+{
+ uint32_t ipv4Addr; /*!< 32 bit IPv4 Address. */
+ uint16_t vlanId; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */
+ /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */
+ uint16_t reserved;
+} _PackedType t_DsarArpBindingEntry;
+
+/**************************************************************************//**
+ @Description Deep Sleep Auto Response Address Resolution Protocol Statistics Descriptor
+ Refer to the FMan Controller spec for more details.
+ 0x00 INVAL_CNT Invalid ARP IPv4-Ethernet counter
+ 0x04 ECHO_CNT Echo counter
+ 0x08 CD_CNT Conflict Detection counter
+ 0x0C AR_CNT Auto-Response counter
+ 0x10 RATM_CNT Replies Addressed To Me counter
+ 0x14 UKOP_CNT Unknown Operation counter
+ 0x18 NMTP_CNT Not my TPA counter
+ 0x1C NMVLAN_CNT Not My VLAN counter
+*//***************************************************************************/
+typedef _Packed struct
+{
+ uint32_t invalCnt; /**< Invalid ARP IPv4-Ethernet counter. */
+ uint32_t echoCnt; /**< Echo counter. */
+ uint32_t cdCnt; /**< Conflict Detection counter. */
+ uint32_t arCnt; /**< Auto-Response counter. */
+ uint32_t ratmCnt; /**< Replies Addressed To Me counter. */
+ uint32_t ukopCnt; /**< Unknown Operation counter. */
+ uint32_t nmtpCnt; /**< Not my TPA counter. */
+ uint32_t nmVlanCnt; /**< Not My VLAN counter */
+} _PackedType t_DsarArpStatistics;
+
+
+/**************************************************************************//**
+ @Description Deep Sleep Auto Response Address Resolution Protocol Descriptor
+ 0x0 0-15 Control bits [0-15]. Bit 15 = CDEN.
+ 0x2 0-15 NumOfBindings Number of entries in the binding list.
+ 0x4 0-15 BindingsPointer Bindings Pointer. This points to an IPv4-MAC Addresses Bindings list.
+ 0x6 0-15
+ 0x8 0-15 StatisticsPointer Statistics Pointer. This field points to the ARP Descriptors statistics data structure.
+ 0xA 0-15
+ 0xC 0-15 Reserved Reserved. Must be cleared.
+ 0xE 015
+
+*//***************************************************************************/
+typedef _Packed struct
+{
+ uint16_t control; /** Control bits [0-15]. Bit 15 = CDEN */
+ uint16_t numOfBindings; /**< Number of VLAN-IPv4 */
+ uint32_t p_Bindings; /**< VLAN-IPv4 Bindings table pointer. */
+ uint32_t p_Statistics; /**< Statistics Data Structure pointer. */
+ uint32_t reserved1; /**< Reserved. */
+} _PackedType t_DsarArpDescriptor;
+
+
+/**************************************************************************//**
+ @Description Deep Sleep Auto Response VLAN-IPv4 Binding Table (for ARP/ICMPv4)
+ Refer to the FMan Controller spec for more details.
+*//***************************************************************************/
+typedef _Packed struct
+{
+ uint32_t ipv4Addr; /*!< 32 bit IPv4 Address. */
+ uint16_t vlanId; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */
+ /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */
+ uint16_t reserved;
+} _PackedType t_DsarIcmpV4BindingEntry;
+
+/**************************************************************************//**
+ @Description Deep Sleep Auto Response ICMPv4 Statistics Descriptor
+ Refer to the FMan Controller spec for more details.
+ 0x00 INVAL_CNT Invalid ICMPv4 header counter
+ 0x04 NMVLAN_CNT Not My VLAN counter
+ 0x08 NMIP_CNT Not My IP counter
+ 0x0C AR_CNT Auto-Response counter
+ 0x10 CSERR_CNT Checksum Error counter
+ 0x14 Reserved Reserved
+ 0x18 Reserved Reserved
+ 0x1C Reserved Reserved
+
+*//***************************************************************************/
+typedef _Packed struct
+{
+ uint32_t invalCnt; /**< Invalid ICMPv4 Echo counter. */
+ uint32_t nmVlanCnt; /**< Not My VLAN counter */
+ uint32_t nmIpCnt; /**< Not My IP counter */
+ uint32_t arCnt; /**< Auto-Response counter */
+ uint32_t cserrCnt; /**< Checksum Error counter */
+ uint32_t reserved0; /**< Reserved */
+ uint32_t reserved1; /**< Reserved */
+ uint32_t reserved2; /**< Reserved */
+} _PackedType t_DsarIcmpV4Statistics;
+
+
+
+/**************************************************************************//**
+ @Description Deep Sleep Auto Response ICMPv4 Descriptor
+ 0x0 0-15 Control bits [0-15]
+ 0x2 0-15 NumOfBindings Number of entries in the binding list.
+ 0x4 0-15 BindingsPointer Bindings Pointer. This points to an VLAN-IPv4 Addresses Bindings list.
+ 0x6 0-15
+ 0x8 0-15 StatisticsPointer Statistics Pointer. This field points to the ICMPv4 statistics data structure.
+ 0xA 0-15
+ 0xC 0-15 Reserved Reserved. Must be cleared.
+ 0xE 015
+
+*//***************************************************************************/
+typedef _Packed struct
+{
+ uint16_t control; /** Control bits [0-15]. */
+ uint16_t numOfBindings; /**< Number of VLAN-IPv4 */
+ uint32_t p_Bindings; /**< VLAN-IPv4 Bindings table pointer. */
+ uint32_t p_Statistics; /**< Statistics Data Structure pointer. */
+ uint32_t reserved1; /**< Reserved. */
+} _PackedType t_DsarIcmpV4Descriptor;
+
+/**************************************************************************//**
+ @Description Deep Sleep Auto Response VLAN-IPv4 Binding Table (for ARP/ICMPv4)
+ The 4 left-most bits (15:12) of the VlanId parameter are control flags.
+ Flags[3:1] (VlanId[15:13]): Reserved, should be cleared.
+ Flags[0] (VlanId[12]): Temporary address.
+ • 0 - Assigned IP address.
+ • 1- Temporary (tentative) IP address.
+ Refer to the FMan Controller spec for more details.
+*//***************************************************************************/
+typedef _Packed struct
+{
+ uint32_t ipv6Addr[4]; /*!< 3 * 32 bit IPv4 Address. */
+ uint16_t resFlags:4; /*!< reserved flags. should be cleared */
+ uint16_t vlanId:12; /*!< 12 bits VLAN ID. */
+ /*!< This field should be 0x000 for an entry with no VLAN tag or a null VLAN ID. */
+ uint16_t reserved;
+} _PackedType t_DsarIcmpV6BindingEntry;
+
+/**************************************************************************//**
+ @Description Deep Sleep Auto Response ICMPv4 Statistics Descriptor
+ Refer to the FMan Controller spec for more details.
+ 0x00 INVAL_CNT Invalid ICMPv4 header counter
+ 0x04 NMVLAN_CNT Not My VLAN counter
+ 0x08 NMIP_CNT Not My IP counter
+ 0x0C AR_CNT Auto-Response counter
+ 0x10 CSERR_CNT Checksum Error counter
+ 0x14 MCAST_CNT Multicast counter
+ 0x18 Reserved Reserved
+ 0x1C Reserved Reserved
+
+*//***************************************************************************/
+typedef _Packed struct
+{
+ uint32_t invalCnt; /**< Invalid ICMPv4 Echo counter. */
+ uint32_t nmVlanCnt; /**< Not My VLAN counter */
+ uint32_t nmIpCnt; /**< Not My IP counter */
+ uint32_t arCnt; /**< Auto-Response counter */
+ uint32_t reserved1; /**< Reserved */
+ uint32_t reserved2; /**< Reserved */
+ uint32_t reserved3; /**< Reserved */
+ uint32_t reserved4; /**< Reserved */
+} _PackedType t_DsarIcmpV6Statistics;
+
+/**************************************************************************//**
+ @Description Deep Sleep Auto Response Neighbor Discovery Statistics Descriptor
+ 0x00 INVAL_CNT Invalid Neighbor Discovery message counter
+ 0x04 NMVLAN_CNT Not My VLAN counter
+ 0x08 NMIP_CNT Not My IP counter
+ 0x0C AR_CNT Auto-Response counter
+ 0x10 CSERR_CNT Checksum Error counter
+ 0x14 USADVERT_CNT Unsolicited Neighbor Advertisements counter
+ 0x18 NMMCAST_CNT Not My Multicast group counter
+ 0x1C NSLLA_CNT No Source Link-Layer Address counter. Indicates that there was a match on a Target
+ Address of a packet that its source IP address is a unicast address, but the ICMPv6
+ Source Link-layer Address option is omitted
+*//***************************************************************************/
+typedef _Packed struct
+{
+ uint32_t invalCnt; /**< Invalid ICMPv4 Echo counter. */
+ uint32_t nmVlanCnt; /**< Not My VLAN counter */
+ uint32_t nmIpCnt; /**< Not My IP counter */
+ uint32_t arCnt; /**< Auto-Response counter */
+ uint32_t reserved1; /**< Reserved */
+ uint32_t usadvertCnt; /**< Unsolicited Neighbor Advertisements counter */
+ uint32_t nmmcastCnt; /**< Not My Multicast group counter */
+ uint32_t nsllaCnt; /**< No Source Link-Layer Address counter */
+} _PackedType t_NdStatistics;
+
+/**************************************************************************//**
+ @Description Deep Sleep Auto Response ICMPv6 Descriptor
+ 0x0 0-15 Control bits [0-15]
+ 0x2 0-15 NumOfBindings Number of entries in the binding list.
+ 0x4 0-15 BindingsPointer Bindings Pointer. This points to an VLAN-IPv4 Addresses Bindings list.
+ 0x6 0-15
+ 0x8 0-15 StatisticsPointer Statistics Pointer. This field points to the ICMPv4 statistics data structure.
+ 0xA 0-15
+ 0xC 0-15 Reserved Reserved. Must be cleared.
+ 0xE 015
+
+*//***************************************************************************/
+typedef _Packed struct
+{
+ uint16_t control; /** Control bits [0-15]. */
+ uint16_t numOfBindings; /**< Number of VLAN-IPv6 */
+ uint32_t p_Bindings; /**< VLAN-IPv4 Bindings table pointer. */
+ uint32_t p_Statistics; /**< Statistics Data Structure pointer. */
+ uint32_t reserved1; /**< Reserved. */
+} _PackedType t_DsarIcmpV6Descriptor;
+
+
+/**************************************************************************//**
+ @Description Internet Control Message Protocol (ICMPv6) Echo message header
+ The fields names are taken from RFC 4443.
+*//***************************************************************************/
+/* 0 1 2 3 */
+/* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 */
+/* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
+/* | Type | Code | Checksum | */
+/* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
+/* | Identifier | Sequence Number | */
+/* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */
+/* | Data ... */
+/* +-+-+-+-+- */
+typedef _Packed struct
+{
+ uint8_t type;
+ uint8_t code;
+ uint16_t checksum;
+ uint16_t identifier;
+ uint16_t sequenceNumber;
+} _PackedType t_IcmpV6EchoHdr;
+
+/**************************************************************************//**
+ @Description Internet Control Message Protocol (ICMPv6)
+ Neighbor Solicitation/Advertisement header
+ The fields names are taken from RFC 4861.
+ The R/S/O fields are valid for Neighbor Advertisement only
+*//***************************************************************************/
+/* 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Type | Code | Checksum |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |R|S|O| Reserved |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | |
+ * + +
+ * | |
+ * + Target Address +
+ * | |
+ * + +
+ * | |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Options ...
+ * +-+-+-+-+-+-+-+-+-+-+-+-
+ *
+ * Options Format:
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Type | Length | Link-Layer Address ... |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Link-Layer Address |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+typedef _Packed struct
+{
+ uint8_t type;
+ uint8_t code;
+ uint16_t checksum;
+ uint32_t router:1;
+ uint32_t solicited:1;
+ uint32_t override:1;
+ uint32_t reserved:29;
+ uint32_t targetAddr[4];
+ uint8_t optionType;
+ uint8_t optionLength;
+ uint8_t linkLayerAddr[6];
+} _PackedType t_IcmpV6NdHdr;
+
+/**************************************************************************//**
+ @Description Deep Sleep Auto Response ICMPv6 Descriptor
+ 0x0 0-15 Control bits [0-15]
+ 0x2 0-15 NumOfBindings Number of entries in the binding list.
+ 0x4 0-15 BindingsPointer Bindings Pointer. This points to an VLAN-IPv4 Addresses Bindings list.
+ 0x6 0-15
+ 0x8 0-15 StatisticsPointer Statistics Pointer. This field points to the ICMPv4 statistics data structure.
+ 0xA 0-15
+ 0xC 0-15 Reserved Reserved. Must be cleared.
+ 0xE 015
+
+*//***************************************************************************/
+typedef _Packed struct
+{
+ uint16_t control; /** Control bits [0-15]. */
+ uint16_t numOfBindings; /**< Number of VLAN-IPv6 */
+ uint32_t p_Bindings; /**< VLAN-IPv4 Bindings table pointer. */
+ uint32_t p_Statistics; /**< Statistics Data Structure pointer. */
+ uint32_t solicitedAddr; /**< Solicited Node Multicast Group Address */
+} _PackedType t_DsarNdDescriptor;
+
+/**************************************************************************//**
+@Description Deep Sleep Auto Response SNMP OIDs table entry
+
+*//***************************************************************************/
+typedef struct {
+ uint16_t oidSize; /**< Size in octets of the OID. */
+ uint16_t resSize; /**< Size in octets of the value that is attached to the OID. */
+ uint32_t p_Oid; /**< Pointer to the OID. OID is encoded in BER but type and length are excluded. */
+ uint32_t resValOrPtr; /**< Value (for up to 4 octets) or pointer to the Value. Encoded in BER. */
+ uint32_t reserved;
+} t_OidsTblEntry;
+
+/**************************************************************************//**
+ @Description Deep Sleep Auto Response SNMP IPv4 Addresses Table Entry
+ Refer to the FMan Controller spec for more details.
+*//***************************************************************************/
+typedef struct
+{
+ uint32_t ipv4Addr; /*!< 32 bit IPv4 Address. */
+ uint16_t vlanId; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */
+ /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */
+ uint16_t reserved;
+} t_DsarSnmpIpv4AddrTblEntry;
+
+/**************************************************************************//**
+ @Description Deep Sleep Auto Response SNMP IPv6 Addresses Table Entry
+ Refer to the FMan Controller spec for more details.
+*//***************************************************************************/
+#pragma pack(push,1)
+typedef struct
+{
+ uint32_t ipv6Addr[4]; /*!< 4 * 32 bit IPv6 Address. */
+ uint16_t vlanId; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */
+ /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */
+ uint16_t reserved;
+} t_DsarSnmpIpv6AddrTblEntry;
+#pragma pack(pop)
+
+/**************************************************************************//**
+@Description Deep Sleep Auto Response SNMP statistics table
+
+*//***************************************************************************/
+typedef struct {
+ uint32_t snmpErrCnt; /**< Counts SNMP errors (wrong version, BER encoding, format). */
+ uint32_t snmpCommunityErrCnt; /**< Counts messages that were dropped due to insufficient permission. */
+ uint32_t snmpTotalDiscardCnt; /**< Counts any message that was dropped. */
+ uint32_t snmpGetReqCnt; /**< Counts the number of get-request messages */
+ uint32_t snmpGetNextReqCnt; /**< Counts the number of get-next-request messages */
+} t_DsarSnmpStatistics;
+
+/**************************************************************************//**
+ @Description Deep Sleep Auto Response SNMP Descriptor
+
+*//***************************************************************************/
+typedef struct
+{
+ uint16_t control; /**< Control bits [0-15]. */
+ uint16_t maxSnmpMsgLength; /**< Maximal allowed SNMP message length. */
+ uint16_t numOfIpv4Addresses; /**< Number of entries in IPv4 addresses table. */
+ uint16_t numOfIpv6Addresses; /**< Number of entries in IPv6 addresses table. */
+ uint32_t p_Ipv4AddrTbl; /**< Pointer to IPv4 addresses table. */
+ uint32_t p_Ipv6AddrTbl; /**< Pointer to IPv6 addresses table. */
+ uint32_t p_RdOnlyCommunityStr; /**< Pointer to the Read Only Community String. */
+ uint32_t p_RdWrCommunityStr; /**< Pointer to the Read Write Community String. */
+ uint32_t p_OidsTbl; /**< Pointer to OIDs table. */
+ uint32_t oidsTblSize; /**< Number of entries in OIDs table. */
+ uint32_t p_Statistics; /**< Pointer to SNMP statistics table. */
+} t_DsarSnmpDescriptor;
+
+/**************************************************************************//**
+@Description Deep Sleep Auto Response (Common) Statistics
+
+*//***************************************************************************/
+typedef _Packed struct {
+ uint32_t dsarDiscarded;
+ uint32_t dsarErrDiscarded;
+ uint32_t dsarFragDiscarded;
+ uint32_t dsarTunnelDiscarded;
+ uint32_t dsarArpDiscarded;
+ uint32_t dsarIpDiscarded;
+ uint32_t dsarTcpDiscarded;
+ uint32_t dsarUdpDiscarded;
+ uint32_t dsarIcmpV6ChecksumErr; /* ICMPv6 Checksum Error counter */
+ uint32_t dsarIcmpV6OtherType; /* ICMPv6 'Other' type (not Echo or Neighbor Solicitaion/Advertisement counter */
+ uint32_t dsarIcmpV4OtherType; /* ICMPv4 'Other' type (not Echo) counter */
+} _PackedType t_ArStatistics;
+
+
+/**************************************************************************//**
+@Description Deep Sleep Auto Response TCP/UDP port filter table entry
+
+*//***************************************************************************/
+typedef _Packed struct {
+ uint32_t Ports;
+ uint32_t PortsMask;
+} _PackedType t_PortTblEntry;
+
+
+
+/**************************************************************************//**
+@Description Deep Sleep Auto Response Common Parameters Descriptor
+
+*//***************************************************************************/
+typedef _Packed struct {
+ uint8_t arTxPort; /* 0x00 0-7 Auto Response Transmit Port number */
+ uint8_t controlBits; /* 0x00 8-15 Auto Response control bits */
+ uint16_t res1; /* 0x00 16-31 Reserved */
+ uint32_t activeHPNIA; /* 0x04 0-31 Active mode Hardware Parser NIA */
+ uint16_t snmpPort; /* 0x08 0-15 SNMP Port. */
+ uint8_t macStationAddr[6]; /* 0x08 16-31 and 0x0C 0-31 MAC Station Address */
+ uint8_t res2; /* 0x10 0-7 Reserved */
+ uint8_t filterControl; /* 0x10 8-15 Filtering Control Bits. */
+ uint16_t tcpControlPass; /* 0x10 16-31 TCP control pass flags */
+ uint8_t ipProtocolTblSize; /* 0x14 0-7 IP Protocol Table Size. */
+ uint8_t udpPortTblSize; /* 0x14 8-15 UDP Port Table Size. */
+ uint8_t tcpPortTblSize; /* 0x14 16-23 TCP Port Table Size. */
+ uint8_t res3; /* 0x14 24-31 Reserved */
+ uint32_t p_IpProtocolFiltTbl; /* 0x18 0-31 Pointer to IP Protocol Filter Table */
+ uint32_t p_UdpPortFiltTbl; /* 0x1C 0-31 Pointer to UDP Port Filter Table */
+ uint32_t p_TcpPortFiltTbl; /* 0x20 0-31 Pointer to TCP Port Filter Table */
+ uint32_t res4; /* 0x24 Reserved */
+ uint32_t p_ArpDescriptor; /* 0x28 0-31 ARP Descriptor Pointer. */
+ uint32_t p_NdDescriptor; /* 0x2C 0-31 Neighbor Discovery Descriptor. */
+ uint32_t p_IcmpV4Descriptor; /* 0x30 0-31 ICMPv4 Descriptor pointer. */
+ uint32_t p_IcmpV6Descriptor; /* 0x34 0-31 ICMPv6 Descriptor pointer. */
+ uint32_t p_SnmpDescriptor; /* 0x38 0-31 SNMP Descriptor pointer. */
+ uint32_t p_ArStats; /* 0x3C 0-31 Pointer to Auto Response Statistics */
+} _PackedType t_ArCommonDesc;
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+/* t_ArCommonDesc.filterControl bits */
+#define IP_PROT_TBL_PASS_MASK 0x08
+#define UDP_PORT_TBL_PASS_MASK 0x04
+#define TCP_PORT_TBL_PASS_MASK 0x02
+
+/* Offset of TCF flags within TCP packet */
+#define TCP_FLAGS_OFFSET 12
+
+
+#endif /* __FM_PORT_DSAR_H_ */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port_im.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port_im.c
new file mode 100644
index 0000000..7f70cc9
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port_im.c
@@ -0,0 +1,754 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_port_im.c
+
+ @Description FM Port Independent-Mode ...
+*//***************************************************************************/
+#include "std_ext.h"
+#include "string_ext.h"
+#include "error_ext.h"
+#include "fm_muram_ext.h"
+
+#include "fm_port.h"
+
+
+#define TX_CONF_STATUS_UNSENT 0x1
+
+
+typedef enum e_TxConfType
+{
+ e_TX_CONF_TYPE_CHECK = 0 /**< check if all the buffers were touched by the muxator, no confirmation callback */
+ ,e_TX_CONF_TYPE_CALLBACK = 1 /**< confirm to user all the available sent buffers */
+ ,e_TX_CONF_TYPE_FLUSH = 3 /**< confirm all buffers plus the unsent one with an appropriate status */
+} e_TxConfType;
+
+
+static void ImException(t_Handle h_FmPort, uint32_t event)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ ASSERT_COND(((event & (IM_EV_RX | IM_EV_BSY)) && FmIsMaster(p_FmPort->h_Fm)) ||
+ !FmIsMaster(p_FmPort->h_Fm));
+
+ if (event & IM_EV_RX)
+ FmPortImRx(p_FmPort);
+ if ((event & IM_EV_BSY) && p_FmPort->f_Exception)
+ p_FmPort->f_Exception(p_FmPort->h_App, e_FM_PORT_EXCEPTION_IM_BUSY);
+}
+
+
+static t_Error TxConf(t_FmPort *p_FmPort, e_TxConfType confType)
+{
+ t_Error retVal = E_BUSY;
+ uint32_t bdStatus;
+ uint16_t savedStartBdId, confBdId;
+
+ ASSERT_COND(p_FmPort);
+
+ /*
+ if (confType==e_TX_CONF_TYPE_CHECK)
+ return (WfqEntryIsQueueEmpty(p_FmPort->im.h_WfqEntry) ? E_OK : E_BUSY);
+ */
+
+ confBdId = savedStartBdId = p_FmPort->im.currBdId;
+ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(confBdId));
+
+ /* If R bit is set, we don't enter, or we break.
+ we run till we get to R, or complete the loop */
+ while ((!(bdStatus & BD_R_E) || (confType == e_TX_CONF_TYPE_FLUSH)) && (retVal != E_OK))
+ {
+ if (confType & e_TX_CONF_TYPE_CALLBACK) /* if it is confirmation with user callbacks */
+ BD_STATUS_AND_LENGTH_SET(BD_GET(confBdId), 0);
+
+ /* case 1: R bit is 0 and Length is set -> confirm! */
+ if ((confType & e_TX_CONF_TYPE_CALLBACK) && (bdStatus & BD_LENGTH_MASK))
+ {
+ if (p_FmPort->im.f_TxConf)
+ {
+ if ((confType == e_TX_CONF_TYPE_FLUSH) && (bdStatus & BD_R_E))
+ p_FmPort->im.f_TxConf(p_FmPort->h_App,
+ BdBufferGet(XX_PhysToVirt, BD_GET(confBdId)),
+ TX_CONF_STATUS_UNSENT,
+ p_FmPort->im.p_BdShadow[confBdId]);
+ else
+ p_FmPort->im.f_TxConf(p_FmPort->h_App,
+ BdBufferGet(XX_PhysToVirt, BD_GET(confBdId)),
+ 0,
+ p_FmPort->im.p_BdShadow[confBdId]);
+ }
+ }
+ /* case 2: R bit is 0 and Length is 0 -> not used yet, nop! */
+
+ confBdId = GetNextBdId(p_FmPort, confBdId);
+ if (confBdId == savedStartBdId)
+ retVal = E_OK;
+ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(confBdId));
+ }
+
+ return retVal;
+}
+
+t_Error FmPortImEnable(t_FmPort *p_FmPort)
+{
+ uint32_t tmpReg = GET_UINT32(p_FmPort->im.p_FmPortImPram->mode);
+ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, (uint32_t)(tmpReg & ~IM_MODE_GRC_STP));
+ return E_OK;
+}
+
+t_Error FmPortImDisable(t_FmPort *p_FmPort)
+{
+ uint32_t tmpReg = GET_UINT32(p_FmPort->im.p_FmPortImPram->mode);
+ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, (uint32_t)(tmpReg | IM_MODE_GRC_STP));
+ return E_OK;
+}
+
+t_Error FmPortImRx(t_FmPort *p_FmPort)
+{
+ t_Handle h_CurrUserPriv, h_NewUserPriv;
+ uint32_t bdStatus;
+ volatile uint8_t buffPos;
+ uint16_t length;
+ uint16_t errors/*, reportErrors*/;
+ uint8_t *p_CurData, *p_Data;
+ uint32_t flags;
+
+ ASSERT_COND(p_FmPort);
+
+ flags = XX_LockIntrSpinlock(p_FmPort->h_Spinlock);
+ if (p_FmPort->lock)
+ {
+ XX_UnlockIntrSpinlock(p_FmPort->h_Spinlock, flags);
+ return E_OK;
+ }
+ p_FmPort->lock = TRUE;
+ XX_UnlockIntrSpinlock(p_FmPort->h_Spinlock, flags);
+
+ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId));
+
+ while (!(bdStatus & BD_R_E)) /* while there is data in the Rx BD */
+ {
+ if ((p_Data = p_FmPort->im.rxPool.f_GetBuf(p_FmPort->im.rxPool.h_BufferPool, &h_NewUserPriv)) == NULL)
+ {
+ p_FmPort->lock = FALSE;
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Data buffer"));
+ }
+
+ if (p_FmPort->im.firstBdOfFrameId == IM_ILEGAL_BD_ID)
+ p_FmPort->im.firstBdOfFrameId = p_FmPort->im.currBdId;
+
+ errors = 0;
+ p_CurData = BdBufferGet(p_FmPort->im.rxPool.f_PhysToVirt, BD_GET(p_FmPort->im.currBdId));
+ h_CurrUserPriv = p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId];
+ length = (uint16_t)((bdStatus & BD_L) ?
+ ((bdStatus & BD_LENGTH_MASK) - p_FmPort->im.rxFrameAccumLength):
+ (bdStatus & BD_LENGTH_MASK));
+ p_FmPort->im.rxFrameAccumLength += length;
+
+ /* determine whether buffer is first, last, first and last (single */
+ /* buffer frame) or middle (not first and not last) */
+ buffPos = (uint8_t)((p_FmPort->im.currBdId == p_FmPort->im.firstBdOfFrameId) ?
+ ((bdStatus & BD_L) ? SINGLE_BUF : FIRST_BUF) :
+ ((bdStatus & BD_L) ? LAST_BUF : MIDDLE_BUF));
+
+ if (bdStatus & BD_L)
+ {
+ p_FmPort->im.rxFrameAccumLength = 0;
+ p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID;
+ }
+
+ BdBufferSet(p_FmPort->im.rxPool.f_VirtToPhys, BD_GET(p_FmPort->im.currBdId), p_Data);
+
+ BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.currBdId), BD_R_E);
+
+ errors = (uint16_t)((bdStatus & BD_RX_ERRORS) >> 16);
+ p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId] = h_NewUserPriv;
+
+ p_FmPort->im.currBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId);
+ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.offsetOut, (uint16_t)(p_FmPort->im.currBdId<<4));
+ /* Pass the buffer if one of the conditions is true:
+ - There are no errors
+ - This is a part of a larger frame ( the application has already received some buffers )
+ - There is an error, but it was defined to be passed anyway. */
+ if ((buffPos != SINGLE_BUF) || !errors || (errors & (uint16_t)(BD_ERROR_PASS_FRAME>>16)))
+ {
+ if (p_FmPort->im.f_RxStore(p_FmPort->h_App,
+ p_CurData,
+ length,
+ errors,
+ buffPos,
+ h_CurrUserPriv) == e_RX_STORE_RESPONSE_PAUSE)
+ break;
+ }
+ else if (p_FmPort->im.rxPool.f_PutBuf(p_FmPort->im.rxPool.h_BufferPool,
+ p_CurData,
+ h_CurrUserPriv))
+ {
+ p_FmPort->lock = FALSE;
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Failed freeing data buffer"));
+ }
+
+ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId));
+ }
+ p_FmPort->lock = FALSE;
+ return E_OK;
+}
+
+void FmPortConfigIM (t_FmPort *p_FmPort, t_FmPortParams *p_FmPortParams)
+{
+ ASSERT_COND(p_FmPort);
+
+ SANITY_CHECK_RETURN(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->im.h_FmMuram = p_FmPortParams->specificParams.imRxTxParams.h_FmMuram;
+ p_FmPort->p_FmPortDriverParam->liodnOffset = p_FmPortParams->specificParams.imRxTxParams.liodnOffset;
+ p_FmPort->im.dataMemId = p_FmPortParams->specificParams.imRxTxParams.dataMemId;
+ p_FmPort->im.dataMemAttributes = p_FmPortParams->specificParams.imRxTxParams.dataMemAttributes;
+
+ p_FmPort->im.fwExtStructsMemId = DEFAULT_PORT_ImfwExtStructsMemId;
+ p_FmPort->im.fwExtStructsMemAttr = DEFAULT_PORT_ImfwExtStructsMemAttr;
+
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
+ {
+ p_FmPort->im.rxPool.h_BufferPool = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.h_BufferPool;
+ p_FmPort->im.rxPool.f_GetBuf = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_GetBuf;
+ p_FmPort->im.rxPool.f_PutBuf = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_PutBuf;
+ p_FmPort->im.rxPool.bufferSize = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.bufferSize;
+ p_FmPort->im.rxPool.f_PhysToVirt = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_PhysToVirt;
+ if (!p_FmPort->im.rxPool.f_PhysToVirt)
+ p_FmPort->im.rxPool.f_PhysToVirt = XX_PhysToVirt;
+ p_FmPort->im.rxPool.f_VirtToPhys = p_FmPortParams->specificParams.imRxTxParams.rxPoolParams.f_VirtToPhys;
+ if (!p_FmPort->im.rxPool.f_VirtToPhys)
+ p_FmPort->im.rxPool.f_VirtToPhys = XX_VirtToPhys;
+ p_FmPort->im.f_RxStore = p_FmPortParams->specificParams.imRxTxParams.f_RxStore;
+
+ p_FmPort->im.mrblr = 0x8000;
+ while (p_FmPort->im.mrblr)
+ {
+ if (p_FmPort->im.rxPool.bufferSize & p_FmPort->im.mrblr)
+ break;
+ p_FmPort->im.mrblr >>= 1;
+ }
+ if (p_FmPort->im.mrblr != p_FmPort->im.rxPool.bufferSize)
+ DBG(WARNING, ("Max-Rx-Buffer-Length set to %d", p_FmPort->im.mrblr));
+ p_FmPort->im.bdRingSize = DEFAULT_PORT_rxBdRingLength;
+ p_FmPort->exceptions = DEFAULT_PORT_exception;
+ if (FmIsMaster(p_FmPort->h_Fm))
+ p_FmPort->polling = FALSE;
+ else
+ p_FmPort->polling = TRUE;
+ p_FmPort->fmanCtrlEventId = (uint8_t)NO_IRQ;
+ }
+ else
+ {
+ p_FmPort->im.f_TxConf = p_FmPortParams->specificParams.imRxTxParams.f_TxConf;
+
+ p_FmPort->im.bdRingSize = DEFAULT_PORT_txBdRingLength;
+ }
+}
+
+t_Error FmPortImCheckInitParameters(t_FmPort *p_FmPort)
+{
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_TX) &&
+ (p_FmPort->portType != e_FM_PORT_TYPE_TX_10G))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, NO_MSG);
+
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
+ {
+ if (!POWER_OF_2(p_FmPort->im.mrblr))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("max Rx buffer length must be power of 2!!!"));
+ if (p_FmPort->im.mrblr < 256)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("max Rx buffer length must at least 256!!!"));
+ if (p_FmPort->p_FmPortDriverParam->liodnOffset & ~FM_LIODN_OFFSET_MASK)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("liodnOffset is larger than %d", FM_LIODN_OFFSET_MASK+1));
+ }
+
+ return E_OK;
+}
+
+t_Error FmPortImInit(t_FmPort *p_FmPort)
+{
+ t_FmImBd *p_Bd=NULL;
+ t_Handle h_BufContext;
+ uint64_t tmpPhysBase;
+ uint16_t log2Num;
+ uint8_t *p_Data/*, *p_Tmp*/;
+ int i;
+ t_Error err;
+ uint16_t tmpReg16;
+ uint32_t tmpReg32;
+
+ ASSERT_COND(p_FmPort);
+
+ p_FmPort->im.p_FmPortImPram =
+ (t_FmPortImPram *)FM_MURAM_AllocMem(p_FmPort->im.h_FmMuram, sizeof(t_FmPortImPram), IM_PRAM_ALIGN);
+ if (!p_FmPort->im.p_FmPortImPram)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Parameter-RAM!!!"));
+ WRITE_BLOCK(p_FmPort->im.p_FmPortImPram, 0, sizeof(t_FmPortImPram));
+
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
+ {
+ p_FmPort->im.p_BdRing =
+ (t_FmImBd *)XX_MallocSmart((uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize),
+ p_FmPort->im.fwExtStructsMemId,
+ 4);
+ if (!p_FmPort->im.p_BdRing)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Rx BD ring!!!"));
+ IOMemSet32(p_FmPort->im.p_BdRing, 0, (uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize));
+
+ p_FmPort->im.p_BdShadow = (t_Handle *)XX_Malloc((uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize));
+ if (!p_FmPort->im.p_BdShadow)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Rx BD shadow!!!"));
+ memset(p_FmPort->im.p_BdShadow, 0, (uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize));
+
+ /* Initialize the Rx-BD ring */
+ for (i=0; i<p_FmPort->im.bdRingSize; i++)
+ {
+ p_Bd = BD_GET(i);
+ BD_STATUS_AND_LENGTH_SET (p_Bd, BD_R_E);
+
+ if ((p_Data = p_FmPort->im.rxPool.f_GetBuf(p_FmPort->im.rxPool.h_BufferPool, &h_BufContext)) == NULL)
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Data buffer"));
+ BdBufferSet(p_FmPort->im.rxPool.f_VirtToPhys, p_Bd, p_Data);
+ p_FmPort->im.p_BdShadow[i] = h_BufContext;
+ }
+
+ if ((p_FmPort->im.dataMemAttributes & MEMORY_ATTR_CACHEABLE) ||
+ (p_FmPort->im.fwExtStructsMemAttr & MEMORY_ATTR_CACHEABLE))
+ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_GBL | IM_MODE_SET_BO(2));
+ else
+ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_SET_BO(2));
+
+ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->rxQdPtr,
+ (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) -
+ p_FmPort->fmMuramPhysBaseAddr + 0x20));
+
+ LOG2((uint64_t)p_FmPort->im.mrblr, log2Num);
+ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->mrblr, log2Num);
+
+ /* Initialize Rx QD */
+ tmpPhysBase = (uint64_t)(XX_VirtToPhys(p_FmPort->im.p_BdRing));
+ SET_ADDR(&p_FmPort->im.p_FmPortImPram->rxQd.bdRingBase, tmpPhysBase);
+ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.bdRingSize, (uint16_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize));
+
+ /* Update the IM PRAM address in the BMI */
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfqid,
+ (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) -
+ p_FmPort->fmMuramPhysBaseAddr));
+ if (!p_FmPort->polling || p_FmPort->exceptions)
+ {
+ /* Allocate, configure and register interrupts */
+ err = FmAllocFmanCtrlEventReg(p_FmPort->h_Fm, &p_FmPort->fmanCtrlEventId);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ ASSERT_COND(!(p_FmPort->fmanCtrlEventId & ~IM_RXQD_FPMEVT_SEL_MASK));
+ tmpReg16 = (uint16_t)(p_FmPort->fmanCtrlEventId & IM_RXQD_FPMEVT_SEL_MASK);
+ tmpReg32 = 0;
+
+ if (p_FmPort->exceptions & IM_EV_BSY)
+ {
+ tmpReg16 |= IM_RXQD_BSYINTM;
+ tmpReg32 |= IM_EV_BSY;
+ }
+ if (!p_FmPort->polling)
+ {
+ tmpReg16 |= IM_RXQD_RXFINTM;
+ tmpReg32 |= IM_EV_RX;
+ }
+ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, tmpReg16);
+
+ FmRegisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, ImException , (t_Handle)p_FmPort);
+
+ FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, tmpReg32);
+ }
+ else
+ p_FmPort->fmanCtrlEventId = (uint8_t)NO_IRQ;
+ }
+ else
+ {
+ p_FmPort->im.p_BdRing = (t_FmImBd *)XX_MallocSmart((uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize), p_FmPort->im.fwExtStructsMemId, 4);
+ if (!p_FmPort->im.p_BdRing)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Tx BD ring!!!"));
+ IOMemSet32(p_FmPort->im.p_BdRing, 0, (uint32_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize));
+
+ p_FmPort->im.p_BdShadow = (t_Handle *)XX_Malloc((uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize));
+ if (!p_FmPort->im.p_BdShadow)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("Independent-Mode Rx BD shadow!!!"));
+ memset(p_FmPort->im.p_BdShadow, 0, (uint32_t)(sizeof(t_Handle)*p_FmPort->im.bdRingSize));
+ p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID;
+
+ if ((p_FmPort->im.dataMemAttributes & MEMORY_ATTR_CACHEABLE) ||
+ (p_FmPort->im.fwExtStructsMemAttr & MEMORY_ATTR_CACHEABLE))
+ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_GBL | IM_MODE_SET_BO(2));
+ else
+ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->mode, IM_MODE_SET_BO(2));
+
+ WRITE_UINT32(p_FmPort->im.p_FmPortImPram->txQdPtr,
+ (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) -
+ p_FmPort->fmMuramPhysBaseAddr + 0x40));
+
+ /* Initialize Tx QD */
+ tmpPhysBase = (uint64_t)(XX_VirtToPhys(p_FmPort->im.p_BdRing));
+ SET_ADDR(&p_FmPort->im.p_FmPortImPram->txQd.bdRingBase, tmpPhysBase);
+ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->txQd.bdRingSize, (uint16_t)(sizeof(t_FmImBd)*p_FmPort->im.bdRingSize));
+
+ /* Update the IM PRAM address in the BMI */
+ WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfqid,
+ (uint32_t)((uint64_t)(XX_VirtToPhys(p_FmPort->im.p_FmPortImPram)) -
+ p_FmPort->fmMuramPhysBaseAddr));
+ }
+
+
+ return E_OK;
+}
+
+void FmPortImFree(t_FmPort *p_FmPort)
+{
+ uint32_t bdStatus;
+ uint8_t *p_CurData;
+
+ ASSERT_COND(p_FmPort);
+ ASSERT_COND(p_FmPort->im.p_FmPortImPram);
+
+ if ((p_FmPort->portType == e_FM_PORT_TYPE_RX) ||
+ (p_FmPort->portType == e_FM_PORT_TYPE_RX_10G))
+ {
+ if (!p_FmPort->polling || p_FmPort->exceptions)
+ {
+ /* Deallocate and unregister interrupts */
+ FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, 0);
+
+ FmFreeFmanCtrlEventReg(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId);
+
+ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, 0);
+
+ FmUnregisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId);
+ }
+ /* Try first clean what has received */
+ FmPortImRx(p_FmPort);
+
+ /* Now, get rid of the the empty buffer! */
+ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId));
+
+ while (bdStatus & BD_R_E) /* while there is data in the Rx BD */
+ {
+ p_CurData = BdBufferGet(p_FmPort->im.rxPool.f_PhysToVirt, BD_GET(p_FmPort->im.currBdId));
+
+ BdBufferSet(p_FmPort->im.rxPool.f_VirtToPhys, BD_GET(p_FmPort->im.currBdId), NULL);
+ BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.currBdId), 0);
+
+ p_FmPort->im.rxPool.f_PutBuf(p_FmPort->im.rxPool.h_BufferPool,
+ p_CurData,
+ p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId]);
+
+ p_FmPort->im.currBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId);
+ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId));
+ }
+ }
+ else
+ TxConf(p_FmPort, e_TX_CONF_TYPE_FLUSH);
+
+ FM_MURAM_FreeMem(p_FmPort->im.h_FmMuram, p_FmPort->im.p_FmPortImPram);
+
+ if (p_FmPort->im.p_BdShadow)
+ XX_Free(p_FmPort->im.p_BdShadow);
+
+ if (p_FmPort->im.p_BdRing)
+ XX_FreeSmart(p_FmPort->im.p_BdRing);
+}
+
+
+t_Error FM_PORT_ConfigIMMaxRxBufLength(t_Handle h_FmPort, uint16_t newVal)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->im.mrblr = newVal;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigIMRxBdRingLength(t_Handle h_FmPort, uint16_t newVal)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->im.bdRingSize = newVal;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigIMTxBdRingLength(t_Handle h_FmPort, uint16_t newVal)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->im.bdRingSize = newVal;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigIMFmanCtrlExternalStructsMemory(t_Handle h_FmPort,
+ uint8_t memId,
+ uint32_t memAttributes)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ p_FmPort->im.fwExtStructsMemId = memId;
+ p_FmPort->im.fwExtStructsMemAttr = memAttributes;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ConfigIMPolling(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ if ((p_FmPort->portType != e_FM_PORT_TYPE_RX_10G) && (p_FmPort->portType != e_FM_PORT_TYPE_RX))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Available for Rx ports only"));
+
+ if (!FmIsMaster(p_FmPort->h_Fm))
+ RETURN_ERROR(MAJOR, E_INVALID_OPERATION, ("Available on master-partition only;"
+ "in guest-partitions, IM is always in polling!"));
+
+ p_FmPort->polling = TRUE;
+
+ return E_OK;
+}
+
+t_Error FM_PORT_SetIMExceptions(t_Handle h_FmPort, e_FmPortExceptions exception, bool enable)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ t_Error err;
+ uint16_t tmpReg16;
+ uint32_t tmpReg32;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ if (exception == e_FM_PORT_EXCEPTION_IM_BUSY)
+ {
+ if (enable)
+ {
+ p_FmPort->exceptions |= IM_EV_BSY;
+ if (p_FmPort->fmanCtrlEventId == (uint8_t)NO_IRQ)
+ {
+ /* Allocate, configure and register interrupts */
+ err = FmAllocFmanCtrlEventReg(p_FmPort->h_Fm, &p_FmPort->fmanCtrlEventId);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ ASSERT_COND(!(p_FmPort->fmanCtrlEventId & ~IM_RXQD_FPMEVT_SEL_MASK));
+
+ FmRegisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, ImException, (t_Handle)p_FmPort);
+ tmpReg16 = (uint16_t)((p_FmPort->fmanCtrlEventId & IM_RXQD_FPMEVT_SEL_MASK) | IM_RXQD_BSYINTM);
+ tmpReg32 = IM_EV_BSY;
+ }
+ else
+ {
+ tmpReg16 = (uint16_t)(GET_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen) | IM_RXQD_BSYINTM);
+ tmpReg32 = FmGetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId) | IM_EV_BSY;
+ }
+
+ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, tmpReg16);
+ FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, tmpReg32);
+ }
+ else
+ {
+ p_FmPort->exceptions &= ~IM_EV_BSY;
+ if (!p_FmPort->exceptions && p_FmPort->polling)
+ {
+ FmFreeFmanCtrlEventReg(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId);
+ FmUnregisterFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId);
+ FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, 0);
+ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, 0);
+ p_FmPort->fmanCtrlEventId = (uint8_t)NO_IRQ;
+ }
+ else
+ {
+ tmpReg16 = (uint16_t)(GET_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen) & ~IM_RXQD_BSYINTM);
+ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->rxQd.gen, tmpReg16);
+ tmpReg32 = FmGetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId) & ~IM_EV_BSY;
+ FmSetFmanCtrlIntr(p_FmPort->h_Fm, p_FmPort->fmanCtrlEventId, tmpReg32);
+ }
+ }
+ }
+ else
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("Invalid exception."));
+
+ return E_OK;
+}
+
+t_Error FM_PORT_ImTx( t_Handle h_FmPort,
+ uint8_t *p_Data,
+ uint16_t length,
+ bool lastBuffer,
+ t_Handle h_BufContext)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+ uint16_t nextBdId;
+ uint32_t bdStatus, nextBdStatus;
+ bool firstBuffer;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ bdStatus = BD_STATUS_AND_LENGTH(BD_GET(p_FmPort->im.currBdId));
+ nextBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId);
+ nextBdStatus = BD_STATUS_AND_LENGTH(BD_GET(nextBdId));
+
+ if (!(bdStatus & BD_R_E) && !(nextBdStatus & BD_R_E))
+ {
+ /* Confirm the current BD - BD is available */
+ if ((bdStatus & BD_LENGTH_MASK) && (p_FmPort->im.f_TxConf))
+ p_FmPort->im.f_TxConf (p_FmPort->h_App,
+ BdBufferGet(XX_PhysToVirt, BD_GET(p_FmPort->im.currBdId)),
+ 0,
+ p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId]);
+
+ bdStatus = length;
+
+ /* if this is the first BD of a frame */
+ if (p_FmPort->im.firstBdOfFrameId == IM_ILEGAL_BD_ID)
+ {
+ firstBuffer = TRUE;
+ p_FmPort->im.txFirstBdStatus = (bdStatus | BD_R_E);
+
+ if (!lastBuffer)
+ p_FmPort->im.firstBdOfFrameId = p_FmPort->im.currBdId;
+ }
+ else
+ firstBuffer = FALSE;
+
+ BdBufferSet(XX_VirtToPhys, BD_GET(p_FmPort->im.currBdId), p_Data);
+ p_FmPort->im.p_BdShadow[p_FmPort->im.currBdId] = h_BufContext;
+
+ /* deal with last */
+ if (lastBuffer)
+ {
+ /* if single buffer frame */
+ if (firstBuffer)
+ BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.currBdId), p_FmPort->im.txFirstBdStatus | BD_L);
+ else
+ {
+ /* Set the last BD of the frame */
+ BD_STATUS_AND_LENGTH_SET (BD_GET(p_FmPort->im.currBdId), (bdStatus | BD_R_E | BD_L));
+ /* Set the first BD of the frame */
+ BD_STATUS_AND_LENGTH_SET(BD_GET(p_FmPort->im.firstBdOfFrameId), p_FmPort->im.txFirstBdStatus);
+ p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID;
+ }
+ WRITE_UINT16(p_FmPort->im.p_FmPortImPram->txQd.offsetIn, (uint16_t)(GetNextBdId(p_FmPort, p_FmPort->im.currBdId)<<4));
+ }
+ else if (!firstBuffer) /* mid frame buffer */
+ BD_STATUS_AND_LENGTH_SET (BD_GET(p_FmPort->im.currBdId), bdStatus | BD_R_E);
+
+ p_FmPort->im.currBdId = GetNextBdId(p_FmPort, p_FmPort->im.currBdId);
+ }
+ else
+ {
+ /* Discard current frame. Return error. */
+ if (p_FmPort->im.firstBdOfFrameId != IM_ILEGAL_BD_ID)
+ {
+ /* Error: No free BD */
+ /* Response: Discard current frame. Return error. */
+ uint16_t cleanBdId = p_FmPort->im.firstBdOfFrameId;
+
+ ASSERT_COND(p_FmPort->im.firstBdOfFrameId != p_FmPort->im.currBdId);
+
+ /* Since firstInFrame is not NULL, one buffer at least has already been
+ inserted into the BD ring. Using do-while covers the situation of a
+ frame spanned throughout the whole Tx BD ring (p_CleanBd is incremented
+ prior to testing whether or not it's equal to TxBd). */
+ do
+ {
+ BD_STATUS_AND_LENGTH_SET(BD_GET(cleanBdId), 0);
+ /* Advance BD pointer */
+ cleanBdId = GetNextBdId(p_FmPort, cleanBdId);
+ } while (cleanBdId != p_FmPort->im.currBdId);
+
+ p_FmPort->im.currBdId = cleanBdId;
+ p_FmPort->im.firstBdOfFrameId = IM_ILEGAL_BD_ID;
+ }
+
+ return ERROR_CODE(E_FULL);
+ }
+
+ return E_OK;
+}
+
+void FM_PORT_ImTxConf(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN(p_FmPort->imEn, E_INVALID_STATE);
+ SANITY_CHECK_RETURN(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ TxConf(p_FmPort, e_TX_CONF_TYPE_CALLBACK);
+}
+
+t_Error FM_PORT_ImRx(t_Handle h_FmPort)
+{
+ t_FmPort *p_FmPort = (t_FmPort*)h_FmPort;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmPort->imEn, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_HANDLE);
+
+ return FmPortImRx(p_FmPort);
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fman_port.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fman_port.c
new file mode 100755
index 0000000..ec261c4
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fman_port.c
@@ -0,0 +1,1574 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "common/general.h"
+
+#include "fman_common.h"
+#include "fsl_fman_port.h"
+
+
+/* problem Eyal: the following should not be here*/
+#define NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_ENQ_FRAME 0x00000028
+
+static uint32_t get_no_pcd_nia_bmi_ac_enc_frame(struct fman_port_cfg *cfg)
+{
+ if (cfg->errata_A006675)
+ return NIA_ENG_FM_CTL |
+ NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_ENQ_FRAME;
+ else
+ return NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME;
+}
+
+static int init_bmi_rx(struct fman_port *port,
+ struct fman_port_cfg *cfg,
+ struct fman_port_params *params)
+{
+ struct fman_port_rx_bmi_regs *regs = &port->bmi_regs->rx;
+ uint32_t tmp;
+
+ /* Rx Configuration register */
+ tmp = 0;
+ if (port->im_en)
+ tmp |= BMI_PORT_CFG_IM;
+ else if (cfg->discard_override)
+ tmp |= BMI_PORT_CFG_FDOVR;
+ iowrite32be(tmp, &regs->fmbm_rcfg);
+
+ /* DMA attributes */
+ tmp = (uint32_t)cfg->dma_swap_data << BMI_DMA_ATTR_SWP_SHIFT;
+ if (cfg->dma_ic_stash_on)
+ tmp |= BMI_DMA_ATTR_IC_STASH_ON;
+ if (cfg->dma_header_stash_on)
+ tmp |= BMI_DMA_ATTR_HDR_STASH_ON;
+ if (cfg->dma_sg_stash_on)
+ tmp |= BMI_DMA_ATTR_SG_STASH_ON;
+ if (cfg->dma_write_optimize)
+ tmp |= BMI_DMA_ATTR_WRITE_OPTIMIZE;
+ iowrite32be(tmp, &regs->fmbm_rda);
+
+ /* Rx FIFO parameters */
+ tmp = (cfg->rx_pri_elevation / FMAN_PORT_BMI_FIFO_UNITS - 1) <<
+ BMI_RX_FIFO_PRI_ELEVATION_SHIFT;
+ tmp |= cfg->rx_fifo_thr / FMAN_PORT_BMI_FIFO_UNITS - 1;
+ iowrite32be(tmp, &regs->fmbm_rfp);
+
+ if (cfg->excessive_threshold_register)
+ /* always allow access to the extra resources */
+ iowrite32be(BMI_RX_FIFO_THRESHOLD_ETHE, &regs->fmbm_reth);
+
+ /* Frame end data */
+ tmp = (uint32_t)cfg->checksum_bytes_ignore <<
+ BMI_RX_FRAME_END_CS_IGNORE_SHIFT;
+ tmp |= (uint32_t)cfg->rx_cut_end_bytes <<
+ BMI_RX_FRAME_END_CUT_SHIFT;
+ if (cfg->errata_A006320)
+ tmp &= 0xffe0ffff;
+ iowrite32be(tmp, &regs->fmbm_rfed);
+
+ /* Internal context parameters */
+ tmp = ((uint32_t)cfg->ic_ext_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+ BMI_IC_TO_EXT_SHIFT;
+ tmp |= ((uint32_t)cfg->ic_int_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+ BMI_IC_FROM_INT_SHIFT;
+ tmp |= cfg->ic_size / FMAN_PORT_IC_OFFSET_UNITS;
+ iowrite32be(tmp, &regs->fmbm_ricp);
+
+ /* Internal buffer offset */
+ tmp = ((uint32_t)cfg->int_buf_start_margin / FMAN_PORT_IC_OFFSET_UNITS)
+ << BMI_INT_BUF_MARG_SHIFT;
+ iowrite32be(tmp, &regs->fmbm_rim);
+
+ /* External buffer margins */
+ if (!port->im_en)
+ {
+ tmp = (uint32_t)cfg->ext_buf_start_margin <<
+ BMI_EXT_BUF_MARG_START_SHIFT;
+ tmp |= (uint32_t)cfg->ext_buf_end_margin;
+ if (cfg->fmbm_rebm_has_sgd && cfg->no_scatter_gather)
+ tmp |= BMI_SG_DISABLE;
+ iowrite32be(tmp, &regs->fmbm_rebm);
+ }
+
+ /* Frame attributes */
+ tmp = BMI_CMD_RX_MR_DEF;
+ if (!port->im_en)
+ {
+ tmp |= BMI_CMD_ATTR_ORDER;
+ tmp |= (uint32_t)cfg->color << BMI_CMD_ATTR_COLOR_SHIFT;
+ if (cfg->sync_req)
+ tmp |= BMI_CMD_ATTR_SYNC;
+ }
+ iowrite32be(tmp, &regs->fmbm_rfca);
+
+ /* NIA */
+ if (port->im_en)
+ tmp = NIA_ENG_FM_CTL | NIA_FM_CTL_AC_IND_MODE_RX;
+ else
+ {
+ tmp = (uint32_t)cfg->rx_fd_bits << BMI_NEXT_ENG_FD_BITS_SHIFT;
+ tmp |= get_no_pcd_nia_bmi_ac_enc_frame(cfg);
+ }
+ iowrite32be(tmp, &regs->fmbm_rfne);
+
+ /* Enqueue NIA */
+ iowrite32be(NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR, &regs->fmbm_rfene);
+
+ /* Default/error queues */
+ if (!port->im_en)
+ {
+ iowrite32be((params->dflt_fqid & 0x00FFFFFF), &regs->fmbm_rfqid);
+ iowrite32be((params->err_fqid & 0x00FFFFFF), &regs->fmbm_refqid);
+ }
+
+ /* Discard/error masks */
+ iowrite32be(params->discard_mask, &regs->fmbm_rfsdm);
+ iowrite32be(params->err_mask, &regs->fmbm_rfsem);
+
+ /* Statistics counters */
+ tmp = 0;
+ if (cfg->stats_counters_enable)
+ tmp = BMI_COUNTERS_EN;
+ iowrite32be(tmp, &regs->fmbm_rstc);
+
+ /* Performance counters */
+ fman_port_set_perf_cnt_params(port, &cfg->perf_cnt_params);
+ tmp = 0;
+ if (cfg->perf_counters_enable)
+ tmp = BMI_COUNTERS_EN;
+ iowrite32be(tmp, &regs->fmbm_rpc);
+
+ return 0;
+}
+
+static int init_bmi_tx(struct fman_port *port,
+ struct fman_port_cfg *cfg,
+ struct fman_port_params *params)
+{
+ struct fman_port_tx_bmi_regs *regs = &port->bmi_regs->tx;
+ uint32_t tmp;
+
+ /* Tx Configuration register */
+ tmp = 0;
+ if (port->im_en)
+ tmp |= BMI_PORT_CFG_IM;
+ iowrite32be(tmp, &regs->fmbm_tcfg);
+
+ /* DMA attributes */
+ tmp = (uint32_t)cfg->dma_swap_data << BMI_DMA_ATTR_SWP_SHIFT;
+ if (cfg->dma_ic_stash_on)
+ tmp |= BMI_DMA_ATTR_IC_STASH_ON;
+ if (cfg->dma_header_stash_on)
+ tmp |= BMI_DMA_ATTR_HDR_STASH_ON;
+ if (cfg->dma_sg_stash_on)
+ tmp |= BMI_DMA_ATTR_SG_STASH_ON;
+ iowrite32be(tmp, &regs->fmbm_tda);
+
+ /* Tx FIFO parameters */
+ tmp = (cfg->tx_fifo_min_level / FMAN_PORT_BMI_FIFO_UNITS) <<
+ BMI_TX_FIFO_MIN_FILL_SHIFT;
+ tmp |= ((uint32_t)cfg->tx_fifo_deq_pipeline_depth - 1) <<
+ BMI_FIFO_PIPELINE_DEPTH_SHIFT;
+ tmp |= (uint32_t)(cfg->tx_fifo_low_comf_level /
+ FMAN_PORT_BMI_FIFO_UNITS - 1);
+ iowrite32be(tmp, &regs->fmbm_tfp);
+
+ /* Frame end data */
+ tmp = (uint32_t)cfg->checksum_bytes_ignore <<
+ BMI_FRAME_END_CS_IGNORE_SHIFT;
+ iowrite32be(tmp, &regs->fmbm_tfed);
+
+ /* Internal context parameters */
+ if (!port->im_en)
+ {
+ tmp = ((uint32_t)cfg->ic_ext_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+ BMI_IC_TO_EXT_SHIFT;
+ tmp |= ((uint32_t)cfg->ic_int_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+ BMI_IC_FROM_INT_SHIFT;
+ tmp |= cfg->ic_size / FMAN_PORT_IC_OFFSET_UNITS;
+ iowrite32be(tmp, &regs->fmbm_ticp);
+ }
+ /* Frame attributes */
+ tmp = BMI_CMD_TX_MR_DEF;
+ if (port->im_en)
+ tmp |= BMI_CMD_MR_DEAS;
+ else
+ {
+ tmp |= BMI_CMD_ATTR_ORDER;
+ tmp |= (uint32_t)cfg->color << BMI_CMD_ATTR_COLOR_SHIFT;
+ }
+ iowrite32be(tmp, &regs->fmbm_tfca);
+
+ /* Dequeue NIA + enqueue NIA */
+ if (port->im_en)
+ {
+ iowrite32be(NIA_ENG_FM_CTL | NIA_FM_CTL_AC_IND_MODE_TX, &regs->fmbm_tfdne);
+ iowrite32be(NIA_ENG_FM_CTL | NIA_FM_CTL_AC_IND_MODE_TX, &regs->fmbm_tfene);
+ }
+ else
+ {
+ iowrite32be(NIA_ENG_QMI_DEQ, &regs->fmbm_tfdne);
+ iowrite32be(NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR, &regs->fmbm_tfene);
+ if (cfg->fmbm_tfne_has_features)
+ iowrite32be(!params->dflt_fqid ?
+ BMI_EBD_EN | NIA_BMI_AC_FETCH_ALL_FRAME :
+ NIA_BMI_AC_FETCH_ALL_FRAME, &regs->fmbm_tfne);
+ if (!params->dflt_fqid && params->dont_release_buf)
+ {
+ iowrite32be(0x00FFFFFF, &regs->fmbm_tcfqid);
+ iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE, &regs->fmbm_tfene);
+ if (cfg->fmbm_tfne_has_features)
+ iowrite32be(ioread32be(&regs->fmbm_tfne) & ~BMI_EBD_EN, &regs->fmbm_tfne);
+ }
+ }
+
+ /* Confirmation/error queues */
+ if (!port->im_en)
+ {
+ if (params->dflt_fqid || !params->dont_release_buf)
+ iowrite32be(params->dflt_fqid & 0x00FFFFFF, &regs->fmbm_tcfqid);
+ iowrite32be((params->err_fqid & 0x00FFFFFF), &regs->fmbm_tefqid);
+ }
+ /* Statistics counters */
+ tmp = 0;
+ if (cfg->stats_counters_enable)
+ tmp = BMI_COUNTERS_EN;
+ iowrite32be(tmp, &regs->fmbm_tstc);
+
+ /* Performance counters */
+ fman_port_set_perf_cnt_params(port, &cfg->perf_cnt_params);
+ tmp = 0;
+ if (cfg->perf_counters_enable)
+ tmp = BMI_COUNTERS_EN;
+ iowrite32be(tmp, &regs->fmbm_tpc);
+
+ return 0;
+}
+
+static int init_bmi_oh(struct fman_port *port,
+ struct fman_port_cfg *cfg,
+ struct fman_port_params *params)
+{
+ struct fman_port_oh_bmi_regs *regs = &port->bmi_regs->oh;
+ uint32_t tmp;
+
+ /* OP Configuration register */
+ tmp = 0;
+ if (cfg->discard_override)
+ tmp |= BMI_PORT_CFG_FDOVR;
+ iowrite32be(tmp, &regs->fmbm_ocfg);
+
+ /* DMA attributes */
+ tmp = (uint32_t)cfg->dma_swap_data << BMI_DMA_ATTR_SWP_SHIFT;
+ if (cfg->dma_ic_stash_on)
+ tmp |= BMI_DMA_ATTR_IC_STASH_ON;
+ if (cfg->dma_header_stash_on)
+ tmp |= BMI_DMA_ATTR_HDR_STASH_ON;
+ if (cfg->dma_sg_stash_on)
+ tmp |= BMI_DMA_ATTR_SG_STASH_ON;
+ if (cfg->dma_write_optimize)
+ tmp |= BMI_DMA_ATTR_WRITE_OPTIMIZE;
+ iowrite32be(tmp, &regs->fmbm_oda);
+
+ /* Tx FIFO parameters */
+ tmp = ((uint32_t)cfg->tx_fifo_deq_pipeline_depth - 1) <<
+ BMI_FIFO_PIPELINE_DEPTH_SHIFT;
+ iowrite32be(tmp, &regs->fmbm_ofp);
+
+ /* Internal context parameters */
+ tmp = ((uint32_t)cfg->ic_ext_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+ BMI_IC_TO_EXT_SHIFT;
+ tmp |= ((uint32_t)cfg->ic_int_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+ BMI_IC_FROM_INT_SHIFT;
+ tmp |= cfg->ic_size / FMAN_PORT_IC_OFFSET_UNITS;
+ iowrite32be(tmp, &regs->fmbm_oicp);
+
+ /* Frame attributes */
+ tmp = BMI_CMD_OP_MR_DEF;
+ tmp |= (uint32_t)cfg->color << BMI_CMD_ATTR_COLOR_SHIFT;
+ if (cfg->sync_req)
+ tmp |= BMI_CMD_ATTR_SYNC;
+ if (port->type == E_FMAN_PORT_TYPE_OP)
+ tmp |= BMI_CMD_ATTR_ORDER;
+ iowrite32be(tmp, &regs->fmbm_ofca);
+
+ /* Internal buffer offset */
+ tmp = ((uint32_t)cfg->int_buf_start_margin / FMAN_PORT_IC_OFFSET_UNITS)
+ << BMI_INT_BUF_MARG_SHIFT;
+ iowrite32be(tmp, &regs->fmbm_oim);
+
+ /* Dequeue NIA */
+ iowrite32be(NIA_ENG_QMI_DEQ, &regs->fmbm_ofdne);
+
+ /* NIA and Enqueue NIA */
+ if (port->type == E_FMAN_PORT_TYPE_HC) {
+ iowrite32be(NIA_ENG_FM_CTL | NIA_FM_CTL_AC_HC,
+ &regs->fmbm_ofne);
+ iowrite32be(NIA_ENG_QMI_ENQ, &regs->fmbm_ofene);
+ } else {
+ iowrite32be(get_no_pcd_nia_bmi_ac_enc_frame(cfg),
+ &regs->fmbm_ofne);
+ iowrite32be(NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR,
+ &regs->fmbm_ofene);
+ }
+
+ /* Default/error queues */
+ iowrite32be((params->dflt_fqid & 0x00FFFFFF), &regs->fmbm_ofqid);
+ iowrite32be((params->err_fqid & 0x00FFFFFF), &regs->fmbm_oefqid);
+
+ /* Discard/error masks */
+ if (port->type == E_FMAN_PORT_TYPE_OP) {
+ iowrite32be(params->discard_mask, &regs->fmbm_ofsdm);
+ iowrite32be(params->err_mask, &regs->fmbm_ofsem);
+ }
+
+ /* Statistics counters */
+ tmp = 0;
+ if (cfg->stats_counters_enable)
+ tmp = BMI_COUNTERS_EN;
+ iowrite32be(tmp, &regs->fmbm_ostc);
+
+ /* Performance counters */
+ fman_port_set_perf_cnt_params(port, &cfg->perf_cnt_params);
+ tmp = 0;
+ if (cfg->perf_counters_enable)
+ tmp = BMI_COUNTERS_EN;
+ iowrite32be(tmp, &regs->fmbm_opc);
+
+ return 0;
+}
+
+static int init_qmi(struct fman_port *port,
+ struct fman_port_cfg *cfg,
+ struct fman_port_params *params)
+{
+ struct fman_port_qmi_regs *regs = port->qmi_regs;
+ uint32_t tmp;
+
+ tmp = 0;
+ if (cfg->queue_counters_enable)
+ tmp |= QMI_PORT_CFG_EN_COUNTERS;
+ iowrite32be(tmp, &regs->fmqm_pnc);
+
+ /* Rx port configuration */
+ if ((port->type == E_FMAN_PORT_TYPE_RX) ||
+ (port->type == E_FMAN_PORT_TYPE_RX_10G)) {
+ /* Enqueue NIA */
+ iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_RELEASE, &regs->fmqm_pnen);
+ return 0;
+ }
+
+ /* Continue with Tx and O/H port configuration */
+ if ((port->type == E_FMAN_PORT_TYPE_TX) ||
+ (port->type == E_FMAN_PORT_TYPE_TX_10G)) {
+ /* Enqueue NIA */
+ iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE,
+ &regs->fmqm_pnen);
+ /* Dequeue NIA */
+ iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_TX, &regs->fmqm_pndn);
+ } else {
+ /* Enqueue NIA */
+ iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_RELEASE, &regs->fmqm_pnen);
+ /* Dequeue NIA */
+ iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_FETCH, &regs->fmqm_pndn);
+ }
+
+ /* Dequeue Configuration register */
+ tmp = 0;
+ if (cfg->deq_high_pri)
+ tmp |= QMI_DEQ_CFG_PRI;
+
+ switch (cfg->deq_type) {
+ case E_FMAN_PORT_DEQ_BY_PRI:
+ tmp |= QMI_DEQ_CFG_TYPE1;
+ break;
+ case E_FMAN_PORT_DEQ_ACTIVE_FQ:
+ tmp |= QMI_DEQ_CFG_TYPE2;
+ break;
+ case E_FMAN_PORT_DEQ_ACTIVE_FQ_NO_ICS:
+ tmp |= QMI_DEQ_CFG_TYPE3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (cfg->qmi_deq_options_support) {
+ if ((port->type == E_FMAN_PORT_TYPE_HC) &&
+ (cfg->deq_prefetch_opt != E_FMAN_PORT_DEQ_NO_PREFETCH))
+ return -EINVAL;
+
+ switch (cfg->deq_prefetch_opt) {
+ case E_FMAN_PORT_DEQ_NO_PREFETCH:
+ break;
+ case E_FMAN_PORT_DEQ_PART_PREFETCH:
+ tmp |= QMI_DEQ_CFG_PREFETCH_PARTIAL;
+ break;
+ case E_FMAN_PORT_DEQ_FULL_PREFETCH:
+ tmp |= QMI_DEQ_CFG_PREFETCH_FULL;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+ tmp |= (uint32_t)(params->deq_sp & QMI_DEQ_CFG_SP_MASK) <<
+ QMI_DEQ_CFG_SP_SHIFT;
+ tmp |= cfg->deq_byte_cnt;
+ iowrite32be(tmp, &regs->fmqm_pndc);
+
+ return 0;
+}
+
+static void get_rx_stats_reg(struct fman_port *port,
+ enum fman_port_stats_counters counter,
+ uint32_t **stats_reg)
+{
+ struct fman_port_rx_bmi_regs *regs = &port->bmi_regs->rx;
+
+ switch (counter) {
+ case E_FMAN_PORT_STATS_CNT_FRAME:
+ *stats_reg = &regs->fmbm_rfrc;
+ break;
+ case E_FMAN_PORT_STATS_CNT_DISCARD:
+ *stats_reg = &regs->fmbm_rfdc;
+ break;
+ case E_FMAN_PORT_STATS_CNT_DEALLOC_BUF:
+ *stats_reg = &regs->fmbm_rbdc;
+ break;
+ case E_FMAN_PORT_STATS_CNT_RX_BAD_FRAME:
+ *stats_reg = &regs->fmbm_rfbc;
+ break;
+ case E_FMAN_PORT_STATS_CNT_RX_LARGE_FRAME:
+ *stats_reg = &regs->fmbm_rlfc;
+ break;
+ case E_FMAN_PORT_STATS_CNT_RX_OUT_OF_BUF:
+ *stats_reg = &regs->fmbm_rodc;
+ break;
+ case E_FMAN_PORT_STATS_CNT_FILTERED_FRAME:
+ *stats_reg = &regs->fmbm_rffc;
+ break;
+ case E_FMAN_PORT_STATS_CNT_DMA_ERR:
+ *stats_reg = &regs->fmbm_rfldec;
+ break;
+ default:
+ *stats_reg = NULL;
+ }
+}
+
+static void get_tx_stats_reg(struct fman_port *port,
+ enum fman_port_stats_counters counter,
+ uint32_t **stats_reg)
+{
+ struct fman_port_tx_bmi_regs *regs = &port->bmi_regs->tx;
+
+ switch (counter) {
+ case E_FMAN_PORT_STATS_CNT_FRAME:
+ *stats_reg = &regs->fmbm_tfrc;
+ break;
+ case E_FMAN_PORT_STATS_CNT_DISCARD:
+ *stats_reg = &regs->fmbm_tfdc;
+ break;
+ case E_FMAN_PORT_STATS_CNT_DEALLOC_BUF:
+ *stats_reg = &regs->fmbm_tbdc;
+ break;
+ case E_FMAN_PORT_STATS_CNT_LEN_ERR:
+ *stats_reg = &regs->fmbm_tfledc;
+ break;
+ case E_FMAN_PORT_STATS_CNT_UNSUPPORTED_FORMAT:
+ *stats_reg = &regs->fmbm_tfufdc;
+ break;
+ default:
+ *stats_reg = NULL;
+ }
+}
+
+static void get_oh_stats_reg(struct fman_port *port,
+ enum fman_port_stats_counters counter,
+ uint32_t **stats_reg)
+{
+ struct fman_port_oh_bmi_regs *regs = &port->bmi_regs->oh;
+
+ switch (counter) {
+ case E_FMAN_PORT_STATS_CNT_FRAME:
+ *stats_reg = &regs->fmbm_ofrc;
+ break;
+ case E_FMAN_PORT_STATS_CNT_DISCARD:
+ *stats_reg = &regs->fmbm_ofdc;
+ break;
+ case E_FMAN_PORT_STATS_CNT_DEALLOC_BUF:
+ *stats_reg = &regs->fmbm_obdc;
+ break;
+ case E_FMAN_PORT_STATS_CNT_FILTERED_FRAME:
+ *stats_reg = &regs->fmbm_offc;
+ break;
+ case E_FMAN_PORT_STATS_CNT_DMA_ERR:
+ *stats_reg = &regs->fmbm_ofldec;
+ break;
+ case E_FMAN_PORT_STATS_CNT_LEN_ERR:
+ *stats_reg = &regs->fmbm_ofledc;
+ break;
+ case E_FMAN_PORT_STATS_CNT_UNSUPPORTED_FORMAT:
+ *stats_reg = &regs->fmbm_ofufdc;
+ break;
+ case E_FMAN_PORT_STATS_CNT_WRED_DISCARD:
+ *stats_reg = &regs->fmbm_ofwdc;
+ break;
+ default:
+ *stats_reg = NULL;
+ }
+}
+
+static void get_rx_perf_reg(struct fman_port *port,
+ enum fman_port_perf_counters counter,
+ uint32_t **perf_reg)
+{
+ struct fman_port_rx_bmi_regs *regs = &port->bmi_regs->rx;
+
+ switch (counter) {
+ case E_FMAN_PORT_PERF_CNT_CYCLE:
+ *perf_reg = &regs->fmbm_rccn;
+ break;
+ case E_FMAN_PORT_PERF_CNT_TASK_UTIL:
+ *perf_reg = &regs->fmbm_rtuc;
+ break;
+ case E_FMAN_PORT_PERF_CNT_QUEUE_UTIL:
+ *perf_reg = &regs->fmbm_rrquc;
+ break;
+ case E_FMAN_PORT_PERF_CNT_DMA_UTIL:
+ *perf_reg = &regs->fmbm_rduc;
+ break;
+ case E_FMAN_PORT_PERF_CNT_FIFO_UTIL:
+ *perf_reg = &regs->fmbm_rfuc;
+ break;
+ case E_FMAN_PORT_PERF_CNT_RX_PAUSE:
+ *perf_reg = &regs->fmbm_rpac;
+ break;
+ default:
+ *perf_reg = NULL;
+ }
+}
+
+static void get_tx_perf_reg(struct fman_port *port,
+ enum fman_port_perf_counters counter,
+ uint32_t **perf_reg)
+{
+ struct fman_port_tx_bmi_regs *regs = &port->bmi_regs->tx;
+
+ switch (counter) {
+ case E_FMAN_PORT_PERF_CNT_CYCLE:
+ *perf_reg = &regs->fmbm_tccn;
+ break;
+ case E_FMAN_PORT_PERF_CNT_TASK_UTIL:
+ *perf_reg = &regs->fmbm_ttuc;
+ break;
+ case E_FMAN_PORT_PERF_CNT_QUEUE_UTIL:
+ *perf_reg = &regs->fmbm_ttcquc;
+ break;
+ case E_FMAN_PORT_PERF_CNT_DMA_UTIL:
+ *perf_reg = &regs->fmbm_tduc;
+ break;
+ case E_FMAN_PORT_PERF_CNT_FIFO_UTIL:
+ *perf_reg = &regs->fmbm_tfuc;
+ break;
+ default:
+ *perf_reg = NULL;
+ }
+}
+
+static void get_oh_perf_reg(struct fman_port *port,
+ enum fman_port_perf_counters counter,
+ uint32_t **perf_reg)
+{
+ struct fman_port_oh_bmi_regs *regs = &port->bmi_regs->oh;
+
+ switch (counter) {
+ case E_FMAN_PORT_PERF_CNT_CYCLE:
+ *perf_reg = &regs->fmbm_occn;
+ break;
+ case E_FMAN_PORT_PERF_CNT_TASK_UTIL:
+ *perf_reg = &regs->fmbm_otuc;
+ break;
+ case E_FMAN_PORT_PERF_CNT_DMA_UTIL:
+ *perf_reg = &regs->fmbm_oduc;
+ break;
+ case E_FMAN_PORT_PERF_CNT_FIFO_UTIL:
+ *perf_reg = &regs->fmbm_ofuc;
+ break;
+ default:
+ *perf_reg = NULL;
+ }
+}
+
+static void get_qmi_counter_reg(struct fman_port *port,
+ enum fman_port_qmi_counters counter,
+ uint32_t **queue_reg)
+{
+ struct fman_port_qmi_regs *regs = port->qmi_regs;
+
+ switch (counter) {
+ case E_FMAN_PORT_ENQ_TOTAL:
+ *queue_reg = &regs->fmqm_pnetfc;
+ break;
+ case E_FMAN_PORT_DEQ_TOTAL:
+ if ((port->type == E_FMAN_PORT_TYPE_RX) ||
+ (port->type == E_FMAN_PORT_TYPE_RX_10G))
+ /* Counter not available for Rx ports */
+ *queue_reg = NULL;
+ else
+ *queue_reg = &regs->fmqm_pndtfc;
+ break;
+ case E_FMAN_PORT_DEQ_FROM_DFLT:
+ if ((port->type == E_FMAN_PORT_TYPE_RX) ||
+ (port->type == E_FMAN_PORT_TYPE_RX_10G))
+ /* Counter not available for Rx ports */
+ *queue_reg = NULL;
+ else
+ *queue_reg = &regs->fmqm_pndfdc;
+ break;
+ case E_FMAN_PORT_DEQ_CONFIRM:
+ if ((port->type == E_FMAN_PORT_TYPE_RX) ||
+ (port->type == E_FMAN_PORT_TYPE_RX_10G))
+ /* Counter not available for Rx ports */
+ *queue_reg = NULL;
+ else
+ *queue_reg = &regs->fmqm_pndcc;
+ break;
+ default:
+ *queue_reg = NULL;
+ }
+}
+
+void fman_port_defconfig(struct fman_port_cfg *cfg, enum fman_port_type type)
+{
+ cfg->dma_swap_data = E_FMAN_PORT_DMA_NO_SWAP;
+ cfg->dma_ic_stash_on = FALSE;
+ cfg->dma_header_stash_on = FALSE;
+ cfg->dma_sg_stash_on = FALSE;
+ cfg->dma_write_optimize = TRUE;
+ cfg->color = E_FMAN_PORT_COLOR_GREEN;
+ cfg->discard_override = FALSE;
+ cfg->checksum_bytes_ignore = 0;
+ cfg->rx_cut_end_bytes = 4;
+ cfg->rx_pri_elevation = ((0x3FF + 1) * FMAN_PORT_BMI_FIFO_UNITS);
+ cfg->rx_fifo_thr = ((0x3FF + 1) * FMAN_PORT_BMI_FIFO_UNITS);
+ cfg->rx_fd_bits = 0;
+ cfg->ic_ext_offset = 0;
+ cfg->ic_int_offset = 0;
+ cfg->ic_size = 0;
+ cfg->int_buf_start_margin = 0;
+ cfg->ext_buf_start_margin = 0;
+ cfg->ext_buf_end_margin = 0;
+ cfg->tx_fifo_min_level = 0;
+ cfg->tx_fifo_low_comf_level = (5 * KILOBYTE);
+ cfg->stats_counters_enable = TRUE;
+ cfg->perf_counters_enable = TRUE;
+ cfg->deq_type = E_FMAN_PORT_DEQ_BY_PRI;
+
+ if (type == E_FMAN_PORT_TYPE_HC) {
+ cfg->sync_req = FALSE;
+ cfg->deq_prefetch_opt = E_FMAN_PORT_DEQ_NO_PREFETCH;
+ } else {
+ cfg->sync_req = TRUE;
+ cfg->deq_prefetch_opt = E_FMAN_PORT_DEQ_FULL_PREFETCH;
+ }
+
+ if (type == E_FMAN_PORT_TYPE_TX_10G) {
+ cfg->tx_fifo_deq_pipeline_depth = 4;
+ cfg->deq_high_pri = TRUE;
+ cfg->deq_byte_cnt = 0x1400;
+ } else {
+ if ((type == E_FMAN_PORT_TYPE_HC) ||
+ (type == E_FMAN_PORT_TYPE_OP))
+ cfg->tx_fifo_deq_pipeline_depth = 2;
+ else
+ cfg->tx_fifo_deq_pipeline_depth = 1;
+
+ cfg->deq_high_pri = FALSE;
+ cfg->deq_byte_cnt = 0x400;
+ }
+ cfg->no_scatter_gather = DEFAULT_FMAN_SP_NO_SCATTER_GATHER;
+}
+
+static uint8_t fman_port_find_bpool(struct fman_port *port, uint8_t bpid)
+{
+ uint32_t *bp_reg, tmp;
+ uint8_t i, id;
+
+ /* Find the pool */
+ bp_reg = port->bmi_regs->rx.fmbm_ebmpi;
+ for (i = 0;
+ (i < port->ext_pools_num && (i < FMAN_PORT_MAX_EXT_POOLS_NUM));
+ i++) {
+ tmp = ioread32be(&bp_reg[i]);
+ id = (uint8_t)((tmp & BMI_EXT_BUF_POOL_ID_MASK) >>
+ BMI_EXT_BUF_POOL_ID_SHIFT);
+
+ if (id == bpid)
+ break;
+ }
+
+ return i;
+}
+
+int fman_port_init(struct fman_port *port,
+ struct fman_port_cfg *cfg,
+ struct fman_port_params *params)
+{
+ int err;
+
+ /* Init BMI registers */
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ err = init_bmi_rx(port, cfg, params);
+ break;
+ case E_FMAN_PORT_TYPE_TX:
+ case E_FMAN_PORT_TYPE_TX_10G:
+ err = init_bmi_tx(port, cfg, params);
+ break;
+ case E_FMAN_PORT_TYPE_OP:
+ case E_FMAN_PORT_TYPE_HC:
+ err = init_bmi_oh(port, cfg, params);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (err)
+ return err;
+
+ /* Init QMI registers */
+ if (!port->im_en)
+ {
+ err = init_qmi(port, cfg, params);
+ return err;
+ }
+ return 0;
+}
+
+int fman_port_enable(struct fman_port *port)
+{
+ uint32_t *bmi_cfg_reg, tmp;
+ bool rx_port;
+
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ bmi_cfg_reg = &port->bmi_regs->rx.fmbm_rcfg;
+ rx_port = TRUE;
+ break;
+ case E_FMAN_PORT_TYPE_TX:
+ case E_FMAN_PORT_TYPE_TX_10G:
+ bmi_cfg_reg = &port->bmi_regs->tx.fmbm_tcfg;
+ rx_port = FALSE;
+ break;
+ case E_FMAN_PORT_TYPE_OP:
+ case E_FMAN_PORT_TYPE_HC:
+ bmi_cfg_reg = &port->bmi_regs->oh.fmbm_ocfg;
+ rx_port = FALSE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Enable QMI */
+ if (!rx_port) {
+ tmp = ioread32be(&port->qmi_regs->fmqm_pnc) | QMI_PORT_CFG_EN;
+ iowrite32be(tmp, &port->qmi_regs->fmqm_pnc);
+ }
+
+ /* Enable BMI */
+ tmp = ioread32be(bmi_cfg_reg) | BMI_PORT_CFG_EN;
+ iowrite32be(tmp, bmi_cfg_reg);
+
+ return 0;
+}
+
+int fman_port_disable(const struct fman_port *port)
+{
+ uint32_t *bmi_cfg_reg, *bmi_status_reg, tmp;
+ bool rx_port, failure = FALSE;
+ int count;
+
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ bmi_cfg_reg = &port->bmi_regs->rx.fmbm_rcfg;
+ bmi_status_reg = &port->bmi_regs->rx.fmbm_rst;
+ rx_port = TRUE;
+ break;
+ case E_FMAN_PORT_TYPE_TX:
+ case E_FMAN_PORT_TYPE_TX_10G:
+ bmi_cfg_reg = &port->bmi_regs->tx.fmbm_tcfg;
+ bmi_status_reg = &port->bmi_regs->tx.fmbm_tst;
+ rx_port = FALSE;
+ break;
+ case E_FMAN_PORT_TYPE_OP:
+ case E_FMAN_PORT_TYPE_HC:
+ bmi_cfg_reg = &port->bmi_regs->oh.fmbm_ocfg;
+ bmi_status_reg = &port->bmi_regs->oh.fmbm_ost;
+ rx_port = FALSE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Disable QMI */
+ if (!rx_port) {
+ tmp = ioread32be(&port->qmi_regs->fmqm_pnc) & ~QMI_PORT_CFG_EN;
+ iowrite32be(tmp, &port->qmi_regs->fmqm_pnc);
+
+ /* Wait for QMI to finish FD handling */
+ count = 100;
+ do {
+ udelay(10);
+ tmp = ioread32be(&port->qmi_regs->fmqm_pns);
+ } while ((tmp & QMI_PORT_STATUS_DEQ_FD_BSY) && --count);
+
+ if (count == 0)
+ {
+ /* Timeout */
+ iowrite32be(ioread32be(&port->qmi_regs->fmqm_pnc) |
+ QMI_PORT_CFG_EN, &port->qmi_regs->fmqm_pnc);
+ failure = TRUE;
+ }
+ }
+
+ /* Disable BMI */
+ tmp = ioread32be(bmi_cfg_reg) & ~BMI_PORT_CFG_EN;
+ iowrite32be(tmp, bmi_cfg_reg);
+
+ /* Wait for graceful stop end */
+ count = 500;
+ do {
+ udelay(10);
+ tmp = ioread32be(bmi_status_reg);
+ } while ((tmp & BMI_PORT_STATUS_BSY) && --count);
+
+ if (count == 0)
+ {
+ /* Timeout */
+ iowrite32be(ioread32be(&port->qmi_regs->fmqm_pnc) |
+ QMI_PORT_CFG_EN, &port->qmi_regs->fmqm_pnc);
+ iowrite32be(ioread32be(bmi_cfg_reg) | BMI_PORT_CFG_EN,
+ bmi_cfg_reg);
+ failure = TRUE;
+ }
+
+ if (failure)
+ return -EBUSY;
+
+ return 0;
+}
+
+int fman_port_set_bpools(const struct fman_port *port,
+ const struct fman_port_bpools *bp)
+{
+ uint32_t tmp, *bp_reg, *bp_depl_reg;
+ uint8_t i, max_bp_num;
+ bool grp_depl_used = FALSE, rx_port;
+
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ max_bp_num = port->ext_pools_num;
+ rx_port = TRUE;
+ bp_reg = port->bmi_regs->rx.fmbm_ebmpi;
+ bp_depl_reg = &port->bmi_regs->rx.fmbm_mpd;
+ break;
+ case E_FMAN_PORT_TYPE_OP:
+ if (port->fm_rev_maj != 4)
+ return -EINVAL;
+ max_bp_num = FMAN_PORT_OBS_EXT_POOLS_NUM;
+ rx_port = FALSE;
+ bp_reg = port->bmi_regs->oh.fmbm_oebmpi;
+ bp_depl_reg = &port->bmi_regs->oh.fmbm_ompd;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (rx_port) {
+ /* Check buffers are provided in ascending order */
+ for (i = 0;
+ (i < (bp->count-1) && (i < FMAN_PORT_MAX_EXT_POOLS_NUM - 1));
+ i++) {
+ if (bp->bpool[i].size > bp->bpool[i+1].size)
+ return -EINVAL;
+ }
+ }
+
+ /* Set up external buffers pools */
+ for (i = 0; i < bp->count; i++) {
+ tmp = BMI_EXT_BUF_POOL_VALID;
+ tmp |= ((uint32_t)bp->bpool[i].bpid <<
+ BMI_EXT_BUF_POOL_ID_SHIFT) & BMI_EXT_BUF_POOL_ID_MASK;
+
+ if (rx_port) {
+ if (bp->counters_enable)
+ tmp |= BMI_EXT_BUF_POOL_EN_COUNTER;
+
+ if (bp->bpool[i].is_backup)
+ tmp |= BMI_EXT_BUF_POOL_BACKUP;
+
+ tmp |= (uint32_t)bp->bpool[i].size;
+ }
+
+ iowrite32be(tmp, &bp_reg[i]);
+ }
+
+ /* Clear unused pools */
+ for (i = bp->count; i < max_bp_num; i++)
+ iowrite32be(0, &bp_reg[i]);
+
+ /* Pools depletion */
+ tmp = 0;
+ for (i = 0; i < FMAN_PORT_MAX_EXT_POOLS_NUM; i++) {
+ if (bp->bpool[i].grp_bp_depleted) {
+ grp_depl_used = TRUE;
+ tmp |= 0x80000000 >> i;
+ }
+
+ if (bp->bpool[i].single_bp_depleted)
+ tmp |= 0x80 >> i;
+
+ if (bp->bpool[i].pfc_priorities_en)
+ tmp |= 0x0100 << i;
+ }
+
+ if (grp_depl_used)
+ tmp |= ((uint32_t)bp->grp_bp_depleted_num - 1) <<
+ BMI_POOL_DEP_NUM_OF_POOLS_SHIFT;
+
+ iowrite32be(tmp, bp_depl_reg);
+ return 0;
+}
+
+int fman_port_set_rate_limiter(struct fman_port *port,
+ struct fman_port_rate_limiter *rate_limiter)
+{
+ uint32_t *rate_limit_reg, *rate_limit_scale_reg;
+ uint32_t granularity, tmp;
+ uint8_t usec_bit, factor;
+
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_TX:
+ case E_FMAN_PORT_TYPE_TX_10G:
+ rate_limit_reg = &port->bmi_regs->tx.fmbm_trlmt;
+ rate_limit_scale_reg = &port->bmi_regs->tx.fmbm_trlmts;
+ granularity = BMI_RATE_LIMIT_GRAN_TX;
+ break;
+ case E_FMAN_PORT_TYPE_OP:
+ rate_limit_reg = &port->bmi_regs->oh.fmbm_orlmt;
+ rate_limit_scale_reg = &port->bmi_regs->oh.fmbm_orlmts;
+ granularity = BMI_RATE_LIMIT_GRAN_OP;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Factor is per 1 usec count */
+ factor = 1;
+ usec_bit = rate_limiter->count_1micro_bit;
+
+ /* If rate limit is too small for an 1usec factor, adjust timestamp
+ * scale and multiply the factor */
+ while (rate_limiter->rate < (granularity / factor)) {
+ if (usec_bit == 31)
+ /* Can't configure rate limiter - rate is too small */
+ return -EINVAL;
+
+ usec_bit++;
+ factor <<= 1;
+ }
+
+ /* Figure out register value. The "while" above quarantees that
+ * (rate_limiter->rate * factor / granularity) >= 1 */
+ tmp = (uint32_t)(rate_limiter->rate * factor / granularity - 1);
+
+ /* Check rate limit isn't too large */
+ if (tmp >= BMI_RATE_LIMIT_MAX_RATE_IN_GRAN_UNITS)
+ return -EINVAL;
+
+ /* Check burst size is in allowed range */
+ if ((rate_limiter->burst_size == 0) ||
+ (rate_limiter->burst_size >
+ BMI_RATE_LIMIT_MAX_BURST_SIZE))
+ return -EINVAL;
+
+ tmp |= (uint32_t)(rate_limiter->burst_size - 1) <<
+ BMI_RATE_LIMIT_MAX_BURST_SHIFT;
+
+ if ((port->type == E_FMAN_PORT_TYPE_OP) &&
+ (port->fm_rev_maj == 4)) {
+ if (rate_limiter->high_burst_size_gran)
+ tmp |= BMI_RATE_LIMIT_HIGH_BURST_SIZE_GRAN;
+ }
+
+ iowrite32be(tmp, rate_limit_reg);
+
+ /* Set up rate limiter scale register */
+ tmp = BMI_RATE_LIMIT_SCALE_EN;
+ tmp |= (31 - (uint32_t)usec_bit) << BMI_RATE_LIMIT_SCALE_TSBS_SHIFT;
+
+ if ((port->type == E_FMAN_PORT_TYPE_OP) &&
+ (port->fm_rev_maj == 4))
+ tmp |= rate_limiter->rate_factor;
+
+ iowrite32be(tmp, rate_limit_scale_reg);
+
+ return 0;
+}
+
+int fman_port_delete_rate_limiter(struct fman_port *port)
+{
+ uint32_t *rate_limit_scale_reg;
+
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_TX:
+ case E_FMAN_PORT_TYPE_TX_10G:
+ rate_limit_scale_reg = &port->bmi_regs->tx.fmbm_trlmts;
+ break;
+ case E_FMAN_PORT_TYPE_OP:
+ rate_limit_scale_reg = &port->bmi_regs->oh.fmbm_orlmts;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ iowrite32be(0, rate_limit_scale_reg);
+ return 0;
+}
+
+int fman_port_set_err_mask(struct fman_port *port, uint32_t err_mask)
+{
+ uint32_t *err_mask_reg;
+
+ /* Obtain register address */
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ err_mask_reg = &port->bmi_regs->rx.fmbm_rfsem;
+ break;
+ case E_FMAN_PORT_TYPE_OP:
+ err_mask_reg = &port->bmi_regs->oh.fmbm_ofsem;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ iowrite32be(err_mask, err_mask_reg);
+ return 0;
+}
+
+int fman_port_set_discard_mask(struct fman_port *port, uint32_t discard_mask)
+{
+ uint32_t *discard_mask_reg;
+
+ /* Obtain register address */
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ discard_mask_reg = &port->bmi_regs->rx.fmbm_rfsdm;
+ break;
+ case E_FMAN_PORT_TYPE_OP:
+ discard_mask_reg = &port->bmi_regs->oh.fmbm_ofsdm;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ iowrite32be(discard_mask, discard_mask_reg);
+ return 0;
+}
+
+int fman_port_modify_rx_fd_bits(struct fman_port *port,
+ uint8_t rx_fd_bits,
+ bool add)
+{
+ uint32_t tmp;
+
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ tmp = ioread32be(&port->bmi_regs->rx.fmbm_rfne);
+
+ if (add)
+ tmp |= (uint32_t)rx_fd_bits << BMI_NEXT_ENG_FD_BITS_SHIFT;
+ else
+ tmp &= ~((uint32_t)rx_fd_bits << BMI_NEXT_ENG_FD_BITS_SHIFT);
+
+ iowrite32be(tmp, &port->bmi_regs->rx.fmbm_rfne);
+ return 0;
+}
+
+int fman_port_set_perf_cnt_params(struct fman_port *port,
+ struct fman_port_perf_cnt_params *params)
+{
+ uint32_t *pcp_reg, tmp;
+
+ /* Obtain register address and check parameters are in range */
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ pcp_reg = &port->bmi_regs->rx.fmbm_rpcp;
+ if ((params->queue_val == 0) ||
+ (params->queue_val > MAX_PERFORMANCE_RX_QUEUE_COMP))
+ return -EINVAL;
+ break;
+ case E_FMAN_PORT_TYPE_TX:
+ case E_FMAN_PORT_TYPE_TX_10G:
+ pcp_reg = &port->bmi_regs->tx.fmbm_tpcp;
+ if ((params->queue_val == 0) ||
+ (params->queue_val > MAX_PERFORMANCE_TX_QUEUE_COMP))
+ return -EINVAL;
+ break;
+ case E_FMAN_PORT_TYPE_OP:
+ case E_FMAN_PORT_TYPE_HC:
+ pcp_reg = &port->bmi_regs->oh.fmbm_opcp;
+ if (params->queue_val != 0)
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if ((params->task_val == 0) ||
+ (params->task_val > MAX_PERFORMANCE_TASK_COMP))
+ return -EINVAL;
+ if ((params->dma_val == 0) ||
+ (params->dma_val > MAX_PERFORMANCE_DMA_COMP))
+ return -EINVAL;
+ if ((params->fifo_val == 0) ||
+ ((params->fifo_val / FMAN_PORT_BMI_FIFO_UNITS) >
+ MAX_PERFORMANCE_FIFO_COMP))
+ return -EINVAL;
+ tmp = (uint32_t)(params->task_val - 1) <<
+ BMI_PERFORMANCE_TASK_COMP_SHIFT;
+ tmp |= (uint32_t)(params->dma_val - 1) <<
+ BMI_PERFORMANCE_DMA_COMP_SHIFT;
+ tmp |= (uint32_t)(params->fifo_val / FMAN_PORT_BMI_FIFO_UNITS - 1);
+
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ case E_FMAN_PORT_TYPE_TX:
+ case E_FMAN_PORT_TYPE_TX_10G:
+ tmp |= (uint32_t)(params->queue_val - 1) <<
+ BMI_PERFORMANCE_QUEUE_COMP_SHIFT;
+ break;
+ default:
+ break;
+ }
+
+
+ iowrite32be(tmp, pcp_reg);
+ return 0;
+}
+
+int fman_port_set_stats_cnt_mode(struct fman_port *port, bool enable)
+{
+ uint32_t *stats_reg, tmp;
+
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ stats_reg = &port->bmi_regs->rx.fmbm_rstc;
+ break;
+ case E_FMAN_PORT_TYPE_TX:
+ case E_FMAN_PORT_TYPE_TX_10G:
+ stats_reg = &port->bmi_regs->tx.fmbm_tstc;
+ break;
+ case E_FMAN_PORT_TYPE_OP:
+ case E_FMAN_PORT_TYPE_HC:
+ stats_reg = &port->bmi_regs->oh.fmbm_ostc;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ tmp = ioread32be(stats_reg);
+
+ if (enable)
+ tmp |= BMI_COUNTERS_EN;
+ else
+ tmp &= ~BMI_COUNTERS_EN;
+
+ iowrite32be(tmp, stats_reg);
+ return 0;
+}
+
+int fman_port_set_perf_cnt_mode(struct fman_port *port, bool enable)
+{
+ uint32_t *stats_reg, tmp;
+
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ stats_reg = &port->bmi_regs->rx.fmbm_rpc;
+ break;
+ case E_FMAN_PORT_TYPE_TX:
+ case E_FMAN_PORT_TYPE_TX_10G:
+ stats_reg = &port->bmi_regs->tx.fmbm_tpc;
+ break;
+ case E_FMAN_PORT_TYPE_OP:
+ case E_FMAN_PORT_TYPE_HC:
+ stats_reg = &port->bmi_regs->oh.fmbm_opc;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ tmp = ioread32be(stats_reg);
+
+ if (enable)
+ tmp |= BMI_COUNTERS_EN;
+ else
+ tmp &= ~BMI_COUNTERS_EN;
+
+ iowrite32be(tmp, stats_reg);
+ return 0;
+}
+
+int fman_port_set_queue_cnt_mode(struct fman_port *port, bool enable)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&port->qmi_regs->fmqm_pnc);
+
+ if (enable)
+ tmp |= QMI_PORT_CFG_EN_COUNTERS;
+ else
+ tmp &= ~QMI_PORT_CFG_EN_COUNTERS;
+
+ iowrite32be(tmp, &port->qmi_regs->fmqm_pnc);
+ return 0;
+}
+
+int fman_port_set_bpool_cnt_mode(struct fman_port *port,
+ uint8_t bpid,
+ bool enable)
+{
+ uint8_t index;
+ uint32_t tmp;
+
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Find the pool */
+ index = fman_port_find_bpool(port, bpid);
+ if (index == port->ext_pools_num || index == FMAN_PORT_MAX_EXT_POOLS_NUM)
+ /* Not found */
+ return -EINVAL;
+
+ tmp = ioread32be(&port->bmi_regs->rx.fmbm_ebmpi[index]);
+
+ if (enable)
+ tmp |= BMI_EXT_BUF_POOL_EN_COUNTER;
+ else
+ tmp &= ~BMI_EXT_BUF_POOL_EN_COUNTER;
+
+ iowrite32be(tmp, &port->bmi_regs->rx.fmbm_ebmpi[index]);
+ return 0;
+}
+
+uint32_t fman_port_get_stats_counter(struct fman_port *port,
+ enum fman_port_stats_counters counter)
+{
+ uint32_t *stats_reg, ret_val;
+
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ get_rx_stats_reg(port, counter, &stats_reg);
+ break;
+ case E_FMAN_PORT_TYPE_TX:
+ case E_FMAN_PORT_TYPE_TX_10G:
+ get_tx_stats_reg(port, counter, &stats_reg);
+ break;
+ case E_FMAN_PORT_TYPE_OP:
+ case E_FMAN_PORT_TYPE_HC:
+ get_oh_stats_reg(port, counter, &stats_reg);
+ break;
+ default:
+ stats_reg = NULL;
+ }
+
+ if (stats_reg == NULL)
+ return 0;
+
+ ret_val = ioread32be(stats_reg);
+ return ret_val;
+}
+
+void fman_port_set_stats_counter(struct fman_port *port,
+ enum fman_port_stats_counters counter,
+ uint32_t value)
+{
+ uint32_t *stats_reg;
+
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ get_rx_stats_reg(port, counter, &stats_reg);
+ break;
+ case E_FMAN_PORT_TYPE_TX:
+ case E_FMAN_PORT_TYPE_TX_10G:
+ get_tx_stats_reg(port, counter, &stats_reg);
+ break;
+ case E_FMAN_PORT_TYPE_OP:
+ case E_FMAN_PORT_TYPE_HC:
+ get_oh_stats_reg(port, counter, &stats_reg);
+ break;
+ default:
+ stats_reg = NULL;
+ }
+
+ if (stats_reg == NULL)
+ return;
+
+ iowrite32be(value, stats_reg);
+}
+
+uint32_t fman_port_get_perf_counter(struct fman_port *port,
+ enum fman_port_perf_counters counter)
+{
+ uint32_t *perf_reg, ret_val;
+
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ get_rx_perf_reg(port, counter, &perf_reg);
+ break;
+ case E_FMAN_PORT_TYPE_TX:
+ case E_FMAN_PORT_TYPE_TX_10G:
+ get_tx_perf_reg(port, counter, &perf_reg);
+ break;
+ case E_FMAN_PORT_TYPE_OP:
+ case E_FMAN_PORT_TYPE_HC:
+ get_oh_perf_reg(port, counter, &perf_reg);
+ break;
+ default:
+ perf_reg = NULL;
+ }
+
+ if (perf_reg == NULL)
+ return 0;
+
+ ret_val = ioread32be(perf_reg);
+ return ret_val;
+}
+
+void fman_port_set_perf_counter(struct fman_port *port,
+ enum fman_port_perf_counters counter,
+ uint32_t value)
+{
+ uint32_t *perf_reg;
+
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ get_rx_perf_reg(port, counter, &perf_reg);
+ break;
+ case E_FMAN_PORT_TYPE_TX:
+ case E_FMAN_PORT_TYPE_TX_10G:
+ get_tx_perf_reg(port, counter, &perf_reg);
+ break;
+ case E_FMAN_PORT_TYPE_OP:
+ case E_FMAN_PORT_TYPE_HC:
+ get_oh_perf_reg(port, counter, &perf_reg);
+ break;
+ default:
+ perf_reg = NULL;
+ }
+
+ if (perf_reg == NULL)
+ return;
+
+ iowrite32be(value, perf_reg);
+}
+
+uint32_t fman_port_get_qmi_counter(struct fman_port *port,
+ enum fman_port_qmi_counters counter)
+{
+ uint32_t *queue_reg, ret_val;
+
+ get_qmi_counter_reg(port, counter, &queue_reg);
+
+ if (queue_reg == NULL)
+ return 0;
+
+ ret_val = ioread32be(queue_reg);
+ return ret_val;
+}
+
+void fman_port_set_qmi_counter(struct fman_port *port,
+ enum fman_port_qmi_counters counter,
+ uint32_t value)
+{
+ uint32_t *queue_reg;
+
+ get_qmi_counter_reg(port, counter, &queue_reg);
+
+ if (queue_reg == NULL)
+ return;
+
+ iowrite32be(value, queue_reg);
+}
+
+uint32_t fman_port_get_bpool_counter(struct fman_port *port, uint8_t bpid)
+{
+ uint8_t index;
+ uint32_t ret_val;
+
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ break;
+ default:
+ return 0;
+ }
+
+ /* Find the pool */
+ index = fman_port_find_bpool(port, bpid);
+ if (index == port->ext_pools_num || index == FMAN_PORT_MAX_EXT_POOLS_NUM)
+ /* Not found */
+ return 0;
+
+ ret_val = ioread32be(&port->bmi_regs->rx.fmbm_acnt[index]);
+ return ret_val;
+}
+
+void fman_port_set_bpool_counter(struct fman_port *port,
+ uint8_t bpid,
+ uint32_t value)
+{
+ uint8_t index;
+
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ break;
+ default:
+ return;
+ }
+
+ /* Find the pool */
+ index = fman_port_find_bpool(port, bpid);
+ if (index == port->ext_pools_num || index == FMAN_PORT_MAX_EXT_POOLS_NUM)
+ /* Not found */
+ return;
+
+ iowrite32be(value, &port->bmi_regs->rx.fmbm_acnt[index]);
+}
+
+int fman_port_add_congestion_grps(struct fman_port *port,
+ uint32_t grps_map[FMAN_PORT_CG_MAP_NUM])
+{
+ int i;
+ uint32_t tmp, *grp_map_reg;
+ uint8_t max_grp_map_num;
+
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ if (port->fm_rev_maj == 4)
+ max_grp_map_num = 1;
+ else
+ max_grp_map_num = FMAN_PORT_CG_MAP_NUM;
+ grp_map_reg = port->bmi_regs->rx.fmbm_rcgm;
+ break;
+ case E_FMAN_PORT_TYPE_OP:
+ max_grp_map_num = 1;
+ if (port->fm_rev_maj != 4)
+ return -EINVAL;
+ grp_map_reg = &port->bmi_regs->oh.fmbm_ocgm;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = (max_grp_map_num - 1); i >= 0; i--) {
+ if (grps_map[i] == 0)
+ continue;
+ tmp = ioread32be(&grp_map_reg[i]);
+ tmp |= grps_map[i];
+ iowrite32be(tmp, &grp_map_reg[i]);
+ }
+
+ return 0;
+}
+
+int fman_port_remove_congestion_grps(struct fman_port *port,
+ uint32_t grps_map[FMAN_PORT_CG_MAP_NUM])
+{
+ int i;
+ uint32_t tmp, *grp_map_reg;
+ uint8_t max_grp_map_num;
+
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ if (port->fm_rev_maj == 4)
+ max_grp_map_num = 1;
+ else
+ max_grp_map_num = FMAN_PORT_CG_MAP_NUM;
+ grp_map_reg = port->bmi_regs->rx.fmbm_rcgm;
+ break;
+ case E_FMAN_PORT_TYPE_OP:
+ max_grp_map_num = 1;
+ if (port->fm_rev_maj != 4)
+ return -EINVAL;
+ grp_map_reg = &port->bmi_regs->oh.fmbm_ocgm;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = (max_grp_map_num - 1); i >= 0; i--) {
+ if (grps_map[i] == 0)
+ continue;
+ tmp = ioread32be(&grp_map_reg[i]);
+ tmp &= ~grps_map[i];
+ iowrite32be(tmp, &grp_map_reg[i]);
+ }
+ return 0;
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/Makefile b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/Makefile
new file mode 100644
index 0000000..f804c51
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/Makefile
@@ -0,0 +1,15 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+
+NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc
+
+EXTRA_CFLAGS += -I$(NCSW_FM_INC)
+
+obj-y += fsl-ncsw-RTC.o
+
+fsl-ncsw-RTC-objs := fm_rtc.o fman_rtc.o
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/fm_rtc.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/fm_rtc.c
new file mode 100644
index 0000000..312e5e3
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/fm_rtc.c
@@ -0,0 +1,711 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_rtc.c
+
+ @Description FM RTC driver implementation.
+
+ @Cautions None
+*//***************************************************************************/
+
+#include "error_ext.h"
+#include "debug_ext.h"
+#include "string_ext.h"
+#include "part_ext.h"
+#include "xx_ext.h"
+#include "ncsw_ext.h"
+
+#include "fm_rtc.h"
+#include "fm_common.h"
+
+
+
+/*****************************************************************************/
+static t_Error CheckInitParameters(t_FmRtc *p_Rtc)
+{
+ struct rtc_cfg *p_RtcDriverParam = p_Rtc->p_RtcDriverParam;
+ int i;
+
+ if ((p_RtcDriverParam->src_clk != E_FMAN_RTC_SOURCE_CLOCK_EXTERNAL) &&
+ (p_RtcDriverParam->src_clk != E_FMAN_RTC_SOURCE_CLOCK_SYSTEM) &&
+ (p_RtcDriverParam->src_clk != E_FMAN_RTC_SOURCE_CLOCK_OSCILATOR))
+ RETURN_ERROR(MAJOR, E_INVALID_CLOCK, ("Source clock undefined"));
+
+ if (p_Rtc->outputClockDivisor == 0)
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("Divisor for output clock (should be positive)"));
+ }
+
+ for (i=0; i < FM_RTC_NUM_OF_ALARMS; i++)
+ {
+ if ((p_RtcDriverParam->alarm_polarity[i] != E_FMAN_RTC_ALARM_POLARITY_ACTIVE_LOW) &&
+ (p_RtcDriverParam->alarm_polarity[i] != E_FMAN_RTC_ALARM_POLARITY_ACTIVE_HIGH))
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm %d signal polarity", i));
+ }
+ }
+ for (i=0; i < FM_RTC_NUM_OF_EXT_TRIGGERS; i++)
+ {
+ if ((p_RtcDriverParam->trigger_polarity[i] != E_FMAN_RTC_TRIGGER_ON_FALLING_EDGE) &&
+ (p_RtcDriverParam->trigger_polarity[i] != E_FMAN_RTC_TRIGGER_ON_RISING_EDGE))
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Trigger %d signal polarity", i));
+ }
+ }
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+static void RtcExceptions(t_Handle h_FmRtc)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+ struct rtc_regs *p_MemMap;
+ register uint32_t events;
+
+ ASSERT_COND(p_Rtc);
+ p_MemMap = p_Rtc->p_MemMap;
+
+ events = fman_rtc_check_and_clear_event(p_MemMap);
+ if (events & FMAN_RTC_TMR_TEVENT_ALM1)
+ {
+ if (p_Rtc->alarmParams[0].clearOnExpiration)
+ {
+ fman_rtc_set_timer_alarm_l(p_MemMap, 0, 0);
+ fman_rtc_disable_interupt(p_MemMap, FMAN_RTC_TMR_TEVENT_ALM1);
+ }
+ ASSERT_COND(p_Rtc->alarmParams[0].f_AlarmCallback);
+ p_Rtc->alarmParams[0].f_AlarmCallback(p_Rtc->h_App, 0);
+ }
+ if (events & FMAN_RTC_TMR_TEVENT_ALM2)
+ {
+ if (p_Rtc->alarmParams[1].clearOnExpiration)
+ {
+ fman_rtc_set_timer_alarm_l(p_MemMap, 1, 0);
+ fman_rtc_disable_interupt(p_MemMap, FMAN_RTC_TMR_TEVENT_ALM2);
+ }
+ ASSERT_COND(p_Rtc->alarmParams[1].f_AlarmCallback);
+ p_Rtc->alarmParams[1].f_AlarmCallback(p_Rtc->h_App, 1);
+ }
+ if (events & FMAN_RTC_TMR_TEVENT_PP1)
+ {
+ ASSERT_COND(p_Rtc->periodicPulseParams[0].f_PeriodicPulseCallback);
+ p_Rtc->periodicPulseParams[0].f_PeriodicPulseCallback(p_Rtc->h_App, 0);
+ }
+ if (events & FMAN_RTC_TMR_TEVENT_PP2)
+ {
+ ASSERT_COND(p_Rtc->periodicPulseParams[1].f_PeriodicPulseCallback);
+ p_Rtc->periodicPulseParams[1].f_PeriodicPulseCallback(p_Rtc->h_App, 1);
+ }
+ if (events & FMAN_RTC_TMR_TEVENT_ETS1)
+ {
+ ASSERT_COND(p_Rtc->externalTriggerParams[0].f_ExternalTriggerCallback);
+ p_Rtc->externalTriggerParams[0].f_ExternalTriggerCallback(p_Rtc->h_App, 0);
+ }
+ if (events & FMAN_RTC_TMR_TEVENT_ETS2)
+ {
+ ASSERT_COND(p_Rtc->externalTriggerParams[1].f_ExternalTriggerCallback);
+ p_Rtc->externalTriggerParams[1].f_ExternalTriggerCallback(p_Rtc->h_App, 1);
+ }
+}
+
+
+/*****************************************************************************/
+t_Handle FM_RTC_Config(t_FmRtcParams *p_FmRtcParam)
+{
+ t_FmRtc *p_Rtc;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmRtcParam, E_NULL_POINTER, NULL);
+
+ /* Allocate memory for the FM RTC driver parameters */
+ p_Rtc = (t_FmRtc *)XX_Malloc(sizeof(t_FmRtc));
+ if (!p_Rtc)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM RTC driver structure"));
+ return NULL;
+ }
+
+ memset(p_Rtc, 0, sizeof(t_FmRtc));
+
+ /* Allocate memory for the FM RTC driver parameters */
+ p_Rtc->p_RtcDriverParam = (struct rtc_cfg *)XX_Malloc(sizeof(struct rtc_cfg));
+ if (!p_Rtc->p_RtcDriverParam)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM RTC driver parameters"));
+ XX_Free(p_Rtc);
+ return NULL;
+ }
+
+ memset(p_Rtc->p_RtcDriverParam, 0, sizeof(struct rtc_cfg));
+
+ /* Store RTC configuration parameters */
+ p_Rtc->h_Fm = p_FmRtcParam->h_Fm;
+
+ /* Set default RTC configuration parameters */
+ fman_rtc_defconfig(p_Rtc->p_RtcDriverParam);
+
+ p_Rtc->outputClockDivisor = DEFAULT_OUTPUT_CLOCK_DIVISOR;
+ p_Rtc->p_RtcDriverParam->bypass = DEFAULT_BYPASS;
+ p_Rtc->clockPeriodNanoSec = DEFAULT_CLOCK_PERIOD; /* 1 usec */
+
+
+ /* Store RTC parameters in the RTC control structure */
+ p_Rtc->p_MemMap = (struct rtc_regs *)UINT_TO_PTR(p_FmRtcParam->baseAddress);
+ p_Rtc->h_App = p_FmRtcParam->h_App;
+
+ return p_Rtc;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_Init(t_Handle h_FmRtc)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+ struct rtc_cfg *p_RtcDriverParam;
+ struct rtc_regs *p_MemMap;
+ uint32_t freqCompensation = 0;
+ uint64_t tmpDouble;
+ bool init_freq_comp = FALSE;
+
+ p_RtcDriverParam = p_Rtc->p_RtcDriverParam;
+ p_MemMap = p_Rtc->p_MemMap;
+
+ if (CheckInitParameters(p_Rtc)!=E_OK)
+ RETURN_ERROR(MAJOR, E_CONFLICT,
+ ("Init Parameters are not Valid"));
+
+ /* TODO check that no timestamping MACs are working in this stage. */
+
+ /* find source clock frequency in Mhz */
+ if (p_Rtc->p_RtcDriverParam->src_clk != E_FMAN_RTC_SOURCE_CLOCK_SYSTEM)
+ p_Rtc->srcClkFreqMhz = p_Rtc->p_RtcDriverParam->ext_src_clk_freq;
+ else
+ p_Rtc->srcClkFreqMhz = (uint32_t)(FmGetClockFreq(p_Rtc->h_Fm)/2);
+
+ /* if timer in Master mode Initialize TMR_CTRL */
+ /* We want the counter (TMR_CNT) to count in nano-seconds */
+ if (!p_RtcDriverParam->timer_slave_mode && p_Rtc->p_RtcDriverParam->bypass)
+ p_Rtc->clockPeriodNanoSec = (1000 / p_Rtc->srcClkFreqMhz);
+ else
+ {
+ /* Initialize TMR_ADD with the initial frequency compensation value:
+ freqCompensation = (2^32 / frequency ratio) */
+ /* frequency ratio = sorce clock/rtc clock =
+ * (p_Rtc->srcClkFreqMhz*1000000))/ 1/(p_Rtc->clockPeriodNanoSec * 1000000000) */
+ init_freq_comp = TRUE;
+ freqCompensation = (uint32_t)DIV_CEIL(ACCUMULATOR_OVERFLOW * 1000,
+ p_Rtc->clockPeriodNanoSec * p_Rtc->srcClkFreqMhz);
+ }
+
+ /* check the legality of the relation between source and destination clocks */
+ /* should be larger than 1.0001 */
+ tmpDouble = 10000 * (uint64_t)p_Rtc->clockPeriodNanoSec * (uint64_t)p_Rtc->srcClkFreqMhz;
+ if ((tmpDouble) <= 10001)
+ RETURN_ERROR(MAJOR, E_CONFLICT,
+ ("Invalid relation between source and destination clocks. Should be larger than 1.0001"));
+
+ fman_rtc_init(p_RtcDriverParam,
+ p_MemMap,
+ FM_RTC_NUM_OF_ALARMS,
+ FM_RTC_NUM_OF_PERIODIC_PULSES,
+ FM_RTC_NUM_OF_EXT_TRIGGERS,
+ init_freq_comp,
+ freqCompensation,
+ p_Rtc->outputClockDivisor);
+
+ /* Register the FM RTC interrupt */
+ FmRegisterIntr(p_Rtc->h_Fm, e_FM_MOD_TMR, 0, e_FM_INTR_TYPE_NORMAL, RtcExceptions , p_Rtc);
+
+ /* Free parameters structures */
+ XX_Free(p_Rtc->p_RtcDriverParam);
+ p_Rtc->p_RtcDriverParam = NULL;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_Free(t_Handle h_FmRtc)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+
+ if (p_Rtc->p_RtcDriverParam)
+ {
+ XX_Free(p_Rtc->p_RtcDriverParam);
+ }
+ else
+ {
+ FM_RTC_Disable(h_FmRtc);
+ }
+
+ /* Unregister FM RTC interrupt */
+ FmUnregisterIntr(p_Rtc->h_Fm, e_FM_MOD_TMR, 0, e_FM_INTR_TYPE_NORMAL);
+ XX_Free(p_Rtc);
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_ConfigSourceClock(t_Handle h_FmRtc,
+ e_FmSrcClk srcClk,
+ uint32_t freqInMhz)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ p_Rtc->p_RtcDriverParam->src_clk = (enum fman_src_clock)srcClk;
+ if (srcClk != e_FM_RTC_SOURCE_CLOCK_SYSTEM)
+ p_Rtc->p_RtcDriverParam->ext_src_clk_freq = freqInMhz;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_ConfigPeriod(t_Handle h_FmRtc, uint32_t period)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ p_Rtc->clockPeriodNanoSec = period;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_ConfigFrequencyBypass(t_Handle h_FmRtc, bool enabled)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ p_Rtc->p_RtcDriverParam->bypass = enabled;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_ConfigInvertedInputClockPhase(t_Handle h_FmRtc, bool inverted)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ p_Rtc->p_RtcDriverParam->invert_input_clk_phase = inverted;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_ConfigInvertedOutputClockPhase(t_Handle h_FmRtc, bool inverted)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ p_Rtc->p_RtcDriverParam->invert_output_clk_phase = inverted;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_ConfigOutputClockDivisor(t_Handle h_FmRtc, uint16_t divisor)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ p_Rtc->outputClockDivisor = divisor;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_ConfigPulseRealignment(t_Handle h_FmRtc, bool enable)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ p_Rtc->p_RtcDriverParam->pulse_realign = enable;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_ConfigAlarmPolarity(t_Handle h_FmRtc,
+ uint8_t alarmId,
+ e_FmRtcAlarmPolarity alarmPolarity)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ if (alarmId >= FM_RTC_NUM_OF_ALARMS)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm ID"));
+
+ p_Rtc->p_RtcDriverParam->alarm_polarity[alarmId] =
+ (enum fman_rtc_alarm_polarity)alarmPolarity;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_ConfigExternalTriggerPolarity(t_Handle h_FmRtc,
+ uint8_t triggerId,
+ e_FmRtcTriggerPolarity triggerPolarity)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ if (triggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS)
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External trigger ID"));
+ }
+
+ p_Rtc->p_RtcDriverParam->trigger_polarity[triggerId] =
+ (enum fman_rtc_trigger_polarity)triggerPolarity;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_Enable(t_Handle h_FmRtc, bool resetClock)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ fman_rtc_enable(p_Rtc->p_MemMap, resetClock);
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_Disable(t_Handle h_FmRtc)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ /* TODO A check must be added here, that no timestamping MAC's
+ * are working in this stage. */
+ fman_rtc_disable(p_Rtc->p_MemMap);
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_SetClockOffset(t_Handle h_FmRtc, int64_t offset)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ fman_rtc_set_timer_offset(p_Rtc->p_MemMap, offset);
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_SetAlarm(t_Handle h_FmRtc, t_FmRtcAlarmParams *p_FmRtcAlarmParams)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+ uint64_t tmpAlarm;
+ bool enable = FALSE;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ if (p_FmRtcAlarmParams->alarmId >= FM_RTC_NUM_OF_ALARMS)
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Alarm ID"));
+ }
+
+ if (p_FmRtcAlarmParams->alarmTime < p_Rtc->clockPeriodNanoSec)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION,
+ ("Alarm time must be equal or larger than RTC period - %d nanoseconds",
+ p_Rtc->clockPeriodNanoSec));
+ if (p_FmRtcAlarmParams->alarmTime % (uint64_t)p_Rtc->clockPeriodNanoSec)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION,
+ ("Alarm time must be a multiple of RTC period - %d nanoseconds",
+ p_Rtc->clockPeriodNanoSec));
+ tmpAlarm = p_FmRtcAlarmParams->alarmTime/(uint64_t)p_Rtc->clockPeriodNanoSec;
+
+ if (p_FmRtcAlarmParams->f_AlarmCallback)
+ {
+ p_Rtc->alarmParams[p_FmRtcAlarmParams->alarmId].f_AlarmCallback = p_FmRtcAlarmParams->f_AlarmCallback;
+ p_Rtc->alarmParams[p_FmRtcAlarmParams->alarmId].clearOnExpiration = p_FmRtcAlarmParams->clearOnExpiration;
+ enable = TRUE;
+ }
+
+ fman_rtc_set_alarm(p_Rtc->p_MemMap, p_FmRtcAlarmParams->alarmId, (unsigned long)tmpAlarm, enable);
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_SetPeriodicPulse(t_Handle h_FmRtc, t_FmRtcPeriodicPulseParams *p_FmRtcPeriodicPulseParams)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+ bool enable = FALSE;
+ uint64_t tmpFiper;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ if (p_FmRtcPeriodicPulseParams->periodicPulseId >= FM_RTC_NUM_OF_PERIODIC_PULSES)
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Periodic pulse ID"));
+ }
+ if (fman_rtc_is_enabled(p_Rtc->p_MemMap))
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Can't set Periodic pulse when RTC is enabled."));
+ if (p_FmRtcPeriodicPulseParams->periodicPulsePeriod < p_Rtc->clockPeriodNanoSec)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION,
+ ("Periodic pulse must be equal or larger than RTC period - %d nanoseconds",
+ p_Rtc->clockPeriodNanoSec));
+ if (p_FmRtcPeriodicPulseParams->periodicPulsePeriod % (uint64_t)p_Rtc->clockPeriodNanoSec)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION,
+ ("Periodic pulse must be a multiple of RTC period - %d nanoseconds",
+ p_Rtc->clockPeriodNanoSec));
+ tmpFiper = p_FmRtcPeriodicPulseParams->periodicPulsePeriod/(uint64_t)p_Rtc->clockPeriodNanoSec;
+ if (tmpFiper & 0xffffffff00000000LL)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION,
+ ("Periodic pulse/RTC Period must be smaller than 4294967296",
+ p_Rtc->clockPeriodNanoSec));
+
+ if (p_FmRtcPeriodicPulseParams->f_PeriodicPulseCallback)
+ {
+ p_Rtc->periodicPulseParams[p_FmRtcPeriodicPulseParams->periodicPulseId].f_PeriodicPulseCallback =
+ p_FmRtcPeriodicPulseParams->f_PeriodicPulseCallback;
+ enable = TRUE;
+ }
+ fman_rtc_set_periodic_pulse(p_Rtc->p_MemMap, p_FmRtcPeriodicPulseParams->periodicPulseId, (uint32_t)tmpFiper, enable);
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_ClearPeriodicPulse(t_Handle h_FmRtc, uint8_t periodicPulseId)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ if (periodicPulseId >= FM_RTC_NUM_OF_PERIODIC_PULSES)
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("Periodic pulse ID"));
+ }
+
+ p_Rtc->periodicPulseParams[periodicPulseId].f_PeriodicPulseCallback = NULL;
+ fman_rtc_clear_periodic_pulse(p_Rtc->p_MemMap, periodicPulseId);
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_SetExternalTrigger(t_Handle h_FmRtc, t_FmRtcExternalTriggerParams *p_FmRtcExternalTriggerParams)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+ bool enable = FALSE;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ if (p_FmRtcExternalTriggerParams->externalTriggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS)
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External Trigger ID"));
+ }
+
+ if (p_FmRtcExternalTriggerParams->f_ExternalTriggerCallback)
+ {
+ p_Rtc->externalTriggerParams[p_FmRtcExternalTriggerParams->externalTriggerId].f_ExternalTriggerCallback = p_FmRtcExternalTriggerParams->f_ExternalTriggerCallback;
+ enable = TRUE;
+ }
+
+ fman_rtc_set_ext_trigger(p_Rtc->p_MemMap, p_FmRtcExternalTriggerParams->externalTriggerId, enable, p_FmRtcExternalTriggerParams->usePulseAsInput);
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_ClearExternalTrigger(t_Handle h_FmRtc, uint8_t externalTriggerId)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ if (externalTriggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External Trigger ID"));
+
+ p_Rtc->externalTriggerParams[externalTriggerId].f_ExternalTriggerCallback = NULL;
+
+ fman_rtc_clear_external_trigger(p_Rtc->p_MemMap, externalTriggerId);
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_GetExternalTriggerTimeStamp(t_Handle h_FmRtc,
+ uint8_t triggerId,
+ uint64_t *p_TimeStamp)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ if (triggerId >= FM_RTC_NUM_OF_EXT_TRIGGERS)
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION, ("External trigger ID"));
+
+ *p_TimeStamp = fman_rtc_get_trigger_stamp(p_Rtc->p_MemMap, triggerId)*p_Rtc->clockPeriodNanoSec;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_GetCurrentTime(t_Handle h_FmRtc, uint64_t *p_Ts)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ *p_Ts = fman_rtc_get_timer(p_Rtc->p_MemMap)*p_Rtc->clockPeriodNanoSec;
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_SetCurrentTime(t_Handle h_FmRtc, uint64_t ts)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ ts = ts/p_Rtc->clockPeriodNanoSec;
+ fman_rtc_set_timer(p_Rtc->p_MemMap, (unsigned long)ts);
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_GetFreqCompensation(t_Handle h_FmRtc, uint32_t *p_Compensation)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ *p_Compensation = fman_rtc_get_frequency_compensation(p_Rtc->p_MemMap);
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+t_Error FM_RTC_SetFreqCompensation(t_Handle h_FmRtc, uint32_t freqCompensation)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+
+ SANITY_CHECK_RETURN_ERROR(p_Rtc, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Rtc->p_RtcDriverParam, E_INVALID_STATE);
+
+ /* set the new freqCompensation */
+ fman_rtc_set_frequency_compensation(p_Rtc->p_MemMap, freqCompensation);
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+t_Error FM_RTC_DumpRegs(t_Handle h_FmRtc)
+{
+ t_FmRtc *p_Rtc = (t_FmRtc *)h_FmRtc;
+ struct rtc_regs *p_MemMap = p_Rtc->p_MemMap;
+ int i = 0;
+
+ DECLARE_DUMP;
+
+ if (p_MemMap)
+ {
+
+ DUMP_TITLE(p_MemMap, ("RTC:"));
+ DUMP_VAR(p_MemMap, tmr_id);
+ DUMP_VAR(p_MemMap, tmr_id2);
+ DUMP_VAR(p_MemMap, tmr_ctrl);
+ DUMP_VAR(p_MemMap, tmr_tevent);
+ DUMP_VAR(p_MemMap, tmr_temask);
+ DUMP_VAR(p_MemMap, tmr_cnt_h);
+ DUMP_VAR(p_MemMap, tmr_cnt_l);
+ DUMP_VAR(p_MemMap, tmr_ctrl);
+ DUMP_VAR(p_MemMap, tmr_add);
+ DUMP_VAR(p_MemMap, tmr_acc);
+ DUMP_VAR(p_MemMap, tmr_prsc);
+ DUMP_VAR(p_MemMap, tmr_off_h);
+ DUMP_VAR(p_MemMap, tmr_off_l);
+
+ DUMP_SUBSTRUCT_ARRAY(i, 2)
+ {
+ DUMP_VAR(p_MemMap, tmr_alarm[i].tmr_alarm_h);
+ DUMP_VAR(p_MemMap, tmr_alarm[i].tmr_alarm_l);
+ }
+ DUMP_SUBSTRUCT_ARRAY(i, 2)
+ {
+ DUMP_VAR(p_MemMap, tmr_fiper[i]);
+ DUMP_VAR(p_MemMap, tmr_fiper[i]);
+ }
+ DUMP_SUBSTRUCT_ARRAY(i, 2)
+ {
+ DUMP_VAR(p_MemMap, tmr_etts[i].tmr_etts_l);
+ DUMP_VAR(p_MemMap, tmr_etts[i].tmr_etts_l);
+ }
+ }
+
+ return E_OK;
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/fm_rtc.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/fm_rtc.h
new file mode 100644
index 0000000..843ca00
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/fm_rtc.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_rtc.h
+
+ @Description Memory map and internal definitions for FM RTC IEEE1588 Timer driver.
+
+ @Cautions None
+*//***************************************************************************/
+
+#ifndef __FM_RTC_H__
+#define __FM_RTC_H__
+
+#include "std_ext.h"
+#include "fm_rtc_ext.h"
+
+
+#define __ERR_MODULE__ MODULE_FM_RTC
+
+/* General definitions */
+
+#define ACCUMULATOR_OVERFLOW ((uint64_t)(1LL << 32))
+#define DEFAULT_OUTPUT_CLOCK_DIVISOR 0x00000002
+#define DEFAULT_BYPASS FALSE
+#define DEFAULT_CLOCK_PERIOD 1000
+
+
+
+typedef struct t_FmRtcAlarm
+{
+ t_FmRtcExceptionsCallback *f_AlarmCallback;
+ bool clearOnExpiration;
+} t_FmRtcAlarm;
+
+typedef struct t_FmRtcPeriodicPulse
+{
+ t_FmRtcExceptionsCallback *f_PeriodicPulseCallback;
+} t_FmRtcPeriodicPulse;
+
+typedef struct t_FmRtcExternalTrigger
+{
+ t_FmRtcExceptionsCallback *f_ExternalTriggerCallback;
+} t_FmRtcExternalTrigger;
+
+
+/**************************************************************************//**
+ @Description RTC FM driver control structure.
+*//***************************************************************************/
+typedef struct t_FmRtc
+{
+ t_Part *p_Part; /**< Pointer to the integration device */
+ t_Handle h_Fm;
+ t_Handle h_App; /**< Application handle */
+ struct rtc_regs *p_MemMap;
+ uint32_t clockPeriodNanoSec; /**< RTC clock period in nano-seconds (for FS mode) */
+ uint32_t srcClkFreqMhz;
+ uint16_t outputClockDivisor; /**< Output clock divisor (for FS mode) */
+ t_FmRtcAlarm alarmParams[FM_RTC_NUM_OF_ALARMS];
+ t_FmRtcPeriodicPulse periodicPulseParams[FM_RTC_NUM_OF_PERIODIC_PULSES];
+ t_FmRtcExternalTrigger externalTriggerParams[FM_RTC_NUM_OF_EXT_TRIGGERS];
+ struct rtc_cfg *p_RtcDriverParam; /**< RTC Driver parameters (for Init phase) */
+} t_FmRtc;
+
+
+#endif /* __FM_RTC_H__ */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/fman_rtc.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/fman_rtc.c
new file mode 100755
index 0000000..acdf507
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Rtc/fman_rtc.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright 2008-2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "fsl_fman_rtc.h"
+
+void fman_rtc_defconfig(struct rtc_cfg *cfg)
+{
+ int i;
+ cfg->src_clk = DEFAULT_SRC_CLOCK;
+ cfg->invert_input_clk_phase = DEFAULT_INVERT_INPUT_CLK_PHASE;
+ cfg->invert_output_clk_phase = DEFAULT_INVERT_OUTPUT_CLK_PHASE;
+ cfg->pulse_realign = DEFAULT_PULSE_REALIGN;
+ for (i = 0; i < FMAN_RTC_MAX_NUM_OF_ALARMS; i++)
+ cfg->alarm_polarity[i] = DEFAULT_ALARM_POLARITY;
+ for (i = 0; i < FMAN_RTC_MAX_NUM_OF_EXT_TRIGGERS; i++)
+ cfg->trigger_polarity[i] = DEFAULT_TRIGGER_POLARITY;
+}
+
+uint32_t fman_rtc_get_events(struct rtc_regs *regs)
+{
+ return ioread32be(&regs->tmr_tevent);
+}
+
+uint32_t fman_rtc_get_event(struct rtc_regs *regs, uint32_t ev_mask)
+{
+ return ioread32be(&regs->tmr_tevent) & ev_mask;
+}
+
+uint32_t fman_rtc_get_interrupt_mask(struct rtc_regs *regs)
+{
+ return ioread32be(&regs->tmr_temask);
+}
+
+void fman_rtc_set_interrupt_mask(struct rtc_regs *regs, uint32_t mask)
+{
+ iowrite32be(mask, &regs->tmr_temask);
+}
+
+void fman_rtc_ack_event(struct rtc_regs *regs, uint32_t events)
+{
+ iowrite32be(events, &regs->tmr_tevent);
+}
+
+uint32_t fman_rtc_check_and_clear_event(struct rtc_regs *regs)
+{
+ uint32_t event;
+
+ event = ioread32be(&regs->tmr_tevent);
+ event &= ioread32be(&regs->tmr_temask);
+
+ if (event)
+ iowrite32be(event, &regs->tmr_tevent);
+ return event;
+}
+
+uint32_t fman_rtc_get_frequency_compensation(struct rtc_regs *regs)
+{
+ return ioread32be(&regs->tmr_add);
+}
+
+void fman_rtc_set_frequency_compensation(struct rtc_regs *regs, uint32_t val)
+{
+ iowrite32be(val, &regs->tmr_add);
+}
+
+void fman_rtc_enable_interupt(struct rtc_regs *regs, uint32_t events)
+{
+ fman_rtc_set_interrupt_mask(regs, fman_rtc_get_interrupt_mask(regs) | events);
+}
+
+void fman_rtc_disable_interupt(struct rtc_regs *regs, uint32_t events)
+{
+ fman_rtc_set_interrupt_mask(regs, fman_rtc_get_interrupt_mask(regs) & ~events);
+}
+
+void fman_rtc_set_timer_alarm_l(struct rtc_regs *regs, int index, uint32_t val)
+{
+ iowrite32be(val, &regs->tmr_alarm[index].tmr_alarm_l);
+}
+
+void fman_rtc_set_timer_fiper(struct rtc_regs *regs, int index, uint32_t val)
+{
+ iowrite32be(val, &regs->tmr_fiper[index]);
+}
+
+void fman_rtc_set_timer_alarm(struct rtc_regs *regs, int index, int64_t val)
+{
+ iowrite32be((uint32_t)val, &regs->tmr_alarm[index].tmr_alarm_l);
+ iowrite32be((uint32_t)(val >> 32), &regs->tmr_alarm[index].tmr_alarm_h);
+}
+
+void fman_rtc_set_timer_offset(struct rtc_regs *regs, int64_t val)
+{
+ iowrite32be((uint32_t)val, &regs->tmr_off_l);
+ iowrite32be((uint32_t)(val >> 32), &regs->tmr_off_h);
+}
+
+uint64_t fman_rtc_get_trigger_stamp(struct rtc_regs *regs, int id)
+{
+ uint64_t time;
+ /* TMR_CNT_L must be read first to get an accurate value */
+ time = (uint64_t)ioread32be(&regs->tmr_etts[id].tmr_etts_l);
+ time |= ((uint64_t)ioread32be(&regs->tmr_etts[id].tmr_etts_h)
+ << 32);
+
+ return time;
+}
+
+uint32_t fman_rtc_get_timer_ctrl(struct rtc_regs *regs)
+{
+ return ioread32be(&regs->tmr_ctrl);
+}
+
+void fman_rtc_set_timer_ctrl(struct rtc_regs *regs, uint32_t val)
+{
+ iowrite32be(val, &regs->tmr_ctrl);
+}
+
+void fman_rtc_timers_soft_reset(struct rtc_regs *regs)
+{
+ fman_rtc_set_timer_ctrl(regs, FMAN_RTC_TMR_CTRL_TMSR);
+ udelay(10);
+ fman_rtc_set_timer_ctrl(regs, 0);
+}
+
+void fman_rtc_init(struct rtc_cfg *cfg, struct rtc_regs *regs, int num_alarms,
+ int num_fipers, int num_ext_triggers, bool init_freq_comp,
+ uint32_t freq_compensation, uint32_t output_clock_divisor)
+{
+ uint32_t tmr_ctrl;
+ int i;
+
+ fman_rtc_timers_soft_reset(regs);
+
+ /* Set the source clock */
+ switch (cfg->src_clk) {
+ case E_FMAN_RTC_SOURCE_CLOCK_SYSTEM:
+ tmr_ctrl = FMAN_RTC_TMR_CTRL_CKSEL_MAC_CLK;
+ break;
+ case E_FMAN_RTC_SOURCE_CLOCK_OSCILATOR:
+ tmr_ctrl = FMAN_RTC_TMR_CTRL_CKSEL_OSC_CLK;
+ break;
+ default:
+ /* Use a clock from the External TMR reference clock.*/
+ tmr_ctrl = FMAN_RTC_TMR_CTRL_CKSEL_EXT_CLK;
+ break;
+ }
+
+ /* whatever period the user picked, the timestamp will advance in '1'
+ * every time the period passed. */
+ tmr_ctrl |= ((1 << FMAN_RTC_TMR_CTRL_TCLK_PERIOD_SHIFT) &
+ FMAN_RTC_TMR_CTRL_TCLK_PERIOD_MASK);
+
+ if (cfg->invert_input_clk_phase)
+ tmr_ctrl |= FMAN_RTC_TMR_CTRL_CIPH;
+ if (cfg->invert_output_clk_phase)
+ tmr_ctrl |= FMAN_RTC_TMR_CTRL_COPH;
+
+ for (i = 0; i < num_alarms; i++) {
+ if (cfg->alarm_polarity[i] ==
+ E_FMAN_RTC_ALARM_POLARITY_ACTIVE_LOW)
+ tmr_ctrl |= (FMAN_RTC_TMR_CTRL_ALMP1 >> i);
+ }
+
+ for (i = 0; i < num_ext_triggers; i++)
+ if (cfg->trigger_polarity[i] ==
+ E_FMAN_RTC_TRIGGER_ON_FALLING_EDGE)
+ tmr_ctrl |= (FMAN_RTC_TMR_CTRL_ETEP1 << i);
+
+ if (!cfg->timer_slave_mode && cfg->bypass)
+ tmr_ctrl |= FMAN_RTC_TMR_CTRL_BYP;
+
+ fman_rtc_set_timer_ctrl(regs, tmr_ctrl);
+ if (init_freq_comp)
+ fman_rtc_set_frequency_compensation(regs, freq_compensation);
+
+ /* Clear TMR_ALARM registers */
+ for (i = 0; i < num_alarms; i++)
+ fman_rtc_set_timer_alarm(regs, i, 0xFFFFFFFFFFFFFFFFLL);
+
+ /* Clear TMR_TEVENT */
+ fman_rtc_ack_event(regs, FMAN_RTC_TMR_TEVENT_ALL);
+
+ /* Initialize TMR_TEMASK */
+ fman_rtc_set_interrupt_mask(regs, 0);
+
+ /* Clear TMR_FIPER registers */
+ for (i = 0; i < num_fipers; i++)
+ fman_rtc_set_timer_fiper(regs, i, 0xFFFFFFFF);
+
+ /* Initialize TMR_PRSC */
+ iowrite32be(output_clock_divisor, &regs->tmr_prsc);
+
+ /* Clear TMR_OFF */
+ fman_rtc_set_timer_offset(regs, 0);
+}
+
+bool fman_rtc_is_enabled(struct rtc_regs *regs)
+{
+ return (bool)(fman_rtc_get_timer_ctrl(regs) & FMAN_RTC_TMR_CTRL_TE);
+}
+
+void fman_rtc_enable(struct rtc_regs *regs, bool reset_clock)
+{
+ uint32_t tmr_ctrl = fman_rtc_get_timer_ctrl(regs);
+
+ /* TODO check that no timestamping MACs are working in this stage. */
+ if (reset_clock) {
+ fman_rtc_set_timer_ctrl(regs, (tmr_ctrl | FMAN_RTC_TMR_CTRL_TMSR));
+
+ udelay(10);
+ /* Clear TMR_OFF */
+ fman_rtc_set_timer_offset(regs, 0);
+ }
+
+ fman_rtc_set_timer_ctrl(regs, (tmr_ctrl | FMAN_RTC_TMR_CTRL_TE));
+}
+
+void fman_rtc_disable(struct rtc_regs *regs)
+{
+ fman_rtc_set_timer_ctrl(regs, (fman_rtc_get_timer_ctrl(regs)
+ & ~(FMAN_RTC_TMR_CTRL_TE)));
+}
+
+void fman_rtc_clear_periodic_pulse(struct rtc_regs *regs, int id)
+{
+ uint32_t tmp_reg;
+ if (id == 0)
+ tmp_reg = FMAN_RTC_TMR_TEVENT_PP1;
+ else
+ tmp_reg = FMAN_RTC_TMR_TEVENT_PP2;
+ fman_rtc_disable_interupt(regs, tmp_reg);
+
+ tmp_reg = fman_rtc_get_timer_ctrl(regs);
+ if (tmp_reg & FMAN_RTC_TMR_CTRL_FS)
+ fman_rtc_set_timer_ctrl(regs, tmp_reg & ~FMAN_RTC_TMR_CTRL_FS);
+
+ fman_rtc_set_timer_fiper(regs, id, 0xFFFFFFFF);
+}
+
+void fman_rtc_clear_external_trigger(struct rtc_regs *regs, int id)
+{
+ uint32_t tmpReg, tmp_ctrl;
+
+ if (id == 0)
+ tmpReg = FMAN_RTC_TMR_TEVENT_ETS1;
+ else
+ tmpReg = FMAN_RTC_TMR_TEVENT_ETS2;
+ fman_rtc_disable_interupt(regs, tmpReg);
+
+ if (id == 0)
+ tmpReg = FMAN_RTC_TMR_CTRL_PP1L;
+ else
+ tmpReg = FMAN_RTC_TMR_CTRL_PP2L;
+ tmp_ctrl = fman_rtc_get_timer_ctrl(regs);
+ if (tmp_ctrl & tmpReg)
+ fman_rtc_set_timer_ctrl(regs, tmp_ctrl & ~tmpReg);
+}
+
+void fman_rtc_set_alarm(struct rtc_regs *regs, int id, uint32_t val, bool enable)
+{
+ uint32_t tmpReg;
+ fman_rtc_set_timer_alarm(regs, id, val);
+ if (enable) {
+ if (id == 0)
+ tmpReg = FMAN_RTC_TMR_TEVENT_ALM1;
+ else
+ tmpReg = FMAN_RTC_TMR_TEVENT_ALM2;
+ fman_rtc_enable_interupt(regs, tmpReg);
+ }
+}
+
+void fman_rtc_set_periodic_pulse(struct rtc_regs *regs, int id, uint32_t val,
+ bool enable)
+{
+ uint32_t tmpReg;
+ fman_rtc_set_timer_fiper(regs, id, val);
+ if (enable) {
+ if (id == 0)
+ tmpReg = FMAN_RTC_TMR_TEVENT_PP1;
+ else
+ tmpReg = FMAN_RTC_TMR_TEVENT_PP2;
+ fman_rtc_enable_interupt(regs, tmpReg);
+ }
+}
+
+void fman_rtc_set_ext_trigger(struct rtc_regs *regs, int id, bool enable,
+ bool use_pulse_as_input)
+{
+ uint32_t tmpReg;
+ if (enable) {
+ if (id == 0)
+ tmpReg = FMAN_RTC_TMR_TEVENT_ETS1;
+ else
+ tmpReg = FMAN_RTC_TMR_TEVENT_ETS2;
+ fman_rtc_enable_interupt(regs, tmpReg);
+ }
+ if (use_pulse_as_input) {
+ if (id == 0)
+ tmpReg = FMAN_RTC_TMR_CTRL_PP1L;
+ else
+ tmpReg = FMAN_RTC_TMR_CTRL_PP2L;
+ fman_rtc_set_timer_ctrl(regs, fman_rtc_get_timer_ctrl(regs) | tmpReg);
+ }
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/Makefile b/drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/Makefile
new file mode 100644
index 0000000..669e940
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/Makefile
@@ -0,0 +1,15 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+
+NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc
+
+EXTRA_CFLAGS += -I$(NCSW_FM_INC)
+
+obj-y += fsl-ncsw-sp.o
+
+fsl-ncsw-sp-objs := fm_sp.o fman_sp.o
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/fm_sp.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/fm_sp.c
new file mode 100644
index 0000000..14b15a1
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/fm_sp.c
@@ -0,0 +1,757 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_sp.c
+
+ @Description FM PCD Storage profile ...
+*//***************************************************************************/
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "string_ext.h"
+#include "debug_ext.h"
+#include "net_ext.h"
+
+#include "fm_vsp_ext.h"
+#include "fm_sp.h"
+#include "fm_common.h"
+#include "fsl_fman_sp.h"
+
+
+#if (DPAA_VERSION >= 11)
+static t_Error CheckParamsGeneratedInternally(t_FmVspEntry *p_FmVspEntry)
+{
+ t_Error err = E_OK;
+
+ if ((err = FmSpCheckIntContextParams(&p_FmVspEntry->intContext))!= E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if ((err = FmSpCheckBufMargins(&p_FmVspEntry->bufMargins)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ return err;
+
+}
+
+static t_Error CheckParams(t_FmVspEntry *p_FmVspEntry)
+{
+ t_Error err = E_OK;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->h_Fm, E_INVALID_HANDLE);
+
+ if ((err = FmSpCheckBufPoolsParams(&p_FmVspEntry->p_FmVspEntryDriverParams->extBufPools,
+ p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools,
+ p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion)) != E_OK)
+
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (p_FmVspEntry->p_FmVspEntryDriverParams->liodnOffset & ~FM_LIODN_OFFSET_MASK)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("liodnOffset is larger than %d", FM_LIODN_OFFSET_MASK+1));
+
+ err = FmVSPCheckRelativeProfile(p_FmVspEntry->h_Fm,
+ p_FmVspEntry->portType,
+ p_FmVspEntry->portId,
+ p_FmVspEntry->relativeProfileId);
+
+ return err;
+}
+#endif /* (DPAA_VERSION >= 11) */
+
+
+/*****************************************************************************/
+/* Inter-module API routines */
+/*****************************************************************************/
+void FmSpSetBufPoolsInAscOrderOfBufSizes(t_FmExtPools *p_FmExtPools,
+ uint8_t *orderedArray,
+ uint16_t *sizesArray)
+{
+ uint16_t bufSize = 0;
+ int i=0, j=0, k=0;
+
+ /* First we copy the external buffers pools information to an ordered local array */
+ for (i=0;i<p_FmExtPools->numOfPoolsUsed;i++)
+ {
+ /* get pool size */
+ bufSize = p_FmExtPools->extBufPool[i].size;
+
+ /* keep sizes in an array according to poolId for direct access */
+ sizesArray[p_FmExtPools->extBufPool[i].id] = bufSize;
+
+ /* save poolId in an ordered array according to size */
+ for (j=0;j<=i;j++)
+ {
+ /* this is the next free place in the array */
+ if (j==i)
+ orderedArray[i] = p_FmExtPools->extBufPool[i].id;
+ else
+ {
+ /* find the right place for this poolId */
+ if (bufSize < sizesArray[orderedArray[j]])
+ {
+ /* move the poolIds one place ahead to make room for this poolId */
+ for (k=i;k>j;k--)
+ orderedArray[k] = orderedArray[k-1];
+
+ /* now k==j, this is the place for the new size */
+ orderedArray[k] = p_FmExtPools->extBufPool[i].id;
+ break;
+ }
+ }
+ }
+ }
+}
+
+t_Error FmSpCheckBufPoolsParams(t_FmExtPools *p_FmExtPools,
+ t_FmBackupBmPools *p_FmBackupBmPools,
+ t_FmBufPoolDepletion *p_FmBufPoolDepletion)
+{
+
+ int i = 0, j = 0;
+ bool found;
+ uint8_t count = 0;
+
+ if (p_FmExtPools)
+ {
+ if (p_FmExtPools->numOfPoolsUsed > FM_PORT_MAX_NUM_OF_EXT_POOLS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numOfPoolsUsed can't be larger than %d", FM_PORT_MAX_NUM_OF_EXT_POOLS));
+
+ for (i=0;i<p_FmExtPools->numOfPoolsUsed;i++)
+ {
+ if (p_FmExtPools->extBufPool[i].id >= BM_MAX_NUM_OF_POOLS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("extBufPools.extBufPool[%d].id can't be larger than %d", i, BM_MAX_NUM_OF_POOLS));
+ if (!p_FmExtPools->extBufPool[i].size)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("extBufPools.extBufPool[%d].size is 0", i));
+ }
+ }
+ if (!p_FmExtPools && (p_FmBackupBmPools || p_FmBufPoolDepletion))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("backupBmPools ot bufPoolDepletion can not be defined without external pools"));
+
+ /* backup BM pools indication is valid only for some chip derivatives
+ (limited by the config routine) */
+ if (p_FmBackupBmPools)
+ {
+ if (p_FmBackupBmPools->numOfBackupPools >= p_FmExtPools->numOfPoolsUsed)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("p_BackupBmPools must be smaller than extBufPools.numOfPoolsUsed"));
+ found = FALSE;
+ for (i = 0;i<p_FmBackupBmPools->numOfBackupPools;i++)
+ {
+
+ for (j=0;j<p_FmExtPools->numOfPoolsUsed;j++)
+ {
+ if (p_FmBackupBmPools->poolIds[i] == p_FmExtPools->extBufPool[j].id)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ if (!found)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("All p_BackupBmPools.poolIds must be included in extBufPools.extBufPool[n].id"));
+ else
+ found = FALSE;
+ }
+ }
+
+ /* up to extBufPools.numOfPoolsUsed pools may be defined */
+ if (p_FmBufPoolDepletion && p_FmBufPoolDepletion->poolsGrpModeEnable)
+ {
+ if ((p_FmBufPoolDepletion->numOfPools > p_FmExtPools->numOfPoolsUsed))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufPoolDepletion.numOfPools can't be larger than %d and can't be larger than numOfPoolsUsed", FM_PORT_MAX_NUM_OF_EXT_POOLS));
+
+ if (!p_FmBufPoolDepletion->numOfPools)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufPoolDepletion.numOfPoolsToConsider can not be 0 when poolsGrpModeEnable=TRUE"));
+
+ found = FALSE;
+ count = 0;
+ /* for each pool that is in poolsToConsider, check if it is defined
+ in extBufPool */
+ for (i=0;i<BM_MAX_NUM_OF_POOLS;i++)
+ {
+ if (p_FmBufPoolDepletion->poolsToConsider[i])
+ {
+ for (j=0;j<p_FmExtPools->numOfPoolsUsed;j++)
+ {
+ if (i == p_FmExtPools->extBufPool[j].id)
+ {
+ found = TRUE;
+ count++;
+ break;
+ }
+ }
+ if (!found)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Pools selected for depletion are not used."));
+ else
+ found = FALSE;
+ }
+ }
+ /* check that the number of pools that we have checked is equal to the number announced by the user */
+ if (count != p_FmBufPoolDepletion->numOfPools)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufPoolDepletion.numOfPools is larger than the number of pools defined."));
+ }
+
+ if (p_FmBufPoolDepletion && p_FmBufPoolDepletion->singlePoolModeEnable)
+ {
+ /* calculate vector for number of pools depletion */
+ found = FALSE;
+ count = 0;
+ for (i=0;i<BM_MAX_NUM_OF_POOLS;i++)
+ {
+ if (p_FmBufPoolDepletion->poolsToConsiderForSingleMode[i])
+ {
+ for (j=0;j<p_FmExtPools->numOfPoolsUsed;j++)
+ {
+ if (i == p_FmExtPools->extBufPool[j].id)
+ {
+ found = TRUE;
+ count++;
+ break;
+ }
+ }
+ if (!found)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Pools selected for depletion are not used."));
+ else
+ found = FALSE;
+ }
+ }
+ if (!count)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("No pools defined for single buffer mode pool depletion."));
+ }
+
+ return E_OK;
+}
+
+t_Error FmSpCheckIntContextParams(t_FmSpIntContextDataCopy *p_FmSpIntContextDataCopy)
+{
+ /* Check that divisible by 16 and not larger than 240 */
+ if (p_FmSpIntContextDataCopy->intContextOffset >MAX_INT_OFFSET)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.intContextOffset can't be larger than %d", MAX_INT_OFFSET));
+ if (p_FmSpIntContextDataCopy->intContextOffset % OFFSET_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.intContextOffset has to be divisible by %d", OFFSET_UNITS));
+
+ /* check that ic size+ic internal offset, does not exceed ic block size */
+ if (p_FmSpIntContextDataCopy->size + p_FmSpIntContextDataCopy->intContextOffset > MAX_IC_SIZE)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.size + intContext.intContextOffset has to be smaller than %d", MAX_IC_SIZE));
+ /* Check that divisible by 16 and not larger than 256 */
+ if (p_FmSpIntContextDataCopy->size % OFFSET_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.size has to be divisible by %d", OFFSET_UNITS));
+
+ /* Check that divisible by 16 and not larger than 4K */
+ if (p_FmSpIntContextDataCopy->extBufOffset > MAX_EXT_OFFSET)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.extBufOffset can't be larger than %d", MAX_EXT_OFFSET));
+ if (p_FmSpIntContextDataCopy->extBufOffset % OFFSET_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("intContext.extBufOffset has to be divisible by %d", OFFSET_UNITS));
+
+ return E_OK;
+}
+
+t_Error FmSpCheckBufMargins(t_FmSpBufMargins *p_FmSpBufMargins)
+{
+ /* Check the margin definition */
+ if (p_FmSpBufMargins->startMargins > MAX_EXT_BUFFER_OFFSET)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufMargins.startMargins can't be larger than %d", MAX_EXT_BUFFER_OFFSET));
+ if (p_FmSpBufMargins->endMargins > MAX_EXT_BUFFER_OFFSET)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("bufMargins.endMargins can't be larger than %d", MAX_EXT_BUFFER_OFFSET));
+
+ return E_OK;
+}
+
+t_Error FmSpBuildBufferStructure(t_FmSpIntContextDataCopy *p_FmSpIntContextDataCopy,
+ t_FmBufferPrefixContent *p_BufferPrefixContent,
+ t_FmSpBufMargins *p_FmSpBufMargins,
+ t_FmSpBufferOffsets *p_FmSpBufferOffsets,
+ uint8_t *internalBufferOffset)
+{
+ uint32_t tmp;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmSpIntContextDataCopy, E_INVALID_VALUE);
+ ASSERT_COND(p_FmSpIntContextDataCopy);
+ ASSERT_COND(p_BufferPrefixContent);
+ ASSERT_COND(p_FmSpBufMargins);
+ ASSERT_COND(p_FmSpBufferOffsets);
+
+ /* Align start of internal context data to 16 byte */
+ p_FmSpIntContextDataCopy->extBufOffset =
+ (uint16_t)((p_BufferPrefixContent->privDataSize & (OFFSET_UNITS-1)) ?
+ ((p_BufferPrefixContent->privDataSize + OFFSET_UNITS) & ~(uint16_t)(OFFSET_UNITS-1)) :
+ p_BufferPrefixContent->privDataSize);
+
+ /* Translate margin and intContext params to FM parameters */
+ /* Initialize with illegal value. Later we'll set legal values. */
+ p_FmSpBufferOffsets->prsResultOffset = (uint32_t)ILLEGAL_BASE;
+ p_FmSpBufferOffsets->timeStampOffset = (uint32_t)ILLEGAL_BASE;
+ p_FmSpBufferOffsets->hashResultOffset= (uint32_t)ILLEGAL_BASE;
+ p_FmSpBufferOffsets->pcdInfoOffset = (uint32_t)ILLEGAL_BASE;
+
+ /* Internally the driver supports 4 options
+ 1. prsResult/timestamp/hashResult selection (in fact 8 options, but for simplicity we'll
+ relate to it as 1).
+ 2. All IC context (from AD) not including debug.*/
+
+ /* This 'if' covers option 2. We copy from beginning of context. */
+ if (p_BufferPrefixContent->passAllOtherPCDInfo)
+ {
+ p_FmSpIntContextDataCopy->size = 128; /* must be aligned to 16 */
+ /* Start copying data after 16 bytes (FD) from the beginning of the internal context */
+ p_FmSpIntContextDataCopy->intContextOffset = 16;
+
+ if (p_BufferPrefixContent->passAllOtherPCDInfo)
+ p_FmSpBufferOffsets->pcdInfoOffset = p_FmSpIntContextDataCopy->extBufOffset;
+ if (p_BufferPrefixContent->passPrsResult)
+ p_FmSpBufferOffsets->prsResultOffset =
+ (uint32_t)(p_FmSpIntContextDataCopy->extBufOffset + 16);
+ if (p_BufferPrefixContent->passTimeStamp)
+ p_FmSpBufferOffsets->timeStampOffset =
+ (uint32_t)(p_FmSpIntContextDataCopy->extBufOffset + 48);
+ if (p_BufferPrefixContent->passHashResult)
+ p_FmSpBufferOffsets->hashResultOffset =
+ (uint32_t)(p_FmSpIntContextDataCopy->extBufOffset + 56);
+ }
+ else
+ {
+ /* This case covers the options under 1 */
+ /* Copy size must be in 16-byte granularity. */
+ p_FmSpIntContextDataCopy->size =
+ (uint16_t)((p_BufferPrefixContent->passPrsResult ? 32 : 0) +
+ ((p_BufferPrefixContent->passTimeStamp ||
+ p_BufferPrefixContent->passHashResult) ? 16 : 0));
+
+ /* Align start of internal context data to 16 byte */
+ p_FmSpIntContextDataCopy->intContextOffset =
+ (uint8_t)(p_BufferPrefixContent->passPrsResult ? 32 :
+ ((p_BufferPrefixContent->passTimeStamp ||
+ p_BufferPrefixContent->passHashResult) ? 64 : 0));
+
+ if (p_BufferPrefixContent->passPrsResult)
+ p_FmSpBufferOffsets->prsResultOffset = p_FmSpIntContextDataCopy->extBufOffset;
+ if (p_BufferPrefixContent->passTimeStamp)
+ p_FmSpBufferOffsets->timeStampOffset = p_BufferPrefixContent->passPrsResult ?
+ (p_FmSpIntContextDataCopy->extBufOffset + sizeof(t_FmPrsResult)) :
+ p_FmSpIntContextDataCopy->extBufOffset;
+ if (p_BufferPrefixContent->passHashResult)
+ /* If PR is not requested, whether TS is requested or not, IC will be copied from TS */
+ p_FmSpBufferOffsets->hashResultOffset = p_BufferPrefixContent->passPrsResult ?
+ (p_FmSpIntContextDataCopy->extBufOffset + sizeof(t_FmPrsResult) + 8) :
+ p_FmSpIntContextDataCopy->extBufOffset + 8;
+ }
+
+ if (p_FmSpIntContextDataCopy->size)
+ p_FmSpBufMargins->startMargins =
+ (uint16_t)(p_FmSpIntContextDataCopy->extBufOffset +
+ p_FmSpIntContextDataCopy->size);
+ else
+ /* No Internal Context passing, STartMargin is immediately after privateInfo */
+ p_FmSpBufMargins->startMargins = p_BufferPrefixContent->privDataSize;
+
+ /* save extra space for manip in both external and internal buffers */
+ if (p_BufferPrefixContent->manipExtraSpace)
+ {
+ uint8_t extraSpace;
+#ifdef FM_CAPWAP_SUPPORT
+ if ((p_BufferPrefixContent->manipExtraSpace + CAPWAP_FRAG_EXTRA_SPACE) >= 256)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("p_BufferPrefixContent->manipExtraSpace should be less than %d",
+ 256-CAPWAP_FRAG_EXTRA_SPACE));
+ extraSpace = (uint8_t)(p_BufferPrefixContent->manipExtraSpace + CAPWAP_FRAG_EXTRA_SPACE);
+#else
+ extraSpace = p_BufferPrefixContent->manipExtraSpace;
+#endif /* FM_CAPWAP_SUPPORT */
+ p_FmSpBufferOffsets->manipOffset = p_FmSpBufMargins->startMargins;
+ p_FmSpBufMargins->startMargins += extraSpace;
+ *internalBufferOffset = extraSpace;
+ }
+
+ /* align data start */
+ tmp = (uint32_t)(p_FmSpBufMargins->startMargins % p_BufferPrefixContent->dataAlign);
+ if (tmp)
+ p_FmSpBufMargins->startMargins += (p_BufferPrefixContent->dataAlign-tmp);
+ p_FmSpBufferOffsets->dataOffset = p_FmSpBufMargins->startMargins;
+
+ return E_OK;
+}
+/*********************** End of inter-module routines ************************/
+
+
+#if (DPAA_VERSION >= 11)
+/*****************************************************************************/
+/* API routines */
+/*****************************************************************************/
+t_Handle FM_VSP_Config(t_FmVspParams *p_FmVspParams)
+{
+ t_FmVspEntry *p_FmVspEntry = NULL;
+ struct fm_storage_profile_params fm_vsp_params;
+
+ p_FmVspEntry = (t_FmVspEntry *)XX_Malloc(sizeof(t_FmVspEntry));
+ if (!p_FmVspEntry)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("p_StorageProfile allocation failed"));
+ return NULL;
+ }
+ memset(p_FmVspEntry, 0, sizeof(t_FmVspEntry));
+
+ p_FmVspEntry->p_FmVspEntryDriverParams = (t_FmVspEntryDriverParams *)XX_Malloc(sizeof(t_FmVspEntryDriverParams));
+ if (!p_FmVspEntry->p_FmVspEntryDriverParams)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("p_StorageProfile allocation failed"));
+ XX_Free(p_FmVspEntry);
+ return NULL;
+ }
+ memset(p_FmVspEntry->p_FmVspEntryDriverParams, 0, sizeof(t_FmVspEntryDriverParams));
+ fman_vsp_defconfig(&fm_vsp_params);
+ p_FmVspEntry->p_FmVspEntryDriverParams->dmaHeaderCacheAttr = fm_vsp_params.header_cache_attr;
+ p_FmVspEntry->p_FmVspEntryDriverParams->dmaIntContextCacheAttr = fm_vsp_params.int_context_cache_attr;
+ p_FmVspEntry->p_FmVspEntryDriverParams->dmaScatterGatherCacheAttr = fm_vsp_params.scatter_gather_cache_attr;
+ p_FmVspEntry->p_FmVspEntryDriverParams->dmaSwapData = fm_vsp_params.dma_swap_data;
+ p_FmVspEntry->p_FmVspEntryDriverParams->dmaWriteOptimize = fm_vsp_params.dma_write_optimize;
+ p_FmVspEntry->p_FmVspEntryDriverParams->noScatherGather = fm_vsp_params.no_scather_gather;
+ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.privDataSize = DEFAULT_FM_SP_bufferPrefixContent_privDataSize;
+ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.passPrsResult= DEFAULT_FM_SP_bufferPrefixContent_passPrsResult;
+ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.passTimeStamp= DEFAULT_FM_SP_bufferPrefixContent_passTimeStamp;
+ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.passAllOtherPCDInfo
+ = DEFAULT_FM_SP_bufferPrefixContent_passTimeStamp;
+ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.dataAlign = DEFAULT_FM_SP_bufferPrefixContent_dataAlign;
+ p_FmVspEntry->p_FmVspEntryDriverParams->liodnOffset = p_FmVspParams->liodnOffset;
+
+ memcpy(&p_FmVspEntry->p_FmVspEntryDriverParams->extBufPools, &p_FmVspParams->extBufPools, sizeof(t_FmExtPools));
+ p_FmVspEntry->h_Fm = p_FmVspParams->h_Fm;
+ p_FmVspEntry->portType = p_FmVspParams->portParams.portType;
+ p_FmVspEntry->portId = p_FmVspParams->portParams.portId;
+
+ p_FmVspEntry->relativeProfileId = p_FmVspParams->relativeProfileId;
+
+ return p_FmVspEntry;
+}
+
+t_Error FM_VSP_Init(t_Handle h_FmVsp)
+{
+
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry *)h_FmVsp;
+ struct fm_storage_profile_params fm_vsp_params;
+ uint8_t orderedArray[FM_PORT_MAX_NUM_OF_EXT_POOLS];
+ uint16_t sizesArray[BM_MAX_NUM_OF_POOLS];
+ t_Error err;
+ uint16_t absoluteProfileId = 0;
+ int i = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams,E_INVALID_HANDLE);
+
+ CHECK_INIT_PARAMETERS(p_FmVspEntry, CheckParams);
+
+ memset(&orderedArray, 0, sizeof(uint8_t) * FM_PORT_MAX_NUM_OF_EXT_POOLS);
+ memset(&sizesArray, 0, sizeof(uint16_t) * BM_MAX_NUM_OF_POOLS);
+
+ err = FmSpBuildBufferStructure(&p_FmVspEntry->intContext,
+ &p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent,
+ &p_FmVspEntry->bufMargins,
+ &p_FmVspEntry->bufferOffsets,
+ &p_FmVspEntry->internalBufferOffset);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+
+ err = CheckParamsGeneratedInternally(p_FmVspEntry);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+
+ p_FmVspEntry->p_FmSpRegsBase =
+ (struct fm_pcd_storage_profile_regs *)FmGetVSPBaseAddr(p_FmVspEntry->h_Fm);
+ if (!p_FmVspEntry->p_FmSpRegsBase)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("impossible to initialize SpRegsBase"));
+
+ /* order external buffer pools in ascending order of buffer pools sizes */
+ FmSpSetBufPoolsInAscOrderOfBufSizes(&(p_FmVspEntry->p_FmVspEntryDriverParams)->extBufPools,
+ orderedArray,
+ sizesArray);
+
+ p_FmVspEntry->extBufPools.numOfPoolsUsed =
+ p_FmVspEntry->p_FmVspEntryDriverParams->extBufPools.numOfPoolsUsed;
+ for (i = 0; i < p_FmVspEntry->extBufPools.numOfPoolsUsed; i++)
+ {
+ p_FmVspEntry->extBufPools.extBufPool[i].id = orderedArray[i];
+ p_FmVspEntry->extBufPools.extBufPool[i].size = sizesArray[orderedArray[i]];
+ }
+
+ /* on user responsibility to fill it according requirement */
+ memset(&fm_vsp_params, 0, sizeof(struct fm_storage_profile_params));
+ fm_vsp_params.dma_swap_data = p_FmVspEntry->p_FmVspEntryDriverParams->dmaSwapData;
+ fm_vsp_params.int_context_cache_attr = p_FmVspEntry->p_FmVspEntryDriverParams->dmaIntContextCacheAttr;
+ fm_vsp_params.header_cache_attr = p_FmVspEntry->p_FmVspEntryDriverParams->dmaHeaderCacheAttr;
+ fm_vsp_params.scatter_gather_cache_attr = p_FmVspEntry->p_FmVspEntryDriverParams->dmaScatterGatherCacheAttr;
+ fm_vsp_params.dma_write_optimize = p_FmVspEntry->p_FmVspEntryDriverParams->dmaWriteOptimize;
+ fm_vsp_params.liodn_offset = p_FmVspEntry->p_FmVspEntryDriverParams->liodnOffset;
+ fm_vsp_params.no_scather_gather = p_FmVspEntry->p_FmVspEntryDriverParams->noScatherGather;
+
+ if (p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion)
+ {
+ fm_vsp_params.buf_pool_depletion.buf_pool_depletion_enabled = TRUE;
+ fm_vsp_params.buf_pool_depletion.pools_grp_mode_enable = p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion->poolsGrpModeEnable;
+ fm_vsp_params.buf_pool_depletion.num_pools = p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion->numOfPools;
+ fm_vsp_params.buf_pool_depletion.pools_to_consider = p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion->poolsToConsider;
+ fm_vsp_params.buf_pool_depletion.single_pool_mode_enable = p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion->singlePoolModeEnable;
+ fm_vsp_params.buf_pool_depletion.pools_to_consider_for_single_mode = p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion->poolsToConsiderForSingleMode;
+ fm_vsp_params.buf_pool_depletion.has_pfc_priorities = TRUE;
+ fm_vsp_params.buf_pool_depletion.pfc_priorities_en = p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion->pfcPrioritiesEn;
+ }
+ else
+ fm_vsp_params.buf_pool_depletion.buf_pool_depletion_enabled = FALSE;
+
+ if (p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools)
+ {
+ fm_vsp_params.backup_pools.num_backup_pools = p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools->numOfBackupPools;
+ fm_vsp_params.backup_pools.pool_ids = p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools->poolIds;
+ }
+ else
+ fm_vsp_params.backup_pools.num_backup_pools = 0;
+
+ fm_vsp_params.fm_ext_pools.num_pools_used = p_FmVspEntry->extBufPools.numOfPoolsUsed;
+ fm_vsp_params.fm_ext_pools.ext_buf_pool = (struct fman_ext_pool_params*)&p_FmVspEntry->extBufPools.extBufPool;
+ fm_vsp_params.buf_margins = (struct fman_sp_buf_margins*)&p_FmVspEntry->bufMargins;
+ fm_vsp_params.int_context = (struct fman_sp_int_context_data_copy*)&p_FmVspEntry->intContext;
+
+ /* no check on err - it was checked earlier */
+ FmVSPGetAbsoluteProfileId(p_FmVspEntry->h_Fm,
+ p_FmVspEntry->portType,
+ p_FmVspEntry->portId,
+ p_FmVspEntry->relativeProfileId,
+ &absoluteProfileId);
+
+ ASSERT_COND(p_FmVspEntry->p_FmSpRegsBase);
+ ASSERT_COND(fm_vsp_params.int_context);
+ ASSERT_COND(fm_vsp_params.buf_margins);
+ ASSERT_COND(IN_RANGE(0, absoluteProfileId, FM_VSP_MAX_NUM_OF_ENTRIES));
+
+ /* Set all registers related to VSP */
+ fman_vsp_init(p_FmVspEntry->p_FmSpRegsBase, absoluteProfileId, &fm_vsp_params,FM_PORT_MAX_NUM_OF_EXT_POOLS, BM_MAX_NUM_OF_POOLS, FM_MAX_NUM_OF_PFC_PRIORITIES);
+
+ p_FmVspEntry->absoluteSpId = absoluteProfileId;
+
+ if (p_FmVspEntry->p_FmVspEntryDriverParams)
+ XX_Free(p_FmVspEntry->p_FmVspEntryDriverParams);
+ p_FmVspEntry->p_FmVspEntryDriverParams = NULL;
+
+ return E_OK;
+}
+
+t_Error FM_VSP_Free(t_Handle h_FmVsp)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry *)h_FmVsp;
+ SANITY_CHECK_RETURN_ERROR(h_FmVsp, E_INVALID_HANDLE);
+ XX_Free(p_FmVspEntry);
+ return E_OK;
+}
+
+t_Error FM_VSP_ConfigBufferPrefixContent(t_Handle h_FmVsp, t_FmBufferPrefixContent *p_FmBufferPrefixContent)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE);
+
+ memcpy(&p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent, p_FmBufferPrefixContent, sizeof(t_FmBufferPrefixContent));
+ /* if dataAlign was not initialized by user, we return to driver's default */
+ if (!p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.dataAlign)
+ p_FmVspEntry->p_FmVspEntryDriverParams->bufferPrefixContent.dataAlign = DEFAULT_FM_SP_bufferPrefixContent_dataAlign;
+
+ return E_OK;
+}
+
+t_Error FM_VSP_ConfigDmaSwapData(t_Handle h_FmVsp, e_FmDmaSwapOption swapData)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE);
+
+ p_FmVspEntry->p_FmVspEntryDriverParams->dmaSwapData = swapData;
+
+ return E_OK;
+}
+
+t_Error FM_VSP_ConfigDmaIcCacheAttr(t_Handle h_FmVsp, e_FmDmaCacheOption intContextCacheAttr)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE);
+
+ p_FmVspEntry->p_FmVspEntryDriverParams->dmaIntContextCacheAttr = intContextCacheAttr;
+
+ return E_OK;
+}
+
+t_Error FM_VSP_ConfigDmaHdrAttr(t_Handle h_FmVsp, e_FmDmaCacheOption headerCacheAttr)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE);
+
+ p_FmVspEntry->p_FmVspEntryDriverParams->dmaHeaderCacheAttr = headerCacheAttr;
+
+ return E_OK;
+}
+
+t_Error FM_VSP_ConfigDmaScatterGatherAttr(t_Handle h_FmVsp, e_FmDmaCacheOption scatterGatherCacheAttr)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE);
+
+ p_FmVspEntry->p_FmVspEntryDriverParams->dmaScatterGatherCacheAttr = scatterGatherCacheAttr;
+
+ return E_OK;
+}
+
+t_Error FM_VSP_ConfigDmaWriteOptimize(t_Handle h_FmVsp, bool optimize)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE);
+
+
+ p_FmVspEntry->p_FmVspEntryDriverParams->dmaWriteOptimize = optimize;
+
+ return E_OK;
+}
+
+t_Error FM_VSP_ConfigNoScatherGather(t_Handle h_FmVsp, bool noScatherGather)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE);
+
+
+ p_FmVspEntry->p_FmVspEntryDriverParams->noScatherGather = noScatherGather;
+
+ return E_OK;
+}
+
+t_Error FM_VSP_ConfigPoolDepletion(t_Handle h_FmVsp, t_FmBufPoolDepletion *p_BufPoolDepletion)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmVsp, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_BufPoolDepletion, E_INVALID_HANDLE);
+
+ p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion = (t_FmBufPoolDepletion *)XX_Malloc(sizeof(t_FmBufPoolDepletion));
+ if (!p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("p_BufPoolDepletion allocation failed"));
+ memcpy(p_FmVspEntry->p_FmVspEntryDriverParams->p_BufPoolDepletion, p_BufPoolDepletion, sizeof(t_FmBufPoolDepletion));
+
+ return E_OK;
+}
+
+t_Error FM_VSP_ConfigBackupPools(t_Handle h_FmVsp, t_FmBackupBmPools *p_BackupBmPools)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmVsp, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_BackupBmPools, E_INVALID_HANDLE);
+
+ p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools = (t_FmBackupBmPools *)XX_Malloc(sizeof(t_FmBackupBmPools));
+ if (!p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("p_BackupBmPools allocation failed"));
+ memcpy(p_FmVspEntry->p_FmVspEntryDriverParams->p_BackupBmPools, p_BackupBmPools, sizeof(t_FmBackupBmPools));
+
+ return E_OK;
+}
+
+uint32_t FM_VSP_GetBufferDataOffset(t_Handle h_FmVsp)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmVspEntry, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_VALUE(!p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_STATE, 0);
+
+ return p_FmVspEntry->bufferOffsets.dataOffset;
+}
+
+uint8_t * FM_VSP_GetBufferICInfo(t_Handle h_FmVsp, char *p_Data)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmVspEntry, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(!p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_STATE, NULL);
+
+ if (p_FmVspEntry->bufferOffsets.pcdInfoOffset == ILLEGAL_BASE)
+ return NULL;
+
+ return (uint8_t *)PTR_MOVE(p_Data, p_FmVspEntry->bufferOffsets.pcdInfoOffset);
+}
+
+t_FmPrsResult * FM_VSP_GetBufferPrsResult(t_Handle h_FmVsp, char *p_Data)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmVspEntry, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(!p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_STATE, NULL);
+
+ if (p_FmVspEntry->bufferOffsets.prsResultOffset == ILLEGAL_BASE)
+ return NULL;
+
+ return (t_FmPrsResult *)PTR_MOVE(p_Data, p_FmVspEntry->bufferOffsets.prsResultOffset);
+}
+
+uint64_t * FM_VSP_GetBufferTimeStamp(t_Handle h_FmVsp, char *p_Data)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmVspEntry, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(!p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_STATE, NULL);
+
+ if (p_FmVspEntry->bufferOffsets.timeStampOffset == ILLEGAL_BASE)
+ return NULL;
+
+ return (uint64_t *)PTR_MOVE(p_Data, p_FmVspEntry->bufferOffsets.timeStampOffset);
+}
+
+uint8_t * FM_VSP_GetBufferHashResult(t_Handle h_FmVsp, char *p_Data)
+{
+ t_FmVspEntry *p_FmVspEntry = (t_FmVspEntry*)h_FmVsp;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmVspEntry, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(!p_FmVspEntry->p_FmVspEntryDriverParams, E_INVALID_STATE, NULL);
+
+ if (p_FmVspEntry->bufferOffsets.hashResultOffset == ILLEGAL_BASE)
+ return NULL;
+
+ return (uint8_t *)PTR_MOVE(p_Data, p_FmVspEntry->bufferOffsets.hashResultOffset);
+}
+
+#endif /* (DPAA_VERSION >= 11) */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/fm_sp.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/fm_sp.h
new file mode 100644
index 0000000..9c171d8
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/fm_sp.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_sp.h
+
+ @Description FM SP ...
+*//***************************************************************************/
+#ifndef __FM_SP_H
+#define __FM_SP_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "list_ext.h"
+
+#include "fm_sp_common.h"
+#include "fm_common.h"
+
+
+#define __ERR_MODULE__ MODULE_FM_SP
+
+typedef struct {
+ t_FmBufferPrefixContent bufferPrefixContent;
+ e_FmDmaSwapOption dmaSwapData;
+ e_FmDmaCacheOption dmaIntContextCacheAttr;
+ e_FmDmaCacheOption dmaHeaderCacheAttr;
+ e_FmDmaCacheOption dmaScatterGatherCacheAttr;
+ bool dmaWriteOptimize;
+ uint16_t liodnOffset;
+ bool noScatherGather;
+ t_FmBufPoolDepletion *p_BufPoolDepletion;
+ t_FmBackupBmPools *p_BackupBmPools;
+ t_FmExtPools extBufPools;
+} t_FmVspEntryDriverParams;
+
+typedef struct {
+ bool valid;
+ volatile bool lock;
+ uint8_t pointedOwners;
+ uint16_t absoluteSpId;
+ uint8_t internalBufferOffset;
+ t_FmSpBufMargins bufMargins;
+ t_FmSpIntContextDataCopy intContext;
+ t_FmSpBufferOffsets bufferOffsets;
+ t_Handle h_Fm;
+ e_FmPortType portType; /**< Port type */
+ uint8_t portId; /**< Port Id - relative to type */
+ uint8_t relativeProfileId;
+ struct fm_pcd_storage_profile_regs *p_FmSpRegsBase;
+ t_FmExtPools extBufPools;
+ t_FmVspEntryDriverParams *p_FmVspEntryDriverParams;
+} t_FmVspEntry;
+
+
+#endif /* __FM_SP_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/fman_sp.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/fman_sp.c
new file mode 100755
index 0000000..0f772e9
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/SP/fman_sp.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "fsl_fman_sp.h"
+
+
+uint32_t fman_vsp_get_statistics(struct fm_pcd_storage_profile_regs *regs,
+ uint16_t index)
+{
+ struct fm_pcd_storage_profile_regs *sp_regs;
+ sp_regs = &regs[index];
+ return ioread32be(&sp_regs->fm_sp_acnt);
+}
+
+void fman_vsp_set_statistics(struct fm_pcd_storage_profile_regs *regs,
+ uint16_t index, uint32_t value)
+{
+ struct fm_pcd_storage_profile_regs *sp_regs;
+ sp_regs = &regs[index];
+ iowrite32be(value, &sp_regs->fm_sp_acnt);
+}
+
+void fman_vsp_defconfig(struct fm_storage_profile_params *cfg)
+{
+ cfg->dma_swap_data =
+ DEFAULT_FMAN_SP_DMA_SWAP_DATA;
+ cfg->int_context_cache_attr =
+ DEFAULT_FMAN_SP_DMA_INT_CONTEXT_CACHE_ATTR;
+ cfg->header_cache_attr =
+ DEFAULT_FMAN_SP_DMA_HEADER_CACHE_ATTR;
+ cfg->scatter_gather_cache_attr =
+ DEFAULT_FMAN_SP_DMA_SCATTER_GATHER_CACHE_ATTR;
+ cfg->dma_write_optimize =
+ DEFAULT_FMAN_SP_DMA_WRITE_OPTIMIZE;
+ cfg->no_scather_gather =
+ DEFAULT_FMAN_SP_NO_SCATTER_GATHER;
+}
+
+static inline uint32_t calc_vec_dep(int max_pools, bool *pools,
+ struct fman_ext_pools *ext_buf_pools, uint32_t mask)
+{
+ int i, j;
+ uint32_t vector = 0;
+ for (i = 0; i < max_pools; i++)
+ if (pools[i])
+ for (j = 0; j < ext_buf_pools->num_pools_used; j++)
+ if (i == ext_buf_pools->ext_buf_pool[j].id) {
+ vector |= mask >> j;
+ break;
+ }
+ return vector;
+}
+
+void fman_vsp_init(struct fm_pcd_storage_profile_regs *regs,
+ uint16_t index, struct fm_storage_profile_params *fm_vsp_params,
+ int port_max_num_of_ext_pools, int bm_max_num_of_pools,
+ int max_num_of_pfc_priorities)
+{
+ int i = 0, j = 0;
+ struct fm_pcd_storage_profile_regs *sp_regs;
+ uint32_t tmp_reg, vector;
+ struct fman_ext_pools *ext_buf_pools = &fm_vsp_params->fm_ext_pools;
+ struct fman_buf_pool_depletion *buf_pool_depletion =
+ &fm_vsp_params->buf_pool_depletion;
+ struct fman_backup_bm_pools *backup_pools =
+ &fm_vsp_params->backup_pools;
+ struct fman_sp_int_context_data_copy *int_context_data_copy =
+ fm_vsp_params->int_context;
+ struct fman_sp_buf_margins *external_buffer_margins =
+ fm_vsp_params->buf_margins;
+ bool no_scather_gather = fm_vsp_params->no_scather_gather;
+ uint16_t liodn_offset = fm_vsp_params->liodn_offset;
+
+ sp_regs = &regs[index];
+
+ /* fill external buffers manager pool information register*/
+ for (i = 0; i < ext_buf_pools->num_pools_used; i++) {
+ tmp_reg = FMAN_SP_EXT_BUF_POOL_VALID |
+ FMAN_SP_EXT_BUF_POOL_EN_COUNTER;
+ tmp_reg |= ((uint32_t)ext_buf_pools->ext_buf_pool[i].id <<
+ FMAN_SP_EXT_BUF_POOL_ID_SHIFT);
+ tmp_reg |= ext_buf_pools->ext_buf_pool[i].size;
+ /* functionality available only for some deriviatives
+ (limited by config) */
+ for (j = 0; j < backup_pools->num_backup_pools; j++)
+ if (ext_buf_pools->ext_buf_pool[i].id ==
+ backup_pools->pool_ids[j]) {
+ tmp_reg |= FMAN_SP_EXT_BUF_POOL_BACKUP;
+ break;
+ }
+ iowrite32be(tmp_reg, &sp_regs->fm_sp_ebmpi[i]);
+ }
+
+ /* clear unused pools */
+ for (i = ext_buf_pools->num_pools_used;
+ i < port_max_num_of_ext_pools; i++)
+ iowrite32be(0, &sp_regs->fm_sp_ebmpi[i]);
+
+ /* fill pool depletion register*/
+ tmp_reg = 0;
+ if (buf_pool_depletion->buf_pool_depletion_enabled && buf_pool_depletion->pools_grp_mode_enable) {
+ /* calculate vector for number of pools depletion */
+ vector = calc_vec_dep(bm_max_num_of_pools, buf_pool_depletion->
+ pools_to_consider, ext_buf_pools, 0x80000000);
+
+ /* configure num of pools and vector for number of pools mode */
+ tmp_reg |= (((uint32_t)buf_pool_depletion->num_pools - 1) <<
+ FMAN_SP_POOL_DEP_NUM_OF_POOLS_SHIFT);
+ tmp_reg |= vector;
+ }
+
+ if (buf_pool_depletion->buf_pool_depletion_enabled && buf_pool_depletion->single_pool_mode_enable) {
+ /* calculate vector for number of pools depletion */
+ vector = calc_vec_dep(bm_max_num_of_pools, buf_pool_depletion->
+ pools_to_consider_for_single_mode,
+ ext_buf_pools, 0x00000080);
+
+ /* configure num of pools and vector for number of pools mode */
+ tmp_reg |= vector;
+ }
+
+ /* fill QbbPEV */
+ if (buf_pool_depletion->buf_pool_depletion_enabled) {
+ vector = 0;
+ for (i = 0; i < max_num_of_pfc_priorities; i++)
+ if (buf_pool_depletion->pfc_priorities_en[i] == TRUE)
+ vector |= 0x00000100 << i;
+ tmp_reg |= vector;
+ }
+ iowrite32be(tmp_reg, &sp_regs->fm_sp_mpd);
+
+ /* fill dma attributes register */
+ tmp_reg = 0;
+ tmp_reg |= (uint32_t)fm_vsp_params->dma_swap_data <<
+ FMAN_SP_DMA_ATTR_SWP_SHIFT;
+ tmp_reg |= (uint32_t)fm_vsp_params->int_context_cache_attr <<
+ FMAN_SP_DMA_ATTR_IC_CACHE_SHIFT;
+ tmp_reg |= (uint32_t)fm_vsp_params->header_cache_attr <<
+ FMAN_SP_DMA_ATTR_HDR_CACHE_SHIFT;
+ tmp_reg |= (uint32_t)fm_vsp_params->scatter_gather_cache_attr <<
+ FMAN_SP_DMA_ATTR_SG_CACHE_SHIFT;
+ if (fm_vsp_params->dma_write_optimize)
+ tmp_reg |= FMAN_SP_DMA_ATTR_WRITE_OPTIMIZE;
+ iowrite32be(tmp_reg, &sp_regs->fm_sp_da);
+
+ /* IC parameters - fill internal context parameters register */
+ tmp_reg = 0;
+ tmp_reg |= (((uint32_t)int_context_data_copy->ext_buf_offset/
+ OFFSET_UNITS) << FMAN_SP_IC_TO_EXT_SHIFT);
+ tmp_reg |= (((uint32_t)int_context_data_copy->int_context_offset/
+ OFFSET_UNITS) << FMAN_SP_IC_FROM_INT_SHIFT);
+ tmp_reg |= (((uint32_t)int_context_data_copy->size/OFFSET_UNITS) <<
+ FMAN_SP_IC_SIZE_SHIFT);
+ iowrite32be(tmp_reg, &sp_regs->fm_sp_icp);
+
+ /* buffer margins - fill external buffer margins register */
+ tmp_reg = 0;
+ tmp_reg |= (((uint32_t)external_buffer_margins->start_margins) <<
+ FMAN_SP_EXT_BUF_MARG_START_SHIFT);
+ tmp_reg |= (((uint32_t)external_buffer_margins->end_margins) <<
+ FMAN_SP_EXT_BUF_MARG_END_SHIFT);
+ if (no_scather_gather)
+ tmp_reg |= FMAN_SP_SG_DISABLE;
+ iowrite32be(tmp_reg, &sp_regs->fm_sp_ebm);
+
+ /* buffer margins - fill spliodn register */
+ iowrite32be(liodn_offset, &sp_regs->fm_sp_spliodn);
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.c
new file mode 100644
index 0000000..e788107
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.c
@@ -0,0 +1,5227 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm.c
+
+ @Description FM driver routines implementation.
+*//***************************************************************************/
+#include "std_ext.h"
+#include "error_ext.h"
+#include "xx_ext.h"
+#include "string_ext.h"
+#include "sprint_ext.h"
+#include "debug_ext.h"
+#include "fm_muram_ext.h"
+
+#include "fm_common.h"
+#include "fm_ipc.h"
+#include "fm.h"
+#include <asm/mpc85xx.h>
+#include "fsl_fman.h"
+
+
+/****************************************/
+/* static functions */
+/****************************************/
+
+static volatile bool blockingFlag = FALSE;
+static void IpcMsgCompletionCB(t_Handle h_Fm,
+ uint8_t *p_Msg,
+ uint8_t *p_Reply,
+ uint32_t replyLength,
+ t_Error status)
+{
+ UNUSED(h_Fm);UNUSED(p_Msg);UNUSED(p_Reply);UNUSED(replyLength);UNUSED(status);
+ blockingFlag = FALSE;
+}
+
+static void FreeInitResources(t_Fm *p_Fm)
+{
+ if (p_Fm->camBaseAddr)
+ FM_MURAM_FreeMem(p_Fm->h_FmMuram, UINT_TO_PTR(p_Fm->camBaseAddr));
+ if (p_Fm->fifoBaseAddr)
+ FM_MURAM_FreeMem(p_Fm->h_FmMuram, UINT_TO_PTR(p_Fm->fifoBaseAddr));
+ if (p_Fm->resAddr)
+ FM_MURAM_FreeMem(p_Fm->h_FmMuram, UINT_TO_PTR(p_Fm->resAddr));
+}
+
+static bool IsFmanCtrlCodeLoaded(t_Fm *p_Fm)
+{
+ t_FMIramRegs *p_Iram;
+
+ ASSERT_COND(p_Fm);
+ p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM);
+
+ return (bool)!!(GET_UINT32(p_Iram->iready) & IRAM_READY);
+}
+
+static t_Error CheckFmParameters(t_Fm *p_Fm)
+{
+ if (IsFmanCtrlCodeLoaded(p_Fm) && !p_Fm->resetOnInit)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Old FMan CTRL code is loaded; FM must be reset!"));
+#if (DPAA_VERSION < 11)
+ if (!p_Fm->p_FmDriverParam->dma_axi_dbg_num_of_beats ||
+ (p_Fm->p_FmDriverParam->dma_axi_dbg_num_of_beats > DMA_MODE_MAX_AXI_DBG_NUM_OF_BEATS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("axiDbgNumOfBeats has to be in the range 1 - %d", DMA_MODE_MAX_AXI_DBG_NUM_OF_BEATS));
+#endif /* (DPAA_VERSION < 11) */
+ if (p_Fm->p_FmDriverParam->dma_cam_num_of_entries % DMA_CAM_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_cam_num_of_entries has to be divisble by %d", DMA_CAM_UNITS));
+// if (!p_Fm->p_FmDriverParam->dma_cam_num_of_entries || (p_Fm->p_FmDriverParam->dma_cam_num_of_entries > DMA_MODE_MAX_CAM_NUM_OF_ENTRIES))
+// RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_cam_num_of_entries has to be in the range 1 - %d", DMA_MODE_MAX_CAM_NUM_OF_ENTRIES));
+ if (p_Fm->p_FmDriverParam->dma_comm_qtsh_asrt_emer > DMA_THRESH_MAX_COMMQ)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_comm_qtsh_asrt_emer can not be larger than %d", DMA_THRESH_MAX_COMMQ));
+ if (p_Fm->p_FmDriverParam->dma_comm_qtsh_clr_emer > DMA_THRESH_MAX_COMMQ)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_comm_qtsh_clr_emer can not be larger than %d", DMA_THRESH_MAX_COMMQ));
+ if (p_Fm->p_FmDriverParam->dma_comm_qtsh_clr_emer >= p_Fm->p_FmDriverParam->dma_comm_qtsh_asrt_emer)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_comm_qtsh_clr_emer must be smaller than dma_comm_qtsh_asrt_emer"));
+#if (DPAA_VERSION < 11)
+ if (p_Fm->p_FmDriverParam->dma_read_buf_tsh_asrt_emer > DMA_THRESH_MAX_BUF)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_read_buf_tsh_asrt_emer can not be larger than %d", DMA_THRESH_MAX_BUF));
+ if (p_Fm->p_FmDriverParam->dma_read_buf_tsh_clr_emer > DMA_THRESH_MAX_BUF)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_read_buf_tsh_clr_emer can not be larger than %d", DMA_THRESH_MAX_BUF));
+ if (p_Fm->p_FmDriverParam->dma_read_buf_tsh_clr_emer >= p_Fm->p_FmDriverParam->dma_read_buf_tsh_asrt_emer)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_read_buf_tsh_clr_emer must be smaller than dma_read_buf_tsh_asrt_emer"));
+ if (p_Fm->p_FmDriverParam->dma_write_buf_tsh_asrt_emer > DMA_THRESH_MAX_BUF)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_write_buf_tsh_asrt_emer can not be larger than %d", DMA_THRESH_MAX_BUF));
+ if (p_Fm->p_FmDriverParam->dma_write_buf_tsh_clr_emer > DMA_THRESH_MAX_BUF)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_write_buf_tsh_clr_emer can not be larger than %d", DMA_THRESH_MAX_BUF));
+ if (p_Fm->p_FmDriverParam->dma_write_buf_tsh_clr_emer >= p_Fm->p_FmDriverParam->dma_write_buf_tsh_asrt_emer)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_write_buf_tsh_clr_emer must be smaller than dma_write_buf_tsh_asrt_emer"));
+#else /* (DPAA_VERSION >= 11) */
+ if ((p_Fm->p_FmDriverParam->dma_dbg_cnt_mode == E_FMAN_DMA_DBG_CNT_INT_READ_EM)||
+ (p_Fm->p_FmDriverParam->dma_dbg_cnt_mode == E_FMAN_DMA_DBG_CNT_INT_WRITE_EM) ||
+ (p_Fm->p_FmDriverParam->dma_dbg_cnt_mode == E_FMAN_DMA_DBG_CNT_RAW_WAR_PROT))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_dbg_cnt_mode value not supported by this integration."));
+ if ((p_Fm->p_FmDriverParam->dma_emergency_bus_select == FM_DMA_MURAM_READ_EMERGENCY)||
+ (p_Fm->p_FmDriverParam->dma_emergency_bus_select == FM_DMA_MURAM_WRITE_EMERGENCY))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("emergencyBusSelect value not supported by this integration."));
+ if (p_Fm->p_FmDriverParam->dma_stop_on_bus_error)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_stop_on_bus_error not supported by this integration."));
+#ifdef FM_AID_MODE_NO_TNUM_SW005
+ if (p_Fm->p_FmDriverParam->dma_aid_mode != E_FMAN_DMA_AID_OUT_PORT_ID)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_aid_mode not supported by this integration."));
+#endif /* FM_AID_MODE_NO_TNUM_SW005 */
+ if (p_Fm->p_FmDriverParam->dma_axi_dbg_num_of_beats)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_axi_dbg_num_of_beats not supported by this integration."));
+#endif /* (DPAA_VERSION < 11) */
+
+ if (!p_Fm->p_FmStateStruct->fmClkFreq)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fmClkFreq must be set."));
+ if (USEC_TO_CLK(p_Fm->p_FmDriverParam->dma_watchdog, p_Fm->p_FmStateStruct->fmClkFreq) > DMA_MAX_WATCHDOG)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("dma_watchdog depends on FM clock. dma_watchdog(in microseconds) * clk (in Mhz), may not exceed 0x08x", DMA_MAX_WATCHDOG));
+
+#if (DPAA_VERSION >= 11)
+ if ((p_Fm->partVSPBase + p_Fm->partNumOfVSPs) > FM_VSP_MAX_NUM_OF_ENTRIES)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("partVSPBase+partNumOfVSPs out of range!!!"));
+#endif /* (DPAA_VERSION >= 11) */
+
+ if (p_Fm->p_FmStateStruct->totalFifoSize % BMI_FIFO_UNITS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("totalFifoSize number has to be divisible by %d", BMI_FIFO_UNITS));
+ if (!p_Fm->p_FmStateStruct->totalFifoSize ||
+ (p_Fm->p_FmStateStruct->totalFifoSize > BMI_MAX_FIFO_SIZE))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("totalFifoSize (curr - %d) has to be in the range 256 - %d",
+ p_Fm->p_FmStateStruct->totalFifoSize,
+ BMI_MAX_FIFO_SIZE));
+ if (!p_Fm->p_FmStateStruct->totalNumOfTasks ||
+ (p_Fm->p_FmStateStruct->totalNumOfTasks > BMI_MAX_NUM_OF_TASKS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("totalNumOfTasks number has to be in the range 1 - %d", BMI_MAX_NUM_OF_TASKS));
+
+#ifdef FM_HAS_TOTAL_DMAS
+ if (!p_Fm->p_FmStateStruct->maxNumOfOpenDmas ||
+ (p_Fm->p_FmStateStruct->maxNumOfOpenDmas > BMI_MAX_NUM_OF_DMAS))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("maxNumOfOpenDmas number has to be in the range 1 - %d", BMI_MAX_NUM_OF_DMAS));
+#endif /* FM_HAS_TOTAL_DMAS */
+
+ if (p_Fm->p_FmDriverParam->disp_limit_tsh > FPM_MAX_DISP_LIMIT)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("disp_limit_tsh can't be greater than %d", FPM_MAX_DISP_LIMIT));
+
+ if (!p_Fm->f_Exception)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exceptions callback not provided"));
+ if (!p_Fm->f_BusError)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exceptions callback not provided"));
+
+#ifdef FM_NO_WATCHDOG
+ if ((p_Fm->p_FmStateStruct->revInfo.majorRev == 2) &&
+ (p_Fm->p_FmDriverParam->dma_watchdog))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("watchdog!"));
+#endif /* FM_NO_WATCHDOG */
+
+#ifdef FM_ECC_HALT_NO_SYNC_ERRATA_10GMAC_A008
+ if ((p_Fm->p_FmStateStruct->revInfo.majorRev < 6) &&
+ (p_Fm->p_FmDriverParam->halt_on_unrecov_ecc_err))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("HaltOnEccError!"));
+#endif /* FM_ECC_HALT_NO_SYNC_ERRATA_10GMAC_A008 */
+
+#ifdef FM_NO_TNUM_AGING
+ if ((p_Fm->p_FmStateStruct->revInfo.majorRev != 4) &&
+ (p_Fm->p_FmStateStruct->revInfo.majorRev < 6))
+ if (p_Fm->p_FmDriverParam->tnum_aging_period)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Tnum aging!"));
+#endif /* FM_NO_TNUM_AGING */
+
+ /* check that user did not set revision-dependent exceptions */
+#ifdef FM_NO_DISPATCH_RAM_ECC
+ if ((p_Fm->p_FmStateStruct->revInfo.majorRev != 4) &&
+ (p_Fm->p_FmStateStruct->revInfo.majorRev < 6))
+ if (p_Fm->userSetExceptions & FM_EX_BMI_DISPATCH_RAM_ECC)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("exception e_FM_EX_BMI_DISPATCH_RAM_ECC!"));
+#endif /* FM_NO_DISPATCH_RAM_ECC */
+
+#ifdef FM_QMI_NO_ECC_EXCEPTIONS
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev == 4)
+ if (p_Fm->userSetExceptions & (FM_EX_QMI_SINGLE_ECC | FM_EX_QMI_DOUBLE_ECC))
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("exception e_FM_EX_QMI_SINGLE_ECC/e_FM_EX_QMI_DOUBLE_ECC!"));
+#endif /* FM_QMI_NO_ECC_EXCEPTIONS */
+
+#ifdef FM_QMI_NO_SINGLE_ECC_EXCEPTION
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)
+ if (p_Fm->userSetExceptions & FM_EX_QMI_SINGLE_ECC)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("exception e_FM_EX_QMI_SINGLE_ECC!"));
+#endif /* FM_QMI_NO_SINGLE_ECC_EXCEPTION */
+
+ return E_OK;
+}
+
+
+static void SendIpcIsr(t_Fm *p_Fm, uint32_t macEvent, uint32_t pendingReg)
+{
+ ASSERT_COND(p_Fm->guestId == NCSW_MASTER_ID);
+
+ if (p_Fm->intrMng[macEvent].guestId == NCSW_MASTER_ID)
+ p_Fm->intrMng[macEvent].f_Isr(p_Fm->intrMng[macEvent].h_SrcHandle);
+
+ /* If the MAC is running on guest-partition and we have IPC session with it,
+ we inform him about the event through IPC; otherwise, we ignore the event. */
+ else if (p_Fm->h_IpcSessions[p_Fm->intrMng[macEvent].guestId])
+ {
+ t_Error err;
+ t_FmIpcIsr fmIpcIsr;
+ t_FmIpcMsg msg;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msgId = FM_GUEST_ISR;
+ fmIpcIsr.pendingReg = pendingReg;
+ fmIpcIsr.boolErr = FALSE;
+ memcpy(msg.msgBody, &fmIpcIsr, sizeof(fmIpcIsr));
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[p_Fm->intrMng[macEvent].guestId],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(fmIpcIsr),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ }
+ else
+ DBG(TRACE, ("FM Guest mode, without IPC - can't call ISR!"));
+}
+
+static void BmiErrEvent(t_Fm *p_Fm)
+{
+ uint32_t event;
+ struct fman_bmi_regs *bmi_rg = p_Fm->p_FmBmiRegs;
+
+
+ event = fman_get_bmi_err_event(bmi_rg);
+
+ if (event & BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC)
+ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_BMI_STORAGE_PROFILE_ECC);
+ if (event & BMI_ERR_INTR_EN_LIST_RAM_ECC)
+ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_BMI_LIST_RAM_ECC);
+ if (event & BMI_ERR_INTR_EN_STATISTICS_RAM_ECC)
+ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_BMI_STATISTICS_RAM_ECC);
+ if (event & BMI_ERR_INTR_EN_DISPATCH_RAM_ECC)
+ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_BMI_DISPATCH_RAM_ECC);
+}
+
+static void QmiErrEvent(t_Fm *p_Fm)
+{
+ uint32_t event;
+ struct fman_qmi_regs *qmi_rg = p_Fm->p_FmQmiRegs;
+
+ event = fman_get_qmi_err_event(qmi_rg);
+
+ if (event & QMI_ERR_INTR_EN_DOUBLE_ECC)
+ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_QMI_DOUBLE_ECC);
+ if (event & QMI_ERR_INTR_EN_DEQ_FROM_DEF)
+ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID);
+}
+
+static void DmaErrEvent(t_Fm *p_Fm)
+{
+ uint32_t status, com_id;
+ uint8_t tnum;
+ uint8_t hardwarePortId;
+ uint8_t relativePortId;
+ uint16_t liodn;
+ struct fman_dma_regs *dma_rg = p_Fm->p_FmDmaRegs;
+
+ status = fman_get_dma_err_event(dma_rg);
+
+ if (status & DMA_STATUS_BUS_ERR)
+ {
+ com_id = fman_get_dma_com_id(dma_rg);
+ hardwarePortId = (uint8_t)(((com_id & DMA_TRANSFER_PORTID_MASK) >> DMA_TRANSFER_PORTID_SHIFT));
+ HW_PORT_ID_TO_SW_PORT_ID(relativePortId, hardwarePortId);
+ tnum = (uint8_t)((com_id & DMA_TRANSFER_TNUM_MASK) >> DMA_TRANSFER_TNUM_SHIFT);
+ liodn = (uint16_t)(com_id & DMA_TRANSFER_LIODN_MASK);
+ ASSERT_COND(p_Fm->p_FmStateStruct->portsTypes[hardwarePortId] != e_FM_PORT_TYPE_DUMMY);
+ p_Fm->f_BusError(p_Fm->h_App,
+ p_Fm->p_FmStateStruct->portsTypes[hardwarePortId],
+ relativePortId,
+ fman_get_dma_addr(dma_rg),
+ tnum,
+ liodn);
+ }
+ if (status & DMA_STATUS_FM_SPDAT_ECC)
+ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_DMA_SINGLE_PORT_ECC);
+ if (status & DMA_STATUS_READ_ECC)
+ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_DMA_READ_ECC);
+ if (status & DMA_STATUS_SYSTEM_WRITE_ECC)
+ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_DMA_SYSTEM_WRITE_ECC);
+ if (status & DMA_STATUS_FM_WRITE_ECC)
+ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_DMA_FM_WRITE_ECC);
+ }
+
+static void FpmErrEvent(t_Fm *p_Fm)
+{
+ uint32_t event;
+ struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs;
+
+ event = fman_get_fpm_err_event(fpm_rg);
+
+ if ((event & FPM_EV_MASK_DOUBLE_ECC) && (event & FPM_EV_MASK_DOUBLE_ECC_EN))
+ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_FPM_DOUBLE_ECC);
+ if ((event & FPM_EV_MASK_STALL) && (event & FPM_EV_MASK_STALL_EN))
+ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_FPM_STALL_ON_TASKS);
+ if ((event & FPM_EV_MASK_SINGLE_ECC) && (event & FPM_EV_MASK_SINGLE_ECC_EN))
+ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_FPM_SINGLE_ECC);
+}
+
+static void MuramErrIntr(t_Fm *p_Fm)
+{
+ uint32_t event;
+ struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs;
+
+ event = fman_get_muram_err_event(fpm_rg);
+
+ if (event & FPM_RAM_MURAM_ECC)
+ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_MURAM_ECC);
+}
+
+static void IramErrIntr(t_Fm *p_Fm)
+{
+ uint32_t event;
+ struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs;
+
+ event = fman_get_iram_err_event(fpm_rg);
+
+ if (event & FPM_RAM_IRAM_ECC)
+ p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_IRAM_ECC);
+}
+
+static void QmiEvent(t_Fm *p_Fm)
+{
+ uint32_t event;
+ struct fman_qmi_regs *qmi_rg = p_Fm->p_FmQmiRegs;
+
+ event = fman_get_qmi_event(qmi_rg);
+
+ if (event & QMI_INTR_EN_SINGLE_ECC)
+ p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_QMI_SINGLE_ECC);
+}
+
+static void UnimplementedIsr(t_Handle h_Arg)
+{
+ UNUSED(h_Arg);
+
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unimplemented ISR!"));
+}
+
+static void UnimplementedFmanCtrlIsr(t_Handle h_Arg, uint32_t event)
+{
+ UNUSED(h_Arg); UNUSED(event);
+
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unimplemented FmCtl ISR!"));
+}
+
+static void EnableTimeStamp(t_Fm *p_Fm)
+{
+ struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs;
+
+ ASSERT_COND(p_Fm->p_FmStateStruct);
+ ASSERT_COND(p_Fm->p_FmStateStruct->count1MicroBit);
+
+ fman_enable_time_stamp(fpm_rg, p_Fm->p_FmStateStruct->count1MicroBit, p_Fm->p_FmStateStruct->fmClkFreq);
+
+ p_Fm->p_FmStateStruct->enabledTimeStamp = TRUE;
+}
+
+static t_Error ClearIRam(t_Fm *p_Fm)
+{
+ t_FMIramRegs *p_Iram;
+ int i;
+
+ ASSERT_COND(p_Fm);
+ p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM);
+
+ /* Enable the auto-increment */
+ WRITE_UINT32(p_Iram->iadd, IRAM_IADD_AIE);
+ while (GET_UINT32(p_Iram->iadd) != IRAM_IADD_AIE) ;
+
+ for (i=0; i < (FM_IRAM_SIZE/4); i++)
+ WRITE_UINT32(p_Iram->idata, 0xffffffff);
+
+ WRITE_UINT32(p_Iram->iadd, FM_IRAM_SIZE - 4);
+ CORE_MemoryBarrier();
+ while (GET_UINT32(p_Iram->idata) != 0xffffffff) ;
+
+ return E_OK;
+}
+
+static t_Error LoadFmanCtrlCode(t_Fm *p_Fm)
+{
+ t_FMIramRegs *p_Iram;
+ int i;
+ uint32_t tmp;
+ uint8_t compTo16;
+
+ ASSERT_COND(p_Fm);
+ p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM);
+
+ /* Enable the auto-increment */
+ WRITE_UINT32(p_Iram->iadd, IRAM_IADD_AIE);
+ while (GET_UINT32(p_Iram->iadd) != IRAM_IADD_AIE) ;
+
+ for (i=0; i < (p_Fm->firmware.size / 4); i++)
+ WRITE_UINT32(p_Iram->idata, p_Fm->firmware.p_Code[i]);
+
+ compTo16 = (uint8_t)(p_Fm->firmware.size % 16);
+ if (compTo16)
+ for (i=0; i < ((16-compTo16) / 4); i++)
+ WRITE_UINT32(p_Iram->idata, 0xffffffff);
+
+ WRITE_UINT32(p_Iram->iadd,p_Fm->firmware.size-4);
+ while (GET_UINT32(p_Iram->iadd) != (p_Fm->firmware.size-4)) ;
+
+ /* verify that writing has completed */
+ while (GET_UINT32(p_Iram->idata) != p_Fm->firmware.p_Code[(p_Fm->firmware.size / 4)-1]) ;
+
+ if (p_Fm->fwVerify)
+ {
+ WRITE_UINT32(p_Iram->iadd, IRAM_IADD_AIE);
+ while (GET_UINT32(p_Iram->iadd) != IRAM_IADD_AIE) ;
+ for (i=0; i < (p_Fm->firmware.size / 4); i++)
+ {
+ tmp = GET_UINT32(p_Iram->idata);
+ if (tmp != p_Fm->firmware.p_Code[i])
+ RETURN_ERROR(MAJOR, E_WRITE_FAILED,
+ ("UCode write error : write 0x%x, read 0x%x",
+ p_Fm->firmware.p_Code[i],tmp));
+ }
+ WRITE_UINT32(p_Iram->iadd, 0x0);
+ }
+
+ /* Enable patch from IRAM */
+ WRITE_UINT32(p_Iram->iready, IRAM_READY);
+ XX_UDelay(1000);
+
+ DBG(INFO, ("FMan-Controller code (ver %d.%d.%d) loaded to IRAM.",
+ ((uint16_t *)p_Fm->firmware.p_Code)[2],
+ ((uint8_t *)p_Fm->firmware.p_Code)[6],
+ ((uint8_t *)p_Fm->firmware.p_Code)[7]));
+
+ return E_OK;
+}
+
+#ifdef FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173
+static t_Error FwNotResetErratumBugzilla6173WA(t_Fm *p_Fm)
+{
+ t_FMIramRegs *p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM);
+ uint32_t tmpReg;
+ uint32_t savedSpliodn[63];
+
+ /* write to IRAM first location the debug instruction */
+ WRITE_UINT32(p_Iram->iadd, 0);
+ while (GET_UINT32(p_Iram->iadd) != 0) ;
+ WRITE_UINT32(p_Iram->idata, FM_FW_DEBUG_INSTRUCTION);
+
+ WRITE_UINT32(p_Iram->iadd, 0);
+ while (GET_UINT32(p_Iram->iadd) != 0) ;
+ while (GET_UINT32(p_Iram->idata) != FM_FW_DEBUG_INSTRUCTION) ;
+
+ /* Enable patch from IRAM */
+ WRITE_UINT32(p_Iram->iready, IRAM_READY);
+ CORE_MemoryBarrier();
+ XX_UDelay(100);
+ IO2MemCpy32((uint8_t *)savedSpliodn,
+ (uint8_t *)p_Fm->p_FmBmiRegs->fmbm_spliodn,
+ 63*sizeof(uint32_t));
+
+ /* reset FMAN */
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rstc, FPM_RSTC_FM_RESET);
+ CORE_MemoryBarrier();
+ XX_UDelay(100);
+
+ /* verify breakpoint debug status register */
+ tmpReg = GET_UINT32(*(uint32_t *)UINT_TO_PTR(p_Fm->baseAddr + FM_DEBUG_STATUS_REGISTER_OFFSET));
+ if (!tmpReg)
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Invalid debug status register value is '0'"));
+
+ /*************************************/
+ /* Load FMan-Controller code to IRAM */
+ /*************************************/
+ if (ClearIRam(p_Fm) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+ if (p_Fm->firmware.p_Code &&
+ (LoadFmanCtrlCode(p_Fm) != E_OK))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+ XX_UDelay(100);
+
+ /* reset FMAN again to start the microcode */
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rstc, FPM_RSTC_FM_RESET);
+ CORE_MemoryBarrier();
+ XX_UDelay(100);
+ Mem2IOCpy32((uint8_t *)p_Fm->p_FmBmiRegs->fmbm_spliodn,
+ (uint8_t *)savedSpliodn,
+ 63*sizeof(uint32_t));
+
+ if (fman_is_qmi_halt_not_busy_state(p_Fm->p_FmQmiRegs))
+ {
+ fman_resume(p_Fm->p_FmFpmRegs);
+ CORE_MemoryBarrier();
+ XX_UDelay(100);
+ }
+
+ return E_OK;
+}
+#endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */
+
+static void GuestErrorIsr(t_Fm *p_Fm, uint32_t pending)
+{
+#define FM_G_CALL_1G_MAC_ERR_ISR(_id) \
+do { \
+ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].h_SrcHandle);\
+} while (0)
+#define FM_G_CALL_10G_MAC_ERR_ISR(_id) \
+do { \
+ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].h_SrcHandle);\
+} while (0)
+
+ /* error interrupts */
+ if (pending & ERR_INTR_EN_1G_MAC0)
+ FM_G_CALL_1G_MAC_ERR_ISR(0);
+ if (pending & ERR_INTR_EN_1G_MAC1)
+ FM_G_CALL_1G_MAC_ERR_ISR(1);
+ if (pending & ERR_INTR_EN_1G_MAC2)
+ FM_G_CALL_1G_MAC_ERR_ISR(2);
+ if (pending & ERR_INTR_EN_1G_MAC3)
+ FM_G_CALL_1G_MAC_ERR_ISR(3);
+ if (pending & ERR_INTR_EN_1G_MAC4)
+ FM_G_CALL_1G_MAC_ERR_ISR(4);
+ if (pending & ERR_INTR_EN_1G_MAC5)
+ FM_G_CALL_1G_MAC_ERR_ISR(5);
+ if (pending & ERR_INTR_EN_1G_MAC6)
+ FM_G_CALL_1G_MAC_ERR_ISR(6);
+ if (pending & ERR_INTR_EN_1G_MAC7)
+ FM_G_CALL_1G_MAC_ERR_ISR(7);
+ if (pending & ERR_INTR_EN_10G_MAC0)
+ FM_G_CALL_10G_MAC_ERR_ISR(0);
+ if (pending & ERR_INTR_EN_10G_MAC1)
+ FM_G_CALL_10G_MAC_ERR_ISR(1);
+}
+
+static void GuestEventIsr(t_Fm *p_Fm, uint32_t pending)
+{
+#define FM_G_CALL_1G_MAC_ISR(_id) \
+do { \
+ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].h_SrcHandle);\
+} while (0)
+#define FM_G_CALL_10G_MAC_ISR(_id) \
+do { \
+ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].h_SrcHandle);\
+} while (0)
+
+ if (pending & INTR_EN_1G_MAC0)
+ FM_G_CALL_1G_MAC_ISR(0);
+ if (pending & INTR_EN_1G_MAC1)
+ FM_G_CALL_1G_MAC_ISR(1);
+ if (pending & INTR_EN_1G_MAC2)
+ FM_G_CALL_1G_MAC_ISR(2);
+ if (pending & INTR_EN_1G_MAC3)
+ FM_G_CALL_1G_MAC_ISR(3);
+ if (pending & INTR_EN_1G_MAC4)
+ FM_G_CALL_1G_MAC_ISR(4);
+ if (pending & INTR_EN_1G_MAC5)
+ FM_G_CALL_1G_MAC_ISR(5);
+ if (pending & INTR_EN_1G_MAC6)
+ FM_G_CALL_1G_MAC_ISR(6);
+ if (pending & INTR_EN_1G_MAC7)
+ FM_G_CALL_1G_MAC_ISR(7);
+ if (pending & INTR_EN_10G_MAC0)
+ FM_G_CALL_10G_MAC_ISR(0);
+ if (pending & INTR_EN_10G_MAC1)
+ FM_G_CALL_10G_MAC_ISR(1);
+ if (pending & INTR_EN_TMR)
+ p_Fm->intrMng[e_FM_EV_TMR].f_Isr(p_Fm->intrMng[e_FM_EV_TMR].h_SrcHandle);
+}
+
+#if (DPAA_VERSION >= 11)
+static t_Error SetVSPWindow(t_Handle h_Fm,
+ uint8_t hardwarePortId,
+ uint8_t baseStorageProfile,
+ uint8_t log2NumOfProfiles)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+
+ ASSERT_COND(h_Fm);
+ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->p_FmBmiRegs &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcVspSetPortWindow fmIpcVspSetPortWindow;
+ t_FmIpcMsg msg;
+ t_Error err = E_OK;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&fmIpcVspSetPortWindow, 0, sizeof(t_FmIpcVspSetPortWindow));
+ fmIpcVspSetPortWindow.hardwarePortId = hardwarePortId;
+ fmIpcVspSetPortWindow.baseStorageProfile = baseStorageProfile;
+ fmIpcVspSetPortWindow.log2NumOfProfiles = log2NumOfProfiles;
+ msg.msgId = FM_VSP_SET_PORT_WINDOW;
+ memcpy(msg.msgBody, &fmIpcVspSetPortWindow, sizeof(t_FmIpcVspSetPortWindow));
+
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ return E_OK;
+ }
+ else if (!p_Fm->p_FmBmiRegs)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("Either IPC or 'baseAddress' is required!"));
+
+ fman_set_vsp_window(p_Fm->p_FmBmiRegs,
+ hardwarePortId,
+ baseStorageProfile,
+ log2NumOfProfiles);
+
+ return E_OK;
+}
+
+static uint8_t AllocVSPsForPartition(t_Handle h_Fm, uint8_t base, uint8_t numOfProfiles, uint8_t guestId)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+ uint8_t profilesFound = 0;
+ int i = 0;
+ uint32_t intFlags;
+
+ if (!numOfProfiles)
+ return E_OK;
+
+ if ((numOfProfiles > FM_VSP_MAX_NUM_OF_ENTRIES) ||
+ (base + numOfProfiles > FM_VSP_MAX_NUM_OF_ENTRIES))
+ return (uint8_t)ILLEGAL_BASE;
+
+ if (p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ t_Error err;
+ uint32_t replyLength;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams));
+ ipcAllocParams.guestId = p_Fm->guestId;
+ ipcAllocParams.num = p_Fm->partNumOfVSPs;
+ ipcAllocParams.base = p_Fm->partVSPBase;
+ msg.msgId = FM_VSP_ALLOC;
+ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams));
+ replyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if ((err != E_OK) ||
+ (replyLength != (sizeof(uint32_t) + sizeof(uint8_t))))
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ else
+ memcpy((uint8_t*)&p_Fm->partVSPBase, reply.replyBody, sizeof(uint8_t));
+ if (p_Fm->partVSPBase == ILLEGAL_BASE)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ {
+ DBG(WARNING, ("FM Guest mode, without IPC - can't validate VSP range!"));
+ return (uint8_t)ILLEGAL_BASE;
+ }
+
+ intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock);
+ for (i = base; i < base + numOfProfiles; i++)
+ if (p_Fm->p_FmSp->profiles[i].profilesMng.ownerId == (uint8_t)ILLEGAL_BASE)
+ profilesFound++;
+ else
+ break;
+
+ if (profilesFound == numOfProfiles)
+ for (i = base; i<base + numOfProfiles; i++)
+ p_Fm->p_FmSp->profiles[i].profilesMng.ownerId = guestId;
+ else
+ {
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+ return (uint8_t)ILLEGAL_BASE;
+ }
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+
+ return base;
+}
+
+static void FreeVSPsForPartition(t_Handle h_Fm, uint8_t base, uint8_t numOfProfiles, uint8_t guestId)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+ int i = 0;
+
+ ASSERT_COND(p_Fm);
+
+ if (p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+ t_Error err;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams));
+ ipcAllocParams.guestId = p_Fm->guestId;
+ ipcAllocParams.num = p_Fm->partNumOfVSPs;
+ ipcAllocParams.base = p_Fm->partVSPBase;
+ msg.msgId = FM_VSP_FREE;
+ memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams));
+ replyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ return;
+ }
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ {
+ DBG(WARNING, ("FM Guest mode, without IPC - can't validate VSP range!"));
+ return;
+ }
+
+ ASSERT_COND(p_Fm->p_FmSp);
+
+ for (i=base; i<numOfProfiles; i++)
+ {
+ if (p_Fm->p_FmSp->profiles[i].profilesMng.ownerId == guestId)
+ p_Fm->p_FmSp->profiles[i].profilesMng.ownerId = (uint8_t)ILLEGAL_BASE;
+ else
+ DBG(WARNING, ("Request for freeing storage profile window which wasn't allocated to this partition"));
+ }
+}
+#endif /* (DPAA_VERSION >= 11) */
+
+static t_Error FmGuestHandleIpcMsgCB(t_Handle h_Fm,
+ uint8_t *p_Msg,
+ uint32_t msgLength,
+ uint8_t *p_Reply,
+ uint32_t *p_ReplyLength)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ t_FmIpcMsg *p_IpcMsg = (t_FmIpcMsg*)p_Msg;
+
+ UNUSED(p_Reply);
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((msgLength > sizeof(uint32_t)), E_INVALID_VALUE);
+
+#ifdef DISABLE_SANITY_CHECKS
+ UNUSED(msgLength);
+#endif /* DISABLE_SANITY_CHECKS */
+
+ ASSERT_COND(p_Msg);
+
+ *p_ReplyLength = 0;
+
+ switch (p_IpcMsg->msgId)
+ {
+ case (FM_GUEST_ISR):
+ {
+ t_FmIpcIsr ipcIsr;
+
+ memcpy((uint8_t*)&ipcIsr, p_IpcMsg->msgBody, sizeof(t_FmIpcIsr));
+ if (ipcIsr.boolErr)
+ GuestErrorIsr(p_Fm, ipcIsr.pendingReg);
+ else
+ GuestEventIsr(p_Fm, ipcIsr.pendingReg);
+ break;
+ }
+ default:
+ *p_ReplyLength = 0;
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("command not found!!!"));
+ }
+ return E_OK;
+}
+
+static t_Error FmHandleIpcMsgCB(t_Handle h_Fm,
+ uint8_t *p_Msg,
+ uint32_t msgLength,
+ uint8_t *p_Reply,
+ uint32_t *p_ReplyLength)
+{
+ t_Error err;
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ t_FmIpcMsg *p_IpcMsg = (t_FmIpcMsg*)p_Msg;
+ t_FmIpcReply *p_IpcReply = (t_FmIpcReply*)p_Reply;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((msgLength >= sizeof(uint32_t)), E_INVALID_VALUE);
+
+#ifdef DISABLE_SANITY_CHECKS
+ UNUSED(msgLength);
+#endif /* DISABLE_SANITY_CHECKS */
+
+ ASSERT_COND(p_IpcMsg);
+
+ memset(p_IpcReply, 0, (sizeof(uint8_t) * FM_IPC_MAX_REPLY_SIZE));
+ *p_ReplyLength = 0;
+
+ switch (p_IpcMsg->msgId)
+ {
+ case (FM_GET_SET_PORT_PARAMS):
+ {
+ t_FmIpcPortInInitParams ipcInitParams;
+ t_FmInterModulePortInitParams initParams;
+ t_FmIpcPortOutInitParams ipcOutInitParams;
+
+ memcpy((uint8_t*)&ipcInitParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortInInitParams));
+ initParams.hardwarePortId = ipcInitParams.hardwarePortId;
+ initParams.portType = (e_FmPortType)ipcInitParams.enumPortType;
+ initParams.independentMode = (bool)(ipcInitParams.boolIndependentMode);
+ initParams.liodnOffset = ipcInitParams.liodnOffset;
+ initParams.numOfTasks = ipcInitParams.numOfTasks;
+ initParams.numOfExtraTasks = ipcInitParams.numOfExtraTasks;
+ initParams.numOfOpenDmas = ipcInitParams.numOfOpenDmas;
+ initParams.numOfExtraOpenDmas = ipcInitParams.numOfExtraOpenDmas;
+ initParams.sizeOfFifo = ipcInitParams.sizeOfFifo;
+ initParams.extraSizeOfFifo = ipcInitParams.extraSizeOfFifo;
+ initParams.deqPipelineDepth = ipcInitParams.deqPipelineDepth;
+ initParams.maxFrameLength = ipcInitParams.maxFrameLength;
+ initParams.liodnBase = ipcInitParams.liodnBase;
+
+ p_IpcReply->error = (uint32_t)FmGetSetPortParams(h_Fm, &initParams);
+
+ ipcOutInitParams.ipcPhysAddr.high = initParams.fmMuramPhysBaseAddr.high;
+ ipcOutInitParams.ipcPhysAddr.low = initParams.fmMuramPhysBaseAddr.low;
+ ipcOutInitParams.sizeOfFifo = initParams.sizeOfFifo;
+ ipcOutInitParams.extraSizeOfFifo = initParams.extraSizeOfFifo;
+ ipcOutInitParams.numOfTasks = initParams.numOfTasks;
+ ipcOutInitParams.numOfExtraTasks = initParams.numOfExtraTasks;
+ ipcOutInitParams.numOfOpenDmas = initParams.numOfOpenDmas;
+ ipcOutInitParams.numOfExtraOpenDmas = initParams.numOfExtraOpenDmas;
+ memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcOutInitParams, sizeof(ipcOutInitParams));
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcPortOutInitParams);
+ break;
+ }
+ case (FM_SET_SIZE_OF_FIFO):
+ {
+ t_FmIpcPortRsrcParams ipcPortRsrcParams;
+
+ memcpy((uint8_t*)&ipcPortRsrcParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortRsrcParams));
+ p_IpcReply->error = (uint32_t)FmSetSizeOfFifo(h_Fm,
+ ipcPortRsrcParams.hardwarePortId,
+ &ipcPortRsrcParams.val,
+ &ipcPortRsrcParams.extra,
+ (bool)ipcPortRsrcParams.boolInitialConfig);
+ *p_ReplyLength = sizeof(uint32_t);
+ break;
+ }
+ case (FM_SET_NUM_OF_TASKS):
+ {
+ t_FmIpcPortRsrcParams ipcPortRsrcParams;
+
+ memcpy((uint8_t*)&ipcPortRsrcParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortRsrcParams));
+ p_IpcReply->error = (uint32_t)FmSetNumOfTasks(h_Fm, ipcPortRsrcParams.hardwarePortId,
+ (uint8_t*)&ipcPortRsrcParams.val,
+ (uint8_t*)&ipcPortRsrcParams.extra,
+ (bool)ipcPortRsrcParams.boolInitialConfig);
+ *p_ReplyLength = sizeof(uint32_t);
+ break;
+ }
+ case (FM_SET_NUM_OF_OPEN_DMAS):
+ {
+ t_FmIpcPortRsrcParams ipcPortRsrcParams;
+
+ memcpy((uint8_t*)&ipcPortRsrcParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortRsrcParams));
+ p_IpcReply->error = (uint32_t)FmSetNumOfOpenDmas(h_Fm, ipcPortRsrcParams.hardwarePortId,
+ (uint8_t*)&ipcPortRsrcParams.val,
+ (uint8_t*)&ipcPortRsrcParams.extra,
+ (bool)ipcPortRsrcParams.boolInitialConfig);
+ *p_ReplyLength = sizeof(uint32_t);
+ break;
+ }
+ case (FM_RESUME_STALLED_PORT):
+ *p_ReplyLength = sizeof(uint32_t);
+ p_IpcReply->error = (uint32_t)FmResumeStalledPort(h_Fm, p_IpcMsg->msgBody[0]);
+ break;
+ case (FM_MASTER_IS_ALIVE):
+ {
+ uint8_t guestId = p_IpcMsg->msgBody[0];
+ /* build the FM master partition IPC address */
+ memset(p_Fm->fmIpcHandlerModuleName[guestId], 0, (sizeof(char)) * MODULE_NAME_SIZE);
+ if (Sprint (p_Fm->fmIpcHandlerModuleName[guestId], "FM_%d_%d",p_Fm->p_FmStateStruct->fmId, guestId) != (guestId<10 ? 6:7))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
+ p_Fm->h_IpcSessions[guestId] = XX_IpcInitSession(p_Fm->fmIpcHandlerModuleName[guestId], p_Fm->fmModuleName);
+ if (p_Fm->h_IpcSessions[guestId] == NULL)
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("FM Master IPC session for guest %d", guestId));
+ *(uint8_t*)(p_IpcReply->replyBody) = 1;
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ break;
+ }
+ case (FM_IS_PORT_STALLED):
+ {
+ bool tmp;
+
+ p_IpcReply->error = (uint32_t)FmIsPortStalled(h_Fm, p_IpcMsg->msgBody[0], &tmp);
+ *(uint8_t*)(p_IpcReply->replyBody) = (uint8_t)tmp;
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ break;
+ }
+ case (FM_RESET_MAC):
+ {
+ t_FmIpcMacParams ipcMacParams;
+
+ memcpy((uint8_t*)&ipcMacParams, p_IpcMsg->msgBody, sizeof(t_FmIpcMacParams));
+ p_IpcReply->error = (uint32_t)FmResetMac(p_Fm,
+ (e_FmMacType)(ipcMacParams.enumType),
+ ipcMacParams.id);
+ *p_ReplyLength = sizeof(uint32_t);
+ break;
+ }
+ case (FM_SET_MAC_MAX_FRAME):
+ {
+ t_FmIpcMacMaxFrameParams ipcMacMaxFrameParams;
+
+ memcpy((uint8_t*)&ipcMacMaxFrameParams, p_IpcMsg->msgBody, sizeof(t_FmIpcMacMaxFrameParams));
+ err = FmSetMacMaxFrame(p_Fm,
+ (e_FmMacType)(ipcMacMaxFrameParams.macParams.enumType),
+ ipcMacMaxFrameParams.macParams.id,
+ ipcMacMaxFrameParams.maxFrameLength);
+ if (err != E_OK)
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ break;
+ }
+#if (DPAA_VERSION >= 11)
+ case (FM_VSP_ALLOC) :
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ uint8_t vspBase;
+ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams));
+ vspBase = AllocVSPsForPartition(h_Fm, ipcAllocParams.base, ipcAllocParams.num, ipcAllocParams.guestId);
+ memcpy(p_IpcReply->replyBody, (uint8_t*)&vspBase, sizeof(uint8_t));
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ break;
+ }
+ case (FM_VSP_FREE) :
+ {
+ t_FmIpcResourceAllocParams ipcAllocParams;
+ memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams));
+ FreeVSPsForPartition(h_Fm, ipcAllocParams.base, ipcAllocParams.num, ipcAllocParams.guestId);
+ break;
+ }
+ case (FM_VSP_SET_PORT_WINDOW) :
+ {
+ t_FmIpcVspSetPortWindow ipcVspSetPortWindow;
+ memcpy(&ipcVspSetPortWindow, p_IpcMsg->msgBody, sizeof(t_FmIpcVspSetPortWindow));
+ err = SetVSPWindow(h_Fm,
+ ipcVspSetPortWindow.hardwarePortId,
+ ipcVspSetPortWindow.baseStorageProfile,
+ ipcVspSetPortWindow.log2NumOfProfiles);
+ return err;
+ }
+ case (FM_SET_CONG_GRP_PFC_PRIO) :
+ {
+ t_FmIpcSetCongestionGroupPfcPriority fmIpcSetCongestionGroupPfcPriority;
+ memcpy(&fmIpcSetCongestionGroupPfcPriority, p_IpcMsg->msgBody, sizeof(t_FmIpcSetCongestionGroupPfcPriority));
+ err = FmSetCongestionGroupPFCpriority(h_Fm,
+ fmIpcSetCongestionGroupPfcPriority.congestionGroupId,
+ fmIpcSetCongestionGroupPfcPriority.priorityBitMap);
+ return err;
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ case (FM_FREE_PORT):
+ {
+ t_FmInterModulePortFreeParams portParams;
+ t_FmIpcPortFreeParams ipcPortParams;
+
+ memcpy((uint8_t*)&ipcPortParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortFreeParams));
+ portParams.hardwarePortId = ipcPortParams.hardwarePortId;
+ portParams.portType = (e_FmPortType)(ipcPortParams.enumPortType);
+ portParams.deqPipelineDepth = ipcPortParams.deqPipelineDepth;
+ FmFreePortParams(h_Fm, &portParams);
+ break;
+ }
+ case (FM_REGISTER_INTR):
+ {
+ t_FmIpcRegisterIntr ipcRegIntr;
+
+ memcpy((uint8_t*)&ipcRegIntr, p_IpcMsg->msgBody, sizeof(ipcRegIntr));
+ p_Fm->intrMng[ipcRegIntr.event].guestId = ipcRegIntr.guestId;
+ break;
+ }
+ case (FM_GET_PARAMS):
+ {
+ t_FmIpcParams ipcParams;
+
+ /* Get clock frequency */
+ ipcParams.fmClkFreq = p_Fm->p_FmStateStruct->fmClkFreq;
+
+ fman_get_revision(p_Fm->p_FmFpmRegs,&ipcParams.majorRev,&ipcParams.minorRev);
+
+ memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcParams, sizeof(t_FmIpcParams));
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcParams);
+ break;
+ }
+ case (FM_GET_FMAN_CTRL_CODE_REV):
+ {
+ t_FmCtrlCodeRevisionInfo fmanCtrlRevInfo;
+ t_FmIpcFmanCtrlCodeRevisionInfo ipcRevInfo;
+
+ p_IpcReply->error = (uint32_t)FM_GetFmanCtrlCodeRevision(h_Fm, &fmanCtrlRevInfo);
+ ipcRevInfo.packageRev = fmanCtrlRevInfo.packageRev;
+ ipcRevInfo.majorRev = fmanCtrlRevInfo.majorRev;
+ ipcRevInfo.minorRev = fmanCtrlRevInfo.minorRev;
+ memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcRevInfo, sizeof(t_FmIpcFmanCtrlCodeRevisionInfo));
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcFmanCtrlCodeRevisionInfo);
+ break;
+ }
+
+ case (FM_DMA_STAT):
+ {
+ t_FmDmaStatus dmaStatus;
+ t_FmIpcDmaStatus ipcDmaStatus;
+
+ FM_GetDmaStatus(h_Fm, &dmaStatus);
+ ipcDmaStatus.boolCmqNotEmpty = (uint8_t)dmaStatus.cmqNotEmpty;
+ ipcDmaStatus.boolBusError = (uint8_t)dmaStatus.busError;
+ ipcDmaStatus.boolReadBufEccError = (uint8_t)dmaStatus.readBufEccError;
+ ipcDmaStatus.boolWriteBufEccSysError = (uint8_t)dmaStatus.writeBufEccSysError;
+ ipcDmaStatus.boolWriteBufEccFmError = (uint8_t)dmaStatus.writeBufEccFmError;
+ ipcDmaStatus.boolSinglePortEccError = (uint8_t)dmaStatus.singlePortEccError;
+ memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcDmaStatus, sizeof(t_FmIpcDmaStatus));
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcDmaStatus);
+ break;
+ }
+ case (FM_ALLOC_FMAN_CTRL_EVENT_REG):
+ p_IpcReply->error = (uint32_t)FmAllocFmanCtrlEventReg(h_Fm, (uint8_t*)p_IpcReply->replyBody);
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ break;
+ case (FM_FREE_FMAN_CTRL_EVENT_REG):
+ FmFreeFmanCtrlEventReg(h_Fm, p_IpcMsg->msgBody[0]);
+ break;
+ case (FM_GET_TIMESTAMP_SCALE):
+ {
+ uint32_t timeStamp = FmGetTimeStampScale(h_Fm);
+
+ memcpy(p_IpcReply->replyBody, (uint8_t*)&timeStamp, sizeof(uint32_t));
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t);
+ break;
+ }
+ case (FM_GET_COUNTER):
+ {
+ e_FmCounters inCounter;
+ uint32_t outCounter;
+
+ memcpy((uint8_t*)&inCounter, p_IpcMsg->msgBody, sizeof(uint32_t));
+ outCounter = FM_GetCounter(h_Fm, inCounter);
+ memcpy(p_IpcReply->replyBody, (uint8_t*)&outCounter, sizeof(uint32_t));
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t);
+ break;
+ }
+ case (FM_SET_FMAN_CTRL_EVENTS_ENABLE):
+ {
+ t_FmIpcFmanEvents ipcFmanEvents;
+
+ memcpy((uint8_t*)&ipcFmanEvents, p_IpcMsg->msgBody, sizeof(t_FmIpcFmanEvents));
+ FmSetFmanCtrlIntr(h_Fm,
+ ipcFmanEvents.eventRegId,
+ ipcFmanEvents.enableEvents);
+ break;
+ }
+ case (FM_GET_FMAN_CTRL_EVENTS_ENABLE):
+ {
+ uint32_t tmp = FmGetFmanCtrlIntr(h_Fm, p_IpcMsg->msgBody[0]);
+
+ memcpy(p_IpcReply->replyBody, (uint8_t*)&tmp, sizeof(uint32_t));
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t);
+ break;
+ }
+ case (FM_GET_PHYS_MURAM_BASE):
+ {
+ t_FmPhysAddr physAddr;
+ t_FmIpcPhysAddr ipcPhysAddr;
+
+ FmGetPhysicalMuramBase(h_Fm, &physAddr);
+ ipcPhysAddr.high = physAddr.high;
+ ipcPhysAddr.low = physAddr.low;
+ memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcPhysAddr, sizeof(t_FmIpcPhysAddr));
+ *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcPhysAddr);
+ break;
+ }
+ case (FM_ENABLE_RAM_ECC):
+ {
+ if (((err = FM_EnableRamsEcc(h_Fm)) != E_OK) ||
+ ((err = FM_SetException(h_Fm, e_FM_EX_IRAM_ECC, TRUE)) != E_OK) ||
+ ((err = FM_SetException(h_Fm, e_FM_EX_MURAM_ECC, TRUE)) != E_OK))
+#if (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0))
+ UNUSED(err);
+#else
+ REPORT_ERROR(MINOR, err, NO_MSG);
+#endif /* (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0)) */
+ break;
+ }
+ case (FM_DISABLE_RAM_ECC):
+ {
+
+ if (((err = FM_SetException(h_Fm, e_FM_EX_IRAM_ECC, FALSE)) != E_OK) ||
+ ((err = FM_SetException(h_Fm, e_FM_EX_MURAM_ECC, FALSE)) != E_OK) ||
+ ((err = FM_DisableRamsEcc(h_Fm)) != E_OK))
+#if (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0))
+ UNUSED(err);
+#else
+ REPORT_ERROR(MINOR, err, NO_MSG);
+#endif /* (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0)) */
+ break;
+ }
+ case (FM_SET_NUM_OF_FMAN_CTRL):
+ {
+ t_FmIpcPortNumOfFmanCtrls ipcPortNumOfFmanCtrls;
+
+ memcpy((uint8_t*)&ipcPortNumOfFmanCtrls, p_IpcMsg->msgBody, sizeof(t_FmIpcPortNumOfFmanCtrls));
+ err = FmSetNumOfRiscsPerPort(h_Fm,
+ ipcPortNumOfFmanCtrls.hardwarePortId,
+ ipcPortNumOfFmanCtrls.numOfFmanCtrls,
+ ipcPortNumOfFmanCtrls.orFmanCtrl);
+ if (err != E_OK)
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ break;
+ }
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+ case (FM_10G_TX_ECC_WA):
+ p_IpcReply->error = (uint32_t)Fm10GTxEccWorkaround(h_Fm, p_IpcMsg->msgBody[0]);
+ *p_ReplyLength = sizeof(uint32_t);
+ break;
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+ default:
+ *p_ReplyLength = 0;
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("command not found!!!"));
+ }
+ return E_OK;
+}
+
+
+/****************************************/
+/* Inter-Module functions */
+/****************************************/
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+t_Error Fm10GTxEccWorkaround(t_Handle h_Fm, uint8_t macId)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ t_Error err = E_OK;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+ uint8_t rxHardwarePortId, txHardwarePortId;
+ struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs;
+
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ {
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_10G_TX_ECC_WA;
+ msg.msgBody[0] = macId;
+ replyLength = sizeof(uint32_t);
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId)+sizeof(macId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ return (t_Error)(reply.error);
+ }
+
+ SANITY_CHECK_RETURN_ERROR((macId == 0), E_NOT_SUPPORTED);
+ SANITY_CHECK_RETURN_ERROR(IsFmanCtrlCodeLoaded(p_Fm), E_INVALID_STATE);
+
+ SW_PORT_ID_TO_HW_PORT_ID(rxHardwarePortId, e_FM_PORT_TYPE_RX_10G, macId);
+ SW_PORT_ID_TO_HW_PORT_ID(txHardwarePortId, e_FM_PORT_TYPE_TX_10G, macId);
+ if ((p_Fm->p_FmStateStruct->portsTypes[rxHardwarePortId] != e_FM_PORT_TYPE_DUMMY) ||
+ (p_Fm->p_FmStateStruct->portsTypes[txHardwarePortId] != e_FM_PORT_TYPE_DUMMY))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,
+ ("MAC should be initialized prior to Rx and Tx ports!"));
+
+ return fman_set_erratum_10gmac_a004_wa(fpm_rg);
+}
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+uint16_t FmGetTnumAgingPeriod(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+
+ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_VALUE(!p_Fm->p_FmDriverParam, E_INVALID_STATE, 0);
+
+ return p_Fm->tnumAgingPeriod;
+}
+
+t_Error FmSetPortPreFetchConfiguration(t_Handle h_Fm,
+ uint8_t portNum,
+ bool preFetchConfigured)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+
+ p_Fm->portsPreFetchConfigured[portNum] = TRUE;
+ p_Fm->portsPreFetchValue[portNum] = preFetchConfigured;
+
+ return E_OK;
+}
+
+t_Error FmGetPortPreFetchConfiguration(t_Handle h_Fm,
+ uint8_t portNum,
+ bool *p_PortConfigured,
+ bool *p_PreFetchConfigured)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+
+ /* If the prefetch wasn't configured yet (not enable or disabled)
+ we return the value TRUE as it was already configured */
+ if (!p_Fm->portsPreFetchConfigured[portNum])
+ {
+ *p_PortConfigured = FALSE;
+ *p_PreFetchConfigured = FALSE;
+ }
+ else
+ {
+ *p_PortConfigured = TRUE;
+ *p_PreFetchConfigured = (p_Fm->portsPreFetchConfigured[portNum]);
+ }
+
+ return E_OK;
+}
+
+t_Error FmSetCongestionGroupPFCpriority(t_Handle h_Fm,
+ uint32_t congestionGroupId,
+ uint8_t priorityBitMap)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+
+ ASSERT_COND(h_Fm);
+
+ if (congestionGroupId > FM_PORT_NUM_OF_CONGESTION_GRPS)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE,
+ ("Congestion group ID bigger than %d",
+ FM_PORT_NUM_OF_CONGESTION_GRPS));
+
+ if (p_Fm->guestId == NCSW_MASTER_ID)
+ {
+ ASSERT_COND(p_Fm->baseAddr);
+ fman_set_congestion_group_pfc_priority((uint32_t *)((p_Fm->baseAddr+FM_MM_CGP)),
+ congestionGroupId,
+ priorityBitMap);
+ }
+ else if (p_Fm->h_IpcSessions[0])
+ {
+ t_Error err;
+ t_FmIpcMsg msg;
+ t_FmIpcSetCongestionGroupPfcPriority fmIpcSetCongestionGroupPfcPriority;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&fmIpcSetCongestionGroupPfcPriority, 0, sizeof(t_FmIpcSetCongestionGroupPfcPriority));
+ fmIpcSetCongestionGroupPfcPriority.congestionGroupId = congestionGroupId;
+ fmIpcSetCongestionGroupPfcPriority.priorityBitMap = priorityBitMap;
+
+ msg.msgId = FM_SET_CONG_GRP_PFC_PRIO;
+ memcpy(msg.msgBody, &fmIpcSetCongestionGroupPfcPriority, sizeof(t_FmIpcSetCongestionGroupPfcPriority));
+
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("guest without IPC!"));
+
+ return E_OK;
+}
+
+uintptr_t FmGetPcdPrsBaseAddr(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0);
+
+ if (!p_Fm->baseAddr)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE,
+ ("No base-addr; probably Guest with IPC!"));
+ return 0;
+ }
+
+ return (p_Fm->baseAddr + FM_MM_PRS);
+}
+
+uintptr_t FmGetPcdKgBaseAddr(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0);
+
+ if (!p_Fm->baseAddr)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE,
+ ("No base-addr; probably Guest with IPC!"));
+ return 0;
+ }
+
+ return (p_Fm->baseAddr + FM_MM_KG);
+}
+
+uintptr_t FmGetPcdPlcrBaseAddr(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0);
+
+ if (!p_Fm->baseAddr)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE,
+ ("No base-addr; probably Guest with IPC!"));
+ return 0;
+ }
+
+ return (p_Fm->baseAddr + FM_MM_PLCR);
+}
+
+#if (DPAA_VERSION >= 11)
+uintptr_t FmGetVSPBaseAddr(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0);
+
+ return p_Fm->vspBaseAddr;
+}
+#endif /* (DPAA_VERSION >= 11) */
+
+t_Handle FmGetMuramHandle(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, NULL);
+
+ return (p_Fm->h_FmMuram);
+}
+
+void FmGetPhysicalMuramBase(t_Handle h_Fm, t_FmPhysAddr *p_FmPhysAddr)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ if (p_Fm->fmMuramPhysBaseAddr)
+ {
+ /* General FM driver initialization */
+ p_FmPhysAddr->low = (uint32_t)p_Fm->fmMuramPhysBaseAddr;
+ p_FmPhysAddr->high = (uint8_t)((p_Fm->fmMuramPhysBaseAddr & 0x000000ff00000000LL) >> 32);
+ return;
+ }
+
+ ASSERT_COND(p_Fm->guestId != NCSW_MASTER_ID);
+
+ if (p_Fm->h_IpcSessions[0])
+ {
+ t_Error err;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+ t_FmIpcPhysAddr ipcPhysAddr;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_GET_PHYS_MURAM_BASE;
+ replyLength = sizeof(uint32_t) + sizeof(t_FmPhysAddr);
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ {
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ return;
+ }
+ if (replyLength != (sizeof(uint32_t) + sizeof(t_FmPhysAddr)))
+ {
+ REPORT_ERROR(MINOR, E_INVALID_VALUE,("IPC reply length mismatch"));
+ return;
+ }
+ memcpy((uint8_t*)&ipcPhysAddr, reply.replyBody, sizeof(t_FmIpcPhysAddr));
+ p_FmPhysAddr->high = ipcPhysAddr.high;
+ p_FmPhysAddr->low = ipcPhysAddr.low;
+ }
+ else
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without neither IPC nor mapped register!"));
+}
+
+#if (DPAA_VERSION >= 11)
+t_Error FmVSPAllocForPort (t_Handle h_Fm,
+ e_FmPortType portType,
+ uint8_t portId,
+ uint8_t numOfVSPs)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+ t_Error err = E_OK;
+ uint32_t profilesFound, intFlags;
+ uint8_t first, i;
+ uint8_t log2Num;
+ uint8_t swPortIndex=0, hardwarePortId;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+
+ if (!numOfVSPs)
+ return E_OK;
+
+ if (numOfVSPs > FM_VSP_MAX_NUM_OF_ENTRIES)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("numProfiles can not be bigger than %d.",FM_VSP_MAX_NUM_OF_ENTRIES));
+
+ if (!POWER_OF_2(numOfVSPs))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numProfiles must be a power of 2."));
+
+ LOG2((uint64_t)numOfVSPs, log2Num);
+
+ if ((log2Num == 0) || (p_Fm->partVSPBase == 0))
+ first = 0;
+ else
+ first = 1<<log2Num;
+
+ if (first > (p_Fm->partVSPBase + p_Fm->partNumOfVSPs))
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("can not allocate storage profile port window"));
+
+ if (first < p_Fm->partVSPBase)
+ while (first < p_Fm->partVSPBase)
+ first = first + numOfVSPs;
+
+ if ((first + numOfVSPs) > (p_Fm->partVSPBase + p_Fm->partNumOfVSPs))
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("can not allocate storage profile port window"));
+
+ intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock);
+ profilesFound = 0;
+ for (i=first; i < p_Fm->partVSPBase + p_Fm->partNumOfVSPs; )
+ {
+ if (!p_Fm->p_FmSp->profiles[i].profilesMng.allocated)
+ {
+ profilesFound++;
+ i++;
+ if (profilesFound == numOfVSPs)
+ break;
+ }
+ else
+ {
+ profilesFound = 0;
+ /* advance i to the next aligned address */
+ first = i = (uint8_t)(first + numOfVSPs);
+ }
+ }
+ if (profilesFound == numOfVSPs)
+ for (i = first; i<first + numOfVSPs; i++)
+ p_Fm->p_FmSp->profiles[i].profilesMng.allocated = TRUE;
+ else
+ {
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+ RETURN_ERROR(MINOR, E_FULL, ("No profiles."));
+ }
+
+ SW_PORT_ID_TO_HW_PORT_ID(hardwarePortId, portType, portId)
+ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId);
+
+ p_Fm->p_FmSp->portsMapping[swPortIndex].numOfProfiles = numOfVSPs;
+ p_Fm->p_FmSp->portsMapping[swPortIndex].profilesBase = first;
+
+ if ((err = SetVSPWindow(h_Fm,hardwarePortId, first,log2Num)) != E_OK)
+ for (i = first; i < first + numOfVSPs; i++)
+ p_Fm->p_FmSp->profiles[i].profilesMng.allocated = FALSE;
+
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+
+ return err;
+}
+
+t_Error FmVSPFreeForPort(t_Handle h_Fm,
+ e_FmPortType portType,
+ uint8_t portId)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+ uint8_t swPortIndex=0, hardwarePortId, first, numOfVSPs, i;
+ uint32_t intFlags;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+
+ SW_PORT_ID_TO_HW_PORT_ID(hardwarePortId, portType, portId)
+ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId);
+
+ numOfVSPs = p_Fm->p_FmSp->portsMapping[swPortIndex].numOfProfiles;
+ first = p_Fm->p_FmSp->portsMapping[swPortIndex].profilesBase;
+
+ intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock);
+ for (i = first; i < first + numOfVSPs; i++)
+ p_Fm->p_FmSp->profiles[i].profilesMng.allocated = FALSE;
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+
+ p_Fm->p_FmSp->portsMapping[swPortIndex].numOfProfiles = 0;
+ p_Fm->p_FmSp->portsMapping[swPortIndex].profilesBase = 0;
+
+ return E_OK;
+}
+#endif /* (DPAA_VERSION >= 11) */
+
+t_Error FmAllocFmanCtrlEventReg(t_Handle h_Fm, uint8_t *p_EventId)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ uint8_t i;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_Error err;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_ALLOC_FMAN_CTRL_EVENT_REG;
+ replyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (replyLength != (sizeof(uint32_t) + sizeof(uint8_t)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+
+ *p_EventId = *(uint8_t*)(reply.replyBody);
+
+ return (t_Error)(reply.error);
+ }
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without IPC!"));
+
+ for (i=0;i<FM_NUM_OF_FMAN_CTRL_EVENT_REGS;i++)
+ if (!p_Fm->usedEventRegs[i])
+ {
+ p_Fm->usedEventRegs[i] = TRUE;
+ *p_EventId = i;
+ break;
+ }
+
+ if (i==FM_NUM_OF_FMAN_CTRL_EVENT_REGS)
+ RETURN_ERROR(MAJOR, E_BUSY, ("No resource - FMan controller event register."));
+
+ return E_OK;
+}
+
+void FmFreeFmanCtrlEventReg(t_Handle h_Fm, uint8_t eventId)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE);
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_Error err;
+ t_FmIpcMsg msg;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msgId = FM_FREE_FMAN_CTRL_EVENT_REG;
+ msg.msgBody[0] = eventId;
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId)+sizeof(eventId),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ return;
+ }
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ {
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without IPC!"));
+ return;
+ }
+
+ ((t_Fm*)h_Fm)->usedEventRegs[eventId] = FALSE;
+}
+
+void FmSetFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId, uint32_t enableEvents)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs;
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->p_FmFpmRegs &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcFmanEvents fmanCtrl;
+ t_Error err;
+ t_FmIpcMsg msg;
+
+ fmanCtrl.eventRegId = eventRegId;
+ fmanCtrl.enableEvents = enableEvents;
+ memset(&msg, 0, sizeof(msg));
+ msg.msgId = FM_SET_FMAN_CTRL_EVENTS_ENABLE;
+ memcpy(msg.msgBody, &fmanCtrl, sizeof(fmanCtrl));
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId)+sizeof(fmanCtrl),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ return;
+ }
+ else if (!p_Fm->p_FmFpmRegs)
+ {
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("Either IPC or 'baseAddress' is required!"));
+ return;
+ }
+
+ ASSERT_COND(eventRegId < FM_NUM_OF_FMAN_CTRL_EVENT_REGS);
+ fman_set_ctrl_intr(fpm_rg, eventRegId, enableEvents);
+}
+
+uint32_t FmGetFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs;
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->p_FmFpmRegs &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_Error err;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength, ctrlIntr;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_GET_FMAN_CTRL_EVENTS_ENABLE;
+ msg.msgBody[0] = eventRegId;
+ replyLength = sizeof(uint32_t) + sizeof(uint32_t);
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId)+sizeof(eventRegId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ {
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ return 0;
+ }
+ if (replyLength != (sizeof(uint32_t) + sizeof(uint32_t)))
+ {
+ REPORT_ERROR(MINOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ return 0;
+ }
+ memcpy((uint8_t*)&ctrlIntr, reply.replyBody, sizeof(uint32_t));
+ return ctrlIntr;
+ }
+ else if (!p_Fm->p_FmFpmRegs)
+ {
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("Either IPC or 'baseAddress' is required!"));
+ return 0;
+ }
+
+ return fman_get_ctrl_intr(fpm_rg, eventRegId);
+}
+
+void FmRegisterIntr(t_Handle h_Fm,
+ e_FmEventModules module,
+ uint8_t modId,
+ e_FmIntrType intrType,
+ void (*f_Isr) (t_Handle h_Arg),
+ t_Handle h_Arg)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ int event = 0;
+
+ ASSERT_COND(h_Fm);
+
+ GET_FM_MODULE_EVENT(module, modId, intrType, event);
+ ASSERT_COND(event < e_FM_EV_DUMMY_LAST);
+
+ /* register in local FM structure */
+ p_Fm->intrMng[event].f_Isr = f_Isr;
+ p_Fm->intrMng[event].h_SrcHandle = h_Arg;
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcRegisterIntr fmIpcRegisterIntr;
+ t_Error err;
+ t_FmIpcMsg msg;
+
+ /* register in Master FM structure */
+ fmIpcRegisterIntr.event = (uint32_t)event;
+ fmIpcRegisterIntr.guestId = p_Fm->guestId;
+ memset(&msg, 0, sizeof(msg));
+ msg.msgId = FM_REGISTER_INTR;
+ memcpy(msg.msgBody, &fmIpcRegisterIntr, sizeof(fmIpcRegisterIntr));
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(fmIpcRegisterIntr),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ }
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without IPC!"));
+}
+
+void FmUnregisterIntr(t_Handle h_Fm,
+ e_FmEventModules module,
+ uint8_t modId,
+ e_FmIntrType intrType)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ int event = 0;
+
+ ASSERT_COND(h_Fm);
+
+ GET_FM_MODULE_EVENT(module, modId,intrType, event);
+ ASSERT_COND(event < e_FM_EV_DUMMY_LAST);
+
+ p_Fm->intrMng[event].f_Isr = UnimplementedIsr;
+ p_Fm->intrMng[event].h_SrcHandle = NULL;
+}
+
+void FmRegisterFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId, void (*f_Isr) (t_Handle h_Arg, uint32_t event), t_Handle h_Arg)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ ASSERT_COND(eventRegId<FM_NUM_OF_FMAN_CTRL_EVENT_REGS);
+
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM in guest-mode"));
+ return;
+ }
+
+ p_Fm->fmanCtrlIntr[eventRegId].f_Isr = f_Isr;
+ p_Fm->fmanCtrlIntr[eventRegId].h_SrcHandle = h_Arg;
+}
+
+void FmUnregisterFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ ASSERT_COND(eventRegId<FM_NUM_OF_FMAN_CTRL_EVENT_REGS);
+
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM in guest-mode"));
+ return;
+ }
+
+ p_Fm->fmanCtrlIntr[eventRegId].f_Isr = UnimplementedFmanCtrlIsr;
+ p_Fm->fmanCtrlIntr[eventRegId].h_SrcHandle = NULL;
+}
+
+void FmRegisterPcd(t_Handle h_Fm, t_Handle h_FmPcd)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ if (p_Fm->h_Pcd)
+ REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ("PCD already set"));
+
+ p_Fm->h_Pcd = h_FmPcd;
+}
+
+void FmUnregisterPcd(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ if (!p_Fm->h_Pcd)
+ REPORT_ERROR(MAJOR, E_NOT_FOUND, ("PCD handle!"));
+
+ p_Fm->h_Pcd = NULL;
+}
+
+t_Handle FmGetPcdHandle(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ return p_Fm->h_Pcd;
+}
+
+uint8_t FmGetId(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0xff);
+
+ return p_Fm->p_FmStateStruct->fmId;
+}
+
+t_Error FmSetNumOfRiscsPerPort(t_Handle h_Fm,
+ uint8_t hardwarePortId,
+ uint8_t numOfFmanCtrls,
+ t_FmFmanCtrl orFmanCtrl)
+{
+
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ struct fman_fpm_regs *fpm_rg;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(((numOfFmanCtrls > 0) && (numOfFmanCtrls < 3)) , E_INVALID_HANDLE);
+
+ fpm_rg = p_Fm->p_FmFpmRegs;
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->p_FmFpmRegs &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_Error err;
+ t_FmIpcPortNumOfFmanCtrls params;
+ t_FmIpcMsg msg;
+
+ memset(&msg, 0, sizeof(msg));
+ params.hardwarePortId = hardwarePortId;
+ params.numOfFmanCtrls = numOfFmanCtrls;
+ params.orFmanCtrl = orFmanCtrl;
+ msg.msgId = FM_SET_NUM_OF_FMAN_CTRL;
+ memcpy(msg.msgBody, &params, sizeof(params));
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) +sizeof(params),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ return E_OK;
+ }
+ else if (!p_Fm->p_FmFpmRegs)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("Either IPC or 'baseAddress' is required!"));
+
+ fman_set_num_of_riscs_per_port(fpm_rg, hardwarePortId, numOfFmanCtrls, orFmanCtrl);
+
+ return E_OK;
+}
+
+t_Error FmGetSetPortParams(t_Handle h_Fm, t_FmInterModulePortInitParams *p_PortParams)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ t_Error err;
+ uint32_t intFlags;
+ uint8_t hardwarePortId = p_PortParams->hardwarePortId, macId;
+ struct fman_rg fman_rg;
+
+ fman_rg.bmi_rg = p_Fm->p_FmBmiRegs;
+ fman_rg.qmi_rg = p_Fm->p_FmQmiRegs;
+ fman_rg.fpm_rg = p_Fm->p_FmFpmRegs;
+ fman_rg.dma_rg = p_Fm->p_FmDmaRegs;
+
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ {
+ t_FmIpcPortInInitParams portInParams;
+ t_FmIpcPortOutInitParams portOutParams;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+
+ portInParams.hardwarePortId = p_PortParams->hardwarePortId;
+ portInParams.enumPortType = (uint32_t)p_PortParams->portType;
+ portInParams.boolIndependentMode= (uint8_t)p_PortParams->independentMode;
+ portInParams.liodnOffset = p_PortParams->liodnOffset;
+ portInParams.numOfTasks = p_PortParams->numOfTasks;
+ portInParams.numOfExtraTasks = p_PortParams->numOfExtraTasks;
+ portInParams.numOfOpenDmas = p_PortParams->numOfOpenDmas;
+ portInParams.numOfExtraOpenDmas = p_PortParams->numOfExtraOpenDmas;
+ portInParams.sizeOfFifo = p_PortParams->sizeOfFifo;
+ portInParams.extraSizeOfFifo = p_PortParams->extraSizeOfFifo;
+ portInParams.deqPipelineDepth = p_PortParams->deqPipelineDepth;
+ portInParams.maxFrameLength = p_PortParams->maxFrameLength;
+ portInParams.liodnBase = p_PortParams->liodnBase;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_GET_SET_PORT_PARAMS;
+ memcpy(msg.msgBody, &portInParams, sizeof(portInParams));
+ replyLength = (sizeof(uint32_t) + sizeof(t_FmIpcPortOutInitParams));
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) +sizeof(portInParams),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ if (replyLength != (sizeof(uint32_t) + sizeof(t_FmIpcPortOutInitParams)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ memcpy((uint8_t*)&portOutParams, reply.replyBody, sizeof(t_FmIpcPortOutInitParams));
+
+ p_PortParams->fmMuramPhysBaseAddr.high = portOutParams.ipcPhysAddr.high;
+ p_PortParams->fmMuramPhysBaseAddr.low = portOutParams.ipcPhysAddr.low;
+ p_PortParams->numOfTasks = portOutParams.numOfTasks;
+ p_PortParams->numOfExtraTasks = portOutParams.numOfExtraTasks;
+ p_PortParams->numOfOpenDmas = portOutParams.numOfOpenDmas;
+ p_PortParams->numOfExtraOpenDmas = portOutParams.numOfExtraOpenDmas;
+ p_PortParams->sizeOfFifo = portOutParams.sizeOfFifo;
+ p_PortParams->extraSizeOfFifo = portOutParams.extraSizeOfFifo;
+
+ return (t_Error)(reply.error);
+ }
+
+ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));
+
+ intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock);
+ if (p_PortParams->independentMode)
+ {
+ /* set port parameters */
+ p_Fm->independentMode = p_PortParams->independentMode;
+ /* disable dispatch limit */
+ fman_qmi_disable_dispatch_limit(fman_rg.fpm_rg);
+ }
+
+ if (p_PortParams->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)
+ {
+ if (p_Fm->hcPortInitialized)
+ {
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Only one host command port is allowed."));
+ }
+ else
+ p_Fm->hcPortInitialized = TRUE;
+ }
+ p_Fm->p_FmStateStruct->portsTypes[hardwarePortId] = p_PortParams->portType;
+
+ err = FmSetNumOfTasks(p_Fm, p_PortParams->hardwarePortId, &p_PortParams->numOfTasks, &p_PortParams->numOfExtraTasks, TRUE);
+ if (err)
+ {
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev != 4)
+#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */
+ if ((p_PortParams->portType != e_FM_PORT_TYPE_RX) &&
+ (p_PortParams->portType != e_FM_PORT_TYPE_RX_10G))
+ /* for transmit & O/H ports */
+ {
+ uint8_t enqTh;
+ uint8_t deqTh;
+
+ /* update qmi ENQ/DEQ threshold */
+ p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums += p_PortParams->deqPipelineDepth;
+ enqTh = fman_get_qmi_enq_th(fman_rg.qmi_rg);
+ /* if enqTh is too big, we reduce it to the max value that is still OK */
+ if (enqTh >= (QMI_MAX_NUM_OF_TNUMS - p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums))
+ {
+ enqTh = (uint8_t)(QMI_MAX_NUM_OF_TNUMS - p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums - 1);
+ fman_set_qmi_enq_th(fman_rg.qmi_rg, enqTh);
+ }
+
+ deqTh = fman_get_qmi_deq_th(fman_rg.qmi_rg);
+ /* if deqTh is too small, we enlarge it to the min value that is still OK.
+ deqTh may not be larger than 63 (QMI_MAX_NUM_OF_TNUMS-1). */
+ if ((deqTh <= p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums) && (deqTh < QMI_MAX_NUM_OF_TNUMS-1))
+ {
+ deqTh = (uint8_t)(p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums + 1);
+ fman_set_qmi_deq_th(fman_rg.qmi_rg, deqTh);
+ }
+ }
+
+#ifdef FM_LOW_END_RESTRICTION
+ if ((hardwarePortId==0x1) || (hardwarePortId==0x29))
+ {
+ if (p_Fm->p_FmStateStruct->lowEndRestriction)
+ {
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("OP #0 cannot work with Tx Port #1."));
+ }
+ else
+ p_Fm->p_FmStateStruct->lowEndRestriction = TRUE;
+ }
+#endif /* FM_LOW_END_RESTRICTION */
+
+ err = FmSetSizeOfFifo(p_Fm,
+ p_PortParams->hardwarePortId,
+ &p_PortParams->sizeOfFifo,
+ &p_PortParams->extraSizeOfFifo,
+ TRUE);
+ if (err)
+ {
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ err = FmSetNumOfOpenDmas(p_Fm,
+ p_PortParams->hardwarePortId,
+ &p_PortParams->numOfOpenDmas,
+ &p_PortParams->numOfExtraOpenDmas,
+ TRUE);
+ if (err)
+ {
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ fman_set_liodn_per_port(&fman_rg,
+ hardwarePortId,
+ p_PortParams->liodnBase,
+ p_PortParams->liodnOffset);
+
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev < 6)
+ fman_set_order_restoration_per_port(fman_rg.fpm_rg,
+ hardwarePortId,
+ p_PortParams->independentMode,
+ !!((p_PortParams->portType==e_FM_PORT_TYPE_RX) || (p_PortParams->portType==e_FM_PORT_TYPE_RX_10G)));
+
+ HW_PORT_ID_TO_SW_PORT_ID(macId, hardwarePortId);
+
+#if defined(FM_MAX_NUM_OF_10G_MACS) && (FM_MAX_NUM_OF_10G_MACS)
+ if ((p_PortParams->portType == e_FM_PORT_TYPE_TX_10G) ||
+ (p_PortParams->portType == e_FM_PORT_TYPE_RX_10G))
+ {
+ ASSERT_COND(macId < FM_MAX_NUM_OF_10G_MACS);
+ if (p_PortParams->maxFrameLength >= p_Fm->p_FmStateStruct->macMaxFrameLengths10G[macId])
+ p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId] = p_PortParams->maxFrameLength;
+ else
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Port maxFrameLength is smaller than MAC current MTU"));
+ }
+ else
+#endif /* defined(FM_MAX_NUM_OF_10G_MACS) && ... */
+ if ((p_PortParams->portType == e_FM_PORT_TYPE_TX) ||
+ (p_PortParams->portType == e_FM_PORT_TYPE_RX))
+ {
+ ASSERT_COND(macId < FM_MAX_NUM_OF_1G_MACS);
+ if (p_PortParams->maxFrameLength >= p_Fm->p_FmStateStruct->macMaxFrameLengths1G[macId])
+ p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId] = p_PortParams->maxFrameLength;
+ else
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Port maxFrameLength is smaller than MAC current MTU"));
+ }
+
+ FmGetPhysicalMuramBase(p_Fm, &p_PortParams->fmMuramPhysBaseAddr);
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+
+ return E_OK;
+}
+
+void FmFreePortParams(t_Handle h_Fm,t_FmInterModulePortFreeParams *p_PortParams)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ uint32_t intFlags;
+ uint8_t hardwarePortId = p_PortParams->hardwarePortId;
+ uint8_t numOfTasks, numOfDmas, macId;
+ uint16_t sizeOfFifo;
+ t_Error err;
+ t_FmIpcPortFreeParams portParams;
+ t_FmIpcMsg msg;
+ struct fman_qmi_regs *qmi_rg = p_Fm->p_FmQmiRegs;
+ struct fman_bmi_regs *bmi_rg = p_Fm->p_FmBmiRegs;
+
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ {
+ portParams.hardwarePortId = p_PortParams->hardwarePortId;
+ portParams.enumPortType = (uint32_t)p_PortParams->portType;
+ portParams.deqPipelineDepth = p_PortParams->deqPipelineDepth;
+ memset(&msg, 0, sizeof(msg));
+ msg.msgId = FM_FREE_PORT;
+ memcpy(msg.msgBody, &portParams, sizeof(portParams));
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId)+sizeof(portParams),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ return;
+ }
+
+ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));
+
+ intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock);
+
+ if (p_PortParams->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND)
+ {
+ ASSERT_COND(p_Fm->hcPortInitialized);
+ p_Fm->hcPortInitialized = FALSE;
+ }
+
+ p_Fm->p_FmStateStruct->portsTypes[hardwarePortId] = e_FM_PORT_TYPE_DUMMY;
+
+ /* free numOfTasks */
+ numOfTasks = fman_get_num_of_tasks(bmi_rg, hardwarePortId);
+ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfTasks >= numOfTasks);
+ p_Fm->p_FmStateStruct->accumulatedNumOfTasks -= numOfTasks;
+
+ /* free numOfOpenDmas */
+ numOfDmas = fman_get_num_of_dmas(bmi_rg, hardwarePortId);
+ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas >= numOfDmas);
+ p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas -= numOfDmas;
+
+#ifdef FM_HAS_TOTAL_DMAS
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev < 6)
+ {
+ /* update total num of DMA's with committed number of open DMAS, and max uncommitted pool. */
+ fman_set_num_of_open_dmas(bmi_rg,
+ hardwarePortId,
+ 1,
+ 0,
+ (uint8_t)(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas + p_Fm->p_FmStateStruct->extraOpenDmasPoolSize));
+ }
+#endif /* FM_HAS_TOTAL_DMAS */
+
+ /* free sizeOfFifo */
+ sizeOfFifo = fman_get_size_of_fifo(bmi_rg, hardwarePortId);
+ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedFifoSize >= (sizeOfFifo * BMI_FIFO_UNITS));
+ p_Fm->p_FmStateStruct->accumulatedFifoSize -= (sizeOfFifo * BMI_FIFO_UNITS);
+
+#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev != 4)
+#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */
+ if ((p_PortParams->portType != e_FM_PORT_TYPE_RX) &&
+ (p_PortParams->portType != e_FM_PORT_TYPE_RX_10G))
+ /* for transmit & O/H ports */
+ {
+ uint8_t enqTh;
+ uint8_t deqTh;
+
+ /* update qmi ENQ/DEQ threshold */
+ p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums -= p_PortParams->deqPipelineDepth;
+
+ /* p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums is now smaller,
+ so we can enlarge enqTh */
+ enqTh = (uint8_t)(QMI_MAX_NUM_OF_TNUMS - p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums - 1);
+
+ /* p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums is now smaller,
+ so we can reduce deqTh */
+ deqTh = (uint8_t)(p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums + 1);
+
+ fman_set_qmi_enq_th(qmi_rg, enqTh);
+ fman_set_qmi_deq_th(qmi_rg, deqTh);
+ }
+
+ HW_PORT_ID_TO_SW_PORT_ID(macId, hardwarePortId);
+
+#if defined(FM_MAX_NUM_OF_10G_MACS) && (FM_MAX_NUM_OF_10G_MACS)
+ if ((p_PortParams->portType == e_FM_PORT_TYPE_TX_10G) ||
+ (p_PortParams->portType == e_FM_PORT_TYPE_RX_10G))
+ {
+ ASSERT_COND(macId < FM_MAX_NUM_OF_10G_MACS);
+ p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId] = 0;
+ }
+ else
+#endif /* defined(FM_MAX_NUM_OF_10G_MACS) && ... */
+ if ((p_PortParams->portType == e_FM_PORT_TYPE_TX) ||
+ (p_PortParams->portType == e_FM_PORT_TYPE_RX))
+ {
+ ASSERT_COND(macId < FM_MAX_NUM_OF_1G_MACS);
+ p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId] = 0;
+ }
+
+#ifdef FM_LOW_END_RESTRICTION
+ if ((hardwarePortId==0x1) || (hardwarePortId==0x29))
+ p_Fm->p_FmStateStruct->lowEndRestriction = FALSE;
+#endif /* FM_LOW_END_RESTRICTION */
+ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags);
+}
+
+t_Error FmIsPortStalled(t_Handle h_Fm, uint8_t hardwarePortId, bool *p_IsStalled)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ t_Error err;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+ struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs;
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->baseAddr &&
+ p_Fm->h_IpcSessions[0])
+ {
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_IS_PORT_STALLED;
+ msg.msgBody[0] = hardwarePortId;
+ replyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId)+sizeof(hardwarePortId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ if (replyLength != (sizeof(uint32_t) + sizeof(uint8_t)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+
+ *p_IsStalled = (bool)!!(*(uint8_t*)(reply.replyBody));
+
+ return (t_Error)(reply.error);
+ }
+ else if (!p_Fm->baseAddr)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("Either IPC or 'baseAddress' is required!"));
+
+ *p_IsStalled = fman_is_port_stalled(fpm_rg, hardwarePortId);
+
+ return E_OK;
+}
+
+t_Error FmResumeStalledPort(t_Handle h_Fm, uint8_t hardwarePortId)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ t_Error err;
+ bool isStalled;
+ struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs;
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->baseAddr &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_RESUME_STALLED_PORT;
+ msg.msgBody[0] = hardwarePortId;
+ replyLength = sizeof(uint32_t);
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(hardwarePortId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ return (t_Error)(reply.error);
+ }
+ else if (!p_Fm->baseAddr)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("Either IPC or 'baseAddress' is required!"));
+
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)
+ RETURN_ERROR(MINOR, E_NOT_AVAILABLE, ("Not available for this FM revision!"));
+
+ /* Get port status */
+ err = FmIsPortStalled(h_Fm, hardwarePortId, &isStalled);
+ if (err)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Can't get port status"));
+ if (!isStalled)
+ return E_OK;
+
+ fman_resume_stalled_port(fpm_rg, hardwarePortId);
+
+ return E_OK;
+}
+
+t_Error FmResetMac(t_Handle h_Fm, e_FmMacType type, uint8_t macId)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ t_Error err;
+ struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs;
+
+#if (DPAA_VERSION >= 11)
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("FMan MAC reset!"));
+#endif /*(DPAA_VERSION >= 11)*/
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->baseAddr &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcMacParams macParams;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ macParams.id = macId;
+ macParams.enumType = (uint32_t)type;
+ msg.msgId = FM_RESET_MAC;
+ memcpy(msg.msgBody, &macParams, sizeof(macParams));
+ replyLength = sizeof(uint32_t);
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId)+sizeof(macParams),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ return (t_Error)(reply.error);
+ }
+ else if (!p_Fm->baseAddr)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("Either IPC or 'baseAddress' is required!"));
+
+ err = (t_Error)fman_reset_mac(fpm_rg, macId, !!(type == e_FM_MAC_10G));
+
+ if (err == E_INVALID_VALUE)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Illegal MAC Id"));
+ else if (err == E_TIMEOUT)
+ return ERROR_CODE(E_TIMEOUT);
+
+ return E_OK;
+}
+
+t_Error FmSetMacMaxFrame(t_Handle h_Fm, e_FmMacType type, uint8_t macId, uint16_t mtu)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcMacMaxFrameParams macMaxFrameLengthParams;
+ t_Error err;
+ t_FmIpcMsg msg;
+
+ memset(&msg, 0, sizeof(msg));
+ macMaxFrameLengthParams.macParams.id = macId;
+ macMaxFrameLengthParams.macParams.enumType = (uint32_t)type;
+ macMaxFrameLengthParams.maxFrameLength = (uint16_t)mtu;
+ msg.msgId = FM_SET_MAC_MAX_FRAME;
+ memcpy(msg.msgBody, &macMaxFrameLengthParams, sizeof(macMaxFrameLengthParams));
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId)+sizeof(macMaxFrameLengthParams),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ return E_OK;
+ }
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without IPC!"));
+
+ /* if port is already initialized, check that MaxFrameLength is smaller
+ * or equal to the port's max */
+#if (defined(FM_MAX_NUM_OF_10G_MACS) && (FM_MAX_NUM_OF_10G_MACS))
+ if (type == e_FM_MAC_10G)
+ {
+ if ((!p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId])
+ || (p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId] &&
+ (mtu <= p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId])))
+ p_Fm->p_FmStateStruct->macMaxFrameLengths10G[macId] = mtu;
+ else
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("MAC maxFrameLength is larger than Port maxFrameLength"));
+
+ }
+ else
+#else
+ UNUSED(type);
+#endif /* (defined(FM_MAX_NUM_OF_10G_MACS) && ... */
+ if ((!p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId])
+ || (p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId] &&
+ (mtu <= p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId])))
+ p_Fm->p_FmStateStruct->macMaxFrameLengths1G[macId] = mtu;
+ else
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, ("MAC maxFrameLength is larger than Port maxFrameLength"));
+
+ return E_OK;
+}
+
+uint16_t FmGetClockFreq(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ /* for multicore environment: this depends on the
+ * fact that fmClkFreq was properly initialized at "init". */
+ return p_Fm->p_FmStateStruct->fmClkFreq;
+}
+
+uint32_t FmGetTimeStampScale(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->baseAddr &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_Error err;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength, timeStamp;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_GET_TIMESTAMP_SCALE;
+ replyLength = sizeof(uint32_t) + sizeof(uint32_t);
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ if (replyLength != (sizeof(uint32_t) + sizeof(uint32_t)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+
+ memcpy((uint8_t*)&timeStamp, reply.replyBody, sizeof(uint32_t));
+ return timeStamp;
+ }
+ else if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ p_Fm->baseAddr)
+ {
+ if (!(GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_tsc1) & FPM_TS_CTL_EN))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("timestamp is not enabled!"));
+
+ return p_Fm->p_FmStateStruct->count1MicroBit;
+ }
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ DBG(WARNING, ("No IPC - can't validate FM if timestamp enabled."));
+
+ return p_Fm->p_FmStateStruct->count1MicroBit;
+}
+
+t_Error FmEnableRamsEcc(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+
+ p_Fm->p_FmStateStruct->ramsEccOwners++;
+ p_Fm->p_FmStateStruct->internalCall = TRUE;
+
+ return FM_EnableRamsEcc(p_Fm);
+}
+
+t_Error FmDisableRamsEcc(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+
+ ASSERT_COND(p_Fm->p_FmStateStruct->ramsEccOwners);
+ p_Fm->p_FmStateStruct->ramsEccOwners--;
+
+ if (p_Fm->p_FmStateStruct->ramsEccOwners==0)
+ {
+ p_Fm->p_FmStateStruct->internalCall = TRUE;
+ return FM_DisableRamsEcc(p_Fm);
+ }
+
+ return E_OK;
+}
+
+uint8_t FmGetGuestId(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ return p_Fm->guestId;
+}
+
+bool FmIsMaster(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ return (p_Fm->guestId == NCSW_MASTER_ID);
+}
+
+t_Error FmSetSizeOfFifo(t_Handle h_Fm,
+ uint8_t hardwarePortId,
+ uint32_t *p_SizeOfFifo,
+ uint32_t *p_ExtraSizeOfFifo,
+ bool initialConfig)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ t_FmIpcPortRsrcParams rsrcParams;
+ t_Error err;
+ struct fman_bmi_regs *bmi_rg = p_Fm->p_FmBmiRegs;
+ uint32_t sizeOfFifo = *p_SizeOfFifo, extraSizeOfFifo = *p_ExtraSizeOfFifo;
+ uint16_t currentVal = 0, currentExtraVal = 0;
+
+ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->baseAddr &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+
+ rsrcParams.hardwarePortId = hardwarePortId;
+ rsrcParams.val = sizeOfFifo;
+ rsrcParams.extra = extraSizeOfFifo;
+ rsrcParams.boolInitialConfig = (uint8_t)initialConfig;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_SET_SIZE_OF_FIFO;
+ memcpy(msg.msgBody, &rsrcParams, sizeof(rsrcParams));
+ replyLength = sizeof(uint32_t);
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(rsrcParams),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ return (t_Error)(reply.error);
+ }
+ else if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ p_Fm->baseAddr)
+ {
+ DBG(WARNING, ("No IPC - can't validate FM total-fifo size."));
+
+#ifndef FM_NO_GUARANTEED_RESET_VALUES
+ if (!sizeOfFifo)
+ /* first config without explicit value: Do Nothing - reset value shouldn't be
+ changed, read register for port save */
+ {
+ *p_ExtraSizeOfFifo = fman_get_size_of_extra_fifo(bmi_rg, hardwarePortId);
+ *p_SizeOfFifo = fman_get_size_of_fifo(bmi_rg, hardwarePortId);
+ }
+ else
+ /* whether it is the first time with explicit value, or runtime "set" - write register */
+#endif /* !FM_NO_GUARANTEED_RESET_VALUES */
+ fman_set_size_of_fifo(bmi_rg, hardwarePortId, sizeOfFifo, extraSizeOfFifo);
+ }
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without neither IPC nor mapped register!"));
+
+ if (!initialConfig)
+ {
+ /* !initialConfig - runtime change of existing value.
+ * - read the current FIFO and extra FIFO size */
+ currentExtraVal = fman_get_size_of_extra_fifo(bmi_rg, hardwarePortId);
+ currentVal = fman_get_size_of_fifo(bmi_rg, hardwarePortId);
+ }
+
+#ifndef FM_NO_GUARANTEED_RESET_VALUES
+ /* it's illegal to be in a state where this is not the first set and no value is specified */
+ ASSERT_COND(initialConfig || sizeOfFifo);
+ if (!sizeOfFifo)
+ {
+ /* !sizeOfFifo - first configuration according to values in regs.
+ * - read the current FIFO and extra FIFO size */
+ currentExtraVal = fman_get_size_of_extra_fifo(bmi_rg, hardwarePortId);
+ currentVal = fman_get_size_of_fifo(bmi_rg, hardwarePortId);
+ /* This is the first configuration and user did not specify value (!numOfTasks),
+ * reset values will be used and we just save these values for resource management */
+ if (currentExtraVal)
+ {
+ if (!p_Fm->p_FmStateStruct->extraFifoPoolSize)
+ /* if this is the first time a port requires extraFifoPoolSize, the total extraFifoPoolSize
+ * must be initialized to 1 buffer per port
+ */
+ p_Fm->p_FmStateStruct->extraFifoPoolSize = FM_MAX_NUM_OF_RX_PORTS*BMI_FIFO_UNITS;
+
+ p_Fm->p_FmStateStruct->extraFifoPoolSize = MAX(p_Fm->p_FmStateStruct->extraFifoPoolSize, extraSizeOfFifo);
+ }
+ if ((p_Fm->p_FmStateStruct->accumulatedFifoSize + currentVal) >
+ (p_Fm->p_FmStateStruct->totalFifoSize - p_Fm->p_FmStateStruct->extraFifoPoolSize))
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Total port's fifo size and extra size exceed total available FIFO size."));
+
+ p_Fm->p_FmStateStruct->accumulatedFifoSize += currentVal;
+
+ *p_SizeOfFifo = currentVal;
+ *p_ExtraSizeOfFifo = currentExtraVal;
+ return E_OK;
+ }
+ /* else: user requires a specific value.
+ * If this is the first configuration call, (numOfTasks != 0) currentVal & currentExtraVal are set to "0",
+ * otherwise they hold the value written in the register.
+ */
+#endif /* !FM_NO_GUARANTEED_RESET_VALUES */
+ if (extraSizeOfFifo > currentExtraVal)
+ {
+ if (extraSizeOfFifo && !p_Fm->p_FmStateStruct->extraFifoPoolSize)
+ /* if this is the first time a port requires extraFifoPoolSize, the total extraFifoPoolSize
+ * must be initialized to 1 buffer per port
+ */
+ p_Fm->p_FmStateStruct->extraFifoPoolSize = FM_MAX_NUM_OF_RX_PORTS*BMI_FIFO_UNITS;
+
+ p_Fm->p_FmStateStruct->extraFifoPoolSize = MAX(p_Fm->p_FmStateStruct->extraFifoPoolSize, extraSizeOfFifo);
+ }
+
+ /* check that there are enough uncommitted fifo size */
+ if ((p_Fm->p_FmStateStruct->accumulatedFifoSize - currentVal + sizeOfFifo) >
+ (p_Fm->p_FmStateStruct->totalFifoSize - p_Fm->p_FmStateStruct->extraFifoPoolSize))
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Requested fifo size and extra size exceed total FIFO size."));
+ else
+ {
+ /* update accumulated */
+ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedFifoSize >= currentVal);
+ p_Fm->p_FmStateStruct->accumulatedFifoSize -= currentVal;
+ p_Fm->p_FmStateStruct->accumulatedFifoSize += sizeOfFifo;
+ fman_set_size_of_fifo(bmi_rg, hardwarePortId, sizeOfFifo, extraSizeOfFifo);
+ }
+
+ return E_OK;
+}
+
+t_Error FmSetNumOfTasks(t_Handle h_Fm,
+ uint8_t hardwarePortId,
+ uint8_t *p_NumOfTasks,
+ uint8_t *p_NumOfExtraTasks,
+ bool initialConfig)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+ t_Error err;
+ struct fman_bmi_regs *bmi_rg = p_Fm->p_FmBmiRegs;
+ uint8_t currentVal = 0, currentExtraVal = 0, numOfTasks = *p_NumOfTasks, numOfExtraTasks = *p_NumOfExtraTasks;
+
+ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->baseAddr &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcPortRsrcParams rsrcParams;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+
+ rsrcParams.hardwarePortId = hardwarePortId;
+ rsrcParams.val = numOfTasks;
+ rsrcParams.extra = numOfExtraTasks;
+ rsrcParams.boolInitialConfig = (uint8_t)initialConfig;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_SET_NUM_OF_TASKS;
+ memcpy(msg.msgBody, &rsrcParams, sizeof(rsrcParams));
+ replyLength = sizeof(uint32_t);
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(rsrcParams),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ return (t_Error)(reply.error);
+ }
+ else if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ p_Fm->baseAddr)
+ {
+ DBG(WARNING, ("No IPC - can't validate FM total-num-of-tasks."));
+
+#ifndef FM_NO_GUARANTEED_RESET_VALUES
+ if (!numOfTasks)
+ /* first config without explicit value: Do Nothing - reset value shouldn't be
+ changed, read register for port save */
+ {
+ *p_NumOfTasks = fman_get_num_of_tasks(bmi_rg, hardwarePortId);
+ *p_NumOfExtraTasks = fman_get_num_extra_tasks(bmi_rg, hardwarePortId);
+ }
+ else
+ /* whether it is the first time with explicit value, or runtime "set" - write register */
+#endif /* !FM_NO_GUARANTEED_RESET_VALUES */
+ fman_set_num_of_tasks(bmi_rg, hardwarePortId, numOfTasks, numOfExtraTasks);
+ }
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without neither IPC nor mapped register!"));
+
+ if (!initialConfig)
+ {
+ /* !initialConfig - runtime change of existing value.
+ * - read the current number of tasks */
+ currentVal = fman_get_num_of_tasks(bmi_rg, hardwarePortId);
+ currentExtraVal = fman_get_num_extra_tasks(bmi_rg, hardwarePortId);
+ }
+
+#ifndef FM_NO_GUARANTEED_RESET_VALUES
+ /* it's illegal to be in a state where this is not the first set and no value is specified */
+ ASSERT_COND(initialConfig || numOfTasks);
+ if (!numOfTasks)
+ {
+ /* !numOfTasks - first configuration according to values in regs.
+ * - read the current number of tasks */
+ currentVal = fman_get_num_of_tasks(bmi_rg, hardwarePortId);
+ currentExtraVal = fman_get_num_extra_tasks(bmi_rg, hardwarePortId);
+ /* This is the first configuration and user did not specify value (!numOfTasks),
+ * reset values will be used and we just save these values for resource management */
+ p_Fm->p_FmStateStruct->extraTasksPoolSize =
+ (uint8_t)MAX(p_Fm->p_FmStateStruct->extraTasksPoolSize, currentExtraVal);
+ if ((p_Fm->p_FmStateStruct->accumulatedNumOfTasks + currentVal) >
+ (p_Fm->p_FmStateStruct->totalNumOfTasks - p_Fm->p_FmStateStruct->extraTasksPoolSize))
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE,
+ ("Total ports' numOfTasks and extra tasks pool for fm%d exceed total available numOfTasks.",
+ p_Fm->p_FmStateStruct->fmId));
+ p_Fm->p_FmStateStruct->accumulatedNumOfTasks += currentVal;
+ *p_NumOfTasks = currentVal;
+ *p_NumOfExtraTasks = currentExtraVal;
+ return E_OK;
+ }
+ /* else - user requires a specific value.
+ * If this is the first configuration call, (numOfTasks != 0) currentVal & currentExtraVal are set to "0",
+ * otherwise they hold the value written in the register.
+ */
+#endif /* !FM_NO_GUARANTEED_RESET_VALUES */
+ if (numOfExtraTasks > currentExtraVal)
+ p_Fm->p_FmStateStruct->extraTasksPoolSize =
+ (uint8_t)MAX(p_Fm->p_FmStateStruct->extraTasksPoolSize, numOfExtraTasks);
+
+ /* check that there are enough uncommitted tasks */
+ if ((p_Fm->p_FmStateStruct->accumulatedNumOfTasks - currentVal + numOfTasks) >
+ (p_Fm->p_FmStateStruct->totalNumOfTasks - p_Fm->p_FmStateStruct->extraTasksPoolSize))
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE,
+ ("Requested numOfTasks and extra tasks pool for fm%d exceed total numOfTasks.",
+ p_Fm->p_FmStateStruct->fmId));
+ else
+ {
+ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfTasks >= currentVal);
+ /* update accumulated */
+ p_Fm->p_FmStateStruct->accumulatedNumOfTasks -= currentVal;
+ p_Fm->p_FmStateStruct->accumulatedNumOfTasks += numOfTasks;
+ fman_set_num_of_tasks(bmi_rg, hardwarePortId, numOfTasks, numOfExtraTasks);
+ }
+
+ return E_OK;
+}
+
+t_Error FmSetNumOfOpenDmas(t_Handle h_Fm,
+ uint8_t hardwarePortId,
+ uint8_t *p_NumOfOpenDmas,
+ uint8_t *p_NumOfExtraOpenDmas,
+ bool initialConfig)
+
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+ t_Error err;
+ struct fman_bmi_regs *bmi_rg = p_Fm->p_FmBmiRegs;
+ uint8_t numOfOpenDmas = *p_NumOfOpenDmas, numOfExtraOpenDmas = *p_NumOfExtraOpenDmas;
+ uint8_t totalNumDmas = 0, currentVal = 0, currentExtraVal = 0;
+
+ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->baseAddr &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcPortRsrcParams rsrcParams;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+
+ rsrcParams.hardwarePortId = hardwarePortId;
+ rsrcParams.val = numOfOpenDmas;
+ rsrcParams.extra = numOfExtraOpenDmas;
+ rsrcParams.boolInitialConfig = (uint8_t)initialConfig;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_SET_NUM_OF_OPEN_DMAS;
+ memcpy(msg.msgBody, &rsrcParams, sizeof(rsrcParams));
+ replyLength = sizeof(uint32_t);
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) + sizeof(rsrcParams),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ if (replyLength != sizeof(uint32_t))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ return (t_Error)(reply.error);
+ }
+#ifdef FM_HAS_TOTAL_DMAS
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without IPC!"));
+#else
+ else if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ p_Fm->baseAddr &&
+ (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6))
+ {
+ /*DBG(WARNING, ("No IPC - can't validate FM total-num-of-dmas."));*/
+
+#ifdef FM_NO_GUARANTEED_RESET_VALUES
+ if (!numOfOpenDmas)
+ {
+ /* first config without explic it value: Do Nothing - reset value shouldn't be
+ changed, read register for port save */
+ *p_NumOfOpenDmas = fman_get_num_of_dmas(bmi_rg, hardwarePortId);
+ *p_NumOfExtraOpenDmas = fman_get_num_extra_dmas(bmi_rg, hardwarePortId);
+ }
+ else
+ /* whether it is the first time with explicit value, or runtime "set" - write register */
+#endif /* FM_NO_GUARANTEED_RESET_VALUES */
+ fman_set_num_of_open_dmas(bmi_rg,
+ hardwarePortId,
+ numOfOpenDmas,
+ numOfExtraOpenDmas,
+ p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas + p_Fm->p_FmStateStruct->extraOpenDmasPoolSize);
+ }
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without neither IPC nor mapped register!"));
+#endif /* FM_HAS_TOTAL_DMAS */
+
+ if (!initialConfig)
+ {
+ /* !initialConfig - runtime change of existing value.
+ * - read the current number of open Dma's */
+ currentExtraVal = fman_get_num_extra_dmas(bmi_rg, hardwarePortId);
+ currentVal = fman_get_num_of_dmas(bmi_rg, hardwarePortId);
+ }
+
+#ifdef FM_NO_GUARANTEED_RESET_VALUES
+ /* it's illegal to be in a state where this is not the first set and no value is specified */
+ ASSERT_COND(initialConfig || numOfOpenDmas);
+ if (!numOfOpenDmas)
+ {
+ /* !numOfOpenDmas - first configuration according to values in regs.
+ * - read the current number of open Dma's */
+ currentExtraVal = fman_get_num_extra_dmas(bmi_rg, hardwarePortId);
+ currentVal = fman_get_num_of_dmas(bmi_rg, hardwarePortId);
+ /* This is the first configuration and user did not specify value (!numOfOpenDmas),
+ * reset values will be used and we just save these values for resource management */
+ p_Fm->p_FmStateStruct->extraOpenDmasPoolSize =
+ (uint8_t)MAX(p_Fm->p_FmStateStruct->extraOpenDmasPoolSize, currentExtraVal);
+ p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas += currentVal;
+ *p_NumOfOpenDmas = currentVal;
+ *p_NumOfExtraOpenDmas = currentExtraVal;
+ return E_OK;
+ }
+#endif /* FM_NO_GUARANTEED_RESET_VALUES */
+
+ if (numOfExtraOpenDmas > currentExtraVal)
+ p_Fm->p_FmStateStruct->extraOpenDmasPoolSize =
+ (uint8_t)MAX(p_Fm->p_FmStateStruct->extraOpenDmasPoolSize, numOfExtraOpenDmas);
+
+#ifdef FM_HAS_TOTAL_DMAS
+ if ((p_Fm->p_FmStateStruct->revInfo.majorRev < 6) &&
+ (p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas - currentVal + numOfOpenDmas >
+ p_Fm->p_FmStateStruct->maxNumOfOpenDmas))
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE,
+ ("Requested numOfOpenDmas for fm%d exceeds total numOfOpenDmas.",
+ p_Fm->p_FmStateStruct->fmId));
+#else
+ if ((p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) &&
+#ifdef FM_HEAVY_TRAFFIC_SEQUENCER_HANG_ERRATA_FMAN_A006981
+ !((p_Fm->p_FmStateStruct->revInfo.majorRev == 6) &&
+ (p_Fm->p_FmStateStruct->revInfo.minorRev == 0)) &&
+#endif /* FM_HEAVY_TRAFFIC_SEQUENCER_HANG_ERRATA_FMAN_A006981 */
+ (p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas - currentVal + numOfOpenDmas > DMA_THRESH_MAX_COMMQ + 1))
+ RETURN_ERROR(MAJOR, E_NOT_AVAILABLE,
+ ("Requested numOfOpenDmas for fm%d exceeds DMA Command queue (%d)",
+ p_Fm->p_FmStateStruct->fmId, DMA_THRESH_MAX_COMMQ+1));
+#endif /* FM_HAS_TOTAL_DMAS */
+ else
+ {
+ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas >= currentVal);
+ /* update acummulated */
+ p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas -= currentVal;
+ p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas += numOfOpenDmas;
+
+#ifdef FM_HAS_TOTAL_DMAS
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev < 6)
+ totalNumDmas = (uint8_t)(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas + p_Fm->p_FmStateStruct->extraOpenDmasPoolSize);
+#endif /* FM_HAS_TOTAL_DMAS */
+ fman_set_num_of_open_dmas(bmi_rg,
+ hardwarePortId,
+ numOfOpenDmas,
+ numOfExtraOpenDmas,
+ totalNumDmas);
+ }
+
+ return E_OK;
+}
+
+#if (DPAA_VERSION >= 11)
+t_Error FmVSPCheckRelativeProfile(t_Handle h_Fm,
+ e_FmPortType portType,
+ uint8_t portId,
+ uint16_t relativeProfile)
+{
+ t_Fm *p_Fm;
+ t_FmSp *p_FmPcdSp;
+ uint8_t swPortIndex=0, hardwarePortId;
+
+ ASSERT_COND(h_Fm);
+ p_Fm = (t_Fm*)h_Fm;
+
+ SW_PORT_ID_TO_HW_PORT_ID(hardwarePortId, portType, portId)
+ ASSERT_COND(hardwarePortId);
+ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId);
+
+ p_FmPcdSp = p_Fm->p_FmSp;
+ ASSERT_COND(p_FmPcdSp);
+
+ if (!p_FmPcdSp->portsMapping[swPortIndex].numOfProfiles)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE , ("Port has no allocated profiles"));
+ if (relativeProfile >= p_FmPcdSp->portsMapping[swPortIndex].numOfProfiles)
+ RETURN_ERROR(MAJOR, E_NOT_IN_RANGE , ("Profile id is out of range"));
+
+ return E_OK;
+}
+
+t_Error FmVSPGetAbsoluteProfileId(t_Handle h_Fm,
+ e_FmPortType portType,
+ uint8_t portId,
+ uint16_t relativeProfile,
+ uint16_t *p_AbsoluteId)
+{
+ t_Fm *p_Fm;
+ t_FmSp *p_FmPcdSp;
+ uint8_t swPortIndex=0, hardwarePortId;
+ t_Error err;
+
+ ASSERT_COND(h_Fm);
+ p_Fm = (t_Fm*)h_Fm;
+
+ err = FmVSPCheckRelativeProfile(h_Fm, portType, portId, relativeProfile);
+ if (err != E_OK)
+ return err;
+
+ SW_PORT_ID_TO_HW_PORT_ID(hardwarePortId, portType, portId)
+ ASSERT_COND(hardwarePortId);
+ HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId);
+
+ p_FmPcdSp = p_Fm->p_FmSp;
+ ASSERT_COND(p_FmPcdSp);
+
+ *p_AbsoluteId = (uint16_t)(p_FmPcdSp->portsMapping[swPortIndex].profilesBase + relativeProfile);
+
+ return E_OK;
+}
+#endif /* (DPAA_VERSION >= 11) */
+
+static t_Error InitFmDma(t_Fm *p_Fm)
+{
+ t_Error err;
+
+ err = (t_Error)fman_dma_init(p_Fm->p_FmDmaRegs, p_Fm->p_FmDriverParam);
+ if (err != E_OK)
+ return err;
+
+ /* Allocate MURAM for CAM */
+ p_Fm->camBaseAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_Fm->h_FmMuram,
+ (uint32_t)(p_Fm->p_FmDriverParam->dma_cam_num_of_entries*DMA_CAM_SIZEOF_ENTRY),
+ DMA_CAM_ALIGN));
+ if (!p_Fm->camBaseAddr)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for DMA CAM failed"));
+
+ WRITE_BLOCK(UINT_TO_PTR(p_Fm->camBaseAddr),
+ 0,
+ (uint32_t)(p_Fm->p_FmDriverParam->dma_cam_num_of_entries*DMA_CAM_SIZEOF_ENTRY));
+
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev == 2)
+ {
+ FM_MURAM_FreeMem(p_Fm->h_FmMuram, UINT_TO_PTR(p_Fm->camBaseAddr));
+
+ p_Fm->camBaseAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_Fm->h_FmMuram,
+ (uint32_t)(p_Fm->p_FmDriverParam->dma_cam_num_of_entries*72 + 128),
+ 64));
+ if (!p_Fm->camBaseAddr)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for DMA CAM failed"));
+
+ WRITE_BLOCK(UINT_TO_PTR(p_Fm->camBaseAddr),
+ 0,
+ (uint32_t)(p_Fm->p_FmDriverParam->dma_cam_num_of_entries*72 + 128));
+
+ switch(p_Fm->p_FmDriverParam->dma_cam_num_of_entries)
+ {
+ case (8):
+ WRITE_UINT32(*(uint32_t*)p_Fm->camBaseAddr, 0xff000000);
+ break;
+ case (16):
+ WRITE_UINT32(*(uint32_t*)p_Fm->camBaseAddr, 0xffff0000);
+ break;
+ case (24):
+ WRITE_UINT32(*(uint32_t*)p_Fm->camBaseAddr, 0xffffff00);
+ break;
+ case (32):
+ WRITE_UINT32(*(uint32_t*)p_Fm->camBaseAddr, 0xffffffff);
+ break;
+ default:
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("wrong dma_cam_num_of_entries"));
+ }
+ }
+
+ p_Fm->p_FmDriverParam->cam_base_addr =
+ (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Fm->camBaseAddr)) - p_Fm->fmMuramPhysBaseAddr);
+
+ return E_OK;
+}
+
+static t_Error InitFmFpm(t_Fm *p_Fm)
+{
+ return (t_Error)fman_fpm_init(p_Fm->p_FmFpmRegs, p_Fm->p_FmDriverParam);
+}
+
+static t_Error InitFmBmi(t_Fm *p_Fm)
+{
+ return (t_Error)fman_bmi_init(p_Fm->p_FmBmiRegs, p_Fm->p_FmDriverParam);
+}
+
+static t_Error InitFmQmi(t_Fm *p_Fm)
+{
+ return (t_Error)fman_qmi_init(p_Fm->p_FmQmiRegs, p_Fm->p_FmDriverParam);
+}
+
+static t_Error InitGuestMode(t_Fm *p_Fm)
+{
+ t_Error err = E_OK;
+ int i;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+
+ ASSERT_COND(p_Fm);
+ ASSERT_COND(p_Fm->guestId != NCSW_MASTER_ID);
+
+ /* build the FM guest partition IPC address */
+ if (Sprint (p_Fm->fmModuleName, "FM_%d_%d",p_Fm->p_FmStateStruct->fmId, p_Fm->guestId) != (p_Fm->guestId<10 ? 6:7))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
+
+ /* build the FM master partition IPC address */
+ memset(p_Fm->fmIpcHandlerModuleName, 0, (sizeof(char)) * MODULE_NAME_SIZE);
+ if (Sprint (p_Fm->fmIpcHandlerModuleName[0], "FM_%d_%d",p_Fm->p_FmStateStruct->fmId, NCSW_MASTER_ID) != 6)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
+
+ for (i=0;i<e_FM_EV_DUMMY_LAST;i++)
+ p_Fm->intrMng[i].f_Isr = UnimplementedIsr;
+
+ p_Fm->h_IpcSessions[0] = XX_IpcInitSession(p_Fm->fmIpcHandlerModuleName[0], p_Fm->fmModuleName);
+ if (p_Fm->h_IpcSessions[0])
+ {
+ uint8_t isMasterAlive;
+ t_FmIpcParams ipcParams;
+
+ err = XX_IpcRegisterMsgHandler(p_Fm->fmModuleName, FmGuestHandleIpcMsgCB, p_Fm, FM_IPC_MAX_REPLY_SIZE);
+ if (err)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_MASTER_IS_ALIVE;
+ msg.msgBody[0] = p_Fm->guestId;
+ replyLength = sizeof(uint32_t) + sizeof(uint8_t);
+ do
+ {
+ blockingFlag = TRUE;
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId)+sizeof(p_Fm->guestId),
+ (uint8_t*)&reply,
+ &replyLength,
+ IpcMsgCompletionCB,
+ p_Fm)) != E_OK)
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ while (blockingFlag) ;
+ if (replyLength != (sizeof(uint32_t) + sizeof(uint8_t)))
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ isMasterAlive = *(uint8_t*)(reply.replyBody);
+ } while (!isMasterAlive);
+
+ /* read FM parameters and save */
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_GET_PARAMS;
+ replyLength = sizeof(uint32_t) + sizeof(t_FmIpcParams);
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ if (replyLength != (sizeof(uint32_t) + sizeof(t_FmIpcParams)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ memcpy((uint8_t*)&ipcParams, reply.replyBody, sizeof(t_FmIpcParams));
+
+ p_Fm->p_FmStateStruct->fmClkFreq = ipcParams.fmClkFreq;
+ p_Fm->p_FmStateStruct->revInfo.majorRev = ipcParams.majorRev;
+ p_Fm->p_FmStateStruct->revInfo.minorRev = ipcParams.minorRev;
+ }
+ else
+ {
+ DBG(WARNING, ("FM Guest mode - without IPC"));
+ if (!p_Fm->p_FmStateStruct->fmClkFreq)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("No fmClkFreq configured for guest without IPC"));
+ if (p_Fm->baseAddr)
+ {
+ fman_get_revision(p_Fm->p_FmFpmRegs,
+ &p_Fm->p_FmStateStruct->revInfo.majorRev,
+ &p_Fm->p_FmStateStruct->revInfo.minorRev);
+
+ }
+ }
+
+#if (DPAA_VERSION >= 11)
+ p_Fm->partVSPBase = AllocVSPsForPartition(p_Fm, p_Fm->partVSPBase, p_Fm->partNumOfVSPs, p_Fm->guestId);
+ if (p_Fm->partVSPBase == ILLEGAL_BASE)
+ DBG(WARNING, ("partition VSPs allocation is FAILED"));
+#endif /* (DPAA_VERSION >= 11) */
+
+ /* General FM driver initialization */
+ if (p_Fm->baseAddr)
+ p_Fm->fmMuramPhysBaseAddr =
+ (uint64_t)(XX_VirtToPhys(UINT_TO_PTR(p_Fm->baseAddr + FM_MM_MURAM)));
+
+ XX_Free(p_Fm->p_FmDriverParam);
+ p_Fm->p_FmDriverParam = NULL;
+
+ if ((p_Fm->guestId == NCSW_MASTER_ID) ||
+ (p_Fm->h_IpcSessions[0]))
+ {
+ FM_DisableRamsEcc(p_Fm);
+ FmMuramClear(p_Fm->h_FmMuram);
+ FM_EnableRamsEcc(p_Fm);
+ }
+
+ return E_OK;
+}
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+t_Error FmDumpPortRegs (t_Handle h_Fm, uint8_t hardwarePortId)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+
+ DECLARE_DUMP;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(((p_Fm->guestId == NCSW_MASTER_ID) ||
+ p_Fm->baseAddr), E_INVALID_OPERATION);
+
+ DUMP_TITLE(&p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1], ("fmbm_pp for port %u", (hardwarePortId)));
+ DUMP_MEMORY(&p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1], sizeof(uint32_t));
+
+ DUMP_TITLE(&p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1], ("fmbm_pfs for port %u", (hardwarePortId )));
+ DUMP_MEMORY(&p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1], sizeof(uint32_t));
+
+ DUMP_TITLE(&p_Fm->p_FmBmiRegs->fmbm_spliodn[hardwarePortId-1], ("fmbm_spliodn for port %u", (hardwarePortId)));
+ DUMP_MEMORY(&p_Fm->p_FmBmiRegs->fmbm_spliodn[hardwarePortId-1], sizeof(uint32_t));
+
+ DUMP_TITLE(&p_Fm->p_FmFpmRegs->fmfp_ps[hardwarePortId], ("fmfp_ps for port %u", (hardwarePortId)));
+ DUMP_MEMORY(&p_Fm->p_FmFpmRegs->fmfp_ps[hardwarePortId], sizeof(uint32_t));
+
+ DUMP_TITLE(&p_Fm->p_FmDmaRegs->fmdmplr[hardwarePortId/2], ("fmdmplr for port %u", (hardwarePortId)));
+ DUMP_MEMORY(&p_Fm->p_FmDmaRegs->fmdmplr[hardwarePortId/2], sizeof(uint32_t));
+
+ return E_OK;
+}
+#endif /* (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) */
+
+
+/*****************************************************************************/
+/* API Init unit functions */
+/*****************************************************************************/
+t_Handle FM_Config(t_FmParams *p_FmParam)
+{
+ t_Fm *p_Fm;
+ uint8_t i;
+ uintptr_t baseAddr;
+
+ SANITY_CHECK_RETURN_VALUE(p_FmParam, E_NULL_POINTER, NULL);
+ SANITY_CHECK_RETURN_VALUE(((p_FmParam->firmware.p_Code && p_FmParam->firmware.size) ||
+ (!p_FmParam->firmware.p_Code && !p_FmParam->firmware.size)),
+ E_INVALID_VALUE, NULL);
+
+ baseAddr = p_FmParam->baseAddr;
+
+ /* Allocate FM structure */
+ p_Fm = (t_Fm *) XX_Malloc(sizeof(t_Fm));
+ if (!p_Fm)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM driver structure"));
+ return NULL;
+ }
+ memset(p_Fm, 0, sizeof(t_Fm));
+
+ p_Fm->p_FmStateStruct = (t_FmStateStruct *) XX_Malloc(sizeof(t_FmStateStruct));
+ if (!p_Fm->p_FmStateStruct)
+ {
+ XX_Free(p_Fm);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Status structure"));
+ return NULL;
+ }
+ memset(p_Fm->p_FmStateStruct, 0, sizeof(t_FmStateStruct));
+
+ /* Initialize FM parameters which will be kept by the driver */
+ p_Fm->p_FmStateStruct->fmId = p_FmParam->fmId;
+ p_Fm->guestId = p_FmParam->guestId;
+
+ for (i=0; i<FM_MAX_NUM_OF_HW_PORT_IDS; i++)
+ p_Fm->p_FmStateStruct->portsTypes[i] = e_FM_PORT_TYPE_DUMMY;
+
+ /* Allocate the FM driver's parameters structure */
+ p_Fm->p_FmDriverParam = (struct fman_cfg *)XX_Malloc(sizeof(struct fman_cfg));
+ if (!p_Fm->p_FmDriverParam)
+ {
+ XX_Free(p_Fm->p_FmStateStruct);
+ XX_Free(p_Fm);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM driver parameters"));
+ return NULL;
+ }
+ memset(p_Fm->p_FmDriverParam, 0, sizeof(struct fman_cfg));
+
+#if (DPAA_VERSION >= 11)
+ p_Fm->p_FmSp = (t_FmSp *)XX_Malloc(sizeof(t_FmSp));
+ if (!p_Fm->p_FmSp)
+ {
+ XX_Free(p_Fm->p_FmDriverParam);
+ XX_Free(p_Fm->p_FmStateStruct);
+ XX_Free(p_Fm);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("allocation for internal data structure failed"));
+ return NULL;
+ }
+ memset(p_Fm->p_FmSp, 0, sizeof(t_FmSp));
+
+ for (i=0; i<FM_VSP_MAX_NUM_OF_ENTRIES; i++)
+ p_Fm->p_FmSp->profiles[i].profilesMng.ownerId = (uint8_t)ILLEGAL_BASE;
+#endif /* (DPAA_VERSION >= 11) */
+
+ /* Initialize FM parameters which will be kept by the driver */
+ p_Fm->p_FmStateStruct->fmId = p_FmParam->fmId;
+ p_Fm->h_FmMuram = p_FmParam->h_FmMuram;
+ p_Fm->h_App = p_FmParam->h_App;
+ p_Fm->p_FmStateStruct->fmClkFreq = p_FmParam->fmClkFreq;
+ p_Fm->f_Exception = p_FmParam->f_Exception;
+ p_Fm->f_BusError = p_FmParam->f_BusError;
+ p_Fm->p_FmFpmRegs = (struct fman_fpm_regs *)UINT_TO_PTR(baseAddr + FM_MM_FPM);
+ p_Fm->p_FmBmiRegs = (struct fman_bmi_regs *)UINT_TO_PTR(baseAddr + FM_MM_BMI);
+ p_Fm->p_FmQmiRegs = (struct fman_qmi_regs *)UINT_TO_PTR(baseAddr + FM_MM_QMI);
+ p_Fm->p_FmDmaRegs = (struct fman_dma_regs *)UINT_TO_PTR(baseAddr + FM_MM_DMA);
+ p_Fm->p_FmRegs = (struct fman_regs *)UINT_TO_PTR(baseAddr + FM_MM_BMI);
+ p_Fm->baseAddr = baseAddr;
+ p_Fm->p_FmStateStruct->irq = p_FmParam->irq;
+ p_Fm->p_FmStateStruct->errIrq = p_FmParam->errIrq;
+ p_Fm->hcPortInitialized = FALSE;
+ p_Fm->independentMode = FALSE;
+
+ p_Fm->h_Spinlock = XX_InitSpinlock();
+ if (!p_Fm->h_Spinlock)
+ {
+ XX_Free(p_Fm->p_FmDriverParam);
+ XX_Free(p_Fm->p_FmStateStruct);
+ XX_Free(p_Fm);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("can't allocate spinlock!"));
+ return NULL;
+ }
+
+#if (DPAA_VERSION >= 11)
+ p_Fm->partVSPBase = p_FmParam->partVSPBase;
+ p_Fm->partNumOfVSPs = p_FmParam->partNumOfVSPs;
+ p_Fm->vspBaseAddr = p_FmParam->vspBaseAddr;
+#endif /* (DPAA_VERSION >= 11) */
+
+ fman_defconfig(p_Fm->p_FmDriverParam,
+ !!(p_Fm->guestId == NCSW_MASTER_ID));
+/* overide macros dependent parameters */
+#ifdef FM_PEDANTIC_DMA
+ p_Fm->p_FmDriverParam->pedantic_dma = TRUE;
+ p_Fm->p_FmDriverParam->dma_aid_override = TRUE;
+#endif /* FM_PEDANTIC_DMA */
+#ifndef FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+ p_Fm->p_FmDriverParam->qmi_deq_option_support = TRUE;
+#endif /* !FM_QMI_NO_DEQ_OPTIONS_SUPPORT */
+
+ p_Fm->p_FmStateStruct->ramsEccEnable = FALSE;
+ p_Fm->p_FmStateStruct->extraFifoPoolSize = 0;
+ p_Fm->p_FmStateStruct->exceptions = DEFAULT_exceptions;
+ p_Fm->resetOnInit = DEFAULT_resetOnInit;
+ p_Fm->fwVerify = DEFAULT_VerifyUcode;
+ p_Fm->firmware.size = p_FmParam->firmware.size;
+ if (p_Fm->firmware.size)
+ {
+ p_Fm->firmware.p_Code = (uint32_t *)XX_Malloc(p_Fm->firmware.size);
+ if (!p_Fm->firmware.p_Code)
+ {
+ XX_FreeSpinlock(p_Fm->h_Spinlock);
+ XX_Free(p_Fm->p_FmStateStruct);
+ XX_Free(p_Fm->p_FmDriverParam);
+ XX_Free(p_Fm);
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM firmware code"));
+ return NULL;
+ }
+ memcpy(p_Fm->firmware.p_Code, p_FmParam->firmware.p_Code ,p_Fm->firmware.size);
+ }
+
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ return p_Fm;
+
+ /* read revision */
+ /* Chip dependent, will be configured in Init */
+ fman_get_revision(p_Fm->p_FmFpmRegs,
+ &p_Fm->p_FmStateStruct->revInfo.majorRev,
+ &p_Fm->p_FmStateStruct->revInfo.minorRev);
+
+#ifdef FM_AID_MODE_NO_TNUM_SW005
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)
+ p_Fm->p_FmDriverParam->dma_aid_mode = e_FM_DMA_AID_OUT_PORT_ID;
+#endif /* FM_AID_MODE_NO_TNUM_SW005 */
+#ifndef FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev != 4)
+ p_Fm->p_FmDriverParam->qmi_def_tnums_thresh = QMI_DEF_TNUMS_THRESH;
+#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */
+#ifdef FM_NO_GUARANTEED_RESET_VALUES
+ if (1)//p_Fm->p_FmStateStruct->revInfo.majorRev < 6)
+ {
+ p_Fm->p_FmStateStruct->totalFifoSize = 0;
+ p_Fm->p_FmStateStruct->totalNumOfTasks = DEFAULT_totalNumOfTasks;
+#ifdef FM_HAS_TOTAL_DMAS
+ p_Fm->p_FmStateStruct->maxNumOfOpenDmas = BMI_MAX_NUM_OF_DMAS;
+#endif /* FM_HAS_TOTAL_DMAS */
+#if (DPAA_VERSION < 11)
+ p_Fm->p_FmDriverParam->dma_comm_qtsh_clr_emer = DEFAULT_dmaCommQLow;
+ p_Fm->p_FmDriverParam->dma_comm_qtsh_asrt_emer = DEFAULT_dmaCommQHigh;
+ p_Fm->p_FmDriverParam->dma_cam_num_of_entries = DEFAULT_dmaCamNumOfEntries;
+ p_Fm->p_FmDriverParam->dma_read_buf_tsh_clr_emer = DEFAULT_dmaReadIntBufLow;
+ p_Fm->p_FmDriverParam->dma_read_buf_tsh_asrt_emer = DEFAULT_dmaReadIntBufHigh;
+ p_Fm->p_FmDriverParam->dma_write_buf_tsh_clr_emer = DEFAULT_dmaWriteIntBufLow;
+ p_Fm->p_FmDriverParam->dma_write_buf_tsh_asrt_emer = DEFAULT_dmaWriteIntBufHigh;
+ p_Fm->p_FmDriverParam->dma_axi_dbg_num_of_beats = DEFAULT_axiDbgNumOfBeats;
+#endif /* (DPAA_VERSION < 11) */
+ }
+ else
+#endif /* FM_NO_GUARANTEED_RESET_VALUES */
+ {
+ struct fman_rg fman_rg;
+
+ fman_rg.bmi_rg = p_Fm->p_FmBmiRegs;
+ fman_rg.qmi_rg = p_Fm->p_FmQmiRegs;
+ fman_rg.fpm_rg = p_Fm->p_FmFpmRegs;
+ fman_rg.dma_rg = p_Fm->p_FmDmaRegs;
+
+#ifdef FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127
+ WRITE_UINT32(p_Fm->p_FmBmiRegs->fmbm_cfg2, 0x007B0000);
+#endif /* FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127 */
+ fman_regconfig(&fman_rg, p_Fm->p_FmDriverParam);
+
+ p_Fm->p_FmStateStruct->totalFifoSize = p_Fm->p_FmDriverParam->total_fifo_size;
+ p_Fm->p_FmStateStruct->totalNumOfTasks = p_Fm->p_FmDriverParam->total_num_of_tasks;
+ }
+#ifdef FM_NO_TNUM_AGING
+ p_Fm->p_FmDriverParam->tnum_aging_period = 0;
+#endif
+ p_Fm->tnumAgingPeriod = p_Fm->p_FmDriverParam->tnum_aging_period;
+
+ return p_Fm;
+}
+
+/**************************************************************************//**
+ @Function FM_Init
+
+ @Description Initializes the FM module
+
+ @Param[in] h_Fm - FM module descriptor
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_Init(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ struct fman_cfg *p_FmDriverParam = NULL;
+ t_Error err = E_OK;
+ int i;
+ t_FmRevisionInfo revInfo;
+ struct fman_rg fman_rg;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+
+ fman_rg.bmi_rg = p_Fm->p_FmBmiRegs;
+ fman_rg.qmi_rg = p_Fm->p_FmQmiRegs;
+ fman_rg.fpm_rg = p_Fm->p_FmFpmRegs;
+ fman_rg.dma_rg = p_Fm->p_FmDmaRegs;
+
+ p_Fm->p_FmStateStruct->count1MicroBit = FM_TIMESTAMP_1_USEC_BIT;
+ p_Fm->p_FmDriverParam->num_of_fman_ctrl_evnt_regs = FM_NUM_OF_FMAN_CTRL_EVENT_REGS;
+
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ return InitGuestMode(p_Fm);
+
+#ifdef FM_NO_GUARANTEED_RESET_VALUES
+ if (1)//p_Fm->p_FmStateStruct->revInfo.majorRev < 6)
+ /* if user didn't configured totalFifoSize - (totalFifoSize=0) we configure default
+ * according to chip. otherwise, we use user's configuration.
+ */
+ if (p_Fm->p_FmStateStruct->totalFifoSize == 0)
+ p_Fm->p_FmStateStruct->totalFifoSize = DEFAULT_totalFifoSize(p_Fm->p_FmStateStruct->revInfo.majorRev,
+ p_Fm->p_FmStateStruct->revInfo.minorRev);
+#endif /* FM_NO_GUARANTEED_RESET_VALUES */
+
+ CHECK_INIT_PARAMETERS(p_Fm, CheckFmParameters);
+
+ p_FmDriverParam = p_Fm->p_FmDriverParam;
+
+ FM_GetRevision(p_Fm, &revInfo);
+
+ /* clear revision-dependent non existing exception */
+#ifdef FM_NO_DISPATCH_RAM_ECC
+ if ((revInfo.majorRev != 4) &&
+ (revInfo.majorRev < 6))
+ p_Fm->p_FmStateStruct->exceptions &= ~FM_EX_BMI_DISPATCH_RAM_ECC;
+#endif /* FM_NO_DISPATCH_RAM_ECC */
+
+#ifdef FM_QMI_NO_ECC_EXCEPTIONS
+ if (revInfo.majorRev == 4)
+ p_Fm->p_FmStateStruct->exceptions &= ~(FM_EX_QMI_SINGLE_ECC | FM_EX_QMI_DOUBLE_ECC);
+#endif /* FM_QMI_NO_ECC_EXCEPTIONS */
+
+#ifdef FM_QMI_NO_SINGLE_ECC_EXCEPTION
+ if (revInfo.majorRev >= 6)
+ p_Fm->p_FmStateStruct->exceptions &= ~FM_EX_QMI_SINGLE_ECC;
+#endif /* FM_QMI_NO_SINGLE_ECC_EXCEPTION */
+
+ FmMuramClear(p_Fm->h_FmMuram);
+
+ /* clear CPG */
+ IOMemSet32(UINT_TO_PTR(p_Fm->baseAddr + FM_MM_CGP), 0, FM_PORT_NUM_OF_CONGESTION_GRPS);
+
+ /* add to the default exceptions the user's definitions */
+ p_Fm->p_FmStateStruct->exceptions |= p_Fm->userSetExceptions;
+
+#ifdef FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173
+ if (p_Fm->resetOnInit)
+ {
+ if ((err = FwNotResetErratumBugzilla6173WA(p_Fm)) != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+ else
+ {
+#endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */
+
+ /* Reset the FM if required. */
+ if (p_Fm->resetOnInit)
+ {
+ u32 svr = mfspr(SPRN_SVR);
+
+ if (((SVR_SOC_VER(svr) == SVR_T4240 && SVR_REV(svr) > 0x10)) ||
+ ((SVR_SOC_VER(svr) == SVR_T4160 && SVR_REV(svr) > 0x10)) ||
+ (SVR_SOC_VER(svr) == SVR_T2080) ||
+ (SVR_SOC_VER(svr) == SVR_T2081)) {
+ DBG(WARNING, ("Hack: No FM reset!\n"));
+ } else {
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rstc, FPM_RSTC_FM_RESET);
+ CORE_MemoryBarrier();
+ XX_UDelay(100);
+ }
+
+ if (fman_is_qmi_halt_not_busy_state(p_Fm->p_FmQmiRegs))
+ {
+ fman_resume(p_Fm->p_FmFpmRegs);
+ XX_UDelay(100);
+ }
+ }
+
+ /*************************************/
+ /* Load FMan-Controller code to IRAM */
+ /*************************************/
+ if (ClearIRam(p_Fm) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+ if (p_Fm->firmware.p_Code &&
+ (LoadFmanCtrlCode(p_Fm) != E_OK))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+#ifdef FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173
+ }
+#endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */
+
+#ifdef FM_CAPWAP_SUPPORT
+ /* save first 256 byte in MURAM */
+ p_Fm->resAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_Fm->h_FmMuram, 256, 0));
+ if (!p_Fm->resAddr)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for reserved Area failed"));
+
+ WRITE_BLOCK(UINT_TO_PTR(p_Fm->resAddr), 0, 256);
+#endif /* FM_CAPWAP_SUPPORT */
+
+#if (DPAA_VERSION >= 11)
+ p_Fm->partVSPBase = AllocVSPsForPartition(h_Fm, p_Fm->partVSPBase, p_Fm->partNumOfVSPs, p_Fm->guestId);
+ if (p_Fm->partVSPBase == ILLEGAL_BASE)
+ DBG(WARNING, ("partition VSPs allocation is FAILED"));
+#endif /* (DPAA_VERSION >= 11) */
+
+ /* General FM driver initialization */
+ p_Fm->fmMuramPhysBaseAddr =
+ (uint64_t)(XX_VirtToPhys(UINT_TO_PTR(p_Fm->baseAddr + FM_MM_MURAM)));
+
+ for (i=0;i<e_FM_EV_DUMMY_LAST;i++)
+ p_Fm->intrMng[i].f_Isr = UnimplementedIsr;
+ for (i=0;i<FM_NUM_OF_FMAN_CTRL_EVENT_REGS;i++)
+ p_Fm->fmanCtrlIntr[i].f_Isr = UnimplementedFmanCtrlIsr;
+
+ p_FmDriverParam->exceptions = p_Fm->p_FmStateStruct->exceptions;
+
+ /**********************/
+ /* Init DMA Registers */
+ /**********************/
+ err = InitFmDma(p_Fm);
+ if (err != E_OK)
+ {
+ FreeInitResources(p_Fm);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ /**********************/
+ /* Init FPM Registers */
+ /**********************/
+ err = InitFmFpm(p_Fm);
+ if (err != E_OK)
+ {
+ FreeInitResources(p_Fm);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ /* define common resources */
+ /* allocate MURAM for FIFO according to total size */
+ p_Fm->fifoBaseAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_Fm->h_FmMuram,
+ p_Fm->p_FmStateStruct->totalFifoSize,
+ BMI_FIFO_ALIGN));
+ if (!p_Fm->fifoBaseAddr)
+ {
+ FreeInitResources(p_Fm);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for BMI FIFO failed"));
+ }
+
+ p_FmDriverParam->fifo_base_addr = (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Fm->fifoBaseAddr)) - p_Fm->fmMuramPhysBaseAddr);
+ p_FmDriverParam->total_fifo_size = p_Fm->p_FmStateStruct->totalFifoSize;
+ p_FmDriverParam->total_num_of_tasks = p_Fm->p_FmStateStruct->totalNumOfTasks;
+ p_FmDriverParam->clk_freq = p_Fm->p_FmStateStruct->fmClkFreq;
+
+ /**********************/
+ /* Init BMI Registers */
+ /**********************/
+ err = InitFmBmi(p_Fm);
+ if (err != E_OK)
+ {
+ FreeInitResources(p_Fm);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ /**********************/
+ /* Init QMI Registers */
+ /**********************/
+ err = InitFmQmi(p_Fm);
+ if (err != E_OK)
+ {
+ FreeInitResources(p_Fm);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ /* build the FM master partition IPC address */
+ if (Sprint (p_Fm->fmModuleName, "FM_%d_%d",p_Fm->p_FmStateStruct->fmId, NCSW_MASTER_ID) != 6)
+ {
+ FreeInitResources(p_Fm);
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed"));
+ }
+
+ err = XX_IpcRegisterMsgHandler(p_Fm->fmModuleName, FmHandleIpcMsgCB, p_Fm, FM_IPC_MAX_REPLY_SIZE);
+ if (err)
+ {
+ FreeInitResources(p_Fm);
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+ }
+
+ /* Register the FM interrupts handlers */
+ if (p_Fm->p_FmStateStruct->irq != NO_IRQ)
+ {
+ XX_SetIntr(p_Fm->p_FmStateStruct->irq, FM_EventIsr, p_Fm);
+ XX_EnableIntr(p_Fm->p_FmStateStruct->irq);
+ }
+
+ if (p_Fm->p_FmStateStruct->errIrq != NO_IRQ)
+ {
+ XX_SetIntr(p_Fm->p_FmStateStruct->errIrq, (void (*) (t_Handle))FM_ErrorIsr, p_Fm);
+ XX_EnableIntr(p_Fm->p_FmStateStruct->errIrq);
+ }
+
+ err = (t_Error)fman_enable(&fman_rg , p_FmDriverParam);
+ if (err != E_OK)
+ return err; /* FIXME */
+
+ EnableTimeStamp(p_Fm);
+
+ if (p_Fm->firmware.p_Code)
+ {
+ XX_Free(p_Fm->firmware.p_Code);
+ p_Fm->firmware.p_Code = NULL;
+ }
+
+ XX_Free(p_Fm->p_FmDriverParam);
+ p_Fm->p_FmDriverParam = NULL;
+
+ return E_OK;
+}
+
+/**************************************************************************//**
+ @Function FM_Free
+
+ @Description Frees all resources that were assigned to FM module.
+
+ Calling this routine invalidates the descriptor.
+
+ @Param[in] h_Fm - FM module descriptor
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_Free(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ struct fman_rg fman_rg;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+
+ fman_rg.bmi_rg = p_Fm->p_FmBmiRegs;
+ fman_rg.qmi_rg = p_Fm->p_FmQmiRegs;
+ fman_rg.fpm_rg = p_Fm->p_FmFpmRegs;
+ fman_rg.dma_rg = p_Fm->p_FmDmaRegs;
+
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ {
+#if (DPAA_VERSION >= 11)
+ FreeVSPsForPartition(h_Fm, p_Fm->partVSPBase, p_Fm->partNumOfVSPs, p_Fm->guestId);
+
+ if (p_Fm->p_FmSp)
+ {
+ XX_Free(p_Fm->p_FmSp);
+ p_Fm->p_FmSp = NULL;
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ if (p_Fm->fmModuleName)
+ XX_IpcUnregisterMsgHandler(p_Fm->fmModuleName);
+
+ if (!p_Fm->recoveryMode)
+ XX_Free(p_Fm->p_FmStateStruct);
+
+ XX_Free(p_Fm);
+
+ return E_OK;
+ }
+
+ fman_free_resources(&fman_rg);
+
+ if ((p_Fm->guestId == NCSW_MASTER_ID) && (p_Fm->fmModuleName[0] != 0))
+ XX_IpcUnregisterMsgHandler(p_Fm->fmModuleName);
+
+ if (p_Fm->p_FmStateStruct)
+ {
+ if (p_Fm->p_FmStateStruct->irq != NO_IRQ)
+ {
+ XX_DisableIntr(p_Fm->p_FmStateStruct->irq);
+ XX_FreeIntr(p_Fm->p_FmStateStruct->irq);
+ }
+ if (p_Fm->p_FmStateStruct->errIrq != NO_IRQ)
+ {
+ XX_DisableIntr(p_Fm->p_FmStateStruct->errIrq);
+ XX_FreeIntr(p_Fm->p_FmStateStruct->errIrq);
+ }
+ }
+
+#if (DPAA_VERSION >= 11)
+ FreeVSPsForPartition(h_Fm, p_Fm->partVSPBase, p_Fm->partNumOfVSPs, p_Fm->guestId);
+
+ if (p_Fm->p_FmSp)
+ {
+ XX_Free(p_Fm->p_FmSp);
+ p_Fm->p_FmSp = NULL;
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ if (p_Fm->h_Spinlock)
+ XX_FreeSpinlock(p_Fm->h_Spinlock);
+
+ if (p_Fm->p_FmDriverParam)
+ {
+ if (p_Fm->firmware.p_Code)
+ XX_Free(p_Fm->firmware.p_Code);
+ XX_Free(p_Fm->p_FmDriverParam);
+ p_Fm->p_FmDriverParam = NULL;
+ }
+
+ FreeInitResources(p_Fm);
+
+ if (!p_Fm->recoveryMode && p_Fm->p_FmStateStruct)
+ XX_Free(p_Fm->p_FmStateStruct);
+
+ XX_Free(p_Fm);
+
+ return E_OK;
+}
+
+/*************************************************/
+/* API Advanced Init unit functions */
+/*************************************************/
+
+t_Error FM_ConfigResetOnInit(t_Handle h_Fm, bool enable)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->resetOnInit = enable;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigTotalFifoSize(t_Handle h_Fm, uint32_t totalFifoSize)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmStateStruct->totalFifoSize = totalFifoSize;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaCacheOverride(t_Handle h_Fm, e_FmDmaCacheOverride cacheOverride)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ enum fman_dma_cache_override fsl_cache_override;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ FMAN_CACHE_OVERRIDE_TRANS(fsl_cache_override, cacheOverride)
+ p_Fm->p_FmDriverParam->dma_cache_override = fsl_cache_override;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaAidOverride(t_Handle h_Fm, bool aidOverride)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->dma_aid_override = aidOverride;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaAidMode(t_Handle h_Fm, e_FmDmaAidMode aidMode)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ enum fman_dma_aid_mode fsl_aid_mode;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ FMAN_AID_MODE_TRANS(fsl_aid_mode, aidMode);
+ p_Fm->p_FmDriverParam->dma_aid_mode = fsl_aid_mode;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaAxiDbgNumOfBeats(t_Handle h_Fm, uint8_t axiDbgNumOfBeats)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+#if (DPAA_VERSION >= 11)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!"));
+#endif /* (DPAA_VERSION >= 11) */
+ p_Fm->p_FmDriverParam->dma_axi_dbg_num_of_beats = axiDbgNumOfBeats;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaCamNumOfEntries(t_Handle h_Fm, uint8_t numOfEntries)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->dma_cam_num_of_entries = numOfEntries;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaDbgCounter(t_Handle h_Fm, e_FmDmaDbgCntMode fmDmaDbgCntMode)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ enum fman_dma_dbg_cnt_mode fsl_dma_dbg_cnt;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ FMAN_DMA_DBG_CNT_TRANS(fsl_dma_dbg_cnt, fmDmaDbgCntMode);
+ p_Fm->p_FmDriverParam->dma_dbg_cnt_mode = fsl_dma_dbg_cnt;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaStopOnBusErr(t_Handle h_Fm, bool stop)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->dma_stop_on_bus_error = stop;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaEmergency(t_Handle h_Fm, t_FmDmaEmergency *p_Emergency)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ enum fman_dma_emergency_level fsl_dma_emer;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ FMAN_DMA_EMER_TRANS(fsl_dma_emer, p_Emergency->emergencyLevel);
+ p_Fm->p_FmDriverParam->dma_en_emergency = TRUE;
+ p_Fm->p_FmDriverParam->dma_emergency_bus_select = (uint32_t)p_Emergency->emergencyBusSelect;
+ p_Fm->p_FmDriverParam->dma_emergency_level = fsl_dma_emer;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaEmergencySmoother(t_Handle h_Fm, uint32_t emergencyCnt)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->dma_en_emergency_smoother = TRUE;
+ p_Fm->p_FmDriverParam->dma_emergency_switch_counter = emergencyCnt;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaErr(t_Handle h_Fm, e_FmDmaErr dmaErr)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ enum fman_dma_err fsl_dma_err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ FMAN_DMA_ERR_TRANS(fsl_dma_err, dmaErr);
+ p_Fm->p_FmDriverParam->dma_err = fsl_dma_err;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigCatastrophicErr(t_Handle h_Fm, e_FmCatastrophicErr catastrophicErr)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ enum fman_catastrophic_err fsl_catastrophic_err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ FMAN_CATASTROPHIC_ERR_TRANS(fsl_catastrophic_err, catastrophicErr);
+ p_Fm->p_FmDriverParam->catastrophic_err = fsl_catastrophic_err;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigEnableMuramTestMode(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!"));
+
+ p_Fm->p_FmDriverParam->en_muram_test_mode = TRUE;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigEnableIramTestMode(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE );
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!"));
+
+ p_Fm->p_FmDriverParam->en_iram_test_mode = TRUE;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigHaltOnExternalActivation(t_Handle h_Fm, bool enable)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->halt_on_external_activ = enable;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigHaltOnUnrecoverableEccError(t_Handle h_Fm, bool enable)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!"));
+
+ p_Fm->p_FmDriverParam->halt_on_unrecov_ecc_err = enable;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigException(t_Handle h_Fm, e_FmExceptions exception, bool enable)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ uint32_t bitMask = 0;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ GET_EXCEPTION_FLAG(bitMask, exception);
+ if (bitMask)
+ {
+ if (enable)
+ p_Fm->userSetExceptions |= bitMask;
+ else
+ p_Fm->p_FmStateStruct->exceptions &= ~bitMask;
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
+
+ return E_OK;
+}
+
+t_Error FM_ConfigExternalEccRamsEnable(t_Handle h_Fm, bool enable)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->external_ecc_rams_enable = enable;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigTnumAgingPeriod(t_Handle h_Fm, uint16_t tnumAgingPeriod)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->tnum_aging_period = tnumAgingPeriod;
+ p_Fm->tnumAgingPeriod = p_Fm->p_FmDriverParam->tnum_aging_period;
+
+ return E_OK;
+}
+
+/****************************************************/
+/* Hidden-DEBUG Only API */
+/****************************************************/
+
+t_Error FM_ConfigThresholds(t_Handle h_Fm, t_FmThresholds *p_FmThresholds)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->disp_limit_tsh = p_FmThresholds->dispLimit;
+ p_Fm->p_FmDriverParam->prs_disp_tsh = p_FmThresholds->prsDispTh;
+ p_Fm->p_FmDriverParam->plcr_disp_tsh = p_FmThresholds->plcrDispTh;
+ p_Fm->p_FmDriverParam->kg_disp_tsh = p_FmThresholds->kgDispTh;
+ p_Fm->p_FmDriverParam->bmi_disp_tsh = p_FmThresholds->bmiDispTh;
+ p_Fm->p_FmDriverParam->qmi_enq_disp_tsh = p_FmThresholds->qmiEnqDispTh;
+ p_Fm->p_FmDriverParam->qmi_deq_disp_tsh = p_FmThresholds->qmiDeqDispTh;
+ p_Fm->p_FmDriverParam->fm_ctl1_disp_tsh = p_FmThresholds->fmCtl1DispTh;
+ p_Fm->p_FmDriverParam->fm_ctl2_disp_tsh = p_FmThresholds->fmCtl2DispTh;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaSosEmergencyThreshold(t_Handle h_Fm, uint32_t dmaSosEmergency)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->dma_sos_emergency = dmaSosEmergency;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaWriteBufThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds)
+
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+#if (DPAA_VERSION >= 11)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!"));
+#endif
+ p_Fm->p_FmDriverParam->dma_write_buf_tsh_asrt_emer = p_FmDmaThresholds->assertEmergency;
+ p_Fm->p_FmDriverParam->dma_write_buf_tsh_clr_emer = p_FmDmaThresholds->clearEmergency;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaCommQThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->dma_comm_qtsh_asrt_emer = p_FmDmaThresholds->assertEmergency;
+ p_Fm->p_FmDriverParam->dma_comm_qtsh_clr_emer = p_FmDmaThresholds->clearEmergency;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaReadBufThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+#if (DPAA_VERSION >= 11)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!"));
+#endif
+ p_Fm->p_FmDriverParam->dma_read_buf_tsh_clr_emer = p_FmDmaThresholds->clearEmergency;
+ p_Fm->p_FmDriverParam->dma_read_buf_tsh_asrt_emer = p_FmDmaThresholds->assertEmergency;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigDmaWatchdog(t_Handle h_Fm, uint32_t watchdogValue)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ p_Fm->p_FmDriverParam->dma_watchdog = watchdogValue;
+
+ return E_OK;
+}
+
+t_Error FM_ConfigEnableCounters(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+UNUSED(p_Fm);
+
+ return E_OK;
+}
+
+/****************************************************/
+/* API Run-time Control uint functions */
+/****************************************************/
+void FM_EventIsr(t_Handle h_Fm)
+{
+#define FM_M_CALL_1G_MAC_ISR(_id) \
+ { \
+ if (p_Fm->guestId != p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].guestId) \
+ SendIpcIsr(p_Fm, (e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id), pending); \
+ else \
+ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].h_SrcHandle);\
+ }
+#define FM_M_CALL_10G_MAC_ISR(_id) \
+ { \
+ if (p_Fm->guestId != p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].guestId) \
+ SendIpcIsr(p_Fm, (e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id), pending); \
+ else \
+ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].h_SrcHandle);\
+ }
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ uint32_t pending, event;
+ struct fman_fpm_regs *fpm_rg;
+
+ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ fpm_rg = p_Fm->p_FmFpmRegs;
+
+ /* normal interrupts */
+ pending = fman_get_normal_pending(fpm_rg);
+ if (!pending)
+ return;
+
+ if (pending & INTR_EN_QMI)
+ QmiEvent(p_Fm);
+ if (pending & INTR_EN_PRS)
+ p_Fm->intrMng[e_FM_EV_PRS].f_Isr(p_Fm->intrMng[e_FM_EV_PRS].h_SrcHandle);
+ if (pending & INTR_EN_PLCR)
+ p_Fm->intrMng[e_FM_EV_PLCR].f_Isr(p_Fm->intrMng[e_FM_EV_PLCR].h_SrcHandle);
+ if (pending & INTR_EN_TMR)
+ p_Fm->intrMng[e_FM_EV_TMR].f_Isr(p_Fm->intrMng[e_FM_EV_TMR].h_SrcHandle);
+
+ /* MAC events may belong to different partitions */
+ if (pending & INTR_EN_1G_MAC0)
+ FM_M_CALL_1G_MAC_ISR(0);
+ if (pending & INTR_EN_1G_MAC1)
+ FM_M_CALL_1G_MAC_ISR(1);
+ if (pending & INTR_EN_1G_MAC2)
+ FM_M_CALL_1G_MAC_ISR(2);
+ if (pending & INTR_EN_1G_MAC3)
+ FM_M_CALL_1G_MAC_ISR(3);
+ if (pending & INTR_EN_1G_MAC4)
+ FM_M_CALL_1G_MAC_ISR(4);
+ if (pending & INTR_EN_1G_MAC5)
+ FM_M_CALL_1G_MAC_ISR(5);
+ if (pending & INTR_EN_1G_MAC6)
+ FM_M_CALL_1G_MAC_ISR(6);
+ if (pending & INTR_EN_1G_MAC7)
+ FM_M_CALL_1G_MAC_ISR(7);
+ if (pending & INTR_EN_10G_MAC0)
+ FM_M_CALL_10G_MAC_ISR(0);
+ if (pending & INTR_EN_10G_MAC1)
+ FM_M_CALL_10G_MAC_ISR(1);
+
+ /* IM port events may belong to different partitions */
+ if (pending & INTR_EN_REV0)
+ {
+ event = fman_get_controller_event(fpm_rg, 0);
+ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_FMAN_CTRL_0].guestId)
+ /*TODO IPC ISR For Fman Ctrl */
+ ASSERT_COND(0);
+ /* SendIpcIsr(p_Fm, e_FM_EV_FMAN_CTRL_0, pending); */
+ else
+ p_Fm->fmanCtrlIntr[0].f_Isr(p_Fm->fmanCtrlIntr[0].h_SrcHandle, event);
+
+ }
+ if (pending & INTR_EN_REV1)
+ {
+ event = fman_get_controller_event(fpm_rg, 1);
+ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_FMAN_CTRL_1].guestId)
+ /*TODO IPC ISR For Fman Ctrl */
+ ASSERT_COND(0);
+ /* SendIpcIsr(p_Fm, e_FM_EV_FMAN_CTRL_1, pending); */
+ else
+ p_Fm->fmanCtrlIntr[1].f_Isr(p_Fm->fmanCtrlIntr[1].h_SrcHandle, event);
+ }
+ if (pending & INTR_EN_REV2)
+ {
+ event = fman_get_controller_event(fpm_rg, 2);
+ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_FMAN_CTRL_2].guestId)
+ /*TODO IPC ISR For Fman Ctrl */
+ ASSERT_COND(0);
+ /* SendIpcIsr(p_Fm, e_FM_EV_FMAN_CTRL_2, pending); */
+ else
+ p_Fm->fmanCtrlIntr[2].f_Isr(p_Fm->fmanCtrlIntr[2].h_SrcHandle, event);
+ }
+ if (pending & INTR_EN_REV3)
+ {
+ event = fman_get_controller_event(fpm_rg, 3);
+ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_FMAN_CTRL_3].guestId)
+ /*TODO IPC ISR For Fman Ctrl */
+ ASSERT_COND(0);
+ /* SendIpcIsr(p_Fm, e_FM_EV_FMAN_CTRL_2, pendin3); */
+ else
+ p_Fm->fmanCtrlIntr[3].f_Isr(p_Fm->fmanCtrlIntr[3].h_SrcHandle, event);
+ }
+#ifdef FM_MACSEC_SUPPORT
+ if (pending & INTR_EN_MACSEC_MAC0)
+ {
+ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_MACSEC_MAC0].guestId)
+ SendIpcIsr(p_Fm, e_FM_EV_MACSEC_MAC0, pending);
+ else
+ p_Fm->intrMng[e_FM_EV_MACSEC_MAC0].f_Isr(p_Fm->intrMng[e_FM_EV_MACSEC_MAC0].h_SrcHandle);
+ }
+#endif /* FM_MACSEC_SUPPORT */
+}
+
+t_Error FM_ErrorIsr(t_Handle h_Fm)
+{
+#define FM_M_CALL_1G_MAC_ERR_ISR(_id) \
+ { \
+ if (p_Fm->guestId != p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].guestId) \
+ SendIpcIsr(p_Fm, (e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id), pending); \
+ else \
+ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].h_SrcHandle);\
+ }
+#define FM_M_CALL_10G_MAC_ERR_ISR(_id) \
+ { \
+ if (p_Fm->guestId != p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].guestId) \
+ SendIpcIsr(p_Fm, (e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id), pending); \
+ else \
+ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].h_SrcHandle);\
+ }
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ uint32_t pending;
+ struct fman_fpm_regs *fpm_rg;
+
+ SANITY_CHECK_RETURN_ERROR(h_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ fpm_rg = p_Fm->p_FmFpmRegs;
+
+ /* error interrupts */
+ pending = fman_get_fpm_error_interrupts(fpm_rg);
+ if (!pending)
+ return ERROR_CODE(E_EMPTY);
+
+ if (pending & ERR_INTR_EN_BMI)
+ BmiErrEvent(p_Fm);
+ if (pending & ERR_INTR_EN_QMI)
+ QmiErrEvent(p_Fm);
+ if (pending & ERR_INTR_EN_FPM)
+ FpmErrEvent(p_Fm);
+ if (pending & ERR_INTR_EN_DMA)
+ DmaErrEvent(p_Fm);
+ if (pending & ERR_INTR_EN_IRAM)
+ IramErrIntr(p_Fm);
+ if (pending & ERR_INTR_EN_MURAM)
+ MuramErrIntr(p_Fm);
+ if (pending & ERR_INTR_EN_PRS)
+ p_Fm->intrMng[e_FM_EV_ERR_PRS].f_Isr(p_Fm->intrMng[e_FM_EV_ERR_PRS].h_SrcHandle);
+ if (pending & ERR_INTR_EN_PLCR)
+ p_Fm->intrMng[e_FM_EV_ERR_PLCR].f_Isr(p_Fm->intrMng[e_FM_EV_ERR_PLCR].h_SrcHandle);
+ if (pending & ERR_INTR_EN_KG)
+ p_Fm->intrMng[e_FM_EV_ERR_KG].f_Isr(p_Fm->intrMng[e_FM_EV_ERR_KG].h_SrcHandle);
+
+ /* MAC events may belong to different partitions */
+ if (pending & ERR_INTR_EN_1G_MAC0)
+ FM_M_CALL_1G_MAC_ERR_ISR(0);
+ if (pending & ERR_INTR_EN_1G_MAC1)
+ FM_M_CALL_1G_MAC_ERR_ISR(1);
+ if (pending & ERR_INTR_EN_1G_MAC2)
+ FM_M_CALL_1G_MAC_ERR_ISR(2);
+ if (pending & ERR_INTR_EN_1G_MAC3)
+ FM_M_CALL_1G_MAC_ERR_ISR(3);
+ if (pending & ERR_INTR_EN_1G_MAC4)
+ FM_M_CALL_1G_MAC_ERR_ISR(4);
+ if (pending & ERR_INTR_EN_1G_MAC5)
+ FM_M_CALL_1G_MAC_ERR_ISR(5);
+ if (pending & ERR_INTR_EN_1G_MAC6)
+ FM_M_CALL_1G_MAC_ERR_ISR(6);
+ if (pending & ERR_INTR_EN_1G_MAC7)
+ FM_M_CALL_1G_MAC_ERR_ISR(7);
+ if (pending & ERR_INTR_EN_10G_MAC0)
+ FM_M_CALL_10G_MAC_ERR_ISR(0);
+ if (pending & ERR_INTR_EN_10G_MAC1)
+ FM_M_CALL_10G_MAC_ERR_ISR(1);
+
+#ifdef FM_MACSEC_SUPPORT
+ if (pending & ERR_INTR_EN_MACSEC_MAC0)
+ {
+ if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_ERR_MACSEC_MAC0].guestId)
+ SendIpcIsr(p_Fm, e_FM_EV_ERR_MACSEC_MAC0, pending);
+ else
+ p_Fm->intrMng[e_FM_EV_ERR_MACSEC_MAC0].f_Isr(p_Fm->intrMng[e_FM_EV_ERR_MACSEC_MAC0].h_SrcHandle);
+ }
+#endif /* FM_MACSEC_SUPPORT */
+
+ return E_OK;
+}
+
+t_Error FM_SetPortsBandwidth(t_Handle h_Fm, t_FmPortsBandwidthParams *p_PortsBandwidth)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ int i;
+ uint8_t sum;
+ uint8_t hardwarePortId;
+ uint8_t weights[64];
+ uint8_t weight, maxPercent = 0;
+ struct fman_bmi_regs *bmi_rg;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ bmi_rg = p_Fm->p_FmBmiRegs;
+
+ memset(weights, 0, (sizeof(uint8_t) * 64));
+ /* check that all ports add up to 100% */
+ sum = 0;
+ for (i=0;i<p_PortsBandwidth->numOfPorts;i++)
+ sum +=p_PortsBandwidth->portsBandwidths[i].bandwidth;
+ if (sum != 100)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Sum of ports bandwidth differ from 100%"));
+
+ /* find highest percent */
+ for (i=0;i<p_PortsBandwidth->numOfPorts;i++)
+ {
+ if (p_PortsBandwidth->portsBandwidths[i].bandwidth > maxPercent)
+ maxPercent = p_PortsBandwidth->portsBandwidths[i].bandwidth;
+ }
+
+ /* calculate weight for each port */
+ for (i=0;i<p_PortsBandwidth->numOfPorts;i++)
+ {
+ weight = (uint8_t)((p_PortsBandwidth->portsBandwidths[i].bandwidth * PORT_MAX_WEIGHT )/maxPercent);
+ /* we want even division between 1-to-PORT_MAX_WEIGHT. so if exect division
+ is not reached, we round up so that:
+ 0 until maxPercent/PORT_MAX_WEIGHT get "1"
+ maxPercent/PORT_MAX_WEIGHT+1 until (maxPercent/PORT_MAX_WEIGHT)*2 get "2"
+ ...
+ maxPercent - maxPercent/PORT_MAX_WEIGHT until maxPercent get "PORT_MAX_WEIGHT: */
+ if ((uint8_t)((p_PortsBandwidth->portsBandwidths[i].bandwidth * PORT_MAX_WEIGHT ) % maxPercent))
+ weight++;
+
+ /* find the location of this port within the register */
+ SW_PORT_ID_TO_HW_PORT_ID(hardwarePortId,
+ p_PortsBandwidth->portsBandwidths[i].type,
+ p_PortsBandwidth->portsBandwidths[i].relativePortId);
+
+ ASSERT_COND(IN_RANGE(1, hardwarePortId, 63));
+ weights[hardwarePortId] = weight;
+ }
+
+ fman_set_ports_bandwidth(bmi_rg, weights);
+
+ return E_OK;
+}
+
+t_Error FM_EnableRamsEcc(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ struct fman_fpm_regs *fpm_rg;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+
+ fpm_rg = p_Fm->p_FmFpmRegs;
+
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ {
+ t_FmIpcMsg msg;
+ t_Error err;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msgId = FM_ENABLE_RAM_ECC;
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ return E_OK;
+ }
+
+ if (!p_Fm->p_FmStateStruct->internalCall)
+ p_Fm->p_FmStateStruct->explicitEnable = TRUE;
+ p_Fm->p_FmStateStruct->internalCall = FALSE;
+
+ if (p_Fm->p_FmStateStruct->ramsEccEnable)
+ return E_OK;
+ else
+ {
+ fman_enable_rams_ecc(fpm_rg);
+ p_Fm->p_FmStateStruct->ramsEccEnable = TRUE;
+ }
+
+ return E_OK;
+}
+
+t_Error FM_DisableRamsEcc(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ bool explicitDisable = FALSE;
+ struct fman_fpm_regs *fpm_rg;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_HANDLE);
+
+ fpm_rg = p_Fm->p_FmFpmRegs;
+
+ if (p_Fm->guestId != NCSW_MASTER_ID)
+ {
+ t_Error err;
+ t_FmIpcMsg msg;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msgId = FM_DISABLE_RAM_ECC;
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ NULL,
+ NULL,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ return E_OK;
+ }
+
+ if (!p_Fm->p_FmStateStruct->internalCall)
+ explicitDisable = TRUE;
+ p_Fm->p_FmStateStruct->internalCall = FALSE;
+
+ /* if rams are already disabled, or if rams were explicitly enabled and are
+ currently called indirectly (not explicitly), ignore this call. */
+ if (!p_Fm->p_FmStateStruct->ramsEccEnable ||
+ (p_Fm->p_FmStateStruct->explicitEnable && !explicitDisable))
+ return E_OK;
+ else
+ {
+ if (p_Fm->p_FmStateStruct->explicitEnable)
+ /* This is the case were both explicit are TRUE.
+ Turn off this flag for cases were following ramsEnable
+ routines are called */
+ p_Fm->p_FmStateStruct->explicitEnable = FALSE;
+
+ fman_enable_rams_ecc(fpm_rg);
+ p_Fm->p_FmStateStruct->ramsEccEnable = FALSE;
+ }
+
+ return E_OK;
+}
+
+t_Error FM_SetException(t_Handle h_Fm, e_FmExceptions exception, bool enable)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ uint32_t bitMask = 0;
+ enum fman_exceptions fslException;
+ struct fman_rg fman_rg;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+
+ fman_rg.bmi_rg = p_Fm->p_FmBmiRegs;
+ fman_rg.qmi_rg = p_Fm->p_FmQmiRegs;
+ fman_rg.fpm_rg = p_Fm->p_FmFpmRegs;
+ fman_rg.dma_rg = p_Fm->p_FmDmaRegs;
+
+ GET_EXCEPTION_FLAG(bitMask, exception);
+ if (bitMask)
+ {
+ if (enable)
+ p_Fm->p_FmStateStruct->exceptions |= bitMask;
+ else
+ p_Fm->p_FmStateStruct->exceptions &= ~bitMask;
+
+ FMAN_EXCEPTION_TRANS(fslException, exception);
+
+
+
+ return (t_Error)fman_set_exception(&fman_rg,
+ fslException,
+ enable);
+ }
+ else
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
+
+ return E_OK;
+}
+
+t_Error FM_GetRevision(t_Handle h_Fm, t_FmRevisionInfo *p_FmRevisionInfo)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+
+ p_FmRevisionInfo->majorRev = p_Fm->p_FmStateStruct->revInfo.majorRev;
+ p_FmRevisionInfo->minorRev = p_Fm->p_FmStateStruct->revInfo.minorRev;
+
+ return E_OK;
+}
+
+t_Error FM_GetFmanCtrlCodeRevision(t_Handle h_Fm, t_FmCtrlCodeRevisionInfo *p_RevisionInfo)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ t_FMIramRegs *p_Iram;
+ uint32_t revInfo;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_RevisionInfo, E_NULL_POINTER);
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_Error err;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength;
+ t_FmIpcFmanCtrlCodeRevisionInfo ipcRevInfo;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_GET_FMAN_CTRL_CODE_REV;
+ replyLength = sizeof(uint32_t) + sizeof(t_FmCtrlCodeRevisionInfo);
+ if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ if (replyLength != (sizeof(uint32_t) + sizeof(t_FmCtrlCodeRevisionInfo)))
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ memcpy((uint8_t*)&ipcRevInfo, reply.replyBody, sizeof(t_FmCtrlCodeRevisionInfo));
+ p_RevisionInfo->packageRev = ipcRevInfo.packageRev;
+ p_RevisionInfo->majorRev = ipcRevInfo.majorRev;
+ p_RevisionInfo->minorRev = ipcRevInfo.minorRev;
+ return (t_Error)(reply.error);
+ }
+ else if (p_Fm->guestId != NCSW_MASTER_ID)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("running in guest-mode without IPC!"));
+
+ p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM);
+ WRITE_UINT32(p_Iram->iadd, 0x4);
+ while (GET_UINT32(p_Iram->iadd) != 0x4) ;
+ revInfo = GET_UINT32(p_Iram->idata);
+ p_RevisionInfo->packageRev = (uint16_t)((revInfo & 0xFFFF0000) >> 16);
+ p_RevisionInfo->majorRev = (uint8_t)((revInfo & 0x0000FF00) >> 8);
+ p_RevisionInfo->minorRev = (uint8_t)(revInfo & 0x000000FF);
+
+ return E_OK;
+}
+
+uint32_t FM_GetCounter(t_Handle h_Fm, e_FmCounters counter)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ t_Error err;
+ uint32_t counterValue;
+ struct fman_rg fman_rg;
+ enum fman_counters fsl_counter;
+
+ SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_VALUE(!p_Fm->p_FmDriverParam, E_INVALID_STATE, 0);
+
+ fman_rg.bmi_rg = p_Fm->p_FmBmiRegs;
+ fman_rg.qmi_rg = p_Fm->p_FmQmiRegs;
+ fman_rg.fpm_rg = p_Fm->p_FmFpmRegs;
+ fman_rg.dma_rg = p_Fm->p_FmDmaRegs;
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->baseAddr &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ uint32_t replyLength, outCounter;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_GET_COUNTER;
+ memcpy(msg.msgBody, (uint8_t *)&counter, sizeof(uint32_t));
+ replyLength = sizeof(uint32_t) + sizeof(uint32_t);
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId) +sizeof(counterValue),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ {
+ REPORT_ERROR(MAJOR, err, NO_MSG);
+ return 0;
+ }
+ if (replyLength != (sizeof(uint32_t) + sizeof(uint32_t)))
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ return 0;
+ }
+
+ memcpy((uint8_t*)&outCounter, reply.replyBody, sizeof(uint32_t));
+ return outCounter;
+ }
+ else if (!p_Fm->baseAddr)
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Either IPC or 'baseAddress' is required!"));
+ return 0;
+ }
+
+ /* When applicable (when there is an 'enable counters' bit,
+ check that counters are enabled */
+ switch (counter)
+ {
+ case (e_FM_COUNTERS_DEQ_1):
+ case (e_FM_COUNTERS_DEQ_2):
+ case (e_FM_COUNTERS_DEQ_3):
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)
+ {
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Requested counter not supported"));
+ return 0;
+ }
+ case (e_FM_COUNTERS_ENQ_TOTAL_FRAME):
+ case (e_FM_COUNTERS_DEQ_TOTAL_FRAME):
+ case (e_FM_COUNTERS_DEQ_0):
+ case (e_FM_COUNTERS_DEQ_FROM_DEFAULT):
+ case (e_FM_COUNTERS_DEQ_FROM_CONTEXT):
+ case (e_FM_COUNTERS_DEQ_FROM_FD):
+ case (e_FM_COUNTERS_DEQ_CONFIRM):
+ if (!(GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_gc) & QMI_CFG_EN_COUNTERS))
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Requested counter was not enabled"));
+ return 0;
+ }
+ break;
+ default:
+ break;
+ }
+
+ FMAN_COUNTERS_TRANS(fsl_counter, counter);
+ return fman_get_counter(&fman_rg, fsl_counter);
+}
+
+t_Error FM_ModifyCounter(t_Handle h_Fm, e_FmCounters counter, uint32_t val)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ struct fman_rg fman_rg;
+ enum fman_counters fsl_counter;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+
+ fman_rg.bmi_rg = p_Fm->p_FmBmiRegs;
+ fman_rg.qmi_rg = p_Fm->p_FmQmiRegs;
+ fman_rg.fpm_rg = p_Fm->p_FmFpmRegs;
+ fman_rg.dma_rg = p_Fm->p_FmDmaRegs;
+
+ FMAN_COUNTERS_TRANS(fsl_counter, counter);
+ return (t_Error)fman_modify_counter(&fman_rg, fsl_counter, val);
+}
+
+void FM_SetDmaEmergency(t_Handle h_Fm, e_FmDmaMuramPort muramPort, bool enable)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ struct fman_dma_regs *dma_rg;
+
+ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+
+ dma_rg = p_Fm->p_FmDmaRegs;
+
+ fman_set_dma_emergency(dma_rg, !!(muramPort==e_FM_DMA_MURAM_PORT_WRITE), enable);
+}
+
+void FM_SetDmaExtBusPri(t_Handle h_Fm, e_FmDmaExtBusPri pri)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ struct fman_dma_regs *dma_rg;
+
+ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+
+ dma_rg = p_Fm->p_FmDmaRegs;
+
+ fman_set_dma_ext_bus_pri(dma_rg, pri);
+}
+
+void FM_GetDmaStatus(t_Handle h_Fm, t_FmDmaStatus *p_FmDmaStatus)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ uint32_t dmaStatus;
+ struct fman_dma_regs *dma_rg;
+
+ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+
+ dma_rg = p_Fm->p_FmDmaRegs;
+
+ if ((p_Fm->guestId != NCSW_MASTER_ID) &&
+ !p_Fm->baseAddr &&
+ p_Fm->h_IpcSessions[0])
+ {
+ t_FmIpcDmaStatus ipcDmaStatus;
+ t_FmIpcMsg msg;
+ t_FmIpcReply reply;
+ t_Error err;
+ uint32_t replyLength;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&reply, 0, sizeof(reply));
+ msg.msgId = FM_DMA_STAT;
+ replyLength = sizeof(uint32_t) + sizeof(t_FmIpcDmaStatus);
+ err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0],
+ (uint8_t*)&msg,
+ sizeof(msg.msgId),
+ (uint8_t*)&reply,
+ &replyLength,
+ NULL,
+ NULL);
+ if (err != E_OK)
+ {
+ REPORT_ERROR(MINOR, err, NO_MSG);
+ return;
+ }
+ if (replyLength != (sizeof(uint32_t) + sizeof(t_FmIpcDmaStatus)))
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch"));
+ return;
+ }
+ memcpy((uint8_t*)&ipcDmaStatus, reply.replyBody, sizeof(t_FmIpcDmaStatus));
+
+ p_FmDmaStatus->cmqNotEmpty = (bool)ipcDmaStatus.boolCmqNotEmpty; /**< Command queue is not empty */
+ p_FmDmaStatus->busError = (bool)ipcDmaStatus.boolBusError; /**< Bus error occurred */
+ p_FmDmaStatus->readBufEccError = (bool)ipcDmaStatus.boolReadBufEccError; /**< Double ECC error on buffer Read */
+ p_FmDmaStatus->writeBufEccSysError =(bool)ipcDmaStatus.boolWriteBufEccSysError; /**< Double ECC error on buffer write from system side */
+ p_FmDmaStatus->writeBufEccFmError = (bool)ipcDmaStatus.boolWriteBufEccFmError; /**< Double ECC error on buffer write from FM side */
+ p_FmDmaStatus->singlePortEccError = (bool)ipcDmaStatus.boolSinglePortEccError; /**< Double ECC error on buffer write from FM side */
+ return;
+ }
+ else if (!p_Fm->baseAddr)
+ {
+ REPORT_ERROR(MINOR, E_NOT_SUPPORTED,
+ ("Either IPC or 'baseAddress' is required!"));
+ return;
+ }
+
+ dmaStatus = fman_get_dma_status(dma_rg);
+
+ p_FmDmaStatus->cmqNotEmpty = (bool)(dmaStatus & DMA_STATUS_CMD_QUEUE_NOT_EMPTY);
+ p_FmDmaStatus->busError = (bool)(dmaStatus & DMA_STATUS_BUS_ERR);
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)
+ p_FmDmaStatus->singlePortEccError = (bool)(dmaStatus & DMA_STATUS_FM_SPDAT_ECC);
+ else
+ {
+ p_FmDmaStatus->readBufEccError = (bool)(dmaStatus & DMA_STATUS_READ_ECC);
+ p_FmDmaStatus->writeBufEccSysError = (bool)(dmaStatus & DMA_STATUS_SYSTEM_WRITE_ECC);
+ p_FmDmaStatus->writeBufEccFmError = (bool)(dmaStatus & DMA_STATUS_FM_WRITE_ECC);
+ }
+}
+
+void FM_Resume(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ struct fman_fpm_regs *fpm_rg;
+
+ SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ fpm_rg = p_Fm->p_FmFpmRegs;
+
+ fman_resume(fpm_rg);
+}
+
+t_Error FM_GetSpecialOperationCoding(t_Handle h_Fm,
+ fmSpecialOperations_t spOper,
+ uint8_t *p_SpOperCoding)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ t_FmCtrlCodeRevisionInfo revInfo;
+ t_Error err;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(p_SpOperCoding, E_NULL_POINTER);
+
+ if (!spOper)
+ {
+ *p_SpOperCoding = 0;
+ return E_OK;
+ }
+
+ if ((err = FM_GetFmanCtrlCodeRevision(p_Fm, &revInfo)) != E_OK)
+ {
+ DBG(WARNING, ("FM in guest-mode without IPC, can't validate firmware revision."));
+ revInfo.packageRev = IP_OFFLOAD_PACKAGE_NUMBER;
+ }
+ else if (revInfo.packageRev != IP_OFFLOAD_PACKAGE_NUMBER)
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Fman ctrl code package"));
+
+ if (revInfo.packageRev == IP_OFFLOAD_PACKAGE_NUMBER)
+ {
+ switch (spOper)
+ {
+ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_UPDATE_UDP_LEN|FM_SP_OP_IPSEC_MANIP):
+ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_UPDATE_UDP_LEN|FM_SP_OP_IPSEC_MANIP|FM_SP_OP_RPD):
+ *p_SpOperCoding = 5;
+ break;
+ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_MANIP):
+ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_MANIP|FM_SP_OP_RPD):
+ *p_SpOperCoding = 6;
+ break;
+ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_UPDATE_UDP_LEN|FM_SP_OP_RPD):
+ *p_SpOperCoding = 3;
+ break;
+ case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_UPDATE_UDP_LEN):
+ *p_SpOperCoding = 1;
+ break;
+ case (FM_SP_OP_IPSEC|FM_SP_OP_RPD):
+ *p_SpOperCoding = 4;
+ break;
+ case (FM_SP_OP_IPSEC):
+ *p_SpOperCoding = 2;
+ break;
+ case (FM_SP_OP_DCL4C):
+ *p_SpOperCoding = 7;
+ break;
+ case (FM_SP_OP_CLEAR_RPD):
+ *p_SpOperCoding = 8;
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG);
+ }
+ }
+ return E_OK;
+}
+
+t_Error FM_CtrlMonStart(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+ t_FmTrbRegs *p_MonRegs;
+ uint8_t i;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_brkc,
+ GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_brkc) | FPM_BRKC_RDBG);
+
+ for (i = 0; i < FM_NUM_OF_CTRL; i++)
+ {
+ p_MonRegs = (t_FmTrbRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_TRB(i));
+
+ /* Reset control registers */
+ WRITE_UINT32(p_MonRegs->tcrh, TRB_TCRH_RESET);
+ WRITE_UINT32(p_MonRegs->tcrl, TRB_TCRL_RESET);
+
+ /* Configure: counter #1 counts all stalls in risc - ldsched stall
+ counter #2 counts all stalls in risc - other stall*/
+ WRITE_UINT32(p_MonRegs->tcrl, TRB_TCRL_RESET | TRB_TCRL_UTIL);
+
+ /* Enable monitoring */
+ WRITE_UINT32(p_MonRegs->tcrh, TRB_TCRH_ENABLE_COUNTERS);
+ }
+
+ return E_OK;
+}
+
+t_Error FM_CtrlMonStop(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+ t_FmTrbRegs *p_MonRegs;
+ uint8_t i;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+
+ for (i = 0; i < FM_NUM_OF_CTRL; i++)
+ {
+ p_MonRegs = (t_FmTrbRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_TRB(i));
+ WRITE_UINT32(p_MonRegs->tcrh, TRB_TCRH_DISABLE_COUNTERS);
+ }
+
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_brkc,
+ GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_brkc) & ~FPM_BRKC_RDBG);
+
+ return E_OK;
+}
+
+t_Error FM_CtrlMonGetCounters(t_Handle h_Fm, uint8_t fmCtrlIndex, t_FmCtrlMon *p_Mon)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+ t_FmTrbRegs *p_MonRegs;
+ uint64_t clkCnt, utilValue, effValue;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED);
+ SANITY_CHECK_RETURN_ERROR(p_Mon, E_NULL_POINTER);
+
+ if (fmCtrlIndex >= FM_NUM_OF_CTRL)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("FM Controller index"));
+
+ p_MonRegs = (t_FmTrbRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_TRB(fmCtrlIndex));
+
+ clkCnt = (uint64_t)
+ ((uint64_t)GET_UINT32(p_MonRegs->tpcch) << 32 | GET_UINT32(p_MonRegs->tpccl));
+
+ utilValue = (uint64_t)
+ ((uint64_t)GET_UINT32(p_MonRegs->tpc1h) << 32 | GET_UINT32(p_MonRegs->tpc1l));
+
+ effValue = (uint64_t)
+ ((uint64_t)GET_UINT32(p_MonRegs->tpc2h) << 32 | GET_UINT32(p_MonRegs->tpc2l));
+
+ p_Mon->percentCnt[0] = (uint8_t)((clkCnt - utilValue) * 100 / clkCnt);
+ if (clkCnt != utilValue)
+ p_Mon->percentCnt[1] = (uint8_t)(((clkCnt - utilValue) - effValue) * 100 / (clkCnt - utilValue));
+ else
+ p_Mon->percentCnt[1] = 0;
+
+ return E_OK;
+}
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+t_Error FM_DumpRegs(t_Handle h_Fm)
+{
+ t_Fm *p_Fm = (t_Fm *)h_Fm;
+ uint8_t i,j = 0;
+
+ DECLARE_DUMP;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+ SANITY_CHECK_RETURN_ERROR(((p_Fm->guestId == NCSW_MASTER_ID) ||
+ p_Fm->baseAddr), E_INVALID_OPERATION);
+
+ DUMP_SUBTITLE(("\n"));
+
+ DUMP_TITLE(p_Fm->p_FmFpmRegs, ("FM-FPM Regs"));
+
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_tnc);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_prc);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_brkc);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_mxd);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_dist1);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_dist2);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_epi);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_rie);
+
+ DUMP_TITLE(&p_Fm->p_FmFpmRegs->fmfp_fcev, ("fmfp_fcev"));
+ DUMP_SUBSTRUCT_ARRAY(i, 4)
+ {
+ DUMP_MEMORY(&p_Fm->p_FmFpmRegs->fmfp_fcev[i], sizeof(uint32_t));
+ }
+
+ DUMP_TITLE(&p_Fm->p_FmFpmRegs->fmfp_cee, ("fmfp_cee"));
+ DUMP_SUBSTRUCT_ARRAY(i, 4)
+ {
+ DUMP_MEMORY(&p_Fm->p_FmFpmRegs->fmfp_cee[i], sizeof(uint32_t));
+ }
+
+ DUMP_SUBTITLE(("\n"));
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_tsc1);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_tsc2);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_tsp);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_tsf);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_rcr);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_extc);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_ext1);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_ext2);
+
+ DUMP_SUBTITLE(("\n"));
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_dra, 0);
+ CORE_MemoryBarrier();
+ for (j=0; j<128; j++)
+ {
+ DUMP_TITLE(j, ("fmfp_dra"));
+ DUMP_SUBSTRUCT_ARRAY(i, 4)
+ {
+ DUMP_MEMORY(&p_Fm->p_FmFpmRegs->fmfp_drd[i], sizeof(uint32_t));
+ }
+ DUMP_TITLE(j, ("fmfp_ts"));
+ DUMP_MEMORY(&p_Fm->p_FmFpmRegs->fmfp_ts[j], sizeof(uint32_t));
+ }
+
+ DUMP_SUBTITLE(("\n"));
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_ip_rev_1);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_ip_rev_2);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_rstc);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_cld);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fm_npi);
+ DUMP_VAR(p_Fm->p_FmFpmRegs,fmfp_ee);
+
+ DUMP_TITLE(&p_Fm->p_FmFpmRegs->fmfp_cev, ("fmfp_cev"));
+ DUMP_SUBSTRUCT_ARRAY(i, 4)
+ {
+ DUMP_MEMORY(&p_Fm->p_FmFpmRegs->fmfp_cev[i], sizeof(uint32_t));
+ }
+
+ DUMP_TITLE(&p_Fm->p_FmFpmRegs->fmfp_ps, ("fmfp_ps"));
+ DUMP_SUBSTRUCT_ARRAY(i, 64)
+ {
+ DUMP_MEMORY(&p_Fm->p_FmFpmRegs->fmfp_ps[i], sizeof(uint32_t));
+ }
+
+ DUMP_TITLE(p_Fm->p_FmDmaRegs, ("FM-DMA Regs"));
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmsr);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmemsr);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmmr);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmtr);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmhy);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmsetr);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmtah);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmtal);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmtcid);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmra);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmrd);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmwcr);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmebcr);
+ DUMP_VAR(p_Fm->p_FmDmaRegs,fmdmdcr);
+
+ DUMP_TITLE(&p_Fm->p_FmDmaRegs->fmdmplr, ("fmdmplr"));
+
+ DUMP_SUBSTRUCT_ARRAY(i, FM_MAX_NUM_OF_HW_PORT_IDS/2)
+ {
+ DUMP_MEMORY(&p_Fm->p_FmDmaRegs->fmdmplr[i], sizeof(uint32_t));
+ }
+
+ DUMP_TITLE(p_Fm->p_FmBmiRegs, ("FM-BMI COMMON Regs"));
+ DUMP_VAR(p_Fm->p_FmBmiRegs,fmbm_init);
+ DUMP_VAR(p_Fm->p_FmBmiRegs,fmbm_cfg1);
+ DUMP_VAR(p_Fm->p_FmBmiRegs,fmbm_cfg2);
+ DUMP_VAR(p_Fm->p_FmBmiRegs,fmbm_ievr);
+ DUMP_VAR(p_Fm->p_FmBmiRegs,fmbm_ier);
+
+ DUMP_TITLE(&p_Fm->p_FmBmiRegs->fmbm_arb, ("fmbm_arb"));
+ DUMP_SUBSTRUCT_ARRAY(i, 8)
+ {
+ DUMP_MEMORY(&p_Fm->p_FmBmiRegs->fmbm_arb[i], sizeof(uint32_t));
+ }
+
+ DUMP_TITLE(p_Fm->p_FmQmiRegs, ("FM-QMI COMMON Regs"));
+ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_gc);
+ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_eie);
+ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_eien);
+ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_eif);
+ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_ie);
+ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_ien);
+ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_if);
+ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_gs);
+ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_etfc);
+ DUMP_VAR(p_Fm->p_FmQmiRegs,fmqm_tapc);
+
+ return E_OK;
+}
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+
+
+/****************************************************/
+/* Hidden-DEBUG Only API */
+/****************************************************/
+
+t_Error FM_ForceIntr (t_Handle h_Fm, e_FmExceptions exception)
+{
+ t_Fm *p_Fm = (t_Fm*)h_Fm;
+ enum fman_exceptions fslException;
+ struct fman_rg fman_rg;
+
+ SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE);
+
+ fman_rg.bmi_rg = p_Fm->p_FmBmiRegs;
+ fman_rg.qmi_rg = p_Fm->p_FmQmiRegs;
+ fman_rg.fpm_rg = p_Fm->p_FmFpmRegs;
+ fman_rg.dma_rg = p_Fm->p_FmDmaRegs;
+
+ switch (exception)
+ {
+ case e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID:
+ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ break;
+ case e_FM_EX_QMI_SINGLE_ECC:
+ if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)
+ RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("e_FM_EX_QMI_SINGLE_ECC not supported on this integration."));
+
+ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_QMI_SINGLE_ECC))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ break;
+ case e_FM_EX_QMI_DOUBLE_ECC:
+ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_QMI_DOUBLE_ECC))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ break;
+ case e_FM_EX_BMI_LIST_RAM_ECC:
+ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_LIST_RAM_ECC))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ break;
+ case e_FM_EX_BMI_STORAGE_PROFILE_ECC:
+ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_STORAGE_PROFILE_ECC))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ break;
+ case e_FM_EX_BMI_STATISTICS_RAM_ECC:
+ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_STATISTICS_RAM_ECC))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ break;
+ case e_FM_EX_BMI_DISPATCH_RAM_ECC:
+ if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_DISPATCH_RAM_ECC))
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked"));
+ break;
+ default:
+ RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception may not be forced"));
+ }
+
+ FMAN_EXCEPTION_TRANS(fslException, exception);
+ fman_force_intr (&fman_rg, fslException);
+
+ return E_OK;
+}
+
+t_Handle FmGetPcd(t_Handle h_Fm)
+{
+ return ((t_Fm*)h_Fm)->h_Pcd;
+}
+
+t_Error FmGetSetParams(t_Handle h_Fm, t_FmGetSetParams *p_Params)
+{
+ t_Fm* p_Fm = (t_Fm*)h_Fm;
+ if (p_Params->setParams.type == UPDATE_FPM_BRKC_SLP)
+ {
+ if (p_Params->setParams.sleep)
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_brkc, GET_UINT32(
+ p_Fm->p_FmFpmRegs->fmfp_brkc) | FPM_BRKC_SLP);
+ else
+ WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_brkc, GET_UINT32(
+ p_Fm->p_FmFpmRegs->fmfp_brkc) & ~FPM_BRKC_SLP);
+ }
+ return E_OK;
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.h
new file mode 100644
index 0000000..41ffc17
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.h
@@ -0,0 +1,695 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm.h
+
+ @Description FM internal structures and definitions.
+*//***************************************************************************/
+#ifndef __FM_H
+#define __FM_H
+
+#include "error_ext.h"
+#include "std_ext.h"
+#include "fm_ext.h"
+#include "fm_ipc.h"
+
+#include "fsl_fman.h"
+
+#define __ERR_MODULE__ MODULE_FM
+
+#define FM_MAX_NUM_OF_HW_PORT_IDS 64
+#define FM_MAX_NUM_OF_GUESTS 100
+
+/**************************************************************************//**
+ @Description Exceptions
+*//***************************************************************************/
+#define FM_EX_DMA_BUS_ERROR 0x80000000 /**< DMA bus error. */
+#define FM_EX_DMA_READ_ECC 0x40000000
+#define FM_EX_DMA_SYSTEM_WRITE_ECC 0x20000000
+#define FM_EX_DMA_FM_WRITE_ECC 0x10000000
+#define FM_EX_FPM_STALL_ON_TASKS 0x08000000 /**< Stall of tasks on FPM */
+#define FM_EX_FPM_SINGLE_ECC 0x04000000 /**< Single ECC on FPM */
+#define FM_EX_FPM_DOUBLE_ECC 0x02000000
+#define FM_EX_QMI_SINGLE_ECC 0x01000000 /**< Single ECC on FPM */
+#define FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID 0x00800000 /**< Dequeu from default queue id */
+#define FM_EX_QMI_DOUBLE_ECC 0x00400000
+#define FM_EX_BMI_LIST_RAM_ECC 0x00200000
+#define FM_EX_BMI_STORAGE_PROFILE_ECC 0x00100000
+#define FM_EX_BMI_STATISTICS_RAM_ECC 0x00080000
+#define FM_EX_IRAM_ECC 0x00040000
+#define FM_EX_MURAM_ECC 0x00020000
+#define FM_EX_BMI_DISPATCH_RAM_ECC 0x00010000
+#define FM_EX_DMA_SINGLE_PORT_ECC 0x00008000
+
+#define DMA_EMSR_EMSTR_MASK 0x0000FFFF
+
+#define DMA_THRESH_COMMQ_MASK 0xFF000000
+#define DMA_THRESH_READ_INT_BUF_MASK 0x007F0000
+#define DMA_THRESH_WRITE_INT_BUF_MASK 0x0000007F
+
+#define GET_EXCEPTION_FLAG(bitMask, exception) \
+switch (exception){ \
+ case e_FM_EX_DMA_BUS_ERROR: \
+ bitMask = FM_EX_DMA_BUS_ERROR; break; \
+ case e_FM_EX_DMA_SINGLE_PORT_ECC: \
+ bitMask = FM_EX_DMA_SINGLE_PORT_ECC; break; \
+ case e_FM_EX_DMA_READ_ECC: \
+ bitMask = FM_EX_DMA_READ_ECC; break; \
+ case e_FM_EX_DMA_SYSTEM_WRITE_ECC: \
+ bitMask = FM_EX_DMA_SYSTEM_WRITE_ECC; break; \
+ case e_FM_EX_DMA_FM_WRITE_ECC: \
+ bitMask = FM_EX_DMA_FM_WRITE_ECC; break; \
+ case e_FM_EX_FPM_STALL_ON_TASKS: \
+ bitMask = FM_EX_FPM_STALL_ON_TASKS; break; \
+ case e_FM_EX_FPM_SINGLE_ECC: \
+ bitMask = FM_EX_FPM_SINGLE_ECC; break; \
+ case e_FM_EX_FPM_DOUBLE_ECC: \
+ bitMask = FM_EX_FPM_DOUBLE_ECC; break; \
+ case e_FM_EX_QMI_SINGLE_ECC: \
+ bitMask = FM_EX_QMI_SINGLE_ECC; break; \
+ case e_FM_EX_QMI_DOUBLE_ECC: \
+ bitMask = FM_EX_QMI_DOUBLE_ECC; break; \
+ case e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID: \
+ bitMask = FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID; break; \
+ case e_FM_EX_BMI_LIST_RAM_ECC: \
+ bitMask = FM_EX_BMI_LIST_RAM_ECC; break; \
+ case e_FM_EX_BMI_STORAGE_PROFILE_ECC: \
+ bitMask = FM_EX_BMI_STORAGE_PROFILE_ECC; break; \
+ case e_FM_EX_BMI_STATISTICS_RAM_ECC: \
+ bitMask = FM_EX_BMI_STATISTICS_RAM_ECC; break; \
+ case e_FM_EX_BMI_DISPATCH_RAM_ECC: \
+ bitMask = FM_EX_BMI_DISPATCH_RAM_ECC; break; \
+ case e_FM_EX_IRAM_ECC: \
+ bitMask = FM_EX_IRAM_ECC; break; \
+ case e_FM_EX_MURAM_ECC: \
+ bitMask = FM_EX_MURAM_ECC; break; \
+ default: bitMask = 0;break; \
+}
+
+#define GET_FM_MODULE_EVENT(_mod, _id, _intrType, _event) \
+ switch (_mod) { \
+ case e_FM_MOD_PRS: \
+ if (_id) _event = e_FM_EV_DUMMY_LAST; \
+ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? e_FM_EV_ERR_PRS : e_FM_EV_PRS; \
+ break; \
+ case e_FM_MOD_KG: \
+ if (_id) _event = e_FM_EV_DUMMY_LAST; \
+ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? e_FM_EV_ERR_KG : e_FM_EV_DUMMY_LAST; \
+ break; \
+ case e_FM_MOD_PLCR: \
+ if (_id) _event = e_FM_EV_DUMMY_LAST; \
+ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? e_FM_EV_ERR_PLCR : e_FM_EV_PLCR; \
+ break; \
+ case e_FM_MOD_TMR: \
+ if (_id) _event = e_FM_EV_DUMMY_LAST; \
+ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? e_FM_EV_DUMMY_LAST : e_FM_EV_TMR; \
+ break; \
+ case e_FM_MOD_10G_MAC: \
+ if (_id >= FM_MAX_NUM_OF_10G_MACS) _event = e_FM_EV_DUMMY_LAST; \
+ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? (e_FM_EV_ERR_10G_MAC0 + _id) : (e_FM_EV_10G_MAC0 + _id); \
+ break; \
+ case e_FM_MOD_1G_MAC: \
+ if (_id >= FM_MAX_NUM_OF_1G_MACS) _event = e_FM_EV_DUMMY_LAST; \
+ else _event = (_intrType == e_FM_INTR_TYPE_ERR) ? (e_FM_EV_ERR_1G_MAC0 + _id) : (e_FM_EV_1G_MAC0 + _id); \
+ break; \
+ case e_FM_MOD_MACSEC: \
+ switch (_id){ \
+ case (0): _event = (_intrType == e_FM_INTR_TYPE_ERR) ? e_FM_EV_ERR_MACSEC_MAC0:e_FM_EV_MACSEC_MAC0; \
+ break; \
+ } \
+ break; \
+ case e_FM_MOD_FMAN_CTRL: \
+ if (_intrType == e_FM_INTR_TYPE_ERR) _event = e_FM_EV_DUMMY_LAST; \
+ else _event = (e_FM_EV_FMAN_CTRL_0 + _id); \
+ break; \
+ default: _event = e_FM_EV_DUMMY_LAST; \
+ break; \
+ }
+
+#define FMAN_EXCEPTION_TRANS(fsl_exception, _exception) \
+ switch (_exception) {\
+ case e_FM_EX_DMA_BUS_ERROR: \
+ fsl_exception = E_FMAN_EX_DMA_BUS_ERROR; break; \
+ case e_FM_EX_DMA_READ_ECC: \
+ fsl_exception = E_FMAN_EX_DMA_READ_ECC; break; \
+ case e_FM_EX_DMA_SYSTEM_WRITE_ECC: \
+ fsl_exception = E_FMAN_EX_DMA_SYSTEM_WRITE_ECC; break; \
+ case e_FM_EX_DMA_FM_WRITE_ECC: \
+ fsl_exception = E_FMAN_EX_DMA_FM_WRITE_ECC; break; \
+ case e_FM_EX_FPM_STALL_ON_TASKS: \
+ fsl_exception = E_FMAN_EX_FPM_STALL_ON_TASKS; break; \
+ case e_FM_EX_FPM_SINGLE_ECC: \
+ fsl_exception = E_FMAN_EX_FPM_SINGLE_ECC; break; \
+ case e_FM_EX_FPM_DOUBLE_ECC: \
+ fsl_exception = E_FMAN_EX_FPM_DOUBLE_ECC; break; \
+ case e_FM_EX_QMI_SINGLE_ECC: \
+ fsl_exception = E_FMAN_EX_QMI_SINGLE_ECC; break; \
+ case e_FM_EX_QMI_DOUBLE_ECC: \
+ fsl_exception = E_FMAN_EX_QMI_DOUBLE_ECC; break; \
+ case e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID: \
+ fsl_exception = E_FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID; break; \
+ case e_FM_EX_BMI_LIST_RAM_ECC: \
+ fsl_exception = E_FMAN_EX_BMI_LIST_RAM_ECC; break; \
+ case e_FM_EX_BMI_STORAGE_PROFILE_ECC: \
+ fsl_exception = E_FMAN_EX_BMI_STORAGE_PROFILE_ECC; break; \
+ case e_FM_EX_BMI_STATISTICS_RAM_ECC: \
+ fsl_exception = E_FMAN_EX_BMI_STATISTICS_RAM_ECC; break; \
+ case e_FM_EX_BMI_DISPATCH_RAM_ECC: \
+ fsl_exception = E_FMAN_EX_BMI_DISPATCH_RAM_ECC; break; \
+ case e_FM_EX_IRAM_ECC: \
+ fsl_exception = E_FMAN_EX_IRAM_ECC; break; \
+ case e_FM_EX_MURAM_ECC: \
+ fsl_exception = E_FMAN_EX_MURAM_ECC; break; \
+ default: \
+ fsl_exception = E_FMAN_EX_DMA_BUS_ERROR; break; \
+ }
+
+#define FMAN_CACHE_OVERRIDE_TRANS(fsl_cache_override, _cache_override) \
+ switch (_cache_override){ \
+ case e_FM_DMA_NO_CACHE_OR: \
+ fsl_cache_override = E_FMAN_DMA_NO_CACHE_OR; break; \
+ case e_FM_DMA_NO_STASH_DATA: \
+ fsl_cache_override = E_FMAN_DMA_NO_STASH_DATA; break; \
+ case e_FM_DMA_MAY_STASH_DATA: \
+ fsl_cache_override = E_FMAN_DMA_MAY_STASH_DATA; break; \
+ case e_FM_DMA_STASH_DATA: \
+ fsl_cache_override = E_FMAN_DMA_STASH_DATA; break; \
+ default: \
+ fsl_cache_override = E_FMAN_DMA_NO_CACHE_OR; break; \
+ }
+
+#define FMAN_AID_MODE_TRANS(fsl_aid_mode, _aid_mode) \
+ switch (_aid_mode){ \
+ case e_FM_DMA_AID_OUT_PORT_ID: \
+ fsl_aid_mode = E_FMAN_DMA_AID_OUT_PORT_ID; break; \
+ case e_FM_DMA_AID_OUT_TNUM: \
+ fsl_aid_mode = E_FMAN_DMA_AID_OUT_TNUM; break; \
+ default: \
+ fsl_aid_mode = E_FMAN_DMA_AID_OUT_PORT_ID; break; \
+ }
+
+#define FMAN_DMA_DBG_CNT_TRANS(fsl_dma_dbg_cnt, _dma_dbg_cnt) \
+ switch (_dma_dbg_cnt){ \
+ case e_FM_DMA_DBG_NO_CNT: \
+ fsl_dma_dbg_cnt = E_FMAN_DMA_DBG_NO_CNT; break; \
+ case e_FM_DMA_DBG_CNT_DONE: \
+ fsl_dma_dbg_cnt = E_FMAN_DMA_DBG_CNT_DONE; break; \
+ case e_FM_DMA_DBG_CNT_COMM_Q_EM: \
+ fsl_dma_dbg_cnt = E_FMAN_DMA_DBG_CNT_COMM_Q_EM; break; \
+ case e_FM_DMA_DBG_CNT_INT_READ_EM: \
+ fsl_dma_dbg_cnt = E_FMAN_DMA_DBG_CNT_INT_READ_EM; break; \
+ case e_FM_DMA_DBG_CNT_INT_WRITE_EM: \
+ fsl_dma_dbg_cnt = E_FMAN_DMA_DBG_CNT_INT_WRITE_EM ; break; \
+ case e_FM_DMA_DBG_CNT_FPM_WAIT: \
+ fsl_dma_dbg_cnt = E_FMAN_DMA_DBG_CNT_FPM_WAIT ; break; \
+ case e_FM_DMA_DBG_CNT_SIGLE_BIT_ECC: \
+ fsl_dma_dbg_cnt = E_FMAN_DMA_DBG_CNT_SIGLE_BIT_ECC ; break; \
+ case e_FM_DMA_DBG_CNT_RAW_WAR_PROT: \
+ fsl_dma_dbg_cnt = E_FMAN_DMA_DBG_CNT_RAW_WAR_PROT ; break; \
+ default: \
+ fsl_dma_dbg_cnt = E_FMAN_DMA_DBG_NO_CNT; break; \
+ }
+
+#define FMAN_DMA_EMER_TRANS(fsl_dma_emer, _dma_emer) \
+ switch (_dma_emer){ \
+ case e_FM_DMA_EM_EBS: \
+ fsl_dma_emer = E_FMAN_DMA_EM_EBS; break; \
+ case e_FM_DMA_EM_SOS: \
+ fsl_dma_emer = E_FMAN_DMA_EM_SOS; break; \
+ default: \
+ fsl_dma_emer = E_FMAN_DMA_EM_EBS; break; \
+ }
+
+#define FMAN_DMA_ERR_TRANS(fsl_dma_err, _dma_err) \
+ switch (_dma_err){ \
+ case e_FM_DMA_ERR_CATASTROPHIC: \
+ fsl_dma_err = E_FMAN_DMA_ERR_CATASTROPHIC; break; \
+ case e_FM_DMA_ERR_REPORT: \
+ fsl_dma_err = E_FMAN_DMA_ERR_REPORT; break; \
+ default: \
+ fsl_dma_err = E_FMAN_DMA_ERR_CATASTROPHIC; break; \
+ }
+
+#define FMAN_CATASTROPHIC_ERR_TRANS(fsl_catastrophic_err, _catastrophic_err) \
+ switch (_catastrophic_err){ \
+ case e_FM_CATASTROPHIC_ERR_STALL_PORT: \
+ fsl_catastrophic_err = E_FMAN_CATAST_ERR_STALL_PORT; break; \
+ case e_FM_CATASTROPHIC_ERR_STALL_TASK: \
+ fsl_catastrophic_err = E_FMAN_CATAST_ERR_STALL_TASK; break; \
+ default: \
+ fsl_catastrophic_err = E_FMAN_CATAST_ERR_STALL_PORT; break; \
+ }
+
+#define FMAN_COUNTERS_TRANS(fsl_counters, _counters) \
+ switch (_counters){ \
+ case e_FM_COUNTERS_ENQ_TOTAL_FRAME: \
+ fsl_counters = E_FMAN_COUNTERS_ENQ_TOTAL_FRAME; break; \
+ case e_FM_COUNTERS_DEQ_TOTAL_FRAME: \
+ fsl_counters = E_FMAN_COUNTERS_DEQ_TOTAL_FRAME; break; \
+ case e_FM_COUNTERS_DEQ_0: \
+ fsl_counters = E_FMAN_COUNTERS_DEQ_0; break; \
+ case e_FM_COUNTERS_DEQ_1: \
+ fsl_counters = E_FMAN_COUNTERS_DEQ_1; break; \
+ case e_FM_COUNTERS_DEQ_2: \
+ fsl_counters = E_FMAN_COUNTERS_DEQ_2; break; \
+ case e_FM_COUNTERS_DEQ_3: \
+ fsl_counters = E_FMAN_COUNTERS_DEQ_3; break; \
+ case e_FM_COUNTERS_DEQ_FROM_DEFAULT: \
+ fsl_counters = E_FMAN_COUNTERS_DEQ_FROM_DEFAULT; break; \
+ case e_FM_COUNTERS_DEQ_FROM_CONTEXT: \
+ fsl_counters = E_FMAN_COUNTERS_DEQ_FROM_CONTEXT; break; \
+ case e_FM_COUNTERS_DEQ_FROM_FD: \
+ fsl_counters = E_FMAN_COUNTERS_DEQ_FROM_FD; break; \
+ case e_FM_COUNTERS_DEQ_CONFIRM: \
+ fsl_counters = E_FMAN_COUNTERS_DEQ_CONFIRM; break; \
+ default: \
+ fsl_counters = E_FMAN_COUNTERS_ENQ_TOTAL_FRAME; break; \
+ }
+
+/**************************************************************************//**
+ @Description defaults
+*//***************************************************************************/
+#define DEFAULT_exceptions (FM_EX_DMA_BUS_ERROR |\
+ FM_EX_DMA_READ_ECC |\
+ FM_EX_DMA_SYSTEM_WRITE_ECC |\
+ FM_EX_DMA_FM_WRITE_ECC |\
+ FM_EX_FPM_STALL_ON_TASKS |\
+ FM_EX_FPM_SINGLE_ECC |\
+ FM_EX_FPM_DOUBLE_ECC |\
+ FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID|\
+ FM_EX_BMI_LIST_RAM_ECC |\
+ FM_EX_BMI_STORAGE_PROFILE_ECC |\
+ FM_EX_BMI_STATISTICS_RAM_ECC |\
+ FM_EX_IRAM_ECC |\
+ FM_EX_MURAM_ECC |\
+ FM_EX_BMI_DISPATCH_RAM_ECC |\
+ FM_EX_QMI_DOUBLE_ECC |\
+ FM_EX_QMI_SINGLE_ECC)
+
+#define DEFAULT_eccEnable FALSE
+#ifdef FM_PEDANTIC_DMA
+#define DEFAULT_aidOverride TRUE
+#else
+#define DEFAULT_aidOverride FALSE
+#endif /* FM_PEDANTIC_DMA */
+#define DEFAULT_aidMode e_FM_DMA_AID_OUT_TNUM
+#define DEFAULT_dmaStopOnBusError FALSE
+#define DEFAULT_stopAtBusError FALSE
+#define DEFAULT_axiDbgNumOfBeats 1
+#define DEFAULT_dmaReadIntBufLow ((DMA_THRESH_MAX_BUF+1)/2)
+#define DEFAULT_dmaReadIntBufHigh ((DMA_THRESH_MAX_BUF+1)*3/4)
+#define DEFAULT_dmaWriteIntBufLow ((DMA_THRESH_MAX_BUF+1)/2)
+#define DEFAULT_dmaWriteIntBufHigh ((DMA_THRESH_MAX_BUF+1)*3/4)
+#define DEFAULT_catastrophicErr e_FM_CATASTROPHIC_ERR_STALL_PORT
+#define DEFAULT_dmaErr e_FM_DMA_ERR_CATASTROPHIC
+#define DEFAULT_resetOnInit FALSE
+#define DEFAULT_haltOnExternalActivation FALSE /* do not change! if changed, must be disabled for rev1 ! */
+#define DEFAULT_haltOnUnrecoverableEccError FALSE /* do not change! if changed, must be disabled for rev1 ! */
+#define DEFAULT_externalEccRamsEnable FALSE
+#define DEFAULT_VerifyUcode FALSE
+
+#if (DPAA_VERSION < 11)
+#define DEFAULT_totalFifoSize(major, minor) \
+ (((major == 2) || (major == 5)) ? \
+ (100*KILOBYTE) : ((major == 4) ? \
+ (46*KILOBYTE) : (122*KILOBYTE)))
+#define DEFAULT_totalNumOfTasks BMI_MAX_NUM_OF_TASKS
+
+#define DEFAULT_dmaCommQLow ((DMA_THRESH_MAX_COMMQ+1)/2)
+#define DEFAULT_dmaCommQHigh ((DMA_THRESH_MAX_COMMQ+1)*3/4)
+#define DEFAULT_cacheOverride e_FM_DMA_NO_CACHE_OR
+#define DEFAULT_dmaCamNumOfEntries 32
+#define DEFAULT_dmaDbgCntMode e_FM_DMA_DBG_NO_CNT
+#define DEFAULT_dmaEnEmergency FALSE
+#define DEFAULT_dmaSosEmergency 0
+#define DEFAULT_dmaWatchdog 0 /* disabled */
+#define DEFAULT_dmaEnEmergencySmoother FALSE
+#define DEFAULT_dmaEmergencySwitchCounter 0
+
+#define DEFAULT_dispLimit 0
+#define DEFAULT_prsDispTh 16
+#define DEFAULT_plcrDispTh 16
+#define DEFAULT_kgDispTh 16
+#define DEFAULT_bmiDispTh 16
+#define DEFAULT_qmiEnqDispTh 16
+#define DEFAULT_qmiDeqDispTh 16
+#define DEFAULT_fmCtl1DispTh 16
+#define DEFAULT_fmCtl2DispTh 16
+
+#else /* (DPAA_VERSION < 11) */
+/* Defaults are registers' reset values */
+#define DEFAULT_totalFifoSize(major, minor) \
+ (((major == 6) && (minor == 1)) ? (128*KILOBYTE) : (295*KILOBYTE))
+
+#define DEFAULT_totalNumOfTasks 124
+
+#define DEFAULT_dmaCommQLow 0x2A
+#define DEFAULT_dmaCommQHigh 0x3F
+#define DEFAULT_cacheOverride e_FM_DMA_NO_CACHE_OR
+#define DEFAULT_dmaCamNumOfEntries 64
+#define DEFAULT_dmaDbgCntMode e_FM_DMA_DBG_NO_CNT
+#define DEFAULT_dmaEnEmergency FALSE
+#define DEFAULT_dmaSosEmergency 0
+#define DEFAULT_dmaWatchdog 0 /* disabled */
+#define DEFAULT_dmaEnEmergencySmoother FALSE
+#define DEFAULT_dmaEmergencySwitchCounter 0
+
+#define DEFAULT_dispLimit 0
+#define DEFAULT_prsDispTh 16
+#define DEFAULT_plcrDispTh 16
+#define DEFAULT_kgDispTh 16
+#define DEFAULT_bmiDispTh 16
+#define DEFAULT_qmiEnqDispTh 16
+#define DEFAULT_qmiDeqDispTh 16
+#define DEFAULT_fmCtl1DispTh 16
+#define DEFAULT_fmCtl2DispTh 16
+#endif /* (DPAA_VERSION < 11) */
+
+#define FM_TIMESTAMP_1_USEC_BIT 8
+
+/**************************************************************************//**
+ @Collection Defines used for enabling/disabling FM interrupts
+ @{
+*//***************************************************************************/
+#define ERR_INTR_EN_DMA 0x00010000
+#define ERR_INTR_EN_FPM 0x80000000
+#define ERR_INTR_EN_BMI 0x00800000
+#define ERR_INTR_EN_QMI 0x00400000
+#define ERR_INTR_EN_PRS 0x00200000
+#define ERR_INTR_EN_KG 0x00100000
+#define ERR_INTR_EN_PLCR 0x00080000
+#define ERR_INTR_EN_MURAM 0x00040000
+#define ERR_INTR_EN_IRAM 0x00020000
+#define ERR_INTR_EN_10G_MAC0 0x00008000
+#define ERR_INTR_EN_10G_MAC1 0x00000040
+#define ERR_INTR_EN_1G_MAC0 0x00004000
+#define ERR_INTR_EN_1G_MAC1 0x00002000
+#define ERR_INTR_EN_1G_MAC2 0x00001000
+#define ERR_INTR_EN_1G_MAC3 0x00000800
+#define ERR_INTR_EN_1G_MAC4 0x00000400
+#define ERR_INTR_EN_1G_MAC5 0x00000200
+#define ERR_INTR_EN_1G_MAC6 0x00000100
+#define ERR_INTR_EN_1G_MAC7 0x00000080
+#define ERR_INTR_EN_MACSEC_MAC0 0x00000001
+
+#define INTR_EN_QMI 0x40000000
+#define INTR_EN_PRS 0x20000000
+#define INTR_EN_PLCR 0x08000000
+#define INTR_EN_1G_MAC0 0x00080000
+#define INTR_EN_1G_MAC1 0x00040000
+#define INTR_EN_1G_MAC2 0x00020000
+#define INTR_EN_1G_MAC3 0x00010000
+#define INTR_EN_1G_MAC4 0x00000040
+#define INTR_EN_1G_MAC5 0x00000020
+#define INTR_EN_1G_MAC6 0x00000008
+#define INTR_EN_1G_MAC7 0x00000002
+#define INTR_EN_10G_MAC0 0x00200000
+#define INTR_EN_10G_MAC1 0x00100000
+#define INTR_EN_REV0 0x00008000
+#define INTR_EN_REV1 0x00004000
+#define INTR_EN_REV2 0x00002000
+#define INTR_EN_REV3 0x00001000
+#define INTR_EN_BRK 0x00000080
+#define INTR_EN_TMR 0x01000000
+#define INTR_EN_MACSEC_MAC0 0x00000001
+/* @} */
+
+/**************************************************************************//**
+ @Description Modules registers offsets
+*//***************************************************************************/
+#define FM_MM_MURAM 0x00000000
+#define FM_MM_BMI 0x00080000
+#define FM_MM_QMI 0x00080400
+#define FM_MM_PRS 0x000c7000
+#define FM_MM_KG 0x000C1000
+#define FM_MM_DMA 0x000C2000
+#define FM_MM_FPM 0x000C3000
+#define FM_MM_PLCR 0x000C0000
+#define FM_MM_IMEM 0x000C4000
+#define FM_MM_CGP 0x000DB000
+#define FM_MM_TRB(i) (0x000D0200 + 0x400 * (i))
+#if (DPAA_VERSION >= 11)
+#define FM_MM_SP 0x000dc000
+#endif /* (DPAA_VERSION >= 11) */
+
+/**************************************************************************//**
+ @Description Memory Mapped Registers
+*//***************************************************************************/
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+typedef _Packed struct
+{
+ volatile uint32_t iadd; /**< FM IRAM instruction address register */
+ volatile uint32_t idata; /**< FM IRAM instruction data register */
+ volatile uint32_t itcfg; /**< FM IRAM timing config register */
+ volatile uint32_t iready; /**< FM IRAM ready register */
+ volatile uint8_t res[0x80000-0x10];
+} _PackedType t_FMIramRegs;
+
+/* Trace buffer registers -
+ each FM Controller has its own trace buffer residing at FM_MM_TRB(fmCtrlIndex) offset */
+typedef _Packed struct t_FmTrbRegs
+{
+ volatile uint32_t tcrh;
+ volatile uint32_t tcrl;
+ volatile uint32_t tesr;
+ volatile uint32_t tecr0h;
+ volatile uint32_t tecr0l;
+ volatile uint32_t terf0h;
+ volatile uint32_t terf0l;
+ volatile uint32_t tecr1h;
+ volatile uint32_t tecr1l;
+ volatile uint32_t terf1h;
+ volatile uint32_t terf1l;
+ volatile uint32_t tpcch;
+ volatile uint32_t tpccl;
+ volatile uint32_t tpc1h;
+ volatile uint32_t tpc1l;
+ volatile uint32_t tpc2h;
+ volatile uint32_t tpc2l;
+ volatile uint32_t twdimr;
+ volatile uint32_t twicvr;
+ volatile uint32_t tar;
+ volatile uint32_t tdr;
+ volatile uint32_t tsnum1;
+ volatile uint32_t tsnum2;
+ volatile uint32_t tsnum3;
+ volatile uint32_t tsnum4;
+} _PackedType t_FmTrbRegs;
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+/**************************************************************************//**
+ @Description General defines
+*//***************************************************************************/
+#define FM_DEBUG_STATUS_REGISTER_OFFSET 0x000d1084UL
+#define FM_FW_DEBUG_INSTRUCTION 0x6ffff805UL
+
+/**************************************************************************//**
+ @Description FPM defines
+*//***************************************************************************/
+/* masks */
+#define FPM_BRKC_RDBG 0x00000200
+#define FPM_BRKC_SLP 0x00000800
+/**************************************************************************//**
+ @Description BMI defines
+*//***************************************************************************/
+/* masks */
+#define BMI_INIT_START 0x80000000
+#define BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC 0x80000000
+#define BMI_ERR_INTR_EN_LIST_RAM_ECC 0x40000000
+#define BMI_ERR_INTR_EN_STATISTICS_RAM_ECC 0x20000000
+#define BMI_ERR_INTR_EN_DISPATCH_RAM_ECC 0x10000000
+/**************************************************************************//**
+ @Description QMI defines
+*//***************************************************************************/
+/* masks */
+#define QMI_ERR_INTR_EN_DOUBLE_ECC 0x80000000
+#define QMI_ERR_INTR_EN_DEQ_FROM_DEF 0x40000000
+#define QMI_INTR_EN_SINGLE_ECC 0x80000000
+
+/**************************************************************************//**
+ @Description IRAM defines
+*//***************************************************************************/
+/* masks */
+#define IRAM_IADD_AIE 0x80000000
+#define IRAM_READY 0x80000000
+
+/**************************************************************************//**
+ @Description TRB defines
+*//***************************************************************************/
+/* masks */
+#define TRB_TCRH_RESET 0x04000000
+#define TRB_TCRH_ENABLE_COUNTERS 0x84008000
+#define TRB_TCRH_DISABLE_COUNTERS 0x8400C000
+#define TRB_TCRL_RESET 0x20000000
+#define TRB_TCRL_UTIL 0x00000460
+typedef struct {
+ void (*f_Isr) (t_Handle h_Arg, uint32_t event);
+ t_Handle h_SrcHandle;
+} t_FmanCtrlIntrSrc;
+
+
+typedef void (t_FmanCtrlIsr)( t_Handle h_Fm, uint32_t event);
+
+typedef struct
+{
+/***************************/
+/* Master/Guest parameters */
+/***************************/
+ uint8_t fmId;
+ e_FmPortType portsTypes[FM_MAX_NUM_OF_HW_PORT_IDS];
+ uint16_t fmClkFreq;
+ t_FmRevisionInfo revInfo;
+/**************************/
+/* Master Only parameters */
+/**************************/
+ bool enabledTimeStamp;
+ uint8_t count1MicroBit;
+ uint8_t totalNumOfTasks;
+ uint32_t totalFifoSize;
+ uint8_t maxNumOfOpenDmas;
+ uint8_t accumulatedNumOfTasks;
+ uint32_t accumulatedFifoSize;
+ uint8_t accumulatedNumOfOpenDmas;
+ uint8_t accumulatedNumOfDeqTnums;
+#ifdef FM_LOW_END_RESTRICTION
+ bool lowEndRestriction;
+#endif /* FM_LOW_END_RESTRICTION */
+ uint32_t exceptions;
+ int irq;
+ int errIrq;
+ bool ramsEccEnable;
+ bool explicitEnable;
+ bool internalCall;
+ uint8_t ramsEccOwners;
+ uint32_t extraFifoPoolSize;
+ uint8_t extraTasksPoolSize;
+ uint8_t extraOpenDmasPoolSize;
+#if defined(FM_MAX_NUM_OF_10G_MACS) && (FM_MAX_NUM_OF_10G_MACS)
+ uint16_t portMaxFrameLengths10G[FM_MAX_NUM_OF_10G_MACS];
+ uint16_t macMaxFrameLengths10G[FM_MAX_NUM_OF_10G_MACS];
+#endif /* defined(FM_MAX_NUM_OF_10G_MACS) && ... */
+ uint16_t portMaxFrameLengths1G[FM_MAX_NUM_OF_1G_MACS];
+ uint16_t macMaxFrameLengths1G[FM_MAX_NUM_OF_1G_MACS];
+} t_FmStateStruct;
+
+#if (DPAA_VERSION >= 11)
+typedef struct t_FmMapParam {
+ uint16_t profilesBase;
+ uint16_t numOfProfiles;
+ t_Handle h_FmPort;
+} t_FmMapParam;
+
+typedef struct t_FmAllocMng {
+ bool allocated;
+ uint8_t ownerId; /* guestId for KG in multi-partition only,
+ portId for PLCR in any environment */
+} t_FmAllocMng;
+
+typedef struct t_FmPcdSpEntry {
+ bool valid;
+ t_FmAllocMng profilesMng;
+} t_FmPcdSpEntry;
+
+typedef struct t_FmSp {
+ void *p_FmPcdStoragePrflRegs;
+ t_FmPcdSpEntry profiles[FM_VSP_MAX_NUM_OF_ENTRIES];
+ t_FmMapParam portsMapping[FM_MAX_NUM_OF_PORTS];
+} t_FmSp;
+#endif /* (DPAA_VERSION >= 11) */
+
+
+typedef struct t_Fm
+{
+/***************************/
+/* Master/Guest parameters */
+/***************************/
+/* locals for recovery */
+ uintptr_t baseAddr;
+
+/* un-needed for recovery */
+ t_Handle h_Pcd;
+ char fmModuleName[MODULE_NAME_SIZE];
+ char fmIpcHandlerModuleName[FM_MAX_NUM_OF_GUESTS][MODULE_NAME_SIZE];
+ t_Handle h_IpcSessions[FM_MAX_NUM_OF_GUESTS];
+ t_FmIntrSrc intrMng[e_FM_EV_DUMMY_LAST]; /* FM exceptions user callback */
+ uint8_t guestId;
+/**************************/
+/* Master Only parameters */
+/**************************/
+/* locals for recovery */
+ struct fman_fpm_regs *p_FmFpmRegs;
+ struct fman_bmi_regs *p_FmBmiRegs;
+ struct fman_qmi_regs *p_FmQmiRegs;
+ struct fman_dma_regs *p_FmDmaRegs;
+ struct fman_regs *p_FmRegs;
+ t_FmExceptionsCallback *f_Exception;
+ t_FmBusErrorCallback *f_BusError;
+ t_Handle h_App; /* Application handle */
+ t_Handle h_Spinlock;
+ bool recoveryMode;
+ t_FmStateStruct *p_FmStateStruct;
+ uint16_t tnumAgingPeriod;
+#if (DPAA_VERSION >= 11)
+ t_FmSp *p_FmSp;
+ uint8_t partNumOfVSPs;
+ uint8_t partVSPBase;
+ uintptr_t vspBaseAddr;
+#endif /* (DPAA_VERSION >= 11) */
+ bool portsPreFetchConfigured[FM_MAX_NUM_OF_HW_PORT_IDS]; /* Prefetch configration per Tx-port */
+ bool portsPreFetchValue[FM_MAX_NUM_OF_HW_PORT_IDS]; /* Prefetch configration per Tx-port */
+
+/* un-needed for recovery */
+ struct fman_cfg *p_FmDriverParam;
+ t_Handle h_FmMuram;
+ uint64_t fmMuramPhysBaseAddr;
+ bool independentMode;
+ bool hcPortInitialized;
+ uintptr_t camBaseAddr; /* save for freeing */
+ uintptr_t resAddr;
+ uintptr_t fifoBaseAddr; /* save for freeing */
+ t_FmanCtrlIntrSrc fmanCtrlIntr[FM_NUM_OF_FMAN_CTRL_EVENT_REGS]; /* FM exceptions user callback */
+ bool usedEventRegs[FM_NUM_OF_FMAN_CTRL_EVENT_REGS];
+ t_FmFirmwareParams firmware;
+ bool fwVerify;
+ bool resetOnInit;
+ uint32_t userSetExceptions;
+} t_Fm;
+
+
+#endif /* __FM_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm_ipc.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm_ipc.h
new file mode 100644
index 0000000..f39d5d9
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm_ipc.h
@@ -0,0 +1,464 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File fm_ipc.h
+
+ @Description FM Inter-Partition prototypes, structures and definitions.
+*//***************************************************************************/
+#ifndef __FM_IPC_H
+#define __FM_IPC_H
+
+#include "error_ext.h"
+#include "std_ext.h"
+
+
+/**************************************************************************//**
+ @Group FM_grp Frame Manager API
+
+ @Description FM API functions, definitions and enums
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group FM_IPC_grp FM Inter-Partition messaging Unit
+
+ @Description FM Inter-Partition messaging unit API definitions and enums.
+
+ @{
+*//***************************************************************************/
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+/**************************************************************************//**
+ @Description enum for defining MAC types
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Description A structure of parameters for specifying a MAC.
+*//***************************************************************************/
+typedef _Packed struct
+{
+ uint8_t id;
+ uint32_t enumType;
+} _PackedType t_FmIpcMacParams;
+
+/**************************************************************************//**
+ @Description A structure of parameters for specifying a MAC.
+*//***************************************************************************/
+typedef _Packed struct
+{
+ t_FmIpcMacParams macParams;
+ uint16_t maxFrameLength;
+} _PackedType t_FmIpcMacMaxFrameParams;
+
+/**************************************************************************//**
+ @Description FM physical Address
+*//***************************************************************************/
+typedef _Packed struct t_FmIpcPhysAddr
+{
+ volatile uint8_t high;
+ volatile uint32_t low;
+} _PackedType t_FmIpcPhysAddr;
+
+
+typedef _Packed struct t_FmIpcPortOutInitParams {
+ uint8_t numOfTasks; /**< OUT */
+ uint8_t numOfExtraTasks; /**< OUT */
+ uint8_t numOfOpenDmas; /**< OUT */
+ uint8_t numOfExtraOpenDmas; /**< OUT */
+ uint32_t sizeOfFifo; /**< OUT */
+ uint32_t extraSizeOfFifo; /**< OUT */
+ t_FmIpcPhysAddr ipcPhysAddr; /**< OUT */
+} _PackedType t_FmIpcPortOutInitParams;
+
+/**************************************************************************//**
+ @Description Structure for IPC communication during FM_PORT_Init.
+*//***************************************************************************/
+typedef _Packed struct t_FmIpcPortInInitParams {
+ uint8_t hardwarePortId; /**< IN. port Id */
+ uint32_t enumPortType; /**< IN. Port type */
+ uint8_t boolIndependentMode;/**< IN. TRUE if FM Port operates in independent mode */
+ uint16_t liodnOffset; /**< IN. Port's requested resource */
+ uint8_t numOfTasks; /**< IN. Port's requested resource */
+ uint8_t numOfExtraTasks; /**< IN. Port's requested resource */
+ uint8_t numOfOpenDmas; /**< IN. Port's requested resource */
+ uint8_t numOfExtraOpenDmas; /**< IN. Port's requested resource */
+ uint32_t sizeOfFifo; /**< IN. Port's requested resource */
+ uint32_t extraSizeOfFifo; /**< IN. Port's requested resource */
+ uint8_t deqPipelineDepth; /**< IN. Port's requested resource */
+ uint16_t maxFrameLength; /**< IN. Port's max frame length. */
+ uint16_t liodnBase; /**< IN. Irrelevant for P4080 rev 1.
+ LIODN base for this port, to be
+ used together with LIODN offset. */
+} _PackedType t_FmIpcPortInInitParams;
+
+
+/**************************************************************************//**
+ @Description Structure for IPC communication between port and FM
+ regarding tasks and open DMA resources management.
+*//***************************************************************************/
+typedef _Packed struct t_FmIpcPortRsrcParams {
+ uint8_t hardwarePortId; /**< IN. port Id */
+ uint32_t val; /**< IN. Port's requested resource */
+ uint32_t extra; /**< IN. Port's requested resource */
+ uint8_t boolInitialConfig;
+} _PackedType t_FmIpcPortRsrcParams;
+
+
+/**************************************************************************//**
+ @Description Structure for IPC communication between port and FM
+ regarding tasks and open DMA resources management.
+*//***************************************************************************/
+typedef _Packed struct t_FmIpcPortFifoParams {
+ t_FmIpcPortRsrcParams rsrcParams;
+ uint32_t enumPortType;
+ uint8_t boolIndependentMode;
+ uint8_t deqPipelineDepth;
+ uint8_t numOfPools;
+ uint16_t secondLargestBufSize;
+ uint16_t largestBufSize;
+ uint8_t boolInitialConfig;
+} _PackedType t_FmIpcPortFifoParams;
+
+/**************************************************************************//**
+ @Description Structure for port-FM communication during FM_PORT_Free.
+*//***************************************************************************/
+typedef _Packed struct t_FmIpcPortFreeParams {
+ uint8_t hardwarePortId; /**< IN. port Id */
+ uint32_t enumPortType; /**< IN. Port type */
+ uint8_t deqPipelineDepth; /**< IN. Port's requested resource */
+} _PackedType t_FmIpcPortFreeParams;
+
+/**************************************************************************//**
+ @Description Structure for defining DMA status
+*//***************************************************************************/
+typedef _Packed struct t_FmIpcDmaStatus {
+ uint8_t boolCmqNotEmpty; /**< Command queue is not empty */
+ uint8_t boolBusError; /**< Bus error occurred */
+ uint8_t boolReadBufEccError; /**< Double ECC error on buffer Read */
+ uint8_t boolWriteBufEccSysError; /**< Double ECC error on buffer write from system side */
+ uint8_t boolWriteBufEccFmError; /**< Double ECC error on buffer write from FM side */
+ uint8_t boolSinglePortEccError; /**< Single port ECC error from FM side */
+} _PackedType t_FmIpcDmaStatus;
+
+typedef _Packed struct t_FmIpcRegisterIntr
+{
+ uint8_t guestId; /* IN */
+ uint32_t event; /* IN */
+} _PackedType t_FmIpcRegisterIntr;
+
+typedef _Packed struct t_FmIpcIsr
+{
+ uint8_t boolErr; /* IN */
+ uint32_t pendingReg; /* IN */
+} _PackedType t_FmIpcIsr;
+
+/**************************************************************************//**
+ @Description structure for returning FM parameters
+*//***************************************************************************/
+typedef _Packed struct t_FmIpcParams {
+ uint16_t fmClkFreq; /**< OUT: FM Clock frequency */
+ uint8_t majorRev; /**< OUT: FM Major revision */
+ uint8_t minorRev; /**< OUT: FM Minor revision */
+} _PackedType t_FmIpcParams;
+
+
+/**************************************************************************//**
+ @Description structure for returning Fman Ctrl Code revision information
+*//***************************************************************************/
+typedef _Packed struct t_FmIpcFmanCtrlCodeRevisionInfo {
+ uint16_t packageRev; /**< OUT: Package revision */
+ uint8_t majorRev; /**< OUT: Major revision */
+ uint8_t minorRev; /**< OUT: Minor revision */
+} _PackedType t_FmIpcFmanCtrlCodeRevisionInfo;
+
+/**************************************************************************//**
+ @Description Structure for defining Fm number of Fman controlers
+*//***************************************************************************/
+typedef _Packed struct t_FmIpcPortNumOfFmanCtrls {
+ uint8_t hardwarePortId; /**< IN. port Id */
+ uint8_t numOfFmanCtrls; /**< IN. Port type */
+ t_FmFmanCtrl orFmanCtrl; /**< IN. fman controller for order restoration*/
+} t_FmIpcPortNumOfFmanCtrls;
+
+/**************************************************************************//**
+ @Description structure for setting Fman contriller events
+*//***************************************************************************/
+typedef _Packed struct t_FmIpcFmanEvents {
+ uint8_t eventRegId; /**< IN: Fman controller event register id */
+ uint32_t enableEvents; /**< IN/OUT: required enabled events mask */
+} _PackedType t_FmIpcFmanEvents;
+
+typedef _Packed struct t_FmIpcResourceAllocParams {
+ uint8_t guestId;
+ uint16_t base;
+ uint16_t num;
+}_PackedType t_FmIpcResourceAllocParams;
+
+typedef _Packed struct t_FmIpcVspSetPortWindow {
+ uint8_t hardwarePortId;
+ uint8_t baseStorageProfile;
+ uint8_t log2NumOfProfiles;
+}_PackedType t_FmIpcVspSetPortWindow;
+
+typedef _Packed struct t_FmIpcSetCongestionGroupPfcPriority {
+ uint32_t congestionGroupId;
+ uint8_t priorityBitMap;
+}_PackedType t_FmIpcSetCongestionGroupPfcPriority;
+
+#define FM_IPC_MAX_REPLY_BODY_SIZE 20
+#define FM_IPC_MAX_REPLY_SIZE (FM_IPC_MAX_REPLY_BODY_SIZE + sizeof(uint32_t))
+#define FM_IPC_MAX_MSG_SIZE 30
+
+typedef _Packed struct t_FmIpcMsg
+{
+ uint32_t msgId;
+ uint8_t msgBody[FM_IPC_MAX_MSG_SIZE];
+} _PackedType t_FmIpcMsg;
+
+typedef _Packed struct t_FmIpcReply
+{
+ uint32_t error;
+ uint8_t replyBody[FM_IPC_MAX_REPLY_BODY_SIZE];
+} _PackedType t_FmIpcReply;
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+/***************************************************************************/
+/************************ FRONT-END-TO-BACK-END*****************************/
+/***************************************************************************/
+
+/**************************************************************************//**
+ @Function FM_GET_TIMESTAMP_SCALE
+
+ @Description Used by FM front-end.
+
+ @Param[out] uint32_t Pointer
+*//***************************************************************************/
+#define FM_GET_TIMESTAMP_SCALE 1
+
+/**************************************************************************//**
+ @Function FM_GET_COUNTER
+
+ @Description Used by FM front-end.
+
+ @Param[in/out] t_FmIpcGetCounter Pointer
+*//***************************************************************************/
+#define FM_GET_COUNTER 2
+
+/**************************************************************************//**
+ @Function FM_GET_SET_PORT_PARAMS
+
+ @Description Used by FM front-end for the PORT module in order to set and get
+ parameters in/from master FM module on FM PORT initialization time.
+
+ @Param[in/out] t_FmIcPortInitParams Pointer
+*//***************************************************************************/
+#define FM_GET_SET_PORT_PARAMS 4
+
+/**************************************************************************//**
+ @Function FM_FREE_PORT
+
+ @Description Used by FM front-end for the PORT module when a port is freed
+ to free all FM PORT resources.
+
+ @Param[in] uint8_t Pointer
+*//***************************************************************************/
+#define FM_FREE_PORT 5
+
+/**************************************************************************//**
+ @Function FM_RESET_MAC
+
+ @Description Used by front-end for the MAC module to reset the MAC registers
+
+ @Param[in] t_FmIpcMacParams Pointer .
+*//***************************************************************************/
+#define FM_RESET_MAC 6
+
+/**************************************************************************//**
+ @Function FM_RESUME_STALLED_PORT
+
+ @Description Used by FM front-end for the PORT module in order to
+ release a stalled FM Port.
+
+ @Param[in] uint8_t Pointer
+*//***************************************************************************/
+#define FM_RESUME_STALLED_PORT 7
+
+/**************************************************************************//**
+ @Function FM_IS_PORT_STALLED
+
+ @Description Used by FM front-end for the PORT module in order to check whether
+ an FM port is stalled.
+
+ @Param[in/out] t_FmIcPortIsStalled Pointer
+*//***************************************************************************/
+#define FM_IS_PORT_STALLED 8
+
+/**************************************************************************//**
+ @Function FM_GET_PARAMS
+
+ @Description Used by FM front-end for the PORT module in order to dump
+ return FM parameters.
+
+ @Param[in] uint8_t Pointer
+*//***************************************************************************/
+#define FM_GET_PARAMS 10
+
+/**************************************************************************//**
+ @Function FM_REGISTER_INTR
+
+ @Description Used by FM front-end to register an interrupt handler to
+ be called upon interrupt for guest.
+
+ @Param[out] t_FmIpcRegisterIntr Pointer
+*//***************************************************************************/
+#define FM_REGISTER_INTR 11
+
+/**************************************************************************//**
+ @Function FM_DMA_STAT
+
+ @Description Used by FM front-end to read the FM DMA status.
+
+ @Param[out] t_FmIpcDmaStatus Pointer
+*//***************************************************************************/
+#define FM_DMA_STAT 13
+
+/**************************************************************************//**
+ @Function FM_ALLOC_FMAN_CTRL_EVENT_REG
+
+ @Description Used by FM front-end to allocate event register.
+
+ @Param[out] Event register id Pointer
+*//***************************************************************************/
+#define FM_ALLOC_FMAN_CTRL_EVENT_REG 14
+
+/**************************************************************************//**
+ @Function FM_FREE_FMAN_CTRL_EVENT_REG
+
+ @Description Used by FM front-end to free locate event register.
+
+ @Param[in] uint8_t Pointer - Event register id
+*//***************************************************************************/
+#define FM_FREE_FMAN_CTRL_EVENT_REG 15
+
+/**************************************************************************//**
+ @Function FM_SET_FMAN_CTRL_EVENTS_ENABLE
+
+ @Description Used by FM front-end to enable events in the FPM
+ Fman controller event register.
+
+ @Param[in] t_FmIpcFmanEvents Pointer
+*//***************************************************************************/
+#define FM_SET_FMAN_CTRL_EVENTS_ENABLE 16
+
+/**************************************************************************//**
+ @Function FM_SET_FMAN_CTRL_EVENTS_ENABLE
+
+ @Description Used by FM front-end to enable events in the FPM
+ Fman controller event register.
+
+ @Param[in/out] t_FmIpcFmanEvents Pointer
+*//***************************************************************************/
+#define FM_GET_FMAN_CTRL_EVENTS_ENABLE 17
+
+/**************************************************************************//**
+ @Function FM_SET_MAC_MAX_FRAME
+
+ @Description Used by FM front-end to set MAC's MTU/RTU's in
+ back-end.
+
+ @Param[in/out] t_FmIpcMacMaxFrameParams Pointer
+*//***************************************************************************/
+#define FM_SET_MAC_MAX_FRAME 18
+
+/**************************************************************************//**
+ @Function FM_GET_PHYS_MURAM_BASE
+
+ @Description Used by FM front-end in order to get MURAM base address
+
+ @Param[in/out] t_FmIpcPhysAddr Pointer
+*//***************************************************************************/
+#define FM_GET_PHYS_MURAM_BASE 19
+
+/**************************************************************************//**
+ @Function FM_MASTER_IS_ALIVE
+
+ @Description Used by FM front-end in order to verify Master is up
+
+ @Param[in/out] bool
+*//***************************************************************************/
+#define FM_MASTER_IS_ALIVE 20
+
+#define FM_ENABLE_RAM_ECC 21
+#define FM_DISABLE_RAM_ECC 22
+#define FM_SET_NUM_OF_FMAN_CTRL 23
+#define FM_SET_SIZE_OF_FIFO 24
+#define FM_SET_NUM_OF_TASKS 25
+#define FM_SET_NUM_OF_OPEN_DMAS 26
+#define FM_VSP_ALLOC 27
+#define FM_VSP_FREE 28
+#define FM_VSP_SET_PORT_WINDOW 29
+#define FM_GET_FMAN_CTRL_CODE_REV 30
+#define FM_SET_CONG_GRP_PFC_PRIO 31
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+#define FM_10G_TX_ECC_WA 100
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+/***************************************************************************/
+/************************ BACK-END-TO-FRONT-END*****************************/
+/***************************************************************************/
+
+/**************************************************************************//**
+ @Function FM_GUEST_ISR
+
+ @Description Used by FM back-end to report an interrupt to the front-end.
+
+ @Param[out] t_FmIpcIsr Pointer
+*//***************************************************************************/
+#define FM_GUEST_ISR 1
+
+
+
+/** @} */ /* end of FM_IPC_grp group */
+/** @} */ /* end of FM_grp group */
+
+
+#endif /* __FM_IPC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm_muram.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm_muram.c
new file mode 100644
index 0000000..a1cbe3f
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm_muram.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File FM_muram.c
+
+ @Description FM MURAM ...
+*//***************************************************************************/
+#include "error_ext.h"
+#include "std_ext.h"
+#include "mm_ext.h"
+#include "string_ext.h"
+#include "sprint_ext.h"
+#include "fm_muram_ext.h"
+#include "fm_common.h"
+
+
+#define __ERR_MODULE__ MODULE_FM_MURAM
+
+
+typedef struct
+{
+ t_Handle h_Mem;
+ uintptr_t baseAddr;
+ uint32_t size;
+} t_FmMuram;
+
+
+void FmMuramClear(t_Handle h_FmMuram)
+{
+ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram;
+
+ SANITY_CHECK_RETURN(h_FmMuram, E_INVALID_HANDLE);
+ IOMemSet32(UINT_TO_PTR(p_FmMuram->baseAddr), 0, p_FmMuram->size);
+}
+
+
+t_Handle FM_MURAM_ConfigAndInit(uintptr_t baseAddress, uint32_t size)
+{
+ t_Handle h_Mem;
+ t_FmMuram *p_FmMuram;
+
+ if (!baseAddress)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("baseAddress 0 is not supported"));
+ return NULL;
+ }
+
+ if (baseAddress%4)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("baseAddress not 4 bytes aligned!"));
+ return NULL;
+ }
+
+ /* Allocate FM MURAM structure */
+ p_FmMuram = (t_FmMuram *) XX_Malloc(sizeof(t_FmMuram));
+ if (!p_FmMuram)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM MURAM driver structure"));
+ return NULL;
+ }
+ memset(p_FmMuram, 0, sizeof(t_FmMuram));
+
+
+ if ((MM_Init(&h_Mem, baseAddress, size) != E_OK) || (!h_Mem))
+ {
+ XX_Free(p_FmMuram);
+ REPORT_ERROR(MAJOR, E_INVALID_HANDLE, ("FM-MURAM partition!!!"));
+ return NULL;
+ }
+
+ /* Initialize FM MURAM parameters which will be kept by the driver */
+ p_FmMuram->baseAddr = baseAddress;
+ p_FmMuram->size = size;
+ p_FmMuram->h_Mem = h_Mem;
+
+ return p_FmMuram;
+}
+
+t_Error FM_MURAM_Free(t_Handle h_FmMuram)
+{
+ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram;
+
+ if (p_FmMuram->h_Mem)
+ MM_Free(p_FmMuram->h_Mem);
+
+ XX_Free(h_FmMuram);
+
+ return E_OK;
+}
+
+void * FM_MURAM_AllocMem(t_Handle h_FmMuram, uint32_t size, uint32_t align)
+{
+ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram;
+ uintptr_t addr;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmMuram, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(p_FmMuram->h_Mem, E_INVALID_HANDLE, NULL);
+
+ addr = (uintptr_t)MM_Get(p_FmMuram->h_Mem, size, align ,"FM MURAM");
+
+ if (addr == ILLEGAL_BASE)
+ return NULL;
+
+ return UINT_TO_PTR(addr);
+}
+
+void * FM_MURAM_AllocMemForce(t_Handle h_FmMuram, uint64_t base, uint32_t size)
+{
+ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram;
+ uintptr_t addr;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmMuram, E_INVALID_HANDLE, NULL);
+ SANITY_CHECK_RETURN_VALUE(p_FmMuram->h_Mem, E_INVALID_HANDLE, NULL);
+
+ addr = (uintptr_t)MM_GetForce(p_FmMuram->h_Mem, base, size, "FM MURAM");
+
+ if (addr == ILLEGAL_BASE)
+ return NULL;
+
+ return UINT_TO_PTR(addr);
+}
+
+t_Error FM_MURAM_FreeMem(t_Handle h_FmMuram, void *ptr)
+{
+ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram;
+
+ SANITY_CHECK_RETURN_ERROR(h_FmMuram, E_INVALID_HANDLE);
+ SANITY_CHECK_RETURN_ERROR(p_FmMuram->h_Mem, E_INVALID_HANDLE);
+
+ if (MM_Put(p_FmMuram->h_Mem, PTR_TO_UINT(ptr)) == 0)
+ RETURN_ERROR(MINOR, E_INVALID_ADDRESS, ("memory pointer!!!"));
+
+ return E_OK;
+}
+
+uint64_t FM_MURAM_GetFreeMemSize(t_Handle h_FmMuram)
+{
+ t_FmMuram *p_FmMuram = ( t_FmMuram *)h_FmMuram;
+
+ SANITY_CHECK_RETURN_VALUE(h_FmMuram, E_INVALID_HANDLE, 0);
+ SANITY_CHECK_RETURN_VALUE(p_FmMuram->h_Mem, E_INVALID_HANDLE, 0);
+
+ return MM_GetFreeMemSize(p_FmMuram->h_Mem);
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/fman.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fman.c
new file mode 100755
index 0000000..16a0854
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fman.c
@@ -0,0 +1,1399 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+#include "fsl_fman.h"
+#include "dpaa_integration_ext.h"
+
+uint32_t fman_get_bmi_err_event(struct fman_bmi_regs *bmi_rg)
+{
+ uint32_t event, mask, force;
+
+ event = ioread32be(&bmi_rg->fmbm_ievr);
+ mask = ioread32be(&bmi_rg->fmbm_ier);
+ event &= mask;
+ /* clear the forced events */
+ force = ioread32be(&bmi_rg->fmbm_ifr);
+ if (force & event)
+ iowrite32be(force & ~event, &bmi_rg->fmbm_ifr);
+ /* clear the acknowledged events */
+ iowrite32be(event, &bmi_rg->fmbm_ievr);
+ return event;
+}
+
+uint32_t fman_get_qmi_err_event(struct fman_qmi_regs *qmi_rg)
+{
+ uint32_t event, mask, force;
+
+ event = ioread32be(&qmi_rg->fmqm_eie);
+ mask = ioread32be(&qmi_rg->fmqm_eien);
+ event &= mask;
+
+ /* clear the forced events */
+ force = ioread32be(&qmi_rg->fmqm_eif);
+ if (force & event)
+ iowrite32be(force & ~event, &qmi_rg->fmqm_eif);
+ /* clear the acknowledged events */
+ iowrite32be(event, &qmi_rg->fmqm_eie);
+ return event;
+}
+
+uint32_t fman_get_dma_com_id(struct fman_dma_regs *dma_rg)
+{
+ return ioread32be(&dma_rg->fmdmtcid);
+}
+
+uint64_t fman_get_dma_addr(struct fman_dma_regs *dma_rg)
+{
+ uint64_t addr;
+
+ addr = (uint64_t)ioread32be(&dma_rg->fmdmtal);
+ addr |= ((uint64_t)(ioread32be(&dma_rg->fmdmtah)) << 32);
+
+ return addr;
+}
+
+uint32_t fman_get_dma_err_event(struct fman_dma_regs *dma_rg)
+{
+ uint32_t status, mask;
+
+ status = ioread32be(&dma_rg->fmdmsr);
+ mask = ioread32be(&dma_rg->fmdmmr);
+
+ /* clear DMA_STATUS_BUS_ERR if mask has no DMA_MODE_BER */
+ if ((mask & DMA_MODE_BER) != DMA_MODE_BER)
+ status &= ~DMA_STATUS_BUS_ERR;
+
+ /* clear relevant bits if mask has no DMA_MODE_ECC */
+ if ((mask & DMA_MODE_ECC) != DMA_MODE_ECC)
+ status &= ~(DMA_STATUS_FM_SPDAT_ECC |
+ DMA_STATUS_READ_ECC |
+ DMA_STATUS_SYSTEM_WRITE_ECC |
+ DMA_STATUS_FM_WRITE_ECC);
+
+ /* clear set events */
+ iowrite32be(status, &dma_rg->fmdmsr);
+
+ return status;
+}
+
+uint32_t fman_get_fpm_err_event(struct fman_fpm_regs *fpm_rg)
+{
+ uint32_t event;
+
+ event = ioread32be(&fpm_rg->fmfp_ee);
+ /* clear the all occurred events */
+ iowrite32be(event, &fpm_rg->fmfp_ee);
+ return event;
+}
+
+uint32_t fman_get_muram_err_event(struct fman_fpm_regs *fpm_rg)
+{
+ uint32_t event, mask;
+
+ event = ioread32be(&fpm_rg->fm_rcr);
+ mask = ioread32be(&fpm_rg->fm_rie);
+
+ /* clear MURAM event bit (do not clear IRAM event) */
+ iowrite32be(event & ~FPM_RAM_IRAM_ECC, &fpm_rg->fm_rcr);
+
+ if ((mask & FPM_MURAM_ECC_ERR_EX_EN))
+ return event;
+ else
+ return 0;
+}
+
+uint32_t fman_get_iram_err_event(struct fman_fpm_regs *fpm_rg)
+{
+ uint32_t event, mask;
+
+ event = ioread32be(&fpm_rg->fm_rcr) ;
+ mask = ioread32be(&fpm_rg->fm_rie);
+ /* clear IRAM event bit (do not clear MURAM event) */
+ iowrite32be(event & ~FPM_RAM_MURAM_ECC,
+ &fpm_rg->fm_rcr);
+
+ if ((mask & FPM_IRAM_ECC_ERR_EX_EN))
+ return event;
+ else
+ return 0;
+}
+
+uint32_t fman_get_qmi_event(struct fman_qmi_regs *qmi_rg)
+{
+ uint32_t event, mask, force;
+
+ event = ioread32be(&qmi_rg->fmqm_ie);
+ mask = ioread32be(&qmi_rg->fmqm_ien);
+ event &= mask;
+ /* clear the forced events */
+ force = ioread32be(&qmi_rg->fmqm_if);
+ if (force & event)
+ iowrite32be(force & ~event, &qmi_rg->fmqm_if);
+ /* clear the acknowledged events */
+ iowrite32be(event, &qmi_rg->fmqm_ie);
+ return event;
+}
+
+void fman_enable_time_stamp(struct fman_fpm_regs *fpm_rg,
+ uint8_t count1ubit,
+ uint16_t fm_clk_freq)
+{
+ uint32_t tmp;
+ uint64_t frac;
+ uint32_t intgr;
+ uint32_t ts_freq = (uint32_t)(1 << count1ubit); /* in Mhz */
+
+ /* configure timestamp so that bit 8 will count 1 microsecond
+ * Find effective count rate at TIMESTAMP least significant bits:
+ * Effective_Count_Rate = 1MHz x 2^8 = 256MHz
+ * Find frequency ratio between effective count rate and the clock:
+ * Effective_Count_Rate / CLK e.g. for 600 MHz clock:
+ * 256/600 = 0.4266666... */
+
+ intgr = ts_freq / fm_clk_freq;
+ /* we multiply by 2^16 to keep the fraction of the division
+ * we do not div back, since we write this value as a fraction
+ * see spec */
+
+ frac = ((ts_freq << 16) - (intgr << 16) * fm_clk_freq) / fm_clk_freq;
+ /* we check remainder of the division in order to round up if not int */
+ if (((ts_freq << 16) - (intgr << 16)*fm_clk_freq) % fm_clk_freq)
+ frac++;
+
+ tmp = (intgr << FPM_TS_INT_SHIFT) | (uint16_t)frac;
+ iowrite32be(tmp, &fpm_rg->fmfp_tsc2);
+
+ /* enable timestamp with original clock */
+ iowrite32be(FPM_TS_CTL_EN, &fpm_rg->fmfp_tsc1);
+}
+
+uint32_t fman_get_fpm_error_interrupts(struct fman_fpm_regs *fpm_rg)
+{
+ return ioread32be(&fpm_rg->fm_epi);
+}
+
+
+int fman_set_erratum_10gmac_a004_wa(struct fman_fpm_regs *fpm_rg)
+{
+ int timeout = 100;
+
+ iowrite32be(0x40000000, &fpm_rg->fmfp_extc);
+
+ while ((ioread32be(&fpm_rg->fmfp_extc) & 0x40000000) && --timeout)
+ udelay(10);
+
+ if (!timeout)
+ return -EBUSY;
+ return 0;
+}
+
+void fman_set_ctrl_intr(struct fman_fpm_regs *fpm_rg,
+ uint8_t event_reg_id,
+ uint32_t enable_events)
+{
+ iowrite32be(enable_events, &fpm_rg->fmfp_cee[event_reg_id]);
+}
+
+uint32_t fman_get_ctrl_intr(struct fman_fpm_regs *fpm_rg, uint8_t event_reg_id)
+{
+ return ioread32be(&fpm_rg->fmfp_cee[event_reg_id]);
+}
+
+void fman_set_num_of_riscs_per_port(struct fman_fpm_regs *fpm_rg,
+ uint8_t port_id,
+ uint8_t num_fman_ctrls,
+ uint32_t or_fman_ctrl)
+{
+ uint32_t tmp = 0;
+
+ tmp = (uint32_t)(port_id << FPM_PORT_FM_CTL_PORTID_SHIFT);
+ /*TODO - maybe to put CTL# according to another criteria*/
+ if (num_fman_ctrls == 2)
+ tmp = FPM_PRT_FM_CTL2 | FPM_PRT_FM_CTL1;
+ /* order restoration */
+ tmp |= (or_fman_ctrl << FPM_PRC_ORA_FM_CTL_SEL_SHIFT) | or_fman_ctrl;
+
+ iowrite32be(tmp, &fpm_rg->fmfp_prc);
+}
+
+void fman_set_order_restoration_per_port(struct fman_fpm_regs *fpm_rg,
+ uint8_t port_id,
+ bool independent_mode,
+ bool is_rx_port)
+{
+ uint32_t tmp = 0;
+
+ tmp = (uint32_t)(port_id << FPM_PORT_FM_CTL_PORTID_SHIFT);
+ if (independent_mode) {
+ if (is_rx_port)
+ tmp |= (FPM_PRT_FM_CTL1 <<
+ FPM_PRC_ORA_FM_CTL_SEL_SHIFT) | FPM_PRT_FM_CTL1;
+ else
+ tmp |= (FPM_PRT_FM_CTL2 <<
+ FPM_PRC_ORA_FM_CTL_SEL_SHIFT) | FPM_PRT_FM_CTL2;
+ } else {
+ tmp |= (FPM_PRT_FM_CTL2|FPM_PRT_FM_CTL1);
+
+ /* order restoration */
+ if (port_id % 2)
+ tmp |= (FPM_PRT_FM_CTL1 <<
+ FPM_PRC_ORA_FM_CTL_SEL_SHIFT);
+ else
+ tmp |= (FPM_PRT_FM_CTL2 <<
+ FPM_PRC_ORA_FM_CTL_SEL_SHIFT);
+ }
+ iowrite32be(tmp, &fpm_rg->fmfp_prc);
+}
+
+uint8_t fman_get_qmi_deq_th(struct fman_qmi_regs *qmi_rg)
+{
+ return (uint8_t)ioread32be(&qmi_rg->fmqm_gc);
+}
+
+uint8_t fman_get_qmi_enq_th(struct fman_qmi_regs *qmi_rg)
+{
+ return (uint8_t)(ioread32be(&qmi_rg->fmqm_gc) >> 8);
+}
+
+void fman_set_qmi_enq_th(struct fman_qmi_regs *qmi_rg, uint8_t val)
+{
+ uint32_t tmp_reg;
+
+ tmp_reg = ioread32be(&qmi_rg->fmqm_gc);
+ tmp_reg &= ~QMI_CFG_ENQ_MASK;
+ tmp_reg |= ((uint32_t)val << 8);
+ iowrite32be(tmp_reg, &qmi_rg->fmqm_gc);
+}
+
+void fman_set_qmi_deq_th(struct fman_qmi_regs *qmi_rg, uint8_t val)
+{
+ uint32_t tmp_reg;
+
+ tmp_reg = ioread32be(&qmi_rg->fmqm_gc);
+ tmp_reg &= ~QMI_CFG_DEQ_MASK;
+ tmp_reg |= (uint32_t)val;
+ iowrite32be(tmp_reg, &qmi_rg->fmqm_gc);
+}
+
+void fman_qmi_disable_dispatch_limit(struct fman_fpm_regs *fpm_rg)
+{
+ iowrite32be(0, &fpm_rg->fmfp_mxd);
+}
+
+void fman_set_liodn_per_port(struct fman_rg *fman_rg, uint8_t port_id,
+ uint16_t liodn_base,
+ uint16_t liodn_ofst)
+{
+ uint32_t tmp;
+
+ if ((port_id > 63) || (port_id < 1))
+ return;
+
+ /* set LIODN base for this port */
+ tmp = ioread32be(&fman_rg->dma_rg->fmdmplr[port_id / 2]);
+ if (port_id % 2) {
+ tmp &= ~FM_LIODN_BASE_MASK;
+ tmp |= (uint32_t)liodn_base;
+ } else {
+ tmp &= ~(FM_LIODN_BASE_MASK << DMA_LIODN_SHIFT);
+ tmp |= (uint32_t)liodn_base << DMA_LIODN_SHIFT;
+ }
+ iowrite32be(tmp, &fman_rg->dma_rg->fmdmplr[port_id / 2]);
+ iowrite32be((uint32_t)liodn_ofst,
+ &fman_rg->bmi_rg->fmbm_spliodn[port_id - 1]);
+}
+
+bool fman_is_port_stalled(struct fman_fpm_regs *fpm_rg, uint8_t port_id)
+{
+ return (bool)!!(ioread32be(&fpm_rg->fmfp_ps[port_id]) & FPM_PS_STALLED);
+}
+
+void fman_resume_stalled_port(struct fman_fpm_regs *fpm_rg, uint8_t port_id)
+{
+ uint32_t tmp;
+
+ tmp = (uint32_t)((port_id << FPM_PORT_FM_CTL_PORTID_SHIFT) |
+ FPM_PRC_REALSE_STALLED);
+ iowrite32be(tmp, &fpm_rg->fmfp_prc);
+}
+
+int fman_reset_mac(struct fman_fpm_regs *fpm_rg, uint8_t mac_id, bool is_10g)
+{
+ uint32_t msk, timeout = 100;
+
+ /* Get the relevant bit mask */
+ if (is_10g) {
+ switch (mac_id) {
+ case(0):
+ msk = FPM_RSTC_10G0_RESET;
+ break;
+ case(1):
+ msk = FPM_RSTC_10G1_RESET;
+ break;
+ default:
+ return -EINVAL;
+ }
+ } else {
+ switch (mac_id) {
+ case(0):
+ msk = FPM_RSTC_1G0_RESET;
+ break;
+ case(1):
+ msk = FPM_RSTC_1G1_RESET;
+ break;
+ case(2):
+ msk = FPM_RSTC_1G2_RESET;
+ break;
+ case(3):
+ msk = FPM_RSTC_1G3_RESET;
+ break;
+ case(4):
+ msk = FPM_RSTC_1G4_RESET;
+ break;
+ case (5):
+ msk = FPM_RSTC_1G5_RESET;
+ break;
+ case (6):
+ msk = FPM_RSTC_1G6_RESET;
+ break;
+ case (7):
+ msk = FPM_RSTC_1G7_RESET;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+ /* reset */
+ iowrite32be(msk, &fpm_rg->fm_rstc);
+ while ((ioread32be(&fpm_rg->fm_rstc) & msk) && --timeout)
+ udelay(10);
+
+ if (!timeout)
+ return -EBUSY;
+ return 0;
+}
+
+uint16_t fman_get_size_of_fifo(struct fman_bmi_regs *bmi_rg, uint8_t port_id)
+{
+ uint32_t tmp_reg;
+
+ if ((port_id > 63) || (port_id < 1))
+ return 0;
+
+ tmp_reg = ioread32be(&bmi_rg->fmbm_pfs[port_id - 1]);
+ return (uint16_t)((tmp_reg & BMI_FIFO_SIZE_MASK) + 1);
+}
+
+uint32_t fman_get_total_fifo_size(struct fman_bmi_regs *bmi_rg)
+{
+ uint32_t reg, res;
+
+ reg = ioread32be(&bmi_rg->fmbm_cfg1);
+ res = (reg >> BMI_CFG1_FIFO_SIZE_SHIFT) & 0x3ff;
+ return res * FMAN_BMI_FIFO_UNITS;
+}
+
+uint16_t fman_get_size_of_extra_fifo(struct fman_bmi_regs *bmi_rg,
+ uint8_t port_id)
+{
+ uint32_t tmp_reg;
+
+ if ((port_id > 63) || (port_id < 1))
+ return 0;
+
+ tmp_reg = ioread32be(&bmi_rg->fmbm_pfs[port_id-1]);
+ return (uint16_t)((tmp_reg & BMI_EXTRA_FIFO_SIZE_MASK) >>
+ BMI_EXTRA_FIFO_SIZE_SHIFT);
+}
+
+void fman_set_size_of_fifo(struct fman_bmi_regs *bmi_rg,
+ uint8_t port_id,
+ uint32_t sz_fifo,
+ uint32_t extra_sz_fifo)
+{
+ uint32_t tmp;
+
+ if ((port_id > 63) || (port_id < 1))
+ return;
+
+ /* calculate reg */
+ tmp = (uint32_t)((sz_fifo / FMAN_BMI_FIFO_UNITS - 1) |
+ ((extra_sz_fifo / FMAN_BMI_FIFO_UNITS) <<
+ BMI_EXTRA_FIFO_SIZE_SHIFT));
+ iowrite32be(tmp, &bmi_rg->fmbm_pfs[port_id - 1]);
+}
+
+uint8_t fman_get_num_of_tasks(struct fman_bmi_regs *bmi_rg, uint8_t port_id)
+{
+ uint32_t tmp;
+
+ if ((port_id > 63) || (port_id < 1))
+ return 0;
+
+ tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]);
+ return (uint8_t)(((tmp & BMI_NUM_OF_TASKS_MASK) >>
+ BMI_NUM_OF_TASKS_SHIFT) + 1);
+}
+
+uint8_t fman_get_num_extra_tasks(struct fman_bmi_regs *bmi_rg, uint8_t port_id)
+{
+ uint32_t tmp;
+
+ if ((port_id > 63) || (port_id < 1))
+ return 0;
+
+ tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]);
+ return (uint8_t)((tmp & BMI_NUM_OF_EXTRA_TASKS_MASK) >>
+ BMI_EXTRA_NUM_OF_TASKS_SHIFT);
+}
+
+void fman_set_num_of_tasks(struct fman_bmi_regs *bmi_rg,
+ uint8_t port_id,
+ uint8_t num_tasks,
+ uint8_t num_extra_tasks)
+{
+ uint32_t tmp;
+
+ if ((port_id > 63) || (port_id < 1))
+ return;
+
+ /* calculate reg */
+ tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]) &
+ ~(BMI_NUM_OF_TASKS_MASK | BMI_NUM_OF_EXTRA_TASKS_MASK);
+ tmp |= (uint32_t)(((num_tasks - 1) << BMI_NUM_OF_TASKS_SHIFT) |
+ (num_extra_tasks << BMI_EXTRA_NUM_OF_TASKS_SHIFT));
+ iowrite32be(tmp, &bmi_rg->fmbm_pp[port_id - 1]);
+}
+
+uint8_t fman_get_num_of_dmas(struct fman_bmi_regs *bmi_rg, uint8_t port_id)
+{
+ uint32_t tmp;
+
+ if ((port_id > 63) || (port_id < 1))
+ return 0;
+
+ tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]);
+ return (uint8_t)(((tmp & BMI_NUM_OF_DMAS_MASK) >>
+ BMI_NUM_OF_DMAS_SHIFT) + 1);
+}
+
+uint8_t fman_get_num_extra_dmas(struct fman_bmi_regs *bmi_rg, uint8_t port_id)
+{
+ uint32_t tmp;
+
+ if ((port_id > 63) || (port_id < 1))
+ return 0;
+
+ tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]);
+ return (uint8_t)((tmp & BMI_NUM_OF_EXTRA_DMAS_MASK) >>
+ BMI_EXTRA_NUM_OF_DMAS_SHIFT);
+}
+
+void fman_set_num_of_open_dmas(struct fman_bmi_regs *bmi_rg,
+ uint8_t port_id,
+ uint8_t num_open_dmas,
+ uint8_t num_extra_open_dmas,
+ uint8_t total_num_dmas)
+{
+ uint32_t tmp = 0;
+
+ if ((port_id > 63) || (port_id < 1))
+ return;
+
+ /* calculate reg */
+ tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]) &
+ ~(BMI_NUM_OF_DMAS_MASK | BMI_NUM_OF_EXTRA_DMAS_MASK);
+ tmp |= (uint32_t)(((num_open_dmas-1) << BMI_NUM_OF_DMAS_SHIFT) |
+ (num_extra_open_dmas << BMI_EXTRA_NUM_OF_DMAS_SHIFT));
+ iowrite32be(tmp, &bmi_rg->fmbm_pp[port_id - 1]);
+
+ /* update total num of DMA's with committed number of open DMAS,
+ * and max uncommitted pool. */
+ if (total_num_dmas)
+ {
+ tmp = ioread32be(&bmi_rg->fmbm_cfg2) & ~BMI_CFG2_DMAS_MASK;
+ tmp |= (uint32_t)(total_num_dmas - 1) << BMI_CFG2_DMAS_SHIFT;
+ iowrite32be(tmp, &bmi_rg->fmbm_cfg2);
+ }
+}
+
+void fman_set_vsp_window(struct fman_bmi_regs *bmi_rg,
+ uint8_t port_id,
+ uint8_t base_storage_profile,
+ uint8_t log2_num_of_profiles)
+{
+ uint32_t tmp = 0;
+ if ((port_id > 63) || (port_id < 1))
+ return;
+
+ tmp = ioread32be(&bmi_rg->fmbm_spliodn[port_id-1]);
+ tmp |= (uint32_t)((uint32_t)base_storage_profile & 0x3f) << 16;
+ tmp |= (uint32_t)log2_num_of_profiles << 28;
+ iowrite32be(tmp, &bmi_rg->fmbm_spliodn[port_id-1]);
+}
+
+void fman_set_congestion_group_pfc_priority(uint32_t *cpg_rg,
+ uint32_t congestion_group_id,
+ uint8_t priority_bit_map)
+{
+ uint32_t reg_num, offset, tmp = 0;
+
+ reg_num = (FM_PORT_NUM_OF_CONGESTION_GRPS-1-congestion_group_id)/4;
+ offset = (congestion_group_id%4)*8;
+
+ tmp = ioread32be(&cpg_rg[reg_num]);
+ tmp &= ~(0xFF<<offset);
+ tmp |= (uint32_t)priority_bit_map << offset;
+
+ iowrite32be(tmp,&cpg_rg[reg_num]);
+}
+
+/*****************************************************************************/
+/* API Init unit functions */
+/*****************************************************************************/
+void fman_defconfig(struct fman_cfg *cfg, bool is_master)
+{
+ memset(cfg, 0, sizeof(struct fman_cfg));
+
+ cfg->catastrophic_err = DEFAULT_CATASTROPHIC_ERR;
+ cfg->dma_err = DEFAULT_DMA_ERR;
+ cfg->halt_on_external_activ = DEFAULT_HALT_ON_EXTERNAL_ACTIVATION;
+ cfg->halt_on_unrecov_ecc_err = DEFAULT_HALT_ON_UNRECOVERABLE_ECC_ERROR;
+ cfg->en_iram_test_mode = FALSE;
+ cfg->en_muram_test_mode = FALSE;
+ cfg->external_ecc_rams_enable = DEFAULT_EXTERNAL_ECC_RAMS_ENABLE;
+
+ if (!is_master)
+ return;
+
+ cfg->dma_aid_override = DEFAULT_AID_OVERRIDE;
+ cfg->dma_aid_mode = DEFAULT_AID_MODE;
+ cfg->dma_comm_qtsh_clr_emer = DEFAULT_DMA_COMM_Q_LOW;
+ cfg->dma_comm_qtsh_asrt_emer = DEFAULT_DMA_COMM_Q_HIGH;
+ cfg->dma_cache_override = DEFAULT_CACHE_OVERRIDE;
+ cfg->dma_cam_num_of_entries = DEFAULT_DMA_CAM_NUM_OF_ENTRIES;
+ cfg->dma_dbg_cnt_mode = DEFAULT_DMA_DBG_CNT_MODE;
+ cfg->dma_en_emergency = DEFAULT_DMA_EN_EMERGENCY;
+ cfg->dma_sos_emergency = DEFAULT_DMA_SOS_EMERGENCY;
+ cfg->dma_watchdog = DEFAULT_DMA_WATCHDOG;
+ cfg->dma_en_emergency_smoother = DEFAULT_DMA_EN_EMERGENCY_SMOOTHER;
+ cfg->dma_emergency_switch_counter = DEFAULT_DMA_EMERGENCY_SWITCH_COUNTER;
+ cfg->disp_limit_tsh = DEFAULT_DISP_LIMIT;
+ cfg->prs_disp_tsh = DEFAULT_PRS_DISP_TH;
+ cfg->plcr_disp_tsh = DEFAULT_PLCR_DISP_TH;
+ cfg->kg_disp_tsh = DEFAULT_KG_DISP_TH;
+ cfg->bmi_disp_tsh = DEFAULT_BMI_DISP_TH;
+ cfg->qmi_enq_disp_tsh = DEFAULT_QMI_ENQ_DISP_TH;
+ cfg->qmi_deq_disp_tsh = DEFAULT_QMI_DEQ_DISP_TH;
+ cfg->fm_ctl1_disp_tsh = DEFAULT_FM_CTL1_DISP_TH;
+ cfg->fm_ctl2_disp_tsh = DEFAULT_FM_CTL2_DISP_TH;
+
+ cfg->pedantic_dma = FALSE;
+ cfg->tnum_aging_period = DEFAULT_TNUM_AGING_PERIOD;
+ cfg->dma_stop_on_bus_error = FALSE;
+ cfg->qmi_deq_option_support = FALSE;
+}
+
+void fman_regconfig(struct fman_rg *fman_rg, struct fman_cfg *cfg)
+{
+ uint32_t tmp_reg;
+
+ /* read the values from the registers as they are initialized by the HW with
+ * the required values.
+ */
+ tmp_reg = ioread32be(&fman_rg->bmi_rg->fmbm_cfg1);
+ cfg->total_fifo_size =
+ (((tmp_reg & BMI_TOTAL_FIFO_SIZE_MASK) >> BMI_CFG1_FIFO_SIZE_SHIFT) + 1) * FMAN_BMI_FIFO_UNITS;
+
+ tmp_reg = ioread32be(&fman_rg->bmi_rg->fmbm_cfg2);
+ cfg->total_num_of_tasks =
+ (uint8_t)(((tmp_reg & BMI_TOTAL_NUM_OF_TASKS_MASK) >> BMI_CFG2_TASKS_SHIFT) + 1);
+
+ tmp_reg = ioread32be(&fman_rg->dma_rg->fmdmtr);
+ cfg->dma_comm_qtsh_asrt_emer = (uint8_t)(tmp_reg >> DMA_THRESH_COMMQ_SHIFT);
+
+ tmp_reg = ioread32be(&fman_rg->dma_rg->fmdmhy);
+ cfg->dma_comm_qtsh_clr_emer = (uint8_t)(tmp_reg >> DMA_THRESH_COMMQ_SHIFT);
+
+ tmp_reg = ioread32be(&fman_rg->dma_rg->fmdmmr);
+ cfg->dma_cache_override = (enum fman_dma_cache_override)((tmp_reg & DMA_MODE_CACHE_OR_MASK) >> DMA_MODE_CACHE_OR_SHIFT);
+ cfg->dma_cam_num_of_entries = (uint8_t)((((tmp_reg & DMA_MODE_CEN_MASK) >> DMA_MODE_CEN_SHIFT) +1)*DMA_CAM_UNITS);
+ cfg->dma_aid_override = (bool)((tmp_reg & DMA_MODE_AID_OR)? TRUE:FALSE);
+ cfg->dma_dbg_cnt_mode = (enum fman_dma_dbg_cnt_mode)((tmp_reg & DMA_MODE_DBG_MASK) >> DMA_MODE_DBG_SHIFT);
+ cfg->dma_en_emergency = (bool)((tmp_reg & DMA_MODE_EB)? TRUE : FALSE);
+
+ tmp_reg = ioread32be(&fman_rg->fpm_rg->fmfp_mxd);
+ cfg->disp_limit_tsh = (uint8_t)((tmp_reg & FPM_DISP_LIMIT_MASK) >> FPM_DISP_LIMIT_SHIFT);
+
+ tmp_reg = ioread32be(&fman_rg->fpm_rg->fmfp_dist1);
+ cfg->prs_disp_tsh = (uint8_t)((tmp_reg & FPM_THR1_PRS_MASK ) >> FPM_THR1_PRS_SHIFT);
+ cfg->plcr_disp_tsh = (uint8_t)((tmp_reg & FPM_THR1_KG_MASK ) >> FPM_THR1_KG_SHIFT);
+ cfg->kg_disp_tsh = (uint8_t)((tmp_reg & FPM_THR1_PLCR_MASK ) >> FPM_THR1_PLCR_SHIFT);
+ cfg->bmi_disp_tsh = (uint8_t)((tmp_reg & FPM_THR1_BMI_MASK ) >> FPM_THR1_BMI_SHIFT);
+
+ tmp_reg = ioread32be(&fman_rg->fpm_rg->fmfp_dist2);
+ cfg->qmi_enq_disp_tsh = (uint8_t)((tmp_reg & FPM_THR2_QMI_ENQ_MASK ) >> FPM_THR2_QMI_ENQ_SHIFT);
+ cfg->qmi_deq_disp_tsh = (uint8_t)((tmp_reg & FPM_THR2_QMI_DEQ_MASK ) >> FPM_THR2_QMI_DEQ_SHIFT);
+ cfg->fm_ctl1_disp_tsh = (uint8_t)((tmp_reg & FPM_THR2_FM_CTL1_MASK ) >> FPM_THR2_FM_CTL1_SHIFT);
+ cfg->fm_ctl2_disp_tsh = (uint8_t)((tmp_reg & FPM_THR2_FM_CTL2_MASK ) >> FPM_THR2_FM_CTL2_SHIFT);
+
+ tmp_reg = ioread32be(&fman_rg->dma_rg->fmdmsetr);
+ cfg->dma_sos_emergency = tmp_reg;
+
+ tmp_reg = ioread32be(&fman_rg->dma_rg->fmdmwcr);
+ cfg->dma_watchdog = tmp_reg/cfg->clk_freq;
+
+ tmp_reg = ioread32be(&fman_rg->dma_rg->fmdmemsr);
+ cfg->dma_en_emergency_smoother = (bool)((tmp_reg & DMA_EMSR_EMSTR_MASK)? TRUE : FALSE);
+ cfg->dma_emergency_switch_counter = (tmp_reg & DMA_EMSR_EMSTR_MASK);
+}
+
+void fman_reset(struct fman_fpm_regs *fpm_rg)
+{
+ iowrite32be(FPM_RSTC_FM_RESET, &fpm_rg->fm_rstc);
+}
+
+/**************************************************************************//**
+ @Function FM_Init
+
+ @Description Initializes the FM module
+
+ @Param[in] h_Fm - FM module descriptor
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+int fman_dma_init(struct fman_dma_regs *dma_rg, struct fman_cfg *cfg)
+{
+ uint32_t tmp_reg;
+
+ /**********************/
+ /* Init DMA Registers */
+ /**********************/
+ /* clear status reg events */
+ /* oren - check!!! */
+ tmp_reg = (DMA_STATUS_BUS_ERR | DMA_STATUS_READ_ECC |
+ DMA_STATUS_SYSTEM_WRITE_ECC | DMA_STATUS_FM_WRITE_ECC);
+ iowrite32be(ioread32be(&dma_rg->fmdmsr) | tmp_reg,
+ &dma_rg->fmdmsr);
+
+ /* configure mode register */
+ tmp_reg = 0;
+ tmp_reg |= cfg->dma_cache_override << DMA_MODE_CACHE_OR_SHIFT;
+ if (cfg->dma_aid_override)
+ tmp_reg |= DMA_MODE_AID_OR;
+ if (cfg->exceptions & FMAN_EX_DMA_BUS_ERROR)
+ tmp_reg |= DMA_MODE_BER;
+ if ((cfg->exceptions & FMAN_EX_DMA_SYSTEM_WRITE_ECC) |
+ (cfg->exceptions & FMAN_EX_DMA_READ_ECC) |
+ (cfg->exceptions & FMAN_EX_DMA_FM_WRITE_ECC))
+ tmp_reg |= DMA_MODE_ECC;
+ if (cfg->dma_stop_on_bus_error)
+ tmp_reg |= DMA_MODE_SBER;
+ if(cfg->dma_axi_dbg_num_of_beats)
+ tmp_reg |= (uint32_t)(DMA_MODE_AXI_DBG_MASK &
+ ((cfg->dma_axi_dbg_num_of_beats - 1) << DMA_MODE_AXI_DBG_SHIFT));
+
+ if (cfg->dma_en_emergency) {
+ tmp_reg |= cfg->dma_emergency_bus_select;
+ tmp_reg |= cfg->dma_emergency_level << DMA_MODE_EMER_LVL_SHIFT;
+ if (cfg->dma_en_emergency_smoother)
+ iowrite32be(cfg->dma_emergency_switch_counter,
+ &dma_rg->fmdmemsr);
+ }
+ tmp_reg |= ((cfg->dma_cam_num_of_entries / DMA_CAM_UNITS) - 1) <<
+ DMA_MODE_CEN_SHIFT;
+ tmp_reg |= DMA_MODE_SECURE_PROT;
+ tmp_reg |= cfg->dma_dbg_cnt_mode << DMA_MODE_DBG_SHIFT;
+ tmp_reg |= cfg->dma_aid_mode << DMA_MODE_AID_MODE_SHIFT;
+
+ if (cfg->pedantic_dma)
+ tmp_reg |= DMA_MODE_EMER_READ;
+
+ iowrite32be(tmp_reg, &dma_rg->fmdmmr);
+
+ /* configure thresholds register */
+ tmp_reg = ((uint32_t)cfg->dma_comm_qtsh_asrt_emer <<
+ DMA_THRESH_COMMQ_SHIFT) |
+ ((uint32_t)cfg->dma_read_buf_tsh_asrt_emer <<
+ DMA_THRESH_READ_INT_BUF_SHIFT) |
+ ((uint32_t)cfg->dma_write_buf_tsh_asrt_emer);
+
+ iowrite32be(tmp_reg, &dma_rg->fmdmtr);
+
+ /* configure hysteresis register */
+ tmp_reg = ((uint32_t)cfg->dma_comm_qtsh_clr_emer <<
+ DMA_THRESH_COMMQ_SHIFT) |
+ ((uint32_t)cfg->dma_read_buf_tsh_clr_emer <<
+ DMA_THRESH_READ_INT_BUF_SHIFT) |
+ ((uint32_t)cfg->dma_write_buf_tsh_clr_emer);
+
+ iowrite32be(tmp_reg, &dma_rg->fmdmhy);
+
+ /* configure emergency threshold */
+ iowrite32be(cfg->dma_sos_emergency, &dma_rg->fmdmsetr);
+
+ /* configure Watchdog */
+ iowrite32be((cfg->dma_watchdog * cfg->clk_freq),
+ &dma_rg->fmdmwcr);
+
+ iowrite32be(cfg->cam_base_addr, &dma_rg->fmdmebcr);
+
+ return 0;
+}
+
+int fman_fpm_init(struct fman_fpm_regs *fpm_rg, struct fman_cfg *cfg)
+{
+ uint32_t tmp_reg;
+ int i;
+
+ /**********************/
+ /* Init FPM Registers */
+ /**********************/
+ tmp_reg = (uint32_t)(cfg->disp_limit_tsh << FPM_DISP_LIMIT_SHIFT);
+ iowrite32be(tmp_reg, &fpm_rg->fmfp_mxd);
+
+ tmp_reg = (((uint32_t)cfg->prs_disp_tsh << FPM_THR1_PRS_SHIFT) |
+ ((uint32_t)cfg->kg_disp_tsh << FPM_THR1_KG_SHIFT) |
+ ((uint32_t)cfg->plcr_disp_tsh << FPM_THR1_PLCR_SHIFT) |
+ ((uint32_t)cfg->bmi_disp_tsh << FPM_THR1_BMI_SHIFT));
+ iowrite32be(tmp_reg, &fpm_rg->fmfp_dist1);
+
+ tmp_reg = (((uint32_t)cfg->qmi_enq_disp_tsh << FPM_THR2_QMI_ENQ_SHIFT) |
+ ((uint32_t)cfg->qmi_deq_disp_tsh << FPM_THR2_QMI_DEQ_SHIFT) |
+ ((uint32_t)cfg->fm_ctl1_disp_tsh << FPM_THR2_FM_CTL1_SHIFT) |
+ ((uint32_t)cfg->fm_ctl2_disp_tsh << FPM_THR2_FM_CTL2_SHIFT));
+ iowrite32be(tmp_reg, &fpm_rg->fmfp_dist2);
+
+ /* define exceptions and error behavior */
+ tmp_reg = 0;
+ /* Clear events */
+ tmp_reg |= (FPM_EV_MASK_STALL | FPM_EV_MASK_DOUBLE_ECC |
+ FPM_EV_MASK_SINGLE_ECC);
+ /* enable interrupts */
+ if (cfg->exceptions & FMAN_EX_FPM_STALL_ON_TASKS)
+ tmp_reg |= FPM_EV_MASK_STALL_EN;
+ if (cfg->exceptions & FMAN_EX_FPM_SINGLE_ECC)
+ tmp_reg |= FPM_EV_MASK_SINGLE_ECC_EN;
+ if (cfg->exceptions & FMAN_EX_FPM_DOUBLE_ECC)
+ tmp_reg |= FPM_EV_MASK_DOUBLE_ECC_EN;
+ tmp_reg |= (cfg->catastrophic_err << FPM_EV_MASK_CAT_ERR_SHIFT);
+ tmp_reg |= (cfg->dma_err << FPM_EV_MASK_DMA_ERR_SHIFT);
+ if (!cfg->halt_on_external_activ)
+ tmp_reg |= FPM_EV_MASK_EXTERNAL_HALT;
+ if (!cfg->halt_on_unrecov_ecc_err)
+ tmp_reg |= FPM_EV_MASK_ECC_ERR_HALT;
+ iowrite32be(tmp_reg, &fpm_rg->fmfp_ee);
+
+ /* clear all fmCtls event registers */
+ for (i = 0; i < cfg->num_of_fman_ctrl_evnt_regs; i++)
+ iowrite32be(0xFFFFFFFF, &fpm_rg->fmfp_cev[i]);
+
+ /* RAM ECC - enable and clear events*/
+ /* first we need to clear all parser memory,
+ * as it is uninitialized and may cause ECC errors */
+ tmp_reg = 0;
+ /* event bits */
+ tmp_reg = (FPM_RAM_MURAM_ECC | FPM_RAM_IRAM_ECC);
+ /* Rams enable not effected by RCR bit, but by a COP configuration */
+ if (cfg->external_ecc_rams_enable)
+ tmp_reg |= FPM_RAM_RAMS_ECC_EN_SRC_SEL;
+
+ /* enable test mode */
+ if (cfg->en_muram_test_mode)
+ tmp_reg |= FPM_RAM_MURAM_TEST_ECC;
+ if (cfg->en_iram_test_mode)
+ tmp_reg |= FPM_RAM_IRAM_TEST_ECC;
+ iowrite32be(tmp_reg, &fpm_rg->fm_rcr);
+
+ tmp_reg = 0;
+ if (cfg->exceptions & FMAN_EX_IRAM_ECC) {
+ tmp_reg |= FPM_IRAM_ECC_ERR_EX_EN;
+ fman_enable_rams_ecc(fpm_rg);
+ }
+ if (cfg->exceptions & FMAN_EX_NURAM_ECC) {
+ tmp_reg |= FPM_MURAM_ECC_ERR_EX_EN;
+ fman_enable_rams_ecc(fpm_rg);
+ }
+ iowrite32be(tmp_reg, &fpm_rg->fm_rie);
+
+ return 0;
+}
+
+int fman_bmi_init(struct fman_bmi_regs *bmi_rg, struct fman_cfg *cfg)
+{
+ uint32_t tmp_reg;
+
+ /**********************/
+ /* Init BMI Registers */
+ /**********************/
+
+ /* define common resources */
+ tmp_reg = cfg->fifo_base_addr;
+ tmp_reg = tmp_reg / BMI_FIFO_ALIGN;
+
+ tmp_reg |= ((cfg->total_fifo_size / FMAN_BMI_FIFO_UNITS - 1) <<
+ BMI_CFG1_FIFO_SIZE_SHIFT);
+ iowrite32be(tmp_reg, &bmi_rg->fmbm_cfg1);
+
+ tmp_reg = ((uint32_t)(cfg->total_num_of_tasks - 1) <<
+ BMI_CFG2_TASKS_SHIFT);
+ /* num of DMA's will be dynamically updated when each port is set */
+ iowrite32be(tmp_reg, &bmi_rg->fmbm_cfg2);
+
+ /* define unmaskable exceptions, enable and clear events */
+ tmp_reg = 0;
+ iowrite32be(BMI_ERR_INTR_EN_LIST_RAM_ECC |
+ BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC |
+ BMI_ERR_INTR_EN_STATISTICS_RAM_ECC |
+ BMI_ERR_INTR_EN_DISPATCH_RAM_ECC,
+ &bmi_rg->fmbm_ievr);
+
+ if (cfg->exceptions & FMAN_EX_BMI_LIST_RAM_ECC)
+ tmp_reg |= BMI_ERR_INTR_EN_LIST_RAM_ECC;
+ if (cfg->exceptions & FMAN_EX_BMI_PIPELINE_ECC)
+ tmp_reg |= BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC;
+ if (cfg->exceptions & FMAN_EX_BMI_STATISTICS_RAM_ECC)
+ tmp_reg |= BMI_ERR_INTR_EN_STATISTICS_RAM_ECC;
+ if (cfg->exceptions & FMAN_EX_BMI_DISPATCH_RAM_ECC)
+ tmp_reg |= BMI_ERR_INTR_EN_DISPATCH_RAM_ECC;
+ iowrite32be(tmp_reg, &bmi_rg->fmbm_ier);
+
+ return 0;
+}
+
+int fman_qmi_init(struct fman_qmi_regs *qmi_rg, struct fman_cfg *cfg)
+{
+ uint32_t tmp_reg;
+ uint16_t period_in_fm_clocks;
+ uint8_t remainder;
+ /**********************/
+ /* Init QMI Registers */
+ /**********************/
+ /* Clear error interrupt events */
+
+ iowrite32be(QMI_ERR_INTR_EN_DOUBLE_ECC | QMI_ERR_INTR_EN_DEQ_FROM_DEF,
+ &qmi_rg->fmqm_eie);
+ tmp_reg = 0;
+ if (cfg->exceptions & FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID)
+ tmp_reg |= QMI_ERR_INTR_EN_DEQ_FROM_DEF;
+ if (cfg->exceptions & FMAN_EX_QMI_DOUBLE_ECC)
+ tmp_reg |= QMI_ERR_INTR_EN_DOUBLE_ECC;
+ /* enable events */
+ iowrite32be(tmp_reg, &qmi_rg->fmqm_eien);
+
+ if (cfg->tnum_aging_period) {
+ /* tnumAgingPeriod is in units of usec, p_FmClockFreq in Mhz */
+ period_in_fm_clocks = (uint16_t)
+ (cfg->tnum_aging_period * cfg->clk_freq);
+ /* periodInFmClocks must be a 64 multiply */
+ remainder = (uint8_t)(period_in_fm_clocks % 64);
+ if (remainder > 64)
+ tmp_reg = (uint32_t)((period_in_fm_clocks / 64) + 1);
+ else{
+ tmp_reg = (uint32_t)(period_in_fm_clocks / 64);
+ if (!tmp_reg)
+ tmp_reg = 1;
+ }
+ tmp_reg <<= QMI_TAPC_TAP;
+ iowrite32be(tmp_reg, &qmi_rg->fmqm_tapc);
+ }
+ tmp_reg = 0;
+ /* Clear interrupt events */
+ iowrite32be(QMI_INTR_EN_SINGLE_ECC, &qmi_rg->fmqm_ie);
+ if (cfg->exceptions & FMAN_EX_QMI_SINGLE_ECC)
+ tmp_reg |= QMI_INTR_EN_SINGLE_ECC;
+ /* enable events */
+ iowrite32be(tmp_reg, &qmi_rg->fmqm_ien);
+
+ return 0;
+}
+
+int fman_enable(struct fman_rg *fman_rg, struct fman_cfg *cfg)
+{
+ uint32_t cfg_reg = 0;
+
+ /**********************/
+ /* Enable all modules */
+ /**********************/
+ /* clear & enable global counters - calculate reg and save for later,
+ because it's the same reg for QMI enable */
+ cfg_reg = QMI_CFG_EN_COUNTERS;
+ if (cfg->qmi_deq_option_support)
+ cfg_reg |= (uint32_t)(((cfg->qmi_def_tnums_thresh) << 8) |
+ (uint32_t)cfg->qmi_def_tnums_thresh);
+
+ iowrite32be(BMI_INIT_START, &fman_rg->bmi_rg->fmbm_init);
+ iowrite32be(cfg_reg | QMI_CFG_ENQ_EN | QMI_CFG_DEQ_EN,
+ &fman_rg->qmi_rg->fmqm_gc);
+
+ return 0;
+}
+
+void fman_free_resources(struct fman_rg *fman_rg)
+{
+ /* disable BMI and QMI */
+ iowrite32be(0, &fman_rg->bmi_rg->fmbm_init);
+ iowrite32be(0, &fman_rg->qmi_rg->fmqm_gc);
+
+ /* release BMI resources */
+ iowrite32be(0, &fman_rg->bmi_rg->fmbm_cfg2);
+ iowrite32be(0, &fman_rg->bmi_rg->fmbm_cfg1);
+
+ /* disable ECC */
+ iowrite32be(0, &fman_rg->fpm_rg->fm_rcr);
+}
+
+/****************************************************/
+/* API Run-time Control uint functions */
+/****************************************************/
+uint32_t fman_get_normal_pending(struct fman_fpm_regs *fpm_rg)
+{
+ return ioread32be(&fpm_rg->fm_npi);
+}
+
+uint32_t fman_get_controller_event(struct fman_fpm_regs *fpm_rg, uint8_t reg_id)
+{
+ uint32_t event;
+
+ event = ioread32be(&fpm_rg->fmfp_fcev[reg_id]) &
+ ioread32be(&fpm_rg->fmfp_cee[reg_id]);
+ iowrite32be(event, &fpm_rg->fmfp_cev[reg_id]);
+
+ return event;
+}
+
+uint32_t fman_get_error_pending(struct fman_fpm_regs *fpm_rg)
+{
+ return ioread32be(&fpm_rg->fm_epi);
+}
+
+void fman_set_ports_bandwidth(struct fman_bmi_regs *bmi_rg, uint8_t *weights)
+{
+ int i;
+ uint8_t shift;
+ uint32_t tmp = 0;
+
+ for (i = 0; i < 64; i++) {
+ if (weights[i] > 1) { /* no need to write 1 since it is 0 */
+ /* Add this port to tmp_reg */
+ /* (each 8 ports result in one register)*/
+ shift = (uint8_t)(32 - 4 * ((i % 8) + 1));
+ tmp |= ((weights[i] - 1) << shift);
+ }
+ if (i % 8 == 7) { /* last in this set */
+ iowrite32be(tmp, &bmi_rg->fmbm_arb[i / 8]);
+ tmp = 0;
+ }
+ }
+}
+
+void fman_enable_rams_ecc(struct fman_fpm_regs *fpm_rg)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&fpm_rg->fm_rcr);
+ if (tmp & FPM_RAM_RAMS_ECC_EN_SRC_SEL)
+ iowrite32be(tmp | FPM_RAM_IRAM_ECC_EN,
+ &fpm_rg->fm_rcr);
+ else
+ iowrite32be(tmp | FPM_RAM_RAMS_ECC_EN |
+ FPM_RAM_IRAM_ECC_EN,
+ &fpm_rg->fm_rcr);
+}
+
+void fman_disable_rams_ecc(struct fman_fpm_regs *fpm_rg)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&fpm_rg->fm_rcr);
+ if (tmp & FPM_RAM_RAMS_ECC_EN_SRC_SEL)
+ iowrite32be(tmp & ~FPM_RAM_IRAM_ECC_EN,
+ &fpm_rg->fm_rcr);
+ else
+ iowrite32be(tmp & ~(FPM_RAM_RAMS_ECC_EN | FPM_RAM_IRAM_ECC_EN),
+ &fpm_rg->fm_rcr);
+}
+
+int fman_set_exception(struct fman_rg *fman_rg,
+ enum fman_exceptions exception,
+ bool enable)
+{
+ uint32_t tmp;
+
+ switch (exception) {
+ case(E_FMAN_EX_DMA_BUS_ERROR):
+ tmp = ioread32be(&fman_rg->dma_rg->fmdmmr);
+ if (enable)
+ tmp |= DMA_MODE_BER;
+ else
+ tmp &= ~DMA_MODE_BER;
+ /* disable bus error */
+ iowrite32be(tmp, &fman_rg->dma_rg->fmdmmr);
+ break;
+ case(E_FMAN_EX_DMA_READ_ECC):
+ case(E_FMAN_EX_DMA_SYSTEM_WRITE_ECC):
+ case(E_FMAN_EX_DMA_FM_WRITE_ECC):
+ tmp = ioread32be(&fman_rg->dma_rg->fmdmmr);
+ if (enable)
+ tmp |= DMA_MODE_ECC;
+ else
+ tmp &= ~DMA_MODE_ECC;
+ iowrite32be(tmp, &fman_rg->dma_rg->fmdmmr);
+ break;
+ case(E_FMAN_EX_FPM_STALL_ON_TASKS):
+ tmp = ioread32be(&fman_rg->fpm_rg->fmfp_ee);
+ if (enable)
+ tmp |= FPM_EV_MASK_STALL_EN;
+ else
+ tmp &= ~FPM_EV_MASK_STALL_EN;
+ iowrite32be(tmp, &fman_rg->fpm_rg->fmfp_ee);
+ break;
+ case(E_FMAN_EX_FPM_SINGLE_ECC):
+ tmp = ioread32be(&fman_rg->fpm_rg->fmfp_ee);
+ if (enable)
+ tmp |= FPM_EV_MASK_SINGLE_ECC_EN;
+ else
+ tmp &= ~FPM_EV_MASK_SINGLE_ECC_EN;
+ iowrite32be(tmp, &fman_rg->fpm_rg->fmfp_ee);
+ break;
+ case(E_FMAN_EX_FPM_DOUBLE_ECC):
+ tmp = ioread32be(&fman_rg->fpm_rg->fmfp_ee);
+ if (enable)
+ tmp |= FPM_EV_MASK_DOUBLE_ECC_EN;
+ else
+ tmp &= ~FPM_EV_MASK_DOUBLE_ECC_EN;
+ iowrite32be(tmp, &fman_rg->fpm_rg->fmfp_ee);
+ break;
+ case(E_FMAN_EX_QMI_SINGLE_ECC):
+ tmp = ioread32be(&fman_rg->qmi_rg->fmqm_ien);
+ if (enable)
+ tmp |= QMI_INTR_EN_SINGLE_ECC;
+ else
+ tmp &= ~QMI_INTR_EN_SINGLE_ECC;
+ iowrite32be(tmp, &fman_rg->qmi_rg->fmqm_ien);
+ break;
+ case(E_FMAN_EX_QMI_DOUBLE_ECC):
+ tmp = ioread32be(&fman_rg->qmi_rg->fmqm_eien);
+ if (enable)
+ tmp |= QMI_ERR_INTR_EN_DOUBLE_ECC;
+ else
+ tmp &= ~QMI_ERR_INTR_EN_DOUBLE_ECC;
+ iowrite32be(tmp, &fman_rg->qmi_rg->fmqm_eien);
+ break;
+ case(E_FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID):
+ tmp = ioread32be(&fman_rg->qmi_rg->fmqm_eien);
+ if (enable)
+ tmp |= QMI_ERR_INTR_EN_DEQ_FROM_DEF;
+ else
+ tmp &= ~QMI_ERR_INTR_EN_DEQ_FROM_DEF;
+ iowrite32be(tmp, &fman_rg->qmi_rg->fmqm_eien);
+ break;
+ case(E_FMAN_EX_BMI_LIST_RAM_ECC):
+ tmp = ioread32be(&fman_rg->bmi_rg->fmbm_ier);
+ if (enable)
+ tmp |= BMI_ERR_INTR_EN_LIST_RAM_ECC;
+ else
+ tmp &= ~BMI_ERR_INTR_EN_LIST_RAM_ECC;
+ iowrite32be(tmp, &fman_rg->bmi_rg->fmbm_ier);
+ break;
+ case(E_FMAN_EX_BMI_STORAGE_PROFILE_ECC):
+ tmp = ioread32be(&fman_rg->bmi_rg->fmbm_ier);
+ if (enable)
+ tmp |= BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC;
+ else
+ tmp &= ~BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC;
+ iowrite32be(tmp, &fman_rg->bmi_rg->fmbm_ier);
+ break;
+ case(E_FMAN_EX_BMI_STATISTICS_RAM_ECC):
+ tmp = ioread32be(&fman_rg->bmi_rg->fmbm_ier);
+ if (enable)
+ tmp |= BMI_ERR_INTR_EN_STATISTICS_RAM_ECC;
+ else
+ tmp &= ~BMI_ERR_INTR_EN_STATISTICS_RAM_ECC;
+ iowrite32be(tmp, &fman_rg->bmi_rg->fmbm_ier);
+ break;
+ case(E_FMAN_EX_BMI_DISPATCH_RAM_ECC):
+ tmp = ioread32be(&fman_rg->bmi_rg->fmbm_ier);
+ if (enable)
+ tmp |= BMI_ERR_INTR_EN_DISPATCH_RAM_ECC;
+ else
+ tmp &= ~BMI_ERR_INTR_EN_DISPATCH_RAM_ECC;
+ iowrite32be(tmp, &fman_rg->bmi_rg->fmbm_ier);
+ break;
+ case(E_FMAN_EX_IRAM_ECC):
+ tmp = ioread32be(&fman_rg->fpm_rg->fm_rie);
+ if (enable) {
+ /* enable ECC if not enabled */
+ fman_enable_rams_ecc(fman_rg->fpm_rg);
+ /* enable ECC interrupts */
+ tmp |= FPM_IRAM_ECC_ERR_EX_EN;
+ } else {
+ /* ECC mechanism may be disabled,
+ * depending on driver status */
+ fman_disable_rams_ecc(fman_rg->fpm_rg);
+ tmp &= ~FPM_IRAM_ECC_ERR_EX_EN;
+ }
+ iowrite32be(tmp, &fman_rg->fpm_rg->fm_rie);
+ break;
+ case(E_FMAN_EX_MURAM_ECC):
+ tmp = ioread32be(&fman_rg->fpm_rg->fm_rie);
+ if (enable) {
+ /* enable ECC if not enabled */
+ fman_enable_rams_ecc(fman_rg->fpm_rg);
+ /* enable ECC interrupts */
+ tmp |= FPM_MURAM_ECC_ERR_EX_EN;
+ } else {
+ /* ECC mechanism may be disabled,
+ * depending on driver status */
+ fman_disable_rams_ecc(fman_rg->fpm_rg);
+ tmp &= ~FPM_MURAM_ECC_ERR_EX_EN;
+ }
+ iowrite32be(tmp, &fman_rg->fpm_rg->fm_rie);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+void fman_get_revision(struct fman_fpm_regs *fpm_rg,
+ uint8_t *major,
+ uint8_t *minor)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&fpm_rg->fm_ip_rev_1);
+ *major = (uint8_t)((tmp & FPM_REV1_MAJOR_MASK) >> FPM_REV1_MAJOR_SHIFT);
+ *minor = (uint8_t)((tmp & FPM_REV1_MINOR_MASK) >> FPM_REV1_MINOR_SHIFT);
+
+}
+
+uint32_t fman_get_counter(struct fman_rg *fman_rg,
+ enum fman_counters reg_name)
+{
+ uint32_t ret_val;
+
+ switch (reg_name) {
+ case(E_FMAN_COUNTERS_ENQ_TOTAL_FRAME):
+ ret_val = ioread32be(&fman_rg->qmi_rg->fmqm_etfc);
+ break;
+ case(E_FMAN_COUNTERS_DEQ_TOTAL_FRAME):
+ ret_val = ioread32be(&fman_rg->qmi_rg->fmqm_dtfc);
+ break;
+ case(E_FMAN_COUNTERS_DEQ_0):
+ ret_val = ioread32be(&fman_rg->qmi_rg->fmqm_dc0);
+ break;
+ case(E_FMAN_COUNTERS_DEQ_1):
+ ret_val = ioread32be(&fman_rg->qmi_rg->fmqm_dc1);
+ break;
+ case(E_FMAN_COUNTERS_DEQ_2):
+ ret_val = ioread32be(&fman_rg->qmi_rg->fmqm_dc2);
+ break;
+ case(E_FMAN_COUNTERS_DEQ_3):
+ ret_val = ioread32be(&fman_rg->qmi_rg->fmqm_dc3);
+ break;
+ case(E_FMAN_COUNTERS_DEQ_FROM_DEFAULT):
+ ret_val = ioread32be(&fman_rg->qmi_rg->fmqm_dfdc);
+ break;
+ case(E_FMAN_COUNTERS_DEQ_FROM_CONTEXT):
+ ret_val = ioread32be(&fman_rg->qmi_rg->fmqm_dfcc);
+ break;
+ case(E_FMAN_COUNTERS_DEQ_FROM_FD):
+ ret_val = ioread32be(&fman_rg->qmi_rg->fmqm_dffc);
+ break;
+ case(E_FMAN_COUNTERS_DEQ_CONFIRM):
+ ret_val = ioread32be(&fman_rg->qmi_rg->fmqm_dcc);
+ break;
+ default:
+ ret_val = 0;
+ }
+ return ret_val;
+}
+
+int fman_modify_counter(struct fman_rg *fman_rg,
+ enum fman_counters reg_name,
+ uint32_t val)
+{
+ /* When applicable (when there is an 'enable counters' bit,
+ * check that counters are enabled */
+ switch (reg_name) {
+ case(E_FMAN_COUNTERS_ENQ_TOTAL_FRAME):
+ case(E_FMAN_COUNTERS_DEQ_TOTAL_FRAME):
+ case(E_FMAN_COUNTERS_DEQ_0):
+ case(E_FMAN_COUNTERS_DEQ_1):
+ case(E_FMAN_COUNTERS_DEQ_2):
+ case(E_FMAN_COUNTERS_DEQ_3):
+ case(E_FMAN_COUNTERS_DEQ_FROM_DEFAULT):
+ case(E_FMAN_COUNTERS_DEQ_FROM_CONTEXT):
+ case(E_FMAN_COUNTERS_DEQ_FROM_FD):
+ case(E_FMAN_COUNTERS_DEQ_CONFIRM):
+ if (!(ioread32be(&fman_rg->qmi_rg->fmqm_gc) &
+ QMI_CFG_EN_COUNTERS))
+ return -EINVAL;
+ break;
+ default:
+ break;
+ }
+ /* Set counter */
+ switch (reg_name) {
+ case(E_FMAN_COUNTERS_ENQ_TOTAL_FRAME):
+ iowrite32be(val, &fman_rg->qmi_rg->fmqm_etfc);
+ break;
+ case(E_FMAN_COUNTERS_DEQ_TOTAL_FRAME):
+ iowrite32be(val, &fman_rg->qmi_rg->fmqm_dtfc);
+ break;
+ case(E_FMAN_COUNTERS_DEQ_0):
+ iowrite32be(val, &fman_rg->qmi_rg->fmqm_dc0);
+ break;
+ case(E_FMAN_COUNTERS_DEQ_1):
+ iowrite32be(val, &fman_rg->qmi_rg->fmqm_dc1);
+ break;
+ case(E_FMAN_COUNTERS_DEQ_2):
+ iowrite32be(val, &fman_rg->qmi_rg->fmqm_dc2);
+ break;
+ case(E_FMAN_COUNTERS_DEQ_3):
+ iowrite32be(val, &fman_rg->qmi_rg->fmqm_dc3);
+ break;
+ case(E_FMAN_COUNTERS_DEQ_FROM_DEFAULT):
+ iowrite32be(val, &fman_rg->qmi_rg->fmqm_dfdc);
+ break;
+ case(E_FMAN_COUNTERS_DEQ_FROM_CONTEXT):
+ iowrite32be(val, &fman_rg->qmi_rg->fmqm_dfcc);
+ break;
+ case(E_FMAN_COUNTERS_DEQ_FROM_FD):
+ iowrite32be(val, &fman_rg->qmi_rg->fmqm_dffc);
+ break;
+ case(E_FMAN_COUNTERS_DEQ_CONFIRM):
+ iowrite32be(val, &fman_rg->qmi_rg->fmqm_dcc);
+ break;
+ case(E_FMAN_COUNTERS_SEMAPHOR_ENTRY_FULL_REJECT):
+ iowrite32be(val, &fman_rg->dma_rg->fmdmsefrc);
+ break;
+ case(E_FMAN_COUNTERS_SEMAPHOR_QUEUE_FULL_REJECT):
+ iowrite32be(val, &fman_rg->dma_rg->fmdmsqfrc);
+ break;
+ case(E_FMAN_COUNTERS_SEMAPHOR_SYNC_REJECT):
+ iowrite32be(val, &fman_rg->dma_rg->fmdmssrc);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+void fman_set_dma_emergency(struct fman_dma_regs *dma_rg,
+ bool is_write,
+ bool enable)
+{
+ uint32_t msk;
+
+ msk = (uint32_t)(is_write ? DMA_MODE_EMER_WRITE : DMA_MODE_EMER_READ);
+
+ if (enable)
+ iowrite32be(ioread32be(&dma_rg->fmdmmr) | msk,
+ &dma_rg->fmdmmr);
+ else /* disable */
+ iowrite32be(ioread32be(&dma_rg->fmdmmr) & ~msk,
+ &dma_rg->fmdmmr);
+}
+
+void fman_set_dma_ext_bus_pri(struct fman_dma_regs *dma_rg, uint32_t pri)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&dma_rg->fmdmmr) |
+ (pri << DMA_MODE_BUS_PRI_SHIFT);
+
+ iowrite32be(tmp, &dma_rg->fmdmmr);
+}
+
+uint32_t fman_get_dma_status(struct fman_dma_regs *dma_rg)
+{
+ return ioread32be(&dma_rg->fmdmsr);
+}
+
+void fman_force_intr(struct fman_rg *fman_rg,
+ enum fman_exceptions exception)
+{
+ switch (exception) {
+ case E_FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID:
+ iowrite32be(QMI_ERR_INTR_EN_DEQ_FROM_DEF,
+ &fman_rg->qmi_rg->fmqm_eif);
+ break;
+ case E_FMAN_EX_QMI_SINGLE_ECC:
+ iowrite32be(QMI_INTR_EN_SINGLE_ECC,
+ &fman_rg->qmi_rg->fmqm_if);
+ break;
+ case E_FMAN_EX_QMI_DOUBLE_ECC:
+ iowrite32be(QMI_ERR_INTR_EN_DOUBLE_ECC,
+ &fman_rg->qmi_rg->fmqm_eif);
+ break;
+ case E_FMAN_EX_BMI_LIST_RAM_ECC:
+ iowrite32be(BMI_ERR_INTR_EN_LIST_RAM_ECC,
+ &fman_rg->bmi_rg->fmbm_ifr);
+ break;
+ case E_FMAN_EX_BMI_STORAGE_PROFILE_ECC:
+ iowrite32be(BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC,
+ &fman_rg->bmi_rg->fmbm_ifr);
+ break;
+ case E_FMAN_EX_BMI_STATISTICS_RAM_ECC:
+ iowrite32be(BMI_ERR_INTR_EN_STATISTICS_RAM_ECC,
+ &fman_rg->bmi_rg->fmbm_ifr);
+ break;
+ case E_FMAN_EX_BMI_DISPATCH_RAM_ECC:
+ iowrite32be(BMI_ERR_INTR_EN_DISPATCH_RAM_ECC,
+ &fman_rg->bmi_rg->fmbm_ifr);
+ break;
+ default:
+ break;
+ }
+}
+
+bool fman_is_qmi_halt_not_busy_state(struct fman_qmi_regs *qmi_rg)
+{
+ return (bool)!!(ioread32be(&qmi_rg->fmqm_gs) & QMI_GS_HALT_NOT_BUSY);
+}
+void fman_resume(struct fman_fpm_regs *fpm_rg)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&fpm_rg->fmfp_ee);
+ /* clear tmp_reg event bits in order not to clear standing events */
+ tmp &= ~(FPM_EV_MASK_DOUBLE_ECC |
+ FPM_EV_MASK_STALL |
+ FPM_EV_MASK_SINGLE_ECC);
+ tmp |= FPM_EV_MASK_RELEASE_FM;
+
+ iowrite32be(tmp, &fpm_rg->fmfp_ee);
+}
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_common.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_common.h
new file mode 100644
index 0000000..c9c963a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_common.h
@@ -0,0 +1,1165 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_common.h
+
+ @Description FM internal structures and definitions.
+*//***************************************************************************/
+#ifndef __FM_COMMON_H
+#define __FM_COMMON_H
+
+#include "error_ext.h"
+#include "std_ext.h"
+#include "fm_pcd_ext.h"
+#include "fm_ext.h"
+#include "fm_port_ext.h"
+
+
+#define e_FM_PORT_TYPE_OH_HOST_COMMAND e_FM_PORT_TYPE_DUMMY
+
+#define CLS_PLAN_NUM_PER_GRP 8
+
+#define IP_OFFLOAD_PACKAGE_NUMBER 106
+
+
+/**************************************************************************//**
+ @Description Enum for inter-module interrupts registration
+*//***************************************************************************/
+typedef enum e_FmEventModules{
+ e_FM_MOD_PRS, /**< Parser event */
+ e_FM_MOD_KG, /**< Keygen event */
+ e_FM_MOD_PLCR, /**< Policer event */
+ e_FM_MOD_10G_MAC, /**< 10G MAC event */
+ e_FM_MOD_1G_MAC, /**< 1G MAC event */
+ e_FM_MOD_TMR, /**< Timer event */
+ e_FM_MOD_FMAN_CTRL, /**< FMAN Controller Timer event */
+ e_FM_MOD_MACSEC,
+ e_FM_MOD_DUMMY_LAST
+} e_FmEventModules;
+
+/**************************************************************************//**
+ @Description Enum for interrupts types
+*//***************************************************************************/
+typedef enum e_FmIntrType {
+ e_FM_INTR_TYPE_ERR,
+ e_FM_INTR_TYPE_NORMAL
+} e_FmIntrType;
+
+/**************************************************************************//**
+ @Description Enum for inter-module interrupts registration
+*//***************************************************************************/
+typedef enum e_FmInterModuleEvent
+{
+ e_FM_EV_PRS = 0, /**< Parser event */
+ e_FM_EV_ERR_PRS, /**< Parser error event */
+ e_FM_EV_KG, /**< Keygen event */
+ e_FM_EV_ERR_KG, /**< Keygen error event */
+ e_FM_EV_PLCR, /**< Policer event */
+ e_FM_EV_ERR_PLCR, /**< Policer error event */
+ e_FM_EV_ERR_10G_MAC0, /**< 10G MAC 0 error event */
+ e_FM_EV_ERR_10G_MAC1, /**< 10G MAC 1 error event */
+ e_FM_EV_ERR_1G_MAC0, /**< 1G MAC 0 error event */
+ e_FM_EV_ERR_1G_MAC1, /**< 1G MAC 1 error event */
+ e_FM_EV_ERR_1G_MAC2, /**< 1G MAC 2 error event */
+ e_FM_EV_ERR_1G_MAC3, /**< 1G MAC 3 error event */
+ e_FM_EV_ERR_1G_MAC4, /**< 1G MAC 4 error event */
+ e_FM_EV_ERR_1G_MAC5, /**< 1G MAC 5 error event */
+ e_FM_EV_ERR_1G_MAC6, /**< 1G MAC 6 error event */
+ e_FM_EV_ERR_1G_MAC7, /**< 1G MAC 7 error event */
+ e_FM_EV_ERR_MACSEC_MAC0,
+ e_FM_EV_TMR, /**< Timer event */
+ e_FM_EV_10G_MAC0, /**< 10G MAC 0 event (Magic packet detection)*/
+ e_FM_EV_10G_MAC1, /**< 10G MAC 1 event (Magic packet detection)*/
+ e_FM_EV_1G_MAC0, /**< 1G MAC 0 event (Magic packet detection)*/
+ e_FM_EV_1G_MAC1, /**< 1G MAC 1 event (Magic packet detection)*/
+ e_FM_EV_1G_MAC2, /**< 1G MAC 2 (Magic packet detection)*/
+ e_FM_EV_1G_MAC3, /**< 1G MAC 3 (Magic packet detection)*/
+ e_FM_EV_1G_MAC4, /**< 1G MAC 4 (Magic packet detection)*/
+ e_FM_EV_1G_MAC5, /**< 1G MAC 5 (Magic packet detection)*/
+ e_FM_EV_1G_MAC6, /**< 1G MAC 6 (Magic packet detection)*/
+ e_FM_EV_1G_MAC7, /**< 1G MAC 7 (Magic packet detection)*/
+ e_FM_EV_MACSEC_MAC0, /**< MACSEC MAC 0 event */
+ e_FM_EV_FMAN_CTRL_0, /**< Fman controller event 0 */
+ e_FM_EV_FMAN_CTRL_1, /**< Fman controller event 1 */
+ e_FM_EV_FMAN_CTRL_2, /**< Fman controller event 2 */
+ e_FM_EV_FMAN_CTRL_3, /**< Fman controller event 3 */
+ e_FM_EV_DUMMY_LAST
+} e_FmInterModuleEvent;
+
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+/**************************************************************************//**
+ @Description PCD KG scheme registers
+*//***************************************************************************/
+typedef _Packed struct t_FmPcdPlcrProfileRegs {
+ volatile uint32_t fmpl_pemode; /* 0x090 FMPL_PEMODE - FM Policer Profile Entry Mode*/
+ volatile uint32_t fmpl_pegnia; /* 0x094 FMPL_PEGNIA - FM Policer Profile Entry GREEN Next Invoked Action*/
+ volatile uint32_t fmpl_peynia; /* 0x098 FMPL_PEYNIA - FM Policer Profile Entry YELLOW Next Invoked Action*/
+ volatile uint32_t fmpl_pernia; /* 0x09C FMPL_PERNIA - FM Policer Profile Entry RED Next Invoked Action*/
+ volatile uint32_t fmpl_pecir; /* 0x0A0 FMPL_PECIR - FM Policer Profile Entry Committed Information Rate*/
+ volatile uint32_t fmpl_pecbs; /* 0x0A4 FMPL_PECBS - FM Policer Profile Entry Committed Burst Size*/
+ volatile uint32_t fmpl_pepepir_eir; /* 0x0A8 FMPL_PEPIR_EIR - FM Policer Profile Entry Peak/Excess Information Rate*/
+ volatile uint32_t fmpl_pepbs_ebs; /* 0x0AC FMPL_PEPBS_EBS - FM Policer Profile Entry Peak/Excess Information Rate*/
+ volatile uint32_t fmpl_pelts; /* 0x0B0 FMPL_PELTS - FM Policer Profile Entry Last TimeStamp*/
+ volatile uint32_t fmpl_pects; /* 0x0B4 FMPL_PECTS - FM Policer Profile Entry Committed Token Status*/
+ volatile uint32_t fmpl_pepts_ets; /* 0x0B8 FMPL_PEPTS_ETS - FM Policer Profile Entry Peak/Excess Token Status*/
+ volatile uint32_t fmpl_pegpc; /* 0x0BC FMPL_PEGPC - FM Policer Profile Entry GREEN Packet Counter*/
+ volatile uint32_t fmpl_peypc; /* 0x0C0 FMPL_PEYPC - FM Policer Profile Entry YELLOW Packet Counter*/
+ volatile uint32_t fmpl_perpc; /* 0x0C4 FMPL_PERPC - FM Policer Profile Entry RED Packet Counter */
+ volatile uint32_t fmpl_perypc; /* 0x0C8 FMPL_PERYPC - FM Policer Profile Entry Recolored YELLOW Packet Counter*/
+ volatile uint32_t fmpl_perrpc; /* 0x0CC FMPL_PERRPC - FM Policer Profile Entry Recolored RED Packet Counter*/
+ volatile uint32_t fmpl_res1[12]; /* 0x0D0-0x0FF Reserved */
+} _PackedType t_FmPcdPlcrProfileRegs;
+
+
+typedef _Packed struct t_FmPcdCcCapwapReassmTimeoutParams {
+ volatile uint32_t portIdAndCapwapReassmTbl;
+ volatile uint32_t fqidForTimeOutFrames;
+ volatile uint32_t timeoutRequestTime;
+}_PackedType t_FmPcdCcCapwapReassmTimeoutParams;
+
+/**************************************************************************//**
+ @Description PCD CTRL Parameters Page
+*//***************************************************************************/
+typedef _Packed struct t_FmPcdCtrlParamsPage {
+ volatile uint8_t reserved0[16];
+ volatile uint32_t iprIpv4Nia;
+ volatile uint32_t iprIpv6Nia;
+ volatile uint8_t reserved1[24];
+ volatile uint32_t ipfOptionsCounter;
+ volatile uint8_t reserved2[12];
+ volatile uint32_t misc;
+ volatile uint32_t errorsDiscardMask;
+ volatile uint32_t discardMask;
+ volatile uint8_t reserved3[180];
+} _PackedType t_FmPcdCtrlParamsPage;
+
+
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+/*for UNDER_CONSTRUCTION_FM_RMU_USE_SEC its defined in fm_ext.h*/
+typedef uint32_t t_FmFmanCtrl;
+
+#define FPM_PORT_FM_CTL1 0x00000001
+#define FPM_PORT_FM_CTL2 0x00000002
+
+
+
+typedef struct t_FmPcdCcFragScratchPoolCmdParams {
+ uint32_t numOfBuffers;
+ uint8_t bufferPoolId;
+} t_FmPcdCcFragScratchPoolCmdParams;
+
+typedef struct t_FmPcdCcIpReassmTimeoutParams {
+ bool activate;
+ uint8_t tsbs;
+ uint32_t iprcpt;
+} t_FmPcdCcIpReassmTimeoutParams;
+
+typedef struct {
+ uint8_t baseEntry;
+ uint16_t numOfClsPlanEntries;
+ uint32_t vectors[FM_PCD_MAX_NUM_OF_CLS_PLANS];
+} t_FmPcdKgInterModuleClsPlanSet;
+
+/**************************************************************************//**
+ @Description Structure for binding a port to keygen schemes.
+*//***************************************************************************/
+typedef struct t_FmPcdKgInterModuleBindPortToSchemes {
+ uint8_t hardwarePortId;
+ uint8_t netEnvId;
+ bool useClsPlan; /**< TRUE if this port uses the clsPlan mechanism */
+ uint8_t numOfSchemes;
+ uint8_t schemesIds[FM_PCD_KG_NUM_OF_SCHEMES];
+} t_FmPcdKgInterModuleBindPortToSchemes;
+
+typedef struct {
+ uint32_t nextCcNodeInfo;
+ t_List node;
+} t_CcNodeInfo;
+
+typedef struct
+{
+ t_Handle h_CcNode;
+ uint16_t index;
+ t_List node;
+}t_CcNodeInformation;
+#define CC_NODE_F_OBJECT(ptr) LIST_OBJECT(ptr, t_CcNodeInformation, node)
+
+typedef struct
+{
+ t_Handle h_Manip;
+ t_List node;
+}t_ManipInfo;
+#define CC_NEXT_NODE_F_OBJECT(ptr) LIST_OBJECT(ptr, t_CcNodeInfo, node)
+
+typedef struct {
+ uint32_t type;
+ uint8_t prOffset;
+ uint16_t dataOffset;
+ // uint8_t poolIndex;
+ uint8_t internalBufferOffset;
+ uint8_t numOfTasks;
+ uint8_t numOfExtraTasks;
+ uint8_t hardwarePortId;
+ t_FmRevisionInfo revInfo;
+ uint32_t nia;
+ uint32_t discardMask;
+} t_GetCcParams;
+
+typedef struct {
+ uint32_t type;
+ int psoSize;
+ uint32_t nia;
+ t_FmFmanCtrl orFmanCtrl;
+ bool overwrite;
+} t_SetCcParams;
+
+typedef struct {
+ t_GetCcParams getCcParams;
+ t_SetCcParams setCcParams;
+} t_FmPortGetSetCcParams;
+
+typedef struct {
+ uint32_t type;
+ bool sleep;
+} t_FmSetParams;
+
+typedef struct {
+ t_FmSetParams setParams;
+} t_FmGetSetParams;
+
+t_Error FmGetSetParams(t_Handle h_Fm, t_FmGetSetParams *p_Params);
+
+static __inline__ bool TRY_LOCK(t_Handle h_Spinlock, volatile bool *p_Flag)
+{
+ uint32_t intFlags;
+ if (h_Spinlock)
+ intFlags = XX_LockIntrSpinlock(h_Spinlock);
+ else
+ intFlags = XX_DisableAllIntr();
+
+ if (*p_Flag)
+ {
+ if (h_Spinlock)
+ XX_UnlockIntrSpinlock(h_Spinlock, intFlags);
+ else
+ XX_RestoreAllIntr(intFlags);
+ return FALSE;
+ }
+ *p_Flag = TRUE;
+
+ if (h_Spinlock)
+ XX_UnlockIntrSpinlock(h_Spinlock, intFlags);
+ else
+ XX_RestoreAllIntr(intFlags);
+
+ return TRUE;
+}
+
+#define RELEASE_LOCK(_flag) _flag = FALSE;
+
+/**************************************************************************//**
+ @Collection Defines used for manipulation CC and BMI
+ @{
+*//***************************************************************************/
+#define INTERNAL_CONTEXT_OFFSET 0x80000000
+#define OFFSET_OF_PR 0x40000000
+#define MANIP_EXTRA_SPACE 0x20000000
+#define NUM_OF_TASKS 0x10000000
+#define OFFSET_OF_DATA 0x08000000
+#define HW_PORT_ID 0x04000000
+#define FM_REV 0x02000000
+#define GET_NIA_FPNE 0x01000000
+#define GET_NIA_PNDN 0x00800000
+#define NUM_OF_EXTRA_TASKS 0x00400000
+#define DISCARD_MASK 0x00200000
+
+#define UPDATE_NIA_PNEN 0x80000000
+#define UPDATE_PSO 0x40000000
+#define UPDATE_NIA_PNDN 0x20000000
+#define UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY 0x10000000
+#define UPDATE_NIA_FENE 0x04000000
+#define UPDATE_NIA_CMNE 0x02000000
+#define UPDATE_NIA_FPNE 0x01000000
+/* @} */
+
+/**************************************************************************//**
+ @Collection Defines used for manipulation CC and CC
+ @{
+*//***************************************************************************/
+#define UPDATE_NIA_ENQ_WITHOUT_DMA 0x80000000
+#define UPDATE_CC_WITH_TREE 0x40000000
+#define UPDATE_CC_WITH_DELETE_TREE 0x20000000
+#define UPDATE_KG_NIA_CC_WA 0x10000000
+#define UPDATE_KG_OPT_MODE 0x08000000
+#define UPDATE_KG_NIA 0x04000000
+/* @} */
+
+#define UPDATE_FPM_BRKC_SLP 0x80000000
+#define FM_MAX_NUM_OF_PORTS (FM_MAX_NUM_OF_OH_PORTS + \
+ FM_MAX_NUM_OF_1G_RX_PORTS + \
+ FM_MAX_NUM_OF_10G_RX_PORTS + \
+ FM_MAX_NUM_OF_1G_TX_PORTS + \
+ FM_MAX_NUM_OF_10G_TX_PORTS)
+
+#define MODULE_NAME_SIZE 30
+#define DUMMY_PORT_ID 0
+
+#define FM_LIODN_OFFSET_MASK 0x3FF
+
+/**************************************************************************//**
+ @Description NIA Description
+*//***************************************************************************/
+#define NIA_ENG_MASK 0x007C0000
+#define NIA_AC_MASK 0x0003ffff
+
+#define NIA_ORDER_RESTOR 0x00800000
+#define NIA_ENG_FM_CTL 0x00000000
+#define NIA_ENG_PRS 0x00440000
+#define NIA_ENG_KG 0x00480000
+#define NIA_ENG_PLCR 0x004C0000
+#define NIA_ENG_BMI 0x00500000
+#define NIA_ENG_QMI_ENQ 0x00540000
+#define NIA_ENG_QMI_DEQ 0x00580000
+
+#define NIA_FM_CTL_AC_CC 0x00000006
+#define NIA_FM_CTL_AC_HC 0x0000000C
+#define NIA_FM_CTL_AC_IND_MODE_TX 0x00000008
+#define NIA_FM_CTL_AC_IND_MODE_RX 0x0000000A
+#define NIA_FM_CTL_AC_POP_TO_N_STEP 0x0000000e
+#define NIA_FM_CTL_AC_PRE_BMI_FETCH_HEADER 0x00000010
+#define NIA_FM_CTL_AC_PRE_BMI_FETCH_FULL_FRAME 0x00000018
+#define NIA_FM_CTL_AC_POST_BMI_FETCH 0x00000012
+#define NIA_FM_CTL_AC_PRE_BMI_ENQ_FRAME 0x0000001A
+#define NIA_FM_CTL_AC_PRE_BMI_DISCARD_FRAME 0x0000001E
+#define NIA_FM_CTL_AC_POST_BMI_ENQ_ORR 0x00000014
+#define NIA_FM_CTL_AC_POST_BMI_ENQ 0x00000022
+#define NIA_FM_CTL_AC_PRE_CC 0x00000020
+#define NIA_FM_CTL_AC_POST_TX 0x00000024
+/* V3 only */
+#define NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_ENQ_FRAME 0x00000028
+#define NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_DISCARD_FRAME 0x0000002A
+#define NIA_FM_CTL_AC_NO_IPACC_POP_TO_N_STEP 0x0000002C
+
+#define NIA_BMI_AC_ENQ_FRAME 0x00000002
+#define NIA_BMI_AC_TX_RELEASE 0x000002C0
+#define NIA_BMI_AC_RELEASE 0x000000C0
+#define NIA_BMI_AC_DISCARD 0x000000C1
+#define NIA_BMI_AC_TX 0x00000274
+#define NIA_BMI_AC_FETCH 0x00000208
+#define NIA_BMI_AC_MASK 0x000003FF
+
+#define NIA_KG_DIRECT 0x00000100
+#define NIA_KG_CC_EN 0x00000200
+#define NIA_PLCR_ABSOLUTE 0x00008000
+
+#define NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA 0x00000202
+
+#if defined(FM_OP_NO_VSP_NO_RELEASE_ERRATA_FMAN_A006675) || defined(FM_ERROR_VSP_NO_MATCH_SW006)
+#define GET_NIA_BMI_AC_ENQ_FRAME(h_FmPcd) \
+ (uint32_t)((FmPcdIsAdvancedOffloadSupported(h_FmPcd)) ? \
+ (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_PRE_BMI_ENQ_FRAME) : \
+ (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_ENQ_FRAME))
+#define GET_NIA_BMI_AC_DISCARD_FRAME(h_FmPcd) \
+ (uint32_t)((FmPcdIsAdvancedOffloadSupported(h_FmPcd)) ? \
+ (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_PRE_BMI_DISCARD_FRAME) : \
+ (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_DISCARD_FRAME))
+#define GET_NO_PCD_NIA_BMI_AC_ENQ_FRAME() \
+ (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_ENQ_FRAME)
+#else
+#define GET_NIA_BMI_AC_ENQ_FRAME(h_FmPcd) \
+ (uint32_t)((FmPcdIsAdvancedOffloadSupported(h_FmPcd)) ? \
+ (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_PRE_BMI_ENQ_FRAME) : \
+ (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME))
+#define GET_NIA_BMI_AC_DISCARD_FRAME(h_FmPcd) \
+ (uint32_t)((FmPcdIsAdvancedOffloadSupported(h_FmPcd)) ? \
+ (NIA_ENG_FM_CTL | NIA_FM_CTL_AC_PRE_BMI_DISCARD_FRAME) : \
+ (NIA_ENG_BMI | NIA_BMI_AC_DISCARD))
+#define GET_NO_PCD_NIA_BMI_AC_ENQ_FRAME() \
+ (NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME)
+#endif /* defined(FM_OP_NO_VSP_NO_RELEASE_ERRATA_FMAN_A006675) || ... */
+
+/**************************************************************************//**
+ @Description CTRL Parameters Page defines
+*//***************************************************************************/
+#define FM_CTL_PARAMS_PAGE_OP_FIX_EN 0x80000000
+#define FM_CTL_PARAMS_PAGE_OFFLOAD_SUPPORT_EN 0x40000000
+#define FM_CTL_PARAMS_PAGE_ALWAYS_ON 0x00000100
+
+#define FM_CTL_PARAMS_PAGE_ERROR_VSP_MASK 0x0000003f
+
+/**************************************************************************//**
+ @Description Port Id defines
+*//***************************************************************************/
+#if (DPAA_VERSION == 10)
+#define BASE_OH_PORTID 1
+#else
+#define BASE_OH_PORTID 2
+#endif /* (DPAA_VERSION == 10) */
+#define BASE_1G_RX_PORTID 8
+#define BASE_10G_RX_PORTID 0x10
+#define BASE_1G_TX_PORTID 0x28
+#define BASE_10G_TX_PORTID 0x30
+
+#define FM_PCD_PORT_OH_BASE_INDX 0
+#define FM_PCD_PORT_1G_RX_BASE_INDX (FM_PCD_PORT_OH_BASE_INDX+FM_MAX_NUM_OF_OH_PORTS)
+#define FM_PCD_PORT_10G_RX_BASE_INDX (FM_PCD_PORT_1G_RX_BASE_INDX+FM_MAX_NUM_OF_1G_RX_PORTS)
+#define FM_PCD_PORT_1G_TX_BASE_INDX (FM_PCD_PORT_10G_RX_BASE_INDX+FM_MAX_NUM_OF_10G_RX_PORTS)
+#define FM_PCD_PORT_10G_TX_BASE_INDX (FM_PCD_PORT_1G_TX_BASE_INDX+FM_MAX_NUM_OF_1G_TX_PORTS)
+
+#if (FM_MAX_NUM_OF_OH_PORTS > 0)
+#define CHECK_PORT_ID_OH_PORTS(_relativePortId) \
+ if ((_relativePortId) >= FM_MAX_NUM_OF_OH_PORTS) \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal OH_PORT port id"))
+#else
+#define CHECK_PORT_ID_OH_PORTS(_relativePortId) \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal OH_PORT port id"))
+#endif
+#if (FM_MAX_NUM_OF_1G_RX_PORTS > 0)
+#define CHECK_PORT_ID_1G_RX_PORTS(_relativePortId) \
+ if ((_relativePortId) >= FM_MAX_NUM_OF_1G_RX_PORTS) \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 1G_RX_PORT port id"))
+#else
+#define CHECK_PORT_ID_1G_RX_PORTS(_relativePortId) \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 1G_RX_PORT port id"))
+#endif
+#if (FM_MAX_NUM_OF_10G_RX_PORTS > 0)
+#define CHECK_PORT_ID_10G_RX_PORTS(_relativePortId) \
+ if ((_relativePortId) >= FM_MAX_NUM_OF_10G_RX_PORTS) \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 10G_RX_PORT port id"))
+#else
+#define CHECK_PORT_ID_10G_RX_PORTS(_relativePortId) \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 10G_RX_PORT port id"))
+#endif
+#if (FM_MAX_NUM_OF_1G_TX_PORTS > 0)
+#define CHECK_PORT_ID_1G_TX_PORTS(_relativePortId) \
+ if ((_relativePortId) >= FM_MAX_NUM_OF_1G_TX_PORTS) \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 1G_TX_PORT port id"))
+#else
+#define CHECK_PORT_ID_1G_TX_PORTS(_relativePortId) \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 1G_TX_PORT port id"))
+#endif
+#if (FM_MAX_NUM_OF_10G_TX_PORTS > 0)
+#define CHECK_PORT_ID_10G_TX_PORTS(_relativePortId) \
+ if ((_relativePortId) >= FM_MAX_NUM_OF_10G_TX_PORTS) \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 10G_TX_PORT port id"))
+#else
+#define CHECK_PORT_ID_10G_TX_PORTS(_relativePortId) \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal 10G_TX_PORT port id"))
+#endif
+
+
+#define SW_PORT_ID_TO_HW_PORT_ID(_port, _type, _relativePortId) \
+switch (_type) { \
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): \
+ case (e_FM_PORT_TYPE_OH_HOST_COMMAND): \
+ CHECK_PORT_ID_OH_PORTS(_relativePortId); \
+ _port = (uint8_t)(BASE_OH_PORTID + (_relativePortId)); \
+ break; \
+ case (e_FM_PORT_TYPE_RX): \
+ CHECK_PORT_ID_1G_RX_PORTS(_relativePortId); \
+ _port = (uint8_t)(BASE_1G_RX_PORTID + (_relativePortId)); \
+ break; \
+ case (e_FM_PORT_TYPE_RX_10G): \
+ CHECK_PORT_ID_10G_RX_PORTS(_relativePortId); \
+ _port = (uint8_t)(BASE_10G_RX_PORTID + (_relativePortId)); \
+ break; \
+ case (e_FM_PORT_TYPE_TX): \
+ CHECK_PORT_ID_1G_TX_PORTS(_relativePortId); \
+ _port = (uint8_t)(BASE_1G_TX_PORTID + (_relativePortId)); \
+ break; \
+ case (e_FM_PORT_TYPE_TX_10G): \
+ CHECK_PORT_ID_10G_TX_PORTS(_relativePortId); \
+ _port = (uint8_t)(BASE_10G_TX_PORTID + (_relativePortId)); \
+ break; \
+ default: \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal port type")); \
+ _port = 0; \
+ break; \
+}
+
+#define HW_PORT_ID_TO_SW_PORT_ID(_relativePortId, hardwarePortId) \
+{ if (((hardwarePortId) >= BASE_OH_PORTID) && \
+ ((hardwarePortId) < BASE_OH_PORTID+FM_MAX_NUM_OF_OH_PORTS)) \
+ _relativePortId = (uint8_t)((hardwarePortId)-BASE_OH_PORTID); \
+ else if (((hardwarePortId) >= BASE_10G_TX_PORTID) && \
+ ((hardwarePortId) < BASE_10G_TX_PORTID+FM_MAX_NUM_OF_10G_TX_PORTS)) \
+ _relativePortId = (uint8_t)((hardwarePortId)-BASE_10G_TX_PORTID); \
+ else if (((hardwarePortId) >= BASE_1G_TX_PORTID) && \
+ ((hardwarePortId) < BASE_1G_TX_PORTID+FM_MAX_NUM_OF_1G_TX_PORTS)) \
+ _relativePortId = (uint8_t)((hardwarePortId)-BASE_1G_TX_PORTID); \
+ else if (((hardwarePortId) >= BASE_10G_RX_PORTID) && \
+ ((hardwarePortId) < BASE_10G_RX_PORTID+FM_MAX_NUM_OF_10G_RX_PORTS)) \
+ _relativePortId = (uint8_t)((hardwarePortId)-BASE_10G_RX_PORTID); \
+ else if (((hardwarePortId) >= BASE_1G_RX_PORTID) && \
+ ((hardwarePortId) < BASE_1G_RX_PORTID+FM_MAX_NUM_OF_1G_RX_PORTS)) \
+ _relativePortId = (uint8_t)((hardwarePortId)-BASE_1G_RX_PORTID); \
+ else { \
+ _relativePortId = (uint8_t)DUMMY_PORT_ID; \
+ ASSERT_COND(TRUE); \
+ } \
+}
+
+#define HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId) \
+do { \
+ if (((hardwarePortId) >= BASE_OH_PORTID) && ((hardwarePortId) < BASE_OH_PORTID+FM_MAX_NUM_OF_OH_PORTS)) \
+ swPortIndex = (uint8_t)((hardwarePortId)-BASE_OH_PORTID+FM_PCD_PORT_OH_BASE_INDX); \
+ else if (((hardwarePortId) >= BASE_1G_RX_PORTID) && \
+ ((hardwarePortId) < BASE_1G_RX_PORTID+FM_MAX_NUM_OF_1G_RX_PORTS)) \
+ swPortIndex = (uint8_t)((hardwarePortId)-BASE_1G_RX_PORTID+FM_PCD_PORT_1G_RX_BASE_INDX); \
+ else if (((hardwarePortId) >= BASE_10G_RX_PORTID) && \
+ ((hardwarePortId) < BASE_10G_RX_PORTID+FM_MAX_NUM_OF_10G_RX_PORTS)) \
+ swPortIndex = (uint8_t)((hardwarePortId)-BASE_10G_RX_PORTID+FM_PCD_PORT_10G_RX_BASE_INDX); \
+ else if (((hardwarePortId) >= BASE_1G_TX_PORTID) && \
+ ((hardwarePortId) < BASE_1G_TX_PORTID+FM_MAX_NUM_OF_1G_TX_PORTS)) \
+ swPortIndex = (uint8_t)((hardwarePortId)-BASE_1G_TX_PORTID+FM_PCD_PORT_1G_TX_BASE_INDX); \
+ else if (((hardwarePortId) >= BASE_10G_TX_PORTID) && \
+ ((hardwarePortId) < BASE_10G_TX_PORTID+FM_MAX_NUM_OF_10G_TX_PORTS)) \
+ swPortIndex = (uint8_t)((hardwarePortId)-BASE_10G_TX_PORTID+FM_PCD_PORT_10G_TX_BASE_INDX); \
+ else ASSERT_COND(FALSE); \
+} while (0)
+
+#define SW_PORT_INDX_TO_HW_PORT_ID(hardwarePortId, swPortIndex) \
+do { \
+ if (((swPortIndex) >= FM_PCD_PORT_OH_BASE_INDX) && ((swPortIndex) < FM_PCD_PORT_1G_RX_BASE_INDX)) \
+ hardwarePortId = (uint8_t)((swPortIndex)-FM_PCD_PORT_OH_BASE_INDX+BASE_OH_PORTID); \
+ else if (((swPortIndex) >= FM_PCD_PORT_1G_RX_BASE_INDX) && ((swPortIndex) < FM_PCD_PORT_10G_RX_BASE_INDX)) \
+ hardwarePortId = (uint8_t)((swPortIndex)-FM_PCD_PORT_1G_RX_BASE_INDX+BASE_1G_RX_PORTID); \
+ else if (((swPortIndex) >= FM_PCD_PORT_10G_RX_BASE_INDX) && ((swPortIndex) < FM_MAX_NUM_OF_PORTS)) \
+ hardwarePortId = (uint8_t)((swPortIndex)-FM_PCD_PORT_10G_RX_BASE_INDX+BASE_10G_RX_PORTID); \
+ else if (((swPortIndex) >= FM_PCD_PORT_1G_TX_BASE_INDX) && ((swPortIndex) < FM_PCD_PORT_10G_TX_BASE_INDX)) \
+ hardwarePortId = (uint8_t)((swPortIndex)-FM_PCD_PORT_1G_TX_BASE_INDX+BASE_1G_TX_PORTID); \
+ else if (((swPortIndex) >= FM_PCD_PORT_10G_TX_BASE_INDX) && ((swPortIndex) < FM_MAX_NUM_OF_PORTS)) \
+ hardwarePortId = (uint8_t)((swPortIndex)-FM_PCD_PORT_10G_TX_BASE_INDX+BASE_10G_TX_PORTID); \
+ else ASSERT_COND(FALSE); \
+} while (0)
+
+#define BMI_MAX_FIFO_SIZE (FM_MURAM_SIZE)
+#define BMI_FIFO_UNITS 0x100
+
+typedef struct {
+ void (*f_Isr) (t_Handle h_Arg);
+ t_Handle h_SrcHandle;
+ uint8_t guestId;
+} t_FmIntrSrc;
+
+#define ILLEGAL_HDR_NUM 0xFF
+#define NO_HDR_NUM FM_PCD_PRS_NUM_OF_HDRS
+
+#define IS_PRIVATE_HEADER(hdr) (((hdr) == HEADER_TYPE_USER_DEFINED_SHIM1) || \
+ ((hdr) == HEADER_TYPE_USER_DEFINED_SHIM2))
+#define IS_SPECIAL_HEADER(hdr) ((hdr) == HEADER_TYPE_MACSEC)
+
+#define GET_PRS_HDR_NUM(num, hdr) \
+switch (hdr) \
+{ case (HEADER_TYPE_ETH): num = 0; break; \
+ case (HEADER_TYPE_LLC_SNAP): num = 1; break; \
+ case (HEADER_TYPE_VLAN): num = 2; break; \
+ case (HEADER_TYPE_PPPoE): num = 3; break; \
+ case (HEADER_TYPE_PPP): num = 3; break; \
+ case (HEADER_TYPE_MPLS): num = 4; break; \
+ case (HEADER_TYPE_IPv4): num = 5; break; \
+ case (HEADER_TYPE_IPv6): num = 6; break; \
+ case (HEADER_TYPE_GRE): num = 7; break; \
+ case (HEADER_TYPE_MINENCAP): num = 8; break; \
+ case (HEADER_TYPE_USER_DEFINED_L3): num = 9; break; \
+ case (HEADER_TYPE_TCP): num = 10; break; \
+ case (HEADER_TYPE_UDP): num = 11; break; \
+ case (HEADER_TYPE_IPSEC_AH): \
+ case (HEADER_TYPE_IPSEC_ESP): num = 12; break; \
+ case (HEADER_TYPE_SCTP): num = 13; break; \
+ case (HEADER_TYPE_DCCP): num = 14; break; \
+ case (HEADER_TYPE_USER_DEFINED_L4): num = 15; break; \
+ case (HEADER_TYPE_USER_DEFINED_SHIM1): \
+ case (HEADER_TYPE_USER_DEFINED_SHIM2): \
+ case (HEADER_TYPE_MACSEC): \
+ num = NO_HDR_NUM; break; \
+ default: \
+ REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unsupported header for parser"));\
+ num = ILLEGAL_HDR_NUM; break; \
+}
+
+#define FM_PCD_MAX_NUM_OF_OPTIONS(clsPlanEntries) ((clsPlanEntries==256)? 8:((clsPlanEntries==128)? 7: ((clsPlanEntries==64)? 6: ((clsPlanEntries==32)? 5:0))))
+
+
+/**************************************************************************//**
+ @Description A structure for initializing a keygen classification plan group
+*//***************************************************************************/
+typedef struct t_FmPcdKgInterModuleClsPlanGrpParams {
+ uint8_t netEnvId; /* IN */
+ bool grpExists; /* OUT (unused in FmPcdKgBuildClsPlanGrp)*/
+ uint8_t clsPlanGrpId; /* OUT */
+ bool emptyClsPlanGrp; /* OUT */
+ uint8_t numOfOptions; /* OUT in FmPcdGetSetClsPlanGrpParams IN in FmPcdKgBuildClsPlanGrp*/
+ protocolOpt_t options[FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)];
+ /* OUT in FmPcdGetSetClsPlanGrpParams IN in FmPcdKgBuildClsPlanGrp*/
+ uint32_t optVectors[FM_PCD_MAX_NUM_OF_OPTIONS(FM_PCD_MAX_NUM_OF_CLS_PLANS)];
+ /* OUT in FmPcdGetSetClsPlanGrpParams IN in FmPcdKgBuildClsPlanGrp*/
+} t_FmPcdKgInterModuleClsPlanGrpParams;
+
+typedef struct t_FmPcdLock {
+ t_Handle h_Spinlock;
+ volatile bool flag;
+ t_List node;
+} t_FmPcdLock;
+#define FM_PCD_LOCK_OBJ(ptr) LIST_OBJECT(ptr, t_FmPcdLock, node)
+
+
+typedef t_Error (t_FmPortGetSetCcParamsCallback) (t_Handle h_FmPort,
+ t_FmPortGetSetCcParams *p_FmPortGetSetCcParams);
+
+
+/***********************************************************************/
+/* Common API for FM-PCD module */
+/***********************************************************************/
+t_Handle FmPcdGetHcHandle(t_Handle h_FmPcd);
+uint32_t FmPcdGetSwPrsOffset(t_Handle h_FmPcd, e_NetHeaderType hdr, uint8_t indexPerHdr);
+uint32_t FmPcdGetLcv(t_Handle h_FmPcd, uint32_t netEnvId, uint8_t hdrNum);
+uint32_t FmPcdGetMacsecLcv(t_Handle h_FmPcd, uint32_t netEnvId);
+void FmPcdIncNetEnvOwners(t_Handle h_FmPcd, uint8_t netEnvId);
+void FmPcdDecNetEnvOwners(t_Handle h_FmPcd, uint8_t netEnvId);
+uint8_t FmPcdGetNetEnvId(t_Handle h_NetEnv);
+void FmPcdPortRegister(t_Handle h_FmPcd, t_Handle h_FmPort, uint8_t hardwarePortId);
+uint32_t FmPcdLock(t_Handle h_FmPcd);
+void FmPcdUnlock(t_Handle h_FmPcd, uint32_t intFlags);
+bool FmPcdNetEnvIsHdrExist(t_Handle h_FmPcd, uint8_t netEnvId, e_NetHeaderType hdr);
+t_Error FmPcdFragHcScratchPoolInit(t_Handle h_FmPcd, uint8_t scratchBpid);
+t_Error FmPcdRegisterReassmPort(t_Handle h_FmPcd, t_Handle h_IpReasmCommonPramTbl);
+t_Error FmPcdUnregisterReassmPort(t_Handle h_FmPcd, t_Handle h_IpReasmCommonPramTbl);
+bool FmPcdIsAdvancedOffloadSupported(t_Handle h_FmPcd);
+bool FmPcdLockTryLockAll(t_Handle h_FmPcd);
+void FmPcdLockUnlockAll(t_Handle h_FmPcd);
+t_Error FmPcdHcSync(t_Handle h_FmPcd);
+t_Handle FmGetPcd(t_Handle h_Fm);
+/***********************************************************************/
+/* Common API for FM-PCD KG module */
+/***********************************************************************/
+uint8_t FmPcdKgGetClsPlanGrpBase(t_Handle h_FmPcd, uint8_t clsPlanGrp);
+uint16_t FmPcdKgGetClsPlanGrpSize(t_Handle h_FmPcd, uint8_t clsPlanGrp);
+t_Error FmPcdKgBuildClsPlanGrp(t_Handle h_FmPcd, t_FmPcdKgInterModuleClsPlanGrpParams *p_Grp, t_FmPcdKgInterModuleClsPlanSet *p_ClsPlanSet);
+
+uint8_t FmPcdKgGetSchemeId(t_Handle h_Scheme);
+#if (DPAA_VERSION >= 11)
+bool FmPcdKgGetVspe(t_Handle h_Scheme);
+#endif /* (DPAA_VERSION >= 11) */
+uint8_t FmPcdKgGetRelativeSchemeId(t_Handle h_FmPcd, uint8_t schemeId);
+void FmPcdKgDestroyClsPlanGrp(t_Handle h_FmPcd, uint8_t grpId);
+t_Error FmPcdKgCheckInvalidateSchemeSw(t_Handle h_Scheme);
+t_Error FmPcdKgBuildBindPortToSchemes(t_Handle h_FmPcd , t_FmPcdKgInterModuleBindPortToSchemes *p_BindPortToSchemes, uint32_t *p_SpReg, bool add);
+bool FmPcdKgHwSchemeIsValid(uint32_t schemeModeReg);
+uint32_t FmPcdKgBuildWriteSchemeActionReg(uint8_t schemeId, bool updateCounter);
+uint32_t FmPcdKgBuildReadSchemeActionReg(uint8_t schemeId);
+uint32_t FmPcdKgBuildWriteClsPlanBlockActionReg(uint8_t grpId);
+uint32_t FmPcdKgBuildWritePortSchemeBindActionReg(uint8_t hardwarePortId);
+uint32_t FmPcdKgBuildReadPortSchemeBindActionReg(uint8_t hardwarePortId);
+uint32_t FmPcdKgBuildWritePortClsPlanBindActionReg(uint8_t hardwarePortId);
+bool FmPcdKgIsSchemeValidSw(t_Handle h_Scheme);
+
+t_Error FmPcdKgBindPortToSchemes(t_Handle h_FmPcd , t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind);
+t_Error FmPcdKgUnbindPortToSchemes(t_Handle h_FmPcd , t_FmPcdKgInterModuleBindPortToSchemes *p_SchemeBind);
+uint32_t FmPcdKgGetRequiredAction(t_Handle h_FmPcd, uint8_t schemeId);
+uint32_t FmPcdKgGetRequiredActionFlag(t_Handle h_FmPcd, uint8_t schemeId);
+e_FmPcdDoneAction FmPcdKgGetDoneAction(t_Handle h_FmPcd, uint8_t schemeId);
+e_FmPcdEngine FmPcdKgGetNextEngine(t_Handle h_FmPcd, uint8_t schemeId);
+void FmPcdKgUpdateRequiredAction(t_Handle h_Scheme, uint32_t requiredAction);
+bool FmPcdKgIsDirectPlcr(t_Handle h_FmPcd, uint8_t schemeId);
+bool FmPcdKgIsDistrOnPlcrProfile(t_Handle h_FmPcd, uint8_t schemeId);
+uint16_t FmPcdKgGetRelativeProfileId(t_Handle h_FmPcd, uint8_t schemeId);
+t_Error FmPcdKgCcGetSetParams(t_Handle h_FmPcd, t_Handle h_Scheme, uint32_t requiredAction, uint32_t value);
+t_Error FmPcdKgSetOrBindToClsPlanGrp(t_Handle h_FmPcd, uint8_t hardwarePortId, uint8_t netEnvId, protocolOpt_t *p_OptArray, uint8_t *p_ClsPlanGrpId, bool *p_IsEmptyClsPlanGrp);
+t_Error FmPcdKgDeleteOrUnbindPortToClsPlanGrp(t_Handle h_FmPcd, uint8_t hardwarePortId, uint8_t clsPlanGrpId);
+
+/***********************************************************************/
+/* Common API for FM-PCD parser module */
+/***********************************************************************/
+t_Error FmPcdPrsIncludePortInStatistics(t_Handle p_FmPcd, uint8_t hardwarePortId, bool include);
+
+/***********************************************************************/
+/* Common API for FM-PCD policer module */
+/***********************************************************************/
+t_Error FmPcdPlcrAllocProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId, uint16_t numOfProfiles);
+t_Error FmPcdPlcrFreeProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId);
+bool FmPcdPlcrIsProfileValid(t_Handle h_FmPcd, uint16_t absoluteProfileId);
+uint16_t FmPcdPlcrGetPortProfilesBase(t_Handle h_FmPcd, uint8_t hardwarePortId);
+uint16_t FmPcdPlcrGetPortNumOfProfiles(t_Handle h_FmPcd, uint8_t hardwarePortId);
+uint32_t FmPcdPlcrBuildWritePlcrActionRegs(uint16_t absoluteProfileId);
+uint32_t FmPcdPlcrBuildCounterProfileReg(e_FmPcdPlcrProfileCounters counter);
+uint32_t FmPcdPlcrBuildWritePlcrActionReg(uint16_t absoluteProfileId);
+uint32_t FmPcdPlcrBuildReadPlcrActionReg(uint16_t absoluteProfileId);
+uint16_t FmPcdPlcrProfileGetAbsoluteId(t_Handle h_Profile);
+t_Error FmPcdPlcrGetAbsoluteIdByProfileParams(t_Handle h_FmPcd,
+ e_FmPcdProfileTypeSelection profileType,
+ t_Handle h_FmPort,
+ uint16_t relativeProfile,
+ uint16_t *p_AbsoluteId);
+void FmPcdPlcrInvalidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId);
+void FmPcdPlcrValidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId);
+bool FmPcdPlcrHwProfileIsValid(uint32_t profileModeReg);
+uint32_t FmPcdPlcrGetRequiredAction(t_Handle h_FmPcd, uint16_t absoluteProfileId);
+uint32_t FmPcdPlcrGetRequiredActionFlag(t_Handle h_FmPcd, uint16_t absoluteProfileId);
+uint32_t FmPcdPlcrBuildNiaProfileReg(bool green, bool yellow, bool red);
+void FmPcdPlcrUpdateRequiredAction(t_Handle h_FmPcd, uint16_t absoluteProfileId, uint32_t requiredAction);
+t_Error FmPcdPlcrCcGetSetParams(t_Handle h_FmPcd, uint16_t profileIndx,uint32_t requiredAction);
+
+/***********************************************************************/
+/* Common API for FM-PCD CC module */
+/***********************************************************************/
+uint8_t FmPcdCcGetParseCode(t_Handle h_CcNode);
+uint8_t FmPcdCcGetOffset(t_Handle h_CcNode);
+t_Error FmPcdCcRemoveKey(t_Handle h_FmPcd, t_Handle h_FmPcdCcNode, uint16_t keyIndex);
+t_Error FmPcdCcAddKey(t_Handle h_FmPcd, t_Handle h_CcNode, uint16_t keyIndex, uint8_t keySize, t_FmPcdCcKeyParams *p_FmPCdCcKeyParams);
+t_Error FmPcdCcModifyKey(t_Handle h_FmPcd, t_Handle h_CcNode, uint16_t keyIndex, uint8_t keySize, uint8_t *p_Key, uint8_t *p_Mask);
+t_Error FmPcdCcModifyKeyAndNextEngine(t_Handle h_FmPcd, t_Handle h_FmPcdCcNode, uint16_t keyIndex, uint8_t keySize, t_FmPcdCcKeyParams *p_FmPcdCcKeyParams);
+t_Error FmPcdCcModifyMissNextEngineParamNode(t_Handle h_FmPcd,t_Handle h_FmPcdCcNode, t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams);
+t_Error FmPcdCcModifyNextEngineParamTree(t_Handle h_FmPcd, t_Handle h_FmPcdCcTree, uint8_t grpId, uint8_t index, t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams);
+uint32_t FmPcdCcGetNodeAddrOffsetFromNodeInfo(t_Handle h_FmPcd, t_Handle h_Pointer);
+t_Handle FmPcdCcTreeGetSavedManipParams(t_Handle h_FmTree);
+void FmPcdCcTreeSetSavedManipParams(t_Handle h_FmTree, t_Handle h_SavedManipParams);
+t_Error FmPcdCcTreeAddIPR(t_Handle h_FmPcd, t_Handle h_FmTree, t_Handle h_NetEnv, t_Handle h_IpReassemblyManip, bool schemes);
+t_Error FmPcdCcBindTree(t_Handle h_FmPcd, t_Handle h_PcdParams, t_Handle h_CcTree, uint32_t *p_Offset,t_Handle h_FmPort);
+t_Error FmPcdCcUnbindTree(t_Handle h_FmPcd, t_Handle h_CcTree);
+
+/***********************************************************************/
+/* Common API for FM-PCD Manip module */
+/***********************************************************************/
+t_Error FmPcdManipUpdate(t_Handle h_FmPcd, t_Handle h_PcdParams, t_Handle h_FmPort, t_Handle h_Manip, t_Handle h_Ad, bool validate, int level, t_Handle h_FmTree, bool modify);
+
+/***********************************************************************/
+/* Common API for FM-Port module */
+/***********************************************************************/
+#if (DPAA_VERSION >= 11)
+typedef enum e_FmPortGprFuncType
+{
+ e_FM_PORT_GPR_EMPTY = 0,
+ e_FM_PORT_GPR_MURAM_PAGE
+} e_FmPortGprFuncType;
+
+t_Error FmPortSetGprFunc(t_Handle h_FmPort, e_FmPortGprFuncType gprFunc, void **p_Value);
+#endif /* DPAA_VERSION >= 11) */
+t_Error FmGetSetParams(t_Handle h_Fm, t_FmGetSetParams *p_FmGetSetParams);
+t_Error FmPortGetSetCcParams(t_Handle h_FmPort, t_FmPortGetSetCcParams *p_FmPortGetSetCcParams);
+uint8_t FmPortGetNetEnvId(t_Handle h_FmPort);
+uint8_t FmPortGetHardwarePortId(t_Handle h_FmPort);
+uint32_t FmPortGetPcdEngines(t_Handle h_FmPort);
+void FmPortPcdKgSwUnbindClsPlanGrp (t_Handle h_FmPort);
+
+
+#if (DPAA_VERSION >= 11)
+t_Error FmPcdFrmReplicUpdate(t_Handle h_FmPcd, t_Handle h_FmPort, t_Handle h_FrmReplic);
+#endif /* (DPAA_VERSION >= 11) */
+
+/**************************************************************************//**
+ @Function FmRegisterIntr
+
+ @Description Used to register an inter-module event handler to be processed by FM
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] mod The module that causes the event
+ @Param[in] modId Module id - if more than 1 instansiation of this
+ mode exists,0 otherwise.
+ @Param[in] intrType Interrupt type (error/normal) selection.
+ @Param[in] f_Isr The interrupt service routine.
+ @Param[in] h_Arg Argument to be passed to f_Isr.
+
+ @Return None.
+*//***************************************************************************/
+void FmRegisterIntr(t_Handle h_Fm,
+ e_FmEventModules mod,
+ uint8_t modId,
+ e_FmIntrType intrType,
+ void (*f_Isr) (t_Handle h_Arg),
+ t_Handle h_Arg);
+
+/**************************************************************************//**
+ @Function FmUnregisterIntr
+
+ @Description Used to un-register an inter-module event handler that was processed by FM
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] mod The module that causes the event
+ @Param[in] modId Module id - if more than 1 instansiation of this
+ mode exists,0 otherwise.
+ @Param[in] intrType Interrupt type (error/normal) selection.
+
+ @Return None.
+*//***************************************************************************/
+void FmUnregisterIntr(t_Handle h_Fm,
+ e_FmEventModules mod,
+ uint8_t modId,
+ e_FmIntrType intrType);
+
+/**************************************************************************//**
+ @Function FmRegisterFmCtlIntr
+
+ @Description Used to register to one of the fmCtl events in the FM module
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] eventRegId FmCtl event id (0-7).
+ @Param[in] f_Isr The interrupt service routine.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+void FmRegisterFmCtlIntr(t_Handle h_Fm, uint8_t eventRegId, void (*f_Isr) (t_Handle h_Fm, uint32_t event));
+
+
+/**************************************************************************//**
+ @Description enum for defining MAC types
+*//***************************************************************************/
+typedef enum e_FmMacType {
+ e_FM_MAC_10G = 0, /**< 10G MAC */
+ e_FM_MAC_1G /**< 1G MAC */
+} e_FmMacType;
+
+/**************************************************************************//**
+ @Description Structure for port-FM communication during FM_PORT_Init.
+ Fields commented 'IN' are passed by the port module to be used
+ by the FM module.
+ Fields commented 'OUT' will be filled by FM before returning to port.
+ Some fields are optional (depending on configuration) and
+ will be analized by the port and FM modules accordingly.
+*//***************************************************************************/
+typedef struct t_FmInterModulePortInitParams {
+ uint8_t hardwarePortId; /**< IN. port Id */
+ e_FmPortType portType; /**< IN. Port type */
+ bool independentMode; /**< IN. TRUE if FM Port operates in independent mode */
+ uint16_t liodnOffset; /**< IN. Port's requested resource */
+ uint8_t numOfTasks; /**< IN. Port's requested resource */
+ uint8_t numOfExtraTasks; /**< IN. Port's requested resource */
+ uint8_t numOfOpenDmas; /**< IN. Port's requested resource */
+ uint8_t numOfExtraOpenDmas; /**< IN. Port's requested resource */
+ uint32_t sizeOfFifo; /**< IN. Port's requested resource */
+ uint32_t extraSizeOfFifo; /**< IN. Port's requested resource */
+ uint8_t deqPipelineDepth; /**< IN. Port's requested resource */
+ uint16_t maxFrameLength; /**< IN. Port's max frame length. */
+ uint16_t liodnBase; /**< IN. Irrelevant for P4080 rev 1.
+ LIODN base for this port, to be
+ used together with LIODN offset. */
+ t_FmPhysAddr fmMuramPhysBaseAddr;/**< OUT. FM-MURAM physical address*/
+} t_FmInterModulePortInitParams;
+
+/**************************************************************************//**
+ @Description Structure for port-FM communication during FM_PORT_Free.
+*//***************************************************************************/
+typedef struct t_FmInterModulePortFreeParams {
+ uint8_t hardwarePortId; /**< IN. port Id */
+ e_FmPortType portType; /**< IN. Port type */
+ uint8_t deqPipelineDepth; /**< IN. Port's requested resource */
+} t_FmInterModulePortFreeParams;
+
+/**************************************************************************//**
+ @Function FmGetPcdPrsBaseAddr
+
+ @Description Get the base address of the Parser from the FM module
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return Base address.
+*//***************************************************************************/
+uintptr_t FmGetPcdPrsBaseAddr(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FmGetPcdKgBaseAddr
+
+ @Description Get the base address of the Keygen from the FM module
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return Base address.
+*//***************************************************************************/
+uintptr_t FmGetPcdKgBaseAddr(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FmGetPcdPlcrBaseAddr
+
+ @Description Get the base address of the Policer from the FM module
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return Base address.
+*//***************************************************************************/
+uintptr_t FmGetPcdPlcrBaseAddr(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FmGetMuramHandle
+
+ @Description Get the handle of the MURAM from the FM module
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return MURAM module handle.
+*//***************************************************************************/
+t_Handle FmGetMuramHandle(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FmGetPhysicalMuramBase
+
+ @Description Get the physical base address of the MURAM from the FM module
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] fmPhysAddr Physical MURAM base
+
+ @Return Physical base address.
+*//***************************************************************************/
+void FmGetPhysicalMuramBase(t_Handle h_Fm, t_FmPhysAddr *fmPhysAddr);
+
+/**************************************************************************//**
+ @Function FmGetTimeStampScale
+
+ @Description Used internally by other modules in order to get the timeStamp
+ period as requested by the application.
+
+ This function returns bit number that is incremented every 1 usec.
+ To calculate timestamp period in nsec, use
+ 1000 / (1 << FmGetTimeStampScale()).
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return Bit that counts 1 usec.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+uint32_t FmGetTimeStampScale(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FmResumeStalledPort
+
+ @Description Used internally by FM port to release a stalled port.
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] hardwarePortId HW port id.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+t_Error FmResumeStalledPort(t_Handle h_Fm, uint8_t hardwarePortId);
+
+/**************************************************************************//**
+ @Function FmIsPortStalled
+
+ @Description Used internally by FM port to read the port's status.
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] hardwarePortId HW port id.
+ @Param[in] p_IsStalled A pointer to the boolean port stalled state
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+t_Error FmIsPortStalled(t_Handle h_Fm, uint8_t hardwarePortId, bool *p_IsStalled);
+
+/**************************************************************************//**
+ @Function FmResetMac
+
+ @Description Used by MAC driver to reset the MAC registers
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] type MAC type.
+ @Param[in] macId MAC id - according to type.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+t_Error FmResetMac(t_Handle h_Fm, e_FmMacType type, uint8_t macId);
+
+/**************************************************************************//**
+ @Function FmGetClockFreq
+
+ @Description Used by MAC driver to get the FM clock frequency
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return clock-freq on success; 0 otherwise.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+uint16_t FmGetClockFreq(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FmGetId
+
+ @Description Used by PCD driver to read rhe FM id
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+uint8_t FmGetId(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FmGetSetPortParams
+
+ @Description Used by FM-PORT driver to pass and receive parameters between
+ PORT and FM modules.
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in,out] p_PortParams A structure of FM Port parameters.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+t_Error FmGetSetPortParams(t_Handle h_Fm,t_FmInterModulePortInitParams *p_PortParams);
+
+/**************************************************************************//**
+ @Function FmFreePortParams
+
+ @Description Used by FM-PORT driver to free port's resources within the FM.
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in,out] p_PortParams A structure of FM Port parameters.
+
+ @Return None.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+void FmFreePortParams(t_Handle h_Fm,t_FmInterModulePortFreeParams *p_PortParams);
+
+/**************************************************************************//**
+ @Function FmSetNumOfRiscsPerPort
+
+ @Description Used by FM-PORT driver to pass parameter between
+ PORT and FM modules for working with number of RISC..
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] hardwarePortId hardware port Id.
+ @Param[in] numOfFmanCtrls number of Fman Controllers.
+ @Param[in] orFmanCtrl Fman Controller for order restoration.
+
+ @Return None.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+t_Error FmSetNumOfRiscsPerPort(t_Handle h_Fm, uint8_t hardwarePortId, uint8_t numOfFmanCtrls, t_FmFmanCtrl orFmanCtrl);
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+/**************************************************************************//*
+ @Function FmDumpPortRegs
+
+ @Description Dumps FM port registers which are part of FM common registers
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] hardwarePortId HW port id.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only FM_Init().
+*//***************************************************************************/
+t_Error FmDumpPortRegs(t_Handle h_Fm,uint8_t hardwarePortId);
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+void FmRegisterPcd(t_Handle h_Fm, t_Handle h_FmPcd);
+void FmUnregisterPcd(t_Handle h_Fm);
+t_Handle FmGetPcdHandle(t_Handle h_Fm);
+t_Error FmEnableRamsEcc(t_Handle h_Fm);
+t_Error FmDisableRamsEcc(t_Handle h_Fm);
+void FmGetRevision(t_Handle h_Fm, t_FmRevisionInfo *p_FmRevisionInfo);
+t_Error FmAllocFmanCtrlEventReg(t_Handle h_Fm, uint8_t *p_EventId);
+void FmFreeFmanCtrlEventReg(t_Handle h_Fm, uint8_t eventId);
+void FmSetFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId, uint32_t enableEvents);
+uint32_t FmGetFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId);
+void FmRegisterFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId, void (*f_Isr) (t_Handle h_Fm, uint32_t event), t_Handle h_Arg);
+void FmUnregisterFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId);
+t_Error FmSetMacMaxFrame(t_Handle h_Fm, e_FmMacType type, uint8_t macId, uint16_t mtu);
+bool FmIsMaster(t_Handle h_Fm);
+uint8_t FmGetGuestId(t_Handle h_Fm);
+uint16_t FmGetTnumAgingPeriod(t_Handle h_Fm);
+t_Error FmSetPortPreFetchConfiguration(t_Handle h_Fm, uint8_t portNum, bool preFetchConfigured);
+t_Error FmGetPortPreFetchConfiguration(t_Handle h_Fm, uint8_t portNum, bool *p_PortConfigured, bool *p_PreFetchConfigured);
+
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+t_Error Fm10GTxEccWorkaround(t_Handle h_Fm, uint8_t macId);
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+void FmMuramClear(t_Handle h_FmMuram);
+t_Error FmSetNumOfOpenDmas(t_Handle h_Fm,
+ uint8_t hardwarePortId,
+ uint8_t *p_NumOfOpenDmas,
+ uint8_t *p_NumOfExtraOpenDmas,
+ bool initialConfig);
+t_Error FmSetNumOfTasks(t_Handle h_Fm,
+ uint8_t hardwarePortId,
+ uint8_t *p_NumOfTasks,
+ uint8_t *p_NumOfExtraTasks,
+ bool initialConfig);
+t_Error FmSetSizeOfFifo(t_Handle h_Fm,
+ uint8_t hardwarePortId,
+ uint32_t *p_SizeOfFifo,
+ uint32_t *p_ExtraSizeOfFifo,
+ bool initialConfig);
+
+t_Error FmSetCongestionGroupPFCpriority(t_Handle h_Fm,
+ uint32_t congestionGroupId,
+ uint8_t priorityBitMap);
+
+#if (DPAA_VERSION >= 11)
+t_Error FmVSPAllocForPort(t_Handle h_Fm,
+ e_FmPortType portType,
+ uint8_t portId,
+ uint8_t numOfStorageProfiles);
+
+t_Error FmVSPFreeForPort(t_Handle h_Fm,
+ e_FmPortType portType,
+ uint8_t portId);
+
+t_Error FmVSPGetAbsoluteProfileId(t_Handle h_Fm,
+ e_FmPortType portType,
+ uint8_t portId,
+ uint16_t relativeProfile,
+ uint16_t *p_AbsoluteId);
+t_Error FmVSPCheckRelativeProfile(t_Handle h_Fm,
+ e_FmPortType portType,
+ uint8_t portId,
+ uint16_t relativeProfile);
+
+uintptr_t FmGetVSPBaseAddr(t_Handle h_Fm);
+#endif /* (DPAA_VERSION >= 11) */
+
+
+#endif /* __FM_COMMON_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_hc.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_hc.h
new file mode 100644
index 0000000..f6a1bb2
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_hc.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __FM_HC_H
+#define __FM_HC_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "fsl_fman_kg.h"
+
+#define __ERR_MODULE__ MODULE_FM_PCD
+
+
+typedef struct t_FmHcParams {
+ t_Handle h_Fm;
+ t_Handle h_FmPcd;
+ t_FmPcdHcParams params;
+} t_FmHcParams;
+
+
+t_Handle FmHcConfigAndInit(t_FmHcParams *p_FmHcParams);
+void FmHcFree(t_Handle h_FmHc);
+t_Error FmHcSetFramesDataMemory(t_Handle h_FmHc,
+ uint8_t memId);
+t_Error FmHcDumpRegs(t_Handle h_FmHc);
+
+void FmHcTxConf(t_Handle h_FmHc, t_DpaaFD *p_Fd);
+
+t_Error FmHcPcdKgSetScheme(t_Handle h_FmHc,
+ t_Handle h_Scheme,
+ struct fman_kg_scheme_regs *p_SchemeRegs,
+ bool updateCounter);
+t_Error FmHcPcdKgDeleteScheme(t_Handle h_FmHc, t_Handle h_Scheme);
+t_Error FmHcPcdCcCapwapTimeoutReassm(t_Handle h_FmHc, t_FmPcdCcCapwapReassmTimeoutParams *p_CcCapwapReassmTimeoutParams );
+t_Error FmHcPcdCcIpFragScratchPollCmd(t_Handle h_FmHc, bool fill, t_FmPcdCcFragScratchPoolCmdParams *p_FmPcdCcFragScratchPoolCmdParams);
+t_Error FmHcPcdCcIpTimeoutReassm(t_Handle h_FmHc, t_FmPcdCcIpReassmTimeoutParams *p_CcIpReassmTimeoutParams, uint8_t *p_Result);
+t_Error FmHcPcdKgSetClsPlan(t_Handle h_FmHc, t_FmPcdKgInterModuleClsPlanSet *p_Set);
+t_Error FmHcPcdKgDeleteClsPlan(t_Handle h_FmHc, uint8_t clsPlanGrpId);
+
+t_Error FmHcPcdKgSetSchemeCounter(t_Handle h_FmHc, t_Handle h_Scheme, uint32_t value);
+uint32_t FmHcPcdKgGetSchemeCounter(t_Handle h_FmHc, t_Handle h_Scheme);
+
+t_Error FmHcPcdCcDoDynamicChange(t_Handle h_FmHc, uint32_t oldAdAddrOffset, uint32_t newAdAddrOffset);
+
+t_Error FmHcPcdPlcrSetProfile(t_Handle h_FmHc, t_Handle h_Profile, t_FmPcdPlcrProfileRegs *p_PlcrRegs);
+t_Error FmHcPcdPlcrDeleteProfile(t_Handle h_FmHc, t_Handle h_Profile);
+
+t_Error FmHcPcdPlcrSetProfileCounter(t_Handle h_FmHc, t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter, uint32_t value);
+uint32_t FmHcPcdPlcrGetProfileCounter(t_Handle h_FmHc, t_Handle h_Profile, e_FmPcdPlcrProfileCounters counter);
+
+t_Error FmHcKgWriteSp(t_Handle h_FmHc, uint8_t hardwarePortId, uint32_t spReg, bool add);
+t_Error FmHcKgWriteCpp(t_Handle h_FmHc, uint8_t hardwarePortId, uint32_t cppReg);
+
+t_Error FmHcPcdKgCcGetSetParams(t_Handle h_FmHc, t_Handle h_Scheme, uint32_t requiredAction, uint32_t value);
+t_Error FmHcPcdPlcrCcGetSetParams(t_Handle h_FmHc,uint16_t absoluteProfileId, uint32_t requiredAction);
+
+t_Error FmHcPcdSync(t_Handle h_FmHc);
+
+
+
+#endif /* __FM_HC_H */
diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_sp_common.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_sp_common.h
new file mode 100644
index 0000000..f9dd384
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_sp_common.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/******************************************************************************
+ @File fm_sp_common.h
+
+ @Description FM SP ...
+*//***************************************************************************/
+#ifndef __FM_SP_COMMON_H
+#define __FM_SP_COMMON_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "list_ext.h"
+
+#include "fm_ext.h"
+#include "fm_pcd_ext.h"
+#include "fsl_fman.h"
+
+/**************************************************************************//**
+ @Description defaults
+*//***************************************************************************/
+#define DEFAULT_FM_SP_bufferPrefixContent_privDataSize 0
+#define DEFAULT_FM_SP_bufferPrefixContent_passPrsResult FALSE
+#define DEFAULT_FM_SP_bufferPrefixContent_passTimeStamp FALSE
+#define DEFAULT_FM_SP_bufferPrefixContent_allOtherPCDInfo FALSE
+#define DEFAULT_FM_SP_bufferPrefixContent_dataAlign 64
+
+/**************************************************************************//**
+ @Description structure for defining internal context copying
+*//***************************************************************************/
+typedef struct
+{
+ uint16_t extBufOffset; /**< Offset in External buffer to which internal
+ context is copied to (Rx) or taken from (Tx, Op). */
+ uint8_t intContextOffset; /**< Offset within internal context to copy from
+ (Rx) or to copy to (Tx, Op). */
+ uint16_t size; /**< Internal offset size to be copied */
+} t_FmSpIntContextDataCopy;
+
+/**************************************************************************//**
+ @Description struct for defining external buffer margins
+*//***************************************************************************/
+typedef struct {
+ uint16_t startMargins; /**< Number of bytes to be left at the beginning
+ of the external buffer (must be divisible by 16) */
+ uint16_t endMargins; /**< number of bytes to be left at the end
+ of the external buffer(must be divisible by 16) */
+} t_FmSpBufMargins;
+
+typedef struct {
+ uint32_t dataOffset;
+ uint32_t prsResultOffset;
+ uint32_t timeStampOffset;
+ uint32_t hashResultOffset;
+ uint32_t pcdInfoOffset;
+ uint32_t manipOffset;
+} t_FmSpBufferOffsets;
+
+
+t_Error FmSpBuildBufferStructure(t_FmSpIntContextDataCopy *p_FmPortIntContextDataCopy,
+ t_FmBufferPrefixContent *p_BufferPrefixContent,
+ t_FmSpBufMargins *p_FmPortBufMargins,
+ t_FmSpBufferOffsets *p_FmPortBufferOffsets,
+ uint8_t *internalBufferOffset);
+
+t_Error FmSpCheckIntContextParams(t_FmSpIntContextDataCopy *p_FmSpIntContextDataCopy);
+t_Error FmSpCheckBufPoolsParams(t_FmExtPools *p_FmExtPools,
+ t_FmBackupBmPools *p_FmBackupBmPools,
+ t_FmBufPoolDepletion *p_FmBufPoolDepletion);
+t_Error FmSpCheckBufMargins(t_FmSpBufMargins *p_FmSpBufMargins);
+void FmSpSetBufPoolsInAscOrderOfBufSizes(t_FmExtPools *p_FmExtPools, uint8_t *orderedArray, uint16_t *sizesArray);
+
+t_Error FmPcdSpAllocProfiles(t_Handle h_FmPcd,
+ uint8_t hardwarePortId,
+ uint16_t numOfStorageProfiles,
+ uint16_t *base,
+ uint8_t *log2Num);
+t_Error FmPcdSpGetAbsoluteProfileId(t_Handle h_FmPcd,
+ t_Handle h_FmPort,
+ uint16_t relativeProfile,
+ uint16_t *p_AbsoluteId);
+void SpInvalidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId);
+void SpValidateProfileSw(t_Handle h_FmPcd, uint16_t absoluteProfileId);
+
+
+#endif /* __FM_SP_COMMON_H */
diff --git a/drivers/net/ethernet/freescale/fman/etc/Makefile b/drivers/net/ethernet/freescale/fman/etc/Makefile
new file mode 100644
index 0000000..5e7c382
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/etc/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+
+obj-y += fsl-ncsw-etc.o
+
+fsl-ncsw-etc-objs := mm.o memcpy.o sprint.o list.o error.o
diff --git a/drivers/net/ethernet/freescale/fman/etc/error.c b/drivers/net/ethernet/freescale/fman/etc/error.c
new file mode 100644
index 0000000..fead7f50
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/etc/error.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*
+
+ @File error.c
+
+ @Description General errors and events reporting utilities.
+*//***************************************************************************/
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+#include "error_ext.h"
+
+
+const char *dbgLevelStrings[] =
+{
+ "CRITICAL"
+ ,"MAJOR"
+ ,"MINOR"
+ ,"WARNING"
+ ,"INFO"
+ ,"TRACE"
+};
+
+
+char * ErrTypeStrings (e_ErrorType err)
+{
+ switch (err)
+ {
+ case (E_OK): return "OK";
+ case (E_WRITE_FAILED): return "Write Access Failed";
+ case (E_NO_DEVICE): return "No Device";
+ case (E_NOT_AVAILABLE): return "Resource Is Unavailable";
+ case (E_NO_MEMORY): return "Memory Allocation Failed";
+ case (E_INVALID_ADDRESS): return "Invalid Address";
+ case (E_BUSY): return "Resource Is Busy";
+ case (E_ALREADY_EXISTS): return "Resource Already Exists";
+ case (E_INVALID_OPERATION): return "Invalid Operation";
+ case (E_INVALID_VALUE): return "Invalid Value";
+ case (E_NOT_IN_RANGE): return "Value Out Of Range";
+ case (E_NOT_SUPPORTED): return "Unsupported Operation";
+ case (E_INVALID_STATE): return "Invalid State";
+ case (E_INVALID_HANDLE): return "Invalid Handle";
+ case (E_INVALID_ID): return "Invalid ID";
+ case (E_NULL_POINTER): return "Unexpected NULL Pointer";
+ case (E_INVALID_SELECTION): return "Invalid Selection";
+ case (E_INVALID_COMM_MODE): return "Invalid Communication Mode";
+ case (E_INVALID_MEMORY_TYPE): return "Invalid Memory Type";
+ case (E_INVALID_CLOCK): return "Invalid Clock";
+ case (E_CONFLICT): return "Conflict In Settings";
+ case (E_NOT_ALIGNED): return "Incorrect Alignment";
+ case (E_NOT_FOUND): return "Resource Not Found";
+ case (E_FULL): return "Resource Is Full";
+ case (E_EMPTY): return "Resource Is Empty";
+ case (E_ALREADY_FREE): return "Resource Already Free";
+ case (E_READ_FAILED): return "Read Access Failed";
+ case (E_INVALID_FRAME): return "Invalid Frame";
+ case (E_SEND_FAILED): return "Send Operation Failed";
+ case (E_RECEIVE_FAILED): return "Receive Operation Failed";
+ case (E_TIMEOUT): return "Operation Timed Out";
+ default:
+ break;
+ }
+ return NULL;
+}
+#endif /* (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) */
diff --git a/drivers/net/ethernet/freescale/fman/etc/list.c b/drivers/net/ethernet/freescale/fman/etc/list.c
new file mode 100644
index 0000000..2d044be
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/etc/list.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+
+ @File list.c
+
+ @Description Implementation of list.
+*//***************************************************************************/
+#include "std_ext.h"
+#include "list_ext.h"
+
+
+void LIST_Append(t_List *p_NewList, t_List *p_Head)
+{
+ t_List *p_First = LIST_FIRST(p_NewList);
+
+ if (p_First != p_NewList)
+ {
+ t_List *p_Last = LIST_LAST(p_NewList);
+ t_List *p_Cur = LIST_NEXT(p_Head);
+
+ LIST_PREV(p_First) = p_Head;
+ LIST_FIRST(p_Head) = p_First;
+ LIST_NEXT(p_Last) = p_Cur;
+ LIST_LAST(p_Cur) = p_Last;
+ }
+}
+
+
+int LIST_NumOfObjs(t_List *p_List)
+{
+ t_List *p_Tmp;
+ int numOfObjs = 0;
+
+ if (!LIST_IsEmpty(p_List))
+ LIST_FOR_EACH(p_Tmp, p_List)
+ numOfObjs++;
+
+ return numOfObjs;
+}
diff --git a/drivers/net/ethernet/freescale/fman/etc/memcpy.c b/drivers/net/ethernet/freescale/fman/etc/memcpy.c
new file mode 100644
index 0000000..02973e5
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/etc/memcpy.c
@@ -0,0 +1,601 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+#include "std_ext.h"
+#include "xx_ext.h"
+#include "memcpy_ext.h"
+
+
+void * MemCpy32(void* pDst,void* pSrc, uint32_t size)
+{
+ uint32_t leftAlign;
+ uint32_t rightAlign;
+ uint32_t lastWord;
+ uint32_t currWord;
+ uint32_t *p_Src32;
+ uint32_t *p_Dst32;
+ uint8_t *p_Src8;
+ uint8_t *p_Dst8;
+
+ p_Src8 = (uint8_t*)(pSrc);
+ p_Dst8 = (uint8_t*)(pDst);
+ /* first copy byte by byte till the source first alignment
+ * this step is necessary to ensure we do not even try to access
+ * data which is before the source buffer, hence it is not ours.
+ */
+ while((PTR_TO_UINT(p_Src8) & 3) && size) /* (pSrc mod 4) > 0 and size > 0 */
+ {
+ *p_Dst8++ = *p_Src8++;
+ size--;
+ }
+
+ /* align destination (possibly disaligning source)*/
+ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */
+ {
+ *p_Dst8++ = *p_Src8++;
+ size--;
+ }
+
+ /* dest is aligned and source is not necessarily aligned */
+ leftAlign = (uint32_t)((PTR_TO_UINT(p_Src8) & 3) << 3); /* leftAlign = (pSrc mod 4)*8 */
+ rightAlign = 32 - leftAlign;
+
+
+ if (leftAlign == 0)
+ {
+ /* source is also aligned */
+ p_Src32 = (uint32_t*)(p_Src8);
+ p_Dst32 = (uint32_t*)(p_Dst8);
+ while (size >> 2) /* size >= 4 */
+ {
+ *p_Dst32++ = *p_Src32++;
+ size -= 4;
+ }
+ p_Src8 = (uint8_t*)(p_Src32);
+ p_Dst8 = (uint8_t*)(p_Dst32);
+ }
+ else
+ {
+ /* source is not aligned (destination is aligned)*/
+ p_Src32 = (uint32_t*)(p_Src8 - (leftAlign >> 3));
+ p_Dst32 = (uint32_t*)(p_Dst8);
+ lastWord = *p_Src32++;
+ while(size >> 3) /* size >= 8 */
+ {
+ currWord = *p_Src32;
+ *p_Dst32 = (lastWord << leftAlign) | (currWord >> rightAlign);
+ lastWord = currWord;
+ p_Src32++;
+ p_Dst32++;
+ size -= 4;
+ }
+ p_Dst8 = (uint8_t*)(p_Dst32);
+ p_Src8 = (uint8_t*)(p_Src32) - 4 + (leftAlign >> 3);
+ }
+
+ /* complete the left overs */
+ while (size--)
+ *p_Dst8++ = *p_Src8++;
+
+ return pDst;
+}
+
+void * IO2IOCpy32(void* pDst,void* pSrc, uint32_t size)
+{
+ uint32_t leftAlign;
+ uint32_t rightAlign;
+ uint32_t lastWord;
+ uint32_t currWord;
+ uint32_t *p_Src32;
+ uint32_t *p_Dst32;
+ uint8_t *p_Src8;
+ uint8_t *p_Dst8;
+
+ p_Src8 = (uint8_t*)(pSrc);
+ p_Dst8 = (uint8_t*)(pDst);
+ /* first copy byte by byte till the source first alignment
+ * this step is necessary to ensure we do not even try to access
+ * data which is before the source buffer, hence it is not ours.
+ */
+ while((PTR_TO_UINT(p_Src8) & 3) && size) /* (pSrc mod 4) > 0 and size > 0 */
+ {
+ WRITE_UINT8(*p_Dst8, GET_UINT8(*p_Src8));
+ p_Dst8++;p_Src8++;
+ size--;
+ }
+
+ /* align destination (possibly disaligning source)*/
+ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */
+ {
+ WRITE_UINT8(*p_Dst8, GET_UINT8(*p_Src8));
+ p_Dst8++;p_Src8++;
+ size--;
+ }
+
+ /* dest is aligned and source is not necessarily aligned */
+ leftAlign = (uint32_t)((PTR_TO_UINT(p_Src8) & 3) << 3); /* leftAlign = (pSrc mod 4)*8 */
+ rightAlign = 32 - leftAlign;
+
+ if (leftAlign == 0)
+ {
+ /* source is also aligned */
+ p_Src32 = (uint32_t*)(p_Src8);
+ p_Dst32 = (uint32_t*)(p_Dst8);
+ while (size >> 2) /* size >= 4 */
+ {
+ WRITE_UINT32(*p_Dst32, GET_UINT32(*p_Src32));
+ p_Dst32++;p_Src32++;
+ size -= 4;
+ }
+ p_Src8 = (uint8_t*)(p_Src32);
+ p_Dst8 = (uint8_t*)(p_Dst32);
+ }
+ else
+ {
+ /* source is not aligned (destination is aligned)*/
+ p_Src32 = (uint32_t*)(p_Src8 - (leftAlign >> 3));
+ p_Dst32 = (uint32_t*)(p_Dst8);
+ lastWord = GET_UINT32(*p_Src32);
+ p_Src32++;
+ while(size >> 3) /* size >= 8 */
+ {
+ currWord = GET_UINT32(*p_Src32);
+ WRITE_UINT32(*p_Dst32, (lastWord << leftAlign) | (currWord >> rightAlign));
+ lastWord = currWord;
+ p_Src32++;p_Dst32++;
+ size -= 4;
+ }
+ p_Dst8 = (uint8_t*)(p_Dst32);
+ p_Src8 = (uint8_t*)(p_Src32) - 4 + (leftAlign >> 3);
+ }
+
+ /* complete the left overs */
+ while (size--)
+ {
+ WRITE_UINT8(*p_Dst8, GET_UINT8(*p_Src8));
+ p_Dst8++;p_Src8++;
+ }
+
+ return pDst;
+}
+
+void * Mem2IOCpy32(void* pDst,void* pSrc, uint32_t size)
+{
+ uint32_t leftAlign;
+ uint32_t rightAlign;
+ uint32_t lastWord;
+ uint32_t currWord;
+ uint32_t *p_Src32;
+ uint32_t *p_Dst32;
+ uint8_t *p_Src8;
+ uint8_t *p_Dst8;
+
+ p_Src8 = (uint8_t*)(pSrc);
+ p_Dst8 = (uint8_t*)(pDst);
+ /* first copy byte by byte till the source first alignment
+ * this step is necessary to ensure we do not even try to access
+ * data which is before the source buffer, hence it is not ours.
+ */
+ while((PTR_TO_UINT(p_Src8) & 3) && size) /* (pSrc mod 4) > 0 and size > 0 */
+ {
+ WRITE_UINT8(*p_Dst8, *p_Src8);
+ p_Dst8++;p_Src8++;
+ size--;
+ }
+
+ /* align destination (possibly disaligning source)*/
+ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */
+ {
+ WRITE_UINT8(*p_Dst8, *p_Src8);
+ p_Dst8++;p_Src8++;
+ size--;
+ }
+
+ /* dest is aligned and source is not necessarily aligned */
+ leftAlign = (uint32_t)((PTR_TO_UINT(p_Src8) & 3) << 3); /* leftAlign = (pSrc mod 4)*8 */
+ rightAlign = 32 - leftAlign;
+
+ if (leftAlign == 0)
+ {
+ /* source is also aligned */
+ p_Src32 = (uint32_t*)(p_Src8);
+ p_Dst32 = (uint32_t*)(p_Dst8);
+ while (size >> 2) /* size >= 4 */
+ {
+ WRITE_UINT32(*p_Dst32, *p_Src32);
+ p_Dst32++;p_Src32++;
+ size -= 4;
+ }
+ p_Src8 = (uint8_t*)(p_Src32);
+ p_Dst8 = (uint8_t*)(p_Dst32);
+ }
+ else
+ {
+ /* source is not aligned (destination is aligned)*/
+ p_Src32 = (uint32_t*)(p_Src8 - (leftAlign >> 3));
+ p_Dst32 = (uint32_t*)(p_Dst8);
+ lastWord = *p_Src32++;
+ while(size >> 3) /* size >= 8 */
+ {
+ currWord = *p_Src32;
+ WRITE_UINT32(*p_Dst32, (lastWord << leftAlign) | (currWord >> rightAlign));
+ lastWord = currWord;
+ p_Src32++;p_Dst32++;
+ size -= 4;
+ }
+ p_Dst8 = (uint8_t*)(p_Dst32);
+ p_Src8 = (uint8_t*)(p_Src32) - 4 + (leftAlign >> 3);
+ }
+
+ /* complete the left overs */
+ while (size--)
+ {
+ WRITE_UINT8(*p_Dst8, *p_Src8);
+ p_Dst8++;p_Src8++;
+ }
+
+ return pDst;
+}
+
+void * IO2MemCpy32(void* pDst,void* pSrc, uint32_t size)
+{
+ uint32_t leftAlign;
+ uint32_t rightAlign;
+ uint32_t lastWord;
+ uint32_t currWord;
+ uint32_t *p_Src32;
+ uint32_t *p_Dst32;
+ uint8_t *p_Src8;
+ uint8_t *p_Dst8;
+
+ p_Src8 = (uint8_t*)(pSrc);
+ p_Dst8 = (uint8_t*)(pDst);
+ /* first copy byte by byte till the source first alignment
+ * this step is necessary to ensure we do not even try to access
+ * data which is before the source buffer, hence it is not ours.
+ */
+ while((PTR_TO_UINT(p_Src8) & 3) && size) /* (pSrc mod 4) > 0 and size > 0 */
+ {
+ *p_Dst8 = GET_UINT8(*p_Src8);
+ p_Dst8++;p_Src8++;
+ size--;
+ }
+
+ /* align destination (possibly disaligning source)*/
+ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */
+ {
+ *p_Dst8 = GET_UINT8(*p_Src8);
+ p_Dst8++;p_Src8++;
+ size--;
+ }
+
+ /* dest is aligned and source is not necessarily aligned */
+ leftAlign = (uint32_t)((PTR_TO_UINT(p_Src8) & 3) << 3); /* leftAlign = (pSrc mod 4)*8 */
+ rightAlign = 32 - leftAlign;
+
+ if (leftAlign == 0)
+ {
+ /* source is also aligned */
+ p_Src32 = (uint32_t*)(p_Src8);
+ p_Dst32 = (uint32_t*)(p_Dst8);
+ while (size >> 2) /* size >= 4 */
+ {
+ *p_Dst32 = GET_UINT32(*p_Src32);
+ p_Dst32++;p_Src32++;
+ size -= 4;
+ }
+ p_Src8 = (uint8_t*)(p_Src32);
+ p_Dst8 = (uint8_t*)(p_Dst32);
+ }
+ else
+ {
+ /* source is not aligned (destination is aligned)*/
+ p_Src32 = (uint32_t*)(p_Src8 - (leftAlign >> 3));
+ p_Dst32 = (uint32_t*)(p_Dst8);
+ lastWord = GET_UINT32(*p_Src32);
+ p_Src32++;
+ while(size >> 3) /* size >= 8 */
+ {
+ currWord = GET_UINT32(*p_Src32);
+ *p_Dst32 = (lastWord << leftAlign) | (currWord >> rightAlign);
+ lastWord = currWord;
+ p_Src32++;p_Dst32++;
+ size -= 4;
+ }
+ p_Dst8 = (uint8_t*)(p_Dst32);
+ p_Src8 = (uint8_t*)(p_Src32) - 4 + (leftAlign >> 3);
+ }
+
+ /* complete the left overs */
+ while (size--)
+ {
+ *p_Dst8 = GET_UINT8(*p_Src8);
+ p_Dst8++;p_Src8++;
+ }
+
+ return pDst;
+}
+
+void * MemCpy64(void* pDst,void* pSrc, uint32_t size)
+{
+ uint32_t leftAlign;
+ uint32_t rightAlign;
+ uint64_t lastWord;
+ uint64_t currWord;
+ uint64_t *pSrc64;
+ uint64_t *pDst64;
+ uint8_t *p_Src8;
+ uint8_t *p_Dst8;
+
+ p_Src8 = (uint8_t*)(pSrc);
+ p_Dst8 = (uint8_t*)(pDst);
+ /* first copy byte by byte till the source first alignment
+ * this step is necessarily to ensure we do not even try to access
+ * data which is before the source buffer, hence it is not ours.
+ */
+ while((PTR_TO_UINT(p_Src8) & 7) && size) /* (pSrc mod 8) > 0 and size > 0 */
+ {
+ *p_Dst8++ = *p_Src8++;
+ size--;
+ }
+
+ /* align destination (possibly disaligning source)*/
+ while((PTR_TO_UINT(p_Dst8) & 7) && size) /* (pDst mod 8) > 0 and size > 0 */
+ {
+ *p_Dst8++ = *p_Src8++;
+ size--;
+ }
+
+ /* dest is aligned and source is not necessarily aligned */
+ leftAlign = (uint32_t)((PTR_TO_UINT(p_Src8) & 7) << 3); /* leftAlign = (pSrc mod 8)*8 */
+ rightAlign = 64 - leftAlign;
+
+
+ if (leftAlign == 0)
+ {
+ /* source is also aligned */
+ pSrc64 = (uint64_t*)(p_Src8);
+ pDst64 = (uint64_t*)(p_Dst8);
+ while (size >> 3) /* size >= 8 */
+ {
+ *pDst64++ = *pSrc64++;
+ size -= 8;
+ }
+ p_Src8 = (uint8_t*)(pSrc64);
+ p_Dst8 = (uint8_t*)(pDst64);
+ }
+ else
+ {
+ /* source is not aligned (destination is aligned)*/
+ pSrc64 = (uint64_t*)(p_Src8 - (leftAlign >> 3));
+ pDst64 = (uint64_t*)(p_Dst8);
+ lastWord = *pSrc64++;
+ while(size >> 4) /* size >= 16 */
+ {
+ currWord = *pSrc64;
+ *pDst64 = (lastWord << leftAlign) | (currWord >> rightAlign);
+ lastWord = currWord;
+ pSrc64++;
+ pDst64++;
+ size -= 8;
+ }
+ p_Dst8 = (uint8_t*)(pDst64);
+ p_Src8 = (uint8_t*)(pSrc64) - 8 + (leftAlign >> 3);
+ }
+
+ /* complete the left overs */
+ while (size--)
+ *p_Dst8++ = *p_Src8++;
+
+ return pDst;
+}
+
+void * MemSet32(void* pDst, uint8_t val, uint32_t size)
+{
+ uint32_t val32;
+ uint32_t *p_Dst32;
+ uint8_t *p_Dst8;
+
+ p_Dst8 = (uint8_t*)(pDst);
+
+ /* generate four 8-bit val's in 32-bit container */
+ val32 = (uint32_t) val;
+ val32 |= (val32 << 8);
+ val32 |= (val32 << 16);
+
+ /* align destination to 32 */
+ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */
+ {
+ *p_Dst8++ = val;
+ size--;
+ }
+
+ /* 32-bit chunks */
+ p_Dst32 = (uint32_t*)(p_Dst8);
+ while (size >> 2) /* size >= 4 */
+ {
+ *p_Dst32++ = val32;
+ size -= 4;
+ }
+
+ /* complete the leftovers */
+ p_Dst8 = (uint8_t*)(p_Dst32);
+ while (size--)
+ *p_Dst8++ = val;
+
+ return pDst;
+}
+
+void * IOMemSet32(void* pDst, uint8_t val, uint32_t size)
+{
+ uint32_t val32;
+ uint32_t *p_Dst32;
+ uint8_t *p_Dst8;
+
+ p_Dst8 = (uint8_t*)(pDst);
+
+ /* generate four 8-bit val's in 32-bit container */
+ val32 = (uint32_t) val;
+ val32 |= (val32 << 8);
+ val32 |= (val32 << 16);
+
+ /* align destination to 32 */
+ while((PTR_TO_UINT(p_Dst8) & 3) && size) /* (pDst mod 4) > 0 and size > 0 */
+ {
+ WRITE_UINT8(*p_Dst8, val);
+ p_Dst8++;
+ size--;
+ }
+
+ /* 32-bit chunks */
+ p_Dst32 = (uint32_t*)(p_Dst8);
+ while (size >> 2) /* size >= 4 */
+ {
+ WRITE_UINT32(*p_Dst32, val32);
+ p_Dst32++;
+ size -= 4;
+ }
+
+ /* complete the leftovers */
+ p_Dst8 = (uint8_t*)(p_Dst32);
+ while (size--)
+ {
+ WRITE_UINT8(*p_Dst8, val);
+ p_Dst8++;
+ }
+
+ return pDst;
+}
+
+void * MemSet64(void* pDst, uint8_t val, uint32_t size)
+{
+ uint64_t val64;
+ uint64_t *pDst64;
+ uint8_t *p_Dst8;
+
+ p_Dst8 = (uint8_t*)(pDst);
+
+ /* generate four 8-bit val's in 32-bit container */
+ val64 = (uint64_t) val;
+ val64 |= (val64 << 8);
+ val64 |= (val64 << 16);
+ val64 |= (val64 << 24);
+ val64 |= (val64 << 32);
+
+ /* align destination to 64 */
+ while((PTR_TO_UINT(p_Dst8) & 7) && size) /* (pDst mod 8) > 0 and size > 0 */
+ {
+ *p_Dst8++ = val;
+ size--;
+ }
+
+ /* 64-bit chunks */
+ pDst64 = (uint64_t*)(p_Dst8);
+ while (size >> 4) /* size >= 8 */
+ {
+ *pDst64++ = val64;
+ size -= 8;
+ }
+
+ /* complete the leftovers */
+ p_Dst8 = (uint8_t*)(pDst64);
+ while (size--)
+ *p_Dst8++ = val;
+
+ return pDst;
+}
+
+void MemDisp(uint8_t *p, int size)
+{
+ uint32_t space = (uint32_t)(PTR_TO_UINT(p) & 0x3);
+ uint8_t *p_Limit;
+
+ if (space)
+ {
+ p_Limit = (p - space + 4);
+
+ XX_Print("0x%08X: ", (p - space));
+
+ while (space--)
+ {
+ XX_Print("--");
+ }
+ while (size && (p < p_Limit))
+ {
+ XX_Print("%02x", *(uint8_t*)p);
+ size--;
+ p++;
+ }
+
+ XX_Print(" ");
+ p_Limit += 12;
+
+ while ((size > 3) && (p < p_Limit))
+ {
+ XX_Print("%08x ", *(uint32_t*)p);
+ size -= 4;
+ p += 4;
+ }
+ XX_Print("\r\n");
+ }
+
+ while (size > 15)
+ {
+ XX_Print("0x%08X: %08x %08x %08x %08x\r\n",
+ p, *(uint32_t *)p, *(uint32_t *)(p + 4),
+ *(uint32_t *)(p + 8), *(uint32_t *)(p + 12));
+ size -= 16;
+ p += 16;
+ }
+
+ if (size)
+ {
+ XX_Print("0x%08X: ", p);
+
+ while (size > 3)
+ {
+ XX_Print("%08x ", *(uint32_t *)p);
+ size -= 4;
+ p += 4;
+ }
+ while (size)
+ {
+ XX_Print("%02x", *(uint8_t *)p);
+ size--;
+ p++;
+ }
+
+ XX_Print("\r\n");
+ }
+}
diff --git a/drivers/net/ethernet/freescale/fman/etc/mm.c b/drivers/net/ethernet/freescale/fman/etc/mm.c
new file mode 100644
index 0000000..7b9d201
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/etc/mm.c
@@ -0,0 +1,1142 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "string_ext.h"
+#include "error_ext.h"
+#include "std_ext.h"
+#include "part_ext.h"
+#include "xx_ext.h"
+
+#include "mm.h"
+
+
+
+
+/**********************************************************************
+ * MM internal routines set *
+ **********************************************************************/
+
+/****************************************************************
+ * Routine: CreateBusyBlock
+ *
+ * Description:
+ * Initializes a new busy block of "size" bytes and started
+ * rom "base" address. Each busy block has a name that
+ * specified the purpose of the memory allocation.
+ *
+ * Arguments:
+ * base - base address of the busy block
+ * size - size of the busy block
+ * name - name that specified the busy block
+ *
+ * Return value:
+ * A pointer to new created structure returned on success;
+ * Otherwise, NULL.
+ ****************************************************************/
+static t_BusyBlock * CreateBusyBlock(uint64_t base, uint64_t size, char *name)
+{
+ t_BusyBlock *p_BusyBlock;
+ uint32_t n;
+
+ p_BusyBlock = (t_BusyBlock *)XX_Malloc(sizeof(t_BusyBlock));
+ if ( !p_BusyBlock )
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+ return NULL;
+ }
+
+ p_BusyBlock->base = base;
+ p_BusyBlock->end = base + size;
+
+ n = strlen(name);
+ if (n >= MM_MAX_NAME_LEN)
+ n = MM_MAX_NAME_LEN - 1;
+ strncpy(p_BusyBlock->name, name, MM_MAX_NAME_LEN-1);
+ p_BusyBlock->name[n] = '\0';
+ p_BusyBlock->p_Next = 0;
+
+ return p_BusyBlock;
+}
+
+/****************************************************************
+ * Routine: CreateNewBlock
+ *
+ * Description:
+ * Initializes a new memory block of "size" bytes and started
+ * from "base" address.
+ *
+ * Arguments:
+ * base - base address of the memory block
+ * size - size of the memory block
+ *
+ * Return value:
+ * A pointer to new created structure returned on success;
+ * Otherwise, NULL.
+ ****************************************************************/
+static t_MemBlock * CreateNewBlock(uint64_t base, uint64_t size)
+{
+ t_MemBlock *p_MemBlock;
+
+ p_MemBlock = (t_MemBlock *)XX_Malloc(sizeof(t_MemBlock));
+ if ( !p_MemBlock )
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+ return NULL;
+ }
+
+ p_MemBlock->base = base;
+ p_MemBlock->end = base+size;
+ p_MemBlock->p_Next = 0;
+
+ return p_MemBlock;
+}
+
+/****************************************************************
+ * Routine: CreateFreeBlock
+ *
+ * Description:
+ * Initializes a new free block of of "size" bytes and
+ * started from "base" address.
+ *
+ * Arguments:
+ * base - base address of the free block
+ * size - size of the free block
+ *
+ * Return value:
+ * A pointer to new created structure returned on success;
+ * Otherwise, NULL.
+ ****************************************************************/
+static t_FreeBlock * CreateFreeBlock(uint64_t base, uint64_t size)
+{
+ t_FreeBlock *p_FreeBlock;
+
+ p_FreeBlock = (t_FreeBlock *)XX_Malloc(sizeof(t_FreeBlock));
+ if ( !p_FreeBlock )
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+ return NULL;
+ }
+
+ p_FreeBlock->base = base;
+ p_FreeBlock->end = base + size;
+ p_FreeBlock->p_Next = 0;
+
+ return p_FreeBlock;
+}
+
+/****************************************************************
+ * Routine: AddFree
+ *
+ * Description:
+ * Adds a new free block to the free lists. It updates each
+ * free list to include a new free block.
+ * Note, that all free block in each free list are ordered
+ * by their base address.
+ *
+ * Arguments:
+ * p_MM - pointer to the MM object
+ * base - base address of a given free block
+ * end - end address of a given free block
+ *
+ * Return value:
+ *
+ *
+ ****************************************************************/
+static t_Error AddFree(t_MM *p_MM, uint64_t base, uint64_t end)
+{
+ t_FreeBlock *p_PrevB, *p_CurrB, *p_NewB;
+ uint64_t alignment;
+ uint64_t alignBase;
+ int i;
+
+ /* Updates free lists to include a just released block */
+ for (i=0; i <= MM_MAX_ALIGNMENT; i++)
+ {
+ p_PrevB = p_NewB = 0;
+ p_CurrB = p_MM->freeBlocks[i];
+
+ alignment = (uint64_t)(0x1 << i);
+ alignBase = MAKE_ALIGNED(base, alignment);
+
+ /* Goes to the next free list if there is no block to free */
+ if (alignBase >= end)
+ continue;
+
+ /* Looks for a free block that should be updated */
+ while ( p_CurrB )
+ {
+ if ( alignBase <= p_CurrB->end )
+ {
+ if ( end > p_CurrB->end )
+ {
+ t_FreeBlock *p_NextB;
+ while ( p_CurrB->p_Next && end > p_CurrB->p_Next->end )
+ {
+ p_NextB = p_CurrB->p_Next;
+ p_CurrB->p_Next = p_CurrB->p_Next->p_Next;
+ XX_Free(p_NextB);
+ }
+
+ p_NextB = p_CurrB->p_Next;
+ if ( !p_NextB || (p_NextB && end < p_NextB->base) )
+ {
+ p_CurrB->end = end;
+ }
+ else
+ {
+ p_CurrB->end = p_NextB->end;
+ p_CurrB->p_Next = p_NextB->p_Next;
+ XX_Free(p_NextB);
+ }
+ }
+ else if ( (end < p_CurrB->base) && ((end-alignBase) >= alignment) )
+ {
+ if ((p_NewB = CreateFreeBlock(alignBase, end-alignBase)) == NULL)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+
+ p_NewB->p_Next = p_CurrB;
+ if (p_PrevB)
+ p_PrevB->p_Next = p_NewB;
+ else
+ p_MM->freeBlocks[i] = p_NewB;
+ break;
+ }
+
+ if ((alignBase < p_CurrB->base) && (end >= p_CurrB->base))
+ {
+ p_CurrB->base = alignBase;
+ }
+
+ /* if size of the free block is less then alignment
+ * deletes that free block from the free list. */
+ if ( (p_CurrB->end - p_CurrB->base) < alignment)
+ {
+ if ( p_PrevB )
+ p_PrevB->p_Next = p_CurrB->p_Next;
+ else
+ p_MM->freeBlocks[i] = p_CurrB->p_Next;
+ XX_Free(p_CurrB);
+ }
+ break;
+ }
+ else
+ {
+ p_PrevB = p_CurrB;
+ p_CurrB = p_CurrB->p_Next;
+ }
+ }
+
+ /* If no free block found to be updated, insert a new free block
+ * to the end of the free list.
+ */
+ if ( !p_CurrB && ((((uint64_t)(end-base)) & ((uint64_t)(alignment-1))) == 0) )
+ {
+ if ((p_NewB = CreateFreeBlock(alignBase, end-base)) == NULL)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+
+ if (p_PrevB)
+ p_PrevB->p_Next = p_NewB;
+ else
+ p_MM->freeBlocks[i] = p_NewB;
+ }
+
+ /* Update boundaries of the new free block */
+ if ((alignment == 1) && !p_NewB)
+ {
+ if ( p_CurrB && base > p_CurrB->base )
+ base = p_CurrB->base;
+ if ( p_CurrB && end < p_CurrB->end )
+ end = p_CurrB->end;
+ }
+ }
+
+ return (E_OK);
+}
+
+/****************************************************************
+ * Routine: CutFree
+ *
+ * Description:
+ * Cuts a free block from holdBase to holdEnd from the free lists.
+ * That is, it updates all free lists of the MM object do
+ * not include a block of memory from holdBase to holdEnd.
+ * For each free lists it seek for a free block that holds
+ * either holdBase or holdEnd. If such block is found it updates it.
+ *
+ * Arguments:
+ * p_MM - pointer to the MM object
+ * holdBase - base address of the allocated block
+ * holdEnd - end address of the allocated block
+ *
+ * Return value:
+ * E_OK is returned on success,
+ * otherwise returns an error code.
+ *
+ ****************************************************************/
+static t_Error CutFree(t_MM *p_MM, uint64_t holdBase, uint64_t holdEnd)
+{
+ t_FreeBlock *p_PrevB, *p_CurrB, *p_NewB;
+ uint64_t alignBase, base, end;
+ uint64_t alignment;
+ int i;
+
+ for (i=0; i <= MM_MAX_ALIGNMENT; i++)
+ {
+ p_PrevB = p_NewB = 0;
+ p_CurrB = p_MM->freeBlocks[i];
+
+ alignment = (uint64_t)(0x1 << i);
+ alignBase = MAKE_ALIGNED(holdEnd, alignment);
+
+ while ( p_CurrB )
+ {
+ base = p_CurrB->base;
+ end = p_CurrB->end;
+
+ if ( (holdBase <= base) && (holdEnd <= end) && (holdEnd > base) )
+ {
+ if ( alignBase >= end ||
+ (alignBase < end && ((end-alignBase) < alignment)) )
+ {
+ if (p_PrevB)
+ p_PrevB->p_Next = p_CurrB->p_Next;
+ else
+ p_MM->freeBlocks[i] = p_CurrB->p_Next;
+ XX_Free(p_CurrB);
+ }
+ else
+ {
+ p_CurrB->base = alignBase;
+ }
+ break;
+ }
+ else if ( (holdBase > base) && (holdEnd <= end) )
+ {
+ if ( (holdBase-base) >= alignment )
+ {
+ if ( (alignBase < end) && ((end-alignBase) >= alignment) )
+ {
+ if ((p_NewB = CreateFreeBlock(alignBase, end-alignBase)) == NULL)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+ p_NewB->p_Next = p_CurrB->p_Next;
+ p_CurrB->p_Next = p_NewB;
+ }
+ p_CurrB->end = holdBase;
+ }
+ else if ( (alignBase < end) && ((end-alignBase) >= alignment) )
+ {
+ p_CurrB->base = alignBase;
+ }
+ else
+ {
+ if (p_PrevB)
+ p_PrevB->p_Next = p_CurrB->p_Next;
+ else
+ p_MM->freeBlocks[i] = p_CurrB->p_Next;
+ XX_Free(p_CurrB);
+ }
+ break;
+ }
+ else
+ {
+ p_PrevB = p_CurrB;
+ p_CurrB = p_CurrB->p_Next;
+ }
+ }
+ }
+
+ return (E_OK);
+}
+
+/****************************************************************
+ * Routine: AddBusy
+ *
+ * Description:
+ * Adds a new busy block to the list of busy blocks. Note,
+ * that all busy blocks are ordered by their base address in
+ * the busy list.
+ *
+ * Arguments:
+ * MM - handler to the MM object
+ * p_NewBusyB - pointer to the a busy block
+ *
+ * Return value:
+ * None.
+ *
+ ****************************************************************/
+static void AddBusy(t_MM *p_MM, t_BusyBlock *p_NewBusyB)
+{
+ t_BusyBlock *p_CurrBusyB, *p_PrevBusyB;
+
+ /* finds a place of a new busy block in the list of busy blocks */
+ p_PrevBusyB = 0;
+ p_CurrBusyB = p_MM->busyBlocks;
+
+ while ( p_CurrBusyB && p_NewBusyB->base > p_CurrBusyB->base )
+ {
+ p_PrevBusyB = p_CurrBusyB;
+ p_CurrBusyB = p_CurrBusyB->p_Next;
+ }
+
+ /* insert the new busy block into the list of busy blocks */
+ if ( p_CurrBusyB )
+ p_NewBusyB->p_Next = p_CurrBusyB;
+ if ( p_PrevBusyB )
+ p_PrevBusyB->p_Next = p_NewBusyB;
+ else
+ p_MM->busyBlocks = p_NewBusyB;
+}
+
+/****************************************************************
+ * Routine: CutBusy
+ *
+ * Description:
+ * Cuts a block from base to end from the list of busy blocks.
+ * This is done by updating the list of busy blocks do not
+ * include a given block, that block is going to be free. If a
+ * given block is a part of some other busy block, so that
+ * busy block is updated. If there are number of busy blocks
+ * included in the given block, so all that blocks are removed
+ * from the busy list and the end blocks are updated.
+ * If the given block devides some block into two parts, a new
+ * busy block is added to the busy list.
+ *
+ * Arguments:
+ * p_MM - pointer to the MM object
+ * base - base address of a given busy block
+ * end - end address of a given busy block
+ *
+ * Return value:
+ * E_OK on success, E_NOMEMORY otherwise.
+ *
+ ****************************************************************/
+static t_Error CutBusy(t_MM *p_MM, uint64_t base, uint64_t end)
+{
+ t_BusyBlock *p_CurrB, *p_PrevB, *p_NewB;
+
+ p_CurrB = p_MM->busyBlocks;
+ p_PrevB = p_NewB = 0;
+
+ while ( p_CurrB )
+ {
+ if ( base < p_CurrB->end )
+ {
+ if ( end > p_CurrB->end )
+ {
+ t_BusyBlock *p_NextB;
+ while ( p_CurrB->p_Next && end >= p_CurrB->p_Next->end )
+ {
+ p_NextB = p_CurrB->p_Next;
+ p_CurrB->p_Next = p_CurrB->p_Next->p_Next;
+ XX_Free(p_NextB);
+ }
+
+ p_NextB = p_CurrB->p_Next;
+ if ( p_NextB && end > p_NextB->base )
+ {
+ p_NextB->base = end;
+ }
+ }
+
+ if ( base <= p_CurrB->base )
+ {
+ if ( end < p_CurrB->end && end > p_CurrB->base )
+ {
+ p_CurrB->base = end;
+ }
+ else if ( end >= p_CurrB->end )
+ {
+ if ( p_PrevB )
+ p_PrevB->p_Next = p_CurrB->p_Next;
+ else
+ p_MM->busyBlocks = p_CurrB->p_Next;
+ XX_Free(p_CurrB);
+ }
+ }
+ else
+ {
+ if ( end < p_CurrB->end && end > p_CurrB->base )
+ {
+ if ((p_NewB = CreateBusyBlock(end,
+ p_CurrB->end-end,
+ p_CurrB->name)) == NULL)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+ p_NewB->p_Next = p_CurrB->p_Next;
+ p_CurrB->p_Next = p_NewB;
+ }
+ p_CurrB->end = base;
+ }
+ break;
+ }
+ else
+ {
+ p_PrevB = p_CurrB;
+ p_CurrB = p_CurrB->p_Next;
+ }
+ }
+
+ return (E_OK);
+}
+
+/****************************************************************
+ * Routine: MmGetGreaterAlignment
+ *
+ * Description:
+ * Allocates a block of memory according to the given size
+ * and the alignment. That routine is called from the MM_Get
+ * routine if the required alignment is greater then MM_MAX_ALIGNMENT.
+ * In that case, it goes over free blocks of 64 byte align list
+ * and checks if it has the required size of bytes of the required
+ * alignment. If no blocks found returns ILLEGAL_BASE.
+ * After the block is found and data is allocated, it calls
+ * the internal CutFree routine to update all free lists
+ * do not include a just allocated block. Of course, each
+ * free list contains a free blocks with the same alignment.
+ * It is also creates a busy block that holds
+ * information about an allocated block.
+ *
+ * Arguments:
+ * MM - handle to the MM object
+ * size - size of the MM
+ * alignment - index as a power of two defines
+ * a required alignment that is greater then 64.
+ * name - the name that specifies an allocated block.
+ *
+ * Return value:
+ * base address of an allocated block.
+ * ILLEGAL_BASE if can't allocate a block
+ *
+ ****************************************************************/
+static uint64_t MmGetGreaterAlignment(t_MM *p_MM, uint64_t size, uint64_t alignment, char* name)
+{
+ t_FreeBlock *p_FreeB;
+ t_BusyBlock *p_NewBusyB;
+ uint64_t holdBase, holdEnd, alignBase = 0;
+
+ /* goes over free blocks of the 64 byte alignment list
+ and look for a block of the suitable size and
+ base address according to the alignment. */
+ p_FreeB = p_MM->freeBlocks[MM_MAX_ALIGNMENT];
+
+ while ( p_FreeB )
+ {
+ alignBase = MAKE_ALIGNED(p_FreeB->base, alignment);
+
+ /* the block is found if the aligned base inside the block
+ * and has the anough size. */
+ if ( alignBase >= p_FreeB->base &&
+ alignBase < p_FreeB->end &&
+ size <= (p_FreeB->end - alignBase) )
+ break;
+ else
+ p_FreeB = p_FreeB->p_Next;
+ }
+
+ /* If such block isn't found */
+ if ( !p_FreeB )
+ return (uint64_t)(ILLEGAL_BASE);
+
+ holdBase = alignBase;
+ holdEnd = alignBase + size;
+
+ /* init a new busy block */
+ if ((p_NewBusyB = CreateBusyBlock(holdBase, size, name)) == NULL)
+ return (uint64_t)(ILLEGAL_BASE);
+
+ /* calls Update routine to update a lists of free blocks */
+ if ( CutFree ( p_MM, holdBase, holdEnd ) != E_OK )
+ return (uint64_t)(ILLEGAL_BASE);
+
+ /* insert the new busy block into the list of busy blocks */
+ AddBusy ( p_MM, p_NewBusyB );
+
+ return (holdBase);
+}
+
+
+/**********************************************************************
+ * MM API routines set *
+ **********************************************************************/
+
+/*****************************************************************************/
+t_Error MM_Init(t_Handle *h_MM, uint64_t base, uint64_t size)
+{
+ t_MM *p_MM;
+ uint64_t newBase, newSize;
+ int i;
+
+ if (!size)
+ {
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Size (should be positive)"));
+ }
+
+ /* Initializes a new MM object */
+ p_MM = (t_MM *)XX_Malloc(sizeof(t_MM));
+ if (!p_MM)
+ {
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+ }
+
+ p_MM->h_Spinlock = XX_InitSpinlock();
+ if (!p_MM->h_Spinlock)
+ {
+ XX_Free(p_MM);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MM spinlock!"));
+ }
+
+ /* Initializes counter of free memory to total size */
+ p_MM->freeMemSize = size;
+
+ /* Initializes a new memory block */
+ if ((p_MM->memBlocks = CreateNewBlock(base, size)) == NULL)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+
+ /* A busy list is empty */
+ p_MM->busyBlocks = 0;
+
+ /* Initializes a new free block for each free list*/
+ for (i=0; i <= MM_MAX_ALIGNMENT; i++)
+ {
+ newBase = MAKE_ALIGNED( base, (0x1 << i) );
+ newSize = size - (newBase - base);
+
+ if ((p_MM->freeBlocks[i] = CreateFreeBlock(newBase, newSize)) == NULL)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+ }
+
+ *h_MM = p_MM;
+
+ return (E_OK);
+}
+
+/*****************************************************************************/
+void MM_Free(t_Handle h_MM)
+{
+ t_MM *p_MM = (t_MM *)h_MM;
+ t_MemBlock *p_MemBlock;
+ t_BusyBlock *p_BusyBlock;
+ t_FreeBlock *p_FreeBlock;
+ void *p_Block;
+ int i;
+
+ ASSERT_COND(p_MM);
+
+ /* release memory allocated for busy blocks */
+ p_BusyBlock = p_MM->busyBlocks;
+ while ( p_BusyBlock )
+ {
+ p_Block = p_BusyBlock;
+ p_BusyBlock = p_BusyBlock->p_Next;
+ XX_Free(p_Block);
+ }
+
+ /* release memory allocated for free blocks */
+ for (i=0; i <= MM_MAX_ALIGNMENT; i++)
+ {
+ p_FreeBlock = p_MM->freeBlocks[i];
+ while ( p_FreeBlock )
+ {
+ p_Block = p_FreeBlock;
+ p_FreeBlock = p_FreeBlock->p_Next;
+ XX_Free(p_Block);
+ }
+ }
+
+ /* release memory allocated for memory blocks */
+ p_MemBlock = p_MM->memBlocks;
+ while ( p_MemBlock )
+ {
+ p_Block = p_MemBlock;
+ p_MemBlock = p_MemBlock->p_Next;
+ XX_Free(p_Block);
+ }
+
+ if (p_MM->h_Spinlock)
+ XX_FreeSpinlock(p_MM->h_Spinlock);
+
+ /* release memory allocated for MM object itself */
+ XX_Free(p_MM);
+}
+
+/*****************************************************************************/
+uint64_t MM_Get(t_Handle h_MM, uint64_t size, uint64_t alignment, char* name)
+{
+ t_MM *p_MM = (t_MM *)h_MM;
+ t_FreeBlock *p_FreeB;
+ t_BusyBlock *p_NewBusyB;
+ uint64_t holdBase, holdEnd, j, i = 0;
+ uint32_t intFlags;
+
+ SANITY_CHECK_RETURN_VALUE(p_MM, E_INVALID_HANDLE, (uint64_t)ILLEGAL_BASE);
+
+ /* checks that alignment value is greater then zero */
+ if (alignment == 0)
+ {
+ alignment = 1;
+ }
+
+ j = alignment;
+
+ /* checks if alignment is a power of two, if it correct and if the
+ required size is multiple of the given alignment. */
+ while ((j & 0x1) == 0)
+ {
+ i++;
+ j = j >> 1;
+ }
+
+ /* if the given alignment isn't power of two, returns an error */
+ if (j != 1)
+ {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("alignment (should be power of 2)"));
+ return (uint64_t)ILLEGAL_BASE;
+ }
+
+ if (i > MM_MAX_ALIGNMENT)
+ {
+ return (MmGetGreaterAlignment(p_MM, size, alignment, name));
+ }
+
+ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock);
+ /* look for a block of the size greater or equal to the required size. */
+ p_FreeB = p_MM->freeBlocks[i];
+ while ( p_FreeB && (p_FreeB->end - p_FreeB->base) < size )
+ p_FreeB = p_FreeB->p_Next;
+
+ /* If such block is found */
+ if ( !p_FreeB )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(ILLEGAL_BASE);
+ }
+
+ holdBase = p_FreeB->base;
+ holdEnd = holdBase + size;
+
+ /* init a new busy block */
+ if ((p_NewBusyB = CreateBusyBlock(holdBase, size, name)) == NULL)
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(ILLEGAL_BASE);
+ }
+
+ /* calls Update routine to update a lists of free blocks */
+ if ( CutFree ( p_MM, holdBase, holdEnd ) != E_OK )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(ILLEGAL_BASE);
+ }
+
+ /* Decreasing the allocated memory size from free memory size */
+ p_MM->freeMemSize -= size;
+
+ /* insert the new busy block into the list of busy blocks */
+ AddBusy ( p_MM, p_NewBusyB );
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+
+ return (holdBase);
+}
+
+/*****************************************************************************/
+uint64_t MM_GetForce(t_Handle h_MM, uint64_t base, uint64_t size, char* name)
+{
+ t_MM *p_MM = (t_MM *)h_MM;
+ t_FreeBlock *p_FreeB;
+ t_BusyBlock *p_NewBusyB;
+ uint32_t intFlags;
+ bool blockIsFree = FALSE;
+
+ ASSERT_COND(p_MM);
+
+ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock);
+ p_FreeB = p_MM->freeBlocks[0]; /* The biggest free blocks are in the
+ free list with alignment 1 */
+
+ while ( p_FreeB )
+ {
+ if ( base >= p_FreeB->base && (base+size) <= p_FreeB->end )
+ {
+ blockIsFree = TRUE;
+ break;
+ }
+ else
+ p_FreeB = p_FreeB->p_Next;
+ }
+
+ if ( !blockIsFree )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(ILLEGAL_BASE);
+ }
+
+ /* init a new busy block */
+ if ((p_NewBusyB = CreateBusyBlock(base, size, name)) == NULL)
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(ILLEGAL_BASE);
+ }
+
+ /* calls Update routine to update a lists of free blocks */
+ if ( CutFree ( p_MM, base, base+size ) != E_OK )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(ILLEGAL_BASE);
+ }
+
+ /* Decreasing the allocated memory size from free memory size */
+ p_MM->freeMemSize -= size;
+
+ /* insert the new busy block into the list of busy blocks */
+ AddBusy ( p_MM, p_NewBusyB );
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+
+ return (base);
+}
+
+/*****************************************************************************/
+uint64_t MM_GetForceMin(t_Handle h_MM, uint64_t size, uint64_t alignment, uint64_t min, char* name)
+{
+ t_MM *p_MM = (t_MM *)h_MM;
+ t_FreeBlock *p_FreeB;
+ t_BusyBlock *p_NewBusyB;
+ uint64_t holdBase, holdEnd, j = alignment, i=0;
+ uint32_t intFlags;
+
+ ASSERT_COND(p_MM);
+
+ /* checks if alignment is a power of two, if it correct and if the
+ required size is multiple of the given alignment. */
+ while ((j & 0x1) == 0)
+ {
+ i++;
+ j = j >> 1;
+ }
+
+ if ( (j != 1) || (i > MM_MAX_ALIGNMENT) )
+ {
+ return (uint64_t)(ILLEGAL_BASE);
+ }
+
+ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock);
+ p_FreeB = p_MM->freeBlocks[i];
+
+ /* look for the first block that contains the minimum
+ base address. If the whole required size may be fit
+ into it, use that block, otherwise look for the next
+ block of size greater or equal to the required size. */
+ while ( p_FreeB && (min >= p_FreeB->end))
+ p_FreeB = p_FreeB->p_Next;
+
+ /* If such block is found */
+ if ( !p_FreeB )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(ILLEGAL_BASE);
+ }
+
+ /* if this block is large enough, use this block */
+ holdBase = ( min <= p_FreeB->base ) ? p_FreeB->base : min;
+ if ((holdBase + size) <= p_FreeB->end )
+ {
+ holdEnd = holdBase + size;
+ }
+ else
+ {
+ p_FreeB = p_FreeB->p_Next;
+ while ( p_FreeB && ((p_FreeB->end - p_FreeB->base) < size) )
+ p_FreeB = p_FreeB->p_Next;
+
+ /* If such block is found */
+ if ( !p_FreeB )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(ILLEGAL_BASE);
+ }
+
+ holdBase = p_FreeB->base;
+ holdEnd = holdBase + size;
+ }
+
+ /* init a new busy block */
+ if ((p_NewBusyB = CreateBusyBlock(holdBase, size, name)) == NULL)
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(ILLEGAL_BASE);
+ }
+
+ /* calls Update routine to update a lists of free blocks */
+ if ( CutFree( p_MM, holdBase, holdEnd ) != E_OK )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(ILLEGAL_BASE);
+ }
+
+ /* Decreasing the allocated memory size from free memory size */
+ p_MM->freeMemSize -= size;
+
+ /* insert the new busy block into the list of busy blocks */
+ AddBusy( p_MM, p_NewBusyB );
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+
+ return (holdBase);
+}
+
+/*****************************************************************************/
+uint64_t MM_Put(t_Handle h_MM, uint64_t base)
+{
+ t_MM *p_MM = (t_MM *)h_MM;
+ t_BusyBlock *p_BusyB, *p_PrevBusyB;
+ uint64_t size;
+ uint32_t intFlags;
+
+ ASSERT_COND(p_MM);
+
+ /* Look for a busy block that have the given base value.
+ * That block will be returned back to the memory.
+ */
+ p_PrevBusyB = 0;
+
+ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock);
+ p_BusyB = p_MM->busyBlocks;
+ while ( p_BusyB && base != p_BusyB->base )
+ {
+ p_PrevBusyB = p_BusyB;
+ p_BusyB = p_BusyB->p_Next;
+ }
+
+ if ( !p_BusyB )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(0);
+ }
+
+ if ( AddFree( p_MM, p_BusyB->base, p_BusyB->end ) != E_OK )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(0);
+ }
+
+ /* removes a busy block form the list of busy blocks */
+ if ( p_PrevBusyB )
+ p_PrevBusyB->p_Next = p_BusyB->p_Next;
+ else
+ p_MM->busyBlocks = p_BusyB->p_Next;
+
+ size = p_BusyB->end - p_BusyB->base;
+
+ /* Adding the deallocated memory size to free memory size */
+ p_MM->freeMemSize += size;
+
+ XX_Free(p_BusyB);
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+
+ return (size);
+}
+
+/*****************************************************************************/
+uint64_t MM_PutForce(t_Handle h_MM, uint64_t base, uint64_t size)
+{
+ t_MM *p_MM = (t_MM *)h_MM;
+ uint64_t end = base + size;
+ uint32_t intFlags;
+
+ ASSERT_COND(p_MM);
+
+ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock);
+
+ if ( CutBusy( p_MM, base, end ) != E_OK )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(0);
+ }
+
+ if ( AddFree ( p_MM, base, end ) != E_OK )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ return (uint64_t)(0);
+ }
+
+ /* Adding the deallocated memory size to free memory size */
+ p_MM->freeMemSize += size;
+
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+
+ return (size);
+}
+
+/*****************************************************************************/
+t_Error MM_Add(t_Handle h_MM, uint64_t base, uint64_t size)
+{
+ t_MM *p_MM = (t_MM *)h_MM;
+ t_MemBlock *p_MemB, *p_NewMemB;
+ t_Error errCode;
+ uint32_t intFlags;
+
+ ASSERT_COND(p_MM);
+
+ /* find a last block in the list of memory blocks to insert a new
+ * memory block
+ */
+ intFlags = XX_LockIntrSpinlock(p_MM->h_Spinlock);
+
+ p_MemB = p_MM->memBlocks;
+ while ( p_MemB->p_Next )
+ {
+ if ( base >= p_MemB->base && base < p_MemB->end )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG);
+ }
+ p_MemB = p_MemB->p_Next;
+ }
+ /* check for a last memory block */
+ if ( base >= p_MemB->base && base < p_MemB->end )
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG);
+ }
+
+ /* create a new memory block */
+ if ((p_NewMemB = CreateNewBlock(base, size)) == NULL)
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+ }
+
+ /* append a new memory block to the end of the list of memory blocks */
+ p_MemB->p_Next = p_NewMemB;
+
+ /* add a new free block to the free lists */
+ errCode = AddFree(p_MM, base, base+size);
+ if (errCode)
+ {
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+ p_MemB->p_Next = 0;
+ XX_Free(p_NewMemB);
+ return ((t_Error)errCode);
+ }
+
+ /* Adding the new block size to free memory size */
+ p_MM->freeMemSize += size;
+
+ XX_UnlockIntrSpinlock(p_MM->h_Spinlock, intFlags);
+
+ return (E_OK);
+}
+
+/*****************************************************************************/
+uint64_t MM_GetMemBlock(t_Handle h_MM, int index)
+{
+ t_MM *p_MM = (t_MM*)h_MM;
+ t_MemBlock *p_MemBlock;
+ int i;
+
+ ASSERT_COND(p_MM);
+
+ p_MemBlock = p_MM->memBlocks;
+ for (i=0; i < index; i++)
+ p_MemBlock = p_MemBlock->p_Next;
+
+ if ( p_MemBlock )
+ return (p_MemBlock->base);
+ else
+ return (uint64_t)ILLEGAL_BASE;
+}
+
+/*****************************************************************************/
+uint64_t MM_GetBase(t_Handle h_MM)
+{
+ t_MM *p_MM = (t_MM*)h_MM;
+ t_MemBlock *p_MemBlock;
+
+ ASSERT_COND(p_MM);
+
+ p_MemBlock = p_MM->memBlocks;
+ return p_MemBlock->base;
+}
+
+/*****************************************************************************/
+bool MM_InRange(t_Handle h_MM, uint64_t addr)
+{
+ t_MM *p_MM = (t_MM*)h_MM;
+ t_MemBlock *p_MemBlock;
+
+ ASSERT_COND(p_MM);
+
+ p_MemBlock = p_MM->memBlocks;
+
+ if ((addr >= p_MemBlock->base) && (addr < p_MemBlock->end))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/*****************************************************************************/
+uint64_t MM_GetFreeMemSize(t_Handle h_MM)
+{
+ t_MM *p_MM = (t_MM*)h_MM;
+
+ ASSERT_COND(p_MM);
+
+ return p_MM->freeMemSize;
+}
+
+/*****************************************************************************/
+void MM_Dump(t_Handle h_MM)
+{
+ t_MM *p_MM = (t_MM *)h_MM;
+ t_FreeBlock *p_FreeB;
+ t_BusyBlock *p_BusyB;
+ int i;
+
+ p_BusyB = p_MM->busyBlocks;
+ XX_Print("List of busy blocks:\n");
+ while (p_BusyB)
+ {
+ XX_Print("\t0x%p: (%s: b=0x%llx, e=0x%llx)\n", p_BusyB, p_BusyB->name, p_BusyB->base, p_BusyB->end );
+ p_BusyB = p_BusyB->p_Next;
+ }
+
+ XX_Print("\nLists of free blocks according to alignment:\n");
+ for (i=0; i <= MM_MAX_ALIGNMENT; i++)
+ {
+ XX_Print("%d alignment:\n", (0x1 << i));
+ p_FreeB = p_MM->freeBlocks[i];
+ while (p_FreeB)
+ {
+ XX_Print("\t0x%p: (b=0x%llx, e=0x%llx)\n", p_FreeB, p_FreeB->base, p_FreeB->end);
+ p_FreeB = p_FreeB->p_Next;
+ }
+ XX_Print("\n");
+ }
+}
diff --git a/drivers/net/ethernet/freescale/fman/etc/mm.h b/drivers/net/ethernet/freescale/fman/etc/mm.h
new file mode 100644
index 0000000..43b2298
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/etc/mm.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/****************************************************************
+ *
+ * File: mm.h
+ *
+ *
+ * Description:
+ * MM (Memory Management) object definitions.
+ * It also includes definitions of the Free Block, Busy Block
+ * and Memory Block structures used by the MM object.
+ *
+ ****************************************************************/
+
+#ifndef __MM_H
+#define __MM_H
+
+
+#include "mm_ext.h"
+
+#define __ERR_MODULE__ MODULE_MM
+
+
+#define MAKE_ALIGNED(addr, align) \
+ (((uint64_t)(addr) + ((align) - 1)) & (~(((uint64_t)align) - 1)))
+
+
+/* t_MemBlock data structure defines parameters of the Memory Block */
+typedef struct t_MemBlock
+{
+ struct t_MemBlock *p_Next; /* Pointer to the next memory block */
+
+ uint64_t base; /* Base address of the memory block */
+ uint64_t end; /* End address of the memory block */
+} t_MemBlock;
+
+
+/* t_FreeBlock data structure defines parameters of the Free Block */
+typedef struct t_FreeBlock
+{
+ struct t_FreeBlock *p_Next; /* Pointer to the next free block */
+
+ uint64_t base; /* Base address of the block */
+ uint64_t end; /* End address of the block */
+} t_FreeBlock;
+
+
+/* t_BusyBlock data structure defines parameters of the Busy Block */
+typedef struct t_BusyBlock
+{
+ struct t_BusyBlock *p_Next; /* Pointer to the next free block */
+
+ uint64_t base; /* Base address of the block */
+ uint64_t end; /* End address of the block */
+ char name[MM_MAX_NAME_LEN]; /* That block of memory was allocated for
+ something specified by the Name */
+} t_BusyBlock;
+
+
+/* t_MM data structure defines parameters of the MM object */
+typedef struct t_MM
+{
+ t_Handle h_Spinlock;
+
+ t_MemBlock *memBlocks; /* List of memory blocks (Memory list) */
+ t_BusyBlock *busyBlocks; /* List of busy blocks (Busy list) */
+ t_FreeBlock *freeBlocks[MM_MAX_ALIGNMENT + 1];
+ /* Alignment lists of free blocks (Free lists) */
+
+ uint64_t freeMemSize; /* Total size of free memory (in bytes) */
+} t_MM;
+
+
+#endif /* __MM_H */
diff --git a/drivers/net/ethernet/freescale/fman/etc/sprint.c b/drivers/net/ethernet/freescale/fman/etc/sprint.c
new file mode 100644
index 0000000..46d2956
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/etc/sprint.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*------------------------------------------------------*/
+/* File: sprint.c */
+/* */
+/* Description: */
+/* Debug routines (externals) */
+/*------------------------------------------------------*/
+#include "string_ext.h"
+#include "stdlib_ext.h"
+#include "stdarg_ext.h"
+#include "sprint_ext.h"
+#include "std_ext.h"
+#include "xx_ext.h"
+
+
+int Sprint(char * buf, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsprintf(buf,fmt,args);
+ va_end(args);
+ return i;
+}
+
+int Snprint(char * buf, uint32_t size, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsnprintf(buf,size,fmt,args);
+ va_end(args);
+ return i;
+}
+
+#ifndef NCSW_VXWORKS
+int Sscan(const char * buf, const char * fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args,fmt);
+ i = vsscanf(buf,fmt,args);
+ va_end(args);
+ return i;
+}
+#endif /* NCSW_VXWORKS */
diff --git a/drivers/net/ethernet/freescale/fman/inc/Peripherals/crc_mac_addr_ext.h b/drivers/net/ethernet/freescale/fman/inc/Peripherals/crc_mac_addr_ext.h
new file mode 100644
index 0000000..a84d563
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/Peripherals/crc_mac_addr_ext.h
@@ -0,0 +1,364 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/*------------------------------------------------------*/
+/* */
+/* File: crc_mac_addr_ext.h */
+/* */
+/* Description: */
+/* Define a macro that calculate the crc value of */
+/* an Ethernet MAC address (48 bitd address */
+/*------------------------------------------------------*/
+
+#ifndef __crc_mac_addr_ext_h
+#define __crc_mac_addr_ext_h
+
+#include "std_ext.h"
+
+
+static uint32_t crc_table[256] =
+{
+ 0x00000000,
+ 0x77073096,
+ 0xee0e612c,
+ 0x990951ba,
+ 0x076dc419,
+ 0x706af48f,
+ 0xe963a535,
+ 0x9e6495a3,
+ 0x0edb8832,
+ 0x79dcb8a4,
+ 0xe0d5e91e,
+ 0x97d2d988,
+ 0x09b64c2b,
+ 0x7eb17cbd,
+ 0xe7b82d07,
+ 0x90bf1d91,
+ 0x1db71064,
+ 0x6ab020f2,
+ 0xf3b97148,
+ 0x84be41de,
+ 0x1adad47d,
+ 0x6ddde4eb,
+ 0xf4d4b551,
+ 0x83d385c7,
+ 0x136c9856,
+ 0x646ba8c0,
+ 0xfd62f97a,
+ 0x8a65c9ec,
+ 0x14015c4f,
+ 0x63066cd9,
+ 0xfa0f3d63,
+ 0x8d080df5,
+ 0x3b6e20c8,
+ 0x4c69105e,
+ 0xd56041e4,
+ 0xa2677172,
+ 0x3c03e4d1,
+ 0x4b04d447,
+ 0xd20d85fd,
+ 0xa50ab56b,
+ 0x35b5a8fa,
+ 0x42b2986c,
+ 0xdbbbc9d6,
+ 0xacbcf940,
+ 0x32d86ce3,
+ 0x45df5c75,
+ 0xdcd60dcf,
+ 0xabd13d59,
+ 0x26d930ac,
+ 0x51de003a,
+ 0xc8d75180,
+ 0xbfd06116,
+ 0x21b4f4b5,
+ 0x56b3c423,
+ 0xcfba9599,
+ 0xb8bda50f,
+ 0x2802b89e,
+ 0x5f058808,
+ 0xc60cd9b2,
+ 0xb10be924,
+ 0x2f6f7c87,
+ 0x58684c11,
+ 0xc1611dab,
+ 0xb6662d3d,
+ 0x76dc4190,
+ 0x01db7106,
+ 0x98d220bc,
+ 0xefd5102a,
+ 0x71b18589,
+ 0x06b6b51f,
+ 0x9fbfe4a5,
+ 0xe8b8d433,
+ 0x7807c9a2,
+ 0x0f00f934,
+ 0x9609a88e,
+ 0xe10e9818,
+ 0x7f6a0dbb,
+ 0x086d3d2d,
+ 0x91646c97,
+ 0xe6635c01,
+ 0x6b6b51f4,
+ 0x1c6c6162,
+ 0x856530d8,
+ 0xf262004e,
+ 0x6c0695ed,
+ 0x1b01a57b,
+ 0x8208f4c1,
+ 0xf50fc457,
+ 0x65b0d9c6,
+ 0x12b7e950,
+ 0x8bbeb8ea,
+ 0xfcb9887c,
+ 0x62dd1ddf,
+ 0x15da2d49,
+ 0x8cd37cf3,
+ 0xfbd44c65,
+ 0x4db26158,
+ 0x3ab551ce,
+ 0xa3bc0074,
+ 0xd4bb30e2,
+ 0x4adfa541,
+ 0x3dd895d7,
+ 0xa4d1c46d,
+ 0xd3d6f4fb,
+ 0x4369e96a,
+ 0x346ed9fc,
+ 0xad678846,
+ 0xda60b8d0,
+ 0x44042d73,
+ 0x33031de5,
+ 0xaa0a4c5f,
+ 0xdd0d7cc9,
+ 0x5005713c,
+ 0x270241aa,
+ 0xbe0b1010,
+ 0xc90c2086,
+ 0x5768b525,
+ 0x206f85b3,
+ 0xb966d409,
+ 0xce61e49f,
+ 0x5edef90e,
+ 0x29d9c998,
+ 0xb0d09822,
+ 0xc7d7a8b4,
+ 0x59b33d17,
+ 0x2eb40d81,
+ 0xb7bd5c3b,
+ 0xc0ba6cad,
+ 0xedb88320,
+ 0x9abfb3b6,
+ 0x03b6e20c,
+ 0x74b1d29a,
+ 0xead54739,
+ 0x9dd277af,
+ 0x04db2615,
+ 0x73dc1683,
+ 0xe3630b12,
+ 0x94643b84,
+ 0x0d6d6a3e,
+ 0x7a6a5aa8,
+ 0xe40ecf0b,
+ 0x9309ff9d,
+ 0x0a00ae27,
+ 0x7d079eb1,
+ 0xf00f9344,
+ 0x8708a3d2,
+ 0x1e01f268,
+ 0x6906c2fe,
+ 0xf762575d,
+ 0x806567cb,
+ 0x196c3671,
+ 0x6e6b06e7,
+ 0xfed41b76,
+ 0x89d32be0,
+ 0x10da7a5a,
+ 0x67dd4acc,
+ 0xf9b9df6f,
+ 0x8ebeeff9,
+ 0x17b7be43,
+ 0x60b08ed5,
+ 0xd6d6a3e8,
+ 0xa1d1937e,
+ 0x38d8c2c4,
+ 0x4fdff252,
+ 0xd1bb67f1,
+ 0xa6bc5767,
+ 0x3fb506dd,
+ 0x48b2364b,
+ 0xd80d2bda,
+ 0xaf0a1b4c,
+ 0x36034af6,
+ 0x41047a60,
+ 0xdf60efc3,
+ 0xa867df55,
+ 0x316e8eef,
+ 0x4669be79,
+ 0xcb61b38c,
+ 0xbc66831a,
+ 0x256fd2a0,
+ 0x5268e236,
+ 0xcc0c7795,
+ 0xbb0b4703,
+ 0x220216b9,
+ 0x5505262f,
+ 0xc5ba3bbe,
+ 0xb2bd0b28,
+ 0x2bb45a92,
+ 0x5cb36a04,
+ 0xc2d7ffa7,
+ 0xb5d0cf31,
+ 0x2cd99e8b,
+ 0x5bdeae1d,
+ 0x9b64c2b0,
+ 0xec63f226,
+ 0x756aa39c,
+ 0x026d930a,
+ 0x9c0906a9,
+ 0xeb0e363f,
+ 0x72076785,
+ 0x05005713,
+ 0x95bf4a82,
+ 0xe2b87a14,
+ 0x7bb12bae,
+ 0x0cb61b38,
+ 0x92d28e9b,
+ 0xe5d5be0d,
+ 0x7cdcefb7,
+ 0x0bdbdf21,
+ 0x86d3d2d4,
+ 0xf1d4e242,
+ 0x68ddb3f8,
+ 0x1fda836e,
+ 0x81be16cd,
+ 0xf6b9265b,
+ 0x6fb077e1,
+ 0x18b74777,
+ 0x88085ae6,
+ 0xff0f6a70,
+ 0x66063bca,
+ 0x11010b5c,
+ 0x8f659eff,
+ 0xf862ae69,
+ 0x616bffd3,
+ 0x166ccf45,
+ 0xa00ae278,
+ 0xd70dd2ee,
+ 0x4e048354,
+ 0x3903b3c2,
+ 0xa7672661,
+ 0xd06016f7,
+ 0x4969474d,
+ 0x3e6e77db,
+ 0xaed16a4a,
+ 0xd9d65adc,
+ 0x40df0b66,
+ 0x37d83bf0,
+ 0xa9bcae53,
+ 0xdebb9ec5,
+ 0x47b2cf7f,
+ 0x30b5ffe9,
+ 0xbdbdf21c,
+ 0xcabac28a,
+ 0x53b39330,
+ 0x24b4a3a6,
+ 0xbad03605,
+ 0xcdd70693,
+ 0x54de5729,
+ 0x23d967bf,
+ 0xb3667a2e,
+ 0xc4614ab8,
+ 0x5d681b02,
+ 0x2a6f2b94,
+ 0xb40bbe37,
+ 0xc30c8ea1,
+ 0x5a05df1b,
+ 0x2d02ef8d
+};
+
+
+#define GET_MAC_ADDR_CRC(addr, crc) \
+{ \
+ uint32_t i; \
+ uint8_t data; \
+ \
+ /* CRC calculation */ \
+ crc = 0xffffffff; \
+ for (i=0; i < 6; i++) \
+ { \
+ data = (uint8_t)(addr >> ((5-i)*8)); \
+ crc = crc^data; \
+ crc = crc_table[crc&0xff] ^ (crc>>8); \
+ } \
+} \
+
+/* Define a macro for getting the mirrored value of */
+/* a byte size number. (0x11010011 --> 0x11001011) */
+/* Sometimes the mirrored value of the CRC is required */
+static __inline__ uint8_t GetMirror(uint8_t n)
+{
+ uint8_t mirror[16] =
+ {
+ 0x00,
+ 0x08,
+ 0x04,
+ 0x0c,
+ 0x02,
+ 0x0a,
+ 0x06,
+ 0x0e,
+ 0x01,
+ 0x09,
+ 0x05,
+ 0x0d,
+ 0x03,
+ 0x0b,
+ 0x07,
+ 0x0f
+ };
+ return ((uint8_t)(((mirror[n & 0x0f] << 4) | (mirror[n >> 4]))));
+}
+
+static __inline__ uint32_t GetMirror32(uint32_t n)
+{
+ return (((uint32_t)GetMirror((uint8_t)(n))<<24) |
+ ((uint32_t)GetMirror((uint8_t)(n>>8))<<16) |
+ ((uint32_t)GetMirror((uint8_t)(n>>16))<<8) |
+ ((uint32_t)GetMirror((uint8_t)(n>>24))));
+}
+
+#define MIRROR GetMirror
+#define MIRROR_32 GetMirror32
+
+
+#endif /* __crc_mac_addr_ext_h */
diff --git a/drivers/net/ethernet/freescale/fman/inc/Peripherals/dpaa_ext.h b/drivers/net/ethernet/freescale/fman/inc/Peripherals/dpaa_ext.h
new file mode 100644
index 0000000..66fa760
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/Peripherals/dpaa_ext.h
@@ -0,0 +1,207 @@
+/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File dpaa_ext.h
+
+ @Description DPAA Application Programming Interface.
+*//***************************************************************************/
+#ifndef __DPAA_EXT_H
+#define __DPAA_EXT_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+
+
+/**************************************************************************//**
+ @Group DPAA_grp Data Path Acceleration Architecture API
+
+ @Description DPAA API functions, definitions and enums.
+
+ @{
+*//***************************************************************************/
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+/**************************************************************************//**
+ @Description Frame descriptor
+*//***************************************************************************/
+typedef _Packed struct t_DpaaFD {
+ volatile uint32_t id; /**< FD id */
+ volatile uint32_t addrl; /**< Data Address */
+ volatile uint32_t length; /**< Frame length */
+ volatile uint32_t status; /**< FD status */
+} _PackedType t_DpaaFD;
+
+/**************************************************************************//**
+ @Description enum for defining frame format
+*//***************************************************************************/
+typedef enum e_DpaaFDFormatType {
+ e_DPAA_FD_FORMAT_TYPE_SHORT_SBSF = 0x0, /**< Simple frame Single buffer; Offset and
+ small length (9b OFFSET, 20b LENGTH) */
+ e_DPAA_FD_FORMAT_TYPE_LONG_SBSF = 0x2, /**< Simple frame, single buffer; big length
+ (29b LENGTH ,No OFFSET) */
+ e_DPAA_FD_FORMAT_TYPE_SHORT_MBSF = 0x4, /**< Simple frame, Scatter Gather table; Offset
+ and small length (9b OFFSET, 20b LENGTH) */
+ e_DPAA_FD_FORMAT_TYPE_LONG_MBSF = 0x6, /**< Simple frame, Scatter Gather table;
+ big length (29b LENGTH ,No OFFSET) */
+ e_DPAA_FD_FORMAT_TYPE_COMPOUND = 0x1, /**< Compound Frame (29b CONGESTION-WEIGHT
+ No LENGTH or OFFSET) */
+ e_DPAA_FD_FORMAT_TYPE_DUMMY
+} e_DpaaFDFormatType;
+
+/**************************************************************************//**
+ @Collection Frame descriptor macros
+*//***************************************************************************/
+#define DPAA_FD_DD_MASK 0xc0000000 /**< FD DD field mask */
+#define DPAA_FD_PID_MASK 0x3f000000 /**< FD PID field mask */
+#define DPAA_FD_ELIODN_MASK 0x0000f000 /**< FD ELIODN field mask */
+#define DPAA_FD_BPID_MASK 0x00ff0000 /**< FD BPID field mask */
+#define DPAA_FD_ADDRH_MASK 0x000000ff /**< FD ADDRH field mask */
+#define DPAA_FD_ADDRL_MASK 0xffffffff /**< FD ADDRL field mask */
+#define DPAA_FD_FORMAT_MASK 0xe0000000 /**< FD FORMAT field mask */
+#define DPAA_FD_OFFSET_MASK 0x1ff00000 /**< FD OFFSET field mask */
+#define DPAA_FD_LENGTH_MASK 0x000fffff /**< FD LENGTH field mask */
+
+#define DPAA_FD_GET_DD(fd) ((((t_DpaaFD *)fd)->id & DPAA_FD_DD_MASK) >> (31-1)) /**< Macro to get FD DD field */
+#define DPAA_FD_GET_PID(fd) (((((t_DpaaFD *)fd)->id & DPAA_FD_PID_MASK) >> (31-7)) | \
+ ((((t_DpaaFD *)fd)->id & DPAA_FD_ELIODN_MASK) >> (31-19-6))) /**< Macro to get FD PID field */
+#define DPAA_FD_GET_BPID(fd) ((((t_DpaaFD *)fd)->id & DPAA_FD_BPID_MASK) >> (31-15)) /**< Macro to get FD BPID field */
+#define DPAA_FD_GET_ADDRH(fd) (((t_DpaaFD *)fd)->id & DPAA_FD_ADDRH_MASK) /**< Macro to get FD ADDRH field */
+#define DPAA_FD_GET_ADDRL(fd) ((t_DpaaFD *)fd)->addrl /**< Macro to get FD ADDRL field */
+#define DPAA_FD_GET_PHYS_ADDR(fd) ((physAddress_t)(((uint64_t)DPAA_FD_GET_ADDRH(fd) << 32) | (uint64_t)DPAA_FD_GET_ADDRL(fd))) /**< Macro to get FD ADDR field */
+#define DPAA_FD_GET_FORMAT(fd) ((((t_DpaaFD *)fd)->length & DPAA_FD_FORMAT_MASK) >> (31-2)) /**< Macro to get FD FORMAT field */
+#define DPAA_FD_GET_OFFSET(fd) ((((t_DpaaFD *)fd)->length & DPAA_FD_OFFSET_MASK) >> (31-11)) /**< Macro to get FD OFFSET field */
+#define DPAA_FD_GET_LENGTH(fd) (((t_DpaaFD *)fd)->length & DPAA_FD_LENGTH_MASK) /**< Macro to get FD LENGTH field */
+#define DPAA_FD_GET_STATUS(fd) ((t_DpaaFD *)fd)->status /**< Macro to get FD STATUS field */
+#define DPAA_FD_GET_ADDR(fd) XX_PhysToVirt(DPAA_FD_GET_PHYS_ADDR(fd)) /**< Macro to get FD ADDR (virtual) */
+
+#define DPAA_FD_SET_DD(fd,val) (((t_DpaaFD *)fd)->id = ((((t_DpaaFD *)fd)->id & ~DPAA_FD_DD_MASK) | (((val) << (31-1)) & DPAA_FD_DD_MASK ))) /**< Macro to set FD DD field */
+ /**< Macro to set FD PID field or LIODN offset*/
+#define DPAA_FD_SET_PID(fd,val) (((t_DpaaFD *)fd)->id = ((((t_DpaaFD *)fd)->id & ~(DPAA_FD_PID_MASK|DPAA_FD_ELIODN_MASK)) | ((((val) << (31-7)) & DPAA_FD_PID_MASK) | ((((val)>>6) << (31-19)) & DPAA_FD_ELIODN_MASK))))
+#define DPAA_FD_SET_BPID(fd,val) (((t_DpaaFD *)fd)->id = ((((t_DpaaFD *)fd)->id & ~DPAA_FD_BPID_MASK) | (((val) << (31-15)) & DPAA_FD_BPID_MASK))) /**< Macro to set FD BPID field */
+#define DPAA_FD_SET_ADDRH(fd,val) (((t_DpaaFD *)fd)->id = ((((t_DpaaFD *)fd)->id & ~DPAA_FD_ADDRH_MASK) | ((val) & DPAA_FD_ADDRH_MASK))) /**< Macro to set FD ADDRH field */
+#define DPAA_FD_SET_ADDRL(fd,val) ((t_DpaaFD *)fd)->addrl = (val) /**< Macro to set FD ADDRL field */
+#define DPAA_FD_SET_ADDR(fd,val) \
+do { \
+ uint64_t physAddr = (uint64_t)(XX_VirtToPhys(val)); \
+ DPAA_FD_SET_ADDRH(fd, ((uint32_t)(physAddr >> 32))); \
+ DPAA_FD_SET_ADDRL(fd, (uint32_t)physAddr); \
+} while (0) /**< Macro to set FD ADDR field */
+#define DPAA_FD_SET_FORMAT(fd,val) (((t_DpaaFD *)fd)->length = ((((t_DpaaFD *)fd)->length & ~DPAA_FD_FORMAT_MASK) | (((val) << (31-2))& DPAA_FD_FORMAT_MASK))) /**< Macro to set FD FORMAT field */
+#define DPAA_FD_SET_OFFSET(fd,val) (((t_DpaaFD *)fd)->length = ((((t_DpaaFD *)fd)->length & ~DPAA_FD_OFFSET_MASK) | (((val) << (31-11))& DPAA_FD_OFFSET_MASK) )) /**< Macro to set FD OFFSET field */
+#define DPAA_FD_SET_LENGTH(fd,val) (((t_DpaaFD *)fd)->length = (((t_DpaaFD *)fd)->length & ~DPAA_FD_LENGTH_MASK) | ((val) & DPAA_FD_LENGTH_MASK)) /**< Macro to set FD LENGTH field */
+#define DPAA_FD_SET_STATUS(fd,val) ((t_DpaaFD *)fd)->status = (val) /**< Macro to set FD STATUS field */
+/* @} */
+
+/**************************************************************************//**
+ @Description Frame Scatter/Gather Table Entry
+*//***************************************************************************/
+typedef _Packed struct t_DpaaSGTE {
+ volatile uint32_t addrh; /**< Buffer Address high */
+ volatile uint32_t addrl; /**< Buffer Address low */
+ volatile uint32_t length; /**< Buffer length */
+ volatile uint32_t offset; /**< SGTE offset */
+} _PackedType t_DpaaSGTE;
+
+#define DPAA_NUM_OF_SG_TABLE_ENTRY 16
+
+/**************************************************************************//**
+ @Description Frame Scatter/Gather Table
+*//***************************************************************************/
+typedef _Packed struct t_DpaaSGT {
+ t_DpaaSGTE tableEntry[DPAA_NUM_OF_SG_TABLE_ENTRY];
+ /**< Structure that holds information about
+ a single S/G entry. */
+} _PackedType t_DpaaSGT;
+
+/**************************************************************************//**
+ @Description Compound Frame Table
+*//***************************************************************************/
+typedef _Packed struct t_DpaaCompTbl {
+ t_DpaaSGTE outputBuffInfo; /**< Structure that holds information about
+ the compound-frame output buffer;
+ NOTE: this may point to a S/G table */
+ t_DpaaSGTE inputBuffInfo; /**< Structure that holds information about
+ the compound-frame input buffer;
+ NOTE: this may point to a S/G table */
+} _PackedType t_DpaaCompTbl;
+
+/**************************************************************************//**
+ @Collection Frame Scatter/Gather Table Entry macros
+*//***************************************************************************/
+#define DPAA_SGTE_ADDRH_MASK 0x000000ff /**< SGTE ADDRH field mask */
+#define DPAA_SGTE_ADDRL_MASK 0xffffffff /**< SGTE ADDRL field mask */
+#define DPAA_SGTE_E_MASK 0x80000000 /**< SGTE Extension field mask */
+#define DPAA_SGTE_F_MASK 0x40000000 /**< SGTE Final field mask */
+#define DPAA_SGTE_LENGTH_MASK 0x3fffffff /**< SGTE LENGTH field mask */
+#define DPAA_SGTE_BPID_MASK 0x00ff0000 /**< SGTE BPID field mask */
+#define DPAA_SGTE_OFFSET_MASK 0x00001fff /**< SGTE OFFSET field mask */
+
+#define DPAA_SGTE_GET_ADDRH(sgte) (((t_DpaaSGTE *)sgte)->addrh & DPAA_SGTE_ADDRH_MASK) /**< Macro to get SGTE ADDRH field */
+#define DPAA_SGTE_GET_ADDRL(sgte) ((t_DpaaSGTE *)sgte)->addrl /**< Macro to get SGTE ADDRL field */
+#define DPAA_SGTE_GET_PHYS_ADDR(sgte) ((physAddress_t)(((uint64_t)DPAA_SGTE_GET_ADDRH(sgte) << 32) | (uint64_t)DPAA_SGTE_GET_ADDRL(sgte))) /**< Macro to get FD ADDR field */
+#define DPAA_SGTE_GET_EXTENSION(sgte) ((((t_DpaaSGTE *)sgte)->length & DPAA_SGTE_E_MASK) >> (31-0)) /**< Macro to get SGTE EXTENSION field */
+#define DPAA_SGTE_GET_FINAL(sgte) ((((t_DpaaSGTE *)sgte)->length & DPAA_SGTE_F_MASK) >> (31-1)) /**< Macro to get SGTE FINAL field */
+#define DPAA_SGTE_GET_LENGTH(sgte) (((t_DpaaSGTE *)sgte)->length & DPAA_SGTE_LENGTH_MASK) /**< Macro to get SGTE LENGTH field */
+#define DPAA_SGTE_GET_BPID(sgte) ((((t_DpaaSGTE *)sgte)->offset & DPAA_SGTE_BPID_MASK) >> (31-15)) /**< Macro to get SGTE BPID field */
+#define DPAA_SGTE_GET_OFFSET(sgte) (((t_DpaaSGTE *)sgte)->offset & DPAA_SGTE_OFFSET_MASK) /**< Macro to get SGTE OFFSET field */
+#define DPAA_SGTE_GET_ADDR(sgte) XX_PhysToVirt(DPAA_SGTE_GET_PHYS_ADDR(sgte))
+
+#define DPAA_SGTE_SET_ADDRH(sgte,val) (((t_DpaaSGTE *)sgte)->addrh = ((((t_DpaaSGTE *)sgte)->addrh & ~DPAA_SGTE_ADDRH_MASK) | ((val) & DPAA_SGTE_ADDRH_MASK))) /**< Macro to set SGTE ADDRH field */
+#define DPAA_SGTE_SET_ADDRL(sgte,val) ((t_DpaaSGTE *)sgte)->addrl = (val) /**< Macro to set SGTE ADDRL field */
+#define DPAA_SGTE_SET_ADDR(sgte,val) \
+do { \
+ uint64_t physAddr = (uint64_t)(XX_VirtToPhys(val)); \
+ DPAA_SGTE_SET_ADDRH(sgte, ((uint32_t)(physAddr >> 32))); \
+ DPAA_SGTE_SET_ADDRL(sgte, (uint32_t)physAddr); \
+} while (0) /**< Macro to set SGTE ADDR field */
+#define DPAA_SGTE_SET_EXTENSION(sgte,val) (((t_DpaaSGTE *)sgte)->length = ((((t_DpaaSGTE *)sgte)->length & ~DPAA_SGTE_E_MASK) | (((val) << (31-0))& DPAA_SGTE_E_MASK))) /**< Macro to set SGTE EXTENSION field */
+#define DPAA_SGTE_SET_FINAL(sgte,val) (((t_DpaaSGTE *)sgte)->length = ((((t_DpaaSGTE *)sgte)->length & ~DPAA_SGTE_F_MASK) | (((val) << (31-1))& DPAA_SGTE_F_MASK))) /**< Macro to set SGTE FINAL field */
+#define DPAA_SGTE_SET_LENGTH(sgte,val) (((t_DpaaSGTE *)sgte)->length = (((t_DpaaSGTE *)sgte)->length & ~DPAA_SGTE_LENGTH_MASK) | ((val) & DPAA_SGTE_LENGTH_MASK)) /**< Macro to set SGTE LENGTH field */
+#define DPAA_SGTE_SET_BPID(sgte,val) (((t_DpaaSGTE *)sgte)->offset = ((((t_DpaaSGTE *)sgte)->offset & ~DPAA_SGTE_BPID_MASK) | (((val) << (31-15))& DPAA_SGTE_BPID_MASK))) /**< Macro to set SGTE BPID field */
+#define DPAA_SGTE_SET_OFFSET(sgte,val) (((t_DpaaSGTE *)sgte)->offset = ((((t_DpaaSGTE *)sgte)->offset & ~DPAA_SGTE_OFFSET_MASK) | (((val) << (31-31))& DPAA_SGTE_OFFSET_MASK) )) /**< Macro to set SGTE OFFSET field */
+/* @} */
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+#define DPAA_LIODN_DONT_OVERRIDE (-1)
+
+/** @} */ /* end of DPAA_grp group */
+
+
+#endif /* __DPAA_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_ext.h b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_ext.h
new file mode 100644
index 0000000..a45682f
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_ext.h
@@ -0,0 +1,1684 @@
+/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File fm_ext.h
+
+ @Description FM Application Programming Interface.
+*//***************************************************************************/
+#ifndef __FM_EXT
+#define __FM_EXT
+
+#include "error_ext.h"
+#include "std_ext.h"
+#include "dpaa_ext.h"
+#include "fsl_fman_sp.h"
+
+/**************************************************************************//**
+ @Group FM_grp Frame Manager API
+
+ @Description FM API functions, definitions and enums.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group FM_lib_grp FM library
+
+ @Description FM API functions, definitions and enums.
+
+ The FM module is the main driver module and is a mandatory module
+ for FM driver users. This module must be initialized first prior
+ to any other drivers modules.
+ The FM is a "singleton" module. It is responsible of the common
+ HW modules: FPM, DMA, common QMI and common BMI initializations and
+ run-time control routines. This module must be initialized always
+ when working with any of the FM modules.
+ NOTE - We assume that the FM library will be initialized only by core No. 0!
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Description Enum for defining port types
+*//***************************************************************************/
+typedef enum e_FmPortType {
+ e_FM_PORT_TYPE_OH_OFFLINE_PARSING = 0, /**< Offline parsing port */
+ e_FM_PORT_TYPE_RX, /**< 1G Rx port */
+ e_FM_PORT_TYPE_RX_10G, /**< 10G Rx port */
+ e_FM_PORT_TYPE_TX, /**< 1G Tx port */
+ e_FM_PORT_TYPE_TX_10G, /**< 10G Tx port */
+ e_FM_PORT_TYPE_DUMMY
+} e_FmPortType;
+
+/**************************************************************************//**
+ @Collection General FM defines
+*//***************************************************************************/
+#define FM_MAX_NUM_OF_PARTITIONS 64 /**< Maximum number of partitions */
+#define FM_PHYS_ADDRESS_SIZE 6 /**< FM Physical address size */
+/* @} */
+
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+
+/**************************************************************************//**
+ @Description FM physical Address
+*//***************************************************************************/
+typedef _Packed struct t_FmPhysAddr {
+ volatile uint8_t high; /**< High part of the physical address */
+ volatile uint32_t low; /**< Low part of the physical address */
+} _PackedType t_FmPhysAddr;
+
+/**************************************************************************//**
+ @Description Parse results memory layout
+*//***************************************************************************/
+typedef _Packed struct t_FmPrsResult {
+ volatile uint8_t lpid; /**< Logical port id */
+ volatile uint8_t shimr; /**< Shim header result */
+ volatile uint16_t l2r; /**< Layer 2 result */
+ volatile uint16_t l3r; /**< Layer 3 result */
+ volatile uint8_t l4r; /**< Layer 4 result */
+ volatile uint8_t cplan; /**< Classification plan id */
+ volatile uint16_t nxthdr; /**< Next Header */
+ volatile uint16_t cksum; /**< Running-sum */
+ volatile uint16_t flags_frag_off; /**< Flags & fragment-offset field of the last IP-header */
+ volatile uint8_t route_type; /**< Routing type field of a IPv6 routing extension header */
+ volatile uint8_t rhp_ip_valid; /**< Routing Extension Header Present; last bit is IP valid */
+ volatile uint8_t shim_off[2]; /**< Shim offset */
+ volatile uint8_t ip_pid_off; /**< IP PID (last IP-proto) offset */
+ volatile uint8_t eth_off; /**< ETH offset */
+ volatile uint8_t llc_snap_off; /**< LLC_SNAP offset */
+ volatile uint8_t vlan_off[2]; /**< VLAN offset */
+ volatile uint8_t etype_off; /**< ETYPE offset */
+ volatile uint8_t pppoe_off; /**< PPP offset */
+ volatile uint8_t mpls_off[2]; /**< MPLS offset */
+ volatile uint8_t ip_off[2]; /**< IP offset */
+ volatile uint8_t gre_off; /**< GRE offset */
+ volatile uint8_t l4_off; /**< Layer 4 offset */
+ volatile uint8_t nxthdr_off; /**< Parser end point */
+} _PackedType t_FmPrsResult;
+
+/**************************************************************************//**
+ @Collection FM Parser results
+*//***************************************************************************/
+#define FM_PR_L2_VLAN_STACK 0x00000100 /**< Parse Result: VLAN stack */
+#define FM_PR_L2_ETHERNET 0x00008000 /**< Parse Result: Ethernet*/
+#define FM_PR_L2_VLAN 0x00004000 /**< Parse Result: VLAN */
+#define FM_PR_L2_LLC_SNAP 0x00002000 /**< Parse Result: LLC_SNAP */
+#define FM_PR_L2_MPLS 0x00001000 /**< Parse Result: MPLS */
+#define FM_PR_L2_PPPoE 0x00000800 /**< Parse Result: PPPoE */
+/* @} */
+
+/**************************************************************************//**
+ @Collection FM Frame descriptor macros
+*//***************************************************************************/
+#define FM_FD_CMD_FCO 0x80000000 /**< Frame queue Context Override */
+#define FM_FD_CMD_RPD 0x40000000 /**< Read Prepended Data */
+#define FM_FD_CMD_UPD 0x20000000 /**< Update Prepended Data */
+#define FM_FD_CMD_DTC 0x10000000 /**< Do L4 Checksum */
+#define FM_FD_CMD_DCL4C 0x10000000 /**< Didn't calculate L4 Checksum */
+#define FM_FD_CMD_CFQ 0x00ffffff /**< Confirmation Frame Queue */
+
+#define FM_FD_ERR_UNSUPPORTED_FORMAT 0x04000000 /**< Not for Rx-Port! Unsupported Format */
+#define FM_FD_ERR_LENGTH 0x02000000 /**< Not for Rx-Port! Length Error */
+#define FM_FD_ERR_DMA 0x01000000 /**< DMA Data error */
+
+#define FM_FD_IPR 0x00000001 /**< IPR frame (not error) */
+
+#define FM_FD_ERR_IPR_NCSP (0x00100000 | FM_FD_IPR) /**< IPR non-consistent-sp */
+#define FM_FD_ERR_IPR (0x00200000 | FM_FD_IPR) /**< IPR error */
+#define FM_FD_ERR_IPR_TO (0x00300000 | FM_FD_IPR) /**< IPR timeout */
+
+#ifdef FM_CAPWAP_SUPPORT
+#define FM_FD_ERR_CRE 0x00200000
+#define FM_FD_ERR_CHE 0x00100000
+#endif /* FM_CAPWAP_SUPPORT */
+
+#define FM_FD_ERR_PHYSICAL 0x00080000 /**< Rx FIFO overflow, FCS error, code error, running disparity
+ error (SGMII and TBI modes), FIFO parity error. PHY
+ Sequence error, PHY error control character detected. */
+#define FM_FD_ERR_SIZE 0x00040000 /**< Frame too long OR Frame size exceeds max_length_frame */
+#define FM_FD_ERR_CLS_DISCARD 0x00020000 /**< classification discard */
+#define FM_FD_ERR_EXTRACTION 0x00008000 /**< Extract Out of Frame */
+#define FM_FD_ERR_NO_SCHEME 0x00004000 /**< No Scheme Selected */
+#define FM_FD_ERR_KEYSIZE_OVERFLOW 0x00002000 /**< Keysize Overflow */
+#define FM_FD_ERR_COLOR_RED 0x00000800 /**< Frame color is red */
+#define FM_FD_ERR_COLOR_YELLOW 0x00000400 /**< Frame color is yellow */
+#define FM_FD_ERR_ILL_PLCR 0x00000200 /**< Illegal Policer Profile selected */
+#define FM_FD_ERR_PLCR_FRAME_LEN 0x00000100 /**< Policer frame length error */
+#define FM_FD_ERR_PRS_TIMEOUT 0x00000080 /**< Parser Time out Exceed */
+#define FM_FD_ERR_PRS_ILL_INSTRUCT 0x00000040 /**< Invalid Soft Parser instruction */
+#define FM_FD_ERR_PRS_HDR_ERR 0x00000020 /**< Header error was identified during parsing */
+#define FM_FD_ERR_BLOCK_LIMIT_EXCEEDED 0x00000008 /**< Frame parsed beyind 256 first bytes */
+
+#define FM_FD_TX_STATUS_ERR_MASK (FM_FD_ERR_UNSUPPORTED_FORMAT | \
+ FM_FD_ERR_LENGTH | \
+ FM_FD_ERR_DMA) /**< TX Error FD bits */
+
+#define FM_FD_RX_STATUS_ERR_MASK (FM_FD_ERR_UNSUPPORTED_FORMAT | \
+ FM_FD_ERR_LENGTH | \
+ FM_FD_ERR_DMA | \
+ FM_FD_ERR_IPR | \
+ FM_FD_ERR_IPR_TO | \
+ FM_FD_ERR_IPR_NCSP | \
+ FM_FD_ERR_PHYSICAL | \
+ FM_FD_ERR_SIZE | \
+ FM_FD_ERR_CLS_DISCARD | \
+ FM_FD_ERR_COLOR_RED | \
+ FM_FD_ERR_COLOR_YELLOW | \
+ FM_FD_ERR_ILL_PLCR | \
+ FM_FD_ERR_PLCR_FRAME_LEN | \
+ FM_FD_ERR_EXTRACTION | \
+ FM_FD_ERR_NO_SCHEME | \
+ FM_FD_ERR_KEYSIZE_OVERFLOW | \
+ FM_FD_ERR_PRS_TIMEOUT | \
+ FM_FD_ERR_PRS_ILL_INSTRUCT | \
+ FM_FD_ERR_PRS_HDR_ERR | \
+ FM_FD_ERR_BLOCK_LIMIT_EXCEEDED) /**< RX Error FD bits */
+
+#define FM_FD_RX_STATUS_ERR_NON_FM 0x00400000 /**< non Frame-Manager error */
+/* @} */
+
+/**************************************************************************//**
+ @Description Context A
+*//***************************************************************************/
+typedef _Packed struct t_FmContextA {
+ volatile uint32_t command; /**< ContextA Command */
+ volatile uint8_t res0[4]; /**< ContextA Reserved bits */
+} _PackedType t_FmContextA;
+
+/**************************************************************************//**
+ @Description Context B
+*//***************************************************************************/
+typedef uint32_t t_FmContextB;
+
+/**************************************************************************//**
+ @Collection Special Operation options
+*//***************************************************************************/
+typedef uint32_t fmSpecialOperations_t; /**< typedef for defining Special Operation options */
+
+#define FM_SP_OP_IPSEC 0x80000000 /**< activate features that related to IPSec (e.g fix Eth-type) */
+#define FM_SP_OP_IPSEC_UPDATE_UDP_LEN 0x40000000 /**< update the UDP-Len after Encryption */
+#define FM_SP_OP_IPSEC_MANIP 0x20000000 /**< handle the IPSec-manip options */
+#define FM_SP_OP_RPD 0x10000000 /**< Set the RPD bit */
+#define FM_SP_OP_DCL4C 0x08000000 /**< Set the DCL4C bit */
+#define FM_SP_OP_CHECK_SEC_ERRORS 0x04000000 /**< Check SEC errors */
+#define FM_SP_OP_CLEAR_RPD 0x02000000 /**< Clear the RPD bit */
+/* @} */
+
+/**************************************************************************//**
+ @Collection Context A macros
+*//***************************************************************************/
+#define FM_CONTEXTA_OVERRIDE_MASK 0x80000000
+#define FM_CONTEXTA_ICMD_MASK 0x40000000
+#define FM_CONTEXTA_A1_VALID_MASK 0x20000000
+#define FM_CONTEXTA_MACCMD_MASK 0x00ff0000
+#define FM_CONTEXTA_MACCMD_VALID_MASK 0x00800000
+#define FM_CONTEXTA_MACCMD_SECURED_MASK 0x00100000
+#define FM_CONTEXTA_MACCMD_SC_MASK 0x000f0000
+#define FM_CONTEXTA_A1_MASK 0x0000ffff
+
+#define FM_CONTEXTA_GET_OVERRIDE(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_OVERRIDE_MASK) >> (31-0))
+#define FM_CONTEXTA_GET_ICMD(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_ICMD_MASK) >> (31-1))
+#define FM_CONTEXTA_GET_A1_VALID(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_A1_VALID_MASK) >> (31-2))
+#define FM_CONTEXTA_GET_A1(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_A1_MASK) >> (31-31))
+#define FM_CONTEXTA_GET_MACCMD(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_MACCMD_MASK) >> (31-15))
+#define FM_CONTEXTA_GET_MACCMD_VALID(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_MACCMD_VALID_MASK) >> (31-8))
+#define FM_CONTEXTA_GET_MACCMD_SECURED(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_MACCMD_SECURED_MASK) >> (31-11))
+#define FM_CONTEXTA_GET_MACCMD_SECURE_CHANNEL(contextA) ((((t_FmContextA *)contextA)->command & FM_CONTEXTA_MACCMD_SC_MASK) >> (31-15))
+
+#define FM_CONTEXTA_SET_OVERRIDE(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_OVERRIDE_MASK) | (((uint32_t)(val) << (31-0)) & FM_CONTEXTA_OVERRIDE_MASK) ))
+#define FM_CONTEXTA_SET_ICMD(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_ICMD_MASK) | (((val) << (31-1)) & FM_CONTEXTA_ICMD_MASK) ))
+#define FM_CONTEXTA_SET_A1_VALID(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_A1_VALID_MASK) | (((val) << (31-2)) & FM_CONTEXTA_A1_VALID_MASK) ))
+#define FM_CONTEXTA_SET_A1(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_A1_MASK) | (((val) << (31-31)) & FM_CONTEXTA_A1_MASK) ))
+#define FM_CONTEXTA_SET_MACCMD(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_MACCMD_MASK) | (((val) << (31-15)) & FM_CONTEXTA_MACCMD_MASK) ))
+#define FM_CONTEXTA_SET_MACCMD_VALID(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_MACCMD_VALID_MASK) | (((val) << (31-8)) & FM_CONTEXTA_MACCMD_VALID_MASK) ))
+#define FM_CONTEXTA_SET_MACCMD_SECURED(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_MACCMD_SECURED_MASK) | (((val) << (31-11)) & FM_CONTEXTA_MACCMD_SECURED_MASK) ))
+#define FM_CONTEXTA_SET_MACCMD_SECURE_CHANNEL(contextA,val) (((t_FmContextA *)contextA)->command = (uint32_t)((((t_FmContextA *)contextA)->command & ~FM_CONTEXTA_MACCMD_SC_MASK) | (((val) << (31-15)) & FM_CONTEXTA_MACCMD_SC_MASK) ))
+/* @} */
+
+/**************************************************************************//**
+ @Collection Context B macros
+*//***************************************************************************/
+#define FM_CONTEXTB_FQID_MASK 0x00ffffff
+
+#define FM_CONTEXTB_GET_FQID(contextB) (*((t_FmContextB *)contextB) & FM_CONTEXTB_FQID_MASK)
+#define FM_CONTEXTB_SET_FQID(contextB,val) (*((t_FmContextB *)contextB) = ((*((t_FmContextB *)contextB) & ~FM_CONTEXTB_FQID_MASK) | ((val) & FM_CONTEXTB_FQID_MASK)))
+/* @} */
+
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+
+
+/**************************************************************************//**
+ @Description FM Exceptions
+*//***************************************************************************/
+typedef enum e_FmExceptions {
+ e_FM_EX_DMA_BUS_ERROR = 0, /**< DMA bus error. */
+ e_FM_EX_DMA_READ_ECC, /**< Read Buffer ECC error (Valid for FM rev < 6)*/
+ e_FM_EX_DMA_SYSTEM_WRITE_ECC, /**< Write Buffer ECC error on system side (Valid for FM rev < 6)*/
+ e_FM_EX_DMA_FM_WRITE_ECC, /**< Write Buffer ECC error on FM side (Valid for FM rev < 6)*/
+ e_FM_EX_DMA_SINGLE_PORT_ECC, /**< Single Port ECC error on FM side (Valid for FM rev > 6)*/
+ e_FM_EX_FPM_STALL_ON_TASKS, /**< Stall of tasks on FPM */
+ e_FM_EX_FPM_SINGLE_ECC, /**< Single ECC on FPM. */
+ e_FM_EX_FPM_DOUBLE_ECC, /**< Double ECC error on FPM ram access */
+ e_FM_EX_QMI_SINGLE_ECC, /**< Single ECC on QMI. */
+ e_FM_EX_QMI_DOUBLE_ECC, /**< Double bit ECC occurred on QMI */
+ e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID,/**< Dequeue from unknown port id */
+ e_FM_EX_BMI_LIST_RAM_ECC, /**< Linked List RAM ECC error */
+ e_FM_EX_BMI_STORAGE_PROFILE_ECC, /**< Storage Profile ECC Error */
+ e_FM_EX_BMI_STATISTICS_RAM_ECC, /**< Statistics Count RAM ECC Error Enable */
+ e_FM_EX_BMI_DISPATCH_RAM_ECC, /**< Dispatch RAM ECC Error Enable */
+ e_FM_EX_IRAM_ECC, /**< Double bit ECC occurred on IRAM*/
+ e_FM_EX_MURAM_ECC /**< Double bit ECC occurred on MURAM*/
+} e_FmExceptions;
+
+/**************************************************************************//**
+ @Description Enum for defining port DMA swap mode
+*//***************************************************************************/
+typedef enum e_FmDmaSwapOption {
+ e_FM_DMA_NO_SWP = FMAN_DMA_NO_SWP, /**< No swap, transfer data as is.*/
+ e_FM_DMA_SWP_PPC_LE = FMAN_DMA_SWP_PPC_LE, /**< The transferred data should be swapped
+ in PowerPc Little Endian mode. */
+ e_FM_DMA_SWP_BE = FMAN_DMA_SWP_BE /**< The transferred data should be swapped
+ in Big Endian mode */
+} e_FmDmaSwapOption;
+
+/**************************************************************************//**
+ @Description Enum for defining port DMA cache attributes
+*//***************************************************************************/
+typedef enum e_FmDmaCacheOption {
+ e_FM_DMA_NO_STASH = FMAN_DMA_NO_STASH, /**< Cacheable, no Allocate (No Stashing) */
+ e_FM_DMA_STASH = FMAN_DMA_STASH /**< Cacheable and Allocate (Stashing on) */
+} e_FmDmaCacheOption;
+
+
+/**************************************************************************//**
+ @Group FM_init_grp FM Initialization Unit
+
+ @Description FM Initialization Unit
+
+ Initialization Flow
+ Initialization of the FM Module will be carried out by the application
+ according to the following sequence:
+ - Calling the configuration routine with basic parameters.
+ - Calling the advance initialization routines to change driver's defaults.
+ - Calling the initialization routine.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Function t_FmExceptionsCallback
+
+ @Description Exceptions user callback routine, will be called upon an
+ exception passing the exception identification.
+
+ @Param[in] h_App - User's application descriptor.
+ @Param[in] exception - The exception.
+*//***************************************************************************/
+typedef void (t_FmExceptionsCallback)(t_Handle h_App,
+ e_FmExceptions exception);
+
+
+/**************************************************************************//**
+ @Function t_FmBusErrorCallback
+
+ @Description Bus error user callback routine, will be called upon a
+ bus error, passing parameters describing the errors and the owner.
+
+ @Param[in] h_App - User's application descriptor.
+ @Param[in] portType - Port type (e_FmPortType)
+ @Param[in] portId - Port id - relative to type.
+ @Param[in] addr - Address that caused the error
+ @Param[in] tnum - Owner of error
+ @Param[in] liodn - Logical IO device number
+*//***************************************************************************/
+typedef void (t_FmBusErrorCallback) (t_Handle h_App,
+ e_FmPortType portType,
+ uint8_t portId,
+ uint64_t addr,
+ uint8_t tnum,
+ uint16_t liodn);
+
+/**************************************************************************//**
+ @Description A structure for defining buffer prefix area content.
+*//***************************************************************************/
+typedef struct t_FmBufferPrefixContent {
+ uint16_t privDataSize; /**< Number of bytes to be left at the beginning
+ of the external buffer; Note that the private-area will
+ start from the base of the buffer address. */
+ bool passPrsResult; /**< TRUE to pass the parse result to/from the FM;
+ User may use FM_PORT_GetBufferPrsResult() in order to
+ get the parser-result from a buffer. */
+ bool passTimeStamp; /**< TRUE to pass the timeStamp to/from the FM
+ User may use FM_PORT_GetBufferTimeStamp() in order to
+ get the parser-result from a buffer. */
+ bool passHashResult; /**< TRUE to pass the KG hash result to/from the FM
+ User may use FM_PORT_GetBufferHashResult() in order to
+ get the parser-result from a buffer. */
+ bool passAllOtherPCDInfo;/**< Add all other Internal-Context information:
+ AD, hash-result, key, etc. */
+ uint16_t dataAlign; /**< 0 to use driver's default alignment [DEFAULT_FM_SP_bufferPrefixContent_dataAlign],
+ other value for selecting a data alignment (must be a power of 2);
+ if write optimization is used, must be >= 16. */
+ uint8_t manipExtraSpace; /**< Maximum extra size needed (insertion-size minus removal-size);
+ Note that this field impacts the size of the buffer-prefix
+ (i.e. it pushes the data offset);
+ This field is irrelevant if DPAA_VERSION==10 */
+} t_FmBufferPrefixContent;
+
+/**************************************************************************//**
+ @Description A structure of information about each of the external
+ buffer pools used by a port or storage-profile.
+*//***************************************************************************/
+typedef struct t_FmExtPoolParams {
+ uint8_t id; /**< External buffer pool id */
+ uint16_t size; /**< External buffer pool buffer size */
+} t_FmExtPoolParams;
+
+/**************************************************************************//**
+ @Description A structure for informing the driver about the external
+ buffer pools allocated in the BM and used by a port or a
+ storage-profile.
+*//***************************************************************************/
+typedef struct t_FmExtPools {
+ uint8_t numOfPoolsUsed; /**< Number of pools use by this port */
+ t_FmExtPoolParams extBufPool[FM_PORT_MAX_NUM_OF_EXT_POOLS];
+ /**< Parameters for each port */
+} t_FmExtPools;
+
+/**************************************************************************//**
+ @Description A structure for defining backup BM Pools.
+*//***************************************************************************/
+typedef struct t_FmBackupBmPools {
+ uint8_t numOfBackupPools; /**< Number of BM backup pools -
+ must be smaller than the total number of
+ pools defined for the specified port.*/
+ uint8_t poolIds[FM_PORT_MAX_NUM_OF_EXT_POOLS];
+ /**< numOfBackupPools pool id's, specifying which
+ pools should be used only as backup. Pool
+ id's specified here must be a subset of the
+ pools used by the specified port.*/
+} t_FmBackupBmPools;
+
+/**************************************************************************//**
+ @Description A structure for defining BM pool depletion criteria
+*//***************************************************************************/
+typedef struct t_FmBufPoolDepletion {
+ bool poolsGrpModeEnable; /**< select mode in which pause frames will be sent after
+ a number of pools (all together!) are depleted */
+ uint8_t numOfPools; /**< the number of depleted pools that will invoke
+ pause frames transmission. */
+ bool poolsToConsider[BM_MAX_NUM_OF_POOLS];
+ /**< For each pool, TRUE if it should be considered for
+ depletion (Note - this pool must be used by this port!). */
+ bool singlePoolModeEnable; /**< select mode in which pause frames will be sent after
+ a single-pool is depleted; */
+ bool poolsToConsiderForSingleMode[BM_MAX_NUM_OF_POOLS];
+ /**< For each pool, TRUE if it should be considered for
+ depletion (Note - this pool must be used by this port!) */
+#if (DPAA_VERSION >= 11)
+ bool pfcPrioritiesEn[FM_MAX_NUM_OF_PFC_PRIORITIES];
+ /**< This field is used by the MAC as the Priority Enable Vector in the PFC frame which is transmitted */
+#endif /* (DPAA_VERSION >= 11) */
+} t_FmBufPoolDepletion;
+
+/**************************************************************************//**
+ @Description A Structure for defining Ucode patch for loading.
+*//***************************************************************************/
+typedef struct t_FmFirmwareParams {
+ uint32_t size; /**< Size of uCode */
+ uint32_t *p_Code; /**< A pointer to the uCode */
+} t_FmFirmwareParams;
+
+/**************************************************************************//**
+ @Description A Structure for defining FM initialization parameters
+*//***************************************************************************/
+typedef struct t_FmParams {
+ uint8_t fmId; /**< Index of the FM */
+ uint8_t guestId; /**< FM Partition Id */
+ uintptr_t baseAddr; /**< A pointer to base of memory mapped FM registers (virtual);
+ this field is optional when the FM runs in "guest-mode"
+ (i.e. guestId != NCSW_MASTER_ID); in that case, the driver will
+ use the memory-map instead of calling the IPC where possible;
+ NOTE that this should include ALL common registers of the FM including
+ the PCD registers area (i.e. until the VSP pages - 880KB). */
+ t_Handle h_FmMuram; /**< A handle of an initialized MURAM object,
+ to be used by the FM. */
+ uint16_t fmClkFreq; /**< In Mhz;
+ Relevant when FM not runs in "guest-mode". */
+ t_FmExceptionsCallback *f_Exception; /**< An application callback routine to handle exceptions;
+ Relevant when FM not runs in "guest-mode". */
+ t_FmBusErrorCallback *f_BusError; /**< An application callback routine to handle exceptions;
+ Relevant when FM not runs in "guest-mode". */
+ t_Handle h_App; /**< A handle to an application layer object; This handle will
+ be passed by the driver upon calling the above callbacks;
+ Relevant when FM not runs in "guest-mode". */
+ int irq; /**< FM interrupt source for normal events;
+ Relevant when FM not runs in "guest-mode". */
+ int errIrq; /**< FM interrupt source for errors;
+ Relevant when FM not runs in "guest-mode". */
+ t_FmFirmwareParams firmware; /**< The firmware parameters structure;
+ Relevant when FM not runs in "guest-mode". */
+
+#if (DPAA_VERSION >= 11)
+ uintptr_t vspBaseAddr; /**< A pointer to base of memory mapped FM VSP registers (virtual);
+ i.e. up to 24KB, depending on the specific chip. */
+ uint8_t partVSPBase; /**< The first Virtual-Storage-Profile-id dedicated to this partition.
+ NOTE: this parameter relevant only when working with multiple partitions. */
+ uint8_t partNumOfVSPs; /**< Number of VSPs dedicated to this partition.
+ NOTE: this parameter relevant only when working with multiple partitions. */
+#endif /* (DPAA_VERSION >= 11) */
+} t_FmParams;
+
+
+/**************************************************************************//**
+ @Function FM_Config
+
+ @Description Creates the FM module and returns its handle (descriptor).
+ This descriptor must be passed as first parameter to all other
+ FM function calls.
+
+ No actual initialization or configuration of FM hardware is
+ done by this routine. All FM parameters get default values that
+ may be changed by calling one or more of the advance config routines.
+
+ @Param[in] p_FmParams - A pointer to a data structure of mandatory FM parameters
+
+ @Return A handle to the FM object, or NULL for Failure.
+*//***************************************************************************/
+t_Handle FM_Config(t_FmParams *p_FmParams);
+
+/**************************************************************************//**
+ @Function FM_Init
+
+ @Description Initializes the FM module by defining the software structure
+ and configuring the hardware registers.
+
+ @Param[in] h_Fm - FM module descriptor
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_Init(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FM_Free
+
+ @Description Frees all resources that were assigned to FM module.
+
+ Calling this routine invalidates the descriptor.
+
+ @Param[in] h_Fm - FM module descriptor
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_Free(t_Handle h_Fm);
+
+
+/**************************************************************************//**
+ @Group FM_advanced_init_grp FM Advanced Configuration Unit
+
+ @Description Advanced configuration routines are optional routines that may
+ be called in order to change the default driver settings.
+
+ Note: Advanced configuration routines are not available for guest partition.
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Description Enum for selecting DMA debug mode
+*//***************************************************************************/
+typedef enum e_FmDmaDbgCntMode {
+ e_FM_DMA_DBG_NO_CNT = 0, /**< No counting */
+ e_FM_DMA_DBG_CNT_DONE, /**< Count DONE commands */
+ e_FM_DMA_DBG_CNT_COMM_Q_EM, /**< count command queue emergency signals */
+ e_FM_DMA_DBG_CNT_INT_READ_EM, /**< Count Internal Read buffer emergency signal */
+ e_FM_DMA_DBG_CNT_INT_WRITE_EM, /**< Count Internal Write buffer emergency signal */
+ e_FM_DMA_DBG_CNT_FPM_WAIT, /**< Count FPM WAIT signal */
+ e_FM_DMA_DBG_CNT_SIGLE_BIT_ECC, /**< Single bit ECC errors. */
+ e_FM_DMA_DBG_CNT_RAW_WAR_PROT /**< Number of times there was a need for RAW & WAR protection. */
+} e_FmDmaDbgCntMode;
+
+/**************************************************************************//**
+ @Description Enum for selecting DMA Cache Override
+*//***************************************************************************/
+typedef enum e_FmDmaCacheOverride {
+ e_FM_DMA_NO_CACHE_OR = 0, /**< No override of the Cache field */
+ e_FM_DMA_NO_STASH_DATA, /**< Data should not be stashed in system level cache */
+ e_FM_DMA_MAY_STASH_DATA, /**< Data may be stashed in system level cache */
+ e_FM_DMA_STASH_DATA /**< Data should be stashed in system level cache */
+} e_FmDmaCacheOverride;
+
+/**************************************************************************//**
+ @Description Enum for selecting DMA External Bus Priority
+*//***************************************************************************/
+typedef enum e_FmDmaExtBusPri {
+ e_FM_DMA_EXT_BUS_NORMAL = 0, /**< Normal priority */
+ e_FM_DMA_EXT_BUS_EBS, /**< AXI extended bus service priority */
+ e_FM_DMA_EXT_BUS_SOS, /**< AXI sos priority */
+ e_FM_DMA_EXT_BUS_EBS_AND_SOS /**< AXI ebs + sos priority */
+} e_FmDmaExtBusPri;
+
+/**************************************************************************//**
+ @Description Enum for choosing the field that will be output on AID
+*//***************************************************************************/
+typedef enum e_FmDmaAidMode {
+ e_FM_DMA_AID_OUT_PORT_ID = 0, /**< 4 LSB of PORT_ID */
+ e_FM_DMA_AID_OUT_TNUM /**< 4 LSB of TNUM */
+} e_FmDmaAidMode;
+
+/**************************************************************************//**
+ @Description Enum for selecting FPM Catastrophic error behavior
+*//***************************************************************************/
+typedef enum e_FmCatastrophicErr {
+ e_FM_CATASTROPHIC_ERR_STALL_PORT = 0, /**< Port_ID is stalled (only reset can release it) */
+ e_FM_CATASTROPHIC_ERR_STALL_TASK /**< Only erroneous task is stalled */
+} e_FmCatastrophicErr;
+
+/**************************************************************************//**
+ @Description Enum for selecting FPM DMA Error behavior
+*//***************************************************************************/
+typedef enum e_FmDmaErr {
+ e_FM_DMA_ERR_CATASTROPHIC = 0, /**< Dma error is treated as a catastrophic
+ error (e_FmCatastrophicErr)*/
+ e_FM_DMA_ERR_REPORT /**< Dma error is just reported */
+} e_FmDmaErr;
+
+/**************************************************************************//**
+ @Description Enum for selecting DMA Emergency level by BMI emergency signal
+*//***************************************************************************/
+typedef enum e_FmDmaEmergencyLevel {
+ e_FM_DMA_EM_EBS = 0, /**< EBS emergency */
+ e_FM_DMA_EM_SOS /**< SOS emergency */
+} e_FmDmaEmergencyLevel;
+
+/**************************************************************************//**
+ @Collection Enum for selecting DMA Emergency options
+*//***************************************************************************/
+typedef uint32_t fmEmergencyBus_t; /**< DMA emergency options */
+
+#define FM_DMA_MURAM_READ_EMERGENCY 0x00800000 /**< Enable emergency for MURAM1 */
+#define FM_DMA_MURAM_WRITE_EMERGENCY 0x00400000 /**< Enable emergency for MURAM2 */
+#define FM_DMA_EXT_BUS_EMERGENCY 0x00100000 /**< Enable emergency for external bus */
+/* @} */
+
+/**************************************************************************//**
+ @Description A structure for defining DMA emergency level
+*//***************************************************************************/
+typedef struct t_FmDmaEmergency {
+ fmEmergencyBus_t emergencyBusSelect; /**< An OR of the busses where emergency
+ should be enabled */
+ e_FmDmaEmergencyLevel emergencyLevel; /**< EBS/SOS */
+} t_FmDmaEmergency;
+
+/**************************************************************************//*
+ @Description structure for defining FM threshold
+*//***************************************************************************/
+typedef struct t_FmThresholds {
+ uint8_t dispLimit; /**< The number of times a frames may
+ be passed in the FM before assumed to
+ be looping. */
+ uint8_t prsDispTh; /**< This is the number pf packets that may be
+ queued in the parser dispatch queue*/
+ uint8_t plcrDispTh; /**< This is the number pf packets that may be
+ queued in the policer dispatch queue*/
+ uint8_t kgDispTh; /**< This is the number pf packets that may be
+ queued in the keygen dispatch queue*/
+ uint8_t bmiDispTh; /**< This is the number pf packets that may be
+ queued in the BMI dispatch queue*/
+ uint8_t qmiEnqDispTh; /**< This is the number pf packets that may be
+ queued in the QMI enqueue dispatch queue*/
+ uint8_t qmiDeqDispTh; /**< This is the number pf packets that may be
+ queued in the QMI dequeue dispatch queue*/
+ uint8_t fmCtl1DispTh; /**< This is the number pf packets that may be
+ queued in fmCtl1 dispatch queue*/
+ uint8_t fmCtl2DispTh; /**< This is the number pf packets that may be
+ queued in fmCtl2 dispatch queue*/
+} t_FmThresholds;
+
+/**************************************************************************//*
+ @Description structure for defining DMA thresholds
+*//***************************************************************************/
+typedef struct t_FmDmaThresholds {
+ uint8_t assertEmergency; /**< When this value is reached,
+ assert emergency (Threshold)*/
+ uint8_t clearEmergency; /**< After emergency is asserted, it is held
+ until this value is reached (Hystheresis) */
+} t_FmDmaThresholds;
+
+
+/**************************************************************************//**
+ @Function FM_ConfigResetOnInit
+
+ @Description Define whether to reset the FM before initialization.
+ Change the default configuration [DEFAULT_resetOnInit].
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] enable When TRUE, FM will be reset before any initialization.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigResetOnInit(t_Handle h_Fm, bool enable);
+
+/**************************************************************************//**
+ @Function FM_ConfigTotalFifoSize
+
+ @Description Define Total FIFO size for the whole FM.
+ Calling this routine changes the total Fifo size in the internal driver
+ data base from its default configuration [DEFAULT_totalFifoSize]
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] totalFifoSize The selected new value.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigTotalFifoSize(t_Handle h_Fm, uint32_t totalFifoSize);
+
+ /**************************************************************************//**
+ @Function FM_ConfigDmaCacheOverride
+
+ @Description Define cache override mode.
+ Calling this routine changes the cache override mode
+ in the internal driver data base from its default configuration [DEFAULT_cacheOverride]
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] cacheOverride The selected new value.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigDmaCacheOverride(t_Handle h_Fm, e_FmDmaCacheOverride cacheOverride);
+
+/**************************************************************************//**
+ @Function FM_ConfigDmaAidOverride
+
+ @Description Define DMA AID override mode.
+ Calling this routine changes the AID override mode
+ in the internal driver data base from its default configuration [DEFAULT_aidOverride]
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] aidOverride The selected new value.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigDmaAidOverride(t_Handle h_Fm, bool aidOverride);
+
+/**************************************************************************//**
+ @Function FM_ConfigDmaAidMode
+
+ @Description Define DMA AID mode.
+ Calling this routine changes the AID mode in the internal
+ driver data base from its default configuration [DEFAULT_aidMode]
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] aidMode The selected new value.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigDmaAidMode(t_Handle h_Fm, e_FmDmaAidMode aidMode);
+
+/**************************************************************************//**
+ @Function FM_ConfigDmaAxiDbgNumOfBeats
+
+ @Description Define DMA AXI number of beats.
+ Calling this routine changes the AXI number of beats in the internal
+ driver data base from its default configuration [DEFAULT_axiDbgNumOfBeats]
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] axiDbgNumOfBeats The selected new value.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigDmaAxiDbgNumOfBeats(t_Handle h_Fm, uint8_t axiDbgNumOfBeats);
+
+/**************************************************************************//**
+ @Function FM_ConfigDmaCamNumOfEntries
+
+ @Description Define number of CAM entries.
+ Calling this routine changes the number of CAM entries in the internal
+ driver data base from its default configuration [DEFAULT_dmaCamNumOfEntries].
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] numOfEntries The selected new value.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigDmaCamNumOfEntries(t_Handle h_Fm, uint8_t numOfEntries);
+
+/**************************************************************************//**
+ @Function FM_ConfigEnableCounters
+
+ @Description Obsolete, always return E_OK.
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_ConfigEnableCounters(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FM_ConfigDmaDbgCounter
+
+ @Description Define DMA debug counter.
+ Calling this routine changes the number of the DMA debug counter in the internal
+ driver data base from its default configuration [DEFAULT_dmaDbgCntMode].
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] fmDmaDbgCntMode An enum selecting the debug counter mode.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigDmaDbgCounter(t_Handle h_Fm, e_FmDmaDbgCntMode fmDmaDbgCntMode);
+
+/**************************************************************************//**
+ @Function FM_ConfigDmaStopOnBusErr
+
+ @Description Define bus error behavior.
+ Calling this routine changes the bus error behavior definition
+ in the internal driver data base from its default
+ configuration [DEFAULT_dmaStopOnBusError].
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] stop TRUE to stop on bus error, FALSE to continue.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ Only if bus error is enabled.
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigDmaStopOnBusErr(t_Handle h_Fm, bool stop);
+
+/**************************************************************************//**
+ @Function FM_ConfigDmaEmergency
+
+ @Description Define DMA emergency.
+ Calling this routine changes the DMA emergency definition
+ in the internal driver data base from its default
+ configuration where's it's disabled.
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] p_Emergency An OR mask of all required options.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigDmaEmergency(t_Handle h_Fm, t_FmDmaEmergency *p_Emergency);
+
+/**************************************************************************//**
+ @Function FM_ConfigDmaErr
+
+ @Description DMA error treatment.
+ Calling this routine changes the DMA error treatment
+ in the internal driver data base from its default
+ configuration [DEFAULT_dmaErr].
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] dmaErr The selected new choice.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigDmaErr(t_Handle h_Fm, e_FmDmaErr dmaErr);
+
+/**************************************************************************//**
+ @Function FM_ConfigCatastrophicErr
+
+ @Description Define FM behavior on catastrophic error.
+ Calling this routine changes the FM behavior on catastrophic
+ error in the internal driver data base from its default
+ [DEFAULT_catastrophicErr].
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] catastrophicErr The selected new choice.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigCatastrophicErr(t_Handle h_Fm, e_FmCatastrophicErr catastrophicErr);
+
+/**************************************************************************//**
+ @Function FM_ConfigEnableMuramTestMode
+
+ @Description Enable MURAM test mode.
+ Calling this routine changes the internal driver data base
+ from its default selection of test mode where it's disabled.
+ This routine is only avaiable on old FM revisions (FMan v2).
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigEnableMuramTestMode(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FM_ConfigEnableIramTestMode
+
+ @Description Enable IRAM test mode.
+ Calling this routine changes the internal driver data base
+ from its default selection of test mode where it's disabled.
+ This routine is only avaiable on old FM revisions (FMan v2).
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigEnableIramTestMode(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FM_ConfigHaltOnExternalActivation
+
+ @Description Define FM behavior on external halt activation.
+ Calling this routine changes the FM behavior on external halt
+ activation in the internal driver data base from its default
+ [DEFAULT_haltOnExternalActivation].
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] enable TRUE to enable halt on external halt
+ activation.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigHaltOnExternalActivation(t_Handle h_Fm, bool enable);
+
+/**************************************************************************//**
+ @Function FM_ConfigHaltOnUnrecoverableEccError
+
+ @Description Define FM behavior on external halt activation.
+ Calling this routine changes the FM behavior on unrecoverable
+ ECC error in the internal driver data base from its default
+ [DEFAULT_haltOnUnrecoverableEccError].
+ This routine is only avaiable on old FM revisions (FMan v2).
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] enable TRUE to enable halt on unrecoverable Ecc error
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigHaltOnUnrecoverableEccError(t_Handle h_Fm, bool enable);
+
+/**************************************************************************//**
+ @Function FM_ConfigException
+
+ @Description Define FM exceptions.
+ Calling this routine changes the exceptions defaults in the
+ internal driver data base where all exceptions are enabled.
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] exception The exception to be selected.
+ @Param[in] enable TRUE to enable interrupt, FALSE to mask it.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigException(t_Handle h_Fm, e_FmExceptions exception, bool enable);
+
+/**************************************************************************//**
+ @Function FM_ConfigExternalEccRamsEnable
+
+ @Description Select external ECC enabling.
+ Calling this routine changes the ECC enabling control in the internal
+ driver data base from its default [DEFAULT_externalEccRamsEnable].
+ When this option is enabled Rams ECC enabling is not effected
+ by FM_EnableRamsEcc/FM_DisableRamsEcc, but by a JTAG.
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] enable TRUE to enable this option.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigExternalEccRamsEnable(t_Handle h_Fm, bool enable);
+
+/**************************************************************************//**
+ @Function FM_ConfigTnumAgingPeriod
+
+ @Description Define Tnum aging period.
+ Calling this routine changes the Tnum aging of dequeue TNUMs
+ in the QMI in the internal driver data base from its default
+ [DEFAULT_tnumAgingPeriod].
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] tnumAgingPeriod Tnum Aging Period in microseconds.
+ Note that period is recalculated in units of
+ 64 FM clocks. Driver will pick the closest
+ possible period.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+ NOTE that if some MAC is configured for PFC, '0' value is NOT
+ allowed.
+*//***************************************************************************/
+t_Error FM_ConfigTnumAgingPeriod(t_Handle h_Fm, uint16_t tnumAgingPeriod);
+
+/**************************************************************************//*
+ @Function FM_ConfigDmaEmergencySmoother
+
+ @Description Define DMA emergency smoother.
+ Calling this routine changes the definition of the minimum
+ amount of DATA beats transferred on the AXI READ and WRITE
+ ports before lowering the emergency level.
+ By default smoother is disabled.
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] emergencyCnt emergency switching counter.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigDmaEmergencySmoother(t_Handle h_Fm, uint32_t emergencyCnt);
+
+/**************************************************************************//*
+ @Function FM_ConfigThresholds
+
+ @Description Calling this routine changes the internal driver data base
+ from its default FM threshold configuration:
+ dispLimit: [DEFAULT_dispLimit]
+ prsDispTh: [DEFAULT_prsDispTh]
+ plcrDispTh: [DEFAULT_plcrDispTh]
+ kgDispTh: [DEFAULT_kgDispTh]
+ bmiDispTh: [DEFAULT_bmiDispTh]
+ qmiEnqDispTh: [DEFAULT_qmiEnqDispTh]
+ qmiDeqDispTh: [DEFAULT_qmiDeqDispTh]
+ fmCtl1DispTh: [DEFAULT_fmCtl1DispTh]
+ fmCtl2DispTh: [DEFAULT_fmCtl2DispTh]
+
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] p_FmThresholds A structure of threshold parameters.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigThresholds(t_Handle h_Fm, t_FmThresholds *p_FmThresholds);
+
+/**************************************************************************//*
+ @Function FM_ConfigDmaSosEmergencyThreshold
+
+ @Description Calling this routine changes the internal driver data base
+ from its default dma SOS emergency configuration [DEFAULT_dmaSosEmergency]
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] dmaSosEmergency The selected new value.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigDmaSosEmergencyThreshold(t_Handle h_Fm, uint32_t dmaSosEmergency);
+
+/**************************************************************************//*
+ @Function FM_ConfigDmaWriteBufThresholds
+
+ @Description Calling this routine changes the internal driver data base
+ from its default configuration of DMA write buffer threshold
+ assertEmergency: [DEFAULT_dmaWriteIntBufLow]
+ clearEmergency: [DEFAULT_dmaWriteIntBufHigh]
+ This routine is only avaiable on old FM revisions (FMan v2).
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] p_FmDmaThresholds A structure of thresholds to define emergency behavior -
+ When 'assertEmergency' value is reached, emergency is asserted,
+ then it is held until 'clearEmergency' value is reached.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigDmaWriteBufThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds);
+
+ /**************************************************************************//*
+ @Function FM_ConfigDmaCommQThresholds
+
+ @Description Calling this routine changes the internal driver data base
+ from its default configuration of DMA command queue threshold
+ assertEmergency: [DEFAULT_dmaCommQLow]
+ clearEmergency: [DEFAULT_dmaCommQHigh]
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] p_FmDmaThresholds A structure of thresholds to define emergency behavior -
+ When 'assertEmergency' value is reached, emergency is asserted,
+ then it is held until 'clearEmergency' value is reached..
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigDmaCommQThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds);
+
+/**************************************************************************//*
+ @Function FM_ConfigDmaReadBufThresholds
+
+ @Description Calling this routine changes the internal driver data base
+ from its default configuration of DMA read buffer threshold
+ assertEmergency: [DEFAULT_dmaReadIntBufLow]
+ clearEmergency: [DEFAULT_dmaReadIntBufHigh]
+ This routine is only avaiable on old FM revisions (FMan v2).
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] p_FmDmaThresholds A structure of thresholds to define emergency behavior -
+ When 'assertEmergency' value is reached, emergency is asserted,
+ then it is held until 'clearEmergency' value is reached..
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigDmaReadBufThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds);
+
+/**************************************************************************//*
+ @Function FM_ConfigDmaWatchdog
+
+ @Description Calling this routine changes the internal driver data base
+ from its default watchdog configuration, which is disabled
+ [DEFAULT_dmaWatchdog].
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] watchDogValue The selected new value - in microseconds.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ConfigDmaWatchdog(t_Handle h_Fm, uint32_t watchDogValue);
+
+/** @} */ /* end of FM_advanced_init_grp group */
+/** @} */ /* end of FM_init_grp group */
+
+
+/**************************************************************************//**
+ @Group FM_runtime_control_grp FM Runtime Control Unit
+
+ @Description FM Runtime control unit API functions, definitions and enums.
+ The FM driver provides a set of control routines.
+ These routines may only be called after the module was fully
+ initialized (both configuration and initialization routines were
+ called). They are typically used to get information from hardware
+ (status, counters/statistics, revision etc.), to modify a current
+ state or to force/enable a required action. Run-time control may
+ be called whenever necessary and as many times as needed.
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Collection General FM defines.
+*//***************************************************************************/
+#define FM_MAX_NUM_OF_VALID_PORTS (FM_MAX_NUM_OF_OH_PORTS + \
+ FM_MAX_NUM_OF_1G_RX_PORTS + \
+ FM_MAX_NUM_OF_10G_RX_PORTS + \
+ FM_MAX_NUM_OF_1G_TX_PORTS + \
+ FM_MAX_NUM_OF_10G_TX_PORTS) /**< Number of available FM ports */
+/* @} */
+
+/**************************************************************************//*
+ @Description A Structure for Port bandwidth requirement. Port is identified
+ by type and relative id.
+*//***************************************************************************/
+typedef struct t_FmPortBandwidth {
+ e_FmPortType type; /**< FM port type */
+ uint8_t relativePortId; /**< Type relative port id */
+ uint8_t bandwidth; /**< bandwidth - (in term of percents) */
+} t_FmPortBandwidth;
+
+/**************************************************************************//*
+ @Description A Structure containing an array of Port bandwidth requirements.
+ The user should state the ports requiring bandwidth in terms of
+ percentage - i.e. all port's bandwidths in the array must add
+ up to 100.
+*//***************************************************************************/
+typedef struct t_FmPortsBandwidthParams {
+ uint8_t numOfPorts; /**< The number of relevant ports, which is the
+ number of valid entries in the array below */
+ t_FmPortBandwidth portsBandwidths[FM_MAX_NUM_OF_VALID_PORTS];
+ /**< for each port, it's bandwidth (all port's
+ bandwidths must add up to 100.*/
+} t_FmPortsBandwidthParams;
+
+/**************************************************************************//**
+ @Description DMA Emergency control on MURAM
+*//***************************************************************************/
+typedef enum e_FmDmaMuramPort {
+ e_FM_DMA_MURAM_PORT_WRITE, /**< MURAM write port */
+ e_FM_DMA_MURAM_PORT_READ /**< MURAM read port */
+} e_FmDmaMuramPort;
+
+/**************************************************************************//**
+ @Description Enum for defining FM counters
+*//***************************************************************************/
+typedef enum e_FmCounters {
+ e_FM_COUNTERS_ENQ_TOTAL_FRAME = 0, /**< QMI total enqueued frames counter */
+ e_FM_COUNTERS_DEQ_TOTAL_FRAME, /**< QMI total dequeued frames counter */
+ e_FM_COUNTERS_DEQ_0, /**< QMI 0 frames from QMan counter */
+ e_FM_COUNTERS_DEQ_1, /**< QMI 1 frames from QMan counter */
+ e_FM_COUNTERS_DEQ_2, /**< QMI 2 frames from QMan counter */
+ e_FM_COUNTERS_DEQ_3, /**< QMI 3 frames from QMan counter */
+ e_FM_COUNTERS_DEQ_FROM_DEFAULT, /**< QMI dequeue from default queue counter */
+ e_FM_COUNTERS_DEQ_FROM_CONTEXT, /**< QMI dequeue from FQ context counter */
+ e_FM_COUNTERS_DEQ_FROM_FD, /**< QMI dequeue from FD command field counter */
+ e_FM_COUNTERS_DEQ_CONFIRM /**< QMI dequeue confirm counter */
+} e_FmCounters;
+
+/**************************************************************************//**
+ @Description A Structure for returning FM revision information
+*//***************************************************************************/
+typedef struct t_FmRevisionInfo {
+ uint8_t majorRev; /**< Major revision */
+ uint8_t minorRev; /**< Minor revision */
+} t_FmRevisionInfo;
+
+/**************************************************************************//**
+ @Description A Structure for returning FM ctrl code revision information
+*//***************************************************************************/
+typedef struct t_FmCtrlCodeRevisionInfo {
+ uint16_t packageRev; /**< Package revision */
+ uint8_t majorRev; /**< Major revision */
+ uint8_t minorRev; /**< Minor revision */
+} t_FmCtrlCodeRevisionInfo;
+
+/**************************************************************************//**
+ @Description A Structure for defining DMA status
+*//***************************************************************************/
+typedef struct t_FmDmaStatus {
+ bool cmqNotEmpty; /**< Command queue is not empty */
+ bool busError; /**< Bus error occurred */
+ bool readBufEccError; /**< Double ECC error on buffer Read (Valid for FM rev < 6)*/
+ bool writeBufEccSysError; /**< Double ECC error on buffer write from system side (Valid for FM rev < 6)*/
+ bool writeBufEccFmError; /**< Double ECC error on buffer write from FM side (Valid for FM rev < 6) */
+ bool singlePortEccError; /**< Single Port ECC error from FM side (Valid for FM rev >= 6)*/
+} t_FmDmaStatus;
+
+/**************************************************************************//**
+ @Description A Structure for obtaining FM controller monitor values
+*//***************************************************************************/
+typedef struct t_FmCtrlMon {
+ uint8_t percentCnt[2]; /**< Percentage value */
+} t_FmCtrlMon;
+
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+/**************************************************************************//**
+ @Function FM_DumpRegs
+
+ @Description Dumps all FM registers
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return E_OK on success;
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+t_Error FM_DumpRegs(t_Handle h_Fm);
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+/**************************************************************************//**
+ @Function FM_SetException
+
+ @Description Calling this routine enables/disables the specified exception.
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] exception The exception to be selected.
+ @Param[in] enable TRUE to enable interrupt, FALSE to mask it.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_SetException(t_Handle h_Fm, e_FmExceptions exception, bool enable);
+
+/**************************************************************************//**
+ @Function FM_EnableRamsEcc
+
+ @Description Enables ECC mechanism for all the different FM RAM's; E.g. IRAM,
+ MURAM, Parser, Keygen, Policer, etc.
+ Note:
+ If FM_ConfigExternalEccRamsEnable was called to enable external
+ setting of ECC, this routine effects IRAM ECC only.
+ This routine is also called by the driver if an ECC exception is
+ enabled.
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_EnableRamsEcc(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FM_DisableRamsEcc
+
+ @Description Disables ECC mechanism for all the different FM RAM's; E.g. IRAM,
+ MURAM, Parser, Keygen, Policer, etc.
+ Note:
+ If FM_ConfigExternalEccRamsEnable was called to enable external
+ setting of ECC, this routine effects IRAM ECC only.
+ In opposed to FM_EnableRamsEcc, this routine must be called
+ explicitly to disable all Rams ECC.
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Config() and before FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_DisableRamsEcc(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FM_GetRevision
+
+ @Description Returns the FM revision
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[out] p_FmRevisionInfo A structure of revision information parameters.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+t_Error FM_GetRevision(t_Handle h_Fm, t_FmRevisionInfo *p_FmRevisionInfo);
+
+/**************************************************************************//**
+ @Function FM_GetFmanCtrlCodeRevision
+
+ @Description Returns the Fman controller code revision
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[out] p_RevisionInfo A structure of revision information parameters.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+t_Error FM_GetFmanCtrlCodeRevision(t_Handle h_Fm, t_FmCtrlCodeRevisionInfo *p_RevisionInfo);
+
+/**************************************************************************//**
+ @Function FM_GetCounter
+
+ @Description Reads one of the FM counters.
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] counter The requested counter.
+
+ @Return Counter's current value.
+
+ @Cautions Allowed only following FM_Init().
+ Note that it is user's responsibility to call this routine only
+ for enabled counters, and there will be no indication if a
+ disabled counter is accessed.
+*//***************************************************************************/
+uint32_t FM_GetCounter(t_Handle h_Fm, e_FmCounters counter);
+
+/**************************************************************************//**
+ @Function FM_ModifyCounter
+
+ @Description Sets a value to an enabled counter. Use "0" to reset the counter.
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] counter The requested counter.
+ @Param[in] val The requested value to be written into the counter.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ModifyCounter(t_Handle h_Fm, e_FmCounters counter, uint32_t val);
+
+/**************************************************************************//**
+ @Function FM_Resume
+
+ @Description Release FM after halt FM command or after unrecoverable ECC error.
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+void FM_Resume(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FM_SetDmaEmergency
+
+ @Description Manual emergency set
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] muramPort MURAM direction select.
+ @Param[in] enable TRUE to manually enable emergency, FALSE to disable.
+
+ @Return None.
+
+ @Cautions Allowed only following FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+void FM_SetDmaEmergency(t_Handle h_Fm, e_FmDmaMuramPort muramPort, bool enable);
+
+/**************************************************************************//**
+ @Function FM_SetDmaExtBusPri
+
+ @Description Set the DMA external bus priority
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] pri External bus priority select
+
+ @Return None.
+
+ @Cautions Allowed only following FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+void FM_SetDmaExtBusPri(t_Handle h_Fm, e_FmDmaExtBusPri pri);
+
+/**************************************************************************//**
+ @Function FM_GetDmaStatus
+
+ @Description Reads the DMA current status
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[out] p_FmDmaStatus A structure of DMA status parameters.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+void FM_GetDmaStatus(t_Handle h_Fm, t_FmDmaStatus *p_FmDmaStatus);
+
+/**************************************************************************//**
+ @Function FM_ErrorIsr
+
+ @Description FM interrupt-service-routine for errors.
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return E_OK on success; E_EMPTY if no errors found in register, other
+ error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ErrorIsr(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FM_EventIsr
+
+ @Description FM interrupt-service-routine for normal events.
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Cautions Allowed only following FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+void FM_EventIsr(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FM_GetSpecialOperationCoding
+
+ @Description Return a specific coding according to the input mask.
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] spOper special operation mask.
+ @Param[out] p_SpOperCoding special operation code.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+t_Error FM_GetSpecialOperationCoding(t_Handle h_Fm,
+ fmSpecialOperations_t spOper,
+ uint8_t *p_SpOperCoding);
+
+/**************************************************************************//**
+ @Function FM_CtrlMonStart
+
+ @Description Start monitoring utilization of all available FM controllers.
+
+ In order to obtain FM controllers utilization the following sequence
+ should be used:
+ -# FM_CtrlMonStart()
+ -# FM_CtrlMonStop()
+ -# FM_CtrlMonGetCounters() - issued for each FM controller
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID).
+*//***************************************************************************/
+t_Error FM_CtrlMonStart(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FM_CtrlMonStop
+
+ @Description Stop monitoring utilization of all available FM controllers.
+
+ In order to obtain FM controllers utilization the following sequence
+ should be used:
+ -# FM_CtrlMonStart()
+ -# FM_CtrlMonStop()
+ -# FM_CtrlMonGetCounters() - issued for each FM controller
+
+ @Param[in] h_Fm A handle to an FM Module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID).
+*//***************************************************************************/
+t_Error FM_CtrlMonStop(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FM_CtrlMonGetCounters
+
+ @Description Obtain FM controller utilization parameters.
+
+ In order to obtain FM controllers utilization the following sequence
+ should be used:
+ -# FM_CtrlMonStart()
+ -# FM_CtrlMonStop()
+ -# FM_CtrlMonGetCounters() - issued for each FM controller
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] fmCtrlIndex FM Controller index for that utilization results
+ are requested.
+ @Param[in] p_Mon Pointer to utilization results structure.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID).
+*//***************************************************************************/
+t_Error FM_CtrlMonGetCounters(t_Handle h_Fm, uint8_t fmCtrlIndex, t_FmCtrlMon *p_Mon);
+
+
+/**************************************************************************//*
+ @Function FM_ForceIntr
+
+ @Description Causes an interrupt event on the requested source.
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] exception An exception to be forced.
+
+ @Return E_OK on success; Error code if the exception is not enabled,
+ or is not able to create interrupt.
+
+ @Cautions Allowed only following FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_ForceIntr (t_Handle h_Fm, e_FmExceptions exception);
+
+/**************************************************************************//*
+ @Function FM_SetPortsBandwidth
+
+ @Description Sets relative weights between ports when accessing common resources.
+
+ @Param[in] h_Fm A handle to an FM Module.
+ @Param[in] p_PortsBandwidth A structure of ports bandwidths in percentage, i.e.
+ total must equal 100.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_SetPortsBandwidth(t_Handle h_Fm, t_FmPortsBandwidthParams *p_PortsBandwidth);
+
+/** @} */ /* end of FM_runtime_control_grp group */
+/** @} */ /* end of FM_lib_grp group */
+/** @} */ /* end of FM_grp group */
+
+
+#ifdef NCSW_BACKWARD_COMPATIBLE_API
+typedef t_FmFirmwareParams t_FmPcdFirmwareParams;
+typedef t_FmBufferPrefixContent t_FmPortBufferPrefixContent;
+typedef t_FmExtPoolParams t_FmPortExtPoolParams;
+typedef t_FmExtPools t_FmPortExtPools;
+typedef t_FmBackupBmPools t_FmPortBackupBmPools;
+typedef t_FmBufPoolDepletion t_FmPortBufPoolDepletion;
+typedef e_FmDmaSwapOption e_FmPortDmaSwapOption;
+typedef e_FmDmaCacheOption e_FmPortDmaCacheOption;
+
+#define FM_CONTEXTA_GET_OVVERIDE FM_CONTEXTA_GET_OVERRIDE
+#define FM_CONTEXTA_SET_OVVERIDE FM_CONTEXTA_SET_OVERRIDE
+
+#define e_FM_EX_BMI_PIPELINE_ECC e_FM_EX_BMI_STORAGE_PROFILE_ECC
+#define e_FM_PORT_DMA_NO_SWP e_FM_DMA_NO_SWP
+#define e_FM_PORT_DMA_SWP_PPC_LE e_FM_DMA_SWP_PPC_LE
+#define e_FM_PORT_DMA_SWP_BE e_FM_DMA_SWP_BE
+#define e_FM_PORT_DMA_NO_STASH e_FM_DMA_NO_STASH
+#define e_FM_PORT_DMA_STASH e_FM_DMA_STASH
+#endif /* NCSW_BACKWARD_COMPATIBLE_API */
+
+
+#endif /* __FM_EXT */
diff --git a/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_mac_ext.h b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_mac_ext.h
new file mode 100644
index 0000000..f90f2a7
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_mac_ext.h
@@ -0,0 +1,846 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File fm_mac_ext.h
+
+ @Description FM MAC ...
+*//***************************************************************************/
+#ifndef __FM_MAC_EXT_H
+#define __FM_MAC_EXT_H
+
+#include "std_ext.h"
+#include "enet_ext.h"
+
+
+/**************************************************************************//**
+
+ @Group FM_grp Frame Manager API
+
+ @Description FM API functions, definitions and enums
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group FM_mac_grp FM MAC
+
+ @Description FM MAC API functions, definitions and enums
+
+ @{
+*//***************************************************************************/
+
+#define FM_MAC_NO_PFC 0xff
+
+
+/**************************************************************************//**
+ @Description FM MAC Exceptions
+*//***************************************************************************/
+typedef enum e_FmMacExceptions {
+ e_FM_MAC_EX_10G_MDIO_SCAN_EVENTMDIO = 0 /**< 10GEC MDIO scan event interrupt */
+ ,e_FM_MAC_EX_10G_MDIO_CMD_CMPL /**< 10GEC MDIO command completion interrupt */
+ ,e_FM_MAC_EX_10G_REM_FAULT /**< 10GEC, mEMAC Remote fault interrupt */
+ ,e_FM_MAC_EX_10G_LOC_FAULT /**< 10GEC, mEMAC Local fault interrupt */
+ ,e_FM_MAC_EX_10G_1TX_ECC_ER /**< 10GEC, mEMAC Transmit frame ECC error interrupt */
+ ,e_FM_MAC_EX_10G_TX_FIFO_UNFL /**< 10GEC, mEMAC Transmit FIFO underflow interrupt */
+ ,e_FM_MAC_EX_10G_TX_FIFO_OVFL /**< 10GEC, mEMAC Transmit FIFO overflow interrupt */
+ ,e_FM_MAC_EX_10G_TX_ER /**< 10GEC Transmit frame error interrupt */
+ ,e_FM_MAC_EX_10G_RX_FIFO_OVFL /**< 10GEC, mEMAC Receive FIFO overflow interrupt */
+ ,e_FM_MAC_EX_10G_RX_ECC_ER /**< 10GEC, mEMAC Receive frame ECC error interrupt */
+ ,e_FM_MAC_EX_10G_RX_JAB_FRM /**< 10GEC Receive jabber frame interrupt */
+ ,e_FM_MAC_EX_10G_RX_OVRSZ_FRM /**< 10GEC Receive oversized frame interrupt */
+ ,e_FM_MAC_EX_10G_RX_RUNT_FRM /**< 10GEC Receive runt frame interrupt */
+ ,e_FM_MAC_EX_10G_RX_FRAG_FRM /**< 10GEC Receive fragment frame interrupt */
+ ,e_FM_MAC_EX_10G_RX_LEN_ER /**< 10GEC Receive payload length error interrupt */
+ ,e_FM_MAC_EX_10G_RX_CRC_ER /**< 10GEC Receive CRC error interrupt */
+ ,e_FM_MAC_EX_10G_RX_ALIGN_ER /**< 10GEC Receive alignment error interrupt */
+ ,e_FM_MAC_EX_1G_BAB_RX /**< dTSEC Babbling receive error */
+ ,e_FM_MAC_EX_1G_RX_CTL /**< dTSEC Receive control (pause frame) interrupt */
+ ,e_FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET /**< dTSEC Graceful transmit stop complete */
+ ,e_FM_MAC_EX_1G_BAB_TX /**< dTSEC Babbling transmit error */
+ ,e_FM_MAC_EX_1G_TX_CTL /**< dTSEC Transmit control (pause frame) interrupt */
+ ,e_FM_MAC_EX_1G_TX_ERR /**< dTSEC Transmit error */
+ ,e_FM_MAC_EX_1G_LATE_COL /**< dTSEC Late collision */
+ ,e_FM_MAC_EX_1G_COL_RET_LMT /**< dTSEC Collision retry limit */
+ ,e_FM_MAC_EX_1G_TX_FIFO_UNDRN /**< dTSEC Transmit FIFO underrun */
+ ,e_FM_MAC_EX_1G_MAG_PCKT /**< dTSEC Magic Packet detection */
+ ,e_FM_MAC_EX_1G_MII_MNG_RD_COMPLET /**< dTSEC MII management read completion */
+ ,e_FM_MAC_EX_1G_MII_MNG_WR_COMPLET /**< dTSEC MII management write completion */
+ ,e_FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET /**< dTSEC Graceful receive stop complete */
+ ,e_FM_MAC_EX_1G_TX_DATA_ERR /**< dTSEC Internal data error on transmit */
+ ,e_FM_MAC_EX_1G_RX_DATA_ERR /**< dTSEC Internal data error on receive */
+ ,e_FM_MAC_EX_1G_1588_TS_RX_ERR /**< dTSEC Time-Stamp Receive Error */
+ ,e_FM_MAC_EX_1G_RX_MIB_CNT_OVFL /**< dTSEC MIB counter overflow */
+ ,e_FM_MAC_EX_TS_FIFO_ECC_ERR /**< mEMAC Time-stamp FIFO ECC error interrupt;
+ not supported on T4240/B4860 rev1 chips */
+ ,e_FM_MAC_EX_MAGIC_PACKET_INDICATION = e_FM_MAC_EX_1G_MAG_PCKT
+ /**< mEMAC Magic Packet Indication Interrupt */
+} e_FmMacExceptions;
+
+/**************************************************************************//**
+ @Description TM MAC statistics level
+*//***************************************************************************/
+typedef enum e_FmMacStatisticsLevel {
+ e_FM_MAC_NONE_STATISTICS = 0, /**< No statistics */
+ e_FM_MAC_PARTIAL_STATISTICS, /**< Only error counters are available; Optimized for performance */
+ e_FM_MAC_FULL_STATISTICS /**< All counters available; Not optimized for performance */
+} e_FmMacStatisticsLevel;
+
+
+#if (DPAA_VERSION >= 11)
+/**************************************************************************//**
+ @Description Priority Flow Control Parameters
+*//***************************************************************************/
+typedef struct t_FmMacPfcParams {
+ bool pfcEnable; /**< Enable/Disable PFC */
+
+ uint16_t pauseQuanta[FM_MAX_NUM_OF_PFC_PRIORITIES]; /**< Pause Quanta per priority to be sent in a pause frame. Each quanta represents a 512 bit-times*/
+
+ uint16_t pauseThresholdQuanta[FM_MAX_NUM_OF_PFC_PRIORITIES];/**< Pause threshold per priority, when timer passes this threshold time a PFC frames is sent again if the port is still congested or BM pool in depletion*/
+
+
+} t_FmMacPfcParams;
+#endif /* (DPAA_VERSION >= 11) */
+
+/**************************************************************************//**
+ @Function t_FmMacExceptionCallback
+
+ @Description Fm Mac Exception Callback from FM MAC to the user
+
+ @Param[in] h_App - Handle to the upper layer handler
+
+ @Param[in] exceptions - The exception that occurred
+
+ @Return void.
+*//***************************************************************************/
+typedef void (t_FmMacExceptionCallback)(t_Handle h_App, e_FmMacExceptions exceptions);
+
+
+/**************************************************************************//**
+ @Description TM MAC statistics rfc3635
+*//***************************************************************************/
+typedef struct t_FmMacStatistics {
+/* RMON */
+ uint64_t eStatPkts64; /**< r-10G tr-DT 64 byte frame counter */
+ uint64_t eStatPkts65to127; /**< r-10G 65 to 127 byte frame counter */
+ uint64_t eStatPkts128to255; /**< r-10G 128 to 255 byte frame counter */
+ uint64_t eStatPkts256to511; /**< r-10G 256 to 511 byte frame counter */
+ uint64_t eStatPkts512to1023; /**< r-10G 512 to 1023 byte frame counter */
+ uint64_t eStatPkts1024to1518; /**< r-10G 1024 to 1518 byte frame counter */
+ uint64_t eStatPkts1519to1522; /**< r-10G 1519 to 1522 byte good frame count */
+/* */
+ uint64_t eStatFragments; /**< Total number of packets that were less than 64 octets long with a wrong CRC.*/
+ uint64_t eStatJabbers; /**< Total number of packets longer than valid maximum length octets */
+ uint64_t eStatsDropEvents; /**< number of dropped packets due to internal errors of the MAC Client (during receive). */
+ uint64_t eStatCRCAlignErrors; /**< Incremented when frames of correct length but with CRC error are received.*/
+ uint64_t eStatUndersizePkts; /**< Incremented for frames under 64 bytes with a valid FCS and otherwise well formed;
+ This count does not include range length errors */
+ uint64_t eStatOversizePkts; /**< Incremented for frames which exceed 1518 (non VLAN) or 1522 (VLAN) and contains
+ a valid FCS and otherwise well formed */
+/* Pause */
+ uint64_t teStatPause; /**< Pause MAC Control received */
+ uint64_t reStatPause; /**< Pause MAC Control sent */
+/* MIB II */
+ uint64_t ifInOctets; /**< Total number of byte received. */
+ uint64_t ifInPkts; /**< Total number of packets received.*/
+ uint64_t ifInUcastPkts; /**< Total number of unicast frame received;
+ NOTE: this counter is not supported on dTSEC MAC */
+ uint64_t ifInMcastPkts; /**< Total number of multicast frame received*/
+ uint64_t ifInBcastPkts; /**< Total number of broadcast frame received */
+ uint64_t ifInDiscards; /**< Frames received, but discarded due to problems within the MAC RX. */
+ uint64_t ifInErrors; /**< Number of frames received with error:
+ - FIFO Overflow Error
+ - CRC Error
+ - Frame Too Long Error
+ - Alignment Error
+ - The dedicated Error Code (0xfe, not a code error) was received */
+ uint64_t ifOutOctets; /**< Total number of byte sent. */
+ uint64_t ifOutPkts; /**< Total number of packets sent .*/
+ uint64_t ifOutUcastPkts; /**< Total number of unicast frame sent;
+ NOTE: this counter is not supported on dTSEC MAC */
+ uint64_t ifOutMcastPkts; /**< Total number of multicast frame sent */
+ uint64_t ifOutBcastPkts; /**< Total number of multicast frame sent */
+ uint64_t ifOutDiscards; /**< Frames received, but discarded due to problems within the MAC TX N/A!.*/
+ uint64_t ifOutErrors; /**< Number of frames transmitted with error:
+ - FIFO Overflow Error
+ - FIFO Underflow Error
+ - Other */
+} t_FmMacStatistics;
+
+
+/**************************************************************************//**
+ @Group FM_mac_init_grp FM MAC Initialization Unit
+
+ @Description FM MAC Initialization Unit
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Description FM MAC config input
+*//***************************************************************************/
+typedef struct t_FmMacParams {
+ uintptr_t baseAddr; /**< Base of memory mapped FM MAC registers */
+ t_EnetAddr addr; /**< MAC address of device; First octet is sent first */
+ uint8_t macId; /**< MAC ID;
+ numbering of dTSEC and 1G-mEMAC:
+ 0 - FM_MAX_NUM_OF_1G_MACS;
+ numbering of 10G-MAC (TGEC) and 10G-mEMAC:
+ 0 - FM_MAX_NUM_OF_10G_MACS */
+ e_EnetMode enetMode; /**< Ethernet operation mode (MAC-PHY interface and speed);
+ Note that the speed should indicate the maximum rate that
+ this MAC should support rather than the actual speed;
+ i.e. user should use the FM_MAC_AdjustLink() routine to
+ provide accurate speed;
+ In case of mEMAC RGMII mode, the MAC is configured to RGMII
+ automatic mode, where actual speed/duplex mode information
+ is provided by PHY automatically in-band; FM_MAC_AdjustLink()
+ function should be used to switch to manual RGMII speed/duplex mode
+ configuration if RGMII PHY doesn't support in-band status signaling;
+ In addition, in mEMAC, in case where user is using the higher MACs
+ (i.e. the MACs that should support 10G), user should pass here
+ speed=10000 even if the interface is not allowing that (e.g. SGMII). */
+ t_Handle h_Fm; /**< A handle to the FM object this port related to */
+ int mdioIrq; /**< MDIO exceptions interrupt source - not valid for all
+ MACs; MUST be set to 'NO_IRQ' for MACs that don't have
+ mdio-irq, or for polling */
+ t_FmMacExceptionCallback *f_Event; /**< MDIO Events Callback Routine */
+ t_FmMacExceptionCallback *f_Exception; /**< Exception Callback Routine */
+ t_Handle h_App; /**< A handle to an application layer object; This handle will
+ be passed by the driver upon calling the above callbacks */
+} t_FmMacParams;
+
+
+/**************************************************************************//**
+ @Function FM_MAC_Config
+
+ @Description Creates descriptor for the FM MAC module.
+
+ The routine returns a handle (descriptor) to the FM MAC object.
+ This descriptor must be passed as first parameter to all other
+ FM MAC function calls.
+
+ No actual initialization or configuration of FM MAC hardware is
+ done by this routine.
+
+ @Param[in] p_FmMacParam - Pointer to data structure of parameters
+
+ @Retval Handle to FM MAC object, or NULL for Failure.
+*//***************************************************************************/
+t_Handle FM_MAC_Config(t_FmMacParams *p_FmMacParam);
+
+/**************************************************************************//**
+ @Function FM_MAC_Init
+
+ @Description Initializes the FM MAC module
+
+ @Param[in] h_FmMac - FM module descriptor
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_MAC_Init(t_Handle h_FmMac);
+
+/**************************************************************************//**
+ @Function FM_Free
+
+ @Description Frees all resources that were assigned to FM MAC module.
+
+ Calling this routine invalidates the descriptor.
+
+ @Param[in] h_FmMac - FM module descriptor
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_MAC_Free(t_Handle h_FmMac);
+
+
+/**************************************************************************//**
+ @Group FM_mac_advanced_init_grp FM MAC Advanced Configuration Unit
+
+ @Description Configuration functions used to change default values.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Function FM_MAC_ConfigResetOnInit
+
+ @Description Tell the driver whether to reset the FM MAC before initialization or
+ not. It changes the default configuration [DEFAULT_resetOnInit].
+
+ @Param[in] h_FmMac A handle to a FM MAC Module.
+ @Param[in] enable When TRUE, FM will be reset before any initialization.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_ConfigResetOnInit(t_Handle h_FmMac, bool enable);
+
+/**************************************************************************//**
+ @Function FM_MAC_ConfigLoopback
+
+ @Description Enable/Disable internal loopback mode
+
+ @Param[in] h_FmMac A handle to a FM MAC Module.
+ @Param[in] enable TRUE to enable or FALSE to disable.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_ConfigLoopback(t_Handle h_FmMac, bool enable);
+
+/**************************************************************************//**
+ @Function FM_MAC_ConfigMaxFrameLength
+
+ @Description Setup maximum Rx Frame Length (in 1G MAC, effects also Tx)
+
+ @Param[in] h_FmMac A handle to a FM MAC Module.
+ @Param[in] newVal MAX Frame length
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_ConfigMaxFrameLength(t_Handle h_FmMac, uint16_t newVal);
+
+/**************************************************************************//**
+ @Function FM_MAC_ConfigWan
+
+ @Description ENABLE WAN mode in 10G-MAC
+
+ @Param[in] h_FmMac A handle to a FM MAC Module.
+ @Param[in] enable TRUE to enable or FALSE to disable.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_ConfigWan(t_Handle h_FmMac, bool enable);
+
+/**************************************************************************//**
+ @Function FM_MAC_ConfigPadAndCrc
+
+ @Description Config PAD and CRC mode
+
+ @Param[in] h_FmMac A handle to a FM MAC Module.
+ @Param[in] enable TRUE to enable or FALSE to disable.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init().
+ Not supported on 10G-MAC (i.e. CRC & PAD are added automatically
+ by HW); on mEMAC, this routine supports only PAD (i.e. CRC is
+ added automatically by HW).
+*//***************************************************************************/
+t_Error FM_MAC_ConfigPadAndCrc(t_Handle h_FmMac, bool enable);
+
+/**************************************************************************//**
+ @Function FM_MAC_ConfigHalfDuplex
+
+ @Description Config Half Duplex Mode
+
+ @Param[in] h_FmMac A handle to a FM MAC Module.
+ @Param[in] enable TRUE to enable or FALSE to disable.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_ConfigHalfDuplex(t_Handle h_FmMac, bool enable);
+
+/**************************************************************************//**
+ @Function FM_MAC_ConfigTbiPhyAddr
+
+ @Description Configures the address of internal TBI PHY.
+
+ @Param[in] h_FmMac A handle to a FM MAC Module.
+ @Param[in] newVal TBI PHY address (1-31).
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_ConfigTbiPhyAddr(t_Handle h_FmMac, uint8_t newVal);
+
+/**************************************************************************//**
+ @Function FM_MAC_ConfigLengthCheck
+
+ @Description Configure the frame length checking.
+
+ @Param[in] h_FmMac A handle to a FM MAC Module.
+ @Param[in] enable TRUE to enable or FALSE to disable.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_ConfigLengthCheck(t_Handle h_FmMac, bool enable);
+
+/**************************************************************************//**
+ @Function FM_MAC_ConfigException
+
+ @Description Change Exception selection from default
+
+ @Param[in] h_FmMac A handle to a FM MAC Module.
+ @Param[in] ex Type of the desired exceptions
+ @Param[in] enable TRUE to enable the specified exception, FALSE to disable it.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_MAC_Config() and before FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_ConfigException(t_Handle h_FmMac, e_FmMacExceptions ex, bool enable);
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+t_Error FM_MAC_ConfigSkipFman11Workaround (t_Handle h_FmMac);
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+/** @} */ /* end of FM_mac_advanced_init_grp group */
+/** @} */ /* end of FM_mac_init_grp group */
+
+
+/**************************************************************************//**
+ @Group FM_mac_runtime_control_grp FM MAC Runtime Control Unit
+
+ @Description FM MAC Runtime control unit API functions, definitions and enums.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Function FM_MAC_Enable
+
+ @Description Enable the MAC
+
+ @Param[in] h_FmMac A handle to a FM MAC Module.
+ @Param[in] mode Mode of operation (RX, TX, Both)
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_Enable(t_Handle h_FmMac, e_CommMode mode);
+
+/**************************************************************************//**
+ @Function FM_MAC_Disable
+
+ @Description DISABLE the MAC
+
+ @Param[in] h_FmMac A handle to a FM MAC Module.
+ @Param[in] mode Define what part to Disable (RX, TX or BOTH)
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_Disable(t_Handle h_FmMac, e_CommMode mode);
+
+/**************************************************************************//**
+ @Function FM_MAC_Enable1588TimeStamp
+
+ @Description Enables the TSU operation.
+
+ @Param[in] h_Fm - Handle to the PTP as returned from the FM_MAC_PtpConfig.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_Enable1588TimeStamp(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FM_MAC_Disable1588TimeStamp
+
+ @Description Disables the TSU operation.
+
+ @Param[in] h_Fm - Handle to the PTP as returned from the FM_MAC_PtpConfig.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_Disable1588TimeStamp(t_Handle h_Fm);
+
+/**************************************************************************//**
+ @Function FM_MAC_SetTxAutoPauseFrames
+
+ @Description Enable/Disable transmission of Pause-Frames.
+ The routine changes the default configuration [DEFAULT_TX_PAUSE_TIME].
+
+ @Param[in] h_FmMac - A handle to a FM MAC Module.
+ @Param[in] pauseTime - Pause quanta value used with transmitted pause frames.
+ Each quanta represents a 512 bit-times; Note that '0'
+ as an input here will be used as disabling the
+ transmission of the pause-frames.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_SetTxAutoPauseFrames(t_Handle h_FmMac,
+ uint16_t pauseTime);
+
+ /**************************************************************************//**
+ @Function FM_MAC_SetTxPauseFrames
+
+ @Description Enable/Disable transmission of Pause-Frames.
+ The routine changes the default configuration:
+ pause-time - [DEFAULT_TX_PAUSE_TIME]
+ threshold-time - [0]
+
+ @Param[in] h_FmMac - A handle to a FM MAC Module.
+ @Param[in] priority - the PFC class of service; use 'FM_MAC_NO_PFC'
+ to indicate legacy pause support (i.e. no PFC).
+ @Param[in] pauseTime - Pause quanta value used with transmitted pause frames.
+ Each quanta represents a 512 bit-times;
+ Note that '0' as an input here will be used as disabling the
+ transmission of the pause-frames.
+ @Param[in] threshTime - Pause Threshold equanta value used by the MAC to retransmit pause frame.
+ if the situation causing a pause frame to be sent didn't finish when the timer
+ reached the threshold quanta, the MAC will retransmit the pause frame.
+ Each quanta represents a 512 bit-times.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_MAC_Init().
+ In order for PFC to work properly the user must configure
+ TNUM-aging in the tx-port it is recommended that pre-fetch and
+ rate limit in the tx port should be disabled;
+ PFC is supported only on new mEMAC; i.e. in MACs that don't have
+ PFC support (10G-MAC and dTSEC), user should use 'FM_MAC_NO_PFC'
+ in the 'priority' field.
+*//***************************************************************************/
+t_Error FM_MAC_SetTxPauseFrames(t_Handle h_FmMac,
+ uint8_t priority,
+ uint16_t pauseTime,
+ uint16_t threshTime);
+
+/**************************************************************************//**
+ @Function FM_MAC_SetRxIgnorePauseFrames
+
+ @Description Enable/Disable ignoring of Pause-Frames.
+
+ @Param[in] h_FmMac - A handle to a FM MAC Module.
+ @Param[in] en - boolean indicates whether to ignore the incoming pause
+ frames or not.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_SetRxIgnorePauseFrames(t_Handle h_FmMac, bool en);
+
+/**************************************************************************//**
+ @Function FM_MAC_SetWakeOnLan
+
+ @Description Enable/Disable Wake On Lan support
+
+ @Param[in] h_FmMac - A handle to a FM MAC Module.
+ @Param[in] en - boolean indicates whether to enable Wake On Lan
+ support or not.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_SetWakeOnLan(t_Handle h_FmMac, bool en);
+
+/**************************************************************************//**
+ @Function FM_MAC_ResetCounters
+
+ @Description reset all statistics counters
+
+ @Param[in] h_FmMac - A handle to a FM MAC Module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_ResetCounters(t_Handle h_FmMac);
+
+/**************************************************************************//**
+ @Function FM_MAC_SetException
+
+ @Description Enable/Disable a specific Exception
+
+ @Param[in] h_FmMac - A handle to a FM MAC Module.
+ @Param[in] ex - Type of the desired exceptions
+ @Param[in] enable - TRUE to enable the specified exception, FALSE to disable it.
+
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_SetException(t_Handle h_FmMac, e_FmMacExceptions ex, bool enable);
+
+/**************************************************************************//**
+ @Function FM_MAC_SetStatistics
+
+ @Description Define Statistics level.
+ Where applicable, the routine also enables the MIB counters
+ overflow interrupt in order to keep counters accurate
+ and account for overflows.
+ This routine is relevant only for dTSEC.
+
+ @Param[in] h_FmMac - A handle to a FM MAC Module.
+ @Param[in] statisticsLevel - Full statistics level provides all standard counters but may
+ reduce performance. Partial statistics provides only special
+ event counters (errors etc.). If selected, regular counters (such as
+ byte/packet) will be invalid and will return -1.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_SetStatistics(t_Handle h_FmMac, e_FmMacStatisticsLevel statisticsLevel);
+
+/**************************************************************************//**
+ @Function FM_MAC_GetStatistics
+
+ @Description get all statistics counters
+
+ @Param[in] h_FmMac - A handle to a FM MAC Module.
+ @Param[in] p_Statistics - Structure with statistics
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_Init().
+*//***************************************************************************/
+t_Error FM_MAC_GetStatistics(t_Handle h_FmMac, t_FmMacStatistics *p_Statistics);
+
+/**************************************************************************//**
+ @Function FM_MAC_ModifyMacAddr
+
+ @Description Replace the main MAC Address
+
+ @Param[in] h_FmMac - A handle to a FM Module.
+ @Param[in] p_EnetAddr - Ethernet Mac address
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only after FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_ModifyMacAddr(t_Handle h_FmMac, t_EnetAddr *p_EnetAddr);
+
+/**************************************************************************//**
+ @Function FM_MAC_AddHashMacAddr
+
+ @Description Add an Address to the hash table. This is for filter purpose only.
+
+ @Param[in] h_FmMac - A handle to a FM Module.
+ @Param[in] p_EnetAddr - Ethernet Mac address
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_MAC_Init(). It is a filter only address.
+ @Cautions Some address need to be filterd out in upper FM blocks.
+*//***************************************************************************/
+t_Error FM_MAC_AddHashMacAddr(t_Handle h_FmMac, t_EnetAddr *p_EnetAddr);
+
+/**************************************************************************//**
+ @Function FM_MAC_RemoveHashMacAddr
+
+ @Description Delete an Address to the hash table. This is for filter purpose only.
+
+ @Param[in] h_FmMac - A handle to a FM Module.
+ @Param[in] p_EnetAddr - Ethernet Mac address
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_RemoveHashMacAddr(t_Handle h_FmMac, t_EnetAddr *p_EnetAddr);
+
+/**************************************************************************//**
+ @Function FM_MAC_AddExactMatchMacAddr
+
+ @Description Add a unicast or multicast mac address for exact-match filtering
+ (8 on dTSEC, 2 for 10G-MAC)
+
+ @Param[in] h_FmMac - A handle to a FM Module.
+ @Param[in] p_EnetAddr - MAC Address to ADD
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only after FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_AddExactMatchMacAddr(t_Handle h_FmMac, t_EnetAddr *p_EnetAddr);
+
+/**************************************************************************//**
+ @Function FM_MAC_RemovelExactMatchMacAddr
+
+ @Description Remove a uni cast or multi cast mac address.
+
+ @Param[in] h_FmMac - A handle to a FM Module.
+ @Param[in] p_EnetAddr - MAC Address to remove
+
+ @Return E_OK on success; Error code otherwise..
+
+ @Cautions Allowed only after FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_RemovelExactMatchMacAddr(t_Handle h_FmMac, t_EnetAddr *p_EnetAddr);
+
+/**************************************************************************//**
+ @Function FM_MAC_SetPromiscuous
+
+ @Description Enable/Disable MAC Promiscuous mode for ALL mac addresses.
+
+ @Param[in] h_FmMac - A handle to a FM MAC Module.
+ @Param[in] enable - TRUE to enable or FALSE to disable.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only after FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_SetPromiscuous(t_Handle h_FmMac, bool enable);
+
+/**************************************************************************//**
+ @Function FM_MAC_AdjustLink
+
+ @Description Adjusts the Ethernet link with new speed/duplex setup.
+ This routine is relevant for dTSEC and mEMAC.
+ In case of mEMAC, this routine is also used for manual
+ re-configuration of RGMII speed and duplex mode for
+ RGMII PHYs not supporting in-band status information
+ to MAC.
+
+ @Param[in] h_FmMac - A handle to a FM Module.
+ @Param[in] speed - Ethernet speed.
+ @Param[in] fullDuplex - TRUE for full-duplex mode;
+ FALSE for half-duplex mode.
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_MAC_AdjustLink(t_Handle h_FmMac, e_EnetSpeed speed, bool fullDuplex);
+
+/**************************************************************************//**
+ @Function FM_MAC_RestartAutoneg
+
+ @Description Restarts the auto-negotiation process.
+ When auto-negotiation process is invoked under traffic the
+ auto-negotiation process between the internal SGMII PHY and the
+ external PHY does not always complete successfully. Calling this
+ function will restart the auto-negotiation process that will end
+ successfully. It is recommended to call this function after issuing
+ auto-negotiation restart command to the Eth Phy.
+ This routine is relevant only for dTSEC.
+
+ @Param[in] h_FmMac - A handle to a FM Module.
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_MAC_RestartAutoneg(t_Handle h_FmMac);
+
+/**************************************************************************//**
+ @Function FM_MAC_GetId
+
+ @Description Return the MAC ID
+
+ @Param[in] h_FmMac - A handle to a FM Module.
+ @Param[out] p_MacId - MAC ID of device
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only after FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_GetId(t_Handle h_FmMac, uint32_t *p_MacId);
+
+/**************************************************************************//**
+ @Function FM_MAC_GetVesrion
+
+ @Description Return Mac HW chip version
+
+ @Param[in] h_FmMac - A handle to a FM Module.
+ @Param[out] p_MacVresion - Mac version as defined by the chip
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only after FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_GetVesrion(t_Handle h_FmMac, uint32_t *p_MacVresion);
+
+/**************************************************************************//**
+ @Function FM_MAC_MII_WritePhyReg
+
+ @Description Write data into Phy Register
+
+ @Param[in] h_FmMac - A handle to a FM Module.
+ @Param[in] phyAddr - Phy Address on the MII bus
+ @Param[in] reg - Register Number.
+ @Param[in] data - Data to write.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only after FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_MII_WritePhyReg(t_Handle h_FmMac, uint8_t phyAddr, uint8_t reg, uint16_t data);
+
+/**************************************************************************//**
+ @Function FM_MAC_MII_ReadPhyReg
+
+ @Description Read data from Phy Register
+
+ @Param[in] h_FmMac - A handle to a FM Module.
+ @Param[in] phyAddr - Phy Address on the MII bus
+ @Param[in] reg - Register Number.
+ @Param[out] p_Data - Data from PHY.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only after FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_MII_ReadPhyReg(t_Handle h_FmMac, uint8_t phyAddr, uint8_t reg, uint16_t *p_Data);
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+/**************************************************************************//**
+ @Function FM_MAC_DumpRegs
+
+ @Description Dump internal registers
+
+ @Param[in] h_FmMac - A handle to a FM Module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only after FM_MAC_Init().
+*//***************************************************************************/
+t_Error FM_MAC_DumpRegs(t_Handle h_FmMac);
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+/** @} */ /* end of FM_mac_runtime_control_grp group */
+/** @} */ /* end of FM_mac_grp group */
+/** @} */ /* end of FM_grp group */
+
+
+#endif /* __FM_MAC_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_muram_ext.h b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_muram_ext.h
new file mode 100644
index 0000000..ef62c8e
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_muram_ext.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File fm_muram_ext.h
+
+ @Description FM MURAM Application Programming Interface.
+*//***************************************************************************/
+#ifndef __FM_MURAM_EXT
+#define __FM_MURAM_EXT
+
+#include "error_ext.h"
+#include "std_ext.h"
+
+
+/**************************************************************************//**
+
+ @Group FM_grp Frame Manager API
+
+ @Description FM API functions, definitions and enums
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group FM_muram_grp FM MURAM
+
+ @Description FM MURAM API functions, definitions and enums
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group FM_muram_init_grp FM MURAM Initialization Unit
+
+ @Description FM MURAM initialization API functions, definitions and enums
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Function FM_MURAM_ConfigAndInit
+
+ @Description Creates partition in the MURAM.
+
+ The routine returns a handle (descriptor) to the MURAM partition.
+ This descriptor must be passed as first parameter to all other
+ FM-MURAM function calls.
+
+ No actual initialization or configuration of FM_MURAM hardware is
+ done by this routine.
+
+ @Param[in] baseAddress - Pointer to base of memory mapped FM-MURAM.
+ @Param[in] size - Size of the FM-MURAM partition.
+
+ @Return Handle to FM-MURAM object, or NULL for Failure.
+*//***************************************************************************/
+t_Handle FM_MURAM_ConfigAndInit(uintptr_t baseAddress, uint32_t size);
+
+/**************************************************************************//**
+ @Function FM_MURAM_Free
+
+ @Description Frees all resources that were assigned to FM-MURAM module.
+
+ Calling this routine invalidates the descriptor.
+
+ @Param[in] h_FmMuram - FM-MURAM module descriptor.
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_MURAM_Free(t_Handle h_FmMuram);
+
+/** @} */ /* end of FM_muram_init_grp group */
+
+
+/**************************************************************************//**
+ @Group FM_muram_ctrl_grp FM MURAM Control Unit
+
+ @Description FM MURAM control API functions, definitions and enums
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Function FM_MURAM_AllocMem
+
+ @Description Allocate some memory from FM-MURAM partition.
+
+ @Param[in] h_FmMuram - FM-MURAM module descriptor.
+ @Param[in] size - size of the memory to be allocated.
+ @Param[in] align - Alignment of the memory.
+
+ @Return address of the allocated memory; NULL otherwise.
+*//***************************************************************************/
+void * FM_MURAM_AllocMem(t_Handle h_FmMuram, uint32_t size, uint32_t align);
+
+/**************************************************************************//**
+ @Function FM_MURAM_AllocMemForce
+
+ @Description Allocate some specific memory from FM-MURAM partition (according
+ to base).
+
+ @Param[in] h_FmMuram - FM-MURAM module descriptor.
+ @Param[in] base - the desired base-address to be allocated.
+ @Param[in] size - size of the memory to be allocated.
+
+ @Return address of the allocated memory; NULL otherwise.
+*//***************************************************************************/
+void * FM_MURAM_AllocMemForce(t_Handle h_FmMuram, uint64_t base, uint32_t size);
+
+/**************************************************************************//**
+ @Function FM_MURAM_FreeMem
+
+ @Description Free an allocated memory from FM-MURAM partition.
+
+ @Param[in] h_FmMuram - FM-MURAM module descriptor.
+ @Param[in] ptr - A pointer to an allocated memory.
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_MURAM_FreeMem(t_Handle h_FmMuram, void *ptr);
+
+/**************************************************************************//**
+ @Function FM_MURAM_GetFreeMemSize
+
+ @Description Returns the size (in bytes) of free MURAM memory.
+
+ @Param[in] h_FmMuram - FM-MURAM module descriptor.
+
+ @Return Free MURAM memory size in bytes.
+*//***************************************************************************/
+uint64_t FM_MURAM_GetFreeMemSize(t_Handle h_FmMuram);
+
+/** @} */ /* end of FM_muram_ctrl_grp group */
+/** @} */ /* end of FM_muram_grp group */
+/** @} */ /* end of FM_grp group */
+
+
+
+#endif /* __FM_MURAM_EXT */
diff --git a/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_pcd_ext.h b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_pcd_ext.h
new file mode 100644
index 0000000..83cf237
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_pcd_ext.h
@@ -0,0 +1,3714 @@
+/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File fm_pcd_ext.h
+
+ @Description FM PCD API definitions
+*//***************************************************************************/
+#ifndef __FM_PCD_EXT
+#define __FM_PCD_EXT
+
+#include "std_ext.h"
+#include "net_ext.h"
+#include "list_ext.h"
+#include "fm_ext.h"
+#include "fsl_fman_kg.h"
+
+
+/**************************************************************************//**
+ @Group FM_grp Frame Manager API
+
+ @Description Frame Manager Application Programming Interface
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group FM_PCD_grp FM PCD
+
+ @Description Frame Manager PCD (Parse-Classify-Distribute) API.
+
+ The FM PCD module is responsible for the initialization of all
+ global classifying FM modules. This includes the parser general and
+ common registers, the key generator global and common registers,
+ and the policer global and common registers.
+ In addition, the FM PCD SW module will initialize all required
+ key generator schemes, coarse classification flows, and policer
+ profiles. When FM module is configured to work with one of these
+ entities, it will register to it using the FM PORT API. The PCD
+ module will manage the PCD resources - i.e. resource management of
+ KeyGen schemes, etc.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Collection General PCD defines
+*//***************************************************************************/
+#define FM_PCD_MAX_NUM_OF_PRIVATE_HDRS 2 /**< Number of units/headers saved for user */
+
+#define FM_PCD_PRS_NUM_OF_HDRS 16 /**< Number of headers supported by HW parser */
+#define FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS (32 - FM_PCD_MAX_NUM_OF_PRIVATE_HDRS)
+ /**< Number of distinction units is limited by
+ register size (32 bits) minus reserved bits
+ for private headers. */
+#define FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS 4 /**< Maximum number of interchangeable headers
+ in a distinction unit */
+#define FM_PCD_KG_NUM_OF_GENERIC_REGS FM_KG_NUM_OF_GENERIC_REGS /**< Total number of generic KeyGen registers */
+#define FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY 35 /**< Max number allowed on any configuration;
+ For HW implementation reasons, in most
+ cases less than this will be allowed; The
+ driver will return an initialization error
+ if resource is unavailable. */
+#define FM_PCD_KG_NUM_OF_EXTRACT_MASKS 4 /**< Total number of masks allowed on KeyGen extractions. */
+#define FM_PCD_KG_NUM_OF_DEFAULT_GROUPS 16 /**< Number of default value logical groups */
+
+#define FM_PCD_PRS_NUM_OF_LABELS 32 /**< Maximum number of SW parser labels */
+#define FM_PCD_SW_PRS_SIZE 0x00000800 /**< Total size of SW parser area */
+#define FM_PCD_PRS_SW_OFFSET 0x00000040 /**< Size of illegal addresses at the beginning
+ of the SW parser area */
+
+#define FM_PCD_MAX_MANIP_INSRT_TEMPLATE_SIZE 128 /**< Maximum size of insertion template for
+ insert manipulation */
+
+#if (DPAA_VERSION >= 11)
+#define FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES 64 /**< Maximum possible entries for frame replicator group */
+#endif /* (DPAA_VERSION >= 11) */
+/* @} */
+
+
+/**************************************************************************//**
+ @Group FM_PCD_init_grp FM PCD Initialization Unit
+
+ @Description Frame Manager PCD Initialization Unit API
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Description PCD counters
+*//***************************************************************************/
+typedef enum e_FmPcdCounters {
+ e_FM_PCD_KG_COUNTERS_TOTAL, /**< KeyGen counter */
+ e_FM_PCD_PLCR_COUNTERS_RED, /**< Policer counter - counts the total number of RED packets that exit the Policer. */
+ e_FM_PCD_PLCR_COUNTERS_YELLOW, /**< Policer counter - counts the total number of YELLOW packets that exit the Policer. */
+ e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED, /**< Policer counter - counts the number of packets that changed color to RED by the Policer;
+ This is a subset of e_FM_PCD_PLCR_COUNTERS_RED packet count, indicating active color changes. */
+ e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW, /**< Policer counter - counts the number of packets that changed color to YELLOW by the Policer;
+ This is a subset of e_FM_PCD_PLCR_COUNTERS_YELLOW packet count, indicating active color changes. */
+ e_FM_PCD_PLCR_COUNTERS_TOTAL, /**< Policer counter - counts the total number of packets passed in the Policer. */
+ e_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH, /**< Policer counter - counts the number of packets with length mismatch. */
+ e_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH, /**< Parser counter - counts the number of times the parser block is dispatched. */
+ e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED, /**< Parser counter - counts the number of times L2 parse result is returned (including errors). */
+ e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED, /**< Parser counter - counts the number of times L3 parse result is returned (including errors). */
+ e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED, /**< Parser counter - counts the number of times L4 parse result is returned (including errors). */
+ e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED, /**< Parser counter - counts the number of times SHIM parse result is returned (including errors). */
+ e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR, /**< Parser counter - counts the number of times L2 parse result is returned with errors. */
+ e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR, /**< Parser counter - counts the number of times L3 parse result is returned with errors. */
+ e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR, /**< Parser counter - counts the number of times L4 parse result is returned with errors. */
+ e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR, /**< Parser counter - counts the number of times SHIM parse result is returned with errors. */
+ e_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES, /**< Parser counter - counts the number of cycles spent executing soft parser instruction (including stall cycles). */
+ e_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES, /**< Parser counter - counts the number of cycles stalled waiting for parser internal memory reads while executing soft parser instruction. */
+ e_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES, /**< Parser counter - counts the number of cycles spent executing hard parser (including stall cycles). */
+ e_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES, /**< MURAM counter - counts the number of cycles while performing FMan Memory read. */
+ e_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES, /**< MURAM counter - counts the number of cycles stalled while performing FMan Memory read. */
+ e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES, /**< MURAM counter - counts the number of cycles while performing FMan Memory write. */
+ e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES, /**< MURAM counter - counts the number of cycles stalled while performing FMan Memory write. */
+ e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES /**< FPM counter - counts the number of cycles stalled while performing a FPM Command. */
+} e_FmPcdCounters;
+
+/**************************************************************************//**
+ @Description PCD interrupts
+*//***************************************************************************/
+typedef enum e_FmPcdExceptions {
+ e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC, /**< KeyGen double-bit ECC error is detected on internal memory read access. */
+ e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW, /**< KeyGen scheme configuration error indicating a key size larger than 56 bytes. */
+ e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC, /**< Policer double-bit ECC error has been detected on PRAM read access. */
+ e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR, /**< Policer access to a non-initialized profile has been detected. */
+ e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE, /**< Policer RAM self-initialization complete */
+ e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE, /**< Policer atomic action complete */
+ e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC, /**< Parser double-bit ECC error */
+ e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC /**< Parser single-bit ECC error */
+} e_FmPcdExceptions;
+
+
+/**************************************************************************//**
+ @Description Exceptions user callback routine, will be called upon an
+ exception passing the exception identification.
+
+ @Param[in] h_App - User's application descriptor.
+ @Param[in] exception - The exception.
+ *//***************************************************************************/
+typedef void (t_FmPcdExceptionCallback) (t_Handle h_App, e_FmPcdExceptions exception);
+
+/**************************************************************************//**
+ @Description Exceptions user callback routine, will be called upon an exception
+ passing the exception identification.
+
+ @Param[in] h_App - User's application descriptor.
+ @Param[in] exception - The exception.
+ @Param[in] index - id of the relevant source (may be scheme or profile id).
+ *//***************************************************************************/
+typedef void (t_FmPcdIdExceptionCallback) ( t_Handle h_App,
+ e_FmPcdExceptions exception,
+ uint16_t index);
+
+/**************************************************************************//**
+ @Description A callback for enqueuing frame onto a QM queue.
+
+ @Param[in] h_QmArg - Application's handle passed to QM module on enqueue.
+ @Param[in] p_Fd - Frame descriptor for the frame.
+
+ @Return E_OK on success; Error code otherwise.
+ *//***************************************************************************/
+typedef t_Error (t_FmPcdQmEnqueueCallback) (t_Handle h_QmArg, void *p_Fd);
+
+/**************************************************************************//**
+ @Description Host-Command parameters structure.
+
+ When using Host command for PCD functionalities, a dedicated port
+ must be used. If this routine is called for a PCD in a single partition
+ environment, or it is the Master partition in a Multi-partition
+ environment, The port will be initialized by the PCD driver
+ initialization routine.
+ *//***************************************************************************/
+typedef struct t_FmPcdHcParams {
+ uintptr_t portBaseAddr; /**< Virtual Address of Host-Command Port memory mapped registers.*/
+ uint8_t portId; /**< Port Id (0-6 relative to Host-Command/Offline-Parsing ports);
+ NOTE: When configuring Host Command port for
+ FMANv3 devices (DPAA_VERSION 11 and higher),
+ portId=0 MUST be used. */
+ uint16_t liodnBase; /**< LIODN base for this port, to be used together with LIODN offset
+ (irrelevant for P4080 revision 1.0) */
+ uint32_t errFqid; /**< Host-Command Port error queue Id. */
+ uint32_t confFqid; /**< Host-Command Port confirmation queue Id. */
+ uint32_t qmChannel; /**< QM channel dedicated to this Host-Command port;
+ will be used by the FM for dequeue. */
+ t_FmPcdQmEnqueueCallback *f_QmEnqueue; /**< Callback routine for enqueuing a frame to the QM */
+ t_Handle h_QmArg; /**< Application's handle passed to QM module on enqueue */
+} t_FmPcdHcParams;
+
+/**************************************************************************//**
+ @Description The main structure for PCD initialization
+ *//***************************************************************************/
+typedef struct t_FmPcdParams {
+ bool prsSupport; /**< TRUE if Parser will be used for any of the FM ports. */
+ bool ccSupport; /**< TRUE if Coarse Classification will be used for any
+ of the FM ports. */
+ bool kgSupport; /**< TRUE if KeyGen will be used for any of the FM ports. */
+ bool plcrSupport; /**< TRUE if Policer will be used for any of the FM ports. */
+ t_Handle h_Fm; /**< A handle to the FM module. */
+ uint8_t numOfSchemes; /**< Number of schemes dedicated to this partition.
+ this parameter is relevant if 'kgSupport'=TRUE. */
+ bool useHostCommand; /**< Optional for single partition, Mandatory for Multi partition */
+ t_FmPcdHcParams hc; /**< Host Command parameters, relevant only if 'useHostCommand'=TRUE;
+ Relevant when FM not runs in "guest-mode". */
+
+ t_FmPcdExceptionCallback *f_Exception; /**< Callback routine for general PCD exceptions;
+ Relevant when FM not runs in "guest-mode". */
+ t_FmPcdIdExceptionCallback *f_ExceptionId; /**< Callback routine for specific KeyGen scheme or
+ Policer profile exceptions;
+ Relevant when FM not runs in "guest-mode". */
+ t_Handle h_App; /**< A handle to an application layer object; This handle will
+ be passed by the driver upon calling the above callbacks;
+ Relevant when FM not runs in "guest-mode". */
+ uint8_t partPlcrProfilesBase; /**< The first policer-profile-id dedicated to this partition.
+ this parameter is relevant if 'plcrSupport'=TRUE.
+ NOTE: this parameter relevant only when working with multiple partitions. */
+ uint16_t partNumOfPlcrProfiles; /**< Number of policer-profiles dedicated to this partition.
+ this parameter is relevant if 'plcrSupport'=TRUE.
+ NOTE: this parameter relevant only when working with multiple partitions. */
+} t_FmPcdParams;
+
+
+/**************************************************************************//**
+ @Function FM_PCD_Config
+
+ @Description Basic configuration of the PCD module.
+ Creates descriptor for the FM PCD module.
+
+ @Param[in] p_FmPcdParams A structure of parameters for the initialization of PCD.
+
+ @Return A handle to the initialized module.
+*//***************************************************************************/
+t_Handle FM_PCD_Config(t_FmPcdParams *p_FmPcdParams);
+
+/**************************************************************************//**
+ @Function FM_PCD_Init
+
+ @Description Initialization of the PCD module.
+
+ @Param[in] h_FmPcd - FM PCD module descriptor.
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_PCD_Init(t_Handle h_FmPcd);
+
+/**************************************************************************//**
+ @Function FM_PCD_Free
+
+ @Description Frees all resources that were assigned to FM module.
+
+ Calling this routine invalidates the descriptor.
+
+ @Param[in] h_FmPcd - FM PCD module descriptor.
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_PCD_Free(t_Handle h_FmPcd);
+
+/**************************************************************************//**
+ @Group FM_PCD_advanced_cfg_grp FM PCD Advanced Configuration Unit
+
+ @Description Frame Manager PCD Advanced Configuration API.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Function FM_PCD_ConfigException
+
+ @Description Calling this routine changes the internal driver data base
+ from its default selection of exceptions enabling.
+ [DEFAULT_numOfSharedPlcrProfiles].
+
+ @Param[in] h_FmPcd FM PCD module descriptor.
+ @Param[in] exception The exception to be selected.
+ @Param[in] enable TRUE to enable interrupt, FALSE to mask it.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_PCD_ConfigException(t_Handle h_FmPcd, e_FmPcdExceptions exception, bool enable);
+
+/**************************************************************************//**
+ @Function FM_PCD_ConfigHcFramesDataMemory
+
+ @Description Configures memory-partition-id for FMan-Controller Host-Command
+ frames. Calling this routine changes the internal driver data
+ base from its default configuration [0].
+
+ @Param[in] h_FmPcd FM PCD module descriptor.
+ @Param[in] memId Memory partition ID.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions This routine may be called only if 'useHostCommand' was TRUE
+ when FM_PCD_Config() routine was called.
+*//***************************************************************************/
+t_Error FM_PCD_ConfigHcFramesDataMemory(t_Handle h_FmPcd, uint8_t memId);
+
+/**************************************************************************//**
+ @Function FM_PCD_ConfigPlcrNumOfSharedProfiles
+
+ @Description Calling this routine changes the internal driver data base
+ from its default selection of exceptions enablement.
+ [DEFAULT_numOfSharedPlcrProfiles].
+
+ @Param[in] h_FmPcd FM PCD module descriptor.
+ @Param[in] numOfSharedPlcrProfiles Number of profiles to
+ be shared between ports on this partition
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_PCD_ConfigPlcrNumOfSharedProfiles(t_Handle h_FmPcd, uint16_t numOfSharedPlcrProfiles);
+
+/**************************************************************************//**
+ @Function FM_PCD_ConfigPlcrAutoRefreshMode
+
+ @Description Calling this routine changes the internal driver data base
+ from its default selection of exceptions enablement.
+ By default auto-refresh is [DEFAULT_plcrAutoRefresh].
+
+ @Param[in] h_FmPcd FM PCD module descriptor.
+ @Param[in] enable TRUE to enable, FALSE to disable
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_PCD_ConfigPlcrAutoRefreshMode(t_Handle h_FmPcd, bool enable);
+
+/**************************************************************************//**
+ @Function FM_PCD_ConfigPrsMaxCycleLimit
+
+ @Description Calling this routine changes the internal data structure for
+ the maximum parsing time from its default value
+ [DEFAULT_MAX_PRS_CYC_LIM].
+
+ @Param[in] h_FmPcd FM PCD module descriptor.
+ @Param[in] value 0 to disable the mechanism, or new
+ maximum parsing time.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_PCD_ConfigPrsMaxCycleLimit(t_Handle h_FmPcd,uint16_t value);
+
+/** @} */ /* end of FM_PCD_advanced_cfg_grp group */
+/** @} */ /* end of FM_PCD_init_grp group */
+
+
+/**************************************************************************//**
+ @Group FM_PCD_Runtime_grp FM PCD Runtime Unit
+
+ @Description Frame Manager PCD Runtime Unit API
+
+ The runtime control allows creation of PCD infrastructure modules
+ such as Network Environment Characteristics, Classification Plan
+ Groups and Coarse Classification Trees.
+ It also allows on-the-fly initialization, modification and removal
+ of PCD modules such as KeyGen schemes, coarse classification nodes
+ and Policer profiles.
+
+ In order to explain the programming model of the PCD driver interface
+ a few terms should be explained, and will be used below.
+ - Distinction Header - One of the 16 protocols supported by the FM parser,
+ or one of the SHIM headers (1 or 2). May be a header with a special
+ option (see below).
+ - Interchangeable Headers Group - This is a group of Headers recognized
+ by either one of them. For example, if in a specific context the user
+ chooses to treat IPv4 and IPV6 in the same way, they may create an
+ interchangeable Headers Unit consisting of these 2 headers.
+ - A Distinction Unit - a Distinction Header or an Interchangeable Headers
+ Group.
+ - Header with special option - applies to Ethernet, MPLS, VLAN, IPv4 and
+ IPv6, includes multicast, broadcast and other protocol specific options.
+ In terms of hardware it relates to the options available in the classification
+ plan.
+ - Network Environment Characteristics - a set of Distinction Units that define
+ the total recognizable header selection for a certain environment. This is
+ NOT the list of all headers that will ever appear in a flow, but rather
+ everything that needs distinction in a flow, where distinction is made by KeyGen
+ schemes and coarse classification action descriptors.
+
+ The PCD runtime modules initialization is done in stages. The first stage after
+ initializing the PCD module itself is to establish a Network Flows Environment
+ Definition. The application may choose to establish one or more such environments.
+ Later, when needed, the application will have to state, for some of its modules,
+ to which single environment it belongs.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Description A structure for SW parser labels
+ *//***************************************************************************/
+typedef struct t_FmPcdPrsLabelParams {
+ uint32_t instructionOffset; /**< SW parser label instruction offset (2 bytes
+ resolution), relative to Parser RAM. */
+ e_NetHeaderType hdr; /**< The existence of this header will invoke
+ the SW parser code. */
+ uint8_t indexPerHdr; /**< Normally 0, if more than one SW parser
+ attachments for the same header, use this
+ index to distinguish between them. */
+} t_FmPcdPrsLabelParams;
+
+/**************************************************************************//**
+ @Description A structure for SW parser
+ *//***************************************************************************/
+typedef struct t_FmPcdPrsSwParams {
+ bool override; /**< FALSE to invoke a check that nothing else
+ was loaded to this address, including
+ internal patches.
+ TRUE to override any existing code.*/
+ uint32_t size; /**< SW parser code size */
+ uint16_t base; /**< SW parser base (in instruction counts!
+ must be larger than 0x20)*/
+ uint8_t *p_Code; /**< SW parser code */
+ uint32_t swPrsDataParams[FM_PCD_PRS_NUM_OF_HDRS];
+ /**< SW parser data (parameters) */
+ uint8_t numOfLabels; /**< Number of labels for SW parser. */
+ t_FmPcdPrsLabelParams labelsTable[FM_PCD_PRS_NUM_OF_LABELS];
+ /**< SW parser labels table, containing
+ numOfLabels entries */
+} t_FmPcdPrsSwParams;
+
+
+/**************************************************************************//**
+ @Function FM_PCD_Enable
+
+ @Description This routine should be called after PCD is initialized for enabling all
+ PCD engines according to their existing configuration.
+
+ @Param[in] h_FmPcd FM PCD module descriptor.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init() and when PCD is disabled.
+*//***************************************************************************/
+t_Error FM_PCD_Enable(t_Handle h_FmPcd);
+
+/**************************************************************************//**
+ @Function FM_PCD_Disable
+
+ @Description This routine may be called when PCD is enabled in order to
+ disable all PCD engines. It may be called
+ only when none of the ports in the system are using the PCD.
+
+ @Param[in] h_FmPcd FM PCD module descriptor.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init() and when PCD is enabled.
+*//***************************************************************************/
+t_Error FM_PCD_Disable(t_Handle h_FmPcd);
+
+/**************************************************************************//**
+ @Function FM_PCD_GetCounter
+
+ @Description Reads one of the FM PCD counters.
+
+ @Param[in] h_FmPcd FM PCD module descriptor.
+ @Param[in] counter The requested counter.
+
+ @Return Counter's current value.
+
+ @Cautions Allowed only following FM_PCD_Init().
+ Note that it is user's responsibility to call this routine only
+ for enabled counters, and there will be no indication if a
+ disabled counter is accessed.
+*//***************************************************************************/
+uint32_t FM_PCD_GetCounter(t_Handle h_FmPcd, e_FmPcdCounters counter);
+
+/**************************************************************************//**
+@Function FM_PCD_PrsLoadSw
+
+@Description This routine may be called in order to load software parsing code.
+
+
+@Param[in] h_FmPcd FM PCD module descriptor.
+@Param[in] p_SwPrs A pointer to a structure of software
+ parser parameters, including the software
+ parser image.
+
+@Return E_OK on success; Error code otherwise.
+
+@Cautions Allowed only following FM_PCD_Init() and when PCD is disabled.
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_PCD_PrsLoadSw(t_Handle h_FmPcd, t_FmPcdPrsSwParams *p_SwPrs);
+
+/**************************************************************************//**
+@Function FM_PCD_SetAdvancedOffloadSupport
+
+@Description This routine must be called in order to support the following features:
+ IP-fragmentation, IP-reassembly, IPsec, Header-manipulation, frame-replicator.
+
+@Param[in] h_FmPcd FM PCD module descriptor.
+
+@Return E_OK on success; Error code otherwise.
+
+@Cautions Allowed only following FM_PCD_Init() and when PCD is disabled.
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_PCD_SetAdvancedOffloadSupport(t_Handle h_FmPcd);
+
+/**************************************************************************//**
+ @Function FM_PCD_KgSetDfltValue
+
+ @Description Calling this routine sets a global default value to be used
+ by the KeyGen when parser does not recognize a required
+ field/header.
+ By default default values are 0.
+
+ @Param[in] h_FmPcd FM PCD module descriptor.
+ @Param[in] valueId 0,1 - one of 2 global default values.
+ @Param[in] value The requested default value.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init() and when PCD is disabled.
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_PCD_KgSetDfltValue(t_Handle h_FmPcd, uint8_t valueId, uint32_t value);
+
+/**************************************************************************//**
+ @Function FM_PCD_KgSetAdditionalDataAfterParsing
+
+ @Description Calling this routine allows the KeyGen to access data past
+ the parser finishing point.
+
+ @Param[in] h_FmPcd FM PCD module descriptor.
+ @Param[in] payloadOffset the number of bytes beyond the parser location.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init() and when PCD is disabled.
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_PCD_KgSetAdditionalDataAfterParsing(t_Handle h_FmPcd, uint8_t payloadOffset);
+
+/**************************************************************************//**
+ @Function FM_PCD_SetException
+
+ @Description Calling this routine enables/disables PCD interrupts.
+
+ @Param[in] h_FmPcd FM PCD module descriptor.
+ @Param[in] exception The exception to be selected.
+ @Param[in] enable TRUE to enable interrupt, FALSE to mask it.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_PCD_SetException(t_Handle h_FmPcd, e_FmPcdExceptions exception, bool enable);
+
+/**************************************************************************//**
+ @Function FM_PCD_ModifyCounter
+
+ @Description Sets a value to an enabled counter. Use "0" to reset the counter.
+
+ @Param[in] h_FmPcd FM PCD module descriptor.
+ @Param[in] counter The requested counter.
+ @Param[in] value The requested value to be written into the counter.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_PCD_ModifyCounter(t_Handle h_FmPcd, e_FmPcdCounters counter, uint32_t value);
+
+/**************************************************************************//**
+ @Function FM_PCD_SetPlcrStatistics
+
+ @Description This routine may be used to enable/disable policer statistics
+ counter. By default the statistics is enabled.
+
+ @Param[in] h_FmPcd FM PCD module descriptor
+ @Param[in] enable TRUE to enable, FALSE to disable.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_PCD_SetPlcrStatistics(t_Handle h_FmPcd, bool enable);
+
+/**************************************************************************//**
+ @Function FM_PCD_SetPrsStatistics
+
+ @Description Defines whether to gather parser statistics including all ports.
+
+ @Param[in] h_FmPcd FM PCD module descriptor.
+ @Param[in] enable TRUE to enable, FALSE to disable.
+
+ @Return None
+
+ @Cautions Allowed only following FM_PCD_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+void FM_PCD_SetPrsStatistics(t_Handle h_FmPcd, bool enable);
+
+/**************************************************************************//**
+ @Function FM_PCD_HcTxConf
+
+ @Description This routine should be called to confirm frames that were
+ received on the HC confirmation queue.
+
+ @Param[in] h_FmPcd A handle to an FM PCD Module.
+ @Param[in] p_Fd Frame descriptor of the received frame.
+
+ @Cautions Allowed only following FM_PCD_Init(). Allowed only if 'useHostCommand'
+ option was selected in the initialization.
+*//***************************************************************************/
+void FM_PCD_HcTxConf(t_Handle h_FmPcd, t_DpaaFD *p_Fd);
+
+/**************************************************************************//*
+ @Function FM_PCD_ForceIntr
+
+ @Description Causes an interrupt event on the requested source.
+
+ @Param[in] h_FmPcd FM PCD module descriptor.
+ @Param[in] exception An exception to be forced.
+
+ @Return E_OK on success; Error code if the exception is not enabled,
+ or is not able to create interrupt.
+
+ @Cautions Allowed only following FM_PCD_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_PCD_ForceIntr (t_Handle h_FmPcd, e_FmPcdExceptions exception);
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+/**************************************************************************//**
+ @Function FM_PCD_DumpRegs
+
+ @Description Dumps all PCD registers
+
+ @Param[in] h_FmPcd A handle to an FM PCD Module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init().
+ NOTE: this routine may be called only for FM in master mode
+ (i.e. 'guestId'=NCSW_MASTER_ID) or in a case that the registers
+ are mapped.
+*//***************************************************************************/
+t_Error FM_PCD_DumpRegs(t_Handle h_FmPcd);
+
+/**************************************************************************//**
+ @Function FM_PCD_KgDumpRegs
+
+ @Description Dumps all PCD KG registers
+
+ @Param[in] h_FmPcd A handle to an FM PCD Module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init().
+ NOTE: this routine may be called only for FM in master mode
+ (i.e. 'guestId'=NCSW_MASTER_ID) or in a case that the registers
+ are mapped.
+*//***************************************************************************/
+t_Error FM_PCD_KgDumpRegs(t_Handle h_FmPcd);
+
+/**************************************************************************//**
+ @Function FM_PCD_PlcrDumpRegs
+
+ @Description Dumps all PCD Policer registers
+
+ @Param[in] h_FmPcd A handle to an FM PCD Module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init().
+ NOTE: this routine may be called only for FM in master mode
+ (i.e. 'guestId'=NCSW_MASTER_ID) or in a case that the registers
+ are mapped.
+*//***************************************************************************/
+t_Error FM_PCD_PlcrDumpRegs(t_Handle h_FmPcd);
+
+/**************************************************************************//**
+ @Function FM_PCD_PlcrProfileDumpRegs
+
+ @Description Dumps all PCD Policer profile registers
+
+ @Param[in] h_Profile A handle to a Policer profile.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init().
+ NOTE: this routine may be called only for FM in master mode
+ (i.e. 'guestId'=NCSW_MASTER_ID) or in a case that the registers
+ are mapped.
+*//***************************************************************************/
+t_Error FM_PCD_PlcrProfileDumpRegs(t_Handle h_Profile);
+
+/**************************************************************************//**
+ @Function FM_PCD_PrsDumpRegs
+
+ @Description Dumps all PCD Parser registers
+
+ @Param[in] h_FmPcd A handle to an FM PCD Module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init().
+ NOTE: this routine may be called only for FM in master mode
+ (i.e. 'guestId'=NCSW_MASTER_ID) or in a case that the registers
+ are mapped.
+*//***************************************************************************/
+t_Error FM_PCD_PrsDumpRegs(t_Handle h_FmPcd);
+
+/**************************************************************************//**
+ @Function FM_PCD_HcDumpRegs
+
+ @Description Dumps HC Port registers
+
+ @Param[in] h_FmPcd A handle to an FM PCD Module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init().
+ NOTE: this routine may be called only for FM in master mode
+ (i.e. 'guestId'=NCSW_MASTER_ID).
+*//***************************************************************************/
+t_Error FM_PCD_HcDumpRegs(t_Handle h_FmPcd);
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+
+
+/**************************************************************************//**
+ KeyGen FM_PCD_Runtime_build_grp FM PCD Runtime Building Unit
+
+ @Description Frame Manager PCD Runtime Building API
+
+ This group contains routines for setting, deleting and modifying
+ PCD resources, for defining the total PCD tree.
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Collection Definitions of coarse classification
+ parameters as required by KeyGen (when coarse classification
+ is the next engine after this scheme).
+*//***************************************************************************/
+#define FM_PCD_MAX_NUM_OF_CC_TREES 8
+#define FM_PCD_MAX_NUM_OF_CC_GROUPS 16
+#define FM_PCD_MAX_NUM_OF_CC_UNITS 4
+#define FM_PCD_MAX_NUM_OF_KEYS 256
+#define FM_PCD_MAX_NUM_OF_FLOWS (4*KILOBYTE)
+#define FM_PCD_MAX_SIZE_OF_KEY 56
+#define FM_PCD_MAX_NUM_OF_CC_ENTRIES_IN_GRP 16
+#define FM_PCD_LAST_KEY_INDEX 0xffff
+
+#define FM_PCD_MAX_NUM_OF_CC_NODES 255 /* Obsolete, not used - will be removed in the future */
+/* @} */
+
+/**************************************************************************//**
+ @Collection A set of definitions to allow protocol
+ special option description.
+*//***************************************************************************/
+typedef uint32_t protocolOpt_t; /**< A general type to define a protocol option. */
+
+typedef protocolOpt_t ethProtocolOpt_t; /**< Ethernet protocol options. */
+#define ETH_BROADCAST 0x80000000 /**< Ethernet Broadcast. */
+#define ETH_MULTICAST 0x40000000 /**< Ethernet Multicast. */
+
+typedef protocolOpt_t vlanProtocolOpt_t; /**< VLAN protocol options. */
+#define VLAN_STACKED 0x20000000 /**< Stacked VLAN. */
+
+typedef protocolOpt_t mplsProtocolOpt_t; /**< MPLS protocol options. */
+#define MPLS_STACKED 0x10000000 /**< Stacked MPLS. */
+
+typedef protocolOpt_t ipv4ProtocolOpt_t; /**< IPv4 protocol options. */
+#define IPV4_BROADCAST_1 0x08000000 /**< IPv4 Broadcast. */
+#define IPV4_MULTICAST_1 0x04000000 /**< IPv4 Multicast. */
+#define IPV4_UNICAST_2 0x02000000 /**< Tunneled IPv4 - Unicast. */
+#define IPV4_MULTICAST_BROADCAST_2 0x01000000 /**< Tunneled IPv4 - Broadcast/Multicast. */
+
+#define IPV4_FRAG_1 0x00000008 /**< IPV4 reassembly option.
+ IPV4 Reassembly manipulation requires network
+ environment with IPV4 header and IPV4_FRAG_1 option */
+
+typedef protocolOpt_t ipv6ProtocolOpt_t; /**< IPv6 protocol options. */
+#define IPV6_MULTICAST_1 0x00800000 /**< IPv6 Multicast. */
+#define IPV6_UNICAST_2 0x00400000 /**< Tunneled IPv6 - Unicast. */
+#define IPV6_MULTICAST_2 0x00200000 /**< Tunneled IPv6 - Multicast. */
+
+#define IPV6_FRAG_1 0x00000004 /**< IPV6 reassembly option.
+ IPV6 Reassembly manipulation requires network
+ environment with IPV6 header and IPV6_FRAG_1 option;
+ in case where fragment found, the fragment-extension offset
+ may be found at 'shim2' (in parser-result). */
+/* @} */
+
+#define FM_PCD_MANIP_MAX_HDR_SIZE 256
+#define FM_PCD_MANIP_DSCP_TO_VLAN_TRANS 64
+
+/**************************************************************************//**
+ @Collection A set of definitions to support Header Manipulation selection.
+*//***************************************************************************/
+typedef uint32_t hdrManipFlags_t; /**< A general type to define a HMan update command flags. */
+
+typedef hdrManipFlags_t ipv4HdrManipUpdateFlags_t; /**< IPv4 protocol HMan update command flags. */
+
+#define HDR_MANIP_IPV4_TOS 0x80000000 /**< update TOS with the given value ('tos' field
+ of t_FmPcdManipHdrFieldUpdateIpv4) */
+#define HDR_MANIP_IPV4_ID 0x40000000 /**< update IP ID with the given value ('id' field
+ of t_FmPcdManipHdrFieldUpdateIpv4) */
+#define HDR_MANIP_IPV4_TTL 0x20000000 /**< Decrement TTL by 1 */
+#define HDR_MANIP_IPV4_SRC 0x10000000 /**< update IP source address with the given value
+ ('src' field of t_FmPcdManipHdrFieldUpdateIpv4) */
+#define HDR_MANIP_IPV4_DST 0x08000000 /**< update IP destination address with the given value
+ ('dst' field of t_FmPcdManipHdrFieldUpdateIpv4) */
+
+typedef hdrManipFlags_t ipv6HdrManipUpdateFlags_t; /**< IPv6 protocol HMan update command flags. */
+
+#define HDR_MANIP_IPV6_TC 0x80000000 /**< update Traffic Class address with the given value
+ ('trafficClass' field of t_FmPcdManipHdrFieldUpdateIpv6) */
+#define HDR_MANIP_IPV6_HL 0x40000000 /**< Decrement Hop Limit by 1 */
+#define HDR_MANIP_IPV6_SRC 0x20000000 /**< update IP source address with the given value
+ ('src' field of t_FmPcdManipHdrFieldUpdateIpv6) */
+#define HDR_MANIP_IPV6_DST 0x10000000 /**< update IP destination address with the given value
+ ('dst' field of t_FmPcdManipHdrFieldUpdateIpv6) */
+
+typedef hdrManipFlags_t tcpUdpHdrManipUpdateFlags_t;/**< TCP/UDP protocol HMan update command flags. */
+
+#define HDR_MANIP_TCP_UDP_SRC 0x80000000 /**< update TCP/UDP source address with the given value
+ ('src' field of t_FmPcdManipHdrFieldUpdateTcpUdp) */
+#define HDR_MANIP_TCP_UDP_DST 0x40000000 /**< update TCP/UDP destination address with the given value
+ ('dst' field of t_FmPcdManipHdrFieldUpdateTcpUdp) */
+#define HDR_MANIP_TCP_UDP_CHECKSUM 0x20000000 /**< update TCP/UDP checksum */
+
+/* @} */
+
+/**************************************************************************//**
+ @Description A type used for returning the order of the key extraction.
+ each value in this array represents the index of the extraction
+ command as defined by the user in the initialization extraction array.
+ The valid size of this array is the user define number of extractions
+ required (also marked by the second '0' in this array).
+*//***************************************************************************/
+typedef uint8_t t_FmPcdKgKeyOrder [FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY];
+
+/**************************************************************************//**
+ @Description All PCD engines
+*//***************************************************************************/
+typedef enum e_FmPcdEngine {
+ e_FM_PCD_INVALID = 0, /**< Invalid PCD engine */
+ e_FM_PCD_DONE, /**< No PCD Engine indicated */
+ e_FM_PCD_KG, /**< KeyGen */
+ e_FM_PCD_CC, /**< Coarse classifier */
+ e_FM_PCD_PLCR, /**< Policer */
+ e_FM_PCD_PRS, /**< Parser */
+#if (DPAA_VERSION >= 11)
+ e_FM_PCD_FR, /**< Frame-Replicator */
+#endif /* (DPAA_VERSION >= 11) */
+ e_FM_PCD_HASH /**< Hash table */
+} e_FmPcdEngine;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting extraction by header types
+*//***************************************************************************/
+typedef enum e_FmPcdExtractByHdrType {
+ e_FM_PCD_EXTRACT_FROM_HDR, /**< Extract bytes from header */
+ e_FM_PCD_EXTRACT_FROM_FIELD, /**< Extract bytes from header field */
+ e_FM_PCD_EXTRACT_FULL_FIELD /**< Extract a full field */
+} e_FmPcdExtractByHdrType;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting extraction source
+ (when it is not the header)
+*//***************************************************************************/
+typedef enum e_FmPcdExtractFrom {
+ e_FM_PCD_EXTRACT_FROM_FRAME_START, /**< KG & CC: Extract from beginning of frame */
+ e_FM_PCD_EXTRACT_FROM_DFLT_VALUE, /**< KG only: Extract from a default value */
+ e_FM_PCD_EXTRACT_FROM_CURR_END_OF_PARSE, /**< KG & CC: Extract from the point where parsing had finished */
+ e_FM_PCD_EXTRACT_FROM_KEY, /**< CC only: Field where saved KEY */
+ e_FM_PCD_EXTRACT_FROM_HASH, /**< CC only: Field where saved HASH */
+ e_FM_PCD_EXTRACT_FROM_PARSE_RESULT, /**< KG only: Extract from the parser result */
+ e_FM_PCD_EXTRACT_FROM_ENQ_FQID, /**< KG & CC: Extract from enqueue FQID */
+ e_FM_PCD_EXTRACT_FROM_FLOW_ID /**< CC only: Field where saved Dequeue FQID */
+} e_FmPcdExtractFrom;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting extraction type
+*//***************************************************************************/
+typedef enum e_FmPcdExtractType {
+ e_FM_PCD_EXTRACT_BY_HDR, /**< Extract according to header */
+ e_FM_PCD_EXTRACT_NON_HDR, /**< Extract from data that is not the header */
+ e_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO /**< Extract private info as specified by user */
+} e_FmPcdExtractType;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting default extraction value
+*//***************************************************************************/
+typedef enum e_FmPcdKgExtractDfltSelect {
+ e_FM_PCD_KG_DFLT_GBL_0, /**< Default selection is KG register 0 */
+ e_FM_PCD_KG_DFLT_GBL_1, /**< Default selection is KG register 1 */
+ e_FM_PCD_KG_DFLT_PRIVATE_0, /**< Default selection is a per scheme register 0 */
+ e_FM_PCD_KG_DFLT_PRIVATE_1, /**< Default selection is a per scheme register 1 */
+ e_FM_PCD_KG_DFLT_ILLEGAL /**< Illegal selection */
+} e_FmPcdKgExtractDfltSelect;
+
+/**************************************************************************//**
+ @Description Enumeration type defining all default groups - each group shares
+ a default value, one of four user-initialized values.
+*//***************************************************************************/
+typedef enum e_FmPcdKgKnownFieldsDfltTypes {
+ e_FM_PCD_KG_MAC_ADDR, /**< MAC Address */
+ e_FM_PCD_KG_TCI, /**< TCI field */
+ e_FM_PCD_KG_ENET_TYPE, /**< ENET Type */
+ e_FM_PCD_KG_PPP_SESSION_ID, /**< PPP Session id */
+ e_FM_PCD_KG_PPP_PROTOCOL_ID, /**< PPP Protocol id */
+ e_FM_PCD_KG_MPLS_LABEL, /**< MPLS label */
+ e_FM_PCD_KG_IP_ADDR, /**< IP address */
+ e_FM_PCD_KG_PROTOCOL_TYPE, /**< Protocol type */
+ e_FM_PCD_KG_IP_TOS_TC, /**< TOS or TC */
+ e_FM_PCD_KG_IPV6_FLOW_LABEL, /**< IPV6 flow label */
+ e_FM_PCD_KG_IPSEC_SPI, /**< IPSEC SPI */
+ e_FM_PCD_KG_L4_PORT, /**< L4 Port */
+ e_FM_PCD_KG_TCP_FLAG, /**< TCP Flag */
+ e_FM_PCD_KG_GENERIC_FROM_DATA, /**< grouping implemented by SW,
+ any data extraction that is not the full
+ field described above */
+ e_FM_PCD_KG_GENERIC_FROM_DATA_NO_V, /**< grouping implemented by SW,
+ any data extraction without validation */
+ e_FM_PCD_KG_GENERIC_NOT_FROM_DATA /**< grouping implemented by SW,
+ extraction from parser result or
+ direct use of default value */
+} e_FmPcdKgKnownFieldsDfltTypes;
+
+/**************************************************************************//**
+ @Description Enumeration type for defining header index for scenarios with
+ multiple (tunneled) headers
+*//***************************************************************************/
+typedef enum e_FmPcdHdrIndex {
+ e_FM_PCD_HDR_INDEX_NONE = 0, /**< used when multiple headers not used, also
+ to specify regular IP (not tunneled). */
+ e_FM_PCD_HDR_INDEX_1, /**< may be used for VLAN, MPLS, tunneled IP */
+ e_FM_PCD_HDR_INDEX_2, /**< may be used for MPLS, tunneled IP */
+ e_FM_PCD_HDR_INDEX_3, /**< may be used for MPLS */
+ e_FM_PCD_HDR_INDEX_LAST = 0xFF /**< may be used for VLAN, MPLS */
+} e_FmPcdHdrIndex;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting the policer profile functional type
+*//***************************************************************************/
+typedef enum e_FmPcdProfileTypeSelection {
+ e_FM_PCD_PLCR_PORT_PRIVATE, /**< Port dedicated profile */
+ e_FM_PCD_PLCR_SHARED /**< Shared profile (shared within partition) */
+} e_FmPcdProfileTypeSelection;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting the policer profile algorithm
+*//***************************************************************************/
+typedef enum e_FmPcdPlcrAlgorithmSelection {
+ e_FM_PCD_PLCR_PASS_THROUGH, /**< Policer pass through */
+ e_FM_PCD_PLCR_RFC_2698, /**< Policer algorithm RFC 2698 */
+ e_FM_PCD_PLCR_RFC_4115 /**< Policer algorithm RFC 4115 */
+} e_FmPcdPlcrAlgorithmSelection;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting a policer profile color mode
+*//***************************************************************************/
+typedef enum e_FmPcdPlcrColorMode {
+ e_FM_PCD_PLCR_COLOR_BLIND, /**< Color blind */
+ e_FM_PCD_PLCR_COLOR_AWARE /**< Color aware */
+} e_FmPcdPlcrColorMode;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting a policer profile color
+*//***************************************************************************/
+typedef enum e_FmPcdPlcrColor {
+ e_FM_PCD_PLCR_GREEN, /**< Green color code */
+ e_FM_PCD_PLCR_YELLOW, /**< Yellow color code */
+ e_FM_PCD_PLCR_RED, /**< Red color code */
+ e_FM_PCD_PLCR_OVERRIDE /**< Color override code */
+} e_FmPcdPlcrColor;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting the policer profile packet frame length selector
+*//***************************************************************************/
+typedef enum e_FmPcdPlcrFrameLengthSelect {
+ e_FM_PCD_PLCR_L2_FRM_LEN, /**< L2 frame length */
+ e_FM_PCD_PLCR_L3_FRM_LEN, /**< L3 frame length */
+ e_FM_PCD_PLCR_L4_FRM_LEN, /**< L4 frame length */
+ e_FM_PCD_PLCR_FULL_FRM_LEN /**< Full frame length */
+} e_FmPcdPlcrFrameLengthSelect;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting roll-back frame
+*//***************************************************************************/
+typedef enum e_FmPcdPlcrRollBackFrameSelect {
+ e_FM_PCD_PLCR_ROLLBACK_L2_FRM_LEN, /**< Roll-back L2 frame length */
+ e_FM_PCD_PLCR_ROLLBACK_FULL_FRM_LEN /**< Roll-back Full frame length */
+} e_FmPcdPlcrRollBackFrameSelect;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting the policer profile packet or byte mode
+*//***************************************************************************/
+typedef enum e_FmPcdPlcrRateMode {
+ e_FM_PCD_PLCR_BYTE_MODE, /**< Byte mode */
+ e_FM_PCD_PLCR_PACKET_MODE /**< Packet mode */
+} e_FmPcdPlcrRateMode;
+
+/**************************************************************************//**
+ @Description Enumeration type for defining action of frame
+*//***************************************************************************/
+typedef enum e_FmPcdDoneAction {
+ e_FM_PCD_ENQ_FRAME = 0, /**< Enqueue frame */
+ e_FM_PCD_DROP_FRAME /**< Mark this frame as error frame and continue
+ to error flow; 'FM_PORT_FRM_ERR_CLS_DISCARD'
+ flag will be set for this frame. */
+} e_FmPcdDoneAction;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting the policer counter
+*//***************************************************************************/
+typedef enum e_FmPcdPlcrProfileCounters {
+ e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER, /**< Green packets counter */
+ e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER, /**< Yellow packets counter */
+ e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER, /**< Red packets counter */
+ e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER, /**< Recolored yellow packets counter */
+ e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER /**< Recolored red packets counter */
+} e_FmPcdPlcrProfileCounters;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting the PCD action after extraction
+*//***************************************************************************/
+typedef enum e_FmPcdAction {
+ e_FM_PCD_ACTION_NONE, /**< NONE */
+ e_FM_PCD_ACTION_EXACT_MATCH, /**< Exact match on the selected extraction */
+ e_FM_PCD_ACTION_INDEXED_LOOKUP /**< Indexed lookup on the selected extraction */
+} e_FmPcdAction;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting type of insert manipulation
+*//***************************************************************************/
+typedef enum e_FmPcdManipHdrInsrtType {
+ e_FM_PCD_MANIP_INSRT_GENERIC, /**< Insert according to offset & size */
+ e_FM_PCD_MANIP_INSRT_BY_HDR, /**< Insert according to protocol */
+#ifdef FM_CAPWAP_SUPPORT
+ e_FM_PCD_MANIP_INSRT_BY_TEMPLATE /**< Insert template to start of frame */
+#endif /* FM_CAPWAP_SUPPORT */
+} e_FmPcdManipHdrInsrtType;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting type of remove manipulation
+*//***************************************************************************/
+typedef enum e_FmPcdManipHdrRmvType {
+ e_FM_PCD_MANIP_RMV_GENERIC, /**< Remove according to offset & size */
+ e_FM_PCD_MANIP_RMV_BY_HDR /**< Remove according to offset & size */
+} e_FmPcdManipHdrRmvType;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting specific L2 fields removal
+*//***************************************************************************/
+typedef enum e_FmPcdManipHdrRmvSpecificL2 {
+ e_FM_PCD_MANIP_HDR_RMV_ETHERNET, /**< Ethernet/802.3 MAC */
+ e_FM_PCD_MANIP_HDR_RMV_STACKED_QTAGS, /**< stacked QTags */
+ e_FM_PCD_MANIP_HDR_RMV_ETHERNET_AND_MPLS, /**< MPLS and Ethernet/802.3 MAC header until
+ the header which follows the MPLS header */
+ e_FM_PCD_MANIP_HDR_RMV_MPLS /**< Remove MPLS header (Unlimited MPLS labels) */
+} e_FmPcdManipHdrRmvSpecificL2;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting specific fields updates
+*//***************************************************************************/
+typedef enum e_FmPcdManipHdrFieldUpdateType {
+ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN, /**< VLAN updates */
+ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV4, /**< IPV4 updates */
+ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV6, /**< IPV6 updates */
+ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_TCP_UDP, /**< TCP_UDP updates */
+} e_FmPcdManipHdrFieldUpdateType;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting VLAN updates
+*//***************************************************************************/
+typedef enum e_FmPcdManipHdrFieldUpdateVlan {
+ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN_VPRI, /**< Replace VPri of outer most VLAN tag. */
+ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN /**< DSCP to VLAN priority bits translation */
+} e_FmPcdManipHdrFieldUpdateVlan;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting specific L2 fields removal
+*//***************************************************************************/
+typedef enum e_FmPcdManipHdrInsrtSpecificL2 {
+ e_FM_PCD_MANIP_HDR_INSRT_MPLS /**< Insert MPLS header (Unlimited MPLS labels) */
+} e_FmPcdManipHdrInsrtSpecificL2;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting type of header insertion
+*//***************************************************************************/
+typedef enum e_FmPcdManipHdrInsrtByHdrType {
+ e_FM_PCD_MANIP_INSRT_BY_HDR_SPECIFIC_L2 /**< Specific L2 fields insertion */
+} e_FmPcdManipHdrInsrtByHdrType;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting specific customCommand
+*//***************************************************************************/
+typedef enum e_FmPcdManipHdrCustomType {
+ e_FM_PCD_MANIP_HDR_CUSTOM_IP_REPLACE, /**< Replace IPv4/IPv6 */
+} e_FmPcdManipHdrCustomType;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting specific customCommand
+*//***************************************************************************/
+typedef enum e_FmPcdManipHdrCustomIpReplace {
+ e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV4_BY_IPV6, /**< Replace IPv4 by IPv6 */
+ e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4 /**< Replace IPv6 by IPv4 */
+} e_FmPcdManipHdrCustomIpReplace;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting type of header removal
+*//***************************************************************************/
+typedef enum e_FmPcdManipHdrRmvByHdrType {
+ e_FM_PCD_MANIP_RMV_BY_HDR_SPECIFIC_L2 = 0, /**< Specific L2 fields removal */
+#ifdef FM_CAPWAP_SUPPORT
+ e_FM_PCD_MANIP_RMV_BY_HDR_FROM_START, /**< Locate from data that is not the header */
+#endif /* FM_CAPWAP_SUPPORT */
+} e_FmPcdManipHdrRmvByHdrType;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting type of timeout mode
+*//***************************************************************************/
+typedef enum e_FmPcdManipReassemTimeOutMode {
+ e_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAMES, /**< Limits the time of the reassembly process
+ from the first fragment to the last */
+ e_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAG /**< Limits the time of receiving the fragment */
+} e_FmPcdManipReassemTimeOutMode;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting type of WaysNumber mode
+*//***************************************************************************/
+typedef enum e_FmPcdManipReassemWaysNumber {
+ e_FM_PCD_MANIP_ONE_WAY_HASH = 1, /**< One way hash */
+ e_FM_PCD_MANIP_TWO_WAYS_HASH, /**< Two ways hash */
+ e_FM_PCD_MANIP_THREE_WAYS_HASH, /**< Three ways hash */
+ e_FM_PCD_MANIP_FOUR_WAYS_HASH, /**< Four ways hash */
+ e_FM_PCD_MANIP_FIVE_WAYS_HASH, /**< Five ways hash */
+ e_FM_PCD_MANIP_SIX_WAYS_HASH, /**< Six ways hash */
+ e_FM_PCD_MANIP_SEVEN_WAYS_HASH, /**< Seven ways hash */
+ e_FM_PCD_MANIP_EIGHT_WAYS_HASH /**< Eight ways hash */
+} e_FmPcdManipReassemWaysNumber;
+
+#ifdef FM_CAPWAP_SUPPORT
+/**************************************************************************//**
+ @Description Enumeration type for selecting type of statistics mode
+*//***************************************************************************/
+typedef enum e_FmPcdStatsType {
+ e_FM_PCD_STATS_PER_FLOWID = 0 /**< Flow ID is used as index for getting statistics */
+} e_FmPcdStatsType;
+#endif /* FM_CAPWAP_SUPPORT */
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting manipulation type
+*//***************************************************************************/
+typedef enum e_FmPcdManipType {
+ e_FM_PCD_MANIP_HDR = 0, /**< Header manipulation */
+ e_FM_PCD_MANIP_REASSEM, /**< Reassembly */
+ e_FM_PCD_MANIP_FRAG, /**< Fragmentation */
+ e_FM_PCD_MANIP_SPECIAL_OFFLOAD /**< Special Offloading */
+} e_FmPcdManipType;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting type of statistics mode
+*//***************************************************************************/
+typedef enum e_FmPcdCcStatsMode {
+ e_FM_PCD_CC_STATS_MODE_NONE = 0, /**< No statistics support */
+ e_FM_PCD_CC_STATS_MODE_FRAME, /**< Frame count statistics */
+ e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME, /**< Byte and frame count statistics */
+#if (DPAA_VERSION >= 11)
+ e_FM_PCD_CC_STATS_MODE_RMON, /**< Byte and frame length range count statistics;
+ This mode is supported only on B4860 device */
+#endif /* (DPAA_VERSION >= 11) */
+} e_FmPcdCcStatsMode;
+
+/**************************************************************************//**
+ @Description Enumeration type for determining the action in case an IP packet
+ is larger than MTU but its DF (Don't Fragment) bit is set.
+*//***************************************************************************/
+typedef enum e_FmPcdManipDontFragAction {
+ e_FM_PCD_MANIP_DISCARD_PACKET = 0, /**< Discard packet */
+ e_FM_PCD_MANIP_ENQ_TO_ERR_Q_OR_DISCARD_PACKET = e_FM_PCD_MANIP_DISCARD_PACKET,
+ /**< Obsolete, cannot enqueue to error queue;
+ In practice, selects to discard packets;
+ Will be removed in the future */
+ e_FM_PCD_MANIP_FRAGMENT_PACKET, /**< Fragment packet and continue normal processing */
+ e_FM_PCD_MANIP_CONTINUE_WITHOUT_FRAG /**< Continue normal processing without fragmenting the packet */
+} e_FmPcdManipDontFragAction;
+
+/**************************************************************************//**
+ @Description Enumeration type for selecting type of special offload manipulation
+*//***************************************************************************/
+typedef enum e_FmPcdManipSpecialOffloadType {
+ e_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC /**< IPSec offload manipulation */
+} e_FmPcdManipSpecialOffloadType;
+
+
+/**************************************************************************//**
+ @Description A Union of protocol dependent special options
+*//***************************************************************************/
+typedef union u_FmPcdHdrProtocolOpt {
+ ethProtocolOpt_t ethOpt; /**< Ethernet options */
+ vlanProtocolOpt_t vlanOpt; /**< VLAN options */
+ mplsProtocolOpt_t mplsOpt; /**< MPLS options */
+ ipv4ProtocolOpt_t ipv4Opt; /**< IPv4 options */
+ ipv6ProtocolOpt_t ipv6Opt; /**< IPv6 options */
+} u_FmPcdHdrProtocolOpt;
+
+/**************************************************************************//**
+ @Description A union holding protocol fields
+
+
+ Fields supported as "full fields":
+ HEADER_TYPE_ETH:
+ NET_HEADER_FIELD_ETH_DA
+ NET_HEADER_FIELD_ETH_SA
+ NET_HEADER_FIELD_ETH_TYPE
+
+ HEADER_TYPE_LLC_SNAP:
+ NET_HEADER_FIELD_LLC_SNAP_TYPE
+
+ HEADER_TYPE_VLAN:
+ NET_HEADER_FIELD_VLAN_TCI
+ (index may apply:
+ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1,
+ e_FM_PCD_HDR_INDEX_LAST)
+
+ HEADER_TYPE_MPLS:
+ NET_HEADER_FIELD_MPLS_LABEL_STACK
+ (index may apply:
+ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1,
+ e_FM_PCD_HDR_INDEX_2,
+ e_FM_PCD_HDR_INDEX_LAST)
+
+ HEADER_TYPE_IPv4:
+ NET_HEADER_FIELD_IPv4_SRC_IP
+ NET_HEADER_FIELD_IPv4_DST_IP
+ NET_HEADER_FIELD_IPv4_PROTO
+ NET_HEADER_FIELD_IPv4_TOS
+ (index may apply:
+ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1,
+ e_FM_PCD_HDR_INDEX_2/e_FM_PCD_HDR_INDEX_LAST)
+
+ HEADER_TYPE_IPv6:
+ NET_HEADER_FIELD_IPv6_SRC_IP
+ NET_HEADER_FIELD_IPv6_DST_IP
+ NET_HEADER_FIELD_IPv6_NEXT_HDR
+ NET_HEADER_FIELD_IPv6_VER | NET_HEADER_FIELD_IPv6_FL | NET_HEADER_FIELD_IPv6_TC (must come together!)
+ (index may apply:
+ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1,
+ e_FM_PCD_HDR_INDEX_2/e_FM_PCD_HDR_INDEX_LAST)
+
+ (Note that starting from DPAA 1-1, NET_HEADER_FIELD_IPv6_NEXT_HDR applies to
+ the last next header indication, meaning the next L4, which may be
+ present at the Ipv6 last extension. On earlier revisions this field
+ applies to the Next-Header field of the main IPv6 header)
+
+ HEADER_TYPE_IP:
+ NET_HEADER_FIELD_IP_PROTO
+ (index may apply:
+ e_FM_PCD_HDR_INDEX_LAST)
+ NET_HEADER_FIELD_IP_DSCP
+ (index may apply:
+ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1)
+ HEADER_TYPE_GRE:
+ NET_HEADER_FIELD_GRE_TYPE
+
+ HEADER_TYPE_MINENCAP
+ NET_HEADER_FIELD_MINENCAP_SRC_IP
+ NET_HEADER_FIELD_MINENCAP_DST_IP
+ NET_HEADER_FIELD_MINENCAP_TYPE
+
+ HEADER_TYPE_TCP:
+ NET_HEADER_FIELD_TCP_PORT_SRC
+ NET_HEADER_FIELD_TCP_PORT_DST
+ NET_HEADER_FIELD_TCP_FLAGS
+
+ HEADER_TYPE_UDP:
+ NET_HEADER_FIELD_UDP_PORT_SRC
+ NET_HEADER_FIELD_UDP_PORT_DST
+
+ HEADER_TYPE_UDP_LITE: - relevant only if FM_CAPWAP_SUPPORT define
+ NET_HEADER_FIELD_UDP_LITE_PORT_SRC
+ NET_HEADER_FIELD_UDP_LITE_PORT_DST
+
+ HEADER_TYPE_IPSEC_AH:
+ NET_HEADER_FIELD_IPSEC_AH_SPI
+ NET_HEADER_FIELD_IPSEC_AH_NH
+
+ HEADER_TYPE_IPSEC_ESP:
+ NET_HEADER_FIELD_IPSEC_ESP_SPI
+
+ HEADER_TYPE_SCTP:
+ NET_HEADER_FIELD_SCTP_PORT_SRC
+ NET_HEADER_FIELD_SCTP_PORT_DST
+
+ HEADER_TYPE_DCCP:
+ NET_HEADER_FIELD_DCCP_PORT_SRC
+ NET_HEADER_FIELD_DCCP_PORT_DST
+
+ HEADER_TYPE_PPPoE:
+ NET_HEADER_FIELD_PPPoE_PID
+ NET_HEADER_FIELD_PPPoE_SID
+
+ *****************************************************************
+ Fields supported as "from fields":
+ HEADER_TYPE_ETH (with or without validation):
+ NET_HEADER_FIELD_ETH_TYPE
+
+ HEADER_TYPE_VLAN (with or without validation):
+ NET_HEADER_FIELD_VLAN_TCI
+ (index may apply:
+ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1,
+ e_FM_PCD_HDR_INDEX_LAST)
+
+ HEADER_TYPE_IPv4 (without validation):
+ NET_HEADER_FIELD_IPv4_PROTO
+ (index may apply:
+ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1,
+ e_FM_PCD_HDR_INDEX_2/e_FM_PCD_HDR_INDEX_LAST)
+
+ HEADER_TYPE_IPv6 (without validation):
+ NET_HEADER_FIELD_IPv6_NEXT_HDR
+ (index may apply:
+ e_FM_PCD_HDR_INDEX_NONE/e_FM_PCD_HDR_INDEX_1,
+ e_FM_PCD_HDR_INDEX_2/e_FM_PCD_HDR_INDEX_LAST)
+
+*//***************************************************************************/
+typedef union t_FmPcdFields {
+ headerFieldEth_t eth; /**< Ethernet */
+ headerFieldVlan_t vlan; /**< VLAN */
+ headerFieldLlcSnap_t llcSnap; /**< LLC SNAP */
+ headerFieldPppoe_t pppoe; /**< PPPoE */
+ headerFieldMpls_t mpls; /**< MPLS */
+ headerFieldIp_t ip; /**< IP */
+ headerFieldIpv4_t ipv4; /**< IPv4 */
+ headerFieldIpv6_t ipv6; /**< IPv6 */
+ headerFieldUdp_t udp; /**< UDP */
+ headerFieldUdpLite_t udpLite; /**< UDP Lite */
+ headerFieldTcp_t tcp; /**< TCP */
+ headerFieldSctp_t sctp; /**< SCTP */
+ headerFieldDccp_t dccp; /**< DCCP */
+ headerFieldGre_t gre; /**< GRE */
+ headerFieldMinencap_t minencap; /**< Minimal Encapsulation */
+ headerFieldIpsecAh_t ipsecAh; /**< IPSec AH */
+ headerFieldIpsecEsp_t ipsecEsp; /**< IPSec ESP */
+ headerFieldUdpEncapEsp_t udpEncapEsp; /**< UDP Encapsulation ESP */
+} t_FmPcdFields;
+
+/**************************************************************************//**
+ @Description Parameters for defining header extraction for key generation
+*//***************************************************************************/
+typedef struct t_FmPcdFromHdr {
+ uint8_t size; /**< Size in byte */
+ uint8_t offset; /**< Byte offset */
+} t_FmPcdFromHdr;
+
+/**************************************************************************//**
+ @Description Parameters for defining field extraction for key generation
+*//***************************************************************************/
+typedef struct t_FmPcdFromField {
+ t_FmPcdFields field; /**< Field selection */
+ uint8_t size; /**< Size in byte */
+ uint8_t offset; /**< Byte offset */
+} t_FmPcdFromField;
+
+/**************************************************************************//**
+ @Description Parameters for defining a single network environment unit
+
+ A distinction unit should be defined if it will later be used
+ by one or more PCD engines to distinguish between flows.
+*//***************************************************************************/
+typedef struct t_FmPcdDistinctionUnit {
+ struct {
+ e_NetHeaderType hdr; /**< One of the headers supported by the FM */
+ u_FmPcdHdrProtocolOpt opt; /**< Select only one option ! */
+ } hdrs[FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS];
+} t_FmPcdDistinctionUnit;
+
+/**************************************************************************//**
+ @Description Parameters for defining all different distinction units supported
+ by a specific PCD Network Environment Characteristics module.
+
+ Each unit represent a protocol or a group of protocols that may
+ be used later by the different PCD engines to distinguish
+ between flows.
+*//***************************************************************************/
+typedef struct t_FmPcdNetEnvParams {
+ uint8_t numOfDistinctionUnits; /**< Number of different units to be identified */
+ t_FmPcdDistinctionUnit units[FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS]; /**< An array of numOfDistinctionUnits of the
+ different units to be identified */
+} t_FmPcdNetEnvParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining a single extraction action when
+ creating a key
+*//***************************************************************************/
+typedef struct t_FmPcdExtractEntry {
+ e_FmPcdExtractType type; /**< Extraction type select */
+ union {
+ struct {
+ e_NetHeaderType hdr; /**< Header selection */
+ bool ignoreProtocolValidation;
+ /**< Ignore protocol validation */
+ e_FmPcdHdrIndex hdrIndex; /**< Relevant only for MPLS, VLAN and tunneled
+ IP. Otherwise should be cleared. */
+ e_FmPcdExtractByHdrType type; /**< Header extraction type select */
+ union {
+ t_FmPcdFromHdr fromHdr; /**< Extract bytes from header parameters */
+ t_FmPcdFromField fromField; /**< Extract bytes from field parameters */
+ t_FmPcdFields fullField; /**< Extract full filed parameters */
+ } extractByHdrType;
+ } extractByHdr; /**< used when type = e_FM_PCD_KG_EXTRACT_BY_HDR */
+ struct {
+ e_FmPcdExtractFrom src; /**< Non-header extraction source */
+ e_FmPcdAction action; /**< Relevant for CC Only */
+ uint16_t icIndxMask; /**< Relevant only for CC when
+ action = e_FM_PCD_ACTION_INDEXED_LOOKUP;
+ Note that the number of bits that are set within
+ this mask must be log2 of the CC-node 'numOfKeys'.
+ Note that the mask cannot be set on the lower bits. */
+ uint8_t offset; /**< Byte offset */
+ uint8_t size; /**< Size in byte */
+ } extractNonHdr; /**< used when type = e_FM_PCD_KG_EXTRACT_NON_HDR */
+ };
+} t_FmPcdExtractEntry;
+
+/**************************************************************************//**
+ @Description Parameters for defining masks for each extracted field in the key.
+*//***************************************************************************/
+typedef struct t_FmPcdKgExtractMask {
+ uint8_t extractArrayIndex; /**< Index in the extraction array, as initialized by user */
+ uint8_t offset; /**< Byte offset */
+ uint8_t mask; /**< A byte mask (selected bits will be used) */
+} t_FmPcdKgExtractMask;
+
+/**************************************************************************//**
+ @Description Parameters for defining default selection per groups of fields
+*//***************************************************************************/
+typedef struct t_FmPcdKgExtractDflt {
+ e_FmPcdKgKnownFieldsDfltTypes type; /**< Default type select */
+ e_FmPcdKgExtractDfltSelect dfltSelect; /**< Default register select */
+} t_FmPcdKgExtractDflt;
+
+/**************************************************************************//**
+ @Description Parameters for defining key extraction and hashing
+*//***************************************************************************/
+typedef struct t_FmPcdKgKeyExtractAndHashParams {
+ uint32_t privateDflt0; /**< Scheme default register 0 */
+ uint32_t privateDflt1; /**< Scheme default register 1 */
+ uint8_t numOfUsedExtracts; /**< defines the valid size of the following array */
+ t_FmPcdExtractEntry extractArray [FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY]; /**< An array of extractions definition. */
+ uint8_t numOfUsedDflts; /**< defines the valid size of the following array */
+ t_FmPcdKgExtractDflt dflts[FM_PCD_KG_NUM_OF_DEFAULT_GROUPS];
+ /**< For each extraction used in this scheme, specify the required
+ default register to be used when header is not found.
+ types not specified in this array will get undefined value. */
+ uint8_t numOfUsedMasks; /**< defines the valid size of the following array */
+ t_FmPcdKgExtractMask masks[FM_PCD_KG_NUM_OF_EXTRACT_MASKS];
+ uint8_t hashShift; /**< hash result right shift. Select the 24 bits out of the 64 hash
+ result. 0 means using the 24 LSB's, otherwise use the
+ 24 LSB's after shifting right.*/
+ uint32_t hashDistributionNumOfFqids; /**< must be > 1 and a power of 2. Represents the range
+ of queues for the key and hash functionality */
+ uint8_t hashDistributionFqidsShift; /**< selects the FQID bits that will be effected by the hash */
+ bool symmetricHash; /**< TRUE to generate the same hash for frames with swapped source and
+ destination fields on all layers; If TRUE, driver will check that for
+ all layers, if SRC extraction is selected, DST extraction must also be
+ selected, and vice versa. */
+} t_FmPcdKgKeyExtractAndHashParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining a single FQID mask (extracted OR).
+*//***************************************************************************/
+typedef struct t_FmPcdKgExtractedOrParams {
+ e_FmPcdExtractType type; /**< Extraction type select */
+ union {
+ struct { /**< used when type = e_FM_PCD_KG_EXTRACT_BY_HDR */
+ e_NetHeaderType hdr;
+ e_FmPcdHdrIndex hdrIndex; /**< Relevant only for MPLS, VLAN and tunneled
+ IP. Otherwise should be cleared.*/
+ bool ignoreProtocolValidation;
+ /**< continue extraction even if protocol is not recognized */
+ } extractByHdr; /**< Header to extract by */
+ e_FmPcdExtractFrom src; /**< used when type = e_FM_PCD_KG_EXTRACT_NON_HDR */
+ };
+ uint8_t extractionOffset; /**< Offset for extraction (in bytes). */
+ e_FmPcdKgExtractDfltSelect dfltValue; /**< Select register from which extraction is taken if
+ field not found */
+ uint8_t mask; /**< Extraction mask (specified bits are used) */
+ uint8_t bitOffsetInFqid; /**< 0-31, Selects which bits of the 24 FQID bits to effect using
+ the extracted byte; Assume byte is placed as the 8 MSB's in
+ a 32 bit word where the lower bits
+ are the FQID; i.e if bitOffsetInFqid=1 than its LSB
+ will effect the FQID MSB, if bitOffsetInFqid=24 than the
+ extracted byte will effect the 8 LSB's of the FQID,
+ if bitOffsetInFqid=31 than the byte's MSB will effect
+ the FQID's LSB; 0 means - no effect on FQID;
+ Note that one, and only one of
+ bitOffsetInFqid or bitOffsetInPlcrProfile must be set (i.e,
+ extracted byte must effect either FQID or Policer profile).*/
+ uint8_t bitOffsetInPlcrProfile;
+ /**< 0-15, Selects which bits of the 8 policer profile id bits to
+ effect using the extracted byte; Assume byte is placed
+ as the 8 MSB's in a 16 bit word where the lower bits
+ are the policer profile id; i.e if bitOffsetInPlcrProfile=1
+ than its LSB will effect the profile MSB, if bitOffsetInFqid=8
+ than the extracted byte will effect the whole policer profile id,
+ if bitOffsetInFqid=15 than the byte's MSB will effect
+ the Policer Profile id's LSB;
+ 0 means - no effect on policer profile; Note that one, and only one of
+ bitOffsetInFqid or bitOffsetInPlcrProfile must be set (i.e,
+ extracted byte must effect either FQID or Policer profile).*/
+} t_FmPcdKgExtractedOrParams;
+
+/**************************************************************************//**
+ @Description Parameters for configuring a scheme counter
+*//***************************************************************************/
+typedef struct t_FmPcdKgSchemeCounter {
+ bool update; /**< FALSE to keep the current counter state
+ and continue from that point, TRUE to update/reset
+ the counter when the scheme is written. */
+ uint32_t value; /**< If update=TRUE, this value will be written into the
+ counter. clear this field to reset the counter. */
+} t_FmPcdKgSchemeCounter;
+
+/**************************************************************************//**
+ @Description Parameters for configuring a policer profile for a KeyGen scheme
+ (when policer is the next engine after this scheme).
+*//***************************************************************************/
+typedef struct t_FmPcdKgPlcrProfile {
+ bool sharedProfile; /**< TRUE if this profile is shared between ports
+ (managed by master partition); Must not be TRUE
+ if profile is after Coarse Classification*/
+ bool direct; /**< if TRUE, directRelativeProfileId only selects the profile
+ id, if FALSE fqidOffsetRelativeProfileIdBase is used
+ together with fqidOffsetShift and numOfProfiles
+ parameters, to define a range of profiles from
+ which the KeyGen result will determine the
+ destination policer profile. */
+ union {
+ uint16_t directRelativeProfileId; /**< Used if 'direct' is TRUE, to select policer profile.
+ should indicate the policer profile offset within the
+ port's policer profiles or shared window. */
+ struct {
+ uint8_t fqidOffsetShift; /**< Shift on the KeyGen create FQID offset (i.e. not the
+ final FQID - without the FQID base). */
+ uint8_t fqidOffsetRelativeProfileIdBase;
+ /**< The base of the FMan Port's relative Storage-Profile ID;
+ this value will be "OR'ed" with the KeyGen create FQID
+ offset (i.e. not the final FQID - without the FQID base);
+ the final result should indicate the Storage-Profile offset
+ within the FMan Port's relative Storage-Profiles window/
+ (or the SHARED window depends on 'sharedProfile'). */
+ uint8_t numOfProfiles; /**< Range of profiles starting at base */
+ } indirectProfile; /**< Indirect profile parameters */
+ } profileSelect; /**< Direct/indirect profile selection and parameters */
+} t_FmPcdKgPlcrProfile;
+
+#if (DPAA_VERSION >= 11)
+/**************************************************************************//**
+ @Description Parameters for configuring a storage profile for a KeyGen scheme.
+*//***************************************************************************/
+typedef struct t_FmPcdKgStorageProfile {
+ bool direct; /**< If TRUE, directRelativeProfileId only selects the
+ profile id;
+ If FALSE, fqidOffsetRelativeProfileIdBase is used
+ together with fqidOffsetShift and numOfProfiles
+ parameters to define a range of profiles from which
+ the KeyGen result will determine the destination
+ storage profile. */
+ union {
+ uint16_t directRelativeProfileId; /**< Used when 'direct' is TRUE, to select a storage profile;
+ should indicate the storage profile offset within the
+ port's storage profiles window. */
+ struct {
+ uint8_t fqidOffsetShift; /**< Shift on the KeyGen create FQID offset (i.e. not the
+ final FQID - without the FQID base). */
+ uint8_t fqidOffsetRelativeProfileIdBase;
+ /**< The base of the FMan Port's relative Storage-Profile ID;
+ this value will be "OR'ed" with the KeyGen create FQID
+ offset (i.e. not the final FQID - without the FQID base);
+ the final result should indicate the Storage-Profile offset
+ within the FMan Port's relative Storage-Profiles window. */
+ uint8_t numOfProfiles; /**< Range of profiles starting at base. */
+ } indirectProfile; /**< Indirect profile parameters. */
+ } profileSelect; /**< Direct/indirect profile selection and parameters. */
+} t_FmPcdKgStorageProfile;
+#endif /* (DPAA_VERSION >= 11) */
+
+/**************************************************************************//**
+ @Description Parameters for defining CC as the next engine after KeyGen
+*//***************************************************************************/
+typedef struct t_FmPcdKgCc {
+ t_Handle h_CcTree; /**< A handle to a CC Tree */
+ uint8_t grpId; /**< CC group id within the CC tree */
+ bool plcrNext; /**< TRUE if after CC, in case of data frame,
+ policing is required. */
+ bool bypassPlcrProfileGeneration; /**< TRUE to bypass KeyGen policer profile generation;
+ selected profile is the one set at port initialization. */
+ t_FmPcdKgPlcrProfile plcrProfile; /**< Valid only if plcrNext = TRUE and
+ bypassPlcrProfileGeneration = FALSE */
+} t_FmPcdKgCc;
+
+/**************************************************************************//**
+ @Description Parameters for defining initializing a KeyGen scheme
+*//***************************************************************************/
+typedef struct t_FmPcdKgSchemeParams {
+ bool modify; /**< TRUE to change an existing scheme */
+ union
+ {
+ uint8_t relativeSchemeId; /**< if modify=FALSE:Partition relative scheme id */
+ t_Handle h_Scheme; /**< if modify=TRUE: a handle of the existing scheme */
+ } id;
+ bool alwaysDirect; /**< This scheme is reached only directly, i.e. no need
+ for match vector; KeyGen will ignore it when matching */
+ struct { /**< HL Relevant only if alwaysDirect = FALSE */
+ t_Handle h_NetEnv; /**< A handle to the Network environment as returned
+ by FM_PCD_NetEnvCharacteristicsSet() */
+ uint8_t numOfDistinctionUnits; /**< Number of NetEnv units listed in unitIds array */
+ uint8_t unitIds[FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS];
+ /**< Indexes as passed to SetNetEnvCharacteristics array*/
+ } netEnvParams;
+ bool useHash; /**< use the KeyGen Hash functionality */
+ t_FmPcdKgKeyExtractAndHashParams keyExtractAndHashParams;
+ /**< used only if useHash = TRUE */
+ bool bypassFqidGeneration; /**< Normally - FALSE, TRUE to avoid FQID update in the IC;
+ In such a case FQID after KeyGen will be the default FQID
+ defined for the relevant port, or the FQID defined by CC
+ in cases where CC was the previous engine. */
+ uint32_t baseFqid; /**< Base FQID; Relevant only if bypassFqidGeneration = FALSE;
+ If hash is used and an even distribution is expected
+ according to hashDistributionNumOfFqids, baseFqid must be aligned to
+ hashDistributionNumOfFqids. */
+ uint8_t numOfUsedExtractedOrs; /**< Number of FQID masks listed in extractedOrs array */
+ t_FmPcdKgExtractedOrParams extractedOrs[FM_PCD_KG_NUM_OF_GENERIC_REGS];
+ /**< FM_PCD_KG_NUM_OF_GENERIC_REGS
+ registers are shared between qidMasks
+ functionality and some of the extraction
+ actions; Normally only some will be used
+ for qidMask. Driver will return error if
+ resource is full at initialization time. */
+
+#if (DPAA_VERSION >= 11)
+ bool overrideStorageProfile; /**< TRUE if KeyGen override previously decided storage profile */
+ t_FmPcdKgStorageProfile storageProfile; /**< Used when overrideStorageProfile TRUE */
+#endif /* (DPAA_VERSION >= 11) */
+
+ e_FmPcdEngine nextEngine; /**< may be BMI, PLCR or CC */
+ union { /**< depends on nextEngine */
+ e_FmPcdDoneAction doneAction; /**< Used when next engine is BMI (done) */
+ t_FmPcdKgPlcrProfile plcrProfile; /**< Used when next engine is PLCR */
+ t_FmPcdKgCc cc; /**< Used when next engine is CC */
+ } kgNextEngineParams;
+ t_FmPcdKgSchemeCounter schemeCounter; /**< A structure of parameters for updating
+ the scheme counter */
+} t_FmPcdKgSchemeParams;
+
+/**************************************************************************//**
+ @Collection Definitions for CC statistics
+*//***************************************************************************/
+#if (DPAA_VERSION >= 11)
+#define FM_PCD_CC_STATS_MAX_NUM_OF_FLR 10 /* Maximal supported number of frame length ranges */
+#define FM_PCD_CC_STATS_FLR_SIZE 2 /* Size in bytes of a frame length range limit */
+#endif /* (DPAA_VERSION >= 11) */
+#define FM_PCD_CC_STATS_COUNTER_SIZE 4 /* Size in bytes of a frame length range counter */
+/* @} */
+
+/**************************************************************************//**
+ @Description Parameters for defining CC as the next engine after a CC node.
+*//***************************************************************************/
+typedef struct t_FmPcdCcNextCcParams {
+ t_Handle h_CcNode; /**< A handle of the next CC node */
+} t_FmPcdCcNextCcParams;
+
+#if (DPAA_VERSION >= 11)
+/**************************************************************************//**
+ @Description Parameters for defining Frame replicator as the next engine after a CC node.
+*//***************************************************************************/
+typedef struct t_FmPcdCcNextFrParams {
+ t_Handle h_FrmReplic; /**< A handle of the next frame replicator group */
+} t_FmPcdCcNextFrParams;
+#endif /* (DPAA_VERSION >= 11) */
+
+/**************************************************************************//**
+ @Description Parameters for defining Policer as the next engine after a CC node.
+*//***************************************************************************/
+typedef struct t_FmPcdCcNextPlcrParams {
+ bool overrideParams; /**< TRUE if CC override previously decided parameters*/
+ bool sharedProfile; /**< Relevant only if overrideParams=TRUE:
+ TRUE if this profile is shared between ports */
+ uint16_t newRelativeProfileId; /**< Relevant only if overrideParams=TRUE:
+ (otherwise profile id is taken from KeyGen);
+ This parameter should indicate the policer
+ profile offset within the port's
+ policer profiles or from SHARED window.*/
+ uint32_t newFqid; /**< Relevant only if overrideParams=TRUE:
+ FQID for enqueuing the frame;
+ In earlier chips if policer next engine is KEYGEN,
+ this parameter can be 0, because the KEYGEN
+ always decides the enqueue FQID.*/
+#if (DPAA_VERSION >= 11)
+ uint8_t newRelativeStorageProfileId;
+ /**< Indicates the relative storage profile offset within
+ the port's storage profiles window;
+ Relevant only if the port was configured with VSP. */
+#endif /* (DPAA_VERSION >= 11) */
+} t_FmPcdCcNextPlcrParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining enqueue as the next action after a CC node.
+*//***************************************************************************/
+typedef struct t_FmPcdCcNextEnqueueParams {
+ e_FmPcdDoneAction action; /**< Action - when next engine is BMI (done) */
+ bool overrideFqid; /**< TRUE if CC override previously decided fqid and vspid,
+ relevant if action = e_FM_PCD_ENQ_FRAME */
+ uint32_t newFqid; /**< Valid if overrideFqid=TRUE, FQID for enqueuing the frame
+ (otherwise FQID is taken from KeyGen),
+ relevant if action = e_FM_PCD_ENQ_FRAME */
+#if (DPAA_VERSION >= 11)
+ uint8_t newRelativeStorageProfileId;
+ /**< Valid if overrideFqid=TRUE, Indicates the relative virtual
+ storage profile offset within the port's storage profiles
+ window; Relevant only if the port was configured with VSP. */
+#endif /* (DPAA_VERSION >= 11) */
+} t_FmPcdCcNextEnqueueParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining KeyGen as the next engine after a CC node.
+*//***************************************************************************/
+typedef struct t_FmPcdCcNextKgParams {
+ bool overrideFqid; /**< TRUE if CC override previously decided fqid and vspid,
+ Note - this parameters irrelevant for earlier chips */
+ uint32_t newFqid; /**< Valid if overrideFqid=TRUE, FQID for enqueuing the frame
+ (otherwise FQID is taken from KeyGen),
+ Note - this parameters irrelevant for earlier chips */
+#if (DPAA_VERSION >= 11)
+ uint8_t newRelativeStorageProfileId;
+ /**< Valid if overrideFqid=TRUE, Indicates the relative virtual
+ storage profile offset within the port's storage profiles
+ window; Relevant only if the port was configured with VSP. */
+#endif /* (DPAA_VERSION >= 11) */
+
+ t_Handle h_DirectScheme; /**< Direct scheme handle to go to. */
+} t_FmPcdCcNextKgParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining the next engine after a CC node.
+*//***************************************************************************/
+typedef struct t_FmPcdCcNextEngineParams {
+ e_FmPcdEngine nextEngine; /**< User has to initialize parameters
+ according to nextEngine definition */
+ union {
+ t_FmPcdCcNextCcParams ccParams; /**< Parameters in case next engine is CC */
+ t_FmPcdCcNextPlcrParams plcrParams; /**< Parameters in case next engine is PLCR */
+ t_FmPcdCcNextEnqueueParams enqueueParams; /**< Parameters in case next engine is BMI */
+ t_FmPcdCcNextKgParams kgParams; /**< Parameters in case next engine is KG */
+#if (DPAA_VERSION >= 11)
+ t_FmPcdCcNextFrParams frParams; /**< Parameters in case next engine is FR */
+#endif /* (DPAA_VERSION >= 11) */
+ } params; /**< union used for all the next-engine parameters options */
+
+ t_Handle h_Manip; /**< Handle to Manipulation object.
+ Relevant if next engine is of type result
+ (e_FM_PCD_PLCR, e_FM_PCD_KG, e_FM_PCD_DONE) */
+
+ bool statisticsEn; /**< If TRUE, statistics counters are incremented
+ for each frame passing through this
+ Coarse Classification entry. */
+} t_FmPcdCcNextEngineParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining a single CC key
+*//***************************************************************************/
+typedef struct t_FmPcdCcKeyParams {
+ uint8_t *p_Key; /**< Relevant only if 'action' = e_FM_PCD_ACTION_EXACT_MATCH;
+ pointer to the key of the size defined in keySize */
+ uint8_t *p_Mask; /**< Relevant only if 'action' = e_FM_PCD_ACTION_EXACT_MATCH;
+ pointer to the Mask per key of the size defined
+ in keySize. p_Key and p_Mask (if defined) has to be
+ of the same size defined in the keySize;
+ NOTE that if this value is equal for all entries whithin
+ this table, the driver will automatically use global-mask
+ (i.e. one common mask for all entries) instead of private
+ one; that is done in order to spare some memory and for
+ better performance. */
+ t_FmPcdCcNextEngineParams ccNextEngineParams;
+ /**< parameters for the next for the defined Key in
+ the p_Key */
+} t_FmPcdCcKeyParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining CC keys parameters
+ The driver supports two methods for CC node allocation: dynamic and static.
+ Static mode was created in order to prevent runtime alloc/free
+ of FMan memory (MURAM), which may cause fragmentation; in this mode,
+ the driver automatically allocates the memory according to
+ 'maxNumOfKeys' parameter. The driver calculates the maximal memory
+ size that may be used for this CC-Node taking into consideration
+ 'maskSupport' and 'statisticsMode' parameters.
+ When 'action' = e_FM_PCD_ACTION_INDEXED_LOOKUP in the extraction
+ parameters of this node, 'maxNumOfKeys' must be equal to 'numOfKeys'.
+ In dynamic mode, 'maxNumOfKeys' must be zero. At initialization,
+ all required structures are allocated according to 'numOfKeys'
+ parameter. During runtime modification, these structures are
+ re-allocated according to the updated number of keys.
+
+ Please note that 'action' and 'icIndxMask' mentioned in the
+ specific parameter explanations are passed in the extraction
+ parameters of the node (fields of extractCcParams.extractNonHdr).
+*//***************************************************************************/
+typedef struct t_KeysParams {
+ uint16_t maxNumOfKeys; /**< Maximum number of keys that will (ever) be used in this CC-Node;
+ A value of zero may be used for dynamic memory allocation. */
+ bool maskSupport; /**< This parameter is relevant only if a node is initialized with
+ 'action' = e_FM_PCD_ACTION_EXACT_MATCH and maxNumOfKeys > 0;
+ Should be TRUE to reserve table memory for key masks, even if
+ initial keys do not contain masks, or if the node was initialized
+ as 'empty' (without keys); this will allow user to add keys with
+ masks at runtime.
+ NOTE that if user want to use only global-masks (i.e. one common mask
+ for all the entries within this table, this parameter should set to 'FALSE'. */
+ e_FmPcdCcStatsMode statisticsMode; /**< Determines the supported statistics mode for all node's keys.
+ To enable statistics gathering, statistics should be enabled per
+ every key, using 'statisticsEn' in next engine parameters structure
+ of that key;
+ If 'maxNumOfKeys' is set, all required structures will be
+ preallocated for all keys. */
+#if (DPAA_VERSION >= 11)
+ uint16_t frameLengthRanges[FM_PCD_CC_STATS_MAX_NUM_OF_FLR];
+ /**< Relevant only for 'RMON' statistics mode
+ (this feature is supported only on B4860 device);
+ Holds a list of programmable thresholds - for each received frame,
+ its length in bytes is examined against these range thresholds and
+ the appropriate counter is incremented by 1 - for example, to belong
+ to range i, the following should hold:
+ range i-1 threshold < frame length <= range i threshold
+ Each range threshold must be larger then its preceding range
+ threshold, and last range threshold must be 0xFFFF. */
+#endif /* (DPAA_VERSION >= 11) */
+ uint16_t numOfKeys; /**< Number of initial keys;
+ Note that in case of 'action' = e_FM_PCD_ACTION_INDEXED_LOOKUP,
+ this field should be power-of-2 of the number of bits that are
+ set in 'icIndxMask'. */
+ uint8_t keySize; /**< Size of key - for extraction of type FULL_FIELD, 'keySize' has
+ to be the standard size of the selected key; For other extraction
+ types, 'keySize' has to be as size of extraction; When 'action' =
+ e_FM_PCD_ACTION_INDEXED_LOOKUP, 'keySize' must be 2. */
+ t_FmPcdCcKeyParams keyParams[FM_PCD_MAX_NUM_OF_KEYS];
+ /**< An array with 'numOfKeys' entries, each entry specifies the
+ corresponding key parameters;
+ When 'action' = e_FM_PCD_ACTION_EXACT_MATCH, this value must not
+ exceed 255 (FM_PCD_MAX_NUM_OF_KEYS-1) as the last entry is saved
+ for the 'miss' entry. */
+ t_FmPcdCcNextEngineParams ccNextEngineParamsForMiss;
+ /**< Parameters for defining the next engine when a key is not matched;
+ Not relevant if action = e_FM_PCD_ACTION_INDEXED_LOOKUP. */
+} t_KeysParams;
+
+
+/**************************************************************************//**
+ @Description Parameters for defining a CC node
+*//***************************************************************************/
+typedef struct t_FmPcdCcNodeParams {
+ t_FmPcdExtractEntry extractCcParams; /**< Extraction parameters */
+ t_KeysParams keysParams; /**< Keys definition matching the selected extraction */
+} t_FmPcdCcNodeParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining a hash table
+*//***************************************************************************/
+typedef struct t_FmPcdHashTableParams {
+ uint16_t maxNumOfKeys; /**< Maximum Number Of Keys that will (ever) be used in this Hash-table */
+ e_FmPcdCcStatsMode statisticsMode; /**< If not e_FM_PCD_CC_STATS_MODE_NONE, the required structures for the
+ requested statistics mode will be allocated according to maxNumOfKeys. */
+ uint8_t kgHashShift; /**< KG-Hash-shift as it was configured in the KG-scheme
+ that leads to this hash-table. */
+ uint16_t hashResMask; /**< Mask that will be used on the hash-result;
+ The number-of-sets for this hash will be calculated
+ as (2^(number of bits set in 'hashResMask'));
+ The 4 lower bits must be cleared. */
+ uint8_t hashShift; /**< Byte offset from the beginning of the KeyGen hash result to the
+ 2-bytes to be used as hash index. */
+ uint8_t matchKeySize; /**< Size of the exact match keys held by the hash buckets */
+
+ t_FmPcdCcNextEngineParams ccNextEngineParamsForMiss; /**< Parameters for defining the next engine when a key is not matched */
+} t_FmPcdHashTableParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining a CC tree group.
+
+ This structure defines a CC group in terms of NetEnv units
+ and the action to be taken in each case. The unitIds list must
+ be given in order from low to high indices.
+
+ t_FmPcdCcNextEngineParams is a list of 2^numOfDistinctionUnits
+ structures where each defines the next action to be taken for
+ each units combination. for example:
+ numOfDistinctionUnits = 2
+ unitIds = {1,3}
+ p_NextEnginePerEntriesInGrp[0] = t_FmPcdCcNextEngineParams for the case that
+ unit 1 - not found; unit 3 - not found;
+ p_NextEnginePerEntriesInGrp[1] = t_FmPcdCcNextEngineParams for the case that
+ unit 1 - not found; unit 3 - found;
+ p_NextEnginePerEntriesInGrp[2] = t_FmPcdCcNextEngineParams for the case that
+ unit 1 - found; unit 3 - not found;
+ p_NextEnginePerEntriesInGrp[3] = t_FmPcdCcNextEngineParams for the case that
+ unit 1 - found; unit 3 - found;
+*//***************************************************************************/
+typedef struct t_FmPcdCcGrpParams {
+ uint8_t numOfDistinctionUnits; /**< Up to 4 */
+ uint8_t unitIds[FM_PCD_MAX_NUM_OF_CC_UNITS];
+ /**< Indices of the units as defined in
+ FM_PCD_NetEnvCharacteristicsSet() */
+ t_FmPcdCcNextEngineParams nextEnginePerEntriesInGrp[FM_PCD_MAX_NUM_OF_CC_ENTRIES_IN_GRP];
+ /**< Maximum entries per group is 16 */
+} t_FmPcdCcGrpParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining CC tree groups
+*//***************************************************************************/
+typedef struct t_FmPcdCcTreeParams {
+ t_Handle h_NetEnv; /**< A handle to the Network environment as returned
+ by FM_PCD_NetEnvCharacteristicsSet() */
+ uint8_t numOfGrps; /**< Number of CC groups within the CC tree */
+ t_FmPcdCcGrpParams ccGrpParams[FM_PCD_MAX_NUM_OF_CC_GROUPS];
+ /**< Parameters for each group. */
+} t_FmPcdCcTreeParams;
+
+
+/**************************************************************************//**
+ @Description CC key statistics structure
+*//***************************************************************************/
+typedef struct t_FmPcdCcKeyStatistics {
+ uint32_t byteCount; /**< This counter reflects byte count of frames that
+ were matched by this key. */
+ uint32_t frameCount; /**< This counter reflects count of frames that
+ were matched by this key. */
+#if (DPAA_VERSION >= 11)
+ uint32_t frameLengthRangeCount[FM_PCD_CC_STATS_MAX_NUM_OF_FLR];
+ /**< These counters reflect how many frames matched
+ this key in 'RMON' statistics mode:
+ Each counter holds the number of frames of a
+ specific frames length range, according to the
+ ranges provided at initialization. */
+#endif /* (DPAA_VERSION >= 11) */
+} t_FmPcdCcKeyStatistics;
+
+/**************************************************************************//**
+ @Description Parameters for defining policer byte rate
+*//***************************************************************************/
+typedef struct t_FmPcdPlcrByteRateModeParams {
+ e_FmPcdPlcrFrameLengthSelect frameLengthSelection; /**< Frame length selection */
+ e_FmPcdPlcrRollBackFrameSelect rollBackFrameSelection; /**< relevant option only e_FM_PCD_PLCR_L2_FRM_LEN,
+ e_FM_PCD_PLCR_FULL_FRM_LEN */
+} t_FmPcdPlcrByteRateModeParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining the policer profile (based on
+ RFC-2698 or RFC-4115 attributes).
+*//***************************************************************************/
+typedef struct t_FmPcdPlcrNonPassthroughAlgParams {
+ e_FmPcdPlcrRateMode rateMode; /**< Byte mode or Packet mode */
+ t_FmPcdPlcrByteRateModeParams byteModeParams; /**< Valid for Byte NULL for Packet */
+ uint32_t comittedInfoRate; /**< KBits/Second or Packets/Second */
+ uint32_t comittedBurstSize; /**< Bytes/Packets */
+ uint32_t peakOrAccessiveInfoRate; /**< KBits/Second or Packets/Second */
+ uint32_t peakOrAccessiveBurstSize; /**< Bytes/Packets */
+} t_FmPcdPlcrNonPassthroughAlgParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining the next engine after policer
+*//***************************************************************************/
+typedef union u_FmPcdPlcrNextEngineParams {
+ e_FmPcdDoneAction action; /**< Action - when next engine is BMI (done) */
+ t_Handle h_Profile; /**< Policer profile handle - used when next engine
+ is Policer, must be a SHARED profile */
+ t_Handle h_DirectScheme; /**< Direct scheme select - when next engine is KeyGen */
+} u_FmPcdPlcrNextEngineParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining the policer profile entry
+*//***************************************************************************/
+typedef struct t_FmPcdPlcrProfileParams {
+ bool modify; /**< TRUE to change an existing profile */
+ union {
+ struct {
+ e_FmPcdProfileTypeSelection profileType; /**< Type of policer profile */
+ t_Handle h_FmPort; /**< Relevant for per-port profiles only */
+ uint16_t relativeProfileId; /**< Profile id - relative to shared group or to port */
+ } newParams; /**< use it when modify = FALSE */
+ t_Handle h_Profile; /**< A handle to a profile - use it when modify=TRUE */
+ } id;
+ e_FmPcdPlcrAlgorithmSelection algSelection; /**< Profile Algorithm PASS_THROUGH, RFC_2698, RFC_4115 */
+ e_FmPcdPlcrColorMode colorMode; /**< COLOR_BLIND, COLOR_AWARE */
+
+ union {
+ e_FmPcdPlcrColor dfltColor; /**< For Color-Blind Pass-Through mode; the policer will re-color
+ any incoming packet with the default value. */
+ e_FmPcdPlcrColor override; /**< For Color-Aware modes; the profile response to a
+ pre-color value of 2'b11. */
+ } color;
+
+ t_FmPcdPlcrNonPassthroughAlgParams nonPassthroughAlgParams; /**< RFC2698 or RFC4115 parameters */
+
+ e_FmPcdEngine nextEngineOnGreen; /**< Next engine for green-colored frames */
+ u_FmPcdPlcrNextEngineParams paramsOnGreen; /**< Next engine parameters for green-colored frames */
+
+ e_FmPcdEngine nextEngineOnYellow; /**< Next engine for yellow-colored frames */
+ u_FmPcdPlcrNextEngineParams paramsOnYellow; /**< Next engine parameters for yellow-colored frames */
+
+ e_FmPcdEngine nextEngineOnRed; /**< Next engine for red-colored frames */
+ u_FmPcdPlcrNextEngineParams paramsOnRed; /**< Next engine parameters for red-colored frames */
+
+ bool trapProfileOnFlowA; /**< Obsolete - do not use */
+ bool trapProfileOnFlowB; /**< Obsolete - do not use */
+ bool trapProfileOnFlowC; /**< Obsolete - do not use */
+} t_FmPcdPlcrProfileParams;
+
+/**************************************************************************//**
+ @Description Parameters for selecting a location for requested manipulation
+*//***************************************************************************/
+typedef struct t_FmManipHdrInfo {
+ e_NetHeaderType hdr; /**< Header selection */
+ e_FmPcdHdrIndex hdrIndex; /**< Relevant only for MPLS, VLAN and tunneled IP. Otherwise should be cleared. */
+ bool byField; /**< TRUE if the location of manipulation is according to some field in the specific header*/
+ t_FmPcdFields fullField; /**< Relevant only when byField = TRUE: Extract field */
+} t_FmManipHdrInfo;
+
+#ifdef FM_CAPWAP_SUPPORT
+/**************************************************************************//**
+ @Description Parameters for defining an insertion manipulation
+ of type e_FM_PCD_MANIP_INSRT_TO_START_OF_FRAME_TEMPLATE
+*//***************************************************************************/
+typedef struct t_FmPcdManipHdrInsrtByTemplateParams {
+ uint8_t size; /**< Size of insert template to the start of the frame. */
+ uint8_t hdrTemplate[FM_PCD_MAX_MANIP_INSRT_TEMPLATE_SIZE];
+ /**< Array of the insertion template. */
+
+ bool modifyOuterIp; /**< TRUE if user want to modify some fields in outer IP. */
+ struct {
+ uint16_t ipOuterOffset; /**< Offset of outer IP in the insert template, relevant if modifyOuterIp = TRUE.*/
+ uint16_t dscpEcn; /**< value of dscpEcn in IP outer, relevant if modifyOuterIp = TRUE.
+ in IPV4 dscpEcn only byte - it has to be adjusted to the right*/
+ bool udpPresent; /**< TRUE if UDP is present in the insert template, relevant if modifyOuterIp = TRUE.*/
+ uint8_t udpOffset; /**< Offset in the insert template of UDP, relevant if modifyOuterIp = TRUE and udpPresent=TRUE.*/
+ uint8_t ipIdentGenId; /**< Used by FMan-CTRL to calculate IP-identification field,relevant if modifyOuterIp = TRUE.*/
+ bool recalculateLength; /**< TRUE if recalculate length has to be performed due to the engines in the path which can change the frame later, relevant if modifyOuterIp = TRUE.*/
+ struct {
+ uint8_t blockSize; /**< The CAAM block-size; Used by FMan-CTRL to calculate the IP Total Length field.*/
+ uint8_t extraBytesAddedAlignedToBlockSize; /**< Used by FMan-CTRL to calculate the IP Total Length field and UDP length*/
+ uint8_t extraBytesAddedNotAlignedToBlockSize;/**< Used by FMan-CTRL to calculate the IP Total Length field and UDP length.*/
+ } recalculateLengthParams; /**< Recalculate length parameters - relevant if modifyOuterIp = TRUE and recalculateLength = TRUE */
+ } modifyOuterIpParams; /**< Outer IP modification parameters - ignored if modifyOuterIp is FALSE */
+
+ bool modifyOuterVlan; /**< TRUE if user wants to modify VPri field in the outer VLAN header*/
+ struct {
+ uint8_t vpri; /**< Value of VPri, relevant if modifyOuterVlan = TRUE
+ VPri only 3 bits, it has to be adjusted to the right*/
+ } modifyOuterVlanParams;
+} t_FmPcdManipHdrInsrtByTemplateParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining CAPWAP fragmentation
+*//***************************************************************************/
+typedef struct t_CapwapFragmentationParams {
+ uint16_t sizeForFragmentation; /**< if length of the frame is greater than this value, CAPWAP fragmentation will be executed.*/
+ bool headerOptionsCompr; /**< TRUE - first fragment include the CAPWAP header options field,
+ and all other fragments exclude the CAPWAP options field,
+ FALSE - all fragments include CAPWAP header options field. */
+} t_CapwapFragmentationParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining CAPWAP reassembly
+*//***************************************************************************/
+typedef struct t_CapwapReassemblyParams {
+ uint16_t maxNumFramesInProcess; /**< Number of frames which can be reassembled concurrently; must be power of 2.
+ In case numOfFramesPerHashEntry == e_FM_PCD_MANIP_FOUR_WAYS_HASH,
+ maxNumFramesInProcess has to be in the range of 4 - 512,
+ In case numOfFramesPerHashEntry == e_FM_PCD_MANIP_EIGHT_WAYS_HASH,
+ maxNumFramesInProcess has to be in the range of 8 - 2048 */
+ bool haltOnDuplicationFrag; /**< If TRUE, reassembly process will be halted due to duplicated fragment,
+ and all processed fragments will be enqueued with error indication;
+ If FALSE, only duplicated fragments will be enqueued with error indication. */
+
+ e_FmPcdManipReassemTimeOutMode timeOutMode; /**< Expiration delay initialized by the reassembly process */
+ uint32_t fqidForTimeOutFrames; /**< FQID in which time out frames will enqueue during Time Out Process */
+ uint32_t timeoutRoutineRequestTime;
+ /**< Represents the time interval in microseconds between consecutive
+ timeout routine requests It has to be power of 2. */
+ uint32_t timeoutThresholdForReassmProcess;
+ /**< Time interval (microseconds) for marking frames in process as too old;
+ Frames in process are those for which at least one fragment was received
+ but not all fragments. */
+
+ e_FmPcdManipReassemWaysNumber numOfFramesPerHashEntry;/**< Number of frames per hash entry (needed for the reassembly process) */
+} t_CapwapReassemblyParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining fragmentation/reassembly manipulation
+*//***************************************************************************/
+typedef struct t_FmPcdManipFragOrReasmParams {
+ bool frag; /**< TRUE if using the structure for fragmentation,
+ otherwise this structure is used for reassembly */
+ uint8_t sgBpid; /**< Scatter/Gather buffer pool id;
+ Same LIODN number is used for these buffers as for
+ the received frames buffers, so buffers of this pool
+ need to be allocated in the same memory area as the
+ received buffers. If the received buffers arrive
+ from different sources, the Scatter/Gather BP id
+ should be mutual to all these sources. */
+ e_NetHeaderType hdr; /**< Header selection */
+ union {
+ t_CapwapFragmentationParams capwapFragParams; /**< Structure for CAPWAP fragmentation,
+ relevant if 'frag' = TRUE, 'hdr' = HEADER_TYPE_CAPWAP */
+ t_CapwapReassemblyParams capwapReasmParams; /**< Structure for CAPWAP reassembly,
+ relevant if 'frag' = FALSE, 'hdr' = HEADER_TYPE_CAPWAP */
+ } u;
+} t_FmPcdManipFragOrReasmParams;
+
+#endif /* FM_CAPWAP_SUPPORT */
+
+/**************************************************************************//**
+ @Description Parameters for defining header removal by header type
+*//***************************************************************************/
+typedef struct t_FmPcdManipHdrRmvByHdrParams {
+ e_FmPcdManipHdrRmvByHdrType type; /**< Selection of header removal location */
+ union {
+#ifdef FM_CAPWAP_SUPPORT
+ struct {
+ bool include; /**< If FALSE, remove until the specified header (not including the header);
+ If TRUE, remove also the specified header. */
+ t_FmManipHdrInfo hdrInfo;
+ } fromStartByHdr; /**< Relevant when type = e_FM_PCD_MANIP_RMV_BY_HDR_FROM_START */
+#endif /* FM_CAPWAP_SUPPORT */
+ e_FmPcdManipHdrRmvSpecificL2 specificL2; /**< Relevant when type = e_FM_PCD_MANIP_BY_HDR_SPECIFIC_L2;
+ Defines which L2 headers to remove. */
+ } u;
+} t_FmPcdManipHdrRmvByHdrParams;
+
+/**************************************************************************//**
+ @Description Parameters for configuring IP fragmentation manipulation
+
+ Restrictions:
+ - IP Fragmentation output fragments must not be forwarded to application directly.
+ - Maximum number of fragments per frame is 16.
+ - Fragmentation of IP fragments is not supported.
+ - IPv4 packets containing header Option fields are fragmented by copying all option
+ fields to each fragment, regardless of the copy bit value.
+ - Transmit confirmation is not supported.
+ - Fragmentation after SEC can't handle S/G frames.
+ - Fragmentation nodes must be set as the last PCD action (i.e. the
+ corresponding CC node key must have next engine set to e_FM_PCD_DONE).
+ - Only BMan buffers shall be used for frames to be fragmented.
+ - IPF does not support VSP. Therefore, on the same port where we have IPF
+ we cannot support VSP.
+ - NOTE: The following comment is relevant only for FMAN v3 devices: IPF
+ does not support VSP. Therefore, on the same port where we have IPF we
+ cannot support VSP.
+*//***************************************************************************/
+typedef struct t_FmPcdManipFragIpParams {
+ uint16_t sizeForFragmentation; /**< If length of the frame is greater than this value,
+ IP fragmentation will be executed.*/
+#if (DPAA_VERSION == 10)
+ uint8_t scratchBpid; /**< Absolute buffer pool id according to BM configuration.*/
+#endif /* (DPAA_VERSION == 10) */
+ bool sgBpidEn; /**< Enable a dedicated buffer pool id for the Scatter/Gather buffer allocation;
+ If disabled, the Scatter/Gather buffer will be allocated from the same pool as the
+ received frame's buffer. */
+ uint8_t sgBpid; /**< Scatter/Gather buffer pool id;
+ This parameters is relevant when 'sgBpidEn=TRUE';
+ Same LIODN number is used for these buffers as for the received frames buffers, so buffers
+ of this pool need to be allocated in the same memory area as the received buffers.
+ If the received buffers arrive from different sources, the Scatter/Gather BP id should be
+ mutual to all these sources. */
+ e_FmPcdManipDontFragAction dontFragAction; /**< Don't Fragment Action - If an IP packet is larger
+ than MTU and its DF bit is set, then this field will
+ determine the action to be taken.*/
+} t_FmPcdManipFragIpParams;
+
+/**************************************************************************//**
+ @Description Parameters for configuring IP reassembly manipulation.
+
+ This is a common structure for both IPv4 and IPv6 reassembly
+ manipulation. For reassembly of both IPv4 and IPv6, make sure to
+ set the 'hdr' field in t_FmPcdManipReassemParams to HEADER_TYPE_IPv6.
+
+ Restrictions:
+ - Application must define at least one scheme to catch the reassembled frames.
+ - Maximum number of fragments per frame is 16.
+ - Reassembly of IPv4 fragments containing Option fields is supported.
+
+*//***************************************************************************/
+typedef struct t_FmPcdManipReassemIpParams {
+ uint8_t relativeSchemeId[2]; /**< Partition relative scheme id:
+ relativeSchemeId[0] - Relative scheme ID for IPV4 Reassembly manipulation;
+ relativeSchemeId[1] - Relative scheme ID for IPV6 Reassembly manipulation;
+ NOTE: The following comment is relevant only for FMAN v2 devices:
+ Relative scheme ID for IPv4/IPv6 Reassembly manipulation must be smaller than
+ the user schemes id to ensure that the reassembly schemes will be first match;
+ Rest schemes, if defined, should have higher relative scheme ID. */
+#if (DPAA_VERSION >= 11)
+ uint32_t nonConsistentSpFqid; /**< In case that other fragments of the frame corresponds to different storage
+ profile than the opening fragment (Non-Consistent-SP state)
+ then one of two possible scenarios occurs:
+ if 'nonConsistentSpFqid != 0', the reassembled frame will be enqueued to
+ this fqid, otherwise a 'Non Consistent SP' bit will be set in the FD[status].*/
+#else
+ uint8_t sgBpid; /**< Buffer pool id for the S/G frame created by the reassembly process */
+#endif /* (DPAA_VERSION >= 11) */
+ uint8_t dataMemId; /**< Memory partition ID for the IPR's external tables structure */
+ uint16_t dataLiodnOffset; /**< LIODN offset for access the IPR's external tables structure. */
+ uint16_t minFragSize[2]; /**< Minimum fragment size:
+ minFragSize[0] - for ipv4, minFragSize[1] - for ipv6 */
+ e_FmPcdManipReassemWaysNumber numOfFramesPerHashEntry[2];
+ /**< Number of frames per hash entry needed for reassembly process:
+ numOfFramesPerHashEntry[0] - for ipv4 (max value is e_FM_PCD_MANIP_EIGHT_WAYS_HASH);
+ numOfFramesPerHashEntry[1] - for ipv6 (max value is e_FM_PCD_MANIP_SIX_WAYS_HASH). */
+ uint16_t maxNumFramesInProcess; /**< Number of frames which can be processed by Reassembly in the same time;
+ Must be power of 2;
+ In the case numOfFramesPerHashEntry == e_FM_PCD_MANIP_FOUR_WAYS_HASH,
+ maxNumFramesInProcess has to be in the range of 4 - 512;
+ In the case numOfFramesPerHashEntry == e_FM_PCD_MANIP_EIGHT_WAYS_HASH,
+ maxNumFramesInProcess has to be in the range of 8 - 2048. */
+ e_FmPcdManipReassemTimeOutMode timeOutMode; /**< Expiration delay initialized by Reassembly process */
+ uint32_t fqidForTimeOutFrames; /**< FQID in which time out frames will enqueue during Time Out Process;
+ Recommended value for this field is 0; in this way timed-out frames will be discarded */
+ uint32_t timeoutThresholdForReassmProcess;
+ /**< Represents the time interval in microseconds which defines
+ if opened frame (at least one fragment was processed but not all the fragments)is found as too old*/
+} t_FmPcdManipReassemIpParams;
+
+/**************************************************************************//**
+ @Description structure for defining IPSEC manipulation
+*//***************************************************************************/
+typedef struct t_FmPcdManipSpecialOffloadIPSecParams {
+ bool decryption; /**< TRUE if being used in decryption direction;
+ FALSE if being used in encryption direction. */
+ bool ecnCopy; /**< TRUE to copy the ECN bits from inner/outer to outer/inner
+ (direction depends on the 'decryption' field). */
+ bool dscpCopy; /**< TRUE to copy the DSCP bits from inner/outer to outer/inner
+ (direction depends on the 'decryption' field). */
+ bool variableIpHdrLen; /**< TRUE for supporting variable IP header length in decryption. */
+ bool variableIpVersion; /**< TRUE for supporting both IP version on the same SA in encryption */
+ uint8_t outerIPHdrLen; /**< if 'variableIpVersion == TRUE' than this field must be set to non-zero value;
+ It is specifies the length of the outer IP header that was configured in the
+ corresponding SA. */
+} t_FmPcdManipSpecialOffloadIPSecParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining special offload manipulation
+*//***************************************************************************/
+typedef struct t_FmPcdManipSpecialOffloadParams {
+ e_FmPcdManipSpecialOffloadType type; /**< Type of special offload manipulation */
+ union
+ {
+ t_FmPcdManipSpecialOffloadIPSecParams ipsec; /**< Parameters for IPSec; Relevant when
+ type = e_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC */
+ } u;
+} t_FmPcdManipSpecialOffloadParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining generic removal manipulation
+*//***************************************************************************/
+typedef struct t_FmPcdManipHdrRmvGenericParams {
+ uint8_t offset; /**< Offset from beginning of header to the start
+ location of the removal */
+ uint8_t size; /**< Size of removed section */
+} t_FmPcdManipHdrRmvGenericParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining generic insertion manipulation
+*//***************************************************************************/
+typedef struct t_FmPcdManipHdrInsrtGenericParams {
+ uint8_t offset; /**< Offset from beginning of header to the start
+ location of the insertion */
+ uint8_t size; /**< Size of inserted section */
+ bool replace; /**< TRUE to override (replace) existing data at
+ 'offset', FALSE to insert */
+ uint8_t *p_Data; /**< Pointer to data to be inserted */
+} t_FmPcdManipHdrInsrtGenericParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining header manipulation VLAN DSCP To Vpri translation
+*//***************************************************************************/
+typedef struct t_FmPcdManipHdrFieldUpdateVlanDscpToVpri {
+ uint8_t dscpToVpriTable[FM_PCD_MANIP_DSCP_TO_VLAN_TRANS];
+ /**< A table of VPri values for each DSCP value;
+ The index is the DSCP value (0-0x3F) and the
+ value is the corresponding VPRI (0-15). */
+ uint8_t vpriDefVal; /**< 0-7, Relevant only if if updateType =
+ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN,
+ this field is the Q Tag default value if the
+ IP header is not found. */
+} t_FmPcdManipHdrFieldUpdateVlanDscpToVpri;
+
+/**************************************************************************//**
+ @Description Parameters for defining header manipulation VLAN fields updates
+*//***************************************************************************/
+typedef struct t_FmPcdManipHdrFieldUpdateVlan {
+ e_FmPcdManipHdrFieldUpdateVlan updateType; /**< Selects VLAN update type */
+ union {
+ uint8_t vpri; /**< 0-7, Relevant only if If updateType =
+ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN_PRI, this
+ is the new VLAN pri. */
+ t_FmPcdManipHdrFieldUpdateVlanDscpToVpri dscpToVpri; /**< Parameters structure, Relevant only if updateType
+ = e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN. */
+ } u;
+} t_FmPcdManipHdrFieldUpdateVlan;
+
+/**************************************************************************//**
+ @Description Parameters for defining header manipulation IPV4 fields updates
+*//***************************************************************************/
+typedef struct t_FmPcdManipHdrFieldUpdateIpv4 {
+ ipv4HdrManipUpdateFlags_t validUpdates; /**< ORed flag, selecting the required updates */
+ uint8_t tos; /**< 8 bit New TOS; Relevant if validUpdates contains
+ HDR_MANIP_IPV4_TOS */
+ uint16_t id; /**< 16 bit New IP ID; Relevant only if validUpdates
+ contains HDR_MANIP_IPV4_ID */
+ uint32_t src; /**< 32 bit New IP SRC; Relevant only if validUpdates
+ contains HDR_MANIP_IPV4_SRC */
+ uint32_t dst; /**< 32 bit New IP DST; Relevant only if validUpdates
+ contains HDR_MANIP_IPV4_DST */
+} t_FmPcdManipHdrFieldUpdateIpv4;
+
+/**************************************************************************//**
+ @Description Parameters for defining header manipulation IPV6 fields updates
+*//***************************************************************************/
+typedef struct t_FmPcdManipHdrFieldUpdateIpv6 {
+ ipv6HdrManipUpdateFlags_t validUpdates; /**< ORed flag, selecting the required updates */
+ uint8_t trafficClass; /**< 8 bit New Traffic Class; Relevant if validUpdates contains
+ HDR_MANIP_IPV6_TC */
+ uint8_t src[NET_HEADER_FIELD_IPv6_ADDR_SIZE];
+ /**< 16 byte new IP SRC; Relevant only if validUpdates
+ contains HDR_MANIP_IPV6_SRC */
+ uint8_t dst[NET_HEADER_FIELD_IPv6_ADDR_SIZE];
+ /**< 16 byte new IP DST; Relevant only if validUpdates
+ contains HDR_MANIP_IPV6_DST */
+} t_FmPcdManipHdrFieldUpdateIpv6;
+
+/**************************************************************************//**
+ @Description Parameters for defining header manipulation TCP/UDP fields updates
+*//***************************************************************************/
+typedef struct t_FmPcdManipHdrFieldUpdateTcpUdp {
+ tcpUdpHdrManipUpdateFlags_t validUpdates; /**< ORed flag, selecting the required updates */
+ uint16_t src; /**< 16 bit New TCP/UDP SRC; Relevant only if validUpdates
+ contains HDR_MANIP_TCP_UDP_SRC */
+ uint16_t dst; /**< 16 bit New TCP/UDP DST; Relevant only if validUpdates
+ contains HDR_MANIP_TCP_UDP_DST */
+} t_FmPcdManipHdrFieldUpdateTcpUdp;
+
+/**************************************************************************//**
+ @Description Parameters for defining header manipulation fields updates
+*//***************************************************************************/
+typedef struct t_FmPcdManipHdrFieldUpdateParams {
+ e_FmPcdManipHdrFieldUpdateType type; /**< Type of header field update manipulation */
+ union {
+ t_FmPcdManipHdrFieldUpdateVlan vlan; /**< Parameters for VLAN update. Relevant when
+ type = e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN */
+ t_FmPcdManipHdrFieldUpdateIpv4 ipv4; /**< Parameters for IPv4 update. Relevant when
+ type = e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV4 */
+ t_FmPcdManipHdrFieldUpdateIpv6 ipv6; /**< Parameters for IPv6 update. Relevant when
+ type = e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV6 */
+ t_FmPcdManipHdrFieldUpdateTcpUdp tcpUdp; /**< Parameters for TCP/UDP update. Relevant when
+ type = e_FM_PCD_MANIP_HDR_FIELD_UPDATE_TCP_UDP */
+ } u;
+} t_FmPcdManipHdrFieldUpdateParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining custom header manipulation for IP replacement
+*//***************************************************************************/
+typedef struct t_FmPcdManipHdrCustomIpHdrReplace {
+ e_FmPcdManipHdrCustomIpReplace replaceType; /**< Selects replace update type */
+ bool decTtlHl; /**< Decrement TTL (IPV4) or Hop limit (IPV6) by 1 */
+ bool updateIpv4Id; /**< Relevant when replaceType =
+ e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4 */
+ uint16_t id; /**< 16 bit New IP ID; Relevant only if
+ updateIpv4Id = TRUE */
+ uint8_t hdrSize; /**< The size of the new IP header */
+ uint8_t hdr[FM_PCD_MANIP_MAX_HDR_SIZE];
+ /**< The new IP header */
+} t_FmPcdManipHdrCustomIpHdrReplace;
+
+/**************************************************************************//**
+ @Description Parameters for defining custom header manipulation
+*//***************************************************************************/
+typedef struct t_FmPcdManipHdrCustomParams {
+ e_FmPcdManipHdrCustomType type; /**< Type of header field update manipulation */
+ union {
+ t_FmPcdManipHdrCustomIpHdrReplace ipHdrReplace; /**< Parameters IP header replacement */
+ } u;
+} t_FmPcdManipHdrCustomParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining specific L2 insertion manipulation
+*//***************************************************************************/
+typedef struct t_FmPcdManipHdrInsrtSpecificL2Params {
+ e_FmPcdManipHdrInsrtSpecificL2 specificL2; /**< Selects which L2 headers to insert */
+ bool update; /**< TRUE to update MPLS header */
+ uint8_t size; /**< size of inserted section */
+ uint8_t *p_Data; /**< data to be inserted */
+} t_FmPcdManipHdrInsrtSpecificL2Params;
+
+/**************************************************************************//**
+ @Description Parameters for defining header insertion manipulation by header type
+*//***************************************************************************/
+typedef struct t_FmPcdManipHdrInsrtByHdrParams {
+ e_FmPcdManipHdrInsrtByHdrType type; /**< Selects manipulation type */
+ union {
+
+ t_FmPcdManipHdrInsrtSpecificL2Params specificL2Params;
+ /**< Used when type = e_FM_PCD_MANIP_INSRT_BY_HDR_SPECIFIC_L2:
+ Selects which L2 headers to remove */
+ } u;
+} t_FmPcdManipHdrInsrtByHdrParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining header insertion manipulation
+*//***************************************************************************/
+typedef struct t_FmPcdManipHdrInsrtParams {
+ e_FmPcdManipHdrInsrtType type; /**< Type of insertion manipulation */
+ union {
+ t_FmPcdManipHdrInsrtByHdrParams byHdr; /**< Parameters for defining header insertion manipulation by header type,
+ relevant if 'type' = e_FM_PCD_MANIP_INSRT_BY_HDR */
+ t_FmPcdManipHdrInsrtGenericParams generic; /**< Parameters for defining generic header insertion manipulation,
+ relevant if 'type' = e_FM_PCD_MANIP_INSRT_GENERIC */
+#ifdef FM_CAPWAP_SUPPORT
+ t_FmPcdManipHdrInsrtByTemplateParams byTemplate; /**< Parameters for defining header insertion manipulation by template,
+ relevant if 'type' = e_FM_PCD_MANIP_INSRT_BY_TEMPLATE */
+#endif /* FM_CAPWAP_SUPPORT */
+ } u;
+} t_FmPcdManipHdrInsrtParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining header removal manipulation
+*//***************************************************************************/
+typedef struct t_FmPcdManipHdrRmvParams {
+ e_FmPcdManipHdrRmvType type; /**< Type of header removal manipulation */
+ union {
+ t_FmPcdManipHdrRmvByHdrParams byHdr; /**< Parameters for defining header removal manipulation by header type,
+ relevant if type = e_FM_PCD_MANIP_RMV_BY_HDR */
+ t_FmPcdManipHdrRmvGenericParams generic; /**< Parameters for defining generic header removal manipulation,
+ relevant if type = e_FM_PCD_MANIP_RMV_GENERIC */
+ } u;
+} t_FmPcdManipHdrRmvParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining header manipulation node
+*//***************************************************************************/
+typedef struct t_FmPcdManipHdrParams {
+ bool rmv; /**< TRUE, to define removal manipulation */
+ t_FmPcdManipHdrRmvParams rmvParams; /**< Parameters for removal manipulation, relevant if 'rmv' = TRUE */
+
+ bool insrt; /**< TRUE, to define insertion manipulation */
+ t_FmPcdManipHdrInsrtParams insrtParams; /**< Parameters for insertion manipulation, relevant if 'insrt' = TRUE */
+
+ bool fieldUpdate; /**< TRUE, to define field update manipulation */
+ t_FmPcdManipHdrFieldUpdateParams fieldUpdateParams; /**< Parameters for field update manipulation, relevant if 'fieldUpdate' = TRUE */
+
+ bool custom; /**< TRUE, to define custom manipulation */
+ t_FmPcdManipHdrCustomParams customParams; /**< Parameters for custom manipulation, relevant if 'custom' = TRUE */
+
+ bool dontParseAfterManip;/**< FALSE to activate the parser a second time after
+ completing the manipulation on the frame */
+} t_FmPcdManipHdrParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining fragmentation manipulation
+*//***************************************************************************/
+typedef struct t_FmPcdManipFragParams {
+ e_NetHeaderType hdr; /**< Header selection */
+ union {
+ t_FmPcdManipFragIpParams ipFrag; /**< Parameters for defining IP fragmentation,
+ relevant if 'hdr' = HEADER_TYPE_Ipv4 or HEADER_TYPE_Ipv6 */
+ } u;
+} t_FmPcdManipFragParams;
+
+/**************************************************************************//**
+ @Description Parameters for defining reassembly manipulation
+*//***************************************************************************/
+typedef struct t_FmPcdManipReassemParams {
+ e_NetHeaderType hdr; /**< Header selection */
+ union {
+ t_FmPcdManipReassemIpParams ipReassem; /**< Parameters for defining IP reassembly,
+ relevant if 'hdr' = HEADER_TYPE_Ipv4 or HEADER_TYPE_Ipv6 */
+ } u;
+} t_FmPcdManipReassemParams;
+
+
+/**************************************************************************//**
+ @Description Parameters for defining a manipulation node
+*//***************************************************************************/
+typedef struct t_FmPcdManipParams {
+ e_FmPcdManipType type; /**< Selects type of manipulation node */
+ union{
+ t_FmPcdManipHdrParams hdr; /**< Parameters for defining header manipulation node */
+ t_FmPcdManipReassemParams reassem; /**< Parameters for defining reassembly manipulation node */
+ t_FmPcdManipFragParams frag; /**< Parameters for defining fragmentation manipulation node */
+ t_FmPcdManipSpecialOffloadParams specialOffload; /**< Parameters for defining special offload manipulation node */
+ } u;
+
+ t_Handle h_NextManip; /**< Supported for Header Manipulation only;
+ Handle to another (previously defined) manipulation node;
+ Allows concatenation of manipulation actions;
+ This parameter is optional and may be NULL. */
+#ifdef FM_CAPWAP_SUPPORT
+ bool fragOrReasm; /**< TRUE, if defined fragmentation/reassembly manipulation */
+ t_FmPcdManipFragOrReasmParams fragOrReasmParams; /**< Parameters for fragmentation/reassembly manipulation,
+ relevant if fragOrReasm = TRUE */
+#endif /* FM_CAPWAP_SUPPORT */
+} t_FmPcdManipParams;
+
+/**************************************************************************//**
+ @Description Structure for retrieving IP reassembly statistics
+*//***************************************************************************/
+typedef struct t_FmPcdManipReassemIpStats {
+ /* common counters for both IPv4 and IPv6 */
+ uint32_t timeout; /**< Counts the number of timeout occurrences */
+ uint32_t rfdPoolBusy; /**< Counts the number of failed attempts to allocate
+ a Reassembly Frame Descriptor */
+ uint32_t internalBufferBusy; /**< Counts the number of times an internal buffer busy occurred */
+ uint32_t externalBufferBusy; /**< Counts the number of times external buffer busy occurred */
+ uint32_t sgFragments; /**< Counts the number of Scatter/Gather fragments */
+ uint32_t dmaSemaphoreDepletion; /**< Counts the number of failed attempts to allocate a DMA semaphore */
+#if (DPAA_VERSION >= 11)
+ uint32_t nonConsistentSp; /**< Counts the number of Non Consistent Storage Profile events for
+ successfully reassembled frames */
+#endif /* (DPAA_VERSION >= 11) */
+ struct {
+ uint32_t successfullyReassembled; /**< Counts the number of successfully reassembled frames */
+ uint32_t validFragments; /**< Counts the total number of valid fragments that
+ have been processed for all frames */
+ uint32_t processedFragments; /**< Counts the number of processed fragments
+ (valid and error fragments) for all frames */
+ uint32_t malformedFragments; /**< Counts the number of malformed fragments processed for all frames */
+ uint32_t discardedFragments; /**< Counts the number of fragments discarded by the reassembly process */
+ uint32_t autoLearnBusy; /**< Counts the number of times a busy condition occurs when attempting
+ to access an IP-Reassembly Automatic Learning Hash set */
+ uint32_t moreThan16Fragments; /**< Counts the fragment occurrences in which the number of fragments-per-frame
+ exceeds 16 */
+ } specificHdrStatistics[2]; /**< slot '0' is for IPv4, slot '1' is for IPv6 */
+} t_FmPcdManipReassemIpStats;
+
+/**************************************************************************//**
+ @Description Structure for retrieving IP fragmentation statistics
+*//***************************************************************************/
+typedef struct t_FmPcdManipFragIpStats {
+ uint32_t totalFrames; /**< Number of frames that passed through the manipulation node */
+ uint32_t fragmentedFrames; /**< Number of frames that were fragmented */
+ uint32_t generatedFragments; /**< Number of fragments that were generated */
+} t_FmPcdManipFragIpStats;
+
+/**************************************************************************//**
+ @Description Structure for retrieving reassembly statistics
+*//***************************************************************************/
+typedef struct t_FmPcdManipReassemStats {
+ union {
+ t_FmPcdManipReassemIpStats ipReassem; /**< Structure for IP reassembly statistics */
+ } u;
+} t_FmPcdManipReassemStats;
+
+/**************************************************************************//**
+ @Description Structure for retrieving fragmentation statistics
+*//***************************************************************************/
+typedef struct t_FmPcdManipFragStats {
+ union {
+ t_FmPcdManipFragIpStats ipFrag; /**< Structure for IP fragmentation statistics */
+ } u;
+} t_FmPcdManipFragStats;
+
+/**************************************************************************//**
+ @Description Structure for selecting manipulation statistics
+*//***************************************************************************/
+typedef struct t_FmPcdManipStats {
+ union {
+ t_FmPcdManipReassemStats reassem; /**< Structure for reassembly statistics */
+ t_FmPcdManipFragStats frag; /**< Structure for fragmentation statistics */
+ } u;
+} t_FmPcdManipStats;
+
+#if (DPAA_VERSION >= 11)
+/**************************************************************************//**
+ @Description Parameters for defining frame replicator group and its members
+*//***************************************************************************/
+typedef struct t_FmPcdFrmReplicGroupParams {
+ uint8_t maxNumOfEntries; /**< Maximal number of members in the group;
+ Must be at least 2. */
+ uint8_t numOfEntries; /**< Number of members in the group;
+ Must be at least 1. */
+ t_FmPcdCcNextEngineParams nextEngineParams[FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES];
+ /**< Array of members' parameters */
+} t_FmPcdFrmReplicGroupParams;
+#endif /* (DPAA_VERSION >= 11) */
+
+#ifdef FM_CAPWAP_SUPPORT
+/**************************************************************************//**
+ @Description structure for defining statistics node
+*//***************************************************************************/
+typedef struct t_FmPcdStatsParams {
+ e_FmPcdStatsType type; /**< type of statistics node */
+} t_FmPcdStatsParams;
+#endif /* FM_CAPWAP_SUPPORT */
+
+
+/**************************************************************************//**
+ @Function FM_PCD_NetEnvCharacteristicsSet
+
+ @Description Define a set of Network Environment Characteristics.
+
+ When setting an environment it is important to understand its
+ application. It is not meant to describe the flows that will run
+ on the ports using this environment, but what the user means TO DO
+ with the PCD mechanisms in order to parse-classify-distribute those
+ frames.
+ By specifying a distinction unit, the user means it would use that option
+ for distinction between frames at either a KeyGen scheme or a coarse
+ classification action descriptor. Using interchangeable headers to define a
+ unit means that the user is indifferent to which of the interchangeable
+ headers is present in the frame, and wants the distinction to be based
+ on the presence of either one of them.
+
+ Depending on context, there are limitations to the use of environments. A
+ port using the PCD functionality is bound to an environment. Some or even
+ all ports may share an environment but also an environment per port is
+ possible. When initializing a scheme, a classification plan group (see below),
+ or a coarse classification tree, one of the initialized environments must be
+ stated and related to. When a port is bound to a scheme, a classification
+ plan group, or a coarse classification tree, it MUST be bound to the same
+ environment.
+
+ The different PCD modules, may relate (for flows definition) ONLY on
+ distinction units as defined by their environment. When initializing a
+ scheme for example, it may not choose to select IPV4 as a match for
+ recognizing flows unless it was defined in the relating environment. In
+ fact, to guide the user through the configuration of the PCD, each module's
+ characterization in terms of flows is not done using protocol names, but using
+ environment indexes.
+
+ In terms of HW implementation, the list of distinction units sets the LCV vectors
+ and later used for match vector, classification plan vectors and coarse classification
+ indexing.
+
+ @Param[in] h_FmPcd FM PCD module descriptor.
+ @Param[in] p_NetEnvParams A structure of parameters for the initialization of
+ the network environment.
+
+ @Return A handle to the initialized object on success; NULL code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init().
+*//***************************************************************************/
+t_Handle FM_PCD_NetEnvCharacteristicsSet(t_Handle h_FmPcd, t_FmPcdNetEnvParams *p_NetEnvParams);
+
+/**************************************************************************//**
+ @Function FM_PCD_NetEnvCharacteristicsDelete
+
+ @Description Deletes a set of Network Environment Characteristics.
+
+ @Param[in] h_NetEnv A handle to the Network environment.
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_PCD_NetEnvCharacteristicsDelete(t_Handle h_NetEnv);
+
+/**************************************************************************//**
+ @Function FM_PCD_KgSchemeSet
+
+ @Description Initializing or modifying and enabling a scheme for the KeyGen.
+ This routine should be called for adding or modifying a scheme.
+ When a scheme needs modifying, the API requires that it will be
+ rewritten. In such a case 'modify' should be TRUE. If the
+ routine is called for a valid scheme and 'modify' is FALSE,
+ it will return error.
+
+ @Param[in] h_FmPcd If this is a new scheme - A handle to an FM PCD Module.
+ Otherwise NULL (ignored by driver).
+ @Param[in,out] p_SchemeParams A structure of parameters for defining the scheme
+
+ @Return A handle to the initialized scheme on success; NULL code otherwise.
+ When used as "modify" (rather than for setting a new scheme),
+ p_SchemeParams->id.h_Scheme will return NULL if action fails due to scheme
+ BUSY state.
+
+ @Cautions Allowed only following FM_PCD_Init().
+*//***************************************************************************/
+t_Handle FM_PCD_KgSchemeSet(t_Handle h_FmPcd,
+ t_FmPcdKgSchemeParams *p_SchemeParams);
+
+/**************************************************************************//**
+ @Function FM_PCD_KgSchemeDelete
+
+ @Description Deleting an initialized scheme.
+
+ @Param[in] h_Scheme scheme handle as returned by FM_PCD_KgSchemeSet()
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init() & FM_PCD_KgSchemeSet().
+*//***************************************************************************/
+t_Error FM_PCD_KgSchemeDelete(t_Handle h_Scheme);
+
+/**************************************************************************//**
+ @Function FM_PCD_KgSchemeGetCounter
+
+ @Description Reads scheme packet counter.
+
+ @Param[in] h_Scheme scheme handle as returned by FM_PCD_KgSchemeSet().
+
+ @Return Counter's current value.
+
+ @Cautions Allowed only following FM_PCD_Init() & FM_PCD_KgSchemeSet().
+*//***************************************************************************/
+uint32_t FM_PCD_KgSchemeGetCounter(t_Handle h_Scheme);
+
+/**************************************************************************//**
+ @Function FM_PCD_KgSchemeSetCounter
+
+ @Description Writes scheme packet counter.
+
+ @Param[in] h_Scheme scheme handle as returned by FM_PCD_KgSchemeSet().
+ @Param[in] value New scheme counter value - typically '0' for
+ resetting the counter.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init() & FM_PCD_KgSchemeSet().
+*//***************************************************************************/
+t_Error FM_PCD_KgSchemeSetCounter(t_Handle h_Scheme, uint32_t value);
+
+/**************************************************************************//**
+ @Function FM_PCD_PlcrProfileSet
+
+ @Description Sets a profile entry in the policer profile table.
+ The routine overrides any existing value.
+
+ @Param[in] h_FmPcd A handle to an FM PCD Module.
+ @Param[in] p_Profile A structure of parameters for defining a
+ policer profile entry.
+
+ @Return A handle to the initialized object on success; NULL code otherwise.
+ When used as "modify" (rather than for setting a new profile),
+ p_Profile->id.h_Profile will return NULL if action fails due to profile
+ BUSY state.
+ @Cautions Allowed only following FM_PCD_Init().
+*//***************************************************************************/
+t_Handle FM_PCD_PlcrProfileSet(t_Handle h_FmPcd,
+ t_FmPcdPlcrProfileParams *p_Profile);
+
+/**************************************************************************//**
+ @Function FM_PCD_PlcrProfileDelete
+
+ @Description Delete a profile entry in the policer profile table.
+ The routine set entry to invalid.
+
+ @Param[in] h_Profile A handle to the profile.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init().
+*//***************************************************************************/
+t_Error FM_PCD_PlcrProfileDelete(t_Handle h_Profile);
+
+/**************************************************************************//**
+ @Function FM_PCD_PlcrProfileGetCounter
+
+ @Description Sets an entry in the classification plan.
+ The routine overrides any existing value.
+
+ @Param[in] h_Profile A handle to the profile.
+ @Param[in] counter Counter selector.
+
+ @Return specific counter value.
+
+ @Cautions Allowed only following FM_PCD_Init().
+*//***************************************************************************/
+uint32_t FM_PCD_PlcrProfileGetCounter(t_Handle h_Profile,
+ e_FmPcdPlcrProfileCounters counter);
+
+/**************************************************************************//**
+ @Function FM_PCD_PlcrProfileSetCounter
+
+ @Description Sets an entry in the classification plan.
+ The routine overrides any existing value.
+
+ @Param[in] h_Profile A handle to the profile.
+ @Param[in] counter Counter selector.
+ @Param[in] value value to set counter with.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init().
+*//***************************************************************************/
+t_Error FM_PCD_PlcrProfileSetCounter(t_Handle h_Profile,
+ e_FmPcdPlcrProfileCounters counter,
+ uint32_t value);
+
+/**************************************************************************//**
+ @Function FM_PCD_CcRootBuild
+
+ @Description This routine must be called to define a complete coarse
+ classification tree. This is the way to define coarse
+ classification to a certain flow - the KeyGen schemes
+ may point only to trees defined in this way.
+
+ @Param[in] h_FmPcd FM PCD module descriptor.
+ @Param[in] p_Params A structure of parameters to define the tree.
+
+ @Return A handle to the initialized object on success; NULL code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init().
+*//***************************************************************************/
+t_Handle FM_PCD_CcRootBuild (t_Handle h_FmPcd,
+ t_FmPcdCcTreeParams *p_Params);
+
+/**************************************************************************//**
+ @Function FM_PCD_CcRootDelete
+
+ @Description Deleting an built tree.
+
+ @Param[in] h_CcTree A handle to a CC tree.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init().
+*//***************************************************************************/
+t_Error FM_PCD_CcRootDelete(t_Handle h_CcTree);
+
+/**************************************************************************//**
+ @Function FM_PCD_CcRootModifyNextEngine
+
+ @Description Modify the Next Engine Parameters in the entry of the tree.
+
+ @Param[in] h_CcTree A handle to the tree
+ @Param[in] grpId A Group index in the tree
+ @Param[in] index Entry index in the group defined by grpId
+ @Param[in] p_FmPcdCcNextEngineParams Pointer to new next engine parameters
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_CcBuildTree().
+*//***************************************************************************/
+t_Error FM_PCD_CcRootModifyNextEngine(t_Handle h_CcTree,
+ uint8_t grpId,
+ uint8_t index,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams);
+
+/**************************************************************************//**
+ @Function FM_PCD_MatchTableSet
+
+ @Description This routine should be called for each CC (coarse classification)
+ node. The whole CC tree should be built bottom up so that each
+ node points to already defined nodes.
+
+ @Param[in] h_FmPcd FM PCD module descriptor.
+ @Param[in] p_Param A structure of parameters defining the CC node
+
+ @Return A handle to the initialized object on success; NULL code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init().
+*//***************************************************************************/
+t_Handle FM_PCD_MatchTableSet(t_Handle h_FmPcd, t_FmPcdCcNodeParams *p_Param);
+
+/**************************************************************************//**
+ @Function FM_PCD_MatchTableDelete
+
+ @Description Deleting an built node.
+
+ @Param[in] h_CcNode A handle to a CC node.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init().
+*//***************************************************************************/
+t_Error FM_PCD_MatchTableDelete(t_Handle h_CcNode);
+
+/**************************************************************************//**
+ @Function FM_PCD_MatchTableModifyMissNextEngine
+
+ @Description Modify the Next Engine Parameters of the Miss key case of the node.
+
+ @Param[in] h_CcNode A handle to the node
+ @Param[in] p_FmPcdCcNextEngineParams Parameters for defining next engine
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_MatchTableSet();
+ Not relevant in the case the node is of type 'INDEXED_LOOKUP'.
+ When configuring nextEngine = e_FM_PCD_CC, note that
+ p_FmPcdCcNextEngineParams->ccParams.h_CcNode must be different
+ from the currently changed table.
+
+*//***************************************************************************/
+t_Error FM_PCD_MatchTableModifyMissNextEngine(t_Handle h_CcNode,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams);
+
+/**************************************************************************//**
+ @Function FM_PCD_MatchTableRemoveKey
+
+ @Description Remove the key (including next engine parameters of this key)
+ defined by the index of the relevant node.
+
+ @Param[in] h_CcNode A handle to the node
+ @Param[in] keyIndex Key index for removing
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_MatchTableSet() was called for this
+ node and the nodes that lead to it.
+*//***************************************************************************/
+t_Error FM_PCD_MatchTableRemoveKey(t_Handle h_CcNode, uint16_t keyIndex);
+
+/**************************************************************************//**
+ @Function FM_PCD_MatchTableAddKey
+
+ @Description Add the key (including next engine parameters of this key in the
+ index defined by the keyIndex. Note that 'FM_PCD_LAST_KEY_INDEX'
+ may be used by user that don't care about the position of the
+ key in the table - in that case, the key will be automatically
+ added by the driver in the last available entry.
+
+ @Param[in] h_CcNode A handle to the node
+ @Param[in] keyIndex Key index for adding.
+ @Param[in] keySize Key size of added key
+ @Param[in] p_KeyParams A pointer to the parameters includes
+ new key with Next Engine Parameters
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_MatchTableSet() was called for this
+ node and the nodes that lead to it.
+*//***************************************************************************/
+t_Error FM_PCD_MatchTableAddKey(t_Handle h_CcNode,
+ uint16_t keyIndex,
+ uint8_t keySize,
+ t_FmPcdCcKeyParams *p_KeyParams);
+
+/**************************************************************************//**
+ @Function FM_PCD_MatchTableModifyNextEngine
+
+ @Description Modify the Next Engine Parameters in the relevant key entry of the node.
+
+ @Param[in] h_CcNode A handle to the node
+ @Param[in] keyIndex Key index for Next Engine modifications
+ @Param[in] p_FmPcdCcNextEngineParams Parameters for defining next engine
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_MatchTableSet().
+ When configuring nextEngine = e_FM_PCD_CC, note that
+ p_FmPcdCcNextEngineParams->ccParams.h_CcNode must be different
+ from the currently changed table.
+
+*//***************************************************************************/
+t_Error FM_PCD_MatchTableModifyNextEngine(t_Handle h_CcNode,
+ uint16_t keyIndex,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams);
+
+/**************************************************************************//**
+ @Function FM_PCD_MatchTableModifyKeyAndNextEngine
+
+ @Description Modify the key and Next Engine Parameters of this key in the
+ index defined by the keyIndex.
+
+ @Param[in] h_CcNode A handle to the node
+ @Param[in] keyIndex Key index for adding
+ @Param[in] keySize Key size of added key
+ @Param[in] p_KeyParams A pointer to the parameters includes
+ modified key and modified Next Engine Parameters
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_MatchTableSet() was called for this
+ node and the nodes that lead to it.
+ When configuring nextEngine = e_FM_PCD_CC, note that
+ p_FmPcdCcNextEngineParams->ccParams.h_CcNode must be different
+ from the currently changed table.
+*//***************************************************************************/
+t_Error FM_PCD_MatchTableModifyKeyAndNextEngine(t_Handle h_CcNode,
+ uint16_t keyIndex,
+ uint8_t keySize,
+ t_FmPcdCcKeyParams *p_KeyParams);
+
+/**************************************************************************//**
+ @Function FM_PCD_MatchTableModifyKey
+
+ @Description Modify the key in the index defined by the keyIndex.
+
+ @Param[in] h_CcNode A handle to the node
+ @Param[in] keyIndex Key index for adding
+ @Param[in] keySize Key size of added key
+ @Param[in] p_Key A pointer to the new key
+ @Param[in] p_Mask A pointer to the new mask if relevant,
+ otherwise pointer to NULL
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_MatchTableSet() was called for this
+ node and the nodes that lead to it.
+*//***************************************************************************/
+t_Error FM_PCD_MatchTableModifyKey(t_Handle h_CcNode,
+ uint16_t keyIndex,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t *p_Mask);
+
+/**************************************************************************//**
+ @Function FM_PCD_MatchTableFindNRemoveKey
+
+ @Description Remove the key (including next engine parameters of this key)
+ defined by the key and mask. Note that this routine will search
+ the node to locate the index of the required key (& mask) to remove.
+
+ @Param[in] h_CcNode A handle to the node
+ @Param[in] keySize Key size of the one to remove.
+ @Param[in] p_Key A pointer to the requested key to remove.
+ @Param[in] p_Mask A pointer to the mask if relevant,
+ otherwise pointer to NULL
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_MatchTableSet() was called for this
+ node and the nodes that lead to it.
+*//***************************************************************************/
+t_Error FM_PCD_MatchTableFindNRemoveKey(t_Handle h_CcNode,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t *p_Mask);
+
+/**************************************************************************//**
+ @Function FM_PCD_MatchTableFindNModifyNextEngine
+
+ @Description Modify the Next Engine Parameters in the relevant key entry of
+ the node. Note that this routine will search the node to locate
+ the index of the required key (& mask) to modify.
+
+ @Param[in] h_CcNode A handle to the node
+ @Param[in] keySize Key size of the one to modify.
+ @Param[in] p_Key A pointer to the requested key to modify.
+ @Param[in] p_Mask A pointer to the mask if relevant,
+ otherwise pointer to NULL
+ @Param[in] p_FmPcdCcNextEngineParams Parameters for defining next engine
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_MatchTableSet().
+ When configuring nextEngine = e_FM_PCD_CC, note that
+ p_FmPcdCcNextEngineParams->ccParams.h_CcNode must be different
+ from the currently changed table.
+*//***************************************************************************/
+t_Error FM_PCD_MatchTableFindNModifyNextEngine(t_Handle h_CcNode,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t *p_Mask,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams);
+
+/**************************************************************************//**
+ @Function FM_PCD_MatchTableFindNModifyKeyAndNextEngine
+
+ @Description Modify the key and Next Engine Parameters of this key in the
+ index defined by the keyIndex. Note that this routine will search
+ the node to locate the index of the required key (& mask) to modify.
+
+ @Param[in] h_CcNode A handle to the node
+ @Param[in] keySize Key size of the one to modify.
+ @Param[in] p_Key A pointer to the requested key to modify.
+ @Param[in] p_Mask A pointer to the mask if relevant,
+ otherwise pointer to NULL
+ @Param[in] p_KeyParams A pointer to the parameters includes
+ modified key and modified Next Engine Parameters
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_MatchTableSet() was called for this
+ node and the nodes that lead to it.
+ When configuring nextEngine = e_FM_PCD_CC, note that
+ p_FmPcdCcNextEngineParams->ccParams.h_CcNode must be different
+ from the currently changed table.
+*//***************************************************************************/
+t_Error FM_PCD_MatchTableFindNModifyKeyAndNextEngine(t_Handle h_CcNode,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t *p_Mask,
+ t_FmPcdCcKeyParams *p_KeyParams);
+
+/**************************************************************************//**
+ @Function FM_PCD_MatchTableFindNModifyKey
+
+ @Description Modify the key in the index defined by the keyIndex. Note that
+ this routine will search the node to locate the index of the
+ required key (& mask) to modify.
+
+ @Param[in] h_CcNode A handle to the node
+ @Param[in] keySize Key size of the one to modify.
+ @Param[in] p_Key A pointer to the requested key to modify.
+ @Param[in] p_Mask A pointer to the mask if relevant,
+ otherwise pointer to NULL
+ @Param[in] p_NewKey A pointer to the new key
+ @Param[in] p_NewMask A pointer to the new mask if relevant,
+ otherwise pointer to NULL
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_MatchTableSet() was called for this
+ node and the nodes that lead to it.
+*//***************************************************************************/
+t_Error FM_PCD_MatchTableFindNModifyKey(t_Handle h_CcNode,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t *p_Mask,
+ uint8_t *p_NewKey,
+ uint8_t *p_NewMask);
+
+/**************************************************************************//**
+ @Function FM_PCD_MatchTableGetKeyCounter
+
+ @Description This routine may be used to get a counter of specific key in a CC
+ Node; This counter reflects how many frames passed that were matched
+ this key.
+
+ @Param[in] h_CcNode A handle to the node
+ @Param[in] keyIndex Key index for adding
+
+ @Return The specific key counter.
+
+ @Cautions Allowed only following FM_PCD_MatchTableSet().
+*//***************************************************************************/
+uint32_t FM_PCD_MatchTableGetKeyCounter(t_Handle h_CcNode, uint16_t keyIndex);
+
+/**************************************************************************//**
+ @Function FM_PCD_MatchTableGetKeyStatistics
+
+ @Description This routine may be used to get statistics counters of specific key
+ in a CC Node.
+
+ If 'e_FM_PCD_CC_STATS_MODE_FRAME' and
+ 'e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME' were set for this node,
+ these counters reflect how many frames passed that were matched
+ this key; The total frames count will be returned in the counter
+ of the first range (as only one frame length range was defined).
+ If 'e_FM_PCD_CC_STATS_MODE_RMON' was set for this node, the total
+ frame count will be separated to frame length counters, based on
+ provided frame length ranges.
+
+ @Param[in] h_CcNode A handle to the node
+ @Param[in] keyIndex Key index for adding
+ @Param[out] p_KeyStatistics Key statistics counters
+
+ @Return The specific key statistics.
+
+ @Cautions Allowed only following FM_PCD_MatchTableSet().
+*//***************************************************************************/
+t_Error FM_PCD_MatchTableGetKeyStatistics(t_Handle h_CcNode,
+ uint16_t keyIndex,
+ t_FmPcdCcKeyStatistics *p_KeyStatistics);
+
+/**************************************************************************//**
+ @Function FM_PCD_MatchTableGetMissStatistics
+
+ @Description This routine may be used to get statistics counters of miss entry
+ in a CC Node.
+
+ If 'e_FM_PCD_CC_STATS_MODE_FRAME' and
+ 'e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME' were set for this node,
+ these counters reflect how many frames were not matched to any
+ existing key and therefore passed through the miss entry; The
+ total frames count will be returned in the counter of the
+ first range (as only one frame length range was defined).
+
+ @Param[in] h_CcNode A handle to the node
+ @Param[out] p_MissStatistics Statistics counters for 'miss'
+
+ @Return The statistics for 'miss'.
+
+ @Cautions Allowed only following FM_PCD_MatchTableSet().
+*//***************************************************************************/
+t_Error FM_PCD_MatchTableGetMissStatistics(t_Handle h_CcNode,
+ t_FmPcdCcKeyStatistics *p_MissStatistics);
+
+/**************************************************************************//**
+ @Function FM_PCD_MatchTableFindNGetKeyStatistics
+
+ @Description This routine may be used to get statistics counters of specific key
+ in a CC Node.
+
+ If 'e_FM_PCD_CC_STATS_MODE_FRAME' and
+ 'e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME' were set for this node,
+ these counters reflect how many frames passed that were matched
+ this key; The total frames count will be returned in the counter
+ of the first range (as only one frame length range was defined).
+ If 'e_FM_PCD_CC_STATS_MODE_RMON' was set for this node, the total
+ frame count will be separated to frame length counters, based on
+ provided frame length ranges.
+ Note that this routine will search the node to locate the index
+ of the required key based on received key parameters.
+
+ @Param[in] h_CcNode A handle to the node
+ @Param[in] keySize Size of the requested key
+ @Param[in] p_Key A pointer to the requested key
+ @Param[in] p_Mask A pointer to the mask if relevant,
+ otherwise pointer to NULL
+ @Param[out] p_KeyStatistics Key statistics counters
+
+ @Return The specific key statistics.
+
+ @Cautions Allowed only following FM_PCD_MatchTableSet().
+*//***************************************************************************/
+t_Error FM_PCD_MatchTableFindNGetKeyStatistics(t_Handle h_CcNode,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ uint8_t *p_Mask,
+ t_FmPcdCcKeyStatistics *p_KeyStatistics);
+
+/**************************************************************************//*
+ @Function FM_PCD_MatchTableGetNextEngine
+
+ @Description Gets NextEngine of the relevant keyIndex.
+
+ @Param[in] h_CcNode A handle to the node.
+ @Param[in] keyIndex keyIndex in the relevant node.
+ @Param[out] p_FmPcdCcNextEngineParams here updated nextEngine parameters for
+ the relevant keyIndex of the CC Node
+ received as parameter to this function
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init().
+*//***************************************************************************/
+t_Error FM_PCD_MatchTableGetNextEngine(t_Handle h_CcNode,
+ uint16_t keyIndex,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams);
+
+/**************************************************************************//*
+ @Function FM_PCD_MatchTableGetIndexedHashBucket
+
+ @Description This routine simulates KeyGen operation on the provided key and
+ calculates to which hash bucket it will be mapped.
+
+ @Param[in] h_CcNode A handle to the node.
+ @Param[in] kgKeySize Key size as it was configured in the KG
+ scheme that leads to this hash.
+ @Param[in] p_KgKey Pointer to the key; must be like the key
+ that the KG is generated, i.e. the same
+ extraction and with mask if exist.
+ @Param[in] kgHashShift Hash-shift as it was configured in the KG
+ scheme that leads to this hash.
+ @Param[out] p_CcNodeBucketHandle Pointer to the bucket of the provided key.
+ @Param[out] p_BucketIndex Index to the bucket of the provided key
+ @Param[out] p_LastIndex Pointer to last index in the bucket of the
+ provided key.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_HashTableSet()
+*//***************************************************************************/
+t_Error FM_PCD_MatchTableGetIndexedHashBucket(t_Handle h_CcNode,
+ uint8_t kgKeySize,
+ uint8_t *p_KgKey,
+ uint8_t kgHashShift,
+ t_Handle *p_CcNodeBucketHandle,
+ uint8_t *p_BucketIndex,
+ uint16_t *p_LastIndex);
+
+/**************************************************************************//**
+ @Function FM_PCD_HashTableSet
+
+ @Description This routine initializes a hash table structure.
+ KeyGen hash result determines the hash bucket.
+ Next, KeyGen key is compared against all keys of this
+ bucket (exact match).
+ Number of sets (number of buckets) of the hash equals to the
+ number of 1-s in 'hashResMask' in the provided parameters.
+ Number of hash table ways is then calculated by dividing
+ 'maxNumOfKeys' equally between the hash sets. This is the maximal
+ number of keys that a hash bucket may hold.
+ The hash table is initialized empty and keys may be
+ added to it following the initialization. Keys masks are not
+ supported in current hash table implementation.
+ The initialized hash table can be integrated as a node in a
+ CC tree.
+
+ @Param[in] h_FmPcd FM PCD module descriptor.
+ @Param[in] p_Param A structure of parameters defining the hash table
+
+ @Return A handle to the initialized object on success; NULL code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init().
+*//***************************************************************************/
+t_Handle FM_PCD_HashTableSet(t_Handle h_FmPcd, t_FmPcdHashTableParams *p_Param);
+
+/**************************************************************************//**
+ @Function FM_PCD_HashTableDelete
+
+ @Description This routine deletes the provided hash table and released all
+ its allocated resources.
+
+ @Param[in] h_HashTbl A handle to a hash table
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_HashTableSet().
+*//***************************************************************************/
+t_Error FM_PCD_HashTableDelete(t_Handle h_HashTbl);
+
+/**************************************************************************//**
+ @Function FM_PCD_HashTableAddKey
+
+ @Description This routine adds the provided key (including next engine
+ parameters of this key) to the hash table.
+ The key is added as the last key of the bucket that it is
+ mapped to.
+
+ @Param[in] h_HashTbl A handle to a hash table
+ @Param[in] keySize Key size of added key
+ @Param[in] p_KeyParams A pointer to the parameters includes
+ new key with next engine parameters; The pointer
+ to the key mask must be NULL, as masks are not
+ supported in hash table implementation.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_HashTableSet().
+*//***************************************************************************/
+t_Error FM_PCD_HashTableAddKey(t_Handle h_HashTbl,
+ uint8_t keySize,
+ t_FmPcdCcKeyParams *p_KeyParams);
+
+/**************************************************************************//**
+ @Function FM_PCD_HashTableRemoveKey
+
+ @Description This routine removes the requested key (including next engine
+ parameters of this key) from the hash table.
+
+ @Param[in] h_HashTbl A handle to a hash table
+ @Param[in] keySize Key size of the one to remove.
+ @Param[in] p_Key A pointer to the requested key to remove.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_HashTableSet().
+*//***************************************************************************/
+t_Error FM_PCD_HashTableRemoveKey(t_Handle h_HashTbl,
+ uint8_t keySize,
+ uint8_t *p_Key);
+
+/**************************************************************************//**
+ @Function FM_PCD_HashTableModifyNextEngine
+
+ @Description This routine modifies the next engine for the provided key. The
+ key should be previously added to the hash table.
+
+ @Param[in] h_HashTbl A handle to a hash table
+ @Param[in] keySize Key size of the key to modify.
+ @Param[in] p_Key A pointer to the requested key to modify.
+ @Param[in] p_FmPcdCcNextEngineParams A structure for defining new next engine
+ parameters.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_HashTableSet().
+ When configuring nextEngine = e_FM_PCD_CC, note that
+ p_FmPcdCcNextEngineParams->ccParams.h_CcNode must be different
+ from the currently changed table.
+*//***************************************************************************/
+t_Error FM_PCD_HashTableModifyNextEngine(t_Handle h_HashTbl,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams);
+
+/**************************************************************************//**
+ @Function FM_PCD_HashTableModifyMissNextEngine
+
+ @Description This routine modifies the next engine on key match miss.
+
+ @Param[in] h_HashTbl A handle to a hash table
+ @Param[in] p_FmPcdCcNextEngineParams A structure for defining new next engine
+ parameters.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_HashTableSet().
+ When configuring nextEngine = e_FM_PCD_CC, note that
+ p_FmPcdCcNextEngineParams->ccParams.h_CcNode must be different
+ from the currently changed table.
+*//***************************************************************************/
+t_Error FM_PCD_HashTableModifyMissNextEngine(t_Handle h_HashTbl,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams);
+
+/**************************************************************************//*
+ @Function FM_PCD_HashTableGetMissNextEngine
+
+ @Description Gets NextEngine in case of key match miss.
+
+ @Param[in] h_HashTbl A handle to a hash table
+ @Param[out] p_FmPcdCcNextEngineParams Next engine parameters for the specified
+ hash table.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_HashTableSet().
+*//***************************************************************************/
+t_Error FM_PCD_HashTableGetMissNextEngine(t_Handle h_HashTbl,
+ t_FmPcdCcNextEngineParams *p_FmPcdCcNextEngineParams);
+
+/**************************************************************************//**
+ @Function FM_PCD_HashTableFindNGetKeyStatistics
+
+ @Description This routine may be used to get statistics counters of specific key
+ in a hash table.
+
+ If 'e_FM_PCD_CC_STATS_MODE_FRAME' and
+ 'e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME' were set for this node,
+ these counters reflect how many frames passed that were matched
+ this key; The total frames count will be returned in the counter
+ of the first range (as only one frame length range was defined).
+ If 'e_FM_PCD_CC_STATS_MODE_RMON' was set for this node, the total
+ frame count will be separated to frame length counters, based on
+ provided frame length ranges.
+ Note that this routine will identify the bucket of this key in
+ the hash table and will search the bucket to locate the index
+ of the required key based on received key parameters.
+
+ @Param[in] h_HashTbl A handle to a hash table
+ @Param[in] keySize Size of the requested key
+ @Param[in] p_Key A pointer to the requested key
+ @Param[out] p_KeyStatistics Key statistics counters
+
+ @Return The specific key statistics.
+
+ @Cautions Allowed only following FM_PCD_HashTableSet().
+*//***************************************************************************/
+t_Error FM_PCD_HashTableFindNGetKeyStatistics(t_Handle h_HashTbl,
+ uint8_t keySize,
+ uint8_t *p_Key,
+ t_FmPcdCcKeyStatistics *p_KeyStatistics);
+
+/**************************************************************************//**
+ @Function FM_PCD_HashTableGetMissStatistics
+
+ @Description This routine may be used to get statistics counters of 'miss'
+ entry of the a hash table.
+
+ If 'e_FM_PCD_CC_STATS_MODE_FRAME' and
+ 'e_FM_PCD_CC_STATS_MODE_BYTE_AND_FRAME' were set for this node,
+ these counters reflect how many frames were not matched to any
+ existing key and therefore passed through the miss entry;
+
+ @Param[in] h_HashTbl A handle to a hash table
+ @Param[out] p_MissStatistics Statistics counters for 'miss'
+
+ @Return The statistics for 'miss'.
+
+ @Cautions Allowed only following FM_PCD_HashTableSet().
+*//***************************************************************************/
+t_Error FM_PCD_HashTableGetMissStatistics(t_Handle h_HashTbl,
+ t_FmPcdCcKeyStatistics *p_MissStatistics);
+
+/**************************************************************************//**
+ @Function FM_PCD_ManipNodeSet
+
+ @Description This routine should be called for defining a manipulation
+ node. A manipulation node must be defined before the CC node
+ that precedes it.
+
+ @Param[in] h_FmPcd FM PCD module descriptor.
+ @Param[in] p_FmPcdManipParams A structure of parameters defining the manipulation
+
+ @Return A handle to the initialized object on success; NULL code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init().
+*//***************************************************************************/
+t_Handle FM_PCD_ManipNodeSet(t_Handle h_FmPcd, t_FmPcdManipParams *p_FmPcdManipParams);
+
+/**************************************************************************//**
+ @Function FM_PCD_ManipNodeDelete
+
+ @Description Delete an existing manipulation node.
+
+ @Param[in] h_ManipNode A handle to a manipulation node.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_ManipNodeSet().
+*//***************************************************************************/
+t_Error FM_PCD_ManipNodeDelete(t_Handle h_ManipNode);
+
+/**************************************************************************//**
+ @Function FM_PCD_ManipGetStatistics
+
+ @Description Retrieve the manipulation statistics.
+
+ @Param[in] h_ManipNode A handle to a manipulation node.
+ @Param[out] p_FmPcdManipStats A structure for retrieving the manipulation statistics
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_ManipNodeSet().
+*//***************************************************************************/
+t_Error FM_PCD_ManipGetStatistics(t_Handle h_ManipNode, t_FmPcdManipStats *p_FmPcdManipStats);
+
+/**************************************************************************//**
+ @Function FM_PCD_ManipNodeReplace
+
+ @Description Change existing manipulation node to be according to new requirement.
+
+ @Param[in] h_ManipNode A handle to a manipulation node.
+ @Param[out] p_ManipParams A structure of parameters defining the change requirement
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_ManipNodeSet().
+*//***************************************************************************/
+t_Error FM_PCD_ManipNodeReplace(t_Handle h_ManipNode, t_FmPcdManipParams *p_ManipParams);
+
+#if (DPAA_VERSION >= 11)
+/**************************************************************************//**
+ @Function FM_PCD_FrmReplicSetGroup
+
+ @Description Initialize a Frame Replicator group.
+
+ @Param[in] h_FmPcd FM PCD module descriptor.
+ @Param[in] p_FrmReplicGroupParam A structure of parameters for the initialization of
+ the frame replicator group.
+
+ @Return A handle to the initialized object on success; NULL code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init().
+*//***************************************************************************/
+t_Handle FM_PCD_FrmReplicSetGroup(t_Handle h_FmPcd, t_FmPcdFrmReplicGroupParams *p_FrmReplicGroupParam);
+
+/**************************************************************************//**
+ @Function FM_PCD_FrmReplicDeleteGroup
+
+ @Description Delete a Frame Replicator group.
+
+ @Param[in] h_FrmReplicGroup A handle to the frame replicator group.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_FrmReplicSetGroup().
+*//***************************************************************************/
+t_Error FM_PCD_FrmReplicDeleteGroup(t_Handle h_FrmReplicGroup);
+
+/**************************************************************************//**
+ @Function FM_PCD_FrmReplicAddMember
+
+ @Description Add the member in the index defined by the memberIndex.
+
+ @Param[in] h_FrmReplicGroup A handle to the frame replicator group.
+ @Param[in] memberIndex member index for adding.
+ @Param[in] p_MemberParams A pointer to the new member parameters.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_FrmReplicSetGroup() of this group.
+*//***************************************************************************/
+t_Error FM_PCD_FrmReplicAddMember(t_Handle h_FrmReplicGroup,
+ uint16_t memberIndex,
+ t_FmPcdCcNextEngineParams *p_MemberParams);
+
+/**************************************************************************//**
+ @Function FM_PCD_FrmReplicRemoveMember
+
+ @Description Remove the member defined by the index from the relevant group.
+
+ @Param[in] h_FrmReplicGroup A handle to the frame replicator group.
+ @Param[in] memberIndex member index for removing.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PCD_FrmReplicSetGroup() of this group.
+*//***************************************************************************/
+t_Error FM_PCD_FrmReplicRemoveMember(t_Handle h_FrmReplicGroup,
+ uint16_t memberIndex);
+#endif /* (DPAA_VERSION >= 11) */
+
+#ifdef FM_CAPWAP_SUPPORT
+/**************************************************************************//**
+ @Function FM_PCD_StatisticsSetNode
+
+ @Description This routine should be called for defining a statistics node.
+
+ @Param[in] h_FmPcd FM PCD module descriptor.
+ @Param[in] p_FmPcdstatsParams A structure of parameters defining the statistics
+
+ @Return A handle to the initialized object on success; NULL code otherwise.
+
+ @Cautions Allowed only following FM_PCD_Init().
+*//***************************************************************************/
+t_Handle FM_PCD_StatisticsSetNode(t_Handle h_FmPcd, t_FmPcdStatsParams *p_FmPcdstatsParams);
+#endif /* FM_CAPWAP_SUPPORT */
+
+/** @} */ /* end of FM_PCD_Runtime_build_grp group */
+/** @} */ /* end of FM_PCD_Runtime_grp group */
+/** @} */ /* end of FM_PCD_grp group */
+/** @} */ /* end of FM_grp group */
+
+
+#ifdef NCSW_BACKWARD_COMPATIBLE_API
+#define FM_PCD_MAX_NUM_OF_INTERCHANGABLE_HDRS FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS
+#define e_FM_PCD_MANIP_ONE_WAYS_HASH e_FM_PCD_MANIP_ONE_WAY_HASH
+#define e_FM_PCD_MANIP_TOW_WAYS_HASH e_FM_PCD_MANIP_TWO_WAYS_HASH
+
+#define e_FM_PCD_MANIP_FRAGMENT_PACKECT e_FM_PCD_MANIP_FRAGMENT_PACKET /* Feb13 */
+
+#define FM_PCD_SetNetEnvCharacteristics(_pcd, _params) \
+ FM_PCD_NetEnvCharacteristicsSet(_pcd, _params)
+#define FM_PCD_KgSetScheme(_pcd, _params) FM_PCD_KgSchemeSet(_pcd, _params)
+#define FM_PCD_CcBuildTree(_pcd, _params) FM_PCD_CcRootBuild(_pcd, _params)
+#define FM_PCD_CcSetNode(_pcd, _params) FM_PCD_MatchTableSet(_pcd, _params)
+#define FM_PCD_PlcrSetProfile(_pcd, _params) FM_PCD_PlcrProfileSet(_pcd, _params)
+#define FM_PCD_ManipSetNode(_pcd, _params) FM_PCD_ManipNodeSet(_pcd, _params)
+
+#define FM_PCD_DeleteNetEnvCharacteristics(_pcd, ...) \
+ FM_PCD_NetEnvCharacteristicsDelete(__VA_ARGS__)
+#define FM_PCD_KgDeleteScheme(_pcd, ...) \
+ FM_PCD_KgSchemeDelete(__VA_ARGS__)
+#define FM_PCD_KgGetSchemeCounter(_pcd, ...) \
+ FM_PCD_KgSchemeGetCounter(__VA_ARGS__)
+#define FM_PCD_KgSetSchemeCounter(_pcd, ...) \
+ FM_PCD_KgSchemeSetCounter(__VA_ARGS__)
+#define FM_PCD_PlcrDeleteProfile(_pcd, ...) \
+ FM_PCD_PlcrProfileDelete(__VA_ARGS__)
+#define FM_PCD_PlcrGetProfileCounter(_pcd, ...) \
+ FM_PCD_PlcrProfileGetCounter(__VA_ARGS__)
+#define FM_PCD_PlcrSetProfileCounter(_pcd, ...) \
+ FM_PCD_PlcrProfileSetCounter(__VA_ARGS__)
+#define FM_PCD_CcDeleteTree(_pcd, ...) \
+ FM_PCD_CcRootDelete(__VA_ARGS__)
+#define FM_PCD_CcTreeModifyNextEngine(_pcd, ...) \
+ FM_PCD_CcRootModifyNextEngine(__VA_ARGS__)
+#define FM_PCD_CcDeleteNode(_pcd, ...) \
+ FM_PCD_MatchTableDelete(__VA_ARGS__)
+#define FM_PCD_CcNodeModifyMissNextEngine(_pcd, ...) \
+ FM_PCD_MatchTableModifyMissNextEngine(__VA_ARGS__)
+#define FM_PCD_CcNodeRemoveKey(_pcd, ...) \
+ FM_PCD_MatchTableRemoveKey(__VA_ARGS__)
+#define FM_PCD_CcNodeAddKey(_pcd, ...) \
+ FM_PCD_MatchTableAddKey(__VA_ARGS__)
+#define FM_PCD_CcNodeModifyNextEngine(_pcd, ...) \
+ FM_PCD_MatchTableModifyNextEngine(__VA_ARGS__)
+#define FM_PCD_CcNodeModifyKeyAndNextEngine(_pcd, ...) \
+ FM_PCD_MatchTableModifyKeyAndNextEngine(__VA_ARGS__)
+#define FM_PCD_CcNodeModifyKey(_pcd, ...) \
+ FM_PCD_MatchTableModifyKey(__VA_ARGS__)
+#define FM_PCD_CcNodeFindNRemoveKey(_pcd, ...) \
+ FM_PCD_MatchTableFindNRemoveKey(__VA_ARGS__)
+#define FM_PCD_CcNodeFindNModifyNextEngine(_pcd, ...) \
+ FM_PCD_MatchTableFindNModifyNextEngine(__VA_ARGS__)
+#define FM_PCD_CcNodeFindNModifyKeyAndNextEngine(_pcd, ...) \
+ FM_PCD_MatchTableFindNModifyKeyAndNextEngine(__VA_ARGS__)
+#define FM_PCD_CcNodeFindNModifyKey(_pcd, ...) \
+ FM_PCD_MatchTableFindNModifyKey(__VA_ARGS__)
+#define FM_PCD_CcIndexedHashNodeGetBucket(_pcd, ...) \
+ FM_PCD_MatchTableGetIndexedHashBucket(__VA_ARGS__)
+#define FM_PCD_CcNodeGetNextEngine(_pcd, ...) \
+ FM_PCD_MatchTableGetNextEngine(__VA_ARGS__)
+#define FM_PCD_CcNodeGetKeyCounter(_pcd, ...) \
+ FM_PCD_MatchTableGetKeyCounter(__VA_ARGS__)
+#define FM_PCD_ManipDeleteNode(_pcd, ...) \
+ FM_PCD_ManipNodeDelete(__VA_ARGS__)
+#endif /* NCSW_BACKWARD_COMPATIBLE_API */
+
+
+#endif /* __FM_PCD_EXT */
diff --git a/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_port_ext.h b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_port_ext.h
new file mode 100644
index 0000000..3a62b8d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_port_ext.h
@@ -0,0 +1,2567 @@
+/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File fm_port_ext.h
+
+ @Description FM-Port Application Programming Interface.
+*//***************************************************************************/
+#ifndef __FM_PORT_EXT
+#define __FM_PORT_EXT
+
+#include "error_ext.h"
+#include "std_ext.h"
+#include "fm_pcd_ext.h"
+#include "fm_ext.h"
+#include "net_ext.h"
+
+/**************************************************************************//**
+
+ @Group FM_grp Frame Manager API
+
+ @Description FM API functions, definitions and enums
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group FM_PORT_grp FM Port
+
+ @Description FM Port API
+
+ The FM uses a general module called "port" to represent a Tx port
+ (MAC), an Rx port (MAC) or Offline Parsing port.
+ The number of ports in an FM varies between SOCs.
+ The SW driver manages these ports as sub-modules of the FM, i.e.
+ after an FM is initialized, its ports may be initialized and
+ operated upon.
+
+ The port is initialized aware of its type, but other functions on
+ a port may be indifferent to its type. When necessary, the driver
+ verifies coherence and returns error if applicable.
+
+ On initialization, user specifies the port type and it's index
+ (relative to the port's type) - always starting at 0.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Description An enum for defining port PCD modes.
+ This enum defines the superset of PCD engines support - i.e. not
+ all engines have to be used, but all have to be enabled. The real
+ flow of a specific frame depends on the PCD configuration and the
+ frame headers and payload.
+ Note: the first engine and the first engine after the parser (if
+ exists) should be in order, the order is important as it will
+ define the flow of the port. However, as for the rest engines
+ (the ones that follows), the order is not important anymore as
+ it is defined by the PCD graph itself.
+*//***************************************************************************/
+typedef enum e_FmPortPcdSupport {
+ e_FM_PORT_PCD_SUPPORT_NONE = 0 /**< BMI to BMI, PCD is not used */
+ , e_FM_PORT_PCD_SUPPORT_PRS_ONLY /**< Use only Parser */
+ , e_FM_PORT_PCD_SUPPORT_PLCR_ONLY /**< Use only Policer */
+ , e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR /**< Use Parser and Policer */
+ , e_FM_PORT_PCD_SUPPORT_PRS_AND_KG /**< Use Parser and Keygen */
+ , e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC /**< Use Parser, Keygen and Coarse Classification */
+ , e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_CC_AND_PLCR
+ /**< Use all PCD engines */
+ , e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR /**< Use Parser, Keygen and Policer */
+ , e_FM_PORT_PCD_SUPPORT_PRS_AND_CC /**< Use Parser and Coarse Classification */
+ , e_FM_PORT_PCD_SUPPORT_PRS_AND_CC_AND_PLCR /**< Use Parser and Coarse Classification and Policer */
+#ifdef FM_CAPWAP_SUPPORT
+ , e_FM_PORT_PCD_SUPPORT_CC_ONLY /**< Use only Coarse Classification */
+ , e_FM_PORT_PCD_SUPPORT_CC_AND_KG /**< Use Coarse Classification,and Keygen */
+ , e_FM_PORT_PCD_SUPPORT_CC_AND_KG_AND_PLCR /**< Use Coarse Classification, Keygen and Policer */
+#endif /* FM_CAPWAP_SUPPORT */
+} e_FmPortPcdSupport;
+
+/**************************************************************************//**
+ @Description Port interrupts
+*//***************************************************************************/
+typedef enum e_FmPortExceptions {
+ e_FM_PORT_EXCEPTION_IM_BUSY /**< Independent-Mode Rx-BUSY */
+} e_FmPortExceptions;
+
+
+/**************************************************************************//**
+ @Collection General FM Port defines
+*//***************************************************************************/
+#define FM_PORT_PRS_RESULT_NUM_OF_WORDS 8 /**< Number of 4 bytes words in parser result */
+/* @} */
+
+/**************************************************************************//**
+ @Collection FM Frame error
+*//***************************************************************************/
+typedef uint32_t fmPortFrameErrSelect_t; /**< typedef for defining Frame Descriptor errors */
+
+#define FM_PORT_FRM_ERR_UNSUPPORTED_FORMAT FM_FD_ERR_UNSUPPORTED_FORMAT /**< Not for Rx-Port! Unsupported Format */
+#define FM_PORT_FRM_ERR_LENGTH FM_FD_ERR_LENGTH /**< Not for Rx-Port! Length Error */
+#define FM_PORT_FRM_ERR_DMA FM_FD_ERR_DMA /**< DMA Data error */
+#define FM_PORT_FRM_ERR_NON_FM FM_FD_RX_STATUS_ERR_NON_FM /**< non Frame-Manager error; probably come from SEC that
+ was chained to FM */
+
+#define FM_PORT_FRM_ERR_IPRE (FM_FD_ERR_IPR & ~FM_FD_IPR) /**< IPR error */
+#define FM_PORT_FRM_ERR_IPR_NCSP (FM_FD_ERR_IPR_NCSP & ~FM_FD_IPR) /**< IPR non-consistent-sp */
+
+#define FM_PORT_FRM_ERR_IPFE 0 /**< Obsolete; will be removed in the future */
+
+#ifdef FM_CAPWAP_SUPPORT
+#define FM_PORT_FRM_ERR_CRE FM_FD_ERR_CRE
+#define FM_PORT_FRM_ERR_CHE FM_FD_ERR_CHE
+#endif /* FM_CAPWAP_SUPPORT */
+
+#define FM_PORT_FRM_ERR_PHYSICAL FM_FD_ERR_PHYSICAL /**< Rx FIFO overflow, FCS error, code error, running disparity
+ error (SGMII and TBI modes), FIFO parity error. PHY
+ Sequence error, PHY error control character detected. */
+#define FM_PORT_FRM_ERR_SIZE FM_FD_ERR_SIZE /**< Frame too long OR Frame size exceeds max_length_frame */
+#define FM_PORT_FRM_ERR_CLS_DISCARD FM_FD_ERR_CLS_DISCARD /**< indicates a classifier "drop" operation */
+#define FM_PORT_FRM_ERR_EXTRACTION FM_FD_ERR_EXTRACTION /**< Extract Out of Frame */
+#define FM_PORT_FRM_ERR_NO_SCHEME FM_FD_ERR_NO_SCHEME /**< No Scheme Selected */
+#define FM_PORT_FRM_ERR_KEYSIZE_OVERFLOW FM_FD_ERR_KEYSIZE_OVERFLOW /**< Keysize Overflow */
+#define FM_PORT_FRM_ERR_COLOR_RED FM_FD_ERR_COLOR_RED /**< Frame color is red */
+#define FM_PORT_FRM_ERR_COLOR_YELLOW FM_FD_ERR_COLOR_YELLOW /**< Frame color is yellow */
+#define FM_PORT_FRM_ERR_ILL_PLCR FM_FD_ERR_ILL_PLCR /**< Illegal Policer Profile selected */
+#define FM_PORT_FRM_ERR_PLCR_FRAME_LEN FM_FD_ERR_PLCR_FRAME_LEN /**< Policer frame length error */
+#define FM_PORT_FRM_ERR_PRS_TIMEOUT FM_FD_ERR_PRS_TIMEOUT /**< Parser Time out Exceed */
+#define FM_PORT_FRM_ERR_PRS_ILL_INSTRUCT FM_FD_ERR_PRS_ILL_INSTRUCT /**< Invalid Soft Parser instruction */
+#define FM_PORT_FRM_ERR_PRS_HDR_ERR FM_FD_ERR_PRS_HDR_ERR /**< Header error was identified during parsing */
+#define FM_PORT_FRM_ERR_BLOCK_LIMIT_EXCEEDED FM_FD_ERR_BLOCK_LIMIT_EXCEEDED /**< Frame parsed beyind 256 first bytes */
+#define FM_PORT_FRM_ERR_PROCESS_TIMEOUT 0x00000001 /**< FPM Frame Processing Timeout Exceeded */
+/* @} */
+
+
+
+/**************************************************************************//**
+ @Group FM_PORT_init_grp FM Port Initialization Unit
+
+ @Description FM Port Initialization Unit
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Description Exceptions user callback routine, will be called upon an
+ exception passing the exception identification.
+
+ @Param[in] h_App - User's application descriptor.
+ @Param[in] exception - The exception.
+ *//***************************************************************************/
+typedef void (t_FmPortExceptionCallback) (t_Handle h_App, e_FmPortExceptions exception);
+
+/**************************************************************************//**
+ @Description User callback function called by driver with received data.
+
+ User provides this function. Driver invokes it.
+
+ @Param[in] h_App Application's handle originally specified to
+ the API Config function
+ @Param[in] p_Data A pointer to data received
+ @Param[in] length length of received data
+ @Param[in] status receive status and errors
+ @Param[in] position position of buffer in frame
+ @Param[in] h_BufContext A handle of the user acossiated with this buffer
+
+ @Retval e_RX_STORE_RESPONSE_CONTINUE - order the driver to continue Rx
+ operation for all ready data.
+ @Retval e_RX_STORE_RESPONSE_PAUSE - order the driver to stop Rx operation.
+*//***************************************************************************/
+typedef e_RxStoreResponse (t_FmPortImRxStoreCallback) (t_Handle h_App,
+ uint8_t *p_Data,
+ uint16_t length,
+ uint16_t status,
+ uint8_t position,
+ t_Handle h_BufContext);
+
+/**************************************************************************//**
+ @Description User callback function called by driver when transmit completed.
+
+ User provides this function. Driver invokes it.
+
+ @Param[in] h_App Application's handle originally specified to
+ the API Config function
+ @Param[in] p_Data A pointer to data received
+ @Param[in] status transmit status and errors
+ @Param[in] lastBuffer is last buffer in frame
+ @Param[in] h_BufContext A handle of the user acossiated with this buffer
+ *//***************************************************************************/
+typedef void (t_FmPortImTxConfCallback) (t_Handle h_App,
+ uint8_t *p_Data,
+ uint16_t status,
+ t_Handle h_BufContext);
+
+/**************************************************************************//**
+ @Description A structure for additional Rx port parameters
+*//***************************************************************************/
+typedef struct t_FmPortRxParams {
+ uint32_t errFqid; /**< Error Queue Id. */
+ uint32_t dfltFqid; /**< Default Queue Id. */
+ uint16_t liodnOffset; /**< Port's LIODN offset. */
+ t_FmExtPools extBufPools; /**< Which external buffer pools are used
+ (up to FM_PORT_MAX_NUM_OF_EXT_POOLS), and their sizes. */
+} t_FmPortRxParams;
+
+/**************************************************************************//**
+ @Description A structure for additional non-Rx port parameters
+*//***************************************************************************/
+typedef struct t_FmPortNonRxParams {
+ uint32_t errFqid; /**< Error Queue Id. */
+ uint32_t dfltFqid; /**< For Tx - Default Confirmation queue,
+ 0 means no Tx confirmation for processed
+ frames. For OP port - default Rx queue. */
+ uint32_t qmChannel; /**< QM-channel dedicated to this port; will be used
+ by the FM for dequeue. */
+} t_FmPortNonRxParams;
+
+/**************************************************************************//**
+ @Description A structure for additional Rx port parameters
+*//***************************************************************************/
+typedef struct t_FmPortImRxTxParams {
+ t_Handle h_FmMuram; /**< A handle of the FM-MURAM partition */
+ uint16_t liodnOffset; /**< For Rx ports only. Port's LIODN Offset. */
+ uint8_t dataMemId; /**< Memory partition ID for data buffers */
+ uint32_t dataMemAttributes; /**< Memory attributes for data buffers */
+ t_BufferPoolInfo rxPoolParams; /**< For Rx ports only. */
+ t_FmPortImRxStoreCallback *f_RxStore; /**< For Rx ports only. */
+ t_FmPortImTxConfCallback *f_TxConf; /**< For Tx ports only. */
+} t_FmPortImRxTxParams;
+
+/**************************************************************************//**
+ @Description A union for additional parameters depending on port type
+*//***************************************************************************/
+typedef union u_FmPortSpecificParams {
+ t_FmPortImRxTxParams imRxTxParams; /**< Rx/Tx Independent-Mode port parameter structure */
+ t_FmPortRxParams rxParams; /**< Rx port parameters structure */
+ t_FmPortNonRxParams nonRxParams; /**< Non-Rx port parameters structure */
+} u_FmPortSpecificParams;
+
+/**************************************************************************//**
+ @Description A structure representing FM initialization parameters
+*//***************************************************************************/
+typedef struct t_FmPortParams {
+ uintptr_t baseAddr; /**< Virtual Address of memory mapped FM Port registers.*/
+ t_Handle h_Fm; /**< A handle to the FM object this port related to */
+ e_FmPortType portType; /**< Port type */
+ uint8_t portId; /**< Port Id - relative to type;
+ NOTE: When configuring Offline Parsing port for
+ FMANv3 devices (DPAA_VERSION 11 and higher),
+ it is highly recommended NOT to use portId=0 due to lack
+ of HW resources on portId=0. */
+ bool independentModeEnable;
+ /**< This port is Independent-Mode - Used for Rx/Tx ports only! */
+ uint16_t liodnBase; /**< Irrelevant for P4080 rev 1. LIODN base for this port, to be
+ used together with LIODN offset. */
+ u_FmPortSpecificParams specificParams; /**< Additional parameters depending on port
+ type. */
+
+ t_FmPortExceptionCallback *f_Exception; /**< Relevant for IM only Callback routine to be called on BUSY exception */
+ t_Handle h_App; /**< A handle to an application layer object; This handle will
+ be passed by the driver upon calling the above callbacks */
+} t_FmPortParams;
+
+
+/**************************************************************************//**
+ @Function FM_PORT_Config
+
+ @Description Creates a descriptor for the FM PORT module.
+
+ The routine returns a handle (descriptor) to the FM PORT object.
+ This descriptor must be passed as first parameter to all other
+ FM PORT function calls.
+
+ No actual initialization or configuration of FM hardware is
+ done by this routine.
+
+ @Param[in] p_FmPortParams - Pointer to data structure of parameters
+
+ @Retval Handle to FM object, or NULL for Failure.
+*//***************************************************************************/
+t_Handle FM_PORT_Config(t_FmPortParams *p_FmPortParams);
+
+/**************************************************************************//**
+ @Function FM_PORT_Init
+
+ @Description Initializes the FM PORT module by defining the software structure
+ and configuring the hardware registers.
+
+ @Param[in] h_FmPort - FM PORT module descriptor
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_PORT_Init(t_Handle h_FmPort);
+
+/**************************************************************************//**
+ @Function FM_PORT_Free
+
+ @Description Frees all resources that were assigned to FM PORT module.
+
+ Calling this routine invalidates the descriptor.
+
+ @Param[in] h_FmPort - FM PORT module descriptor
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_PORT_Free(t_Handle h_FmPort);
+
+
+/**************************************************************************//**
+ @Group FM_PORT_advanced_init_grp FM Port Advanced Configuration Unit
+
+ @Description Configuration functions used to change default values.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Description enum for defining QM frame dequeue
+*//***************************************************************************/
+typedef enum e_FmPortDeqType {
+ e_FM_PORT_DEQ_TYPE1, /**< Dequeue from the SP channel - with priority precedence,
+ and Intra-Class Scheduling respected. */
+ e_FM_PORT_DEQ_TYPE2, /**< Dequeue from the SP channel - with active FQ precedence,
+ and Intra-Class Scheduling respected. */
+ e_FM_PORT_DEQ_TYPE3 /**< Dequeue from the SP channel - with active FQ precedence,
+ and override Intra-Class Scheduling */
+} e_FmPortDeqType;
+
+/**************************************************************************//**
+ @Description enum for defining QM frame dequeue
+*//***************************************************************************/
+typedef enum e_FmPortDeqPrefetchOption {
+ e_FM_PORT_DEQ_NO_PREFETCH, /**< QMI preforms a dequeue action for a single frame
+ only when a dedicated portID Tnum is waiting. */
+ e_FM_PORT_DEQ_PARTIAL_PREFETCH, /**< QMI preforms a dequeue action for 3 frames when
+ one dedicated portId tnum is waiting. */
+ e_FM_PORT_DEQ_FULL_PREFETCH /**< QMI preforms a dequeue action for 3 frames when
+ no dedicated portId tnums are waiting. */
+
+} e_FmPortDeqPrefetchOption;
+
+/**************************************************************************//**
+ @Description enum for defining port default color
+*//***************************************************************************/
+typedef enum e_FmPortColor {
+ e_FM_PORT_COLOR_GREEN, /**< Default port color is green */
+ e_FM_PORT_COLOR_YELLOW, /**< Default port color is yellow */
+ e_FM_PORT_COLOR_RED, /**< Default port color is red */
+ e_FM_PORT_COLOR_OVERRIDE /**< Ignore color */
+} e_FmPortColor;
+
+/**************************************************************************//**
+ @Description A structure for defining Dual Tx rate limiting scale
+*//***************************************************************************/
+typedef enum e_FmPortDualRateLimiterScaleDown {
+ e_FM_PORT_DUAL_RATE_LIMITER_NONE = 0, /**< Use only single rate limiter */
+ e_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_2, /**< Divide high rate limiter by 2 */
+ e_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_4, /**< Divide high rate limiter by 4 */
+ e_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_8 /**< Divide high rate limiter by 8 */
+} e_FmPortDualRateLimiterScaleDown;
+
+
+/**************************************************************************//**
+ @Description A structure for defining FM port resources
+*//***************************************************************************/
+typedef struct t_FmPortRsrc {
+ uint32_t num; /**< Committed required resource */
+ uint32_t extra; /**< Extra (not committed) required resource */
+} t_FmPortRsrc;
+
+/**************************************************************************//**
+ @Description A structure for defining observed pool depletion
+*//***************************************************************************/
+typedef struct t_FmPortObservedBufPoolDepletion {
+ t_FmBufPoolDepletion poolDepletionParams;/**< parameters to define pool depletion */
+ t_FmExtPools poolsParams; /**< Which external buffer pools are observed
+ (up to FM_PORT_MAX_NUM_OF_OBSERVED_EXT_POOLS),
+ and their sizes. */
+} t_FmPortObservedBufPoolDepletion;
+
+/**************************************************************************//**
+ @Description A structure for defining Tx rate limiting
+*//***************************************************************************/
+typedef struct t_FmPortRateLimit {
+ uint16_t maxBurstSize; /**< in KBytes for Tx ports, in frames
+ for OP ports. (note that
+ for early chips burst size is
+ rounded up to a multiply of 1000 frames).*/
+ uint32_t rateLimit; /**< in Kb/sec for Tx ports, in frame/sec for
+ OP ports. Rate limit refers to
+ data rate (rather than line rate). */
+ e_FmPortDualRateLimiterScaleDown rateLimitDivider; /**< For OP ports only. Not-valid
+ for some earlier chip revisions */
+} t_FmPortRateLimit;
+
+/**************************************************************************//**
+ @Description A structure for defining the parameters of
+ the Rx port performance counters
+*//***************************************************************************/
+typedef struct t_FmPortPerformanceCnt {
+ uint8_t taskCompVal; /**< Task compare value */
+ uint8_t queueCompVal; /**< Rx queue/Tx confirm queue compare
+ value (unused for H/O) */
+ uint8_t dmaCompVal; /**< Dma compare value */
+ uint32_t fifoCompVal; /**< Fifo compare value (in bytes) */
+} t_FmPortPerformanceCnt;
+
+/**************************************************************************//**
+ @Description A structure for defining the sizes of the Deep Sleep
+ the Auto Response tables
+*//***************************************************************************/
+typedef struct t_FmPortDsarTablesSizes
+{
+ uint16_t maxNumOfArpEntries;
+ uint16_t maxNumOfEchoIpv4Entries;
+ uint16_t maxNumOfNdpEntries;
+ uint16_t maxNumOfEchoIpv6Entries;
+ uint16_t maxNumOfSnmpIPV4Entries;
+ uint16_t maxNumOfSnmpIPV6Entries;
+ uint16_t maxNumOfSnmpOidEntries;
+ uint16_t maxNumOfSnmpOidChar; /* total amount of character needed for the snmp table */
+
+ uint16_t maxNumOfIpProtFiltering;
+ uint16_t maxNumOfTcpPortFiltering;
+ uint16_t maxNumOfUdpPortFiltering;
+} t_FmPortDsarTablesSizes;
+
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigDsarSupport
+
+ @Description This function will allocate the amount of MURAM needed for
+ this max number of entries for Deep Sleep Auto Response.
+ it will calculate all needed MURAM for autoresponse including
+ necesary common stuff.
+
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] params A pointer to a structure containing the maximum
+ sizes of the auto response tables
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigDsarSupport(t_Handle h_FmPortRx, t_FmPortDsarTablesSizes *params);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigNumOfOpenDmas
+
+ @Description Calling this routine changes the max number of open DMA's
+ available for this port. It changes this parameter in the
+ internal driver data base from its default configuration
+ [OP: 1]
+ [1G-RX, 1G-TX: 1 (+1)]
+ [10G-RX, 10G-TX: 8 (+8)]
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] p_OpenDmas A pointer to a structure of parameters defining
+ the open DMA allocation.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigNumOfOpenDmas(t_Handle h_FmPort, t_FmPortRsrc *p_OpenDmas);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigNumOfTasks
+
+ @Description Calling this routine changes the max number of tasks
+ available for this port. It changes this parameter in the
+ internal driver data base from its default configuration
+ [OP: 1]
+ [1G-RX, 1G-TX: 3 (+2)]
+ [10G-RX, 10G-TX: 16 (+8)]
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] p_NumOfTasks A pointer to a structure of parameters defining
+ the tasks allocation.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigNumOfTasks(t_Handle h_FmPort, t_FmPortRsrc *p_NumOfTasks);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigSizeOfFifo
+
+ @Description Calling this routine changes the max FIFO size configured for this port.
+
+ This function changes the internal driver data base from its
+ default configuration. Please refer to the driver's User Guide for
+ information on default FIFO sizes in the various devices.
+ [OP: 2KB]
+ [1G-RX, 1G-TX: 11KB]
+ [10G-RX, 10G-TX: 12KB]
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] p_SizeOfFifo A pointer to a structure of parameters defining
+ the FIFO allocation.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigSizeOfFifo(t_Handle h_FmPort, t_FmPortRsrc *p_SizeOfFifo);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigDeqHighPriority
+
+ @Description Calling this routine changes the dequeue priority in the
+ internal driver data base from its default configuration
+ 1G: [DEFAULT_PORT_deqHighPriority_1G]
+ 10G: [DEFAULT_PORT_deqHighPriority_10G]
+
+ May be used for Non-Rx ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] highPri TRUE to select high priority, FALSE for normal operation.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigDeqHighPriority(t_Handle h_FmPort, bool highPri);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigDeqType
+
+ @Description Calling this routine changes the dequeue type parameter in the
+ internal driver data base from its default configuration
+ [DEFAULT_PORT_deqType].
+
+ May be used for Non-Rx ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] deqType According to QM definition.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigDeqType(t_Handle h_FmPort, e_FmPortDeqType deqType);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigDeqPrefetchOption
+
+ @Description Calling this routine changes the dequeue prefetch option parameter in the
+ internal driver data base from its default configuration
+ [DEFAULT_PORT_deqPrefetchOption]
+ Note: Available for some chips only
+
+ May be used for Non-Rx ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] deqPrefetchOption New option
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigDeqPrefetchOption(t_Handle h_FmPort, e_FmPortDeqPrefetchOption deqPrefetchOption);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigDeqByteCnt
+
+ @Description Calling this routine changes the dequeue byte count parameter in
+ the internal driver data base from its default configuration
+ 1G:[DEFAULT_PORT_deqByteCnt_1G].
+ 10G:[DEFAULT_PORT_deqByteCnt_10G].
+
+ May be used for Non-Rx ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] deqByteCnt New byte count
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigDeqByteCnt(t_Handle h_FmPort, uint16_t deqByteCnt);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigBufferPrefixContent
+
+ @Description Defines the structure, size and content of the application buffer.
+ The prefix will
+ In Tx ports, if 'passPrsResult', the application
+ should set a value to their offsets in the prefix of
+ the FM will save the first 'privDataSize', than,
+ depending on 'passPrsResult' and 'passTimeStamp', copy parse result
+ and timeStamp, and the packet itself (in this order), to the
+ application buffer, and to offset.
+ Calling this routine changes the buffer margins definitions
+ in the internal driver data base from its default
+ configuration: Data size: [DEFAULT_PORT_bufferPrefixContent_privDataSize]
+ Pass Parser result: [DEFAULT_PORT_bufferPrefixContent_passPrsResult].
+ Pass timestamp: [DEFAULT_PORT_bufferPrefixContent_passTimeStamp].
+
+ May be used for all ports
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in,out] p_FmBufferPrefixContent A structure of parameters describing the
+ structure of the buffer.
+ Out parameter: Start margin - offset
+ of data from start of external buffer.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigBufferPrefixContent(t_Handle h_FmPort,
+ t_FmBufferPrefixContent *p_FmBufferPrefixContent);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigCheksumLastBytesIgnore
+
+ @Description Calling this routine changes the number of checksum bytes to ignore
+ parameter in the internal driver data base from its default configuration
+ [DEFAULT_PORT_cheksumLastBytesIgnore]
+
+ May be used by Tx & Rx ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] cheksumLastBytesIgnore New value
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigCheksumLastBytesIgnore(t_Handle h_FmPort, uint8_t cheksumLastBytesIgnore);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigCutBytesFromEnd
+
+ @Description Calling this routine changes the number of bytes to cut from a
+ frame's end parameter in the internal driver data base
+ from its default configuration [DEFAULT_PORT_cutBytesFromEnd]
+ Note that if the result of (frame length before chop - cutBytesFromEnd) is
+ less than 14 bytes, the chop operation is not executed.
+
+ May be used for Rx ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] cutBytesFromEnd New value
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigCutBytesFromEnd(t_Handle h_FmPort, uint8_t cutBytesFromEnd);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigPoolDepletion
+
+ @Description Calling this routine enables pause frame generation depending on the
+ depletion status of BM pools. It also defines the conditions to activate
+ this functionality. By default, this functionality is disabled.
+
+ May be used for Rx ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] p_BufPoolDepletion A structure of pool depletion parameters
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigPoolDepletion(t_Handle h_FmPort, t_FmBufPoolDepletion *p_BufPoolDepletion);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigObservedPoolDepletion
+
+ @Description Calling this routine enables a mechanism to stop port enqueue
+ depending on the depletion status of selected BM pools.
+ It also defines the conditions to activate
+ this functionality. By default, this functionality is disabled.
+
+ Note: Available for some chips only
+
+ May be used for OP ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] p_FmPortObservedBufPoolDepletion A structure of parameters for pool depletion.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigObservedPoolDepletion(t_Handle h_FmPort,
+ t_FmPortObservedBufPoolDepletion *p_FmPortObservedBufPoolDepletion);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigExtBufPools
+
+ @Description This routine should be called for OP ports
+ that internally use BM buffer pools. In such cases, e.g. for fragmentation and
+ re-assembly, the FM needs new BM buffers. By calling this routine the user
+ specifies the BM buffer pools that should be used.
+
+ Note: Available for some chips only
+
+ May be used for OP ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] p_FmExtPools A structure of parameters for the external pools.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigExtBufPools(t_Handle h_FmPort, t_FmExtPools *p_FmExtPools);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigBackupPools
+
+ @Description Calling this routine allows the configuration of some of the BM pools
+ defined for this port as backup pools.
+ A pool configured to be a backup pool will be used only if all other
+ enabled non-backup pools are depleted.
+
+ May be used for Rx ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] p_FmPortBackupBmPools An array of pool id's. All pools specified here will
+ be defined as backup pools.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigBackupPools(t_Handle h_FmPort, t_FmBackupBmPools *p_FmPortBackupBmPools);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigFrmDiscardOverride
+
+ @Description Calling this routine changes the error frames destination parameter
+ in the internal driver data base from its default configuration:
+ override = [DEFAULT_PORT_frmDiscardOverride]
+
+ May be used for Rx and OP ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] override TRUE to override discarding of error frames and
+ enqueueing them to error queue.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigFrmDiscardOverride(t_Handle h_FmPort, bool override);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigErrorsToDiscard
+
+ @Description Calling this routine changes the behaviour on error parameter
+ in the internal driver data base from its default configuration:
+ [DEFAULT_PORT_errorsToDiscard].
+ If a requested error was previously defined as "ErrorsToEnqueue" it's
+ definition will change and the frame will be discarded.
+ Errors that were not defined either as "ErrorsToEnqueue" nor as
+ "ErrorsToDiscard", will be forwarded to CPU.
+
+ May be used for Rx and OP ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] errs A list of errors to discard
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigErrorsToDiscard(t_Handle h_FmPort, fmPortFrameErrSelect_t errs);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigDmaSwapData
+
+ @Description Calling this routine changes the DMA swap data aparameter
+ in the internal driver data base from its default
+ configuration [DEFAULT_PORT_dmaSwapData]
+
+ May be used for all port types
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] swapData New selection
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigDmaSwapData(t_Handle h_FmPort, e_FmDmaSwapOption swapData);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigDmaIcCacheAttr
+
+ @Description Calling this routine changes the internal context cache
+ attribute parameter in the internal driver data base
+ from its default configuration [DEFAULT_PORT_dmaIntContextCacheAttr]
+
+ May be used for all port types
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] intContextCacheAttr New selection
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigDmaIcCacheAttr(t_Handle h_FmPort, e_FmDmaCacheOption intContextCacheAttr);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigDmaHdrAttr
+
+ @Description Calling this routine changes the header cache
+ attribute parameter in the internal driver data base
+ from its default configuration [DEFAULT_PORT_dmaHeaderCacheAttr]
+
+ May be used for all port types
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] headerCacheAttr New selection
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigDmaHdrAttr(t_Handle h_FmPort, e_FmDmaCacheOption headerCacheAttr);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigDmaScatterGatherAttr
+
+ @Description Calling this routine changes the scatter gather cache
+ attribute parameter in the internal driver data base
+ from its default configuration [DEFAULT_PORT_dmaScatterGatherCacheAttr]
+
+ May be used for all port types
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] scatterGatherCacheAttr New selection
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigDmaScatterGatherAttr(t_Handle h_FmPort, e_FmDmaCacheOption scatterGatherCacheAttr);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigDmaWriteOptimize
+
+ @Description Calling this routine changes the write optimization
+ parameter in the internal driver data base
+ from its default configuration: By default optimize = [DEFAULT_PORT_dmaWriteOptimize].
+ Note:
+
+ 1. For head optimization, data alignment must be >= 16 (supported by default).
+
+ 3. For tail optimization, note that the optimization is performed by extending the write transaction
+ of the frame payload at the tail as needed to achieve optimal bus transfers, so that the last write
+ is extended to be on 16/64 bytes aligned block (chip dependent).
+
+ Relevant for non-Tx port types
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] optimize TRUE to enable optimization, FALSE for normal operation
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigDmaWriteOptimize(t_Handle h_FmPort, bool optimize);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigNoScatherGather
+
+ @Description Calling this routine changes the noScatherGather parameter in internal driver data base
+ from its default configuration.
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] noScatherGather (TRUE - frame is discarded if can not be stored in single buffer,
+ FALSE - frame can be stored in scatter gather (S/G) format).
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigNoScatherGather(t_Handle h_FmPort, bool noScatherGather);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigDfltColor
+
+ @Description Calling this routine changes the internal default color parameter
+ in the internal driver data base
+ from its default configuration [DEFAULT_PORT_color]
+
+ May be used for all port types
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] color New selection
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigDfltColor(t_Handle h_FmPort, e_FmPortColor color);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigSyncReq
+
+ @Description Calling this routine changes the synchronization attribute parameter
+ in the internal driver data base from its default configuration:
+ syncReq = [DEFAULT_PORT_syncReq]
+
+ May be used for all port types
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] syncReq TRUE to request synchronization, FALSE otherwize.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigSyncReq(t_Handle h_FmPort, bool syncReq);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigForwardReuseIntContext
+
+ @Description This routine is relevant for Rx ports that are routed to OP port.
+ It changes the internal context reuse option in the internal
+ driver data base from its default configuration:
+ reuse = [DEFAULT_PORT_forwardIntContextReuse]
+
+ May be used for Rx ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] reuse TRUE to reuse internal context on frames
+ forwarded to OP port.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigForwardReuseIntContext(t_Handle h_FmPort, bool reuse);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigDontReleaseTxBufToBM
+
+ @Description This routine should be called if no Tx confirmation
+ is done, and yet buffers should not be released to the BM.
+ Normally, buffers are returned using the Tx confirmation
+ process. When Tx confirmation is not used (defFqid=0),
+ buffers are typically released to the BM. This routine
+ may be called to avoid this behavior and not release the
+ buffers.
+
+ May be used for Tx ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigDontReleaseTxBufToBM(t_Handle h_FmPort);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigIMMaxRxBufLength
+
+ @Description Changes the maximum receive buffer length from its default
+ configuration: Closest rounded down power of 2 value of the
+ data buffer size.
+
+ The maximum receive buffer length directly affects the structure
+ of received frames (single- or multi-buffered) and the performance
+ of both the FM and the driver.
+
+ The selection between single- or multi-buffered frames should be
+ done according to the characteristics of the specific application.
+ The recommended mode is to use a single data buffer per packet,
+ as this mode provides the best performance. However, the user can
+ select to use multiple data buffers per packet.
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] newVal Maximum receive buffer length (in bytes).
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+ This routine is to be used only if Independent-Mode is enabled.
+*//***************************************************************************/
+t_Error FM_PORT_ConfigIMMaxRxBufLength(t_Handle h_FmPort, uint16_t newVal);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigIMRxBdRingLength
+
+ @Description Changes the receive BD ring length from its default
+ configuration:[DEFAULT_PORT_rxBdRingLength]
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] newVal The desired BD ring length.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+ This routine is to be used only if Independent-Mode is enabled.
+*//***************************************************************************/
+t_Error FM_PORT_ConfigIMRxBdRingLength(t_Handle h_FmPort, uint16_t newVal);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigIMTxBdRingLength
+
+ @Description Changes the transmit BD ring length from its default
+ configuration:[DEFAULT_PORT_txBdRingLength]
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] newVal The desired BD ring length.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+ This routine is to be used only if Independent-Mode is enabled.
+*//***************************************************************************/
+t_Error FM_PORT_ConfigIMTxBdRingLength(t_Handle h_FmPort, uint16_t newVal);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigIMFmanCtrlExternalStructsMemory
+
+ @Description Configures memory partition and attributes for FMan-Controller
+ data structures (e.g. BD rings).
+ Calling this routine changes the internal driver data base
+ from its default configuration
+ [DEFAULT_PORT_ImfwExtStructsMemId, DEFAULT_PORT_ImfwExtStructsMemAttr].
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] memId Memory partition ID.
+ @Param[in] memAttributes Memory attributes mask (a combination of MEMORY_ATTR_x flags).
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_PORT_ConfigIMFmanCtrlExternalStructsMemory(t_Handle h_FmPort,
+ uint8_t memId,
+ uint32_t memAttributes);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigIMPolling
+
+ @Description Changes the Rx flow from interrupt driven (default) to polling.
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+ This routine is to be used only if Independent-Mode is enabled.
+*//***************************************************************************/
+t_Error FM_PORT_ConfigIMPolling(t_Handle h_FmPort);
+
+/**************************************************************************//**
+ @Function FM_PORT_ConfigMaxFrameLength
+
+ @Description Changes the definition of the max size of frame that should be
+ transmitted/received on this port from its default value [DEFAULT_PORT_maxFrameLength].
+ This parameter is used for confirmation of the minimum Fifo
+ size calculations and only for Tx ports or ports working in
+ independent mode. This should be larger than the maximum possible
+ MTU that will be used for this port (i.e. its MAC).
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] length Max size of frame
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+ This routine is to be used only if Independent-Mode is enabled.
+*//***************************************************************************/
+t_Error FM_PORT_ConfigMaxFrameLength(t_Handle h_FmPort, uint16_t length);
+
+/**************************************************************************//*
+ @Function FM_PORT_ConfigTxFifoMinFillLevel
+
+ @Description Calling this routine changes the fifo minimum
+ fill level parameter in the internal driver data base
+ from its default configuration [DEFAULT_PORT_txFifoMinFillLevel]
+
+ May be used for Tx ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] minFillLevel New value
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigTxFifoMinFillLevel(t_Handle h_FmPort, uint32_t minFillLevel);
+
+/**************************************************************************//*
+ @Function FM_PORT_ConfigFifoDeqPipelineDepth
+
+ @Description Calling this routine changes the fifo dequeue
+ pipeline depth parameter in the internal driver data base
+
+ from its default configuration: 1G ports: [DEFAULT_PORT_fifoDeqPipelineDepth_1G],
+ 10G port: [DEFAULT_PORT_fifoDeqPipelineDepth_10G],
+ OP port: [DEFAULT_PORT_fifoDeqPipelineDepth_OH]
+
+ May be used for Tx/OP ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] deqPipelineDepth New value
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigFifoDeqPipelineDepth(t_Handle h_FmPort, uint8_t deqPipelineDepth);
+
+/**************************************************************************//*
+ @Function FM_PORT_ConfigTxFifoLowComfLevel
+
+ @Description Calling this routine changes the fifo low comfort level
+ parameter in internal driver data base
+ from its default configuration [DEFAULT_PORT_txFifoLowComfLevel]
+
+ May be used for Tx ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] fifoLowComfLevel New value
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigTxFifoLowComfLevel(t_Handle h_FmPort, uint32_t fifoLowComfLevel);
+
+/**************************************************************************//*
+ @Function FM_PORT_ConfigRxFifoThreshold
+
+ @Description Calling this routine changes the threshold of the FIFO
+ fill level parameter in the internal driver data base
+ from its default configuration [DEFAULT_PORT_rxFifoThreshold]
+
+ If the total number of buffers which are
+ currently in use and associated with the
+ specific RX port exceed this threshold, the
+ BMI will signal the MAC to send a pause frame
+ over the link.
+
+ May be used for Rx ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] fifoThreshold New value
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigRxFifoThreshold(t_Handle h_FmPort, uint32_t fifoThreshold);
+
+/**************************************************************************//*
+ @Function FM_PORT_ConfigRxFifoPriElevationLevel
+
+ @Description Calling this routine changes the priority elevation level
+ parameter in the internal driver data base from its default
+ configuration [DEFAULT_PORT_rxFifoPriElevationLevel]
+
+ If the total number of buffers which are currently in use and
+ associated with the specific RX port exceed the amount specified
+ in priElevationLevel, BMI will signal the main FM's DMA to
+ elevate the FM priority on the system bus.
+
+ May be used for Rx ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] priElevationLevel New value
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigRxFifoPriElevationLevel(t_Handle h_FmPort, uint32_t priElevationLevel);
+
+#ifdef FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669
+/**************************************************************************//*
+ @Function FM_PORT_ConfigBCBWorkaround
+
+ @Description Configures BCB errata workaround.
+
+ When BCB errata is applicable, the workaround is always
+ performed by FM Controller. Thus, this functions doesn't
+ actually enable errata workaround but rather allows driver
+ to perform adjustments required due to errata workaround
+ execution in FM controller.
+
+ Applying BCB workaround also configures FM_PORT_FRM_ERR_PHYSICAL
+ errors to be discarded. Thus FM_PORT_FRM_ERR_PHYSICAL can't be
+ set by FM_PORT_SetErrorsRoute() function.
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigBCBWorkaround(t_Handle h_FmPort);
+#endif /* FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 */
+
+#if (DPAA_VERSION >= 11)
+/**************************************************************************//*
+ @Function FM_PORT_ConfigInternalBuffOffset
+
+ @Description Configures internal buffer offset.
+
+ May be used for Rx and OP ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] val New value
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ConfigInternalBuffOffset(t_Handle h_FmPort, uint8_t val);
+#endif /* (DPAA_VERSION >= 11) */
+
+/** @} */ /* end of FM_PORT_advanced_init_grp group */
+/** @} */ /* end of FM_PORT_init_grp group */
+
+
+/**************************************************************************//**
+ @Group FM_PORT_runtime_control_grp FM Port Runtime Control Unit
+
+ @Description FM Port Runtime control unit API functions, definitions and enums.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Description enum for defining FM Port counters
+*//***************************************************************************/
+typedef enum e_FmPortCounters {
+ e_FM_PORT_COUNTERS_CYCLE, /**< BMI performance counter */
+ e_FM_PORT_COUNTERS_TASK_UTIL, /**< BMI performance counter */
+ e_FM_PORT_COUNTERS_QUEUE_UTIL, /**< BMI performance counter */
+ e_FM_PORT_COUNTERS_DMA_UTIL, /**< BMI performance counter */
+ e_FM_PORT_COUNTERS_FIFO_UTIL, /**< BMI performance counter */
+ e_FM_PORT_COUNTERS_RX_PAUSE_ACTIVATION, /**< BMI Rx only performance counter */
+ e_FM_PORT_COUNTERS_FRAME, /**< BMI statistics counter */
+ e_FM_PORT_COUNTERS_DISCARD_FRAME, /**< BMI statistics counter */
+ e_FM_PORT_COUNTERS_DEALLOC_BUF, /**< BMI deallocate buffer statistics counter */
+ e_FM_PORT_COUNTERS_RX_BAD_FRAME, /**< BMI Rx only statistics counter */
+ e_FM_PORT_COUNTERS_RX_LARGE_FRAME, /**< BMI Rx only statistics counter */
+ e_FM_PORT_COUNTERS_RX_FILTER_FRAME, /**< BMI Rx & OP only statistics counter */
+ e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR, /**< BMI Rx, OP & HC only statistics counter */
+ e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD, /**< BMI Rx, OP & HC statistics counter */
+ e_FM_PORT_COUNTERS_PREPARE_TO_ENQUEUE_COUNTER, /**< BMI Rx, OP & HC only statistics counter */
+ e_FM_PORT_COUNTERS_WRED_DISCARD, /**< BMI OP & HC only statistics counter */
+ e_FM_PORT_COUNTERS_LENGTH_ERR, /**< BMI non-Rx statistics counter */
+ e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT, /**< BMI non-Rx statistics counter */
+ e_FM_PORT_COUNTERS_DEQ_TOTAL, /**< QMI total QM dequeues counter */
+ e_FM_PORT_COUNTERS_ENQ_TOTAL, /**< QMI total QM enqueues counter */
+ e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT, /**< QMI counter */
+ e_FM_PORT_COUNTERS_DEQ_CONFIRM /**< QMI counter */
+} e_FmPortCounters;
+
+
+/**************************************************************************//**
+ @Description Structure for Port id parameters.
+ Fields commented 'IN' are passed by the port module to be used
+ by the FM module.
+ Fields commented 'OUT' will be filled by FM before returning to port.
+*//***************************************************************************/
+typedef struct t_FmPortCongestionGrps {
+ uint16_t numOfCongestionGrpsToConsider; /**< The number of required CGs
+ to define the size of the following array */
+ uint8_t congestionGrpsToConsider[FM_PORT_NUM_OF_CONGESTION_GRPS];
+ /**< An array of CG indexes;
+ Note that the size of the array should be
+ 'numOfCongestionGrpsToConsider'. */
+#if (DPAA_VERSION >= 11)
+ bool pfcPrioritiesEn[FM_PORT_NUM_OF_CONGESTION_GRPS][FM_MAX_NUM_OF_PFC_PRIORITIES];
+ /**< a matrix that represents the map between the CG ids
+ defined in 'congestionGrpsToConsider' to the priorties
+ mapping array. */
+#endif /* (DPAA_VERSION >= 11) */
+} t_FmPortCongestionGrps;
+
+/**************************************************************************//**
+ @Description Structure for Deep Sleep Auto Response ARP Entry
+*//***************************************************************************/
+typedef struct t_FmPortDsarArpEntry
+{
+ uint32_t ipAddress;
+ uint8_t mac[6];
+ bool isVlan;
+ uint16_t vid;
+} t_FmPortDsarArpEntry;
+
+/**************************************************************************//**
+ @Description Structure for Deep Sleep Auto Response ARP info
+*//***************************************************************************/
+typedef struct t_FmPortDsarArpInfo
+{
+ uint8_t tableSize;
+ t_FmPortDsarArpEntry *p_AutoResTable;
+ bool enableConflictDetection; /* when TRUE Conflict Detection will be checked and wake the host if needed */
+} t_FmPortDsarArpInfo;
+
+/**************************************************************************//**
+ @Description Structure for Deep Sleep Auto Response NDP Entry
+*//***************************************************************************/
+typedef struct t_FmPortDsarNdpEntry
+{
+ uint32_t ipAddress[4];
+ uint8_t mac[6];
+ bool isVlan;
+ uint16_t vid;
+} t_FmPortDsarNdpEntry;
+
+/**************************************************************************//**
+ @Description Structure for Deep Sleep Auto Response NDP info
+*//***************************************************************************/
+typedef struct t_FmPortDsarNdpInfo
+{
+ uint32_t multicastGroup;
+
+ uint8_t tableSizeAssigned;
+ t_FmPortDsarNdpEntry *p_AutoResTableAssigned; /* This list refer to solicitation IP addresses.
+ Note that all IP adresses must be from the same multicast group.
+ This will be checked and if not operation will fail. */
+ uint8_t tableSizeTmp;
+ t_FmPortDsarNdpEntry *p_AutoResTableTmp; /* This list refer to temp IP addresses.
+ Note that all temp IP adresses must be from the same multicast group.
+ This will be checked and if not operation will fail. */
+
+ bool enableConflictDetection; /* when TRUE Conflict Detection will be checked and wake the host if needed */
+
+} t_FmPortDsarNdpInfo;
+
+/**************************************************************************//**
+ @Description Structure for Deep Sleep Auto Response ICMPV4 info
+*//***************************************************************************/
+typedef struct t_FmPortDsarEchoIpv4Info
+{
+ uint8_t tableSize;
+ t_FmPortDsarArpEntry *p_AutoResTable;
+} t_FmPortDsarEchoIpv4Info;
+
+/**************************************************************************//**
+ @Description Structure for Deep Sleep Auto Response ICMPV6 info
+*//***************************************************************************/
+typedef struct t_FmPortDsarEchoIpv6Info
+{
+ uint8_t tableSize;
+ t_FmPortDsarNdpEntry *p_AutoResTable;
+} t_FmPortDsarEchoIpv6Info;
+
+/**************************************************************************//**
+@Description Deep Sleep Auto Response SNMP OIDs table entry
+
+*//***************************************************************************/
+typedef struct {
+ uint16_t oidSize; /**< Size in octets of the OID. */
+ uint16_t resSize; /**< Size in octets of the value that is attached to the OID. */
+ uint8_t *p_Oid; /**< Pointer to the OID. OID is encoded in BER but type and length are excluded. */
+ uint64_t resValOrPtr; /**< Value (for up to 4 octets) or pointer to the Value. Encoded in BER. */
+} t_FmPortDsarOidsEntry;
+
+/**************************************************************************//**
+ @Description Deep Sleep Auto Response SNMP IPv4 Addresses Table Entry
+ Refer to the FMan Controller spec for more details.
+*//***************************************************************************/
+typedef struct
+{
+ uint32_t ipv4Addr; /*!< 32 bit IPv4 Address. */
+ bool isVlan;
+ uint16_t vid; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */
+ /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */
+} t_FmPortDsarSnmpIpv4AddrTblEntry;
+
+/**************************************************************************//**
+ @Description Deep Sleep Auto Response SNMP IPv6 Addresses Table Entry
+ Refer to the FMan Controller spec for more details.
+*//***************************************************************************/
+typedef struct
+{
+ uint32_t ipv6Addr[4]; /*!< 4 * 32 bit IPv6 Address. */
+ bool isVlan;
+ uint16_t vid; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */
+ /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */
+} t_FmPortDsarSnmpIpv6AddrTblEntry;
+
+/**************************************************************************//**
+ @Description Deep Sleep Auto Response SNMP Descriptor
+
+*//***************************************************************************/
+typedef struct
+{
+ uint16_t control; /**< Control bits [0-15]. */
+ uint16_t maxSnmpMsgLength; /**< Maximal allowed SNMP message length. */
+ uint16_t numOfIpv4Addresses; /**< Number of entries in IPv4 addresses table. */
+ uint16_t numOfIpv6Addresses; /**< Number of entries in IPv6 addresses table. */
+ t_FmPortDsarSnmpIpv4AddrTblEntry *p_Ipv4AddrTbl; /**< Pointer to IPv4 addresses table. */
+ t_FmPortDsarSnmpIpv6AddrTblEntry *p_Ipv6AddrTbl; /**< Pointer to IPv6 addresses table. */
+ uint8_t *p_RdOnlyCommunityStr; /**< Pointer to the Read Only Community String. */
+ uint8_t *p_RdWrCommunityStr; /**< Pointer to the Read Write Community String. */
+ t_FmPortDsarOidsEntry *p_OidsTbl; /**< Pointer to OIDs table. */
+ uint32_t oidsTblSize; /**< Number of entries in OIDs table. */
+} t_FmPortDsarSnmpInfo;
+
+/**************************************************************************//**
+ @Description Structure for Deep Sleep Auto Response filtering Entry
+*//***************************************************************************/
+typedef struct t_FmPortDsarFilteringEntry
+{
+ uint16_t srcPort;
+ uint16_t dstPort;
+ uint16_t srcPortMask;
+ uint16_t dstPortMask;
+} t_FmPortDsarFilteringEntry;
+
+/**************************************************************************//**
+ @Description Structure for Deep Sleep Auto Response filtering info
+*//***************************************************************************/
+typedef struct t_FmPortDsarFilteringInfo
+{
+ /* IP protocol filtering parameters */
+ uint8_t ipProtTableSize;
+ uint8_t *p_IpProtTablePtr;
+ bool ipProtDropOnHit; /* when TRUE, hit in the table will cause the packet to be droped,
+ miss will pass the packet to UDP/TCP filters if needed and if not
+ to the classification tree. If the classification tree will pass
+ the packet to a queue it will cause a wake interupt.
+ When FALSE it the other way around. */
+ /* UDP port filtering parameters */
+ uint8_t udpPortsTableSize;
+ t_FmPortDsarFilteringEntry *p_UdpPortsTablePtr;
+ bool udpPortDropOnHit; /* when TRUE, hit in the table will cause the packet to be droped,
+ miss will pass the packet to classification tree.
+ If the classification tree will pass the packet to a queue it
+ will cause a wake interupt.
+ When FALSE it the other way around. */
+ /* TCP port filtering parameters */
+ uint16_t tcpFlagsMask;
+ uint8_t tcpPortsTableSize;
+ t_FmPortDsarFilteringEntry *p_TcpPortsTablePtr;
+ bool tcpPortDropOnHit; /* when TRUE, hit in the table will cause the packet to be droped,
+ miss will pass the packet to classification tree.
+ If the classification tree will pass the packet to a queue it
+ will cause a wake interupt.
+ When FALSE it the other way around. */
+} t_FmPortDsarFilteringInfo;
+
+/**************************************************************************//**
+ @Description Structure for Deep Sleep Auto Response parameters
+*//***************************************************************************/
+typedef struct t_FmPortDsarParams
+{
+ t_Handle h_FmPortTx;
+ t_FmPortDsarArpInfo *p_AutoResArpInfo;
+ t_FmPortDsarEchoIpv4Info *p_AutoResEchoIpv4Info;
+ t_FmPortDsarNdpInfo *p_AutoResNdpInfo;
+ t_FmPortDsarEchoIpv6Info *p_AutoResEchoIpv6Info;
+ t_FmPortDsarSnmpInfo *p_AutoResSnmpInfo;
+ t_FmPortDsarFilteringInfo *p_AutoResFilteringInfo;
+} t_FmPortDsarParams;
+
+/**************************************************************************//**
+ @Function FM_PORT_EnterDsar
+
+ @Description Enter Deep Sleep Auto Response mode.
+ This function write the apropriate values to in the relevant
+ tables in the MURAM. It then set the Tx port in independent
+ mode as needed and redirect the receive flow to go through the
+ Dsar Fman-ctrl code
+
+ Calling this routine invalidates the descriptor.
+
+ @Param[in] h_FmPortRx - FM PORT module descriptor
+ @Param[in] params - Auto Response parameters
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_EnterDsar(t_Handle h_FmPortRx, t_FmPortDsarParams *params);
+
+/**************************************************************************//**
+ @Function FM_PORT_ExitDsar
+
+ @Description Exit Deep Sleep Auto Response mode.
+ This function reverse the AR mode and put the ports back into
+ their original wake mode
+
+ @Param[in] h_FmPortRx - FM PORT Rx module descriptor
+ @Param[in] h_FmPortTx - FM PORT Tx module descriptor
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_EnterDsar().
+*//***************************************************************************/
+void FM_PORT_ExitDsar(t_Handle h_FmPortRx, t_Handle h_FmPortTx);
+
+/**************************************************************************//**
+ @Function FM_PORT_IsInDsar
+
+ @Description This function returns TRUE if the port was set as Auto Response
+ and FALSE if not. Once Exit AR mode it will return FALSE as well
+ until re-enabled once more.
+
+ @Param[in] h_FmPort - FM PORT module descriptor
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+bool FM_PORT_IsInDsar(t_Handle h_FmPort);
+
+typedef struct t_FmPortDsarStats
+{
+ uint32_t arpArCnt;
+ uint32_t echoIcmpv4ArCnt;
+ uint32_t ndpArCnt;
+ uint32_t echoIcmpv6ArCnt;
+ uint32_t snmpGetCnt;
+ uint32_t snmpGetNextCnt;
+} t_FmPortDsarStats;
+
+/**************************************************************************//**
+ @Function FM_PORT_GetDsarStats
+
+ @Description Return statistics for Deep Sleep Auto Response
+
+ @Param[in] h_FmPortRx - FM PORT module descriptor
+ @Param[out] stats - structure containing the statistics counters
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_PORT_GetDsarStats(t_Handle h_FmPortRx, t_FmPortDsarStats *stats);
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+/**************************************************************************//**
+ @Function FM_PORT_DumpRegs
+
+ @Description Dump all regs.
+
+ Calling this routine invalidates the descriptor.
+
+ @Param[in] h_FmPort - FM PORT module descriptor
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_DumpRegs(t_Handle h_FmPort);
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+/**************************************************************************//**
+ @Function FM_PORT_GetBufferDataOffset
+
+ @Description Relevant for Rx ports.
+ Returns the data offset from the beginning of the data buffer
+
+ @Param[in] h_FmPort - FM PORT module descriptor
+
+ @Return data offset.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+uint32_t FM_PORT_GetBufferDataOffset(t_Handle h_FmPort);
+
+/**************************************************************************//**
+ @Function FM_PORT_GetBufferICInfo
+
+ @Description Returns the Internal Context offset from the beginning of the data buffer
+
+ @Param[in] h_FmPort - FM PORT module descriptor
+ @Param[in] p_Data - A pointer to the data buffer.
+
+ @Return Internal context info pointer on success, NULL if 'allOtherInfo' was not
+ configured for this port.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+uint8_t * FM_PORT_GetBufferICInfo(t_Handle h_FmPort, char *p_Data);
+
+/**************************************************************************//**
+ @Function FM_PORT_GetBufferPrsResult
+
+ @Description Returns the pointer to the parse result in the data buffer.
+ In Rx ports this is relevant after reception, if parse
+ result is configured to be part of the data passed to the
+ application. For non Rx ports it may be used to get the pointer
+ of the area in the buffer where parse result should be
+ initialized - if so configured.
+ See FM_PORT_ConfigBufferPrefixContent for data buffer prefix
+ configuration.
+
+ @Param[in] h_FmPort - FM PORT module descriptor
+ @Param[in] p_Data - A pointer to the data buffer.
+
+ @Return Parse result pointer on success, NULL if parse result was not
+ configured for this port.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+t_FmPrsResult * FM_PORT_GetBufferPrsResult(t_Handle h_FmPort, char *p_Data);
+
+/**************************************************************************//**
+ @Function FM_PORT_GetBufferTimeStamp
+
+ @Description Returns the time stamp in the data buffer.
+ Relevant for Rx ports for getting the buffer time stamp.
+ See FM_PORT_ConfigBufferPrefixContent for data buffer prefix
+ configuration.
+
+ @Param[in] h_FmPort - FM PORT module descriptor
+ @Param[in] p_Data - A pointer to the data buffer.
+
+ @Return A pointer to the hash result on success, NULL otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+uint64_t * FM_PORT_GetBufferTimeStamp(t_Handle h_FmPort, char *p_Data);
+
+/**************************************************************************//**
+ @Function FM_PORT_GetBufferHashResult
+
+ @Description Given a data buffer, on the condition that hash result was defined
+ as a part of the buffer content (see FM_PORT_ConfigBufferPrefixContent)
+ this routine will return the pointer to the hash result location in the
+ buffer prefix.
+
+ @Param[in] h_FmPort - FM PORT module descriptor
+ @Param[in] p_Data - A pointer to the data buffer.
+
+ @Return A pointer to the hash result on success, NULL otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+uint8_t * FM_PORT_GetBufferHashResult(t_Handle h_FmPort, char *p_Data);
+
+/**************************************************************************//**
+ @Function FM_PORT_Disable
+
+ @Description Gracefully disable an FM port. The port will not start new tasks after all
+ tasks associated with the port are terminated.
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+ This is a blocking routine, it returns after port is
+ gracefully stopped, i.e. the port will not except new frames,
+ but it will finish all frames or tasks which were already began
+*//***************************************************************************/
+t_Error FM_PORT_Disable(t_Handle h_FmPort);
+
+/**************************************************************************//**
+ @Function FM_PORT_Enable
+
+ @Description A runtime routine provided to allow disable/enable of port.
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_Enable(t_Handle h_FmPort);
+
+/**************************************************************************//**
+ @Function FM_PORT_SetRateLimit
+
+ @Description Calling this routine enables rate limit algorithm.
+ By default, this functionality is disabled.
+ Note that rate-limit mechanism uses the FM time stamp.
+ The selected rate limit specified here would be
+ rounded DOWN to the nearest 16M.
+
+ May be used for Tx and OP ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] p_RateLimit A structure of rate limit parameters
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+ If rate limit is set on a port that need to send PFC frames,
+ it might violate the stop transmit timing.
+*//***************************************************************************/
+t_Error FM_PORT_SetRateLimit(t_Handle h_FmPort, t_FmPortRateLimit *p_RateLimit);
+
+/**************************************************************************//**
+ @Function FM_PORT_DeleteRateLimit
+
+ @Description Calling this routine disables and clears rate limit
+ initialization.
+
+ May be used for Tx and OP ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_DeleteRateLimit(t_Handle h_FmPort);
+
+/**************************************************************************//**
+ @Function FM_PORT_SetPfcPrioritiesMappingToQmanWQ
+
+ @Description Calling this routine maps each PFC received priority to the transmit WQ.
+ This WQ will be blocked upon receiving a PFC frame with this priority.
+
+ May be used for Tx ports only.
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] prio PFC priority (0-7).
+ @Param[in] wq Work Queue (0-7).
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_SetPfcPrioritiesMappingToQmanWQ(t_Handle h_FmPort, uint8_t prio, uint8_t wq);
+
+/**************************************************************************//**
+ @Function FM_PORT_SetStatisticsCounters
+
+ @Description Calling this routine enables/disables port's statistics counters.
+ By default, counters are enabled.
+
+ May be used for all port types
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] enable TRUE to enable, FALSE to disable.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_SetStatisticsCounters(t_Handle h_FmPort, bool enable);
+
+/**************************************************************************//**
+ @Function FM_PORT_SetFrameQueueCounters
+
+ @Description Calling this routine enables/disables port's enqueue/dequeue counters.
+ By default, counters are enabled.
+
+ May be used for all ports
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] enable TRUE to enable, FALSE to disable.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_SetFrameQueueCounters(t_Handle h_FmPort, bool enable);
+
+/**************************************************************************//**
+ @Function FM_PORT_AnalyzePerformanceParams
+
+ @Description User may call this routine to so the driver will analyze if the
+ basic performance parameters are correct and also the driver may
+ suggest of improvements; The basic parameters are FIFO sizes, number
+ of DMAs and number of TNUMs for the port.
+
+ May be used for all port types
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_AnalyzePerformanceParams(t_Handle h_FmPort);
+
+
+/**************************************************************************//**
+ @Function FM_PORT_SetAllocBufCounter
+
+ @Description Calling this routine enables/disables BM pool allocate
+ buffer counters.
+ By default, counters are enabled.
+
+ May be used for Rx ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] poolId BM pool id.
+ @Param[in] enable TRUE to enable, FALSE to disable.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_SetAllocBufCounter(t_Handle h_FmPort, uint8_t poolId, bool enable);
+
+/**************************************************************************//**
+ @Function FM_PORT_GetCounter
+
+ @Description Reads one of the FM PORT counters.
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] fmPortCounter The requested counter.
+
+ @Return Counter's current value.
+
+ @Cautions Allowed only following FM_PORT_Init().
+ Note that it is user's responsibility to call this routine only
+ for enabled counters, and there will be no indication if a
+ disabled counter is accessed.
+*//***************************************************************************/
+uint32_t FM_PORT_GetCounter(t_Handle h_FmPort, e_FmPortCounters fmPortCounter);
+
+/**************************************************************************//**
+ @Function FM_PORT_ModifyCounter
+
+ @Description Sets a value to an enabled counter. Use "0" to reset the counter.
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] fmPortCounter The requested counter.
+ @Param[in] value The requested value to be written into the counter.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ModifyCounter(t_Handle h_FmPort, e_FmPortCounters fmPortCounter, uint32_t value);
+
+/**************************************************************************//**
+ @Function FM_PORT_GetAllocBufCounter
+
+ @Description Reads one of the FM PORT buffer counters.
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] poolId The requested pool.
+
+ @Return Counter's current value.
+
+ @Cautions Allowed only following FM_PORT_Init().
+ Note that it is user's responsibility to call this routine only
+ for enabled counters, and there will be no indication if a
+ disabled counter is accessed.
+*//***************************************************************************/
+uint32_t FM_PORT_GetAllocBufCounter(t_Handle h_FmPort, uint8_t poolId);
+
+/**************************************************************************//**
+ @Function FM_PORT_ModifyAllocBufCounter
+
+ @Description Sets a value to an enabled counter. Use "0" to reset the counter.
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] poolId The requested pool.
+ @Param[in] value The requested value to be written into the counter.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ModifyAllocBufCounter(t_Handle h_FmPort, uint8_t poolId, uint32_t value);
+
+/**************************************************************************//**
+ @Function FM_PORT_AddCongestionGrps
+
+ @Description This routine effects the corresponding Tx port.
+ It should be called in order to enable pause
+ frame transmission in case of congestion in one or more
+ of the congestion groups relevant to this port.
+ Each call to this routine may add one or more congestion
+ groups to be considered relevant to this port.
+
+ May be used for Rx, or RX+OP ports only (depending on chip)
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] p_CongestionGrps A pointer to an array of congestion groups
+ id's to consider.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_AddCongestionGrps(t_Handle h_FmPort, t_FmPortCongestionGrps *p_CongestionGrps);
+
+/**************************************************************************//**
+ @Function FM_PORT_RemoveCongestionGrps
+
+ @Description This routine effects the corresponding Tx port. It should be
+ called when congestion groups were
+ defined for this port and are no longer relevant, or pause
+ frames transmitting is not required on their behalf.
+ Each call to this routine may remove one or more congestion
+ groups to be considered relevant to this port.
+
+ May be used for Rx, or RX+OP ports only (depending on chip)
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] p_CongestionGrps A pointer to an array of congestion groups
+ id's to consider.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_RemoveCongestionGrps(t_Handle h_FmPort, t_FmPortCongestionGrps *p_CongestionGrps);
+
+/**************************************************************************//**
+ @Function FM_PORT_IsStalled
+
+ @Description A routine for checking whether the specified port is stalled.
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+
+ @Return TRUE if port is stalled, FALSE otherwize
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+bool FM_PORT_IsStalled(t_Handle h_FmPort);
+
+/**************************************************************************//**
+ @Function FM_PORT_ReleaseStalled
+
+ @Description This routine may be called in case the port was stalled and may
+ now be released.
+ Note that this routine is available only on older FMan revisions
+ (FMan v2, DPAA v1.0 only).
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_ReleaseStalled(t_Handle h_FmPort);
+
+/**************************************************************************//**
+ @Function FM_PORT_SetRxL4ChecksumVerify
+
+ @Description This routine is relevant for Rx ports (1G and 10G). The routine
+ set/clear the L3/L4 checksum verification (on RX side).
+ Note that this takes affect only if hw-parser is enabled!
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] l4Checksum boolean indicates whether to do L3/L4 checksum
+ on frames or not.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_SetRxL4ChecksumVerify(t_Handle h_FmPort, bool l4Checksum);
+
+/**************************************************************************//**
+ @Function FM_PORT_SetErrorsRoute
+
+ @Description Errors selected for this routine will cause a frame with that error
+ to be enqueued to error queue.
+ Errors not selected for this routine will cause a frame with that error
+ to be enqueued to the one of the other port queues.
+ By default all errors are defined to be enqueued to error queue.
+ Errors that were configured to be discarded (at initialization)
+ may not be selected here.
+
+ May be used for Rx and OP ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] errs A list of errors to enqueue to error queue
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Config() and before FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_SetErrorsRoute(t_Handle h_FmPort, fmPortFrameErrSelect_t errs);
+
+/**************************************************************************//**
+ @Function FM_PORT_SetIMExceptions
+
+ @Description Calling this routine enables/disables FM PORT interrupts.
+
+ @Param[in] h_FmPort FM PORT module descriptor.
+ @Param[in] exception The exception to be selected.
+ @Param[in] enable TRUE to enable interrupt, FALSE to mask it.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+ This routine should NOT be called from guest-partition
+ (i.e. guestId != NCSW_MASTER_ID)
+*//***************************************************************************/
+t_Error FM_PORT_SetIMExceptions(t_Handle h_FmPort, e_FmPortExceptions exception, bool enable);
+
+/**************************************************************************//*
+ @Function FM_PORT_SetPerformanceCounters
+
+ @Description Calling this routine enables/disables port's performance counters.
+ By default, counters are enabled.
+
+ May be used for all port types
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] enable TRUE to enable, FALSE to disable.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_SetPerformanceCounters(t_Handle h_FmPort, bool enable);
+
+/**************************************************************************//*
+ @Function FM_PORT_SetPerformanceCountersParams
+
+ @Description Calling this routine defines port's performance
+ counters parameters.
+
+ May be used for all port types
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] p_FmPortPerformanceCnt A pointer to a structure of performance
+ counters parameters.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_SetPerformanceCountersParams(t_Handle h_FmPort, t_FmPortPerformanceCnt *p_FmPortPerformanceCnt);
+
+/**************************************************************************//**
+ @Group FM_PORT_pcd_runtime_control_grp FM Port PCD Runtime Control Unit
+
+ @Description FM Port PCD Runtime control unit API functions, definitions and enums.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Description A structure defining the KG scheme after the parser.
+ This is relevant only to change scheme selection mode - from
+ direct to indirect and vice versa, or when the scheme is selected directly,
+ to select the scheme id.
+
+*//***************************************************************************/
+typedef struct t_FmPcdKgSchemeSelect {
+ bool direct; /**< TRUE to use 'h_Scheme' directly, FALSE to use LCV. */
+ t_Handle h_DirectScheme; /**< Scheme handle, selects the scheme after parser;
+ Relevant only when 'direct' is TRUE. */
+} t_FmPcdKgSchemeSelect;
+
+/**************************************************************************//**
+ @Description A structure of scheme parameters
+*//***************************************************************************/
+typedef struct t_FmPcdPortSchemesParams {
+ uint8_t numOfSchemes; /**< Number of schemes for port to be bound to. */
+ t_Handle h_Schemes[FM_PCD_KG_NUM_OF_SCHEMES]; /**< Array of 'numOfSchemes' schemes for the
+ port to be bound to */
+} t_FmPcdPortSchemesParams;
+
+/**************************************************************************//**
+ @Description Union for defining port protocol parameters for parser
+*//***************************************************************************/
+typedef union u_FmPcdHdrPrsOpts {
+ /* MPLS */
+ struct {
+ bool labelInterpretationEnable; /**< When this bit is set, the last MPLS label will be
+ interpreted as described in HW spec table. When the bit
+ is cleared, the parser will advance to MPLS next parse */
+ e_NetHeaderType nextParse; /**< must be equal or higher than IPv4 */
+ } mplsPrsOptions;
+ /* VLAN */
+ struct {
+ uint16_t tagProtocolId1; /**< User defined Tag Protocol Identifier, to be recognized
+ on VLAN TAG on top of 0x8100 and 0x88A8 */
+ uint16_t tagProtocolId2; /**< User defined Tag Protocol Identifier, to be recognized
+ on VLAN TAG on top of 0x8100 and 0x88A8 */
+ } vlanPrsOptions;
+ /* PPP */
+ struct{
+ bool enableMTUCheck; /**< Check validity of MTU according to RFC2516 */
+ } pppoePrsOptions;
+
+ /* IPV6 */
+ struct{
+ bool routingHdrEnable; /**< TRUE to enable routing header, otherwise ignore */
+ } ipv6PrsOptions;
+
+ /* UDP */
+ struct{
+ bool padIgnoreChecksum; /**< TRUE to ignore pad in checksum */
+ } udpPrsOptions;
+
+ /* TCP */
+ struct {
+ bool padIgnoreChecksum; /**< TRUE to ignore pad in checksum */
+ } tcpPrsOptions;
+} u_FmPcdHdrPrsOpts;
+
+/**************************************************************************//**
+ @Description A structure for defining each header for the parser
+*//***************************************************************************/
+typedef struct t_FmPcdPrsAdditionalHdrParams {
+ e_NetHeaderType hdr; /**< Selected header */
+ bool errDisable; /**< TRUE to disable error indication */
+ bool swPrsEnable; /**< Enable jump to SW parser when this
+ header is recognized by the HW parser. */
+ uint8_t indexPerHdr; /**< Normally 0, if more than one sw parser
+ attachments exists for the same header,
+ (in the main sw parser code) use this
+ index to distinguish between them. */
+ bool usePrsOpts; /**< TRUE to use parser options. */
+ u_FmPcdHdrPrsOpts prsOpts; /**< A union according to header type,
+ defining the parser options selected.*/
+} t_FmPcdPrsAdditionalHdrParams;
+
+/**************************************************************************//**
+ @Description struct for defining port PCD parameters
+*//***************************************************************************/
+typedef struct t_FmPortPcdPrsParams {
+ uint8_t prsResultPrivateInfo; /**< The private info provides a method of inserting
+ port information into the parser result. This information
+ may be extracted by Keygen and be used for frames
+ distribution when a per-port distinction is required,
+ it may also be used as a port logical id for analyzing
+ incoming frames. */
+ uint8_t parsingOffset; /**< Number of bytes from beginning of packet to start parsing */
+ e_NetHeaderType firstPrsHdr; /**< The type of the first header expected at 'parsingOffset' */
+ bool includeInPrsStatistics; /**< TRUE to include this port in the parser statistics;
+ NOTE: this field is not valid when the FM is in "guest" mode
+ and IPC is not available. */
+ uint8_t numOfHdrsWithAdditionalParams; /**< Normally 0, some headers may get
+ special parameters */
+ t_FmPcdPrsAdditionalHdrParams additionalParams[FM_PCD_PRS_NUM_OF_HDRS];
+ /**< 'numOfHdrsWithAdditionalParams' structures
+ of additional parameters
+ for each header that requires them */
+ bool setVlanTpid1; /**< TRUE to configure user selection of Ethertype to
+ indicate a VLAN tag (in addition to the TPID values
+ 0x8100 and 0x88A8). */
+ uint16_t vlanTpid1; /**< extra tag to use if setVlanTpid1=TRUE. */
+ bool setVlanTpid2; /**< TRUE to configure user selection of Ethertype to
+ indicate a VLAN tag (in addition to the TPID values
+ 0x8100 and 0x88A8). */
+ uint16_t vlanTpid2; /**< extra tag to use if setVlanTpid1=TRUE. */
+} t_FmPortPcdPrsParams;
+
+/**************************************************************************//**
+ @Description struct for defining coarse alassification parameters
+*//***************************************************************************/
+typedef struct t_FmPortPcdCcParams {
+ t_Handle h_CcTree; /**< A handle to a CC tree */
+} t_FmPortPcdCcParams;
+
+/**************************************************************************//**
+ @Description struct for defining keygen parameters
+*//***************************************************************************/
+typedef struct t_FmPortPcdKgParams {
+ uint8_t numOfSchemes; /**< Number of schemes for port to be bound to. */
+ t_Handle h_Schemes[FM_PCD_KG_NUM_OF_SCHEMES];
+ /**< Array of 'numOfSchemes' schemes handles for the
+ port to be bound to */
+ bool directScheme; /**< TRUE for going from parser to a specific scheme,
+ regardless of parser result */
+ t_Handle h_DirectScheme; /**< relevant only if direct == TRUE, Scheme handle,
+ as returned by FM_PCD_KgSetScheme */
+} t_FmPortPcdKgParams;
+
+/**************************************************************************//**
+ @Description struct for defining policer parameters
+*//***************************************************************************/
+typedef struct t_FmPortPcdPlcrParams {
+ t_Handle h_Profile; /**< Selected profile handle */
+} t_FmPortPcdPlcrParams;
+
+/**************************************************************************//**
+ @Description struct for defining port PCD parameters
+*//***************************************************************************/
+typedef struct t_FmPortPcdParams {
+ e_FmPortPcdSupport pcdSupport; /**< Relevant for Rx and offline ports only.
+ Describes the active PCD engines for this port. */
+ t_Handle h_NetEnv; /**< HL Unused in PLCR only mode */
+ t_FmPortPcdPrsParams *p_PrsParams; /**< Parser parameters for this port */
+ t_FmPortPcdCcParams *p_CcParams; /**< Coarse classification parameters for this port */
+ t_FmPortPcdKgParams *p_KgParams; /**< Keygen parameters for this port */
+ t_FmPortPcdPlcrParams *p_PlcrParams; /**< Policer parameters for this port; Relevant for one of
+ following cases:
+ e_FM_PORT_PCD_SUPPORT_PLCR_ONLY or
+ e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR were selected,
+ or if any flow uses a KG scheme were policer
+ profile is not generated
+ ('bypassPlcrProfileGeneration selected'). */
+ t_Handle h_IpReassemblyManip;/**< IP Reassembly manipulation */
+} t_FmPortPcdParams;
+
+/**************************************************************************//**
+ @Description A structure for defining the Parser starting point
+*//***************************************************************************/
+typedef struct t_FmPcdPrsStart {
+ uint8_t parsingOffset; /**< Number of bytes from beginning of packet to
+ start parsing */
+ e_NetHeaderType firstPrsHdr; /**< The type of the first header axpected at
+ 'parsingOffset' */
+} t_FmPcdPrsStart;
+
+#if (DPAA_VERSION >= 11)
+/**************************************************************************//**
+ @Description struct for defining external buffer margins
+*//***************************************************************************/
+typedef struct t_FmPortVSPAllocParams {
+ uint8_t numOfProfiles; /**< Number of Virtual Storage Profiles; must be a power of 2 */
+ uint8_t dfltRelativeId; /**< The default Virtual-Storage-Profile-id dedicated to Rx/OP port
+ The same default Virtual-Storage-Profile-id will be for coupled Tx port
+ if relevant function called for Rx port */
+ t_Handle h_FmTxPort; /**< Handle to coupled Tx Port; not relevant for OP port. */
+} t_FmPortVSPAllocParams;
+#endif /* (DPAA_VERSION >= 11) */
+
+
+/**************************************************************************//**
+ @Function FM_PORT_SetPCD
+
+ @Description Calling this routine defines the port's PCD configuration.
+ It changes it from its default configuration which is PCD
+ disabled (BMI to BMI) and configures it according to the passed
+ parameters.
+
+ May be used for Rx and OP ports only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] p_FmPortPcd A Structure of parameters defining the port's PCD
+ configuration.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_SetPCD(t_Handle h_FmPort, t_FmPortPcdParams *p_FmPortPcd);
+
+/**************************************************************************//**
+ @Function FM_PORT_DeletePCD
+
+ @Description Calling this routine releases the port's PCD configuration.
+ The port returns to its default configuration which is PCD
+ disabled (BMI to BMI) and all PCD configuration is removed.
+
+ May be used for Rx and OP ports which are
+ in PCD mode only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_DeletePCD(t_Handle h_FmPort);
+
+/**************************************************************************//**
+ @Function FM_PORT_AttachPCD
+
+ @Description This routine may be called after FM_PORT_DetachPCD was called,
+ to return to the originally configured PCD support flow.
+ The couple of routines are used to allow PCD configuration changes
+ that demand that PCD will not be used while changes take place.
+
+ May be used for Rx and OP ports which are
+ in PCD mode only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+*//***************************************************************************/
+t_Error FM_PORT_AttachPCD(t_Handle h_FmPort);
+
+/**************************************************************************//**
+ @Function FM_PORT_DetachPCD
+
+ @Description Calling this routine detaches the port from its PCD functionality.
+ The port returns to its default flow which is BMI to BMI.
+
+ May be used for Rx and OP ports which are
+ in PCD mode only
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_AttachPCD().
+*//***************************************************************************/
+t_Error FM_PORT_DetachPCD(t_Handle h_FmPort);
+
+/**************************************************************************//**
+ @Function FM_PORT_PcdPlcrAllocProfiles
+
+ @Description This routine may be called only for ports that use the Policer in
+ order to allocate private policer profiles.
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] numOfProfiles The number of required policer profiles
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init() and FM_PCD_Init(),
+ and before FM_PORT_SetPCD().
+*//***************************************************************************/
+t_Error FM_PORT_PcdPlcrAllocProfiles(t_Handle h_FmPort, uint16_t numOfProfiles);
+
+/**************************************************************************//**
+ @Function FM_PORT_PcdPlcrFreeProfiles
+
+ @Description This routine should be called for freeing private policer profiles.
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init() and FM_PCD_Init(),
+ and before FM_PORT_SetPCD().
+*//***************************************************************************/
+t_Error FM_PORT_PcdPlcrFreeProfiles(t_Handle h_FmPort);
+
+#if (DPAA_VERSION >= 11)
+/**************************************************************************//**
+ @Function FM_PORT_VSPAlloc
+
+ @Description This routine allocated VSPs per port and forces the port to work
+ in VSP mode. Note that the port is initialized by default with the
+ physical-storage-profile only.
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] p_Params A structure of parameters for allocation VSP's per port
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init(), and before FM_PORT_SetPCD()
+ and also before FM_PORT_Enable(); i.e. the port should be disabled.
+*//***************************************************************************/
+t_Error FM_PORT_VSPAlloc(t_Handle h_FmPort, t_FmPortVSPAllocParams *p_Params);
+#endif /* (DPAA_VERSION >= 11) */
+
+/**************************************************************************//**
+ @Function FM_PORT_PcdKgModifyInitialScheme
+
+ @Description This routine may be called only for ports that use the keygen in
+ order to change the initial scheme frame should be routed to.
+ The change may be of a scheme id (in case of direct mode),
+ from direct to indirect, or from indirect to direct - specifying the scheme id.
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] p_FmPcdKgScheme A structure of parameters for defining whether
+ a scheme is direct/indirect, and if direct - scheme id.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init() and FM_PORT_SetPCD().
+*//***************************************************************************/
+t_Error FM_PORT_PcdKgModifyInitialScheme (t_Handle h_FmPort, t_FmPcdKgSchemeSelect *p_FmPcdKgScheme);
+
+/**************************************************************************//**
+ @Function FM_PORT_PcdPlcrModifyInitialProfile
+
+ @Description This routine may be called for ports with flows
+ e_FM_PORT_PCD_SUPPORT_PLCR_ONLY or e_FM_PORT_PCD_SUPPORT_PRS_AND_PLCR
+ only, to change the initial Policer profile frame should be
+ routed to. The change may be of a profile and/or absolute/direct
+ mode selection.
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] h_Profile Policer profile handle
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init() and FM_PORT_SetPCD().
+*//***************************************************************************/
+t_Error FM_PORT_PcdPlcrModifyInitialProfile (t_Handle h_FmPort, t_Handle h_Profile);
+
+/**************************************************************************//**
+ @Function FM_PORT_PcdCcModifyTree
+
+ @Description This routine may be called for ports that use coarse classification tree
+ if the user wishes to replace the tree. The routine may not be called while port
+ receives packets using the PCD functionalities, therefor port must be first detached
+ from the PCD, only than the routine may be called, and than port be attached to PCD again.
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] h_CcTree A CC tree that was already built. The tree id as returned from
+ the BuildTree routine.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init(), FM_PORT_SetPCD() and FM_PORT_DetachPCD()
+*//***************************************************************************/
+t_Error FM_PORT_PcdCcModifyTree (t_Handle h_FmPort, t_Handle h_CcTree);
+
+/**************************************************************************//**
+ @Function FM_PORT_PcdKgBindSchemes
+
+ @Description These routines may be called for adding more schemes for the
+ port to be bound to. The selected schemes are not added,
+ just this specific port starts using them.
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] p_PortScheme A structure defining the list of schemes to be added.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init() and FM_PORT_SetPCD().
+*//***************************************************************************/
+t_Error FM_PORT_PcdKgBindSchemes (t_Handle h_FmPort, t_FmPcdPortSchemesParams *p_PortScheme);
+
+/**************************************************************************//**
+ @Function FM_PORT_PcdKgUnbindSchemes
+
+ @Description These routines may be called for adding more schemes for the
+ port to be bound to. The selected schemes are not removed or invalidated,
+ just this specific port stops using them.
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] p_PortScheme A structure defining the list of schemes to be added.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init() and FM_PORT_SetPCD().
+*//***************************************************************************/
+t_Error FM_PORT_PcdKgUnbindSchemes (t_Handle h_FmPort, t_FmPcdPortSchemesParams *p_PortScheme);
+
+/**************************************************************************//**
+ @Function FM_PORT_PcdPrsModifyStartOffset
+
+ @Description Runtime change of the parser start offset within the header.
+ The routine may not be called while port
+ receives packets using the PCD functionalities, therefore port must be first detached
+ from the PCD, only than the routine may be called, and than port be attached to PCD again.
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] p_FmPcdPrsStart A structure of parameters for defining the
+ start point for the parser.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init(), FM_PORT_SetPCD() and FM_PORT_DetatchPCD().
+*//***************************************************************************/
+t_Error FM_PORT_PcdPrsModifyStartOffset (t_Handle h_FmPort, t_FmPcdPrsStart *p_FmPcdPrsStart);
+
+/**************************************************************************//**
+ @Function FM_PORT_GetIPv4OptionsCount
+
+ @Description TODO
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[out] p_Ipv4OptionsCount will hold the counter value
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init()
+*//***************************************************************************/
+t_Error FM_PORT_GetIPv4OptionsCount(t_Handle h_FmPort, uint32_t *p_Ipv4OptionsCount);
+
+/** @} */ /* end of FM_PORT_pcd_runtime_control_grp group */
+/** @} */ /* end of FM_PORT_runtime_control_grp group */
+
+
+/**************************************************************************//**
+ @Group FM_PORT_runtime_data_grp FM Port Runtime Data-path Unit
+
+ @Description FM Port Runtime data unit API functions, definitions and enums.
+ This API is valid only if working in Independent-Mode.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Function FM_PORT_ImTx
+
+ @Description Tx function, called to transmit a data buffer on the port.
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+ @Param[in] p_Data A pointer to an LCP data buffer.
+ @Param[in] length Size of data for transmission.
+ @Param[in] lastBuffer Buffer position - TRUE for the last buffer
+ of a frame, including a single buffer frame
+ @Param[in] h_BufContext A handle of the user acossiated with this buffer
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+ NOTE - This routine can be used only when working in
+ Independent-Mode mode.
+*//***************************************************************************/
+t_Error FM_PORT_ImTx( t_Handle h_FmPort,
+ uint8_t *p_Data,
+ uint16_t length,
+ bool lastBuffer,
+ t_Handle h_BufContext);
+
+/**************************************************************************//**
+ @Function FM_PORT_ImTxConf
+
+ @Description Tx port confirmation routine, optional, may be called to verify
+ transmission of all frames. The procedure performed by this
+ routine will be performed automatically on next buffer transmission,
+ but if desired, calling this routine will invoke this action on
+ demand.
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+
+ @Cautions Allowed only following FM_PORT_Init().
+ NOTE - This routine can be used only when working in
+ Independent-Mode mode.
+*//***************************************************************************/
+void FM_PORT_ImTxConf(t_Handle h_FmPort);
+
+/**************************************************************************//**
+ @Function FM_PORT_ImRx
+
+ @Description Rx function, may be called to poll for received buffers.
+ Normally, Rx process is invoked by the driver on Rx interrupt.
+ Alternatively, this routine may be called on demand.
+
+ @Param[in] h_FmPort A handle to a FM Port module.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_PORT_Init().
+ NOTE - This routine can be used only when working in
+ Independent-Mode mode.
+*//***************************************************************************/
+t_Error FM_PORT_ImRx(t_Handle h_FmPort);
+
+/** @} */ /* end of FM_PORT_runtime_data_grp group */
+/** @} */ /* end of FM_PORT_grp group */
+/** @} */ /* end of FM_grp group */
+
+
+
+#ifdef NCSW_BACKWARD_COMPATIBLE_API
+#define FM_PORT_ConfigTxFifoDeqPipelineDepth FM_PORT_ConfigFifoDeqPipelineDepth
+#endif /* NCSW_BACKWARD_COMPATIBLE_API */
+
+
+#endif /* __FM_PORT_EXT */
diff --git a/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_rtc_ext.h b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_rtc_ext.h
new file mode 100644
index 0000000..315405c
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_rtc_ext.h
@@ -0,0 +1,593 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File fm_rtc_ext.h
+
+ @Description External definitions and API for FM RTC IEEE1588 Timer Module.
+
+ @Cautions None.
+*//***************************************************************************/
+
+#ifndef __FM_RTC_EXT_H__
+#define __FM_RTC_EXT_H__
+
+
+#include "error_ext.h"
+#include "std_ext.h"
+#include "fsl_fman_rtc.h"
+
+/**************************************************************************//**
+
+ @Group FM_grp Frame Manager API
+
+ @Description FM API functions, definitions and enums
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group fm_rtc_grp FM RTC
+
+ @Description FM RTC functions, definitions and enums.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group fm_rtc_init_grp FM RTC Initialization Unit
+
+ @Description FM RTC initialization API.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Description FM RTC Alarm Polarity Options.
+*//***************************************************************************/
+typedef enum e_FmRtcAlarmPolarity
+{
+ e_FM_RTC_ALARM_POLARITY_ACTIVE_HIGH = E_FMAN_RTC_ALARM_POLARITY_ACTIVE_HIGH, /**< Active-high output polarity */
+ e_FM_RTC_ALARM_POLARITY_ACTIVE_LOW = E_FMAN_RTC_ALARM_POLARITY_ACTIVE_LOW /**< Active-low output polarity */
+} e_FmRtcAlarmPolarity;
+
+/**************************************************************************//**
+ @Description FM RTC Trigger Polarity Options.
+*//***************************************************************************/
+typedef enum e_FmRtcTriggerPolarity
+{
+ e_FM_RTC_TRIGGER_ON_RISING_EDGE = E_FMAN_RTC_TRIGGER_ON_RISING_EDGE, /**< Trigger on rising edge */
+ e_FM_RTC_TRIGGER_ON_FALLING_EDGE = E_FMAN_RTC_TRIGGER_ON_FALLING_EDGE /**< Trigger on falling edge */
+} e_FmRtcTriggerPolarity;
+
+/**************************************************************************//**
+ @Description IEEE1588 Timer Module FM RTC Optional Clock Sources.
+*//***************************************************************************/
+typedef enum e_FmSrcClock
+{
+ e_FM_RTC_SOURCE_CLOCK_EXTERNAL = E_FMAN_RTC_SOURCE_CLOCK_EXTERNAL, /**< external high precision timer reference clock */
+ e_FM_RTC_SOURCE_CLOCK_SYSTEM = E_FMAN_RTC_SOURCE_CLOCK_SYSTEM, /**< MAC system clock */
+ e_FM_RTC_SOURCE_CLOCK_OSCILATOR = E_FMAN_RTC_SOURCE_CLOCK_OSCILATOR /**< RTC clock oscilator */
+}e_FmSrcClk;
+
+/**************************************************************************//**
+ @Description FM RTC configuration parameters structure.
+
+ This structure should be passed to FM_RTC_Config().
+*//***************************************************************************/
+typedef struct t_FmRtcParams
+{
+ t_Handle h_Fm; /**< FM Handle*/
+ uintptr_t baseAddress; /**< Base address of FM RTC registers */
+ t_Handle h_App; /**< A handle to an application layer object; This handle will
+ be passed by the driver upon calling the above callbacks */
+} t_FmRtcParams;
+
+
+/**************************************************************************//**
+ @Function FM_RTC_Config
+
+ @Description Configures the FM RTC module according to user's parameters.
+
+ The driver assigns default values to some FM RTC parameters.
+ These parameters can be overwritten using the advanced
+ configuration routines.
+
+ @Param[in] p_FmRtcParam - FM RTC configuration parameters.
+
+ @Return Handle to the new FM RTC object; NULL pointer on failure.
+
+ @Cautions None
+*//***************************************************************************/
+t_Handle FM_RTC_Config(t_FmRtcParams *p_FmRtcParam);
+
+/**************************************************************************//**
+ @Function FM_RTC_Init
+
+ @Description Initializes the FM RTC driver and hardware.
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously created using FM_RTC_Config().
+*//***************************************************************************/
+t_Error FM_RTC_Init(t_Handle h_FmRtc);
+
+/**************************************************************************//**
+ @Function FM_RTC_Free
+
+ @Description Frees the FM RTC object and all allocated resources.
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously created using FM_RTC_Config().
+*//***************************************************************************/
+t_Error FM_RTC_Free(t_Handle h_FmRtc);
+
+
+/**************************************************************************//**
+ @Group fm_rtc_adv_config_grp FM RTC Advanced Configuration Unit
+
+ @Description FM RTC advanced configuration functions.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Function FM_RTC_ConfigPeriod
+
+ @Description Configures the period of the timestamp if different than
+ default [DEFAULT_clockPeriod].
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+ @Param[in] period - Period in nano-seconds.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously created using FM_RTC_Config().
+*//***************************************************************************/
+t_Error FM_RTC_ConfigPeriod(t_Handle h_FmRtc, uint32_t period);
+
+/**************************************************************************//**
+ @Function FM_RTC_ConfigSourceClock
+
+ @Description Configures the source clock of the RTC.
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+ @Param[in] srcClk - Source clock selection.
+ @Param[in] freqInMhz - the source-clock frequency (in MHz).
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously created using FM_RTC_Config().
+*//***************************************************************************/
+t_Error FM_RTC_ConfigSourceClock(t_Handle h_FmRtc,
+ e_FmSrcClk srcClk,
+ uint32_t freqInMhz);
+
+/**************************************************************************//**
+ @Function FM_RTC_ConfigPulseRealignment
+
+ @Description Configures the RTC to automatic FIPER pulse realignment in
+ response to timer adjustments [DEFAULT_pulseRealign]
+
+ In this mode, the RTC clock is identical to the source clock.
+ This feature can be useful when the system contains an external
+ RTC with inherent frequency compensation.
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+ @Param[in] enable - TRUE to enable automatic realignment.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously created using FM_RTC_Config().
+*//***************************************************************************/
+t_Error FM_RTC_ConfigPulseRealignment(t_Handle h_FmRtc, bool enable);
+
+/**************************************************************************//**
+ @Function FM_RTC_ConfigFrequencyBypass
+
+ @Description Configures the RTC to bypass the frequency compensation
+ mechanism. [DEFAULT_bypass]
+
+ In this mode, the RTC clock is identical to the source clock.
+ This feature can be useful when the system contains an external
+ RTC with inherent frequency compensation.
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+ @Param[in] enabled - TRUE to bypass frequency compensation;
+ FALSE otherwise.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously created using FM_RTC_Config().
+*//***************************************************************************/
+t_Error FM_RTC_ConfigFrequencyBypass(t_Handle h_FmRtc, bool enabled);
+
+/**************************************************************************//**
+ @Function FM_RTC_ConfigInvertedInputClockPhase
+
+ @Description Configures the RTC to invert the source clock phase on input.
+ [DEFAULT_invertInputClkPhase]
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+ @Param[in] inverted - TRUE to invert the source clock phase on input.
+ FALSE otherwise.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously created using FM_RTC_Config().
+*//***************************************************************************/
+t_Error FM_RTC_ConfigInvertedInputClockPhase(t_Handle h_FmRtc, bool inverted);
+
+/**************************************************************************//**
+ @Function FM_RTC_ConfigInvertedOutputClockPhase
+
+ @Description Configures the RTC to invert the output clock phase.
+ [DEFAULT_invertOutputClkPhase]
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+ @Param[in] inverted - TRUE to invert the output clock phase.
+ FALSE otherwise.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously created using FM_RTC_Config().
+*//***************************************************************************/
+t_Error FM_RTC_ConfigInvertedOutputClockPhase(t_Handle h_FmRtc, bool inverted);
+
+/**************************************************************************//**
+ @Function FM_RTC_ConfigOutputClockDivisor
+
+ @Description Configures the divisor for generating the output clock from
+ the RTC clock. [DEFAULT_outputClockDivisor]
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+ @Param[in] divisor - Divisor for generation of the output clock.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously created using FM_RTC_Config().
+*//***************************************************************************/
+t_Error FM_RTC_ConfigOutputClockDivisor(t_Handle h_FmRtc, uint16_t divisor);
+
+/**************************************************************************//**
+ @Function FM_RTC_ConfigAlarmPolarity
+
+ @Description Configures the polarity (active-high/active-low) of a specific
+ alarm signal. [DEFAULT_alarmPolarity]
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+ @Param[in] alarmId - Alarm ID.
+ @Param[in] alarmPolarity - Alarm polarity.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously created using FM_RTC_Config().
+*//***************************************************************************/
+t_Error FM_RTC_ConfigAlarmPolarity(t_Handle h_FmRtc,
+ uint8_t alarmId,
+ e_FmRtcAlarmPolarity alarmPolarity);
+
+/**************************************************************************//**
+ @Function FM_RTC_ConfigExternalTriggerPolarity
+
+ @Description Configures the polarity (rising/falling edge) of a specific
+ external trigger signal. [DEFAULT_triggerPolarity]
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+ @Param[in] triggerId - Trigger ID.
+ @Param[in] triggerPolarity - Trigger polarity.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously created using FM_RTC_Config().
+*//***************************************************************************/
+t_Error FM_RTC_ConfigExternalTriggerPolarity(t_Handle h_FmRtc,
+ uint8_t triggerId,
+ e_FmRtcTriggerPolarity triggerPolarity);
+
+/** @} */ /* end of fm_rtc_adv_config_grp */
+/** @} */ /* end of fm_rtc_init_grp */
+
+
+/**************************************************************************//**
+ @Group fm_rtc_control_grp FM RTC Control Unit
+
+ @Description FM RTC runtime control API.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Function t_FmRtcExceptionsCallback
+
+ @Description Exceptions user callback routine, used for RTC different mechanisms.
+
+ @Param[in] h_App - User's application descriptor.
+ @Param[in] id - source id.
+*//***************************************************************************/
+typedef void (t_FmRtcExceptionsCallback) ( t_Handle h_App, uint8_t id);
+
+/**************************************************************************//**
+ @Description FM RTC alarm parameters.
+*//***************************************************************************/
+typedef struct t_FmRtcAlarmParams {
+ uint8_t alarmId; /**< 0 or 1 */
+ uint64_t alarmTime; /**< In nanoseconds, the time when the alarm
+ should go off - must be a multiple of
+ the RTC period */
+ t_FmRtcExceptionsCallback *f_AlarmCallback; /**< This routine will be called when RTC
+ reaches alarmTime */
+ bool clearOnExpiration; /**< TRUE to turn off the alarm once expired. */
+} t_FmRtcAlarmParams;
+
+/**************************************************************************//**
+ @Description FM RTC Periodic Pulse parameters.
+*//***************************************************************************/
+typedef struct t_FmRtcPeriodicPulseParams {
+ uint8_t periodicPulseId; /**< 0 or 1 */
+ uint64_t periodicPulsePeriod; /**< In Nanoseconds. Must be
+ a multiple of the RTC period */
+ t_FmRtcExceptionsCallback *f_PeriodicPulseCallback; /**< This routine will be called every
+ periodicPulsePeriod. */
+} t_FmRtcPeriodicPulseParams;
+
+/**************************************************************************//**
+ @Description FM RTC Periodic Pulse parameters.
+*//***************************************************************************/
+typedef struct t_FmRtcExternalTriggerParams {
+ uint8_t externalTriggerId; /**< 0 or 1 */
+ bool usePulseAsInput; /**< Use the pulse interrupt instead of
+ an external signal */
+ t_FmRtcExceptionsCallback *f_ExternalTriggerCallback; /**< This routine will be called every
+ periodicPulsePeriod. */
+} t_FmRtcExternalTriggerParams;
+
+
+/**************************************************************************//**
+ @Function FM_RTC_Enable
+
+ @Description Enable the RTC (time count is started).
+
+ The user can select to resume the time count from previous
+ point, or to restart the time count.
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+ @Param[in] resetClock - Restart the time count from zero.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init().
+*//***************************************************************************/
+t_Error FM_RTC_Enable(t_Handle h_FmRtc, bool resetClock);
+
+/**************************************************************************//**
+ @Function FM_RTC_Disable
+
+ @Description Disables the RTC (time count is stopped).
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init().
+*//***************************************************************************/
+t_Error FM_RTC_Disable(t_Handle h_FmRtc);
+
+/**************************************************************************//**
+ @Function FM_RTC_SetClockOffset
+
+ @Description Sets the clock offset (usually relative to another clock).
+
+ The user can pass a negative offset value.
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+ @Param[in] offset - New clock offset (in nanoseconds).
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init().
+*//***************************************************************************/
+t_Error FM_RTC_SetClockOffset(t_Handle h_FmRtc, int64_t offset);
+
+/**************************************************************************//**
+ @Function FM_RTC_SetAlarm
+
+ @Description Schedules an alarm event to a given RTC time.
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+ @Param[in] p_FmRtcAlarmParams - Alarm parameters.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init().
+ Must be called only prior to FM_RTC_Enable().
+*//***************************************************************************/
+t_Error FM_RTC_SetAlarm(t_Handle h_FmRtc, t_FmRtcAlarmParams *p_FmRtcAlarmParams);
+
+/**************************************************************************//**
+ @Function FM_RTC_SetPeriodicPulse
+
+ @Description Sets a periodic pulse.
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+ @Param[in] p_FmRtcPeriodicPulseParams - Periodic pulse parameters.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init().
+ Must be called only prior to FM_RTC_Enable().
+*//***************************************************************************/
+t_Error FM_RTC_SetPeriodicPulse(t_Handle h_FmRtc, t_FmRtcPeriodicPulseParams *p_FmRtcPeriodicPulseParams);
+
+/**************************************************************************//**
+ @Function FM_RTC_ClearPeriodicPulse
+
+ @Description Clears a periodic pulse.
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+ @Param[in] periodicPulseId - Periodic pulse id.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init().
+*//***************************************************************************/
+t_Error FM_RTC_ClearPeriodicPulse(t_Handle h_FmRtc, uint8_t periodicPulseId);
+
+/**************************************************************************//**
+ @Function FM_RTC_SetExternalTrigger
+
+ @Description Sets an external trigger indication and define a callback
+ routine to be called on such event.
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+ @Param[in] p_FmRtcExternalTriggerParams - External Trigger parameters.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init().
+*//***************************************************************************/
+t_Error FM_RTC_SetExternalTrigger(t_Handle h_FmRtc, t_FmRtcExternalTriggerParams *p_FmRtcExternalTriggerParams);
+
+/**************************************************************************//**
+ @Function FM_RTC_ClearExternalTrigger
+
+ @Description Clears external trigger indication.
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+ @Param[in] id - External Trigger id.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init().
+*//***************************************************************************/
+t_Error FM_RTC_ClearExternalTrigger(t_Handle h_FmRtc, uint8_t id);
+
+/**************************************************************************//**
+ @Function FM_RTC_GetExternalTriggerTimeStamp
+
+ @Description Reads the External Trigger TimeStamp.
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+ @Param[in] triggerId - External Trigger id.
+ @Param[out] p_TimeStamp - External Trigger timestamp (in nanoseconds).
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init().
+*//***************************************************************************/
+t_Error FM_RTC_GetExternalTriggerTimeStamp(t_Handle h_FmRtc,
+ uint8_t triggerId,
+ uint64_t *p_TimeStamp);
+
+/**************************************************************************//**
+ @Function FM_RTC_GetCurrentTime
+
+ @Description Returns the current RTC time.
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+ @Param[out] p_Ts - returned time stamp (in nanoseconds).
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init().
+*//***************************************************************************/
+t_Error FM_RTC_GetCurrentTime(t_Handle h_FmRtc, uint64_t *p_Ts);
+
+/**************************************************************************//**
+ @Function FM_RTC_SetCurrentTime
+
+ @Description Sets the current RTC time.
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+ @Param[in] ts - The new time stamp (in nanoseconds).
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init().
+*//***************************************************************************/
+t_Error FM_RTC_SetCurrentTime(t_Handle h_FmRtc, uint64_t ts);
+
+/**************************************************************************//**
+ @Function FM_RTC_GetFreqCompensation
+
+ @Description Retrieves the frequency compensation value
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+ @Param[out] p_Compensation - A pointer to the returned value of compensation.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init().
+*//***************************************************************************/
+t_Error FM_RTC_GetFreqCompensation(t_Handle h_FmRtc, uint32_t *p_Compensation);
+
+/**************************************************************************//**
+ @Function FM_RTC_SetFreqCompensation
+
+ @Description Sets a new frequency compensation value.
+
+ @Param[in] h_FmRtc - Handle to FM RTC object.
+ @Param[in] freqCompensation - The new frequency compensation value to set.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions h_FmRtc must have been previously initialized using FM_RTC_Init().
+*//***************************************************************************/
+t_Error FM_RTC_SetFreqCompensation(t_Handle h_FmRtc, uint32_t freqCompensation);
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+/**************************************************************************//**
+ @Function FM_RTC_DumpRegs
+
+ @Description Dumps all FM registers
+
+ @Param[in] h_FmRtc A handle to an FM RTC Module.
+
+ @Return E_OK on success;
+
+ @Cautions Allowed only FM_Init().
+*//***************************************************************************/
+t_Error FM_RTC_DumpRegs(t_Handle h_FmRtc);
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+/** @} */ /* end of fm_rtc_control_grp */
+/** @} */ /* end of fm_rtc_grp */
+/** @} */ /* end of FM_grp group */
+
+
+#endif /* __FM_RTC_EXT_H__ */
diff --git a/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_vsp_ext.h b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_vsp_ext.h
new file mode 100644
index 0000000..f9aed03
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_vsp_ext.h
@@ -0,0 +1,411 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File fm_vsp_ext.h
+
+ @Description FM Virtual Storage-Profile ...
+*//***************************************************************************/
+#ifndef __FM_VSP_EXT_H
+#define __FM_VSP_EXT_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "string_ext.h"
+#include "debug_ext.h"
+
+#include "fm_ext.h"
+
+
+/**************************************************************************//**
+
+ @Group FM_grp Frame Manager API
+
+ @Description FM API functions, definitions and enums
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group FM_VSP_grp FM Virtual-Storage-Profile
+
+ @Description FM Virtual-Storage-Profile API
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group FM_VSP_init_grp FM VSP Initialization Unit
+
+ @Description FM VSP initialization API.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Description Virtual Storage Profile
+*//***************************************************************************/
+typedef struct t_FmVspParams {
+ t_Handle h_Fm; /**< A handle to the FM object this VSP related to */
+ t_FmExtPools extBufPools; /**< Which external buffer pools are used
+ (up to FM_PORT_MAX_NUM_OF_EXT_POOLS), and their sizes.
+ parameter associated with Rx / OP port */
+ uint16_t liodnOffset; /**< VSP's LIODN offset */
+ struct {
+ e_FmPortType portType; /**< Port type */
+ uint8_t portId; /**< Port Id - relative to type */
+ } portParams;
+ uint8_t relativeProfileId; /**< VSP Id - relative to VSP's range
+ defined in relevant FM object */
+} t_FmVspParams;
+
+
+/**************************************************************************//**
+ @Function FM_VSP_Config
+
+ @Description Creates descriptor for the FM VSP module.
+
+ The routine returns a handle (descriptor) to the FM VSP object.
+ This descriptor must be passed as first parameter to all other
+ FM VSP function calls.
+
+ No actual initialization or configuration of FM hardware is
+ done by this routine.
+
+@Param[in] p_FmVspParams Pointer to data structure of parameters
+
+ @Retval Handle to FM VSP object, or NULL for Failure.
+*//***************************************************************************/
+t_Handle FM_VSP_Config(t_FmVspParams *p_FmVspParams);
+
+/**************************************************************************//**
+ @Function FM_VSP_Init
+
+ @Description Initializes the FM VSP module
+
+ @Param[in] h_FmVsp - FM VSP module descriptor
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_VSP_Init(t_Handle h_FmVsp);
+
+/**************************************************************************//**
+ @Function FM_VSP_Free
+
+ @Description Frees all resources that were assigned to FM VSP module.
+
+ Calling this routine invalidates the descriptor.
+
+ @Param[in] h_FmVsp - FM VSP module descriptor
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error FM_VSP_Free(t_Handle h_FmVsp);
+
+
+/**************************************************************************//**
+ @Group FM_VSP_adv_config_grp FM VSP Advanced Configuration Unit
+
+ @Description FM VSP advanced configuration functions.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Function FM_VSP_ConfigBufferPrefixContent
+
+ @Description Defines the structure, size and content of the application buffer.
+
+ The prefix will
+ In VSPs defined for Tx ports, if 'passPrsResult', the application
+ should set a value to their offsets in the prefix of
+ the FM will save the first 'privDataSize', than,
+ depending on 'passPrsResult' and 'passTimeStamp', copy parse result
+ and timeStamp, and the packet itself (in this order), to the
+ application buffer, and to offset.
+
+ Calling this routine changes the buffer margins definitions
+ in the internal driver data base from its default
+ configuration: Data size: [DEFAULT_FM_SP_bufferPrefixContent_privDataSize]
+ Pass Parser result: [DEFAULT_FM_SP_bufferPrefixContent_passPrsResult].
+ Pass timestamp: [DEFAULT_FM_SP_bufferPrefixContent_passTimeStamp].
+
+ @Param[in] h_FmVsp A handle to a FM VSP module.
+ @Param[in,out] p_FmBufferPrefixContent A structure of parameters describing the
+ structure of the buffer.
+ Out parameter: Start margin - offset
+ of data from start of external buffer.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init().
+*//***************************************************************************/
+t_Error FM_VSP_ConfigBufferPrefixContent(t_Handle h_FmVsp,
+ t_FmBufferPrefixContent *p_FmBufferPrefixContent);
+
+/**************************************************************************//**
+ @Function FM_VSP_ConfigDmaSwapData
+
+ @Description Calling this routine changes the DMA swap data parameter
+ in the internal driver data base from its default
+ configuration [DEFAULT_FM_SP_dmaSwapData]
+
+ @Param[in] h_FmVsp A handle to a FM VSP module.
+ @Param[in] swapData New selection
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init().
+*//***************************************************************************/
+t_Error FM_VSP_ConfigDmaSwapData(t_Handle h_FmVsp, e_FmDmaSwapOption swapData);
+
+/**************************************************************************//**
+ @Function FM_VSP_ConfigDmaIcCacheAttr
+
+ @Description Calling this routine changes the internal context cache
+ attribute parameter in the internal driver data base
+ from its default configuration [DEFAULT_FM_SP_dmaIntContextCacheAttr]
+
+ @Param[in] h_FmVsp A handle to a FM VSP module.
+ @Param[in] intContextCacheAttr New selection
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init().
+*//***************************************************************************/
+t_Error FM_VSP_ConfigDmaIcCacheAttr(t_Handle h_FmVsp,
+ e_FmDmaCacheOption intContextCacheAttr);
+
+/**************************************************************************//**
+ @Function FM_VSP_ConfigDmaHdrAttr
+
+ @Description Calling this routine changes the header cache
+ attribute parameter in the internal driver data base
+ from its default configuration [DEFAULT_FM_SP_dmaHeaderCacheAttr]
+
+ @Param[in] h_FmVsp A handle to a FM VSP module.
+ @Param[in] headerCacheAttr New selection
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init().
+*//***************************************************************************/
+t_Error FM_VSP_ConfigDmaHdrAttr(t_Handle h_FmVsp, e_FmDmaCacheOption headerCacheAttr);
+
+/**************************************************************************//**
+ @Function FM_VSP_ConfigDmaScatterGatherAttr
+
+ @Description Calling this routine changes the scatter gather cache
+ attribute parameter in the internal driver data base
+ from its default configuration [DEFAULT_FM_SP_dmaScatterGatherCacheAttr]
+
+ @Param[in] h_FmVsp A handle to a FM VSP module.
+ @Param[in] scatterGatherCacheAttr New selection
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init().
+*//***************************************************************************/
+t_Error FM_VSP_ConfigDmaScatterGatherAttr(t_Handle h_FmVsp,
+ e_FmDmaCacheOption scatterGatherCacheAttr);
+
+/**************************************************************************//**
+ @Function FM_VSP_ConfigDmaWriteOptimize
+
+ @Description Calling this routine changes the write optimization
+ parameter in the internal driver data base
+ from its default configuration: optimize = [DEFAULT_FM_SP_dmaWriteOptimize]
+
+ @Param[in] h_FmVsp A handle to a FM VSP module.
+ @Param[in] optimize TRUE to enable optimization, FALSE for normal operation
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init().
+*//***************************************************************************/
+t_Error FM_VSP_ConfigDmaWriteOptimize(t_Handle h_FmVsp, bool optimize);
+
+/**************************************************************************//**
+ @Function FM_VSP_ConfigNoScatherGather
+
+ @Description Calling this routine changes the possibility to receive S/G frame
+ in the internal driver data base
+ from its default configuration: optimize = [DEFAULT_FM_SP_noScatherGather]
+
+ @Param[in] h_FmVsp A handle to a FM VSP module.
+ @Param[in] noScatherGather TRUE to operate without scatter/gather capability.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init().
+*//***************************************************************************/
+t_Error FM_VSP_ConfigNoScatherGather(t_Handle h_FmVsp, bool noScatherGather);
+
+/**************************************************************************//**
+ @Function FM_VSP_ConfigPoolDepletion
+
+ @Description Calling this routine enables pause frame generation depending on the
+ depletion status of BM pools. It also defines the conditions to activate
+ this functionality. By default, this functionality is disabled.
+
+ @Param[in] h_FmVsp A handle to a FM VSP module.
+ @Param[in] p_BufPoolDepletion A structure of pool depletion parameters
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init().
+*//***************************************************************************/
+t_Error FM_VSP_ConfigPoolDepletion(t_Handle h_FmVsp, t_FmBufPoolDepletion *p_BufPoolDepletion);
+
+/**************************************************************************//**
+ @Function FM_VSP_ConfigBackupPools
+
+ @Description Calling this routine allows the configuration of some of the BM pools
+ defined for this port as backup pools.
+ A pool configured to be a backup pool will be used only if all other
+ enabled non-backup pools are depleted.
+
+ @Param[in] h_FmVsp A handle to a FM VSP module.
+ @Param[in] p_BackupBmPools An array of pool id's. All pools specified here will
+ be defined as backup pools.
+
+ @Return E_OK on success; Error code otherwise.
+
+ @Cautions Allowed only following FM_VSP_Config() and before FM_VSP_Init().
+*//***************************************************************************/
+t_Error FM_VSP_ConfigBackupPools(t_Handle h_FmVsp, t_FmBackupBmPools *p_BackupBmPools);
+
+/** @} */ /* end of FM_VSP_adv_config_grp group */
+/** @} */ /* end of FM_VSP_init_grp group */
+
+
+/**************************************************************************//**
+ @Group FM_VSP_control_grp FM VSP Control Unit
+
+ @Description FM VSP runtime control API.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Function FM_VSP_GetBufferDataOffset
+
+ @Description Relevant for Rx ports.
+ Returns the data offset from the beginning of the data buffer
+
+ @Param[in] h_FmVsp - FM PORT module descriptor
+
+ @Return data offset.
+
+ @Cautions Allowed only following FM_VSP_Init().
+*//***************************************************************************/
+uint32_t FM_VSP_GetBufferDataOffset(t_Handle h_FmVsp);
+
+/**************************************************************************//**
+ @Function FM_VSP_GetBufferICInfo
+
+ @Description Returns the Internal Context offset from the beginning of the data buffer
+
+ @Param[in] h_FmVsp - FM PORT module descriptor
+ @Param[in] p_Data - A pointer to the data buffer.
+
+ @Return Internal context info pointer on success, NULL if 'allOtherInfo' was not
+ configured for this port.
+
+ @Cautions Allowed only following FM_VSP_Init().
+*//***************************************************************************/
+uint8_t * FM_VSP_GetBufferICInfo(t_Handle h_FmVsp, char *p_Data);
+
+/**************************************************************************//**
+ @Function FM_VSP_GetBufferPrsResult
+
+ @Description Returns the pointer to the parse result in the data buffer.
+ In Rx ports this is relevant after reception, if parse
+ result is configured to be part of the data passed to the
+ application. For non Rx ports it may be used to get the pointer
+ of the area in the buffer where parse result should be
+ initialized - if so configured.
+ See FM_VSP_ConfigBufferPrefixContent for data buffer prefix
+ configuration.
+
+ @Param[in] h_FmVsp - FM PORT module descriptor
+ @Param[in] p_Data - A pointer to the data buffer.
+
+ @Return Parse result pointer on success, NULL if parse result was not
+ configured for this port.
+
+ @Cautions Allowed only following FM_VSP_Init().
+*//***************************************************************************/
+t_FmPrsResult * FM_VSP_GetBufferPrsResult(t_Handle h_FmVsp, char *p_Data);
+
+/**************************************************************************//**
+ @Function FM_VSP_GetBufferTimeStamp
+
+ @Description Returns the time stamp in the data buffer.
+ Relevant for Rx ports for getting the buffer time stamp.
+ See FM_VSP_ConfigBufferPrefixContent for data buffer prefix
+ configuration.
+
+ @Param[in] h_FmVsp - FM PORT module descriptor
+ @Param[in] p_Data - A pointer to the data buffer.
+
+ @Return A pointer to the hash result on success, NULL otherwise.
+
+ @Cautions Allowed only following FM_VSP_Init().
+*//***************************************************************************/
+uint64_t * FM_VSP_GetBufferTimeStamp(t_Handle h_FmVsp, char *p_Data);
+
+/**************************************************************************//**
+ @Function FM_VSP_GetBufferHashResult
+
+ @Description Given a data buffer, on the condition that hash result was defined
+ as a part of the buffer content (see FM_VSP_ConfigBufferPrefixContent)
+ this routine will return the pointer to the hash result location in the
+ buffer prefix.
+
+ @Param[in] h_FmVsp - FM PORT module descriptor
+ @Param[in] p_Data - A pointer to the data buffer.
+
+ @Return A pointer to the hash result on success, NULL otherwise.
+
+ @Cautions Allowed only following FM_VSP_Init().
+*//***************************************************************************/
+uint8_t * FM_VSP_GetBufferHashResult(t_Handle h_FmVsp, char *p_Data);
+
+
+/** @} */ /* end of FM_VSP_control_grp group */
+/** @} */ /* end of FM_VSP_grp group */
+/** @} */ /* end of FM_grp group */
+
+
+#endif /* __FM_VSP_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/Peripherals/mii_acc_ext.h b/drivers/net/ethernet/freescale/fman/inc/Peripherals/mii_acc_ext.h
new file mode 100644
index 0000000..f635d3c
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/Peripherals/mii_acc_ext.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+#ifndef __MII_ACC_EXT_H
+#define __MII_ACC_EXT_H
+
+
+/**************************************************************************//**
+ @Function MII_ReadPhyReg
+
+ @Description This routine is called to read a specified PHY
+ register value.
+
+ @Param[in] h_MiiAccess - Handle to MII configuration access registers
+ @Param[in] phyAddr - PHY address (0-31).
+ @Param[in] reg - PHY register to read
+ @Param[out] p_Data - Gets the register value.
+
+ @Return Always zero (success).
+*//***************************************************************************/
+int MII_ReadPhyReg(t_Handle h_MiiAccess,
+ uint8_t phyAddr,
+ uint8_t reg,
+ uint16_t *p_Data);
+
+/**************************************************************************//**
+ @Function MII_WritePhyReg
+
+ @Description This routine is called to write data to a specified PHY
+ register.
+
+ @Param[in] h_MiiAccess - Handle to MII configuration access registers
+ @Param[in] phyAddr - PHY address (0-31).
+ @Param[in] reg - PHY register to write
+ @Param[in] data - Data to write in register.
+
+ @Return Always zero (success).
+*//***************************************************************************/
+int MII_WritePhyReg(t_Handle h_MiiAccess,
+ uint8_t phyAddr,
+ uint8_t reg,
+ uint16_t data);
+
+
+#endif /* __MII_ACC_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/core_ext.h b/drivers/net/ethernet/freescale/fman/inc/core_ext.h
new file mode 100644
index 0000000..42174cf
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/core_ext.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File core_ext.h
+
+ @Description Generic interface to basic core operations.
+
+ The system integrator must ensure that this interface is
+ mapped to a specific core implementation, by including the
+ appropriate header file.
+*//***************************************************************************/
+#ifndef __CORE_EXT_H
+#define __CORE_EXT_H
+
+
+#ifdef NCSW_PPC_CORE
+#include "ppc_ext.h"
+#elif defined(NCSW_VXWORKS)
+#include "core_vxw_ext.h"
+#else
+#error "Core is not defined!"
+#endif /* NCSW_CORE */
+
+#if (!defined(CORE_IS_LITTLE_ENDIAN) && !defined(CORE_IS_BIG_ENDIAN))
+#error "Must define core as little-endian or big-endian!"
+#endif /* (!defined(CORE_IS_LITTLE_ENDIAN) && ... */
+
+#ifndef CORE_CACHELINE_SIZE
+#error "Must define the core cache-line size!"
+#endif /* !CORE_CACHELINE_SIZE */
+
+
+/**************************************************************************//**
+ @Function CORE_GetId
+
+ @Description Returns the core ID in the system.
+
+ @Return Core ID.
+*//***************************************************************************/
+uint32_t CORE_GetId(void);
+
+/**************************************************************************//**
+ @Function CORE_MemoryBarrier
+
+ @Description This routine will cause the core to stop executing any commands
+ until all previous memory read/write commands are completely out
+ of the core's pipeline.
+
+ @Return None.
+*//***************************************************************************/
+void CORE_MemoryBarrier(void);
+#define fsl_mem_core_barrier() CORE_MemoryBarrier()
+
+#endif /* __CORE_EXT_H */
+
diff --git a/drivers/net/ethernet/freescale/fman/inc/cores/e500v2_ext.h b/drivers/net/ethernet/freescale/fman/inc/cores/e500v2_ext.h
new file mode 100644
index 0000000..e79b1dd
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/cores/e500v2_ext.h
@@ -0,0 +1,476 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File e500v2_ext.h
+
+ @Description E500 external definitions prototypes
+ This file is not included by the E500
+ source file as it is an assembly file. It is used
+ only for prototypes exposure, for inclusion
+ by user and other modules.
+*//***************************************************************************/
+
+#ifndef __E500V2_EXT_H
+#define __E500V2_EXT_H
+
+#include "std_ext.h"
+
+
+/* Layer 1 Cache Manipulations
+ *==============================
+ * Should not be called directly by the user.
+ */
+void L1DCache_Invalidate (void);
+void L1ICache_Invalidate(void);
+void L1DCache_Enable(void);
+void L1ICache_Enable(void);
+void L1DCache_Disable(void);
+void L1ICache_Disable(void);
+void L1DCache_Flush(void);
+void L1ICache_Flush(void);
+uint32_t L1ICache_IsEnabled(void);
+uint32_t L1DCache_IsEnabled(void);
+/*
+ *
+ */
+uint32_t L1DCache_LineLock(uint32_t addr);
+uint32_t L1ICache_LineLock(uint32_t addr);
+void L1Cache_BroadCastEnable(void);
+void L1Cache_BroadCastDisable(void);
+
+
+#define CORE_DCacheEnable E500_DCacheEnable
+#define CORE_ICacheEnable E500_ICacheEnable
+#define CORE_DCacheDisable E500_DCacheDisable
+#define CORE_ICacheDisable E500_ICacheDisable
+#define CORE_GetId E500_GetId
+#define CORE_TestAndSet E500_TestAndSet
+#define CORE_MemoryBarrier E500_MemoryBarrier
+#define CORE_InstructionSync E500_InstructionSync
+
+#define CORE_SetDozeMode E500_SetDozeMode
+#define CORE_SetNapMode E500_SetNapMode
+#define CORE_SetSleepMode E500_SetSleepMode
+#define CORE_SetJogMode E500_SetJogMode
+#define CORE_SetDeepSleepMode E500_SetDeepSleepMode
+
+#define CORE_RecoverDozeMode E500_RecoverDozeMode
+#define CORE_RecoverNapMode E500_RecoverNapMode
+#define CORE_RecoverSleepMode E500_RecoverSleepMode
+#define CORE_RecoverJogMode E500_RecoverJogMode
+
+void E500_SetDozeMode(void);
+void E500_SetNapMode(void);
+void E500_SetSleepMode(void);
+void E500_SetJogMode(void);
+t_Error E500_SetDeepSleepMode(uint32_t bptrAddress);
+
+void E500_RecoverDozeMode(void);
+void E500_RecoverNapMode(void);
+void E500_RecoverSleepMode(void);
+void E500_RecoverJogMode(void);
+
+
+/**************************************************************************//**
+ @Group E500_id E500 Application Programming Interface
+
+ @Description E500 API functions, definitions and enums
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group E500_init_grp E500 Initialization Unit
+
+ @Description E500 initialization unit API functions, definitions and enums
+
+ @{
+*//***************************************************************************/
+
+
+/**************************************************************************//**
+ @Function E500_DCacheEnable
+
+ @Description Enables the data cache for memory pages that are
+ not cache inhibited.
+
+ @Return None.
+*//***************************************************************************/
+void E500_DCacheEnable(void);
+
+/**************************************************************************//**
+ @Function E500_ICacheEnable
+
+ @Description Enables the instruction cache for memory pages that are
+ not cache inhibited.
+
+ @Return None.
+*//***************************************************************************/
+void E500_ICacheEnable(void);
+
+/**************************************************************************//**
+ @Function E500_DCacheDisable
+
+ @Description Disables the data cache.
+
+ @Return None.
+*//***************************************************************************/
+void E500_DCacheDisable(void);
+
+/**************************************************************************//**
+ @Function E500_ICacheDisable
+
+ @Description Disables the instruction cache.
+
+ @Return None.
+*//***************************************************************************/
+void E500_ICacheDisable(void);
+
+/**************************************************************************//**
+ @Function E500_DCacheFlush
+
+ @Description Flushes the data cache
+
+ @Return None.
+*//***************************************************************************/
+void E500_DCacheFlush(void);
+
+/**************************************************************************//**
+ @Function E500_ICacheFlush
+
+ @Description Flushes the instruction cache.
+
+ @Return None.
+*//***************************************************************************/
+void E500_ICacheFlush(void);
+
+/**************************************************************************//**
+ @Function E500_DCacheSetStashId
+
+ @Description Set Stash Id for data cache
+
+ @Param[in] stashId the stash id to be set.
+
+ @Return None.
+*//***************************************************************************/
+void E500_DCacheSetStashId(uint8_t stashId);
+
+/**************************************************************************//**
+ @Description E500mc L2 Cache Operation Mode
+*//***************************************************************************/
+typedef enum e_E500mcL2CacheMode
+{
+ e_L2_CACHE_MODE_DATA_ONLY = 0x00000001, /**< Cache data only */
+ e_L2_CACHE_MODE_INST_ONLY = 0x00000002, /**< Cache instructions only */
+ e_L2_CACHE_MODE_DATA_AND_INST = 0x00000003 /**< Cache data and instructions */
+} e_E500mcL2CacheMode;
+
+#if defined(CORE_E500MC) || defined(CORE_E5500)
+/**************************************************************************//**
+ @Function E500_L2CacheEnable
+
+ @Description Enables the cache for memory pages that are not cache inhibited.
+
+ @param[in] mode - L2 cache mode: data only, instruction only or instruction and data.
+
+ @Return None.
+
+ @Cautions This routine must be call only ONCE for both caches. I.e. it is
+ not possible to call this routine for i-cache and than to call
+ again for d-cache; The second call will override the first one.
+*//***************************************************************************/
+void E500_L2CacheEnable(e_E500mcL2CacheMode mode);
+
+/**************************************************************************//**
+ @Function E500_L2CacheDisable
+
+ @Description Disables the cache (data instruction or both).
+
+ @Return None.
+
+*//***************************************************************************/
+void E500_L2CacheDisable(void);
+
+/**************************************************************************//**
+ @Function E500_L2CacheFlush
+
+ @Description Flushes the cache.
+
+ @Return None.
+*//***************************************************************************/
+void E500_L2CacheFlush(void);
+
+/**************************************************************************//**
+ @Function E500_L2SetStashId
+
+ @Description Set Stash Id
+
+ @Param[in] stashId the stash id to be set.
+
+ @Return None.
+*//***************************************************************************/
+void E500_L2SetStashId(uint8_t stashId);
+#endif /* defined(CORE_E500MC) || defined(CORE_E5500) */
+
+#ifdef CORE_E6500
+/**************************************************************************//**
+ @Function E6500_L2CacheEnable
+
+ @Description Enables the cache for memory pages that are not cache inhibited.
+
+ @param[in] mode - L2 cache mode: support data & instruction only.
+
+ @Return None.
+
+ @Cautions This routine must be call only ONCE for both caches. I.e. it is
+ not possible to call this routine for i-cache and than to call
+ again for d-cache; The second call will override the first one.
+*//***************************************************************************/
+void E6500_L2CacheEnable(uintptr_t clusterBase);
+
+/**************************************************************************//**
+ @Function E6500_L2CacheDisable
+
+ @Description Disables the cache (data instruction or both).
+
+ @Return None.
+
+*//***************************************************************************/
+void E6500_L2CacheDisable(uintptr_t clusterBase);
+
+/**************************************************************************//**
+ @Function E6500_L2CacheFlush
+
+ @Description Flushes the cache.
+
+ @Return None.
+*//***************************************************************************/
+void E6500_L2CacheFlush(uintptr_t clusterBase);
+
+/**************************************************************************//**
+ @Function E6500_L2SetStashId
+
+ @Description Set Stash Id
+
+ @Param[in] stashId the stash id to be set.
+
+ @Return None.
+*//***************************************************************************/
+void E6500_L2SetStashId(uintptr_t clusterBase, uint8_t stashId);
+
+/**************************************************************************//**
+ @Function E6500_GetCcsrBase
+
+ @Description Obtain SoC CCSR base address
+
+ @Param[in] None.
+
+ @Return Physical CCSR base address.
+*//***************************************************************************/
+physAddress_t E6500_GetCcsrBase(void);
+#endif /* CORE_E6500 */
+
+/**************************************************************************//**
+ @Function E500_AddressBusStreamingEnable
+
+ @Description Enables address bus streaming on the CCB.
+
+ This setting, along with the ECM streaming configuration
+ parameters, enables address bus streaming on the CCB.
+
+ @Return None.
+*//***************************************************************************/
+void E500_AddressBusStreamingEnable(void);
+
+/**************************************************************************//**
+ @Function E500_AddressBusStreamingDisable
+
+ @Description Disables address bus streaming on the CCB.
+
+ @Return None.
+*//***************************************************************************/
+void E500_AddressBusStreamingDisable(void);
+
+/**************************************************************************//**
+ @Function E500_AddressBroadcastEnable
+
+ @Description Enables address broadcast.
+
+ The e500 broadcasts cache management instructions (dcbst, dcblc
+ (CT = 1), icblc (CT = 1), dcbf, dcbi, mbar, msync, tlbsync, icbi)
+ based on ABE. ABE must be set to allow management of external
+ L2 caches.
+
+ @Return None.
+*//***************************************************************************/
+void E500_AddressBroadcastEnable(void);
+
+/**************************************************************************//**
+ @Function E500_AddressBroadcastDisable
+
+ @Description Disables address broadcast.
+
+ The e500 broadcasts cache management instructions (dcbst, dcblc
+ (CT = 1), icblc (CT = 1), dcbf, dcbi, mbar, msync, tlbsync, icbi)
+ based on ABE. ABE must be set to allow management of external
+ L2 caches.
+
+ @Return None.
+*//***************************************************************************/
+void E500_AddressBroadcastDisable(void);
+
+/**************************************************************************//**
+ @Function E500_IsTaskletSupported
+
+ @Description Checks if tasklets are supported by the e500 interrupt handler.
+
+ @Retval TRUE - Tasklets are supported.
+ @Retval FALSE - Tasklets are not supported.
+*//***************************************************************************/
+bool E500_IsTaskletSupported(void);
+
+void E500_EnableTimeBase(void);
+void E500_DisableTimeBase(void);
+
+uint64_t E500_GetTimeBaseTime(void);
+
+void E500_GenericIntrInit(void);
+
+t_Error E500_SetIntr(int ppcIntrSrc,
+ void (* Isr)(t_Handle handle),
+ t_Handle handle);
+
+t_Error E500_ClearIntr(int ppcIntrSrc);
+
+/**************************************************************************//**
+ @Function E500_GenericIntrHandler
+
+ @Description This is the general e500 interrupt handler.
+
+ It is called by the main assembly interrupt handler
+ when an exception occurs and no other function has been
+ assigned to this exception.
+
+ @Param intrEntry - (In) The exception interrupt vector entry.
+*//***************************************************************************/
+void E500_GenericIntrHandler(uint32_t intrEntry);
+
+/**************************************************************************//**
+ @Function CriticalIntr
+
+ @Description This is the specific critical e500 interrupt handler.
+
+ It is called by the main assembly interrupt handler
+ when an critical interrupt.
+
+ @Param intrEntry - (In) The exception interrupt vector entry.
+*//***************************************************************************/
+void CriticalIntr(uint32_t intrEntry);
+
+
+/**************************************************************************//**
+ @Function E500_GetId
+
+ @Description Returns the core ID in the system.
+
+ @Return Core ID.
+*//***************************************************************************/
+uint32_t E500_GetId(void);
+
+/**************************************************************************//**
+ @Function E500_TestAndSet
+
+ @Description This routine tries to atomically test-and-set an integer
+ in memory to a non-zero value.
+
+ The memory will be set only if it is tested as zero, in which
+ case the routine returns the new non-zero value; otherwise the
+ routine returns zero.
+
+ @Param[in] p - pointer to a volatile int in memory, on which test-and-set
+ operation should be made.
+
+ @Retval Zero - Operation failed - memory was already set.
+ @Retval Non-zero - Operation succeeded - memory has been set.
+*//***************************************************************************/
+int E500_TestAndSet(volatile int *p);
+
+/**************************************************************************//**
+ @Function E500_MemoryBarrier
+
+ @Description This routine will cause the core to stop executing any commands
+ until all previous memory read/write commands are completely out
+ of the core's pipeline.
+
+ @Return None.
+*//***************************************************************************/
+static __inline__ void E500_MemoryBarrier(void)
+{
+#ifndef CORE_E500V2
+ __asm__ ("mbar 1");
+#else /* CORE_E500V2 */
+ /**** ERRATA WORK AROUND START ****/
+ /* ERRATA num: CPU1 */
+ /* Description: "mbar MO = 1" instruction fails to order caching-inhibited
+ guarded loads and stores. */
+
+ /* "msync" instruction is used instead */
+
+ __asm__ ("msync");
+
+ /**** ERRATA WORK AROUND END ****/
+#endif /* CORE_E500V2 */
+}
+
+/**************************************************************************//**
+ @Function E500_InstructionSync
+
+ @Description This routine will cause the core to wait for previous instructions
+ (including any interrupts they generate) to complete before the
+ synchronization command executes, which purges all instructions
+ from the processor's pipeline and refetches the next instruction.
+
+ @Return None.
+*//***************************************************************************/
+static __inline__ void E500_InstructionSync(void)
+{
+ __asm__ ("isync");
+}
+
+
+/** @} */ /* end of E500_init_grp group */
+/** @} */ /* end of E500_grp group */
+
+
+#endif /* __E500V2_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/cores/ppc_ext.h b/drivers/net/ethernet/freescale/fman/inc/cores/ppc_ext.h
new file mode 100644
index 0000000..9344b3a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/cores/ppc_ext.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File ppc_ext.h
+
+ @Description Core API for PowerPC cores
+
+ These routines must be implemented by each specific PowerPC
+ core driver.
+*//***************************************************************************/
+#ifndef __PPC_EXT_H
+#define __PPC_EXT_H
+
+#include "part_ext.h"
+
+
+#define CORE_IS_BIG_ENDIAN
+
+#if defined(CORE_E300) || defined(CORE_E500V2)
+#define CORE_CACHELINE_SIZE 32
+#elif defined(CORE_E500MC) || defined(CORE_E5500) || defined(CORE_E6500)
+#define CORE_CACHELINE_SIZE 64
+#else
+#error "Core not defined!"
+#endif /* defined(CORE_E300) || ... */
+
+
+/**************************************************************************//**
+ @Function CORE_TestAndSet
+
+ @Description This routine tries to atomically test-and-set an integer
+ in memory to a non-zero value.
+
+ The memory will be set only if it is tested as zero, in which
+ case the routine returns the new non-zero value; otherwise the
+ routine returns zero.
+
+ @Param[in] p - pointer to a volatile int in memory, on which test-and-set
+ operation should be made.
+
+ @Retval Zero - Operation failed - memory was already set.
+ @Retval Non-zero - Operation succeeded - memory has been set.
+*//***************************************************************************/
+int CORE_TestAndSet(volatile int *p);
+
+/**************************************************************************//**
+ @Function CORE_InstructionSync
+
+ @Description This routine will cause the core to wait for previous instructions
+ (including any interrupts they generate) to complete before the
+ synchronization command executes, which purges all instructions
+ from the processor's pipeline and refetches the next instruction.
+
+ @Return None.
+*//***************************************************************************/
+void CORE_InstructionSync(void);
+
+/**************************************************************************//**
+ @Function CORE_DCacheEnable
+
+ @Description Enables the data cache for memory pages that are
+ not cache inhibited.
+
+ @Return None.
+*//***************************************************************************/
+void CORE_DCacheEnable(void);
+
+/**************************************************************************//**
+ @Function CORE_ICacheEnable
+
+ @Description Enables the instruction cache for memory pages that are
+ not cache inhibited.
+
+ @Return None.
+*//***************************************************************************/
+void CORE_ICacheEnable(void);
+
+/**************************************************************************//**
+ @Function CORE_DCacheDisable
+
+ @Description Disables the data cache.
+
+ @Return None.
+*//***************************************************************************/
+void CORE_DCacheDisable(void);
+
+/**************************************************************************//**
+ @Function CORE_ICacheDisable
+
+ @Description Disables the instruction cache.
+
+ @Return None.
+*//***************************************************************************/
+void CORE_ICacheDisable(void);
+
+
+
+#if defined(CORE_E300)
+#include "e300_ext.h"
+#elif defined(CORE_E500V2) || defined(CORE_E500MC) || defined(CORE_E5500) || defined(CORE_E6500)
+#include "e500v2_ext.h"
+#if !defined(NCSW_LINUX)
+#include "e500v2_asm_ext.h"
+#endif
+#else
+#error "Core not defined!"
+#endif
+
+
+#endif /* __PPC_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/ctype_ext.h b/drivers/net/ethernet/freescale/fman/inc/ctype_ext.h
new file mode 100644
index 0000000..e3d5d8d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/ctype_ext.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __CTYPE_EXT_H
+#define __CTYPE_EXT_H
+
+
+#if defined(NCSW_LINUX) && defined(__KERNEL__)
+/*
+ * NOTE! This ctype does not handle EOF like the standard C
+ * library is required to.
+ */
+
+#define _U 0x01 /* upper */
+#define _L 0x02 /* lower */
+#define _D 0x04 /* digit */
+#define _C 0x08 /* cntrl */
+#define _P 0x10 /* punct */
+#define _S 0x20 /* white space (space/lf/tab) */
+#define _X 0x40 /* hex digit */
+#define _SP 0x80 /* hard space (0x20) */
+
+extern unsigned char _ctype[];
+
+#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
+
+#define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0)
+#define isalpha(c) ((__ismask(c)&(_U|_L)) != 0)
+#define iscntrl(c) ((__ismask(c)&(_C)) != 0)
+#define isdigit(c) ((__ismask(c)&(_D)) != 0)
+#define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0)
+#define islower(c) ((__ismask(c)&(_L)) != 0)
+#define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
+#define ispunct(c) ((__ismask(c)&(_P)) != 0)
+#define isspace(c) ((__ismask(c)&(_S)) != 0)
+#define isupper(c) ((__ismask(c)&(_U)) != 0)
+#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0)
+
+#define isascii(c) (((unsigned char)(c))<=0x7f)
+#define toascii(c) (((unsigned char)(c))&0x7f)
+
+static __inline__ unsigned char __tolower(unsigned char c)
+{
+ if (isupper(c))
+ c -= 'A'-'a';
+ return c;
+}
+
+static __inline__ unsigned char __toupper(unsigned char c)
+{
+ if (islower(c))
+ c -= 'a'-'A';
+ return c;
+}
+
+#define tolower(c) __tolower(c)
+#define toupper(c) __toupper(c)
+
+#else
+#include <ctype.h>
+#endif /* defined(NCSW_LINUX) && defined(__KERNEL__) */
+
+
+#endif /* __CTYPE_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/ddr_std_ext.h b/drivers/net/ethernet/freescale/fman/inc/ddr_std_ext.h
new file mode 100644
index 0000000..8bb343fc
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/ddr_std_ext.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DDR_SDT_EXT_H
+#define __DDR_SDT_EXT_H
+
+
+/**************************************************************************//**
+ @Group ddr_Generic_Resources
+
+ @Description ddr generic functions, definitions and enums.
+
+ @{
+*//***************************************************************************/
+
+
+/**************************************************************************//**
+ @Description SPD maximum size
+*//***************************************************************************/
+#define SPD_MAX_SIZE 256
+
+/**************************************************************************//**
+ @Description DDR types select
+*//***************************************************************************/
+typedef enum e_DdrType
+{
+ e_DDR_DDR1,
+ e_DDR_DDR2,
+ e_DDR_DDR3,
+ e_DDR_DDR3L,
+ e_DDR_DDR4
+} e_DdrType;
+
+/**************************************************************************//**
+ @Description DDR Mode.
+*//***************************************************************************/
+typedef enum e_DdrMode
+{
+ e_DDR_BUS_WIDTH_32BIT,
+ e_DDR_BUS_WIDTH_64BIT
+} e_DdrMode;
+
+/** @} */ /* end of ddr_Generic_Resources group */
+
+
+
+#endif /* __DDR_SDT_EXT_H */
+
diff --git a/drivers/net/ethernet/freescale/fman/inc/debug_ext.h b/drivers/net/ethernet/freescale/fman/inc/debug_ext.h
new file mode 100644
index 0000000..62865bb
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/debug_ext.h
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File debug_ext.h
+
+ @Description Debug mode definitions.
+*//***************************************************************************/
+
+#ifndef __DEBUG_EXT_H
+#define __DEBUG_EXT_H
+
+#include "std_ext.h"
+#include "xx_ext.h"
+#include "memcpy_ext.h"
+#if (DEBUG_ERRORS > 0)
+#include "sprint_ext.h"
+#include "string_ext.h"
+#endif /* DEBUG_ERRORS > 0 */
+
+
+#if (DEBUG_ERRORS > 0)
+
+/* Internally used macros */
+
+#define DUMP_Print XX_Print
+#define DUMP_MAX_LEVELS 6
+#define DUMP_MAX_STR 64
+
+
+#define _CREATE_DUMP_SUBSTR(phrase) \
+ dumpTmpLevel = 0; dumpSubStr[0] = '\0'; \
+ sprintf(dumpTmpStr, "%s", #phrase); \
+ p_DumpToken = strtok(dumpTmpStr, (dumpIsArr[0] ? "[" : ".")); \
+ while (p_DumpToken != NULL) \
+ { \
+ strcat(dumpSubStr, p_DumpToken); \
+ if (dumpIsArr[dumpTmpLevel]) \
+ { \
+ strcat(dumpSubStr, dumpIdxStr[dumpTmpLevel]); \
+ p_DumpToken = strtok(NULL, "."); \
+ } \
+ if ((p_DumpToken = strtok(NULL, (dumpIsArr[++dumpTmpLevel] ? "[" : "."))) != 0) \
+ strcat(dumpSubStr, "."); \
+ }\
+
+
+/**************************************************************************//**
+ @Group gen_id General Drivers Utilities
+
+ @Description External routines.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group dump_id Memory and Registers Dump Mechanism
+
+ @Description Macros for dumping memory mapped structures.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Description Declaration of dump mechanism variables.
+
+ This macro must be declared at the beginning of each routine
+ which uses the dump mechanism macros, before the routine's code
+ starts.
+*//***************************************************************************/
+#define DECLARE_DUMP \
+ char dumpIdxStr[DUMP_MAX_LEVELS + 1][6] = { "", }; \
+ char dumpSubStr[DUMP_MAX_STR] = ""; \
+ char dumpTmpStr[DUMP_MAX_STR] = ""; \
+ char *p_DumpToken = NULL; \
+ int dumpArrIdx = 0, dumpArrSize = 0, dumpVarSize = 0, dumpLevel = 0, dumpTmpLevel = 0; \
+ uint8_t dumpIsArr[DUMP_MAX_LEVELS + 1] = { 0 }; \
+ /* Prevent warnings if not all used */ \
+ UNUSED(dumpIdxStr[0][0]); \
+ UNUSED(dumpSubStr[0]); \
+ UNUSED(dumpTmpStr[0]); \
+ UNUSED(p_DumpToken); \
+ UNUSED(dumpArrIdx); \
+ UNUSED(dumpArrSize); \
+ UNUSED(dumpVarSize); \
+ UNUSED(dumpLevel); \
+ UNUSED(dumpTmpLevel); \
+ UNUSED(dumpIsArr[0]);
+
+
+/**************************************************************************//**
+ @Description Prints a title for a subsequent dumped structure or memory.
+
+ The inputs for this macro are the structure/memory title and
+ its base addresses.
+*//***************************************************************************/
+#define DUMP_TITLE(addr, msg) \
+ DUMP_Print("\r\n"); DUMP_Print msg; \
+ if (addr) \
+ DUMP_Print(" (%p)", (addr)); \
+ DUMP_Print("\r\n---------------------------------------------------------\r\n");
+
+/**************************************************************************//**
+ @Description Prints a subtitle for a subsequent dumped sub-structure (optional).
+
+ The inputs for this macro are the sub-structure subtitle.
+ A separating line with this subtitle will be printed.
+*//***************************************************************************/
+#define DUMP_SUBTITLE(subtitle) \
+ DUMP_Print("----------- "); DUMP_Print subtitle; DUMP_Print("\r\n")
+
+
+/**************************************************************************//**
+ @Description Dumps a memory region in 4-bytes aligned format.
+
+ The inputs for this macro are the base addresses and size
+ (in bytes) of the memory region.
+*//***************************************************************************/
+#define DUMP_MEMORY(addr, size) \
+ MemDisp((uint8_t *)(addr), (int)(size))
+
+
+/**************************************************************************//**
+ @Description Declares a dump loop, for dumping a sub-structure array.
+
+ The inputs for this macro are:
+ - idx: an index variable, for indexing the sub-structure items
+ inside the loop. This variable must be declared separately
+ in the beginning of the routine.
+ - cnt: the number of times to repeat the loop. This number should
+ equal the number of items in the sub-structures array.
+
+ Note, that the body of the loop must be written inside brackets.
+*//***************************************************************************/
+#define DUMP_SUBSTRUCT_ARRAY(idx, cnt) \
+ for (idx=0, dumpIsArr[dumpLevel++] = 1; \
+ (idx < cnt) && sprintf(dumpIdxStr[dumpLevel-1], "[%d]", idx); \
+ idx++, ((idx < cnt) || ((dumpIsArr[--dumpLevel] = 0) == 0)))
+
+
+/**************************************************************************//**
+ @Description Dumps a structure's member variable.
+
+ The input for this macro is the full reference for the member
+ variable, where the structure is referenced using a pointer.
+
+ Note, that a members array must be dumped using DUMP_ARR macro,
+ rather than using this macro.
+
+ If the member variable is part of a sub-structure hierarchy,
+ the full hierarchy (including array indexing) must be specified.
+
+ Examples: p_Struct->member
+ p_Struct->sub.member
+ p_Struct->sub[i].member
+*//***************************************************************************/
+#define DUMP_VAR(st, phrase) \
+ do { \
+ void *addr = (void *)&((st)->phrase); \
+ physAddress_t physAddr = XX_VirtToPhys(addr); \
+ _CREATE_DUMP_SUBSTR(phrase); \
+ dumpVarSize = sizeof((st)->phrase); \
+ switch (dumpVarSize) \
+ { \
+ case 1: DUMP_Print("0x%010llX: 0x%02x%14s\t%s\r\n", \
+ physAddr, GET_UINT8(*(uint8_t*)addr), "", dumpSubStr); break; \
+ case 2: DUMP_Print("0x%010llX: 0x%04x%12s\t%s\r\n", \
+ physAddr, GET_UINT16(*(uint16_t*)addr), "", dumpSubStr); break; \
+ case 4: DUMP_Print("0x%010llX: 0x%08x%8s\t%s\r\n", \
+ physAddr, GET_UINT32(*(uint32_t*)addr), "", dumpSubStr); break; \
+ case 8: DUMP_Print("0x%010llX: 0x%016llx\t%s\r\n", \
+ physAddr, GET_UINT64(*(uint64_t*)addr), dumpSubStr); break; \
+ default: DUMP_Print("Bad size %d (" #st "->" #phrase ")\r\n", dumpVarSize); \
+ } \
+ } while (0)
+
+
+/**************************************************************************//**
+ @Description Dumps a structure's members array.
+
+ The input for this macro is the full reference for the members
+ array, where the structure is referenced using a pointer.
+
+ If the members array is part of a sub-structure hierarchy,
+ the full hierarchy (including array indexing) must be specified.
+
+ Examples: p_Struct->array
+ p_Struct->sub.array
+ p_Struct->sub[i].array
+*//***************************************************************************/
+#define DUMP_ARR(st, phrase) \
+ do { \
+ physAddress_t physAddr; \
+ _CREATE_DUMP_SUBSTR(phrase); \
+ dumpArrSize = ARRAY_SIZE((st)->phrase); \
+ dumpVarSize = sizeof((st)->phrase[0]); \
+ switch (dumpVarSize) \
+ { \
+ case 1: \
+ for (dumpArrIdx=0; dumpArrIdx < dumpArrSize; dumpArrIdx++) { \
+ physAddr = XX_VirtToPhys((void *)&((st)->phrase[dumpArrIdx])); \
+ DUMP_Print("0x%010llX: 0x%02x%14s\t%s[%d]\r\n", \
+ physAddr, GET_UINT8((st)->phrase[dumpArrIdx]), "", dumpSubStr, dumpArrIdx); \
+ } break; \
+ case 2: \
+ for (dumpArrIdx=0; dumpArrIdx < dumpArrSize; dumpArrIdx++) { \
+ physAddr = XX_VirtToPhys((void *)&((st)->phrase[dumpArrIdx])); \
+ DUMP_Print("0x%010llX: 0x%04x%12s\t%s[%d]\r\n", \
+ physAddr, GET_UINT16((st)->phrase[dumpArrIdx]), "", dumpSubStr, dumpArrIdx); \
+ } break; \
+ case 4: \
+ for (dumpArrIdx=0; dumpArrIdx < dumpArrSize; dumpArrIdx++) { \
+ physAddr = XX_VirtToPhys((void *)&((st)->phrase[dumpArrIdx])); \
+ DUMP_Print("0x%010llX: 0x%08x%8s\t%s[%d]\r\n", \
+ physAddr, GET_UINT32((st)->phrase[dumpArrIdx]), "", dumpSubStr, dumpArrIdx); \
+ } break; \
+ case 8: \
+ for (dumpArrIdx=0; dumpArrIdx < dumpArrSize; dumpArrIdx++) { \
+ physAddr = XX_VirtToPhys((void *)&((st)->phrase[dumpArrIdx])); \
+ DUMP_Print("0x%010llX: 0x%016llx\t%s[%d]\r\n", \
+ physAddr, GET_UINT64((st)->phrase[dumpArrIdx]), dumpSubStr, dumpArrIdx); \
+ } break; \
+ default: DUMP_Print("Bad size %d (" #st "->" #phrase "[0])\r\n", dumpVarSize); \
+ } \
+ } while (0)
+
+
+#endif /* DEBUG_ERRORS > 0 */
+
+
+/** @} */ /* end of dump_id group */
+/** @} */ /* end of gen_id group */
+
+
+#endif /* __DEBUG_EXT_H */
+
diff --git a/drivers/net/ethernet/freescale/fman/inc/endian_ext.h b/drivers/net/ethernet/freescale/fman/inc/endian_ext.h
new file mode 100644
index 0000000..5cdec66
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/endian_ext.h
@@ -0,0 +1,447 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+
+ @File endian_ext.h
+
+ @Description Big/little endian swapping routines.
+*//***************************************************************************/
+
+#ifndef __ENDIAN_EXT_H
+#define __ENDIAN_EXT_H
+
+#include "std_ext.h"
+
+
+/**************************************************************************//**
+ @Group gen_id General Drivers Utilities
+
+ @Description General usage API. This API is intended for usage by both the
+ internal modules and the user's application.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group endian_id Big/Little-Endian Conversion
+
+ @Description Routines and macros for Big/Little-Endian conversion and
+ general byte swapping.
+
+ All routines and macros are expecting unsigned values as
+ parameters, but will generate the correct result also for
+ signed values. Therefore, signed/unsigned casting is allowed.
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Collection Byte-Swap Macros
+
+ Macros for swapping byte order.
+
+ @Cautions The parameters of these macros are evaluated multiple times.
+ For calculated expressions or expressions that contain function
+ calls it is recommended to use the byte-swap routines.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Description Swaps the byte order of a given 16-bit value.
+
+ @Param[in] val - The 16-bit value to swap.
+
+ @Return The byte-swapped value..
+
+ @Cautions The given value is evaluated multiple times by this macro.
+ For calculated expressions or expressions that contain function
+ calls it is recommended to use the SwapUint16() routine.
+
+ @hideinitializer
+*//***************************************************************************/
+#define SWAP_UINT16(val) \
+ ((uint16_t)((((val) & 0x00FF) << 8) | (((val) & 0xFF00) >> 8)))
+
+/**************************************************************************//**
+ @Description Swaps the byte order of a given 32-bit value.
+
+ @Param[in] val - The 32-bit value to swap.
+
+ @Return The byte-swapped value..
+
+ @Cautions The given value is evaluated multiple times by this macro.
+ For calculated expressions or expressions that contain function
+ calls it is recommended to use the SwapUint32() routine.
+
+ @hideinitializer
+*//***************************************************************************/
+#define SWAP_UINT32(val) \
+ ((uint32_t)((((val) & 0x000000FF) << 24) | \
+ (((val) & 0x0000FF00) << 8) | \
+ (((val) & 0x00FF0000) >> 8) | \
+ (((val) & 0xFF000000) >> 24)))
+
+/**************************************************************************//**
+ @Description Swaps the byte order of a given 64-bit value.
+
+ @Param[in] val - The 64-bit value to swap.
+
+ @Return The byte-swapped value..
+
+ @Cautions The given value is evaluated multiple times by this macro.
+ For calculated expressions or expressions that contain function
+ calls it is recommended to use the SwapUint64() routine.
+
+ @hideinitializer
+*//***************************************************************************/
+#define SWAP_UINT64(val) \
+ ((uint64_t)((((val) & 0x00000000000000FFULL) << 56) | \
+ (((val) & 0x000000000000FF00ULL) << 40) | \
+ (((val) & 0x0000000000FF0000ULL) << 24) | \
+ (((val) & 0x00000000FF000000ULL) << 8) | \
+ (((val) & 0x000000FF00000000ULL) >> 8) | \
+ (((val) & 0x0000FF0000000000ULL) >> 24) | \
+ (((val) & 0x00FF000000000000ULL) >> 40) | \
+ (((val) & 0xFF00000000000000ULL) >> 56)))
+
+/* @} */
+
+/**************************************************************************//**
+ @Collection Byte-Swap Routines
+
+ Routines for swapping the byte order of a given parameter and
+ returning the swapped value.
+
+ These inline routines are safer than the byte-swap macros,
+ because they evaluate the parameter expression only once.
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Function SwapUint16
+
+ @Description Returns the byte-swapped value of a given 16-bit value.
+
+ @Param[in] val - The 16-bit value.
+
+ @Return The byte-swapped value of the parameter.
+*//***************************************************************************/
+static __inline__ uint16_t SwapUint16(uint16_t val)
+{
+ return (uint16_t)(((val & 0x00FF) << 8) |
+ ((val & 0xFF00) >> 8));
+}
+
+/**************************************************************************//**
+ @Function SwapUint32
+
+ @Description Returns the byte-swapped value of a given 32-bit value.
+
+ @Param[in] val - The 32-bit value.
+
+ @Return The byte-swapped value of the parameter.
+*//***************************************************************************/
+static __inline__ uint32_t SwapUint32(uint32_t val)
+{
+ return (uint32_t)(((val & 0x000000FF) << 24) |
+ ((val & 0x0000FF00) << 8) |
+ ((val & 0x00FF0000) >> 8) |
+ ((val & 0xFF000000) >> 24));
+}
+
+/**************************************************************************//**
+ @Function SwapUint64
+
+ @Description Returns the byte-swapped value of a given 64-bit value.
+
+ @Param[in] val - The 64-bit value.
+
+ @Return The byte-swapped value of the parameter.
+*//***************************************************************************/
+static __inline__ uint64_t SwapUint64(uint64_t val)
+{
+ return (uint64_t)(((val & 0x00000000000000FFULL) << 56) |
+ ((val & 0x000000000000FF00ULL) << 40) |
+ ((val & 0x0000000000FF0000ULL) << 24) |
+ ((val & 0x00000000FF000000ULL) << 8) |
+ ((val & 0x000000FF00000000ULL) >> 8) |
+ ((val & 0x0000FF0000000000ULL) >> 24) |
+ ((val & 0x00FF000000000000ULL) >> 40) |
+ ((val & 0xFF00000000000000ULL) >> 56));
+}
+
+/* @} */
+
+/**************************************************************************//**
+ @Collection In-place Byte-Swap-And-Set Routines
+
+ Routines for swapping the byte order of a given variable and
+ setting the swapped value back to the same variable.
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Function SwapUint16P
+
+ @Description Swaps the byte order of a given 16-bit variable.
+
+ @Param[in] p_Val - Pointer to the 16-bit variable.
+
+ @Return None.
+*//***************************************************************************/
+static __inline__ void SwapUint16P(uint16_t *p_Val)
+{
+ *p_Val = SwapUint16(*p_Val);
+}
+
+/**************************************************************************//**
+ @Function SwapUint32P
+
+ @Description Swaps the byte order of a given 32-bit variable.
+
+ @Param[in] p_Val - Pointer to the 32-bit variable.
+
+ @Return None.
+*//***************************************************************************/
+static __inline__ void SwapUint32P(uint32_t *p_Val)
+{
+ *p_Val = SwapUint32(*p_Val);
+}
+
+/**************************************************************************//**
+ @Function SwapUint64P
+
+ @Description Swaps the byte order of a given 64-bit variable.
+
+ @Param[in] p_Val - Pointer to the 64-bit variable.
+
+ @Return None.
+*//***************************************************************************/
+static __inline__ void SwapUint64P(uint64_t *p_Val)
+{
+ *p_Val = SwapUint64(*p_Val);
+}
+
+/* @} */
+
+
+/**************************************************************************//**
+ @Collection Little-Endian Conversion Macros
+
+ These macros convert given parameters to or from Little-Endian
+ format. Use these macros when you want to read or write a specific
+ Little-Endian value in memory, without a-priori knowing the CPU
+ byte order.
+
+ These macros use the byte-swap routines. For conversion of
+ constants in initialization structures, you may use the CONST
+ versions of these macros (see below), which are using the
+ byte-swap macros instead.
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Description Converts a given 16-bit value from CPU byte order to
+ Little-Endian byte order.
+
+ @Param[in] val - The 16-bit value to convert.
+
+ @Return The converted value.
+
+ @hideinitializer
+*//***************************************************************************/
+#define CPU_TO_LE16(val) SwapUint16(val)
+
+/**************************************************************************//**
+ @Description Converts a given 32-bit value from CPU byte order to
+ Little-Endian byte order.
+
+ @Param[in] val - The 32-bit value to convert.
+
+ @Return The converted value.
+
+ @hideinitializer
+*//***************************************************************************/
+#define CPU_TO_LE32(val) SwapUint32(val)
+
+/**************************************************************************//**
+ @Description Converts a given 64-bit value from CPU byte order to
+ Little-Endian byte order.
+
+ @Param[in] val - The 64-bit value to convert.
+
+ @Return The converted value.
+
+ @hideinitializer
+*//***************************************************************************/
+#define CPU_TO_LE64(val) SwapUint64(val)
+
+
+/**************************************************************************//**
+ @Description Converts a given 16-bit value from Little-Endian byte order to
+ CPU byte order.
+
+ @Param[in] val - The 16-bit value to convert.
+
+ @Return The converted value.
+
+ @hideinitializer
+*//***************************************************************************/
+#define LE16_TO_CPU(val) CPU_TO_LE16(val)
+
+/**************************************************************************//**
+ @Description Converts a given 32-bit value from Little-Endian byte order to
+ CPU byte order.
+
+ @Param[in] val - The 32-bit value to convert.
+
+ @Return The converted value.
+
+ @hideinitializer
+*//***************************************************************************/
+#define LE32_TO_CPU(val) CPU_TO_LE32(val)
+
+/**************************************************************************//**
+ @Description Converts a given 64-bit value from Little-Endian byte order to
+ CPU byte order.
+
+ @Param[in] val - The 64-bit value to convert.
+
+ @Return The converted value.
+
+ @hideinitializer
+*//***************************************************************************/
+#define LE64_TO_CPU(val) CPU_TO_LE64(val)
+
+/* @} */
+
+/**************************************************************************//**
+ @Collection Little-Endian Constant Conversion Macros
+
+ These macros convert given constants to or from Little-Endian
+ format. Use these macros when you want to read or write a specific
+ Little-Endian constant in memory, without a-priori knowing the
+ CPU byte order.
+
+ These macros use the byte-swap macros, therefore can be used for
+ conversion of constants in initialization structures.
+
+ @Cautions The parameters of these macros are evaluated multiple times.
+ For non-constant expressions, use the non-CONST macro versions.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Description Converts a given 16-bit constant from CPU byte order to
+ Little-Endian byte order.
+
+ @Param[in] val - The 16-bit value to convert.
+
+ @Return The converted value.
+
+ @hideinitializer
+*//***************************************************************************/
+#define CONST_CPU_TO_LE16(val) SWAP_UINT16(val)
+
+/**************************************************************************//**
+ @Description Converts a given 32-bit constant from CPU byte order to
+ Little-Endian byte order.
+
+ @Param[in] val - The 32-bit value to convert.
+
+ @Return The converted value.
+
+ @hideinitializer
+*//***************************************************************************/
+#define CONST_CPU_TO_LE32(val) SWAP_UINT32(val)
+
+/**************************************************************************//**
+ @Description Converts a given 64-bit constant from CPU byte order to
+ Little-Endian byte order.
+
+ @Param[in] val - The 64-bit value to convert.
+
+ @Return The converted value.
+
+ @hideinitializer
+*//***************************************************************************/
+#define CONST_CPU_TO_LE64(val) SWAP_UINT64(val)
+
+
+/**************************************************************************//**
+ @Description Converts a given 16-bit constant from Little-Endian byte order
+ to CPU byte order.
+
+ @Param[in] val - The 16-bit value to convert.
+
+ @Return The converted value.
+
+ @hideinitializer
+*//***************************************************************************/
+#define CONST_LE16_TO_CPU(val) CONST_CPU_TO_LE16(val)
+
+/**************************************************************************//**
+ @Description Converts a given 32-bit constant from Little-Endian byte order
+ to CPU byte order.
+
+ @Param[in] val - The 32-bit value to convert.
+
+ @Return The converted value.
+
+ @hideinitializer
+*//***************************************************************************/
+#define CONST_LE32_TO_CPU(val) CONST_CPU_TO_LE32(val)
+
+/**************************************************************************//**
+ @Description Converts a given 64-bit constant from Little-Endian byte order
+ to CPU byte order.
+
+ @Param[in] val - The 64-bit value to convert.
+
+ @Return The converted value.
+
+ @hideinitializer
+*//***************************************************************************/
+#define CONST_LE64_TO_CPU(val) CONST_CPU_TO_LE64(val)
+
+/* @} */
+
+
+/** @} */ /* end of endian_id group */
+/** @} */ /* end of gen_id group */
+
+
+#endif /* __ENDIAN_EXT_H */
+
diff --git a/drivers/net/ethernet/freescale/fman/inc/enet_ext.h b/drivers/net/ethernet/freescale/fman/inc/enet_ext.h
new file mode 100644
index 0000000..c6b9071
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/enet_ext.h
@@ -0,0 +1,203 @@
+/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File enet_ext.h
+
+ @Description Ethernet generic definitions and enums.
+*//***************************************************************************/
+
+#ifndef __ENET_EXT_H
+#define __ENET_EXT_H
+
+#include "fsl_enet.h"
+
+#define ENET_NUM_OCTETS_PER_ADDRESS 6 /**< Number of octets (8-bit bytes) in an ethernet address */
+#define ENET_GROUP_ADDR 0x01 /**< Group address mask for ethernet addresses */
+
+
+/**************************************************************************//**
+ @Description Ethernet Address
+*//***************************************************************************/
+typedef uint8_t t_EnetAddr[ENET_NUM_OCTETS_PER_ADDRESS];
+
+/**************************************************************************//**
+ @Description Ethernet Address Type.
+*//***************************************************************************/
+typedef enum e_EnetAddrType
+{
+ e_ENET_ADDR_TYPE_INDIVIDUAL, /**< Individual (unicast) address */
+ e_ENET_ADDR_TYPE_GROUP, /**< Group (multicast) address */
+ e_ENET_ADDR_TYPE_BROADCAST /**< Broadcast address */
+} e_EnetAddrType;
+
+/**************************************************************************//**
+ @Description Ethernet MAC-PHY Interface
+*//***************************************************************************/
+typedef enum e_EnetInterface
+{
+ e_ENET_IF_MII = E_ENET_IF_MII, /**< MII interface */
+ e_ENET_IF_RMII = E_ENET_IF_RMII, /**< RMII interface */
+ e_ENET_IF_SMII = E_ENET_IF_SMII, /**< SMII interface */
+ e_ENET_IF_GMII = E_ENET_IF_GMII, /**< GMII interface */
+ e_ENET_IF_RGMII = E_ENET_IF_RGMII, /**< RGMII interface */
+ e_ENET_IF_TBI = E_ENET_IF_TBI, /**< TBI interface */
+ e_ENET_IF_RTBI = E_ENET_IF_RTBI, /**< RTBI interface */
+ e_ENET_IF_SGMII = E_ENET_IF_SGMII, /**< SGMII interface */
+ e_ENET_IF_XGMII = E_ENET_IF_XGMII, /**< XGMII interface */
+ e_ENET_IF_QSGMII= E_ENET_IF_QSGMII, /**< QSGMII interface */
+ e_ENET_IF_XFI = E_ENET_IF_XFI /**< XFI interface */
+} e_EnetInterface;
+
+#define ENET_IF_SGMII_BASEX 0x80000000 /**< SGMII/QSGII interface with 1000BaseX
+ auto-negotiation between MAC and phy
+ or backplane;
+ Note: 1000BaseX auto-negotiation relates
+ only to interface between MAC and phy/backplane,
+ SGMII phy can still synchronize with far-end phy
+ at 10Mbps, 100Mbps or 1000Mbps */
+
+/**************************************************************************//**
+ @Description Ethernet Duplex Mode
+*//***************************************************************************/
+typedef enum e_EnetDuplexMode
+{
+ e_ENET_HALF_DUPLEX, /**< Half-Duplex mode */
+ e_ENET_FULL_DUPLEX /**< Full-Duplex mode */
+} e_EnetDuplexMode;
+
+/**************************************************************************//**
+ @Description Ethernet Speed (nominal data rate)
+*//***************************************************************************/
+typedef enum e_EnetSpeed
+{
+ e_ENET_SPEED_10 = E_ENET_SPEED_10, /**< 10 Mbps */
+ e_ENET_SPEED_100 = E_ENET_SPEED_100, /**< 100 Mbps */
+ e_ENET_SPEED_1000 = E_ENET_SPEED_1000, /**< 1000 Mbps = 1 Gbps */
+ e_ENET_SPEED_10000 = E_ENET_SPEED_10000 /**< 10000 Mbps = 10 Gbps */
+} e_EnetSpeed;
+
+/**************************************************************************//**
+ @Description Ethernet mode (combination of MAC-PHY interface and speed)
+*//***************************************************************************/
+typedef enum e_EnetMode
+{
+ e_ENET_MODE_INVALID = 0, /**< Invalid Ethernet mode */
+ e_ENET_MODE_MII_10 = (e_ENET_IF_MII | e_ENET_SPEED_10), /**< 10 Mbps MII */
+ e_ENET_MODE_MII_100 = (e_ENET_IF_MII | e_ENET_SPEED_100), /**< 100 Mbps MII */
+ e_ENET_MODE_RMII_10 = (e_ENET_IF_RMII | e_ENET_SPEED_10), /**< 10 Mbps RMII */
+ e_ENET_MODE_RMII_100 = (e_ENET_IF_RMII | e_ENET_SPEED_100), /**< 100 Mbps RMII */
+ e_ENET_MODE_SMII_10 = (e_ENET_IF_SMII | e_ENET_SPEED_10), /**< 10 Mbps SMII */
+ e_ENET_MODE_SMII_100 = (e_ENET_IF_SMII | e_ENET_SPEED_100), /**< 100 Mbps SMII */
+ e_ENET_MODE_GMII_1000 = (e_ENET_IF_GMII | e_ENET_SPEED_1000), /**< 1000 Mbps GMII */
+ e_ENET_MODE_RGMII_10 = (e_ENET_IF_RGMII | e_ENET_SPEED_10), /**< 10 Mbps RGMII */
+ e_ENET_MODE_RGMII_100 = (e_ENET_IF_RGMII | e_ENET_SPEED_100), /**< 100 Mbps RGMII */
+ e_ENET_MODE_RGMII_1000 = (e_ENET_IF_RGMII | e_ENET_SPEED_1000), /**< 1000 Mbps RGMII */
+ e_ENET_MODE_TBI_1000 = (e_ENET_IF_TBI | e_ENET_SPEED_1000), /**< 1000 Mbps TBI */
+ e_ENET_MODE_RTBI_1000 = (e_ENET_IF_RTBI | e_ENET_SPEED_1000), /**< 1000 Mbps RTBI */
+ e_ENET_MODE_SGMII_10 = (e_ENET_IF_SGMII | e_ENET_SPEED_10),
+ /**< 10 Mbps SGMII with auto-negotiation between MAC and
+ SGMII phy according to Cisco SGMII specification */
+ e_ENET_MODE_SGMII_100 = (e_ENET_IF_SGMII | e_ENET_SPEED_100),
+ /**< 100 Mbps SGMII with auto-negotiation between MAC and
+ SGMII phy according to Cisco SGMII specification */
+ e_ENET_MODE_SGMII_1000 = (e_ENET_IF_SGMII | e_ENET_SPEED_1000),
+ /**< 1000 Mbps SGMII with auto-negotiation between MAC and
+ SGMII phy according to Cisco SGMII specification */
+ e_ENET_MODE_SGMII_BASEX_10 = (ENET_IF_SGMII_BASEX | e_ENET_IF_SGMII | e_ENET_SPEED_10),
+ /**< 10 Mbps SGMII with 1000BaseX auto-negotiation between
+ MAC and SGMII phy or backplane */
+ e_ENET_MODE_SGMII_BASEX_100 = (ENET_IF_SGMII_BASEX | e_ENET_IF_SGMII | e_ENET_SPEED_100),
+ /**< 100 Mbps SGMII with 1000BaseX auto-negotiation between
+ MAC and SGMII phy or backplane */
+ e_ENET_MODE_SGMII_BASEX_1000 = (ENET_IF_SGMII_BASEX | e_ENET_IF_SGMII | e_ENET_SPEED_1000),
+ /**< 1000 Mbps SGMII with 1000BaseX auto-negotiation between
+ MAC and SGMII phy or backplane */
+ e_ENET_MODE_QSGMII_1000 = (e_ENET_IF_QSGMII| e_ENET_SPEED_1000),
+ /**< 1000 Mbps QSGMII with auto-negotiation between MAC and
+ QSGMII phy according to Cisco QSGMII specification */
+ e_ENET_MODE_QSGMII_BASEX_1000 = (ENET_IF_SGMII_BASEX | e_ENET_IF_QSGMII| e_ENET_SPEED_1000),
+ /**< 1000 Mbps QSGMII with 1000BaseX auto-negotiation between
+ MAC and QSGMII phy or backplane */
+ e_ENET_MODE_XGMII_10000 = (e_ENET_IF_XGMII | e_ENET_SPEED_10000), /**< 10000 Mbps XGMII */
+ e_ENET_MODE_XFI_10000 = (e_ENET_IF_XFI | e_ENET_SPEED_10000) /**< 10000 Mbps XFI */
+} e_EnetMode;
+
+
+#define IS_ENET_MODE_VALID(mode) \
+ (((mode) == e_ENET_MODE_MII_10 ) || \
+ ((mode) == e_ENET_MODE_MII_100 ) || \
+ ((mode) == e_ENET_MODE_RMII_10 ) || \
+ ((mode) == e_ENET_MODE_RMII_100 ) || \
+ ((mode) == e_ENET_MODE_SMII_10 ) || \
+ ((mode) == e_ENET_MODE_SMII_100 ) || \
+ ((mode) == e_ENET_MODE_GMII_1000 ) || \
+ ((mode) == e_ENET_MODE_RGMII_10 ) || \
+ ((mode) == e_ENET_MODE_RGMII_100 ) || \
+ ((mode) == e_ENET_MODE_RGMII_1000 ) || \
+ ((mode) == e_ENET_MODE_TBI_1000 ) || \
+ ((mode) == e_ENET_MODE_RTBI_1000 ) || \
+ ((mode) == e_ENET_MODE_SGMII_10 ) || \
+ ((mode) == e_ENET_MODE_SGMII_100 ) || \
+ ((mode) == e_ENET_MODE_SGMII_1000 ) || \
+ ((mode) == e_ENET_MODE_SGMII_BASEX_10 ) || \
+ ((mode) == e_ENET_MODE_SGMII_BASEX_100 ) || \
+ ((mode) == e_ENET_MODE_SGMII_BASEX_1000 ) || \
+ ((mode) == e_ENET_MODE_XGMII_10000) || \
+ ((mode) == e_ENET_MODE_QSGMII_1000) || \
+ ((mode) == e_ENET_MODE_QSGMII_BASEX_1000) || \
+ ((mode) == e_ENET_MODE_XFI_10000))
+
+
+#define MAKE_ENET_MODE(_interface, _speed) (e_EnetMode)((_interface) | (_speed))
+
+#define ENET_INTERFACE_FROM_MODE(mode) (e_EnetInterface)((mode) & 0x0FFF0000)
+#define ENET_SPEED_FROM_MODE(mode) (e_EnetSpeed)((mode) & 0x0000FFFF)
+
+#define ENET_ADDR_TO_UINT64(_enetAddr) \
+ (uint64_t)(((uint64_t)(_enetAddr)[0] << 40) | \
+ ((uint64_t)(_enetAddr)[1] << 32) | \
+ ((uint64_t)(_enetAddr)[2] << 24) | \
+ ((uint64_t)(_enetAddr)[3] << 16) | \
+ ((uint64_t)(_enetAddr)[4] << 8) | \
+ ((uint64_t)(_enetAddr)[5]))
+
+#define MAKE_ENET_ADDR_FROM_UINT64(_addr64, _enetAddr) \
+ do { \
+ int i; \
+ for (i=0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++) \
+ (_enetAddr)[i] = (uint8_t)((_addr64) >> ((5-i)*8)); \
+ } while (0)
+
+
+#endif /* __ENET_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/error_ext.h b/drivers/net/ethernet/freescale/fman/inc/error_ext.h
new file mode 100644
index 0000000..71f9398
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/error_ext.h
@@ -0,0 +1,529 @@
+/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File error_ext.h
+
+ @Description Error definitions.
+*//***************************************************************************/
+
+#ifndef __ERROR_EXT_H
+#define __ERROR_EXT_H
+
+#if !defined(NCSW_LINUX)
+#include <errno.h>
+#endif
+
+#include "std_ext.h"
+#include "xx_ext.h"
+#include "core_ext.h"
+
+
+
+
+/**************************************************************************//**
+ @Group gen_id General Drivers Utilities
+
+ @Description External routines.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group gen_error_id Errors, Events and Debug
+
+ @Description External routines.
+
+ @{
+*//***************************************************************************/
+
+/******************************************************************************
+The scheme below provides the bits description for error codes:
+
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+| Reserved (should be zero) | Module ID |
+
+ 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+| Error Type |
+******************************************************************************/
+
+#define ERROR_CODE(_err) ((((uint32_t)_err) & 0x0000FFFF) | __ERR_MODULE__)
+
+#define GET_ERROR_TYPE(_errcode) ((_errcode) & 0x0000FFFF)
+ /**< Extract module code from error code (#t_Error) */
+
+#define GET_ERROR_MODULE(_errcode) ((_errcode) & 0x00FF0000)
+ /**< Extract error type (#e_ErrorType) from
+ error code (#t_Error) */
+
+
+/**************************************************************************//**
+ @Description Error Type Enumeration
+*//***************************************************************************/
+typedef enum e_ErrorType /* Comments / Associated Message Strings */
+{ /* ------------------------------------------------------------ */
+ E_OK = 0 /* Never use "RETURN_ERROR" with E_OK; Use "return E_OK;" */
+ ,E_WRITE_FAILED = EIO /**< Write access failed on memory/device. */
+ /* String: none, or device name. */
+ ,E_NO_DEVICE = ENXIO /**< The associated device is not initialized. */
+ /* String: none. */
+ ,E_NOT_AVAILABLE = EAGAIN
+ /**< Resource is unavailable. */
+ /* String: none, unless the operation is not the main goal
+ of the function (in this case add resource description). */
+ ,E_NO_MEMORY = ENOMEM /**< External memory allocation failed. */
+ /* String: description of item for which allocation failed. */
+ ,E_INVALID_ADDRESS = EFAULT
+ /**< Invalid address. */
+ /* String: description of the specific violation. */
+ ,E_BUSY = EBUSY /**< Resource or module is busy. */
+ /* String: none, unless the operation is not the main goal
+ of the function (in this case add resource description). */
+ ,E_ALREADY_EXISTS = EEXIST
+ /**< Requested resource or item already exists. */
+ /* Use when resource duplication or sharing are not allowed.
+ String: none, unless the operation is not the main goal
+ of the function (in this case add item description). */
+ ,E_INVALID_OPERATION = ENODEV
+ /**< The operation/command is invalid (unrecognized). */
+ /* String: none. */
+ ,E_INVALID_VALUE = EDOM /**< Invalid value. */
+ /* Use for non-enumeration parameters, and
+ only when other error types are not suitable.
+ String: parameter description + "(should be <attribute>)",
+ e.g: "Maximum Rx buffer length (should be divisible by 8)",
+ "Channel number (should be even)". */
+ ,E_NOT_IN_RANGE = ERANGE/**< Parameter value is out of range. */
+ /* Don't use this error for enumeration parameters.
+ String: parameter description + "(should be %d-%d)",
+ e.g: "Number of pad characters (should be 0-15)". */
+ ,E_NOT_SUPPORTED = ENOSYS
+ /**< The function is not supported or not implemented. */
+ /* String: none. */
+ ,E_INVALID_STATE /**< The operation is not allowed in current module state. */
+ /* String: none. */
+ ,E_INVALID_HANDLE /**< Invalid handle of module or object. */
+ /* String: none, unless the function takes in more than one
+ handle (in this case add the handle description) */
+ ,E_INVALID_ID /**< Invalid module ID (usually enumeration or index). */
+ /* String: none, unless the function takes in more than one
+ ID (in this case add the ID description) */
+ ,E_NULL_POINTER /**< Unexpected NULL pointer. */
+ /* String: pointer description. */
+ ,E_INVALID_SELECTION /**< Invalid selection or mode. */
+ /* Use for enumeration values, only when other error types
+ are not suitable.
+ String: parameter description. */
+ ,E_INVALID_COMM_MODE /**< Invalid communication mode. */
+ /* String: none, unless the function takes in more than one
+ communication mode indications (in this case add
+ parameter description). */
+ ,E_INVALID_MEMORY_TYPE /**< Invalid memory type. */
+ /* String: none, unless the function takes in more than one
+ memory types (in this case add memory description,
+ e.g: "Data memory", "Buffer descriptors memory"). */
+ ,E_INVALID_CLOCK /**< Invalid clock. */
+ /* String: none, unless the function takes in more than one
+ clocks (in this case add clock description,
+ e.g: "Rx clock", "Tx clock"). */
+ ,E_CONFLICT /**< Some setting conflicts with another setting. */
+ /* String: description of the conflicting settings. */
+ ,E_NOT_ALIGNED /**< Non-aligned address. */
+ /* String: parameter description + "(should be %d-bytes aligned)",
+ e.g: "Rx data buffer (should be 32-bytes aligned)". */
+ ,E_NOT_FOUND /**< Requested resource or item was not found. */
+ /* Use only when the resource/item is uniquely identified.
+ String: none, unless the operation is not the main goal
+ of the function (in this case add item description). */
+ ,E_FULL /**< Resource is full. */
+ /* String: none, unless the operation is not the main goal
+ of the function (in this case add resource description). */
+ ,E_EMPTY /**< Resource is empty. */
+ /* String: none, unless the operation is not the main goal
+ of the function (in this case add resource description). */
+ ,E_ALREADY_FREE /**< Specified resource or item is already free or deleted. */
+ /* String: none, unless the operation is not the main goal
+ of the function (in this case add item description). */
+ ,E_READ_FAILED /**< Read access failed on memory/device. */
+ /* String: none, or device name. */
+ ,E_INVALID_FRAME /**< Invalid frame object (NULL handle or missing buffers). */
+ /* String: none. */
+ ,E_SEND_FAILED /**< Send operation failed on device. */
+ /* String: none, or device name. */
+ ,E_RECEIVE_FAILED /**< Receive operation failed on device. */
+ /* String: none, or device name. */
+ ,E_TIMEOUT/* = ETIMEDOUT*/ /**< The operation timed out. */
+ /* String: none. */
+
+ ,E_DUMMY_LAST /* NEVER USED */
+
+} e_ErrorType;
+
+/**************************************************************************//**
+ @Description Event Type Enumeration
+*//***************************************************************************/
+typedef enum e_Event /* Comments / Associated Flags and Message Strings */
+{ /* ------------------------------------------------------------ */
+ EV_NO_EVENT = 0 /**< No event; Never used. */
+
+ ,EV_RX_DISCARD /**< Received packet discarded (by the driver, and only for
+ complete packets);
+ Flags: error flags in case of error, zero otherwise. */
+ /* String: reason for discard, e.g: "Error in frame",
+ "Disordered frame", "Incomplete frame", "No frame object". */
+ ,EV_RX_ERROR /**< Receive error (by hardware/firmware);
+ Flags: usually status flags from the buffer descriptor. */
+ /* String: none. */
+ ,EV_TX_ERROR /**< Transmit error (by hardware/firmware);
+ Flags: usually status flags from the buffer descriptor. */
+ /* String: none. */
+ ,EV_NO_BUFFERS /**< System ran out of buffer objects;
+ Flags: zero. */
+ /* String: none. */
+ ,EV_NO_MB_FRAMES /**< System ran out of multi-buffer frame objects;
+ Flags: zero. */
+ /* String: none. */
+ ,EV_NO_SB_FRAMES /**< System ran out of single-buffer frame objects;
+ Flags: zero. */
+ /* String: none. */
+ ,EV_TX_QUEUE_FULL /**< Transmit queue is full;
+ Flags: zero. */
+ /* String: none. */
+ ,EV_RX_QUEUE_FULL /**< Receive queue is full;
+ Flags: zero. */
+ /* String: none. */
+ ,EV_INTR_QUEUE_FULL /**< Interrupt queue overflow;
+ Flags: zero. */
+ /* String: none. */
+ ,EV_NO_DATA_BUFFER /**< Data buffer allocation (from higher layer) failed;
+ Flags: zero. */
+ /* String: none. */
+ ,EV_OBJ_POOL_EMPTY /**< Objects pool is empty;
+ Flags: zero. */
+ /* String: object description (name). */
+ ,EV_BUS_ERROR /**< Illegal access on bus;
+ Flags: the address (if available) or bus identifier */
+ /* String: bus/address/module description. */
+ ,EV_PTP_TXTS_QUEUE_FULL /**< PTP Tx timestamps queue is full;
+ Flags: zero. */
+ /* String: none. */
+ ,EV_PTP_RXTS_QUEUE_FULL /**< PTP Rx timestamps queue is full;
+ Flags: zero. */
+ /* String: none. */
+ ,EV_DUMMY_LAST
+
+} e_Event;
+
+
+/**************************************************************************//**
+ @Collection Debug Levels for Errors and Events
+
+ The level description refers to errors only.
+ For events, classification is done by the user.
+
+ The TRACE, INFO and WARNING levels are allowed only when using
+ the DBG macro, and are not allowed when using the error macros
+ (RETURN_ERROR or REPORT_ERROR).
+ @{
+*//***************************************************************************/
+#define REPORT_LEVEL_CRITICAL 1 /**< Crasher: Incorrect flow, NULL pointers/handles. */
+#define REPORT_LEVEL_MAJOR 2 /**< Cannot proceed: Invalid operation, parameters or
+ configuration. */
+#define REPORT_LEVEL_MINOR 3 /**< Recoverable problem: a repeating call with the same
+ parameters may be successful. */
+#define REPORT_LEVEL_WARNING 4 /**< Something is not exactly right, yet it is not an error. */
+#define REPORT_LEVEL_INFO 5 /**< Messages which may be of interest to user/programmer. */
+#define REPORT_LEVEL_TRACE 6 /**< Program flow messages. */
+
+#define EVENT_DISABLED 0xFF /**< Disabled event (not reported at all) */
+
+/* @} */
+
+
+
+#define NO_MSG ("")
+
+#ifndef DEBUG_GLOBAL_LEVEL
+#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_WARNING
+#endif /* DEBUG_GLOBAL_LEVEL */
+
+#ifndef ERROR_GLOBAL_LEVEL
+#define ERROR_GLOBAL_LEVEL DEBUG_GLOBAL_LEVEL
+#endif /* ERROR_GLOBAL_LEVEL */
+
+#ifndef EVENT_GLOBAL_LEVEL
+#define EVENT_GLOBAL_LEVEL REPORT_LEVEL_MINOR
+#endif /* EVENT_GLOBAL_LEVEL */
+
+#ifdef EVENT_LOCAL_LEVEL
+#define EVENT_DYNAMIC_LEVEL EVENT_LOCAL_LEVEL
+#else
+#define EVENT_DYNAMIC_LEVEL EVENT_GLOBAL_LEVEL
+#endif /* EVENT_LOCAL_LEVEL */
+
+
+#ifndef DEBUG_DYNAMIC_LEVEL
+#define DEBUG_USING_STATIC_LEVEL
+
+#ifdef DEBUG_STATIC_LEVEL
+#define DEBUG_DYNAMIC_LEVEL DEBUG_STATIC_LEVEL
+#else
+#define DEBUG_DYNAMIC_LEVEL DEBUG_GLOBAL_LEVEL
+#endif /* DEBUG_STATIC_LEVEL */
+
+#else /* DEBUG_DYNAMIC_LEVEL */
+#ifdef DEBUG_STATIC_LEVEL
+#error "Please use either DEBUG_STATIC_LEVEL or DEBUG_DYNAMIC_LEVEL (not both)"
+#else
+int DEBUG_DYNAMIC_LEVEL = DEBUG_GLOBAL_LEVEL;
+#endif /* DEBUG_STATIC_LEVEL */
+#endif /* !DEBUG_DYNAMIC_LEVEL */
+
+
+#ifndef ERROR_DYNAMIC_LEVEL
+
+#ifdef ERROR_STATIC_LEVEL
+#define ERROR_DYNAMIC_LEVEL ERROR_STATIC_LEVEL
+#else
+#define ERROR_DYNAMIC_LEVEL ERROR_GLOBAL_LEVEL
+#endif /* ERROR_STATIC_LEVEL */
+
+#else /* ERROR_DYNAMIC_LEVEL */
+#ifdef ERROR_STATIC_LEVEL
+#error "Please use either ERROR_STATIC_LEVEL or ERROR_DYNAMIC_LEVEL (not both)"
+#else
+int ERROR_DYNAMIC_LEVEL = ERROR_GLOBAL_LEVEL;
+#endif /* ERROR_STATIC_LEVEL */
+#endif /* !ERROR_DYNAMIC_LEVEL */
+
+#define PRINT_FORMAT "[CPU%02d, %s:%d %s]"
+#define PRINT_FMT_PARAMS CORE_GetId(), __FILE__, __LINE__, __FUNCTION__
+
+#if (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0))
+/* No debug/error/event messages at all */
+#define DBG(_level, _vmsg)
+
+#define REPORT_ERROR(_level, _err, _vmsg)
+
+#define RETURN_ERROR(_level, _err, _vmsg) \
+ return ERROR_CODE(_err)
+
+#if (REPORT_EVENTS > 0)
+
+#define REPORT_EVENT(_ev, _appId, _flg, _vmsg) \
+ do { \
+ if (_ev##_LEVEL <= EVENT_DYNAMIC_LEVEL) { \
+ XX_EventById((uint32_t)(_ev), (t_Handle)(_appId), (uint16_t)(_flg), NO_MSG); \
+ } \
+ } while (0)
+
+#else
+
+#define REPORT_EVENT(_ev, _appId, _flg, _vmsg)
+
+#endif /* (REPORT_EVENTS > 0) */
+
+
+#else /* DEBUG_ERRORS > 0 */
+
+extern const char *dbgLevelStrings[];
+extern const char *moduleStrings[];
+#if (REPORT_EVENTS > 0)
+extern const char *eventStrings[];
+#endif /* (REPORT_EVENTS > 0) */
+
+char * ErrTypeStrings (e_ErrorType err);
+
+
+#if ((defined(DEBUG_USING_STATIC_LEVEL)) && (DEBUG_DYNAMIC_LEVEL < REPORT_LEVEL_WARNING))
+/* No need for DBG macro - debug level is higher anyway */
+#define DBG(_level, _vmsg)
+#else
+#define DBG(_level, _vmsg) \
+ do { \
+ if (REPORT_LEVEL_##_level <= DEBUG_DYNAMIC_LEVEL) { \
+ XX_Print("> %s (%s) " PRINT_FORMAT ": ", \
+ dbgLevelStrings[REPORT_LEVEL_##_level - 1], \
+ moduleStrings[__ERR_MODULE__ >> 16], \
+ PRINT_FMT_PARAMS); \
+ XX_Print _vmsg; \
+ XX_Print("\r\n"); \
+ } \
+ } while (0)
+#endif /* (defined(DEBUG_USING_STATIC_LEVEL) && (DEBUG_DYNAMIC_LEVEL < WARNING)) */
+
+
+#define REPORT_ERROR(_level, _err, _vmsg) \
+ do { \
+ if (REPORT_LEVEL_##_level <= ERROR_DYNAMIC_LEVEL) { \
+ XX_Print("! %s %s Error " PRINT_FORMAT ": %s; ", \
+ dbgLevelStrings[REPORT_LEVEL_##_level - 1], \
+ moduleStrings[__ERR_MODULE__ >> 16], \
+ PRINT_FMT_PARAMS, \
+ ErrTypeStrings((e_ErrorType)GET_ERROR_TYPE(_err))); \
+ XX_Print _vmsg; \
+ XX_Print("\r\n"); \
+ } \
+ } while (0)
+
+
+#define RETURN_ERROR(_level, _err, _vmsg) \
+ do { \
+ REPORT_ERROR(_level, (_err), _vmsg); \
+ return ERROR_CODE(_err); \
+ } while (0)
+
+
+#if (REPORT_EVENTS > 0)
+
+#define REPORT_EVENT(_ev, _appId, _flg, _vmsg) \
+ do { \
+ if (_ev##_LEVEL <= EVENT_DYNAMIC_LEVEL) { \
+ XX_Print("~ %s %s Event " PRINT_FORMAT ": %s (flags: 0x%04x); ", \
+ dbgLevelStrings[_ev##_LEVEL - 1], \
+ moduleStrings[__ERR_MODULE__ >> 16], \
+ PRINT_FMT_PARAMS, \
+ eventStrings[((_ev) - EV_NO_EVENT - 1)], \
+ (uint16_t)(_flg)); \
+ XX_Print _vmsg; \
+ XX_Print("\r\n"); \
+ XX_EventById((uint32_t)(_ev), (t_Handle)(_appId), (uint16_t)(_flg), NO_MSG); \
+ } \
+ } while (0)
+
+#else /* not REPORT_EVENTS */
+
+#define REPORT_EVENT(_ev, _appId, _flg, _vmsg)
+
+#endif /* (REPORT_EVENTS > 0) */
+
+#endif /* (DEBUG_ERRORS > 0) */
+
+
+/**************************************************************************//**
+ @Function ASSERT_COND
+
+ @Description Assertion macro.
+
+ @Param[in] _cond - The condition being checked, in positive form;
+ Failure of the condition triggers the assert.
+*//***************************************************************************/
+#ifdef DISABLE_ASSERTIONS
+#define ASSERT_COND(_cond)
+#else
+#define ASSERT_COND(_cond) \
+ do { \
+ if (!(_cond)) { \
+ XX_Print("*** ASSERT_COND failed " PRINT_FORMAT "\r\n", \
+ PRINT_FMT_PARAMS); \
+ XX_Exit(1); \
+ } \
+ } while (0)
+#endif /* DISABLE_ASSERTIONS */
+
+
+#ifdef DISABLE_INIT_PARAMETERS_CHECK
+
+#define CHECK_INIT_PARAMETERS(handle, f_check)
+#define CHECK_INIT_PARAMETERS_RETURN_VALUE(handle, f_check, retval)
+
+#else
+
+#define CHECK_INIT_PARAMETERS(handle, f_check) \
+ do { \
+ t_Error err = f_check(handle); \
+ if (err != E_OK) { \
+ RETURN_ERROR(MAJOR, err, NO_MSG); \
+ } \
+ } while (0)
+
+#define CHECK_INIT_PARAMETERS_RETURN_VALUE(handle, f_check, retval) \
+ do { \
+ t_Error err = f_check(handle); \
+ if (err != E_OK) { \
+ REPORT_ERROR(MAJOR, err, NO_MSG); \
+ return (retval); \
+ } \
+ } while (0)
+
+#endif /* DISABLE_INIT_PARAMETERS_CHECK */
+
+#ifdef DISABLE_SANITY_CHECKS
+
+#define SANITY_CHECK_RETURN_ERROR(_cond, _err)
+#define SANITY_CHECK_RETURN_VALUE(_cond, _err, retval)
+#define SANITY_CHECK_RETURN(_cond, _err)
+#define SANITY_CHECK_EXIT(_cond, _err)
+
+#else /* DISABLE_SANITY_CHECKS */
+
+#define SANITY_CHECK_RETURN_ERROR(_cond, _err) \
+ do { \
+ if (!(_cond)) { \
+ RETURN_ERROR(CRITICAL, (_err), NO_MSG); \
+ } \
+ } while (0)
+
+#define SANITY_CHECK_RETURN_VALUE(_cond, _err, retval) \
+ do { \
+ if (!(_cond)) { \
+ REPORT_ERROR(CRITICAL, (_err), NO_MSG); \
+ return (retval); \
+ } \
+ } while (0)
+
+#define SANITY_CHECK_RETURN(_cond, _err) \
+ do { \
+ if (!(_cond)) { \
+ REPORT_ERROR(CRITICAL, (_err), NO_MSG); \
+ return; \
+ } \
+ } while (0)
+
+#define SANITY_CHECK_EXIT(_cond, _err) \
+ do { \
+ if (!(_cond)) { \
+ REPORT_ERROR(CRITICAL, (_err), NO_MSG); \
+ XX_Exit(1); \
+ } \
+ } while (0)
+
+#endif /* DISABLE_SANITY_CHECKS */
+
+/** @} */ /* end of Debug/error Utils group */
+
+/** @} */ /* end of General Utils group */
+
+#endif /* __ERROR_EXT_H */
+
+
diff --git a/drivers/net/ethernet/freescale/fman/inc/etc/list_ext.h b/drivers/net/ethernet/freescale/fman/inc/etc/list_ext.h
new file mode 100644
index 0000000..ee6b9f2
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/etc/list_ext.h
@@ -0,0 +1,358 @@
+/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+
+ @File list_ext.h
+
+ @Description External prototypes for list.c
+*//***************************************************************************/
+
+#ifndef __LIST_EXT_H
+#define __LIST_EXT_H
+
+
+#include "std_ext.h"
+
+
+/**************************************************************************//**
+ @Group etc_id Utility Library Application Programming Interface
+
+ @Description External routines.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group list_id List
+
+ @Description List module functions,definitions and enums.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Description List structure.
+*//***************************************************************************/
+typedef struct List
+{
+ struct List *p_Next; /**< A pointer to the next list object */
+ struct List *p_Prev; /**< A pointer to the previous list object */
+} t_List;
+
+
+/**************************************************************************//**
+ @Function LIST_FIRST/LIST_LAST/LIST_NEXT/LIST_PREV
+
+ @Description Macro to get first/last/next/previous entry in a list.
+
+ @Param[in] p_List - A pointer to a list.
+*//***************************************************************************/
+#define LIST_FIRST(p_List) (p_List)->p_Next
+#define LIST_LAST(p_List) (p_List)->p_Prev
+#define LIST_NEXT LIST_FIRST
+#define LIST_PREV LIST_LAST
+
+
+/**************************************************************************//**
+ @Function LIST_INIT
+
+ @Description Macro for initialization of a list struct.
+
+ @Param[in] lst - The t_List object to initialize.
+*//***************************************************************************/
+#define LIST_INIT(lst) {&(lst), &(lst)}
+
+
+/**************************************************************************//**
+ @Function LIST
+
+ @Description Macro to declare of a list.
+
+ @Param[in] listName - The list object name.
+*//***************************************************************************/
+#define LIST(listName) t_List listName = LIST_INIT(listName)
+
+
+/**************************************************************************//**
+ @Function INIT_LIST
+
+ @Description Macro to initialize a list pointer.
+
+ @Param[in] p_List - The list pointer.
+*//***************************************************************************/
+#define INIT_LIST(p_List) LIST_FIRST(p_List) = LIST_LAST(p_List) = (p_List)
+
+
+/**************************************************************************//**
+ @Function LIST_OBJECT
+
+ @Description Macro to get the struct (object) for this entry.
+
+ @Param[in] type - The type of the struct (object) this list is embedded in.
+ @Param[in] member - The name of the t_List object within the struct.
+
+ @Return The structure pointer for this entry.
+*//***************************************************************************/
+#define MEMBER_OFFSET(type, member) (PTR_TO_UINT(&((type *)0)->member))
+#define LIST_OBJECT(p_List, type, member) \
+ ((type *)((char *)(p_List)-MEMBER_OFFSET(type, member)))
+
+
+/**************************************************************************//**
+ @Function LIST_FOR_EACH
+
+ @Description Macro to iterate over a list.
+
+ @Param[in] p_Pos - A pointer to a list to use as a loop counter.
+ @Param[in] p_Head - A pointer to the head for your list pointer.
+
+ @Cautions You can't delete items with this routine.
+ For deletion use LIST_FOR_EACH_SAFE().
+*//***************************************************************************/
+#define LIST_FOR_EACH(p_Pos, p_Head) \
+ for (p_Pos = LIST_FIRST(p_Head); p_Pos != (p_Head); p_Pos = LIST_NEXT(p_Pos))
+
+
+/**************************************************************************//**
+ @Function LIST_FOR_EACH_SAFE
+
+ @Description Macro to iterate over a list safe against removal of list entry.
+
+ @Param[in] p_Pos - A pointer to a list to use as a loop counter.
+ @Param[in] p_Tmp - Another pointer to a list to use as temporary storage.
+ @Param[in] p_Head - A pointer to the head for your list pointer.
+*//***************************************************************************/
+#define LIST_FOR_EACH_SAFE(p_Pos, p_Tmp, p_Head) \
+ for (p_Pos = LIST_FIRST(p_Head), p_Tmp = LIST_FIRST(p_Pos); \
+ p_Pos != (p_Head); \
+ p_Pos = p_Tmp, p_Tmp = LIST_NEXT(p_Pos))
+
+
+/**************************************************************************//**
+ @Function LIST_FOR_EACH_OBJECT_SAFE
+
+ @Description Macro to iterate over list of given type safely.
+
+ @Param[in] p_Pos - A pointer to a list to use as a loop counter.
+ @Param[in] p_Tmp - Another pointer to a list to use as temporary storage.
+ @Param[in] type - The type of the struct this is embedded in.
+ @Param[in] p_Head - A pointer to the head for your list pointer.
+ @Param[in] member - The name of the list_struct within the struct.
+
+ @Cautions You can't delete items with this routine.
+ For deletion use LIST_FOR_EACH_SAFE().
+*//***************************************************************************/
+#define LIST_FOR_EACH_OBJECT_SAFE(p_Pos, p_Tmp, p_Head, type, member) \
+ for (p_Pos = LIST_OBJECT(LIST_FIRST(p_Head), type, member), \
+ p_Tmp = LIST_OBJECT(LIST_FIRST(&p_Pos->member), type, member); \
+ &p_Pos->member != (p_Head); \
+ p_Pos = p_Tmp, \
+ p_Tmp = LIST_OBJECT(LIST_FIRST(&p_Pos->member), type, member))
+
+/**************************************************************************//**
+ @Function LIST_FOR_EACH_OBJECT
+
+ @Description Macro to iterate over list of given type.
+
+ @Param[in] p_Pos - A pointer to a list to use as a loop counter.
+ @Param[in] type - The type of the struct this is embedded in.
+ @Param[in] p_Head - A pointer to the head for your list pointer.
+ @Param[in] member - The name of the list_struct within the struct.
+
+ @Cautions You can't delete items with this routine.
+ For deletion use LIST_FOR_EACH_SAFE().
+*//***************************************************************************/
+#define LIST_FOR_EACH_OBJECT(p_Pos, type, p_Head, member) \
+ for (p_Pos = LIST_OBJECT(LIST_FIRST(p_Head), type, member); \
+ &p_Pos->member != (p_Head); \
+ p_Pos = LIST_OBJECT(LIST_FIRST(&(p_Pos->member)), type, member))
+
+
+/**************************************************************************//**
+ @Function LIST_Add
+
+ @Description Add a new entry to a list.
+
+ Insert a new entry after the specified head.
+ This is good for implementing stacks.
+
+ @Param[in] p_New - A pointer to a new list entry to be added.
+ @Param[in] p_Head - A pointer to a list head to add it after.
+
+ @Return none.
+*//***************************************************************************/
+static __inline__ void LIST_Add(t_List *p_New, t_List *p_Head)
+{
+ LIST_PREV(LIST_NEXT(p_Head)) = p_New;
+ LIST_NEXT(p_New) = LIST_NEXT(p_Head);
+ LIST_PREV(p_New) = p_Head;
+ LIST_NEXT(p_Head) = p_New;
+}
+
+
+/**************************************************************************//**
+ @Function LIST_AddToTail
+
+ @Description Add a new entry to a list.
+
+ Insert a new entry before the specified head.
+ This is useful for implementing queues.
+
+ @Param[in] p_New - A pointer to a new list entry to be added.
+ @Param[in] p_Head - A pointer to a list head to add it before.
+
+ @Return none.
+*//***************************************************************************/
+static __inline__ void LIST_AddToTail(t_List *p_New, t_List *p_Head)
+{
+ LIST_NEXT(LIST_PREV(p_Head)) = p_New;
+ LIST_PREV(p_New) = LIST_PREV(p_Head);
+ LIST_NEXT(p_New) = p_Head;
+ LIST_PREV(p_Head) = p_New;
+}
+
+
+/**************************************************************************//**
+ @Function LIST_Del
+
+ @Description Deletes entry from a list.
+
+ @Param[in] p_Entry - A pointer to the element to delete from the list.
+
+ @Return none.
+
+ @Cautions LIST_IsEmpty() on entry does not return true after this,
+ the entry is in an undefined state.
+*//***************************************************************************/
+static __inline__ void LIST_Del(t_List *p_Entry)
+{
+ LIST_PREV(LIST_NEXT(p_Entry)) = LIST_PREV(p_Entry);
+ LIST_NEXT(LIST_PREV(p_Entry)) = LIST_NEXT(p_Entry);
+}
+
+
+/**************************************************************************//**
+ @Function LIST_DelAndInit
+
+ @Description Deletes entry from list and reinitialize it.
+
+ @Param[in] p_Entry - A pointer to the element to delete from the list.
+
+ @Return none.
+*//***************************************************************************/
+static __inline__ void LIST_DelAndInit(t_List *p_Entry)
+{
+ LIST_Del(p_Entry);
+ INIT_LIST(p_Entry);
+}
+
+
+/**************************************************************************//**
+ @Function LIST_Move
+
+ @Description Delete from one list and add as another's head.
+
+ @Param[in] p_Entry - A pointer to the list entry to move.
+ @Param[in] p_Head - A pointer to the list head that will precede our entry.
+
+ @Return none.
+*//***************************************************************************/
+static __inline__ void LIST_Move(t_List *p_Entry, t_List *p_Head)
+{
+ LIST_Del(p_Entry);
+ LIST_Add(p_Entry, p_Head);
+}
+
+
+/**************************************************************************//**
+ @Function LIST_MoveToTail
+
+ @Description Delete from one list and add as another's tail.
+
+ @Param[in] p_Entry - A pointer to the entry to move.
+ @Param[in] p_Head - A pointer to the list head that will follow our entry.
+
+ @Return none.
+*//***************************************************************************/
+static __inline__ void LIST_MoveToTail(t_List *p_Entry, t_List *p_Head)
+{
+ LIST_Del(p_Entry);
+ LIST_AddToTail(p_Entry, p_Head);
+}
+
+
+/**************************************************************************//**
+ @Function LIST_IsEmpty
+
+ @Description Tests whether a list is empty.
+
+ @Param[in] p_List - A pointer to the list to test.
+
+ @Return 1 if the list is empty, 0 otherwise.
+*//***************************************************************************/
+static __inline__ int LIST_IsEmpty(t_List *p_List)
+{
+ return (LIST_FIRST(p_List) == p_List);
+}
+
+
+/**************************************************************************//**
+ @Function LIST_Append
+
+ @Description Join two lists.
+
+ @Param[in] p_NewList - A pointer to the new list to add.
+ @Param[in] p_Head - A pointer to the place to add it in the first list.
+
+ @Return none.
+*//***************************************************************************/
+void LIST_Append(t_List *p_NewList, t_List *p_Head);
+
+
+/**************************************************************************//**
+ @Function LIST_NumOfObjs
+
+ @Description Counts number of objects in the list
+
+ @Param[in] p_List - A pointer to the list which objects are to be counted.
+
+ @Return Number of objects in the list.
+*//***************************************************************************/
+int LIST_NumOfObjs(t_List *p_List);
+
+/** @} */ /* end of list_id group */
+/** @} */ /* end of etc_id group */
+
+
+#endif /* __LIST_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/etc/mem_ext.h b/drivers/net/ethernet/freescale/fman/inc/etc/mem_ext.h
new file mode 100644
index 0000000..d0565d4
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/etc/mem_ext.h
@@ -0,0 +1,318 @@
+/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+
+ @File mem_ext.h
+
+ @Description External prototypes for the memory manager object
+*//***************************************************************************/
+
+#ifndef __MEM_EXT_H
+#define __MEM_EXT_H
+
+#include "std_ext.h"
+#include "part_ext.h"
+
+
+/**************************************************************************//**
+ @Group etc_id Utility Library Application Programming Interface
+
+ @Description External routines.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group mem_id Slab Memory Manager
+
+ @Description Slab Memory Manager module functions, definitions and enums.
+
+ @{
+*//***************************************************************************/
+
+/* Each block is of the following structure:
+ *
+ *
+ * +-----------+----------+---------------------------+-----------+-----------+
+ * | Alignment | Prefix | Data | Postfix | Alignment |
+ * | field | field | field | field | Padding |
+ * | | | | | |
+ * +-----------+----------+---------------------------+-----------+-----------+
+ * and at the beginning of all bytes, an additional optional padding might reside
+ * to ensure that the first blocks data field is aligned as requested.
+ */
+
+
+#define MEM_MAX_NAME_LENGTH 8
+
+/**************************************************************************//*
+ @Description Memory Segment structure
+*//***************************************************************************/
+
+typedef struct
+{
+ char name[MEM_MAX_NAME_LENGTH];
+ /* The segment's name */
+ uint8_t **p_Bases; /* Base addresses of the segments */
+ uint8_t **p_BlocksStack; /* Array of pointers to blocks */
+ t_Handle h_Spinlock;
+ uint16_t dataSize; /* Size of each data block */
+ uint16_t prefixSize; /* How many bytes to reserve before the data */
+ uint16_t postfixSize; /* How many bytes to reserve after the data */
+ uint16_t alignment; /* Requested alignment for the data field */
+ int allocOwner; /* Memory allocation owner */
+ uint32_t getFailures; /* Number of times get failed */
+ uint32_t num; /* Number of blocks in segment */
+ uint32_t current; /* Current block */
+ bool consecutiveMem; /* Allocate consecutive data blocks memory */
+#ifdef DEBUG_MEM_LEAKS
+ void *p_MemDbg; /* MEM debug database (MEM leaks detection) */
+ uint32_t blockOffset;
+ uint32_t blockSize;
+#endif /* DEBUG_MEM_LEAKS */
+} t_MemorySegment;
+
+
+
+/**************************************************************************//**
+ @Function MEM_Init
+
+ @Description Create a new memory segment.
+
+ @Param[in] name - Name of memory partition.
+ @Param[in] p_Handle - Handle to new segment is returned through here.
+ @Param[in] num - Number of blocks in new segment.
+ @Param[in] dataSize - Size of blocks in segment.
+ @Param[in] prefixSize - How many bytes to allocate before the data.
+ @Param[in] postfixSize - How many bytes to allocate after the data.
+ @Param[in] alignment - Requested alignment for data field (in bytes).
+
+ @Return E_OK - success, E_NO_MEMORY - out of memory.
+*//***************************************************************************/
+t_Error MEM_Init(char name[],
+ t_Handle *p_Handle,
+ uint32_t num,
+ uint16_t dataSize,
+ uint16_t prefixSize,
+ uint16_t postfixSize,
+ uint16_t alignment);
+
+/**************************************************************************//**
+ @Function MEM_InitSmart
+
+ @Description Create a new memory segment.
+
+ @Param[in] name - Name of memory partition.
+ @Param[in] p_Handle - Handle to new segment is returned through here.
+ @Param[in] num - Number of blocks in new segment.
+ @Param[in] dataSize - Size of blocks in segment.
+ @Param[in] prefixSize - How many bytes to allocate before the data.
+ @Param[in] postfixSize - How many bytes to allocate after the data.
+ @Param[in] alignment - Requested alignment for data field (in bytes).
+ @Param[in] memPartitionId - Memory partition ID for allocation.
+ @Param[in] consecutiveMem - Whether to allocate the memory blocks
+ continuously or not.
+
+ @Return E_OK - success, E_NO_MEMORY - out of memory.
+*//***************************************************************************/
+t_Error MEM_InitSmart(char name[],
+ t_Handle *p_Handle,
+ uint32_t num,
+ uint16_t dataSize,
+ uint16_t prefixSize,
+ uint16_t postfixSize,
+ uint16_t alignment,
+ uint8_t memPartitionId,
+ bool consecutiveMem);
+
+/**************************************************************************//**
+ @Function MEM_InitByAddress
+
+ @Description Create a new memory segment with a specified base address.
+
+ @Param[in] name - Name of memory partition.
+ @Param[in] p_Handle - Handle to new segment is returned through here.
+ @Param[in] num - Number of blocks in new segment.
+ @Param[in] dataSize - Size of blocks in segment.
+ @Param[in] prefixSize - How many bytes to allocate before the data.
+ @Param[in] postfixSize - How many bytes to allocate after the data.
+ @Param[in] alignment - Requested alignment for data field (in bytes).
+ @Param[in] address - The required base address.
+
+ @Return E_OK - success, E_NO_MEMORY - out of memory.
+ *//***************************************************************************/
+t_Error MEM_InitByAddress(char name[],
+ t_Handle *p_Handle,
+ uint32_t num,
+ uint16_t dataSize,
+ uint16_t prefixSize,
+ uint16_t postfixSize,
+ uint16_t alignment,
+ uint8_t *address);
+
+/**************************************************************************//**
+ @Function MEM_Free
+
+ @Description Free a specific memory segment.
+
+ @Param[in] h_Mem - Handle to memory segment.
+
+ @Return None.
+*//***************************************************************************/
+void MEM_Free(t_Handle h_Mem);
+
+/**************************************************************************//**
+ @Function MEM_Get
+
+ @Description Get a block of memory from a segment.
+
+ @Param[in] h_Mem - Handle to memory segment.
+
+ @Return Pointer to new memory block on success,0 otherwise.
+*//***************************************************************************/
+void * MEM_Get(t_Handle h_Mem);
+
+/**************************************************************************//**
+ @Function MEM_GetN
+
+ @Description Get up to N blocks of memory from a segment.
+
+ The blocks are assumed to be of a fixed size (one size per segment).
+
+ @Param[in] h_Mem - Handle to memory segment.
+ @Param[in] num - Number of blocks to allocate.
+ @Param[out] array - Array of at least num pointers to which the addresses
+ of the allocated blocks are written.
+
+ @Return The number of blocks actually allocated.
+
+ @Cautions Interrupts are disabled for all of the allocation loop.
+ Although this loop is very short for each block (several machine
+ instructions), you should not allocate a very large number
+ of blocks via this routine.
+*//***************************************************************************/
+uint16_t MEM_GetN(t_Handle h_Mem, uint32_t num, void *array[]);
+
+/**************************************************************************//**
+ @Function MEM_Put
+
+ @Description Put a block of memory back to a segment.
+
+ @Param[in] h_Mem - Handle to memory segment.
+ @Param[in] p_Block - The block to return.
+
+ @Return Pointer to new memory block on success,0 otherwise.
+*//***************************************************************************/
+t_Error MEM_Put(t_Handle h_Mem, void *p_Block);
+
+/**************************************************************************//**
+ @Function MEM_ComputePartitionSize
+
+ @Description calculate a tight upper boundary of the size of a partition with
+ given attributes.
+
+ The returned value is suitable if one wants to use MEM_InitByAddress().
+
+ @Param[in] num - The number of blocks in the segment.
+ @Param[in] dataSize - Size of block to get.
+ @Param[in] prefixSize - The prefix size
+ @Param postfixSize - The postfix size
+ @Param[in] alignment - The requested alignment value (in bytes)
+
+ @Return The memory block size a segment with the given attributes needs.
+*//***************************************************************************/
+uint32_t MEM_ComputePartitionSize(uint32_t num,
+ uint16_t dataSize,
+ uint16_t prefixSize,
+ uint16_t postfixSize,
+ uint16_t alignment);
+
+#ifdef DEBUG_MEM_LEAKS
+#if !((defined(__MWERKS__) || defined(__GNUC__)) && (__dest_os == __ppc_eabi))
+#error "Memory-Leaks-Debug option is supported only for freescale CodeWarrior"
+#endif /* !(defined(__MWERKS__) && ... */
+
+/**************************************************************************//**
+ @Function MEM_CheckLeaks
+
+ @Description Report MEM object leaks.
+
+ This routine is automatically called by the MEM_Free() routine,
+ but it can also be invoked while the MEM object is alive.
+
+ @Param[in] h_Mem - Handle to memory segment.
+
+ @Return None.
+*//***************************************************************************/
+void MEM_CheckLeaks(t_Handle h_Mem);
+
+#else /* not DEBUG_MEM_LEAKS */
+#define MEM_CheckLeaks(h_Mem)
+#endif /* not DEBUG_MEM_LEAKS */
+
+/**************************************************************************//**
+ @Description Get base of MEM
+*//***************************************************************************/
+#define MEM_GetBase(h_Mem) ((t_MemorySegment *)(h_Mem))->p_Bases[0]
+
+/**************************************************************************//**
+ @Description Get size of MEM block
+*//***************************************************************************/
+#define MEM_GetSize(h_Mem) ((t_MemorySegment *)(h_Mem))->dataSize
+
+/**************************************************************************//**
+ @Description Get prefix size of MEM block
+*//***************************************************************************/
+#define MEM_GetPrefixSize(h_Mem) ((t_MemorySegment *)(h_Mem))->prefixSize
+
+/**************************************************************************//**
+ @Description Get postfix size of MEM block
+*//***************************************************************************/
+#define MEM_GetPostfixSize(h_Mem) ((t_MemorySegment *)(h_Mem))->postfixSize
+
+/**************************************************************************//**
+ @Description Get alignment of MEM block (in bytes)
+*//***************************************************************************/
+#define MEM_GetAlignment(h_Mem) ((t_MemorySegment *)(h_Mem))->alignment
+
+/**************************************************************************//**
+ @Description Get the number of blocks in the segment
+*//***************************************************************************/
+#define MEM_GetNumOfBlocks(h_Mem) ((t_MemorySegment *)(h_Mem))->num
+
+/** @} */ /* end of MEM group */
+/** @} */ /* end of etc_id group */
+
+
+#endif /* __MEM_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/etc/memcpy_ext.h b/drivers/net/ethernet/freescale/fman/inc/etc/memcpy_ext.h
new file mode 100644
index 0000000..cc5bb72
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/etc/memcpy_ext.h
@@ -0,0 +1,174 @@
+/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+
+ @File memcpy_ext.h
+
+ @Description Efficient functions for copying and setting blocks of memory.
+*//***************************************************************************/
+
+#ifndef __MEMCPY_EXT_H
+#define __MEMCPY_EXT_H
+
+#include "std_ext.h"
+
+
+/**************************************************************************//**
+ @Group etc_id Utility Library Application Programming Interface
+
+ @Description External routines.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group mem_cpy Memory Copy
+
+ @Description Memory Copy module functions,definitions and enums.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Function MemCpy32
+
+ @Description Copies one memory buffer into another one in 4-byte chunks!
+ Which should be more efficient than byte by byte.
+
+ For large buffers (over 60 bytes) this function is about 4 times
+ more efficient than the trivial memory copy. For short buffers
+ it is reduced to the trivial copy and may be a bit worse.
+
+ @Param[in] pDst - The address of the destination buffer.
+ @Param[in] pSrc - The address of the source buffer.
+ @Param[in] size - The number of bytes that will be copied from pSrc to pDst.
+
+ @Return pDst (the address of the destination buffer).
+
+ @Cautions There is no parameter or boundary checking! It is up to the user
+ to supply non-null parameters as source & destination and size
+ that actually fits into the destination buffer.
+*//***************************************************************************/
+void * MemCpy32(void* pDst,void* pSrc, uint32_t size);
+void * IO2IOCpy32(void* pDst,void* pSrc, uint32_t size);
+void * IO2MemCpy32(void* pDst,void* pSrc, uint32_t size);
+void * Mem2IOCpy32(void* pDst,void* pSrc, uint32_t size);
+
+/**************************************************************************//**
+ @Function MemCpy64
+
+ @Description Copies one memory buffer into another one in 8-byte chunks!
+ Which should be more efficient than byte by byte.
+
+ For large buffers (over 60 bytes) this function is about 8 times
+ more efficient than the trivial memory copy. For short buffers
+ it is reduced to the trivial copy and may be a bit worse.
+
+ Some testing suggests that MemCpy32() preforms better than
+ MemCpy64() over small buffers. On average they break even at
+ 100 byte buffers. For buffers larger than that MemCpy64 is
+ superior.
+
+ @Param[in] pDst - The address of the destination buffer.
+ @Param[in] pSrc - The address of the source buffer.
+ @Param[in] size - The number of bytes that will be copied from pSrc to pDst.
+
+ @Return pDst (the address of the destination buffer).
+
+ @Cautions There is no parameter or boundary checking! It is up to the user
+ to supply non null parameters as source & destination and size
+ that actually fits into their buffer.
+
+ Do not use under Linux.
+*//***************************************************************************/
+void * MemCpy64(void* pDst,void* pSrc, uint32_t size);
+
+/**************************************************************************//**
+ @Function MemSet32
+
+ @Description Sets all bytes of a memory buffer to a specific value, in
+ 4-byte chunks.
+
+ @Param[in] pDst - The address of the destination buffer.
+ @Param[in] val - Value to set destination bytes to.
+ @Param[in] size - The number of bytes that will be set to val.
+
+ @Return pDst (the address of the destination buffer).
+
+ @Cautions There is no parameter or boundary checking! It is up to the user
+ to supply non null parameter as destination and size
+ that actually fits into the destination buffer.
+*//***************************************************************************/
+void * MemSet32(void* pDst, uint8_t val, uint32_t size);
+void * IOMemSet32(void* pDst, uint8_t val, uint32_t size);
+
+/**************************************************************************//**
+ @Function MemSet64
+
+ @Description Sets all bytes of a memory buffer to a specific value, in
+ 8-byte chunks.
+
+ @Param[in] pDst - The address of the destination buffer.
+ @Param[in] val - Value to set destination bytes to.
+ @Param[in] size - The number of bytes that will be set to val.
+
+ @Return pDst (the address of the destination buffer).
+
+ @Cautions There is no parameter or boundary checking! It is up to the user
+ to supply non null parameter as destination and size
+ that actually fits into the destination buffer.
+*//***************************************************************************/
+void * MemSet64(void* pDst, uint8_t val, uint32_t size);
+
+/**************************************************************************//**
+ @Function MemDisp
+
+ @Description Displays a block of memory in chunks of 32 bits.
+
+ @Param[in] addr - The address of the memory to display.
+ @Param[in] size - The number of bytes that will be displayed.
+
+ @Return None.
+
+ @Cautions There is no parameter or boundary checking! It is up to the user
+ to supply non null parameter as destination and size
+ that actually fits into the destination buffer.
+*//***************************************************************************/
+void MemDisp(uint8_t *addr, int size);
+
+/** @} */ /* end of mem_cpy group */
+/** @} */ /* end of etc_id group */
+
+
+#endif /* __MEMCPY_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/etc/mm_ext.h b/drivers/net/ethernet/freescale/fman/inc/etc/mm_ext.h
new file mode 100644
index 0000000..fa7c85e
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/etc/mm_ext.h
@@ -0,0 +1,310 @@
+/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File mm_ext.h
+
+ @Description Memory Manager Application Programming Interface
+*//***************************************************************************/
+#ifndef __MM_EXT
+#define __MM_EXT
+
+#include "std_ext.h"
+
+#define MM_MAX_ALIGNMENT 20 /* Alignments from 2 to 128 are available
+ where maximum alignment defined as
+ MM_MAX_ALIGNMENT power of 2 */
+
+#define MM_MAX_NAME_LEN 32
+
+/**************************************************************************//**
+ @Group etc_id Utility Library Application Programming Interface
+
+ @Description External routines.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group mm_grp Flexible Memory Manager
+
+ @Description Flexible Memory Manager module functions,definitions and enums.
+ (All of the following functions,definitions and enums can be found in mm_ext.h)
+
+ @{
+*//***************************************************************************/
+
+
+/**************************************************************************//**
+ @Function MM_Init
+
+ @Description Initializes a new MM object.
+
+ It initializes a new memory block consisting of base address
+ and size of the available memory by calling to MemBlock_Init
+ routine. It is also initializes a new free block for each
+ by calling FreeBlock_Init routine, which is pointed to
+ the almost all memory started from the required alignment
+ from the base address and to the end of the memory.
+ The handle to the new MM object is returned via "MM"
+ argument (passed by reference).
+
+ @Param[in] h_MM - Handle to the MM object.
+ @Param[in] base - Base address of the MM.
+ @Param[in] size - Size of the MM.
+
+ @Return E_OK is returned on success. E_NOMEMORY is returned if the new MM object or a new free block can not be initialized.
+*//***************************************************************************/
+t_Error MM_Init(t_Handle *h_MM, uint64_t base, uint64_t size);
+
+/**************************************************************************//**
+ @Function MM_Get
+
+ @Description Allocates a block of memory according to the given size and the alignment.
+
+ The Alignment argument tells from which
+ free list allocate a block of memory. 2^alignment indicates
+ the alignment that the base address of the allocated block
+ should have. So, the only values 1, 2, 4, 8, 16, 32 and 64
+ are available for the alignment argument.
+ The routine passes through the specific free list of free
+ blocks and seeks for a first block that have anough memory
+ that is required (best fit).
+ After the block is found and data is allocated, it calls
+ the internal MM_CutFree routine to update all free lists
+ do not include a just allocated block. Of course, each
+ free list contains a free blocks with the same alignment.
+ It is also creates a busy block that holds
+ information about an allocated block.
+
+ @Param[in] h_MM - Handle to the MM object.
+ @Param[in] size - Size of the MM.
+ @Param[in] alignment - Index as a power of two defines a required
+ alignment (in bytes); Should be 1, 2, 4, 8, 16, 32 or 64
+ @Param[in] name - The name that specifies an allocated block.
+
+ @Return base address of an allocated block ILLEGAL_BASE if can't allocate a block
+*//***************************************************************************/
+uint64_t MM_Get(t_Handle h_MM, uint64_t size, uint64_t alignment, char *name);
+
+/**************************************************************************//**
+ @Function MM_GetBase
+
+ @Description Gets the base address of the required MM objects.
+
+ @Param[in] h_MM - Handle to the MM object.
+
+ @Return base address of the block.
+*//***************************************************************************/
+uint64_t MM_GetBase(t_Handle h_MM);
+
+/**************************************************************************//**
+ @Function MM_GetForce
+
+ @Description Force memory allocation.
+
+ It means to allocate a block of memory of the given
+ size from the given base address.
+ The routine checks if the required block can be allocated
+ (that is it is free) and then, calls the internal MM_CutFree
+ routine to update all free lists do not include that block.
+
+ @Param[in] h_MM - Handle to the MM object.
+ @Param[in] base - Base address of the MM.
+ @Param[in] size - Size of the MM.
+ @Param[in] name - Name that specifies an allocated block.
+
+ @Return base address of an allocated block, ILLEGAL_BASE if can't allocate a block.
+*//***************************************************************************/
+uint64_t MM_GetForce(t_Handle h_MM, uint64_t base, uint64_t size, char *name);
+
+/**************************************************************************//**
+ @Function MM_GetForceMin
+
+ @Description Allocates a block of memory according to the given size, the alignment and minimum base address.
+
+ The Alignment argument tells from which
+ free list allocate a block of memory. 2^alignment indicates
+ the alignment that the base address of the allocated block
+ should have. So, the only values 1, 2, 4, 8, 16, 32 and 64
+ are available for the alignment argument.
+ The minimum baser address forces the location of the block
+ to be from a given address onward.
+ The routine passes through the specific free list of free
+ blocks and seeks for the first base address equal or smaller
+ than the required minimum address and end address larger than
+ than the required base + its size - i.e. that may contain
+ the required block.
+ After the block is found and data is allocated, it calls
+ the internal MM_CutFree routine to update all free lists
+ do not include a just allocated block. Of course, each
+ free list contains a free blocks with the same alignment.
+ It is also creates a busy block that holds
+ information about an allocated block.
+
+ @Param[in] h_MM - Handle to the MM object.
+ @Param[in] size - Size of the MM.
+ @Param[in] alignment - Index as a power of two defines a required
+ alignment (in bytes); Should be 1, 2, 4, 8, 16, 32 or 64
+ @Param[in] min - The minimum base address of the block.
+ @Param[in] name - Name that specifies an allocated block.
+
+ @Return base address of an allocated block,ILLEGAL_BASE if can't allocate a block.
+*//***************************************************************************/
+uint64_t MM_GetForceMin(t_Handle h_MM,
+ uint64_t size,
+ uint64_t alignment,
+ uint64_t min,
+ char *name);
+
+/**************************************************************************//**
+ @Function MM_Put
+
+ @Description Puts a block of memory of the given base address back to the memory.
+
+ It checks if there is a busy block with the
+ given base address. If not, it returns 0, that
+ means can't free a block. Otherwise, it gets parameters of
+ the busy block and after it updates lists of free blocks,
+ removes that busy block from the list by calling to MM_CutBusy
+ routine.
+ After that it calls to MM_AddFree routine to add a new free
+ block to the free lists.
+
+ @Param[in] h_MM - Handle to the MM object.
+ @Param[in] base - Base address of the MM.
+
+ @Return The size of bytes released, 0 if failed.
+*//***************************************************************************/
+uint64_t MM_Put(t_Handle h_MM, uint64_t base);
+
+/**************************************************************************//**
+ @Function MM_PutForce
+
+ @Description Releases a block of memory of the required size from the required base address.
+
+ First, it calls to MM_CutBusy routine
+ to cut a free block from the busy list. And then, calls to
+ MM_AddFree routine to add the free block to the free lists.
+
+ @Param[in] h_MM - Handle to the MM object.
+ @Param[in] base - Base address of of a block to free.
+ @Param[in] size - Size of a block to free.
+
+ @Return The number of bytes released, 0 on failure.
+*//***************************************************************************/
+uint64_t MM_PutForce(t_Handle h_MM, uint64_t base, uint64_t size);
+
+/**************************************************************************//**
+ @Function MM_Add
+
+ @Description Adds a new memory block for memory allocation.
+
+ When a new memory block is initialized and added to the
+ memory list, it calls to MM_AddFree routine to add the
+ new free block to the free lists.
+
+ @Param[in] h_MM - Handle to the MM object.
+ @Param[in] base - Base address of the memory block.
+ @Param[in] size - Size of the memory block.
+
+ @Return E_OK on success, otherwise returns an error code.
+*//***************************************************************************/
+t_Error MM_Add(t_Handle h_MM, uint64_t base, uint64_t size);
+
+/**************************************************************************//**
+ @Function MM_Dump
+
+ @Description Prints results of free and busy lists.
+
+ @Param[in] h_MM - Handle to the MM object.
+*//***************************************************************************/
+void MM_Dump(t_Handle h_MM);
+
+/**************************************************************************//**
+ @Function MM_Free
+
+ @Description Releases memory allocated for MM object.
+
+ @Param[in] h_MM - Handle of the MM object.
+*//***************************************************************************/
+void MM_Free(t_Handle h_MM);
+
+/**************************************************************************//**
+ @Function MM_GetMemBlock
+
+ @Description Returns base address of the memory block specified by the index.
+
+ If index is 0, returns base address
+ of the first memory block, 1 - returns base address
+ of the second memory block, etc.
+ Note, those memory blocks are allocated by the
+ application before MM_Init or MM_Add and have to
+ be released by the application before or after invoking
+ the MM_Free routine.
+
+ @Param[in] h_MM - Handle to the MM object.
+ @Param[in] index - Index of the memory block.
+
+ @Return valid base address or ILLEGAL_BASE if no memory block specified by the index.
+*//***************************************************************************/
+uint64_t MM_GetMemBlock(t_Handle h_MM, int index);
+
+/**************************************************************************//**
+ @Function MM_InRange
+
+ @Description Checks if a specific address is in the memory range of the passed MM object.
+
+ @Param[in] h_MM - Handle to the MM object.
+ @Param[in] addr - The address to be checked.
+
+ @Return TRUE if the address is in the address range of the block, FALSE otherwise.
+*//***************************************************************************/
+bool MM_InRange(t_Handle h_MM, uint64_t addr);
+
+/**************************************************************************//**
+ @Function MM_GetFreeMemSize
+
+ @Description Returns the size (in bytes) of free memory.
+
+ @Param[in] h_MM - Handle to the MM object.
+
+ @Return Free memory size in bytes.
+*//***************************************************************************/
+uint64_t MM_GetFreeMemSize(t_Handle h_MM);
+
+
+/** @} */ /* end of mm_grp group */
+/** @} */ /* end of etc_id group */
+
+#endif /* __MM_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/etc/sprint_ext.h b/drivers/net/ethernet/freescale/fman/inc/etc/sprint_ext.h
new file mode 100644
index 0000000..52f7a9d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/etc/sprint_ext.h
@@ -0,0 +1,118 @@
+/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File sprint_ext.h
+
+ @Description Debug routines (externals).
+
+*//***************************************************************************/
+
+#ifndef __SPRINT_EXT_H
+#define __SPRINT_EXT_H
+
+
+#if defined(NCSW_LINUX) && defined(__KERNEL__)
+#include <linux/kernel.h>
+
+#elif defined(NCSW_VXWORKS)
+#include "private/stdioP.h"
+
+#else
+#include <stdio.h>
+#endif /* defined(NCSW_LINUX) && defined(__KERNEL__) */
+
+#include "std_ext.h"
+
+
+/**************************************************************************//**
+ @Group etc_id Utility Library Application Programming Interface
+
+ @Description External routines.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group sprint_id Sprint
+
+ @Description Sprint & Sscan module functions,definitions and enums.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Function Sprint
+
+ @Description Format a string and place it in a buffer.
+
+ @Param[in] buff - The buffer to place the result into.
+ @Param[in] str - The format string to use.
+ @Param[in] ... - Arguments for the format string.
+
+ @Return Number of bytes formatted.
+*//***************************************************************************/
+int Sprint(char *buff, const char *str, ...);
+
+/**************************************************************************//**
+ @Function Snprint
+
+ @Description Format a string and place it in a buffer.
+
+ @Param[in] buf - The buffer to place the result into.
+ @Param[in] size - The size of the buffer, including the trailing null space.
+ @Param[in] fmt - The format string to use.
+ @Param[in] ... - Arguments for the format string.
+
+ @Return Number of bytes formatted.
+*//***************************************************************************/
+int Snprint(char * buf, uint32_t size, const char *fmt, ...);
+
+/**************************************************************************//**
+ @Function Sscan
+
+ @Description Unformat a buffer into a list of arguments.
+
+ @Param[in] buf - input buffer.
+ @Param[in] fmt - formatting of buffer.
+ @Param[out] ... - resulting arguments.
+
+ @Return Number of bytes unformatted.
+*//***************************************************************************/
+int Sscan(const char * buf, const char * fmt, ...);
+
+/** @} */ /* end of sprint_id group */
+/** @} */ /* end of etc_id group */
+
+
+#endif /* __SPRINT_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/flib/common/arch/ppc_access.h b/drivers/net/ethernet/freescale/fman/inc/flib/common/arch/ppc_access.h
new file mode 100644
index 0000000..c7b9b46
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/flib/common/arch/ppc_access.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FL_E500_MACROS_H
+#define FL_E500_MACROS_H
+
+#endif /* FL_E500_MACROS_H */
+
diff --git a/drivers/net/ethernet/freescale/fman/inc/flib/common/general.h b/drivers/net/ethernet/freescale/fman/inc/flib/common/general.h
new file mode 100644
index 0000000..8150e01
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/flib/common/general.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __GENERAL_H
+#define __GENERAL_H
+
+#include "std_ext.h"
+#if !defined(NCSW_LINUX)
+#include "errno.h"
+#endif
+
+
+extern uint32_t get_mac_addr_crc(uint64_t _addr);
+
+
+#define iowrite32be(val, addr) WRITE_UINT32(*addr, val)
+#define ioread32be(addr) GET_UINT32(*addr)
+
+#define ether_crc(len, addr) get_mac_addr_crc(*(uint64_t *)(addr)>>16)
+
+
+#endif /* __GENERAL_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/flib/fman_common.h b/drivers/net/ethernet/freescale/fman/inc/flib/fman_common.h
new file mode 100755
index 0000000..8b194e9
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/flib/fman_common.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2008-2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __FMAN_COMMON_H
+#define __FMAN_COMMON_H
+
+/**************************************************************************//**
+ @Description NIA Description
+*//***************************************************************************/
+#define NIA_ORDER_RESTOR 0x00800000
+#define NIA_ENG_FM_CTL 0x00000000
+#define NIA_ENG_PRS 0x00440000
+#define NIA_ENG_KG 0x00480000
+#define NIA_ENG_PLCR 0x004C0000
+#define NIA_ENG_BMI 0x00500000
+#define NIA_ENG_QMI_ENQ 0x00540000
+#define NIA_ENG_QMI_DEQ 0x00580000
+#define NIA_ENG_MASK 0x007C0000
+
+#define NIA_FM_CTL_AC_CC 0x00000006
+#define NIA_FM_CTL_AC_HC 0x0000000C
+#define NIA_FM_CTL_AC_IND_MODE_TX 0x00000008
+#define NIA_FM_CTL_AC_IND_MODE_RX 0x0000000A
+#define NIA_FM_CTL_AC_FRAG 0x0000000e
+#define NIA_FM_CTL_AC_PRE_FETCH 0x00000010
+#define NIA_FM_CTL_AC_POST_FETCH_PCD 0x00000012
+#define NIA_FM_CTL_AC_POST_FETCH_PCD_UDP_LEN 0x00000018
+#define NIA_FM_CTL_AC_POST_FETCH_NO_PCD 0x00000012
+#define NIA_FM_CTL_AC_FRAG_CHECK 0x00000014
+#define NIA_FM_CTL_AC_PRE_CC 0x00000020
+
+
+#define NIA_BMI_AC_ENQ_FRAME 0x00000002
+#define NIA_BMI_AC_TX_RELEASE 0x000002C0
+#define NIA_BMI_AC_RELEASE 0x000000C0
+#define NIA_BMI_AC_DISCARD 0x000000C1
+#define NIA_BMI_AC_TX 0x00000274
+#define NIA_BMI_AC_FETCH 0x00000208
+#define NIA_BMI_AC_MASK 0x000003FF
+
+#define NIA_KG_DIRECT 0x00000100
+#define NIA_KG_CC_EN 0x00000200
+#define NIA_PLCR_ABSOLUTE 0x00008000
+
+#define NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA 0x00000202
+#define NIA_BMI_AC_FETCH_ALL_FRAME 0x0000020c
+
+#endif /* __FMAN_COMMON_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/flib/fsl_enet.h b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_enet.h
new file mode 100644
index 0000000..dde6a4e
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_enet.h
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FSL_ENET_H
+#define __FSL_ENET_H
+
+/**
+ @Description Ethernet MAC-PHY Interface
+*/
+
+enum enet_interface {
+ E_ENET_IF_MII = 0x00010000, /**< MII interface */
+ E_ENET_IF_RMII = 0x00020000, /**< RMII interface */
+ E_ENET_IF_SMII = 0x00030000, /**< SMII interface */
+ E_ENET_IF_GMII = 0x00040000, /**< GMII interface */
+ E_ENET_IF_RGMII = 0x00050000, /**< RGMII interface */
+ E_ENET_IF_TBI = 0x00060000, /**< TBI interface */
+ E_ENET_IF_RTBI = 0x00070000, /**< RTBI interface */
+ E_ENET_IF_SGMII = 0x00080000, /**< SGMII interface */
+ E_ENET_IF_XGMII = 0x00090000, /**< XGMII interface */
+ E_ENET_IF_QSGMII = 0x000a0000, /**< QSGMII interface */
+ E_ENET_IF_XFI = 0x000b0000 /**< XFI interface */
+};
+
+/**
+ @Description Ethernet Speed (nominal data rate)
+*/
+enum enet_speed {
+ E_ENET_SPEED_10 = 10, /**< 10 Mbps */
+ E_ENET_SPEED_100 = 100, /**< 100 Mbps */
+ E_ENET_SPEED_1000 = 1000, /**< 1000 Mbps = 1 Gbps */
+ E_ENET_SPEED_10000 = 10000 /**< 10000 Mbps = 10 Gbps */
+};
+
+enum mac_type {
+ E_MAC_DTSEC,
+ E_MAC_TGEC,
+ E_MAC_MEMAC
+};
+
+/**************************************************************************//**
+ @Description Enum for inter-module interrupts registration
+*//***************************************************************************/
+enum fman_event_modules {
+ E_FMAN_MOD_PRS, /**< Parser event */
+ E_FMAN_MOD_KG, /**< Keygen event */
+ E_FMAN_MOD_PLCR, /**< Policer event */
+ E_FMAN_MOD_10G_MAC, /**< 10G MAC event */
+ E_FMAN_MOD_1G_MAC, /**< 1G MAC event */
+ E_FMAN_MOD_TMR, /**< Timer event */
+ E_FMAN_MOD_FMAN_CTRL, /**< FMAN Controller Timer event */
+ E_FMAN_MOD_MACSEC,
+ E_FMAN_MOD_DUMMY_LAST
+};
+
+/**************************************************************************//**
+ @Description Enum for interrupts types
+*//***************************************************************************/
+enum fman_intr_type {
+ E_FMAN_INTR_TYPE_ERR,
+ E_FMAN_INTR_TYPE_NORMAL
+};
+
+/**************************************************************************//**
+ @Description enum for defining MAC types
+*//***************************************************************************/
+enum fman_mac_type {
+ E_FMAN_MAC_10G = 0, /**< 10G MAC */
+ E_FMAN_MAC_1G /**< 1G MAC */
+};
+
+enum fman_mac_exceptions {
+ E_FMAN_MAC_EX_10G_MDIO_SCAN_EVENTMDIO = 0,
+ /**< 10GEC MDIO scan event interrupt */
+ E_FMAN_MAC_EX_10G_MDIO_CMD_CMPL,
+ /**< 10GEC MDIO command completion interrupt */
+ E_FMAN_MAC_EX_10G_REM_FAULT,
+ /**< 10GEC, mEMAC Remote fault interrupt */
+ E_FMAN_MAC_EX_10G_LOC_FAULT,
+ /**< 10GEC, mEMAC Local fault interrupt */
+ E_FMAN_MAC_EX_10G_1TX_ECC_ER,
+ /**< 10GEC, mEMAC Transmit frame ECC error interrupt */
+ E_FMAN_MAC_EX_10G_TX_FIFO_UNFL,
+ /**< 10GEC, mEMAC Transmit FIFO underflow interrupt */
+ E_FMAN_MAC_EX_10G_TX_FIFO_OVFL,
+ /**< 10GEC, mEMAC Transmit FIFO overflow interrupt */
+ E_FMAN_MAC_EX_10G_TX_ER,
+ /**< 10GEC Transmit frame error interrupt */
+ E_FMAN_MAC_EX_10G_RX_FIFO_OVFL,
+ /**< 10GEC, mEMAC Receive FIFO overflow interrupt */
+ E_FMAN_MAC_EX_10G_RX_ECC_ER,
+ /**< 10GEC, mEMAC Receive frame ECC error interrupt */
+ E_FMAN_MAC_EX_10G_RX_JAB_FRM,
+ /**< 10GEC Receive jabber frame interrupt */
+ E_FMAN_MAC_EX_10G_RX_OVRSZ_FRM,
+ /**< 10GEC Receive oversized frame interrupt */
+ E_FMAN_MAC_EX_10G_RX_RUNT_FRM,
+ /**< 10GEC Receive runt frame interrupt */
+ E_FMAN_MAC_EX_10G_RX_FRAG_FRM,
+ /**< 10GEC Receive fragment frame interrupt */
+ E_FMAN_MAC_EX_10G_RX_LEN_ER,
+ /**< 10GEC Receive payload length error interrupt */
+ E_FMAN_MAC_EX_10G_RX_CRC_ER,
+ /**< 10GEC Receive CRC error interrupt */
+ E_FMAN_MAC_EX_10G_RX_ALIGN_ER,
+ /**< 10GEC Receive alignment error interrupt */
+ E_FMAN_MAC_EX_1G_BAB_RX,
+ /**< dTSEC Babbling receive error */
+ E_FMAN_MAC_EX_1G_RX_CTL,
+ /**< dTSEC Receive control (pause frame) interrupt */
+ E_FMAN_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET,
+ /**< dTSEC Graceful transmit stop complete */
+ E_FMAN_MAC_EX_1G_BAB_TX,
+ /**< dTSEC Babbling transmit error */
+ E_FMAN_MAC_EX_1G_TX_CTL,
+ /**< dTSEC Transmit control (pause frame) interrupt */
+ E_FMAN_MAC_EX_1G_TX_ERR,
+ /**< dTSEC Transmit error */
+ E_FMAN_MAC_EX_1G_LATE_COL,
+ /**< dTSEC Late collision */
+ E_FMAN_MAC_EX_1G_COL_RET_LMT,
+ /**< dTSEC Collision retry limit */
+ E_FMAN_MAC_EX_1G_TX_FIFO_UNDRN,
+ /**< dTSEC Transmit FIFO underrun */
+ E_FMAN_MAC_EX_1G_MAG_PCKT,
+ /**< dTSEC Magic Packet detection */
+ E_FMAN_MAC_EX_1G_MII_MNG_RD_COMPLET,
+ /**< dTSEC MII management read completion */
+ E_FMAN_MAC_EX_1G_MII_MNG_WR_COMPLET,
+ /**< dTSEC MII management write completion */
+ E_FMAN_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET,
+ /**< dTSEC Graceful receive stop complete */
+ E_FMAN_MAC_EX_1G_TX_DATA_ERR,
+ /**< dTSEC Internal data error on transmit */
+ E_FMAN_MAC_EX_1G_RX_DATA_ERR,
+ /**< dTSEC Internal data error on receive */
+ E_FMAN_MAC_EX_1G_1588_TS_RX_ERR,
+ /**< dTSEC Time-Stamp Receive Error */
+ E_FMAN_MAC_EX_1G_RX_MIB_CNT_OVFL,
+ /**< dTSEC MIB counter overflow */
+ E_FMAN_MAC_EX_TS_FIFO_ECC_ERR,
+ /**< mEMAC Time-stamp FIFO ECC error interrupt;
+ not supported on T4240/B4860 rev1 chips */
+};
+
+#define ENET_IF_SGMII_BASEX 0x80000000
+ /**< SGMII/QSGII interface with 1000BaseX auto-negotiation between MAC
+ and phy or backplane;
+ Note: 1000BaseX auto-negotiation relates only to interface between MAC
+ and phy/backplane, SGMII phy can still synchronize with far-end phy at
+ 10Mbps, 100Mbps or 1000Mbps */
+
+enum enet_mode {
+ E_ENET_MODE_INVALID = 0,
+ /**< Invalid Ethernet mode */
+ E_ENET_MODE_MII_10 = (E_ENET_IF_MII | E_ENET_SPEED_10),
+ /**< 10 Mbps MII */
+ E_ENET_MODE_MII_100 = (E_ENET_IF_MII | E_ENET_SPEED_100),
+ /**< 100 Mbps MII */
+ E_ENET_MODE_RMII_10 = (E_ENET_IF_RMII | E_ENET_SPEED_10),
+ /**< 10 Mbps RMII */
+ E_ENET_MODE_RMII_100 = (E_ENET_IF_RMII | E_ENET_SPEED_100),
+ /**< 100 Mbps RMII */
+ E_ENET_MODE_SMII_10 = (E_ENET_IF_SMII | E_ENET_SPEED_10),
+ /**< 10 Mbps SMII */
+ E_ENET_MODE_SMII_100 = (E_ENET_IF_SMII | E_ENET_SPEED_100),
+ /**< 100 Mbps SMII */
+ E_ENET_MODE_GMII_1000 = (E_ENET_IF_GMII | E_ENET_SPEED_1000),
+ /**< 1000 Mbps GMII */
+ E_ENET_MODE_RGMII_10 = (E_ENET_IF_RGMII | E_ENET_SPEED_10),
+ /**< 10 Mbps RGMII */
+ E_ENET_MODE_RGMII_100 = (E_ENET_IF_RGMII | E_ENET_SPEED_100),
+ /**< 100 Mbps RGMII */
+ E_ENET_MODE_RGMII_1000 = (E_ENET_IF_RGMII | E_ENET_SPEED_1000),
+ /**< 1000 Mbps RGMII */
+ E_ENET_MODE_TBI_1000 = (E_ENET_IF_TBI | E_ENET_SPEED_1000),
+ /**< 1000 Mbps TBI */
+ E_ENET_MODE_RTBI_1000 = (E_ENET_IF_RTBI | E_ENET_SPEED_1000),
+ /**< 1000 Mbps RTBI */
+ E_ENET_MODE_SGMII_10 = (E_ENET_IF_SGMII | E_ENET_SPEED_10),
+ /**< 10 Mbps SGMII with auto-negotiation between MAC and
+ SGMII phy according to Cisco SGMII specification */
+ E_ENET_MODE_SGMII_100 = (E_ENET_IF_SGMII | E_ENET_SPEED_100),
+ /**< 100 Mbps SGMII with auto-negotiation between MAC and
+ SGMII phy according to Cisco SGMII specification */
+ E_ENET_MODE_SGMII_1000 = (E_ENET_IF_SGMII | E_ENET_SPEED_1000),
+ /**< 1000 Mbps SGMII with auto-negotiation between MAC and
+ SGMII phy according to Cisco SGMII specification */
+ E_ENET_MODE_SGMII_BASEX_10 = (ENET_IF_SGMII_BASEX | E_ENET_IF_SGMII
+ | E_ENET_SPEED_10),
+ /**< 10 Mbps SGMII with 1000BaseX auto-negotiation between
+ MAC and SGMII phy or backplane */
+ E_ENET_MODE_SGMII_BASEX_100 = (ENET_IF_SGMII_BASEX | E_ENET_IF_SGMII
+ | E_ENET_SPEED_100),
+ /**< 100 Mbps SGMII with 1000BaseX auto-negotiation between
+ MAC and SGMII phy or backplane */
+ E_ENET_MODE_SGMII_BASEX_1000 = (ENET_IF_SGMII_BASEX | E_ENET_IF_SGMII
+ | E_ENET_SPEED_1000),
+ /**< 1000 Mbps SGMII with 1000BaseX auto-negotiation between
+ MAC and SGMII phy or backplane */
+ E_ENET_MODE_QSGMII_1000 = (E_ENET_IF_QSGMII | E_ENET_SPEED_1000),
+ /**< 1000 Mbps QSGMII with auto-negotiation between MAC and
+ QSGMII phy according to Cisco QSGMII specification */
+ E_ENET_MODE_QSGMII_BASEX_1000 = (ENET_IF_SGMII_BASEX | E_ENET_IF_QSGMII
+ | E_ENET_SPEED_1000),
+ /**< 1000 Mbps QSGMII with 1000BaseX auto-negotiation between
+ MAC and QSGMII phy or backplane */
+ E_ENET_MODE_XGMII_10000 = (E_ENET_IF_XGMII | E_ENET_SPEED_10000),
+ /**< 10000 Mbps XGMII */
+ E_ENET_MODE_XFI_10000 = (E_ENET_IF_XFI | E_ENET_SPEED_10000)
+ /**< 10000 Mbps XFI */
+};
+
+enum fmam_mac_statistics_level {
+ E_FMAN_MAC_NONE_STATISTICS, /**< No statistics */
+ E_FMAN_MAC_PARTIAL_STATISTICS, /**< Only error counters are available;
+ Optimized for performance */
+ E_FMAN_MAC_FULL_STATISTICS /**< All counters available; Not
+ optimized for performance */
+};
+
+#define _MAKE_ENET_MODE(_interface, _speed) (enum enet_mode)((_interface) \
+ | (_speed))
+
+#define _ENET_INTERFACE_FROM_MODE(mode) (enum enet_interface) \
+ ((mode) & 0x0FFF0000)
+#define _ENET_SPEED_FROM_MODE(mode) (enum enet_speed)((mode) & 0x0000FFFF)
+#define _ENET_ADDR_TO_UINT64(_enet_addr) \
+ (uint64_t)(((uint64_t)(_enet_addr)[0] << 40) | \
+ ((uint64_t)(_enet_addr)[1] << 32) | \
+ ((uint64_t)(_enet_addr)[2] << 24) | \
+ ((uint64_t)(_enet_addr)[3] << 16) | \
+ ((uint64_t)(_enet_addr)[4] << 8) | \
+ ((uint64_t)(_enet_addr)[5]))
+
+#define _MAKE_ENET_ADDR_FROM_UINT64(_addr64, _enet_addr) \
+ do { \
+ int i; \
+ for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++) \
+ (_enet_addr)[i] = (uint8_t)((_addr64) >> ((5-i)*8));\
+ } while (0)
+
+#endif /* __FSL_ENET_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman.h b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman.h
new file mode 100755
index 0000000..e66ad73
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman.h
@@ -0,0 +1,826 @@
+/*
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FSL_FMAN_H
+#define __FSL_FMAN_H
+
+#include "common/general.h"
+
+struct fman_ext_pool_params {
+ uint8_t id; /**< External buffer pool id */
+ uint16_t size; /**< External buffer pool buffer size */
+};
+
+struct fman_ext_pools {
+ uint8_t num_pools_used; /**< Number of pools use by this port */
+ struct fman_ext_pool_params *ext_buf_pool;
+ /**< Parameters for each port */
+};
+
+struct fman_backup_bm_pools {
+ uint8_t num_backup_pools; /**< Number of BM backup pools -
+ must be smaller than the total number
+ of pools defined for the specified
+ port.*/
+ uint8_t *pool_ids; /**< numOfBackupPools pool id's,
+ specifying which pools should be used
+ only as backup. Pool id's specified
+ here must be a subset of the pools
+ used by the specified port.*/
+};
+
+/**************************************************************************//**
+ @Description A structure for defining BM pool depletion criteria
+*//***************************************************************************/
+struct fman_buf_pool_depletion {
+ bool buf_pool_depletion_enabled;
+ bool pools_grp_mode_enable; /**< select mode in which pause frames
+ will be sent after a number of pools
+ (all together!) are depleted */
+ uint8_t num_pools; /**< the number of depleted pools that
+ will invoke pause frames transmission.
+ */
+ bool *pools_to_consider; /**< For each pool, TRUE if it should be
+ considered for depletion (Note - this
+ pool must be used by this port!). */
+ bool single_pool_mode_enable; /**< select mode in which pause frames
+ will be sent after a single-pool
+ is depleted; */
+ bool *pools_to_consider_for_single_mode;
+ /**< For each pool, TRUE if it should be
+ considered for depletion (Note - this
+ pool must be used by this port!) */
+ bool has_pfc_priorities;
+ bool *pfc_priorities_en; /**< This field is used by the MAC as
+ the Priority Enable Vector in the PFC
+ frame which is transmitted */
+};
+
+/**************************************************************************//**
+ @Description Enum for defining port DMA swap mode
+*//***************************************************************************/
+enum fman_dma_swap_option {
+ FMAN_DMA_NO_SWP, /**< No swap, transfer data as is.*/
+ FMAN_DMA_SWP_PPC_LE, /**< The transferred data should be swapped
+ in PowerPc Little Endian mode. */
+ FMAN_DMA_SWP_BE /**< The transferred data should be swapped
+ in Big Endian mode */
+};
+
+/**************************************************************************//**
+ @Description Enum for defining port DMA cache attributes
+*//***************************************************************************/
+enum fman_dma_cache_option {
+ FMAN_DMA_NO_STASH = 0, /**< Cacheable, no Allocate (No Stashing) */
+ FMAN_DMA_STASH = 1 /**< Cacheable and Allocate (Stashing on) */
+};
+
+typedef struct t_FmPrsResult fm_prs_result_t;
+typedef enum e_EnetMode enet_mode_t;
+typedef t_Handle handle_t;
+
+struct fman_revision_info {
+ uint8_t majorRev; /**< Major revision */
+ uint8_t minorRev; /**< Minor revision */
+};
+
+/* sizes */
+#define CAPWAP_FRAG_EXTRA_SPACE 32
+#define OFFSET_UNITS 16
+#define MAX_INT_OFFSET 240
+#define MAX_IC_SIZE 256
+#define MAX_EXT_OFFSET 496
+#define MAX_EXT_BUFFER_OFFSET 511
+
+/**************************************************************************
+ @Description Memory Mapped Registers
+***************************************************************************/
+#define FMAN_LIODN_TBL 64 /* size of LIODN table */
+
+struct fman_fpm_regs {
+ uint32_t fmfp_tnc; /**< FPM TNUM Control 0x00 */
+ uint32_t fmfp_prc; /**< FPM Port_ID FmCtl Association 0x04 */
+ uint32_t fmfp_brkc; /**< FPM Breakpoint Control 0x08 */
+ uint32_t fmfp_mxd; /**< FPM Flush Control 0x0c */
+ uint32_t fmfp_dist1; /**< FPM Dispatch Thresholds1 0x10 */
+ uint32_t fmfp_dist2; /**< FPM Dispatch Thresholds2 0x14 */
+ uint32_t fm_epi; /**< FM Error Pending Interrupts 0x18 */
+ uint32_t fm_rie; /**< FM Error Interrupt Enable 0x1c */
+ uint32_t fmfp_fcev[4]; /**< FPM FMan-Controller Event 1-4 0x20-0x2f */
+ uint32_t res0030[4]; /**< res 0x30 - 0x3f */
+ uint32_t fmfp_cee[4]; /**< PM FMan-Controller Event 1-4 0x40-0x4f */
+ uint32_t res0050[4]; /**< res 0x50-0x5f */
+ uint32_t fmfp_tsc1; /**< FPM TimeStamp Control1 0x60 */
+ uint32_t fmfp_tsc2; /**< FPM TimeStamp Control2 0x64 */
+ uint32_t fmfp_tsp; /**< FPM Time Stamp 0x68 */
+ uint32_t fmfp_tsf; /**< FPM Time Stamp Fraction 0x6c */
+ uint32_t fm_rcr; /**< FM Rams Control 0x70 */
+ uint32_t fmfp_extc; /**< FPM External Requests Control 0x74 */
+ uint32_t fmfp_ext1; /**< FPM External Requests Config1 0x78 */
+ uint32_t fmfp_ext2; /**< FPM External Requests Config2 0x7c */
+ uint32_t fmfp_drd[16]; /**< FPM Data_Ram Data 0-15 0x80 - 0xbf */
+ uint32_t fmfp_dra; /**< FPM Data Ram Access 0xc0 */
+ uint32_t fm_ip_rev_1; /**< FM IP Block Revision 1 0xc4 */
+ uint32_t fm_ip_rev_2; /**< FM IP Block Revision 2 0xc8 */
+ uint32_t fm_rstc; /**< FM Reset Command 0xcc */
+ uint32_t fm_cld; /**< FM Classifier Debug 0xd0 */
+ uint32_t fm_npi; /**< FM Normal Pending Interrupts 0xd4 */
+ uint32_t fmfp_exte; /**< FPM External Requests Enable 0xd8 */
+ uint32_t fmfp_ee; /**< FPM Event & Mask 0xdc */
+ uint32_t fmfp_cev[4]; /**< FPM CPU Event 1-4 0xe0-0xef */
+ uint32_t res00f0[4]; /**< res 0xf0-0xff */
+ uint32_t fmfp_ps[50]; /**< FPM Port Status 0x100-0x1c7 */
+ uint32_t res01c8[14]; /**< res 0x1c8-0x1ff */
+ uint32_t fmfp_clfabc; /**< FPM CLFABC 0x200 */
+ uint32_t fmfp_clfcc; /**< FPM CLFCC 0x204 */
+ uint32_t fmfp_clfaval; /**< FPM CLFAVAL 0x208 */
+ uint32_t fmfp_clfbval; /**< FPM CLFBVAL 0x20c */
+ uint32_t fmfp_clfcval; /**< FPM CLFCVAL 0x210 */
+ uint32_t fmfp_clfamsk; /**< FPM CLFAMSK 0x214 */
+ uint32_t fmfp_clfbmsk; /**< FPM CLFBMSK 0x218 */
+ uint32_t fmfp_clfcmsk; /**< FPM CLFCMSK 0x21c */
+ uint32_t fmfp_clfamc; /**< FPM CLFAMC 0x220 */
+ uint32_t fmfp_clfbmc; /**< FPM CLFBMC 0x224 */
+ uint32_t fmfp_clfcmc; /**< FPM CLFCMC 0x228 */
+ uint32_t fmfp_decceh; /**< FPM DECCEH 0x22c */
+ uint32_t res0230[116]; /**< res 0x230 - 0x3ff */
+ uint32_t fmfp_ts[128]; /**< 0x400: FPM Task Status 0x400 - 0x5ff */
+ uint32_t res0600[0x400 - 384];
+};
+
+struct fman_bmi_regs {
+ uint32_t fmbm_init; /**< BMI Initialization 0x00 */
+ uint32_t fmbm_cfg1; /**< BMI Configuration 1 0x04 */
+ uint32_t fmbm_cfg2; /**< BMI Configuration 2 0x08 */
+ uint32_t res000c[5]; /**< 0x0c - 0x1f */
+ uint32_t fmbm_ievr; /**< Interrupt Event Register 0x20 */
+ uint32_t fmbm_ier; /**< Interrupt Enable Register 0x24 */
+ uint32_t fmbm_ifr; /**< Interrupt Force Register 0x28 */
+ uint32_t res002c[5]; /**< 0x2c - 0x3f */
+ uint32_t fmbm_arb[8]; /**< BMI Arbitration 0x40 - 0x5f */
+ uint32_t res0060[12]; /**<0x60 - 0x8f */
+ uint32_t fmbm_dtc[3]; /**< Debug Trap Counter 0x90 - 0x9b */
+ uint32_t res009c; /**< 0x9c */
+ uint32_t fmbm_dcv[3][4]; /**< Debug Compare val 0xa0-0xcf */
+ uint32_t fmbm_dcm[3][4]; /**< Debug Compare Mask 0xd0-0xff */
+ uint32_t fmbm_gde; /**< BMI Global Debug Enable 0x100 */
+ uint32_t fmbm_pp[63]; /**< BMI Port Parameters 0x104 - 0x1ff */
+ uint32_t res0200; /**< 0x200 */
+ uint32_t fmbm_pfs[63]; /**< BMI Port FIFO Size 0x204 - 0x2ff */
+ uint32_t res0300; /**< 0x300 */
+ uint32_t fmbm_spliodn[63]; /**< Port Partition ID 0x304 - 0x3ff */
+};
+
+struct fman_qmi_regs {
+ uint32_t fmqm_gc; /**< General Configuration Register 0x00 */
+ uint32_t res0004; /**< 0x04 */
+ uint32_t fmqm_eie; /**< Error Interrupt Event Register 0x08 */
+ uint32_t fmqm_eien; /**< Error Interrupt Enable Register 0x0c */
+ uint32_t fmqm_eif; /**< Error Interrupt Force Register 0x10 */
+ uint32_t fmqm_ie; /**< Interrupt Event Register 0x14 */
+ uint32_t fmqm_ien; /**< Interrupt Enable Register 0x18 */
+ uint32_t fmqm_if; /**< Interrupt Force Register 0x1c */
+ uint32_t fmqm_gs; /**< Global Status Register 0x20 */
+ uint32_t fmqm_ts; /**< Task Status Register 0x24 */
+ uint32_t fmqm_etfc; /**< Enqueue Total Frame Counter 0x28 */
+ uint32_t fmqm_dtfc; /**< Dequeue Total Frame Counter 0x2c */
+ uint32_t fmqm_dc0; /**< Dequeue Counter 0 0x30 */
+ uint32_t fmqm_dc1; /**< Dequeue Counter 1 0x34 */
+ uint32_t fmqm_dc2; /**< Dequeue Counter 2 0x38 */
+ uint32_t fmqm_dc3; /**< Dequeue Counter 3 0x3c */
+ uint32_t fmqm_dfdc; /**< Dequeue FQID from Default Counter 0x40 */
+ uint32_t fmqm_dfcc; /**< Dequeue FQID from Context Counter 0x44 */
+ uint32_t fmqm_dffc; /**< Dequeue FQID from FD Counter 0x48 */
+ uint32_t fmqm_dcc; /**< Dequeue Confirm Counter 0x4c */
+ uint32_t res0050[7]; /**< 0x50 - 0x6b */
+ uint32_t fmqm_tapc; /**< Tnum Aging Period Control 0x6c */
+ uint32_t fmqm_dmcvc; /**< Dequeue MAC Command Valid Counter 0x70 */
+ uint32_t fmqm_difdcc; /**< Dequeue Invalid FD Command Counter 0x74 */
+ uint32_t fmqm_da1v; /**< Dequeue A1 Valid Counter 0x78 */
+ uint32_t res007c; /**< 0x7c */
+ uint32_t fmqm_dtc; /**< 0x80 Debug Trap Counter 0x80 */
+ uint32_t fmqm_efddd; /**< 0x84 Enqueue Frame desc Dynamic dbg 0x84 */
+ uint32_t res0088[2]; /**< 0x88 - 0x8f */
+ struct {
+ uint32_t fmqm_dtcfg1; /**< 0x90 dbg trap cfg 1 Register 0x00 */
+ uint32_t fmqm_dtval1; /**< Debug Trap Value 1 Register 0x04 */
+ uint32_t fmqm_dtm1; /**< Debug Trap Mask 1 Register 0x08 */
+ uint32_t fmqm_dtc1; /**< Debug Trap Counter 1 Register 0x0c */
+ uint32_t fmqm_dtcfg2; /**< dbg Trap cfg 2 Register 0x10 */
+ uint32_t fmqm_dtval2; /**< Debug Trap Value 2 Register 0x14 */
+ uint32_t fmqm_dtm2; /**< Debug Trap Mask 2 Register 0x18 */
+ uint32_t res001c; /**< 0x1c */
+ } dbg_traps[3]; /**< 0x90 - 0xef */
+ uint8_t res00f0[0x400 - 0xf0]; /**< 0xf0 - 0x3ff */
+};
+
+struct fman_dma_regs {
+ uint32_t fmdmsr; /**< FM DMA status register 0x00 */
+ uint32_t fmdmmr; /**< FM DMA mode register 0x04 */
+ uint32_t fmdmtr; /**< FM DMA bus threshold register 0x08 */
+ uint32_t fmdmhy; /**< FM DMA bus hysteresis register 0x0c */
+ uint32_t fmdmsetr; /**< FM DMA SOS emergency Threshold Register 0x10 */
+ uint32_t fmdmtah; /**< FM DMA transfer bus address high reg 0x14 */
+ uint32_t fmdmtal; /**< FM DMA transfer bus address low reg 0x18 */
+ uint32_t fmdmtcid; /**< FM DMA transfer bus communication ID reg 0x1c */
+ uint32_t fmdmra; /**< FM DMA bus internal ram address register 0x20 */
+ uint32_t fmdmrd; /**< FM DMA bus internal ram data register 0x24 */
+ uint32_t fmdmwcr; /**< FM DMA CAM watchdog counter value 0x28 */
+ uint32_t fmdmebcr; /**< FM DMA CAM base in MURAM register 0x2c */
+ uint32_t fmdmccqdr; /**< FM DMA CAM and CMD Queue Debug reg 0x30 */
+ uint32_t fmdmccqvr1; /**< FM DMA CAM and CMD Queue Value reg #1 0x34 */
+ uint32_t fmdmccqvr2; /**< FM DMA CAM and CMD Queue Value reg #2 0x38 */
+ uint32_t fmdmcqvr3; /**< FM DMA CMD Queue Value register #3 0x3c */
+ uint32_t fmdmcqvr4; /**< FM DMA CMD Queue Value register #4 0x40 */
+ uint32_t fmdmcqvr5; /**< FM DMA CMD Queue Value register #5 0x44 */
+ uint32_t fmdmsefrc; /**< FM DMA Semaphore Entry Full Reject Cntr 0x48 */
+ uint32_t fmdmsqfrc; /**< FM DMA Semaphore Queue Full Reject Cntr 0x4c */
+ uint32_t fmdmssrc; /**< FM DMA Semaphore SYNC Reject Counter 0x50 */
+ uint32_t fmdmdcr; /**< FM DMA Debug Counter 0x54 */
+ uint32_t fmdmemsr; /**< FM DMA Emergency Smoother Register 0x58 */
+ uint32_t res005c; /**< 0x5c */
+ uint32_t fmdmplr[FMAN_LIODN_TBL / 2]; /**< DMA LIODN regs 0x60-0xdf */
+ uint32_t res00e0[0x400 - 56];
+};
+
+struct fman_rg {
+ struct fman_fpm_regs *fpm_rg;
+ struct fman_dma_regs *dma_rg;
+ struct fman_bmi_regs *bmi_rg;
+ struct fman_qmi_regs *qmi_rg;
+};
+
+enum fman_dma_cache_override {
+ E_FMAN_DMA_NO_CACHE_OR = 0, /**< No override of the Cache field */
+ E_FMAN_DMA_NO_STASH_DATA, /**< No data stashing in system level cache */
+ E_FMAN_DMA_MAY_STASH_DATA, /**< Stashing allowed in sys level cache */
+ E_FMAN_DMA_STASH_DATA /**< Stashing performed in system level cache */
+};
+
+enum fman_dma_aid_mode {
+ E_FMAN_DMA_AID_OUT_PORT_ID = 0, /**< 4 LSB of PORT_ID */
+ E_FMAN_DMA_AID_OUT_TNUM /**< 4 LSB of TNUM */
+};
+
+enum fman_dma_dbg_cnt_mode {
+ E_FMAN_DMA_DBG_NO_CNT = 0, /**< No counting */
+ E_FMAN_DMA_DBG_CNT_DONE, /**< Count DONE commands */
+ E_FMAN_DMA_DBG_CNT_COMM_Q_EM, /**< command Q emergency signal */
+ E_FMAN_DMA_DBG_CNT_INT_READ_EM, /**< Read buf emergency signal */
+ E_FMAN_DMA_DBG_CNT_INT_WRITE_EM, /**< Write buf emergency signal */
+ E_FMAN_DMA_DBG_CNT_FPM_WAIT, /**< FPM WAIT signal */
+ E_FMAN_DMA_DBG_CNT_SIGLE_BIT_ECC, /**< Single bit ECC errors */
+ E_FMAN_DMA_DBG_CNT_RAW_WAR_PROT /**< RAW & WAR protection counter */
+};
+
+enum fman_dma_emergency_level {
+ E_FMAN_DMA_EM_EBS = 0, /**< EBS emergency */
+ E_FMAN_DMA_EM_SOS /**< SOS emergency */
+};
+
+enum fman_catastrophic_err {
+ E_FMAN_CATAST_ERR_STALL_PORT = 0, /**< Port_ID stalled reset required */
+ E_FMAN_CATAST_ERR_STALL_TASK /**< Only erroneous task is stalled */
+};
+
+enum fman_dma_err {
+ E_FMAN_DMA_ERR_CATASTROPHIC = 0, /**< Catastrophic DMA error */
+ E_FMAN_DMA_ERR_REPORT /**< Reported DMA error */
+};
+
+struct fman_cfg {
+ uint16_t liodn_bs_pr_port[FMAN_LIODN_TBL];/* base per port */
+ bool en_counters;
+ uint8_t disp_limit_tsh;
+ uint8_t prs_disp_tsh;
+ uint8_t plcr_disp_tsh;
+ uint8_t kg_disp_tsh;
+ uint8_t bmi_disp_tsh;
+ uint8_t qmi_enq_disp_tsh;
+ uint8_t qmi_deq_disp_tsh;
+ uint8_t fm_ctl1_disp_tsh;
+ uint8_t fm_ctl2_disp_tsh;
+ enum fman_dma_cache_override dma_cache_override;
+ enum fman_dma_aid_mode dma_aid_mode;
+ bool dma_aid_override;
+ uint8_t dma_axi_dbg_num_of_beats;
+ uint8_t dma_cam_num_of_entries;
+ uint32_t dma_watchdog;
+ uint8_t dma_comm_qtsh_asrt_emer;
+ uint8_t dma_write_buf_tsh_asrt_emer;
+ uint8_t dma_read_buf_tsh_asrt_emer;
+ uint8_t dma_comm_qtsh_clr_emer;
+ uint8_t dma_write_buf_tsh_clr_emer;
+ uint8_t dma_read_buf_tsh_clr_emer;
+ uint32_t dma_sos_emergency;
+ enum fman_dma_dbg_cnt_mode dma_dbg_cnt_mode;
+ bool dma_stop_on_bus_error;
+ bool dma_en_emergency;
+ uint32_t dma_emergency_bus_select;
+ enum fman_dma_emergency_level dma_emergency_level;
+ bool dma_en_emergency_smoother;
+ uint32_t dma_emergency_switch_counter;
+ bool halt_on_external_activ;
+ bool halt_on_unrecov_ecc_err;
+ enum fman_catastrophic_err catastrophic_err;
+ enum fman_dma_err dma_err;
+ bool en_muram_test_mode;
+ bool en_iram_test_mode;
+ bool external_ecc_rams_enable;
+ uint16_t tnum_aging_period;
+ uint32_t exceptions;
+ uint16_t clk_freq;
+ bool pedantic_dma;
+ uint32_t cam_base_addr;
+ uint32_t fifo_base_addr;
+ uint32_t total_fifo_size;
+ uint8_t total_num_of_tasks;
+ bool qmi_deq_option_support;
+ uint32_t qmi_def_tnums_thresh;
+ bool fman_partition_array;
+ uint8_t num_of_fman_ctrl_evnt_regs;
+};
+
+/**************************************************************************//**
+ @Description Exceptions
+*//***************************************************************************/
+#define FMAN_EX_DMA_BUS_ERROR 0x80000000
+#define FMAN_EX_DMA_READ_ECC 0x40000000
+#define FMAN_EX_DMA_SYSTEM_WRITE_ECC 0x20000000
+#define FMAN_EX_DMA_FM_WRITE_ECC 0x10000000
+#define FMAN_EX_FPM_STALL_ON_TASKS 0x08000000
+#define FMAN_EX_FPM_SINGLE_ECC 0x04000000
+#define FMAN_EX_FPM_DOUBLE_ECC 0x02000000
+#define FMAN_EX_QMI_SINGLE_ECC 0x01000000
+#define FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID 0x00800000
+#define FMAN_EX_QMI_DOUBLE_ECC 0x00400000
+#define FMAN_EX_BMI_LIST_RAM_ECC 0x00200000
+#define FMAN_EX_BMI_PIPELINE_ECC 0x00100000
+#define FMAN_EX_BMI_STATISTICS_RAM_ECC 0x00080000
+#define FMAN_EX_IRAM_ECC 0x00040000
+#define FMAN_EX_NURAM_ECC 0x00020000
+#define FMAN_EX_BMI_DISPATCH_RAM_ECC 0x00010000
+
+enum fman_exceptions {
+ E_FMAN_EX_DMA_BUS_ERROR = 0, /**< DMA bus error. */
+ E_FMAN_EX_DMA_READ_ECC, /**< Read Buffer ECC error */
+ E_FMAN_EX_DMA_SYSTEM_WRITE_ECC, /**< Write Buffer ECC err on sys side */
+ E_FMAN_EX_DMA_FM_WRITE_ECC, /**< Write Buffer ECC error on FM side */
+ E_FMAN_EX_FPM_STALL_ON_TASKS, /**< Stall of tasks on FPM */
+ E_FMAN_EX_FPM_SINGLE_ECC, /**< Single ECC on FPM. */
+ E_FMAN_EX_FPM_DOUBLE_ECC, /**< Double ECC error on FPM ram access */
+ E_FMAN_EX_QMI_SINGLE_ECC, /**< Single ECC on QMI. */
+ E_FMAN_EX_QMI_DOUBLE_ECC, /**< Double bit ECC occurred on QMI */
+ E_FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID,/**< DeQ from unknown port id */
+ E_FMAN_EX_BMI_LIST_RAM_ECC, /**< Linked List RAM ECC error */
+ E_FMAN_EX_BMI_STORAGE_PROFILE_ECC, /**< storage profile */
+ E_FMAN_EX_BMI_STATISTICS_RAM_ECC, /**< Statistics RAM ECC Err Enable */
+ E_FMAN_EX_BMI_DISPATCH_RAM_ECC, /**< Dispatch RAM ECC Error Enable */
+ E_FMAN_EX_IRAM_ECC, /**< Double bit ECC occurred on IRAM*/
+ E_FMAN_EX_MURAM_ECC /**< Double bit ECC occurred on MURAM*/
+};
+
+enum fman_counters {
+ E_FMAN_COUNTERS_ENQ_TOTAL_FRAME = 0, /**< QMI tot enQ frames counter */
+ E_FMAN_COUNTERS_DEQ_TOTAL_FRAME, /**< QMI tot deQ frames counter */
+ E_FMAN_COUNTERS_DEQ_0, /**< QMI 0 frames from QMan counter */
+ E_FMAN_COUNTERS_DEQ_1, /**< QMI 1 frames from QMan counter */
+ E_FMAN_COUNTERS_DEQ_2, /**< QMI 2 frames from QMan counter */
+ E_FMAN_COUNTERS_DEQ_3, /**< QMI 3 frames from QMan counter */
+ E_FMAN_COUNTERS_DEQ_FROM_DEFAULT, /**< QMI deQ from dflt queue cntr */
+ E_FMAN_COUNTERS_DEQ_FROM_CONTEXT, /**< QMI deQ from FQ context cntr */
+ E_FMAN_COUNTERS_DEQ_FROM_FD, /**< QMI deQ from FD command field cntr */
+ E_FMAN_COUNTERS_DEQ_CONFIRM, /**< QMI dequeue confirm counter */
+ E_FMAN_COUNTERS_SEMAPHOR_ENTRY_FULL_REJECT, /**< DMA full entry cntr */
+ E_FMAN_COUNTERS_SEMAPHOR_QUEUE_FULL_REJECT, /**< DMA full CAM Q cntr */
+ E_FMAN_COUNTERS_SEMAPHOR_SYNC_REJECT /**< DMA sync counter */
+};
+
+#define FPM_PRT_FM_CTL1 0x00000001
+#define FPM_PRT_FM_CTL2 0x00000002
+
+/**************************************************************************//**
+ @Description DMA definitions
+*//***************************************************************************/
+
+/* masks */
+#define DMA_MODE_AID_OR 0x20000000
+#define DMA_MODE_SBER 0x10000000
+#define DMA_MODE_BER 0x00200000
+#define DMA_MODE_EB 0x00100000
+#define DMA_MODE_ECC 0x00000020
+#define DMA_MODE_PRIVILEGE_PROT 0x00001000
+#define DMA_MODE_SECURE_PROT 0x00000800
+#define DMA_MODE_EMER_READ 0x00080000
+#define DMA_MODE_EMER_WRITE 0x00040000
+#define DMA_MODE_CACHE_OR_MASK 0xC0000000
+#define DMA_MODE_CEN_MASK 0x0000E000
+#define DMA_MODE_DBG_MASK 0x00000380
+#define DMA_MODE_AXI_DBG_MASK 0x0F000000
+
+#define DMA_EMSR_EMSTR_MASK 0x0000FFFF
+
+#define DMA_TRANSFER_PORTID_MASK 0xFF000000
+#define DMA_TRANSFER_TNUM_MASK 0x00FF0000
+#define DMA_TRANSFER_LIODN_MASK 0x00000FFF
+
+#define DMA_HIGH_LIODN_MASK 0x0FFF0000
+#define DMA_LOW_LIODN_MASK 0x00000FFF
+
+#define DMA_STATUS_CMD_QUEUE_NOT_EMPTY 0x10000000
+#define DMA_STATUS_BUS_ERR 0x08000000
+#define DMA_STATUS_READ_ECC 0x04000000
+#define DMA_STATUS_SYSTEM_WRITE_ECC 0x02000000
+#define DMA_STATUS_FM_WRITE_ECC 0x01000000
+#define DMA_STATUS_SYSTEM_DPEXT_ECC 0x00800000
+#define DMA_STATUS_FM_DPEXT_ECC 0x00400000
+#define DMA_STATUS_SYSTEM_DPDAT_ECC 0x00200000
+#define DMA_STATUS_FM_DPDAT_ECC 0x00100000
+#define DMA_STATUS_FM_SPDAT_ECC 0x00080000
+
+#define FM_LIODN_BASE_MASK 0x00000FFF
+
+/* shifts */
+#define DMA_MODE_CACHE_OR_SHIFT 30
+#define DMA_MODE_BUS_PRI_SHIFT 16
+#define DMA_MODE_AXI_DBG_SHIFT 24
+#define DMA_MODE_CEN_SHIFT 13
+#define DMA_MODE_BUS_PROT_SHIFT 10
+#define DMA_MODE_DBG_SHIFT 7
+#define DMA_MODE_EMER_LVL_SHIFT 6
+#define DMA_MODE_AID_MODE_SHIFT 4
+#define DMA_MODE_MAX_AXI_DBG_NUM_OF_BEATS 16
+#define DMA_MODE_MAX_CAM_NUM_OF_ENTRIES 32
+
+#define DMA_THRESH_COMMQ_SHIFT 24
+#define DMA_THRESH_READ_INT_BUF_SHIFT 16
+
+#define DMA_LIODN_SHIFT 16
+
+#define DMA_TRANSFER_PORTID_SHIFT 24
+#define DMA_TRANSFER_TNUM_SHIFT 16
+
+/* sizes */
+#define DMA_MAX_WATCHDOG 0xffffffff
+
+/* others */
+#define DMA_CAM_SIZEOF_ENTRY 0x40
+#define DMA_CAM_ALIGN 0x1000
+#define DMA_CAM_UNITS 8
+
+/**************************************************************************//**
+ @Description General defines
+*//***************************************************************************/
+
+#define FM_DEBUG_STATUS_REGISTER_OFFSET 0x000d1084UL
+#define FM_UCODE_DEBUG_INSTRUCTION 0x6ffff805UL
+
+/**************************************************************************//**
+ @Description FPM defines
+*//***************************************************************************/
+
+/* masks */
+#define FPM_EV_MASK_DOUBLE_ECC 0x80000000
+#define FPM_EV_MASK_STALL 0x40000000
+#define FPM_EV_MASK_SINGLE_ECC 0x20000000
+#define FPM_EV_MASK_RELEASE_FM 0x00010000
+#define FPM_EV_MASK_DOUBLE_ECC_EN 0x00008000
+#define FPM_EV_MASK_STALL_EN 0x00004000
+#define FPM_EV_MASK_SINGLE_ECC_EN 0x00002000
+#define FPM_EV_MASK_EXTERNAL_HALT 0x00000008
+#define FPM_EV_MASK_ECC_ERR_HALT 0x00000004
+
+#define FPM_RAM_RAMS_ECC_EN 0x80000000
+#define FPM_RAM_IRAM_ECC_EN 0x40000000
+#define FPM_RAM_MURAM_ECC 0x00008000
+#define FPM_RAM_IRAM_ECC 0x00004000
+#define FPM_RAM_MURAM_TEST_ECC 0x20000000
+#define FPM_RAM_IRAM_TEST_ECC 0x10000000
+#define FPM_RAM_RAMS_ECC_EN_SRC_SEL 0x08000000
+
+#define FPM_IRAM_ECC_ERR_EX_EN 0x00020000
+#define FPM_MURAM_ECC_ERR_EX_EN 0x00040000
+
+#define FPM_REV1_MAJOR_MASK 0x0000FF00
+#define FPM_REV1_MINOR_MASK 0x000000FF
+
+#define FPM_REV2_INTEG_MASK 0x00FF0000
+#define FPM_REV2_ERR_MASK 0x0000FF00
+#define FPM_REV2_CFG_MASK 0x000000FF
+
+#define FPM_TS_FRACTION_MASK 0x0000FFFF
+#define FPM_TS_CTL_EN 0x80000000
+
+#define FPM_PRC_REALSE_STALLED 0x00800000
+
+#define FPM_PS_STALLED 0x00800000
+#define FPM_PS_FM_CTL1_SEL 0x80000000
+#define FPM_PS_FM_CTL2_SEL 0x40000000
+#define FPM_PS_FM_CTL_SEL_MASK (FPM_PS_FM_CTL1_SEL | FPM_PS_FM_CTL2_SEL)
+
+#define FPM_RSTC_FM_RESET 0x80000000
+#define FPM_RSTC_10G0_RESET 0x04000000
+#define FPM_RSTC_1G0_RESET 0x40000000
+#define FPM_RSTC_1G1_RESET 0x20000000
+#define FPM_RSTC_1G2_RESET 0x10000000
+#define FPM_RSTC_1G3_RESET 0x08000000
+#define FPM_RSTC_1G4_RESET 0x02000000
+
+
+#define FPM_DISP_LIMIT_MASK 0x1F000000
+#define FPM_THR1_PRS_MASK 0xFF000000
+#define FPM_THR1_KG_MASK 0x00FF0000
+#define FPM_THR1_PLCR_MASK 0x0000FF00
+#define FPM_THR1_BMI_MASK 0x000000FF
+
+#define FPM_THR2_QMI_ENQ_MASK 0xFF000000
+#define FPM_THR2_QMI_DEQ_MASK 0x000000FF
+#define FPM_THR2_FM_CTL1_MASK 0x00FF0000
+#define FPM_THR2_FM_CTL2_MASK 0x0000FF00
+
+/* shifts */
+#define FPM_DISP_LIMIT_SHIFT 24
+
+#define FPM_THR1_PRS_SHIFT 24
+#define FPM_THR1_KG_SHIFT 16
+#define FPM_THR1_PLCR_SHIFT 8
+#define FPM_THR1_BMI_SHIFT 0
+
+#define FPM_THR2_QMI_ENQ_SHIFT 24
+#define FPM_THR2_QMI_DEQ_SHIFT 0
+#define FPM_THR2_FM_CTL1_SHIFT 16
+#define FPM_THR2_FM_CTL2_SHIFT 8
+
+#define FPM_EV_MASK_CAT_ERR_SHIFT 1
+#define FPM_EV_MASK_DMA_ERR_SHIFT 0
+
+#define FPM_REV1_MAJOR_SHIFT 8
+#define FPM_REV1_MINOR_SHIFT 0
+
+#define FPM_REV2_INTEG_SHIFT 16
+#define FPM_REV2_ERR_SHIFT 8
+#define FPM_REV2_CFG_SHIFT 0
+
+#define FPM_TS_INT_SHIFT 16
+
+#define FPM_PORT_FM_CTL_PORTID_SHIFT 24
+
+#define FPM_PS_FM_CTL_SEL_SHIFT 30
+#define FPM_PRC_ORA_FM_CTL_SEL_SHIFT 16
+
+#define FPM_DISP_LIMIT_SHIFT 24
+
+/* Interrupts defines */
+#define FPM_EVENT_FM_CTL_0 0x00008000
+#define FPM_EVENT_FM_CTL 0x0000FF00
+#define FPM_EVENT_FM_CTL_BRK 0x00000080
+
+/* others */
+#define FPM_MAX_DISP_LIMIT 31
+#define FPM_RSTC_FM_RESET 0x80000000
+#define FPM_RSTC_1G0_RESET 0x40000000
+#define FPM_RSTC_1G1_RESET 0x20000000
+#define FPM_RSTC_1G2_RESET 0x10000000
+#define FPM_RSTC_1G3_RESET 0x08000000
+#define FPM_RSTC_10G0_RESET 0x04000000
+#define FPM_RSTC_1G4_RESET 0x02000000
+#define FPM_RSTC_1G5_RESET 0x01000000
+#define FPM_RSTC_1G6_RESET 0x00800000
+#define FPM_RSTC_1G7_RESET 0x00400000
+#define FPM_RSTC_10G1_RESET 0x00200000
+/**************************************************************************//**
+ @Description BMI defines
+*//***************************************************************************/
+/* masks */
+#define BMI_INIT_START 0x80000000
+#define BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC 0x80000000
+#define BMI_ERR_INTR_EN_LIST_RAM_ECC 0x40000000
+#define BMI_ERR_INTR_EN_STATISTICS_RAM_ECC 0x20000000
+#define BMI_ERR_INTR_EN_DISPATCH_RAM_ECC 0x10000000
+#define BMI_NUM_OF_TASKS_MASK 0x3F000000
+#define BMI_NUM_OF_EXTRA_TASKS_MASK 0x000F0000
+#define BMI_NUM_OF_DMAS_MASK 0x00000F00
+#define BMI_NUM_OF_EXTRA_DMAS_MASK 0x0000000F
+#define BMI_FIFO_SIZE_MASK 0x000003FF
+#define BMI_EXTRA_FIFO_SIZE_MASK 0x03FF0000
+#define BMI_CFG2_DMAS_MASK 0x0000003F
+#define BMI_TOTAL_FIFO_SIZE_MASK 0x07FF0000
+#define BMI_TOTAL_NUM_OF_TASKS_MASK 0x007F0000
+
+/* shifts */
+#define BMI_CFG2_TASKS_SHIFT 16
+#define BMI_CFG2_DMAS_SHIFT 0
+#define BMI_CFG1_FIFO_SIZE_SHIFT 16
+#define BMI_FIFO_SIZE_SHIFT 0
+#define BMI_EXTRA_FIFO_SIZE_SHIFT 16
+#define BMI_NUM_OF_TASKS_SHIFT 24
+#define BMI_EXTRA_NUM_OF_TASKS_SHIFT 16
+#define BMI_NUM_OF_DMAS_SHIFT 8
+#define BMI_EXTRA_NUM_OF_DMAS_SHIFT 0
+
+/* others */
+#define BMI_FIFO_ALIGN 0x100
+#define FMAN_BMI_FIFO_UNITS 0x100
+
+
+/**************************************************************************//**
+ @Description QMI defines
+*//***************************************************************************/
+/* masks */
+#define QMI_CFG_ENQ_EN 0x80000000
+#define QMI_CFG_DEQ_EN 0x40000000
+#define QMI_CFG_EN_COUNTERS 0x10000000
+#define QMI_CFG_SOFT_RESET 0x01000000
+#define QMI_CFG_DEQ_MASK 0x0000003F
+#define QMI_CFG_ENQ_MASK 0x00003F00
+
+#define QMI_ERR_INTR_EN_DOUBLE_ECC 0x80000000
+#define QMI_ERR_INTR_EN_DEQ_FROM_DEF 0x40000000
+#define QMI_INTR_EN_SINGLE_ECC 0x80000000
+
+/* shifts */
+#define QMI_CFG_ENQ_SHIFT 8
+#define QMI_TAPC_TAP 22
+
+#define QMI_GS_HALT_NOT_BUSY 0x00000002
+
+
+/**************************************************************************//**
+ @Description IRAM defines
+*//***************************************************************************/
+/* masks */
+#define IRAM_IADD_AIE 0x80000000
+#define IRAM_READY 0x80000000
+
+uint32_t fman_get_bmi_err_event(struct fman_bmi_regs *bmi_rg);
+uint32_t fman_get_qmi_err_event(struct fman_qmi_regs *qmi_rg);
+uint32_t fman_get_dma_com_id(struct fman_dma_regs *dma_rg);
+uint64_t fman_get_dma_addr(struct fman_dma_regs *dma_rg);
+uint32_t fman_get_dma_err_event(struct fman_dma_regs *dma_rg);
+uint32_t fman_get_fpm_err_event(struct fman_fpm_regs *fpm_rg);
+uint32_t fman_get_muram_err_event(struct fman_fpm_regs *fpm_rg);
+uint32_t fman_get_iram_err_event(struct fman_fpm_regs *fpm_rg);
+uint32_t fman_get_qmi_event(struct fman_qmi_regs *qmi_rg);
+uint32_t fman_get_fpm_error_interrupts(struct fman_fpm_regs *fpm_rg);
+uint32_t fman_get_ctrl_intr(struct fman_fpm_regs *fpm_rg,
+ uint8_t event_reg_id);
+uint8_t fman_get_qmi_deq_th(struct fman_qmi_regs *qmi_rg);
+uint8_t fman_get_qmi_enq_th(struct fman_qmi_regs *qmi_rg);
+uint16_t fman_get_size_of_fifo(struct fman_bmi_regs *bmi_rg, uint8_t port_id);
+uint32_t fman_get_total_fifo_size(struct fman_bmi_regs *bmi_rg);
+uint16_t fman_get_size_of_extra_fifo(struct fman_bmi_regs *bmi_rg,
+ uint8_t port_id);
+uint8_t fman_get_num_of_tasks(struct fman_bmi_regs *bmi_rg, uint8_t port_id);
+uint8_t fman_get_num_extra_tasks(struct fman_bmi_regs *bmi_rg,
+ uint8_t port_id);
+uint8_t fman_get_num_of_dmas(struct fman_bmi_regs *bmi_rg, uint8_t port_id);
+uint8_t fman_get_num_extra_dmas(struct fman_bmi_regs *bmi_rg,
+ uint8_t port_id);
+uint32_t fman_get_normal_pending(struct fman_fpm_regs *fpm_rg);
+uint32_t fman_get_controller_event(struct fman_fpm_regs *fpm_rg,
+ uint8_t reg_id);
+uint32_t fman_get_error_pending(struct fman_fpm_regs *fpm_rg);
+void fman_get_revision(struct fman_fpm_regs *fpm_rg, uint8_t *major,
+ uint8_t *minor);
+uint32_t fman_get_counter(struct fman_rg *fman_rg,
+ enum fman_counters reg_name);
+uint32_t fman_get_dma_status(struct fman_dma_regs *dma_rg);
+
+
+int fman_set_erratum_10gmac_a004_wa(struct fman_fpm_regs *fpm_rg);
+void fman_set_ctrl_intr(struct fman_fpm_regs *fpm_rg, uint8_t event_reg_id,
+ uint32_t enable_events);
+void fman_set_num_of_riscs_per_port(struct fman_fpm_regs *fpm_rg,
+ uint8_t port_id,
+ uint8_t num_fman_ctrls,
+ uint32_t or_fman_ctrl);
+void fman_set_order_restoration_per_port(struct fman_fpm_regs *fpm_rg,
+ uint8_t port_id,
+ bool independent_mode,
+ bool is_rx_port);
+void fman_set_qmi_enq_th(struct fman_qmi_regs *qmi_rg, uint8_t val);
+void fman_set_qmi_deq_th(struct fman_qmi_regs *qmi_rg, uint8_t val);
+void fman_set_liodn_per_port(struct fman_rg *fman_rg,
+ uint8_t port_id,
+ uint16_t liodn_base,
+ uint16_t liodn_offset);
+void fman_set_size_of_fifo(struct fman_bmi_regs *bmi_rg,
+ uint8_t port_id,
+ uint32_t size_of_fifo,
+ uint32_t extra_size_of_fifo);
+void fman_set_num_of_tasks(struct fman_bmi_regs *bmi_rg,
+ uint8_t port_id,
+ uint8_t num_of_tasks,
+ uint8_t num_of_extra_tasks);
+void fman_set_num_of_open_dmas(struct fman_bmi_regs *bmi_rg,
+ uint8_t port_id,
+ uint8_t num_of_open_dmas,
+ uint8_t num_of_extra_open_dmas,
+ uint8_t total_num_of_dmas);
+void fman_set_ports_bandwidth(struct fman_bmi_regs *bmi_rg, uint8_t *weights);
+int fman_set_exception(struct fman_rg *fman_rg,
+ enum fman_exceptions exception,
+ bool enable);
+void fman_set_dma_emergency(struct fman_dma_regs *dma_rg, bool is_write,
+ bool enable);
+void fman_set_dma_ext_bus_pri(struct fman_dma_regs *dma_rg, uint32_t pri);
+void fman_set_congestion_group_pfc_priority(uint32_t *cpg_rg,
+ uint32_t congestion_group_id,
+ uint8_t priority_bit_map);
+
+
+void fman_defconfig(struct fman_cfg *cfg, bool is_master);
+void fman_regconfig(struct fman_rg *fman_rg, struct fman_cfg *cfg);
+int fman_fpm_init(struct fman_fpm_regs *fpm_rg, struct fman_cfg *cfg);
+int fman_bmi_init(struct fman_bmi_regs *bmi_rg, struct fman_cfg *cfg);
+int fman_qmi_init(struct fman_qmi_regs *qmi_rg, struct fman_cfg *cfg);
+int fman_dma_init(struct fman_dma_regs *dma_rg, struct fman_cfg *cfg);
+void fman_free_resources(struct fman_rg *fman_rg);
+int fman_enable(struct fman_rg *fman_rg, struct fman_cfg *cfg);
+void fman_reset(struct fman_fpm_regs *fpm_rg);
+void fman_resume(struct fman_fpm_regs *fpm_rg);
+
+
+void fman_enable_time_stamp(struct fman_fpm_regs *fpm_rg,
+ uint8_t count1ubit,
+ uint16_t fm_clk_freq);
+void fman_enable_rams_ecc(struct fman_fpm_regs *fpm_rg);
+void fman_qmi_disable_dispatch_limit(struct fman_fpm_regs *fpm_rg);
+void fman_disable_rams_ecc(struct fman_fpm_regs *fpm_rg);
+void fman_resume_stalled_port(struct fman_fpm_regs *fpm_rg, uint8_t port_id);
+int fman_reset_mac(struct fman_fpm_regs *fpm_rg, uint8_t macId, bool is_10g);
+bool fman_is_port_stalled(struct fman_fpm_regs *fpm_rg, uint8_t port_id);
+bool fman_rams_ecc_is_external_ctl(struct fman_fpm_regs *fpm_rg);
+bool fman_is_qmi_halt_not_busy_state(struct fman_qmi_regs *qmi_rg);
+int fman_modify_counter(struct fman_rg *fman_rg,
+ enum fman_counters reg_name,
+ uint32_t val);
+void fman_force_intr(struct fman_rg *fman_rg,
+ enum fman_exceptions exception);
+void fman_set_vsp_window(struct fman_bmi_regs *bmi_rg,
+ uint8_t port_id,
+ uint8_t base_storage_profile,
+ uint8_t log2_num_of_profiles);
+
+/**************************************************************************//**
+ @Description default values
+*//***************************************************************************/
+#define DEFAULT_CATASTROPHIC_ERR E_FMAN_CATAST_ERR_STALL_PORT
+#define DEFAULT_DMA_ERR E_FMAN_DMA_ERR_CATASTROPHIC
+#define DEFAULT_HALT_ON_EXTERNAL_ACTIVATION FALSE /* do not change! if changed, must be disabled for rev1 ! */
+#define DEFAULT_HALT_ON_UNRECOVERABLE_ECC_ERROR FALSE /* do not change! if changed, must be disabled for rev1 ! */
+#define DEFAULT_EXTERNAL_ECC_RAMS_ENABLE FALSE
+#define DEFAULT_AID_OVERRIDE FALSE
+#define DEFAULT_AID_MODE E_FMAN_DMA_AID_OUT_TNUM
+#define DEFAULT_DMA_COMM_Q_LOW 0x2A
+#define DEFAULT_DMA_COMM_Q_HIGH 0x3F
+#define DEFAULT_CACHE_OVERRIDE E_FMAN_DMA_NO_CACHE_OR
+#define DEFAULT_DMA_CAM_NUM_OF_ENTRIES 64
+#define DEFAULT_DMA_DBG_CNT_MODE E_FMAN_DMA_DBG_NO_CNT
+#define DEFAULT_DMA_EN_EMERGENCY FALSE
+#define DEFAULT_DMA_SOS_EMERGENCY 0
+#define DEFAULT_DMA_WATCHDOG 0 /* disabled */
+#define DEFAULT_DMA_EN_EMERGENCY_SMOOTHER FALSE
+#define DEFAULT_DMA_EMERGENCY_SWITCH_COUNTER 0
+#define DEFAULT_DISP_LIMIT 0
+#define DEFAULT_PRS_DISP_TH 16
+#define DEFAULT_PLCR_DISP_TH 16
+#define DEFAULT_KG_DISP_TH 16
+#define DEFAULT_BMI_DISP_TH 16
+#define DEFAULT_QMI_ENQ_DISP_TH 16
+#define DEFAULT_QMI_DEQ_DISP_TH 16
+#define DEFAULT_FM_CTL1_DISP_TH 16
+#define DEFAULT_FM_CTL2_DISP_TH 16
+#define DEFAULT_TNUM_AGING_PERIOD 4
+
+
+#endif /* __FSL_FMAN_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_dtsec.h b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_dtsec.h
new file mode 100644
index 0000000..6004e47
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_dtsec.h
@@ -0,0 +1,1096 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FSL_FMAN_DTSEC_H
+#define __FSL_FMAN_DTSEC_H
+
+#include "common/general.h"
+#include "fsl_enet.h"
+
+/**
+ * DOC: dTSEC Init sequence
+ *
+ * To prepare dTSEC block for transfer use the following call sequence:
+ *
+ * - fman_dtsec_defconfig() - This step is optional and yet recommended. Its
+ * use is to obtain the default dTSEC configuration parameters.
+ *
+ * - Change dtsec configuration in &dtsec_cfg. This structure will be used
+ * to customize the dTSEC behavior.
+ *
+ * - fman_dtsec_init() - Applies the configuration on dTSEC hardware. Note that
+ * dTSEC is initialized while both Tx and Rx are disabled.
+ *
+ * - fman_dtsec_set_mac_address() - Set the station address (mac address).
+ * This is used by dTSEC to match against received packets.
+ *
+ * - fman_dtsec_adjust_link() - Set the link speed and duplex parameters
+ * after the PHY establishes the link.
+ *
+ * - dtsec_enable_tx() and dtsec_enable_rx() to enable transmission and
+ * reception.
+ */
+
+/**
+ * DOC: dTSEC Graceful stop
+ *
+ * To temporary stop dTSEC activity use fman_dtsec_stop_tx() and
+ * fman_dtsec_stop_rx(). Note that these functions request dTSEC graceful stop
+ * but return before this stop is complete. To query for graceful stop
+ * completion use fman_dtsec_get_event() and check DTSEC_IEVENT_GTSC and
+ * DTSEC_IEVENT_GRSC bits. Alternatively the dTSEC interrupt mask can be set to
+ * enable graceful stop interrupts.
+ *
+ * To resume operation after graceful stop use fman_dtsec_start_tx() and
+ * fman_dtsec_start_rx().
+ */
+
+/**
+ * DOC: dTSEC interrupt handling
+ *
+ * This code does not provide an interrupt handler for dTSEC. Instead this
+ * handler should be implemented and registered to the operating system by the
+ * caller. Some primitives for accessing the event status and mask registers
+ * are provided.
+ *
+ * See "dTSEC Events" section for a list of events that dTSEC can generate.
+ */
+
+/**
+ * DOC: dTSEC Events
+ *
+ * Interrupt events cause dTSEC event bits to be set. Software may poll the
+ * event register at any time to check for pending interrupts. If an event
+ * occurs and its corresponding enable bit is set in the interrupt mask
+ * register, the event also causes a hardware interrupt at the PIC.
+ *
+ * To poll for event status use the fman_dtsec_get_event() function.
+ * To configure the interrupt mask use fman_dtsec_enable_interrupt() and
+ * fman_dtsec_disable_interrupt() functions.
+ * After servicing a dTSEC interrupt use fman_dtsec_ack_event to reset the
+ * serviced event bit.
+ *
+ * The following events may be signaled by dTSEC hardware:
+ *
+ * %DTSEC_IEVENT_BABR - Babbling receive error. This bit indicates that
+ * a frame was received with length in excess of the MAC's maximum frame length
+ * register.
+ *
+ * %DTSEC_IEVENT_RXC - Receive control (pause frame) interrupt. A pause
+ * control frame was received while Rx pause frame handling is enabled.
+ * Also see fman_dtsec_handle_rx_pause().
+ *
+ * %DTSEC_IEVENT_MSRO - MIB counter overflow. The count for one of the MIB
+ * counters has exceeded the size of its register.
+ *
+ * %DTSEC_IEVENT_GTSC - Graceful transmit stop complete. Graceful stop is now
+ * complete. The transmitter is in a stopped state, in which only pause frames
+ * can be transmitted.
+ * Also see fman_dtsec_stop_tx().
+ *
+ * %DTSEC_IEVENT_BABT - Babbling transmit error. The transmitted frame length
+ * has exceeded the value in the MAC's Maximum Frame Length register.
+ *
+ * %DTSEC_IEVENT_TXC - Transmit control (pause frame) interrupt. his bit
+ * indicates that a control frame was transmitted.
+ *
+ * %DTSEC_IEVENT_TXE - Transmit error. This bit indicates that an error
+ * occurred on the transmitted channel. This bit is set whenever any transmit
+ * error occurs which causes the dTSEC to discard all or part of a frame
+ * (LC, CRL, XFUN).
+ *
+ * %DTSEC_IEVENT_LC - Late collision. This bit indicates that a collision
+ * occurred beyond the collision window (slot time) in half-duplex mode.
+ * The frame is truncated with a bad CRC and the remainder of the frame
+ * is discarded.
+ *
+ * %DTSEC_IEVENT_CRL - Collision retry limit. is bit indicates that the number
+ * of successive transmission collisions has exceeded the MAC's half-duplex
+ * register's retransmission maximum count. The frame is discarded without
+ * being transmitted and transmission of the next frame commences. This only
+ * occurs while in half-duplex mode.
+ * The number of retransmit attempts can be set in
+ * &dtsec_halfdup_cfg.@retransmit before calling fman_dtsec_init().
+ *
+ * %DTSEC_IEVENT_XFUN - Transmit FIFO underrun. This bit indicates that the
+ * transmit FIFO became empty before the complete frame was transmitted.
+ * The frame is truncated with a bad CRC and the remainder of the frame is
+ * discarded.
+ *
+ * %DTSEC_IEVENT_MAG - TBD
+ *
+ * %DTSEC_IEVENT_MMRD - MII management read completion.
+ *
+ * %DTSEC_IEVENT_MMWR - MII management write completion.
+ *
+ * %DTSEC_IEVENT_GRSC - Graceful receive stop complete. It allows the user to
+ * know if the system has completed the stop and it is safe to write to receive
+ * registers (status, control or configuration registers) that are used by the
+ * system during normal operation.
+ *
+ * %DTSEC_IEVENT_TDPE - Internal data error on transmit. This bit indicates
+ * that the dTSEC has detected a parity error on its stored transmit data, which
+ * is likely to compromise the validity of recently transferred frames.
+ *
+ * %DTSEC_IEVENT_RDPE - Internal data error on receive. This bit indicates that
+ * the dTSEC has detected a parity error on its stored receive data, which is
+ * likely to compromise the validity of recently transferred frames.
+ */
+/* Interrupt Mask Register (IMASK) */
+#define DTSEC_IMASK_BREN 0x80000000
+#define DTSEC_IMASK_RXCEN 0x40000000
+#define DTSEC_IMASK_MSROEN 0x04000000
+#define DTSEC_IMASK_GTSCEN 0x02000000
+#define DTSEC_IMASK_BTEN 0x01000000
+#define DTSEC_IMASK_TXCEN 0x00800000
+#define DTSEC_IMASK_TXEEN 0x00400000
+#define DTSEC_IMASK_LCEN 0x00040000
+#define DTSEC_IMASK_CRLEN 0x00020000
+#define DTSEC_IMASK_XFUNEN 0x00010000
+#define DTSEC_IMASK_ABRTEN 0x00008000
+#define DTSEC_IMASK_IFERREN 0x00004000
+#define DTSEC_IMASK_MAGEN 0x00000800
+#define DTSEC_IMASK_MMRDEN 0x00000400
+#define DTSEC_IMASK_MMWREN 0x00000200
+#define DTSEC_IMASK_GRSCEN 0x00000100
+#define DTSEC_IMASK_TDPEEN 0x00000002
+#define DTSEC_IMASK_RDPEEN 0x00000001
+
+#define DTSEC_EVENTS_MASK \
+ ((uint32_t)(DTSEC_IMASK_BREN | \
+ DTSEC_IMASK_RXCEN | \
+ DTSEC_IMASK_BTEN | \
+ DTSEC_IMASK_TXCEN | \
+ DTSEC_IMASK_TXEEN | \
+ DTSEC_IMASK_ABRTEN | \
+ DTSEC_IMASK_LCEN | \
+ DTSEC_IMASK_CRLEN | \
+ DTSEC_IMASK_XFUNEN | \
+ DTSEC_IMASK_IFERREN | \
+ DTSEC_IMASK_MAGEN | \
+ DTSEC_IMASK_TDPEEN | \
+ DTSEC_IMASK_RDPEEN))
+
+/* dtsec timestamp event bits */
+#define TMR_PEMASK_TSREEN 0x00010000
+#define TMR_PEVENT_TSRE 0x00010000
+
+/* Group address bit indication */
+#define MAC_GROUP_ADDRESS 0x0000010000000000ULL
+/* size in bytes of L2 address */
+#define MAC_ADDRLEN 6
+
+#define DEFAULT_HALFDUP_ON FALSE
+#define DEFAULT_HALFDUP_RETRANSMIT 0xf
+#define DEFAULT_HALFDUP_COLL_WINDOW 0x37
+#define DEFAULT_HALFDUP_EXCESS_DEFER TRUE
+#define DEFAULT_HALFDUP_NO_BACKOFF FALSE
+#define DEFAULT_HALFDUP_BP_NO_BACKOFF FALSE
+#define DEFAULT_HALFDUP_ALT_BACKOFF_VAL 0x0A
+#define DEFAULT_HALFDUP_ALT_BACKOFF_EN FALSE
+#define DEFAULT_RX_DROP_BCAST FALSE
+#define DEFAULT_RX_SHORT_FRM TRUE
+#define DEFAULT_RX_LEN_CHECK FALSE
+#define DEFAULT_TX_PAD_CRC TRUE
+#define DEFAULT_TX_CRC FALSE
+#define DEFAULT_RX_CTRL_ACC FALSE
+#define DEFAULT_TX_PAUSE_TIME 0xf000
+#define DEFAULT_TBIPA 5
+#define DEFAULT_RX_PREPEND 0
+#define DEFAULT_PTP_TSU_EN TRUE
+#define DEFAULT_PTP_EXCEPTION_EN TRUE
+#define DEFAULT_PREAMBLE_LEN 7
+#define DEFAULT_RX_PREAMBLE FALSE
+#define DEFAULT_TX_PREAMBLE FALSE
+#define DEFAULT_LOOPBACK FALSE
+#define DEFAULT_RX_TIME_STAMP_EN FALSE
+#define DEFAULT_TX_TIME_STAMP_EN FALSE
+#define DEFAULT_RX_FLOW TRUE
+#define DEFAULT_TX_FLOW TRUE
+#define DEFAULT_RX_GROUP_HASH_EXD FALSE
+#define DEFAULT_TX_PAUSE_TIME_EXTD 0
+#define DEFAULT_RX_PROMISC FALSE
+#define DEFAULT_NON_BACK_TO_BACK_IPG1 0x40
+#define DEFAULT_NON_BACK_TO_BACK_IPG2 0x60
+#define DEFAULT_MIN_IFG_ENFORCEMENT 0x50
+#define DEFAULT_BACK_TO_BACK_IPG 0x60
+#define DEFAULT_MAXIMUM_FRAME 0x600
+#define DEFAULT_TBI_PHY_ADDR 5
+#define DEFAULT_WAKE_ON_LAN FALSE
+
+/* register related defines (bits, field offsets..) */
+#define DTSEC_ID1_ID 0xffff0000
+#define DTSEC_ID1_REV_MJ 0x0000FF00
+#define DTSEC_ID1_REV_MN 0x000000ff
+
+#define DTSEC_ID2_INT_REDUCED_OFF 0x00010000
+#define DTSEC_ID2_INT_NORMAL_OFF 0x00020000
+
+#define DTSEC_ECNTRL_CLRCNT 0x00004000
+#define DTSEC_ECNTRL_AUTOZ 0x00002000
+#define DTSEC_ECNTRL_STEN 0x00001000
+#define DTSEC_ECNTRL_CFG_RO 0x80000000
+#define DTSEC_ECNTRL_GMIIM 0x00000040
+#define DTSEC_ECNTRL_TBIM 0x00000020
+#define DTSEC_ECNTRL_SGMIIM 0x00000002
+#define DTSEC_ECNTRL_RPM 0x00000010
+#define DTSEC_ECNTRL_R100M 0x00000008
+#define DTSEC_ECNTRL_RMM 0x00000004
+#define DTSEC_ECNTRL_QSGMIIM 0x00000001
+
+#define DTSEC_TCTRL_THDF 0x00000800
+#define DTSEC_TCTRL_TTSE 0x00000040
+#define DTSEC_TCTRL_GTS 0x00000020
+#define DTSEC_TCTRL_TFC_PAUSE 0x00000010
+
+/* PTV offsets */
+#define PTV_PTE_OFST 16
+
+#define RCTRL_CFA 0x00008000
+#define RCTRL_GHTX 0x00000400
+#define RCTRL_RTSE 0x00000040
+#define RCTRL_GRS 0x00000020
+#define RCTRL_BC_REJ 0x00000010
+#define RCTRL_MPROM 0x00000008
+#define RCTRL_RSF 0x00000004
+#define RCTRL_UPROM 0x00000001
+#define RCTRL_PROM (RCTRL_UPROM | RCTRL_MPROM)
+
+#define TMR_CTL_ESFDP 0x00000800
+#define TMR_CTL_ESFDE 0x00000400
+
+#define MACCFG1_SOFT_RESET 0x80000000
+#define MACCFG1_LOOPBACK 0x00000100
+#define MACCFG1_RX_FLOW 0x00000020
+#define MACCFG1_TX_FLOW 0x00000010
+#define MACCFG1_TX_EN 0x00000001
+#define MACCFG1_RX_EN 0x00000004
+#define MACCFG1_RESET_RxMC 0x00080000
+#define MACCFG1_RESET_TxMC 0x00040000
+#define MACCFG1_RESET_RxFUN 0x00020000
+#define MACCFG1_RESET_TxFUN 0x00010000
+
+#define MACCFG2_NIBBLE_MODE 0x00000100
+#define MACCFG2_BYTE_MODE 0x00000200
+#define MACCFG2_PRE_AM_Rx_EN 0x00000080
+#define MACCFG2_PRE_AM_Tx_EN 0x00000040
+#define MACCFG2_LENGTH_CHECK 0x00000010
+#define MACCFG2_MAGIC_PACKET_EN 0x00000008
+#define MACCFG2_PAD_CRC_EN 0x00000004
+#define MACCFG2_CRC_EN 0x00000002
+#define MACCFG2_FULL_DUPLEX 0x00000001
+
+#define PREAMBLE_LENGTH_SHIFT 12
+
+#define IPGIFG_NON_BACK_TO_BACK_IPG_1_SHIFT 24
+#define IPGIFG_NON_BACK_TO_BACK_IPG_2_SHIFT 16
+#define IPGIFG_MIN_IFG_ENFORCEMENT_SHIFT 8
+
+#define IPGIFG_NON_BACK_TO_BACK_IPG_1 0x7F000000
+#define IPGIFG_NON_BACK_TO_BACK_IPG_2 0x007F0000
+#define IPGIFG_MIN_IFG_ENFORCEMENT 0x0000FF00
+#define IPGIFG_BACK_TO_BACK_IPG 0x0000007F
+
+#define HAFDUP_ALT_BEB 0x00080000
+#define HAFDUP_BP_NO_BACKOFF 0x00040000
+#define HAFDUP_NO_BACKOFF 0x00020000
+#define HAFDUP_EXCESS_DEFER 0x00010000
+#define HAFDUP_COLLISION_WINDOW 0x000003ff
+
+#define HAFDUP_ALTERNATE_BEB_TRUNCATION_SHIFT 20
+#define HAFDUP_RETRANSMISSION_MAX_SHIFT 12
+#define HAFDUP_RETRANSMISSION_MAX 0x0000f000
+
+#define NUM_OF_HASH_REGS 8 /* Number of hash table registers */
+
+/* CAR1/2 bits */
+#define DTSEC_CAR1_TR64 0x80000000
+#define DTSEC_CAR1_TR127 0x40000000
+#define DTSEC_CAR1_TR255 0x20000000
+#define DTSEC_CAR1_TR511 0x10000000
+#define DTSEC_CAR1_TRK1 0x08000000
+#define DTSEC_CAR1_TRMAX 0x04000000
+#define DTSEC_CAR1_TRMGV 0x02000000
+
+#define DTSEC_CAR1_RBYT 0x00010000
+#define DTSEC_CAR1_RPKT 0x00008000
+#define DTSEC_CAR1_RFCS 0x00004000
+#define DTSEC_CAR1_RMCA 0x00002000
+#define DTSEC_CAR1_RBCA 0x00001000
+#define DTSEC_CAR1_RXCF 0x00000800
+#define DTSEC_CAR1_RXPF 0x00000400
+#define DTSEC_CAR1_RXUO 0x00000200
+#define DTSEC_CAR1_RALN 0x00000100
+#define DTSEC_CAR1_RFLR 0x00000080
+#define DTSEC_CAR1_RCDE 0x00000040
+#define DTSEC_CAR1_RCSE 0x00000020
+#define DTSEC_CAR1_RUND 0x00000010
+#define DTSEC_CAR1_ROVR 0x00000008
+#define DTSEC_CAR1_RFRG 0x00000004
+#define DTSEC_CAR1_RJBR 0x00000002
+#define DTSEC_CAR1_RDRP 0x00000001
+
+#define DTSEC_CAR2_TJBR 0x00080000
+#define DTSEC_CAR2_TFCS 0x00040000
+#define DTSEC_CAR2_TXCF 0x00020000
+#define DTSEC_CAR2_TOVR 0x00010000
+#define DTSEC_CAR2_TUND 0x00008000
+#define DTSEC_CAR2_TFRG 0x00004000
+#define DTSEC_CAR2_TBYT 0x00002000
+#define DTSEC_CAR2_TPKT 0x00001000
+#define DTSEC_CAR2_TMCA 0x00000800
+#define DTSEC_CAR2_TBCA 0x00000400
+#define DTSEC_CAR2_TXPF 0x00000200
+#define DTSEC_CAR2_TDFR 0x00000100
+#define DTSEC_CAR2_TEDF 0x00000080
+#define DTSEC_CAR2_TSCL 0x00000040
+#define DTSEC_CAR2_TMCL 0x00000020
+#define DTSEC_CAR2_TLCL 0x00000010
+#define DTSEC_CAR2_TXCL 0x00000008
+#define DTSEC_CAR2_TNCL 0x00000004
+#define DTSEC_CAR2_TDRP 0x00000001
+
+#define CAM1_ERRORS_ONLY \
+ (DTSEC_CAR1_RXPF | DTSEC_CAR1_RALN | DTSEC_CAR1_RFLR \
+ | DTSEC_CAR1_RCDE | DTSEC_CAR1_RCSE | DTSEC_CAR1_RUND \
+ | DTSEC_CAR1_ROVR | DTSEC_CAR1_RFRG | DTSEC_CAR1_RJBR \
+ | DTSEC_CAR1_RDRP)
+
+#define CAM2_ERRORS_ONLY (DTSEC_CAR2_TFCS | DTSEC_CAR2_TXPF | DTSEC_CAR2_TDRP)
+
+/*
+ * Group of dTSEC specific counters relating to the standard RMON MIB Group 1
+ * (or Ethernet) statistics.
+ */
+#define CAM1_MIB_GRP_1 \
+ (DTSEC_CAR1_RDRP | DTSEC_CAR1_RBYT | DTSEC_CAR1_RPKT | DTSEC_CAR1_RMCA\
+ | DTSEC_CAR1_RBCA | DTSEC_CAR1_RALN | DTSEC_CAR1_RUND | DTSEC_CAR1_ROVR\
+ | DTSEC_CAR1_RFRG | DTSEC_CAR1_RJBR \
+ | DTSEC_CAR1_TR64 | DTSEC_CAR1_TR127 | DTSEC_CAR1_TR255 \
+ | DTSEC_CAR1_TR511 | DTSEC_CAR1_TRMAX)
+
+#define CAM2_MIB_GRP_1 (DTSEC_CAR2_TNCL | DTSEC_CAR2_TDRP)
+
+/* memory map */
+
+struct dtsec_regs {
+ /* dTSEC General Control and Status Registers */
+ uint32_t tsec_id; /* 0x000 ETSEC_ID register */
+ uint32_t tsec_id2; /* 0x004 ETSEC_ID2 register */
+ uint32_t ievent; /* 0x008 Interrupt event register */
+ uint32_t imask; /* 0x00C Interrupt mask register */
+ uint32_t reserved0010[1];
+ uint32_t ecntrl; /* 0x014 E control register */
+ uint32_t ptv; /* 0x018 Pause time value register */
+ uint32_t tbipa; /* 0x01C TBI PHY address register */
+ uint32_t tmr_ctrl; /* 0x020 Time-stamp Control register */
+ uint32_t tmr_pevent; /* 0x024 Time-stamp event register */
+ uint32_t tmr_pemask; /* 0x028 Timer event mask register */
+ uint32_t reserved002c[5];
+ uint32_t tctrl; /* 0x040 Transmit control register */
+ uint32_t reserved0044[3];
+ uint32_t rctrl; /* 0x050 Receive control register */
+ uint32_t reserved0054[11];
+ uint32_t igaddr[8]; /* 0x080-0x09C Individual/group address */
+ uint32_t gaddr[8]; /* 0x0A0-0x0BC Group address registers 0-7 */
+ uint32_t reserved00c0[16];
+ uint32_t maccfg1; /* 0x100 MAC configuration #1 */
+ uint32_t maccfg2; /* 0x104 MAC configuration #2 */
+ uint32_t ipgifg; /* 0x108 IPG/IFG */
+ uint32_t hafdup; /* 0x10C Half-duplex */
+ uint32_t maxfrm; /* 0x110 Maximum frame */
+ uint32_t reserved0114[10];
+ uint32_t ifstat; /* 0x13C Interface status */
+ uint32_t macstnaddr1; /* 0x140 Station Address,part 1 */
+ uint32_t macstnaddr2; /* 0x144 Station Address,part 2 */
+ struct {
+ uint32_t exact_match1; /* octets 1-4 */
+ uint32_t exact_match2; /* octets 5-6 */
+ } macaddr[15]; /* 0x148-0x1BC mac exact match addresses 1-15 */
+ uint32_t reserved01c0[16];
+ uint32_t tr64; /* 0x200 transmit and receive 64 byte frame counter */
+ uint32_t tr127; /* 0x204 transmit and receive 65 to 127 byte frame
+ * counter */
+ uint32_t tr255; /* 0x208 transmit and receive 128 to 255 byte frame
+ * counter */
+ uint32_t tr511; /* 0x20C transmit and receive 256 to 511 byte frame
+ * counter */
+ uint32_t tr1k; /* 0x210 transmit and receive 512 to 1023 byte frame
+ * counter */
+ uint32_t trmax; /* 0x214 transmit and receive 1024 to 1518 byte frame
+ * counter */
+ uint32_t trmgv; /* 0x218 transmit and receive 1519 to 1522 byte good
+ * VLAN frame count */
+ uint32_t rbyt; /* 0x21C receive byte counter */
+ uint32_t rpkt; /* 0x220 receive packet counter */
+ uint32_t rfcs; /* 0x224 receive FCS error counter */
+ uint32_t rmca; /* 0x228 RMCA receive multicast packet counter */
+ uint32_t rbca; /* 0x22C receive broadcast packet counter */
+ uint32_t rxcf; /* 0x230 receive control frame packet counter */
+ uint32_t rxpf; /* 0x234 receive pause frame packet counter */
+ uint32_t rxuo; /* 0x238 receive unknown OP code counter */
+ uint32_t raln; /* 0x23C receive alignment error counter */
+ uint32_t rflr; /* 0x240 receive frame length error counter */
+ uint32_t rcde; /* 0x244 receive code error counter */
+ uint32_t rcse; /* 0x248 receive carrier sense error counter */
+ uint32_t rund; /* 0x24C receive undersize packet counter */
+ uint32_t rovr; /* 0x250 receive oversize packet counter */
+ uint32_t rfrg; /* 0x254 receive fragments counter */
+ uint32_t rjbr; /* 0x258 receive jabber counter */
+ uint32_t rdrp; /* 0x25C receive drop */
+ uint32_t tbyt; /* 0x260 transmit byte counter */
+ uint32_t tpkt; /* 0x264 transmit packet counter */
+ uint32_t tmca; /* 0x268 transmit multicast packet counter */
+ uint32_t tbca; /* 0x26C transmit broadcast packet counter */
+ uint32_t txpf; /* 0x270 transmit pause control frame counter */
+ uint32_t tdfr; /* 0x274 transmit deferral packet counter */
+ uint32_t tedf; /* 0x278 transmit excessive deferral packet counter */
+ uint32_t tscl; /* 0x27C transmit single collision packet counter */
+ uint32_t tmcl; /* 0x280 transmit multiple collision packet counter */
+ uint32_t tlcl; /* 0x284 transmit late collision packet counter */
+ uint32_t txcl; /* 0x288 transmit excessive collision packet counter */
+ uint32_t tncl; /* 0x28C transmit total collision counter */
+ uint32_t reserved0290[1];
+ uint32_t tdrp; /* 0x294 transmit drop frame counter */
+ uint32_t tjbr; /* 0x298 transmit jabber frame counter */
+ uint32_t tfcs; /* 0x29C transmit FCS error counter */
+ uint32_t txcf; /* 0x2A0 transmit control frame counter */
+ uint32_t tovr; /* 0x2A4 transmit oversize frame counter */
+ uint32_t tund; /* 0x2A8 transmit undersize frame counter */
+ uint32_t tfrg; /* 0x2AC transmit fragments frame counter */
+ uint32_t car1; /* 0x2B0 carry register one register* */
+ uint32_t car2; /* 0x2B4 carry register two register* */
+ uint32_t cam1; /* 0x2B8 carry register one mask register */
+ uint32_t cam2; /* 0x2BC carry register two mask register */
+ uint32_t reserved02c0[848];
+};
+
+/**
+ * struct dtsec_mib_grp_1_counters - MIB counter overflows
+ *
+ * @tr64: Transmit and Receive 64 byte frame count. Increment for each
+ * good or bad frame, of any type, transmitted or received, which
+ * is 64 bytes in length.
+ * @tr127: Transmit and Receive 65 to 127 byte frame count. Increments for
+ * each good or bad frame of any type, transmitted or received,
+ * which is 65-127 bytes in length.
+ * @tr255: Transmit and Receive 128 to 255 byte frame count. Increments
+ * for each good or bad frame, of any type, transmitted or
+ * received, which is 128-255 bytes in length.
+ * @tr511: Transmit and Receive 256 to 511 byte frame count. Increments
+ * for each good or bad frame, of any type, transmitted or
+ * received, which is 256-511 bytes in length.
+ * @tr1k: Transmit and Receive 512 to 1023 byte frame count. Increments
+ * for each good or bad frame, of any type, transmitted or
+ * received, which is 512-1023 bytes in length.
+ * @trmax: Transmit and Receive 1024 to 1518 byte frame count. Increments
+ * for each good or bad frame, of any type, transmitted or
+ * received, which is 1024-1518 bytes in length.
+ * @rfrg: Receive fragments count. Increments for each received frame
+ * which is less than 64 bytes in length and contains an invalid
+ * FCS. This includes integral and non-integral lengths.
+ * @rjbr: Receive jabber count. Increments for received frames which
+ * exceed 1518 (non VLAN) or 1522 (VLAN) bytes and contain an
+ * invalid FCS. This includes alignment errors.
+ * @rdrp: Receive dropped packets count. Increments for received frames
+ * which are streamed to system but are later dropped due to lack
+ * of system resources. Does not increment for frames rejected due
+ * to address filtering.
+ * @raln: Receive alignment error count. Increments for each received
+ * frame from 64 to 1518 (non VLAN) or 1522 (VLAN) which contains
+ * an invalid FCS and is not an integral number of bytes.
+ * @rund: Receive undersize packet count. Increments each time a frame is
+ * received which is less than 64 bytes in length and contains a
+ * valid FCS and is otherwise well formed. This count does not
+ * include range length errors.
+ * @rovr: Receive oversize packet count. Increments each time a frame is
+ * received which exceeded 1518 (non VLAN) or 1522 (VLAN) and
+ * contains a valid FCS and is otherwise well formed.
+ * @rbyt: Receive byte count. Increments by the byte count of frames
+ * received, including those in bad packets, excluding preamble and
+ * SFD but including FCS bytes.
+ * @rpkt: Receive packet count. Increments for each received frame
+ * (including bad packets, all unicast, broadcast, and multicast
+ * packets).
+ * @rmca: Receive multicast packet count. Increments for each multicast
+ * frame with valid CRC and of lengths 64 to 1518 (non VLAN) or
+ * 1522 (VLAN), excluding broadcast frames. This count does not
+ * include range/length errors.
+ * @rbca: Receive broadcast packet count. Increments for each broadcast
+ * frame with valid CRC and of lengths 64 to 1518 (non VLAN) or
+ * 1522 (VLAN), excluding multicast frames. Does not include
+ * range/length errors.
+ * @tdrp: Transmit drop frame count. Increments each time a memory error
+ * or an underrun has occurred.
+ * @tncl: Transmit total collision counter. Increments by the number of
+ * collisions experienced during the transmission of a frame. Does
+ * not increment for aborted frames.
+ *
+ * The structure contains a group of dTSEC HW specific counters relating to the
+ * standard RMON MIB Group 1 (or Ethernet statistics) counters. This structure
+ * is counting only the carry events of the corresponding HW counters.
+ *
+ * tr64 to trmax notes: Frame sizes specified are considered excluding preamble
+ * and SFD but including FCS bytes.
+ */
+struct dtsec_mib_grp_1_counters {
+ uint64_t rdrp;
+ uint64_t tdrp;
+ uint64_t rbyt;
+ uint64_t rpkt;
+ uint64_t rbca;
+ uint64_t rmca;
+ uint64_t raln;
+ uint64_t rund;
+ uint64_t rovr;
+ uint64_t rfrg;
+ uint64_t rjbr;
+ uint64_t tncl;
+ uint64_t tr64;
+ uint64_t tr127;
+ uint64_t tr255;
+ uint64_t tr511;
+ uint64_t tr1k;
+ uint64_t trmax;
+};
+
+enum dtsec_stat_counters {
+ E_DTSEC_STAT_TR64,
+ E_DTSEC_STAT_TR127,
+ E_DTSEC_STAT_TR255,
+ E_DTSEC_STAT_TR511,
+ E_DTSEC_STAT_TR1K,
+ E_DTSEC_STAT_TRMAX,
+ E_DTSEC_STAT_TRMGV,
+ E_DTSEC_STAT_RBYT,
+ E_DTSEC_STAT_RPKT,
+ E_DTSEC_STAT_RMCA,
+ E_DTSEC_STAT_RBCA,
+ E_DTSEC_STAT_RXPF,
+ E_DTSEC_STAT_RALN,
+ E_DTSEC_STAT_RFLR,
+ E_DTSEC_STAT_RCDE,
+ E_DTSEC_STAT_RCSE,
+ E_DTSEC_STAT_RUND,
+ E_DTSEC_STAT_ROVR,
+ E_DTSEC_STAT_RFRG,
+ E_DTSEC_STAT_RJBR,
+ E_DTSEC_STAT_RDRP,
+ E_DTSEC_STAT_TFCS,
+ E_DTSEC_STAT_TBYT,
+ E_DTSEC_STAT_TPKT,
+ E_DTSEC_STAT_TMCA,
+ E_DTSEC_STAT_TBCA,
+ E_DTSEC_STAT_TXPF,
+ E_DTSEC_STAT_TNCL,
+ E_DTSEC_STAT_TDRP
+};
+
+enum dtsec_stat_level {
+ /* No statistics */
+ E_MAC_STAT_NONE = 0,
+ /* Only RMON MIB group 1 (ether stats). Optimized for performance */
+ E_MAC_STAT_MIB_GRP1,
+ /* Only error counters are available. Optimized for performance */
+ E_MAC_STAT_PARTIAL,
+ /* All counters available. Not optimized for performance */
+ E_MAC_STAT_FULL
+};
+
+
+/**
+ * struct dtsec_cfg - dTSEC configuration
+ *
+ * @halfdup_on: Transmit half-duplex flow control, under software
+ * control for 10/100-Mbps half-duplex media. If set,
+ * back pressure is applied to media by raising carrier.
+ * @halfdup_retransmit: Number of retransmission attempts following a collision.
+ * If this is exceeded dTSEC aborts transmission due to
+ * excessive collisions. The standard specifies the
+ * attempt limit to be 15.
+ * @halfdup_coll_window:The number of bytes of the frame during which
+ * collisions may occur. The default value of 55
+ * corresponds to the frame byte at the end of the
+ * standard 512-bit slot time window. If collisions are
+ * detected after this byte, the late collision event is
+ * asserted and transmission of current frame is aborted.
+ * @rx_drop_bcast: Discard broadcast frames. If set, all broadcast frames
+ * will be discarded by dTSEC.
+ * @rx_short_frm: Accept short frames. If set, dTSEC will accept frames
+ * of length 14..63 bytes.
+ * @rx_len_check: Length check for received frames. If set, the MAC
+ * checks the frame's length field on receive to ensure it
+ * matches the actual data field length. This only works
+ * for received frames with length field less than 1500.
+ * No check is performed for larger frames.
+ * @tx_pad_crc: Pad and append CRC. If set, the MAC pads all
+ * transmitted short frames and appends a CRC to every
+ * frame regardless of padding requirement.
+ * @tx_crc: Transmission CRC enable. If set, the MAC appends a CRC
+ * to all frames. If frames presented to the MAC have a
+ * valid length and contain a valid CRC, @tx_crc should be
+ * reset.
+ * This field is ignored if @tx_pad_crc is set.
+ * @rx_ctrl_acc: Control frame accept. If set, this overrides 802.3
+ * standard control frame behavior, and all Ethernet frames
+ * that have an ethertype of 0x8808 are treated as normal
+ * Ethernet frames and passed up to the packet interface on
+ * a DA match. Received pause control frames are passed to
+ * the packet interface only if Rx flow control is also
+ * disabled. See fman_dtsec_handle_rx_pause() function.
+ * @tx_pause_time: Transmit pause time value. This pause value is used as
+ * part of the pause frame to be sent when a transmit pause
+ * frame is initiated. If set to 0 this disables
+ * transmission of pause frames.
+ * @rx_preamble: Receive preamble enable. If set, the MAC recovers the
+ * received Ethernet 7-byte preamble and passes it to the
+ * packet interface at the start of each received frame.
+ * This field should be reset for internal MAC loop-back
+ * mode.
+ * @tx_preamble: User defined preamble enable for transmitted frames.
+ * If set, a user-defined preamble must passed to the MAC
+ * and it is transmitted instead of the standard preamble.
+ * @preamble_len: Length, in bytes, of the preamble field preceding each
+ * Ethernet start-of-frame delimiter byte. The default
+ * value of 0x7 should be used in order to guarantee
+ * reliable operation with IEEE 802.3 compliant hardware.
+ * @rx_prepend: Packet alignment padding length. The specified number
+ * of bytes (1-31) of zero padding are inserted before the
+ * start of each received frame. For Ethernet, where
+ * optional preamble extraction is enabled, the padding
+ * appears before the preamble, otherwise the padding
+ * precedes the layer 2 header.
+ *
+ * This structure contains basic dTSEC configuration and must be passed to
+ * fman_dtsec_init() function. A default set of configuration values can be
+ * obtained by calling fman_dtsec_defconfig().
+ */
+struct dtsec_cfg {
+ bool halfdup_on;
+ bool halfdup_alt_backoff_en;
+ bool halfdup_excess_defer;
+ bool halfdup_no_backoff;
+ bool halfdup_bp_no_backoff;
+ uint8_t halfdup_alt_backoff_val;
+ uint16_t halfdup_retransmit;
+ uint16_t halfdup_coll_window;
+ bool rx_drop_bcast;
+ bool rx_short_frm;
+ bool rx_len_check;
+ bool tx_pad_crc;
+ bool tx_crc;
+ bool rx_ctrl_acc;
+ unsigned short tx_pause_time;
+ unsigned short tbipa;
+ bool ptp_tsu_en;
+ bool ptp_exception_en;
+ bool rx_preamble;
+ bool tx_preamble;
+ unsigned char preamble_len;
+ unsigned char rx_prepend;
+ bool loopback;
+ bool rx_time_stamp_en;
+ bool tx_time_stamp_en;
+ bool rx_flow;
+ bool tx_flow;
+ bool rx_group_hash_exd;
+ bool rx_promisc;
+ uint8_t tbi_phy_addr;
+ uint16_t tx_pause_time_extd;
+ uint16_t maximum_frame;
+ uint32_t non_back_to_back_ipg1;
+ uint32_t non_back_to_back_ipg2;
+ uint32_t min_ifg_enforcement;
+ uint32_t back_to_back_ipg;
+ bool wake_on_lan;
+};
+
+
+/**
+ * fman_dtsec_defconfig() - Get default dTSEC configuration
+ * @cfg: pointer to configuration structure.
+ *
+ * Call this function to obtain a default set of configuration values for
+ * initializing dTSEC. The user can overwrite any of the values before calling
+ * fman_dtsec_init(), if specific configuration needs to be applied.
+ */
+void fman_dtsec_defconfig(struct dtsec_cfg *cfg);
+
+/**
+ * fman_dtsec_init() - Init dTSEC hardware block
+ * @regs: Pointer to dTSEC register block
+ * @cfg: dTSEC configuration data
+ * @iface_mode: dTSEC interface mode, the type of MAC - PHY interface.
+ * @iface_speed: 1G or 10G
+ * @macaddr: MAC station address to be assigned to the device
+ * @fm_rev_maj: major rev number
+ * @fm_rev_min: minor rev number
+ * @exceptions_mask: initial exceptions mask
+ *
+ * This function initializes dTSEC and applies basic configuration.
+ *
+ * dTSEC initialization sequence:
+ * Before enabling Rx/Tx call dtsec_set_address() to set MAC address,
+ * fman_dtsec_adjust_link() to configure interface speed and duplex and finally
+ * dtsec_enable_tx()/dtsec_enable_rx() to start transmission and reception.
+ *
+ * Returns: 0 if successful, an error code otherwise.
+ */
+int fman_dtsec_init(struct dtsec_regs *regs, struct dtsec_cfg *cfg,
+ enum enet_interface iface_mode,
+ enum enet_speed iface_speed,
+ uint8_t *macaddr, uint8_t fm_rev_maj,
+ uint8_t fm_rev_min,
+ uint32_t exception_mask);
+
+/**
+ * fman_dtsec_enable() - Enable dTSEC Tx and Tx
+ * @regs: Pointer to dTSEC register block
+ * @apply_rx: enable rx side
+ * @apply_tx: enable tx side
+ *
+ * This function resets Tx and Rx graceful stop bit and enables dTSEC Tx and Rx.
+ */
+void fman_dtsec_enable(struct dtsec_regs *regs, bool apply_rx, bool apply_tx);
+
+/**
+ * fman_dtsec_disable() - Disable dTSEC Tx and Rx
+ * @regs: Pointer to dTSEC register block
+ * @apply_rx: disable rx side
+ * @apply_tx: disable tx side
+ *
+ * This function disables Tx and Rx in dTSEC.
+ */
+void fman_dtsec_disable(struct dtsec_regs *regs, bool apply_rx, bool apply_tx);
+
+/**
+ * fman_dtsec_get_revision() - Get dTSEC hardware revision
+ * @regs: Pointer to dTSEC register block
+ *
+ * Returns dtsec_id content
+ *
+ * Call this function to obtain the dTSEC hardware version.
+ */
+uint32_t fman_dtsec_get_revision(struct dtsec_regs *regs);
+
+/**
+ * fman_dtsec_set_mac_address() - Set MAC station address
+ * @regs: Pointer to dTSEC register block
+ * @macaddr: MAC address array
+ *
+ * This function sets MAC station address. To enable unicast reception call
+ * this after fman_dtsec_init(). While promiscuous mode is disabled dTSEC will
+ * match the destination address of received unicast frames against this
+ * address.
+ */
+void fman_dtsec_set_mac_address(struct dtsec_regs *regs, uint8_t *macaddr);
+
+/**
+ * fman_dtsec_get_mac_address() - Query MAC station address
+ * @regs: Pointer to dTSEC register block
+ * @macaddr: MAC address array
+ */
+void fman_dtsec_get_mac_address(struct dtsec_regs *regs, uint8_t *macaddr);
+
+/**
+ * fman_dtsec_set_uc_promisc() - Sets unicast promiscuous mode
+ * @regs: Pointer to dTSEC register block
+ * @enable: Enable unicast promiscuous mode
+ *
+ * Use this function to enable/disable dTSEC L2 address filtering. If the
+ * address filtering is disabled all unicast packets are accepted.
+ * To set dTSEC in promiscuous mode call both fman_dtsec_set_uc_promisc() and
+ * fman_dtsec_set_mc_promisc() to disable filtering for both unicast and
+ * multicast addresses.
+ */
+void fman_dtsec_set_uc_promisc(struct dtsec_regs *regs, bool enable);
+
+/**
+ * fman_dtsec_set_wol() - Enable/Disable wake on lan
+ * (magic packet support)
+ * @regs: Pointer to dTSEC register block
+ * @en: Enable Wake On Lan support in dTSEC
+ *
+ */
+void fman_dtsec_set_wol(struct dtsec_regs *regs, bool en);
+
+/**
+ * fman_dtsec_adjust_link() - Adjust dTSEC speed/duplex settings
+ * @regs: Pointer to dTSEC register block
+ * @iface_mode: dTSEC interface mode
+ * @speed: Link speed
+ * @full_dx: True for full-duplex, false for half-duplex.
+ *
+ * This function configures the MAC to function and the desired rates. Use it
+ * to configure dTSEC after fman_dtsec_init() and whenever the link speed
+ * changes (for instance following PHY auto-negociation).
+ *
+ * Returns: 0 if successful, an error code otherwise.
+ */
+int fman_dtsec_adjust_link(struct dtsec_regs *regs,
+ enum enet_interface iface_mode,
+ enum enet_speed speed, bool full_dx);
+
+/**
+ * fman_dtsec_set_tbi_phy_addr() - Updates TBI address field
+ * @regs: Pointer to dTSEC register block
+ * @address: Valid PHY address in the range of 1 to 31. 0 is reserved.
+ *
+ * In SGMII mode, the dTSEC's TBIPA field must contain a valid TBI PHY address
+ * so that the associated TBI PHY (i.e. the link) may be initialized.
+ *
+ * Returns: 0 if successful, an error code otherwise.
+ */
+int fman_dtsec_set_tbi_phy_addr(struct dtsec_regs *regs,
+ uint8_t addr);
+
+/**
+ * fman_dtsec_set_max_frame_len() - Set max frame length
+ * @regs: Pointer to dTSEC register block
+ * @length: Max frame length.
+ *
+ * Sets maximum frame length for received and transmitted frames. Frames that
+ * exceeds this length are truncated.
+ */
+void fman_dtsec_set_max_frame_len(struct dtsec_regs *regs, uint16_t length);
+
+/**
+ * fman_dtsec_get_max_frame_len() - Query max frame length
+ * @regs: Pointer to dTSEC register block
+ *
+ * Returns: the current value of the maximum frame length.
+ */
+uint16_t fman_dtsec_get_max_frame_len(struct dtsec_regs *regs);
+
+/**
+ * fman_dtsec_handle_rx_pause() - Configure pause frame handling
+ * @regs: Pointer to dTSEC register block
+ * @en: Enable pause frame handling in dTSEC
+ *
+ * If enabled, dTSEC will handle pause frames internally. This must be disabled
+ * if dTSEC is set in half-duplex mode.
+ * If pause frame handling is disabled and &dtsec_cfg.rx_ctrl_acc is set, pause
+ * frames will be transferred to the packet interface just like regular Ethernet
+ * frames.
+ */
+void fman_dtsec_handle_rx_pause(struct dtsec_regs *regs, bool en);
+
+/**
+ * fman_dtsec_set_tx_pause_frames() - Configure Tx pause time
+ * @regs: Pointer to dTSEC register block
+ * @time: Time value included in pause frames
+ *
+ * Call this function to set the time value used in transmitted pause frames.
+ * If time is 0, transmission of pause frames is disabled
+ */
+void fman_dtsec_set_tx_pause_frames(struct dtsec_regs *regs, uint16_t time);
+
+/**
+ * fman_dtsec_ack_event() - Acknowledge handled events
+ * @regs: Pointer to dTSEC register block
+ * @ev_mask: Events to acknowledge
+ *
+ * After handling events signaled by dTSEC in either polling or interrupt mode,
+ * call this function to reset the associated status bits in dTSEC event
+ * register.
+ */
+void fman_dtsec_ack_event(struct dtsec_regs *regs, uint32_t ev_mask);
+
+/**
+ * fman_dtsec_get_event() - Returns currently asserted events
+ * @regs: Pointer to dTSEC register block
+ * @ev_mask: Mask of relevant events
+ *
+ * Call this function to obtain a bit-mask of events that are currently asserted
+ * in dTSEC, taken from IEVENT register.
+ *
+ * Returns: a bit-mask of events asserted in dTSEC.
+ */
+uint32_t fman_dtsec_get_event(struct dtsec_regs *regs, uint32_t ev_mask);
+
+/**
+ * fman_dtsec_get_interrupt_mask() - Returns a bit-mask of enabled interrupts
+ * @regs: Pointer to dTSEC register block
+ *
+ * Call this function to obtain a bit-mask of enabled interrupts
+ * in dTSEC, taken from IMASK register.
+ *
+ * Returns: a bit-mask of enabled interrupts in dTSEC.
+ */
+uint32_t fman_dtsec_get_interrupt_mask(struct dtsec_regs *regs);
+
+void fman_dtsec_clear_addr_in_paddr(struct dtsec_regs *regs,
+ uint8_t paddr_num);
+
+void fman_dtsec_add_addr_in_paddr(struct dtsec_regs *regs,
+ uint64_t addr,
+ uint8_t paddr_num);
+
+void fman_dtsec_enable_tmr_interrupt (struct dtsec_regs *regs);
+
+void fman_dtsec_disable_tmr_interrupt(struct dtsec_regs *regs);
+
+/**
+ * fman_dtsec_disable_interrupt() - Disables interrupts for the specified events
+ * @regs: Pointer to dTSEC register block
+ * @ev_mask: Mask of relevant events
+ *
+ * Call this function to disable interrupts in dTSEC for the specified events.
+ * To enable interrupts use fman_dtsec_enable_interrupt().
+ */
+void fman_dtsec_disable_interrupt(struct dtsec_regs *regs, uint32_t ev_mask);
+
+/**
+ * fman_dtsec_enable_interrupt() - Enable interrupts for the specified events
+ * @regs: Pointer to dTSEC register block
+ * @ev_mask: Mask of relevant events
+ *
+ * Call this function to enable interrupts in dTSEC for the specified events.
+ * To disable interrupts use fman_dtsec_disable_interrupt().
+ */
+void fman_dtsec_enable_interrupt(struct dtsec_regs *regs, uint32_t ev_mask);
+
+/**
+ * fman_dtsec_set_ts() - Enables dTSEC timestamps
+ * @regs: Pointer to dTSEC register block
+ * @en: true to enable timestamps, false to disable them
+ *
+ * Call this function to enable/disable dTSEC timestamps. This affects both
+ * Tx and Rx.
+ */
+void fman_dtsec_set_ts(struct dtsec_regs *regs, bool en);
+
+/**
+ * fman_dtsec_set_bucket() - Enables/disables a filter bucket
+ * @regs: Pointer to dTSEC register block
+ * @bucket: Bucket index
+ * @enable: true/false to enable/disable this bucket
+ *
+ * This function enables or disables the specified bucket. Enabling a bucket
+ * associated with an address configures dTSEC to accept received packets
+ * with that destination address.
+ * Multiple addresses may be associated with the same bucket. Disabling a
+ * bucket will affect all addresses associated with that bucket. A bucket that
+ * is enabled requires further filtering and verification in the upper layers
+ *
+ */
+void fman_dtsec_set_bucket(struct dtsec_regs *regs, int bucket, bool enable);
+
+/**
+ * dtsec_set_hash_table() - insert a crc code into thr filter table
+ * @regs: Pointer to dTSEC register block
+ * @crc: crc to insert
+ * @mcast: true is this is a multicast address
+ * @ghtx: true if we are in ghtx mode
+ *
+ * This function inserts a crc code into the filter table.
+ */
+void fman_dtsec_set_hash_table(struct dtsec_regs *regs, uint32_t crc,
+ bool mcast, bool ghtx);
+
+/**
+ * fman_dtsec_reset_filter_table() - Resets the address filtering table
+ * @regs: Pointer to dTSEC register block
+ * @mcast: Reset multicast entries
+ * @ucast: Reset unicast entries
+ *
+ * Resets all entries in L2 address filter table. After calling this function
+ * all buckets enabled using fman_dtsec_set_bucket() will be disabled.
+ * If dtsec_init_filter_table() was called with @unicast_hash set to false,
+ * @ucast argument is ignored.
+ * This does not affect the primary nor the 15 additional addresses configured
+ * using dtsec_set_address() or dtsec_set_match_address().
+ */
+void fman_dtsec_reset_filter_table(struct dtsec_regs *regs, bool mcast,
+ bool ucast);
+
+/**
+ * fman_dtsec_set_mc_promisc() - Set multicast promiscuous mode
+ * @regs: Pointer to dTSEC register block
+ * @enable: Enable multicast promiscuous mode
+ *
+ * Call this to enable/disable L2 address filtering for multicast packets.
+ */
+void fman_dtsec_set_mc_promisc(struct dtsec_regs *regs, bool enable);
+
+/* statistics APIs */
+
+/**
+ * fman_dtsec_set_stat_level() - Enable a group of MIB statistics counters
+ * @regs: Pointer to dTSEC register block
+ * @level: Specifies a certain group of dTSEC MIB HW counters or _all_,
+ * to specify all the existing counters.
+ * If set to _none_, it disables all the counters.
+ *
+ * Enables the MIB statistics hw counters and sets up the carry interrupt
+ * masks for the counters corresponding to the @level input parameter.
+ *
+ * Returns: error if invalid @level value given.
+ */
+int fman_dtsec_set_stat_level(struct dtsec_regs *regs,
+ enum dtsec_stat_level level);
+
+/**
+ * fman_dtsec_reset_stat() - Completely resets all dTSEC HW counters
+ * @regs: Pointer to dTSEC register block
+ */
+void fman_dtsec_reset_stat(struct dtsec_regs *regs);
+
+/**
+ * fman_dtsec_get_clear_carry_regs() - Read and clear carry bits (CAR1-2 registers)
+ * @regs: Pointer to dTSEC register block
+ * @car1: car1 register value
+ * @car2: car2 register value
+ *
+ * When set, the carry bits signal that an overflow occurred on the
+ * corresponding counters.
+ * Note that the carry bits (CAR1-2 registers) will assert the
+ * %DTSEC_IEVENT_MSRO interrupt if unmasked (via CAM1-2 regs).
+ *
+ * Returns: true if overflow occurred, otherwise - false
+ */
+bool fman_dtsec_get_clear_carry_regs(struct dtsec_regs *regs,
+ uint32_t *car1, uint32_t *car2);
+
+uint32_t fman_dtsec_check_and_clear_tmr_event(struct dtsec_regs *regs);
+
+uint32_t fman_dtsec_get_stat_counter(struct dtsec_regs *regs,
+ enum dtsec_stat_counters reg_name);
+
+void fman_dtsec_start_tx(struct dtsec_regs *regs);
+void fman_dtsec_start_rx(struct dtsec_regs *regs);
+void fman_dtsec_stop_tx(struct dtsec_regs *regs);
+void fman_dtsec_stop_rx(struct dtsec_regs *regs);
+uint32_t fman_dtsec_get_rctrl(struct dtsec_regs *regs);
+
+
+#endif /* __FSL_FMAN_DTSEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_dtsec_mii_acc.h b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_dtsec_mii_acc.h
new file mode 100644
index 0000000..0dda09c
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_dtsec_mii_acc.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2008-2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FSL_FMAN_DTSEC_MII_ACC_H
+#define __FSL_FMAN_DTSEC_MII_ACC_H
+
+#include "common/general.h"
+
+
+/* MII Management Configuration Register */
+#define MIIMCFG_RESET_MGMT 0x80000000
+#define MIIMCFG_MGNTCLK_MASK 0x00000007
+#define MIIMCFG_MGNTCLK_SHIFT 0
+
+/* MII Management Command Register */
+#define MIIMCOM_SCAN_CYCLE 0x00000002
+#define MIIMCOM_READ_CYCLE 0x00000001
+
+/* MII Management Address Register */
+#define MIIMADD_PHY_ADDR_SHIFT 8
+#define MIIMADD_PHY_ADDR_MASK 0x00001f00
+
+#define MIIMADD_REG_ADDR_SHIFT 0
+#define MIIMADD_REG_ADDR_MASK 0x0000001f
+
+/* MII Management Indicator Register */
+#define MIIMIND_BUSY 0x00000001
+
+
+/* PHY Control Register */
+#define PHY_CR_PHY_RESET 0x8000
+#define PHY_CR_LOOPBACK 0x4000
+#define PHY_CR_SPEED0 0x2000
+#define PHY_CR_ANE 0x1000
+#define PHY_CR_RESET_AN 0x0200
+#define PHY_CR_FULLDUPLEX 0x0100
+#define PHY_CR_SPEED1 0x0040
+
+#define PHY_TBICON_SRESET 0x8000
+#define PHY_TBICON_SPEED2 0x0020
+#define PHY_TBICON_CLK_SEL 0x0020
+#define PHY_TBIANA_SGMII 0x4001
+#define PHY_TBIANA_1000X 0x01a0
+/* register map */
+
+/* MII Configuration Control Memory Map Registers */
+struct dtsec_mii_reg {
+ uint32_t reserved1[72];
+ uint32_t miimcfg; /* MII Mgmt:configuration */
+ uint32_t miimcom; /* MII Mgmt:command */
+ uint32_t miimadd; /* MII Mgmt:address */
+ uint32_t miimcon; /* MII Mgmt:control 3 */
+ uint32_t miimstat; /* MII Mgmt:status */
+ uint32_t miimind; /* MII Mgmt:indicators */
+};
+
+/* dTSEC MII API */
+
+/* functions to access the mii registers for phy configuration.
+ * this functionality may not be available for all dtsecs in the system.
+ * consult the reference manual for details */
+void fman_dtsec_mii_reset(struct dtsec_mii_reg *regs);
+/* frequency is in MHz.
+ * note that dtsec clock is 1/2 of fman clock */
+void fman_dtsec_mii_init(struct dtsec_mii_reg *regs, uint16_t dtsec_freq);
+int fman_dtsec_mii_write_reg(struct dtsec_mii_reg *regs,
+ uint8_t addr,
+ uint8_t reg,
+ uint16_t data,
+ uint16_t dtsec_freq);
+
+int fman_dtsec_mii_read_reg(struct dtsec_mii_reg *regs,
+ uint8_t addr,
+ uint8_t reg,
+ uint16_t *data,
+ uint16_t dtsec_freq);
+
+#endif /* __FSL_FMAN_DTSEC_MII_ACC_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_kg.h b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_kg.h
new file mode 100644
index 0000000..010e4b7
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_kg.h
@@ -0,0 +1,514 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FSL_FMAN_KG_H
+#define __FSL_FMAN_KG_H
+
+#include "common/general.h"
+
+#define FM_KG_NUM_OF_GENERIC_REGS 8 /**< Num of generic KeyGen regs */
+#define FMAN_MAX_NUM_OF_HW_PORTS 64
+/**< Total num of masks allowed on KG extractions */
+#define FM_KG_EXTRACT_MASKS_NUM 4
+#define FM_KG_NUM_CLS_PLAN_ENTR 8 /**< Num of class. plan regs */
+#define FM_KG_CLS_PLAN_GRPS_NUM 32 /**< Max num of class. groups */
+
+struct fman_kg_regs {
+ uint32_t fmkg_gcr;
+ uint32_t res004;
+ uint32_t res008;
+ uint32_t fmkg_eer;
+ uint32_t fmkg_eeer;
+ uint32_t res014;
+ uint32_t res018;
+ uint32_t fmkg_seer;
+ uint32_t fmkg_seeer;
+ uint32_t fmkg_gsr;
+ uint32_t fmkg_tpc;
+ uint32_t fmkg_serc;
+ uint32_t res030[4];
+ uint32_t fmkg_fdor;
+ uint32_t fmkg_gdv0r;
+ uint32_t fmkg_gdv1r;
+ uint32_t res04c[6];
+ uint32_t fmkg_feer;
+ uint32_t res068[38];
+ uint32_t fmkg_indirect[63];
+ uint32_t fmkg_ar;
+};
+
+struct fman_kg_scheme_regs {
+ uint32_t kgse_mode; /**< MODE */
+ uint32_t kgse_ekfc; /**< Extract Known Fields Command */
+ uint32_t kgse_ekdv; /**< Extract Known Default Value */
+ uint32_t kgse_bmch; /**< Bit Mask Command High */
+ uint32_t kgse_bmcl; /**< Bit Mask Command Low */
+ uint32_t kgse_fqb; /**< Frame Queue Base */
+ uint32_t kgse_hc; /**< Hash Command */
+ uint32_t kgse_ppc; /**< Policer Profile Command */
+ uint32_t kgse_gec[FM_KG_NUM_OF_GENERIC_REGS];
+ /**< Generic Extract Command */
+ uint32_t kgse_spc; /**< KeyGen Scheme Entry Statistic Packet Counter */
+ uint32_t kgse_dv0; /**< KeyGen Scheme Entry Default Value 0 */
+ uint32_t kgse_dv1; /**< KeyGen Scheme Entry Default Value 1 */
+ uint32_t kgse_ccbs; /**< KeyGen Scheme Entry Coarse Classification Bit*/
+ uint32_t kgse_mv; /**< KeyGen Scheme Entry Match vector */
+ uint32_t kgse_om; /**< KeyGen Scheme Entry Operation Mode bits */
+ uint32_t kgse_vsp; /**< KeyGen Scheme Entry Virtual Storage Profile */
+};
+
+struct fman_kg_pe_regs{
+ uint32_t fmkg_pe_sp;
+ uint32_t fmkg_pe_cpp;
+};
+
+struct fman_kg_cp_regs {
+ uint32_t kgcpe[FM_KG_NUM_CLS_PLAN_ENTR];
+};
+
+
+#define FM_KG_KGAR_GO 0x80000000
+#define FM_KG_KGAR_READ 0x40000000
+#define FM_KG_KGAR_WRITE 0x00000000
+#define FM_KG_KGAR_SEL_SCHEME_ENTRY 0x00000000
+#define FM_KG_KGAR_SCM_WSEL_UPDATE_CNT 0x00008000
+
+#define KG_SCH_PP_SHIFT_HIGH 0x80000000
+#define KG_SCH_PP_NO_GEN 0x10000000
+#define KG_SCH_PP_SHIFT_LOW 0x0000F000
+#define KG_SCH_MODE_NIA_PLCR 0x40000000
+#define KG_SCH_GEN_EXTRACT_TYPE 0x00008000
+#define KG_SCH_BITMASK_MASK 0x000000FF
+#define KG_SCH_GEN_VALID 0x80000000
+#define KG_SCH_GEN_MASK 0x00FF0000
+#define FM_PCD_KG_KGAR_ERR 0x20000000
+#define FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY 0x01000000
+#define FM_PCD_KG_KGAR_SEL_PORT_ENTRY 0x02000000
+#define FM_PCD_KG_KGAR_SEL_PORT_WSEL_SP 0x00008000
+#define FM_PCD_KG_KGAR_SEL_PORT_WSEL_CPP 0x00004000
+#define FM_PCD_KG_KGAR_WSEL_MASK 0x0000FF00
+#define KG_SCH_HASH_CONFIG_NO_FQID 0x80000000
+#define KG_SCH_HASH_CONFIG_SYM 0x40000000
+
+#define FM_EX_KG_DOUBLE_ECC 0x80000000
+#define FM_EX_KG_KEYSIZE_OVERFLOW 0x40000000
+
+/* ECC capture register */
+#define KG_FMKG_SERC_CAP 0x80000000
+#define KG_FMKG_SERC_CET 0x40000000
+#define KG_FMKG_SERC_CNT_MSK 0x00FF0000
+#define KG_FMKG_SERC_CNT_SHIFT 16
+#define KG_FMKG_SERC_ADDR_MSK 0x000003FF
+
+/* Masks */
+#define FM_KG_KGGCR_EN 0x80000000
+#define KG_SCH_GEN_VALID 0x80000000
+#define KG_SCH_GEN_EXTRACT_TYPE 0x00008000
+#define KG_ERR_TYPE_DOUBLE 0x40000000
+#define KG_ERR_ADDR_MASK 0x00000FFF
+#define KG_SCH_MODE_EN 0x80000000
+
+/* shifts */
+#define FM_KG_KGAR_NUM_SHIFT 16
+#define FM_KG_PE_CPP_MASK_SHIFT 16
+#define FM_KG_KGAR_WSEL_SHIFT 8
+
+#define FM_KG_SCH_GEN_HT_INVALID 0
+
+#define FM_KG_MASK_SEL_GEN_BASE 0x20
+
+#define KG_GET_MASK_SEL_SHIFT(shift, i) \
+switch (i) \
+{ \
+ case 0: (shift) = 26; break; \
+ case 1: (shift) = 20; break; \
+ case 2: (shift) = 10; break; \
+ case 3: (shift) = 4; break; \
+ default: (shift) = 0; \
+}
+
+#define KG_GET_MASK_OFFSET_SHIFT(shift, i) \
+switch (i) \
+{ \
+ case 0: (shift) = 16; break; \
+ case 1: (shift) = 0; break; \
+ case 2: (shift) = 28; break; \
+ case 3: (shift) = 24; break; \
+ default: (shift) = 0; \
+}
+
+#define KG_GET_MASK_SHIFT(shift, i) \
+switch (i) \
+{ \
+ case 0: shift = 24; break; \
+ case 1: shift = 16; break; \
+ case 2: shift = 8; break; \
+ case 3: shift = 0; break; \
+ default: shift = 0; \
+}
+
+/* Port entry CPP register */
+#define FMAN_KG_PE_CPP_MASK_SHIFT 16
+
+/* Scheme registers */
+#define FMAN_KG_SCH_MODE_EN 0x80000000
+#define FMAN_KG_SCH_MODE_NIA_PLCR 0x40000000
+#define FMAN_KG_SCH_MODE_CCOBASE_SHIFT 24
+
+#define FMAN_KG_SCH_DEF_MAC_ADDR_SHIFT 30
+#define FMAN_KG_SCH_DEF_VLAN_TCI_SHIFT 28
+#define FMAN_KG_SCH_DEF_ETYPE_SHIFT 26
+#define FMAN_KG_SCH_DEF_PPP_SID_SHIFT 24
+#define FMAN_KG_SCH_DEF_PPP_PID_SHIFT 22
+#define FMAN_KG_SCH_DEF_MPLS_SHIFT 20
+#define FMAN_KG_SCH_DEF_IP_ADDR_SHIFT 18
+#define FMAN_KG_SCH_DEF_PTYPE_SHIFT 16
+#define FMAN_KG_SCH_DEF_IP_TOS_TC_SHIFT 14
+#define FMAN_KG_SCH_DEF_IPv6_FL_SHIFT 12
+#define FMAN_KG_SCH_DEF_IPSEC_SPI_SHIFT 10
+#define FMAN_KG_SCH_DEF_L4_PORT_SHIFT 8
+#define FMAN_KG_SCH_DEF_TCP_FLG_SHIFT 6
+
+#define FMAN_KG_SCH_GEN_VALID 0x80000000
+#define FMAN_KG_SCH_GEN_SIZE_MAX 16
+#define FMAN_KG_SCH_GEN_OR 0x00008000
+
+#define FMAN_KG_SCH_GEN_DEF_SHIFT 29
+#define FMAN_KG_SCH_GEN_SIZE_SHIFT 24
+#define FMAN_KG_SCH_GEN_MASK_SHIFT 16
+#define FMAN_KG_SCH_GEN_HT_SHIFT 8
+
+#define FMAN_KG_SCH_HASH_HSHIFT_SHIFT 24
+#define FMAN_KG_SCH_HASH_HSHIFT_MAX 0x28
+#define FMAN_KG_SCH_HASH_SYM 0x40000000
+#define FMAN_KG_SCH_HASH_NO_FQID_GEN 0x80000000
+
+#define FMAN_KG_SCH_PP_SH_SHIFT 27
+#define FMAN_KG_SCH_PP_SL_SHIFT 12
+#define FMAN_KG_SCH_PP_SH_MASK 0x80000000
+#define FMAN_KG_SCH_PP_SL_MASK 0x0000F000
+#define FMAN_KG_SCH_PP_SHIFT_MAX 0x17
+#define FMAN_KG_SCH_PP_MASK_SHIFT 16
+#define FMAN_KG_SCH_PP_NO_GEN 0x10000000
+
+enum fman_kg_gen_extract_src {
+ E_FMAN_KG_GEN_EXTRACT_ETH,
+ E_FMAN_KG_GEN_EXTRACT_ETYPE,
+ E_FMAN_KG_GEN_EXTRACT_SNAP,
+ E_FMAN_KG_GEN_EXTRACT_VLAN_TCI_1,
+ E_FMAN_KG_GEN_EXTRACT_VLAN_TCI_N,
+ E_FMAN_KG_GEN_EXTRACT_PPPoE,
+ E_FMAN_KG_GEN_EXTRACT_MPLS_1,
+ E_FMAN_KG_GEN_EXTRACT_MPLS_2,
+ E_FMAN_KG_GEN_EXTRACT_MPLS_3,
+ E_FMAN_KG_GEN_EXTRACT_MPLS_N,
+ E_FMAN_KG_GEN_EXTRACT_IPv4_1,
+ E_FMAN_KG_GEN_EXTRACT_IPv6_1,
+ E_FMAN_KG_GEN_EXTRACT_IPv4_2,
+ E_FMAN_KG_GEN_EXTRACT_IPv6_2,
+ E_FMAN_KG_GEN_EXTRACT_MINENCAP,
+ E_FMAN_KG_GEN_EXTRACT_IP_PID,
+ E_FMAN_KG_GEN_EXTRACT_GRE,
+ E_FMAN_KG_GEN_EXTRACT_TCP,
+ E_FMAN_KG_GEN_EXTRACT_UDP,
+ E_FMAN_KG_GEN_EXTRACT_SCTP,
+ E_FMAN_KG_GEN_EXTRACT_DCCP,
+ E_FMAN_KG_GEN_EXTRACT_IPSEC_AH,
+ E_FMAN_KG_GEN_EXTRACT_IPSEC_ESP,
+ E_FMAN_KG_GEN_EXTRACT_SHIM_1,
+ E_FMAN_KG_GEN_EXTRACT_SHIM_2,
+ E_FMAN_KG_GEN_EXTRACT_FROM_DFLT,
+ E_FMAN_KG_GEN_EXTRACT_FROM_FRAME_START,
+ E_FMAN_KG_GEN_EXTRACT_FROM_PARSE_RESULT,
+ E_FMAN_KG_GEN_EXTRACT_FROM_END_OF_PARSE,
+ E_FMAN_KG_GEN_EXTRACT_FROM_FQID
+};
+
+struct fman_kg_ex_ecc_attr
+{
+ bool valid;
+ bool double_ecc;
+ uint16_t addr;
+ uint8_t single_ecc_count;
+};
+
+enum fman_kg_def_select
+{
+ E_FMAN_KG_DEF_GLOBAL_0,
+ E_FMAN_KG_DEF_GLOBAL_1,
+ E_FMAN_KG_DEF_SCHEME_0,
+ E_FMAN_KG_DEF_SCHEME_1
+};
+
+struct fman_kg_extract_def
+{
+ enum fman_kg_def_select mac_addr;
+ enum fman_kg_def_select vlan_tci;
+ enum fman_kg_def_select etype;
+ enum fman_kg_def_select ppp_sid;
+ enum fman_kg_def_select ppp_pid;
+ enum fman_kg_def_select mpls;
+ enum fman_kg_def_select ip_addr;
+ enum fman_kg_def_select ptype;
+ enum fman_kg_def_select ip_tos_tc;
+ enum fman_kg_def_select ipv6_fl;
+ enum fman_kg_def_select ipsec_spi;
+ enum fman_kg_def_select l4_port;
+ enum fman_kg_def_select tcp_flg;
+};
+
+enum fman_kg_gen_extract_type
+{
+ E_FMAN_KG_HASH_EXTRACT,
+ E_FMAN_KG_OR_EXTRACT
+};
+
+struct fman_kg_gen_extract_params
+{
+ /* Hash or Or-ed extract */
+ enum fman_kg_gen_extract_type type;
+ enum fman_kg_gen_extract_src src;
+ bool no_validation;
+ /* Extraction offset from the header location specified above */
+ uint8_t offset;
+ /* Size of extraction for FMAN_KG_HASH_EXTRACT,
+ * hash result shift for FMAN_KG_OR_EXTRACT */
+ uint8_t extract;
+ uint8_t mask;
+ /* Default value to use when header specified
+ * by fman_kg_gen_extract_src doesn't present */
+ enum fman_kg_def_select def_val;
+};
+
+struct fman_kg_extract_mask
+{
+ /**< Indication if mask is on known field extraction or
+ * on general extraction; TRUE for known field */
+ bool is_known;
+ /**< One of FMAN_KG_EXTRACT_xxx defines for known fields mask and
+ * generic register index for generic extracts mask */
+ uint32_t field_or_gen_idx;
+ /**< Byte offset from start of the extracted data specified
+ * by field_or_gen_idx */
+ uint8_t offset;
+ /**< Byte mask (selected bits will be used) */
+ uint8_t mask;
+};
+
+struct fman_kg_extract_params
+{
+ /* Or-ed mask of FMAN_KG_EXTRACT_xxx defines */
+ uint32_t known_fields;
+ struct fman_kg_extract_def known_fields_def;
+ /* Number of entries in gen_extract */
+ uint8_t gen_extract_num;
+ struct fman_kg_gen_extract_params gen_extract[FM_KG_NUM_OF_GENERIC_REGS];
+ /* Number of entries in masks */
+ uint8_t masks_num;
+ struct fman_kg_extract_mask masks[FM_KG_EXTRACT_MASKS_NUM];
+ uint32_t def_scheme_0;
+ uint32_t def_scheme_1;
+};
+
+struct fman_kg_hash_params
+{
+ bool use_hash;
+ uint8_t shift_r;
+ uint32_t mask; /**< 24-bit mask */
+ bool sym; /**< Symmetric hash for src and dest pairs */
+};
+
+struct fman_kg_pp_params
+{
+ uint8_t base;
+ uint8_t shift;
+ uint8_t mask;
+ bool bypass_pp_gen;
+};
+
+struct fman_kg_cc_params
+{
+ uint8_t base_offset;
+ uint32_t qlcv_bits_sel;
+};
+
+enum fman_pcd_engine
+{
+ E_FMAN_PCD_INVALID = 0, /**< Invalid PCD engine indicated*/
+ E_FMAN_PCD_DONE, /**< No PCD Engine indicated */
+ E_FMAN_PCD_KG, /**< Keygen indicated */
+ E_FMAN_PCD_CC, /**< Coarse classification indicated */
+ E_FMAN_PCD_PLCR, /**< Policer indicated */
+ E_FMAN_PCD_PRS /**< Parser indicated */
+};
+
+struct fman_kg_cls_plan_params
+{
+ uint8_t entries_mask;
+ uint32_t mask_vector[FM_KG_NUM_CLS_PLAN_ENTR];
+};
+
+struct fman_kg_scheme_params
+{
+ uint32_t match_vector;
+ struct fman_kg_extract_params extract_params;
+ struct fman_kg_hash_params hash_params;
+ uint32_t base_fqid;
+ /* What we do w/features supported per FM version ?? */
+ bool bypass_fqid_gen;
+ struct fman_kg_pp_params policer_params;
+ struct fman_kg_cc_params cc_params;
+ bool update_counter;
+ /**< counter_value: Set scheme counter to the specified value;
+ * relevant only when update_counter = TRUE. */
+ uint32_t counter_value;
+ enum fman_pcd_engine next_engine;
+ /**< Next engine action code */
+ uint32_t next_engine_action;
+};
+
+
+
+int fman_kg_write_ar_wait(struct fman_kg_regs *regs, uint32_t fmkg_ar);
+void fman_kg_write_sp(struct fman_kg_regs *regs, uint32_t sp, bool add);
+void fman_kg_write_cpp(struct fman_kg_regs *regs, uint32_t cpp);
+void fman_kg_get_event(struct fman_kg_regs *regs,
+ uint32_t *event,
+ uint32_t *scheme_idx);
+void fman_kg_init(struct fman_kg_regs *regs,
+ uint32_t exceptions,
+ uint32_t dflt_nia);
+void fman_kg_enable_scheme_interrupts(struct fman_kg_regs *regs);
+void fman_kg_enable(struct fman_kg_regs *regs);
+void fman_kg_disable(struct fman_kg_regs *regs);
+int fman_kg_write_bind_cls_plans(struct fman_kg_regs *regs,
+ uint8_t hwport_id,
+ uint32_t bind_cls_plans);
+int fman_kg_build_bind_cls_plans(uint8_t grp_base,
+ uint8_t grp_mask,
+ uint32_t *bind_cls_plans);
+int fman_kg_write_bind_schemes(struct fman_kg_regs *regs,
+ uint8_t hwport_id,
+ uint32_t schemes);
+int fman_kg_write_cls_plan(struct fman_kg_regs *regs,
+ uint8_t grp_id,
+ uint8_t entries_mask,
+ uint8_t hwport_id,
+ struct fman_kg_cp_regs *cls_plan_regs);
+int fman_kg_build_cls_plan(struct fman_kg_cls_plan_params *params,
+ struct fman_kg_cp_regs *cls_plan_regs);
+uint32_t fman_kg_get_schemes_total_counter(struct fman_kg_regs *regs);
+int fman_kg_set_scheme_counter(struct fman_kg_regs *regs,
+ uint8_t scheme_id,
+ uint8_t hwport_id,
+ uint32_t counter);
+int fman_kg_get_scheme_counter(struct fman_kg_regs *regs,
+ uint8_t scheme_id,
+ uint8_t hwport_id,
+ uint32_t *counter);
+int fman_kg_delete_scheme(struct fman_kg_regs *regs,
+ uint8_t scheme_id,
+ uint8_t hwport_id);
+int fman_kg_write_scheme(struct fman_kg_regs *regs,
+ uint8_t scheme_id,
+ uint8_t hwport_id,
+ struct fman_kg_scheme_regs *scheme_regs,
+ bool update_counter);
+int fman_kg_build_scheme(struct fman_kg_scheme_params *params,
+ struct fman_kg_scheme_regs *scheme_regs);
+void fman_kg_get_capture(struct fman_kg_regs *regs,
+ struct fman_kg_ex_ecc_attr *ecc_attr,
+ bool clear);
+void fman_kg_get_exception(struct fman_kg_regs *regs,
+ uint32_t *events,
+ uint32_t *scheme_ids,
+ bool clear);
+void fman_kg_set_exception(struct fman_kg_regs *regs,
+ uint32_t exception,
+ bool enable);
+void fman_kg_set_dflt_val(struct fman_kg_regs *regs,
+ uint8_t def_id,
+ uint32_t val);
+void fman_kg_set_data_after_prs(struct fman_kg_regs *regs, uint8_t offset);
+
+
+
+/**************************************************************************//**
+ @Description NIA Description
+*//***************************************************************************/
+#define KG_NIA_ORDER_RESTOR 0x00800000
+#define KG_NIA_ENG_FM_CTL 0x00000000
+#define KG_NIA_ENG_PRS 0x00440000
+#define KG_NIA_ENG_KG 0x00480000
+#define KG_NIA_ENG_PLCR 0x004C0000
+#define KG_NIA_ENG_BMI 0x00500000
+#define KG_NIA_ENG_QMI_ENQ 0x00540000
+#define KG_NIA_ENG_QMI_DEQ 0x00580000
+#define KG_NIA_ENG_MASK 0x007C0000
+
+#define KG_NIA_AC_MASK 0x0003FFFF
+
+#define KG_NIA_INVALID 0xFFFFFFFF
+
+static __inline__ uint32_t fm_kg_build_nia(enum fman_pcd_engine next_engine,
+ uint32_t next_engine_action)
+{
+ uint32_t nia;
+
+ if (next_engine_action & ~KG_NIA_AC_MASK)
+ return KG_NIA_INVALID;
+
+ switch (next_engine) {
+ case E_FMAN_PCD_DONE:
+ nia = KG_NIA_ENG_BMI | next_engine_action;
+ break;
+
+ case E_FMAN_PCD_KG:
+ nia = KG_NIA_ENG_KG | next_engine_action;
+ break;
+
+ case E_FMAN_PCD_CC:
+ nia = KG_NIA_ENG_FM_CTL | next_engine_action;
+ break;
+
+ case E_FMAN_PCD_PLCR:
+ nia = KG_NIA_ENG_PLCR | next_engine_action;
+ break;
+
+ default:
+ nia = KG_NIA_INVALID;
+ }
+
+ return nia;
+}
+
+#endif /* __FSL_FMAN_KG_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_memac.h b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_memac.h
new file mode 100644
index 0000000..2d2e795
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_memac.h
@@ -0,0 +1,425 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __FSL_FMAN_MEMAC_H
+#define __FSL_FMAN_MEMAC_H
+
+#include "common/general.h"
+#include "fsl_enet.h"
+
+
+#define MEMAC_NUM_OF_PADDRS 7 /* Num of additional exact match MAC adr regs */
+
+/* Control and Configuration Register (COMMAND_CONFIG) */
+#define CMD_CFG_MG 0x80000000 /* 00 Magic Packet detection */
+#define CMD_CFG_REG_LOWP_RXETY 0x01000000 /* 07 Rx low power indication */
+#define CMD_CFG_TX_LOWP_ENA 0x00800000 /* 08 Tx Low Power Idle Enable */
+#define CMD_CFG_SFD_ANY 0x00200000 /* 10 Disable SFD check */
+#define CMD_CFG_PFC_MODE 0x00080000 /* 12 Enable PFC */
+#define CMD_CFG_NO_LEN_CHK 0x00020000 /* 14 Payload length check disable */
+#define CMD_CFG_SEND_IDLE 0x00010000 /* 15 Force idle generation */
+#define CMD_CFG_CNT_FRM_EN 0x00002000 /* 18 Control frame rx enable */
+#define CMD_CFG_SW_RESET 0x00001000 /* 19 S/W Reset, self clearing bit */
+#define CMD_CFG_TX_PAD_EN 0x00000800 /* 20 Enable Tx padding of frames */
+#define CMD_CFG_LOOPBACK_EN 0x00000400 /* 21 XGMII/GMII loopback enable */
+#define CMD_CFG_TX_ADDR_INS 0x00000200 /* 22 Tx source MAC addr insertion */
+#define CMD_CFG_PAUSE_IGNORE 0x00000100 /* 23 Ignore Pause frame quanta */
+#define CMD_CFG_PAUSE_FWD 0x00000080 /* 24 Terminate/frwd Pause frames */
+#define CMD_CFG_CRC_FWD 0x00000040 /* 25 Terminate/frwd CRC of frames */
+#define CMD_CFG_PAD_EN 0x00000020 /* 26 Frame padding removal */
+#define CMD_CFG_PROMIS_EN 0x00000010 /* 27 Promiscuous operation enable */
+#define CMD_CFG_WAN_MODE 0x00000008 /* 28 WAN mode enable */
+#define CMD_CFG_RX_EN 0x00000002 /* 30 MAC receive path enable */
+#define CMD_CFG_TX_EN 0x00000001 /* 31 MAC transmit path enable */
+
+/* Transmit FIFO Sections Register (TX_FIFO_SECTIONS) */
+#define TX_FIFO_SECTIONS_TX_EMPTY_MASK 0xFFFF0000
+#define TX_FIFO_SECTIONS_TX_AVAIL_MASK 0x0000FFFF
+#define TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G 0x00400000
+#define TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G 0x00100000
+#define TX_FIFO_SECTIONS_TX_EMPTY_PFC_10G 0x00360000
+#define TX_FIFO_SECTIONS_TX_EMPTY_PFC_1G 0x00040000
+#define TX_FIFO_SECTIONS_TX_AVAIL_10G 0x00000019
+#define TX_FIFO_SECTIONS_TX_AVAIL_1G 0x00000020
+
+#define GET_TX_EMPTY_DEFAULT_VALUE(_val) \
+_val &= ~TX_FIFO_SECTIONS_TX_EMPTY_MASK; \
+((_val == TX_FIFO_SECTIONS_TX_AVAIL_10G) ? \
+ (_val |= TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G) : \
+ (_val |= TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G));
+
+#define GET_TX_EMPTY_PFC_VALUE(_val) \
+_val &= ~TX_FIFO_SECTIONS_TX_EMPTY_MASK; \
+((_val == TX_FIFO_SECTIONS_TX_AVAIL_10G) ? \
+ (_val |= TX_FIFO_SECTIONS_TX_EMPTY_PFC_10G) : \
+ (_val |= TX_FIFO_SECTIONS_TX_EMPTY_PFC_1G));
+
+/* Interface Mode Register (IF_MODE) */
+#define IF_MODE_MASK 0x00000003 /* 30-31 Mask on i/f mode bits */
+#define IF_MODE_XGMII 0x00000000 /* 30-31 XGMII (10G) interface */
+#define IF_MODE_GMII 0x00000002 /* 30-31 GMII (1G) interface */
+#define IF_MODE_RGMII 0x00000004
+#define IF_MODE_RGMII_AUTO 0x00008000
+#define IF_MODE_RGMII_1000 0x00004000 /* 10 - 1000Mbps RGMII */
+#define IF_MODE_RGMII_100 0x00000000 /* 00 - 100Mbps RGMII */
+#define IF_MODE_RGMII_10 0x00002000 /* 01 - 10Mbps RGMII */
+#define IF_MODE_RGMII_SP_MASK 0x00006000 /* Setsp mask bits */
+#define IF_MODE_RGMII_FD 0x00001000 /* Full duplex RGMII */
+#define IF_MODE_HD 0x00000040 /* Half duplex operation */
+
+/* Hash table Control Register (HASHTABLE_CTRL) */
+#define HASH_CTRL_MCAST_SHIFT 26
+#define HASH_CTRL_MCAST_EN 0x00000100 /* 23 Mcast frame rx for hash */
+#define HASH_CTRL_ADDR_MASK 0x0000003F /* 26-31 Hash table address code */
+
+#define GROUP_ADDRESS 0x0000010000000000LL /* MAC mcast indication */
+#define HASH_TABLE_SIZE 64 /* Hash tbl size */
+
+/* Transmit Inter-Packet Gap Length Register (TX_IPG_LENGTH) */
+#define MEMAC_TX_IPG_LENGTH_MASK 0x0000003F
+
+/* Statistics Configuration Register (STATN_CONFIG) */
+#define STATS_CFG_CLR 0x00000004 /* 29 Reset all counters */
+#define STATS_CFG_CLR_ON_RD 0x00000002 /* 30 Clear on read */
+#define STATS_CFG_SATURATE 0x00000001 /* 31 Saturate at the maximum val */
+
+/* Interrupt Mask Register (IMASK) */
+#define MEMAC_IMASK_MGI 0x40000000 /* 1 Magic pkt detect indication */
+#define MEMAC_IMASK_TSECC_ER 0x20000000 /* 2 Timestamp FIFO ECC error evnt */
+#define MEMAC_IMASK_TECC_ER 0x02000000 /* 6 Transmit frame ECC error evnt */
+#define MEMAC_IMASK_RECC_ER 0x01000000 /* 7 Receive frame ECC error evnt */
+
+#define MEMAC_ALL_ERRS_IMASK \
+ ((uint32_t)(MEMAC_IMASK_TSECC_ER | \
+ MEMAC_IMASK_TECC_ER | \
+ MEMAC_IMASK_RECC_ER | \
+ MEMAC_IMASK_MGI))
+
+#define MEMAC_IEVNT_PCS 0x80000000 /* PCS (XG). Link sync (G) */
+#define MEMAC_IEVNT_AN 0x40000000 /* Auto-negotiation */
+#define MEMAC_IEVNT_LT 0x20000000 /* Link Training/New page */
+#define MEMAC_IEVNT_MGI 0x00004000 /* Magic pkt detection */
+#define MEMAC_IEVNT_TS_ECC_ER 0x00002000 /* Timestamp FIFO ECC error */
+#define MEMAC_IEVNT_RX_FIFO_OVFL 0x00001000 /* Rx FIFO overflow */
+#define MEMAC_IEVNT_TX_FIFO_UNFL 0x00000800 /* Tx FIFO underflow */
+#define MEMAC_IEVNT_TX_FIFO_OVFL 0x00000400 /* Tx FIFO overflow */
+#define MEMAC_IEVNT_TX_ECC_ER 0x00000200 /* Tx frame ECC error */
+#define MEMAC_IEVNT_RX_ECC_ER 0x00000100 /* Rx frame ECC error */
+#define MEMAC_IEVNT_LI_FAULT 0x00000080 /* Link Interruption flt */
+#define MEMAC_IEVNT_RX_EMPTY 0x00000040 /* Rx FIFO empty */
+#define MEMAC_IEVNT_TX_EMPTY 0x00000020 /* Tx FIFO empty */
+#define MEMAC_IEVNT_RX_LOWP 0x00000010 /* Low Power Idle */
+#define MEMAC_IEVNT_PHY_LOS 0x00000004 /* Phy loss of signal */
+#define MEMAC_IEVNT_REM_FAULT 0x00000002 /* Remote fault (XGMII) */
+#define MEMAC_IEVNT_LOC_FAULT 0x00000001 /* Local fault (XGMII) */
+
+enum memac_counters {
+ E_MEMAC_COUNTER_R64,
+ E_MEMAC_COUNTER_R127,
+ E_MEMAC_COUNTER_R255,
+ E_MEMAC_COUNTER_R511,
+ E_MEMAC_COUNTER_R1023,
+ E_MEMAC_COUNTER_R1518,
+ E_MEMAC_COUNTER_R1519X,
+ E_MEMAC_COUNTER_RFRG,
+ E_MEMAC_COUNTER_RJBR,
+ E_MEMAC_COUNTER_RDRP,
+ E_MEMAC_COUNTER_RALN,
+ E_MEMAC_COUNTER_TUND,
+ E_MEMAC_COUNTER_ROVR,
+ E_MEMAC_COUNTER_RXPF,
+ E_MEMAC_COUNTER_TXPF,
+ E_MEMAC_COUNTER_ROCT,
+ E_MEMAC_COUNTER_RMCA,
+ E_MEMAC_COUNTER_RBCA,
+ E_MEMAC_COUNTER_RPKT,
+ E_MEMAC_COUNTER_RUCA,
+ E_MEMAC_COUNTER_RERR,
+ E_MEMAC_COUNTER_TOCT,
+ E_MEMAC_COUNTER_TMCA,
+ E_MEMAC_COUNTER_TBCA,
+ E_MEMAC_COUNTER_TUCA,
+ E_MEMAC_COUNTER_TERR
+};
+
+#define DEFAULT_PAUSE_QUANTA 0xf000
+#define DEFAULT_FRAME_LENGTH 0x600
+#define DEFAULT_TX_IPG_LENGTH 12
+
+/*
+ * memory map
+ */
+
+struct mac_addr {
+ uint32_t mac_addr_l; /* Lower 32 bits of 48-bit MAC address */
+ uint32_t mac_addr_u; /* Upper 16 bits of 48-bit MAC address */
+};
+
+struct memac_regs {
+ /* General Control and Status */
+ uint32_t res0000[2];
+ uint32_t command_config; /* 0x008 Ctrl and cfg */
+ struct mac_addr mac_addr0; /* 0x00C-0x010 MAC_ADDR_0...1 */
+ uint32_t maxfrm; /* 0x014 Max frame length */
+ uint32_t res0018[1];
+ uint32_t rx_fifo_sections; /* Receive FIFO configuration reg */
+ uint32_t tx_fifo_sections; /* Transmit FIFO configuration reg */
+ uint32_t res0024[2];
+ uint32_t hashtable_ctrl; /* 0x02C Hash table control */
+ uint32_t res0030[4];
+ uint32_t ievent; /* 0x040 Interrupt event */
+ uint32_t tx_ipg_length; /* 0x044 Transmitter inter-packet-gap */
+ uint32_t res0048;
+ uint32_t imask; /* 0x04C Interrupt mask */
+ uint32_t res0050;
+ uint32_t pause_quanta[4]; /* 0x054 Pause quanta */
+ uint32_t pause_thresh[4]; /* 0x064 Pause quanta threshold */
+ uint32_t rx_pause_status; /* 0x074 Receive pause status */
+ uint32_t res0078[2];
+ struct mac_addr mac_addr[MEMAC_NUM_OF_PADDRS]; /* 0x80-0x0B4 mac padr */
+ uint32_t lpwake_timer; /* 0x0B8 Low Power Wakeup Timer */
+ uint32_t sleep_timer; /* 0x0BC Transmit EEE Low Power Timer */
+ uint32_t res00c0[8];
+ uint32_t statn_config; /* 0x0E0 Statistics configuration */
+ uint32_t res00e4[7];
+ /* Rx Statistics Counter */
+ uint32_t reoct_l;
+ uint32_t reoct_u;
+ uint32_t roct_l;
+ uint32_t roct_u;
+ uint32_t raln_l;
+ uint32_t raln_u;
+ uint32_t rxpf_l;
+ uint32_t rxpf_u;
+ uint32_t rfrm_l;
+ uint32_t rfrm_u;
+ uint32_t rfcs_l;
+ uint32_t rfcs_u;
+ uint32_t rvlan_l;
+ uint32_t rvlan_u;
+ uint32_t rerr_l;
+ uint32_t rerr_u;
+ uint32_t ruca_l;
+ uint32_t ruca_u;
+ uint32_t rmca_l;
+ uint32_t rmca_u;
+ uint32_t rbca_l;
+ uint32_t rbca_u;
+ uint32_t rdrp_l;
+ uint32_t rdrp_u;
+ uint32_t rpkt_l;
+ uint32_t rpkt_u;
+ uint32_t rund_l;
+ uint32_t rund_u;
+ uint32_t r64_l;
+ uint32_t r64_u;
+ uint32_t r127_l;
+ uint32_t r127_u;
+ uint32_t r255_l;
+ uint32_t r255_u;
+ uint32_t r511_l;
+ uint32_t r511_u;
+ uint32_t r1023_l;
+ uint32_t r1023_u;
+ uint32_t r1518_l;
+ uint32_t r1518_u;
+ uint32_t r1519x_l;
+ uint32_t r1519x_u;
+ uint32_t rovr_l;
+ uint32_t rovr_u;
+ uint32_t rjbr_l;
+ uint32_t rjbr_u;
+ uint32_t rfrg_l;
+ uint32_t rfrg_u;
+ uint32_t rcnp_l;
+ uint32_t rcnp_u;
+ uint32_t rdrntp_l;
+ uint32_t rdrntp_u;
+ uint32_t res01d0[12];
+ /* Tx Statistics Counter */
+ uint32_t teoct_l;
+ uint32_t teoct_u;
+ uint32_t toct_l;
+ uint32_t toct_u;
+ uint32_t res0210[2];
+ uint32_t txpf_l;
+ uint32_t txpf_u;
+ uint32_t tfrm_l;
+ uint32_t tfrm_u;
+ uint32_t tfcs_l;
+ uint32_t tfcs_u;
+ uint32_t tvlan_l;
+ uint32_t tvlan_u;
+ uint32_t terr_l;
+ uint32_t terr_u;
+ uint32_t tuca_l;
+ uint32_t tuca_u;
+ uint32_t tmca_l;
+ uint32_t tmca_u;
+ uint32_t tbca_l;
+ uint32_t tbca_u;
+ uint32_t res0258[2];
+ uint32_t tpkt_l;
+ uint32_t tpkt_u;
+ uint32_t tund_l;
+ uint32_t tund_u;
+ uint32_t t64_l;
+ uint32_t t64_u;
+ uint32_t t127_l;
+ uint32_t t127_u;
+ uint32_t t255_l;
+ uint32_t t255_u;
+ uint32_t t511_l;
+ uint32_t t511_u;
+ uint32_t t1023_l;
+ uint32_t t1023_u;
+ uint32_t t1518_l;
+ uint32_t t1518_u;
+ uint32_t t1519x_l;
+ uint32_t t1519x_u;
+ uint32_t res02a8[6];
+ uint32_t tcnp_l;
+ uint32_t tcnp_u;
+ uint32_t res02c8[14];
+ /* Line Interface Control */
+ uint32_t if_mode; /* 0x300 Interface Mode Control */
+ uint32_t if_status; /* 0x304 Interface Status */
+ uint32_t res0308[14];
+ /* HiGig/2 */
+ uint32_t hg_config; /* 0x340 Control and cfg */
+ uint32_t res0344[3];
+ uint32_t hg_pause_quanta; /* 0x350 Pause quanta */
+ uint32_t res0354[3];
+ uint32_t hg_pause_thresh; /* 0x360 Pause quanta threshold */
+ uint32_t res0364[3];
+ uint32_t hgrx_pause_status; /* 0x370 Receive pause status */
+ uint32_t hg_fifos_status; /* 0x374 fifos status */
+ uint32_t rhm; /* 0x378 rx messages counter */
+ uint32_t thm; /* 0x37C tx messages counter */
+};
+
+struct memac_cfg {
+ bool reset_on_init;
+ bool rx_error_discard;
+ bool pause_ignore;
+ bool pause_forward_enable;
+ bool no_length_check_enable;
+ bool cmd_frame_enable;
+ bool send_idle_enable;
+ bool wan_mode_enable;
+ bool promiscuous_mode_enable;
+ bool tx_addr_ins_enable;
+ bool loopback_enable;
+ bool lgth_check_nostdr;
+ bool time_stamp_enable;
+ bool pad_enable;
+ bool phy_tx_ena_on;
+ bool rx_sfd_any;
+ bool rx_pbl_fwd;
+ bool tx_pbl_fwd;
+ bool debug_mode;
+ bool wake_on_lan;
+ uint16_t max_frame_length;
+ uint16_t pause_quanta;
+ uint32_t tx_ipg_length;
+};
+
+
+/**
+ * fman_memac_defconfig() - Get default MEMAC configuration
+ * @cfg: pointer to configuration structure.
+ *
+ * Call this function to obtain a default set of configuration values for
+ * initializing MEMAC. The user can overwrite any of the values before calling
+ * fman_memac_init(), if specific configuration needs to be applied.
+ */
+void fman_memac_defconfig(struct memac_cfg *cfg);
+
+int fman_memac_init(struct memac_regs *regs,
+ struct memac_cfg *cfg,
+ enum enet_interface enet_interface,
+ enum enet_speed enet_speed,
+ uint32_t exceptions);
+
+void fman_memac_enable(struct memac_regs *regs, bool apply_rx, bool apply_tx);
+
+void fman_memac_disable(struct memac_regs *regs, bool apply_rx, bool apply_tx);
+
+void fman_memac_set_promiscuous(struct memac_regs *regs, bool val);
+
+void fman_memac_add_addr_in_paddr(struct memac_regs *regs,
+ uint8_t *adr,
+ uint8_t paddr_num);
+
+void fman_memac_clear_addr_in_paddr(struct memac_regs *regs,
+ uint8_t paddr_num);
+
+uint64_t fman_memac_get_counter(struct memac_regs *regs,
+ enum memac_counters reg_name);
+
+void fman_memac_set_tx_pause_frames(struct memac_regs *regs,
+ uint8_t priority, uint16_t pauseTime, uint16_t threshTime);
+
+uint16_t fman_memac_get_max_frame_len(struct memac_regs *regs);
+
+void fman_memac_set_exception(struct memac_regs *regs, uint32_t val,
+ bool enable);
+
+void fman_memac_reset_stat(struct memac_regs *regs);
+
+void fman_memac_reset(struct memac_regs *regs);
+
+void fman_memac_reset_filter_table(struct memac_regs *regs);
+
+void fman_memac_set_hash_table_entry(struct memac_regs *regs, uint32_t crc);
+
+void fman_memac_set_hash_table(struct memac_regs *regs, uint32_t val);
+
+void fman_memac_set_rx_ignore_pause_frames(struct memac_regs *regs,
+ bool enable);
+
+void fman_memac_set_wol(struct memac_regs *regs, bool enable);
+
+uint32_t fman_memac_get_event(struct memac_regs *regs, uint32_t ev_mask);
+
+void fman_memac_ack_event(struct memac_regs *regs, uint32_t ev_mask);
+
+uint32_t fman_memac_get_interrupt_mask(struct memac_regs *regs);
+
+void fman_memac_adjust_link(struct memac_regs *regs,
+ enum enet_interface iface_mode,
+ enum enet_speed speed, bool full_dx);
+
+
+
+#endif /*__FSL_FMAN_MEMAC_H*/
diff --git a/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_memac_mii_acc.h b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_memac_mii_acc.h
new file mode 100755
index 0000000..b430445
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_memac_mii_acc.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2008-2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FSL_FMAN_MEMAC_MII_ACC_H
+#define __FSL_FMAN_MEMAC_MII_ACC_H
+
+#include "common/general.h"
+#include "fsl_enet.h"
+/* MII Management Registers */
+#define MDIO_CFG_CLK_DIV_MASK 0x0080ff80
+#define MDIO_CFG_CLK_DIV_SHIFT 7
+#define MDIO_CFG_HOLD_MASK 0x0000001c
+#define MDIO_CFG_ENC45 0x00000040
+#define MDIO_CFG_READ_ERR 0x00000002
+#define MDIO_CFG_BSY 0x00000001
+
+#define MDIO_CTL_PHY_ADDR_SHIFT 5
+#define MDIO_CTL_READ 0x00008000
+
+#define MDIO_DATA_BSY 0x80000000
+
+/*MEMAC Internal PHY Registers - SGMII */
+#define PHY_SGMII_CR_PHY_RESET 0x8000
+#define PHY_SGMII_CR_RESET_AN 0x0200
+#define PHY_SGMII_CR_DEF_VAL 0x1140
+#define PHY_SGMII_DEV_ABILITY_SGMII 0x4001
+#define PHY_SGMII_DEV_ABILITY_1000X 0x01A0
+#define PHY_SGMII_IF_MODE_AN 0x0002
+#define PHY_SGMII_IF_MODE_SGMII 0x0001
+#define PHY_SGMII_IF_MODE_1000X 0x0000
+
+/*----------------------------------------------------*/
+/* MII Configuration Control Memory Map Registers */
+/*----------------------------------------------------*/
+struct memac_mii_access_mem_map {
+ uint32_t mdio_cfg; /* 0x030 */
+ uint32_t mdio_ctrl; /* 0x034 */
+ uint32_t mdio_data; /* 0x038 */
+ uint32_t mdio_addr; /* 0x03c */
+};
+
+int fman_memac_mii_read_phy_reg(struct memac_mii_access_mem_map *mii_regs,
+ uint8_t phy_addr, uint8_t reg, uint16_t *data,
+ enum enet_speed enet_speed);
+int fman_memac_mii_write_phy_reg(struct memac_mii_access_mem_map *mii_regs,
+ uint8_t phy_addr, uint8_t reg, uint16_t data,
+ enum enet_speed enet_speed);
+
+#endif /* __MAC_API_MEMAC_MII_ACC_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_port.h b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_port.h
new file mode 100755
index 0000000..292d37d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_port.h
@@ -0,0 +1,594 @@
+/*
+ * Copyright 2008-2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FSL_FMAN_PORT_H
+#define __FSL_FMAN_PORT_H
+
+#include "fsl_fman_sp.h"
+
+/** @Collection Registers bit fields */
+
+/** @Description BMI defines */
+#define BMI_EBD_EN 0x80000000
+
+#define BMI_PORT_CFG_EN 0x80000000
+#define BMI_PORT_CFG_FDOVR 0x02000000
+#define BMI_PORT_CFG_IM 0x01000000
+
+#define BMI_PORT_STATUS_BSY 0x80000000
+
+#define BMI_DMA_ATTR_SWP_SHIFT FMAN_SP_DMA_ATTR_SWP_SHIFT
+#define BMI_DMA_ATTR_IC_STASH_ON 0x10000000
+#define BMI_DMA_ATTR_HDR_STASH_ON 0x04000000
+#define BMI_DMA_ATTR_SG_STASH_ON 0x01000000
+#define BMI_DMA_ATTR_WRITE_OPTIMIZE FMAN_SP_DMA_ATTR_WRITE_OPTIMIZE
+
+#define BMI_RX_FIFO_PRI_ELEVATION_SHIFT 16
+#define BMI_RX_FIFO_THRESHOLD_ETHE 0x80000000
+
+#define BMI_TX_FRAME_END_CS_IGNORE_SHIFT 24
+#define BMI_RX_FRAME_END_CS_IGNORE_SHIFT 24
+#define BMI_RX_FRAME_END_CUT_SHIFT 16
+
+#define BMI_IC_TO_EXT_SHIFT FMAN_SP_IC_TO_EXT_SHIFT
+#define BMI_IC_FROM_INT_SHIFT FMAN_SP_IC_FROM_INT_SHIFT
+
+#define BMI_INT_BUF_MARG_SHIFT 28
+#define BMI_EXT_BUF_MARG_START_SHIFT FMAN_SP_EXT_BUF_MARG_START_SHIFT
+
+#define BMI_CMD_MR_LEAC 0x00200000
+#define BMI_CMD_MR_SLEAC 0x00100000
+#define BMI_CMD_MR_MA 0x00080000
+#define BMI_CMD_MR_DEAS 0x00040000
+#define BMI_CMD_RX_MR_DEF (BMI_CMD_MR_LEAC | \
+ BMI_CMD_MR_SLEAC | \
+ BMI_CMD_MR_MA | \
+ BMI_CMD_MR_DEAS)
+#define BMI_CMD_TX_MR_DEF 0
+#define BMI_CMD_OP_MR_DEF (BMI_CMD_MR_DEAS | \
+ BMI_CMD_MR_MA)
+
+#define BMI_CMD_ATTR_ORDER 0x80000000
+#define BMI_CMD_ATTR_SYNC 0x02000000
+#define BMI_CMD_ATTR_COLOR_SHIFT 26
+
+#define BMI_FIFO_PIPELINE_DEPTH_SHIFT 12
+#define BMI_NEXT_ENG_FD_BITS_SHIFT 24
+#define BMI_FRAME_END_CS_IGNORE_SHIFT 24
+
+#define BMI_COUNTERS_EN 0x80000000
+
+#define BMI_EXT_BUF_POOL_VALID FMAN_SP_EXT_BUF_POOL_VALID
+#define BMI_EXT_BUF_POOL_EN_COUNTER FMAN_SP_EXT_BUF_POOL_EN_COUNTER
+#define BMI_EXT_BUF_POOL_BACKUP FMAN_SP_EXT_BUF_POOL_BACKUP
+#define BMI_EXT_BUF_POOL_ID_SHIFT 16
+#define BMI_EXT_BUF_POOL_ID_MASK 0x003F0000
+#define BMI_POOL_DEP_NUM_OF_POOLS_SHIFT 16
+
+#define BMI_TX_FIFO_MIN_FILL_SHIFT 16
+#define BMI_TX_FIFO_PIPELINE_DEPTH_SHIFT 12
+
+#define MAX_PERFORMANCE_TASK_COMP 64
+#define MAX_PERFORMANCE_RX_QUEUE_COMP 64
+#define MAX_PERFORMANCE_TX_QUEUE_COMP 8
+#define MAX_PERFORMANCE_DMA_COMP 16
+#define MAX_PERFORMANCE_FIFO_COMP 1024
+
+#define BMI_PERFORMANCE_TASK_COMP_SHIFT 24
+#define BMI_PERFORMANCE_QUEUE_COMP_SHIFT 16
+#define BMI_PERFORMANCE_DMA_COMP_SHIFT 12
+
+#define BMI_RATE_LIMIT_GRAN_TX 16000 /* In Kbps */
+#define BMI_RATE_LIMIT_GRAN_OP 10000 /* In frames */
+#define BMI_RATE_LIMIT_MAX_RATE_IN_GRAN_UNITS 1024
+#define BMI_RATE_LIMIT_MAX_BURST_SIZE 1024 /* In KBytes */
+#define BMI_RATE_LIMIT_MAX_BURST_SHIFT 16
+#define BMI_RATE_LIMIT_HIGH_BURST_SIZE_GRAN 0x80000000
+#define BMI_RATE_LIMIT_SCALE_TSBS_SHIFT 16
+#define BMI_RATE_LIMIT_SCALE_EN 0x80000000
+#define BMI_SG_DISABLE FMAN_SP_SG_DISABLE
+
+/** @Description QMI defines */
+#define QMI_PORT_CFG_EN 0x80000000
+#define QMI_PORT_CFG_EN_COUNTERS 0x10000000
+
+#define QMI_PORT_STATUS_DEQ_TNUM_BSY 0x80000000
+#define QMI_PORT_STATUS_DEQ_FD_BSY 0x20000000
+
+#define QMI_DEQ_CFG_PRI 0x80000000
+#define QMI_DEQ_CFG_TYPE1 0x10000000
+#define QMI_DEQ_CFG_TYPE2 0x20000000
+#define QMI_DEQ_CFG_TYPE3 0x30000000
+#define QMI_DEQ_CFG_PREFETCH_PARTIAL 0x01000000
+#define QMI_DEQ_CFG_PREFETCH_FULL 0x03000000
+#define QMI_DEQ_CFG_SP_MASK 0xf
+#define QMI_DEQ_CFG_SP_SHIFT 20
+
+
+/** @Description General port defines */
+#define FMAN_PORT_EXT_POOLS_NUM(fm_rev_maj) \
+ (((fm_rev_maj) == 4) ? 4 : 8)
+#define FMAN_PORT_MAX_EXT_POOLS_NUM 8
+#define FMAN_PORT_OBS_EXT_POOLS_NUM 2
+#define FMAN_PORT_CG_MAP_NUM 8
+#define FMAN_PORT_PRS_RESULT_WORDS_NUM 8
+#define FMAN_PORT_BMI_FIFO_UNITS 0x100
+#define FMAN_PORT_IC_OFFSET_UNITS 0x10
+
+
+/** @Collection FM Port Register Map */
+
+/** @Description BMI Rx port register map */
+struct fman_port_rx_bmi_regs {
+ uint32_t fmbm_rcfg; /**< Rx Configuration */
+ uint32_t fmbm_rst; /**< Rx Status */
+ uint32_t fmbm_rda; /**< Rx DMA attributes*/
+ uint32_t fmbm_rfp; /**< Rx FIFO Parameters*/
+ uint32_t fmbm_rfed; /**< Rx Frame End Data*/
+ uint32_t fmbm_ricp; /**< Rx Internal Context Parameters*/
+ uint32_t fmbm_rim; /**< Rx Internal Buffer Margins*/
+ uint32_t fmbm_rebm; /**< Rx External Buffer Margins*/
+ uint32_t fmbm_rfne; /**< Rx Frame Next Engine*/
+ uint32_t fmbm_rfca; /**< Rx Frame Command Attributes.*/
+ uint32_t fmbm_rfpne; /**< Rx Frame Parser Next Engine*/
+ uint32_t fmbm_rpso; /**< Rx Parse Start Offset*/
+ uint32_t fmbm_rpp; /**< Rx Policer Profile */
+ uint32_t fmbm_rccb; /**< Rx Coarse Classification Base */
+ uint32_t fmbm_reth; /**< Rx Excessive Threshold */
+ uint32_t reserved003c[1]; /**< (0x03C 0x03F) */
+ uint32_t fmbm_rprai[FMAN_PORT_PRS_RESULT_WORDS_NUM];
+ /**< Rx Parse Results Array Init*/
+ uint32_t fmbm_rfqid; /**< Rx Frame Queue ID*/
+ uint32_t fmbm_refqid; /**< Rx Error Frame Queue ID*/
+ uint32_t fmbm_rfsdm; /**< Rx Frame Status Discard Mask*/
+ uint32_t fmbm_rfsem; /**< Rx Frame Status Error Mask*/
+ uint32_t fmbm_rfene; /**< Rx Frame Enqueue Next Engine */
+ uint32_t reserved0074[0x2]; /**< (0x074-0x07C) */
+ uint32_t fmbm_rcmne; /**< Rx Frame Continuous Mode Next Engine */
+ uint32_t reserved0080[0x20];/**< (0x080 0x0FF) */
+ uint32_t fmbm_ebmpi[FMAN_PORT_MAX_EXT_POOLS_NUM];
+ /**< Buffer Manager pool Information-*/
+ uint32_t fmbm_acnt[FMAN_PORT_MAX_EXT_POOLS_NUM];
+ /**< Allocate Counter-*/
+ uint32_t reserved0130[8];
+ /**< 0x130/0x140 - 0x15F reserved -*/
+ uint32_t fmbm_rcgm[FMAN_PORT_CG_MAP_NUM];
+ /**< Congestion Group Map*/
+ uint32_t fmbm_mpd; /**< BM Pool Depletion */
+ uint32_t reserved0184[0x1F]; /**< (0x184 0x1FF) */
+ uint32_t fmbm_rstc; /**< Rx Statistics Counters*/
+ uint32_t fmbm_rfrc; /**< Rx Frame Counter*/
+ uint32_t fmbm_rfbc; /**< Rx Bad Frames Counter*/
+ uint32_t fmbm_rlfc; /**< Rx Large Frames Counter*/
+ uint32_t fmbm_rffc; /**< Rx Filter Frames Counter*/
+ uint32_t fmbm_rfdc; /**< Rx Frame Discard Counter*/
+ uint32_t fmbm_rfldec; /**< Rx Frames List DMA Error Counter*/
+ uint32_t fmbm_rodc; /**< Rx Out of Buffers Discard nntr*/
+ uint32_t fmbm_rbdc; /**< Rx Buffers Deallocate Counter*/
+ uint32_t reserved0224[0x17]; /**< (0x224 0x27F) */
+ uint32_t fmbm_rpc; /**< Rx Performance Counters*/
+ uint32_t fmbm_rpcp; /**< Rx Performance Count Parameters*/
+ uint32_t fmbm_rccn; /**< Rx Cycle Counter*/
+ uint32_t fmbm_rtuc; /**< Rx Tasks Utilization Counter*/
+ uint32_t fmbm_rrquc; /**< Rx Receive Queue Utilization cntr*/
+ uint32_t fmbm_rduc; /**< Rx DMA Utilization Counter*/
+ uint32_t fmbm_rfuc; /**< Rx FIFO Utilization Counter*/
+ uint32_t fmbm_rpac; /**< Rx Pause Activation Counter*/
+ uint32_t reserved02a0[0x18]; /**< (0x2A0 0x2FF) */
+ uint32_t fmbm_rdbg; /**< Rx Debug-*/
+};
+
+/** @Description BMI Tx port register map */
+struct fman_port_tx_bmi_regs {
+ uint32_t fmbm_tcfg; /**< Tx Configuration */
+ uint32_t fmbm_tst; /**< Tx Status */
+ uint32_t fmbm_tda; /**< Tx DMA attributes */
+ uint32_t fmbm_tfp; /**< Tx FIFO Parameters */
+ uint32_t fmbm_tfed; /**< Tx Frame End Data */
+ uint32_t fmbm_ticp; /**< Tx Internal Context Parameters */
+ uint32_t fmbm_tfdne; /**< Tx Frame Dequeue Next Engine. */
+ uint32_t fmbm_tfca; /**< Tx Frame Command attribute. */
+ uint32_t fmbm_tcfqid; /**< Tx Confirmation Frame Queue ID. */
+ uint32_t fmbm_tefqid; /**< Tx Frame Error Queue ID */
+ uint32_t fmbm_tfene; /**< Tx Frame Enqueue Next Engine */
+ uint32_t fmbm_trlmts; /**< Tx Rate Limiter Scale */
+ uint32_t fmbm_trlmt; /**< Tx Rate Limiter */
+ uint32_t reserved0034[0x0e]; /**< (0x034-0x6c) */
+ uint32_t fmbm_tccb; /**< Tx Coarse Classification base */
+ uint32_t fmbm_tfne; /**< Tx Frame Next Engine */
+ uint32_t fmbm_tpfcm[0x02]; /**< Tx Priority based Flow Control (PFC) Mapping */
+ uint32_t fmbm_tcmne; /**< Tx Frame Continuous Mode Next Engine */
+ uint32_t reserved0080[0x60]; /**< (0x080-0x200) */
+ uint32_t fmbm_tstc; /**< Tx Statistics Counters */
+ uint32_t fmbm_tfrc; /**< Tx Frame Counter */
+ uint32_t fmbm_tfdc; /**< Tx Frames Discard Counter */
+ uint32_t fmbm_tfledc; /**< Tx Frame len error discard cntr */
+ uint32_t fmbm_tfufdc; /**< Tx Frame unsprt frmt discard cntr*/
+ uint32_t fmbm_tbdc; /**< Tx Buffers Deallocate Counter */
+ uint32_t reserved0218[0x1A]; /**< (0x218-0x280) */
+ uint32_t fmbm_tpc; /**< Tx Performance Counters*/
+ uint32_t fmbm_tpcp; /**< Tx Performance Count Parameters*/
+ uint32_t fmbm_tccn; /**< Tx Cycle Counter*/
+ uint32_t fmbm_ttuc; /**< Tx Tasks Utilization Counter*/
+ uint32_t fmbm_ttcquc; /**< Tx Transmit conf Q util Counter*/
+ uint32_t fmbm_tduc; /**< Tx DMA Utilization Counter*/
+ uint32_t fmbm_tfuc; /**< Tx FIFO Utilization Counter*/
+};
+
+/** @Description BMI O/H port register map */
+struct fman_port_oh_bmi_regs {
+ uint32_t fmbm_ocfg; /**< O/H Configuration */
+ uint32_t fmbm_ost; /**< O/H Status */
+ uint32_t fmbm_oda; /**< O/H DMA attributes */
+ uint32_t fmbm_oicp; /**< O/H Internal Context Parameters */
+ uint32_t fmbm_ofdne; /**< O/H Frame Dequeue Next Engine */
+ uint32_t fmbm_ofne; /**< O/H Frame Next Engine */
+ uint32_t fmbm_ofca; /**< O/H Frame Command Attributes. */
+ uint32_t fmbm_ofpne; /**< O/H Frame Parser Next Engine */
+ uint32_t fmbm_opso; /**< O/H Parse Start Offset */
+ uint32_t fmbm_opp; /**< O/H Policer Profile */
+ uint32_t fmbm_occb; /**< O/H Coarse Classification base */
+ uint32_t fmbm_oim; /**< O/H Internal margins*/
+ uint32_t fmbm_ofp; /**< O/H Fifo Parameters*/
+ uint32_t fmbm_ofed; /**< O/H Frame End Data*/
+ uint32_t reserved0030[2]; /**< (0x038 - 0x03F) */
+ uint32_t fmbm_oprai[FMAN_PORT_PRS_RESULT_WORDS_NUM];
+ /**< O/H Parse Results Array Initialization */
+ uint32_t fmbm_ofqid; /**< O/H Frame Queue ID */
+ uint32_t fmbm_oefqid; /**< O/H Error Frame Queue ID */
+ uint32_t fmbm_ofsdm; /**< O/H Frame Status Discard Mask */
+ uint32_t fmbm_ofsem; /**< O/H Frame Status Error Mask */
+ uint32_t fmbm_ofene; /**< O/H Frame Enqueue Next Engine */
+ uint32_t fmbm_orlmts; /**< O/H Rate Limiter Scale */
+ uint32_t fmbm_orlmt; /**< O/H Rate Limiter */
+ uint32_t fmbm_ocmne; /**< O/H Continuous Mode Next Engine */
+ uint32_t reserved0080[0x20]; /**< 0x080 - 0x0FF Reserved */
+ uint32_t fmbm_oebmpi[2]; /**< Buf Mngr Observed Pool Info */
+ uint32_t reserved0108[0x16]; /**< 0x108 - 0x15F Reserved */
+ uint32_t fmbm_ocgm; /**< Observed Congestion Group Map */
+ uint32_t reserved0164[0x7]; /**< 0x164 - 0x17F Reserved */
+ uint32_t fmbm_ompd; /**< Observed BMan Pool Depletion */
+ uint32_t reserved0184[0x1F]; /**< 0x184 - 0x1FF Reserved */
+ uint32_t fmbm_ostc; /**< O/H Statistics Counters */
+ uint32_t fmbm_ofrc; /**< O/H Frame Counter */
+ uint32_t fmbm_ofdc; /**< O/H Frames Discard Counter */
+ uint32_t fmbm_ofledc; /**< O/H Frames Len Err Discard Cntr */
+ uint32_t fmbm_ofufdc; /**< O/H Frames Unsprtd Discard Cutr */
+ uint32_t fmbm_offc; /**< O/H Filter Frames Counter */
+ uint32_t fmbm_ofwdc; /**< Rx Frames WRED Discard Counter */
+ uint32_t fmbm_ofldec; /**< O/H Frames List DMA Error Cntr */
+ uint32_t fmbm_obdc; /**< O/H Buffers Deallocate Counter */
+ uint32_t reserved0218[0x17]; /**< (0x218 - 0x27F) */
+ uint32_t fmbm_opc; /**< O/H Performance Counters */
+ uint32_t fmbm_opcp; /**< O/H Performance Count Parameters */
+ uint32_t fmbm_occn; /**< O/H Cycle Counter */
+ uint32_t fmbm_otuc; /**< O/H Tasks Utilization Counter */
+ uint32_t fmbm_oduc; /**< O/H DMA Utilization Counter */
+ uint32_t fmbm_ofuc; /**< O/H FIFO Utilization Counter */
+};
+
+/** @Description BMI port register map */
+union fman_port_bmi_regs {
+ struct fman_port_rx_bmi_regs rx;
+ struct fman_port_tx_bmi_regs tx;
+ struct fman_port_oh_bmi_regs oh;
+};
+
+/** @Description QMI port register map */
+struct fman_port_qmi_regs {
+ uint32_t fmqm_pnc; /**< PortID n Configuration Register */
+ uint32_t fmqm_pns; /**< PortID n Status Register */
+ uint32_t fmqm_pnts; /**< PortID n Task Status Register */
+ uint32_t reserved00c[4]; /**< 0xn00C - 0xn01B */
+ uint32_t fmqm_pnen; /**< PortID n Enqueue NIA Register */
+ uint32_t fmqm_pnetfc; /**< PortID n Enq Total Frame Counter */
+ uint32_t reserved024[2]; /**< 0xn024 - 0x02B */
+ uint32_t fmqm_pndn; /**< PortID n Dequeue NIA Register */
+ uint32_t fmqm_pndc; /**< PortID n Dequeue Config Register */
+ uint32_t fmqm_pndtfc; /**< PortID n Dequeue tot Frame cntr */
+ uint32_t fmqm_pndfdc; /**< PortID n Dequeue FQID Dflt Cntr */
+ uint32_t fmqm_pndcc; /**< PortID n Dequeue Confirm Counter */
+};
+
+
+enum fman_port_dma_swap {
+ E_FMAN_PORT_DMA_NO_SWAP, /**< No swap, transfer data as is */
+ E_FMAN_PORT_DMA_SWAP_LE,
+ /**< The transferred data should be swapped in PPC Little Endian mode */
+ E_FMAN_PORT_DMA_SWAP_BE
+ /**< The transferred data should be swapped in Big Endian mode */
+};
+
+/* Default port color */
+enum fman_port_color {
+ E_FMAN_PORT_COLOR_GREEN, /**< Default port color is green */
+ E_FMAN_PORT_COLOR_YELLOW, /**< Default port color is yellow */
+ E_FMAN_PORT_COLOR_RED, /**< Default port color is red */
+ E_FMAN_PORT_COLOR_OVERRIDE /**< Ignore color */
+};
+
+/* QMI dequeue from the SP channel - types */
+enum fman_port_deq_type {
+ E_FMAN_PORT_DEQ_BY_PRI,
+ /**< Priority precedence and Intra-Class scheduling */
+ E_FMAN_PORT_DEQ_ACTIVE_FQ,
+ /**< Active FQ precedence and Intra-Class scheduling */
+ E_FMAN_PORT_DEQ_ACTIVE_FQ_NO_ICS
+ /**< Active FQ precedence and override Intra-Class scheduling */
+};
+
+/* QMI dequeue prefetch modes */
+enum fman_port_deq_prefetch {
+ E_FMAN_PORT_DEQ_NO_PREFETCH, /**< No prefetch mode */
+ E_FMAN_PORT_DEQ_PART_PREFETCH, /**< Partial prefetch mode */
+ E_FMAN_PORT_DEQ_FULL_PREFETCH /**< Full prefetch mode */
+};
+
+/* Parameters for defining performance counters behavior */
+struct fman_port_perf_cnt_params {
+ uint8_t task_val; /**< Task compare value */
+ uint8_t queue_val;
+ /**< Rx or Tx conf queue compare value (unused for O/H ports) */
+ uint8_t dma_val; /**< Dma compare value */
+ uint32_t fifo_val; /**< Fifo compare value (in bytes) */
+};
+
+/** @Description FM Port configuration structure, used at init */
+struct fman_port_cfg {
+ struct fman_port_perf_cnt_params perf_cnt_params;
+ /* BMI parameters */
+ enum fman_port_dma_swap dma_swap_data;
+ bool dma_ic_stash_on;
+ bool dma_header_stash_on;
+ bool dma_sg_stash_on;
+ bool dma_write_optimize;
+ uint16_t ic_ext_offset;
+ uint8_t ic_int_offset;
+ uint16_t ic_size;
+ enum fman_port_color color;
+ bool sync_req;
+ bool discard_override;
+ uint8_t checksum_bytes_ignore;
+ uint8_t rx_cut_end_bytes;
+ uint32_t rx_pri_elevation;
+ uint32_t rx_fifo_thr;
+ uint8_t rx_fd_bits;
+ uint8_t int_buf_start_margin;
+ uint16_t ext_buf_start_margin;
+ uint16_t ext_buf_end_margin;
+ uint32_t tx_fifo_min_level;
+ uint32_t tx_fifo_low_comf_level;
+ uint8_t tx_fifo_deq_pipeline_depth;
+ bool stats_counters_enable;
+ bool perf_counters_enable;
+ /* QMI parameters */
+ bool deq_high_pri;
+ enum fman_port_deq_type deq_type;
+ enum fman_port_deq_prefetch deq_prefetch_opt;
+ uint16_t deq_byte_cnt;
+ bool queue_counters_enable;
+ bool no_scatter_gather;
+ int errata_A006675;
+ int errata_A006320;
+ int excessive_threshold_register;
+ int fmbm_rebm_has_sgd;
+ int fmbm_tfne_has_features;
+ int qmi_deq_options_support;
+};
+
+enum fman_port_type {
+ E_FMAN_PORT_TYPE_OP = 0,
+ /**< Offline parsing port, shares id-s with
+ * host command, so must have exclusive id-s */
+ E_FMAN_PORT_TYPE_RX, /**< 1G Rx port */
+ E_FMAN_PORT_TYPE_RX_10G, /**< 10G Rx port */
+ E_FMAN_PORT_TYPE_TX, /**< 1G Tx port */
+ E_FMAN_PORT_TYPE_TX_10G, /**< 10G Tx port */
+ E_FMAN_PORT_TYPE_DUMMY,
+ E_FMAN_PORT_TYPE_HC = E_FMAN_PORT_TYPE_DUMMY
+ /**< Host command port, shares id-s with
+ * offline parsing ports, so must have exclusive id-s */
+};
+
+struct fman_port_params {
+ uint32_t discard_mask;
+ uint32_t err_mask;
+ uint32_t dflt_fqid;
+ uint32_t err_fqid;
+ uint8_t deq_sp;
+ bool dont_release_buf;
+};
+
+/* Port context - used by most API functions */
+struct fman_port {
+ enum fman_port_type type;
+ uint8_t fm_rev_maj;
+ uint8_t fm_rev_min;
+ union fman_port_bmi_regs *bmi_regs;
+ struct fman_port_qmi_regs *qmi_regs;
+ bool im_en;
+ uint8_t ext_pools_num;
+};
+
+/** @Description External buffer pools configuration */
+struct fman_port_bpools {
+ uint8_t count; /**< Num of pools to set up */
+ bool counters_enable; /**< Enable allocate counters */
+ uint8_t grp_bp_depleted_num;
+ /**< Number of depleted pools - if reached the BMI indicates
+ * the MAC to send a pause frame */
+ struct {
+ uint8_t bpid; /**< BM pool ID */
+ uint16_t size;
+ /**< Pool's size - must be in ascending order */
+ bool is_backup;
+ /**< If this is a backup pool */
+ bool grp_bp_depleted;
+ /**< Consider this buffer in multiple pools depletion criteria*/
+ bool single_bp_depleted;
+ /**< Consider this buffer in single pool depletion criteria */
+ bool pfc_priorities_en;
+ } bpool[FMAN_PORT_MAX_EXT_POOLS_NUM];
+};
+
+enum fman_port_rate_limiter_scale_down {
+ E_FMAN_PORT_RATE_DOWN_NONE,
+ E_FMAN_PORT_RATE_DOWN_BY_2,
+ E_FMAN_PORT_RATE_DOWN_BY_4,
+ E_FMAN_PORT_RATE_DOWN_BY_8
+};
+
+/* Rate limiter configuration */
+struct fman_port_rate_limiter {
+ uint8_t count_1micro_bit;
+ bool high_burst_size_gran;
+ /**< Defines burst_size granularity for OP ports; when TRUE,
+ * burst_size below counts in frames, otherwise in 10^3 frames */
+ uint16_t burst_size;
+ /**< Max burst size, in KBytes for Tx port, according to
+ * high_burst_size_gran definition for OP port */
+ uint32_t rate;
+ /**< In Kbps for Tx port, in frames/sec for OP port */
+ enum fman_port_rate_limiter_scale_down rate_factor;
+};
+
+/* BMI statistics counters */
+enum fman_port_stats_counters {
+ E_FMAN_PORT_STATS_CNT_FRAME,
+ /**< Number of processed frames; valid for all ports */
+ E_FMAN_PORT_STATS_CNT_DISCARD,
+ /**< For Rx ports - frames discarded by QMAN, for Tx or O/H ports -
+ * frames discarded due to DMA error; valid for all ports */
+ E_FMAN_PORT_STATS_CNT_DEALLOC_BUF,
+ /**< Number of buffer deallocate operations; valid for all ports */
+ E_FMAN_PORT_STATS_CNT_RX_BAD_FRAME,
+ /**< Number of bad Rx frames, like CRC error, Rx FIFO overflow etc;
+ * valid for Rx ports only */
+ E_FMAN_PORT_STATS_CNT_RX_LARGE_FRAME,
+ /**< Number of Rx oversized frames, that is frames exceeding max frame
+ * size configured for the corresponding ETH controller;
+ * valid for Rx ports only */
+ E_FMAN_PORT_STATS_CNT_RX_OUT_OF_BUF,
+ /**< Frames discarded due to lack of external buffers; valid for
+ * Rx ports only */
+ E_FMAN_PORT_STATS_CNT_LEN_ERR,
+ /**< Frames discarded due to frame length error; valid for Tx and
+ * O/H ports only */
+ E_FMAN_PORT_STATS_CNT_UNSUPPORTED_FORMAT,
+ /**< Frames discarded due to unsupported FD format; valid for Tx
+ * and O/H ports only */
+ E_FMAN_PORT_STATS_CNT_FILTERED_FRAME,
+ /**< Number of frames filtered out by PCD module; valid for
+ * Rx and OP ports only */
+ E_FMAN_PORT_STATS_CNT_DMA_ERR,
+ /**< Frames rejected by QMAN that were not able to release their
+ * buffers due to DMA error; valid for Rx and O/H ports only */
+ E_FMAN_PORT_STATS_CNT_WRED_DISCARD
+ /**< Frames going through O/H port that were not able to to enter the
+ * return queue due to WRED algorithm; valid for O/H ports only */
+};
+
+/* BMI performance counters */
+enum fman_port_perf_counters {
+ E_FMAN_PORT_PERF_CNT_CYCLE, /**< Cycle counter */
+ E_FMAN_PORT_PERF_CNT_TASK_UTIL, /**< Tasks utilization counter */
+ E_FMAN_PORT_PERF_CNT_QUEUE_UTIL,
+ /**< For Rx ports - Rx queue utilization, for Tx ports - Tx conf queue
+ * utilization; not valid for O/H ports */
+ E_FMAN_PORT_PERF_CNT_DMA_UTIL, /**< DMA utilization counter */
+ E_FMAN_PORT_PERF_CNT_FIFO_UTIL, /**< FIFO utilization counter */
+ E_FMAN_PORT_PERF_CNT_RX_PAUSE
+ /**< Number of cycles in which Rx pause activation control is on;
+ * valid for Rx ports only */
+};
+
+/* QMI counters */
+enum fman_port_qmi_counters {
+ E_FMAN_PORT_ENQ_TOTAL, /**< EnQ tot frame cntr */
+ E_FMAN_PORT_DEQ_TOTAL, /**< DeQ tot frame cntr; invalid for Rx ports */
+ E_FMAN_PORT_DEQ_FROM_DFLT,
+ /**< Dequeue from default FQID counter not valid for Rx ports */
+ E_FMAN_PORT_DEQ_CONFIRM /**< DeQ confirm cntr invalid for Rx ports */
+};
+
+
+/** @Collection FM Port API */
+void fman_port_defconfig(struct fman_port_cfg *cfg, enum fman_port_type type);
+int fman_port_init(struct fman_port *port,
+ struct fman_port_cfg *cfg,
+ struct fman_port_params *params);
+int fman_port_enable(struct fman_port *port);
+int fman_port_disable(const struct fman_port *port);
+int fman_port_set_bpools(const struct fman_port *port,
+ const struct fman_port_bpools *bp);
+int fman_port_set_rate_limiter(struct fman_port *port,
+ struct fman_port_rate_limiter *rate_limiter);
+int fman_port_delete_rate_limiter(struct fman_port *port);
+int fman_port_set_err_mask(struct fman_port *port, uint32_t err_mask);
+int fman_port_set_discard_mask(struct fman_port *port, uint32_t discard_mask);
+int fman_port_modify_rx_fd_bits(struct fman_port *port,
+ uint8_t rx_fd_bits,
+ bool add);
+int fman_port_set_perf_cnt_params(struct fman_port *port,
+ struct fman_port_perf_cnt_params *params);
+int fman_port_set_stats_cnt_mode(struct fman_port *port, bool enable);
+int fman_port_set_perf_cnt_mode(struct fman_port *port, bool enable);
+int fman_port_set_queue_cnt_mode(struct fman_port *port, bool enable);
+int fman_port_set_bpool_cnt_mode(struct fman_port *port,
+ uint8_t bpid,
+ bool enable);
+uint32_t fman_port_get_stats_counter(struct fman_port *port,
+ enum fman_port_stats_counters counter);
+void fman_port_set_stats_counter(struct fman_port *port,
+ enum fman_port_stats_counters counter,
+ uint32_t value);
+uint32_t fman_port_get_perf_counter(struct fman_port *port,
+ enum fman_port_perf_counters counter);
+void fman_port_set_perf_counter(struct fman_port *port,
+ enum fman_port_perf_counters counter,
+ uint32_t value);
+uint32_t fman_port_get_qmi_counter(struct fman_port *port,
+ enum fman_port_qmi_counters counter);
+void fman_port_set_qmi_counter(struct fman_port *port,
+ enum fman_port_qmi_counters counter,
+ uint32_t value);
+uint32_t fman_port_get_bpool_counter(struct fman_port *port, uint8_t bpid);
+void fman_port_set_bpool_counter(struct fman_port *port,
+ uint8_t bpid,
+ uint32_t value);
+int fman_port_add_congestion_grps(struct fman_port *port,
+ uint32_t grps_map[FMAN_PORT_CG_MAP_NUM]);
+int fman_port_remove_congestion_grps(struct fman_port *port,
+ uint32_t grps_map[FMAN_PORT_CG_MAP_NUM]);
+
+
+#endif /* __FSL_FMAN_PORT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_prs.h b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_prs.h
new file mode 100644
index 0000000..b18997d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_prs.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FSL_FMAN_PRS_H
+#define __FSL_FMAN_PRS_H
+
+#include "common/general.h"
+
+#define FM_PCD_EX_PRS_DOUBLE_ECC 0x02000000
+#define FM_PCD_EX_PRS_SINGLE_ECC 0x01000000
+
+#define FM_PCD_PRS_PPSC_ALL_PORTS 0xffff0000
+#define FM_PCD_PRS_RPIMAC_EN 0x00000001
+#define FM_PCD_PRS_PORT_IDLE_STS 0xffff0000
+#define FM_PCD_PRS_SINGLE_ECC 0x00004000
+#define FM_PCD_PRS_DOUBLE_ECC 0x00004000
+#define PRS_MAX_CYCLE_LIMIT 8191
+
+#define DEFAULT_MAX_PRS_CYC_LIM 0
+
+struct fman_prs_regs {
+ uint32_t fmpr_rpclim;
+ uint32_t fmpr_rpimac;
+ uint32_t pmeec;
+ uint32_t res00c[5];
+ uint32_t fmpr_pevr;
+ uint32_t fmpr_pever;
+ uint32_t res028;
+ uint32_t fmpr_perr;
+ uint32_t fmpr_perer;
+ uint32_t res034;
+ uint32_t res038[10];
+ uint32_t fmpr_ppsc;
+ uint32_t res064;
+ uint32_t fmpr_pds;
+ uint32_t fmpr_l2rrs;
+ uint32_t fmpr_l3rrs;
+ uint32_t fmpr_l4rrs;
+ uint32_t fmpr_srrs;
+ uint32_t fmpr_l2rres;
+ uint32_t fmpr_l3rres;
+ uint32_t fmpr_l4rres;
+ uint32_t fmpr_srres;
+ uint32_t fmpr_spcs;
+ uint32_t fmpr_spscs;
+ uint32_t fmpr_hxscs;
+ uint32_t fmpr_mrcs;
+ uint32_t fmpr_mwcs;
+ uint32_t fmpr_mrscs;
+ uint32_t fmpr_mwscs;
+ uint32_t fmpr_fcscs;
+};
+
+struct fman_prs_cfg {
+ uint32_t port_id_stat;
+ uint16_t max_prs_cyc_lim;
+ uint32_t prs_exceptions;
+};
+
+uint32_t fman_prs_get_err_event(struct fman_prs_regs *regs, uint32_t ev_mask);
+uint32_t fman_prs_get_err_ev_mask(struct fman_prs_regs *regs);
+void fman_prs_ack_err_event(struct fman_prs_regs *regs, uint32_t event);
+uint32_t fman_prs_get_expt_event(struct fman_prs_regs *regs, uint32_t ev_mask);
+uint32_t fman_prs_get_expt_ev_mask(struct fman_prs_regs *regs);
+void fman_prs_ack_expt_event(struct fman_prs_regs *regs, uint32_t event);
+void fman_prs_defconfig(struct fman_prs_cfg *cfg);
+int fman_prs_init(struct fman_prs_regs *regs, struct fman_prs_cfg *cfg);
+void fman_prs_enable(struct fman_prs_regs *regs);
+void fman_prs_disable(struct fman_prs_regs *regs);
+int fman_prs_is_enabled(struct fman_prs_regs *regs);
+void fman_prs_set_stst_port_msk(struct fman_prs_regs *regs, uint32_t pid_msk);
+void fman_prs_set_stst(struct fman_prs_regs *regs, bool enable);
+#endif /* __FSL_FMAN_PRS_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_rtc.h b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_rtc.h
new file mode 100755
index 0000000..f6b69a1
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_rtc.h
@@ -0,0 +1,449 @@
+/*
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FSL_FMAN_RTC_H
+#define __FSL_FMAN_RTC_H
+
+#include "common/general.h"
+
+/* FM RTC Registers definitions */
+#define FMAN_RTC_TMR_CTRL_ALMP1 0x80000000
+#define FMAN_RTC_TMR_CTRL_ALMP2 0x40000000
+#define FMAN_RTC_TMR_CTRL_FS 0x10000000
+#define FMAN_RTC_TMR_CTRL_PP1L 0x08000000
+#define FMAN_RTC_TMR_CTRL_PP2L 0x04000000
+#define FMAN_RTC_TMR_CTRL_TCLK_PERIOD_MASK 0x03FF0000
+#define FMAN_RTC_TMR_CTRL_FRD 0x00004000
+#define FMAN_RTC_TMR_CTRL_SLV 0x00002000
+#define FMAN_RTC_TMR_CTRL_ETEP1 0x00000100
+#define FMAN_RTC_TMR_CTRL_COPH 0x00000080
+#define FMAN_RTC_TMR_CTRL_CIPH 0x00000040
+#define FMAN_RTC_TMR_CTRL_TMSR 0x00000020
+#define FMAN_RTC_TMR_CTRL_DBG 0x00000010
+#define FMAN_RTC_TMR_CTRL_BYP 0x00000008
+#define FMAN_RTC_TMR_CTRL_TE 0x00000004
+#define FMAN_RTC_TMR_CTRL_CKSEL_OSC_CLK 0x00000003
+#define FMAN_RTC_TMR_CTRL_CKSEL_MAC_CLK 0x00000001
+#define FMAN_RTC_TMR_CTRL_CKSEL_EXT_CLK 0x00000000
+#define FMAN_RTC_TMR_CTRL_TCLK_PERIOD_SHIFT 16
+
+#define FMAN_RTC_TMR_TEVENT_ETS2 0x02000000
+#define FMAN_RTC_TMR_TEVENT_ETS1 0x01000000
+#define FMAN_RTC_TMR_TEVENT_ALM2 0x00020000
+#define FMAN_RTC_TMR_TEVENT_ALM1 0x00010000
+#define FMAN_RTC_TMR_TEVENT_PP1 0x00000080
+#define FMAN_RTC_TMR_TEVENT_PP2 0x00000040
+#define FMAN_RTC_TMR_TEVENT_PP3 0x00000020
+#define FMAN_RTC_TMR_TEVENT_ALL (FMAN_RTC_TMR_TEVENT_ETS2 |\
+ FMAN_RTC_TMR_TEVENT_ETS1 |\
+ FMAN_RTC_TMR_TEVENT_ALM2 |\
+ FMAN_RTC_TMR_TEVENT_ALM1 |\
+ FMAN_RTC_TMR_TEVENT_PP1 |\
+ FMAN_RTC_TMR_TEVENT_PP2 |\
+ FMAN_RTC_TMR_TEVENT_PP3)
+
+#define FMAN_RTC_TMR_PRSC_OCK_MASK 0x0000FFFF
+
+/**************************************************************************//**
+ @Description FM RTC Alarm Polarity Options.
+*//***************************************************************************/
+enum fman_rtc_alarm_polarity {
+ E_FMAN_RTC_ALARM_POLARITY_ACTIVE_HIGH, /**< Active-high output polarity */
+ E_FMAN_RTC_ALARM_POLARITY_ACTIVE_LOW /**< Active-low output polarity */
+};
+
+/**************************************************************************//**
+ @Description FM RTC Trigger Polarity Options.
+*//***************************************************************************/
+enum fman_rtc_trigger_polarity {
+ E_FMAN_RTC_TRIGGER_ON_RISING_EDGE, /**< Trigger on rising edge */
+ E_FMAN_RTC_TRIGGER_ON_FALLING_EDGE /**< Trigger on falling edge */
+};
+
+/**************************************************************************//**
+ @Description IEEE1588 Timer Module FM RTC Optional Clock Sources.
+*//***************************************************************************/
+enum fman_src_clock {
+ E_FMAN_RTC_SOURCE_CLOCK_EXTERNAL, /**< external high precision timer
+ reference clock */
+ E_FMAN_RTC_SOURCE_CLOCK_SYSTEM, /**< MAC system clock */
+ E_FMAN_RTC_SOURCE_CLOCK_OSCILATOR /**< RTC clock oscilator */
+};
+
+/* RTC default values */
+#define DEFAULT_SRC_CLOCK E_FMAN_RTC_SOURCE_CLOCK_SYSTEM
+#define DEFAULT_INVERT_INPUT_CLK_PHASE FALSE
+#define DEFAULT_INVERT_OUTPUT_CLK_PHASE FALSE
+#define DEFAULT_ALARM_POLARITY E_FMAN_RTC_ALARM_POLARITY_ACTIVE_HIGH
+#define DEFAULT_TRIGGER_POLARITY E_FMAN_RTC_TRIGGER_ON_FALLING_EDGE
+#define DEFAULT_PULSE_REALIGN FALSE
+
+#define FMAN_RTC_MAX_NUM_OF_ALARMS 3
+#define FMAN_RTC_MAX_NUM_OF_PERIODIC_PULSES 4
+#define FMAN_RTC_MAX_NUM_OF_EXT_TRIGGERS 3
+
+/**************************************************************************//**
+ @Description FM RTC timer alarm
+*//***************************************************************************/
+struct t_tmr_alarm{
+ uint32_t tmr_alarm_h; /**< */
+ uint32_t tmr_alarm_l; /**< */
+};
+
+/**************************************************************************//**
+ @Description FM RTC timer Ex trigger
+*//***************************************************************************/
+struct t_tmr_ext_trigger{
+ uint32_t tmr_etts_h; /**< */
+ uint32_t tmr_etts_l; /**< */
+};
+
+struct rtc_regs {
+ uint32_t tmr_id; /* 0x000 Module ID register */
+ uint32_t tmr_id2; /* 0x004 Controller ID register */
+ uint32_t reserved0008[30];
+ uint32_t tmr_ctrl; /* 0x0080 timer control register */
+ uint32_t tmr_tevent; /* 0x0084 timer event register */
+ uint32_t tmr_temask; /* 0x0088 timer event mask register */
+ uint32_t reserved008c[3];
+ uint32_t tmr_cnt_h; /* 0x0098 timer counter high register */
+ uint32_t tmr_cnt_l; /* 0x009c timer counter low register */
+ uint32_t tmr_add; /* 0x00a0 timer drift compensation addend register */
+ uint32_t tmr_acc; /* 0x00a4 timer accumulator register */
+ uint32_t tmr_prsc; /* 0x00a8 timer prescale */
+ uint32_t reserved00ac;
+ uint32_t tmr_off_h; /* 0x00b0 timer offset high */
+ uint32_t tmr_off_l; /* 0x00b4 timer offset low */
+ struct t_tmr_alarm tmr_alarm[FMAN_RTC_MAX_NUM_OF_ALARMS]; /* 0x00b8 timer
+ alarm */
+ uint32_t tmr_fiper[FMAN_RTC_MAX_NUM_OF_PERIODIC_PULSES]; /* 0x00d0 timer
+ fixed period interval */
+ struct t_tmr_ext_trigger tmr_etts[FMAN_RTC_MAX_NUM_OF_EXT_TRIGGERS];
+ /* 0x00e0 time stamp general purpose external */
+ uint32_t reserved00f0[4];
+};
+
+struct rtc_cfg {
+ enum fman_src_clock src_clk;
+ uint32_t ext_src_clk_freq;
+ uint32_t rtc_freq_hz;
+ bool timer_slave_mode;
+ bool invert_input_clk_phase;
+ bool invert_output_clk_phase;
+ uint32_t events_mask;
+ bool bypass; /**< Indicates if frequency compensation
+ is bypassed */
+ bool pulse_realign;
+ enum fman_rtc_alarm_polarity alarm_polarity[FMAN_RTC_MAX_NUM_OF_ALARMS];
+ enum fman_rtc_trigger_polarity trigger_polarity
+ [FMAN_RTC_MAX_NUM_OF_EXT_TRIGGERS];
+};
+
+/**
+ * fman_rtc_defconfig() - Get default RTC configuration
+ * @cfg: pointer to configuration structure.
+ *
+ * Call this function to obtain a default set of configuration values for
+ * initializing RTC. The user can overwrite any of the values before calling
+ * fman_rtc_init(), if specific configuration needs to be applied.
+ */
+void fman_rtc_defconfig(struct rtc_cfg *cfg);
+
+/**
+ * fman_rtc_get_events() - Get the events
+ * @regs: Pointer to RTC register block
+ *
+ * Returns: The events
+ */
+uint32_t fman_rtc_get_events(struct rtc_regs *regs);
+
+/**
+ * fman_rtc_get_interrupt_mask() - Get the events mask
+ * @regs: Pointer to RTC register block
+ *
+ * Returns: The events mask
+ */
+uint32_t fman_rtc_get_interrupt_mask(struct rtc_regs *regs);
+
+
+/**
+ * fman_rtc_set_interrupt_mask() - Set the events mask
+ * @regs: Pointer to RTC register block
+ * @mask: The mask to set
+ */
+void fman_rtc_set_interrupt_mask(struct rtc_regs *regs, uint32_t mask);
+
+/**
+ * fman_rtc_get_event() - Check if specific events occurred
+ * @regs: Pointer to RTC register block
+ * @ev_mask: a mask of the events to check
+ *
+ * Returns: 0 if the events did not occur. Non zero if one of the events occurred
+ */
+uint32_t fman_rtc_get_event(struct rtc_regs *regs, uint32_t ev_mask);
+
+/**
+ * fman_rtc_check_and_clear_event() - Clear events which are on
+ * @regs: Pointer to RTC register block
+ *
+ * Returns: A mask of the events which were cleared
+ */
+uint32_t fman_rtc_check_and_clear_event(struct rtc_regs *regs);
+
+/**
+ * fman_rtc_ack_event() - Clear events
+ * @regs: Pointer to RTC register block
+ * @events: The events to disable
+ */
+void fman_rtc_ack_event(struct rtc_regs *regs, uint32_t events);
+
+/**
+ * fman_rtc_enable_interupt() - Enable events interrupts
+ * @regs: Pointer to RTC register block
+ * @mask: The events to disable
+ */
+void fman_rtc_enable_interupt(struct rtc_regs *regs, uint32_t mask);
+
+/**
+ * fman_rtc_disable_interupt() - Disable events interrupts
+ * @regs: Pointer to RTC register block
+ * @mask: The events to disable
+ */
+void fman_rtc_disable_interupt(struct rtc_regs *regs, uint32_t mask);
+
+/**
+ * fman_rtc_get_timer_ctrl() - Get the control register
+ * @regs: Pointer to RTC register block
+ *
+ * Returns: The control register value
+ */
+uint32_t fman_rtc_get_timer_ctrl(struct rtc_regs *regs);
+
+/**
+ * fman_rtc_set_timer_ctrl() - Set timer control register
+ * @regs: Pointer to RTC register block
+ * @val: The value to set
+ */
+void fman_rtc_set_timer_ctrl(struct rtc_regs *regs, uint32_t val);
+
+/**
+ * fman_rtc_get_frequency_compensation() - Get the frequency compensation
+ * @regs: Pointer to RTC register block
+ *
+ * Returns: The timer counter
+ */
+uint32_t fman_rtc_get_frequency_compensation(struct rtc_regs *regs);
+
+/**
+ * fman_rtc_set_frequency_compensation() - Set frequency compensation
+ * @regs: Pointer to RTC register block
+ * @val: The value to set
+ */
+void fman_rtc_set_frequency_compensation(struct rtc_regs *regs, uint32_t val);
+
+/**
+ * fman_rtc_get_trigger_stamp() - Get a trigger stamp
+ * @regs: Pointer to RTC register block
+ * @id: The id of the trigger stamp
+ *
+ * Returns: The time stamp
+ */
+uint64_t fman_rtc_get_trigger_stamp(struct rtc_regs *regs, int id);
+
+/**
+ * fman_rtc_set_timer_alarm_l() - Set timer alarm low register
+ * @regs: Pointer to RTC register block
+ * @index: The index of alarm to set
+ * @val: The value to set
+ */
+void fman_rtc_set_timer_alarm_l(struct rtc_regs *regs, int index,
+ uint32_t val);
+
+/**
+ * fman_rtc_set_timer_alarm() - Set timer alarm
+ * @regs: Pointer to RTC register block
+ * @index: The index of alarm to set
+ * @val: The value to set
+ */
+void fman_rtc_set_timer_alarm(struct rtc_regs *regs, int index, int64_t val);
+
+/**
+ * fman_rtc_set_timer_fiper() - Set timer fiper
+ * @regs: Pointer to RTC register block
+ * @index: The index of fiper to set
+ * @val: The value to set
+ */
+void fman_rtc_set_timer_fiper(struct rtc_regs *regs, int index, uint32_t val);
+
+/**
+ * fman_rtc_set_timer_offset() - Set timer offset
+ * @regs: Pointer to RTC register block
+ * @val: The value to set
+ */
+void fman_rtc_set_timer_offset(struct rtc_regs *regs, int64_t val);
+
+/**
+ * fman_rtc_get_timer() - Get the timer counter
+ * @regs: Pointer to RTC register block
+ *
+ * Returns: The timer counter
+ */
+static inline uint64_t fman_rtc_get_timer(struct rtc_regs *regs)
+{
+ uint64_t time;
+ /* TMR_CNT_L must be read first to get an accurate value */
+ time = (uint64_t)ioread32be(&regs->tmr_cnt_l);
+ time |= ((uint64_t)ioread32be(&regs->tmr_cnt_h) << 32);
+
+ return time;
+}
+
+/**
+ * fman_rtc_set_timer() - Set timer counter
+ * @regs: Pointer to RTC register block
+ * @val: The value to set
+ */
+static inline void fman_rtc_set_timer(struct rtc_regs *regs, int64_t val)
+{
+ iowrite32be((uint32_t)val, &regs->tmr_cnt_l);
+ iowrite32be((uint32_t)(val >> 32), &regs->tmr_cnt_h);
+}
+
+/**
+ * fman_rtc_timers_soft_reset() - Soft reset
+ * @regs: Pointer to RTC register block
+ *
+ * Resets all the timer registers and state machines for the 1588 IP and
+ * the attached client 1588
+ */
+void fman_rtc_timers_soft_reset(struct rtc_regs *regs);
+
+/**
+ * fman_rtc_clear_external_trigger() - Clear an external trigger
+ * @regs: Pointer to RTC register block
+ * @id: The id of the trigger to clear
+ */
+void fman_rtc_clear_external_trigger(struct rtc_regs *regs, int id);
+
+/**
+ * fman_rtc_clear_periodic_pulse() - Clear periodic pulse
+ * @regs: Pointer to RTC register block
+ * @id: The id of the fiper to clear
+ */
+void fman_rtc_clear_periodic_pulse(struct rtc_regs *regs, int id);
+
+/**
+ * fman_rtc_enable() - Enable RTC hardware block
+ * @regs: Pointer to RTC register block
+ */
+void fman_rtc_enable(struct rtc_regs *regs, bool reset_clock);
+
+/**
+ * fman_rtc_is_enabled() - Is RTC hardware block enabled
+ * @regs: Pointer to RTC register block
+ *
+ * Return: TRUE if enabled
+ */
+bool fman_rtc_is_enabled(struct rtc_regs *regs);
+
+/**
+ * fman_rtc_disable() - Disable RTC hardware block
+ * @regs: Pointer to RTC register block
+ */
+void fman_rtc_disable(struct rtc_regs *regs);
+
+/**
+ * fman_rtc_init() - Init RTC hardware block
+ * @cfg: RTC configuration data
+ * @regs: Pointer to RTC register block
+ * @num_alarms: Number of alarms in RTC
+ * @num_fipers: Number of fipers in RTC
+ * @num_ext_triggers: Number of external triggers in RTC
+ * @freq_compensation: Frequency compensation
+ * @output_clock_divisor: Output clock divisor
+ *
+ * This function initializes RTC and applies basic configuration.
+ */
+void fman_rtc_init(struct rtc_cfg *cfg, struct rtc_regs *regs, int num_alarms,
+ int num_fipers, int num_ext_triggers, bool init_freq_comp,
+ uint32_t freq_compensation, uint32_t output_clock_divisor);
+
+/**
+ * fman_rtc_set_alarm() - Set an alarm
+ * @regs: Pointer to RTC register block
+ * @id: id of alarm
+ * @val: value to write
+ * @enable: should interrupt be enabled
+ */
+void fman_rtc_set_alarm(struct rtc_regs *regs, int id, uint32_t val, bool enable);
+
+/**
+ * fman_rtc_set_periodic_pulse() - Set an alarm
+ * @regs: Pointer to RTC register block
+ * @id: id of fiper
+ * @val: value to write
+ * @enable: should interrupt be enabled
+ */
+void fman_rtc_set_periodic_pulse(struct rtc_regs *regs, int id, uint32_t val,
+ bool enable);
+
+/**
+ * fman_rtc_set_ext_trigger() - Set an external trigger
+ * @regs: Pointer to RTC register block
+ * @id: id of trigger
+ * @enable: should interrupt be enabled
+ * @use_pulse_as_input: use the pulse as input
+ */
+void fman_rtc_set_ext_trigger(struct rtc_regs *regs, int id, bool enable,
+ bool use_pulse_as_input);
+
+struct fm_rtc_alarm_params {
+ uint8_t alarm_id; /**< 0 or 1 */
+ uint64_t alarm_time; /**< In nanoseconds, the time when the
+ alarm should go off - must be a
+ multiple of the RTC period */
+ void (*f_alarm_callback)(void* app, uint8_t id); /**< This routine will
+ be called when RTC reaches alarmTime */
+ bool clear_on_expiration; /**< TRUE to turn off the alarm once
+ expired.*/
+};
+
+struct fm_rtc_periodic_pulse_params {
+ uint8_t periodic_pulse_id; /**< 0 or 1 */
+ uint64_t periodic_pulse_period; /**< In Nanoseconds. Must be a multiple
+ of the RTC period */
+ void (*f_periodic_pulse_callback)(void* app, uint8_t id); /**< This
+ routine will be called every
+ periodicPulsePeriod. */
+};
+
+#endif /* __FSL_FMAN_RTC_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_sp.h b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_sp.h
new file mode 100755
index 0000000..f8ef7d5
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_sp.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FSL_FMAN_SP_H
+#define __FSL_FMAN_SP_H
+
+#include "common/general.h"
+#include "fsl_fman.h"
+
+
+struct fm_pcd_storage_profile_regs{
+ uint32_t fm_sp_ebmpi[8];
+ /*offset 0 - 0xc*/
+ /**< Buffer Manager pool Information */
+
+ uint32_t fm_sp_acnt; /*offset 0x20*/
+ uint32_t fm_sp_ebm; /*offset 0x24*/
+ uint32_t fm_sp_da; /*offset 0x28*/
+ uint32_t fm_sp_icp; /*offset 0x2c*/
+ uint32_t fm_sp_mpd; /*offset 0x30*/
+ uint32_t res1[2]; /*offset 0x34 - 0x38*/
+ uint32_t fm_sp_spliodn; /*offset 0x3c*/
+};
+
+/**************************************************************************//**
+ @Description structure for defining internal context copying
+*//***************************************************************************/
+struct fman_sp_int_context_data_copy{
+ uint16_t ext_buf_offset; /**< Offset in External buffer to which
+ internal context is copied to (Rx)
+ or taken from (Tx, Op). */
+ uint8_t int_context_offset; /**< Offset within internal context to copy
+ from (Rx) or to copy to (Tx, Op).*/
+ uint16_t size; /**< Internal offset size to be copied */
+};
+
+/**************************************************************************//**
+ @Description struct for defining external buffer margins
+*//***************************************************************************/
+struct fman_sp_buf_margins{
+ uint16_t start_margins; /**< Number of bytes to be left at the
+ beginning of the external buffer (must be
+ divisible by 16) */
+ uint16_t end_margins; /**< number of bytes to be left at the end of
+ the external buffer(must be divisible by 16)*/
+};
+
+struct fm_storage_profile_params {
+ struct fman_ext_pools fm_ext_pools;
+ struct fman_backup_bm_pools backup_pools;
+ struct fman_sp_int_context_data_copy *int_context;
+ struct fman_sp_buf_margins *buf_margins;
+ enum fman_dma_swap_option dma_swap_data;
+ enum fman_dma_cache_option int_context_cache_attr;
+ enum fman_dma_cache_option header_cache_attr;
+ enum fman_dma_cache_option scatter_gather_cache_attr;
+ bool dma_write_optimize;
+ uint16_t liodn_offset;
+ bool no_scather_gather;
+ struct fman_buf_pool_depletion buf_pool_depletion;
+};
+
+/**************************************************************************//**
+ @Description Registers bit fields
+*//***************************************************************************/
+#define FMAN_SP_EXT_BUF_POOL_EN_COUNTER 0x40000000
+#define FMAN_SP_EXT_BUF_POOL_VALID 0x80000000
+#define FMAN_SP_EXT_BUF_POOL_BACKUP 0x20000000
+#define FMAN_SP_DMA_ATTR_WRITE_OPTIMIZE 0x00100000
+#define FMAN_SP_SG_DISABLE 0x80000000
+
+/* shifts */
+#define FMAN_SP_EXT_BUF_POOL_ID_SHIFT 16
+#define FMAN_SP_POOL_DEP_NUM_OF_POOLS_SHIFT 16
+#define FMAN_SP_EXT_BUF_MARG_START_SHIFT 16
+#define FMAN_SP_EXT_BUF_MARG_END_SHIFT 0
+#define FMAN_SP_DMA_ATTR_SWP_SHIFT 30
+#define FMAN_SP_DMA_ATTR_IC_CACHE_SHIFT 28
+#define FMAN_SP_DMA_ATTR_HDR_CACHE_SHIFT 26
+#define FMAN_SP_DMA_ATTR_SG_CACHE_SHIFT 24
+#define FMAN_SP_IC_TO_EXT_SHIFT 16
+#define FMAN_SP_IC_FROM_INT_SHIFT 8
+#define FMAN_SP_IC_SIZE_SHIFT 0
+
+/**************************************************************************//**
+ @Description defaults
+*//***************************************************************************/
+#define DEFAULT_FMAN_SP_DMA_SWAP_DATA FMAN_DMA_NO_SWP
+#define DEFAULT_FMAN_SP_DMA_INT_CONTEXT_CACHE_ATTR FMAN_DMA_NO_STASH
+#define DEFAULT_FMAN_SP_DMA_HEADER_CACHE_ATTR FMAN_DMA_NO_STASH
+#define DEFAULT_FMAN_SP_DMA_SCATTER_GATHER_CACHE_ATTR FMAN_DMA_NO_STASH
+#define DEFAULT_FMAN_SP_DMA_WRITE_OPTIMIZE TRUE
+#define DEFAULT_FMAN_SP_NO_SCATTER_GATHER FALSE
+
+void fman_vsp_defconfig(struct fm_storage_profile_params *cfg);
+
+void fman_vsp_init(struct fm_pcd_storage_profile_regs *regs,
+ uint16_t index, struct fm_storage_profile_params *fm_vsp_params,
+ int port_max_num_of_ext_pools, int bm_max_num_of_pools,
+ int max_num_of_pfc_priorities);
+
+uint32_t fman_vsp_get_statistics(struct fm_pcd_storage_profile_regs *regs,
+ uint16_t index);
+
+void fman_vsp_set_statistics(struct fm_pcd_storage_profile_regs *regs,
+ uint16_t index, uint32_t value);
+
+
+#endif /* __FSL_FMAN_SP_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_tgec.h b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_tgec.h
new file mode 100644
index 0000000..a037314
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/flib/fsl_fman_tgec.h
@@ -0,0 +1,479 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FSL_FMAN_TGEC_H
+#define __FSL_FMAN_TGEC_H
+
+#include "common/general.h"
+#include "fsl_enet.h"
+
+
+/* Transmit Inter-Packet Gap Length Register (TX_IPG_LENGTH) */
+#define TGEC_TX_IPG_LENGTH_MASK 0x000003ff
+
+enum tgec_counters {
+ E_TGEC_COUNTER_R64,
+ E_TGEC_COUNTER_R127,
+ E_TGEC_COUNTER_R255,
+ E_TGEC_COUNTER_R511,
+ E_TGEC_COUNTER_R1023,
+ E_TGEC_COUNTER_R1518,
+ E_TGEC_COUNTER_R1519X,
+ E_TGEC_COUNTER_TRFRG,
+ E_TGEC_COUNTER_TRJBR,
+ E_TGEC_COUNTER_RDRP,
+ E_TGEC_COUNTER_RALN,
+ E_TGEC_COUNTER_TRUND,
+ E_TGEC_COUNTER_TROVR,
+ E_TGEC_COUNTER_RXPF,
+ E_TGEC_COUNTER_TXPF,
+ E_TGEC_COUNTER_ROCT,
+ E_TGEC_COUNTER_RMCA,
+ E_TGEC_COUNTER_RBCA,
+ E_TGEC_COUNTER_RPKT,
+ E_TGEC_COUNTER_RUCA,
+ E_TGEC_COUNTER_RERR,
+ E_TGEC_COUNTER_TOCT,
+ E_TGEC_COUNTER_TMCA,
+ E_TGEC_COUNTER_TBCA,
+ E_TGEC_COUNTER_TUCA,
+ E_TGEC_COUNTER_TERR
+};
+
+/* Command and Configuration Register (COMMAND_CONFIG) */
+#define CMD_CFG_EN_TIMESTAMP 0x00100000
+#define CMD_CFG_TX_ADDR_INS_SEL 0x00080000
+#define CMD_CFG_NO_LEN_CHK 0x00020000
+#define CMD_CFG_SEND_IDLE 0x00010000
+#define CMD_CFG_RX_ER_DISC 0x00004000
+#define CMD_CFG_CMD_FRM_EN 0x00002000
+#define CMD_CFG_STAT_CLR 0x00001000
+#define CMD_CFG_LOOPBACK_EN 0x00000400
+#define CMD_CFG_TX_ADDR_INS 0x00000200
+#define CMD_CFG_PAUSE_IGNORE 0x00000100
+#define CMD_CFG_PAUSE_FWD 0x00000080
+#define CMD_CFG_PROMIS_EN 0x00000010
+#define CMD_CFG_WAN_MODE 0x00000008
+#define CMD_CFG_RX_EN 0x00000002
+#define CMD_CFG_TX_EN 0x00000001
+
+/* Interrupt Mask Register (IMASK) */
+#define TGEC_IMASK_MDIO_SCAN_EVENT 0x00010000
+#define TGEC_IMASK_MDIO_CMD_CMPL 0x00008000
+#define TGEC_IMASK_REM_FAULT 0x00004000
+#define TGEC_IMASK_LOC_FAULT 0x00002000
+#define TGEC_IMASK_TX_ECC_ER 0x00001000
+#define TGEC_IMASK_TX_FIFO_UNFL 0x00000800
+#define TGEC_IMASK_TX_FIFO_OVFL 0x00000400
+#define TGEC_IMASK_TX_ER 0x00000200
+#define TGEC_IMASK_RX_FIFO_OVFL 0x00000100
+#define TGEC_IMASK_RX_ECC_ER 0x00000080
+#define TGEC_IMASK_RX_JAB_FRM 0x00000040
+#define TGEC_IMASK_RX_OVRSZ_FRM 0x00000020
+#define TGEC_IMASK_RX_RUNT_FRM 0x00000010
+#define TGEC_IMASK_RX_FRAG_FRM 0x00000008
+#define TGEC_IMASK_RX_LEN_ER 0x00000004
+#define TGEC_IMASK_RX_CRC_ER 0x00000002
+#define TGEC_IMASK_RX_ALIGN_ER 0x00000001
+
+#define TGEC_EVENTS_MASK \
+ ((uint32_t)(TGEC_IMASK_MDIO_SCAN_EVENT | \
+ TGEC_IMASK_MDIO_CMD_CMPL | \
+ TGEC_IMASK_REM_FAULT | \
+ TGEC_IMASK_LOC_FAULT | \
+ TGEC_IMASK_TX_ECC_ER | \
+ TGEC_IMASK_TX_FIFO_UNFL | \
+ TGEC_IMASK_TX_FIFO_OVFL | \
+ TGEC_IMASK_TX_ER | \
+ TGEC_IMASK_RX_FIFO_OVFL | \
+ TGEC_IMASK_RX_ECC_ER | \
+ TGEC_IMASK_RX_JAB_FRM | \
+ TGEC_IMASK_RX_OVRSZ_FRM | \
+ TGEC_IMASK_RX_RUNT_FRM | \
+ TGEC_IMASK_RX_FRAG_FRM | \
+ TGEC_IMASK_RX_LEN_ER | \
+ TGEC_IMASK_RX_CRC_ER | \
+ TGEC_IMASK_RX_ALIGN_ER))
+
+/* Hashtable Control Register (HASHTABLE_CTRL) */
+#define TGEC_HASH_MCAST_SHIFT 23
+#define TGEC_HASH_MCAST_EN 0x00000200
+#define TGEC_HASH_ADR_MSK 0x000001ff
+
+#define DEFAULT_WAN_MODE_ENABLE FALSE
+#define DEFAULT_PROMISCUOUS_MODE_ENABLE FALSE
+#define DEFAULT_PAUSE_FORWARD_ENABLE FALSE
+#define DEFAULT_PAUSE_IGNORE FALSE
+#define DEFAULT_TX_ADDR_INS_ENABLE FALSE
+#define DEFAULT_LOOPBACK_ENABLE FALSE
+#define DEFAULT_CMD_FRAME_ENABLE FALSE
+#define DEFAULT_RX_ERROR_DISCARD FALSE
+#define DEFAULT_SEND_IDLE_ENABLE FALSE
+#define DEFAULT_NO_LENGTH_CHECK_ENABLE TRUE
+#define DEFAULT_LGTH_CHECK_NOSTDR FALSE
+#define DEFAULT_TIME_STAMP_ENABLE FALSE
+#define DEFAULT_TX_IPG_LENGTH 12
+#define DEFAULT_MAX_FRAME_LENGTH 0x600
+#define DEFAULT_PAUSE_QUANT 0xf000
+
+/*
+ * 10G memory map
+ */
+struct tgec_regs {
+ uint32_t tgec_id; /* 0x000 Controller ID */
+ uint32_t reserved001[1]; /* 0x004 */
+ uint32_t command_config; /* 0x008 Control and configuration */
+ uint32_t mac_addr_0; /* 0x00c Lower 32 bits of the MAC adr */
+ uint32_t mac_addr_1; /* 0x010 Upper 16 bits of the MAC adr */
+ uint32_t maxfrm; /* 0x014 Maximum frame length */
+ uint32_t pause_quant; /* 0x018 Pause quanta */
+ uint32_t rx_fifo_sections; /* 0x01c */
+ uint32_t tx_fifo_sections; /* 0x020 */
+ uint32_t rx_fifo_almost_f_e; /* 0x024 */
+ uint32_t tx_fifo_almost_f_e; /* 0x028 */
+ uint32_t hashtable_ctrl; /* 0x02c Hash table control*/
+ uint32_t mdio_cfg_status; /* 0x030 */
+ uint32_t mdio_command; /* 0x034 */
+ uint32_t mdio_data; /* 0x038 */
+ uint32_t mdio_regaddr; /* 0x03c */
+ uint32_t status; /* 0x040 */
+ uint32_t tx_ipg_len; /* 0x044 Transmitter inter-packet-gap */
+ uint32_t mac_addr_2; /* 0x048 Lower 32 bits of 2nd MAC adr */
+ uint32_t mac_addr_3; /* 0x04c Upper 16 bits of 2nd MAC adr */
+ uint32_t rx_fifo_ptr_rd; /* 0x050 */
+ uint32_t rx_fifo_ptr_wr; /* 0x054 */
+ uint32_t tx_fifo_ptr_rd; /* 0x058 */
+ uint32_t tx_fifo_ptr_wr; /* 0x05c */
+ uint32_t imask; /* 0x060 Interrupt mask */
+ uint32_t ievent; /* 0x064 Interrupt event */
+ uint32_t udp_port; /* 0x068 Defines a UDP Port number */
+ uint32_t type_1588v2; /* 0x06c Type field for 1588v2 */
+ uint32_t reserved070[4]; /* 0x070 */
+ /*10Ge Statistics Counter */
+ uint32_t tfrm_u; /* 80 aFramesTransmittedOK */
+ uint32_t tfrm_l; /* 84 aFramesTransmittedOK */
+ uint32_t rfrm_u; /* 88 aFramesReceivedOK */
+ uint32_t rfrm_l; /* 8c aFramesReceivedOK */
+ uint32_t rfcs_u; /* 90 aFrameCheckSequenceErrors */
+ uint32_t rfcs_l; /* 94 aFrameCheckSequenceErrors */
+ uint32_t raln_u; /* 98 aAlignmentErrors */
+ uint32_t raln_l; /* 9c aAlignmentErrors */
+ uint32_t txpf_u; /* A0 aPAUSEMACCtrlFramesTransmitted */
+ uint32_t txpf_l; /* A4 aPAUSEMACCtrlFramesTransmitted */
+ uint32_t rxpf_u; /* A8 aPAUSEMACCtrlFramesReceived */
+ uint32_t rxpf_l; /* Ac aPAUSEMACCtrlFramesReceived */
+ uint32_t rlong_u; /* B0 aFrameTooLongErrors */
+ uint32_t rlong_l; /* B4 aFrameTooLongErrors */
+ uint32_t rflr_u; /* B8 aInRangeLengthErrors */
+ uint32_t rflr_l; /* Bc aInRangeLengthErrors */
+ uint32_t tvlan_u; /* C0 VLANTransmittedOK */
+ uint32_t tvlan_l; /* C4 VLANTransmittedOK */
+ uint32_t rvlan_u; /* C8 VLANReceivedOK */
+ uint32_t rvlan_l; /* Cc VLANReceivedOK */
+ uint32_t toct_u; /* D0 ifOutOctets */
+ uint32_t toct_l; /* D4 ifOutOctets */
+ uint32_t roct_u; /* D8 ifInOctets */
+ uint32_t roct_l; /* Dc ifInOctets */
+ uint32_t ruca_u; /* E0 ifInUcastPkts */
+ uint32_t ruca_l; /* E4 ifInUcastPkts */
+ uint32_t rmca_u; /* E8 ifInMulticastPkts */
+ uint32_t rmca_l; /* Ec ifInMulticastPkts */
+ uint32_t rbca_u; /* F0 ifInBroadcastPkts */
+ uint32_t rbca_l; /* F4 ifInBroadcastPkts */
+ uint32_t terr_u; /* F8 ifOutErrors */
+ uint32_t terr_l; /* Fc ifOutErrors */
+ uint32_t reserved100[2]; /* 100-108*/
+ uint32_t tuca_u; /* 108 ifOutUcastPkts */
+ uint32_t tuca_l; /* 10c ifOutUcastPkts */
+ uint32_t tmca_u; /* 110 ifOutMulticastPkts */
+ uint32_t tmca_l; /* 114 ifOutMulticastPkts */
+ uint32_t tbca_u; /* 118 ifOutBroadcastPkts */
+ uint32_t tbca_l; /* 11c ifOutBroadcastPkts */
+ uint32_t rdrp_u; /* 120 etherStatsDropEvents */
+ uint32_t rdrp_l; /* 124 etherStatsDropEvents */
+ uint32_t reoct_u; /* 128 etherStatsOctets */
+ uint32_t reoct_l; /* 12c etherStatsOctets */
+ uint32_t rpkt_u; /* 130 etherStatsPkts */
+ uint32_t rpkt_l; /* 134 etherStatsPkts */
+ uint32_t trund_u; /* 138 etherStatsUndersizePkts */
+ uint32_t trund_l; /* 13c etherStatsUndersizePkts */
+ uint32_t r64_u; /* 140 etherStatsPkts64Octets */
+ uint32_t r64_l; /* 144 etherStatsPkts64Octets */
+ uint32_t r127_u; /* 148 etherStatsPkts65to127Octets */
+ uint32_t r127_l; /* 14c etherStatsPkts65to127Octets */
+ uint32_t r255_u; /* 150 etherStatsPkts128to255Octets */
+ uint32_t r255_l; /* 154 etherStatsPkts128to255Octets */
+ uint32_t r511_u; /* 158 etherStatsPkts256to511Octets */
+ uint32_t r511_l; /* 15c etherStatsPkts256to511Octets */
+ uint32_t r1023_u; /* 160 etherStatsPkts512to1023Octets */
+ uint32_t r1023_l; /* 164 etherStatsPkts512to1023Octets */
+ uint32_t r1518_u; /* 168 etherStatsPkts1024to1518Octets */
+ uint32_t r1518_l; /* 16c etherStatsPkts1024to1518Octets */
+ uint32_t r1519x_u; /* 170 etherStatsPkts1519toX */
+ uint32_t r1519x_l; /* 174 etherStatsPkts1519toX */
+ uint32_t trovr_u; /* 178 etherStatsOversizePkts */
+ uint32_t trovr_l; /* 17c etherStatsOversizePkts */
+ uint32_t trjbr_u; /* 180 etherStatsJabbers */
+ uint32_t trjbr_l; /* 184 etherStatsJabbers */
+ uint32_t trfrg_u; /* 188 etherStatsFragments */
+ uint32_t trfrg_l; /* 18C etherStatsFragments */
+ uint32_t rerr_u; /* 190 ifInErrors */
+ uint32_t rerr_l; /* 194 ifInErrors */
+};
+
+/**
+ * struct tgec_cfg - TGEC configuration
+ *
+ * @rx_error_discard: Receive Erroneous Frame Discard Enable. When set to 1
+ * any frame received with an error is discarded in the
+ * Core and not forwarded to the Client interface.
+ * When set to 0 (Reset value), erroneous Frames are
+ * forwarded to the Client interface with ff_rx_err
+ * asserted.
+ * @pause_ignore: Ignore Pause Frame Quanta. If set to 1 received pause
+ * frames are ignored by the MAC. When set to 0
+ * (Reset value) the transmit process is stopped for the
+ * amount of time specified in the pause quanta received
+ * within a pause frame.
+ * @pause_forward_enable:
+ * Terminate / Forward Pause Frames. If set to 1 pause
+ * frames are forwarded to the user application. When set
+ * to 0 (Reset value) pause frames are terminated and
+ * discarded within the MAC.
+ * @no_length_check_enable:
+ * Payload Length Check Disable. When set to 0
+ * (Reset value), the Core checks the frame's payload
+ * length with the Frame Length/Type field, when set to 1
+ * the payload length check is disabled.
+ * @cmd_frame_enable: Enables reception of all command frames. When set to 1
+ * all Command Frames are accepted, when set to 0
+ * (Reset Value) only Pause Frames are accepted and all
+ * other Command Frames are rejected.
+ * @send_idle_enable: Force Idle Generation. When set to 1, the MAC
+ * permanently sends XGMII Idle sequences even when faults
+ * are received.
+ * @wan_mode_enable: WAN Mode Enable. Sets WAN mode (1) or LAN mode
+ * (0, default) of operation.
+ * @promiscuous_mode_enable:
+ * Enables MAC promiscuous operation. When set to 1, all
+ * frames are received without any MAC address filtering,
+ * when set to 0 (Reset value) Unicast Frames with a
+ * destination address not matching the Core MAC Address
+ * (MAC Address programmed in Registers MAC_ADDR_0 and
+ * MAC_ADDR_1 or the MAC address programmed in Registers
+ * MAC_ADDR_2 and MAC_ADDR_3) are rejected.
+ * @tx_addr_ins_enable: Set Source MAC Address on Transmit. If set to 1 the
+ * MAC overwrites the source MAC address received from the
+ * Client Interface with one of the MAC addresses. If set
+ * to 0 (Reset value), the source MAC address from the
+ * Client Interface is transmitted unmodified to the line.
+ * @loopback_enable: PHY Interface Loopback. When set to 1, the signal
+ * loop_ena is set to '1', when set to 0 (Reset value)
+ * the signal loop_ena is set to 0.
+ * @lgth_check_nostdr: The Core interprets the Length/Type field differently
+ * depending on the value of this Bit
+ * @time_stamp_enable: This bit selects between enabling and disabling the
+ * IEEE 1588 functionality. 1: IEEE 1588 is enabled
+ * 0: IEEE 1588 is disabled
+ * @max_frame_length: Maximum supported received frame length.
+ * The 10GEC MAC supports reception of any frame size up
+ * to 16,352 bytes (0x3FE0). Typical settings are
+ * 0x05EE (1,518 bytes) for standard frames.
+ * Default setting is 0x0600 (1,536 bytes).
+ * Received frames that exceed this stated maximum
+ * are truncated.
+ * @pause_quant: Pause quanta value used with transmitted pause frames.
+ * Each quanta represents a 512 bit-times.
+ * @tx_ipg_length: Transmit Inter-Packet-Gap (IPG) value. A 6-bit value:
+ * Depending on LAN or WAN mode of operation the value has
+ * the following meaning: - LAN Mode: Number of octets in
+ * steps of 4. Valid values are 8, 12, 16, ... 100. DIC is
+ * fully supported (see 10.6.1 page 49) for any setting. A
+ * default of 12 (reset value) must be set to conform to
+ * IEEE802.3ae. Warning: When set to 8, PCS layers may not
+ * be able to perform clock rate compensation. - WAN Mode:
+ * Stretch factor. Valid values are 4..15. The stretch
+ * factor is calculated as (value+1)*8. A default of 12
+ * (reset value) must be set to conform to IEEE 802.3ae
+ * (i.e. 13*8=104). A larger value shrinks the IPG
+ * (increasing bandwidth).
+ *
+ * This structure contains basic TGEC configuration and must be passed to
+ * fman_tgec_init() function. A default set of configuration values can be
+ * obtained by calling fman_tgec_defconfig().
+ */
+struct tgec_cfg {
+ bool rx_error_discard;
+ bool pause_ignore;
+ bool pause_forward_enable;
+ bool no_length_check_enable;
+ bool cmd_frame_enable;
+ bool send_idle_enable;
+ bool wan_mode_enable;
+ bool promiscuous_mode_enable;
+ bool tx_addr_ins_enable;
+ bool loopback_enable;
+ bool lgth_check_nostdr;
+ bool time_stamp_enable;
+ uint16_t max_frame_length;
+ uint16_t pause_quant;
+ uint32_t tx_ipg_length;
+ bool skip_fman11_workaround;
+};
+
+
+void fman_tgec_defconfig(struct tgec_cfg *cfg);
+
+/**
+ * fman_tgec_init() - Init tgec hardware block
+ * @regs: Pointer to tgec register block
+ * @cfg: tgec configuration data
+ * @exceptions_mask: initial exceptions mask
+ *
+ * This function initializes the tgec controller and applies its
+ * basic configuration.
+ *
+ * Returns: 0 if successful, an error code otherwise.
+ */
+
+int fman_tgec_init(struct tgec_regs *regs, struct tgec_cfg *cfg,
+ uint32_t exception_mask);
+
+void fman_tgec_enable(struct tgec_regs *regs, bool apply_rx, bool apply_tx);
+
+void fman_tgec_disable(struct tgec_regs *regs, bool apply_rx, bool apply_tx);
+
+uint32_t fman_tgec_get_revision(struct tgec_regs *regs);
+
+void fman_tgec_set_mac_address(struct tgec_regs *regs, uint8_t *macaddr);
+
+void fman_tgec_set_promiscuous(struct tgec_regs *regs, bool val);
+
+/**
+ * fman_tgec_reset_stat() - Completely resets all TGEC HW counters
+ * @regs: Pointer to TGEC register block
+ */
+void fman_tgec_reset_stat(struct tgec_regs *regs);
+
+/**
+ * fman_tgec_get_counter() - Reads TGEC HW counters
+ * @regs: Pointer to TGEC register block
+ * @reg_name: Counter name according to the appropriate enum
+ *
+ * Returns: Required counter value
+ */
+uint64_t fman_tgec_get_counter(struct tgec_regs *regs,
+ enum tgec_counters reg_name);
+
+/**
+ * fman_tgec_set_hash_table() - Sets the Hashtable Control Register
+ * @regs: Pointer to TGEC register block
+ * @value: Value to be written in Hashtable Control Register
+ */
+void fman_tgec_set_hash_table(struct tgec_regs *regs, uint32_t value);
+
+/**
+ * fman_tgec_set_tx_pause_frames() - Sets the Pause Quanta Register
+ * @regs: Pointer to TGEC register block
+ * @pause_time: Pause quanta value used with transmitted pause frames.
+ * Each quanta represents a 512 bit-times
+ */
+void fman_tgec_set_tx_pause_frames(struct tgec_regs *regs, uint16_t pause_time);
+
+/**
+ * fman_tgec_set_rx_ignore_pause_frames() - Changes the policy WRT pause frames
+ * @regs: Pointer to TGEC register block
+ * @en: Ignore/Respond to pause frame quanta
+ *
+ * Sets the value of PAUSE_IGNORE field in the COMMAND_CONFIG Register
+ * 0 - MAC stops transmit process for the duration specified
+ * in the Pause frame quanta of a received Pause frame.
+ * 1 - MAC ignores received Pause frames.
+ */
+void fman_tgec_set_rx_ignore_pause_frames(struct tgec_regs *regs, bool en);
+
+/**
+ * fman_tgec_enable_1588_time_stamp() - change timestamp functionality
+ * @regs: Pointer to TGEC register block
+ * @en: enable/disable timestamp functionality
+ *
+ * Sets the value of EN_TIMESTAMP field in the COMMAND_CONFIG Register
+ * IEEE 1588 timestamp functionality control:
+ * 0 disabled, 1 enabled
+ */
+
+void fman_tgec_enable_1588_time_stamp(struct tgec_regs *regs, bool en);
+
+uint32_t fman_tgec_get_event(struct tgec_regs *regs, uint32_t ev_mask);
+
+void fman_tgec_ack_event(struct tgec_regs *regs, uint32_t ev_mask);
+
+uint32_t fman_tgec_get_interrupt_mask(struct tgec_regs *regs);
+
+/**
+ * fman_tgec_add_addr_in_paddr() - Sets additional exact match MAC address
+ * @regs: Pointer to TGEC register block
+ * @addr_ptr: Pointer to 6-byte array containing the MAC address
+ *
+ * Sets the additional station MAC address
+ */
+void fman_tgec_add_addr_in_paddr(struct tgec_regs *regs, uint8_t *addr_ptr);
+
+void fman_tgec_clear_addr_in_paddr(struct tgec_regs *regs);
+
+void fman_tgec_enable_interrupt(struct tgec_regs *regs, uint32_t ev_mask);
+
+void fman_tgec_disable_interrupt(struct tgec_regs *regs, uint32_t ev_mask);
+
+void fman_tgec_reset_filter_table(struct tgec_regs *regs);
+
+void fman_tgec_set_hash_table_entry(struct tgec_regs *regs, uint32_t crc);
+
+
+/**
+ * fman_tgec_get_max_frame_len() - Returns the maximum frame length value
+ * @regs: Pointer to TGEC register block
+ */
+uint16_t fman_tgec_get_max_frame_len(struct tgec_regs *regs);
+
+/**
+ * fman_tgec_set_erratum_tx_fifo_corruption_10gmac_a007() - Initialize the
+ * main tgec configuration parameters
+ * @regs: Pointer to TGEC register block
+ *
+ * TODO
+ */
+void fman_tgec_set_erratum_tx_fifo_corruption_10gmac_a007(struct tgec_regs
+ *regs);
+
+
+#endif /* __FSL_FMAN_TGEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/integrations/P1023/dpaa_integration_ext.h b/drivers/net/ethernet/freescale/fman/inc/integrations/P1023/dpaa_integration_ext.h
new file mode 100644
index 0000000..92906db
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/integrations/P1023/dpaa_integration_ext.h
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**
+
+ @File dpaa_integration_ext.h
+
+ @Description P1023 FM external definitions and structures.
+*//***************************************************************************/
+#ifndef __DPAA_INTEGRATION_EXT_H
+#define __DPAA_INTEGRATION_EXT_H
+
+#include "std_ext.h"
+
+
+#define DPAA_VERSION 10
+
+typedef enum e_DpaaSwPortal {
+ e_DPAA_SWPORTAL0 = 0,
+ e_DPAA_SWPORTAL1,
+ e_DPAA_SWPORTAL2,
+ e_DPAA_SWPORTAL_DUMMY_LAST
+} e_DpaaSwPortal;
+
+typedef enum {
+ e_DPAA_DCPORTAL0 = 0,
+ e_DPAA_DCPORTAL2,
+ e_DPAA_DCPORTAL_DUMMY_LAST
+} e_DpaaDcPortal;
+
+#define DPAA_MAX_NUM_OF_SW_PORTALS e_DPAA_SWPORTAL_DUMMY_LAST
+#define DPAA_MAX_NUM_OF_DC_PORTALS e_DPAA_DCPORTAL_DUMMY_LAST
+
+/*****************************************************************************
+ QMAN INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define QM_MAX_NUM_OF_POOL_CHANNELS 3
+#define QM_MAX_NUM_OF_WQ 8
+#define QM_MAX_NUM_OF_SWP_AS 2
+#define QM_MAX_NUM_OF_CGS 64
+#define QM_MAX_NUM_OF_FQIDS (16*MEGABYTE)
+
+typedef enum {
+ e_QM_FQ_CHANNEL_SWPORTAL0 = 0,
+ e_QM_FQ_CHANNEL_SWPORTAL1,
+ e_QM_FQ_CHANNEL_SWPORTAL2,
+
+ e_QM_FQ_CHANNEL_POOL1 = 0x21,
+ e_QM_FQ_CHANNEL_POOL2,
+ e_QM_FQ_CHANNEL_POOL3,
+
+ e_QM_FQ_CHANNEL_FMAN0_SP0 = 0x40,
+ e_QM_FQ_CHANNEL_FMAN0_SP1,
+ e_QM_FQ_CHANNEL_FMAN0_SP2,
+ e_QM_FQ_CHANNEL_FMAN0_SP3,
+ e_QM_FQ_CHANNEL_FMAN0_SP4,
+ e_QM_FQ_CHANNEL_FMAN0_SP5,
+ e_QM_FQ_CHANNEL_FMAN0_SP6,
+
+
+ e_QM_FQ_CHANNEL_CAAM = 0x80
+} e_QmFQChannel;
+
+/*****************************************************************************
+ BMAN INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define BM_MAX_NUM_OF_POOLS 8
+
+/*****************************************************************************
+ SEC INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define SEC_NUM_OF_DECOS 2
+#define SEC_ALL_DECOS_MASK 0x00000003
+#define SEC_RNGB
+#define SEC_NO_ESP_TRAILER_REMOVAL
+
+/*****************************************************************************
+ FM INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define INTG_MAX_NUM_OF_FM 1
+
+/* Ports defines */
+#define FM_MAX_NUM_OF_1G_MACS 2
+#define FM_MAX_NUM_OF_10G_MACS 0
+#define FM_MAX_NUM_OF_MACS (FM_MAX_NUM_OF_1G_MACS + FM_MAX_NUM_OF_10G_MACS)
+#define FM_MAX_NUM_OF_OH_PORTS 5
+
+#define FM_MAX_NUM_OF_1G_RX_PORTS FM_MAX_NUM_OF_1G_MACS
+#define FM_MAX_NUM_OF_10G_RX_PORTS FM_MAX_NUM_OF_10G_MACS
+#define FM_MAX_NUM_OF_RX_PORTS (FM_MAX_NUM_OF_10G_RX_PORTS + FM_MAX_NUM_OF_1G_RX_PORTS)
+
+#define FM_MAX_NUM_OF_1G_TX_PORTS FM_MAX_NUM_OF_1G_MACS
+#define FM_MAX_NUM_OF_10G_TX_PORTS FM_MAX_NUM_OF_10G_MACS
+#define FM_MAX_NUM_OF_TX_PORTS (FM_MAX_NUM_OF_10G_TX_PORTS + FM_MAX_NUM_OF_1G_TX_PORTS)
+
+#define FM_MAX_NUM_OF_MACSECS 1
+
+#define FM_MACSEC_SUPPORT
+
+#define FM_LOW_END_RESTRICTION /* prevents the use of TX port 1 with OP port 0 */
+
+#define FM_PORT_MAX_NUM_OF_EXT_POOLS 4 /**< Number of external BM pools per Rx port */
+#define FM_PORT_MAX_NUM_OF_OBSERVED_EXT_POOLS 2 /**< Number of Offline parsing port external BM pools per Rx port */
+#define FM_PORT_NUM_OF_CONGESTION_GRPS 32 /**< Total number of congestion groups in QM */
+#define FM_MAX_NUM_OF_SUB_PORTALS 7
+
+/* Rams defines */
+#define FM_MURAM_SIZE (64*KILOBYTE)
+#define FM_IRAM_SIZE (32*KILOBYTE)
+#define FM_NUM_OF_CTRL 2
+
+/* PCD defines */
+#define FM_PCD_PLCR_NUM_ENTRIES 32 /**< Total number of policer profiles */
+#define FM_PCD_KG_NUM_OF_SCHEMES 16 /**< Total number of KG schemes */
+#define FM_PCD_MAX_NUM_OF_CLS_PLANS 128 /**< Number of classification plan entries. */
+#define FM_PCD_PRS_SW_PATCHES_SIZE 0x00000240 /**< Number of bytes saved for patches */
+#define FM_PCD_SW_PRS_SIZE 0x00000800 /**< Total size of SW parser area */
+
+/* RTC defines */
+#define FM_RTC_NUM_OF_ALARMS 2
+#define FM_RTC_NUM_OF_PERIODIC_PULSES 2
+#define FM_RTC_NUM_OF_EXT_TRIGGERS 2
+
+/* QMI defines */
+#define QMI_MAX_NUM_OF_TNUMS 15
+
+/* FPM defines */
+#define FM_NUM_OF_FMAN_CTRL_EVENT_REGS 4
+
+/* DMA defines */
+#define DMA_THRESH_MAX_COMMQ 15
+#define DMA_THRESH_MAX_BUF 7
+
+/* BMI defines */
+#define BMI_MAX_NUM_OF_TASKS 64
+#define BMI_MAX_NUM_OF_DMAS 16
+#define BMI_MAX_FIFO_SIZE (FM_MURAM_SIZE)
+#define PORT_MAX_WEIGHT 4
+
+/*****************************************************************************
+ FM MACSEC INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define NUM_OF_RX_SC 16
+#define NUM_OF_TX_SC 16
+
+#define NUM_OF_SA_PER_RX_SC 2
+#define NUM_OF_SA_PER_TX_SC 2
+
+/**************************************************************************//**
+ @Description Enum for inter-module interrupts registration
+*//***************************************************************************/
+
+typedef enum e_FmMacsecEventModules{
+ e_FM_MACSEC_MOD_SC_TX,
+ e_FM_MACSEC_MOD_DUMMY_LAST
+} e_FmMacsecEventModules;
+
+typedef enum e_FmMacsecInterModuleEvent {
+ e_FM_MACSEC_EV_SC_TX,
+ e_FM_MACSEC_EV_ERR_SC_TX,
+ e_FM_MACSEC_EV_DUMMY_LAST
+} e_FmMacsecInterModuleEvent;
+
+#define NUM_OF_INTER_MODULE_EVENTS (NUM_OF_TX_SC * 2)
+
+#define GET_MACSEC_MODULE_EVENT(mod, id, intrType, event) \
+ switch(mod){ \
+ case e_FM_MACSEC_MOD_SC_TX: \
+ event = (intrType == e_FM_INTR_TYPE_ERR) ? \
+ e_FM_MACSEC_EV_ERR_SC_TX: \
+ e_FM_MACSEC_EV_SC_TX; \
+ event += (uint8_t)(2 * id);break; \
+ break; \
+ default:event = e_FM_MACSEC_EV_DUMMY_LAST; \
+ break;}
+
+
+/* 1023 unique features */
+#define FM_QMI_NO_ECC_EXCEPTIONS
+#define FM_CSI_CFED_LIMIT
+#define FM_PEDANTIC_DMA
+#define FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+#define FM_FIFO_ALLOCATION_ALG
+#define FM_DEQ_PIPELINE_PARAMS_FOR_OP
+#define FM_HAS_TOTAL_DMAS
+#define FM_KG_NO_IPPID_SUPPORT
+#define FM_NO_GUARANTEED_RESET_VALUES
+#define FM_MAC_RESET
+
+/* FM erratas */
+#define FM_RX_PREAM_4_ERRATA_DTSEC_A001
+#define FM_MAGIC_PACKET_UNRECOGNIZED_ERRATA_DTSEC2 /* No implementation, Out of LLD scope */
+
+#define FM_DEBUG_TRACE_FMAN_A004 /* No implementation, Out of LLD scope */
+#define FM_INT_BUF_LEAK_FMAN_A005 /* No implementation, Out of LLD scope. App must avoid S/G */
+
+#define FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839
+
+/* #define FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */
+
+/*
+TKT056919 - axi12axi0 can hang if read request follows the single byte write on the very next cycle
+TKT038900 - FM dma lockup occur due to AXI slave protocol violation
+*/
+#define FM_LOCKUP_ALIGNMENT_ERRATA_FMAN_SW004
+
+
+#endif /* __DPAA_INTEGRATION_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/integrations/P1023/part_ext.h b/drivers/net/ethernet/freescale/fman/inc/integrations/P1023/part_ext.h
new file mode 100644
index 0000000..6814d5f
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/integrations/P1023/part_ext.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+
+ @File part_ext.h
+
+ @Description Definitions for the part (integration) module.
+*//***************************************************************************/
+
+#ifndef __PART_EXT_H
+#define __PART_EXT_H
+
+#include "std_ext.h"
+#include "part_integration_ext.h"
+
+
+#if !(defined(MPC8306) || \
+ defined(MPC8309) || \
+ defined(MPC834x) || \
+ defined(MPC836x) || \
+ defined(MPC832x) || \
+ defined(MPC837x) || \
+ defined(MPC8568) || \
+ defined(MPC8569) || \
+ defined(P1020) || \
+ defined(P1021) || \
+ defined(P1022) || \
+ defined(P1023) || \
+ defined(P2020) || \
+ defined(P3041) || \
+ defined(P4080) || \
+ defined(P5020) || \
+ defined(MSC814x))
+#error "unable to proceed without chip-definition"
+#endif
+
+
+/**************************************************************************//*
+ @Description Part data structure - must be contained in any integration
+ data structure.
+*//***************************************************************************/
+typedef struct t_Part
+{
+ uint64_t (* f_GetModuleBase)(t_Handle h_Part, e_ModuleId moduleId);
+ /**< Returns the address of the module's memory map base. */
+ e_ModuleId (* f_GetModuleIdByBase)(t_Handle h_Part, uint64_t baseAddress);
+ /**< Returns the module's ID according to its memory map base. */
+} t_Part;
+
+
+#endif /* __PART_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/integrations/P1023/part_integration_ext.h b/drivers/net/ethernet/freescale/fman/inc/integrations/P1023/part_integration_ext.h
new file mode 100644
index 0000000..e838283
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/integrations/P1023/part_integration_ext.h
@@ -0,0 +1,635 @@
+/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**************************************************************************//**
+ @File part_integration_ext.h
+
+ @Description P1023 external definitions and structures.
+*//***************************************************************************/
+#ifndef __PART_INTEGRATION_EXT_H
+#define __PART_INTEGRATION_EXT_H
+
+#include "std_ext.h"
+#include "dpaa_integration_ext.h"
+
+
+/**************************************************************************//**
+ @Group 1023_chip_id P1023 Application Programming Interface
+
+ @Description P1023 Chip functions,definitions and enums.
+
+ @{
+*//***************************************************************************/
+
+#define INTG_MAX_NUM_OF_CORES 2
+
+
+/**************************************************************************//**
+ @Description Module types.
+*//***************************************************************************/
+typedef enum e_ModuleId
+{
+ e_MODULE_ID_LAW, /**< Local Access module */
+ e_MODULE_ID_ECM, /**< e500 Coherency Module */
+ e_MODULE_ID_DDR, /**< DDR memory controller */
+ e_MODULE_ID_I2C_1, /**< I2C 1 */
+ e_MODULE_ID_I2C_2, /**< I2C 1 */
+ e_MODULE_ID_DUART_1, /**< DUART module 1 */
+ e_MODULE_ID_DUART_2, /**< DUART module 2 */
+ e_MODULE_ID_LBC, /**< Local bus memory controller module */
+ e_MODULE_ID_PCIE_1, /**< PCI Express 1 controller module */
+ e_MODULE_ID_PCIE_ATMU_1, /**< PCI 1 ATMU Window */
+ e_MODULE_ID_PCIE_2, /**< PCI Express 2 controller module */
+ e_MODULE_ID_PCIE_ATMU_2, /**< PCI 2 ATMU Window */
+ e_MODULE_ID_PCIE_3, /**< PCI Express 3 controller module */
+ e_MODULE_ID_PCIE_ATMU_3, /**< PCI 3 ATMU Window */
+ e_MODULE_ID_MSI, /**< MSI registers */
+ e_MODULE_ID_L2_SRAM, /**< L2/SRAM Memory-Mapped controller module */
+ e_MODULE_ID_DMA_1, /**< DMA controller 1 */
+ e_MODULE_ID_DMA_2, /**< DMA controller 2 */
+ e_MODULE_ID_EPIC, /**< Programmable interrupt controller */
+ e_MODULE_ID_ESPI, /**< ESPI module */
+ e_MODULE_ID_GPIO, /**< General Purpose I/O */
+ e_MODULE_ID_SEC_GEN, /**< SEC 4.0 General registers */
+ e_MODULE_ID_SEC_QI, /**< SEC 4.0 QI registers */
+ e_MODULE_ID_SEC_JQ0, /**< SEC 4.0 JQ-0 registers */
+ e_MODULE_ID_SEC_JQ1, /**< SEC 4.0 JQ-1 registers */
+ e_MODULE_ID_SEC_JQ2, /**< SEC 4.0 JQ-2 registers */
+ e_MODULE_ID_SEC_JQ3, /**< SEC 4.0 JQ-3 registers */
+ e_MODULE_ID_SEC_RTIC, /**< SEC 4.0 RTIC registers */
+ e_MODULE_ID_SEC_DECO0_CCB0, /**< SEC 4.0 DECO-0/CCB-0 registers */
+ e_MODULE_ID_SEC_DECO1_CCB1, /**< SEC 4.0 DECO-1/CCB-1 registers */
+ e_MODULE_ID_SEC_DECO2_CCB2, /**< SEC 4.0 DECO-2/CCB-2 registers */
+ e_MODULE_ID_SEC_DECO3_CCB3, /**< SEC 4.0 DECO-3/CCB-3 registers */
+ e_MODULE_ID_SEC_DECO4_CCB4, /**< SEC 4.0 DECO-4/CCB-4 registers */
+ e_MODULE_ID_USB_DR_1, /**< USB 2.0 module 1 */
+ e_MODULE_ID_USB_DR_2, /**< USB 2.0 module 2 */
+ e_MODULE_ID_ETSEC_MII_MNG, /**< MII MNG registers */
+ e_MODULE_ID_ETSEC_1, /**< ETSEC module 1 */
+ e_MODULE_ID_ETSEC_2, /**< ETSEC module 2 */
+ e_MODULE_ID_GUTS, /**< Serial DMA */
+ e_MODULE_ID_PM, /**< Performance Monitor module */
+ e_MODULE_ID_QM, /**< Queue manager module */
+ e_MODULE_ID_BM, /**< Buffer manager module */
+ e_MODULE_ID_QM_CE_PORTAL,
+ e_MODULE_ID_QM_CI_PORTAL,
+ e_MODULE_ID_BM_CE_PORTAL,
+ e_MODULE_ID_BM_CI_PORTAL,
+ e_MODULE_ID_FM, /**< Frame manager #1 module */
+ e_MODULE_ID_FM_RTC, /**< FM Real-Time-Clock */
+ e_MODULE_ID_FM_MURAM, /**< FM Multi-User-RAM */
+ e_MODULE_ID_FM_BMI, /**< FM BMI block */
+ e_MODULE_ID_FM_QMI, /**< FM QMI block */
+ e_MODULE_ID_FM_PRS, /**< FM parser block */
+ e_MODULE_ID_FM_PORT_HO0, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM_PORT_HO1, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM_PORT_HO2, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM_PORT_HO3, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM_PORT_HO4, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM_PORT_1GRx0, /**< FM Rx 1G MAC port block */
+ e_MODULE_ID_FM_PORT_1GRx1, /**< FM Rx 1G MAC port block */
+ e_MODULE_ID_FM_PORT_1GTx0, /**< FM Tx 1G MAC port block */
+ e_MODULE_ID_FM_PORT_1GTx1, /**< FM Tx 1G MAC port block */
+ e_MODULE_ID_FM_PLCR, /**< FM Policer */
+ e_MODULE_ID_FM_KG, /**< FM Keygen */
+ e_MODULE_ID_FM_DMA, /**< FM DMA */
+ e_MODULE_ID_FM_FPM, /**< FM FPM */
+ e_MODULE_ID_FM_IRAM, /**< FM Instruction-RAM */
+ e_MODULE_ID_FM_1GMDIO0, /**< FM 1G MDIO MAC 0*/
+ e_MODULE_ID_FM_1GMDIO1, /**< FM 1G MDIO MAC 1*/
+ e_MODULE_ID_FM_PRS_IRAM, /**< FM SW-parser Instruction-RAM */
+ e_MODULE_ID_FM_RISC0, /**< FM risc #0 */
+ e_MODULE_ID_FM_RISC1, /**< FM risc #1 */
+ e_MODULE_ID_FM_1GMAC0, /**< FM 1G MAC #0 */
+ e_MODULE_ID_FM_1GMAC1, /**< FM 1G MAC #1 */
+ e_MODULE_ID_FM_MACSEC, /**< FM MACSEC */
+
+ e_MODULE_ID_DUMMY_LAST
+} e_ModuleId;
+
+#define NUM_OF_MODULES e_MODULE_ID_DUMMY_LAST
+
+
+#define P1023_OFFSET_LAW 0x00000C08
+#define P1023_OFFSET_ECM 0x00001000
+#define P1023_OFFSET_DDR 0x00002000
+#define P1023_OFFSET_I2C1 0x00003000
+#define P1023_OFFSET_I2C2 0x00003100
+#define P1023_OFFSET_DUART1 0x00004500
+#define P1023_OFFSET_DUART2 0x00004600
+#define P1023_OFFSET_LBC 0x00005000
+#define P1023_OFFSET_ESPI 0x00007000
+#define P1023_OFFSET_PCIE2 0x00009000
+#define P1023_OFFSET_PCIE2_ATMU 0x00009C00
+#define P1023_OFFSET_PCIE1 0x0000A000
+#define P1023_OFFSET_PCIE1_ATMU 0x0000AC00
+#define P1023_OFFSET_PCIE3 0x0000B000
+#define P1023_OFFSET_PCIE3_ATMU 0x0000BC00
+#define P1023_OFFSET_DMA2 0x0000C100
+#define P1023_OFFSET_GPIO 0x0000F000
+#define P1023_OFFSET_L2_SRAM 0x00020000
+#define P1023_OFFSET_DMA1 0x00021100
+#define P1023_OFFSET_USB1 0x00022000
+#define P1023_OFFSET_SEC_GEN 0x00030000
+#define P1023_OFFSET_SEC_JQ0 0x00031000
+#define P1023_OFFSET_SEC_JQ1 0x00032000
+#define P1023_OFFSET_SEC_JQ2 0x00033000
+#define P1023_OFFSET_SEC_JQ3 0x00034000
+#define P1023_OFFSET_SEC_RTIC 0x00036000
+#define P1023_OFFSET_SEC_QI 0x00037000
+#define P1023_OFFSET_SEC_DECO0_CCB0 0x00038000
+#define P1023_OFFSET_SEC_DECO1_CCB1 0x00039000
+#define P1023_OFFSET_SEC_DECO2_CCB2 0x0003a000
+#define P1023_OFFSET_SEC_DECO3_CCB3 0x0003b000
+#define P1023_OFFSET_SEC_DECO4_CCB4 0x0003c000
+#define P1023_OFFSET_PIC 0x00040000
+#define P1023_OFFSET_MSI 0x00041600
+#define P1023_OFFSET_AXI 0x00081000
+#define P1023_OFFSET_QM 0x00088000
+#define P1023_OFFSET_BM 0x0008A000
+#define P1022_OFFSET_PM 0x000E1000
+
+#define P1023_OFFSET_GUTIL 0x000E0000
+#define P1023_OFFSET_PM 0x000E1000
+#define P1023_OFFSET_DEBUG 0x000E2000
+#define P1023_OFFSET_SERDES 0x000E3000
+#define P1023_OFFSET_ROM 0x000F0000
+#define P1023_OFFSET_FM 0x00100000
+
+#define P1023_OFFSET_FM_MURAM (P1023_OFFSET_FM + 0x00000000)
+#define P1023_OFFSET_FM_BMI (P1023_OFFSET_FM + 0x00080000)
+#define P1023_OFFSET_FM_QMI (P1023_OFFSET_FM + 0x00080400)
+#define P1023_OFFSET_FM_PRS (P1023_OFFSET_FM + 0x00080800)
+#define P1023_OFFSET_FM_PORT_HO0 (P1023_OFFSET_FM + 0x00081000)
+#define P1023_OFFSET_FM_PORT_HO1 (P1023_OFFSET_FM + 0x00082000)
+#define P1023_OFFSET_FM_PORT_HO2 (P1023_OFFSET_FM + 0x00083000)
+#define P1023_OFFSET_FM_PORT_HO3 (P1023_OFFSET_FM + 0x00084000)
+#define P1023_OFFSET_FM_PORT_HO4 (P1023_OFFSET_FM + 0x00085000)
+#define P1023_OFFSET_FM_PORT_1GRX0 (P1023_OFFSET_FM + 0x00088000)
+#define P1023_OFFSET_FM_PORT_1GRX1 (P1023_OFFSET_FM + 0x00089000)
+#define P1023_OFFSET_FM_PORT_1GTX0 (P1023_OFFSET_FM + 0x000A8000)
+#define P1023_OFFSET_FM_PORT_1GTX1 (P1023_OFFSET_FM + 0x000A9000)
+#define P1023_OFFSET_FM_PLCR (P1023_OFFSET_FM + 0x000C0000)
+#define P1023_OFFSET_FM_KG (P1023_OFFSET_FM + 0x000C1000)
+#define P1023_OFFSET_FM_DMA (P1023_OFFSET_FM + 0x000C2000)
+#define P1023_OFFSET_FM_FPM (P1023_OFFSET_FM + 0x000C3000)
+#define P1023_OFFSET_FM_IRAM (P1023_OFFSET_FM + 0x000C4000)
+#define P1023_OFFSET_FM_PRS_IRAM (P1023_OFFSET_FM + 0x000C7000)
+#define P1023_OFFSET_FM_RISC0 (P1023_OFFSET_FM + 0x000D0000)
+#define P1023_OFFSET_FM_RISC1 (P1023_OFFSET_FM + 0x000D0400)
+#define P1023_OFFSET_FM_MACSEC (P1023_OFFSET_FM + 0x000D8000)
+#define P1023_OFFSET_FM_1GMAC0 (P1023_OFFSET_FM + 0x000E0000)
+#define P1023_OFFSET_FM_1GMDIO0 (P1023_OFFSET_FM + 0x000E1120)
+#define P1023_OFFSET_FM_1GMAC1 (P1023_OFFSET_FM + 0x000E2000)
+#define P1023_OFFSET_FM_1GMDIO1 (P1023_OFFSET_FM + 0x000E3000)
+#define P1023_OFFSET_FM_RTC (P1023_OFFSET_FM + 0x000FE000)
+
+/* Offsets relative to QM or BM portals base */
+#define P1023_OFFSET_PORTALS_CE_AREA 0x00000000 /* cache enabled area */
+#define P1023_OFFSET_PORTALS_CI_AREA 0x00100000 /* cache inhibited area */
+
+#define P1023_OFFSET_PORTALS_CE(portal) (P1023_OFFSET_PORTALS_CE_AREA + 0x4000 * (portal))
+#define P1023_OFFSET_PORTALS_CI(portal) (P1023_OFFSET_PORTALS_CI_AREA + 0x1000 * (portal))
+
+/**************************************************************************//**
+ @Description Transaction source ID (for memory controllers error reporting).
+*//***************************************************************************/
+typedef enum e_TransSrc
+{
+ e_TRANS_SRC_PCIE_2 = 0x01, /**< PCIe port 2 */
+ e_TRANS_SRC_PCIE_1 = 0x02, /**< PCIe port 1 */
+ e_TRANS_SRC_PCIE_3 = 0x03, /**< PCIe port 3 */
+ e_TRANS_SRC_LBC = 0x04, /**< Enhanced local bus */
+ e_TRANS_SRC_DPAA_SW_PORTALS = 0x0E, /**< DPAA software portals or SRAM */
+ e_TRANS_SRC_DDR = 0x0F, /**< DDR controller */
+ e_TRANS_SRC_CORE_INS_FETCH = 0x10, /**< Processor (instruction) */
+ e_TRANS_SRC_CORE_DATA = 0x11, /**< Processor (data) */
+ e_TRANS_SRC_DMA = 0x15 /**< DMA */
+} e_TransSrc;
+
+/**************************************************************************//**
+ @Description Local Access Window Target interface ID
+*//***************************************************************************/
+typedef enum e_P1023LawTargetId
+{
+ e_P1023_LAW_TARGET_PCIE_2 = 0x01, /**< PCI Express 2 target interface */
+ e_P1023_LAW_TARGET_PCIE_1 = 0x02, /**< PCI Express 1 target interface */
+ e_P1023_LAW_TARGET_PCIE_3 = 0x03, /**< PCI Express 3 target interface */
+ e_P1023_LAW_TARGET_LBC = 0x04, /**< Local bus target interface */
+ e_P1023_LAW_TARGET_QM_PORTALS = 0x0E, /**< Queue Manager Portals */
+ e_P1023_LAW_TARGET_BM_PORTALS = 0x0E, /**< Buffer Manager Portals */
+ e_P1023_LAW_TARGET_SRAM = 0x0E, /**< SRAM scratchpad */
+ e_P1023_LAW_TARGET_DDR = 0x0F, /**< DDR target interface */
+ e_P1023_LAW_TARGET_NONE = 0xFF /**< Invalid target interface */
+} e_P1023LawTargetId;
+
+
+/**************************************************************************//**
+ @Group 1023_init_grp P1023 Initialization Unit
+
+ @Description P1023 initialization unit API functions, definitions and enums
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Description Part ID and revision number
+*//***************************************************************************/
+typedef enum e_P1023DeviceName
+{
+ e_P1023_REV_INVALID = 0x00000000, /**< Invalid revision */
+ e_SC1023_REV_1_0 = (int)0x80FC0010, /**< SC1023 rev 1.0 */
+ e_SC1023_REV_1_1 = (int)0x80FC0011, /**< SC1023 rev 1.1 */
+ e_P1023_REV_1_0 = (int)0x80FE0010, /**< P1023 rev 1.0 with security */
+ e_P1023_REV_1_1 = (int)0x80FE0011, /**< P1023 rev 1.1 with security */
+ e_P1017_REV_1_1 = (int)0x80FF0011, /**< P1017 rev 1.1 with security */
+ e_P1023_REV_1_0_NO_SEC = (int)0x80F60010, /**< P1023 rev 1.0 without security */
+ e_P1023_REV_1_1_NO_SEC = (int)0x80F60011, /**< P1023 rev 1.1 without security */
+ e_P1017_REV_1_1_NO_SEC = (int)0x80F70011 /**< P1017 rev 1.1 without security */
+} e_P1023DeviceName;
+
+/**************************************************************************//**
+ @Description structure representing P1023 initialization parameters
+*//***************************************************************************/
+typedef struct t_P1023Params
+{
+ uintptr_t ccsrBaseAddress; /**< CCSR base address (virtual) */
+ uintptr_t bmPortalsBaseAddress; /**< Portals base address (virtual) */
+ uintptr_t qmPortalsBaseAddress; /**< Portals base address (virtual) */
+} t_P1023Params;
+
+/**************************************************************************//**
+ @Function P1023_ConfigAndInit
+
+ @Description General initiation of the chip registers.
+
+ @Param[in] p_P1023Params - A pointer to data structure of parameters
+
+ @Return A handle to the P1023 data structure.
+*//***************************************************************************/
+t_Handle P1023_ConfigAndInit(t_P1023Params *p_P1023Params);
+
+/**************************************************************************//**
+ @Function P1023_Free
+
+ @Description Free all resources.
+
+ @Param h_P1023 - (In) The handle of the initialized P1023 object.
+
+ @Return E_OK on success; Other value otherwise.
+*//***************************************************************************/
+t_Error P1023_Free(t_Handle h_P1023);
+
+/**************************************************************************//**
+ @Function P1023_GetRevInfo
+
+ @Description This routine enables access to chip and revision information.
+
+ @Param[in] gutilBase - Base address of P1023 GUTIL registers.
+
+ @Return Part ID and revision.
+*//***************************************************************************/
+e_P1023DeviceName P1023_GetRevInfo(uintptr_t gutilBase);
+
+/**************************************************************************//**
+ @Function P1023_GetE500Factor
+
+ @Description Returns E500 core clock multiplication factor.
+
+ @Param[in] gutilBase - Base address of P1023 GUTIL registers.
+ @Param[in] coreId - Id of the requested core.
+ @Param[out] p_E500MulFactor - Returns E500 to CCB multification factor.
+ @Param[out] p_E500DivFactor - Returns E500 to CCB division factor.
+
+ @Return E_OK on success; Other value otherwise.
+*
+*//***************************************************************************/
+t_Error P1023_GetE500Factor(uintptr_t gutilBase,
+ uint32_t coreId,
+ uint32_t *p_E500MulFactor,
+ uint32_t *p_E500DivFactor);
+
+/**************************************************************************//**
+ @Function P1023_GetFmFactor
+
+ @Description returns FM multiplication factors. (This value is returned using
+ two parameters to avoid using float parameter).
+
+ @Param[in] gutilBase - Base address of P1023 GUTIL registers.
+ @Param[out] p_FmMulFactor - returns E500 to CCB multification factor.
+ @Param[out] p_FmDivFactor - returns E500 to CCB division factor.
+
+ @Return E_OK on success; Other value otherwise.
+*//***************************************************************************/
+t_Error P1023_GetFmFactor(uintptr_t gutilBase, uint32_t *p_FmMulFactor, uint32_t *p_FmDivFactor);
+
+/**************************************************************************//**
+ @Function P1023_GetCcbFactor
+
+ @Description returns system multiplication factor.
+
+ @Param[in] gutilBase - Base address of P1023 GUTIL registers.
+
+ @Return System multiplication factor.
+*//***************************************************************************/
+uint32_t P1023_GetCcbFactor(uintptr_t gutilBase);
+
+#if 0
+/**************************************************************************//**
+ @Function P1023_GetDdrFactor
+
+ @Description returns the multiplication factor of the clock in for the DDR clock .
+ Note: assumes the ddr_in_clk is identical to the sys_in_clk
+
+ @Param[in] gutilBase - Base address of P1023 GUTIL registers.
+ @Param p_DdrMulFactor - returns DDR in clk multification factor.
+ @Param p_DdrDivFactor - returns DDR division factor.
+
+ @Return E_OK on success; Other value otherwise..
+*//***************************************************************************/
+t_Error P1023_GetDdrFactor( uintptr_t gutilBase,
+ uint32_t *p_DdrMulFactor,
+ uint32_t *p_DdrDivFactor);
+
+/**************************************************************************//**
+ @Function P1023_GetDdrType
+
+ @Description returns the multiplication factor of the clock in for the DDR clock .
+
+ @Param[in] gutilBase - Base address of P1023 GUTIL registers.
+ @Param p_DdrType - (Out) returns DDR type DDR1/DDR2/DDR3.
+
+ @Return E_OK on success; Other value otherwise.
+*//***************************************************************************/
+t_Error P1023_GetDdrType(uintptr_t gutilBase, e_DdrType *p_DdrType );
+#endif
+
+/** @} */ /* end of 1023_init_grp group */
+/** @} */ /* end of 1023_grp group */
+
+#define CORE_E500V2
+
+#if 0 /* using unified values */
+/*****************************************************************************
+ INTEGRATION-SPECIFIC MODULE CODES
+******************************************************************************/
+#define MODULE_UNKNOWN 0x00000000
+#define MODULE_MEM 0x00010000
+#define MODULE_MM 0x00020000
+#define MODULE_CORE 0x00030000
+#define MODULE_P1023 0x00040000
+#define MODULE_MII 0x00050000
+#define MODULE_PM 0x00060000
+#define MODULE_MMU 0x00070000
+#define MODULE_PIC 0x00080000
+#define MODULE_L2_CACHE 0x00090000
+#define MODULE_DUART 0x000a0000
+#define MODULE_SERDES 0x000b0000
+#define MODULE_PIO 0x000c0000
+#define MODULE_QM 0x000d0000
+#define MODULE_BM 0x000e0000
+#define MODULE_SEC 0x000f0000
+#define MODULE_FM 0x00100000
+#define MODULE_FM_MURAM 0x00110000
+#define MODULE_FM_PCD 0x00120000
+#define MODULE_FM_RTC 0x00130000
+#define MODULE_FM_MAC 0x00140000
+#define MODULE_FM_PORT 0x00150000
+#define MODULE_FM_MACSEC 0x00160000
+#define MODULE_FM_MACSEC_SECY 0x00170000
+#define MODULE_FM_SP 0x00280000
+#define MODULE_ECM 0x00190000
+#define MODULE_DMA 0x001a0000
+#define MODULE_DDR 0x001b0000
+#define MODULE_LAW 0x001c0000
+#define MODULE_LBC 0x001d0000
+#define MODULE_I2C 0x001e0000
+#define MODULE_ESPI 0x001f0000
+#define MODULE_PCI 0x00200000
+#define MODULE_DPA_PORT 0x00210000
+#define MODULE_USB 0x00220000
+#endif /* using unified values */
+
+/*****************************************************************************
+ LBC INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+/**************************************************************************//**
+ @Group lbc_exception_grp LBC Exception Unit
+
+ @Description LBC Exception unit API functions, definitions and enums
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Anchor lbc_exbm
+
+ @Collection LBC Errors Bit Mask
+
+ These errors are reported through the exceptions callback..
+ The values can be or'ed in any combination in the errors mask
+ parameter of the errors report structure.
+
+ These errors can also be passed as a bit-mask to
+ LBC_EnableErrorChecking() or LBC_DisableErrorChecking(),
+ for enabling or disabling error checking.
+ @{
+*//***************************************************************************/
+#define LBC_ERR_BUS_MONITOR 0x80000000 /**< Bus monitor error */
+#define LBC_ERR_PARITY_ECC 0x20000000 /**< Parity error for GPCM/UPM */
+#define LBC_ERR_WRITE_PROTECT 0x04000000 /**< Write protection error */
+#define LBC_ERR_CHIP_SELECT 0x00080000 /**< Unrecognized chip select */
+
+#define LBC_ERR_ALL (LBC_ERR_BUS_MONITOR | LBC_ERR_PARITY_ECC | \
+ LBC_ERR_WRITE_PROTECT | LBC_ERR_CHIP_SELECT)
+ /**< All possible errors */
+/* @} */
+/** @} */ /* end of lbc_exception_grp group */
+
+#define LBC_NUM_OF_BANKS 2
+#define LBC_MAX_CS_SIZE 0x0000000100000000LL
+#define LBC_ATOMIC_OPERATION_SUPPORT
+#define LBC_PARITY_SUPPORT
+#define LBC_ADDRESS_SHIFT_SUPPORT
+#define LBC_ADDRESS_HOLD_TIME_CTRL
+#define LBC_HIGH_CLK_DIVIDERS
+#define LBC_FCM_AVAILABLE
+
+
+/*****************************************************************************
+ LAW INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define LAW_ARCH_CCB
+#define LAW_NUM_OF_WINDOWS 12
+#define LAW_MIN_WINDOW_SIZE 0x0000000000001000LL /**< 4KB */
+#define LAW_MAX_WINDOW_SIZE 0x0000001000000000LL /**< 32GB */
+
+
+/*****************************************************************************
+ SPI INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define SPI_NUM_OF_CONTROLLERS 1
+
+/*****************************************************************************
+ PCI/PCIe INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+
+#define PCI_MAX_INBOUND_WINDOWS_NUM 4
+#define PCI_MAX_OUTBOUND_WINDOWS_NUM 5
+
+/**************************************************************************//**
+ @Description Target interface of an inbound window
+*//***************************************************************************/
+typedef enum e_PciTargetInterface
+{
+ e_PCI_TARGET_PCIE_2 = 0x1, /**< PCI Express target interface 2 */
+ e_PCI_TARGET_PCIE_1 = 0x2, /**< PCI Express target interface 1 */
+ e_PCI_TARGET_PCIE_3 = 0x3, /**< PCI Express target interface 3 */
+ e_PCI_TARGET_LOCAL_MEMORY = 0xF /**< Local Memory (DDR SDRAM, Local Bus, SRAM) target interface */
+
+} e_PciTargetInterface;
+
+/*****************************************************************************
+ DDR INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define DDR_NUM_OF_VALID_CS 2
+
+/*****************************************************************************
+ SEC INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define SEC_ERRATA_STAT_REGS_UNUSABLE
+
+/*****************************************************************************
+ DMA INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define DMA_NUM_OF_CONTROLLERS 2
+
+
+
+
+/*****************************************************************************
+ 1588 INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define PTP_V2
+
+/**************************************************************************//**
+ @Function P1023_GetMuxControlReg
+
+ @Description Returns the value of PMUXCR (Alternate Function Signal Multiplex
+ Control Register)
+
+ @Param[in] gutilBase - Base address of P1023 GUTIL registers.
+
+ @Return Value of PMUXCR
+*//***************************************************************************/
+uint32_t P1023_GetMuxControlReg(uintptr_t gutilBase);
+
+/**************************************************************************//**
+ @Function P1023_SetMuxControlReg
+
+ @Description Sets the value of PMUXCR (Alternate Function Signal Multiplex
+ Control Register)
+
+ @Param[in] gutilBase - Base address of P1023 GUTIL registers.
+ @Param[in] val - the new value for PMUXCR.
+
+ @Return None
+*//***************************************************************************/
+void P1023_SetMuxControlReg(uintptr_t gutilBase, uint32_t val);
+
+/**************************************************************************//**
+ @Function P1023_GetDeviceDisableStatusRegister
+
+ @Description Returns the value of DEVDISR (Device Disable Register)
+
+ @Param[in] gutilBase - Base address of P1023 GUTIL registers.
+
+ @Return Value of DEVDISR
+*//***************************************************************************/
+uint32_t P1023_GetDeviceDisableStatusRegister(uintptr_t gutilBase);
+
+/**************************************************************************//**
+ @Function P1023_GetPorDeviceStatusRegister
+
+ @Description Returns the value of POR Device Status Register
+
+ @Param[in] gutilBase - Base address of P1023 GUTIL registers.
+
+ @Return POR Device Status Register
+*//***************************************************************************/
+uint32_t P1023_GetPorDeviceStatusRegister(uintptr_t gutilBase);
+
+/**************************************************************************//**
+ @Function P1023_GetPorBootModeStatusRegister
+
+ @Description Returns the value of POR Boot Mode Status Register
+
+ @Param[in] gutilBase - Base address of P1023 GUTIL registers.
+
+ @Return POR Boot Mode Status Register value
+*//***************************************************************************/
+uint32_t P1023_GetPorBootModeStatusRegister(uintptr_t gutilBase);
+
+
+#define PORDEVSR_SGMII1_DIS 0x10000000
+#define PORDEVSR_SGMII2_DIS 0x08000000
+#define PORDEVSR_ECP1 0x02000000
+#define PORDEVSR_IO_SEL 0x00780000
+#define PORDEVSR_IO_SEL_SHIFT 19
+#define PORBMSR_HA 0x00070000
+#define PORBMSR_HA_SHIFT 16
+
+#define DEVDISR_QM_BM 0x80000000
+#define DEVDISR_FM 0x40000000
+#define DEVDISR_PCIE1 0x20000000
+#define DEVDISR_MAC_SEC 0x10000000
+#define DEVDISR_ELBC 0x08000000
+#define DEVDISR_PCIE2 0x04000000
+#define DEVDISR_PCIE3 0x02000000
+#define DEVDISR_CAAM 0x01000000
+#define DEVDISR_USB0 0x00800000
+#define DEVDISR_1588 0x00020000
+#define DEVDISR_CORE0 0x00008000
+#define DEVDISR_TB0 0x00004000
+#define DEVDISR_CORE1 0x00002000
+#define DEVDISR_TB1 0x00001000
+#define DEVDISR_DMA1 0x00000400
+#define DEVDISR_DMA2 0x00000200
+#define DEVDISR_DDR 0x00000010
+#define DEVDISR_TSEC1 0x00000080
+#define DEVDISR_TSEC2 0x00000040
+#define DEVDISR_SPI 0x00000008
+#define DEVDISR_I2C 0x00000004
+#define DEVDISR_DUART 0x00000002
+
+
+#endif /* __PART_INTEGRATION_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/integrations/P3040_P4080_P5020/dpaa_integration_ext.h b/drivers/net/ethernet/freescale/fman/inc/integrations/P3040_P4080_P5020/dpaa_integration_ext.h
new file mode 100644
index 0000000..257acb0
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/integrations/P3040_P4080_P5020/dpaa_integration_ext.h
@@ -0,0 +1,266 @@
+/* Copyright (c) 2009-2012 Freescale Semiconductor, Inc
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**************************************************************************//**
+ @File dpaa_integration_ext.h
+
+ @Description P3040/P4080/P5020 FM external definitions and structures.
+*//***************************************************************************/
+#ifndef __DPAA_INTEGRATION_EXT_H
+#define __DPAA_INTEGRATION_EXT_H
+
+#include "std_ext.h"
+
+
+#define DPAA_VERSION 10
+
+typedef enum {
+ e_DPAA_SWPORTAL0 = 0,
+ e_DPAA_SWPORTAL1,
+ e_DPAA_SWPORTAL2,
+ e_DPAA_SWPORTAL3,
+ e_DPAA_SWPORTAL4,
+ e_DPAA_SWPORTAL5,
+ e_DPAA_SWPORTAL6,
+ e_DPAA_SWPORTAL7,
+ e_DPAA_SWPORTAL8,
+ e_DPAA_SWPORTAL9,
+ e_DPAA_SWPORTAL_DUMMY_LAST
+} e_DpaaSwPortal;
+
+typedef enum {
+ e_DPAA_DCPORTAL0 = 0,
+ e_DPAA_DCPORTAL1,
+ e_DPAA_DCPORTAL2,
+ e_DPAA_DCPORTAL3,
+ e_DPAA_DCPORTAL4,
+ e_DPAA_DCPORTAL_DUMMY_LAST
+} e_DpaaDcPortal;
+
+#define DPAA_MAX_NUM_OF_SW_PORTALS e_DPAA_SWPORTAL_DUMMY_LAST
+#define DPAA_MAX_NUM_OF_DC_PORTALS e_DPAA_DCPORTAL_DUMMY_LAST
+
+/*****************************************************************************
+ QMan INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define QM_MAX_NUM_OF_POOL_CHANNELS 15 /**< Total number of channels, dedicated and pool */
+#define QM_MAX_NUM_OF_WQ 8 /**< Number of work queues per channel */
+#define QM_MAX_NUM_OF_SWP_AS 4
+#define QM_MAX_NUM_OF_CGS 256 /**< Number of congestion groups */
+#define QM_MAX_NUM_OF_FQIDS (16 * MEGABYTE) /**< FQIDs range - 24 bits */
+
+/**************************************************************************//**
+ @Description Work Queue Channel assignments in QMan.
+*//***************************************************************************/
+typedef enum
+{
+ e_QM_FQ_CHANNEL_SWPORTAL0 = 0, /**< Dedicated channels serviced by software portals 0 to 9 */
+ e_QM_FQ_CHANNEL_SWPORTAL1,
+ e_QM_FQ_CHANNEL_SWPORTAL2,
+ e_QM_FQ_CHANNEL_SWPORTAL3,
+ e_QM_FQ_CHANNEL_SWPORTAL4,
+ e_QM_FQ_CHANNEL_SWPORTAL5,
+ e_QM_FQ_CHANNEL_SWPORTAL6,
+ e_QM_FQ_CHANNEL_SWPORTAL7,
+ e_QM_FQ_CHANNEL_SWPORTAL8,
+ e_QM_FQ_CHANNEL_SWPORTAL9,
+
+ e_QM_FQ_CHANNEL_POOL1 = 0x21, /**< Pool channels that can be serviced by any of the software portals */
+ e_QM_FQ_CHANNEL_POOL2,
+ e_QM_FQ_CHANNEL_POOL3,
+ e_QM_FQ_CHANNEL_POOL4,
+ e_QM_FQ_CHANNEL_POOL5,
+ e_QM_FQ_CHANNEL_POOL6,
+ e_QM_FQ_CHANNEL_POOL7,
+ e_QM_FQ_CHANNEL_POOL8,
+ e_QM_FQ_CHANNEL_POOL9,
+ e_QM_FQ_CHANNEL_POOL10,
+ e_QM_FQ_CHANNEL_POOL11,
+ e_QM_FQ_CHANNEL_POOL12,
+ e_QM_FQ_CHANNEL_POOL13,
+ e_QM_FQ_CHANNEL_POOL14,
+ e_QM_FQ_CHANNEL_POOL15,
+
+ e_QM_FQ_CHANNEL_FMAN0_SP0 = 0x40, /**< Dedicated channels serviced by Direct Connect Portal 0:
+ connected to FMan 0; assigned in incrementing order to
+ each sub-portal (SP) in the portal */
+ e_QM_FQ_CHANNEL_FMAN0_SP1,
+ e_QM_FQ_CHANNEL_FMAN0_SP2,
+ e_QM_FQ_CHANNEL_FMAN0_SP3,
+ e_QM_FQ_CHANNEL_FMAN0_SP4,
+ e_QM_FQ_CHANNEL_FMAN0_SP5,
+ e_QM_FQ_CHANNEL_FMAN0_SP6,
+ e_QM_FQ_CHANNEL_FMAN0_SP7,
+ e_QM_FQ_CHANNEL_FMAN0_SP8,
+ e_QM_FQ_CHANNEL_FMAN0_SP9,
+ e_QM_FQ_CHANNEL_FMAN0_SP10,
+ e_QM_FQ_CHANNEL_FMAN0_SP11,
+/* difference between 5020 and 4080 :) */
+ e_QM_FQ_CHANNEL_FMAN1_SP0 = 0x60,
+ e_QM_FQ_CHANNEL_FMAN1_SP1,
+ e_QM_FQ_CHANNEL_FMAN1_SP2,
+ e_QM_FQ_CHANNEL_FMAN1_SP3,
+ e_QM_FQ_CHANNEL_FMAN1_SP4,
+ e_QM_FQ_CHANNEL_FMAN1_SP5,
+ e_QM_FQ_CHANNEL_FMAN1_SP6,
+ e_QM_FQ_CHANNEL_FMAN1_SP7,
+ e_QM_FQ_CHANNEL_FMAN1_SP8,
+ e_QM_FQ_CHANNEL_FMAN1_SP9,
+ e_QM_FQ_CHANNEL_FMAN1_SP10,
+ e_QM_FQ_CHANNEL_FMAN1_SP11,
+
+ e_QM_FQ_CHANNEL_CAAM = 0x80, /**< Dedicated channel serviced by Direct Connect Portal 2:
+ connected to SEC 4.x */
+
+ e_QM_FQ_CHANNEL_PME = 0xA0, /**< Dedicated channel serviced by Direct Connect Portal 3:
+ connected to PME */
+ e_QM_FQ_CHANNEL_RAID = 0xC0 /**< Dedicated channel serviced by Direct Connect Portal 4:
+ connected to RAID */
+} e_QmFQChannel;
+
+/*****************************************************************************
+ BMan INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define BM_MAX_NUM_OF_POOLS 64 /**< Number of buffers pools */
+
+
+/*****************************************************************************
+ FM INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define INTG_MAX_NUM_OF_FM 2
+
+/* Ports defines */
+#define FM_MAX_NUM_OF_1G_MACS 5
+#define FM_MAX_NUM_OF_10G_MACS 1
+#define FM_MAX_NUM_OF_MACS (FM_MAX_NUM_OF_1G_MACS + FM_MAX_NUM_OF_10G_MACS)
+#define FM_MAX_NUM_OF_OH_PORTS 7
+
+#define FM_MAX_NUM_OF_1G_RX_PORTS FM_MAX_NUM_OF_1G_MACS
+#define FM_MAX_NUM_OF_10G_RX_PORTS FM_MAX_NUM_OF_10G_MACS
+#define FM_MAX_NUM_OF_RX_PORTS (FM_MAX_NUM_OF_10G_RX_PORTS + FM_MAX_NUM_OF_1G_RX_PORTS)
+
+#define FM_MAX_NUM_OF_1G_TX_PORTS FM_MAX_NUM_OF_1G_MACS
+#define FM_MAX_NUM_OF_10G_TX_PORTS FM_MAX_NUM_OF_10G_MACS
+#define FM_MAX_NUM_OF_TX_PORTS (FM_MAX_NUM_OF_10G_TX_PORTS + FM_MAX_NUM_OF_1G_TX_PORTS)
+
+#define FM_PORT_MAX_NUM_OF_EXT_POOLS 8 /**< Number of external BM pools per Rx port */
+#define FM_PORT_NUM_OF_CONGESTION_GRPS 256 /**< Total number of congestion groups in QM */
+#define FM_MAX_NUM_OF_SUB_PORTALS 12
+#define FM_PORT_MAX_NUM_OF_OBSERVED_EXT_POOLS 0
+
+/* Rams defines */
+#define FM_MURAM_SIZE (160*KILOBYTE)
+#define FM_IRAM_SIZE ( 64*KILOBYTE)
+#define FM_NUM_OF_CTRL 2
+
+/* PCD defines */
+#define FM_PCD_PLCR_NUM_ENTRIES 256 /**< Total number of policer profiles */
+#define FM_PCD_KG_NUM_OF_SCHEMES 32 /**< Total number of KG schemes */
+#define FM_PCD_MAX_NUM_OF_CLS_PLANS 256 /**< Number of classification plan entries. */
+#define FM_PCD_PRS_SW_PATCHES_SIZE 0x00000200 /**< Number of bytes saved for patches */
+#define FM_PCD_SW_PRS_SIZE 0x00000800 /**< Total size of SW parser area */
+
+/* RTC defines */
+#define FM_RTC_NUM_OF_ALARMS 2 /**< RTC number of alarms */
+#define FM_RTC_NUM_OF_PERIODIC_PULSES 2 /**< RTC number of periodic pulses */
+#define FM_RTC_NUM_OF_EXT_TRIGGERS 2 /**< RTC number of external triggers */
+
+/* QMI defines */
+#define QMI_MAX_NUM_OF_TNUMS 64
+#define QMI_DEF_TNUMS_THRESH 48
+
+/* FPM defines */
+#define FM_NUM_OF_FMAN_CTRL_EVENT_REGS 4
+
+/* DMA defines */
+#define DMA_THRESH_MAX_COMMQ 31
+#define DMA_THRESH_MAX_BUF 127
+
+/* BMI defines */
+#define BMI_MAX_NUM_OF_TASKS 128
+#define BMI_MAX_NUM_OF_DMAS 32
+#define BMI_MAX_FIFO_SIZE (FM_MURAM_SIZE)
+#define PORT_MAX_WEIGHT 16
+
+
+#define FM_CHECK_PORT_RESTRICTIONS(__validPorts, __newPortIndx) TRUE
+
+/* p4080-rev1 unique features */
+#define QM_CGS_NO_FRAME_MODE
+
+/* p4080 unique features */
+#define FM_NO_DISPATCH_RAM_ECC
+#define FM_NO_WATCHDOG
+#define FM_NO_TNUM_AGING
+#define FM_KG_NO_BYPASS_FQID_GEN
+#define FM_KG_NO_BYPASS_PLCR_PROFILE_GEN
+#define FM_NO_BACKUP_POOLS
+#define FM_NO_OP_OBSERVED_POOLS
+#define FM_NO_ADVANCED_RATE_LIMITER
+#define FM_NO_OP_OBSERVED_CGS
+#define FM_HAS_TOTAL_DMAS
+#define FM_KG_NO_IPPID_SUPPORT
+#define FM_NO_GUARANTEED_RESET_VALUES
+#define FM_MAC_RESET
+
+/* FM erratas */
+#define FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+#define FM_TX_SHORT_FRAME_BAD_TS_ERRATA_10GMAC_A006 /* No implementation, Out of LLD scope */
+#define FM_TX_FIFO_CORRUPTION_ERRATA_10GMAC_A007
+#define FM_ECC_HALT_NO_SYNC_ERRATA_10GMAC_A008
+#define FM_TX_INVALID_ECC_ERRATA_10GMAC_A009 /* Out of LLD scope, user may disable ECC exceptions using FM_DisableRamsEcc */
+#define FM_BAD_VLAN_DETECT_ERRATA_10GMAC_A010
+
+#define FM_RX_PREAM_4_ERRATA_DTSEC_A001
+#define FM_GRS_ERRATA_DTSEC_A002
+#define FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003
+#define FM_GTS_ERRATA_DTSEC_A004
+#define FM_GTS_AFTER_MAC_ABORTED_FRAME_ERRATA_DTSEC_A0012
+#define FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014
+#define FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839
+
+#define FM_MAGIC_PACKET_UNRECOGNIZED_ERRATA_DTSEC2 /* No implementation, Out of LLD scope */
+#define FM_TX_LOCKUP_ERRATA_DTSEC6
+
+#define FM_HC_DEF_FQID_ONLY_ERRATA_FMAN_A003 /* Implemented by ucode */
+#define FM_DEBUG_TRACE_FMAN_A004 /* No implementation, Out of LLD scope */
+
+#define FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173
+
+#define FM_10G_REM_N_LCL_FLT_EX_10GMAC_ERRATA_SW005
+
+#define FM_LEN_CHECK_ERRATA_FMAN_SW002
+
+#define FM_NO_CTXA_COPY_ERRATA_FMAN_SW001
+#define FM_KG_ERASE_FLOW_ID_ERRATA_FMAN_SW004
+
+#endif /* __DPAA_INTEGRATION_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/integrations/P3040_P4080_P5020/part_ext.h b/drivers/net/ethernet/freescale/fman/inc/integrations/P3040_P4080_P5020/part_ext.h
new file mode 100644
index 0000000..512f0ba
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/integrations/P3040_P4080_P5020/part_ext.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**************************************************************************//**
+
+ @File part_ext.h
+
+ @Description Definitions for the part (integration) module.
+*//***************************************************************************/
+
+#ifndef __PART_EXT_H
+#define __PART_EXT_H
+
+#include "std_ext.h"
+#include "part_integration_ext.h"
+
+
+#if !(defined(MPC8306) || \
+ defined(MPC8309) || \
+ defined(MPC834x) || \
+ defined(MPC836x) || \
+ defined(MPC832x) || \
+ defined(MPC837x) || \
+ defined(MPC8568) || \
+ defined(MPC8569) || \
+ defined(P1020) || \
+ defined(P1021) || \
+ defined(P1022) || \
+ defined(P1023) || \
+ defined(P2020) || \
+ defined(P2040) || \
+ defined(P3041) || \
+ defined(P4080) || \
+ defined(SC4080) || \
+ defined(P5020) || \
+ defined(MSC814x))
+#error "unable to proceed without chip-definition"
+#endif /* !(defined(MPC834x) || ... */
+
+
+/**************************************************************************//*
+ @Description Part data structure - must be contained in any integration
+ data structure.
+*//***************************************************************************/
+typedef struct t_Part
+{
+ uintptr_t (* f_GetModuleBase)(t_Handle h_Part, e_ModuleId moduleId);
+ /**< Returns the address of the module's memory map base. */
+ e_ModuleId (* f_GetModuleIdByBase)(t_Handle h_Part, uintptr_t baseAddress);
+ /**< Returns the module's ID according to its memory map base. */
+} t_Part;
+
+
+#endif /* __PART_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/integrations/P3040_P4080_P5020/part_integration_ext.h b/drivers/net/ethernet/freescale/fman/inc/integrations/P3040_P4080_P5020/part_integration_ext.h
new file mode 100644
index 0000000..03c59b8
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/integrations/P3040_P4080_P5020/part_integration_ext.h
@@ -0,0 +1,336 @@
+/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**************************************************************************//**
+ @File part_integration_ext.h
+
+ @Description P3040/P4080/P5020 external definitions and structures.
+*//***************************************************************************/
+#ifndef __PART_INTEGRATION_EXT_H
+#define __PART_INTEGRATION_EXT_H
+
+#include "std_ext.h"
+#include "dpaa_integration_ext.h"
+
+
+/**************************************************************************//**
+ @Group P3040/P4080/P5020_chip_id P5020 Application Programming Interface
+
+ @Description P3040/P4080/P5020 Chip functions,definitions and enums.
+
+ @{
+*//***************************************************************************/
+
+#define CORE_E500MC
+
+#define INTG_MAX_NUM_OF_CORES 1
+
+
+/**************************************************************************//**
+ @Description Module types.
+*//***************************************************************************/
+typedef enum e_ModuleId
+{
+ e_MODULE_ID_DUART_1 = 0,
+ e_MODULE_ID_DUART_2,
+ e_MODULE_ID_DUART_3,
+ e_MODULE_ID_DUART_4,
+ e_MODULE_ID_LAW,
+ e_MODULE_ID_LBC,
+ e_MODULE_ID_PAMU,
+ e_MODULE_ID_QM, /**< Queue manager module */
+ e_MODULE_ID_BM, /**< Buffer manager module */
+ e_MODULE_ID_QM_CE_PORTAL_0,
+ e_MODULE_ID_QM_CI_PORTAL_0,
+ e_MODULE_ID_QM_CE_PORTAL_1,
+ e_MODULE_ID_QM_CI_PORTAL_1,
+ e_MODULE_ID_QM_CE_PORTAL_2,
+ e_MODULE_ID_QM_CI_PORTAL_2,
+ e_MODULE_ID_QM_CE_PORTAL_3,
+ e_MODULE_ID_QM_CI_PORTAL_3,
+ e_MODULE_ID_QM_CE_PORTAL_4,
+ e_MODULE_ID_QM_CI_PORTAL_4,
+ e_MODULE_ID_QM_CE_PORTAL_5,
+ e_MODULE_ID_QM_CI_PORTAL_5,
+ e_MODULE_ID_QM_CE_PORTAL_6,
+ e_MODULE_ID_QM_CI_PORTAL_6,
+ e_MODULE_ID_QM_CE_PORTAL_7,
+ e_MODULE_ID_QM_CI_PORTAL_7,
+ e_MODULE_ID_QM_CE_PORTAL_8,
+ e_MODULE_ID_QM_CI_PORTAL_8,
+ e_MODULE_ID_QM_CE_PORTAL_9,
+ e_MODULE_ID_QM_CI_PORTAL_9,
+ e_MODULE_ID_BM_CE_PORTAL_0,
+ e_MODULE_ID_BM_CI_PORTAL_0,
+ e_MODULE_ID_BM_CE_PORTAL_1,
+ e_MODULE_ID_BM_CI_PORTAL_1,
+ e_MODULE_ID_BM_CE_PORTAL_2,
+ e_MODULE_ID_BM_CI_PORTAL_2,
+ e_MODULE_ID_BM_CE_PORTAL_3,
+ e_MODULE_ID_BM_CI_PORTAL_3,
+ e_MODULE_ID_BM_CE_PORTAL_4,
+ e_MODULE_ID_BM_CI_PORTAL_4,
+ e_MODULE_ID_BM_CE_PORTAL_5,
+ e_MODULE_ID_BM_CI_PORTAL_5,
+ e_MODULE_ID_BM_CE_PORTAL_6,
+ e_MODULE_ID_BM_CI_PORTAL_6,
+ e_MODULE_ID_BM_CE_PORTAL_7,
+ e_MODULE_ID_BM_CI_PORTAL_7,
+ e_MODULE_ID_BM_CE_PORTAL_8,
+ e_MODULE_ID_BM_CI_PORTAL_8,
+ e_MODULE_ID_BM_CE_PORTAL_9,
+ e_MODULE_ID_BM_CI_PORTAL_9,
+ e_MODULE_ID_FM1, /**< Frame manager #1 module */
+ e_MODULE_ID_FM1_RTC, /**< FM Real-Time-Clock */
+ e_MODULE_ID_FM1_MURAM, /**< FM Multi-User-RAM */
+ e_MODULE_ID_FM1_BMI, /**< FM BMI block */
+ e_MODULE_ID_FM1_QMI, /**< FM QMI block */
+ e_MODULE_ID_FM1_PRS, /**< FM parser block */
+ e_MODULE_ID_FM1_PORT_HO0, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM1_PORT_HO1, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM1_PORT_HO2, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM1_PORT_HO3, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM1_PORT_HO4, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM1_PORT_HO5, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM1_PORT_HO6, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM1_PORT_1GRx0, /**< FM Rx 1G MAC port block */
+ e_MODULE_ID_FM1_PORT_1GRx1, /**< FM Rx 1G MAC port block */
+ e_MODULE_ID_FM1_PORT_1GRx2, /**< FM Rx 1G MAC port block */
+ e_MODULE_ID_FM1_PORT_1GRx3, /**< FM Rx 1G MAC port block */
+ e_MODULE_ID_FM1_PORT_1GRx4, /**< FM Rx 1G MAC port block */
+ e_MODULE_ID_FM1_PORT_10GRx0, /**< FM Rx 10G MAC port block */
+ e_MODULE_ID_FM1_PORT_1GTx0, /**< FM Tx 1G MAC port block */
+ e_MODULE_ID_FM1_PORT_1GTx1, /**< FM Tx 1G MAC port block */
+ e_MODULE_ID_FM1_PORT_1GTx2, /**< FM Tx 1G MAC port block */
+ e_MODULE_ID_FM1_PORT_1GTx3, /**< FM Tx 1G MAC port block */
+ e_MODULE_ID_FM1_PORT_1GTx4, /**< FM Tx 1G MAC port block */
+ e_MODULE_ID_FM1_PORT_10GTx0, /**< FM Tx 10G MAC port block */
+ e_MODULE_ID_FM1_PLCR, /**< FM Policer */
+ e_MODULE_ID_FM1_KG, /**< FM Keygen */
+ e_MODULE_ID_FM1_DMA, /**< FM DMA */
+ e_MODULE_ID_FM1_FPM, /**< FM FPM */
+ e_MODULE_ID_FM1_IRAM, /**< FM Instruction-RAM */
+ e_MODULE_ID_FM1_1GMDIO0, /**< FM 1G MDIO MAC 0*/
+ e_MODULE_ID_FM1_1GMDIO1, /**< FM 1G MDIO MAC 1*/
+ e_MODULE_ID_FM1_1GMDIO2, /**< FM 1G MDIO MAC 2*/
+ e_MODULE_ID_FM1_1GMDIO3, /**< FM 1G MDIO MAC 3*/
+ e_MODULE_ID_FM1_10GMDIO, /**< FM 10G MDIO */
+ e_MODULE_ID_FM1_PRS_IRAM, /**< FM SW-parser Instruction-RAM */
+ e_MODULE_ID_FM1_1GMAC0, /**< FM 1G MAC #0 */
+ e_MODULE_ID_FM1_1GMAC1, /**< FM 1G MAC #1 */
+ e_MODULE_ID_FM1_1GMAC2, /**< FM 1G MAC #2 */
+ e_MODULE_ID_FM1_1GMAC3, /**< FM 1G MAC #3 */
+ e_MODULE_ID_FM1_10GMAC0, /**< FM 10G MAC #0 */
+
+ e_MODULE_ID_FM2, /**< Frame manager #2 module */
+ e_MODULE_ID_FM2_RTC, /**< FM Real-Time-Clock */
+ e_MODULE_ID_FM2_MURAM, /**< FM Multi-User-RAM */
+ e_MODULE_ID_FM2_BMI, /**< FM BMI block */
+ e_MODULE_ID_FM2_QMI, /**< FM QMI block */
+ e_MODULE_ID_FM2_PRS, /**< FM parser block */
+ e_MODULE_ID_FM2_PORT_HO0, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM2_PORT_HO1, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM2_PORT_HO2, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM2_PORT_HO3, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM2_PORT_HO4, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM2_PORT_HO5, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM2_PORT_HO6, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM2_PORT_1GRx0, /**< FM Rx 1G MAC port block */
+ e_MODULE_ID_FM2_PORT_1GRx1, /**< FM Rx 1G MAC port block */
+ e_MODULE_ID_FM2_PORT_1GRx2, /**< FM Rx 1G MAC port block */
+ e_MODULE_ID_FM2_PORT_1GRx3, /**< FM Rx 1G MAC port block */
+ e_MODULE_ID_FM2_PORT_10GRx0, /**< FM Rx 10G MAC port block */
+ e_MODULE_ID_FM2_PORT_1GTx0, /**< FM Tx 1G MAC port block */
+ e_MODULE_ID_FM2_PORT_1GTx1, /**< FM Tx 1G MAC port block */
+ e_MODULE_ID_FM2_PORT_1GTx2, /**< FM Tx 1G MAC port block */
+ e_MODULE_ID_FM2_PORT_1GTx3, /**< FM Tx 1G MAC port block */
+ e_MODULE_ID_FM2_PORT_10GTx0, /**< FM Tx 10G MAC port block */
+ e_MODULE_ID_FM2_PLCR, /**< FM Policer */
+ e_MODULE_ID_FM2_KG, /**< FM Keygen */
+ e_MODULE_ID_FM2_DMA, /**< FM DMA */
+ e_MODULE_ID_FM2_FPM, /**< FM FPM */
+ e_MODULE_ID_FM2_IRAM, /**< FM Instruction-RAM */
+ e_MODULE_ID_FM2_1GMDIO0, /**< FM 1G MDIO MAC 0*/
+ e_MODULE_ID_FM2_1GMDIO1, /**< FM 1G MDIO MAC 1*/
+ e_MODULE_ID_FM2_1GMDIO2, /**< FM 1G MDIO MAC 2*/
+ e_MODULE_ID_FM2_1GMDIO3, /**< FM 1G MDIO MAC 3*/
+ e_MODULE_ID_FM2_10GMDIO, /**< FM 10G MDIO */
+ e_MODULE_ID_FM2_PRS_IRAM, /**< FM SW-parser Instruction-RAM */
+ e_MODULE_ID_FM2_1GMAC0, /**< FM 1G MAC #0 */
+ e_MODULE_ID_FM2_1GMAC1, /**< FM 1G MAC #1 */
+ e_MODULE_ID_FM2_1GMAC2, /**< FM 1G MAC #2 */
+ e_MODULE_ID_FM2_1GMAC3, /**< FM 1G MAC #3 */
+ e_MODULE_ID_FM2_10GMAC0, /**< FM 10G MAC #0 */
+
+ e_MODULE_ID_SEC_GEN, /**< SEC 4.0 General registers */
+ e_MODULE_ID_SEC_QI, /**< SEC 4.0 QI registers */
+ e_MODULE_ID_SEC_JQ0, /**< SEC 4.0 JQ-0 registers */
+ e_MODULE_ID_SEC_JQ1, /**< SEC 4.0 JQ-1 registers */
+ e_MODULE_ID_SEC_JQ2, /**< SEC 4.0 JQ-2 registers */
+ e_MODULE_ID_SEC_JQ3, /**< SEC 4.0 JQ-3 registers */
+ e_MODULE_ID_SEC_RTIC, /**< SEC 4.0 RTIC registers */
+ e_MODULE_ID_SEC_DECO0_CCB0, /**< SEC 4.0 DECO-0/CCB-0 registers */
+ e_MODULE_ID_SEC_DECO1_CCB1, /**< SEC 4.0 DECO-1/CCB-1 registers */
+ e_MODULE_ID_SEC_DECO2_CCB2, /**< SEC 4.0 DECO-2/CCB-2 registers */
+ e_MODULE_ID_SEC_DECO3_CCB3, /**< SEC 4.0 DECO-3/CCB-3 registers */
+ e_MODULE_ID_SEC_DECO4_CCB4, /**< SEC 4.0 DECO-4/CCB-4 registers */
+
+ e_MODULE_ID_MPIC, /**< MPIC */
+ e_MODULE_ID_GPIO, /**< GPIO */
+ e_MODULE_ID_SERDES, /**< SERDES */
+ e_MODULE_ID_CPC_1, /**< CoreNet-Platform-Cache 1 */
+ e_MODULE_ID_CPC_2, /**< CoreNet-Platform-Cache 2 */
+
+ e_MODULE_ID_SRIO_PORTS, /**< RapidIO controller */
+ e_MODULE_ID_SRIO_MU, /**< RapidIO messaging unit module */
+
+ e_MODULE_ID_DUMMY_LAST
+} e_ModuleId;
+
+#define NUM_OF_MODULES e_MODULE_ID_DUMMY_LAST
+
+#if 0 /* using unified values */
+/*****************************************************************************
+ INTEGRATION-SPECIFIC MODULE CODES
+******************************************************************************/
+#define MODULE_UNKNOWN 0x00000000
+#define MODULE_MEM 0x00010000
+#define MODULE_MM 0x00020000
+#define MODULE_CORE 0x00030000
+#define MODULE_CHIP 0x00040000
+#define MODULE_PLTFRM 0x00050000
+#define MODULE_PM 0x00060000
+#define MODULE_MMU 0x00070000
+#define MODULE_PIC 0x00080000
+#define MODULE_CPC 0x00090000
+#define MODULE_DUART 0x000a0000
+#define MODULE_SERDES 0x000b0000
+#define MODULE_PIO 0x000c0000
+#define MODULE_QM 0x000d0000
+#define MODULE_BM 0x000e0000
+#define MODULE_SEC 0x000f0000
+#define MODULE_LAW 0x00100000
+#define MODULE_LBC 0x00110000
+#define MODULE_PAMU 0x00120000
+#define MODULE_FM 0x00130000
+#define MODULE_FM_MURAM 0x00140000
+#define MODULE_FM_PCD 0x00150000
+#define MODULE_FM_RTC 0x00160000
+#define MODULE_FM_MAC 0x00170000
+#define MODULE_FM_PORT 0x00180000
+#define MODULE_FM_SP 0x00190000
+#define MODULE_DPA_PORT 0x001a0000
+#define MODULE_MII 0x001b0000
+#define MODULE_I2C 0x001c0000
+#define MODULE_DMA 0x001d0000
+#define MODULE_DDR 0x001e0000
+#define MODULE_ESPI 0x001f0000
+#define MODULE_DPAA_IPSEC 0x00200000
+#endif /* using unified values */
+
+/*****************************************************************************
+ PAMU INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define PAMU_NUM_OF_PARTITIONS 5
+
+#define PAMU_PICS_AVICS_ERRATA_PAMU3
+
+/*****************************************************************************
+ LAW INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define LAW_NUM_OF_WINDOWS 32
+#define LAW_MIN_WINDOW_SIZE 0x0000000000001000LL /**< 4KB */
+#define LAW_MAX_WINDOW_SIZE 0x0000002000000000LL /**< 64GB */
+
+
+/*****************************************************************************
+ LBC INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+/**************************************************************************//**
+ @Group lbc_exception_grp LBC Exception Unit
+
+ @Description LBC Exception unit API functions, definitions and enums
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Anchor lbc_exbm
+
+ @Collection LBC Errors Bit Mask
+
+ These errors are reported through the exceptions callback..
+ The values can be or'ed in any combination in the errors mask
+ parameter of the errors report structure.
+
+ These errors can also be passed as a bit-mask to
+ LBC_EnableErrorChecking() or LBC_DisableErrorChecking(),
+ for enabling or disabling error checking.
+ @{
+*//***************************************************************************/
+#define LBC_ERR_BUS_MONITOR 0x80000000 /**< Bus monitor error */
+#define LBC_ERR_PARITY_ECC 0x20000000 /**< Parity error for GPCM/UPM */
+#define LBC_ERR_WRITE_PROTECT 0x04000000 /**< Write protection error */
+#define LBC_ERR_ATOMIC_WRITE 0x00800000 /**< Atomic write error */
+#define LBC_ERR_ATOMIC_READ 0x00400000 /**< Atomic read error */
+#define LBC_ERR_CHIP_SELECT 0x00080000 /**< Unrecognized chip select */
+
+#define LBC_ERR_ALL (LBC_ERR_BUS_MONITOR | LBC_ERR_PARITY_ECC | \
+ LBC_ERR_WRITE_PROTECT | LBC_ERR_ATOMIC_WRITE | \
+ LBC_ERR_ATOMIC_READ | LBC_ERR_CHIP_SELECT)
+ /**< All possible errors */
+/* @} */
+/** @} */ /* end of lbc_exception_grp group */
+
+#define LBC_INCORRECT_ERROR_REPORT_ERRATA
+
+#define LBC_NUM_OF_BANKS 8
+#define LBC_MAX_CS_SIZE 0x0000000100000000LL
+#define LBC_ATOMIC_OPERATION_SUPPORT
+#define LBC_PARITY_SUPPORT
+#define LBC_ADDRESS_HOLD_TIME_CTRL
+#define LBC_HIGH_CLK_DIVIDERS
+#define LBC_FCM_AVAILABLE
+
+/*****************************************************************************
+ GPIO INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define GPIO_NUM_OF_PORTS 1 /**< Number of ports in GPIO module;
+ Each port contains up to 32 i/O pins. */
+
+#define GPIO_VALID_PIN_MASKS \
+ { /* Port A */ 0xFFFFFFFF }
+
+#define GPIO_VALID_INTR_MASKS \
+ { /* Port A */ 0xFFFFFFFF }
+
+#endif /* __PART_INTEGRATION_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/integrations/T4240/dpaa_integration_ext.h b/drivers/net/ethernet/freescale/fman/inc/integrations/T4240/dpaa_integration_ext.h
new file mode 100644
index 0000000..6fa8c25
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/integrations/T4240/dpaa_integration_ext.h
@@ -0,0 +1,281 @@
+/*
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+
+ @File dpaa_integration_ext.h
+
+ @Description T4240 FM external definitions and structures.
+*//***************************************************************************/
+#ifndef __DPAA_INTEGRATION_EXT_H
+#define __DPAA_INTEGRATION_EXT_H
+
+#include "std_ext.h"
+
+
+#define DPAA_VERSION 11
+
+/**************************************************************************//**
+ @Description DPAA SW Portals Enumeration.
+*//***************************************************************************/
+typedef enum
+{
+ e_DPAA_SWPORTAL0 = 0,
+ e_DPAA_SWPORTAL1,
+ e_DPAA_SWPORTAL2,
+ e_DPAA_SWPORTAL3,
+ e_DPAA_SWPORTAL4,
+ e_DPAA_SWPORTAL5,
+ e_DPAA_SWPORTAL6,
+ e_DPAA_SWPORTAL7,
+ e_DPAA_SWPORTAL8,
+ e_DPAA_SWPORTAL9,
+ e_DPAA_SWPORTAL10,
+ e_DPAA_SWPORTAL11,
+ e_DPAA_SWPORTAL12,
+ e_DPAA_SWPORTAL13,
+ e_DPAA_SWPORTAL14,
+ e_DPAA_SWPORTAL15,
+ e_DPAA_SWPORTAL16,
+ e_DPAA_SWPORTAL17,
+ e_DPAA_SWPORTAL18,
+ e_DPAA_SWPORTAL19,
+ e_DPAA_SWPORTAL20,
+ e_DPAA_SWPORTAL21,
+ e_DPAA_SWPORTAL22,
+ e_DPAA_SWPORTAL23,
+ e_DPAA_SWPORTAL24,
+ e_DPAA_SWPORTAL_DUMMY_LAST
+} e_DpaaSwPortal;
+
+/**************************************************************************//**
+ @Description DPAA Direct Connect Portals Enumeration.
+*//***************************************************************************/
+typedef enum
+{
+ e_DPAA_DCPORTAL0 = 0,
+ e_DPAA_DCPORTAL1,
+ e_DPAA_DCPORTAL2,
+ e_DPAA_DCPORTAL_DUMMY_LAST
+} e_DpaaDcPortal;
+
+#define DPAA_MAX_NUM_OF_SW_PORTALS e_DPAA_SWPORTAL_DUMMY_LAST
+#define DPAA_MAX_NUM_OF_DC_PORTALS e_DPAA_DCPORTAL_DUMMY_LAST
+
+/*****************************************************************************
+ QMan INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define QM_MAX_NUM_OF_POOL_CHANNELS 15 /**< Total number of channels, dedicated and pool */
+#define QM_MAX_NUM_OF_WQ 8 /**< Number of work queues per channel */
+#define QM_MAX_NUM_OF_CGS 256 /**< Congestion groups number */
+#define QM_MAX_NUM_OF_FQIDS (16 * MEGABYTE)
+ /**< FQIDs range - 24 bits */
+
+/**************************************************************************//**
+ @Description Work Queue Channel assignments in QMan.
+*//***************************************************************************/
+typedef enum
+{
+ e_QM_FQ_CHANNEL_SWPORTAL0 = 0x0, /**< Dedicated channels serviced by software portals 0 to 24 */
+ e_QM_FQ_CHANNEL_SWPORTAL1,
+ e_QM_FQ_CHANNEL_SWPORTAL2,
+ e_QM_FQ_CHANNEL_SWPORTAL3,
+ e_QM_FQ_CHANNEL_SWPORTAL4,
+ e_QM_FQ_CHANNEL_SWPORTAL5,
+ e_QM_FQ_CHANNEL_SWPORTAL6,
+ e_QM_FQ_CHANNEL_SWPORTAL7,
+ e_QM_FQ_CHANNEL_SWPORTAL8,
+ e_QM_FQ_CHANNEL_SWPORTAL9,
+ e_QM_FQ_CHANNEL_SWPORTAL10,
+ e_QM_FQ_CHANNEL_SWPORTAL11,
+ e_QM_FQ_CHANNEL_SWPORTAL12,
+ e_QM_FQ_CHANNEL_SWPORTAL13,
+ e_QM_FQ_CHANNEL_SWPORTAL14,
+ e_QM_FQ_CHANNEL_SWPORTAL15,
+ e_QM_FQ_CHANNEL_SWPORTAL16,
+ e_QM_FQ_CHANNEL_SWPORTAL17,
+ e_QM_FQ_CHANNEL_SWPORTAL18,
+ e_QM_FQ_CHANNEL_SWPORTAL19,
+ e_QM_FQ_CHANNEL_SWPORTAL20,
+ e_QM_FQ_CHANNEL_SWPORTAL21,
+ e_QM_FQ_CHANNEL_SWPORTAL22,
+ e_QM_FQ_CHANNEL_SWPORTAL23,
+ e_QM_FQ_CHANNEL_SWPORTAL24,
+
+ e_QM_FQ_CHANNEL_POOL1 = 0x401, /**< Pool channels that can be serviced by any of the software portals */
+ e_QM_FQ_CHANNEL_POOL2,
+ e_QM_FQ_CHANNEL_POOL3,
+ e_QM_FQ_CHANNEL_POOL4,
+ e_QM_FQ_CHANNEL_POOL5,
+ e_QM_FQ_CHANNEL_POOL6,
+ e_QM_FQ_CHANNEL_POOL7,
+ e_QM_FQ_CHANNEL_POOL8,
+ e_QM_FQ_CHANNEL_POOL9,
+ e_QM_FQ_CHANNEL_POOL10,
+ e_QM_FQ_CHANNEL_POOL11,
+ e_QM_FQ_CHANNEL_POOL12,
+ e_QM_FQ_CHANNEL_POOL13,
+ e_QM_FQ_CHANNEL_POOL14,
+ e_QM_FQ_CHANNEL_POOL15,
+
+ e_QM_FQ_CHANNEL_FMAN0_SP0 = 0x800, /**< Dedicated channels serviced by Direct Connect Portal 0:
+ connected to FMan 0; assigned in incrementing order to
+ each sub-portal (SP) in the portal */
+ e_QM_FQ_CHANNEL_FMAN0_SP1,
+ e_QM_FQ_CHANNEL_FMAN0_SP2,
+ e_QM_FQ_CHANNEL_FMAN0_SP3,
+ e_QM_FQ_CHANNEL_FMAN0_SP4,
+ e_QM_FQ_CHANNEL_FMAN0_SP5,
+ e_QM_FQ_CHANNEL_FMAN0_SP6,
+ e_QM_FQ_CHANNEL_FMAN0_SP7,
+ e_QM_FQ_CHANNEL_FMAN0_SP8,
+ e_QM_FQ_CHANNEL_FMAN0_SP9,
+ e_QM_FQ_CHANNEL_FMAN0_SP10,
+ e_QM_FQ_CHANNEL_FMAN0_SP11,
+ e_QM_FQ_CHANNEL_FMAN0_SP12,
+ e_QM_FQ_CHANNEL_FMAN0_SP13,
+ e_QM_FQ_CHANNEL_FMAN0_SP14,
+ e_QM_FQ_CHANNEL_FMAN0_SP15,
+
+ e_QM_FQ_CHANNEL_RMAN_SP0 = 0x820, /**< Dedicated channels serviced by Direct Connect Portal 1: connected to RMan */
+ e_QM_FQ_CHANNEL_RMAN_SP1,
+
+ e_QM_FQ_CHANNEL_CAAM = 0x840 /**< Dedicated channel serviced by Direct Connect Portal 2:
+ connected to SEC */
+} e_QmFQChannel;
+
+/*****************************************************************************
+ BMan INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define BM_MAX_NUM_OF_POOLS 64 /**< Number of buffers pools */
+
+/*****************************************************************************
+ SEC INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define SEC_NUM_OF_DECOS 3
+#define SEC_ALL_DECOS_MASK 0x00000003
+
+
+/*****************************************************************************
+ FM INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define INTG_MAX_NUM_OF_FM 2
+
+/* Ports defines */
+#define FM_MAX_NUM_OF_1G_MACS 6
+#define FM_MAX_NUM_OF_10G_MACS 2
+#define FM_MAX_NUM_OF_MACS (FM_MAX_NUM_OF_1G_MACS + FM_MAX_NUM_OF_10G_MACS)
+#define FM_MAX_NUM_OF_OH_PORTS 6
+
+#define FM_MAX_NUM_OF_1G_RX_PORTS FM_MAX_NUM_OF_1G_MACS
+#define FM_MAX_NUM_OF_10G_RX_PORTS FM_MAX_NUM_OF_10G_MACS
+#define FM_MAX_NUM_OF_RX_PORTS (FM_MAX_NUM_OF_10G_RX_PORTS + FM_MAX_NUM_OF_1G_RX_PORTS)
+
+#define FM_MAX_NUM_OF_1G_TX_PORTS FM_MAX_NUM_OF_1G_MACS
+#define FM_MAX_NUM_OF_10G_TX_PORTS FM_MAX_NUM_OF_10G_MACS
+#define FM_MAX_NUM_OF_TX_PORTS (FM_MAX_NUM_OF_10G_TX_PORTS + FM_MAX_NUM_OF_1G_TX_PORTS)
+
+#define FM_PORT_MAX_NUM_OF_EXT_POOLS 4 /**< Number of external BM pools per Rx port */
+#define FM_PORT_NUM_OF_CONGESTION_GRPS 256 /**< Total number of congestion groups in QM */
+#define FM_MAX_NUM_OF_SUB_PORTALS 16
+#define FM_PORT_MAX_NUM_OF_OBSERVED_EXT_POOLS 0
+
+#define FM_VSP_MAX_NUM_OF_ENTRIES 64
+#define FM_MAX_NUM_OF_PFC_PRIORITIES 8
+
+/* RAMs defines */
+#define FM_MURAM_SIZE (384 * KILOBYTE)
+#define FM_IRAM_SIZE ( 64 * KILOBYTE)
+#define FM_NUM_OF_CTRL 4
+
+/* PCD defines */
+#define FM_PCD_PLCR_NUM_ENTRIES 256 /**< Total number of policer profiles */
+#define FM_PCD_KG_NUM_OF_SCHEMES 32 /**< Total number of KG schemes */
+#define FM_PCD_MAX_NUM_OF_CLS_PLANS 256 /**< Number of classification plan entries. */
+#define FM_PCD_PRS_SW_PATCHES_SIZE 0x00000240 /**< Number of bytes saved for patches */
+#define FM_PCD_SW_PRS_SIZE 0x00000800 /**< Total size of SW parser area */
+
+/* RTC defines */
+#define FM_RTC_NUM_OF_ALARMS 2 /**< RTC number of alarms */
+#define FM_RTC_NUM_OF_PERIODIC_PULSES 3 /**< RTC number of periodic pulses */
+#define FM_RTC_NUM_OF_EXT_TRIGGERS 2 /**< RTC number of external triggers */
+
+/* QMI defines */
+#define QMI_MAX_NUM_OF_TNUMS 64
+#define QMI_DEF_TNUMS_THRESH 32
+/* FPM defines */
+#define FM_NUM_OF_FMAN_CTRL_EVENT_REGS 4
+
+/* DMA defines */
+#define DMA_THRESH_MAX_COMMQ 83
+#define DMA_THRESH_MAX_BUF 127
+
+/* BMI defines */
+#define BMI_MAX_NUM_OF_TASKS 128
+#define BMI_MAX_NUM_OF_DMAS 84
+#define BMI_MAX_FIFO_SIZE (FM_MURAM_SIZE)
+#define PORT_MAX_WEIGHT 16
+
+#define FM_CHECK_PORT_RESTRICTIONS(__validPorts, __newPortIndx) TRUE
+
+/* Unique T4240 */
+#define FM_OP_OPEN_DMA_MIN_LIMIT
+#define FM_NO_RESTRICT_ON_ACCESS_RSRC
+#define FM_NO_OP_OBSERVED_POOLS
+#define FM_FRAME_END_PARAMS_FOR_OP
+#define FM_DEQ_PIPELINE_PARAMS_FOR_OP
+#define FM_QMI_NO_SINGLE_ECC_EXCEPTION
+
+#define FM_NO_GUARANTEED_RESET_VALUES
+
+/* FM errata */
+#define FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669
+#define FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127
+#define FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320
+#define FM_OP_NO_VSP_NO_RELEASE_ERRATA_FMAN_A006675
+#define FM_HEAVY_TRAFFIC_SEQUENCER_HANG_ERRATA_FMAN_A006981
+
+#define FM_BCB_ERRATA_BMI_SW001
+#define FM_LEN_CHECK_ERRATA_FMAN_SW002
+#define FM_AID_MODE_NO_TNUM_SW005 /* refer to pdm TKT068794 - only support of port_id on aid */
+#define FM_ERROR_VSP_NO_MATCH_SW006 /* refer to pdm TKT174304 - no match between errorQ and VSP */
+
+/*****************************************************************************
+ RMan INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define RM_MAX_NUM_OF_IB 4 /**< Number of inbound blocks */
+#define RM_NUM_OF_IBCU 8 /**< NUmber of classification units in an inbound block */
+
+/* RMan erratas */
+#define RM_ERRONEOUS_ACK_ERRATA_RMAN_A006756
+
+#endif /* __DPAA_INTEGRATION_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/integrations/T4240/part_ext.h b/drivers/net/ethernet/freescale/fman/inc/integrations/T4240/part_ext.h
new file mode 100644
index 0000000..0d62dd1
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/integrations/T4240/part_ext.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**************************************************************************//**
+
+ @File part_ext.h
+
+ @Description Definitions for the part (integration) module.
+*//***************************************************************************/
+
+#ifndef __PART_EXT_H
+#define __PART_EXT_H
+
+#include "std_ext.h"
+#include "part_integration_ext.h"
+
+#if !(defined(P1023) || \
+ defined(P2041) || \
+ defined(P3041) || \
+ defined(P4080) || \
+ defined(P5020) || \
+ defined(P5040) || \
+ defined(B4860) || \
+ defined(T4240))
+#error "unable to proceed without chip-definition"
+#endif
+
+
+/**************************************************************************//*
+ @Description Part data structure - must be contained in any integration
+ data structure.
+*//***************************************************************************/
+typedef struct t_Part
+{
+ uintptr_t (* f_GetModuleBase)(t_Handle h_Part, e_ModuleId moduleId);
+ /**< Returns the address of the module's memory map base. */
+ e_ModuleId (* f_GetModuleIdByBase)(t_Handle h_Part, uintptr_t baseAddress);
+ /**< Returns the module's ID according to its memory map base. */
+} t_Part;
+
+
+#endif /* __PART_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/integrations/T4240/part_integration_ext.h b/drivers/net/ethernet/freescale/fman/inc/integrations/T4240/part_integration_ext.h
new file mode 100644
index 0000000..3254c76
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/integrations/T4240/part_integration_ext.h
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+
+ @File part_integration_ext.h
+
+ @Description T4240 external definitions and structures.
+*//***************************************************************************/
+#ifndef __PART_INTEGRATION_EXT_H
+#define __PART_INTEGRATION_EXT_H
+
+#include "std_ext.h"
+#include "ddr_std_ext.h"
+#include "enet_ext.h"
+#include "dpaa_integration_ext.h"
+
+
+/**************************************************************************//**
+ @Group T4240_chip_id T4240 Application Programming Interface
+
+ @Description T4240 Chip functions,definitions and enums.
+
+ @{
+*//***************************************************************************/
+
+#define CORE_E6500
+
+#define INTG_MAX_NUM_OF_CORES 24
+
+
+/**************************************************************************//**
+ @Description Module types.
+*//***************************************************************************/
+typedef enum e_ModuleId
+{
+ e_MODULE_ID_DUART_1 = 0,
+ e_MODULE_ID_DUART_2,
+ e_MODULE_ID_DUART_3,
+ e_MODULE_ID_DUART_4,
+ e_MODULE_ID_LAW,
+ e_MODULE_ID_IFC,
+ e_MODULE_ID_PAMU,
+ e_MODULE_ID_QM, /**< Queue manager module */
+ e_MODULE_ID_BM, /**< Buffer manager module */
+ e_MODULE_ID_QM_CE_PORTAL_0,
+ e_MODULE_ID_QM_CI_PORTAL_0,
+ e_MODULE_ID_QM_CE_PORTAL_1,
+ e_MODULE_ID_QM_CI_PORTAL_1,
+ e_MODULE_ID_QM_CE_PORTAL_2,
+ e_MODULE_ID_QM_CI_PORTAL_2,
+ e_MODULE_ID_QM_CE_PORTAL_3,
+ e_MODULE_ID_QM_CI_PORTAL_3,
+ e_MODULE_ID_QM_CE_PORTAL_4,
+ e_MODULE_ID_QM_CI_PORTAL_4,
+ e_MODULE_ID_QM_CE_PORTAL_5,
+ e_MODULE_ID_QM_CI_PORTAL_5,
+ e_MODULE_ID_QM_CE_PORTAL_6,
+ e_MODULE_ID_QM_CI_PORTAL_6,
+ e_MODULE_ID_QM_CE_PORTAL_7,
+ e_MODULE_ID_QM_CI_PORTAL_7,
+ e_MODULE_ID_QM_CE_PORTAL_8,
+ e_MODULE_ID_QM_CI_PORTAL_8,
+ e_MODULE_ID_QM_CE_PORTAL_9,
+ e_MODULE_ID_QM_CI_PORTAL_9,
+ e_MODULE_ID_BM_CE_PORTAL_0,
+ e_MODULE_ID_BM_CI_PORTAL_0,
+ e_MODULE_ID_BM_CE_PORTAL_1,
+ e_MODULE_ID_BM_CI_PORTAL_1,
+ e_MODULE_ID_BM_CE_PORTAL_2,
+ e_MODULE_ID_BM_CI_PORTAL_2,
+ e_MODULE_ID_BM_CE_PORTAL_3,
+ e_MODULE_ID_BM_CI_PORTAL_3,
+ e_MODULE_ID_BM_CE_PORTAL_4,
+ e_MODULE_ID_BM_CI_PORTAL_4,
+ e_MODULE_ID_BM_CE_PORTAL_5,
+ e_MODULE_ID_BM_CI_PORTAL_5,
+ e_MODULE_ID_BM_CE_PORTAL_6,
+ e_MODULE_ID_BM_CI_PORTAL_6,
+ e_MODULE_ID_BM_CE_PORTAL_7,
+ e_MODULE_ID_BM_CI_PORTAL_7,
+ e_MODULE_ID_BM_CE_PORTAL_8,
+ e_MODULE_ID_BM_CI_PORTAL_8,
+ e_MODULE_ID_BM_CE_PORTAL_9,
+ e_MODULE_ID_BM_CI_PORTAL_9,
+ e_MODULE_ID_FM, /**< Frame manager module */
+ e_MODULE_ID_FM_RTC, /**< FM Real-Time-Clock */
+ e_MODULE_ID_FM_MURAM, /**< FM Multi-User-RAM */
+ e_MODULE_ID_FM_BMI, /**< FM BMI block */
+ e_MODULE_ID_FM_QMI, /**< FM QMI block */
+ e_MODULE_ID_FM_PARSER, /**< FM parser block */
+ e_MODULE_ID_FM_PORT_HO1, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM_PORT_HO2, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM_PORT_HO3, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM_PORT_HO4, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM_PORT_HO5, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM_PORT_HO6, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM_PORT_HO7, /**< FM Host-command/offline-parsing port block */
+ e_MODULE_ID_FM_PORT_1GRx1, /**< FM Rx 1G MAC port block */
+ e_MODULE_ID_FM_PORT_1GRx2, /**< FM Rx 1G MAC port block */
+ e_MODULE_ID_FM_PORT_1GRx3, /**< FM Rx 1G MAC port block */
+ e_MODULE_ID_FM_PORT_1GRx4, /**< FM Rx 1G MAC port block */
+ e_MODULE_ID_FM_PORT_1GRx5, /**< FM Rx 1G MAC port block */
+ e_MODULE_ID_FM_PORT_1GRx6, /**< FM Rx 1G MAC port block */
+ e_MODULE_ID_FM_PORT_10GRx1, /**< FM Rx 10G MAC port block */
+ e_MODULE_ID_FM_PORT_10GRx2, /**< FM Rx 10G MAC port block */
+ e_MODULE_ID_FM_PORT_1GTx1, /**< FM Tx 1G MAC port block */
+ e_MODULE_ID_FM_PORT_1GTx2, /**< FM Tx 1G MAC port block */
+ e_MODULE_ID_FM_PORT_1GTx3, /**< FM Tx 1G MAC port block */
+ e_MODULE_ID_FM_PORT_1GTx4, /**< FM Tx 1G MAC port block */
+ e_MODULE_ID_FM_PORT_1GTx5, /**< FM Tx 1G MAC port block */
+ e_MODULE_ID_FM_PORT_1GTx6, /**< FM Tx 1G MAC port block */
+ e_MODULE_ID_FM_PORT_10GTx1, /**< FM Tx 10G MAC port block */
+ e_MODULE_ID_FM_PORT_10GTx2, /**< FM Tx 10G MAC port block */
+ e_MODULE_ID_FM_PLCR, /**< FM Policer */
+ e_MODULE_ID_FM_KG, /**< FM Keygen */
+ e_MODULE_ID_FM_DMA, /**< FM DMA */
+ e_MODULE_ID_FM_FPM, /**< FM FPM */
+ e_MODULE_ID_FM_IRAM, /**< FM Instruction-RAM */
+ e_MODULE_ID_FM_1GMDIO, /**< FM 1G MDIO MAC */
+ e_MODULE_ID_FM_10GMDIO, /**< FM 10G MDIO */
+ e_MODULE_ID_FM_PRS_IRAM, /**< FM SW-parser Instruction-RAM */
+ e_MODULE_ID_FM_1GMAC1, /**< FM 1G MAC #1 */
+ e_MODULE_ID_FM_1GMAC2, /**< FM 1G MAC #2 */
+ e_MODULE_ID_FM_1GMAC3, /**< FM 1G MAC #3 */
+ e_MODULE_ID_FM_1GMAC4, /**< FM 1G MAC #4 */
+ e_MODULE_ID_FM_1GMAC5, /**< FM 1G MAC #5 */
+ e_MODULE_ID_FM_1GMAC6, /**< FM 1G MAC #6 */
+ e_MODULE_ID_FM_10GMAC1, /**< FM 10G MAC */
+ e_MODULE_ID_FM_10GMAC2, /**< FM 10G MAC */
+
+ e_MODULE_ID_SEC_GEN, /**< SEC 4.0 General registers */
+ e_MODULE_ID_SEC_QI, /**< SEC 4.0 QI registers */
+ e_MODULE_ID_SEC_JQ0, /**< SEC 4.0 JQ-0 registers */
+ e_MODULE_ID_SEC_JQ1, /**< SEC 4.0 JQ-1 registers */
+ e_MODULE_ID_SEC_JQ2, /**< SEC 4.0 JQ-2 registers */
+ e_MODULE_ID_SEC_JQ3, /**< SEC 4.0 JQ-3 registers */
+ e_MODULE_ID_SEC_RTIC, /**< SEC 4.0 RTIC registers */
+ e_MODULE_ID_SEC_DECO0_CCB0, /**< SEC 4.0 DECO-0/CCB-0 registers */
+ e_MODULE_ID_SEC_DECO1_CCB1, /**< SEC 4.0 DECO-1/CCB-1 registers */
+ e_MODULE_ID_SEC_DECO2_CCB2, /**< SEC 4.0 DECO-2/CCB-2 registers */
+ e_MODULE_ID_SEC_DECO3_CCB3, /**< SEC 4.0 DECO-3/CCB-3 registers */
+ e_MODULE_ID_SEC_DECO4_CCB4, /**< SEC 4.0 DECO-4/CCB-4 registers */
+
+ e_MODULE_ID_PIC, /**< PIC */
+ e_MODULE_ID_GPIO, /**< GPIO */
+ e_MODULE_ID_SERDES, /**< SERDES */
+ e_MODULE_ID_CPC_1, /**< CoreNet-Platform-Cache 1 */
+ e_MODULE_ID_CPC_2, /**< CoreNet-Platform-Cache 2 */
+
+ e_MODULE_ID_SRIO_PORTS, /**< RapidIO controller */
+
+ e_MODULE_ID_DUMMY_LAST
+} e_ModuleId;
+
+#define NUM_OF_MODULES e_MODULE_ID_DUMMY_LAST
+
+#if 0 /* using unified values */
+/*****************************************************************************
+ INTEGRATION-SPECIFIC MODULE CODES
+******************************************************************************/
+#define MODULE_UNKNOWN 0x00000000
+#define MODULE_MEM 0x00010000
+#define MODULE_MM 0x00020000
+#define MODULE_CORE 0x00030000
+#define MODULE_T4240 0x00040000
+#define MODULE_T4240_PLATFORM 0x00050000
+#define MODULE_PM 0x00060000
+#define MODULE_MMU 0x00070000
+#define MODULE_PIC 0x00080000
+#define MODULE_CPC 0x00090000
+#define MODULE_DUART 0x000a0000
+#define MODULE_SERDES 0x000b0000
+#define MODULE_PIO 0x000c0000
+#define MODULE_QM 0x000d0000
+#define MODULE_BM 0x000e0000
+#define MODULE_SEC 0x000f0000
+#define MODULE_LAW 0x00100000
+#define MODULE_LBC 0x00110000
+#define MODULE_PAMU 0x00120000
+#define MODULE_FM 0x00130000
+#define MODULE_FM_MURAM 0x00140000
+#define MODULE_FM_PCD 0x00150000
+#define MODULE_FM_RTC 0x00160000
+#define MODULE_FM_MAC 0x00170000
+#define MODULE_FM_PORT 0x00180000
+#define MODULE_FM_SP 0x00190000
+#define MODULE_DPA_PORT 0x001a0000
+#define MODULE_MII 0x001b0000
+#define MODULE_I2C 0x001c0000
+#define MODULE_DMA 0x001d0000
+#define MODULE_DDR 0x001e0000
+#define MODULE_ESPI 0x001f0000
+#define MODULE_DPAA_IPSEC 0x00200000
+#endif /* using unified values */
+
+/*****************************************************************************
+ PAMU INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define PAMU_NUM_OF_PARTITIONS 4
+
+/*****************************************************************************
+ LAW INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define LAW_NUM_OF_WINDOWS 32
+#define LAW_MIN_WINDOW_SIZE 0x0000000000001000LL /**< 4 Kbytes */
+#define LAW_MAX_WINDOW_SIZE 0x0000010000000000LL /**< 1 Tbytes for 40-bit address space */
+
+
+/*****************************************************************************
+ LBC INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+/**************************************************************************//**
+ @Group lbc_exception_grp LBC Exception Unit
+
+ @Description LBC Exception unit API functions, definitions and enums
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Anchor lbc_exbm
+
+ @Collection LBC Errors Bit Mask
+
+ These errors are reported through the exceptions callback..
+ The values can be or'ed in any combination in the errors mask
+ parameter of the errors report structure.
+
+ These errors can also be passed as a bit-mask to
+ LBC_EnableErrorChecking() or LBC_DisableErrorChecking(),
+ for enabling or disabling error checking.
+ @{
+*//***************************************************************************/
+#define LBC_ERR_BUS_MONITOR 0x80000000 /**< Bus monitor error */
+#define LBC_ERR_PARITY_ECC 0x20000000 /**< Parity error for GPCM/UPM */
+#define LBC_ERR_WRITE_PROTECT 0x04000000 /**< Write protection error */
+#define LBC_ERR_CHIP_SELECT 0x00080000 /**< Unrecognized chip select */
+
+#define LBC_ERR_ALL (LBC_ERR_BUS_MONITOR | LBC_ERR_PARITY_ECC | \
+ LBC_ERR_WRITE_PROTECT | LBC_ERR_CHIP_SELECT)
+ /**< All possible errors */
+/* @} */
+/** @} */ /* end of lbc_exception_grp group */
+
+#define LBC_INCORRECT_ERROR_REPORT_ERRATA
+
+#define LBC_NUM_OF_BANKS 8
+#define LBC_MAX_CS_SIZE 0x0000000100000000LL /* Up to 4G memory block size */
+#define LBC_PARITY_SUPPORT
+#define LBC_ADDRESS_HOLD_TIME_CTRL
+#define LBC_HIGH_CLK_DIVIDERS
+#define LBC_FCM_AVAILABLE
+
+/*****************************************************************************
+ GPIO INTEGRATION-SPECIFIC DEFINITIONS
+******************************************************************************/
+#define GPIO_PORT_OFFSET_0x1000
+
+#define GPIO_NUM_OF_PORTS 3 /**< Number of ports in GPIO module;
+ Each port contains up to 32 I/O pins. */
+
+#define GPIO_VALID_PIN_MASKS \
+ { /* Port A */ 0xFFFFFFFF, \
+ /* Port B */ 0xFFFFFFFF, \
+ /* Port C */ 0xFFFFFFFF }
+
+#define GPIO_VALID_INTR_MASKS \
+ { /* Port A */ 0xFFFFFFFF, \
+ /* Port B */ 0xFFFFFFFF, \
+ /* Port C */ 0xFFFFFFFF }
+
+
+
+#endif /* __PART_INTEGRATION_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/math_ext.h b/drivers/net/ethernet/freescale/fman/inc/math_ext.h
new file mode 100644
index 0000000..bff428d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/math_ext.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __MATH_EXT_H
+#define __MATH_EXT_H
+
+
+#if defined(NCSW_LINUX) && defined(__KERNEL__)
+#include <linux/math.h>
+
+#elif defined(__MWERKS__)
+#define LOW(x) ( sizeof(x)==8 ? *(1+(int32_t*)&x) : (*(int32_t*)&x))
+#define HIGH(x) (*(int32_t*)&x)
+#define ULOW(x) ( sizeof(x)==8 ? *(1+(uint32_t*)&x) : (*(uint32_t*)&x))
+#define UHIGH(x) (*(uint32_t*)&x)
+
+static const double big = 1.0e300;
+
+/* Macro for checking if a number is a power of 2 */
+static __inline__ double ceil(double x)
+{
+ int32_t i0,i1,j0; /*- cc 020130 -*/
+ uint32_t i,j; /*- cc 020130 -*/
+ i0 = HIGH(x);
+ i1 = LOW(x);
+ j0 = ((i0>>20)&0x7ff)-0x3ff;
+ if(j0<20) {
+ if(j0<0) { /* raise inexact if x != 0 */
+ if(big+x>0.0) {/* return 0*sign(x) if |x|<1 */
+ if(i0<0) {i0=0x80000000;i1=0;}
+ else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;}
+ }
+ } else {
+ i = (uint32_t)(0x000fffff)>>j0;
+ if(((i0&i)|i1)==0) return x; /* x is integral */
+ if(big+x>0.0) { /* raise inexact flag */
+ if(i0>0) i0 += (0x00100000)>>j0;
+ i0 &= (~i); i1=0;
+ }
+ }
+ } else if (j0>51) {
+ if(j0==0x400) return x+x; /* inf or NaN */
+ else return x; /* x is integral */
+ } else {
+ i = ((uint32_t)(0xffffffff))>>(j0-20); /*- cc 020130 -*/
+ if((i1&i)==0) return x; /* x is integral */
+ if(big+x>0.0) { /* raise inexact flag */
+ if(i0>0) {
+ if(j0==20) i0+=1;
+ else {
+ j = (uint32_t)(i1 + (1<<(52-j0)));
+ if(j<i1) i0+=1; /* got a carry */
+ i1 = (int32_t)j;
+ }
+ }
+ i1 &= (~i);
+ }
+ }
+ HIGH(x) = i0;
+ LOW(x) = i1;
+ return x;
+}
+
+#else
+#include <math.h>
+#endif /* defined(NCSW_LINUX) && defined(__KERNEL__) */
+
+
+#endif /* __MATH_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/ncsw_ext.h b/drivers/net/ethernet/freescale/fman/inc/ncsw_ext.h
new file mode 100644
index 0000000..c3341cd
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/ncsw_ext.h
@@ -0,0 +1,432 @@
+/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File ncsw_ext.h
+
+ @Description General NetCommSw Standard Definitions
+*//***************************************************************************/
+
+#ifndef __NCSW_EXT_H
+#define __NCSW_EXT_H
+
+#include "memcpy_ext.h"
+
+
+#define WRITE_BLOCK IOMemSet32
+#define COPY_BLOCK Mem2IOCpy32
+
+#define PTR_TO_UINT(_ptr) ((uintptr_t)(_ptr))
+#define UINT_TO_PTR(_val) ((void*)(uintptr_t)(_val))
+
+#define PTR_MOVE(_ptr, _offset) (void*)((uint8_t*)(_ptr) + (_offset))
+
+
+#define WRITE_UINT8_UINT24(arg, data08, data24) WRITE_UINT32(arg,((uint32_t)(data08)<<24)|((uint32_t)(data24)&0x00FFFFFF))
+#define WRITE_UINT24_UINT8(arg, data24, data08) WRITE_UINT32(arg,((uint32_t)(data24)<< 8)|((uint32_t)(data08)&0x000000FF))
+
+/* Little-Endian access macros */
+
+#define WRITE_UINT16_LE(arg, data) \
+ WRITE_UINT16((arg), SwapUint16(data))
+
+#define WRITE_UINT32_LE(arg, data) \
+ WRITE_UINT32((arg), SwapUint32(data))
+
+#define WRITE_UINT64_LE(arg, data) \
+ WRITE_UINT64((arg), SwapUint64(data))
+
+#define GET_UINT16_LE(arg) \
+ SwapUint16(GET_UINT16(arg))
+
+#define GET_UINT32_LE(arg) \
+ SwapUint32(GET_UINT32(arg))
+
+#define GET_UINT64_LE(arg) \
+ SwapUint64(GET_UINT64(arg))
+
+/* Write and Read again macros */
+#define WRITE_UINT_SYNC(size, arg, data) \
+ do { \
+ WRITE_UINT##size((arg), (data)); \
+ CORE_MemoryBarrier(); \
+ } while (0)
+
+#define WRITE_UINT8_SYNC(arg, data) WRITE_UINT_SYNC(8, (arg), (data))
+
+#define WRITE_UINT16_SYNC(arg, data) WRITE_UINT_SYNC(16, (arg), (data))
+#define WRITE_UINT32_SYNC(arg, data) WRITE_UINT_SYNC(32, (arg), (data))
+
+#define MAKE_UINT64(high32, low32) (((uint64_t)high32 << 32) | (low32))
+
+
+/*----------------------*/
+/* Miscellaneous macros */
+/*----------------------*/
+
+#define UNUSED(X) (X=X)
+
+#define KILOBYTE 0x400UL /* 1024 */
+#define MEGABYTE (KILOBYTE * KILOBYTE) /* 1024*1024 */
+#define GIGABYTE ((uint64_t)(KILOBYTE * MEGABYTE)) /* 1024*1024*1024 */
+#define TERABYTE ((uint64_t)(KILOBYTE * GIGABYTE)) /* 1024*1024*1024*1024 */
+
+#undef NO_IRQ
+#define NO_IRQ (-1)
+#define NCSW_MASTER_ID (0)
+
+/* Macro for checking if a number is a power of 2 */
+#define POWER_OF_2(n) (!((n) & ((n)-1)))
+
+/* Macro for calculating log of base 2 */
+#define LOG2(num, log2Num) \
+ do \
+ { \
+ uint64_t tmp = (num); \
+ log2Num = 0; \
+ while (tmp > 1) \
+ { \
+ log2Num++; \
+ tmp >>= 1; \
+ } \
+ } while (0)
+
+#define NEXT_POWER_OF_2(_num, _nextPow) \
+do \
+{ \
+ if (POWER_OF_2(_num)) \
+ _nextPow = (_num); \
+ else \
+ { \
+ uint64_t tmp = (_num); \
+ _nextPow = 1; \
+ while (tmp) \
+ { \
+ _nextPow <<= 1; \
+ tmp >>= 1; \
+ } \
+ } \
+} while (0)
+
+/* Ceiling division - not the fastest way, but safer in terms of overflow */
+#define DIV_CEIL(x,y) (((x)/(y)) + ((((((x)/(y)))*(y)) == (x)) ? 0 : 1))
+
+/* Round up a number to be a multiple of a second number */
+#define ROUND_UP(x,y) ((((x) + (y) - 1) / (y)) * (y))
+
+/* Timing macro for converting usec units to number of ticks. */
+/* (number of usec * clock_Hz) / 1,000,000) - since */
+/* clk is in MHz units, no division needed. */
+#define USEC_TO_CLK(usec,clk) ((usec) * (clk))
+#define CYCLES_TO_USEC(cycles,clk) ((cycles) / (clk))
+
+/* Timing macros for converting between nsec units and number of clocks. */
+#define NSEC_TO_CLK(nsec,clk) DIV_CEIL(((nsec) * (clk)), 1000)
+#define CYCLES_TO_NSEC(cycles,clk) (((cycles) * 1000) / (clk))
+
+/* Timing macros for converting between psec units and number of clocks. */
+#define PSEC_TO_CLK(psec,clk) DIV_CEIL(((psec) * (clk)), 1000000)
+#define CYCLES_TO_PSEC(cycles,clk) (((cycles) * 1000000) / (clk))
+
+/* Min, Max macros */
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define IN_RANGE(min,val,max) ((min)<=(val) && (val)<=(max))
+
+#define ABS(a) ((a<0)?(a*-1):a)
+
+#if !(defined(ARRAY_SIZE))
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#endif /* !defined(ARRAY_SIZE) */
+
+
+/* possible alignments */
+#define HALF_WORD_ALIGNMENT 2
+#define WORD_ALIGNMENT 4
+#define DOUBLE_WORD_ALIGNMENT 8
+#define BURST_ALIGNMENT 32
+
+#define HALF_WORD_ALIGNED 0x00000001
+#define WORD_ALIGNED 0x00000003
+#define DOUBLE_WORD_ALIGNED 0x00000007
+#define BURST_ALIGNED 0x0000001f
+#ifndef IS_ALIGNED
+#define IS_ALIGNED(n,align) (!((uint32_t)(n) & (align - 1)))
+#endif /* IS_ALIGNED */
+
+
+#define LAST_BUF 1
+#define FIRST_BUF 2
+#define SINGLE_BUF (LAST_BUF | FIRST_BUF)
+#define MIDDLE_BUF 4
+
+#define ARRAY_END -1
+
+#define ILLEGAL_BASE (~0)
+
+#define BUF_POSITION(first, last) state[(!!(last))<<1 | !!(first)]
+#define DECLARE_POSITION static uint8_t state[4] = { (uint8_t)MIDDLE_BUF, (uint8_t)FIRST_BUF, (uint8_t)LAST_BUF, (uint8_t)SINGLE_BUF };
+
+
+/**************************************************************************//**
+ @Description Timers operation mode
+*//***************************************************************************/
+typedef enum e_TimerMode
+{
+ e_TIMER_MODE_INVALID = 0,
+ e_TIMER_MODE_FREE_RUN, /**< Free run - counter continues to increase
+ after reaching the reference value. */
+ e_TIMER_MODE_PERIODIC, /**< Periodic - counter restarts counting from 0
+ after reaching the reference value. */
+ e_TIMER_MODE_SINGLE /**< Single (one-shot) - counter stops counting
+ after reaching the reference value. */
+} e_TimerMode;
+
+
+/**************************************************************************//**
+ @Description Enumeration (bit flags) of communication modes (Transmit,
+ receive or both).
+*//***************************************************************************/
+typedef enum e_CommMode
+{
+ e_COMM_MODE_NONE = 0, /**< No transmit/receive communication */
+ e_COMM_MODE_RX = 1, /**< Only receive communication */
+ e_COMM_MODE_TX = 2, /**< Only transmit communication */
+ e_COMM_MODE_RX_AND_TX = 3 /**< Both transmit and receive communication */
+} e_CommMode;
+
+/**************************************************************************//**
+ @Description General Diagnostic Mode
+*//***************************************************************************/
+typedef enum e_DiagMode
+{
+ e_DIAG_MODE_NONE = 0, /**< Normal operation; no diagnostic mode */
+ e_DIAG_MODE_CTRL_LOOPBACK, /**< Loopback in the controller */
+ e_DIAG_MODE_CHIP_LOOPBACK, /**< Loopback in the chip but not in the
+ controller; e.g. IO-pins, SerDes, etc. */
+ e_DIAG_MODE_PHY_LOOPBACK, /**< Loopback in the external PHY */
+ e_DIAG_MODE_EXT_LOOPBACK, /**< Loopback in the external line (beyond the PHY) */
+ e_DIAG_MODE_CTRL_ECHO, /**< Echo incoming data by the controller */
+ e_DIAG_MODE_PHY_ECHO /**< Echo incoming data by the PHY */
+} e_DiagMode;
+
+/**************************************************************************//**
+ @Description Possible RxStore callback responses.
+*//***************************************************************************/
+typedef enum e_RxStoreResponse
+{
+ e_RX_STORE_RESPONSE_PAUSE /**< Pause invoking callback with received data;
+ in polling mode, start again invoking callback
+ only next time user invokes the receive routine;
+ in interrupt mode, start again invoking callback
+ only next time a receive event triggers an interrupt;
+ in all cases, received data that are pending are not
+ lost, rather, their processing is temporarily deferred;
+ in all cases, received data are processed in the order
+ in which they were received. */
+ , e_RX_STORE_RESPONSE_CONTINUE /**< Continue invoking callback with received data. */
+} e_RxStoreResponse;
+
+
+/**************************************************************************//**
+ @Description General Handle
+*//***************************************************************************/
+typedef void * t_Handle; /**< handle, used as object's descriptor */
+
+/**************************************************************************//**
+ @Description MUTEX type
+*//***************************************************************************/
+typedef uint32_t t_Mutex;
+
+/**************************************************************************//**
+ @Description Error Code.
+
+ The high word of the error code is the code of the software
+ module (driver). The low word is the error type (e_ErrorType).
+ To get the values from the error code, use GET_ERROR_TYPE()
+ and GET_ERROR_MODULE().
+*//***************************************************************************/
+typedef uint32_t t_Error;
+
+/**************************************************************************//**
+ @Description General prototype of interrupt service routine (ISR).
+
+ @Param[in] handle - Optional handle of the module handling the interrupt.
+
+ @Return None
+ *//***************************************************************************/
+typedef void (t_Isr)(t_Handle handle);
+
+/**************************************************************************//**
+ @Anchor mem_attr
+
+ @Collection Memory Attributes
+
+ Various attributes of memory partitions. These values may be
+ or'ed together to create a mask of all memory attributes.
+ @{
+*//***************************************************************************/
+#define MEMORY_ATTR_CACHEABLE 0x00000001
+ /**< Memory is cacheable */
+#define MEMORY_ATTR_QE_2ND_BUS_ACCESS 0x00000002
+ /**< Memory can be accessed by QUICC Engine
+ through its secondary bus interface */
+
+/* @} */
+
+
+/**************************************************************************//**
+ @Function t_GetBufFunction
+
+ @Description User callback function called by driver to get data buffer.
+
+ User provides this function. Driver invokes it.
+
+ @Param[in] h_BufferPool - A handle to buffer pool manager
+ @Param[out] p_BufContextHandle - Returns the user's private context that
+ should be associated with the buffer
+
+ @Return Pointer to data buffer, NULL if error
+ *//***************************************************************************/
+typedef uint8_t * (t_GetBufFunction)(t_Handle h_BufferPool,
+ t_Handle *p_BufContextHandle);
+
+/**************************************************************************//**
+ @Function t_PutBufFunction
+
+ @Description User callback function called by driver to return data buffer.
+
+ User provides this function. Driver invokes it.
+
+ @Param[in] h_BufferPool - A handle to buffer pool manager
+ @Param[in] p_Buffer - A pointer to buffer to return
+ @Param[in] h_BufContext - The user's private context associated with
+ the returned buffer
+
+ @Return E_OK on success; Error code otherwise
+ *//***************************************************************************/
+typedef t_Error (t_PutBufFunction)(t_Handle h_BufferPool,
+ uint8_t *p_Buffer,
+ t_Handle h_BufContext);
+
+/**************************************************************************//**
+ @Function t_PhysToVirt
+
+ @Description Translates a physical address to the matching virtual address.
+
+ @Param[in] addr - The physical address to translate.
+
+ @Return Virtual address.
+*//***************************************************************************/
+typedef void * t_PhysToVirt(physAddress_t addr);
+
+/**************************************************************************//**
+ @Function t_VirtToPhys
+
+ @Description Translates a virtual address to the matching physical address.
+
+ @Param[in] addr - The virtual address to translate.
+
+ @Return Physical address.
+*//***************************************************************************/
+typedef physAddress_t t_VirtToPhys(void *addr);
+
+/**************************************************************************//**
+ @Description Buffer Pool Information Structure.
+*//***************************************************************************/
+typedef struct t_BufferPoolInfo
+{
+ t_Handle h_BufferPool; /**< A handle to the buffer pool manager */
+ t_GetBufFunction *f_GetBuf; /**< User callback to get a free buffer */
+ t_PutBufFunction *f_PutBuf; /**< User callback to return a buffer */
+ uint16_t bufferSize; /**< Buffer size (in bytes) */
+
+ t_PhysToVirt *f_PhysToVirt; /**< User callback to translate pool buffers
+ physical addresses to virtual addresses */
+ t_VirtToPhys *f_VirtToPhys; /**< User callback to translate pool buffers
+ virtual addresses to physical addresses */
+} t_BufferPoolInfo;
+
+
+/**************************************************************************//**
+ @Description User callback function called by driver when transmit completed.
+
+ User provides this function. Driver invokes it.
+
+ @Param[in] h_App - Application's handle, as was provided to the
+ driver by the user
+ @Param[in] queueId - Transmit queue ID
+ @Param[in] p_Data - Pointer to the data buffer
+ @Param[in] h_BufContext - The user's private context associated with
+ the given data buffer
+ @Param[in] status - Transmit status and errors
+ @Param[in] flags - Driver-dependent information
+ *//***************************************************************************/
+typedef void (t_TxConfFunction)(t_Handle h_App,
+ uint32_t queueId,
+ uint8_t *p_Data,
+ t_Handle h_BufContext,
+ uint16_t status,
+ uint32_t flags);
+
+/**************************************************************************//**
+ @Description User callback function called by driver with receive data.
+
+ User provides this function. Driver invokes it.
+
+ @Param[in] h_App - Application's handle, as was provided to the
+ driver by the user
+ @Param[in] queueId - Receive queue ID
+ @Param[in] p_Data - Pointer to the buffer with received data
+ @Param[in] h_BufContext - The user's private context associated with
+ the given data buffer
+ @Param[in] length - Length of received data
+ @Param[in] status - Receive status and errors
+ @Param[in] position - Position of buffer in frame
+ @Param[in] flags - Driver-dependent information
+
+ @Retval e_RX_STORE_RESPONSE_CONTINUE - order the driver to continue Rx
+ operation for all ready data.
+ @Retval e_RX_STORE_RESPONSE_PAUSE - order the driver to stop Rx operation.
+ *//***************************************************************************/
+typedef e_RxStoreResponse (t_RxStoreFunction)(t_Handle h_App,
+ uint32_t queueId,
+ uint8_t *p_Data,
+ t_Handle h_BufContext,
+ uint32_t length,
+ uint16_t status,
+ uint8_t position,
+ uint32_t flags);
+
+
+#endif /* __NCSW_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/net_ext.h b/drivers/net/ethernet/freescale/fman/inc/net_ext.h
new file mode 100644
index 0000000..8f3bc36
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/net_ext.h
@@ -0,0 +1,430 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File net_ext.h
+
+ @Description This file contains common and general netcomm headers definitions.
+*//***************************************************************************/
+#ifndef __NET_EXT_H
+#define __NET_EXT_H
+
+#include "std_ext.h"
+
+
+typedef uint8_t headerFieldPpp_t;
+
+#define NET_HEADER_FIELD_PPP_PID (1)
+#define NET_HEADER_FIELD_PPP_COMPRESSED (NET_HEADER_FIELD_PPP_PID << 1)
+#define NET_HEADER_FIELD_PPP_ALL_FIELDS ((NET_HEADER_FIELD_PPP_PID << 2) - 1)
+
+
+typedef uint8_t headerFieldPppoe_t;
+
+#define NET_HEADER_FIELD_PPPoE_VER (1)
+#define NET_HEADER_FIELD_PPPoE_TYPE (NET_HEADER_FIELD_PPPoE_VER << 1)
+#define NET_HEADER_FIELD_PPPoE_CODE (NET_HEADER_FIELD_PPPoE_VER << 2)
+#define NET_HEADER_FIELD_PPPoE_SID (NET_HEADER_FIELD_PPPoE_VER << 3)
+#define NET_HEADER_FIELD_PPPoE_LEN (NET_HEADER_FIELD_PPPoE_VER << 4)
+#define NET_HEADER_FIELD_PPPoE_SESSION (NET_HEADER_FIELD_PPPoE_VER << 5)
+#define NET_HEADER_FIELD_PPPoE_PID (NET_HEADER_FIELD_PPPoE_VER << 6)
+#define NET_HEADER_FIELD_PPPoE_ALL_FIELDS ((NET_HEADER_FIELD_PPPoE_VER << 7) - 1)
+
+#define NET_HEADER_FIELD_PPPMUX_PID (1)
+#define NET_HEADER_FIELD_PPPMUX_CKSUM (NET_HEADER_FIELD_PPPMUX_PID << 1)
+#define NET_HEADER_FIELD_PPPMUX_COMPRESSED (NET_HEADER_FIELD_PPPMUX_PID << 2)
+#define NET_HEADER_FIELD_PPPMUX_ALL_FIELDS ((NET_HEADER_FIELD_PPPMUX_PID << 3) - 1)
+
+#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF (1)
+#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_LXT (NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 1)
+#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_LEN (NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 2)
+#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_PID (NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 3)
+#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_USE_PID (NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 4)
+#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_ALL_FIELDS ((NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 5) - 1)
+
+
+typedef uint8_t headerFieldEth_t;
+
+#define NET_HEADER_FIELD_ETH_DA (1)
+#define NET_HEADER_FIELD_ETH_SA (NET_HEADER_FIELD_ETH_DA << 1)
+#define NET_HEADER_FIELD_ETH_LENGTH (NET_HEADER_FIELD_ETH_DA << 2)
+#define NET_HEADER_FIELD_ETH_TYPE (NET_HEADER_FIELD_ETH_DA << 3)
+#define NET_HEADER_FIELD_ETH_FINAL_CKSUM (NET_HEADER_FIELD_ETH_DA << 4)
+#define NET_HEADER_FIELD_ETH_PADDING (NET_HEADER_FIELD_ETH_DA << 5)
+#define NET_HEADER_FIELD_ETH_ALL_FIELDS ((NET_HEADER_FIELD_ETH_DA << 6) - 1)
+
+#define NET_HEADER_FIELD_ETH_ADDR_SIZE 6
+
+typedef uint16_t headerFieldIp_t;
+
+#define NET_HEADER_FIELD_IP_VER (1)
+#define NET_HEADER_FIELD_IP_DSCP (NET_HEADER_FIELD_IP_VER << 2)
+#define NET_HEADER_FIELD_IP_ECN (NET_HEADER_FIELD_IP_VER << 3)
+#define NET_HEADER_FIELD_IP_PROTO (NET_HEADER_FIELD_IP_VER << 4)
+
+#define NET_HEADER_FIELD_IP_PROTO_SIZE 1
+
+typedef uint16_t headerFieldIpv4_t;
+
+#define NET_HEADER_FIELD_IPv4_VER (1)
+#define NET_HEADER_FIELD_IPv4_HDR_LEN (NET_HEADER_FIELD_IPv4_VER << 1)
+#define NET_HEADER_FIELD_IPv4_TOS (NET_HEADER_FIELD_IPv4_VER << 2)
+#define NET_HEADER_FIELD_IPv4_TOTAL_LEN (NET_HEADER_FIELD_IPv4_VER << 3)
+#define NET_HEADER_FIELD_IPv4_ID (NET_HEADER_FIELD_IPv4_VER << 4)
+#define NET_HEADER_FIELD_IPv4_FLAG_D (NET_HEADER_FIELD_IPv4_VER << 5)
+#define NET_HEADER_FIELD_IPv4_FLAG_M (NET_HEADER_FIELD_IPv4_VER << 6)
+#define NET_HEADER_FIELD_IPv4_OFFSET (NET_HEADER_FIELD_IPv4_VER << 7)
+#define NET_HEADER_FIELD_IPv4_TTL (NET_HEADER_FIELD_IPv4_VER << 8)
+#define NET_HEADER_FIELD_IPv4_PROTO (NET_HEADER_FIELD_IPv4_VER << 9)
+#define NET_HEADER_FIELD_IPv4_CKSUM (NET_HEADER_FIELD_IPv4_VER << 10)
+#define NET_HEADER_FIELD_IPv4_SRC_IP (NET_HEADER_FIELD_IPv4_VER << 11)
+#define NET_HEADER_FIELD_IPv4_DST_IP (NET_HEADER_FIELD_IPv4_VER << 12)
+#define NET_HEADER_FIELD_IPv4_OPTS (NET_HEADER_FIELD_IPv4_VER << 13)
+#define NET_HEADER_FIELD_IPv4_OPTS_COUNT (NET_HEADER_FIELD_IPv4_VER << 14)
+#define NET_HEADER_FIELD_IPv4_ALL_FIELDS ((NET_HEADER_FIELD_IPv4_VER << 15) - 1)
+
+#define NET_HEADER_FIELD_IPv4_ADDR_SIZE 4
+#define NET_HEADER_FIELD_IPv4_PROTO_SIZE 1
+
+
+typedef uint8_t headerFieldIpv6_t;
+
+#define NET_HEADER_FIELD_IPv6_VER (1)
+#define NET_HEADER_FIELD_IPv6_TC (NET_HEADER_FIELD_IPv6_VER << 1)
+#define NET_HEADER_FIELD_IPv6_SRC_IP (NET_HEADER_FIELD_IPv6_VER << 2)
+#define NET_HEADER_FIELD_IPv6_DST_IP (NET_HEADER_FIELD_IPv6_VER << 3)
+#define NET_HEADER_FIELD_IPv6_NEXT_HDR (NET_HEADER_FIELD_IPv6_VER << 4)
+#define NET_HEADER_FIELD_IPv6_FL (NET_HEADER_FIELD_IPv6_VER << 5)
+#define NET_HEADER_FIELD_IPv6_HOP_LIMIT (NET_HEADER_FIELD_IPv6_VER << 6)
+#define NET_HEADER_FIELD_IPv6_ALL_FIELDS ((NET_HEADER_FIELD_IPv6_VER << 7) - 1)
+
+#define NET_HEADER_FIELD_IPv6_ADDR_SIZE 16
+#define NET_HEADER_FIELD_IPv6_NEXT_HDR_SIZE 1
+
+#define NET_HEADER_FIELD_ICMP_TYPE (1)
+#define NET_HEADER_FIELD_ICMP_CODE (NET_HEADER_FIELD_ICMP_TYPE << 1)
+#define NET_HEADER_FIELD_ICMP_CKSUM (NET_HEADER_FIELD_ICMP_TYPE << 2)
+#define NET_HEADER_FIELD_ICMP_ID (NET_HEADER_FIELD_ICMP_TYPE << 3)
+#define NET_HEADER_FIELD_ICMP_SQ_NUM (NET_HEADER_FIELD_ICMP_TYPE << 4)
+#define NET_HEADER_FIELD_ICMP_ALL_FIELDS ((NET_HEADER_FIELD_ICMP_TYPE << 5) - 1)
+
+#define NET_HEADER_FIELD_ICMP_CODE_SIZE 1
+#define NET_HEADER_FIELD_ICMP_TYPE_SIZE 1
+
+#define NET_HEADER_FIELD_IGMP_VERSION (1)
+#define NET_HEADER_FIELD_IGMP_TYPE (NET_HEADER_FIELD_IGMP_VERSION << 1)
+#define NET_HEADER_FIELD_IGMP_CKSUM (NET_HEADER_FIELD_IGMP_VERSION << 2)
+#define NET_HEADER_FIELD_IGMP_DATA (NET_HEADER_FIELD_IGMP_VERSION << 3)
+#define NET_HEADER_FIELD_IGMP_ALL_FIELDS ((NET_HEADER_FIELD_IGMP_VERSION << 4) - 1)
+
+
+typedef uint16_t headerFieldTcp_t;
+
+#define NET_HEADER_FIELD_TCP_PORT_SRC (1)
+#define NET_HEADER_FIELD_TCP_PORT_DST (NET_HEADER_FIELD_TCP_PORT_SRC << 1)
+#define NET_HEADER_FIELD_TCP_SEQ (NET_HEADER_FIELD_TCP_PORT_SRC << 2)
+#define NET_HEADER_FIELD_TCP_ACK (NET_HEADER_FIELD_TCP_PORT_SRC << 3)
+#define NET_HEADER_FIELD_TCP_OFFSET (NET_HEADER_FIELD_TCP_PORT_SRC << 4)
+#define NET_HEADER_FIELD_TCP_FLAGS (NET_HEADER_FIELD_TCP_PORT_SRC << 5)
+#define NET_HEADER_FIELD_TCP_WINDOW (NET_HEADER_FIELD_TCP_PORT_SRC << 6)
+#define NET_HEADER_FIELD_TCP_CKSUM (NET_HEADER_FIELD_TCP_PORT_SRC << 7)
+#define NET_HEADER_FIELD_TCP_URGPTR (NET_HEADER_FIELD_TCP_PORT_SRC << 8)
+#define NET_HEADER_FIELD_TCP_OPTS (NET_HEADER_FIELD_TCP_PORT_SRC << 9)
+#define NET_HEADER_FIELD_TCP_OPTS_COUNT (NET_HEADER_FIELD_TCP_PORT_SRC << 10)
+#define NET_HEADER_FIELD_TCP_ALL_FIELDS ((NET_HEADER_FIELD_TCP_PORT_SRC << 11) - 1)
+
+#define NET_HEADER_FIELD_TCP_PORT_SIZE 2
+
+
+typedef uint8_t headerFieldSctp_t;
+
+#define NET_HEADER_FIELD_SCTP_PORT_SRC (1)
+#define NET_HEADER_FIELD_SCTP_PORT_DST (NET_HEADER_FIELD_SCTP_PORT_SRC << 1)
+#define NET_HEADER_FIELD_SCTP_VER_TAG (NET_HEADER_FIELD_SCTP_PORT_SRC << 2)
+#define NET_HEADER_FIELD_SCTP_CKSUM (NET_HEADER_FIELD_SCTP_PORT_SRC << 3)
+#define NET_HEADER_FIELD_SCTP_ALL_FIELDS ((NET_HEADER_FIELD_SCTP_PORT_SRC << 4) - 1)
+
+#define NET_HEADER_FIELD_SCTP_PORT_SIZE 2
+
+typedef uint8_t headerFieldDccp_t;
+
+#define NET_HEADER_FIELD_DCCP_PORT_SRC (1)
+#define NET_HEADER_FIELD_DCCP_PORT_DST (NET_HEADER_FIELD_DCCP_PORT_SRC << 1)
+#define NET_HEADER_FIELD_DCCP_ALL_FIELDS ((NET_HEADER_FIELD_DCCP_PORT_SRC << 2) - 1)
+
+#define NET_HEADER_FIELD_DCCP_PORT_SIZE 2
+
+
+typedef uint8_t headerFieldUdp_t;
+
+#define NET_HEADER_FIELD_UDP_PORT_SRC (1)
+#define NET_HEADER_FIELD_UDP_PORT_DST (NET_HEADER_FIELD_UDP_PORT_SRC << 1)
+#define NET_HEADER_FIELD_UDP_LEN (NET_HEADER_FIELD_UDP_PORT_SRC << 2)
+#define NET_HEADER_FIELD_UDP_CKSUM (NET_HEADER_FIELD_UDP_PORT_SRC << 3)
+#define NET_HEADER_FIELD_UDP_ALL_FIELDS ((NET_HEADER_FIELD_UDP_PORT_SRC << 4) - 1)
+
+#define NET_HEADER_FIELD_UDP_PORT_SIZE 2
+
+typedef uint8_t headerFieldUdpLite_t;
+
+#define NET_HEADER_FIELD_UDP_LITE_PORT_SRC (1)
+#define NET_HEADER_FIELD_UDP_LITE_PORT_DST (NET_HEADER_FIELD_UDP_LITE_PORT_SRC << 1)
+#define NET_HEADER_FIELD_UDP_LITE_ALL_FIELDS ((NET_HEADER_FIELD_UDP_LITE_PORT_SRC << 2) - 1)
+
+#define NET_HEADER_FIELD_UDP_LITE_PORT_SIZE 2
+
+typedef uint8_t headerFieldUdpEncapEsp_t;
+
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC (1)
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_DST (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 1)
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_LEN (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 2)
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_CKSUM (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 3)
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 4)
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_SEQUENCE_NUM (NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 5)
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_ALL_FIELDS ((NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 6) - 1)
+
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SIZE 2
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI_SIZE 4
+
+#define NET_HEADER_FIELD_IPHC_CID (1)
+#define NET_HEADER_FIELD_IPHC_CID_TYPE (NET_HEADER_FIELD_IPHC_CID << 1)
+#define NET_HEADER_FIELD_IPHC_HCINDEX (NET_HEADER_FIELD_IPHC_CID << 2)
+#define NET_HEADER_FIELD_IPHC_GEN (NET_HEADER_FIELD_IPHC_CID << 3)
+#define NET_HEADER_FIELD_IPHC_D_BIT (NET_HEADER_FIELD_IPHC_CID << 4)
+#define NET_HEADER_FIELD_IPHC_ALL_FIELDS ((NET_HEADER_FIELD_IPHC_CID << 5) - 1)
+
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE (1)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_FLAGS (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 1)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_LENGTH (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 2)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_TSN (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 3)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_STREAM_ID (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 4)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_STREAM_SQN (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 5)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_PAYLOAD_PID (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 6)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_UNORDERED (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 7)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_BEGGINING (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 8)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_END (NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 9)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_ALL_FIELDS ((NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 10) - 1)
+
+#define NET_HEADER_FIELD_L2TPv2_TYPE_BIT (1)
+#define NET_HEADER_FIELD_L2TPv2_LENGTH_BIT (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 1)
+#define NET_HEADER_FIELD_L2TPv2_SEQUENCE_BIT (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 2)
+#define NET_HEADER_FIELD_L2TPv2_OFFSET_BIT (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 3)
+#define NET_HEADER_FIELD_L2TPv2_PRIORITY_BIT (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 4)
+#define NET_HEADER_FIELD_L2TPv2_VERSION (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 5)
+#define NET_HEADER_FIELD_L2TPv2_LEN (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 6)
+#define NET_HEADER_FIELD_L2TPv2_TUNNEL_ID (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 7)
+#define NET_HEADER_FIELD_L2TPv2_SESSION_ID (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 8)
+#define NET_HEADER_FIELD_L2TPv2_NS (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 9)
+#define NET_HEADER_FIELD_L2TPv2_NR (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 10)
+#define NET_HEADER_FIELD_L2TPv2_OFFSET_SIZE (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 11)
+#define NET_HEADER_FIELD_L2TPv2_FIRST_BYTE (NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 12)
+#define NET_HEADER_FIELD_L2TPv2_ALL_FIELDS ((NET_HEADER_FIELD_L2TPv2_TYPE_BIT << 13) - 1)
+
+#define NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT (1)
+#define NET_HEADER_FIELD_L2TPv3_CTRL_LENGTH_BIT (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 1)
+#define NET_HEADER_FIELD_L2TPv3_CTRL_SEQUENCE_BIT (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 2)
+#define NET_HEADER_FIELD_L2TPv3_CTRL_VERSION (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 3)
+#define NET_HEADER_FIELD_L2TPv3_CTRL_LENGTH (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 4)
+#define NET_HEADER_FIELD_L2TPv3_CTRL_CONTROL (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 5)
+#define NET_HEADER_FIELD_L2TPv3_CTRL_SENT (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 6)
+#define NET_HEADER_FIELD_L2TPv3_CTRL_RECV (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 7)
+#define NET_HEADER_FIELD_L2TPv3_CTRL_FIRST_BYTE (NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 8)
+#define NET_HEADER_FIELD_L2TPv3_CTRL_ALL_FIELDS ((NET_HEADER_FIELD_L2TPv3_CTRL_TYPE_BIT << 9) - 1)
+
+#define NET_HEADER_FIELD_L2TPv3_SESS_TYPE_BIT (1)
+#define NET_HEADER_FIELD_L2TPv3_SESS_VERSION (NET_HEADER_FIELD_L2TPv3_SESS_TYPE_BIT << 1)
+#define NET_HEADER_FIELD_L2TPv3_SESS_ID (NET_HEADER_FIELD_L2TPv3_SESS_TYPE_BIT << 2)
+#define NET_HEADER_FIELD_L2TPv3_SESS_COOKIE (NET_HEADER_FIELD_L2TPv3_SESS_TYPE_BIT << 3)
+#define NET_HEADER_FIELD_L2TPv3_SESS_ALL_FIELDS ((NET_HEADER_FIELD_L2TPv3_SESS_TYPE_BIT << 4) - 1)
+
+
+typedef uint8_t headerFieldVlan_t;
+
+#define NET_HEADER_FIELD_VLAN_VPRI (1)
+#define NET_HEADER_FIELD_VLAN_CFI (NET_HEADER_FIELD_VLAN_VPRI << 1)
+#define NET_HEADER_FIELD_VLAN_VID (NET_HEADER_FIELD_VLAN_VPRI << 2)
+#define NET_HEADER_FIELD_VLAN_LENGTH (NET_HEADER_FIELD_VLAN_VPRI << 3)
+#define NET_HEADER_FIELD_VLAN_TYPE (NET_HEADER_FIELD_VLAN_VPRI << 4)
+#define NET_HEADER_FIELD_VLAN_ALL_FIELDS ((NET_HEADER_FIELD_VLAN_VPRI << 5) - 1)
+
+#define NET_HEADER_FIELD_VLAN_TCI (NET_HEADER_FIELD_VLAN_VPRI | \
+ NET_HEADER_FIELD_VLAN_CFI | \
+ NET_HEADER_FIELD_VLAN_VID)
+
+
+typedef uint8_t headerFieldLlc_t;
+
+#define NET_HEADER_FIELD_LLC_DSAP (1)
+#define NET_HEADER_FIELD_LLC_SSAP (NET_HEADER_FIELD_LLC_DSAP << 1)
+#define NET_HEADER_FIELD_LLC_CTRL (NET_HEADER_FIELD_LLC_DSAP << 2)
+#define NET_HEADER_FIELD_LLC_ALL_FIELDS ((NET_HEADER_FIELD_LLC_DSAP << 3) - 1)
+
+#define NET_HEADER_FIELD_NLPID_NLPID (1)
+#define NET_HEADER_FIELD_NLPID_ALL_FIELDS ((NET_HEADER_FIELD_NLPID_NLPID << 1) - 1)
+
+
+typedef uint8_t headerFieldSnap_t;
+
+#define NET_HEADER_FIELD_SNAP_OUI (1)
+#define NET_HEADER_FIELD_SNAP_PID (NET_HEADER_FIELD_SNAP_OUI << 1)
+#define NET_HEADER_FIELD_SNAP_ALL_FIELDS ((NET_HEADER_FIELD_SNAP_OUI << 2) - 1)
+
+
+typedef uint8_t headerFieldLlcSnap_t;
+
+#define NET_HEADER_FIELD_LLC_SNAP_TYPE (1)
+#define NET_HEADER_FIELD_LLC_SNAP_ALL_FIELDS ((NET_HEADER_FIELD_LLC_SNAP_TYPE << 1) - 1)
+
+#define NET_HEADER_FIELD_ARP_HTYPE (1)
+#define NET_HEADER_FIELD_ARP_PTYPE (NET_HEADER_FIELD_ARP_HTYPE << 1)
+#define NET_HEADER_FIELD_ARP_HLEN (NET_HEADER_FIELD_ARP_HTYPE << 2)
+#define NET_HEADER_FIELD_ARP_PLEN (NET_HEADER_FIELD_ARP_HTYPE << 3)
+#define NET_HEADER_FIELD_ARP_OPER (NET_HEADER_FIELD_ARP_HTYPE << 4)
+#define NET_HEADER_FIELD_ARP_SHA (NET_HEADER_FIELD_ARP_HTYPE << 5)
+#define NET_HEADER_FIELD_ARP_SPA (NET_HEADER_FIELD_ARP_HTYPE << 6)
+#define NET_HEADER_FIELD_ARP_THA (NET_HEADER_FIELD_ARP_HTYPE << 7)
+#define NET_HEADER_FIELD_ARP_TPA (NET_HEADER_FIELD_ARP_HTYPE << 8)
+#define NET_HEADER_FIELD_ARP_ALL_FIELDS ((NET_HEADER_FIELD_ARP_HTYPE << 9) - 1)
+
+#define NET_HEADER_FIELD_RFC2684_LLC (1)
+#define NET_HEADER_FIELD_RFC2684_NLPID (NET_HEADER_FIELD_RFC2684_LLC << 1)
+#define NET_HEADER_FIELD_RFC2684_OUI (NET_HEADER_FIELD_RFC2684_LLC << 2)
+#define NET_HEADER_FIELD_RFC2684_PID (NET_HEADER_FIELD_RFC2684_LLC << 3)
+#define NET_HEADER_FIELD_RFC2684_VPN_OUI (NET_HEADER_FIELD_RFC2684_LLC << 4)
+#define NET_HEADER_FIELD_RFC2684_VPN_IDX (NET_HEADER_FIELD_RFC2684_LLC << 5)
+#define NET_HEADER_FIELD_RFC2684_ALL_FIELDS ((NET_HEADER_FIELD_RFC2684_LLC << 6) - 1)
+
+#define NET_HEADER_FIELD_USER_DEFINED_SRCPORT (1)
+#define NET_HEADER_FIELD_USER_DEFINED_PCDID (NET_HEADER_FIELD_USER_DEFINED_SRCPORT << 1)
+#define NET_HEADER_FIELD_USER_DEFINED_ALL_FIELDS ((NET_HEADER_FIELD_USER_DEFINED_SRCPORT << 2) - 1)
+
+#define NET_HEADER_FIELD_PAYLOAD_BUFFER (1)
+#define NET_HEADER_FIELD_PAYLOAD_SIZE (NET_HEADER_FIELD_PAYLOAD_BUFFER << 1)
+#define NET_HEADER_FIELD_MAX_FRM_SIZE (NET_HEADER_FIELD_PAYLOAD_BUFFER << 2)
+#define NET_HEADER_FIELD_MIN_FRM_SIZE (NET_HEADER_FIELD_PAYLOAD_BUFFER << 3)
+#define NET_HEADER_FIELD_PAYLOAD_TYPE (NET_HEADER_FIELD_PAYLOAD_BUFFER << 4)
+#define NET_HEADER_FIELD_FRAME_SIZE (NET_HEADER_FIELD_PAYLOAD_BUFFER << 5)
+#define NET_HEADER_FIELD_PAYLOAD_ALL_FIELDS ((NET_HEADER_FIELD_PAYLOAD_BUFFER << 6) - 1)
+
+
+typedef uint8_t headerFieldGre_t;
+
+#define NET_HEADER_FIELD_GRE_TYPE (1)
+#define NET_HEADER_FIELD_GRE_ALL_FIELDS ((NET_HEADER_FIELD_GRE_TYPE << 1) - 1)
+
+
+typedef uint8_t headerFieldMinencap_t;
+
+#define NET_HEADER_FIELD_MINENCAP_SRC_IP (1)
+#define NET_HEADER_FIELD_MINENCAP_DST_IP (NET_HEADER_FIELD_MINENCAP_SRC_IP << 1)
+#define NET_HEADER_FIELD_MINENCAP_TYPE (NET_HEADER_FIELD_MINENCAP_SRC_IP << 2)
+#define NET_HEADER_FIELD_MINENCAP_ALL_FIELDS ((NET_HEADER_FIELD_MINENCAP_SRC_IP << 3) - 1)
+
+
+typedef uint8_t headerFieldIpsecAh_t;
+
+#define NET_HEADER_FIELD_IPSEC_AH_SPI (1)
+#define NET_HEADER_FIELD_IPSEC_AH_NH (NET_HEADER_FIELD_IPSEC_AH_SPI << 1)
+#define NET_HEADER_FIELD_IPSEC_AH_ALL_FIELDS ((NET_HEADER_FIELD_IPSEC_AH_SPI << 2) - 1)
+
+
+typedef uint8_t headerFieldIpsecEsp_t;
+
+#define NET_HEADER_FIELD_IPSEC_ESP_SPI (1)
+#define NET_HEADER_FIELD_IPSEC_ESP_SEQUENCE_NUM (NET_HEADER_FIELD_IPSEC_ESP_SPI << 1)
+#define NET_HEADER_FIELD_IPSEC_ESP_ALL_FIELDS ((NET_HEADER_FIELD_IPSEC_ESP_SPI << 2) - 1)
+
+#define NET_HEADER_FIELD_IPSEC_ESP_SPI_SIZE 4
+
+
+typedef uint8_t headerFieldMpls_t;
+
+#define NET_HEADER_FIELD_MPLS_LABEL_STACK (1)
+#define NET_HEADER_FIELD_MPLS_LABEL_STACK_ALL_FIELDS ((NET_HEADER_FIELD_MPLS_LABEL_STACK << 1) - 1)
+
+
+typedef uint8_t headerFieldMacsec_t;
+
+#define NET_HEADER_FIELD_MACSEC_SECTAG (1)
+#define NET_HEADER_FIELD_MACSEC_ALL_FIELDS ((NET_HEADER_FIELD_MACSEC_SECTAG << 1) - 1)
+
+
+typedef enum {
+ HEADER_TYPE_NONE = 0,
+ HEADER_TYPE_PAYLOAD,
+ HEADER_TYPE_ETH,
+ HEADER_TYPE_VLAN,
+ HEADER_TYPE_IPv4,
+ HEADER_TYPE_IPv6,
+ HEADER_TYPE_IP,
+ HEADER_TYPE_TCP,
+ HEADER_TYPE_UDP,
+ HEADER_TYPE_UDP_LITE,
+ HEADER_TYPE_IPHC,
+ HEADER_TYPE_SCTP,
+ HEADER_TYPE_SCTP_CHUNK_DATA,
+ HEADER_TYPE_PPPoE,
+ HEADER_TYPE_PPP,
+ HEADER_TYPE_PPPMUX,
+ HEADER_TYPE_PPPMUX_SUBFRAME,
+ HEADER_TYPE_L2TPv2,
+ HEADER_TYPE_L2TPv3_CTRL,
+ HEADER_TYPE_L2TPv3_SESS,
+ HEADER_TYPE_LLC,
+ HEADER_TYPE_LLC_SNAP,
+ HEADER_TYPE_NLPID,
+ HEADER_TYPE_SNAP,
+ HEADER_TYPE_MPLS,
+ HEADER_TYPE_IPSEC_AH,
+ HEADER_TYPE_IPSEC_ESP,
+ HEADER_TYPE_UDP_ENCAP_ESP, /* RFC 3948 */
+ HEADER_TYPE_MACSEC,
+ HEADER_TYPE_GRE,
+ HEADER_TYPE_MINENCAP,
+ HEADER_TYPE_DCCP,
+ HEADER_TYPE_ICMP,
+ HEADER_TYPE_IGMP,
+ HEADER_TYPE_ARP,
+ HEADER_TYPE_CAPWAP,
+ HEADER_TYPE_CAPWAP_DTLS,
+ HEADER_TYPE_RFC2684,
+ HEADER_TYPE_USER_DEFINED_L2,
+ HEADER_TYPE_USER_DEFINED_L3,
+ HEADER_TYPE_USER_DEFINED_L4,
+ HEADER_TYPE_USER_DEFINED_SHIM1,
+ HEADER_TYPE_USER_DEFINED_SHIM2,
+ MAX_HEADER_TYPE_COUNT
+} e_NetHeaderType;
+
+
+#endif /* __NET_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/std_ext.h b/drivers/net/ethernet/freescale/fman/inc/std_ext.h
new file mode 100644
index 0000000..d91e6fd
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/std_ext.h
@@ -0,0 +1,48 @@
+/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File std_ext.h
+
+ @Description General Standard Definitions
+*//***************************************************************************/
+
+#ifndef __STD_EXT_H
+#define __STD_EXT_H
+
+
+#include "types_ext.h"
+#include "ncsw_ext.h"
+
+
+#endif /* __STD_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/stdarg_ext.h b/drivers/net/ethernet/freescale/fman/inc/stdarg_ext.h
new file mode 100644
index 0000000..3c8bb0a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/stdarg_ext.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __STDARG_EXT_H
+#define __STDARG_EXT_H
+
+
+#if defined(NCSW_LINUX) && defined(__KERNEL__)
+#include <stdarg.h>
+
+#else
+#include <stdarg.h>
+
+#endif /* defined(NCSW_LINUX) && defined(__KERNEL__) */
+
+#include "std_ext.h"
+
+
+#endif /* __STDARG_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/stdlib_ext.h b/drivers/net/ethernet/freescale/fman/inc/stdlib_ext.h
new file mode 100644
index 0000000..a47860c
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/stdlib_ext.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+
+#ifndef __STDLIB_EXT_H
+#define __STDLIB_EXT_H
+
+
+#if (defined(NCSW_LINUX)) && defined(__KERNEL__)
+#include "stdarg_ext.h"
+#include "std_ext.h"
+
+
+/**
+ * strtoul - convert a string to an uint32_t
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+uint32_t strtoul(const char *cp,char **endp,uint32_t base);
+
+/**
+ * strtol - convert a string to a int32_t
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+long strtol(const char *cp,char **endp,uint32_t base);
+
+/**
+ * strtoull - convert a string to an uint64_t
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+uint64_t strtoull(const char *cp,char **endp,uint32_t base);
+
+/**
+ * strtoll - convert a string to a int64 long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+long long strtoll(const char *cp,char **endp,uint32_t base);
+
+/**
+ * atoi - convert a character to a int
+ * @s: The start of the string
+ */
+int atoi(const char *s);
+
+/**
+ * strnlen - Find the length of a length-limited string
+ * @s: The string to be sized
+ * @count: The maximum number of bytes to search
+ */
+size_t strnlen(const char * s, size_t count);
+
+/**
+ * strlen - Find the length of a string
+ * @s: The string to be sized
+ */
+size_t strlen(const char * s);
+
+/**
+ * strtok - Split a string into tokens
+ * @s: The string to be searched
+ * @ct: The characters to search for
+ *
+ * WARNING: strtok is deprecated, use strsep instead.
+ */
+char * strtok(char * s,const char * ct);
+
+/**
+ * strncpy - Copy a length-limited, %NUL-terminated string
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ * @count: The maximum number of bytes to copy
+ *
+ * Note that unlike userspace strncpy, this does not %NUL-pad the buffer.
+ * However, the result is not %NUL-terminated if the source exceeds
+ * @count bytes.
+ */
+char * strncpy(char * dest,const char *src,size_t count);
+
+/**
+ * strcpy - Copy a %NUL terminated string
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ */
+char * strcpy(char * dest,const char *src);
+
+/**
+ * vsscanf - Unformat a buffer into a list of arguments
+ * @buf: input buffer
+ * @fmt: format of buffer
+ * @args: arguments
+ */
+int vsscanf(const char * buf, const char * fmt, va_list args);
+
+/**
+ * vsnprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @size: The size of the buffer, including the trailing null space
+ * @fmt: The format string to use
+ * @args: Arguments for the format string
+ *
+ * Call this function if you are already dealing with a va_list.
+ * You probably want snprintf instead.
+ */
+int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
+
+/**
+ * vsprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @fmt: The format string to use
+ * @args: Arguments for the format string
+ *
+ * Call this function if you are already dealing with a va_list.
+ * You probably want sprintf instead.
+ */
+int vsprintf(char *buf, const char *fmt, va_list args);
+
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#endif /* defined(NCSW_LINUX) && defined(__KERNEL__) */
+
+#include "std_ext.h"
+
+
+#endif /* __STDLIB_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/string_ext.h b/drivers/net/ethernet/freescale/fman/inc/string_ext.h
new file mode 100644
index 0000000..a5c6c7e
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/string_ext.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __STRING_EXT_H
+#define __STRING_EXT_H
+
+
+#if defined(NCSW_LINUX) && defined(__KERNEL__)
+#include <linux/kernel.h>
+#include <linux/string.h>
+extern char * strtok ( char * str, const char * delimiters );
+
+#elif defined(__KERNEL__)
+#include "linux/types.h"
+#include "linux/posix_types.h"
+#include "linux/string.h"
+
+#else
+#include <string.h>
+
+#endif /* defined(NCSW_LINUX) && defined(__KERNEL__) */
+
+#include "std_ext.h"
+
+
+#endif /* __STRING_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/types_ext.h b/drivers/net/ethernet/freescale/fman/inc/types_ext.h
new file mode 100644
index 0000000..fd900e2
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/types_ext.h
@@ -0,0 +1,104 @@
+/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File types_ext.h
+
+ @Description General types Standard Definitions
+*//***************************************************************************/
+
+#ifndef __TYPES_EXT_H
+#define __TYPES_EXT_H
+
+#if defined(NCSW_LINUX)
+#include "types_linux.h"
+
+#elif defined(NCSW_VXWORKS)
+#include "types_vxworks.h"
+
+#elif defined(__GNUC__) && defined(__cplusplus)
+#include "types_bb_gpp.h"
+
+#elif defined(__GNUC__)
+#include "types_bb_gcc.h"
+
+#elif defined(__ghs__)
+#include "types_ghs.h"
+
+#else
+#include "types_dflt.h"
+#endif /* defined (__ROCOO__) */
+
+static __inline__ void TypesChecker(void)
+{
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(push,1)
+#endif /* defined(__MWERKS__) && ... */
+ _Packed struct strct {
+ __volatile__ int vi;
+ } _PackedType;
+#if defined(__MWERKS__) && !defined(__GNUC__)
+#pragma pack(pop)
+#endif /* defined(__MWERKS__) && ... */
+ size_t size = 0;
+ bool tr = TRUE, fls = FALSE;
+ struct strct *p_Struct = NULL;
+ physAddress_t addr = 0x100;
+
+ tr = fls;
+ p_Struct = p_Struct;
+ size++;
+ if (tr) size++;
+
+ WRITE_UINT8(*((uint8_t*)((size_t)(addr))),
+ GET_UINT8(*((uint8_t*)((size_t)(addr)))));
+
+ WRITE_UINT8(*((uint8_t*)((size_t)(UINT8_MAX))),
+ GET_UINT8(*((uint8_t*)((size_t)(UINT8_MAX)))));
+ WRITE_UINT16(*((uint16_t*)((size_t)(UINT16_MAX))),
+ GET_UINT16(*((uint16_t*)((size_t)(UINT16_MAX)))));
+ WRITE_UINT32(*((uint32_t*)((size_t)(UINT32_MAX))),
+ GET_UINT32(*((uint32_t*)((size_t)(UINT32_MAX)))));
+ WRITE_UINT64(*((uint64_t*)((size_t)(UINT64_MAX))),
+ GET_UINT64(*((uint64_t*)((size_t)(UINT64_MAX)))));
+ WRITE_UINT8(*((uint8_t*)((size_t)(INT8_MAX))),
+ GET_UINT8(*((uint8_t*)((size_t)(INT8_MIN)))));
+ WRITE_UINT16(*((uint16_t*)((size_t)(INT16_MAX))),
+ GET_UINT16(*((uint16_t*)((size_t)(INT16_MIN)))));
+ WRITE_UINT32(*((uint32_t*)((size_t)(INT32_MAX))),
+ GET_UINT32(*((uint32_t*)((size_t)(INT32_MIN)))));
+ WRITE_UINT64(*((uint64_t*)((size_t)(INT64_MAX))),
+ GET_UINT64(*((uint64_t*)((size_t)(INT64_MIN)))));
+}
+
+#endif /* __TYPES_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/xx_common.h b/drivers/net/ethernet/freescale/fman/inc/xx_common.h
new file mode 100644
index 0000000..1c45177
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/xx_common.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File debug_ext.h
+
+ @Description Debug mode definitions.
+*//***************************************************************************/
+
+#ifndef __XX_COMMON_H
+#define __XX_COMMON_H
+
+/*****************************************************************************
+ * UNIFIED MODULE CODES
+ *****************************************************************************/
+#define MODULE_UNKNOWN 0x00000000
+#define MODULE_FM 0x00010000
+#define MODULE_FM_MURAM 0x00020000
+#define MODULE_FM_PCD 0x00030000
+#define MODULE_FM_RTC 0x00040000
+#define MODULE_FM_MAC 0x00050000
+#define MODULE_FM_PORT 0x00060000
+#define MODULE_MM 0x00070000
+#define MODULE_FM_SP 0x00080000
+
+#endif /* __XX_COMMON_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/xx_ext.h b/drivers/net/ethernet/freescale/fman/inc/xx_ext.h
new file mode 100644
index 0000000..21b62d0
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/xx_ext.h
@@ -0,0 +1,791 @@
+/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**************************************************************************//**
+ @File xx_ext.h
+
+ @Description Prototypes, externals and typedefs for system-supplied
+ (external) routines
+*//***************************************************************************/
+
+#ifndef __XX_EXT_H
+#define __XX_EXT_H
+
+#include "std_ext.h"
+#include "xx_common.h"
+#include "part_ext.h"
+
+
+
+/**************************************************************************//**
+ @Group xx_id XX Interface (System call hooks)
+
+ @Description Prototypes, externals and typedefs for system-supplied
+ (external) routines
+
+ @{
+*//***************************************************************************/
+
+#ifdef DEBUG_XX_MALLOC
+void * XX_MallocDebug(uint32_t size, char *fname, int line);
+
+void * XX_MallocSmartDebug(uint32_t size,
+ int memPartitionId,
+ uint32_t alignment,
+ char *fname,
+ int line);
+
+#define XX_Malloc(sz) \
+ XX_MallocDebug((sz), __FILE__, __LINE__)
+
+#define XX_MallocSmart(sz, memt, al) \
+ XX_MallocSmartDebug((sz), (memt), (al), __FILE__, __LINE__)
+
+#else /* not DEBUG_XX_MALLOC */
+/**************************************************************************//**
+ @Function XX_Malloc
+
+ @Description allocates contiguous block of memory.
+
+ @Param[in] size - Number of bytes to allocate.
+
+ @Return The address of the newly allocated block on success, NULL on failure.
+*//***************************************************************************/
+void * XX_Malloc(uint32_t size);
+
+/**************************************************************************//**
+ @Function XX_MallocSmart
+
+ @Description Allocates contiguous block of memory in a specified
+ alignment and from the specified segment.
+
+ @Param[in] size - Number of bytes to allocate.
+ @Param[in] memPartitionId - Memory partition ID; The value zero must
+ be mapped to the default heap partition.
+ @Param[in] alignment - Required memory alignment (in bytes).
+
+ @Return The address of the newly allocated block on success, NULL on failure.
+*//***************************************************************************/
+void * XX_MallocSmart(uint32_t size, int memPartitionId, uint32_t alignment);
+#endif /* not DEBUG_XX_MALLOC */
+
+/**************************************************************************//**
+ @Function XX_FreeSmart
+
+ @Description Frees the memory block pointed to by "p".
+ Only for memory allocated by XX_MallocSmart
+
+ @Param[in] p_Memory - pointer to the memory block.
+
+ @Return None.
+*//***************************************************************************/
+void XX_FreeSmart(void *p_Memory);
+
+/**************************************************************************//**
+ @Function XX_Free
+
+ @Description frees the memory block pointed to by "p".
+
+ @Param[in] p_Memory - pointer to the memory block.
+
+ @Return None.
+*//***************************************************************************/
+void XX_Free(void *p_Memory);
+
+/**************************************************************************//**
+ @Function XX_Print
+
+ @Description print a string.
+
+ @Param[in] str - string to print.
+
+ @Return None.
+*//***************************************************************************/
+void XX_Print(char *str, ...);
+
+/**************************************************************************//**
+ @Function XX_SetIntr
+
+ @Description Set an interrupt service routine for a specific interrupt source.
+
+ @Param[in] irq - Interrupt ID (system-specific number).
+ @Param[in] f_Isr - Callback routine that will be called when the interrupt occurs.
+ @Param[in] handle - The argument for the user callback routine.
+
+ @Return E_OK on success; error code otherwise..
+*//***************************************************************************/
+t_Error XX_SetIntr(int irq, t_Isr *f_Isr, t_Handle handle);
+
+/**************************************************************************//**
+ @Function XX_FreeIntr
+
+ @Description Free a specific interrupt and a specific callback routine.
+
+ @Param[in] irq - Interrupt ID (system-specific number).
+
+ @Return E_OK on success; error code otherwise..
+*//***************************************************************************/
+t_Error XX_FreeIntr(int irq);
+
+/**************************************************************************//**
+ @Function XX_EnableIntr
+
+ @Description Enable a specific interrupt.
+
+ @Param[in] irq - Interrupt ID (system-specific number).
+
+ @Return E_OK on success; error code otherwise..
+*//***************************************************************************/
+t_Error XX_EnableIntr(int irq);
+
+/**************************************************************************//**
+ @Function XX_DisableIntr
+
+ @Description Disable a specific interrupt.
+
+ @Param[in] irq - Interrupt ID (system-specific number).
+
+ @Return E_OK on success; error code otherwise..
+*//***************************************************************************/
+t_Error XX_DisableIntr(int irq);
+
+/**************************************************************************//**
+ @Function XX_DisableAllIntr
+
+ @Description Disable all interrupts by masking them at the CPU.
+
+ @Return A value that represents the interrupts state before the
+ operation, and should be passed to the matching
+ XX_RestoreAllIntr() call.
+*//***************************************************************************/
+uint32_t XX_DisableAllIntr(void);
+
+/**************************************************************************//**
+ @Function XX_RestoreAllIntr
+
+ @Description Restore previous state of interrupts level at the CPU.
+
+ @Param[in] flags - A value that represents the interrupts state to restore,
+ as returned by the matching call for XX_DisableAllIntr().
+
+ @Return None.
+*//***************************************************************************/
+void XX_RestoreAllIntr(uint32_t flags);
+
+
+/**************************************************************************//**
+ @Function XX_Exit
+
+ @Description Stop execution and report status (where it is applicable)
+
+ @Param[in] status - exit status
+*//***************************************************************************/
+void XX_Exit(int status);
+
+
+/*****************************************************************************/
+/* Tasklet Service Routines */
+/*****************************************************************************/
+typedef t_Handle t_TaskletHandle;
+
+/**************************************************************************//**
+ @Function XX_InitTasklet
+
+ @Description Create and initialize a tasklet object.
+
+ @Param[in] routine - A routine to be ran as a tasklet.
+ @Param[in] data - An argument to pass to the tasklet.
+
+ @Return Tasklet handle is returned on success. NULL is returned otherwise.
+*//***************************************************************************/
+t_TaskletHandle XX_InitTasklet (void (*routine)(void *), void *data);
+
+/**************************************************************************//**
+ @Function XX_FreeTasklet
+
+ @Description Free a tasklet object.
+
+ @Param[in] h_Tasklet - A handle to a tasklet to be free.
+
+ @Return None.
+*//***************************************************************************/
+void XX_FreeTasklet (t_TaskletHandle h_Tasklet);
+
+/**************************************************************************//**
+ @Function XX_ScheduleTask
+
+ @Description Schedule a tasklet object.
+
+ @Param[in] h_Tasklet - A handle to a tasklet to be scheduled.
+ @Param[in] immediate - Indicate whether to schedule this tasklet on
+ the immediate queue or on the delayed one.
+
+ @Return 0 - on success. Error code - otherwise.
+*//***************************************************************************/
+int XX_ScheduleTask(t_TaskletHandle h_Tasklet, int immediate);
+
+/**************************************************************************//**
+ @Function XX_FlushScheduledTasks
+
+ @Description Flush all tasks there are in the scheduled tasks queue.
+
+ @Return None.
+*//***************************************************************************/
+void XX_FlushScheduledTasks(void);
+
+/**************************************************************************//**
+ @Function XX_TaskletIsQueued
+
+ @Description Check if task is queued.
+
+ @Param[in] h_Tasklet - A handle to a tasklet to be scheduled.
+
+ @Return 1 - task is queued. 0 - otherwise.
+*//***************************************************************************/
+int XX_TaskletIsQueued(t_TaskletHandle h_Tasklet);
+
+/**************************************************************************//**
+ @Function XX_SetTaskletData
+
+ @Description Set data to a scheduled task. Used to change data of already
+ scheduled task.
+
+ @Param[in] h_Tasklet - A handle to a tasklet to be scheduled.
+ @Param[in] data - Data to be set.
+*//***************************************************************************/
+void XX_SetTaskletData(t_TaskletHandle h_Tasklet, t_Handle data);
+
+/**************************************************************************//**
+ @Function XX_GetTaskletData
+
+ @Description Get the data of scheduled task.
+
+ @Param[in] h_Tasklet - A handle to a tasklet to be scheduled.
+
+ @Return handle to the data of the task.
+*//***************************************************************************/
+t_Handle XX_GetTaskletData(t_TaskletHandle h_Tasklet);
+
+/**************************************************************************//**
+ @Function XX_BottomHalf
+
+ @Description Bottom half implementation, invoked by the interrupt handler.
+
+ This routine handles all bottom-half tasklets with interrupts
+ enabled.
+
+ @Return None.
+*//***************************************************************************/
+void XX_BottomHalf(void);
+
+
+/*****************************************************************************/
+/* Spinlock Service Routines */
+/*****************************************************************************/
+
+/**************************************************************************//**
+ @Function XX_InitSpinlock
+
+ @Description Creates a spinlock.
+
+ @Return Spinlock handle is returned on success; NULL otherwise.
+*//***************************************************************************/
+t_Handle XX_InitSpinlock(void);
+
+/**************************************************************************//**
+ @Function XX_FreeSpinlock
+
+ @Description Frees the memory allocated for the spinlock creation.
+
+ @Param[in] h_Spinlock - A handle to a spinlock.
+
+ @Return None.
+*//***************************************************************************/
+void XX_FreeSpinlock(t_Handle h_Spinlock);
+
+/**************************************************************************//**
+ @Function XX_LockSpinlock
+
+ @Description Locks a spinlock.
+
+ @Param[in] h_Spinlock - A handle to a spinlock.
+
+ @Return None.
+*//***************************************************************************/
+void XX_LockSpinlock(t_Handle h_Spinlock);
+
+/**************************************************************************//**
+ @Function XX_UnlockSpinlock
+
+ @Description Unlocks a spinlock.
+
+ @Param[in] h_Spinlock - A handle to a spinlock.
+
+ @Return None.
+*//***************************************************************************/
+void XX_UnlockSpinlock(t_Handle h_Spinlock);
+
+/**************************************************************************//**
+ @Function XX_LockIntrSpinlock
+
+ @Description Locks a spinlock (interrupt safe).
+
+ @Param[in] h_Spinlock - A handle to a spinlock.
+
+ @Return A value that represents the interrupts state before the
+ operation, and should be passed to the matching
+ XX_UnlockIntrSpinlock() call.
+*//***************************************************************************/
+uint32_t XX_LockIntrSpinlock(t_Handle h_Spinlock);
+
+/**************************************************************************//**
+ @Function XX_UnlockIntrSpinlock
+
+ @Description Unlocks a spinlock (interrupt safe).
+
+ @Param[in] h_Spinlock - A handle to a spinlock.
+ @Param[in] intrFlags - A value that represents the interrupts state to
+ restore, as returned by the matching call for
+ XX_LockIntrSpinlock().
+
+ @Return None.
+*//***************************************************************************/
+void XX_UnlockIntrSpinlock(t_Handle h_Spinlock, uint32_t intrFlags);
+
+
+/*****************************************************************************/
+/* Timers Service Routines */
+/*****************************************************************************/
+
+/**************************************************************************//**
+ @Function XX_CurrentTime
+
+ @Description Returns current system time.
+
+ @Return Current system time (in milliseconds).
+*//***************************************************************************/
+uint32_t XX_CurrentTime(void);
+
+/**************************************************************************//**
+ @Function XX_CreateTimer
+
+ @Description Creates a timer.
+
+ @Return Timer handle is returned on success; NULL otherwise.
+*//***************************************************************************/
+t_Handle XX_CreateTimer(void);
+
+/**************************************************************************//**
+ @Function XX_FreeTimer
+
+ @Description Frees the memory allocated for the timer creation.
+
+ @Param[in] h_Timer - A handle to a timer.
+
+ @Return None.
+*//***************************************************************************/
+void XX_FreeTimer(t_Handle h_Timer);
+
+/**************************************************************************//**
+ @Function XX_StartTimer
+
+ @Description Starts a timer.
+
+ The user can select to start the timer as periodic timer or as
+ one-shot timer. The user should provide a callback routine that
+ will be called when the timer expires.
+
+ @Param[in] h_Timer - A handle to a timer.
+ @Param[in] msecs - Timer expiration period (in milliseconds).
+ @Param[in] periodic - TRUE for a periodic timer;
+ FALSE for a one-shot timer..
+ @Param[in] f_TimerExpired - A callback routine to be called when the
+ timer expires.
+ @Param[in] h_Arg - The argument to pass in the timer-expired
+ callback routine.
+
+ @Return None.
+*//***************************************************************************/
+void XX_StartTimer(t_Handle h_Timer,
+ uint32_t msecs,
+ bool periodic,
+ void (*f_TimerExpired)(t_Handle h_Arg),
+ t_Handle h_Arg);
+
+/**************************************************************************//**
+ @Function XX_StopTimer
+
+ @Description Frees the memory allocated for the timer creation.
+
+ @Param[in] h_Timer - A handle to a timer.
+
+ @Return None.
+*//***************************************************************************/
+void XX_StopTimer(t_Handle h_Timer);
+
+/**************************************************************************//**
+ @Function XX_ModTimer
+
+ @Description Updates the expiration time of a timer.
+
+ This routine adds the given time to the current system time,
+ and sets this value as the new expiration time of the timer.
+
+ @Param[in] h_Timer - A handle to a timer.
+ @Param[in] msecs - The new interval until timer expiration
+ (in milliseconds).
+
+ @Return None.
+*//***************************************************************************/
+void XX_ModTimer(t_Handle h_Timer, uint32_t msecs);
+
+/**************************************************************************//**
+ @Function XX_Sleep
+
+ @Description Non-busy wait until the desired time (in milliseconds) has passed.
+
+ @Param[in] msecs - The requested sleep time (in milliseconds).
+
+ @Return Zero if the requested time has elapsed; Otherwise, the value
+ returned will be the unslept amount) in milliseconds.
+
+ @Cautions This routine enables interrupts during its wait time.
+*//***************************************************************************/
+uint32_t XX_Sleep(uint32_t msecs);
+
+/**************************************************************************//**
+ @Function XX_UDelay
+
+ @Description Busy-wait until the desired time (in microseconds) has passed.
+
+ @Param[in] usecs - The requested delay time (in microseconds).
+
+ @Return None.
+
+ @Cautions It is highly unrecommended to call this routine during interrupt
+ time, because the system time may not be updated properly during
+ the delay loop. The behavior of this routine during interrupt
+ time is unexpected.
+*//***************************************************************************/
+void XX_UDelay(uint32_t usecs);
+
+
+/*****************************************************************************/
+/* Other Service Routines */
+/*****************************************************************************/
+
+/**************************************************************************//**
+ @Function XX_PhysToVirt
+
+ @Description Translates a physical address to the matching virtual address.
+
+ @Param[in] addr - The physical address to translate.
+
+ @Return Virtual address.
+*//***************************************************************************/
+void * XX_PhysToVirt(physAddress_t addr);
+
+/**************************************************************************//**
+ @Function XX_VirtToPhys
+
+ @Description Translates a virtual address to the matching physical address.
+
+ @Param[in] addr - The virtual address to translate.
+
+ @Return Physical address.
+*//***************************************************************************/
+physAddress_t XX_VirtToPhys(void *addr);
+
+
+/**************************************************************************//**
+ @Group xx_ipc XX Inter-Partition-Communication API
+
+ @Description The following API is to be used when working with multiple
+ partitions configuration.
+
+ @{
+*//***************************************************************************/
+
+#define XX_IPC_MAX_ADDR_NAME_LENGTH 16 /**< Maximum length of an endpoint name string;
+ The IPC service can use this constant to limit
+ the storage space for IPC endpoint names. */
+
+
+/**************************************************************************//**
+ @Function t_IpcMsgCompletion
+
+ @Description Callback function used upon IPC non-blocking transaction completion
+ to return message buffer to the caller and to forward reply if available.
+
+ This callback function may be attached by the source endpoint to any outgoing
+ IPC message to indicate a non-blocking send (see also XX_IpcSendMessage() routine).
+ Upon completion of an IPC transaction (consisting of a message and an optional reply),
+ the IPC service invokes this callback routine to return the message buffer to the sender
+ and to provide the received reply, if requested.
+
+ User provides this function. Driver invokes it.
+
+ @Param[in] h_Module - Abstract handle to the sending module - the same handle as was passed
+ in the XX_IpcSendMessage() function; This handle is typically used to point
+ to the internal data structure of the source endpoint.
+ @Param[in] p_Msg - Pointer to original (sent) message buffer;
+ The source endpoint can free (or reuse) this buffer when message
+ completion callback is called.
+ @Param[in] p_Reply - Pointer to (received) reply buffer;
+ This pointer is the same as was provided by the source endpoint in
+ XX_IpcSendMessage().
+ @Param[in] replyLength - Length (in bytes) of actual data in the reply buffer.
+ @Param[in] status - Completion status - E_OK or failure indication, e.g. IPC transaction completion
+ timeout.
+
+ @Return None
+ *//***************************************************************************/
+typedef void (t_IpcMsgCompletion)(t_Handle h_Module,
+ uint8_t *p_Msg,
+ uint8_t *p_Reply,
+ uint32_t replyLength,
+ t_Error status);
+
+/**************************************************************************//**
+ @Function t_IpcMsgHandler
+
+ @Description Callback function used as IPC message handler.
+
+ The IPC service invokes message handlers for each IPC message received.
+ The actual function pointer should be registered by each destination endpoint
+ via the XX_IpcRegisterMsgHandler() routine.
+
+ User provides this function. Driver invokes it.
+
+ @Param[in] h_Module - Abstract handle to the message handling module - the same handle as
+ was passed in the XX_IpcRegisterMsgHandler() function; this handle is
+ typically used to point to the internal data structure of the destination
+ endpoint.
+ @Param[in] p_Msg - Pointer to message buffer with data received from peer.
+ @Param[in] msgLength - Length (in bytes) of message data.
+ @Param[in] p_Reply - Pointer to reply buffer, to be filled by the message handler and then sent
+ by the IPC service;
+ The reply buffer is allocated by the IPC service with size equals to the
+ replyLength parameter provided in message handler registration (see
+ XX_IpcRegisterMsgHandler() function);
+ If replyLength was initially specified as zero during message handler registration,
+ the IPC service may set this pointer to NULL and assume that a reply is not needed;
+ The IPC service is also responsible for freeing the reply buffer after the
+ reply has been sent or dismissed.
+ @Param[in,out] p_ReplyLength - Pointer to reply length, which has a dual role in this function:
+ [In] equals the replyLength parameter provided in message handler
+ registration (see XX_IpcRegisterMsgHandler() function), and
+ [Out] should be updated by message handler to the actual reply length; if
+ this value is set to zero, the IPC service must assume that a reply should
+ not be sent;
+ Note: If p_Reply is not NULL, p_ReplyLength must not be NULL as well.
+
+ @Return E_OK on success; Error code otherwise.
+ *//***************************************************************************/
+typedef t_Error (t_IpcMsgHandler)(t_Handle h_Module,
+ uint8_t *p_Msg,
+ uint32_t msgLength,
+ uint8_t *p_Reply,
+ uint32_t *p_ReplyLength);
+
+/**************************************************************************//**
+ @Function XX_IpcRegisterMsgHandler
+
+ @Description IPC mailbox registration.
+
+ This function is used for registering an IPC message handler in the IPC service.
+ This function is called by each destination endpoint to indicate that it is ready
+ to handle incoming messages. The IPC service invokes the message handler upon receiving
+ a message addressed to the specified destination endpoint.
+
+ @Param[in] addr - The address name string associated with the destination endpoint;
+ This address must be unique across the IPC service domain to ensure
+ correct message routing.
+ @Param[in] f_MsgHandler - Pointer to the message handler callback for processing incoming
+ message; invoked by the IPC service upon receiving a message
+ addressed to the destination endpoint specified by the addr
+ parameter.
+ @Param[in] h_Module - Abstract handle to the message handling module, passed unchanged
+ to f_MsgHandler callback function.
+ @Param[in] replyLength - The maximal data length (in bytes) of any reply that the specified message handler
+ may generate; the IPC service provides the message handler with buffer
+ for reply according to the length specified here (refer also to the description
+ of #t_IpcMsgHandler callback function type);
+ This size shall be zero if the message handler never generates replies.
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error XX_IpcRegisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH],
+ t_IpcMsgHandler *f_MsgHandler,
+ t_Handle h_Module,
+ uint32_t replyLength);
+
+/**************************************************************************//**
+ @Function XX_IpcUnregisterMsgHandler
+
+ @Description Release IPC mailbox routine.
+
+ This function is used for unregistering an IPC message handler from the IPC service.
+ This function is called by each destination endpoint to indicate that it is no longer
+ capable of handling incoming messages.
+
+ @Param[in] addr - The address name string associated with the destination endpoint;
+ This address is the same as was used when the message handler was
+ registered via XX_IpcRegisterMsgHandler().
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error XX_IpcUnregisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH]);
+
+/**************************************************************************//**
+ @Function XX_IpcInitSession
+
+ @Description This function is used for creating an IPC session between the source endpoint
+ and the destination endpoint.
+
+ The actual implementation and representation of a session is left for the IPC service.
+ The function returns an abstract handle to the created session. This handle shall be used
+ by the source endpoint in subsequent calls to XX_IpcSendMessage().
+ The IPC service assumes that before this function is called, no messages are sent from
+ the specified source endpoint to the specified destination endpoint.
+
+ The IPC service may use a connection-oriented approach or a connectionless approach (or both)
+ as described below.
+
+ @par Connection-Oriented Approach
+
+ The IPC service may implement a session in a connection-oriented approach - when this function is called,
+ the IPC service should take the necessary steps to bring up a source-to-destination channel for messages
+ and a destination-to-source channel for replies. The returned handle should represent the internal
+ representation of these channels.
+
+ @par Connectionless Approach
+
+ The IPC service may implement a session in a connectionless approach - when this function is called, the
+ IPC service should not perform any particular steps, but it must store the pair of source and destination
+ addresses in some session representation and return it as a handle. When XX_IpcSendMessage() shall be
+ called, the IPC service may use this handle to provide the necessary identifiers for routing the messages
+ through the connectionless medium.
+
+ @Param[in] destAddr - The address name string associated with the destination endpoint.
+ @Param[in] srcAddr - The address name string associated with the source endpoint.
+
+ @Return Abstract handle to the initialized session, or NULL on error.
+*//***************************************************************************/
+t_Handle XX_IpcInitSession(char destAddr[XX_IPC_MAX_ADDR_NAME_LENGTH],
+ char srcAddr[XX_IPC_MAX_ADDR_NAME_LENGTH]);
+
+/**************************************************************************//**
+ @Function XX_IpcFreeSession
+
+ @Description This function is used for terminating an existing IPC session between a source endpoint
+ and a destination endpoint.
+
+ The IPC service assumes that after this function is called, no messages shall be sent from
+ the associated source endpoint to the associated destination endpoint.
+
+ @Param[in] h_Session - Abstract handle to the IPC session - the same handle as was originally
+ returned by the XX_IpcInitSession() function.
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error XX_IpcFreeSession(t_Handle h_Session);
+
+/**************************************************************************//**
+ @Function XX_IpcSendMessage
+
+ @Description IPC message send routine.
+
+ This function may be used by a source endpoint to send an IPC message to a destination
+ endpoint. The source endpoint cannot send a message to the destination endpoint without
+ first initiating a session with that destination endpoint via XX_IpcInitSession() routine.
+
+ The source endpoint must provide the buffer pointer and length of the outgoing message.
+ Optionally, it may also provide a buffer for an expected reply. In the latter case, the
+ transaction is not considered complete by the IPC service until the reply has been received.
+ If the source endpoint does not provide a reply buffer, the transaction is considered
+ complete after the message has been sent. The source endpoint must keep the message (and
+ optional reply) buffers valid until the transaction is complete.
+
+ @par Non-blocking mode
+
+ The source endpoint may request a non-blocking send by providing a non-NULL pointer to a message
+ completion callback function (f_Completion). Upon completion of the IPC transaction (consisting of a
+ message and an optional reply), the IPC service invokes this callback routine to return the message
+ buffer to the sender and to provide the received reply, if requested.
+
+ @par Blocking mode
+
+ The source endpoint may request a blocking send by setting f_Completion to NULL. The function is
+ expected to block until the IPC transaction is complete - either the reply has been received or (if no reply
+ was requested) the message has been sent.
+
+ @Param[in] h_Session - Abstract handle to the IPC session - the same handle as was originally
+ returned by the XX_IpcInitSession() function.
+ @Param[in] p_Msg - Pointer to message buffer to send.
+ @Param[in] msgLength - Length (in bytes) of actual data in the message buffer.
+ @Param[in] p_Reply - Pointer to reply buffer - if this buffer is not NULL, the IPC service
+ fills this buffer with the received reply data;
+ In blocking mode, the reply data must be valid when the function returns;
+ In non-blocking mode, the reply data is valid when f_Completion is called;
+ If this pointer is NULL, no reply is expected.
+ @Param[in,out] p_ReplyLength - Pointer to reply length, which has a dual role in this function:
+ [In] specifies the maximal length (in bytes) of the reply buffer pointed by
+ p_Reply, and
+ [Out] in non-blocking mode this value is updated by the IPC service to the
+ actual reply length (in bytes).
+ @Param[in] f_Completion - Pointer to a completion callback to be used in non-blocking send mode;
+ The completion callback is invoked by the IPC service upon
+ completion of the IPC transaction (consisting of a message and an optional
+ reply);
+ If this pointer is NULL, the function is expected to block until the IPC
+ transaction is complete.
+ @Param[in] h_Arg - Abstract handle to the sending module; passed unchanged to the f_Completion
+ callback function as the first argument.
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error XX_IpcSendMessage(t_Handle h_Session,
+ uint8_t *p_Msg,
+ uint32_t msgLength,
+ uint8_t *p_Reply,
+ uint32_t *p_ReplyLength,
+ t_IpcMsgCompletion *f_Completion,
+ t_Handle h_Arg);
+
+
+/** @} */ /* end of xx_ipc group */
+/** @} */ /* end of xx_id group */
+
+
+#endif /* __XX_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/ncsw_config.mk b/drivers/net/ethernet/freescale/fman/ncsw_config.mk
new file mode 100644
index 0000000..14cb9d0
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/ncsw_config.mk
@@ -0,0 +1,41 @@
+#
+# Makefile config for the Freescale NetcommSW
+#
+NET_DPA = $(srctree)/drivers/net
+DRV_DPA = $(srctree)/drivers/net/ethernet/freescale/dpa
+FMAN = $(srctree)/drivers/net/ethernet/freescale/fman
+
+ifeq ("$(CONFIG_FMAN_P3040_P4080_P5020)", "y")
+EXTRA_CFLAGS +=-include $(FMAN)/p3040_4080_5020_dflags.h
+endif
+ifeq ("$(CONFIG_FMAN_P1023)", "y")
+EXTRA_CFLAGS +=-include $(FMAN)/p1023_dflags.h
+endif
+ifdef CONFIG_FMAN_T4240
+EXTRA_CFLAGS +=-include $(FMAN)/t4240_dflags.h
+endif
+
+EXTRA_CFLAGS += -I$(DRV_DPA)/
+EXTRA_CFLAGS += -I$(FMAN)/inc
+EXTRA_CFLAGS += -I$(FMAN)/inc/cores
+EXTRA_CFLAGS += -I$(FMAN)/inc/etc
+EXTRA_CFLAGS += -I$(FMAN)/inc/Peripherals
+EXTRA_CFLAGS += -I$(FMAN)/inc/flib
+
+ifeq ("$(CONFIG_FMAN_P3040_P4080_P5020)", "y")
+EXTRA_CFLAGS += -I$(FMAN)/inc/integrations/P3040_P4080_P5020
+endif
+ifeq ("$(CONFIG_FMAN_P1023)", "y")
+EXTRA_CFLAGS += -I$(FMAN)/inc/integrations/P1023
+endif
+ifdef CONFIG_FMAN_T4240
+EXTRA_CFLAGS += -I$(FMAN)/inc/integrations/T4240
+endif
+
+EXTRA_CFLAGS += -I$(FMAN)/src/inc
+EXTRA_CFLAGS += -I$(FMAN)/src/inc/system
+EXTRA_CFLAGS += -I$(FMAN)/src/inc/wrapper
+EXTRA_CFLAGS += -I$(FMAN)/src/inc/xx
+EXTRA_CFLAGS += -I$(srctree)/include/uapi/linux/fmd
+EXTRA_CFLAGS += -I$(srctree)/include/uapi/linux/fmd/Peripherals
+EXTRA_CFLAGS += -I$(srctree)/include/uapi/linux/fmd/integrations
diff --git a/drivers/net/ethernet/freescale/fman/p1023_dflags.h b/drivers/net/ethernet/freescale/fman/p1023_dflags.h
new file mode 100644
index 0000000..b48819d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/p1023_dflags.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __dflags_h
+#define __dflags_h
+
+
+#define NCSW_LINUX
+#if 0
+#define DEBUG
+#endif
+
+#define P1023
+#define NCSW_PPC_CORE
+
+#define DEBUG_ERRORS 1
+
+#if defined(DEBUG)
+#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_INFO
+
+#define DEBUG_XX_MALLOC
+#define DEBUG_MEM_LEAKS
+
+#else
+#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_WARNING
+#endif /* (DEBUG) */
+
+#define REPORT_EVENTS 1
+#define EVENT_GLOBAL_LEVEL REPORT_LEVEL_MINOR
+
+#ifdef CONFIG_P4080_SIM
+#error "Do not define CONFIG_P4080_SIM..."
+#endif
+
+
+#endif /* __dflags_h */
diff --git a/drivers/net/ethernet/freescale/fman/p3040_4080_5020_dflags.h b/drivers/net/ethernet/freescale/fman/p3040_4080_5020_dflags.h
new file mode 100644
index 0000000..7438974
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/p3040_4080_5020_dflags.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __dflags_h
+#define __dflags_h
+
+
+#define NCSW_LINUX
+
+#define P4080
+#define NCSW_PPC_CORE
+
+#define DEBUG_ERRORS 1
+
+#if defined(DEBUG)
+#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_INFO
+
+#define DEBUG_XX_MALLOC
+#define DEBUG_MEM_LEAKS
+
+#else
+#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_WARNING
+#endif /* (DEBUG) */
+
+#define REPORT_EVENTS 1
+#define EVENT_GLOBAL_LEVEL REPORT_LEVEL_MINOR
+
+#ifdef CONFIG_P4080_SIM
+#define SIMULATOR
+#endif /* CONFIG_P4080_SIM */
+
+
+#endif /* __dflags_h */
diff --git a/drivers/net/ethernet/freescale/fman/src/Makefile b/drivers/net/ethernet/freescale/fman/src/Makefile
new file mode 100644
index 0000000..af5d2e7
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+#
+obj-y += system/
+obj-y += wrapper/
+obj-y += xx/
diff --git a/drivers/net/ethernet/freescale/fman/src/inc/system/sys_ext.h b/drivers/net/ethernet/freescale/fman/src/inc/system/sys_ext.h
new file mode 100644
index 0000000..20f27d2
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/inc/system/sys_ext.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SYS_EXT_H
+#define __SYS_EXT_H
+
+#include "std_ext.h"
+
+
+/**************************************************************************//**
+ @Group sys_grp System Interfaces
+
+ @Description Linux system programming interfaces.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group sys_gen_grp System General Interface
+
+ @Description General definitions, structures and routines of the linux
+ system programming interface.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Collection Macros for Advanced Configuration Requests
+ @{
+*//***************************************************************************/
+#define SYS_MAX_ADV_CONFIG_ARGS 4
+ /**< Maximum number of arguments in
+ an advanced configuration entry */
+/* @} */
+
+/**************************************************************************//**
+ @Description System Object Advanced Configuration Entry
+
+ This structure represents a single request for an advanced
+ configuration call on the initialized object. An array of such
+ requests may be contained in the settings structure of the
+ corresponding object.
+
+ The maximum number of arguments is limited to #SYS_MAX_ADV_CONFIG_ARGS.
+*//***************************************************************************/
+typedef struct t_SysObjectAdvConfigEntry
+{
+ void *p_Function; /**< Pointer to advanced configuration routine */
+
+ uintptr_t args[SYS_MAX_ADV_CONFIG_ARGS];
+ /**< Array of arguments for the specified routine;
+ All arguments should be casted to uint32_t. */
+} t_SysObjectAdvConfigEntry;
+
+
+/** @} */ /* end of sys_gen_grp */
+/** @} */ /* end of sys_grp */
+
+#define NCSW_PARAMS(_num, _params) ADV_CONFIG_PARAMS_##_num _params
+
+#define ADV_CONFIG_PARAMS_1(_type) \
+ , (_type)p_Entry->args[0]
+
+#define SET_ADV_CONFIG_ARGS_1(_arg0) \
+ p_Entry->args[0] = (uintptr_t )(_arg0); \
+
+#define ARGS(_num, _params) SET_ADV_CONFIG_ARGS_##_num _params
+
+#define ADD_ADV_CONFIG_START(_p_Entries, _maxEntries) \
+ { \
+ t_SysObjectAdvConfigEntry *p_Entry; \
+ t_SysObjectAdvConfigEntry *p_Entrys = (_p_Entries); \
+ int i=0, max = (_maxEntries); \
+
+#define ADD_ADV_CONFIG_END \
+ }
+
+#define ADV_CONFIG_CHECK_START(_p_Entry) \
+ { \
+ t_SysObjectAdvConfigEntry *p_Entry = _p_Entry; \
+ t_Error errCode; \
+
+#define ADV_CONFIG_CHECK(_handle, _func, _params) \
+ if (p_Entry->p_Function == _func) \
+ { \
+ errCode = _func(_handle _params); \
+ } else
+
+#endif /* __SYS_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/src/inc/system/sys_io_ext.h b/drivers/net/ethernet/freescale/fman/src/inc/system/sys_io_ext.h
new file mode 100644
index 0000000..d6aa9d4
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/inc/system/sys_io_ext.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SYS_IO_EXT_H
+#define __SYS_IO_EXT_H
+
+#include "std_ext.h"
+#include "error_ext.h"
+
+
+t_Error SYS_RegisterIoMap (uint64_t virtAddr, uint64_t physAddr, uint32_t size);
+t_Error SYS_UnregisterIoMap (uint64_t virtAddr);
+uint64_t SYS_PhysToVirt (uint64_t addr);
+uint64_t SYS_VirtToPhys (uint64_t addr);
+
+
+#endif /* __SYS_IO_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/src/inc/types_linux.h b/drivers/net/ethernet/freescale/fman/src/inc/types_linux.h
new file mode 100644
index 0000000..ac15d66
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/inc/types_linux.h
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TYPES_LINUX_H__
+#define __TYPES_LINUX_H__
+
+#include <linux/version.h>
+
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+#define MODVERSIONS
+#endif
+#ifdef MODVERSIONS
+#include <config/modversions.h>
+#endif /* MODVERSIONS */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/io.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
+ #error "This kernel is probably not supported!!!"
+#elif (!((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)) || \
+ (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,27)) || \
+ (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,30))))
+ #warning "This kernel is probably not supported!!! You may need to add some fixes."
+#endif /* LINUX_VERSION_CODE */
+
+
+typedef float float_t; /* Single precision floating point */
+typedef double double_t; /* Double precision floating point */
+
+
+#define _Packed
+#define _PackedType __attribute__ ((packed))
+
+typedef phys_addr_t physAddress_t;
+
+#define UINT8_MAX 0xFF
+#define UINT8_MIN 0
+#define UINT16_MAX 0xFFFF
+#define UINT16_MIN 0
+#define UINT32_MAX 0xFFFFFFFF
+#define UINT32_MIN 0
+#define UINT64_MAX 0xFFFFFFFFFFFFFFFFLL
+#define UINT64_MIN 0
+#define INT8_MAX 0x7F
+#define INT8_MIN 0x80
+#define INT16_MAX 0x7FFF
+#define INT16_MIN 0x8000
+#define INT32_MAX 0x7FFFFFFF
+#define INT32_MIN 0x80000000
+#define INT64_MAX 0x7FFFFFFFFFFFFFFFLL
+#define INT64_MIN 0x8000000000000000LL
+
+#define ON 1
+#define OFF 0
+
+#define FALSE false
+#define TRUE true
+
+
+/************************/
+/* memory access macros */
+/************************/
+#define GET_UINT8(arg) *(volatile uint8_t *)(&(arg))
+#define GET_UINT16(arg) in_be16(&(arg))//*(volatile uint16_t*)(&(arg))
+#define GET_UINT32(arg) in_be32(&(arg))//*(volatile uint32_t*)(&(arg))
+#define GET_UINT64(arg) *(volatile uint64_t*)(&(arg))
+
+#ifdef VERBOSE_WRITE
+void XX_Print(char *str, ...);
+#define WRITE_UINT8(arg, data) \
+ do { XX_Print("ADDR: 0x%08x, VAL: 0x%02x\r\n", (uint32_t)&(arg), (data)); *(volatile uint8_t *)(&(arg)) = (data); } while (0)
+#define WRITE_UINT16(arg, data) \
+ do { XX_Print("ADDR: 0x%08x, VAL: 0x%04x\r\n", (uint32_t)&(arg), (data)); out_be16(&(arg), data); /* *(volatile uint16_t*)(&(arg)) = (data);*/ } while (0)
+#define WRITE_UINT32(arg, data) \
+ do { XX_Print("ADDR: 0x%08x, VAL: 0x%08x\r\n", (uint32_t)&(arg), (data)); out_be32(&(arg), data); /* *(volatile uint32_t*)(&(arg)) = (data);*/ } while (0)
+#define WRITE_UINT64(arg, data) \
+ do { XX_Print("ADDR: 0x%08x, VAL: 0x%016llx\r\n", (uint32_t)&(arg), (data)); *(volatile uint64_t*)(&(arg)) = (data); } while (0)
+
+#else /* not VERBOSE_WRITE */
+#define WRITE_UINT8(arg, data) *(volatile uint8_t *)(&(arg)) = (data)
+#define WRITE_UINT16(arg, data) out_be16(&(arg), data)//*(volatile uint16_t*)(&(arg)) = (data)
+#define WRITE_UINT32(arg, data) out_be32(&(arg), data)//*(volatile unsigned int *)(&(arg)) = (data)
+#define WRITE_UINT64(arg, data) *(volatile uint64_t*)(&(arg)) = (data)
+#endif /* not VERBOSE_WRITE */
+
+
+/*****************************************************************************/
+/* General stuff */
+/*****************************************************************************/
+#ifdef ARRAY_SIZE
+#undef ARRAY_SIZE
+#endif /* ARRAY_SIZE */
+
+#ifdef MAJOR
+#undef MAJOR
+#endif /* MAJOR */
+
+#ifdef MINOR
+#undef MINOR
+#endif /* MINOR */
+
+#ifdef QE_SIZEOF_BD
+#undef QE_SIZEOF_BD
+#endif /* QE_SIZEOF_BD */
+
+#ifdef BD_BUFFER_CLEAR
+#undef BD_BUFFER_CLEAR
+#endif /* BD_BUFFER_CLEAR */
+
+#ifdef BD_BUFFER
+#undef BD_BUFFER
+#endif /* BD_BUFFER */
+
+#ifdef BD_STATUS_AND_LENGTH_SET
+#undef BD_STATUS_AND_LENGTH_SET
+#endif /* BD_STATUS_AND_LENGTH_SET */
+
+#ifdef BD_STATUS_AND_LENGTH
+#undef BD_STATUS_AND_LENGTH
+#endif /* BD_STATUS_AND_LENGTH */
+
+#ifdef BD_BUFFER_ARG
+#undef BD_BUFFER_ARG
+#endif /* BD_BUFFER_ARG */
+
+#ifdef BD_GET_NEXT
+#undef BD_GET_NEXT
+#endif /* BD_GET_NEXT */
+
+#ifdef QE_SDEBCR_BA_MASK
+#undef QE_SDEBCR_BA_MASK
+#endif /* QE_SDEBCR_BA_MASK */
+
+#ifdef BD_BUFFER_SET
+#undef BD_BUFFER_SET
+#endif /* BD_BUFFER_SET */
+
+#ifdef UPGCR_PROTOCOL
+#undef UPGCR_PROTOCOL
+#endif /* UPGCR_PROTOCOL */
+
+#ifdef UPGCR_TMS
+#undef UPGCR_TMS
+#endif /* UPGCR_TMS */
+
+#ifdef UPGCR_RMS
+#undef UPGCR_RMS
+#endif /* UPGCR_RMS */
+
+#ifdef UPGCR_ADDR
+#undef UPGCR_ADDR
+#endif /* UPGCR_ADDR */
+
+#ifdef UPGCR_DIAG
+#undef UPGCR_DIAG
+#endif /* UPGCR_DIAG */
+
+#ifdef NCSW_PARAMS
+#undef NCSW_PARAMS
+#endif /* NCSW_PARAMS */
+
+#ifdef NO_IRQ
+#undef NO_IRQ
+#endif /* NO_IRQ */
+
+#define PRINT_LINE XX_Print("%s:\n %s [%d]\n",__FILE__,__FUNCTION__,__LINE__);
+
+
+#endif /* __TYPES_LINUX_H__ */
diff --git a/drivers/net/ethernet/freescale/fman/src/inc/wrapper/fsl_fman_test.h b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/fsl_fman_test.h
new file mode 100644
index 0000000..0466a47
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/fsl_fman_test.h
@@ -0,0 +1,84 @@
+/* Copyright (c) 2008-2011 Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/******************************************************************************
+ @File fsl_fman_test.h
+
+ @Description
+*//***************************************************************************/
+
+#ifndef __FSL_FMAN_TEST_H
+#define __FSL_FMAN_TEST_H
+
+#include <linux/types.h>
+#include <linux/smp.h> /* raw_smp_processor_id() */
+
+//#define FMT_K_DBG
+//#define FMT_K_DBG_RUNTIME
+
+#define _fmt_prk(stage, format, arg...) \
+ printk(stage "fmt (cpu:%u): " format, raw_smp_processor_id(), ##arg)
+
+#define _fmt_inf(format, arg...) _fmt_prk(KERN_INFO, format, ##arg)
+#define _fmt_wrn(format, arg...) _fmt_prk(KERN_WARNING, format, ##arg)
+#define _fmt_err(format, arg...) _fmt_prk(KERN_ERR, format, ##arg)
+
+/* there are two macros for debugging: for runtime and generic.
+ * Helps when the runtime functions are not targeted for debugging,
+ * thus all the unnecessary information will be skipped.
+ */
+/* used for generic debugging */
+#if defined(FMT_K_DBG)
+ #define _fmt_dbg(format, arg...) \
+ printk("fmt [%s:%u](cpu:%u) - " format, \
+ __func__, __LINE__, raw_smp_processor_id(), ##arg)
+#else
+# define _fmt_dbg(arg...)
+#endif
+
+/* used for debugging runtime functions */
+#if defined(FMT_K_DBG_RUNTIME)
+ #define _fmt_dbgr(format, arg...) \
+ printk("fmt [%s:%u](cpu:%u) - " format, \
+ __func__, __LINE__, raw_smp_processor_id(), ##arg)
+#else
+# define _fmt_dbgr(arg...)
+#endif
+
+#define FMT_RX_ERR_Q 0xffffffff
+#define FMT_RX_DFLT_Q 0xfffffffe
+#define FMT_TX_ERR_Q 0xfffffffd
+#define FMT_TX_CONF_Q 0xfffffffc
+
+#define FMAN_TEST_MAX_TX_FQS 8
+
+#endif /* __FSL_FMAN_TEST_H */
diff --git a/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_exp_sym.h b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_exp_sym.h
new file mode 100644
index 0000000..13c61d2
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_exp_sym.h
@@ -0,0 +1,127 @@
+/* Copyright (c) 2008-2012 Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ @File lnxwrp_exp_sym.h
+ @Description FMan exported routines
+*/
+
+#ifndef __LNXWRP_EXP_SYM_H
+#define __LNXWRP_EXP_SYM_H
+
+#include "fm_port_ext.h"
+#include "fm_pcd_ext.h"
+#include "fm_mac_ext.h"
+
+
+/* FMAN Port exported routines */
+EXPORT_SYMBOL(FM_PORT_Disable);
+EXPORT_SYMBOL(FM_PORT_Enable);
+EXPORT_SYMBOL(FM_PORT_SetPCD);
+
+/* Runtime PCD exported routines */
+EXPORT_SYMBOL(FM_PCD_Enable);
+EXPORT_SYMBOL(FM_PCD_Disable);
+EXPORT_SYMBOL(FM_PCD_GetCounter);
+EXPORT_SYMBOL(FM_PCD_PrsLoadSw);
+EXPORT_SYMBOL(FM_PCD_KgSetDfltValue);
+EXPORT_SYMBOL(FM_PCD_KgSetAdditionalDataAfterParsing);
+EXPORT_SYMBOL(FM_PCD_SetException);
+EXPORT_SYMBOL(FM_PCD_ModifyCounter);
+EXPORT_SYMBOL(FM_PCD_SetPlcrStatistics);
+EXPORT_SYMBOL(FM_PCD_SetPrsStatistics);
+EXPORT_SYMBOL(FM_PCD_ForceIntr);
+EXPORT_SYMBOL(FM_PCD_HcTxConf);
+
+EXPORT_SYMBOL(FM_PCD_NetEnvCharacteristicsSet);
+EXPORT_SYMBOL(FM_PCD_NetEnvCharacteristicsDelete);
+EXPORT_SYMBOL(FM_PCD_KgSchemeSet);
+EXPORT_SYMBOL(FM_PCD_KgSchemeDelete);
+EXPORT_SYMBOL(FM_PCD_KgSchemeGetCounter);
+EXPORT_SYMBOL(FM_PCD_KgSchemeSetCounter);
+EXPORT_SYMBOL(FM_PCD_CcRootBuild);
+EXPORT_SYMBOL(FM_PCD_CcRootDelete);
+EXPORT_SYMBOL(FM_PCD_MatchTableSet);
+EXPORT_SYMBOL(FM_PCD_MatchTableDelete);
+EXPORT_SYMBOL(FM_PCD_CcRootModifyNextEngine);
+EXPORT_SYMBOL(FM_PCD_MatchTableModifyNextEngine);
+EXPORT_SYMBOL(FM_PCD_MatchTableFindNModifyNextEngine);
+EXPORT_SYMBOL(FM_PCD_MatchTableModifyMissNextEngine);
+EXPORT_SYMBOL(FM_PCD_MatchTableRemoveKey);
+EXPORT_SYMBOL(FM_PCD_MatchTableFindNRemoveKey);
+EXPORT_SYMBOL(FM_PCD_MatchTableAddKey);
+EXPORT_SYMBOL(FM_PCD_MatchTableModifyKeyAndNextEngine);
+EXPORT_SYMBOL(FM_PCD_MatchTableFindNModifyKeyAndNextEngine);
+EXPORT_SYMBOL(FM_PCD_MatchTableModifyKey);
+EXPORT_SYMBOL(FM_PCD_MatchTableFindNModifyKey);
+EXPORT_SYMBOL(FM_PCD_MatchTableGetIndexedHashBucket);
+EXPORT_SYMBOL(FM_PCD_MatchTableGetNextEngine);
+EXPORT_SYMBOL(FM_PCD_MatchTableGetKeyCounter);
+EXPORT_SYMBOL(FM_PCD_MatchTableGetKeyStatistics);
+EXPORT_SYMBOL(FM_PCD_MatchTableFindNGetKeyStatistics);
+EXPORT_SYMBOL(FM_PCD_MatchTableGetMissStatistics);
+EXPORT_SYMBOL(FM_PCD_HashTableGetMissStatistics);
+EXPORT_SYMBOL(FM_PCD_HashTableSet);
+EXPORT_SYMBOL(FM_PCD_HashTableDelete);
+EXPORT_SYMBOL(FM_PCD_HashTableAddKey);
+EXPORT_SYMBOL(FM_PCD_HashTableRemoveKey);
+EXPORT_SYMBOL(FM_PCD_HashTableModifyNextEngine);
+EXPORT_SYMBOL(FM_PCD_HashTableModifyMissNextEngine);
+EXPORT_SYMBOL(FM_PCD_HashTableGetMissNextEngine);
+EXPORT_SYMBOL(FM_PCD_HashTableFindNGetKeyStatistics);
+EXPORT_SYMBOL(FM_PCD_PlcrProfileSet);
+EXPORT_SYMBOL(FM_PCD_PlcrProfileDelete);
+EXPORT_SYMBOL(FM_PCD_PlcrProfileGetCounter);
+EXPORT_SYMBOL(FM_PCD_PlcrProfileSetCounter);
+EXPORT_SYMBOL(FM_PCD_ManipNodeSet);
+EXPORT_SYMBOL(FM_PCD_ManipNodeDelete);
+EXPORT_SYMBOL(FM_PCD_ManipGetStatistics);
+EXPORT_SYMBOL(FM_PCD_ManipNodeReplace);
+#if (DPAA_VERSION >= 11)
+EXPORT_SYMBOL(FM_PCD_FrmReplicSetGroup);
+EXPORT_SYMBOL(FM_PCD_FrmReplicDeleteGroup);
+EXPORT_SYMBOL(FM_PCD_FrmReplicAddMember);
+EXPORT_SYMBOL(FM_PCD_FrmReplicRemoveMember);
+#endif /* DPAA_VERSION >= 11 */
+
+#ifdef FM_CAPWAP_SUPPORT
+EXPORT_SYMBOL(FM_PCD_StatisticsSetNode);
+#endif /* FM_CAPWAP_SUPPORT */
+
+EXPORT_SYMBOL(FM_PCD_SetAdvancedOffloadSupport);
+
+/* FMAN MAC exported routines */
+EXPORT_SYMBOL(FM_MAC_GetStatistics);
+
+EXPORT_SYMBOL(FM_GetSpecialOperationCoding);
+
+#endif /* __LNXWRP_EXP_SYM_H */
diff --git a/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fm_ext.h b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fm_ext.h
new file mode 100644
index 0000000..1b56cbd
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fm_ext.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/******************************************************************************
+ @File lnxwrp_fm_ext.h
+
+ @Description TODO
+*//***************************************************************************/
+
+#ifndef __LNXWRP_FM_EXT_H
+#define __LNXWRP_FM_EXT_H
+
+#include "std_ext.h"
+#include "sys_ext.h"
+#include "fm_ext.h"
+#include "fm_muram_ext.h"
+#include "fm_pcd_ext.h"
+#include "fm_port_ext.h"
+#include "fm_mac_ext.h"
+#include "fm_rtc_ext.h"
+
+
+/**************************************************************************//**
+ @Group FM_LnxKern_grp Frame Manager Linux wrapper API
+
+ @Description FM API functions, definitions and enums.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group FM_LnxKern_init_grp Initialization Unit
+
+ @Description Initialization Unit
+
+ Initialization Flow:
+ Initialization of the FM Module will be carried out by the Linux
+ kernel according to the following sequence:
+ a. Calling the initialization routine with no parameters.
+ b. The driver will register to the Device-Tree.
+ c. The Linux Device-Tree will initiate a call to the driver for
+ initialization.
+ d. The driver will read the appropriate information from the Device-Tree
+ e. [Optional] Calling the advance initialization routines to change
+ driver's defaults.
+ f. Initialization of the device will be automatically upon using it.
+
+ @{
+*//***************************************************************************/
+
+typedef struct t_WrpFmDevSettings
+{
+ t_FmParams param;
+ t_SysObjectAdvConfigEntry *advConfig;
+} t_WrpFmDevSettings;
+
+typedef struct t_WrpFmPcdDevSettings
+{
+ t_FmPcdParams param;
+ t_SysObjectAdvConfigEntry *advConfig;
+} t_WrpFmPcdDevSettings;
+
+typedef struct t_WrpFmPortDevSettings
+{
+ bool frag_enabled;
+ t_FmPortParams param;
+ t_SysObjectAdvConfigEntry *advConfig;
+} t_WrpFmPortDevSettings;
+
+typedef struct t_WrpFmMacDevSettings
+{
+ t_FmMacParams param;
+ t_SysObjectAdvConfigEntry *advConfig;
+} t_WrpFmMacDevSettings;
+
+
+/**************************************************************************//**
+ @Function LNXWRP_FM_Init
+
+ @Description Initialize the FM linux wrapper.
+
+ @Return A handle (descriptor) of the newly created FM Linux wrapper
+ structure.
+*//***************************************************************************/
+t_Handle LNXWRP_FM_Init(void);
+
+/**************************************************************************//**
+ @Function LNXWRP_FM_Free
+
+ @Description Free the FM linux wrapper.
+
+ @Param[in] h_LnxWrpFm - A handle to the FM linux wrapper.
+
+ @Return E_OK on success; Error code otherwise.
+*//***************************************************************************/
+t_Error LNXWRP_FM_Free(t_Handle h_LnxWrpFm);
+
+/**************************************************************************//**
+ @Function LNXWRP_FM_GetMacHandle
+
+ @Description Get the FM-MAC LLD handle from the FM linux wrapper.
+
+ @Param[in] h_LnxWrpFm - A handle to the FM linux wrapper.
+ @Param[in] fmId - Index of the FM device to get the MAC handle from.
+ @Param[in] macId - Index of the mac handle.
+
+ @Return A handle of the LLD compressor.
+*//***************************************************************************/
+t_Handle LNXWRP_FM_GetMacHandle(t_Handle h_LnxWrpFm, uint8_t fmId, uint8_t macId);
+
+#ifdef CONFIG_FSL_FMAN_TEST
+t_Handle LNXWRP_FM_TEST_Init(void);
+t_Error LNXWRP_FM_TEST_Free(t_Handle h_FmTestLnxWrp);
+#endif /* CONFIG_FSL_FMAN_TEST */
+
+/** @} */ /* end of FM_LnxKern_init_grp group */
+
+
+/**************************************************************************//**
+ @Group FM_LnxKern_ctrl_grp Control Unit
+
+ @Description Control Unit
+
+ TODO
+ @{
+*//***************************************************************************/
+
+#include "lnxwrp_fsl_fman.h"
+
+/** @} */ /* end of FM_LnxKern_ctrl_grp group */
+/** @} */ /* end of FM_LnxKern_grp group */
+
+
+#endif /* __LNXWRP_FM_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fsl_fman.h b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fsl_fman.h
new file mode 100644
index 0000000..97a7c0c
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fsl_fman.h
@@ -0,0 +1,657 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/******************************************************************************
+ @File lnxwrp_fsl_fman.h
+
+ @Description Linux internal kernel API
+*//***************************************************************************/
+
+#ifndef __LNXWRP_FSL_FMAN_H
+#define __LNXWRP_FSL_FMAN_H
+
+#include <linux/types.h>
+#include <linux/device.h> /* struct device */
+#include <linux/fsl_qman.h> /* struct qman_fq */
+#include "dpaa_integration_ext.h"
+#include "fm_port_ext.h"
+#include "fm_mac_ext.h"
+#include "fm_rtc_ext.h"
+
+/**************************************************************************//**
+ @Group FM_LnxKern_grp Frame Manager Linux wrapper API
+
+ @Description FM API functions, definitions and enums.
+
+ @{
+*//***************************************************************************/
+
+/**************************************************************************//**
+ @Group FM_LnxKern_ctrl_grp Control Unit
+
+ @Description Control Unit
+
+ Internal Kernel Control Unit API
+ @{
+*//***************************************************************************/
+
+/*****************************************************************************/
+/* Internal Linux kernel routines */
+/*****************************************************************************/
+
+/**************************************************************************//**
+ @Description FM device opaque structure used for type checking
+*//***************************************************************************/
+struct fm;
+
+/**************************************************************************//**
+ @Description FM MAC device opaque structure used for type checking
+*//***************************************************************************/
+struct fm_mac_dev;
+
+/**************************************************************************//**
+ @Description A structure ..,
+*//***************************************************************************/
+struct fm_port;
+
+typedef int (*alloc_pcd_fqids)(struct device *dev, uint32_t num,
+ uint8_t alignment, uint32_t *base_fqid);
+
+typedef int (*free_pcd_fqids)(struct device *dev, uint32_t base_fqid);
+
+struct fm_port_pcd_param {
+ alloc_pcd_fqids cba;
+ free_pcd_fqids cbf;
+ struct device *dev;
+};
+
+/**************************************************************************//**
+ @Description A structure of information about each of the external
+ buffer pools used by the port,
+*//***************************************************************************/
+struct fm_port_pool_param {
+ uint8_t id; /**< External buffer pool id */
+ uint16_t size; /**< External buffer pool buffer size */
+};
+
+/**************************************************************************//**
+ @Description structure for additional port parameters
+*//***************************************************************************/
+struct fm_port_params {
+ uint32_t errq; /**< Error Queue Id. */
+ uint32_t defq; /**< For Tx and HC - Default Confirmation queue,
+ 0 means no Tx conf for processed frames.
+ For Rx and OP - default Rx queue. */
+ uint8_t num_pools; /**< Number of pools use by this port */
+ struct fm_port_pool_param pool_param[FM_PORT_MAX_NUM_OF_EXT_POOLS];
+ /**< Parameters for each pool */
+ uint16_t priv_data_size; /**< Area that user may save for his own
+ need (E.g. save the SKB) */
+ bool parse_results; /**< Put the parser-results in the Rx/Tx buffer */
+ bool hash_results; /**< Put the hash-results in the Rx/Tx buffer */
+ bool time_stamp; /**< Put the time-stamp in the Rx/Tx buffer */
+ bool frag_enable; /**< Fragmentation support, for OP only */
+ uint16_t data_align; /**< value for selecting a data alignment (must be a power of 2);
+ if write optimization is used, must be >= 16. */
+ uint8_t manip_extra_space; /**< Maximum extra size needed (insertion-size minus removal-size);
+ Note that this field impacts the size of the buffer-prefix
+ (i.e. it pushes the data offset); */
+};
+
+/**************************************************************************//**
+ @Function fm_bind
+
+ @Description Bind to a specific FM device.
+
+ @Param[in] fm_dev - the OF handle of the FM device.
+
+ @Return A handle of the FM device.
+
+ @Cautions Allowed only after the port was created.
+*//***************************************************************************/
+struct fm *fm_bind(struct device *fm_dev);
+
+/**************************************************************************//**
+ @Function fm_unbind
+
+ @Description Un-bind from a specific FM device.
+
+ @Param[in] fm - A handle of the FM device.
+
+ @Cautions Allowed only after the port was created.
+*//***************************************************************************/
+void fm_unbind(struct fm *fm);
+
+void *fm_get_handle(struct fm *fm);
+void *fm_get_rtc_handle(struct fm *fm);
+struct resource *fm_get_mem_region(struct fm *fm);
+
+/**************************************************************************//**
+ @Function fm_port_bind
+
+ @Description Bind to a specific FM-port device (may be Rx or Tx port).
+
+ @Param[in] fm_port_dev - the OF handle of the FM port device.
+
+ @Return A handle of the FM port device.
+
+ @Cautions Allowed only after the port was created.
+*//***************************************************************************/
+struct fm_port *fm_port_bind(struct device *fm_port_dev);
+
+/**************************************************************************//**
+ @Function fm_port_unbind
+
+ @Description Un-bind from a specific FM-port device (may be Rx or Tx port).
+
+ @Param[in] port - A handle of the FM port device.
+
+ @Cautions Allowed only after the port was created.
+*//***************************************************************************/
+void fm_port_unbind(struct fm_port *port);
+
+/**************************************************************************//**
+ @Function fm_set_rx_port_params
+
+ @Description Configure parameters for a specific Rx FM-port device.
+
+ @Param[in] port - A handle of the FM port device.
+ @Param[in] params - Rx port parameters
+
+ @Cautions Allowed only after the port is binded.
+*//***************************************************************************/
+void fm_set_rx_port_params(struct fm_port *port,
+ struct fm_port_params *params);
+
+/**************************************************************************//**
+ @Function fm_port_pcd_bind
+
+ @Description Bind as a listener on a port PCD.
+
+ @Param[in] port - A handle of the FM port device.
+ @Param[in] params - PCD port parameters
+
+ @Cautions Allowed only after the port is binded.
+*//***************************************************************************/
+void fm_port_pcd_bind (struct fm_port *port, struct fm_port_pcd_param *params);
+
+/**************************************************************************//**
+ @Function fm_port_get_buff_layout_ext_params
+
+ @Description Get data_align and manip_extra_space from the device tree
+ chosen node if applied.
+ This function will only update these two parameters.
+ When this port has no such parameters in the device tree
+ values will be set to 0.
+
+ @Param[in] port - A handle of the FM port device.
+ @Param[in] params - PCD port parameters
+
+ @Cautions Allowed only after the port is binded.
+*//***************************************************************************/
+void fm_port_get_buff_layout_ext_params(struct fm_port *port, struct fm_port_params *params);
+
+/**************************************************************************//**
+ @Function fm_get_tx_port_channel
+
+ @Description Get qman-channel number for this Tx port.
+
+ @Param[in] port - A handle of the FM port device.
+
+ @Return qman-channel number for this Tx port.
+
+ @Cautions Allowed only after the port is binded.
+*//***************************************************************************/
+int fm_get_tx_port_channel(struct fm_port *port);
+
+/**************************************************************************//**
+ @Function fm_set_tx_port_params
+
+ @Description Configure parameters for a specific Tx FM-port device
+
+ @Param[in] port - A handle of the FM port device.
+ @Param[in] params - Tx port parameters
+
+ @Cautions Allowed only after the port is binded.
+*//***************************************************************************/
+void fm_set_tx_port_params(struct fm_port *port, struct fm_port_params *params);
+
+
+/**************************************************************************//**
+ @Function fm_mac_set_handle
+
+ @Description Set mac handle
+
+ @Param[in] h_lnx_wrp_fm_dev - A handle of the LnxWrp FM device.
+ @Param[in] h_fm_mac - A handle of the LnxWrp FM MAC device.
+ @Param[in] mac_id - MAC id.
+*//***************************************************************************/
+void fm_mac_set_handle(t_Handle h_lnx_wrp_fm_dev, t_Handle h_fm_mac,
+ int mac_id);
+
+/**************************************************************************//**
+ @Function fm_port_enable
+
+ @Description Enable specific FM-port device (may be Rx or Tx port).
+
+ @Param[in] port - A handle of the FM port device.
+
+ @Cautions Allowed only after the port is initialized.
+*//***************************************************************************/
+int fm_port_enable(struct fm_port *port);
+
+/**************************************************************************//**
+ @Function fm_port_disable
+
+ @Description Disable specific FM-port device (may be Rx or Tx port).
+
+ @Param[in] port - A handle of the FM port device.
+
+ @Cautions Allowed only after the port is initialized.
+*//***************************************************************************/
+int fm_port_disable(struct fm_port *port);
+
+void *fm_port_get_handle(const struct fm_port *port);
+
+u64 *fm_port_get_buffer_time_stamp(const struct fm_port *port,
+ const void *data);
+
+/**************************************************************************//**
+ @Function fm_port_get_base_address
+
+ @Description Get base address of this port. Useful for accessing
+ port-specific registers (i.e., not common ones).
+
+ @Param[in] port - A handle of the FM port device.
+
+ @Param[out] base_addr - The port's base addr (virtual address).
+*//***************************************************************************/
+void fm_port_get_base_addr(const struct fm_port *port, uint64_t *base_addr);
+
+/**************************************************************************//**
+ @Function fm_mutex_lock
+
+ @Description Lock function required before any FMD/LLD call.
+*//***************************************************************************/
+void fm_mutex_lock(void);
+
+/**************************************************************************//**
+ @Function fm_mutex_unlock
+
+ @Description Unlock function required after any FMD/LLD call.
+*//***************************************************************************/
+void fm_mutex_unlock(void);
+
+/**************************************************************************//**
+ @Function fm_get_max_frm
+
+ @Description Get the maximum frame size
+*//***************************************************************************/
+int fm_get_max_frm(void);
+
+/**************************************************************************//**
+ @Function fm_get_rx_extra_headroom
+
+ @Description Get the extra headroom size
+*//***************************************************************************/
+int fm_get_rx_extra_headroom(void);
+
+/**************************************************************************//**
+@Function fm_port_set_rate_limit
+
+@Description Configure Shaper parameter on FM-port device (Tx port).
+
+@Param[in] port - A handle of the FM port device.
+@Param[in] max_burst_size - Value of maximum burst size allowed.
+@Param[in] rate_limit - The required rate value.
+
+@Cautions Allowed only after the port is initialized.
+*//***************************************************************************/
+int fm_port_set_rate_limit(struct fm_port *port,
+ uint16_t max_burst_size,
+ uint32_t rate_limit);
+/**************************************************************************//**
+@Function fm_port_set_rate_limit
+
+@Description Delete Shaper configuration on FM-port device (Tx port).
+
+@Param[in] port - A handle of the FM port device.
+
+@Cautions Allowed only after the port is initialized.
+*//***************************************************************************/
+int fm_port_del_rate_limit(struct fm_port *port);
+
+struct auto_res_tables_sizes
+{
+ uint16_t max_num_of_arp_entries;
+ uint16_t max_num_of_echo_ipv4_entries;
+ uint16_t max_num_of_ndp_entries;
+ uint16_t max_num_of_echo_ipv6_entries;
+ uint16_t max_num_of_snmp_ipv4_entries;
+ uint16_t max_num_of_snmp_ipv6_entries;
+ uint16_t max_num_of_snmp_oid_entries;
+ uint16_t max_num_of_snmp_char; /* total amount of character needed
+ for the snmp table */
+ uint16_t max_num_of_ip_prot_filtering;
+ uint16_t max_num_of_tcp_port_filtering;
+ uint16_t max_num_of_udp_port_filtering;
+};
+/* ARP */
+struct auto_res_arp_entry
+{
+ uint32_t ip_address;
+ uint8_t mac[6];
+ bool is_vlan;
+ uint16_t vid;
+};
+struct auto_res_arp_info
+{
+ uint8_t table_size;
+ struct auto_res_arp_entry *auto_res_table;
+ bool enable_conflict_detection; /* when TRUE
+ Conflict Detection will be checked and wake the host if
+ needed */
+};
+
+/* NDP */
+struct auto_res_ndp_entry
+{
+ uint32_t ip_address[4];
+ uint8_t mac[6];
+ bool is_vlan;
+ uint16_t vid;
+};
+struct auto_res_ndp_info
+{
+ uint32_t multicast_group;
+ uint8_t table_size_assigned;
+ struct auto_res_ndp_entry *auto_res_table_assigned; /* This list
+ refer to solicitation IP addresses. Note that all IP adresses
+ must be from the same multicast group. This will be checked and
+ if not operation will fail. */
+ uint8_t table_size_tmp;
+ struct auto_res_ndp_entry *auto_res_table_tmp; /* This list
+ refer to temp IP addresses. Note that all temp IP adresses must
+ be from the same multicast group. This will be checked and if
+ not operation will fail. */
+
+ bool enable_conflict_detection; /* when TRUE
+ Conflict Detection will be checked and wake the host if
+ needed */
+};
+
+/* ICMP ECHO */
+struct auto_res_echo_ipv4_info
+{
+ uint8_t table_size;
+ struct auto_res_arp_entry *auto_res_table;
+};
+
+struct auto_res_echo_ipv6_info
+{
+ uint8_t table_size;
+ struct auto_res_ndp_entry *auto_res_table;
+};
+
+/* SNMP */
+struct auto_res_snmp_entry
+{
+ uint16_t oidSize;
+ uint8_t *oidVal; /* only the oid string */
+ uint16_t resSize;
+ uint8_t *resVal; /* resVal will be the entire reply,
+ i.e. "Type|Length|Value" */
+};
+
+/**************************************************************************//**
+ @Description Deep Sleep Auto Response SNMP IPv4 Addresses Table Entry
+ Refer to the FMan Controller spec for more details.
+*//***************************************************************************/
+struct auto_res_snmp_ipv4addr_tbl_entry
+{
+ uint32_t ipv4addr; /*!< 32 bit IPv4 Address. */
+ bool is_vlan;
+ uint16_t vid; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */
+ /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */
+};
+
+/**************************************************************************//**
+ @Description Deep Sleep Auto Response SNMP IPv6 Addresses Table Entry
+ Refer to the FMan Controller spec for more details.
+*//***************************************************************************/
+struct auto_res_snmp_ipv6addr_tbl_entry
+{
+ uint32_t ipv6Addr[4]; /*!< 4 * 32 bit IPv6 Address. */
+ bool isVlan;
+ uint16_t vid; /*!< 12 bits VLAN ID. The 4 left-most bits should be cleared */
+ /*!< This field should be 0x0000 for an entry with no VLAN tag or a null VLAN ID. */
+};
+
+struct auto_res_snmp_info
+{
+ uint16_t control; /**< Control bits [0-15]. */
+ uint16_t max_snmp_msg_length; /**< Maximal allowed SNMP message length. */
+ uint16_t num_ipv4_addresses; /**< Number of entries in IPv4 addresses table. */
+ uint16_t num_ipv6_addresses; /**< Number of entries in IPv6 addresses table. */
+ struct auto_res_snmp_ipv4addr_tbl_entry *ipv4addr_tbl; /**< Pointer to IPv4 addresses table. */
+ struct auto_res_snmp_ipv6addr_tbl_entry *ipv6addr_tbl; /**< Pointer to IPv6 addresses table. */
+ char *community_read_write_string;
+ char *community_read_only_string;
+ struct auto_res_snmp_entry *oid_table;
+ uint32_t oid_table_size;
+};
+
+/* Filtering */
+struct auto_res_port_filtering_entry
+{
+ uint16_t src_port;
+ uint16_t dst_port;
+ uint16_t src_port_mask;
+ uint16_t dst_port_mask;
+};
+struct auto_res_filtering_info
+{
+ /* IP protocol filtering parameters */
+ uint8_t ip_prot_table_size;
+ uint8_t *ip_prot_table_ptr;
+ bool ip_prot_drop_on_hit; /* when TRUE, hit in the table will
+ cause the packet to be droped, miss will pass the packet to
+ UDP/TCP filters if needed and if not to the classification
+ tree. If the classification tree will pass the packet to a
+ queue it will cause a wake interupt. When FALSE it the other
+ way around. */
+ /* UDP port filtering parameters */
+ uint8_t udp_ports_table_size;
+ struct auto_res_port_filtering_entry *udp_ports_table_ptr;
+ bool udp_port_drop_on_hit; /* when TRUE, hit in the table will
+ cause the packet to be droped, miss will pass the packet to
+ classification tree. If the classification tree will pass the
+ packet to a queue it will cause a wake interupt. When FALSE it
+ the other way around. */
+ /* TCP port filtering parameters */
+ uint16_t tcp_flags_mask;
+ uint8_t tcp_ports_table_size;
+ struct auto_res_port_filtering_entry *tcp_ports_table_ptr;
+ bool tcp_port_drop_on_hit; /* when TRUE, hit in the table will
+ cause the packet to be droped, miss will pass the packet to
+ classification tree. If the classification tree will pass the
+ packet to a queue it will cause a wake interupt. When FALSE it
+ the other way around. */
+};
+
+struct auto_res_port_params
+{
+ t_Handle h_FmPortTx;
+ struct auto_res_arp_info *p_auto_res_arp_info;
+ struct auto_res_echo_ipv4_info *p_auto_res_echo_ipv4_info;
+ struct auto_res_ndp_info *p_auto_res_ndp_info;
+ struct auto_res_echo_ipv6_info *p_auto_res_echo_ipv6_info;
+ struct auto_res_snmp_info *p_auto_res_snmp_info;
+ struct auto_res_filtering_info *p_auto_res_filtering_info;
+};
+
+struct auto_res_port_stats
+{
+ uint32_t arp_ar_cnt;
+ uint32_t echo_icmpv4_ar_cnt;
+ uint32_t ndp_ar_cnt;
+ uint32_t echo_icmpv6_ar_cnt;
+};
+
+int fm_port_config_autores_for_deepsleep_support(struct fm_port *port,
+ struct auto_res_tables_sizes *params);
+
+int fm_port_enter_autores_for_deepsleep(struct fm_port *port,
+ struct auto_res_port_params *params);
+
+void fm_port_exit_auto_res_for_deep_sleep(struct fm_port *port_rx,
+ struct fm_port *port_tx);
+
+bool fm_port_is_in_auto_res_mode(struct fm_port *port);
+
+struct auto_res_tables_sizes *fm_port_get_autores_maxsize(
+ struct fm_port *port);
+
+int fm_port_get_autores_stats(struct fm_port *port, struct auto_res_port_stats
+ *stats);
+
+int fm_port_resume(struct fm_port *port);
+
+int fm_port_suspend(struct fm_port *port);
+
+#ifdef CONFIG_FMAN_PFC
+/**************************************************************************//**
+@Function fm_port_set_pfc_priorities_mapping_to_qman_wq
+
+@Description Associate a QMan Work Queue with a PFC priority on this
+ FM-port device (Tx port).
+
+@Param[in] port - A handle of the FM port device.
+
+@Param[in] prio - The PFC priority.
+
+@Param[in] wq - The Work Queue associated with the PFC priority.
+
+@Cautions Allowed only after the port is initialized.
+*//***************************************************************************/
+int fm_port_set_pfc_priorities_mapping_to_qman_wq(struct fm_port *port,
+ uint8_t prio, uint8_t wq);
+#endif
+
+/**************************************************************************//**
+@Function fm_mac_set_exception
+
+@Description Set MAC exception state.
+
+@Param[in] fm_mac_dev - A handle of the FM MAC device.
+@Param[in] exception - FM MAC exception type.
+@Param[in] enable - new state.
+
+*//***************************************************************************/
+int fm_mac_set_exception(struct fm_mac_dev *fm_mac_dev,
+ e_FmMacExceptions exception, bool enable);
+
+int fm_mac_free(struct fm_mac_dev *fm_mac_dev);
+
+struct fm_mac_dev *fm_mac_config(t_FmMacParams *params);
+
+int fm_mac_config_max_frame_length(struct fm_mac_dev *fm_mac_dev,
+ int len);
+
+int fm_mac_config_pad_and_crc(struct fm_mac_dev *fm_mac_dev, bool enable);
+
+int fm_mac_config_half_duplex(struct fm_mac_dev *fm_mac_dev, bool enable);
+
+int fm_mac_config_reset_on_init(struct fm_mac_dev *fm_mac_dev, bool enable);
+
+int fm_mac_init(struct fm_mac_dev *fm_mac_dev);
+
+int fm_mac_get_version(struct fm_mac_dev *fm_mac_dev, uint32_t *version);
+
+int fm_mac_enable(struct fm_mac_dev *fm_mac_dev);
+
+int fm_mac_disable(struct fm_mac_dev *fm_mac_dev);
+
+int fm_mac_set_promiscuous(struct fm_mac_dev *fm_mac_dev,
+ bool enable);
+
+int fm_mac_remove_hash_mac_addr(struct fm_mac_dev *fm_mac_dev,
+ t_EnetAddr *mac_addr);
+
+int fm_mac_add_hash_mac_addr(struct fm_mac_dev *fm_mac_dev,
+ t_EnetAddr *mac_addr);
+
+int fm_mac_modify_mac_addr(struct fm_mac_dev *fm_mac_dev,
+ uint8_t *addr);
+
+int fm_mac_adjust_link(struct fm_mac_dev *fm_mac_dev,
+ bool link, int speed, bool duplex);
+
+int fm_mac_enable_1588_time_stamp(struct fm_mac_dev *fm_mac_dev);
+
+int fm_mac_disable_1588_time_stamp(struct fm_mac_dev *fm_mac_dev);
+
+int fm_mac_set_rx_pause_frames(
+ struct fm_mac_dev *fm_mac_dev, bool en);
+
+int fm_mac_set_tx_pause_frames(struct fm_mac_dev *fm_mac_dev,
+ bool en);
+
+int fm_rtc_enable(struct fm *fm_dev);
+
+int fm_rtc_disable(struct fm *fm_dev);
+
+int fm_rtc_get_cnt(struct fm *fm_dev, uint64_t *ts);
+
+int fm_rtc_set_cnt(struct fm *fm_dev, uint64_t ts);
+
+int fm_rtc_get_drift(struct fm *fm_dev, uint32_t *drift);
+
+int fm_rtc_set_drift(struct fm *fm_dev, uint32_t drift);
+
+int fm_rtc_set_alarm(struct fm *fm_dev, uint32_t id,
+ uint64_t time);
+
+int fm_rtc_set_fiper(struct fm *fm_dev, uint32_t id,
+ uint64_t fiper);
+
+int fm_mac_set_wol(struct fm_port *port, struct fm_mac_dev *fm_mac_dev,
+ bool en);
+
+/** @} */ /* end of FM_LnxKern_ctrl_grp group */
+/** @} */ /* end of FM_LnxKern_grp group */
+
+/* default values for initializing PTP 1588 timer clock */
+#define DPA_PTP_NOMINAL_FREQ_PERIOD_SHIFT 2 /* power of 2 for better performance */
+#define DPA_PTP_NOMINAL_FREQ_PERIOD_NS (1 << DPA_PTP_NOMINAL_FREQ_PERIOD_SHIFT) /* 4ns,250MHz */
+
+#endif /* __LNXWRP_FSL_FMAN_H */
diff --git a/drivers/net/ethernet/freescale/fman/src/inc/xx/xx.h b/drivers/net/ethernet/freescale/fman/src/inc/xx/xx.h
new file mode 100644
index 0000000..b183c86
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/inc/xx/xx.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __XX_H
+#define __XX_H
+
+#include "xx_ext.h"
+
+void * xx_Malloc(uint32_t n);
+void xx_Free(void *p);
+
+void *xx_MallocSmart(uint32_t size, int memPartitionId, uint32_t align);
+void xx_FreeSmart(void *p);
+
+/* never used: */
+#define GetDeviceName(irq) ((char *)NULL)
+
+int GetDeviceIrqNum(int irq);
+
+
+#endif /* __XX_H */
diff --git a/drivers/net/ethernet/freescale/fman/src/system/Makefile b/drivers/net/ethernet/freescale/fman/src/system/Makefile
new file mode 100644
index 0000000..f1aa763
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/system/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+#
+
+obj-y += sys_io.o
diff --git a/drivers/net/ethernet/freescale/fman/src/system/sys_io.c b/drivers/net/ethernet/freescale/fman/src/system/sys_io.c
new file mode 100644
index 0000000..c106a8b
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/system/sys_io.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/version.h>
+
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+#define MODVERSIONS
+#endif
+#ifdef MODVERSIONS
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+#include <linux/modversions.h>
+#else
+#include <config/modversions.h>
+#endif /* LINUX_VERSION_CODE */
+#endif /* MODVERSIONS */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#include <asm/io.h>
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "string_ext.h"
+#include "list_ext.h"
+#include "sys_io_ext.h"
+
+
+#define __ERR_MODULE__ MODULE_UNKNOWN
+
+
+typedef struct {
+ uint64_t virtAddr;
+ uint64_t physAddr;
+ uint32_t size;
+ t_List node;
+} t_IoMap;
+#define IOMAP_OBJECT(ptr) LIST_OBJECT(ptr, t_IoMap, node)
+
+LIST(mapsList);
+
+
+static void EnqueueIoMap(t_IoMap *p_IoMap)
+{
+ uint32_t intFlags;
+
+ intFlags = XX_DisableAllIntr();
+ LIST_AddToTail(&p_IoMap->node, &mapsList);
+ XX_RestoreAllIntr(intFlags);
+}
+
+static t_IoMap * FindIoMapByVirtAddr(uint64_t addr)
+{
+ t_IoMap *p_IoMap;
+ t_List *p_Pos;
+
+ LIST_FOR_EACH(p_Pos, &mapsList)
+ {
+ p_IoMap = IOMAP_OBJECT(p_Pos);
+ if ((addr >= p_IoMap->virtAddr) && (addr < p_IoMap->virtAddr+p_IoMap->size))
+ return p_IoMap;
+ }
+
+ return NULL;
+}
+
+static t_IoMap * FindIoMapByPhysAddr(uint64_t addr)
+{
+ t_IoMap *p_IoMap;
+ t_List *p_Pos;
+
+ LIST_FOR_EACH(p_Pos, &mapsList)
+ {
+ p_IoMap = IOMAP_OBJECT(p_Pos);
+ if ((addr >= p_IoMap->physAddr) && (addr < p_IoMap->physAddr+p_IoMap->size))
+ return p_IoMap;
+ }
+
+ return NULL;
+}
+
+t_Error SYS_RegisterIoMap (uint64_t virtAddr, uint64_t physAddr, uint32_t size)
+{
+ t_IoMap *p_IoMap;
+
+ p_IoMap = (t_IoMap*)XX_Malloc(sizeof(t_IoMap));
+ if (!p_IoMap)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("message handler object!!!"));
+ memset(p_IoMap, 0, sizeof(t_IoMap));
+
+ p_IoMap->virtAddr = virtAddr;
+ p_IoMap->physAddr = physAddr;
+ p_IoMap->size = size;
+
+ INIT_LIST(&p_IoMap->node);
+ EnqueueIoMap(p_IoMap);
+
+ return E_OK;
+}
+
+t_Error SYS_UnregisterIoMap (uint64_t virtAddr)
+{
+ t_IoMap *p_IoMap = FindIoMapByVirtAddr(virtAddr);
+ if (!p_IoMap)
+ RETURN_ERROR(MINOR, E_NO_DEVICE, ("message handler not found in list!!!"));
+
+ LIST_Del(&p_IoMap->node);
+ XX_Free(p_IoMap);
+
+ return E_OK;
+}
+
+uint64_t SYS_PhysToVirt(uint64_t addr)
+{
+ t_IoMap *p_IoMap = FindIoMapByPhysAddr(addr);
+ if (p_IoMap)
+ {
+ /* This is optimization - put the latest in the list-head - like a cache */
+ if (mapsList.p_Next != &p_IoMap->node)
+ {
+ uint32_t intFlags = XX_DisableAllIntr();
+ LIST_DelAndInit(&p_IoMap->node);
+ LIST_Add(&p_IoMap->node, &mapsList);
+ XX_RestoreAllIntr(intFlags);
+ }
+ return (uint64_t)(addr - p_IoMap->physAddr + p_IoMap->virtAddr);
+ }
+ return PTR_TO_UINT(phys_to_virt((unsigned long)addr));
+}
+
+uint64_t SYS_VirtToPhys(uint64_t addr)
+{
+ t_IoMap *p_IoMap;
+
+ if (addr == 0)
+ return 0;
+
+ p_IoMap = FindIoMapByVirtAddr(addr);
+ if (p_IoMap)
+ return (uint64_t)(addr - p_IoMap->virtAddr + p_IoMap->physAddr);
+ return (uint64_t)virt_to_phys(UINT_TO_PTR(addr));
+}
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/Makefile b/drivers/net/ethernet/freescale/fman/src/wrapper/Makefile
new file mode 100644
index 0000000..22fe2e2
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/Makefile
@@ -0,0 +1,20 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+
+NCSW_FM_INC = $(srctree)/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc
+
+EXTRA_CFLAGS += -I$(NCSW_FM_INC)
+EXTRA_CFLAGS += -I$(NET_DPA)
+
+obj-y += fsl-ncsw-PFM.o
+obj-$(CONFIG_FSL_FMAN_TEST) += fman_test.o
+
+fsl-ncsw-PFM-objs := lnxwrp_fm.o lnxwrp_fm_port.o lnxwrp_ioctls_fm.o \
+ lnxwrp_sysfs.o lnxwrp_sysfs_fm.o lnxwrp_sysfs_fm_port.o \
+ lnxwrp_resources.o
+obj-$(CONFIG_COMPAT) += lnxwrp_ioctls_fm_compat.o
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/fman_test.c b/drivers/net/ethernet/freescale/fman/src/wrapper/fman_test.c
new file mode 100644
index 0000000..7d04f20
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/fman_test.c
@@ -0,0 +1,1665 @@
+/* Copyright (c) 2008-2011 Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ @File fman_test.c
+ @Authors Pistirica Sorin Andrei
+ @Description FM Linux test environment
+*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/of_platform.h>
+#include <linux/ip.h>
+#include <linux/compat.h>
+#include <linux/uaccess.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/fsl_qman.h>
+#include <linux/fsl_bman.h>
+
+/* private headers */
+#include "fm_ext.h"
+#include "lnxwrp_fsl_fman.h"
+#include "fm_port_ext.h"
+#if (DPAA_VERSION == 11)
+#include "../../Peripherals/FM/MAC/memac.h"
+#endif
+#include "fm_test_ioctls.h"
+#include "fsl_fman_test.h"
+
+#include "dpaa_eth.h"
+#include "dpaa_eth-common.h"
+
+#define FMT_FRM_WATERMARK 0xdeadbeefdeadbeeaLL
+
+struct fmt_frame_s {
+ ioc_fmt_buff_desc_t buff;
+ struct list_head list;
+};
+
+struct fmt_fqs_s {
+ struct qman_fq fq_base;
+ bool init;
+ struct fmt_port_s *fmt_port_priv;
+};
+
+struct fmt_port_pcd_s {
+ int num_queues;
+ struct fmt_fqs_s *fmt_pcd_fqs;
+ uint32_t fqid_base;
+};
+
+/* char dev structure: fm test port */
+struct fmt_port_s {
+ bool valid;
+ uint8_t id;
+ ioc_fmt_port_type port_type;
+ ioc_diag_mode diag;
+ bool compat_test_type;
+
+ /* fm ports */
+ /* ! for oh ports p_tx_fm_port_dev == p_rx_fm_port_dev &&
+ * p_tx_port == p_rx_port */
+ /* t_LnxWrpFmPortDev */
+ struct fm_port *p_tx_port;
+ /* t_LnxWrpFmPortDev->h_Dev: t_FmPort */
+ void *p_tx_fm_port_dev;
+ /* t_LnxWrpFmPortDev */
+ struct fm_port *p_rx_port;
+ /* t_LnxWrpFmPortDev->h_Dev: t_FmPort */
+ void *p_rx_fm_port_dev;
+
+ void *p_mac_dev;
+ uint64_t fm_phys_base_addr;
+
+ /* read/write queue manipulation */
+ spinlock_t rx_q_lock;
+ struct list_head rx_q;
+
+ /* tx queuee for injecting traffic */
+ int num_of_tx_fqs;
+ struct fmt_fqs_s p_tx_fqs[FMAN_TEST_MAX_TX_FQS];
+
+ /* pcd private queues manipulation */
+ struct fmt_port_pcd_s fmt_port_pcd;
+
+ /* debugging stuff */
+
+#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME)
+ atomic_t enqueue_to_qman_frm;
+ atomic_t enqueue_to_rxq;
+ atomic_t dequeue_from_rxq;
+ atomic_t not_enqueue_to_rxq_wrong_frm;
+#endif
+
+};
+
+/* The devices. */
+struct fmt_s {
+ int major;
+ struct fmt_port_s ports[IOC_FMT_MAX_NUM_OF_PORTS];
+ struct class *fmt_class;
+};
+
+/* fm test structure */
+static struct fmt_s fm_test;
+
+#if (DPAA_VERSION == 11)
+struct mac_priv_s {
+ t_Handle mac;
+};
+#endif
+
+#define DTSEC_BASE_ADDR 0x000e0000
+#define DTSEC_MEM_RANGE 0x00002000
+#define MAC_1G_MACCFG1 0x00000100
+#define MAC_1G_LOOP_MASK 0x00000100
+static int set_1gmac_loopback(
+ struct fmt_port_s *fmt_port,
+ bool en)
+{
+#if (DPAA_VERSION <= 10)
+ uint32_t dtsec_idx = fmt_port->id; /* dtsec for which port */
+ uint32_t dtsec_idx_off = dtsec_idx * DTSEC_MEM_RANGE;
+ phys_addr_t maccfg1_hw;
+ void *maccfg1_map;
+ uint32_t maccfg1_val;
+
+ /* compute the maccfg1 register address */
+ maccfg1_hw = fmt_port->fm_phys_base_addr +
+ (phys_addr_t)(DTSEC_BASE_ADDR +
+ dtsec_idx_off +
+ MAC_1G_MACCFG1);
+
+ /* map register */
+ maccfg1_map = ioremap(maccfg1_hw, sizeof(u32));
+
+ /* set register */
+ maccfg1_val = in_be32(maccfg1_map);
+ if (en)
+ maccfg1_val |= MAC_1G_LOOP_MASK;
+ else
+ maccfg1_val &= ~MAC_1G_LOOP_MASK;
+ out_be32(maccfg1_map, maccfg1_val);
+
+ /* unmap register */
+ iounmap(maccfg1_map);
+#else
+ struct mac_device *mac_dev;
+ struct mac_priv_s *priv;
+ t_Memac *p_memac;
+
+ if (!fmt_port)
+ return -EINVAL;
+
+ mac_dev = (struct mac_device *)fmt_port->p_mac_dev;
+
+ if (!mac_dev)
+ return -EINVAL;
+
+ priv = macdev_priv(mac_dev);
+
+ if (!priv)
+ return -EINVAL;
+
+ p_memac = priv->mac;
+
+ if (!p_memac)
+ return -EINVAL;
+
+ memac_set_loopback(p_memac->p_MemMap, en);
+#endif
+ return 0;
+}
+
+/* TODO: re-write this function */
+static int set_10gmac_int_loopback(
+ struct fmt_port_s *fmt_port,
+ bool en)
+{
+#ifndef FM_10G_MAC_NO_CTRL_LOOPBACK
+#define FM_10GMAC0_OFFSET 0x000f0000
+#define FM_10GMAC_CMD_CONF_CTRL_OFFSET 0x8
+#define CMD_CFG_LOOPBACK_EN 0x00000400
+
+ uint64_t base_addr, reg_addr;
+ uint32_t tmp_val;
+
+ base_addr = fmt_port->fm_phys_base_addr + (FM_10GMAC0_OFFSET +
+ ((fmt_port->id-FM_MAX_NUM_OF_1G_RX_PORTS)*0x2000));
+
+ base_addr = PTR_TO_UINT(ioremap(base_addr, 0x1000));
+
+ reg_addr = base_addr + FM_10GMAC_CMD_CONF_CTRL_OFFSET;
+ tmp_val = GET_UINT32(*((uint32_t *)UINT_TO_PTR(reg_addr)));
+ if (en)
+ tmp_val |= CMD_CFG_LOOPBACK_EN;
+ else
+ tmp_val &= ~CMD_CFG_LOOPBACK_EN;
+ WRITE_UINT32(*((uint32_t *)UINT_TO_PTR(reg_addr)), tmp_val);
+
+ iounmap(UINT_TO_PTR(base_addr));
+
+ return 0;
+#else
+ _fmt_err("TGEC don't have internal-loopback.\n");
+ return -EPERM;
+#endif
+}
+
+static int set_mac_int_loopback(struct fmt_port_s *fmt_port, bool en)
+{
+ int _err = 0;
+
+ switch (fmt_port->port_type) {
+
+ case e_IOC_FMT_PORT_T_RXTX:
+ /* 1G port */
+ if (fmt_port->id < FM_MAX_NUM_OF_1G_RX_PORTS)
+ _err = set_1gmac_loopback(fmt_port, en);
+ /* 10g port */
+ else if ((fmt_port->id >= FM_MAX_NUM_OF_1G_RX_PORTS) &&
+ (fmt_port->id < FM_MAX_NUM_OF_1G_RX_PORTS +
+ FM_MAX_NUM_OF_10G_RX_PORTS)) {
+
+ _err = set_10gmac_int_loopback(fmt_port, en);
+ } else
+ _err = -EINVAL;
+ break;
+ /* op port does not have MAC (loopback mode) */
+ case e_IOC_FMT_PORT_T_OP:
+
+ _err = 0;
+ break;
+ default:
+
+ _err = -EPERM;
+ break;
+ }
+
+ return _err;
+}
+
+static void enqueue_fmt_frame(
+ struct fmt_port_s *fmt_port,
+ struct fmt_frame_s *p_fmt_frame)
+{
+ spinlock_t *rx_q_lock = NULL;
+
+ rx_q_lock = &fmt_port->rx_q_lock;
+
+ spin_lock(rx_q_lock);
+ list_add_tail(&p_fmt_frame->list, &fmt_port->rx_q);
+ spin_unlock(rx_q_lock);
+
+#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME)
+ atomic_inc(&fmt_port->enqueue_to_rxq);
+#endif
+}
+
+static struct fmt_frame_s *dequeue_fmt_frame(
+ struct fmt_port_s *fmt_port)
+{
+ struct fmt_frame_s *p_fmt_frame = NULL;
+ spinlock_t *rx_q_lock = NULL;
+
+ rx_q_lock = &fmt_port->rx_q_lock;
+
+ spin_lock(rx_q_lock);
+
+#define list_last_entry(ptr, type, member) list_entry((ptr)->prev, type, member)
+
+ if (!list_empty(&fmt_port->rx_q)) {
+ p_fmt_frame = list_last_entry(&fmt_port->rx_q,
+ struct fmt_frame_s,
+ list);
+ list_del(&p_fmt_frame->list);
+
+#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME)
+ atomic_inc(&fmt_port->dequeue_from_rxq);
+#endif
+ }
+
+ spin_unlock(rx_q_lock);
+
+ return p_fmt_frame;
+}
+
+/* eth-dev -to- fmt port association */
+struct fmt_port_s *match_dpa_to_fmt_port(
+ struct dpa_priv_s *dpa_priv) {
+ struct mac_device *mac_dev = dpa_priv->mac_dev;
+ struct fm_port *fm_port = (struct fm_port *) mac_dev;
+ struct fmt_port_s *fmt_port = NULL;
+ int i;
+
+ _fmt_dbgr("calling...\n");
+
+ /* find the FM-test-port object */
+ for (i = 0; i < IOC_FMT_MAX_NUM_OF_PORTS; i++)
+ if ((fm_test.ports[i].p_mac_dev &&
+ mac_dev == fm_test.ports[i].p_mac_dev) ||
+ fm_port == fm_test.ports[i].p_tx_port) {
+
+ fmt_port = &fm_test.ports[i];
+ break;
+ }
+
+ _fmt_dbgr("called\n");
+ return fmt_port;
+}
+
+void dump_frame(
+ uint8_t *buffer,
+ uint32_t size)
+{
+#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME)
+ unsigned int i;
+
+ for (i = 0; i < size; i++) {
+ if (i%16 == 0)
+ printk(KERN_DEBUG "\n");
+ printk(KERN_DEBUG "%2x ", *(buffer+i));
+ }
+#endif
+ return;
+}
+
+bool test_and_steal_frame(struct fmt_port_s *fmt_port,
+ uint32_t fqid,
+ uint8_t *buffer,
+ uint32_t size)
+{
+ struct fmt_frame_s *p_fmt_frame = NULL;
+ bool test_and_steal_frame_frame;
+ uint32_t data_offset;
+ uint32_t i;
+
+ _fmt_dbgr("calling...\n");
+
+ if (!fmt_port || !fmt_port->p_rx_fm_port_dev)
+ return false;
+
+ /* check watermark */
+ test_and_steal_frame_frame = false;
+ for (i = 0; i < size; i++) {
+ uint64_t temp = *((uint64_t *)(buffer + i));
+
+ if (temp == (uint64_t) FMT_FRM_WATERMARK) {
+ _fmt_dbgr("watermark found!\n");
+ test_and_steal_frame_frame = true;
+ break;
+ }
+ }
+
+ if (!test_and_steal_frame_frame) {
+#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME)
+ atomic_inc(&fmt_port->not_enqueue_to_rxq_wrong_frm);
+#endif
+ _fmt_dbgr("NOT watermark found!\n");
+ return false;
+ }
+
+ /* do not enqueue the tx conf/err frames */
+ if ((fqid == FMT_TX_CONF_Q) || (fqid == FMT_TX_ERR_Q))
+ goto _test_and_steal_frame_return_true;
+
+ _fmt_dbgr("on port %d got FMUC frame\n", fmt_port->id);
+ data_offset = FM_PORT_GetBufferDataOffset(
+ fmt_port->p_rx_fm_port_dev);
+
+ p_fmt_frame = kmalloc(sizeof(struct fmt_frame_s), GFP_KERNEL);
+
+ /* dump frame... no more space left on device */
+ if (p_fmt_frame == NULL) {
+ _fmt_err("no space left on device!\n");
+ goto _test_and_steal_frame_return_true;
+ }
+
+ memset(p_fmt_frame, 0, sizeof(struct fmt_frame_s));
+ p_fmt_frame->buff.p_data = kmalloc(size * sizeof(uint8_t), GFP_KERNEL);
+
+ /* No more space left on device*/
+ if (p_fmt_frame->buff.p_data == NULL) {
+ _fmt_err("no space left on device!\n");
+ kfree(p_fmt_frame);
+ goto _test_and_steal_frame_return_true;
+ }
+
+ p_fmt_frame->buff.size = size-data_offset;
+ p_fmt_frame->buff.qid = fqid;
+
+ memcpy(p_fmt_frame->buff.p_data,
+ (uint8_t *)PTR_MOVE(buffer, data_offset),
+ p_fmt_frame->buff.size);
+
+ memcpy(p_fmt_frame->buff.buff_context.fm_prs_res,
+ FM_PORT_GetBufferPrsResult(fmt_port->p_rx_fm_port_dev,
+ (char *)buffer),
+ 32);
+
+ /* enqueue frame - this frame will go to us */
+ enqueue_fmt_frame(fmt_port, p_fmt_frame);
+
+_test_and_steal_frame_return_true:
+ return true;
+}
+
+static int fmt_fq_release(const struct qm_fd *fd)
+{
+ struct dpa_bp *_dpa_bp;
+ struct bm_buffer _bmb;
+
+ if (fd->format == qm_fd_contig) {
+ _dpa_bp = dpa_bpid2pool(fd->bpid);
+ BUG_ON(IS_ERR(_dpa_bp));
+
+ _bmb.hi = fd->addr_hi;
+ _bmb.lo = fd->addr_lo;
+
+ while (bman_release(_dpa_bp->pool, &_bmb, 1, 0))
+ cpu_relax();
+
+ } else {
+ _fmt_err("frame not supported !\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* sync it w/ dpaa_eth.c: DPA_BP_HEAD */
+#define DPA_BP_HEADROOM (DPA_TX_PRIV_DATA_SIZE + \
+ fm_get_rx_extra_headroom() + \
+ DPA_PARSE_RESULTS_SIZE + \
+ DPA_HASH_RESULTS_SIZE)
+#define MAC_HEADER_LENGTH 14
+#define L2_AND_HEADROOM_OFF ((DPA_BP_HEADROOM) + (MAC_HEADER_LENGTH))
+
+/* dpa ingress hooks definition */
+enum dpaa_eth_hook_result fmt_rx_default_hook(
+ struct sk_buff *skb,
+ struct net_device *net_dev,
+ u32 fqid)
+{
+ struct dpa_priv_s *dpa_priv = NULL;
+ struct fmt_port_s *fmt_port = NULL;
+ uint8_t *buffer;
+ uint32_t buffer_len;
+
+ _fmt_dbgr("calling...\n");
+
+ dpa_priv = netdev_priv(net_dev);
+ fmt_port = match_dpa_to_fmt_port(dpa_priv);
+
+ /* conversion from skb to fd:
+ * skb cames processed for L3, so we need to go back for
+ * layer 2 offset */
+ buffer = (uint8_t *)(skb->data - ((int)L2_AND_HEADROOM_OFF));
+ buffer_len = skb->len + ((int)L2_AND_HEADROOM_OFF);
+
+ /* if is not out frame let dpa to handle it */
+ if (test_and_steal_frame(fmt_port,
+ FMT_RX_DFLT_Q,
+ buffer,
+ buffer_len))
+ goto _fmt_rx_default_hook_stolen;
+
+ _fmt_dbgr("called:DPAA_ETH_CONTINUE.\n");
+ return DPAA_ETH_CONTINUE;
+
+_fmt_rx_default_hook_stolen:
+ dev_kfree_skb(skb);
+
+ _fmt_dbgr("called:DPAA_ETH_STOLEN.\n");
+ return DPAA_ETH_STOLEN;
+}
+
+enum dpaa_eth_hook_result fmt_rx_error_hook(
+ struct net_device *net_dev,
+ const struct qm_fd *fd,
+ u32 fqid)
+{
+ struct dpa_priv_s *dpa_priv = NULL;
+ struct dpa_bp *dpa_bp = NULL;
+ struct fmt_port_s *fmt_port = NULL;
+ void *fd_virt_addr = NULL;
+ dma_addr_t addr = qm_fd_addr(fd);
+
+ _fmt_dbgr("calling...\n");
+
+ dpa_priv = netdev_priv(net_dev);
+ fmt_port = match_dpa_to_fmt_port(dpa_priv);
+
+ /* dpaa doesn't do this... we have to do it here */
+ dpa_bp = dpa_bpid2pool(fd->bpid);
+ dma_unmap_single(dpa_bp->dev, addr, dpa_bp->size, DMA_BIDIRECTIONAL);
+
+ fd_virt_addr = phys_to_virt(addr);
+ /* if is not out frame let dpa to handle it */
+ if (test_and_steal_frame(fmt_port,
+ FMT_RX_ERR_Q,
+ fd_virt_addr,
+ fd->length20 + fd->offset)) {
+ goto _fmt_rx_error_hook_stolen;
+ }
+
+ _fmt_dbgr("called:DPAA_ETH_CONTINUE.\n");
+ return DPAA_ETH_CONTINUE;
+
+_fmt_rx_error_hook_stolen:
+ /* the frame data doesn't matter,
+ * so, no mapping is needed */
+ fmt_fq_release(fd);
+
+ _fmt_dbgr("called:DPAA_ETH_STOLEN.\n");
+ return DPAA_ETH_STOLEN;
+}
+
+enum dpaa_eth_hook_result fmt_tx_confirm_hook(
+ struct net_device *net_dev,
+ const struct qm_fd *fd,
+ u32 fqid)
+{
+ struct dpa_priv_s *dpa_priv = NULL;
+ struct fmt_port_s *fmt_port = NULL;
+ dma_addr_t addr = qm_fd_addr(fd);
+ void *fd_virt_addr = NULL;
+ uint32_t fd_len = 0;
+
+ _fmt_dbgr("calling...\n");
+
+ dpa_priv = netdev_priv(net_dev);
+ fmt_port = match_dpa_to_fmt_port(dpa_priv);
+
+ fd_virt_addr = phys_to_virt(addr);
+ fd_len = fd->length20 + fd->offset;
+
+ if (fd_len > fm_get_max_frm()) {
+ _fmt_err("tx confirm bad frame size: %u!\n", fd_len);
+ goto _fmt_tx_confirm_hook_continue;
+ }
+
+ if (test_and_steal_frame(fmt_port,
+ FMT_TX_CONF_Q,
+ fd_virt_addr,
+ fd_len))
+ goto _fmt_tx_confirm_hook_stolen;
+
+_fmt_tx_confirm_hook_continue:
+ _fmt_dbgr("called:DPAA_ETH_CONTINUE.\n");
+ return DPAA_ETH_CONTINUE;
+
+_fmt_tx_confirm_hook_stolen:
+ kfree(fd_virt_addr);
+
+ _fmt_dbgr("called:DPAA_ETH_STOLEN.\n");
+ return DPAA_ETH_STOLEN;
+}
+
+enum dpaa_eth_hook_result fmt_tx_confirm_error_hook(
+ struct net_device *net_dev,
+ const struct qm_fd *fd,
+ u32 fqid)
+{
+ struct dpa_priv_s *dpa_priv = NULL;
+ struct fmt_port_s *fmt_port = NULL;
+ dma_addr_t addr = qm_fd_addr(fd);
+ void *fd_virt_addr = NULL;
+ uint32_t fd_len = 0;
+
+ _fmt_dbgr("calling...\n");
+
+ dpa_priv = netdev_priv(net_dev);
+ fmt_port = match_dpa_to_fmt_port(dpa_priv);
+
+ fd_virt_addr = phys_to_virt(addr);
+ fd_len = fd->length20 + fd->offset;
+
+ if (fd_len > fm_get_max_frm()) {
+ _fmt_err("tx confirm err bad frame size: %u !\n", fd_len);
+ goto _priv_ingress_tx_err_continue;
+ }
+
+ if (test_and_steal_frame(fmt_port, FMT_TX_ERR_Q, fd_virt_addr, fd_len))
+ goto _priv_ingress_tx_err_stolen;
+
+_priv_ingress_tx_err_continue:
+ _fmt_dbgr("called:DPAA_ETH_CONTINUE.\n");
+ return DPAA_ETH_CONTINUE;
+
+_priv_ingress_tx_err_stolen:
+ kfree(fd_virt_addr);
+
+ _fmt_dbgr("called:DPAA_ETH_STOLEN.\n");
+ return DPAA_ETH_STOLEN;
+}
+
+/* egress callbacks definition */
+enum qman_cb_dqrr_result fmt_egress_dqrr(
+ struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry *dqrr)
+{
+ /* this callback should never be called */
+ BUG();
+ return qman_cb_dqrr_consume;
+}
+
+static void fmt_egress_error_dqrr(
+ struct qman_portal *p,
+ struct qman_fq *fq,
+ const struct qm_mr_entry *msg)
+{
+ uint8_t *fd_virt_addr = NULL;
+
+ /* tx failure, on the ern callback - release buffer */
+ fd_virt_addr = (uint8_t *)phys_to_virt(qm_fd_addr(&msg->ern.fd));
+ kfree(fd_virt_addr);
+
+ return;
+}
+
+static const struct qman_fq fmt_egress_fq = {
+ .cb = { .dqrr = fmt_egress_dqrr,
+ .ern = fmt_egress_error_dqrr,
+ .fqs = NULL}
+};
+
+int fmt_fq_alloc(
+ struct fmt_fqs_s *fmt_fqs,
+ const struct qman_fq *qman_fq,
+ uint32_t fqid, uint32_t flags,
+ uint16_t channel, uint8_t wq)
+{
+ int _errno = 0;
+
+ _fmt_dbg("calling...\n");
+
+ fmt_fqs->fq_base = *qman_fq;
+
+ if (fqid == 0) {
+ flags |= QMAN_FQ_FLAG_DYNAMIC_FQID;
+ flags &= ~QMAN_FQ_FLAG_NO_MODIFY;
+ } else
+ flags &= ~QMAN_FQ_FLAG_DYNAMIC_FQID;
+
+ fmt_fqs->init = !(flags & QMAN_FQ_FLAG_NO_MODIFY);
+
+ _errno = qman_create_fq(fqid, flags, &fmt_fqs->fq_base);
+ if (_errno < 0) {
+ _fmt_err("frame queues create failed.\n");
+ return -EINVAL;
+ }
+
+ if (fmt_fqs->init) {
+ struct qm_mcc_initfq initfq;
+
+ initfq.we_mask = QM_INITFQ_WE_DESTWQ;
+ initfq.fqd.dest.channel = channel;
+ initfq.fqd.dest.wq = wq;
+
+ _errno = qman_init_fq(&fmt_fqs->fq_base,
+ QMAN_INITFQ_FLAG_SCHED,
+ &initfq);
+ if (_errno < 0) {
+ _fmt_err("frame queues init erorr.\n");
+ qman_destroy_fq(&fmt_fqs->fq_base, 0);
+ return -EINVAL;
+ }
+ }
+
+ _fmt_dbg("called.\n");
+ return 0;
+}
+
+static int fmt_fq_free(struct fmt_fqs_s *fmt_fq)
+{
+ int _err = 0;
+
+ _fmt_dbg("calling...\n");
+
+ if (fmt_fq->init) {
+ _err = qman_retire_fq(&fmt_fq->fq_base, NULL);
+ if (unlikely(_err < 0))
+ _fmt_err("qman_retire_fq(%u) = %d\n",
+ qman_fq_fqid(&fmt_fq->fq_base), _err);
+
+ _err = qman_oos_fq(&fmt_fq->fq_base);
+ if (unlikely(_err < 0))
+ _fmt_err("qman_oos_fq(%u) = %d\n",
+ qman_fq_fqid(&fmt_fq->fq_base), _err);
+ }
+
+ qman_destroy_fq(&fmt_fq->fq_base, 0);
+
+ _fmt_dbg("called.\n");
+ return _err;
+}
+
+/* private pcd dqrr calbacks */
+static enum qman_cb_dqrr_result fmt_pcd_dqrr(
+ struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry *dq)
+{
+ struct dpa_bp *dpa_bp = NULL;
+ dma_addr_t addr = qm_fd_addr(&dq->fd);
+ uint8_t *fd_virt_addr = NULL;
+ struct fmt_port_s *fmt_port;
+ struct fmt_port_pcd_s *fmt_port_pcd;
+ uint32_t relative_fqid = 0;
+ uint32_t fd_len = 0;
+
+ _fmt_dbgr("calling...\n");
+
+ /* upcast - from pcd_alloc_fq */
+ fmt_port = ((struct fmt_fqs_s *)fq)->fmt_port_priv;
+ if (!fmt_port) {
+ _fmt_err(" wrong fmt port -to- fq match.\n");
+ goto _fmt_pcd_dqrr_return;
+ }
+ fmt_port_pcd = &fmt_port->fmt_port_pcd;
+
+ relative_fqid = dq->fqid - fmt_port_pcd->fqid_base;
+ _fmt_dbgr("pcd dqrr got frame on relative fq:%u@base:%u\n",
+ relative_fqid, fmt_port_pcd->fqid_base);
+
+ fd_len = dq->fd.length20 + dq->fd.offset;
+
+ if (fd_len > fm_get_max_frm()) {
+ _fmt_err("pcd dqrr wrong frame size: %u (%u:%u)!\n",
+ fd_len, dq->fd.length20, dq->fd.offset);
+ goto _fmt_pcd_dqrr_return;
+ }
+
+ dpa_bp = dpa_bpid2pool(dq->fd.bpid);
+ dma_unmap_single(dpa_bp->dev, addr, dpa_bp->size, DMA_BIDIRECTIONAL);
+
+ fd_virt_addr = phys_to_virt(addr);
+ if (!test_and_steal_frame(fmt_port, relative_fqid, fd_virt_addr,
+ fd_len)) {
+
+#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME)
+ atomic_inc(&fmt_port->not_enqueue_to_rxq_wrong_frm);
+#endif
+ _fmt_wrn("pcd dqrr unrecognized frame@fqid: %u,"
+ " frame len: %u (dropped).\n",
+ dq->fqid, dq->fd.length20);
+ dump_frame(fd_virt_addr, fd_len);
+ }
+
+_fmt_pcd_dqrr_return:
+ /* no need to map again here */
+ fmt_fq_release(&dq->fd);
+
+ _fmt_dbgr("calle.\n");
+ return qman_cb_dqrr_consume;
+}
+
+static void fmt_pcd_err_dqrr(
+ struct qman_portal *qm,
+ struct qman_fq *fq,
+ const struct qm_mr_entry *msg)
+{
+ _fmt_err("this callback should never be called.\n");
+ BUG();
+ return;
+}
+
+static void fmt_pcd_fqs_dqrr(
+ struct qman_portal *qm,
+ struct qman_fq *fq,
+ const struct qm_mr_entry *msg)
+{
+ _fmt_dbg(" fq state(0x%x)@fqid(%u.\n", msg->fq.fqs, msg->fq.fqid);
+ return;
+}
+
+/* private pcd queue template */
+static const struct qman_fq pcd_fq = {
+ .cb = { .dqrr = fmt_pcd_dqrr,
+ .ern = fmt_pcd_err_dqrr,
+ .fqs = fmt_pcd_fqs_dqrr}
+};
+
+/* defined as weak in dpaa driver. */
+/* ! parameters come from IOCTL call - US */
+int dpa_alloc_pcd_fqids(
+ struct device *dev,
+ uint32_t num, uint8_t alignment,
+ uint32_t *base_fqid)
+{
+ int _err = 0, i;
+ struct net_device *net_dev = NULL;
+ struct dpa_priv_s *dpa_priv = NULL;
+ struct fmt_port_pcd_s *fmt_port_pcd = NULL;
+ struct fmt_fqs_s *fmt_fqs = NULL;
+ struct fmt_port_s *fmt_port = NULL;
+ int num_allocated = 0;
+
+ _fmt_dbg("calling...\n");
+
+ net_dev = (typeof(net_dev))dev_get_drvdata(dev);
+ dpa_priv = (typeof(dpa_priv))netdev_priv(net_dev);
+
+ if (!netif_msg_probe(dpa_priv)) {
+ _fmt_err("dpa not probe.\n");
+ _err = -ENODEV;
+ goto _pcd_alloc_fqs_err;
+ }
+
+ fmt_port = match_dpa_to_fmt_port(dpa_priv);
+ if (!fmt_port) {
+ _fmt_err("fmt port not found.");
+ _err = -EINVAL;
+ goto _pcd_alloc_fqs_err;
+ }
+
+ fmt_port_pcd = &fmt_port->fmt_port_pcd;
+
+ num_allocated = qman_alloc_fqid_range(base_fqid, num, alignment, 0);
+
+ if ((num_allocated <= 0) ||
+ (num_allocated < num) ||
+ (alignment && (*base_fqid) % alignment)) {
+ *base_fqid = 0;
+ _fmt_err("Failed to alloc pcd fqs rang.\n");
+ _err = -EINVAL;
+ goto _pcd_alloc_fqs_err;
+ }
+
+ _fmt_dbg("wanted %d fqs(align %d), got %d fqids@%u.\n",
+ num, alignment, num_allocated, *base_fqid);
+
+ /* alloc pcd queues */
+ fmt_port_pcd->fmt_pcd_fqs = kmalloc(num_allocated *
+ sizeof(struct fmt_fqs_s),
+ GFP_KERNEL);
+ fmt_port_pcd->num_queues = num_allocated;
+ fmt_port_pcd->fqid_base = *base_fqid;
+ fmt_fqs = fmt_port_pcd->fmt_pcd_fqs;
+
+ /* alloc the pcd queues */
+ for (i = 0; i < num_allocated; i++, fmt_fqs++) {
+ _err = fmt_fq_alloc(
+ fmt_fqs,
+ &pcd_fq,
+ (*base_fqid) + i, QMAN_FQ_FLAG_NO_ENQUEUE,
+ dpa_priv->channel, 7);
+
+ if (_err < 0)
+ goto _pcd_alloc_fqs_err;
+
+ /* upcast to identify from where the frames came from */
+ fmt_fqs->fmt_port_priv = fmt_port;
+ }
+
+ _fmt_dbg("called.\n");
+ return _err;
+_pcd_alloc_fqs_err:
+ if (num_allocated > 0)
+ qman_release_fqid_range(*base_fqid, num_allocated);
+ /*TODO: free fmt_pcd_fqs if are any */
+
+ _fmt_dbg("called(_err:%d).\n", _err);
+ return _err;
+}
+
+/* defined as weak in dpaa driver. */
+int dpa_free_pcd_fqids(
+ struct device *dev,
+ uint32_t base_fqid)
+{
+
+ int _err = 0, i;
+ struct net_device *net_dev = NULL;
+ struct dpa_priv_s *dpa_priv = NULL;
+ struct fmt_port_pcd_s *fmt_port_pcd = NULL;
+ struct fmt_fqs_s *fmt_fqs = NULL;
+ struct fmt_port_s *fmt_port = NULL;
+ int num_allocated = 0;
+
+ _fmt_dbg("calling...\n");
+
+ net_dev = (typeof(net_dev))dev_get_drvdata(dev);
+ dpa_priv = (typeof(dpa_priv))netdev_priv(net_dev);
+
+ if (!netif_msg_probe(dpa_priv)) {
+ _fmt_err("dpa not probe.\n");
+ _err = -ENODEV;
+ goto _pcd_free_fqs_err;
+ }
+
+ fmt_port = match_dpa_to_fmt_port(dpa_priv);
+ if (!fmt_port) {
+ _fmt_err("fmt port not found.");
+ _err = -EINVAL;
+ goto _pcd_free_fqs_err;
+ }
+
+ fmt_port_pcd = &fmt_port->fmt_port_pcd;
+ num_allocated = fmt_port_pcd->num_queues;
+ fmt_fqs = fmt_port_pcd->fmt_pcd_fqs;
+
+ for (i = 0; i < num_allocated; i++, fmt_fqs++)
+ fmt_fq_free(fmt_fqs);
+
+ qman_release_fqid_range(base_fqid,num_allocated);
+
+ kfree(fmt_port_pcd->fmt_pcd_fqs);
+ memset(fmt_port_pcd, 0, sizeof(*fmt_port_pcd));
+
+ /* debugging stuff */
+#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME)
+ _fmt_dbg(" portid: %u.\n", fmt_port->id);
+ _fmt_dbg(" frames enqueue to qman: %u.\n",
+ atomic_read(&fmt_port->enqueue_to_qman_frm));
+ _fmt_dbg(" frames enqueue to rxq: %u.\n",
+ atomic_read(&fmt_port->enqueue_to_rxq));
+ _fmt_dbg(" frames dequeue from rxq: %u.\n",
+ atomic_read(&fmt_port->dequeue_from_rxq));
+ _fmt_dbg(" frames not enqueue to rxq - wrong frm: %u.\n",
+ atomic_read(&fmt_port->not_enqueue_to_rxq_wrong_frm));
+ atomic_set(&fmt_port->enqueue_to_qman_frm, 0);
+ atomic_set(&fmt_port->enqueue_to_rxq, 0);
+ atomic_set(&fmt_port->dequeue_from_rxq, 0);
+ atomic_set(&fmt_port->not_enqueue_to_rxq_wrong_frm, 0);
+#endif
+ return 0;
+
+_pcd_free_fqs_err:
+ return _err;
+}
+
+static int fmt_port_init(
+ struct fmt_port_s *fmt_port,
+ ioc_fmt_port_param_t *p_Params)
+{
+ struct device_node *fm_node, *fm_port_node;
+ const uint32_t *uint32_prop;
+ int _errno = 0, lenp = 0, i;
+ static struct of_device_id fm_node_of_match[] = {
+ { .compatible = "fsl,fman", },
+ { /* end of list */ },
+ };
+
+ _fmt_dbg("calling...\n");
+
+ /* init send/receive tu US list */
+ INIT_LIST_HEAD(&fmt_port->rx_q);
+
+ /* check parameters */
+ if (p_Params->num_tx_queues > FMAN_TEST_MAX_TX_FQS ||
+ p_Params->fm_port_id > IOC_FMT_MAX_NUM_OF_PORTS) {
+ _fmt_dbg("wrong test parameters.\n");
+ return -EINVAL;
+ }
+
+ /* set port parameters */
+ fmt_port->num_of_tx_fqs = p_Params->num_tx_queues;
+ fmt_port->id = p_Params->fm_port_id;
+ fmt_port->port_type = p_Params->fm_port_type;
+ fmt_port->diag = e_IOC_DIAG_MODE_NONE;
+
+ /* init debugging stuff */
+#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME)
+ atomic_set(&fmt_port->enqueue_to_qman_frm, 0);
+ atomic_set(&fmt_port->enqueue_to_rxq, 0);
+ atomic_set(&fmt_port->dequeue_from_rxq, 0);
+ atomic_set(&fmt_port->not_enqueue_to_rxq_wrong_frm, 0);
+#endif
+
+ /* TODO: This should be done at probe time not at runtime
+ * very ugly function */
+ /* fill fmt port properties from dts */
+ for_each_matching_node(fm_node, fm_node_of_match) {
+
+ uint32_prop = (uint32_t *)of_get_property(fm_node,
+ "cell-index", &lenp);
+ if (unlikely(uint32_prop == NULL)) {
+ _fmt_wrn("of_get_property(%s, cell-index) invalid",
+ fm_node->full_name);
+ return -EINVAL;
+ }
+ if (WARN_ON(lenp != sizeof(uint32_t))) {
+ _fmt_wrn("of_get_property(%s, cell-index) invalid",
+ fm_node->full_name);
+ return -EINVAL;
+ }
+
+ if (*uint32_prop == p_Params->fm_id) {
+ struct resource res;
+
+ /* Get the FM address */
+ _errno = of_address_to_resource(fm_node, 0, &res);
+ if (unlikely(_errno < 0)) {
+ _fmt_wrn("of_address_to_resource() = %u.\n", _errno);
+ return -EINVAL;
+ }
+
+ fmt_port->fm_phys_base_addr = res.start;
+
+ for_each_child_of_node(fm_node, fm_port_node) {
+ struct platform_device *of_dev;
+
+ if (!of_device_is_available(fm_port_node))
+ continue;
+
+ uint32_prop = (uint32_t *)of_get_property(
+ fm_port_node,
+ "cell-index",
+ &lenp);
+ if (uint32_prop == NULL)
+ continue;
+
+ if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-port-oh") &&
+ (fmt_port->port_type == e_IOC_FMT_PORT_T_OP)) {
+
+ if (*uint32_prop == fmt_port->id) {
+ of_dev = of_find_device_by_node(fm_port_node);
+ if (unlikely(of_dev == NULL)) {
+ _fmt_wrn("fm id invalid\n");
+ return -EINVAL;
+ }
+
+ fmt_port->p_tx_port =
+ fm_port_bind(&of_dev->dev);
+ fmt_port->p_tx_fm_port_dev =
+ (void *)fm_port_get_handle(
+ fmt_port->p_tx_port);
+ fmt_port->p_rx_port =
+ fmt_port->p_tx_port;
+ fmt_port->p_rx_fm_port_dev =
+ fmt_port->p_tx_fm_port_dev;
+ fmt_port->p_mac_dev = NULL;
+ break;
+ }
+ } else if ((*uint32_prop == fmt_port->id) &&
+ fmt_port->port_type == e_IOC_FMT_PORT_T_RXTX) {
+
+ of_dev = of_find_device_by_node(fm_port_node);
+ if (unlikely(of_dev == NULL)) {
+ _fmt_wrn("dtb fm id invalid value");
+ return -EINVAL;
+ }
+
+ if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-port-1g-tx")) {
+ fmt_port->p_tx_port =
+ fm_port_bind(&of_dev->dev);
+ fmt_port->p_tx_fm_port_dev = (void *)
+ fm_port_get_handle(
+ fmt_port->p_tx_port);
+ } else if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-port-1g-rx")) {
+ fmt_port->p_rx_port =
+ fm_port_bind(&of_dev->dev);
+ fmt_port->p_rx_fm_port_dev = (void *)
+ fm_port_get_handle(
+ fmt_port->p_rx_port);
+ } else if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-1g-mac") ||
+ of_device_is_compatible(fm_port_node,
+ "fsl,fman-memac"))
+ fmt_port->p_mac_dev =
+ (typeof(fmt_port->p_mac_dev))
+ dev_get_drvdata(&of_dev->dev);
+ else
+ continue;
+
+ if (fmt_port->p_tx_fm_port_dev &&
+ fmt_port->p_rx_fm_port_dev && fmt_port->p_mac_dev)
+ break;
+ } else if (((*uint32_prop + FM_MAX_NUM_OF_1G_RX_PORTS) ==
+ fmt_port->id) &&
+ fmt_port->port_type == e_IOC_FMT_PORT_T_RXTX) {
+
+ of_dev = of_find_device_by_node(fm_port_node);
+ if (unlikely(of_dev == NULL)) {
+ _fmt_wrn("dtb fm id invalid value\n");
+ return -EINVAL;
+ }
+
+ if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-port-10g-tx")) {
+ fmt_port->p_tx_port =
+ fm_port_bind(&of_dev->dev);
+ fmt_port->p_tx_fm_port_dev = (void *)
+ fm_port_get_handle(
+ fmt_port->p_tx_port);
+ } else if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-port-10g-rx")) {
+ fmt_port->p_rx_port =
+ fm_port_bind(&of_dev->dev);
+ fmt_port->p_rx_fm_port_dev = (void *)
+ fm_port_get_handle(
+ fmt_port->p_rx_port);
+ } else if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-10g-mac") ||
+ of_device_is_compatible(fm_port_node,
+ "fsl,fman-memac"))
+ fmt_port->p_mac_dev =
+ (typeof(fmt_port->p_mac_dev))
+ dev_get_drvdata(&of_dev->dev);
+ else
+ continue;
+
+ if (fmt_port->p_tx_fm_port_dev &&
+ fmt_port->p_rx_fm_port_dev && fmt_port->p_mac_dev)
+ break;
+ }
+ } /* for_each_child */
+ }
+ } /* for each matching node */
+
+ if (fmt_port->p_tx_fm_port_dev == 0 ||
+ fmt_port->p_rx_fm_port_dev == 0) {
+
+ _fmt_err("bad fm port pointers.\n");
+ return -EINVAL;
+ }
+
+ _fmt_dbg("alloc %u tx queues.\n", fmt_port->num_of_tx_fqs);
+
+ /* init fman test egress dynamic frame queues */
+ for (i = 0; i < fmt_port->num_of_tx_fqs; i++) {
+ int _errno;
+ _errno = fmt_fq_alloc(
+ &fmt_port->p_tx_fqs[i],
+ &fmt_egress_fq,
+ 0,
+ QMAN_FQ_FLAG_TO_DCPORTAL,
+ fm_get_tx_port_channel(fmt_port->p_tx_port),
+ i);
+
+ if (_errno < 0) {
+ _fmt_err("tx queues allocation failed.\n");
+ /* TODO: memory leak here if 1 queue is allocated and
+ * next queues are failing ... */
+ return -EINVAL;
+ }
+ }
+
+ /* port is valid and ready to use. */
+ fmt_port->valid = TRUE;
+
+ _fmt_dbg("called.\n");
+ return 0;
+}
+
+/* fm test chardev functions */
+static int fmt_open(struct inode *inode, struct file *file)
+{
+ unsigned int minor = iminor(inode);
+
+ _fmt_dbg("calling...\n");
+
+ if (file->private_data != NULL)
+ return 0;
+
+ /* The minor represent the port number.
+ * Set the port structure accordingly, thus all the operations
+ * will be done on this port. */
+ if ((minor >= DEV_FM_TEST_PORTS_MINOR_BASE) &&
+ (minor < DEV_FM_TEST_MAX_MINORS))
+ file->private_data = &fm_test.ports[minor];
+ else
+ return -ENXIO;
+
+ _fmt_dbg("called.\n");
+ return 0;
+}
+
+static int fmt_close(struct inode *inode, struct file *file)
+{
+ struct fmt_port_s *fmt_port = NULL;
+ struct fmt_frame_s *fmt_frame = NULL;
+
+ int err = 0;
+
+ _fmt_dbg("calling...\n");
+
+ fmt_port = file->private_data;
+ if (!fmt_port)
+ return -ENODEV;
+
+ /* Close the current test port by invalidating it. */
+ fmt_port->valid = FALSE;
+
+ /* clean the fmt port queue */
+ while ((fmt_frame = dequeue_fmt_frame(fmt_port)) != NULL) {
+ if (fmt_frame && fmt_frame->buff.p_data){
+ kfree(fmt_frame->buff.p_data);
+ kfree(fmt_frame);
+ }
+ }
+
+ /* !!! the qman queues are cleaning from fm_ioctl...
+ * - very ugly */
+
+ _fmt_dbg("called.\n");
+ return err;
+}
+
+static int fmt_ioctls(unsigned int minor,
+ struct file *file,
+ unsigned int cmd,
+ unsigned long arg,
+ bool compat)
+{
+ struct fmt_port_s *fmt_port = NULL;
+
+ _fmt_dbg("IOCTL minor:%u "
+ " arg:0x%08lx ioctl cmd (0x%08x):(0x%02x:0x%02x.\n",
+ minor, arg, cmd, _IOC_TYPE(cmd), _IOC_NR(cmd));
+
+ fmt_port = file->private_data;
+ if (!fmt_port) {
+ _fmt_err("invalid fmt port.\n");
+ return -ENODEV;
+ }
+
+ /* set test type properly */
+ if (compat)
+ fmt_port->compat_test_type = true;
+ else
+ fmt_port->compat_test_type = false;
+
+ switch (cmd) {
+ case FMT_PORT_IOC_INIT:
+ {
+ ioc_fmt_port_param_t param;
+
+ if (fmt_port->valid) {
+ _fmt_wrn("port is already initialized.\n");
+ return -EFAULT;
+ }
+#if defined(CONFIG_COMPAT)
+ if (compat) {
+ if (copy_from_user(&param,
+ (ioc_fmt_port_param_t *)compat_ptr(arg),
+ sizeof(ioc_fmt_port_param_t)))
+
+ return -EFAULT;
+ } else
+#endif
+ {
+ if (copy_from_user(&param,
+ (ioc_fmt_port_param_t *) arg,
+ sizeof(ioc_fmt_port_param_t)))
+
+ return -EFAULT;
+ }
+
+ return fmt_port_init(fmt_port, &param);
+ }
+
+ case FMT_PORT_IOC_SET_DIAG_MODE:
+ if (get_user(fmt_port->diag, (ioc_diag_mode *)arg))
+ return -EFAULT;
+
+ if (fmt_port->diag == e_IOC_DIAG_MODE_CTRL_LOOPBACK)
+ return set_mac_int_loopback(fmt_port, TRUE);
+ else
+ return set_mac_int_loopback(fmt_port, FALSE);
+ break;
+
+ case FMT_PORT_IOC_SET_DPAECHO_MODE:
+ case FMT_PORT_IOC_SET_IP_HEADER_MANIP:
+ default:
+ _fmt_wrn("ioctl unimplemented minor:%u@ioctl"
+ " cmd:0x%08x(type:0x%02x, nr:0x%02x.\n",
+ minor, cmd, _IOC_TYPE(cmd), _IOC_NR(cmd));
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_COMPAT
+static long fmt_compat_ioctl(
+ struct file *file,
+ unsigned int cmd,
+ unsigned long arg)
+{
+ unsigned int minor = iminor(file->f_path.dentry->d_inode);
+
+ _fmt_dbg("calling...\n");
+ return fmt_ioctls(minor, file, cmd, arg, true);
+}
+#endif
+
+static long fmt_ioctl(
+ struct file *file,
+ unsigned int cmd,
+ unsigned long arg)
+{
+ unsigned int minor = iminor(file->f_path.dentry->d_inode);
+ unsigned int res;
+
+ _fmt_dbg("calling...\n");
+
+ fm_mutex_lock();
+ res = fmt_ioctls(minor, file, cmd, arg, false);
+ fm_mutex_unlock();
+
+ _fmt_dbg("called.\n");
+
+ return res;
+}
+
+#ifdef CONFIG_COMPAT
+void copy_compat_test_frame_buffer(
+ ioc_fmt_buff_desc_t *buff,
+ ioc_fmt_compat_buff_desc_t *compat_buff)
+{
+ compat_buff->qid = buff->qid;
+ compat_buff->p_data = ptr_to_compat(buff->p_data);
+ compat_buff->size = buff->size;
+ compat_buff->status = buff->status;
+
+ compat_buff->buff_context.p_user_priv =
+ ptr_to_compat(buff->buff_context.p_user_priv);
+ memcpy(compat_buff->buff_context.fm_prs_res,
+ buff->buff_context.fm_prs_res,
+ FM_PRS_MAX * sizeof(uint8_t));
+ memcpy(compat_buff->buff_context.fm_time_stamp,
+ buff->buff_context.fm_time_stamp,
+ FM_TIME_STAMP_MAX * sizeof(uint8_t));
+}
+#endif
+
+ssize_t fmt_read(
+ struct file *file,
+ char __user *buf,
+ size_t size,
+ loff_t *ppos)
+{
+ struct fmt_port_s *fmt_port = NULL;
+ struct fmt_frame_s *p_fmt_frame = NULL;
+ ssize_t cnt = 0;
+
+ fmt_port = file->private_data;
+ if (!fmt_port || !fmt_port->valid) {
+ _fmt_err("fmt port not valid!\n");
+ return -ENODEV;
+ }
+
+ p_fmt_frame = dequeue_fmt_frame(fmt_port);
+ if (p_fmt_frame == NULL)
+ return 0;
+
+ _fmt_dbgr("calling...\n");
+
+#ifdef CONFIG_COMPAT
+ if (fmt_port->compat_test_type){
+ cnt = sizeof(ioc_fmt_compat_buff_desc_t);
+ }
+ else
+#endif
+ {
+ cnt = sizeof(ioc_fmt_buff_desc_t);
+ }
+
+ if (size < cnt) {
+ _fmt_err("illegal buffer-size!\n");
+ cnt = 0;
+ goto _fmt_read_return;
+ }
+
+ /* Copy structure */
+#ifdef CONFIG_COMPAT
+ if (fmt_port->compat_test_type) {
+ {
+ ioc_fmt_compat_buff_desc_t compat_buff;
+ copy_compat_test_frame_buffer(&p_fmt_frame->buff,
+ &compat_buff);
+
+ if (copy_to_user(buf, &compat_buff, cnt)) {
+ _fmt_err("copy_to_user failed!\n");
+ goto _fmt_read_return;
+ }
+ }
+
+ ((ioc_fmt_compat_buff_desc_t *)buf)->p_data =
+ ptr_to_compat(buf+sizeof(ioc_fmt_compat_buff_desc_t));
+ cnt += MIN(p_fmt_frame->buff.size, size-cnt);
+ } else
+#endif
+ {
+ if (copy_to_user(buf, &p_fmt_frame->buff, cnt)) {
+ _fmt_err("copy_to_user failed!\n");
+ goto _fmt_read_return;
+ }
+
+ ((ioc_fmt_buff_desc_t *)buf)->p_data =
+ buf + sizeof(ioc_fmt_buff_desc_t);
+ cnt += MIN(p_fmt_frame->buff.size, size-cnt);
+ }
+
+ if (size < cnt) {
+ _fmt_err("illegal buffer-size!\n");
+ goto _fmt_read_return;
+ }
+
+ /* copy frame */
+#ifdef CONFIG_COMPAT
+ if (fmt_port->compat_test_type) {
+ if (copy_to_user(buf+sizeof(ioc_fmt_compat_buff_desc_t),
+ p_fmt_frame->buff.p_data, cnt)) {
+ _fmt_err("copy_to_user failed!\n");
+ goto _fmt_read_return;
+ }
+ } else
+#endif
+ {
+ if (copy_to_user(buf+sizeof(ioc_fmt_buff_desc_t),
+ p_fmt_frame->buff.p_data, cnt)) {
+ _fmt_err("copy_to_user failed!\n");
+ goto _fmt_read_return;
+ }
+ }
+
+_fmt_read_return:
+ kfree(p_fmt_frame->buff.p_data);
+ kfree(p_fmt_frame);
+
+ _fmt_dbgr("called.\n");
+ return cnt;
+}
+
+ssize_t fmt_write(
+ struct file *file,
+ const char __user *buf,
+ size_t size,
+ loff_t *ppos)
+{
+ struct fmt_port_s *fmt_port = NULL;
+ ioc_fmt_buff_desc_t buff_desc;
+#ifdef CONFIG_COMPAT
+ ioc_fmt_compat_buff_desc_t buff_desc_compat;
+#endif
+ uint8_t *p_data = NULL;
+ uint32_t data_offset;
+ int _errno;
+ t_DpaaFD fd;
+
+ _fmt_dbgr("calling...\n");
+
+ fmt_port = file->private_data;
+ if (!fmt_port || !fmt_port->valid) {
+ _fmt_err("fmt port not valid.\n");
+ return -EINVAL;
+ }
+
+ /* If Compat (32B UserSpace - 64B KernelSpace) */
+#ifdef CONFIG_COMPAT
+ if (fmt_port->compat_test_type) {
+ if (size < sizeof(ioc_fmt_compat_buff_desc_t)) {
+ _fmt_err("invalid buff_desc size.\n");
+ return -EFAULT;
+ }
+
+ if (copy_from_user(&buff_desc_compat, buf,
+ sizeof(ioc_fmt_compat_buff_desc_t)))
+ return -EFAULT;
+
+ buff_desc.qid = buff_desc_compat.qid;
+ buff_desc.p_data = compat_ptr(buff_desc_compat.p_data);
+ buff_desc.size = buff_desc_compat.size;
+ buff_desc.status = buff_desc_compat.status;
+
+ buff_desc.buff_context.p_user_priv =
+ compat_ptr(buff_desc_compat.buff_context.p_user_priv);
+ memcpy(buff_desc.buff_context.fm_prs_res,
+ buff_desc_compat.buff_context.fm_prs_res,
+ FM_PRS_MAX * sizeof(uint8_t));
+ memcpy(buff_desc.buff_context.fm_time_stamp,
+ buff_desc_compat.buff_context.fm_time_stamp,
+ FM_TIME_STAMP_MAX * sizeof(uint8_t));
+ } else
+#endif
+ {
+ if (size < sizeof(ioc_fmt_buff_desc_t)) {
+ _fmt_err("invalid buff_desc size.\n");
+ return -EFAULT;
+ }
+
+ if (copy_from_user(&buff_desc, (ioc_fmt_buff_desc_t *)buf,
+ sizeof(ioc_fmt_buff_desc_t)))
+ return -EFAULT;
+ }
+
+ data_offset = FM_PORT_GetBufferDataOffset(fmt_port->p_tx_fm_port_dev);
+ p_data = kmalloc(buff_desc.size+data_offset, GFP_KERNEL);
+ if (!p_data)
+ return -ENOMEM;
+
+ /* If Compat (32UserSpace - 64KernelSpace) the buff_desc.p_data is ok */
+ if (copy_from_user((uint8_t *)PTR_MOVE(p_data, data_offset),
+ buff_desc.p_data,
+ buff_desc.size)) {
+ kfree(p_data);
+ return -EFAULT;
+ }
+
+ /* TODO: dma_map_single here (cannot access the bpool struct) */
+
+ /* prepare fd */
+ memset(&fd, 0, sizeof(fd));
+ DPAA_FD_SET_ADDR(&fd, p_data);
+ DPAA_FD_SET_OFFSET(&fd, data_offset);
+ DPAA_FD_SET_LENGTH(&fd, buff_desc.size);
+
+ _errno = qman_enqueue(&fmt_port->p_tx_fqs[buff_desc.qid].fq_base,
+ (struct qm_fd *)&fd, 0);
+ if (_errno) {
+ buff_desc.status = (uint32_t)_errno;
+ if (copy_to_user((ioc_fmt_buff_desc_t *)buf, &buff_desc,
+ sizeof(ioc_fmt_buff_desc_t))) {
+ kfree(p_data);
+ return -EFAULT;
+ }
+ }
+
+ /* for debugging */
+#if defined(FMT_K_DBG) || defined(FMT_K_DBG_RUNTIME)
+ atomic_inc(&fmt_port->enqueue_to_qman_frm);
+#endif
+ _fmt_dbgr("called.\n");
+ return buff_desc.size;
+}
+
+/* fm test character device definition */
+static const struct file_operations fmt_fops =
+{
+ .owner = THIS_MODULE,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = fmt_compat_ioctl,
+#endif
+ .unlocked_ioctl = fmt_ioctl,
+ .open = fmt_open,
+ .release = fmt_close,
+ .read = fmt_read,
+ .write = fmt_write,
+};
+
+static int fmt_init(void)
+{
+ int id;
+
+ _fmt_dbg("calling...\n");
+
+ /* Register to the /dev for IOCTL API */
+ /* Register dynamically a new major number for the character device: */
+ fm_test.major = register_chrdev(0, DEV_FM_TEST_NAME, &fmt_fops);
+ if (fm_test.major <= 0) {
+ _fmt_wrn("Failed to allocate major number for device %s.\n",
+ DEV_FM_TEST_NAME);
+ return -ENODEV;
+ }
+
+ /* Creating class for FMan_test */
+ fm_test.fmt_class = class_create(THIS_MODULE, DEV_FM_TEST_NAME);
+ if (IS_ERR(fm_test.fmt_class)) {
+ unregister_chrdev(fm_test.major, DEV_FM_TEST_NAME);
+ _fmt_wrn("Error creating %s class.\n", DEV_FM_TEST_NAME);
+ return -ENODEV;
+ }
+
+ for (id = 0; id < IOC_FMT_MAX_NUM_OF_PORTS; id++)
+ if (NULL == device_create(fm_test.fmt_class, NULL,
+ MKDEV(fm_test.major,
+ DEV_FM_TEST_PORTS_MINOR_BASE + id), NULL,
+ DEV_FM_TEST_NAME "%d", id)) {
+
+ _fmt_err("Error creating %s device.\n",
+ DEV_FM_TEST_NAME);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static void fmt_free(void)
+{
+ int id;
+
+ for (id = 0; id < IOC_FMT_MAX_NUM_OF_PORTS; id++)
+ device_destroy(fm_test.fmt_class, MKDEV(fm_test.major,
+ DEV_FM_TEST_PORTS_MINOR_BASE + id));
+ class_destroy(fm_test.fmt_class);
+}
+
+static int __init __cold fmt_load(void)
+{
+ struct dpaa_eth_hooks_s priv_dpaa_eth_hooks;
+
+ /* set dpaa hooks for default queues */
+ memset(&priv_dpaa_eth_hooks, 0, sizeof(priv_dpaa_eth_hooks));
+ priv_dpaa_eth_hooks.rx_default = fmt_rx_default_hook;
+ priv_dpaa_eth_hooks.rx_error = fmt_rx_error_hook;
+ priv_dpaa_eth_hooks.tx_confirm = fmt_tx_confirm_hook;
+ priv_dpaa_eth_hooks.tx_error = fmt_tx_confirm_error_hook;
+
+ fsl_dpaa_eth_set_hooks(&priv_dpaa_eth_hooks);
+
+ /* initialize the fman test environment */
+ if (fmt_init() < 0) {
+ _fmt_err("Failed to init FM-test modul.\n");
+ fmt_free();
+ return -ENODEV;
+ }
+
+ _fmt_inf("FSL FM test module loaded.\n");
+
+ return 0;
+}
+
+static void __exit __cold fmt_unload(void)
+{
+ fmt_free();
+ _fmt_inf("FSL FM test module unloaded.\n");
+}
+
+module_init(fmt_load);
+module_exit(fmt_unload);
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.c
new file mode 100755
index 0000000..7c09d8b
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.c
@@ -0,0 +1,1964 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ @File lnxwrp_fm.c
+ @Author Shlomi Gridish
+ @Description FM Linux wrapper functions.
+*/
+
+#include <linux/version.h>
+#include <linux/slab.h>
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+#define MODVERSIONS
+#endif
+#ifdef MODVERSIONS
+#include <config/modversions.h>
+#endif /* MODVERSIONS */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/uaccess.h>
+#include <asm/errno.h>
+#include <asm/qe.h> /* For struct qe_firmware */
+#include <sysdev/fsl_soc.h>
+#include <linux/stat.h> /* For file access mask */
+#include <linux/skbuff.h>
+#include <linux/proc_fs.h>
+
+/* NetCommSw Headers --------------- */
+#include "std_ext.h"
+#include "error_ext.h"
+#include "sprint_ext.h"
+#include "debug_ext.h"
+#include "sys_io_ext.h"
+
+#include "fm_ioctls.h"
+
+#include "lnxwrp_fm.h"
+#include "lnxwrp_resources.h"
+#include "lnxwrp_sysfs_fm.h"
+#include "lnxwrp_sysfs_fm_port.h"
+#include "lnxwrp_exp_sym.h"
+
+#define __ERR_MODULE__ MODULE_FM
+
+extern struct device_node *GetFmPortAdvArgsDevTreeNode (struct device_node *fm_node,
+ e_FmPortType portType,
+ uint8_t portId);
+
+#define PROC_PRINT(args...) offset += sprintf(buf+offset,args)
+
+#define ADD_ADV_CONFIG_NO_RET(_func, _param) \
+ do { \
+ if (i<max){ \
+ p_Entry = &p_Entrys[i]; \
+ p_Entry->p_Function = _func; \
+ _param \
+ i++; \
+ } \
+ else \
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,\
+ ("Number of advanced-configuration entries exceeded"));\
+ } while (0)
+
+/* Bootarg used to override the Kconfig FSL_FM_MAX_FRAME_SIZE value */
+#define FSL_FM_MAX_FRM_BOOTARG "fsl_fm_max_frm"
+
+/* Bootarg used to override FSL_FM_RX_EXTRA_HEADROOM Kconfig value */
+#define FSL_FM_RX_EXTRA_HEADROOM_BOOTARG "fsl_fm_rx_extra_headroom"
+
+/* Minimum and maximum value for the fsl_fm_rx_extra_headroom bootarg */
+#define FSL_FM_RX_EXTRA_HEADROOM_MIN 16
+#define FSL_FM_RX_EXTRA_HEADROOM_MAX 384
+
+#define FSL_FM_PAUSE_TIME_ENABLE 0xf000
+#define FSL_FM_PAUSE_TIME_DISABLE 0
+#define FSL_FM_PAUSE_THRESH_DEFAULT 0
+
+/*
+ * Max frame size, across all interfaces.
+ * Configurable from Kconfig or bootargs, to avoid allocating
+ * oversized (socket) buffers when not using jumbo frames.
+ * Must be large enough to accommodate the network MTU, but small enough
+ * to avoid wasting skb memory.
+ *
+ * Could be overridden once, at boot-time, via the
+ * fm_set_max_frm() callback.
+ */
+int fsl_fm_max_frm = CONFIG_FSL_FM_MAX_FRAME_SIZE;
+
+/*
+ * Extra headroom for Rx buffers.
+ * FMan is instructed to allocate, on the Rx path, this amount of
+ * space at the beginning of a data buffer, beside the DPA private
+ * data area and the IC fields.
+ * Does not impact Tx buffer layout.
+ *
+ * Configurable from Kconfig or bootargs. Zero by default, it's needed
+ * on particular forwarding scenarios that add extra headers to the
+ * forwarded frame.
+ */
+int fsl_fm_rx_extra_headroom = CONFIG_FSL_FM_RX_EXTRA_HEADROOM;
+
+#ifdef CONFIG_FMAN_PFC
+static int fsl_fm_pfc_quanta[] = {
+ CONFIG_FMAN_PFC_QUANTA_0,
+ CONFIG_FMAN_PFC_QUANTA_1,
+ CONFIG_FMAN_PFC_QUANTA_2,
+ CONFIG_FMAN_PFC_QUANTA_3
+};
+#endif
+
+static t_LnxWrpFm lnxWrpFm;
+
+int fm_get_max_frm()
+{
+ return fsl_fm_max_frm;
+}
+
+int fm_get_rx_extra_headroom()
+{
+ return ALIGN(fsl_fm_rx_extra_headroom, 16);
+}
+
+static int __init fm_set_max_frm(char *str)
+{
+ int ret = 0;
+
+ ret = get_option(&str, &fsl_fm_max_frm);
+ if (ret != 1) {
+ /*
+ * This will only work if CONFIG_EARLY_PRINTK is compiled in,
+ * and something like "earlyprintk=serial,uart0,115200" is
+ * specified in the bootargs
+ */
+ printk(KERN_WARNING "No suitable %s=<int> prop in bootargs; "
+ "will use the default FSL_FM_MAX_FRAME_SIZE (%d) "
+ "from Kconfig.\n", FSL_FM_MAX_FRM_BOOTARG,
+ CONFIG_FSL_FM_MAX_FRAME_SIZE);
+
+ fsl_fm_max_frm = CONFIG_FSL_FM_MAX_FRAME_SIZE;
+ return 1;
+ }
+
+ /* Don't allow invalid bootargs; fallback to the Kconfig value */
+ if (fsl_fm_max_frm < 64 || fsl_fm_max_frm > 9600) {
+ printk(KERN_WARNING "Invalid %s=%d in bootargs, valid range is "
+ "64-9600. Falling back to the FSL_FM_MAX_FRAME_SIZE (%d) "
+ "from Kconfig.\n",
+ FSL_FM_MAX_FRM_BOOTARG, fsl_fm_max_frm,
+ CONFIG_FSL_FM_MAX_FRAME_SIZE);
+
+ fsl_fm_max_frm = CONFIG_FSL_FM_MAX_FRAME_SIZE;
+ return 1;
+ }
+
+ printk(KERN_INFO "Using fsl_fm_max_frm=%d from bootargs\n",
+ fsl_fm_max_frm);
+ return 0;
+}
+early_param(FSL_FM_MAX_FRM_BOOTARG, fm_set_max_frm);
+
+static int __init fm_set_rx_extra_headroom(char *str)
+{
+ int ret;
+
+ ret = get_option(&str, &fsl_fm_rx_extra_headroom);
+
+ if (ret != 1) {
+ printk(KERN_WARNING "No suitable %s=<int> prop in bootargs; "
+ "will use the default FSL_FM_RX_EXTRA_HEADROOM (%d) "
+ "from Kconfig.\n", FSL_FM_RX_EXTRA_HEADROOM_BOOTARG,
+ CONFIG_FSL_FM_RX_EXTRA_HEADROOM);
+ fsl_fm_rx_extra_headroom = CONFIG_FSL_FM_RX_EXTRA_HEADROOM;
+
+ return 1;
+ }
+
+ if (fsl_fm_rx_extra_headroom < FSL_FM_RX_EXTRA_HEADROOM_MIN ||
+ fsl_fm_rx_extra_headroom > FSL_FM_RX_EXTRA_HEADROOM_MAX) {
+ printk(KERN_WARNING "Invalid value for %s=%d prop in "
+ "bootargs; will use the default "
+ "FSL_FM_RX_EXTRA_HEADROOM (%d) from Kconfig.\n",
+ FSL_FM_RX_EXTRA_HEADROOM_BOOTARG,
+ fsl_fm_rx_extra_headroom,
+ CONFIG_FSL_FM_RX_EXTRA_HEADROOM);
+ fsl_fm_rx_extra_headroom = CONFIG_FSL_FM_RX_EXTRA_HEADROOM;
+ }
+
+ printk(KERN_INFO "Using fsl_fm_rx_extra_headroom=%d from bootargs\n",
+ fsl_fm_rx_extra_headroom);
+
+ return 0;
+}
+early_param(FSL_FM_RX_EXTRA_HEADROOM_BOOTARG, fm_set_rx_extra_headroom);
+
+static irqreturn_t fm_irq(int irq, void *_dev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *)_dev;
+
+ if (!p_LnxWrpFmDev || !p_LnxWrpFmDev->h_Dev)
+ return IRQ_NONE;
+
+ FM_EventIsr(p_LnxWrpFmDev->h_Dev);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t fm_err_irq(int irq, void *_dev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *)_dev;
+
+ if (!p_LnxWrpFmDev || !p_LnxWrpFmDev->h_Dev)
+ return IRQ_NONE;
+
+ if (FM_ErrorIsr(p_LnxWrpFmDev->h_Dev) == E_OK)
+ return IRQ_HANDLED;
+
+ return IRQ_NONE;
+}
+
+/* used to protect FMD/LLD from concurrent calls in functions fm_mutex_lock / fm_mutex_unlock */
+static struct mutex lnxwrp_mutex;
+
+static t_LnxWrpFmDev * CreateFmDev(uint8_t id)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
+ int j;
+
+ p_LnxWrpFmDev = (t_LnxWrpFmDev *)XX_Malloc(sizeof(t_LnxWrpFmDev));
+ if (!p_LnxWrpFmDev)
+ {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+ return NULL;
+ }
+
+ memset(p_LnxWrpFmDev, 0, sizeof(t_LnxWrpFmDev));
+ p_LnxWrpFmDev->fmDevSettings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry));
+ memset(p_LnxWrpFmDev->fmDevSettings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)));
+ p_LnxWrpFmDev->fmPcdDevSettings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry));
+ memset(p_LnxWrpFmDev->fmPcdDevSettings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)));
+ p_LnxWrpFmDev->hcPort.settings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry));
+ memset(p_LnxWrpFmDev->hcPort.settings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)));
+ for (j=0; j<FM_MAX_NUM_OF_RX_PORTS; j++)
+ {
+ p_LnxWrpFmDev->rxPorts[j].settings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry));
+ memset(p_LnxWrpFmDev->rxPorts[j].settings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)));
+ }
+ for (j=0; j<FM_MAX_NUM_OF_TX_PORTS; j++)
+ {
+ p_LnxWrpFmDev->txPorts[j].settings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry));
+ memset(p_LnxWrpFmDev->txPorts[j].settings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)));
+ }
+ for (j=0; j<FM_MAX_NUM_OF_OH_PORTS-1; j++)
+ {
+ p_LnxWrpFmDev->opPorts[j].settings.advConfig = (t_SysObjectAdvConfigEntry*)XX_Malloc(FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry));
+ memset(p_LnxWrpFmDev->opPorts[j].settings.advConfig, 0, (FM_MAX_NUM_OF_ADV_SETTINGS*sizeof(t_SysObjectAdvConfigEntry)));
+ }
+
+ return p_LnxWrpFmDev;
+}
+
+static void DestroyFmDev(t_LnxWrpFmDev *p_LnxWrpFmDev)
+{
+ int j;
+
+ for (j=0; j<FM_MAX_NUM_OF_OH_PORTS-1; j++)
+ if (p_LnxWrpFmDev->opPorts[j].settings.advConfig)
+ XX_Free(p_LnxWrpFmDev->opPorts[j].settings.advConfig);
+ for (j=0; j<FM_MAX_NUM_OF_TX_PORTS; j++)
+ if (p_LnxWrpFmDev->txPorts[j].settings.advConfig)
+ XX_Free(p_LnxWrpFmDev->txPorts[j].settings.advConfig);
+ for (j=0; j<FM_MAX_NUM_OF_RX_PORTS; j++)
+ if (p_LnxWrpFmDev->rxPorts[j].settings.advConfig)
+ XX_Free(p_LnxWrpFmDev->rxPorts[j].settings.advConfig);
+ if (p_LnxWrpFmDev->hcPort.settings.advConfig)
+ XX_Free(p_LnxWrpFmDev->hcPort.settings.advConfig);
+ if (p_LnxWrpFmDev->fmPcdDevSettings.advConfig)
+ XX_Free(p_LnxWrpFmDev->fmPcdDevSettings.advConfig);
+ if (p_LnxWrpFmDev->fmDevSettings.advConfig)
+ XX_Free(p_LnxWrpFmDev->fmDevSettings.advConfig);
+
+ XX_Free(p_LnxWrpFmDev);
+}
+
+static t_Error FillRestFmInfo(t_LnxWrpFmDev *p_LnxWrpFmDev)
+{
+#define FM_BMI_PPIDS_OFFSET 0x00080304
+#define FM_DMA_PLR_OFFSET 0x000c2060
+#define FM_FPM_IP_REV_1_OFFSET 0x000c30c4
+#define DMA_HIGH_LIODN_MASK 0x0FFF0000
+#define DMA_LOW_LIODN_MASK 0x00000FFF
+#define DMA_LIODN_SHIFT 16
+
+typedef _Packed struct {
+ uint32_t plr[32];
+} _PackedType t_Plr;
+
+typedef _Packed struct {
+ volatile uint32_t fmbm_ppid[63];
+} _PackedType t_Ppids;
+
+ t_Plr *p_Plr;
+ t_Ppids *p_Ppids;
+ int i,j;
+ uint32_t fmRev;
+
+ static const uint8_t phys1GRxPortId[] = {0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf};
+ static const uint8_t phys10GRxPortId[] = {0x10,0x11};
+#if (DPAA_VERSION >= 11)
+ static const uint8_t physOhPortId[] = {/* 0x1, */0x2,0x3,0x4,0x5,0x6,0x7};
+#else
+ static const uint8_t physOhPortId[] = {0x1,0x2,0x3,0x4,0x5,0x6,0x7};
+#endif
+ static const uint8_t phys1GTxPortId[] = {0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f};
+ static const uint8_t phys10GTxPortId[] = {0x30,0x31};
+
+ fmRev = (uint32_t)(*((volatile uint32_t *)UINT_TO_PTR(p_LnxWrpFmDev->fmBaseAddr+FM_FPM_IP_REV_1_OFFSET)));
+ fmRev &= 0xffff;
+
+ p_Plr = (t_Plr *)UINT_TO_PTR(p_LnxWrpFmDev->fmBaseAddr+FM_DMA_PLR_OFFSET);
+#ifdef MODULE
+ for (i=0;i<FM_MAX_NUM_OF_PARTITIONS/2;i++)
+ p_Plr->plr[i] = 0;
+#endif /* MODULE */
+
+ for (i=0; i<FM_MAX_NUM_OF_PARTITIONS; i++)
+ {
+ uint16_t liodnBase = (uint16_t)((i%2) ?
+ (p_Plr->plr[i/2] & DMA_LOW_LIODN_MASK) :
+ ((p_Plr->plr[i/2] & DMA_HIGH_LIODN_MASK) >> DMA_LIODN_SHIFT));
+#ifdef FM_PARTITION_ARRAY
+ /* TODO: this was .liodnPerPartition[i] = liodnBase; is the index meaning the same? */
+ p_LnxWrpFmDev->fmDevSettings.param.liodnBasePerPort[i] = liodnBase;
+#endif /* FM_PARTITION_ARRAY */
+
+ if ((i >= phys1GRxPortId[0]) &&
+ (i <= phys1GRxPortId[FM_MAX_NUM_OF_1G_RX_PORTS-1]))
+ {
+ for (j=0; j<ARRAY_SIZE(phys1GRxPortId); j++)
+ if (phys1GRxPortId[j] == i)
+ break;
+ ASSERT_COND(j<ARRAY_SIZE(phys1GRxPortId));
+ p_LnxWrpFmDev->rxPorts[j].settings.param.liodnBase = liodnBase;
+ }
+ else if (FM_MAX_NUM_OF_10G_RX_PORTS &&
+ (i >= phys10GRxPortId[0]) &&
+ (i <= phys10GRxPortId[FM_MAX_NUM_OF_10G_RX_PORTS-1]))
+ {
+ for (j=0; j<ARRAY_SIZE(phys10GRxPortId); j++)
+ if (phys10GRxPortId[j] == i)
+ break;
+ ASSERT_COND(j<ARRAY_SIZE(phys10GRxPortId));
+ p_LnxWrpFmDev->rxPorts[FM_MAX_NUM_OF_1G_RX_PORTS+j].settings.param.liodnBase = liodnBase;
+ }
+ else if ((i >= physOhPortId[0]) &&
+ (i <= physOhPortId[FM_MAX_NUM_OF_OH_PORTS-1]))
+ {
+ for (j=0; j<ARRAY_SIZE(physOhPortId); j++)
+ if (physOhPortId[j] == i)
+ break;
+ ASSERT_COND(j<ARRAY_SIZE(physOhPortId));
+ if (j == 0)
+ p_LnxWrpFmDev->hcPort.settings.param.liodnBase = liodnBase;
+ else
+ p_LnxWrpFmDev->opPorts[j - 1].settings.param.liodnBase = liodnBase;
+ }
+ else if ((i >= phys1GTxPortId[0]) &&
+ (i <= phys1GTxPortId[FM_MAX_NUM_OF_1G_TX_PORTS-1]))
+ {
+ for (j=0; j<ARRAY_SIZE(phys1GTxPortId); j++)
+ if (phys1GTxPortId[j] == i)
+ break;
+ ASSERT_COND(j<ARRAY_SIZE(phys1GTxPortId));
+ p_LnxWrpFmDev->txPorts[j].settings.param.liodnBase = liodnBase;
+ }
+ else if (FM_MAX_NUM_OF_10G_TX_PORTS &&
+ (i >= phys10GTxPortId[0]) &&
+ (i <= phys10GTxPortId[FM_MAX_NUM_OF_10G_TX_PORTS-1]))
+ {
+ for (j=0; j<ARRAY_SIZE(phys10GTxPortId); j++)
+ if (phys10GTxPortId[j] == i)
+ break;
+ ASSERT_COND(j<ARRAY_SIZE(phys10GTxPortId));
+ p_LnxWrpFmDev->txPorts[FM_MAX_NUM_OF_1G_TX_PORTS+j].settings.param.liodnBase = liodnBase;
+ }
+ }
+
+ p_Ppids = (t_Ppids *)UINT_TO_PTR(p_LnxWrpFmDev->fmBaseAddr+FM_BMI_PPIDS_OFFSET);
+
+ for (i=0; i<FM_MAX_NUM_OF_1G_RX_PORTS; i++)
+ p_LnxWrpFmDev->rxPorts[i].settings.param.specificParams.rxParams.liodnOffset =
+ p_Ppids->fmbm_ppid[phys1GRxPortId[i]-1];
+
+ for (i=0; i<FM_MAX_NUM_OF_10G_RX_PORTS; i++)
+ p_LnxWrpFmDev->rxPorts[FM_MAX_NUM_OF_1G_RX_PORTS+i].settings.param.specificParams.rxParams.liodnOffset =
+ p_Ppids->fmbm_ppid[phys10GRxPortId[i]-1];
+
+ return E_OK;
+}
+
+/**
+ * FindFmanMicrocode - find the Fman microcode
+ *
+ * This function returns a pointer to the QE Firmware blob that holds
+ * the Fman microcode. We use the QE Firmware structure because Fman microcode
+ * is similar to QE microcode, so there's no point in defining a new layout.
+ *
+ * Current versions of U-Boot embed the Fman firmware into the device tree,
+ * so we check for that first. Each Fman node in the device tree contains a
+ * node or a pointer to node that holds the firmware. Technically, we should
+ * be fetching the firmware node for the current Fman, but we don't have that
+ * information any more, so we assume that there is only one firmware node in
+ * the device tree, and that all Fmen use the same firmware.
+ */
+static const struct qe_firmware *FindFmanMicrocode(void)
+{
+ static const struct qe_firmware *P4080_UCPatch;
+ struct device_node *np;
+
+ if (P4080_UCPatch)
+ return P4080_UCPatch;
+
+ /* The firmware should be inside the device tree. */
+ np = of_find_compatible_node(NULL, NULL, "fsl,fman-firmware");
+ if (np) {
+ P4080_UCPatch = of_get_property(np, "fsl,firmware", NULL);
+ of_node_put(np);
+ if (P4080_UCPatch)
+ return P4080_UCPatch;
+ else
+ REPORT_ERROR(WARNING, E_NOT_FOUND, ("firmware node is incomplete"));
+ }
+
+ /* Returning NULL here forces the reuse of the IRAM content */
+ return NULL;
+}
+#define SVR_SECURITY_MASK 0x00080000
+#define SVR_PERSONALITY_MASK 0x0000FF00
+#define SVR_VER_IGNORE_MASK (SVR_SECURITY_MASK | SVR_PERSONALITY_MASK)
+#define SVR_B4860_REV1_VALUE 0x86800010
+#define SVR_B4860_REV2_VALUE 0x86800020
+
+
+static t_LnxWrpFmDev * ReadFmDevTreeNode (struct platform_device *of_dev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
+ struct device_node *fm_node, *dev_node;
+ struct of_device_id name;
+ struct resource res;
+ const uint32_t *uint32_prop;
+ int _errno=0, lenp;
+
+ fm_node = of_node_get(of_dev->dev.of_node);
+
+ uint32_prop = (uint32_t *)of_get_property(fm_node, "cell-index", &lenp);
+ if (unlikely(uint32_prop == NULL)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_get_property(%s, cell-index) failed", fm_node->full_name));
+ return NULL;
+ }
+ if (WARN_ON(lenp != sizeof(uint32_t)))
+ return NULL;
+ if (*uint32_prop > INTG_MAX_NUM_OF_FM) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("fm id!"));
+ return NULL;
+ }
+ p_LnxWrpFmDev = CreateFmDev(*uint32_prop);
+ if (!p_LnxWrpFmDev) {
+ REPORT_ERROR(MAJOR, E_NULL_POINTER, NO_MSG);
+ return NULL;
+ }
+ p_LnxWrpFmDev->dev = &of_dev->dev;
+ p_LnxWrpFmDev->id = *uint32_prop;
+
+ /* Get the FM interrupt */
+ p_LnxWrpFmDev->irq = of_irq_to_resource(fm_node, 0, NULL);
+ if (unlikely(p_LnxWrpFmDev->irq == /*NO_IRQ*/0)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_irq_to_resource() = %d", NO_IRQ));
+ return NULL;
+ }
+
+ /* Get the FM error interrupt */
+ p_LnxWrpFmDev->err_irq = of_irq_to_resource(fm_node, 1, NULL);
+ /* TODO - un-comment it once there will be err_irq in the DTS */
+#if 0
+ if (unlikely(p_LnxWrpFmDev->err_irq == /*NO_IRQ*/0)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_irq_to_resource() = %d", NO_IRQ));
+ return NULL;
+ }
+#endif /* 0 */
+
+ /* Get the FM address */
+ _errno = of_address_to_resource(fm_node, 0, &res);
+ if (unlikely(_errno < 0)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_address_to_resource() = %d", _errno));
+ return NULL;
+ }
+
+
+ p_LnxWrpFmDev->fmBaseAddr = 0;
+ p_LnxWrpFmDev->fmPhysBaseAddr = res.start;
+ p_LnxWrpFmDev->fmMemSize = res.end + 1 - res.start;
+
+ uint32_prop = (uint32_t *)of_get_property(fm_node, "clock-frequency", &lenp);
+ if (unlikely(uint32_prop == NULL)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_get_property(%s, clock-frequency) failed", fm_node->full_name));
+ return NULL;
+ }
+ if (WARN_ON(lenp != sizeof(uint32_t)))
+ return NULL;
+ p_LnxWrpFmDev->fmDevSettings.param.fmClkFreq = (*uint32_prop + 500000)/1000000; /* In MHz, rounded */
+
+ /* Get the MURAM base address and size */
+ memset(&name, 0, sizeof(struct of_device_id));
+ if (WARN_ON(strlen("muram") >= sizeof(name.name)))
+ return NULL;
+ strcpy(name.name, "muram");
+ if (WARN_ON(strlen("fsl,fman-muram") >= sizeof(name.compatible)))
+ return NULL;
+ strcpy(name.compatible, "fsl,fman-muram");
+ for_each_child_of_node(fm_node, dev_node) {
+ if (likely(of_match_node(&name, dev_node) != NULL)) {
+ _errno = of_address_to_resource(dev_node, 0, &res);
+ if (unlikely(_errno < 0)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_address_to_resource() = %d", _errno));
+ return NULL;
+ }
+
+ p_LnxWrpFmDev->fmMuramBaseAddr = 0;
+ p_LnxWrpFmDev->fmMuramPhysBaseAddr = res.start;
+ p_LnxWrpFmDev->fmMuramMemSize = res.end + 1 - res.start;
+ {
+ uint32_t svr;
+ svr = mfspr(SPRN_SVR);
+
+ if ((svr & ~SVR_VER_IGNORE_MASK) >= SVR_B4860_REV2_VALUE)
+ p_LnxWrpFmDev->fmMuramMemSize = 0x80000;
+ }
+ }
+ }
+
+ /* Get the RTC base address and size */
+ memset(&name, 0, sizeof(struct of_device_id));
+ if (WARN_ON(strlen("rtc") >= sizeof(name.name)))
+ return NULL;
+ strcpy(name.name, "rtc");
+ if (WARN_ON(strlen("fsl,fman-rtc") >= sizeof(name.compatible)))
+ return NULL;
+ strcpy(name.compatible, "fsl,fman-rtc");
+ for_each_child_of_node(fm_node, dev_node) {
+ if (likely(of_match_node(&name, dev_node) != NULL)) {
+ _errno = of_address_to_resource(dev_node, 0, &res);
+ if (unlikely(_errno < 0)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_address_to_resource() = %d", _errno));
+ return NULL;
+ }
+
+ p_LnxWrpFmDev->fmRtcBaseAddr = 0;
+ p_LnxWrpFmDev->fmRtcPhysBaseAddr = res.start;
+ p_LnxWrpFmDev->fmRtcMemSize = res.end + 1 - res.start;
+ }
+ }
+
+#if (DPAA_VERSION >= 11)
+ /* Get the VSP base address */
+ for_each_child_of_node(fm_node, dev_node) {
+ if (of_device_is_compatible(dev_node, "fsl,fman-vsps")) {
+ _errno = of_address_to_resource(dev_node, 0, &res);
+ if (unlikely(_errno < 0)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("of_address_to_resource() = %d", _errno));
+ return NULL;
+ }
+ p_LnxWrpFmDev->fmVspBaseAddr = 0;
+ p_LnxWrpFmDev->fmVspPhysBaseAddr = res.start;
+ p_LnxWrpFmDev->fmVspMemSize = res.end + 1 - res.start;
+ }
+ }
+#endif
+
+ /* Get all PCD nodes */
+ memset(&name, 0, sizeof(struct of_device_id));
+ if (WARN_ON(strlen("parser") >= sizeof(name.name)))
+ return NULL;
+ strcpy(name.name, "parser");
+ if (WARN_ON(strlen("fsl,fman-parser") >= sizeof(name.compatible)))
+ return NULL;
+ strcpy(name.compatible, "fsl,fman-parser");
+ for_each_child_of_node(fm_node, dev_node)
+ if (likely(of_match_node(&name, dev_node) != NULL))
+ p_LnxWrpFmDev->prsActive = TRUE;
+
+ memset(&name, 0, sizeof(struct of_device_id));
+ if (WARN_ON(strlen("keygen") >= sizeof(name.name)))
+ return NULL;
+ strcpy(name.name, "keygen");
+ if (WARN_ON(strlen("fsl,fman-keygen") >= sizeof(name.compatible)))
+ return NULL;
+ strcpy(name.compatible, "fsl,fman-keygen");
+ for_each_child_of_node(fm_node, dev_node)
+ if (likely(of_match_node(&name, dev_node) != NULL))
+ p_LnxWrpFmDev->kgActive = TRUE;
+
+ memset(&name, 0, sizeof(struct of_device_id));
+ if (WARN_ON(strlen("cc") >= sizeof(name.name)))
+ return NULL;
+ strcpy(name.name, "cc");
+ if (WARN_ON(strlen("fsl,fman-cc") >= sizeof(name.compatible)))
+ return NULL;
+ strcpy(name.compatible, "fsl,fman-cc");
+ for_each_child_of_node(fm_node, dev_node)
+ if (likely(of_match_node(&name, dev_node) != NULL))
+ p_LnxWrpFmDev->ccActive = TRUE;
+
+ memset(&name, 0, sizeof(struct of_device_id));
+ if (WARN_ON(strlen("policer") >= sizeof(name.name)))
+ return NULL;
+ strcpy(name.name, "policer");
+ if (WARN_ON(strlen("fsl,fman-policer") >= sizeof(name.compatible)))
+ return NULL;
+ strcpy(name.compatible, "fsl,fman-policer");
+ for_each_child_of_node(fm_node, dev_node)
+ if (likely(of_match_node(&name, dev_node) != NULL))
+ p_LnxWrpFmDev->plcrActive = TRUE;
+
+ if (p_LnxWrpFmDev->prsActive || p_LnxWrpFmDev->kgActive ||
+ p_LnxWrpFmDev->ccActive || p_LnxWrpFmDev->plcrActive)
+ p_LnxWrpFmDev->pcdActive = TRUE;
+
+ if (p_LnxWrpFmDev->pcdActive)
+ {
+ const char *str_prop = (char *)of_get_property(fm_node, "fsl,default-pcd", &lenp);
+ if (str_prop) {
+ if (strncmp(str_prop, "3-tuple", strlen("3-tuple")) == 0)
+ p_LnxWrpFmDev->defPcd = e_FM_PCD_3_TUPLE;
+ }
+ else
+ p_LnxWrpFmDev->defPcd = e_NO_PCD;
+ }
+
+ of_node_put(fm_node);
+
+ p_LnxWrpFmDev->hcCh =
+ qman_affine_channel(cpumask_first(qman_affine_cpus()));
+
+ p_LnxWrpFmDev->active = TRUE;
+
+ return p_LnxWrpFmDev;
+}
+
+struct device_node *GetFmAdvArgsDevTreeNode (uint8_t fmIndx)
+{
+ struct device_node *dev_node;
+ const uint32_t *uint32_prop;
+ int lenp;
+
+ for_each_compatible_node(dev_node, NULL, "fsl,fman-extended-args") {
+ uint32_prop = (uint32_t *)of_get_property(dev_node, "cell-index", &lenp);
+ if (unlikely(uint32_prop == NULL)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("of_get_property(%s, cell-index) failed",
+ dev_node->full_name));
+ return NULL;
+ }
+ if (WARN_ON(lenp != sizeof(uint32_t)))
+ return NULL;
+ if (*uint32_prop > INTG_MAX_NUM_OF_FM) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("fm id!"));
+ return NULL;
+ }
+ if (fmIndx == *uint32_prop)
+ return dev_node;
+ }
+
+ return NULL;
+}
+
+static t_Error CheckNConfigFmAdvArgs (t_LnxWrpFmDev *p_LnxWrpFmDev)
+{
+ struct device_node *dev_node;
+ t_Error err = E_INVALID_VALUE;
+ const uint32_t *uint32_prop;
+ const char *str_prop;
+ int lenp;
+
+ dev_node = GetFmAdvArgsDevTreeNode(p_LnxWrpFmDev->id);
+ if (!dev_node) /* no advance parameters for FMan */
+ return E_OK;
+
+ str_prop = (char *)of_get_property(dev_node, "dma-aid-mode", &lenp);
+ if (str_prop) {
+ if (strcmp(str_prop, "port") == 0)
+ err = FM_ConfigDmaAidMode(p_LnxWrpFmDev->h_Dev, e_FM_DMA_AID_OUT_PORT_ID);
+ else if (strcmp(str_prop, "tnum") == 0)
+ err = FM_ConfigDmaAidMode(p_LnxWrpFmDev->h_Dev, e_FM_DMA_AID_OUT_TNUM);
+ }
+
+ uint32_prop = (uint32_t *)of_get_property(dev_node, "tnum-aging-period",
+ &lenp);
+ if (uint32_prop) {
+ if (WARN_ON(lenp != sizeof(uint32_t)))
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG);
+
+ err = FM_ConfigTnumAgingPeriod(p_LnxWrpFmDev->h_Dev,
+ (uint16_t)uint32_prop[0]/*tnumAgingPeriod*/);
+ }
+
+ if (err != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ of_node_put(dev_node);
+
+ return E_OK;
+}
+
+static void LnxwrpFmDevExceptionsCb(t_Handle h_App, e_FmExceptions exception)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *)h_App;
+
+ ASSERT_COND(p_LnxWrpFmDev);
+
+ DBG(INFO, ("got fm exception %d", exception));
+
+ /* do nothing */
+ UNUSED(exception);
+}
+
+static void LnxwrpFmDevBusErrorCb(t_Handle h_App,
+ e_FmPortType portType,
+ uint8_t portId,
+ uint64_t addr,
+ uint8_t tnum,
+ uint16_t liodn)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *)h_App;
+
+ ASSERT_COND(p_LnxWrpFmDev);
+
+ /* do nothing */
+ UNUSED(portType);UNUSED(portId);UNUSED(addr);UNUSED(tnum);UNUSED(liodn);
+}
+
+static t_Error ConfigureFmDev(t_LnxWrpFmDev *p_LnxWrpFmDev)
+{
+ struct resource *dev_res;
+ int _errno;
+
+ if (!p_LnxWrpFmDev->active)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM not configured!!!"));
+
+#ifndef MODULE
+ _errno = can_request_irq(p_LnxWrpFmDev->irq, 0);
+ if (unlikely(_errno < 0))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("can_request_irq() = %d", _errno));
+#endif
+ _errno = devm_request_irq(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->irq, fm_irq, 0, "fman", p_LnxWrpFmDev);
+ if (unlikely(_errno < 0))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("request_irq(%d) = %d", p_LnxWrpFmDev->irq, _errno));
+
+ if (p_LnxWrpFmDev->err_irq != 0) {
+#ifndef MODULE
+ _errno = can_request_irq(p_LnxWrpFmDev->err_irq, 0);
+ if (unlikely(_errno < 0))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("can_request_irq() = %d", _errno));
+#endif
+ _errno = devm_request_irq(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->err_irq, fm_err_irq, IRQF_SHARED | IRQF_NO_SUSPEND, "fman-err", p_LnxWrpFmDev);
+ if (unlikely(_errno < 0))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("request_irq(%d) = %d", p_LnxWrpFmDev->err_irq, _errno));
+ }
+
+ p_LnxWrpFmDev->res = devm_request_mem_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmPhysBaseAddr, p_LnxWrpFmDev->fmMemSize, "fman");
+ if (unlikely(p_LnxWrpFmDev->res == NULL))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("request_mem_region() failed"));
+
+ p_LnxWrpFmDev->fmBaseAddr = PTR_TO_UINT(devm_ioremap(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmPhysBaseAddr, p_LnxWrpFmDev->fmMemSize));
+ if (unlikely(p_LnxWrpFmDev->fmBaseAddr == 0))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("devm_ioremap() failed"));
+
+ if (SYS_RegisterIoMap((uint64_t)p_LnxWrpFmDev->fmBaseAddr, (uint64_t)p_LnxWrpFmDev->fmPhysBaseAddr, p_LnxWrpFmDev->fmMemSize) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM memory map"));
+
+ dev_res = __devm_request_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, p_LnxWrpFmDev->fmMuramPhysBaseAddr, p_LnxWrpFmDev->fmMuramMemSize, "fman-muram");
+ if (unlikely(dev_res == NULL))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("__devm_request_region() failed"));
+
+ p_LnxWrpFmDev->fmMuramBaseAddr = PTR_TO_UINT(devm_ioremap(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmMuramPhysBaseAddr, p_LnxWrpFmDev->fmMuramMemSize));
+ if (unlikely(p_LnxWrpFmDev->fmMuramBaseAddr == 0))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("devm_ioremap() failed"));
+
+ if (SYS_RegisterIoMap((uint64_t)p_LnxWrpFmDev->fmMuramBaseAddr, (uint64_t)p_LnxWrpFmDev->fmMuramPhysBaseAddr, p_LnxWrpFmDev->fmMuramMemSize) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM MURAM memory map"));
+
+ if (p_LnxWrpFmDev->fmRtcPhysBaseAddr)
+ {
+ dev_res = __devm_request_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, p_LnxWrpFmDev->fmRtcPhysBaseAddr, p_LnxWrpFmDev->fmRtcMemSize, "fman-rtc");
+ if (unlikely(dev_res == NULL))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("__devm_request_region() failed"));
+
+ p_LnxWrpFmDev->fmRtcBaseAddr = PTR_TO_UINT(devm_ioremap(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmRtcPhysBaseAddr, p_LnxWrpFmDev->fmRtcMemSize));
+ if (unlikely(p_LnxWrpFmDev->fmRtcBaseAddr == 0))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("devm_ioremap() failed"));
+
+ if (SYS_RegisterIoMap((uint64_t)p_LnxWrpFmDev->fmRtcBaseAddr, (uint64_t)p_LnxWrpFmDev->fmRtcPhysBaseAddr, p_LnxWrpFmDev->fmRtcMemSize) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM-RTC memory map"));
+ }
+
+#if (DPAA_VERSION >= 11)
+ if (p_LnxWrpFmDev->fmVspPhysBaseAddr) {
+ dev_res = __devm_request_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, p_LnxWrpFmDev->fmVspPhysBaseAddr, p_LnxWrpFmDev->fmVspMemSize, "fman-vsp");
+ if (unlikely(dev_res == NULL))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("__devm_request_region() failed"));
+
+ p_LnxWrpFmDev->fmVspBaseAddr = PTR_TO_UINT(devm_ioremap(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmVspPhysBaseAddr, p_LnxWrpFmDev->fmVspMemSize));
+ if (unlikely(p_LnxWrpFmDev->fmVspBaseAddr == 0))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("devm_ioremap() failed"));
+ }
+#endif
+
+ p_LnxWrpFmDev->fmDevSettings.param.baseAddr = p_LnxWrpFmDev->fmBaseAddr;
+ p_LnxWrpFmDev->fmDevSettings.param.fmId = p_LnxWrpFmDev->id;
+ p_LnxWrpFmDev->fmDevSettings.param.irq = NO_IRQ;
+ p_LnxWrpFmDev->fmDevSettings.param.errIrq = NO_IRQ;
+ p_LnxWrpFmDev->fmDevSettings.param.f_Exception = LnxwrpFmDevExceptionsCb;
+ p_LnxWrpFmDev->fmDevSettings.param.f_BusError = LnxwrpFmDevBusErrorCb;
+ p_LnxWrpFmDev->fmDevSettings.param.h_App = p_LnxWrpFmDev;
+
+ return FillRestFmInfo(p_LnxWrpFmDev);
+}
+
+static t_Error InitFmDev(t_LnxWrpFmDev *p_LnxWrpFmDev)
+{
+ const struct qe_firmware *fw;
+
+ if (!p_LnxWrpFmDev->active)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM not configured!!!"));
+
+ if ((p_LnxWrpFmDev->h_MuramDev = FM_MURAM_ConfigAndInit(p_LnxWrpFmDev->fmMuramBaseAddr, p_LnxWrpFmDev->fmMuramMemSize)) == NULL)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM-MURAM!"));
+
+ /* Loading the fman-controller code */
+ fw = FindFmanMicrocode();
+
+ if (!fw) {
+ /* this forces the reuse of the current IRAM content */
+ p_LnxWrpFmDev->fmDevSettings.param.firmware.size = 0;
+ p_LnxWrpFmDev->fmDevSettings.param.firmware.p_Code = NULL;
+ } else {
+ p_LnxWrpFmDev->fmDevSettings.param.firmware.p_Code =
+ (void *) fw + fw->microcode[0].code_offset;
+ p_LnxWrpFmDev->fmDevSettings.param.firmware.size =
+ sizeof(u32) * fw->microcode[0].count;
+ DBG(INFO, ("Loading fman-controller code version %d.%d.%d",
+ fw->microcode[0].major,
+ fw->microcode[0].minor,
+ fw->microcode[0].revision));
+ }
+
+ p_LnxWrpFmDev->fmDevSettings.param.h_FmMuram = p_LnxWrpFmDev->h_MuramDev;
+
+#if (DPAA_VERSION >= 11)
+ if (p_LnxWrpFmDev->fmVspBaseAddr) {
+ p_LnxWrpFmDev->fmDevSettings.param.vspBaseAddr = p_LnxWrpFmDev->fmVspBaseAddr;
+ p_LnxWrpFmDev->fmDevSettings.param.partVSPBase = 0;
+ p_LnxWrpFmDev->fmDevSettings.param.partNumOfVSPs = FM_VSP_MAX_NUM_OF_ENTRIES;
+ }
+#endif
+
+ if ((p_LnxWrpFmDev->h_Dev = FM_Config(&p_LnxWrpFmDev->fmDevSettings.param)) == NULL)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM"));
+
+
+ if (FM_ConfigResetOnInit(p_LnxWrpFmDev->h_Dev, TRUE) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM"));
+
+#ifdef CONFIG_FMAN_P1023
+ if (FM_ConfigDmaAidOverride(p_LnxWrpFmDev->h_Dev, TRUE) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM"));
+#endif
+
+
+#if defined(CONFIG_FMAN_RESOURCE_ALLOCATION_ALGORITHM) && defined(CONFIG_FMAN_P3040_P4080_P5020)
+ /* Enable 14g w/ jumbo frames following HW suggestion. */
+ FM_ConfigTotalFifoSize(p_LnxWrpFmDev->h_Dev, 128*KILOBYTE);
+#elif defined(CONFIG_FMAN_RESOURCE_ALLOCATION_ALGORITHM) && defined(CONFIG_FMAN_P1023)
+ FM_ConfigTotalFifoSize(p_LnxWrpFmDev->h_Dev, 48*KILOBYTE);
+#endif
+#if (DPAA_VERSION >= 11)
+#define DEFAULT_TOTAL_FIFO_SIZE_FOR_FMAN_V3H 295*KILOBYTE
+ FM_ConfigTotalFifoSize(p_LnxWrpFmDev->h_Dev,
+ DEFAULT_TOTAL_FIFO_SIZE_FOR_FMAN_V3H);
+#endif /* (DPAA_VERSION >= 11) */
+
+ CheckNConfigFmAdvArgs(p_LnxWrpFmDev);
+
+ if (FM_Init(p_LnxWrpFmDev->h_Dev) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM"));
+
+ /* TODO: Why we mask these interrupts? */
+ if (p_LnxWrpFmDev->err_irq == 0) {
+ FM_SetException(p_LnxWrpFmDev->h_Dev, e_FM_EX_DMA_BUS_ERROR,FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_DMA_READ_ECC,FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_DMA_SYSTEM_WRITE_ECC,FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_DMA_FM_WRITE_ECC,FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_DMA_SINGLE_PORT_ECC, FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_FPM_STALL_ON_TASKS , FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_FPM_SINGLE_ECC, FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_FPM_DOUBLE_ECC,FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_QMI_SINGLE_ECC, FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_QMI_DOUBLE_ECC,FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID,FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_BMI_LIST_RAM_ECC,FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_BMI_STORAGE_PROFILE_ECC, FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_BMI_STATISTICS_RAM_ECC, FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_BMI_DISPATCH_RAM_ECC, FALSE);
+ FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_IRAM_ECC,FALSE);
+ /* TODO: FmDisableRamsEcc assert for ramsEccOwners.
+ * FM_SetException(p_LnxWrpFmDev->h_Dev,e_FM_EX_MURAM_ECC,FALSE);*/
+ }
+
+ if (p_LnxWrpFmDev->fmRtcBaseAddr)
+ {
+ t_FmRtcParams fmRtcParam;
+
+ memset(&fmRtcParam, 0, sizeof(fmRtcParam));
+ fmRtcParam.h_App = p_LnxWrpFmDev;
+ fmRtcParam.h_Fm = p_LnxWrpFmDev->h_Dev;
+ fmRtcParam.baseAddress = p_LnxWrpFmDev->fmRtcBaseAddr;
+
+ if(!(p_LnxWrpFmDev->h_RtcDev = FM_RTC_Config(&fmRtcParam)))
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM-RTC"));
+
+ if (FM_RTC_ConfigPeriod(p_LnxWrpFmDev->h_RtcDev, DPA_PTP_NOMINAL_FREQ_PERIOD_NS) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM-RTC"));
+
+ if (FM_RTC_Init(p_LnxWrpFmDev->h_RtcDev) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, ("FM-RTC"));
+ }
+
+ return E_OK;
+}
+
+/* TODO: to be moved back here */
+extern void FreeFmPcdDev(t_LnxWrpFmDev *p_LnxWrpFmDev);
+
+static void FreeFmDev(t_LnxWrpFmDev *p_LnxWrpFmDev)
+{
+ if (!p_LnxWrpFmDev->active)
+ return;
+
+ FreeFmPcdDev(p_LnxWrpFmDev);
+
+ if (p_LnxWrpFmDev->h_RtcDev)
+ FM_RTC_Free(p_LnxWrpFmDev->h_RtcDev);
+
+ if (p_LnxWrpFmDev->h_Dev)
+ FM_Free(p_LnxWrpFmDev->h_Dev);
+
+ if (p_LnxWrpFmDev->h_MuramDev)
+ FM_MURAM_Free(p_LnxWrpFmDev->h_MuramDev);
+
+ if (p_LnxWrpFmDev->fmRtcBaseAddr)
+ {
+ SYS_UnregisterIoMap(p_LnxWrpFmDev->fmRtcBaseAddr);
+ devm_iounmap(p_LnxWrpFmDev->dev, UINT_TO_PTR(p_LnxWrpFmDev->fmRtcBaseAddr));
+ __devm_release_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, p_LnxWrpFmDev->fmRtcPhysBaseAddr, p_LnxWrpFmDev->fmRtcMemSize);
+ }
+ SYS_UnregisterIoMap(p_LnxWrpFmDev->fmMuramBaseAddr);
+ devm_iounmap(p_LnxWrpFmDev->dev, UINT_TO_PTR(p_LnxWrpFmDev->fmMuramBaseAddr));
+ __devm_release_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res, p_LnxWrpFmDev->fmMuramPhysBaseAddr, p_LnxWrpFmDev->fmMuramMemSize);
+ SYS_UnregisterIoMap(p_LnxWrpFmDev->fmBaseAddr);
+ devm_iounmap(p_LnxWrpFmDev->dev, UINT_TO_PTR(p_LnxWrpFmDev->fmBaseAddr));
+ devm_release_mem_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->fmPhysBaseAddr, p_LnxWrpFmDev->fmMemSize);
+ if (p_LnxWrpFmDev->err_irq != 0) {
+ devm_free_irq(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->err_irq, p_LnxWrpFmDev);
+ }
+
+ devm_free_irq(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->irq, p_LnxWrpFmDev);
+}
+
+/* FMan character device file operations */
+extern struct file_operations fm_fops;
+
+static int /*__devinit*/ fm_probe(struct platform_device *of_dev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
+
+ if ((p_LnxWrpFmDev = ReadFmDevTreeNode(of_dev)) == NULL)
+ return -EIO;
+ if (ConfigureFmDev(p_LnxWrpFmDev) != E_OK)
+ return -EIO;
+ if (InitFmDev(p_LnxWrpFmDev) != E_OK)
+ return -EIO;
+
+ /* IOCTL ABI checking */
+ LnxWrpPCDIOCTLEnumChecking();
+ LnxWrpPCDIOCTLTypeChecking();
+
+ Sprint (p_LnxWrpFmDev->name, "%s%d", DEV_FM_NAME, p_LnxWrpFmDev->id);
+
+ /* Register to the /dev for IOCTL API */
+ /* Register dynamically a new major number for the character device: */
+ if ((p_LnxWrpFmDev->major = register_chrdev(0, p_LnxWrpFmDev->name, &fm_fops)) <= 0) {
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Failed to allocate a major number for device \"%s\"", p_LnxWrpFmDev->name));
+ return -EIO;
+ }
+
+ /* Creating classes for FM */
+ DBG(TRACE ,("class_create fm_class"));
+ p_LnxWrpFmDev->fm_class = class_create(THIS_MODULE, p_LnxWrpFmDev->name);
+ if (IS_ERR(p_LnxWrpFmDev->fm_class)) {
+ unregister_chrdev(p_LnxWrpFmDev->major, p_LnxWrpFmDev->name);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("class_create error fm_class"));
+ return -EIO;
+ }
+
+ device_create(p_LnxWrpFmDev->fm_class, NULL, MKDEV(p_LnxWrpFmDev->major, DEV_FM_MINOR_BASE), NULL,
+ "fm%d", p_LnxWrpFmDev->id);
+ device_create(p_LnxWrpFmDev->fm_class, NULL, MKDEV(p_LnxWrpFmDev->major, DEV_FM_PCD_MINOR_BASE), NULL,
+ "fm%d-pcd", p_LnxWrpFmDev->id);
+ dev_set_drvdata(p_LnxWrpFmDev->dev, p_LnxWrpFmDev);
+
+ /* create sysfs entries for stats and regs */
+ if ( fm_sysfs_create(p_LnxWrpFmDev->dev) !=0 )
+ {
+ FreeFmDev(p_LnxWrpFmDev);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Unable to create sysfs entry - fm!!!"));
+ return -EIO;
+ }
+
+ DBG(TRACE, ("FM%d probed", p_LnxWrpFmDev->id));
+
+#if defined(CONFIG_FMAN_RESOURCE_ALLOCATION_ALGORITHM)
+ /* Precalculate resources for FMAN based on number of
+ * FMan ports available
+ */
+ if(fm_set_active_fman_ports(of_dev, p_LnxWrpFmDev)!= 0)
+ return -EIO;
+
+#if defined(CONFIG_FMAN_P3040_P4080_P5020)
+ /* 128K MURAM for p3,p4 and p5 */
+ if(fm_precalculate_fifosizes(
+ p_LnxWrpFmDev,
+ 128*KILOBYTE)
+ != 0)
+ return -EIO;
+#else
+ /* for all other platforms: MURAM Space for fifosize=3/4 * MURAM_SIZE*/
+ if(fm_precalculate_fifosizes(
+ p_LnxWrpFmDev,
+ 48*KILOBYTE)
+ != 0)
+ return -EIO;
+#endif
+ if(fm_precalculate_open_dma(
+ p_LnxWrpFmDev,
+ BMI_MAX_NUM_OF_DMAS, /* max open dmas:dpaa_integration_ext.h */
+ FM_DEFAULT_TX10G_OPENDMA, /* default TX 10g open dmas */
+ FM_DEFAULT_RX10G_OPENDMA, /* default RX 10g open dmas */
+ FM_10G_OPENDMA_MIN_TRESHOLD,/* TX 10g minimum treshold */
+ FM_10G_OPENDMA_MIN_TRESHOLD)/* RX 10g minimum treshold */
+ != 0)
+ return -EIO;
+ if(fm_precalculate_tnums(
+ p_LnxWrpFmDev,
+ BMI_MAX_NUM_OF_TASKS) /* max TNUMS: dpa integration file. */
+ != 0)
+ return -EIO;
+#endif
+
+ return 0;
+}
+
+static int fm_remove(struct platform_device *of_dev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
+ struct device *dev;
+
+ dev = &of_dev->dev;
+ p_LnxWrpFmDev = dev_get_drvdata(dev);
+
+ fm_sysfs_destroy(dev);
+
+ DBG(TRACE, ("destroy fm_class"));
+ device_destroy(p_LnxWrpFmDev->fm_class, MKDEV(p_LnxWrpFmDev->major, DEV_FM_MINOR_BASE));
+ device_destroy(p_LnxWrpFmDev->fm_class, MKDEV(p_LnxWrpFmDev->major, DEV_FM_PCD_MINOR_BASE));
+ class_destroy(p_LnxWrpFmDev->fm_class);
+
+ /* Destroy chardev */
+ unregister_chrdev(p_LnxWrpFmDev->major, p_LnxWrpFmDev->name);
+
+ FreeFmDev(p_LnxWrpFmDev);
+
+ DestroyFmDev(p_LnxWrpFmDev);
+
+ dev_set_drvdata(dev, NULL);
+
+ return 0;
+}
+
+static const struct of_device_id fm_match[] = {
+ {
+ .compatible = "fsl,fman"
+ },
+ {}
+};
+#ifndef MODULE
+MODULE_DEVICE_TABLE(of, fm_match);
+#endif /* !MODULE */
+
+static struct platform_driver fm_driver = {
+ .driver = {
+ .name = "fsl-fman",
+ .of_match_table = fm_match,
+ .owner = THIS_MODULE,
+ },
+ .probe = fm_probe,
+ .remove = fm_remove
+};
+
+t_Handle LNXWRP_FM_Init(void)
+{
+ memset(&lnxWrpFm, 0, sizeof(lnxWrpFm));
+ mutex_init(&lnxwrp_mutex);
+
+ /* Register to the DTB for basic FM API */
+ platform_driver_register(&fm_driver);
+
+ return &lnxWrpFm;
+}
+
+t_Error LNXWRP_FM_Free(t_Handle h_LnxWrpFm)
+{
+ platform_driver_unregister(&fm_driver);
+ mutex_destroy(&lnxwrp_mutex);
+
+ return E_OK;
+}
+
+
+struct fm * fm_bind(struct device *fm_dev)
+{
+ return (struct fm *)(dev_get_drvdata(get_device(fm_dev)));
+}
+EXPORT_SYMBOL(fm_bind);
+
+void fm_unbind(struct fm *fm)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev*)fm;
+
+ put_device(p_LnxWrpFmDev->dev);
+}
+EXPORT_SYMBOL(fm_unbind);
+
+struct resource * fm_get_mem_region(struct fm *fm)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev*)fm;
+
+ return p_LnxWrpFmDev->res;
+}
+EXPORT_SYMBOL(fm_get_mem_region);
+
+void * fm_get_handle(struct fm *fm)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev*)fm;
+
+ return (void *)p_LnxWrpFmDev->h_Dev;
+}
+EXPORT_SYMBOL(fm_get_handle);
+
+void * fm_get_rtc_handle(struct fm *fm)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev*)fm;
+
+ return (void *)p_LnxWrpFmDev->h_RtcDev;
+}
+EXPORT_SYMBOL(fm_get_rtc_handle);
+
+struct fm_port * fm_port_bind (struct device *fm_port_dev)
+{
+ return (struct fm_port *)(dev_get_drvdata(get_device(fm_port_dev)));
+}
+EXPORT_SYMBOL(fm_port_bind);
+
+void fm_port_unbind(struct fm_port *port)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port;
+
+ put_device(p_LnxWrpFmPortDev->dev);
+}
+EXPORT_SYMBOL(fm_port_unbind);
+
+void *fm_port_get_handle(const struct fm_port *port)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port;
+
+ return (void *)p_LnxWrpFmPortDev->h_Dev;
+}
+EXPORT_SYMBOL(fm_port_get_handle);
+
+u64 *fm_port_get_buffer_time_stamp(const struct fm_port *port,
+ const void *data)
+{
+ return FM_PORT_GetBufferTimeStamp(fm_port_get_handle(port),
+ (void *)data);
+}
+EXPORT_SYMBOL(fm_port_get_buffer_time_stamp);
+
+void fm_port_get_base_addr(const struct fm_port *port, uint64_t *base_addr)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port;
+
+ *base_addr = p_LnxWrpFmPortDev->settings.param.baseAddr;
+}
+EXPORT_SYMBOL(fm_port_get_base_addr);
+
+void fm_port_pcd_bind (struct fm_port *port, struct fm_port_pcd_param *params)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port;
+
+ p_LnxWrpFmPortDev->pcd_owner_params.cba = params->cba;
+ p_LnxWrpFmPortDev->pcd_owner_params.cbf = params->cbf;
+ p_LnxWrpFmPortDev->pcd_owner_params.dev = params->dev;
+}
+EXPORT_SYMBOL(fm_port_pcd_bind);
+
+void fm_port_get_buff_layout_ext_params(struct fm_port *port, struct fm_port_params *params)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port;
+ struct device_node *fm_node, *port_node;
+ const uint32_t *uint32_prop;
+ int lenp;
+
+ params->data_align = 0;
+ params->manip_extra_space = 0;
+
+ fm_node = GetFmAdvArgsDevTreeNode(((t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev)->id);
+ if (!fm_node) /* no advance parameters for FMan */
+ return;
+
+ port_node = GetFmPortAdvArgsDevTreeNode(fm_node,
+ p_LnxWrpFmPortDev->settings.param.portType,
+ p_LnxWrpFmPortDev->settings.param.portId);
+ if (!port_node) /* no advance parameters for FMan-Port */
+ return;
+
+ uint32_prop = (uint32_t *)of_get_property(port_node, "buffer-layout", &lenp);
+ if (uint32_prop) {
+ if (WARN_ON(lenp != sizeof(uint32_t)*2))
+ return;
+
+ params->manip_extra_space = (uint8_t)uint32_prop[0];
+ params->data_align = (uint16_t)uint32_prop[1];
+ }
+
+ of_node_put(port_node);
+ of_node_put(fm_node);
+}
+EXPORT_SYMBOL(fm_port_get_buff_layout_ext_params);
+
+int fm_get_tx_port_channel(struct fm_port *port)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port;
+
+ return p_LnxWrpFmPortDev->txCh;
+}
+EXPORT_SYMBOL(fm_get_tx_port_channel);
+
+int fm_port_enable (struct fm_port *port)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port;
+ t_Error err = FM_PORT_Enable(p_LnxWrpFmPortDev->h_Dev);
+
+ return GET_ERROR_TYPE(err);
+}
+EXPORT_SYMBOL(fm_port_enable);
+
+int fm_port_disable(struct fm_port *port)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)port;
+ t_Error err = FM_PORT_Disable(p_LnxWrpFmPortDev->h_Dev);
+
+ return GET_ERROR_TYPE(err);
+}
+EXPORT_SYMBOL(fm_port_disable);
+
+int fm_port_set_rate_limit(struct fm_port *port,
+ uint16_t max_burst_size,
+ uint32_t rate_limit)
+{
+ t_FmPortRateLimit param;
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port;
+ int err = 0;
+
+ param.maxBurstSize = max_burst_size;
+ param.rateLimit = rate_limit;
+ param.rateLimitDivider = 0;
+
+ err = FM_PORT_SetRateLimit(p_LnxWrpFmPortDev->h_Dev, &param);
+ return err;
+}
+EXPORT_SYMBOL(fm_port_set_rate_limit);
+
+int fm_port_del_rate_limit(struct fm_port *port)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port;
+
+ FM_PORT_DeleteRateLimit(p_LnxWrpFmPortDev->h_Dev);
+ return 0;
+}
+EXPORT_SYMBOL(fm_port_del_rate_limit);
+
+void FM_PORT_Dsar_DumpRegs(void);
+int ar_showmem(struct file *file, const char __user *buffer,
+ unsigned long count, void *data)
+{
+ FM_PORT_Dsar_DumpRegs();
+ return 2;
+}
+
+struct auto_res_tables_sizes *fm_port_get_autores_maxsize(
+ struct fm_port *port)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port;
+ return &p_LnxWrpFmPortDev->dsar_table_sizes;
+}
+EXPORT_SYMBOL(fm_port_get_autores_maxsize);
+
+int fm_port_enter_autores_for_deepsleep(struct fm_port *port,
+ struct auto_res_port_params *params)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port;
+ /*Register other under /proc/autoresponse */
+ if (WARN_ON(sizeof(t_FmPortDsarParams) != sizeof(struct auto_res_port_params)))
+ return -EFAULT;
+
+ FM_PORT_EnterDsar(p_LnxWrpFmPortDev->h_Dev, (t_FmPortDsarParams*)params);
+ return 0;
+}
+EXPORT_SYMBOL(fm_port_enter_autores_for_deepsleep);
+
+void fm_port_exit_auto_res_for_deep_sleep(struct fm_port *port_rx,
+ struct fm_port *port_tx)
+{
+ FM_PORT_ExitDsar(port_rx, port_tx);
+}
+EXPORT_SYMBOL(fm_port_exit_auto_res_for_deep_sleep);
+
+int fm_port_get_autores_stats(struct fm_port *port,
+ struct auto_res_port_stats *stats)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port;
+ if (WARN_ON(sizeof(t_FmPortDsarStats) != sizeof(struct auto_res_port_stats)))
+ return -EFAULT;
+ return FM_PORT_GetDsarStats(p_LnxWrpFmPortDev->h_Dev, (t_FmPortDsarStats*)stats);
+}
+EXPORT_SYMBOL(fm_port_get_autores_stats);
+
+int fm_port_suspend(struct fm_port *port)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port;
+ if (!FM_PORT_IsInDsar(p_LnxWrpFmPortDev->h_Dev))
+ return FM_PORT_Disable(p_LnxWrpFmPortDev->h_Dev);
+ else
+ return 0;
+}
+EXPORT_SYMBOL(fm_port_suspend);
+
+int fm_port_resume(struct fm_port *port)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port;
+ if (!FM_PORT_IsInDsar(p_LnxWrpFmPortDev->h_Dev))
+ return FM_PORT_Enable(p_LnxWrpFmPortDev->h_Dev);
+ else
+ return 0;
+}
+EXPORT_SYMBOL(fm_port_resume);
+
+bool fm_port_is_in_auto_res_mode(struct fm_port *port)
+{
+ return FM_PORT_IsInDsar(port);
+}
+EXPORT_SYMBOL(fm_port_is_in_auto_res_mode);
+
+#ifdef CONFIG_FMAN_PFC
+int fm_port_set_pfc_priorities_mapping_to_qman_wq(struct fm_port *port,
+ uint8_t prio, uint8_t wq)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port;
+ int err;
+ int _errno;
+
+ err = FM_PORT_SetPfcPrioritiesMappingToQmanWQ(p_LnxWrpFmPortDev->h_Dev,
+ prio, wq);
+ _errno = -GET_ERROR_TYPE(err);
+ if (unlikely(_errno < 0))
+ pr_err("FM_PORT_SetPfcPrioritiesMappingToQmanWQ() = 0x%08x\n", err);
+
+ return _errno;
+}
+EXPORT_SYMBOL(fm_port_set_pfc_priorities_mapping_to_qman_wq);
+#endif
+
+int fm_mac_set_exception(struct fm_mac_dev *fm_mac_dev,
+ e_FmMacExceptions exception, bool enable)
+{
+ int err;
+ int _errno;
+
+ err = FM_MAC_SetException(fm_mac_dev, exception, enable);
+
+ _errno = -GET_ERROR_TYPE(err);
+ if (unlikely(_errno < 0))
+ pr_err("FM_MAC_SetException() = 0x%08x\n", err);
+
+ return _errno;
+}
+EXPORT_SYMBOL(fm_mac_set_exception);
+
+int fm_mac_free(struct fm_mac_dev *fm_mac_dev)
+{
+ int err;
+ int _error;
+
+ err = FM_MAC_Free(fm_mac_dev);
+ _error = -GET_ERROR_TYPE(err);
+
+ if (unlikely(_error < 0))
+ pr_err("FM_MAC_Free() = 0x%08x\n", err);
+
+ return _error;
+}
+EXPORT_SYMBOL(fm_mac_free);
+
+struct fm_mac_dev *fm_mac_config(t_FmMacParams *params)
+{
+ struct fm_mac_dev *fm_mac_dev;
+
+ fm_mac_dev = FM_MAC_Config(params);
+ if (unlikely(fm_mac_dev == NULL))
+ pr_err("FM_MAC_Config() failed\n");
+
+ return fm_mac_dev;
+}
+EXPORT_SYMBOL(fm_mac_config);
+
+int fm_mac_config_max_frame_length(struct fm_mac_dev *fm_mac_dev,
+ int len)
+{
+ int err;
+ int _errno;
+
+ err = FM_MAC_ConfigMaxFrameLength(fm_mac_dev, len);
+ _errno = -GET_ERROR_TYPE(err);
+ if (unlikely(_errno < 0))
+ pr_err("FM_MAC_ConfigMaxFrameLength() = 0x%08x\n", err);
+
+ return _errno;
+}
+EXPORT_SYMBOL(fm_mac_config_max_frame_length);
+
+int fm_mac_config_pad_and_crc(struct fm_mac_dev *fm_mac_dev, bool enable)
+{
+ int err;
+ int _errno;
+
+ err = FM_MAC_ConfigPadAndCrc(fm_mac_dev, enable);
+ _errno = -GET_ERROR_TYPE(err);
+ if (unlikely(_errno < 0))
+ pr_err("FM_MAC_ConfigPadAndCrc() = 0x%08x\n", err);
+
+ return _errno;
+}
+EXPORT_SYMBOL(fm_mac_config_pad_and_crc);
+
+int fm_mac_config_half_duplex(struct fm_mac_dev *fm_mac_dev, bool enable)
+{
+ int err;
+ int _errno;
+
+ err = FM_MAC_ConfigHalfDuplex(fm_mac_dev, enable);
+ _errno = -GET_ERROR_TYPE(err);
+ if (unlikely(_errno < 0))
+ pr_err("FM_MAC_ConfigHalfDuplex() = 0x%08x\n", err);
+
+ return _errno;
+}
+EXPORT_SYMBOL(fm_mac_config_half_duplex);
+
+int fm_mac_config_reset_on_init(struct fm_mac_dev *fm_mac_dev, bool enable)
+{
+ int err;
+ int _errno;
+
+ err = FM_MAC_ConfigResetOnInit(fm_mac_dev, enable);
+ _errno = -GET_ERROR_TYPE(err);
+ if (unlikely(_errno < 0))
+ pr_err("FM_MAC_ConfigResetOnInit() = 0x%08x\n", err);
+
+ return _errno;
+}
+EXPORT_SYMBOL(fm_mac_config_reset_on_init);
+
+int fm_mac_init(struct fm_mac_dev *fm_mac_dev)
+{
+ int err;
+ int _errno;
+
+ err = FM_MAC_Init(fm_mac_dev);
+ _errno = -GET_ERROR_TYPE(err);
+ if (unlikely(_errno < 0))
+ pr_err("FM_MAC_Init() = 0x%08x\n", err);
+
+ return _errno;
+}
+EXPORT_SYMBOL(fm_mac_init);
+
+int fm_mac_get_version(struct fm_mac_dev *fm_mac_dev, uint32_t *version)
+{
+ int err;
+ int _errno;
+
+ err = FM_MAC_GetVesrion(fm_mac_dev, version);
+ _errno = -GET_ERROR_TYPE(err);
+ if (unlikely(_errno < 0))
+ pr_err("FM_MAC_GetVesrion() = 0x%08x\n", err);
+
+ return _errno;
+}
+EXPORT_SYMBOL(fm_mac_get_version);
+
+int fm_mac_enable(struct fm_mac_dev *fm_mac_dev)
+{
+ int _errno;
+ t_Error err;
+
+ err = FM_MAC_Enable(fm_mac_dev, e_COMM_MODE_RX_AND_TX);
+ _errno = -GET_ERROR_TYPE(err);
+ if (unlikely(_errno < 0))
+ pr_err("FM_MAC_Enable() = 0x%08x\n", err);
+
+ return _errno;
+}
+EXPORT_SYMBOL(fm_mac_enable);
+
+int fm_mac_disable(struct fm_mac_dev *fm_mac_dev)
+{
+ int _errno;
+ t_Error err;
+
+ err = FM_MAC_Disable(fm_mac_dev, e_COMM_MODE_RX_AND_TX);
+ _errno = -GET_ERROR_TYPE(err);
+ if (unlikely(_errno < 0))
+ pr_err("FM_MAC_Disable() = 0x%08x\n", err);
+
+ return _errno;
+}
+EXPORT_SYMBOL(fm_mac_disable);
+
+int fm_mac_set_promiscuous(struct fm_mac_dev *fm_mac_dev,
+ bool enable)
+{
+ int _errno;
+ t_Error err;
+
+ err = FM_MAC_SetPromiscuous(fm_mac_dev, enable);
+ _errno = -GET_ERROR_TYPE(err);
+ if (unlikely(_errno < 0))
+ pr_err("FM_MAC_SetPromiscuous() = 0x%08x\n", err);
+
+ return _errno;
+}
+EXPORT_SYMBOL(fm_mac_set_promiscuous);
+
+int fm_mac_remove_hash_mac_addr(struct fm_mac_dev *fm_mac_dev,
+ t_EnetAddr *mac_addr)
+{
+ int _errno;
+ t_Error err;
+
+ err = FM_MAC_RemoveHashMacAddr(fm_mac_dev, mac_addr);
+ _errno = -GET_ERROR_TYPE(err);
+ if (_errno < 0) {
+ pr_err("FM_MAC_RemoveHashMacAddr() = 0x%08x\n", err);
+ return _errno;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(fm_mac_remove_hash_mac_addr);
+
+int fm_mac_add_hash_mac_addr(struct fm_mac_dev *fm_mac_dev,
+ t_EnetAddr *mac_addr)
+{
+ int _errno;
+ t_Error err;
+
+ err = FM_MAC_AddHashMacAddr(fm_mac_dev, mac_addr);
+ _errno = -GET_ERROR_TYPE(err);
+ if (_errno < 0) {
+ pr_err("FM_MAC_AddHashMacAddr() = 0x%08x\n", err);
+ return _errno;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(fm_mac_add_hash_mac_addr);
+
+int fm_mac_modify_mac_addr(struct fm_mac_dev *fm_mac_dev,
+ uint8_t *addr)
+{
+ int _errno;
+ t_Error err;
+
+ err = FM_MAC_ModifyMacAddr(fm_mac_dev, (t_EnetAddr *)addr);
+ _errno = -GET_ERROR_TYPE(err);
+ if (_errno < 0)
+ pr_err("FM_MAC_ModifyMacAddr() = 0x%08x\n", err);
+
+ return _errno;
+}
+EXPORT_SYMBOL(fm_mac_modify_mac_addr);
+
+int fm_mac_adjust_link(struct fm_mac_dev *fm_mac_dev,
+ bool link, int speed, bool duplex)
+{
+ int _errno;
+ t_Error err;
+
+ if (!link) {
+#if (DPAA_VERSION < 11)
+ FM_MAC_RestartAutoneg(fm_mac_dev);
+#endif
+ return 0;
+ }
+
+ err = FM_MAC_AdjustLink(fm_mac_dev, speed, duplex);
+ _errno = -GET_ERROR_TYPE(err);
+ if (unlikely(_errno < 0))
+ pr_err("FM_MAC_AdjustLink() = 0x%08x\n", err);
+
+ return _errno;
+}
+EXPORT_SYMBOL(fm_mac_adjust_link);
+
+int fm_mac_enable_1588_time_stamp(struct fm_mac_dev *fm_mac_dev)
+{
+ int _errno;
+ t_Error err;
+
+ err = FM_MAC_Enable1588TimeStamp(fm_mac_dev);
+ _errno = -GET_ERROR_TYPE(err);
+ if (unlikely(_errno < 0))
+ pr_err("FM_MAC_Enable1588TimeStamp() = 0x%08x\n", err);
+ return _errno;
+}
+EXPORT_SYMBOL(fm_mac_enable_1588_time_stamp);
+
+int fm_mac_disable_1588_time_stamp(struct fm_mac_dev *fm_mac_dev)
+{
+ int _errno;
+ t_Error err;
+
+ err = FM_MAC_Disable1588TimeStamp(fm_mac_dev);
+ _errno = -GET_ERROR_TYPE(err);
+ if (unlikely(_errno < 0))
+ pr_err("FM_MAC_Disable1588TimeStamp() = 0x%08x\n", err);
+ return _errno;
+}
+EXPORT_SYMBOL(fm_mac_disable_1588_time_stamp);
+
+int fm_mac_set_rx_pause_frames(
+ struct fm_mac_dev *fm_mac_dev, bool en)
+{
+ int _errno;
+ t_Error err;
+
+ /* if rx pause is enabled, do NOT ignore pause frames */
+ err = FM_MAC_SetRxIgnorePauseFrames(fm_mac_dev, !en);
+
+ _errno = -GET_ERROR_TYPE(err);
+ if (_errno < 0)
+ pr_err("FM_MAC_SetRxIgnorePauseFrames() = 0x%08x\n", err);
+
+ return _errno;
+}
+EXPORT_SYMBOL(fm_mac_set_rx_pause_frames);
+
+#ifdef CONFIG_FMAN_PFC
+int fm_mac_set_tx_pause_frames(struct fm_mac_dev *fm_mac_dev,
+ bool en)
+{
+ int _errno, i;
+ t_Error err;
+
+ if (en)
+ for (i = 0; i < CONFIG_FMAN_PFC_COS_COUNT; i++) {
+ err = FM_MAC_SetTxPauseFrames(fm_mac_dev,
+ i, fsl_fm_pfc_quanta[i],
+ FSL_FM_PAUSE_THRESH_DEFAULT);
+ _errno = -GET_ERROR_TYPE(err);
+ if (_errno < 0) {
+ pr_err("FM_MAC_SetTxPauseFrames() = 0x%08x\n", err);
+ return _errno;
+ }
+ }
+ else
+ for (i = 0; i < CONFIG_FMAN_PFC_COS_COUNT; i++) {
+ err = FM_MAC_SetTxPauseFrames(fm_mac_dev,
+ i, FSL_FM_PAUSE_TIME_DISABLE,
+ FSL_FM_PAUSE_THRESH_DEFAULT);
+ _errno = -GET_ERROR_TYPE(err);
+ if (_errno < 0) {
+ pr_err("FM_MAC_SetTxPauseFrames() = 0x%08x\n", err);
+ return _errno;
+ }
+ }
+
+ return _errno;
+}
+#else
+int fm_mac_set_tx_pause_frames(struct fm_mac_dev *fm_mac_dev,
+ bool en)
+{
+ int _errno;
+ t_Error err;
+
+ if (en)
+ err = FM_MAC_SetTxAutoPauseFrames(fm_mac_dev,
+ FSL_FM_PAUSE_TIME_ENABLE);
+ else
+ err = FM_MAC_SetTxAutoPauseFrames(fm_mac_dev,
+ FSL_FM_PAUSE_TIME_DISABLE);
+
+ _errno = -GET_ERROR_TYPE(err);
+ if (_errno < 0)
+ pr_err("FM_MAC_SetTxAutoPauseFrames() = 0x%08x\n", err);
+
+ return _errno;
+}
+#endif
+EXPORT_SYMBOL(fm_mac_set_tx_pause_frames);
+
+int fm_rtc_enable(struct fm *fm_dev)
+{
+ int _errno;
+ t_Error err;
+
+ err = FM_RTC_Enable(fm_get_rtc_handle(fm_dev), 0);
+ _errno = -GET_ERROR_TYPE(err);
+ if (unlikely(_errno < 0))
+ pr_err("FM_RTC_Enable = 0x%08x\n", err);
+
+ return _errno;
+}
+EXPORT_SYMBOL(fm_rtc_enable);
+
+int fm_rtc_disable(struct fm *fm_dev)
+{
+ int _errno;
+ t_Error err;
+
+ err = FM_RTC_Disable(fm_get_rtc_handle(fm_dev));
+ _errno = -GET_ERROR_TYPE(err);
+ if (unlikely(_errno < 0))
+ pr_err("FM_RTC_Disable = 0x%08x\n", err);
+
+ return _errno;
+}
+EXPORT_SYMBOL(fm_rtc_disable);
+
+int fm_rtc_get_cnt(struct fm *fm_dev, uint64_t *ts)
+{
+ int _errno;
+ t_Error err;
+
+ err = FM_RTC_GetCurrentTime(fm_get_rtc_handle(fm_dev), ts);
+ _errno = -GET_ERROR_TYPE(err);
+ if (unlikely(_errno < 0))
+ pr_err("FM_RTC_GetCurrentTime = 0x%08x\n", err);
+
+ return _errno;
+}
+EXPORT_SYMBOL(fm_rtc_get_cnt);
+
+int fm_rtc_set_cnt(struct fm *fm_dev, uint64_t ts)
+{
+ int _errno;
+ t_Error err;
+
+ err = FM_RTC_SetCurrentTime(fm_get_rtc_handle(fm_dev), ts);
+ _errno = -GET_ERROR_TYPE(err);
+ if (unlikely(_errno < 0))
+ pr_err("FM_RTC_SetCurrentTime = 0x%08x\n", err);
+
+ return _errno;
+}
+EXPORT_SYMBOL(fm_rtc_set_cnt);
+
+int fm_rtc_get_drift(struct fm *fm_dev, uint32_t *drift)
+{
+ int _errno;
+ t_Error err;
+
+ err = FM_RTC_GetFreqCompensation(fm_get_rtc_handle(fm_dev),
+ drift);
+ _errno = -GET_ERROR_TYPE(err);
+ if (unlikely(_errno < 0))
+ pr_err("FM_RTC_GetFreqCompensation = 0x%08x\n", err);
+
+ return _errno;
+}
+EXPORT_SYMBOL(fm_rtc_get_drift);
+
+int fm_rtc_set_drift(struct fm *fm_dev, uint32_t drift)
+{
+ int _errno;
+ t_Error err;
+
+ err = FM_RTC_SetFreqCompensation(fm_get_rtc_handle(fm_dev),
+ drift);
+ _errno = -GET_ERROR_TYPE(err);
+ if (unlikely(_errno < 0))
+ pr_err("FM_RTC_SetFreqCompensation = 0x%08x\n", err);
+
+ return _errno;
+}
+EXPORT_SYMBOL(fm_rtc_set_drift);
+
+int fm_rtc_set_alarm(struct fm *fm_dev, uint32_t id,
+ uint64_t time)
+{
+ t_FmRtcAlarmParams alarm;
+ int _errno;
+ t_Error err;
+
+ alarm.alarmId = id;
+ alarm.alarmTime = time;
+ alarm.f_AlarmCallback = NULL;
+ err = FM_RTC_SetAlarm(fm_get_rtc_handle(fm_dev),
+ &alarm);
+ _errno = -GET_ERROR_TYPE(err);
+ if (unlikely(_errno < 0))
+ pr_err("FM_RTC_SetAlarm = 0x%08x\n", err);
+
+ return _errno;
+}
+EXPORT_SYMBOL(fm_rtc_set_alarm);
+
+int fm_rtc_set_fiper(struct fm *fm_dev, uint32_t id,
+ uint64_t fiper)
+{
+ t_FmRtcPeriodicPulseParams pp;
+ int _errno;
+ t_Error err;
+
+ pp.periodicPulseId = id;
+ pp.periodicPulsePeriod = fiper;
+ pp.f_PeriodicPulseCallback = NULL;
+ err = FM_RTC_SetPeriodicPulse(fm_get_rtc_handle(fm_dev), &pp);
+ _errno = -GET_ERROR_TYPE(err);
+ if (unlikely(_errno < 0))
+ pr_err("FM_RTC_SetPeriodicPulse = 0x%08x\n", err);
+
+ return _errno;
+}
+EXPORT_SYMBOL(fm_rtc_set_fiper);
+
+int fm_mac_set_wol(struct fm_port *port, struct fm_mac_dev *fm_mac_dev, bool en)
+{
+ int _errno;
+ t_Error err;
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port;
+
+ /* Do not set WoL on AR ports */
+ if (FM_PORT_IsInDsar(p_LnxWrpFmPortDev->h_Dev)) {
+ printk(KERN_WARNING "Port is AutoResponse enabled! WoL will not be set on this port!\n");
+ return 0;
+ }
+
+ err = FM_MAC_SetWakeOnLan(fm_mac_dev, en);
+
+ _errno = -GET_ERROR_TYPE(err);
+ if (_errno < 0)
+ pr_err("FM_MAC_SetWakeOnLan() = 0x%08x\n", err);
+
+ return _errno;
+}
+EXPORT_SYMBOL(fm_mac_set_wol);
+
+void fm_mutex_lock(void)
+{
+ mutex_lock(&lnxwrp_mutex);
+}
+EXPORT_SYMBOL(fm_mutex_lock);
+
+void fm_mutex_unlock(void)
+{
+ mutex_unlock(&lnxwrp_mutex);
+}
+EXPORT_SYMBOL(fm_mutex_unlock);
+
+static t_Handle h_FmLnxWrp;
+
+static int __init __cold fm_load (void)
+{
+ if ((h_FmLnxWrp = LNXWRP_FM_Init()) == NULL)
+ {
+ printk("Failed to init FM wrapper!\n");
+ return -ENODEV;
+ }
+
+ printk(KERN_CRIT "Freescale FM module ("__DATE__ ":"__TIME__")," \
+ " FMD API version %d.%d.%d\n",
+ FMD_API_VERSION_MAJOR,
+ FMD_API_VERSION_MINOR,
+ FMD_API_VERSION_RESPIN);
+ return 0;
+}
+
+static void __exit __cold fm_unload (void)
+{
+ if (h_FmLnxWrp)
+ LNXWRP_FM_Free(h_FmLnxWrp);
+}
+
+module_init (fm_load);
+module_exit (fm_unload);
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.h b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.h
new file mode 100644
index 0000000..9c657ac
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.h
@@ -0,0 +1,290 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ @File lnxwrp_fm.h
+
+ @Author Shlomi Gridish
+
+ @Description FM Linux wrapper functions.
+
+*/
+
+#ifndef __LNXWRP_FM_H__
+#define __LNXWRP_FM_H__
+
+#include <linux/fsl_qman.h> /* struct qman_fq */
+
+#include "std_ext.h"
+#include "error_ext.h"
+#include "list_ext.h"
+
+#include "lnxwrp_fm_ext.h"
+
+#define FM_MAX_NUM_OF_ADV_SETTINGS 10
+
+#define LNXWRP_FM_NUM_OF_SHARED_PROFILES 16
+
+#if defined(CONFIG_FMAN_DISABLE_OH_TO_REUSE_RESOURCES)
+#define FM_10G_OPENDMA_MIN_TRESHOLD 8 /* 10g minimum treshold if only HC is enabled and no OH port enabled */
+#define FM_OPENDMA_RX_TX_RAPORT 2 /* RX = 2*TX */
+#else
+#define FM_10G_OPENDMA_MIN_TRESHOLD 7 /* 10g minimum treshold if 7 OH ports are enabled */
+#define FM_OPENDMA_RX_TX_RAPORT 1 /* RX = TX */
+#endif
+#define FM_DEFAULT_TX10G_OPENDMA 8 /* default TX 10g open dmas */
+#define FM_DEFAULT_RX10G_OPENDMA 8 /* default RX 10g open dmas */
+
+#define FRAG_MANIP_SPACE 128
+#define FRAG_DATA_ALIGN 64
+
+#ifndef CONFIG_FSL_FM_MAX_FRAME_SIZE
+#define CONFIG_FSL_FM_MAX_FRAME_SIZE 0
+#endif
+
+#ifndef CONFIG_FSL_FM_RX_EXTRA_HEADROOM
+#define CONFIG_FSL_FM_RX_EXTRA_HEADROOM 16
+#endif
+
+typedef enum {
+ e_NO_PCD = 0,
+ e_FM_PCD_3_TUPLE
+} e_LnxWrpFmPortPcdDefUseCase;
+
+
+typedef struct t_FmTestFq {
+ struct qman_fq fq_base;
+ t_Handle h_Arg;
+} t_FmTestFq;
+
+typedef struct {
+ uint8_t id; /* sw port id, see SW_PORT_ID_TO_HW_PORT_ID() in fm_common.h */
+ int minor;
+ char name[20];
+ bool active;
+ uint64_t phys_baseAddr;
+ uint64_t baseAddr; /* Port's *virtual* address */
+ uint32_t memSize;
+ t_WrpFmPortDevSettings settings;
+ t_FmExtPools opExtPools;
+ uint8_t totalNumOfSchemes;
+ uint8_t schemesBase;
+ uint8_t numOfSchemesUsed;
+ uint32_t pcdBaseQ;
+ uint16_t pcdNumOfQs;
+ struct fm_port_pcd_param pcd_owner_params;
+ e_LnxWrpFmPortPcdDefUseCase defPcd;
+ t_Handle h_DefNetEnv;
+ t_Handle h_Schemes[FM_PCD_KG_NUM_OF_SCHEMES];
+ t_FmBufferPrefixContent buffPrefixContent;
+ t_Handle h_Dev;
+ t_Handle h_DfltVsp;
+ t_Handle h_LnxWrpFmDev;
+ uint16_t txCh;
+ struct device *dev;
+ struct device_attribute *dev_attr_stats;
+ struct device_attribute *dev_attr_regs;
+ struct device_attribute *dev_attr_bmi_regs;
+ struct device_attribute *dev_attr_qmi_regs;
+#if (DPAA_VERSION >= 11)
+ struct device_attribute *dev_attr_ipv4_opt;
+#endif
+ struct device_attribute *dev_attr_dsar_regs;
+ struct device_attribute *dev_attr_dsar_mem;
+ struct auto_res_tables_sizes dsar_table_sizes;
+} t_LnxWrpFmPortDev;
+
+typedef struct {
+ uint8_t id;
+ bool active;
+ uint64_t baseAddr;
+ uint32_t memSize;
+ t_WrpFmMacDevSettings settings;
+ t_Handle h_Dev;
+ t_Handle h_LnxWrpFmDev;
+} t_LnxWrpFmMacDev;
+
+/* information about all active ports for an FMan.
+ * !Some ports may be disabled by u-boot, thus will not be available */
+struct fm_active_ports {
+ uint32_t num_oh_ports;
+ uint32_t num_tx_ports;
+ uint32_t num_rx_ports;
+ uint32_t num_tx25_ports;
+ uint32_t num_rx25_ports;
+ uint32_t num_tx10_ports;
+ uint32_t num_rx10_ports;
+};
+
+/* FMan resources precalculated at fm probe based
+ * on available FMan port. */
+struct fm_resource_settings {
+ /* buffers - fifo sizes */
+ uint32_t tx1g_num_buffers;
+ uint32_t rx1g_num_buffers;
+ uint32_t tx2g5_num_buffers; /* Not supported yet by LLD */
+ uint32_t rx2g5_num_buffers; /* Not supported yet by LLD */
+ uint32_t tx10g_num_buffers;
+ uint32_t rx10g_num_buffers;
+ uint32_t oh_num_buffers;
+ uint32_t shared_ext_buffers;
+
+ /* open DMAs */
+ uint32_t tx_1g_dmas;
+ uint32_t rx_1g_dmas;
+ uint32_t tx_2g5_dmas; /* Not supported yet by LLD */
+ uint32_t rx_2g5_dmas; /* Not supported yet by LLD */
+ uint32_t tx_10g_dmas;
+ uint32_t rx_10g_dmas;
+ uint32_t oh_dmas;
+ uint32_t shared_ext_open_dma;
+
+ /* Tnums */
+ uint32_t tx_1g_tnums;
+ uint32_t rx_1g_tnums;
+ uint32_t tx_2g5_tnums; /* Not supported yet by LLD */
+ uint32_t rx_2g5_tnums; /* Not supported yet by LLD */
+ uint32_t tx_10g_tnums;
+ uint32_t rx_10g_tnums;
+ uint32_t oh_tnums;
+ uint32_t shared_ext_tnums;
+};
+
+typedef struct {
+ uint8_t id;
+ char name[10];
+ bool active;
+ bool pcdActive;
+ bool prsActive;
+ bool kgActive;
+ bool ccActive;
+ bool plcrActive;
+ e_LnxWrpFmPortPcdDefUseCase defPcd;
+ uint32_t usedSchemes;
+ uint8_t totalNumOfSharedSchemes;
+ uint8_t sharedSchemesBase;
+ uint8_t numOfSchemesUsed;
+ uint8_t defNetEnvId;
+ uint64_t fmPhysBaseAddr;
+ uint64_t fmBaseAddr;
+ uint32_t fmMemSize;
+ uint64_t fmMuramPhysBaseAddr;
+ uint64_t fmMuramBaseAddr;
+ uint32_t fmMuramMemSize;
+ uint64_t fmRtcPhysBaseAddr;
+ uint64_t fmRtcBaseAddr;
+ uint32_t fmRtcMemSize;
+ uint64_t fmVspPhysBaseAddr;
+ uint64_t fmVspBaseAddr;
+ uint32_t fmVspMemSize;
+ int irq;
+ int err_irq;
+ t_WrpFmDevSettings fmDevSettings;
+ t_WrpFmPcdDevSettings fmPcdDevSettings;
+ t_Handle h_Dev;
+ uint16_t hcCh;
+
+ t_Handle h_MuramDev;
+ t_Handle h_PcdDev;
+ t_Handle h_RtcDev;
+
+ t_LnxWrpFmPortDev hcPort;
+ t_LnxWrpFmPortDev opPorts[FM_MAX_NUM_OF_OH_PORTS-1];
+ t_LnxWrpFmPortDev rxPorts[FM_MAX_NUM_OF_RX_PORTS];
+ t_LnxWrpFmPortDev txPorts[FM_MAX_NUM_OF_TX_PORTS];
+ t_LnxWrpFmMacDev macs[FM_MAX_NUM_OF_MACS];
+ struct fm_active_ports fm_active_ports_info;
+ struct fm_resource_settings fm_resource_settings_info;
+
+ struct device *dev;
+ struct resource *res;
+ int major;
+ struct class *fm_class;
+ struct device_attribute *dev_attr_stats;
+ struct device_attribute *dev_attr_regs;
+
+ struct device_attribute *dev_pcd_attr_stats;
+ struct device_attribute *dev_plcr_attr_regs;
+ struct device_attribute *dev_prs_attr_regs;
+ struct device_attribute *dev_fm_fpm_attr_regs;
+ struct device_attribute *dev_fm_kg_attr_regs;
+ struct device_attribute *dev_fm_kg_pe_attr_regs;
+ struct device_attribute *dev_attr_muram_free_size;
+ struct device_attribute *dev_attr_fm_ctrl_code_ver;
+
+
+ struct qman_fq *hc_tx_conf_fq, *hc_tx_err_fq, *hc_tx_fq;
+} t_LnxWrpFmDev;
+
+typedef struct {
+ t_LnxWrpFmDev *p_FmDevs[INTG_MAX_NUM_OF_FM];
+} t_LnxWrpFm;
+#define LNXWRP_FM_OBJECT(ptr) LIST_OBJECT(ptr, t_LnxWrpFm, fms[((t_LnxWrpFmDev *)ptr)->id])
+
+
+t_Error LnxwrpFmIOCTL(t_LnxWrpFmDev *p_LnxWrpFmDev, unsigned int cmd, unsigned long arg, bool compat);
+t_Error LnxwrpFmPortIOCTL(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev, unsigned int cmd, unsigned long arg, bool compat);
+
+
+#if 0
+static __inline__ t_Error AllocSchemesForPort(t_LnxWrpFmDev *p_LnxWrpFmDev, uint8_t numSchemes, uint8_t *p_BaseSchemeNum)
+{
+ uint32_t schemeMask;
+ uint8_t i;
+
+ if (!numSchemes)
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG);
+
+ schemeMask = 0x80000000;
+ *p_BaseSchemeNum = 0xff;
+
+ for (i=0; schemeMask && numSchemes; schemeMask>>=1, i++)
+ if ((p_LnxWrpFmDev->usedSchemes & schemeMask) == 0)
+ {
+ p_LnxWrpFmDev->usedSchemes |= schemeMask;
+ numSchemes--;
+ if (*p_BaseSchemeNum==0xff)
+ *p_BaseSchemeNum = i;
+ }
+ else if (*p_BaseSchemeNum!=0xff)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("Fragmentation on schemes array!!!"));
+
+ if (numSchemes)
+ RETURN_ERROR(MINOR, E_FULL, ("schemes!!!"));
+ return E_OK;
+}
+#endif
+
+void LnxWrpPCDIOCTLTypeChecking(void);
+void LnxWrpPCDIOCTLEnumChecking(void);
+
+#endif /* __LNXWRP_FM_H__ */
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm_port.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm_port.c
new file mode 100644
index 0000000..2c464cb
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm_port.c
@@ -0,0 +1,1418 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ @File lnxwrp_fm_port.c
+
+ @Description FMD wrapper - FMan port functions.
+
+*/
+
+#include <linux/version.h>
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+#define MODVERSIONS
+#endif
+#ifdef MODVERSIONS
+#include <config/modversions.h>
+#endif /* MODVERSIONS */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/cdev.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#include "sprint_ext.h"
+#include "fm_common.h"
+#include "lnxwrp_fsl_fman.h"
+#include "fm_port_ext.h"
+#if (DPAA_VERSION >= 11)
+#include "fm_vsp_ext.h"
+#endif /* DPAA_VERSION >= 11 */
+#include "fm_ioctls.h"
+#include "lnxwrp_resources.h"
+#include "lnxwrp_sysfs_fm_port.h"
+
+#define __ERR_MODULE__ MODULE_FM
+
+extern struct device_node *GetFmAdvArgsDevTreeNode (uint8_t fmIndx);
+
+/* TODO: duplicated, see lnxwrp_fm.c */
+#define ADD_ADV_CONFIG_NO_RET(_func, _param)\
+do {\
+ if (i < max) {\
+ p_Entry = &p_Entrys[i];\
+ p_Entry->p_Function = _func;\
+ _param\
+ i++;\
+ } else {\
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,\
+ ("Number of advanced-configuration entries exceeded"));\
+ } \
+} while (0)
+
+
+static volatile int hcFrmRcv/* = 0 */;
+static spinlock_t lock;
+
+static enum qman_cb_dqrr_result qm_tx_conf_dqrr_cb(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry
+ *dq)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = ((t_FmTestFq *) fq)->h_Arg;
+ unsigned long flags;
+
+ FM_PCD_HcTxConf(p_LnxWrpFmDev->h_PcdDev, (t_DpaaFD *)&dq->fd);
+ spin_lock_irqsave(&lock, flags);
+ hcFrmRcv--;
+ spin_unlock_irqrestore(&lock, flags);
+
+ return qman_cb_dqrr_consume;
+}
+
+static enum qman_cb_dqrr_result qm_tx_dqrr_cb(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry *dq)
+{
+ WARN(1, "FMD: failure at %s:%d/%s()!\n", __FILE__, __LINE__,
+ __func__);
+ return qman_cb_dqrr_consume;
+}
+
+static void qm_err_cb(struct qman_portal *portal,
+ struct qman_fq *fq, const struct qm_mr_entry *msg)
+{
+ WARN(1, "FMD: failure at %s:%d/%s()!\n", __FILE__, __LINE__,
+ __func__);
+}
+
+static struct qman_fq *FqAlloc(t_LnxWrpFmDev * p_LnxWrpFmDev,
+ uint32_t fqid,
+ uint32_t flags, uint16_t channel, uint8_t wq)
+{
+ int _errno;
+ struct qman_fq *fq = NULL;
+ t_FmTestFq *p_FmtFq;
+ struct qm_mcc_initfq initfq;
+
+ p_FmtFq = (t_FmTestFq *) XX_Malloc(sizeof(t_FmTestFq));
+ if (!p_FmtFq) {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FQ obj!!!"));
+ return NULL;
+ }
+
+ p_FmtFq->fq_base.cb.dqrr = ((flags & QMAN_FQ_FLAG_NO_ENQUEUE)
+ ? qm_tx_conf_dqrr_cb
+ : qm_tx_dqrr_cb);
+ p_FmtFq->fq_base.cb.ern = qm_err_cb;
+ /* p_FmtFq->fq_base.cb.fqs = qm_err_cb; */
+ /* qm_err_cb wrongly called when the FQ is parked */
+ p_FmtFq->fq_base.cb.fqs = NULL;
+ p_FmtFq->h_Arg = (t_Handle) p_LnxWrpFmDev;
+ if (fqid == 0) {
+ flags |= QMAN_FQ_FLAG_DYNAMIC_FQID;
+ flags &= ~QMAN_FQ_FLAG_NO_MODIFY;
+ } else {
+ flags &= ~QMAN_FQ_FLAG_DYNAMIC_FQID;
+ }
+
+ if (qman_create_fq(fqid, flags, &p_FmtFq->fq_base)) {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FQ obj - qman_new_fq!!!"));
+ XX_Free(p_FmtFq);
+ return NULL;
+ }
+ fq = &p_FmtFq->fq_base;
+
+ if (!(flags & QMAN_FQ_FLAG_NO_MODIFY)) {
+ initfq.we_mask = QM_INITFQ_WE_DESTWQ;
+ initfq.fqd.dest.channel = channel;
+ initfq.fqd.dest.wq = wq;
+
+ _errno = qman_init_fq(fq, QMAN_INITFQ_FLAG_SCHED, &initfq);
+ if (unlikely(_errno < 0)) {
+ REPORT_ERROR(MAJOR, E_NO_MEMORY,
+ ("FQ obj - qman_init_fq!!!"));
+ qman_destroy_fq(fq, 0);
+ XX_Free(p_FmtFq);
+ return NULL;
+ }
+ }
+
+ DBG(TRACE,
+ ("fqid %d, flags 0x%08x, channel %d, wq %d", qman_fq_fqid(fq),
+ flags, channel, wq));
+
+ return fq;
+}
+
+static void FqFree(struct qman_fq *fq)
+{
+ int _errno;
+
+ _errno = qman_retire_fq(fq, NULL);
+ if (unlikely(_errno < 0))
+ printk(KERN_WARNING "qman_retire_fq(%u) = %d\n", qman_fq_fqid(fq), _errno);
+
+ _errno = qman_oos_fq(fq);
+ if (unlikely(_errno < 0))
+ printk(KERN_WARNING "qman_oos_fq(%u) = %d\n", qman_fq_fqid(fq), _errno);
+
+ qman_destroy_fq(fq, 0);
+ XX_Free((t_FmTestFq *) fq);
+}
+
+static t_Error QmEnqueueCB(t_Handle h_Arg, void *p_Fd)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *) h_Arg;
+ int _errno, timeout = 1000000;
+ unsigned long flags;
+
+ ASSERT_COND(p_LnxWrpFmDev);
+
+ spin_lock_irqsave(&lock, flags);
+ hcFrmRcv++;
+ spin_unlock_irqrestore(&lock, flags);
+
+ _errno = qman_enqueue(p_LnxWrpFmDev->hc_tx_fq, (struct qm_fd *) p_Fd,
+ 0);
+ if (_errno)
+ RETURN_ERROR(MINOR, E_INVALID_STATE,
+ ("qman_enqueue() failed"));
+
+ while (hcFrmRcv && --timeout) {
+ udelay(1);
+ cpu_relax();
+ }
+ if (timeout == 0) {
+ dump_stack();
+ RETURN_ERROR(MINOR, E_WRITE_FAILED,
+ ("timeout waiting for Tx confirmation"));
+ return E_WRITE_FAILED;
+ }
+
+ return E_OK;
+}
+
+static t_LnxWrpFmPortDev *ReadFmPortDevTreeNode(struct platform_device
+ *of_dev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev;
+ struct device_node *fm_node, *port_node;
+ struct resource res;
+ const uint32_t *uint32_prop;
+ int _errno = 0, lenp;
+#ifdef CONFIG_FMAN_P1023
+ static unsigned char have_oh_port/* = 0 */;
+#endif
+
+ port_node = of_node_get(of_dev->dev.of_node);
+
+ /* Get the FM node */
+ fm_node = of_get_parent(port_node);
+ if (unlikely(fm_node == NULL)) {
+ REPORT_ERROR(MAJOR, E_NO_DEVICE,
+ ("of_get_parent() = %d", _errno));
+ return NULL;
+ }
+
+ p_LnxWrpFmDev =
+ dev_get_drvdata(&of_find_device_by_node(fm_node)->dev);
+ of_node_put(fm_node);
+
+ /* if fm_probe() failed, no point in going further with port probing */
+ if (p_LnxWrpFmDev == NULL)
+ return NULL;
+
+ uint32_prop =
+ (uint32_t *) of_get_property(port_node, "cell-index", &lenp);
+ if (unlikely(uint32_prop == NULL)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("of_get_property(%s, cell-index) failed",
+ port_node->full_name));
+ return NULL;
+ }
+ if (WARN_ON(lenp != sizeof(uint32_t)))
+ return NULL;
+ if (of_device_is_compatible(port_node, "fsl,fman-port-oh")) {
+ if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_OH_PORTS)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("of_get_property(%s, cell-index) failed",
+ port_node->full_name));
+ return NULL;
+ }
+
+#ifdef CONFIG_FMAN_P1023
+ /* Beware, this can be done when there is only
+ one FMan to be initialized */
+ if (!have_oh_port) {
+ have_oh_port = 1; /* first OP/HC port
+ is used for host command */
+#else
+ /* Here it is hardcoded the use of the OH port 1
+ (with cell-index 0) */
+ if (*uint32_prop == 0) {
+#endif
+ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->hcPort;
+ p_LnxWrpFmPortDev->id = 0;
+ /*
+ p_LnxWrpFmPortDev->id = *uint32_prop-1;
+ p_LnxWrpFmPortDev->id = *uint32_prop;
+ */
+ p_LnxWrpFmPortDev->settings.param.portType =
+ e_FM_PORT_TYPE_OH_HOST_COMMAND;
+ } else {
+ p_LnxWrpFmPortDev =
+ &p_LnxWrpFmDev->opPorts[*uint32_prop - 1];
+ p_LnxWrpFmPortDev->id = *uint32_prop - 1;
+ p_LnxWrpFmPortDev->settings.param.portType =
+ e_FM_PORT_TYPE_OH_OFFLINE_PARSING;
+ }
+ p_LnxWrpFmPortDev->settings.param.portId = *uint32_prop;
+
+ uint32_prop =
+ (uint32_t *) of_get_property(port_node,
+ "fsl,qman-channel-id",
+ &lenp);
+ if (uint32_prop == NULL) {
+ /*
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("missing fsl,qman-channel-id"));
+ */
+ XX_Print("FM warning: missing fsl,qman-channel-id"
+ " for OH port.\n");
+ return NULL;
+ }
+ if (WARN_ON(lenp != sizeof(uint32_t)))
+ return NULL;
+ p_LnxWrpFmPortDev->txCh = *uint32_prop;
+
+ p_LnxWrpFmPortDev->settings.param.specificParams.nonRxParams.
+ qmChannel = p_LnxWrpFmPortDev->txCh;
+ } else if (of_device_is_compatible(port_node, "fsl,fman-port-1g-tx")) {
+ if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_1G_TX_PORTS)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("of_get_property(%s, cell-index) failed",
+ port_node->full_name));
+ return NULL;
+ }
+ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->txPorts[*uint32_prop];
+
+ p_LnxWrpFmPortDev->id = *uint32_prop;
+ p_LnxWrpFmPortDev->settings.param.portId =
+ p_LnxWrpFmPortDev->id;
+ p_LnxWrpFmPortDev->settings.param.portType = e_FM_PORT_TYPE_TX;
+
+ uint32_prop = (uint32_t *) of_get_property(port_node,
+ "fsl,qman-channel-id", &lenp);
+ if (uint32_prop == NULL) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("missing fsl,qman-channel-id"));
+ return NULL;
+ }
+ if (WARN_ON(lenp != sizeof(uint32_t)))
+ return NULL;
+ p_LnxWrpFmPortDev->txCh = *uint32_prop;
+ p_LnxWrpFmPortDev->
+ settings.param.specificParams.nonRxParams.qmChannel =
+ p_LnxWrpFmPortDev->txCh;
+ } else if (of_device_is_compatible(port_node, "fsl,fman-port-10g-tx")) {
+ if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_10G_TX_PORTS)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("of_get_property(%s, cell-index) failed",
+ port_node->full_name));
+ return NULL;
+ }
+ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->txPorts[*uint32_prop +
+ FM_MAX_NUM_OF_1G_TX_PORTS];
+
+ p_LnxWrpFmPortDev->id = *uint32_prop;
+ p_LnxWrpFmPortDev->settings.param.portId =
+ p_LnxWrpFmPortDev->id;
+ p_LnxWrpFmPortDev->settings.param.portType =
+ e_FM_PORT_TYPE_TX_10G;
+ uint32_prop = (uint32_t *) of_get_property(port_node,
+ "fsl,qman-channel-id", &lenp);
+ if (uint32_prop == NULL) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("missing fsl,qman-channel-id"));
+ return NULL;
+ }
+ if (WARN_ON(lenp != sizeof(uint32_t)))
+ return NULL;
+ p_LnxWrpFmPortDev->txCh = *uint32_prop;
+ p_LnxWrpFmPortDev->settings.param.specificParams.nonRxParams.
+ qmChannel = p_LnxWrpFmPortDev->txCh;
+ } else if (of_device_is_compatible(port_node, "fsl,fman-port-1g-rx")) {
+ if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_1G_RX_PORTS)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("of_get_property(%s, cell-index) failed",
+ port_node->full_name));
+ return NULL;
+ }
+ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->rxPorts[*uint32_prop];
+
+ p_LnxWrpFmPortDev->id = *uint32_prop;
+ p_LnxWrpFmPortDev->settings.param.portId =
+ p_LnxWrpFmPortDev->id;
+ p_LnxWrpFmPortDev->settings.param.portType = e_FM_PORT_TYPE_RX;
+ if (p_LnxWrpFmDev->pcdActive)
+ p_LnxWrpFmPortDev->defPcd = p_LnxWrpFmDev->defPcd;
+ } else if (of_device_is_compatible(port_node, "fsl,fman-port-10g-rx")) {
+ if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_10G_RX_PORTS)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("of_get_property(%s, cell-index) failed",
+ port_node->full_name));
+ return NULL;
+ }
+ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->rxPorts[*uint32_prop +
+ FM_MAX_NUM_OF_1G_RX_PORTS];
+
+ p_LnxWrpFmPortDev->id = *uint32_prop;
+ p_LnxWrpFmPortDev->settings.param.portId =
+ p_LnxWrpFmPortDev->id;
+ p_LnxWrpFmPortDev->settings.param.portType =
+ e_FM_PORT_TYPE_RX_10G;
+ if (p_LnxWrpFmDev->pcdActive)
+ p_LnxWrpFmPortDev->defPcd = p_LnxWrpFmDev->defPcd;
+ } else {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal port type"));
+ return NULL;
+ }
+
+ _errno = of_address_to_resource(port_node, 0, &res);
+ if (unlikely(_errno < 0)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("of_address_to_resource() = %d", _errno));
+ return NULL;
+ }
+
+ p_LnxWrpFmPortDev->dev = &of_dev->dev;
+ p_LnxWrpFmPortDev->baseAddr = 0;
+ p_LnxWrpFmPortDev->phys_baseAddr = res.start;
+ p_LnxWrpFmPortDev->memSize = res.end + 1 - res.start;
+ p_LnxWrpFmPortDev->settings.param.h_Fm = p_LnxWrpFmDev->h_Dev;
+ p_LnxWrpFmPortDev->h_LnxWrpFmDev = (t_Handle) p_LnxWrpFmDev;
+
+ of_node_put(port_node);
+
+ p_LnxWrpFmPortDev->active = TRUE;
+
+#if defined(CONFIG_FMAN_DISABLE_OH_TO_REUSE_RESOURCES)
+ /* for performance mode no OH port available. */
+ if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ p_LnxWrpFmPortDev->active = FALSE;
+#endif
+
+ return p_LnxWrpFmPortDev;
+}
+
+struct device_node * GetFmPortAdvArgsDevTreeNode (struct device_node *fm_node,
+ e_FmPortType portType,
+ uint8_t portId)
+{
+ struct device_node *port_node;
+ const uint32_t *uint32_prop;
+ int lenp;
+ char *portTypeString;
+
+ switch(portType) {
+ case e_FM_PORT_TYPE_OH_OFFLINE_PARSING:
+ portTypeString = "fsl,fman-port-op-extended-args";
+ break;
+ case e_FM_PORT_TYPE_TX:
+ portTypeString = "fsl,fman-port-1g-tx-extended-args";
+ break;
+ case e_FM_PORT_TYPE_TX_10G:
+ portTypeString = "fsl,fman-port-10g-tx-extended-args";
+ break;
+ case e_FM_PORT_TYPE_RX:
+ portTypeString = "fsl,fman-port-1g-rx-extended-args";
+ break;
+ case e_FM_PORT_TYPE_RX_10G:
+ portTypeString = "fsl,fman-port-10g-rx-extended-args";
+ break;
+ default:
+ return NULL;
+ }
+
+ for_each_child_of_node(fm_node, port_node) {
+ uint32_prop = (uint32_t *)of_get_property(port_node, "cell-index", &lenp);
+ if (unlikely(uint32_prop == NULL)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("of_get_property(%s, cell-index) failed",
+ port_node->full_name));
+ return NULL;
+ }
+ if (WARN_ON(lenp != sizeof(uint32_t)))
+ return NULL;
+ if (unlikely(*uint32_prop >= FM_MAX_NUM_OF_OH_PORTS)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE,
+ ("of_get_property(%s, cell-index) failed",
+ port_node->full_name));
+ return NULL;
+ }
+
+ if ((portId == *uint32_prop) &&
+ (of_device_is_compatible(port_node, portTypeString))) {
+ return port_node;
+ }
+ }
+
+ return NULL;
+}
+
+static t_Error CheckNConfigFmPortAdvArgs (t_LnxWrpFmPortDev *p_LnxWrpFmPortDev)
+{
+ struct device_node *fm_node, *port_node;
+ t_Error err;
+ t_FmPortRsrc portRsrc;
+ const uint32_t *uint32_prop;
+ /*const char *str_prop;*/
+ int lenp;
+#ifdef CONFIG_FMAN_PFC
+ uint8_t i, id, num_pools;
+ t_FmBufPoolDepletion poolDepletion;
+
+ if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_RX ||
+ p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_RX_10G) {
+ memset(&poolDepletion, 0, sizeof(t_FmBufPoolDepletion));
+ poolDepletion.singlePoolModeEnable = true;
+ num_pools = p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.
+ extBufPools.numOfPoolsUsed;
+ for (i = 0; i < num_pools; i++) {
+ id = p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.
+ extBufPools.extBufPool[i].id;
+ poolDepletion.poolsToConsiderForSingleMode[id] = true;
+ }
+
+ for (i = 0; i < CONFIG_FMAN_PFC_COS_COUNT; i++)
+ poolDepletion.pfcPrioritiesEn[i] = true;
+
+ err = FM_PORT_ConfigPoolDepletion(p_LnxWrpFmPortDev->h_Dev,
+ &poolDepletion);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, ("FM_PORT_ConfigPoolDepletion() failed"));
+ }
+#endif
+
+ fm_node = GetFmAdvArgsDevTreeNode(((t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev)->id);
+ if (!fm_node) /* no advance parameters for FMan */
+ return E_OK;
+
+ port_node = GetFmPortAdvArgsDevTreeNode(fm_node,
+ p_LnxWrpFmPortDev->settings.param.portType,
+ p_LnxWrpFmPortDev->settings.param.portId);
+ if (!port_node) /* no advance parameters for FMan-Port */
+ return E_OK;
+
+ uint32_prop = (uint32_t *)of_get_property(port_node, "num-tnums", &lenp);
+ if (uint32_prop) {
+ if (WARN_ON(lenp != sizeof(uint32_t)*2))
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG);
+
+ portRsrc.num = uint32_prop[0];
+ portRsrc.extra = uint32_prop[1];
+
+ if ((err = FM_PORT_ConfigNumOfTasks(p_LnxWrpFmPortDev->h_Dev,
+ &portRsrc)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ uint32_prop = (uint32_t *)of_get_property(port_node, "num-dmas", &lenp);
+ if (uint32_prop) {
+ if (WARN_ON(lenp != sizeof(uint32_t)*2))
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG);
+
+ portRsrc.num = uint32_prop[0];
+ portRsrc.extra = uint32_prop[1];
+
+ if ((err = FM_PORT_ConfigNumOfOpenDmas(p_LnxWrpFmPortDev->h_Dev,
+ &portRsrc)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ uint32_prop = (uint32_t *)of_get_property(port_node, "fifo-size", &lenp);
+ if (uint32_prop) {
+ if (WARN_ON(lenp != sizeof(uint32_t)*2))
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG);
+
+ portRsrc.num = uint32_prop[0];
+ portRsrc.extra = uint32_prop[1];
+
+ if ((err = FM_PORT_ConfigSizeOfFifo(p_LnxWrpFmPortDev->h_Dev,
+ &portRsrc)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ uint32_prop = (uint32_t *)of_get_property(port_node, "errors-to-discard", &lenp);
+ if (uint32_prop) {
+ if (WARN_ON(lenp != sizeof(uint32_t)))
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG);
+ if ((err = FM_PORT_ConfigErrorsToDiscard(p_LnxWrpFmPortDev->h_Dev,
+ uint32_prop[0])) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ uint32_prop = (uint32_t *)of_get_property(port_node, "ar-tables-sizes",
+ &lenp);
+ if (uint32_prop) {
+
+ if (WARN_ON(lenp != sizeof(uint32_t)*8))
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG);
+ if (WARN_ON(p_LnxWrpFmPortDev->settings.param.portType !=
+ e_FM_PORT_TYPE_RX) &&
+ (p_LnxWrpFmPortDev->settings.param.portType !=
+ e_FM_PORT_TYPE_RX_10G))
+ RETURN_ERROR(MINOR, E_INVALID_VALUE,
+ ("Auto Response is an Rx port atribute."));
+
+ memset(&p_LnxWrpFmPortDev->dsar_table_sizes, 0, sizeof(struct auto_res_tables_sizes));
+
+ p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_arp_entries =
+ (uint16_t)uint32_prop[0];
+ p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_echo_ipv4_entries =
+ (uint16_t)uint32_prop[1];
+ p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_ndp_entries =
+ (uint16_t)uint32_prop[2];
+ p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_echo_ipv6_entries =
+ (uint16_t)uint32_prop[3];
+ p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_snmp_ipv4_entries =
+ (uint16_t)uint32_prop[4];
+ p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_snmp_ipv6_entries =
+ (uint16_t)uint32_prop[5];
+ p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_snmp_oid_entries =
+ (uint16_t)uint32_prop[6];
+ p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_snmp_char =
+ (uint16_t)uint32_prop[7];
+ uint32_prop = (uint32_t *)of_get_property(port_node,
+ "ar-filters-sizes", &lenp);
+ if (uint32_prop) {
+ if (WARN_ON(lenp != sizeof(uint32_t)*3))
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG);
+
+ p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_ip_prot_filtering =
+ (uint16_t)uint32_prop[0];
+ p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_tcp_port_filtering =
+ (uint16_t)uint32_prop[1];
+ p_LnxWrpFmPortDev->dsar_table_sizes.max_num_of_udp_port_filtering =
+ (uint16_t)uint32_prop[2];
+ }
+
+ if ((err = FM_PORT_ConfigDsarSupport(p_LnxWrpFmPortDev->h_Dev,
+ (t_FmPortDsarTablesSizes*)&p_LnxWrpFmPortDev->dsar_table_sizes)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+
+ of_node_put(port_node);
+ of_node_put(fm_node);
+
+ return E_OK;
+}
+
+static t_Error CheckNSetFmPortAdvArgs (t_LnxWrpFmPortDev *p_LnxWrpFmPortDev)
+{
+ struct device_node *fm_node, *port_node;
+ t_Error err;
+ const uint32_t *uint32_prop;
+ /*const char *str_prop;*/
+ int lenp;
+
+ fm_node = GetFmAdvArgsDevTreeNode(((t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev)->id);
+ if (!fm_node) /* no advance parameters for FMan */
+ return E_OK;
+
+ port_node = GetFmPortAdvArgsDevTreeNode(fm_node,
+ p_LnxWrpFmPortDev->settings.param.portType,
+ p_LnxWrpFmPortDev->settings.param.portId);
+ if (!port_node) /* no advance parameters for FMan-Port */
+ return E_OK;
+
+#if (DPAA_VERSION >= 11)
+ uint32_prop = (uint32_t *)of_get_property(port_node, "vsp-window", &lenp);
+ if (uint32_prop) {
+ t_FmPortVSPAllocParams portVSPAllocParams;
+ t_FmVspParams fmVspParams;
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
+ uint8_t portId;
+
+ p_LnxWrpFmDev = ((t_LnxWrpFmDev *)p_LnxWrpFmPortDev->h_LnxWrpFmDev);
+
+ if (WARN_ON(lenp != sizeof(uint32_t)*2))
+ RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG);
+
+ if ((p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_TX) ||
+ (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_TX_10G) ||
+ ((p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) &&
+ p_LnxWrpFmPortDev->settings.frag_enabled))
+ return E_OK;
+
+ memset(&portVSPAllocParams, 0, sizeof(portVSPAllocParams));
+ memset(&fmVspParams, 0, sizeof(fmVspParams));
+
+ portVSPAllocParams.numOfProfiles = (uint8_t)uint32_prop[0];
+ portVSPAllocParams.dfltRelativeId = (uint8_t)uint32_prop[1];
+ fmVspParams.h_Fm = p_LnxWrpFmDev->h_Dev;
+
+ fmVspParams.portParams.portType = p_LnxWrpFmPortDev->settings.param.portType;
+ fmVspParams.portParams.portId = p_LnxWrpFmPortDev->settings.param.portId;
+ fmVspParams.relativeProfileId = portVSPAllocParams.dfltRelativeId;
+
+ if (p_LnxWrpFmPortDev->settings.param.portType != e_FM_PORT_TYPE_OH_OFFLINE_PARSING)
+ {
+ portId = fmVspParams.portParams.portId;
+ if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_RX_10G)
+ portId += FM_MAX_NUM_OF_1G_RX_PORTS;
+ portVSPAllocParams.h_FmTxPort =
+ p_LnxWrpFmDev->txPorts[portId].h_Dev;
+ fmVspParams.liodnOffset =
+ p_LnxWrpFmDev->rxPorts[portId].settings.param.specificParams.rxParams.liodnOffset;
+ memcpy(&fmVspParams.extBufPools,
+ &p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.extBufPools,
+ sizeof(t_FmExtPools));
+ }
+ else
+ {
+ memcpy(&fmVspParams.extBufPools,
+ &p_LnxWrpFmPortDev->opExtPools,
+ sizeof(t_FmExtPools));
+ }
+
+ if ((err = FM_PORT_VSPAlloc(p_LnxWrpFmPortDev->h_Dev,
+ &portVSPAllocParams)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ /* We're initializing only the default VSP that are being used by the Linux-Ethernet-driver */
+ if ((p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_OH_OFFLINE_PARSING) &&
+ !p_LnxWrpFmPortDev->opExtPools.numOfPoolsUsed)
+ return E_OK;
+
+ p_LnxWrpFmPortDev->h_DfltVsp = FM_VSP_Config(&fmVspParams);
+ if (!p_LnxWrpFmPortDev->h_DfltVsp)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("default-VSP for port!"));
+
+ if ((err = FM_VSP_ConfigBufferPrefixContent(p_LnxWrpFmPortDev->h_DfltVsp,
+ &p_LnxWrpFmPortDev->buffPrefixContent)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+
+ if ((err = FM_VSP_Init(p_LnxWrpFmPortDev->h_DfltVsp)) != E_OK)
+ RETURN_ERROR(MINOR, err, NO_MSG);
+ }
+#else
+UNUSED(err); UNUSED(uint32_prop); UNUSED(lenp);
+#endif /* (DPAA_VERSION >= 11) */
+
+ of_node_put(port_node);
+ of_node_put(fm_node);
+
+ return E_OK;
+}
+
+static t_Error ConfigureFmPortDev(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev =
+ (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev;
+ struct resource *dev_res;
+
+ if (!p_LnxWrpFmPortDev->active)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,
+ ("FM port not configured!!!"));
+
+ dev_res =
+ __devm_request_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res,
+ p_LnxWrpFmPortDev->phys_baseAddr,
+ p_LnxWrpFmPortDev->memSize,
+ "fman-port-hc");
+ if (unlikely(dev_res == NULL))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE,
+ ("__devm_request_region() failed"));
+ p_LnxWrpFmPortDev->baseAddr =
+ PTR_TO_UINT(devm_ioremap
+ (p_LnxWrpFmDev->dev,
+ p_LnxWrpFmPortDev->phys_baseAddr,
+ p_LnxWrpFmPortDev->memSize));
+ if (unlikely(p_LnxWrpFmPortDev->baseAddr == 0))
+ REPORT_ERROR(MAJOR, E_INVALID_STATE,
+ ("devm_ioremap() failed"));
+
+ p_LnxWrpFmPortDev->settings.param.baseAddr =
+ p_LnxWrpFmPortDev->baseAddr;
+
+ return E_OK;
+}
+
+static t_Error InitFmPortDev(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev)
+{
+#define MY_ADV_CONFIG_CHECK_END \
+ RETURN_ERROR(MAJOR, E_INVALID_SELECTION,\
+ ("Advanced configuration routine"));\
+ if (errCode != E_OK)\
+ RETURN_ERROR(MAJOR, errCode, NO_MSG);\
+ }
+
+ int i = 0;
+
+ if (!p_LnxWrpFmPortDev->active || p_LnxWrpFmPortDev->h_Dev)
+ return E_INVALID_STATE;
+
+ p_LnxWrpFmPortDev->h_Dev =
+ FM_PORT_Config(&p_LnxWrpFmPortDev->settings.param);
+ if (p_LnxWrpFmPortDev->h_Dev == NULL)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM-port"));
+
+#ifndef FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+ if ((p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_TX_10G)
+ || (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_TX)) {
+ t_Error errCode = E_OK;
+ errCode =
+ FM_PORT_ConfigDeqHighPriority(p_LnxWrpFmPortDev->h_Dev,
+ TRUE);
+ if (errCode != E_OK)
+ RETURN_ERROR(MAJOR, errCode, NO_MSG);
+ errCode =
+ FM_PORT_ConfigDeqPrefetchOption(p_LnxWrpFmPortDev->h_Dev,
+ e_FM_PORT_DEQ_FULL_PREFETCH);
+ if (errCode
+ != E_OK)
+ RETURN_ERROR(MAJOR, errCode, NO_MSG);
+ }
+#endif /* !FM_QMI_NO_DEQ_OPTIONS_SUPPORT */
+
+#ifdef FM_BCB_ERRATA_BMI_SW001
+/* Configure BCB workaround on Rx ports, only for B4860 rev1 */
+#define SVR_SECURITY_MASK 0x00080000
+#define SVR_PERSONALITY_MASK 0x0000FF00
+#define SVR_VER_IGNORE_MASK (SVR_SECURITY_MASK | SVR_PERSONALITY_MASK)
+#define SVR_B4860_REV1_VALUE 0x86800010
+
+ if ((p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_RX_10G) ||
+ (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_RX)) {
+ unsigned int svr;
+
+ svr = mfspr(SPRN_SVR);
+
+ if ((svr & ~SVR_VER_IGNORE_MASK) == SVR_B4860_REV1_VALUE)
+ FM_PORT_ConfigBCBWorkaround(p_LnxWrpFmPortDev->h_Dev);
+ }
+#endif /* FM_BCB_ERRATA_BMI_SW001 */
+
+/* Call the driver's advanced configuration routines, if requested:
+ Compare the function pointer of each entry to the available routines,
+ and invoke the matching routine with proper casting of arguments. */
+ while (p_LnxWrpFmPortDev->settings.advConfig[i].p_Function
+ && (i < FM_MAX_NUM_OF_ADV_SETTINGS)) {
+
+/* TODO: Change this MACRO */
+ ADV_CONFIG_CHECK_START(
+ &(p_LnxWrpFmPortDev->settings.advConfig[i]))
+
+ ADV_CONFIG_CHECK(p_LnxWrpFmPortDev->h_Dev,
+ FM_PORT_ConfigBufferPrefixContent,
+ NCSW_PARAMS(1,
+ (t_FmBufferPrefixContent *)))
+
+ if ((p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_OH_OFFLINE_PARSING) &&
+ (p_LnxWrpFmPortDev->settings.frag_enabled == TRUE)) {
+
+ ADV_CONFIG_CHECK(p_LnxWrpFmPortDev->h_Dev,
+ FM_PORT_ConfigExtBufPools,
+ NCSW_PARAMS(1, (t_FmExtPools *)))
+
+ /* this define contains an else */
+ MY_ADV_CONFIG_CHECK_END
+ }
+
+ /* Advance to next advanced configuration entry */
+ i++;
+ }
+
+#if defined(CONFIG_FMAN_RESOURCE_ALLOCATION_ALGORITHM)
+#if (DPAA_VERSION >= 11)
+#warning The resource allocation algorithm is not available for FMan v3 platforms
+#else
+ /* even if these functions return w/ error, do not crash kernel.
+ Do not return anything because the container function is not
+ linux complient (it should return -EIO). */
+ fm_config_precalculate_fifosize(p_LnxWrpFmPortDev);
+ fm_config_precalculate_open_dma(p_LnxWrpFmPortDev);
+ fm_config_precalculate_tnums(p_LnxWrpFmPortDev);
+#endif
+#endif
+
+ if ((p_LnxWrpFmPortDev->settings.param.portType != e_FM_PORT_TYPE_TX) &&
+ (p_LnxWrpFmPortDev->settings.param.portType != e_FM_PORT_TYPE_TX_10G)) {
+ if (FM_PORT_ConfigErrorsToDiscard(p_LnxWrpFmPortDev->h_Dev, (FM_PORT_FRM_ERR_IPRE |
+ FM_PORT_FRM_ERR_IPR_NCSP |
+ FM_PORT_FRM_ERR_CLS_DISCARD)) !=E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+ }
+
+ if (CheckNConfigFmPortAdvArgs(p_LnxWrpFmPortDev) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ if (FM_PORT_Init(p_LnxWrpFmPortDev->h_Dev) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+ if (CheckNSetFmPortAdvArgs(p_LnxWrpFmPortDev) != E_OK)
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+
+/* FMan Fifo sizes behind the scene":
+ * Using the following formulae (*), under a set of simplifying assumptions (.):
+ * . all ports are configured in Normal Mode (rather than Independent Mode)
+ * . the DPAA Eth driver allocates buffers of size:
+ * . MAXFRM + NET_IP_ALIGN + DPA_PRIV_DATA_SIZE + DPA_PARSE_RESULTS_SIZE
+ * + DPA_HASH_RESULTS_SIZE, i.e.:
+ * MAXFRM + 2 + 16 + sizeof(t_FmPrsResult) + 16, i.e.:
+ * MAXFRM + 66
+ * . excessive buffer pools not accounted for
+ *
+ * * for Rx ports on P4080:
+ * . IFSZ = ceil(max(FMBM_EBMPI[PBS]) / 256) * 256 + 7 * 256
+ * . no internal frame offset (FMBM_RIM[FOF] == 0) - otherwise,
+ * add up to 256 to the above
+ *
+ * * for Rx ports on P1023:
+ * . IFSZ = ceil(second_largest(FMBM_EBMPI[PBS] / 256)) * 256 + 7 * 256,
+ * if at least 2 bpools are configured
+ * . IFSZ = 8 * 256, if only a single bpool is configured
+ *
+ * * for Tx ports:
+ * . IFSZ = ceil(frame_size / 256) * 256 + 3 * 256
+ * + FMBM_TFP[DPDE] * 256, i.e.:
+ * IFSZ = ceil(MAXFRM / 256) * 256 + 3 x 256 + FMBM_TFP[DPDE] * 256
+ *
+ * * for OH ports on P4080:
+ * . IFSZ = ceil(frame_size / 256) * 256 + 1 * 256 + FMBM_PP[MXT] * 256
+ * * for OH ports on P1023:
+ * . IFSZ = ceil(frame_size / 256) * 256 + 3 * 256 + FMBM_TFP[DPDE] * 256
+ * * for both P4080 and P1023:
+ * . (conservative decisions, assuming that BMI must bring the entire
+ * frame, not only the frame header)
+ * . no internal frame offset (FMBM_OIM[FOF] == 0) - otherwise,
+ * add up to 256 to the above
+ *
+ * . for P4080/P5020/P3041/P2040, DPDE is:
+ * > 0 or 1, for 1Gb ports, HW default: 0
+ * > 2..7 (recommended: 3..7) for 10Gb ports, HW default: 3
+ * . for P1023, DPDE should be 1
+ *
+ * . for P1023, MXT is in range (0..31)
+ * . for P4080, MXT is in range (0..63)
+ *
+ */
+#if 0
+ if ((p_LnxWrpFmPortDev->defPcd != e_NO_PCD) &&
+ (InitFmPort3TupleDefPcd(p_LnxWrpFmPortDev) != E_OK))
+ RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG);
+#endif
+ return E_OK;
+}
+
+void fm_set_rx_port_params(struct fm_port *port,
+ struct fm_port_params *params)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *) port;
+ int i;
+
+ p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.errFqid =
+ params->errq;
+ p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.dfltFqid =
+ params->defq;
+ p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.extBufPools.
+ numOfPoolsUsed = params->num_pools;
+ for (i = 0; i < params->num_pools; i++) {
+ p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.
+ extBufPools.extBufPool[i].id =
+ params->pool_param[i].id;
+ p_LnxWrpFmPortDev->settings.param.specificParams.rxParams.
+ extBufPools.extBufPool[i].size =
+ params->pool_param[i].size;
+ }
+
+ p_LnxWrpFmPortDev->buffPrefixContent.privDataSize =
+ params->priv_data_size;
+ p_LnxWrpFmPortDev->buffPrefixContent.passPrsResult =
+ params->parse_results;
+ p_LnxWrpFmPortDev->buffPrefixContent.passHashResult =
+ params->hash_results;
+ p_LnxWrpFmPortDev->buffPrefixContent.passTimeStamp =
+ params->time_stamp;
+ p_LnxWrpFmPortDev->buffPrefixContent.dataAlign =
+ params->data_align;
+ p_LnxWrpFmPortDev->buffPrefixContent.manipExtraSpace =
+ params->manip_extra_space;
+
+ ADD_ADV_CONFIG_START(p_LnxWrpFmPortDev->settings.advConfig,
+ FM_MAX_NUM_OF_ADV_SETTINGS)
+
+ ADD_ADV_CONFIG_NO_RET(FM_PORT_ConfigBufferPrefixContent,
+ ARGS(1,
+ (&p_LnxWrpFmPortDev->
+ buffPrefixContent)));
+
+ ADD_ADV_CONFIG_END InitFmPortDev(p_LnxWrpFmPortDev);
+}
+EXPORT_SYMBOL(fm_set_rx_port_params);
+
+/* this function is called from oh_probe as well, thus it contains oh port
+ * specific parameters (make sure everything is checked) */
+void fm_set_tx_port_params(struct fm_port *port,
+ struct fm_port_params *params)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *) port;
+
+ p_LnxWrpFmPortDev->settings.param.specificParams.nonRxParams.errFqid =
+ params->errq;
+ p_LnxWrpFmPortDev->settings.param.specificParams.nonRxParams.
+ dfltFqid = params->defq;
+
+ p_LnxWrpFmPortDev->buffPrefixContent.privDataSize =
+ params->priv_data_size;
+ p_LnxWrpFmPortDev->buffPrefixContent.passPrsResult =
+ params->parse_results;
+ p_LnxWrpFmPortDev->buffPrefixContent.passHashResult =
+ params->hash_results;
+ p_LnxWrpFmPortDev->buffPrefixContent.passTimeStamp =
+ params->time_stamp;
+ p_LnxWrpFmPortDev->settings.frag_enabled =
+ params->frag_enable;
+ p_LnxWrpFmPortDev->buffPrefixContent.dataAlign =
+ params->data_align;
+ p_LnxWrpFmPortDev->buffPrefixContent.manipExtraSpace =
+ params->manip_extra_space;
+
+ ADD_ADV_CONFIG_START(p_LnxWrpFmPortDev->settings.advConfig,
+ FM_MAX_NUM_OF_ADV_SETTINGS)
+
+ ADD_ADV_CONFIG_NO_RET(FM_PORT_ConfigBufferPrefixContent,
+ ARGS(1,
+ (&p_LnxWrpFmPortDev->
+ buffPrefixContent)));
+
+ /* oh port specific parameter (for fragmentation only) */
+ if ((p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_OH_OFFLINE_PARSING) &&
+ params->num_pools) {
+ int i;
+
+ p_LnxWrpFmPortDev->opExtPools.numOfPoolsUsed = params->num_pools;
+ for (i = 0; i < params->num_pools; i++) {
+ p_LnxWrpFmPortDev->opExtPools.extBufPool[i].id = params->pool_param[i].id;
+ p_LnxWrpFmPortDev->opExtPools.extBufPool[i].size = params->pool_param[i].size;
+ }
+
+ if (p_LnxWrpFmPortDev->settings.frag_enabled)
+ ADD_ADV_CONFIG_NO_RET(FM_PORT_ConfigExtBufPools,
+ ARGS(1, (&p_LnxWrpFmPortDev->opExtPools)));
+ }
+
+ ADD_ADV_CONFIG_END InitFmPortDev(p_LnxWrpFmPortDev);
+}
+EXPORT_SYMBOL(fm_set_tx_port_params);
+
+void fm_mac_set_handle(t_Handle h_lnx_wrp_fm_dev,
+ t_Handle h_fm_mac,
+ int mac_id)
+{
+ t_LnxWrpFmDev *p_lnx_wrp_fm_dev = (t_LnxWrpFmDev *)h_lnx_wrp_fm_dev;
+
+ p_lnx_wrp_fm_dev->macs[mac_id].h_Dev = h_fm_mac;
+ p_lnx_wrp_fm_dev->macs[mac_id].h_LnxWrpFmDev = h_lnx_wrp_fm_dev;
+}
+EXPORT_SYMBOL(fm_mac_set_handle);
+
+static void LnxwrpFmPcdDevExceptionsCb(t_Handle h_App,
+ e_FmPcdExceptions exception)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *) h_App;
+
+ ASSERT_COND(p_LnxWrpFmDev);
+
+ DBG(INFO, ("got fm-pcd exception %d", exception));
+
+ /* do nothing */
+ UNUSED(exception);
+}
+
+static void LnxwrpFmPcdDevIndexedExceptionsCb(t_Handle h_App,
+ e_FmPcdExceptions exception,
+ uint16_t index)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *) h_App;
+
+ ASSERT_COND(p_LnxWrpFmDev);
+
+ DBG(INFO,
+ ("got fm-pcd-indexed exception %d, indx %d", exception, index));
+
+ /* do nothing */
+ UNUSED(exception);
+ UNUSED(index);
+}
+
+static t_Error InitFmPcdDev(t_LnxWrpFmDev *p_LnxWrpFmDev)
+{
+ spin_lock_init(&lock);
+
+ if (p_LnxWrpFmDev->pcdActive) {
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = &p_LnxWrpFmDev->hcPort;
+ t_FmPcdParams fmPcdParams;
+ t_Error err;
+
+ memset(&fmPcdParams, 0, sizeof(fmPcdParams));
+ fmPcdParams.h_Fm = p_LnxWrpFmDev->h_Dev;
+ fmPcdParams.prsSupport = p_LnxWrpFmDev->prsActive;
+ fmPcdParams.kgSupport = p_LnxWrpFmDev->kgActive;
+ fmPcdParams.plcrSupport = p_LnxWrpFmDev->plcrActive;
+ fmPcdParams.ccSupport = p_LnxWrpFmDev->ccActive;
+ fmPcdParams.numOfSchemes = FM_PCD_KG_NUM_OF_SCHEMES;
+
+#ifndef CONFIG_GUEST_PARTITION
+ fmPcdParams.f_Exception = LnxwrpFmPcdDevExceptionsCb;
+ if (fmPcdParams.kgSupport)
+ fmPcdParams.f_ExceptionId =
+ LnxwrpFmPcdDevIndexedExceptionsCb;
+ fmPcdParams.h_App = p_LnxWrpFmDev;
+#endif /* !CONFIG_GUEST_PARTITION */
+
+#ifdef CONFIG_MULTI_PARTITION_SUPPORT
+ fmPcdParams.numOfSchemes = 0;
+ fmPcdParams.numOfClsPlanEntries = 0;
+ fmPcdParams.partitionId = 0;
+#endif /* CONFIG_MULTI_PARTITION_SUPPORT */
+ fmPcdParams.useHostCommand = TRUE;
+
+ p_LnxWrpFmDev->hc_tx_fq =
+ FqAlloc(p_LnxWrpFmDev,
+ 0,
+ QMAN_FQ_FLAG_TO_DCPORTAL,
+ p_LnxWrpFmPortDev->txCh, 0);
+ if (!p_LnxWrpFmDev->hc_tx_fq)
+ RETURN_ERROR(MAJOR, E_NULL_POINTER,
+ ("Frame queue allocation failed..."));
+
+ p_LnxWrpFmDev->hc_tx_conf_fq =
+ FqAlloc(p_LnxWrpFmDev,
+ 0,
+ QMAN_FQ_FLAG_NO_ENQUEUE,
+ p_LnxWrpFmDev->hcCh, 7);
+ if (!p_LnxWrpFmDev->hc_tx_conf_fq)
+ RETURN_ERROR(MAJOR, E_NULL_POINTER,
+ ("Frame queue allocation failed..."));
+
+ p_LnxWrpFmDev->hc_tx_err_fq =
+ FqAlloc(p_LnxWrpFmDev,
+ 0,
+ QMAN_FQ_FLAG_NO_ENQUEUE,
+ p_LnxWrpFmDev->hcCh, 7);
+ if (!p_LnxWrpFmDev->hc_tx_err_fq)
+ RETURN_ERROR(MAJOR, E_NULL_POINTER,
+ ("Frame queue allocation failed..."));
+
+ fmPcdParams.hc.portBaseAddr = p_LnxWrpFmPortDev->baseAddr;
+ fmPcdParams.hc.portId =
+ p_LnxWrpFmPortDev->settings.param.portId;
+ fmPcdParams.hc.liodnBase =
+ p_LnxWrpFmPortDev->settings.param.liodnBase;
+ fmPcdParams.hc.errFqid =
+ qman_fq_fqid(p_LnxWrpFmDev->hc_tx_err_fq);
+ fmPcdParams.hc.confFqid =
+ qman_fq_fqid(p_LnxWrpFmDev->hc_tx_conf_fq);
+ fmPcdParams.hc.qmChannel = p_LnxWrpFmPortDev->txCh;
+ fmPcdParams.hc.f_QmEnqueue = QmEnqueueCB;
+ fmPcdParams.hc.h_QmArg = (t_Handle) p_LnxWrpFmDev;
+
+ p_LnxWrpFmDev->h_PcdDev = FM_PCD_Config(&fmPcdParams);
+ if (!p_LnxWrpFmDev->h_PcdDev)
+ RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("FM PCD!"));
+
+ err =
+ FM_PCD_ConfigPlcrNumOfSharedProfiles(p_LnxWrpFmDev->h_PcdDev,
+ LNXWRP_FM_NUM_OF_SHARED_PROFILES);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ err = FM_PCD_Init(p_LnxWrpFmDev->h_PcdDev);
+ if (err != E_OK)
+ RETURN_ERROR(MAJOR, err, NO_MSG);
+
+ if (p_LnxWrpFmDev->err_irq == 0) {
+ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev,
+ e_FM_PCD_KG_EXCEPTION_DOUBLE_ECC,
+ FALSE);
+ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev,
+ e_FM_PCD_KG_EXCEPTION_KEYSIZE_OVERFLOW,
+ FALSE);
+ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev,
+ e_FM_PCD_PLCR_EXCEPTION_INIT_ENTRY_ERROR,
+ FALSE);
+ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev,
+ e_FM_PCD_PLCR_EXCEPTION_DOUBLE_ECC,
+ FALSE);
+ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev,
+ e_FM_PCD_PRS_EXCEPTION_DOUBLE_ECC,
+ FALSE);
+ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev,
+ e_FM_PCD_PLCR_EXCEPTION_PRAM_SELF_INIT_COMPLETE,
+ FALSE);
+ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev,
+ e_FM_PCD_PLCR_EXCEPTION_ATOMIC_ACTION_COMPLETE,
+ FALSE);
+ FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev,
+ e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC,
+ FALSE);
+ }
+ }
+
+ return E_OK;
+}
+
+void FreeFmPcdDev(t_LnxWrpFmDev *p_LnxWrpFmDev)
+{
+
+ if (p_LnxWrpFmDev->h_PcdDev)
+ FM_PCD_Free(p_LnxWrpFmDev->h_PcdDev);
+
+ if (p_LnxWrpFmDev->hc_tx_err_fq)
+ FqFree(p_LnxWrpFmDev->hc_tx_err_fq);
+
+ if (p_LnxWrpFmDev->hc_tx_conf_fq)
+ FqFree(p_LnxWrpFmDev->hc_tx_conf_fq);
+
+ if (p_LnxWrpFmDev->hc_tx_fq)
+ FqFree(p_LnxWrpFmDev->hc_tx_fq);
+}
+
+static void FreeFmPortDev(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev =
+ (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev;
+
+ if (!p_LnxWrpFmPortDev->active)
+ return;
+
+ if (p_LnxWrpFmPortDev->h_Dev)
+ FM_PORT_Free(p_LnxWrpFmPortDev->h_Dev);
+
+ devm_iounmap(p_LnxWrpFmDev->dev,
+ UINT_TO_PTR(p_LnxWrpFmPortDev->baseAddr));
+ __devm_release_region(p_LnxWrpFmDev->dev, p_LnxWrpFmDev->res,
+ p_LnxWrpFmPortDev->phys_baseAddr,
+ p_LnxWrpFmPortDev->memSize);
+}
+
+static int /*__devinit*/ fm_port_probe(struct platform_device *of_dev)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev;
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
+ struct device *dev;
+
+ dev = &of_dev->dev;
+
+ p_LnxWrpFmPortDev = ReadFmPortDevTreeNode(of_dev);
+ if (p_LnxWrpFmPortDev == NULL)
+ return -EIO;
+ /* Port can be inactive, thus will not be probed:
+ - in performance mode, OH ports are disabled
+ ...
+ */
+ if (!p_LnxWrpFmPortDev->active)
+ return 0;
+
+ if (ConfigureFmPortDev(p_LnxWrpFmPortDev) != E_OK)
+ return -EIO;
+
+ dev_set_drvdata(dev, p_LnxWrpFmPortDev);
+
+ if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_OH_HOST_COMMAND)
+ InitFmPcdDev((t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev);
+
+ p_LnxWrpFmDev = (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev;
+
+ if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_RX) {
+ Sprint(p_LnxWrpFmPortDev->name, "%s-port-rx%d",
+ p_LnxWrpFmDev->name, p_LnxWrpFmPortDev->id);
+ p_LnxWrpFmPortDev->minor =
+ p_LnxWrpFmPortDev->id + DEV_FM_RX_PORTS_MINOR_BASE;
+ } else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_RX_10G) {
+ Sprint(p_LnxWrpFmPortDev->name, "%s-port-rx%d",
+ p_LnxWrpFmDev->name,
+ p_LnxWrpFmPortDev->id + FM_MAX_NUM_OF_1G_RX_PORTS);
+ p_LnxWrpFmPortDev->minor =
+ p_LnxWrpFmPortDev->id + FM_MAX_NUM_OF_1G_RX_PORTS +
+ DEV_FM_RX_PORTS_MINOR_BASE;
+ } else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_TX) {
+ Sprint(p_LnxWrpFmPortDev->name, "%s-port-tx%d",
+ p_LnxWrpFmDev->name, p_LnxWrpFmPortDev->id);
+ p_LnxWrpFmPortDev->minor =
+ p_LnxWrpFmPortDev->id + DEV_FM_TX_PORTS_MINOR_BASE;
+ } else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_TX_10G) {
+ Sprint(p_LnxWrpFmPortDev->name, "%s-port-tx%d",
+ p_LnxWrpFmDev->name,
+ p_LnxWrpFmPortDev->id + FM_MAX_NUM_OF_1G_TX_PORTS);
+ p_LnxWrpFmPortDev->minor =
+ p_LnxWrpFmPortDev->id + FM_MAX_NUM_OF_1G_TX_PORTS +
+ DEV_FM_TX_PORTS_MINOR_BASE;
+ } else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_OH_HOST_COMMAND) {
+ Sprint(p_LnxWrpFmPortDev->name, "%s-port-oh%d",
+ p_LnxWrpFmDev->name, p_LnxWrpFmPortDev->id);
+ p_LnxWrpFmPortDev->minor =
+ p_LnxWrpFmPortDev->id + DEV_FM_OH_PORTS_MINOR_BASE;
+ } else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_OH_OFFLINE_PARSING) {
+ Sprint(p_LnxWrpFmPortDev->name, "%s-port-oh%d",
+ p_LnxWrpFmDev->name, p_LnxWrpFmPortDev->id + 1);
+ p_LnxWrpFmPortDev->minor =
+ p_LnxWrpFmPortDev->id + 1 +
+ DEV_FM_OH_PORTS_MINOR_BASE;
+ }
+
+ device_create(p_LnxWrpFmDev->fm_class, NULL,
+ MKDEV(p_LnxWrpFmDev->major, p_LnxWrpFmPortDev->minor),
+ NULL, p_LnxWrpFmPortDev->name);
+
+ /* create sysfs entries for stats and regs */
+
+ if (fm_port_sysfs_create(dev) != 0) {
+ FreeFmPortDev(p_LnxWrpFmPortDev);
+ REPORT_ERROR(MAJOR, E_INVALID_STATE,
+ ("Unable to create sys entry - fm port!!!"));
+ return -EIO;
+ }
+
+#ifdef FM_TX_INVALID_ECC_ERRATA_10GMAC_A009
+ FM_DisableRamsEcc(p_LnxWrpFmDev->h_Dev);
+#endif /* FM_TX_INVALID_ECC_ERRATA_10GMAC_A009 */
+
+ DBG(TRACE, ("%s probed", p_LnxWrpFmPortDev->name));
+
+ return 0;
+}
+
+static int fm_port_remove(struct platform_device *of_dev)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev;
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
+ struct device *dev;
+
+ dev = &of_dev->dev;
+ p_LnxWrpFmPortDev = dev_get_drvdata(dev);
+
+ fm_port_sysfs_destroy(dev);
+
+ p_LnxWrpFmDev = (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev;
+ device_destroy(p_LnxWrpFmDev->fm_class,
+ MKDEV(p_LnxWrpFmDev->major, p_LnxWrpFmPortDev->minor));
+
+ FreeFmPortDev(p_LnxWrpFmPortDev);
+
+ dev_set_drvdata(dev, NULL);
+
+ return 0;
+}
+
+static const struct of_device_id fm_port_match[] = {
+ {
+ .compatible = "fsl,fman-port-oh"},
+ {
+ .compatible = "fsl,fman-port-1g-rx"},
+ {
+ .compatible = "fsl,fman-port-10g-rx"},
+ {
+ .compatible = "fsl,fman-port-1g-tx"},
+ {
+ .compatible = "fsl,fman-port-10g-tx"},
+ {}
+};
+
+#ifndef MODULE
+MODULE_DEVICE_TABLE(of, fm_port_match);
+#endif /* !MODULE */
+
+static struct platform_driver fm_port_driver = {
+
+ .driver = {
+ .name = "fsl-fman-port",
+ .of_match_table = fm_port_match,
+ .owner = THIS_MODULE,
+ },
+ .probe = fm_port_probe,
+ .remove = fm_port_remove
+};
+
+
+t_Error LNXWRP_FM_Port_Init(void)
+{
+ /* Register to the DTB for basic FM port API */
+ if (platform_driver_register(&fm_port_driver))
+ return E_NO_DEVICE;
+
+ return E_OK;
+}
+
+void LNXWRP_FM_Port_Free(void)
+{
+ platform_driver_unregister(&fm_port_driver);
+}
+
+static int __init __cold fm_port_load(void)
+{
+ if (LNXWRP_FM_Port_Init() != E_OK) {
+ printk(KERN_CRIT "Failed to init FM Ports wrapper!\n");
+ return -ENODEV;
+ }
+
+ printk(KERN_CRIT "Freescale FM Ports module (" __DATE__ ":" __TIME__
+ ")\n");
+
+ return 0;
+}
+
+static void __exit __cold fm_port_unload(void)
+{
+ LNXWRP_FM_Port_Free();
+}
+
+module_init(fm_port_load);
+module_exit(fm_port_unload);
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm.c
new file mode 100644
index 0000000..473c3b0
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm.c
@@ -0,0 +1,4556 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ @File lnxwrp_ioctls_fm.c
+ @Author Shlomi Gridish
+ @Description FM Linux wrapper functions.
+*/
+
+/* Linux Headers ------------------- */
+#include <linux/version.h>
+
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+#define MODVERSIONS
+#endif
+#ifdef MODVERSIONS
+#include <config/modversions.h>
+#endif /* MODVERSIONS */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/of_platform.h>
+#include <asm/uaccess.h>
+#include <asm/errno.h>
+#include <sysdev/fsl_soc.h>
+
+#if defined(CONFIG_COMPAT)
+#include <linux/compat.h>
+#endif
+
+#include "part_ext.h"
+#include "fm_ioctls.h"
+#include "fm_pcd_ioctls.h"
+#include "fm_port_ioctls.h"
+#include "fm_vsp_ext.h"
+
+#define __ERR_MODULE__ MODULE_FM
+
+#if defined(CONFIG_COMPAT)
+#include "lnxwrp_ioctls_fm_compat.h"
+#endif
+
+#include "lnxwrp_fm.h"
+
+#define CMP_IOC_DEFINE(def) (IOC_##def != def)
+
+/* fm_pcd_ioctls.h === fm_pcd_ext.h assertions */
+#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_PRIVATE_HDRS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_PRS_NUM_OF_HDRS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_INTERCHANGEABLE_HDRS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_KG_NUM_OF_GENERIC_REGS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_KG_MAX_NUM_OF_EXTRACTS_PER_KEY)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_KG_NUM_OF_EXTRACT_MASKS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_KG_NUM_OF_DEFAULT_GROUPS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_PRS_NUM_OF_LABELS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_SW_PRS_SIZE)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_PRS_SW_OFFSET)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_MAX_MANIP_INSRT_TEMPLATE_SIZE)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if DPAA_VERSION >= 11
+#if CMP_IOC_DEFINE(FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES)
+#error Error: please synchronize IOC_ defines!
+#endif
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_CC_TREES)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_CC_GROUPS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_CC_UNITS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_KEYS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_MAX_SIZE_OF_KEY)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_MAX_NUM_OF_CC_ENTRIES_IN_GRP)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(FM_PCD_LAST_KEY_INDEX)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+/* net_ioctls.h === net_ext.h assertions */
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPP_PID)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPP_COMPRESSED)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPPoE_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPPMUX_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PPPMUX_SUBFRAME_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_ETH_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IPv4_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IPv6_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_ICMP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IGMP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_TCP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_SCTP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_DCCP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_UDP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_UDP_ENCAP_ESP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IPHC_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_SCTP_CHUNK_DATA_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_L2TPv2_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_L2TPv3_CTRL_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_L2TPv3_SESS_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_VLAN_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_LLC_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_NLPID_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_SNAP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_LLC_SNAP_ALL_FIELDS)
+#warning Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_ARP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_RFC2684_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_USER_DEFINED_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_PAYLOAD_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_GRE_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_MINENCAP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IPSEC_AH_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_IPSEC_ESP_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_MPLS_LABEL_STACK_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+#if CMP_IOC_DEFINE(NET_HEADER_FIELD_MACSEC_ALL_FIELDS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+/* fm_ioctls.h === fm_ext.h assertions */
+#if CMP_IOC_DEFINE(FM_MAX_NUM_OF_VALID_PORTS)
+#error Error: please synchronize IOC_ defines!
+#endif
+
+void LnxWrpPCDIOCTLTypeChecking(void)
+{
+ /* fm_ext.h == fm_ioctls.h */
+ ASSERT_COND(sizeof(ioc_fm_port_bandwidth_params) == sizeof(t_FmPortsBandwidthParams));
+ ASSERT_COND(sizeof(ioc_fm_revision_info_t) == sizeof(t_FmRevisionInfo));
+
+ /* fm_pcd_ext.h == fm_pcd_ioctls.h */
+ /*ioc_fm_pcd_counters_params_t : NOT USED */
+ /*ioc_fm_pcd_exception_params_t : private */
+ ASSERT_COND(sizeof(ioc_fm_pcd_prs_label_params_t) == sizeof(t_FmPcdPrsLabelParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_prs_sw_params_t) == sizeof(t_FmPcdPrsSwParams));
+ /*ioc_fm_pcd_kg_dflt_value_params_t : private */
+ ASSERT_COND(sizeof(ioc_fm_pcd_hdr_protocol_opt_u) == sizeof(u_FmPcdHdrProtocolOpt));
+ ASSERT_COND(sizeof(ioc_fm_pcd_fields_u) == sizeof(t_FmPcdFields));
+ ASSERT_COND(sizeof(ioc_fm_pcd_from_hdr_t) == sizeof(t_FmPcdFromHdr));
+ ASSERT_COND(sizeof(ioc_fm_pcd_from_field_t) == sizeof(t_FmPcdFromField));
+ ASSERT_COND(sizeof(ioc_fm_pcd_distinction_unit_t) == sizeof(t_FmPcdDistinctionUnit));
+#if !defined(CONFIG_COMPAT)
+ /* different alignment */
+ ASSERT_COND(sizeof(ioc_fm_pcd_net_env_params_t) == sizeof(t_FmPcdNetEnvParams) + sizeof(void *));
+#endif
+ ASSERT_COND(sizeof(ioc_fm_pcd_extract_entry_t) == sizeof(t_FmPcdExtractEntry));
+ ASSERT_COND(sizeof(ioc_fm_pcd_kg_extract_mask_t) == sizeof(t_FmPcdKgExtractMask));
+ ASSERT_COND(sizeof(ioc_fm_pcd_kg_extract_dflt_t) == sizeof(t_FmPcdKgExtractDflt));
+ ASSERT_COND(sizeof(ioc_fm_pcd_kg_key_extract_and_hash_params_t) == sizeof(t_FmPcdKgKeyExtractAndHashParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_kg_extracted_or_params_t) == sizeof(t_FmPcdKgExtractedOrParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_kg_scheme_counter_t) == sizeof(t_FmPcdKgSchemeCounter));
+ ASSERT_COND(sizeof(ioc_fm_pcd_kg_plcr_profile_t) == sizeof(t_FmPcdKgPlcrProfile));
+#if (DPAA_VERSION >= 11)
+ ASSERT_COND(sizeof(ioc_fm_pcd_kg_storage_profile_t) == sizeof(t_FmPcdKgStorageProfile));
+#endif
+ ASSERT_COND(sizeof(ioc_fm_pcd_kg_cc_t) == sizeof(t_FmPcdKgCc));
+#if !defined(CONFIG_COMPAT)
+ /* different alignment */
+ ASSERT_COND(sizeof(ioc_fm_pcd_kg_scheme_params_t) == sizeof(t_FmPcdKgSchemeParams) + sizeof(void *));
+#endif
+ ASSERT_COND(sizeof(ioc_fm_pcd_cc_next_cc_params_t) == sizeof(t_FmPcdCcNextCcParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_cc_next_plcr_params_t) == sizeof(t_FmPcdCcNextPlcrParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_cc_next_enqueue_params_t) == sizeof(t_FmPcdCcNextEnqueueParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_cc_next_kg_params_t) == sizeof(t_FmPcdCcNextKgParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_cc_next_engine_params_t) == sizeof(t_FmPcdCcNextEngineParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_cc_key_params_t) == sizeof(t_FmPcdCcKeyParams));
+ ASSERT_COND(sizeof(ioc_keys_params_t) == sizeof(t_KeysParams));
+#if !defined(CONFIG_COMPAT)
+ /* different alignment */
+ ASSERT_COND(sizeof(ioc_fm_pcd_cc_node_params_t) == sizeof(t_FmPcdCcNodeParams) + sizeof(void *));
+ ASSERT_COND(sizeof(ioc_fm_pcd_hash_table_params_t) == sizeof(t_FmPcdHashTableParams) + sizeof(void *));
+#endif
+ ASSERT_COND(sizeof(ioc_fm_pcd_cc_grp_params_t) == sizeof(t_FmPcdCcGrpParams));
+#if !defined(CONFIG_COMPAT)
+ /* different alignment */
+ ASSERT_COND(sizeof(ioc_fm_pcd_cc_tree_params_t) == sizeof(t_FmPcdCcTreeParams) + sizeof(void *));
+#endif
+ ASSERT_COND(sizeof(ioc_fm_pcd_plcr_byte_rate_mode_param_t) == sizeof(t_FmPcdPlcrByteRateModeParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_plcr_non_passthrough_alg_param_t) == sizeof(t_FmPcdPlcrNonPassthroughAlgParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_plcr_next_engine_params_u) == sizeof(u_FmPcdPlcrNextEngineParams));
+ /*ioc_fm_pcd_port_params_t : private */
+ ASSERT_COND(sizeof(ioc_fm_pcd_plcr_profile_params_t) == sizeof(t_FmPcdPlcrProfileParams) + sizeof(void *));
+ /*ioc_fm_pcd_cc_tree_modify_next_engine_params_t : private */
+
+#ifdef FM_CAPWAP_SUPPORT
+#error TODO: unsupported feature
+/*
+ ASSERT_COND(sizeof(TODO) == sizeof(t_FmPcdManipHdrInsrtByTemplateParams));
+ ASSERT_COND(sizeof(TODO) == sizeof(t_CapwapFragmentationParams));
+ ASSERT_COND(sizeof(TODO) == sizeof(t_CapwapReassemblyParams));
+ ASSERT_COND(sizeof(TODO) == sizeof(t_FmPcdManipFragOrReasmParams));
+ ASSERT_COND(sizeof(TODO) == sizeof(t_FmPcdManipHdrRmvByHdrParams));
+*/
+#endif
+
+ /*ioc_fm_pcd_cc_node_modify_next_engine_params_t : private */
+ /*ioc_fm_pcd_cc_node_remove_key_params_t : private */
+ /*ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t : private */
+ /*ioc_fm_pcd_cc_node_modify_key_params_t : private */
+ /*ioc_fm_manip_hdr_info_t : private */
+ /*ioc_fm_pcd_hash_table_set_t : private */
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_frag_ip_params_t) == sizeof(t_FmPcdManipFragIpParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_reassem_ip_params_t) == sizeof(t_FmPcdManipReassemIpParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_special_offload_ipsec_params_t) == sizeof(t_FmPcdManipSpecialOffloadIPSecParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_special_offload_params_t) == sizeof(t_FmPcdManipSpecialOffloadParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_rmv_generic_params_t) == sizeof(t_FmPcdManipHdrRmvGenericParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_insrt_generic_params_t) == sizeof(t_FmPcdManipHdrInsrtGenericParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_insrt_params_t) == sizeof(t_FmPcdManipHdrInsrtParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_rmv_params_t) == sizeof(t_FmPcdManipHdrRmvParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_hdr_params_t) == sizeof(t_FmPcdManipHdrParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_frag_params_t) == sizeof(t_FmPcdManipFragParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_reassem_params_t) == sizeof(t_FmPcdManipReassemParams));
+#if !defined(CONFIG_COMPAT)
+ /* different alignment */
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_params_t) == sizeof(t_FmPcdManipParams) + sizeof(void *));
+#endif
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_reassem_ip_stats_t) == sizeof(t_FmPcdManipReassemIpStats));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_frag_ip_stats_t) == sizeof(t_FmPcdManipFragIpStats));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_reassem_stats_t) == sizeof(t_FmPcdManipReassemStats));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_frag_stats_t) == sizeof(t_FmPcdManipFragStats));
+ ASSERT_COND(sizeof(ioc_fm_pcd_manip_stats_t) == sizeof(t_FmPcdManipStats));
+#if DPAA_VERSION >= 11
+ ASSERT_COND(sizeof(ioc_fm_pcd_frm_replic_group_params_t) == sizeof(t_FmPcdFrmReplicGroupParams) + sizeof(void *));
+#endif
+
+ /* fm_port_ext.h == fm_port_ioctls.h */
+ ASSERT_COND(sizeof(ioc_fm_port_rate_limit_t) == sizeof(t_FmPortRateLimit));
+ ASSERT_COND(sizeof(ioc_fm_port_pcd_params_t) == sizeof(t_FmPortPcdParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_kg_scheme_select_t) == sizeof(t_FmPcdKgSchemeSelect));
+ ASSERT_COND(sizeof(ioc_fm_pcd_port_schemes_params_t) == sizeof(t_FmPcdPortSchemesParams));
+ ASSERT_COND(sizeof(ioc_fm_pcd_prs_start_t) == sizeof(t_FmPcdPrsStart));
+
+ return;
+}
+
+#define ASSERT_IOC_NET_ENUM(def) ASSERT_COND((unsigned long)e_IOC_NET_##def == (unsigned long)def)
+
+void LnxWrpPCDIOCTLEnumChecking(void)
+{
+ /* net_ext.h == net_ioctls.h : sampling checks */
+ ASSERT_IOC_NET_ENUM(HEADER_TYPE_MACSEC);
+ ASSERT_IOC_NET_ENUM(HEADER_TYPE_PPP);
+ ASSERT_IOC_NET_ENUM(MAX_HEADER_TYPE_COUNT);
+
+ /* fm_ext.h == fm_ioctls.h */
+ ASSERT_COND((unsigned long)e_IOC_FM_PORT_TYPE_DUMMY == (unsigned long)e_FM_PORT_TYPE_DUMMY);
+ ASSERT_COND((unsigned long)e_IOC_EX_MURAM_ECC == (unsigned long)e_FM_EX_MURAM_ECC);
+ ASSERT_COND((unsigned long)e_IOC_FM_COUNTERS_DEQ_CONFIRM == (unsigned long)e_FM_COUNTERS_DEQ_CONFIRM);
+
+ /* fm_pcd_ext.h == fm_pcd_ioctls.h */
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES == (unsigned long)e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PRS_EXCEPTION_SINGLE_ECC == (unsigned long)e_FM_PCD_PRS_EXCEPTION_SINGLE_ECC);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PRS == (unsigned long)e_FM_PCD_PRS);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_EXTRACT_FULL_FIELD == (unsigned long)e_FM_PCD_EXTRACT_FULL_FIELD);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_EXTRACT_FROM_FLOW_ID == (unsigned long)e_FM_PCD_EXTRACT_FROM_FLOW_ID);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO == (unsigned long)e_FM_PCD_KG_EXTRACT_PORT_PRIVATE_INFO);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_KG_DFLT_ILLEGAL == (unsigned long)e_FM_PCD_KG_DFLT_ILLEGAL);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_KG_GENERIC_NOT_FROM_DATA == (unsigned long)e_FM_PCD_KG_GENERIC_NOT_FROM_DATA);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_HDR_INDEX_LAST == (unsigned long)e_FM_PCD_HDR_INDEX_LAST);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_SHARED == (unsigned long)e_FM_PCD_PLCR_SHARED);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_RFC_4115 == (unsigned long)e_FM_PCD_PLCR_RFC_4115);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_COLOR_AWARE == (unsigned long)e_FM_PCD_PLCR_COLOR_AWARE);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_OVERRIDE == (unsigned long)e_FM_PCD_PLCR_OVERRIDE);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_FULL_FRM_LEN == (unsigned long)e_FM_PCD_PLCR_FULL_FRM_LEN);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_ROLLBACK_FULL_FRM_LEN == (unsigned long)e_FM_PCD_PLCR_ROLLBACK_FULL_FRM_LEN);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_PACKET_MODE == (unsigned long)e_FM_PCD_PLCR_PACKET_MODE);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_DROP_FRAME == (unsigned long)e_FM_PCD_DROP_FRAME);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER == (unsigned long)e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_ACTION_INDEXED_LOOKUP == (unsigned long)e_FM_PCD_ACTION_INDEXED_LOOKUP);
+ ASSERT_COND((unsigned long)e_IOC_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR == (unsigned long)e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR);
+#if !defined(FM_CAPWAP_SUPPORT)
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_INSRT_GENERIC == (unsigned long)e_FM_PCD_MANIP_INSRT_GENERIC);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_RMV_GENERIC == (unsigned long)e_FM_PCD_MANIP_RMV_GENERIC);
+#else
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_INSRT_BY_TEMPLATE == (unsigned long)e_FM_PCD_MANIP_INSRT_BY_TEMPLATE);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_RMV_BY_HDR == (unsigned long)e_FM_PCD_MANIP_RMV_BY_HDR);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_RMV_BY_HDR_FROM_START == (unsigned long)e_FM_PCD_MANIP_RMV_BY_HDR_FROM_START);
+#endif
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAG == (unsigned long)e_FM_PCD_MANIP_TIME_OUT_BETWEEN_FRAG);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_EIGHT_WAYS_HASH == (unsigned long)e_FM_PCD_MANIP_EIGHT_WAYS_HASH);
+
+#ifdef FM_CAPWAP_SUPPORT
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_STATS_PER_FLOWID == (unsigned long)e_FM_PCD_STATS_PER_FLOWID);
+#endif
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_SPECIAL_OFFLOAD == (unsigned long)e_FM_PCD_MANIP_SPECIAL_OFFLOAD);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_CC_STATS_MODE_FRAME == (unsigned long)e_FM_PCD_CC_STATS_MODE_FRAME);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_CONTINUE_WITHOUT_FRAG == (unsigned long)e_FM_PCD_MANIP_CONTINUE_WITHOUT_FRAG);
+ ASSERT_COND((unsigned long)e_IOC_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC == (unsigned long)e_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC);
+
+ /* fm_port_ext.h == fm_port_ioctls.h */
+#if !defined(FM_CAPWAP_SUPPORT)
+ ASSERT_COND((unsigned long)e_IOC_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR == (unsigned long)e_FM_PORT_PCD_SUPPORT_PRS_AND_KG_AND_PLCR);
+#else
+ ASSERT_COND((unsigned long)e_IOC_FM_PORT_PCD_SUPPORT_CC_AND_KG_AND_PLCR == (unsigned long)e_FM_PORT_PCD_SUPPORT_CC_AND_KG_AND_PLCR);
+#endif
+ ASSERT_COND((unsigned long)e_IOC_FM_PORT_COUNTERS_DEQ_CONFIRM == (unsigned long)e_FM_PORT_COUNTERS_DEQ_CONFIRM);
+ ASSERT_COND((unsigned long)e_IOC_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_8 == (unsigned long)e_FM_PORT_DUAL_RATE_LIMITER_SCALE_DOWN_BY_8);
+
+ return;
+}
+
+static t_Error LnxwrpFmPcdIOCTL(t_LnxWrpFmDev *p_LnxWrpFmDev, unsigned int cmd, unsigned long arg, bool compat)
+{
+ t_Error err = E_OK;
+
+/*
+Status: PCD API to fmlib (file: drivers/net/dpa/NetCommSw/inc/Peripherals/fm_pcd_ext.h):
+
+ FM_PCD_PrsLoadSw
+ FM_PCD_SetAdvancedOffloadSupport
+ FM_PCD_Enable
+ FM_PCD_Disable
+ FM_PCD_ForceIntr
+ FM_PCD_SetException
+ FM_PCD_KgSetAdditionalDataAfterParsing
+ FM_PCD_KgSetDfltValue
+ FM_PCD_NetEnvCharacteristicsSet
+ FM_PCD_NetEnvCharacteristicsDelete
+ FM_PCD_KgSchemeSet
+ FM_PCD_KgSchemeDelete
+ FM_PCD_MatchTableSet
+ FM_PCD_MatchTableDelete
+ FM_PCD_CcRootBuild
+ FM_PCD_CcRootDelete
+ FM_PCD_PlcrProfileSet
+ FM_PCD_PlcrProfileDelete
+ FM_PCD_CcRootModifyNextEngine
+ FM_PCD_MatchTableModifyNextEngine
+ FM_PCD_MatchTableModifyMissNextEngine
+ FM_PCD_MatchTableRemoveKey
+ FM_PCD_MatchTableAddKey
+ FM_PCD_MatchTableModifyKeyAndNextEngine
+ FM_PCD_HashTableSet
+ FM_PCD_HashTableDelete
+ FM_PCD_HashTableAddKey
+ FM_PCD_HashTableRemoveKey
+ FM_PCD_MatchTableModifyKey
+ FM_PCD_ManipNodeReplace
+ FM_PCD_ManipNodeSet
+ FM_PCD_ManipNodeDelete
+
+Status: not exported, should be thru sysfs
+ FM_PCD_KgSchemeGetCounter
+ FM_PCD_KgSchemeSetCounter
+ FM_PCD_PlcrProfileGetCounter
+ FM_PCD_PlcrProfileSetCounter
+
+Status: not exported
+ FM_PCD_MatchTableFindNRemoveKey
+ FM_PCD_MatchTableFindNModifyNextEngine
+ FM_PCD_MatchTableFindNModifyKeyAndNextEngine
+ FM_PCD_MatchTableFindNModifyKey
+ FM_PCD_MatchTableGetIndexedHashBucket
+ FM_PCD_MatchTableGetNextEngine
+ FM_PCD_MatchTableGetKeyCounter
+
+Status: not exported, would be nice to have
+ FM_PCD_HashTableModifyNextEngine
+ FM_PCD_HashTableModifyMissNextEngine
+ FM_PCD_HashTableGetMissNextEngine
+ FM_PCD_ManipGetStatistics
+
+Status: not exported
+#if DPAA_VERSION >= 11
+
+ FM_VSP_GetStatistics -- it's not available yet
+#endif
+
+Status: feature not supported
+#ifdef FM_CAPWAP_SUPPORT
+#error unsupported feature
+ FM_PCD_StatisticsSetNode
+#endif
+
+ */
+ _fm_ioctl_dbg("cmd:0x%08x(type:0x%02x, nr:%u).\n",
+ cmd, _IOC_TYPE(cmd), _IOC_NR(cmd) - 20);
+
+ switch (cmd)
+ {
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_PRS_LOAD_SW_COMPAT:
+#endif
+ case FM_PCD_IOC_PRS_LOAD_SW:
+ {
+ ioc_fm_pcd_prs_sw_params_t *param;
+ uint8_t *p_code;
+
+ param = (ioc_fm_pcd_prs_sw_params_t *) XX_Malloc(sizeof(ioc_fm_pcd_prs_sw_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_prs_sw_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_prs_sw_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_prs_sw_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_prs_sw_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_prs_sw_params_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_prs_sw_params_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_prs_sw_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_fm_pcd_prs_sw(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_prs_sw_params_t *)arg,
+ sizeof(ioc_fm_pcd_prs_sw_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ if (!param->p_code || !param->size)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ p_code = (uint8_t *) XX_Malloc(param->size);
+ if (!p_code)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(p_code, 0, param->size);
+ if (copy_from_user(p_code, param->p_code, param->size))
+ {
+ XX_Free(p_code);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->p_code = p_code;
+
+ err = FM_PCD_PrsLoadSw(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdPrsSwParams*)param);
+
+ XX_Free(p_code);
+ XX_Free(param);
+ break;
+ }
+
+ case FM_PCD_IOC_SET_ADVANCED_OFFLOAD_SUPPORT:
+ err = FM_PCD_SetAdvancedOffloadSupport(p_LnxWrpFmDev->h_PcdDev);
+ break;
+
+ case FM_PCD_IOC_ENABLE:
+ err = FM_PCD_Enable(p_LnxWrpFmDev->h_PcdDev);
+ break;
+
+ case FM_PCD_IOC_DISABLE:
+ err = FM_PCD_Disable(p_LnxWrpFmDev->h_PcdDev);
+ break;
+
+ case FM_PCD_IOC_FORCE_INTR:
+ {
+ int exception;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (get_user(exception, (int *) compat_ptr(arg)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ else
+#endif
+ {
+ if (get_user(exception, (int *)arg))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PCD_ForceIntr(p_LnxWrpFmDev->h_PcdDev, (e_FmPcdExceptions)exception);
+ break;
+ }
+
+ case FM_PCD_IOC_SET_EXCEPTION:
+ {
+ ioc_fm_pcd_exception_params_t *param;
+
+ param = (ioc_fm_pcd_exception_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_exception_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_exception_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_exception_params_t *)compat_ptr(arg),
+ sizeof(ioc_fm_pcd_exception_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_exception_params_t *)arg,
+ sizeof(ioc_fm_pcd_exception_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PCD_SetException(p_LnxWrpFmDev->h_PcdDev, param->exception, param->enable);
+
+ XX_Free(param);
+ break;
+ }
+
+ case FM_PCD_IOC_KG_SET_ADDITIONAL_DATA_AFTER_PARSING:
+ {
+ uint8_t payloadOffset;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (get_user(payloadOffset, (uint8_t*) compat_ptr(arg)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ else
+#endif
+ {
+ if (get_user(payloadOffset, (uint8_t*) arg))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PCD_KgSetAdditionalDataAfterParsing(p_LnxWrpFmDev->h_PcdDev, payloadOffset);
+ break;
+ }
+
+ case FM_PCD_IOC_KG_SET_DFLT_VALUE:
+ {
+ ioc_fm_pcd_kg_dflt_value_params_t *param;
+
+ param = (ioc_fm_pcd_kg_dflt_value_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_kg_dflt_value_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_kg_dflt_value_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_kg_dflt_value_params_t *)compat_ptr(arg),
+ sizeof(ioc_fm_pcd_kg_dflt_value_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_kg_dflt_value_params_t *)arg,
+ sizeof(ioc_fm_pcd_kg_dflt_value_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PCD_KgSetDfltValue(p_LnxWrpFmDev->h_PcdDev, param->valueId, param->value);
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_NET_ENV_CHARACTERISTICS_SET_COMPAT:
+#endif
+ case FM_PCD_IOC_NET_ENV_CHARACTERISTICS_SET:
+ {
+ ioc_fm_pcd_net_env_params_t *param;
+
+ param = (ioc_fm_pcd_net_env_params_t *) XX_Malloc(sizeof(ioc_fm_pcd_net_env_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_net_env_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_net_env_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_net_env_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_net_env_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_net_env_params_t));
+ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_net_env_params_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_net_env_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_net_env(compat_param, param, COMPAT_US_TO_K);
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_net_env_params_t *) arg,
+ sizeof(ioc_fm_pcd_net_env_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ param->id = FM_PCD_NetEnvCharacteristicsSet(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdNetEnvParams*)param);
+
+ if (!param->id)
+ {
+ XX_Free(param);
+ err = E_INVALID_VALUE;
+ /* Since the LLD has no errno-style error reporting,
+ we're left here with no other option than to report
+ a generic E_INVALID_VALUE */
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_net_env_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_net_env_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_net_env_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_net_env_params_t));
+ compat_copy_fm_pcd_net_env(compat_param, param, COMPAT_K_TO_US);
+
+ if (copy_to_user((ioc_compat_fm_pcd_net_env_params_t *) compat_ptr(arg),
+ compat_param,
+ sizeof(ioc_compat_fm_pcd_net_env_params_t)))
+ err = E_READ_FAILED;
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_pcd_net_env_params_t *)arg,
+ param,
+ sizeof(ioc_fm_pcd_net_env_params_t)))
+ err = E_READ_FAILED;
+ }
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_NET_ENV_CHARACTERISTICS_DELETE_COMPAT:
+#endif
+ case FM_PCD_IOC_NET_ENV_CHARACTERISTICS_DELETE:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0 , sizeof(ioc_fm_obj_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_obj_delete(&compat_id, &id);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PCD_NetEnvCharacteristicsDelete(id.obj);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_KG_SCHEME_SET_COMPAT:
+#endif
+ case FM_PCD_IOC_KG_SCHEME_SET:
+ {
+ ioc_fm_pcd_kg_scheme_params_t *param;
+
+ param = (ioc_fm_pcd_kg_scheme_params_t *) XX_Malloc(sizeof(ioc_fm_pcd_kg_scheme_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_kg_scheme_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_kg_scheme_params_t *compat_param = NULL;
+
+ compat_param = (ioc_compat_fm_pcd_kg_scheme_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_kg_scheme_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_kg_scheme_params_t));
+
+ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_kg_scheme_params_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_kg_scheme_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_kg_scheme(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_kg_scheme_params_t *)arg,
+ sizeof(ioc_fm_pcd_kg_scheme_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ param->id = FM_PCD_KgSchemeSet(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdKgSchemeParams*)param);
+
+ if (!param->id)
+ {
+ XX_Free(param);
+ err = E_INVALID_VALUE;
+ /* Since the LLD has no errno-style error reporting,
+ we're left here with no other option than to report
+ a generic E_INVALID_VALUE */
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_kg_scheme_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_kg_scheme_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_kg_scheme_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_kg_scheme_params_t));
+ compat_copy_fm_pcd_kg_scheme(compat_param, param, COMPAT_K_TO_US);
+ if (copy_to_user((ioc_compat_fm_pcd_kg_scheme_params_t *)compat_ptr(arg),
+ compat_param,
+ sizeof(ioc_compat_fm_pcd_kg_scheme_params_t)))
+ err = E_READ_FAILED;
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_pcd_kg_scheme_params_t *)arg,
+ param,
+ sizeof(ioc_fm_pcd_kg_scheme_params_t)))
+ err = E_READ_FAILED;
+ }
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_KG_SCHEME_DELETE_COMPAT:
+#endif
+ case FM_PCD_IOC_KG_SCHEME_DELETE:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0 , sizeof(ioc_fm_obj_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_obj_delete(&compat_id, &id);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PCD_KgSchemeDelete(id.obj);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_MATCH_TABLE_SET_COMPAT:
+#endif
+ case FM_PCD_IOC_MATCH_TABLE_SET:
+ {
+ ioc_fm_pcd_cc_node_params_t *param;
+ uint8_t *keys;
+ uint8_t *masks;
+ int i,k;
+
+ param = (ioc_fm_pcd_cc_node_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_cc_node_params_t) +
+ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY);
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_params_t) +
+ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY);
+
+ keys = (uint8_t *) (param + 1);
+ masks = keys + IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_node_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_node_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_node_params_t) +
+ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY);
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_params_t) +
+ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY);
+
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_cc_node_params_t *)compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_cc_node_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_cc_node(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_cc_node_params_t *)arg, sizeof(ioc_fm_pcd_cc_node_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ ASSERT_COND(param->keys_params.num_of_keys <= IOC_FM_PCD_MAX_NUM_OF_KEYS);
+ ASSERT_COND(param->keys_params.key_size <= IOC_FM_PCD_MAX_SIZE_OF_KEY);
+
+ /* support for indexed lookup */
+ if( !(param->extract_cc_params.type == e_IOC_FM_PCD_EXTRACT_NON_HDR &&
+ param->extract_cc_params.extract_params.extract_non_hdr.src == e_IOC_FM_PCD_EXTRACT_FROM_HASH &&
+ param->extract_cc_params.extract_params.extract_non_hdr.action == e_IOC_FM_PCD_ACTION_INDEXED_LOOKUP))
+ {
+ for (i=0, k=0;
+ i < param->keys_params.num_of_keys;
+ i++, k += IOC_FM_PCD_MAX_SIZE_OF_KEY)
+ {
+ if (param->keys_params.key_params[i].p_key &&
+ param->keys_params.key_size)
+ {
+ if (copy_from_user(&keys[k],
+ param->keys_params.key_params[i].p_key,
+ param->keys_params.key_size))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->keys_params.key_params[i].p_key = &keys[k];
+ }
+
+ if (param->keys_params.key_params[i].p_mask)
+ {
+ if (copy_from_user(&masks[k],
+ param->keys_params.key_params[i].p_mask,
+ param->keys_params.key_size))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->keys_params.key_params[i].p_mask = &masks[k];
+ }
+ }
+ }
+
+ param->id = FM_PCD_MatchTableSet(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdCcNodeParams*)param);
+
+ if (!param->id) {
+ XX_Free(param);
+ err = E_INVALID_VALUE;
+ /* Since the LLD has no errno-style error reporting,
+ we're left here with no other option than to report
+ a generic E_INVALID_VALUE */
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_node_params_t *compat_param;
+ compat_param = (ioc_compat_fm_pcd_cc_node_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_node_params_t) +
+ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY);
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_params_t) +
+ 2 * IOC_FM_PCD_MAX_NUM_OF_KEYS * IOC_FM_PCD_MAX_SIZE_OF_KEY);
+ compat_copy_fm_pcd_cc_node(compat_param, param, COMPAT_K_TO_US);
+
+ if (copy_to_user((ioc_compat_fm_pcd_cc_node_params_t *)compat_ptr(arg),
+ compat_param,
+ sizeof(ioc_compat_fm_pcd_cc_node_params_t)))
+ err = E_READ_FAILED;
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_pcd_cc_node_params_t *)arg,
+ param,
+ sizeof(ioc_fm_pcd_cc_node_params_t)))
+ err = E_READ_FAILED;
+ }
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_MATCH_TABLE_DELETE_COMPAT:
+#endif
+ case FM_PCD_IOC_MATCH_TABLE_DELETE:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0 , sizeof(ioc_fm_obj_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_obj_delete(&compat_id, &id);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PCD_MatchTableDelete(id.obj);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_CC_ROOT_BUILD_COMPAT:
+#endif
+ case FM_PCD_IOC_CC_ROOT_BUILD:
+ {
+ ioc_fm_pcd_cc_tree_params_t *param;
+
+ param = (ioc_fm_pcd_cc_tree_params_t *) XX_Malloc(sizeof(ioc_fm_pcd_cc_tree_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_cc_tree_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_tree_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_tree_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_tree_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tree_params_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_cc_tree_params_t *)compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_cc_tree_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_cc_tree(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_cc_tree_params_t *)arg,
+ sizeof(ioc_fm_pcd_cc_tree_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ param->id = FM_PCD_CcRootBuild(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdCcTreeParams*)param);
+
+ if (!param->id) {
+ XX_Free(param);
+ err = E_INVALID_VALUE;
+ /* Since the LLD has no errno-style error reporting,
+ we're left here with no other option than to report
+ a generic E_INVALID_VALUE */
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_tree_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_tree_params_t *) XX_Malloc(sizeof(ioc_compat_fm_pcd_cc_tree_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tree_params_t));
+
+ compat_copy_fm_pcd_cc_tree(compat_param, param, COMPAT_K_TO_US);
+
+ if (copy_to_user((ioc_compat_fm_pcd_cc_tree_params_t *)compat_ptr(arg),
+ compat_param,
+ sizeof(ioc_compat_fm_pcd_cc_tree_params_t)))
+ err = E_READ_FAILED;
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_pcd_cc_tree_params_t *)arg,
+ param,
+ sizeof(ioc_fm_pcd_cc_tree_params_t)))
+ err = E_READ_FAILED;
+ }
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_CC_ROOT_DELETE_COMPAT:
+#endif
+ case FM_PCD_IOC_CC_ROOT_DELETE:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0 , sizeof(ioc_fm_obj_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_obj_delete(&compat_id, &id);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PCD_CcRootDelete(id.obj);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_PLCR_PROFILE_SET_COMPAT:
+#endif
+ case FM_PCD_IOC_PLCR_PROFILE_SET:
+ {
+ ioc_fm_pcd_plcr_profile_params_t *param;
+
+ param = (ioc_fm_pcd_plcr_profile_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_plcr_profile_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_plcr_profile_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_plcr_profile_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_plcr_profile_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_plcr_profile_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_plcr_profile_params_t));
+ if (copy_from_user(compat_param, (
+ ioc_compat_fm_pcd_plcr_profile_params_t *)compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_plcr_profile_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_plcr_profile(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_plcr_profile_params_t *)arg,
+ sizeof(ioc_fm_pcd_plcr_profile_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ if (!param->modify &&
+ (((t_FmPcdPlcrProfileParams*)param)->id.newParams.profileType != e_FM_PCD_PLCR_SHARED))
+ {
+ t_Handle h_Port;
+ ioc_fm_pcd_port_params_t *port_params;
+
+ port_params = (ioc_fm_pcd_port_params_t*) XX_Malloc(sizeof(ioc_fm_pcd_port_params_t));
+ if (!port_params)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(port_params, 0, sizeof(ioc_fm_pcd_port_params_t));
+ if (copy_from_user(port_params, (ioc_fm_pcd_port_params_t*)((t_FmPcdPlcrProfileParams*)param)->id.newParams.h_FmPort,
+ sizeof(ioc_fm_pcd_port_params_t)))
+ {
+ XX_Free(port_params);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ switch(port_params->port_type)
+ {
+ case (e_IOC_FM_PORT_TYPE_RX):
+ if (port_params->port_id < FM_MAX_NUM_OF_1G_RX_PORTS) {
+ h_Port = p_LnxWrpFmDev->rxPorts[port_params->port_id].h_Dev;
+ break;
+ }
+ goto invalid_port_id;
+
+ case (e_IOC_FM_PORT_TYPE_RX_10G):
+ if (port_params->port_id < FM_MAX_NUM_OF_10G_RX_PORTS) {
+ h_Port = p_LnxWrpFmDev->rxPorts[port_params->port_id + FM_MAX_NUM_OF_1G_RX_PORTS].h_Dev;
+ break;
+ }
+ goto invalid_port_id;
+
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ if (port_params->port_id && port_params->port_id < FM_MAX_NUM_OF_OH_PORTS) {
+ h_Port = p_LnxWrpFmDev->opPorts[port_params->port_id - 1].h_Dev;
+ break;
+ }
+ goto invalid_port_id;
+
+ default:
+invalid_port_id:
+ XX_Free(port_params);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION, NO_MSG);
+ }
+
+ ((t_FmPcdPlcrProfileParams*)param)->id.newParams.h_FmPort = h_Port;
+ XX_Free(port_params);
+ }
+
+ param->id = FM_PCD_PlcrProfileSet(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdPlcrProfileParams*)param);
+
+ if (!param->id) {
+ XX_Free(param);
+ err = E_INVALID_VALUE;
+ /* Since the LLD has no errno-style error reporting,
+ we're left here with no other option than to report
+ a generic E_INVALID_VALUE */
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_plcr_profile_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_plcr_profile_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_plcr_profile_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_plcr_profile_params_t));
+ compat_copy_fm_pcd_plcr_profile(compat_param, param, COMPAT_K_TO_US);
+ if (copy_to_user((ioc_compat_fm_pcd_plcr_profile_params_t *) compat_ptr(arg),
+ compat_param,
+ sizeof(ioc_compat_fm_pcd_plcr_profile_params_t)))
+ err = E_READ_FAILED;
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_pcd_plcr_profile_params_t *)arg,
+ param,
+ sizeof(ioc_fm_pcd_plcr_profile_params_t)))
+ err = E_READ_FAILED;
+ }
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_PLCR_PROFILE_DELETE_COMPAT:
+#endif
+ case FM_PCD_IOC_PLCR_PROFILE_DELETE:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0 , sizeof(ioc_fm_obj_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_obj_delete(&compat_id, &id);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PCD_PlcrProfileDelete(id.obj);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_CC_ROOT_MODIFY_NEXT_ENGINE_COMPAT:
+#endif
+ case FM_PCD_IOC_CC_ROOT_MODIFY_NEXT_ENGINE:
+ {
+ ioc_fm_pcd_cc_tree_modify_next_engine_params_t *param;
+
+ param = (ioc_fm_pcd_cc_tree_modify_next_engine_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_cc_tree_modify_next_engine_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_cc_tree_modify_next_engine_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t));
+ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_fm_pcd_cc_tree_modify_next_engine(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_cc_tree_modify_next_engine_params_t *)arg,
+ sizeof(ioc_fm_pcd_cc_tree_modify_next_engine_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PCD_CcRootModifyNextEngine(param->id,
+ param->grp_indx,
+ param->indx,
+ (t_FmPcdCcNextEngineParams*)(&param->cc_next_engine_params));
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_MATCH_TABLE_MODIFY_NEXT_ENGINE_COMPAT:
+#endif
+ case FM_PCD_IOC_MATCH_TABLE_MODIFY_NEXT_ENGINE:
+ {
+ ioc_fm_pcd_cc_node_modify_next_engine_params_t *param;
+
+ param = (ioc_fm_pcd_cc_node_modify_next_engine_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t));
+ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_cc_node_modify_next_engine(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_cc_node_modify_next_engine_params_t *)arg,
+ sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PCD_MatchTableModifyNextEngine(param->id,
+ param->key_indx,
+ (t_FmPcdCcNextEngineParams*)(&param->cc_next_engine_params));
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_MATCH_TABLE_MODIFY_MISS_NEXT_ENGINE_COMPAT:
+#endif
+ case FM_PCD_IOC_MATCH_TABLE_MODIFY_MISS_NEXT_ENGINE:
+ {
+ ioc_fm_pcd_cc_node_modify_next_engine_params_t *param;
+
+ param = (ioc_fm_pcd_cc_node_modify_next_engine_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t));
+ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_cc_node_modify_next_engine(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_cc_node_modify_next_engine_params_t *) arg,
+ sizeof(ioc_fm_pcd_cc_node_modify_next_engine_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PCD_MatchTableModifyMissNextEngine(param->id,
+ (t_FmPcdCcNextEngineParams*)(&param->cc_next_engine_params));
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_MATCH_TABLE_REMOVE_KEY_COMPAT:
+#endif
+ case FM_PCD_IOC_MATCH_TABLE_REMOVE_KEY:
+ {
+ ioc_fm_pcd_cc_node_remove_key_params_t *param;
+
+ param = (ioc_fm_pcd_cc_node_remove_key_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_cc_node_remove_key_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_remove_key_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_node_remove_key_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_node_remove_key_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_node_remove_key_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_remove_key_params_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_cc_node_remove_key_params_t *)compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_cc_node_remove_key_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->id = compat_ptr(compat_param->id);
+ param->key_indx = compat_param->key_indx;
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_cc_node_remove_key_params_t *) arg,
+ sizeof(ioc_fm_pcd_cc_node_remove_key_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PCD_MatchTableRemoveKey(param->id, param->key_indx);
+
+ XX_Free(param);
+ break;
+ }
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_MATCH_TABLE_ADD_KEY_COMPAT:
+#endif
+ case FM_PCD_IOC_MATCH_TABLE_ADD_KEY:
+ {
+ ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *param;
+
+ param = (ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *)compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_cc_node_modify_key_and_next_engine(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *)arg,
+ sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ if (param->key_size)
+ {
+ int size = 0;
+
+ if (param->key_params.p_key) size += param->key_size;
+ if (param->key_params.p_mask) size += param->key_size;
+
+ if (size)
+ {
+ uint8_t *p_tmp;
+
+ p_tmp = (uint8_t*) XX_Malloc(size);
+ if (!p_tmp)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD key/mask"));
+ }
+
+ if (param->key_params.p_key)
+ {
+ if (copy_from_user(p_tmp, param->key_params.p_key, param->key_size))
+ {
+ XX_Free(p_tmp);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->key_params.p_key = p_tmp;
+ }
+
+ if (param->key_params.p_mask)
+ {
+ p_tmp += param->key_size;
+ if (copy_from_user(p_tmp, param->key_params.p_mask, param->key_size))
+ {
+ XX_Free(p_tmp - param->key_size);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->key_params.p_mask = p_tmp;
+ }
+ }
+ }
+
+ err = FM_PCD_MatchTableAddKey(
+ param->id,
+ param->key_indx,
+ param->key_size,
+ (t_FmPcdCcKeyParams*)&param->key_params);
+
+ if (param->key_params.p_key)
+ XX_Free(param->key_params.p_key);
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY_AND_NEXT_ENGINE_COMPAT:
+#endif
+ case FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY_AND_NEXT_ENGINE:
+ {
+ ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *param;
+
+ param = (ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *)compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_cc_node_modify_key_and_next_engine(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *)arg,
+ sizeof(ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PCD_MatchTableModifyKeyAndNextEngine(param->id,
+ param->key_indx,
+ param->key_size,
+ (t_FmPcdCcKeyParams*)(&param->key_params));
+
+ XX_Free(param);
+ break;
+ }
+
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_MATCH_TABLE_GET_MISS_STAT_COMPAT:
+#endif
+ case FM_PCD_IOC_MATCH_TABLE_GET_MISS_STAT:
+ {
+ ioc_fm_pcd_cc_tbl_get_miss_params_t param;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_tbl_get_miss_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_tbl_get_miss_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t));
+ if (!compat_param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_cc_tbl_get_miss_params_t *)compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t)))
+ {
+ XX_Free(compat_param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_cc_tbl_get_miss(compat_param, &param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&param, (ioc_fm_pcd_cc_tbl_get_miss_params_t *)arg,
+ sizeof(ioc_fm_pcd_cc_tbl_get_miss_params_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+
+ err = FM_PCD_MatchTableGetMissStatistics((t_Handle) param.id,
+ (t_FmPcdCcKeyStatistics *) &param.miss_statistics);
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_tbl_get_miss_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_tbl_get_miss_params_t*) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t));
+ if (!compat_param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t));
+ compat_copy_fm_pcd_cc_tbl_get_miss(compat_param, &param, COMPAT_K_TO_US);
+ if (copy_to_user((ioc_compat_fm_pcd_cc_tbl_get_miss_params_t*) compat_ptr(arg),
+ compat_param,
+ sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t)))
+ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_pcd_hash_table_params_t *)arg,
+ &param,
+ sizeof(ioc_fm_pcd_cc_tbl_get_miss_params_t)))
+ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG);
+ }
+
+ break;
+ }
+
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_HASH_TABLE_GET_MISS_STAT_COMPAT:
+#endif
+ case FM_PCD_IOC_HASH_TABLE_GET_MISS_STAT:
+ {
+ ioc_fm_pcd_cc_tbl_get_miss_params_t param;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_tbl_get_miss_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_tbl_get_miss_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t));
+ if (!compat_param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_cc_tbl_get_miss_params_t *)compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t)))
+ {
+ XX_Free(compat_param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_cc_tbl_get_miss(compat_param, &param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&param, (ioc_fm_pcd_cc_tbl_get_miss_params_t *)arg,
+ sizeof(ioc_fm_pcd_cc_tbl_get_miss_params_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+
+ err = FM_PCD_HashTableGetMissStatistics((t_Handle) param.id,
+ (t_FmPcdCcKeyStatistics *) &param.miss_statistics);
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_tbl_get_miss_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_tbl_get_miss_params_t*) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t));
+ if (!compat_param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t));
+ compat_copy_fm_pcd_cc_tbl_get_miss(compat_param, &param, COMPAT_K_TO_US);
+ if (copy_to_user((ioc_compat_fm_pcd_cc_tbl_get_miss_params_t*) compat_ptr(arg),
+ compat_param,
+ sizeof(ioc_compat_fm_pcd_cc_tbl_get_miss_params_t)))
+ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_pcd_hash_table_params_t *)arg,
+ &param,
+ sizeof(ioc_fm_pcd_cc_tbl_get_miss_params_t)))
+ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG);
+ }
+
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_HASH_TABLE_SET_COMPAT:
+#endif
+ case FM_PCD_IOC_HASH_TABLE_SET:
+ {
+ ioc_fm_pcd_hash_table_params_t *param;
+
+ param = (ioc_fm_pcd_hash_table_params_t*) XX_Malloc(
+ sizeof(ioc_fm_pcd_hash_table_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_hash_table_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_hash_table_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_hash_table_params_t*) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_hash_table_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_hash_table_params_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_hash_table_params_t*)compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_hash_table_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_hash_table(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_hash_table_params_t *)arg,
+ sizeof(ioc_fm_pcd_hash_table_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ param->id = FM_PCD_HashTableSet(p_LnxWrpFmDev->h_PcdDev, (t_FmPcdHashTableParams *) param);
+
+ if (!param->id)
+ {
+ XX_Free(param);
+ err = E_INVALID_VALUE;
+ /* Since the LLD has no errno-style error reporting,
+ we're left here with no other option than to report
+ a generic E_INVALID_VALUE */
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_hash_table_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_hash_table_params_t*) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_hash_table_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_hash_table_params_t));
+ compat_copy_fm_pcd_hash_table(compat_param, param, COMPAT_K_TO_US);
+ if (copy_to_user((ioc_compat_fm_pcd_hash_table_params_t*) compat_ptr(arg),
+ compat_param,
+ sizeof(ioc_compat_fm_pcd_hash_table_params_t)))
+ err = E_READ_FAILED;
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_pcd_hash_table_params_t *)arg,
+ param,
+ sizeof(ioc_fm_pcd_hash_table_params_t)))
+ err = E_READ_FAILED;
+ }
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_HASH_TABLE_DELETE_COMPAT:
+#endif
+ case FM_PCD_IOC_HASH_TABLE_DELETE:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0, sizeof(ioc_fm_obj_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ id.obj = compat_pcd_id2ptr(compat_id.obj);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PCD_HashTableDelete(id.obj);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_HASH_TABLE_ADD_KEY_COMPAT:
+#endif
+ case FM_PCD_IOC_HASH_TABLE_ADD_KEY:
+ {
+ ioc_fm_pcd_hash_table_add_key_params_t *param = NULL;
+
+ param = (ioc_fm_pcd_hash_table_add_key_params_t*) XX_Malloc(
+ sizeof(ioc_fm_pcd_hash_table_add_key_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_hash_table_add_key_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_hash_table_add_key_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_hash_table_add_key_params_t*) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_hash_table_add_key_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_hash_table_add_key_params_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_hash_table_add_key_params_t*) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_hash_table_add_key_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ if (compat_param->key_size)
+ {
+ param->p_hash_tbl = compat_pcd_id2ptr(compat_param->p_hash_tbl);
+ param->key_size = compat_param->key_size;
+
+ compat_copy_fm_pcd_cc_key(&compat_param->key_params, &param->key_params, COMPAT_US_TO_K);
+ }
+ else
+ {
+ XX_Free(compat_param);
+ err = E_INVALID_VALUE;
+ break;
+ }
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_hash_table_add_key_params_t*) arg,
+ sizeof(ioc_fm_pcd_hash_table_add_key_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ if (param->key_size)
+ {
+ int size = 0;
+
+ if (param->key_params.p_key) size += param->key_size;
+ if (param->key_params.p_mask) size += param->key_size;
+
+ if (size)
+ {
+ uint8_t *p_tmp;
+
+ p_tmp = (uint8_t*) XX_Malloc(size);
+ if (!p_tmp)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD key/mask"));
+ }
+
+ if (param->key_params.p_key)
+ {
+ if (copy_from_user(p_tmp, param->key_params.p_key, param->key_size))
+ {
+ XX_Free(p_tmp);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->key_params.p_key = p_tmp;
+ }
+
+ if (param->key_params.p_mask)
+ {
+ p_tmp += param->key_size;
+ if (copy_from_user(p_tmp, param->key_params.p_mask, param->key_size))
+ {
+ XX_Free(p_tmp - param->key_size);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->key_params.p_mask = p_tmp;
+ }
+ }
+ }
+
+ err = FM_PCD_HashTableAddKey(
+ param->p_hash_tbl,
+ param->key_size,
+ (t_FmPcdCcKeyParams*)&param->key_params);
+
+ if (param->key_params.p_key)
+ XX_Free(param->key_params.p_key);
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_HASH_TABLE_REMOVE_KEY_COMPAT:
+#endif
+ case FM_PCD_IOC_HASH_TABLE_REMOVE_KEY:
+ {
+ ioc_fm_pcd_hash_table_remove_key_params_t *param = NULL;
+
+ param = (ioc_fm_pcd_hash_table_remove_key_params_t*) XX_Malloc(
+ sizeof(ioc_fm_pcd_hash_table_remove_key_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_hash_table_remove_key_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_hash_table_remove_key_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_hash_table_remove_key_params_t*) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_hash_table_remove_key_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_hash_table_remove_key_params_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_hash_table_remove_key_params_t*) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_hash_table_remove_key_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->p_hash_tbl = compat_pcd_id2ptr(compat_param->p_hash_tbl);
+ param->key_size = compat_param->key_size;
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_hash_table_remove_key_params_t*)arg,
+ sizeof(ioc_fm_pcd_hash_table_remove_key_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ if (param->key_size)
+ {
+ uint8_t *p_key;
+
+ p_key = (uint8_t*) XX_Malloc(param->key_size);
+ if (!p_key)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ if (param->p_key && copy_from_user(p_key, param->p_key, param->key_size))
+ {
+ XX_Free(p_key);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ param->p_key = p_key;
+ }
+
+ err = FM_PCD_HashTableRemoveKey(
+ param->p_hash_tbl,
+ param->key_size,
+ param->p_key);
+
+ if (param->p_key)
+ XX_Free(param->p_key);
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY_COMPAT:
+#endif
+ case FM_PCD_IOC_MATCH_TABLE_MODIFY_KEY:
+ {
+ ioc_fm_pcd_cc_node_modify_key_params_t *param;
+
+ param = (ioc_fm_pcd_cc_node_modify_key_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_cc_node_modify_key_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_cc_node_modify_key_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_cc_node_modify_key_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_cc_node_modify_key_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_cc_node_modify_key_params_t));
+ if (copy_from_user(compat_param, (ioc_compat_fm_pcd_cc_node_modify_key_params_t *)compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_cc_node_modify_key_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_cc_node_modify_key(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_cc_node_modify_key_params_t *)arg,
+ sizeof(ioc_fm_pcd_cc_node_modify_key_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ if (param->key_size)
+ {
+ int size = 0;
+
+ if (param->p_key) size += param->key_size;
+ if (param->p_mask) size += param->key_size;
+
+ if (size)
+ {
+ uint8_t *p_tmp;
+
+ p_tmp = (uint8_t*) XX_Malloc(size);
+ if (!p_tmp)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD key/mask"));
+ }
+
+ if (param->p_key)
+ {
+ if (copy_from_user(p_tmp, param->p_key, param->key_size))
+ {
+ XX_Free(p_tmp);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->p_key = p_tmp;
+ }
+
+ if (param->p_mask)
+ {
+ p_tmp += param->key_size;
+ if (copy_from_user(p_tmp, param->p_mask, param->key_size))
+ {
+ XX_Free(p_tmp - param->key_size);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->p_mask = p_tmp;
+ }
+ }
+ }
+
+ err = FM_PCD_MatchTableModifyKey(param->id,
+ param->key_indx,
+ param->key_size,
+ param->p_key,
+ param->p_mask);
+
+ if (param->p_key)
+ XX_Free(param->p_key);
+ else if (param->p_mask)
+ XX_Free(param->p_mask);
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_MANIP_NODE_SET_COMPAT:
+#endif
+ case FM_PCD_IOC_MANIP_NODE_SET:
+ {
+ ioc_fm_pcd_manip_params_t *param;
+ uint8_t *p_data = NULL;
+ uint8_t size;
+
+ param = (ioc_fm_pcd_manip_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_manip_params_t));
+
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_manip_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_manip_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_manip_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_manip_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_manip_params_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_manip_params_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_manip_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_fm_pcd_manip_set_node(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_manip_params_t *)arg,
+ sizeof(ioc_fm_pcd_manip_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ if (param->type == e_IOC_FM_PCD_MANIP_HDR)
+ {
+ size = param->u.hdr.insrt_params.u.generic.size;
+ p_data = (uint8_t *) XX_Malloc(size);
+ if (!p_data )
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, NO_MSG);
+ }
+
+ if (param->u.hdr.insrt_params.u.generic.p_data &&
+ copy_from_user(p_data,
+ param->u.hdr.insrt_params.u.generic.p_data, size))
+ {
+ XX_Free(p_data);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ param->u.hdr.insrt_params.u.generic.p_data = p_data;
+ }
+
+ if (param->id)
+ {
+ /* Security Hole: the user can pass any piece of garbage
+ in 'param->id', and that will go straight through to the LLD,
+ no checks being done by the wrapper! */
+ err = FM_PCD_ManipNodeReplace(
+ (t_Handle) param->id,
+ (t_FmPcdManipParams*) param);
+ if (err)
+ {
+ if (p_data)
+ XX_Free(p_data);
+ XX_Free(param);
+ break;
+ }
+ }
+ else
+ {
+ param->id = FM_PCD_ManipNodeSet(
+ p_LnxWrpFmDev->h_PcdDev,
+ (t_FmPcdManipParams*) param);
+ if (!param->id)
+ {
+ if (p_data)
+ XX_Free(p_data);
+ XX_Free(param);
+ err = E_INVALID_VALUE;
+ /* Since the LLD has no errno-style error reporting,
+ we're left here with no other option than to report
+ a generic E_INVALID_VALUE */
+ break;
+ }
+ }
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_manip_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_manip_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_manip_params_t));
+ if (!compat_param)
+ {
+ if (p_data)
+ XX_Free(p_data);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_manip_params_t));
+
+ compat_fm_pcd_manip_set_node(compat_param, param, COMPAT_K_TO_US);
+
+ if (copy_to_user((ioc_compat_fm_pcd_manip_params_t *) compat_ptr(arg),
+ compat_param,
+ sizeof(ioc_compat_fm_pcd_manip_params_t)))
+ err = E_READ_FAILED;
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_pcd_manip_params_t *)arg,
+ param, sizeof(ioc_fm_pcd_manip_params_t)))
+ err = E_READ_FAILED;
+ }
+
+ if (p_data)
+ XX_Free(p_data);
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_MANIP_NODE_DELETE_COMPAT:
+#endif
+ case FM_PCD_IOC_MANIP_NODE_DELETE:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0, sizeof(ioc_fm_obj_t));
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_obj_delete(&compat_id, &id);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PCD_ManipNodeDelete(id.obj);
+ break;
+ }
+
+#if (DPAA_VERSION >= 11)
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_FRM_REPLIC_GROUP_SET_COMPAT:
+#endif
+ case FM_PCD_IOC_FRM_REPLIC_GROUP_SET:
+ {
+ ioc_fm_pcd_frm_replic_group_params_t *param;
+
+ param = (ioc_fm_pcd_frm_replic_group_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_frm_replic_group_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_frm_replic_group_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_frm_replic_group_params_t
+ *compat_param;
+
+ compat_param =
+ (ioc_compat_fm_pcd_frm_replic_group_params_t *)
+ XX_Malloc(sizeof(ioc_compat_fm_pcd_frm_replic_group_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY,
+ ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_frm_replic_group_params_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_frm_replic_group_params_t *)
+ compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_frm_replic_group_params_t))) {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_frm_replic_group_params(compat_param,
+ param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param,
+ (ioc_fm_pcd_frm_replic_group_params_t *)arg,
+ sizeof(ioc_fm_pcd_frm_replic_group_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG);
+ }
+ }
+
+ param->id = FM_PCD_FrmReplicSetGroup(p_LnxWrpFmDev->h_PcdDev,
+ (t_FmPcdFrmReplicGroupParams*)param);
+
+ if (!param->id) {
+ XX_Free(param);
+ err = E_INVALID_VALUE;
+ /*
+ * Since the LLD has no errno-style error reporting,
+ * we're left here with no other option than to report
+ * a generic E_INVALID_VALUE
+ */
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_frm_replic_group_params_t
+ *compat_param;
+
+ compat_param =
+ (ioc_compat_fm_pcd_frm_replic_group_params_t *)
+ XX_Malloc(sizeof(ioc_compat_fm_pcd_frm_replic_group_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY,
+ ("IOCTL FM PCD"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_frm_replic_group_params_t));
+ compat_copy_fm_pcd_frm_replic_group_params(compat_param,
+ param, COMPAT_K_TO_US);
+ if (copy_to_user(
+ (ioc_compat_fm_pcd_frm_replic_group_params_t *)
+ compat_ptr(arg),
+ compat_param,
+ sizeof(ioc_compat_fm_pcd_frm_replic_group_params_t)))
+ err = E_WRITE_FAILED;
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_to_user(
+ (ioc_fm_pcd_frm_replic_group_params_t *)arg,
+ param,
+ sizeof(ioc_fm_pcd_frm_replic_group_params_t)))
+ err = E_WRITE_FAILED;
+ }
+
+ XX_Free(param);
+ break;
+ }
+ break;
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_FRM_REPLIC_GROUP_DELETE_COMPAT:
+#endif
+ case FM_PCD_IOC_FRM_REPLIC_GROUP_DELETE:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0, sizeof(ioc_fm_obj_t));
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id,
+ (ioc_compat_fm_obj_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_obj_t)))
+ break;
+ compat_obj_delete(&compat_id, &id);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg,
+ sizeof(ioc_fm_obj_t)))
+ break;
+ }
+
+ return FM_PCD_FrmReplicDeleteGroup(id.obj);
+ }
+ break;
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_FRM_REPLIC_MEMBER_ADD_COMPAT:
+#endif
+ case FM_PCD_IOC_FRM_REPLIC_MEMBER_ADD:
+ {
+ ioc_fm_pcd_frm_replic_member_params_t param;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_frm_replic_member_params_t compat_param;
+
+ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_copy_fm_pcd_frm_replic_member_params(&compat_param, &param, COMPAT_US_TO_K);
+ }
+ else
+#endif
+ if (copy_from_user(&param, (void *)arg, sizeof(param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ return FM_PCD_FrmReplicAddMember(param.member.h_replic_group,
+ param.member.member_index,
+ (t_FmPcdCcNextEngineParams*)&param.next_engine_params);
+ }
+ break;
+
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_FRM_REPLIC_MEMBER_REMOVE_COMPAT:
+#endif
+ case FM_PCD_IOC_FRM_REPLIC_MEMBER_REMOVE:
+ {
+ ioc_fm_pcd_frm_replic_member_t param;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_frm_replic_member_t compat_param;
+
+ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_copy_fm_pcd_frm_replic_member(&compat_param, &param, COMPAT_US_TO_K);
+ }
+ else
+#endif
+ if (copy_from_user(&param, (void *)arg, sizeof(param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ return FM_PCD_FrmReplicRemoveMember(param.h_replic_group, param.member_index);
+ }
+ break;
+
+#if defined(CONFIG_COMPAT)
+ case FM_IOC_VSP_CONFIG_COMPAT:
+#endif
+ case FM_IOC_VSP_CONFIG:
+ {
+ ioc_fm_vsp_params_t param;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_vsp_params_t compat_param;
+
+ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_copy_fm_vsp_params(&compat_param, &param, COMPAT_US_TO_K);
+ }
+ else
+#endif
+ if (copy_from_user(&param, (void *)arg, sizeof(param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ {
+ uint8_t portId = param.port_params.port_id;
+ param.p_fm = p_LnxWrpFmDev->h_Dev;
+ param.liodn_offset =
+ p_LnxWrpFmDev->rxPorts[portId].settings.param.specificParams.rxParams.liodnOffset;
+ }
+ param.id = FM_VSP_Config((t_FmVspParams *)&param);
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_vsp_params_t compat_param;
+
+ memset(&compat_param, 0, sizeof(compat_param));
+ compat_copy_fm_vsp_params(&compat_param, &param, COMPAT_K_TO_US);
+
+ if (copy_to_user(compat_ptr(arg), &compat_param, sizeof(compat_param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ else
+#endif
+ if (copy_to_user((void *)arg, &param, sizeof(param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_IOC_VSP_INIT_COMPAT:
+#endif
+ case FM_IOC_VSP_INIT:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0, sizeof(ioc_fm_obj_t));
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id,
+ (ioc_compat_fm_obj_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_obj_t)))
+ break;
+ id.obj = compat_pcd_id2ptr(compat_id.obj);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg,
+ sizeof(ioc_fm_obj_t)))
+ break;
+ }
+
+ return FM_VSP_Init(id.obj);
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_IOC_VSP_FREE_COMPAT:
+#endif
+ case FM_IOC_VSP_FREE:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0, sizeof(ioc_fm_obj_t));
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id,
+ (ioc_compat_fm_obj_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_obj_t)))
+ break;
+ compat_obj_delete(&compat_id, &id);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg,
+ sizeof(ioc_fm_obj_t)))
+ break;
+ }
+
+ return FM_VSP_Free(id.obj);
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_IOC_VSP_CONFIG_POOL_DEPLETION_COMPAT:
+#endif
+ case FM_IOC_VSP_CONFIG_POOL_DEPLETION:
+ {
+ ioc_fm_buf_pool_depletion_params_t param;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_buf_pool_depletion_params_t compat_param;
+
+ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_copy_fm_buf_pool_depletion_params(&compat_param, &param, COMPAT_US_TO_K);
+ }
+ else
+#endif
+ if (copy_from_user(&param, (void *)arg, sizeof(param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ if (FM_VSP_ConfigPoolDepletion(param.p_fm_vsp,
+ (t_FmBufPoolDepletion *)&param.fm_buf_pool_depletion))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ break;
+ }
+
+
+#if defined(CONFIG_COMPAT)
+ case FM_IOC_VSP_CONFIG_BUFFER_PREFIX_CONTENT_COMPAT:
+#endif
+ case FM_IOC_VSP_CONFIG_BUFFER_PREFIX_CONTENT:
+ {
+ ioc_fm_buffer_prefix_content_params_t param;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_buffer_prefix_content_params_t compat_param;
+
+ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_copy_fm_buffer_prefix_content_params(&compat_param, &param, COMPAT_US_TO_K);
+ }
+ else
+#endif
+ if (copy_from_user(&param, (void *)arg, sizeof(param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ if (FM_VSP_ConfigBufferPrefixContent(param.p_fm_vsp,
+ (t_FmBufferPrefixContent *)&param.fm_buffer_prefix_content))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_IOC_VSP_CONFIG_NO_SG_COMPAT:
+#endif
+ case FM_IOC_VSP_CONFIG_NO_SG:
+ {
+ ioc_fm_vsp_config_no_sg_params_t param;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_vsp_config_no_sg_params_t compat_param;
+
+ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_copy_fm_vsp_config_no_sg_params(&compat_param, &param, COMPAT_US_TO_K);
+ }
+ else
+#endif
+ if (copy_from_user(&param, (void *)arg, sizeof(param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ if (FM_VSP_ConfigNoScatherGather(param.p_fm_vsp, param.no_sg))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_IOC_VSP_GET_BUFFER_PRS_RESULT_COMPAT:
+#endif
+ case FM_IOC_VSP_GET_BUFFER_PRS_RESULT:
+ {
+ ioc_fm_vsp_prs_result_params_t param;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_vsp_prs_result_params_t compat_param;
+
+ if (copy_from_user(&compat_param, compat_ptr(arg), sizeof(compat_param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_copy_fm_vsp_prs_result_params(&compat_param, &param, COMPAT_US_TO_K);
+ }
+ else
+#endif
+ if (copy_from_user(&param, (void *)arg, sizeof(param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ /* this call just adds the parse results offset to p_data */
+ param.p_data = FM_VSP_GetBufferPrsResult(param.p_fm_vsp, param.p_data);
+
+ if (!param.p_data)
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_vsp_prs_result_params_t compat_param;
+
+ memset(&compat_param, 0, sizeof(compat_param));
+ compat_copy_fm_vsp_prs_result_params(&compat_param, &param, COMPAT_K_TO_US);
+
+ if (copy_to_user(compat_ptr(arg), &compat_param, sizeof(compat_param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ else
+#endif
+ if (copy_to_user((void *)arg, &param, sizeof(param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ break;
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+#ifdef FM_CAPWAP_SUPPORT
+#warning "feature not supported!"
+#if defined(CONFIG_COMPAT)
+ case FM_PCD_IOC_STATISTICS_SET_NODE_COMPAT:
+#endif
+ case FM_PCD_IOC_STATISTICS_SET_NODE:
+ {
+/* ioc_fm_pcd_stats_params_t param;
+ ...
+ param->id = FM_PCD_StatisticsSetNode(p_LnxWrpFmDev->h_PcdDev,
+ (t_FmPcdStatsParams *)&param);
+*/
+ err = E_NOT_SUPPORTED;
+ break;
+ }
+#endif /* FM_CAPWAP_SUPPORT */
+
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION,
+ ("invalid ioctl: cmd:0x%08x(type:0x%02x, nr: %d.\n",
+ cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)));
+ }
+
+ if (err)
+ RETURN_ERROR(MINOR, err, ("IOCTL FM PCD"));
+
+ return E_OK;
+}
+
+void FM_Get_Api_Version(ioc_fm_api_version_t *p_version)
+{
+ p_version->version.major = FMD_API_VERSION_MAJOR;
+ p_version->version.minor = FMD_API_VERSION_MINOR;
+ p_version->version.respin = FMD_API_VERSION_RESPIN;
+ p_version->version.reserved = 0;
+}
+
+t_Error LnxwrpFmIOCTL(t_LnxWrpFmDev *p_LnxWrpFmDev, unsigned int cmd, unsigned long arg, bool compat)
+{
+ t_Error err = E_OK;
+
+ switch (cmd)
+ {
+ case FM_IOC_SET_PORTS_BANDWIDTH:
+ {
+ ioc_fm_port_bandwidth_params *param;
+
+ param = (ioc_fm_port_bandwidth_params*) XX_Malloc(sizeof(ioc_fm_port_bandwidth_params));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_port_bandwidth_params));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_from_user(param, (ioc_fm_port_bandwidth_params*)compat_ptr(arg), sizeof(ioc_fm_port_bandwidth_params)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_port_bandwidth_params*)arg, sizeof(ioc_fm_port_bandwidth_params)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_SetPortsBandwidth(p_LnxWrpFmDev->h_Dev, (t_FmPortsBandwidthParams*) param);
+
+ XX_Free(param);
+ break;
+ }
+
+ case FM_IOC_GET_REVISION:
+ {
+ ioc_fm_revision_info_t *param;
+
+ param = (ioc_fm_revision_info_t *) XX_Malloc(sizeof(ioc_fm_revision_info_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ FM_GetRevision(p_LnxWrpFmDev->h_Dev, (t_FmRevisionInfo*)param);
+ /* This one never returns anything other than E_OK */
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_to_user((ioc_fm_revision_info_t *)compat_ptr(arg),
+ param,
+ sizeof(ioc_fm_revision_info_t)))
+ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG);
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_revision_info_t *)arg,
+ param,
+ sizeof(ioc_fm_revision_info_t)))
+ RETURN_ERROR(MINOR, E_READ_FAILED, NO_MSG);
+ }
+
+ XX_Free(param);
+ break;
+ }
+
+ case FM_IOC_SET_COUNTER:
+ {
+ ioc_fm_counters_params_t *param;
+
+ param = (ioc_fm_counters_params_t *) XX_Malloc(sizeof(ioc_fm_counters_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_counters_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_from_user(param, (ioc_fm_counters_params_t *)compat_ptr(arg), sizeof(ioc_fm_counters_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_counters_params_t *)arg, sizeof(ioc_fm_counters_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_ModifyCounter(p_LnxWrpFmDev->h_Dev, param->cnt, param->val);
+
+ XX_Free(param);
+ break;
+ }
+
+ case FM_IOC_GET_COUNTER:
+ {
+ ioc_fm_counters_params_t *param;
+
+ param = (ioc_fm_counters_params_t *) XX_Malloc(sizeof(ioc_fm_counters_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PCD"));
+
+ memset(param, 0, sizeof(ioc_fm_counters_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_from_user(param, (ioc_fm_counters_params_t *)compat_ptr(arg), sizeof(ioc_fm_counters_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_counters_params_t *)arg, sizeof(ioc_fm_counters_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ param->val = FM_GetCounter(p_LnxWrpFmDev->h_Dev, param->cnt);
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_to_user((ioc_fm_counters_params_t *)compat_ptr(arg), param, sizeof(ioc_fm_counters_params_t)))
+ err = E_READ_FAILED;
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_counters_params_t *)arg, param, sizeof(ioc_fm_counters_params_t)))
+ err = E_READ_FAILED;
+ }
+
+ XX_Free(param);
+ break;
+ }
+
+ case FM_IOC_FORCE_INTR:
+ {
+ ioc_fm_exceptions param;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (get_user(param, (ioc_fm_exceptions*) compat_ptr(arg)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ else
+#endif
+ {
+ if (get_user(param, (ioc_fm_exceptions*)arg))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_ForceIntr(p_LnxWrpFmDev->h_Dev, (e_FmExceptions)param);
+ break;
+ }
+
+ case FM_IOC_GET_API_VERSION:
+ {
+ ioc_fm_api_version_t version;
+
+ FM_Get_Api_Version(&version);
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_to_user(
+ (ioc_fm_api_version_t *)compat_ptr(arg),
+ &version, sizeof(version)))
+ err = E_READ_FAILED;
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_api_version_t *)arg,
+ &version, sizeof(version)))
+ err = E_READ_FAILED;
+ }
+ }
+ break;
+
+ case FM_IOC_CTRL_MON_START:
+ {
+ FM_CtrlMonStart(p_LnxWrpFmDev->h_Dev);
+ }
+ break;
+
+ case FM_IOC_CTRL_MON_STOP:
+ {
+ FM_CtrlMonStop(p_LnxWrpFmDev->h_Dev);
+ }
+ break;
+
+#if defined(CONFIG_COMPAT)
+ case FM_IOC_CTRL_MON_GET_COUNTERS_COMPAT:
+#endif
+ case FM_IOC_CTRL_MON_GET_COUNTERS:
+ {
+ ioc_fm_ctrl_mon_counters_params_t param;
+ t_FmCtrlMon mon;
+
+#if defined(CONFIG_COMPAT)
+ ioc_compat_fm_ctrl_mon_counters_params_t compat_param;
+
+ if (compat)
+ {
+ if (copy_from_user(&compat_param, (void *)compat_ptr(arg),
+ sizeof(compat_param)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ param.fm_ctrl_index = compat_param.fm_ctrl_index;
+ param.p_mon = (fm_ctrl_mon_t *)compat_ptr(compat_param.p_mon);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&param, (void *)arg, sizeof(ioc_fm_counters_params_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ if (FM_CtrlMonGetCounters(p_LnxWrpFmDev->h_Dev, param.fm_ctrl_index, &mon))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ if (copy_to_user(param.p_mon, &mon, sizeof(t_FmCtrlMon)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ break;
+
+ default:
+ return LnxwrpFmPcdIOCTL(p_LnxWrpFmDev, cmd, arg, compat);
+ }
+
+ if (err)
+ RETURN_ERROR(MINOR, E_INVALID_OPERATION, ("IOCTL FM"));
+
+ return E_OK;
+}
+
+t_Error LnxwrpFmPortIOCTL(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev, unsigned int cmd, unsigned long arg, bool compat)
+{
+ t_Error err = E_OK;
+
+ _fm_ioctl_dbg("cmd:0x%08x(type:0x%02x, nr:%u).\n",
+ cmd, _IOC_TYPE(cmd), _IOC_NR(cmd) - 50);
+
+ switch (cmd)
+ {
+ case FM_PORT_IOC_DISABLE:
+ FM_PORT_Disable(p_LnxWrpFmPortDev->h_Dev);
+ /* deliberately ignoring error codes here */
+ return E_OK;
+
+ case FM_PORT_IOC_ENABLE:
+ FM_PORT_Enable(p_LnxWrpFmPortDev->h_Dev);
+ /* deliberately ignoring error codes here */
+ return E_OK;
+
+ case FM_PORT_IOC_SET_ERRORS_ROUTE:
+ {
+ ioc_fm_port_frame_err_select_t errs;
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (get_user(errs, (ioc_fm_port_frame_err_select_t*)compat_ptr(arg)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ else
+#endif
+ {
+ if (get_user(errs, (ioc_fm_port_frame_err_select_t*)arg))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PORT_SetErrorsRoute(p_LnxWrpFmPortDev->h_Dev, (fmPortFrameErrSelect_t)errs);
+ break;
+ }
+
+ case FM_PORT_IOC_SET_RATE_LIMIT:
+ {
+ ioc_fm_port_rate_limit_t *param;
+
+ param = (ioc_fm_port_rate_limit_t *) XX_Malloc(sizeof(ioc_fm_port_rate_limit_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+
+ memset(param, 0, sizeof(ioc_fm_port_rate_limit_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_from_user(param, (ioc_fm_port_rate_limit_t *)compat_ptr(arg), sizeof(ioc_fm_port_rate_limit_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_port_rate_limit_t *)arg, sizeof(ioc_fm_port_rate_limit_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PORT_SetRateLimit(p_LnxWrpFmPortDev->h_Dev, (t_FmPortRateLimit *)param);
+
+ XX_Free(param);
+ break;
+ }
+
+ case FM_PORT_IOC_REMOVE_RATE_LIMIT:
+ FM_PORT_DeleteRateLimit(p_LnxWrpFmPortDev->h_Dev);
+ /* deliberately ignoring error codes here */
+ return E_OK;
+
+ case FM_PORT_IOC_ALLOC_PCD_FQIDS:
+ {
+ ioc_fm_port_pcd_fqids_params_t *param;
+
+ if (!p_LnxWrpFmPortDev->pcd_owner_params.cba)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("No one to listen on this PCD!!!"));
+
+ param = (ioc_fm_port_pcd_fqids_params_t *) XX_Malloc(sizeof(ioc_fm_port_pcd_fqids_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+
+ memset(param, 0, sizeof(ioc_fm_port_pcd_fqids_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_from_user(param, (ioc_fm_port_pcd_fqids_params_t *)compat_ptr(arg),
+ sizeof(ioc_fm_port_pcd_fqids_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_port_pcd_fqids_params_t *)arg,
+ sizeof(ioc_fm_port_pcd_fqids_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ if (p_LnxWrpFmPortDev->pcd_owner_params.cba(p_LnxWrpFmPortDev->pcd_owner_params.dev,
+ param->num_fqids,
+ param->alignment,
+ &param->base_fqid))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("can't allocate fqids for PCD!!!"));
+ }
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_to_user((ioc_fm_port_pcd_fqids_params_t *)compat_ptr(arg),
+ param, sizeof(ioc_fm_port_pcd_fqids_params_t)))
+ err = E_READ_FAILED;
+ }
+ else
+#endif
+ {
+ if (copy_to_user((ioc_fm_port_pcd_fqids_params_t *)arg,
+ param, sizeof(ioc_fm_port_pcd_fqids_params_t)))
+ err = E_READ_FAILED;
+ }
+
+ XX_Free(param);
+ break;
+ }
+
+ case FM_PORT_IOC_FREE_PCD_FQIDS:
+ {
+ uint32_t base_fqid;
+
+ if (!p_LnxWrpFmPortDev->pcd_owner_params.cbf)
+ RETURN_ERROR(MINOR, E_INVALID_STATE, ("No one to listen on this PCD!!!"));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (get_user(base_fqid, (uint32_t*) compat_ptr(arg)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ else
+#endif
+ {
+ if (get_user(base_fqid, (uint32_t*)arg))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ if (p_LnxWrpFmPortDev->pcd_owner_params.cbf(p_LnxWrpFmPortDev->pcd_owner_params.dev, base_fqid))
+ err = E_WRITE_FAILED;
+
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PORT_IOC_SET_PCD_COMPAT:
+#endif
+ case FM_PORT_IOC_SET_PCD:
+ {
+ ioc_fm_port_pcd_params_t *port_pcd_params;
+ ioc_fm_port_pcd_prs_params_t *port_pcd_prs_params;
+ ioc_fm_port_pcd_cc_params_t *port_pcd_cc_params;
+ ioc_fm_port_pcd_kg_params_t *port_pcd_kg_params;
+ ioc_fm_port_pcd_plcr_params_t *port_pcd_plcr_params;
+
+ port_pcd_params = (ioc_fm_port_pcd_params_t *) XX_Malloc(
+ sizeof(ioc_fm_port_pcd_params_t) +
+ sizeof(ioc_fm_port_pcd_prs_params_t) +
+ sizeof(ioc_fm_port_pcd_cc_params_t) +
+ sizeof(ioc_fm_port_pcd_kg_params_t) +
+ sizeof(ioc_fm_port_pcd_plcr_params_t));
+ if (!port_pcd_params)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+
+ memset(port_pcd_params, 0,
+ sizeof(ioc_fm_port_pcd_params_t) +
+ sizeof(ioc_fm_port_pcd_prs_params_t) +
+ sizeof(ioc_fm_port_pcd_cc_params_t) +
+ sizeof(ioc_fm_port_pcd_kg_params_t) +
+ sizeof(ioc_fm_port_pcd_plcr_params_t));
+
+ port_pcd_prs_params = (ioc_fm_port_pcd_prs_params_t *) (port_pcd_params + 1);
+ port_pcd_cc_params = (ioc_fm_port_pcd_cc_params_t *) (port_pcd_prs_params + 1);
+ port_pcd_kg_params = (ioc_fm_port_pcd_kg_params_t *) (port_pcd_cc_params + 1);
+ port_pcd_plcr_params = (ioc_fm_port_pcd_plcr_params_t *) (port_pcd_kg_params + 1);
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_port_pcd_params_t *compat_port_pcd_params;
+ ioc_fm_port_pcd_prs_params_t *same_port_pcd_prs_params;
+ ioc_compat_fm_port_pcd_cc_params_t *compat_port_pcd_cc_params;
+ ioc_compat_fm_port_pcd_kg_params_t *compat_port_pcd_kg_params;
+ ioc_compat_fm_port_pcd_plcr_params_t *compat_port_pcd_plcr_params;
+
+ compat_port_pcd_params = (ioc_compat_fm_port_pcd_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_port_pcd_params_t) +
+ sizeof(ioc_fm_port_pcd_prs_params_t) +
+ sizeof(ioc_compat_fm_port_pcd_cc_params_t) +
+ sizeof(ioc_compat_fm_port_pcd_kg_params_t) +
+ sizeof(ioc_compat_fm_port_pcd_plcr_params_t));
+ if (!compat_port_pcd_params)
+ {
+ XX_Free(port_pcd_params);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+ }
+
+ memset(compat_port_pcd_params, 0,
+ sizeof(ioc_compat_fm_port_pcd_params_t) +
+ sizeof(ioc_fm_port_pcd_prs_params_t) +
+ sizeof(ioc_compat_fm_port_pcd_cc_params_t) +
+ sizeof(ioc_compat_fm_port_pcd_kg_params_t) +
+ sizeof(ioc_compat_fm_port_pcd_plcr_params_t));
+ same_port_pcd_prs_params = (ioc_fm_port_pcd_prs_params_t *) (compat_port_pcd_params + 1);
+ compat_port_pcd_cc_params = (ioc_compat_fm_port_pcd_cc_params_t *) (same_port_pcd_prs_params + 1);
+ compat_port_pcd_kg_params = (ioc_compat_fm_port_pcd_kg_params_t *) (compat_port_pcd_cc_params + 1);
+ compat_port_pcd_plcr_params = (ioc_compat_fm_port_pcd_plcr_params_t *) (compat_port_pcd_kg_params + 1);
+
+ if (copy_from_user(compat_port_pcd_params,
+ (ioc_compat_fm_port_pcd_params_t*) compat_ptr(arg),
+ sizeof(ioc_compat_fm_port_pcd_params_t)))
+ err = E_WRITE_FAILED;
+
+ while (!err) /* pseudo-while */
+ {
+ /* set pointers from where to copy from: */
+ port_pcd_params->p_prs_params = compat_ptr(compat_port_pcd_params->p_prs_params); /* same structure */
+ port_pcd_params->p_cc_params = compat_ptr(compat_port_pcd_params->p_cc_params);
+ port_pcd_params->p_kg_params = compat_ptr(compat_port_pcd_params->p_kg_params);
+ port_pcd_params->p_plcr_params = compat_ptr(compat_port_pcd_params->p_plcr_params);
+ port_pcd_params->p_ip_reassembly_manip = compat_ptr(compat_port_pcd_params->p_ip_reassembly_manip);
+
+ /* the prs member is the same, no compat structure...memcpy only */
+ if (port_pcd_params->p_prs_params)
+ {
+ if (copy_from_user(same_port_pcd_prs_params,
+ port_pcd_params->p_prs_params,
+ sizeof(ioc_fm_port_pcd_prs_params_t)))
+ {
+ err = E_WRITE_FAILED;
+ break; /* from pseudo-while */
+ }
+
+ memcpy(port_pcd_prs_params, same_port_pcd_prs_params, sizeof(ioc_fm_port_pcd_prs_params_t));
+ port_pcd_params->p_prs_params = port_pcd_prs_params;
+ }
+
+ if (port_pcd_params->p_cc_params)
+ {
+ if (copy_from_user(compat_port_pcd_cc_params,
+ port_pcd_params->p_cc_params,
+ sizeof(ioc_compat_fm_port_pcd_cc_params_t)))
+ {
+ err = E_WRITE_FAILED;
+ break; /* from pseudo-while */
+ }
+
+ port_pcd_params->p_cc_params = port_pcd_cc_params;
+ }
+
+ if (port_pcd_params->p_kg_params)
+ {
+ if (copy_from_user(compat_port_pcd_kg_params,
+ port_pcd_params->p_kg_params,
+ sizeof(ioc_compat_fm_port_pcd_kg_params_t)))
+ {
+ err = E_WRITE_FAILED;
+ break; /* from pseudo-while */
+ }
+
+ port_pcd_params->p_kg_params = port_pcd_kg_params;
+ }
+
+ if (port_pcd_params->p_plcr_params)
+ {
+ if (copy_from_user(compat_port_pcd_plcr_params,
+ port_pcd_params->p_plcr_params,
+ sizeof(ioc_compat_fm_port_pcd_plcr_params_t)))
+ {
+ err = E_WRITE_FAILED;
+ break; /* from pseudo-while */
+ }
+
+ port_pcd_params->p_plcr_params = port_pcd_plcr_params;
+ }
+
+ break; /* pseudo-while: always run once! */
+ }
+
+ if (!err)
+ compat_copy_fm_port_pcd(compat_port_pcd_params, port_pcd_params, COMPAT_US_TO_K);
+
+ XX_Free(compat_port_pcd_params);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(port_pcd_params,
+ (ioc_fm_port_pcd_params_t*) arg,
+ sizeof(ioc_fm_port_pcd_params_t)))
+ err = E_WRITE_FAILED;
+
+ while (!err) /* pseudo-while */
+ {
+ if (port_pcd_params->p_prs_params)
+ {
+ if (copy_from_user(port_pcd_prs_params,
+ port_pcd_params->p_prs_params,
+ sizeof(ioc_fm_port_pcd_prs_params_t)))
+ {
+ err = E_WRITE_FAILED;
+ break; /* from pseudo-while */
+ }
+
+ port_pcd_params->p_prs_params = port_pcd_prs_params;
+ }
+
+ if (port_pcd_params->p_cc_params)
+ {
+ if (copy_from_user(port_pcd_cc_params,
+ port_pcd_params->p_cc_params,
+ sizeof(ioc_fm_port_pcd_cc_params_t)))
+ {
+ err = E_WRITE_FAILED;
+ break; /* from pseudo-while */
+ }
+
+ port_pcd_params->p_cc_params = port_pcd_cc_params;
+ }
+
+ if (port_pcd_params->p_kg_params)
+ {
+ if (copy_from_user(port_pcd_kg_params,
+ port_pcd_params->p_kg_params,
+ sizeof(ioc_fm_port_pcd_kg_params_t)))
+ {
+ err = E_WRITE_FAILED;
+ break; /* from pseudo-while */
+ }
+
+ port_pcd_params->p_kg_params = port_pcd_kg_params;
+ }
+
+ if (port_pcd_params->p_plcr_params)
+ {
+ if (copy_from_user(port_pcd_plcr_params,
+ port_pcd_params->p_plcr_params,
+ sizeof(ioc_fm_port_pcd_plcr_params_t)))
+ {
+ err = E_WRITE_FAILED;
+ break; /* from pseudo-while */
+ }
+
+ port_pcd_params->p_plcr_params = port_pcd_plcr_params;
+ }
+
+ break; /* pseudo-while: always run once! */
+ }
+ }
+
+ if (!err)
+ err = FM_PORT_SetPCD(p_LnxWrpFmPortDev->h_Dev, (t_FmPortPcdParams*) port_pcd_params);
+
+ XX_Free(port_pcd_params);
+ break;
+ }
+
+ case FM_PORT_IOC_DELETE_PCD:
+ err = FM_PORT_DeletePCD(p_LnxWrpFmPortDev->h_Dev);
+ break;
+
+#if defined(CONFIG_COMPAT)
+ case FM_PORT_IOC_PCD_KG_MODIFY_INITIAL_SCHEME_COMPAT:
+#endif
+ case FM_PORT_IOC_PCD_KG_MODIFY_INITIAL_SCHEME:
+ {
+ ioc_fm_pcd_kg_scheme_select_t *param;
+
+ param = (ioc_fm_pcd_kg_scheme_select_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_kg_scheme_select_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_kg_scheme_select_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_kg_scheme_select_t *compat_param;
+
+ compat_param = (ioc_compat_fm_pcd_kg_scheme_select_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_pcd_kg_scheme_select_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_pcd_kg_scheme_select_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_pcd_kg_scheme_select_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_kg_scheme_select_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_kg_scheme_select(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_kg_scheme_select_t *)arg,
+ sizeof(ioc_fm_pcd_kg_scheme_select_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PORT_PcdKgModifyInitialScheme(p_LnxWrpFmPortDev->h_Dev, (t_FmPcdKgSchemeSelect *)param);
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PORT_IOC_PCD_PLCR_MODIFY_INITIAL_PROFILE_COMPAT:
+#endif
+ case FM_PORT_IOC_PCD_PLCR_MODIFY_INITIAL_PROFILE:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0 , sizeof(ioc_fm_obj_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ id.obj = compat_ptr(compat_id.obj);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PORT_PcdPlcrModifyInitialProfile(p_LnxWrpFmPortDev->h_Dev, id.obj);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PORT_IOC_PCD_KG_BIND_SCHEMES_COMPAT:
+#endif
+ case FM_PORT_IOC_PCD_KG_BIND_SCHEMES:
+ {
+ ioc_fm_pcd_port_schemes_params_t *param;
+
+ param = (ioc_fm_pcd_port_schemes_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_port_schemes_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+
+ memset(param, 0 , sizeof(ioc_fm_pcd_port_schemes_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_port_schemes_params_t compat_param;
+
+ if (copy_from_user(&compat_param,
+ (ioc_compat_fm_pcd_port_schemes_params_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_port_schemes_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_kg_schemes_params(&compat_param, param, COMPAT_US_TO_K);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_port_schemes_params_t *) arg,
+ sizeof(ioc_fm_pcd_port_schemes_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PORT_PcdKgBindSchemes(p_LnxWrpFmPortDev->h_Dev, (t_FmPcdPortSchemesParams *)param);
+
+ XX_Free(param);
+ break;
+ }
+
+#if defined(CONFIG_COMPAT)
+ case FM_PORT_IOC_PCD_KG_UNBIND_SCHEMES_COMPAT:
+#endif
+ case FM_PORT_IOC_PCD_KG_UNBIND_SCHEMES:
+ {
+ ioc_fm_pcd_port_schemes_params_t *param;
+
+ param = (ioc_fm_pcd_port_schemes_params_t *) XX_Malloc(
+ sizeof(ioc_fm_pcd_port_schemes_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+
+ memset(param, 0 , sizeof(ioc_fm_pcd_port_schemes_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_pcd_port_schemes_params_t compat_param;
+
+ if (copy_from_user(&compat_param,
+ (ioc_compat_fm_pcd_port_schemes_params_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_pcd_port_schemes_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_pcd_kg_schemes_params(&compat_param, param, COMPAT_US_TO_K);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_port_schemes_params_t *) arg,
+ sizeof(ioc_fm_pcd_port_schemes_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PORT_PcdKgUnbindSchemes(p_LnxWrpFmPortDev->h_Dev, (t_FmPcdPortSchemesParams *)param);
+
+ XX_Free(param);
+ break;
+ }
+
+ case FM_PORT_IOC_PCD_PRS_MODIFY_START_OFFSET:
+ {
+ ioc_fm_pcd_prs_start_t *param;
+
+ param = (ioc_fm_pcd_prs_start_t *) XX_Malloc(sizeof(ioc_fm_pcd_prs_start_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+
+ memset(param, 0, sizeof(ioc_fm_pcd_prs_start_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_prs_start_t *)compat_ptr(arg),
+ sizeof(ioc_fm_pcd_prs_start_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_pcd_prs_start_t *)arg,
+ sizeof(ioc_fm_pcd_prs_start_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = FM_PORT_PcdPrsModifyStartOffset(p_LnxWrpFmPortDev->h_Dev, (t_FmPcdPrsStart *)param);
+
+ XX_Free(param);
+ break;
+ }
+
+ case FM_PORT_IOC_PCD_PLCR_ALLOC_PROFILES:
+ {
+ uint16_t num;
+ if (get_user(num, (uint16_t*) arg))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ err = FM_PORT_PcdPlcrAllocProfiles(p_LnxWrpFmPortDev->h_Dev, num);
+ break;
+ }
+
+ case FM_PORT_IOC_PCD_PLCR_FREE_PROFILES:
+ err = FM_PORT_PcdPlcrFreeProfiles(p_LnxWrpFmPortDev->h_Dev);
+ break;
+
+ case FM_PORT_IOC_DETACH_PCD:
+ err = FM_PORT_DetachPCD(p_LnxWrpFmPortDev->h_Dev);
+ break;
+
+ case FM_PORT_IOC_ATTACH_PCD:
+ err = FM_PORT_AttachPCD(p_LnxWrpFmPortDev->h_Dev);
+ break;
+
+#if defined(CONFIG_COMPAT)
+ case FM_PORT_IOC_PCD_CC_MODIFY_TREE_COMPAT:
+#endif
+ case FM_PORT_IOC_PCD_CC_MODIFY_TREE:
+ {
+ ioc_fm_obj_t id;
+
+ memset(&id, 0 , sizeof(ioc_fm_obj_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_obj_t compat_id;
+
+ if (copy_from_user(&compat_id, (ioc_compat_fm_obj_t *) compat_ptr(arg), sizeof(ioc_compat_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ compat_copy_fm_port_pcd_modify_tree(&compat_id, &id, COMPAT_US_TO_K);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(&id, (ioc_fm_obj_t *) arg, sizeof(ioc_fm_obj_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ err = FM_PORT_PcdCcModifyTree(p_LnxWrpFmPortDev->h_Dev, id.obj);
+ break;
+ }
+
+ case FM_PORT_IOC_ADD_CONGESTION_GRPS:
+ case FM_PORT_IOC_REMOVE_CONGESTION_GRPS:
+ {
+ ioc_fm_port_congestion_groups_t *param;
+
+ param = (ioc_fm_port_congestion_groups_t*) XX_Malloc(sizeof(ioc_fm_port_congestion_groups_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+
+ memset(param, 0, sizeof(ioc_fm_port_congestion_groups_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_from_user(param, (t_FmPortCongestionGrps*) compat_ptr(arg),
+ sizeof(t_FmPortCongestionGrps)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+ else
+#endif /* CONFIG_COMPAT */
+ {
+ if (copy_from_user(param, (t_FmPortCongestionGrps*) arg,
+ sizeof(t_FmPortCongestionGrps)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ err = (cmd == FM_PORT_IOC_ADD_CONGESTION_GRPS)
+ ? FM_PORT_AddCongestionGrps(p_LnxWrpFmPortDev->h_Dev, (t_FmPortCongestionGrps*) param)
+ : FM_PORT_RemoveCongestionGrps(p_LnxWrpFmPortDev->h_Dev, (t_FmPortCongestionGrps*) param)
+ ;
+
+ XX_Free(param);
+ break;
+ }
+
+ case FM_PORT_IOC_ADD_RX_HASH_MAC_ADDR:
+ case FM_PORT_IOC_REMOVE_RX_HASH_MAC_ADDR:
+ {
+ ioc_fm_port_mac_addr_params_t *param;
+
+ param = (ioc_fm_port_mac_addr_params_t*) XX_Malloc(
+ sizeof(ioc_fm_port_mac_addr_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+
+ memset(param, 0, sizeof(ioc_fm_port_mac_addr_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ if (copy_from_user(param, (ioc_fm_port_mac_addr_params_t*) compat_ptr(arg),
+ sizeof(ioc_fm_port_mac_addr_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+ else
+#endif /* CONFIG_COMPAT */
+ {
+ if (copy_from_user(param, (ioc_fm_port_mac_addr_params_t*) arg,
+ sizeof(ioc_fm_port_mac_addr_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ if (p_LnxWrpFmPortDev->pcd_owner_params.dev)
+ {
+ int id = -1;
+
+ switch(p_LnxWrpFmPortDev->settings.param.portType)
+ {
+ case e_FM_PORT_TYPE_RX:
+ case e_FM_PORT_TYPE_TX:
+ id = p_LnxWrpFmPortDev->id;
+ break;
+ case e_FM_PORT_TYPE_RX_10G:
+ case e_FM_PORT_TYPE_TX_10G:
+ id = p_LnxWrpFmPortDev->id + FM_MAX_NUM_OF_1G_MACS;
+ break;
+ default:
+ err = E_NOT_AVAILABLE;
+ REPORT_ERROR(MINOR, err, ("Attempt to add/remove hash MAC addr. to/from MAC-less port!"));
+ }
+ if (id >= 0)
+ {
+ t_LnxWrpFmDev *fm = (t_LnxWrpFmDev *)p_LnxWrpFmPortDev->h_LnxWrpFmDev;
+ t_Handle mac_handle = fm->macs[id].h_Dev;
+
+ err = (cmd == FM_PORT_IOC_ADD_RX_HASH_MAC_ADDR)
+ ? FM_MAC_AddHashMacAddr(mac_handle, (t_EnetAddr*) param)
+ : FM_MAC_RemoveHashMacAddr(mac_handle, (t_EnetAddr*) param);
+ }
+ }
+ else
+ {
+ err = E_NOT_AVAILABLE;
+ REPORT_ERROR(MINOR, err, ("Port not initialized or other error!?!?"));
+ }
+
+ XX_Free(param);
+ break;
+ }
+
+ case FM_PORT_IOC_SET_TX_PAUSE_FRAMES:
+ {
+ t_LnxWrpFmDev *p_LnxWrpFmDev =
+ (t_LnxWrpFmDev *)p_LnxWrpFmPortDev->h_LnxWrpFmDev;
+ ioc_fm_port_tx_pause_frames_params_t param;
+ int mac_id = p_LnxWrpFmPortDev->id;
+
+ if(&p_LnxWrpFmDev->txPorts[mac_id] != p_LnxWrpFmPortDev)
+ mac_id += FM_MAX_NUM_OF_1G_MACS; /* 10G port */
+
+ if (copy_from_user(&param, (ioc_fm_port_tx_pause_frames_params_t *)arg,
+ sizeof(ioc_fm_port_tx_pause_frames_params_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ if (p_LnxWrpFmDev && p_LnxWrpFmDev->macs[mac_id].h_Dev)
+ {
+ FM_MAC_SetTxPauseFrames(p_LnxWrpFmDev->macs[mac_id].h_Dev,
+ param.priority,
+ param.pause_time,
+ param.thresh_time);
+ }
+ else
+ {
+ err = E_NOT_AVAILABLE;
+ REPORT_ERROR(MINOR, err, ("Port not initialized or other error!"));
+ }
+
+ break;
+ }
+
+ case FM_PORT_IOC_CONFIG_BUFFER_PREFIX_CONTENT:
+ {
+ ioc_fm_buffer_prefix_content_t *param;
+
+ param = (ioc_fm_buffer_prefix_content_t*) XX_Malloc(sizeof(ioc_fm_buffer_prefix_content_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+
+ memset(param, 0, sizeof(ioc_fm_buffer_prefix_content_t));
+
+ if (copy_from_user(param, (ioc_fm_buffer_prefix_content_t*) arg,
+ sizeof(ioc_fm_buffer_prefix_content_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ if (FM_PORT_ConfigBufferPrefixContent(p_LnxWrpFmPortDev->h_Dev,
+ (t_FmBufferPrefixContent *)param))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ XX_Free(param);
+ break;
+ }
+
+#if (DPAA_VERSION >= 11)
+#if defined(CONFIG_COMPAT)
+ case FM_PORT_IOC_VSP_ALLOC_COMPAT:
+#endif
+ case FM_PORT_IOC_VSP_ALLOC:
+ {
+ ioc_fm_port_vsp_alloc_params_t *param;
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
+ t_LnxWrpFmPortDev *p_LnxWrpFmTxPortDev;
+
+ param = (ioc_fm_port_vsp_alloc_params_t *) XX_Malloc(
+ sizeof(ioc_fm_port_vsp_alloc_params_t));
+ if (!param)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+
+ memset(param, 0, sizeof(ioc_fm_port_vsp_alloc_params_t));
+
+#if defined(CONFIG_COMPAT)
+ if (compat)
+ {
+ ioc_compat_fm_port_vsp_alloc_params_t *compat_param;
+
+ compat_param = (ioc_compat_fm_port_vsp_alloc_params_t *) XX_Malloc(
+ sizeof(ioc_compat_fm_port_vsp_alloc_params_t));
+ if (!compat_param)
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("IOCTL FM PORT"));
+ }
+
+ memset(compat_param, 0, sizeof(ioc_compat_fm_port_vsp_alloc_params_t));
+ if (copy_from_user(compat_param,
+ (ioc_compat_fm_port_vsp_alloc_params_t *) compat_ptr(arg),
+ sizeof(ioc_compat_fm_port_vsp_alloc_params_t)))
+ {
+ XX_Free(compat_param);
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ compat_copy_fm_port_vsp_alloc_params(compat_param, param, COMPAT_US_TO_K);
+
+ XX_Free(compat_param);
+ }
+ else
+#endif
+ {
+ if (copy_from_user(param, (ioc_fm_port_vsp_alloc_params_t *)arg,
+ sizeof(ioc_fm_port_vsp_alloc_params_t)))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+ }
+
+ /* Userspace may not have the Tx port t_handle when issuing the IOCTL */
+ if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_RX ||
+ p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_RX_10G)
+ {
+ /* Determine the Tx port t_Handle from the Rx port id */
+ p_LnxWrpFmDev = p_LnxWrpFmPortDev->h_LnxWrpFmDev;
+ p_LnxWrpFmTxPortDev = &p_LnxWrpFmDev->txPorts[p_LnxWrpFmPortDev->id];
+ param->p_fm_tx_port = p_LnxWrpFmTxPortDev->h_Dev;
+ }
+
+ if (FM_PORT_VSPAlloc(p_LnxWrpFmPortDev->h_Dev, (t_FmPortVSPAllocParams *)param))
+ {
+ XX_Free(param);
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+ }
+
+ XX_Free(param);
+ break;
+ }
+#endif /* (DPAA_VERSION >= 11) */
+
+ case FM_PORT_IOC_GET_MAC_STATISTICS:
+ {
+ t_LnxWrpFmDev *p_LnxWrpFmDev =
+ (t_LnxWrpFmDev *)p_LnxWrpFmPortDev->h_LnxWrpFmDev;
+ ioc_fm_port_mac_statistics_t param;
+ int mac_id = p_LnxWrpFmPortDev->id;
+
+ if (!p_LnxWrpFmDev)
+ RETURN_ERROR(MINOR, E_NOT_AVAILABLE, ("Port not initialized or other error!"));
+
+ if (&p_LnxWrpFmDev->txPorts[mac_id] != p_LnxWrpFmPortDev &&
+ &p_LnxWrpFmDev->rxPorts[mac_id] != p_LnxWrpFmPortDev)
+ mac_id += FM_MAX_NUM_OF_1G_MACS; /* 10G port */
+
+ if (!p_LnxWrpFmDev->macs[mac_id].h_Dev)
+ RETURN_ERROR(MINOR, E_NOT_AVAILABLE, ("Port not initialized or other error!"));
+
+ if (FM_MAC_GetStatistics(p_LnxWrpFmDev->macs[mac_id].h_Dev,
+ (t_FmMacStatistics *)&param))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ if (copy_to_user((ioc_fm_port_mac_statistics_t *)arg, &param,
+ sizeof(ioc_fm_port_mac_statistics_t)))
+ RETURN_ERROR(MINOR, E_WRITE_FAILED, NO_MSG);
+
+ break;
+ }
+
+ default:
+ RETURN_ERROR(MINOR, E_INVALID_SELECTION,
+ ("invalid ioctl: cmd:0x%08x(type:0x%02x, nr:0x%02x.\n",
+ cmd, _IOC_TYPE(cmd), _IOC_NR(cmd)));
+ }
+
+ if (err)
+ RETURN_ERROR(MINOR, E_INVALID_OPERATION, ("IOCTL FM PORT"));
+
+ return E_OK;
+}
+
+/*****************************************************************************/
+/* API routines for the FM Linux Device */
+/*****************************************************************************/
+
+static int fm_open(struct inode *inode, struct file *file)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev = NULL;
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = NULL;
+ unsigned int major = imajor(inode);
+ unsigned int minor = iminor(inode);
+ struct device_node *fm_node;
+ static struct of_device_id fm_node_of_match[] = {
+ { .compatible = "fsl,fman", },
+ { /* end of list */ },
+ };
+
+ DBG(TRACE, ("Opening minor - %d - ", minor));
+
+ if (file->private_data != NULL)
+ return 0;
+
+ /* Get all the FM nodes */
+ for_each_matching_node(fm_node, fm_node_of_match) {
+ struct platform_device *of_dev;
+
+ of_dev = of_find_device_by_node(fm_node);
+ if (unlikely(of_dev == NULL)) {
+ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("fm id!"));
+ return -ENXIO;
+ }
+
+ p_LnxWrpFmDev = (t_LnxWrpFmDev *)fm_bind(&of_dev->dev);
+ if (p_LnxWrpFmDev->major == major)
+ break;
+ fm_unbind((struct fm *)p_LnxWrpFmDev);
+ p_LnxWrpFmDev = NULL;
+ }
+
+ if (!p_LnxWrpFmDev)
+ return -ENODEV;
+
+ if (minor == DEV_FM_MINOR_BASE)
+ file->private_data = p_LnxWrpFmDev;
+ else if (minor == DEV_FM_PCD_MINOR_BASE)
+ file->private_data = p_LnxWrpFmDev;
+ else {
+ if (minor == DEV_FM_OH_PORTS_MINOR_BASE)
+ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->hcPort;
+ else if ((minor > DEV_FM_OH_PORTS_MINOR_BASE) && (minor < DEV_FM_RX_PORTS_MINOR_BASE))
+ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->opPorts[minor-DEV_FM_OH_PORTS_MINOR_BASE-1];
+ else if ((minor >= DEV_FM_RX_PORTS_MINOR_BASE) && (minor < DEV_FM_TX_PORTS_MINOR_BASE))
+ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->rxPorts[minor-DEV_FM_RX_PORTS_MINOR_BASE];
+ else if ((minor >= DEV_FM_TX_PORTS_MINOR_BASE) && (minor < DEV_FM_MAX_MINORS))
+ p_LnxWrpFmPortDev = &p_LnxWrpFmDev->txPorts[minor-DEV_FM_TX_PORTS_MINOR_BASE];
+ else
+ return -EINVAL;
+
+ /* if trying to open port, check if it initialized */
+ if (!p_LnxWrpFmPortDev->h_Dev)
+ return -ENODEV;
+
+ p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)fm_port_bind(p_LnxWrpFmPortDev->dev);
+ file->private_data = p_LnxWrpFmPortDev;
+ fm_unbind((struct fm *)p_LnxWrpFmDev);
+ }
+
+ if (file->private_data == NULL)
+ return -ENXIO;
+
+ return 0;
+}
+
+static int fm_close(struct inode *inode, struct file *file)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev;
+ unsigned int minor = iminor(inode);
+ int err = 0;
+
+ DBG(TRACE, ("Closing minor - %d - ", minor));
+
+ if ((minor == DEV_FM_MINOR_BASE) ||
+ (minor == DEV_FM_PCD_MINOR_BASE))
+ {
+ p_LnxWrpFmDev = (t_LnxWrpFmDev*)file->private_data;
+ if (!p_LnxWrpFmDev)
+ return -ENODEV;
+ fm_unbind((struct fm *)p_LnxWrpFmDev);
+ }
+ else if (((minor >= DEV_FM_OH_PORTS_MINOR_BASE) && (minor < DEV_FM_RX_PORTS_MINOR_BASE)) ||
+ ((minor >= DEV_FM_RX_PORTS_MINOR_BASE) && (minor < DEV_FM_TX_PORTS_MINOR_BASE)) ||
+ ((minor >= DEV_FM_TX_PORTS_MINOR_BASE) && (minor < DEV_FM_MAX_MINORS)))
+ {
+ p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev*)file->private_data;
+ if (!p_LnxWrpFmPortDev)
+ return -ENODEV;
+ fm_port_unbind((struct fm_port *)p_LnxWrpFmPortDev);
+ }
+
+ return err;
+}
+
+static int fm_ioctls(unsigned int minor, struct file *file, unsigned int cmd, unsigned long arg, bool compat)
+{
+ DBG(TRACE, ("IOCTL minor - %u, cmd - 0x%08x, arg - 0x%08lx \n", minor, cmd, arg));
+
+ if ((minor == DEV_FM_MINOR_BASE) ||
+ (minor == DEV_FM_PCD_MINOR_BASE))
+ {
+ t_LnxWrpFmDev *p_LnxWrpFmDev = ((t_LnxWrpFmDev*)file->private_data);
+ if (!p_LnxWrpFmDev)
+ return -ENODEV;
+ if (LnxwrpFmIOCTL(p_LnxWrpFmDev, cmd, arg, compat))
+ return -EFAULT;
+ }
+ else if (((minor >= DEV_FM_OH_PORTS_MINOR_BASE) && (minor < DEV_FM_RX_PORTS_MINOR_BASE)) ||
+ ((minor >= DEV_FM_RX_PORTS_MINOR_BASE) && (minor < DEV_FM_TX_PORTS_MINOR_BASE)) ||
+ ((minor >= DEV_FM_TX_PORTS_MINOR_BASE) && (minor < DEV_FM_MAX_MINORS)))
+ {
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = ((t_LnxWrpFmPortDev*)file->private_data);
+ if (!p_LnxWrpFmPortDev)
+ return -ENODEV;
+ if (LnxwrpFmPortIOCTL(p_LnxWrpFmPortDev, cmd, arg, compat))
+ return -EFAULT;
+ }
+ else
+ {
+ REPORT_ERROR(MINOR, E_INVALID_VALUE, ("minor"));
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_COMPAT
+static long fm_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ unsigned int minor = iminor(file->f_path.dentry->d_inode);
+ long res;
+
+ fm_mutex_lock();
+ res = fm_ioctls(minor, file, cmd, arg, true);
+ fm_mutex_unlock();
+
+ return res;
+}
+#endif
+
+static long fm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ unsigned int minor = iminor(file->f_path.dentry->d_inode);
+ long res;
+
+ fm_mutex_lock();
+ res = fm_ioctls(minor, file, cmd, arg, false);
+ fm_mutex_unlock();
+
+ return res;
+}
+
+/* Globals for FM character device */
+struct file_operations fm_fops =
+{
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = fm_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = fm_compat_ioctl,
+#endif
+ .open = fm_open,
+ .release = fm_close,
+};
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.c
new file mode 100644
index 0000000..3c1ac30
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.c
@@ -0,0 +1,1241 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ @File lnxwrp_fm_compat_ioctls.c
+
+ @Description FM PCD compat functions
+
+*/
+
+#if !defined(CONFIG_COMPAT)
+#error "missing COMPAT layer..."
+#endif
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <asm/uaccess.h>
+#include <asm/errno.h>
+#include <sysdev/fsl_soc.h>
+
+#include "part_ext.h"
+#include "fm_ioctls.h"
+#include "fm_pcd_ioctls.h"
+#include "fm_port_ioctls.h"
+#include "lnxwrp_ioctls_fm_compat.h"
+
+#if defined(FM_COMPAT_DBG)
+static void hex_dump(void * p_addr, unsigned int size)
+{
+ int i;
+
+ for(i=0; i<size; i+=16)
+ {
+ printk("%p: 0x%08x 0x%08x 0x%08x 0x%08x\n", p_addr + i,
+ *(unsigned int *)(p_addr + i),
+ *(unsigned int *)(p_addr + i + 4),
+ *(unsigned int *)(p_addr + i + 8),
+ *(unsigned int *)(p_addr + i +12)
+ );
+ }
+}
+#endif
+
+/* maping kernel pointers w/ UserSpace id's { */
+struct map_node {
+ void *ptr;
+ u8 node_type;
+};
+
+static struct map_node compat_ptr2id_array[COMPAT_PTR2ID_ARRAY_MAX] = {{NULL},{FM_MAP_TYPE_UNSPEC}};
+
+void compat_del_ptr2id(void *p, enum fm_map_node_type node_type)
+{
+ compat_uptr_t k;
+
+ _fm_cpt_dbg(COMPAT_GENERIC, "delete (%p)\n", p);
+
+ for(k=1; k < COMPAT_PTR2ID_ARRAY_MAX; k++)
+ if(compat_ptr2id_array[k].ptr == p){
+ compat_ptr2id_array[k].ptr = NULL;
+ compat_ptr2id_array[k].node_type = FM_MAP_TYPE_UNSPEC;
+ }
+}
+EXPORT_SYMBOL(compat_del_ptr2id);
+
+compat_uptr_t compat_add_ptr2id(void *p, enum fm_map_node_type node_type)
+{
+ compat_uptr_t k;
+
+ _fm_cpt_dbg(COMPAT_GENERIC, " (%p) do ->\n", p);
+
+ if(!p)
+ return 0;
+
+ for(k=1; k < COMPAT_PTR2ID_ARRAY_MAX; k++)
+ if(compat_ptr2id_array[k].ptr == NULL)
+ {
+ compat_ptr2id_array[k].ptr = p;
+ compat_ptr2id_array[k].node_type = node_type;
+ _fm_cpt_dbg(COMPAT_GENERIC, "0x%08x \n", k | COMPAT_PTR2ID_WATERMARK);
+ return k | COMPAT_PTR2ID_WATERMARK;
+ }
+
+ printk(KERN_WARNING "FMan map list full! No more PCD space on kernel!\n");
+ return 0;
+}
+EXPORT_SYMBOL(compat_add_ptr2id);
+
+compat_uptr_t compat_get_ptr2id(void *p, enum fm_map_node_type node_type)
+{
+ compat_uptr_t k;
+
+ _fm_cpt_dbg(COMPAT_GENERIC, " (%p) get -> \n", p);
+
+ for(k=1; k < COMPAT_PTR2ID_ARRAY_MAX; k++)
+ if(compat_ptr2id_array[k].ptr == p &&
+ compat_ptr2id_array[k].node_type == node_type) {
+
+ _fm_cpt_dbg(COMPAT_GENERIC, "0x%08x\n", k | COMPAT_PTR2ID_WATERMARK);
+ return k | COMPAT_PTR2ID_WATERMARK;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(compat_get_ptr2id);
+
+void *compat_get_id2ptr(compat_uptr_t comp, enum fm_map_node_type node_type)
+{
+
+ _fm_cpt_dbg(COMPAT_GENERIC, " (0x%08x) get -> \n", comp);
+
+ if((COMPAT_PTR2ID_WM_MASK & comp) != COMPAT_PTR2ID_WATERMARK) {
+ _fm_cpt_dbg(COMPAT_GENERIC, "Error, invalid watermark (0x%08x)!\n\n", comp);
+ dump_stack();
+ return compat_ptr(comp);
+ }
+
+ comp &= ~COMPAT_PTR2ID_WM_MASK;
+
+ if(((0 < comp) && (comp < COMPAT_PTR2ID_ARRAY_MAX) && (compat_ptr2id_array[comp].ptr != NULL)
+ && compat_ptr2id_array[comp].node_type == node_type)) {
+ _fm_cpt_dbg(COMPAT_GENERIC, "%p\n", compat_ptr2id_array[comp].ptr);
+ return compat_ptr2id_array[comp].ptr;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(compat_get_id2ptr);
+/* } maping kernel pointers w/ UserSpace id's */
+
+void compat_obj_delete(
+ ioc_compat_fm_obj_t *compat_id,
+ ioc_fm_obj_t *id)
+{
+ id->obj = compat_pcd_id2ptr(compat_id->obj);
+ compat_del_ptr2id(id->obj, FM_MAP_TYPE_PCD_NODE);
+}
+
+static inline void compat_copy_fm_pcd_plcr_next_engine(
+ ioc_compat_fm_pcd_plcr_next_engine_params_u *compat_param,
+ ioc_fm_pcd_plcr_next_engine_params_u *param,
+ ioc_fm_pcd_engine next_engine,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ switch (next_engine)
+ {
+ case e_IOC_FM_PCD_PLCR:
+ if (compat == COMPAT_US_TO_K)
+ param->p_profile = compat_pcd_id2ptr(compat_param->p_profile);
+ else
+ compat_param->p_profile = compat_pcd_ptr2id(param->p_profile);
+ break;
+ case e_IOC_FM_PCD_KG:
+ if (compat == COMPAT_US_TO_K)
+ param->p_direct_scheme = compat_pcd_id2ptr(compat_param->p_direct_scheme);
+ else
+ compat_param->p_direct_scheme = compat_pcd_ptr2id(param->p_direct_scheme);
+ break;
+ default:
+ if (compat == COMPAT_US_TO_K)
+ param->action = compat_param->action;
+ else
+ compat_param->action = param->action;
+ break;
+ }
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+void compat_copy_fm_pcd_plcr_profile(
+ ioc_compat_fm_pcd_plcr_profile_params_t *compat_param,
+ ioc_fm_pcd_plcr_profile_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->modify = compat_param->modify;
+
+ /* profile_select */
+ if (!compat_param->modify)
+ {
+ param->profile_select.new_params.profile_type =
+ compat_param->profile_select.new_params.profile_type;
+ param->profile_select.new_params.p_fm_port =
+ compat_ptr(compat_param->profile_select.new_params.p_fm_port);
+ param->profile_select.new_params.relative_profile_id =
+ compat_param->profile_select.new_params.relative_profile_id;
+ }
+ else
+ param->profile_select.p_profile =
+ compat_pcd_id2ptr(compat_param->profile_select.p_profile);
+
+ param->alg_selection = compat_param->alg_selection;
+ param->color_mode = compat_param->color_mode;
+
+ /* both parameters in the union has the same size, so memcpy works */
+ memcpy(&param->color, &compat_param->color, sizeof(param->color));
+
+ memcpy(&param->non_passthrough_alg_param,
+ &compat_param->non_passthrough_alg_param,
+ sizeof(ioc_fm_pcd_plcr_non_passthrough_alg_param_t));
+
+ param->next_engine_on_green = compat_param->next_engine_on_green;
+ param->next_engine_on_yellow = compat_param->next_engine_on_yellow;
+ param->next_engine_on_red = compat_param->next_engine_on_red;
+
+ param->trap_profile_on_flow_A = compat_param->trap_profile_on_flow_A;
+ param->trap_profile_on_flow_B = compat_param->trap_profile_on_flow_B;
+ param->trap_profile_on_flow_C = compat_param->trap_profile_on_flow_C;
+ }
+ else
+ {
+ compat_param->modify = param->modify;
+
+ /* profile_select */
+ if (!param->modify)
+ {
+ compat_param->profile_select.new_params.profile_type =
+ param->profile_select.new_params.profile_type;
+ compat_param->profile_select.new_params.p_fm_port =
+ ptr_to_compat(param->profile_select.new_params.p_fm_port);
+ compat_param->profile_select.new_params.relative_profile_id =
+ param->profile_select.new_params.relative_profile_id;
+ }
+ else
+ compat_param->profile_select.p_profile =
+ compat_pcd_ptr2id(param->profile_select.p_profile);
+
+ compat_param->alg_selection = param->alg_selection;
+ compat_param->color_mode = param->color_mode;
+
+ /* both parameters in the union has the same size, so memcpy works */
+ memcpy(&compat_param->color, &param->color, sizeof(compat_param->color));
+
+ memcpy(&compat_param->non_passthrough_alg_param,
+ &param->non_passthrough_alg_param,
+ sizeof(ioc_fm_pcd_plcr_non_passthrough_alg_param_t));
+
+ compat_param->next_engine_on_green = param->next_engine_on_green;
+ compat_param->next_engine_on_yellow = param->next_engine_on_yellow;
+ compat_param->next_engine_on_red = param->next_engine_on_red;
+
+ compat_param->trap_profile_on_flow_A = param->trap_profile_on_flow_A;
+ compat_param->trap_profile_on_flow_B = param->trap_profile_on_flow_B;
+ compat_param->trap_profile_on_flow_C = param->trap_profile_on_flow_C;
+
+ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE);
+ }
+
+ compat_copy_fm_pcd_plcr_next_engine(&compat_param->params_on_green,
+ &param->params_on_green, param->next_engine_on_green, compat);
+
+ compat_copy_fm_pcd_plcr_next_engine(&compat_param->params_on_yellow,
+ &param->params_on_yellow, param->next_engine_on_yellow, compat);
+
+ compat_copy_fm_pcd_plcr_next_engine(&compat_param->params_on_red,
+ &param->params_on_red, param->next_engine_on_red, compat);
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+static inline void compat_copy_fm_pcd_cc_next_kg(
+ ioc_compat_fm_pcd_cc_next_kg_params_t *compat_param,
+ ioc_fm_pcd_cc_next_kg_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->new_fqid = compat_param->new_fqid;
+ param->override_fqid = compat_param->override_fqid;
+ param->p_direct_scheme = compat_pcd_id2ptr(compat_param->p_direct_scheme);
+ }
+ else
+ {
+ compat_param->new_fqid = param->new_fqid;
+ compat_param->override_fqid = param->override_fqid;
+ compat_param->p_direct_scheme = compat_pcd_ptr2id(param->p_direct_scheme);
+ }
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+static inline void compat_copy_fm_pcd_cc_next_cc(
+ ioc_compat_fm_pcd_cc_next_cc_params_t *compat_param,
+ ioc_fm_pcd_cc_next_cc_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ param->cc_node_id = compat_pcd_id2ptr(compat_param->cc_node_id);
+ else
+ compat_param->cc_node_id = compat_pcd_ptr2id(param->cc_node_id);
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+static inline void compat_copy_fm_pcd_cc_next_engine(
+ ioc_compat_fm_pcd_cc_next_engine_params_t *compat_param,
+ ioc_fm_pcd_cc_next_engine_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->next_engine = compat_param->next_engine;
+ if (param->next_engine != e_IOC_FM_PCD_INVALID )
+ _fm_cpt_dbg(compat, " param->next_engine = %i \n", param->next_engine);
+
+ switch (param->next_engine)
+ {
+#if DPAA_VERSION >= 11
+ case e_IOC_FM_PCD_FR:
+ param->params.fr_params.frm_replic_id = compat_pcd_id2ptr(compat_param->params.fr_params.frm_replic_id);
+ break;
+#endif /* DPAA_VERSION >= 11 */
+ case e_IOC_FM_PCD_CC:
+ compat_copy_fm_pcd_cc_next_cc(&compat_param->params.cc_params, &param->params.cc_params, compat);
+ break;
+ case e_IOC_FM_PCD_KG:
+ param->manip_id = compat_pcd_id2ptr(compat_param->manip_id);
+ compat_copy_fm_pcd_cc_next_kg(&compat_param->params.kg_params, &param->params.kg_params, compat);
+ break;
+ case e_IOC_FM_PCD_DONE:
+ case e_IOC_FM_PCD_PLCR:
+ param->manip_id = compat_pcd_id2ptr(compat_param->manip_id);
+ default:
+ memcpy(&param->params, &compat_param->params, sizeof(param->params));
+ }
+ param->statistics_en = compat_param->statistics_en;
+ }
+ else
+ {
+ compat_param->next_engine = param->next_engine;
+
+ switch (compat_param->next_engine)
+ {
+#if DPAA_VERSION >= 11
+ case e_IOC_FM_PCD_FR:
+ compat_param->params.fr_params.frm_replic_id = compat_pcd_ptr2id(param->params.fr_params.frm_replic_id);
+ break;
+#endif /* DPAA_VERSION >= 11 */
+ case e_IOC_FM_PCD_CC:
+ compat_copy_fm_pcd_cc_next_cc(&compat_param->params.cc_params, &param->params.cc_params, compat);
+ break;
+ case e_IOC_FM_PCD_KG:
+ compat_param->manip_id = compat_pcd_ptr2id(param->manip_id);
+ compat_copy_fm_pcd_cc_next_kg(&compat_param->params.kg_params, &param->params.kg_params, compat);
+ break;
+ case e_IOC_FM_PCD_DONE:
+ case e_IOC_FM_PCD_PLCR:
+ compat_param->manip_id = compat_pcd_ptr2id(param->manip_id);
+ default:
+ memcpy(&compat_param->params, &param->params, sizeof(compat_param->params));
+ }
+ compat_param->statistics_en = param->statistics_en;
+ }
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+void compat_copy_fm_pcd_cc_key(
+ ioc_compat_fm_pcd_cc_key_params_t *compat_param,
+ ioc_fm_pcd_cc_key_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->p_key = compat_ptr(compat_param->p_key);
+ param->p_mask = compat_ptr(compat_param->p_mask);
+ }
+ else
+ {
+ compat_param->p_key = ptr_to_compat(param->p_key);
+ compat_param->p_mask = ptr_to_compat(param->p_mask);
+ }
+
+ compat_copy_fm_pcd_cc_next_engine(
+ &compat_param->cc_next_engine_params,
+ &param->cc_next_engine_params,
+ compat);
+}
+
+void compat_copy_fm_pcd_cc_node_modify_key_and_next_engine(
+ ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *compat_param,
+ ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->id = compat_pcd_id2ptr(compat_param->id);
+ param->key_indx = compat_param->key_indx;
+ param->key_size = compat_param->key_size;
+ compat_copy_fm_pcd_cc_key(
+ &compat_param->key_params,
+ &param->key_params,
+ compat);
+ }
+ else
+ {
+ compat_param->id = compat_pcd_ptr2id(param->id);
+ compat_param->key_indx = param->key_indx;
+ compat_param->key_size = param->key_size;
+ compat_copy_fm_pcd_cc_key(
+ &compat_param->key_params,
+ &param->key_params,
+ compat);
+ }
+}
+
+void compat_copy_fm_pcd_cc_node_modify_next_engine(
+ ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *compat_param,
+ ioc_fm_pcd_cc_node_modify_next_engine_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->id = compat_pcd_id2ptr(compat_param->id);
+ param->key_indx = compat_param->key_indx;
+ param->key_size = compat_param->key_size;
+ }
+ else
+ {
+ compat_param->id = compat_pcd_ptr2id(param->id);
+ compat_param->key_indx = param->key_indx;
+ compat_param->key_size = param->key_size;
+ }
+
+ compat_copy_fm_pcd_cc_next_engine(
+ &compat_param->cc_next_engine_params,
+ &param->cc_next_engine_params,
+ compat);
+}
+
+void compat_fm_pcd_cc_tree_modify_next_engine(
+ ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t *compat_param,
+ ioc_fm_pcd_cc_tree_modify_next_engine_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->id = compat_pcd_id2ptr(compat_param->id);
+ param->grp_indx = compat_param->grp_indx;
+ param->indx = compat_param->indx;
+ }
+ else
+ {
+ compat_param->id = compat_pcd_ptr2id(param->id);
+ compat_param->grp_indx = param->grp_indx;
+ compat_param->indx = param->indx;
+ }
+
+ compat_copy_fm_pcd_cc_next_engine(
+ &compat_param->cc_next_engine_params,
+ &param->cc_next_engine_params,
+ compat);
+}
+
+void compat_copy_fm_pcd_hash_table(
+ ioc_compat_fm_pcd_hash_table_params_t *compat_param,
+ ioc_fm_pcd_hash_table_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->max_num_of_keys = compat_param->max_num_of_keys;
+ param->statistics_mode = compat_param->statistics_mode;
+ param->kg_hash_shift = compat_param->kg_hash_shift;
+ param->hash_res_mask = compat_param->hash_res_mask;
+ param->hash_shift = compat_param->hash_shift;
+ param->match_key_size = compat_param->match_key_size;
+ param->id = compat_pcd_id2ptr(compat_param->id);
+ }
+ else
+ {
+ compat_param->max_num_of_keys = param->max_num_of_keys;
+ compat_param->statistics_mode = param->statistics_mode;
+ compat_param->kg_hash_shift = param->kg_hash_shift;
+ compat_param->hash_res_mask = param->hash_res_mask;
+ compat_param->hash_shift = param->hash_shift;
+ compat_param->match_key_size = param->match_key_size;
+
+ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE);
+ }
+
+ compat_copy_fm_pcd_cc_next_engine(
+ &compat_param->cc_next_engine_params_for_miss,
+ &param->cc_next_engine_params_for_miss,
+ compat);
+}
+
+void compat_copy_fm_pcd_cc_grp(
+ ioc_compat_fm_pcd_cc_grp_params_t *compat_param,
+ ioc_fm_pcd_cc_grp_params_t *param,
+ uint8_t compat)
+{
+ int k;
+
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->num_of_distinction_units = compat_param->num_of_distinction_units;
+ memcpy(param->unit_ids, compat_param->unit_ids, IOC_FM_PCD_MAX_NUM_OF_CC_UNITS);
+ }
+ else
+ {
+ compat_param->num_of_distinction_units = param->num_of_distinction_units;
+ memcpy(compat_param->unit_ids, param->unit_ids, IOC_FM_PCD_MAX_NUM_OF_CC_UNITS);
+ }
+
+ for (k=0; k < IOC_FM_PCD_MAX_NUM_OF_CC_ENTRIES_IN_GRP; k++)
+ compat_copy_fm_pcd_cc_next_engine(
+ &compat_param->next_engine_per_entries_in_grp[k],
+ &param->next_engine_per_entries_in_grp[k],
+ compat);
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+void compat_copy_fm_pcd_cc_tree(
+ ioc_compat_fm_pcd_cc_tree_params_t *compat_param,
+ ioc_fm_pcd_cc_tree_params_t *param,
+ uint8_t compat)
+{
+ int k;
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->net_env_id = compat_pcd_id2ptr(compat_param->net_env_id);
+ param->num_of_groups = compat_param->num_of_groups;
+ }
+ else
+ {
+ compat_param->net_env_id = compat_pcd_ptr2id(param->net_env_id);
+ compat_param->num_of_groups = param->num_of_groups;
+
+ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE);
+ }
+
+ for (k=0; k < IOC_FM_PCD_MAX_NUM_OF_CC_GROUPS; k++)
+ compat_copy_fm_pcd_cc_grp(
+ &compat_param->fm_pcd_cc_group_params[k],
+ &param->fm_pcd_cc_group_params[k],
+ compat);
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+void compat_fm_pcd_prs_sw(
+ ioc_compat_fm_pcd_prs_sw_params_t *compat_param,
+ ioc_fm_pcd_prs_sw_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->override = compat_param->override;
+ param->size = compat_param->size;
+ param->base = compat_param->base;
+ param->p_code = compat_ptr(compat_param->p_code);
+ memcpy(param->sw_prs_data_params,compat_param->sw_prs_data_params,IOC_FM_PCD_PRS_NUM_OF_HDRS*sizeof(uint32_t));
+ param->num_of_labels = compat_param->num_of_labels;
+ memcpy(param->labels_table,compat_param->labels_table,IOC_FM_PCD_PRS_NUM_OF_LABELS*sizeof(ioc_fm_pcd_prs_label_params_t));
+ }
+}
+
+void compat_copy_fm_pcd_kg_scheme(
+ ioc_compat_fm_pcd_kg_scheme_params_t *compat_param,
+ ioc_fm_pcd_kg_scheme_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg(compat," {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->modify = compat_param->modify;
+
+ /* scm_id */
+ if (compat_param->modify)
+ {
+ param->scm_id.scheme_id = compat_pcd_id2ptr(compat_param->scm_id.scheme_id);
+ _fm_cpt_dbg(compat," param->scm_id.scheme_id = %p \n", param->scm_id.scheme_id);
+ }
+ else
+ param->scm_id.relative_scheme_id = compat_param->scm_id.relative_scheme_id;
+
+ param->always_direct = compat_param->always_direct;
+ /* net_env_params */
+ param->net_env_params.net_env_id = compat_pcd_id2ptr(compat_param->net_env_params.net_env_id);
+ param->net_env_params.num_of_distinction_units = compat_param->net_env_params.num_of_distinction_units;
+ memcpy(param->net_env_params.unit_ids,
+ compat_param->net_env_params.unit_ids,
+ IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS);
+
+ param->use_hash = compat_param->use_hash;
+ memcpy(&param->key_extract_and_hash_params,
+ &compat_param->key_extract_and_hash_params,
+ sizeof(ioc_fm_pcd_kg_key_extract_and_hash_params_t));
+ param->bypass_fqid_generation = compat_param->bypass_fqid_generation;
+ param->base_fqid = compat_param->base_fqid;
+#if DPAA_VERSION >= 11
+ param->override_storage_profile =
+ compat_param->override_storage_profile;
+ param->storage_profile = compat_param->storage_profile;
+#endif
+ param->num_of_used_extracted_ors = compat_param->num_of_used_extracted_ors;
+ memcpy(param->extracted_ors,
+ compat_param->extracted_ors,
+ IOC_FM_PCD_KG_NUM_OF_GENERIC_REGS * sizeof(ioc_fm_pcd_kg_extracted_or_params_t));
+ param->next_engine = compat_param->next_engine;
+
+ /* kg_next_engine_params */
+ if (param->next_engine == e_IOC_FM_PCD_CC)
+ {
+ param->kg_next_engine_params.cc.tree_id = compat_pcd_id2ptr(compat_param->kg_next_engine_params.cc.tree_id);
+ param->kg_next_engine_params.cc.grp_id = compat_param->kg_next_engine_params.cc.grp_id;
+ param->kg_next_engine_params.cc.plcr_next = compat_param->kg_next_engine_params.cc.plcr_next;
+ param->kg_next_engine_params.cc.bypass_plcr_profile_generation
+ = compat_param->kg_next_engine_params.cc.bypass_plcr_profile_generation;
+ memcpy(&param->kg_next_engine_params.cc.plcr_profile,
+ &compat_param->kg_next_engine_params.cc.plcr_profile,
+ sizeof(ioc_fm_pcd_kg_plcr_profile_t));
+ }
+ else
+ memcpy(&param->kg_next_engine_params,
+ &compat_param->kg_next_engine_params,
+ sizeof(param->kg_next_engine_params));
+
+ memcpy(&param->scheme_counter,
+ &compat_param->scheme_counter,
+ sizeof(ioc_fm_pcd_kg_scheme_counter_t));
+ }
+ else
+ {
+ compat_param->modify = param->modify;
+
+ /* scm_id */
+ if (param->modify)
+ compat_param->scm_id.scheme_id = compat_pcd_ptr2id(param->scm_id.scheme_id);
+ else
+ compat_param->scm_id.relative_scheme_id = param->scm_id.relative_scheme_id;
+
+ compat_param->always_direct = param->always_direct;
+
+ /* net_env_params */
+ compat_param->net_env_params.net_env_id = compat_pcd_ptr2id(param->net_env_params.net_env_id);
+ compat_param->net_env_params.num_of_distinction_units = param->net_env_params.num_of_distinction_units;
+ memcpy(compat_param->net_env_params.unit_ids, param->net_env_params.unit_ids, IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS);
+
+ compat_param->use_hash = param->use_hash;
+ memcpy(&compat_param->key_extract_and_hash_params, &param->key_extract_and_hash_params, sizeof(ioc_fm_pcd_kg_key_extract_and_hash_params_t));
+ compat_param->bypass_fqid_generation = param->bypass_fqid_generation;
+ compat_param->base_fqid = param->base_fqid;
+#if DPAA_VERSION >= 11
+ compat_param->override_storage_profile =
+ param->override_storage_profile;
+ compat_param->storage_profile = param->storage_profile;
+#endif
+ compat_param->num_of_used_extracted_ors = param->num_of_used_extracted_ors;
+ memcpy(compat_param->extracted_ors, param->extracted_ors, IOC_FM_PCD_KG_NUM_OF_GENERIC_REGS * sizeof(ioc_fm_pcd_kg_extracted_or_params_t));
+ compat_param->next_engine = param->next_engine;
+
+ /* kg_next_engine_params */
+ if (compat_param->next_engine == e_IOC_FM_PCD_CC)
+ {
+ compat_param->kg_next_engine_params.cc.tree_id = compat_pcd_ptr2id(param->kg_next_engine_params.cc.tree_id);
+ compat_param->kg_next_engine_params.cc.grp_id = param->kg_next_engine_params.cc.grp_id;
+ compat_param->kg_next_engine_params.cc.plcr_next = param->kg_next_engine_params.cc.plcr_next;
+ compat_param->kg_next_engine_params.cc.bypass_plcr_profile_generation
+ = param->kg_next_engine_params.cc.bypass_plcr_profile_generation;
+ memcpy(&compat_param->kg_next_engine_params.cc.plcr_profile,
+ &param->kg_next_engine_params.cc.plcr_profile,
+ sizeof(ioc_fm_pcd_kg_plcr_profile_t));
+ }
+ else
+ memcpy(&param->kg_next_engine_params, &compat_param->kg_next_engine_params, sizeof(compat_param->kg_next_engine_params));
+
+ memcpy(&compat_param->scheme_counter, &param->scheme_counter, sizeof(ioc_fm_pcd_kg_scheme_counter_t));
+
+ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE);
+ }
+
+ _fm_cpt_dbg(compat," ...->}\n");
+}
+
+void compat_copy_fm_pcd_kg_scheme_select(
+ ioc_compat_fm_pcd_kg_scheme_select_t *compat_param,
+ ioc_fm_pcd_kg_scheme_select_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->direct = compat_param->direct;
+ if (param->direct)
+ param->scheme_id = compat_pcd_id2ptr(compat_param->scheme_id);
+ }
+}
+
+void compat_copy_fm_pcd_kg_schemes_params(
+ ioc_compat_fm_pcd_port_schemes_params_t *compat_param,
+ ioc_fm_pcd_port_schemes_params_t *param,
+ uint8_t compat)
+{
+ int k;
+
+ if (compat == COMPAT_US_TO_K) {
+ param->num_of_schemes = compat_param->num_of_schemes;
+ for(k=0; k < compat_param->num_of_schemes; k++)
+ param->scheme_ids[k] = compat_pcd_id2ptr(compat_param->scheme_ids[k]);
+ }
+}
+
+void compat_copy_fm_port_pcd_cc(
+ ioc_compat_fm_port_pcd_cc_params_t *compat_cc_params ,
+ ioc_fm_port_pcd_cc_params_t *p_cc_params,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K){
+ p_cc_params->cc_tree_id = compat_pcd_id2ptr(compat_cc_params->cc_tree_id);
+ }
+}
+
+void compat_copy_fm_port_pcd_kg(
+ ioc_compat_fm_port_pcd_kg_params_t *compat_param,
+ ioc_fm_port_pcd_kg_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K){
+ uint8_t k;
+
+ param->num_of_schemes = compat_param->num_of_schemes;
+ for(k=0; k<compat_param->num_of_schemes; k++)
+ param->scheme_ids[k] = compat_pcd_id2ptr(compat_param->scheme_ids[k]);
+
+ param->direct_scheme = compat_param->direct_scheme;
+ if (param->direct_scheme)
+ param->direct_scheme_id = compat_pcd_id2ptr(compat_param->direct_scheme_id);
+ }
+}
+
+void compat_copy_fm_port_pcd(
+ ioc_compat_fm_port_pcd_params_t *compat_param,
+ ioc_fm_port_pcd_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ {
+ ioc_fm_port_pcd_prs_params_t *same_port_pcd_prs_params;
+ ioc_compat_fm_port_pcd_cc_params_t *compat_port_pcd_cc_params;
+ ioc_compat_fm_port_pcd_kg_params_t *compat_port_pcd_kg_params;
+ ioc_compat_fm_port_pcd_plcr_params_t *compat_port_pcd_plcr_params;
+
+ same_port_pcd_prs_params = (ioc_fm_port_pcd_prs_params_t *) (compat_param + 1);
+ compat_port_pcd_cc_params = (ioc_compat_fm_port_pcd_cc_params_t *) (same_port_pcd_prs_params + 1);
+ compat_port_pcd_kg_params = (ioc_compat_fm_port_pcd_kg_params_t *) (compat_port_pcd_cc_params + 1);
+ compat_port_pcd_plcr_params = (ioc_compat_fm_port_pcd_plcr_params_t *) (compat_port_pcd_kg_params + 1);
+
+ _fm_cpt_dbg(compat,"\n param->p_prs_params=%p \n", param->p_prs_params);
+ _fm_cpt_dbg(compat," param->p_cc_params=%p \n", param->p_cc_params);
+ _fm_cpt_dbg(compat," param->p_kg_params=%p \n", param->p_kg_params);
+ _fm_cpt_dbg(compat," param->p_plcr_params=%p \n", param->p_plcr_params);
+ _fm_cpt_dbg(compat," param->p_ip_reassembly_manip=%p \n", param->p_ip_reassembly_manip);
+
+ param->pcd_support = compat_param->pcd_support;
+ param->net_env_id = compat_pcd_id2ptr(compat_param->net_env_id);
+
+ if (param->p_cc_params)
+ compat_copy_fm_port_pcd_cc(compat_port_pcd_cc_params, param->p_cc_params, COMPAT_US_TO_K);
+ if (param->p_kg_params)
+ compat_copy_fm_port_pcd_kg(compat_port_pcd_kg_params, param->p_kg_params, COMPAT_US_TO_K);
+ if (param->p_plcr_params)
+ param->p_plcr_params->plcr_profile_id = compat_pcd_id2ptr(compat_port_pcd_plcr_params->plcr_profile_id);
+ param->p_ip_reassembly_manip = compat_pcd_id2ptr(compat_param->p_ip_reassembly_manip);
+ }
+}
+
+void compat_copy_fm_port_pcd_modify_tree(
+ ioc_compat_fm_obj_t *compat_id,
+ ioc_fm_obj_t *id,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ id->obj = compat_pcd_id2ptr(compat_id->obj);
+}
+
+#if (DPAA_VERSION >= 11)
+void compat_copy_fm_port_vsp_alloc_params(
+ ioc_compat_fm_port_vsp_alloc_params_t *compat_param,
+ ioc_fm_port_vsp_alloc_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ {
+ _fm_cpt_dbg(compat," param->p_fm_tx_port=%p \n", param->p_fm_tx_port);
+
+ param->dflt_relative_id = compat_param->dflt_relative_id;
+ param->num_of_profiles = compat_param->num_of_profiles;
+ param->p_fm_tx_port = compat_pcd_id2ptr(compat_param->p_fm_tx_port);
+ }
+}
+#endif /* (DPAA_VERSION >= 11) */
+
+void compat_copy_fm_pcd_cc_tbl_get_miss(
+ ioc_compat_fm_pcd_cc_tbl_get_miss_params_t *compat_param,
+ ioc_fm_pcd_cc_tbl_get_miss_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->id = compat_pcd_id2ptr(compat_param->id);
+ memcpy(&param->miss_statistics, &compat_param->miss_statistics, sizeof(ioc_fm_pcd_cc_key_statistics_t));
+ } else {
+ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE);
+ memcpy(&compat_param->miss_statistics, &param->miss_statistics, sizeof(ioc_fm_pcd_cc_key_statistics_t));
+ }
+}
+
+
+void compat_copy_fm_pcd_net_env(
+ ioc_compat_fm_pcd_net_env_params_t *compat_param,
+ ioc_fm_pcd_net_env_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->num_of_distinction_units = compat_param->num_of_distinction_units;
+ memcpy(param->units, compat_param->units, sizeof(ioc_fm_pcd_distinction_unit_t)*IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS);
+ param->id = NULL; /* to avoid passing garbage to the kernel */
+ }
+ else
+ {
+ compat_param->num_of_distinction_units = param->num_of_distinction_units;
+ memcpy(compat_param->units, param->units, sizeof(ioc_fm_pcd_distinction_unit_t)*IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS);
+
+ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE);
+ }
+}
+
+void compat_copy_fm_pcd_cc_node_modify_key(
+ ioc_compat_fm_pcd_cc_node_modify_key_params_t *compat_param,
+ ioc_fm_pcd_cc_node_modify_key_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->key_indx = compat_param->key_indx;
+ param->key_size = compat_param->key_size;
+ param->p_key = (uint8_t *)compat_ptr(compat_param->p_key);
+ _fm_cpt_dbg(compat," param->p_key = %p \n", param->p_key);
+ param->p_mask = (uint8_t *)compat_ptr(compat_param->p_mask);
+ _fm_cpt_dbg(compat," param->p_mask = %p\n", param->p_mask);
+ param->id = compat_pcd_id2ptr(compat_param->id);
+ _fm_cpt_dbg(compat," param->id = %p \n", param->id);
+ }
+ else
+ {
+ compat_param->key_indx = param->key_indx;
+ compat_param->key_size = param->key_size;
+ compat_param->p_key = ptr_to_compat((void *)param->p_key);
+ compat_param->p_mask = ptr_to_compat((void *)param->p_mask);
+
+ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE);
+ }
+}
+
+void compat_copy_keys(
+ ioc_compat_keys_params_t *compat_param,
+ ioc_keys_params_t *param,
+ uint8_t compat)
+{
+ int k = 0;
+
+ _fm_cpt_dbg(compat," {->...\n");
+
+ if (compat == COMPAT_US_TO_K) {
+ param->max_num_of_keys = compat_param->max_num_of_keys;
+ param->mask_support = compat_param->mask_support;
+ param->statistics_mode = compat_param->statistics_mode;
+ param->num_of_keys = compat_param->num_of_keys;
+ param->key_size = compat_param->key_size;
+#if (DPAA_VERSION >= 11)
+ memcpy(&param->frame_length_ranges,
+ &compat_param->frame_length_ranges,
+ sizeof(param->frame_length_ranges[0]) *
+ IOC_FM_PCD_CC_STATS_MAX_NUM_OF_FLR);
+#endif /* (DPAA_VERSION >= 11) */
+ }
+ else {
+ compat_param->max_num_of_keys = param->max_num_of_keys;
+ compat_param->mask_support = param->mask_support;
+ compat_param->statistics_mode = param->statistics_mode;
+ compat_param->num_of_keys = param->num_of_keys;
+ compat_param->key_size = param->key_size;
+#if (DPAA_VERSION >= 11)
+ memcpy(&compat_param->frame_length_ranges,
+ &param->frame_length_ranges,
+ sizeof(compat_param->frame_length_ranges[0] *
+ IOC_FM_PCD_CC_STATS_MAX_NUM_OF_FLR));
+#endif /* (DPAA_VERSION >= 11) */
+ }
+
+ for (k=0; k < IOC_FM_PCD_MAX_NUM_OF_KEYS; k++)
+ compat_copy_fm_pcd_cc_key(
+ &compat_param->key_params[k],
+ &param->key_params[k],
+ compat);
+
+ compat_copy_fm_pcd_cc_next_engine(
+ &compat_param->cc_next_engine_params_for_miss,
+ &param->cc_next_engine_params_for_miss,
+ compat);
+
+ _fm_cpt_dbg(compat," ...->}\n");
+}
+
+void compat_copy_fm_pcd_cc_node(
+ ioc_compat_fm_pcd_cc_node_params_t *compat_param,
+ ioc_fm_pcd_cc_node_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg(compat," {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ memcpy(&param->extract_cc_params, &compat_param->extract_cc_params, sizeof(ioc_fm_pcd_extract_entry_t));
+
+ else
+ {
+ compat_copy_keys(&compat_param->keys_params, &param->keys_params, compat);
+
+ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE);
+ _fm_cpt_dbg(compat," param->id = %p \n", param->id);
+ }
+
+ compat_copy_keys(&compat_param->keys_params, &param->keys_params, compat);
+
+ _fm_cpt_dbg(compat," ...->}\n");
+}
+
+void compat_fm_pcd_manip_set_node(
+ ioc_compat_fm_pcd_manip_params_t *compat_param,
+ ioc_fm_pcd_manip_params_t *param,
+ uint8_t compat)
+{
+ if (compat == COMPAT_US_TO_K) {
+ param->type = compat_param->type;
+ switch (param->type) {
+ case e_IOC_FM_PCD_MANIP_HDR:
+ param->u.hdr.rmv = compat_param->u.hdr.rmv;
+ memcpy(&param->u.hdr.rmv_params,
+ &compat_param->u.hdr.rmv_params,
+ sizeof(param->u.hdr.rmv_params));
+
+ param->u.hdr.insrt = compat_param->u.hdr.insrt;
+ param->u.hdr.insrt_params.type =
+ compat_param->u.hdr.insrt_params.type;
+ switch (compat_param->u.hdr.insrt_params.type)
+ {
+ case e_IOC_FM_PCD_MANIP_INSRT_GENERIC:
+ param->u.hdr.insrt_params.u.generic.offset =
+ compat_param->u.hdr.insrt_params.u.generic.offset;
+ param->u.hdr.insrt_params.u.generic.size =
+ compat_param->u.hdr.insrt_params.u.generic.size;
+ param->u.hdr.insrt_params.u.generic.replace =
+ compat_param->u.hdr.insrt_params.u.generic.replace;
+ param->u.hdr.insrt_params.u.generic.p_data =
+ compat_ptr(compat_param->u.hdr.insrt_params.u.generic.p_data);
+ break;
+ case e_IOC_FM_PCD_MANIP_INSRT_BY_HDR:
+ param->u.hdr.insrt_params.u.by_hdr.type =
+ compat_param->u.hdr.insrt_params.u.by_hdr.type;
+ param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.specific_l2 =
+ compat_param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.specific_l2;
+ param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.update =
+ compat_param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.update;
+ param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.size =
+ compat_param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.size;
+ param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.p_data =
+ compat_ptr(compat_param->u.hdr.insrt_params.u.by_hdr.u.specific_l2_params.p_data);
+ break;
+ default:
+ _fm_cpt_err("Unsupported type: %d", compat_param->u.hdr.insrt_params.type);
+ }
+
+ param->u.hdr.field_update = compat_param->u.hdr.field_update;
+ memcpy(&param->u.hdr.field_update_params,
+ &compat_param->u.hdr.field_update_params,
+ sizeof(param->u.hdr.field_update_params));
+
+ param->u.hdr.custom = compat_param->u.hdr.custom;
+ memcpy(&param->u.hdr.custom_params,
+ &compat_param->u.hdr.custom_params,
+ sizeof(param->u.hdr.custom_params));
+
+ param->u.hdr.dont_parse_after_manip =
+ compat_param->u.hdr.dont_parse_after_manip;
+ break;
+ case e_IOC_FM_PCD_MANIP_REASSEM:
+ memcpy(&param->u.reassem, &compat_param->u.reassem, sizeof(param->u.reassem));
+ break;
+ case e_IOC_FM_PCD_MANIP_FRAG:
+ memcpy(&param->u.frag, &compat_param->u.frag, sizeof(param->u.frag));
+ break;
+ case e_IOC_FM_PCD_MANIP_SPECIAL_OFFLOAD:
+ param->u.special_offload = compat_param->u.special_offload;
+ break;
+ }
+
+ param->p_next_manip = compat_pcd_id2ptr(compat_param->p_next_manip);
+ param->id = compat_pcd_id2ptr(compat_param->id);
+ }
+ else {
+ compat_param->type = param->type;
+ memcpy(&compat_param->u, &param->u, sizeof(compat_param->u));
+
+ if (param->type == e_IOC_FM_PCD_MANIP_HDR &&
+ param->u.hdr.insrt_params.type == e_IOC_FM_PCD_MANIP_INSRT_GENERIC)
+ compat_param->u.hdr.insrt_params.u.generic.p_data =
+ ptr_to_compat(param->u.hdr.insrt_params.u.generic.p_data);
+
+ compat_param->p_next_manip = compat_pcd_ptr2id(param->id);
+ /* ... should be one that was added previously by the very call to
+ compat_add_ptr2id() below: */
+ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE);
+ }
+}
+
+#if (DPAA_VERSION >= 11)
+void compat_copy_fm_pcd_frm_replic_group_params(
+ ioc_compat_fm_pcd_frm_replic_group_params_t *compat_param,
+ ioc_fm_pcd_frm_replic_group_params_t *param,
+ uint8_t compat)
+{
+ int k;
+
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->max_num_of_entries = compat_param->max_num_of_entries;
+ param->num_of_entries = compat_param->num_of_entries;
+ param->id = compat_pcd_id2ptr(compat_param->id);
+ }
+ else
+ {
+ compat_param->max_num_of_entries = param->max_num_of_entries;
+ compat_param->num_of_entries = param->num_of_entries;
+ compat_param->id = compat_add_ptr2id(param->id,
+ FM_MAP_TYPE_PCD_NODE);
+ }
+
+ for (k=0; k < IOC_FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES; k++)
+ compat_copy_fm_pcd_cc_next_engine(
+ &compat_param->next_engine_params[k],
+ &param->next_engine_params[k],
+ compat);
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+void compat_copy_fm_pcd_frm_replic_member(
+ ioc_compat_fm_pcd_frm_replic_member_t *compat_param,
+ ioc_fm_pcd_frm_replic_member_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->h_replic_group = compat_pcd_id2ptr(compat_param->h_replic_group);
+ param->member_index = compat_param->member_index;
+ }
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+void compat_copy_fm_pcd_frm_replic_member_params(
+ ioc_compat_fm_pcd_frm_replic_member_params_t *compat_param,
+ ioc_fm_pcd_frm_replic_member_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ compat_copy_fm_pcd_frm_replic_member(&compat_param->member,
+ &param->member, compat);
+
+ compat_copy_fm_pcd_cc_next_engine(&compat_param->next_engine_params,
+ &param->next_engine_params, compat);
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+void compat_copy_fm_vsp_params(
+ ioc_compat_fm_vsp_params_t *compat_param,
+ ioc_fm_vsp_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->p_fm = compat_pcd_id2ptr(compat_param->p_fm);
+ memcpy(&param->ext_buf_pools, &compat_param->ext_buf_pools, sizeof(ioc_fm_ext_pools));
+ param->liodn_offset = compat_param->liodn_offset;
+ param->port_params.port_id = compat_param->port_params.port_id;
+ param->port_params.port_type = compat_param->port_params.port_type;
+ param->relative_profile_id = compat_param->relative_profile_id;
+ param->id = compat_pcd_id2ptr(compat_param->id);
+ }
+ else
+ {
+ compat_param->p_fm = compat_pcd_ptr2id(param->p_fm);
+ memcpy(&compat_param->ext_buf_pools, &param->ext_buf_pools, sizeof(ioc_fm_ext_pools));
+ compat_param->liodn_offset = param->liodn_offset;
+ compat_param->port_params.port_id = param->port_params.port_id;
+ compat_param->port_params.port_type = param->port_params.port_type;
+ compat_param->relative_profile_id = param->relative_profile_id;
+ compat_param->id = compat_add_ptr2id(param->id, FM_MAP_TYPE_PCD_NODE);
+ }
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+void compat_copy_fm_buf_pool_depletion_params(
+ ioc_compat_fm_buf_pool_depletion_params_t *compat_param,
+ ioc_fm_buf_pool_depletion_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->p_fm_vsp = compat_pcd_id2ptr(compat_param->p_fm_vsp);
+ memcpy(&param->fm_buf_pool_depletion,
+ &compat_param->fm_buf_pool_depletion,
+ sizeof(ioc_fm_buf_pool_depletion_t));
+ }
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+void compat_copy_fm_buffer_prefix_content_params(
+ ioc_compat_fm_buffer_prefix_content_params_t *compat_param,
+ ioc_fm_buffer_prefix_content_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->p_fm_vsp = compat_pcd_id2ptr(compat_param->p_fm_vsp);
+ memcpy(&param->fm_buffer_prefix_content,
+ &compat_param->fm_buffer_prefix_content,
+ sizeof(ioc_fm_buffer_prefix_content_t));
+ }
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+void compat_copy_fm_vsp_config_no_sg_params(
+ ioc_compat_fm_vsp_config_no_sg_params_t *compat_param,
+ ioc_fm_vsp_config_no_sg_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->p_fm_vsp = compat_pcd_id2ptr(compat_param->p_fm_vsp);
+ param->no_sg = compat_param->no_sg;
+ }
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+
+void compat_copy_fm_vsp_prs_result_params(
+ ioc_compat_fm_vsp_prs_result_params_t *compat_param,
+ ioc_fm_vsp_prs_result_params_t *param,
+ uint8_t compat)
+{
+ _fm_cpt_dbg (compat, " {->...\n");
+
+ if (compat == COMPAT_US_TO_K)
+ {
+ param->p_fm_vsp = compat_pcd_id2ptr(compat_param->p_fm_vsp);
+ /* p_data is an user-space pointer that needs to remain unmodified */
+ param->p_data = (void *)(unsigned long long)compat_param->p_data;
+ }
+ else
+ {
+ compat_param->p_fm_vsp = compat_pcd_ptr2id(param->p_fm_vsp);
+ /* p_data is an user-space pointer that needs to remain unmodified */
+ compat_param->p_data = (compat_uptr_t)((unsigned long long)param->p_data & 0xFFFFFFFF);
+ }
+
+ _fm_cpt_dbg (compat, " ...->}\n");
+}
+#endif /* (DPAA_VERSION >= 11) */
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.h b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.h
new file mode 100644
index 0000000..ae19b68
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_ioctls_fm_compat.h
@@ -0,0 +1,691 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ @File lnxwrp_ioctls_fm_compat.h
+
+ @Description FM PCD compat structures definition.
+
+*/
+
+#ifndef __FM_COMPAT_IOCTLS_H
+#define __FM_COMPAT_IOCTLS_H
+
+#include <linux/compat.h>
+
+#define COMPAT_K_TO_US 0 /* copy from Kernel to User */
+#define COMPAT_US_TO_K 1 /* copy from User to Kernel */
+#define COMPAT_GENERIC 2
+
+#define COMPAT_COPY_K2US(dest, src, type) compat_copy_##type(src, dest, 0)
+#define COMPAT_COPY_US2K(dest, src, type) compat_copy_##type(dest, src, 1)
+
+/* mapping kernel pointers w/ UserSpace id's { */
+/* Because compat_ptr(ptr_to_compat(X)) != X, this way we cannot exchange pointers
+ back and forth (US - KS). compat_ptr is a cast and pointers are broken. */
+#define COMPAT_PTR2ID_ARRAY_MAX (512+1) /* first location is not used */
+#define COMPAT_PTR2ID_WATERMARK 0xface0000
+#define COMPAT_PTR2ID_WM_MASK 0xffff0000
+
+/* define it for debug trace */
+/*#define FM_COMPAT_DBG*/
+
+#define _fm_cpt_prk(stage, format, arg...) \
+ printk(stage "fm_cpt (cpu:%u): " format, raw_smp_processor_id(), ##arg)
+
+#define _fm_cpt_inf(format, arg...) _fm_cpt_prk(KERN_INFO, format, ##arg)
+#define _fm_cpt_wrn(format, arg...) _fm_cpt_prk(KERN_WARNING, format, ##arg)
+#define _fm_cpt_err(format, arg...) _fm_cpt_prk(KERN_ERR, format, ##arg)
+
+/* used for compat IOCTL debugging */
+#if defined(FM_COMPAT_DBG)
+ #define _fm_cpt_dbg(from, format, arg...) \
+ do{ \
+ if (from == COMPAT_US_TO_K) \
+ printk("fm_cpt to KS [%s:%u](cpu:%u) - " format, \
+ __func__, __LINE__, raw_smp_processor_id(), ##arg); \
+ else if (from == COMPAT_K_TO_US) \
+ printk("fm_cpt to US [%s:%u](cpu:%u) - " format, \
+ __func__, __LINE__, raw_smp_processor_id(), ##arg); \
+ else \
+ printk("fm_cpt [%s:%u](cpu:%u) - " format, \
+ __func__, __LINE__, raw_smp_processor_id(), ##arg); \
+ }while(0)
+#else
+# define _fm_cpt_dbg(arg...)
+#endif
+
+/*TODO: per FMan module:
+ *
+ * Parser: FM_MAP_TYPE_PARSER_NODE,
+ * Kg: FM_MAP_TYPE_KG_NODE,
+ * Policer: FM_MAP_TYPE_POLICER_NODE
+ * Manip: FM_MAP_TYPE_MANIP_NODE
+ **/
+enum fm_map_node_type {
+ FM_MAP_TYPE_UNSPEC = 0,
+ FM_MAP_TYPE_PCD_NODE,
+
+ /* add types here, update the policy */
+
+ __FM_MAP_TYPE_AFTER_LAST,
+ FM_MAP_TYPE_MAX = __FM_MAP_TYPE_AFTER_LAST - 1
+};
+
+void compat_del_ptr2id(void *p, enum fm_map_node_type);
+compat_uptr_t compat_add_ptr2id(void *p, enum fm_map_node_type);
+compat_uptr_t compat_get_ptr2id(void *p, enum fm_map_node_type);
+void *compat_get_id2ptr(compat_uptr_t comp, enum fm_map_node_type);
+
+static inline compat_uptr_t compat_pcd_ptr2id(void *ptr) {
+ return (ptr)? compat_get_ptr2id(ptr, FM_MAP_TYPE_PCD_NODE)
+ : (compat_uptr_t) 0;
+}
+
+static inline void *compat_pcd_id2ptr(compat_uptr_t id) {
+ return (id) ? compat_get_id2ptr(id, FM_MAP_TYPE_PCD_NODE)
+ : NULL;
+}
+
+/* other similar inlines may be added as new nodes are added
+ to enum fm_map_node_type above... */
+/* } mapping kernel pointers w/ UserSpace id's */
+
+/* pcd compat structures { */
+typedef struct ioc_compat_fm_pcd_cc_node_remove_key_params_t {
+ compat_uptr_t id;
+ uint16_t key_indx;
+} ioc_compat_fm_pcd_cc_node_remove_key_params_t;
+
+typedef union ioc_compat_fm_pcd_plcr_next_engine_params_u {
+ ioc_fm_pcd_done_action action;
+ compat_uptr_t p_profile;
+ compat_uptr_t p_direct_scheme;
+} ioc_compat_fm_pcd_plcr_next_engine_params_u;
+
+typedef struct ioc_compat_fm_pcd_plcr_profile_params_t {
+ bool modify;
+ union {
+ struct {
+ ioc_fm_pcd_profile_type_selection profile_type;
+ compat_uptr_t p_fm_port;
+ uint16_t relative_profile_id;
+ } new_params;
+ compat_uptr_t p_profile;
+ } profile_select;
+ ioc_fm_pcd_plcr_algorithm_selection alg_selection;
+ ioc_fm_pcd_plcr_color_mode color_mode;
+
+ union {
+ ioc_fm_pcd_plcr_color dflt_color;
+ ioc_fm_pcd_plcr_color override;
+ } color;
+
+ ioc_fm_pcd_plcr_non_passthrough_alg_param_t non_passthrough_alg_param;
+
+ ioc_fm_pcd_engine next_engine_on_green;
+ ioc_compat_fm_pcd_plcr_next_engine_params_u params_on_green;
+
+ ioc_fm_pcd_engine next_engine_on_yellow;
+ ioc_compat_fm_pcd_plcr_next_engine_params_u params_on_yellow;
+
+ ioc_fm_pcd_engine next_engine_on_red;
+ ioc_compat_fm_pcd_plcr_next_engine_params_u params_on_red;
+
+ bool trap_profile_on_flow_A;
+ bool trap_profile_on_flow_B;
+ bool trap_profile_on_flow_C;
+ compat_uptr_t id;
+} ioc_compat_fm_pcd_plcr_profile_params_t;
+
+typedef struct ioc_compat_fm_obj_t {
+ compat_uptr_t obj;
+} ioc_compat_fm_obj_t;
+
+typedef struct ioc_compat_fm_pcd_kg_scheme_select_t {
+ bool direct;
+ compat_uptr_t scheme_id;
+} ioc_compat_fm_pcd_kg_scheme_select_t;
+
+typedef struct ioc_compat_fm_pcd_port_schemes_params_t {
+ uint8_t num_of_schemes;
+ compat_uptr_t scheme_ids[FM_PCD_KG_NUM_OF_SCHEMES];
+} ioc_compat_fm_pcd_port_schemes_params_t;
+
+#if (DPAA_VERSION >= 11)
+typedef struct ioc_compat_fm_port_vsp_alloc_params_t {
+ uint8_t num_of_profiles; /**< Number of Virtual Storage Profiles */
+ uint8_t dflt_relative_id; /**< The default Virtual-Storage-Profile-id dedicated to Rx/OP port
+ The same default Virtual-Storage-Profile-id will be for coupled Tx port
+ if relevant function called for Rx port */
+ compat_uptr_t p_fm_tx_port; /**< Handle to coupled Tx Port; not relevant for OP port. */
+}ioc_compat_fm_port_vsp_alloc_params_t;
+#endif /* (DPAA_VERSION >= 11) */
+
+typedef struct ioc_compat_fm_pcd_net_env_params_t {
+ uint8_t num_of_distinction_units;
+ ioc_fm_pcd_distinction_unit_t units[IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS]; /* same structure*/
+ compat_uptr_t id;
+} ioc_compat_fm_pcd_net_env_params_t;
+
+typedef struct ioc_compat_fm_pcd_prs_sw_params_t {
+ bool override;
+ uint32_t size;
+ uint16_t base;
+ compat_uptr_t p_code;
+ uint32_t sw_prs_data_params[IOC_FM_PCD_PRS_NUM_OF_HDRS];
+ uint8_t num_of_labels;
+ ioc_fm_pcd_prs_label_params_t labels_table[IOC_FM_PCD_PRS_NUM_OF_LABELS];
+} ioc_compat_fm_pcd_prs_sw_params_t;
+
+typedef struct ioc_compat_fm_pcd_cc_next_kg_params_t {
+ bool override_fqid;
+ uint32_t new_fqid;
+#if DPAA_VERSION >= 11
+ uint8_t new_relative_storage_profile_id;
+#endif
+ compat_uptr_t p_direct_scheme;
+} ioc_compat_fm_pcd_cc_next_kg_params_t;
+
+typedef struct ioc_compat_fm_pcd_cc_next_cc_params_t {
+ compat_uptr_t cc_node_id;
+} ioc_compat_fm_pcd_cc_next_cc_params_t;
+
+#if DPAA_VERSION >= 11
+typedef struct ioc_compat_fm_pcd_cc_next_fr_params_t {
+ compat_uptr_t frm_replic_id;
+} ioc_compat_fm_pcd_cc_next_fr_params_t;
+#endif /* DPAA_VERSION >= 11 */
+
+typedef struct ioc_compat_fm_pcd_cc_next_engine_params_t {
+ ioc_fm_pcd_engine next_engine;
+ union {
+ ioc_compat_fm_pcd_cc_next_cc_params_t cc_params; /**< compat structure*/
+ ioc_fm_pcd_cc_next_plcr_params_t plcr_params; /**< same structure*/
+ ioc_fm_pcd_cc_next_enqueue_params_t enqueue_params; /**< same structure*/
+ ioc_compat_fm_pcd_cc_next_kg_params_t kg_params; /**< compat structure*/
+#if DPAA_VERSION >= 11
+ ioc_compat_fm_pcd_cc_next_fr_params_t fr_params; /**< compat structure*/
+#endif /* DPAA_VERSION >= 11 */
+ } params;
+ compat_uptr_t manip_id;
+ bool statistics_en;
+} ioc_compat_fm_pcd_cc_next_engine_params_t;
+
+typedef struct ioc_compat_fm_pcd_cc_grp_params_t {
+ uint8_t num_of_distinction_units;
+ uint8_t unit_ids [IOC_FM_PCD_MAX_NUM_OF_CC_UNITS];
+ ioc_compat_fm_pcd_cc_next_engine_params_t next_engine_per_entries_in_grp[IOC_FM_PCD_MAX_NUM_OF_CC_ENTRIES_IN_GRP];
+} ioc_compat_fm_pcd_cc_grp_params_t;
+
+typedef struct ioc_compat_fm_pcd_cc_tree_params_t {
+ compat_uptr_t net_env_id;
+ uint8_t num_of_groups;
+ ioc_compat_fm_pcd_cc_grp_params_t fm_pcd_cc_group_params [IOC_FM_PCD_MAX_NUM_OF_CC_GROUPS];
+ compat_uptr_t id;
+} ioc_compat_fm_pcd_cc_tree_params_t;
+
+typedef struct ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t {
+ compat_uptr_t id;
+ uint8_t grp_indx;
+ uint8_t indx;
+ ioc_compat_fm_pcd_cc_next_engine_params_t cc_next_engine_params;
+} ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t;
+
+typedef struct ioc_compat_fm_pcd_cc_key_params_t {
+ compat_uptr_t p_key;
+ compat_uptr_t p_mask;
+ ioc_compat_fm_pcd_cc_next_engine_params_t cc_next_engine_params; /**< compat structure*/
+} ioc_compat_fm_pcd_cc_key_params_t;
+
+typedef struct ioc_compat_keys_params_t {
+ uint16_t max_num_of_keys;
+ bool mask_support;
+ ioc_fm_pcd_cc_stats_mode statistics_mode;
+#if (DPAA_VERSION >= 11)
+ uint16_t frame_length_ranges[IOC_FM_PCD_CC_STATS_MAX_NUM_OF_FLR];
+#endif /* (DPAA_VERSION >= 11) */
+ uint16_t num_of_keys;
+ uint8_t key_size;
+ ioc_compat_fm_pcd_cc_key_params_t key_params[IOC_FM_PCD_MAX_NUM_OF_KEYS]; /**< compat structure*/
+ ioc_compat_fm_pcd_cc_next_engine_params_t cc_next_engine_params_for_miss; /**< compat structure*/
+} ioc_compat_keys_params_t;
+
+typedef struct ioc_compat_fm_pcd_cc_node_params_t {
+ ioc_fm_pcd_extract_entry_t extract_cc_params; /**< same structure*/
+ ioc_compat_keys_params_t keys_params; /**< compat structure*/
+ compat_uptr_t id;
+} ioc_compat_fm_pcd_cc_node_params_t;
+
+/**************************************************************************//**
+ @Description Parameters for defining a hash table
+*//***************************************************************************/
+typedef struct ioc_compat_fm_pcd_hash_table_params_t {
+ uint16_t max_num_of_keys;
+ ioc_fm_pcd_cc_stats_mode statistics_mode;
+ uint8_t kg_hash_shift;
+ uint16_t hash_res_mask;
+ uint8_t hash_shift;
+ uint8_t match_key_size;
+ ioc_compat_fm_pcd_cc_next_engine_params_t cc_next_engine_params_for_miss;
+ compat_uptr_t id;
+} ioc_compat_fm_pcd_hash_table_params_t;
+
+typedef struct ioc_compat_fm_pcd_hash_table_add_key_params_t {
+ compat_uptr_t p_hash_tbl;
+ uint8_t key_size;
+ ioc_compat_fm_pcd_cc_key_params_t key_params;
+} ioc_compat_fm_pcd_hash_table_add_key_params_t;
+
+typedef struct ioc_compat_fm_pcd_cc_node_modify_key_params_t {
+ compat_uptr_t id;
+ uint16_t key_indx;
+ uint8_t key_size;
+ compat_uptr_t p_key;
+ compat_uptr_t p_mask;
+} ioc_compat_fm_pcd_cc_node_modify_key_params_t;
+
+typedef struct ioc_compat_fm_pcd_hash_table_remove_key_params_t {
+ compat_uptr_t p_hash_tbl;
+ uint8_t key_size;
+ compat_uptr_t p_key;
+} ioc_compat_fm_pcd_hash_table_remove_key_params_t;
+
+typedef struct ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t {
+ compat_uptr_t id;
+ uint16_t key_indx;
+ uint8_t key_size;
+ ioc_compat_fm_pcd_cc_key_params_t key_params;
+} ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t;
+
+typedef struct ioc_compat_fm_port_pcd_plcr_params_t {
+ compat_uptr_t plcr_profile_id;
+} ioc_compat_fm_port_pcd_plcr_params_t;
+
+typedef struct ioc_compat_fm_port_pcd_cc_params_t {
+ compat_uptr_t cc_tree_id;
+} ioc_compat_fm_port_pcd_cc_params_t;
+
+typedef struct ioc_compat_fm_port_pcd_kg_params_t {
+ uint8_t num_of_schemes;
+ compat_uptr_t scheme_ids[FM_PCD_KG_NUM_OF_SCHEMES];
+ bool direct_scheme;
+ compat_uptr_t direct_scheme_id;
+} ioc_compat_fm_port_pcd_kg_params_t;
+
+typedef struct ioc_compat_fm_port_pcd_params_t {
+ ioc_fm_port_pcd_support pcd_support;
+ compat_uptr_t net_env_id;
+ compat_uptr_t p_prs_params;
+ compat_uptr_t p_cc_params;
+ compat_uptr_t p_kg_params;
+ compat_uptr_t p_plcr_params;
+ compat_uptr_t p_ip_reassembly_manip;
+} ioc_compat_fm_port_pcd_params_t;
+
+typedef struct ioc_compat_fm_pcd_kg_cc_t {
+ compat_uptr_t tree_id;
+ uint8_t grp_id;
+ bool plcr_next;
+ bool bypass_plcr_profile_generation;
+ ioc_fm_pcd_kg_plcr_profile_t plcr_profile;
+} ioc_compat_fm_pcd_kg_cc_t;
+
+typedef struct ioc_compat_fm_pcd_kg_scheme_params_t {
+ bool modify;
+ union {
+ uint8_t relative_scheme_id;
+ compat_uptr_t scheme_id;
+ } scm_id;
+ bool always_direct;
+ struct {
+ compat_uptr_t net_env_id;
+ uint8_t num_of_distinction_units;
+ uint8_t unit_ids[IOC_FM_PCD_MAX_NUM_OF_DISTINCTION_UNITS];
+ } net_env_params;
+ bool use_hash;
+ ioc_fm_pcd_kg_key_extract_and_hash_params_t key_extract_and_hash_params;
+ bool bypass_fqid_generation;
+ uint32_t base_fqid;
+ uint8_t num_of_used_extracted_ors;
+ ioc_fm_pcd_kg_extracted_or_params_t extracted_ors[IOC_FM_PCD_KG_NUM_OF_GENERIC_REGS];
+#if DPAA_VERSION >= 11
+ bool override_storage_profile;
+ ioc_fm_pcd_kg_storage_profile_t storage_profile;
+#endif /* DPAA_VERSION >= 11 */
+ ioc_fm_pcd_engine next_engine;
+ union{
+ ioc_fm_pcd_done_action done_action;
+ ioc_fm_pcd_kg_plcr_profile_t plcr_profile;
+ ioc_compat_fm_pcd_kg_cc_t cc;
+ } kg_next_engine_params;
+ ioc_fm_pcd_kg_scheme_counter_t scheme_counter;
+ compat_uptr_t id;
+} ioc_compat_fm_pcd_kg_scheme_params_t;
+
+typedef struct ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t {
+ compat_uptr_t id;
+ uint16_t key_indx;
+ uint8_t key_size;
+ ioc_compat_fm_pcd_cc_next_engine_params_t cc_next_engine_params;
+} ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t;
+
+typedef struct ioc_compat_fm_pcd_manip_hdr_insrt_generic_params_t {
+ uint8_t offset;
+ uint8_t size;
+ bool replace;
+ compat_uptr_t p_data;
+} ioc_compat_fm_pcd_manip_hdr_insrt_generic_params_t;
+
+typedef struct ioc_compat_fm_pcd_manip_hdr_insrt_specific_l2_params_t {
+ ioc_fm_pcd_manip_hdr_insrt_specific_l2 specific_l2;
+ bool update;
+ uint8_t size;
+ compat_uptr_t p_data;
+} ioc_compat_fm_pcd_manip_hdr_insrt_specific_l2_params_t;
+
+typedef struct ioc_compat_fm_pcd_manip_hdr_insrt_by_hdr_params_t {
+ ioc_fm_pcd_manip_hdr_insrt_by_hdr_type type;
+ union {
+ ioc_compat_fm_pcd_manip_hdr_insrt_specific_l2_params_t specific_l2_params;
+ } u;
+} ioc_compat_fm_pcd_manip_hdr_insrt_by_hdr_params_t;
+
+typedef struct ioc_compat_fm_pcd_manip_hdr_insrt_params_t {
+ ioc_fm_pcd_manip_hdr_insrt_type type;
+ union {
+ ioc_compat_fm_pcd_manip_hdr_insrt_by_hdr_params_t by_hdr;
+ ioc_compat_fm_pcd_manip_hdr_insrt_generic_params_t generic;
+#ifdef FM_CAPWAP_SUPPORT
+#error CAPWAP not supported!
+ ioc_fm_pcd_manip_hdr_insrt_by_template_params_t by_template;
+#endif /* FM_CAPWAP_SUPPORT */
+ } u;
+} ioc_compat_fm_pcd_manip_hdr_insrt_params_t;
+
+typedef struct ioc_compat_fm_pcd_manip_hdr_params_t {
+ bool rmv;
+ ioc_fm_pcd_manip_hdr_rmv_params_t rmv_params;
+ bool insrt;
+ ioc_compat_fm_pcd_manip_hdr_insrt_params_t insrt_params;
+ bool field_update;
+ ioc_fm_pcd_manip_hdr_field_update_params_t field_update_params;
+ bool custom;
+ ioc_fm_pcd_manip_hdr_custom_params_t custom_params;
+ bool dont_parse_after_manip;
+} ioc_compat_fm_pcd_manip_hdr_params_t;
+
+typedef struct ioc_compat_fm_pcd_manip_params_t {
+ ioc_fm_pcd_manip_type type;
+ union {
+ ioc_compat_fm_pcd_manip_hdr_params_t hdr;
+ ioc_fm_pcd_manip_reassem_params_t reassem;
+ ioc_fm_pcd_manip_frag_params_t frag;
+ ioc_fm_pcd_manip_special_offload_params_t special_offload;
+ } u;
+ compat_uptr_t p_next_manip;
+#ifdef FM_CAPWAP_SUPPORT
+#error "FM_CAPWAP_SUPPORT feature not supported!"
+ bool frag_or_reasm;
+ ioc_fm_pcd_manip_frag_or_reasm_params_t frag_or_reasm_params;
+#endif /* FM_CAPWAP_SUPPORT */
+ compat_uptr_t id;
+} ioc_compat_fm_pcd_manip_params_t;
+
+#if (DPAA_VERSION >= 11)
+typedef struct ioc_compat_fm_pcd_frm_replic_group_params_t {
+ uint8_t max_num_of_entries;
+ uint8_t num_of_entries;
+ ioc_compat_fm_pcd_cc_next_engine_params_t
+ next_engine_params[IOC_FM_PCD_FRM_REPLIC_MAX_NUM_OF_ENTRIES];
+ compat_uptr_t id;
+} ioc_compat_fm_pcd_frm_replic_group_params_t;
+
+typedef struct ioc_compat_fm_pcd_frm_replic_member_t {
+ compat_uptr_t h_replic_group;
+ uint16_t member_index;
+} ioc_compat_fm_pcd_frm_replic_member_t;
+
+typedef struct ioc_compat_fm_pcd_frm_replic_member_params_t {
+ ioc_compat_fm_pcd_frm_replic_member_t member;
+ ioc_compat_fm_pcd_cc_next_engine_params_t next_engine_params;
+} ioc_compat_fm_pcd_frm_replic_member_params_t;
+
+typedef struct ioc_compat_fm_vsp_params_t {
+ compat_uptr_t p_fm; /**< A handle to the FM object this VSP related to */
+ ioc_fm_ext_pools ext_buf_pools; /**< Which external buffer pools are used
+ (up to FM_PORT_MAX_NUM_OF_EXT_POOLS), and their sizes.
+ parameter associated with Rx / OP port */
+ uint16_t liodn_offset; /**< VSP's LIODN offset */
+ struct {
+ ioc_fm_port_type port_type; /**< Port type */
+ uint8_t port_id; /**< Port Id - relative to type */
+ } port_params;
+ uint8_t relative_profile_id; /**< VSP Id - relative to VSP's range
+ defined in relevant FM object */
+ compat_uptr_t id; /**< return value */
+} ioc_compat_fm_vsp_params_t;
+
+typedef struct ioc_compat_fm_buf_pool_depletion_params_t {
+ compat_uptr_t p_fm_vsp;
+ ioc_fm_buf_pool_depletion_t fm_buf_pool_depletion;
+} ioc_compat_fm_buf_pool_depletion_params_t;
+
+typedef struct ioc_compat_fm_buffer_prefix_content_params_t {
+ compat_uptr_t p_fm_vsp;
+ ioc_fm_buffer_prefix_content_t fm_buffer_prefix_content;
+} ioc_compat_fm_buffer_prefix_content_params_t;
+
+typedef struct ioc_compat_fm_vsp_config_no_sg_params_t {
+ compat_uptr_t p_fm_vsp;
+ bool no_sg;
+} ioc_compat_fm_vsp_config_no_sg_params_t;
+
+typedef struct ioc_compat_fm_vsp_prs_result_params_t {
+ compat_uptr_t p_fm_vsp;
+ compat_uptr_t p_data;
+} ioc_compat_fm_vsp_prs_result_params_t;
+#endif /* (DPAA_VERSION >= 11) */
+
+typedef struct ioc_compat_fm_ctrl_mon_counters_params_t {
+ uint8_t fm_ctrl_index;
+ compat_uptr_t p_mon;
+} ioc_compat_fm_ctrl_mon_counters_params_t;
+
+typedef struct ioc_compat_fm_pcd_cc_tbl_get_miss_params_t {
+ compat_uptr_t id;
+ ioc_fm_pcd_cc_key_statistics_t miss_statistics;
+} ioc_compat_fm_pcd_cc_tbl_get_miss_params_t;
+
+
+/* } pcd compat structures */
+
+void compat_obj_delete(
+ ioc_compat_fm_obj_t *compat_id,
+ ioc_fm_obj_t *id);
+
+/* pcd compat functions { */
+void compat_copy_fm_pcd_plcr_profile(
+ ioc_compat_fm_pcd_plcr_profile_params_t *compat_param,
+ ioc_fm_pcd_plcr_profile_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_cc_key(
+ ioc_compat_fm_pcd_cc_key_params_t *compat_param,
+ ioc_fm_pcd_cc_key_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_cc_node_modify_key_and_next_engine(
+ ioc_compat_fm_pcd_cc_node_modify_key_and_next_engine_params_t *compat_param,
+ ioc_fm_pcd_cc_node_modify_key_and_next_engine_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_cc_node_modify_next_engine(
+ ioc_compat_fm_pcd_cc_node_modify_next_engine_params_t *compat_param,
+ ioc_fm_pcd_cc_node_modify_next_engine_params_t *param,
+ uint8_t compat);
+
+void compat_fm_pcd_cc_tree_modify_next_engine(
+ ioc_compat_fm_pcd_cc_tree_modify_next_engine_params_t *compat_param,
+ ioc_fm_pcd_cc_tree_modify_next_engine_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_hash_table(
+ ioc_compat_fm_pcd_hash_table_params_t *compat_param,
+ ioc_fm_pcd_hash_table_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_cc_grp(
+ ioc_compat_fm_pcd_cc_grp_params_t *compat_param,
+ ioc_fm_pcd_cc_grp_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_cc_tree(
+ ioc_compat_fm_pcd_cc_tree_params_t *compat_param,
+ ioc_fm_pcd_cc_tree_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_cc_tbl_get_miss(
+ ioc_compat_fm_pcd_cc_tbl_get_miss_params_t *compat_param,
+ ioc_fm_pcd_cc_tbl_get_miss_params_t *param,
+ uint8_t compat);
+
+void compat_fm_pcd_prs_sw(
+ ioc_compat_fm_pcd_prs_sw_params_t *compat_param,
+ ioc_fm_pcd_prs_sw_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_kg_scheme(
+ ioc_compat_fm_pcd_kg_scheme_params_t *compat_param,
+ ioc_fm_pcd_kg_scheme_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_kg_scheme_select(
+ ioc_compat_fm_pcd_kg_scheme_select_t *compat_param,
+ ioc_fm_pcd_kg_scheme_select_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_kg_schemes_params(
+ ioc_compat_fm_pcd_port_schemes_params_t *compat_param,
+ ioc_fm_pcd_port_schemes_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_port_pcd_kg(
+ ioc_compat_fm_port_pcd_kg_params_t *compat_param,
+ ioc_fm_port_pcd_kg_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_port_pcd(
+ ioc_compat_fm_port_pcd_params_t *compat_param,
+ ioc_fm_port_pcd_params_t *param,
+ uint8_t compat);
+
+#if (DPAA_VERSION >= 11)
+void compat_copy_fm_port_vsp_alloc_params(
+ ioc_compat_fm_port_vsp_alloc_params_t *compat_param,
+ ioc_fm_port_vsp_alloc_params_t *param,
+ uint8_t compat);
+#endif /* (DPAA_VERSION >= 11) */
+
+void compat_copy_fm_pcd_net_env(
+ ioc_compat_fm_pcd_net_env_params_t *compat_param,
+ ioc_fm_pcd_net_env_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_cc_node_modify_key(
+ ioc_compat_fm_pcd_cc_node_modify_key_params_t *compat_param,
+ ioc_fm_pcd_cc_node_modify_key_params_t *param,
+ uint8_t compat);
+
+void compat_copy_keys(
+ ioc_compat_keys_params_t *compat_param,
+ ioc_keys_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_cc_node(
+ ioc_compat_fm_pcd_cc_node_params_t *compat_param,
+ ioc_fm_pcd_cc_node_params_t *param,
+ uint8_t compat);
+
+void compat_fm_pcd_manip_set_node(
+ ioc_compat_fm_pcd_manip_params_t *compat_param,
+ ioc_fm_pcd_manip_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_port_pcd_modify_tree(
+ ioc_compat_fm_obj_t *compat_id,
+ ioc_fm_obj_t *id,
+ uint8_t compat);
+
+#if (DPAA_VERSION >= 11)
+void compat_copy_fm_pcd_frm_replic_group_params(
+ ioc_compat_fm_pcd_frm_replic_group_params_t *compat_param,
+ ioc_fm_pcd_frm_replic_group_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_frm_replic_member(
+ ioc_compat_fm_pcd_frm_replic_member_t *compat_param,
+ ioc_fm_pcd_frm_replic_member_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_pcd_frm_replic_member_params(
+ ioc_compat_fm_pcd_frm_replic_member_params_t *compat_param,
+ ioc_fm_pcd_frm_replic_member_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_vsp_params(
+ ioc_compat_fm_vsp_params_t *compat_param,
+ ioc_fm_vsp_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_buf_pool_depletion_params(
+ ioc_compat_fm_buf_pool_depletion_params_t *compat_param,
+ ioc_fm_buf_pool_depletion_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_buffer_prefix_content_params(
+ ioc_compat_fm_buffer_prefix_content_params_t *compat_param,
+ ioc_fm_buffer_prefix_content_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_vsp_config_no_sg_params(
+ ioc_compat_fm_vsp_config_no_sg_params_t *compat_param,
+ ioc_fm_vsp_config_no_sg_params_t *param,
+ uint8_t compat);
+
+void compat_copy_fm_vsp_prs_result_params(
+ ioc_compat_fm_vsp_prs_result_params_t *compat_param,
+ ioc_fm_vsp_prs_result_params_t *param,
+ uint8_t compat);
+#endif /* (DPAA_VERSION >= 11) */
+/* } pcd compat functions */
+#endif
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources.c
new file mode 100644
index 0000000..b27016f
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources.c
@@ -0,0 +1,1189 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ @File lnxwrp_resources.c
+
+ @Description FMD wrapper resource allocation functions.
+
+*/
+#if !defined(FMAN_RESOURCES_UNIT_TEST)
+
+#include <linux/version.h>
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+#define MODVERSIONS
+#endif
+#ifdef MODVERSIONS
+#include <config/modversions.h>
+#endif /* MODVERSIONS */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/skbuff.h>
+
+#endif /*#if !defined(FMAN_RESOURCES_UNIT_TEST)*/
+
+#include "lnxwrp_resources.h"
+
+#if !defined(FMAN_RESOURCES_UNIT_TEST)
+static struct device_node *match_mac_to_dpaa_port(struct device_node
+ *enet_mac_node)
+{
+ struct device_node *dpaa_node = NULL;
+ struct device_node *dpaa_itf = NULL;
+
+ /* find DPAA node starting from root */
+ dpaa_node = of_find_compatible_node(NULL, NULL, "fsl,dpaa");
+ if (dpaa_node) {
+ /* for all dpaa ports check which one refers this mac node. */
+ for_each_child_of_node(dpaa_node, dpaa_itf) {
+ struct device_node *by_handle_enet_mac_node = NULL;
+ const phandle *phandle_prop = NULL;
+ int lenp = 0;
+
+ phandle_prop =
+ (typeof(phandle_prop))
+ of_get_property(dpaa_itf, "fsl,fman-mac",
+ &lenp);
+ if (phandle_prop == NULL)
+ continue;
+
+ if (WARN_ON(lenp != sizeof(phandle)))
+ return NULL;
+
+ by_handle_enet_mac_node =
+ of_find_node_by_phandle(*phandle_prop);
+ if (unlikely(by_handle_enet_mac_node == NULL))
+ return NULL;
+
+ /* check */
+ if (by_handle_enet_mac_node == enet_mac_node) {
+ of_node_put(by_handle_enet_mac_node);
+ return dpaa_itf;
+ }
+
+ of_node_put(by_handle_enet_mac_node);
+ }
+ of_node_put(dpaa_node);
+ }
+
+ return NULL;
+}
+
+static struct device_node *match_fman_port_to_mac(struct device_node *fm_node,
+ struct device_node
+ *fm_port_node)
+{
+ struct device_node *fm_node_idx = NULL;
+
+ /* for all enet nodes (macs) check which one refers this FMan port. */
+ for_each_child_of_node(fm_node, fm_node_idx) {
+ if (of_device_is_compatible(fm_node_idx, "fsl,fman-1g-mac") ||
+ of_device_is_compatible(fm_node_idx, "fsl,fman-10g-mac") ||
+ of_device_is_compatible(fm_node_idx, "fsl,fman-memac")) {
+ struct device_node *fman_port_node_rx = NULL;
+ struct device_node *fman_port_node_tx = NULL;
+ /* RX is first */
+ fman_port_node_rx = of_parse_phandle(fm_node_idx,
+ "fsl,port-handles", 0);
+ if (unlikely(fman_port_node_rx == NULL))
+ continue;
+ /* TX is second */
+ fman_port_node_tx = of_parse_phandle(fm_node_idx,
+ "fsl,port-handles", 1);
+ if (unlikely(fman_port_node_tx == NULL)) {
+ of_node_put(fman_port_node_rx);
+ continue;
+ }
+
+ /* check */
+ if (fman_port_node_rx == fm_port_node
+ || fman_port_node_tx == fm_port_node) {
+ of_node_put(fman_port_node_rx);
+ of_node_put(fman_port_node_tx);
+ return fm_node_idx;
+ }
+
+ of_node_put(fman_port_node_rx);
+ of_node_put(fman_port_node_tx);
+ }
+ }
+
+ return NULL;
+}
+
+static bool is_fman_port_active(struct device_node *fm_node,
+ struct device_node *fm_port_node)
+{
+ struct device_node *enet_mac_node = NULL;
+ struct device_node *itf_node = NULL;
+
+ /* Which MAC node refers to this FMan port. */
+ enet_mac_node = match_fman_port_to_mac(fm_node, fm_port_node);
+
+ if (unlikely(enet_mac_node == NULL))
+ return false;
+
+ /* Which dpaa port node refers this MAC node. */
+ itf_node = match_mac_to_dpaa_port(enet_mac_node);
+ of_node_put(enet_mac_node);
+
+ if (unlikely(!itf_node))
+ return false;
+
+ /* check if itf (DPAA ports) is available.
+ * if available, means that the FMan port is
+ * also available - return true
+ */
+ if (!of_device_is_available(itf_node)) {
+ of_node_put(itf_node);
+ return false;
+ }
+ of_node_put(itf_node);
+
+ return true;
+}
+
+int fm_set_active_fman_ports(struct platform_device *of_dev,
+ t_LnxWrpFmDev *p_LnxWrpFmDev)
+{
+ struct device_node *fm_node = NULL;
+ struct device_node *fm_port_node = NULL;
+
+ memset(&p_LnxWrpFmDev->fm_active_ports_info, 0,
+ sizeof(struct fm_active_ports));
+
+ /* get FMan node */
+ fm_node = of_dev->dev.of_node;
+
+ /* for all ports which belong to this FMan, check if they are active.
+ * If active, set their parameters. */
+ for_each_child_of_node(fm_node, fm_port_node) {
+
+ if (!of_device_is_available(fm_port_node))
+ continue;
+
+ /* OH FMan ports */
+ if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-port-oh")) {
+ p_LnxWrpFmDev->fm_active_ports_info.num_oh_ports++;
+ continue;
+ }
+
+ if (!is_fman_port_active(fm_node, fm_port_node))
+ continue;
+
+ /* 10g TX FMan ports */
+ if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-port-10g-tx"))
+ p_LnxWrpFmDev->fm_active_ports_info.num_tx10_ports++;
+
+ /* 10g RX FMan ports */
+ else if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-port-10g-rx"))
+ p_LnxWrpFmDev->fm_active_ports_info.num_rx10_ports++;
+
+ /* 1G TX FMan ports */
+ else if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-port-1g-tx"))
+ p_LnxWrpFmDev->fm_active_ports_info.num_tx_ports++;
+
+ /* 1G RX FMan ports */
+ else if (of_device_is_compatible(fm_port_node,
+ "fsl,fman-port-1g-rx"))
+ p_LnxWrpFmDev->fm_active_ports_info.num_rx_ports++;
+ }
+
+ /* If performance is needed no oh port is probed
+ * except the one used for host command. */
+#if defined(CONFIG_FMAN_DISABLE_OH_TO_REUSE_RESOURCES)
+ if (p_LnxWrpFmDev->fm_active_ports_info.num_oh_ports)
+ p_LnxWrpFmDev->fm_active_ports_info.num_oh_ports = 1;
+
+ printk(KERN_WARNING "FMAN(%u)-Performance mode - no OH support...\n",
+ p_LnxWrpFmDev->id);
+#endif
+
+ return 0;
+}
+#endif /*!defined(FMAN_RESOURCES_UNIT_TEST)*/
+
+/* BPOOL size is constant and equal w/ DPA_BP_SIZE */
+static uint32_t get_largest_buf_size(uint32_t max_rx_frame_size, uint32_t buf_size)
+{
+ uint32_t priv_data_size = 16; /* DPA_PRIV_DATA_SIZE */
+ uint32_t hash_results_size = 16; /* DPA_HASH_RESULTS_SIZE */
+ uint32_t parse_results_size =
+ sizeof(t_FmPrsResult); /* DPA_PARSE_RESULTS_SIZE */
+ uint32_t bp_head = priv_data_size + hash_results_size +
+ parse_results_size +
+ fm_get_rx_extra_headroom(); /* DPA_BP_HEAD */
+ uint32_t bp_size = bp_head + max_rx_frame_size
+ + NET_IP_ALIGN; /* DPA_BP_SIZE */
+
+ return CEIL_DIV(bp_size, buf_size);
+}
+
+/* Calculate the fifosize based on MURAM allocation, number of ports, dpde
+ value and s/g software support (! Kernel does not suport s/g).
+
+ Algorithm summary:
+ - Calculate the the minimum fifosize required for every type of port
+ (TX,RX for 1G, 2.5G and 10G).
+ - Set TX the minimum fifosize required.
+ - Distribute the remaining buffers (after all TX were set) to RX ports
+ based on:
+ 1G RX = Remaining_buffers * 1/(1+2.5+10)
+ 2.5G RX = Remaining_buffers * 2.5/(1+2.5+10)
+ 10G RX = Remaining_buffers * 10/(1+2.5+10)
+ - if the RX is smaller than the minimum required, then set the minimum
+ required
+ - In the end distribuite the leftovers if there are any (due to
+ unprecise calculus) or if over allocation cat some buffers from all RX
+ ports w/o pass over minimum required treshold, but if there must be
+ pass the treshold in order to cat the over allocation ,then this
+ configuration can not be set - KERN_ALERT.
+*/
+int fm_precalculate_fifosizes(t_LnxWrpFmDev *p_LnxWrpFmDev, int muram_fifo_size)
+{
+
+ /* input parameters */
+ struct fm_active_ports *fm_active_ports_info = NULL;
+ int num_1g_ports = 0;
+ int num_2g5_ports = 0;
+ int num_10g_ports = 0;
+ int num_oh_ports = 0;
+
+ /* output parameters */
+ struct fm_resource_settings *fm_resource_settings_info = NULL;
+ int oh_buff = 0;
+ int tx_1g_bufs = 0, rx_1g_bufs = 0;
+ int tx_2g5_bufs = 0, rx_2g5_bufs = 0;
+ int tx_10g_bufs = 0, rx_10g_bufs = 0;
+ int err = 0;
+
+ /* throughput parameters: divide it by 10 when used */
+ int gb1g = 10, gb2g5 = 25, gb10g = 100, gb_sum = 0;
+
+ /* buffers parameters */
+ int buf_size = 0x100; /* Buffer unit size */
+ int total_no_buffers = 0; /* Calculus based on MURAM size for
+ fifos and buf. unit size */
+
+ int shared_ext_buff = 0; /* External buffers allocated - LLD
+ boundaries:DEFAULT_PORT_extraSizeOfFifo */
+
+ int min_tx_1g_2g5_bufs = 0; /* minimum TX1g buffers required
+ (see refman.) */
+ int min_tx_10g_bufs = 0; /* minimum TX10g buffers required
+ (see refman.) */
+ int min_rx_bufs = 0; /* minimum RX buffers required (see refman.) */
+
+ /* Buffer sizes calculus */
+ int max_frame_size = fm_get_max_frm();
+ int remaining_bufs = 0;
+ int rx_1g_bufs_ceil = 0, rx_2g5_bufs_ceil = 0, rx_10g_bufs_ceil = 0;
+ int rx_2g5_max_bufs = 0, rx_10g_max_bufs = 0;
+ int rx_1g_used = 0, rx_1g_2g5_used = 0, rx_1g_10g_used =0,
+ rx_2g5_used = 0, rx_2g5_10g_used = 0, rx_1g_2g5_10g_used = 0;
+
+ /* overflow checking */
+ int tot_rx_buffs, tot_tx_buffs, tot_oh_buffs, tot_used_buffs,
+ leftovers = 0;
+ int overflow = 0;
+ bool loop = false;
+
+ /* check input parameters correctness */
+ ASSERT_COND(p_LnxWrpFmDev != NULL);
+ fm_active_ports_info = &p_LnxWrpFmDev->fm_active_ports_info;
+ fm_resource_settings_info = &p_LnxWrpFmDev->fm_resource_settings_info;
+ ASSERT_COND(fm_active_ports_info != NULL);
+ ASSERT_COND(fm_resource_settings_info != NULL);
+ ASSERT_COND(fm_active_ports_info->num_tx_ports ==
+ fm_active_ports_info->num_rx_ports);
+ ASSERT_COND(fm_active_ports_info->num_tx25_ports ==
+ fm_active_ports_info->num_tx25_ports);
+ ASSERT_COND(fm_active_ports_info->num_tx10_ports ==
+ fm_active_ports_info->num_tx10_ports);
+ ASSERT_COND(max_frame_size != 0);
+ ASSERT_COND(muram_fifo_size != 0);
+
+ /* set input parameters */
+ num_1g_ports = fm_active_ports_info->num_tx_ports;
+ num_2g5_ports = fm_active_ports_info->num_tx25_ports;
+ num_10g_ports = fm_active_ports_info->num_tx10_ports;
+ num_oh_ports = fm_active_ports_info->num_oh_ports;
+
+ /* throughput calculus */
+ gb_sum = gb1g * num_1g_ports + gb2g5 * num_2g5_ports
+ + gb10g * num_10g_ports; /* divide it by 10 */
+
+ /* Base buffer calculus */
+ oh_buff = 8;
+ total_no_buffers = muram_fifo_size / buf_size;
+
+ min_tx_1g_2g5_bufs = CEIL_DIV(max_frame_size, buf_size)
+ + DPDE_1G + 3 + 1; /* +1 to handle Jumbo Frames */
+ min_tx_10g_bufs = CEIL_DIV(max_frame_size, buf_size)
+ + DPDE_10G + 3 + 1; /* +1 to handle Jumbo Frames */
+
+ {
+/*
+ * On P1023RDS FM_FIFO_ALLOCATION_ALG is enabled allowing a smaller Rx FIFO
+ * on hardware major rev 4. If the Rx FIFO is smaller than the size of the
+ * buffer in the buffer pool SG frames will be received
+ */
+#if defined(FM_FIFO_ALLOCATION_ALG) && \
+ !defined(FMAN_RESOURCES_UNIT_TEST)
+ uint8_t fm_rev_major = 0;
+ fm_rev_major = (uint8_t) ((*
+ ((volatile uint32_t *)
+ UINT_TO_PTR(p_LnxWrpFmDev->fmBaseAddr +
+ 0x000c30c4)) & 0xff00) >> 8);
+
+ if (fm_rev_major == 4)
+ min_rx_bufs = 8;
+ else
+#endif
+ min_rx_bufs = get_largest_buf_size(max_frame_size,
+ buf_size) + 7;
+ }
+
+#ifdef CONFIG_FMAN_P1023
+ shared_ext_buff = 0;
+#else
+ /* changing these might reduce performance */
+ shared_ext_buff = num_10g_ports ? 32 : 16; /* LLD boundaries:
+ DEFAULT_PORT_extraNumOfFifoBufs */
+#endif
+
+ /* TX ports will have minimum required buffers
+ Calculus of the remaining buffers for all RX ports */
+ tx_1g_bufs = num_1g_ports ? min_tx_1g_2g5_bufs : 0;
+ tx_2g5_bufs = num_2g5_ports ? min_tx_1g_2g5_bufs : 0;
+ tx_10g_bufs = num_10g_ports ? min_tx_10g_bufs : 0;
+
+ remaining_bufs = total_no_buffers -
+ oh_buff * num_oh_ports -
+ num_1g_ports * min_tx_1g_2g5_bufs -
+ num_2g5_ports * min_tx_1g_2g5_bufs -
+ num_10g_ports * min_tx_10g_bufs - shared_ext_buff;
+
+ if (remaining_bufs < 0) {
+ printk(KERN_ALERT
+ "\nThis configuration will not work due to low number of"
+ " buffers (%u buffers)...\n",
+ total_no_buffers);
+ err = -1;
+ goto precalculated_fifosize_out;
+ }
+
+ /* Per port buffer size calculus
+ . for TX ports give always minimum required
+ . for RX ports give whatever left scaled per port type */
+ /* ------------------------------------------------------- */
+ if (num_1g_ports) {
+ rx_1g_bufs_ceil =
+ (gb_sum /
+ 10) ? CEIL_DIV(((remaining_bufs * gb1g) / 10),
+ (gb_sum / 10)) : 0;
+ rx_1g_bufs = MAX(min_rx_bufs, rx_1g_bufs_ceil);
+ rx_1g_used = rx_1g_bufs - rx_1g_bufs_ceil; /* always >= 0 */
+ /* distribute to 2.5g and 10g ports */
+ rx_1g_2g5_used =
+ (num_2g5_ports +
+ num_10g_ports) ? CEIL_DIV(rx_1g_used * num_1g_ports *
+ num_2g5_ports,
+ num_2g5_ports +
+ num_10g_ports) : 0;
+ rx_1g_10g_used =
+ (num_2g5_ports +
+ num_10g_ports) ? CEIL_DIV(rx_1g_used * num_1g_ports *
+ num_10g_ports,
+ num_2g5_ports +
+ num_10g_ports) : 0;
+ }
+
+ if (num_2g5_ports) {
+ rx_2g5_bufs_ceil =
+ (gb_sum /
+ 10) ? CEIL_DIV(((remaining_bufs * gb2g5) / 10),
+ (gb_sum / 10)) : 0;
+ rx_2g5_max_bufs = MAX(min_rx_bufs, rx_2g5_bufs_ceil);
+ rx_2g5_bufs =
+ MAX(min_rx_bufs, rx_2g5_max_bufs - rx_1g_2g5_used);
+ rx_2g5_used = rx_2g5_bufs - rx_2g5_bufs_ceil; /* always >= 0 */
+ /* distribute to 10g ports */
+ rx_2g5_10g_used =
+ num_10g_ports ? CEIL_DIV(rx_2g5_used * num_2g5_ports,
+ num_10g_ports) : 0;
+ }
+
+ if (num_10g_ports) {
+ rx_10g_bufs_ceil =
+ (gb_sum /
+ 10) ? CEIL_DIV(((remaining_bufs * gb10g) / 10),
+ (gb_sum / 10)) : 0;
+ rx_10g_max_bufs = MAX(min_rx_bufs, rx_10g_bufs_ceil);
+ /* keep count of all distribution */
+ rx_1g_2g5_10g_used = rx_1g_10g_used + rx_2g5_10g_used;
+ rx_10g_bufs =
+ MAX(min_rx_bufs,
+ rx_10g_max_bufs - rx_1g_2g5_10g_used);
+ }
+
+ /* overflow-leftover calculus */
+ tot_rx_buffs = rx_1g_bufs * num_1g_ports +
+ rx_2g5_bufs * num_2g5_ports + rx_10g_bufs * num_10g_ports;
+ tot_tx_buffs = tx_1g_bufs * num_1g_ports +
+ tx_2g5_bufs * num_2g5_ports + tx_10g_bufs * num_10g_ports;
+ tot_oh_buffs = oh_buff * num_oh_ports;
+ tot_used_buffs =
+ tot_oh_buffs + tot_tx_buffs + tot_rx_buffs + shared_ext_buff;
+
+ overflow = tot_used_buffs - total_no_buffers;
+ /* used more than available */
+ if (overflow > 0) {
+ loop = true;
+ while (overflow > 0 && loop) {
+ loop = false;
+ if (overflow && num_10g_ports
+ && rx_10g_bufs > min_rx_bufs) {
+ rx_10g_bufs--;
+ overflow -= num_10g_ports;
+ loop = true;
+ }
+ if (overflow && num_2g5_ports
+ && rx_2g5_bufs > min_rx_bufs) {
+ rx_2g5_bufs--;
+ overflow -= num_2g5_ports;
+ loop = true;
+ }
+ if (overflow && num_1g_ports
+ && rx_1g_bufs > min_rx_bufs) {
+ rx_1g_bufs--;
+ overflow -= num_1g_ports;
+ loop = true;
+ }
+ }
+
+ if (overflow > 0) {
+ printk(KERN_ALERT
+ "This configuration will not work due to over"
+ " buffer allocation (%d buffers)...\n",
+ overflow);
+ err = -1;
+ goto precalculated_fifosize_out;
+ }
+ }
+ /* left a few buffers */
+ else if (overflow < 0) {
+ leftovers = total_no_buffers - tot_used_buffs;
+ loop = true;
+ while (leftovers > 0 && loop) {
+ loop = false;
+ if (leftovers && num_1g_ports) {
+ rx_1g_bufs++;
+ leftovers -= num_1g_ports;
+ loop = true;
+ }
+
+ if (leftovers && num_2g5_ports) {
+ rx_2g5_bufs++;
+ leftovers -= num_2g5_ports;
+ loop = true;
+ }
+
+ if (leftovers && num_10g_ports) {
+ rx_10g_bufs++;
+ leftovers -= num_10g_ports;
+ loop = true;
+ }
+ }
+ }
+
+ /* set fifosizes for this FMan ports */
+ fm_resource_settings_info->tx1g_num_buffers = tx_1g_bufs;
+ fm_resource_settings_info->rx1g_num_buffers = rx_1g_bufs;
+ fm_resource_settings_info->tx2g5_num_buffers = tx_2g5_bufs;
+ fm_resource_settings_info->rx2g5_num_buffers = rx_2g5_bufs;
+ fm_resource_settings_info->tx10g_num_buffers = tx_10g_bufs;
+ fm_resource_settings_info->rx10g_num_buffers = rx_10g_bufs;
+ fm_resource_settings_info->oh_num_buffers = oh_buff;
+ fm_resource_settings_info->shared_ext_buffers = shared_ext_buff;
+
+precalculated_fifosize_out:
+ printk(KERN_INFO " FMAN(%u) Fifo size settings:\n",
+ p_LnxWrpFmDev->id);
+ printk(KERN_INFO " - Total buffers available(%u - 256B/buffer)\n",
+ total_no_buffers);
+ printk(KERN_INFO " - Total throughput(%uGbps)\n", (gb_sum / 10));
+ printk(KERN_INFO " - Max frame size(%uB)\n", max_frame_size);
+ if (num_1g_ports) {
+ printk(KERN_INFO
+ " - 1G ports TX %u(%u bufs set (min: %u))\n",
+ num_1g_ports, tx_1g_bufs, min_tx_1g_2g5_bufs);
+ printk(KERN_INFO
+ " - 1G ports RX %u(%u bufs set (min: %u))\n",
+ num_1g_ports, rx_1g_bufs, min_rx_bufs);
+ }
+ if (num_2g5_ports) {
+ printk(KERN_INFO
+ " - 2.5G ports TX %u(%u bufs set (min: %u))\n",
+ num_2g5_ports, tx_2g5_bufs, min_tx_1g_2g5_bufs);
+ printk(KERN_INFO
+ " - 2.5G ports RX %u(%u bufs set (min: %u))\n",
+ num_2g5_ports, rx_2g5_bufs, min_rx_bufs);
+ }
+ if (num_10g_ports) {
+ printk(KERN_INFO
+ " - 10G ports TX %u(%u bufs set (min: %u))\n",
+ num_10g_ports, tx_10g_bufs, min_tx_10g_bufs);
+ printk(KERN_INFO
+ " - 10G ports RX %u(%u bufs set (min: %u))\n",
+ num_10g_ports, rx_10g_bufs, min_rx_bufs);
+ }
+ if (num_oh_ports)
+ printk(KERN_INFO " - OH-HC ports %u(%u)\n", num_oh_ports,
+ oh_buff);
+ printk(KERN_INFO " - Shared extra buffers(%u)\n", shared_ext_buff);
+
+ return err;
+}
+
+#if !defined(FMAN_RESOURCES_UNIT_TEST)
+int fm_config_precalculate_fifosize(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev =
+ (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev;
+ struct fm_resource_settings *fm_resource_settings_info = NULL;
+ struct fm_active_ports *fm_active_ports_info = NULL;
+ t_FmPortRsrc portRsrc;
+ t_Error errCode;
+ uint32_t buf_size = 0x100;
+
+ ASSERT_COND(p_LnxWrpFmDev != NULL);
+ fm_resource_settings_info = &p_LnxWrpFmDev->fm_resource_settings_info;
+ fm_active_ports_info = &p_LnxWrpFmDev->fm_active_ports_info;
+
+ memset(&portRsrc, 0, sizeof(t_FmPortRsrc));
+
+/* IF 1G PORT */
+ if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_TX) {
+ portRsrc.num =
+ fm_resource_settings_info->tx1g_num_buffers * buf_size;
+ portRsrc.extra = 0;
+ } else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_RX) {
+ portRsrc.num =
+ fm_resource_settings_info->rx1g_num_buffers * buf_size;
+ portRsrc.extra =
+ fm_resource_settings_info->shared_ext_buffers *
+ buf_size;
+ }
+/* IF 2.5G PORT */
+ /* TODO: Not supported by LLD yet. */
+
+/* IF 10G PORT */
+ else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_TX_10G) {
+ portRsrc.num =
+ fm_resource_settings_info->tx10g_num_buffers *
+ buf_size;
+ portRsrc.extra = 0;
+ } else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_RX_10G) {
+ portRsrc.num =
+ fm_resource_settings_info->rx10g_num_buffers *
+ buf_size;
+ portRsrc.extra =
+ fm_resource_settings_info->shared_ext_buffers *
+ buf_size;
+ } else { /* IF OH PORT */
+ portRsrc.num =
+ fm_resource_settings_info->oh_num_buffers * buf_size;
+ portRsrc.extra = 0;
+ }
+
+ errCode = FM_PORT_ConfigSizeOfFifo(p_LnxWrpFmPortDev->h_Dev, &portRsrc);
+ if (errCode != E_OK) {
+ printk(KERN_WARNING
+ "FM_PORT_SetSizeOfFifo failed (errCode:0x%2x)",
+ errCode);
+ return -EIO;
+ }
+
+ return 0;
+}
+#endif /*if !defined(FMAN_RESOURCES_UNIT_TEST)*/
+
+/* Compute FMan open DMA based on total number of open DMAs and
+ * number of available FMan ports.
+ *
+ * By default 10g ports are set to input parameters. The other ports
+ * tries to keep the proportion rx=2tx open DMAs or thresholds.
+ *
+ * If leftovers, then those will be set as shared.
+ *
+ * If after computing overflow appears, then it decrements open DMA
+ * for all ports w/o cross the thresholds. If the thresholds are meet
+ * and is still overflow, then it returns error.
+ */
+int fm_precalculate_open_dma(t_LnxWrpFmDev *p_LnxWrpFmDev,
+ int max_fm_open_dma,
+ int default_tx_10g_dmas,
+ int default_rx_10g_dmas,
+ int min_tx_10g_treshold, int min_rx_10g_treshold)
+{
+ /* input parameters */
+ struct fm_active_ports *fm_active_ports_info = NULL;
+ int num_1g_ports = 0;
+ int num_2g5_ports = 0;
+ int num_10g_ports = 0;
+ int num_oh_ports = 0;
+
+ /* output parameters */
+ struct fm_resource_settings *fm_resource_settings_info = NULL;
+ int tx_1g_dmas = 0, rx_1g_dmas = 0;
+ int tx_2g5_dmas = 0, rx_2g5_dmas = 0;
+ int tx_10g_dmas = 0, rx_10g_dmas = 0;
+ int oh_dmas = 0;
+ int shared_ext_open_dma = 0;
+ int err = 0;
+
+ /* open dma calculus */
+ int remaing_dmas = 0;
+ int rx_tx_raport =
+ FM_OPENDMA_RX_TX_RAPORT; /* RX = FM_OPENDMA_RX_TX_RAPORT *TX */
+ int min_tx_1_2g5_treshold = 1;
+ int min_rx_1_2g5_treshold = 1;
+ int max_open_dma_treshold = 16; /* LLD: MAX_NUM_OF_DMAS */
+ int max_ext_open_dma_treshold = 8; /* LLD: MAX_NUM_OF_EXTRA_DMAS */
+
+ int open_dmas_computed = 0;
+ int weighted_remaining_ports = 0;
+ int overflow = 0;
+ bool re_loop = false;
+
+ /* check input parameters correctness */
+ ASSERT_COND(p_LnxWrpFmDev != NULL);
+ fm_active_ports_info = &p_LnxWrpFmDev->fm_active_ports_info;
+ fm_resource_settings_info = &p_LnxWrpFmDev->fm_resource_settings_info;
+ ASSERT_COND(fm_active_ports_info != NULL);
+ ASSERT_COND(fm_resource_settings_info != NULL);
+ ASSERT_COND(fm_active_ports_info->num_tx_ports ==
+ fm_active_ports_info->num_rx_ports);
+ ASSERT_COND(fm_active_ports_info->num_tx25_ports ==
+ fm_active_ports_info->num_tx25_ports);
+ ASSERT_COND(fm_active_ports_info->num_tx10_ports ==
+ fm_active_ports_info->num_tx10_ports);
+ ASSERT_COND(min_tx_10g_treshold <= max_open_dma_treshold);
+ ASSERT_COND(min_tx_10g_treshold <= max_open_dma_treshold);
+
+ /* set input parameters */
+ num_1g_ports = fm_active_ports_info->num_tx_ports;
+ num_2g5_ports = fm_active_ports_info->num_tx25_ports;
+ num_10g_ports = fm_active_ports_info->num_tx10_ports;
+ num_oh_ports = fm_active_ports_info->num_oh_ports;
+
+ /* compute open DMAs per port */
+ /* ------------------------------------------------------- */
+ if (num_10g_ports) {
+ tx_10g_dmas = default_tx_10g_dmas; /* per 10G TX port */
+ rx_10g_dmas = default_rx_10g_dmas; /* per 10G RX port */
+ }
+ if (num_oh_ports)
+ oh_dmas = 1; /* per OH port */
+
+ /* should this be null? or LLD:
+ DEFAULT_PORT_extraNumOfOpenDmas:10g-8,else 1 */
+ shared_ext_open_dma = 0;
+
+ /* based on total number of ports set open DMAs for all other ports */
+ remaing_dmas = max_fm_open_dma -
+ (oh_dmas * num_oh_ports) -
+ (tx_10g_dmas * num_10g_ports + rx_10g_dmas * num_10g_ports) -
+ shared_ext_open_dma;
+
+ if (remaing_dmas < 0) {
+ printk(KERN_ALERT
+ "This configuration will not work due to low number"
+ " of open dmas (%u open dmas)...\n",
+ max_fm_open_dma);
+ err = -1;
+ goto precalculated_open_dma_out;
+ }
+
+ weighted_remaining_ports =
+ /*tx */ num_1g_ports * rx_tx_raport + /*rx */ num_1g_ports +
+ /*tx */ num_2g5_ports * rx_tx_raport + /*rx */ num_2g5_ports;
+
+ /* compute the other ports */
+ if (num_1g_ports) {
+ tx_1g_dmas =
+ MAX(MIN
+ (ROUND_DIV
+ (remaing_dmas, weighted_remaining_ports),
+ max_open_dma_treshold), min_tx_1_2g5_treshold);
+ rx_1g_dmas =
+ MAX(MIN
+ (ROUND_DIV
+ ((remaing_dmas * rx_tx_raport),
+ weighted_remaining_ports),
+ max_open_dma_treshold), min_rx_1_2g5_treshold);
+ }
+ if (num_2g5_ports) {
+ tx_2g5_dmas =
+ MAX(MIN
+ (CEIL_DIV(remaing_dmas, weighted_remaining_ports),
+ max_open_dma_treshold), min_tx_1_2g5_treshold);
+ rx_2g5_dmas =
+ MAX(MIN
+ (CEIL_DIV
+ ((remaing_dmas * rx_tx_raport),
+ weighted_remaining_ports),
+ max_open_dma_treshold), min_rx_1_2g5_treshold);
+
+ }
+
+ /* Check if these settings is not exceding treshold */
+ open_dmas_computed = num_1g_ports * tx_1g_dmas +
+ num_1g_ports * rx_1g_dmas +
+ num_2g5_ports * tx_2g5_dmas +
+ num_2g5_ports * rx_2g5_dmas +
+ num_10g_ports * tx_10g_dmas +
+ num_10g_ports * rx_10g_dmas +
+ num_oh_ports * oh_dmas + shared_ext_open_dma;
+
+ /* overflow-leftover calculus */
+ overflow = open_dmas_computed - max_fm_open_dma;
+ re_loop = true;
+ while (overflow > 0 && re_loop == true) {
+ re_loop = false;
+ if (num_1g_ports && overflow
+ && rx_1g_dmas > min_rx_1_2g5_treshold) {
+ rx_1g_dmas--;
+ overflow -= num_1g_ports;
+ re_loop = true;
+ }
+ if (num_2g5_ports && overflow
+ && rx_2g5_dmas > min_rx_1_2g5_treshold) {
+ rx_2g5_dmas--;
+ overflow -= num_2g5_ports;
+ re_loop = true;
+ }
+ if (num_10g_ports && overflow
+ && rx_10g_dmas > min_rx_10g_treshold) {
+ rx_10g_dmas--;
+ overflow -= num_10g_ports;
+ re_loop = true;
+ }
+
+ if (num_1g_ports && overflow
+ && tx_1g_dmas > min_tx_1_2g5_treshold) {
+ tx_1g_dmas--;
+ overflow -= num_1g_ports;
+ re_loop = true;
+ }
+ if (num_2g5_ports && overflow
+ && tx_2g5_dmas > min_tx_1_2g5_treshold) {
+ tx_2g5_dmas--;
+ overflow -= num_2g5_ports;
+ re_loop = true;
+ }
+ if (num_10g_ports && overflow
+ && tx_10g_dmas > min_tx_10g_treshold) {
+ tx_10g_dmas--;
+ overflow -= num_10g_ports;
+ re_loop = true;
+ }
+ }
+
+ if (overflow > 0) {
+ printk(KERN_ALERT
+ "This configuration will not work due to over open dma"
+ " allocation (%d open dmas)...\n",
+ overflow);
+ err = -1;
+ goto precalculated_open_dma_out;
+ }
+
+ /* could remain leftovers... e.g. overflow=1,
+ 2ports => leftover=1 => shared=1 */
+ open_dmas_computed = num_1g_ports * tx_1g_dmas +
+ num_1g_ports * rx_1g_dmas +
+ num_2g5_ports * tx_2g5_dmas +
+ num_2g5_ports * rx_2g5_dmas +
+ num_10g_ports * tx_10g_dmas +
+ num_10g_ports * rx_10g_dmas +
+ num_oh_ports * oh_dmas + shared_ext_open_dma;
+
+ if (max_fm_open_dma - open_dmas_computed > 0)
+ shared_ext_open_dma =
+ MIN(shared_ext_open_dma + max_fm_open_dma -
+ open_dmas_computed, max_ext_open_dma_treshold);
+
+ /* set open dmas */
+ fm_resource_settings_info->tx_1g_dmas = tx_1g_dmas;
+ fm_resource_settings_info->rx_1g_dmas = rx_1g_dmas;
+ fm_resource_settings_info->tx_2g5_dmas = tx_2g5_dmas;
+ fm_resource_settings_info->rx_2g5_dmas = rx_2g5_dmas;
+ fm_resource_settings_info->tx_10g_dmas = tx_10g_dmas;
+ fm_resource_settings_info->rx_10g_dmas = rx_10g_dmas;
+ fm_resource_settings_info->oh_dmas = oh_dmas;
+ fm_resource_settings_info->shared_ext_open_dma = shared_ext_open_dma;
+
+precalculated_open_dma_out:
+ printk(KERN_INFO " FMAN(%u) open dma settings:\n",
+ p_LnxWrpFmDev->id);
+ printk(KERN_INFO " - Total open dma available(%u)\n",
+ max_fm_open_dma);
+ if (num_1g_ports) {
+ printk(KERN_INFO " - 1G ports TX %u(%u)\n", num_1g_ports,
+ tx_1g_dmas);
+ printk(KERN_INFO " - 1G ports RX %u(%u)\n", num_1g_ports,
+ rx_1g_dmas);
+ }
+ if (num_2g5_ports) {
+ printk(KERN_INFO " - 2.5G ports TX %u(%u)\n", num_2g5_ports,
+ tx_2g5_dmas);
+ printk(KERN_INFO " - 2.5G ports RX %u(%u)\n", num_2g5_ports,
+ tx_2g5_dmas);
+ }
+ if (num_10g_ports) {
+ printk(KERN_INFO " - 10G ports TX %u(%u)\n", num_10g_ports,
+ tx_10g_dmas);
+ printk(KERN_INFO " - 10G ports RX %u(%u)\n", num_10g_ports,
+ rx_10g_dmas);
+ }
+ if (num_oh_ports)
+ printk(KERN_INFO " - OH-HC ports %u(%u)\n", num_oh_ports,
+ oh_dmas);
+ printk(KERN_INFO " - Shared extra open dma(%u)\n",
+ shared_ext_open_dma ? shared_ext_open_dma : 0);
+
+ return err;
+}
+
+#if !defined(FMAN_RESOURCES_UNIT_TEST)
+int fm_config_precalculate_open_dma(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev =
+ (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev;
+ struct fm_resource_settings *fm_resource_settings_info = NULL;
+ t_FmPortRsrc numOfOpenDmas;
+ t_Error errCode;
+
+ ASSERT_COND(p_LnxWrpFmDev != NULL);
+ fm_resource_settings_info = &p_LnxWrpFmDev->fm_resource_settings_info;
+
+ memset(&numOfOpenDmas, 0, sizeof(t_FmPortRsrc));
+
+/* IF 1G PORT */
+ if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_TX)
+ numOfOpenDmas.num = fm_resource_settings_info->tx_1g_dmas;
+ else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_RX)
+ numOfOpenDmas.num = fm_resource_settings_info->rx_1g_dmas;
+/* IF 2.5G PORT*/
+ /* TODO: Not supported by LLD yet. */
+
+/* IF 10G PORT */
+ else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_TX_10G)
+ numOfOpenDmas.num = fm_resource_settings_info->tx_10g_dmas;
+ else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_RX_10G)
+ numOfOpenDmas.num = fm_resource_settings_info->rx_10g_dmas;
+/* IF OH PORT */
+ else
+ numOfOpenDmas.num = fm_resource_settings_info->oh_dmas;
+
+ numOfOpenDmas.extra = fm_resource_settings_info->shared_ext_open_dma;
+
+ errCode = FM_PORT_ConfigNumOfOpenDmas(p_LnxWrpFmPortDev->h_Dev,
+ &numOfOpenDmas);
+ if (errCode != E_OK) {
+ printk(KERN_WARNING
+ "FM_PORT_SetNumOfOpenDmas failed (errCode:0x%2x)",
+ errCode);
+ return -EIO;
+ }
+
+ return 0;
+}
+#endif /*if !defined(FMAN_RESOURCES_UNIT_TEST)*/
+
+/* Compute FMan tnums based on available tnums and number of ports.
+ Set defaults (minim tresholds) and then distribute leftovers.*/
+int fm_precalculate_tnums(t_LnxWrpFmDev *p_LnxWrpFmDev, int max_fm_tnums)
+{
+ /* input parameters */
+ struct fm_active_ports *fm_active_ports_info = NULL;
+ int num_1g_ports = 0;
+ int num_2g5_ports = 0;
+ int num_10g_ports = 0;
+ int num_oh_ports = 0;
+
+ /* output parameters */
+ struct fm_resource_settings *fm_resource_settings_info = NULL;
+ int tx_1g_tnums = 0, rx_1g_tnums = 0;
+ int tx_2g5_tnums = 0, rx_2g5_tnums = 0;
+ int tx_10g_tnums = 0, rx_10g_tnums = 0;
+ int oh_tnums = 0;
+ int shared_ext_tnums = 0;
+ int err = 0;
+
+ /* open dma calculus */
+ int default_and_treshold_rx_tx_10g_tnums = 16; /* DPDE_10g */
+ int default_and_treshold_rx_tx_1g_2g5_tnums = 4; /* DPDE_1g */
+ int default_and_treshold_oh_tnums = 2; /* Hell knows why */
+ int max_tnums_treshold = 64; /* LLD: MAX_NUM_OF_TASKS */
+ int max_ext_tnums_treshold = 8; /* LLD: MAX_NUM_OF_EXTRA_TASKS */
+ int remaing_tnums = 0;
+ int tnums_computed = 0;
+ int leftovers = 0;
+ bool re_loop = true;
+
+ /* check input parameters correctness */
+ ASSERT_COND(p_LnxWrpFmDev != NULL);
+ fm_active_ports_info = &p_LnxWrpFmDev->fm_active_ports_info;
+ fm_resource_settings_info = &p_LnxWrpFmDev->fm_resource_settings_info;
+ ASSERT_COND(fm_active_ports_info != NULL);
+ ASSERT_COND(fm_resource_settings_info != NULL);
+ ASSERT_COND(fm_active_ports_info->num_tx_ports ==
+ fm_active_ports_info->num_rx_ports);
+ ASSERT_COND(fm_active_ports_info->num_tx25_ports ==
+ fm_active_ports_info->num_tx25_ports);
+ ASSERT_COND(fm_active_ports_info->num_tx10_ports ==
+ fm_active_ports_info->num_tx10_ports);
+
+ /* set input parameters */
+ num_1g_ports = fm_active_ports_info->num_tx_ports;
+ num_2g5_ports = fm_active_ports_info->num_tx25_ports;
+ num_10g_ports = fm_active_ports_info->num_tx10_ports;
+ num_oh_ports = fm_active_ports_info->num_oh_ports;
+
+ /* compute FMan TNUMs per port */
+ /* ------------------------------------------------------- */
+ if (num_1g_ports) {
+ tx_1g_tnums = default_and_treshold_rx_tx_1g_2g5_tnums;
+ rx_1g_tnums = default_and_treshold_rx_tx_1g_2g5_tnums;
+ }
+ if (num_2g5_ports) {
+ tx_2g5_tnums = default_and_treshold_rx_tx_1g_2g5_tnums;
+ rx_2g5_tnums = default_and_treshold_rx_tx_1g_2g5_tnums;
+ }
+ if (num_10g_ports) {
+ tx_10g_tnums = default_and_treshold_rx_tx_10g_tnums;
+ rx_10g_tnums = default_and_treshold_rx_tx_10g_tnums;
+ }
+ if (num_oh_ports)
+ oh_tnums = default_and_treshold_oh_tnums;
+
+ shared_ext_tnums = num_10g_ports ?
+ max_ext_tnums_treshold : 2; /* DEFAULT_PORT_extraNumOfTasks */
+
+ /* based on total number of ports set open DMAs for all other ports */
+ remaing_tnums = max_fm_tnums -
+ (oh_tnums * num_oh_ports) -
+ (tx_1g_tnums * num_1g_ports + rx_1g_tnums * num_1g_ports) -
+ (tx_2g5_tnums * num_2g5_ports + rx_2g5_tnums * num_2g5_ports) -
+ (tx_10g_tnums * num_10g_ports + rx_10g_tnums * num_10g_ports) -
+ shared_ext_tnums;
+
+ if (remaing_tnums < 0) {
+ printk(KERN_ALERT
+ "This configuration will not work due to low number"
+ " of tnums (%u tnums) and number of total ports"
+ " available...\n",
+ max_fm_tnums);
+ err = -1;
+ goto precalculated_tnums_out;
+ }
+
+ leftovers = remaing_tnums;
+ re_loop = true;
+ while (leftovers > 0 && re_loop == true) {
+ re_loop = false;
+ if (num_10g_ports && (leftovers - (int) num_10g_ports) >= 0
+ && (rx_10g_tnums < max_tnums_treshold)) {
+ rx_10g_tnums++;
+ leftovers -= num_10g_ports;
+ re_loop = true;
+ }
+
+ if (num_10g_ports && (leftovers - (int) num_10g_ports) >= 0
+ && (tx_10g_tnums < max_tnums_treshold)) {
+ tx_10g_tnums++;
+ leftovers -= num_10g_ports;
+ re_loop = true;
+ }
+
+ if (num_2g5_ports && (leftovers - (int) num_2g5_ports) >= 0
+ && (rx_2g5_tnums < max_tnums_treshold)) {
+ rx_2g5_tnums++;
+ leftovers -= num_2g5_ports;
+ re_loop = true;
+ }
+
+ if (num_2g5_ports && (leftovers - (int) num_2g5_ports) >= 0
+ && (tx_2g5_tnums < max_tnums_treshold)) {
+ tx_2g5_tnums++;
+ leftovers -= num_2g5_ports;
+ re_loop = true;
+ }
+
+ if (num_1g_ports && (leftovers - (int) num_1g_ports) >= 0
+ && (rx_1g_tnums < max_tnums_treshold)) {
+ rx_1g_tnums++;
+ leftovers -= num_1g_ports;
+ re_loop = true;
+ }
+
+ if (num_1g_ports && (leftovers - (int) num_1g_ports) >= 0
+ && (tx_1g_tnums < max_tnums_treshold)) {
+ tx_1g_tnums++;
+ leftovers -= num_1g_ports;
+ re_loop = true;
+ }
+ }
+
+ tnums_computed =
+ num_1g_ports * tx_1g_tnums +
+ num_1g_ports * rx_1g_tnums +
+ num_2g5_ports * tx_2g5_tnums +
+ num_2g5_ports * rx_2g5_tnums +
+ num_10g_ports * tx_10g_tnums +
+ num_10g_ports * rx_10g_tnums +
+ num_oh_ports * oh_tnums +
+ shared_ext_tnums;
+
+ if (leftovers > 0)
+ shared_ext_tnums =
+ MIN(shared_ext_tnums + max_fm_tnums - tnums_computed,
+ max_ext_tnums_treshold);
+
+ ASSERT_COND((oh_tnums * num_oh_ports) +
+ (tx_1g_tnums * num_1g_ports + rx_1g_tnums * num_1g_ports) +
+ (tx_2g5_tnums * num_2g5_ports +
+ rx_2g5_tnums * num_2g5_ports) +
+ (tx_10g_tnums * num_10g_ports +
+ rx_10g_tnums * num_10g_ports) + shared_ext_tnums <=
+ max_fm_tnums);
+
+ /* set computed tnums */
+ fm_resource_settings_info->tx_1g_tnums = tx_1g_tnums;
+ fm_resource_settings_info->rx_1g_tnums = rx_1g_tnums;
+ fm_resource_settings_info->tx_2g5_tnums = tx_2g5_tnums;
+ fm_resource_settings_info->rx_2g5_tnums = rx_2g5_tnums;
+ fm_resource_settings_info->tx_10g_tnums = tx_10g_tnums;
+ fm_resource_settings_info->rx_10g_tnums = rx_10g_tnums;
+ fm_resource_settings_info->oh_tnums = oh_tnums;
+ fm_resource_settings_info->shared_ext_tnums = shared_ext_tnums;
+
+precalculated_tnums_out:
+ printk(KERN_INFO " FMAN(%u) Tnums settings:\n", p_LnxWrpFmDev->id);
+ printk(KERN_INFO " - Total Tnums available(%u)\n", max_fm_tnums);
+ if (num_1g_ports) {
+ printk(KERN_INFO " - 1G ports TX %u(%u)\n", num_1g_ports,
+ tx_1g_tnums);
+ printk(KERN_INFO " - 1G ports RX %u(%u)\n", num_1g_ports,
+ rx_1g_tnums);
+ }
+ if (num_2g5_ports) {
+ printk(KERN_INFO " - 2.5G ports TX %u(%u)\n", num_2g5_ports,
+ tx_2g5_tnums);
+ printk(KERN_INFO " - 2.5G ports RX %u(%u)\n", num_2g5_ports,
+ rx_2g5_tnums);
+ }
+ if (num_10g_ports) {
+ printk(KERN_INFO " - 10G ports TX %u(%u)\n", num_10g_ports,
+ tx_10g_tnums);
+ printk(KERN_INFO " - 10G ports RX %u(%u)\n", num_10g_ports,
+ rx_10g_tnums);
+ }
+ if (num_oh_ports)
+ printk(KERN_INFO " - OH-HC ports %u(%u)\n", num_oh_ports,
+ oh_tnums);
+ printk(KERN_INFO " - Shared extra tnums(%u)\n", shared_ext_tnums);
+
+ return err;
+}
+
+#if !defined(FMAN_RESOURCES_UNIT_TEST)
+int fm_config_precalculate_tnums(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev)
+{
+ t_LnxWrpFmDev *p_LnxWrpFmDev =
+ (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev;
+ struct fm_resource_settings *fm_resource_settings_info = NULL;
+ t_FmPortRsrc numOfTask;
+ t_Error errCode;
+
+ ASSERT_COND(p_LnxWrpFmDev != NULL);
+ fm_resource_settings_info = &p_LnxWrpFmDev->fm_resource_settings_info;
+
+ memset(&numOfTask, 0, sizeof(t_FmPortRsrc));
+
+/* IF 1G PORT */
+ if (p_LnxWrpFmPortDev->settings.param.portType == e_FM_PORT_TYPE_TX)
+ numOfTask.num = fm_resource_settings_info->tx_1g_tnums;
+ else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_RX)
+ numOfTask.num = fm_resource_settings_info->rx_1g_tnums;
+/* IF 2.5G PORT*/
+ /* TODO: Not supported by LLD yet. */
+
+/* IF 10G PORT */
+ else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_TX_10G)
+ numOfTask.num = fm_resource_settings_info->tx_10g_tnums;
+ else if (p_LnxWrpFmPortDev->settings.param.portType ==
+ e_FM_PORT_TYPE_RX_10G)
+ numOfTask.num = fm_resource_settings_info->rx_10g_tnums;
+/* IF OH PORT */
+ else
+ numOfTask.num = fm_resource_settings_info->oh_dmas;
+
+ numOfTask.extra = fm_resource_settings_info->shared_ext_tnums;
+
+ errCode = FM_PORT_ConfigNumOfTasks(p_LnxWrpFmPortDev->h_Dev, &numOfTask);
+ if (errCode != E_OK) {
+ printk(KERN_WARNING
+ "FM_PORT_SetNumOfTasks failed (errCode:0x%2x)",
+ errCode);
+ return -EIO;
+ }
+
+ return 0;
+}
+#endif /*if !defined(FMAN_RESOURCES_UNIT_TEST)*/
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources.h b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources.h
new file mode 100644
index 0000000..1b72e1d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ @File lnxwrp_resources.h
+
+ @Description FMD wrapper resource allocation functions.
+
+*/
+
+#ifndef LNXWRP_RESOURCES_H_
+#define LNXWRP_RESOURCES_H_
+
+#if !defined(FMAN_RESOURCES_UNIT_TEST)
+#include "lnxwrp_fm.h"
+#else
+#include "lnxwrp_resources_ut.h"
+#endif
+
+#define ROUND(X) ((2*(X)+1)/2)
+#define CEIL(X) ((X)+1)
+/* #define ROUND_DIV(X, Y) (((X)+(Y)/2)/(Y)) */
+#define ROUND_DIV(X, Y) ((2*(X)+(Y))/(2*(Y)))
+#define CEIL_DIV(X, Y) (((X)+(Y)-1)/(Y))
+
+/* used for resource calculus */
+#define DPDE_1G 2 /* DQDP 1g - from LLD:
+ DEFAULT_PORT_txFifoDeqPipelineDepth_1G */
+#define DPDE_10G 8 /* DQDP 10g - from LLD:
+ DEFAULT_PORT_txFifoDeqPipelineDepth_10G */
+
+int fm_set_active_fman_ports(struct platform_device *of_dev,
+ t_LnxWrpFmDev *p_LnxWrpFmDev);
+
+/* Calculate the fifosize based on MURAM allocation, number of ports, dpde
+ * value and s/g software support (! Kernel does not suport s/g).
+ *
+ * Algorithm summary:
+ * - Calculate the the minimum fifosize required for every type of port
+ * (TX,RX for 1G, 2.5G and 10G).
+ * - Set TX the minimum fifosize required.
+ * - Distribute the remaining buffers (after all TX were set) to RX ports
+ * based on:
+ * 1G RX = Remaining_buffers * 1/(1+2.5+10)
+ * 2.5G RX = Remaining_buffers * 2.5/(1+2.5+10)
+ * 10G RX = Remaining_buffers * 10/(1+2.5+10)
+ * - if the RX is smaller than the minimum required, then set the minimum
+ * required
+ * - In the end distribuite the leftovers if there are any (due to
+ * unprecise calculus) or if over allocation cat some buffers from all RX
+ * ports w/o pass over minimum required treshold, but if there must be
+ * pass the treshold in order to cat the over allocation ,then this
+ * configuration can not be set - KERN_ALERT.
+*/
+int fm_precalculate_fifosizes(t_LnxWrpFmDev *p_LnxWrpFmDev,
+ int muram_fifo_size);
+
+#if !defined(FMAN_RESOURCES_UNIT_TEST)
+int fm_config_precalculate_fifosize(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev);
+#endif
+
+/* Compute FMan open DMA based on total number of open DMAs and
+ * number of available fman ports.
+ *
+ * By default 10g ports are set to input parameters. The other ports
+ * tries to keep the proportion rx=2tx open dmas or tresholds.
+ *
+ * If leftovers, then those will be set as shared.
+ *
+ * If after computing overflow appears, then it decrements open dma
+ * for all ports w/o cross the tresholds. If the tresholds are meet
+ * and is still overflow, then it returns error.
+*/
+int fm_precalculate_open_dma(t_LnxWrpFmDev *p_LnxWrpFmDev,
+ int max_fm_open_dma,
+ int default_tx_10g_dmas,
+ int default_rx_10g_dmas,
+ int min_tx_10g_treshold, int min_rx_10g_treshold);
+
+#if !defined(FMAN_RESOURCES_UNIT_TEST)
+int fm_config_precalculate_open_dma(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev);
+#endif
+
+/* Compute FMan tnums based on available tnums and number of ports.
+ * Set defaults (minim tresholds) and then distribute leftovers.*/
+int fm_precalculate_tnums(t_LnxWrpFmDev *p_LnxWrpFmDev, int max_fm_tnums);
+
+#if !defined(FMAN_RESOURCES_UNIT_TEST)
+int fm_config_precalculate_tnums(t_LnxWrpFmPortDev *p_LnxWrpFmPortDev);
+#endif
+
+#endif /* LNXWRP_RESOURCES_H_ */
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.c
new file mode 100644
index 0000000..6c06a5a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.c
@@ -0,0 +1,191 @@
+/* Copyright (c) 2012 Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "lnxwrp_resources.h"
+#include "lnxwrp_resources_ut.h"
+
+#define KILOBYTE 0x400 /* 1024 */
+
+typedef enum e_board_type {
+ e_p3041,
+ e_p4080,
+ e_p5020,
+ e_p1023
+} e_board_type;
+
+uint8_t board_type;
+uint32_t muram_size = 0;
+uint32_t dmas_num = 0;
+uint32_t task_num = 0;
+uint32_t frame_size = 0;
+uint32_t oh_num = 0;
+uint32_t num_ports_1g = 0;
+uint32_t num_ports_10g = 0;
+uint32_t num_ports_2g5 = 0;
+uint32_t fsl_fman_phy_maxfrm = 0;
+uint32_t dpa_rx_extra_headroom = 0;
+
+void show_help(void){
+ printf(" help: \n");
+ printf(" -b <board_type> -f <max_fram_size(mtu)> -o <num_oh_ports> -g1"
+ " <num_1g_ports> -g10 <num_10g_ports> -g25 <num_2g5_ports>\n");
+ printf(" Maxim num of DMAS availbale: P3/P4/P5:32 , P1023:16 \n");
+ printf(" Maxim num of TNUMs availbale: P3/P4/P5:128, P1023:32 \n");
+ printf(" Muram size: P3/P4/P5:160K, P1023:64K \n");
+ printf(" Number of ports:\n");
+ printf(" P3/P5: 5p 1g, 1p 10g, 7p oh \n");
+ printf(" P4 : 4p 1g, 1p 10g, 7p oh \n");
+ printf(" P1 : 2p 1g, 0p 10g, 4p oh \n");
+ printf(" MTU: Default:1522, Jumbo:9600 \n");
+}
+
+int fm_set_param(t_LnxWrpFmDev *p_LnxWrpFmDev) {
+ struct fm_active_ports *fm_active_ports_info = NULL;
+ fm_active_ports_info = &p_LnxWrpFmDev->fm_active_ports_info;
+
+ switch(board_type){
+ case e_p3041:
+ case e_p5020:
+ muram_size = 160*KILOBYTE;
+ dmas_num = 32;
+ task_num = 128;
+ if ((num_ports_1g+num_ports_2g5) > 5 || num_ports_10g > 1 || oh_num > 7)
+ goto err_fm_set_param;
+ break;
+ case e_p4080:
+ muram_size = 160*KILOBYTE;
+ dmas_num = 32;
+ task_num = 128;
+ if ((num_ports_1g+num_ports_2g5) > 4 || num_ports_10g > 1 || oh_num > 7)
+ goto err_fm_set_param;
+ break;
+ case e_p1023:
+ muram_size = 64*KILOBYTE;
+ dmas_num = 16;
+ task_num = 128;
+ if ((num_ports_1g+num_ports_2g5) > 2 || oh_num > 4)
+ goto err_fm_set_param;
+ break;
+ default:
+ goto err_fm_set_param;
+ break;
+ }
+
+ p_LnxWrpFmDev->id = 0;
+ fsl_fman_phy_maxfrm = frame_size;
+ dpa_rx_extra_headroom = 0; /* ATTENTION: can be != 0 */
+ fm_active_ports_info->num_oh_ports = oh_num;
+ fm_active_ports_info->num_tx_ports = num_ports_1g;
+ fm_active_ports_info->num_rx_ports = num_ports_1g;
+ fm_active_ports_info->num_tx25_ports = num_ports_2g5;
+ fm_active_ports_info->num_rx25_ports = num_ports_2g5;
+ fm_active_ports_info->num_tx10_ports = num_ports_10g;
+ fm_active_ports_info->num_rx10_ports = num_ports_10g;
+
+ return 0;
+
+err_fm_set_param:
+ printf(" ERR: To many ports!!! \n");
+ return -1;
+}
+
+int main (int argc, char *argv[]){
+ t_LnxWrpFmDev LnxWrpFmDev;
+ t_LnxWrpFmDev *p_LnxWrpFmDev = &LnxWrpFmDev;
+ int tokens_cnt = 1;
+
+ char *token = NULL;
+
+ while(tokens_cnt < argc)
+ {
+ token = argv[tokens_cnt++];
+ if (strcmp(token, "-b") == 0){
+ if(strcmp(argv[tokens_cnt],"p3") == 0)
+ board_type = e_p3041;
+ else if(strcmp(argv[tokens_cnt],"p4") == 0)
+ board_type = e_p4080;
+ else if(strcmp(argv[tokens_cnt],"p5") == 0)
+ board_type = e_p5020;
+ else if(strcmp(argv[tokens_cnt],"p1") == 0)
+ board_type = e_p1023;
+ else
+ show_help();
+ tokens_cnt++;
+ }
+ else if(strcmp(token, "-d") == 0){
+ dmas_num = atoi(argv[tokens_cnt++]);
+ }
+ else if(strcmp(token, "-t") == 0)
+ task_num = atoi(argv[tokens_cnt++]);
+ else if(strcmp(token, "-f") == 0)
+ frame_size = atoi(argv[tokens_cnt++]);
+ else if(strcmp(token, "-o") == 0)
+ oh_num = atoi(argv[tokens_cnt++]);
+ else if(strcmp(token, "-g1") == 0)
+ num_ports_1g = atoi(argv[tokens_cnt++]);
+ else if(strcmp(token, "-g10") == 0)
+ num_ports_10g = atoi(argv[tokens_cnt++]);
+ else if(strcmp(token, "-g25") == 0)
+ num_ports_2g5 = atoi(argv[tokens_cnt++]);
+ else {
+ show_help();
+ return -1;
+ }
+ }
+
+ if(fm_set_param(p_LnxWrpFmDev) < 0){
+ show_help();
+ return -1;
+ }
+
+ if(fm_precalculate_fifosizes(
+ p_LnxWrpFmDev,
+ 128*KILOBYTE)
+ != 0)
+ return -1;
+ if(fm_precalculate_open_dma(
+ p_LnxWrpFmDev,
+ dmas_num, /* max open dmas:dpaa_integration_ext.h */
+ FM_DEFAULT_TX10G_OPENDMA, /* default TX 10g open dmas */
+ FM_DEFAULT_RX10G_OPENDMA, /* default RX 10g open dmas */
+ FM_10G_OPENDMA_MIN_TRESHOLD,/* TX 10g minimum treshold */
+ FM_10G_OPENDMA_MIN_TRESHOLD)/* RX 10g minimum treshold */
+ != 0)
+ return -1;
+ if(fm_precalculate_tnums(
+ p_LnxWrpFmDev,
+ task_num) /* max TNUMS: dpa integration file. */
+ != 0)
+ return -1;
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.h b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.h
new file mode 100644
index 0000000..063946e
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.h
@@ -0,0 +1,144 @@
+/* Copyright (c) 2012 Freescale Semiconductor, Inc
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FM_RESS_TEST_H_
+#define FM_RESS_TEST_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define _Packed
+#define _PackedType __attribute__ ((packed))
+#define MAX(x, y) (((x) > (y)) ? (x) : (y))
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+#define KERN_ALERT ""
+#define KERN_INFO ""
+#define ASSERT_COND assert
+#define printk printf
+#define NET_IP_ALIGN 0
+#define FM_FIFO_ALLOCATION_OLD_ALG
+
+#if defined(CONFIG_FMAN_DISABLE_OH_AND_DISTRIBUTE_RESOURCES)
+#define FM_10G_OPENDMA_MIN_TRESHOLD 8 /* 10g minimum treshold if only HC is enabled and no OH port enabled */
+#define FM_OPENDMA_RX_TX_RAPORT 2 /* RX = 2*TX */
+#else
+#define FM_10G_OPENDMA_MIN_TRESHOLD 7 /* 10g minimum treshold if 7 OH ports are enabled */
+#define FM_OPENDMA_RX_TX_RAPORT 1 /* RX = TX */
+#endif
+#define FM_DEFAULT_TX10G_OPENDMA 8 /* default TX 10g open dmas */
+#define FM_DEFAULT_RX10G_OPENDMA 8 /* default RX 10g open dmas */
+
+/* information about all active ports for an FMan.
+ * !Some ports may be disabled by u-boot, thus will not be available */
+struct fm_active_ports {
+ uint32_t num_oh_ports;
+ uint32_t num_tx_ports;
+ uint32_t num_rx_ports;
+ uint32_t num_tx25_ports;
+ uint32_t num_rx25_ports;
+ uint32_t num_tx10_ports;
+ uint32_t num_rx10_ports;
+};
+
+/* FMan resources precalculated at fm probe based
+ * on available FMan port. */
+struct fm_resource_settings {
+ /* buffers - fifo sizes */
+ uint32_t tx1g_num_buffers;
+ uint32_t rx1g_num_buffers;
+ uint32_t tx2g5_num_buffers; /* Not supported yet by LLD */
+ uint32_t rx2g5_num_buffers; /* Not supported yet by LLD */
+ uint32_t tx10g_num_buffers;
+ uint32_t rx10g_num_buffers;
+ uint32_t oh_num_buffers;
+ uint32_t shared_ext_buffers;
+
+
+ /* open DMAs */
+ uint32_t tx_1g_dmas;
+ uint32_t rx_1g_dmas;
+ uint32_t tx_2g5_dmas; /* Not supported yet by LLD */
+ uint32_t rx_2g5_dmas; /* Not supported yet by LLD */
+ uint32_t tx_10g_dmas;
+ uint32_t rx_10g_dmas;
+ uint32_t oh_dmas;
+ uint32_t shared_ext_open_dma;
+
+ /* Tnums */
+ uint32_t tx_1g_tnums;
+ uint32_t rx_1g_tnums;
+ uint32_t tx_2g5_tnums; /* Not supported yet by LLD */
+ uint32_t rx_2g5_tnums; /* Not supported yet by LLD */
+ uint32_t tx_10g_tnums;
+ uint32_t rx_10g_tnums;
+ uint32_t oh_tnums;
+ uint32_t shared_ext_tnums;
+};
+
+typedef struct {
+ uint8_t id;
+ struct fm_active_ports fm_active_ports_info;
+ struct fm_resource_settings fm_resource_settings_info;
+} t_LnxWrpFmDev;
+
+typedef struct {
+ uint8_t id;
+} t_LnxWrpFmPortDev;
+
+typedef _Packed struct t_FmPrsResult {
+ volatile uint8_t lpid; /**< Logical port id */
+ volatile uint8_t shimr; /**< Shim header result */
+ volatile uint16_t l2r; /**< Layer 2 result */
+ volatile uint16_t l3r; /**< Layer 3 result */
+ volatile uint8_t l4r; /**< Layer 4 result */
+ volatile uint8_t cplan; /**< Classification plan id */
+ volatile uint16_t nxthdr; /**< Next Header */
+ volatile uint16_t cksum; /**< Checksum */
+ volatile uint32_t lcv; /**< LCV */
+ volatile uint8_t shim_off[3]; /**< Shim offset */
+ volatile uint8_t eth_off; /**< ETH offset */
+ volatile uint8_t llc_snap_off; /**< LLC_SNAP offset */
+ volatile uint8_t vlan_off[2]; /**< VLAN offset */
+ volatile uint8_t etype_off; /**< ETYPE offset */
+ volatile uint8_t pppoe_off; /**< PPP offset */
+ volatile uint8_t mpls_off[2]; /**< MPLS offset */
+ volatile uint8_t ip_off[2]; /**< IP offset */
+ volatile uint8_t gre_off; /**< GRE offset */
+ volatile uint8_t l4_off; /**< Layer 4 offset */
+ volatile uint8_t nxthdr_off; /**< Parser end point */
+} _PackedType t_FmPrsResult;
+
+#endif
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.make b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.make
new file mode 100644
index 0000000..58009cd
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_resources_ut.make
@@ -0,0 +1,28 @@
+CC=gcc
+
+LNXWRP_RESS_UT=lnxwrp_resources_ut
+OBJ=lnxwrp_resources
+
+INC_PATH=
+LIB_PATH=
+
+INC=$(addprefix -I,$(INC_PATH))
+LIB=$(addprefix -L,$(LIB_PATH))
+
+CFLAGS= -gdwarf-2 -g -O0 -Wall
+XFLAGS= -DFMAN_RESOURCES_UNIT_TEST
+
+all: $(LNXWRP_RESS_UT)
+
+$(LNXWRP_RESS_UT):$(addsuffix .o,$(OBJ)) $(LNXWRP_RESS_UT).o
+ $(CC) -o $(LNXWRP_RESS_UT) $(LNXWRP_RESS_UT).o $(addsuffix .o,$(OBJ))
+
+%.o: %.c
+ @(echo " (CC) $@")
+ @($(CC) $(INC) $(CFLAGS) $(XFLAGS) -o $(@) -c $<)
+
+.PHONY: clean
+
+clean:
+ rm -f *.o
+ rm -f $(LNXWRP_RESS_UT)
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs.c
new file mode 100644
index 0000000..813771b
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ @File lnxwrp_sysfs.c
+
+ @Description FM wrapper sysfs related functions.
+
+*/
+
+#include <linux/types.h>
+#include "lnxwrp_sysfs.h"
+
+uint8_t fm_find_statistic_counter_by_name(const char *attr_name,
+ const struct sysfs_stats_t *sysfs_stats,
+ uint8_t *offset)
+{
+ int i = 0;
+
+ while (sysfs_stats[i].stat_name != NULL) {
+ if (strcmp(sysfs_stats[i].stat_name, attr_name) == 0) {
+ if (offset != NULL)
+ *offset = i;
+ return sysfs_stats[i].stat_counter;
+ }
+
+ i++;
+ }
+ WARN(1, "FMD: Should never get here!");
+ return 0;
+}
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs.h b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs.h
new file mode 100644
index 0000000..2098b24
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LNXWRP_SYSFS_H_
+#define LNXWRP_SYSFS_H_
+
+/* Linux Headers ------------------- */
+#include <linux/version.h>
+
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+#define MODVERSIONS
+#endif
+#ifdef MODVERSIONS
+#include <config/modversions.h>
+#endif /* MODVERSIONS */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/sysfs.h>
+
+struct sysfs_stats_t {
+ const char *stat_name;
+ uint8_t stat_counter;
+};
+
+uint8_t fm_find_statistic_counter_by_name(const char *attr_name,
+ const struct sysfs_stats_t *sysfs_stats,
+ uint8_t *offset);
+
+#endif /* LNXWRP_SYSFS_H_ */
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm.c
new file mode 100644
index 0000000..0ea6d1c
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm.c
@@ -0,0 +1,1809 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "lnxwrp_sysfs.h"
+#include "lnxwrp_sysfs_fm.h"
+#include "lnxwrp_fm.h"
+
+#include "../../fman/Peripherals/FM/inc/fm_common.h"
+#include "../../fman/Peripherals/FM/Pcd/fm_pcd.h"
+#include "../../fman/Peripherals/FM/Pcd/fm_kg.h"
+#include "../../fman/Peripherals/FM/Pcd/fm_plcr.h"
+
+#if defined(__ERR_MODULE__)
+#undef __ERR_MODULE__
+#endif
+
+#include "../../fman/Peripherals/FM/fm.h"
+
+
+static int fm_get_counter(void *h_fm, e_FmCounters cnt_e, uint32_t *cnt_val);
+
+enum fm_dma_match_stats {
+ FM_DMA_COUNTERS_CMQ_NOT_EMPTY,
+ FM_DMA_COUNTERS_BUS_ERROR,
+ FM_DMA_COUNTERS_READ_BUF_ECC_ERROR,
+ FM_DMA_COUNTERS_WRITE_BUF_ECC_SYS_ERROR,
+ FM_DMA_COUNTERS_WRITE_BUF_ECC_FM_ERROR
+};
+
+static const struct sysfs_stats_t fm_sysfs_stats[] = {
+ /* FM statistics */
+ {
+ .stat_name = "enq_total_frame",
+ .stat_counter = e_FM_COUNTERS_ENQ_TOTAL_FRAME,
+ },
+ {
+ .stat_name = "deq_total_frame",
+ .stat_counter = e_FM_COUNTERS_DEQ_TOTAL_FRAME,
+ },
+ {
+ .stat_name = "deq_0",
+ .stat_counter = e_FM_COUNTERS_DEQ_0,
+ },
+ {
+ .stat_name = "deq_1",
+ .stat_counter = e_FM_COUNTERS_DEQ_1,
+ },
+ {
+ .stat_name = "deq_2",
+ .stat_counter = e_FM_COUNTERS_DEQ_2,
+ },
+ {
+ .stat_name = "deq_3",
+ .stat_counter = e_FM_COUNTERS_DEQ_3,
+ },
+ {
+ .stat_name = "deq_from_default",
+ .stat_counter = e_FM_COUNTERS_DEQ_FROM_DEFAULT,
+ },
+ {
+ .stat_name = "deq_from_context",
+ .stat_counter = e_FM_COUNTERS_DEQ_FROM_CONTEXT,
+ },
+ {
+ .stat_name = "deq_from_fd",
+ .stat_counter = e_FM_COUNTERS_DEQ_FROM_FD,
+ },
+ {
+ .stat_name = "deq_confirm",
+ .stat_counter = e_FM_COUNTERS_DEQ_CONFIRM,
+ },
+ /* FM:DMA statistics */
+ {
+ .stat_name = "cmq_not_empty",
+ .stat_counter = FM_DMA_COUNTERS_CMQ_NOT_EMPTY,
+ },
+ {
+ .stat_name = "bus_error",
+ .stat_counter = FM_DMA_COUNTERS_BUS_ERROR,
+ },
+ {
+ .stat_name = "read_buf_ecc_error",
+ .stat_counter = FM_DMA_COUNTERS_READ_BUF_ECC_ERROR,
+ },
+ {
+ .stat_name = "write_buf_ecc_sys_error",
+ .stat_counter = FM_DMA_COUNTERS_WRITE_BUF_ECC_SYS_ERROR,
+ },
+ {
+ .stat_name = "write_buf_ecc_fm_error",
+ .stat_counter = FM_DMA_COUNTERS_WRITE_BUF_ECC_FM_ERROR,
+ },
+ /* FM:PCD statistics */
+ {
+ .stat_name = "pcd_kg_total",
+ .stat_counter = e_FM_PCD_KG_COUNTERS_TOTAL,
+ },
+ {
+ .stat_name = "pcd_plcr_yellow",
+ .stat_counter = e_FM_PCD_PLCR_COUNTERS_YELLOW,
+ },
+ {
+ .stat_name = "pcd_plcr_red",
+ .stat_counter = e_FM_PCD_PLCR_COUNTERS_RED,
+ },
+ {
+ .stat_name = "pcd_plcr_recolored_to_red",
+ .stat_counter = e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_RED,
+ },
+ {
+ .stat_name = "pcd_plcr_recolored_to_yellow",
+ .stat_counter = e_FM_PCD_PLCR_COUNTERS_RECOLORED_TO_YELLOW,
+ },
+ {
+ .stat_name = "pcd_plcr_total",
+ .stat_counter = e_FM_PCD_PLCR_COUNTERS_TOTAL,
+ },
+ {
+ .stat_name = "pcd_plcr_length_mismatch",
+ .stat_counter = e_FM_PCD_PLCR_COUNTERS_LENGTH_MISMATCH,
+ },
+ {
+ .stat_name = "pcd_prs_parse_dispatch",
+ .stat_counter = e_FM_PCD_PRS_COUNTERS_PARSE_DISPATCH,
+ },
+ {
+ .stat_name = "pcd_prs_l2_parse_result_returned",
+ .stat_counter = e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED,
+ },
+ {
+ .stat_name = "pcd_prs_l3_parse_result_returned",
+ .stat_counter = e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED,
+ },
+ {
+ .stat_name = "pcd_prs_l4_parse_result_returned",
+ .stat_counter = e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED,
+ },
+ {
+ .stat_name = "pcd_prs_shim_parse_result_returned",
+ .stat_counter = e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED,
+ },
+ {
+ .stat_name = "pcd_prs_l2_parse_result_returned_with_err",
+ .stat_counter =
+ e_FM_PCD_PRS_COUNTERS_L2_PARSE_RESULT_RETURNED_WITH_ERR,
+ },
+ {
+ .stat_name = "pcd_prs_l3_parse_result_returned_with_err",
+ .stat_counter =
+ e_FM_PCD_PRS_COUNTERS_L3_PARSE_RESULT_RETURNED_WITH_ERR,
+ },
+ {
+ .stat_name = "pcd_prs_l4_parse_result_returned_with_err",
+ .stat_counter =
+ e_FM_PCD_PRS_COUNTERS_L4_PARSE_RESULT_RETURNED_WITH_ERR,
+ },
+ {
+ .stat_name = "pcd_prs_shim_parse_result_returned_with_err",
+ .stat_counter =
+ e_FM_PCD_PRS_COUNTERS_SHIM_PARSE_RESULT_RETURNED_WITH_ERR,
+ },
+ {
+ .stat_name = "pcd_prs_soft_prs_cycles",
+ .stat_counter = e_FM_PCD_PRS_COUNTERS_SOFT_PRS_CYCLES,
+ },
+ {
+ .stat_name = "pcd_prs_soft_prs_stall_cycles",
+ .stat_counter = e_FM_PCD_PRS_COUNTERS_SOFT_PRS_STALL_CYCLES,
+ },
+ {
+ .stat_name = "pcd_prs_hard_prs_cycle_incl_stall_cycles",
+ .stat_counter =
+ e_FM_PCD_PRS_COUNTERS_HARD_PRS_CYCLE_INCL_STALL_CYCLES,
+ },
+ {
+ .stat_name = "pcd_prs_muram_read_cycles",
+ .stat_counter = e_FM_PCD_PRS_COUNTERS_MURAM_READ_CYCLES,
+ },
+ {
+ .stat_name = "pcd_prs_muram_read_stall_cycles",
+ .stat_counter = e_FM_PCD_PRS_COUNTERS_MURAM_READ_STALL_CYCLES,
+ },
+ {
+ .stat_name = "pcd_prs_muram_write_cycles",
+ .stat_counter = e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_CYCLES,
+ },
+ {
+ .stat_name = "pcd_prs_muram_write_stall_cycles",
+ .stat_counter = e_FM_PCD_PRS_COUNTERS_MURAM_WRITE_STALL_CYCLES,
+ },
+ {
+ .stat_name = "pcd_prs_fpm_command_stall_cycles",
+ .stat_counter = e_FM_PCD_PRS_COUNTERS_FPM_COMMAND_STALL_CYCLES,
+ },
+ {}
+};
+
+
+/* Fm stats and regs dumps via sysfs */
+static ssize_t show_fm_dma_stats(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ t_LnxWrpFmDev *p_wrp_fm_dev = NULL;
+ t_FmDmaStatus dma_status;
+ unsigned long flags = 0;
+ unsigned n = 0;
+ uint8_t counter_value = 0, counter = 0;
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_wrp_fm_dev == NULL))
+ return -EINVAL;
+
+ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_Dev)
+ return -EIO;
+
+ counter = fm_find_statistic_counter_by_name(
+ attr->attr.name,
+ fm_sysfs_stats, NULL);
+
+ local_irq_save(flags);
+
+ memset(&dma_status, 0, sizeof(dma_status));
+ FM_GetDmaStatus(p_wrp_fm_dev->h_Dev, &dma_status);
+
+ switch (counter) {
+ case FM_DMA_COUNTERS_CMQ_NOT_EMPTY:
+ counter_value = dma_status.cmqNotEmpty;
+ break;
+ case FM_DMA_COUNTERS_BUS_ERROR:
+ counter_value = dma_status.busError;
+ break;
+ case FM_DMA_COUNTERS_READ_BUF_ECC_ERROR:
+ counter_value = dma_status.readBufEccError;
+ break;
+ case FM_DMA_COUNTERS_WRITE_BUF_ECC_SYS_ERROR:
+ counter_value = dma_status.writeBufEccSysError;
+ break;
+ case FM_DMA_COUNTERS_WRITE_BUF_ECC_FM_ERROR:
+ counter_value = dma_status.writeBufEccFmError;
+ break;
+ default:
+ WARN(1, "FMD: failure at %s:%d/%s()!\n", __FILE__, __LINE__,
+ __func__);
+ break;
+ };
+
+ n = snprintf(buf, PAGE_SIZE, "\tFM %u counter: %c\n",
+ p_wrp_fm_dev->id, counter_value ? 'T' : 'F');
+
+ local_irq_restore(flags);
+
+ return n;
+}
+
+static ssize_t show_fm_stats(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ t_LnxWrpFmDev *p_wrp_fm_dev = NULL;
+ unsigned long flags = 0;
+ unsigned n = 0, cnt_e = 0;
+ uint32_t cnt_val;
+ int err;
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_wrp_fm_dev == NULL))
+ return -EINVAL;
+
+ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_Dev)
+ return -EIO;
+
+ cnt_e = fm_find_statistic_counter_by_name(
+ attr->attr.name,
+ fm_sysfs_stats, NULL);
+
+ err = fm_get_counter(p_wrp_fm_dev->h_Dev,
+ (e_FmCounters) cnt_e, &cnt_val);
+
+ if (err)
+ return err;
+
+ local_irq_save(flags);
+
+ n = snprintf(buf, PAGE_SIZE, "\tFM %d counter: %d\n",
+ p_wrp_fm_dev->id, cnt_val);
+
+ local_irq_restore(flags);
+
+ return n;
+}
+
+static ssize_t show_fm_muram_free_sz(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ t_LnxWrpFmDev *p_wrp_fm_dev = NULL;
+ unsigned long flags = 0;
+ unsigned n = 0;
+ uint64_t muram_free_size = 0;
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_wrp_fm_dev == NULL))
+ return -EINVAL;
+
+ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_Dev)
+ return -EIO;
+
+ muram_free_size = FM_MURAM_GetFreeMemSize(p_wrp_fm_dev->h_MuramDev);
+
+ local_irq_save(flags);
+
+ n = snprintf(buf, PAGE_SIZE, "\tFM %d muram_free_size: %lld\n",
+ p_wrp_fm_dev->id, muram_free_size);
+
+ local_irq_restore(flags);
+
+ return n;
+}
+
+static ssize_t show_fm_ctrl_code_ver(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ t_LnxWrpFmDev *p_wrp_fm_dev = NULL;
+ unsigned long flags = 0;
+ unsigned n = 0;
+ t_FmCtrlCodeRevisionInfo rv_info;
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_wrp_fm_dev == NULL))
+ return -EINVAL;
+
+ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_Dev)
+ return -EIO;
+
+ FM_GetFmanCtrlCodeRevision((t_Fm *)p_wrp_fm_dev->h_Dev, &rv_info);
+
+ local_irq_save(flags);
+
+ FM_DMP_LN(buf, n, "- FM %d ctrl code pkg info:\n", p_wrp_fm_dev->id);
+ FM_DMP_LN(buf, n, "Package rev: %d\n", rv_info.packageRev);
+ FM_DMP_LN(buf, n, "major rev: %d\n", rv_info.majorRev);
+ FM_DMP_LN(buf, n, "minor rev: %d\n", rv_info.minorRev);
+
+ local_irq_restore(flags);
+
+ return n;
+}
+
+static ssize_t show_fm_pcd_stats(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ t_LnxWrpFmDev *p_wrp_fm_dev = NULL;
+ unsigned long flags = 0;
+ unsigned n = 0, counter = 0;
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_wrp_fm_dev == NULL))
+ return -EINVAL;
+
+ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_Dev ||
+ !p_wrp_fm_dev->h_PcdDev)
+ return -EIO;
+
+ counter = fm_find_statistic_counter_by_name(
+ attr->attr.name,
+ fm_sysfs_stats, NULL);
+
+ local_irq_save(flags);
+
+ n = snprintf(buf, PAGE_SIZE, "\tFM %d counter: %d\n",
+ p_wrp_fm_dev->id,
+ FM_PCD_GetCounter(p_wrp_fm_dev->h_PcdDev,
+ (e_FmPcdCounters) counter));
+
+ local_irq_restore(flags);
+
+ return n;
+}
+
+static ssize_t show_fm_tnum_dbg(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ unsigned long flags;
+ unsigned n = 0;
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ t_LnxWrpFmDev *p_wrp_fm_dev = NULL;
+#endif
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+
+ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_wrp_fm_dev == NULL))
+ return -EINVAL;
+
+ local_irq_save(flags);
+
+ if (!p_wrp_fm_dev->active)
+ return -EIO;
+ else {
+ int tn_s;
+
+ if (!sscanf(attr->attr.name, "tnum_dbg_%d", &tn_s))
+ return -EINVAL;
+
+ n = fm_dump_tnum_dbg(p_wrp_fm_dev->h_Dev,
+ tn_s, tn_s + 15, buf, n);
+ }
+ local_irq_restore(flags);
+#else
+
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE,
+ "Debug level is too low to dump registers!!!\n");
+ local_irq_restore(flags);
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+ return n;
+}
+
+static ssize_t show_fm_cls_plan(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ unsigned long flags;
+ unsigned n = 0;
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ t_LnxWrpFmDev *p_wrp_fm_dev = NULL;
+#endif
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_wrp_fm_dev == NULL))
+ return -EINVAL;
+
+ local_irq_save(flags);
+
+ n = snprintf(buf, PAGE_SIZE, "\n FM-KG classification plan dump.\n");
+
+ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_PcdDev)
+ return -EIO;
+ else {
+ int cpn;
+
+ if (!sscanf(attr->attr.name, "cls_plan_%d", &cpn))
+ return -EINVAL;
+
+ n = fm_dump_cls_plan(p_wrp_fm_dev->h_PcdDev, cpn, buf, n);
+ }
+ local_irq_restore(flags);
+#else
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE,
+ "Debug level is too low to dump registers!!!\n");
+ local_irq_restore(flags);
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+ return n;
+}
+
+static ssize_t show_fm_profiles(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ unsigned long flags;
+ unsigned n = 0;
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ t_LnxWrpFmDev *p_wrp_fm_dev = NULL;
+#endif
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+
+ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_wrp_fm_dev == NULL))
+ return -EINVAL;
+
+ local_irq_save(flags);
+
+ n = snprintf(buf, PAGE_SIZE, "FM policer profile dump.\n");
+
+ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_PcdDev)
+ return -EIO;
+ else {
+ int pn;
+
+ if (!sscanf(attr->attr.name, "profile_%d", &pn))
+ return -EINVAL;
+
+ n = fm_profile_dump_regs(p_wrp_fm_dev->h_PcdDev, pn, buf, n);
+ }
+ local_irq_restore(flags);
+#else
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE,
+ "Debug level is too low to dump registers!!!\n");
+ local_irq_restore(flags);
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+ return n;
+}
+
+static ssize_t show_fm_schemes(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ unsigned long flags;
+ unsigned n = 0;
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ t_LnxWrpFmDev *p_wrp_fm_dev = NULL;
+#endif
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+
+ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_wrp_fm_dev == NULL))
+ return -EINVAL;
+
+ local_irq_save(flags);
+
+ n = snprintf(buf, PAGE_SIZE, "FM-KG driver schemes dump.\n");
+
+ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_PcdDev)
+ return -EIO;
+ else {
+ int sn;
+
+ if (!sscanf(attr->attr.name, "scheme_%d", &sn))
+ return -EINVAL;
+
+ n = fm_dump_scheme(p_wrp_fm_dev->h_PcdDev, sn, buf, n);
+ }
+ local_irq_restore(flags);
+#else
+
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE,
+ "Debug level is too low to dump registers!!!\n");
+ local_irq_restore(flags);
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+ return n;
+}
+
+/* FM */
+static DEVICE_ATTR(enq_total_frame, S_IRUGO, show_fm_stats, NULL);
+static DEVICE_ATTR(deq_total_frame, S_IRUGO, show_fm_stats, NULL);
+static DEVICE_ATTR(deq_0, S_IRUGO, show_fm_stats, NULL);
+static DEVICE_ATTR(deq_1, S_IRUGO, show_fm_stats, NULL);
+static DEVICE_ATTR(deq_2, S_IRUGO, show_fm_stats, NULL);
+static DEVICE_ATTR(deq_3, S_IRUGO, show_fm_stats, NULL);
+static DEVICE_ATTR(deq_from_default, S_IRUGO, show_fm_stats, NULL);
+static DEVICE_ATTR(deq_from_context, S_IRUGO, show_fm_stats, NULL);
+static DEVICE_ATTR(deq_from_fd, S_IRUGO, show_fm_stats, NULL);
+static DEVICE_ATTR(deq_confirm, S_IRUGO, show_fm_stats, NULL);
+/* FM:DMA */
+static DEVICE_ATTR(cmq_not_empty, S_IRUGO, show_fm_dma_stats, NULL);
+static DEVICE_ATTR(bus_error, S_IRUGO, show_fm_dma_stats, NULL);
+static DEVICE_ATTR(read_buf_ecc_error, S_IRUGO, show_fm_dma_stats, NULL);
+static DEVICE_ATTR(write_buf_ecc_sys_error, S_IRUGO, show_fm_dma_stats, NULL);
+static DEVICE_ATTR(write_buf_ecc_fm_error, S_IRUGO, show_fm_dma_stats, NULL);
+/* FM:PCD */
+static DEVICE_ATTR(pcd_kg_total, S_IRUGO, show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_plcr_yellow, S_IRUGO, show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_plcr_red, S_IRUGO, show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_plcr_recolored_to_red, S_IRUGO, show_fm_pcd_stats,
+ NULL);
+static DEVICE_ATTR(pcd_plcr_recolored_to_yellow, S_IRUGO, show_fm_pcd_stats,
+ NULL);
+static DEVICE_ATTR(pcd_plcr_total, S_IRUGO, show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_plcr_length_mismatch, S_IRUGO, show_fm_pcd_stats,
+ NULL);
+static DEVICE_ATTR(pcd_prs_parse_dispatch, S_IRUGO, show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_l2_parse_result_returned, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_l3_parse_result_returned, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_l4_parse_result_returned, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_shim_parse_result_returned, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_l2_parse_result_returned_with_err, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_l3_parse_result_returned_with_err, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_l4_parse_result_returned_with_err, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_shim_parse_result_returned_with_err, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_soft_prs_cycles, S_IRUGO, show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_soft_prs_stall_cycles, S_IRUGO, show_fm_pcd_stats,
+ NULL);
+static DEVICE_ATTR(pcd_prs_hard_prs_cycle_incl_stall_cycles, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_muram_read_cycles, S_IRUGO, show_fm_pcd_stats,
+ NULL);
+static DEVICE_ATTR(pcd_prs_muram_read_stall_cycles, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_muram_write_cycles, S_IRUGO, show_fm_pcd_stats,
+ NULL);
+static DEVICE_ATTR(pcd_prs_muram_write_stall_cycles, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+static DEVICE_ATTR(pcd_prs_fpm_command_stall_cycles, S_IRUGO,
+ show_fm_pcd_stats, NULL);
+
+static DEVICE_ATTR(tnum_dbg_0, S_IRUGO, show_fm_tnum_dbg, NULL);
+static DEVICE_ATTR(tnum_dbg_16, S_IRUGO, show_fm_tnum_dbg, NULL);
+static DEVICE_ATTR(tnum_dbg_32, S_IRUGO, show_fm_tnum_dbg, NULL);
+static DEVICE_ATTR(tnum_dbg_48, S_IRUGO, show_fm_tnum_dbg, NULL);
+static DEVICE_ATTR(tnum_dbg_64, S_IRUGO, show_fm_tnum_dbg, NULL);
+static DEVICE_ATTR(tnum_dbg_80, S_IRUGO, show_fm_tnum_dbg, NULL);
+static DEVICE_ATTR(tnum_dbg_96, S_IRUGO, show_fm_tnum_dbg, NULL);
+static DEVICE_ATTR(tnum_dbg_112, S_IRUGO, show_fm_tnum_dbg, NULL);
+
+static DEVICE_ATTR(cls_plan_0, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_1, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_2, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_3, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_4, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_5, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_6, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_7, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_8, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_9, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_10, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_11, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_12, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_13, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_14, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_15, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_16, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_17, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_18, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_19, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_20, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_21, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_22, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_23, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_24, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_25, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_26, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_27, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_28, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_29, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_30, S_IRUGO, show_fm_cls_plan, NULL);
+static DEVICE_ATTR(cls_plan_31, S_IRUGO, show_fm_cls_plan, NULL);
+
+static DEVICE_ATTR(profile_0, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_1, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_2, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_3, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_4, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_5, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_6, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_7, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_8, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_9, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_10, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_11, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_12, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_13, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_14, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_15, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_16, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_17, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_18, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_19, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_20, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_21, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_22, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_23, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_24, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_25, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_26, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_27, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_28, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_29, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_30, S_IRUGO, show_fm_profiles, NULL);
+static DEVICE_ATTR(profile_31, S_IRUGO, show_fm_profiles, NULL);
+
+static DEVICE_ATTR(scheme_0, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_1, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_2, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_3, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_4, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_5, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_6, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_7, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_8, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_9, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_10, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_11, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_12, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_13, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_14, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_15, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_16, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_17, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_18, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_19, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_20, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_21, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_22, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_23, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_24, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_25, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_26, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_27, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_28, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_29, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_30, S_IRUGO, show_fm_schemes, NULL);
+static DEVICE_ATTR(scheme_31, S_IRUGO, show_fm_schemes, NULL);
+
+
+static struct attribute *fm_dev_stats_attributes[] = {
+ &dev_attr_enq_total_frame.attr,
+ &dev_attr_deq_total_frame.attr,
+ &dev_attr_deq_0.attr,
+ &dev_attr_deq_1.attr,
+ &dev_attr_deq_2.attr,
+ &dev_attr_deq_3.attr,
+ &dev_attr_deq_from_default.attr,
+ &dev_attr_deq_from_context.attr,
+ &dev_attr_deq_from_fd.attr,
+ &dev_attr_deq_confirm.attr,
+ &dev_attr_cmq_not_empty.attr,
+ &dev_attr_bus_error.attr,
+ &dev_attr_read_buf_ecc_error.attr,
+ &dev_attr_write_buf_ecc_sys_error.attr,
+ &dev_attr_write_buf_ecc_fm_error.attr,
+ &dev_attr_pcd_kg_total.attr,
+ &dev_attr_pcd_plcr_yellow.attr,
+ &dev_attr_pcd_plcr_red.attr,
+ &dev_attr_pcd_plcr_recolored_to_red.attr,
+ &dev_attr_pcd_plcr_recolored_to_yellow.attr,
+ &dev_attr_pcd_plcr_total.attr,
+ &dev_attr_pcd_plcr_length_mismatch.attr,
+ &dev_attr_pcd_prs_parse_dispatch.attr,
+ &dev_attr_pcd_prs_l2_parse_result_returned.attr,
+ &dev_attr_pcd_prs_l3_parse_result_returned.attr,
+ &dev_attr_pcd_prs_l4_parse_result_returned.attr,
+ &dev_attr_pcd_prs_shim_parse_result_returned.attr,
+ &dev_attr_pcd_prs_l2_parse_result_returned_with_err.attr,
+ &dev_attr_pcd_prs_l3_parse_result_returned_with_err.attr,
+ &dev_attr_pcd_prs_l4_parse_result_returned_with_err.attr,
+ &dev_attr_pcd_prs_shim_parse_result_returned_with_err.attr,
+ &dev_attr_pcd_prs_soft_prs_cycles.attr,
+ &dev_attr_pcd_prs_soft_prs_stall_cycles.attr,
+ &dev_attr_pcd_prs_hard_prs_cycle_incl_stall_cycles.attr,
+ &dev_attr_pcd_prs_muram_read_cycles.attr,
+ &dev_attr_pcd_prs_muram_read_stall_cycles.attr,
+ &dev_attr_pcd_prs_muram_write_cycles.attr,
+ &dev_attr_pcd_prs_muram_write_stall_cycles.attr,
+ &dev_attr_pcd_prs_fpm_command_stall_cycles.attr,
+ NULL
+};
+
+static struct attribute *fm_dev_tnums_dbg_attributes[] = {
+ &dev_attr_tnum_dbg_0.attr,
+ &dev_attr_tnum_dbg_16.attr,
+ &dev_attr_tnum_dbg_32.attr,
+ &dev_attr_tnum_dbg_48.attr,
+ &dev_attr_tnum_dbg_64.attr,
+ &dev_attr_tnum_dbg_80.attr,
+ &dev_attr_tnum_dbg_96.attr,
+ &dev_attr_tnum_dbg_112.attr,
+ NULL
+};
+
+static struct attribute *fm_dev_cls_plans_attributes[] = {
+ &dev_attr_cls_plan_0.attr,
+ &dev_attr_cls_plan_1.attr,
+ &dev_attr_cls_plan_2.attr,
+ &dev_attr_cls_plan_3.attr,
+ &dev_attr_cls_plan_4.attr,
+ &dev_attr_cls_plan_5.attr,
+ &dev_attr_cls_plan_6.attr,
+ &dev_attr_cls_plan_7.attr,
+ &dev_attr_cls_plan_8.attr,
+ &dev_attr_cls_plan_9.attr,
+ &dev_attr_cls_plan_10.attr,
+ &dev_attr_cls_plan_11.attr,
+ &dev_attr_cls_plan_12.attr,
+ &dev_attr_cls_plan_13.attr,
+ &dev_attr_cls_plan_14.attr,
+ &dev_attr_cls_plan_15.attr,
+ &dev_attr_cls_plan_16.attr,
+ &dev_attr_cls_plan_17.attr,
+ &dev_attr_cls_plan_18.attr,
+ &dev_attr_cls_plan_19.attr,
+ &dev_attr_cls_plan_20.attr,
+ &dev_attr_cls_plan_21.attr,
+ &dev_attr_cls_plan_22.attr,
+ &dev_attr_cls_plan_23.attr,
+ &dev_attr_cls_plan_24.attr,
+ &dev_attr_cls_plan_25.attr,
+ &dev_attr_cls_plan_26.attr,
+ &dev_attr_cls_plan_27.attr,
+ &dev_attr_cls_plan_28.attr,
+ &dev_attr_cls_plan_29.attr,
+ &dev_attr_cls_plan_30.attr,
+ &dev_attr_cls_plan_31.attr,
+ NULL
+};
+
+static struct attribute *fm_dev_profiles_attributes[] = {
+ &dev_attr_profile_0.attr,
+ &dev_attr_profile_1.attr,
+ &dev_attr_profile_2.attr,
+ &dev_attr_profile_3.attr,
+ &dev_attr_profile_4.attr,
+ &dev_attr_profile_5.attr,
+ &dev_attr_profile_6.attr,
+ &dev_attr_profile_7.attr,
+ &dev_attr_profile_8.attr,
+ &dev_attr_profile_9.attr,
+ &dev_attr_profile_10.attr,
+ &dev_attr_profile_11.attr,
+ &dev_attr_profile_12.attr,
+ &dev_attr_profile_13.attr,
+ &dev_attr_profile_14.attr,
+ &dev_attr_profile_15.attr,
+ &dev_attr_profile_16.attr,
+ &dev_attr_profile_17.attr,
+ &dev_attr_profile_18.attr,
+ &dev_attr_profile_19.attr,
+ &dev_attr_profile_20.attr,
+ &dev_attr_profile_21.attr,
+ &dev_attr_profile_22.attr,
+ &dev_attr_profile_23.attr,
+ &dev_attr_profile_24.attr,
+ &dev_attr_profile_25.attr,
+ &dev_attr_profile_26.attr,
+ &dev_attr_profile_27.attr,
+ &dev_attr_profile_28.attr,
+ &dev_attr_profile_29.attr,
+ &dev_attr_profile_30.attr,
+ &dev_attr_profile_31.attr,
+ NULL
+};
+
+static struct attribute *fm_dev_schemes_attributes[] = {
+ &dev_attr_scheme_0.attr,
+ &dev_attr_scheme_1.attr,
+ &dev_attr_scheme_2.attr,
+ &dev_attr_scheme_3.attr,
+ &dev_attr_scheme_4.attr,
+ &dev_attr_scheme_5.attr,
+ &dev_attr_scheme_6.attr,
+ &dev_attr_scheme_7.attr,
+ &dev_attr_scheme_8.attr,
+ &dev_attr_scheme_9.attr,
+ &dev_attr_scheme_10.attr,
+ &dev_attr_scheme_11.attr,
+ &dev_attr_scheme_12.attr,
+ &dev_attr_scheme_13.attr,
+ &dev_attr_scheme_14.attr,
+ &dev_attr_scheme_15.attr,
+ &dev_attr_scheme_16.attr,
+ &dev_attr_scheme_17.attr,
+ &dev_attr_scheme_18.attr,
+ &dev_attr_scheme_19.attr,
+ &dev_attr_scheme_20.attr,
+ &dev_attr_scheme_21.attr,
+ &dev_attr_scheme_22.attr,
+ &dev_attr_scheme_23.attr,
+ &dev_attr_scheme_24.attr,
+ &dev_attr_scheme_25.attr,
+ &dev_attr_scheme_26.attr,
+ &dev_attr_scheme_27.attr,
+ &dev_attr_scheme_28.attr,
+ &dev_attr_scheme_29.attr,
+ &dev_attr_scheme_30.attr,
+ &dev_attr_scheme_31.attr,
+ NULL
+};
+
+static const struct attribute_group fm_dev_stats_attr_grp = {
+ .name = "statistics",
+ .attrs = fm_dev_stats_attributes
+};
+
+static const struct attribute_group fm_dev_tnums_dbg_attr_grp = {
+ .name = "tnums_dbg",
+ .attrs = fm_dev_tnums_dbg_attributes
+};
+
+static const struct attribute_group fm_dev_cls_plans_attr_grp = {
+ .name = "cls_plans",
+ .attrs = fm_dev_cls_plans_attributes
+};
+
+static const struct attribute_group fm_dev_schemes_attr_grp = {
+ .name = "schemes",
+ .attrs = fm_dev_schemes_attributes
+};
+
+static const struct attribute_group fm_dev_profiles_attr_grp = {
+ .name = "profiles",
+ .attrs = fm_dev_profiles_attributes
+};
+
+static ssize_t show_fm_regs(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ unsigned long flags;
+ unsigned n = 0;
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ t_LnxWrpFmDev *p_wrp_fm_dev = NULL;
+#endif
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+
+ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_wrp_fm_dev == NULL))
+ return -EINVAL;
+
+ local_irq_save(flags);
+
+ n = snprintf(buf, PAGE_SIZE, "FM driver registers dump.\n");
+
+ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_Dev)
+ return -EIO;
+ else
+ n = fm_dump_regs(p_wrp_fm_dev->h_Dev, buf, n);
+
+ local_irq_restore(flags);
+#else
+
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE,
+ "Debug level is too low to dump registers!!!\n");
+ local_irq_restore(flags);
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+ return n;
+}
+
+static ssize_t show_fm_kg_pe_regs(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ unsigned long flags;
+ unsigned n = 0;
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ t_LnxWrpFmDev *p_wrp_fm_dev = NULL;
+#endif
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+
+ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_wrp_fm_dev == NULL))
+ return -EINVAL;
+
+ local_irq_save(flags);
+
+ n = snprintf(buf, PAGE_SIZE,
+ "\n FM-KG Port Partition Config registers dump.\n");
+
+ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_PcdDev)
+ return -EIO;
+ else
+ n = fm_kg_pe_dump_regs(p_wrp_fm_dev->h_PcdDev, buf, n);
+
+ local_irq_restore(flags);
+#else
+
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE,
+ "Debug level is too low to dump registers!!!\n");
+ local_irq_restore(flags);
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+ return n;
+}
+
+static ssize_t show_fm_kg_regs(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ unsigned long flags;
+ unsigned n = 0;
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ t_LnxWrpFmDev *p_wrp_fm_dev = NULL;
+#endif
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+
+ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_wrp_fm_dev == NULL))
+ return -EINVAL;
+
+ local_irq_save(flags);
+
+ n = snprintf(buf, PAGE_SIZE, "FM-KG registers dump.\n");
+
+ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_PcdDev)
+ return -EIO;
+ else
+ n = fm_kg_dump_regs(p_wrp_fm_dev->h_PcdDev, buf, n);
+
+ local_irq_restore(flags);
+#else
+
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE,
+ "Debug level is too low to dump registers!!!\n");
+ local_irq_restore(flags);
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+ return n;
+}
+
+
+static ssize_t show_fm_fpm_regs(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ unsigned long flags;
+ unsigned n = 0;
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ t_LnxWrpFmDev *p_wrp_fm_dev = NULL;
+#endif
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+
+ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_wrp_fm_dev == NULL))
+ return -EINVAL;
+
+ local_irq_save(flags);
+
+ n = snprintf(buf, PAGE_SIZE, "FM-FPM registers dump.\n");
+
+ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_Dev)
+ return -EIO;
+ else
+ n = fm_fpm_dump_regs(p_wrp_fm_dev->h_Dev, buf, n);
+
+ local_irq_restore(flags);
+#else
+
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE,
+ "Debug level is too low to dump registers!!!\n");
+ local_irq_restore(flags);
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+ return n;
+}
+
+static ssize_t show_prs_regs(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long flags;
+ unsigned n = 0;
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ t_LnxWrpFmDev *p_wrp_fm_dev = NULL;
+#endif
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_wrp_fm_dev == NULL))
+ return -EINVAL;
+
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE, "FM Policer registers dump.\n");
+
+ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_PcdDev)
+ return -EIO;
+ else
+ n = fm_prs_dump_regs(p_wrp_fm_dev->h_PcdDev, buf, n);
+
+ local_irq_restore(flags);
+#else
+
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE,
+ "Debug level is too low to dump registers!!!\n");
+ local_irq_restore(flags);
+
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+ return n;
+}
+
+static ssize_t show_plcr_regs(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ unsigned long flags;
+ unsigned n = 0;
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ t_LnxWrpFmDev *p_wrp_fm_dev = NULL;
+#endif
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_wrp_fm_dev == NULL))
+ return -EINVAL;
+
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE, "FM Policer registers dump.\n");
+
+ if (!p_wrp_fm_dev->active || !p_wrp_fm_dev->h_PcdDev)
+ return -EIO;
+ else
+ n = fm_plcr_dump_regs(p_wrp_fm_dev->h_PcdDev, buf, n);
+
+ local_irq_restore(flags);
+#else
+
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE,
+ "Debug level is too low to dump registers!!!\n");
+ local_irq_restore(flags);
+
+#endif /* (defined(DEBUG_ERRORS) && ... */
+
+ return n;
+}
+
+static DEVICE_ATTR(fm_regs, S_IRUGO, show_fm_regs, NULL);
+static DEVICE_ATTR(fm_fpm_regs, S_IRUGO, show_fm_fpm_regs, NULL);
+static DEVICE_ATTR(fm_kg_regs, S_IRUGO, show_fm_kg_regs, NULL);
+static DEVICE_ATTR(fm_kg_pe_regs, S_IRUGO, show_fm_kg_pe_regs, NULL);
+static DEVICE_ATTR(fm_plcr_regs, S_IRUGO, show_plcr_regs, NULL);
+static DEVICE_ATTR(fm_prs_regs, S_IRUGO, show_prs_regs, NULL);
+static DEVICE_ATTR(fm_muram_free_size, S_IRUGO, show_fm_muram_free_sz, NULL);
+static DEVICE_ATTR(fm_ctrl_code_ver, S_IRUGO, show_fm_ctrl_code_ver, NULL);
+
+int fm_sysfs_create(struct device *dev)
+{
+ t_LnxWrpFmDev *p_wrp_fm_dev = NULL;
+
+ if (dev == NULL)
+ return -EIO;
+
+ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+
+ /* store to remove them when module is disabled */
+ p_wrp_fm_dev->dev_attr_regs = &dev_attr_fm_regs;
+ p_wrp_fm_dev->dev_fm_fpm_attr_regs = &dev_attr_fm_fpm_regs;
+ p_wrp_fm_dev->dev_fm_kg_attr_regs = &dev_attr_fm_kg_regs;
+ p_wrp_fm_dev->dev_fm_kg_pe_attr_regs = &dev_attr_fm_kg_pe_regs;
+ p_wrp_fm_dev->dev_plcr_attr_regs = &dev_attr_fm_plcr_regs;
+ p_wrp_fm_dev->dev_prs_attr_regs = &dev_attr_fm_prs_regs;
+ p_wrp_fm_dev->dev_attr_muram_free_size = &dev_attr_fm_muram_free_size;
+ p_wrp_fm_dev->dev_attr_fm_ctrl_code_ver = &dev_attr_fm_ctrl_code_ver;
+
+ /* Create sysfs statistics group for FM module */
+ if (sysfs_create_group(&dev->kobj, &fm_dev_stats_attr_grp) != 0)
+ return -EIO;
+
+ if (sysfs_create_group(&dev->kobj, &fm_dev_schemes_attr_grp) != 0)
+ return -EIO;
+
+ if (sysfs_create_group(&dev->kobj, &fm_dev_profiles_attr_grp) != 0)
+ return -EIO;
+
+ if (sysfs_create_group(&dev->kobj, &fm_dev_tnums_dbg_attr_grp) != 0)
+ return -EIO;
+
+ if (sysfs_create_group(&dev->kobj, &fm_dev_cls_plans_attr_grp) != 0)
+ return -EIO;
+
+ /* Registers dump entry - in future will be moved to debugfs */
+ if (device_create_file(dev, &dev_attr_fm_regs) != 0)
+ return -EIO;
+
+ if (device_create_file(dev, &dev_attr_fm_fpm_regs) != 0)
+ return -EIO;
+
+ if (device_create_file(dev, &dev_attr_fm_kg_regs) != 0)
+ return -EIO;
+
+ if (device_create_file(dev, &dev_attr_fm_kg_pe_regs) != 0)
+ return -EIO;
+
+ if (device_create_file(dev, &dev_attr_fm_plcr_regs) != 0)
+ return -EIO;
+
+ if (device_create_file(dev, &dev_attr_fm_prs_regs) != 0)
+ return -EIO;
+
+ /* muram free size */
+ if (device_create_file(dev, &dev_attr_fm_muram_free_size) != 0)
+ return -EIO;
+
+ /* fm ctrl code version */
+ if (device_create_file(dev, &dev_attr_fm_ctrl_code_ver) != 0)
+ return -EIO;
+
+ return 0;
+}
+
+void fm_sysfs_destroy(struct device *dev)
+{
+ t_LnxWrpFmDev *p_wrp_fm_dev = NULL;
+
+ if (WARN_ON(dev == NULL))
+ return;
+
+ p_wrp_fm_dev = (t_LnxWrpFmDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_wrp_fm_dev == NULL))
+ return;
+
+ sysfs_remove_group(&dev->kobj, &fm_dev_stats_attr_grp);
+ sysfs_remove_group(&dev->kobj, &fm_dev_schemes_attr_grp);
+ sysfs_remove_group(&dev->kobj, &fm_dev_profiles_attr_grp);
+ sysfs_remove_group(&dev->kobj, &fm_dev_cls_plans_attr_grp);
+ sysfs_remove_group(&dev->kobj, &fm_dev_tnums_dbg_attr_grp);
+ device_remove_file(dev, p_wrp_fm_dev->dev_attr_regs);
+ device_remove_file(dev, p_wrp_fm_dev->dev_fm_fpm_attr_regs);
+ device_remove_file(dev, p_wrp_fm_dev->dev_fm_kg_attr_regs);
+ device_remove_file(dev, p_wrp_fm_dev->dev_fm_kg_pe_attr_regs);
+ device_remove_file(dev, p_wrp_fm_dev->dev_plcr_attr_regs);
+ device_remove_file(dev, p_wrp_fm_dev->dev_prs_attr_regs);
+ device_remove_file(dev, p_wrp_fm_dev->dev_attr_muram_free_size);
+ device_remove_file(dev, p_wrp_fm_dev->dev_attr_fm_ctrl_code_ver);
+}
+
+int fm_dump_regs(void *h_fm, char *buf, int nn)
+{
+ t_Fm *p_Fm = (t_Fm *)h_fm;
+ uint8_t i = 0;
+ int n = nn;
+
+ FM_DMP_SUBTITLE(buf, n, "\n");
+
+ FM_DMP_TITLE(buf, n, p_Fm->p_FmDmaRegs, "FM-DMA Regs");
+
+ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmsr);
+ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmemsr);
+ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmmr);
+ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmtr);
+ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmhy);
+ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmsetr);
+ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmtah);
+ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmtal);
+ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmtcid);
+ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmra);
+ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmrd);
+ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmwcr);
+ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmebcr);
+ FM_DMP_V32(buf, n, p_Fm->p_FmDmaRegs, fmdmdcr);
+
+ FM_DMP_TITLE(buf, n, &p_Fm->p_FmDmaRegs->fmdmplr, "fmdmplr");
+
+ for (i = 0; i < FM_MAX_NUM_OF_HW_PORT_IDS / 2 ; ++i)
+ FM_DMP_MEM_32(buf, n, &p_Fm->p_FmDmaRegs->fmdmplr[i]);
+
+ FM_DMP_TITLE(buf, n, p_Fm->p_FmBmiRegs, "FM-BMI COMMON Regs");
+ FM_DMP_V32(buf, n, p_Fm->p_FmBmiRegs, fmbm_init);
+ FM_DMP_V32(buf, n, p_Fm->p_FmBmiRegs, fmbm_cfg1);
+ FM_DMP_V32(buf, n, p_Fm->p_FmBmiRegs, fmbm_cfg2);
+ FM_DMP_V32(buf, n, p_Fm->p_FmBmiRegs, fmbm_ievr);
+ FM_DMP_V32(buf, n, p_Fm->p_FmBmiRegs, fmbm_ier);
+
+ FM_DMP_TITLE(buf, n, &p_Fm->p_FmBmiRegs->fmbm_arb, "fmbm_arb");
+ for (i = 0; i < 8 ; ++i)
+ FM_DMP_MEM_32(buf, n, &p_Fm->p_FmBmiRegs->fmbm_arb[i]);
+
+ FM_DMP_TITLE(buf, n, p_Fm->p_FmQmiRegs, "FM-QMI COMMON Regs");
+ FM_DMP_V32(buf, n, p_Fm->p_FmQmiRegs, fmqm_gc);
+ FM_DMP_V32(buf, n, p_Fm->p_FmQmiRegs, fmqm_eie);
+ FM_DMP_V32(buf, n, p_Fm->p_FmQmiRegs, fmqm_eien);
+ FM_DMP_V32(buf, n, p_Fm->p_FmQmiRegs, fmqm_eif);
+ FM_DMP_V32(buf, n, p_Fm->p_FmQmiRegs, fmqm_ie);
+ FM_DMP_V32(buf, n, p_Fm->p_FmQmiRegs, fmqm_ien);
+ FM_DMP_V32(buf, n, p_Fm->p_FmQmiRegs, fmqm_if);
+ FM_DMP_V32(buf, n, p_Fm->p_FmQmiRegs, fmqm_gs);
+ FM_DMP_V32(buf, n, p_Fm->p_FmQmiRegs, fmqm_etfc);
+
+ return n;
+}
+
+int fm_dump_tnum_dbg(void *h_fm, int tn_s, int tn_e, char *buf, int nn)
+{
+ t_Fm *p_Fm = (t_Fm *)h_fm;
+ uint8_t i, j = 0;
+ int n = nn;
+
+ FM_DMP_TITLE(buf, n, NULL, "Tnums and Tnum dbg regs %d - %d",
+ tn_s, tn_e);
+
+ iowrite32be(tn_s << 24, &p_Fm->p_FmFpmRegs->fmfp_dra);
+
+ mb();
+
+ for (j = tn_s; j <= tn_e; j++) {
+ FM_DMP_LN(buf, n, "> fmfp_ts[%d]\n", j);
+ FM_DMP_MEM_32(buf, n, &p_Fm->p_FmFpmRegs->fmfp_ts[j]);
+ FM_DMP_V32(buf, n, p_Fm->p_FmFpmRegs, fmfp_dra);
+ FM_DMP_LN(buf, n, "> fmfp_drd[0-3]\n");
+
+ for (i = 0; i < 4 ; ++i)
+ FM_DMP_MEM_32(buf, n, &p_Fm->p_FmFpmRegs->fmfp_drd[i]);
+
+ FM_DMP_LN(buf, n, "\n");
+
+ }
+
+ return n;
+}
+
+int fm_dump_cls_plan(void *h_fm_pcd, int cpn, char *buf, int nn)
+{
+ t_FmPcd *p_pcd = (t_FmPcd *)h_fm_pcd;
+ int i = 0;
+ uint32_t tmp;
+ unsigned long i_flg;
+ int n = nn;
+ u_FmPcdKgIndirectAccessRegs *idac;
+ spinlock_t *p_lk;
+
+ p_lk = (spinlock_t *)p_pcd->p_FmPcdKg->h_HwSpinlock;
+ idac = p_pcd->p_FmPcdKg->p_IndirectAccessRegs;
+
+ spin_lock_irqsave(p_lk, i_flg);
+
+ /* Read ClsPlan Block Action Regs */
+ tmp = (uint32_t)(FM_KG_KGAR_GO |
+ FM_KG_KGAR_READ |
+ FM_PCD_KG_KGAR_SEL_CLS_PLAN_ENTRY |
+ DUMMY_PORT_ID |
+ ((uint32_t)cpn << FM_PCD_KG_KGAR_NUM_SHIFT) |
+ FM_PCD_KG_KGAR_WSEL_MASK);
+
+ if (fman_kg_write_ar_wait(p_pcd->p_FmPcdKg->p_FmPcdKgRegs, tmp)) {
+ FM_DMP_LN(buf, nn, "Keygen scheme access violation");
+ spin_unlock_irqrestore(p_lk, i_flg);
+ return nn;
+ }
+ FM_DMP_TITLE(buf, n, &idac->clsPlanRegs,
+ "ClsPlan %d Indirect Access Regs", cpn);
+
+ for (i = 0; i < 8; i++)
+ FM_DMP_MEM_32(buf, n, &idac->clsPlanRegs.kgcpe[i]);
+
+ spin_unlock_irqrestore(p_lk, i_flg);
+
+ return n;
+}
+
+int fm_profile_dump_regs(void *h_fm_pcd, int ppn, char *buf, int nn)
+{
+ t_FmPcd *p_pcd = (t_FmPcd *)h_fm_pcd;
+ t_FmPcdPlcrProfileRegs *p_prof_regs;
+ t_FmPcdPlcrRegs *p_plcr_regs;
+ t_FmPcdPlcr *p_plcr;
+ uint32_t tmp;
+ unsigned long i_flg;
+ int n = nn;
+ int toc = 10;
+ spinlock_t *p_lk;
+
+ p_plcr = p_pcd->p_FmPcdPlcr;
+ p_prof_regs = &p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->profileRegs;
+ p_plcr_regs = p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs;
+
+ p_lk = (spinlock_t *)((t_FmPcdPlcr *)p_plcr)->h_HwSpinlock;
+
+ FM_DMP_SUBTITLE(buf, n, "\n");
+ FM_DMP_TITLE(buf, n, p_plcr_regs, "FM-PCD policer-profile regs");
+
+ tmp = (uint32_t)(FM_PCD_PLCR_PAR_GO |
+ FM_PCD_PLCR_PAR_R |
+ ((uint32_t)ppn << FM_PCD_PLCR_PAR_PNUM_SHIFT) |
+ FM_PCD_PLCR_PAR_PWSEL_MASK);
+
+ spin_lock_irqsave(p_lk, i_flg);
+
+ iowrite32be(tmp, &p_plcr_regs->fmpl_par);
+
+ mb();
+
+ /* wait for the porfile regs to be present */
+ do {
+ --toc;
+ udelay(10);
+ if (!toc) {
+ /* looks like PLCR_PAR_GO refuses to clear */
+ spin_unlock_irqrestore(p_lk, i_flg);
+ FM_DMP_LN(buf, n, "Profile regs not accessible -");
+ FM_DMP_LN(buf, n, " check profile init process\n");
+ return n;
+ }
+ } while ((ioread32be(&p_plcr_regs->fmpl_par) & FM_PCD_PLCR_PAR_GO));
+
+ FM_DMP_TITLE(buf, n, p_prof_regs, "Profile %d regs", ppn);
+
+ FM_DMP_V32(buf, n, p_prof_regs, fmpl_pemode);
+ FM_DMP_V32(buf, n, p_prof_regs, fmpl_pegnia);
+ FM_DMP_V32(buf, n, p_prof_regs, fmpl_peynia);
+ FM_DMP_V32(buf, n, p_prof_regs, fmpl_pernia);
+ FM_DMP_V32(buf, n, p_prof_regs, fmpl_pecir);
+ FM_DMP_V32(buf, n, p_prof_regs, fmpl_pecbs);
+ FM_DMP_V32(buf, n, p_prof_regs, fmpl_pepepir_eir);
+ FM_DMP_V32(buf, n, p_prof_regs, fmpl_pepbs_ebs);
+ FM_DMP_V32(buf, n, p_prof_regs, fmpl_pelts);
+ FM_DMP_V32(buf, n, p_prof_regs, fmpl_pects);
+ FM_DMP_V32(buf, n, p_prof_regs, fmpl_pepts_ets);
+ FM_DMP_V32(buf, n, p_prof_regs, fmpl_pegpc);
+ FM_DMP_V32(buf, n, p_prof_regs, fmpl_peypc);
+ FM_DMP_V32(buf, n, p_prof_regs, fmpl_perpc);
+ FM_DMP_V32(buf, n, p_prof_regs, fmpl_perypc);
+ FM_DMP_V32(buf, n, p_prof_regs, fmpl_perrpc);
+
+ spin_unlock_irqrestore(p_lk, i_flg);
+
+ return n;
+}
+
+int fm_dump_scheme(void *h_fm_pcd, int scnum, char *buf, int nn)
+{
+ t_FmPcd *p_pcd = (t_FmPcd *)h_fm_pcd;
+ uint32_t tmp_ar;
+ unsigned long i_flg;
+ int i, n = nn;
+ spinlock_t *p_lk;
+ u_FmPcdKgIndirectAccessRegs *idac;
+
+ idac = p_pcd->p_FmPcdKg->p_IndirectAccessRegs;
+ p_lk = (spinlock_t *)p_pcd->p_FmPcdKg->h_HwSpinlock;
+
+ spin_lock_irqsave(p_lk, i_flg);
+
+ tmp_ar = FmPcdKgBuildReadSchemeActionReg((uint8_t)scnum);
+ if (fman_kg_write_ar_wait(p_pcd->p_FmPcdKg->p_FmPcdKgRegs, tmp_ar)) {
+ FM_DMP_LN(buf, nn,
+ "Keygen scheme access violation or no such scheme");
+ spin_unlock_irqrestore(p_lk, i_flg);
+ return nn;
+ }
+
+ FM_DMP_TITLE(buf, n, &idac->schemeRegs,
+ "Scheme %d Indirect Access Regs", scnum);
+
+ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_mode);
+ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_ekfc);
+ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_ekdv);
+ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_bmch);
+ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_bmcl);
+ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_fqb);
+ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_hc);
+ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_ppc);
+
+ FM_DMP_TITLE(buf, n, &idac->schemeRegs.kgse_gec, "kgse_gec");
+
+ for (i = 0; i < FM_KG_NUM_OF_GENERIC_REGS; i++)
+ FM_DMP_MEM_32(buf, n, &idac->schemeRegs.kgse_gec[i]);
+
+ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_spc);
+ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_dv0);
+ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_dv1);
+ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_ccbs);
+ FM_DMP_V32(buf, n, &idac->schemeRegs, kgse_mv);
+
+ FM_DMP_SUBTITLE(buf, n, "\n");
+
+ spin_unlock_irqrestore(p_lk, i_flg);
+
+ return n;
+}
+
+int fm_kg_pe_dump_regs(void *h_fm_pcd, char *buf, int nn)
+{
+ t_FmPcd *p_pcd = (t_FmPcd *)h_fm_pcd;
+ int i = 0;
+ uint8_t prt_id = 0;
+ uint32_t tmp_ar;
+ unsigned long i_flg;
+ int n = nn;
+ u_FmPcdKgIndirectAccessRegs *idac;
+ t_FmPcdKg *p_kg;
+ spinlock_t *p_lk;
+
+ p_kg = p_pcd->p_FmPcdKg;
+ idac = p_pcd->p_FmPcdKg->p_IndirectAccessRegs;
+ p_lk = (spinlock_t *)p_kg->h_HwSpinlock;
+
+ spin_lock_irqsave(p_lk, i_flg);
+
+ FM_DMP_SUBTITLE(buf, n, "\n");
+
+ for (i = 0; i < FM_MAX_NUM_OF_PORTS; i++) {
+ SW_PORT_INDX_TO_HW_PORT_ID(prt_id, i);
+
+ tmp_ar = FmPcdKgBuildReadPortSchemeBindActionReg(prt_id);
+
+ if (fman_kg_write_ar_wait(p_kg->p_FmPcdKgRegs, tmp_ar)) {
+ FM_DMP_LN(buf, nn, "Keygen scheme access violation");
+ spin_unlock_irqrestore(p_lk, i_flg);
+ return nn;
+ }
+ FM_DMP_TITLE(buf, n, &idac->portRegs, "Port %d regs", prt_id);
+ FM_DMP_V32(buf, n, &idac->portRegs, fmkg_pe_sp);
+ FM_DMP_V32(buf, n, &idac->portRegs, fmkg_pe_cpp);
+ }
+
+ FM_DMP_SUBTITLE(buf, n, "\n");
+
+ spin_unlock_irqrestore(p_lk, i_flg);
+
+ return n;
+}
+
+int fm_kg_dump_regs(void *h_fm_pcd, char *buf, int nn)
+{
+ t_FmPcd *p_pcd = (t_FmPcd *)h_fm_pcd;
+ int n = nn;
+
+ FM_DMP_SUBTITLE(buf, n, "\n");
+ FM_DMP_TITLE(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs,
+ "FmPcdKgRegs Regs");
+
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_gcr);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_eer);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_eeer);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_seer);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_seeer);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_gsr);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_tpc);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_serc);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_fdor);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_gdv0r);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_gdv1r);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_feer);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdKg->p_FmPcdKgRegs, fmkg_ar);
+
+ FM_DMP_SUBTITLE(buf, n, "\n");
+
+ return n;
+}
+
+
+int fm_fpm_dump_regs(void *h_fm, char *buf, int nn)
+{
+ t_Fm *p_fm = (t_Fm *)h_fm;
+ uint8_t i;
+ int n = nn;
+
+ FM_DMP_SUBTITLE(buf, n, "\n");
+
+ FM_DMP_TITLE(buf, n, p_fm->p_FmFpmRegs, "FM-FPM Regs");
+
+ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_tnc);
+ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_prc);
+ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_brkc);
+ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_mxd);
+ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_dist1);
+ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_dist2);
+ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fm_epi);
+ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fm_rie);
+
+ FM_DMP_TITLE(buf, n, &p_fm->p_FmFpmRegs->fmfp_fcev, "fmfp_fcev");
+ for (i = 0; i < 4; ++i)
+ FM_DMP_MEM_32(buf, n, &p_fm->p_FmFpmRegs->fmfp_fcev[i]);
+
+ FM_DMP_TITLE(buf, n, &p_fm->p_FmFpmRegs->fmfp_cee, "fmfp_cee");
+ for (i = 0; i < 4; ++i)
+ FM_DMP_MEM_32(buf, n, &p_fm->p_FmFpmRegs->fmfp_cee[i]);
+
+ FM_DMP_SUBTITLE(buf, n, "\n");
+ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_tsc1);
+ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_tsc2);
+ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_tsp);
+ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_tsf);
+ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fm_rcr);
+ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_extc);
+ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_ext1);
+ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_ext2);
+
+ FM_DMP_SUBTITLE(buf, n, "\n");
+ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fm_ip_rev_1);
+ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fm_ip_rev_2);
+ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fm_rstc);
+ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fm_cld);
+ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fm_npi);
+ FM_DMP_V32(buf, n, p_fm->p_FmFpmRegs, fmfp_ee);
+
+ FM_DMP_TITLE(buf, n, &p_fm->p_FmFpmRegs->fmfp_cev, "fmfp_cev");
+ for (i = 0; i < 4; ++i)
+ FM_DMP_MEM_32(buf, n, &p_fm->p_FmFpmRegs->fmfp_cev[i]);
+
+ FM_DMP_TITLE(buf, n, &p_fm->p_FmFpmRegs->fmfp_ps, "fmfp_ps");
+ for (i = 0; i < 64; ++i)
+ FM_DMP_MEM_32(buf, n, &p_fm->p_FmFpmRegs->fmfp_ps[i]);
+
+ return n;
+}
+
+int fm_prs_dump_regs(void *h_fm_pcd, char *buf, int nn)
+{
+ t_FmPcd *p_pcd = (t_FmPcd *)h_fm_pcd;
+ int n = nn;
+
+ FM_DMP_SUBTITLE(buf, n, "\n");
+
+ FM_DMP_TITLE(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs,
+ "FM-PCD parser regs");
+
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_rpclim);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_rpimac);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, pmeec);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_pevr);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_pever);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_perr);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_perer);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_ppsc);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_pds);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_l2rrs);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_l3rrs);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_l4rrs);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_srrs);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_l2rres);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_l3rres);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_l4rres);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_srres);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_spcs);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_spscs);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_hxscs);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_mrcs);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_mwcs);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_mrscs);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_mwscs);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPrs->p_FmPcdPrsRegs, fmpr_fcscs);
+
+ return n;
+}
+
+int fm_plcr_dump_regs(void *h_fm_pcd, char *buf, int nn)
+{
+ t_FmPcd *p_pcd = (t_FmPcd *)h_fm_pcd;
+ int i = 0;
+ int n = nn;
+
+ FM_DMP_SUBTITLE(buf, n, "\n");
+
+ FM_DMP_TITLE(buf, n,
+ p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs,
+ "FM policer regs");
+
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_gcr);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_gsr);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_evr);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_ier);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_ifr);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_eevr);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_eier);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_eifr);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_rpcnt);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_ypcnt);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_rrpcnt);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_rypcnt);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_tpcnt);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_flmcnt);
+
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_serc);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_upcr);
+ FM_DMP_V32(buf, n, p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs, fmpl_dpmr);
+
+ FM_DMP_TITLE(buf, n,
+ &p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_pmr,
+ "fmpl_pmr");
+
+ for (i = 0; i < 64; ++i)
+ FM_DMP_MEM_32(buf, n,
+ &p_pcd->p_FmPcdPlcr->p_FmPcdPlcrRegs->fmpl_pmr[i]);
+
+ return n;
+}
+
+int fm_get_counter(void *h_fm, e_FmCounters cnt_e, uint32_t *cnt_val)
+{
+ t_Fm *p_fm = (t_Fm *)h_fm;
+
+ /* When applicable (when there is an "enable counters" bit),
+ check that counters are enabled */
+
+ switch (cnt_e) {
+ case (e_FM_COUNTERS_DEQ_1):
+ case (e_FM_COUNTERS_DEQ_2):
+ case (e_FM_COUNTERS_DEQ_3):
+ if (p_fm->p_FmStateStruct->revInfo.majorRev >= 6)
+ return -EINVAL; /* counter not available */
+
+ case (e_FM_COUNTERS_ENQ_TOTAL_FRAME):
+ case (e_FM_COUNTERS_DEQ_TOTAL_FRAME):
+ case (e_FM_COUNTERS_DEQ_0):
+ case (e_FM_COUNTERS_DEQ_FROM_DEFAULT):
+ case (e_FM_COUNTERS_DEQ_FROM_CONTEXT):
+ case (e_FM_COUNTERS_DEQ_FROM_FD):
+ case (e_FM_COUNTERS_DEQ_CONFIRM):
+ if (!(ioread32be(&p_fm->p_FmQmiRegs->fmqm_gc) &
+ QMI_CFG_EN_COUNTERS))
+ return -EINVAL; /* Requested counter not available */
+ break;
+ default:
+ break;
+ }
+
+ switch (cnt_e) {
+ case (e_FM_COUNTERS_ENQ_TOTAL_FRAME):
+ *cnt_val = ioread32be(&p_fm->p_FmQmiRegs->fmqm_etfc);
+ return 0;
+ case (e_FM_COUNTERS_DEQ_TOTAL_FRAME):
+ *cnt_val = ioread32be(&p_fm->p_FmQmiRegs->fmqm_dtfc);
+ return 0;
+ case (e_FM_COUNTERS_DEQ_0):
+ *cnt_val = ioread32be(&p_fm->p_FmQmiRegs->fmqm_dc0);
+ return 0;
+ case (e_FM_COUNTERS_DEQ_1):
+ *cnt_val = ioread32be(&p_fm->p_FmQmiRegs->fmqm_dc1);
+ return 0;
+ case (e_FM_COUNTERS_DEQ_2):
+ *cnt_val = ioread32be(&p_fm->p_FmQmiRegs->fmqm_dc2);
+ return 0;
+ case (e_FM_COUNTERS_DEQ_3):
+ *cnt_val = ioread32be(&p_fm->p_FmQmiRegs->fmqm_dc3);
+ return 0;
+ case (e_FM_COUNTERS_DEQ_FROM_DEFAULT):
+ *cnt_val = ioread32be(&p_fm->p_FmQmiRegs->fmqm_dfdc);
+ return 0;
+ case (e_FM_COUNTERS_DEQ_FROM_CONTEXT):
+ *cnt_val = ioread32be(&p_fm->p_FmQmiRegs->fmqm_dfcc);
+ return 0;
+ case (e_FM_COUNTERS_DEQ_FROM_FD):
+ *cnt_val = ioread32be(&p_fm->p_FmQmiRegs->fmqm_dffc);
+ return 0;
+ case (e_FM_COUNTERS_DEQ_CONFIRM):
+ *cnt_val = ioread32be(&p_fm->p_FmQmiRegs->fmqm_dcc);
+ return 0;
+ }
+ /* should never get here */
+ return -EINVAL; /* counter not available */
+}
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm.h b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm.h
new file mode 100644
index 0000000..e6bf83e
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef LNXWRP_SYSFS_FM_H_
+#define LNXWRP_SYSFS_FM_H_
+
+#include "lnxwrp_sysfs.h"
+
+int fm_sysfs_create(struct device *dev);
+void fm_sysfs_destroy(struct device *dev);
+int fm_dump_regs(void *h_dev, char *buf, int nn);
+int fm_fpm_dump_regs(void *h_dev, char *buf, int nn);
+int fm_kg_dump_regs(void *h_pcd, char *buf, int nn);
+int fm_kg_pe_dump_regs(void *h_pcd, char *buf, int nn);
+int fm_dump_scheme(void *h_pcd, int scnum, char *buf, int nn);
+int fm_dump_tnum_dbg(void *h_fm, int tn_s, int tn_e, char *buf, int nn);
+int fm_dump_cls_plan(void *h_pcd, int cpn, char *buf, int nn);
+int fm_plcr_dump_regs(void *h_pcd, char *buf, int nn);
+int fm_prs_dump_regs(void *h_pcd, char *buf, int nn);
+int fm_profile_dump_regs(void *h_pcd, int ppnum, char *buf, int nn);
+
+#define FM_DMP_PGSZ_ERR { \
+ snprintf(&buf[PAGE_SIZE - 80], 70, \
+ "\n Err: current sysfs buffer reached PAGE_SIZE\n");\
+ n = PAGE_SIZE - 2; \
+ }
+
+#define FM_DMP_LN(buf, n, ...) \
+ do { \
+ int k, m = n; \
+ m += k = snprintf(&buf[m], PAGE_SIZE - m, __VA_ARGS__); \
+ if (k < 0 || m > PAGE_SIZE - 90) \
+ FM_DMP_PGSZ_ERR \
+ n = m; \
+ } while (0)
+
+#define FM_DMP_TITLE(buf, n, addr, ...) \
+ do { \
+ int k, m = n; \
+ m += k = snprintf(&buf[m], PAGE_SIZE - m, "\n"); \
+ if (k < 0 || m > PAGE_SIZE - 90) \
+ FM_DMP_PGSZ_ERR \
+ m += k = snprintf(&buf[m], PAGE_SIZE - m, __VA_ARGS__); \
+ if (k < 0 || m > PAGE_SIZE - 90) \
+ FM_DMP_PGSZ_ERR \
+ if (addr) { \
+ phys_addr_t pa; \
+ pa = virt_to_phys(addr); \
+ m += k = \
+ snprintf(&buf[m], PAGE_SIZE - m, " (0x%lX)", \
+ (long unsigned int)(pa)); \
+ if (k < 0 || m > PAGE_SIZE - 90) \
+ FM_DMP_PGSZ_ERR \
+ } \
+ m += k = snprintf(&buf[m], PAGE_SIZE - m, \
+ "\n----------------------------------------\n\n"); \
+ if (k < 0 || m > PAGE_SIZE - 90) \
+ FM_DMP_PGSZ_ERR \
+ n = m; \
+ } while (0)
+
+#define FM_DMP_SUBTITLE(buf, n, ...) \
+ do { \
+ int k, m = n; \
+ m += k = snprintf(&buf[m], PAGE_SIZE - m, "------- "); \
+ if (k < 0 || m > PAGE_SIZE - 90) \
+ FM_DMP_PGSZ_ERR \
+ m += k = snprintf(&buf[m], PAGE_SIZE - m, __VA_ARGS__); \
+ if (k < 0 || m > PAGE_SIZE - 90) \
+ FM_DMP_PGSZ_ERR \
+ m += k = snprintf(&buf[m], PAGE_SIZE - m, "\n"); \
+ if (k < 0 || m > PAGE_SIZE - 90) \
+ FM_DMP_PGSZ_ERR \
+ n = m; \
+ } while (0)
+
+#define FM_DMP_MEM_32(buf, n, addr) \
+ { \
+ uint32_t val; \
+ phys_addr_t pa; \
+ int k, m = n; \
+ pa = virt_to_phys(addr); \
+ val = ioread32be((addr)); \
+ do { \
+ m += k = snprintf(&buf[m], \
+ PAGE_SIZE - m, "0x%010llX: 0x%08x\n", \
+ pa, val); \
+ if (k < 0 || m > PAGE_SIZE - 90) \
+ FM_DMP_PGSZ_ERR \
+ n += k; \
+ } while (0) ;\
+ }
+
+#define FM_DMP_V32(buf, n, st, phrase) \
+ do { \
+ int k, m = n; \
+ phys_addr_t pa = virt_to_phys(&((st)->phrase)); \
+ k = snprintf(&buf[m], PAGE_SIZE - m, \
+ "0x%010llX: 0x%08x%8s\t%s\n", pa, \
+ ioread32be((uint32_t *)&((st)->phrase)), "", #phrase); \
+ if (k < 0 || m > PAGE_SIZE - 90) \
+ FM_DMP_PGSZ_ERR \
+ n += k; \
+ } while (0)
+
+#endif /* LNXWRP_SYSFS_FM_H_ */
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.c
new file mode 100644
index 0000000..ead8c7a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.c
@@ -0,0 +1,1242 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "lnxwrp_sysfs.h"
+#include "lnxwrp_fm.h"
+#include "debug_ext.h"
+#include "lnxwrp_sysfs_fm_port.h"
+#include "lnxwrp_sysfs_fm.h"
+
+#include "../../fman/Peripherals/FM/Port/fm_port.h"
+#include "../../fman/Peripherals/FM/Port/fm_port_dsar.h"
+
+#if defined(__ERR_MODULE__)
+#undef __ERR_MODULE__
+#endif
+
+#include "../../fman/Peripherals/FM/fm.h"
+
+static const struct sysfs_stats_t portSysfsStats[] = {
+ /* RX/TX/OH common statistics */
+ {
+ .stat_name = "port_frame",
+ .stat_counter = e_FM_PORT_COUNTERS_FRAME,
+ },
+ {
+ .stat_name = "port_discard_frame",
+ .stat_counter = e_FM_PORT_COUNTERS_DISCARD_FRAME,
+ },
+ {
+ .stat_name = "port_dealloc_buf",
+ .stat_counter = e_FM_PORT_COUNTERS_DEALLOC_BUF,
+ },
+ {
+ .stat_name = "port_enq_total",
+ .stat_counter = e_FM_PORT_COUNTERS_ENQ_TOTAL,
+ },
+ /* TX/OH */
+ {
+ .stat_name = "port_length_err",
+ .stat_counter = e_FM_PORT_COUNTERS_LENGTH_ERR,
+ },
+ {
+ .stat_name = "port_unsupprted_format",
+ .stat_counter = e_FM_PORT_COUNTERS_UNSUPPRTED_FORMAT,
+ },
+ {
+ .stat_name = "port_deq_total",
+ .stat_counter = e_FM_PORT_COUNTERS_DEQ_TOTAL,
+ },
+ {
+ .stat_name = "port_deq_from_default",
+ .stat_counter = e_FM_PORT_COUNTERS_DEQ_FROM_DEFAULT,
+ },
+ {
+ .stat_name = "port_deq_confirm",
+ .stat_counter = e_FM_PORT_COUNTERS_DEQ_CONFIRM,
+ },
+ /* RX/OH */
+ {
+ .stat_name = "port_rx_bad_frame",
+ .stat_counter = e_FM_PORT_COUNTERS_RX_BAD_FRAME,
+ },
+ {
+ .stat_name = "port_rx_large_frame",
+ .stat_counter = e_FM_PORT_COUNTERS_RX_LARGE_FRAME,
+ },
+ {
+ .stat_name = "port_rx_out_of_buffers_discard",
+ .stat_counter = e_FM_PORT_COUNTERS_RX_OUT_OF_BUFFERS_DISCARD,
+ },
+ {
+ .stat_name = "port_rx_filter_frame",
+ .stat_counter = e_FM_PORT_COUNTERS_RX_FILTER_FRAME,
+ },
+ /* TODO: Particular statistics for OH ports */
+ {}
+};
+
+static ssize_t show_fm_port_stats(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev;
+ t_LnxWrpFmDev *p_LnxWrpFmDev;
+ unsigned long flags;
+ int n = 0;
+ uint8_t counter = 0;
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+ p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_LnxWrpFmPortDev == NULL))
+ return -EINVAL;
+
+ p_LnxWrpFmDev = (t_LnxWrpFmDev *) p_LnxWrpFmPortDev->h_LnxWrpFmDev;
+ if (WARN_ON(p_LnxWrpFmDev == NULL))
+ return -EINVAL;
+
+ if (!p_LnxWrpFmDev->active || !p_LnxWrpFmDev->h_Dev)
+ return -EIO;
+
+ if (!p_LnxWrpFmPortDev->h_Dev) {
+ n = snprintf(buf, PAGE_SIZE, "\tFM Port not configured...\n");
+ return n;
+ }
+
+ counter = fm_find_statistic_counter_by_name(
+ attr->attr.name,
+ portSysfsStats, NULL);
+
+ if (counter == e_FM_PORT_COUNTERS_RX_LIST_DMA_ERR) {
+ uint32_t fmRev = 0;
+ fmRev = 0xffff &
+ ioread32(UINT_TO_PTR(p_LnxWrpFmDev->fmBaseAddr +
+ 0x000c30c4));
+
+ if (fmRev == 0x0100) {
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE,
+ "counter not available for revision 1\n");
+ local_irq_restore(flags);
+ }
+ return n;
+ }
+
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE, "\t%s counter: %u\n",
+ p_LnxWrpFmPortDev->name,
+ FM_PORT_GetCounter(p_LnxWrpFmPortDev->h_Dev,
+ (e_FmPortCounters) counter));
+ local_irq_restore(flags);
+
+ return n;
+}
+
+/* FM PORT RX/TX/OH statistics */
+static DEVICE_ATTR(port_frame, S_IRUGO, show_fm_port_stats, NULL);
+static DEVICE_ATTR(port_discard_frame, S_IRUGO, show_fm_port_stats, NULL);
+static DEVICE_ATTR(port_dealloc_buf, S_IRUGO, show_fm_port_stats, NULL);
+static DEVICE_ATTR(port_enq_total, S_IRUGO, show_fm_port_stats, NULL);
+/* FM PORT TX/OH statistics */
+static DEVICE_ATTR(port_length_err, S_IRUGO, show_fm_port_stats, NULL);
+static DEVICE_ATTR(port_unsupprted_format, S_IRUGO, show_fm_port_stats, NULL);
+static DEVICE_ATTR(port_deq_total, S_IRUGO, show_fm_port_stats, NULL);
+static DEVICE_ATTR(port_deq_from_default, S_IRUGO, show_fm_port_stats, NULL);
+static DEVICE_ATTR(port_deq_confirm, S_IRUGO, show_fm_port_stats, NULL);
+/* FM PORT RX/OH statistics */
+static DEVICE_ATTR(port_rx_bad_frame, S_IRUGO, show_fm_port_stats, NULL);
+static DEVICE_ATTR(port_rx_large_frame, S_IRUGO, show_fm_port_stats, NULL);
+static DEVICE_ATTR(port_rx_out_of_buffers_discard, S_IRUGO,
+ show_fm_port_stats, NULL);
+static DEVICE_ATTR(port_rx_filter_frame, S_IRUGO, show_fm_port_stats, NULL);
+
+/* FM PORT TX statistics */
+static struct attribute *fm_tx_port_dev_stats_attributes[] = {
+ &dev_attr_port_frame.attr,
+ &dev_attr_port_discard_frame.attr,
+ &dev_attr_port_dealloc_buf.attr,
+ &dev_attr_port_enq_total.attr,
+ &dev_attr_port_length_err.attr,
+ &dev_attr_port_unsupprted_format.attr,
+ &dev_attr_port_deq_total.attr,
+ &dev_attr_port_deq_from_default.attr,
+ &dev_attr_port_deq_confirm.attr,
+ NULL
+};
+
+static const struct attribute_group fm_tx_port_dev_stats_attr_grp = {
+ .name = "statistics",
+ .attrs = fm_tx_port_dev_stats_attributes
+};
+
+/* FM PORT RX statistics */
+static struct attribute *fm_rx_port_dev_stats_attributes[] = {
+ &dev_attr_port_frame.attr,
+ &dev_attr_port_discard_frame.attr,
+ &dev_attr_port_dealloc_buf.attr,
+ &dev_attr_port_enq_total.attr,
+ &dev_attr_port_rx_bad_frame.attr,
+ &dev_attr_port_rx_large_frame.attr,
+ &dev_attr_port_rx_out_of_buffers_discard.attr,
+ &dev_attr_port_rx_filter_frame.attr,
+ NULL
+};
+
+static const struct attribute_group fm_rx_port_dev_stats_attr_grp = {
+ .name = "statistics",
+ .attrs = fm_rx_port_dev_stats_attributes
+};
+
+/* TODO: add particular OH ports statistics */
+static struct attribute *fm_oh_port_dev_stats_attributes[] = {
+ &dev_attr_port_frame.attr,
+ &dev_attr_port_discard_frame.attr,
+ &dev_attr_port_dealloc_buf.attr,
+ &dev_attr_port_enq_total.attr,
+ /*TX*/ &dev_attr_port_length_err.attr,
+ &dev_attr_port_unsupprted_format.attr,
+ &dev_attr_port_deq_total.attr,
+ &dev_attr_port_deq_from_default.attr,
+ &dev_attr_port_deq_confirm.attr,
+ /* &dev_attr_port_rx_bad_frame.attr, */
+ /* &dev_attr_port_rx_large_frame.attr, */
+ &dev_attr_port_rx_out_of_buffers_discard.attr,
+ /*&dev_attr_port_rx_filter_frame.attr, */
+ NULL
+};
+
+static const struct attribute_group fm_oh_port_dev_stats_attr_grp = {
+ .name = "statistics",
+ .attrs = fm_oh_port_dev_stats_attributes
+};
+
+static ssize_t show_fm_port_regs(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long flags;
+ unsigned n = 0;
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev =
+ (t_LnxWrpFmPortDev *) dev_get_drvdata(dev);
+#endif
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ local_irq_save(flags);
+
+ if (!p_LnxWrpFmPortDev->h_Dev) {
+ n = snprintf(buf, PAGE_SIZE, "\tFM Port not configured...\n");
+ return n;
+ } else {
+ n = snprintf(buf, PAGE_SIZE,
+ "FM port driver registers dump.\n");
+ n = fm_port_dump_regs(p_LnxWrpFmPortDev->h_Dev, buf, n);
+ }
+
+ local_irq_restore(flags);
+
+ return n;
+#else
+
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE,
+ "Debug level is too low to dump registers!!!\n");
+ local_irq_restore(flags);
+
+ return n;
+#endif
+}
+static int fm_port_dsar_dump_mem(void *h_dev, char *buf, int nn)
+{
+ t_FmPort *p_FmPort;
+ t_Fm *p_Fm;
+ uint8_t hardwarePortId;
+ uint32_t *param_page;
+ t_ArCommonDesc *ArCommonDescPtr;
+ uint32_t *mem;
+ int i, n = nn;
+
+ p_FmPort = (t_FmPort *)h_dev;
+ hardwarePortId = p_FmPort->hardwarePortId;
+ p_Fm = (t_Fm *)p_FmPort->h_Fm;
+
+ if (!FM_PORT_IsInDsar(p_FmPort))
+ {
+ FM_DMP_LN(buf, n, "port %u is not a DSAR port\n",
+ hardwarePortId);
+ return n;
+ }
+ FM_DMP_LN(buf, n, "port %u DSAR mem\n", hardwarePortId);
+ FM_DMP_LN(buf, n, "========================\n");
+
+ /* do I need request_mem_region here? */
+ param_page = ioremap(p_FmPort->fmMuramPhysBaseAddr + ioread32be(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr), 4);
+ ArCommonDescPtr = (t_ArCommonDesc*)(ioremap(p_FmPort->fmMuramPhysBaseAddr + ioread32be(param_page), sizeof(t_ArCommonDesc))); /* this should be changed*/
+ mem = (uint32_t*)ArCommonDescPtr;
+ for (i = 0; i < 100; i+=4)
+ FM_DMP_LN(buf, n, "%08x %08x %08x %08x\n", mem[i], mem[i + 1], mem[i + 2], mem[i + 3]);
+ iounmap(ArCommonDescPtr);
+ iounmap(param_page);
+ return n;
+}
+
+static int fm_port_dsar_dump_regs(void *h_dev, char *buf, int nn)
+{
+ t_FmPort *p_FmPort;
+ t_Fm *p_Fm;
+ uint8_t hardwarePortId;
+ uint32_t *param_page;
+ t_ArCommonDesc *ArCommonDescPtr;
+ int i, n = nn;
+
+ p_FmPort = (t_FmPort *)h_dev;
+ hardwarePortId = p_FmPort->hardwarePortId;
+ p_Fm = (t_Fm *)p_FmPort->h_Fm;
+
+ if (!FM_PORT_IsInDsar(p_FmPort))
+ {
+ FM_DMP_LN(buf, n, "port %u is not a DSAR port\n",
+ hardwarePortId);
+ return n;
+ }
+ FM_DMP_LN(buf, n, "port %u DSAR information\n", hardwarePortId);
+ FM_DMP_LN(buf, n, "========================\n");
+
+ /* do I need request_mem_region here? */
+ param_page = ioremap(p_FmPort->fmMuramPhysBaseAddr + ioread32be(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr), 4);
+ ArCommonDescPtr = (t_ArCommonDesc*)(ioremap(p_FmPort->fmMuramPhysBaseAddr + ioread32be(param_page), sizeof(t_ArCommonDesc))); /* this should be changed*/
+ FM_DMP_LN(buf, n, "Tx port: 0x%x\n", ArCommonDescPtr->arTxPort);
+ FM_DMP_LN(buf, n, "Active HPNIA: 0x%08x\n", ArCommonDescPtr->activeHPNIA);
+ FM_DMP_LN(buf, n, "Snmp port: 0x%x\n", ArCommonDescPtr->snmpPort);
+ FM_DMP_LN(buf, n, "MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", ArCommonDescPtr->macStationAddr[0],
+ ArCommonDescPtr->macStationAddr[1], ArCommonDescPtr->macStationAddr[2],
+ ArCommonDescPtr->macStationAddr[3], ArCommonDescPtr->macStationAddr[4],
+ ArCommonDescPtr->macStationAddr[5]);
+ FM_DMP_LN(buf, n, "filterControl: 0x%02x\n", ArCommonDescPtr->filterControl);
+ FM_DMP_LN(buf, n, "tcpControlPass: 0x%04x\n", ArCommonDescPtr->tcpControlPass);
+ FM_DMP_LN(buf, n, "ipProtocolTblSize: 0x%x\n", ArCommonDescPtr->ipProtocolTblSize);
+ FM_DMP_LN(buf, n, "udpPortTblSize: 0x%x\n", ArCommonDescPtr->udpPortTblSize);
+ FM_DMP_LN(buf, n, "tcpPortTblSize: 0x%x\n", ArCommonDescPtr->tcpPortTblSize);
+ if (ArCommonDescPtr->p_ArStats)
+ {
+ t_ArStatistics *arStatistics = (t_ArStatistics*)
+ ioremap(ioread32be(&ArCommonDescPtr->p_ArStats) +
+ p_FmPort->fmMuramPhysBaseAddr,
+ sizeof (t_ArStatistics));
+ FM_DMP_LN(buf, n, "\nDSAR statistics\n");
+ FM_DMP_LN(buf, n, "DSAR_Discarded: 0x%x\n", arStatistics->dsarDiscarded);
+ FM_DMP_LN(buf, n, "DSAR_Err_Discarded: 0x%x\n", arStatistics->dsarErrDiscarded);
+ FM_DMP_LN(buf, n, "DSAR_Frag_Discarded: 0x%x\n", arStatistics->dsarFragDiscarded);
+ FM_DMP_LN(buf, n, "DSAR_Tunnel_Discarded: 0x%x\n", arStatistics->dsarTunnelDiscarded);
+ FM_DMP_LN(buf, n, "DSAR_ARP_Discarded: 0x%x\n", arStatistics->dsarArpDiscarded);
+ FM_DMP_LN(buf, n, "DSAR_IP_Discarded: 0x%x\n", arStatistics->dsarIpDiscarded);
+ FM_DMP_LN(buf, n, "DSAR_TCP_Discarded: 0x%x\n", arStatistics->dsarTcpDiscarded);
+ FM_DMP_LN(buf, n, "DSAR_UDP_Discarded: 0x%x\n", arStatistics->dsarUdpDiscarded);
+ FM_DMP_LN(buf, n, "DSAR_ICMPv6_Checksum_Err: 0x%x\n", arStatistics->dsarIcmpV6ChecksumErr);
+ FM_DMP_LN(buf, n, "DSAR_ICMPv6_Other_Type: 0x%x\n", arStatistics->dsarIcmpV6OtherType);
+ FM_DMP_LN(buf, n, "DSAR_ICMPv4_Other_Type: 0x%x\n", arStatistics->dsarIcmpV4OtherType);
+
+ iounmap(arStatistics);
+ }
+ if (ArCommonDescPtr->p_ArpDescriptor)
+ {
+ t_DsarArpDescriptor* ArpDescriptor = (t_DsarArpDescriptor*)
+ ioremap(ioread32be(&ArCommonDescPtr->p_ArpDescriptor) +
+ p_FmPort->fmMuramPhysBaseAddr,
+ sizeof (t_DsarArpDescriptor));
+ FM_DMP_LN(buf, n, "\nARP\n");
+ FM_DMP_LN(buf, n, "===\n");
+ FM_DMP_LN(buf, n, "control bits 0x%04x\n", ArpDescriptor->control);
+ if (ArpDescriptor->numOfBindings)
+ {
+ char ip_str[20];
+ t_DsarArpBindingEntry* bindings = ioremap(
+ ioread32be(&ArpDescriptor->p_Bindings) +
+ p_FmPort->fmMuramPhysBaseAddr,
+ ArpDescriptor->numOfBindings *
+ sizeof(t_DsarArpBindingEntry));
+ uint8_t* ip_addr = (uint8_t*)&bindings->ipv4Addr;
+ FM_DMP_LN(buf, n, " ip vlan id\n");
+ for (i = 0; i < ArpDescriptor->numOfBindings; i++)
+ {
+ n += sprintf(ip_str, "%d:%d:%d:%d", ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]);
+ FM_DMP_LN(buf, n, "%-15s 0x%x\n", ip_str, bindings->vlanId);
+ }
+ iounmap(bindings);
+ }
+ if (ArpDescriptor->p_Statistics)
+ {
+ t_DsarArpStatistics* arpStats = ioremap(
+ ioread32be(&ArpDescriptor->p_Statistics) +
+ p_FmPort->fmMuramPhysBaseAddr,
+ sizeof(t_DsarArpStatistics));
+ FM_DMP_LN(buf, n, "statistics\n");
+ FM_DMP_LN(buf, n, "INVAL_CNT: 0x%x\n", arpStats->invalCnt);
+ FM_DMP_LN(buf, n, "ECHO_CNT: 0x%x\n", arpStats->echoCnt);
+ FM_DMP_LN(buf, n, "CD_CNT: 0x%x\n", arpStats->cdCnt);
+ FM_DMP_LN(buf, n, "AR_CNT: 0x%x\n", arpStats->arCnt);
+ FM_DMP_LN(buf, n, "RATM_CNT: 0x%x\n", arpStats->ratmCnt);
+ FM_DMP_LN(buf, n, "UKOP_CNT: 0x%x\n", arpStats->ukopCnt);
+ FM_DMP_LN(buf, n, "NMTP_CNT: 0x%x\n", arpStats->nmtpCnt);
+ FM_DMP_LN(buf, n, "NMVLAN_CNT: 0x%x\n", arpStats->nmVlanCnt);
+ iounmap(arpStats);
+ }
+
+ iounmap(ArpDescriptor);
+ }
+ if (ArCommonDescPtr->p_IcmpV4Descriptor)
+ {
+ t_DsarIcmpV4Descriptor* ICMPV4Descriptor =
+ (t_DsarIcmpV4Descriptor*)ioremap(ioread32be(
+ &ArCommonDescPtr->p_IcmpV4Descriptor) +
+ p_FmPort->fmMuramPhysBaseAddr,
+ sizeof (t_DsarIcmpV4Descriptor));
+ FM_DMP_LN(buf, n, "\nEcho ICMPv4\n");
+ FM_DMP_LN(buf, n, "===========\n");
+ FM_DMP_LN(buf, n, "control bits 0x%04x\n", ICMPV4Descriptor->control);
+ if (ICMPV4Descriptor->numOfBindings)
+ {
+ char ip_str[20];
+ t_DsarArpBindingEntry* bindings = ioremap(
+ ioread32be(&ICMPV4Descriptor->p_Bindings) +
+ p_FmPort->fmMuramPhysBaseAddr,
+ ICMPV4Descriptor->numOfBindings *
+ sizeof(t_DsarArpBindingEntry));
+ uint8_t* ip_addr = (uint8_t*)&bindings->ipv4Addr;
+ FM_DMP_LN(buf, n, " ip vlan id\n");
+ for (i = 0; i < ICMPV4Descriptor->numOfBindings; i++)
+ {
+ n += sprintf(ip_str, "%d:%d:%d:%d", ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]);
+ FM_DMP_LN(buf, n, "%-15s 0x%x\n", ip_str, bindings->vlanId);
+ }
+ iounmap(bindings);
+ }
+ if (ICMPV4Descriptor->p_Statistics)
+ {
+ t_DsarIcmpV4Statistics* icmpv4Stats = ioremap(
+ ioread32be(&ICMPV4Descriptor->p_Statistics) +
+ p_FmPort->fmMuramPhysBaseAddr,
+ sizeof(t_DsarIcmpV4Statistics));
+ FM_DMP_LN(buf, n, "statistics\n");
+ FM_DMP_LN(buf, n, "INVAL_CNT: 0x%x\n", icmpv4Stats->invalCnt);
+ FM_DMP_LN(buf, n, "NMVLAN_CNT: 0x%x\n", icmpv4Stats->nmVlanCnt);
+ FM_DMP_LN(buf, n, "NMIP_CNT: 0x%x\n", icmpv4Stats->nmIpCnt);
+ FM_DMP_LN(buf, n, "AR_CNT: 0x%x\n", icmpv4Stats->arCnt);
+ FM_DMP_LN(buf, n, "CSERR_CNT: 0x%x\n", icmpv4Stats->cserrCnt);
+ iounmap(icmpv4Stats);
+ }
+ iounmap(ICMPV4Descriptor);
+ }
+ if (ArCommonDescPtr->p_NdDescriptor)
+ {
+ t_DsarNdDescriptor *NDDescriptor =
+ (t_DsarNdDescriptor*)ioremap(ioread32be(
+ &ArCommonDescPtr->p_NdDescriptor) + p_FmPort->
+ fmMuramPhysBaseAddr, sizeof (t_DsarNdDescriptor));
+ FM_DMP_LN(buf, n, "\nNDP\n");
+ FM_DMP_LN(buf, n, "===\n");
+ FM_DMP_LN(buf, n, "control bits 0x%04x\n", NDDescriptor->control);
+ FM_DMP_LN(buf, n, "solicited address 0x%08x\n", NDDescriptor->solicitedAddr);
+ if (NDDescriptor->numOfBindings)
+ {
+ char ip_str[20];
+ t_DsarIcmpV6BindingEntry* bindings = ioremap(
+ ioread32be(&NDDescriptor->p_Bindings) +
+ p_FmPort->fmMuramPhysBaseAddr,
+ NDDescriptor->numOfBindings *
+ sizeof(t_DsarIcmpV6BindingEntry));
+ uint16_t* ip_addr = (uint16_t*)&bindings->ipv6Addr;
+ FM_DMP_LN(buf, n, " ip vlan id\n");
+ for (i = 0; i < NDDescriptor->numOfBindings; i++)
+ {
+ n += sprintf(ip_str, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
+ ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3],
+ ip_addr[4], ip_addr[5], ip_addr[6], ip_addr[7]);
+ FM_DMP_LN(buf, n, "%s 0x%x\n", ip_str, bindings->vlanId);
+ }
+ iounmap(bindings);
+ }
+ if (NDDescriptor->p_Statistics)
+ {
+ t_NdStatistics* ndStats = ioremap(
+ ioread32be(&NDDescriptor->p_Statistics) +
+ p_FmPort->fmMuramPhysBaseAddr,
+ sizeof(t_NdStatistics));
+ FM_DMP_LN(buf, n, "statistics\n");
+ FM_DMP_LN(buf, n, "INVAL_CNT: 0x%x\n", ndStats->invalCnt);
+ FM_DMP_LN(buf, n, "NMVLAN_CNT: 0x%x\n", ndStats->nmVlanCnt);
+ FM_DMP_LN(buf, n, "NMIP_CNT: 0x%x\n", ndStats->nmIpCnt);
+ FM_DMP_LN(buf, n, "AR_CNT: 0x%x\n", ndStats->arCnt);
+ FM_DMP_LN(buf, n, "USADVERT_CNT: 0x%x\n", ndStats->usadvertCnt);
+ FM_DMP_LN(buf, n, "NMMCAST_CNT: 0x%x\n", ndStats->nmmcastCnt);
+ FM_DMP_LN(buf, n, "NSLLA_CNT: 0x%x\n", ndStats->nsllaCnt);
+ iounmap(ndStats);
+ }
+ iounmap(NDDescriptor);
+ }
+ if (ArCommonDescPtr->p_IcmpV6Descriptor)
+ {
+ t_DsarIcmpV6Descriptor *ICMPV6Descriptor =
+ (t_DsarIcmpV6Descriptor*)ioremap(ioread32be(
+ &ArCommonDescPtr->p_IcmpV6Descriptor) + p_FmPort->
+ fmMuramPhysBaseAddr, sizeof (t_DsarIcmpV6Descriptor));
+ FM_DMP_LN(buf, n, "\nEcho ICMPv6\n");
+ FM_DMP_LN(buf, n, "===========\n");
+ FM_DMP_LN(buf, n, "control bits 0x%04x\n", ICMPV6Descriptor->control);
+ if (ICMPV6Descriptor->numOfBindings)
+ {
+ char ip_str[20];
+ t_DsarIcmpV6BindingEntry* bindings = ioremap(
+ ioread32be(&ICMPV6Descriptor->p_Bindings) +
+ p_FmPort->fmMuramPhysBaseAddr,
+ ICMPV6Descriptor->numOfBindings *
+ sizeof(t_DsarIcmpV6BindingEntry));
+ uint16_t* ip_addr = (uint16_t*)&bindings->ipv6Addr;
+ FM_DMP_LN(buf, n, " ip vlan id\n");
+ for (i = 0; i < ICMPV6Descriptor->numOfBindings; i++)
+ {
+ n += sprintf(ip_str, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
+ ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3],
+ ip_addr[4], ip_addr[5], ip_addr[6], ip_addr[7]);
+ FM_DMP_LN(buf, n, "%s 0x%x\n", ip_str, bindings->vlanId);
+ }
+ iounmap(bindings);
+ }
+ if (ICMPV6Descriptor->p_Statistics)
+ {
+ t_DsarIcmpV6Statistics* icmpv6Stats = ioremap(
+ ioread32be(&ICMPV6Descriptor->p_Statistics) +
+ p_FmPort->fmMuramPhysBaseAddr,
+ sizeof(t_DsarIcmpV6Statistics));
+ FM_DMP_LN(buf, n, "statistics\n");
+ FM_DMP_LN(buf, n, "INVAL_CNT: 0x%x\n", icmpv6Stats->invalCnt);
+ FM_DMP_LN(buf, n, "NMVLAN_CNT: 0x%x\n", icmpv6Stats->nmVlanCnt);
+ FM_DMP_LN(buf, n, "NMIP_CNT: 0x%x\n", icmpv6Stats->nmIpCnt);
+ FM_DMP_LN(buf, n, "AR_CNT: 0x%x\n", icmpv6Stats->arCnt);
+ iounmap(icmpv6Stats);
+ }
+ iounmap(ICMPV6Descriptor);
+ }
+ if (ArCommonDescPtr->p_SnmpDescriptor)
+ {
+ t_DsarSnmpDescriptor *SnmpDescriptor =
+ (t_DsarSnmpDescriptor*)ioremap(ioread32be(
+ &ArCommonDescPtr->p_SnmpDescriptor) + p_FmPort->
+ fmMuramPhysBaseAddr, sizeof (t_DsarSnmpDescriptor));
+ FM_DMP_LN(buf, n, "\nSNMP\n");
+ FM_DMP_LN(buf, n, "===========\n");
+ FM_DMP_LN(buf, n, "control bits 0x%04x\n", SnmpDescriptor->control);
+ FM_DMP_LN(buf, n, "max message length 0x%04x\n", SnmpDescriptor->maxSnmpMsgLength);
+ if (SnmpDescriptor->numOfIpv4Addresses)
+ {
+ char ip_str[20];
+ t_DsarSnmpIpv4AddrTblEntry* addrs = ioremap(
+ ioread32be(&SnmpDescriptor->p_Ipv4AddrTbl) +
+ p_FmPort->fmMuramPhysBaseAddr,
+ SnmpDescriptor->numOfIpv4Addresses *
+ sizeof(t_DsarSnmpIpv4AddrTblEntry));
+ uint8_t* ip_addr = (uint8_t*)&addrs->ipv4Addr;
+ FM_DMP_LN(buf, n, " ip vlan id\n");
+ for (i = 0; i < SnmpDescriptor->numOfIpv4Addresses; i++)
+ {
+ n += sprintf(ip_str, "%d:%d:%d:%d", ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]);
+ FM_DMP_LN(buf, n, "%-15s 0x%x\n", ip_str, addrs->vlanId);
+ }
+ iounmap(addrs);
+ }
+ if (SnmpDescriptor->p_Statistics)
+ {
+ t_DsarSnmpStatistics* snmpStats = ioremap(
+ ioread32be(&SnmpDescriptor->p_Statistics) +
+ p_FmPort->fmMuramPhysBaseAddr,
+ sizeof(t_DsarSnmpStatistics));
+ FM_DMP_LN(buf, n, "statistics\n");
+ FM_DMP_LN(buf, n, "snmpErrCnt: 0x%x\n", snmpStats->snmpErrCnt);
+ FM_DMP_LN(buf, n, "snmpCommunityErrCnt: 0x%x\n", snmpStats->snmpCommunityErrCnt);
+ FM_DMP_LN(buf, n, "snmpTotalDiscardCnt: 0x%x\n", snmpStats->snmpTotalDiscardCnt);
+ FM_DMP_LN(buf, n, "snmpGetReqCnt: 0x%x\n", snmpStats->snmpGetReqCnt);
+ FM_DMP_LN(buf, n, "snmpGetNextReqCnt: 0x%x\n", snmpStats->snmpGetNextReqCnt);
+ iounmap(snmpStats);
+ }
+ iounmap(SnmpDescriptor);
+ }
+ iounmap(ArCommonDescPtr);
+ iounmap(param_page);
+ return n;
+}
+
+static ssize_t show_fm_port_dsar_mem(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long flags;
+ unsigned n = 0;
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev =
+ (t_LnxWrpFmPortDev *) dev_get_drvdata(dev);
+#endif
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ local_irq_save(flags);
+
+ if (!p_LnxWrpFmPortDev->h_Dev) {
+ n = snprintf(buf, PAGE_SIZE, "\tFM Port not configured...\n");
+ return n;
+ } else {
+ n = snprintf(buf, PAGE_SIZE,
+ "FM port driver registers dump.\n");
+ n = fm_port_dsar_dump_mem(p_LnxWrpFmPortDev->h_Dev, buf, n);
+ }
+
+ local_irq_restore(flags);
+
+ return n;
+#else
+
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE,
+ "Debug level is too low to dump registers!!!\n");
+ local_irq_restore(flags);
+
+ return n;
+#endif
+}
+
+static ssize_t show_fm_port_dsar_regs(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long flags;
+ unsigned n = 0;
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev =
+ (t_LnxWrpFmPortDev *) dev_get_drvdata(dev);
+#endif
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ local_irq_save(flags);
+
+ if (!p_LnxWrpFmPortDev->h_Dev) {
+ n = snprintf(buf, PAGE_SIZE, "\tFM Port not configured...\n");
+ return n;
+ } else {
+ n = snprintf(buf, PAGE_SIZE,
+ "FM port driver registers dump.\n");
+ n = fm_port_dsar_dump_regs(p_LnxWrpFmPortDev->h_Dev, buf, n);
+ }
+
+ local_irq_restore(flags);
+
+ return n;
+#else
+
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE,
+ "Debug level is too low to dump registers!!!\n");
+ local_irq_restore(flags);
+
+ return n;
+#endif
+}
+
+#if (DPAA_VERSION >= 11)
+static ssize_t show_fm_port_ipv4_options(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long flags;
+ unsigned n = 0;
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev =
+ (t_LnxWrpFmPortDev *) dev_get_drvdata(dev);
+#endif
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ local_irq_save(flags);
+
+ if (!p_LnxWrpFmPortDev->h_Dev) {
+ n = snprintf(buf, PAGE_SIZE, "\tFM Port not configured...\n");
+ return n;
+ } else {
+ n = snprintf(buf, PAGE_SIZE,
+ "Counter for fragmented pkt with IP header options\n");
+ n = fm_port_dump_ipv4_opt(p_LnxWrpFmPortDev->h_Dev, buf, n);
+ }
+
+ local_irq_restore(flags);
+
+ return n;
+#else
+
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE,
+ "Debug level is too low to dump registers!!!\n");
+ local_irq_restore(flags);
+
+ return n;
+#endif
+}
+
+#endif
+
+static ssize_t show_fm_port_bmi_regs(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long flags;
+ unsigned n = 0;
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev =
+ (t_LnxWrpFmPortDev *) dev_get_drvdata(dev);
+#endif
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ local_irq_save(flags);
+
+ if (!p_LnxWrpFmPortDev->h_Dev) {
+ n = snprintf(buf, PAGE_SIZE, "\tFM Port not configured...\n");
+ return n;
+ } else {
+ n = snprintf(buf, PAGE_SIZE,
+ "FM port driver registers dump.\n");
+ n = fm_port_dump_regs_bmi(p_LnxWrpFmPortDev->h_Dev, buf, n);
+ }
+
+ local_irq_restore(flags);
+
+ return n;
+#else
+
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE,
+ "Debug level is too low to dump registers!!!\n");
+ local_irq_restore(flags);
+
+ return n;
+#endif
+}
+
+static ssize_t show_fm_port_qmi_regs(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned long flags;
+ unsigned n = 0;
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev =
+ (t_LnxWrpFmPortDev *) dev_get_drvdata(dev);
+#endif
+
+ if (attr == NULL || buf == NULL || dev == NULL)
+ return -EINVAL;
+
+#if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0))
+ local_irq_save(flags);
+
+ if (!p_LnxWrpFmPortDev->h_Dev) {
+ n = snprintf(buf, PAGE_SIZE, "\tFM Port not configured...\n");
+ return n;
+ } else {
+ n = snprintf(buf, PAGE_SIZE,
+ "FM port driver registers dump.\n");
+ n = fm_port_dump_regs_qmi(p_LnxWrpFmPortDev->h_Dev, buf, n);
+ }
+
+ local_irq_restore(flags);
+
+ return n;
+#else
+
+ local_irq_save(flags);
+ n = snprintf(buf, PAGE_SIZE,
+ "Debug level is too low to dump registers!!!\n");
+ local_irq_restore(flags);
+
+ return n;
+#endif
+}
+
+static DEVICE_ATTR(fm_port_regs, 0x644, show_fm_port_regs, NULL);
+static DEVICE_ATTR(fm_port_qmi_regs, 0x644, show_fm_port_qmi_regs, NULL);
+static DEVICE_ATTR(fm_port_bmi_regs, 0x644, show_fm_port_bmi_regs, NULL);
+#if (DPAA_VERSION >= 11)
+static DEVICE_ATTR(fm_port_ipv4_opt, 0x644, show_fm_port_ipv4_options, NULL);
+#endif
+static DEVICE_ATTR(fm_port_dsar_regs, 0x644, show_fm_port_dsar_regs, NULL);
+static DEVICE_ATTR(fm_port_dsar_mem, 0x644, show_fm_port_dsar_mem, NULL);
+
+int fm_port_sysfs_create(struct device *dev)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev;
+
+ if (dev == NULL)
+ return -EINVAL;
+
+ p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_LnxWrpFmPortDev == NULL))
+ return -EINVAL;
+
+ /* store to remove them when module is disabled */
+ p_LnxWrpFmPortDev->dev_attr_regs = &dev_attr_fm_port_regs;
+ p_LnxWrpFmPortDev->dev_attr_qmi_regs = &dev_attr_fm_port_qmi_regs;
+ p_LnxWrpFmPortDev->dev_attr_bmi_regs = &dev_attr_fm_port_bmi_regs;
+#if (DPAA_VERSION >= 11)
+ p_LnxWrpFmPortDev->dev_attr_ipv4_opt = &dev_attr_fm_port_ipv4_opt;
+#endif
+ p_LnxWrpFmPortDev->dev_attr_dsar_regs = &dev_attr_fm_port_dsar_regs;
+ p_LnxWrpFmPortDev->dev_attr_dsar_mem = &dev_attr_fm_port_dsar_mem;
+ /* Registers dump entry - in future will be moved to debugfs */
+ if (device_create_file(dev, &dev_attr_fm_port_regs) != 0)
+ return -EIO;
+ if (device_create_file(dev, &dev_attr_fm_port_qmi_regs) != 0)
+ return -EIO;
+ if (device_create_file(dev, &dev_attr_fm_port_bmi_regs) != 0)
+ return -EIO;
+#if (DPAA_VERSION >= 11)
+ if (device_create_file(dev, &dev_attr_fm_port_ipv4_opt) != 0)
+ return -EIO;
+#endif
+ if (device_create_file(dev, &dev_attr_fm_port_dsar_regs) != 0)
+ return -EIO;
+ if (device_create_file(dev, &dev_attr_fm_port_dsar_mem) != 0)
+ return -EIO;
+
+ /* FM Ports statistics */
+ switch (p_LnxWrpFmPortDev->settings.param.portType) {
+ case e_FM_PORT_TYPE_TX:
+ case e_FM_PORT_TYPE_TX_10G:
+ if (sysfs_create_group
+ (&dev->kobj, &fm_tx_port_dev_stats_attr_grp) != 0)
+ return -EIO;
+ break;
+ case e_FM_PORT_TYPE_RX:
+ case e_FM_PORT_TYPE_RX_10G:
+ if (sysfs_create_group
+ (&dev->kobj, &fm_rx_port_dev_stats_attr_grp) != 0)
+ return -EIO;
+ break;
+ case e_FM_PORT_TYPE_DUMMY:
+ case e_FM_PORT_TYPE_OH_OFFLINE_PARSING:
+ if (sysfs_create_group
+ (&dev->kobj, &fm_oh_port_dev_stats_attr_grp) != 0)
+ return -EIO;
+ break;
+ default:
+ WARN(1, "FMD: failure at %s:%d/%s()!\n", __FILE__, __LINE__,
+ __func__);
+ return -EINVAL;
+ break;
+ };
+
+ return 0;
+}
+
+void fm_port_sysfs_destroy(struct device *dev)
+{
+ t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = NULL;
+
+ /* this function has never been tested !!! */
+
+ if (WARN_ON(dev == NULL))
+ return;
+
+ p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *) dev_get_drvdata(dev);
+ if (WARN_ON(p_LnxWrpFmPortDev == NULL))
+ return;
+
+ /* The name attribute will be freed also by these 2 functions? */
+ switch (p_LnxWrpFmPortDev->settings.param.portType) {
+ case e_FM_PORT_TYPE_TX:
+ case e_FM_PORT_TYPE_TX_10G:
+ sysfs_remove_group(&dev->kobj, &fm_tx_port_dev_stats_attr_grp);
+ break;
+ case e_FM_PORT_TYPE_RX:
+ case e_FM_PORT_TYPE_RX_10G:
+ sysfs_remove_group(&dev->kobj, &fm_rx_port_dev_stats_attr_grp);
+ break;
+ case e_FM_PORT_TYPE_DUMMY:
+ case e_FM_PORT_TYPE_OH_OFFLINE_PARSING:
+ sysfs_remove_group(&dev->kobj, &fm_oh_port_dev_stats_attr_grp);
+ break;
+ default:
+ WARN(1, "FMD: failure at %s:%d/%s()!\n", __FILE__, __LINE__,
+ __func__);
+ break;
+ };
+
+ device_remove_file(dev, p_LnxWrpFmPortDev->dev_attr_regs);
+ device_remove_file(dev, p_LnxWrpFmPortDev->dev_attr_qmi_regs);
+ device_remove_file(dev, p_LnxWrpFmPortDev->dev_attr_bmi_regs);
+#if (DPAA_VERSION >= 11)
+ device_remove_file(dev, p_LnxWrpFmPortDev->dev_attr_ipv4_opt);
+#endif
+ device_remove_file(dev, p_LnxWrpFmPortDev->dev_attr_dsar_regs);
+ device_remove_file(dev, p_LnxWrpFmPortDev->dev_attr_dsar_mem);
+}
+
+
+int fm_port_dump_regs(void *h_dev, char *buf, int nn)
+{
+ t_FmPort *p_FmPort;
+ t_Fm *p_Fm;
+ uint8_t hardwarePortId;
+ int n = nn;
+
+ p_FmPort = (t_FmPort *)h_dev;
+ hardwarePortId = p_FmPort->hardwarePortId;
+ p_Fm = (t_Fm *)p_FmPort->h_Fm;
+
+ FM_DMP_TITLE(buf, n, &p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId - 1],
+ "fmbm_pp for port %u", hardwarePortId);
+ FM_DMP_MEM_32(buf, n,
+ &p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId - 1]);
+
+ FM_DMP_TITLE(buf, n, &p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId - 1],
+ "fmbm_pfs for port %u", hardwarePortId);
+ FM_DMP_MEM_32(buf, n,
+ &p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId - 1]);
+
+ FM_DMP_TITLE(buf, n,
+ &p_Fm->p_FmBmiRegs->fmbm_spliodn[hardwarePortId - 1],
+ "fmbm_spliodn for port %u", hardwarePortId);
+ FM_DMP_MEM_32(buf, n,
+ &p_Fm->p_FmBmiRegs->fmbm_spliodn[hardwarePortId - 1]);
+
+ FM_DMP_TITLE(buf, n, &p_Fm->p_FmFpmRegs->fmfp_ps[hardwarePortId],
+ "fmfp_psfor port %u", hardwarePortId);
+ FM_DMP_MEM_32(buf, n, &p_Fm->p_FmFpmRegs->fmfp_ps[hardwarePortId]);
+
+ FM_DMP_TITLE(buf, n, &p_Fm->p_FmDmaRegs->fmdmplr[hardwarePortId / 2],
+ "fmdmplrfor port %u", hardwarePortId);
+ FM_DMP_MEM_32(buf, n,
+ &p_Fm->p_FmDmaRegs->fmdmplr[hardwarePortId / 2]);
+ return n;
+}
+
+#if (DPAA_VERSION >= 11)
+
+int fm_port_dump_ipv4_opt(void *h_dev, char *buf, int nn)
+{
+ t_FmPort *p_FmPort;
+ int n = nn;
+
+ p_FmPort = (t_FmPort *)h_dev;
+
+ FM_DMP_V32(buf, n, p_FmPort->p_ParamsPage, ipfOptionsCounter);
+
+ FM_DMP_SUBTITLE(buf, n, "\n");
+
+ return n;
+}
+#endif
+
+int fm_port_dump_regs_bmi(void *h_dev, char *buf, int nn)
+{
+ t_FmPort *p_FmPort;
+ u_FmPortBmiRegs *p_bmi;
+
+ char arr[20];
+ uint8_t flag;
+ int i = 0;
+ int n = nn;
+
+ p_FmPort = (t_FmPort *)h_dev;
+ p_bmi = p_FmPort->p_FmPortBmiRegs;
+
+ memset(arr, 0, sizeof(arr));
+ switch (p_FmPort->portType) {
+ case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING):
+ strcpy(arr, "OFFLINE-PARSING");
+ flag = 0;
+ break;
+ case (e_FM_PORT_TYPE_OH_HOST_COMMAND):
+ strcpy(arr, "HOST-COMMAND");
+ flag = 0;
+ break;
+ case (e_FM_PORT_TYPE_RX):
+ strcpy(arr, "RX");
+ flag = 1;
+ break;
+ case (e_FM_PORT_TYPE_RX_10G):
+ strcpy(arr, "RX-10G");
+ flag = 1;
+ break;
+ case (e_FM_PORT_TYPE_TX):
+ strcpy(arr, "TX");
+ flag = 2;
+ break;
+ case (e_FM_PORT_TYPE_TX_10G):
+ strcpy(arr, "TX-10G");
+ flag = 2;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ FM_DMP_TITLE(buf, n, NULL,
+ "FMan-Port (%s #%d) registers:",
+ arr, p_FmPort->portId);
+
+ FM_DMP_TITLE(buf, n, p_bmi, "Bmi Port Regs");
+
+ switch (flag) {
+ case (0):
+ FM_DMP_SUBTITLE(buf, n, "\n");
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ocfg);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ost);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_oda);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_oicp);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofdne);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofne);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofca);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofpne);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_opso);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_opp);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_occb);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_oim);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofp);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofed);
+
+ FM_DMP_TITLE(buf, n,
+ &(p_bmi->ohPortBmiRegs.fmbm_oprai), "fmbm_oprai");
+ for (i = 0; i < FM_PORT_PRS_RESULT_NUM_OF_WORDS; ++i) {
+ FM_DMP_MEM_32(buf, n,
+ &(p_bmi->ohPortBmiRegs.fmbm_oprai[i]));
+ }
+ FM_DMP_SUBTITLE(buf, n, "\n");
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofqid);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_oefqid);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofsdm);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofsem);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofene);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_orlmts);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_orlmt);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ocmne);
+ {
+#ifndef FM_NO_OP_OBSERVED_POOLS
+ if (p_FmPort->fmRevInfo.majorRev == 4) {
+ FM_DMP_TITLE(buf, n,
+ &p_bmi->ohPortBmiRegs.fmbm_oebmpi,
+ "fmbm_oebmpi");
+
+ for (i = 0; i < FM_PORT_MAX_NUM_OF_OBSERVED_EXT_POOLS; ++i) {
+ FM_DMP_MEM_32(buf, n,
+ &(p_bmi->ohPortBmiRegs.fmbm_oebmpi[i]));
+ }
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ocgm);
+ }
+#endif /* !FM_NO_OP_OBSERVED_POOLS */
+ }
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ostc);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofrc);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofdc);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofledc);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofufdc);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_offc);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofwdc);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofldec);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_opc);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_opcp);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_occn);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_otuc);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_oduc);
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ofuc);
+ FM_DMP_TITLE(buf, n, &(p_bmi->ohPortBmiRegs.fmbm_odcfg),
+ "fmbm_odcfg");
+ for (i = 0; i < 3; ++i) {
+ FM_DMP_MEM_32(buf, n,
+ &(p_bmi->ohPortBmiRegs.fmbm_odcfg[i]));
+ }
+ FM_DMP_SUBTITLE(buf, n, "\n");
+
+ FM_DMP_V32(buf, n, &p_bmi->ohPortBmiRegs, fmbm_ogpr);
+ break;
+ case (1):
+ FM_DMP_SUBTITLE(buf, n, "\n");
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rcfg);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rst);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rda);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfp);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_reth);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfed);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_ricp);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rebm);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfne);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfca);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfpne);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rpso);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rpp);
+ FM_DMP_TITLE(buf, n, &(p_bmi->rxPortBmiRegs.fmbm_rprai),
+ "fmbm_rprai");
+ for (i = 0; i < FM_PORT_PRS_RESULT_NUM_OF_WORDS; ++i) {
+ FM_DMP_MEM_32(buf, n,
+ &(p_bmi->rxPortBmiRegs.fmbm_rprai[i]));
+ }
+ FM_DMP_SUBTITLE(buf, n, "\n");
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfqid);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_refqid);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfsdm);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfsem);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfene);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rcmne);
+ FM_DMP_TITLE(buf, n, &p_bmi->rxPortBmiRegs.fmbm_ebmpi,
+ "fmbm_ebmpi");
+ for (i = 0; i < FM_PORT_MAX_NUM_OF_EXT_POOLS; ++i) {
+ FM_DMP_MEM_32(buf, n,
+ &(p_bmi->rxPortBmiRegs.fmbm_ebmpi[i]));
+ }
+ FM_DMP_TITLE(buf, n, &p_bmi->rxPortBmiRegs.fmbm_acnt,
+ "fmbm_acnt");
+ for (i = 0; i < FM_PORT_MAX_NUM_OF_EXT_POOLS; ++i) {
+ FM_DMP_MEM_32(buf, n,
+ &(p_bmi->rxPortBmiRegs.fmbm_acnt[i]));
+ }
+ FM_DMP_TITLE(buf, n, &p_bmi->rxPortBmiRegs.fmbm_rcgm,
+ "fmbm_rcgm");
+ for (i = 0; i < FM_PORT_NUM_OF_CONGESTION_GRPS / 32; ++i) {
+ FM_DMP_MEM_32(buf, n,
+ &(p_bmi->rxPortBmiRegs.fmbm_rcgm[i]));
+ }
+
+ FM_DMP_SUBTITLE(buf, n, "\n");
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rmpd);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rstc);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfrc);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfbc);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rlfc);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rffc);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfcd);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfldec);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rodc);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rpc);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rpcp);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rccn);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rtuc);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rrquc);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rduc);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rfuc);
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rpac);
+ FM_DMP_TITLE(buf, n, &(p_bmi->rxPortBmiRegs.fmbm_rdcfg),
+ "fmbm_rdcfg");
+ for (i = 0; i < 3; ++i) {
+ FM_DMP_MEM_32(buf, n,
+ &(p_bmi->rxPortBmiRegs.fmbm_rdcfg[i]));
+ }
+ FM_DMP_SUBTITLE(buf, n, "\n");
+ FM_DMP_V32(buf, n, &p_bmi->rxPortBmiRegs, fmbm_rgpr);
+ break;
+ case (2):
+ FM_DMP_SUBTITLE(buf, n, "\n");
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tcfg);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tst);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tda);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfp);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfed);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_ticp);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfdne);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfca);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tcfqid);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfeqid);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfene);
+#if (DPAA_VERSION >= 11)
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfne);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tcmne);
+#endif /* (DPAA_VERSION >= 11) */
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_trlmts);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_trlmt);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tstc);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfrc);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfdc);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfledc);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfufdc);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tpc);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tpcp);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tccn);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_ttuc);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_ttcquc);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tduc);
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tfuc);
+ FM_DMP_TITLE(buf, n, &(p_bmi->txPortBmiRegs.fmbm_tdcfg),
+ "fmbm_tdcfg");
+ for (i = 0; i < 3 ; ++i) {
+ FM_DMP_MEM_32(buf, n,
+ &(p_bmi->txPortBmiRegs.fmbm_tdcfg[i]));
+ }
+ FM_DMP_SUBTITLE(buf, n, "\n");
+ FM_DMP_V32(buf, n, &p_bmi->txPortBmiRegs, fmbm_tgpr);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ FM_DMP_SUBTITLE(buf, n, "\n");
+
+ return n;
+}
+
+int fm_port_dump_regs_qmi(void *h_dev, char *buf, int nn)
+{
+ t_FmPort *p_FmPort;
+ int n = nn;
+
+ p_FmPort = (t_FmPort *)h_dev;
+
+ FM_DMP_TITLE(buf, n, p_FmPort->p_FmPortQmiRegs, "Qmi Port Regs");
+
+ FM_DMP_V32(buf, n, p_FmPort->p_FmPortQmiRegs, fmqm_pnc);
+ FM_DMP_V32(buf, n, p_FmPort->p_FmPortQmiRegs, fmqm_pns);
+ FM_DMP_V32(buf, n, p_FmPort->p_FmPortQmiRegs, fmqm_pnts);
+ FM_DMP_V32(buf, n, p_FmPort->p_FmPortQmiRegs, fmqm_pnen);
+ FM_DMP_V32(buf, n, p_FmPort->p_FmPortQmiRegs, fmqm_pnetfc);
+ FM_DMP_V32(buf, n,
+ &p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs, fmqm_pndn);
+ FM_DMP_V32(buf, n,
+ &p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs, fmqm_pndc);
+ FM_DMP_V32(buf, n,
+ &p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs, fmqm_pndtfc);
+ FM_DMP_V32(buf, n,
+ &p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs, fmqm_pndfdc);
+ FM_DMP_V32(buf, n,
+ &p_FmPort->p_FmPortQmiRegs->nonRxQmiRegs, fmqm_pndcc);
+
+ FM_DMP_SUBTITLE(buf, n, "\n");
+
+ return n;
+}
+
diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.h b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.h
new file mode 100644
index 0000000..1e7636f
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ @File lnxwrp_sysfs_fm_port.h
+
+ @Description FM port sysfs functions.
+
+*/
+
+#ifndef LNXWRP_SYSFS_FM_PORT_H_
+#define LNXWRP_SYSFS_FM_PORT_H_
+
+#include "lnxwrp_sysfs.h"
+
+int fm_port_sysfs_create(struct device *dev);
+void fm_port_sysfs_destroy(struct device *dev);
+
+int fm_port_dump_regs(void *h_dev, char *buf, int n);
+int fm_port_dump_regs_bmi(void *h_dev, char *buf, int n);
+int fm_port_dump_regs_qmi(void *h_dev, char *buf, int n);
+
+#if (DPAA_VERSION >= 11)
+int fm_port_dump_ipv4_opt(void *h_dev, char *buf, int n);
+#endif
+
+#endif /* LNXWRP_SYSFS_FM_PORT_H_ */
diff --git a/drivers/net/ethernet/freescale/fman/src/xx/Makefile b/drivers/net/ethernet/freescale/fman/src/xx/Makefile
new file mode 100644
index 0000000..1e0db57
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/xx/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for the Freescale Ethernet controllers
+#
+EXTRA_CFLAGS += -DVERSION=\"\"
+#
+#Include netcomm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+
+obj-y += fsl-ncsw-xx.o
+
+fsl-ncsw-xx-objs := xx_linux.o udivdi3.o stdlib.o \
+ module_strings.o
diff --git a/drivers/net/ethernet/freescale/fman/src/xx/module_strings.c b/drivers/net/ethernet/freescale/fman/src/xx/module_strings.c
new file mode 100644
index 0000000..98c64fb
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/xx/module_strings.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Module names for debug messages */
+const char *moduleStrings[] =
+{
+ "", /* MODULE_UNKNOWN */
+ "FM", /* MODULE_FM */
+ "FM-MURAM", /* MODULE_FM_MURAM */
+ "FM-PCD", /* MODULE_FM_PCD */
+ "FM-RTC", /* MODULE_FM_RTC */
+ "FM-MAC", /* MODULE_FM_MAC */
+ "FM-Port", /* MODULE_FM_PORT */
+ "MM", /* MODULE_MM */
+ "FM-SP" /* MODULE_FM_SP */
+};
diff --git a/drivers/net/ethernet/freescale/fman/src/xx/stdlib.c b/drivers/net/ethernet/freescale/fman/src/xx/stdlib.c
new file mode 100644
index 0000000..851bcf1
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/xx/stdlib.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*------------------------------------------------------*/
+/* */
+/* File: stdlib.c */
+/* */
+/* Description: */
+/* Standard library routines (externals) */
+/* */
+/* Modifications: */
+/* ============== */
+/* */
+/*------------------------------------------------------*/
+#include "stdlib_ext.h"
+#include "stdarg_ext.h"
+#include "ctype_ext.h"
+#include "string_ext.h"
+#include "std_ext.h"
+#include "xx_ext.h"
+
+
+#ifdef MODULE
+/**
+ * strtoul - convert a string to an uint32_t
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+uint32_t strtoul(const char *cp,char **endp,uint32_t base)
+{
+ uint32_t result = 0,value;
+
+ if (!base) {
+ base = 10;
+ if (*cp == '0') {
+ base = 8;
+ cp++;
+ if ((*cp == 'x') && isxdigit(cp[1])) {
+ cp++;
+ base = 16;
+ }
+ }
+ }
+ while (isxdigit(*cp) &&
+ (value = (uint32_t)(isdigit(*cp) ? *cp-'0' : toupper((uint8_t)(*cp))-'A'+10)) < base) {
+ result = result*base + value;
+ cp++;
+ }
+ if (endp)
+ *endp = (char *)cp;
+ return result;
+}
+
+/**
+ * strtol - convert a string to a int32_t
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+long strtol(const char *cp,char **endp,uint32_t base)
+{
+ if(*cp=='-')
+ return (long)(-strtoul(cp+1,endp,base));
+ return (long)strtoul(cp,endp,base);
+}
+
+/**
+ * strtoull - convert a string to an uint64_t
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+uint64_t strtoull(const char *cp,char **endp,uint32_t base)
+{
+ uint64_t result = 0,value;
+
+ if (!base) {
+ base = 10;
+ if (*cp == '0') {
+ base = 8;
+ cp++;
+ if ((*cp == 'x') && isxdigit(cp[1])) {
+ cp++;
+ base = 16;
+ }
+ }
+ }
+ while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
+ ? toupper((uint8_t)(*cp)) : *cp)-'A'+10) < base) {
+ result = result*base + value;
+ cp++;
+ }
+ if (endp)
+ *endp = (char *)cp;
+ return result;
+}
+
+/**
+ * strtoll - convert a string to a int64
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+long long strtoll(const char *cp,char **endp,uint32_t base)
+{
+ if(*cp=='-')
+ return (long long)(-strtoull(cp+1,endp,base));
+ return (long long)(strtoull(cp,endp,base));
+}
+
+/**
+ * atoi - convert a string to a int
+ * @s: The start of the string
+ */
+int atoi(const char *s)
+{
+ int i=0;
+ const char **tmp_s = &s;
+
+ while (isdigit(**tmp_s))
+ i = i*10 + *((*tmp_s)++) - '0';
+ return i;
+}
+
+/**
+ * strlen - Find the length of a string
+ * @s: The string to be sized
+ */
+size_t strlen(const char * s)
+{
+ const char *sc;
+
+ for (sc = s; *sc != '\0'; ++sc)
+ /* nothing */;
+
+ return sc - s;
+}
+
+/**
+ * strnlen - Find the length of a length-limited string
+ * @s: The string to be sized
+ * @count: The maximum number of bytes to search
+ */
+size_t strnlen(const char * s, size_t count)
+{
+ const char *sc;
+
+ for (sc = s; count-- && *sc != '\0'; ++sc)
+ /* nothing */;
+
+ return sc - s;
+}
+
+/**
+ * strcpy - Copy a %NUL terminated string
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ */
+char * strcpy(char * dest,const char *src)
+{
+ char *tmp = dest;
+
+ while ((*dest++ = *src++) != '\0')
+ /* nothing */;
+
+ return tmp;
+}
+#endif /* MODULE */
+
+/**
+ * strtok - Split a string into tokens
+ * @s: The string to be searched
+ * @ct: The characters to search for
+ *
+ * WARNING: strtok is deprecated, use strsep instead.
+ */
+char *___strtok;
+
+char * strtok(char * s,const char * ct)
+{
+ char *sbegin, *send;
+
+ sbegin = s ? s : ___strtok;
+ if (!sbegin) {
+ return NULL;
+ }
+ sbegin += strspn(sbegin,ct);
+ if (*sbegin == '\0') {
+ ___strtok = NULL;
+ return( NULL );
+ }
+ send = strpbrk( sbegin, ct);
+ if (send && *send != '\0')
+ *send++ = '\0';
+ ___strtok = send;
+ return (sbegin);
+}
+
+
+#ifdef MODULE
+/**
+ * strncpy - Copy a length-limited, %NUL-terminated string
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ * @count: The maximum number of bytes to copy
+ *
+ * Note that unlike userspace strncpy, this does not %NUL-pad the buffer.
+ * However, the result is not %NUL-terminated if the source exceeds
+ * @count bytes.
+ */
+char * strncpy(char * dest,const char *src,size_t count)
+{
+ char *tmp = dest;
+
+ while (count-- && (*dest++ = *src++) != '\0')
+ /* nothing */;
+
+ return tmp;
+}
+
+/**
+ * vsprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @fmt: The format string to use
+ * @args: Arguments for the format string
+ *
+ * Call this function if you are already dealing with a va_list.
+ * You probably want sprintf instead.
+ */
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+ return vsnprintf(buf, INT32_MAX, fmt, args);
+}
+#endif /* MODULE */
diff --git a/drivers/net/ethernet/freescale/fman/src/xx/udivdi3.c b/drivers/net/ethernet/freescale/fman/src/xx/udivdi3.c
new file mode 100644
index 0000000..419e27e
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/xx/udivdi3.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/version.h>
+
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+#define MODVERSIONS
+#endif
+#ifdef MODVERSIONS
+#include <config/modversions.h>
+#endif /* MODVERSIONS */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <asm/div64.h>
+
+
+#define BITS_PER_UNIT 8
+#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
+
+
+typedef unsigned int UQItype __attribute__ ((mode (QI)));
+typedef int SItype __attribute__ ((mode (SI)));
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef int DItype __attribute__ ((mode (DI)));
+typedef int word_type __attribute__ ((mode (__word__)));
+typedef unsigned int UDItype __attribute__ ((mode (DI)));
+
+struct DIstruct {SItype low, high;};
+
+typedef union
+{
+ struct DIstruct s;
+ DItype ll;
+} DIunion;
+
+
+/* bit divisor, dividend and result. dynamic precision */
+static __inline__ uint64_t _div64_64(uint64_t dividend, uint64_t divisor)
+{
+ uint32_t d = divisor;
+
+ if (divisor > 0xffffffffULL)
+ {
+ unsigned int shift = fls(divisor >> 32);
+
+ d = divisor >> shift;
+ dividend >>= shift;
+ }
+
+ /* avoid 64 bit division if possible */
+ if (dividend >> 32)
+ do_div(dividend, d);
+ else
+ dividend = (uint32_t) dividend / d;
+
+ return dividend;
+}
+
+UDItype __udivdi3 (UDItype n, UDItype d)
+{
+ return _div64_64(n, d);
+}
+
+DItype __divdi3 (DItype n, DItype d)
+{
+ DItype sign = 1;
+ if (n<0)
+ {
+ sign *= -1;
+ n *= -1;
+ }
+ if (d<0)
+ {
+ sign *= -1;
+ d *= -1;
+ }
+ return sign*_div64_64((UDItype)n, (UDItype)d);
+}
+
+UDItype __umoddi3 (UDItype n, UDItype d)
+{
+ return n-(_div64_64(n, d)*d);
+}
+
+#ifdef MODULE
+word_type __ucmpdi2 (DItype a, DItype b)
+{
+ DIunion au, bu;
+
+ au.ll = a, bu.ll = b;
+
+ if ((USItype) au.s.high < (USItype) bu.s.high)
+ return 0;
+ else if ((USItype) au.s.high > (USItype) bu.s.high)
+ return 2;
+ if ((USItype) au.s.low < (USItype) bu.s.low)
+ return 0;
+ else if ((USItype) au.s.low > (USItype) bu.s.low)
+ return 2;
+ return 1;
+}
+#endif /* MODULE */
diff --git a/drivers/net/ethernet/freescale/fman/src/xx/xx_linux.c b/drivers/net/ethernet/freescale/fman/src/xx/xx_linux.c
new file mode 100644
index 0000000..546c68b
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/src/xx/xx_linux.c
@@ -0,0 +1,910 @@
+/*
+ * Copyright 2008-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**************************************************************************//**
+ @File xx_linux.c
+
+ @Description XX routines implementation for Linux.
+*//***************************************************************************/
+#include <linux/version.h>
+
+#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
+#define MODVERSIONS
+#endif
+#ifdef MODVERSIONS
+#include <config/modversions.h>
+#endif /* MODVERSIONS */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/proc_fs.h>
+#include <linux/smp.h>
+#include <linux/of.h>
+
+#include <linux/workqueue.h>
+
+#ifdef BIGPHYSAREA_ENABLE
+#include <linux/bigphysarea.h>
+#endif /* BIGPHYSAREA_ENABLE */
+
+#include <sysdev/fsl_soc.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include <asm/string.h>
+#include <asm/byteorder.h>
+#include <asm/page.h>
+
+#include "error_ext.h"
+#include "std_ext.h"
+#include "list_ext.h"
+#include "mm_ext.h"
+#include "sys_io_ext.h"
+#include "xx.h"
+
+
+#define __ERR_MODULE__ MODULE_UNKNOWN
+
+#ifdef BIGPHYSAREA_ENABLE
+#define MAX_ALLOCATION_SIZE 128 * 1024 /* Maximum size allocated with kmalloc is 128K */
+
+
+/* TODO: large allocations => use big phys area */
+/******************************************************************************
+ * routine: get_nr_pages
+ *
+ * description:
+ * calculates the number of memory pages for a given size (in bytes)
+ *
+ * arguments:
+ * size - the number of bytes
+ *
+ * return code:
+ * The number of pages
+ *
+ *****************************************************************************/
+static __inline__ uint32_t get_nr_pages (uint32_t size)
+{
+ return (uint32_t)((size >> PAGE_SHIFT) + (size & PAGE_SHIFT ? 1 : 0));
+}
+
+static bool in_big_phys_area (uint32_t addr)
+{
+ uint32_t base, size;
+
+ bigphysarea_get_details (&base, &size);
+ return ((addr >= base) && (addr < base + size));
+}
+#endif /* BIGPHYSAREA_ENABLE */
+
+void * xx_Malloc(uint32_t n)
+{
+ void *a;
+ uint32_t flags;
+
+ flags = XX_DisableAllIntr();
+#ifdef BIGPHYSAREA_ENABLE
+ if (n >= MAX_ALLOCATION_SIZE)
+ a = (void*)bigphysarea_alloc_pages(get_nr_pages(n), 0, GFP_ATOMIC);
+ else
+#endif /* BIGPHYSAREA_ENABLE */
+ a = (void *)kmalloc((uint32_t)n, GFP_ATOMIC);
+ if (!a)
+ XX_Print("No memory for XX_Malloc\n");
+ XX_RestoreAllIntr(flags);
+
+ return a;
+}
+
+void xx_Free(void *p)
+{
+#ifdef BIGPHYSAREA_ENABLE
+ if (in_big_phys_area ((uint32_t)p))
+ bigphysarea_free_pages(p);
+ else
+#endif /* BIGPHYSAREA_ENABLE */
+ kfree(p);
+}
+
+void XX_Exit(int status)
+{
+ WARN(1, "\n\nFMD: fatal error, driver can't go on!!!\n\n");
+}
+
+#define BUF_SIZE 512
+void XX_Print(char *str, ...)
+{
+ va_list args;
+#ifdef CONFIG_SMP
+ char buf[BUF_SIZE];
+#endif /* CONFIG_SMP */
+
+ va_start(args, str);
+#ifdef CONFIG_SMP
+ if (vsnprintf (buf, BUF_SIZE, str, args) >= BUF_SIZE)
+ printk(KERN_WARNING "Illegal string to print!\n more than %d characters.\n\tString was not printed completelly.\n", BUF_SIZE);
+ printk(KERN_CRIT "cpu%d/%d: %s", get_hard_smp_processor_id(raw_smp_processor_id()), raw_smp_processor_id(), buf);
+#else
+ vprintk(str, args);
+#endif /* CONFIG_SMP */
+ va_end(args);
+}
+
+void XX_Fprint(void *file, char *str, ...)
+{
+ va_list args;
+#ifdef CONFIG_SMP
+ char buf[BUF_SIZE];
+#endif /* CONFIG_SMP */
+
+ va_start(args, str);
+#ifdef CONFIG_SMP
+ if (vsnprintf (buf, BUF_SIZE, str, args) >= BUF_SIZE)
+ printk(KERN_WARNING "Illegal string to print!\n more than %d characters.\n\tString was not printed completelly.\n", BUF_SIZE);
+ printk (KERN_CRIT "cpu%d/%d: %s",hard_smp_processor_id(), smp_processor_id(), buf);
+
+#else
+ vprintk(str, args);
+#endif /* CONFIG_SMP */
+ va_end(args);
+}
+
+#ifdef DEBUG_XX_MALLOC
+typedef void (*t_ffn)(void *);
+typedef struct {
+ t_ffn f_free;
+ void *mem;
+ char *fname;
+ int fline;
+ uint32_t size;
+ t_List node;
+} t_MemDebug;
+#define MEMDBG_OBJECT(p_List) LIST_OBJECT(p_List, t_MemDebug, node)
+
+LIST(memDbgLst);
+
+
+void * XX_MallocDebug(uint32_t size, char *fname, int line)
+{
+ void *mem;
+ t_MemDebug *p_MemDbg;
+
+ p_MemDbg = (t_MemDebug *)xx_Malloc(sizeof(t_MemDebug));
+ if (p_MemDbg == NULL)
+ return NULL;
+
+ mem = xx_Malloc(size);
+ if (mem == NULL)
+ {
+ XX_Free(p_MemDbg);
+ return NULL;
+ }
+
+ INIT_LIST(&p_MemDbg->node);
+ p_MemDbg->f_free = xx_Free;
+ p_MemDbg->mem = mem;
+ p_MemDbg->fname = fname;
+ p_MemDbg->fline = line;
+ p_MemDbg->size = size+sizeof(t_MemDebug);
+ LIST_AddToTail(&p_MemDbg->node, &memDbgLst);
+
+ return mem;
+}
+
+void * XX_MallocSmartDebug(uint32_t size,
+ int memPartitionId,
+ uint32_t align,
+ char *fname,
+ int line)
+{
+ void *mem;
+ t_MemDebug *p_MemDbg;
+
+ p_MemDbg = (t_MemDebug *)XX_Malloc(sizeof(t_MemDebug));
+ if (p_MemDbg == NULL)
+ return NULL;
+
+ mem = xx_MallocSmart((uint32_t)size, memPartitionId, align);
+ if (mem == NULL)
+ {
+ XX_Free(p_MemDbg);
+ return NULL;
+ }
+
+ INIT_LIST(&p_MemDbg->node);
+ p_MemDbg->f_free = xx_FreeSmart;
+ p_MemDbg->mem = mem;
+ p_MemDbg->fname = fname;
+ p_MemDbg->fline = line;
+ p_MemDbg->size = size+sizeof(t_MemDebug);
+ LIST_AddToTail(&p_MemDbg->node, &memDbgLst);
+
+ return mem;
+}
+
+static void debug_free(void *mem)
+{
+ t_List *p_MemDbgLh = NULL;
+ t_MemDebug *p_MemDbg;
+ bool found = FALSE;
+
+ if (LIST_IsEmpty(&memDbgLst))
+ {
+ REPORT_ERROR(MAJOR, E_ALREADY_FREE, ("Unbalanced free (0x%08x)", mem));
+ return;
+ }
+
+ LIST_FOR_EACH(p_MemDbgLh, &memDbgLst)
+ {
+ p_MemDbg = MEMDBG_OBJECT(p_MemDbgLh);
+ if (p_MemDbg->mem == mem)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ REPORT_ERROR(MAJOR, E_NOT_FOUND,
+ ("Attempt to free unallocated address (0x%08x)",mem));
+ dump_stack();
+ return;
+ }
+
+ LIST_Del(p_MemDbgLh);
+ p_MemDbg->f_free(mem);
+ p_MemDbg->f_free(p_MemDbg);
+}
+
+void XX_FreeSmart(void *p)
+{
+ debug_free(p);
+}
+
+
+void XX_Free(void *p)
+{
+ debug_free(p);
+}
+
+#else /* not DEBUG_XX_MALLOC */
+void * XX_Malloc(uint32_t size)
+{
+ return xx_Malloc(size);
+}
+
+void * XX_MallocSmart(uint32_t size, int memPartitionId, uint32_t alignment)
+{
+ return xx_MallocSmart(size,memPartitionId, alignment);
+}
+
+void XX_FreeSmart(void *p)
+{
+ xx_FreeSmart(p);
+}
+
+
+void XX_Free(void *p)
+{
+ xx_Free(p);
+}
+#endif /* not DEBUG_XX_MALLOC */
+
+
+#if (defined(REPORT_EVENTS) && (REPORT_EVENTS > 0))
+void XX_EventById(uint32_t event, t_Handle appId, uint16_t flags, char *msg)
+{
+ e_Event eventCode = (e_Event)event;
+
+ UNUSED(eventCode);
+ UNUSED(appId);
+ UNUSED(flags);
+ UNUSED(msg);
+}
+#endif /* (defined(REPORT_EVENTS) && ... */
+
+
+uint32_t XX_DisableAllIntr(void)
+{
+ unsigned long flags;
+
+#ifdef local_irq_save_nort
+ local_irq_save_nort(flags);
+#else
+ local_irq_save(flags);
+#endif
+
+ return (uint32_t)flags;
+}
+
+void XX_RestoreAllIntr(uint32_t flags)
+{
+#ifdef local_irq_restore_nort
+ local_irq_restore_nort((unsigned long)flags);
+#else
+ local_irq_restore((unsigned long)flags);
+#endif
+}
+
+t_Error XX_Call( uint32_t qid, t_Error (* f)(t_Handle), t_Handle id, t_Handle appId, uint16_t flags )
+{
+ UNUSED(qid);
+ UNUSED(appId);
+ UNUSED(flags);
+
+ return f(id);
+}
+
+int XX_IsICacheEnable(void)
+{
+ return TRUE;
+}
+
+int XX_IsDCacheEnable(void)
+{
+ return TRUE;
+}
+
+
+typedef struct {
+ t_Isr *f_Isr;
+ t_Handle handle;
+} t_InterruptHandler;
+
+
+t_Handle interruptHandlers[0x00010000];
+
+static irqreturn_t LinuxInterruptHandler (int irq, void *dev_id)
+{
+ t_InterruptHandler *p_IntrHndl = (t_InterruptHandler *)dev_id;
+ p_IntrHndl->f_Isr(p_IntrHndl->handle);
+ return IRQ_HANDLED;
+}
+
+t_Error XX_SetIntr(int irq, t_Isr *f_Isr, t_Handle handle)
+{
+ const char *device;
+ t_InterruptHandler *p_IntrHndl;
+
+ device = GetDeviceName(irq);
+ if (device == NULL)
+ RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Interrupt source - %d", irq));
+
+ p_IntrHndl = (t_InterruptHandler *)XX_Malloc(sizeof(t_InterruptHandler));
+ if (p_IntrHndl == NULL)
+ RETURN_ERROR(MAJOR, E_NO_MEMORY, NO_MSG);
+ p_IntrHndl->f_Isr = f_Isr;
+ p_IntrHndl->handle = handle;
+ interruptHandlers[irq] = p_IntrHndl;
+
+ if (request_irq(GetDeviceIrqNum(irq), LinuxInterruptHandler, 0, device, p_IntrHndl) < 0)
+ RETURN_ERROR(MAJOR, E_BUSY, ("Can't get IRQ %s\n", device));
+ disable_irq(GetDeviceIrqNum(irq));
+
+ return E_OK;
+}
+
+t_Error XX_FreeIntr(int irq)
+{
+ t_InterruptHandler *p_IntrHndl = interruptHandlers[irq];
+ free_irq(GetDeviceIrqNum(irq), p_IntrHndl);
+ XX_Free(p_IntrHndl);
+ interruptHandlers[irq] = 0;
+ return E_OK;
+}
+
+t_Error XX_EnableIntr(int irq)
+{
+ enable_irq(GetDeviceIrqNum(irq));
+ return E_OK;
+}
+
+t_Error XX_DisableIntr(int irq)
+{
+ disable_irq(GetDeviceIrqNum(irq));
+ return E_OK;
+}
+
+
+/*****************************************************************************/
+/* Tasklet Service Routines */
+/*****************************************************************************/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
+typedef struct
+{
+ t_Handle h_Data;
+ void (*f_Callback) (void *);
+ struct delayed_work dwork;
+} t_Tasklet;
+
+static void GenericTaskletCallback(struct work_struct *p_Work)
+{
+ t_Tasklet *p_Task = container_of(p_Work, t_Tasklet, dwork.work);
+
+ p_Task->f_Callback(p_Task->h_Data);
+}
+#endif /* LINUX_VERSION_CODE */
+
+
+t_TaskletHandle XX_InitTasklet (void (*routine)(void *), void *data)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ struct work_struct *p_Task;
+ p_Task = (struct work_struct *)XX_Malloc(sizeof(struct work_struct));
+ INIT_WORK(p_Task, routine, data);
+#else
+ t_Tasklet *p_Task = (t_Tasklet *)XX_Malloc(sizeof(t_Tasklet));
+ p_Task->h_Data = data;
+ p_Task->f_Callback = routine;
+ INIT_DELAYED_WORK(&p_Task->dwork, GenericTaskletCallback);
+#endif /* LINUX_VERSION_CODE */
+
+ return (t_TaskletHandle)p_Task;
+}
+
+
+void XX_FreeTasklet (t_TaskletHandle h_Tasklet)
+{
+ if (h_Tasklet)
+ XX_Free(h_Tasklet);
+}
+
+int XX_ScheduleTask(t_TaskletHandle h_Tasklet, int immediate)
+{
+ int ans;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ if (immediate)
+ ans = schedule_work(h_Tasklet);
+ else
+ ans = schedule_delayed_work(h_Tasklet, 1);
+#else
+ if (immediate)
+ ans = schedule_delayed_work(&((t_Tasklet *)h_Tasklet)->dwork, 0);
+ else
+ ans = schedule_delayed_work(&((t_Tasklet *)h_Tasklet)->dwork, HZ);
+#endif /* LINUX_VERSION_CODE */
+
+ return ans;
+}
+
+void XX_FlushScheduledTasks(void)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ flush_scheduled_tasks();
+#else
+ flush_scheduled_work();
+#endif /* LINUX_VERSION_CODE */
+}
+
+int XX_TaskletIsQueued(t_TaskletHandle h_Tasklet)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ return (int)(((struct work_struct *)h_Tasklet)->pending);
+#else
+ return (int)delayed_work_pending(&((t_Tasklet *)h_Tasklet)->dwork);
+#endif /* LINUX_VERSION_CODE */
+}
+
+void XX_SetTaskletData(t_TaskletHandle h_Tasklet, t_Handle data)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ ((struct tq_struct *)h_Tasklet)->data = data;
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ ((struct work_struct *)h_Tasklet)->data = data;
+#else
+ ((t_Tasklet *)h_Tasklet)->h_Data = data;
+#endif /* LINUX_VERSION_CODE */
+}
+
+t_Handle XX_GetTaskletData(t_TaskletHandle h_Tasklet)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ return (t_Handle)(((struct work_struct *)h_Tasklet)->data);
+#else
+ return ((t_Tasklet *)h_Tasklet)->h_Data;
+#endif /* LINUX_VERSION_CODE */
+}
+
+
+/*****************************************************************************/
+/* Spinlock Service Routines */
+/*****************************************************************************/
+
+t_Handle XX_InitSpinlock(void)
+{
+ spinlock_t *p_Spinlock = (spinlock_t *)XX_Malloc(sizeof(spinlock_t));
+ if (!p_Spinlock)
+ return NULL;
+
+ spin_lock_init(p_Spinlock);
+
+ return (t_Handle)p_Spinlock;
+}
+
+void XX_FreeSpinlock(t_Handle h_Spinlock)
+{
+ if (h_Spinlock)
+ XX_Free(h_Spinlock);
+}
+
+void XX_LockSpinlock(t_Handle h_Spinlock)
+{
+ spin_lock((spinlock_t *)h_Spinlock);
+}
+
+void XX_UnlockSpinlock(t_Handle h_Spinlock)
+{
+ spin_unlock((spinlock_t *)h_Spinlock);
+}
+
+uint32_t XX_LockIntrSpinlock(t_Handle h_Spinlock)
+{
+ unsigned long intrFlags;
+ spin_lock_irqsave((spinlock_t *)h_Spinlock, intrFlags);
+ return intrFlags;
+}
+
+void XX_UnlockIntrSpinlock(t_Handle h_Spinlock, uint32_t intrFlags)
+{
+ spin_unlock_irqrestore((spinlock_t *)h_Spinlock, (unsigned long)intrFlags);
+}
+
+
+/*****************************************************************************/
+/* Timers Service Routines */
+/*****************************************************************************/
+/* The time now is in mili sec. resolution */
+uint32_t XX_CurrentTime(void)
+{
+ return (jiffies*1000)/HZ;
+}
+
+
+t_Handle XX_CreateTimer(void)
+{
+ struct timer_list *p_Timer = (struct timer_list *)XX_Malloc(sizeof(struct timer_list));
+ if (p_Timer)
+ {
+ memset(p_Timer, 0, sizeof(struct timer_list));
+ init_timer(p_Timer);
+ }
+ return (t_Handle)p_Timer;
+}
+
+void XX_FreeTimer(t_Handle h_Timer)
+{
+ if (h_Timer)
+ XX_Free(h_Timer);
+}
+
+void XX_StartTimer(t_Handle h_Timer,
+ uint32_t msecs,
+ bool periodic,
+ void (*f_TimerExpired)(t_Handle),
+ t_Handle h_Arg)
+{
+ int tmp_jiffies = (msecs*HZ)/1000;
+ struct timer_list *p_Timer = (struct timer_list *)h_Timer;
+
+ SANITY_CHECK_RETURN((periodic == FALSE), E_NOT_SUPPORTED);
+
+ p_Timer->function = (void (*)(unsigned long))f_TimerExpired;
+ p_Timer->data = (unsigned long)h_Arg;
+ if ((msecs*HZ)%1000)
+ tmp_jiffies++;
+ p_Timer->expires = (jiffies + tmp_jiffies);
+
+ add_timer((struct timer_list *)h_Timer);
+}
+
+void XX_SetTimerData(t_Handle h_Timer, t_Handle data)
+{
+ struct timer_list *p_Timer = (struct timer_list *)h_Timer;
+
+ p_Timer->data = (unsigned long)data;
+}
+
+t_Handle XX_GetTimerData(t_Handle h_Timer)
+{
+ struct timer_list *p_Timer = (struct timer_list *)h_Timer;
+
+ return (t_Handle)p_Timer->data;
+}
+
+uint32_t XX_GetExpirationTime(t_Handle h_Timer)
+{
+ struct timer_list *p_Timer = (struct timer_list *)h_Timer;
+
+ return (uint32_t)p_Timer->expires;
+}
+
+void XX_StopTimer(t_Handle h_Timer)
+{
+ del_timer((struct timer_list *)h_Timer);
+}
+
+void XX_ModTimer(t_Handle h_Timer, uint32_t msecs)
+{
+ int tmp_jiffies = (msecs*HZ)/1000;
+
+ if ((msecs*HZ)%1000)
+ tmp_jiffies++;
+ mod_timer((struct timer_list *)h_Timer, jiffies + tmp_jiffies);
+}
+
+int XX_TimerIsActive(t_Handle h_Timer)
+{
+ return timer_pending((struct timer_list *)h_Timer);
+}
+
+uint32_t XX_Sleep(uint32_t msecs)
+{
+ int tmp_jiffies = (msecs*HZ)/1000;
+
+ if ((msecs*HZ)%1000)
+ tmp_jiffies++;
+ return schedule_timeout(tmp_jiffies);
+}
+
+/*BEWARE!!!!! UDelay routine is BUSY WAITTING!!!!!*/
+void XX_UDelay(uint32_t usecs)
+{
+ udelay(usecs);
+}
+
+/* TODO: verify that these are correct */
+#define MSG_BODY_SIZE 512
+typedef t_Error (t_MsgHandler) (t_Handle h_Mod, uint32_t msgId, uint8_t msgBody[MSG_BODY_SIZE]);
+typedef void (t_MsgCompletionCB) (t_Handle h_Arg, uint8_t msgBody[MSG_BODY_SIZE]);
+t_Error XX_SendMessage(char *p_DestAddr,
+ uint32_t msgId,
+ uint8_t msgBody[MSG_BODY_SIZE],
+ t_MsgCompletionCB *f_CompletionCB,
+ t_Handle h_CBArg);
+
+typedef struct {
+ char *p_Addr;
+ t_MsgHandler *f_MsgHandlerCB;
+ t_Handle h_Mod;
+ t_List node;
+} t_MsgHndlr;
+#define MSG_HNDLR_OBJECT(ptr) LIST_OBJECT(ptr, t_MsgHndlr, node)
+
+LIST(msgHndlrList);
+
+static void EnqueueMsgHndlr(t_MsgHndlr *p_MsgHndlr)
+{
+ uint32_t intFlags;
+
+ intFlags = XX_DisableAllIntr();
+ LIST_AddToTail(&p_MsgHndlr->node, &msgHndlrList);
+ XX_RestoreAllIntr(intFlags);
+}
+/* TODO: add this for multi-platform support
+static t_MsgHndlr * DequeueMsgHndlr(void)
+{
+ t_MsgHndlr *p_MsgHndlr = NULL;
+ uint32_t intFlags;
+
+ intFlags = XX_DisableAllIntr();
+ if (!LIST_IsEmpty(&msgHndlrList))
+ {
+ p_MsgHndlr = MSG_HNDLR_OBJECT(msgHndlrList.p_Next);
+ LIST_DelAndInit(&p_MsgHndlr->node);
+ }
+ XX_RestoreAllIntr(intFlags);
+
+ return p_MsgHndlr;
+}
+*/
+static t_MsgHndlr * FindMsgHndlr(char *p_Addr)
+{
+ t_MsgHndlr *p_MsgHndlr;
+ t_List *p_Pos;
+
+ LIST_FOR_EACH(p_Pos, &msgHndlrList)
+ {
+ p_MsgHndlr = MSG_HNDLR_OBJECT(p_Pos);
+ if (strstr(p_MsgHndlr->p_Addr, p_Addr))
+ return p_MsgHndlr;
+ }
+
+ return NULL;
+}
+
+t_Error XX_RegisterMessageHandler (char *p_Addr, t_MsgHandler *f_MsgHandlerCB, t_Handle h_Mod)
+{
+ t_MsgHndlr *p_MsgHndlr;
+ uint32_t len;
+
+ p_MsgHndlr = (t_MsgHndlr*)XX_Malloc(sizeof(t_MsgHndlr));
+ if (!p_MsgHndlr)
+ RETURN_ERROR(MINOR, E_NO_MEMORY, ("message handler object!!!"));
+ memset(p_MsgHndlr, 0, sizeof(t_MsgHndlr));
+
+ len = strlen(p_Addr);
+ p_MsgHndlr->p_Addr = (char*)XX_Malloc(len+1);
+ strncpy(p_MsgHndlr->p_Addr,p_Addr, (uint32_t)(len+1));
+
+ p_MsgHndlr->f_MsgHandlerCB = f_MsgHandlerCB;
+ p_MsgHndlr->h_Mod = h_Mod;
+ INIT_LIST(&p_MsgHndlr->node);
+ EnqueueMsgHndlr(p_MsgHndlr);
+
+ return E_OK;
+}
+
+t_Error XX_UnregisterMessageHandler (char *p_Addr)
+{
+ t_MsgHndlr *p_MsgHndlr = FindMsgHndlr(p_Addr);
+ if (!p_MsgHndlr)
+ RETURN_ERROR(MINOR, E_NO_DEVICE, ("message handler not found in list!!!"));
+
+ LIST_Del(&p_MsgHndlr->node);
+ XX_Free(p_MsgHndlr->p_Addr);
+ XX_Free(p_MsgHndlr);
+
+ return E_OK;
+}
+
+t_Error XX_SendMessage(char *p_DestAddr,
+ uint32_t msgId,
+ uint8_t msgBody[MSG_BODY_SIZE],
+ t_MsgCompletionCB *f_CompletionCB,
+ t_Handle h_CBArg)
+{
+ t_Error ans;
+ t_MsgHndlr *p_MsgHndlr = FindMsgHndlr(p_DestAddr);
+ if (!p_MsgHndlr)
+ RETURN_ERROR(MINOR, E_NO_DEVICE, ("message handler not found in list!!!"));
+
+ ans = p_MsgHndlr->f_MsgHandlerCB(p_MsgHndlr->h_Mod, msgId, msgBody);
+
+ if (f_CompletionCB)
+ f_CompletionCB(h_CBArg, msgBody);
+
+ return ans;
+}
+
+t_Error XX_IpcRegisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH],
+ t_IpcMsgHandler *f_MsgHandler,
+ t_Handle h_Module,
+ uint32_t replyLength)
+{
+ UNUSED(addr);UNUSED(f_MsgHandler);UNUSED(h_Module);UNUSED(replyLength);
+ return E_OK;
+}
+
+t_Error XX_IpcUnregisterMsgHandler(char addr[XX_IPC_MAX_ADDR_NAME_LENGTH])
+{
+ UNUSED(addr);
+ return E_OK;
+}
+
+
+t_Error XX_IpcSendMessage(t_Handle h_Session,
+ uint8_t *p_Msg,
+ uint32_t msgLength,
+ uint8_t *p_Reply,
+ uint32_t *p_ReplyLength,
+ t_IpcMsgCompletion *f_Completion,
+ t_Handle h_Arg)
+{
+ UNUSED(h_Session); UNUSED(p_Msg); UNUSED(msgLength); UNUSED(p_Reply);
+ UNUSED(p_ReplyLength); UNUSED(f_Completion); UNUSED(h_Arg);
+ return E_OK;
+}
+
+t_Handle XX_IpcInitSession(char destAddr[XX_IPC_MAX_ADDR_NAME_LENGTH],
+ char srcAddr[XX_IPC_MAX_ADDR_NAME_LENGTH])
+{
+ UNUSED(destAddr); UNUSED(srcAddr);
+ return E_OK;
+}
+
+/*Forced to introduce due to PRINT_FMT_PARAMS define*/
+uint32_t E500_GetId(void)
+{
+ return raw_smp_processor_id();
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+int GetDeviceIrqNum(int irq)
+{
+ struct device_node *iPar;
+ struct irq_domain *irqHost;
+ uint32_t hwIrq;
+
+ /* Get the interrupt controller */
+ iPar = of_find_node_by_name(NULL, "mpic");
+ hwIrq = 0;
+
+ ASSERT_COND(iPar != NULL);
+ /* Get the irq host */
+ irqHost = irq_find_host(iPar);
+ of_node_put(iPar);
+
+ /* Create irq mapping */
+ return irq_create_mapping(irqHost, hwIrq);
+}
+#else
+#error "kernel not supported!!!"
+#endif /* LINUX_VERSION_CODE */
+
+void * XX_PhysToVirt(physAddress_t addr)
+{
+ return UINT_TO_PTR(SYS_PhysToVirt((uint64_t)addr));
+}
+
+physAddress_t XX_VirtToPhys(void * addr)
+{
+ return (physAddress_t)SYS_VirtToPhys(PTR_TO_UINT(addr));
+}
+
+void * xx_MallocSmart(uint32_t size, int memPartitionId, uint32_t alignment)
+{
+ uintptr_t *returnCode, tmp;
+
+ if (alignment < sizeof(uintptr_t))
+ alignment = sizeof(uintptr_t);
+ size += alignment + sizeof(returnCode);
+ tmp = (uintptr_t)xx_Malloc(size);
+ if (tmp == 0)
+ return NULL;
+ returnCode = (uintptr_t*)((tmp + alignment + sizeof(returnCode)) & ~((uintptr_t)alignment - 1));
+ *(returnCode - 1) = tmp;
+
+ return (void*)returnCode;
+}
+
+void xx_FreeSmart(void *p)
+{
+ xx_Free((void*)(*((uintptr_t *)(p) - 1)));
+}
diff --git a/drivers/net/ethernet/freescale/fman/t4240_dflags.h b/drivers/net/ethernet/freescale/fman/t4240_dflags.h
new file mode 100644
index 0000000..435b0d2
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/t4240_dflags.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __dflags_h
+#define __dflags_h
+
+
+#define NCSW_LINUX
+
+#define T4240
+#define NCSW_PPC_CORE
+
+#define DEBUG_ERRORS 1
+
+#if defined(DEBUG)
+#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_INFO
+
+#define DEBUG_XX_MALLOC
+#define DEBUG_MEM_LEAKS
+
+#else
+#define DEBUG_GLOBAL_LEVEL REPORT_LEVEL_WARNING
+#endif /* (DEBUG) */
+
+#define REPORT_EVENTS 1
+#define EVENT_GLOBAL_LEVEL REPORT_LEVEL_MINOR
+
+#endif /* __dflags_h */
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 9fbe4dd..d1c3799 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -9,7 +9,7 @@
* Maintainer: Kumar Gala
* Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com>
*
- * Copyright 2002-2009, 2011 Freescale Semiconductor, Inc.
+ * Copyright 2002-2009, 2011-2013 Freescale Semiconductor, Inc.
* Copyright 2007 MontaVista Software, Inc.
*
* This program is free software; you can redistribute it and/or modify it
@@ -102,6 +102,10 @@
#include "gianfar.h"
+#ifdef CONFIG_AS_FASTPATH
+#include "asf_gianfar.h"
+#endif
+
#define TX_TIMEOUT (1*HZ)
const char gfar_driver_version[] = "1.3";
@@ -111,16 +115,14 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev);
static void gfar_reset_task(struct work_struct *work);
static void gfar_timeout(struct net_device *dev);
static int gfar_close(struct net_device *dev);
+static struct sk_buff *gfar_alloc_skb(struct net_device *dev);
struct sk_buff *gfar_new_skb(struct net_device *dev);
-static void gfar_new_rxbdp(struct gfar_priv_rx_q *rx_queue, struct rxbd8 *bdp,
- struct sk_buff *skb);
static int gfar_set_mac_address(struct net_device *dev);
static int gfar_change_mtu(struct net_device *dev, int new_mtu);
static irqreturn_t gfar_error(int irq, void *dev_id);
static irqreturn_t gfar_transmit(int irq, void *dev_id);
static irqreturn_t gfar_interrupt(int irq, void *dev_id);
static void adjust_link(struct net_device *dev);
-static void init_registers(struct net_device *dev);
static int init_phy(struct net_device *dev);
static int gfar_probe(struct platform_device *ofdev);
static int gfar_remove(struct platform_device *ofdev);
@@ -128,8 +130,15 @@ static void free_skb_resources(struct gfar_private *priv);
static void gfar_set_multi(struct net_device *dev);
static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
static void gfar_configure_serdes(struct net_device *dev);
-static int gfar_poll(struct napi_struct *napi, int budget);
-static int gfar_poll_sq(struct napi_struct *napi, int budget);
+static int gfar_poll_rx_sq(struct napi_struct *napi, int budget);
+static int gfar_poll_tx_sq(struct napi_struct *napi, int budget);
+#ifdef GFAR_MQ_POLLING
+static int gfar_poll_rx(struct napi_struct *napi, int budget);
+static int gfar_poll_tx(struct napi_struct *napi, int budget);
+#else
+#define gfar_poll_rx gfar_poll_rx_sq
+#define gfar_poll_tx gfar_poll_tx_sq
+#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
static void gfar_netpoll(struct net_device *dev);
#endif
@@ -137,9 +146,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit);
static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue);
static void gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
int amount_pull, struct napi_struct *napi);
-void gfar_halt(struct net_device *dev);
-static void gfar_halt_nodisable(struct net_device *dev);
-void gfar_start(struct net_device *dev);
+static void gfar_halt_nodisable(struct gfar_private *priv);
static void gfar_clear_exact_match(struct net_device *dev);
static void gfar_set_mac_for_addr(struct net_device *dev, int num,
const u8 *addr);
@@ -149,21 +156,9 @@ MODULE_AUTHOR("Freescale Semiconductor, Inc");
MODULE_DESCRIPTION("Gianfar Ethernet Driver");
MODULE_LICENSE("GPL");
-static void gfar_init_rxbdp(struct gfar_priv_rx_q *rx_queue, struct rxbd8 *bdp,
- dma_addr_t buf)
-{
- u32 lstatus;
+DEFINE_PER_CPU(struct sk_buff_head, skb_recycle_list);
- bdp->bufPtr = buf;
-
- lstatus = BD_LFLAG(RXBD_EMPTY | RXBD_INTERRUPT);
- if (bdp == rx_queue->rx_bd_base + rx_queue->rx_ring_size - 1)
- lstatus |= BD_LFLAG(RXBD_WRAP);
-
- eieio();
-
- bdp->lstatus = lstatus;
-}
+#define GFAR_RXB_REC_SZ (DEFAULT_RX_BUFFER_SIZE + RXBUF_ALIGNMENT)
static int gfar_init_bds(struct net_device *ndev)
{
@@ -209,7 +204,7 @@ static int gfar_init_bds(struct net_device *ndev)
gfar_init_rxbdp(rx_queue, rxbdp,
rxbdp->bufPtr);
} else {
- skb = gfar_new_skb(ndev);
+ skb = gfar_alloc_skb(ndev);
if (!skb) {
netdev_err(ndev, "Can't allocate RX buffers\n");
return -ENOMEM;
@@ -331,72 +326,76 @@ static void gfar_init_tx_rx_base(struct gfar_private *priv)
}
}
-static void gfar_init_mac(struct net_device *ndev)
+static void gfar_rx_buff_size_config(struct gfar_private *priv)
{
- struct gfar_private *priv = netdev_priv(ndev);
- struct gfar __iomem *regs = priv->gfargrp[0].regs;
- u32 rctrl = 0;
- u32 tctrl = 0;
- u32 attrs = 0;
-
- /* write the tx/rx base registers */
- gfar_init_tx_rx_base(priv);
-
- /* Configure the coalescing support */
- gfar_configure_coalescing_all(priv);
+ int frame_size = priv->ndev->mtu + ETH_HLEN;
/* set this when rx hw offload (TOE) functions are being used */
priv->uses_rxfcb = 0;
+ if (priv->ndev->features & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_RX))
+ priv->uses_rxfcb = 1;
+
+ if (priv->hwts_rx_en)
+ priv->uses_rxfcb = 1;
+
+ if (priv->uses_rxfcb)
+ frame_size += GMAC_FCB_LEN;
+
+ frame_size += priv->padding;
+
+ frame_size = (frame_size & ~(INCREMENTAL_BUFFER_SIZE - 1)) +
+ INCREMENTAL_BUFFER_SIZE;
+
+ priv->rx_buffer_size = frame_size;
+}
+
+static void gfar_mac_rx_config(struct gfar_private *priv)
+{
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
+ u32 rctrl = 0;
+
if (priv->rx_filer_enable) {
rctrl |= RCTRL_FILREN;
/* Program the RIR0 reg with the required distribution */
- gfar_write(&regs->rir0, DEFAULT_RIR0);
+ if (priv->poll_mode == GFAR_SQ_POLLING)
+ gfar_write(&regs->rir0, DEFAULT_2RXQ_RIR0);
+ else /* GFAR_MQ_POLLING */
+ gfar_write(&regs->rir0, DEFAULT_8RXQ_RIR0);
}
/* Restore PROMISC mode */
- if (ndev->flags & IFF_PROMISC)
+ if (priv->ndev->flags & IFF_PROMISC)
rctrl |= RCTRL_PROM;
- if (ndev->features & NETIF_F_RXCSUM) {
+ if (priv->ndev->features & NETIF_F_RXCSUM)
rctrl |= RCTRL_CHECKSUMMING;
- priv->uses_rxfcb = 1;
- }
-
- if (priv->extended_hash) {
- rctrl |= RCTRL_EXTHASH;
- gfar_clear_exact_match(ndev);
- rctrl |= RCTRL_EMEN;
- }
+ if (priv->extended_hash)
+ rctrl |= RCTRL_EXTHASH | RCTRL_EMEN;
if (priv->padding) {
rctrl &= ~RCTRL_PAL_MASK;
rctrl |= RCTRL_PADDING(priv->padding);
}
- /* Insert receive time stamps into padding alignment bytes */
- if (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) {
- rctrl &= ~RCTRL_PAL_MASK;
- rctrl |= RCTRL_PADDING(8);
- priv->padding = 8;
- }
-
/* Enable HW time stamping if requested from user space */
- if (priv->hwts_rx_en) {
+ if (priv->hwts_rx_en)
rctrl |= RCTRL_PRSDEP_INIT | RCTRL_TS_ENABLE;
- priv->uses_rxfcb = 1;
- }
- if (ndev->features & NETIF_F_HW_VLAN_CTAG_RX) {
+ if (priv->ndev->features & NETIF_F_HW_VLAN_CTAG_RX)
rctrl |= RCTRL_VLEX | RCTRL_PRSDEP_INIT;
- priv->uses_rxfcb = 1;
- }
/* Init rctrl based on our settings */
gfar_write(&regs->rctrl, rctrl);
+}
- if (ndev->features & NETIF_F_IP_CSUM)
+static void gfar_mac_tx_config(struct gfar_private *priv)
+{
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
+ u32 tctrl = 0;
+
+ if (priv->ndev->features & NETIF_F_IP_CSUM)
tctrl |= TCTRL_INIT_CSUM;
if (priv->prio_sched_en)
@@ -407,30 +406,51 @@ static void gfar_init_mac(struct net_device *ndev)
gfar_write(&regs->tr47wt, DEFAULT_WRRS_WEIGHT);
}
- gfar_write(&regs->tctrl, tctrl);
+ if (priv->ndev->features & NETIF_F_HW_VLAN_CTAG_TX)
+ tctrl |= TCTRL_VLINS;
- /* Set the extraction length and index */
- attrs = ATTRELI_EL(priv->rx_stash_size) |
- ATTRELI_EI(priv->rx_stash_index);
+ gfar_write(&regs->tctrl, tctrl);
+}
- gfar_write(&regs->attreli, attrs);
+static void gfar_configure_coalescing(struct gfar_private *priv,
+ unsigned long tx_mask, unsigned long rx_mask)
+{
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
+ u32 __iomem *baddr;
- /* Start with defaults, and add stashing or locking
- * depending on the approprate variables
- */
- attrs = ATTR_INIT_SETTINGS;
+ if (priv->mode == MQ_MG_MODE) {
+ int i = 0;
- if (priv->bd_stash_en)
- attrs |= ATTR_BDSTASH;
+ baddr = &regs->txic0;
+ for_each_set_bit(i, &tx_mask, priv->num_tx_queues) {
+ gfar_write(baddr + i, 0);
+ if (likely(priv->tx_queue[i]->txcoalescing))
+ gfar_write(baddr + i, priv->tx_queue[i]->txic);
+ }
- if (priv->rx_stash_size != 0)
- attrs |= ATTR_BUFSTASH;
+ baddr = &regs->rxic0;
+ for_each_set_bit(i, &rx_mask, priv->num_rx_queues) {
+ gfar_write(baddr + i, 0);
+ if (likely(priv->rx_queue[i]->rxcoalescing))
+ gfar_write(baddr + i, priv->rx_queue[i]->rxic);
+ }
+ } else {
+ /* Backward compatible case -- even if we enable
+ * multiple queues, there's only single reg to program
+ */
+ gfar_write(&regs->txic, 0);
+ if (likely(priv->tx_queue[0]->txcoalescing))
+ gfar_write(&regs->txic, priv->tx_queue[0]->txic);
- gfar_write(&regs->attr, attrs);
+ gfar_write(&regs->rxic, 0);
+ if (unlikely(priv->rx_queue[0]->rxcoalescing))
+ gfar_write(&regs->rxic, priv->rx_queue[0]->rxic);
+ }
+}
- gfar_write(&regs->fifo_tx_thr, priv->fifo_threshold);
- gfar_write(&regs->fifo_tx_starve, priv->fifo_starve);
- gfar_write(&regs->fifo_tx_starve_shutoff, priv->fifo_starve_off);
+void gfar_configure_coalescing_all(struct gfar_private *priv)
+{
+ gfar_configure_coalescing(priv, 0xFF, 0xFF);
}
static struct net_device_stats *gfar_get_stats(struct net_device *dev)
@@ -478,12 +498,27 @@ static const struct net_device_ops gfar_netdev_ops = {
#endif
};
-void lock_rx_qs(struct gfar_private *priv)
+static void gfar_ints_disable(struct gfar_private *priv)
{
int i;
+ for (i = 0; i < priv->num_grps; i++) {
+ struct gfar __iomem *regs = priv->gfargrp[i].regs;
+ /* Clear IEVENT */
+ gfar_write(&regs->ievent, IEVENT_INIT_CLEAR);
- for (i = 0; i < priv->num_rx_queues; i++)
- spin_lock(&priv->rx_queue[i]->rxlock);
+ /* Initialize IMASK */
+ gfar_write(&regs->imask, IMASK_INIT_CLEAR);
+ }
+}
+
+static void gfar_ints_enable(struct gfar_private *priv)
+{
+ int i;
+ for (i = 0; i < priv->num_grps; i++) {
+ struct gfar __iomem *regs = priv->gfargrp[i].regs;
+ /* Unmask the interrupts we look for */
+ gfar_write(&regs->imask, IMASK_DEFAULT);
+ }
}
void lock_tx_qs(struct gfar_private *priv)
@@ -494,23 +529,50 @@ void lock_tx_qs(struct gfar_private *priv)
spin_lock(&priv->tx_queue[i]->txlock);
}
-void unlock_rx_qs(struct gfar_private *priv)
+void unlock_tx_qs(struct gfar_private *priv)
{
int i;
- for (i = 0; i < priv->num_rx_queues; i++)
- spin_unlock(&priv->rx_queue[i]->rxlock);
+ for (i = 0; i < priv->num_tx_queues; i++)
+ spin_unlock(&priv->tx_queue[i]->txlock);
}
-void unlock_tx_qs(struct gfar_private *priv)
+static int gfar_alloc_tx_queues(struct gfar_private *priv)
{
int i;
- for (i = 0; i < priv->num_tx_queues; i++)
- spin_unlock(&priv->tx_queue[i]->txlock);
+ for (i = 0; i < priv->num_tx_queues; i++) {
+ priv->tx_queue[i] = kzalloc(sizeof(struct gfar_priv_tx_q),
+ GFP_KERNEL);
+ if (!priv->tx_queue[i])
+ return -ENOMEM;
+
+ priv->tx_queue[i]->tx_skbuff = NULL;
+ priv->tx_queue[i]->qindex = i;
+ priv->tx_queue[i]->dev = priv->ndev;
+ spin_lock_init(&(priv->tx_queue[i]->txlock));
+ }
+ return 0;
}
-static void free_tx_pointers(struct gfar_private *priv)
+static int gfar_alloc_rx_queues(struct gfar_private *priv)
+{
+ int i;
+
+ for (i = 0; i < priv->num_rx_queues; i++) {
+ priv->rx_queue[i] = kzalloc(sizeof(struct gfar_priv_rx_q),
+ GFP_KERNEL);
+ if (!priv->rx_queue[i])
+ return -ENOMEM;
+
+ priv->rx_queue[i]->rx_skbuff = NULL;
+ priv->rx_queue[i]->qindex = i;
+ priv->rx_queue[i]->dev = priv->ndev;
+ }
+ return 0;
+}
+
+static void gfar_free_tx_queues(struct gfar_private *priv)
{
int i;
@@ -518,7 +580,7 @@ static void free_tx_pointers(struct gfar_private *priv)
kfree(priv->tx_queue[i]);
}
-static void free_rx_pointers(struct gfar_private *priv)
+static void gfar_free_rx_queues(struct gfar_private *priv)
{
int i;
@@ -552,23 +614,26 @@ static void disable_napi(struct gfar_private *priv)
{
int i;
- for (i = 0; i < priv->num_grps; i++)
- napi_disable(&priv->gfargrp[i].napi);
+ for (i = 0; i < priv->num_grps; i++) {
+ napi_disable(&priv->gfargrp[i].napi_rx);
+ napi_disable(&priv->gfargrp[i].napi_tx);
+ }
}
static void enable_napi(struct gfar_private *priv)
{
int i;
- for (i = 0; i < priv->num_grps; i++)
- napi_enable(&priv->gfargrp[i].napi);
+ for (i = 0; i < priv->num_grps; i++) {
+ napi_enable(&priv->gfargrp[i].napi_rx);
+ napi_enable(&priv->gfargrp[i].napi_tx);
+ }
}
static int gfar_parse_group(struct device_node *np,
struct gfar_private *priv, const char *model)
{
struct gfar_priv_grp *grp = &priv->gfargrp[priv->num_grps];
- u32 *queue_mask;
int i;
for (i = 0; i < GFAR_NUM_IRQS; i++) {
@@ -597,16 +662,52 @@ static int gfar_parse_group(struct device_node *np,
grp->priv = priv;
spin_lock_init(&grp->grplock);
if (priv->mode == MQ_MG_MODE) {
- queue_mask = (u32 *)of_get_property(np, "fsl,rx-bit-map", NULL);
- grp->rx_bit_map = queue_mask ?
- *queue_mask : (DEFAULT_MAPPING >> priv->num_grps);
- queue_mask = (u32 *)of_get_property(np, "fsl,tx-bit-map", NULL);
- grp->tx_bit_map = queue_mask ?
- *queue_mask : (DEFAULT_MAPPING >> priv->num_grps);
+ u32 *rxq_mask, *txq_mask;
+ rxq_mask = (u32 *)of_get_property(np, "fsl,rx-bit-map", NULL);
+ txq_mask = (u32 *)of_get_property(np, "fsl,tx-bit-map", NULL);
+
+ if (priv->poll_mode == GFAR_SQ_POLLING) {
+ /* One Q per interrupt group: Q0 to G0, Q1 to G1 */
+ grp->rx_bit_map = (DEFAULT_MAPPING >> priv->num_grps);
+ grp->tx_bit_map = (DEFAULT_MAPPING >> priv->num_grps);
+ } else { /* GFAR_MQ_POLLING */
+ grp->rx_bit_map = rxq_mask ?
+ *rxq_mask : (DEFAULT_MAPPING >> priv->num_grps);
+ grp->tx_bit_map = txq_mask ?
+ *txq_mask : (DEFAULT_MAPPING >> priv->num_grps);
+ }
} else {
grp->rx_bit_map = 0xFF;
grp->tx_bit_map = 0xFF;
}
+
+ /* bit_map's MSB is q0 (from q0 to q7) but, for_each_set_bit parses
+ * right to left, so we need to revert the 8 bits to get the q index
+ */
+ grp->rx_bit_map = bitrev8(grp->rx_bit_map);
+ grp->tx_bit_map = bitrev8(grp->tx_bit_map);
+
+ /* Calculate RSTAT, TSTAT, RQUEUE and TQUEUE values,
+ * also assign queues to groups
+ */
+ for_each_set_bit(i, &grp->rx_bit_map, priv->num_rx_queues) {
+ if (!grp->rx_queue)
+ grp->rx_queue = priv->rx_queue[i];
+ grp->num_rx_queues++;
+ grp->rstat |= (RSTAT_CLEAR_RHALT >> i);
+ priv->rqueue |= ((RQUEUE_EN0 | RQUEUE_EX0) >> i);
+ priv->rx_queue[i]->grp = grp;
+ }
+
+ for_each_set_bit(i, &grp->tx_bit_map, priv->num_tx_queues) {
+ if (!grp->tx_queue)
+ grp->tx_queue = priv->tx_queue[i];
+ grp->num_tx_queues++;
+ grp->tstat |= (TSTAT_CLEAR_THALT >> i);
+ priv->tqueue |= (TQUEUE_EN0 >> i);
+ priv->tx_queue[i]->grp = grp;
+ }
+
priv->num_grps++;
return 0;
@@ -627,13 +728,45 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
const u32 *stash_idx;
unsigned int num_tx_qs, num_rx_qs;
u32 *tx_queues, *rx_queues;
+ unsigned short mode, poll_mode;
if (!np || !of_device_is_available(np))
return -ENODEV;
- /* parse the num of tx and rx queues */
+ if (of_device_is_compatible(np, "fsl,etsec2")) {
+ mode = MQ_MG_MODE;
+ poll_mode = GFAR_SQ_POLLING;
+ } else {
+ mode = SQ_SG_MODE;
+ poll_mode = GFAR_SQ_POLLING;
+ }
+
+ /* parse the num of HW tx and rx queues */
tx_queues = (u32 *)of_get_property(np, "fsl,num_tx_queues", NULL);
- num_tx_qs = tx_queues ? *tx_queues : 1;
+ rx_queues = (u32 *)of_get_property(np, "fsl,num_rx_queues", NULL);
+
+ if (mode == SQ_SG_MODE) {
+ num_tx_qs = 1;
+ num_rx_qs = 1;
+ } else { /* MQ_MG_MODE */
+ /* get the actual number of supported groups */
+ unsigned int num_grps = of_get_available_child_count(np);
+
+ if (num_grps == 0 || num_grps > MAXGROUPS) {
+ dev_err(&ofdev->dev, "Invalid # of int groups(%d)\n",
+ num_grps);
+ pr_err("Cannot do alloc_etherdev, aborting\n");
+ return -EINVAL;
+ }
+
+ if (poll_mode == GFAR_SQ_POLLING) {
+ num_tx_qs = num_grps; /* one txq per int group */
+ num_rx_qs = num_grps; /* one rxq per int group */
+ } else { /* GFAR_MQ_POLLING */
+ num_tx_qs = tx_queues ? *tx_queues : 1;
+ num_rx_qs = rx_queues ? *rx_queues : 1;
+ }
+ }
if (num_tx_qs > MAX_TX_QS) {
pr_err("num_tx_qs(=%d) greater than MAX_TX_QS(=%d)\n",
@@ -642,9 +775,6 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
return -EINVAL;
}
- rx_queues = (u32 *)of_get_property(np, "fsl,num_rx_queues", NULL);
- num_rx_qs = rx_queues ? *rx_queues : 1;
-
if (num_rx_qs > MAX_RX_QS) {
pr_err("num_rx_qs(=%d) greater than MAX_RX_QS(=%d)\n",
num_rx_qs, MAX_RX_QS);
@@ -652,6 +782,11 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
return -EINVAL;
}
+#ifdef CONFIG_AS_FASTPATH
+ /* Creating multilple queues for avoiding lock in xmit function.*/
+ num_tx_qs = (num_tx_qs < 2) ? 2 : num_tx_qs;
+#endif
+
*pdev = alloc_etherdev_mq(sizeof(*priv), num_tx_qs);
dev = *pdev;
if (NULL == dev)
@@ -660,10 +795,20 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
priv = netdev_priv(dev);
priv->ndev = dev;
+ priv->mode = mode;
+ priv->poll_mode = poll_mode;
+
priv->num_tx_queues = num_tx_qs;
netif_set_real_num_rx_queues(dev, num_rx_qs);
priv->num_rx_queues = num_rx_qs;
- priv->num_grps = 0x0;
+
+ err = gfar_alloc_tx_queues(priv);
+ if (err)
+ goto tx_alloc_failed;
+
+ err = gfar_alloc_rx_queues(priv);
+ if (err)
+ goto rx_alloc_failed;
/* Init Rx queue filer rule set linked list */
INIT_LIST_HEAD(&priv->rx_list.list);
@@ -676,52 +821,18 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
priv->gfargrp[i].regs = NULL;
/* Parse and initialize group specific information */
- if (of_device_is_compatible(np, "fsl,etsec2")) {
- priv->mode = MQ_MG_MODE;
+ if (priv->mode == MQ_MG_MODE) {
for_each_child_of_node(np, child) {
err = gfar_parse_group(child, priv, model);
if (err)
goto err_grp_init;
}
- } else {
- priv->mode = SQ_SG_MODE;
+ } else { /* SQ_SG_MODE */
err = gfar_parse_group(np, priv, model);
if (err)
goto err_grp_init;
}
- for (i = 0; i < priv->num_tx_queues; i++)
- priv->tx_queue[i] = NULL;
- for (i = 0; i < priv->num_rx_queues; i++)
- priv->rx_queue[i] = NULL;
-
- for (i = 0; i < priv->num_tx_queues; i++) {
- priv->tx_queue[i] = kzalloc(sizeof(struct gfar_priv_tx_q),
- GFP_KERNEL);
- if (!priv->tx_queue[i]) {
- err = -ENOMEM;
- goto tx_alloc_failed;
- }
- priv->tx_queue[i]->tx_skbuff = NULL;
- priv->tx_queue[i]->qindex = i;
- priv->tx_queue[i]->dev = dev;
- spin_lock_init(&(priv->tx_queue[i]->txlock));
- }
-
- for (i = 0; i < priv->num_rx_queues; i++) {
- priv->rx_queue[i] = kzalloc(sizeof(struct gfar_priv_rx_q),
- GFP_KERNEL);
- if (!priv->rx_queue[i]) {
- err = -ENOMEM;
- goto rx_alloc_failed;
- }
- priv->rx_queue[i]->rx_skbuff = NULL;
- priv->rx_queue[i]->qindex = i;
- priv->rx_queue[i]->dev = dev;
- spin_lock_init(&(priv->rx_queue[i]->rxlock));
- }
-
-
stash = of_get_property(np, "bd-stash", NULL);
if (stash) {
@@ -748,17 +859,16 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
memcpy(dev->dev_addr, mac_addr, ETH_ALEN);
if (model && !strcasecmp(model, "TSEC"))
- priv->device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+ priv->device_flags |= FSL_GIANFAR_DEV_HAS_GIGABIT |
FSL_GIANFAR_DEV_HAS_COALESCE |
FSL_GIANFAR_DEV_HAS_RMON |
FSL_GIANFAR_DEV_HAS_MULTI_INTR;
if (model && !strcasecmp(model, "eTSEC"))
- priv->device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+ priv->device_flags |= FSL_GIANFAR_DEV_HAS_GIGABIT |
FSL_GIANFAR_DEV_HAS_COALESCE |
FSL_GIANFAR_DEV_HAS_RMON |
FSL_GIANFAR_DEV_HAS_MULTI_INTR |
- FSL_GIANFAR_DEV_HAS_PADDING |
FSL_GIANFAR_DEV_HAS_CSUM |
FSL_GIANFAR_DEV_HAS_VLAN |
FSL_GIANFAR_DEV_HAS_MAGIC_PACKET |
@@ -780,15 +890,19 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
/* Find the TBI PHY. If it's not there, we don't support SGMII */
priv->tbi_node = of_parse_phandle(np, "tbi-handle", 0);
-
+#if defined CONFIG_FSL_GIANFAR_1588
+ /* Handle IEEE1588 node */
+ if (!gfar_ptp_init(np, priv))
+ dev_info(&ofdev->dev, "ptp 1588 is initialized.\n");
+#endif
return 0;
-rx_alloc_failed:
- free_rx_pointers(priv);
-tx_alloc_failed:
- free_tx_pointers(priv);
err_grp_init:
unmap_group_regs(priv);
+rx_alloc_failed:
+ gfar_free_rx_queues(priv);
+tx_alloc_failed:
+ gfar_free_tx_queues(priv);
free_gfar_dev(priv);
return err;
}
@@ -822,18 +936,16 @@ static int gfar_hwtstamp_ioctl(struct net_device *netdev,
switch (config.rx_filter) {
case HWTSTAMP_FILTER_NONE:
if (priv->hwts_rx_en) {
- stop_gfar(netdev);
priv->hwts_rx_en = 0;
- startup_gfar(netdev);
+ reset_gfar(netdev);
}
break;
default:
if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER))
return -ERANGE;
if (!priv->hwts_rx_en) {
- stop_gfar(netdev);
priv->hwts_rx_en = 1;
- startup_gfar(netdev);
+ reset_gfar(netdev);
}
config.rx_filter = HWTSTAMP_FILTER_ALL;
break;
@@ -856,21 +968,15 @@ static int gfar_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
if (!priv->phydev)
return -ENODEV;
-
+#if defined CONFIG_FSL_GIANFAR_1588
+ if ((cmd >= PTP_ENBL_TXTS_IOCTL) &&
+ (cmd <= PTP_CLEANUP_TS))
+ return gfar_ioctl_1588(dev, rq, cmd);
+ else
+ return phy_mii_ioctl(priv->phydev, rq, cmd);
+#else
return phy_mii_ioctl(priv->phydev, rq, cmd);
-}
-
-static unsigned int reverse_bitmap(unsigned int bit_map, unsigned int max_qs)
-{
- unsigned int new_bit_map = 0x0;
- int mask = 0x1 << (max_qs - 1), i;
-
- for (i = 0; i < max_qs; i++) {
- if (bit_map & mask)
- new_bit_map = new_bit_map + (1 << i);
- mask = mask >> 0x1;
- }
- return new_bit_map;
+#endif
}
static u32 cluster_entry_per_class(struct gfar_private *priv, u32 rqfar,
@@ -990,99 +1096,140 @@ static void gfar_detect_errata(struct gfar_private *priv)
priv->errata);
}
-/* Set up the ethernet device structure, private data,
- * and anything else we need before we start
- */
-static int gfar_probe(struct platform_device *ofdev)
+void gfar_mac_reset(struct gfar_private *priv)
{
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
u32 tempval;
- struct net_device *dev = NULL;
- struct gfar_private *priv = NULL;
- struct gfar __iomem *regs = NULL;
- int err = 0, i, grp_idx = 0;
- u32 rstat = 0, tstat = 0, rqueue = 0, tqueue = 0;
- u32 isrg = 0;
- u32 __iomem *baddr;
-
- err = gfar_of_init(ofdev, &dev);
-
- if (err)
- return err;
-
- priv = netdev_priv(dev);
- priv->ndev = dev;
- priv->ofdev = ofdev;
- priv->dev = &ofdev->dev;
- SET_NETDEV_DEV(dev, &ofdev->dev);
-
- spin_lock_init(&priv->bflock);
- INIT_WORK(&priv->reset_task, gfar_reset_task);
-
- platform_set_drvdata(ofdev, priv);
- regs = priv->gfargrp[0].regs;
-
- gfar_detect_errata(priv);
-
- /* Stop the DMA engine now, in case it was running before
- * (The firmware could have used it, and left it running).
- */
- gfar_halt(dev);
/* Reset MAC layer */
gfar_write(&regs->maccfg1, MACCFG1_SOFT_RESET);
/* We need to delay at least 3 TX clocks */
- udelay(2);
+ udelay(3);
- tempval = 0;
- if (!priv->pause_aneg_en && priv->tx_pause_en)
- tempval |= MACCFG1_TX_FLOW;
- if (!priv->pause_aneg_en && priv->rx_pause_en)
- tempval |= MACCFG1_RX_FLOW;
/* the soft reset bit is not self-resetting, so we need to
* clear it before resuming normal operation
*/
- gfar_write(&regs->maccfg1, tempval);
+ gfar_write(&regs->maccfg1, 0);
+
+ udelay(3);
+
+ /* Compute rx_buff_size based on config flags */
+ gfar_rx_buff_size_config(priv);
+
+ /* Initialize the max receive frame/buffer lengths */
+ gfar_write(&regs->maxfrm, priv->rx_buffer_size);
+ gfar_write(&regs->mrblr, priv->rx_buffer_size);
+
+ /* Initialize the Minimum Frame Length Register */
+ gfar_write(&regs->minflr, MINFLR_INIT_SETTINGS);
/* Initialize MACCFG2. */
tempval = MACCFG2_INIT_SETTINGS;
- if (gfar_has_errata(priv, GFAR_ERRATA_74))
+
+ /* If the mtu is larger than the max size for standard
+ * ethernet frames (ie, a jumbo frame), then set maccfg2
+ * to allow huge frames, and to check the length
+ */
+ if (priv->rx_buffer_size > DEFAULT_RX_BUFFER_SIZE ||
+ gfar_has_errata(priv, GFAR_ERRATA_74))
tempval |= MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK;
+
gfar_write(&regs->maccfg2, tempval);
+ /* Clear mac addr hash registers */
+ gfar_write(&regs->igaddr0, 0);
+ gfar_write(&regs->igaddr1, 0);
+ gfar_write(&regs->igaddr2, 0);
+ gfar_write(&regs->igaddr3, 0);
+ gfar_write(&regs->igaddr4, 0);
+ gfar_write(&regs->igaddr5, 0);
+ gfar_write(&regs->igaddr6, 0);
+ gfar_write(&regs->igaddr7, 0);
+
+ gfar_write(&regs->gaddr0, 0);
+ gfar_write(&regs->gaddr1, 0);
+ gfar_write(&regs->gaddr2, 0);
+ gfar_write(&regs->gaddr3, 0);
+ gfar_write(&regs->gaddr4, 0);
+ gfar_write(&regs->gaddr5, 0);
+ gfar_write(&regs->gaddr6, 0);
+ gfar_write(&regs->gaddr7, 0);
+
+ if (priv->extended_hash)
+ gfar_clear_exact_match(priv->ndev);
+
+ gfar_mac_rx_config(priv);
+
+ gfar_mac_tx_config(priv);
+
+ gfar_set_mac_address(priv->ndev);
+
+ gfar_set_multi(priv->ndev);
+
+ /* clear ievent and imask before configuring coalescing */
+ gfar_ints_disable(priv);
+
+ /* Configure the coalescing support */
+ gfar_configure_coalescing_all(priv);
+}
+
+static void gfar_hw_init(struct gfar_private *priv)
+{
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
+ u32 attrs;
+
+ /* Stop the DMA engine now, in case it was running before
+ * (The firmware could have used it, and left it running).
+ */
+ gfar_halt(priv);
+
+ gfar_mac_reset(priv);
+
+ /* Zero out the rmon mib registers if it has them */
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
+ memset_io(&(regs->rmon), 0, sizeof(struct rmon_mib));
+
+ /* Mask off the CAM interrupts */
+ gfar_write(&regs->rmon.cam1, 0xffffffff);
+ gfar_write(&regs->rmon.cam2, 0xffffffff);
+ }
+
/* Initialize ECNTRL */
gfar_write(&regs->ecntrl, ECNTRL_INIT_SETTINGS);
- /* Set the dev->base_addr to the gfar reg region */
- dev->base_addr = (unsigned long) regs;
+ /* Set the extraction length and index */
+ attrs = ATTRELI_EL(priv->rx_stash_size) |
+ ATTRELI_EI(priv->rx_stash_index);
- /* Fill in the dev structure */
- dev->watchdog_timeo = TX_TIMEOUT;
- dev->mtu = 1500;
- dev->netdev_ops = &gfar_netdev_ops;
- dev->ethtool_ops = &gfar_ethtool_ops;
+ gfar_write(&regs->attreli, attrs);
- /* Register for napi ...We are registering NAPI for each grp */
- if (priv->mode == SQ_SG_MODE)
- netif_napi_add(dev, &priv->gfargrp[0].napi, gfar_poll_sq,
- GFAR_DEV_WEIGHT);
- else
- for (i = 0; i < priv->num_grps; i++)
- netif_napi_add(dev, &priv->gfargrp[i].napi, gfar_poll,
- GFAR_DEV_WEIGHT);
+ /* Start with defaults, and add stashing
+ * depending on driver parameters
+ */
+ attrs = ATTR_INIT_SETTINGS;
- if (priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) {
- dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
- NETIF_F_RXCSUM;
- dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG |
- NETIF_F_RXCSUM | NETIF_F_HIGHDMA;
- }
+ if (priv->bd_stash_en)
+ attrs |= ATTR_BDSTASH;
- if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) {
- dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX |
- NETIF_F_HW_VLAN_CTAG_RX;
- dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
- }
+ if (priv->rx_stash_size != 0)
+ attrs |= ATTR_BUFSTASH;
+
+ gfar_write(&regs->attr, attrs);
+
+ /* FIFO configs */
+ gfar_write(&regs->fifo_tx_thr, DEFAULT_FIFO_TX_THR);
+ gfar_write(&regs->fifo_tx_starve, DEFAULT_FIFO_TX_STARVE);
+ gfar_write(&regs->fifo_tx_starve_shutoff, DEFAULT_FIFO_TX_STARVE_OFF);
+
+ /* Program the interrupt steering regs, only for MG devices */
+ if (priv->num_grps > 1)
+ gfar_write_isrg(priv);
+}
+
+static void __init gfar_init_addr_hash_table(struct gfar_private *priv)
+{
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
if (priv->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) {
priv->extended_hash = 1;
@@ -1118,68 +1265,81 @@ static int gfar_probe(struct platform_device *ofdev)
priv->hash_regs[6] = &regs->gaddr6;
priv->hash_regs[7] = &regs->gaddr7;
}
+}
- if (priv->device_flags & FSL_GIANFAR_DEV_HAS_PADDING)
- priv->padding = DEFAULT_PADDING;
- else
- priv->padding = 0;
+/* Set up the ethernet device structure, private data,
+ * and anything else we need before we start
+ */
+static int gfar_probe(struct platform_device *ofdev)
+{
+ struct net_device *dev = NULL;
+ struct gfar_private *priv = NULL;
+ int err = 0, i;
- if (dev->features & NETIF_F_IP_CSUM ||
- priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)
- dev->needed_headroom = GMAC_FCB_LEN;
+ err = gfar_of_init(ofdev, &dev);
- /* Program the isrg regs only if number of grps > 1 */
- if (priv->num_grps > 1) {
- baddr = &regs->isrg0;
- for (i = 0; i < priv->num_grps; i++) {
- isrg |= (priv->gfargrp[i].rx_bit_map << ISRG_SHIFT_RX);
- isrg |= (priv->gfargrp[i].tx_bit_map << ISRG_SHIFT_TX);
- gfar_write(baddr, isrg);
- baddr++;
- isrg = 0x0;
+ if (err)
+ return err;
+
+ priv = netdev_priv(dev);
+ priv->ndev = dev;
+ priv->ofdev = ofdev;
+ priv->dev = &ofdev->dev;
+ SET_NETDEV_DEV(dev, &ofdev->dev);
+
+ spin_lock_init(&priv->bflock);
+ INIT_WORK(&priv->reset_task, gfar_reset_task);
+
+ platform_set_drvdata(ofdev, priv);
+
+ gfar_detect_errata(priv);
+
+ /* Set the dev->base_addr to the gfar reg region */
+ dev->base_addr = (unsigned long) priv->gfargrp[0].regs;
+
+ /* Fill in the dev structure */
+ dev->watchdog_timeo = TX_TIMEOUT;
+ dev->mtu = 1500;
+ dev->netdev_ops = &gfar_netdev_ops;
+ dev->ethtool_ops = &gfar_ethtool_ops;
+
+ /* Register for napi ...We are registering NAPI for each grp */
+ for (i = 0; i < priv->num_grps; i++) {
+ if (priv->poll_mode == GFAR_SQ_POLLING) {
+ netif_napi_add(dev, &priv->gfargrp[i].napi_rx,
+ gfar_poll_rx_sq, GFAR_DEV_WEIGHT);
+ netif_napi_add(dev, &priv->gfargrp[i].napi_tx,
+ gfar_poll_tx_sq, 2);
+ } else {
+ netif_napi_add(dev, &priv->gfargrp[i].napi_rx,
+ gfar_poll_rx, GFAR_DEV_WEIGHT);
+ netif_napi_add(dev, &priv->gfargrp[i].napi_tx,
+ gfar_poll_tx, 2);
}
}
- /* Need to reverse the bit maps as bit_map's MSB is q0
- * but, for_each_set_bit parses from right to left, which
- * basically reverses the queue numbers
- */
- for (i = 0; i< priv->num_grps; i++) {
- priv->gfargrp[i].tx_bit_map =
- reverse_bitmap(priv->gfargrp[i].tx_bit_map, MAX_TX_QS);
- priv->gfargrp[i].rx_bit_map =
- reverse_bitmap(priv->gfargrp[i].rx_bit_map, MAX_RX_QS);
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) {
+ dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG |
+ NETIF_F_RXCSUM;
+ dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG |
+ NETIF_F_RXCSUM | NETIF_F_HIGHDMA;
}
- /* Calculate RSTAT, TSTAT, RQUEUE and TQUEUE values,
- * also assign queues to groups
- */
- for (grp_idx = 0; grp_idx < priv->num_grps; grp_idx++) {
- priv->gfargrp[grp_idx].num_rx_queues = 0x0;
-
- for_each_set_bit(i, &priv->gfargrp[grp_idx].rx_bit_map,
- priv->num_rx_queues) {
- priv->gfargrp[grp_idx].num_rx_queues++;
- priv->rx_queue[i]->grp = &priv->gfargrp[grp_idx];
- rstat = rstat | (RSTAT_CLEAR_RHALT >> i);
- rqueue = rqueue | ((RQUEUE_EN0 | RQUEUE_EX0) >> i);
- }
- priv->gfargrp[grp_idx].num_tx_queues = 0x0;
-
- for_each_set_bit(i, &priv->gfargrp[grp_idx].tx_bit_map,
- priv->num_tx_queues) {
- priv->gfargrp[grp_idx].num_tx_queues++;
- priv->tx_queue[i]->grp = &priv->gfargrp[grp_idx];
- tstat = tstat | (TSTAT_CLEAR_THALT >> i);
- tqueue = tqueue | (TQUEUE_EN0 >> i);
- }
- priv->gfargrp[grp_idx].rstat = rstat;
- priv->gfargrp[grp_idx].tstat = tstat;
- rstat = tstat =0;
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) {
+ dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_CTAG_RX;
+ dev->features |= NETIF_F_HW_VLAN_CTAG_RX;
}
- gfar_write(&regs->rqueue, rqueue);
- gfar_write(&regs->tqueue, tqueue);
+ gfar_init_addr_hash_table(priv);
+
+ /* Insert receive time stamps into padding alignment bytes */
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)
+ priv->padding = 8;
+
+ if (dev->features & NETIF_F_IP_CSUM ||
+ priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)
+ dev->needed_headroom = GMAC_FCB_LEN;
priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE;
@@ -1205,8 +1365,9 @@ static int gfar_probe(struct platform_device *ofdev)
if (priv->num_tx_queues == 1)
priv->prio_sched_en = 1;
- /* Carrier starts down, phylib will bring it up */
- netif_carrier_off(dev);
+ set_bit(GFAR_DOWN, &priv->state);
+
+ gfar_hw_init(priv);
err = register_netdev(dev);
@@ -1215,6 +1376,9 @@ static int gfar_probe(struct platform_device *ofdev)
goto register_fail;
}
+ /* Carrier starts down, phylib will bring it up */
+ netif_carrier_off(dev);
+
device_init_wakeup(&dev->dev,
priv->device_flags &
FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
@@ -1236,9 +1400,6 @@ static int gfar_probe(struct platform_device *ofdev)
/* Initialize the filer table */
gfar_init_filer_table(priv);
- /* Create all the sysfs files */
- gfar_init_sysfs(dev);
-
/* Print out the device info */
netdev_info(dev, "mac: %pM\n", dev->dev_addr);
@@ -1256,9 +1417,12 @@ static int gfar_probe(struct platform_device *ofdev)
return 0;
register_fail:
+#if defined CONFIG_FSL_GIANFAR_1588
+ gfar_ptp_cleanup(priv);
+#endif
unmap_group_regs(priv);
- free_tx_pointers(priv);
- free_rx_pointers(priv);
+ gfar_free_rx_queues(priv);
+ gfar_free_tx_queues(priv);
if (priv->phy_node)
of_node_put(priv->phy_node);
if (priv->tbi_node)
@@ -1278,6 +1442,8 @@ static int gfar_remove(struct platform_device *ofdev)
unregister_netdev(priv->ndev);
unmap_group_regs(priv);
+ gfar_free_rx_queues(priv);
+ gfar_free_tx_queues(priv);
free_gfar_dev(priv);
return 0;
@@ -1303,9 +1469,8 @@ static int gfar_suspend(struct device *dev)
local_irq_save(flags);
lock_tx_qs(priv);
- lock_rx_qs(priv);
- gfar_halt_nodisable(ndev);
+ gfar_halt_nodisable(priv);
/* Disable Tx, and Rx if wake-on-LAN is disabled. */
tempval = gfar_read(&regs->maccfg1);
@@ -1317,7 +1482,6 @@ static int gfar_suspend(struct device *dev)
gfar_write(&regs->maccfg1, tempval);
- unlock_rx_qs(priv);
unlock_tx_qs(priv);
local_irq_restore(flags);
@@ -1363,15 +1527,13 @@ static int gfar_resume(struct device *dev)
*/
local_irq_save(flags);
lock_tx_qs(priv);
- lock_rx_qs(priv);
tempval = gfar_read(&regs->maccfg2);
tempval &= ~MACCFG2_MPEN;
gfar_write(&regs->maccfg2, tempval);
- gfar_start(ndev);
+ gfar_start(priv);
- unlock_rx_qs(priv);
unlock_tx_qs(priv);
local_irq_restore(flags);
@@ -1398,10 +1560,11 @@ static int gfar_restore(struct device *dev)
return -ENOMEM;
}
- init_registers(ndev);
- gfar_set_mac_address(ndev);
- gfar_init_mac(ndev);
- gfar_start(ndev);
+ gfar_mac_reset(priv);
+
+ gfar_init_tx_rx_base(priv);
+
+ gfar_start(priv);
priv->oldlink = 0;
priv->oldspeed = 0;
@@ -1559,57 +1722,6 @@ static void gfar_configure_serdes(struct net_device *dev)
BMCR_SPEED1000);
}
-static void init_registers(struct net_device *dev)
-{
- struct gfar_private *priv = netdev_priv(dev);
- struct gfar __iomem *regs = NULL;
- int i;
-
- for (i = 0; i < priv->num_grps; i++) {
- regs = priv->gfargrp[i].regs;
- /* Clear IEVENT */
- gfar_write(&regs->ievent, IEVENT_INIT_CLEAR);
-
- /* Initialize IMASK */
- gfar_write(&regs->imask, IMASK_INIT_CLEAR);
- }
-
- regs = priv->gfargrp[0].regs;
- /* Init hash registers to zero */
- gfar_write(&regs->igaddr0, 0);
- gfar_write(&regs->igaddr1, 0);
- gfar_write(&regs->igaddr2, 0);
- gfar_write(&regs->igaddr3, 0);
- gfar_write(&regs->igaddr4, 0);
- gfar_write(&regs->igaddr5, 0);
- gfar_write(&regs->igaddr6, 0);
- gfar_write(&regs->igaddr7, 0);
-
- gfar_write(&regs->gaddr0, 0);
- gfar_write(&regs->gaddr1, 0);
- gfar_write(&regs->gaddr2, 0);
- gfar_write(&regs->gaddr3, 0);
- gfar_write(&regs->gaddr4, 0);
- gfar_write(&regs->gaddr5, 0);
- gfar_write(&regs->gaddr6, 0);
- gfar_write(&regs->gaddr7, 0);
-
- /* Zero out the rmon mib registers if it has them */
- if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
- memset_io(&(regs->rmon), 0, sizeof (struct rmon_mib));
-
- /* Mask off the CAM interrupts */
- gfar_write(&regs->rmon.cam1, 0xffffffff);
- gfar_write(&regs->rmon.cam2, 0xffffffff);
- }
-
- /* Initialize the max receive buffer length */
- gfar_write(&regs->mrblr, priv->rx_buffer_size);
-
- /* Initialize the Minimum Frame Length Register */
- gfar_write(&regs->minflr, MINFLR_INIT_SETTINGS);
-}
-
static int __gfar_is_rx_idle(struct gfar_private *priv)
{
u32 res;
@@ -1633,23 +1745,13 @@ static int __gfar_is_rx_idle(struct gfar_private *priv)
}
/* Halt the receive and transmit queues */
-static void gfar_halt_nodisable(struct net_device *dev)
+static void gfar_halt_nodisable(struct gfar_private *priv)
{
- struct gfar_private *priv = netdev_priv(dev);
- struct gfar __iomem *regs = NULL;
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
u32 tempval;
- int i;
- for (i = 0; i < priv->num_grps; i++) {
- regs = priv->gfargrp[i].regs;
- /* Mask all interrupts */
- gfar_write(&regs->imask, IMASK_INIT_CLEAR);
-
- /* Clear all interrupts */
- gfar_write(&regs->ievent, IEVENT_INIT_CLEAR);
- }
+ gfar_ints_disable(priv);
- regs = priv->gfargrp[0].regs;
/* Stop the DMA, and wait for it to stop */
tempval = gfar_read(&regs->dmactrl);
if ((tempval & (DMACTRL_GRS | DMACTRL_GTS)) !=
@@ -1670,56 +1772,41 @@ static void gfar_halt_nodisable(struct net_device *dev)
}
/* Halt the receive and transmit queues */
-void gfar_halt(struct net_device *dev)
+void gfar_halt(struct gfar_private *priv)
{
- struct gfar_private *priv = netdev_priv(dev);
struct gfar __iomem *regs = priv->gfargrp[0].regs;
u32 tempval;
- gfar_halt_nodisable(dev);
+ /* Dissable the Rx/Tx hw queues */
+ gfar_write(&regs->rqueue, 0);
+ gfar_write(&regs->tqueue, 0);
+
+ mdelay(10);
- /* Disable Rx and Tx */
+ gfar_halt_nodisable(priv);
+
+ /* Disable Rx/Tx DMA */
tempval = gfar_read(&regs->maccfg1);
tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN);
gfar_write(&regs->maccfg1, tempval);
}
-static void free_grp_irqs(struct gfar_priv_grp *grp)
-{
- free_irq(gfar_irq(grp, TX)->irq, grp);
- free_irq(gfar_irq(grp, RX)->irq, grp);
- free_irq(gfar_irq(grp, ER)->irq, grp);
-}
-
void stop_gfar(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
- unsigned long flags;
- int i;
- phy_stop(priv->phydev);
+ netif_tx_stop_all_queues(dev);
+ smp_mb__before_clear_bit();
+ set_bit(GFAR_DOWN, &priv->state);
+ smp_mb__after_clear_bit();
- /* Lock it down */
- local_irq_save(flags);
- lock_tx_qs(priv);
- lock_rx_qs(priv);
+ disable_napi(priv);
- gfar_halt(dev);
+ /* disable ints and gracefully shut down Rx/Tx DMA */
+ gfar_halt(priv);
- unlock_rx_qs(priv);
- unlock_tx_qs(priv);
- local_irq_restore(flags);
-
- /* Free the IRQs */
- if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
- for (i = 0; i < priv->num_grps; i++)
- free_grp_irqs(&priv->gfargrp[i]);
- } else {
- for (i = 0; i < priv->num_grps; i++)
- free_irq(gfar_irq(&priv->gfargrp[i], TX)->irq,
- &priv->gfargrp[i]);
- }
+ phy_stop(priv->phydev);
free_skb_resources(priv);
}
@@ -1810,17 +1897,15 @@ static void free_skb_resources(struct gfar_private *priv)
priv->tx_queue[0]->tx_bd_dma_base);
}
-void gfar_start(struct net_device *dev)
+void gfar_start(struct gfar_private *priv)
{
- struct gfar_private *priv = netdev_priv(dev);
struct gfar __iomem *regs = priv->gfargrp[0].regs;
u32 tempval;
int i = 0;
- /* Enable Rx and Tx in MACCFG1 */
- tempval = gfar_read(&regs->maccfg1);
- tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
- gfar_write(&regs->maccfg1, tempval);
+ /* Enable Rx/Tx hw queues */
+ gfar_write(&regs->rqueue, priv->rqueue);
+ gfar_write(&regs->tqueue, priv->tqueue);
/* Initialize DMACTRL to have WWR and WOP */
tempval = gfar_read(&regs->dmactrl);
@@ -1837,52 +1922,23 @@ void gfar_start(struct net_device *dev)
/* Clear THLT/RHLT, so that the DMA starts polling now */
gfar_write(&regs->tstat, priv->gfargrp[i].tstat);
gfar_write(&regs->rstat, priv->gfargrp[i].rstat);
- /* Unmask the interrupts we look for */
- gfar_write(&regs->imask, IMASK_DEFAULT);
}
- dev->trans_start = jiffies; /* prevent tx timeout */
-}
-
-static void gfar_configure_coalescing(struct gfar_private *priv,
- unsigned long tx_mask, unsigned long rx_mask)
-{
- struct gfar __iomem *regs = priv->gfargrp[0].regs;
- u32 __iomem *baddr;
-
- if (priv->mode == MQ_MG_MODE) {
- int i = 0;
+ /* Enable Rx/Tx DMA */
+ tempval = gfar_read(&regs->maccfg1);
+ tempval |= (MACCFG1_RX_EN | MACCFG1_TX_EN);
+ gfar_write(&regs->maccfg1, tempval);
- baddr = &regs->txic0;
- for_each_set_bit(i, &tx_mask, priv->num_tx_queues) {
- gfar_write(baddr + i, 0);
- if (likely(priv->tx_queue[i]->txcoalescing))
- gfar_write(baddr + i, priv->tx_queue[i]->txic);
- }
+ gfar_ints_enable(priv);
- baddr = &regs->rxic0;
- for_each_set_bit(i, &rx_mask, priv->num_rx_queues) {
- gfar_write(baddr + i, 0);
- if (likely(priv->rx_queue[i]->rxcoalescing))
- gfar_write(baddr + i, priv->rx_queue[i]->rxic);
- }
- } else {
- /* Backward compatible case -- even if we enable
- * multiple queues, there's only single reg to program
- */
- gfar_write(&regs->txic, 0);
- if (likely(priv->tx_queue[0]->txcoalescing))
- gfar_write(&regs->txic, priv->tx_queue[0]->txic);
-
- gfar_write(&regs->rxic, 0);
- if (unlikely(priv->rx_queue[0]->rxcoalescing))
- gfar_write(&regs->rxic, priv->rx_queue[0]->rxic);
- }
+ priv->ndev->trans_start = jiffies; /* prevent tx timeout */
}
-void gfar_configure_coalescing_all(struct gfar_private *priv)
+static void free_grp_irqs(struct gfar_priv_grp *grp)
{
- gfar_configure_coalescing(priv, 0xFF, 0xFF);
+ free_irq(gfar_irq(grp, TX)->irq, grp);
+ free_irq(gfar_irq(grp, RX)->irq, grp);
+ free_irq(gfar_irq(grp, ER)->irq, grp);
}
static int register_grp_irqs(struct gfar_priv_grp *grp)
@@ -1941,46 +1997,65 @@ err_irq_fail:
}
-/* Bring the controller up and running */
-int startup_gfar(struct net_device *ndev)
+static void gfar_free_irq(struct gfar_private *priv)
{
- struct gfar_private *priv = netdev_priv(ndev);
- struct gfar __iomem *regs = NULL;
- int err, i, j;
+ int i;
- for (i = 0; i < priv->num_grps; i++) {
- regs= priv->gfargrp[i].regs;
- gfar_write(&regs->imask, IMASK_INIT_CLEAR);
+ /* Free the IRQs */
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
+ for (i = 0; i < priv->num_grps; i++)
+ free_grp_irqs(&priv->gfargrp[i]);
+ } else {
+ for (i = 0; i < priv->num_grps; i++)
+ free_irq(gfar_irq(&priv->gfargrp[i], TX)->irq,
+ &priv->gfargrp[i]);
}
+}
- regs= priv->gfargrp[0].regs;
- err = gfar_alloc_skb_resources(ndev);
- if (err)
- return err;
-
- gfar_init_mac(ndev);
+static int gfar_request_irq(struct gfar_private *priv)
+{
+ int err, i, j;
for (i = 0; i < priv->num_grps; i++) {
err = register_grp_irqs(&priv->gfargrp[i]);
if (err) {
for (j = 0; j < i; j++)
free_grp_irqs(&priv->gfargrp[j]);
- goto irq_fail;
+ return err;
}
}
- /* Start the controller */
- gfar_start(ndev);
+ return 0;
+}
+
+/* Bring the controller up and running */
+int startup_gfar(struct net_device *ndev)
+{
+ struct gfar_private *priv = netdev_priv(ndev);
+ int err;
+
+ gfar_mac_reset(priv);
+
+ err = gfar_alloc_skb_resources(ndev);
+ if (err)
+ return err;
+
+ gfar_init_tx_rx_base(priv);
+
+ smp_mb__before_clear_bit();
+ clear_bit(GFAR_DOWN, &priv->state);
+ smp_mb__after_clear_bit();
+
+ /* Start Rx/Tx DMA and enable the interrupts */
+ gfar_start(priv);
phy_start(priv->phydev);
- gfar_configure_coalescing_all(priv);
+ enable_napi(priv);
- return 0;
+ netif_tx_wake_all_queues(ndev);
-irq_fail:
- free_skb_resources(priv);
- return err;
+ return 0;
}
/* Called when something needs to use the ethernet device
@@ -1991,109 +2066,28 @@ static int gfar_enet_open(struct net_device *dev)
struct gfar_private *priv = netdev_priv(dev);
int err;
- enable_napi(priv);
-
- /* Initialize a bunch of registers */
- init_registers(dev);
-
- gfar_set_mac_address(dev);
-
err = init_phy(dev);
+ if (err)
+ return err;
- if (err) {
- disable_napi(priv);
+ err = gfar_request_irq(priv);
+ if (err)
return err;
- }
err = startup_gfar(dev);
- if (err) {
- disable_napi(priv);
+ if (err)
return err;
- }
-
- netif_tx_start_all_queues(dev);
device_set_wakeup_enable(&dev->dev, priv->wol_en);
return err;
}
-
-static inline struct txfcb *gfar_add_fcb(struct sk_buff *skb)
-{
- struct txfcb *fcb = (struct txfcb *)skb_push(skb, GMAC_FCB_LEN);
-
- memset(fcb, 0, GMAC_FCB_LEN);
-
- return fcb;
-}
-
-static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb,
- int fcb_length)
-{
- /* If we're here, it's a IP packet with a TCP or UDP
- * payload. We set it to checksum, using a pseudo-header
- * we provide
- */
- u8 flags = TXFCB_DEFAULT;
-
- /* Tell the controller what the protocol is
- * And provide the already calculated phcs
- */
- if (ip_hdr(skb)->protocol == IPPROTO_UDP) {
- flags |= TXFCB_UDP;
- fcb->phcs = udp_hdr(skb)->check;
- } else
- fcb->phcs = tcp_hdr(skb)->check;
-
- /* l3os is the distance between the start of the
- * frame (skb->data) and the start of the IP hdr.
- * l4os is the distance between the start of the
- * l3 hdr and the l4 hdr
- */
- fcb->l3os = (u16)(skb_network_offset(skb) - fcb_length);
- fcb->l4os = skb_network_header_len(skb);
-
- fcb->flags = flags;
-}
-
void inline gfar_tx_vlan(struct sk_buff *skb, struct txfcb *fcb)
{
fcb->flags |= TXFCB_VLN;
fcb->vlctl = vlan_tx_tag_get(skb);
}
-static inline struct txbd8 *skip_txbd(struct txbd8 *bdp, int stride,
- struct txbd8 *base, int ring_size)
-{
- struct txbd8 *new_bd = bdp + stride;
-
- return (new_bd >= (base + ring_size)) ? (new_bd - ring_size) : new_bd;
-}
-
-static inline struct txbd8 *next_txbd(struct txbd8 *bdp, struct txbd8 *base,
- int ring_size)
-{
- return skip_txbd(bdp, 1, base, ring_size);
-}
-
-/* eTSEC12: csum generation not supported for some fcb offsets */
-static inline bool gfar_csum_errata_12(struct gfar_private *priv,
- unsigned long fcb_addr)
-{
- return (gfar_has_errata(priv, GFAR_ERRATA_12) &&
- (fcb_addr % 0x20) > 0x18);
-}
-
-/* eTSEC76: csum generation for frames larger than 2500 may
- * cause excess delays before start of transmission
- */
-static inline bool gfar_csum_errata_76(struct gfar_private *priv,
- unsigned int len)
-{
- return (gfar_has_errata(priv, GFAR_ERRATA_76) &&
- (len > 2500));
-}
-
/* This is called by the kernel when a frame is ready for transmission.
* It is pointed to by the dev->hard_start_xmit function pointer
*/
@@ -2109,9 +2103,12 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
int i, rq = 0;
int do_tstamp, do_csum, do_vlan;
u32 bufaddr;
- unsigned long flags;
unsigned int nr_frags, nr_txbds, bytes_sent, fcb_len = 0;
+#ifdef CONFIG_AS_FASTPATH
+ return gfar_asf_start_xmit(skb, dev);
+#endif
+
rq = skb->queue_mapping;
tx_queue = priv->tx_queue[rq];
txq = netdev_get_tx_queue(dev, rq);
@@ -2120,9 +2117,13 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
do_csum = (CHECKSUM_PARTIAL == skb->ip_summed);
do_vlan = vlan_tx_tag_present(skb);
+#if defined CONFIG_FSL_GIANFAR_1588
+ do_tstamp = unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
+ priv->hwts_tx_en) || unlikely(priv->hwts_tx_en_ioctl);
+#else
do_tstamp = (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
priv->hwts_tx_en;
-
+#endif
if (do_csum || do_vlan)
fcb_len = GMAC_FCB_LEN;
@@ -2251,8 +2252,21 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Setup tx hardware time stamping if requested */
if (unlikely(do_tstamp)) {
+#if defined CONFIG_FSL_GIANFAR_1588
+ u32 vlan_ctrl;
+#endif
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
fcb->ptp = 1;
+#if defined CONFIG_FSL_GIANFAR_1588
+ /* When PTP in FCB is enabled, VLN in FCB is ignored.
+ * Instead VLAN tag is read from DFVLAN register. Thus need
+ * to copy VLCTL to DFVLAN register.
+ */
+ vlan_ctrl = gfar_read(&regs->dfvlan);
+ vlan_ctrl &= ~0xFFFF;
+ vlan_ctrl |= (fcb->vlctl & 0xFFFF);
+ gfar_write(&regs->dfvlan, vlan_ctrl);
+#endif
}
txbdp_start->bufPtr = dma_map_single(priv->dev, skb->data,
@@ -2274,19 +2288,6 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
netdev_tx_sent_queue(txq, bytes_sent);
- /* We can work in parallel with gfar_clean_tx_ring(), except
- * when modifying num_txbdfree. Note that we didn't grab the lock
- * when we were reading the num_txbdfree and checking for available
- * space, that's because outside of this function it can only grow,
- * and once we've got needed space, it cannot suddenly disappear.
- *
- * The lock also protects us from gfar_error(), which can modify
- * regs->tstat and thus retrigger the transfers, which is why we
- * also must grab the lock before setting ready bit for the first
- * to be transmitted BD.
- */
- spin_lock_irqsave(&tx_queue->txlock, flags);
-
/* The powerpc-specific eieio() is used, as wmb() has too strong
* semantics (it requires synchronization between cacheable and
* uncacheable mappings, which eieio doesn't provide and which we
@@ -2310,8 +2311,16 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
tx_queue->cur_tx = next_txbd(txbdp, base, tx_queue->tx_ring_size);
+ /* We can work in parallel with gfar_clean_tx_ring(), except
+ * when modifying num_txbdfree. Note that we didn't grab the lock
+ * when we were reading the num_txbdfree and checking for available
+ * space, that's because outside of this function it can only grow,
+ * and once we've got needed space, it cannot suddenly disappear.
+ */
+ spin_lock_bh(&tx_queue->txlock);
/* reduce TxBD free count */
tx_queue->num_txbdfree -= (nr_txbds);
+ spin_unlock_bh(&tx_queue->txlock);
/* If the next BD still needs to be cleaned up, then the bds
* are full. We need to tell the kernel to stop sending us stuff.
@@ -2325,9 +2334,6 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Tell the DMA to go go go */
gfar_write(&regs->tstat, TSTAT_CLEAR_THALT >> tx_queue->qindex);
- /* Unlock priv */
- spin_unlock_irqrestore(&tx_queue->txlock, flags);
-
return NETDEV_TX_OK;
}
@@ -2336,8 +2342,6 @@ static int gfar_close(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
- disable_napi(priv);
-
cancel_work_sync(&priv->reset_task);
stop_gfar(dev);
@@ -2345,7 +2349,7 @@ static int gfar_close(struct net_device *dev)
phy_disconnect(priv->phydev);
priv->phydev = NULL;
- netif_tx_stop_all_queues(dev);
+ gfar_free_irq(priv);
return 0;
}
@@ -2358,77 +2362,9 @@ static int gfar_set_mac_address(struct net_device *dev)
return 0;
}
-/* Check if rx parser should be activated */
-void gfar_check_rx_parser_mode(struct gfar_private *priv)
-{
- struct gfar __iomem *regs;
- u32 tempval;
-
- regs = priv->gfargrp[0].regs;
-
- tempval = gfar_read(&regs->rctrl);
- /* If parse is no longer required, then disable parser */
- if (tempval & RCTRL_REQ_PARSER) {
- tempval |= RCTRL_PRSDEP_INIT;
- priv->uses_rxfcb = 1;
- } else {
- tempval &= ~RCTRL_PRSDEP_INIT;
- priv->uses_rxfcb = 0;
- }
- gfar_write(&regs->rctrl, tempval);
-}
-
-/* Enables and disables VLAN insertion/extraction */
-void gfar_vlan_mode(struct net_device *dev, netdev_features_t features)
-{
- struct gfar_private *priv = netdev_priv(dev);
- struct gfar __iomem *regs = NULL;
- unsigned long flags;
- u32 tempval;
-
- regs = priv->gfargrp[0].regs;
- local_irq_save(flags);
- lock_rx_qs(priv);
-
- if (features & NETIF_F_HW_VLAN_CTAG_TX) {
- /* Enable VLAN tag insertion */
- tempval = gfar_read(&regs->tctrl);
- tempval |= TCTRL_VLINS;
- gfar_write(&regs->tctrl, tempval);
- } else {
- /* Disable VLAN tag insertion */
- tempval = gfar_read(&regs->tctrl);
- tempval &= ~TCTRL_VLINS;
- gfar_write(&regs->tctrl, tempval);
- }
-
- if (features & NETIF_F_HW_VLAN_CTAG_RX) {
- /* Enable VLAN tag extraction */
- tempval = gfar_read(&regs->rctrl);
- tempval |= (RCTRL_VLEX | RCTRL_PRSDEP_INIT);
- gfar_write(&regs->rctrl, tempval);
- priv->uses_rxfcb = 1;
- } else {
- /* Disable VLAN tag extraction */
- tempval = gfar_read(&regs->rctrl);
- tempval &= ~RCTRL_VLEX;
- gfar_write(&regs->rctrl, tempval);
-
- gfar_check_rx_parser_mode(priv);
- }
-
- gfar_change_mtu(dev, dev->mtu);
-
- unlock_rx_qs(priv);
- local_irq_restore(flags);
-}
-
static int gfar_change_mtu(struct net_device *dev, int new_mtu)
{
- int tempsize, tempval;
struct gfar_private *priv = netdev_priv(dev);
- struct gfar __iomem *regs = priv->gfargrp[0].regs;
- int oldsize = priv->rx_buffer_size;
int frame_size = new_mtu + ETH_HLEN;
if ((frame_size < 64) || (frame_size > JUMBO_FRAME_SIZE)) {
@@ -2436,45 +2372,33 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu)
return -EINVAL;
}
- if (priv->uses_rxfcb)
- frame_size += GMAC_FCB_LEN;
-
- frame_size += priv->padding;
-
- tempsize = (frame_size & ~(INCREMENTAL_BUFFER_SIZE - 1)) +
- INCREMENTAL_BUFFER_SIZE;
+ while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
+ cpu_relax();
- /* Only stop and start the controller if it isn't already
- * stopped, and we changed something
- */
- if ((oldsize != tempsize) && (dev->flags & IFF_UP))
+ if (dev->flags & IFF_UP)
stop_gfar(dev);
- priv->rx_buffer_size = tempsize;
-
dev->mtu = new_mtu;
- gfar_write(&regs->mrblr, priv->rx_buffer_size);
- gfar_write(&regs->maxfrm, priv->rx_buffer_size);
+ if (dev->flags & IFF_UP)
+ startup_gfar(dev);
- /* If the mtu is larger than the max size for standard
- * ethernet frames (ie, a jumbo frame), then set maccfg2
- * to allow huge frames, and to check the length
- */
- tempval = gfar_read(&regs->maccfg2);
+ clear_bit_unlock(GFAR_RESETTING, &priv->state);
- if (priv->rx_buffer_size > DEFAULT_RX_BUFFER_SIZE ||
- gfar_has_errata(priv, GFAR_ERRATA_74))
- tempval |= (MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK);
- else
- tempval &= ~(MACCFG2_HUGEFRAME | MACCFG2_LENGTHCHECK);
+ return 0;
+}
- gfar_write(&regs->maccfg2, tempval);
+void reset_gfar(struct net_device *ndev)
+{
+ struct gfar_private *priv = netdev_priv(ndev);
- if ((oldsize != tempsize) && (dev->flags & IFF_UP))
- startup_gfar(dev);
+ while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
+ cpu_relax();
- return 0;
+ stop_gfar(ndev);
+ startup_gfar(ndev);
+
+ clear_bit_unlock(GFAR_RESETTING, &priv->state);
}
/* gfar_reset_task gets scheduled when a packet has not been
@@ -2486,16 +2410,7 @@ static void gfar_reset_task(struct work_struct *work)
{
struct gfar_private *priv = container_of(work, struct gfar_private,
reset_task);
- struct net_device *dev = priv->ndev;
-
- if (dev->flags & IFF_UP) {
- netif_tx_stop_all_queues(dev);
- stop_gfar(dev);
- startup_gfar(dev);
- netif_tx_start_all_queues(dev);
- }
-
- netif_tx_schedule_all(dev);
+ reset_gfar(priv->ndev);
}
static void gfar_timeout(struct net_device *dev)
@@ -2506,13 +2421,26 @@ static void gfar_timeout(struct net_device *dev)
schedule_work(&priv->reset_task);
}
-static void gfar_align_skb(struct sk_buff *skb)
+static void gfar_recycle_skb(struct sk_buff *skb)
{
- /* We need the data buffer to be aligned properly. We will reserve
- * as many bytes as needed to align the data properly
- */
- skb_reserve(skb, RXBUF_ALIGNMENT -
- (((unsigned long) skb->data) & (RXBUF_ALIGNMENT - 1)));
+ struct sk_buff_head *h = &__get_cpu_var(skb_recycle_list);
+ int skb_size = SKB_DATA_ALIGN(GFAR_RXB_REC_SZ + NET_SKB_PAD);
+
+ if (skb_queue_len(h) < DEFAULT_RX_RING_SIZE &&
+ !skb_cloned(skb) && !skb_is_nonlinear(skb) &&
+ skb->fclone == SKB_FCLONE_UNAVAILABLE && !skb_shared(skb) &&
+ skb_end_offset(skb) == skb_size) {
+
+ skb_recycle(skb);
+
+ gfar_align_skb(skb);
+
+ __skb_queue_head(h, skb);
+
+ return;
+ }
+
+ dev_kfree_skb_any(skb);
}
/* Interrupt Handler for Transmit complete */
@@ -2540,7 +2468,6 @@ static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
skb_dirtytx = tx_queue->skb_dirtytx;
while ((skb = tx_queue->tx_skbuff[skb_dirtytx])) {
- unsigned long flags;
frags = skb_shinfo(skb)->nr_frags;
@@ -2571,13 +2498,48 @@ static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
buflen, DMA_TO_DEVICE);
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
+#if defined CONFIG_FSL_GIANFAR_1588
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
+#endif
struct skb_shared_hwtstamps shhwtstamps;
+#if defined CONFIG_FSL_GIANFAR_1588
+ u32 high, low;
+ struct gfar_ptp_time tx_ts;
+ u64 ns;
+
+ if (priv->device_flags &
+ FSL_GIANFAR_DEV_HAS_TS_TO_BUFFER) {
+ /* get tx timestamp out of frame */
+ void *ts;
+ ts = (void *)(((uintptr_t)skb->data + 0x10)
+ & ~0x7);
+ ns = be64_to_cpup(ts);
+ } else
+ /* get tx timestamp from register */
+ ns = gfar_get_tx_timestamp(regs);
+
+ if (unlikely(priv->hwts_tx_en))
+ shhwtstamps.hwtstamp = ns_to_ktime(ns);
+ if (likely(priv->hwts_tx_en_ioctl)) {
+ high = upper_32_bits(ns);
+ low = lower_32_bits(ns);
+ gfar_cnt_to_ptp_time(high, low, &tx_ts);
+ }
+ /* remove tx fcb */
+ skb_pull(skb, GMAC_FCB_LEN + GMAC_TXPAL_LEN);
+ /* pass timestamp back */
+ if (unlikely(priv->hwts_tx_en))
+ skb_tstamp_tx(skb, &shhwtstamps);
+ if (likely(priv->hwts_tx_en_ioctl))
+ gfar_ptp_store_txstamp(dev, skb, &tx_ts);
+#else
u64 *ns = (u64*) (((u32)skb->data + 0x10) & ~0x7);
memset(&shhwtstamps, 0, sizeof(shhwtstamps));
shhwtstamps.hwtstamp = ns_to_ktime(*ns);
skb_pull(skb, GMAC_FCB_LEN + GMAC_TXPAL_LEN);
skb_tstamp_tx(skb, &shhwtstamps);
+#endif
bdp->lstatus &= BD_LFLAG(TXBD_WRAP);
bdp = next;
}
@@ -2594,7 +2556,7 @@ static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
bytes_sent += GFAR_CB(skb)->bytes_sent;
- dev_kfree_skb_any(skb);
+ gfar_recycle_skb(skb);
tx_queue->tx_skbuff[skb_dirtytx] = NULL;
@@ -2602,14 +2564,16 @@ static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
TX_RING_MOD_MASK(tx_ring_size);
howmany++;
- spin_lock_irqsave(&tx_queue->txlock, flags);
+ spin_lock(&tx_queue->txlock);
tx_queue->num_txbdfree += nr_txbds;
- spin_unlock_irqrestore(&tx_queue->txlock, flags);
+ spin_unlock(&tx_queue->txlock);
}
/* If we freed a buffer, we can restart transmission, if necessary */
- if (netif_tx_queue_stopped(txq) && tx_queue->num_txbdfree)
- netif_wake_subqueue(dev, tqi);
+ if (tx_queue->num_txbdfree &&
+ netif_tx_queue_stopped(txq) &&
+ !(test_bit(GFAR_DOWN, &priv->state)))
+ netif_wake_subqueue(priv->ndev, tqi);
/* Update dirty indicators */
tx_queue->skb_dirtytx = skb_dirtytx;
@@ -2618,49 +2582,17 @@ static void gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue)
netdev_tx_completed_queue(txq, howmany, bytes_sent);
}
-static void gfar_schedule_cleanup(struct gfar_priv_grp *gfargrp)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&gfargrp->grplock, flags);
- if (napi_schedule_prep(&gfargrp->napi)) {
- gfar_write(&gfargrp->regs->imask, IMASK_RTX_DISABLED);
- __napi_schedule(&gfargrp->napi);
- } else {
- /* Clear IEVENT, so interrupts aren't called again
- * because of the packets that have already arrived.
- */
- gfar_write(&gfargrp->regs->ievent, IEVENT_RTX_MASK);
- }
- spin_unlock_irqrestore(&gfargrp->grplock, flags);
-
-}
-
-/* Interrupt Handler for Transmit complete */
-static irqreturn_t gfar_transmit(int irq, void *grp_id)
-{
- gfar_schedule_cleanup((struct gfar_priv_grp *)grp_id);
- return IRQ_HANDLED;
-}
-
-static void gfar_new_rxbdp(struct gfar_priv_rx_q *rx_queue, struct rxbd8 *bdp,
- struct sk_buff *skb)
-{
- struct net_device *dev = rx_queue->dev;
- struct gfar_private *priv = netdev_priv(dev);
- dma_addr_t buf;
-
- buf = dma_map_single(priv->dev, skb->data,
- priv->rx_buffer_size, DMA_FROM_DEVICE);
- gfar_init_rxbdp(rx_queue, bdp, buf);
-}
-
static struct sk_buff *gfar_alloc_skb(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
struct sk_buff *skb;
+#ifndef CONFIG_AS_FASTPATH
skb = netdev_alloc_skb(dev, priv->rx_buffer_size + RXBUF_ALIGNMENT);
+#else
+ skb = netdev_alloc_skb(dev, priv->rx_buffer_size + RXBUF_ALIGNMENT +
+ EXTRA_HEADROOM);
+#endif
if (!skb)
return NULL;
@@ -2671,64 +2603,71 @@ static struct sk_buff *gfar_alloc_skb(struct net_device *dev)
struct sk_buff *gfar_new_skb(struct net_device *dev)
{
- return gfar_alloc_skb(dev);
-}
-
-static inline void count_errors(unsigned short status, struct net_device *dev)
-{
struct gfar_private *priv = netdev_priv(dev);
- struct net_device_stats *stats = &dev->stats;
- struct gfar_extra_stats *estats = &priv->extra_stats;
-
- /* If the packet was truncated, none of the other errors matter */
- if (status & RXBD_TRUNCATED) {
- stats->rx_length_errors++;
+ struct sk_buff *skb;
- atomic64_inc(&estats->rx_trunc);
+ if (likely(priv->rx_buffer_size <= DEFAULT_RX_BUFFER_SIZE)) {
+ struct sk_buff_head *h = &__get_cpu_var(skb_recycle_list);
- return;
+ skb = __skb_dequeue(h);
+ if (skb != NULL)
+ return skb;
}
- /* Count the errors, if there were any */
- if (status & (RXBD_LARGE | RXBD_SHORT)) {
- stats->rx_length_errors++;
- if (status & RXBD_LARGE)
- atomic64_inc(&estats->rx_large);
- else
- atomic64_inc(&estats->rx_short);
- }
- if (status & RXBD_NONOCTET) {
- stats->rx_frame_errors++;
- atomic64_inc(&estats->rx_nonoctet);
- }
- if (status & RXBD_CRCERR) {
- atomic64_inc(&estats->rx_crcerr);
- stats->rx_crc_errors++;
- }
- if (status & RXBD_OVERRUN) {
- atomic64_inc(&estats->rx_overrun);
- stats->rx_crc_errors++;
- }
+ return gfar_alloc_skb(dev);
}
irqreturn_t gfar_receive(int irq, void *grp_id)
{
- gfar_schedule_cleanup((struct gfar_priv_grp *)grp_id);
+ struct gfar_priv_grp *grp = (struct gfar_priv_grp *)grp_id;
+ unsigned long flags;
+ u32 imask;
+
+ if (likely(napi_schedule_prep(&grp->napi_rx))) {
+ spin_lock_irqsave(&grp->grplock, flags);
+ imask = gfar_read(&grp->regs->imask);
+ imask &= IMASK_RX_DISABLED;
+ gfar_write(&grp->regs->imask, imask);
+ spin_unlock_irqrestore(&grp->grplock, flags);
+ __napi_schedule(&grp->napi_rx);
+ } else {
+ /* Clear IEVENT, so interrupts aren't called again
+ * because of the packets that have already arrived.
+ */
+ gfar_write(&grp->regs->ievent, IEVENT_RX_MASK);
+ }
+
return IRQ_HANDLED;
}
+EXPORT_SYMBOL(gfar_new_skb);
-static inline void gfar_rx_checksum(struct sk_buff *skb, struct rxfcb *fcb)
+/* Interrupt Handler for Transmit complete */
+static irqreturn_t gfar_transmit(int irq, void *grp_id)
{
- /* If valid headers were found, and valid sums
- * were verified, then we tell the kernel that no
- * checksumming is necessary. Otherwise, it is [FIXME]
- */
- if ((fcb->flags & RXFCB_CSUM_MASK) == (RXFCB_CIP | RXFCB_CTU))
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- else
- skb_checksum_none_assert(skb);
-}
+ struct gfar_priv_grp *grp = (struct gfar_priv_grp *)grp_id;
+ unsigned long flags;
+ u32 imask;
+#ifdef CONFIG_AS_FASTPATH
+ return gfar_enable_tx_queue(irq, grp_id);
+#endif
+
+ if (likely(napi_schedule_prep(&grp->napi_tx))) {
+ spin_lock_irqsave(&grp->grplock, flags);
+ imask = gfar_read(&grp->regs->imask);
+ imask &= IMASK_TX_DISABLED;
+ gfar_write(&grp->regs->imask, imask);
+ spin_unlock_irqrestore(&grp->grplock, flags);
+ __napi_schedule(&grp->napi_tx);
+ } else {
+ /* Clear IEVENT, so interrupts aren't called again
+ * because of the packets that have already arrived.
+ */
+ gfar_write(&grp->regs->ievent, IEVENT_TX_MASK);
+ }
+
+ return IRQ_HANDLED;
+}
/* gfar_process_frame() -- handle one incoming packet if skb isn't NULL. */
static void gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
@@ -2749,6 +2688,32 @@ static void gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
}
/* Get receive timestamp from the skb */
+#if defined CONFIG_FSL_GIANFAR_1588
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) {
+ u32 high, low;
+
+ /* get timestamp */
+ high = *((u32 *)skb->data);
+ low = *(((u32 *)skb->data) + 1);
+ skb_pull(skb, 8);
+ /* proprietary PTP timestamping over ioctl */
+ if (unlikely(priv->hwts_rx_en_ioctl)) {
+ struct gfar_ptp_time rx_ts;
+ /* get rx timestamp */
+ gfar_cnt_to_ptp_time(high, low, &rx_ts);
+ /* parse and store rx timestamp */
+ gfar_ptp_store_rxstamp(dev, skb, &rx_ts);
+ } else if (unlikely(priv->hwts_rx_en)) {
+ /* kernel-API timestamping ? */
+ u64 nsec;
+ struct skb_shared_hwtstamps *hws;
+ hws = skb_hwtstamps(skb);
+ nsec = make64(high, low);
+ hws->hwtstamp = ns_to_ktime(nsec);
+ }
+ } else if (priv->padding)
+ skb_pull(skb, priv->padding);
+#else
if (priv->hwts_rx_en) {
struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
u64 *ns = (u64 *) skb->data;
@@ -2759,7 +2724,7 @@ static void gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
if (priv->padding)
skb_pull(skb, priv->padding);
-
+#endif
if (dev->features & NETIF_F_RXCSUM)
gfar_rx_checksum(skb, fcb);
@@ -2793,6 +2758,10 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
int howmany = 0;
struct gfar_private *priv = netdev_priv(dev);
+#ifdef CONFIG_AS_FASTPATH
+ return gfar_asf_clean_rx_ring(rx_queue, rx_work_limit);
+#endif
+
/* Get the first full descriptor */
bdp = rx_queue->cur_rx;
base = rx_queue->rx_bd_base;
@@ -2837,7 +2806,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
rx_queue->stats.rx_bytes += pkt_len;
skb_record_rx_queue(skb, rx_queue->qindex);
gfar_process_frame(dev, skb, amount_pull,
- &rx_queue->grp->napi);
+ &rx_queue->grp->napi_rx);
} else {
netif_warn(priv, rx_err, dev, "Missing skb!\n");
@@ -2866,66 +2835,82 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit)
return howmany;
}
-static int gfar_poll_sq(struct napi_struct *napi, int budget)
+static int gfar_poll_rx_sq(struct napi_struct *napi, int budget)
{
struct gfar_priv_grp *gfargrp =
- container_of(napi, struct gfar_priv_grp, napi);
+ container_of(napi, struct gfar_priv_grp, napi_rx);
struct gfar __iomem *regs = gfargrp->regs;
- struct gfar_priv_tx_q *tx_queue = gfargrp->priv->tx_queue[0];
- struct gfar_priv_rx_q *rx_queue = gfargrp->priv->rx_queue[0];
+ struct gfar_priv_rx_q *rx_queue = gfargrp->rx_queue;
int work_done = 0;
/* Clear IEVENT, so interrupts aren't called again
* because of the packets that have already arrived
*/
- gfar_write(&regs->ievent, IEVENT_RTX_MASK);
-
- /* run Tx cleanup to completion */
- if (tx_queue->tx_skbuff[tx_queue->skb_dirtytx])
- gfar_clean_tx_ring(tx_queue);
+ gfar_write(&regs->ievent, IEVENT_RX_MASK);
work_done = gfar_clean_rx_ring(rx_queue, budget);
if (work_done < budget) {
+ u32 imask;
napi_complete(napi);
/* Clear the halt bit in RSTAT */
gfar_write(&regs->rstat, gfargrp->rstat);
- gfar_write(&regs->imask, IMASK_DEFAULT);
-
- /* If we are coalescing interrupts, update the timer
- * Otherwise, clear it
- */
- gfar_write(&regs->txic, 0);
- if (likely(tx_queue->txcoalescing))
- gfar_write(&regs->txic, tx_queue->txic);
-
- gfar_write(&regs->rxic, 0);
- if (unlikely(rx_queue->rxcoalescing))
- gfar_write(&regs->rxic, rx_queue->rxic);
+ spin_lock_irq(&gfargrp->grplock);
+ imask = gfar_read(&regs->imask);
+ imask |= IMASK_RX_DEFAULT;
+ gfar_write(&regs->imask, imask);
+ spin_unlock_irq(&gfargrp->grplock);
}
return work_done;
}
-static int gfar_poll(struct napi_struct *napi, int budget)
+static int gfar_poll_tx_sq(struct napi_struct *napi, int budget)
+{
+ struct gfar_priv_grp *gfargrp =
+ container_of(napi, struct gfar_priv_grp, napi_tx);
+ struct gfar __iomem *regs = gfargrp->regs;
+ struct gfar_priv_tx_q *tx_queue = gfargrp->tx_queue;
+ u32 imask;
+
+ /* Clear IEVENT, so interrupts aren't called again
+ * because of the packets that have already arrived
+ */
+ gfar_write(&regs->ievent, IEVENT_TX_MASK);
+
+ /* run Tx cleanup to completion */
+ if (tx_queue->tx_skbuff[tx_queue->skb_dirtytx])
+ gfar_clean_tx_ring(tx_queue);
+
+ napi_complete(napi);
+
+ spin_lock_irq(&gfargrp->grplock);
+ imask = gfar_read(&regs->imask);
+ imask |= IMASK_TX_DEFAULT;
+ gfar_write(&regs->imask, imask);
+ spin_unlock_irq(&gfargrp->grplock);
+
+ return 0;
+}
+
+#ifdef GFAR_MQ_POLLING
+static int gfar_poll_rx(struct napi_struct *napi, int budget)
{
struct gfar_priv_grp *gfargrp =
- container_of(napi, struct gfar_priv_grp, napi);
+ container_of(napi, struct gfar_priv_grp, napi_rx);
struct gfar_private *priv = gfargrp->priv;
struct gfar __iomem *regs = gfargrp->regs;
- struct gfar_priv_tx_q *tx_queue = NULL;
struct gfar_priv_rx_q *rx_queue = NULL;
int work_done = 0, work_done_per_q = 0;
int i, budget_per_q = 0;
- int has_tx_work;
unsigned long rstat_rxf;
int num_act_queues;
/* Clear IEVENT, so interrupts aren't called again
* because of the packets that have already arrived
*/
- gfar_write(&regs->ievent, IEVENT_RTX_MASK);
+ gfar_write(&regs->ievent, IEVENT_RX_MASK);
rstat_rxf = gfar_read(&regs->rstat) & RSTAT_RXF_MASK;
@@ -2933,66 +2918,83 @@ static int gfar_poll(struct napi_struct *napi, int budget)
if (num_act_queues)
budget_per_q = budget/num_act_queues;
- while (1) {
- has_tx_work = 0;
- for_each_set_bit(i, &gfargrp->tx_bit_map, priv->num_tx_queues) {
- tx_queue = priv->tx_queue[i];
- /* run Tx cleanup to completion */
- if (tx_queue->tx_skbuff[tx_queue->skb_dirtytx]) {
- gfar_clean_tx_ring(tx_queue);
- has_tx_work = 1;
- }
- }
+ for_each_set_bit(i, &gfargrp->rx_bit_map, priv->num_rx_queues) {
+ /* skip queue if not active */
+ if (!(rstat_rxf & (RSTAT_CLEAR_RXF0 >> i)))
+ continue;
- for_each_set_bit(i, &gfargrp->rx_bit_map, priv->num_rx_queues) {
- /* skip queue if not active */
- if (!(rstat_rxf & (RSTAT_CLEAR_RXF0 >> i)))
- continue;
-
- rx_queue = priv->rx_queue[i];
- work_done_per_q =
- gfar_clean_rx_ring(rx_queue, budget_per_q);
- work_done += work_done_per_q;
-
- /* finished processing this queue */
- if (work_done_per_q < budget_per_q) {
- /* clear active queue hw indication */
- gfar_write(&regs->rstat,
- RSTAT_CLEAR_RXF0 >> i);
- rstat_rxf &= ~(RSTAT_CLEAR_RXF0 >> i);
- num_act_queues--;
-
- if (!num_act_queues)
- break;
- /* recompute budget per Rx queue */
- budget_per_q =
- (budget - work_done) / num_act_queues;
- }
+ rx_queue = priv->rx_queue[i];
+ work_done_per_q =
+ gfar_clean_rx_ring(rx_queue, budget_per_q);
+ work_done += work_done_per_q;
+
+ /* finished processing this queue */
+ if (work_done_per_q < budget_per_q) {
+ /* clear active queue hw indication */
+ gfar_write(&regs->rstat,
+ RSTAT_CLEAR_RXF0 >> i);
+ num_act_queues--;
+
+ if (!num_act_queues)
+ break;
}
+ }
- if (work_done >= budget)
- break;
+ if (!num_act_queues) {
+ u32 imask;
+ napi_complete(napi);
- if (!num_act_queues && !has_tx_work) {
+ /* Clear the halt bit in RSTAT */
+ gfar_write(&regs->rstat, gfargrp->rstat);
- napi_complete(napi);
+ spin_lock_irq(&gfargrp->grplock);
+ imask = gfar_read(&regs->imask);
+ imask |= IMASK_RX_DEFAULT;
+ gfar_write(&regs->imask, imask);
+ spin_unlock_irq(&gfargrp->grplock);
+ }
- /* Clear the halt bit in RSTAT */
- gfar_write(&regs->rstat, gfargrp->rstat);
+ return work_done;
+}
- gfar_write(&regs->imask, IMASK_DEFAULT);
+static int gfar_poll_tx(struct napi_struct *napi, int budget)
+{
+ struct gfar_priv_grp *gfargrp =
+ container_of(napi, struct gfar_priv_grp, napi_tx);
+ struct gfar_private *priv = gfargrp->priv;
+ struct gfar __iomem *regs = gfargrp->regs;
+ struct gfar_priv_tx_q *tx_queue = NULL;
+ int has_tx_work = 0;
+ int i;
- /* If we are coalescing interrupts, update the timer
- * Otherwise, clear it
- */
- gfar_configure_coalescing(priv, gfargrp->rx_bit_map,
- gfargrp->tx_bit_map);
- break;
+ /* Clear IEVENT, so interrupts aren't called again
+ * because of the packets that have already arrived
+ */
+ gfar_write(&regs->ievent, IEVENT_TX_MASK);
+
+ for_each_set_bit(i, &gfargrp->tx_bit_map, priv->num_tx_queues) {
+ tx_queue = priv->tx_queue[i];
+ /* run Tx cleanup to completion */
+ if (tx_queue->tx_skbuff[tx_queue->skb_dirtytx]) {
+ gfar_clean_tx_ring(tx_queue);
+ has_tx_work = 1;
}
}
- return work_done;
+ if (!has_tx_work) {
+ u32 imask;
+ napi_complete(napi);
+
+ spin_lock_irq(&gfargrp->grplock);
+ imask = gfar_read(&regs->imask);
+ imask |= IMASK_TX_DEFAULT;
+ gfar_write(&regs->imask, imask);
+ spin_unlock_irq(&gfargrp->grplock);
+ }
+
+ return 0;
}
+#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
/* Polling 'interrupt' - used by things like netconsole to send skbs
@@ -3097,12 +3099,11 @@ static void adjust_link(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
struct gfar __iomem *regs = priv->gfargrp[0].regs;
- unsigned long flags;
struct phy_device *phydev = priv->phydev;
int new_state = 0;
- local_irq_save(flags);
- lock_tx_qs(priv);
+ if (test_bit(GFAR_RESETTING, &priv->state))
+ return;
if (phydev->link) {
u32 tempval1 = gfar_read(&regs->maccfg1);
@@ -3174,8 +3175,6 @@ static void adjust_link(struct net_device *dev)
if (new_state && netif_msg_link(priv))
phy_print_status(phydev);
- unlock_tx_qs(priv);
- local_irq_restore(flags);
}
/* Update the hash table based on the current list of multicast
@@ -3374,21 +3373,12 @@ static irqreturn_t gfar_error(int irq, void *grp_id)
if (events & IEVENT_CRL)
dev->stats.tx_aborted_errors++;
if (events & IEVENT_XFUN) {
- unsigned long flags;
-
netif_dbg(priv, tx_err, dev,
"TX FIFO underrun, packet dropped\n");
dev->stats.tx_dropped++;
atomic64_inc(&priv->extra_stats.tx_underrun);
- local_irq_save(flags);
- lock_tx_qs(priv);
-
- /* Reactivate the Tx Queues */
- gfar_write(&regs->tstat, gfargrp->tstat);
-
- unlock_tx_qs(priv);
- local_irq_restore(flags);
+ schedule_work(&priv->reset_task);
}
netif_dbg(priv, tx_err, dev, "Transmit Error\n");
}
@@ -3446,4 +3436,29 @@ static struct platform_driver gfar_driver = {
.remove = gfar_remove,
};
-module_platform_driver(gfar_driver);
+static int __init gfar_init(void)
+{
+ int i;
+
+ for_each_possible_cpu(i) {
+ struct sk_buff_head *h = &per_cpu(skb_recycle_list, i);
+ skb_queue_head_init(h);
+ }
+
+ return platform_driver_register(&gfar_driver);
+}
+
+static void __exit gfar_exit(void)
+{
+ int i;
+
+ for_each_possible_cpu(i) {
+ struct sk_buff_head *h = &per_cpu(skb_recycle_list, i);
+ skb_queue_purge(h);
+ }
+
+ platform_driver_unregister(&gfar_driver);
+}
+
+module_init(gfar_init);
+module_exit(gfar_exit);
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index 04112b9..44a32ac 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -9,7 +9,7 @@
* Maintainer: Kumar Gala
* Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com>
*
- * Copyright 2002-2009, 2011 Freescale Semiconductor, Inc.
+ * Copyright 2002-2009, 2011-2013 Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -38,6 +38,10 @@
#include <linux/mm.h>
#include <linux/mii.h>
#include <linux/phy.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+
#include <asm/io.h>
#include <asm/irq.h>
@@ -47,6 +51,10 @@
#include <linux/workqueue.h>
#include <linux/ethtool.h>
+#if defined CONFIG_FSL_GIANFAR_1588
+#include <linux/circ_buf.h>
+#endif
+
struct ethtool_flow_spec_container {
struct ethtool_rx_flow_spec fs;
struct list_head list;
@@ -72,6 +80,10 @@ struct ethtool_rx_list {
/* Number of bytes to align the rx bufs to */
#define RXBUF_ALIGNMENT 64
+#ifdef CONFIG_AS_FASTPATH
+/* Headroom required for IPSec processing in ASF */
+#define EXTRA_HEADROOM 128
+#endif
/* The number of bytes which composes a unit for the purpose of
* allocating data buffers. ie-for any given MTU, the data buffer
* will be the next highest multiple of 512 bytes. */
@@ -150,6 +162,62 @@ extern const char gfar_driver_version[];
| SUPPORTED_Pause \
| SUPPORTED_Asym_Pause)
+#if defined CONFIG_FSL_GIANFAR_1588
+/* 1588 defines */
+#define make64(high, low) (((u64)(high) << 32) | (low))
+
+#define PTP_ENBL_TXTS_IOCTL SIOCDEVPRIVATE
+#define PTP_DSBL_TXTS_IOCTL (SIOCDEVPRIVATE + 1)
+#define PTP_ENBL_RXTS_IOCTL (SIOCDEVPRIVATE + 2)
+#define PTP_DSBL_RXTS_IOCTL (SIOCDEVPRIVATE + 3)
+#define PTP_GET_TX_TIMESTAMP (SIOCDEVPRIVATE + 4)
+#define PTP_GET_RX_TIMESTAMP (SIOCDEVPRIVATE + 5)
+#define PTP_SET_TIME (SIOCDEVPRIVATE + 6)
+#define PTP_GET_TIME (SIOCDEVPRIVATE + 7)
+#define PTP_SET_FIPER_ALARM (SIOCDEVPRIVATE + 8)
+#define PTP_SET_ADJ (SIOCDEVPRIVATE + 9)
+#define PTP_GET_ADJ (SIOCDEVPRIVATE + 10)
+#define PTP_CLEANUP_TS (SIOCDEVPRIVATE + 11)
+
+#define DEFAULT_PTP_TX_BUF_SZ 1024
+#define DEFAULT_PTP_RX_BUF_SZ 2048
+
+/* The threshold between the current found one and the oldest one */
+#define TS_ACCUMULATION_THRESHOLD 50
+
+#define GFAR_PTP_SOURCE_PORT_LENGTH 10
+#define GFAR_PTP_HEADER_SEQ_OFFS 30
+#define GFAR_PTP_SPID_OFFS 20
+#define GFAR_PTP_HEADER_SZE 34
+#define GFAR_PTP_EVENT_PORT 0x013F
+
+#define GFAR_VLAN_QINQ_1 0x9100
+#define GFAR_VLAN_QINQ_2 0x9200
+#define GFAR_VLAN_QINQ_3 0x9300
+#define GFAR_VLAN_QINQ_4 0x88A8
+#define GFAR_VLAN_TAG_LEN 0x04
+#define GFAR_ETHTYPE_LEN 0x02
+#define GFAR_PACKET_TYPE_UDP 0x11
+/* 1588-2008 network protocol enumeration values */
+#define GFAR_PTP_PROT_IPV4 1
+#define GFAR_PTP_PROT_IPV6 2
+#define GFAR_PTP_PROT_802_3 3
+#define GFAR_PTP_PROT_DONTCARE 0xFFFF
+
+/* 1588 Module Registers bits */
+#define TMR_CTRL_CKSEL_MASK 0x00000003
+#define TMR_CTRL_ENABLE 0x00000004
+#define TMR_RTPE 0x00008000
+#define TMR_CTRL_TCLK_MASK 0x03ff0000
+#define TMR_CTRL_FIPER_START 0x10000000
+#define ONE_GIGA 1000000000
+
+/*Alarm to traigger at 15sec boundary */
+#define TMR_ALARM1_L 0xD964B800
+#define TMR_ALARM1_H 0x00000045
+#define NANOSEC_PER_SEC 1000000000
+#endif
+
/* TBI register addresses */
#define MII_TBICON 0x11
@@ -378,8 +446,11 @@ extern const char gfar_driver_version[];
IMASK_RXFEN0 | IMASK_BSY | IMASK_EBERR | IMASK_BABR | \
IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_DPE \
| IMASK_PERR)
-#define IMASK_RTX_DISABLED ((~(IMASK_RXFEN0 | IMASK_TXFEN | IMASK_BSY)) \
- & IMASK_DEFAULT)
+#define IMASK_RX_DEFAULT (IMASK_RXFEN0 | IMASK_BSY)
+#define IMASK_TX_DEFAULT (IMASK_TXFEN | IMASK_TXBEN)
+
+#define IMASK_RX_DISABLED ((~(IMASK_RX_DEFAULT)) & IMASK_DEFAULT)
+#define IMASK_TX_DISABLED ((~(IMASK_TX_DEFAULT)) & IMASK_DEFAULT)
/* Fifo management */
#define FIFO_TX_THR_MASK 0x01ff
@@ -410,7 +481,9 @@ extern const char gfar_driver_version[];
/* This default RIR value directly corresponds
* to the 3-bit hash value generated */
-#define DEFAULT_RIR0 0x05397700
+#define DEFAULT_8RXQ_RIR0 0x05397700
+/* Map even hash values to Q0, and odd ones to Q1 */
+#define DEFAULT_2RXQ_RIR0 0x04104100
/* RQFCR register bits */
#define RQFCR_GPI 0x80000000
@@ -655,6 +728,80 @@ struct gfar_extra_stats {
/* Number of stats exported via ethtool */
#define GFAR_STATS_LEN (GFAR_RMON_LEN + GFAR_EXTRA_STATS_LEN)
+#if defined CONFIG_FSL_GIANFAR_1588
+/* IEEE-1588 Timer Controller Registers */
+struct gfar_regs_1588 {
+ u32 tmr_ctrl; /* 0x.e00 - Timer Control Register */
+ u32 tmr_tevent; /* 0x.e04 - Timer stamp event register */
+ u32 tmr_temask; /* 0x.e08 - Timer event mask register */
+ u32 tmr_pevent; /* 0x.e0c - Timer stamp event register */
+ u32 tmr_pemask; /* 0x.e10 - Timer event mask register */
+ u32 tmr_stat; /* 0x.e14 - Timer stamp status register */
+ u32 tmr_cnt_h; /* 0x.e18 - Timer counter high register */
+ u32 tmr_cnt_l; /* 0x.e1c - Timer counter low register */
+ u32 tmr_add; /* 0x.e20 - Timer dirft compensation */
+ /* addend register */
+ u32 tmr_acc; /* 0x.e24 - Timer accumulator register */
+ u32 tmr_prsc; /* 0x.e28 - Timer prescale register */
+ u8 res24a[4]; /* 0x.e2c - 0x.e2f reserved */
+ u32 tmr_off_h; /* 0x.e30 - Timer offset high register */
+ u32 tmr_off_l; /* 0x.e34 - Timer offset low register */
+ u8 res24b[8]; /* 0x.e38 - 0x.e3f reserved */
+ u32 tmr_alarm1_h; /* 0x.e40 - Timer alarm 1 high register */
+ u32 tmr_alarm1_l; /* 0x.e44 - Timer alarm 1 low register */
+ u32 tmr_alarm2_h; /* 0x.e48 - Timer alarm 2 high register */
+ u32 tmr_alarm2_l; /* 0x.e4c - Timer alarm 2 low register */
+ u8 res24c[48]; /* 0x.e50 - 0x.e7f reserved */
+ u32 tmr_fiper1; /* 0x.e80 - Timer fixed period register 1 */
+ u32 tmr_fiper2; /* 0x.e84 - Timer fixed period register 2 */
+ u32 tmr_fiper3; /* 0x.e88 - Timer fixed period register 3 */
+ u8 res24d[20]; /* 0x.e8c - 0x.ebf reserved */
+ u32 tmr_etts1_h; /* 0x.ea0 - Timer stamp high of */
+ /* general purpose external trigger 1 */
+ u32 tmr_etts1_l; /* 0x.ea4 - Timer stamp low of */
+ /* general purpose external trigger 1 */
+ u32 tmr_etts2_h; /* 0x.ea8 - Timer stamp high of */
+ /* general purpose external trigger 2 */
+ u32 tmr_etts2_l; /* 0x.eac - Timer stamp low of */
+};
+
+/* struct needed to identify a timestamp */
+struct gfar_ptp_ident {
+ u8 version;
+ u8 msg_type;
+ u16 netw_prot;
+ u16 seq_id;
+ u8 snd_port_id[GFAR_PTP_SOURCE_PORT_LENGTH];
+};
+
+/* timestamp format in 1588-2008 */
+struct gfar_ptp_time {
+ u64 sec; /* just 48 bit used */
+ u32 nsec;
+};
+
+/* needed for timestamp data over ioctl */
+struct gfar_ptp_data {
+ struct gfar_ptp_ident ident;
+ struct gfar_ptp_time ts;
+};
+
+/* circular buffer for ptp timestamps over ioctl */
+struct gfar_ptp_circular {
+ struct circ_buf circ_buf;
+ u32 size;
+ spinlock_t ptp_lock;
+};
+
+struct gfar_ptp_attr_t {
+ u32 tclk_period;
+ u32 nominal_freq;
+ u32 sysclock_freq;
+ u32 tmr_fiper1;
+ u32 freq_comp;
+};
+#endif
+
struct gfar {
u32 tsec_id; /* 0x.000 - Controller ID register */
u32 tsec_id2; /* 0x.004 - Controller ID2 register */
@@ -727,7 +874,19 @@ struct gfar {
u32 tbase6; /* 0x.234 - TxBD Base Address of ring 6 */
u8 res10g[4];
u32 tbase7; /* 0x.23c - TxBD Base Address of ring 7 */
+#if defined CONFIG_FSL_GIANFAR_1588
+ u8 res10h[64];
+ u32 tmr_txts1_id; /* 0x.280 Tx time stamp identification */
+ u32 tmr_txts2_id; /* 0x.284 Tx time stamp Identification */
+ u8 res10i[56];
+ u32 tmr_txts1_h; /* 0x.2c0 Tx time stamp high */
+ u32 tmr_txts1_l; /* 0x.2c4 Tx Time Stamp low */
+ u32 tmr_txts2_h; /* 0x.2c8 Tx time stamp high */
+ u32 tmr_txts2_l; /* 0x.2cc Tx Time Stamp low */
+ u8 res10j[48];
+#else
u8 res10[192];
+#endif
u32 rctrl; /* 0x.300 - Receive Control Register */
u32 rstat; /* 0x.304 - Receive Status Register */
u8 res12[8];
@@ -778,7 +937,14 @@ struct gfar {
u32 rbase6; /* 0x.434 - RxBD base address of ring 6 */
u8 res17g[4];
u32 rbase7; /* 0x.43c - RxBD base address of ring 7 */
+#if defined CONFIG_FSL_GIANFAR_1588
+ u8 res17h[128];
+ u32 tmr_rxts_h; /* 0x.4c0 Rx Time Stamp high */
+ u32 tmr_rxts_l; /* 0x.4c4 Rx Time Stamp low */
+ u8 res17i[56];
+#else
u8 res17[192];
+#endif
u32 maccfg1; /* 0x.500 - MAC Configuration 1 Register */
u32 maccfg2; /* 0x.504 - MAC Configuration 2 Register */
u32 ipgifg; /* 0x.508 - Inter Packet Gap/Inter Frame Gap Register */
@@ -847,7 +1013,12 @@ struct gfar {
u8 res23c[248];
u32 attr; /* 0x.bf8 - Attributes Register */
u32 attreli; /* 0x.bfc - Attributes Extract Length and Extract Index Register */
+#if defined CONFIG_FSL_GIANFAR_1588
+ u8 res24[512];
+ struct gfar_regs_1588 regs_1588;
+#else
u8 res24[688];
+#endif
u32 isrg0; /* 0x.eb0 - Interrupt steering group 0 register */
u32 isrg1; /* 0x.eb4 - Interrupt steering group 1 register */
u32 isrg2; /* 0x.eb8 - Interrupt steering group 2 register */
@@ -881,20 +1052,23 @@ struct gfar {
#define FSL_GIANFAR_DEV_HAS_CSUM 0x00000010
#define FSL_GIANFAR_DEV_HAS_VLAN 0x00000020
#define FSL_GIANFAR_DEV_HAS_EXTENDED_HASH 0x00000040
-#define FSL_GIANFAR_DEV_HAS_PADDING 0x00000080
#define FSL_GIANFAR_DEV_HAS_MAGIC_PACKET 0x00000100
#define FSL_GIANFAR_DEV_HAS_BD_STASHING 0x00000200
#define FSL_GIANFAR_DEV_HAS_BUF_STASHING 0x00000400
#define FSL_GIANFAR_DEV_HAS_TIMER 0x00000800
+#if defined CONFIG_FSL_GIANFAR_1588
+#define FSL_GIANFAR_DEV_HAS_TS_TO_BUFFER 0x00001000
+#endif
+
#if (MAXGROUPS == 2)
#define DEFAULT_MAPPING 0xAA
#else
#define DEFAULT_MAPPING 0xFF
#endif
-#define ISRG_SHIFT_TX 0x10
-#define ISRG_SHIFT_RX 0x18
+#define ISRG_RR0 0x80000000
+#define ISRG_TR0 0x00800000
/* The same driver can operate in two modes */
/* SQ_SG_MODE: Single Queue Single Group Mode
@@ -906,6 +1080,22 @@ enum {
MQ_MG_MODE
};
+/* GFAR_SQ_POLLING: Single Queue NAPI polling mode
+ * The driver supports a single pair of RX/Tx queues
+ * per interrupt group (Rx/Tx int line). MQ_MG mode
+ * devices have 2 interrupt groups, so the device will
+ * have a total of 2 Tx and 2 Rx queues in this case.
+ * GFAR_MQ_POLLING: Multi Queue NAPI polling mode
+ * The driver supports all the 8 Rx and Tx HW queues
+ * each queue mapped by the Device Tree to one of
+ * the 2 interrupt groups. This mode implies significant
+ * processing overhead (CPU and controller level).
+ */
+enum gfar_poll_mode {
+ GFAR_SQ_POLLING = 0,
+ GFAR_MQ_POLLING
+};
+
/*
* Per TX queue stats
*/
@@ -967,7 +1157,6 @@ struct rx_q_stats {
/**
* struct gfar_priv_rx_q - per rx queue structure
- * @rxlock: per queue rx spin lock
* @rx_skbuff: skb pointers
* @skb_currx: currently use skb pointer
* @rx_bd_base: First rx buffer descriptor
@@ -980,8 +1169,7 @@ struct rx_q_stats {
*/
struct gfar_priv_rx_q {
- spinlock_t rxlock __attribute__ ((aligned (SMP_CACHE_BYTES)));
- struct sk_buff ** rx_skbuff;
+ struct sk_buff **rx_skbuff __aligned(SMP_CACHE_BYTES);
dma_addr_t rx_bd_dma_base;
struct rxbd8 *rx_bd_base;
struct rxbd8 *cur_rx;
@@ -1017,17 +1205,20 @@ struct gfar_irqinfo {
*/
struct gfar_priv_grp {
- spinlock_t grplock __attribute__ ((aligned (SMP_CACHE_BYTES)));
- struct napi_struct napi;
- struct gfar_private *priv;
+ spinlock_t grplock __aligned(SMP_CACHE_BYTES);
+ struct napi_struct napi_rx;
+ struct napi_struct napi_tx;
struct gfar __iomem *regs;
- unsigned int rstat;
- unsigned long num_rx_queues;
- unsigned long rx_bit_map;
- /* cacheline 3 */
+ struct gfar_priv_tx_q *tx_queue;
+ struct gfar_priv_rx_q *rx_queue;
unsigned int tstat;
+ unsigned int rstat;
+
+ struct gfar_private *priv;
unsigned long num_tx_queues;
unsigned long tx_bit_map;
+ unsigned long num_rx_queues;
+ unsigned long rx_bit_map;
struct gfar_irqinfo *irqinfo[GFAR_NUM_IRQS];
};
@@ -1042,6 +1233,11 @@ enum gfar_errata {
GFAR_ERRATA_12 = 0x08, /* a.k.a errata eTSEC49 */
};
+enum gfar_dev_state {
+ GFAR_DOWN = 1,
+ GFAR_RESETTING
+};
+
/* Struct stolen almost completely (and shamelessly) from the FCC enet source
* (Ok, that's not so true anymore, but there is a family resemblance)
* The GFAR buffer descriptors track the ring buffers. The rx_bd_base
@@ -1052,8 +1248,6 @@ enum gfar_errata {
* the buffer descriptor determines the actual condition.
*/
struct gfar_private {
- unsigned int num_rx_queues;
-
struct device *dev;
struct net_device *ndev;
enum gfar_errata errata;
@@ -1061,24 +1255,43 @@ struct gfar_private {
u16 uses_rxfcb;
u16 padding;
+ u32 device_flags;
+#if defined CONFIG_FSL_GIANFAR_1588
+ /* HW TX timestamping enabled flag */
+ u16 hwts_tx_en;
+ u16 hwts_tx_en_ioctl;
+#else
/* HW time stamping enabled flag */
int hwts_rx_en;
int hwts_tx_en;
-
+#endif
struct gfar_priv_tx_q *tx_queue[MAX_TX_QS];
struct gfar_priv_rx_q *rx_queue[MAX_RX_QS];
struct gfar_priv_grp gfargrp[MAXGROUPS];
- u32 device_flags;
+ unsigned long state;
- unsigned int mode;
+ unsigned short mode;
+ unsigned short poll_mode;
unsigned int num_tx_queues;
+ unsigned int num_rx_queues;
unsigned int num_grps;
/* Network Statistics */
struct gfar_extra_stats extra_stats;
+#if defined CONFIG_FSL_GIANFAR_1588
+ /* HW RX timestamping enabled flag */
+ u16 hwts_rx_en;
+ u16 hwts_rx_en_ioctl;
+
+ /* 1588 stuff */
+ struct gfar_regs_1588 __iomem *ptimer;
+ struct gfar_ptp_circular tx_timestamps;
+ struct gfar_ptp_circular rx_timestamps;
+#endif
+
/* PHY stuff */
phy_interface_t interface;
struct device_node *phy_node;
@@ -1114,6 +1327,9 @@ struct gfar_private {
unsigned int total_tx_ring_size;
unsigned int total_rx_ring_size;
+ u32 rqueue;
+ u32 tqueue;
+
/* RX per device parameters */
unsigned int rx_stash_size;
unsigned int rx_stash_index;
@@ -1128,11 +1344,6 @@ struct gfar_private {
u32 __iomem *hash_regs[16];
int hash_width;
- /* global parameters */
- unsigned int fifo_threshold;
- unsigned int fifo_starve;
- unsigned int fifo_starve_off;
-
/*Filer table*/
unsigned int ftp_rqfpr[MAX_FILER_IDX + 1];
unsigned int ftp_rqfcr[MAX_FILER_IDX + 1];
@@ -1177,21 +1388,55 @@ static inline void gfar_read_filer(struct gfar_private *priv,
*fpr = gfar_read(&regs->rqfpr);
}
-extern void lock_rx_qs(struct gfar_private *priv);
-extern void lock_tx_qs(struct gfar_private *priv);
-extern void unlock_rx_qs(struct gfar_private *priv);
-extern void unlock_tx_qs(struct gfar_private *priv);
-extern irqreturn_t gfar_receive(int irq, void *dev_id);
-extern int startup_gfar(struct net_device *dev);
-extern void stop_gfar(struct net_device *dev);
-extern void gfar_halt(struct net_device *dev);
-extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev,
- int enable, u32 regnum, u32 read);
-extern void gfar_configure_coalescing_all(struct gfar_private *priv);
-void gfar_init_sysfs(struct net_device *dev);
+static inline void gfar_write_isrg(struct gfar_private *priv)
+{
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
+ u32 __iomem *baddr = &regs->isrg0;
+ u32 isrg = 0;
+ int grp_idx, i;
+
+ for (grp_idx = 0; grp_idx < priv->num_grps; grp_idx++) {
+ struct gfar_priv_grp *grp = &priv->gfargrp[grp_idx];
+
+ for_each_set_bit(i, &grp->rx_bit_map, priv->num_rx_queues) {
+ isrg |= (ISRG_RR0 >> i);
+ }
+
+ for_each_set_bit(i, &grp->tx_bit_map, priv->num_tx_queues) {
+ isrg |= (ISRG_TR0 >> i);
+ }
+
+ gfar_write(baddr, isrg);
+
+ baddr++;
+ isrg = 0;
+ }
+}
+
+irqreturn_t gfar_receive(int irq, void *dev_id);
+int startup_gfar(struct net_device *dev);
+void stop_gfar(struct net_device *dev);
+void reset_gfar(struct net_device *dev);
+void gfar_mac_reset(struct gfar_private *priv);
+void gfar_halt(struct gfar_private *priv);
+void gfar_start(struct gfar_private *priv);
+#if defined CONFIG_FSL_GIANFAR_1588
+void gfar_1588_start(struct gfar_private *priv);
+void gfar_1588_stop(struct gfar_private *priv);
+int gfar_ptp_init(struct device_node *np, struct gfar_private *priv);
+void gfar_ptp_cleanup(struct gfar_private *priv);
+int gfar_ioctl_1588(struct net_device *dev, struct ifreq *ifr, int cmd);
+void gfar_ptp_store_txstamp(struct net_device *dev,
+ struct sk_buff *skb, struct gfar_ptp_time *tx_ts);
+void gfar_ptp_store_rxstamp(struct net_device *dev,
+ struct sk_buff *skb, struct gfar_ptp_time *rx_ts);
+void gfar_cnt_to_ptp_time(u32 high, u32 low, struct gfar_ptp_time *time);
+u64 gfar_get_tx_timestamp(struct gfar __iomem *regs);
+#endif
+void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev, int enable,
+ u32 regnum, u32 read);
+void gfar_configure_coalescing_all(struct gfar_private *priv);
int gfar_set_features(struct net_device *dev, netdev_features_t features);
-extern void gfar_check_rx_parser_mode(struct gfar_private *priv);
-extern void gfar_vlan_mode(struct net_device *dev, netdev_features_t features);
extern const struct ethtool_ops gfar_ethtool_ops;
@@ -1226,4 +1471,156 @@ struct filer_table {
/* The gianfar_ptp module will set this variable */
extern int gfar_phc_index;
+static inline struct txbd8 *skip_txbd(struct txbd8 *bdp, int stride,
+ struct txbd8 *base, int ring_size)
+{
+ struct txbd8 *new_bd = bdp + stride;
+ return (new_bd >= (base + ring_size)) ? (new_bd - ring_size) : new_bd;
+}
+
+static inline struct txbd8 *next_txbd(struct txbd8 *bdp, struct txbd8 *base,
+ int ring_size)
+{
+ return skip_txbd(bdp, 1, base, ring_size);
+}
+
+static inline struct txfcb *gfar_add_fcb(struct sk_buff *skb)
+{
+ struct txfcb *fcb = (struct txfcb *)skb_push(skb, GMAC_FCB_LEN);
+ memset(fcb, 0, GMAC_FCB_LEN);
+ return fcb;
+}
+
+static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb,
+ int fcb_length)
+{
+ /* If we're here, it's a IP packet with a TCP or UDP
+ * payload. We set it to checksum, using a pseudo-header
+ * we provide
+ */
+ u8 flags = TXFCB_DEFAULT;
+
+ /* Tell the controller what the protocol is
+ * And provide the already calculated phcs
+ */
+ if (ip_hdr(skb)->protocol == IPPROTO_UDP) {
+ flags |= TXFCB_UDP;
+ fcb->phcs = udp_hdr(skb)->check;
+ } else
+ fcb->phcs = tcp_hdr(skb)->check;
+
+ /* l3os is the distance between the start of the
+ * frame (skb->data) and the start of the IP hdr.
+ * l4os is the distance between the start of the
+ * l3 hdr and the l4 hdr
+ */
+ fcb->l3os = (u16)(skb_network_offset(skb) - fcb_length);
+ fcb->l4os = skb_network_header_len(skb);
+ fcb->flags = flags;
+}
+
+static inline bool gfar_csum_errata_12(struct gfar_private *priv,
+ unsigned long fcb_addr)
+{
+ return gfar_has_errata(priv, GFAR_ERRATA_12) &&
+ (fcb_addr % 0x20) > 0x18;
+}
+
+static inline bool gfar_csum_errata_76(struct gfar_private *priv,
+ unsigned int len)
+{
+ return gfar_has_errata(priv, GFAR_ERRATA_76) &&
+ (len > 2500);
+}
+
+static inline void gfar_init_rxbdp(struct gfar_priv_rx_q *rx_queue,
+ struct rxbd8 *bdp, dma_addr_t buf)
+{
+ u32 lstatus;
+
+ bdp->bufPtr = buf;
+
+ lstatus = BD_LFLAG(RXBD_EMPTY | RXBD_INTERRUPT);
+ if (bdp == rx_queue->rx_bd_base + rx_queue->rx_ring_size - 1)
+ lstatus |= BD_LFLAG(RXBD_WRAP);
+
+ eieio();
+
+ bdp->lstatus = lstatus;
+}
+
+static inline void gfar_new_rxbdp(struct gfar_priv_rx_q *rx_queue,
+ struct rxbd8 *bdp, struct sk_buff *skb)
+{
+ struct net_device *dev = rx_queue->dev;
+ struct gfar_private *priv = netdev_priv(dev);
+ dma_addr_t buf;
+
+ buf = dma_map_single(priv->dev, skb->data,
+ priv->rx_buffer_size, DMA_FROM_DEVICE);
+ gfar_init_rxbdp(rx_queue, bdp, buf);
+}
+
+static inline void count_errors(unsigned short status, struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct net_device_stats *stats = &dev->stats;
+ struct gfar_extra_stats *estats = &priv->extra_stats;
+
+ /* If the packet was truncated, none of the other errors matter */
+ if (status & RXBD_TRUNCATED) {
+ stats->rx_length_errors++;
+
+ atomic64_inc(&estats->rx_trunc);
+
+ return;
+ }
+ /* Count the errors, if there were any */
+ if (status & (RXBD_LARGE | RXBD_SHORT)) {
+ stats->rx_length_errors++;
+
+ if (status & RXBD_LARGE)
+ atomic64_inc(&estats->rx_large);
+ else
+ atomic64_inc(&estats->rx_short);
+ }
+ if (status & RXBD_NONOCTET) {
+ stats->rx_frame_errors++;
+ atomic64_inc(&estats->rx_nonoctet);
+ }
+ if (status & RXBD_CRCERR) {
+ atomic64_inc(&estats->rx_crcerr);
+ stats->rx_crc_errors++;
+ }
+ if (status & RXBD_OVERRUN) {
+ atomic64_inc(&estats->rx_overrun);
+ stats->rx_crc_errors++;
+ }
+}
+
+static inline void gfar_rx_checksum(struct sk_buff *skb, struct rxfcb *fcb)
+{
+ /* If valid headers were found, and valid sums
+ * were verified, then we tell the kernel that no
+ * checksumming is necessary. Otherwise, it is [FIXME]
+ */
+ if ((fcb->flags & RXFCB_CSUM_MASK) == (RXFCB_CIP | RXFCB_CTU))
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb_checksum_none_assert(skb);
+}
+
+static inline void gfar_align_skb(struct sk_buff *skb)
+{
+#ifdef CONFIG_AS_FASTPATH
+ /* Reserving the extra headroom required for ASF IPSec processing */
+ skb_reserve(skb, EXTRA_HEADROOM);
+#endif
+ /* We need the data buffer to be aligned properly. We will reserve
+ * as many bytes as needed to align the data properly
+ */
+ skb_reserve(skb, RXBUF_ALIGNMENT -
+ (((unsigned long) skb->data) & (RXBUF_ALIGNMENT - 1)));
+}
+
#endif /* __GIANFAR_H */
diff --git a/drivers/net/ethernet/freescale/gianfar_1588.c b/drivers/net/ethernet/freescale/gianfar_1588.c
new file mode 100644
index 0000000..0a9e70a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/gianfar_1588.c
@@ -0,0 +1,736 @@
+/* drivers/net/gianfar_1588.c
+ *
+ * Copyright 2008-2012 Freescale Semiconductor, Inc.
+ * Copyright 2009-2011 IXXAT Automation GmbH
+ *
+ * Author: Anup Gangwar <anup.gangwar@freescale.com>
+ * Yashpal Dutta <yashpal.dutta@freescale.com>
+ *
+ * Gianfar Ethernet Driver -- IEEE 1588 interface functionality
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+*/
+
+#include <linux/vmalloc.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/if_vlan.h>
+#include <linux/net_tstamp.h>
+#include <linux/of_platform.h>
+#include <linux/proc_fs.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/udp.h>
+#include "gianfar.h"
+
+static struct gfar_ptp_attr_t ptp_attr;
+
+static bool gfar_ptp_init_circ(struct gfar_ptp_circular *buf, int size)
+{
+ struct circ_buf *circ_buf = &buf->circ_buf;
+ circ_buf->buf = vmalloc(size * sizeof(struct gfar_ptp_data));
+
+ if (!circ_buf->buf)
+ return 1;
+
+ circ_buf->head = 0;
+ circ_buf->tail = 0;
+ buf->size = size;
+ spin_lock_init(&buf->ptp_lock);
+
+ return 0;
+}
+
+static bool gfar_ptp_is_full(struct gfar_ptp_circular *buf)
+{
+ struct circ_buf *circ_buf = &buf->circ_buf;
+ bool ret;
+
+ ret = CIRC_SPACE(circ_buf->head, circ_buf->tail,
+ buf->size) == 0;
+ return ret;
+}
+
+static bool gfar_ptp_is_empty(struct gfar_ptp_circular *buf)
+{
+ struct circ_buf *circ_buf = &buf->circ_buf;
+ bool ret;
+
+ ret = CIRC_CNT(circ_buf->head, circ_buf->tail,
+ buf->size) == 0;
+ return ret;
+}
+
+static bool gfar_ptp_insert(struct gfar_ptp_circular *buf,
+ struct gfar_ptp_data *data)
+{
+ struct gfar_ptp_data *tmp;
+ struct circ_buf *circ_buf = &buf->circ_buf;
+ unsigned int head;
+ unsigned long flags;
+
+ spin_lock_irqsave(&buf->ptp_lock, flags);
+ if (gfar_ptp_is_full(buf)) {
+ spin_unlock_irqrestore(&buf->ptp_lock, flags);
+ return 1;
+ }
+
+ head = circ_buf->head;
+ tmp = (struct gfar_ptp_data *)circ_buf->buf + head;
+ memcpy(tmp, data, sizeof(struct gfar_ptp_data));
+ circ_buf->head = (head + 1) & (buf->size - 1);
+ spin_unlock_irqrestore(&buf->ptp_lock, flags);
+
+ return 0;
+}
+
+static int gfar_ptp_is_ident_match(struct gfar_ptp_ident *dst,
+ struct gfar_ptp_ident *src)
+{
+ int ret;
+
+ if ((dst->version != src->version) ||
+ (dst->msg_type != src->msg_type))
+ return 0;
+
+ if ((dst->netw_prot == src->netw_prot)
+ || src->netw_prot == GFAR_PTP_PROT_DONTCARE) {
+ if (dst->seq_id != src->seq_id)
+ return 0;
+
+ ret = memcmp(dst->snd_port_id, src->snd_port_id,
+ GFAR_PTP_SOURCE_PORT_LENGTH);
+ if (ret)
+ return 0;
+ else
+ return 1;
+ }
+
+ return 0;
+}
+
+static bool gfar_ptp_find_and_remove(struct gfar_ptp_circular *buf,
+ struct gfar_ptp_ident *ident,
+ struct gfar_ptp_time *ts)
+{
+ struct circ_buf *circ_buf = &buf->circ_buf;
+ unsigned int size = buf->size;
+ unsigned int head, tail, idx;
+ struct gfar_ptp_data *tmp, *tmp2;
+ struct gfar_ptp_ident *tmp_ident;
+ unsigned long flags;
+
+ spin_lock_irqsave(&buf->ptp_lock, flags);
+ if (gfar_ptp_is_empty(buf)) {
+ spin_unlock_irqrestore(&buf->ptp_lock, flags);
+ return 1;
+ }
+
+ head = circ_buf->head;
+ tail = idx = circ_buf->tail;
+
+ while (idx != head) {
+ tmp = (struct gfar_ptp_data *)(circ_buf->buf) + idx;
+ tmp_ident = &tmp->ident;
+ if (gfar_ptp_is_ident_match(tmp_ident, ident))
+ break;
+
+ /* get next */
+ idx = (idx + 1) & (size - 1);
+ }
+
+ /* not found ? */
+ if (idx == head) {
+ spin_unlock_irqrestore(&buf->ptp_lock, flags);
+ return 1;
+ }
+
+ *ts = tmp->ts;
+
+ if (idx != tail) {
+ if (CIRC_CNT(idx, tail, size) > TS_ACCUMULATION_THRESHOLD) {
+ tail = circ_buf->tail =
+ (idx - TS_ACCUMULATION_THRESHOLD) & (size - 1);
+ }
+
+ while (CIRC_CNT(idx, tail, size) > 0) {
+ tmp = (struct gfar_ptp_data *)(circ_buf->buf) + idx;
+ idx = (idx - 1) & (size - 1);
+ tmp2 = (struct gfar_ptp_data *)(circ_buf->buf) + idx;
+ *tmp = *tmp2;
+ }
+ }
+
+ /* set tail pointer to postion after found */
+ circ_buf->tail = (tail + 1) & (size - 1);
+
+ spin_unlock_irqrestore(&buf->ptp_lock, flags);
+
+ return 0;
+}
+
+
+/* Parse packets if they are PTP.
+ * The PTP header can be found in an IPv4, IPv6 or in an IEEE802.3
+ * ethernet frame. The function returns the position of the PTP packet
+ * or NULL, if no PTP found.
+*/
+static void *gfar_ptp_parse_packet(struct sk_buff *skb, u16 *eth_type)
+{
+ struct iphdr *iph;
+ struct udphdr *udph;
+ struct ipv6hdr *ipv6h;
+ void *pos = skb->data + ETH_ALEN + ETH_ALEN;
+ u8 *ptp_loc = NULL;
+
+ *eth_type = be16_to_cpup(pos);
+
+ /* Check if outer vlan tag is here */
+ if (*eth_type == GFAR_VLAN_QINQ_1 ||
+ *eth_type == GFAR_VLAN_QINQ_2 ||
+ *eth_type == GFAR_VLAN_QINQ_3 ||
+ *eth_type == GFAR_VLAN_QINQ_4) {
+ pos += GFAR_VLAN_TAG_LEN;
+ *eth_type = be16_to_cpup(pos);
+ }
+
+ /* Check if inner tag is here */
+ if (*eth_type == ETH_P_8021Q) {
+ pos += GFAR_VLAN_TAG_LEN;
+ *eth_type = be16_to_cpup(pos);
+ }
+
+ /* set pos after ethertype */
+ pos += GFAR_ETHTYPE_LEN;
+
+ switch (*eth_type) {
+ case ETH_P_1588:
+ ptp_loc = pos;
+ if ((ptp_loc[0] & 0xF) <= 3) {
+ /* long enough ? */
+ if (skb->len >= ((ptp_loc - skb->data) +
+ GFAR_PTP_HEADER_SZE))
+ return ptp_loc;
+ }
+ break;
+ case ETH_P_IP:
+ iph = (struct iphdr *)pos;
+
+ if (ntohs(iph->protocol) != IPPROTO_UDP)
+ return NULL;
+
+ pos += iph->ihl * 4;
+ udph = (struct udphdr *)pos;
+
+ /* check the destination port address
+ * ( 319 (0x013F) = PTP event port )
+ */
+ if (ntohs(udph->dest) != GFAR_PTP_EVENT_PORT)
+ return NULL;
+
+ ptp_loc = pos + sizeof(struct udphdr);
+ /* long enough ? */
+ if (skb->len >= ((ptp_loc - skb->data)
+ + GFAR_PTP_HEADER_SZE))
+ return ptp_loc;
+ break;
+ case ETH_P_IPV6:
+ ipv6h = (struct ipv6hdr *)pos;
+
+ if (ntohs(ipv6h->nexthdr) != IPPROTO_UDP)
+ return NULL;
+
+ pos += sizeof(struct ipv6hdr);
+ udph = (struct udphdr *)pos;
+
+ /* check the destination port address
+ * ( 319 (0x013F) = PTP event port )
+ */
+ if (ntohs(udph->dest) != GFAR_PTP_EVENT_PORT)
+ return NULL;
+
+ ptp_loc = pos + sizeof(struct udphdr);
+ /* long enough ? */
+ if (skb->len >= ((ptp_loc - skb->data)
+ + GFAR_PTP_HEADER_SZE))
+ return ptp_loc;
+ break;
+ default:
+ break;
+ }
+
+ return NULL; /* no PTP frame */
+}
+
+/* Store the tx hardware timestamp with additional information
+ * in the gfar internal ringbuffer for timestamps.
+ */
+void gfar_ptp_store_txstamp(struct net_device *dev, struct sk_buff *skb,
+ struct gfar_ptp_time *tx_ts)
+{
+ struct gfar_ptp_data tmp_tx_time;
+ struct gfar_private *priv = netdev_priv(dev);
+ void *ptp_loc;
+ u16 eth_type;
+
+ ptp_loc = gfar_ptp_parse_packet(skb, &eth_type);
+ if (ptp_loc == NULL)
+ return;
+
+ /* store identification data */
+ switch (eth_type) {
+ case ETH_P_IP:
+ tmp_tx_time.ident.netw_prot = GFAR_PTP_PROT_IPV4;
+ break;
+ case ETH_P_IPV6:
+ tmp_tx_time.ident.netw_prot = GFAR_PTP_PROT_IPV6;
+ break;
+ case ETH_P_1588:
+ tmp_tx_time.ident.netw_prot = GFAR_PTP_PROT_802_3;
+ break;
+ default:
+ return;
+ }
+
+ tmp_tx_time.ident.version = (*(u8 *)(ptp_loc + 1)) & 0X0F;
+ tmp_tx_time.ident.msg_type = (*(u8 *)(ptp_loc)) & 0x0F;
+ tmp_tx_time.ident.seq_id = be16_to_cpup(ptp_loc +
+ GFAR_PTP_HEADER_SEQ_OFFS);
+ memcpy(tmp_tx_time.ident.snd_port_id,
+ ptp_loc + GFAR_PTP_SPID_OFFS, GFAR_PTP_SOURCE_PORT_LENGTH);
+
+ /* store tx timestamp */
+ tmp_tx_time.ts = *tx_ts;
+
+ /* insert timestamp in circular buffer */
+ gfar_ptp_insert(&(priv->tx_timestamps), &tmp_tx_time);
+}
+
+/* Store the rx hardware timestamp with additional information
+ * in the gfar internal ringbuffer for timestamps.
+ */
+void gfar_ptp_store_rxstamp(struct net_device *dev, struct sk_buff *skb,
+ struct gfar_ptp_time *rx_ts)
+{
+ struct gfar_ptp_data tmp_rx_time;
+ struct gfar_private *priv = netdev_priv(dev);
+ void *ptp_loc;
+ u16 eth_type;
+
+ ptp_loc = gfar_ptp_parse_packet(skb, &eth_type);
+ if (ptp_loc == NULL)
+ return;
+
+ /* store identification data */
+ switch (eth_type) {
+ case ETH_P_IP:
+ tmp_rx_time.ident.netw_prot = GFAR_PTP_PROT_IPV4;
+ break;
+ case ETH_P_IPV6:
+ tmp_rx_time.ident.netw_prot = GFAR_PTP_PROT_IPV6;
+ break;
+ case ETH_P_1588:
+ tmp_rx_time.ident.netw_prot = GFAR_PTP_PROT_802_3;
+ break;
+ default:
+ return;
+ }
+
+ tmp_rx_time.ident.version = (*(u8 *)(ptp_loc + 1)) & 0X0F;
+ tmp_rx_time.ident.msg_type = (*(u8 *)(ptp_loc)) & 0x0F;
+ tmp_rx_time.ident.seq_id = be16_to_cpup(ptp_loc +
+ GFAR_PTP_HEADER_SEQ_OFFS);
+ memcpy(tmp_rx_time.ident.snd_port_id,
+ ptp_loc + GFAR_PTP_SPID_OFFS,
+ GFAR_PTP_SOURCE_PORT_LENGTH);
+
+ /* store rx timestamp */
+ tmp_rx_time.ts = *rx_ts;
+
+ /* insert timestamp in circular buffer */
+ gfar_ptp_insert(&(priv->rx_timestamps), &tmp_rx_time);
+}
+
+/* nominal_frequency - This function calculates the nominal frequency.
+ * nominal frequency is the desired clock frequency.
+ * @sysclock_freq: Timer Oscillator Frequency
+ *
+ * Description:
+ * Returns the nominal frequency which is calculated on the following
+ * basis.
+ * nominal frequency should be less than the Timer Oscillator frequency.
+ * nominal frequency should be a factor of 1000.
+ *
+ * Eg If Timer Oscillator frequency is 400.
+ * then nominal frequency can be 200.
+ *
+ * If Timer Oscillator frequency is 600.
+ * then nominal frequency can be 500.
+ *
+ * If Timer Oscillator frequency is 333.
+ * then nominal frequency can be 200.
+ */
+static u32 nominal_frequency(u32 sysclock_freq)
+{
+ u32 remainder = 0;
+
+ sysclock_freq /= 1000000;
+ remainder = sysclock_freq % 100;
+ if (remainder) {
+ sysclock_freq = sysclock_freq - remainder;
+ sysclock_freq += 100;
+ }
+
+ while ((1000 % (sysclock_freq -= 100)))
+ continue;
+
+ return sysclock_freq * 1000000;
+}
+
+static int gfar_ptp_cal_attr(u32 sysclk_freq)
+{
+ ptp_attr.sysclock_freq = sysclk_freq;
+
+ ptp_attr.nominal_freq =
+ nominal_frequency(ptp_attr.sysclock_freq);
+ ptp_attr.tmr_fiper1 = ONE_GIGA;
+
+ /* TCLK_PERIOD = 10^9/Nominal_Frequency in HZ */
+ ptp_attr.tclk_period =
+ 1000000000 / ptp_attr.nominal_freq;
+
+ return 0;
+}
+
+/*set Fiper Trigger Alarm */
+static void gfar_set_fiper_alarm(struct net_device *dev,
+ struct gfar_ptp_time *alarm)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ u64 act_time;
+
+ act_time = alarm->sec * NANOSEC_PER_SEC + alarm->nsec;
+ gfar_write(&(priv->ptimer->tmr_alarm1_l), lower_32_bits(act_time));
+ gfar_write(&(priv->ptimer->tmr_alarm1_h), upper_32_bits(act_time));
+
+ gfar_write(&(priv->ptimer->tmr_fiper1), ptp_attr.tmr_fiper1
+ - ptp_attr.tclk_period);
+}
+
+/* Set the 1588 timer counter registers */
+static void gfar_set_1588cnt(struct net_device *dev,
+ struct gfar_ptp_time *gfar_time)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ u64 act_time;
+
+ act_time = gfar_time->sec * NANOSEC_PER_SEC + gfar_time->nsec;
+
+ /* We must write the tmr_cnt_l register first */
+ gfar_write(&priv->ptimer->tmr_cnt_l, lower_32_bits(act_time));
+ gfar_write(&priv->ptimer->tmr_cnt_h, upper_32_bits(act_time));
+
+ /* restart fiper two second later */
+ gfar_time->sec += 2;
+ gfar_time->nsec = 0;
+ gfar_set_fiper_alarm(dev, gfar_time);
+}
+
+void gfar_cnt_to_ptp_time(u32 high, u32 low, struct gfar_ptp_time *ptp_time)
+{
+ u64 sec;
+ u32 nsec;
+
+ sec = make64(high, low);
+ nsec = do_div(sec, NANOSEC_PER_SEC);
+ ptp_time->nsec = nsec;
+ ptp_time->sec = sec;
+}
+
+static void gfar_get_curr_cnt(struct gfar_regs_1588 __iomem *ptimer,
+ struct gfar_ptp_time *curr_time)
+{
+ u32 high1, high2, low1, low2;
+
+ /* do not accept a time at the rollover from low to high */
+ do {
+ high1 = gfar_read(&ptimer->tmr_cnt_h);
+ low1 = gfar_read(&ptimer->tmr_cnt_l);
+ high2 = gfar_read(&ptimer->tmr_cnt_h);
+ low2 = gfar_read(&ptimer->tmr_cnt_l);
+ } while (high1 != high2);
+
+ gfar_cnt_to_ptp_time(high2, low2, curr_time);
+}
+
+/* Get both the time-stamps and use the larger one */
+u64 gfar_get_tx_timestamp(struct gfar __iomem *regs)
+{
+ u32 high1, high2, low1, low2;
+ u64 ts1, ts2;
+
+ /* Read the nsec register first */
+ low1 = gfar_read(&regs->tmr_txts1_l);
+ high1 = gfar_read(&regs->tmr_txts1_h);
+ low2 = gfar_read(&regs->tmr_txts2_l);
+ high2 = gfar_read(&regs->tmr_txts2_h);
+
+ ts1 = make64(high1, low1);
+ ts2 = make64(high2, low2);
+
+ return (ts1 > ts2) ? ts1 : ts2;
+}
+
+int gfar_ioctl_1588(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct gfar_ptp_time act_time;
+ struct gfar_ptp_data ptp_ts_data;
+ struct gfar_ptp_data *ptp_dat_user;
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
+ u32 adj;
+
+ if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER))
+ return -ERANGE;
+
+ switch (cmd) {
+ case PTP_ENBL_TXTS_IOCTL:
+ priv->hwts_tx_en_ioctl = 1;
+ /* add RTPE bit - enable timestamp insertion on tx packets */
+ gfar_write(&(priv->ptimer->tmr_ctrl),
+ gfar_read(&(priv->ptimer->tmr_ctrl)) | TMR_RTPE);
+ break;
+ case PTP_DSBL_TXTS_IOCTL:
+ priv->hwts_tx_en_ioctl = 0;
+ /* remove RTPE bit - disable timestamp insertion
+ * on tx packets
+ */
+ gfar_write(&(priv->ptimer->tmr_ctrl),
+ gfar_read(&(priv->ptimer->tmr_ctrl)) & ~TMR_RTPE);
+ break;
+ case PTP_ENBL_RXTS_IOCTL:
+ priv->hwts_rx_en_ioctl = 1;
+ gfar_write(&regs->rctrl,
+ gfar_read(&regs->rctrl) | RCTRL_TS_ENABLE);
+ break;
+ case PTP_DSBL_RXTS_IOCTL:
+ priv->hwts_rx_en_ioctl = 0;
+ gfar_write(&regs->rctrl,
+ gfar_read(&regs->rctrl) & ~RCTRL_TS_ENABLE);
+ break;
+ case PTP_GET_TX_TIMESTAMP:
+ ptp_dat_user = (struct gfar_ptp_data *)ifr->ifr_data;
+ if (copy_from_user(&ptp_ts_data.ident,
+ &ptp_dat_user->ident, sizeof(ptp_ts_data.ident)))
+ return -EINVAL;
+
+ if (gfar_ptp_find_and_remove(&(priv->tx_timestamps),
+ &ptp_ts_data.ident, &ptp_ts_data.ts))
+ return -EAGAIN;
+
+ if (copy_to_user(&ptp_dat_user->ts, &ptp_ts_data.ts,
+ sizeof(ptp_ts_data.ts)))
+ return -EFAULT;
+ break;
+ case PTP_GET_RX_TIMESTAMP:
+ ptp_dat_user = (struct gfar_ptp_data *)ifr->ifr_data;
+ if (copy_from_user(&ptp_ts_data.ident,
+ &ptp_dat_user->ident, sizeof(ptp_ts_data.ident)))
+ return -EINVAL;
+
+ if (gfar_ptp_find_and_remove(&(priv->rx_timestamps),
+ &ptp_ts_data.ident, &ptp_ts_data.ts))
+ return -EAGAIN;
+
+ if (copy_to_user(&ptp_dat_user->ts,
+ &ptp_ts_data.ts, sizeof(ptp_ts_data.ts)))
+ return -EFAULT;
+ break;
+ case PTP_SET_TIME:
+ if (copy_from_user(&act_time, ifr->ifr_data,
+ sizeof(act_time)))
+ return -EINVAL;
+
+ gfar_set_1588cnt(dev, &act_time);
+ break;
+ case PTP_GET_TIME:
+ gfar_get_curr_cnt(priv->ptimer, &act_time);
+ if (copy_to_user(ifr->ifr_data, &act_time,
+ sizeof(act_time)))
+ return -EFAULT;
+ break;
+ case PTP_SET_FIPER_ALARM:
+ if (copy_from_user(&act_time, ifr->ifr_data,
+ sizeof(act_time)))
+ return -EINVAL;
+
+ gfar_set_fiper_alarm(dev, &act_time);
+ break;
+ case PTP_SET_ADJ:
+ if (copy_from_user(&adj, ifr->ifr_data, sizeof(adj)))
+ return -EINVAL;
+
+ /* assign new value directly */
+ gfar_write(&priv->ptimer->tmr_add, adj);
+ break;
+ case PTP_GET_ADJ:
+ /* return initial timer add value
+ * to calculate drift correction
+ */
+ if (copy_to_user(ifr->ifr_data, &ptp_attr.freq_comp,
+ sizeof(ptp_attr.freq_comp)))
+ return -EFAULT;
+ break;
+ case PTP_CLEANUP_TS:
+ /* reset tx-timestamping buffer */
+ priv->tx_timestamps.circ_buf.head = 0;
+ priv->tx_timestamps.circ_buf.tail = 0;
+ priv->tx_timestamps.size = DEFAULT_PTP_TX_BUF_SZ;
+ /* reset rx-timestamping buffer */
+ priv->rx_timestamps.circ_buf.head = 0;
+ priv->rx_timestamps.circ_buf.tail = 0;
+ priv->rx_timestamps.size = DEFAULT_PTP_RX_BUF_SZ;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int get_of_u32(struct device_node *node, char *str, u32 *val)
+{
+ int plen;
+ const u32 *prop = of_get_property(node, str, &plen);
+
+ if (!prop || plen != sizeof(*prop))
+ return -1;
+
+ *val = *prop;
+
+ return 0;
+}
+
+/* Resource required for accessing 1588 Timer Registers. There are few 1588
+ * modules registers which are present in eTSEC1 memory space only. The second
+ * reg entry there in denotes the 1588 regs.
+ */
+int gfar_ptp_init(struct device_node *np, struct gfar_private *priv)
+{
+ struct device_node *node;
+ const phandle *timer_handle;
+ u32 tmr_prsc, cksel, sysclk;
+ u64 freq_comp;
+
+ timer_handle = of_get_property(np, "ptimer-handle", NULL);
+ if (!timer_handle)
+ return -ENODEV;
+
+ node = of_find_node_by_phandle(*timer_handle);
+ if (!node)
+ return -ENODEV;
+
+ if (get_of_u32(node, "fsl,tmr-prsc", &tmr_prsc) ||
+ get_of_u32(node, "timer-frequency", &sysclk) ||
+ get_of_u32(node, "fsl,clock-source-select", &cksel))
+ return -ENODEV;
+
+ priv->ptimer = of_iomap(node, 0);
+ if (!priv->ptimer)
+ return -ENOMEM;
+
+ gfar_ptp_cal_attr(sysclk);
+
+ if (of_get_property(node, "fsl,ts-to-buffer", NULL))
+ priv->device_flags |= FSL_GIANFAR_DEV_HAS_TS_TO_BUFFER;
+
+ gfar_write(&(priv->ptimer->tmr_prsc), tmr_prsc);
+ gfar_write(&(priv->ptimer->tmr_fiper1), ptp_attr.tmr_fiper1
+ - ptp_attr.tclk_period);
+
+ gfar_write(&(priv->ptimer->tmr_alarm1_l), TMR_ALARM1_L);
+ gfar_write(&(priv->ptimer->tmr_alarm1_h), TMR_ALARM1_H);
+
+ /* Need to mask the TCLK bits as they are initialized with 1 */
+ gfar_write(&(priv->ptimer->tmr_ctrl),
+ (gfar_read(&(priv->ptimer->tmr_ctrl))
+ & ~TMR_CTRL_TCLK_MASK) | (ptp_attr.tclk_period << 16));
+
+ /* initialize TMR_ADD with the initial frequency compensation value:
+ * freq_compensation = ceil(2^32 / frequency ratio)
+ * frequency ratio = sysclock frequency / nominal frequency
+ */
+ freq_comp = ((u64)2 << 31) * ptp_attr.nominal_freq;
+ if (do_div(freq_comp, ptp_attr.sysclock_freq))
+ freq_comp++;
+ ptp_attr.freq_comp = lower_32_bits(freq_comp);
+ gfar_write(&(priv->ptimer->tmr_add), ptp_attr.freq_comp);
+
+ gfar_write(&(priv->ptimer->tmr_ctrl),
+ (gfar_read(&(priv->ptimer->tmr_ctrl)) & ~TMR_CTRL_CKSEL_MASK) |
+ TMR_CTRL_ENABLE | cksel | TMR_CTRL_FIPER_START);
+
+ /* initialize circular buffer for tx timestamps */
+ if (gfar_ptp_init_circ(&(priv->tx_timestamps),
+ DEFAULT_PTP_TX_BUF_SZ))
+ goto txbuf;
+
+ /* initialize circular buffer for rx timestamps */
+ if (gfar_ptp_init_circ(&(priv->rx_timestamps),
+ DEFAULT_PTP_RX_BUF_SZ))
+ goto rxbuf;
+
+ gfar_1588_start(priv);
+
+ return 0;
+
+rxbuf:
+ vfree(priv->tx_timestamps.circ_buf.buf);
+txbuf:
+ iounmap(priv->ptimer);
+
+ return -EBUSY;
+}
+
+void gfar_ptp_cleanup(struct gfar_private *priv)
+{
+ if (priv->ptimer)
+ iounmap(priv->ptimer);
+
+ if (priv->tx_timestamps.circ_buf.buf)
+ vfree(priv->tx_timestamps.circ_buf.buf);
+
+ if (priv->rx_timestamps.circ_buf.buf)
+ vfree(priv->rx_timestamps.circ_buf.buf);
+}
+
+/* 1588 Module intialization */
+void gfar_1588_start(struct gfar_private *priv)
+{
+ if (!priv->ptimer)
+ return;
+
+ priv->hwts_tx_en = 0;
+ priv->hwts_rx_en = 0;
+ priv->hwts_tx_en_ioctl = 0;
+ priv->hwts_rx_en_ioctl = 0;
+
+ priv->device_flags |= FSL_GIANFAR_DEV_HAS_TIMER;
+}
+
+/* When PTP is disabled this routing is called */
+void gfar_1588_stop(struct gfar_private *priv)
+{
+ if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER))
+ return;
+
+ priv->hwts_tx_en = 0;
+ priv->hwts_rx_en = 0;
+ priv->hwts_tx_en_ioctl = 0;
+ priv->hwts_rx_en_ioctl = 0;
+
+ priv->device_flags &= ~FSL_GIANFAR_DEV_HAS_TIMER;
+}
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index d3d7ede..f2dfa10 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -45,10 +45,6 @@
#include "gianfar.h"
-extern void gfar_start(struct net_device *dev);
-extern int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue,
- int rx_work_limit);
-
#define GFAR_MAX_COAL_USECS 0xffff
#define GFAR_MAX_COAL_FRAMES 0xff
static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
@@ -365,25 +361,11 @@ static int gfar_scoalesce(struct net_device *dev,
struct ethtool_coalesce *cvals)
{
struct gfar_private *priv = netdev_priv(dev);
- int i = 0;
+ int i, err = 0;
if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
return -EOPNOTSUPP;
- /* Set up rx coalescing */
- /* As of now, we will enable/disable coalescing for all
- * queues together in case of eTSEC2, this will be modified
- * along with the ethtool interface
- */
- if ((cvals->rx_coalesce_usecs == 0) ||
- (cvals->rx_max_coalesced_frames == 0)) {
- for (i = 0; i < priv->num_rx_queues; i++)
- priv->rx_queue[i]->rxcoalescing = 0;
- } else {
- for (i = 0; i < priv->num_rx_queues; i++)
- priv->rx_queue[i]->rxcoalescing = 1;
- }
-
if (NULL == priv->phydev)
return -ENODEV;
@@ -400,6 +382,32 @@ static int gfar_scoalesce(struct net_device *dev,
return -EINVAL;
}
+ /* Check the bounds of the values */
+ if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
+ netdev_info(dev, "Coalescing is limited to %d microseconds\n",
+ GFAR_MAX_COAL_USECS);
+ return -EINVAL;
+ }
+
+ if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
+ netdev_info(dev, "Coalescing is limited to %d frames\n",
+ GFAR_MAX_COAL_FRAMES);
+ return -EINVAL;
+ }
+
+ while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
+ cpu_relax();
+
+ /* Set up rx coalescing */
+ if ((cvals->rx_coalesce_usecs == 0) ||
+ (cvals->rx_max_coalesced_frames == 0)) {
+ for (i = 0; i < priv->num_rx_queues; i++)
+ priv->rx_queue[i]->rxcoalescing = 0;
+ } else {
+ for (i = 0; i < priv->num_rx_queues; i++)
+ priv->rx_queue[i]->rxcoalescing = 1;
+ }
+
for (i = 0; i < priv->num_rx_queues; i++) {
priv->rx_queue[i]->rxic = mk_ic_value(
cvals->rx_max_coalesced_frames,
@@ -416,28 +424,22 @@ static int gfar_scoalesce(struct net_device *dev,
priv->tx_queue[i]->txcoalescing = 1;
}
- /* Check the bounds of the values */
- if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
- netdev_info(dev, "Coalescing is limited to %d microseconds\n",
- GFAR_MAX_COAL_USECS);
- return -EINVAL;
- }
-
- if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
- netdev_info(dev, "Coalescing is limited to %d frames\n",
- GFAR_MAX_COAL_FRAMES);
- return -EINVAL;
- }
-
for (i = 0; i < priv->num_tx_queues; i++) {
priv->tx_queue[i]->txic = mk_ic_value(
cvals->tx_max_coalesced_frames,
gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs));
}
- gfar_configure_coalescing_all(priv);
+ if (dev->flags & IFF_UP) {
+ stop_gfar(dev);
+ err = startup_gfar(dev);
+ } else {
+ gfar_mac_reset(priv);
+ }
+
+ clear_bit_unlock(GFAR_RESETTING, &priv->state);
- return 0;
+ return err;
}
/* Fills in rvals with the current ring parameters. Currently,
@@ -468,15 +470,13 @@ static void gfar_gringparam(struct net_device *dev,
}
/* Change the current ring parameters, stopping the controller if
- * necessary so that we don't mess things up while we're in
- * motion. We wait for the ring to be clean before reallocating
- * the rings.
+ * necessary so that we don't mess things up while we're in motion.
*/
static int gfar_sringparam(struct net_device *dev,
struct ethtool_ringparam *rvals)
{
struct gfar_private *priv = netdev_priv(dev);
- int err = 0, i = 0;
+ int err = 0, i;
if (rvals->rx_pending > GFAR_RX_MAX_RING_SIZE)
return -EINVAL;
@@ -494,44 +494,25 @@ static int gfar_sringparam(struct net_device *dev,
return -EINVAL;
}
+ while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
+ cpu_relax();
- if (dev->flags & IFF_UP) {
- unsigned long flags;
-
- /* Halt TX and RX, and process the frames which
- * have already been received
- */
- local_irq_save(flags);
- lock_tx_qs(priv);
- lock_rx_qs(priv);
-
- gfar_halt(dev);
-
- unlock_rx_qs(priv);
- unlock_tx_qs(priv);
- local_irq_restore(flags);
-
- for (i = 0; i < priv->num_rx_queues; i++)
- gfar_clean_rx_ring(priv->rx_queue[i],
- priv->rx_queue[i]->rx_ring_size);
-
- /* Now we take down the rings to rebuild them */
+ if (dev->flags & IFF_UP)
stop_gfar(dev);
- }
- /* Change the size */
- for (i = 0; i < priv->num_rx_queues; i++) {
+ /* Change the sizes */
+ for (i = 0; i < priv->num_rx_queues; i++)
priv->rx_queue[i]->rx_ring_size = rvals->rx_pending;
+
+ for (i = 0; i < priv->num_tx_queues; i++)
priv->tx_queue[i]->tx_ring_size = rvals->tx_pending;
- priv->tx_queue[i]->num_txbdfree =
- priv->tx_queue[i]->tx_ring_size;
- }
/* Rebuild the rings with the new size */
- if (dev->flags & IFF_UP) {
+ if (dev->flags & IFF_UP)
err = startup_gfar(dev);
- netif_tx_wake_all_queues(dev);
- }
+
+ clear_bit_unlock(GFAR_RESETTING, &priv->state);
+
return err;
}
@@ -609,43 +590,29 @@ static int gfar_spauseparam(struct net_device *dev,
int gfar_set_features(struct net_device *dev, netdev_features_t features)
{
- struct gfar_private *priv = netdev_priv(dev);
- unsigned long flags;
- int err = 0, i = 0;
netdev_features_t changed = dev->features ^ features;
+ struct gfar_private *priv = netdev_priv(dev);
+ int err = 0;
- if (changed & (NETIF_F_HW_VLAN_CTAG_TX|NETIF_F_HW_VLAN_CTAG_RX))
- gfar_vlan_mode(dev, features);
-
- if (!(changed & NETIF_F_RXCSUM))
+ if (!(changed & (NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
+ NETIF_F_RXCSUM)))
return 0;
- if (dev->flags & IFF_UP) {
- /* Halt TX and RX, and process the frames which
- * have already been received
- */
- local_irq_save(flags);
- lock_tx_qs(priv);
- lock_rx_qs(priv);
+ while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
+ cpu_relax();
- gfar_halt(dev);
-
- unlock_tx_qs(priv);
- unlock_rx_qs(priv);
- local_irq_restore(flags);
-
- for (i = 0; i < priv->num_rx_queues; i++)
- gfar_clean_rx_ring(priv->rx_queue[i],
- priv->rx_queue[i]->rx_ring_size);
+ dev->features = features;
+ if (dev->flags & IFF_UP) {
/* Now we take down the rings to rebuild them */
stop_gfar(dev);
-
- dev->features = features;
-
err = startup_gfar(dev);
- netif_tx_wake_all_queues(dev);
+ } else {
+ gfar_mac_reset(priv);
}
+
+ clear_bit_unlock(GFAR_RESETTING, &priv->state);
+
return err;
}
@@ -889,11 +856,9 @@ static int gfar_set_hash_opts(struct gfar_private *priv,
static int gfar_check_filer_hardware(struct gfar_private *priv)
{
- struct gfar __iomem *regs = NULL;
+ struct gfar __iomem *regs = priv->gfargrp[0].regs;
u32 i;
- regs = priv->gfargrp[0].regs;
-
/* Check if we are in FIFO mode */
i = gfar_read(&regs->ecntrl);
i &= ECNTRL_FIFM;
@@ -927,7 +892,7 @@ static int gfar_check_filer_hardware(struct gfar_private *priv)
/* Sets the properties for arbitrary filer rule
* to the first 4 Layer 4 Bytes
*/
- regs->rbifx = 0xC0C1C2C3;
+ gfar_write(&regs->rbifx, 0xC0C1C2C3);
return 0;
}
@@ -1055,10 +1020,18 @@ static void gfar_set_basic_ip(struct ethtool_tcpip4_spec *value,
struct ethtool_tcpip4_spec *mask,
struct filer_table *tab)
{
- gfar_set_attribute(value->ip4src, mask->ip4src, RQFCR_PID_SIA, tab);
- gfar_set_attribute(value->ip4dst, mask->ip4dst, RQFCR_PID_DIA, tab);
- gfar_set_attribute(value->pdst, mask->pdst, RQFCR_PID_DPT, tab);
- gfar_set_attribute(value->psrc, mask->psrc, RQFCR_PID_SPT, tab);
+ gfar_set_attribute(be32_to_cpu(value->ip4src),
+ be32_to_cpu(mask->ip4src),
+ RQFCR_PID_SIA, tab);
+ gfar_set_attribute(be32_to_cpu(value->ip4dst),
+ be32_to_cpu(mask->ip4dst),
+ RQFCR_PID_DIA, tab);
+ gfar_set_attribute(be16_to_cpu(value->pdst),
+ be16_to_cpu(mask->pdst),
+ RQFCR_PID_DPT, tab);
+ gfar_set_attribute(be16_to_cpu(value->psrc),
+ be16_to_cpu(mask->psrc),
+ RQFCR_PID_SPT, tab);
gfar_set_attribute(value->tos, mask->tos, RQFCR_PID_TOS, tab);
}
@@ -1067,12 +1040,17 @@ static void gfar_set_user_ip(struct ethtool_usrip4_spec *value,
struct ethtool_usrip4_spec *mask,
struct filer_table *tab)
{
- gfar_set_attribute(value->ip4src, mask->ip4src, RQFCR_PID_SIA, tab);
- gfar_set_attribute(value->ip4dst, mask->ip4dst, RQFCR_PID_DIA, tab);
+ gfar_set_attribute(be32_to_cpu(value->ip4src),
+ be32_to_cpu(mask->ip4src),
+ RQFCR_PID_SIA, tab);
+ gfar_set_attribute(be32_to_cpu(value->ip4dst),
+ be32_to_cpu(mask->ip4dst),
+ RQFCR_PID_DIA, tab);
gfar_set_attribute(value->tos, mask->tos, RQFCR_PID_TOS, tab);
gfar_set_attribute(value->proto, mask->proto, RQFCR_PID_L4P, tab);
- gfar_set_attribute(value->l4_4_bytes, mask->l4_4_bytes, RQFCR_PID_ARB,
- tab);
+ gfar_set_attribute(be32_to_cpu(value->l4_4_bytes),
+ be32_to_cpu(mask->l4_4_bytes),
+ RQFCR_PID_ARB, tab);
}
@@ -1139,7 +1117,41 @@ static void gfar_set_ether(struct ethhdr *value, struct ethhdr *mask,
}
}
- gfar_set_attribute(value->h_proto, mask->h_proto, RQFCR_PID_ETY, tab);
+ gfar_set_attribute(be16_to_cpu(value->h_proto),
+ be16_to_cpu(mask->h_proto),
+ RQFCR_PID_ETY, tab);
+}
+
+static inline u32 vlan_tci_vid(struct ethtool_rx_flow_spec *rule)
+{
+ return be16_to_cpu(rule->h_ext.vlan_tci) & VLAN_VID_MASK;
+}
+
+static inline u32 vlan_tci_vidm(struct ethtool_rx_flow_spec *rule)
+{
+ return be16_to_cpu(rule->m_ext.vlan_tci) & VLAN_VID_MASK;
+}
+
+static inline u32 vlan_tci_cfi(struct ethtool_rx_flow_spec *rule)
+{
+ return be16_to_cpu(rule->h_ext.vlan_tci) & VLAN_CFI_MASK;
+}
+
+static inline u32 vlan_tci_cfim(struct ethtool_rx_flow_spec *rule)
+{
+ return be16_to_cpu(rule->m_ext.vlan_tci) & VLAN_CFI_MASK;
+}
+
+static inline u32 vlan_tci_prio(struct ethtool_rx_flow_spec *rule)
+{
+ return (be16_to_cpu(rule->h_ext.vlan_tci) & VLAN_PRIO_MASK) >>
+ VLAN_PRIO_SHIFT;
+}
+
+static inline u32 vlan_tci_priom(struct ethtool_rx_flow_spec *rule)
+{
+ return (be16_to_cpu(rule->m_ext.vlan_tci) & VLAN_PRIO_MASK) >>
+ VLAN_PRIO_SHIFT;
}
/* Convert a rule to binary filter format of gianfar */
@@ -1153,22 +1165,21 @@ static int gfar_convert_to_filer(struct ethtool_rx_flow_spec *rule,
u32 old_index = tab->index;
/* Check if vlan is wanted */
- if ((rule->flow_type & FLOW_EXT) && (rule->m_ext.vlan_tci != 0xFFFF)) {
+ if ((rule->flow_type & FLOW_EXT) &&
+ (rule->m_ext.vlan_tci != cpu_to_be16(0xFFFF))) {
if (!rule->m_ext.vlan_tci)
- rule->m_ext.vlan_tci = 0xFFFF;
+ rule->m_ext.vlan_tci = cpu_to_be16(0xFFFF);
vlan = RQFPR_VLN;
vlan_mask = RQFPR_VLN;
/* Separate the fields */
- id = rule->h_ext.vlan_tci & VLAN_VID_MASK;
- id_mask = rule->m_ext.vlan_tci & VLAN_VID_MASK;
- cfi = rule->h_ext.vlan_tci & VLAN_CFI_MASK;
- cfi_mask = rule->m_ext.vlan_tci & VLAN_CFI_MASK;
- prio = (rule->h_ext.vlan_tci & VLAN_PRIO_MASK) >>
- VLAN_PRIO_SHIFT;
- prio_mask = (rule->m_ext.vlan_tci & VLAN_PRIO_MASK) >>
- VLAN_PRIO_SHIFT;
+ id = vlan_tci_vid(rule);
+ id_mask = vlan_tci_vidm(rule);
+ cfi = vlan_tci_cfi(rule);
+ cfi_mask = vlan_tci_cfim(rule);
+ prio = vlan_tci_prio(rule);
+ prio_mask = vlan_tci_priom(rule);
if (cfi == VLAN_TAG_PRESENT && cfi_mask == VLAN_TAG_PRESENT) {
vlan |= RQFPR_CFI;
@@ -1567,9 +1578,6 @@ static int gfar_write_filer_table(struct gfar_private *priv,
if (tab->index > MAX_FILER_IDX - 1)
return -EBUSY;
- /* Avoid inconsistent filer table to be processed */
- lock_rx_qs(priv);
-
/* Fill regular entries */
for (; i < MAX_FILER_IDX - 1 && (tab->fe[i].ctrl | tab->fe[i].ctrl);
i++)
@@ -1582,8 +1590,6 @@ static int gfar_write_filer_table(struct gfar_private *priv,
*/
gfar_write_filer(priv, i, 0x20, 0x0);
- unlock_rx_qs(priv);
-
return 0;
}
@@ -1666,10 +1672,10 @@ static void gfar_invert_masks(struct ethtool_rx_flow_spec *flow)
for (i = 0; i < sizeof(flow->m_u); i++)
flow->m_u.hdata[i] ^= 0xFF;
- flow->m_ext.vlan_etype ^= 0xFFFF;
- flow->m_ext.vlan_tci ^= 0xFFFF;
- flow->m_ext.data[0] ^= ~0;
- flow->m_ext.data[1] ^= ~0;
+ flow->m_ext.vlan_etype ^= cpu_to_be16(0xFFFF);
+ flow->m_ext.vlan_tci ^= cpu_to_be16(0xFFFF);
+ flow->m_ext.data[0] ^= cpu_to_be32(~0);
+ flow->m_ext.data[1] ^= cpu_to_be32(~0);
}
static int gfar_add_cls(struct gfar_private *priv,
@@ -1788,6 +1794,9 @@ static int gfar_set_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
struct gfar_private *priv = netdev_priv(dev);
int ret = 0;
+ if (test_bit(GFAR_RESETTING, &priv->state))
+ return -EBUSY;
+
mutex_lock(&priv->rx_queue_access);
switch (cmd->cmd) {
diff --git a/drivers/net/ethernet/freescale/gianfar_ptp.c b/drivers/net/ethernet/freescale/gianfar_ptp.c
index e006a09..6ba2fd4 100644
--- a/drivers/net/ethernet/freescale/gianfar_ptp.c
+++ b/drivers/net/ethernet/freescale/gianfar_ptp.c
@@ -134,7 +134,7 @@ struct gianfar_ptp_registers {
#define REG_SIZE sizeof(struct gianfar_ptp_registers)
struct etsects {
- struct gianfar_ptp_registers *regs;
+ struct gianfar_ptp_registers __iomem *regs;
spinlock_t lock; /* protects regs */
struct ptp_clock *clock;
struct ptp_clock_info caps;
diff --git a/drivers/net/ethernet/freescale/gianfar_sysfs.c b/drivers/net/ethernet/freescale/gianfar_sysfs.c
deleted file mode 100644
index acb55af..0000000
--- a/drivers/net/ethernet/freescale/gianfar_sysfs.c
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * drivers/net/ethernet/freescale/gianfar_sysfs.c
- *
- * Gianfar Ethernet Driver
- * This driver is designed for the non-CPM ethernet controllers
- * on the 85xx and 83xx family of integrated processors
- * Based on 8260_io/fcc_enet.c
- *
- * Author: Andy Fleming
- * Maintainer: Kumar Gala (galak@kernel.crashing.org)
- * Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com>
- *
- * Copyright 2002-2009 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * Sysfs file creation and management
- */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/unistd.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/etherdevice.h>
-#include <linux/spinlock.h>
-#include <linux/mm.h>
-#include <linux/device.h>
-
-#include <asm/uaccess.h>
-#include <linux/module.h>
-
-#include "gianfar.h"
-
-static ssize_t gfar_show_bd_stash(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct gfar_private *priv = netdev_priv(to_net_dev(dev));
-
- return sprintf(buf, "%s\n", priv->bd_stash_en ? "on" : "off");
-}
-
-static ssize_t gfar_set_bd_stash(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct gfar_private *priv = netdev_priv(to_net_dev(dev));
- struct gfar __iomem *regs = priv->gfargrp[0].regs;
- int new_setting = 0;
- u32 temp;
- unsigned long flags;
-
- if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BD_STASHING))
- return count;
-
-
- /* Find out the new setting */
- if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1))
- new_setting = 1;
- else if (!strncmp("off", buf, count - 1) ||
- !strncmp("0", buf, count - 1))
- new_setting = 0;
- else
- return count;
-
-
- local_irq_save(flags);
- lock_rx_qs(priv);
-
- /* Set the new stashing value */
- priv->bd_stash_en = new_setting;
-
- temp = gfar_read(&regs->attr);
-
- if (new_setting)
- temp |= ATTR_BDSTASH;
- else
- temp &= ~(ATTR_BDSTASH);
-
- gfar_write(&regs->attr, temp);
-
- unlock_rx_qs(priv);
- local_irq_restore(flags);
-
- return count;
-}
-
-static DEVICE_ATTR(bd_stash, 0644, gfar_show_bd_stash, gfar_set_bd_stash);
-
-static ssize_t gfar_show_rx_stash_size(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct gfar_private *priv = netdev_priv(to_net_dev(dev));
-
- return sprintf(buf, "%d\n", priv->rx_stash_size);
-}
-
-static ssize_t gfar_set_rx_stash_size(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct gfar_private *priv = netdev_priv(to_net_dev(dev));
- struct gfar __iomem *regs = priv->gfargrp[0].regs;
- unsigned int length = simple_strtoul(buf, NULL, 0);
- u32 temp;
- unsigned long flags;
-
- if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING))
- return count;
-
- local_irq_save(flags);
- lock_rx_qs(priv);
-
- if (length > priv->rx_buffer_size)
- goto out;
-
- if (length == priv->rx_stash_size)
- goto out;
-
- priv->rx_stash_size = length;
-
- temp = gfar_read(&regs->attreli);
- temp &= ~ATTRELI_EL_MASK;
- temp |= ATTRELI_EL(length);
- gfar_write(&regs->attreli, temp);
-
- /* Turn stashing on/off as appropriate */
- temp = gfar_read(&regs->attr);
-
- if (length)
- temp |= ATTR_BUFSTASH;
- else
- temp &= ~(ATTR_BUFSTASH);
-
- gfar_write(&regs->attr, temp);
-
-out:
- unlock_rx_qs(priv);
- local_irq_restore(flags);
-
- return count;
-}
-
-static DEVICE_ATTR(rx_stash_size, 0644, gfar_show_rx_stash_size,
- gfar_set_rx_stash_size);
-
-/* Stashing will only be enabled when rx_stash_size != 0 */
-static ssize_t gfar_show_rx_stash_index(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct gfar_private *priv = netdev_priv(to_net_dev(dev));
-
- return sprintf(buf, "%d\n", priv->rx_stash_index);
-}
-
-static ssize_t gfar_set_rx_stash_index(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct gfar_private *priv = netdev_priv(to_net_dev(dev));
- struct gfar __iomem *regs = priv->gfargrp[0].regs;
- unsigned short index = simple_strtoul(buf, NULL, 0);
- u32 temp;
- unsigned long flags;
-
- if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_BUF_STASHING))
- return count;
-
- local_irq_save(flags);
- lock_rx_qs(priv);
-
- if (index > priv->rx_stash_size)
- goto out;
-
- if (index == priv->rx_stash_index)
- goto out;
-
- priv->rx_stash_index = index;
-
- temp = gfar_read(&regs->attreli);
- temp &= ~ATTRELI_EI_MASK;
- temp |= ATTRELI_EI(index);
- gfar_write(&regs->attreli, temp);
-
-out:
- unlock_rx_qs(priv);
- local_irq_restore(flags);
-
- return count;
-}
-
-static DEVICE_ATTR(rx_stash_index, 0644, gfar_show_rx_stash_index,
- gfar_set_rx_stash_index);
-
-static ssize_t gfar_show_fifo_threshold(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct gfar_private *priv = netdev_priv(to_net_dev(dev));
-
- return sprintf(buf, "%d\n", priv->fifo_threshold);
-}
-
-static ssize_t gfar_set_fifo_threshold(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct gfar_private *priv = netdev_priv(to_net_dev(dev));
- struct gfar __iomem *regs = priv->gfargrp[0].regs;
- unsigned int length = simple_strtoul(buf, NULL, 0);
- u32 temp;
- unsigned long flags;
-
- if (length > GFAR_MAX_FIFO_THRESHOLD)
- return count;
-
- local_irq_save(flags);
- lock_tx_qs(priv);
-
- priv->fifo_threshold = length;
-
- temp = gfar_read(&regs->fifo_tx_thr);
- temp &= ~FIFO_TX_THR_MASK;
- temp |= length;
- gfar_write(&regs->fifo_tx_thr, temp);
-
- unlock_tx_qs(priv);
- local_irq_restore(flags);
-
- return count;
-}
-
-static DEVICE_ATTR(fifo_threshold, 0644, gfar_show_fifo_threshold,
- gfar_set_fifo_threshold);
-
-static ssize_t gfar_show_fifo_starve(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct gfar_private *priv = netdev_priv(to_net_dev(dev));
-
- return sprintf(buf, "%d\n", priv->fifo_starve);
-}
-
-static ssize_t gfar_set_fifo_starve(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct gfar_private *priv = netdev_priv(to_net_dev(dev));
- struct gfar __iomem *regs = priv->gfargrp[0].regs;
- unsigned int num = simple_strtoul(buf, NULL, 0);
- u32 temp;
- unsigned long flags;
-
- if (num > GFAR_MAX_FIFO_STARVE)
- return count;
-
- local_irq_save(flags);
- lock_tx_qs(priv);
-
- priv->fifo_starve = num;
-
- temp = gfar_read(&regs->fifo_tx_starve);
- temp &= ~FIFO_TX_STARVE_MASK;
- temp |= num;
- gfar_write(&regs->fifo_tx_starve, temp);
-
- unlock_tx_qs(priv);
- local_irq_restore(flags);
-
- return count;
-}
-
-static DEVICE_ATTR(fifo_starve, 0644, gfar_show_fifo_starve,
- gfar_set_fifo_starve);
-
-static ssize_t gfar_show_fifo_starve_off(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct gfar_private *priv = netdev_priv(to_net_dev(dev));
-
- return sprintf(buf, "%d\n", priv->fifo_starve_off);
-}
-
-static ssize_t gfar_set_fifo_starve_off(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct gfar_private *priv = netdev_priv(to_net_dev(dev));
- struct gfar __iomem *regs = priv->gfargrp[0].regs;
- unsigned int num = simple_strtoul(buf, NULL, 0);
- u32 temp;
- unsigned long flags;
-
- if (num > GFAR_MAX_FIFO_STARVE_OFF)
- return count;
-
- local_irq_save(flags);
- lock_tx_qs(priv);
-
- priv->fifo_starve_off = num;
-
- temp = gfar_read(&regs->fifo_tx_starve_shutoff);
- temp &= ~FIFO_TX_STARVE_OFF_MASK;
- temp |= num;
- gfar_write(&regs->fifo_tx_starve_shutoff, temp);
-
- unlock_tx_qs(priv);
- local_irq_restore(flags);
-
- return count;
-}
-
-static DEVICE_ATTR(fifo_starve_off, 0644, gfar_show_fifo_starve_off,
- gfar_set_fifo_starve_off);
-
-void gfar_init_sysfs(struct net_device *dev)
-{
- struct gfar_private *priv = netdev_priv(dev);
- int rc;
-
- /* Initialize the default values */
- priv->fifo_threshold = DEFAULT_FIFO_TX_THR;
- priv->fifo_starve = DEFAULT_FIFO_TX_STARVE;
- priv->fifo_starve_off = DEFAULT_FIFO_TX_STARVE_OFF;
-
- /* Create our sysfs files */
- rc = device_create_file(&dev->dev, &dev_attr_bd_stash);
- rc |= device_create_file(&dev->dev, &dev_attr_rx_stash_size);
- rc |= device_create_file(&dev->dev, &dev_attr_rx_stash_index);
- rc |= device_create_file(&dev->dev, &dev_attr_fifo_threshold);
- rc |= device_create_file(&dev->dev, &dev_attr_fifo_starve);
- rc |= device_create_file(&dev->dev, &dev_attr_fifo_starve_off);
- if (rc)
- dev_err(&dev->dev, "Error creating gianfar sysfs files\n");
-}
diff --git a/drivers/net/ethernet/freescale/xgmac_mdio.c b/drivers/net/ethernet/freescale/xgmac_mdio.c
index c1b6e7e..fba4f92b 100644
--- a/drivers/net/ethernet/freescale/xgmac_mdio.c
+++ b/drivers/net/ethernet/freescale/xgmac_mdio.c
@@ -31,6 +31,10 @@ struct tgec_mdio_controller {
__be32 mdio_addr; /* MDIO address */
} __packed;
+/* Taken from memac_mdio.c */
+#define MDIO_STAT_ENC (1 << 6)
+#define MDIO_STAT_HOLD_15_CLK (7 << 2)
+
#define MDIO_STAT_CLKDIV(x) (((x>>1) & 0xff) << 8)
#define MDIO_STAT_BSY (1 << 0)
#define MDIO_STAT_RD_ER (1 << 1)
@@ -90,26 +94,39 @@ static int xgmac_wait_until_done(struct device *dev,
static int xgmac_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 value)
{
struct tgec_mdio_controller __iomem *regs = bus->priv;
- uint16_t dev_addr = regnum >> 16;
+ uint16_t dev_addr;
+ u32 mdio_ctl, mdio_stat;
int ret;
- /* Setup the MII Mgmt clock speed */
- out_be32(&regs->mdio_stat, MDIO_STAT_CLKDIV(100));
+ mdio_stat = in_be32(&regs->mdio_stat);
+ if (regnum & MII_ADDR_C45) {
+ /* Clause 45 (ie 10G) */
+ dev_addr = (regnum >> 16) & 0x1f;
+ mdio_stat |= MDIO_STAT_ENC | MDIO_STAT_HOLD_15_CLK;
+ } else {
+ /* Clause 22 (ie 1G) */
+ dev_addr = regnum & 0x1f;
+ mdio_stat &= ~MDIO_STAT_ENC;
+ }
+
+ out_be32(&regs->mdio_stat, mdio_stat);
ret = xgmac_wait_until_free(&bus->dev, regs);
if (ret)
return ret;
/* Set the port and dev addr */
- out_be32(&regs->mdio_ctl,
- MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr));
+ mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
+ out_be32(&regs->mdio_ctl, mdio_ctl);
/* Set the register address */
- out_be32(&regs->mdio_addr, regnum & 0xffff);
+ if (regnum & MII_ADDR_C45) {
+ out_be32(&regs->mdio_addr, regnum & 0xffff);
- ret = xgmac_wait_until_free(&bus->dev, regs);
- if (ret)
- return ret;
+ ret = xgmac_wait_until_free(&bus->dev, regs);
+ if (ret)
+ return ret;
+ }
/* Write the value to the register */
out_be32(&regs->mdio_data, MDIO_DATA(value));
@@ -129,13 +146,22 @@ static int xgmac_mdio_write(struct mii_bus *bus, int phy_id, int regnum, u16 val
static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
{
struct tgec_mdio_controller __iomem *regs = bus->priv;
- uint16_t dev_addr = regnum >> 16;
+ uint16_t dev_addr;
+ uint32_t mdio_stat;
uint32_t mdio_ctl;
uint16_t value;
int ret;
- /* Setup the MII Mgmt clock speed */
- out_be32(&regs->mdio_stat, MDIO_STAT_CLKDIV(100));
+ mdio_stat = in_be32(&regs->mdio_stat);
+ if (regnum & MII_ADDR_C45) {
+ dev_addr = (regnum >> 16) & 0x1f;
+ mdio_stat |= MDIO_STAT_ENC | MDIO_STAT_HOLD_15_CLK;
+ } else {
+ dev_addr = regnum & 0x1f;
+ mdio_stat = ~MDIO_STAT_ENC;
+ }
+
+ out_be32(&regs->mdio_stat, mdio_stat);
ret = xgmac_wait_until_free(&bus->dev, regs);
if (ret)
@@ -146,11 +172,13 @@ static int xgmac_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
out_be32(&regs->mdio_ctl, mdio_ctl);
/* Set the register address */
- out_be32(&regs->mdio_addr, regnum & 0xffff);
+ if (regnum & MII_ADDR_C45) {
+ out_be32(&regs->mdio_addr, regnum & 0xffff);
- ret = xgmac_wait_until_free(&bus->dev, regs);
- if (ret)
- return ret;
+ ret = xgmac_wait_until_free(&bus->dev, regs);
+ if (ret)
+ return ret;
+ }
/* Initiate the read */
out_be32(&regs->mdio_ctl, mdio_ctl | MDIO_CTL_READ);
@@ -180,7 +208,7 @@ static int xgmac_mdio_reset(struct mii_bus *bus)
mutex_lock(&bus->mdio_lock);
/* Setup the MII Mgmt clock speed */
- out_be32(&regs->mdio_stat, MDIO_STAT_CLKDIV(100));
+ clrbits32(&regs->mdio_stat, MDIO_STAT_ENC);
ret = xgmac_wait_until_free(&bus->dev, regs);
@@ -255,6 +283,9 @@ static struct of_device_id xgmac_mdio_match[] = {
{
.compatible = "fsl,fman-xmdio",
},
+ {
+ .compatible = "fsl,fman-memac-mdio",
+ },
{},
};
MODULE_DEVICE_TABLE(of, xgmac_mdio_match);
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 342561a..559ca1c 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -24,6 +24,11 @@ config AMD_PHY
---help---
Currently supports the am79c874
+config ATHEROS_PHY
+ tristate "Drivers for Atheros PHYs"
+ ---help---
+ Currently supports the AR8035 PHY
+
config MARVELL_PHY
tristate "Drivers for Marvell PHYs"
---help---
@@ -91,6 +96,11 @@ config NATIONAL_PHY
---help---
Currently supports the DP83865 PHY.
+config DP8384x_PHY
+ tristate "Drivers for National Semiconductor dp83848 dp83849 PHYs"
+ ---help---
+ Currently supports the DP83848/DP83849 PHY.
+
config STE10XP
tristate "Driver for STMicroelectronics STe10Xp PHYs"
---help---
@@ -185,6 +195,11 @@ config MDIO_BUS_MUX_MMIOREG
the FPGA's registers.
Currently, only 8-bit registers are supported.
+config FSL_10GBASE_KR
+ tristate "Support for 10GBASE-KR on Freescale XFI interface"
+ depends on OF_MDIO
+ help
+ This module provides a driver for Freescale XFI's 10GBASE-KR.
endif # PHYLIB
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 23a2ab2..6342943 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -3,6 +3,7 @@
libphy-objs := phy.o phy_device.o mdio_bus.o
obj-$(CONFIG_PHYLIB) += libphy.o
+obj-$(CONFIG_ATHEROS_PHY) += atheros.o
obj-$(CONFIG_MARVELL_PHY) += marvell.o
obj-$(CONFIG_DAVICOM_PHY) += davicom.o
obj-$(CONFIG_CICADA_PHY) += cicada.o
@@ -20,6 +21,7 @@ obj-$(CONFIG_FIXED_PHY) += fixed.o
obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o
obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o
obj-$(CONFIG_NATIONAL_PHY) += national.o
+obj-$(CONFIG_DP8384x_PHY) += dp8384x.o
obj-$(CONFIG_DP83640_PHY) += dp83640.o
obj-$(CONFIG_STE10XP) += ste10Xp.o
obj-$(CONFIG_MICREL_PHY) += micrel.o
@@ -30,4 +32,5 @@ obj-$(CONFIG_AMD_PHY) += amd.o
obj-$(CONFIG_MDIO_BUS_MUX) += mdio-mux.o
obj-$(CONFIG_MDIO_BUS_MUX_GPIO) += mdio-mux-gpio.o
obj-$(CONFIG_MDIO_BUS_MUX_MMIOREG) += mdio-mux-mmioreg.o
+obj-$(CONFIG_FSL_10GBASE_KR) += fsl_10gkr.o
obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index ac22283..f3778ad 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -27,6 +27,9 @@
#define AT803X_MMD_ACCESS_CONTROL 0x0D
#define AT803X_MMD_ACCESS_CONTROL_DATA 0x0E
#define AT803X_FUNC_DATA 0x4003
+#define AT803X_INER 0x0012
+#define AT803X_INER_INIT 0xec00
+#define AT803X_INSR 0x0013
#define AT803X_DEBUG_ADDR 0x1D
#define AT803X_DEBUG_DATA 0x1E
#define AT803X_DEBUG_SYSTEM_MODE_CTRL 0x05
@@ -152,6 +155,31 @@ static int at803x_config_init(struct phy_device *phydev)
return 0;
}
+static int at803x_ack_interrupt(struct phy_device *phydev)
+{
+ int err;
+
+ err = phy_read(phydev, AT803X_INSR);
+
+ return (err < 0) ? err : 0;
+}
+
+static int at803x_config_intr(struct phy_device *phydev)
+{
+ int err;
+ int value;
+
+ value = phy_read(phydev, AT803X_INER);
+
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ err = phy_write(phydev, AT803X_INER,
+ (value | AT803X_INER_INIT));
+ else
+ err = phy_write(phydev, AT803X_INER, value);
+
+ return err;
+}
+
static struct phy_driver at803x_driver[] = {
{
/* ATHEROS 8035 */
@@ -169,6 +197,21 @@ static struct phy_driver at803x_driver[] = {
.owner = THIS_MODULE,
},
}, {
+ /* ATHEROS 8033 */
+ .phy_id = 0x004dd074,
+ .name = "Atheros 8033 ethernet",
+ .phy_id_mask = 0xffffffef,
+ .config_init = at803x_config_init,
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_aneg = &genphy_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &at803x_ack_interrupt,
+ .config_intr = &at803x_config_intr,
+ .driver = {
+ .owner = THIS_MODULE,
+ },
+}, {
/* ATHEROS 8030 */
.phy_id = 0x004dd076,
.name = "Atheros 8030 ethernet",
diff --git a/drivers/net/phy/atheros.c b/drivers/net/phy/atheros.c
new file mode 100644
index 0000000..934b51e
--- /dev/null
+++ b/drivers/net/phy/atheros.c
@@ -0,0 +1,97 @@
+/*
+ * drivers/net/phy/atheros.c
+ *
+ * Driver for Atheros PHYs
+ *
+ * Author: Michael Johnston <michael.johnston@freescale.com>
+ * Chunhe Lan <Chunhe.Lan@freescale.com>
+ *
+ * Copyright (c) 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+#include <linux/phy.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#define AR8035_PHYSR 0x0011
+#define AR8035_PHYSR_DUPLEX 0x2000
+#define AR8035_PHYSR_SPEED 0xc000
+#define AR8035_INER 0x0012
+#define AR8035_INER_INIT 0xec00
+#define AR8035_INSR 0x0013
+
+#define PHY_ID_AR8035 0x004dd072
+
+MODULE_DESCRIPTION("Atheros PHY driver");
+MODULE_AUTHOR("Michael Johnston");
+MODULE_LICENSE("GPL");
+
+static int ar8035_ack_interrupt(struct phy_device *phydev)
+{
+ int err;
+
+ err = phy_read(phydev, AR8035_INSR);
+
+ return (err < 0) ? err : 0;
+}
+
+static int ar8035_config_intr(struct phy_device *phydev)
+{
+ int err;
+
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ err = phy_write(phydev, AR8035_INER, AR8035_INER_INIT);
+ else
+ err = phy_write(phydev, AR8035_INER, 0);
+
+ return err;
+}
+
+/* AR8035 */
+static struct phy_driver ar8035_driver = {
+ .phy_id = PHY_ID_AR8035,
+ .name = "AR8035 Gigabit Ethernet",
+ .phy_id_mask = 0x007fffff,
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_aneg = &genphy_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &ar8035_ack_interrupt,
+ .config_intr = &ar8035_config_intr,
+ .driver = {
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init atheros_init(void)
+{
+ int ret;
+
+ ret = phy_driver_register(&ar8035_driver);
+ if (ret < 0)
+ pr_warn("AR8035: phy_driver_register is error\n");
+
+ return ret;
+}
+
+static void __exit atheros_exit(void)
+{
+ phy_driver_unregister(&ar8035_driver);
+}
+
+module_init(atheros_init);
+module_exit(atheros_exit);
+
+static struct mdio_device_id __maybe_unused atheros_tbl[] = {
+ { PHY_ID_AR8035, 0x007fffff },
+ { }
+};
+
+MODULE_DEVICE_TABLE(mdio, atheros_tbl);
diff --git a/drivers/net/phy/dp8384x.c b/drivers/net/phy/dp8384x.c
new file mode 100644
index 0000000..5fec1e5a
--- /dev/null
+++ b/drivers/net/phy/dp8384x.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2009-2012 Freescale Semiconductor, Inc.
+ *
+ * Driver for National Semiconductor PHYs 8384x
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+#include <linux/netdevice.h>
+
+/* DP8384x phy identifier values */
+#define DP83848_PHY_ID 0x20005c90
+#define DP83849_PHY_ID 0x20005ca0
+/* PHY Status Register */
+#define MII_DP8384X_PHYSTST 16
+
+static int ns8384x_config_init(struct phy_device *phydev)
+{
+ int ret = phy_read(phydev, MII_DP8384X_PHYSTST);
+ if (ret < 0) {
+ printk(KERN_INFO "%s MII_DP83640_ISR %x\n",
+ __func__, ret);
+ }
+
+ return 0;
+}
+
+static struct phy_driver dp83848_driver = {
+ .phy_id = DP83848_PHY_ID,
+ .phy_id_mask = 0xfffffff0,
+ .name = "NatSemi DP83848",
+ .features = PHY_BASIC_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = ns8384x_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .driver = {.owner = THIS_MODULE,}
+};
+
+static struct phy_driver dp83849_driver = {
+ .phy_id = DP83849_PHY_ID,
+ .phy_id_mask = 0xfffffff0,
+ .name = "NatSemi DP83849",
+ .features = PHY_BASIC_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = ns8384x_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .driver = {.owner = THIS_MODULE,}
+};
+
+static int __init ns8384x_init(void)
+{
+ int ret;
+
+ ret = phy_driver_register(&dp83848_driver);
+ if (ret)
+ goto err1;
+
+ ret = phy_driver_register(&dp83849_driver);
+ if (ret)
+ goto err2;
+
+ return 0;
+err2:
+ printk(KERN_INFO "register dp83849 PHY driver fail\n");
+ phy_driver_unregister(&dp83848_driver);
+err1:
+ printk(KERN_INFO "register dp83848 PHY driver fail\n");
+ return ret;
+}
+
+static void __exit ns8384x_exit(void)
+{
+ phy_driver_unregister(&dp83848_driver);
+ phy_driver_unregister(&dp83849_driver);
+}
+
+MODULE_DESCRIPTION("NatSemi PHY driver");
+MODULE_AUTHOR("Chenghu Wu <b16972@freescale.com>");
+MODULE_LICENSE("GPL v2");
+
+module_init(ns8384x_init);
+module_exit(ns8384x_exit);
diff --git a/drivers/net/phy/fsl_10gkr.c b/drivers/net/phy/fsl_10gkr.c
new file mode 100644
index 0000000..7cfb4a4
--- /dev/null
+++ b/drivers/net/phy/fsl_10gkr.c
@@ -0,0 +1,1263 @@
+/* Freescale XFI 10GBASE-KR driver.
+ * Author: Shaohui Xie <Shaohui.Xie@freescale.com>
+ *
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+#include <linux/of.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/workqueue.h>
+
+#define FSL_XFI_PCS_PHY_ID 0x7C000012
+#define FSL_XFI_PCS_PHY_ID2 0x0083e400
+
+/* Freescale XFI PCS MMD */
+#define FSL_XFI_PMD 0x1
+#define FSL_XFI_PCS 0x3
+#define FSL_XFI_AN 0x7
+#define FSL_XFI_VS1 0x1e
+
+/* Freescale XFI PMD registers */
+#define FSL_XFI_PMD_CTRL 0x0
+#define FSL_XFI_KR_PMD_CTRL 0x0096
+#define FSL_XFI_KR_PMD_STATUS 0x0097
+#define FSL_XFI_KR_LP_CU 0x0098
+#define FSL_XFI_KR_LP_STATUS 0x0099
+#define FSL_XFI_KR_LD_CU 0x009a
+#define FSL_XFI_KR_LD_STATUS 0x009b
+
+/* PMD define */
+#define PMD_RESET 0x1
+#define PMD_STATUS_SUP_STAT 0x4
+#define PMD_STATUS_FRAME_LOCK 0x2
+#define TRAIN_EN 0x3
+#define TRAIN_DISABLE 0x1
+#define RX_STAT 0x1
+
+/* Freescale XFI PCS registers */
+#define FSL_XFI_PCS_CTRL 0x0
+#define FSL_XFI_PCS_STATUS 0x1
+
+/* Freescale XFI Auto-Negotiation Registers */
+#define FSL_XFI_AN_CTRL 0x0000
+#define FSL_XFI_LNK_STATUS 0x0001
+#define FSL_XFI_AN_AD_1 0x0011
+#define FSL_XFI_BP_STATUS 0x0030
+
+#define XFI_AN_AD1 0x85
+#define XF_AN_RESTART 0x1200
+#define XFI_AN_LNK_STAT_UP 0x4
+
+/* Freescale XFI Vendor-Specific 1 Registers */
+#define FSL_XFI_PCS_INTR_EVENT 0x0002
+#define FSL_XFI_PCS_INTR_MASK 0x0003
+#define FSL_XFI_AN_INTR_EVENT 0x0004
+#define FSL_XFI_AN_INTR_MASK 0x0005
+#define FSL_XFI_LT_INTR_EVENT 0x0006
+#define FSL_XFI_LT_INTR_MASK 0x0007
+
+/* C(-1) */
+#define BIN_M1 0
+/* C(1) */
+#define BIN_LONG 1
+#define BIN_M1_SEL 6
+#define BIN_Long_SEL 7
+#define CDR_SEL_MASK 0x00070000
+#define BIN_SNAPSHOT_NUM 5
+#define BIN_M1_THRESHOLD 3
+#define BIN_LONG_THRESHOLD 2
+
+#define PRE_COE_MASK 0x03c00000
+#define POST_COE_MASK 0x001f0000
+#define ZERO_COE_MASK 0x00003f00
+#define PRE_COE_SHIFT 22
+#define POST_COE_SHIFT 16
+#define ZERO_COE_SHIFT 8
+
+#define PRE_COE_MAX 0x0
+#define PRE_COE_MIN 0x8
+#define POST_COE_MAX 0x0
+#define POST_COE_MIN 0x10
+#define ZERO_COE_MAX 0x30
+#define ZERO_COE_MIN 0x0
+
+#define TECR0_INIT 0x24200000
+#define RATIO_PREQ 0x2
+#define RATIO_PST1Q 0xd
+#define RATIO_EQ 0x20
+
+#define GCR1_SNP_START_MASK 0x00000040
+#define RECR1_SNP_DONE_MASK 0x00000004
+#define TCSR1_SNP_DATA_MASK 0x0000ffc0
+#define TCSR1_SNP_DATA_SHIFT 6
+#define TCSR1_EQ_SNPBIN_SIGN_MASK 0x100
+
+#define XGKR_TIMEOUT 1050
+#define AN_ABILITY_MASK 0x9
+#define AN_10GKR_MASK 0x8
+#define LT_10GKR_MASK 0x4
+#define TRAIN_FAIL 0x8
+
+#define INCREMENT 1
+#define DECREMENT 2
+#define TIMEOUT_LONG 3
+#define TIMEOUT_M1 3
+
+#define RX_READY_MASK 0x8000
+#define PRESET_MASK 0x2000
+#define INIT_MASK 0x1000
+#define COP1_MASK 0x30
+#define COP1_SHIFT 4
+#define COZ_MASK 0xc
+#define COZ_SHIFT 2
+#define COM1_MASK 0x3
+#define COM1_SHIFT 0
+#define REQUEST_MASK 0x3f
+#define LD_ALL_MASK (PRESET_MASK | INIT_MASK | \
+ COP1_MASK | COZ_MASK | COM1_MASK)
+
+#define FSL_SERDES_INSTANCE1_BASE 0xffe0ea000
+#define FSL_SERDES_INSTANCE2_BASE 0xffe0eb000
+#define FSL_LANE_A_BASE 0x800
+#define FSL_LANE_B_BASE 0x840
+#define FSL_LANE_C_BASE 0x880
+#define FSL_LANE_D_BASE 0x8C0
+#define FSL_LANE_E_BASE 0x900
+#define FSL_LANE_F_BASE 0x940
+#define FSL_LANE_G_BASE 0x980
+#define FSL_LANE_H_BASE 0x9C0
+#define GCR0_RESET_MASK 0x600000
+
+enum fsl_xgkr_driver {
+ FSL_XGKR_REV1,
+ FSL_XGKR_REV2,
+ FSL_XGKR_INV
+};
+
+static struct phy_driver fsl_xgkr_driver[FSL_XGKR_INV];
+
+enum coe_filed {
+ COE_COP1,
+ COE_COZ,
+ COE_COM
+};
+
+enum coe_update {
+ COE_NOTUPDATED,
+ COE_UPDATED,
+ COE_MIN,
+ COE_MAX,
+ COE_INV
+};
+
+enum serdes_inst {
+ SERDES_1,
+ SERDES_2,
+ SERDES_MAX
+};
+
+enum lane_inst {
+ LANE_A,
+ LANE_B,
+ LANE_C,
+ LANE_D,
+ LANE_E,
+ LANE_F,
+ LANE_G,
+ LANE_H,
+ LANE_MAX
+};
+
+struct serdes_map {
+ const char *serdes_name;
+ unsigned long serdes_base;
+};
+
+struct lane_map {
+ const char *lane_name;
+ unsigned long lane_base;
+};
+
+const struct serdes_map s_map[SERDES_MAX] = {
+ {"serdes-1", FSL_SERDES_INSTANCE1_BASE},
+ {"serdes-2", FSL_SERDES_INSTANCE2_BASE}
+};
+
+const struct lane_map l_map[LANE_MAX] = {
+ {"lane-a", FSL_LANE_A_BASE},
+ {"lane-b", FSL_LANE_B_BASE},
+ {"lane-c", FSL_LANE_C_BASE},
+ {"lane-d", FSL_LANE_D_BASE},
+ {"lane-e", FSL_LANE_E_BASE},
+ {"lane-f", FSL_LANE_F_BASE},
+ {"lane-g", FSL_LANE_G_BASE},
+ {"lane-h", FSL_LANE_H_BASE}
+};
+
+struct per_lane_ctrl_status {
+ __be32 gcr0; /* 0x.000 - General Control Register 0 */
+ __be32 gcr1; /* 0x.004 - General Control Register 1 */
+ __be32 gcr2; /* 0x.008 - General Control Register 2 */
+ __be32 resv1; /* 0x.00C - Reserved */
+ __be32 recr0; /* 0x.010 - Receive Equalization Control Register 0 */
+ __be32 recr1; /* 0x.014 - Receive Equalization Control Register 1 */
+ __be32 tecr0; /* 0x.018 - Transmit Equalization Control Register 0 */
+ __be32 resv2; /* 0x.01C - Reserved */
+ __be32 tlcr0; /* 0x.020 - TTL Control Register 0 */
+ __be32 tlcr1; /* 0x.024 - TTL Control Register 1 */
+ __be32 tlcr2; /* 0x.028 - TTL Control Register 2 */
+ __be32 tlcr3; /* 0x.02C - TTL Control Register 3 */
+ __be32 tcsr0; /* 0x.030 - Test Control/Status Register 0 */
+ __be32 tcsr1; /* 0x.034 - Test Control/Status Register 1 */
+ __be32 tcsr2; /* 0x.038 - Test Control/Status Register 2 */
+ __be32 tcsr3; /* 0x.03C - Test Control/Status Register 3 */
+};
+
+struct training_state_machine {
+ bool bin_m1_late_early;
+ bool bin_long_late_early;
+ bool bin_m1_stop;
+ bool bin_long_stop;
+ bool tx_complete;
+ bool an_ok;
+ bool link_up;
+ bool running;
+ bool sent_init;
+ int m1_min_max_cnt;
+ int long_min_max_cnt;
+};
+
+struct fsl_xgkr_inst {
+ void *reg_base;
+ struct mii_bus *bus;
+ struct phy_device *phydev;
+ struct training_state_machine t_s_m;
+ u32 ld_update;
+ u32 ld_status;
+ u32 ratio_preq;
+ u32 ratio_pst1q;
+ u32 adpt_eq;
+};
+
+struct fsl_xgkr_wk {
+ struct work_struct xgkr_wk;
+ struct list_head xgkr_list;
+ struct fsl_xgkr_inst *xgkr_inst;
+};
+
+LIST_HEAD(fsl_xgkr_list);
+
+static struct timer_list xgkr_timer;
+static int fire_timer;
+static struct workqueue_struct *xgkr_wq;
+
+static void init_state_machine(struct training_state_machine *s_m)
+{
+ s_m->bin_m1_late_early = true;
+ s_m->bin_long_late_early = false;
+ s_m->bin_m1_stop = false;
+ s_m->bin_long_stop = false;
+ s_m->tx_complete = false;
+ s_m->an_ok = false;
+ s_m->link_up = false;
+ s_m->running = false;
+ s_m->sent_init = false;
+ s_m->m1_min_max_cnt = 0;
+ s_m->long_min_max_cnt = 0;
+}
+
+void tune_tecr0(struct fsl_xgkr_inst *inst)
+{
+ struct per_lane_ctrl_status *reg_base;
+ u32 val;
+
+ reg_base = (struct per_lane_ctrl_status *)inst->reg_base;
+
+ val = TECR0_INIT |
+ inst->adpt_eq << ZERO_COE_SHIFT |
+ inst->ratio_preq << PRE_COE_SHIFT |
+ inst->ratio_pst1q << POST_COE_SHIFT;
+
+ /* reset the lane */
+ iowrite32be(ioread32be(&reg_base->gcr0) & ~GCR0_RESET_MASK,
+ &reg_base->gcr0);
+ udelay(1);
+ iowrite32be(val, &reg_base->tecr0);
+ udelay(1);
+ /* unreset the lane */
+ iowrite32be(ioread32be(&reg_base->gcr0) | GCR0_RESET_MASK,
+ &reg_base->gcr0);
+ udelay(1);
+}
+
+static void start_lt(struct phy_device *phydev)
+{
+ phy_write_mmd(phydev, FSL_XFI_PMD, FSL_XFI_KR_PMD_CTRL, TRAIN_EN);
+}
+
+static void stop_lt(struct phy_device *phydev)
+{
+ phy_write_mmd(phydev, FSL_XFI_PMD, FSL_XFI_KR_PMD_CTRL, TRAIN_DISABLE);
+}
+
+static void reset_gcr0(struct fsl_xgkr_inst *inst)
+{
+ struct per_lane_ctrl_status *reg_base;
+
+ reg_base = (struct per_lane_ctrl_status *)inst->reg_base;
+
+ iowrite32be(ioread32be(&reg_base->gcr0) & ~GCR0_RESET_MASK,
+ &reg_base->gcr0);
+ udelay(1);
+ iowrite32be(ioread32be(&reg_base->gcr0) | GCR0_RESET_MASK,
+ &reg_base->gcr0);
+ udelay(1);
+}
+
+static void reset_lt(struct phy_device *phydev)
+{
+ phy_write_mmd(phydev, FSL_XFI_PMD, FSL_XFI_PMD_CTRL, PMD_RESET);
+ phy_write_mmd(phydev, FSL_XFI_PMD, FSL_XFI_KR_PMD_CTRL, TRAIN_DISABLE);
+ phy_write_mmd(phydev, FSL_XFI_PMD, FSL_XFI_KR_LD_CU, 0);
+ phy_write_mmd(phydev, FSL_XFI_PMD, FSL_XFI_KR_LD_STATUS, 0);
+ phy_write_mmd(phydev, FSL_XFI_PMD, FSL_XFI_KR_PMD_STATUS, 0);
+ phy_write_mmd(phydev, FSL_XFI_PMD, FSL_XFI_KR_LP_CU, 0);
+ phy_write_mmd(phydev, FSL_XFI_PMD, FSL_XFI_KR_LP_STATUS, 0);
+}
+
+static void start_an(struct phy_device *phydev)
+{
+ reset_lt(phydev);
+ phy_write_mmd(phydev, FSL_XFI_AN, FSL_XFI_AN_AD_1, XFI_AN_AD1);
+ phy_write_mmd(phydev, FSL_XFI_AN, FSL_XFI_AN_CTRL, XF_AN_RESTART);
+}
+
+static void ld_coe_status(struct fsl_xgkr_inst *inst)
+{
+ phy_write_mmd(inst->phydev, FSL_XFI_PMD,
+ FSL_XFI_KR_LD_STATUS, inst->ld_status);
+}
+
+static void ld_coe_update(struct fsl_xgkr_inst *inst)
+{
+ phy_write_mmd(inst->phydev, FSL_XFI_PMD,
+ FSL_XFI_KR_LD_CU, inst->ld_update);
+}
+
+static void init_inst(struct fsl_xgkr_inst *inst, int reset)
+{
+ if (reset) {
+ inst->ratio_preq = RATIO_PREQ;
+ inst->ratio_pst1q = RATIO_PST1Q;
+ inst->adpt_eq = RATIO_EQ;
+ tune_tecr0(inst);
+ }
+
+ inst->ld_status &= RX_READY_MASK;
+ ld_coe_status(inst);
+
+ /* init state machine */
+ init_state_machine(&inst->t_s_m);
+
+ inst->ld_update = 0;
+ ld_coe_update(inst);
+
+ inst->ld_status &= ~RX_READY_MASK;
+ ld_coe_status(inst);
+}
+
+static bool is_bin_early(int bin_sel, void __iomem *reg)
+{
+ bool early = false;
+ int bin_snap_shot[BIN_SNAPSHOT_NUM];
+ int i, negative_count = 0;
+ struct per_lane_ctrl_status *reg_base;
+ int timeout;
+
+ reg_base = (struct per_lane_ctrl_status *)reg;
+
+ for (i = 0; i < BIN_SNAPSHOT_NUM; i++) {
+ /* wait RECR1_SNP_DONE_MASK has cleared */
+ timeout = 100;
+ while ((ioread32be(&reg_base->recr1) & RECR1_SNP_DONE_MASK)) {
+ udelay(1);
+ timeout--;
+ if (timeout == 0)
+ break;
+ }
+
+ /* set TCSR1[CDR_SEL] to BinM1/BinLong */
+ if (bin_sel == BIN_M1) {
+ iowrite32be((ioread32be(&reg_base->tcsr1) &
+ ~CDR_SEL_MASK) | BIN_M1_SEL,
+ &reg_base->tcsr1);
+ } else {
+ iowrite32be((ioread32be(&reg_base->tcsr1) &
+ ~CDR_SEL_MASK) | BIN_Long_SEL,
+ &reg_base->tcsr1);
+ }
+
+ /* start snap shot */
+ iowrite32be(ioread32be(&reg_base->gcr1) | GCR1_SNP_START_MASK,
+ &reg_base->gcr1);
+
+ /* wait for SNP done */
+ timeout = 100;
+ while (!(ioread32be(&reg_base->recr1) & RECR1_SNP_DONE_MASK)) {
+ udelay(1);
+ timeout--;
+ if (timeout == 0)
+ break;
+ }
+
+ /* read and save the snap shot */
+ bin_snap_shot[i] = (ioread32be(&reg_base->tcsr1) &
+ TCSR1_SNP_DATA_MASK) >> TCSR1_SNP_DATA_SHIFT;
+ if (bin_snap_shot[i] & TCSR1_EQ_SNPBIN_SIGN_MASK)
+ negative_count++;
+
+ /* terminate the snap shot by setting GCR1[REQ_CTL_SNP] */
+ iowrite32be(ioread32be(&reg_base->gcr1) & ~GCR1_SNP_START_MASK,
+ &reg_base->gcr1);
+ }
+
+ if (((bin_sel == BIN_M1) && negative_count > BIN_M1_THRESHOLD) ||
+ ((bin_sel == BIN_LONG && negative_count > BIN_LONG_THRESHOLD))) {
+ early = true;
+ }
+
+ return early;
+}
+
+static void train_tx(struct fsl_xgkr_inst *inst)
+{
+ struct phy_device *phydev = inst->phydev;
+ struct training_state_machine *s_m = &inst->t_s_m;
+ bool bin_m1_early, bin_long_early;
+ u32 lp_status, old_ld_update;
+ u32 status_cop1, status_coz, status_com1;
+ u32 req_cop1, req_coz, req_com1, req_preset, req_init;
+ u32 temp;
+
+recheck:
+ if (s_m->bin_long_stop && s_m->bin_m1_stop) {
+ s_m->tx_complete = true;
+ inst->ld_status |= RX_READY_MASK;
+ ld_coe_status(inst);
+ /* tell LP we are ready */
+ phy_write_mmd(phydev, FSL_XFI_PMD,
+ FSL_XFI_KR_PMD_STATUS, RX_STAT);
+ return;
+ }
+
+ /* We start by checking the current LP status. If we got any responses,
+ * we can clear up the appropriate update request so that the
+ * subsequent code may easily issue new update requests if needed.
+ */
+ lp_status = phy_read_mmd(phydev, FSL_XFI_PMD, FSL_XFI_KR_LP_STATUS) &
+ REQUEST_MASK;
+ status_cop1 = (lp_status & COP1_MASK) >> COP1_SHIFT;
+ status_coz = (lp_status & COZ_MASK) >> COZ_SHIFT;
+ status_com1 = (lp_status & COM1_MASK) >> COM1_SHIFT;
+
+ old_ld_update = inst->ld_update;
+ req_cop1 = (old_ld_update & COP1_MASK) >> COP1_SHIFT;
+ req_coz = (old_ld_update & COZ_MASK) >> COZ_SHIFT;
+ req_com1 = (old_ld_update & COM1_MASK) >> COM1_SHIFT;
+ req_preset = old_ld_update & PRESET_MASK;
+ req_init = old_ld_update & INIT_MASK;
+
+ /* IEEE802.3-2008, 72.6.10.2.3.1
+ * We may clear PRESET when all coefficients show UPDATED or MAX.
+ */
+ if (req_preset) {
+ if ((status_cop1 == COE_UPDATED || status_cop1 == COE_MAX) &&
+ (status_coz == COE_UPDATED || status_coz == COE_MAX) &&
+ (status_com1 == COE_UPDATED || status_com1 == COE_MAX)) {
+ inst->ld_update &= ~PRESET_MASK;
+ }
+ }
+
+ /* IEEE802.3-2008, 72.6.10.2.3.2
+ * We may clear INITIALIZE when no coefficients show NOT UPDATED.
+ */
+ if (req_init) {
+ if (status_cop1 != COE_NOTUPDATED &&
+ status_coz != COE_NOTUPDATED &&
+ status_com1 != COE_NOTUPDATED) {
+ inst->ld_update &= ~INIT_MASK;
+ }
+ }
+
+ /* IEEE802.3-2008, 72.6.10.2.3.2
+ * we send initialize to the other side to ensure default settings
+ * for the LP. Naturally, we should do this only once.
+ */
+ if (!s_m->sent_init) {
+ if (!lp_status && !(old_ld_update & (LD_ALL_MASK))) {
+ inst->ld_update |= INIT_MASK;
+ s_m->sent_init = true;
+ }
+ }
+
+ /* IEEE802.3-2008, 72.6.10.2.3.3
+ * We set coefficient requests to HOLD when we get the information
+ * about any updates On clearing our prior response, we also update
+ * our internal status.
+ */
+ if (status_cop1 != COE_NOTUPDATED) {
+ if (req_cop1) {
+ inst->ld_update &= ~COP1_MASK;
+ if ((req_cop1 == DECREMENT && status_cop1 == COE_MIN) ||
+ (req_cop1 == INCREMENT && status_cop1 == COE_MAX)) {
+ s_m->long_min_max_cnt++;
+ if (s_m->long_min_max_cnt >= TIMEOUT_LONG) {
+ s_m->bin_long_stop = true;
+ goto recheck;
+ }
+ }
+ }
+ }
+
+ if (status_coz != COE_NOTUPDATED) {
+ if (req_coz)
+ inst->ld_update &= ~COZ_MASK;
+ }
+
+ if (status_com1 != COE_NOTUPDATED) {
+ if (req_com1) {
+ inst->ld_update &= ~COM1_MASK;
+ /* Stop If we have reached the limit for a parameter. */
+ if ((req_com1 == DECREMENT && status_com1 == COE_MIN) ||
+ (req_com1 == INCREMENT && status_com1 == COE_MAX)) {
+ s_m->m1_min_max_cnt++;
+ if (s_m->m1_min_max_cnt >= TIMEOUT_M1) {
+ s_m->bin_m1_stop = true;
+ goto recheck;
+ }
+ }
+ }
+ }
+
+ if (old_ld_update != inst->ld_update) {
+ ld_coe_update(inst);
+ /* Redo these status checks and updates until we have no more
+ * changes, to speed up the overall process.
+ */
+ goto recheck;
+ }
+
+ /* snapshot and select bin */
+ bin_m1_early = is_bin_early(BIN_M1, inst->reg_base);
+ bin_long_early = is_bin_early(BIN_LONG, inst->reg_base);
+
+ if (!s_m->bin_m1_stop && !s_m->bin_m1_late_early && bin_m1_early) {
+ s_m->bin_m1_stop = true;
+ goto recheck;
+ }
+
+ if (!s_m->bin_long_stop &&
+ s_m->bin_long_late_early && !bin_long_early) {
+ s_m->bin_long_stop = true;
+ goto recheck;
+ }
+
+ /* IEEE802.3-2008, 72.6.10.2.3.3
+ * We only request coefficient updates when no PRESET/INITIALIZE is
+ * pending! We also only request coefficient updates when the
+ * corresponding status is NOT UPDATED and nothing is pending.
+ */
+ if (!(inst->ld_update & (PRESET_MASK | INIT_MASK))) {
+ if (!s_m->bin_long_stop) {
+ /* BinM1 correction means changing COM1 */
+ if (!status_com1 && !(inst->ld_update & COM1_MASK)) {
+ /* Avoid BinM1Late by requesting an
+ * immediate decrement.
+ */
+ if (!bin_m1_early) {
+ /* request decrement c(-1) */
+ temp = DECREMENT << COM1_SHIFT;
+ inst->ld_update |= temp;
+ ld_coe_update(inst);
+ s_m->bin_m1_late_early = bin_m1_early;
+ }
+ }
+
+ /* BinLong correction means changing COP1 */
+ if (!status_cop1 && !(inst->ld_update & COP1_MASK)) {
+ /* Locate BinLong transition point (if any)
+ * while avoiding BinM1Late.
+ */
+ if (bin_long_early) {
+ /* request increment c(1) */
+ temp = INCREMENT << COP1_SHIFT;
+ inst->ld_update |= temp;
+ } else {
+ /* request decrement c(1) */
+ temp = DECREMENT << COP1_SHIFT;
+ inst->ld_update |= temp;
+ }
+
+ ld_coe_update(inst);
+ s_m->bin_long_late_early = bin_long_early;
+ }
+ /* We try to finish BinLong before we do BinM1 */
+ return;
+ }
+
+ if (!s_m->bin_m1_stop) {
+ /* BinM1 correction means changing COM1 */
+ if (!status_com1 && !(inst->ld_update & COM1_MASK)) {
+ /* Locate BinM1 transition point (if any) */
+ if (bin_m1_early) {
+ /* request increment c(-1) */
+ temp = INCREMENT << COM1_SHIFT;
+ inst->ld_update |= temp;
+ } else {
+ /* request decrement c(-1) */
+ temp = DECREMENT << COM1_SHIFT;
+ inst->ld_update |= temp;
+ }
+
+ ld_coe_update(inst);
+ s_m->bin_m1_late_early = bin_m1_early;
+ }
+ }
+ }
+}
+
+static int check_an_link(struct phy_device *phydev)
+{
+ int val;
+ int timeout = 100;
+
+ while (timeout--) {
+ val = phy_read_mmd(phydev, FSL_XFI_AN, FSL_XFI_LNK_STATUS);
+ if (val & XFI_AN_LNK_STAT_UP)
+ return 1;
+ usleep_range(100, 500);
+ }
+
+ return 0;
+}
+
+static int is_link_training_fail(struct phy_device *phydev)
+{
+ int val;
+
+ val = phy_read_mmd(phydev, FSL_XFI_PMD, FSL_XFI_KR_PMD_STATUS);
+ if (!(val & TRAIN_FAIL) && (val & RX_STAT)) {
+ /* check LNK_STAT for sure */
+ if (check_an_link(phydev))
+ return 0;
+ return 1;
+ }
+ return 1;
+}
+
+static int check_rx(struct phy_device *phydev)
+{
+ return phy_read_mmd(phydev, FSL_XFI_PMD, FSL_XFI_KR_LP_STATUS) &
+ RX_READY_MASK;
+}
+
+/* Coefficient values have hardware restrictions */
+static int is_ld_valid(u32 *ld_coe)
+{
+ u32 ratio_pst1q = *ld_coe;
+ u32 adpt_eq = *(ld_coe + 1);
+ u32 ratio_preq = *(ld_coe + 2);
+
+ if ((ratio_pst1q + adpt_eq + ratio_preq) > 48)
+ return 0;
+
+ if (((ratio_pst1q + adpt_eq + ratio_preq) * 4) >=
+ ((adpt_eq - ratio_pst1q - ratio_preq) * 17))
+ return 0;
+
+ if (ratio_preq > ratio_pst1q)
+ return 0;
+
+ if (ratio_preq > 8)
+ return 0;
+
+ if (adpt_eq < 26)
+ return 0;
+
+ if (ratio_pst1q > 16)
+ return 0;
+
+ return 1;
+}
+
+static int inc_dec(struct fsl_xgkr_inst *inst, int field, int request)
+{
+ u32 ld_limit[3], ld_coe[3], step[3];
+
+ ld_coe[0] = inst->ratio_pst1q;
+ ld_coe[1] = inst->adpt_eq;
+ ld_coe[2] = inst->ratio_preq;
+
+ /* Information specific to the Freescale SerDes for 10GBase-KR:
+ * Incrementing C(+1) means *decrementing* RATIO_PST1Q
+ * Incrementing C(0) means incrementing ADPT_EQ
+ * Incrementing C(-1) means *decrementing* RATIO_PREQ
+ */
+ step[0] = -1;
+ step[1] = 1;
+ step[2] = -1;
+
+ switch (request) {
+ case INCREMENT:
+ ld_limit[0] = POST_COE_MAX;
+ ld_limit[1] = ZERO_COE_MAX;
+ ld_limit[2] = PRE_COE_MAX;
+ if (ld_coe[field] != ld_limit[field])
+ ld_coe[field] += step[field];
+ else
+ /* MAX */
+ return 2;
+ break;
+ case DECREMENT:
+ ld_limit[0] = POST_COE_MIN;
+ ld_limit[1] = ZERO_COE_MIN;
+ ld_limit[2] = PRE_COE_MIN;
+ if (ld_coe[field] != ld_limit[field])
+ ld_coe[field] -= step[field];
+ else
+ /* MIN */
+ return 1;
+ break;
+ default:
+ break;
+ }
+
+ if (is_ld_valid(ld_coe)) {
+ /* accept new ld */
+ inst->ratio_pst1q = ld_coe[0];
+ inst->adpt_eq = ld_coe[1];
+ inst->ratio_preq = ld_coe[2];
+ tune_tecr0(inst);
+ } else {
+ if (request == DECREMENT)
+ /* MIN */
+ return 1;
+ if (request == INCREMENT)
+ /* MAX */
+ return 2;
+ }
+
+ return 0;
+}
+
+static void min_max_updated(struct fsl_xgkr_inst *inst, int field, int new_ld)
+{
+ u32 ld_coe[] = {COE_UPDATED, COE_MIN, COE_MAX};
+ u32 mask, val;
+
+ switch (field) {
+ case COE_COP1:
+ mask = COP1_MASK;
+ val = ld_coe[new_ld] << COP1_SHIFT;
+ break;
+ case COE_COZ:
+ mask = COZ_MASK;
+ val = ld_coe[new_ld] << COZ_SHIFT;
+ break;
+ case COE_COM:
+ mask = COM1_MASK;
+ val = ld_coe[new_ld] << COM1_SHIFT;
+ break;
+ default:
+ return;
+ break;
+ }
+
+ inst->ld_status &= ~mask;
+ inst->ld_status |= val;
+}
+
+static void check_request(struct fsl_xgkr_inst *inst, int request)
+{
+ int cop1_req, coz_req, com_req;
+ int old_status, new_ld_sta;
+
+ cop1_req = (request & COP1_MASK) >> COP1_SHIFT;
+ coz_req = (request & COZ_MASK) >> COZ_SHIFT;
+ com_req = (request & COM1_MASK) >> COM1_SHIFT;
+
+ /* IEEE802.3-2008, 72.6.10.2.5
+ * Ensure we only act on INCREMENT/DECREMENT when we are in NOT UPDATED!
+ */
+ old_status = inst->ld_status;
+
+ if (cop1_req && !(inst->ld_status & COP1_MASK)) {
+ new_ld_sta = inc_dec(inst, COE_COP1, cop1_req);
+ min_max_updated(inst, COE_COP1, new_ld_sta);
+ }
+
+ if (coz_req && !(inst->ld_status & COZ_MASK)) {
+ new_ld_sta = inc_dec(inst, COE_COZ, coz_req);
+ min_max_updated(inst, COE_COZ, new_ld_sta);
+ }
+
+ if (com_req && !(inst->ld_status & COM1_MASK)) {
+ new_ld_sta = inc_dec(inst, COE_COM, com_req);
+ min_max_updated(inst, COE_COM, new_ld_sta);
+ }
+
+ if (old_status != inst->ld_status)
+ ld_coe_status(inst);
+
+}
+
+static void preset(struct fsl_xgkr_inst *inst)
+{
+ /* These are all MAX values from the IEEE802.3 perspective! */
+ inst->ratio_pst1q = POST_COE_MAX;
+ inst->adpt_eq = ZERO_COE_MAX;
+ inst->ratio_preq = PRE_COE_MAX;
+
+ tune_tecr0(inst);
+ inst->ld_status &= ~(COP1_MASK | COZ_MASK | COM1_MASK);
+ inst->ld_status |= COE_MAX << COP1_SHIFT |
+ COE_MAX << COZ_SHIFT |
+ COE_MAX << COM1_SHIFT;
+ ld_coe_status(inst);
+}
+
+static void initialize(struct fsl_xgkr_inst *inst)
+{
+ inst->ratio_preq = RATIO_PREQ;
+ inst->ratio_pst1q = RATIO_PST1Q;
+ inst->adpt_eq = RATIO_EQ;
+
+ tune_tecr0(inst);
+ inst->ld_status &= ~(COP1_MASK | COZ_MASK | COM1_MASK);
+ inst->ld_status |= COE_UPDATED << COP1_SHIFT |
+ COE_UPDATED << COZ_SHIFT |
+ COE_UPDATED << COM1_SHIFT;
+ ld_coe_status(inst);
+}
+
+static void train_rx(struct fsl_xgkr_inst *inst)
+{
+ struct phy_device *phydev = inst->phydev;
+ int request, old_ld_status;
+
+ /* get request from LP */
+ request = phy_read_mmd(phydev, FSL_XFI_PMD, FSL_XFI_KR_LP_CU) &
+ (LD_ALL_MASK);
+ old_ld_status = inst->ld_status;
+
+ /* IEEE802.3-2008, 72.6.10.2.5
+ * Ensure we always go to NOT UDPATED for status reporting in
+ * response to HOLD requests.
+ * IEEE802.3-2008, 72.6.10.2.3.1/2
+ * ... but only if PRESET/INITIALIZE are not active to ensure
+ * we keep status until they are released!
+ */
+ if (!(request & (PRESET_MASK | INIT_MASK))) {
+ if (!(request & COP1_MASK))
+ inst->ld_status &= ~COP1_MASK;
+
+ if (!(request & COZ_MASK))
+ inst->ld_status &= ~COZ_MASK;
+
+ if (!(request & COM1_MASK))
+ inst->ld_status &= ~COM1_MASK;
+
+ if (old_ld_status != inst->ld_status)
+ ld_coe_status(inst);
+
+ }
+
+ /* As soon as the LP shows ready, no need to do any more updates. */
+ if (check_rx(phydev)) {
+ /* LP receiver is ready */
+ if (inst->ld_status & (COP1_MASK | COZ_MASK | COM1_MASK)) {
+ inst->ld_status &= ~(COP1_MASK | COZ_MASK | COM1_MASK);
+ ld_coe_status(inst);
+ }
+ } else {
+ /* IEEE802.3-2008, 72.6.10.2.3.1/2
+ * only act on PRESET/INITIALIZE if all status is NOT UPDATED.
+ */
+ if (request & (PRESET_MASK | INIT_MASK)) {
+ if (!(inst->ld_status &
+ (COP1_MASK | COZ_MASK | COM1_MASK))) {
+ if (request & PRESET_MASK)
+ preset(inst);
+
+ if (request & INIT_MASK)
+ initialize(inst);
+ }
+ }
+
+ /* LP Coefficient are not in HOLD */
+ if (request & REQUEST_MASK)
+ check_request(inst, request & REQUEST_MASK);
+ }
+}
+
+static void xgkr_wq_state_machine(struct work_struct *work)
+{
+ struct fsl_xgkr_wk *wk = container_of(work,
+ struct fsl_xgkr_wk, xgkr_wk);
+ struct fsl_xgkr_inst *inst = wk->xgkr_inst;
+ struct training_state_machine *s_m = &inst->t_s_m;
+ struct phy_device *phydev = inst->phydev;
+ int val = 0, i;
+ int an_state, lt_state;
+ unsigned long dead_line;
+ int rx_ok, tx_ok;
+
+ if (s_m->link_up) {
+ /* check abnormal link down events when link is up, for ex.
+ * the cable is pulled out or link partner is down.
+ */
+ an_state = phy_read_mmd(phydev, FSL_XFI_AN, FSL_XFI_LNK_STATUS);
+ if (!(an_state & XFI_AN_LNK_STAT_UP)) {
+ dev_info(&phydev->dev,
+ "Detect hotplug, restart training!\n");
+ init_inst(inst, 1);
+ start_an(phydev);
+ }
+ s_m->running = false;
+ return;
+ }
+
+ if (!s_m->an_ok) {
+ an_state = phy_read_mmd(phydev, FSL_XFI_AN, FSL_XFI_BP_STATUS);
+ if (!(an_state & AN_10GKR_MASK)) {
+ s_m->running = false;
+ return;
+ } else
+ s_m->an_ok = true;
+ }
+
+ dev_info(&phydev->dev, "is training.\n");
+
+ start_lt(phydev);
+ for (i = 0; i < 2;) {
+ /* i < 1 also works, but start one more try immediately when
+ * failed can adjust our training frequency to match other
+ * devices. This can help the link being established more
+ * quickly.
+ */
+ dead_line = jiffies + msecs_to_jiffies(500);
+ while (time_before(jiffies, dead_line)) {
+ val = phy_read_mmd(phydev, FSL_XFI_PMD,
+ FSL_XFI_KR_PMD_STATUS);
+ if (val & TRAIN_FAIL) {
+ /* LT failed already, reset lane to avoid
+ * it run into hanging, then start LT again.
+ */
+ reset_gcr0(inst);
+ start_lt(phydev);
+ } else if (val & PMD_STATUS_SUP_STAT &&
+ val & PMD_STATUS_FRAME_LOCK)
+ break;
+ usleep_range(100, 500);
+ }
+
+ if (!(val & PMD_STATUS_FRAME_LOCK &&
+ val & PMD_STATUS_SUP_STAT)) {
+ i++;
+ continue;
+ }
+
+ /* init process */
+ rx_ok = tx_ok = false;
+ /* the LT should be finished in 500ms, failed or OK. */
+ dead_line = jiffies + msecs_to_jiffies(500);
+
+ while (time_before(jiffies, dead_line)) {
+ /* check if the LT is already failed */
+ lt_state = phy_read_mmd(phydev, FSL_XFI_PMD,
+ FSL_XFI_KR_PMD_STATUS);
+ if (lt_state & TRAIN_FAIL) {
+ reset_gcr0(inst);
+ break;
+ }
+
+ rx_ok = check_rx(phydev);
+ tx_ok = s_m->tx_complete;
+
+ if (rx_ok && tx_ok)
+ break;
+
+ if (!rx_ok)
+ train_rx(inst);
+
+ if (!tx_ok)
+ train_tx(inst);
+ usleep_range(100, 500);
+ }
+
+ i++;
+ /* check LT result */
+ if (is_link_training_fail(phydev)) {
+ /* reset state machine */
+ init_inst(inst, 0);
+ continue;
+ } else {
+ stop_lt(phydev);
+ s_m->running = false;
+ s_m->link_up = true;
+ dev_info(&phydev->dev, "LT training is SUCCEEDED!\n");
+ break;
+ }
+ }
+
+ if (!s_m->link_up) {
+ /* reset state machine */
+ init_inst(inst, 0);
+ }
+}
+
+static void xgkr_timer_handle(unsigned long arg)
+{
+ struct list_head *pos;
+ struct fsl_xgkr_wk *wk;
+ struct fsl_xgkr_inst *xgkr_inst;
+ struct phy_device *phydev;
+ struct training_state_machine *s_m;
+
+ list_for_each(pos, &fsl_xgkr_list) {
+ wk = list_entry(pos, struct fsl_xgkr_wk, xgkr_list);
+ xgkr_inst = wk->xgkr_inst;
+ phydev = xgkr_inst->phydev;
+ s_m = &xgkr_inst->t_s_m;
+
+ if (!s_m->running && (!s_m->an_ok || s_m->link_up)) {
+ s_m->running = true;
+ queue_work(xgkr_wq, (struct work_struct *)wk);
+ }
+ }
+
+ if (!list_empty(&fsl_xgkr_list))
+ mod_timer(&xgkr_timer,
+ jiffies + msecs_to_jiffies(XGKR_TIMEOUT));
+}
+
+static int fsl_xgkr_bind_serdes(const char *lane_name,
+ struct phy_device *phydev)
+{
+ unsigned long serdes_base;
+ unsigned long lane_base;
+ int i;
+
+ for (i = 0; i < SERDES_MAX; i++) {
+ if (strstr(lane_name, s_map[i].serdes_name)) {
+ serdes_base = s_map[i].serdes_base;
+ break;
+ }
+ }
+
+ if (i == SERDES_MAX)
+ goto serdes_err;
+
+ for (i = 0; i < LANE_MAX; i++) {
+ if (strstr(lane_name, l_map[i].lane_name)) {
+ lane_base = l_map[i].lane_base;
+ break;
+ }
+ }
+
+ if (i == LANE_MAX)
+ goto lane_err;
+
+ phydev->priv = ioremap(serdes_base + lane_base,
+ sizeof(struct per_lane_ctrl_status));
+ if (!phydev->priv)
+ return -ENOMEM;
+
+ return 0;
+
+serdes_err:
+ dev_err(&phydev->dev, "Unknown SerDes name");
+ return -EINVAL;
+lane_err:
+ dev_err(&phydev->dev, "Unknown Lane name");
+ return -EINVAL;
+}
+
+static int fsl_xgkr_probe(struct phy_device *phydev)
+{
+ struct fsl_xgkr_inst *xgkr_inst;
+ struct fsl_xgkr_wk *xgkr_wk;
+ struct device_node *child;
+ const char *lane_name;
+ int len;
+
+ child = phydev->dev.of_node;
+
+ /* if there is lane-instance property, 10G-KR need to run */
+ lane_name = of_get_property(child, "lane-instance", &len);
+ if (!lane_name || (fsl_xgkr_bind_serdes(lane_name, phydev)))
+ return 0;
+
+ xgkr_inst = kzalloc(sizeof(struct fsl_xgkr_inst), GFP_KERNEL);
+ if (!xgkr_inst)
+ goto mem_err1;
+
+ xgkr_inst->reg_base = phydev->priv;
+
+ xgkr_inst->bus = phydev->bus;
+
+ xgkr_inst->phydev = phydev;
+
+ init_inst(xgkr_inst, 1);
+
+ xgkr_wk = kzalloc(sizeof(struct fsl_xgkr_wk), GFP_KERNEL);
+ if (!xgkr_wk)
+ goto mem_err2;
+
+ xgkr_wk->xgkr_inst = xgkr_inst;
+ phydev->priv = xgkr_wk;
+
+ list_add(&xgkr_wk->xgkr_list, &fsl_xgkr_list);
+
+ if (!fire_timer) {
+ setup_timer(&xgkr_timer, xgkr_timer_handle,
+ (unsigned long)&fsl_xgkr_list);
+ mod_timer(&xgkr_timer,
+ jiffies + msecs_to_jiffies(XGKR_TIMEOUT));
+ fire_timer = 1;
+ xgkr_wq = create_workqueue("fsl_xgkr");
+ }
+ INIT_WORK((struct work_struct *)xgkr_wk, xgkr_wq_state_machine);
+
+ /* start auto-negotiation to detect link partner */
+ start_an(phydev);
+
+ return 0;
+mem_err2:
+ kfree(xgkr_inst);
+mem_err1:
+ dev_err(&phydev->dev, "failed to allocate memory!\n");
+ return -ENOMEM;
+}
+
+static int fsl_xgkr_config_init(struct phy_device *phydev)
+{
+ return 0;
+}
+
+static int fsl_xgkr_config_aneg(struct phy_device *phydev)
+{
+ return 0;
+}
+
+static void fsl_xgkr_remove(struct phy_device *phydev)
+{
+ struct fsl_xgkr_wk *wk = (struct fsl_xgkr_wk *)phydev->priv;
+ struct fsl_xgkr_inst *xgkr_inst = wk->xgkr_inst;
+ struct list_head *this, *next;
+ struct fsl_xgkr_wk *tmp;
+
+ list_for_each_safe(this, next, &fsl_xgkr_list) {
+ tmp = list_entry(this, struct fsl_xgkr_wk, xgkr_list);
+ if (tmp == wk) {
+ cancel_work_sync((struct work_struct *)wk);
+ list_del(this);
+ }
+ }
+
+ if (list_empty(&fsl_xgkr_list))
+ del_timer(&xgkr_timer);
+
+ if (xgkr_inst->reg_base)
+ iounmap(xgkr_inst->reg_base);
+
+ kfree(xgkr_inst);
+ kfree(wk);
+}
+
+static int fsl_xgkr_read_status(struct phy_device *phydev)
+{
+ int val = phy_read_mmd(phydev, FSL_XFI_AN, FSL_XFI_LNK_STATUS);
+
+ phydev->speed = SPEED_10000;
+ phydev->duplex = 1;
+
+ if (val & XFI_AN_LNK_STAT_UP)
+ phydev->link = 1;
+ else
+ phydev->link = 0;
+
+ return 0;
+}
+
+static int fsl_xgkr_match_phy_device(struct phy_device *phydev)
+{
+ return phydev->c45_ids.device_ids[3] == FSL_XFI_PCS_PHY_ID;
+}
+
+static int fsl_xgkr_match_phy_device2(struct phy_device *phydev)
+{
+ return phydev->c45_ids.device_ids[3] == FSL_XFI_PCS_PHY_ID2;
+}
+
+static struct phy_driver fsl_xgkr_driver[] = {
+ {
+ .phy_id = FSL_XFI_PCS_PHY_ID,
+ .name = "Freescale 10G KR Rev1",
+ .phy_id_mask = 0xffffffff,
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .probe = fsl_xgkr_probe,
+ .config_init = &fsl_xgkr_config_init,
+ .config_aneg = &fsl_xgkr_config_aneg,
+ .read_status = &fsl_xgkr_read_status,
+ .match_phy_device = fsl_xgkr_match_phy_device,
+ .remove = fsl_xgkr_remove,
+ .driver = { .owner = THIS_MODULE,},
+ },
+ {
+ .phy_id = FSL_XFI_PCS_PHY_ID2,
+ .name = "Freescale 10G KR Rev2",
+ .phy_id_mask = 0xffffffff,
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .probe = fsl_xgkr_probe,
+ .config_init = &fsl_xgkr_config_init,
+ .config_aneg = &fsl_xgkr_config_aneg,
+ .read_status = &fsl_xgkr_read_status,
+ .match_phy_device = fsl_xgkr_match_phy_device2,
+ .remove = fsl_xgkr_remove,
+ .driver = { .owner = THIS_MODULE,},
+ },
+};
+
+static int __init fsl_xgkr_init(void)
+{
+ return phy_drivers_register(fsl_xgkr_driver,
+ ARRAY_SIZE(fsl_xgkr_driver));
+}
+
+static void __exit fsl_xgkr_exit(void)
+{
+ phy_drivers_unregister(fsl_xgkr_driver,
+ ARRAY_SIZE(fsl_xgkr_driver));
+}
+
+module_init(fsl_xgkr_init);
+module_exit(fsl_xgkr_exit);
+
+static struct mdio_device_id __maybe_unused freescale_tbl[] = {
+ { FSL_XFI_PCS_PHY_ID, 0xffffffff },
+ { FSL_XFI_PCS_PHY_ID2, 0xffffffff },
+ { }
+};
+
+MODULE_DEVICE_TABLE(mdio, freescale_tbl);
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 2e91477..2128c6c 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -54,6 +54,8 @@
#define MII_M1145_RGMII_RX_DELAY 0x0080
#define MII_M1145_RGMII_TX_DELAY 0x0002
+#define MII_M1145_PHY_EXT_ADDR_PAGE 0x16
+
#define MII_M1111_PHY_LED_CONTROL 0x18
#define MII_M1111_PHY_LED_DIRECT 0x4100
#define MII_M1111_PHY_LED_COMBINE 0x411c
@@ -490,6 +492,16 @@ static int m88e1111_config_init(struct phy_device *phydev)
err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
if (err < 0)
return err;
+
+ /* make sure copper is selected */
+ err = phy_read(phydev, MII_M1145_PHY_EXT_ADDR_PAGE);
+ if (err < 0)
+ return err;
+
+ err = phy_write(phydev, MII_M1145_PHY_EXT_ADDR_PAGE,
+ err & (~1));
+ if (err < 0)
+ return err;
}
if (phydev->interface == PHY_INTERFACE_MODE_RTBI) {
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 74630e9..cfb5110 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -32,6 +32,7 @@
#include <linux/module.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
+#include <linux/mdio.h>
#include <linux/phy.h>
#include <asm/io.h>
@@ -54,15 +55,13 @@ static void phy_device_release(struct device *dev)
}
static struct phy_driver genphy_driver;
+static struct phy_driver gen10g_driver;
extern int mdio_bus_init(void);
extern void mdio_bus_exit(void);
static LIST_HEAD(phy_fixup_list);
static DEFINE_MUTEX(phy_fixup_lock);
-static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
- u32 flags, phy_interface_t interface);
-
/*
* Creates a new phy_fixup and adds it to the list
* @bus_id: A string which matches phydev->dev.bus_id (or PHY_ANY_ID)
@@ -520,12 +519,12 @@ int phy_init_hw(struct phy_device *phydev)
*
* Description: Called by drivers to attach to a particular PHY
* device. The phy_device is found, and properly hooked up
- * to the phy_driver. If no driver is attached, then the
- * genphy_driver is used. The phy_device is given a ptr to
+ * to the phy_driver. If no driver is attached, then a
+ * generic driver is used. The phy_device is given a ptr to
* the attaching device, and given a callback for link status
* change. The phy_device is returned to the attaching driver.
*/
-static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
+int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
u32 flags, phy_interface_t interface)
{
struct device *d = &phydev->dev;
@@ -534,12 +533,10 @@ static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
/* Assume that if there is no driver, that it doesn't
* exist, and we should use the genphy driver. */
if (NULL == d->driver) {
- if (phydev->is_c45) {
- pr_err("No driver for phy %x\n", phydev->phy_id);
- return -ENODEV;
- }
-
- d->driver = &genphy_driver.driver;
+ if (phydev->is_c45)
+ d->driver = &gen10g_driver.driver;
+ else
+ d->driver = &genphy_driver.driver;
err = d->driver->probe(d);
if (err >= 0)
@@ -572,6 +569,7 @@ static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
return err;
}
+EXPORT_SYMBOL(phy_attach_direct);
/**
* phy_attach - attach a network device to a particular PHY device
@@ -622,6 +620,8 @@ void phy_detach(struct phy_device *phydev)
* real driver could be loaded */
if (phydev->dev.driver == &genphy_driver.driver)
device_release_driver(&phydev->dev);
+ else if (phydev->dev.driver == &gen10g_driver.driver)
+ device_release_driver(&phydev->dev);
}
EXPORT_SYMBOL(phy_detach);
@@ -689,6 +689,13 @@ static int genphy_config_advert(struct phy_device *phydev)
return changed;
}
+int gen10g_config_advert(struct phy_device *dev)
+{
+ return 0;
+}
+EXPORT_SYMBOL(gen10g_config_advert);
+
+
/**
* genphy_setup_forced - configures/forces speed/duplex from @phydev
* @phydev: target phy_device struct
@@ -697,7 +704,7 @@ static int genphy_config_advert(struct phy_device *phydev)
* to the values in phydev. Assumes that the values are valid.
* Please see phy_sanitize_settings().
*/
-static int genphy_setup_forced(struct phy_device *phydev)
+int genphy_setup_forced(struct phy_device *phydev)
{
int err;
int ctl = 0;
@@ -716,7 +723,7 @@ static int genphy_setup_forced(struct phy_device *phydev)
return err;
}
-
+EXPORT_SYMBOL(genphy_setup_forced);
/**
* genphy_restart_aneg - Enable and Restart Autonegotiation
@@ -742,6 +749,12 @@ int genphy_restart_aneg(struct phy_device *phydev)
}
EXPORT_SYMBOL(genphy_restart_aneg);
+int gen10g_restart_aneg(struct phy_device *phydev)
+{
+ return 0;
+}
+EXPORT_SYMBOL(gen10g_restart_aneg);
+
/**
* genphy_config_aneg - restart auto-negotiation or write BMCR
@@ -784,6 +797,13 @@ int genphy_config_aneg(struct phy_device *phydev)
}
EXPORT_SYMBOL(genphy_config_aneg);
+int gen10g_config_aneg(struct phy_device *phydev)
+{
+ return 0;
+}
+EXPORT_SYMBOL(gen10g_config_aneg);
+
+
/**
* genphy_update_link - update link status in @phydev
* @phydev: target phy_device struct
@@ -832,6 +852,8 @@ int genphy_read_status(struct phy_device *phydev)
int err;
int lpa;
int lpagb = 0;
+ int common_adv;
+ int common_adv_gb = 0;
/* Update the link, but return if there
* was an error */
@@ -852,7 +874,7 @@ int genphy_read_status(struct phy_device *phydev)
if (adv < 0)
return adv;
- lpagb &= adv << 2;
+ common_adv_gb = lpagb & adv << 2;
}
lpa = phy_read(phydev, MII_LPA);
@@ -865,24 +887,24 @@ int genphy_read_status(struct phy_device *phydev)
if (adv < 0)
return adv;
- lpa &= adv;
+ common_adv = lpa & adv;
phydev->speed = SPEED_10;
phydev->duplex = DUPLEX_HALF;
phydev->pause = phydev->asym_pause = 0;
- if (lpagb & (LPA_1000FULL | LPA_1000HALF)) {
+ if (common_adv_gb & (LPA_1000FULL | LPA_1000HALF)) {
phydev->speed = SPEED_1000;
- if (lpagb & LPA_1000FULL)
+ if (common_adv_gb & LPA_1000FULL)
phydev->duplex = DUPLEX_FULL;
- } else if (lpa & (LPA_100FULL | LPA_100HALF)) {
+ } else if (common_adv & (LPA_100FULL | LPA_100HALF)) {
phydev->speed = SPEED_100;
- if (lpa & LPA_100FULL)
+ if (common_adv & LPA_100FULL)
phydev->duplex = DUPLEX_FULL;
} else
- if (lpa & LPA_10FULL)
+ if (common_adv & LPA_10FULL)
phydev->duplex = DUPLEX_FULL;
if (phydev->duplex == DUPLEX_FULL){
@@ -913,6 +935,34 @@ int genphy_read_status(struct phy_device *phydev)
}
EXPORT_SYMBOL(genphy_read_status);
+int gen10g_read_status(struct phy_device *phydev)
+{
+ int devad, reg;
+ u32 mmd_mask = phydev->c45_ids.devices_in_package;
+
+ phydev->link = 1;
+
+ /* For now just lie and say it's 10G all the time */
+ phydev->speed = 10000;
+ phydev->duplex = DUPLEX_FULL;
+
+ for (devad = 0; mmd_mask; devad++, mmd_mask = mmd_mask >> 1) {
+ if (!(mmd_mask & 1))
+ continue;
+
+ /* Read twice because link state is latched and a
+ * read moves the current state into the register */
+ phy_read_mmd(phydev, devad, MDIO_STAT1);
+ reg = phy_read_mmd(phydev, devad, MDIO_STAT1);
+ if (reg < 0 || !(reg & MDIO_STAT1_LSTATUS))
+ phydev->link = 0;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(gen10g_read_status);
+
+
static int genphy_config_init(struct phy_device *phydev)
{
int val;
@@ -959,6 +1009,15 @@ static int genphy_config_init(struct phy_device *phydev)
return 0;
}
+
+static int gen10g_config_init(struct phy_device *phydev)
+{
+ /* Temporarily just say we support everything */
+ phydev->supported = phydev->advertising = SUPPORTED_10000baseT_Full;
+
+ return 0;
+}
+
int genphy_suspend(struct phy_device *phydev)
{
int value;
@@ -974,6 +1033,13 @@ int genphy_suspend(struct phy_device *phydev)
}
EXPORT_SYMBOL(genphy_suspend);
+int gen10g_suspend(struct phy_device *phydev)
+{
+ return 0;
+}
+EXPORT_SYMBOL(gen10g_suspend);
+
+
int genphy_resume(struct phy_device *phydev)
{
int value;
@@ -989,6 +1055,13 @@ int genphy_resume(struct phy_device *phydev)
}
EXPORT_SYMBOL(genphy_resume);
+int gen10g_resume(struct phy_device *phydev)
+{
+ return 0;
+}
+EXPORT_SYMBOL(gen10g_resume);
+
+
/**
* phy_probe - probe and init a PHY device
* @dev: device to probe and init
@@ -1129,6 +1202,20 @@ static struct phy_driver genphy_driver = {
.driver = {.owner= THIS_MODULE, },
};
+static struct phy_driver gen10g_driver = {
+ .phy_id = 0xffffffff,
+ .phy_id_mask = 0xffffffff,
+ .name = "Generic 10G PHY",
+ .config_init = gen10g_config_init,
+ .features = 0,
+ .config_aneg = gen10g_config_aneg,
+ .read_status = gen10g_read_status,
+ .suspend = gen10g_suspend,
+ .resume = gen10g_resume,
+ .driver = {.owner = THIS_MODULE, },
+};
+
+
static int __init phy_init(void)
{
int rc;
@@ -1139,13 +1226,25 @@ static int __init phy_init(void)
rc = phy_driver_register(&genphy_driver);
if (rc)
- mdio_bus_exit();
+ goto genphy_register_failed;
+
+ rc = phy_driver_register(&gen10g_driver);
+ if (rc)
+ goto gen10g_register_failed;
+
+ return rc;
+
+gen10g_register_failed:
+ phy_driver_unregister(&genphy_driver);
+genphy_register_failed:
+ mdio_bus_exit();
return rc;
}
static void __exit phy_exit(void)
{
+ phy_driver_unregister(&gen10g_driver);
phy_driver_unregister(&genphy_driver);
mdio_bus_exit();
}
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index 69b482b..14372c6 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -3,7 +3,7 @@
*
* Author: Kriston Carson
*
- * Copyright (c) 2005, 2009 Freescale Semiconductor, Inc.
+ * Copyright (c) 2005, 2009, 2011 Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -18,6 +18,11 @@
#include <linux/ethtool.h>
#include <linux/phy.h>
+/* Vitesse Extended Page Magic Register(s) */
+#define MII_VSC82X4_EXT_PAGE_16E 0x10
+#define MII_VSC82X4_EXT_PAGE_17E 0x11
+#define MII_VSC82X4_EXT_PAGE_18E 0x12
+
/* Vitesse Extended Control Register 1 */
#define MII_VSC8244_EXT_CON1 0x17
#define MII_VSC8244_EXTCON1_INIT 0x0000
@@ -54,7 +59,14 @@
#define MII_VSC8221_AUXCONSTAT_INIT 0x0004 /* need to set this bit? */
#define MII_VSC8221_AUXCONSTAT_RESERVED 0x0004
+/* Vitesse Extended Page Access Register */
+#define MII_VSC82X4_EXT_PAGE_ACCESS 0x1f
+
+#define PHY_ID_VSC8234 0x000fc620
#define PHY_ID_VSC8244 0x000fc6c0
+#define PHY_ID_VSC8514 0x00070670
+#define PHY_ID_VSC8574 0x000704a0
+#define PHY_ID_VSC8662 0x00070660
#define PHY_ID_VSC8221 0x000fc550
#define PHY_ID_VSC8211 0x000fc4b0
@@ -118,7 +130,10 @@ static int vsc82xx_config_intr(struct phy_device *phydev)
if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
err = phy_write(phydev, MII_VSC8244_IMASK,
- phydev->drv->phy_id == PHY_ID_VSC8244 ?
+ (phydev->drv->phy_id == PHY_ID_VSC8234 ||
+ phydev->drv->phy_id == PHY_ID_VSC8244 ||
+ phydev->drv->phy_id == PHY_ID_VSC8514 ||
+ phydev->drv->phy_id == PHY_ID_VSC8574) ?
MII_VSC8244_IMASK_MASK :
MII_VSC8221_IMASK_MASK);
else {
@@ -149,21 +164,126 @@ static int vsc8221_config_init(struct phy_device *phydev)
*/
}
-/* Vitesse 824x */
+/* vsc82x4_config_autocross_enable - Enable auto MDI/MDI-X for forced links
+ * @phydev: target phy_device struct
+ *
+ * Enable auto MDI/MDI-X when in 10/100 forced link speeds by writing
+ * special values in the VSC8234/VSC8244 extended reserved registers
+ */
+static int vsc82x4_config_autocross_enable(struct phy_device *phydev)
+{
+ int ret;
+
+ if (phydev->autoneg == AUTONEG_ENABLE || phydev->speed > SPEED_100)
+ return 0;
+
+ /* map extended registers set 0x10 - 0x1e */
+ ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_ACCESS, 0x52b5);
+ if (ret >= 0)
+ ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_18E, 0x0012);
+ if (ret >= 0)
+ ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_17E, 0x2803);
+ if (ret >= 0)
+ ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_16E, 0x87fa);
+ /* map standard registers set 0x10 - 0x1e */
+ if (ret >= 0)
+ ret = phy_write(phydev, MII_VSC82X4_EXT_PAGE_ACCESS, 0x0000);
+ else
+ phy_write(phydev, MII_VSC82X4_EXT_PAGE_ACCESS, 0x0000);
+
+ return ret;
+}
+
+/* vsc82x4_config_aneg - restart auto-negotiation or write BMCR
+ * @phydev: target phy_device struct
+ *
+ * Description: If auto-negotiation is enabled, we configure the
+ * advertising, and then restart auto-negotiation. If it is not
+ * enabled, then we write the BMCR and also start the auto
+ * MDI/MDI-X feature
+ */
+static int vsc82x4_config_aneg(struct phy_device *phydev)
+{
+ int ret;
+
+ /* Enable auto MDI/MDI-X when in 10/100 forced link speeds by
+ * writing special values in the VSC8234 extended reserved registers
+ */
+ if (phydev->autoneg != AUTONEG_ENABLE && phydev->speed <= SPEED_100) {
+ ret = genphy_setup_forced(phydev);
+
+ if (ret < 0) /* error */
+ return ret;
+
+ return vsc82x4_config_autocross_enable(phydev);
+ }
+
+ return genphy_config_aneg(phydev);
+}
+
+/* Vitesse 82xx */
static struct phy_driver vsc82xx_driver[] = {
{
+ .phy_id = PHY_ID_VSC8234,
+ .name = "Vitesse VSC8234",
+ .phy_id_mask = 0x000ffff0,
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = &vsc824x_config_init,
+ .config_aneg = &vsc82x4_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &vsc824x_ack_interrupt,
+ .config_intr = &vsc82xx_config_intr,
+ .driver = { .owner = THIS_MODULE,},
+}, {
.phy_id = PHY_ID_VSC8244,
.name = "Vitesse VSC8244",
.phy_id_mask = 0x000fffc0,
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_init = &vsc824x_config_init,
- .config_aneg = &genphy_config_aneg,
+ .config_aneg = &vsc82x4_config_aneg,
.read_status = &genphy_read_status,
.ack_interrupt = &vsc824x_ack_interrupt,
.config_intr = &vsc82xx_config_intr,
.driver = { .owner = THIS_MODULE,},
}, {
+ .phy_id = PHY_ID_VSC8514,
+ .name = "Vitesse VSC8514",
+ .phy_id_mask = 0x000ffff0,
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = &vsc824x_config_init,
+ .config_aneg = &vsc82x4_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &vsc824x_ack_interrupt,
+ .config_intr = &vsc82xx_config_intr,
+ .driver = { .owner = THIS_MODULE,},
+}, {
+ .phy_id = PHY_ID_VSC8574,
+ .name = "Vitesse VSC8574",
+ .phy_id_mask = 0x000ffff0,
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = &vsc824x_config_init,
+ .config_aneg = &vsc82x4_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &vsc824x_ack_interrupt,
+ .config_intr = &vsc82xx_config_intr,
+ .driver = { .owner = THIS_MODULE,},
+}, {
+ .phy_id = PHY_ID_VSC8662,
+ .name = "Vitesse VSC8662",
+ .phy_id_mask = 0x000ffff0,
+ .features = PHY_GBIT_FEATURES,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = &vsc824x_config_init,
+ .config_aneg = &vsc82x4_config_aneg,
+ .read_status = &genphy_read_status,
+ .ack_interrupt = &vsc824x_ack_interrupt,
+ .config_intr = &vsc82xx_config_intr,
+ .driver = { .owner = THIS_MODULE,},
+}, {
/* Vitesse 8221 */
.phy_id = PHY_ID_VSC8221,
.phy_id_mask = 0x000ffff0,
@@ -207,7 +327,11 @@ module_init(vsc82xx_init);
module_exit(vsc82xx_exit);
static struct mdio_device_id __maybe_unused vitesse_tbl[] = {
+ { PHY_ID_VSC8234, 0x000ffff0 },
{ PHY_ID_VSC8244, 0x000fffc0 },
+ { PHY_ID_VSC8514, 0x000ffff0 },
+ { PHY_ID_VSC8574, 0x000ffff0 },
+ { PHY_ID_VSC8662, 0x000ffff0 },
{ PHY_ID_VSC8221, 0x000ffff0 },
{ PHY_ID_VSC8211, 0x000ffff0 },
{ }
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 72ff14b..936f091 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -53,6 +53,9 @@
#include <linux/nsproxy.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
+#ifdef CONFIG_AS_FASTPATH
+#include <linux/if_pppox.h>
+#endif
#define PPP_VERSION "2.4.2"
@@ -1624,6 +1627,31 @@ ppp_do_recv(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
ppp_recv_unlock(ppp);
}
+#ifdef CONFIG_AS_FASTPATH
+struct net_device *
+ppp_get_parent_dev(struct net_device *dev, __be16 *sessid)
+{
+ struct ppp *ppp = netdev_priv(dev);
+ struct channel *pch;
+ struct list_head *list;
+ struct sock *sk;
+ struct pppox_sock *po;
+
+ list = &ppp->channels;
+ if (list_empty(list))
+ return NULL;
+
+ list = list->next;
+ pch = list_entry(list, struct channel, clist);
+ sk = pch->chan->private;
+ po = pppox_sk(sk);
+
+ *sessid = po->num;
+ return po->pppoe_dev;
+}
+EXPORT_SYMBOL(ppp_get_parent_dev);
+#endif
+
void
ppp_input(struct ppp_channel *chan, struct sk_buff *skb)
{
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index 94e2349..0288bdb 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -280,6 +280,16 @@ config DSCC4
To compile this driver as a module, choose M here: the
module will be called dscc4.
+config FSL_UCC_HDLC
+ tristate "freescale QUICC Engine HDLC support"
+ depends on HDLC
+ help
+ Driver for freescale QUICC Engine HDLC controller. The driver
+ support HDLC run on NMSI and TDM mode.
+
+ To compile this driver as a module, choose M here: the
+ module will be called fsl_ucc_hdlc.
+
config DSCC4_PCISYNC
bool "Etinc PCISYNC features"
depends on DSCC4
diff --git a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile
index c135ef4..25fec40 100644
--- a/drivers/net/wan/Makefile
+++ b/drivers/net/wan/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_WANXL) += wanxl.o
obj-$(CONFIG_PCI200SYN) += pci200syn.o
obj-$(CONFIG_PC300TOO) += pc300too.o
obj-$(CONFIG_IXP4XX_HSS) += ixp4xx_hss.o
+obj-$(CONFIG_FSL_UCC_HDLC) += fsl_ucc_hdlc.o
clean-files := wanxlfw.inc
$(obj)/wanxl.o: $(obj)/wanxlfw.inc
diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c
new file mode 100644
index 0000000..0c8cac6
--- /dev/null
+++ b/drivers/net/wan/fsl_ucc_hdlc.c
@@ -0,0 +1,1404 @@
+/* Freescale QUICC Engine HDLC Device Driver
+ *
+ * Copyright 2014 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/hdlc.h>
+#include <linux/io.h>
+#include <linux/tdm.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/dma-mapping.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <sysdev/fsl_soc.h>
+#include <linux/slab.h>
+#include "fsl_ucc_hdlc.h"
+
+#define DRV_DESC "Freescale QE UCC HDLC Driver"
+#define DRV_NAME "ucc_hdlc"
+
+#undef DEBUG
+
+static struct ucc_hdlc_info uhdlc_primary_info = {
+ .uf_info = {
+ .tsa = 0,
+ .cdp = 0,
+ .cds = 1,
+ .ctsp = 0,
+ .ctss = 1,
+ .revd = 0,
+ .urfs = 256,
+ .utfs = 256,
+ .urfet = 128,
+ .urfset = 192,
+ .utfet = 128,
+ .utftt = 0x40,
+ .ufpt = 256,
+ .mode = UCC_FAST_PROTOCOL_MODE_HDLC,
+ .ttx_trx = UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_NORMAL,
+ .tenc = UCC_FAST_TX_ENCODING_NRZ,
+ .renc = UCC_FAST_RX_ENCODING_NRZ,
+ .tcrc = UCC_FAST_16_BIT_CRC,
+ .synl = UCC_FAST_SYNC_LEN_NOT_USED,
+ },
+
+ .si_info = {
+ .simr_rfsd = 1, /* TDM card need 1 bit delay */
+ .simr_tfsd = 0,
+ .simr_crt = 0,
+ .simr_sl = 0,
+ .simr_ce = 1,
+ .simr_fe = 1,
+ .simr_gm = 0,
+ },
+};
+
+static struct ucc_hdlc_info uhdlc_info[MAX_HDLC_NUM];
+static int siram_init_flag;
+
+
+#ifdef DEBUG
+static void dump_siram(struct ucc_hdlc_private *priv)
+{
+ int i;
+ u16 *siram = priv->siram;
+
+ dev_info(priv->dev, "Dump the SI RX RAM\n");
+ for (i = 0; i < priv->num_of_ts; i++) {
+ pr_info("%04x ", siram[priv->siram_entry_id * 32 + i]);
+ if ((i + 1) % 4)
+ pr_info("\n");
+ }
+
+ dev_info(priv->dev, "Dump the SI TX RAM\n");
+ for (i = 0; i < priv->num_of_ts; i++) {
+ pr_info("%04x ", siram[priv->siram_entry_id * 32 + 0x200 + i]);
+ if ((i + 1) % 4)
+ pr_info("\n");
+ }
+}
+
+static void mem_disp(u8 *addr, int size)
+{
+ void *i;
+ int size16_aling = (size >> 4) << 4;
+ int size4_aling = (size >> 2) << 2;
+ int not_align = 0;
+ if (size % 16)
+ not_align = 1;
+
+ for (i = addr; i < addr + size16_aling; i += 16) {
+ u32 *i32 = i;
+
+ pr_info("0x%08p: %08x %08x %08x %08x\r\n",
+ i32, i32[0], i32[1], i32[2], i32[3]);
+ }
+
+ if (not_align == 1)
+ pr_info("0x%08p: ", i);
+ for (; i < addr + size4_aling; i += 4)
+ pr_info("%08x ", *((u32 *) (i)));
+ for (; i < addr + size; i++)
+ pr_info("%02x", *((u8 *) (i)));
+ if (not_align == 1)
+ pr_info("\r\n");
+}
+
+static void dump_ucc(struct ucc_hdlc_private *priv)
+{
+ struct ucc_hdlc_param *ucc_pram;
+ ucc_pram = priv->ucc_pram;
+
+ dev_info(priv->dev, "DumpiniCC %d Registers\n",
+ priv->uh_info->uf_info.ucc_num);
+ ucc_fast_dump_regs(priv->uccf);
+ dev_info(priv->dev, "Dumping UCC %d Parameter RAM\n",
+ priv->uh_info->uf_info.ucc_num);
+ dev_info(priv->dev, "rbase = 0x%x\n", in_be32(&ucc_pram->rbase));
+ dev_info(priv->dev, "rbptr = 0x%x\n", in_be32(&ucc_pram->rbptr));
+ dev_info(priv->dev, "mrblr = 0x%x\n", in_be16(&ucc_pram->mrblr));
+ dev_info(priv->dev, "rbdlen = 0x%x\n", in_be16(&ucc_pram->rbdlen));
+ dev_info(priv->dev, "rbdstat = 0x%x\n", in_be16(&ucc_pram->rbdstat));
+ dev_info(priv->dev, "rstate = 0x%x\n", in_be32(&ucc_pram->rstate));
+ dev_info(priv->dev, "rdptr = 0x%x\n", in_be32(&ucc_pram->rdptr));
+ dev_info(priv->dev, "riptr = 0x%x\n", in_be16(&ucc_pram->riptr));
+ dev_info(priv->dev, "tbase = 0x%x\n", in_be32(&ucc_pram->tbase));
+ dev_info(priv->dev, "tbptr = 0x%x\n", in_be32(&ucc_pram->tbptr));
+ dev_info(priv->dev, "tbdlen = 0x%x\n", in_be16(&ucc_pram->tbdlen));
+ dev_info(priv->dev, "tbdstat = 0x%x\n", in_be16(&ucc_pram->tbdstat));
+ dev_info(priv->dev, "tstate = 0x%x\n", in_be32(&ucc_pram->tstate));
+ dev_info(priv->dev, "tdptr = 0x%x\n", in_be32(&ucc_pram->tdptr));
+ dev_info(priv->dev, "tiptr = 0x%x\n", in_be16(&ucc_pram->tiptr));
+ dev_info(priv->dev, "rcrc = 0x%x\n", in_be32(&ucc_pram->rcrc));
+ dev_info(priv->dev, "tcrc = 0x%x\n", in_be32(&ucc_pram->tcrc));
+ dev_info(priv->dev, "c_mask = 0x%x\n", in_be32(&ucc_pram->c_mask));
+ dev_info(priv->dev, "c_pers = 0x%x\n", in_be32(&ucc_pram->c_pres));
+ dev_info(priv->dev, "disfc = 0x%x\n", in_be16(&ucc_pram->disfc));
+ dev_info(priv->dev, "crcec = 0x%x\n", in_be16(&ucc_pram->crcec));
+}
+
+static void dump_bds(struct ucc_hdlc_private *priv)
+{
+ int length;
+
+ if (priv->tx_bd_base) {
+ length = sizeof(struct qe_bd) * NUM_OF_BUF;
+ dev_info(priv->dev, " Dump tx BDs\n");
+ mem_disp((u8 *)priv->tx_bd_base, length);
+ }
+
+ if (priv->rx_bd_base) {
+ length = sizeof(struct qe_bd) * NUM_OF_BUF;
+ dev_info(priv->dev, " Dump rx BDs\n");
+ mem_disp((u8 *)priv->rx_bd_base, length);
+ }
+
+}
+
+static void dump_priv(struct ucc_hdlc_private *priv)
+{
+ dev_info(priv->dev, "uh_info = 0x%x\n", (u32)priv->uh_info);
+ dev_info(priv->dev, "uccf = 0x%x\n", (u32)priv->uccf);
+ dev_info(priv->dev, "uf_regs = 0x%x\n", (u32)priv->uf_regs);
+ dev_info(priv->dev, "si_regs = 0x%x\n", (u32)priv->si_regs);
+ dev_info(priv->dev, "ucc_pram = 0x%x\n", (u32)priv->ucc_pram);
+ dev_info(priv->dev, "tdm_port = 0x%x\n", (u32)priv->tdm_port);
+ dev_info(priv->dev, "siram_entry_id = 0x%x\n", priv->siram_entry_id);
+ dev_info(priv->dev, "siram = 0x%x\n", (u32)priv->siram);
+ dev_info(priv->dev, "tdm_mode = 0x%x\n", (u32)priv->tdm_mode);
+ dev_info(priv->dev, "tdm_framer_type; = 0x%x\n",
+ (u32)priv->tdm_framer_type);
+ dev_info(priv->dev, "rx_buffer; = 0x%x\n", (u32)priv->rx_buffer);
+ dev_info(priv->dev, "tx_buffer; = 0x%x\n", (u32)priv->tx_buffer);
+ dev_info(priv->dev, "dma_rx_addr; = 0x%x\n", (u32)priv->dma_rx_addr);
+ dev_info(priv->dev, "tx_bd; = 0x%x\n", (u32)priv->tx_bd_base);
+ dev_info(priv->dev, "rx_bd; = 0x%x\n", (u32)priv->rx_bd_base);
+ dev_info(priv->dev, "phase_rx = 0x%x\n", (u32)priv->phase_rx);
+ dev_info(priv->dev, "phase_tx = 0x%x\n", (u32)priv->phase_tx);
+ dev_info(priv->dev, "ucc_pram_offset = 0x%x\n", priv->ucc_pram_offset);
+
+}
+
+#endif /* DEBUG */
+
+static void init_si(struct ucc_hdlc_private *priv)
+{
+ struct si1 __iomem *si_regs;
+ u16 __iomem *siram;
+ u16 siram_entry_valid;
+ u16 siram_entry_closed;
+ u16 ucc_num;
+ u8 csel;
+ u16 sixmr;
+ u16 tdm_port;
+ u32 siram_entry_id;
+ u32 mask;
+ int i;
+
+ si_regs = priv->si_regs;
+ siram = priv->siram;
+ ucc_num = priv->uh_info->uf_info.ucc_num;
+ tdm_port = priv->tdm_port;
+ siram_entry_id = priv->siram_entry_id;
+
+ if (priv->tdm_framer_type == TDM_FRAMER_T1)
+ priv->num_of_ts = 24;
+ if (priv->tdm_framer_type == TDM_FRAMER_E1)
+ priv->num_of_ts = 32;
+
+ /* set siram table */
+ csel = (ucc_num < 4) ? ucc_num + 9 : ucc_num - 3;
+
+ siram_entry_valid = SIR_CSEL(csel) | SIR_BYTE | SIR_CNT(0);
+ siram_entry_closed = SIR_IDLE | SIR_BYTE | SIR_CNT(0);
+
+ for (i = 0; i < priv->num_of_ts; i++) {
+ mask = 0x01 << i;
+
+ if (priv->tx_ts_mask & mask)
+ out_be16(&siram[siram_entry_id * 32 + i],
+ siram_entry_valid);
+ else
+ out_be16(&siram[siram_entry_id * 32 + i],
+ siram_entry_closed);
+
+ if (priv->rx_ts_mask & mask)
+ out_be16(&siram[siram_entry_id * 32 + 0x200 + i],
+ siram_entry_valid);
+ else
+ out_be16(&siram[siram_entry_id * 32 + 0x200 + i],
+ siram_entry_closed);
+ }
+
+ setbits16(&siram[(siram_entry_id * 32) + (priv->num_of_ts - 1)],
+ SIR_LAST);
+ setbits16(&siram[(siram_entry_id * 32) + 0x200 + (priv->num_of_ts - 1)],
+ SIR_LAST);
+
+ /* Set SIxMR register */
+ sixmr = SIMR_SAD(siram_entry_id);
+
+ sixmr &= ~SIMR_SDM_MASK;
+
+ if (priv->tdm_mode == TDM_INTERNAL_LOOPBACK)
+ sixmr |= SIMR_SDM_INTERNAL_LOOPBACK;
+ else
+ sixmr |= SIMR_SDM_NORMAL;
+
+ sixmr |= SIMR_RFSD(priv->uh_info->si_info.simr_rfsd) |
+ SIMR_TFSD(priv->uh_info->si_info.simr_tfsd);
+
+ if (priv->uh_info->si_info.simr_crt)
+ sixmr |= SIMR_CRT;
+ if (priv->uh_info->si_info.simr_sl)
+ sixmr |= SIMR_SL;
+ if (priv->uh_info->si_info.simr_ce)
+ sixmr |= SIMR_CE;
+ if (priv->uh_info->si_info.simr_fe)
+ sixmr |= SIMR_FE;
+ if (priv->uh_info->si_info.simr_gm)
+ sixmr |= SIMR_GM;
+
+ switch (tdm_port) {
+ case 0:
+ out_be16(&si_regs->sixmr1[0], sixmr);
+ break;
+ case 1:
+ out_be16(&si_regs->sixmr1[1], sixmr);
+ break;
+ case 2:
+ out_be16(&si_regs->sixmr1[2], sixmr);
+ break;
+ case 3:
+ out_be16(&si_regs->sixmr1[3], sixmr);
+ break;
+ default:
+ dev_err(priv->dev, "can not find tdm sixmr reg\n");
+ break;
+ }
+
+#ifdef DEBUG
+ dump_siram(priv);
+#endif
+
+}
+static int uhdlc_init(struct ucc_hdlc_private *priv)
+{
+ struct ucc_hdlc_info *uh_info;
+ struct ucc_fast_info *uf_info;
+ u32 cecr_subblock;
+ u32 bd_status;
+ int ret, i;
+ void *bd_buffer;
+ dma_addr_t bd_dma_addr;
+ u32 riptr;
+ u32 tiptr;
+ u32 gumr;
+
+ uh_info = priv->uh_info;
+ uf_info = &uh_info->uf_info;
+
+ if (priv->tsa) {
+ uf_info->tsa = 1;
+ uf_info->ctsp = 1;
+ }
+ uf_info->uccm_mask = (u32)((UCC_HDLC_UCCE_RXB | UCC_HDLC_UCCE_RXF |
+ UCC_HDLC_UCCE_TXB) << 16);
+
+ if (ucc_fast_init(uf_info, &priv->uccf)) {
+ dev_err(priv->dev, "Failed to init uccf.");
+ return -ENOMEM;
+ }
+
+ priv->uf_regs = priv->uccf->uf_regs;
+ ucc_fast_disable(priv->uccf, COMM_DIR_RX | COMM_DIR_TX);
+
+ /* Loopback mode */
+ if (priv->loopback) {
+ gumr = in_be32(&priv->uf_regs->gumr);
+ gumr |= (0x40000000 | UCC_FAST_GUMR_CDS | UCC_FAST_GUMR_TCI);
+ gumr &= ~(UCC_FAST_GUMR_CTSP | UCC_FAST_GUMR_RSYN);
+ out_be32(&priv->uf_regs->gumr, gumr);
+ }
+
+ /* Initialize SI */
+ if (priv->tsa)
+ init_si(priv);
+
+ /* Write to QE CECR, UCCx channel to Stop Transmission */
+ cecr_subblock = ucc_fast_get_qe_cr_subblock(uf_info->ucc_num);
+ ret = qe_issue_cmd(QE_STOP_TX, cecr_subblock,
+ (u8) QE_CR_PROTOCOL_UNSPECIFIED, 0);
+
+ /* Set UPSMR normal mode (need fixed)*/
+ out_be32(&priv->uf_regs->upsmr, 0);
+
+ priv->rx_ring_size = RX_BD_RING_LEN;
+ priv->tx_ring_size = TX_BD_RING_LEN;
+ /* Alloc Rx BD */
+ priv->rx_bd_base = dma_alloc_coherent(priv->dev,
+ RX_BD_RING_LEN * sizeof(struct qe_bd),
+ &priv->dma_rx_bd, GFP_KERNEL);
+
+ if (IS_ERR_VALUE((unsigned long)priv->rx_bd_base)) {
+ dev_err(priv->dev, "Cannot allocate MURAM memory for RxBDs\n");
+ ret = -ENOMEM;
+ goto rxbd_alloc_error;
+ }
+
+ /* Alloc Tx BD */
+ priv->tx_bd_base = dma_alloc_coherent(priv->dev,
+ TX_BD_RING_LEN * sizeof(struct qe_bd),
+ &priv->dma_tx_bd, GFP_KERNEL);
+
+ if (IS_ERR_VALUE((unsigned long)priv->tx_bd_base)) {
+ dev_err(priv->dev, "Cannot allocate MURAM memory for TxBDs\n");
+ ret = -ENOMEM;
+ goto txbd_alloc_error;
+ }
+
+ /* Alloc parameter ram for ucc hdlc */
+ priv->ucc_pram_offset = qe_muram_alloc(sizeof(priv->ucc_pram),
+ ALIGNMENT_OF_UCC_HDLC_PRAM);
+
+ if (IS_ERR_VALUE(priv->ucc_pram_offset)) {
+ dev_err(priv->dev, "Can not allocate MURAM for hdlc prameter.\n");
+ ret = -ENOMEM;
+ goto pram_alloc_error;
+ }
+
+ priv->tx_skbuff = kmalloc_array(priv->tx_ring_size,
+ sizeof(*priv->tx_skbuff), GFP_KERNEL);
+ if (!priv->tx_skbuff)
+ goto pram_alloc_error;
+ for (i = 0; i < priv->tx_ring_size; i++)
+ priv->tx_skbuff[i] = NULL;
+
+ priv->skb_curtx = 0;
+ priv->skb_dirtytx = 0;
+ priv->curtx_bd = priv->tx_bd_base;
+ priv->dirty_tx = priv->tx_bd_base;
+ priv->currx_bd = priv->rx_bd_base;
+ priv->currx_bdnum = 0;
+
+ /* init parameter base */
+ cecr_subblock = ucc_fast_get_qe_cr_subblock(uf_info->ucc_num);
+ ret = qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, cecr_subblock,
+ QE_CR_PROTOCOL_UNSPECIFIED, priv->ucc_pram_offset);
+
+ priv->ucc_pram = (struct ucc_hdlc_param __iomem *)
+ qe_muram_addr(priv->ucc_pram_offset);
+
+ /* Zero out parameter ram */
+ memset_io(priv->ucc_pram, 0, sizeof(struct ucc_hdlc_param));
+
+ /* Alloc riptr, tiptr */
+ riptr = qe_muram_alloc(32, 32);
+ if (IS_ERR_VALUE(riptr)) {
+ dev_err(priv->dev, "Cannot allocate MURAM mem for Receive internal temp data pointer\n");
+ ret = -ENOMEM;
+ goto riptr_alloc_error;
+ }
+
+ tiptr = qe_muram_alloc(32, 32);
+ if (IS_ERR_VALUE(tiptr)) {
+ dev_err(priv->dev, "Cannot allocate MURAM mem for transmit internal temp data pointer\n");
+ ret = -ENOMEM;
+ goto tiptr_alloc_error;
+ }
+
+ /* Set RIPTR, TIPTR */
+ out_be16(&priv->ucc_pram->riptr, (u16)riptr);
+ out_be16(&priv->ucc_pram->tiptr, (u16)tiptr);
+
+ /* Set MRBLR */
+ out_be16(&priv->ucc_pram->mrblr, (u16)MAX_RX_BUF_LENGTH);
+
+ /* Set RBASE, TBASE */
+ out_be32(&priv->ucc_pram->rbase, (u32)priv->dma_rx_bd);
+ out_be32(&priv->ucc_pram->tbase, (u32)priv->dma_tx_bd);
+
+ /* Set RSTATE, TSTATE */
+ out_be32(&priv->ucc_pram->rstate, 0x30000000);
+ out_be32(&priv->ucc_pram->tstate, 0x30000000);
+
+ /* Set C_MASK, C_PRES for 16bit CRC */
+ out_be32(&priv->ucc_pram->c_mask, 0x0000F0B8);
+ out_be32(&priv->ucc_pram->c_pres, 0x0000FFFF);
+
+ out_be16(&priv->ucc_pram->mflr, MAX_RX_BUF_LENGTH + 8);
+ out_be16(&priv->ucc_pram->rfthr, 1);
+ out_be16(&priv->ucc_pram->rfcnt, 1);
+ out_be16(&priv->ucc_pram->hmask, DEFAULT_ADDR_MASK);
+ out_be16(&priv->ucc_pram->haddr2, DEFAULT_BROAD_ADDR);
+ out_be16(&priv->ucc_pram->haddr1, DEFAULT_HDLC_ADDR);
+ out_be16(&priv->ucc_pram->haddr3, DEFAULT_HDLC_ADDR);
+ out_be16(&priv->ucc_pram->haddr4, DEFAULT_HDLC_ADDR);
+
+ /* Get BD buffer */
+ bd_buffer = dma_alloc_coherent(priv->dev,
+ RX_BD_RING_LEN * MAX_RX_BUF_LENGTH,
+ &bd_dma_addr, GFP_KERNEL);
+
+ if (!bd_buffer) {
+ dev_err(priv->dev, "Could not allocate buffer descriptors\n");
+ return -ENOMEM;
+ }
+
+ memset(bd_buffer, 0, RX_BD_RING_LEN * MAX_RX_BUF_LENGTH);
+
+ priv->rx_buffer = bd_buffer;
+
+ priv->dma_rx_addr = bd_dma_addr;
+
+ for (i = 0; i < RX_BD_RING_LEN; i++) {
+ if (i < (RX_BD_RING_LEN - 1))
+ bd_status = R_E | R_I;
+ else
+ bd_status = R_E | R_I | R_W;
+
+ out_be32((u32 *)(priv->rx_bd_base + i), bd_status);
+ out_be32(&priv->rx_bd_base[i].buf, priv->dma_rx_addr
+ + i * MAX_RX_BUF_LENGTH);
+ }
+
+ for (i = 0; i < TX_BD_RING_LEN; i++) {
+ if (i < (TX_BD_RING_LEN - 1))
+ bd_status = T_I | T_TC;
+ else
+ bd_status = T_I | T_TC | T_W;
+
+ out_be32((u32 *)(priv->tx_bd_base + i), bd_status);
+ }
+
+ return 0;
+
+tiptr_alloc_error:
+ qe_muram_free(riptr);
+riptr_alloc_error:
+ qe_muram_free(priv->ucc_pram_offset);
+pram_alloc_error:
+ dma_free_coherent(priv->dev,
+ TX_BD_RING_LEN * sizeof(struct qe_bd),
+ priv->tx_bd_base, priv->dma_tx_bd);
+txbd_alloc_error:
+ dma_free_coherent(priv->dev,
+ RX_BD_RING_LEN * sizeof(struct qe_bd),
+ priv->rx_bd_base, priv->dma_rx_bd);
+rxbd_alloc_error:
+ ucc_fast_free(priv->uccf);
+
+ return ret;
+}
+
+static netdev_tx_t ucc_hdlc_tx(struct sk_buff *skb, struct net_device *dev)
+{
+ hdlc_device *hdlc = dev_to_hdlc(dev);
+ struct ucc_hdlc_private *priv = (struct ucc_hdlc_private *)hdlc->priv;
+ struct qe_bd __iomem *bd;
+ u32 bd_status;
+ u8 *send_buf;
+ int i;
+ u32 *hdlc_head, tmp_head;
+
+ if (skb_headroom(skb) < HDLC_HEAD_LEN) {
+ dev->stats.tx_dropped++;
+ dev_kfree_skb(skb);
+ netdev_err(dev, "No enough space for hdlc head\n");
+ return -ENOMEM;
+ }
+ skb_push(skb, HDLC_HEAD_LEN);
+
+ hdlc_head = (u32 *)skb->data;
+ tmp_head = *hdlc_head;
+ tmp_head = (tmp_head & HDLC_HEAD_MASK) | DEFAULT_HDLC_HEAD;
+ *hdlc_head = tmp_head;
+
+ dev->stats.tx_bytes += skb->len;
+
+ send_buf = (u8 *)skb->data;
+
+ if (priv->loopback) {
+ pr_info("\nTransmitted data:\n");
+ for (i = 0; (i < 16); i++)
+ pr_info("%x ", send_buf[i]);
+ }
+
+ /* Start from the next BD that should be filled */
+ bd = priv->curtx_bd;
+ bd_status = in_be32((u32 __iomem *)bd);
+ /* Save the skb pointer so we can free it later */
+ priv->tx_skbuff[priv->skb_curtx] = skb;
+
+
+ /* Update the current skb pointer (wrapping if this was the last) */
+ priv->skb_curtx =
+ (priv->skb_curtx + 1) & TX_RING_MOD_MASK(TX_BD_RING_LEN);
+ /* set up the buffer descriptor */
+ out_be32(&((struct qe_bd __iomem *)bd)->buf,
+ dma_map_single(priv->dev, skb->data,
+ skb->len, DMA_TO_DEVICE));
+
+ bd_status = (bd_status & T_W) | T_R | T_I | T_L | T_TC | skb->len;
+
+ /* set bd status and length */
+ out_be32((u32 __iomem *)bd, bd_status);
+
+ /* Move to next BD in the ring */
+ if (!(bd_status & T_W))
+ bd += 1;
+ else
+ bd = priv->tx_bd_base;
+ priv->curtx_bd = bd;
+
+ return NETDEV_TX_OK;
+}
+
+static int hdlc_tx_done(struct ucc_hdlc_private *priv)
+{
+ /* Start from the next BD that should be filled */
+ struct net_device *dev = priv->ndev;
+ struct qe_bd *bd; /* BD pointer */
+ u32 bd_status;
+
+ bd = priv->dirty_tx;
+ bd_status = in_be32((u32 __iomem *)bd);
+
+ /* Normal processing. */
+ while ((bd_status & T_R) == 0) {
+ struct sk_buff *skb;
+
+ /* BD contains already transmitted buffer. */
+ /* Handle the transmitted buffer and release */
+ /* the BD to be used with the current frame */
+
+ skb = priv->tx_skbuff[priv->skb_dirtytx];
+ if (!skb)
+ break;
+
+ dev->stats.tx_packets++;
+ dma_unmap_single(priv->dev,
+ in_be32(&((struct qe_bd __iomem *)bd)->buf),
+ skb->len, DMA_TO_DEVICE);
+ dev_kfree_skb_irq(skb);
+
+ priv->tx_skbuff[priv->skb_dirtytx] = NULL;
+ priv->skb_dirtytx =
+ (priv->skb_dirtytx +
+ 1) & TX_RING_MOD_MASK(TX_BD_RING_LEN);
+
+ /* We freed a buffer, so now we can restart transmission */
+ if (netif_queue_stopped(dev))
+ netif_wake_queue(dev);
+
+ /* Advance the confirmation BD pointer */
+ if (!(bd_status & T_W))
+ bd += 1;
+ else
+ bd = priv->tx_bd_base;
+ bd_status = in_be32((u32 __iomem *)bd);
+ }
+ priv->dirty_tx = bd;
+
+ return 0;
+}
+
+static int hdlc_rx_done(struct ucc_hdlc_private *priv, int rx_work_limit)
+{
+ struct net_device *dev = priv->ndev;
+ struct sk_buff *skb;
+ hdlc_device *hdlc = dev_to_hdlc(dev);
+ struct qe_bd *bd;
+ u32 bd_status;
+ u16 length, howmany = 0;
+ u8 *bdbuffer;
+ int i;
+
+ bd = priv->currx_bd;
+ bd_status = in_be32((u32 __iomem *)bd);
+
+ /* while there are received buffers and BD is full (~R_E) */
+ while (!((bd_status & (R_E)) || (--rx_work_limit < 0))) {
+ bdbuffer = priv->rx_buffer +
+ (priv->currx_bdnum * MAX_RX_BUF_LENGTH);
+ length = (u16) (bd_status & BD_LENGTH_MASK);
+
+ if (priv->loopback) {
+ pr_info("\nReceived data:\n");
+ for (i = 0; (i < 16); i++)
+ pr_info("%x ", bdbuffer[i]);
+ }
+
+ bdbuffer += HDLC_HEAD_LEN;
+ length -= (HDLC_HEAD_LEN + HDLC_CRC_SIZE);
+ skb = dev_alloc_skb(length);
+ if (!skb) {
+ dev->stats.rx_dropped++;
+ return -ENOMEM;
+ }
+
+ skb_put(skb, length);
+ skb->len = length;
+ skb->dev = dev;
+ memcpy(skb->data, bdbuffer, length);
+
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += skb->len;
+ howmany++;
+ if (hdlc->proto)
+ skb->protocol = hdlc_type_trans(skb, dev);
+ else
+ skb->protocol = cpu_to_be16(ETH_P_IP);
+ netif_rx(skb);
+
+ /* update to point at the next bd */
+ if (bd_status & R_W)
+ bd = priv->rx_bd_base;
+ else
+ bd += 1;
+
+ if (priv->currx_bdnum < (RX_BD_RING_LEN - 1))
+ priv->currx_bdnum += 1;
+ else
+ priv->currx_bdnum = RX_BD_RING_LEN - 1;
+
+ bd_status = in_be32((u32 __iomem *)bd);
+ }
+
+ priv->currx_bd = bd;
+ return howmany;
+}
+
+static irqreturn_t ucc_hdlc_irq_handler(int irq, void *dev_id)
+{
+ struct ucc_hdlc_private *priv = (struct ucc_hdlc_private *)dev_id;
+ struct ucc_fast_private *uccf;
+ struct ucc_hdlc_info *uh_info;
+ u32 ucce;
+ u32 uccm;
+
+ uh_info = priv->uh_info;
+ uccf = priv->uccf;
+
+ ucce = in_be32(uccf->p_ucce);
+ uccm = in_be32(uccf->p_uccm);
+
+ if ((ucce >> 16) & (UCC_HDLC_UCCE_RXF | UCC_HDLC_UCCE_RXB))
+ hdlc_rx_done(priv, RX_CLEAN_MAX);
+
+ if ((ucce >> 16) & UCC_HDLC_UCCE_TXB)
+ hdlc_tx_done(priv);
+
+ out_be32(uccf->p_ucce, ucce);
+
+ return IRQ_HANDLED;
+}
+
+static int uhdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ const size_t size = sizeof(te1_settings);
+ te1_settings line;
+ struct ucc_hdlc_private *priv = netdev_priv(dev);
+
+ if (cmd != SIOCWANDEV)
+ return hdlc_ioctl(dev, ifr, cmd);
+
+ switch (ifr->ifr_settings.type) {
+ case IF_GET_IFACE:
+ ifr->ifr_settings.type = IF_IFACE_E1;
+ if (ifr->ifr_settings.size < size) {
+ ifr->ifr_settings.size = size; /* data size wanted */
+ return -ENOBUFS;
+ }
+ line.clock_type = priv->clocking;
+ line.clock_rate = 0;
+ line.loopback = 0;
+
+ if (copy_to_user(ifr->ifr_settings.ifs_ifsu.sync, &line, size))
+ return -EFAULT;
+ return 0;
+
+ default:
+ return hdlc_ioctl(dev, ifr, cmd);
+ }
+}
+
+static int uhdlc_open(struct net_device *dev)
+{
+ u32 cecr_subblock;
+ struct ucc_hdlc_private *priv = dev_to_hdlc(dev)->priv;
+
+ if (priv->hdlc_busy != 1) {
+ if (request_irq(priv->uh_info->uf_info.irq,
+ ucc_hdlc_irq_handler, 0,
+ "hdlc", (void *)priv)) {
+ dev_err(priv->dev, "request_irq for ucc hdlc failed\n");
+ return -ENODEV;
+ }
+ cecr_subblock = ucc_fast_get_qe_cr_subblock(
+ priv->uh_info->uf_info.ucc_num);
+
+ qe_issue_cmd(QE_INIT_TX_RX, cecr_subblock,
+ (u8) QE_CR_PROTOCOL_UNSPECIFIED, 0);
+
+ ucc_fast_enable(priv->uccf, COMM_DIR_RX | COMM_DIR_TX);
+
+ /* Enable the TDM port */
+ if (priv->tsa)
+ priv->si_regs->siglmr1_h |= (0x1 << priv->tdm_port);
+
+ priv->hdlc_busy = 1;
+ } else
+ dev_err(priv->dev, "HDLC IS RUNNING!\n");
+
+#ifdef DEBUG
+ dump_priv(priv);
+ dump_ucc(priv);
+ dump_bds(priv);
+#endif
+
+ return 0;
+}
+
+static void uhdlc_memclean(struct ucc_hdlc_private *priv)
+{
+ qe_muram_free(priv->ucc_pram->riptr);
+ qe_muram_free(priv->ucc_pram->tiptr);
+
+ if (priv->rx_bd_base) {
+ dma_free_coherent(priv->dev,
+ RX_BD_RING_LEN * sizeof(struct qe_bd),
+ priv->rx_bd_base, priv->dma_rx_bd);
+
+ priv->rx_bd_base = NULL;
+ priv->dma_rx_bd = 0;
+ }
+
+ if (priv->tx_bd_base) {
+ dma_free_coherent(priv->dev,
+ TX_BD_RING_LEN * sizeof(struct qe_bd),
+ priv->tx_bd_base, priv->dma_tx_bd);
+
+ priv->tx_bd_base = NULL;
+ priv->dma_tx_bd = 0;
+ }
+
+ if (priv->ucc_pram) {
+ qe_muram_free(priv->ucc_pram_offset);
+ priv->ucc_pram = NULL;
+ priv->ucc_pram_offset = 0;
+ }
+
+ if (priv->uf_regs) {
+ iounmap(priv->uf_regs);
+ priv->uf_regs = NULL;
+ }
+
+ if (priv->uccf) {
+ ucc_fast_free(priv->uccf);
+ priv->uccf = NULL;
+ }
+
+ if (priv->rx_buffer) {
+ dma_free_coherent(priv->dev,
+ 2 * NUM_OF_BUF * MAX_RX_BUF_LENGTH,
+ priv->rx_buffer, priv->dma_rx_addr);
+ priv->rx_buffer = NULL;
+ priv->dma_rx_addr = 0;
+ }
+}
+
+static int uhdlc_close(struct net_device *dev)
+{
+ struct ucc_hdlc_private *priv = dev_to_hdlc(dev)->priv;
+ u32 cecr_subblock;
+
+ cecr_subblock = ucc_fast_get_qe_cr_subblock(
+ priv->uh_info->uf_info.ucc_num);
+
+ qe_issue_cmd(QE_GRACEFUL_STOP_TX, cecr_subblock,
+ (u8) QE_CR_PROTOCOL_UNSPECIFIED, 0);
+ qe_issue_cmd(QE_CLOSE_RX_BD, cecr_subblock,
+ (u8) QE_CR_PROTOCOL_UNSPECIFIED, 0);
+
+ if (priv->tsa)
+ priv->si_regs->siglmr1_h &= ~(0x1 << priv->tdm_port);
+
+ ucc_fast_disable(priv->uccf, COMM_DIR_RX | COMM_DIR_TX);
+
+ free_irq(priv->uh_info->uf_info.irq, priv);
+ priv->hdlc_busy = 0;
+
+ return 0;
+}
+
+static enum tdm_mode_t set_tdm_mode(const char *tdm_mode_type)
+{
+ if (strcasecmp(tdm_mode_type, "internal-loopback") == 0)
+ return TDM_INTERNAL_LOOPBACK;
+ else
+ return TDM_NORMAL;
+}
+
+
+static enum tdm_framer_t set_tdm_framer(const char *tdm_framer_type)
+{
+ if (strcasecmp(tdm_framer_type, "e1") == 0)
+ return TDM_FRAMER_E1;
+ else
+ return TDM_FRAMER_T1;
+}
+
+static void set_si_param(struct ucc_hdlc_private *priv)
+{
+ struct si_mode_info *si_info = &priv->uh_info->si_info;
+
+ if (priv->tdm_mode == TDM_INTERNAL_LOOPBACK) {
+ si_info->simr_crt = 1;
+ si_info->simr_rfsd = 0;
+ }
+}
+
+static int of_parse_hdlc_tdm(struct device_node *np,
+ struct ucc_hdlc_private *priv, struct ucc_hdlc_info *uh_info)
+{
+ const unsigned int *prop;
+ const char *sprop;
+ int ret = 0;
+
+ sprop = of_get_property(np, "fsl,rx-sync-clock", NULL);
+ if (sprop) {
+ uh_info->uf_info.rx_sync = qe_clock_source(sprop);
+ if ((uh_info->uf_info.rx_sync < QE_CLK_NONE) ||
+ (uh_info->uf_info.rx_sync > QE_RSYNC_PIN)) {
+ dev_err(priv->dev, "Invalid rx-sync-clock property\n");
+ return -EINVAL;
+ }
+ } else {
+ dev_err(priv->dev, "Invalid rx-sync-clock property\n");
+ return -EINVAL;
+ }
+
+ sprop = of_get_property(np, "fsl,tx-sync-clock", NULL);
+ if (sprop) {
+ uh_info->uf_info.tx_sync = qe_clock_source(sprop);
+ if ((uh_info->uf_info.tx_sync < QE_CLK_NONE) ||
+ (uh_info->uf_info.tx_sync > QE_TSYNC_PIN)) {
+ dev_err(priv->dev, "Invalid tx-sync-clock property\n");
+ return -EINVAL;
+ }
+ } else {
+ dev_err(priv->dev, "Invalid tx-sync-clock property\n");
+ return -EINVAL;
+ }
+
+ prop = of_get_property(np, "fsl,tx-timeslot", NULL);
+ if (!prop) {
+ ret = -EINVAL;
+ dev_err(priv->dev, "Invalid tx-timeslot property\n");
+ return ret;
+ }
+ priv->tx_ts_mask = *prop;
+
+ prop = of_get_property(np, "fsl,rx-timeslot", NULL);
+ if (!prop) {
+ ret = -EINVAL;
+ dev_err(priv->dev, "Invalid rx-timeslot property\n");
+ return ret;
+ }
+ priv->rx_ts_mask = *prop;
+
+ prop = of_get_property(np, "fsl,tdm-id", NULL);
+ if (!prop) {
+ ret = -EINVAL;
+ dev_err(priv->dev, "No fsl,tdm-id property for this UCC\n");
+ return ret;
+ }
+ priv->tdm_port = *prop;
+ uh_info->uf_info.tdm_num = priv->tdm_port;
+
+ prop = of_get_property(np, "fsl,tdm-mode", NULL);
+ if (!prop) {
+ ret = -EINVAL;
+ dev_err(priv->dev, "No tdm-mode property for UCC\n");
+ return ret;
+ }
+ priv->tdm_mode = set_tdm_mode((const char *)prop);
+
+ prop = of_get_property(np, "fsl,tdm-framer-type", NULL);
+ if (!prop) {
+ ret = -EINVAL;
+ dev_err(priv->dev, "No tdm-framer-type property for UCC\n");
+ return ret;
+ }
+ priv->tdm_framer_type = set_tdm_framer((const char *)prop);
+
+ prop = of_get_property(np, "fsl,siram-entry-id", NULL);
+ if (!prop) {
+ ret = -EINVAL;
+ dev_err(priv->dev, "No siram entry id for UCC\n");
+ return ret;
+ }
+ priv->siram_entry_id = *(const u32 *)prop;
+
+ set_si_param(priv);
+
+ return ret;
+}
+
+static int ucc_hdlc_attach(struct net_device *dev, unsigned short encoding,
+ unsigned short parity)
+{
+ struct ucc_hdlc_private *priv = dev_to_hdlc(dev)->priv;
+
+ if (encoding != ENCODING_NRZ &&
+ encoding != ENCODING_NRZI)
+ return -EINVAL;
+
+ if (parity != PARITY_NONE &&
+ parity != PARITY_CRC32_PR1_CCITT &&
+ parity != PARITY_CRC16_PR1_CCITT)
+ return -EINVAL;
+
+ priv->encoding = encoding;
+ priv->parity = parity;
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static void store_clk_config(struct ucc_hdlc_private *priv)
+{
+ struct qe_mux *qe_mux_reg = &qe_immr->qmx;
+
+ /* store si clk */
+ priv->cmxsi1cr_h = in_be32(&qe_mux_reg->cmxsi1cr_h);
+ priv->cmxsi1cr_l = in_be32(&qe_mux_reg->cmxsi1cr_l);
+
+ /* store si sync */
+ priv->cmxsi1syr = in_be32(&qe_mux_reg->cmxsi1syr);
+
+ /* store ucc clk */
+ memcpy_fromio(priv->cmxucr, qe_mux_reg->cmxucr, 4 * sizeof(u32));
+}
+
+static void resume_clk_config(struct ucc_hdlc_private *priv)
+{
+ struct qe_mux *qe_mux_reg = &qe_immr->qmx;
+
+ memcpy_toio(qe_mux_reg->cmxucr, priv->cmxucr, 4 * sizeof(u32));
+
+ out_be32(&qe_mux_reg->cmxsi1cr_h, priv->cmxsi1cr_h);
+ out_be32(&qe_mux_reg->cmxsi1cr_l, priv->cmxsi1cr_l);
+
+ out_be32(&qe_mux_reg->cmxsi1syr, priv->cmxsi1syr);
+
+}
+
+static int uhdlc_suspend(struct device *dev)
+{
+ struct ucc_hdlc_private *priv = dev_get_drvdata(dev);
+ struct ucc_hdlc_info *uh_info;
+ struct ucc_fast __iomem *uf_regs;
+
+ if (!priv)
+ return -EINVAL;
+
+ uh_info = priv->uh_info;
+ uf_regs = priv->uf_regs;
+
+ /* backup gumr guemr*/
+ priv->gumr = in_be32(&uf_regs->gumr);
+ priv->guemr = in_8(&uf_regs->guemr);
+
+ priv->ucc_pram_bak = kmalloc(sizeof(struct ucc_hdlc_param),
+ GFP_KERNEL);
+ if (!priv->ucc_pram_bak)
+ return -ENOMEM;
+
+ /* backup HDLC parameter */
+ memcpy_fromio(priv->ucc_pram_bak, priv->ucc_pram,
+ sizeof(struct ucc_hdlc_param));
+
+ /* store the clk configuration */
+ store_clk_config(priv);
+
+ /* save power */
+ ucc_fast_disable(priv->uccf, COMM_DIR_RX | COMM_DIR_TX);
+
+ dev_dbg(dev, "ucc hdlc suspend\n");
+ return 0;
+}
+
+static int uhdlc_resume(struct device *dev)
+{
+ struct ucc_hdlc_private *priv = dev_get_drvdata(dev);
+ struct ucc_hdlc_info *uh_info;
+ struct ucc_fast __iomem *uf_regs;
+ struct ucc_fast_private *uccf;
+ struct ucc_fast_info *uf_info;
+ int ret, i;
+ u32 cecr_subblock, bd_status;
+
+ if (!priv)
+ return -EINVAL;
+
+ uh_info = priv->uh_info;
+ uf_info = &uh_info->uf_info;
+ uf_regs = priv->uf_regs;
+ uccf = priv->uccf;
+
+ /* restore gumr guemr */
+ out_8(&uf_regs->guemr, priv->guemr);
+ out_be32(&uf_regs->gumr, priv->gumr);
+
+ /* Set Virtual Fifo registers */
+ out_be16(&uf_regs->urfs, uf_info->urfs);
+ out_be16(&uf_regs->urfet, uf_info->urfet);
+ out_be16(&uf_regs->urfset, uf_info->urfset);
+ out_be16(&uf_regs->utfs, uf_info->utfs);
+ out_be16(&uf_regs->utfet, uf_info->utfet);
+ out_be16(&uf_regs->utftt, uf_info->utftt);
+ /* utfb, urfb are offsets from MURAM base */
+ out_be32(&uf_regs->utfb, uccf->ucc_fast_tx_virtual_fifo_base_offset);
+ out_be32(&uf_regs->urfb, uccf->ucc_fast_rx_virtual_fifo_base_offset);
+
+ /* Rx Tx and sync clock routing */
+ resume_clk_config(priv);
+
+ out_be32(&uf_regs->uccm, uf_info->uccm_mask);
+ out_be32(&uf_regs->ucce, 0xffffffff);
+
+ ucc_fast_disable(priv->uccf, COMM_DIR_RX | COMM_DIR_TX);
+
+ /* rebuild SIRAM */
+ if (priv->tsa)
+ init_si(priv);
+
+ /* Write to QE CECR, UCCx channel to Stop Transmission */
+ cecr_subblock = ucc_fast_get_qe_cr_subblock(uf_info->ucc_num);
+ ret = qe_issue_cmd(QE_STOP_TX, cecr_subblock,
+ (u8)QE_CR_PROTOCOL_UNSPECIFIED, 0);
+
+ /* Set UPSMR normal mode */
+ out_be32(&uf_regs->upsmr, 0);
+
+ /* init parameter base */
+ cecr_subblock = ucc_fast_get_qe_cr_subblock(uf_info->ucc_num);
+ ret = qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, cecr_subblock,
+ QE_CR_PROTOCOL_UNSPECIFIED, priv->ucc_pram_offset);
+
+ priv->ucc_pram = (struct ucc_hdlc_param __iomem *)
+ qe_muram_addr(priv->ucc_pram_offset);
+
+ /* restore ucc parameter */
+ memcpy_toio(priv->ucc_pram, priv->ucc_pram_bak,
+ sizeof(struct ucc_hdlc_param));
+ kfree(priv->ucc_pram_bak);
+
+ /* rebuild BD entry */
+ for (i = 0; i < RX_BD_RING_LEN; i++) {
+ if (i < (RX_BD_RING_LEN - 1))
+ bd_status = R_E | R_I;
+ else
+ bd_status = R_E | R_I | R_W;
+
+ out_be32((u32 *)(priv->rx_bd_base + i), bd_status);
+ out_be32(&priv->rx_bd_base[i].buf, priv->dma_rx_addr
+ + i * MAX_RX_BUF_LENGTH);
+ }
+
+ for (i = 0; i < TX_BD_RING_LEN; i++) {
+ if (i < (TX_BD_RING_LEN - 1))
+ bd_status = T_I | T_TC;
+ else
+ bd_status = T_I | T_TC | T_W;
+
+ out_be32((u32 *)(priv->tx_bd_base + i), bd_status);
+ }
+
+ /* if hdlc is busy enable TX and RX */
+ if (priv->hdlc_busy == 1) {
+ cecr_subblock = ucc_fast_get_qe_cr_subblock(
+ priv->uh_info->uf_info.ucc_num);
+
+ qe_issue_cmd(QE_INIT_TX_RX, cecr_subblock,
+ (u8)QE_CR_PROTOCOL_UNSPECIFIED, 0);
+
+ ucc_fast_enable(priv->uccf, COMM_DIR_RX | COMM_DIR_TX);
+
+ /* Enable the TDM port */
+ if (priv->tsa)
+ priv->si_regs->siglmr1_h |= (0x1 << priv->tdm_port);
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops uhdlc_pm_ops = {
+ .suspend = uhdlc_suspend,
+ .resume = uhdlc_resume,
+ .freeze = uhdlc_suspend,
+ .thaw = uhdlc_resume,
+};
+
+#define HDLC_PM_OPS (&uhdlc_pm_ops)
+
+#else
+
+#define HDLC_PM_OPS NULL
+
+#endif
+static const struct net_device_ops uhdlc_ops = {
+ .ndo_open = uhdlc_open,
+ .ndo_stop = uhdlc_close,
+ .ndo_change_mtu = hdlc_change_mtu,
+ .ndo_start_xmit = hdlc_start_xmit,
+ .ndo_do_ioctl = uhdlc_ioctl,
+};
+
+static int ucc_hdlc_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct ucc_hdlc_private *uhdlc_priv = NULL;
+ struct ucc_hdlc_info *uh_info;
+ struct resource res;
+ struct device_node *np2;
+ struct net_device *dev;
+ hdlc_device *hdlc;
+ int ucc_num;
+ const unsigned int *prop;
+ const char *sprop;
+ int ret;
+
+ prop = of_get_property(np, "cell-index", NULL);
+ if (!prop) {
+ dev_err(&pdev->dev, "Invalid ucc property\n");
+ return -ENODEV;
+ }
+
+ ucc_num = *prop - 1;
+ if ((ucc_num > 3) || (ucc_num < 0)) {
+ dev_err(&pdev->dev, ": Invalid UCC num\n");
+ return -EINVAL;
+ }
+
+ memcpy(&(uhdlc_info[ucc_num]), &uhdlc_primary_info,
+ sizeof(uhdlc_primary_info));
+
+ uh_info = &uhdlc_info[ucc_num];
+ uh_info->uf_info.ucc_num = ucc_num;
+
+ sprop = of_get_property(np, "rx-clock-name", NULL);
+ if (sprop) {
+ uh_info->uf_info.rx_clock = qe_clock_source(sprop);
+ if ((uh_info->uf_info.rx_clock < QE_CLK_NONE) ||
+ (uh_info->uf_info.rx_clock > QE_CLK24)) {
+ dev_err(&pdev->dev, "Invalid rx-clock-name property\n");
+ return -EINVAL;
+ }
+ } else {
+ dev_err(&pdev->dev, "Invalid rx-clock-name property\n");
+ return -EINVAL;
+ }
+
+ sprop = of_get_property(np, "tx-clock-name", NULL);
+ if (sprop) {
+ uh_info->uf_info.tx_clock = qe_clock_source(sprop);
+ if ((uh_info->uf_info.tx_clock < QE_CLK_NONE) ||
+ (uh_info->uf_info.tx_clock > QE_CLK24)) {
+ dev_err(&pdev->dev, "Invalid tx-clock-name property\n");
+ return -EINVAL;
+ }
+ } else {
+ dev_err(&pdev->dev, "Invalid tx-clock-name property\n");
+ return -EINVAL;
+ }
+
+ /* use the same clock when work in loopback */
+ if (uh_info->uf_info.rx_clock == uh_info->uf_info.tx_clock)
+ qe_setbrg(uh_info->uf_info.rx_clock, 20000000, 1);
+
+ ret = of_address_to_resource(np, 0, &res);
+ if (ret)
+ return -EINVAL;
+
+ uh_info->uf_info.regs = res.start;
+ uh_info->uf_info.irq = irq_of_parse_and_map(np, 0);
+
+ uhdlc_priv = kzalloc(sizeof(struct ucc_hdlc_private), GFP_KERNEL);
+ if (!uhdlc_priv) {
+ ret = -ENOMEM;
+ dev_err(&pdev->dev, "No mem to alloc hdlc private data\n");
+ goto err_alloc_priv;
+ }
+
+ dev_set_drvdata(&pdev->dev, uhdlc_priv);
+ uhdlc_priv->dev = &pdev->dev;
+ uhdlc_priv->uh_info = uh_info;
+
+ if (of_get_property(np, "fsl,tdm-interface", NULL))
+ uhdlc_priv->tsa = 1;
+
+ if (of_get_property(np, "fsl,inter-loopback", NULL))
+ uhdlc_priv->loopback = 1;
+
+ if (uhdlc_priv->tsa == 1) {
+ ret = of_parse_hdlc_tdm(np, uhdlc_priv, uh_info);
+ if (ret)
+ goto err_miss_tsa_property;
+ np2 = of_find_node_by_name(NULL, "si");
+ if (!np2) {
+ dev_err(uhdlc_priv->dev, "No si property\n");
+ ret = -EINVAL;
+ goto err_miss_tsa_property;
+ }
+ of_address_to_resource(np2, 0, &res);
+ uhdlc_priv->si_regs = ioremap(res.start,
+ res.end - res.start + 1);
+ of_node_put(np2);
+
+ np2 = of_find_node_by_name(NULL, "siram");
+ if (!np2) {
+ ret = -EINVAL;
+ dev_err(uhdlc_priv->dev, "No siramproperty\n");
+ goto err_miss_siram_property;
+ }
+ of_address_to_resource(np2, 0 , &res);
+ uhdlc_priv->siram = ioremap(res.start, res.end - res.start + 1);
+ of_node_put(np2);
+
+ if (siram_init_flag == 0) {
+ memset(uhdlc_priv->siram, 0, res.end - res.start + 1);
+ siram_init_flag = 1;
+ }
+ }
+
+
+ ret = uhdlc_init(uhdlc_priv);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to init uhdlc\n");
+ goto err_hdlc_init;
+ }
+
+ dev = alloc_hdlcdev(uhdlc_priv);
+ if (!dev) {
+ ret = -ENOMEM;
+ pr_err("ucc_hdlc: unable to allocate memory\n");
+ goto err_hdlc_init;
+ }
+
+ uhdlc_priv->ndev = dev;
+ hdlc = dev_to_hdlc(dev);
+ dev->tx_queue_len = 16;
+ dev->netdev_ops = &uhdlc_ops;
+ hdlc->attach = ucc_hdlc_attach;
+ hdlc->xmit = ucc_hdlc_tx;
+ if (register_hdlc_device(dev)) {
+ ret = -ENOBUFS;
+ pr_err("ucc_hdlc: unable to register hdlc device\n");
+ free_netdev(dev);
+ goto err_hdlc_init;
+ }
+
+#ifdef DEBUG
+ dump_priv(uhdlc_priv);
+ dump_ucc(uhdlc_priv);
+ dump_bds(uhdlc_priv);
+ if (uhdlc_priv->tsa)
+ mem_disp((u8 *)uhdlc_priv->si_regs, 0x20);
+#endif
+
+ return 0;
+
+err_hdlc_init:
+ if (uhdlc_priv->tsa) {
+ iounmap(uhdlc_priv->siram);
+ iounmap(uhdlc_priv->si_regs);
+ }
+err_miss_siram_property:
+ if (uhdlc_priv->tsa)
+ iounmap(uhdlc_priv->si_regs);
+err_miss_tsa_property:
+ kfree(uhdlc_priv);
+err_alloc_priv:
+ return ret;
+
+}
+
+static int ucc_hdlc_remove(struct platform_device *pdev)
+{
+ struct ucc_hdlc_private *priv = dev_get_drvdata(&pdev->dev);
+
+ uhdlc_memclean(priv);
+
+ if (priv->si_regs) {
+ iounmap(priv->si_regs);
+ priv->si_regs = NULL;
+ }
+
+ if (priv->siram) {
+ iounmap(priv->siram);
+ priv->siram = NULL;
+ }
+ kfree(priv);
+
+ dev_info(&pdev->dev, "UCC based hdlc module removed\n");
+
+ return 0;
+}
+
+static const struct of_device_id fsl_ucc_hdlc_of_match[] = {
+ {
+ .compatible = "fsl,ucc_hdlc",
+ },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, fsl_ucc_hdlc_of_match);
+
+static struct platform_driver ucc_hdlc_driver = {
+ .probe = ucc_hdlc_probe,
+ .remove = ucc_hdlc_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRV_NAME,
+ .pm = HDLC_PM_OPS,
+ .of_match_table = fsl_ucc_hdlc_of_match,
+ },
+};
+
+static int __init ucc_hdlc_init(void)
+{
+ return platform_driver_register(&ucc_hdlc_driver);
+}
+
+static void __exit ucc_hdlc_exit(void)
+{
+ platform_driver_unregister(&ucc_hdlc_driver);
+}
+
+module_init(ucc_hdlc_init);
+module_exit(ucc_hdlc_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Freescale Semiconductor Inc.");
+MODULE_DESCRIPTION("Driver For Freescale QE UCC HDLC controller");
+MODULE_VERSION("1.0");
diff --git a/drivers/net/wan/fsl_ucc_hdlc.h b/drivers/net/wan/fsl_ucc_hdlc.h
new file mode 100644
index 0000000..e0c8a4a
--- /dev/null
+++ b/drivers/net/wan/fsl_ucc_hdlc.h
@@ -0,0 +1,191 @@
+/* Freescale QUICC Engine HDLC Device Driver
+ *
+ * Copyright 2014 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef CONFIG_UCC_HDLC_H
+#define CONFIG_UCC_HDLC_H
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+
+#include <asm/immap_qe.h>
+#include <asm/qe.h>
+
+#include <asm/ucc.h>
+#include <asm/ucc_fast.h>
+
+/* SI RAM entries */
+#define SIR_LAST 0x0001
+#define SIR_BYTE 0x0002
+#define SIR_CNT(x) ((x) << 2)
+#define SIR_CSEL(x) ((x) << 5)
+#define SIR_SGS 0x0200
+#define SIR_SWTR 0x4000
+#define SIR_MCC 0x8000
+#define SIR_IDLE 0
+
+/* SIxMR fields */
+#define SIMR_SAD(x) ((x) << 12)
+#define SIMR_SDM_NORMAL 0x0000
+#define SIMR_SDM_INTERNAL_LOOPBACK 0x0800
+#define SIMR_SDM_MASK 0x0c00
+#define SIMR_CRT 0x0040
+#define SIMR_SL 0x0020
+#define SIMR_CE 0x0010
+#define SIMR_FE 0x0008
+#define SIMR_GM 0x0004
+#define SIMR_TFSD(n) (n)
+#define SIMR_RFSD(n) ((n) << 8)
+
+enum tdm_ts_t {
+ TDM_TX_TS,
+ TDM_RX_TS
+};
+
+
+enum tdm_framer_t {
+ TDM_FRAMER_T1,
+ TDM_FRAMER_E1
+};
+
+enum tdm_mode_t {
+ TDM_INTERNAL_LOOPBACK,
+ TDM_NORMAL
+};
+
+struct ucc_hdlc_param {
+ __be16 riptr;
+ __be16 tiptr;
+ __be16 res0;
+ __be16 mrblr;
+ __be32 rstate;
+ __be32 rbase;
+ __be16 rbdstat;
+ __be16 rbdlen;
+ __be32 rdptr;
+ __be32 tstate;
+ __be32 tbase;
+ __be16 tbdstat;
+ __be16 tbdlen;
+ __be32 tdptr;
+ __be32 rbptr;
+ __be32 tbptr;
+ __be32 rcrc;
+ __be32 res1;
+ __be32 tcrc;
+ __be32 res2;
+ __be32 res3;
+ __be32 c_mask;
+ __be32 c_pres;
+ __be16 disfc;
+ __be16 crcec;
+ __be16 abtsc;
+ __be16 nmarc;
+ __be32 max_cnt;
+ __be16 mflr;
+ __be16 rfthr;
+ __be16 rfcnt;
+ __be16 hmask;
+ __be16 haddr1;
+ __be16 haddr2;
+ __be16 haddr3;
+ __be16 haddr4;
+ __be16 ts_tmp;
+ __be16 tmp_mb;
+} __attribute__ ((__packed__));
+
+struct si_mode_info {
+ u8 simr_rfsd;
+ u8 simr_tfsd;
+ u8 simr_crt;
+ u8 simr_sl;
+ u8 simr_ce;
+ u8 simr_fe;
+ u8 simr_gm;
+};
+
+struct ucc_hdlc_info {
+ struct ucc_fast_info uf_info;
+ struct si_mode_info si_info;
+};
+
+struct ucc_hdlc_private {
+ struct ucc_hdlc_info *uh_info;
+ struct ucc_fast_private *uccf;
+ struct device *dev;
+ struct net_device *ndev;
+ struct ucc_fast __iomem *uf_regs; /* UCC Fast registers */
+ struct si1 __iomem *si_regs;
+ struct ucc_hdlc_param __iomem *ucc_pram;
+ u16 tsa;
+ u16 tdm_port; /* port for this tdm:TDMA,TDMB */
+ u32 siram_entry_id;
+ u16 __iomem *siram;
+ enum tdm_mode_t tdm_mode;
+ enum tdm_framer_t tdm_framer_type;
+ bool hdlc_busy;
+ u8 loopback;
+ u8 num_of_ts; /* the number of timeslots in this tdm frame */
+ u32 tx_ts_mask; /* tx time slot mask */
+ u32 rx_ts_mask; /* rx time slot mask */
+ u8 *rx_buffer; /* buffer used for Rx by the HDLC */
+ u8 *tx_buffer; /* buffer used for Tx by the HDLC */
+ dma_addr_t dma_rx_addr; /* dma mapped buffer for HDLC Rx */
+ dma_addr_t dma_tx_addr; /* dma mapped buffer for HDLC Tx */
+ struct qe_bd *tx_bd_base;
+ struct qe_bd *rx_bd_base;
+ struct qe_bd *curtx_bd;
+ struct qe_bd *currx_bd;
+ struct qe_bd *dirty_tx;
+ struct sk_buff **tx_skbuff;
+ struct sk_buff **rx_skbuff;
+ u16 skb_currx;
+ u16 skb_curtx;
+ u16 currx_bdnum;
+ unsigned short skb_dirtytx;
+ unsigned short tx_ring_size;
+ unsigned short rx_ring_size;
+ u32 ucc_pram_offset;
+ dma_addr_t dma_rx_bd;
+ dma_addr_t dma_tx_bd;
+
+ unsigned short encoding;
+ unsigned short parity;
+ u32 clocking;
+#ifdef CONFIG_PM
+ struct ucc_hdlc_param *ucc_pram_bak;
+ u32 gumr;
+ u8 guemr;
+ u32 cmxsi1cr_l, cmxsi1cr_h;
+ u32 cmxsi1syr;
+ u32 cmxucr[4];
+#endif
+};
+
+#define TX_BD_RING_LEN 0x10
+#define RX_BD_RING_LEN 0x20
+#define RX_CLEAN_MAX 0x10
+#define NUM_OF_BUF 4
+#define MAX_RX_BUF_LENGTH (48*0x20)
+#define ALIGNMENT_OF_UCC_HDLC_PRAM 64
+#define SI_BANK_SIZE 128
+#define MAX_HDLC_NUM 4
+#define BD_LEN_MASK 0xffff
+#define HDLC_HEAD_LEN 3
+#define HDLC_CRC_SIZE 2
+#define TX_RING_MOD_MASK(size) (size-1)
+#define RX_RING_MOD_MASK(size) (size-1)
+
+#define HDLC_HEAD_MASK 0x000000ff
+#define DEFAULT_HDLC_HEAD 0x68aa4400
+#define DEFAULT_ADDR_MASK 0xffff
+#define DEFAULT_HDLC_ADDR 0xaa68
+#define DEFAULT_BROAD_ADDR 0xffff
+
+#endif
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index d5a57a9..8fb13ba 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -247,3 +247,25 @@ struct phy_device *of_phy_connect_fixed_link(struct net_device *dev,
return IS_ERR(phy) ? NULL : phy;
}
EXPORT_SYMBOL(of_phy_connect_fixed_link);
+
+/**
+ * of_phy_attach - Attach to a PHY without starting the state machine
+ * @dev: pointer to net_device claiming the phy
+ * @phy_np: Node pointer for the PHY
+ * @flags: flags to pass to the PHY
+ * @iface: PHY data interface type
+ */
+struct phy_device *of_phy_attach(struct net_device *dev,
+ struct device_node *phy_np,
+ u32 flags,
+ phy_interface_t iface)
+{
+ struct phy_device *phy = of_phy_find_device(phy_np);
+
+ if (!phy)
+ return NULL;
+
+ return phy_attach_direct(dev, phy, flags, iface) ? NULL : phy;
+}
+EXPORT_SYMBOL(of_phy_attach);
+
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index f6dcde2..f849ae3 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -148,6 +148,18 @@ struct platform_device *of_device_alloc(struct device_node *np,
if (!dev)
return NULL;
+ dev->dev.of_node = of_node_get(np);
+ if (bus_id)
+ dev_set_name(&dev->dev, "%s", bus_id);
+ else
+ of_device_make_bus_id(&dev->dev);
+
+ if (kset_find_obj(dev->dev.kobj.kset, kobject_name(&dev->dev.kobj))) {
+ kfree(dev);
+ of_node_put(np);
+ return NULL;
+ }
+
/* count the io and irq resources */
if (of_can_translate_address(np))
while (of_address_to_resource(np, num_reg, &temp_res) == 0)
@@ -171,17 +183,11 @@ struct platform_device *of_device_alloc(struct device_node *np,
WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq);
}
- dev->dev.of_node = of_node_get(np);
#if defined(CONFIG_MICROBLAZE)
dev->dev.dma_mask = &dev->archdata.dma_mask;
#endif
dev->dev.parent = parent;
- if (bus_id)
- dev_set_name(&dev->dev, "%s", bus_id);
- else
- of_device_make_bus_id(&dev->dev);
-
return dev;
}
EXPORT_SYMBOL(of_device_alloc);
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index d5f90d6..8312492 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -30,6 +30,20 @@ static int pci_msi_enable = 1;
/* Arch hooks */
+#ifndef arch_msi_get_region_count
+int arch_msi_get_region_count(void)
+{
+ return 0;
+}
+#endif
+
+#ifndef arch_msi_get_region
+int arch_msi_get_region(int region_num, struct msi_region *region)
+{
+ return 0;
+}
+#endif
+
int __weak arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
{
struct msi_chip *chip = dev->bus->msi;
@@ -920,6 +934,18 @@ void pci_disable_msi(struct pci_dev *dev)
}
EXPORT_SYMBOL(pci_disable_msi);
+int msi_get_region_count(void)
+{
+ return arch_msi_get_region_count();
+}
+EXPORT_SYMBOL(msi_get_region_count);
+
+int msi_get_region(int region_num, struct msi_region *region)
+{
+ return arch_msi_get_region(region_num, region);
+}
+EXPORT_SYMBOL(msi_get_region);
+
/**
* pci_msix_table_size - return the number of device's MSI-X table entries
* @dev: pointer to the pci_dev data structure of MSI-X device function
diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig
index 69616ae..54ada25 100644
--- a/drivers/platform/Kconfig
+++ b/drivers/platform/Kconfig
@@ -5,3 +5,4 @@ if GOLDFISH
source "drivers/platform/goldfish/Kconfig"
endif
+source "drivers/platform/fsl/Kconfig"
diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile
index 8a44a4c..d0cce95 100644
--- a/drivers/platform/Makefile
+++ b/drivers/platform/Makefile
@@ -5,3 +5,4 @@
obj-$(CONFIG_X86) += x86/
obj-$(CONFIG_OLPC) += olpc/
obj-$(CONFIG_GOLDFISH) += goldfish/
+obj-$(CONFIG_FSL_SOC) += fsl/
diff --git a/drivers/platform/fsl/Kconfig b/drivers/platform/fsl/Kconfig
new file mode 100644
index 0000000..72ed053
--- /dev/null
+++ b/drivers/platform/fsl/Kconfig
@@ -0,0 +1,10 @@
+#
+# Freescale Specific Power Management Drivers
+#
+
+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.
diff --git a/drivers/platform/fsl/Makefile b/drivers/platform/fsl/Makefile
new file mode 100644
index 0000000..d99ca0e
--- /dev/null
+++ b/drivers/platform/fsl/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for linux/drivers/platform/fsl
+# Freescale Specific Power Management Drivers
+#
+obj-$(CONFIG_FSL_SLEEP_FSM) += sleep_fsm.o
diff --git a/drivers/platform/fsl/sleep_fsm.c b/drivers/platform/fsl/sleep_fsm.c
new file mode 100644
index 0000000..195a09c
--- /dev/null
+++ b/drivers/platform/fsl/sleep_fsm.c
@@ -0,0 +1,342 @@
+/*
+ * Freescale deep sleep FSM (finite-state machine) configuration
+ *
+ * Copyright 2014 Freescale Semiconductor Inc.
+ *
+ * Author: Hongbo Zhang <hongbo.zhang@freescale.com>
+ * Chenhui Zhao <chenhui.zhao@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/io.h>
+#include <linux/types.h>
+
+#define FSL_STRIDE_4B 4
+#define FSL_STRIDE_8B 8
+
+/* End flag */
+#define FSM_END_FLAG 0xFFFFFFFFUL
+
+/* EPGCR (Event Processor Global Control Register) */
+#define EPGCR 0x000
+
+/* EPEVTCR0-9 (Event Processor EVT Pin Control Registers) */
+#define EPEVTCR0 0x050
+#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 EPIMCR_STRIDE FSL_STRIDE_4B
+
+/* EPSMCR0-15 (Event Processor SCU Mux Control Registers) */
+#define EPSMCR0 0x200
+#define EPSMCR_STRIDE FSL_STRIDE_8B
+
+/* EPECR0-15 (Event Processor Event Control Registers) */
+#define EPECR0 0x300
+#define EPECR_STRIDE FSL_STRIDE_4B
+
+/* EPACR0-15 (Event Processor Action Control Registers) */
+#define EPACR0 0x400
+#define EPACR_STRIDE FSL_STRIDE_4B
+
+/* EPCCRi0-15 (Event Processor Counter Control Registers) */
+#define EPCCR0 0x800
+#define EPCCR_STRIDE FSL_STRIDE_4B
+
+/* EPCMPR0-15 (Event Processor Counter Compare Registers) */
+#define EPCMPR0 0x900
+#define EPCMPR_STRIDE FSL_STRIDE_4B
+
+/* EPCTR0-31 (Event Processor Counter Register) */
+#define EPCTR0 0xA00
+#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
+
+/* Block offsets */
+#define RCPM_BLOCK_OFFSET 0x00022000
+#define EPU_BLOCK_OFFSET 0x00000000
+#define NPC_BLOCK_OFFSET 0x00001000
+
+struct fsm_reg_vals {
+ u32 offset;
+ u32 value;
+};
+
+/*
+ * 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.
+ */
+struct fsm_reg_vals fsm_default_val[] = {
+ /* EPGCR (Event Processor Global Control Register) */
+ {EPU_BLOCK_OFFSET + EPGCR, 0},
+ /* EPCTR (Event Processor Counter Register) */
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 0, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 1, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 2, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 3, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 4, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 5, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 6, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 7, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 8, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 9, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 10, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 11, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 12, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 13, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 14, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 15, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 16, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 17, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 18, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 19, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 20, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 21, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 22, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 23, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 24, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 25, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 26, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 27, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 28, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 29, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 30, 0},
+ {EPU_BLOCK_OFFSET + EPCTR0 + EPCTR_STRIDE * 31, 0},
+ /* EPECR (Event Processor Event Control Registers) */
+ {EPU_BLOCK_OFFSET + EPECR0 + EPECR_STRIDE * 0, 0},
+ {EPU_BLOCK_OFFSET + EPECR0 + EPECR_STRIDE * 1, 0},
+ {EPU_BLOCK_OFFSET + EPECR0 + EPECR_STRIDE * 2, 0xF0004004},
+ {EPU_BLOCK_OFFSET + EPECR0 + EPECR_STRIDE * 3, 0x80000084},
+ {EPU_BLOCK_OFFSET + EPECR0 + EPECR_STRIDE * 4, 0x20000084},
+ {EPU_BLOCK_OFFSET + EPECR0 + EPECR_STRIDE * 5, 0x08000004},
+ {EPU_BLOCK_OFFSET + EPECR0 + EPECR_STRIDE * 6, 0x80000084},
+ {EPU_BLOCK_OFFSET + EPECR0 + EPECR_STRIDE * 7, 0x80000084},
+ {EPU_BLOCK_OFFSET + EPECR0 + EPECR_STRIDE * 8, 0x60000084},
+ {EPU_BLOCK_OFFSET + EPECR0 + EPECR_STRIDE * 9, 0x08000084},
+ {EPU_BLOCK_OFFSET + EPECR0 + EPECR_STRIDE * 10, 0x42000084},
+ {EPU_BLOCK_OFFSET + EPECR0 + EPECR_STRIDE * 11, 0x90000084},
+ {EPU_BLOCK_OFFSET + EPECR0 + EPECR_STRIDE * 12, 0x80000084},
+ {EPU_BLOCK_OFFSET + EPECR0 + EPECR_STRIDE * 13, 0x08000084},
+ {EPU_BLOCK_OFFSET + EPECR0 + EPECR_STRIDE * 14, 0x02000084},
+ {EPU_BLOCK_OFFSET + EPECR0 + EPECR_STRIDE * 15, 0x00000004},
+ /*
+ * EPEVTCR (Event Processor EVT Pin Control Registers)
+ * SCU8 triger EVT2, and SCU11 triger EVT9
+ */
+ {EPU_BLOCK_OFFSET + EPEVTCR0 + EPEVTCR_STRIDE * 0, 0},
+ {EPU_BLOCK_OFFSET + EPEVTCR0 + EPEVTCR_STRIDE * 1, 0},
+ {EPU_BLOCK_OFFSET + EPEVTCR0 + EPEVTCR_STRIDE * 2, 0x80000001},
+ {EPU_BLOCK_OFFSET + EPEVTCR0 + EPEVTCR_STRIDE * 3, 0},
+ {EPU_BLOCK_OFFSET + EPEVTCR0 + EPEVTCR_STRIDE * 4, 0},
+ {EPU_BLOCK_OFFSET + EPEVTCR0 + EPEVTCR_STRIDE * 5, 0},
+ {EPU_BLOCK_OFFSET + EPEVTCR0 + EPEVTCR_STRIDE * 6, 0},
+ {EPU_BLOCK_OFFSET + EPEVTCR0 + EPEVTCR_STRIDE * 7, 0},
+ {EPU_BLOCK_OFFSET + EPEVTCR0 + EPEVTCR_STRIDE * 8, 0},
+ {EPU_BLOCK_OFFSET + EPEVTCR0 + EPEVTCR_STRIDE * 9, 0xB0000001},
+ /* EPCMPR (Event Processor Counter Compare Registers) */
+ {EPU_BLOCK_OFFSET + EPCMPR0 + EPCMPR_STRIDE * 0, 0},
+ {EPU_BLOCK_OFFSET + EPCMPR0 + EPCMPR_STRIDE * 1, 0},
+ {EPU_BLOCK_OFFSET + EPCMPR0 + EPCMPR_STRIDE * 2, 0x000000FF},
+ {EPU_BLOCK_OFFSET + EPCMPR0 + EPCMPR_STRIDE * 3, 0},
+ {EPU_BLOCK_OFFSET + EPCMPR0 + EPCMPR_STRIDE * 4, 0x000000FF},
+ {EPU_BLOCK_OFFSET + EPCMPR0 + EPCMPR_STRIDE * 5, 0x00000020},
+ {EPU_BLOCK_OFFSET + EPCMPR0 + EPCMPR_STRIDE * 6, 0},
+ {EPU_BLOCK_OFFSET + EPCMPR0 + EPCMPR_STRIDE * 7, 0},
+ {EPU_BLOCK_OFFSET + EPCMPR0 + EPCMPR_STRIDE * 8, 0x000000FF},
+ {EPU_BLOCK_OFFSET + EPCMPR0 + EPCMPR_STRIDE * 9, 0x000000FF},
+ {EPU_BLOCK_OFFSET + EPCMPR0 + EPCMPR_STRIDE * 10, 0x000000FF},
+ {EPU_BLOCK_OFFSET + EPCMPR0 + EPCMPR_STRIDE * 11, 0x000000FF},
+ {EPU_BLOCK_OFFSET + EPCMPR0 + EPCMPR_STRIDE * 12, 0x000000FF},
+ {EPU_BLOCK_OFFSET + EPCMPR0 + EPCMPR_STRIDE * 13, 0},
+ {EPU_BLOCK_OFFSET + EPCMPR0 + EPCMPR_STRIDE * 14, 0x000000FF},
+ {EPU_BLOCK_OFFSET + EPCMPR0 + EPCMPR_STRIDE * 15, 0x000000FF},
+ /* EPCCR (Event Processor Counter Control Registers) */
+ {EPU_BLOCK_OFFSET + EPCCR0 + EPCCR_STRIDE * 0, 0},
+ {EPU_BLOCK_OFFSET + EPCCR0 + EPCCR_STRIDE * 1, 0},
+ {EPU_BLOCK_OFFSET + EPCCR0 + EPCCR_STRIDE * 2, 0x92840000},
+ {EPU_BLOCK_OFFSET + EPCCR0 + EPCCR_STRIDE * 3, 0},
+ {EPU_BLOCK_OFFSET + EPCCR0 + EPCCR_STRIDE * 4, 0x92840000},
+ {EPU_BLOCK_OFFSET + EPCCR0 + EPCCR_STRIDE * 5, 0x92840000},
+ {EPU_BLOCK_OFFSET + EPCCR0 + EPCCR_STRIDE * 6, 0},
+ {EPU_BLOCK_OFFSET + EPCCR0 + EPCCR_STRIDE * 7, 0},
+ {EPU_BLOCK_OFFSET + EPCCR0 + EPCCR_STRIDE * 8, 0x92840000},
+ {EPU_BLOCK_OFFSET + EPCCR0 + EPCCR_STRIDE * 9, 0x92840000},
+ {EPU_BLOCK_OFFSET + EPCCR0 + EPCCR_STRIDE * 10, 0x92840000},
+ {EPU_BLOCK_OFFSET + EPCCR0 + EPCCR_STRIDE * 11, 0x92840000},
+ {EPU_BLOCK_OFFSET + EPCCR0 + EPCCR_STRIDE * 12, 0x92840000},
+ {EPU_BLOCK_OFFSET + EPCCR0 + EPCCR_STRIDE * 13, 0},
+ {EPU_BLOCK_OFFSET + EPCCR0 + EPCCR_STRIDE * 14, 0x92840000},
+ {EPU_BLOCK_OFFSET + EPCCR0 + EPCCR_STRIDE * 15, 0x92840000},
+ /* EPSMCR (Event Processor SCU Mux Control Registers) */
+ {EPU_BLOCK_OFFSET + EPSMCR0 + EPSMCR_STRIDE * 0, 0},
+ {EPU_BLOCK_OFFSET + EPSMCR0 + EPSMCR_STRIDE * 1, 0},
+ {EPU_BLOCK_OFFSET + EPSMCR0 + EPSMCR_STRIDE * 2, 0x6C700000},
+ {EPU_BLOCK_OFFSET + EPSMCR0 + EPSMCR_STRIDE * 3, 0x2F000000},
+ {EPU_BLOCK_OFFSET + EPSMCR0 + EPSMCR_STRIDE * 4, 0x002F0000},
+ {EPU_BLOCK_OFFSET + EPSMCR0 + EPSMCR_STRIDE * 5, 0x00002E00},
+ {EPU_BLOCK_OFFSET + EPSMCR0 + EPSMCR_STRIDE * 6, 0x7C000000},
+ {EPU_BLOCK_OFFSET + EPSMCR0 + EPSMCR_STRIDE * 7, 0x30000000},
+ {EPU_BLOCK_OFFSET + EPSMCR0 + EPSMCR_STRIDE * 8, 0x64300000},
+ {EPU_BLOCK_OFFSET + EPSMCR0 + EPSMCR_STRIDE * 9, 0x00003000},
+ {EPU_BLOCK_OFFSET + EPSMCR0 + EPSMCR_STRIDE * 10, 0x65000030},
+ {EPU_BLOCK_OFFSET + EPSMCR0 + EPSMCR_STRIDE * 11, 0x31740000},
+ {EPU_BLOCK_OFFSET + EPSMCR0 + EPSMCR_STRIDE * 12, 0x7F000000},
+ {EPU_BLOCK_OFFSET + EPSMCR0 + EPSMCR_STRIDE * 13, 0x00003100},
+ {EPU_BLOCK_OFFSET + EPSMCR0 + EPSMCR_STRIDE * 14, 0x00000031},
+ {EPU_BLOCK_OFFSET + EPSMCR0 + EPSMCR_STRIDE * 15, 0x76000000},
+ /* EPACR (Event Processor Action Control Registers) */
+ {EPU_BLOCK_OFFSET + EPACR0 + EPACR_STRIDE * 0, 0},
+ {EPU_BLOCK_OFFSET + EPACR0 + EPACR_STRIDE * 1, 0},
+ {EPU_BLOCK_OFFSET + EPACR0 + EPACR_STRIDE * 2, 0},
+ {EPU_BLOCK_OFFSET + EPACR0 + EPACR_STRIDE * 3, 0x00000080},
+ {EPU_BLOCK_OFFSET + EPACR0 + EPACR_STRIDE * 4, 0},
+ {EPU_BLOCK_OFFSET + EPACR0 + EPACR_STRIDE * 5, 0x00000040},
+ {EPU_BLOCK_OFFSET + EPACR0 + EPACR_STRIDE * 6, 0},
+ {EPU_BLOCK_OFFSET + EPACR0 + EPACR_STRIDE * 7, 0},
+ {EPU_BLOCK_OFFSET + EPACR0 + EPACR_STRIDE * 8, 0},
+ {EPU_BLOCK_OFFSET + EPACR0 + EPACR_STRIDE * 9, 0x0000001C},
+ {EPU_BLOCK_OFFSET + EPACR0 + EPACR_STRIDE * 10, 0x00000020},
+ {EPU_BLOCK_OFFSET + EPACR0 + EPACR_STRIDE * 11, 0},
+ {EPU_BLOCK_OFFSET + EPACR0 + EPACR_STRIDE * 12, 0x00000003},
+ {EPU_BLOCK_OFFSET + EPACR0 + EPACR_STRIDE * 13, 0x06000000},
+ {EPU_BLOCK_OFFSET + EPACR0 + EPACR_STRIDE * 14, 0x04000000},
+ {EPU_BLOCK_OFFSET + EPACR0 + EPACR_STRIDE * 15, 0x02000000},
+ /* EPIMCR (Event Processor Input Mux Control Registers) */
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 0, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 1, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 2, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 3, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 4, 0x44000000},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 5, 0x40000000},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 6, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 7, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 8, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 9, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 10, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 11, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 12, 0x44000000},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 13, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 14, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 15, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 16, 0x6A000000},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 17, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 18, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 19, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 20, 0x48000000},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 21, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 22, 0x6C000000},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 23, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 24, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 25, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 26, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 27, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 28, 0x76000000},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 29, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 30, 0},
+ {EPU_BLOCK_OFFSET + EPIMCR0 + EPIMCR_STRIDE * 31, 0x76000000},
+ /* EPXTRIGCR (Event Processor Crosstrigger Control Register) */
+ {EPU_BLOCK_OFFSET + EPXTRIGCR, 0x0000FFDF},
+ /* NPC triggered Memory-Mapped Access Registers */
+ {NPC_BLOCK_OFFSET + NCR, 0x80000000},
+ {NPC_BLOCK_OFFSET + MCCR1, 0},
+ {NPC_BLOCK_OFFSET + MCSR1, 0},
+ {NPC_BLOCK_OFFSET + MMAR1LO, 0},
+ {NPC_BLOCK_OFFSET + MMAR1HI, 0},
+ {NPC_BLOCK_OFFSET + MMDR1, 0},
+ {NPC_BLOCK_OFFSET + MCSR2, 0},
+ {NPC_BLOCK_OFFSET + MMAR2LO, 0},
+ {NPC_BLOCK_OFFSET + MMAR2HI, 0},
+ {NPC_BLOCK_OFFSET + MMDR2, 0},
+ {NPC_BLOCK_OFFSET + MCSR3, 0x80000000},
+ {NPC_BLOCK_OFFSET + MMAR3LO, 0x000E2130},
+ {NPC_BLOCK_OFFSET + MMAR3HI, 0x00030000},
+ {NPC_BLOCK_OFFSET + MMDR3, 0x00020000},
+ /* Configure RCPM for detecting Core0’s PH15 state */
+ {RCPM_BLOCK_OFFSET + CSTTACR0, 0x00001001},
+ {RCPM_BLOCK_OFFSET + CG1CR0, 0x00000001},
+ /* end */
+ {FSM_END_FLAG, 0},
+};
+
+/**
+ * fsl_dp_fsm_clean - Clear EPU's FSM
+ * @dcsr_base: the base address of DCSR registers
+ * @val: Pointer to values for FSM registers. If NULL,
+ * will use the default value.
+ */
+void fsl_dp_fsm_clean(void __iomem *dcsr_base, struct fsm_reg_vals *val)
+{
+ struct fsm_reg_vals *data;
+
+ /* if NULL, use the default values */
+ if (val)
+ data = val;
+ else
+ data = fsm_default_val;
+
+ while (data->offset != FSM_END_FLAG) {
+ out_be32(dcsr_base + data->offset, 0);
+ in_be32(dcsr_base + data->offset);
+ data++;
+ }
+}
+
+/**
+ * fsl_dp_fsm_setup - Configure EPU's FSM
+ * @dcsr_base: the base address of DCSR registers
+ * @val: Pointer to values for FSM registers. If NULL,
+ * will use the default value.
+ */
+void fsl_dp_fsm_setup(void __iomem *dcsr_base, struct fsm_reg_vals *val)
+{
+ struct fsm_reg_vals *data;
+
+ /* if NULL, use the default values */
+ if (val)
+ data = val;
+ else
+ data = fsm_default_val;
+
+ /* clear all registers */
+ fsl_dp_fsm_clean(dcsr_base, data);
+
+ while (data->offset != FSM_END_FLAG) {
+ if (data->value) {
+ out_be32(dcsr_base + data->offset, data->value);
+ in_be32(dcsr_base + data->offset);
+ }
+ data++;
+ }
+}
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c
index b83bb5a5..dfd810f 100644
--- a/drivers/rtc/rtc-ds3232.c
+++ b/drivers/rtc/rtc-ds3232.c
@@ -418,9 +418,9 @@ static int ds3232_probe(struct i2c_client *client,
return PTR_ERR(ds3232->rtc);
}
- if (client->irq >= 0) {
- ret = devm_request_irq(&client->dev, client->irq, ds3232_irq, 0,
- "ds3232", client);
+ if (client->irq > 0) {
+ ret = devm_request_irq(&client->dev, client->irq, ds3232_irq,
+ IRQF_SHARED, "ds3232", client);
if (ret) {
dev_err(&client->dev, "unable to request IRQ\n");
return ret;
diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c
index b8f1103..50c2040 100644
--- a/drivers/spi/spi-fsl-espi.c
+++ b/drivers/spi/spi-fsl-espi.c
@@ -725,6 +725,66 @@ static int of_fsl_espi_remove(struct platform_device *dev)
return mpc8xxx_spi_remove(&dev->dev);
}
+#ifdef CONFIG_PM_SLEEP
+static int of_fsl_espi_suspend(struct device *dev)
+{
+ struct spi_master *master = dev_get_drvdata(dev);
+ struct mpc8xxx_spi *mpc8xxx_spi;
+ struct fsl_espi_reg *reg_base;
+ u32 regval;
+ int ret;
+
+ mpc8xxx_spi = spi_master_get_devdata(master);
+ reg_base = mpc8xxx_spi->reg_base;
+
+ ret = spi_master_suspend(master);
+ if (ret) {
+ dev_warn(dev, "cannot suspend master\n");
+ return ret;
+ }
+
+ regval = mpc8xxx_spi_read_reg(&reg_base->mode);
+ regval &= ~SPMODE_ENABLE;
+ mpc8xxx_spi_write_reg(&reg_base->mode, regval);
+
+ return 0;
+}
+
+static int of_fsl_espi_resume(struct device *dev)
+{
+ struct fsl_spi_platform_data *pdata = dev_get_platdata(dev);
+ struct spi_master *master = dev_get_drvdata(dev);
+ struct mpc8xxx_spi *mpc8xxx_spi;
+ struct fsl_espi_reg *reg_base;
+ u32 regval;
+ int i;
+
+ mpc8xxx_spi = spi_master_get_devdata(master);
+ reg_base = mpc8xxx_spi->reg_base;
+
+ /* SPI controller initializations */
+ mpc8xxx_spi_write_reg(&reg_base->mode, 0);
+ mpc8xxx_spi_write_reg(&reg_base->mask, 0);
+ mpc8xxx_spi_write_reg(&reg_base->command, 0);
+ mpc8xxx_spi_write_reg(&reg_base->event, 0xffffffff);
+
+ /* Init eSPI CS mode register */
+ for (i = 0; i < pdata->max_chipselect; i++)
+ mpc8xxx_spi_write_reg(&reg_base->csmode[i], CSMODE_INIT_VAL);
+
+ /* Enable SPI interface */
+ regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE;
+
+ mpc8xxx_spi_write_reg(&reg_base->mode, regval);
+
+ return spi_master_resume(master);
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static const struct dev_pm_ops espi_pm = {
+ SET_SYSTEM_SLEEP_PM_OPS(of_fsl_espi_suspend, of_fsl_espi_resume)
+};
+
static const struct of_device_id of_fsl_espi_match[] = {
{ .compatible = "fsl,mpc8536-espi" },
{}
@@ -736,6 +796,7 @@ static struct platform_driver fsl_espi_driver = {
.name = "fsl_espi",
.owner = THIS_MODULE,
.of_match_table = of_fsl_espi_match,
+ .pm = &espi_pm,
},
.probe = of_fsl_espi_probe,
.remove = of_fsl_espi_remove,
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 3626dbc8..96b7873 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -138,6 +138,16 @@ source "drivers/staging/netlogic/Kconfig"
source "drivers/staging/dwc2/Kconfig"
+source "drivers/staging/fsl_qbman/Kconfig"
+
+source "drivers/staging/fsl_pme2/Kconfig"
+
+source "drivers/staging/fsl_rman/Kconfig"
+
+source "drivers/staging/fsl_dpa_offload/Kconfig"
+
+source "drivers/staging/fsl_dce/Kconfig"
+
source "drivers/staging/lustre/Kconfig"
source "drivers/staging/btmtk_usb/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index d1b4b80..8aacb13 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -61,6 +61,11 @@ obj-$(CONFIG_SB105X) += sb105x/
obj-$(CONFIG_FIREWIRE_SERIAL) += fwserial/
obj-$(CONFIG_GOLDFISH) += goldfish/
obj-$(CONFIG_USB_DWC2) += dwc2/
+obj-$(CONFIG_FSL_DPA) += fsl_qbman/
+obj-$(CONFIG_FSL_PME2) += fsl_pme2/
+obj-$(CONFIG_FSL_RMAN_UIO) += fsl_rman/
+obj-$(CONFIG_FSL_DPA_OFFLOAD) += fsl_dpa_offload/
+obj-$(CONFIG_FSL_DCE) += fsl_dce/
obj-$(CONFIG_LUSTRE_FS) += lustre/
obj-$(CONFIG_USB_BTMTK) += btmtk_usb/
obj-$(CONFIG_XILLYBUS) += xillybus/
diff --git a/drivers/staging/fsl_dce/Kconfig b/drivers/staging/fsl_dce/Kconfig
new file mode 100644
index 0000000..628c0be
--- /dev/null
+++ b/drivers/staging/fsl_dce/Kconfig
@@ -0,0 +1,32 @@
+config FSL_DCE
+ tristate "Freescale Decompression Compression Engine support"
+ depends on FSL_QMAN
+ help
+ Say Y here to include support for the Freescale DCE driver.
+ To compile this driver as a module, choose M here: the module
+ will be called dce
+
+if FSL_DCE
+
+config FSL_DCE_CONFIG
+ tristate "Freescale DCE device management"
+ default y
+ help
+ Say Y here to include support for the Freescale DCE driver.
+ To compile this driver as a module, choose M here: the module
+ will be called dce
+
+config FSL_DCE_DEBUGFS
+ tristate "Freescale Decompression Compression Engine DebugFS interface"
+ default y
+ help
+ Say Y here to include debugfs interface
+
+config FSL_DCE_TESTS
+ tristate "Build dce test"
+ depends on m
+ default m
+ help
+ Build dce test module
+
+endif # FSL_DCE
diff --git a/drivers/staging/fsl_dce/Makefile b/drivers/staging/fsl_dce/Makefile
new file mode 100644
index 0000000..87886fa
--- /dev/null
+++ b/drivers/staging/fsl_dce/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for Freesecale DCE driver
+#
+
+obj-$(CONFIG_FSL_DCE) += fsl-dce.o
+obj-$(CONFIG_FSL_DCE_CONFIG) += fsl-dce-config.o
+obj-$(CONFIG_FSL_DCE_DEBUGFS) += fsl-dce-debugfs.o
+
+fsl-dce-y := dce_sys.o flib/dce_flow.o fsl_dce_chunk.o fsl_dce_stream.o
+fsl-dce-config-y := dce_driver.o
+fsl-dce-debugfs-y := dce_debugfs.o
+
+obj-y += tests/
+
diff --git a/drivers/staging/fsl_dce/dce_debugfs.c b/drivers/staging/fsl_dce/dce_debugfs.c
new file mode 100644
index 0000000..34ba589
--- /dev/null
+++ b/drivers/staging/fsl_dce/dce_debugfs.c
@@ -0,0 +1,282 @@
+/* Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * This software is provided by Freescale Semiconductor "as is" and any
+ * express or implied warranties, including, but not limited to, the implied
+ * warranties of merchantability and fitness for a particular purpose are
+ * disclaimed. In no event shall Freescale Semiconductor be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential damages
+ * (including, but not limited to, procurement of substitute goods or services;
+ * loss of use, data, or profits; or business interruption) however caused and
+ * on any theory of liability, whether in contract, strict liability, or tort
+ * (including negligence or otherwise) arising in any way out of the use of
+ * this software, even if advised of the possibility of such damage.
+ */
+
+#include <linux/of_address.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+#include <linux/module.h>
+
+#define DRV_VERSION "0.1"
+
+static uint64_t dce_ccsr_start;
+static uint64_t dce_ccsr_size;
+
+/* takes userspace input and converts to upper case */
+static int user_input_convert(const char __user *user_buf, size_t count,
+ unsigned long *val)
+{
+ char buf[12];
+
+ if (count > sizeof(buf) - 1)
+ return -EINVAL;
+ if (copy_from_user(buf, user_buf, count))
+ return -EFAULT;
+ buf[count] = '\0';
+ if (kstrtoul(buf, 0, val))
+ return -EINVAL;
+ return 0;
+}
+
+static struct dentry *dfs_root; /* debugfs root directory */
+
+struct dce_register_s {
+ uint32_t val;
+};
+static struct dce_register_s dce_register_data;
+
+static int init_ccsrmempeek(void)
+{
+ struct device_node *dn;
+ const uint32_t *regaddr_p;
+
+ dn = of_find_compatible_node(NULL, NULL, "fsl,dce");
+ if (!dn) {
+ pr_info("No fsl,dce node\n");
+ return -ENODEV;
+ }
+ regaddr_p = of_get_address(dn, 0, &dce_ccsr_size, NULL);
+ if (!regaddr_p) {
+ of_node_put(dn);
+ return -EINVAL;
+ }
+ dce_ccsr_start = of_translate_address(dn, regaddr_p);
+ of_node_put(dn);
+ return 0;
+}
+
+/* This function provides access to DCE ccsr memory map */
+static int dce_ccsrmem_get(uint32_t *val, uint32_t offset)
+{
+ void __iomem *addr;
+ uint64_t phys_addr;
+
+ if (!dce_ccsr_start)
+ return -EINVAL;
+
+ if (offset > (dce_ccsr_size - sizeof(uint32_t)))
+ return -EINVAL;
+
+ phys_addr = dce_ccsr_start + offset;
+ addr = ioremap(phys_addr, sizeof(uint32_t));
+ if (!addr) {
+ pr_err("ccsrmem, ioremap failed\n");
+ return -EINVAL;
+ }
+ *val = in_be32(addr);
+ iounmap(addr);
+ return 0;
+}
+
+static int dce_ccsrmem_put(uint32_t val, uint32_t offset)
+{
+ void __iomem *addr;
+ uint64_t phys_addr;
+
+ if (!dce_ccsr_start)
+ return -EINVAL;
+
+ if (offset > (dce_ccsr_size - sizeof(uint32_t)))
+ return -EINVAL;
+
+ phys_addr = dce_ccsr_start + offset;
+ addr = ioremap(phys_addr, sizeof(uint32_t));
+ if (!addr) {
+ pr_err("ccsrmem, ioremap failed\n");
+ return -EINVAL;
+ }
+ iowrite32be(val, addr);
+ iounmap(addr);
+ return 0;
+}
+
+
+static int dce_ccsrmem_addr_show(struct seq_file *file, void *offset)
+{
+ seq_printf(file, "DCE register offset = 0x%x\n",
+ dce_register_data.val);
+ return 0;
+}
+
+static int dce_ccsrmem_addr_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, dce_ccsrmem_addr_show, NULL);
+}
+
+static ssize_t dce_ccsrmem_addr_write(struct file *f, const char __user *buf,
+ size_t count, loff_t *off)
+{
+ int ret;
+ unsigned long val;
+
+ ret = user_input_convert(buf, count, &val);
+ if (ret)
+ return ret;
+ /* multiple of 4 */
+ if (val > (dce_ccsr_size - sizeof(uint32_t))) {
+ pr_info("Input 0x%lx > 0x%llx\n",
+ val, (dce_ccsr_size - sizeof(uint32_t)));
+ return -EINVAL;
+ }
+ if (val & 0x3) {
+ pr_info("Input 0x%lx not multiple of 4\n", val);
+ return -EINVAL;
+ }
+ dce_register_data.val = val;
+ return count;
+}
+
+static const struct file_operations dce_ccsrmem_addr_fops = {
+ .owner = THIS_MODULE,
+ .open = dce_ccsrmem_addr_open,
+ .read = seq_read,
+ .write = dce_ccsrmem_addr_write,
+};
+
+
+static int dce_ccsrmem_rw_show(struct seq_file *file, void *offset)
+{
+ uint32_t out_val = 0;
+ int ret;
+
+ ret = dce_ccsrmem_get(&out_val, dce_register_data.val);
+ if (ret)
+ return ret;
+ seq_printf(file, "DCE register offset = 0x%x\n",
+ dce_register_data.val);
+ seq_printf(file, "value = 0x%08x\n", out_val);
+
+ return 0;
+}
+
+static int dce_ccsrmem_rw_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, dce_ccsrmem_rw_show, NULL);
+}
+
+static ssize_t dce_ccsrmem_rw_write(struct file *f, const char __user *buf,
+ size_t count, loff_t *off)
+{
+ int ret;
+ unsigned long val;
+
+ ret = user_input_convert(buf, count, &val);
+ if (ret)
+ return ret;
+
+ ret = dce_ccsrmem_put(val, dce_register_data.val);
+
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static const struct file_operations dce_ccsrmem_rw_fops = {
+ .owner = THIS_MODULE,
+ .open = dce_ccsrmem_rw_open,
+ .read = seq_read,
+ .write = dce_ccsrmem_rw_write,
+};
+
+#define DCE_DBGFS_ENTRY(name, mode, parent, data, fops) \
+ do { \
+ d = debugfs_create_file(name, \
+ mode, parent, \
+ data, \
+ fops); \
+ if (d == NULL) { \
+ ret = -ENOMEM; \
+ } \
+ } while (0)
+
+/* dfs_root as parent */
+#define DCE_DBGFS_ENTRY_ROOT(name, mode, data, fops) \
+ DCE_DBGFS_ENTRY(name, mode, dfs_root, data, fops)
+
+static int __init dce_debugfs_module_init(void)
+{
+ int ret = 0;
+ struct dentry *d;
+
+ ret = init_ccsrmempeek();
+ if (ret)
+ goto fail_init;
+ dfs_root = debugfs_create_dir("dce", NULL);
+ if (dfs_root == NULL) {
+ ret = -ENOMEM;
+ pr_err("Cannot create dce debugfs dir\n");
+ goto fail_dce_dir;
+ }
+
+ DCE_DBGFS_ENTRY_ROOT("ccsrmem_addr", S_IRUGO | S_IWUGO,
+ NULL, &dce_ccsrmem_addr_fops);
+ if (ret)
+ goto fail_dce_dir;
+
+ DCE_DBGFS_ENTRY_ROOT("ccsrmem_rw", S_IRUGO | S_IWUGO,
+ NULL, &dce_ccsrmem_rw_fops);
+ if (ret)
+ goto fail_dce_dir;
+
+ return 0;
+
+fail_dce_dir:
+ debugfs_remove_recursive(dfs_root);
+fail_init:
+ return ret;
+}
+
+static void __exit dce_debugfs_module_exit(void)
+{
+ debugfs_remove_recursive(dfs_root);
+}
+
+module_init(dce_debugfs_module_init);
+module_exit(dce_debugfs_module_exit);
+
+MODULE_AUTHOR("Jeffrey Ladouceur");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("FSL DCE debugfs accessr");
+MODULE_VERSION(DRV_VERSION);
+
diff --git a/drivers/staging/fsl_dce/dce_driver.c b/drivers/staging/fsl_dce/dce_driver.c
new file mode 100644
index 0000000..07ccb0d
--- /dev/null
+++ b/drivers/staging/fsl_dce/dce_driver.c
@@ -0,0 +1,347 @@
+/* Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * This software is provided by Freescale Semiconductor "as is" and any
+ * express or implied warranties, including, but not limited to, the implied
+ * warranties of merchantability and fitness for a particular purpose are
+ * disclaimed. In no event shall Freescale Semiconductor be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential damages
+ * (including, but not limited to, procurement of substitute goods or services;
+ * loss of use, data, or profits; or business interruption) however caused and
+ * on any theory of liability, whether in contract, strict liability, or tort
+ * (including negligence or otherwise) arising in any way out of the use of
+ * this software, even if advised of the possibility of such damage.
+ */
+
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/kernel.h>
+#include <linux/debugfs.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include "fsl_dce.h"
+#include "flib/dce_regs.h"
+#include "flib/dce_defs.h"
+
+#define DRV_VERSION "0.1"
+
+uint16_t dce_ip_rev = DCE_REV10;
+EXPORT_SYMBOL(dce_ip_rev);
+
+/* Pointer used to represent the DCE CCSR map and its instance */
+static struct dce_regs *global_dce_regs;
+
+/*
+ * Driver-private storage for a single DCE block instance
+ */
+struct dce_drv_private {
+ struct device *dev;
+ struct platform_device *pdev;
+
+ /* Physical-presence section */
+ struct dce_regs __iomem *topregs;
+ int err_irq; /* Error interrupt number */
+};
+
+/* Simple DCE error interrupt handler */
+static irqreturn_t dce_isr(int irq, void *st_dev)
+{
+ struct device *dev = st_dev;
+ struct dce_drv_private *ctrlpriv = dev_get_drvdata(dev);
+ static uint32_t last_isrstate;
+ uint32_t isrstate = ioread32be(&ctrlpriv->topregs->isr) ^ last_isrstate;
+
+ /* What new ISR state has been raise */
+ if (!isrstate)
+ return IRQ_NONE;
+ if (ISEQ_32FTK(isrstate, DCE_ISR_SBE, AT_LEAST_ONE))
+ dev_err(dev, "Single Bit Error detected\n");
+ if (ISEQ_32FTK(isrstate, DCE_ISR_DBE, AT_LEAST_ONE))
+ dev_err(dev, "Double Bit Error detected\n");
+ if (ISEQ_32FTK(isrstate, DCE_ISR_UWE, AT_LEAST_ONE)) {
+ uint32_t uwe_high, uwe_low;
+
+ /* print extra info registers */
+ uwe_high = ioread32be(&ctrlpriv->topregs->uwe_info_h);
+ uwe_low = ioread32be(&ctrlpriv->topregs->uwe_info_l);
+ dev_err(dev,
+ "Unreported Write Error detected: infoh = 0x%x infol = 0x%x\n",
+ uwe_high, uwe_low);
+ }
+
+ /* Clear the ier interrupt bit */
+ last_isrstate |= isrstate;
+ iowrite32be(~last_isrstate, &ctrlpriv->topregs->ier);
+
+ return IRQ_HANDLED;
+}
+
+static int fsl_dce_remove(struct platform_device *pdev)
+{
+ struct device *ctrldev;
+ struct dce_drv_private *ctrlpriv;
+ struct dce_regs __iomem *topregs;
+ int ret = 0;
+
+ ctrldev = &pdev->dev;
+ ctrlpriv = dev_get_drvdata(ctrldev);
+ topregs = ctrlpriv->topregs;
+
+ /* Disable dce */
+ iowrite32be(DCE_CFG_EN_DISABLE, &topregs->cfg);
+
+ /* Release interrupt */
+ free_irq(ctrlpriv->err_irq, ctrldev);
+
+ /* Unmap controller region */
+ iounmap(topregs);
+ kfree(ctrlpriv);
+ global_dce_regs = NULL;
+
+ dev_info(&pdev->dev, "device full name %s removed\n",
+ pdev->dev.of_node->full_name);
+ return ret;
+}
+
+static int fsl_dce_probe(struct platform_device *pdev)
+{
+ int err;
+ struct device *dev;
+ struct device_node *nprop = NULL;
+ struct dce_regs __iomem *topregs;
+ struct dce_drv_private *ctrlpriv;
+ const char *s;
+ int ret;
+
+ /*
+ * TODO: This standby handling won't work properly after failover, it's
+ * just to allow bring up for now.
+ */
+ s = of_get_property(nprop, "fsl,hv-claimable", &ret);
+ if (s && !strcmp(s, "standby"))
+ return 0;
+
+ ctrlpriv = kzalloc(sizeof(struct dce_drv_private), GFP_KERNEL);
+ if (!ctrlpriv)
+ return -ENOMEM;
+
+ dev = &pdev->dev;
+ dev_set_drvdata(dev, ctrlpriv);
+ ctrlpriv->pdev = pdev;
+ nprop = pdev->dev.of_node;
+
+ /* Get configuration properties from device tree */
+
+ /* First, get register page */
+ topregs = of_iomap(nprop, 0);
+ if (topregs == NULL) {
+ dev_err(dev, "of_iomap() failed\n");
+ err = -ENOMEM;
+ goto out_free_ctrlpriv;
+ }
+ ctrlpriv->topregs = topregs;
+ global_dce_regs = topregs;
+
+ /* Get the IRQ of the error interrupt */
+ ctrlpriv->err_irq = of_irq_to_resource(nprop, 0, NULL);
+ if (!ctrlpriv->err_irq) {
+ dev_warn(dev, "Can't get %s property '%s'\n", nprop->full_name,
+ "interrupts");
+ } else {
+ /* Register the dce ISR handler */
+ err = request_irq(ctrlpriv->err_irq, dce_isr, IRQF_SHARED,
+ "dce-err", dev);
+ if (err) {
+ dev_err(dev, "request_irq() failed\n");
+ goto out_free_ctrlpriv;
+ }
+ }
+
+ /*
+ * Set System Memory Cache Attribute Control Register. Set all
+ * transactions to coherent.
+ */
+ iowrite32be(
+ (FL_FGENTK(DCE_SMCACR_CHWC, COHERENT) |
+ FL_FGENTK(DCE_SMCACR_SCWC, COHERENT) |
+ FL_FGENTK(DCE_SMCACR_FDWC, COHERENT) |
+ FL_FGENTK(DCE_SMCACR_DHWC, COHERENT) |
+ FL_FGENTK(DCE_SMCACR_CHRC, COHERENT) |
+ FL_FGENTK(DCE_SMCACR_SCRC, COHERENT) |
+ FL_FGENTK(DCE_SMCACR_FDRC, COHERENT) |
+ FL_FGENTK(DCE_SMCACR_DHRC, COHERENT)),
+ &topregs->smcacr);
+
+ /* Enable interrupts */
+ /*iowrite32be(DCE_IER_ALL, &topregs->ier);*/
+ iowrite32be(FL_FGENTK(DCE_IER_ALL, ENABLE), &topregs->ier);
+
+ /* Enable dce */
+ iowrite32be(FL_FGENTK(DCE_CFG_EN, ENABLE), &topregs->cfg);
+
+ dev_info(&pdev->dev, "Device %s initialized ver: 0x%08x\n\n",
+ pdev->dev.of_node->full_name, ioread32be(&topregs->ip_rev_1));
+
+ return 0;
+
+out_free_ctrlpriv:
+ kfree(ctrlpriv);
+ dev_set_drvdata(dev, NULL);
+ global_dce_regs = NULL;
+ return err;
+}
+
+static struct of_device_id fsl_dce_match[] = {
+ {
+ .compatible = "fsl,dce",
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, fsl_dce_match);
+
+static struct platform_driver fsl_dce_driver = {
+ .driver = {
+ .name = "fsl-dce",
+ .owner = THIS_MODULE,
+ .of_match_table = fsl_dce_match,
+ },
+ .probe = fsl_dce_probe,
+ .remove = fsl_dce_remove,
+};
+
+static int __init fsl_dce_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&fsl_dce_driver);
+ if (ret)
+ pr_err("fsl-dce: Failed to register platform driver\n");
+
+ return ret;
+}
+
+static void __exit fsl_dce_exit(void)
+{
+ platform_driver_unregister(&fsl_dce_driver);
+}
+
+module_init(fsl_dce_init);
+module_exit(fsl_dce_exit);
+
+MODULE_AUTHOR("Jeffrey Ladouceur");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("FSL DCE driver");
+MODULE_VERSION(DRV_VERSION);
+
+/*
+ * These APIs are the only functional hooks into the control driver, besides the
+ * sysfs attributes.
+ */
+
+int fsl_dce_have_control(void)
+{
+ return global_dce_regs ? 1 : 0;
+}
+EXPORT_SYMBOL(fsl_dce_have_control);
+
+int fsl_dce_get_stat(enum fsl_dce_stat_attr attr, uint64_t *val, int reset)
+{
+ if (!fsl_dce_have_control())
+ return -ENODEV;
+
+ switch (attr) {
+ case DCE_COMP_INPUT_BYTES:
+ *val = ioread32be(&global_dce_regs->cibc_h);
+ *val <<= 32;
+ *val |= ioread32be(&global_dce_regs->cibc_l);
+ if (reset) {
+ iowrite32be(0, &global_dce_regs->cibc_l);
+ iowrite32be(0, &global_dce_regs->cibc_h);
+ }
+ break;
+ case DCE_COMP_OUTPUT_BYTES:
+ *val = ioread32be(&global_dce_regs->cobc_h);
+ *val <<= 32;
+ *val |= ioread32be(&global_dce_regs->cobc_l);
+ if (reset) {
+ iowrite32be(0, &global_dce_regs->cobc_l);
+ iowrite32be(0, &global_dce_regs->cobc_h);
+ }
+ break;
+ case DCE_DECOMP_INPUT_BYTES:
+ *val = ioread32be(&global_dce_regs->dibc_h);
+ *val <<= 32;
+ *val |= ioread32be(&global_dce_regs->dibc_l);
+ if (reset) {
+ iowrite32be(0, &global_dce_regs->dibc_l);
+ iowrite32be(0, &global_dce_regs->dibc_h);
+ }
+ break;
+ case DCE_DECOMP_OUTPUT_BYTES:
+ *val = ioread32be(&global_dce_regs->dobc_h);
+ *val <<= 32;
+ *val |= ioread32be(&global_dce_regs->dobc_l);
+ if (reset) {
+ iowrite32be(0, &global_dce_regs->dobc_l);
+ iowrite32be(0, &global_dce_regs->dobc_h);
+ }
+ break;
+ default:
+ pr_err("fsl_dce: Unknown attr %u\n", attr);
+ return -EINVAL;
+ };
+ return 0;
+}
+EXPORT_SYMBOL(fsl_dce_get_stat);
+
+int fsl_dce_clear_stat(enum fsl_dce_stat_attr attr)
+{
+ if (!fsl_dce_have_control())
+ return -ENODEV;
+
+ switch (attr) {
+ case DCE_COMP_INPUT_BYTES:
+ iowrite32be(0, &global_dce_regs->cibc_l);
+ iowrite32be(0, &global_dce_regs->cibc_h);
+ break;
+ case DCE_COMP_OUTPUT_BYTES:
+ iowrite32be(0, &global_dce_regs->cobc_l);
+ iowrite32be(0, &global_dce_regs->cobc_h);
+ break;
+ case DCE_DECOMP_INPUT_BYTES:
+ iowrite32be(0, &global_dce_regs->dibc_l);
+ iowrite32be(0, &global_dce_regs->dibc_h);
+ break;
+ case DCE_DECOMP_OUTPUT_BYTES:
+ iowrite32be(0, &global_dce_regs->dobc_l);
+ iowrite32be(0, &global_dce_regs->dobc_h);
+ break;
+ default:
+ pr_err("fsl_dce: Unknown attr %u\n", attr);
+ return -EINVAL;
+ };
+ return 0;
+}
+EXPORT_SYMBOL(fsl_dce_clear_stat);
+
+
diff --git a/drivers/staging/fsl_dce/dce_sys.c b/drivers/staging/fsl_dce/dce_sys.c
new file mode 100644
index 0000000..29ad636
--- /dev/null
+++ b/drivers/staging/fsl_dce/dce_sys.c
@@ -0,0 +1,273 @@
+/* Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * This software is provided by Freescale Semiconductor "as is" and any
+ * express or implied warranties, including, but not limited to, the implied
+ * warranties of merchantability and fitness for a particular purpose are
+ * disclaimed. In no event shall Freescale Semiconductor be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential damages
+ * (including, but not limited to, procurement of substitute goods or services;
+ * loss of use, data, or profits; or business interruption) however caused and
+ * on any theory of liability, whether in contract, strict liability, or tort
+ * (including negligence or otherwise) arising in any way out of the use of
+ * this software, even if advised of the possibility of such damage.
+ */
+
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include "flib/dce_defs.h"
+
+#define DRV_VERSION "0.1"
+
+MODULE_AUTHOR("Jeffrey Ladouceur");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("FSL DCE device usage");
+MODULE_VERSION(DRV_VERSION);
+
+static struct kmem_cache *slab_scr_64b;
+static struct kmem_cache *slab_scr_128b;
+static struct kmem_cache *slab_compress_history;
+static struct kmem_cache *slab_decompress_history;
+static struct kmem_cache *slab_pending_output;
+static struct kmem_cache *slab_decomp_ctxt;
+
+/*
+ * DCE hw dma memory requirements for stateful mode
+ * compression:
+ * scr: 64B size, 64B aligned
+ * history: 4096B size, 64B aligned
+ * pending_output: 8202B, 64B aligned optimal, recycle mode only.
+ *
+ * decompression:
+ * scr: 128B size, 64B aligned
+ * history: 32768b, 64b aligned
+ * pending_output: 8256b, 64b aligned optimal, recycle mode only
+ * decomp_ctx: 256b, 64b aligned optimal
+ */
+
+/* Hack to support "dce_map()". The point of this is that dma_map_single() now
+ * requires a non-NULL device, so the idea is that address mapping must be
+ * device-sensitive. Now the PAMU IO-MMU already takes care of this, as can be
+ * seen by the device-tree structure generated by the hypervisor (each portal
+ * node has sub-nodes for each h/w end-point it provides access to, and each
+ * sub-node has its own LIODN configuration). So we just need to map cpu
+ * pointers to (guest-)physical address and the PAMU takes care of the rest, so
+ * this doesn't need to be portal-sensitive nor device-sensitive. */
+static struct platform_device *pdev;
+
+static int dce_sys_init(void)
+{
+ int ret = -ENOMEM;
+
+ slab_scr_64b = kmem_cache_create("fsl_dce_scr_64b",
+ sizeof(struct scf_64b), /* 64 byte size */
+ DCE_SCR_ALIGN, SLAB_HWCACHE_ALIGN, NULL);
+ if (!slab_scr_64b)
+ goto end;
+
+ slab_scr_128b = kmem_cache_create("fsl_dce_scr_128b",
+ sizeof(struct scf_128b), /* 128 byte size */
+ DCE_SCR_ALIGN, SLAB_HWCACHE_ALIGN, NULL);
+ if (!slab_scr_64b)
+ goto end;
+ slab_compress_history = kmem_cache_create("fsl_dce_compress_history",
+ DCE_COMP_HISTORY_SIZE,
+ DCE_COMP_HISTORY_ALIGN, SLAB_HWCACHE_ALIGN, NULL);
+ if (!slab_compress_history)
+ goto end;
+ slab_decompress_history = kmem_cache_create(
+ "fsl_dce_decompress_history",
+ DCE_DECOMP_HISTORY_SIZE,
+ DCE_DECOMP_HISTORY_ALIGN, SLAB_HWCACHE_ALIGN, NULL);
+ if (!slab_decompress_history)
+ goto end;
+ slab_pending_output = kmem_cache_create("fsl_dce_pending_output",
+ DCE_PENDING_OUTPUT_SIZE, /* 8256 size */
+ DCE_PENDING_OUTPUT_ALIGN, SLAB_HWCACHE_ALIGN, NULL);
+ if (!slab_pending_output)
+ goto end;
+ slab_decomp_ctxt = kmem_cache_create("fsl_dce_decomp_ctxt",
+ DCE_DECOMP_CTXT_SIZE, /* 256 bytes */
+ DCE_DECOMP_CTXT_ALIGN, SLAB_HWCACHE_ALIGN, NULL);
+ if (!slab_decomp_ctxt)
+ goto end;
+
+ pdev = platform_device_alloc("dce", -1);
+ if (!pdev)
+ goto end;
+ if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(40)))
+ goto end;
+ if (platform_device_add(pdev))
+ goto end;
+
+ pr_info("dce_sys_init done!\n");
+ return 0;
+end:
+ if (pdev) {
+ platform_device_put(pdev);
+ pdev = NULL;
+ }
+ if (slab_scr_64b) {
+ kmem_cache_destroy(slab_scr_64b);
+ slab_scr_64b = NULL;
+ }
+ if (slab_scr_128b) {
+ kmem_cache_destroy(slab_scr_128b);
+ slab_scr_128b = NULL;
+ }
+ if (slab_compress_history) {
+ kmem_cache_destroy(slab_compress_history);
+ slab_compress_history = NULL;
+ }
+ if (slab_decompress_history) {
+ kmem_cache_destroy(slab_decompress_history);
+ slab_decompress_history = NULL;
+ }
+ if (slab_pending_output) {
+ kmem_cache_destroy(slab_pending_output);
+ slab_pending_output = NULL;
+ }
+ if (slab_decomp_ctxt) {
+ kmem_cache_destroy(slab_decomp_ctxt);
+ slab_decomp_ctxt = NULL;
+ }
+ pr_err("DCE: dce_sys_init failed\n");
+ return ret;
+}
+
+static void dce_sys_exit(void)
+{
+ platform_device_del(pdev);
+ platform_device_put(pdev);
+ pdev = NULL;
+ kmem_cache_destroy(slab_scr_64b);
+ kmem_cache_destroy(slab_scr_128b);
+ kmem_cache_destroy(slab_compress_history);
+ kmem_cache_destroy(slab_decompress_history);
+ kmem_cache_destroy(slab_pending_output);
+ kmem_cache_destroy(slab_decomp_ctxt);
+}
+
+module_init(dce_sys_init);
+module_exit(dce_sys_exit);
+
+/**************************/
+/* system level functions */
+/**************************/
+struct fsl_dce_hw_scr_64b *fsl_dce_hw_scr_64b_new(void)
+{
+ return kmem_cache_zalloc(slab_scr_64b, GFP_KERNEL);
+}
+EXPORT_SYMBOL(fsl_dce_hw_scr_64b_new);
+
+void fsl_dce_hw_scr_64b_free(struct fsl_dce_hw_scr_64b *p)
+{
+ kmem_cache_free(slab_scr_64b, p);
+}
+EXPORT_SYMBOL(fsl_dce_hw_scr_64b_free);
+
+struct fsl_dce_hw_scr_128b *fsl_dce_hw_scr_128b_new(void)
+{
+ return kmem_cache_zalloc(slab_scr_128b, GFP_KERNEL);
+}
+EXPORT_SYMBOL(fsl_dce_hw_scr_128b_new);
+
+void fsl_dce_hw_scr_128b_free(struct fsl_dce_hw_scr_128b *p)
+{
+ kmem_cache_free(slab_scr_128b, p);
+}
+EXPORT_SYMBOL(fsl_dce_hw_scr_128b_free);
+
+struct fsl_dce_hw_compress_history *fsl_dce_hw_compress_history_new(void)
+{
+ return kmem_cache_zalloc(slab_compress_history, GFP_KERNEL);
+}
+EXPORT_SYMBOL(fsl_dce_hw_compress_history_new);
+
+void fsl_dce_hw_compress_history_free(struct fsl_dce_hw_compress_history *p)
+{
+ kmem_cache_free(slab_compress_history, p);
+}
+EXPORT_SYMBOL(fsl_dce_hw_compress_history_free);
+
+struct fsl_dce_hw_decompress_history *fsl_dce_hw_decompress_history_new(void)
+{
+ return kmem_cache_zalloc(slab_decompress_history, GFP_KERNEL);
+}
+EXPORT_SYMBOL(fsl_dce_hw_decompress_history_new);
+
+void fsl_dce_hw_decompress_history_free(struct fsl_dce_hw_decompress_history *p)
+{
+ kmem_cache_free(slab_decompress_history, p);
+}
+EXPORT_SYMBOL(fsl_dce_hw_decompress_history_free);
+
+struct fsl_dce_hw_pending_output *fsl_dce_hw_pending_output_new(void)
+{
+ return kmem_cache_zalloc(slab_pending_output, GFP_KERNEL);
+}
+EXPORT_SYMBOL(fsl_dce_hw_pending_output_new);
+
+void fsl_dce_hw_pending_output_free(struct fsl_dce_hw_pending_output *p)
+{
+ kmem_cache_free(slab_pending_output, p);
+}
+EXPORT_SYMBOL(fsl_dce_hw_pending_output_free);
+
+struct fsl_dce_hw_decomp_ctxt *fsl_dce_hw_decomp_ctxt_new(void)
+{
+ return kmem_cache_zalloc(slab_decomp_ctxt, GFP_KERNEL);
+}
+EXPORT_SYMBOL(fsl_dce_hw_decomp_ctxt_new);
+
+void fsl_dce_hw_decomp_ctxt_free(struct fsl_dce_hw_decomp_ctxt *p)
+{
+ kmem_cache_free(slab_decomp_ctxt, p);
+}
+EXPORT_SYMBOL(fsl_dce_hw_decomp_ctxt_free);
+
+dma_addr_t fsl_dce_map(void *ptr)
+{
+ return dma_map_single(&pdev->dev, ptr, 1, DMA_BIDIRECTIONAL);
+}
+EXPORT_SYMBOL(fsl_dce_map);
+
+void fsl_dce_unmap(dma_addr_t handle)
+{
+ dma_unmap_single(&pdev->dev, handle, 1, DMA_BIDIRECTIONAL);
+}
+EXPORT_SYMBOL(fsl_dce_unmap);
+
+struct device *fsl_dce_get_device(void)
+{
+ if (!pdev)
+ return NULL;
+ return &pdev->dev;
+}
+EXPORT_SYMBOL(fsl_dce_get_device);
+
+int fsl_dce_map_error(dma_addr_t dma_addr)
+{
+ return dma_mapping_error(&pdev->dev, dma_addr);
+}
+EXPORT_SYMBOL(fsl_dce_map_error);
+
diff --git a/drivers/staging/fsl_dce/dce_sys.h b/drivers/staging/fsl_dce/dce_sys.h
new file mode 100644
index 0000000..b3ef730
--- /dev/null
+++ b/drivers/staging/fsl_dce/dce_sys.h
@@ -0,0 +1,68 @@
+/* Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * This software is provided by Freescale Semiconductor "as is" and any
+ * express or implied warranties, including, but not limited to, the implied
+ * warranties of merchantability and fitness for a particular purpose are
+ * disclaimed. In no event shall Freescale Semiconductor be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential damages
+ * (including, but not limited to, procurement of substitute goods or services;
+ * loss of use, data, or profits; or business interruption) however caused and
+ * on any theory of liability, whether in contract, strict liability, or tort
+ * (including negligence or otherwise) arising in any way out of the use of
+ * this software, even if advised of the possibility of such damage.
+ */
+
+#ifndef DCE_SYS_H
+#define DCE_SYS_H
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/bootmem.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/of_platform.h>
+#include <linux/kthread.h>
+#include <linux/memblock.h>
+#include <linux/completion.h>
+#include <linux/log2.h>
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/device.h>
+#include <linux/uio_driver.h>
+#include <linux/smp.h>
+#include <sysdev/fsl_soc.h>
+#include <linux/fsl_hypervisor.h>
+#include <linux/fsl_bman.h>
+
+dma_addr_t fsl_dce_map(void *ptr);
+void fsl_dce_unmap(dma_addr_t handle);
+int fsl_dce_map_error(dma_addr_t dma_addr);
+struct device *fsl_dce_get_device(void);
+
+#endif
diff --git a/drivers/staging/fsl_dce/flib/bitfield_macros.h b/drivers/staging/fsl_dce/flib/bitfield_macros.h
new file mode 100644
index 0000000..0a52bf1
--- /dev/null
+++ b/drivers/staging/fsl_dce/flib/bitfield_macros.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ */
+
+#ifndef FL_BITFIELD_MACROS_H
+#define FL_BITFIELD_MACROS_H
+
+/*
+ * macro to generate a field. This field can be part of a register or other
+ * defined structure
+ */
+#define FL_FGEN(field, value) \
+ (((value) << field##_SHIFT) & field##_MASK)
+
+/* macro which generates field based on a token value */
+#define FL_FGENTK(field, token) \
+ FL_FGEN(field, field##_##token)
+
+/**
+ * SET_BFXX(v, m, x) - Returns the result of setting value [x] into bit
+ * field [m] of value [v]
+ *
+ * [m] identifies the bit field and it is assumed that there exists
+ * two macros: m_MASK and m_SHIFT. The former contains the bit mask;
+ * the latter contains the number of least-significant zero bits in
+ * the mask.
+ * XX idenfies the width of the value and destination
+ *
+ * _IDX is a variant where a this idenfies an index into a array. The
+ * macros expects a define of field_XXIDX to be defined where XX is inline
+ * with the XX type (8, 16, 32, 64). This is useful when using dma stuctures.
+ */
+#define SET_BF64(dest, field, value) \
+ (dest = \
+ ((dest & ~field##_MASK) | (((uint64_t)value << field##_SHIFT) & \
+ field##_MASK)))
+
+#define SET_BF64_IDX(dest, field, value) \
+ ((*(dest+field##_64IDX)) = \
+ (((*(dest+field##_64IDX)) & ~field##_MASK) | \
+ (((value) << field##_SHIFT) & field##_MASK)))
+
+#define SET_BF64_TK(dest, field, token) \
+ (dest = \
+ ((dest & ~field##_MASK) | ((field##_##token << field##_SHIFT) & \
+ field##_MASK)))
+
+#define SET_BF64_TK_IDX(dest, field, token) \
+ ((*(dest+field##_64IDX)) = \
+ (((*(dest+field##_64IDX)) & ~field##_MASK) | \
+ ((field##_##token << field##_SHIFT) & field##_MASK)))
+
+#define SET_BF32(dest, field, value) \
+ (dest = \
+ ((dest & ~field##_MASK) | ((value << field##_SHIFT) & field##_MASK)))
+
+#define SET_BF32_IDX(dest, field, value) \
+ ((*(dest+field##_32IDX)) = \
+ (((*(dest+field##_32IDX)) & ~field##_MASK) | \
+ ((value << field##_SHIFT) & field##_MASK)))
+
+#define SET_BF32_TK(dest, field, token) \
+ (dest = \
+ ((dest & ~field##_MASK) | ((field##_##token << field##_SHIFT) & \
+ field##_MASK)))
+
+#define SET_BF32_TK_IDX(dest, field, token) \
+ ((*(dest+field##_32IDX)) = \
+ (((*(dest+field##_32IDX)) & ~field##_MASK) | \
+ ((field##_##token << field##_SHIFT) & field##_MASK)))
+
+#define SET_BF16(dest, field, value) \
+ (dest = \
+ ((dest & ~field##_MASK) | ((value << field##_SHIFT) & field##_MASK)))
+
+#define SET_BF16_IDX(dest, field, value) \
+ ((*(dest+field##_16IDX)) = \
+ (((*(dest+field##_16IDX)) & ~field##_MASK) | \
+ ((value << field##_SHIFT) & field##_MASK)))
+
+#define SET_BF16_TK(dest, field, token) \
+ (dest = \
+ ((dest & ~field##_MASK) | ((field##_##token << field##_SHIFT) & \
+ field##_MASK)))
+
+#define SET_BF16_TK_IDX(dest, field, token) \
+ ((*(dest+field##_16IDX)) = \
+ (((*(dest+field##_16IDX)) & ~field##_MASK) | \
+ ((field##_##token << field##_SHIFT) & field##_MASK)))
+
+#define SET_BF8(dest, field, value) \
+ (dest = \
+ ((dest & ~field##_MASK) | ((value << field##_SHIFT) & field##_MASK)))
+
+#define SET_BF8_IDX(dest, field, value) \
+ ((*(dest+field##_8IDX)) = \
+ (((*(dest+field##_8IDX)) & ~field##_MASK) | \
+ ((value << field##_SHIFT) & field##_MASK)))
+
+#define SET_BF8_TK(dest, field, token) \
+ (dest = \
+ ((dest & ~field##_MASK) | ((field##_##token << field##_SHIFT) & \
+ field##_MASK)))
+
+#define SET_BF8_TK_IDX(dest, field, token) \
+ ((*(dest+field##_8IDX)) = \
+ (((*(dest+field##_8IDX)) & ~field##_MASK) | \
+ ((field##_##token << field##_SHIFT) & field##_MASK)))
+
+/**
+ * GET_BF(v, m) - Gets the value in bit field [m] of expression [v]
+ *
+ * [m] identifies the bit field and it is assumed that there exists
+ * two macros: m_MASK and m_SHIFT. The former contains the bit mask;
+ * the latter contains the number of least-significant zero bits in
+ * the mask.
+ */
+#define GET_BF64(source, field) \
+ ((source & field##_MASK) >> field##_SHIFT)
+
+#define GET_BF64_IDX(source, field) \
+ (((*(source+field##_64IDX)) & field##_MASK) >> field##_SHIFT)
+
+#define GET_BF32(source, field) \
+ ((source & field##_MASK) >> field##_SHIFT)
+
+#define GET_BF32_IDX(source, field) \
+ (((*(source+field##_32IDX)) & field##_MASK) >> field##_SHIFT)
+
+#define GET_BF16(source, field) \
+ ((source & field##_MASK) >> field##_SHIFT)
+
+#define GET_BF16_IDX(source, field) \
+ (((*(source+field##_16IDX)) & field##_MASK) >> field##_SHIFT)
+
+#define GET_BF8(source, field) \
+ ((source & field##_MASK) >> field##_SHIFT)
+
+#define GET_BF8_IDX(source, field) \
+ (((*(source+field##_8IDX)) & field##_MASK) >> field##_SHIFT)
+
+/* Register field is-equal based on token (enum) */
+#define ISEQ_32FTK(source, reg_field, token) \
+ (GET_BF32((source), reg_field) == reg_field##_##token)
+
+#endif /* FL_BITFIELD_MACROS */
diff --git a/drivers/staging/fsl_dce/flib/dce_defs.h b/drivers/staging/fsl_dce/flib/dce_defs.h
new file mode 100644
index 0000000..7ccb69d
--- /dev/null
+++ b/drivers/staging/fsl_dce/flib/dce_defs.h
@@ -0,0 +1,1924 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ */
+
+#ifndef FL_DCE_DEFS_H
+#define FL_DCE_DEFS_H
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <stdint.h>
+#include <stdbool.h>
+#endif
+
+#include "bitfield_macros.h"
+
+/*
+ * Some interfaces depend on the revision of the DCE HW block. An external
+ * dependency has been added which requires this external variable to be
+ * set accordingly. If the variable is not set, the interfaces will behave
+ * as if the revision is DCE_DEFAULT_REV.
+ */
+extern uint16_t dce_ip_rev;
+#define DCE_REV10 0x0100
+#define DCE_REV11 0x0101
+#define DCE_DEFAULT_REV DCE_REV10
+
+/*
+ * QMan defines the dedicated channels serviced by the DCE engine. The first
+ * channel is serviced by compression engine while the second channel is
+ * is serviced by the decompression engine.
+ */
+#define DCE_COMPRESSION_CHANNEL_OFFSET 0
+#define DCE_DECOMPRESSION_CHANNEL_OFFSET 1
+
+/**
+ * struct dce_context_a - context_a field of the qm_fqd for rx frame queue. The
+ * rx frame queue is in the sw portal to dce hw direction.
+ *
+ * @d64: contains mask of following values:
+ *
+ * TSIZE: size of BMan buffers used to create s/g tables, each table entry
+ * being 16 bytes in size.
+ * DEXP: Specifies the exponent part of BMan buffer size used to output data
+ * using DBPID. All values (0x0 to 0xF) are valid. A coding of 0x0 is
+ * treated as 0x10, so exponent values 1 to 16 are possible.
+ * DMANT: Specifies the mantissa part of BMan buffer size used to output data
+ * using DBPID. All values (0x0 to 0xF) are valid. A coding of 0x0 is
+ * treated as 0x10, so mantissa values 1 to 16 are possible.
+ * TBPID: Indicates which BMan buffer pool is to be used to create
+ * scatter/gather tables. Typically this will indicate a pool of buffers
+ * that are smaller in size than the buffers used to store Frame data.
+ * SCRP: The upper bits of a 40-bit memory pointer to the SCR
+ * The lower bits are presumed to be 0 as the record must be device
+ * virtual address aligned on a 64B address boundary in system memory.
+ */
+struct dce_context_a {
+ uint64_t d64;
+/* TSIZE */
+#define DCE_CONTEXT_A_TSIZE_SHIFT 60
+#define DCE_CONTEXT_A_TSIZE_MASK (0x7ULL << DCE_CONTEXT_A_TSIZE_SHIFT)
+
+/* DEXP */
+#define DCE_CONTEXT_A_DEXP_SHIFT 56
+#define DCE_CONTEXT_A_DEXP_MASK (0xfULL << DCE_CONTEXT_A_DEXP_SHIFT)
+
+/* DMANT*/
+#define DCE_CONTEXT_A_DMANT_SHIFT 52
+#define DCE_CONTEXT_A_DMANT_MASK (0xfULL << DCE_CONTEXT_A_DMANT_SHIFT)
+
+/* TBPID */
+#define DCE_CONTEXT_A_TBPID_SHIFT 40
+#define DCE_CONTEXT_A_TBPID_MASK (0xffULL << DCE_CONTEXT_A_TBPID_SHIFT)
+
+/* SCRP */
+#define DCE_CONTEXT_A_SCRP_SHIFT 6
+#define DCE_CONTEXT_A_SCRP_MASK (0x3ffffffffULL << DCE_CONTEXT_A_SCRP_SHIFT)
+};
+
+/**
+ * dce_context_a_set_scrp - Set SCRP in context_a field
+ *
+ * @ctxa: a dce_context_a structure
+ * @val: Value to set the scrp field to.
+ */
+static inline void dce_context_a_set_scrp(struct dce_context_a *ctx_a,
+ uint64_t val)
+{
+ /* lower 6 bits expected to be zero, since 64 byte aligned */
+ SET_BF64(ctx_a->d64, DCE_CONTEXT_A_SCRP,
+ (val >> DCE_CONTEXT_A_SCRP_SHIFT));
+}
+
+/**
+ * dce_context_a_get_scrp - Get SCRP in context_a field
+ *
+ * @ctxa: a dce_context_a structure
+ */
+static inline uint64_t dce_context_a_get_scrp(struct dce_context_a *ctx_a)
+{
+ /* lower 6 bits expected to be zero, since 64 byte aligned */
+ return GET_BF64(ctx_a->d64, DCE_CONTEXT_A_SCRP) <<
+ DCE_CONTEXT_A_SCRP_SHIFT;
+}
+
+/**
+ * struct dce_context_b - context_b field of the qm_fqd for tx frame queue.
+ * contains data buffer pool id and rx fq id. The tx frame queue is in the
+ * dce hw -> sw portal direction.
+ *
+ * @d32: contains mask of following values:
+ *
+ * DBPID: Indicates which BMan pool is to be used to create data buffers
+ * (not scatter/gather tables) in output Frames.
+ * FQID: DCE output Frames for this Frame Queue pair (Flow) are enqueued on
+ * this FQID
+ */
+struct dce_context_b {
+ uint32_t d32;
+/* DBPID */
+#define DCE_CONTEXT_B_DBPID_SHIFT 24
+#define DCE_CONTEXT_B_DBPID_MASK (0xffUL << DCE_CONTEXT_B_DBPID_SHIFT)
+
+/* FQID */
+#define DCE_CONTEXT_B_FQID_SHIFT 0
+#define DCE_CONTEXT_B_FQID_MASK (0xffffffUL << DCE_CONTEXT_B_FQID_SHIFT)
+};
+
+/**
+ * struct dce_cmd - 32-bit frame descritor "cmd/status" field, sent to DCE
+ *
+ * @d32: mask of command and associated parameters. The bit fields depend
+ * on the value of the CMD.
+ *
+ * The DCE_CMD_*** field identifies the command type.
+ * @DCE_CMD_PROCESS: invokes DCE's misison mode operation. It
+ * indicates to DCE hardware that the provided Frame is to
+ * be processed according to the mode of its Frame Queue
+ * channel (compression vs decompression) and the Frame's
+ * associated Stream Context Record, and/or a Stream
+ * Configuration Frame.
+ * @DCE_CMD_CTX_INVALIDATE: provides a means to invalidate a cached
+ * copy of a Stream Context Record in the DCE hardware.
+ * Only application on stateful stream.
+ * @DCE_CMD_NOP: a frame with this command travel through the DCE's
+ * pipeline without causing any system memory accesses or
+ * other side effects.
+ *
+ * Additiona fields depend on value of DCE_CMD_***
+ * -----------------------------------------
+ * DCE_CMD_NOP DCE_NOP_TOKEN
+ * The token is not processed by the DCE and is
+ * echoed back in the returned frame.
+ *
+ * DCE_CMD_CTX_INVALIDATE DCE_CIC_TOKEN
+ * The token is not processed by the DCE
+ * and is echoed back in the returned
+ * Frame.
+ *
+ * DCE_CMD_PROCESS DCE_PROCESS_OO_***
+ * Coded value specifying the number of unused
+ * bytes to leave at the beginning of the first
+ * buffer of the output Frame, if it is being
+ * created out of BMan buffers. Note that software
+ * must ensure that non-zero offset values remain
+ * within the size of BMan buffers being used for
+ * the flow. A value that is greater than or equal
+ * to the buffer size will result in an Output
+ * Offset Too Large exception.
+ * DCE_PROCESS_Z_***
+ * Support for zlib flush semantics
+ *
+ * @DCE_PROCESS_Z_NO_FLUSH: Normal value for flush
+ * @DCE_PROCESS_Z_PARTIAL_FLUSH: Pending output is
+ * flushed, output not aligned.
+ * @DCE_PROCESS_Z_SYNC_FLUSH: Pending output is
+ * flushed, output is aligned.
+ * @DCE_PROCESS_Z_FULL_FLUSH: All output is flushed
+ * and state reset.
+ * @DCE_PROCESS_Z_FINISH: All pending input is
+ * processed and all output is flushed
+ * @DCE_PROCESS_Z_BLOCK: A compressed block is
+ * completed and emitted, as with
+ * DCE_PROCESS_Z_SYNC_FLUSH, but the output
+ * is not necessarily aligned on a byte
+ * boundary, and up to 7 bits of the
+ * current block are held to be written as
+ * the next byte when the next DEFLATE
+ * block is completed
+ * @DCE_PROCESS_Z_TREES: For decompression, the
+ * DCE_PROCESS_Z_TREES option behaves as
+ * DCE_PROCESS_Z_BLOCK does, but also
+ * returns after the end of each DEFLATE
+ * block header before any data in the
+ * block itself is decoded, allowing the
+ * caller to determine the length of the
+ * DEFLATE block header for later use in
+ * random access within a DEFLATE block.
+ * DCE_PROCESS_SCRF
+ * When set, forces DCE to flush the updated Stream
+ * Context Record to system memory once the Frame
+ * is processed. DCE also invalidates its internal
+ * copy of the Stream Context Record so that it
+ * must be read from system memory before
+ * processing a subsequent Frame on the same
+ * Stream. Note that this is independent of the
+ * Frame data flushing behavior that is controlledi
+ * by the DCE_Z_FLUSH field.
+ * DCE_PROCESS_RECYCLED
+ * Indicates that this Frame is being recycled to
+ * DCE following a previous Output Blocked Suspend
+ * or Acquire Data Buffer Denied Suspend exception.
+ * DCE_PROCESS_INITIAL
+ * When set, indicates that this Frame is
+ * considered to be the first, and possibly only,
+ * Frame of data in the Stream. DCE will disregard
+ * any stale Frame data pointers and residue data
+ * values in the Stream Context Record and
+ * initialize the Stream Context Record prior to
+ * processing the Frame(1). The following Stream
+ * Context Record fields are initialized as
+ * indicated:
+ * TOTAL_IN, TOTAL_OUT, ADLER32 zeroed (2)
+ * XO, NO, and CO zeroed
+ * XLEN, NLEN, and CLEN zeroed
+ * (decompression Flows only)
+ * PENDING_OUTPUT_LEN zeroed
+ * HISTORY_LEN zeroed
+ * RBC zeroed
+ * CRC16 zeroed
+ * HUFFMAN_RBC zeroed
+ * B64_RESIDUE_LEN zeroed
+ * HEADER_REMAINING zeroed
+ * Note that a set I bit does not have any effect
+ * on the Stream Context Record if the Flow is
+ * suspended. A frame received with I=1 on a
+ * suspended flow will either be skipped or
+ * treated as a recycled frame depending on the
+ * value of the Frame’s R bit. On stateless Flows
+ * this flag is ignored (DCE behaves as though I=1
+ * for every Frame).
+ *
+ * (1) Stream Context Record initialization does
+ * not happen when an initial (I=1) Frame is
+ * recycled (R=1) due to a previous exception, DCE
+ * will continue processing of the Frame based on
+ * existing context as it would for any recycled
+ * Frame. Further, an Initial Frame received on a
+ * suspended flow that does not have its recycle
+ * bit set (R=0) will be skipped (i.e. an I=1
+ * Frame does not clear the SUSP bit).
+ *
+ * (2) Unless DCE_PROCESS_USDC is also set, in
+ * which case the DCE_PROCESS_USDC function takes
+ * precedence over the set DCE_PROCESS_INITIAL bit.
+ * DCE_PROCESS_RB
+ * Specifies that the input Frame buffers are to be
+ * released to BMan once their data bytes have been
+ * fully processed.
+ * DCE_PROCESS_B64
+ * Set to indicate that data in this Frame is to be
+ * Base64 encoded following compression, or Base64
+ * decoded prior to decompression.
+ * DCE_PROCESS_CF_***
+ * Specifies the data format to be used for
+ * compressing this Frame (compression Flow) or the
+ * format of the compressed data present in this
+ * Frame (decompression Flow).
+ * This field must remain consistent (keep the same
+ * value) across multiple Frames (chunks) of a
+ * single file within a stateful Flow.
+ *
+ * @DCE_DEFLATE: Format is DEFLATE as defined in
+ * RFC 1951
+ * @DCE_ZLIB: Format is ZLIB as defined in RFC 1950
+ * @DCE_GZIP: Format is GXIP as defined in RFC 1952
+ * DCE_PROCESS_CE_***
+ * Specifies the type of compression to be
+ * performed on this Stream. This field is ignored
+ * on decompress Flows.
+ * This field must remain consistent (keep the same
+ * value) across multiple Frames (chunks) of a
+ * single file within a stateful Flow.
+ *
+ * @DCE_CE_NONE: No compression
+ * @DCE_CE_STATIC_HUFF_STRMATCH: Static Huffman
+ * coding and string matching only
+ * @DCE_CE_HUFF_ONLY: Huffman only (static or
+ * dynamic, but no string matching).
+ * @DCE_CE_BEST_POSSIBLE: Best possible compression
+ * (static or dynamic Huffman coding may
+ * result).
+ * DCE_PROCESS_UHC
+ * Update Header Context
+ * On stateful Flows, instructs the DCE to update
+ * the Flow’s Stream Context Record’s protocol
+ * header fields with the values found in the
+ * dequeued Frame’s Stream Configuration Frame.
+ * DCE will update the following Stream Context
+ * Record header fields:
+ * ID1, ID2
+ * CM
+ * FLG
+ * MTIME
+ * XFL
+ * OS
+ * XLEN
+ * NLEN
+ * CLEN
+ * EXTRA_LIMIT and EXTRA_PTR
+ * Some or all of these context fields may not be
+ * used depending on the DCE_PROCESS_CF field
+ * setting in the individual Frames that arrive on
+ * the Flow, but all are updated. On stateless
+ * Flows, this flag is ignored and the appropriate
+ * values from the Stream Configuration Frame are
+ * used unconditionally according to the
+ * DCE_PROCESS_CF field.
+ * DCE_PROCESS_USPC
+ * Update Stream Processing Context. Instructs the
+ * DCE to update the following Stream Context
+ * Record fields with the values found in the
+ * Stream Configuration Frame, or zero them as
+ * indicated:
+ * XO, NO, and CO zeroed
+ * PENDING_OUTPUT_PTR updated
+ * PENDING_OUTPUT_LEN zeroed
+ * HISTORY_PTR updated, HISTORY_LEN zeroed
+ * PMODE updated
+ * SUSP zeroed
+ * RBC zeroed
+ * DECOMP_CTXT_PTR updated
+ * CRC16 zeroed
+ * HUFFMAN_RBC zeroed
+ * B64_RESIDUE_LEN zeroed
+ * HEADER_REMAINING zeroed.
+ * DCE_PROCESS_USDC
+ * Update Stream Data Context
+ * Instructs the DCE to update the following fields
+ * in the Stream Context Record with the value
+ * found in the Stream Configuration Frame prior to
+ * processing the dequeued Frame:
+ * TOTAL_IN
+ * TOTAL_OUT
+ * ADLER32
+ * This bit is included to maintain full zlib
+ * compatibility such that Software is able to
+ * update/modify the incremental total_in,
+ * total_out, and adler32 values (in the z_stream
+ * struct) between inflate() and deflate() calls.
+ * This bit should normally be left unset.
+ * Software should not normally need to modify the
+ * incremental values in these fields between
+ * Frames of a larger entity on a stateful Flow.
+ * DCE_PROCESS_SCUS_***
+ * Stream Configuration Update Select
+ * This field specifies how the DCE performs
+ * updates (writes) to the output Stream
+ * Configuration Frame after processing the
+ * dequeued Frame. SCUS settings only apply when
+ * compound Frames containing a valid (non-null)
+ * Stream Configuration Frame member are used.
+ * The field has no effect for simple Frames or
+ * compound Frames in which the Stream
+ * Configuration Frame member is null.
+ *
+ * @DCE_PROCESS_SCUS_NORMAL_MODE:
+ * Stream Context Recor updated, Stream
+ * Configuration Frame not updated except
+ * in cases of Output Blocked Suspend or
+ * Acquire Data Buffer Denied Suspend
+ * exceptions3. This is the expected
+ * mission mode setting.
+ * @DCE_PROCESS_SCUS_UPDATE:
+ * Stream Context Record updated, Stream
+ * Configuration Frame updated partially.
+ * Note that captured header information
+ * may be partial until the entire header
+ * has been processed.
+ * @DCE_SCUS_UPDATE_DEBUG:
+ * Stream Context Record updated, Stream
+ * Configuration Frame updated with a
+ * Stream Context Record snapshot. This
+ * setting exposes Stream Context Record
+ * updates by shadowing them in the Stream
+ * Configuration Frame, enabling debug.
+
+ * DCE_PROCESS_STATUS
+ * This is of type enum dce_status. This value
+ * is set on the output fd received from the DCE.
+ */
+struct dce_cmd {
+ uint32_t d32;
+/* Common to all commands */
+#define DCE_CMD_SHIFT 29
+#define DCE_CMD_MASK (0x7UL << DCE_CMD_SHIFT)
+/* CMD Tokens */
+#define DCE_CMD_PROCESS 0x0UL
+#define DCE_CMD_CTX_INVALIDATE 0x4UL
+#define DCE_CMD_NOP 0x7UL
+
+/* NOP Input command */
+#define DCE_NOP_TOKEN_SHIFT 0
+#define DCE_NOP_TOKEN_MASK (0x1fffffffUL << DCE_NOP_TOKEN_SHIFT)
+
+/* Context Invalidate Command Input command */
+#define DCE_CIC_TOKEN_SHIFT 0
+#define DCE_CIC_TOKEN_MASK (0x1fffffffUL << DCE_CIC_TOKEN_SHIFT)
+
+/* Process Input command */
+/* Output Offset */
+#define DCE_PROCESS_OO_SHIFT 26
+#define DCE_PROCESS_OO_MASK (0x7UL << DCE_PROCESS_OO_SHIFT)
+/* Output Offset Tokens */
+#define DCE_PROCESS_OO_NONE_LONG 0x0UL
+#define DCE_PROCESS_OO_32B 0x1UL
+#define DCE_PROCESS_OO_64B 0x2UL
+#define DCE_PROCESS_OO_128B 0x3UL
+#define DCE_PROCESS_OO_256B 0x4uL
+#define DCE_PROCESS_OO_512B 0x5UL
+#define DCE_PROCESS_OO_1024B 0x6UL
+#define DCE_PROCESS_OO_NON_SHORT 0x7UL
+/* Z_FLUSH */
+#define DCE_PROCESS_Z_FLUSH_SHIFT 23
+#define DCE_PROCESS_Z_FLUSH_MASK (0x7UL << DCE_PROCESS_Z_FLUSH_SHIFT)
+/* Z_FLUSH Tokens */
+#define DCE_PROCESS_Z_FLUSH_NO_FLUSH 0x0UL
+#define DCE_PROCESS_Z_FLUSH_PARTIAL_FLUSH 0x1UL
+#define DCE_PROCESS_Z_FLUSH_SYNC_FLUSH 0x2UL
+#define DCE_PROCESS_Z_FLUSH_FULL_FLUSH 0x3UL
+#define DCE_PROCESS_Z_FLUSH_FINISH 0x4UL
+#define DCE_PROCESS_Z_FLUSH_BLOCK 0x5UL
+#define DCE_PROCESS_Z_FLUSH_TREES 0x6UL
+
+#define DCE_PROCESS_SCRF_SHIFT 22
+#define DCE_PROCESS_SCRF_MASK (0x1UL << DCE_PROCESS_SCRF_SHIFT)
+/* SCRF Tokens */
+#define DCE_PROCESS_SCRF_SET 0x1UL
+#define DCE_PROCESS_SCRF_CLEAR 0x0UL
+
+#define DCE_PROCESS_RECYCLED_SHIFT 21
+#define DCE_PROCESS_RECYCLED_MASK (0x1UL << DCE_PROCESS_RECYCLED_SHIFT)
+/* Recycle Tokens */
+#define DCE_PROCESS_RECYCLED_SET 0x1UL
+#define DCE_PROCESS_RECYCLED_CLEAR 0x0UL
+
+#define DCE_PROCESS_INITIAL_SHIFT 20
+#define DCE_PROCESS_INITIAL_MASK (0x1UL << DCE_PROCESS_INITIAL_SHIFT)
+/* Initial Tokens */
+#define DCE_PROCESS_INITIAL_SET 0x1UL
+#define DCE_PROCESS_INITIAL_CLEAR 0x0UL
+
+#define DCE_PROCESS_RB_SHIFT 19
+#define DCE_PROCESS_RB_MASK (0x1UL << DCE_PROCESS_RB_SHIFT)
+/* Release Buffers Tokens */
+#define DCE_PROCESS_RB_YES 0x1UL
+#define DCE_PROCESS_RB_NO 0x0UL
+
+#define DCE_PROCESS_B64_SHIFT 18
+#define DCE_PROCESS_B64_MASK (0x1UL << DCE_PROCESS_B64_SHIFT)
+/* Is Base64 encoding Tokens */
+#define DCE_PROCESS_B64_YES 0x1UL
+#define DCE_PROCESS_B64_NO 0x0UL
+
+/* Compression Format */
+#define DCE_PROCESS_CF_SHIFT 16
+#define DCE_PROCESS_CF_MASK (0x3UL << DCE_PROCESS_CF_SHIFT)
+/* CF Tokesn */
+#define DCE_PROCESS_CF_DEFLATE 0x0UL
+#define DCE_PROCESS_CF_ZLIB 0x1UL
+#define DCE_PROCESS_CF_GZIP 0x2UL
+
+/* Compression Effort */
+#define DCE_PROCESS_CE_SHIFT 13
+#define DCE_PROCESS_CE_MASK (0x3UL << DCE_PROCESS_CE_SHIFT)
+/* CE Tokens */
+#define DCE_PROCESS_CE_NONE 0x0UL
+#define DCE_PROCESS_CE_STATIC_HUFF_STRMATCH 0x1UL
+#define DCE_PROCESS_CE_HUFF_ONLY 0x2UL
+#define DCE_PROCESS_CE_BEST_POSSIBLE 0x3UL
+
+/* UHC, USPC, and USDC are ignored for stateless flows */
+#define DCE_PROCESS_UHC_SHIFT 12
+#define DCE_PROCESS_UHC_MASK (0x1UL << DCE_PROCESS_UHC_SHIFT)
+/* Update Header Context Request Tokens */
+#define DCE_PROCESS_UHC_YES 0x1UL
+#define DCE_PROCESS_UHC_NO 0x0UL
+
+#define DCE_PROCESS_USPC_SHIFT 11
+#define DCE_PROCESS_USPC_MASK (0x1UL << DCE_PROCESS_USPC_SHIFT)
+/* Update Stream Processing Context Request Tokens */
+#define DCE_PROCESS_USPC_YES 0x1UL
+#define DCE_PROCESS_USPC_NO 0x0UL
+
+#define DCE_PROCESS_USDC_SHIFT 10
+#define DCE_PROCESS_USDC_MASK (0x1UL << DCE_PROCESS_USDC_SHIFT)
+/* Update Stream Data Context Request Tokens */
+#define DCE_PROCESS_USDC_YES 0x1UL
+#define DCE_PROCESS_USDC_NO 0x0UL
+
+/* Stream Configuration Update Select */
+#define DCE_PROCESS_SCUS_SHIFT 8
+#define DCE_PROCESS_SCUS_MASK (0x3UL << DCE_PROCESS_SCUS_SHIFT)
+/* SCUS Tokens */
+#define DCE_PROCESS_SCUS_NORMAL_MODE 0x0UL
+#define DCE_PROCESS_SCUS_UPDATE 0x1UL
+#define DCE_PROCESS_SCUS_UPDATE_DEBUG 0x2UL
+
+/* On output there is a Command Status */
+#define DCE_PROCESS_STATUS_SHIFT 0
+#define DCE_PROCESS_STATUS_MASK (0xffUL << DCE_PROCESS_STATUS_SHIFT)
+};
+
+/* Various dma memory size and alignment requirements */
+#define DCE_SCR_ALIGN 64
+#define DCE_COMP_HISTORY_ALIGN 64
+#define DCE_COMP_HISTORY_SIZE 4096
+#define DCE_DECOMP_HISTORY_ALIGN 64
+#define DCE_DECOMP_HISTORY_SIZE 32768
+#define DCE_PENDING_OUTPUT_SIZE 8256 /* 8202 bytes for compression */
+#define DCE_PENDING_OUTPUT_ALIGN 64
+#define DCE_DECOMP_CTXT_ALIGN 64
+#define DCE_DECOMP_CTXT_SIZE 256
+
+/* 64 bytes Stream Context Frame, must be 64 byte aligned */
+struct scf_64b {
+ union {
+ uint8_t opaque_data8[64];
+ uint16_t opaque_data16[32];
+ uint32_t opaque_data32[16];
+ uint64_t opaque_data64[8];
+ };
+} __aligned(DCE_SCR_ALIGN);
+
+/* 128 byte Stream Context Frame (Record), must be 64 byte aligned */
+struct scf_128b {
+ union {
+ uint8_t opaque_data8[128];
+ uint16_t opaque_data16[64];
+ uint32_t opaque_data32[32];
+ uint64_t opaque_data64[16];
+ struct scf_64b scf[2];
+ };
+} __aligned(DCE_SCR_ALIGN);
+
+/* Accessors to 64 byte Stream Configuration Frame */
+
+#define SCF_TOTAL_IN_SHIFT 0
+#define SCF_TOTAL_IN_MASK (0xffffffffUL << SCF_TOTAL_IN_SHIFT)
+#define SCF_TOTAL_IN_32IDX 0
+/**
+ * get_total_in - Get total_in field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_total_in(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_TOTAL_IN);
+}
+
+/**
+ * set_total_in - Set total_in field in SCF
+ *
+ * @scf: stream context frame
+ * @val: Value to set the total_in field to.
+ */
+static inline void set_total_in(struct scf_64b *scf, uint32_t val)
+{
+ SET_BF32_IDX(&scf->opaque_data32[0], SCF_TOTAL_IN, val);
+}
+
+#define SCF_TOTAL_OUT_SHIFT 0
+#define SCF_TOTAL_OUT_MASK (0xffffffffUL << SCF_TOTAL_OUT_SHIFT)
+#define SCF_TOTAL_OUT_32IDX 1
+/**
+ * get_total_out - Get total_out field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_total_out(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_TOTAL_OUT);
+}
+
+/**
+ * set_total_out - Set total_out field in SCF
+ *
+ * @scf: stream context frame
+ * @val: Value to set the total_out field to.
+ */
+static inline void set_total_out(struct scf_64b *scf, uint32_t val)
+{
+ SET_BF32_IDX(&scf->opaque_data32[0], SCF_TOTAL_OUT, val);
+}
+
+#define SCF_ADLER32_SHIFT 0
+#define SCF_ADLER32_MASK (0xffffffffUL << SCF_ADLER32_SHIFT)
+#define SCF_ADLER32_32IDX 2
+/**
+ * get_adler32 - Get adler32 field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_adler32(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_ADLER32);
+}
+
+/**
+ * set_adler32 - Set adler32 field in SCF
+ *
+ * @scf: stream context frame
+ * @val: Value to set the adler32 field to.
+ */
+static inline void set_adler32(struct scf_64b *scf, uint32_t val)
+{
+ SET_BF32_IDX(&scf->opaque_data32[0], SCF_ADLER32, val);
+}
+
+#define SCF_ID1_SHIFT 24
+#define SCF_ID1_MASK (0xffUL << SCF_ID1_SHIFT)
+#define SCF_ID1_32IDX 4
+/**
+ * get_id1 - Get id1 field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_id1(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_ID1);
+}
+
+/**
+ * set_id1 - Set id1 field in SCF
+ *
+ * @scf: stream context frame
+ * @val: Value to set the id1 field to.
+ */
+static inline void set_id1(struct scf_64b *scf, uint32_t val)
+{
+ SET_BF32_IDX(&scf->opaque_data32[0], SCF_ID1, val);
+}
+
+#define SCF_ID2_SHIFT 16
+#define SCF_ID2_MASK (0xffUL << SCF_ID2_SHIFT)
+#define SCF_ID2_32IDX 4
+/**
+ * get_id2 - Get id2 field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_id2(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_ID2);
+}
+
+/**
+ * set_id2 - Set id2 field in SCF
+ *
+ * @scf: stream context frame
+ * @val: Value to set the id2 field to.
+ */
+static inline void set_id2(struct scf_64b *scf, uint32_t val)
+{
+ SET_BF32_IDX(&scf->opaque_data32[0], SCF_ID2, val);
+}
+
+#define SCF_ID1_ID2_SHIFT 16
+#define SCF_ID1_ID2_MASK (0xffffUL << SCF_ID1_ID2_SHIFT)
+#define SCF_ID1_ID2_32IDX 4
+/**
+ * get_id1id2 - Get both the id1 and id2 fields in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_id1id2(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_ID1_ID2);
+}
+
+/**
+ * set_id1id2 - Set both the id1 and id2 fields in SCF
+ *
+ * @scf: stream context frame
+ * @val: Value to set the id1 and id2 fields to.
+ */
+static inline void set_id1id2(struct scf_64b *scf, uint32_t val)
+{
+ SET_BF32_IDX(&scf->opaque_data32[0], SCF_ID1_ID2, val);
+}
+
+#define SCF_CM_SHIFT 8
+#define SCF_CM_MASK (0xffUL << SCF_CM_SHIFT)
+#define SCF_CM_32IDX 4
+/**
+ * get_cm - Get cm field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_cm(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_CM);
+}
+
+/**
+ * set_cm - Set cm field in SCF
+ *
+ * @scf: stream context frame
+ * @val: Value to set the cm field to.
+ */
+static inline void set_cm(struct scf_64b *scf, uint32_t val)
+{
+ SET_BF32_IDX(&scf->opaque_data32[0], SCF_CM, val);
+}
+
+#define SCF_FLG_SHIFT 0
+#define SCF_FLG_MASK (0xffUL << SCF_FLG_SHIFT)
+#define SCF_FLG_32IDX 4
+/**
+ * get_flg - Get flg field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_flg(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_FLG);
+}
+
+/**
+ * set_flg - Set flg field in SCF
+ *
+ * @scf: stream context frame
+ * @val: Value to set the cm field to.
+ */
+static inline void set_flg(struct scf_64b *scf, uint32_t val)
+{
+ SET_BF32_IDX(&scf->opaque_data32[0], SCF_FLG, val);
+}
+
+#define SCF_CMFLG_SHIFT 0
+#define SCF_CMFLG_MASK (0xffffUL << SCF_CMFLG_SHIFT)
+#define SCF_CMFLG_32IDX 4
+/**
+ * set_cmflg - Set cm and flg fields in SCF
+ *
+ * @scf: stream context frame
+ * @val: Value to set the cm and flg fields to.
+ */
+static inline void set_cmflg(struct scf_64b *scf, uint32_t val)
+{
+ SET_BF32_IDX(&scf->opaque_data32[0], SCF_CMFLG, val);
+}
+
+/**
+ * get_cmflg - Get the combined cm and flg fields in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_cmflg(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_CMFLG);
+}
+
+#define SCF_MTIME_SHIFT 0
+#define SCF_MTIME_MASK (0xffffffffUL << SCF_MTIME_SHIFT)
+#define SCF_MTIME_32IDX 5
+/**
+ * get_mtime - Get mtime field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_mtime(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_MTIME);
+}
+
+/**
+ * set_mtime - Set mtime field in SCF
+ *
+ * @scf: stream context frame
+ * @val: Value to set the mtime field to.
+ */
+static inline void set_mtime(struct scf_64b *scf, uint32_t val)
+{
+ SET_BF32_IDX(&scf->opaque_data32[0], SCF_MTIME, val);
+}
+
+#define SCF_XFL_SHIFT 24
+#define SCF_XFL_MASK (0xffUL << SCF_XFL_SHIFT)
+#define SCF_XFL_32IDX 6
+/**
+ * get_xfl - Get xfl field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_xfl(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_XFL);
+}
+
+/**
+ * set_xfl - Set xfl field in SCF
+ *
+ * @scf: stream context frame
+ * @val: Value to set the xfl field to.
+ */
+static inline void set_xfl(struct scf_64b *scf, uint32_t val)
+{
+ SET_BF32_IDX(&scf->opaque_data32[0], SCF_XFL, val);
+}
+
+#define SCF_OS_SHIFT 16
+#define SCF_OS_MASK (0xffUL << SCF_OS_SHIFT)
+#define SCF_OS_32IDX 6
+/**
+ * get_os - Get os field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_os(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_OS);
+}
+
+/**
+ * set_os - Set os field in SCF
+ *
+ * @scf: stream context frame
+ * @val: Value to set the os field to.
+ */
+static inline void set_os(struct scf_64b *scf, uint32_t val)
+{
+ SET_BF32_IDX(&scf->opaque_data32[0], SCF_OS, val);
+}
+
+#define SCF_XLEN_SHIFT 0
+#define SCF_XLEN_MASK (0xffffUL << SCF_XLEN_SHIFT)
+#define SCF_XLEN_32IDX 6
+/**
+ * get_xlen - Get xlen field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_xlen(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_XLEN);
+}
+
+/**
+ * set_xlen - Set xlen field in SCF
+ *
+ * @scf: stream context frame
+ * @val: Value to set the xlen field to.
+ */
+static inline void set_xlen(struct scf_64b *scf, uint32_t val)
+{
+ SET_BF32_IDX(&scf->opaque_data32[0], SCF_XLEN, val);
+}
+
+#define SCF_NLEN_SHIFT 16
+#define SCF_NLEN_MASK (0xffffUL << SCF_NLEN_SHIFT)
+#define SCF_NLEN_32IDX 7
+/**
+ * get_nlen - Get nlen field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_nlen(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_NLEN);
+}
+
+/**
+ * set_nlen - Set nlen field in SCF
+ *
+ * @scf: stream context frame
+ * @val: Value to set the nlen field to.
+ */
+static inline void set_nlen(struct scf_64b *scf, uint32_t val)
+{
+ SET_BF32_IDX(&scf->opaque_data32[0], SCF_NLEN, val);
+}
+
+#define SCF_CLEN_SHIFT 0
+#define SCF_CLEN_MASK (0xffffUL << SCF_CLEN_SHIFT)
+#define SCF_CLEN_32IDX 7
+/**
+ * get_clen - Get clen field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_clen(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_CLEN);
+}
+
+/**
+ * set_clen - Set clen field in SCF
+ *
+ * @scf: stream context frame
+ * @val: Value to set the clen field to.
+ */
+static inline void set_clen(struct scf_64b *scf, uint32_t val)
+{
+ SET_BF32_IDX(&scf->opaque_data32[0], SCF_CLEN, val);
+}
+
+#define SCF_EXTRA_PTR_SHIFT 0
+#define SCF_EXTRA_PTR_MASK (0xffffffffffULL << SCF_EXTRA_PTR_SHIFT)
+#define SCF_EXTRA_PTR_64IDX 4
+/**
+ * get_extra_ptr - Get extra_ptr field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint64_t get_extra_ptr(const struct scf_64b *scf)
+{
+ return GET_BF64_IDX(&scf->opaque_data64[0], SCF_EXTRA_PTR);
+}
+
+/**
+ * set_extra_ptr - Set extra_ptr field in SCF
+ *
+ * @scf: stream context frame
+ * @val: Value to set the extra_ptr field to.
+ */
+static inline void set_extra_ptr(struct scf_64b *scf, uint64_t val)
+{
+ SET_BF64_IDX(&scf->opaque_data64[0], SCF_EXTRA_PTR, val);
+}
+
+#define SCF_PENDING_OUTPUT_PTR_SHIFT 0
+#define SCF_PENDING_OUTPUT_PTR_MASK \
+ (0xffffffffffULL << SCF_PENDING_OUTPUT_PTR_SHIFT)
+#define SCF_PENDING_OUTPUT_PTR_64IDX 5
+/**
+ * get_pending_output_ptr - Get pending_output_ptr field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint64_t get_pending_output_ptr(const struct scf_64b *scf)
+{
+ return GET_BF64_IDX(&scf->opaque_data64[0], SCF_PENDING_OUTPUT_PTR);
+}
+
+/**
+ * set_pending_output_ptr - Set pending_output_ptr field in SCF
+ *
+ * @scf: stream context frame
+ * @val: Value to set the pending_output_ptr field to.
+ */
+static inline void set_pending_output_ptr(struct scf_64b *scf, uint64_t val)
+{
+ SET_BF64_IDX(&scf->opaque_data64[0], SCF_PENDING_OUTPUT_PTR, val);
+}
+
+
+/*
+ * Rev 1.0 BG specifies is a 40bit value, but the lower 6 bits are ignored
+ * since the ptr has to be 64B aligned. Rev 1.1 specifies it as a 34 bit value
+ * but that the next 6 lowers bits are implied to be zero. No space is
+ * reserved for these 6 lower bits. The API will accept the full value
+ * and shift accordingly. It will also shift when returning the value.
+ */
+#define SCF_HISTORY_PTR_SHIFT 6
+#define SCF_HISTORY_PTR_MASK (0x3ffffffffULL << SCF_HISTORY_PTR_SHIFT)
+#define SCF_HISTORY_PTR_64IDX 6
+/**
+ * get_history_ptr - Get history_ptr field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint64_t get_history_ptr(const struct scf_64b *scf)
+{
+ return GET_BF64_IDX(&scf->opaque_data64[0], SCF_HISTORY_PTR) <<
+ SCF_HISTORY_PTR_SHIFT;
+}
+
+/**
+ * set_history_ptr - Set history_ptr field in SCF
+ *
+ * @scf: stream context frame
+ * @val: Value to set the history_ptr field to.
+ */
+static inline void set_history_ptr(struct scf_64b *scf, uint64_t val)
+{
+ /* lower 6 bits expected to be zero, since 64 byte aligned */
+ SET_BF64_IDX(&scf->opaque_data64[0], SCF_HISTORY_PTR,
+ val >> SCF_HISTORY_PTR_SHIFT);
+}
+
+#define SCF_PMODE_SHIFT 31
+#define SCF_PMODE_MASK (0x1UL << SCF_PMODE_SHIFT)
+#define SCF_PMODE_32IDX 14
+/**
+ * get_pmode - Get pmode field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline bool get_pmode(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_PMODE);
+}
+
+/**
+ * set_pmode - Set pmode field in SCF
+ *
+ * @scf: stream context frame
+ * @val: Value to set the pmode field to.
+ */
+static inline void set_pmode(struct scf_64b *scf, bool val)
+{
+ SET_BF32_IDX(&scf->opaque_data32[0], SCF_PMODE, val ? 1 : 0);
+}
+
+
+/* Compression, Output SCF attribute accessors */
+
+#define SCF_BYTES_PROCESSED_SHIFT 0
+#define SCF_BYTES_PROCESSED_MASK \
+ (0x1fffffffUL << SCF_BYTES_PROCESSED_SHIFT)
+#define SCF_BYTES_PROCESSED_32IDX 3
+/**
+ * get_bytes_processed - Get bytes_processed field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_bytes_processed(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_BYTES_PROCESSED);
+}
+
+#define SCF_PENDING_OUTPUT_LEN_SHIFT 16
+#define SCF_PENDING_OUTPUT_LEN_MASK \
+ (0xffffUL << SCF_PENDING_OUTPUT_LEN_SHIFT)
+#define SCF_PENDING_OUTPUT_LEN_32IDX 10
+/**
+ * get_pending_output_len - Get pending_output_len field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_pending_output_len(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_PENDING_OUTPUT_LEN);
+}
+
+/* Decompression, Input SCF attribute accessors */
+
+/* DEC Rev 1.0 */
+#define SCF_EXTRA_LIMIT_SHIFT 16
+#define SCF_EXTRA_LIMIT_MASK (0xffffUL << SCF_EXTRA_LIMIT_SHIFT)
+#define SCF_EXTRA_LIMIT_32IDX 8
+
+/* DCE Rev 1.1 */
+#define SCF_EXTRA_LIMIT_V11_SHIFT 8
+#define SCF_EXTRA_LIMIT_V11_MASK (0x3ffffUL << SCF_EXTRA_LIMIT_V11_SHIFT)
+#define SCF_EXTRA_LIMIT_V11_32IDX 8
+
+/**
+ * get_extra_limit - Get extra_limit field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_extra_limit(const struct scf_64b *scf)
+{
+ uint16_t local_rev = dce_ip_rev;
+
+ if (local_rev == 0)
+ local_rev = DCE_DEFAULT_REV;
+
+ if (local_rev == DCE_REV10)
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_EXTRA_LIMIT);
+ else
+ return GET_BF32_IDX(&scf->opaque_data32[0],
+ SCF_EXTRA_LIMIT_V11);
+}
+
+/**
+ * set_extra_limit - Set extra_limit field in SCF
+ *
+ * @scf: stream context frame
+ * @val: Value to set the extra_limit field to.
+ */
+static inline void set_extra_limit(struct scf_64b *scf, uint32_t val)
+{
+ uint16_t local_rev;
+
+ if (!dce_ip_rev)
+ local_rev = DCE_DEFAULT_REV;
+ else
+ local_rev = dce_ip_rev;
+
+ if (local_rev == DCE_REV10)
+ SET_BF32_IDX(&scf->opaque_data32[0], SCF_EXTRA_LIMIT, val);
+ else
+ SET_BF32_IDX(&scf->opaque_data32[0], SCF_EXTRA_LIMIT_V11, val);
+}
+
+#define SCF_DECOMP_CTXT_PTR_SHIFT 0
+#define SCF_DECOMP_CTXT_PTR_MASK \
+ (0xffffffffffULL << SCF_DECOMP_CTXT_PTR_SHIFT)
+#define SCF_DECOMP_CTXT_PTR_64IDX 7
+/**
+ * get_decomp_ctxt_ptr - Get decomp_ctxt_ptr field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint64_t get_decomp_ctxt_ptr(const struct scf_64b *scf)
+{
+ return GET_BF64_IDX(&scf->opaque_data64[0], SCF_DECOMP_CTXT_PTR);
+}
+
+/**
+ * set_decomp_ctxt_ptr - Set decomp_ctxt_ptr field in SCF
+ *
+ * @scf: stream context frame
+ * @val: Value to set the decomp_ctxt_ptr field to.
+ */
+static inline void set_decomp_ctxt_ptr(struct scf_64b *scf, uint64_t val)
+{
+ SET_BF64_IDX(&scf->opaque_data64[0], SCF_DECOMP_CTXT_PTR, val);
+}
+
+
+/*
+ * Decompression, Output SCF attribute accessors. Attribute list
+ * TOTAL_IN
+ * TOTAL_OUT
+ * ADLER32
+ * XO
+ * NO
+ * CO
+ * BYTES_PROCESSED
+ * ID1
+ * ID2
+ * CM
+ * FLG
+ * MTIME
+ * XFL
+ * OS
+ * XLEN
+ * NLEN
+ * CLEN
+ * EXTRA_LIMIT
+ * EXTRA_PTR
+ * PENDING_OUTPUT_LEN
+ */
+
+#define SCF_XO_SHIFT 31
+#define SCF_XO_MASK (0x1UL << SCF_XO_SHIFT)
+#define SCF_XO_32IDX 3
+/**
+ * get_xo - Get xo field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline bool get_xo(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_XO);
+}
+
+#define SCF_NO_SHIFT 30
+#define SCF_NO_MASK (0x1UL << SCF_NO_SHIFT)
+#define SCF_NO_32IDX 3
+/**
+ * get_no - Get no field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline bool get_no(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_NO);
+}
+
+#define SCF_CO_SHIFT 29
+#define SCF_CO_MASK (0x1UL << SCF_CO_SHIFT)
+#define SCF_CO_32IDX 3
+/**
+ * get_co - Get co field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_co(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_CO);
+}
+
+/* This following accessors is when accessing the full stream context recort */
+
+/*
+ * Compression, Output Debug SCF attribute accessors. Attribute list
+ * TOTAL_IN
+ * TOTAL_OUT
+ * ADLER32
+ * OUTPUT_PHASE
+ * B64_RESIDUE_LEN
+ * B64_RESIDUE
+ * ID1
+ * ID2
+ * CM
+ * FLG
+ * MTIME
+ * XFL
+ * OS
+ * XLEN
+ * NLEN
+ * CLEN
+ * RESIDUE_DATA
+ * EXTRA_PTR
+ * PENDING_OUTPUT_LEN
+ * PENDING_WORKING_PTR(_H) (1.0, 1.1)
+ * PENDING_OUTPUT_PTR
+ * HISTORY_LEN
+ * PENDING_WORKING_PTR_L (1.1)
+ * HISTORY_PTR
+ * PMODE
+ * SUSP
+ * TERMINATED
+ * RBC
+ * MCPLT (1.1)
+ * HEADER_REMAINING
+ * CRC16
+ */
+#define SCF_OUTPUT_PHASE_SHIFT 26
+#define SCF_OUTPUT_PHASE_MASK (0x7UL << SCF_OUTPUT_PHASE_SHIFT)
+#define SCF_OUTPUT_PHASE_32IDX 3
+/**
+ * get_output_phase - Get output_phase field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_output_phase(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_OUTPUT_PHASE);
+}
+
+#define SCF_B64_RESIDUE_LEN_SHIFT 24
+#define SCF_B64_RESIDUE_LEN_MASK (0x3UL << SCF_B64_RESIDUE_LEN_SHIFT)
+#define SCF_B64_RESIDUE_LEN_32IDX 3
+/**
+ * get_b64_residue_len - Get b64_residue_len field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_b64_residue_len(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_B64_RESIDUE_LEN);
+}
+
+#define SCF_B64_RESIDUE_SHIFT 0
+#define SCF_B64_RESIDUE_MASK (0xffffffUL << SCF_B64_RESIDUE_SHIFT)
+#define SCF_B64_RESIDUE_32IDX 3
+/**
+ * get_b64_residue - Get b64_residue field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_b64_residue(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_B64_RESIDUE);
+}
+
+#define SCF_RESIDUE_DATA_SHIFT 9
+#define SCF_RESIDUE_DATA_MASK (0x7fffffUL << SCF_RESIDUE_DATA_SHIFT)
+#define SCF_RESIDUE_DATA_32IDX 8
+/**
+ * get_residue_data - Get residue_data field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_residue_data(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_RESIDUE_DATA);
+}
+
+#define SCF_PENDING_WKG_PTR_SHIFT 8
+#define SCF_PENDING_WKG_PTR_MASK (0xffUL << SCF_PENDING_WKG_PTR_SHIFT)
+#define SCF_PENDING_WKG_PTR_32IDX 10
+#define SCF_PENDING_WKG_L_PTR_SHIFT 8
+#define SCF_PENDING_WKG_L_PTR_MASK (0xffUL << SCF_PENDING_WKG_L_PTR_SHIFT)
+#define SCF_PENDING_WKG_L_PTR_32IDX 12
+/* This is a Rev 1.0 field, in Rev 1.1 this is the High field */
+/*
+ * get_pending_working_ptr - Get pending_working_ptr field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_pending_working_ptr(const struct scf_64b *scf)
+{
+ uint16_t local_rev = dce_ip_rev;
+
+ if (local_rev == 0)
+ local_rev = DCE_DEFAULT_REV;
+
+ if (local_rev == DCE_REV10) {
+ return GET_BF32_IDX(&scf->opaque_data32[0],
+ SCF_PENDING_WKG_PTR);
+ } else {
+ uint32_t val = 0;
+ val = GET_BF32_IDX(&scf->opaque_data32[0], SCF_PENDING_WKG_PTR)
+ << 8;
+ val |= GET_BF32_IDX(&scf->opaque_data32[0],
+ SCF_PENDING_WKG_L_PTR);
+ return val;
+ }
+}
+
+#define SCF_HISTORY_LEN_SHIFT 16
+#define SCF_HISTORY_LEN_MASK (0xffffUL << SCF_HISTORY_LEN_SHIFT)
+#define SCF_HISTORY_LEN_32IDX 12
+/**
+ * get_history_len - Get history_len field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_history_len(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_HISTORY_LEN);
+}
+
+#define SCF_SUSP_SHIFT 30
+#define SCF_SUSP_MASK (0x1UL << SCF_SUSP_SHIFT)
+#define SCF_SUSP_32IDX 14
+/**
+ * get_susp - Get susp field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_susp(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_SUSP);
+}
+
+#define SCF_TERMINATED_SHIFT 29
+#define SCF_TERMINATED_MASK (0x1UL << SCF_TERMINATED_SHIFT)
+#define SCF_TERMINATED_32IDX 14
+/**
+ * get_terminated - Get terminated field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_terminated(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_TERMINATED);
+}
+
+#define SCF_RBC_SHIFT 24
+#define SCF_RBC_MASK (0x1fUL << SCF_RBC_SHIFT)
+#define SCF_RBC_32IDX 14
+/**
+ * get_rbc - Get rbc field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_rbc(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_RBC);
+}
+
+#define SCF_MCPLT_SHIFT 22
+#define SCF_MCPLT_MASK (0x1UL << SCF_MCPLT_SHIFT)
+#define SCF_MCPLT_32IDX 14
+/**
+ * get_mcplt - Get mcplt field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_mcplt(const struct scf_64b *scf)
+{
+ /* only in rev > 1.0 */
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_MCPLT);
+}
+
+
+#define SCF_HEADER_REMAINING_SHIFT 0
+#define SCF_HEADER_REMAINING_MASK \
+ (0x3ffffUL << SCF_HEADER_REMAINING_SHIFT)
+#define SCF_HEADER_REMAINING_32IDX 14
+/**
+ * get_header_remaining - Get header_remaining field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_header_remaining(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_HEADER_REMAINING);
+}
+
+#define SCF_CRC16_SHIFT 0
+#define SCF_CRC16_MASK (0xffffffffUL << SCF_CRC16_SHIFT)
+#define SCF_CRC16_32IDX 15
+/**
+ * get_crc16 - Get crc16 field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_crc16(const struct scf_64b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCF_CRC16);
+}
+
+/*
+ * Deompression, Output Debug SCF attribute accessors. Attribute list
+ * IMPORTANT: This structure is 128Bytes is size.
+ * TOTAL_IN
+ * TOTAL_OUT
+ * ADLER32
+ * OUTPUT_PHASE
+ * B64_RESIDUE_LEN
+ * B64_RESIDUE
+ * ID1
+ * ID2
+ * CM
+ * FLG
+ * MTIME
+ * XFL
+ * OS
+ * XLEN
+ * NLEN
+ * CLEN
+ * RESIDUE_DATA
+ * EXTRA_PTR
+ * PENDING_OUTPUT_LEN
+ * PENDING_WORKING_PTR(_H) (1.0, 1.1)
+ * PENDING_OUTPUT_PTR
+ * HISTORY_LEN
+ * PENDING_WORKING_PTR_L (1.1)
+ * HISTORY_PTR
+ * PMODE
+ * SUSP
+ * TERMINATED
+ * RBC
+ * MCPLT (1.1)
+ * MC (1.1)
+ * HEADER_REMAINING
+ * CRC16
+ *
+ * ## second cache line ##
+ * DECOMP_CTXT_PTR
+ * DECOMP_TOTAL_OUT (1.1)
+ * BFINAL
+ * BTYPE
+ * FRAME_PARSE_STATE
+ * NUM_CODE_LEN
+ * PREVIOUS_CODE_LEN (moved location, 1.0, 1.1)
+ * NCBB_REMAINING
+ * HLIT
+ * HDIST
+ * HCLEN
+ * HUFFMAN_RBC
+ * HUFFMAN_RESIDUE
+ */
+
+#define SCFCL2_DECOMP_CTXT_PTR_SHIFT 0
+#define SCFCL2_DECOMP_CTXT_PTR_MASK \
+ (0xffffffffffULL << SCFCL2_DECOMP_CTXT_PTR_SHIFT)
+#define SCFCL2_DECOMP_CTXT_PTR_64IDX 8
+/**
+ * get_decomp_ctxt_ptr_cl2 - Get decomp_ctxt_ptr field in 128 byte SCF
+ *
+ * @scf: stream context frame, 128 bytes in size
+ *
+ * Returns the decomp_ctxt_ptr field in the second cache line.
+ */
+static inline uint64_t get_decomp_ctxt_ptr_cl2(const struct scf_128b *scf)
+{
+ return GET_BF64_IDX(&scf->opaque_data64[0], SCFCL2_DECOMP_CTXT_PTR);
+}
+
+#define SCFCL2_DECOMP_TOTAL_OUT_SHIFT 0
+#define SCFCL2_DECOMP_TOTAL_OUT_MASK \
+ (0xffffffffUL << SCFCL2_DECOMP_TOTAL_OUT_SHIFT)
+#define SCFCL2_DECOMP_TOTAL_OUT_32IDX 17
+/**
+ * get_decomp_total_out_cl2 - Get decomp_total_out field in 128 byte SCF
+ *
+ * @scf: stream context frame, 128 bytes in size
+ *
+ * Returns the decomp_total_out field in the second cache line.
+ */
+static inline uint64_t get_decomp_total_out_cl2(const struct scf_128b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCFCL2_DECOMP_TOTAL_OUT);
+}
+
+#define SCFCL2_PREVIOUS_CODE_LEN_SHIFT 28
+#define SCFCL2_PREVIOUS_CODE_LEN_V11_SHIFT 12
+#define SCFCL2_PREVIOUS_CODE_LEN_MASK \
+ (0xfUL << SCFCL2_PREVIOUS_CODE_LEN_SHIFT)
+#define SCFCL2_PREVIOUS_CODE_LEN_V11_MASK \
+ (0xfUL << SCFCL2_PREVIOUS_CODE_LEN_V11_SHIFT)
+#define SCFCL2_PREVIOUS_CODE_LEN_32IDX 18
+#define SCFCL2_PREVIOUS_CODE_LEN_V11_32IDX 20
+
+/**
+ * get_previous_code_len_cl2 - Get previous_code_len field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_previous_code_len_cl2(const struct scf_128b *scf)
+{
+ uint16_t local_rev = dce_ip_rev;
+
+ if (local_rev == 0)
+ local_rev = DCE_DEFAULT_REV;
+
+ if (local_rev == DCE_REV10)
+ return GET_BF32_IDX(&scf->opaque_data32[0],
+ SCFCL2_PREVIOUS_CODE_LEN);
+ else
+ return GET_BF32_IDX(&scf->opaque_data32[0],
+ SCFCL2_PREVIOUS_CODE_LEN_V11);
+}
+
+#define SCFCL2_BFINAL_SHIFT 30
+#define SCFCL2_BFINAL_MASK (0x1UL << SCFCL2_BFINAL_SHIFT)
+#define SCFCL2_BFINAL_32IDX 19
+/**
+ * get_bfinal_cl2 - Get bfinal field in SCF
+ *
+ * @scf: stream context frame, 128 bytes in size
+ */
+static inline uint32_t get_bfinal_cl2(const struct scf_128b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCFCL2_BFINAL);
+}
+
+#define SCFCL2_BTYPE_SHIFT 28
+#define SCFCL2_BTYPE_MASK (0x3UL << SCFCL2_BTYPE_SHIFT)
+#define SCFCL2_BTYPE_32IDX 19
+/**
+ * get_btype_cl2 - Get btype field in SCF
+ *
+ * @scf: stream context frame, 128 bytes in size
+ */
+static inline uint32_t get_btype_cl2(const struct scf_128b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCFCL2_BTYPE);
+}
+
+#define SCFCL2_FRAME_PARSE_STATE_SHIFT 27
+#define SCFCL2_FRAME_PARSE_STATE_MASK \
+ (0x1fUL << SCFCL2_FRAME_PARSE_STATE_SHIFT)
+#define SCFCL2_FRAME_PARSE_STATE_32IDX 20
+/**
+ * get_frame_parse_state_cl2 - Get frame_parse_state field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_frame_parse_state_cl2(const struct scf_128b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCFCL2_FRAME_PARSE_STATE);
+}
+
+#define SCFCL2_NUM_CODE_LEN_SHIFT 18
+#define SCFCL2_NUM_CODE_LEN_MASK (0x1ffUL << SCFCL2_NUM_CODE_LEN_SHIFT)
+#define SCFCL2_NUM_CODE_LEN_32IDX 20
+/**
+ * get_num_code_len_cl2 - Get num_code_len field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_num_code_len_cl2(const struct scf_128b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0],
+ SCFCL2_NUM_CODE_LEN);
+}
+
+#define SCFCL2_NCBB_REMAINING_SHIFT 16
+#define SCFCL2_NCBB_REMAINING_MASK \
+ (0xffffUL << SCFCL2_NCBB_REMAINING_SHIFT)
+#define SCFCL2_NCBB_REMAINING_32IDX 21
+/**
+ * get_ncbb_remaining_cl2 - Get ncbb_remaining field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_ncbb_remaining_cl2(const struct scf_128b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0],
+ SCFCL2_NCBB_REMAINING);
+}
+
+#define SCFCL2_HLIT_SHIFT 11
+#define SCFCL2_HLIT_MASK (0x1fUL << SCFCL2_HLIT_SHIFT)
+#define SCFCL2_HLIT_32IDX 21
+/**
+ * get_hlit_cl2 - Get hlit field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_hlit_cl2(const struct scf_128b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCFCL2_HLIT);
+}
+
+#define SCFCL2_HDIST_SHIFT 6
+#define SCFCL2_HDIST_MASK (0x1fUL << SCFCL2_HDIST_SHIFT)
+#define SCFCL2_HDIST_32IDX 21
+/**
+ * get_hdist_cl2 - Get hdist field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_hdist_cl2(const struct scf_128b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCFCL2_HDIST);
+}
+
+#define SCFCL2_HCLEN_SHIFT 2
+#define SCFCL2_HCLEN_MASK (0xfUL << SCFCL2_HCLEN_SHIFT)
+#define SCFCL2_HCLEN_32IDX 21
+/**
+ * get_hclen_cl2 - Get hclen field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_hclen_cl2(const struct scf_128b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCFCL2_HCLEN);
+}
+
+#define SCFCL2_HUFFMAN_RBC_SHIFT 24
+#define SCFCL2_HUFFMAN_RBC_MASK (0x3fUL << SCFCL2_HUFFMAN_RBC_SHIFT)
+#define SCFCL2_HUFFMAN_RBC_32IDX 22
+/**
+ * get_huffman_rbc_cl2 - Get huffman_rbc field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint32_t get_huffman_rbc_cl2(const struct scf_128b *scf)
+{
+ return GET_BF32_IDX(&scf->opaque_data32[0], SCFCL2_HUFFMAN_RBC);
+}
+
+#define SCFCL2_HUFFMAN_RESIDUE_SHIFT 0
+#define SCFCL2_HUFFMAN_RESIDUE_MASK \
+ (0x7fffffffffffULL << SCFCL2_HUFFMAN_RESIDUE_SHIFT)
+#define SCFCL2_HUFFMAN_RESIDUE_64IDX 11
+/**
+ * get_huffman_residue_cl2 - Get huffman_residue field in SCF
+ *
+ * @scf: stream context frame
+ */
+static inline uint64_t get_huffman_residue_cl2(const struct scf_128b *scf)
+{
+ return GET_BF64_IDX(&scf->opaque_data64[0], SCFCL2_HUFFMAN_RESIDUE);
+}
+
+/**
+ * enum dce_status - This enumeration depicts all of the possible status codes
+ * that can appear in the output frame status field.
+ *
+ * @FULLY_PROCESSED: The work unit data was fully processed without
+ * encountering an exception, and the work unit was not
+ * marked as an end of Stream (no DCE_Z_FINISH parameter).
+ * @STREAM_END: The work unit data was fully processed without
+ * encountering an exception, and was marked as an end of
+ * Stream with the DCE_Z_FINISH flush parameter.
+ * @INPUT_STARVED The compressed input Frame did not contain an integral
+ * number of compressed data blocks and/or ended before
+ * the expected number of decompressed bytes were produced.
+ * This exception occurs when an input Frame with
+ * Z_FLUSH = Z_FINISH is received. It indicates a missing
+ * end of block code;
+ * i.e. “invalid code * missing end-of-block†in *msg
+ * (zlib software library equivalent).
+ * @Z_BLOCK_SUSPENDED The decompressor module halted processing of an input
+ * Frame at the end of a compressed block (or block header
+ * if Z_FLUSH = Z_BLOCK or Z_TREES). This code can only
+ * occur on stateful Flows in recycling mode
+ * @OUTPUT_BLOCKED_SUSPEND The pre-built output structure was not large
+ * enough to contain all of the (de)compressed input Frame
+ * data. This code can only occur on stateful Flows in
+ * recycling mode
+ * @ACQUIRE_DATA_BUFFER_DENIED_SUSPEND An attempt to acquire a free buffer from
+ * BMan (DBPID) was unsuccessful. This code can only occur
+ * on stateful Flows in recycling mode
+ * @ACQUIRE_TABLE_BUFFER_DENIED_SUSPEND An attempt to acquire a free buffer from
+ * BMan (TBPID) was unsuccessful. This code can only occur
+ * on stateful Flows in recycling mode
+ * @OOL_REACHED_SUSPEND The DCE halted processing so as not to exceed the OLL
+ * setting. This code can only occur on stateful Flows in
+ * recycling mode
+ * @HCL_REACHED_SUSPEND The DCE halted processing so as not to exceed the HCL
+ * setting. This code can only occur on stateful Flows in
+ * recycling mode
+ * @OUTPUT_BLOCKED_DISCARD The pre-built output structure was not large
+ * enough to contain all of the (de)compressed input Frame
+ * data. Some output data has been lost. This code can only
+ * occur on stateless Flows or a stateful Flow in
+ * truncation mode
+ * @ACQUIRE_DATA_BUFFER_DENIED_DISCARD An attempt to acquire a free buffer from
+ * BMan (DBPID) was unsuccessful. Some output data has been
+ * lost. This code can only occur on stateless Flows or a
+ * stateful Flow in truncation mode
+ *
+ * @ACQUIRE_TABLE_BUFFER_DENIED_DISCARD An attempt to acquire a free buffer from
+ * BMan (TBPID) was unsuccessful. Some output data has been
+ * lost. This code can only occur on stateless Flows or a
+ * stateful Flow in truncation mode
+ * @OLL_REACHED_DISCARD The DCE halted processing so as not to exceed the OLL
+ * setting. Some output data has been lost. This code can
+ * only occur on stateless Flows or a stateful Flow in
+ * truncation mod
+ * @HCL_REACHED_DISCARD The DCE halted processing so as not to exceed the HCL
+ * setting. Some output data has been lost. This code can
+ * only occur on stateless Flows or a stateful Flow in
+ * truncation mode
+ * @SKIPPED The work unit was not processed due to a previous “suspendâ€
+ * (i.e. Output Blocked Suspend, etc.) exception on the same
+ * Stream. This code can only occur on stateful Flows in recycling
+ * mode
+ * @PREVIOUS_FLOW_TERMINATION The work unit was not processed due to a
+ * previous exception (other than Input Starved or Output Blocked
+ * Suspend) or completed Z_FINISH Frame on the same Stream. This
+ * exception code will appear in Frames that follow a
+ * non-recoverable exception on a Stream, or in Frames that follow
+ * a Z_FINISH Frame but do not have a set I bit.
+ * @INVALID_COMPOUND_FRAME This status code is generated if the DCE
+ * dequeues a compound Frame that does not contain an {E=0, F=1}
+ * pair in its third member Frame.
+ * @INVALID_STATUS_CMD An invalid field setting was detected in the received
+ * Frame’s STATUS/CMD field. This code results from one of the
+ * following conditions:
+ * Reserved setting in any of the defined fields
+ * @UNSUPPORTED_FRAME This status code is generated if the DCE dequeues a
+ * compound Frame that does not match the supported three member
+ * configuration.
+ * @FRAME_TOO_SHORT This status code is generated if DCE reaches the end of
+ * a multi-buffer input Frame (simple or compound) and determines
+ * that the structure contains fewer than LENGTH bytes of data.
+ * @OUTPUT_OFFSET_TOO_LARGE This status code is generated if the OO field in
+ * the Frame’s STATUS/CMD field specifies an offset that is
+ * greater than or equal to the BMan buffer size specified for the
+ * Flow. This exception will only occur if buffer acquisition is
+ * necessary; i.e. DCE has some output data to buffer for the
+ * processed Frame.
+ * @ZLIB_INCOMPLETE_HEADER
+ * @ZLIB_HEADER_ERROR An error was detected in the ZLIB header of a compressed
+ * work unit. This code results from one of the following
+ * conditions:
+ * Z_FINISH Frame (plus any preceding Frames) did not
+ * contain enough bytes to comprise a complete
+ * header: “incorrect header check†in *msg
+ * Compression method other than DEFLATE specified:
+ * “unknown compression method†in *msg
+ * Invalid window size specified: “invalid window sizeâ€
+ * in *msg
+ * Reserved BTYPE: “invalid block type†in *msg
+ * LEN and NLEN fields are not 1’s complement of each
+ * other: “invalid stored block lengthsâ€
+ * in *msg
+ * @ZLIB_NEED_DICTIONARY_ERROR A compressed ZLIB Stream has the FLG.FDICT flag
+ * set.
+ * @GZIP_INCOMPLETE_HEADER
+ * @GZIP_HEADER_ERROR An error was detected in the header of a compressed GZIP
+ * work unit. This code results from one of the following
+ * conditions:
+ * ID1/ID2 invalid
+ * Compression method other than DEFLATE
+ * Any of the reserved flags are set: “unknown header
+ * flags set†in *msg.
+ * Header CRC16 value check mismatch: “header crc
+ * mismatch†in *msg.
+ * @DEFLATE_INVALID_BLOCK_TYPE An error was detected in the header of a
+ * compressed DEFLATE block: “invalid block type†in *msg.
+ * @DEFLATE_INVALID_BLOCK_LENGTHS An error was detected in the header of a
+ * compressed DEFLATE block: “invalid stored block lengths†in
+ * *msg
+ * @DEFLATE_TOO_MANY_LEN_OR_DIST_SYM “too many length or distance symbols†in
+ * *msg.
+ * @DEFLATE_INVALID_CODE_LENGTHS_SET “invalid code lengths set†in *msg.
+ * @DEFLATE_INVALID_BIT_LENGTH_REPEAT “invalid bit length repeat†in *msg.
+ * @DEFLATE_INVALID_LITERAL_LENGTHS_SET “invalid literal/lengths set†in *msg.
+ * @DEFLATE_INVALID_DISTANCES_SET “invalid distances set†in *msg.
+ * @DEFLATE_INVALID_LITERAL_LENGTH_CODE “invalid literal/length code†in *msg.
+ * @DEFLATE_INVALID_DISTANCE_CODE “invalid distance code†in *msg.
+ * @DEFLATE_INVALID_DISTANCE_TOO_FAR_BACK “invalid distance too far backâ€
+ * in *msg.
+ * @DEFLATE_INCORRECT_DATA_CHECK “incorrect data check†in *msg.
+ * @DEFLATE_INCORRECT_LENGTH_CHECK “incorrect length check†in *msg.
+ * @DEFLATE_INVALID_CODE “invalid code * missing end of block†in *msg.
+ * @CXM_2BIT_ECC_ERROR A double bit ECC error was detected on an access to the
+ * CXM internal memory while processing this Frame.
+ * @CBM_2BIT_ECC_ERROR A double bit ECC error was detected on an access to the
+ * CBM internal memory while processing this Frame.
+ * @DHM_2BIT_ECC_ERROR A double bit ECC error was detected on an access to the
+ * DHM internal memory while processing this Frame.
+ * @INVALID_BASE64_CODE An invalid Base64 code (bad byte value) was encountered.
+ * @INVALID_BASE64_PADDING In invalid amount of padding was detected on
+ * Base64 encoded input data.
+ * @SCF_SYSTEM_MEM_READ_ERROR A system memory read transaction performed by
+ * the DCE has resulted in a system memory bus error. This code
+ * will occur when the error is detected on the following
+ * read transactions:
+ * * Stream Configuration Frame
+ * @PENDING_OUTPUT_SYSTEM_MEM_READ_ERROR A system memory read transaction
+ * performed by the DCE has resulted in a system memory bus error.
+ * This code will occur when the error is detected on the following
+ * read transactions:
+ * Pending Output Buffer
+ * @HISTORY_WINDOW_SYSTEM_MEM_READ_ERROR A system memory read transaction
+ * performed by the DCE has resulted in a system memory bus error.
+ * This code will occur when the error is detected on the following
+ * read transactions:
+ * * History Window
+ * @CTX_DATA_SYSTEM_MEM_READ_ERROR A system memory read transaction
+ * performed by the DCE has resulted in a system memory bus error.
+ * This code will occur when the error is detected on the
+ * following read transactions:
+ * Stream Context Record
+ * “Extra†data for GZIP header insertion.
+ * @FRAME_DATA_SYSTEM_READ_ERROR A system memory read transaction
+ * performed by the DCE has resulted in a system memory bus error.
+ * This code will occur when the error is detected on the
+ * following read transactions:
+ * Input Frame data buffer
+ * @INPUT_FRAME_TBL_SYSTEM_READ_ERROR A system memory read transaction
+ * performed by the DCE has resulted in a system memory bus error.
+ * This code will occur when the error is detected on the
+ * following read transactions:
+ * Input Frame scatter/gather table entry
+ * @OUTPUT_FRAME_TBL_SYSTEM_READ_ERROR A system memory read transaction
+ * performed by the DCE has resulted in a system memory bus error.
+ * This code will occur when the error is detected on the
+ * following read transactions:
+ * Output Frame scatter/gather table entry (pre-built
+ * Frames only)
+ * @SCF_SYSTEM_MEM_WRITE_ERROR A system memory write transaction performed by
+ * the DCE has resulted in a system memory bus error. This code
+ * will occur when the error is detected on the following write
+ * transactions:
+ * Stream Configuration Frame
+ * @PENDING_OUTPUT_SYSTEM_MEM_WRITE_ERROR A system memory write
+ * transaction performed by the DCE has resulted in a system
+ * memory bus error. This code will occur when the error is
+ * detected on the following write transactions:
+ * Pending Output Buffer
+ * @HISTORY_WINDOW_SYSTEM_MEM_WRITE_ERROR A system memory write
+ * transaction performed by the DCE has resulted in a system
+ * memory bus error. This code will occur when the error is
+ * detected on the following write transactions:
+ * History Window
+ * @CTX_DATA_SYSTEM_MEM_WRITE_ERROR A system memory write transaction
+ * performed by the DCE has resulted in a system memory bus error.
+ * This code will occur when the error is detected on the
+ * following write transactions:
+ * Stream Context Record
+ * @FRAME_DATA_SYSTEM_MEM_WRITE_ERROR A system memory write transaction
+ * performed by the DCE has resulted in a system memory bus error.
+ * This code will occur when the error is detected on the
+ * following write transactions:
+ * Output Frame data buffer
+ * @FRAME_TBL_SYSTEM_MEM_WRITE_ERROR A system memory write transaction
+ * performed by the DCE has resulted in a system memory bus error.
+ * This code will occur when the error is detected on the
+ * following write transactions:
+ * Output Frame scatter/gather table entry
+ *
+ * @FULLY_PROCESSED and @STREAM_END are successful return code, all other codes
+ * are operational error.
+ */
+enum dce_status {
+ FULLY_PROCESSED = 0x00,
+ STREAM_END = 0x01,
+ INPUT_STARVED = 0x10,
+ Z_BLOCK_SUSPENDED = 0x12,
+ OUTPUT_BLOCKED_SUSPEND = 0x14,
+ ACQUIRE_DATA_BUFFER_DENIED_SUSPEND = 0x15,
+ ACQUIRE_TABLE_BUFFER_DENIED_SUSPEND = 0x16,
+ OOL_REACHED_SUSPEND = 0x17,
+ HCL_REACHED_SUSPEND = 0x18,
+ OUTPUT_BLOCKED_DISCARD = 0x24,
+ ACQUIRE_DATA_BUFFER_DENIED_DISCARD = 0x25,
+ ACQUIRE_TABLE_BUFFER_DENIED_DISCARD = 0x26,
+ OLL_REACHED_DISCARD = 0x27,
+ HCL_REACHED_DISCARD = 0x28,
+ SKIPPED = 0x30,
+ PREVIOUS_FLOW_TERMINATION = 0x31,
+ INVALID_COMPOUND_FRAME = 0x40,
+ INVALID_STATUS_CMD = 0x41,
+ UNSUPPORTED_FRAME = 0x42,
+ FRAME_TOO_SHORT = 0x44,
+ OUTPUT_OFFSET_TOO_LARGE = 0x46,
+ ZLIB_INCOMPLETE_HEADER = 0x50,
+ ZLIB_HEADER_ERROR = 0x51,
+ ZLIB_NEED_DICTIONARY_ERROR = 0x52,
+ GZIP_INCOMPLETE_HEADER = 0x60,
+ GZIP_HEADER_ERROR = 0x61,
+ DEFLATE_INVALID_BLOCK_TYPE = 0x70,
+ DEFLATE_INVALID_BLOCK_LENGTHS = 0x71,
+ DEFLATE_TOO_MANY_LEN_OR_DIST_SYM = 0x80,
+ DEFLATE_INVALID_CODE_LENGTHS_SET = 0x81,
+ DEFLATE_INVALID_BIT_LENGTH_REPEAT = 0x82,
+ DEFLATE_INVALID_LITERAL_LENGTHS_SET = 0x83,
+ DEFLATE_INVALID_DISTANCES_SET = 0x84,
+ DEFLATE_INVALID_LITERAL_LENGTH_CODE = 0x85,
+ DEFLATE_INVALID_DISTANCE_CODE = 0x86,
+ DEFLATE_INVALID_DISTANCE_TOO_FAR_BACK = 0x87,
+ DEFLATE_INCORRECT_DATA_CHECK = 0x88,
+ DEFLATE_INCORRECT_LENGTH_CHECK = 0x89,
+ DEFLATE_INVALID_CODE = 0x8A,
+ CXM_2BIT_ECC_ERROR = 0xB0,
+ CBM_2BIT_ECC_ERROR = 0xB1,
+ DHM_2BIT_ECC_ERROR = 0xB2,
+ INVALID_BASE64_CODE = 0xC0,
+ INVALID_BASE64_PADDING = 0xC1,
+ SCF_SYSTEM_MEM_READ_ERROR = 0xD5,
+ PENDING_OUTPUT_SYSTEM_MEM_READ_ERROR = 0xD6,
+ HISTORY_WINDOW_SYSTEM_MEM_READ_ERROR = 0xD7,
+ CTX_DATA_SYSTEM_MEM_READ_ERROR = 0xD8,
+ FRAME_DATA_SYSTEM_READ_ERROR = 0xD9,
+ INPUT_FRAME_TBL_SYSTEM_READ_ERROR = 0xDA,
+ OUTPUT_FRAME_TBL_SYSTEM_READ_ERROR = 0xDB,
+ SCF_SYSTEM_MEM_WRITE_ERROR = 0xE5,
+ PENDING_OUTPUT_SYSTEM_MEM_WRITE_ERROR = 0xE6,
+ HISTORY_WINDOW_SYSTEM_MEM_WRITE_ERROR = 0xE7,
+ CTX_DATA_SYSTEM_MEM_WRITE_ERROR = 0xE8,
+ FRAME_DATA_SYSTEM_MEM_WRITE_ERROR = 0xE9,
+ FRAME_TBL_SYSTEM_MEM_WRITE_ERROR = 0xEA
+};
+
+#endif /* FL_DCE_DEFS_H */
diff --git a/drivers/staging/fsl_dce/flib/dce_flow.c b/drivers/staging/fsl_dce/flib/dce_flow.c
new file mode 100644
index 0000000..5025254
--- /dev/null
+++ b/drivers/staging/fsl_dce/flib/dce_flow.c
@@ -0,0 +1,513 @@
+/* Copyright 2013 Freescale Semiconductor, Inc. */
+
+#include "../dce_sys.h"
+#include "dce_flow.h"
+#include "dce_helper.h"
+
+#define LOW_PRIORITY_WQ 7
+#define DEXP_MAX 22
+#define DEXP_OFFSET 6
+#define DMANT_MAX 16
+
+#define MAX_FIFO_SIZE 256
+
+/* Internal-only flow flags, mustn't conflict with exported ones */
+#define DCE_FLOW_FLAG_DEAD 0x80000000
+#define DCE_FLOW_FLAG_FINISHING 0x40000000
+#define DCE_FLOW_FLAG_FINISHED 0x20000000
+#define DCE_FLOW_FLAG_INITIALIZING 0x10000000
+#define DCE_FLOW_FLAG_PRIVATE 0xf8000000 /* mask of them all */
+
+/* Internal-only cmd flags, musn't conflict with exported ones */
+#define DCE_FLOW_OP_PRIVATE 0x80000000 /* mask of them all */
+
+static enum qman_cb_dqrr_result cb_dqrr(struct qman_portal *, struct qman_fq *,
+ const struct qm_dqrr_entry *);
+static void cb_ern(struct qman_portal *, struct qman_fq *,
+ const struct qm_mr_entry *);
+static void cb_fqs(struct qman_portal *, struct qman_fq *,
+ const struct qm_mr_entry *);
+static const struct qman_fq_cb dce_fq_base_rx = {
+ .fqs = cb_fqs,
+ .ern = cb_ern
+};
+static const struct qman_fq_cb dce_fq_base_tx = {
+ .dqrr = cb_dqrr,
+ .fqs = cb_fqs
+};
+
+/* this is hitting the rx FQ with a large blunt instrument, ie. park()
+ * does a retire, query, oos, and (re)init. It's possible to force-eligible the
+ * rx FQ instead, then use a DCA_PK within the cb_dqrr() callback to park it.
+ * Implement this optimisation later if it's an issue (and incur the additional
+ * complexity in the state-machine). */
+static int park(struct qman_fq *fq, struct qm_mcc_initfq *initfq)
+{
+ int ret;
+ uint32_t flags;
+
+ ret = qman_retire_fq(fq, &flags);
+ if (ret)
+ return ret;
+ BUG_ON(flags & QMAN_FQ_STATE_BLOCKOOS);
+ /* We can't revert from now on */
+ ret = qman_query_fq(fq, &initfq->fqd);
+ BUG_ON(ret);
+ ret = qman_oos_fq(fq);
+ BUG_ON(ret);
+ /* can't set QM_INITFQ_WE_OAC and QM_INITFQ_WE_TDTHRESH
+ * at the same time */
+ initfq->we_mask = QM_INITFQ_WE_MASK & ~QM_INITFQ_WE_TDTHRESH;
+ ret = qman_init_fq(fq, 0, initfq);
+ BUG_ON(ret);
+ initfq->we_mask = QM_INITFQ_WE_TDTHRESH;
+ ret = qman_init_fq(fq, 0, initfq);
+ BUG_ON(ret);
+ return 0;
+}
+
+static int configure_tx(struct fsl_dce_flow *flow, bool use_specified_txfq_dest,
+ uint16_t dest_qm_channel)
+{
+ struct qm_mcc_initfq initfq;
+ uint32_t qinit_flags = QMAN_INITFQ_FLAG_SCHED;
+ int ret;
+
+ initfq.we_mask = QM_INITFQ_WE_DESTWQ | QM_INITFQ_WE_FQCTRL;
+ initfq.fqd.dest.wq = LOW_PRIORITY_WQ;
+ initfq.fqd.fq_ctrl = 0; /* disable stashing */
+ if (use_specified_txfq_dest) {
+ /* TODO: this path not supported at the moment */
+ BUG();
+ initfq.fqd.dest.channel = dest_qm_channel;
+ /* Set hold-active *IFF* it's a pool channel */
+ if (dest_qm_channel >= qm_channel_pool1)
+ initfq.fqd.fq_ctrl |= QM_FQCTRL_HOLDACTIVE;
+ } else {
+ qinit_flags |= QMAN_INITFQ_FLAG_LOCAL;
+ }
+ ret = qman_init_fq(&flow->fq_tx, qinit_flags, &initfq);
+ return ret;
+}
+
+static int configure_rx(struct fsl_dce_flow *flow, struct dce_bman_cfg *bcfg,
+ dma_addr_t scr)
+{
+ int ret;
+ struct qm_mcc_initfq initfq;
+ struct dce_context_a *dce_ctx_a =
+ (struct dce_context_a *)&initfq.fqd.context_a;
+ struct dce_context_b *dce_ctx_b =
+ (struct dce_context_b *)&initfq.fqd.context_b;
+
+ pr_debug("dce_flow configure_rx: flow %p, bcfg %p, scr 0x%llx\n",
+ flow, bcfg, scr);
+
+ memset(&initfq, 0, sizeof(initfq));
+
+ initfq.we_mask = QM_INITFQ_WE_DESTWQ | QM_INITFQ_WE_CONTEXTA |
+ QM_INITFQ_WE_CONTEXTB;
+ /* compression channel uses sub-portal 0, decompression sub-portal 1 */
+ initfq.fqd.dest.channel = (flow->mode == DCE_COMPRESSION) ?
+ qm_channel_dce : qm_channel_dce + 1;
+ initfq.fqd.dest.wq = LOW_PRIORITY_WQ;
+
+ /*
+ * bit shift scr since it is required to be 64B aligned and the
+ * hardware assumes lower 6 bits to be zero
+ */
+ BUG_ON(scr & 0x3F);
+ dce_context_a_set_scrp(dce_ctx_a, scr);
+ SET_BF64(dce_ctx_a->d64, DCE_CONTEXT_A_TSIZE,
+ ((bcfg) ? bcfg->tsize : 0));
+ /* adjust DEXP according to spec */
+ if (bcfg && bcfg->dbpid) {
+ if (bcfg->dexp == DEXP_MAX)
+ SET_BF64(dce_ctx_a->d64, DCE_CONTEXT_A_DEXP, 0);
+ else
+ SET_BF64(dce_ctx_a->d64, DCE_CONTEXT_A_DEXP,
+ (bcfg->dexp - DEXP_OFFSET));
+ /* adjust DMANT according to spec */
+ if (bcfg->dmant == DMANT_MAX)
+ SET_BF64(dce_ctx_a->d64, DCE_CONTEXT_A_DMANT, 0);
+ else
+ SET_BF64(dce_ctx_a->d64, DCE_CONTEXT_A_DMANT,
+ bcfg->dmant);
+ }
+ SET_BF64(dce_ctx_a->d64, DCE_CONTEXT_A_TBPID,
+ ((bcfg) ? bcfg->tbpid : 0));
+ /* Setup context_b field */
+ SET_BF32(dce_ctx_b->d32, DCE_CONTEXT_B_DBPID,
+ ((bcfg) ? bcfg->dbpid : 0));
+ SET_BF32(dce_ctx_b->d32, DCE_CONTEXT_B_FQID,
+ qman_fq_fqid(&flow->fq_tx));
+
+ ret = qman_init_fq(&flow->fq_rx, QMAN_INITFQ_FLAG_SCHED, &initfq);
+ return ret;
+}
+
+void fsl_dce_flow_setopt_fqtx_id(struct fsl_dce_flow *flow, uint32_t id)
+{
+ flow->fqtx_id = id;
+}
+
+void fsl_dce_flow_setopt_fqrx_id(struct fsl_dce_flow *flow, uint32_t id)
+{
+ flow->fqrx_id = id;
+}
+
+void fsl_dce_flow_setopt_bcfg(struct fsl_dce_flow *flow,
+ struct dce_bman_cfg bcfg)
+{
+ flow->bcfg = bcfg;
+}
+
+int fsl_dce_flow_setopt_txfqdest(struct fsl_dce_flow *flow, uint32_t dest)
+{
+ if (dest == 0xffffffff) {
+ flow->use_specified_txfq_dest = false;
+ } else {
+ flow->use_specified_txfq_dest = true;
+ flow->txfq_dest = (uint32_t)dest;
+ }
+
+ return 0;
+}
+
+int fsl_dce_flow_setopt_outputoffset(struct fsl_dce_flow *flow, uint32_t val)
+{
+ switch (val) {
+ case DCE_PROCESS_OO_NONE_LONG:
+ case DCE_PROCESS_OO_32B:
+ case DCE_PROCESS_OO_64B:
+ case DCE_PROCESS_OO_128B:
+ case DCE_PROCESS_OO_256B:
+ case DCE_PROCESS_OO_512B:
+ case DCE_PROCESS_OO_1024B:
+ case DCE_PROCESS_OO_NON_SHORT:
+ SET_BF32(flow->proc_flags, DCE_PROCESS_OO, val);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+int fsl_dce_flow_setopt_compression_effort(struct fsl_dce_flow *flow,
+ uint32_t val)
+{
+ switch (val) {
+ case DCE_PROCESS_CE_NONE:
+ case DCE_PROCESS_CE_STATIC_HUFF_STRMATCH:
+ case DCE_PROCESS_CE_HUFF_ONLY:
+ case DCE_PROCESS_CE_BEST_POSSIBLE:
+ SET_BF32(flow->proc_flags, DCE_PROCESS_CE, val);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+int fsl_dce_flow_setopt_release_input(struct fsl_dce_flow *flow, bool val)
+{
+ if (val)
+ SET_BF32_TK(flow->proc_flags, DCE_PROCESS_RB, YES);
+ else
+ SET_BF32_TK(flow->proc_flags, DCE_PROCESS_RB, NO);
+ return 0;
+}
+
+int fsl_dce_flow_setopt_base64(struct fsl_dce_flow *flow, bool val)
+{
+ if (val)
+ SET_BF32_TK(flow->proc_flags, DCE_PROCESS_B64, YES);
+ else
+ SET_BF32_TK(flow->proc_flags, DCE_PROCESS_B64, NO);
+ return 0;
+}
+
+int fsl_dce_flow_init(struct fsl_dce_flow *flow,
+ struct fsl_dce_flow_init_params *params)
+{
+ int ret = -EINVAL, ret_tmp;
+
+ if (!params) {
+ pr_debug("dce_flow: params is null\n");
+ goto failed_params;
+ }
+
+ if (!params->fifo_depth) {
+ pr_err("dce_flow: invalid fifo depth of zero\n");
+ goto failed_params;
+ }
+ if (params->fifo_depth > MAX_FIFO_SIZE) {
+ pr_err("dce_flow: fifo depth too large %d > %d\n",
+ params->fifo_depth, MAX_FIFO_SIZE);
+ goto failed_params;
+ }
+
+ flow->proc_flags = 0;
+ SET_BF32_TK(flow->proc_flags, DCE_PROCESS_OO, NONE_LONG);
+ SET_BF32_TK(flow->proc_flags, DCE_PROCESS_Z_FLUSH, NO_FLUSH);
+ SET_BF32_TK(flow->proc_flags, DCE_PROCESS_CF, DEFLATE);
+ SET_BF32_TK(flow->proc_flags, DCE_PROCESS_CE, BEST_POSSIBLE);
+ SET_BF32_TK(flow->proc_flags, DCE_PROCESS_SCUS, NORMAL_MODE);
+
+
+ /* set callback functions */
+ flow->cbs.process_cb = params->process_cb;
+ flow->cbs.nop_cb = params->nop_cb;
+ flow->cbs.scr_invalidate_cb = params->scr_invalidate_cb;
+ flow->cbs.base_cb = params->base_cb;
+ /* set compression/decompression mode */
+ flow->mode = params->mode;
+
+ /*
+ * QMan driver invokes these callback function when a frame is dequeued
+ * on the tx frame queue
+ */
+ flow->fq_tx.cb = dce_fq_base_tx;
+ flow->fq_rx.cb = dce_fq_base_rx;
+
+ /*
+ * allow a fifo depth of 1. Need to bump to 2 for kfifo since
+ * it only allows power of 2, starting with 2. Otherwise it
+ * will round down.
+ */
+ flow->wanted_fifo_depth = params->fifo_depth;
+ if (params->fifo_depth == 1)
+ ret = kfifo_alloc(&flow->fifo, 2, GFP_KERNEL);
+ else
+ ret = kfifo_alloc(&flow->fifo, flow->wanted_fifo_depth,
+ GFP_KERNEL);
+ if (ret) {
+ pr_err("dce_flow: error allocating kfifo 0x%x\n", ret);
+ goto failed_params;
+ }
+ flow->actual_fifo_depth = kfifo_size(&flow->fifo);
+
+ pr_debug("Requested fifo %d, actual %d\n",
+ flow->wanted_fifo_depth, flow->actual_fifo_depth);
+
+ /* Create the Rx frame queue. Use QMan multi-core locking always */
+ ret = qman_create_fq(flow->fqrx_id, QMAN_FQ_FLAG_TO_DCPORTAL |
+ ((flow->fqrx_id) ? 0 : QMAN_FQ_FLAG_DYNAMIC_FQID) |
+ QMAN_FQ_FLAG_LOCKED, &flow->fq_rx);
+ if (ret) {
+ pr_err("dce_flow: failed to create RX frame queue 0x%x\n", ret);
+ goto failed_create_rx_fq;
+ }
+ ret = qman_create_fq(flow->fqtx_id, QMAN_FQ_FLAG_NO_ENQUEUE |
+ ((flow->fqtx_id) ? 0 : QMAN_FQ_FLAG_DYNAMIC_FQID) |
+ QMAN_FQ_FLAG_LOCKED , &flow->fq_tx);
+ if (ret) {
+ pr_err("dce_flow: failed to create TX frame queue 0x%x\n", ret);
+ goto failed_create_tx_fq;
+ }
+
+ /* Setup RX FQ */
+ ret = configure_rx(flow, &flow->bcfg, params->scr);
+ if (ret) {
+ pr_err("dce_flow: failed to configure RX frame queue 0x%x\n",
+ ret);
+ goto failed_configure_rx_fq;
+ }
+
+ /* Setup TX FQ */
+ ret = configure_tx(flow, flow->use_specified_txfq_dest,
+ flow->txfq_dest);
+ if (ret) {
+ pr_err("dce_flow: failed to configure TX frame queue 0x%x\n",
+ ret);
+ goto failed_configure_tx_fq;
+ }
+ return 0;
+failed_configure_tx_fq:
+ ret_tmp = qman_oos_fq(&flow->fq_rx);
+ BUG_ON(ret_tmp);
+failed_configure_rx_fq:
+ qman_destroy_fq(&flow->fq_tx, 0);
+failed_create_tx_fq:
+ qman_destroy_fq(&flow->fq_rx, 0);
+failed_create_rx_fq:
+ kfifo_free(&flow->fifo);
+failed_params:
+ return ret;
+}
+
+int fsl_dce_flow_fifo_len(struct fsl_dce_flow *flow)
+{
+ return kfifo_len(&flow->fifo);
+}
+
+int fsl_dce_flow_finish(struct fsl_dce_flow *flow, uint32_t flags)
+{
+ int ret = 0;
+ struct qm_mcc_initfq initfq;
+
+ /* This pipeline must be empty */
+ if (kfifo_len(&flow->fifo))
+ return -EBUSY;
+
+ /* Park fq_rx */
+ ret = park(&flow->fq_rx, &initfq);
+ /**
+ * All the conditions for park() to succeed should be met. If
+ * this fails, there's a bug (s/w or h/w).
+ */
+ if (ret)
+ pr_err("fsl_dce: park() should never fail! (%d)\n", ret);
+ /* Rx/Tx are empty so retirement should be immediate */
+ ret = qman_retire_fq(&flow->fq_rx, &flags);
+ BUG_ON(ret);
+ BUG_ON(flags & QMAN_FQ_STATE_BLOCKOOS);
+ ret = qman_retire_fq(&flow->fq_tx, &flags);
+ BUG_ON(ret);
+ BUG_ON(flags & QMAN_FQ_STATE_BLOCKOOS);
+ /* OOS and destroy */
+ ret = qman_oos_fq(&flow->fq_rx);
+ BUG_ON(ret);
+ ret = qman_oos_fq(&flow->fq_tx);
+ BUG_ON(ret);
+ qman_destroy_fq(&flow->fq_rx, 0);
+ qman_destroy_fq(&flow->fq_tx, 0);
+ kfifo_free(&flow->fifo);
+ return 0;
+}
+
+/**
+ * Used for 'work' APIs, convert DCE->QMAN wait flags. The DCE and
+ * QMAN "wait" flags have been aligned so that the below conversion should
+ * compile with good straight-line speed.
+ */
+static inline uint32_t ctrl2eq(uint32_t flags)
+{
+#ifdef CONFIG_FSL_DPA_CAN_WAIT
+ return flags & (QMAN_ENQUEUE_FLAG_WAIT | QMAN_ENQUEUE_FLAG_WAIT_INT);
+#else
+ return flags;
+#endif
+}
+
+/*
+ * Have qman enqueue call this function just before setting the verb so
+ * that we write to our fifo just before having qman process the request.
+ * This way we don't have to remove (rollback) this transaction
+ */
+struct qman_precommit_arg {
+ struct fsl_dce_flow *flow;
+ struct fsl_dce_cmd_token *token;
+};
+
+static int _pre_commit_cb(void *arg)
+{
+ struct qman_precommit_arg *fifo_arg = (struct qman_precommit_arg *)arg;
+ if (unlikely(kfifo_put(&fifo_arg->flow->fifo, *fifo_arg->token) == 0))
+ return -ENOMEM;
+ return 0;
+}
+
+static inline int submit_job(struct fsl_dce_flow *flow, uint32_t flags,
+ struct qm_fd *fd, struct fsl_dce_cmd_token *token)
+{
+ int ret = 0;
+ struct qman_precommit_arg cb_arg;
+
+ cb_arg.flow = flow;
+ cb_arg.token = token;
+
+ if (unlikely(kfifo_len(&flow->fifo) == flow->wanted_fifo_depth))
+ return -ENOMEM;
+
+ ret = qman_enqueue_precommit(&flow->fq_rx, fd, ctrl2eq(flags),
+ _pre_commit_cb, &cb_arg);
+
+ return ret;
+}
+
+int fsl_dce_nop(struct fsl_dce_flow *flow, uint32_t flags, void *callback_tag)
+{
+ struct qm_fd fd;
+ struct fsl_dce_cmd_token token;
+
+ token.callback_tag = callback_tag;
+ /* enqueue the NOP command to DCE */
+ memset(&fd, 0, sizeof(fd));
+ fsl_dce_cmd_set_nop(&fd.cmd);
+ return submit_job(flow, flags, &fd, &token);
+}
+
+int fsl_dce_process(struct fsl_dce_flow *flow, uint32_t flags, struct qm_fd *fd,
+ void *callback_tag)
+{
+ struct fsl_dce_cmd_token token;
+
+ token.callback_tag = callback_tag;
+ /* set process options flags */
+ fd->cmd |= flow->proc_flags;
+ /* This is the primary interface to compress/decompress frames */
+ fsl_dce_cmd_set_process(&fd->cmd);
+ return submit_job(flow, flags, fd, &token);
+}
+
+int fsl_dce_src_invalidate(struct fsl_dce_flow *flow, uint32_t flags,
+ void *callback_tag)
+{
+ struct qm_fd fd;
+ struct fsl_dce_cmd_token token;
+
+ memset(&fd, 0, sizeof(fd));
+
+ token.callback_tag = callback_tag;
+ /* enqueue the DCE_CMD_CTX_INVALIDATE command to DCE */
+ memset(&fd, 0, sizeof(fd));
+ fsl_dce_cmd_set_ctx_invalidate(&fd.cmd);
+ return submit_job(flow, flags, &fd, &token);
+}
+
+static inline void cb_helper(__always_unused struct qman_portal *portal,
+ struct fsl_dce_flow *flow, const struct qm_fd *fd,
+ enum dce_status status)
+{
+ struct fsl_dce_cmd_token token;
+
+ if (unlikely(kfifo_get(&flow->fifo, &token) == 0)) {
+ pr_err("dce_flow: fifo empty\n");
+ return;
+ }
+ flow->cbs.base_cb(flow, fd, token.callback_tag);
+}
+
+/* TODO: this scheme does not allow DCE receivers to use held-active at all. Eg.
+ * there's no configuration of held-active for 'fq', and if there was, there's
+ * (a) nothing in the cb_dqrr() to support "park" or "defer" logic, and (b)
+ * nothing in cb_fqs() to support a delayed FQPN (DCAP_PK) notification. */
+static enum qman_cb_dqrr_result cb_dqrr(struct qman_portal *portal,
+ struct qman_fq *fq, const struct qm_dqrr_entry *dq)
+{
+ enum dce_status status = dq->fd.status & DCE_PROCESS_STATUS_MASK;
+ struct fsl_dce_flow *flow = (struct fsl_dce_flow *)fq;
+
+ /* Put flow into DEAD state is a erious error is received ? */
+ cb_helper(portal, flow, &dq->fd, status);
+ return qman_cb_dqrr_consume;
+}
+
+static void cb_ern(__always_unused struct qman_portal *portal,
+ struct qman_fq *fq, const struct qm_mr_entry *mr)
+{
+ pr_err("ERN un-expected\n");
+ BUG();
+}
+
+static void cb_fqs(__always_unused struct qman_portal *portal,
+ __always_unused struct qman_fq *fq,
+ const struct qm_mr_entry *mr)
+{
+ uint8_t verb = mr->verb & QM_MR_VERB_TYPE_MASK;
+
+ if (verb == QM_MR_VERB_FQRNI)
+ return;
+ /* nothing else is supposed to occur */
+ BUG();
+}
+
diff --git a/drivers/staging/fsl_dce/flib/dce_flow.h b/drivers/staging/fsl_dce/flib/dce_flow.h
new file mode 100644
index 0000000..cf16092
--- /dev/null
+++ b/drivers/staging/fsl_dce/flib/dce_flow.h
@@ -0,0 +1,447 @@
+/* Copyright 2013 Freescale Semiconductor, Inc. */
+
+#ifndef DCE_FLOW_H
+#define DCE_FLOW_H
+
+#include "dce_defs.h"
+#include <linux/fsl_qman.h>
+#include <linux/kfifo.h>
+
+/**
+ * enum dce_mode - selector for compression or decompression
+ * @DCE_COMPRESSION: mode is compression
+ * @DCE_DECOMPRESSIONE: mode is decompression
+ */
+enum dce_mode {
+ DCE_COMPRESSION,
+ DCE_DECOMPRESSION
+};
+
+/**
+ * enum dce_state_config - Flow configuration
+ *
+ * @STATEFUL: Flow is configured as stateful
+ * @STATELESS: Flow is configured as stateless
+ *
+ * A stateful Flow is a series of non-interleaved (i.e. Frames from different
+ * Streams do not interleave within a Flow) Streams to be processed, where a
+ * Stream consists of a series of Frames from the same Flow that together
+ * comprise a complete entity to be compressed/decompressed (e.g. GZIP member,
+ * ZLIB stream, or DEFLATE block). DCE maintains a set of Stream Context values,
+ * or state, for each Stream across the individual Frames that comprise it.
+ * Thus, an in-order series, or Stream, of Frames, making up a complete entity
+ * can be processed over time by DCE without having to be reassembled first.
+ * Further, if processing of an individual Frame within the Stream is
+ * interrupted due to insufficient output buffer space, DCE provides a
+ * mechanism to resume processing of the Stream at a later time with additional
+ * output buffer supplied.
+ *
+ * A stateless Flow is a series of single Frame Streams that are to be
+ * processed, but DCE does not maintain any Stream Context between individual
+ * Frames. From DCE’s point of view, each dequeued Frame on a stateless
+ * Flow is an atomic work unit. If processing of a Frame is interrupted for any
+ * reason, DCE returns it with an exception code but does not maintain or update
+ * any Stream Context that would allow resumption of processing.
+ */
+enum dce_state_config {
+ DCE_STATEFUL,
+ DCE_STATELESS,
+};
+
+/**
+ * enum dce_processing_mode - mode of behavior when processing statful Flows.
+ *
+ * @DCE_RECYCLING: Interrupted streams can be resumed at a later time.
+ * @DCE_TRUNCATION: Interrupted streams cannot be resumed at a later time.
+ *
+ * When processing of an individual Frame within a Stream is interrupted, due to
+ * insufficient output buffer space, on a @DCE_RECYCLING Flow, DCE keeps
+ * context to allow later resumption of processing of the Flow. All
+ * subsequently received Frames are returned to software unmodified. This mode
+ * thus enables resumption of processing of the interrupted Stream at a later
+ * time, even if additional pipelined Frames from the same Flow arrive at DCE
+ * after the exception occurs. To resume processing, software resends (recycles)
+ * the interrupted Frame, and all subsequently drained Frames, to DCE with an
+ * indication that processing of the stream is to be resumed.
+ */
+enum dce_processing_mode {
+ DCE_RECYCLING,
+ DCE_TRUNCATION
+};
+
+/**
+ * enum dce_tsize_coding - Specifies the size of the BMan buffers used to create
+ * scatter/gather tables.
+ *
+ * @DCE_TSIZE_64B: 4 table entries
+ * @DCE_TSIZE_128B: 8 table entries
+ * @DCE_TSIZE_256B: 16 table entries
+ * @DCE_TSIZE_512B: 32 table entries
+ * @DCE_TSIZE_1024B: 64 table entries
+ * @DCE_TSIZE_2048B: 128 table entries
+ * @DCE_TSIZE_4096B: 256 table entries
+ * @DCE_TSIZE_8192B: 512 table entries
+ *
+ * This value is used in the @dce_bman_cfg structure which is used to configure
+ * the usage of BMan when using BMan output buffers.
+ */
+enum dce_tsize_coding {
+ DCE_TSIZE_64B = 0,
+ DCE_TSIZE_128B,
+ DCE_TSIZE_256B,
+ DCE_TSIZE_512B,
+ DCE_TSIZE_1024B,
+ DCE_TSIZE_2048B,
+ DCE_TSIZE_4096B,
+ DCE_TSIZE_8192B
+};
+
+/**
+ * enum dce_compression_format - Specifies the compression format
+ *
+ * @DCE_CF_DEFLATE: deflate encoding format
+ * @DCE_CF_ZLIB: zlib encoding format
+ * @DCE_CF_GZIP: gzip encoding format
+ *
+ * Each PROCESS hardware command received by the DCE hw has a compression format
+ * field.
+ */
+enum dce_compression_format {
+ DCE_CF_DEFLATE,
+ DCE_CF_ZLIB,
+ DCE_CF_GZIP
+};
+
+/**
+ * struct dce_bman_cfg - configuration for BMan usage
+ *
+ * @tsize: size of buffers for scatter/gather tables
+ * @tbpid: buffer pool id for s/g tables
+ * @dmant: data buffer size, mantissa value
+ * @dexp: data buffer size, exponent value
+ * @dbpid: buffer pool is for data buffer
+ *
+ * The DCE treats BMan buffers which hold data vs scatter gather tables
+ * differently. These can be managed from independent buffer pools.
+ */
+struct dce_bman_cfg {
+ /* scatter gather entries size */
+ enum dce_tsize_coding tsize;
+ uint32_t tbpid;
+ /* data buffer configuration */
+ uint32_t dmant; /* range 1..16, gets translated internally */
+ uint32_t dexp; /* range 7..22, gets translated internally */
+ uint32_t dbpid;
+};
+
+/* predeclaration of structure */
+struct fsl_dce_flow;
+
+/* cmd results invoke a user-provided callback of this type */
+typedef void (*fsl_dce_base_cb)(struct fsl_dce_flow *, const struct qm_fd *,
+ void *callback_tag);
+typedef void (*fsl_dce_process_cb)(struct fsl_dce_flow *, const struct qm_fd *,
+ void *callback_tag);
+typedef void (*fsl_dce_nop_cb)(struct fsl_dce_flow *, const struct qm_fd *,
+ void *callback_tag);
+typedef void (*fsl_dce_scr_invalidate_cb)(struct fsl_dce_flow *,
+ const struct qm_fd *, void *callback_tag);
+
+/**
+ * struct fsl_dce_flow_cbs - various command callback functions
+ *
+ * @process_cb: callback to process command
+ * @nop_cb: callback to nop command
+ * @scr_invalidate_cb: callback to stream context record invalidate command
+ */
+struct fsl_dce_flow_cbs {
+ fsl_dce_base_cb base_cb;
+ fsl_dce_process_cb process_cb;
+ fsl_dce_nop_cb nop_cb;
+ fsl_dce_scr_invalidate_cb scr_invalidate_cb;
+};
+
+/**
+ * struct fsl_dce_cmd_token - internal structure used by flow
+ *
+ * @callback_tag: user supplied void pointer.
+ */
+struct fsl_dce_cmd_token {
+ void *callback_tag;
+ uint32_t flags;
+};
+
+/**
+ * struct fsl_dce_flow - pair of QMan frame queues which represents a dce flow
+ *
+ * @fq_tx: dce egress frame queue and associated state change and dequeue
+ * callback functions. This memory must be dma-able.
+ * @fq_rx: dce ingress frame queue and associated state change and ern QMan
+ * callback functions. This memory does NOT have to be dma-able.
+ * @cbs: callback functions
+ * @mode: mode of operation, compression or decompression
+ * @bcfg: BMan configuration
+ * @actual_fifo_depth: internal fifo length
+ * @wanted_fifo_depth: requested size of internal fifo
+ * @fifo: A fifo of commands sent to DCE hw
+ * @fqtx_id: id of tx fq
+ * @fqrx_id: if of rx fq
+ * @use_specified_txfq_dest: use the specified @txfq_dest attribute
+ * @txfq_dest: the tx fq destination attribute
+ * @flags: internal state info
+ * @proc_flags: flags used during PROCESS commands
+ */
+struct fsl_dce_flow {
+ struct qman_fq fq_tx;
+ struct qman_fq fq_rx;
+ struct fsl_dce_flow_cbs cbs;
+ enum dce_mode mode;
+ struct dce_bman_cfg bcfg;
+ uint16_t actual_fifo_depth;
+ uint16_t wanted_fifo_depth;
+ DECLARE_KFIFO_PTR(fifo, struct fsl_dce_cmd_token);
+ uint32_t fqtx_id;
+ uint32_t fqrx_id;
+ bool use_specified_txfq_dest;
+ uint32_t txfq_dest;
+ uint32_t flags;
+ uint32_t proc_flags;
+};
+
+void fsl_dce_flow_setopt_fqtx_id(struct fsl_dce_flow *flow, uint32_t id);
+void fsl_dce_flow_setopt_fqrx_id(struct fsl_dce_flow *flow, uint32_t id);
+void fsl_dce_flow_setopt_bcfg(struct fsl_dce_flow *flow,
+ struct dce_bman_cfg bcfg);
+int fsl_dce_flow_setopt_txfqdest(struct fsl_dce_flow *flow, uint32_t dest);
+int fsl_dce_flow_setopt_outputoffset(struct fsl_dce_flow *flow,
+ uint32_t val); /* DCE_PROCESS_OO_*** value */
+int fsl_dce_flow_setopt_compression_effort(struct fsl_dce_flow *flow,
+ uint32_t val); /* DCE_PROCESS_CE_*** value */
+int fsl_dce_flow_setopt_release_input(struct fsl_dce_flow *flow, bool val);
+int fsl_dce_flow_setopt_base64(struct fsl_dce_flow *flow, bool val);
+
+/**
+ * struct fsl_dce_flow_init_params - parameters to initialize a dce flow
+ *
+ * @mode: compression or decompression
+ * @cbs: function callbacks
+ * @state_config: stateless or statefull
+ * @p_mode: truncation mode or recycle mode
+ * @fifo_depth: wanted depth in internal fifo
+ * @base_cb: Base callback function. QMan will invoke this function callback
+ * on every dequeue from the DCE tx fq.
+ * @process_cb: callback function to invoke on completion of process request.
+ * @nop_cb: callback function to invoke on completion of nop request.
+ * @scr_invalidate_cb: callback function to invoke on completion of a stream
+ * context record invalidate request.
+ * @scr: if statefull configuration, dma memory for Stream Context Record
+ * This memory must be 64B aligned. If compression mode must be 64B in
+ * size. If decompression, must be 128B in size.
+ */
+struct fsl_dce_flow_init_params {
+ enum dce_mode mode;
+ enum dce_state_config state_config;
+ enum dce_processing_mode p_mode;
+ uint16_t fifo_depth;
+ fsl_dce_base_cb base_cb;
+ fsl_dce_process_cb process_cb;
+ fsl_dce_nop_cb nop_cb;
+ fsl_dce_scr_invalidate_cb scr_invalidate_cb;
+ dma_addr_t scr;
+};
+
+/**
+ * fsl_dce_flow_init - Initialize the dce flow
+ *
+ * @flow: the dce flow object to initialize
+ * @params: flow parameters to set.
+ *
+ * Details of what this api does:
+ * creates the RX Frame Queue. attributes include:
+ * rx_fqid (either supplied or allocated)
+ * consumer is a DCPORTAL (ie. DCE)
+ *
+ * creates the TX Frame Queue. attribute include:
+ * tx_fqid (either supplied or allocated)
+ * No Enqueues are permitted.
+ *
+ * Initialise RX Frame Queue:
+ * Schedule the frame queue
+ * set context_a field (stream context record pointer) and output
+ * buffer pool attributes
+ * set context_b field (more buffer pool attributes and Tx Frame
+ * Queue Id.
+ * set @flow->fq_rx.dest.channel. Different channel if
+ * compression is being used, vs decompression.
+ *
+ * Initialise TX Frame Queue:
+ * Schedules the frame queue
+ * sets the stashing parameters
+ * sets @flow->fq_tx.dest.channel. This is either the local
+ * portal on which this api is being invoked on, or
+ * a channel_pool. If channel pool, the fq is placed in
+ * hold active state.
+ */
+int fsl_dce_flow_init(struct fsl_dce_flow *flow,
+ struct fsl_dce_flow_init_params *params);
+
+
+/**
+ * fsl_dce_flow_fifo_len - Number of elements in the fifo
+ *
+ * @flow: the dce flow object to query
+ *
+ * Returns the number of elements in the internal fifo.
+ */
+int fsl_dce_flow_fifo_len(struct fsl_dce_flow *flow);
+
+
+/**
+ * fsl_dce_flow_finish - Finalize the dce flow
+ *
+ * @flow: the dce flow object to finalize
+ * @flags:
+ *
+ * The QMan frame queues will be put out-of-service and destroyed.
+ */
+int fsl_dce_flow_finish(struct fsl_dce_flow *flow, uint32_t flags);
+
+/* Flags for operations */
+#ifdef CONFIG_FSL_DPA_CAN_WAIT
+#define DCE_ENQUEUE_FLAG_WAIT QMAN_ENQUEUE_FLAG_WAIT
+#define DCE_ENQUEUE_FLAG_WAIT_INT QMAN_ENQUEUE_FLAG_WAIT_INT
+#endif
+
+/**
+ * fsl_dce_process - send a DCE PROCESS request
+ *
+ * @flow:an initialized dce flow object
+ * @flags:
+ * @fd: dpaa frame descriptor to enqueue
+ * @callback_tag: optional, returned to the user in associated callback function
+ *
+ * The PROCESS Command invokes DCE’s mission mode operation. It indicates to
+ * DCE that the provided Frame structure (simple or compound) is to be
+ * processed according to the mode of its Frame Queue channel and the Frame’s
+ * associated Stream Context Record, and/or a Stream Configuration Frame. The
+ * PROCESS Command is analogous to an invocation of the zlib inflate() or
+ * deflate() function call.
+ *
+ * On a stateful Flow, the DCE will process the provided input Frame,
+ * potentially write some produced output data into the output Frame (less any
+ * residue data held back), and update the Stream Context Record in
+ * anticipation of processing a subsequent PROCESS command on the same Stream.
+ *
+ * On a stateless Flow, the DCE will attempt to fully process the input Frame
+ * and write all produced output data into the output Frame. If the DCE cannot
+ * complete processing of the input Frame it is simply returned with an error
+ * indication code. No continuation of processing, as is done in a typical zlib
+ * function call, is possible using DCE-maintained context.
+ *
+ * Simple Frames may optionally have their component buffers released to BMan
+ * as the Frame is processed. The simple output Frame that is returned to
+ * Software is constructed of buffers that are acquired from BMan.
+ *
+ * Compound Frames also may optionally have their component buffers released to
+ * BMan. Compound output Frames may be pre-built or constructed of buffers that
+ * are acquired from BMan.
+ *
+ * It is valid for DCE to receive a PROCESS Command Frame that has a null or
+ * zero-length input buffer or zero-length output buffer. DCE will attempt to
+ * process the Frame and update Stream Context Record if necessary.
+ *
+ * For creating GZIP or ZLIB compressed members, the PROCESS Command relies on
+ * the following values in the Stream Configuration Frame, or the Stream Context
+ * Record, fields being valid when the initial Frame of a series (i.e. a Stream)
+ * of Frames is dequeued from QMan:
+ * - ID1, ID2: Required for compression of GZIP members. Values will be
+ * placed into the created header.
+ * - CM: Required for compression of GZIP or ZLIB members. Value will be
+ * places into the created header. This 8-bit field contains the
+ * 8-bit CM field for GZIP compression and the 8-bit CMF field for
+ * ZLIB compression.
+ * - FLG: Required for compression of GZIP or ZLIB members. Value will be
+ * placed into the created header, with unsupported options
+ * overridden to 0 (i.e. FDICT) and computed values overridden by
+ * DCE (i.e. FCHECK).
+ * - MTIME: Only required for creation of GZIP members. Value will be
+ * placed into the created GZIP header.
+ * - XFL: Only required for creation of GZIP members. Value will be placed
+ * into the created GZIP header.
+ * - OS: Only required for creation of GZIP members. Value will be placed
+ * into the created GZIP header.
+ * - XLEN: Only required for creation of GZIP members. If FLG.FEXTRA is set
+ * XLEN bytes of data will be read from EXTRA_PTR and inserted into
+ * the GZIP header.
+ * - NLEN: Only required for creation of GZIP members. If FLG.FNAME is set,
+ * NLEN bytes of data will be read from (EXTRA_PTR + XLEN) and
+ * inserted into the GZIP header. Note that it does not matter
+ * whether or not FLG.FEXTRA is set.
+ * - CLEN: Only required for creation of GZIP members. If FLG.FCOMMENT is
+ * set, CLEN bytes of data will be read from (EXTRA_PTR + XLEN +
+ * NLEN) and inserted into the GZIP header. Note that it does not
+ * matter whether or not FLG.FEXTRA or FLG.FNAME is set.
+ * - EXTRA_PTR: Only required for creation of GZIP members. Only required
+ * if one or more of XLEN, NLEN, or CLEN is non-zero.
+ *
+ * All other Stream Context Record fields will be initialized by DCE prior to
+ * processing the first input Frame (denoted by a set I bit). Any stale values
+ * present are ignored and updated afterwards. Note that in order for the
+ * created compressed stream to be RFC compliant, care must be taken to ensure
+ * that the provisioned header values are consistent with DCE’s output. For
+ * example, DCE is only capable of producing GZIP streams with CM=8 and CINFO=4,
+ * so these values must be provisioned in order to create properly formed GZIP
+ * members.
+ *
+ * On decompression Flows, DCE validates the received header information found
+ * in the first N1 bytes of the Stream for consistency with the CF field
+ * setting. Any inconsistencies in the header or unsupported/reserved values
+ * present in the STATUS/CMD fields will result in an Invalid STATUS/CMD error
+ * or the appropriate GZIP, ZLIB, or DEFLATE header error. The PROCESS Command
+ * supports the same set of flush parameters as zlib inflate() and deflate()
+ * calls do.
+ */
+int fsl_dce_process(struct fsl_dce_flow *flow, uint32_t flags,
+ struct qm_fd *fd, void *callback_tag);
+
+/**
+ * fsl_dce_nop - send a DCE NOP request
+ *
+ * @flow: an initialized dce flow object
+ * @flags: bit-mask of DCE_FLOW_OP_*** options
+ * @callback_tag: optional, returned to the user in associated callback function
+ *
+ * Sends a NOP command to the DCE. The flow must be initialized. Returns
+ * zero on success. If no flags are specified the api will return after the
+ * command has been enqueued.
+ * The NOP Command provides Software with a non-invasive ordering mechanism to
+ * ensure that all preceding input Frames from the associated Stream have been
+ * fully processed, without needing to send a compress or decompress command
+ * through the DCE.
+ */
+int fsl_dce_nop(struct fsl_dce_flow *flow, uint32_t flags, void *callback_tag);
+
+/**
+ * fsl_dce_scr_invalidate - send a DCE Context Invalidate request
+ *
+ * @flow: an initiazed dce flow object
+ * @flags: bit-mask of DCE_FLOW_OP_*** options
+ * @callback_tag: optional, returned to the user in associated callback function
+ *
+ * Sends a Context Invalidate command to the DCE. Returns zero on success. If no
+ * flags are specified the api will return after the command has been enqueued.
+ * The Context Invalidate Command provides Software with a means to invalidate a
+ * cached copy of a Stream Context Record in the DCE hardware. The invalidate
+ * command guarantees that the system memory locations used by, or referenced
+ * by, the context can be returned to Software. As its name implies, the
+ * Context Invalidate command does not cause an updated copy of the Stream
+ * Context Record to be written to system memory, so it will cause a loss of
+ * information if used in the middle of Stream that is being processed. This
+ * command is only useful when processed on a stateful Flow. If it is received
+ * on a stateless Frame Queue it has no effect.
+ */
+int fsl_dce_scr_invalidate(struct fsl_dce_flow *flow, uint32_t flags,
+ void *callback_tag);
+
+#endif /* DCE_FLOW_H */
+
diff --git a/drivers/staging/fsl_dce/flib/dce_gzip_helper.h b/drivers/staging/fsl_dce/flib/dce_gzip_helper.h
new file mode 100644
index 0000000..6f5dbb8
--- /dev/null
+++ b/drivers/staging/fsl_dce/flib/dce_gzip_helper.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ */
+
+#ifndef FL_DCE_GZIP_HELPER_H
+#define FL_DCE_GZIP_HELPER_H
+
+#include "dce_defs.h"
+
+/* GZIP constants */
+#define GZIP_ID1 0x1f
+#define GZIP_ID2 0x8b
+#define GZIP_ID1_ID2 0x1f8b
+#define GZIP_CM_DEFLATE 8
+
+/* GZIP FLaGs settings */
+#define GZIP_FLG_FTEXT 0x01
+#define GZIP_FLG_FHCRC 0x02
+#define GZIP_FLG_FEXTRA 0x04
+#define GZIP_FLG_FNAME 0x08
+#define GZIP_FLG_FCOMMENT 0x10
+
+/* GZIP XFL */
+#define GZIP_XFL_MAX_COMPRESSION 2
+#define GZIP_XFL_FASTEST_ALGO 4
+
+/* GZIP OS */
+#define GZIP_OS_FAT 0
+#define GZIP_OS_AMIGA 1
+#define GZIP_OS_VMS 2
+#define GZIP_OS_UNIX 3
+#define GZIP_OS_VM_CMS 4
+#define GZIP_OS_ATARI 5
+#define GZIP_OS_HPFS 6
+#define GZIP_OS_MACINTOSH 7
+#define GZIP_OS_Z_SYSTEM 8
+#define GZIP_OS_CP_M 9
+#define GZIP_OS_TOPS_20 10
+#define GZIP_OS_NTFS 11
+#define GZIP_OS_QDOS 12
+#define GZIP_OS_ACORN 13
+#define GZIP_OS_UNKNOWN 255
+
+/**
+ * set_extra_ptr_content - set the content of the extra_ptr
+ *
+ * @extra_ptr: location where extra_data, comment and filename are located.
+ * @extra_ptr_size: number of byte that extra_ptr points to
+ * @extra_data: gzip extra data container
+ * @extra_data_size: size in bytes to use in extra_data
+ * @filename: NULL terminated filename or can be NULL
+ * @comment: NULL terminated comment or can be NULL
+ *
+ * @extra_data_size + strlen(@filename)+1 + strlen(@comment)+1 <= extra_ptr_size
+ * return 0 on success
+ * NOTE: Don't think I can define this api like this because of dma_add_t.
+ * The intent is to copy in contiguous memory first the extra data followed
+ * by the file name and then the comment at the extra_ptr location.
+ * But I think this has to be cpu address, not dma address.
+ */
+static inline int set_extra_ptr_content(void *extra_ptr, size_t extra_ptr_size,
+ void *extra_data, size_t extra_data_size, char *filename, char *comment)
+{
+ size_t filename_size = 0, comment_size = 0;
+
+ if (filename)
+ filename_size = strlen(filename) + 1;
+ if (comment)
+ comment_size = strlen(comment) + 1;
+
+ if (extra_ptr_size < extra_data_size + filename_size + comment_size)
+ return -EINVAL;
+ memcpy(extra_ptr, extra_data, extra_data_size);
+ memcpy(extra_ptr + extra_data_size, filename, filename_size);
+ memcpy(extra_ptr + extra_data_size + filename_size, comment,
+ comment_size);
+ return 0;
+}
+
+/**
+ * init_gzip_header - initialize the gzip header in the stream configuration
+ * stream
+ *
+ * @scf: A stream configuration frame which is 64 byte aligned and at least
+ * 64 bytes in size. The following fields are set:
+ * ID1 = 31
+ * ID2 = 139
+ * CM = 8
+ * FLG, MTIME, XFL, XLEN, NLEN, CLEN = 0
+ * OS = GZIP_OS_UNIX
+ * EXTRA_PTR is left unmodified.
+ */
+static inline void init_gzip_header(struct scf_64b *scf)
+{
+ set_id1id2(scf, GZIP_ID1_ID2);
+ set_cm(scf, GZIP_CM_DEFLATE);
+ set_flg(scf, 0);
+ set_mtime(scf, 0);
+ set_xfl(scf, GZIP_XFL_MAX_COMPRESSION);
+ set_os(scf, GZIP_OS_UNIX);
+}
+
+#endif /* FL_DCE_GZIP_HELPER_H */
+
diff --git a/drivers/staging/fsl_dce/flib/dce_helper.h b/drivers/staging/fsl_dce/flib/dce_helper.h
new file mode 100644
index 0000000..d6fe3d0
--- /dev/null
+++ b/drivers/staging/fsl_dce/flib/dce_helper.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ */
+
+#ifndef FL_DCE_HELPER_H
+#define FL_DCE_HELPER_H
+
+#include "dce_defs.h"
+
+/**
+ * get_dce_status - returns lowest 8 bits
+ * @fd_status: frame descriptor 32bit field
+ */
+static inline enum dce_status fsl_dce_get_status(uint32_t fd_status)
+{
+ return (enum dce_status)
+ GET_BF32(fd_status, DCE_PROCESS_STATUS);
+};
+
+/* stateful dma memory minimum size and alignment requirements */
+
+/* compression or decompression */
+#define PENDING_OUTPUT_MIN_SIZE 8192
+#define PENDING_OUTPUT_ALIGN 64 /* not required, but optimal */
+
+/* compression only */
+#define SCR_COMPRESSION_MIN_SIZE 64
+#define SCR_COMPRESSION_ALIGN 64
+#define HISTORY_COMPRESSION_MIN_SIZE 4096
+#define HISTORY_COMPRESSION_ALIGN 64
+
+/* decompression only */
+#define SCR_DECOMPRESSION_MIN_SIZE 128
+#define SCR_DECOMPRESSION_ALIGN 64
+#define HISTORY_DECOMPRESSION_MIN_SIZE 32768
+#define HISTORY_DECOMPRESSION_ALIGN 64
+#define DECOMPRESSION_CTX_MIN_SIZE 256
+#define DECOMPRESSION_CTX_ALIGN 64 /* not required, but optimal */
+
+/* Various Stream Context Frame Helpers */
+
+/**
+ * fsl_dce_statefull_decompression_dma - dma memory required for statefull
+ * decompression
+ *
+ * @scf: the stream context frame object to set the corresponding dma memory
+ * pointers. This need to be subsequently sent using a process command
+ * while setting the USPC.
+ * @pending_output: must be minumum of PENDING_OUTPUT_MIN_SIZE, and optimal
+ * if alignment is PENDING_OUTPUT_ALIGN
+ * @history: minimum size is HISTORY_DECOMPRESSION_MIN_SIZE with alignment of
+ * HISTORY_DECOMPRESSION_ALIGN
+ * @decomp_ctxt: must be minimum size of DECOMPRESSION_CTX_MIN_SIZE, with
+ * optimal alignment of DECOMPRESSION_CTX_ALIGN
+ */
+static inline void fsl_dce_statefull_decompression_dma(struct scf_64b *scf,
+ dma_addr_t pending_output, dma_addr_t history, dma_addr_t decomp_ctxt)
+{
+ set_pending_output_ptr(scf, pending_output);
+ set_history_ptr(scf, history);
+ set_decomp_ctxt_ptr(scf, decomp_ctxt);
+}
+
+/**
+ * fsl_dce_statefull_compression_dma - dma memory required for statefull
+ * compression
+ *
+ * @scf: the stream context frame object to set the corresponding dma memory
+ * pointers. This will subsequently be sent using a process command while
+ * setting the USPC.
+ * @pending_output: must be minumum of PENDING_OUTPUT_MIN_SIZE, and optimal
+ * if alignment is PENDING_OUTPUT_ALIGN
+ * history: minimum size is HISTORY_COMPRESSION_MIN_SIZE with alignment of
+ * HISTORY_COMPRESSION_ALIGN
+ */
+static inline void fsl_dce_statefull_compression_dma(struct scf_64b *scf,
+ dma_addr_t pending_output, dma_addr_t history)
+{
+ set_pending_output_ptr(scf, pending_output);
+ set_history_ptr(scf, history);
+}
+
+/* DCE input command helpers */
+static inline void fsl_dce_cmd_set_process(uint32_t *cmd)
+{
+ SET_BF32_TK(*cmd, DCE_CMD, PROCESS);
+}
+
+static inline void fsl_dce_cmd_set_ctx_invalidate(uint32_t *cmd)
+{
+ SET_BF32_TK(*cmd, DCE_CMD, CTX_INVALIDATE);
+}
+
+static inline void fsl_dce_cmd_set_nop(uint32_t *cmd)
+{
+ SET_BF32_TK(*cmd, DCE_CMD, NOP);
+}
+
+/* DCE process command helpers */
+static inline void fsl_dce_cmd_set_compression_effort_none(uint32_t *cmd)
+{
+ SET_BF32_TK(*cmd, DCE_PROCESS_CE, NONE);
+}
+static inline void fsl_dce_cmd_set_compression_effort_statichuff(uint32_t *cmd)
+
+{
+ SET_BF32_TK(*cmd, DCE_PROCESS_CE, STATIC_HUFF_STRMATCH);
+}
+
+#endif /* FL_DCE_HELPER_H */
+
diff --git a/drivers/staging/fsl_dce/flib/dce_regs.h b/drivers/staging/fsl_dce/flib/dce_regs.h
new file mode 100644
index 0000000..201ff76
--- /dev/null
+++ b/drivers/staging/fsl_dce/flib/dce_regs.h
@@ -0,0 +1,546 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ */
+
+#ifndef FL_DCE_REGS_H
+#define FL_DCE_REGS_H
+
+/* Memory Mapped Registers */
+
+/** @Description struct for defining dce CCSR registes */
+struct dce_regs {
+ /* DCE Global Common Configuration */
+ uint32_t cfg; /* DCE configuration */
+ uint8_t reserved1[0x014-0x004];
+ uint32_t oll; /* Output Length Limit */
+ uint8_t reserved2[0x024-0x018];
+ uint32_t hcl; /* Hop Count Limit */
+ uint8_t reserved3[0x03c-0x028];
+ uint32_t idle; /* DCE Idle status */
+ uint8_t reserved4[0x100-0x040];
+
+ /* System Memory Configuration */
+ uint32_t liodnbr; /* LIODN Base */
+ uint32_t srcidr; /* Source ID Register */
+ uint32_t smcacr; /* System Memory Cache Attribute Control */
+ uint32_t smpcr; /* System Memory Priority Control */
+ uint32_t icir; /* Internal Context Invalidate */
+ uint8_t reserved5[0x200-0x114];
+
+ /* Statistics */
+ uint32_t cibc_h; /* Compressor Input Bytes count High */
+ uint32_t cibc_l; /* Compressor Input Bytes count Low */
+ uint32_t cobc_h; /* Compressor Output Bytes count High */
+ uint32_t cobc_l; /* Compressor Output Bytes count Low */
+ uint32_t dibc_h; /* Decompressor Input Bytes count High */
+ uint32_t dibc_l; /* Decompressor Input Bytes count Low */
+ uint32_t dobc_h; /* Decompressor Output Bytes count High */
+ uint32_t dobc_l; /* Decompressor Output Bytes count Low */
+ uint8_t reserved6[0x3f8-0x220];
+
+ /* Block ID */
+ uint32_t ip_rev_1; /* DCE IP Block Revision 1 */
+ uint32_t ip_rev_2; /* DCE IP Block Revision 2 */
+
+ /* Interrupt */
+ uint32_t isr; /* Interrupt Status */
+ uint32_t ier; /* Interrupt Enable */
+ uint32_t isdr; /* Interrupt Status Disable */
+ uint32_t iir; /* Interrupt Inhibit */
+ uint32_t ifr; /* Interrupt Force */
+ uint8_t reserved7[0x440-0x414];
+
+ /* Error status */
+ uint32_t ecc1bes; /* ECC 1-Bit Error Status */
+ uint32_t ecc2bes; /* ECC 2-Bit Error Status */
+ uint32_t eccaddr; /* ECC Address */
+ uint32_t ecc1th; /* ECC 1-Bit Threshold */
+ uint32_t dhecc1ec; /*
+ * Decompression History memory ECC 1-Bit Error
+ * Count
+ */
+ uint32_t cxecc1ec; /*
+ * Internal Context memory ECC 1-Bit Error
+ * Count
+ */
+ uint32_t cbecc1ec; /* Internal Data memory ECC 1-Bit Error Count */
+ uint8_t reserved8[0x480-0x45C];
+ /* revision 1.1 */
+ uint32_t uwe_info_h; /* Unreported Write Error Information High */
+ uint32_t uwe_info_l; /* Unreported Write Error Information Low */
+ /* pad out to 4k */
+ uint8_t padding[0x1000-0x488];
+};
+
+/* masks and shifts */
+
+/* DCE Configuration definitions */
+
+/* Read Safe Behavior */
+#define DCE_CFG_RSD_SHIFT 20
+#define DCE_CFG_RSD_MASK (0x1UL << DCE_CFG_RSD_SHIFT)
+/* RSD Tokens */
+#define DCE_CFG_RSD_ENABLE 0x0UL
+#define DCE_CFG_RSD_DISABLE 0x1UL
+
+/* Dynamic Power Management Disable */
+#define DCE_CFG_DPMD_SHIFT 17
+#define DCE_CFG_DPMD_MASK (0x1UL << DCE_CFG_DPMD_SHIFT)
+/* DPMD Tokens */
+#define DCE_CFG_DPMD_ENABLE 0x0UL
+#define DCE_CFG_DPMD_DISABLE 0x1UL
+
+/* Enable Level */
+#define DCE_CFG_EN_SHIFT 0
+#define DCE_CFG_EN_MASK (0x3UL << DCE_CFG_EN_SHIFT)
+
+/* Enable level Tokens */
+#define DCE_CFG_EN_DISABLE 0x0UL
+#define DCE_CFG_EN_PAUSE 0x1UL
+#define DCE_CFG_EN_RESERVED 0x2UL
+#define DCE_CFG_EN_ENABLE 0x3UL
+
+/* Output Length Limit */
+#define DCE_OLL_SHIFT 0
+#define DCE_OLL_MASK (0xffffUL << DCE_OLL_SHIFT)
+
+/* Hop Count Limit */
+#define DCE_HCL_SHIFT 0
+#define DCE_HCL_MASK (0x3ffUL << DCE_HCL_SHIFT)
+
+/* Idle status */
+#define DCE_IDLE_STOPPED_SHIFT 8
+#define DCE_IDLE_STOPPED_MASK (0x1UL << DCE_IDLE_STOPPED_SHIFT)
+
+/* Stopped Tokens */
+#define DCE_IDLE_STOPPED_YES 0x1UL
+#define DCE_IDLE_STOPPED_NO 0x0UL
+/* Idle */
+#define DCE_IDLE_IDLE_SHIFT 0
+#define DCE_IDLE_IDLE_MASK (0x1UL << DCE_IDLE_IDLE_SHIFT)
+
+/* Idle Tokens */
+#define DCE_IDLE_IDLE_YES 0x1UL
+#define DCE_IDLE_IDLE_NO 0x0UL
+
+/* DCE System memory configuration */
+
+/* LIODN Base */
+#define DCE_LIODNBR_QI_SHARED_LIODN_BASE_SHIFT 16
+#define DCE_LIODNBR_QI_SHARED_LIODN_BASE_MASK \
+ (0xfffUL << DCE_LIODNBR_QI_SHARED_LIODN_BASE_SHIFT)
+
+#define DCE_LIODNBR_QI_JOB_LIODN_BASE_SHIFT 0
+#define DCE_LIODNBR_QI_JOB_LIODN_BASE_MASK \
+ (0xfffUL << DCE_LIODNBR_QI_JOB_LIODN_BASE_SHIFT)
+
+/* Source ID */
+#define DCE_SCRID_SHIFT 0
+#define DCE_SRCID_MASK (0xffUL << DCE_SCRID_SHIFT)
+
+/* System Memory Cache Attribute Control */
+#define DCE_SMCACR_CHWC_SHIFT 28
+#define DCE_SMCACR_CHWC_MASK (0x3UL << DCE_SMCACR_CHWC_SHIFT)
+
+/* CHWC Tokens */
+#define DCE_SMCACR_CHWC_NON_COHERENT 0x0UL
+#define DCE_SMCACR_CHWC_COHERENT 0x1UL
+#define DCE_SMCACR_CHWC_COHERENT_STASH 0x2UL
+
+#define DCE_SMCACR_SCWC_SHIFT 24
+#define DCE_SMCACR_SCWC_MASK (0x3UL << DCE_SMCACR_SCWC_SHIFT)
+
+/* SCWC Tokens */
+#define DCE_SMCACR_SCWC_NON_COHERENT 0x0UL
+#define DCE_SMCACR_SCWC_COHERENT 0x1UL
+#define DCE_SMCACR_SCWC_COHERENT_STASH 0x2UL
+
+#define DCE_SMCACR_FDWC_SHIFT 20
+#define DCE_SMCACR_FDWC_MASK (0x3UL << DCE_SMCACR_FDWC_SHIFT)
+/* SMCACR Tokens */
+#define DCE_SMCACR_FDWC_NON_COHERENT 0x0UL
+#define DCE_SMCACR_FDWC_COHERENT 0x1UL
+#define DCE_SMCACR_FDWC_COHERENT_STASH 0x2UL
+
+#define DCE_SMCACR_DHWC_SHIFT 16
+#define DCE_SMCACR_DHWC_MASK (0x3UL << DCE_SMCACR_DHWC_SHIFT)
+/* DHWC Tokens */
+#define DCE_SMCACR_DHWC_NON_COHERENT 0x0UL
+#define DCE_SMCACR_DHWC_COHERENT 0x1UL
+#define DCE_SMCACR_DHWC_COHERENT_STASH 0x2UL
+
+#define DCE_SMCACR_CHRC_SHIFT 12
+#define DCE_SMCACR_CHRC_MASK (0x3UL << DCE_SMCACR_CHRC_SHIFT)
+/* CHRC Tokens */
+#define DCE_SMCACR_CHRC_NON_COHERENT 0x0UL
+#define DCE_SMCACR_CHRC_COHERENT 0x1UL
+#define DCE_SMCACR_CHRC_COHERENT_STASH 0x2UL
+
+#define DCE_SMCACR_SCRC_SHIFT 8
+#define DCE_SMCACR_SCRC_MASK (0x3UL << DCE_SMCACR_SCRC_SHIFT)
+/* SCRC Tokens */
+#define DCE_SMCACR_SCRC_NON_COHERENT 0x0UL
+#define DCE_SMCACR_SCRC_COHERENT 0x1UL
+#define DCE_SMCACR_SCRC_COHERENT_STASH 0x2UL
+
+#define DCE_SMCACR_FDRC_SHIFT 4
+#define DCE_SMCACR_FDRC_MASK (0x3UL << DCE_SMCACR_FDRC_SHIFT)
+/* FDRC Tokens */
+#define DCE_SMCACR_FDRC_NON_COHERENT 0x0
+#define DCE_SMCACR_FDRC_COHERENT 0x1
+#define DCE_SMCACR_FDRC_COHERENT_STASH 0x2
+
+#define DCE_SMCACR_DHRC_SHIFT 0
+#define DCE_SMCACR_DHRC_MASK (0x3UL << DCE_SMCACR_DHRC_SHIFT)
+/* DHRC Tokens */
+#define DCE_SMCACR_DHRC_NON_COHERENT 0x0UL
+#define DCE_SMCACR_DHRC_COHERENT 0x1UL
+#define DCE_SMCACR_DHRC_COHERENT_STASH 0x2UL
+
+/* System Memory Priority Control */
+/* Write Priority */
+#define DCE_SMPCR_WP_SHIFT 4
+#define DCE_SMPCR_WP_MASK (0x1UL << DCE_SMPCR_WP_SHIFT)
+/* WP Tokens */
+#define DCE_SMPCR_WP_NORMAL 0x0UL
+#define DCE_SMPCR_WP_ELEVATED 0x1UL
+/* Read Priority */
+#define DCE_SMPCR_RP_SHIFT 0
+#define DCE_SMPCR_RP_MASK (0x1UL << DCE_SMPCR_RP_SHIFT)
+/* RP Tokens */
+#define DCE_SMPCR_RP_NORMAL 0x0UL
+#define DCE_SMPCR_RP_ELEVATED 0x1UL
+
+/* Internal Context Invalid */
+/* Invalidate Internal Context */
+#define DCE_ICIR_ICI_SHIFT 0
+#define DCE_ICIR_ICI_MASK (0x1UL << DCE_ICIR_ICI_SHIFT)
+/* ICIR Tokens */
+#define DCE_ICIR_ICI_NO_EFFECT 0x0
+#define DCE_ICIR_ICI_INVALIDATE 0x1
+
+/* Statistics */
+/* Compressor Input Byte count High */
+#define DCE_CIBC_H_SHIFT 0
+#define DCE_CIBC_H_MASK (0xffffffffUL << DCE_CIBC_H_SHIFT)
+/* Compressor Input Byte count Low */
+#define DCE_CIBC_L_SHIFT 0
+#define DCE_CIBC_L_MASK (0xffffffffUL << DCE_CIBC_L_SHIFT)
+/* Compressor Output Byte count High */
+#define DCE_COBC_H_SHIFT 0
+#define DCE_COBC_H_MASK (0xffffffffUL << DCE_COBC_H_SHIFT)
+/* Compressor Output Byte count Low */
+#define DCE_COBC_L_SHIFT 0
+#define DCE_COBC_L_MASK (0xffffffffUL << DCE_COBC_L_SHIFT)
+
+/* Decompressor Input Byte count High */
+#define DCE_DIBC_H_SHIFT 0
+#define DCE_DIBC_H_MASK (0xffffffffUL << DCE_DIBC_H_SHIFT)
+/* Decompressor Input Byte count Low */
+#define DCE_DIBC_L_SHIFT 0
+#define DCE_DIBC_L_MASK (0xffffffffUL << DCE_DIBC_L_SHIFT)
+/* Decompressor Output Byte count High */
+#define DCE_DOBC_H_SHIFT 0
+#define DCE_DOBC_H_MASK (0xffffffffUL << DCE_DOBC_H_SHIFT)
+/* Decompressor Output Byte count Low */
+#define DCE_DOBC_L_SHIFT 0
+#define DCE_DOBC_L_MASK (0xffffffffUL << DCE_DOBC_L_SHIFT)
+
+/* Block ID */
+/* Revision 1 */
+#define DCE_IP_REV_1_IP_ID_SHIFT 16
+#define DCE_IP_REV_1_IP_ID_MASK (0xffffUL << DCE_IP_REV_1_IP_ID_SHIFT)
+/* IP_ID Tokens */
+#define DCE_IP_REV_1_IP_ID_DCE 0xaf0UL
+/* Major */
+#define DCE_IP_REV_1_IP_MJ_SHIFT 8
+#define DCE_IP_REV_1_IP_MJ_MASK (0xffUL << DCE_IP_REV_1_IP_MJ_SHIFT)
+/* Minor */
+#define DCE_IP_REV_1_IP_MN_SHIFT 0
+#define DCE_IP_REV_1_IP_MN_MASK (0xffUL << DCE_IP_REV_1_IP_MN_SHIFT)
+/* Revision 2 */
+/* Integration Option */
+#define DCE_IP_REV_2_IP_INT_SHIFT 16
+#define DCE_IP_REV_2_IP_INT_MASK (0xffUL << DCE_IP_REV_2_IP_INT_SHIFT)
+/* Errata Revision Level */
+#define DCE_IP_REV_2_IP_ERR_SHIFT 8
+#define DCE_IP_REV_2_IP_ERR_MASK (0xffUL << DCE_IP_REV_2_IP_ERR_SHIFT)
+/* Configuration Option */
+#define DCE_IP_REV_2_IP_CFG_SHIFT 0
+#define DCE_IP_REV_2_IP_CFG_MASK (0xffUL << DCE_IP_REV_2_IP_CFG_SHIFT)
+
+/* Interrupt */
+
+/* Interrupt Status */
+/* Unreported Write Error */
+#define DCE_ISR_UWE_SHIFT 7
+#define DCE_ISR_UWE_MASK (0x1UL << DCE_ISR_UWE_SHIFT)
+/* ISR UWE Tokens */
+#define DCE_ISR_UWE_NONE 0x0UL
+#define DCE_ISR_UWE_AT_LEAST_ONE 0x1UL
+
+/* Single Bit Error */
+#define DCE_ISR_SBE_SHIFT 1
+#define DCE_ISR_SBE_MASK (0x1UL << DCE_ISR_SBE_SHIFT)
+
+/* ISR SBE Tokens */
+#define DCE_ISR_SBE_NONE 0x0UL
+#define DCE_ISR_SBE_AT_LEAST_ONE 0x1UL
+
+/* Double Bit Error */
+#define DCE_ISR_DBE_SHIFT 0
+#define DCE_ISR_DBE_MASK (0x1UL << DCE_ISR_DBE_SHIFT)
+/* ISR DBE Tokens */
+#define DCE_ISR_DBE_NONE 0x0UL
+#define DCE_ISR_DBE_AT_LEAST_ONE 0x1UL
+
+/* Interrupt Enable */
+/* Unreported Write Error */
+#define DCE_IER_UWE_SHIFT 7
+#define DCE_IER_UWE_MASK (0x1UL << DCE_IER_UWE_SHIFT)
+
+/* IER UWE Tokens */
+#define DCE_IER_UWE_DISABLE 0x0UL
+#define DCE_IER_UWE_ENABLE 0x1UL
+
+/* Single Bit Error */
+#define DCE_IER_SBE_SHIFT 1
+#define DCE_IER_SBE_MASK (0x1UL << DCE_IER_SBE_SHIFT)
+/* IER SBE Tokens */
+#define DCE_IER_SBE_DISABLE 0x0
+#define DCE_IER_SBE_ENABLE 0x1
+
+/* Double Bit Error */
+#define DCE_IER_DBE_SHIFT 0
+#define DCE_IER_DBE_MASK (0x1UL << DCE_IER_DBE_SHIFT)
+/* IER DBE Tokens */
+#define DCE_IER_DBE_DISABLE 0x0
+#define DCE_IER_DBE_ENABLE 0x1
+
+/* All interrupts */
+#define DCE_IER_ALL_MASK \
+ (DCE_IER_UWE_MASK | DCE_IER_SBE_MASK | DCE_IER_DBE_MASK)
+#define DCE_IER_ALL_SHIFT 0
+/* IER ALL Tokens */
+#define DCE_IER_ALL_DISABLE 0x0UL
+#define DCE_IER_ALL_ENABLE 0x83UL
+
+/* Interrupt Status Disable */
+/* Unreported Write Error */
+#define DCE_ISDR_UWE_SHIFT 7
+#define DCE_ISDR_UWE_MASK (0x1UL << DCE_ISDR_UWE_SHIFT)
+
+/* IER UWE Tokens */
+#define DCE_ISDR_UWE_DISABLE 0x0UL
+#define DCE_ISDR_UWE_ENABLE 0x1UL
+
+/* Single Bit Error */
+#define DCE_ISDR_SBE_SHIFT 1
+#define DCE_ISDR_SBE_MASK (0x1UL << DCE_ISDR_SBE_SHIFT)
+/* IER SBE Tokens */
+#define DCE_ISDR_SBE_DISABLE 0x0UL
+#define DCE_ISDR_SBE_ENABLE 0x1UL
+
+/* Double Bit Error */
+#define DCE_ISDR_DBE_SHIFT 0
+#define DCE_ISDR_DBE_MASK (0x1UL << DCE_ISDR_DBE_SHIFT)
+/* IER DBE Tokens */
+#define DCE_ISDR_DBE_DISABLE 0x0UL
+#define DCE_ISDR_DBE_ENABLE 0x1UL
+
+/* Interrupt Inhibit */
+/* Inhibit */
+#define DCE_IIR_I_SHIFT 0
+#define DCE_IIR_I_MASK (0x1UL << DCE_IIR_I_SHIFT)
+
+/* IIR I Tokens */
+#define DCE_IIR_I_CLEAR 0x0UL
+#define DCE_IIR_I_SET 0x1UL
+
+/* Interrupt Force */
+/* Unreported Write Error */
+#define DCE_IFR_UWE_SHIFT 7
+#define DCE_IFR_UWE_MASK (0x1UL << DCE_IFR_UWE_SHIFT)
+/* IFR UWE Tokens */
+#define DCE_IFR_UWE_SET 0x1UL
+
+/* Single Bit Error */
+#define DCE_IFR_SBE_SHIFT 1
+#define DCE_IFR_SBE_MASK (0x1UL << DCE_IFR_SBE_SHIFT)
+/* IFR SBE Tokens */
+#define DCE_IFR_SBE_SET 0x1UL
+
+/* Double Bit Error */
+#define DCE_IFR_DBE_SHIFT 0
+#define DCE_IFR_DBE_MASK (0x1UL << DCE_IFR_DBE_SHIFT)
+/* IFR DBE Tokens */
+#define DCE_IFR_DBE_SET 0x1
+
+/* Error Status */
+
+/* ECC 1-Bit Error Status */
+/* Compression History Memory */
+#define DCE_ECC1BES_CBM_SHIFT 2
+#define DCE_ECC1BES_CBM_MASK (0x1UL << DCE_ECC1BES_CBM_MASK)
+
+/* CBM Tokens */
+#define DCE_ECC1BES_CBM_FALSE 0x0UL
+#define DCE_ECC1BES_CBM_TRUE 0x1UL
+#define DCE_ECC1BES_CBM_CLEAR 0x1UL
+
+/* Decompression History Memory */
+#define DCE_ECC1BES_DHM_SHIFT 1
+#define DCE_ECC1BES_DHM_MASK (0x1UL << DCE_ECC1BES_DHM_SHIFT)
+/* DHM Tokens */
+#define DCE_ECC1BES_DHM_FALSE 0x0UL
+#define DCE_ECC1BES_DHM_TRUE 0x1UL
+#define DCE_ECC1BES_DHM_CLEAR 0x1UL
+
+/* Internal Context Memory */
+#define DCE_ECC1BES_CXM_SHIFT 0
+#define DCE_ECC1BES_CXM_MASK (0x1UL << DCE_ECC1BES_CXM_SHIFT)
+/* CXM Tokens */
+#define DCE_ECC1BES_CXM_FALSE 0x0UL
+#define DCE_ECC1BES_CXM_TRUE 0x1UL
+#define DCE_ECC1BES_CXM_CLEAR 0x1UL
+
+/* ECC 2-Bit Error Status */
+/* Compression History Memory */
+#define DCE_ECC2BES_CBM_SHIFT 2
+#define DCE_ECC2BES_CBM_MASK (0x1UL << DCE_ECC2BES_CBM_SHIFT)
+/* CBM Tokens */
+#define DCE_ECC2BES_CBM_FALSE 0x0UL
+#define DCE_ECC2BES_CBM_TRUE 0x1UL
+#define DCE_ECC2BES_CBM_CLEAR 0x1UL
+
+/* Decompression History Memory */
+#define DCE_ECC2BES_DHM_SHIFT 1
+#define DCE_ECC2BES_DHM_MASK (0x1UL << DCE_ECC2BES_DHM_SHIFT)
+/* DHM Tokens */
+#define DCE_ECC2BES_DHM_FALSE 0x0UL
+#define DCE_ECC2BES_DHM_TRUE 0x1UL
+#define DCE_ECC2BES_DHM_CLEAR 0x1UL
+
+/* Internal Context Memory */
+#define DCE_ECC2BES_CXM_SHIFT 0
+#define DCE_ECC2BES_CXM_MASK (0x1UL << DCE_ECC2BES_CXM_SHIFT)
+/* CXM Tokens */
+#define DCE_ECC2BES_CXM_FALSE 0x0UL
+#define DCE_ECC2BES_CXM_TRUE 0x1UL
+#define DCE_ECC2BES_CXM_CLEAR 0x1UL
+
+/* ECC Address */
+/* Capture Error Indication */
+#define DCE_ECCADDR_CAP_SHIFT 31
+#define DCE_ECCADDR_CAP_MASK (0x1UL << DCE_ECCADDR_CAP_SHIFT)
+/* CAP Tokens */
+#define DCE_ECCADDR_CAP_NONE 0x0UL
+#define DCE_ECCADDR_CAP_CAPTURED 0x1UL
+#define DCE_ECCADDR_CAP_CLEAR 0x1UL
+
+/* Capture Error Type */
+#define DCE_ECCADDR_CAT_SHIFT 30
+#define DCE_ECCADDR_CAT_MASK (0x1UL << DCE_ECCADDR_CAT_SHIFT)
+/* CAT Tokens */
+#define DCE_ECCADDR_CAT_SB_ECC 0x0UL
+#define DCE_ECCADDR_CAT_MB_ECC 0x1UL
+
+/* Memory Identifier */
+#define DCE_ECCADDR_MEM_SHIFT 16
+#define DCE_ECCADDR_MEM_MASK (0x1fUL << DCE_ECCADDR_MEM_SHIFT)
+/* MEM Tokens */
+#define DCE_ECCADDR_MEM_DHM0 0x0UL
+#define DCE_ECCADDR_MEM_DHM1 0x1UL
+#define DCE_ECCADDR_MEM_DHM2 0x2UL
+#define DCE_ECCADDR_MEM_DHM3 0x3UL
+#define DCE_ECCADDR_MEM_DHM4 0x4UL
+#define DCE_ECCADDR_MEM_DHM5 0x5UL
+#define DCE_ECCADDR_MEM_DHM6 0x6UL
+#define DCE_ECCADDR_MEM_DHM7 0x7UL
+#define DCE_ECCADDR_MEM_CBM0 0x8UL
+#define DCE_ECCADDR_MEM_CBM1 0x9UL
+#define DCE_ECCADDR_MEM_CBM2 0xaUL
+#define DCE_ECCADDR_MEM_CBM3 0xbUL
+#define DCE_ECCADDR_MEM_CBM4 0xcUL
+#define DCE_ECCADDR_MEM_CBM5 0xdUL
+#define DCE_ECCADDR_MEM_CBM6 0xeUL
+#define DCE_ECCADDR_MEM_CBM7 0xfUL
+#define DCE_ECCADDR_MEM_CXMA0 0x10UL
+#define DCE_ECCADDR_MEM_CXMB0 0x11UL
+#define DCE_ECCADDR_MEM_CXMA1 0x12UL
+#define DCE_ECCADDR_MEM_CXMB1 0x13UL
+#define DCE_ECCADDR_MEM_CXMA2 0x14UL
+#define DCE_ECCADDR_MEM_CXMB2 0x15UL
+#define DCE_ECCADDR_MEM_CXMA3 0x16UL
+#define DCE_ECCADDR_MEM_CXMB3 0x17UL
+#define DCE_ECCADDR_MEM_CXMA4 0x18UL
+#define DCE_ECCADDR_MEM_CXMB4 0x19UL
+#define DCE_ECCADDR_MEM_CXMA5 0x1aUL
+#define DCE_ECCADDR_MEM_CXMB5 0x1bUL
+#define DCE_ECCADDR_MEM_CXMA6 0x1cUL
+#define DCE_ECCADDR_MEM_CXMB6 0x1dUL
+#define DCE_ECCADDR_MEM_CXMA7 0x1eUL
+#define DCE_ECCADDR_MEM_CXMB7 0x1fUL
+
+/* Capture the address within the memory upon which the error occurred */
+#define DCE_ECCADDR_ADDR_SHIFT 0
+#define DCE_ECCADDR_ADDR_MASK (0xffffUL << DCE_ECCADDR_ADDR_SHIFT)
+
+/* ECC 1-Bit Threshold */
+/* Internal Data Memory */
+#define DCE_ECC1TH_DECBM_SHIFT 10
+#define DCE_ECC1TH_DECBM_MASK (0x1UL << DCE_ECC1TH_DECBM_SHIFT)
+/* DECBM Tokens */
+#define DCE_ECC1TH_DECBM_DISABLE 0x1UL
+#define DCE_ECC1TH_DECBM_ENABLE 0x0UL
+
+/* Decompression History Memory */
+#define DCE_ECC1TH_DEDHM_SHIFT 9
+#define DCE_ECC1TH_DEDHM_MASK (0x1UL << DCE_ECC1TH_DEDHM_SHIFT)
+/* DEDHM Tokens */
+#define DCE_ECC1TH_DEDHM_DISABLE 0x1UL
+#define DCE_ECC1TH_DEDHM_ENABLE 0x0UL
+
+/* Internal Context Memory */
+#define DCE_ECC1TH_DECXM_SHIFT 8
+#define DCE_ECC1TH_DECXM_MASK (0x1UL << DCE_ECC1TH_DECXM_SHIFT)
+/* DECXM Tokens */
+#define DCE_ECC1TH_DECXM_DISABLE 0x1UL
+#define DCE_ECC1TH_DECXM_ENABLE 0x0UL
+
+/* Threshold value */
+#define DCE_ECC1TH_THRESH_SHIFT 0
+#define DCE_ECC1TH_THRESH_MASK (0xffUL << DCE_ECC1TH_THRESH_SHIFT)
+
+/* Decompression History memory ECC 1-Bit Count */
+/* Count */
+#define DCE_ECC1EC_COUNT_SHIFT 0
+#define DCE_ECC1EC_COUNT_MASK (0xffUL << DCE_ECC1EC_COUNT_SHIFT)
+
+/* Internal Context ECC 1-Bit Error Count */
+/* Count */
+#define DCE_CXECC1EC_COUNT_SHIFT 0
+#define DCE_CXECC1EC_COUNT_MASK (0xffUL << DCE_CXECC1EC_COUNT_SHIFT)
+
+/* Internal Data ECC 1-Bit Error Count */
+/* Count */
+#define DCE_CBECC1EC_COUNT_SHIFT 0
+#define DCE_CBECC1EC_COUNT_MASK (0xffUL << DCE_CBECC1EC_COUNT_SHIFT)
+
+/* Unreported Write Error Information High */
+/* LIODN */
+#define DCE_UWE_INFO_H_LIODN_SHIFT 16
+#define DCE_UWE_INFO_H_LIODN_MASK (0xfffUL << DCE_UWE_INFO_H_LIODN_SHIFT)
+/* SCRP */
+#define DCE_UWE_INFO_H_SCRP_SHIFT 0
+#define DCE_UWE_INFO_H_SCRP_MASK (0xffUL << DCE_UWE_INFO_H_SCRP_SHIFT)
+
+/* Unreported Write Error Information Low */
+#define DCE_UWE_INFO_L_SCRP_SHIFT 6
+#define DCE_UWE_INFO_L_SCRP_MASK (0x3ffffffUL << DCE_UWE_INFO_L_SCRP_SHIFT)
+
+/* helper to get combine and shift SCRPH and L */
+#define DCE_GEN_SCRP(scrp_h, scrp_l) \
+ (((uint64_t)scrp_h << 32 | scrp_l) << DCE_UWE_INFO_L_SCRP_SHIFT)
+
+#endif /* FL_DCE_REGS_H */
diff --git a/drivers/staging/fsl_dce/fsl_dce.h b/drivers/staging/fsl_dce/fsl_dce.h
new file mode 100644
index 0000000..8df4316
--- /dev/null
+++ b/drivers/staging/fsl_dce/fsl_dce.h
@@ -0,0 +1,60 @@
+/* Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * This software is provided by Freescale Semiconductor "as is" and any
+ * express or implied warranties, including, but not limited to, the implied
+ * warranties of merchantability and fitness for a particular purpose are
+ * disclaimed. In no event shall Freescale Semiconductor be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential damages
+ * (including, but not limited to, procurement of substitute goods or services;
+ * loss of use, data, or profits; or business interruption) however caused and
+ * on any theory of liability, whether in contract, strict liability, or tort
+ * (including negligence or otherwise) arising in any way out of the use of
+ * this software, even if advised of the possibility of such damage.
+ */
+
+#ifndef FSL_DCE_H
+#define FSL_DCE_H
+
+/****************/
+/* KERNEL SPACE */
+/****************/
+
+#ifdef __KERNEL__
+
+/* Does dce have access to ccsr */
+int fsl_dce_have_control(void);
+
+/**************************/
+/* control-plane only API */
+/**************************/
+
+enum fsl_dce_stat_attr {
+ DCE_COMP_INPUT_BYTES,
+ DCE_COMP_OUTPUT_BYTES,
+ DCE_DECOMP_INPUT_BYTES,
+ DCE_DECOMP_OUTPUT_BYTES
+};
+
+int fsl_dce_get_stat(enum fsl_dce_stat_attr attr, uint64_t *val, int reset);
+int fsl_dce_clear_stat(enum fsl_dce_stat_attr attr);
+
+#endif /* __KERNEL__ */
+
+#endif /* FSL_DCE_H */
diff --git a/drivers/staging/fsl_dce/fsl_dce_chunk.c b/drivers/staging/fsl_dce/fsl_dce_chunk.c
new file mode 100644
index 0000000..18895b4
--- /dev/null
+++ b/drivers/staging/fsl_dce/fsl_dce_chunk.c
@@ -0,0 +1,154 @@
+/* Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * This software is provided by Freescale Semiconductor "as is" and any
+ * express or implied warranties, including, but not limited to, the implied
+ * warranties of merchantability and fitness for a particular purpose are
+ * disclaimed. In no event shall Freescale Semiconductor be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential damages
+ * (including, but not limited to, procurement of substitute goods or services;
+ * loss of use, data, or profits; or business interruption) however caused and
+ * on any theory of liability, whether in contract, strict liability, or tort
+ * (including negligence or otherwise) arising in any way out of the use of
+ * this software, even if advised of the possibility of such damage.
+ */
+
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/spinlock_types.h>
+#include <linux/cpumask.h>
+#include <linux/rbtree.h>
+#include <linux/export.h>
+#include "fsl_dce_chunk.h"
+
+#define DCE_FIFO_DEPTH 256
+
+static void chunk_base_cb(struct fsl_dce_flow *flow, const struct qm_fd *fd,
+ void *callback_tag)
+{
+ if (likely(ISEQ_32FTK(fd->cmd, DCE_CMD, PROCESS)))
+ flow->cbs.process_cb(flow, fd, callback_tag);
+ else if (ISEQ_32FTK(fd->cmd, DCE_CMD, CTX_INVALIDATE))
+ flow->cbs.scr_invalidate_cb(flow, fd, callback_tag);
+ else if (ISEQ_32FTK(fd->cmd, DCE_CMD, NOP))
+ flow->cbs.nop_cb(flow, fd, callback_tag);
+}
+
+int fsl_dce_chunk_setup2(struct fsl_dce_chunk *chunk,
+ uint32_t flags,
+ enum dce_mode mode,
+ enum dce_compression_format cf,
+ struct dce_bman_cfg *bcfg,
+ fsl_dce_process_cb process_cb,
+ fsl_dce_nop_cb nop_cb)
+{
+ int ret = 0;
+ struct fsl_dce_flow_init_params flow_params;
+
+ if (!chunk)
+ return -EINVAL;
+
+ memset(&flow_params, 0, sizeof(flow_params));
+ memset(chunk, 0, sizeof(*chunk));
+
+ chunk->cf = cf;
+
+ /* QMan frame queue ids will be allocated */
+ if (bcfg)
+ fsl_dce_flow_setopt_bcfg(&chunk->flow, *bcfg);
+ flow_params.mode = mode;
+ flow_params.fifo_depth = DCE_FIFO_DEPTH;
+ flow_params.state_config = DCE_STATELESS;
+ flow_params.base_cb = chunk_base_cb;
+ flow_params.process_cb = process_cb;
+ flow_params.nop_cb = nop_cb;
+ ret = fsl_dce_flow_init(&chunk->flow, &flow_params);
+ if (ret) {
+ pr_debug("dce_chunk: err ret = %d\n", ret);
+ return ret;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(fsl_dce_chunk_setup2);
+
+int fsl_dce_chunk_fifo_len(struct fsl_dce_chunk *chunk)
+{
+ return fsl_dce_flow_fifo_len(&chunk->flow);
+}
+EXPORT_SYMBOL(fsl_dce_chunk_fifo_len);
+
+
+int fsl_dce_chunk_destroy(struct fsl_dce_chunk *chunk, uint32_t flags,
+ void *callback_tag)
+{
+ return fsl_dce_flow_finish(&chunk->flow, flags);
+}
+EXPORT_SYMBOL(fsl_dce_chunk_destroy);
+
+
+int fsl_dce_chunk_process(struct fsl_dce_chunk *chunk, uint32_t flags,
+ struct qm_fd *fd, void *callback_tag)
+{
+ if (chunk->cf == DCE_CF_ZLIB)
+ SET_BF32_TK(fd->cmd, DCE_PROCESS_CF, ZLIB);
+ else if (chunk->cf == DCE_CF_GZIP)
+ SET_BF32_TK(fd->cmd, DCE_PROCESS_CF, GZIP);
+
+ /* Bug 15470 */
+ SET_BF32_TK(fd->cmd, DCE_PROCESS_Z_FLUSH, FINISH);
+
+ /* Bug 14479, see 14477, must set UHC for gzip/zlib */
+ SET_BF32_TK(fd->cmd, DCE_PROCESS_UHC, YES);
+ return fsl_dce_process(&chunk->flow, flags, fd, callback_tag);
+}
+EXPORT_SYMBOL(fsl_dce_chunk_process);
+
+int fsl_dce_chunk_nop(struct fsl_dce_chunk *chunk, uint32_t flags,
+ void *callback_tag)
+{
+ return fsl_dce_nop(&chunk->flow, flags, callback_tag);
+}
+EXPORT_SYMBOL(fsl_dce_chunk_nop);
+
+int fsl_dce_chunk_deflate_params(struct fsl_dce_chunk *chunk,
+ uint32_t bman_output_offset,
+ bool bman_release_input,
+ bool base64,
+ uint32_t ce)
+{
+ fsl_dce_flow_setopt_outputoffset(&chunk->flow, bman_output_offset);
+ fsl_dce_flow_setopt_release_input(&chunk->flow, bman_release_input);
+ fsl_dce_flow_setopt_base64(&chunk->flow, base64);
+ fsl_dce_flow_setopt_compression_effort(&chunk->flow, ce);
+ return 0;
+}
+EXPORT_SYMBOL(fsl_dce_chunk_deflate_params);
+
+int fsl_dce_chunk_inflate_params(struct fsl_dce_chunk *chunk,
+ uint32_t bman_output_offset,
+ bool bman_release_input,
+ bool base64)
+{
+ fsl_dce_flow_setopt_outputoffset(&chunk->flow, bman_output_offset);
+ fsl_dce_flow_setopt_release_input(&chunk->flow, bman_release_input);
+ fsl_dce_flow_setopt_base64(&chunk->flow, base64);
+ return 0;
+}
+EXPORT_SYMBOL(fsl_dce_chunk_inflate_params);
+
diff --git a/drivers/staging/fsl_dce/fsl_dce_chunk.h b/drivers/staging/fsl_dce/fsl_dce_chunk.h
new file mode 100644
index 0000000..156c568
--- /dev/null
+++ b/drivers/staging/fsl_dce/fsl_dce_chunk.h
@@ -0,0 +1,86 @@
+/* Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * This software is provided by Freescale Semiconductor "as is" and any
+ * express or implied warranties, including, but not limited to, the implied
+ * warranties of merchantability and fitness for a particular purpose are
+ * disclaimed. In no event shall Freescale Semiconductor be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential damages
+ * (including, but not limited to, procurement of substitute goods or services;
+ * loss of use, data, or profits; or business interruption) however caused and
+ * on any theory of liability, whether in contract, strict liability, or tort
+ * (including negligence or otherwise) arising in any way out of the use of
+ * this software, even if advised of the possibility of such damage.
+ */
+
+#ifndef FSL_DCE_CHUNK_H
+#define FSL_DCE_CHUNK_H
+
+#include <linux/fsl_qman.h>
+#include <linux/fsl_bman.h>
+#include "flib/dce_flow.h"
+
+/*
+ * DCE chunk is a stateless compressor/decompressor object. Each Frame which
+ * is compressed/decompressed is one complete work item and doesn't depend
+ * on previous Frames. As an example a Frame should be considered as one
+ * complete file.
+ */
+struct fsl_dce_chunk {
+ struct fsl_dce_flow flow;
+
+ enum dce_compression_format cf; /* deflate, zlib or gzip */
+ /* optional BMan output settings */
+ bool use_bman_output;
+ uint32_t flags; /* internal state */
+ spinlock_t lock;
+ wait_queue_head_t queue;
+};
+
+int fsl_dce_chunk_setup2(struct fsl_dce_chunk *chunk,
+ uint32_t flags,
+ enum dce_mode mode,
+ enum dce_compression_format cf,
+ struct dce_bman_cfg *bcfg,
+ fsl_dce_process_cb process_cb,
+ fsl_dce_nop_cb nop_cb);
+
+int fsl_dce_chunk_fifo_len(struct fsl_dce_chunk *chunk);
+
+int fsl_dce_chunk_destroy(struct fsl_dce_chunk *chunk, uint32_t flags,
+ void *callback_tag);
+
+int fsl_dce_chunk_deflate_params(struct fsl_dce_chunk *chunk,
+ uint32_t bman_output_offset,
+ bool bman_release_input,
+ bool base64,
+ uint32_t ce); /* DCE_PROCESS_CE_* value */
+
+int fsl_dce_chunk_inflate_params(struct fsl_dce_chunk *chunk,
+ uint32_t bman_output_offset,
+ bool bman_release_input,
+ bool base64);
+
+int fsl_dce_chunk_process(struct fsl_dce_chunk *chunk, uint32_t flags,
+ struct qm_fd *fd, void *callback_tag); /* optional callback tag */
+
+int fsl_dce_chunk_nop(struct fsl_dce_chunk *chunk, uint32_t flags,
+ void *callback_tag); /* optional callback tag */
+
+#endif /* FSL_DCE_CHUNK_H */
diff --git a/drivers/staging/fsl_dce/fsl_dce_stream.c b/drivers/staging/fsl_dce/fsl_dce_stream.c
new file mode 100644
index 0000000..c49ef2f
--- /dev/null
+++ b/drivers/staging/fsl_dce/fsl_dce_stream.c
@@ -0,0 +1,306 @@
+/* Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * This software is provided by Freescale Semiconductor "as is" and any
+ * express or implied warranties, including, but not limited to, the implied
+ * warranties of merchantability and fitness for a particular purpose are
+ * disclaimed. In no event shall Freescale Semiconductor be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential damages
+ * (including, but not limited to, procurement of substitute goods or services;
+ * loss of use, data, or profits; or business interruption) however caused and
+ * on any theory of liability, whether in contract, strict liability, or tort
+ * (including negligence or otherwise) arising in any way out of the use of
+ * this software, even if advised of the possibility of such damage.
+ */
+
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/spinlock_types.h>
+#include <linux/cpumask.h>
+#include <linux/rbtree.h>
+#include <linux/export.h>
+#include "fsl_dce_stream.h"
+#include "dce_sys.h"
+
+static void stream_base_cb(struct fsl_dce_flow *flow, const struct qm_fd *fd,
+ void *callback_tag)
+{
+ if (likely(ISEQ_32FTK(fd->cmd, DCE_CMD, PROCESS)))
+ flow->cbs.process_cb(flow, fd, callback_tag);
+ else if (ISEQ_32FTK(fd->cmd, DCE_CMD, CTX_INVALIDATE))
+ flow->cbs.scr_invalidate_cb(flow, fd, callback_tag);
+ else if (ISEQ_32FTK(fd->cmd, DCE_CMD, NOP))
+ flow->cbs.nop_cb(flow, fd, callback_tag);
+}
+
+int fsl_dce_stream_setup(struct fsl_dce_stream *stream,
+ uint32_t flags,
+ enum dce_mode mode,
+ enum dce_compression_format cf,
+ fsl_dce_process_cb process_cb,
+ fsl_dce_nop_cb nop_cb,
+ fsl_dce_scr_invalidate_cb scr_invalidate_cb)
+{
+ return fsl_dce_stream_setup2(stream, flags, mode, cf,
+ DCE_TRUNCATION, NULL, process_cb, nop_cb, scr_invalidate_cb);
+}
+EXPORT_SYMBOL(fsl_dce_stream_setup);
+
+static int allocate_stateful_dma_resources(struct fsl_dce_stream *stream,
+ enum dce_mode mode,
+ enum dce_processing_mode pmode)
+{
+ int ret = -ENOMEM;
+
+ if (mode == DCE_COMPRESSION) {
+ stream->hw_comp_scr = fsl_dce_hw_scr_64b_new();
+ if (!stream->hw_comp_scr)
+ return ret;
+ stream->comp_hist = fsl_dce_hw_compress_history_new();
+ if (!stream->comp_hist)
+ return ret;
+ if (pmode == DCE_RECYCLING) {
+ stream->pending_output_ptr =
+ fsl_dce_hw_pending_output_new();
+ if (!stream->pending_output_ptr)
+ return ret;
+ }
+ } else {
+ stream->hw_decomp_scr = fsl_dce_hw_scr_128b_new();
+ if (!stream->hw_decomp_scr)
+ return ret;
+ stream->decomp_hist = fsl_dce_hw_decompress_history_new();
+ if (!stream->decomp_hist)
+ return ret;
+ if (pmode == DCE_RECYCLING) {
+ stream->pending_output_ptr =
+ fsl_dce_hw_pending_output_new();
+ if (!stream->pending_output_ptr)
+ return ret;
+ }
+ stream->decomp_ctx_ptr = fsl_dce_hw_decomp_ctxt_new();
+ if (!stream->decomp_ctx_ptr)
+ return ret;
+ }
+ return 0;
+}
+
+static void free_stateful_dma_resources(struct fsl_dce_stream *stream,
+ enum dce_mode mode,
+ enum dce_processing_mode pmode)
+{
+ if (mode == DCE_COMPRESSION) {
+ if (stream->hw_comp_scr)
+ fsl_dce_hw_scr_64b_free(stream->hw_comp_scr);
+ stream->comp_hist = fsl_dce_hw_compress_history_new();
+ if (stream->comp_hist)
+ fsl_dce_hw_compress_history_free(stream->comp_hist);
+ if (pmode == DCE_RECYCLING) {
+ stream->pending_output_ptr =
+ fsl_dce_hw_pending_output_new();
+ if (stream->pending_output_ptr)
+ fsl_dce_hw_pending_output_free(
+ stream->pending_output_ptr);
+ }
+ } else {
+ if (stream->hw_decomp_scr)
+ fsl_dce_hw_scr_128b_free(stream->hw_decomp_scr);
+ if (stream->decomp_hist)
+ fsl_dce_hw_decompress_history_free(stream->decomp_hist);
+ if (pmode == DCE_RECYCLING) {
+ stream->pending_output_ptr =
+ fsl_dce_hw_pending_output_new();
+ if (stream->pending_output_ptr)
+ fsl_dce_hw_pending_output_free(
+ stream->pending_output_ptr);
+ }
+ if (stream->decomp_ctx_ptr)
+ fsl_dce_hw_decomp_ctxt_free(stream->decomp_ctx_ptr);
+ }
+}
+
+void fsl_dce_build_scf_uspc(struct fsl_dce_stream *stream, struct scf_64b *scf)
+{
+ set_pending_output_ptr(scf, fsl_dce_map(stream->pending_output_ptr));
+ if (stream->flow.mode == DCE_COMPRESSION)
+ set_history_ptr(scf, fsl_dce_map(stream->hw_comp_scr));
+ else {
+ set_history_ptr(scf, fsl_dce_map(stream->hw_decomp_scr));
+ set_decomp_ctxt_ptr(scf, fsl_dce_map(stream->decomp_ctx_ptr));
+ }
+ set_pmode(scf, stream->pmode);
+}
+EXPORT_SYMBOL(fsl_dce_build_scf_uspc);
+
+void fsl_dce_attach_scf_64b_2_3mbr_sgtable(struct scf_64b *scf,
+ struct qm_sg_entry sg_table[3])
+{
+ qm_sg_entry_set64(&sg_table[2], fsl_dce_map(scf));
+ sg_table[2].length = sizeof(*scf);
+ sg_table[2].final = 1;
+}
+EXPORT_SYMBOL(fsl_dce_attach_scf_64b_2_3mbr_sgtable);
+
+void fsl_dce_attach_scf_128b_2_3mbr_sgtable(struct scf_128b *scf,
+ struct qm_sg_entry sg_table[3])
+{
+ qm_sg_entry_set64(&sg_table[2], fsl_dce_map(scf));
+ sg_table[2].length = sizeof(*scf);
+ sg_table[2].final = 1;
+}
+EXPORT_SYMBOL(fsl_dce_attach_scf_128b_2_3mbr_sgtable);
+
+void fsl_dce_attach_3mbr_sgtable_2_fd(struct qm_sg_entry sg_table[3],
+ struct qm_fd *fd)
+{
+ qm_fd_addr_set64(fd, fsl_dce_map(sg_table));
+ fd->format = qm_fd_compound;
+}
+EXPORT_SYMBOL(fsl_dce_attach_3mbr_sgtable_2_fd);
+
+int fsl_dce_stream_setup2(struct fsl_dce_stream *stream,
+ uint32_t flags,
+ enum dce_mode mode,
+ enum dce_compression_format cf,
+ enum dce_processing_mode pmode,
+ struct dce_bman_cfg *bcfg,
+ fsl_dce_process_cb process_cb,
+ fsl_dce_nop_cb nop_cb,
+ fsl_dce_scr_invalidate_cb scr_invalidate_cb)
+{
+ int ret = 0;
+ struct fsl_dce_flow_init_params flow_params;
+
+ memset(&flow_params, 0, sizeof(flow_params));
+
+ if (!stream)
+ return -EINVAL;
+ memset(stream, 0, sizeof(*stream));
+
+ stream->pmode = pmode;
+
+ ret = allocate_stateful_dma_resources(stream, mode, pmode);
+ if (ret) {
+ free_stateful_dma_resources(stream, mode, pmode);
+ return ret;
+ }
+
+ /* QMan frame queue ids will be allocated */
+ if (bcfg)
+ fsl_dce_flow_setopt_bcfg(&stream->flow, *bcfg);
+ flow_params.mode = mode;
+ flow_params.fifo_depth = 1;
+ flow_params.state_config = DCE_STATEFUL;
+ flow_params.base_cb = stream_base_cb;
+ flow_params.process_cb = process_cb;
+ flow_params.nop_cb = nop_cb;
+ flow_params.scr_invalidate_cb = scr_invalidate_cb;
+ if (mode == DCE_COMPRESSION)
+ flow_params.scr = fsl_dce_map(stream->hw_comp_scr);
+ else
+ flow_params.scr = fsl_dce_map(stream->hw_decomp_scr);
+ /* RECYCLE mode only supports sychronous mode */
+ ret = fsl_dce_flow_init(&stream->flow, &flow_params);
+ if (ret) {
+ pr_debug("err ret=%d\n", ret);
+ free_stateful_dma_resources(stream, mode, pmode);
+ return ret;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(fsl_dce_stream_setup2);
+
+int fsl_dce_stream_destroy(struct fsl_dce_stream *stream, uint32_t flags,
+ void *callback_tag)
+{
+ int ret;
+
+ ret = fsl_dce_flow_finish(&stream->flow, flags);
+ if (!ret)
+ free_stateful_dma_resources(stream, stream->flow.mode,
+ stream->pmode);
+ return 0;
+}
+EXPORT_SYMBOL(fsl_dce_stream_destroy);
+
+
+int fsl_dce_stream_init_scr(struct fsl_dce_stream *stream, struct qm_fd *fd,
+ void *callback_tag)
+{
+ SET_BF32_TK(fd->cmd, DCE_PROCESS_USPC, YES);
+ return fsl_dce_process(&stream->flow, 0, fd, callback_tag);
+}
+EXPORT_SYMBOL(fsl_dce_stream_init_scr);
+
+int fsl_dce_stream_process(struct fsl_dce_stream *stream, struct qm_fd *fd,
+ bool initial_frame, int z_flush, void *callback_tag)
+{
+ switch (z_flush) {
+ case DCE_PROCESS_Z_FLUSH_NO_FLUSH:
+ case DCE_PROCESS_Z_FLUSH_PARTIAL_FLUSH:
+ case DCE_PROCESS_Z_FLUSH_SYNC_FLUSH:
+ case DCE_PROCESS_Z_FLUSH_FULL_FLUSH:
+ case DCE_PROCESS_Z_FLUSH_FINISH:
+ case DCE_PROCESS_Z_FLUSH_BLOCK:
+ case DCE_PROCESS_Z_FLUSH_TREES:
+ SET_BF32(fd->cmd, DCE_PROCESS_Z_FLUSH, z_flush);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (initial_frame)
+ SET_BF32_TK(fd->cmd, DCE_PROCESS_INITIAL, SET);
+ return fsl_dce_process(&stream->flow, 0, fd, callback_tag);
+}
+EXPORT_SYMBOL(fsl_dce_stream_process);
+
+int fsl_dce_stream_nop(struct fsl_dce_stream *stream, uint32_t flags,
+ void *callback_tag)
+{
+ return fsl_dce_nop(&stream->flow, flags, callback_tag);
+}
+EXPORT_SYMBOL(fsl_dce_stream_nop);
+
+int fsl_dce_stream_deflate_params(struct fsl_dce_stream *stream,
+ uint32_t bman_output_offset,
+ bool bman_release_input,
+ bool base64,
+ uint32_t ce)
+{
+ fsl_dce_flow_setopt_outputoffset(&stream->flow, bman_output_offset);
+ fsl_dce_flow_setopt_release_input(&stream->flow, bman_release_input);
+ fsl_dce_flow_setopt_base64(&stream->flow, base64);
+ fsl_dce_flow_setopt_compression_effort(&stream->flow, ce);
+ return 0;
+}
+EXPORT_SYMBOL(fsl_dce_stream_deflate_params);
+
+int fsl_dce_stream_inflate_params(struct fsl_dce_stream *stream,
+ uint32_t bman_output_offset,
+ bool bman_release_input,
+ bool base64)
+{
+ fsl_dce_flow_setopt_outputoffset(&stream->flow, bman_output_offset);
+ fsl_dce_flow_setopt_release_input(&stream->flow, bman_release_input);
+ fsl_dce_flow_setopt_base64(&stream->flow, base64);
+ return 0;
+}
+EXPORT_SYMBOL(fsl_dce_stream_inflate_params);
+
diff --git a/drivers/staging/fsl_dce/fsl_dce_stream.h b/drivers/staging/fsl_dce/fsl_dce_stream.h
new file mode 100644
index 0000000..09713d9
--- /dev/null
+++ b/drivers/staging/fsl_dce/fsl_dce_stream.h
@@ -0,0 +1,187 @@
+/* Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * This software is provided by Freescale Semiconductor "as is" and any
+ * express or implied warranties, including, but not limited to, the implied
+ * warranties of merchantability and fitness for a particular purpose are
+ * disclaimed. In no event shall Freescale Semiconductor be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential damages
+ * (including, but not limited to, procurement of substitute goods or services;
+ * loss of use, data, or profits; or business interruption) however caused and
+ * on any theory of liability, whether in contract, strict liability, or tort
+ * (including negligence or otherwise) arising in any way out of the use of
+ * this software, even if advised of the possibility of such damage.
+ */
+
+#ifndef FSL_DCE_STREAM_H
+#define FSL_DCE_STREAM_H
+
+#include <linux/fsl_qman.h>
+#include <linux/fsl_bman.h>
+#include "flib/dce_flow.h"
+
+/* (De)Allocate DCE hardware resources */
+struct fsl_dce_hw_scr_64b;
+struct fsl_dce_hw_scr_128b;
+struct fsl_dce_hw_compress_history;
+struct fsl_dce_hw_decompress_history;
+struct fsl_dce_hw_pending_output;
+struct fsl_dce_hw_decomp_ctxt;
+
+struct fsl_dce_hw_scr_64b *fsl_dce_hw_scr_64b_new(void);
+void fsl_dce_hw_scr_64b_free(struct fsl_dce_hw_scr_64b *);
+struct fsl_dce_hw_scr_128b *fsl_dce_hw_scr_128b_new(void);
+void fsl_dce_hw_scr_128b_free(struct fsl_dce_hw_scr_128b *);
+struct fsl_dce_hw_compress_history *fsl_dce_hw_compress_history_new(void);
+void fsl_dce_hw_compress_history_free(struct fsl_dce_hw_compress_history *);
+struct fsl_dce_hw_decompress_history *fsl_dce_hw_decompress_history_new(void);
+void fsl_dce_hw_decompress_history_free
+ (struct fsl_dce_hw_decompress_history *);
+struct fsl_dce_hw_pending_output *fsl_dce_hw_pending_output_new(void);
+void fsl_dce_hw_pending_output_free(struct fsl_dce_hw_pending_output *);
+struct fsl_dce_hw_decomp_ctxt *fsl_dce_hw_decomp_ctxt_new(void);
+void fsl_dce_hw_decomp_ctxt_free(struct fsl_dce_hw_decomp_ctxt *);
+
+/************************/
+/* high-level functions */
+/************************/
+struct fsl_dce_stream;
+
+/* DCE stream is a stateful compressor/decompressor object */
+struct fsl_dce_stream {
+ struct fsl_dce_flow flow;
+
+ enum dce_compression_format cf; /* deflate, zlib or gzip */
+ enum dce_processing_mode pmode; /* recycle, trunc */
+
+ /* optional BMan output settings */
+ bool use_bman_output;
+ uint32_t process_params; /* inflate, deflate parameters */
+
+ /* hw dma scr structure */
+ union {
+ struct fsl_dce_hw_scr_64b *hw_comp_scr;
+ struct fsl_dce_hw_scr_128b *hw_decomp_scr;
+ };
+
+ /*
+ * history window
+ * decompression: 32k size 64B aligned
+ * compression: 4k size, 64B aligned
+ */
+ union {
+ struct fsl_dce_hw_compress_history *comp_hist;
+ struct fsl_dce_hw_decompress_history *decomp_hist;
+ };
+
+ /*
+ * Pending Ouput Data
+ * decomp: 8256 bytes, comp: 8202. No hard requirement on alignment,
+ * but 64 is optimal. Only needed in recycle mode.
+ */
+ struct fsl_dce_hw_pending_output *pending_output_ptr;
+
+ /*
+ * Decompression Context Pointer, used to store the alphabet
+ * This is a 256 byte buffer with no alignment requirement
+ */
+ struct fsl_dce_hw_decomp_ctxt *decomp_ctx_ptr;
+
+ uint32_t flags; /* internal state */
+ spinlock_t lock;
+ wait_queue_head_t queue;
+};
+/**
+ * fsl_dce_stream_setup - setup for dce stream object
+ * @stream:
+ * @mode:
+ * @cf:
+ *
+ * Simple dce stream setup function
+ */
+int fsl_dce_stream_setup(struct fsl_dce_stream *stream,
+ uint32_t flags,
+ enum dce_mode mode,
+ enum dce_compression_format cf,
+ fsl_dce_process_cb process_cb,
+ fsl_dce_nop_cb nop_cb,
+ fsl_dce_scr_invalidate_cb scr_invalidate_cb);
+
+/**
+ * fsl_dce_stream_setup2 - Advanced setup for dce stream object
+ * @stream:
+ * @mode:
+ * @cf:
+ * @pmode:
+ * @bcfg
+ *
+ * Advanced dce stream setup function.
+ * A dce_stream in DCE HW terminology is an object which is able to perform
+ * statful (de)compression in either recycle or truncation processing mode.
+ * In recycle mode, only synchronous processing is permitted and therefore
+ * a fifo_depth of 1 is only permitted.
+ */
+int fsl_dce_stream_setup2(struct fsl_dce_stream *stream,
+ uint32_t flags,
+ enum dce_mode mode,
+ enum dce_compression_format cf,
+ enum dce_processing_mode pmode,
+ struct dce_bman_cfg *bcfg,
+ fsl_dce_process_cb process_cb,
+ fsl_dce_nop_cb nop_cb,
+ fsl_dce_scr_invalidate_cb scr_invalidate_cb);
+
+int fsl_dce_stream_destroy(struct fsl_dce_stream *stream, uint32_t flags,
+ void *callback_tag);
+
+int fsl_dce_stream_deflate_params(struct fsl_dce_stream *stream,
+ uint32_t bman_output_offset,
+ bool bman_release_input,
+ bool base64,
+ uint32_t ce); /* DCE_PROCESS_CE_* value */
+
+int fsl_dce_stream_inflate_params(struct fsl_dce_stream *stream,
+ uint32_t bman_output_offset,
+ bool bman_release_input,
+ bool base64);
+
+/*
+ * This is the mission mode api.
+ */
+int fsl_dce_stream_process(struct fsl_dce_stream *stream,
+ struct qm_fd *fd,
+ bool initial_frame, /* if initial frame, sets I bit */
+ int z_flush, /* one of DCE_PROCESS_Z_* values */
+ void *callback_tag); /* optional callback tag */
+
+int fsl_dce_stream_nop(struct fsl_dce_stream *stream, uint32_t flags,
+ void *callback_tag); /* optional callback tag */
+
+/* helper apis */
+int fsl_dce_stream_init_scr(struct fsl_dce_stream *stream, struct qm_fd *fd,
+ void *callback_tag);
+void fsl_dce_attach_3mbr_sgtable_2_fd(struct qm_sg_entry sg_table[3],
+ struct qm_fd *fd);
+void fsl_dce_attach_scf_128b_2_3mbr_sgtable(struct scf_128b *scf,
+ struct qm_sg_entry sg_table[3]);
+void fsl_dce_attach_scf_64b_2_3mbr_sgtable(struct scf_64b *scf,
+ struct qm_sg_entry sg_table[3]);
+void fsl_dce_build_scf_uspc(struct fsl_dce_stream *stream, struct scf_64b *scf);
+
+#endif /* FSL_DCE_STREAM_H */
diff --git a/drivers/staging/fsl_dce/tests/Makefile b/drivers/staging/fsl_dce/tests/Makefile
new file mode 100644
index 0000000..4f95d7e
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/Makefile
@@ -0,0 +1,2 @@
+obj-y += common/ chunk_comp_def_cf/ performance_simple/
+
diff --git a/drivers/staging/fsl_dce/tests/chunk_comp_def_cf/Makefile b/drivers/staging/fsl_dce/tests/chunk_comp_def_cf/Makefile
new file mode 100644
index 0000000..dd7b96c
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/chunk_comp_def_cf/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_FSL_DCE_TESTS) += dce_chunk_comp_def_cf_tester.o
+dce_chunk_comp_def_cf_tester-objs := dce_chunk_comp_def_cf_test.o
+
diff --git a/drivers/staging/fsl_dce/tests/chunk_comp_def_cf/dce_chunk_comp_def_cf_test.c b/drivers/staging/fsl_dce/tests/chunk_comp_def_cf/dce_chunk_comp_def_cf_test.c
new file mode 100644
index 0000000..7bb2ff8
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/chunk_comp_def_cf/dce_chunk_comp_def_cf_test.c
@@ -0,0 +1,694 @@
+/* Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * This software is provided by Freescale Semiconductor "as is" and any
+ * express or implied warranties, including, but not limited to, the implied
+ * warranties of merchantability and fitness for a particular purpose are
+ * disclaimed. In no event shall Freescale Semiconductor be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential damages
+ * (including, but not limited to, procurement of substitute goods or services;
+ * loss of use, data, or profits; or business interruption) however caused and
+ * on any theory of liability, whether in contract, strict liability, or tort
+ * (including negligence or otherwise) arising in any way out of the use of
+ * this software, even if advised of the possibility of such damage.
+ */
+
+#include <linux/vmalloc.h>
+#include "../../dce_sys.h"
+#include "../../fsl_dce_chunk.h"
+#include "../../flib/dce_helper.h"
+
+#include "../common/bible.txt.128k.h"
+#include "../common/bible.txt.64k.h"
+#include "../common/bible.txt.32k.h"
+#include "../common/bible.txt.16k.h"
+#include "../common/bible.txt.8k.h"
+#include "../common/bible.txt.4k.h"
+#include "../common/bible.txt.2k.h"
+#include "../common/bible.txt.1k.h"
+#include "../common/bible.txt.128b.h"
+#include "../common/test_frame_helpers.h"
+
+MODULE_AUTHOR("Jeffrey Ladouceur");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("FSL DCE test: stateless trunc deflate compoundframes");
+
+static int block_size = 4096;
+
+module_param(block_size, int, 0);
+
+static void chunk_process_cb(struct fsl_dce_flow *flow,
+ const struct qm_fd *fd, void *callback_tag)
+{
+ struct dce_process_cf_req *req =
+ (struct dce_process_cf_req *)callback_tag;
+
+ pr_info("fsl_dce_chunk_process_cb flow = %p, fd = %p, cb_tab = %p\n",
+ flow, fd, callback_tag);
+
+ req->output_fd = *fd;
+ complete(&req->cb_done);
+
+}
+
+static void chunk_nop_cb(struct fsl_dce_flow *flow,
+ const struct qm_fd *fd, void *callback_tag)
+{
+ struct dce_nop_req *nop_req = (struct dce_nop_req *)callback_tag;
+ pr_info("fsl_dce_chunk_nop_cb flow = %p, fd = %p, cb_tab = %p\n",
+ flow, fd, callback_tag);
+
+ nop_req->output_fd = *fd;
+ complete(&nop_req->cb_done);
+}
+
+struct dce_test_ctx {
+ struct fsl_dce_chunk deflate_chunk;
+ struct fsl_dce_chunk inflate_chunk;
+};
+
+static int destroy_test_ctx(struct dce_test_ctx *ctx)
+{
+ int ret;
+
+ ret = fsl_dce_chunk_destroy(&ctx->deflate_chunk, 0, NULL);
+ if (ret) {
+ BUG();
+ return ret;
+ }
+ ret = fsl_dce_chunk_destroy(&ctx->inflate_chunk, 0, NULL);
+ if (ret) {
+ BUG();
+ return ret;
+ }
+ return 0;
+}
+
+
+
+static int init_test_ctx(struct dce_test_ctx *ctx,
+ enum dce_compression_format format)
+{
+ int ret, ret_fail;
+ uint32_t flags = 0;
+
+ /* initialize a compression deflate stream */
+ ret = fsl_dce_chunk_setup2(&ctx->deflate_chunk, flags,
+ DCE_COMPRESSION, format, NULL, chunk_process_cb, chunk_nop_cb);
+
+ if (ret) {
+ BUG();
+ goto fail_deflate_setup;
+ }
+
+ ret = fsl_dce_chunk_deflate_params(&ctx->deflate_chunk,
+ DCE_PROCESS_OO_NONE_LONG, false, false,
+ DCE_PROCESS_CE_BEST_POSSIBLE);
+
+ if (ret) {
+ BUG();
+ goto fail_deflate_params;
+ }
+
+ /* initialize a decompression deflate stream */
+ ret = fsl_dce_chunk_setup2(&ctx->inflate_chunk, flags,
+ DCE_DECOMPRESSION, format, NULL, chunk_process_cb,
+ chunk_nop_cb);
+
+ if (ret) {
+ BUG();
+ goto fail_inflate_setup;
+ }
+
+ ret = fsl_dce_chunk_inflate_params(&ctx->inflate_chunk,
+ DCE_PROCESS_OO_NONE_LONG, false, false);
+
+ if (ret) {
+ BUG();
+ goto fail_inflate_params;
+ }
+
+ return 0;
+
+fail_inflate_params:
+ ret_fail = fsl_dce_chunk_destroy(&ctx->inflate_chunk, 0, NULL);
+ BUG_ON(ret_fail);
+fail_inflate_setup:
+fail_deflate_params:
+ ret_fail = fsl_dce_chunk_destroy(&ctx->deflate_chunk, 0, NULL);
+ BUG_ON(ret_fail);
+fail_deflate_setup:
+ return ret;
+}
+
+
+static int do_test(struct dce_test_ctx *ctx,
+ enum dce_compression_format format,
+ char *input_data, size_t input_len, size_t block_len,
+ size_t output_len)
+{
+ int ret;
+ struct dce_process_cf_req *def_process_req, *inf_process_req;
+ struct dce_nop_req *nop_req;
+
+ ret = init_test_ctx(ctx, format);
+ if (ret)
+ goto fail_init_test_ctx;
+
+ nop_req = kmalloc(sizeof(*nop_req), GFP_KERNEL);
+ if (!nop_req) {
+ ret = -ENOMEM;
+ goto fail_deflate_nop;
+ }
+
+ init_completion(&nop_req->cb_done);
+
+ /* send a nop cmd */
+ ret = fsl_dce_chunk_nop(&ctx->deflate_chunk, 0, nop_req);
+ if (ret) {
+ BUG();
+ goto fail_deflate_nop;
+ }
+ pr_info("Sent NOP on deflate path\n");
+
+ wait_for_completion(&nop_req->cb_done);
+
+ pr_info("Got NOP on deflate path\n");
+
+ ret = fsl_dce_chunk_nop(&ctx->inflate_chunk, 0, nop_req);
+ if (ret) {
+ BUG();
+ goto fail_inflate_nop;
+ }
+ pr_info("Sent NOP on inflate path\n");
+
+ wait_for_completion(&nop_req->cb_done);
+
+ pr_info("Got NOP on inflate path\n");
+
+ /* Perform a deflate operation */
+
+ def_process_req = kzalloc(sizeof(*def_process_req), GFP_KERNEL);
+ if (!def_process_req) {
+ BUG();
+ goto fail_inflate_params;
+ }
+ pr_info("Allocated def_process_req\n");
+
+ def_process_req->v_output = vmalloc(output_len);
+ if (!def_process_req) {
+ BUG();
+ goto fail_v_output;
+ }
+
+ init_completion(&def_process_req->cb_done);
+
+ ret = alloc_dce_data(input_len, block_len,
+ &def_process_req->input_data);
+ if (ret) {
+ BUG();
+ goto fail_alloc_dce_data_input;
+ }
+
+ pr_info("Printing input_list info\n");
+ print_dce_data_list(&def_process_req->input_data);
+
+ ret = alloc_dce_data(input_len, block_len,
+ &def_process_req->output_data);
+ if (ret) {
+ BUG();
+ goto fail_alloc_dce_data_output;
+ }
+
+ pr_info("Printing output_list info\n");
+ print_dce_data_list(&def_process_req->output_data);
+
+ ret = copy_input_to_dce_data(input_data, input_len,
+ &def_process_req->input_data);
+ if (ret) {
+ BUG();
+ goto fail_alloc_dce_data_output;
+ }
+
+ pr_info("Printing input after copy info\n");
+ print_dce_data_list(&def_process_req->input_data);
+
+ ret = dma_map_dce_data(&def_process_req->input_data, DMA_BIDIRECTIONAL);
+ if (ret) {
+ BUG();
+ goto fail_alloc_dce_data_output;
+ }
+
+ pr_info("Printing input after dma_map info\n");
+ print_dce_data_list(&def_process_req->input_data);
+
+ ret = dma_map_dce_data(&def_process_req->output_data,
+ DMA_BIDIRECTIONAL);
+ if (ret) {
+ BUG();
+ goto fail_dma_map_deflate_output_data;
+ }
+
+ pr_info("Printing output after dma_map info\n");
+ print_dce_data_list(&def_process_req->output_data);
+
+ ret = attach_data_list_to_sg(&def_process_req->dce_cf[0],
+ &def_process_req->output_data,
+ DMA_BIDIRECTIONAL);
+ if (ret) {
+ BUG();
+ goto fail_output_attach_data_to_sg_deflate;
+ }
+
+ ret = attach_data_list_to_sg(&def_process_req->dce_cf[1],
+ &def_process_req->input_data,
+ DMA_BIDIRECTIONAL);
+ if (ret) {
+ BUG();
+ goto fail_input_attach_data_to_sg_deflate;
+ }
+
+ def_process_req->dce_cf[2].final = 1;
+
+ def_process_req->input_fd._format2 = qm_fd_compound;
+ qm_fd_addr_set64(&def_process_req->input_fd,
+ fsl_dce_map(def_process_req->dce_cf));
+
+ print_dce_fd(def_process_req->input_fd);
+ print_dce_sg(def_process_req->dce_cf[0]);
+ print_dce_sg(def_process_req->dce_cf[1]);
+ print_dce_sg(def_process_req->dce_cf[2]);
+
+ ret = fsl_dce_chunk_process(&ctx->deflate_chunk, 0,
+ &def_process_req->input_fd, def_process_req);
+
+ if (ret) {
+ pr_err("Error %d\n", __LINE__);
+ goto fail_deflate_process;
+ }
+
+ wait_for_completion(&def_process_req->cb_done);
+
+ if (fsl_dce_get_status(def_process_req->output_fd.status) !=
+ STREAM_END) {
+ pr_err("Error expected STREAM_END result but got %d\n",
+ fsl_dce_get_status(def_process_req->output_fd.status));
+ ret = -EINVAL;
+ goto fail_deflate_process;
+ }
+
+ pr_info("Output FD\n");
+ print_dce_fd(def_process_req->output_fd);
+
+ ret = detach_data_list_from_sg(&def_process_req->dce_cf[1],
+ &def_process_req->input_data, DMA_BIDIRECTIONAL);
+ if (ret) {
+ pr_err("Error %d\n", __LINE__);
+ goto fail_input_attach_data_to_sg_deflate;
+ }
+
+ ret = detach_data_list_from_sg(&def_process_req->dce_cf[0],
+ &def_process_req->output_data, DMA_BIDIRECTIONAL);
+ if (ret) {
+ pr_err("Error %d\n", __LINE__);
+ goto fail_output_attach_data_to_sg_deflate;
+ }
+
+ ret = dma_unmap_dce_data(&def_process_req->output_data,
+ DMA_BIDIRECTIONAL);
+ if (ret) {
+ pr_err("Error %d\n", __LINE__);
+ goto fail_dma_map_deflate_output_data;
+ }
+
+ ret = dma_unmap_dce_data(&def_process_req->input_data,
+ DMA_BIDIRECTIONAL);
+ if (ret) {
+ pr_err("Error %d\n", __LINE__);
+ goto fail_alloc_dce_data_output;
+ }
+
+ pr_info("Got chunk process, status = %d, sg_table[0].length = %d\n",
+ def_process_req->output_fd.status,
+ def_process_req->dce_cf[0].length);
+
+ print_dce_sg(def_process_req->dce_cf[0]);
+ print_dce_data_list(&def_process_req->output_data);
+
+ /* Save Output */
+ def_process_req->v_output = vmalloc(def_process_req->dce_cf[0].length);
+ if (!def_process_req->v_output) {
+ pr_err("Error %d\n", __LINE__);
+ goto fail_alloc_dce_data_output;
+ }
+ def_process_req->v_output_size = def_process_req->dce_cf[0].length;
+
+ ret = copy_dce_data_to_buffer(&def_process_req->output_data,
+ def_process_req->v_output_size,
+ def_process_req->v_output, def_process_req->v_output_size);
+
+ if (ret) {
+ pr_err("Error %d\n", __LINE__);
+ return ret;
+ }
+
+ /* Free dce data deflate operation, but keep vmalloc output */
+ free_dce_data(&def_process_req->output_data);
+ free_dce_data(&def_process_req->input_data);
+
+ /********** Now inflate the data ************/
+
+ inf_process_req = kzalloc(sizeof(*inf_process_req), GFP_KERNEL);
+ if (!inf_process_req) {
+ pr_err("Error %d\n", __LINE__);
+ return ret;
+ }
+ pr_info("Allocated inf_process_req\n");
+
+ inf_process_req->v_output = vmalloc(input_len);
+ if (!def_process_req) {
+ pr_err("Error %d\n", __LINE__);
+ return ret;
+ }
+
+ init_completion(&inf_process_req->cb_done);
+
+ /* Copy the previous output as input */
+ ret = alloc_dce_data(def_process_req->v_output_size, block_len,
+ &inf_process_req->input_data);
+ if (ret) {
+ pr_err("Error %d\n", __LINE__);
+ return ret;
+ }
+
+ pr_info("Printing input_list info\n");
+ print_dce_data_list(&inf_process_req->input_data);
+
+ ret = alloc_dce_data(input_len, block_len,
+ &inf_process_req->output_data);
+ if (ret) {
+ pr_err("Error %d\n", __LINE__);
+ return ret;
+ }
+
+ pr_info("Printing output_list info\n");
+ print_dce_data_list(&inf_process_req->output_data);
+
+ ret = copy_input_to_dce_data(def_process_req->v_output,
+ def_process_req->v_output_size, &inf_process_req->input_data);
+ if (ret) {
+ pr_err("Error %d\n", __LINE__);
+ return ret;
+ }
+
+ pr_info("Printing inflate input after copy info\n");
+ print_dce_data_list(&inf_process_req->input_data);
+
+ ret = dma_map_dce_data(&inf_process_req->input_data, DMA_BIDIRECTIONAL);
+ if (ret) {
+ pr_err("Error %d\n", __LINE__);
+ return ret;
+ }
+
+ pr_info("Printing input after dma_map info\n");
+ print_dce_data_list(&inf_process_req->input_data);
+
+ ret = dma_map_dce_data(&inf_process_req->output_data,
+ DMA_BIDIRECTIONAL);
+ if (ret) {
+ pr_err("Error %d\n", __LINE__);
+ return ret;
+ }
+
+ pr_info("Printing output after dma_map info\n");
+ print_dce_data_list(&inf_process_req->output_data);
+
+ ret = attach_data_list_to_sg(&inf_process_req->dce_cf[0],
+ &inf_process_req->output_data, DMA_BIDIRECTIONAL);
+ if (ret) {
+ pr_err("Error %d\n", __LINE__);
+ return ret;
+ }
+
+ ret = attach_data_list_to_sg(&inf_process_req->dce_cf[1],
+ &inf_process_req->input_data, DMA_BIDIRECTIONAL);
+ if (ret) {
+ pr_err("Error %d\n", __LINE__);
+ return ret;
+ }
+
+ inf_process_req->dce_cf[2].final = 1;
+
+ inf_process_req->input_fd._format2 = qm_fd_compound;
+ qm_fd_addr_set64(&inf_process_req->input_fd,
+ fsl_dce_map(inf_process_req->dce_cf));
+
+ print_dce_fd(inf_process_req->input_fd);
+ print_dce_sg(inf_process_req->dce_cf[0]);
+ print_dce_sg(inf_process_req->dce_cf[1]);
+ print_dce_sg(inf_process_req->dce_cf[2]);
+
+ fsl_dce_chunk_process(&ctx->inflate_chunk, 0,
+ &inf_process_req->input_fd, inf_process_req);
+
+ wait_for_completion(&inf_process_req->cb_done);
+
+ pr_info("Output FD\n");
+ print_dce_fd(inf_process_req->output_fd);
+
+ ret = dma_unmap_dce_data(&inf_process_req->input_data,
+ DMA_BIDIRECTIONAL);
+ if (ret) {
+ pr_err("Error %d\n", __LINE__);
+ return ret;
+ }
+
+ ret = dma_unmap_dce_data(&inf_process_req->output_data,
+ DMA_BIDIRECTIONAL);
+ if (ret) {
+ pr_err("Error %d\n", __LINE__);
+ return ret;
+ }
+
+ ret = detach_data_list_from_sg(&inf_process_req->dce_cf[0],
+ &inf_process_req->output_data, DMA_BIDIRECTIONAL);
+ if (ret) {
+ pr_err("Error %d\n", __LINE__);
+ return ret;
+ }
+
+ ret = detach_data_list_from_sg(&inf_process_req->dce_cf[1],
+ &inf_process_req->input_data, DMA_BIDIRECTIONAL);
+ if (ret) {
+ pr_err("Error %d\n", __LINE__);
+ return ret;
+ }
+
+ pr_info("Got chunk process, status = %d, sg_table[0].length = %d\n",
+ inf_process_req->output_fd.status,
+ inf_process_req->dce_cf[0].length);
+
+ if (inf_process_req->dce_cf[0].length != input_len) {
+ pr_err("Error %d\n", __LINE__);
+ return ret;
+ }
+
+ print_dce_sg(inf_process_req->dce_cf[0]);
+
+ inf_process_req->v_output = vmalloc(inf_process_req->dce_cf[0].length);
+
+ if (!inf_process_req->v_output) {
+ pr_err("Error %d\n", __LINE__);
+ return ret;
+ }
+ inf_process_req->v_output_size = inf_process_req->dce_cf[0].length;
+
+ ret = copy_dce_data_to_buffer(&inf_process_req->output_data,
+ inf_process_req->v_output_size, inf_process_req->v_output,
+ input_len);
+ if (ret) {
+ pr_err("Error %d\n", __LINE__);
+ return ret;
+ }
+ /* compare output to orinal data */
+ if (memcmp(inf_process_req->v_output, input_data, input_len)) {
+ pr_err("Error %d\n", __LINE__);
+ return ret;
+ }
+ pr_info("Ouput inflate data matched original!\n");
+
+ /* Free dce data deflate operation, but keep vmalloc output */
+ free_dce_data(&inf_process_req->output_data);
+ free_dce_data(&inf_process_req->input_data);
+
+ vfree(inf_process_req->v_output);
+ vfree(def_process_req->v_output);
+ kfree(inf_process_req);
+ kfree(def_process_req);
+
+ ret = destroy_test_ctx(ctx);
+ if (ret)
+ pr_err("Error with test\n");
+ else
+ pr_info("Done test loop\n");
+
+ pr_info("Done test loop\n");
+ return 0;
+
+fail_deflate_process:
+ detach_data_list_from_sg(&def_process_req->dce_cf[1],
+ &def_process_req->input_data,
+ DMA_BIDIRECTIONAL);
+
+fail_input_attach_data_to_sg_deflate:
+ detach_data_list_from_sg(&def_process_req->dce_cf[0],
+ &def_process_req->output_data,
+ DMA_BIDIRECTIONAL);
+
+fail_output_attach_data_to_sg_deflate:
+ dma_unmap_dce_data(&def_process_req->output_data, DMA_BIDIRECTIONAL);
+
+fail_dma_map_deflate_output_data:
+ dma_unmap_dce_data(&def_process_req->input_data, DMA_BIDIRECTIONAL);
+
+fail_alloc_dce_data_output:
+ free_dce_data(&def_process_req->input_data);
+
+fail_alloc_dce_data_input:
+ vfree(def_process_req->v_output);
+
+fail_v_output:
+ kfree(def_process_req);
+
+fail_inflate_params:
+ fsl_dce_chunk_destroy(&ctx->inflate_chunk, 0, NULL);
+
+fail_inflate_nop:
+fail_deflate_nop:
+ destroy_test_ctx(ctx);
+
+fail_init_test_ctx:
+ return ret;
+}
+
+struct test_meta_info_t {
+ char *data;
+ unsigned int len;
+};
+
+static int compression_stateless_truncation_deflate_compoundframes_init(void)
+{
+ int ret, i;
+ struct dce_test_ctx *test_ctx;
+ struct cpumask backup_mask = current->cpus_allowed;
+ struct cpumask new_mask = *qman_affine_cpus();
+ char big_buf[200];
+
+ struct test_meta_info_t test_meta_info_array[] = {
+ {
+ .data = bible_txt_128k,
+ .len = bible_txt_128k_len
+ },
+ {
+ .data = bible_txt_64k,
+ .len = bible_txt_64k_len
+ },
+ {
+ .data = bible_txt_32k,
+ .len = bible_txt_32k_len
+ },
+ {
+ .data = bible_txt_16k,
+ .len = bible_txt_16k_len
+ },
+ {
+ .data = bible_txt_8k,
+ .len = bible_txt_8k_len
+ },
+ {
+ .data = bible_txt_4k,
+ .len = bible_txt_4k_len
+ },
+ {
+ .data = bible_txt_2k,
+ .len = bible_txt_2k_len
+ },
+ {
+ .data = bible_txt_1k,
+ .len = bible_txt_1k_len
+ },
+ {
+ .data = bible_txt_128b,
+ .len = bible_txt_128b_len
+ },
+ };
+
+ cpumask_scnprintf(big_buf, 200, &new_mask);
+
+ pr_info("DCE TEST Start, cpu_mask = %s\n", big_buf);
+
+ /* need to control on which cpu this module runs on */
+ test_ctx = kzalloc(sizeof(*test_ctx), GFP_KERNEL);
+ if (!test_ctx) {
+ pr_err("DCE Test, no memory\n");
+ return -ENOMEM;
+ }
+
+ /* Only run on cpus that have qman and bman portals */
+ cpumask_and(&new_mask, &new_mask, bman_affine_cpus());
+ ret = set_cpus_allowed_ptr(current, &new_mask);
+ if (ret) {
+ pr_err("DCE: test high: can't set cpumask\n");
+ goto fail_test;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(test_meta_info_array); i++) {
+
+ pr_info("DCE init test: input size: %d, block len %d\n",
+ test_meta_info_array[i].len, block_size);
+
+ ret = do_test(test_ctx, DCE_CF_DEFLATE,
+ test_meta_info_array[i].data,
+ test_meta_info_array[i].len, block_size,
+ test_meta_info_array[i].len + 512);
+ if (ret) {
+ pr_err("Error %d\n", __LINE__);
+ goto fail_test;
+ }
+ }
+
+ pr_info("DCE TEST FINISHED SUCCESS\n");
+
+fail_test:
+
+ ret = set_cpus_allowed_ptr(current, &backup_mask);
+ if (ret)
+ pr_err("DCE test high: can't restore cpumask");
+ kfree(test_ctx);
+
+ return ret;
+}
+
+static void compression_stateless_truncation_deflate_compoundframes_exit(void)
+{
+}
+
+module_init(compression_stateless_truncation_deflate_compoundframes_init);
+module_exit(compression_stateless_truncation_deflate_compoundframes_exit);
+
diff --git a/drivers/staging/fsl_dce/tests/common/Makefile b/drivers/staging/fsl_dce/tests/common/Makefile
new file mode 100644
index 0000000..ef94dfa
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/common/Makefile
@@ -0,0 +1,7 @@
+obj-y += test_frame_helpers.o
+
+#obj-$(CONFIG_FSL_DCE_TESTS) += dce_chunk_comp_def_cf_tester.o
+#dce_chunk_comp_def_cf_tester-objs := common/test_frame_helpers.o dce_chunk_comp_def_cf_test.o
+
+#obj-y += performance_simple/
+
diff --git a/drivers/staging/fsl_dce/tests/common/bible.txt.128b.h b/drivers/staging/fsl_dce/tests/common/bible.txt.128b.h
new file mode 100644
index 0000000..473b4ef
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/common/bible.txt.128b.h
@@ -0,0 +1,14 @@
+unsigned char bible_txt_128b[] = {
+ 0x49, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e,
+ 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65,
+ 0x61, 0x74, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61,
+ 0x76, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e, 0x65, 0x73,
+ 0x73, 0x20, 0x77, 0x61, 0x73, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20
+};
+unsigned int bible_txt_128b_len = 128;
diff --git a/drivers/staging/fsl_dce/tests/common/bible.txt.128k.h b/drivers/staging/fsl_dce/tests/common/bible.txt.128k.h
new file mode 100644
index 0000000..97ba5e2
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/common/bible.txt.128k.h
@@ -0,0 +1,10926 @@
+unsigned char bible_txt_128k[] = {
+ 0x49, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e,
+ 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65,
+ 0x61, 0x74, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61,
+ 0x76, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e, 0x65, 0x73,
+ 0x73, 0x20, 0x77, 0x61, 0x73, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x65, 0x65, 0x70, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x70, 0x69, 0x72, 0x69, 0x74, 0x20,
+ 0x6f, 0x66, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x6f, 0x76, 0x65, 0x64,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61,
+ 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x6c, 0x69,
+ 0x67, 0x68, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73,
+ 0x61, 0x77, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x20, 0x66, 0x72,
+ 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e,
+ 0x65, 0x73, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x20, 0x44, 0x61, 0x79, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x72, 0x6b,
+ 0x6e, 0x65, 0x73, 0x73, 0x20, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c,
+ 0x65, 0x64, 0x20, 0x4e, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x20, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f,
+ 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x64, 0x61, 0x79,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x66, 0x69, 0x72, 0x6d,
+ 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x69, 0x64, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x69, 0x74, 0x20, 0x64, 0x69, 0x76,
+ 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65,
+ 0x72, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20,
+ 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x75,
+ 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72,
+ 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x61, 0x62,
+ 0x6f, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d,
+ 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69,
+ 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d,
+ 0x65, 0x6e, 0x74, 0x20, 0x48, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x2e, 0x20,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e,
+ 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20,
+ 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x75,
+ 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61,
+ 0x76, 0x65, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x67, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x70, 0x6c,
+ 0x61, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x72, 0x79, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61,
+ 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x72, 0x79,
+ 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x45, 0x61, 0x72, 0x74, 0x68, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x53, 0x65, 0x61, 0x73, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f,
+ 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x62, 0x72, 0x69,
+ 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x67, 0x72, 0x61,
+ 0x73, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x72, 0x62,
+ 0x20, 0x79, 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65,
+ 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x79,
+ 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x77, 0x68, 0x6f, 0x73, 0x65, 0x20,
+ 0x73, 0x65, 0x65, 0x64, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x69,
+ 0x74, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x67, 0x72, 0x61, 0x73, 0x73,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x72, 0x62, 0x20, 0x79,
+ 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65, 0x65, 0x64,
+ 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b,
+ 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x79, 0x69, 0x65, 0x6c, 0x64, 0x69,
+ 0x6e, 0x67, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x2c, 0x20, 0x77, 0x68,
+ 0x6f, 0x73, 0x65, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x69, 0x6e, 0x20, 0x69, 0x74, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69,
+ 0x6e, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69,
+ 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x6f, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64, 0x20, 0x64, 0x61,
+ 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
+ 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72,
+ 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20,
+ 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x79, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6e, 0x69, 0x67, 0x68, 0x74, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c,
+ 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x62, 0x65, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x65, 0x61, 0x73, 0x6f, 0x6e,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64,
+ 0x61, 0x79, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x76,
+ 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x6c,
+ 0x69, 0x67, 0x68, 0x74, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64,
+ 0x65, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20,
+ 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x3b, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x67, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x67, 0x68,
+ 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x61, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x6c, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x68,
+ 0x65, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x74, 0x61, 0x72, 0x73, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x65, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x20,
+ 0x74, 0x6f, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68,
+ 0x74, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x6f, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x69, 0x67,
+ 0x68, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64,
+ 0x69, 0x76, 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e, 0x65, 0x73, 0x73, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67,
+ 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x6f, 0x75, 0x72, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x74, 0x65, 0x72, 0x73, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66,
+ 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x62, 0x75, 0x6e, 0x64, 0x61, 0x6e,
+ 0x74, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x76, 0x69,
+ 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x6c, 0x69,
+ 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x77, 0x6c,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x66, 0x6c,
+ 0x79, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d,
+ 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65,
+ 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x67, 0x72, 0x65, 0x61,
+ 0x74, 0x20, 0x77, 0x68, 0x61, 0x6c, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69,
+ 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x6f, 0x76, 0x65, 0x74, 0x68, 0x2c,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68,
+ 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x62, 0x75, 0x6e,
+ 0x64, 0x61, 0x6e, 0x74, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e, 0x64,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20,
+ 0x77, 0x69, 0x6e, 0x67, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69,
+ 0x6e, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73,
+ 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x73, 0x61, 0x79,
+ 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x42, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75,
+ 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x66, 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74,
+ 0x65, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x61, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70,
+ 0x6c, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x69, 0x66, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e,
+ 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x61,
+ 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e,
+ 0x64, 0x2c, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20,
+ 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61,
+ 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x61, 0x73, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74,
+ 0x68, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61,
+ 0x74, 0x74, 0x6c, 0x65, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x68, 0x69,
+ 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x72, 0x65, 0x65,
+ 0x70, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74,
+ 0x20, 0x75, 0x73, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x6d, 0x61, 0x6e,
+ 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x75, 0x72, 0x20, 0x69, 0x6d, 0x61, 0x67,
+ 0x65, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x6f, 0x75, 0x72,
+ 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x6f,
+ 0x6e, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x69, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x61, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f,
+ 0x76, 0x65, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f,
+ 0x76, 0x65, 0x72, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x72,
+ 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x65,
+ 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x53, 0x6f, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6d,
+ 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x77,
+ 0x6e, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x3b, 0x20, 0x6d, 0x61, 0x6c,
+ 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65,
+ 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x42, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75,
+ 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x72, 0x65, 0x70, 0x6c, 0x65, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x75, 0x62, 0x64, 0x75, 0x65, 0x20, 0x69, 0x74, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x64, 0x6f, 0x6d,
+ 0x69, 0x6e, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x65, 0x61, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x77,
+ 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x65,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x20,
+ 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d,
+ 0x6f, 0x76, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x68,
+ 0x61, 0x76, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x79, 0x6f,
+ 0x75, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x68, 0x65, 0x72, 0x62,
+ 0x20, 0x62, 0x65, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65, 0x65,
+ 0x64, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x72, 0x65, 0x65, 0x2c, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20,
+ 0x79, 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65, 0x65,
+ 0x64, 0x3b, 0x20, 0x74, 0x6f, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x69, 0x74,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x6d, 0x65, 0x61, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x62, 0x65,
+ 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x63, 0x72, 0x65, 0x65, 0x70, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c,
+ 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x2c, 0x20,
+ 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x67, 0x72, 0x65, 0x65, 0x6e,
+ 0x20, 0x68, 0x65, 0x72, 0x62, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x65,
+ 0x61, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x76, 0x65,
+ 0x72, 0x79, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e, 0x67,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72,
+ 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x69, 0x78, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79, 0x2e,
+ 0x20, 0x0a, 0x54, 0x68, 0x75, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68,
+ 0x65, 0x61, 0x76, 0x65, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x68, 0x6f, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x64, 0x61,
+ 0x79, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61,
+ 0x64, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x72,
+ 0x65, 0x73, 0x74, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x62,
+ 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x76, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x6e, 0x63, 0x74, 0x69, 0x66, 0x69,
+ 0x65, 0x64, 0x20, 0x69, 0x74, 0x3a, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75,
+ 0x73, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x69,
+ 0x74, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x72, 0x65, 0x73,
+ 0x74, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x6c, 0x6c,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x68,
+ 0x69, 0x63, 0x68, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65, 0x61,
+ 0x74, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65,
+ 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x77,
+ 0x65, 0x72, 0x65, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x2c,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x73,
+ 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x66, 0x6f,
+ 0x72, 0x65, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x68, 0x65,
+ 0x72, 0x62, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69,
+ 0x65, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x69,
+ 0x74, 0x20, 0x67, 0x72, 0x65, 0x77, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x61, 0x75,
+ 0x73, 0x65, 0x64, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x61,
+ 0x69, 0x6e, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x74,
+ 0x20, 0x61, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x69,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2e, 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x72,
+ 0x65, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x70, 0x20, 0x61, 0x20,
+ 0x6d, 0x69, 0x73, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x68, 0x6f, 0x6c, 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72,
+ 0x6d, 0x65, 0x64, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x75, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x62, 0x72, 0x65, 0x61, 0x74, 0x68, 0x65, 0x64, 0x20,
+ 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x73,
+ 0x74, 0x72, 0x69, 0x6c, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x72,
+ 0x65, 0x61, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x69, 0x66, 0x65,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x62, 0x65,
+ 0x63, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e,
+ 0x67, 0x20, 0x73, 0x6f, 0x75, 0x6c, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x61, 0x20,
+ 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x20, 0x65, 0x61, 0x73, 0x74, 0x77,
+ 0x61, 0x72, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x45, 0x64, 0x65, 0x6e, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x68,
+ 0x65, 0x20, 0x70, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61,
+ 0x6e, 0x20, 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x64,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x72, 0x6f, 0x77, 0x20, 0x65,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x70, 0x6c, 0x65, 0x61, 0x73, 0x61,
+ 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69,
+ 0x67, 0x68, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x6f, 0x6f,
+ 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x66, 0x6f, 0x6f, 0x64, 0x3b, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x6c, 0x69, 0x66, 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x69, 0x64, 0x73, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72,
+ 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x6c, 0x65,
+ 0x64, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x69, 0x6c, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x61, 0x20, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x77,
+ 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x45,
+ 0x64, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68,
+ 0x65, 0x6e, 0x63, 0x65, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x70, 0x61, 0x72, 0x74, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20,
+ 0x66, 0x6f, 0x75, 0x72, 0x20, 0x68, 0x65, 0x61, 0x64, 0x73, 0x2e, 0x20,
+ 0x0a, 0x54, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x69,
+ 0x73, 0x20, 0x50, 0x69, 0x73, 0x6f, 0x6e, 0x3a, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x69, 0x73, 0x20, 0x69, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63,
+ 0x68, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x73, 0x73, 0x65, 0x74, 0x68,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x6f, 0x6c, 0x65, 0x20, 0x6c,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x61, 0x76, 0x69, 0x6c,
+ 0x61, 0x68, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x67, 0x6f, 0x6c, 0x64, 0x3b,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x6f,
+ 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6c,
+ 0x61, 0x6e, 0x64, 0x20, 0x69, 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x3a,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x62, 0x64,
+ 0x65, 0x6c, 0x6c, 0x69, 0x75, 0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6f, 0x6e, 0x79, 0x78, 0x20, 0x73, 0x74, 0x6f, 0x6e,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20, 0x72, 0x69, 0x76, 0x65, 0x72,
+ 0x20, 0x69, 0x73, 0x20, 0x47, 0x69, 0x68, 0x6f, 0x6e, 0x3a, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x73, 0x20, 0x69,
+ 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61,
+ 0x73, 0x73, 0x65, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68,
+ 0x6f, 0x6c, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x45, 0x74, 0x68, 0x69, 0x6f, 0x70, 0x69, 0x61, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64,
+ 0x20, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x48, 0x69,
+ 0x64, 0x64, 0x65, 0x6b, 0x65, 0x6c, 0x3a, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x69, 0x73, 0x20, 0x69, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x67, 0x6f, 0x65, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x77, 0x61, 0x72,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x41, 0x73, 0x73, 0x79, 0x72, 0x69, 0x61, 0x2e, 0x20, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x75, 0x72, 0x74,
+ 0x68, 0x20, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x45,
+ 0x75, 0x70, 0x68, 0x72, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x75,
+ 0x74, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x20, 0x6f, 0x66,
+ 0x20, 0x45, 0x64, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x72, 0x65,
+ 0x73, 0x73, 0x20, 0x69, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f,
+ 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x69, 0x74, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x73,
+ 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x4f, 0x66, 0x20, 0x65, 0x76,
+ 0x65, 0x72, 0x79, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x65, 0x73, 0x74, 0x20, 0x66,
+ 0x72, 0x65, 0x65, 0x6c, 0x79, 0x20, 0x65, 0x61, 0x74, 0x3a, 0x20, 0x0a,
+ 0x42, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
+ 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b,
+ 0x6e, 0x6f, 0x77, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x69,
+ 0x6c, 0x2c, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c,
+ 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x61, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x69, 0x74, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x65, 0x61, 0x74, 0x65, 0x73, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x73, 0x75, 0x72, 0x65,
+ 0x6c, 0x79, 0x20, 0x64, 0x69, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x74, 0x20, 0x69,
+ 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x20,
+ 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6c,
+ 0x6f, 0x6e, 0x65, 0x3b, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61, 0x6e, 0x20,
+ 0x68, 0x65, 0x6c, 0x70, 0x20, 0x6d, 0x65, 0x65, 0x74, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x65,
+ 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x62, 0x65, 0x61, 0x73,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65,
+ 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x61, 0x69, 0x72, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x74, 0x6f,
+ 0x20, 0x73, 0x65, 0x65, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65,
+ 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68,
+ 0x61, 0x74, 0x73, 0x6f, 0x65, 0x76, 0x65, 0x72, 0x20, 0x41, 0x64, 0x61,
+ 0x6d, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x65, 0x76, 0x65,
+ 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x72,
+ 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x67, 0x61, 0x76,
+ 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f,
+ 0x77, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69,
+ 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x76,
+ 0x65, 0x72, 0x79, 0x20, 0x62, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x3b, 0x20,
+ 0x62, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x41, 0x64, 0x61, 0x6d,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x20,
+ 0x68, 0x65, 0x6c, 0x70, 0x20, 0x6d, 0x65, 0x65, 0x74, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x63, 0x61, 0x75, 0x73, 0x65, 0x64, 0x20, 0x61, 0x20, 0x64, 0x65,
+ 0x65, 0x70, 0x20, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x20, 0x74, 0x6f, 0x20,
+ 0x66, 0x61, 0x6c, 0x6c, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x41, 0x64,
+ 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73,
+ 0x6c, 0x65, 0x70, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x72, 0x69, 0x62, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x20, 0x75, 0x70,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20, 0x69,
+ 0x6e, 0x73, 0x74, 0x65, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65,
+ 0x6f, 0x66, 0x3b, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x72, 0x69, 0x62, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x6d, 0x61, 0x64,
+ 0x65, 0x20, 0x68, 0x65, 0x20, 0x61, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68,
+ 0x74, 0x20, 0x68, 0x65, 0x72, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20,
+ 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20,
+ 0x62, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x62,
+ 0x6f, 0x6e, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6c,
+ 0x65, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x66, 0x6c,
+ 0x65, 0x73, 0x68, 0x3a, 0x20, 0x73, 0x68, 0x65, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x57, 0x6f, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x62, 0x65, 0x63, 0x61,
+ 0x75, 0x73, 0x65, 0x20, 0x73, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x4d, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x72, 0x65,
+ 0x66, 0x6f, 0x72, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x61,
+ 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x63, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c,
+ 0x20, 0x62, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x66, 0x6c, 0x65, 0x73,
+ 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6e,
+ 0x61, 0x6b, 0x65, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61,
+ 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69,
+ 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x73, 0x68, 0x61, 0x6d, 0x65, 0x64,
+ 0x2e, 0x20, 0x0a, 0x4e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x72, 0x70, 0x65, 0x6e, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6d,
+ 0x6f, 0x72, 0x65, 0x20, 0x73, 0x75, 0x62, 0x74, 0x69, 0x6c, 0x20, 0x74,
+ 0x68, 0x61, 0x6e, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x62, 0x65, 0x61, 0x73,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65,
+ 0x6c, 0x64, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x2c, 0x20,
+ 0x59, 0x65, 0x61, 0x2c, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x59, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x61, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x72,
+ 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61,
+ 0x72, 0x64, 0x65, 0x6e, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x72, 0x70, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x57, 0x65, 0x20, 0x6d,
+ 0x61, 0x79, 0x20, 0x65, 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x3a, 0x20,
+ 0x0a, 0x42, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x69,
+ 0x64, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67,
+ 0x61, 0x72, 0x64, 0x65, 0x6e, 0x2c, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68,
+ 0x61, 0x74, 0x68, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x59, 0x65,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65,
+ 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x6e, 0x65,
+ 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x79, 0x65, 0x20, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x20, 0x69, 0x74, 0x2c,
+ 0x20, 0x6c, 0x65, 0x73, 0x74, 0x20, 0x79, 0x65, 0x20, 0x64, 0x69, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x72, 0x70, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d,
+ 0x61, 0x6e, 0x2c, 0x20, 0x59, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x72, 0x65, 0x6c, 0x79, 0x20,
+ 0x64, 0x69, 0x65, 0x3a, 0x20, 0x0a, 0x46, 0x6f, 0x72, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x64, 0x6f, 0x74, 0x68, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x64, 0x61, 0x79, 0x20, 0x79, 0x65, 0x20, 0x65, 0x61, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x6e,
+ 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x65, 0x79, 0x65, 0x73, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6f, 0x70, 0x65, 0x6e,
+ 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x73, 0x20, 0x67,
+ 0x6f, 0x64, 0x73, 0x2c, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x69, 0x6e, 0x67,
+ 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76,
+ 0x69, 0x6c, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20,
+ 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f,
+ 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x66, 0x6f, 0x6f, 0x64, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x70, 0x6c, 0x65, 0x61, 0x73, 0x61, 0x6e,
+ 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x79, 0x65,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x74, 0x72, 0x65,
+ 0x65, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x64, 0x65, 0x73, 0x69,
+ 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20,
+ 0x6f, 0x6e, 0x65, 0x20, 0x77, 0x69, 0x73, 0x65, 0x2c, 0x20, 0x73, 0x68,
+ 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x74, 0x68, 0x65, 0x72,
+ 0x65, 0x6f, 0x66, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x64,
+ 0x20, 0x65, 0x61, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x61,
+ 0x76, 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x65, 0x72, 0x20, 0x68, 0x75, 0x73, 0x62, 0x61, 0x6e, 0x64,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x65, 0x72, 0x3b, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x64, 0x20, 0x65, 0x61,
+ 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x79, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6f,
+ 0x70, 0x65, 0x6e, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x6b, 0x6e, 0x65, 0x77, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x6e, 0x61, 0x6b, 0x65, 0x64, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x73, 0x65, 0x77, 0x65, 0x64, 0x20, 0x66, 0x69,
+ 0x67, 0x20, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x67,
+ 0x65, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d,
+ 0x61, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x73, 0x65, 0x6c, 0x76,
+ 0x65, 0x73, 0x20, 0x61, 0x70, 0x72, 0x6f, 0x6e, 0x73, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x68, 0x65, 0x61,
+ 0x72, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64,
+ 0x65, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f,
+ 0x6f, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61,
+ 0x79, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65,
+ 0x20, 0x68, 0x69, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x73, 0x65, 0x6c,
+ 0x76, 0x65, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x73, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x57, 0x68, 0x65, 0x72, 0x65, 0x20,
+ 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x3f, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20,
+ 0x49, 0x20, 0x68, 0x65, 0x61, 0x72, 0x64, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x76, 0x6f, 0x69, 0x63, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x49, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x66, 0x72, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x49,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e, 0x61, 0x6b, 0x65, 0x64, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x68, 0x69, 0x64, 0x20, 0x6d, 0x79,
+ 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x57, 0x68, 0x6f, 0x20,
+ 0x74, 0x6f, 0x6c, 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x77, 0x61, 0x73, 0x74,
+ 0x20, 0x6e, 0x61, 0x6b, 0x65, 0x64, 0x3f, 0x20, 0x48, 0x61, 0x73, 0x74,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x65, 0x61, 0x74, 0x65, 0x6e, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x2c,
+ 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x20, 0x49, 0x20, 0x63,
+ 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x6f,
+ 0x74, 0x20, 0x65, 0x61, 0x74, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x54, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20,
+ 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x67, 0x61,
+ 0x76, 0x65, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x68, 0x65, 0x20,
+ 0x67, 0x61, 0x76, 0x65, 0x20, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x49, 0x20, 0x64, 0x69, 0x64, 0x20, 0x65, 0x61, 0x74, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61,
+ 0x6e, 0x2c, 0x20, 0x57, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74,
+ 0x68, 0x69, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x3f,
+ 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d,
+ 0x61, 0x6e, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x65,
+ 0x20, 0x73, 0x65, 0x72, 0x70, 0x65, 0x6e, 0x74, 0x20, 0x62, 0x65, 0x67,
+ 0x75, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x49, 0x20, 0x64, 0x69, 0x64, 0x20, 0x65, 0x61, 0x74, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72,
+ 0x70, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x42, 0x65, 0x63, 0x61, 0x75, 0x73,
+ 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20,
+ 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2c, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x61, 0x72, 0x74, 0x20, 0x63, 0x75, 0x72, 0x73,
+ 0x65, 0x64, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20, 0x61, 0x6c, 0x6c,
+ 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x62, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x3b, 0x20, 0x75, 0x70, 0x6f,
+ 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x65, 0x6c, 0x6c, 0x79, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x67,
+ 0x6f, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x75, 0x73, 0x74, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x65,
+ 0x61, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6c,
+ 0x69, 0x66, 0x65, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x70, 0x75, 0x74, 0x20, 0x65, 0x6e, 0x6d,
+ 0x69, 0x74, 0x79, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x73, 0x65, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x72,
+ 0x20, 0x73, 0x65, 0x65, 0x64, 0x3b, 0x20, 0x69, 0x74, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x72, 0x75, 0x69, 0x73, 0x65, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x68, 0x65, 0x61, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20,
+ 0x62, 0x72, 0x75, 0x69, 0x73, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68,
+ 0x65, 0x65, 0x6c, 0x2e, 0x20, 0x0a, 0x55, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20, 0x68, 0x65, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x6c, 0x79, 0x20, 0x6d, 0x75, 0x6c,
+ 0x74, 0x69, 0x70, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x6f,
+ 0x72, 0x72, 0x6f, 0x77, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3b,
+ 0x20, 0x69, 0x6e, 0x20, 0x73, 0x6f, 0x72, 0x72, 0x6f, 0x77, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x62, 0x72,
+ 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x63, 0x68,
+ 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x79, 0x20, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x68, 0x75, 0x73, 0x62, 0x61, 0x6e, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c,
+ 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x68,
+ 0x65, 0x61, 0x72, 0x6b, 0x65, 0x6e, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x65, 0x61,
+ 0x74, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
+ 0x72, 0x65, 0x65, 0x2c, 0x20, 0x6f, 0x66, 0x20, 0x77, 0x68, 0x69, 0x63,
+ 0x68, 0x20, 0x49, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69,
+ 0x6e, 0x67, 0x2c, 0x20, 0x54, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x61, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x69, 0x74, 0x3a, 0x20, 0x63, 0x75, 0x72, 0x73, 0x65, 0x64,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75,
+ 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73,
+ 0x61, 0x6b, 0x65, 0x3b, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x6f, 0x72, 0x72,
+ 0x6f, 0x77, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x65, 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6c, 0x69, 0x66, 0x65,
+ 0x3b, 0x20, 0x0a, 0x54, 0x68, 0x6f, 0x72, 0x6e, 0x73, 0x20, 0x61, 0x6c,
+ 0x73, 0x6f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x74,
+ 0x6c, 0x65, 0x73, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x69, 0x74,
+ 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68,
+ 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74,
+ 0x20, 0x65, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x72,
+ 0x62, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65,
+ 0x6c, 0x64, 0x3b, 0x20, 0x0a, 0x49, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x77, 0x65, 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x65, 0x61, 0x74, 0x20, 0x62, 0x72, 0x65,
+ 0x61, 0x64, 0x2c, 0x20, 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x3a, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x64, 0x75, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x61,
+ 0x72, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x64, 0x75, 0x73, 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x63,
+ 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69,
+ 0x66, 0x65, 0x27, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x45, 0x76,
+ 0x65, 0x3b, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c,
+ 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x20, 0x0a, 0x55, 0x6e,
+ 0x74, 0x6f, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x61, 0x6c, 0x73, 0x6f,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x77, 0x69, 0x66, 0x65, 0x20, 0x64, 0x69, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61,
+ 0x6b, 0x65, 0x20, 0x63, 0x6f, 0x61, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x73, 0x6b, 0x69, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63,
+ 0x6c, 0x6f, 0x74, 0x68, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x62, 0x65, 0x63, 0x6f,
+ 0x6d, 0x65, 0x20, 0x61, 0x73, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x75, 0x73, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x6b, 0x6e, 0x6f, 0x77,
+ 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76,
+ 0x69, 0x6c, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x6f, 0x77, 0x2c,
+ 0x20, 0x6c, 0x65, 0x73, 0x74, 0x20, 0x68, 0x65, 0x20, 0x70, 0x75, 0x74,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68,
+ 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x61, 0x6b,
+ 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x69,
+ 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x61, 0x74, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x65, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x0a, 0x54, 0x68, 0x65,
+ 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x65, 0x6e, 0x74,
+ 0x20, 0x68, 0x69, 0x6d, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64,
+ 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x64, 0x65, 0x6e, 0x2c, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x77, 0x68, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x53, 0x6f,
+ 0x20, 0x68, 0x65, 0x20, 0x64, 0x72, 0x6f, 0x76, 0x65, 0x20, 0x6f, 0x75,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x3b, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x64,
+ 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x73, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64,
+ 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x64, 0x65, 0x6e, 0x20, 0x43,
+ 0x68, 0x65, 0x72, 0x75, 0x62, 0x69, 0x6d, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x61, 0x20, 0x66, 0x6c, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x20,
+ 0x73, 0x77, 0x6f, 0x72, 0x64, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x77, 0x61, 0x79, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x6b, 0x65, 0x65,
+ 0x70, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x79, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x6c, 0x69, 0x66, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x41, 0x64, 0x61, 0x6d, 0x20, 0x6b, 0x6e, 0x65, 0x77, 0x20, 0x45, 0x76,
+ 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x63,
+ 0x65, 0x69, 0x76, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x61, 0x72, 0x65, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x67, 0x6f, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x61, 0x20,
+ 0x6d, 0x61, 0x6e, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x73, 0x68, 0x65, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x20, 0x62, 0x61,
+ 0x72, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68,
+ 0x65, 0x72, 0x20, 0x41, 0x62, 0x65, 0x6c, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x62, 0x65, 0x6c, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x20,
+ 0x6b, 0x65, 0x65, 0x70, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x68,
+ 0x65, 0x65, 0x70, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x43, 0x61, 0x69,
+ 0x6e, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x20, 0x74, 0x69, 0x6c, 0x6c,
+ 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69,
+ 0x6e, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d,
+ 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20, 0x62, 0x72, 0x6f,
+ 0x75, 0x67, 0x68, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x6f,
+ 0x66, 0x66, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x68, 0x65,
+ 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72,
+ 0x73, 0x74, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63, 0x74, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x41, 0x62, 0x65, 0x6c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72,
+ 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72,
+ 0x69, 0x6e, 0x67, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63, 0x74, 0x2e, 0x20,
+ 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x77, 0x72, 0x6f, 0x74, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x75,
+ 0x6e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x66, 0x65, 0x6c,
+ 0x6c, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x57, 0x68, 0x79,
+ 0x20, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x77, 0x72,
+ 0x6f, 0x74, 0x68, 0x3f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x79,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x79, 0x20, 0x63, 0x6f, 0x75, 0x6e,
+ 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x66, 0x61, 0x6c, 0x6c,
+ 0x65, 0x6e, 0x3f, 0x20, 0x0a, 0x49, 0x66, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x64, 0x6f, 0x65, 0x73, 0x74, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x2c,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70,
+ 0x74, 0x65, 0x64, 0x3f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x66, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x74, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x2c, 0x20, 0x73, 0x69, 0x6e,
+ 0x20, 0x6c, 0x69, 0x65, 0x74, 0x68, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x6f, 0x6f, 0x72, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x64,
+ 0x65, 0x73, 0x69, 0x72, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x72, 0x75,
+ 0x6c, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x68, 0x69, 0x6d, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20, 0x74,
+ 0x61, 0x6c, 0x6b, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x41,
+ 0x62, 0x65, 0x6c, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20,
+ 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73,
+ 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x77, 0x65, 0x72, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x43, 0x61, 0x69, 0x6e, 0x20, 0x72, 0x6f, 0x73, 0x65, 0x20, 0x75, 0x70,
+ 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x73, 0x74, 0x20, 0x41, 0x62, 0x65,
+ 0x6c, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65,
+ 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x6c, 0x65, 0x77, 0x20,
+ 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x57,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x41, 0x62, 0x65, 0x6c,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x3f, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x49, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20, 0x6e, 0x6f,
+ 0x74, 0x3a, 0x20, 0x41, 0x6d, 0x20, 0x49, 0x20, 0x6d, 0x79, 0x20, 0x62,
+ 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x6b, 0x65, 0x65,
+ 0x70, 0x65, 0x72, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x57, 0x68, 0x61, 0x74, 0x20,
+ 0x68, 0x61, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x64, 0x6f,
+ 0x6e, 0x65, 0x3f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x63,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x72, 0x6f,
+ 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x62, 0x6c, 0x6f, 0x6f, 0x64,
+ 0x20, 0x63, 0x72, 0x69, 0x65, 0x74, 0x68, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x6d, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x63, 0x75, 0x72, 0x73, 0x65, 0x64, 0x20, 0x66, 0x72,
+ 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x68, 0x61, 0x74, 0x68,
+ 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x65, 0x64, 0x20, 0x68, 0x65, 0x72, 0x20,
+ 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, 0x63,
+ 0x65, 0x69, 0x76, 0x65, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x72, 0x6f,
+ 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x62, 0x6c, 0x6f, 0x6f, 0x64,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x79, 0x20, 0x68, 0x61,
+ 0x6e, 0x64, 0x3b, 0x20, 0x0a, 0x57, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x74, 0x69, 0x6c, 0x6c, 0x65, 0x73, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2c, 0x20, 0x69,
+ 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x68, 0x65, 0x6e, 0x63, 0x65, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x79,
+ 0x69, 0x65, 0x6c, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x20, 0x68, 0x65, 0x72, 0x20, 0x73, 0x74, 0x72, 0x65, 0x6e,
+ 0x67, 0x74, 0x68, 0x3b, 0x20, 0x61, 0x20, 0x66, 0x75, 0x67, 0x69, 0x74,
+ 0x69, 0x76, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x76, 0x61,
+ 0x67, 0x61, 0x62, 0x6f, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x62, 0x65, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x2c, 0x20, 0x4d, 0x79, 0x20, 0x70, 0x75, 0x6e, 0x69,
+ 0x73, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x73, 0x20, 0x67, 0x72,
+ 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x49,
+ 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x61, 0x72, 0x2e, 0x20, 0x0a,
+ 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x64, 0x72, 0x69, 0x76, 0x65, 0x6e,
+ 0x20, 0x6d, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x64, 0x61, 0x79, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x79, 0x20, 0x66, 0x61,
+ 0x63, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x49, 0x20, 0x62,
+ 0x65, 0x20, 0x68, 0x69, 0x64, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20,
+ 0x66, 0x75, 0x67, 0x69, 0x74, 0x69, 0x76, 0x65, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x61, 0x20, 0x76, 0x61, 0x67, 0x61, 0x62, 0x6f, 0x6e, 0x64, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70,
+ 0x61, 0x73, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x65, 0x76,
+ 0x65, 0x72, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x66, 0x69, 0x6e, 0x64, 0x65, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x73, 0x6c, 0x61, 0x79, 0x20, 0x6d,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x54, 0x68, 0x65, 0x72,
+ 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x77, 0x68, 0x6f, 0x73, 0x6f, 0x65,
+ 0x76, 0x65, 0x72, 0x20, 0x73, 0x6c, 0x61, 0x79, 0x65, 0x74, 0x68, 0x20,
+ 0x43, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x76, 0x65, 0x6e, 0x67, 0x65, 0x61,
+ 0x6e, 0x63, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65,
+ 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x6f, 0x6e, 0x20, 0x68, 0x69,
+ 0x6d, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x66, 0x6f, 0x6c, 0x64, 0x2e,
+ 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x73, 0x65, 0x74, 0x20, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x2c, 0x20,
+ 0x6c, 0x65, 0x73, 0x74, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x66, 0x69, 0x6e,
+ 0x64, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x73, 0x68, 0x6f,
+ 0x75, 0x6c, 0x64, 0x20, 0x6b, 0x69, 0x6c, 0x6c, 0x20, 0x68, 0x69, 0x6d,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20,
+ 0x77, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e,
+ 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x77, 0x65, 0x6c,
+ 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x4e, 0x6f, 0x64, 0x2c, 0x20, 0x6f, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x45, 0x64, 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x43, 0x61, 0x69, 0x6e, 0x20, 0x6b, 0x6e, 0x65, 0x77, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x69, 0x76, 0x65,
+ 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20,
+ 0x45, 0x6e, 0x6f, 0x63, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x64, 0x20, 0x61, 0x20,
+ 0x63, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61,
+ 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x69, 0x74,
+ 0x79, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x45, 0x6e, 0x6f, 0x63, 0x68, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x45,
+ 0x6e, 0x6f, 0x63, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x62, 0x6f, 0x72,
+ 0x6e, 0x20, 0x49, 0x72, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x49, 0x72, 0x61, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4d,
+ 0x65, 0x68, 0x75, 0x6a, 0x61, 0x65, 0x6c, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x4d, 0x65, 0x68, 0x75, 0x6a, 0x61, 0x65, 0x6c, 0x20, 0x62, 0x65,
+ 0x67, 0x61, 0x74, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x75, 0x73, 0x61, 0x65,
+ 0x6c, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x75,
+ 0x73, 0x61, 0x65, 0x6c, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4c,
+ 0x61, 0x6d, 0x65, 0x63, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x74, 0x77, 0x6f,
+ 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6f, 0x6e, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x41, 0x64, 0x61, 0x68,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x5a, 0x69, 0x6c, 0x6c, 0x61, 0x68, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x64, 0x61, 0x68, 0x20, 0x62, 0x61,
+ 0x72, 0x65, 0x20, 0x4a, 0x61, 0x62, 0x61, 0x6c, 0x3a, 0x20, 0x68, 0x65,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20,
+ 0x61, 0x73, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f,
+ 0x66, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x4a, 0x75, 0x62, 0x61, 0x6c, 0x3a, 0x20, 0x68, 0x65,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x73,
+ 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x72, 0x70, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x5a, 0x69, 0x6c, 0x6c, 0x61, 0x68, 0x2c, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x62, 0x61, 0x72, 0x65,
+ 0x20, 0x54, 0x75, 0x62, 0x61, 0x6c, 0x63, 0x61, 0x69, 0x6e, 0x2c, 0x20,
+ 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x65,
+ 0x72, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x61,
+ 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20,
+ 0x62, 0x72, 0x61, 0x73, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x72,
+ 0x6f, 0x6e, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x69, 0x73, 0x74, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x54, 0x75,
+ 0x62, 0x61, 0x6c, 0x63, 0x61, 0x69, 0x6e, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x4e, 0x61, 0x61, 0x6d, 0x61, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69,
+ 0x76, 0x65, 0x73, 0x2c, 0x20, 0x41, 0x64, 0x61, 0x68, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x5a, 0x69, 0x6c, 0x6c, 0x61, 0x68, 0x2c, 0x20, 0x48, 0x65,
+ 0x61, 0x72, 0x20, 0x6d, 0x79, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x3b,
+ 0x20, 0x79, 0x65, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68, 0x2c, 0x20, 0x68, 0x65, 0x61,
+ 0x72, 0x6b, 0x65, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x79,
+ 0x20, 0x73, 0x70, 0x65, 0x65, 0x63, 0x68, 0x3a, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x73, 0x6c, 0x61, 0x69,
+ 0x6e, 0x20, 0x61, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6d,
+ 0x79, 0x20, 0x77, 0x6f, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x79, 0x6f, 0x75, 0x6e, 0x67, 0x20,
+ 0x6d, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x79, 0x20, 0x68, 0x75,
+ 0x72, 0x74, 0x2e, 0x20, 0x0a, 0x49, 0x66, 0x20, 0x43, 0x61, 0x69, 0x6e,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x76,
+ 0x65, 0x6e, 0x67, 0x65, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x66,
+ 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x74, 0x72, 0x75, 0x6c, 0x79, 0x20, 0x4c,
+ 0x61, 0x6d, 0x65, 0x63, 0x68, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x74,
+ 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x66,
+ 0x6f, 0x6c, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x64,
+ 0x61, 0x6d, 0x20, 0x6b, 0x6e, 0x65, 0x77, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x77, 0x69, 0x66, 0x65, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x62, 0x61, 0x72, 0x65,
+ 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e,
+ 0x61, 0x6d, 0x65, 0x20, 0x53, 0x65, 0x74, 0x68, 0x3a, 0x20, 0x46, 0x6f,
+ 0x72, 0x20, 0x47, 0x6f, 0x64, 0x2c, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x73, 0x68, 0x65, 0x2c, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x61, 0x70,
+ 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x20, 0x61,
+ 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20,
+ 0x69, 0x6e, 0x73, 0x74, 0x65, 0x61, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x41,
+ 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x43, 0x61,
+ 0x69, 0x6e, 0x20, 0x73, 0x6c, 0x65, 0x77, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x6f, 0x20, 0x53, 0x65, 0x74, 0x68, 0x2c, 0x20, 0x74,
+ 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x62, 0x6f, 0x72,
+ 0x6e, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x45, 0x6e, 0x6f, 0x73,
+ 0x3a, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x62, 0x65, 0x67, 0x61, 0x6e,
+ 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x61, 0x6c, 0x6c,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x6f, 0x6b, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x64, 0x61, 0x6d,
+ 0x2e, 0x20, 0x49, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72,
+ 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x6e, 0x65,
+ 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61,
+ 0x64, 0x65, 0x20, 0x68, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x3b, 0x20, 0x0a,
+ 0x4d, 0x61, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x65, 0x6d,
+ 0x61, 0x6c, 0x65, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6e, 0x61, 0x6d, 0x65,
+ 0x20, 0x41, 0x64, 0x61, 0x6d, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x63, 0x72, 0x65,
+ 0x61, 0x74, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41,
+ 0x64, 0x61, 0x6d, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x6e,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74,
+ 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x6f, 0x77, 0x6e, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x6e, 0x65,
+ 0x73, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x53, 0x65, 0x74,
+ 0x68, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x64, 0x61, 0x6d,
+ 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x62, 0x65, 0x67, 0x6f, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x53,
+ 0x65, 0x74, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x65, 0x69, 0x67,
+ 0x68, 0x74, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x79,
+ 0x65, 0x61, 0x72, 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72,
+ 0x73, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x20, 0x68,
+ 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x69, 0x72, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x65, 0x64,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x65, 0x74, 0x68, 0x20,
+ 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x75, 0x6e,
+ 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x76,
+ 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x45, 0x6e, 0x6f, 0x73, 0x3a,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x65, 0x74, 0x68, 0x20, 0x6c,
+ 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68,
+ 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x45, 0x6e, 0x6f, 0x73,
+ 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72,
+ 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73,
+ 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x53,
+ 0x65, 0x74, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6e, 0x69, 0x6e,
+ 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x77, 0x65, 0x6c, 0x76, 0x65, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64,
+ 0x69, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x6e,
+ 0x6f, 0x73, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x6e, 0x69, 0x6e,
+ 0x65, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x43, 0x61, 0x69,
+ 0x6e, 0x61, 0x6e, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x6e,
+ 0x6f, 0x73, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74,
+ 0x65, 0x72, 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20,
+ 0x43, 0x61, 0x69, 0x6e, 0x61, 0x6e, 0x20, 0x65, 0x69, 0x67, 0x68, 0x74,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x66, 0x69, 0x66, 0x74, 0x65, 0x65, 0x6e, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61,
+ 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64,
+ 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x3a, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x6e, 0x6f, 0x73, 0x20,
+ 0x77, 0x65, 0x72, 0x65, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x75,
+ 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69,
+ 0x76, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x65, 0x64, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x61, 0x6e, 0x20, 0x6c,
+ 0x69, 0x76, 0x65, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x79,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x67, 0x61, 0x74, 0x20, 0x4d, 0x61, 0x68, 0x61, 0x6c, 0x61, 0x6c,
+ 0x65, 0x65, 0x6c, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61,
+ 0x69, 0x6e, 0x61, 0x6e, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61,
+ 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61,
+ 0x74, 0x20, 0x4d, 0x61, 0x68, 0x61, 0x6c, 0x61, 0x6c, 0x65, 0x65, 0x6c,
+ 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72,
+ 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x79,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73,
+ 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x43,
+ 0x61, 0x69, 0x6e, 0x61, 0x6e, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6e,
+ 0x69, 0x6e, 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x65, 0x6e, 0x20, 0x79, 0x65, 0x61, 0x72,
+ 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69,
+ 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4d, 0x61, 0x68,
+ 0x61, 0x6c, 0x61, 0x6c, 0x65, 0x65, 0x6c, 0x20, 0x6c, 0x69, 0x76, 0x65,
+ 0x64, 0x20, 0x73, 0x69, 0x78, 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x66, 0x69, 0x76, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4a, 0x61,
+ 0x72, 0x65, 0x64, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4d, 0x61,
+ 0x68, 0x61, 0x6c, 0x61, 0x6c, 0x65, 0x65, 0x6c, 0x20, 0x6c, 0x69, 0x76,
+ 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x65, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4a, 0x61, 0x72, 0x65, 0x64, 0x20,
+ 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65,
+ 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73,
+ 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4d,
+ 0x61, 0x68, 0x61, 0x6c, 0x61, 0x6c, 0x65, 0x65, 0x6c, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x75, 0x6e,
+ 0x64, 0x72, 0x65, 0x64, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x74, 0x79, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64,
+ 0x69, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61,
+ 0x72, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x6e,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x73, 0x69, 0x78,
+ 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x79,
+ 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x45, 0x6e, 0x6f, 0x63, 0x68,
+ 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x72, 0x65, 0x64,
+ 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x45, 0x6e,
+ 0x6f, 0x63, 0x68, 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x75,
+ 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73,
+ 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67,
+ 0x68, 0x74, 0x65, 0x72, 0x73, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x4a, 0x61, 0x72, 0x65, 0x64, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64,
+ 0x72, 0x65, 0x64, 0x20, 0x73, 0x69, 0x78, 0x74, 0x79, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x65, 0x64,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x6e, 0x6f, 0x63, 0x68,
+ 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x73, 0x69, 0x78, 0x74, 0x79,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20, 0x79, 0x65,
+ 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67,
+ 0x61, 0x74, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x75, 0x73, 0x65, 0x6c, 0x61,
+ 0x68, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x6e, 0x6f, 0x63,
+ 0x68, 0x20, 0x77, 0x61, 0x6c, 0x6b, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4d, 0x65, 0x74,
+ 0x68, 0x75, 0x73, 0x65, 0x6c, 0x61, 0x68, 0x20, 0x74, 0x68, 0x72, 0x65,
+ 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x79, 0x65,
+ 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67,
+ 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x3a, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x6e, 0x6f, 0x63,
+ 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x73, 0x69, 0x78,
+ 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20,
+ 0x79, 0x65, 0x61, 0x72, 0x73, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x45, 0x6e, 0x6f, 0x63, 0x68, 0x20, 0x77, 0x61, 0x6c, 0x6b, 0x65, 0x64,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x6f, 0x64, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e, 0x6f,
+ 0x74, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x74,
+ 0x6f, 0x6f, 0x6b, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x75, 0x73, 0x65, 0x6c, 0x61, 0x68,
+ 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x75,
+ 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x79,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x79,
+ 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65,
+ 0x67, 0x61, 0x74, 0x20, 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x75, 0x73, 0x65,
+ 0x6c, 0x61, 0x68, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66,
+ 0x74, 0x65, 0x72, 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74,
+ 0x20, 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68, 0x20, 0x73, 0x65, 0x76, 0x65,
+ 0x6e, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x65, 0x69,
+ 0x67, 0x68, 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x77, 0x6f,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73,
+ 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4d,
+ 0x65, 0x74, 0x68, 0x75, 0x73, 0x65, 0x6c, 0x61, 0x68, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64,
+ 0x72, 0x65, 0x64, 0x20, 0x73, 0x69, 0x78, 0x74, 0x79, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x65,
+ 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4c, 0x61, 0x6d, 0x65,
+ 0x63, 0x68, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20,
+ 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x79,
+ 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65,
+ 0x67, 0x61, 0x74, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x3a, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x4e,
+ 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c,
+ 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x66, 0x6f, 0x72, 0x74,
+ 0x20, 0x75, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x72, 0x6e, 0x69,
+ 0x6e, 0x67, 0x20, 0x6f, 0x75, 0x72, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x69, 0x6c, 0x20, 0x6f, 0x66, 0x20,
+ 0x6f, 0x75, 0x72, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x2c, 0x20, 0x62,
+ 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20,
+ 0x68, 0x61, 0x74, 0x68, 0x20, 0x63, 0x75, 0x72, 0x73, 0x65, 0x64, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68,
+ 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4e, 0x6f,
+ 0x61, 0x68, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64,
+ 0x72, 0x65, 0x64, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x74, 0x79, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74,
+ 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61,
+ 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x3a, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61,
+ 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20,
+ 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65,
+ 0x6e, 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65,
+ 0x6e, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x66, 0x69, 0x76, 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x62, 0x65, 0x67,
+ 0x61, 0x74, 0x20, 0x53, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x48, 0x61, 0x6d,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x70, 0x68, 0x65, 0x74,
+ 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63,
+ 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c,
+ 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x62, 0x65,
+ 0x67, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69,
+ 0x70, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61,
+ 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x0a, 0x54, 0x68, 0x61, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x6d, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x79, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x66, 0x61, 0x69, 0x72, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x74, 0x6f,
+ 0x6f, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x77, 0x69, 0x76, 0x65,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x68, 0x6f, 0x73,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4d,
+ 0x79, 0x20, 0x73, 0x70, 0x69, 0x72, 0x69, 0x74, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x6c, 0x77, 0x61, 0x79,
+ 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x76, 0x65, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20,
+ 0x69, 0x73, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x3a, 0x20, 0x79, 0x65,
+ 0x74, 0x20, 0x68, 0x69, 0x73, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x68,
+ 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x77, 0x65, 0x6e, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2e,
+ 0x20, 0x0a, 0x54, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x67, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x61, 0x66, 0x74,
+ 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x2c, 0x20, 0x77, 0x68, 0x65,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f,
+ 0x66, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x69,
+ 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x6d, 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x79, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64,
+ 0x72, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x62, 0x65,
+ 0x63, 0x61, 0x6d, 0x65, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x79, 0x20,
+ 0x6d, 0x65, 0x6e, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x6d,
+ 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x6e, 0x6f, 0x77, 0x6e,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73,
+ 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x6f,
+ 0x66, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x72,
+ 0x65, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x69, 0x6d, 0x61,
+ 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x65, 0x61, 0x72,
+ 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x65,
+ 0x76, 0x69, 0x6c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61,
+ 0x6c, 0x6c, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74,
+ 0x20, 0x72, 0x65, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20,
+ 0x6d, 0x61, 0x6e, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74,
+ 0x20, 0x67, 0x72, 0x69, 0x65, 0x76, 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d,
+ 0x20, 0x61, 0x74, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x65, 0x61, 0x72,
+ 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49,
+ 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f,
+ 0x79, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x49,
+ 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
+ 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x3b, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6d,
+ 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x61, 0x73,
+ 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x72, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e,
+ 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x6f, 0x77, 0x6c, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x61, 0x69, 0x72, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x74, 0x20,
+ 0x72, 0x65, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x74, 0x68, 0x20, 0x6d, 0x65,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65,
+ 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2e, 0x20,
+ 0x0a, 0x42, 0x75, 0x74, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x66, 0x6f,
+ 0x75, 0x6e, 0x64, 0x20, 0x67, 0x72, 0x61, 0x63, 0x65, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x79, 0x65, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2e, 0x20, 0x0a,
+ 0x54, 0x68, 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x3a, 0x20, 0x4e,
+ 0x6f, 0x61, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x20, 0x6a, 0x75,
+ 0x73, 0x74, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70,
+ 0x65, 0x72, 0x66, 0x65, 0x63, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20,
+ 0x77, 0x61, 0x6c, 0x6b, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x47, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4e, 0x6f,
+ 0x61, 0x68, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x74, 0x68, 0x72,
+ 0x65, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x53, 0x68, 0x65,
+ 0x6d, 0x2c, 0x20, 0x48, 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x4a, 0x61, 0x70, 0x68, 0x65, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x54, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x61, 0x6c, 0x73, 0x6f,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x63, 0x6f, 0x72, 0x72, 0x75, 0x70, 0x74,
+ 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x47, 0x6f, 0x64, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x76, 0x69, 0x6f, 0x6c, 0x65,
+ 0x6e, 0x63, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x65, 0x64, 0x20, 0x75, 0x70, 0x6f,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64,
+ 0x2c, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x63, 0x6f, 0x72,
+ 0x72, 0x75, 0x70, 0x74, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20, 0x68, 0x61, 0x64, 0x20,
+ 0x63, 0x6f, 0x72, 0x72, 0x75, 0x70, 0x74, 0x65, 0x64, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x61, 0x79, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x54,
+ 0x68, 0x65, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20, 0x69, 0x73, 0x20, 0x63,
+ 0x6f, 0x6d, 0x65, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x6d,
+ 0x65, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x20, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x6c,
+ 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x76, 0x69, 0x6f, 0x6c,
+ 0x65, 0x6e, 0x63, 0x65, 0x20, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20,
+ 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69,
+ 0x6c, 0x6c, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x4d, 0x61, 0x6b,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x72,
+ 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x67, 0x6f, 0x70, 0x68, 0x65, 0x72, 0x20,
+ 0x77, 0x6f, 0x6f, 0x64, 0x3b, 0x20, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x6d,
+ 0x61, 0x6b, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61,
+ 0x72, 0x6b, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c,
+ 0x74, 0x20, 0x70, 0x69, 0x74, 0x63, 0x68, 0x20, 0x69, 0x74, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x70,
+ 0x69, 0x74, 0x63, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x61, 0x73, 0x68, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20,
+ 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x69, 0x74, 0x20, 0x6f, 0x66, 0x3a, 0x20,
+ 0x54, 0x68, 0x65, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x63, 0x75, 0x62,
+ 0x69, 0x74, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x72, 0x65,
+ 0x61, 0x64, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x20, 0x66,
+ 0x69, 0x66, 0x74, 0x79, 0x20, 0x63, 0x75, 0x62, 0x69, 0x74, 0x73, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x20, 0x74, 0x68,
+ 0x69, 0x72, 0x74, 0x79, 0x20, 0x63, 0x75, 0x62, 0x69, 0x74, 0x73, 0x2e,
+ 0x20, 0x0a, 0x41, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x6d, 0x61,
+ 0x6b, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72,
+ 0x6b, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20,
+ 0x63, 0x75, 0x62, 0x69, 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x20,
+ 0x69, 0x74, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x6f, 0x6f, 0x72, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x65, 0x74,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x64, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x3b, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x2c, 0x20, 0x73, 0x65,
+ 0x63, 0x6f, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x69, 0x72, 0x64, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x6d,
+ 0x61, 0x6b, 0x65, 0x20, 0x69, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x49, 0x2c,
+ 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x49, 0x2c, 0x20, 0x64, 0x6f, 0x20,
+ 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x66, 0x6c, 0x6f, 0x6f,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72,
+ 0x6f, 0x79, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68,
+ 0x2c, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x20, 0x69, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x72, 0x65, 0x61, 0x74, 0x68, 0x20,
+ 0x6f, 0x66, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x68, 0x65, 0x61, 0x76,
+ 0x65, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x64,
+ 0x69, 0x65, 0x2e, 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x49, 0x20, 0x65, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x20,
+ 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x27, 0x20, 0x77,
+ 0x69, 0x76, 0x65, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67,
+ 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x2c, 0x20, 0x74, 0x77, 0x6f,
+ 0x20, 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x73, 0x6f,
+ 0x72, 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x74, 0x6f,
+ 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x61,
+ 0x6c, 0x69, 0x76, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x3b, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6d, 0x61, 0x6c, 0x65, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65, 0x2e, 0x20, 0x0a,
+ 0x4f, 0x66, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x73, 0x20, 0x61, 0x66, 0x74,
+ 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e,
+ 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x61,
+ 0x74, 0x74, 0x6c, 0x65, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x6f,
+ 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x72, 0x65, 0x65,
+ 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69,
+ 0x6e, 0x64, 0x2c, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x6f, 0x66, 0x20, 0x65,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x73, 0x6f, 0x72, 0x74, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x6b,
+ 0x65, 0x65, 0x70, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x61, 0x6c, 0x69,
+ 0x76, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x61, 0x6b,
+ 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x66, 0x6f, 0x6f, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73,
+ 0x20, 0x65, 0x61, 0x74, 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x67,
+ 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x66, 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x75, 0x73,
+ 0x20, 0x64, 0x69, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x3b, 0x20, 0x61,
+ 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x68,
+ 0x69, 0x6d, 0x2c, 0x20, 0x73, 0x6f, 0x20, 0x64, 0x69, 0x64, 0x20, 0x68,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x43, 0x6f, 0x6d,
+ 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x79, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65,
+ 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72,
+ 0x6b, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x49, 0x20, 0x73, 0x65, 0x65, 0x6e, 0x20,
+ 0x72, 0x69, 0x67, 0x68, 0x74, 0x65, 0x6f, 0x75, 0x73, 0x20, 0x62, 0x65,
+ 0x66, 0x6f, 0x72, 0x65, 0x20, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x69, 0x73, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x2e, 0x20, 0x0a, 0x4f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x63, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x61, 0x73,
+ 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74,
+ 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x65, 0x20, 0x62, 0x79, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x73, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6c, 0x65, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x62, 0x65, 0x61,
+ 0x73, 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x62,
+ 0x79, 0x20, 0x74, 0x77, 0x6f, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x61, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65, 0x2e, 0x20, 0x0a, 0x4f, 0x66, 0x20,
+ 0x66, 0x6f, 0x77, 0x6c, 0x73, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72, 0x20, 0x62, 0x79,
+ 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x61, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65, 0x3b, 0x20, 0x74, 0x6f,
+ 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x61,
+ 0x6c, 0x69, 0x76, 0x65, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e,
+ 0x20, 0x0a, 0x46, 0x6f, 0x72, 0x20, 0x79, 0x65, 0x74, 0x20, 0x73, 0x65,
+ 0x76, 0x65, 0x6e, 0x20, 0x64, 0x61, 0x79, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x63, 0x61, 0x75,
+ 0x73, 0x65, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x61, 0x69,
+ 0x6e, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x79, 0x20, 0x64,
+ 0x61, 0x79, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x74,
+ 0x79, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x73, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69,
+ 0x6e, 0x67, 0x20, 0x73, 0x75, 0x62, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65,
+ 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x49,
+ 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x6f, 0x66, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61,
+ 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4e, 0x6f,
+ 0x61, 0x68, 0x20, 0x64, 0x69, 0x64, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x72,
+ 0x64, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65,
+ 0x64, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x69, 0x78,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x6f, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61,
+ 0x68, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66,
+ 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73,
+ 0x6f, 0x6e, 0x73, 0x27, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x69, 0x6e, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x62,
+ 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a,
+ 0x4f, 0x66, 0x20, 0x63, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x61,
+ 0x73, 0x74, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x62, 0x65, 0x61, 0x73, 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6c, 0x65, 0x61,
+ 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x6f,
+ 0x77, 0x6c, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x65, 0x74,
+ 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x72, 0x65,
+ 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x77, 0x6f,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x61, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65, 0x2c, 0x20, 0x61, 0x73,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68, 0x61, 0x64, 0x20, 0x63, 0x6f, 0x6d,
+ 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d,
+ 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x20, 0x61, 0x66,
+ 0x74, 0x65, 0x72, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x64, 0x61,
+ 0x79, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x6f, 0x64, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x49, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x69, 0x78, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65,
+ 0x64, 0x74, 0x68, 0x20, 0x79, 0x65, 0x61, 0x72, 0x20, 0x6f, 0x66, 0x20,
+ 0x4e, 0x6f, 0x61, 0x68, 0x27, 0x73, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x2c,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6f,
+ 0x6e, 0x64, 0x20, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x2c, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x74,
+ 0x68, 0x20, 0x64, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x61, 0x6d, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f,
+ 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x64, 0x65, 0x65,
+ 0x70, 0x20, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x75, 0x70, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6e,
+ 0x64, 0x6f, 0x77, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65, 0x61, 0x76,
+ 0x65, 0x6e, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6f, 0x70, 0x65, 0x6e,
+ 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x72, 0x61, 0x69, 0x6e, 0x20, 0x77, 0x61, 0x73, 0x20, 0x75, 0x70,
+ 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x79, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x69,
+ 0x67, 0x68, 0x74, 0x73, 0x2e, 0x20, 0x0a, 0x49, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x64,
+ 0x61, 0x79, 0x20, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x4e,
+ 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x68, 0x65,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48, 0x61, 0x6d, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x70, 0x68, 0x65, 0x74, 0x68, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4e,
+ 0x6f, 0x61, 0x68, 0x27, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x72, 0x65,
+ 0x65, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x3b, 0x20, 0x0a, 0x54, 0x68,
+ 0x65, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x62, 0x65, 0x61, 0x73, 0x74, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63,
+ 0x72, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e,
+ 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70,
+ 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x66, 0x6f, 0x77,
+ 0x6c, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20,
+ 0x62, 0x69, 0x72, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x73, 0x6f, 0x72, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x69,
+ 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20,
+ 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b,
+ 0x2c, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x77,
+ 0x6f, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c, 0x65,
+ 0x73, 0x68, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x20,
+ 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x72, 0x65, 0x61, 0x74,
+ 0x68, 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x2c, 0x20, 0x77,
+ 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x6d, 0x61, 0x6c, 0x65, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x2c,
+ 0x20, 0x61, 0x73, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68, 0x61, 0x64, 0x20,
+ 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x68, 0x69,
+ 0x6d, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x20, 0x73, 0x68, 0x75, 0x74, 0x20, 0x68, 0x69, 0x6d,
+ 0x20, 0x69, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x6f, 0x64, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x66, 0x6f, 0x72, 0x74, 0x79, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x75,
+ 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74,
+ 0x68, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x72, 0x65, 0x61,
+ 0x73, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x61, 0x72,
+ 0x65, 0x20, 0x75, 0x70, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x6c, 0x69, 0x66, 0x74, 0x20, 0x75, 0x70, 0x20, 0x61, 0x62, 0x6f,
+ 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x70, 0x72, 0x65, 0x76, 0x61, 0x69,
+ 0x6c, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x69, 0x6e, 0x63, 0x72, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20,
+ 0x67, 0x72, 0x65, 0x61, 0x74, 0x6c, 0x79, 0x20, 0x75, 0x70, 0x6f, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x20,
+ 0x77, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72,
+ 0x73, 0x20, 0x70, 0x72, 0x65, 0x76, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20,
+ 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x69, 0x6e, 0x67, 0x6c, 0x79, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x68, 0x69, 0x67, 0x68, 0x20, 0x68, 0x69, 0x6c,
+ 0x6c, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x68, 0x6f, 0x6c, 0x65, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e,
+ 0x2c, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72,
+ 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x46, 0x69, 0x66, 0x74, 0x65, 0x65, 0x6e,
+ 0x20, 0x63, 0x75, 0x62, 0x69, 0x74, 0x73, 0x20, 0x75, 0x70, 0x77, 0x61,
+ 0x72, 0x64, 0x20, 0x64, 0x69, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x70, 0x72, 0x65, 0x76, 0x61, 0x69,
+ 0x6c, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73,
+ 0x68, 0x20, 0x64, 0x69, 0x65, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x62, 0x6f,
+ 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c,
+ 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x62, 0x65,
+ 0x61, 0x73, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x69,
+ 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x65, 0x74, 0x68, 0x20, 0x75,
+ 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74,
+ 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x6d, 0x61, 0x6e, 0x3a, 0x20, 0x0a, 0x41, 0x6c, 0x6c, 0x20, 0x69,
+ 0x6e, 0x20, 0x77, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x6e, 0x6f, 0x73, 0x74,
+ 0x72, 0x69, 0x6c, 0x73, 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x62, 0x72, 0x65, 0x61, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x6c,
+ 0x69, 0x66, 0x65, 0x2c, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x72, 0x79, 0x20, 0x6c, 0x61, 0x6e, 0x64,
+ 0x2c, 0x20, 0x64, 0x69, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e,
+ 0x67, 0x20, 0x73, 0x75, 0x62, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x65,
+ 0x64, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2c, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6d, 0x61,
+ 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c,
+ 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x72, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e,
+ 0x67, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x6f, 0x77, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x64, 0x65,
+ 0x73, 0x74, 0x72, 0x6f, 0x79, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x6f, 0x6e, 0x6c,
+ 0x79, 0x20, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x61,
+ 0x6c, 0x69, 0x76, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72,
+ 0x73, 0x20, 0x70, 0x72, 0x65, 0x76, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65,
+ 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x66, 0x74, 0x79, 0x20,
+ 0x64, 0x61, 0x79, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x72, 0x65, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x65,
+ 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67,
+ 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x74, 0x74,
+ 0x6c, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x61, 0x20,
+ 0x77, 0x69, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73,
+ 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x61, 0x73, 0x73, 0x77,
+ 0x61, 0x67, 0x65, 0x64, 0x3b, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x66,
+ 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x61, 0x6c, 0x73,
+ 0x6f, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x65,
+ 0x70, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69,
+ 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65, 0x61,
+ 0x76, 0x65, 0x6e, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x73, 0x74, 0x6f,
+ 0x70, 0x70, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x72, 0x61, 0x69, 0x6e, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x20, 0x77, 0x61, 0x73, 0x20, 0x72,
+ 0x65, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x3b, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65,
+ 0x72, 0x73, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x20,
+ 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6f, 0x66, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x69,
+ 0x6e, 0x75, 0x61, 0x6c, 0x6c, 0x79, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x75, 0x6e,
+ 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x66,
+ 0x74, 0x79, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x61, 0x62, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x20, 0x72, 0x65, 0x73,
+ 0x74, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x76, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x6d, 0x6f, 0x6e, 0x74, 0x68,
+ 0x2c, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x76,
+ 0x65, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6e, 0x74,
+ 0x68, 0x2c, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x41, 0x72, 0x61, 0x72, 0x61, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73,
+ 0x20, 0x64, 0x65, 0x63, 0x72, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x63,
+ 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x75,
+ 0x6e, 0x74, 0x69, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x6e,
+ 0x74, 0x68, 0x20, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x3a, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x6d,
+ 0x6f, 0x6e, 0x74, 0x68, 0x2c, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x64, 0x61, 0x79, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x2c,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x6f,
+ 0x70, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f,
+ 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x73, 0x65, 0x65, 0x6e,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61,
+ 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x20, 0x61,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x79, 0x20, 0x64, 0x61, 0x79, 0x73, 0x2c,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x6f,
+ 0x70, 0x65, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69,
+ 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x61, 0x72, 0x6b, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x68, 0x65,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20,
+ 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x20, 0x72, 0x61, 0x76, 0x65,
+ 0x6e, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x6e,
+ 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x2c, 0x20, 0x75, 0x6e, 0x74, 0x69,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x64, 0x72, 0x69, 0x65, 0x64, 0x20,
+ 0x75, 0x70, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6f, 0x66, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6c, 0x73, 0x6f, 0x20, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x74,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x20, 0x64, 0x6f, 0x76,
+ 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20,
+ 0x74, 0x6f, 0x20, 0x73, 0x65, 0x65, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x61, 0x62, 0x61, 0x74, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x6f, 0x66, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61,
+ 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x6f, 0x76, 0x65, 0x20, 0x66, 0x6f, 0x75, 0x6e,
+ 0x64, 0x20, 0x6e, 0x6f, 0x20, 0x72, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6c, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x68, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x6f, 0x74, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x72, 0x65, 0x74, 0x75,
+ 0x72, 0x6e, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69,
+ 0x6d, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61,
+ 0x72, 0x6b, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x6f, 0x6c, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x6e,
+ 0x20, 0x68, 0x65, 0x20, 0x70, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74,
+ 0x68, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x68, 0x65, 0x72,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x75, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x68, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x69, 0x6d, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x74, 0x61, 0x79, 0x65, 0x64, 0x20, 0x79, 0x65,
+ 0x74, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x65, 0x76, 0x65,
+ 0x6e, 0x20, 0x64, 0x61, 0x79, 0x73, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x61, 0x67, 0x61, 0x69, 0x6e, 0x20, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e,
+ 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x64, 0x6f, 0x76, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x3b, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x6f, 0x76, 0x65, 0x20, 0x63,
+ 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69,
+ 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65,
+ 0x6e, 0x69, 0x6e, 0x67, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x6c,
+ 0x6f, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x65, 0x72, 0x20, 0x6d, 0x6f,
+ 0x75, 0x74, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x6f,
+ 0x6c, 0x69, 0x76, 0x65, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x20, 0x70, 0x6c,
+ 0x75, 0x63, 0x6b, 0x74, 0x20, 0x6f, 0x66, 0x66, 0x3a, 0x20, 0x73, 0x6f,
+ 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x6b, 0x6e, 0x65, 0x77, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65,
+ 0x72, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x61, 0x62, 0x61, 0x74,
+ 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6f, 0x66, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x74, 0x61, 0x79, 0x65,
+ 0x64, 0x20, 0x79, 0x65, 0x74, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x64, 0x61, 0x79, 0x73, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x6f, 0x76, 0x65, 0x3b,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72,
+ 0x6e, 0x65, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x67, 0x61, 0x69,
+ 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61,
+ 0x6e, 0x79, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f,
+ 0x20, 0x70, 0x61, 0x73, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x69, 0x78, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64,
+ 0x74, 0x68, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x6d, 0x6f, 0x6e, 0x74,
+ 0x68, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74,
+ 0x20, 0x64, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x64,
+ 0x72, 0x69, 0x65, 0x64, 0x20, 0x75, 0x70, 0x20, 0x66, 0x72, 0x6f, 0x6d,
+ 0x20, 0x6f, 0x66, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68,
+ 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x64, 0x72, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e,
+ 0x64, 0x20, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x2c, 0x20, 0x6f, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x77, 0x65, 0x6e, 0x74, 0x69, 0x65, 0x74, 0x68, 0x20,
+ 0x64, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x6f, 0x6e, 0x74, 0x68, 0x2c, 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x64, 0x72, 0x69, 0x65,
+ 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x70, 0x61, 0x6b, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4e,
+ 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c,
+ 0x20, 0x0a, 0x47, 0x6f, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x27, 0x20, 0x77,
+ 0x69, 0x76, 0x65, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x2e, 0x20, 0x0a, 0x42, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66,
+ 0x6f, 0x72, 0x74, 0x68, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76,
+ 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74,
+ 0x68, 0x65, 0x65, 0x2c, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x66, 0x6c, 0x65, 0x73, 0x68, 0x2c, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20,
+ 0x6f, 0x66, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x6f, 0x66, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68,
+ 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x72, 0x65,
+ 0x65, 0x70, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3b, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x6d, 0x61, 0x79, 0x20,
+ 0x62, 0x72, 0x65, 0x65, 0x64, 0x20, 0x61, 0x62, 0x75, 0x6e, 0x64, 0x61,
+ 0x6e, 0x74, 0x6c, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x66, 0x75, 0x6c, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4e, 0x6f,
+ 0x61, 0x68, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74,
+ 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73,
+ 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x27, 0x20, 0x77, 0x69, 0x76,
+ 0x65, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x3a,
+ 0x20, 0x0a, 0x45, 0x76, 0x65, 0x72, 0x79, 0x20, 0x62, 0x65, 0x61, 0x73,
+ 0x74, 0x2c, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x72, 0x65,
+ 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x66,
+ 0x6f, 0x77, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x61,
+ 0x74, 0x73, 0x6f, 0x65, 0x76, 0x65, 0x72, 0x20, 0x63, 0x72, 0x65, 0x65,
+ 0x70, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x66, 0x74,
+ 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e,
+ 0x64, 0x73, 0x2c, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72,
+ 0x74, 0x68, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x64,
+ 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x6f, 0x66,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x6c, 0x65, 0x61, 0x6e,
+ 0x20, 0x62, 0x65, 0x61, 0x73, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x6c, 0x65,
+ 0x61, 0x6e, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x65, 0x64, 0x20, 0x62, 0x75, 0x72,
+ 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x73,
+ 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6c, 0x74, 0x61,
+ 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x6d, 0x65, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x61, 0x20, 0x73, 0x77, 0x65, 0x65, 0x74, 0x20, 0x73, 0x61, 0x76,
+ 0x6f, 0x75, 0x72, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x69,
+ 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x65, 0x61, 0x72, 0x74, 0x2c,
+ 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x61, 0x67, 0x61, 0x69, 0x6e, 0x20, 0x63, 0x75, 0x72, 0x73, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x61,
+ 0x6e, 0x79, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x6d, 0x61, 0x6e, 0x27, 0x73, 0x20, 0x73, 0x61, 0x6b, 0x65, 0x3b, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6d, 0x61, 0x67,
+ 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x6d,
+ 0x61, 0x6e, 0x27, 0x73, 0x20, 0x68, 0x65, 0x61, 0x72, 0x74, 0x20, 0x69,
+ 0x73, 0x20, 0x65, 0x76, 0x69, 0x6c, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x79, 0x6f, 0x75, 0x74, 0x68, 0x3b, 0x20, 0x6e,
+ 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x49, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x20, 0x73, 0x6d, 0x69, 0x74,
+ 0x65, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x65,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x6c,
+ 0x69, 0x76, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x49, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x2e, 0x20, 0x0a,
+ 0x57, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x72, 0x74, 0x68, 0x20, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x65, 0x74,
+ 0x68, 0x2c, 0x20, 0x73, 0x65, 0x65, 0x64, 0x74, 0x69, 0x6d, 0x65, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x61, 0x72, 0x76, 0x65, 0x73, 0x74, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6c, 0x64, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x61, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x75, 0x6d, 0x6d, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64,
+ 0x61, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63,
+ 0x65, 0x61, 0x73, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x4e,
+ 0x6f, 0x61, 0x68, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x73, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x2c, 0x20, 0x42, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x66, 0x75,
+ 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69,
+ 0x70, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x70,
+ 0x6c, 0x65, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x65, 0x61, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x79,
+ 0x6f, 0x75, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x72, 0x65, 0x61, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x75, 0x70, 0x6f,
+ 0x6e, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x62, 0x65, 0x61, 0x73,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72, 0x2c, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x6d, 0x6f, 0x76, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x73, 0x68, 0x65, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x61, 0x3b,
+ 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x68,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x65, 0x64, 0x2e, 0x20,
+ 0x0a, 0x45, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6d, 0x6f, 0x76, 0x69, 0x6e,
+ 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x6c, 0x69, 0x76, 0x65, 0x74, 0x68, 0x20, 0x73, 0x68, 0x61, 0x6c,
+ 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6d, 0x65, 0x61, 0x74, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x79, 0x6f, 0x75, 0x3b, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20,
+ 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x65, 0x65, 0x6e,
+ 0x20, 0x68, 0x65, 0x72, 0x62, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x49,
+ 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x20, 0x0a,
+ 0x42, 0x75, 0x74, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x2c, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6c,
+ 0x6f, 0x6f, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x2c,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x79, 0x65, 0x20, 0x6e, 0x6f,
+ 0x74, 0x20, 0x65, 0x61, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x73, 0x75, 0x72, 0x65, 0x6c, 0x79, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20,
+ 0x62, 0x6c, 0x6f, 0x6f, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x6f, 0x75,
+ 0x72, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x49, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x3b, 0x20,
+ 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x62, 0x65, 0x61,
+ 0x73, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x49, 0x20, 0x72, 0x65,
+ 0x71, 0x75, 0x69, 0x72, 0x65, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x6e,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x61, 0x6e, 0x3b, 0x20, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6d, 0x61, 0x6e, 0x27, 0x73,
+ 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x69, 0x6c,
+ 0x6c, 0x20, 0x49, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x6d, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x57, 0x68, 0x6f, 0x73, 0x6f, 0x20,
+ 0x73, 0x68, 0x65, 0x64, 0x64, 0x65, 0x74, 0x68, 0x20, 0x6d, 0x61, 0x6e,
+ 0x27, 0x73, 0x20, 0x62, 0x6c, 0x6f, 0x6f, 0x64, 0x2c, 0x20, 0x62, 0x79,
+ 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x62, 0x6c, 0x6f, 0x6f, 0x64, 0x20, 0x62, 0x65, 0x20,
+ 0x73, 0x68, 0x65, 0x64, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x68,
+ 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x79, 0x6f, 0x75, 0x2c, 0x20, 0x62, 0x65, 0x20, 0x79, 0x65, 0x20, 0x66,
+ 0x72, 0x75, 0x69, 0x74, 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x3b, 0x20, 0x62,
+ 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61,
+ 0x62, 0x75, 0x6e, 0x64, 0x61, 0x6e, 0x74, 0x6c, 0x79, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x70, 0x61, 0x6b, 0x65,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73,
+ 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d,
+ 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x49, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64,
+ 0x2c, 0x20, 0x49, 0x20, 0x65, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73,
+ 0x68, 0x20, 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e,
+ 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x79, 0x6f, 0x75, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x79, 0x6f, 0x75,
+ 0x72, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x79, 0x6f, 0x75, 0x3b, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69,
+ 0x76, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72,
+ 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x79, 0x6f, 0x75, 0x2c, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x2c, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x62, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x79, 0x6f, 0x75, 0x3b, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x67, 0x6f, 0x20, 0x6f,
+ 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72,
+ 0x6b, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20,
+ 0x62, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x65, 0x73, 0x74, 0x61,
+ 0x62, 0x6c, 0x69, 0x73, 0x68, 0x20, 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x76,
+ 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x79,
+ 0x6f, 0x75, 0x2c, 0x20, 0x6e, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c,
+ 0x65, 0x73, 0x68, 0x20, 0x62, 0x65, 0x20, 0x63, 0x75, 0x74, 0x20, 0x6f,
+ 0x66, 0x66, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20,
+ 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x66, 0x6c, 0x6f, 0x6f, 0x64,
+ 0x3b, 0x20, 0x6e, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61, 0x6e,
+ 0x79, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20,
+ 0x66, 0x6c, 0x6f, 0x6f, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x65, 0x73,
+ 0x74, 0x72, 0x6f, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20,
+ 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x76, 0x65,
+ 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x49,
+ 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65,
+ 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79, 0x6f, 0x75,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c,
+ 0x69, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75,
+ 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x79, 0x6f, 0x75, 0x2c, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x70, 0x65, 0x72, 0x70, 0x65, 0x74, 0x75, 0x61, 0x6c, 0x20, 0x67,
+ 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x20,
+ 0x0a, 0x49, 0x20, 0x64, 0x6f, 0x20, 0x73, 0x65, 0x74, 0x20, 0x6d, 0x79,
+ 0x20, 0x62, 0x6f, 0x77, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69,
+ 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x61, 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x6f,
+ 0x66, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74,
+ 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x6d, 0x65, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74,
+ 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x6f,
+ 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20,
+ 0x49, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x63, 0x6c,
+ 0x6f, 0x75, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x77, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x73, 0x65, 0x65, 0x6e, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x3a,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x72, 0x65, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6d, 0x79,
+ 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x2c, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x62, 0x65, 0x74, 0x77,
+ 0x65, 0x65, 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79,
+ 0x6f, 0x75, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61,
+ 0x74, 0x75, 0x72, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x66, 0x6c, 0x65, 0x73, 0x68, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20,
+ 0x62, 0x65, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x61, 0x20, 0x66, 0x6c, 0x6f,
+ 0x6f, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f,
+ 0x79, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f,
+ 0x77, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x6c, 0x6f, 0x6f, 0x6b, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x69, 0x74,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x6d, 0x61, 0x79,
+ 0x20, 0x72, 0x65, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x62,
+ 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76,
+ 0x69, 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73,
+ 0x68, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x75, 0x70,
+ 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4e, 0x6f, 0x61,
+ 0x68, 0x2c, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74,
+ 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x49, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x65, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68,
+ 0x65, 0x64, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x6d,
+ 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c,
+ 0x65, 0x73, 0x68, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4e, 0x6f, 0x61,
+ 0x68, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x6e, 0x74,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x53, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48, 0x61,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x70, 0x68, 0x65,
+ 0x74, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48, 0x61, 0x6d, 0x20,
+ 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x2e,
+ 0x20, 0x0a, 0x54, 0x68, 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x20, 0x73, 0x6f,
+ 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x6f, 0x6c,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x6f, 0x76, 0x65, 0x72,
+ 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x62, 0x65, 0x67, 0x61, 0x6e, 0x20,
+ 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x75, 0x73,
+ 0x62, 0x61, 0x6e, 0x64, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x20,
+ 0x61, 0x20, 0x76, 0x69, 0x6e, 0x65, 0x79, 0x61, 0x72, 0x64, 0x3a, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x72, 0x61, 0x6e,
+ 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6e,
+ 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x61, 0x73, 0x20, 0x64,
+ 0x72, 0x75, 0x6e, 0x6b, 0x65, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x75, 0x6e, 0x63, 0x6f, 0x76,
+ 0x65, 0x72, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x48, 0x61, 0x6d, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x61,
+ 0x6e, 0x61, 0x61, 0x6e, 0x2c, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6e, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x65, 0x73, 0x73, 0x20,
+ 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x6c, 0x64, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x62, 0x72, 0x65, 0x74,
+ 0x68, 0x72, 0x65, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x68, 0x65, 0x6d, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x70, 0x68, 0x65, 0x74, 0x68, 0x20,
+ 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x61, 0x20, 0x67, 0x61, 0x72, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x61, 0x69, 0x64,
+ 0x20, 0x69, 0x74, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x62, 0x6f, 0x74,
+ 0x68, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x73, 0x68, 0x6f, 0x75,
+ 0x6c, 0x64, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77,
+ 0x65, 0x6e, 0x74, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x77, 0x61, 0x72, 0x64,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6b, 0x65, 0x64, 0x6e,
+ 0x65, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72,
+ 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x66, 0x61, 0x63, 0x65, 0x73,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x77, 0x61,
+ 0x72, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x73, 0x61, 0x77, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x69, 0x72, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20,
+ 0x6e, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x65, 0x73, 0x73, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x61, 0x77, 0x6f,
+ 0x6b, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x77, 0x69, 0x6e, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6b, 0x6e,
+ 0x65, 0x77, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x79, 0x6f, 0x75, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x73, 0x6f, 0x6e, 0x20,
+ 0x68, 0x61, 0x64, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x43, 0x75, 0x72,
+ 0x73, 0x65, 0x64, 0x20, 0x62, 0x65, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61,
+ 0x6e, 0x3b, 0x20, 0x61, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x68, 0x65, 0x20, 0x62, 0x65,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72,
+ 0x65, 0x74, 0x68, 0x72, 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x6c,
+ 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x62, 0x65, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x53, 0x68, 0x65, 0x6d, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43,
+ 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x62, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61,
+ 0x6e, 0x74, 0x2e, 0x20, 0x0a, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x65, 0x6e, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x20, 0x4a,
+ 0x61, 0x70, 0x68, 0x65, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x64, 0x77, 0x65,
+ 0x6c, 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65,
+ 0x6e, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x68, 0x65, 0x6d, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x6c, 0x69, 0x76, 0x65,
+ 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x6c, 0x6f, 0x6f, 0x64, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x20,
+ 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x66, 0x69, 0x66, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4e, 0x6f,
+ 0x61, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6e, 0x69, 0x6e, 0x65,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x66, 0x69, 0x66, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x65,
+ 0x64, 0x2e, 0x20, 0x0a, 0x4e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65, 0x73,
+ 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65,
+ 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x53, 0x68, 0x65, 0x6d, 0x2c,
+ 0x20, 0x48, 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x61,
+ 0x70, 0x68, 0x65, 0x74, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c,
+ 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x73, 0x6f,
+ 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4a, 0x61, 0x70, 0x68, 0x65, 0x74,
+ 0x68, 0x3b, 0x20, 0x47, 0x6f, 0x6d, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x4d, 0x61, 0x67, 0x6f, 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x4d, 0x61, 0x64, 0x61, 0x69, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x4a, 0x61, 0x76, 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x54,
+ 0x75, 0x62, 0x61, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4d, 0x65,
+ 0x73, 0x68, 0x65, 0x63, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x54,
+ 0x69, 0x72, 0x61, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x47,
+ 0x6f, 0x6d, 0x65, 0x72, 0x3b, 0x20, 0x41, 0x73, 0x68, 0x6b, 0x65, 0x6e,
+ 0x61, 0x7a, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x52, 0x69, 0x70, 0x68,
+ 0x61, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x54, 0x6f, 0x67,
+ 0x61, 0x72, 0x6d, 0x61, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x4a, 0x61, 0x76, 0x61, 0x6e, 0x3b, 0x20, 0x45, 0x6c, 0x69, 0x73, 0x68,
+ 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x54, 0x61, 0x72, 0x73,
+ 0x68, 0x69, 0x73, 0x68, 0x2c, 0x20, 0x4b, 0x69, 0x74, 0x74, 0x69, 0x6d,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x44, 0x6f, 0x64, 0x61, 0x6e, 0x69,
+ 0x6d, 0x2e, 0x20, 0x0a, 0x42, 0x79, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x73,
+ 0x6c, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47,
+ 0x65, 0x6e, 0x74, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x64, 0x69, 0x76, 0x69,
+ 0x64, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72,
+ 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x3b, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x74, 0x6f, 0x6e, 0x67, 0x75, 0x65, 0x2c, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20,
+ 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x61, 0x6d,
+ 0x3b, 0x20, 0x43, 0x75, 0x73, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x4d, 0x69, 0x7a, 0x72, 0x61, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x50, 0x68, 0x75, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43,
+ 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x43, 0x75, 0x73, 0x68, 0x3b, 0x20, 0x53, 0x65, 0x62, 0x61, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x48, 0x61, 0x76, 0x69, 0x6c, 0x61, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x62, 0x74, 0x61, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x52, 0x61, 0x61, 0x6d, 0x61, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x62, 0x74, 0x65, 0x63, 0x68,
+ 0x61, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x52, 0x61, 0x61, 0x6d,
+ 0x61, 0x68, 0x3b, 0x20, 0x53, 0x68, 0x65, 0x62, 0x61, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x44, 0x65, 0x64, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x43, 0x75, 0x73, 0x68, 0x20, 0x62, 0x65, 0x67, 0x61,
+ 0x74, 0x20, 0x4e, 0x69, 0x6d, 0x72, 0x6f, 0x64, 0x3a, 0x20, 0x68, 0x65,
+ 0x20, 0x62, 0x65, 0x67, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65,
+ 0x20, 0x61, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x79, 0x20, 0x6f, 0x6e,
+ 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x48, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x61, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x79, 0x20, 0x68, 0x75, 0x6e,
+ 0x74, 0x65, 0x72, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x3a, 0x20, 0x77, 0x68, 0x65,
+ 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x45, 0x76, 0x65, 0x6e, 0x20,
+ 0x61, 0x73, 0x20, 0x4e, 0x69, 0x6d, 0x72, 0x6f, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x79, 0x20, 0x68, 0x75, 0x6e,
+ 0x74, 0x65, 0x72, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x6e,
+ 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b,
+ 0x69, 0x6e, 0x67, 0x64, 0x6f, 0x6d, 0x20, 0x77, 0x61, 0x73, 0x20, 0x42,
+ 0x61, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x45, 0x72,
+ 0x65, 0x63, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x63, 0x63,
+ 0x61, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x6c, 0x6e,
+ 0x65, 0x68, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x68, 0x69, 0x6e, 0x61,
+ 0x72, 0x2e, 0x20, 0x0a, 0x4f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x6e,
+ 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x41, 0x73, 0x73, 0x68,
+ 0x75, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x75, 0x69, 0x6c,
+ 0x64, 0x65, 0x64, 0x20, 0x4e, 0x69, 0x6e, 0x65, 0x76, 0x65, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x69, 0x74,
+ 0x79, 0x20, 0x52, 0x65, 0x68, 0x6f, 0x62, 0x6f, 0x74, 0x68, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x6c, 0x61, 0x68, 0x2c, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x6e, 0x20, 0x62, 0x65,
+ 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x4e, 0x69, 0x6e, 0x65, 0x76, 0x65,
+ 0x68, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x6c, 0x61, 0x68, 0x3a,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x73,
+ 0x20, 0x61, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x63, 0x69, 0x74,
+ 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4d, 0x69, 0x7a, 0x72,
+ 0x61, 0x69, 0x6d, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4c, 0x75,
+ 0x64, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x6e, 0x61,
+ 0x6d, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x65, 0x68,
+ 0x61, 0x62, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4e, 0x61,
+ 0x70, 0x68, 0x74, 0x75, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x50, 0x61, 0x74, 0x68, 0x72, 0x75, 0x73, 0x69, 0x6d, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x73, 0x6c, 0x75, 0x68, 0x69,
+ 0x6d, 0x2c, 0x20, 0x28, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x77,
+ 0x68, 0x6f, 0x6d, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x50, 0x68, 0x69,
+ 0x6c, 0x69, 0x73, 0x74, 0x69, 0x6d, 0x2c, 0x29, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x43, 0x61, 0x70, 0x68, 0x74, 0x6f, 0x72, 0x69, 0x6d, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x53, 0x69, 0x64, 0x6f, 0x6e, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x62, 0x6f,
+ 0x72, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48, 0x65, 0x74, 0x68,
+ 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4a,
+ 0x65, 0x62, 0x75, 0x73, 0x69, 0x74, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x6d, 0x6f, 0x72, 0x69, 0x74, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x69,
+ 0x72, 0x67, 0x61, 0x73, 0x69, 0x74, 0x65, 0x2c, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x69, 0x76, 0x69, 0x74, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x72,
+ 0x6b, 0x69, 0x74, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x53, 0x69, 0x6e, 0x69, 0x74, 0x65, 0x2c, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x72, 0x76, 0x61, 0x64,
+ 0x69, 0x74, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x5a, 0x65, 0x6d, 0x61, 0x72, 0x69, 0x74, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x61, 0x6d, 0x61, 0x74,
+ 0x68, 0x69, 0x74, 0x65, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x66,
+ 0x74, 0x65, 0x72, 0x77, 0x61, 0x72, 0x64, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x61, 0x6e,
+ 0x61, 0x61, 0x6e, 0x69, 0x74, 0x65, 0x73, 0x20, 0x73, 0x70, 0x72, 0x65,
+ 0x61, 0x64, 0x20, 0x61, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x61,
+ 0x6e, 0x61, 0x61, 0x6e, 0x69, 0x74, 0x65, 0x73, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x53, 0x69, 0x64, 0x6f, 0x6e, 0x2c,
+ 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x63, 0x6f, 0x6d,
+ 0x65, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x47, 0x65, 0x72, 0x61, 0x72,
+ 0x2c, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x47, 0x61, 0x7a, 0x61, 0x3b,
+ 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x67, 0x6f, 0x65,
+ 0x73, 0x74, 0x2c, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x53, 0x6f, 0x64,
+ 0x6f, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x6d, 0x6f,
+ 0x72, 0x72, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x64,
+ 0x6d, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x5a, 0x65, 0x62,
+ 0x6f, 0x69, 0x6d, 0x2c, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x4c, 0x61, 0x73, 0x68, 0x61, 0x2e, 0x20, 0x0a, 0x54,
+ 0x68, 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x61, 0x6d,
+ 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69,
+ 0x72, 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x2c, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20,
+ 0x74, 0x6f, 0x6e, 0x67, 0x75, 0x65, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72,
+ 0x69, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x2e, 0x20, 0x0a, 0x55, 0x6e, 0x74, 0x6f, 0x20, 0x53, 0x68, 0x65,
+ 0x6d, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72,
+ 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x62, 0x65, 0x72, 0x2c, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x6f, 0x66, 0x20, 0x4a, 0x61, 0x70, 0x68, 0x65, 0x74, 0x68, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x6c, 0x64, 0x65, 0x72, 0x2c, 0x20, 0x65, 0x76,
+ 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20,
+ 0x62, 0x6f, 0x72, 0x6e, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x63,
+ 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x53,
+ 0x68, 0x65, 0x6d, 0x3b, 0x20, 0x45, 0x6c, 0x61, 0x6d, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x41, 0x73, 0x73, 0x68, 0x75, 0x72, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x41, 0x72, 0x70, 0x68, 0x61, 0x78, 0x61, 0x64, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x75, 0x64, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x41, 0x72, 0x61, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65,
+ 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x72, 0x61, 0x6d, 0x3b, 0x20, 0x55,
+ 0x7a, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48, 0x75, 0x6c, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x47, 0x65, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4d, 0x61, 0x73, 0x68, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x41, 0x72, 0x70, 0x68, 0x61, 0x78, 0x61, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x53, 0x61, 0x6c, 0x61, 0x68, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x6c, 0x61, 0x68, 0x20, 0x62,
+ 0x65, 0x67, 0x61, 0x74, 0x20, 0x45, 0x62, 0x65, 0x72, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x45, 0x62, 0x65,
+ 0x72, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x20,
+ 0x74, 0x77, 0x6f, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x3a, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6f, 0x6e,
+ 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x50, 0x65, 0x6c, 0x65, 0x67, 0x3b,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x64, 0x61, 0x79, 0x73, 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64,
+ 0x65, 0x64, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x4a, 0x6f, 0x6b, 0x74, 0x61,
+ 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x6f, 0x6b, 0x74,
+ 0x61, 0x6e, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x41, 0x6c, 0x6d,
+ 0x6f, 0x64, 0x61, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x68,
+ 0x65, 0x6c, 0x65, 0x70, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48,
+ 0x61, 0x7a, 0x61, 0x72, 0x6d, 0x61, 0x76, 0x65, 0x74, 0x68, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x65, 0x72, 0x61, 0x68, 0x2c, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x48, 0x61, 0x64, 0x6f, 0x72, 0x61, 0x6d, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x55, 0x7a, 0x61, 0x6c, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x44, 0x69, 0x6b, 0x6c, 0x61, 0x68, 0x2c, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x4f, 0x62, 0x61, 0x6c, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x41, 0x62, 0x69, 0x6d, 0x61, 0x65, 0x6c, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x53, 0x68, 0x65, 0x62, 0x61, 0x2c, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x4f, 0x70, 0x68, 0x69, 0x72, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x48, 0x61, 0x76, 0x69, 0x6c, 0x61, 0x68, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x4a, 0x6f, 0x62, 0x61, 0x62, 0x3a, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x4a, 0x6f, 0x6b, 0x74, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x64, 0x77, 0x65, 0x6c,
+ 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x61, 0x73, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x4d, 0x65, 0x73, 0x68, 0x61, 0x2c, 0x20, 0x61, 0x73, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x67, 0x6f, 0x65, 0x73, 0x74, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x53, 0x65, 0x70, 0x68, 0x61, 0x72, 0x20, 0x61,
+ 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65,
+ 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x68, 0x65, 0x6d, 0x2c,
+ 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72,
+ 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x61,
+ 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x74,
+ 0x6f, 0x6e, 0x67, 0x75, 0x65, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x69, 0x72, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x2c, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20,
+ 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x20, 0x0a, 0x54, 0x68,
+ 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x4e, 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x69, 0x72, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x73,
+ 0x65, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64,
+ 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x72, 0x74, 0x68, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x6f, 0x6c, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67,
+ 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x6f, 0x6e,
+ 0x65, 0x20, 0x73, 0x70, 0x65, 0x65, 0x63, 0x68, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74,
+ 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x65,
+ 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x73, 0x74, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x70,
+ 0x6c, 0x61, 0x69, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x68, 0x69, 0x6e,
+ 0x61, 0x72, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x64, 0x77, 0x65, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x6f, 0x20,
+ 0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x47, 0x6f, 0x20,
+ 0x74, 0x6f, 0x2c, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x75, 0x73, 0x20, 0x6d,
+ 0x61, 0x6b, 0x65, 0x20, 0x62, 0x72, 0x69, 0x63, 0x6b, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x62, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x20, 0x74, 0x68, 0x6f, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x6c, 0x79, 0x2e,
+ 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x62, 0x72, 0x69, 0x63, 0x6b, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x73, 0x74, 0x6f, 0x6e, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x6c, 0x69, 0x6d, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x6f, 0x72, 0x74, 0x65, 0x72,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x47, 0x6f, 0x20, 0x74, 0x6f, 0x2c,
+ 0x20, 0x6c, 0x65, 0x74, 0x20, 0x75, 0x73, 0x20, 0x62, 0x75, 0x69, 0x6c,
+ 0x64, 0x20, 0x75, 0x73, 0x20, 0x61, 0x20, 0x63, 0x69, 0x74, 0x79, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x74, 0x6f, 0x77, 0x65, 0x72, 0x2c,
+ 0x20, 0x77, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x74, 0x6f, 0x70, 0x20, 0x6d,
+ 0x61, 0x79, 0x20, 0x72, 0x65, 0x61, 0x63, 0x68, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x75, 0x73, 0x20, 0x6d, 0x61, 0x6b,
+ 0x65, 0x20, 0x75, 0x73, 0x20, 0x61, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2c,
+ 0x20, 0x6c, 0x65, 0x73, 0x74, 0x20, 0x77, 0x65, 0x20, 0x62, 0x65, 0x20,
+ 0x73, 0x63, 0x61, 0x74, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x61, 0x62,
+ 0x72, 0x6f, 0x61, 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x68, 0x6f, 0x6c, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74,
+ 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x64, 0x6f,
+ 0x77, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x65, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x63, 0x69, 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x6f, 0x77, 0x65, 0x72, 0x2c, 0x20, 0x77, 0x68,
+ 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c,
+ 0x64, 0x72, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x65, 0x6e, 0x20,
+ 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x20,
+ 0x69, 0x73, 0x20, 0x6f, 0x6e, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61,
+ 0x67, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x20,
+ 0x74, 0x6f, 0x20, 0x64, 0x6f, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e,
+ 0x6f, 0x77, 0x20, 0x6e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72,
+ 0x61, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x69, 0x6d, 0x61,
+ 0x67, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x6f, 0x2e,
+ 0x20, 0x0a, 0x47, 0x6f, 0x20, 0x74, 0x6f, 0x2c, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x75, 0x73, 0x20, 0x67, 0x6f, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x63,
+ 0x6f, 0x6e, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x69,
+ 0x72, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x2c, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x6d, 0x61,
+ 0x79, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x73,
+ 0x74, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x61, 0x6e, 0x6f,
+ 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x73, 0x70, 0x65, 0x65, 0x63,
+ 0x68, 0x2e, 0x20, 0x0a, 0x53, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x20, 0x73, 0x63, 0x61, 0x74, 0x74, 0x65, 0x72, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x61, 0x62, 0x72, 0x6f, 0x61,
+ 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x63,
+ 0x65, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20,
+ 0x6f, 0x66, 0x66, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x69, 0x74, 0x79, 0x2e, 0x20, 0x0a,
+ 0x54, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x69, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x42,
+ 0x61, 0x62, 0x65, 0x6c, 0x3b, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x64,
+ 0x69, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x63, 0x6f, 0x6e,
+ 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61,
+ 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68,
+ 0x65, 0x6e, 0x63, 0x65, 0x20, 0x64, 0x69, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x63, 0x61, 0x74, 0x74, 0x65,
+ 0x72, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x61, 0x62, 0x72, 0x6f, 0x61,
+ 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x54,
+ 0x68, 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x53, 0x68, 0x65, 0x6d, 0x3a, 0x20, 0x53, 0x68,
+ 0x65, 0x6d, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x75,
+ 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20,
+ 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67,
+ 0x61, 0x74, 0x20, 0x41, 0x72, 0x70, 0x68, 0x61, 0x78, 0x61, 0x64, 0x20,
+ 0x74, 0x77, 0x6f, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x61, 0x66,
+ 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x6f,
+ 0x64, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x68, 0x65, 0x6d,
+ 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x41, 0x72,
+ 0x70, 0x68, 0x61, 0x78, 0x61, 0x64, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20,
+ 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x79, 0x65, 0x61, 0x72,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74,
+ 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61,
+ 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x41, 0x72, 0x70, 0x68, 0x61, 0x78, 0x61, 0x64, 0x20, 0x6c,
+ 0x69, 0x76, 0x65, 0x64, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61,
+ 0x74, 0x20, 0x53, 0x61, 0x6c, 0x61, 0x68, 0x3a, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x41, 0x72, 0x70, 0x68, 0x61, 0x78, 0x61, 0x64, 0x20, 0x6c,
+ 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68,
+ 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x53, 0x61, 0x6c, 0x61,
+ 0x68, 0x20, 0x66, 0x6f, 0x75, 0x72, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72,
+ 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x6c, 0x61, 0x68,
+ 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x74, 0x68, 0x69, 0x72, 0x74,
+ 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x45, 0x62, 0x65, 0x72, 0x3a,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x6c, 0x61, 0x68, 0x20,
+ 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x45, 0x62, 0x65,
+ 0x72, 0x20, 0x66, 0x6f, 0x75, 0x72, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72,
+ 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x62, 0x65, 0x72, 0x20,
+ 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x75, 0x72, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79, 0x20, 0x79, 0x65,
+ 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67,
+ 0x61, 0x74, 0x20, 0x50, 0x65, 0x6c, 0x65, 0x67, 0x3a, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x45, 0x62, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x76, 0x65,
+ 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x65, 0x20, 0x62,
+ 0x65, 0x67, 0x61, 0x74, 0x20, 0x50, 0x65, 0x6c, 0x65, 0x67, 0x20, 0x66,
+ 0x6f, 0x75, 0x72, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79, 0x20, 0x79,
+ 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65,
+ 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x50, 0x65, 0x6c, 0x65, 0x67, 0x20, 0x6c,
+ 0x69, 0x76, 0x65, 0x64, 0x20, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79, 0x20,
+ 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x67, 0x61, 0x74, 0x20, 0x52, 0x65, 0x75, 0x3a, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x50, 0x65, 0x6c, 0x65, 0x67, 0x20, 0x6c, 0x69, 0x76,
+ 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x65, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x52, 0x65, 0x75, 0x20, 0x74, 0x77,
+ 0x6f, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20,
+ 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75,
+ 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x52, 0x65, 0x75, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x74,
+ 0x77, 0x6f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x72, 0x74,
+ 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x53, 0x65, 0x72, 0x75, 0x67,
+ 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x52, 0x65, 0x75, 0x20, 0x6c,
+ 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68,
+ 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x53, 0x65, 0x72, 0x75,
+ 0x67, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65,
+ 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20,
+ 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x65, 0x72, 0x75, 0x67, 0x20,
+ 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4e, 0x61, 0x68, 0x6f, 0x72, 0x3a,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x65, 0x72, 0x75, 0x67, 0x20,
+ 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4e, 0x61, 0x68,
+ 0x6f, 0x72, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72,
+ 0x65, 0x64, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65,
+ 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4e, 0x61, 0x68,
+ 0x6f, 0x72, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x6e, 0x69, 0x6e,
+ 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x77, 0x65, 0x6e, 0x74, 0x79,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x54, 0x65, 0x72, 0x61, 0x68, 0x3a,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4e, 0x61, 0x68, 0x6f, 0x72, 0x20,
+ 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x54, 0x65, 0x72,
+ 0x61, 0x68, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65,
+ 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x74, 0x65,
+ 0x65, 0x6e, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65,
+ 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x54, 0x65, 0x72,
+ 0x61, 0x68, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x73, 0x65, 0x76,
+ 0x65, 0x6e, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x6d, 0x2c, 0x20, 0x4e, 0x61, 0x68, 0x6f, 0x72, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x48, 0x61, 0x72, 0x61, 0x6e, 0x2e, 0x20, 0x0a,
+ 0x4e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x61, 0x72,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x54, 0x65, 0x72,
+ 0x61, 0x68, 0x3a, 0x20, 0x54, 0x65, 0x72, 0x61, 0x68, 0x20, 0x62, 0x65,
+ 0x67, 0x61, 0x74, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x2c, 0x20, 0x4e,
+ 0x61, 0x68, 0x6f, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48, 0x61,
+ 0x72, 0x61, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48, 0x61, 0x72,
+ 0x61, 0x6e, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4c, 0x6f, 0x74,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x48, 0x61, 0x72, 0x61, 0x6e,
+ 0x20, 0x64, 0x69, 0x65, 0x64, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x54, 0x65, 0x72, 0x61, 0x68, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x69,
+ 0x6e, 0x20, 0x55, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x43, 0x68, 0x61, 0x6c, 0x64, 0x65, 0x65, 0x73, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x4e, 0x61, 0x68, 0x6f, 0x72, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x3a, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x41, 0x62, 0x72, 0x61, 0x6d, 0x27, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x4e, 0x61, 0x68, 0x6f, 0x72, 0x27, 0x73, 0x20,
+ 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x4d, 0x69, 0x6c, 0x63, 0x61, 0x68,
+ 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74,
+ 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x61, 0x72, 0x61, 0x6e, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x6f, 0x66, 0x20, 0x4d, 0x69, 0x6c, 0x63, 0x61, 0x68, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x20, 0x6f, 0x66, 0x20, 0x49, 0x73, 0x63, 0x61, 0x68, 0x2e, 0x20,
+ 0x0a, 0x42, 0x75, 0x74, 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x62, 0x61, 0x72, 0x72, 0x65, 0x6e, 0x3b, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6e, 0x6f, 0x20, 0x63, 0x68,
+ 0x69, 0x6c, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x54, 0x65,
+ 0x72, 0x61, 0x68, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x6d, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x61, 0x72, 0x61, 0x6e,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x27, 0x73, 0x20, 0x73,
+ 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x72, 0x61,
+ 0x69, 0x20, 0x68, 0x69, 0x73, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74,
+ 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x61, 0x77, 0x2c, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d,
+ 0x27, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x66,
+ 0x6f, 0x72, 0x74, 0x68, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x6d, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x55, 0x72, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x68, 0x61, 0x6c, 0x64, 0x65,
+ 0x65, 0x73, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x6f, 0x20, 0x69, 0x6e,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x66, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x3b, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x61, 0x6d, 0x65,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x48, 0x61, 0x72, 0x61, 0x6e, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x54,
+ 0x65, 0x72, 0x61, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x77,
+ 0x6f, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x54, 0x65, 0x72, 0x61, 0x68, 0x20,
+ 0x64, 0x69, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x48, 0x61, 0x72, 0x61,
+ 0x6e, 0x2e, 0x20, 0x0a, 0x4e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x68, 0x61, 0x64, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d,
+ 0x2c, 0x20, 0x47, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x6f,
+ 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x63, 0x6f,
+ 0x75, 0x6e, 0x74, 0x72, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6b, 0x69, 0x6e, 0x64,
+ 0x72, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x74, 0x68, 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72,
+ 0x27, 0x73, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2c, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x61, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x73, 0x68,
+ 0x65, 0x77, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3a, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6d, 0x61, 0x6b,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x61, 0x20,
+ 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x74, 0x68,
+ 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x62, 0x6c,
+ 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x6c, 0x65, 0x73,
+ 0x73, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x62, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x63, 0x75, 0x72, 0x73, 0x65, 0x20, 0x68, 0x69,
+ 0x6d, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x75, 0x72, 0x73, 0x65,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6c,
+ 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x20, 0x62, 0x65, 0x20, 0x62, 0x6c, 0x65, 0x73,
+ 0x73, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x53, 0x6f, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x6d, 0x20, 0x64, 0x65, 0x70, 0x61, 0x72, 0x74, 0x65, 0x64, 0x2c,
+ 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x73, 0x70, 0x6f, 0x6b, 0x65, 0x6e, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73,
+ 0x65, 0x76, 0x65, 0x6e, 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66,
+ 0x69, 0x76, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x6f, 0x6c,
+ 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x68, 0x65, 0x20, 0x64, 0x65,
+ 0x70, 0x61, 0x72, 0x74, 0x65, 0x64, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x48, 0x61, 0x72, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x74, 0x6f, 0x6f, 0x6b,
+ 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77,
+ 0x69, 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x6f, 0x74,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x27, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x73, 0x75,
+ 0x62, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x68, 0x61, 0x64, 0x20, 0x67, 0x61,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x75, 0x6c, 0x73, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x68, 0x61, 0x64, 0x20,
+ 0x67, 0x6f, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x48, 0x61,
+ 0x72, 0x61, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x79, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68,
+ 0x20, 0x74, 0x6f, 0x20, 0x67, 0x6f, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x70, 0x61,
+ 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x53, 0x69, 0x63, 0x68, 0x65, 0x6d, 0x2c, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61,
+ 0x69, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x4d, 0x6f, 0x72, 0x65, 0x68, 0x2e,
+ 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x61, 0x6e,
+ 0x61, 0x61, 0x6e, 0x69, 0x74, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x74,
+ 0x68, 0x65, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c,
+ 0x61, 0x6e, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61,
+ 0x72, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x55, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73,
+ 0x65, 0x65, 0x64, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x49, 0x20, 0x67,
+ 0x69, 0x76, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65,
+ 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2c, 0x20,
+ 0x77, 0x68, 0x6f, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x65, 0x64,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76,
+ 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x6e,
+ 0x63, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x6d, 0x6f,
+ 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x42, 0x65,
+ 0x74, 0x68, 0x65, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x69,
+ 0x74, 0x63, 0x68, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x74, 0x65,
+ 0x6e, 0x74, 0x2c, 0x20, 0x68, 0x61, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x42,
+ 0x65, 0x74, 0x68, 0x65, 0x6c, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x65, 0x73, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48,
+ 0x61, 0x69, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x73, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72,
+ 0x65, 0x20, 0x68, 0x65, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x64,
+ 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61,
+ 0x6d, 0x20, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x65, 0x64, 0x2c,
+ 0x20, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x6e, 0x20, 0x73, 0x74,
+ 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x6f, 0x77, 0x61, 0x72, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x6f, 0x75, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x61, 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6e, 0x65, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x77, 0x65, 0x6e,
+ 0x74, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20,
+ 0x45, 0x67, 0x79, 0x70, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x6f, 0x6a,
+ 0x6f, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x3b, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x6d, 0x69,
+ 0x6e, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x72, 0x69, 0x65, 0x76,
+ 0x6f, 0x75, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c,
+ 0x61, 0x6e, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74,
+ 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73,
+ 0x73, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x6e, 0x65, 0x61, 0x72,
+ 0x20, 0x74, 0x6f, 0x20, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x69, 0x6e,
+ 0x74, 0x6f, 0x20, 0x45, 0x67, 0x79, 0x70, 0x74, 0x2c, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f,
+ 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x77, 0x2c, 0x20, 0x49, 0x20, 0x6b, 0x6e,
+ 0x6f, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x61, 0x72, 0x74, 0x20, 0x61, 0x20, 0x66, 0x61, 0x69, 0x72, 0x20,
+ 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x6f,
+ 0x6b, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x3a, 0x20, 0x0a, 0x54, 0x68, 0x65,
+ 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x69, 0x74, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20,
+ 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x45, 0x67, 0x79, 0x70, 0x74, 0x69, 0x61, 0x6e, 0x73,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x73, 0x65, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x73, 0x61, 0x79,
+ 0x2c, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6b, 0x69,
+ 0x6c, 0x6c, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x73, 0x61, 0x76,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x61, 0x6c, 0x69, 0x76, 0x65,
+ 0x2e, 0x20, 0x0a, 0x53, 0x61, 0x79, 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72,
+ 0x61, 0x79, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x61, 0x72, 0x74, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x69, 0x73,
+ 0x74, 0x65, 0x72, 0x3a, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74,
+ 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x77, 0x65, 0x6c, 0x6c,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x61, 0x6b, 0x65, 0x3b, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x6f, 0x75, 0x6c, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x20, 0x62, 0x65,
+ 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63,
+ 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20,
+ 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x77, 0x61, 0x73, 0x20, 0x63, 0x6f,
+ 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x45, 0x67, 0x79, 0x70,
+ 0x74, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x45, 0x67, 0x79, 0x70, 0x74,
+ 0x69, 0x61, 0x6e, 0x73, 0x20, 0x62, 0x65, 0x68, 0x65, 0x6c, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x73, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x76,
+ 0x65, 0x72, 0x79, 0x20, 0x66, 0x61, 0x69, 0x72, 0x2e, 0x20, 0x0a, 0x54,
+ 0x68, 0x65, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x73, 0x20, 0x61,
+ 0x6c, 0x73, 0x6f, 0x20, 0x6f, 0x66, 0x20, 0x50, 0x68, 0x61, 0x72, 0x61,
+ 0x6f, 0x68, 0x20, 0x73, 0x61, 0x77, 0x20, 0x68, 0x65, 0x72, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x65,
+ 0x64, 0x20, 0x68, 0x65, 0x72, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65,
+ 0x20, 0x50, 0x68, 0x61, 0x72, 0x61, 0x6f, 0x68, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x69, 0x6e,
+ 0x74, 0x6f, 0x20, 0x50, 0x68, 0x61, 0x72, 0x61, 0x6f, 0x68, 0x27, 0x73,
+ 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x65, 0x6e, 0x74, 0x72, 0x65, 0x61, 0x74, 0x65,
+ 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x77, 0x65, 0x6c, 0x6c,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68, 0x65, 0x72, 0x20, 0x73, 0x61, 0x6b,
+ 0x65, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x73, 0x68, 0x65, 0x65, 0x70, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x6f, 0x78, 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x61, 0x73, 0x73, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x6d, 0x65, 0x6e, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x64, 0x73, 0x65,
+ 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x68, 0x65, 0x20, 0x61, 0x73, 0x73, 0x65, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x6c, 0x73, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x70, 0x6c, 0x61, 0x67, 0x75, 0x65, 0x64, 0x20, 0x50, 0x68, 0x61,
+ 0x72, 0x61, 0x6f, 0x68, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x67, 0x75, 0x65,
+ 0x73, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d,
+ 0x27, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x50, 0x68, 0x61, 0x72, 0x61, 0x6f, 0x68, 0x20, 0x63, 0x61,
+ 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x57, 0x68, 0x61,
+ 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74,
+ 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d,
+ 0x65, 0x3f, 0x20, 0x77, 0x68, 0x79, 0x20, 0x64, 0x69, 0x64, 0x73, 0x74,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x65,
+ 0x6c, 0x6c, 0x20, 0x6d, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x79, 0x20, 0x77,
+ 0x69, 0x66, 0x65, 0x3f, 0x20, 0x0a, 0x57, 0x68, 0x79, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x2c, 0x20, 0x53,
+ 0x68, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x69, 0x73,
+ 0x74, 0x65, 0x72, 0x3f, 0x20, 0x73, 0x6f, 0x20, 0x49, 0x20, 0x6d, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x61, 0x6b,
+ 0x65, 0x6e, 0x20, 0x68, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x65,
+ 0x20, 0x74, 0x6f, 0x20, 0x77, 0x69, 0x66, 0x65, 0x3a, 0x20, 0x6e, 0x6f,
+ 0x77, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20,
+ 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x20, 0x74, 0x68, 0x79, 0x20, 0x77,
+ 0x69, 0x66, 0x65, 0x2c, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x68, 0x65,
+ 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x6f, 0x20, 0x74, 0x68,
+ 0x79, 0x20, 0x77, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x50, 0x68, 0x61, 0x72, 0x61, 0x6f, 0x68, 0x20, 0x63, 0x6f, 0x6d, 0x6d,
+ 0x61, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x65,
+ 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x72, 0x6e, 0x69, 0x6e, 0x67,
+ 0x20, 0x68, 0x69, 0x6d, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x68, 0x69, 0x6d, 0x20,
+ 0x61, 0x77, 0x61, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x20,
+ 0x68, 0x61, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x6d, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x70, 0x20,
+ 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x67, 0x79, 0x70, 0x74,
+ 0x2c, 0x20, 0x68, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x20,
+ 0x68, 0x61, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x6f, 0x74,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x69,
+ 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x75, 0x74,
+ 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61,
+ 0x6d, 0x20, 0x77, 0x61, 0x73, 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x72,
+ 0x69, 0x63, 0x68, 0x20, 0x69, 0x6e, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c,
+ 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x69, 0x6c, 0x76, 0x65, 0x72,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x67, 0x6f, 0x6c,
+ 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x77,
+ 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6a,
+ 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x65,
+ 0x76, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x42, 0x65, 0x74, 0x68, 0x65,
+ 0x6c, 0x2c, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x68, 0x61, 0x64,
+ 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x2c, 0x20,
+ 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x42, 0x65, 0x74, 0x68,
+ 0x65, 0x6c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48, 0x61, 0x69, 0x3b, 0x20,
+ 0x0a, 0x55, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c,
+ 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61,
+ 0x6c, 0x74, 0x61, 0x72, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20,
+ 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x2c, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x2c, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x72, 0x64, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74,
+ 0x6f, 0x20, 0x62, 0x65, 0x61, 0x72, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x6d,
+ 0x69, 0x67, 0x68, 0x74, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x74,
+ 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x3a, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x73, 0x75, 0x62, 0x73, 0x74,
+ 0x61, 0x6e, 0x63, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x72, 0x65,
+ 0x61, 0x74, 0x2c, 0x20, 0x73, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x74, 0x6f, 0x67,
+ 0x65, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x20,
+ 0x73, 0x74, 0x72, 0x69, 0x66, 0x65, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65,
+ 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x72, 0x64, 0x6d,
+ 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x27,
+ 0x73, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x72, 0x64, 0x6d, 0x65, 0x6e,
+ 0x20, 0x6f, 0x66, 0x20, 0x4c, 0x6f, 0x74, 0x27, 0x73, 0x20, 0x63, 0x61,
+ 0x74, 0x74, 0x6c, 0x65, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x69, 0x74, 0x65, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x50, 0x65, 0x72, 0x69,
+ 0x7a, 0x7a, 0x69, 0x74, 0x65, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4c, 0x6f, 0x74, 0x2c, 0x20, 0x4c, 0x65,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x6e,
+ 0x6f, 0x20, 0x73, 0x74, 0x72, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x49, 0x20,
+ 0x70, 0x72, 0x61, 0x79, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x62,
+ 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x6d, 0x79, 0x20, 0x68,
+ 0x65, 0x72, 0x64, 0x6d, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x68, 0x65, 0x72, 0x64, 0x6d, 0x65, 0x6e, 0x3b, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x77, 0x65, 0x20, 0x62, 0x65, 0x20, 0x62, 0x72,
+ 0x65, 0x74, 0x68, 0x72, 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x49, 0x73, 0x20,
+ 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x6f, 0x6c,
+ 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3f, 0x20, 0x73, 0x65, 0x70, 0x61,
+ 0x72, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68, 0x79, 0x73, 0x65, 0x6c, 0x66,
+ 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72, 0x61, 0x79, 0x20, 0x74, 0x68, 0x65,
+ 0x65, 0x2c, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6d, 0x65, 0x3a, 0x20,
+ 0x69, 0x66, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x77, 0x69, 0x6c, 0x74,
+ 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x65,
+ 0x66, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65,
+ 0x6e, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x67, 0x6f, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74,
+ 0x3b, 0x20, 0x6f, 0x72, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x64, 0x65, 0x70, 0x61, 0x72, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x61, 0x6e,
+ 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x49, 0x20, 0x77, 0x69,
+ 0x6c, 0x6c, 0x20, 0x67, 0x6f, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6c, 0x65, 0x66, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x4c, 0x6f, 0x74, 0x20, 0x6c, 0x69, 0x66, 0x74, 0x65, 0x64, 0x20, 0x75,
+ 0x70, 0x20, 0x68, 0x69, 0x73, 0x20, 0x65, 0x79, 0x65, 0x73, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x68, 0x65, 0x6c, 0x64, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x69, 0x6e,
+ 0x20, 0x6f, 0x66, 0x20, 0x4a, 0x6f, 0x72, 0x64, 0x61, 0x6e, 0x2c, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x65, 0x64,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65,
+ 0x2c, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f,
+ 0x79, 0x65, 0x64, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x47, 0x6f, 0x6d, 0x6f, 0x72, 0x72, 0x61, 0x68, 0x2c, 0x20,
+ 0x65, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2c, 0x20, 0x6c, 0x69, 0x6b, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x45, 0x67, 0x79, 0x70, 0x74, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x73, 0x74, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x5a, 0x6f, 0x61, 0x72, 0x2e, 0x20, 0x0a, 0x54,
+ 0x68, 0x65, 0x6e, 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x63, 0x68, 0x6f, 0x73,
+ 0x65, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x4a,
+ 0x6f, 0x72, 0x64, 0x61, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c,
+ 0x6f, 0x74, 0x20, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x65, 0x64,
+ 0x20, 0x65, 0x61, 0x73, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x73, 0x65, 0x6c, 0x76, 0x65, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2e,
+ 0x20, 0x0a, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x64, 0x77, 0x65, 0x6c,
+ 0x6c, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61,
+ 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x64,
+ 0x77, 0x65, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x63, 0x69, 0x74, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x70, 0x69, 0x74, 0x63, 0x68, 0x65, 0x64, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x77, 0x61,
+ 0x72, 0x64, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x2e, 0x20, 0x0a, 0x42,
+ 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x6f,
+ 0x66, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x77, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x20, 0x62, 0x65, 0x66, 0x6f,
+ 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20,
+ 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x69, 0x6e, 0x67, 0x6c, 0x79, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x64,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x4c,
+ 0x69, 0x66, 0x74, 0x20, 0x75, 0x70, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x74,
+ 0x68, 0x69, 0x6e, 0x65, 0x20, 0x65, 0x79, 0x65, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x20, 0x66, 0x72, 0x6f, 0x6d,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x77,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x61, 0x72,
+ 0x74, 0x20, 0x6e, 0x6f, 0x72, 0x74, 0x68, 0x77, 0x61, 0x72, 0x64, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x6f, 0x75, 0x74, 0x68, 0x77, 0x61,
+ 0x72, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x61, 0x73, 0x74,
+ 0x77, 0x61, 0x72, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65,
+ 0x73, 0x74, 0x77, 0x61, 0x72, 0x64, 0x3a, 0x20, 0x0a, 0x46, 0x6f, 0x72,
+ 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x73, 0x65, 0x65, 0x73, 0x74, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x49, 0x20, 0x67,
+ 0x69, 0x76, 0x65, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x65, 0x76, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6d, 0x61,
+ 0x6b, 0x65, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20,
+ 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x75, 0x73, 0x74, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x3a, 0x20, 0x73, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x66,
+ 0x20, 0x61, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x6e,
+ 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x75,
+ 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x72, 0x74, 0x68, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64,
+ 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x6e, 0x75, 0x6d,
+ 0x62, 0x65, 0x72, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x72, 0x69, 0x73,
+ 0x65, 0x2c, 0x20, 0x77, 0x61, 0x6c, 0x6b, 0x20, 0x74, 0x68, 0x72, 0x6f,
+ 0x75, 0x67, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x65, 0x6e, 0x67,
+ 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x72, 0x65, 0x61,
+ 0x64, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x3b, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x67, 0x69,
+ 0x76, 0x65, 0x20, 0x69, 0x74, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x65, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x6e, 0x20, 0x41,
+ 0x62, 0x72, 0x61, 0x6d, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x64, 0x77, 0x65, 0x6c, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x4d, 0x61,
+ 0x6d, 0x72, 0x65, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x69,
+ 0x73, 0x20, 0x69, 0x6e, 0x20, 0x48, 0x65, 0x62, 0x72, 0x6f, 0x6e, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x74, 0x61,
+ 0x72, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74,
+ 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73,
+ 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x6d, 0x72, 0x61, 0x70, 0x68, 0x65,
+ 0x6c, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x68,
+ 0x69, 0x6e, 0x61, 0x72, 0x2c, 0x20, 0x41, 0x72, 0x69, 0x6f, 0x63, 0x68,
+ 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x6c, 0x6c,
+ 0x61, 0x73, 0x61, 0x72, 0x2c, 0x20, 0x43, 0x68, 0x65, 0x64, 0x6f, 0x72,
+ 0x6c, 0x61, 0x6f, 0x6d, 0x65, 0x72, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20,
+ 0x6f, 0x66, 0x20, 0x45, 0x6c, 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x54, 0x69, 0x64, 0x61, 0x6c, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20,
+ 0x6f, 0x66, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3b, 0x20,
+ 0x0a, 0x54, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20,
+ 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x61, 0x72, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x42, 0x65, 0x72, 0x61, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20,
+ 0x6f, 0x66, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x42, 0x69, 0x72, 0x73, 0x68,
+ 0x61, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x47, 0x6f,
+ 0x6d, 0x6f, 0x72, 0x72, 0x61, 0x68, 0x2c, 0x20, 0x53, 0x68, 0x69, 0x6e,
+ 0x61, 0x62, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x41,
+ 0x64, 0x6d, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x68,
+ 0x65, 0x6d, 0x65, 0x62, 0x65, 0x72, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20,
+ 0x6f, 0x66, 0x20, 0x5a, 0x65, 0x62, 0x6f, 0x69, 0x69, 0x6d, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 0x69, 0x6e, 0x67,
+ 0x20, 0x6f, 0x66, 0x20, 0x42, 0x65, 0x6c, 0x61, 0x2c, 0x20, 0x77, 0x68,
+ 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x5a, 0x6f, 0x61, 0x72, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20,
+ 0x77, 0x65, 0x72, 0x65, 0x20, 0x6a, 0x6f, 0x69, 0x6e, 0x65, 0x64, 0x20,
+ 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x53, 0x69, 0x64, 0x64, 0x69, 0x6d, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63,
+ 0x68, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6c,
+ 0x74, 0x20, 0x73, 0x65, 0x61, 0x2e, 0x20, 0x0a, 0x54, 0x77, 0x65, 0x6c,
+ 0x76, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x74, 0x68, 0x65,
+ 0x79, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x20, 0x43, 0x68, 0x65,
+ 0x64, 0x6f, 0x72, 0x6c, 0x61, 0x6f, 0x6d, 0x65, 0x72, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x68,
+ 0x69, 0x72, 0x74, 0x65, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x72, 0x65, 0x62, 0x65, 0x6c,
+ 0x6c, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x75, 0x72, 0x74, 0x65, 0x65,
+ 0x6e, 0x74, 0x68, 0x20, 0x79, 0x65, 0x61, 0x72, 0x20, 0x63, 0x61, 0x6d,
+ 0x65, 0x20, 0x43, 0x68, 0x65, 0x64, 0x6f, 0x72, 0x6c, 0x61, 0x6f, 0x6d,
+ 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6b, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77,
+ 0x65, 0x72, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x6d, 0x6f, 0x74, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x52, 0x65, 0x70, 0x68, 0x61, 0x69, 0x6d, 0x73,
+ 0x20, 0x69, 0x6e, 0x20, 0x41, 0x73, 0x68, 0x74, 0x65, 0x72, 0x6f, 0x74,
+ 0x68, 0x20, 0x4b, 0x61, 0x72, 0x6e, 0x61, 0x69, 0x6d, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x5a, 0x75, 0x7a, 0x69, 0x6d,
+ 0x73, 0x20, 0x69, 0x6e, 0x20, 0x48, 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x45, 0x6d, 0x69, 0x6e, 0x73, 0x20,
+ 0x69, 0x6e, 0x20, 0x53, 0x68, 0x61, 0x76, 0x65, 0x68, 0x20, 0x4b, 0x69,
+ 0x72, 0x69, 0x61, 0x74, 0x68, 0x61, 0x69, 0x6d, 0x2c, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x6f, 0x72, 0x69, 0x74,
+ 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20,
+ 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x53, 0x65, 0x69, 0x72, 0x2c, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x45, 0x6c, 0x70, 0x61, 0x72, 0x61, 0x6e,
+ 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x62,
+ 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x64, 0x65, 0x72,
+ 0x6e, 0x65, 0x73, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74,
+ 0x6f, 0x20, 0x45, 0x6e, 0x6d, 0x69, 0x73, 0x68, 0x70, 0x61, 0x74, 0x2c,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x4b, 0x61,
+ 0x64, 0x65, 0x73, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x6d,
+ 0x6f, 0x74, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x41, 0x6d, 0x61, 0x6c, 0x65, 0x6b, 0x69, 0x74, 0x65,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x41, 0x6d, 0x6f, 0x72, 0x69, 0x74, 0x65, 0x73,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x74,
+ 0x20, 0x69, 0x6e, 0x20, 0x48, 0x61, 0x7a, 0x65, 0x7a, 0x6f, 0x6e, 0x74,
+ 0x61, 0x6d, 0x61, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x75,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6f,
+ 0x66, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66,
+ 0x20, 0x47, 0x6f, 0x6d, 0x6f, 0x72, 0x72, 0x61, 0x68, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20,
+ 0x6f, 0x66, 0x20, 0x41, 0x64, 0x6d, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6f,
+ 0x66, 0x20, 0x5a, 0x65, 0x62, 0x6f, 0x69, 0x69, 0x6d, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20,
+ 0x6f, 0x66, 0x20, 0x42, 0x65, 0x6c, 0x61, 0x20, 0x28, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x73, 0x20, 0x5a, 0x6f, 0x61,
+ 0x72, 0x3b, 0x29, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x6a, 0x6f, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x61, 0x74, 0x74,
+ 0x6c, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x53, 0x69, 0x64, 0x64, 0x69, 0x6d, 0x3b, 0x20,
+ 0x0a, 0x57, 0x69, 0x74, 0x68, 0x20, 0x43, 0x68, 0x65, 0x64, 0x6f, 0x72,
+ 0x6c, 0x61, 0x6f, 0x6d, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b,
+ 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x6c, 0x61, 0x6d, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x54, 0x69,
+ 0x64, 0x61, 0x6c, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20,
+ 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x41, 0x6d, 0x72, 0x61, 0x70, 0x68, 0x65, 0x6c, 0x20, 0x6b, 0x69,
+ 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x68, 0x69, 0x6e, 0x61, 0x72,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x72, 0x69, 0x6f, 0x63, 0x68,
+ 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x6c, 0x6c,
+ 0x61, 0x73, 0x61, 0x72, 0x3b, 0x20, 0x66, 0x6f, 0x75, 0x72, 0x20, 0x6b,
+ 0x69, 0x6e, 0x67, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x66, 0x69,
+ 0x76, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x76, 0x61, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x69, 0x64,
+ 0x64, 0x69, 0x6d, 0x20, 0x77, 0x61, 0x73, 0x20, 0x66, 0x75, 0x6c, 0x6c,
+ 0x20, 0x6f, 0x66, 0x20, 0x73, 0x6c, 0x69, 0x6d, 0x65, 0x70, 0x69, 0x74,
+ 0x73, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b,
+ 0x69, 0x6e, 0x67, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x6f, 0x64, 0x6f,
+ 0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x6d, 0x6f, 0x72, 0x72,
+ 0x61, 0x68, 0x20, 0x66, 0x6c, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x66, 0x65, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x20,
+ 0x66, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x74, 0x6f, 0x6f, 0x6b,
+ 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x6f, 0x6f,
+ 0x64, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x6d, 0x6f, 0x72, 0x72, 0x61, 0x68,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68,
+ 0x65, 0x69, 0x72, 0x20, 0x76, 0x69, 0x63, 0x74, 0x75, 0x61, 0x6c, 0x73,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x69, 0x72, 0x20, 0x77, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x74, 0x6f, 0x6f, 0x6b,
+ 0x20, 0x4c, 0x6f, 0x74, 0x2c, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x27,
+ 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20,
+ 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x77, 0x68, 0x6f, 0x20, 0x64, 0x77, 0x65,
+ 0x6c, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x67, 0x6f, 0x6f,
+ 0x64, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x65, 0x70, 0x61,
+ 0x72, 0x74, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x6e,
+ 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x64, 0x20, 0x65,
+ 0x73, 0x63, 0x61, 0x70, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x6f, 0x6c, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x48, 0x65, 0x62, 0x72, 0x65, 0x77, 0x3b, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x68, 0x65, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x74, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x69, 0x6e,
+ 0x20, 0x6f, 0x66, 0x20, 0x4d, 0x61, 0x6d, 0x72, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x41, 0x6d, 0x6f, 0x72, 0x69, 0x74, 0x65, 0x2c, 0x20, 0x62,
+ 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x73,
+ 0x68, 0x63, 0x6f, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x72,
+ 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x6e, 0x65,
+ 0x72, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x65, 0x64,
+ 0x65, 0x72, 0x61, 0x74, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x41,
+ 0x62, 0x72, 0x61, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x77,
+ 0x68, 0x65, 0x6e, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x68, 0x65,
+ 0x61, 0x72, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x63, 0x61, 0x70, 0x74, 0x69,
+ 0x76, 0x65, 0x2c, 0x20, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6d, 0x65, 0x64,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x65, 0x64,
+ 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x62,
+ 0x6f, 0x72, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6f,
+ 0x77, 0x6e, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2c, 0x20, 0x74, 0x68,
+ 0x72, 0x65, 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x65, 0x6e,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x75, 0x72, 0x73, 0x75, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x44, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d,
+ 0x73, 0x65, 0x6c, 0x66, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x73, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x68, 0x65, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e,
+ 0x74, 0x73, 0x2c, 0x20, 0x62, 0x79, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x6d, 0x6f, 0x74, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x75,
+ 0x72, 0x73, 0x75, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x48, 0x6f, 0x62, 0x61, 0x68, 0x2c, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64,
+ 0x20, 0x6f, 0x66, 0x20, 0x44, 0x61, 0x6d, 0x61, 0x73, 0x63, 0x75, 0x73,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x62, 0x72,
+ 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x73,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x62,
+ 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x4c, 0x6f, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x65, 0x6e, 0x20, 0x61,
+ 0x6c, 0x73, 0x6f, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6f,
+ 0x66, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x20, 0x77, 0x65, 0x6e, 0x74,
+ 0x20, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x65, 0x74,
+ 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x72,
+ 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6c, 0x61, 0x75, 0x67,
+ 0x68, 0x74, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x68, 0x65, 0x64,
+ 0x6f, 0x72, 0x6c, 0x61, 0x6f, 0x6d, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 0x69, 0x6e,
+ 0x67, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x61,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x6c, 0x65, 0x79,
+ 0x20, 0x6f, 0x66, 0x20, 0x53, 0x68, 0x61, 0x76, 0x65, 0x68, 0x2c, 0x20,
+ 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x27, 0x73, 0x20, 0x64, 0x61, 0x6c, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4d, 0x65, 0x6c, 0x63, 0x68,
+ 0x69, 0x7a, 0x65, 0x64, 0x65, 0x6b, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20,
+ 0x6f, 0x66, 0x20, 0x53, 0x61, 0x6c, 0x65, 0x6d, 0x20, 0x62, 0x72, 0x6f,
+ 0x75, 0x67, 0x68, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x62,
+ 0x72, 0x65, 0x61, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x6e,
+ 0x65, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x69, 0x65, 0x73, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x73, 0x74,
+ 0x20, 0x68, 0x69, 0x67, 0x68, 0x20, 0x47, 0x6f, 0x64, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73,
+ 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x6c, 0x65, 0x73, 0x73, 0x65,
+ 0x64, 0x20, 0x62, 0x65, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x73, 0x74, 0x20, 0x68,
+ 0x69, 0x67, 0x68, 0x20, 0x47, 0x6f, 0x64, 0x2c, 0x20, 0x70, 0x6f, 0x73,
+ 0x73, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65,
+ 0x61, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x62, 0x6c, 0x65,
+ 0x73, 0x73, 0x65, 0x64, 0x20, 0x62, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x6f, 0x73, 0x74, 0x20, 0x68, 0x69, 0x67, 0x68, 0x20, 0x47, 0x6f,
+ 0x64, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x68, 0x61, 0x74,
+ 0x68, 0x20, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20,
+ 0x74, 0x68, 0x69, 0x6e, 0x65, 0x20, 0x65, 0x6e, 0x65, 0x6d, 0x69, 0x65,
+ 0x73, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79, 0x20, 0x68,
+ 0x61, 0x6e, 0x64, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x67, 0x61, 0x76, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x74, 0x69, 0x74,
+ 0x68, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 0x69, 0x6e,
+ 0x67, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x6d, 0x2c, 0x20, 0x47, 0x69, 0x76, 0x65, 0x20, 0x6d, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x73, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x79, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20,
+ 0x6f, 0x66, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x2c, 0x20, 0x49, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x6c, 0x69, 0x66, 0x74, 0x20, 0x75, 0x70,
+ 0x20, 0x6d, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x73, 0x74, 0x20, 0x68,
+ 0x69, 0x67, 0x68, 0x20, 0x47, 0x6f, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x70, 0x6f, 0x73, 0x73, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x20, 0x6f,
+ 0x66, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x0a, 0x54, 0x68, 0x61,
+ 0x74, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74,
+ 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61,
+ 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x20, 0x65, 0x76, 0x65, 0x6e,
+ 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x73, 0x68, 0x6f, 0x65, 0x6c, 0x61,
+ 0x74, 0x63, 0x68, 0x65, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x61, 0x6e, 0x79, 0x20,
+ 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69,
+ 0x73, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x65, 0x2c, 0x20, 0x6c, 0x65, 0x73,
+ 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c,
+ 0x64, 0x65, 0x73, 0x74, 0x20, 0x73, 0x61, 0x79, 0x2c, 0x20, 0x49, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x6d, 0x20, 0x72, 0x69, 0x63, 0x68, 0x3a, 0x20, 0x0a, 0x53,
+ 0x61, 0x76, 0x65, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x79, 0x6f, 0x75, 0x6e, 0x67, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x65, 0x61, 0x74, 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x41, 0x6e, 0x65,
+ 0x72, 0x2c, 0x20, 0x45, 0x73, 0x68, 0x63, 0x6f, 0x6c, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x4d, 0x61, 0x6d, 0x72, 0x65, 0x3b, 0x20, 0x6c, 0x65,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f,
+ 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68,
+ 0x65, 0x73, 0x65, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x63, 0x61, 0x6d, 0x65,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20,
+ 0x69, 0x6e, 0x20, 0x61, 0x20, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2c,
+ 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x46, 0x65, 0x61,
+ 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x2c, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d,
+ 0x3a, 0x20, 0x49, 0x20, 0x61, 0x6d, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73,
+ 0x68, 0x69, 0x65, 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x69, 0x6e, 0x67,
+ 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x72, 0x65, 0x77, 0x61, 0x72,
+ 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61,
+ 0x6d, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x47, 0x6f, 0x64, 0x2c, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x77,
+ 0x69, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x67, 0x69, 0x76,
+ 0x65, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x65, 0x65, 0x69, 0x6e, 0x67,
+ 0x20, 0x49, 0x20, 0x67, 0x6f, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x6c,
+ 0x65, 0x73, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x74, 0x65, 0x77, 0x61, 0x72, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x6d, 0x79, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20,
+ 0x74, 0x68, 0x69, 0x73, 0x20, 0x45, 0x6c, 0x69, 0x65, 0x7a, 0x65, 0x72,
+ 0x20, 0x6f, 0x66, 0x20, 0x44, 0x61, 0x6d, 0x61, 0x73, 0x63, 0x75, 0x73,
+ 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e,
+ 0x20, 0x6e, 0x6f, 0x20, 0x73, 0x65, 0x65, 0x64, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x2c, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x62,
+ 0x6f, 0x72, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x6d, 0x79, 0x20, 0x68, 0x6f,
+ 0x75, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x69, 0x6e, 0x65, 0x20,
+ 0x68, 0x65, 0x69, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x2c, 0x20,
+ 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x6f, 0x72, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69,
+ 0x6e, 0x67, 0x2c, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x74, 0x68,
+ 0x69, 0x6e, 0x65, 0x20, 0x68, 0x65, 0x69, 0x72, 0x3b, 0x20, 0x62, 0x75,
+ 0x74, 0x20, 0x68, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x66, 0x6f, 0x72,
+ 0x74, 0x68, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x69, 0x6e, 0x65, 0x20, 0x6f, 0x77, 0x6e, 0x20, 0x62, 0x6f, 0x77, 0x65,
+ 0x6c, 0x73, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20,
+ 0x74, 0x68, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x65, 0x69, 0x72, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x62, 0x72, 0x6f, 0x75,
+ 0x67, 0x68, 0x74, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x66, 0x6f, 0x72, 0x74,
+ 0x68, 0x20, 0x61, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x6f, 0x6f, 0x6b,
+ 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x6f, 0x77, 0x61, 0x72, 0x64, 0x20,
+ 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x65, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x61,
+ 0x72, 0x73, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x62, 0x65, 0x20, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x6e,
+ 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x53, 0x6f,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73,
+ 0x65, 0x65, 0x64, 0x20, 0x62, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x6c, 0x69, 0x65, 0x76, 0x65, 0x64,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x75,
+ 0x6e, 0x74, 0x65, 0x64, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x68,
+ 0x69, 0x6d, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74,
+ 0x65, 0x6f, 0x75, 0x73, 0x6e, 0x65, 0x73, 0x73, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x49, 0x20, 0x61,
+ 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20,
+ 0x55, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x68,
+ 0x61, 0x6c, 0x64, 0x65, 0x65, 0x73, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x67,
+ 0x69, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x74, 0x68, 0x69,
+ 0x73, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e,
+ 0x68, 0x65, 0x72, 0x69, 0x74, 0x20, 0x69, 0x74, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x2c, 0x20, 0x77, 0x68,
+ 0x65, 0x72, 0x65, 0x62, 0x79, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x49, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x49, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x69, 0x6e, 0x68, 0x65,
+ 0x72, 0x69, 0x74, 0x20, 0x69, 0x74, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x54, 0x61, 0x6b, 0x65, 0x20,
+ 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x65, 0x69, 0x66, 0x65, 0x72,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x20, 0x79, 0x65,
+ 0x61, 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x61, 0x20, 0x73, 0x68, 0x65, 0x20, 0x67, 0x6f, 0x61, 0x74, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x61, 0x20, 0x72, 0x61, 0x6d, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x72,
+ 0x65, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x74, 0x75, 0x72, 0x74,
+ 0x6c, 0x65, 0x64, 0x6f, 0x76, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x61, 0x20, 0x79, 0x6f, 0x75, 0x6e, 0x67, 0x20, 0x70, 0x69, 0x67, 0x65,
+ 0x6f, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69,
+ 0x6d, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x69, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6c, 0x61, 0x69, 0x64, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x70, 0x69,
+ 0x65, 0x63, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x61, 0x67, 0x61, 0x69,
+ 0x6e, 0x73, 0x74, 0x20, 0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x3a,
+ 0x20, 0x62, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x72,
+ 0x64, 0x73, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x77,
+ 0x6c, 0x73, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x64, 0x6f, 0x77, 0x6e,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61,
+ 0x72, 0x63, 0x61, 0x73, 0x65, 0x73, 0x2c, 0x20, 0x41, 0x62, 0x72, 0x61,
+ 0x6d, 0x20, 0x64, 0x72, 0x6f, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x20, 0x61, 0x77, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x75, 0x6e,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x20, 0x64,
+ 0x6f, 0x77, 0x6e, 0x2c, 0x20, 0x61, 0x20, 0x64, 0x65, 0x65, 0x70, 0x20,
+ 0x73, 0x6c, 0x65, 0x65, 0x70, 0x20, 0x66, 0x65, 0x6c, 0x6c, 0x20, 0x75,
+ 0x70, 0x6f, 0x6e, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x3b, 0x20, 0x61,
+ 0x6e, 0x64, 0x2c, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x61, 0x6e, 0x20, 0x68,
+ 0x6f, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x67, 0x72, 0x65,
+ 0x61, 0x74, 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e, 0x65, 0x73, 0x73, 0x20,
+ 0x66, 0x65, 0x6c, 0x6c, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x68, 0x69,
+ 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x6d, 0x2c, 0x20, 0x4b, 0x6e, 0x6f, 0x77, 0x20, 0x6f, 0x66, 0x20,
+ 0x61, 0x20, 0x73, 0x75, 0x72, 0x65, 0x74, 0x79, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x73, 0x74,
+ 0x72, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20,
+ 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x27, 0x73,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x73, 0x65, 0x72, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x61, 0x66, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x20, 0x66, 0x6f, 0x75, 0x72, 0x20, 0x68, 0x75, 0x6e,
+ 0x64, 0x72, 0x65, 0x64, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x3b, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x77,
+ 0x68, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x2c, 0x20, 0x77, 0x69,
+ 0x6c, 0x6c, 0x20, 0x49, 0x20, 0x6a, 0x75, 0x64, 0x67, 0x65, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x77, 0x61, 0x72,
+ 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x73, 0x75, 0x62,
+ 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20,
+ 0x67, 0x6f, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79, 0x20, 0x66, 0x61,
+ 0x74, 0x68, 0x65, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x65, 0x61,
+ 0x63, 0x65, 0x3b, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x74, 0x20, 0x62, 0x65, 0x20, 0x62, 0x75, 0x72, 0x69, 0x65, 0x64,
+ 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x6f,
+ 0x6c, 0x64, 0x20, 0x61, 0x67, 0x65, 0x2e, 0x20, 0x0a, 0x42, 0x75, 0x74,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x75, 0x72,
+ 0x74, 0x68, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c,
+ 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x68, 0x69, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x69, 0x71, 0x75, 0x69, 0x74, 0x79,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x6d, 0x6f, 0x72,
+ 0x69, 0x74, 0x65, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x79, 0x65, 0x74, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74,
+ 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x75, 0x6e, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x64, 0x6f, 0x77, 0x6e,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x64, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x20, 0x61, 0x20, 0x73, 0x6d, 0x6f, 0x6b, 0x69, 0x6e, 0x67, 0x20,
+ 0x66, 0x75, 0x72, 0x6e, 0x61, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x61, 0x20, 0x62, 0x75, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x6c,
+ 0x61, 0x6d, 0x70, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x61, 0x73,
+ 0x73, 0x65, 0x64, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20,
+ 0x74, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x70, 0x69, 0x65, 0x63, 0x65, 0x73,
+ 0x2e, 0x20, 0x0a, 0x49, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61,
+ 0x6d, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x61, 0x20, 0x63,
+ 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69,
+ 0x6e, 0x67, 0x2c, 0x20, 0x55, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x49,
+ 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20,
+ 0x6c, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20,
+ 0x45, 0x67, 0x79, 0x70, 0x74, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x72, 0x69, 0x76,
+ 0x65, 0x72, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x69, 0x76, 0x65,
+ 0x72, 0x20, 0x45, 0x75, 0x70, 0x68, 0x72, 0x61, 0x74, 0x65, 0x73, 0x3a,
+ 0x20, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x4b, 0x65, 0x6e, 0x69, 0x74, 0x65,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4b,
+ 0x65, 0x6e, 0x69, 0x7a, 0x7a, 0x69, 0x74, 0x65, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4b, 0x61, 0x64, 0x6d, 0x6f,
+ 0x6e, 0x69, 0x74, 0x65, 0x73, 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x48, 0x69, 0x74, 0x74, 0x69, 0x74, 0x65, 0x73,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x50, 0x65,
+ 0x72, 0x69, 0x7a, 0x7a, 0x69, 0x74, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x52, 0x65, 0x70, 0x68, 0x61, 0x69,
+ 0x6d, 0x73, 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x41, 0x6d, 0x6f, 0x72, 0x69, 0x74, 0x65, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61,
+ 0x6e, 0x69, 0x74, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x47, 0x69, 0x72, 0x67, 0x61, 0x73, 0x68, 0x69, 0x74,
+ 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4a, 0x65, 0x62, 0x75, 0x73, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x20, 0x0a,
+ 0x4e, 0x6f, 0x77, 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x6d, 0x27, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x20, 0x62,
+ 0x61, 0x72, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x6e, 0x6f, 0x20, 0x63,
+ 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x61, 0x6e, 0x20,
+ 0x68, 0x61, 0x6e, 0x64, 0x6d, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x61, 0x6e,
+ 0x20, 0x45, 0x67, 0x79, 0x70, 0x74, 0x69, 0x61, 0x6e, 0x2c, 0x20, 0x77,
+ 0x68, 0x6f, 0x73, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x48, 0x61, 0x67, 0x61, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x2c,
+ 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x77, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x68, 0x61,
+ 0x74, 0x68, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x65,
+ 0x64, 0x20, 0x6d, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x62, 0x65,
+ 0x61, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x49, 0x20, 0x70, 0x72, 0x61,
+ 0x79, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x67, 0x6f, 0x20, 0x69,
+ 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x79, 0x20, 0x6d, 0x61,
+ 0x69, 0x64, 0x3b, 0x20, 0x69, 0x74, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62,
+ 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x6d, 0x61, 0x79,
+ 0x20, 0x6f, 0x62, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x63, 0x68, 0x69, 0x6c,
+ 0x64, 0x72, 0x65, 0x6e, 0x20, 0x62, 0x79, 0x20, 0x68, 0x65, 0x72, 0x2e,
+ 0x20, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x68,
+ 0x65, 0x61, 0x72, 0x6b, 0x65, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d,
+ 0x27, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x6b,
+ 0x20, 0x48, 0x61, 0x67, 0x61, 0x72, 0x20, 0x68, 0x65, 0x72, 0x20, 0x6d,
+ 0x61, 0x69, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x45, 0x67, 0x79, 0x70,
+ 0x74, 0x69, 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x68, 0x61, 0x64, 0x20, 0x64, 0x77,
+ 0x65, 0x6c, 0x74, 0x20, 0x74, 0x65, 0x6e, 0x20, 0x79, 0x65, 0x61, 0x72,
+ 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x61, 0x76, 0x65, 0x20, 0x68, 0x65,
+ 0x72, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x65, 0x72, 0x20, 0x68, 0x75, 0x73,
+ 0x62, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x74,
+ 0x6f, 0x20, 0x62, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x77,
+ 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x48, 0x61, 0x67, 0x61, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x73, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x63,
+ 0x65, 0x69, 0x76, 0x65, 0x64, 0x2c, 0x20, 0x68, 0x65, 0x72, 0x20, 0x6d,
+ 0x69, 0x73, 0x74, 0x72, 0x65, 0x73, 0x73, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x64, 0x65, 0x73, 0x70, 0x69, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20,
+ 0x68, 0x65, 0x72, 0x20, 0x65, 0x79, 0x65, 0x73, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d,
+ 0x2c, 0x20, 0x4d, 0x79, 0x20, 0x77, 0x72, 0x6f, 0x6e, 0x67, 0x20, 0x62,
+ 0x65, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3a,
+ 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65,
+ 0x6e, 0x20, 0x6d, 0x79, 0x20, 0x6d, 0x61, 0x69, 0x64, 0x20, 0x69, 0x6e,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x6f, 0x73, 0x6f, 0x6d,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x73, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x63,
+ 0x65, 0x69, 0x76, 0x65, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x64, 0x65, 0x73, 0x70, 0x69, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e,
+ 0x20, 0x68, 0x65, 0x72, 0x20, 0x65, 0x79, 0x65, 0x73, 0x3a, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x6a, 0x75, 0x64, 0x67,
+ 0x65, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x6d, 0x65,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2e, 0x20, 0x0a,
+ 0x42, 0x75, 0x74, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x53, 0x61, 0x72, 0x61,
+ 0x69, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x6d, 0x61, 0x69, 0x64, 0x20, 0x69, 0x73, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x61, 0x6e, 0x64,
+ 0x3b, 0x20, 0x64, 0x6f, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x65, 0x72, 0x20,
+ 0x61, 0x73, 0x20, 0x69, 0x74, 0x20, 0x70, 0x6c, 0x65, 0x61, 0x73, 0x65,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x20,
+ 0x64, 0x65, 0x61, 0x6c, 0x74, 0x20, 0x68, 0x61, 0x72, 0x64, 0x6c, 0x79,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x66, 0x6c, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d,
+ 0x20, 0x68, 0x65, 0x72, 0x20, 0x66, 0x61, 0x63, 0x65, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6e, 0x67, 0x65,
+ 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x72, 0x20,
+ 0x62, 0x79, 0x20, 0x61, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69,
+ 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x64, 0x65, 0x72,
+ 0x6e, 0x65, 0x73, 0x73, 0x2c, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x79, 0x20, 0x74, 0x6f, 0x20,
+ 0x53, 0x68, 0x75, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x48, 0x61, 0x67, 0x61,
+ 0x72, 0x2c, 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x27, 0x73, 0x20, 0x6d,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x63, 0x65, 0x20,
+ 0x63, 0x61, 0x6d, 0x65, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x3f,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x69, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x77, 0x69, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x67,
+ 0x6f, 0x3f, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x66, 0x6c, 0x65, 0x65, 0x20,
+ 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x6d, 0x69, 0x73, 0x74,
+ 0x72, 0x65, 0x73, 0x73, 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6e, 0x67,
+ 0x65, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e,
+ 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6d, 0x69, 0x73, 0x74,
+ 0x72, 0x65, 0x73, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x75,
+ 0x62, 0x6d, 0x69, 0x74, 0x20, 0x74, 0x68, 0x79, 0x73, 0x65, 0x6c, 0x66,
+ 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x68, 0x65, 0x72, 0x20, 0x68,
+ 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x65, 0x72, 0x2c, 0x20,
+ 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69,
+ 0x70, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64,
+ 0x20, 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x69, 0x6e, 0x67, 0x6c, 0x79,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x6e,
+ 0x75, 0x6d, 0x62, 0x65, 0x72, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6e, 0x67, 0x65,
+ 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x68, 0x65, 0x72, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x61, 0x72, 0x74, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x62, 0x65, 0x61, 0x72, 0x20,
+ 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x74, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x49, 0x73, 0x68, 0x6d, 0x61,
+ 0x65, 0x6c, 0x3b, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x68, 0x61, 0x74,
+ 0x68, 0x20, 0x68, 0x65, 0x61, 0x72, 0x64, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x61, 0x66, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x77, 0x69, 0x6c, 0x64, 0x20, 0x6d,
+ 0x61, 0x6e, 0x3b, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x61, 0x6e, 0x64,
+ 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x67, 0x61,
+ 0x69, 0x6e, 0x73, 0x74, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6d,
+ 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x6d, 0x61, 0x6e, 0x27, 0x73, 0x20, 0x68, 0x61, 0x6e, 0x64,
+ 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x73, 0x74, 0x20, 0x68, 0x69, 0x6d,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x62, 0x72, 0x65, 0x74, 0x68, 0x72, 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x73, 0x70, 0x61, 0x6b, 0x65, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x54, 0x68, 0x6f, 0x75,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x65, 0x65, 0x73, 0x74, 0x20, 0x6d,
+ 0x65, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x48, 0x61, 0x76, 0x65, 0x20, 0x49, 0x20,
+ 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x68, 0x65, 0x72, 0x65, 0x20, 0x6c, 0x6f,
+ 0x6f, 0x6b, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68,
+ 0x69, 0x6d, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73, 0x65, 0x65, 0x74,
+ 0x68, 0x20, 0x6d, 0x65, 0x3f, 0x20, 0x0a, 0x57, 0x68, 0x65, 0x72, 0x65,
+ 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x65, 0x6c,
+ 0x6c, 0x20, 0x77, 0x61, 0x73, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x42, 0x65, 0x65, 0x72, 0x6c, 0x61, 0x68, 0x61, 0x69, 0x72, 0x6f,
+ 0x69, 0x3b, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x69,
+ 0x74, 0x20, 0x69, 0x73, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e,
+ 0x20, 0x4b, 0x61, 0x64, 0x65, 0x73, 0x68, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x42, 0x65, 0x72, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x48, 0x61, 0x67, 0x61, 0x72, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20, 0x41,
+ 0x62, 0x72, 0x61, 0x6d, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61,
+ 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e,
+ 0x27, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x48, 0x61, 0x67, 0x61, 0x72, 0x20, 0x62, 0x61, 0x72,
+ 0x65, 0x2c, 0x20, 0x49, 0x73, 0x68, 0x6d, 0x61, 0x65, 0x6c, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x66, 0x6f, 0x75, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x69, 0x78, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e,
+ 0x20, 0x48, 0x61, 0x67, 0x61, 0x72, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20,
+ 0x49, 0x73, 0x68, 0x6d, 0x61, 0x65, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x41,
+ 0x62, 0x72, 0x61, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x77,
+ 0x68, 0x65, 0x6e, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e,
+ 0x69, 0x6e, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x65, 0x64, 0x20, 0x74,
+ 0x6f, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68,
+ 0x69, 0x6d, 0x2c, 0x20, 0x49, 0x20, 0x61, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x41, 0x6c, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x79, 0x20, 0x47, 0x6f,
+ 0x64, 0x3b, 0x20, 0x77, 0x61, 0x6c, 0x6b, 0x20, 0x62, 0x65, 0x66, 0x6f,
+ 0x72, 0x65, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x63, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x6d, 0x79, 0x20,
+ 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x62, 0x65, 0x74,
+ 0x77, 0x65, 0x65, 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69,
+ 0x6c, 0x6c, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x20, 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x69,
+ 0x6e, 0x67, 0x6c, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41,
+ 0x62, 0x72, 0x61, 0x6d, 0x20, 0x66, 0x65, 0x6c, 0x6c, 0x20, 0x6f, 0x6e,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x74, 0x61, 0x6c, 0x6b, 0x65,
+ 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20,
+ 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x0a, 0x41, 0x73, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f,
+ 0x6c, 0x64, 0x2c, 0x20, 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e,
+ 0x61, 0x6e, 0x74, 0x20, 0x69, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x62, 0x65, 0x20,
+ 0x61, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20,
+ 0x6d, 0x61, 0x6e, 0x79, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+ 0x2e, 0x20, 0x0a, 0x4e, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6e, 0x61, 0x6d,
+ 0x65, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x62,
+ 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x6d, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62,
+ 0x65, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x3b, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x61, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x6f, 0x66, 0x20, 0x6d, 0x61, 0x6e, 0x79, 0x20, 0x6e, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x49, 0x20, 0x6d,
+ 0x61, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6d, 0x61,
+ 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x65, 0x78, 0x63, 0x65,
+ 0x65, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x66,
+ 0x75, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69,
+ 0x6c, 0x6c, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x6e, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x75,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x65,
+ 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x20, 0x6d, 0x79, 0x20,
+ 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x62, 0x65, 0x74,
+ 0x77, 0x65, 0x65, 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x69,
+ 0x72, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x76, 0x65,
+ 0x72, 0x6c, 0x61, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x6f, 0x76,
+ 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65,
+ 0x20, 0x61, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x61, 0x66,
+ 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x67, 0x69,
+ 0x76, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61,
+ 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x61, 0x72, 0x74, 0x20, 0x61, 0x20, 0x73, 0x74,
+ 0x72, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x61, 0x6e, 0x20, 0x65, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x73, 0x74, 0x69,
+ 0x6e, 0x67, 0x20, 0x70, 0x6f, 0x73, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f,
+ 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c,
+ 0x6c, 0x20, 0x62, 0x65, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x47,
+ 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41,
+ 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x54, 0x68, 0x6f, 0x75,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20,
+ 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x2c, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x69,
+ 0x72, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
+ 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x2c,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x79, 0x65, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x6b, 0x65, 0x65, 0x70, 0x2c, 0x20, 0x62, 0x65,
+ 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x79, 0x6f, 0x75, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x3b, 0x20, 0x45, 0x76, 0x65, 0x72, 0x79, 0x20,
+ 0x6d, 0x61, 0x6e, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x61, 0x6d,
+ 0x6f, 0x6e, 0x67, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c,
+ 0x6c, 0x20, 0x62, 0x65, 0x20, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x63,
+ 0x69, 0x73, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x79,
+ 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x69, 0x72, 0x63,
+ 0x75, 0x6d, 0x63, 0x69, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x6c, 0x65, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x72,
+ 0x20, 0x66, 0x6f, 0x72, 0x65, 0x73, 0x6b, 0x69, 0x6e, 0x3b, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x62, 0x65, 0x20, 0x61, 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61,
+ 0x6e, 0x74, 0x20, 0x62, 0x65, 0x74, 0x77, 0x69, 0x78, 0x74, 0x20, 0x6d,
+ 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79, 0x6f, 0x75, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x69, 0x73, 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x64, 0x61, 0x79,
+ 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x62, 0x65, 0x20, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x63, 0x69, 0x73,
+ 0x65, 0x64, 0x20, 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x20, 0x79, 0x6f, 0x75,
+ 0x2c, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6d, 0x61, 0x6e, 0x20,
+ 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x79, 0x6f, 0x75,
+ 0x72, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x2c, 0x20, 0x68, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69,
+ 0x73, 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2c, 0x20, 0x6f, 0x72, 0x20,
+ 0x62, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x6d, 0x6f, 0x6e, 0x65, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x79,
+ 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x2c, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64, 0x2e,
+ 0x20, 0x0a, 0x48, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73,
+ 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x62,
+ 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x6d, 0x6f, 0x6e, 0x65, 0x79, 0x2c, 0x20, 0x6d, 0x75,
+ 0x73, 0x74, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x20, 0x62, 0x65, 0x20,
+ 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x63, 0x69, 0x73, 0x65, 0x64, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x76, 0x65,
+ 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62,
+ 0x65, 0x20, 0x69, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x66, 0x6c,
+ 0x65, 0x73, 0x68, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x20, 0x65,
+ 0x76, 0x65, 0x72, 0x6c, 0x61, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x63,
+ 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x6e, 0x63, 0x69, 0x72, 0x63,
+ 0x75, 0x6d, 0x63, 0x69, 0x73, 0x65, 0x64, 0x20, 0x6d, 0x61, 0x6e, 0x20,
+ 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x77, 0x68, 0x6f, 0x73, 0x65, 0x20,
+ 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x66, 0x6f, 0x72, 0x65, 0x73, 0x6b, 0x69, 0x6e, 0x20, 0x69, 0x73,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x63,
+ 0x69, 0x73, 0x65, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73,
+ 0x6f, 0x75, 0x6c, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65,
+ 0x20, 0x63, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x66, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x68, 0x69, 0x73, 0x20, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65,
+ 0x3b, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x62, 0x72,
+ 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x76, 0x65,
+ 0x6e, 0x61, 0x6e, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x41, 0x73,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x68, 0x65, 0x72, 0x20, 0x6e, 0x61, 0x6d,
+ 0x65, 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x2c, 0x20, 0x62, 0x75, 0x74,
+ 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c,
+ 0x20, 0x68, 0x65, 0x72, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x62, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c,
+ 0x6c, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x68, 0x65, 0x72, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x61, 0x6c, 0x73,
+ 0x6f, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65, 0x72, 0x3a, 0x20, 0x79, 0x65,
+ 0x61, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x6c,
+ 0x65, 0x73, 0x73, 0x20, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x68, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62,
+ 0x65, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f,
+ 0x66, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3b, 0x20, 0x6b,
+ 0x69, 0x6e, 0x67, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x70, 0x65, 0x6f, 0x70,
+ 0x6c, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65,
+ 0x6e, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x66, 0x65,
+ 0x6c, 0x6c, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x66, 0x61, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x61,
+ 0x75, 0x67, 0x68, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68,
+ 0x65, 0x61, 0x72, 0x74, 0x2c, 0x20, 0x53, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x61, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x62,
+ 0x6f, 0x72, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6e, 0x20,
+ 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x79, 0x65, 0x61, 0x72,
+ 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x3f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x2c, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x69, 0x6e, 0x65,
+ 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64,
+ 0x2c, 0x20, 0x62, 0x65, 0x61, 0x72, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x47, 0x6f, 0x64, 0x2c, 0x20,
+ 0x4f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x73, 0x68, 0x6d, 0x61,
+ 0x65, 0x6c, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x20, 0x6c, 0x69, 0x76,
+ 0x65, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65,
+ 0x65, 0x21, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x20,
+ 0x74, 0x68, 0x79, 0x20, 0x77, 0x69, 0x66, 0x65, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x61, 0x72, 0x20, 0x74, 0x68, 0x65, 0x65,
+ 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x65,
+ 0x64, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x49, 0x73, 0x61, 0x61,
+ 0x63, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c,
+ 0x6c, 0x20, 0x65, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x20,
+ 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x61, 0x6e, 0x20, 0x65, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x73, 0x74,
+ 0x69, 0x6e, 0x67, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x61, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x49, 0x73, 0x68, 0x6d, 0x61,
+ 0x65, 0x6c, 0x2c, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x68,
+ 0x65, 0x61, 0x72, 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3a, 0x20, 0x42,
+ 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76,
+ 0x65, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x68, 0x69,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x66, 0x72, 0x75,
+ 0x69, 0x74, 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79,
+ 0x20, 0x68, 0x69, 0x6d, 0x20, 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x69,
+ 0x6e, 0x67, 0x6c, 0x79, 0x3b, 0x20, 0x74, 0x77, 0x65, 0x6c, 0x76, 0x65,
+ 0x20, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x73, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x65, 0x74, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61, 0x20, 0x67,
+ 0x72, 0x65, 0x61, 0x74, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
+ 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x76,
+ 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x49,
+ 0x20, 0x65, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x2c, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x61, 0x72, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x61, 0x74, 0x20, 0x74,
+ 0x68, 0x69, 0x73, 0x20, 0x73, 0x65, 0x74, 0x20, 0x74, 0x69, 0x6d, 0x65,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x65, 0x78, 0x74,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x6f, 0x66, 0x66, 0x20,
+ 0x74, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x70, 0x20, 0x66, 0x72,
+ 0x6f, 0x6d, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d,
+ 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x49, 0x73, 0x68, 0x6d, 0x61, 0x65,
+ 0x6c, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x77, 0x65, 0x72, 0x65, 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x69, 0x6e,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x62, 0x6f, 0x75, 0x67, 0x68, 0x74,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x6f,
+ 0x6e, 0x65, 0x79, 0x2c, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6d,
+ 0x61, 0x6c, 0x65, 0x20, 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x68, 0x61, 0x6d, 0x27, 0x73, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d,
+ 0x63, 0x69, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c,
+ 0x65, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72,
+ 0x20, 0x66, 0x6f, 0x72, 0x65, 0x73, 0x6b, 0x69, 0x6e, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x73, 0x61, 0x6d,
+ 0x65, 0x20, 0x64, 0x61, 0x79, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x68, 0x61, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e,
+ 0x69, 0x6e, 0x65, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x68, 0x65,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x63,
+ 0x69, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x66, 0x6f, 0x72, 0x65, 0x73, 0x6b, 0x69, 0x6e, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x68, 0x6d, 0x61, 0x65, 0x6c, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x74, 0x68, 0x69, 0x72, 0x74, 0x65, 0x65, 0x6e, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e,
+ 0x20, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x63, 0x69, 0x72, 0x63,
+ 0x75, 0x6d, 0x63, 0x69, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x65, 0x73, 0x6b, 0x69, 0x6e,
+ 0x2e, 0x20, 0x0a, 0x49, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65,
+ 0x6c, 0x66, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x63,
+ 0x69, 0x72, 0x63, 0x75, 0x6d, 0x63, 0x69, 0x73, 0x65, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x68, 0x6d, 0x61, 0x65, 0x6c, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65,
+ 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x6f, 0x75,
+ 0x73, 0x65, 0x2c, 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x62, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x6d, 0x6f, 0x6e, 0x65, 0x79, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x72,
+ 0x2c, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x63, 0x69, 0x72, 0x63, 0x75,
+ 0x6d, 0x63, 0x69, 0x73, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61,
+ 0x72, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x69,
+ 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4d, 0x61, 0x6d, 0x72, 0x65, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x74, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x20,
+ 0x64, 0x6f, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x68, 0x65, 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x64, 0x61, 0x79, 0x3b, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x6c, 0x69, 0x66, 0x74, 0x20, 0x75, 0x70, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x65, 0x79, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f,
+ 0x6f, 0x6b, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x6c,
+ 0x6f, 0x2c, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x20, 0x6d, 0x65, 0x6e,
+ 0x20, 0x73, 0x74, 0x6f, 0x6f, 0x64, 0x20, 0x62, 0x79, 0x20, 0x68, 0x69,
+ 0x6d, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c,
+ 0x20, 0x68, 0x65, 0x20, 0x72, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6d,
+ 0x65, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x64,
+ 0x6f, 0x6f, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x6f, 0x77,
+ 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x73, 0x65, 0x6c, 0x66, 0x20, 0x74,
+ 0x6f, 0x77, 0x61, 0x72, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4d, 0x79, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x2c, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x49, 0x20, 0x68,
+ 0x61, 0x76, 0x65, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x66, 0x61,
+ 0x76, 0x6f, 0x75, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x73, 0x69, 0x67, 0x68, 0x74, 0x2c, 0x20, 0x70, 0x61, 0x73, 0x73, 0x20,
+ 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x77, 0x61, 0x79, 0x2c, 0x20, 0x49, 0x20,
+ 0x70, 0x72, 0x61, 0x79, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x72, 0x76,
+ 0x61, 0x6e, 0x74, 0x3a, 0x20, 0x0a, 0x4c, 0x65, 0x74, 0x20, 0x61, 0x20,
+ 0x6c, 0x69, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72,
+ 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72, 0x61, 0x79, 0x20, 0x79, 0x6f, 0x75,
+ 0x2c, 0x20, 0x62, 0x65, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x65, 0x64,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x61, 0x73, 0x68, 0x20, 0x79,
+ 0x6f, 0x75, 0x72, 0x20, 0x66, 0x65, 0x65, 0x74, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x72, 0x65, 0x73, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x73,
+ 0x65, 0x6c, 0x76, 0x65, 0x73, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x3a, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x66, 0x65,
+ 0x74, 0x63, 0x68, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x72, 0x73, 0x65, 0x6c,
+ 0x20, 0x6f, 0x66, 0x20, 0x62, 0x72, 0x65, 0x61, 0x64, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6d, 0x66, 0x6f, 0x72, 0x74, 0x20, 0x79,
+ 0x65, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x68, 0x65, 0x61, 0x72, 0x74,
+ 0x73, 0x3b, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x79, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x70,
+ 0x61, 0x73, 0x73, 0x20, 0x6f, 0x6e, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x61, 0x72,
+ 0x65, 0x20, 0x79, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x6f,
+ 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e,
+ 0x74, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x53, 0x6f, 0x20, 0x64, 0x6f, 0x2c,
+ 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73,
+ 0x74, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x68, 0x61, 0x73,
+ 0x74, 0x65, 0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4d, 0x61, 0x6b, 0x65, 0x20, 0x72,
+ 0x65, 0x61, 0x64, 0x79, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x6c, 0x79,
+ 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x20, 0x6d, 0x65, 0x61, 0x73, 0x75,
+ 0x72, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x69, 0x6e, 0x65, 0x20,
+ 0x6d, 0x65, 0x61, 0x6c, 0x2c, 0x20, 0x6b, 0x6e, 0x65, 0x61, 0x64, 0x20,
+ 0x69, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x6b, 0x65,
+ 0x20, 0x63, 0x61, 0x6b, 0x65, 0x73, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d,
+ 0x20, 0x72, 0x61, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x68, 0x65, 0x72, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x66, 0x65, 0x74, 0x63, 0x68, 0x74, 0x20, 0x61, 0x20, 0x63, 0x61, 0x6c,
+ 0x66, 0x20, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67,
+ 0x61, 0x76, 0x65, 0x20, 0x69, 0x74, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x61, 0x20, 0x79, 0x6f, 0x75, 0x6e, 0x67, 0x20, 0x6d, 0x61, 0x6e, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x73, 0x74,
+ 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20,
+ 0x69, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x62, 0x75, 0x74, 0x74, 0x65, 0x72, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x69, 0x6c, 0x6b, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x66, 0x20,
+ 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64,
+ 0x20, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x65, 0x74, 0x20, 0x69, 0x74, 0x20, 0x62, 0x65, 0x66,
+ 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x6f, 0x64, 0x20, 0x62,
+ 0x79, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x64, 0x69, 0x64, 0x20,
+ 0x65, 0x61, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x57, 0x68, 0x65, 0x72, 0x65, 0x20,
+ 0x69, 0x73, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x77, 0x69, 0x66, 0x65, 0x3f, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f,
+ 0x6c, 0x64, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
+ 0x65, 0x6e, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c,
+ 0x6c, 0x20, 0x63, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6e, 0x6c, 0x79, 0x20,
+ 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69,
+ 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x69,
+ 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x53, 0x61, 0x72,
+ 0x61, 0x68, 0x20, 0x74, 0x68, 0x79, 0x20, 0x77, 0x69, 0x66, 0x65, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x61,
+ 0x20, 0x73, 0x6f, 0x6e, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x61,
+ 0x72, 0x61, 0x68, 0x20, 0x68, 0x65, 0x61, 0x72, 0x64, 0x20, 0x69, 0x74,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x6e, 0x74,
+ 0x20, 0x64, 0x6f, 0x6f, 0x72, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x62, 0x65, 0x68, 0x69, 0x6e, 0x64, 0x20,
+ 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x4e, 0x6f, 0x77, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x61,
+ 0x72, 0x61, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6f, 0x6c, 0x64,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x73, 0x74,
+ 0x72, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x67,
+ 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x65,
+ 0x61, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x61, 0x66,
+ 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x6e,
+ 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x77, 0x6f, 0x6d, 0x65, 0x6e, 0x2e,
+ 0x20, 0x0a, 0x54, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20,
+ 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x6c, 0x61, 0x75, 0x67, 0x68, 0x65,
+ 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x68, 0x65, 0x72,
+ 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67,
+ 0x2c, 0x20, 0x41, 0x66, 0x74, 0x65, 0x72, 0x20, 0x49, 0x20, 0x61, 0x6d,
+ 0x20, 0x77, 0x61, 0x78, 0x65, 0x64, 0x20, 0x6f, 0x6c, 0x64, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20,
+ 0x70, 0x6c, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x6d, 0x79,
+ 0x20, 0x6c, 0x6f, 0x72, 0x64, 0x20, 0x62, 0x65, 0x69, 0x6e, 0x67, 0x20,
+ 0x6f, 0x6c, 0x64, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x3f, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x57, 0x68, 0x65, 0x72, 0x65,
+ 0x66, 0x6f, 0x72, 0x65, 0x20, 0x64, 0x69, 0x64, 0x20, 0x53, 0x61, 0x72,
+ 0x61, 0x68, 0x20, 0x6c, 0x61, 0x75, 0x67, 0x68, 0x2c, 0x20, 0x73, 0x61,
+ 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x53, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x49, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x73, 0x75, 0x72, 0x65, 0x74,
+ 0x79, 0x20, 0x62, 0x65, 0x61, 0x72, 0x20, 0x61, 0x20, 0x63, 0x68, 0x69,
+ 0x6c, 0x64, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, 0x6d,
+ 0x20, 0x6f, 0x6c, 0x64, 0x3f, 0x20, 0x0a, 0x49, 0x73, 0x20, 0x61, 0x6e,
+ 0x79, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x6f, 0x20,
+ 0x68, 0x61, 0x72, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x3f, 0x20, 0x41, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x61, 0x70, 0x70, 0x6f, 0x69,
+ 0x6e, 0x74, 0x65, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64,
+ 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
+ 0x69, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x61, 0x20,
+ 0x73, 0x6f, 0x6e, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x6e, 0x20, 0x53,
+ 0x61, 0x72, 0x61, 0x68, 0x20, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x2c,
+ 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x49, 0x20, 0x6c,
+ 0x61, 0x75, 0x67, 0x68, 0x65, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x3b, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x73, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x61, 0x66, 0x72, 0x61, 0x69, 0x64, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4e, 0x61, 0x79,
+ 0x3b, 0x20, 0x62, 0x75, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x64,
+ 0x69, 0x64, 0x73, 0x74, 0x20, 0x6c, 0x61, 0x75, 0x67, 0x68, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e,
+ 0x20, 0x72, 0x6f, 0x73, 0x65, 0x20, 0x75, 0x70, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x77,
+ 0x61, 0x72, 0x64, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x77,
+ 0x65, 0x6e, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65,
+ 0x6d, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20,
+ 0x53, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x49, 0x20, 0x68, 0x69, 0x64, 0x65,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61,
+ 0x6d, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x49, 0x20, 0x64, 0x6f, 0x3b,
+ 0x20, 0x0a, 0x53, 0x65, 0x65, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x73, 0x75, 0x72, 0x65, 0x6c, 0x79, 0x20, 0x62,
+ 0x65, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x61, 0x20, 0x67, 0x72, 0x65, 0x61,
+ 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x79,
+ 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x62, 0x65, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x69,
+ 0x6e, 0x20, 0x68, 0x69, 0x6d, 0x3f, 0x20, 0x0a, 0x46, 0x6f, 0x72, 0x20,
+ 0x49, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x68,
+ 0x6f, 0x6c, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x77, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x64,
+ 0x6f, 0x20, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x63, 0x65, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6a, 0x75, 0x64, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x3b, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x68, 0x65, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x73, 0x70, 0x6f, 0x6b,
+ 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x63, 0x61, 0x75,
+ 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x72, 0x79, 0x20, 0x6f,
+ 0x66, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x47, 0x6f, 0x6d, 0x6f, 0x72, 0x72, 0x61, 0x68, 0x20, 0x69, 0x73, 0x20,
+ 0x67, 0x72, 0x65, 0x61, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72,
+ 0x20, 0x73, 0x69, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x67, 0x72, 0x69, 0x65, 0x76, 0x6f, 0x75, 0x73, 0x3b, 0x20, 0x0a,
+ 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x67, 0x6f, 0x20, 0x64, 0x6f,
+ 0x77, 0x6e, 0x20, 0x6e, 0x6f, 0x77, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x65, 0x65, 0x20, 0x77, 0x68, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x64, 0x6f,
+ 0x6e, 0x65, 0x20, 0x61, 0x6c, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65,
+ 0x72, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x72, 0x79, 0x20, 0x6f,
+ 0x66, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x69, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x6d, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x66, 0x20,
+ 0x6e, 0x6f, 0x74, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x6b, 0x6e, 0x6f, 0x77, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x74, 0x75, 0x72, 0x6e, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x66, 0x61, 0x63, 0x65,
+ 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x63,
+ 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20,
+ 0x74, 0x6f, 0x77, 0x61, 0x72, 0x64, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d,
+ 0x3a, 0x20, 0x62, 0x75, 0x74, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61,
+ 0x6d, 0x20, 0x73, 0x74, 0x6f, 0x6f, 0x64, 0x20, 0x79, 0x65, 0x74, 0x20,
+ 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x64, 0x72, 0x65, 0x77, 0x20, 0x6e,
+ 0x65, 0x61, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x57, 0x69, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f,
+ 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x65,
+ 0x6f, 0x75, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x3f, 0x20, 0x0a, 0x50, 0x65,
+ 0x72, 0x61, 0x64, 0x76, 0x65, 0x6e, 0x74, 0x75, 0x72, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x66, 0x69, 0x66, 0x74,
+ 0x79, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x65, 0x6f, 0x75, 0x73, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x69, 0x74, 0x79, 0x3a, 0x20, 0x77, 0x69, 0x6c, 0x74, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x64, 0x65, 0x73, 0x74,
+ 0x72, 0x6f, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x73, 0x70, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c,
+ 0x61, 0x63, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x69, 0x66, 0x74, 0x79, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x65,
+ 0x6f, 0x75, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x3f, 0x20, 0x0a, 0x54,
+ 0x68, 0x61, 0x74, 0x20, 0x62, 0x65, 0x20, 0x66, 0x61, 0x72, 0x20, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x74, 0x6f, 0x20,
+ 0x64, 0x6f, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x69,
+ 0x73, 0x20, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2c, 0x20, 0x74, 0x6f,
+ 0x20, 0x73, 0x6c, 0x61, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x69,
+ 0x67, 0x68, 0x74, 0x65, 0x6f, 0x75, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x65, 0x6f, 0x75, 0x73, 0x20,
+ 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x61, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x2c,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x62, 0x65, 0x20, 0x66, 0x61, 0x72,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3a, 0x20,
+ 0x53, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x4a, 0x75, 0x64, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x20, 0x64, 0x6f, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3f, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20,
+ 0x66, 0x69, 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x53, 0x6f, 0x64, 0x6f,
+ 0x6d, 0x20, 0x66, 0x69, 0x66, 0x74, 0x79, 0x20, 0x72, 0x69, 0x67, 0x68,
+ 0x74, 0x65, 0x6f, 0x75, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x74,
+ 0x68, 0x65, 0x6e, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x73,
+ 0x70, 0x61, 0x72, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x69, 0x72, 0x20, 0x73, 0x61, 0x6b, 0x65, 0x73, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d,
+ 0x20, 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f,
+ 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x77, 0x2c, 0x20, 0x49, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x75, 0x70, 0x6f,
+ 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x70, 0x65, 0x61,
+ 0x6b, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
+ 0x6d, 0x20, 0x62, 0x75, 0x74, 0x20, 0x64, 0x75, 0x73, 0x74, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x61, 0x73, 0x68, 0x65, 0x73, 0x3a, 0x20, 0x0a, 0x50,
+ 0x65, 0x72, 0x61, 0x64, 0x76, 0x65, 0x6e, 0x74, 0x75, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x6c, 0x61, 0x63, 0x6b, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x66, 0x74, 0x79, 0x20, 0x72,
+ 0x69, 0x67, 0x68, 0x74, 0x65, 0x6f, 0x75, 0x73, 0x3a, 0x20, 0x77, 0x69,
+ 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x64, 0x65, 0x73, 0x74,
+ 0x72, 0x6f, 0x79, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x63, 0x69, 0x74, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6c, 0x61, 0x63,
+ 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x69, 0x76, 0x65, 0x3f, 0x20, 0x41,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20,
+ 0x49, 0x66, 0x20, 0x49, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x72, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x79, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x66, 0x69, 0x76, 0x65, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69,
+ 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72,
+ 0x6f, 0x79, 0x20, 0x69, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x70, 0x61, 0x6b, 0x65, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x79, 0x65, 0x74, 0x20, 0x61, 0x67,
+ 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x50, 0x65, 0x72, 0x61, 0x64, 0x76, 0x65, 0x6e, 0x74,
+ 0x75, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x79,
+ 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65,
+ 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6e, 0x6f,
+ 0x74, 0x20, 0x64, 0x6f, 0x20, 0x69, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x66, 0x6f, 0x72, 0x74, 0x79, 0x27, 0x73, 0x20, 0x73, 0x61, 0x6b, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c,
+ 0x20, 0x4f, 0x68, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x62, 0x65, 0x20,
+ 0x61, 0x6e, 0x67, 0x72, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49,
+ 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x73, 0x70, 0x65, 0x61, 0x6b, 0x3a,
+ 0x20, 0x50, 0x65, 0x72, 0x61, 0x64, 0x76, 0x65, 0x6e, 0x74, 0x75, 0x72,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79, 0x20, 0x62, 0x65, 0x20,
+ 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x2e,
+ 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74,
+ 0x20, 0x64, 0x6f, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x49,
+ 0x20, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65,
+ 0x68, 0x6f, 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x77, 0x2c, 0x20, 0x49, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x75,
+ 0x70, 0x6f, 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x70,
+ 0x65, 0x61, 0x6b, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x3a, 0x20, 0x50, 0x65, 0x72, 0x61, 0x64,
+ 0x76, 0x65, 0x6e, 0x74, 0x75, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x72,
+ 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x74,
+ 0x77, 0x65, 0x6e, 0x74, 0x79, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69,
+ 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72,
+ 0x6f, 0x79, 0x20, 0x69, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x77,
+ 0x65, 0x6e, 0x74, 0x79, 0x27, 0x73, 0x20, 0x73, 0x61, 0x6b, 0x65, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x4f, 0x68, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x6e, 0x6f,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x62,
+ 0x65, 0x20, 0x61, 0x6e, 0x67, 0x72, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x73, 0x70, 0x65, 0x61,
+ 0x6b, 0x20, 0x79, 0x65, 0x74, 0x20, 0x62, 0x75, 0x74, 0x20, 0x74, 0x68,
+ 0x69, 0x73, 0x20, 0x6f, 0x6e, 0x63, 0x65, 0x3a, 0x20, 0x50, 0x65, 0x72,
+ 0x61, 0x64, 0x76, 0x65, 0x6e, 0x74, 0x75, 0x72, 0x65, 0x20, 0x74, 0x65,
+ 0x6e, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x66,
+ 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x2e, 0x20,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x20, 0x69, 0x74, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x74, 0x65, 0x6e, 0x27, 0x73, 0x20, 0x73, 0x61, 0x6b,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x61, 0x79, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x73, 0x6f,
+ 0x6f, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64,
+ 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e,
+ 0x69, 0x6e, 0x67, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x68, 0x61, 0x6d, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
+ 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74,
+ 0x77, 0x6f, 0x20, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x73, 0x20, 0x74, 0x6f,
+ 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x20, 0x61, 0x74, 0x20, 0x65, 0x76,
+ 0x65, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x6f, 0x74, 0x20,
+ 0x73, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67,
+ 0x61, 0x74, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x73, 0x65,
+ 0x65, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x72, 0x6f,
+ 0x73, 0x65, 0x20, 0x75, 0x70, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x65,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x62, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d,
+ 0x73, 0x65, 0x6c, 0x66, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x74, 0x6f, 0x77, 0x61, 0x72,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x3b, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x20, 0x6e,
+ 0x6f, 0x77, 0x2c, 0x20, 0x6d, 0x79, 0x20, 0x6c, 0x6f, 0x72, 0x64, 0x73,
+ 0x2c, 0x20, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x69, 0x6e, 0x2c, 0x20, 0x49,
+ 0x20, 0x70, 0x72, 0x61, 0x79, 0x20, 0x79, 0x6f, 0x75, 0x2c, 0x20, 0x69,
+ 0x6e, 0x74, 0x6f, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x65, 0x72,
+ 0x76, 0x61, 0x6e, 0x74, 0x27, 0x73, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x61, 0x72, 0x72, 0x79, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x77, 0x61, 0x73, 0x68, 0x20, 0x79, 0x6f, 0x75, 0x72,
+ 0x20, 0x66, 0x65, 0x65, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79,
+ 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x72, 0x69, 0x73, 0x65,
+ 0x20, 0x75, 0x70, 0x20, 0x65, 0x61, 0x72, 0x6c, 0x79, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x67, 0x6f, 0x20, 0x6f, 0x6e, 0x20, 0x79, 0x6f, 0x75,
+ 0x72, 0x20, 0x77, 0x61, 0x79, 0x73, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4e,
+ 0x61, 0x79, 0x3b, 0x20, 0x62, 0x75, 0x74, 0x20, 0x77, 0x65, 0x20, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x61, 0x62, 0x69, 0x64, 0x65, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x72, 0x65, 0x65, 0x74, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x70, 0x72, 0x65, 0x73, 0x73,
+ 0x65, 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x6c, 0x79, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x74, 0x75, 0x72, 0x6e, 0x65,
+ 0x64, 0x20, 0x69, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6e, 0x74, 0x65, 0x72,
+ 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x68, 0x6f, 0x75, 0x73, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20,
+ 0x61, 0x20, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x64, 0x69, 0x64, 0x20, 0x62, 0x61, 0x6b, 0x65, 0x20, 0x75, 0x6e,
+ 0x6c, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x72, 0x65,
+ 0x61, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x64, 0x69, 0x64, 0x20, 0x65, 0x61, 0x74, 0x2e, 0x20, 0x0a, 0x42,
+ 0x75, 0x74, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x6c, 0x61, 0x79, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x63, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x65, 0x76,
+ 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x6f,
+ 0x66, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x2c, 0x20, 0x63, 0x6f, 0x6d,
+ 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68,
+ 0x6f, 0x75, 0x73, 0x65, 0x20, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2c, 0x20,
+ 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6f, 0x6c, 0x64, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x79, 0x6f, 0x75, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x20, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x71, 0x75,
+ 0x61, 0x72, 0x74, 0x65, 0x72, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4c, 0x6f, 0x74, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x57, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61,
+ 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x74, 0x68, 0x69,
+ 0x73, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x3f, 0x20, 0x62, 0x72, 0x69,
+ 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x6f, 0x75, 0x74, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x75, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x6b, 0x6e, 0x6f,
+ 0x77, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x75,
+ 0x74, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x6f, 0x6f,
+ 0x72, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x75, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x6f, 0x6f, 0x72, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72, 0x61, 0x79, 0x20,
+ 0x79, 0x6f, 0x75, 0x2c, 0x20, 0x62, 0x72, 0x65, 0x74, 0x68, 0x72, 0x65,
+ 0x6e, 0x2c, 0x20, 0x64, 0x6f, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x6f,
+ 0x20, 0x77, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x6c, 0x79, 0x2e, 0x20, 0x0a,
+ 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x77, 0x2c, 0x20,
+ 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x64,
+ 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x6d, 0x61, 0x6e, 0x3b, 0x20, 0x6c,
+ 0x65, 0x74, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72, 0x61,
+ 0x79, 0x20, 0x79, 0x6f, 0x75, 0x2c, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x79, 0x6f, 0x75, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x64, 0x6f, 0x20, 0x79, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x6d, 0x20, 0x61, 0x73, 0x20, 0x69, 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64,
+ 0x20, 0x69, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x65, 0x79, 0x65,
+ 0x73, 0x3a, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x64,
+ 0x6f, 0x20, 0x6e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x3b, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65,
+ 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x75,
+ 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x68, 0x61,
+ 0x64, 0x6f, 0x77, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x72, 0x6f,
+ 0x6f, 0x66, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x79, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x53, 0x74, 0x61, 0x6e,
+ 0x64, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x61, 0x67,
+ 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x6e,
+ 0x65, 0x20, 0x66, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x63, 0x61, 0x6d,
+ 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x6f, 0x6a, 0x6f,
+ 0x75, 0x72, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x20, 0x62,
+ 0x65, 0x20, 0x61, 0x20, 0x6a, 0x75, 0x64, 0x67, 0x65, 0x3a, 0x20, 0x6e,
+ 0x6f, 0x77, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x77, 0x65, 0x20, 0x64,
+ 0x65, 0x61, 0x6c, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x65, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x61,
+ 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2e,
+ 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x70, 0x72,
+ 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x73, 0x6f, 0x72, 0x65, 0x20, 0x75,
+ 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x2c,
+ 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x4c, 0x6f, 0x74, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x6e, 0x65, 0x61, 0x72,
+ 0x20, 0x74, 0x6f, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x6f, 0x6f, 0x72, 0x2e, 0x20, 0x0a, 0x42, 0x75, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x70, 0x75, 0x74,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72,
+ 0x20, 0x68, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70,
+ 0x75, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x69, 0x6e,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65,
+ 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x68, 0x75, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x6f, 0x6f, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x6d, 0x6f, 0x74, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x64, 0x6f, 0x6f, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x62, 0x6c, 0x69, 0x6e, 0x64, 0x6e, 0x65, 0x73, 0x73, 0x2c, 0x20, 0x62,
+ 0x6f, 0x74, 0x68, 0x20, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x3a, 0x20, 0x73, 0x6f, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x65,
+ 0x61, 0x72, 0x69, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x73, 0x65,
+ 0x6c, 0x76, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x69, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x6f, 0x6f, 0x72, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4c, 0x6f,
+ 0x74, 0x2c, 0x20, 0x48, 0x61, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x62, 0x65,
+ 0x73, 0x69, 0x64, 0x65, 0x73, 0x3f, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x69,
+ 0x6e, 0x20, 0x6c, 0x61, 0x77, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65,
+ 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x61, 0x74,
+ 0x73, 0x6f, 0x65, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x68, 0x61, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x63, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x69, 0x73, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x3a, 0x20,
+ 0x0a, 0x46, 0x6f, 0x72, 0x20, 0x77, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x20, 0x74, 0x68, 0x69,
+ 0x73, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c, 0x20, 0x62, 0x65, 0x63,
+ 0x61, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x72, 0x79,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x69, 0x73, 0x20,
+ 0x77, 0x61, 0x78, 0x65, 0x6e, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20,
+ 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x73,
+ 0x65, 0x6e, 0x74, 0x20, 0x75, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x65,
+ 0x73, 0x74, 0x72, 0x6f, 0x79, 0x20, 0x69, 0x74, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20,
+ 0x6f, 0x75, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x70, 0x61,
+ 0x6b, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x61, 0x77, 0x2c,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x6d, 0x61, 0x72, 0x72, 0x69,
+ 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68,
+ 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x2c, 0x20, 0x55, 0x70, 0x2c, 0x20, 0x67, 0x65, 0x74, 0x20,
+ 0x79, 0x6f, 0x75, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x69, 0x73, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x3b, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79,
+ 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x63, 0x69, 0x74, 0x79, 0x2e, 0x20,
+ 0x42, 0x75, 0x74, 0x20, 0x68, 0x65, 0x20, 0x73, 0x65, 0x65, 0x6d, 0x65,
+ 0x64, 0x20, 0x61, 0x73, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x6d, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x69,
+ 0x6e, 0x20, 0x6c, 0x61, 0x77, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72,
+ 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x72, 0x6f, 0x73, 0x65, 0x2c, 0x20,
+ 0x74, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6e, 0x67,
+ 0x65, 0x6c, 0x73, 0x20, 0x68, 0x61, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x64,
+ 0x20, 0x4c, 0x6f, 0x74, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67,
+ 0x2c, 0x20, 0x41, 0x72, 0x69, 0x73, 0x65, 0x2c, 0x20, 0x74, 0x61, 0x6b,
+ 0x65, 0x20, 0x74, 0x68, 0x79, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x79, 0x20, 0x74, 0x77, 0x6f, 0x20,
+ 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, 0x72, 0x65, 0x20, 0x68, 0x65, 0x72,
+ 0x65, 0x3b, 0x20, 0x6c, 0x65, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x62, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x69, 0x71,
+ 0x75, 0x69, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x63, 0x69, 0x74, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x77,
+ 0x68, 0x69, 0x6c, 0x65, 0x20, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x6e, 0x67,
+ 0x65, 0x72, 0x65, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65,
+ 0x6e, 0x20, 0x6c, 0x61, 0x69, 0x64, 0x20, 0x68, 0x6f, 0x6c, 0x64, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x61, 0x6e,
+ 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x74,
+ 0x77, 0x6f, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73,
+ 0x3b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x62,
+ 0x65, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x65, 0x72, 0x63, 0x69, 0x66, 0x75,
+ 0x6c, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x62, 0x72, 0x6f,
+ 0x75, 0x67, 0x68, 0x74, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x66, 0x6f, 0x72,
+ 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x74, 0x20,
+ 0x68, 0x69, 0x6d, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x63, 0x69, 0x74, 0x79, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74,
+ 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x68, 0x61, 0x64, 0x20, 0x62, 0x72,
+ 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x66,
+ 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x2c,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x3b, 0x20,
+ 0x6c, 0x6f, 0x6f, 0x6b, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x68,
+ 0x69, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x6e, 0x65,
+ 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x74, 0x61, 0x79, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x3b, 0x20, 0x65, 0x73,
+ 0x63, 0x61, 0x70, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x6c, 0x65,
+ 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x62, 0x65, 0x20, 0x63,
+ 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x4f, 0x68,
+ 0x2c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x6f, 0x2c, 0x20, 0x6d, 0x79,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x3a, 0x20, 0x0a, 0x42, 0x65, 0x68, 0x6f,
+ 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x77, 0x2c, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x20, 0x68, 0x61, 0x74, 0x68,
+ 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x67, 0x72, 0x61, 0x63, 0x65,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x69, 0x67, 0x68,
+ 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x68, 0x61, 0x73, 0x74, 0x20, 0x6d, 0x61, 0x67, 0x6e, 0x69, 0x66, 0x69,
+ 0x65, 0x64, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6d, 0x65, 0x72, 0x63, 0x79,
+ 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x73, 0x68, 0x65, 0x77, 0x65, 0x64,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20,
+ 0x73, 0x61, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x79, 0x20, 0x6c, 0x69,
+ 0x66, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x63, 0x61,
+ 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
+ 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x6c, 0x65, 0x73, 0x74, 0x20, 0x73, 0x6f,
+ 0x6d, 0x65, 0x20, 0x65, 0x76, 0x69, 0x6c, 0x20, 0x74, 0x61, 0x6b, 0x65,
+ 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x64,
+ 0x69, 0x65, 0x3a, 0x20, 0x0a, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x20,
+ 0x6e, 0x6f, 0x77, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x63, 0x69,
+ 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x65, 0x61, 0x72, 0x20, 0x74,
+ 0x6f, 0x20, 0x66, 0x6c, 0x65, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x61,
+ 0x20, 0x6c, 0x69, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x3a,
+ 0x20, 0x4f, 0x68, 0x2c, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x6d, 0x65, 0x20,
+ 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x20, 0x74, 0x68, 0x69, 0x74, 0x68,
+ 0x65, 0x72, 0x2c, 0x20, 0x28, 0x69, 0x73, 0x20, 0x69, 0x74, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x61, 0x20, 0x6c, 0x69, 0x74, 0x74, 0x6c, 0x65, 0x20,
+ 0x6f, 0x6e, 0x65, 0x3f, 0x29, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x79,
+ 0x20, 0x73, 0x6f, 0x75, 0x6c, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x6c, 0x69, 0x76, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x53, 0x65, 0x65, 0x2c, 0x20, 0x49, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65,
+ 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x74,
+ 0x68, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x2c, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x74, 0x68, 0x72, 0x6f, 0x77,
+ 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x63, 0x69, 0x74, 0x79, 0x2c, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x69, 0x63,
+ 0x68, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20,
+ 0x73, 0x70, 0x6f, 0x6b, 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x48, 0x61, 0x73,
+ 0x74, 0x65, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x65, 0x73, 0x63,
+ 0x61, 0x70, 0x65, 0x20, 0x74, 0x68, 0x69, 0x74, 0x68, 0x65, 0x72, 0x3b,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x49, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
+ 0x74, 0x20, 0x64, 0x6f, 0x20, 0x61, 0x6e, 0x79, 0x74, 0x68, 0x69, 0x6e,
+ 0x67, 0x20, 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x62, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x68, 0x69, 0x74,
+ 0x68, 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f,
+ 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x69, 0x74, 0x79, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x5a,
+ 0x6f, 0x61, 0x72, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x73, 0x75,
+ 0x6e, 0x20, 0x77, 0x61, 0x73, 0x20, 0x72, 0x69, 0x73, 0x65, 0x6e, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x4c, 0x6f, 0x74, 0x20,
+ 0x65, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f,
+ 0x20, 0x5a, 0x6f, 0x61, 0x72, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x72, 0x61,
+ 0x69, 0x6e, 0x65, 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x53, 0x6f,
+ 0x64, 0x6f, 0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e,
+ 0x20, 0x47, 0x6f, 0x6d, 0x6f, 0x72, 0x72, 0x61, 0x68, 0x20, 0x62, 0x72,
+ 0x69, 0x6d, 0x73, 0x74, 0x6f, 0x6e, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x66, 0x69, 0x72, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x3b, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x74, 0x68,
+ 0x72, 0x65, 0x77, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x63, 0x69,
+ 0x74, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x69, 0x6e, 0x68, 0x61, 0x62, 0x69, 0x74, 0x61, 0x6e, 0x74, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x69, 0x74, 0x69,
+ 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x67, 0x72, 0x65, 0x77, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2e, 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x65,
+ 0x64, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x62, 0x65, 0x68, 0x69, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x62, 0x65, 0x63, 0x61,
+ 0x6d, 0x65, 0x20, 0x61, 0x20, 0x70, 0x69, 0x6c, 0x6c, 0x61, 0x72, 0x20,
+ 0x6f, 0x66, 0x20, 0x73, 0x61, 0x6c, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x67, 0x61,
+ 0x74, 0x20, 0x75, 0x70, 0x20, 0x65, 0x61, 0x72, 0x6c, 0x79, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61,
+ 0x63, 0x65, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x68, 0x65, 0x20,
+ 0x73, 0x74, 0x6f, 0x6f, 0x64, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x3a, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x65,
+ 0x64, 0x20, 0x74, 0x6f, 0x77, 0x61, 0x72, 0x64, 0x20, 0x53, 0x6f, 0x64,
+ 0x6f, 0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x6d, 0x6f, 0x72,
+ 0x72, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x77,
+ 0x61, 0x72, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x68, 0x65, 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20,
+ 0x6c, 0x6f, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6d, 0x6f, 0x6b,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x75,
+ 0x6e, 0x74, 0x72, 0x79, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x70,
+ 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6d, 0x6f, 0x6b,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x66, 0x75, 0x72, 0x6e, 0x61,
+ 0x63, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20,
+ 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73,
+ 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x64,
+ 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x63, 0x69, 0x74, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x72, 0x65, 0x6d, 0x65, 0x6d,
+ 0x62, 0x65, 0x72, 0x65, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20,
+ 0x4c, 0x6f, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6d, 0x69, 0x64, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x74, 0x68, 0x72, 0x6f,
+ 0x77, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x68, 0x65, 0x20, 0x6f,
+ 0x76, 0x65, 0x72, 0x74, 0x68, 0x72, 0x65, 0x77, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x63, 0x69, 0x74, 0x69, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x4c, 0x6f, 0x74,
+ 0x20, 0x64, 0x77, 0x65, 0x6c, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x70,
+ 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x5a, 0x6f, 0x61, 0x72,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x74, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
+ 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x74, 0x77, 0x6f, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65,
+ 0x72, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x3b,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68, 0x65, 0x20, 0x66, 0x65, 0x61, 0x72,
+ 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x20,
+ 0x69, 0x6e, 0x20, 0x5a, 0x6f, 0x61, 0x72, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x74, 0x20, 0x69, 0x6e,
+ 0x20, 0x61, 0x20, 0x63, 0x61, 0x76, 0x65, 0x2c, 0x20, 0x68, 0x65, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x74, 0x77, 0x6f, 0x20,
+ 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73,
+ 0x74, 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x79, 0x6f, 0x75, 0x6e,
+ 0x67, 0x65, 0x72, 0x2c, 0x20, 0x4f, 0x75, 0x72, 0x20, 0x66, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20,
+ 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x75, 0x73, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x20,
+ 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20, 0x0a, 0x43, 0x6f, 0x6d, 0x65, 0x2c,
+ 0x20, 0x6c, 0x65, 0x74, 0x20, 0x75, 0x73, 0x20, 0x6d, 0x61, 0x6b, 0x65,
+ 0x20, 0x6f, 0x75, 0x72, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x64, 0x72, 0x69, 0x6e, 0x6b, 0x20, 0x77, 0x69, 0x6e, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x6c, 0x69, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x20, 0x6d, 0x61,
+ 0x79, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x20, 0x73,
+ 0x65, 0x65, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x6f, 0x75, 0x72, 0x20, 0x66,
+ 0x61, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x69, 0x72, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x64,
+ 0x72, 0x69, 0x6e, 0x6b, 0x20, 0x77, 0x69, 0x6e, 0x65, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x62,
+ 0x6f, 0x72, 0x6e, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x61, 0x79, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x68, 0x65, 0x72, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x70, 0x65, 0x72,
+ 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x77,
+ 0x68, 0x65, 0x6e, 0x20, 0x73, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x79, 0x20,
+ 0x64, 0x6f, 0x77, 0x6e, 0x2c, 0x20, 0x6e, 0x6f, 0x72, 0x20, 0x77, 0x68,
+ 0x65, 0x6e, 0x20, 0x73, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6f, 0x73, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61,
+ 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x20, 0x6f,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x72, 0x6f, 0x77,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x69, 0x72, 0x73, 0x74, 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x79,
+ 0x6f, 0x75, 0x6e, 0x67, 0x65, 0x72, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f,
+ 0x6c, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x6c, 0x61, 0x79, 0x20, 0x79, 0x65,
+ 0x73, 0x74, 0x65, 0x72, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x6d, 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72,
+ 0x3a, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x75, 0x73, 0x20, 0x6d, 0x61, 0x6b,
+ 0x65, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x64, 0x72, 0x69, 0x6e, 0x6b, 0x20,
+ 0x77, 0x69, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x67, 0x6f, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x69, 0x6e,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x69, 0x65, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x70, 0x72, 0x65, 0x73,
+ 0x65, 0x72, 0x76, 0x65, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x6f, 0x75, 0x72, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x6d,
+ 0x61, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x66, 0x61,
+ 0x74, 0x68, 0x65, 0x72, 0x20, 0x64, 0x72, 0x69, 0x6e, 0x6b, 0x20, 0x77,
+ 0x69, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6e, 0x69, 0x67,
+ 0x68, 0x74, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x79, 0x6f, 0x75, 0x6e, 0x67, 0x65, 0x72,
+ 0x20, 0x61, 0x72, 0x6f, 0x73, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6c, 0x61, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x70, 0x65, 0x72,
+ 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x77,
+ 0x68, 0x65, 0x6e, 0x20, 0x73, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x79, 0x20,
+ 0x64, 0x6f, 0x77, 0x6e, 0x2c, 0x20, 0x6e, 0x6f, 0x72, 0x20, 0x77, 0x68,
+ 0x65, 0x6e, 0x20, 0x73, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6f, 0x73, 0x65,
+ 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x75, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61,
+ 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4c,
+ 0x6f, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x63, 0x68, 0x69, 0x6c,
+ 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x66,
+ 0x61, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x62, 0x6f,
+ 0x72, 0x6e, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20, 0x61, 0x20, 0x73, 0x6f,
+ 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x4d,
+ 0x6f, 0x61, 0x62, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d,
+ 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4d,
+ 0x6f, 0x61, 0x62, 0x69, 0x74, 0x65, 0x73, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x79, 0x6f, 0x75, 0x6e,
+ 0x67, 0x65, 0x72, 0x2c, 0x20, 0x73, 0x68, 0x65, 0x20, 0x61, 0x6c, 0x73,
+ 0x6f, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x42, 0x65,
+ 0x6e, 0x61, 0x6d, 0x6d, 0x69, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x6d, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20, 0x6f, 0x66,
+ 0x20, 0x41, 0x6d, 0x6d, 0x6f, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x69, 0x73, 0x20, 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x6a,
+ 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x74, 0x6f, 0x77,
+ 0x61, 0x72, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x75, 0x74,
+ 0x68, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x62,
+ 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x4b, 0x61, 0x64, 0x65, 0x73,
+ 0x68, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x68, 0x75, 0x72, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x6f, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x65,
+ 0x64, 0x20, 0x69, 0x6e, 0x20, 0x47, 0x65, 0x72, 0x61, 0x72, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x61, 0x72,
+ 0x61, 0x68, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c,
+ 0x20, 0x53, 0x68, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x79, 0x20, 0x73,
+ 0x69, 0x73, 0x74, 0x65, 0x72, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41,
+ 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68, 0x20, 0x6b, 0x69, 0x6e,
+ 0x67, 0x20, 0x6f, 0x66, 0x20, 0x47, 0x65, 0x72, 0x61, 0x72, 0x20, 0x73,
+ 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x6f,
+ 0x6b, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x2e, 0x20, 0x0a, 0x42, 0x75,
+ 0x74, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74,
+ 0x6f, 0x20, 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68, 0x20,
+ 0x69, 0x6e, 0x20, 0x61, 0x20, 0x64, 0x72, 0x65, 0x61, 0x6d, 0x20, 0x62,
+ 0x79, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d,
+ 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x61, 0x72, 0x74, 0x20, 0x62, 0x75, 0x74, 0x20, 0x61,
+ 0x20, 0x64, 0x65, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x68, 0x61, 0x73, 0x74, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x3b, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x73, 0x68, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61,
+ 0x20, 0x6d, 0x61, 0x6e, 0x27, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2e,
+ 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c,
+ 0x65, 0x63, 0x68, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x6e, 0x65, 0x61, 0x72, 0x20, 0x68, 0x65,
+ 0x72, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2c, 0x20, 0x77, 0x69,
+ 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x6c, 0x61, 0x79,
+ 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x61, 0x20, 0x72, 0x69, 0x67, 0x68,
+ 0x74, 0x65, 0x6f, 0x75, 0x73, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x3f, 0x20, 0x0a, 0x53, 0x61, 0x69, 0x64, 0x20, 0x68, 0x65, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x2c, 0x20,
+ 0x53, 0x68, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x69,
+ 0x73, 0x74, 0x65, 0x72, 0x3f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68,
+ 0x65, 0x2c, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x73, 0x68, 0x65, 0x20,
+ 0x68, 0x65, 0x72, 0x73, 0x65, 0x6c, 0x66, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x48, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x79, 0x20, 0x62,
+ 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x3a, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x69, 0x74, 0x79,
+ 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x68, 0x65, 0x61, 0x72, 0x74,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x6e, 0x6f, 0x63, 0x65, 0x6e,
+ 0x63, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x68, 0x61, 0x6e,
+ 0x64, 0x73, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x49, 0x20, 0x64, 0x6f,
+ 0x6e, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x61,
+ 0x20, 0x64, 0x72, 0x65, 0x61, 0x6d, 0x2c, 0x20, 0x59, 0x65, 0x61, 0x2c,
+ 0x20, 0x49, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x64, 0x69, 0x64, 0x73, 0x74, 0x20,
+ 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x69, 0x74, 0x79, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x68, 0x65, 0x61, 0x72, 0x74, 0x3b, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x49, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x68, 0x65, 0x6c, 0x64, 0x20, 0x74, 0x68, 0x65, 0x65,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x73, 0x69, 0x6e, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x73, 0x74, 0x20, 0x6d, 0x65,
+ 0x3a, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20,
+ 0x73, 0x75, 0x66, 0x66, 0x65, 0x72, 0x65, 0x64, 0x20, 0x49, 0x20, 0x74,
+ 0x68, 0x65, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74,
+ 0x6f, 0x75, 0x63, 0x68, 0x20, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x4e,
+ 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65,
+ 0x20, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66,
+ 0x65, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68, 0x65, 0x20, 0x69, 0x73,
+ 0x20, 0x61, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x68, 0x65, 0x74, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c,
+ 0x20, 0x70, 0x72, 0x61, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x68, 0x65, 0x72,
+ 0x20, 0x6e, 0x6f, 0x74, 0x2c, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x73, 0x75, 0x72, 0x65,
+ 0x6c, 0x79, 0x20, 0x64, 0x69, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x65,
+ 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65,
+ 0x20, 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68, 0x20, 0x72,
+ 0x6f, 0x73, 0x65, 0x20, 0x65, 0x61, 0x72, 0x6c, 0x79, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e, 0x67,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x65, 0x72,
+ 0x76, 0x61, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x6f, 0x6c, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x73,
+ 0x65, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x65, 0x61, 0x72, 0x73, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20,
+ 0x77, 0x65, 0x72, 0x65, 0x20, 0x73, 0x6f, 0x72, 0x65, 0x20, 0x61, 0x66,
+ 0x72, 0x61, 0x69, 0x64, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x6e, 0x20,
+ 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68, 0x20, 0x63, 0x61,
+ 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x57, 0x68, 0x61,
+ 0x74, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x75, 0x73,
+ 0x3f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x68,
+ 0x61, 0x76, 0x65, 0x20, 0x49, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64,
+ 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20,
+ 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x6f, 0x6e, 0x20, 0x6d,
+ 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x6d, 0x79, 0x20,
+ 0x6b, 0x69, 0x6e, 0x67, 0x64, 0x6f, 0x6d, 0x20, 0x61, 0x20, 0x67, 0x72,
+ 0x65, 0x61, 0x74, 0x20, 0x73, 0x69, 0x6e, 0x3f, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x20,
+ 0x64, 0x65, 0x65, 0x64, 0x73, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d,
+ 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6f, 0x75, 0x67, 0x68, 0x74,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x64,
+ 0x6f, 0x6e, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62,
+ 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61,
+ 0x6d, 0x2c, 0x20, 0x57, 0x68, 0x61, 0x74, 0x20, 0x73, 0x61, 0x77, 0x65,
+ 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x2c, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20,
+ 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x74, 0x68,
+ 0x69, 0x6e, 0x67, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20,
+ 0x42, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x49, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x67, 0x68, 0x74, 0x2c, 0x20, 0x53, 0x75, 0x72, 0x65, 0x6c,
+ 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x65, 0x61, 0x72, 0x20, 0x6f,
+ 0x66, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x70, 0x6c, 0x61,
+ 0x63, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x73, 0x6c, 0x61, 0x79, 0x20, 0x6d,
+ 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x79, 0x20, 0x77, 0x69, 0x66,
+ 0x65, 0x27, 0x73, 0x20, 0x73, 0x61, 0x6b, 0x65, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x79, 0x65, 0x74, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x65,
+ 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x79, 0x20,
+ 0x73, 0x69, 0x73, 0x74, 0x65, 0x72, 0x3b, 0x20, 0x73, 0x68, 0x65, 0x20,
+ 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68,
+ 0x74, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x66, 0x61,
+ 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6e, 0x6f,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74,
+ 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x6d, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65,
+ 0x20, 0x62, 0x65, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x6d, 0x79, 0x20, 0x77,
+ 0x69, 0x66, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74,
+ 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73,
+ 0x73, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x63, 0x61, 0x75, 0x73, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x20, 0x74, 0x6f,
+ 0x20, 0x77, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x66, 0x72, 0x6f, 0x6d,
+ 0x20, 0x6d, 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73,
+ 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x49, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69,
+ 0x73, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x6e, 0x65,
+ 0x73, 0x73, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x73, 0x68, 0x65, 0x77,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x3b, 0x20, 0x61, 0x74,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65,
+ 0x20, 0x77, 0x68, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x65, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x2c, 0x20,
+ 0x73, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x48,
+ 0x65, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x79, 0x20, 0x62, 0x72, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62,
+ 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68, 0x20, 0x74, 0x6f, 0x6f, 0x6b,
+ 0x20, 0x73, 0x68, 0x65, 0x65, 0x70, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x78, 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x65,
+ 0x6e, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x77, 0x6f, 0x6d, 0x65, 0x6e, 0x73, 0x65, 0x72, 0x76,
+ 0x61, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x61,
+ 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x68,
+ 0x69, 0x6d, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x77, 0x69, 0x66, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20,
+ 0x6d, 0x79, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x73, 0x20, 0x62,
+ 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3a, 0x20,
+ 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20,
+ 0x69, 0x74, 0x20, 0x70, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x74, 0x68, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x68, 0x65,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x2c, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x67, 0x69,
+ 0x76, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x72, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x61, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x73, 0x61,
+ 0x6e, 0x64, 0x20, 0x70, 0x69, 0x65, 0x63, 0x65, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x73, 0x69, 0x6c, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x62, 0x65, 0x68,
+ 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x68, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x76,
+ 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x79, 0x65, 0x73, 0x2c, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6c, 0x6c,
+ 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x3a, 0x20, 0x74, 0x68, 0x75, 0x73,
+ 0x20, 0x73, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x72, 0x65, 0x70,
+ 0x72, 0x6f, 0x76, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x53, 0x6f, 0x20, 0x41,
+ 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x70, 0x72, 0x61, 0x79, 0x65,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x47, 0x6f, 0x64, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68, 0x65, 0x61, 0x6c,
+ 0x65, 0x64, 0x20, 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69,
+ 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6d, 0x61, 0x69, 0x64, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x62,
+ 0x61, 0x72, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e,
+ 0x2e, 0x20, 0x0a, 0x46, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x20, 0x68, 0x61, 0x64, 0x20, 0x66, 0x61, 0x73, 0x74,
+ 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x20, 0x75, 0x70, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x62, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x6f, 0x75, 0x73,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65,
+ 0x63, 0x68, 0x2c, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x68, 0x61, 0x6d, 0x27, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x20, 0x76, 0x69, 0x73, 0x69, 0x74, 0x65, 0x64, 0x20, 0x53,
+ 0x61, 0x72, 0x61, 0x68, 0x20, 0x61, 0x73, 0x20, 0x68, 0x65, 0x20, 0x68,
+ 0x61, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x64, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68,
+ 0x20, 0x61, 0x73, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x73,
+ 0x70, 0x6f, 0x6b, 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x46, 0x6f, 0x72, 0x20,
+ 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x69,
+ 0x76, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x61, 0x72,
+ 0x65, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x61, 0x20,
+ 0x73, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6f,
+ 0x6c, 0x64, 0x20, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x61, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x65, 0x74, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x73, 0x70, 0x6f, 0x6b, 0x65, 0x6e, 0x20,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6c,
+ 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x62, 0x6f, 0x72,
+ 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20,
+ 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x62,
+ 0x61, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20,
+ 0x49, 0x73, 0x61, 0x61, 0x63, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x63, 0x69, 0x72, 0x63,
+ 0x75, 0x6d, 0x63, 0x69, 0x73, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x73, 0x6f, 0x6e, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x62, 0x65,
+ 0x69, 0x6e, 0x67, 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x64, 0x61,
+ 0x79, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x68, 0x61, 0x64, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
+ 0x6e, 0x64, 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65,
+ 0x64, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x2c,
+ 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f,
+ 0x6e, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69,
+ 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x72, 0x61,
+ 0x68, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x68, 0x61, 0x74, 0x68, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x6d, 0x65,
+ 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x61, 0x75, 0x67, 0x68, 0x2c, 0x20, 0x73,
+ 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x61, 0x72, 0x20, 0x77, 0x69, 0x6c,
+ 0x6c, 0x20, 0x6c, 0x61, 0x75, 0x67, 0x68, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x6d, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x73, 0x68,
+ 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x57, 0x68, 0x6f, 0x20,
+ 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x53,
+ 0x61, 0x72, 0x61, 0x68, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x63,
+ 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20, 0x73, 0x75, 0x63, 0x6b,
+ 0x3f, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65,
+ 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61, 0x20,
+ 0x73, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6f,
+ 0x6c, 0x64, 0x20, 0x61, 0x67, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x67,
+ 0x72, 0x65, 0x77, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x77, 0x65, 0x61, 0x6e, 0x65, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x6d, 0x61, 0x64,
+ 0x65, 0x20, 0x61, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x66, 0x65,
+ 0x61, 0x73, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65,
+ 0x20, 0x64, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x73,
+ 0x61, 0x61, 0x63, 0x20, 0x77, 0x61, 0x73, 0x20, 0x77, 0x65, 0x61, 0x6e,
+ 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x72,
+ 0x61, 0x68, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x61, 0x67, 0x61, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x45, 0x67, 0x79, 0x70, 0x74, 0x69, 0x61, 0x6e,
+ 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x73, 0x68, 0x65, 0x20,
+ 0x68, 0x61, 0x64, 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x6d,
+ 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x20, 0x0a, 0x57, 0x68, 0x65,
+ 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x73, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x43, 0x61, 0x73, 0x74, 0x20, 0x6f,
+ 0x75, 0x74, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x62, 0x6f, 0x6e, 0x64,
+ 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x72, 0x20, 0x73, 0x6f, 0x6e, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x69, 0x73, 0x20, 0x62, 0x6f, 0x6e, 0x64, 0x77, 0x6f, 0x6d, 0x61, 0x6e,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62,
+ 0x65, 0x20, 0x68, 0x65, 0x69, 0x72, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x6d, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x65, 0x76, 0x65, 0x6e,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x68,
+ 0x69, 0x6e, 0x67, 0x20, 0x77, 0x61, 0x73, 0x20, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x67, 0x72, 0x69, 0x65, 0x76, 0x6f, 0x75, 0x73, 0x20, 0x69, 0x6e,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x27, 0x73, 0x20, 0x73,
+ 0x69, 0x67, 0x68, 0x74, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72, 0x61,
+ 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x69, 0x74, 0x20,
+ 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x67, 0x72, 0x69, 0x65, 0x76,
+ 0x6f, 0x75, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73,
+ 0x69, 0x67, 0x68, 0x74, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x64, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x6f, 0x6e, 0x64,
+ 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x3b, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68,
+ 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x68, 0x65,
+ 0x61, 0x72, 0x6b, 0x65, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68,
+ 0x65, 0x72, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x3b, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65,
+ 0x64, 0x20, 0x62, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x6e, 0x64, 0x77, 0x6f, 0x6d,
+ 0x61, 0x6e, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x49, 0x20, 0x6d, 0x61,
+ 0x6b, 0x65, 0x20, 0x61, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c,
+ 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x68, 0x65, 0x20,
+ 0x69, 0x73, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61,
+ 0x6d, 0x20, 0x72, 0x6f, 0x73, 0x65, 0x20, 0x75, 0x70, 0x20, 0x65, 0x61,
+ 0x72, 0x6c, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x6f, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x62, 0x72, 0x65, 0x61, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x62, 0x6f, 0x74, 0x74, 0x6c, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x67, 0x61, 0x76, 0x65, 0x20, 0x69, 0x74, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x48, 0x61, 0x67, 0x61, 0x72, 0x2c, 0x20, 0x70,
+ 0x75, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x74, 0x20, 0x6f, 0x6e,
+ 0x20, 0x68, 0x65, 0x72, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x65,
+ 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x68, 0x69, 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65,
+ 0x6e, 0x74, 0x20, 0x68, 0x65, 0x72, 0x20, 0x61, 0x77, 0x61, 0x79, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x64, 0x65, 0x70,
+ 0x61, 0x72, 0x74, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77,
+ 0x61, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x6e, 0x65, 0x73,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x42, 0x65, 0x65, 0x72, 0x73, 0x68, 0x65,
+ 0x62, 0x61, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73,
+ 0x70, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x62, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x68, 0x65, 0x20, 0x63, 0x61, 0x73, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72,
+ 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x68, 0x72, 0x75, 0x62, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x73, 0x68, 0x65, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x73, 0x61, 0x74, 0x20, 0x68, 0x65, 0x72, 0x20, 0x64,
+ 0x6f, 0x77, 0x6e, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x61, 0x67, 0x61,
+ 0x69, 0x6e, 0x73, 0x74, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61, 0x20, 0x67,
+ 0x6f, 0x6f, 0x64, 0x20, 0x77, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x66, 0x2c,
+ 0x20, 0x61, 0x73, 0x20, 0x69, 0x74, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x61, 0x20, 0x62, 0x6f, 0x77, 0x20, 0x73, 0x68, 0x6f, 0x74, 0x3a, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x73, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x6d, 0x65, 0x20, 0x6e, 0x6f, 0x74,
+ 0x20, 0x73, 0x65, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x61,
+ 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68,
+ 0x69, 0x6c, 0x64, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65,
+ 0x20, 0x73, 0x61, 0x74, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x61, 0x67,
+ 0x61, 0x69, 0x6e, 0x73, 0x74, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x6c, 0x69, 0x66, 0x74, 0x20, 0x75, 0x70, 0x20, 0x68,
+ 0x65, 0x72, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x77, 0x65, 0x70, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68, 0x65, 0x61, 0x72, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x64, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x20, 0x6f,
+ 0x66, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x48, 0x61, 0x67, 0x61, 0x72, 0x20, 0x6f, 0x75,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x57, 0x68, 0x61, 0x74,
+ 0x20, 0x61, 0x69, 0x6c, 0x65, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x65,
+ 0x2c, 0x20, 0x48, 0x61, 0x67, 0x61, 0x72, 0x3f, 0x20, 0x66, 0x65, 0x61,
+ 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x68, 0x65, 0x61, 0x72,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x64, 0x20, 0x77,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x68, 0x65, 0x20, 0x69, 0x73, 0x2e, 0x20,
+ 0x0a, 0x41, 0x72, 0x69, 0x73, 0x65, 0x2c, 0x20, 0x6c, 0x69, 0x66, 0x74,
+ 0x20, 0x75, 0x70, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x64, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x6f, 0x6c, 0x64, 0x20, 0x68, 0x69,
+ 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x65, 0x20, 0x68,
+ 0x61, 0x6e, 0x64, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x49, 0x20, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x68, 0x69, 0x6d,
+ 0x20, 0x61, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x6e, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x65, 0x64, 0x20, 0x68, 0x65, 0x72,
+ 0x20, 0x65, 0x79, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x77, 0x20, 0x61, 0x20, 0x77, 0x65, 0x6c,
+ 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x77, 0x65, 0x6e, 0x74,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x74, 0x74, 0x6c, 0x65, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x67, 0x61, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6c, 0x61, 0x64, 0x20, 0x64, 0x72, 0x69, 0x6e, 0x6b, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61,
+ 0x64, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x67, 0x72,
+ 0x65, 0x77, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x77, 0x65, 0x6c,
+ 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6c,
+ 0x64, 0x65, 0x72, 0x6e, 0x65, 0x73, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x62, 0x65, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61,
+ 0x72, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x74, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x6e, 0x65,
+ 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x50, 0x61, 0x72, 0x61, 0x6e, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x68, 0x69, 0x6d,
+ 0x20, 0x61, 0x20, 0x77, 0x69, 0x66, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x66, 0x20, 0x45, 0x67, 0x79, 0x70, 0x74, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74,
+ 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x50, 0x68, 0x69, 0x63, 0x68, 0x6f, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x69, 0x65, 0x66, 0x20, 0x63, 0x61,
+ 0x70, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x68, 0x6f, 0x73, 0x74, 0x20, 0x73, 0x70, 0x61, 0x6b, 0x65, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d,
+ 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x69, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x64, 0x6f, 0x65, 0x73,
+ 0x74, 0x3a, 0x20, 0x0a, 0x4e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65, 0x72,
+ 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x73, 0x77, 0x65, 0x61, 0x72, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x20, 0x68, 0x65, 0x72, 0x65,
+ 0x20, 0x62, 0x79, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x77, 0x69, 0x6c, 0x74, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x64, 0x65, 0x61, 0x6c, 0x20, 0x66, 0x61, 0x6c, 0x73,
+ 0x65, 0x6c, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x2c,
+ 0x20, 0x6e, 0x6f, 0x72, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x79,
+ 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x6e, 0x6f, 0x72, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x27, 0x73, 0x20,
+ 0x73, 0x6f, 0x6e, 0x3a, 0x20, 0x62, 0x75, 0x74, 0x20, 0x61, 0x63, 0x63,
+ 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x64,
+ 0x6f, 0x6e, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x65, 0x2c, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c,
+ 0x74, 0x20, 0x64, 0x6f, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20,
+ 0x73, 0x6f, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x73, 0x77, 0x65, 0x61, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x72, 0x65, 0x70,
+ 0x72, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c,
+ 0x65, 0x63, 0x68, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x61, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x6f, 0x66,
+ 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63,
+ 0x68, 0x20, 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68, 0x27,
+ 0x73, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73, 0x20, 0x68,
+ 0x61, 0x64, 0x20, 0x76, 0x69, 0x6f, 0x6c, 0x65, 0x6e, 0x74, 0x6c, 0x79,
+ 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x61, 0x77, 0x61, 0x79, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c,
+ 0x65, 0x63, 0x68, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x20,
+ 0x77, 0x6f, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x77, 0x68, 0x6f, 0x20,
+ 0x68, 0x61, 0x74, 0x68, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x68,
+ 0x69, 0x73, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x3b, 0x20, 0x6e, 0x65,
+ 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x64, 0x69, 0x64, 0x73, 0x74, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x74, 0x65, 0x6c, 0x6c, 0x20, 0x6d, 0x65,
+ 0x2c, 0x20, 0x6e, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x79, 0x65,
+ 0x74, 0x20, 0x68, 0x65, 0x61, 0x72, 0x64, 0x20, 0x49, 0x20, 0x6f, 0x66,
+ 0x20, 0x69, 0x74, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x74, 0x6f, 0x20,
+ 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x73,
+ 0x68, 0x65, 0x65, 0x70, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x78, 0x65,
+ 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x61, 0x76, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62,
+ 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x6d, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x76,
+ 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x73, 0x65, 0x74, 0x20,
+ 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x65, 0x77, 0x65, 0x20, 0x6c, 0x61,
+ 0x6d, 0x62, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x73, 0x65, 0x6c, 0x76, 0x65, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x57, 0x68, 0x61, 0x74, 0x20, 0x6d,
+ 0x65, 0x61, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x73, 0x65,
+ 0x76, 0x65, 0x6e, 0x20, 0x65, 0x77, 0x65, 0x20, 0x6c, 0x61, 0x6d, 0x62,
+ 0x73, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x73, 0x65, 0x74, 0x20, 0x62, 0x79,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x73, 0x65, 0x6c, 0x76, 0x65, 0x73, 0x3f,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65,
+ 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x65, 0x77, 0x65, 0x20, 0x6c,
+ 0x61, 0x6d, 0x62, 0x73, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x6d, 0x79, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62,
+ 0x65, 0x20, 0x61, 0x20, 0x77, 0x69, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x64, 0x69, 0x67,
+ 0x67, 0x65, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x77, 0x65, 0x6c,
+ 0x6c, 0x2e, 0x20, 0x0a, 0x57, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72,
+ 0x65, 0x20, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x42,
+ 0x65, 0x65, 0x72, 0x73, 0x68, 0x65, 0x62, 0x61, 0x3b, 0x20, 0x62, 0x65,
+ 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x77, 0x61, 0x72, 0x65, 0x20, 0x62,
+ 0x6f, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2e,
+ 0x20, 0x0a, 0x54, 0x68, 0x75, 0x73, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x6d, 0x61, 0x64, 0x65, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e,
+ 0x61, 0x6e, 0x74, 0x20, 0x61, 0x74, 0x20, 0x42, 0x65, 0x65, 0x72, 0x73,
+ 0x68, 0x65, 0x62, 0x61, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x41,
+ 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68, 0x20, 0x72, 0x6f, 0x73,
+ 0x65, 0x20, 0x75, 0x70, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x50, 0x68,
+ 0x69, 0x63, 0x68, 0x6f, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68,
+ 0x69, 0x65, 0x66, 0x20, 0x63, 0x61, 0x70, 0x74, 0x61, 0x69, 0x6e, 0x20,
+ 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x6f, 0x73, 0x74, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x72, 0x65,
+ 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x73, 0x74, 0x69,
+ 0x6e, 0x65, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x74, 0x65,
+ 0x64, 0x20, 0x61, 0x20, 0x67, 0x72, 0x6f, 0x76, 0x65, 0x20, 0x69, 0x6e,
+ 0x20, 0x42, 0x65, 0x65, 0x72, 0x73, 0x68, 0x65, 0x62, 0x61, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76,
+ 0x65, 0x72, 0x6c, 0x61, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x47, 0x6f,
+ 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61,
+ 0x68, 0x61, 0x6d, 0x20, 0x73, 0x6f, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x65,
+ 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x50, 0x68, 0x69,
+ 0x6c, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x65, 0x73, 0x27, 0x20, 0x6c, 0x61,
+ 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x6e, 0x79, 0x20, 0x64, 0x61, 0x79, 0x73,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61,
+ 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x20, 0x61,
+ 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x74,
+ 0x68, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x64, 0x69, 0x64, 0x20, 0x74, 0x65, 0x6d, 0x70,
+ 0x74, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61,
+ 0x6d, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x49, 0x20, 0x61, 0x6d, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x54, 0x61, 0x6b, 0x65, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x68,
+ 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x65,
+ 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x49, 0x73,
+ 0x61, 0x61, 0x63, 0x2c, 0x20, 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x73, 0x74, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x67, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20,
+ 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x4d, 0x6f, 0x72, 0x69, 0x61, 0x68, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x20, 0x68,
+ 0x69, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x61, 0x20, 0x62, 0x75, 0x72, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x66,
+ 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x6f,
+ 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f,
+ 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x77, 0x68, 0x69, 0x63,
+ 0x68, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x65, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20,
+ 0x72, 0x6f, 0x73, 0x65, 0x20, 0x75, 0x70, 0x20, 0x65, 0x61, 0x72, 0x6c,
+ 0x79, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72,
+ 0x6e, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61,
+ 0x64, 0x64, 0x6c, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x61, 0x73,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20,
+ 0x74, 0x77, 0x6f, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x79,
+ 0x6f, 0x75, 0x6e, 0x67, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49,
+ 0x73, 0x61, 0x61, 0x63, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6c, 0x61, 0x76, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x75, 0x72, 0x6e, 0x74, 0x20, 0x6f,
+ 0x66, 0x66, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x72, 0x6f, 0x73, 0x65, 0x20, 0x75, 0x70, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68,
+ 0x61, 0x64, 0x20, 0x74, 0x6f, 0x6c, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x2e,
+ 0x20, 0x0a, 0x54, 0x68, 0x65, 0x6e, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64, 0x20, 0x64, 0x61, 0x79, 0x20,
+ 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x6c, 0x69, 0x66, 0x74,
+ 0x65, 0x64, 0x20, 0x75, 0x70, 0x20, 0x68, 0x69, 0x73, 0x20, 0x65, 0x79,
+ 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x61, 0x66,
+ 0x61, 0x72, 0x20, 0x6f, 0x66, 0x66, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x79,
+ 0x6f, 0x75, 0x6e, 0x67, 0x20, 0x6d, 0x65, 0x6e, 0x2c, 0x20, 0x41, 0x62,
+ 0x69, 0x64, 0x65, 0x20, 0x79, 0x65, 0x20, 0x68, 0x65, 0x72, 0x65, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x73, 0x73,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x64, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x67, 0x6f, 0x20, 0x79, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x68, 0x69, 0x70, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x61, 0x67, 0x61,
+ 0x69, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x79, 0x6f, 0x75, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20,
+ 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6f,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x75, 0x72,
+ 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x61, 0x69, 0x64, 0x20, 0x69, 0x74,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x66, 0x69, 0x72, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x68, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61,
+ 0x20, 0x6b, 0x6e, 0x69, 0x66, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x62, 0x6f,
+ 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x74,
+ 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x73, 0x70, 0x61, 0x6b,
+ 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68,
+ 0x61, 0x6d, 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x4d, 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x48, 0x65, 0x72, 0x65, 0x20, 0x61, 0x6d, 0x20, 0x49, 0x2c, 0x20,
+ 0x6d, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x68,
+ 0x6f, 0x6c, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x65,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6f,
+ 0x64, 0x3a, 0x20, 0x62, 0x75, 0x74, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6d, 0x62,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x62, 0x75, 0x72, 0x6e, 0x74,
+ 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x3f, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4d, 0x79, 0x20, 0x73, 0x6f, 0x6e,
+ 0x2c, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x70,
+ 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x73, 0x65,
+ 0x6c, 0x66, 0x20, 0x61, 0x20, 0x6c, 0x61, 0x6d, 0x62, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x61, 0x20, 0x62, 0x75, 0x72, 0x6e, 0x74, 0x20, 0x6f, 0x66,
+ 0x66, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x73, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x62, 0x6f, 0x74,
+ 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x74, 0x6f,
+ 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20,
+ 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x74, 0x6f, 0x6c, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x6f,
+ 0x66, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68,
+ 0x61, 0x6d, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x20, 0x61, 0x6e, 0x20,
+ 0x61, 0x6c, 0x74, 0x61, 0x72, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x61, 0x69, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x6f, 0x6f, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x72,
+ 0x64, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x6f, 0x75,
+ 0x6e, 0x64, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x61,
+ 0x69, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x20, 0x75, 0x70, 0x6f, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20,
+ 0x73, 0x74, 0x72, 0x65, 0x74, 0x63, 0x68, 0x65, 0x64, 0x20, 0x66, 0x6f,
+ 0x72, 0x74, 0x68, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x61, 0x6e, 0x64,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6b, 0x6e, 0x69, 0x66, 0x65, 0x20, 0x74, 0x6f, 0x20,
+ 0x73, 0x6c, 0x61, 0x79, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61,
+ 0x6e, 0x67, 0x65, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x6f, 0x75, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68,
+ 0x61, 0x6d, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x48, 0x65, 0x72, 0x65, 0x20, 0x61, 0x6d,
+ 0x20, 0x49, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x61, 0x79, 0x20, 0x6e, 0x6f,
+ 0x74, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x61, 0x6e, 0x64,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61,
+ 0x64, 0x2c, 0x20, 0x6e, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x64,
+ 0x6f, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x74,
+ 0x68, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69,
+ 0x6d, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x49,
+ 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x66, 0x65, 0x61, 0x72, 0x65, 0x73, 0x74, 0x20,
+ 0x47, 0x6f, 0x64, 0x2c, 0x20, 0x73, 0x65, 0x65, 0x69, 0x6e, 0x67, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x6e, 0x6f,
+ 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x68, 0x65, 0x6c, 0x64, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x6e,
+ 0x65, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x6d, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x6c, 0x69, 0x66,
+ 0x74, 0x65, 0x64, 0x20, 0x75, 0x70, 0x20, 0x68, 0x69, 0x73, 0x20, 0x65,
+ 0x79, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x6f,
+ 0x6b, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x68,
+ 0x6f, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x68, 0x69, 0x6e, 0x64, 0x20, 0x68,
+ 0x69, 0x6d, 0x20, 0x61, 0x20, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x75,
+ 0x67, 0x68, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x74, 0x68, 0x69,
+ 0x63, 0x6b, 0x65, 0x74, 0x20, 0x62, 0x79, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x68, 0x6f, 0x72, 0x6e, 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41,
+ 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x72, 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66,
+ 0x66, 0x65, 0x72, 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x75, 0x70,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x62, 0x75, 0x72, 0x6e, 0x74,
+ 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x65, 0x61, 0x64, 0x20, 0x6f,
+ 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20,
+ 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e,
+ 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x4a, 0x65, 0x68, 0x6f, 0x76, 0x61,
+ 0x68, 0x6a, 0x69, 0x72, 0x65, 0x68, 0x3a, 0x20, 0x61, 0x73, 0x20, 0x69,
+ 0x74, 0x20, 0x69, 0x73, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x64, 0x61, 0x79, 0x2c, 0x20, 0x49,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20,
+ 0x69, 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20,
+ 0x73, 0x65, 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x63, 0x61, 0x6c,
+ 0x6c, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x68, 0x61, 0x6d, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20,
+ 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x2c, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42,
+ 0x79, 0x20, 0x6d, 0x79, 0x73, 0x65, 0x6c, 0x66, 0x20, 0x68, 0x61, 0x76,
+ 0x65, 0x20, 0x49, 0x20, 0x73, 0x77, 0x6f, 0x72, 0x6e, 0x2c, 0x20, 0x73,
+ 0x61, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75,
+ 0x73, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74,
+ 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x74,
+ 0x68, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x61,
+ 0x73, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x68,
+ 0x65, 0x6c, 0x64, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x2c,
+ 0x20, 0x74, 0x68, 0x69, 0x6e, 0x65, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20,
+ 0x73, 0x6f, 0x6e, 0x3a, 0x20, 0x0a, 0x54, 0x68, 0x61, 0x74, 0x20, 0x69,
+ 0x6e, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x49,
+ 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x6e,
+ 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x69, 0x6e, 0x67,
+ 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6d, 0x75, 0x6c, 0x74,
+ 0x69, 0x70, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65,
+ 0x64, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x61,
+ 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65,
+ 0x61, 0x76, 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68,
+ 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x61, 0x20, 0x73, 0x68, 0x6f, 0x72,
+ 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73,
+ 0x65, 0x65, 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x70, 0x6f,
+ 0x73, 0x73, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61,
+ 0x74, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x65, 0x6e,
+ 0x65, 0x6d, 0x69, 0x65, 0x73, 0x3b, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x62,
+ 0x65, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x3b, 0x20, 0x62,
+ 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x68, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x62, 0x65, 0x79, 0x65, 0x64, 0x20,
+ 0x6d, 0x79, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x2e, 0x20, 0x0a, 0x53,
+ 0x6f, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x72, 0x65,
+ 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x79, 0x6f, 0x75, 0x6e, 0x67, 0x20, 0x6d, 0x65,
+ 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x72, 0x6f, 0x73, 0x65, 0x20, 0x75, 0x70, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x77, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65,
+ 0x72, 0x20, 0x74, 0x6f, 0x20, 0x42, 0x65, 0x65, 0x72, 0x73, 0x68, 0x65,
+ 0x62, 0x61, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61,
+ 0x68, 0x61, 0x6d, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x74, 0x20, 0x61, 0x74,
+ 0x20, 0x42, 0x65, 0x65, 0x72, 0x73, 0x68, 0x65, 0x62, 0x61, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d, 0x65,
+ 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x20, 0x61, 0x66, 0x74,
+ 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x74, 0x68, 0x69,
+ 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x6f, 0x6c, 0x64, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e,
+ 0x67, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x4d,
+ 0x69, 0x6c, 0x63, 0x61, 0x68, 0x2c, 0x20, 0x73, 0x68, 0x65, 0x20, 0x68,
+ 0x61, 0x74, 0x68, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x62, 0x6f, 0x72,
+ 0x6e, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x72, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x4e, 0x61, 0x68, 0x6f, 0x72, 0x3b, 0x20, 0x0a,
+ 0x48, 0x75, 0x7a, 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x72, 0x73,
+ 0x74, 0x62, 0x6f, 0x72, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x42,
+ 0x75, 0x7a, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68,
+ 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4b, 0x65, 0x6d, 0x75,
+ 0x65, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x72, 0x61, 0x6d, 0x2c, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x43, 0x68, 0x65, 0x73, 0x65, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x48, 0x61, 0x7a, 0x6f, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x50, 0x69, 0x6c, 0x64, 0x61, 0x73, 0x68, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x4a, 0x69, 0x64, 0x6c, 0x61, 0x70, 0x68, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x42, 0x65, 0x74, 0x68, 0x75, 0x65, 0x6c, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x42, 0x65, 0x74, 0x68, 0x75, 0x65,
+ 0x6c, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x52, 0x65, 0x62, 0x65,
+ 0x6b, 0x61, 0x68, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x65,
+ 0x69, 0x67, 0x68, 0x74, 0x20, 0x4d, 0x69, 0x6c, 0x63, 0x61, 0x68, 0x20,
+ 0x64, 0x69, 0x64, 0x20, 0x62, 0x65, 0x61, 0x72, 0x20, 0x74, 0x6f, 0x20,
+ 0x4e, 0x61, 0x68, 0x6f, 0x72, 0x2c, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68,
+ 0x61, 0x6d, 0x27, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x63,
+ 0x6f, 0x6e, 0x63, 0x75, 0x62, 0x69, 0x6e, 0x65, 0x2c, 0x20, 0x77, 0x68,
+ 0x6f, 0x73, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x52, 0x65, 0x75, 0x6d, 0x61, 0x68, 0x2c, 0x20, 0x73, 0x68, 0x65,
+ 0x20, 0x62, 0x61, 0x72, 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x54,
+ 0x65, 0x62, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x61,
+ 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x54, 0x68, 0x61,
+ 0x68, 0x61, 0x73, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4d, 0x61,
+ 0x61, 0x63, 0x68, 0x61, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x6e,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x77, 0x65, 0x6e, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20,
+ 0x6f, 0x6c, 0x64, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x77,
+ 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x66,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x64,
+ 0x69, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x4b, 0x69, 0x72, 0x6a, 0x61,
+ 0x74, 0x68, 0x61, 0x72, 0x62, 0x61, 0x3b, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x73, 0x20, 0x48, 0x65, 0x62, 0x72,
+ 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61,
+ 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61,
+ 0x6d, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x6f,
+ 0x75, 0x72, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x53, 0x61, 0x72, 0x61,
+ 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x65,
+ 0x65, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68, 0x65, 0x72, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d,
+ 0x20, 0x73, 0x74, 0x6f, 0x6f, 0x64, 0x20, 0x75, 0x70, 0x20, 0x66, 0x72,
+ 0x6f, 0x6d, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x64, 0x65, 0x61, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x70, 0x61, 0x6b, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x48,
+ 0x65, 0x74, 0x68, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c,
+ 0x20, 0x0a, 0x49, 0x20, 0x61, 0x6d, 0x20, 0x61, 0x20, 0x73, 0x74, 0x72,
+ 0x61, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20,
+ 0x73, 0x6f, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x72, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x79, 0x6f, 0x75, 0x3a, 0x20, 0x67, 0x69, 0x76, 0x65,
+ 0x20, 0x6d, 0x65, 0x20, 0x61, 0x20, 0x70, 0x6f, 0x73, 0x73, 0x65, 0x73,
+ 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x62, 0x75,
+ 0x72, 0x79, 0x69, 0x6e, 0x67, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x79, 0x6f, 0x75, 0x2c, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x49, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x75, 0x72, 0x79,
+ 0x20, 0x6d, 0x79, 0x20, 0x64, 0x65, 0x61, 0x64, 0x20, 0x6f, 0x75, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x69, 0x67, 0x68, 0x74,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x48,
+ 0x65, 0x74, 0x68, 0x20, 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x65, 0x64,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x73, 0x61,
+ 0x79, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69,
+ 0x6d, 0x2c, 0x20, 0x0a, 0x48, 0x65, 0x61, 0x72, 0x20, 0x75, 0x73, 0x2c,
+ 0x20, 0x6d, 0x79, 0x20, 0x6c, 0x6f, 0x72, 0x64, 0x3a, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x61, 0x72, 0x74, 0x20, 0x61, 0x20, 0x6d, 0x69, 0x67,
+ 0x68, 0x74, 0x79, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x20, 0x61,
+ 0x6d, 0x6f, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x3a, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x65, 0x70, 0x75, 0x6c, 0x63,
+ 0x68, 0x72, 0x65, 0x73, 0x20, 0x62, 0x75, 0x72, 0x79, 0x20, 0x74, 0x68,
+ 0x79, 0x20, 0x64, 0x65, 0x61, 0x64, 0x3b, 0x20, 0x6e, 0x6f, 0x6e, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x75, 0x73, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x68, 0x6f, 0x6c, 0x64, 0x20, 0x66, 0x72,
+ 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x73, 0x65, 0x70, 0x75, 0x6c, 0x63, 0x68, 0x72, 0x65, 0x2c, 0x20, 0x62,
+ 0x75, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x6d, 0x61, 0x79, 0x65, 0x73, 0x74, 0x20, 0x62, 0x75, 0x72, 0x79,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x64, 0x65, 0x61, 0x64, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20,
+ 0x73, 0x74, 0x6f, 0x6f, 0x64, 0x20, 0x75, 0x70, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x62, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x73,
+ 0x65, 0x6c, 0x66, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70,
+ 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64,
+ 0x72, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x65, 0x74, 0x68, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d,
+ 0x6d, 0x75, 0x6e, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c,
+ 0x20, 0x49, 0x66, 0x20, 0x69, 0x74, 0x20, 0x62, 0x65, 0x20, 0x79, 0x6f,
+ 0x75, 0x72, 0x20, 0x6d, 0x69, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x49, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x75,
+ 0x72, 0x79, 0x20, 0x6d, 0x79, 0x20, 0x64, 0x65, 0x61, 0x64, 0x20, 0x6f,
+ 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x69, 0x67,
+ 0x68, 0x74, 0x3b, 0x20, 0x68, 0x65, 0x61, 0x72, 0x20, 0x6d, 0x65, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x65, 0x61, 0x74,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x45,
+ 0x70, 0x68, 0x72, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f,
+ 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x5a, 0x6f, 0x68, 0x61, 0x72, 0x2c, 0x20,
+ 0x0a, 0x54, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x79,
+ 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x6d, 0x65, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x63, 0x61, 0x76, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x4d, 0x61, 0x63,
+ 0x68, 0x70, 0x65, 0x6c, 0x61, 0x68, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63,
+ 0x68, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x74, 0x68, 0x2c, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x3b, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x61, 0x73, 0x20, 0x6d, 0x75, 0x63, 0x68, 0x20, 0x6d, 0x6f, 0x6e,
+ 0x65, 0x79, 0x20, 0x61, 0x73, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20,
+ 0x77, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x68, 0x65, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x69, 0x74, 0x20, 0x6d,
+ 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x70, 0x6f, 0x73, 0x73,
+ 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20,
+ 0x62, 0x75, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x70, 0x6c, 0x61, 0x63, 0x65,
+ 0x20, 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x73, 0x74, 0x20, 0x79, 0x6f, 0x75,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x70, 0x68, 0x72, 0x6f,
+ 0x6e, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x74, 0x20, 0x61, 0x6d, 0x6f, 0x6e,
+ 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72,
+ 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x65, 0x74, 0x68, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x45, 0x70, 0x68, 0x72, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x48, 0x69, 0x74, 0x74, 0x69, 0x74, 0x65, 0x20, 0x61,
+ 0x6e, 0x73, 0x77, 0x65, 0x72, 0x65, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61,
+ 0x68, 0x61, 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61,
+ 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20,
+ 0x6f, 0x66, 0x20, 0x48, 0x65, 0x74, 0x68, 0x2c, 0x20, 0x65, 0x76, 0x65,
+ 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x74, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x63, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x73,
+ 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x0a, 0x4e, 0x61, 0x79, 0x2c,
+ 0x20, 0x6d, 0x79, 0x20, 0x6c, 0x6f, 0x72, 0x64, 0x2c, 0x20, 0x68, 0x65,
+ 0x61, 0x72, 0x20, 0x6d, 0x65, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x69, 0x65, 0x6c, 0x64, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x49, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x63, 0x61, 0x76, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x2c, 0x20,
+ 0x49, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x69, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x3b, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70,
+ 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x6d,
+ 0x79, 0x20, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x20, 0x67, 0x69, 0x76,
+ 0x65, 0x20, 0x49, 0x20, 0x69, 0x74, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3a,
+ 0x20, 0x62, 0x75, 0x72, 0x79, 0x20, 0x74, 0x68, 0x79, 0x20, 0x64, 0x65,
+ 0x61, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x68, 0x61, 0x6d, 0x20, 0x62, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x64,
+ 0x6f, 0x77, 0x6e, 0x20, 0x68, 0x69, 0x6d, 0x73, 0x65, 0x6c, 0x66, 0x20,
+ 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70,
+ 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x70, 0x61, 0x6b, 0x65, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x45, 0x70, 0x68, 0x72, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x61, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x65, 0x6f, 0x70,
+ 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61,
+ 0x6e, 0x64, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20,
+ 0x42, 0x75, 0x74, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x77, 0x69, 0x6c, 0x74, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x69, 0x74,
+ 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72, 0x61, 0x79, 0x20, 0x74, 0x68, 0x65,
+ 0x65, 0x2c, 0x20, 0x68, 0x65, 0x61, 0x72, 0x20, 0x6d, 0x65, 0x3a, 0x20,
+ 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x20, 0x6d, 0x6f, 0x6e, 0x65, 0x79, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64,
+ 0x3b, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x69, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x75, 0x72, 0x79, 0x20, 0x6d, 0x79, 0x20,
+ 0x64, 0x65, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x70, 0x68, 0x72, 0x6f, 0x6e, 0x20,
+ 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x65, 0x64, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x0a,
+ 0x4d, 0x79, 0x20, 0x6c, 0x6f, 0x72, 0x64, 0x2c, 0x20, 0x68, 0x65, 0x61,
+ 0x72, 0x6b, 0x65, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x65,
+ 0x3a, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x69,
+ 0x73, 0x20, 0x77, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x66, 0x6f, 0x75, 0x72,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x73, 0x68, 0x65,
+ 0x6b, 0x65, 0x6c, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x69, 0x6c, 0x76,
+ 0x65, 0x72, 0x3b, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x62, 0x65, 0x74, 0x77, 0x69, 0x78, 0x74,
+ 0x20, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x65,
+ 0x3f, 0x20, 0x62, 0x75, 0x72, 0x79, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65,
+ 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x79, 0x20, 0x64, 0x65, 0x61,
+ 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61,
+ 0x68, 0x61, 0x6d, 0x20, 0x68, 0x65, 0x61, 0x72, 0x6b, 0x65, 0x6e, 0x65,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x45, 0x70, 0x68, 0x72, 0x6f,
+ 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68,
+ 0x61, 0x6d, 0x20, 0x77, 0x65, 0x69, 0x67, 0x68, 0x65, 0x64, 0x20, 0x74,
+ 0x6f, 0x20, 0x45, 0x70, 0x68, 0x72, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x69, 0x6c, 0x76, 0x65, 0x72, 0x2c, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61,
+ 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x48,
+ 0x65, 0x74, 0x68, 0x2c, 0x20, 0x66, 0x6f, 0x75, 0x72, 0x20, 0x68, 0x75,
+ 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x73, 0x68, 0x65, 0x6b, 0x65, 0x6c,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x69, 0x6c, 0x76, 0x65, 0x72, 0x2c,
+ 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x6f, 0x6e,
+ 0x65, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x65, 0x72, 0x63, 0x68, 0x61, 0x6e, 0x74, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64,
+ 0x20, 0x6f, 0x66, 0x20, 0x45, 0x70, 0x68, 0x72, 0x6f, 0x6e, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x69, 0x6e, 0x20,
+ 0x4d, 0x61, 0x63, 0x68, 0x70, 0x65, 0x6c, 0x61, 0x68, 0x2c, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x62, 0x65, 0x66,
+ 0x6f, 0x72, 0x65, 0x20, 0x4d, 0x61, 0x6d, 0x72, 0x65, 0x2c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x76, 0x65, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x69, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x73, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2c, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x69, 0x6e,
+ 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x72,
+ 0x64, 0x65, 0x72, 0x73, 0x20, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x61,
+ 0x62, 0x6f, 0x75, 0x74, 0x2c, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6d,
+ 0x61, 0x64, 0x65, 0x20, 0x73, 0x75, 0x72, 0x65, 0x20, 0x0a, 0x55, 0x6e,
+ 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x61, 0x20, 0x70, 0x6f, 0x73, 0x73, 0x65, 0x73, 0x73,
+ 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70,
+ 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20,
+ 0x6f, 0x66, 0x20, 0x48, 0x65, 0x74, 0x68, 0x2c, 0x20, 0x62, 0x65, 0x66,
+ 0x6f, 0x72, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x74, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x63, 0x69, 0x74, 0x79, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x69,
+ 0x73, 0x2c, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x62,
+ 0x75, 0x72, 0x69, 0x65, 0x64, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x76, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x4d, 0x61, 0x63, 0x68, 0x70, 0x65, 0x6c, 0x61, 0x68, 0x20, 0x62,
+ 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x4d, 0x61, 0x6d, 0x72, 0x65, 0x3a,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x73,
+ 0x20, 0x48, 0x65, 0x62, 0x72, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x43,
+ 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x76, 0x65, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x72,
+ 0x65, 0x69, 0x6e, 0x2c, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6d, 0x61,
+ 0x64, 0x65, 0x20, 0x73, 0x75, 0x72, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x61, 0x20, 0x70, 0x6f, 0x73, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f,
+ 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x62, 0x75, 0x72, 0x79, 0x69,
+ 0x6e, 0x67, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x62, 0x79, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x48,
+ 0x65, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6f, 0x6c,
+ 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x20,
+ 0x73, 0x74, 0x72, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x20, 0x69, 0x6e, 0x20,
+ 0x61, 0x67, 0x65, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x68, 0x61, 0x64, 0x20, 0x62, 0x6c,
+ 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61,
+ 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x69,
+ 0x6e, 0x67, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x65, 0x6c, 0x64, 0x65,
+ 0x73, 0x74, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2c,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x64, 0x20,
+ 0x6f, 0x76, 0x65, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x2c, 0x20, 0x50, 0x75,
+ 0x74, 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72, 0x61, 0x79, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x79, 0x20, 0x68, 0x61, 0x6e, 0x64,
+ 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x6d, 0x79, 0x20, 0x74, 0x68,
+ 0x69, 0x67, 0x68, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x20, 0x73, 0x77, 0x65, 0x61, 0x72, 0x20, 0x62, 0x79, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2c, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65, 0x61,
+ 0x76, 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x61, 0x20, 0x77, 0x69,
+ 0x66, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x79, 0x20, 0x73,
+ 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61,
+ 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x69, 0x74, 0x65,
+ 0x73, 0x2c, 0x20, 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x20, 0x77, 0x68, 0x6f,
+ 0x6d, 0x20, 0x49, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x3a, 0x20, 0x0a,
+ 0x42, 0x75, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x74, 0x20, 0x67, 0x6f, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d,
+ 0x79, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x79, 0x20, 0x6b, 0x69, 0x6e,
+ 0x64, 0x72, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x61,
+ 0x6b, 0x65, 0x20, 0x61, 0x20, 0x77, 0x69, 0x66, 0x65, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x49, 0x73,
+ 0x61, 0x61, 0x63, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c,
+ 0x20, 0x50, 0x65, 0x72, 0x61, 0x64, 0x76, 0x65, 0x6e, 0x74, 0x75, 0x72,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x66,
+ 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x6d, 0x65, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x3a,
+ 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x49, 0x20, 0x6e, 0x65, 0x65, 0x64,
+ 0x73, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x73, 0x6f, 0x6e, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20,
+ 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x63, 0x65, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x73, 0x74, 0x3f,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61,
+ 0x6d, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x42, 0x65, 0x77, 0x61, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x6e, 0x6f, 0x74,
+ 0x20, 0x6d, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x2e, 0x20, 0x0a,
+ 0x54, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x2c, 0x20,
+ 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x6d,
+ 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6d, 0x79, 0x20, 0x66, 0x61,
+ 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x6d,
+ 0x79, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x73, 0x70, 0x61,
+ 0x6b, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73, 0x77, 0x61,
+ 0x72, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x2c, 0x20,
+ 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x55, 0x6e, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x77, 0x69,
+ 0x6c, 0x6c, 0x20, 0x49, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x74, 0x68,
+ 0x69, 0x73, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x3b, 0x20, 0x68, 0x65, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x20, 0x62, 0x65, 0x66,
+ 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74,
+ 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x61, 0x20, 0x77, 0x69, 0x66, 0x65,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x6f, 0x6e,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x63, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f,
+ 0x77, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x6e,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20,
+ 0x62, 0x65, 0x20, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x79, 0x20, 0x6f, 0x61,
+ 0x74, 0x68, 0x3a, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x62, 0x72, 0x69,
+ 0x6e, 0x67, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x6f,
+ 0x6e, 0x20, 0x74, 0x68, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x61, 0x67,
+ 0x61, 0x69, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x20, 0x70, 0x75,
+ 0x74, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x20, 0x75,
+ 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x69,
+ 0x67, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61,
+ 0x6d, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x77, 0x61, 0x72, 0x65, 0x20,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65,
+ 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d,
+ 0x61, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x20,
+ 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x74, 0x65, 0x6e, 0x20, 0x63, 0x61, 0x6d,
+ 0x65, 0x6c, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x61, 0x6d, 0x65, 0x6c, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x64, 0x65, 0x70, 0x61, 0x72, 0x74, 0x65, 0x64, 0x3b, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67,
+ 0x6f, 0x6f, 0x64, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x69, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6f, 0x73,
+ 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20,
+ 0x74, 0x6f, 0x20, 0x4d, 0x65, 0x73, 0x6f, 0x70, 0x6f, 0x74, 0x61, 0x6d,
+ 0x69, 0x61, 0x2c, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x63, 0x69, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x4e, 0x61, 0x68,
+ 0x6f, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x6d, 0x61, 0x64, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x63, 0x61, 0x6d,
+ 0x65, 0x6c, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x6b, 0x6e, 0x65, 0x65, 0x6c,
+ 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x69, 0x74, 0x79, 0x20, 0x62,
+ 0x79, 0x20, 0x61, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x6f, 0x66, 0x20,
+ 0x77, 0x61, 0x74, 0x65, 0x72, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x65, 0x76,
+ 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x6f, 0x6d, 0x65, 0x6e, 0x20, 0x67,
+ 0x6f, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x72, 0x61,
+ 0x77, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x4f, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x6d, 0x79, 0x20, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72, 0x61,
+ 0x79, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x73, 0x65, 0x6e, 0x64,
+ 0x20, 0x6d, 0x65, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x73, 0x70, 0x65,
+ 0x65, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x64, 0x61, 0x79, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x77, 0x20, 0x6b, 0x69,
+ 0x6e, 0x64, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x6d, 0x79, 0x20, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x68, 0x61, 0x6d, 0x2e, 0x20, 0x0a, 0x42, 0x65, 0x68, 0x6f,
+ 0x6c, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x77, 0x61, 0x74, 0x65,
+ 0x72, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x63, 0x69, 0x74, 0x79, 0x20, 0x63, 0x6f, 0x6d, 0x65,
+ 0x20, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x72, 0x61, 0x77,
+ 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x6c, 0x65, 0x74, 0x20, 0x69, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x65,
+ 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x6d, 0x73, 0x65,
+ 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x49, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x73, 0x61, 0x79, 0x2c, 0x20, 0x4c,
+ 0x65, 0x74, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x70, 0x69, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x49, 0x20, 0x70,
+ 0x72, 0x61, 0x79, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x49, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x64, 0x72, 0x69,
+ 0x6e, 0x6b, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x73, 0x61, 0x79, 0x2c, 0x20, 0x44,
+ 0x72, 0x69, 0x6e, 0x6b, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x74, 0x68,
+ 0x79, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x6c, 0x73, 0x20, 0x64, 0x72, 0x69,
+ 0x6e, 0x6b, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x3a, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x62, 0x65,
+ 0x20, 0x73, 0x68, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x61, 0x70, 0x70, 0x6f,
+ 0x69, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68,
+ 0x79, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x20, 0x49, 0x73,
+ 0x61, 0x61, 0x63, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x62, 0x79, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x49,
+ 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x73, 0x68, 0x65,
+ 0x77, 0x65, 0x64, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x6e, 0x65, 0x73, 0x73,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x79, 0x20, 0x6d, 0x61, 0x73,
+ 0x74, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74,
+ 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73,
+ 0x73, 0x2c, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x68, 0x65,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x73, 0x70,
+ 0x65, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x52, 0x65,
+ 0x62, 0x65, 0x6b, 0x61, 0x68, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x6f,
+ 0x75, 0x74, 0x2c, 0x20, 0x77, 0x68, 0x6f, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x42, 0x65, 0x74, 0x68,
+ 0x75, 0x65, 0x6c, 0x2c, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20,
+ 0x4d, 0x69, 0x6c, 0x63, 0x61, 0x68, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x69, 0x66, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x4e, 0x61, 0x68, 0x6f,
+ 0x72, 0x2c, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x27, 0x73,
+ 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x68, 0x65, 0x72, 0x20, 0x70, 0x69, 0x74, 0x63, 0x68,
+ 0x65, 0x72, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x68, 0x65, 0x72, 0x20,
+ 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x6d, 0x73, 0x65,
+ 0x6c, 0x20, 0x77, 0x61, 0x73, 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x66,
+ 0x61, 0x69, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x20, 0x76, 0x69, 0x72, 0x67,
+ 0x69, 0x6e, 0x2c, 0x20, 0x6e, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x68, 0x61, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6d, 0x61, 0x6e, 0x20,
+ 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x68, 0x65, 0x72, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20,
+ 0x64, 0x6f, 0x77, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x65, 0x6c, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69,
+ 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68, 0x65, 0x72, 0x20, 0x70, 0x69, 0x74,
+ 0x63, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61,
+ 0x6d, 0x65, 0x20, 0x75, 0x70, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x20,
+ 0x72, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x65, 0x74, 0x20,
+ 0x68, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x49,
+ 0x20, 0x70, 0x72, 0x61, 0x79, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20,
+ 0x64, 0x72, 0x69, 0x6e, 0x6b, 0x20, 0x61, 0x20, 0x6c, 0x69, 0x74, 0x74,
+ 0x6c, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x79, 0x20, 0x70, 0x69, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x2c, 0x20, 0x44, 0x72, 0x69, 0x6e, 0x6b, 0x2c, 0x20, 0x6d,
+ 0x79, 0x20, 0x6c, 0x6f, 0x72, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x68, 0x65, 0x20, 0x68, 0x61, 0x73, 0x74, 0x65, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x64, 0x6f, 0x77, 0x6e,
+ 0x20, 0x68, 0x65, 0x72, 0x20, 0x70, 0x69, 0x74, 0x63, 0x68, 0x65, 0x72,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x68, 0x65, 0x72, 0x20, 0x68, 0x61,
+ 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x61, 0x76, 0x65,
+ 0x20, 0x68, 0x69, 0x6d, 0x20, 0x64, 0x72, 0x69, 0x6e, 0x6b, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x73, 0x68,
+ 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x67,
+ 0x69, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x64, 0x72,
+ 0x69, 0x6e, 0x6b, 0x2c, 0x20, 0x73, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x64, 0x72,
+ 0x61, 0x77, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x6c, 0x73, 0x20,
+ 0x61, 0x6c, 0x73, 0x6f, 0x2c, 0x20, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x64, 0x6f,
+ 0x6e, 0x65, 0x20, 0x64, 0x72, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x68, 0x61,
+ 0x73, 0x74, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6d,
+ 0x70, 0x74, 0x69, 0x65, 0x64, 0x20, 0x68, 0x65, 0x72, 0x20, 0x70, 0x69,
+ 0x74, 0x63, 0x68, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x72, 0x61, 0x6e, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x65,
+ 0x6c, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x72, 0x61, 0x77, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x72,
+ 0x65, 0x77, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x6c, 0x73, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x20,
+ 0x77, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x74,
+ 0x20, 0x68, 0x65, 0x72, 0x20, 0x68, 0x65, 0x6c, 0x64, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x70, 0x65, 0x61, 0x63, 0x65, 0x2c, 0x20, 0x74, 0x6f, 0x20,
+ 0x77, 0x69, 0x74, 0x20, 0x77, 0x68, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x68, 0x61, 0x64,
+ 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6a, 0x6f,
+ 0x75, 0x72, 0x6e, 0x65, 0x79, 0x20, 0x70, 0x72, 0x6f, 0x73, 0x70, 0x65,
+ 0x72, 0x6f, 0x75, 0x73, 0x20, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d,
+ 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x61,
+ 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x6c, 0x73,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x64, 0x72,
+ 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x6f,
+ 0x6b, 0x20, 0x61, 0x20, 0x67, 0x6f, 0x6c, 0x64, 0x65, 0x6e, 0x20, 0x65,
+ 0x61, 0x72, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x61,
+ 0x6c, 0x66, 0x20, 0x61, 0x20, 0x73, 0x68, 0x65, 0x6b, 0x65, 0x6c, 0x20,
+ 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x77, 0x6f, 0x20, 0x62, 0x72, 0x61, 0x63, 0x65, 0x6c, 0x65, 0x74,
+ 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68, 0x65, 0x72, 0x20, 0x68, 0x61,
+ 0x6e, 0x64, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x65, 0x6e, 0x20, 0x73,
+ 0x68, 0x65, 0x6b, 0x65, 0x6c, 0x73, 0x20, 0x77, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x67, 0x6f, 0x6c, 0x64, 0x3b, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x57, 0x68,
+ 0x6f, 0x73, 0x65, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72,
+ 0x20, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x3f, 0x20, 0x74,
+ 0x65, 0x6c, 0x6c, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72,
+ 0x61, 0x79, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3a, 0x20, 0x69, 0x73, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x72, 0x6f, 0x6f, 0x6d, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72,
+ 0x27, 0x73, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x75, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x64, 0x67, 0x65,
+ 0x20, 0x69, 0x6e, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x73, 0x68,
+ 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x49, 0x20, 0x61, 0x6d, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x20, 0x6f,
+ 0x66, 0x20, 0x42, 0x65, 0x74, 0x68, 0x75, 0x65, 0x6c, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x4d, 0x69, 0x6c,
+ 0x63, 0x61, 0x68, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x4e, 0x61, 0x68, 0x6f, 0x72, 0x2e, 0x20, 0x0a, 0x53, 0x68, 0x65,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x6f, 0x76,
+ 0x65, 0x72, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c,
+ 0x20, 0x57, 0x65, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x6f, 0x74,
+ 0x68, 0x20, 0x73, 0x74, 0x72, 0x61, 0x77, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x70, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x65, 0x6e,
+ 0x6f, 0x75, 0x67, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x6f,
+ 0x6f, 0x6d, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x64, 0x67, 0x65, 0x20,
+ 0x69, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x62, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x64,
+ 0x6f, 0x77, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x65, 0x61, 0x64,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x68, 0x69,
+ 0x70, 0x70, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64,
+ 0x20, 0x62, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x6d,
+ 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61,
+ 0x6d, 0x2c, 0x20, 0x77, 0x68, 0x6f, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20,
+ 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x64, 0x65, 0x73,
+ 0x74, 0x69, 0x74, 0x75, 0x74, 0x65, 0x20, 0x6d, 0x79, 0x20, 0x6d, 0x61,
+ 0x73, 0x74, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6d, 0x65, 0x72, 0x63, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x74, 0x72, 0x75, 0x74, 0x68, 0x3a, 0x20, 0x49, 0x20, 0x62,
+ 0x65, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x61, 0x79, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x6c, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x6d, 0x79, 0x20, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x27, 0x73,
+ 0x20, 0x62, 0x72, 0x65, 0x74, 0x68, 0x72, 0x65, 0x6e, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x6d, 0x73,
+ 0x65, 0x6c, 0x20, 0x72, 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x6f, 0x6c, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x6f, 0x66,
+ 0x20, 0x68, 0x65, 0x72, 0x20, 0x6d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x27,
+ 0x73, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x73,
+ 0x65, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x52, 0x65, 0x62, 0x65, 0x6b, 0x61, 0x68, 0x20, 0x68,
+ 0x61, 0x64, 0x20, 0x61, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20,
+ 0x72, 0x61, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d,
+ 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x77,
+ 0x68, 0x65, 0x6e, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x62, 0x72, 0x61, 0x63, 0x65, 0x6c, 0x65, 0x74, 0x73,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x69,
+ 0x73, 0x74, 0x65, 0x72, 0x27, 0x73, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x73,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x68,
+ 0x65, 0x20, 0x68, 0x65, 0x61, 0x72, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x6f, 0x72, 0x64, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x52, 0x65, 0x62,
+ 0x65, 0x6b, 0x61, 0x68, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x69, 0x73,
+ 0x74, 0x65, 0x72, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c,
+ 0x20, 0x54, 0x68, 0x75, 0x73, 0x20, 0x73, 0x70, 0x61, 0x6b, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x6d, 0x65, 0x3b, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65,
+ 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x2c,
+ 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x68, 0x65, 0x20,
+ 0x73, 0x74, 0x6f, 0x6f, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x63, 0x61, 0x6d, 0x65, 0x6c, 0x73, 0x20, 0x61, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x43,
+ 0x6f, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x2c, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x3b, 0x20, 0x77, 0x68,
+ 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x73, 0x74, 0x61, 0x6e,
+ 0x64, 0x65, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x6f, 0x75, 0x74, 0x3f, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x49,
+ 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72,
+ 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x6f, 0x6f, 0x6d, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x6c,
+ 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x61, 0x6e, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x75, 0x6e, 0x67, 0x69,
+ 0x72, 0x64, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x63, 0x61, 0x6d,
+ 0x65, 0x6c, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x61, 0x76,
+ 0x65, 0x20, 0x73, 0x74, 0x72, 0x61, 0x77, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x70, 0x72, 0x6f, 0x76, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x6c, 0x73,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x20,
+ 0x74, 0x6f, 0x20, 0x77, 0x61, 0x73, 0x68, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x66, 0x65, 0x65, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x27, 0x73, 0x20, 0x66, 0x65, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x73, 0x65, 0x74, 0x20, 0x6d, 0x65, 0x61, 0x74, 0x20, 0x62, 0x65, 0x66,
+ 0x6f, 0x72, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x74, 0x6f, 0x20, 0x65,
+ 0x61, 0x74, 0x3a, 0x20, 0x62, 0x75, 0x74, 0x20, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x61, 0x74, 0x2c, 0x20, 0x75, 0x6e, 0x74,
+ 0x69, 0x6c, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x6f,
+ 0x6c, 0x64, 0x20, 0x6d, 0x69, 0x6e, 0x65, 0x20, 0x65, 0x72, 0x72, 0x61,
+ 0x6e, 0x64, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x53, 0x70, 0x65, 0x61, 0x6b, 0x20, 0x6f,
+ 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x61, 0x6d, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x68, 0x61, 0x6d, 0x27, 0x73, 0x20, 0x73, 0x65, 0x72, 0x76,
+ 0x61, 0x6e, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20,
+ 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x6d, 0x79, 0x20, 0x6d,
+ 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x6c,
+ 0x79, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x69, 0x73,
+ 0x20, 0x62, 0x65, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x67, 0x72, 0x65, 0x61,
+ 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61,
+ 0x74, 0x68, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x68, 0x69, 0x6d,
+ 0x20, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x72, 0x64, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x69, 0x6c, 0x76, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x67, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x65,
+ 0x6e, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x64, 0x73, 0x65, 0x72, 0x76, 0x61,
+ 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6d,
+ 0x65, 0x6c, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x73, 0x73,
+ 0x65, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x72,
+ 0x61, 0x68, 0x20, 0x6d, 0x79, 0x20, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72,
+ 0x27, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x20, 0x62, 0x61, 0x72, 0x65,
+ 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x79,
+ 0x20, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x77, 0x68, 0x65, 0x6e,
+ 0x20, 0x73, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6f, 0x6c, 0x64,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68,
+ 0x69, 0x6d, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x68, 0x65, 0x20, 0x67,
+ 0x69, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x74, 0x68, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x6d, 0x79, 0x20, 0x6d, 0x61, 0x73, 0x74, 0x65,
+ 0x72, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x6d, 0x65, 0x20, 0x73, 0x77,
+ 0x65, 0x61, 0x72, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c,
+ 0x20, 0x54, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20,
+ 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x61, 0x20, 0x77,
+ 0x69, 0x66, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x6f,
+ 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x75,
+ 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x69, 0x74, 0x65, 0x73,
+ 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x77, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x6c,
+ 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x3a,
+ 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x74, 0x20, 0x67, 0x6f, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x6d, 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73,
+ 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x6d, 0x79, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x72, 0x65,
+ 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20,
+ 0x61, 0x20, 0x77, 0x69, 0x66, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x6d, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x49, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x6d, 0x79, 0x20, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2c, 0x20,
+ 0x50, 0x65, 0x72, 0x61, 0x64, 0x76, 0x65, 0x6e, 0x74, 0x75, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x6c, 0x6c,
+ 0x6f, 0x77, 0x20, 0x6d, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x54, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x2c, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x77, 0x68,
+ 0x6f, 0x6d, 0x20, 0x49, 0x20, 0x77, 0x61, 0x6c, 0x6b, 0x2c, 0x20, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x72,
+ 0x6f, 0x73, 0x70, 0x65, 0x72, 0x20, 0x74, 0x68, 0x79, 0x20, 0x77, 0x61,
+ 0x79, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x61,
+ 0x20, 0x77, 0x69, 0x66, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x79,
+ 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x6b,
+ 0x69, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72,
+ 0x27, 0x73, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x3a, 0x20, 0x0a, 0x54,
+ 0x68, 0x65, 0x6e, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x62, 0x65, 0x20, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x20,
+ 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x79,
+ 0x20, 0x6f, 0x61, 0x74, 0x68, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x73, 0x74, 0x20,
+ 0x74, 0x6f, 0x20, 0x6d, 0x79, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x72, 0x65,
+ 0x64, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x2c, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x62, 0x65, 0x20,
+ 0x63, 0x6c, 0x65, 0x61, 0x72, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6d,
+ 0x79, 0x20, 0x6f, 0x61, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x49, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x64, 0x61, 0x79, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4f, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x6d,
+ 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61,
+ 0x6d, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x64, 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x73, 0x70, 0x65,
+ 0x72, 0x20, 0x6d, 0x79, 0x20, 0x77, 0x61, 0x79, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x49, 0x20, 0x67, 0x6f, 0x3a, 0x20, 0x0a, 0x42, 0x65,
+ 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x73, 0x74, 0x61, 0x6e,
+ 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x65, 0x6c,
+ 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c,
+ 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73,
+ 0x73, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x68, 0x65, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x69, 0x72, 0x67, 0x69, 0x6e, 0x20,
+ 0x63, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68,
+ 0x20, 0x74, 0x6f, 0x20, 0x64, 0x72, 0x61, 0x77, 0x20, 0x77, 0x61, 0x74,
+ 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x73, 0x61,
+ 0x79, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x47, 0x69,
+ 0x76, 0x65, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72, 0x61,
+ 0x79, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x20, 0x6c, 0x69,
+ 0x74, 0x74, 0x6c, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x70, 0x69, 0x74, 0x63, 0x68, 0x65,
+ 0x72, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x72, 0x69, 0x6e, 0x6b, 0x3b, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x73, 0x61, 0x79,
+ 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x42, 0x6f, 0x74, 0x68,
+ 0x20, 0x64, 0x72, 0x69, 0x6e, 0x6b, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x64, 0x72, 0x61, 0x77, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x74, 0x68, 0x79, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x6c, 0x73,
+ 0x3a, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61,
+ 0x6d, 0x65, 0x20, 0x62, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f,
+ 0x6d, 0x61, 0x6e, 0x20, 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x61,
+ 0x70, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x6f, 0x75, 0x74,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x79, 0x20, 0x6d, 0x61, 0x73, 0x74,
+ 0x65, 0x72, 0x27, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x49, 0x20,
+ 0x68, 0x61, 0x64, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x73, 0x70, 0x65,
+ 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x20, 0x6d, 0x69, 0x6e,
+ 0x65, 0x20, 0x68, 0x65, 0x61, 0x72, 0x74, 0x2c, 0x20, 0x62, 0x65, 0x68,
+ 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x52, 0x65, 0x62, 0x65, 0x6b, 0x61, 0x68,
+ 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x65, 0x72, 0x20, 0x70, 0x69, 0x74,
+ 0x63, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x6e, 0x20, 0x68, 0x65, 0x72, 0x20,
+ 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x65, 0x72, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x64,
+ 0x6f, 0x77, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64,
+ 0x72, 0x65, 0x77, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x49, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20,
+ 0x6d, 0x65, 0x20, 0x64, 0x72, 0x69, 0x6e, 0x6b, 0x2c, 0x20, 0x49, 0x20,
+ 0x70, 0x72, 0x61, 0x79, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x64, 0x65,
+ 0x20, 0x68, 0x61, 0x73, 0x74, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6c, 0x65, 0x74, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x20, 0x68, 0x65, 0x72,
+ 0x20, 0x70, 0x69, 0x74, 0x63, 0x68, 0x65, 0x72, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x68, 0x65, 0x72, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64,
+ 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x44, 0x72, 0x69, 0x6e, 0x6b, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x67, 0x69, 0x76, 0x65,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x6c, 0x73, 0x20,
+ 0x64, 0x72, 0x69, 0x6e, 0x6b, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x3a, 0x20,
+ 0x73, 0x6f, 0x20, 0x49, 0x20, 0x64, 0x72, 0x61, 0x6e, 0x6b, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x64, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x6c, 0x73, 0x20,
+ 0x64, 0x72, 0x69, 0x6e, 0x6b, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x61, 0x73, 0x6b, 0x65, 0x64,
+ 0x20, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x2c, 0x20, 0x57, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x64, 0x61,
+ 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x20, 0x61, 0x72, 0x74, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x3f, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x42,
+ 0x65, 0x74, 0x68, 0x75, 0x65, 0x6c, 0x2c, 0x20, 0x4e, 0x61, 0x68, 0x6f,
+ 0x72, 0x27, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x77, 0x68, 0x6f,
+ 0x6d, 0x20, 0x4d, 0x69, 0x6c, 0x63, 0x61, 0x68, 0x20, 0x62, 0x61, 0x72,
+ 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x70, 0x75, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x70,
+ 0x6f, 0x6e, 0x20, 0x68, 0x65, 0x72, 0x20, 0x66, 0x61, 0x63, 0x65, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x72, 0x61,
+ 0x63, 0x65, 0x6c, 0x65, 0x74, 0x73, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20,
+ 0x68, 0x65, 0x72, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x62, 0x6f, 0x77, 0x65, 0x64, 0x20,
+ 0x64, 0x6f, 0x77, 0x6e, 0x20, 0x6d, 0x79, 0x20, 0x68, 0x65, 0x61, 0x64,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x68, 0x69,
+ 0x70, 0x70, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73,
+ 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x6d, 0x61,
+ 0x73, 0x74, 0x65, 0x72, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d,
+ 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x68, 0x61, 0x64, 0x20,
+ 0x6c, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x77, 0x61, 0x79, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x6d, 0x79, 0x20, 0x6d,
+ 0x61, 0x73, 0x74, 0x65, 0x72, 0x27, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74,
+ 0x65, 0x72, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x73, 0x6f, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x6e, 0x6f,
+ 0x77, 0x20, 0x69, 0x66, 0x20, 0x79, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x64, 0x65, 0x61, 0x6c, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x6c, 0x79,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x72, 0x75, 0x6c, 0x79, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x6d, 0x79, 0x20, 0x6d, 0x61, 0x73, 0x74, 0x65,
+ 0x72, 0x2c, 0x20, 0x74, 0x65, 0x6c, 0x6c, 0x20, 0x6d, 0x65, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x2c, 0x20,
+ 0x74, 0x65, 0x6c, 0x6c, 0x20, 0x6d, 0x65, 0x3b, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x49, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x74, 0x75, 0x72, 0x6e,
+ 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x69, 0x67, 0x68,
+ 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x2e, 0x20,
+ 0x0a, 0x54, 0x68, 0x65, 0x6e, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x42, 0x65, 0x74, 0x68, 0x75, 0x65, 0x6c, 0x20,
+ 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x65, 0x20, 0x74,
+ 0x68, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x65, 0x64,
+ 0x65, 0x74, 0x68, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x3a, 0x20, 0x77, 0x65, 0x20, 0x63, 0x61,
+ 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x70, 0x65, 0x61, 0x6b, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x62, 0x61, 0x64,
+ 0x20, 0x6f, 0x72, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x42,
+ 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x52, 0x65, 0x62, 0x65, 0x6b,
+ 0x61, 0x68, 0x20, 0x69, 0x73, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20,
+ 0x68, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x6f, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x68, 0x65, 0x72,
+ 0x20, 0x62, 0x65, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6d, 0x61, 0x73, 0x74,
+ 0x65, 0x72, 0x27, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x27, 0x73, 0x20, 0x77,
+ 0x69, 0x66, 0x65, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x73, 0x70,
+ 0x6f, 0x6b, 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69,
+ 0x74, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61,
+ 0x73, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x2c, 0x20, 0x77, 0x68,
+ 0x65, 0x6e, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x27, 0x73,
+ 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x20, 0x68, 0x65, 0x61,
+ 0x72, 0x64, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x77, 0x6f, 0x72,
+ 0x64, 0x73, 0x2c, 0x20, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x68,
+ 0x69, 0x70, 0x70, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x2c, 0x20, 0x62, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x68,
+ 0x69, 0x6d, 0x73, 0x65, 0x6c, 0x66, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e,
+ 0x74, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x66, 0x6f,
+ 0x72, 0x74, 0x68, 0x20, 0x6a, 0x65, 0x77, 0x65, 0x6c, 0x73, 0x20, 0x6f,
+ 0x66, 0x20, 0x73, 0x69, 0x6c, 0x76, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6a, 0x65, 0x77, 0x65, 0x6c, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x67, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x61,
+ 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67,
+ 0x61, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x74, 0x6f, 0x20,
+ 0x52, 0x65, 0x62, 0x65, 0x6b, 0x61, 0x68, 0x3a, 0x20, 0x68, 0x65, 0x20,
+ 0x67, 0x61, 0x76, 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x74, 0x6f,
+ 0x20, 0x68, 0x65, 0x72, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x65, 0x72, 0x20,
+ 0x6d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x70, 0x72, 0x65, 0x63, 0x69,
+ 0x6f, 0x75, 0x73, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x64, 0x69,
+ 0x64, 0x20, 0x65, 0x61, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x72,
+ 0x69, 0x6e, 0x6b, 0x2c, 0x20, 0x68, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68,
+ 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x61, 0x72, 0x72,
+ 0x69, 0x65, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x69, 0x67, 0x68,
+ 0x74, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x72, 0x6f, 0x73, 0x65, 0x20, 0x75, 0x70, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x53, 0x65, 0x6e, 0x64, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x77, 0x61,
+ 0x79, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x79, 0x20, 0x6d, 0x61,
+ 0x73, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x72, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x72, 0x20, 0x6d, 0x6f, 0x74, 0x68, 0x65,
+ 0x72, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x6d, 0x73, 0x65, 0x6c, 0x20, 0x61,
+ 0x62, 0x69, 0x64, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x75, 0x73,
+ 0x20, 0x61, 0x20, 0x66, 0x65, 0x77, 0x20, 0x64, 0x61, 0x79, 0x73, 0x2c,
+ 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x65, 0x61, 0x73,
+ 0x74, 0x20, 0x74, 0x65, 0x6e, 0x3b, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73, 0x68, 0x65, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x67, 0x6f, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x48, 0x69, 0x6e, 0x64,
+ 0x65, 0x72, 0x20, 0x6d, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x2c, 0x20, 0x73,
+ 0x65, 0x65, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x70, 0x72, 0x6f, 0x73,
+ 0x70, 0x65, 0x72, 0x65, 0x64, 0x20, 0x6d, 0x79, 0x20, 0x77, 0x61, 0x79,
+ 0x3b, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x77,
+ 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x6d, 0x61,
+ 0x79, 0x20, 0x67, 0x6f, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x79, 0x20, 0x6d,
+ 0x61, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x57,
+ 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x6d, 0x73, 0x65, 0x6c, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6e, 0x71, 0x75, 0x69, 0x72, 0x65, 0x20,
+ 0x61, 0x74, 0x20, 0x68, 0x65, 0x72, 0x20, 0x6d, 0x6f, 0x75, 0x74, 0x68,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x52, 0x65, 0x62, 0x65, 0x6b,
+ 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x57,
+ 0x69, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x67, 0x6f, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x61,
+ 0x6e, 0x3f, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x67, 0x6f, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x79, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x77, 0x61, 0x79, 0x20,
+ 0x52, 0x65, 0x62, 0x65, 0x6b, 0x61, 0x68, 0x20, 0x74, 0x68, 0x65, 0x69,
+ 0x72, 0x20, 0x73, 0x69, 0x73, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x72, 0x20, 0x6e, 0x75, 0x72, 0x73, 0x65, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d,
+ 0x27, 0x73, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x65, 0x6e, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x62,
+ 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x52, 0x65, 0x62, 0x65, 0x6b,
+ 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x54,
+ 0x68, 0x6f, 0x75, 0x20, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x75, 0x72, 0x20,
+ 0x73, 0x69, 0x73, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x62, 0x65, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x74, 0x68,
+ 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x73, 0x61,
+ 0x6e, 0x64, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x69, 0x6c, 0x6c, 0x69,
+ 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x70, 0x6f,
+ 0x73, 0x73, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61,
+ 0x74, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65, 0x20,
+ 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x68, 0x61, 0x74, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x52, 0x65,
+ 0x62, 0x65, 0x6b, 0x61, 0x68, 0x20, 0x61, 0x72, 0x6f, 0x73, 0x65, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x72, 0x20, 0x64, 0x61, 0x6d,
+ 0x73, 0x65, 0x6c, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x72, 0x6f, 0x64, 0x65, 0x20, 0x75, 0x70, 0x6f, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x6c, 0x73, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61,
+ 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x52, 0x65, 0x62, 0x65,
+ 0x6b, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x6e,
+ 0x74, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x61, 0x79, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x63, 0x61,
+ 0x6d, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x65, 0x6c, 0x6c, 0x20, 0x4c, 0x61, 0x68, 0x61, 0x69, 0x72, 0x6f, 0x69,
+ 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68, 0x65, 0x20, 0x64, 0x77, 0x65,
+ 0x6c, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f,
+ 0x75, 0x74, 0x68, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20,
+ 0x77, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x6f, 0x20,
+ 0x6d, 0x65, 0x64, 0x69, 0x74, 0x61, 0x74, 0x65, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x69, 0x64,
+ 0x65, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x6c, 0x69,
+ 0x66, 0x74, 0x65, 0x64, 0x20, 0x75, 0x70, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x65, 0x79, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61,
+ 0x77, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f,
+ 0x6c, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6d, 0x65,
+ 0x6c, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x69,
+ 0x6e, 0x67, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x52, 0x65, 0x62,
+ 0x65, 0x6b, 0x61, 0x68, 0x20, 0x6c, 0x69, 0x66, 0x74, 0x65, 0x64, 0x20,
+ 0x75, 0x70, 0x20, 0x68, 0x65, 0x72, 0x20, 0x65, 0x79, 0x65, 0x73, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x73, 0x68,
+ 0x65, 0x20, 0x73, 0x61, 0x77, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x2c,
+ 0x20, 0x73, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x65, 0x64,
+ 0x20, 0x6f, 0x66, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6d,
+ 0x65, 0x6c, 0x2e, 0x20, 0x0a, 0x46, 0x6f, 0x72, 0x20, 0x73, 0x68, 0x65,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61,
+ 0x6e, 0x74, 0x2c, 0x20, 0x57, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x61, 0x6e,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x77, 0x61, 0x6c, 0x6b, 0x65, 0x74, 0x68, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x74,
+ 0x6f, 0x20, 0x6d, 0x65, 0x65, 0x74, 0x20, 0x75, 0x73, 0x3f, 0x20, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61,
+ 0x6e, 0x74, 0x20, 0x68, 0x61, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x49, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x79, 0x20, 0x6d, 0x61,
+ 0x73, 0x74, 0x65, 0x72, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x66,
+ 0x6f, 0x72, 0x65, 0x20, 0x73, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x6b,
+ 0x20, 0x61, 0x20, 0x76, 0x61, 0x69, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x68, 0x65, 0x72,
+ 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x20, 0x74,
+ 0x6f, 0x6c, 0x64, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x64, 0x6f, 0x6e,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x61, 0x61,
+ 0x63, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x68, 0x65,
+ 0x72, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6d,
+ 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x27,
+ 0x73, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x52, 0x65, 0x62, 0x65, 0x6b, 0x61, 0x68,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x62, 0x65,
+ 0x63, 0x61, 0x6d, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66,
+ 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x6c, 0x6f,
+ 0x76, 0x65, 0x64, 0x20, 0x68, 0x65, 0x72, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x77, 0x61, 0x73, 0x20, 0x63,
+ 0x6f, 0x6d, 0x66, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74,
+ 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x6f, 0x74, 0x68, 0x65,
+ 0x72, 0x27, 0x73, 0x20, 0x64, 0x65, 0x61, 0x74, 0x68, 0x2e, 0x20, 0x0a,
+ 0x54, 0x68, 0x65, 0x6e, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x20, 0x41,
+ 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20,
+ 0x61, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x72, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x4b, 0x65, 0x74, 0x75, 0x72, 0x61, 0x68, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20,
+ 0x68, 0x69, 0x6d, 0x20, 0x5a, 0x69, 0x6d, 0x72, 0x61, 0x6e, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x6f, 0x6b, 0x73, 0x68, 0x61, 0x6e, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4d, 0x65, 0x64, 0x61, 0x6e, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4d, 0x69, 0x64, 0x69, 0x61, 0x6e, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x68, 0x62, 0x61, 0x6b, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x53, 0x68, 0x75, 0x61, 0x68, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x6f, 0x6b, 0x73, 0x68, 0x61, 0x6e, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x53, 0x68, 0x65, 0x62, 0x61, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x44, 0x65, 0x64, 0x61, 0x6e, 0x2e, 0x20,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x44, 0x65, 0x64, 0x61, 0x6e, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x41, 0x73, 0x73, 0x68, 0x75, 0x72, 0x69, 0x6d, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x65, 0x74, 0x75, 0x73, 0x68, 0x69,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x65, 0x75, 0x6d, 0x6d,
+ 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4d, 0x69, 0x64,
+ 0x69, 0x61, 0x6e, 0x3b, 0x20, 0x45, 0x70, 0x68, 0x61, 0x68, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x45, 0x70, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x48, 0x61, 0x6e, 0x6f, 0x63, 0x68, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x41, 0x62, 0x69, 0x64, 0x61, 0x68, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x45, 0x6c, 0x64, 0x61, 0x61, 0x68, 0x2e, 0x20, 0x41,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72,
+ 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x4b, 0x65, 0x74, 0x75, 0x72, 0x61,
+ 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61,
+ 0x68, 0x61, 0x6d, 0x20, 0x67, 0x61, 0x76, 0x65, 0x20, 0x61, 0x6c, 0x6c,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x2e,
+ 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x62, 0x69, 0x6e, 0x65,
+ 0x73, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x68, 0x61, 0x6d, 0x20, 0x68, 0x61, 0x64, 0x2c, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x67, 0x61, 0x76, 0x65, 0x20, 0x67,
+ 0x69, 0x66, 0x74, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65,
+ 0x6e, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x61, 0x77, 0x61, 0x79,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x77, 0x68, 0x69,
+ 0x6c, 0x65, 0x20, 0x68, 0x65, 0x20, 0x79, 0x65, 0x74, 0x20, 0x6c, 0x69,
+ 0x76, 0x65, 0x64, 0x2c, 0x20, 0x65, 0x61, 0x73, 0x74, 0x77, 0x61, 0x72,
+ 0x64, 0x2c, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65,
+ 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61,
+ 0x6d, 0x27, 0x73, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x2c,
+ 0x20, 0x61, 0x6e, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20,
+ 0x74, 0x68, 0x72, 0x65, 0x65, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x66, 0x69, 0x66, 0x74, 0x65, 0x65, 0x6e, 0x20, 0x79,
+ 0x65, 0x61, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x6e, 0x20,
+ 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x67, 0x61, 0x76, 0x65,
+ 0x20, 0x75, 0x70, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x68, 0x6f, 0x73,
+ 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x65, 0x64, 0x20,
+ 0x69, 0x6e, 0x20, 0x61, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x6f, 0x6c,
+ 0x64, 0x20, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x6c,
+ 0x64, 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66,
+ 0x75, 0x6c, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x61,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20,
+ 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x73,
+ 0x68, 0x6d, 0x61, 0x65, 0x6c, 0x20, 0x62, 0x75, 0x72, 0x69, 0x65, 0x64,
+ 0x20, 0x68, 0x69, 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x63, 0x61, 0x76, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x4d, 0x61, 0x63, 0x68,
+ 0x70, 0x65, 0x6c, 0x61, 0x68, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x45,
+ 0x70, 0x68, 0x72, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f,
+ 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x5a, 0x6f, 0x68, 0x61, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x48, 0x69, 0x74, 0x74, 0x69, 0x74, 0x65, 0x2c, 0x20,
+ 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x62, 0x65, 0x66,
+ 0x6f, 0x72, 0x65, 0x20, 0x4d, 0x61, 0x6d, 0x72, 0x65, 0x3b, 0x20, 0x0a,
+ 0x54, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x77, 0x68,
+ 0x69, 0x63, 0x68, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20,
+ 0x70, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x48, 0x65, 0x74, 0x68, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d,
+ 0x20, 0x62, 0x75, 0x72, 0x69, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77,
+ 0x69, 0x66, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74,
+ 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73,
+ 0x73, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x64, 0x65, 0x61, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20,
+ 0x64, 0x77, 0x65, 0x6c, 0x74, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x4c, 0x61, 0x68, 0x61, 0x69, 0x72,
+ 0x6f, 0x69, 0x2e, 0x20, 0x0a, 0x4e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65,
+ 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67,
+ 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f,
+ 0x66, 0x20, 0x49, 0x73, 0x68, 0x6d, 0x61, 0x65, 0x6c, 0x2c, 0x20, 0x41,
+ 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x27, 0x73, 0x20, 0x73, 0x6f, 0x6e,
+ 0x2c, 0x20, 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x48, 0x61, 0x67, 0x61, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x45, 0x67, 0x79, 0x70, 0x74, 0x69, 0x61,
+ 0x6e, 0x2c, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x27, 0x73, 0x20, 0x68,
+ 0x61, 0x6e, 0x64, 0x6d, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x62, 0x61, 0x72,
+ 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68,
+ 0x61, 0x6d, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e,
+ 0x61, 0x6d, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x49, 0x73, 0x68, 0x6d,
+ 0x61, 0x65, 0x6c, 0x2c, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x69,
+ 0x72, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x63, 0x63,
+ 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68,
+ 0x65, 0x69, 0x72, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72,
+ 0x73, 0x74, 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x49, 0x73,
+ 0x68, 0x6d, 0x61, 0x65, 0x6c, 0x2c, 0x20, 0x4e, 0x65, 0x62, 0x61, 0x6a,
+ 0x6f, 0x74, 0x68, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4b, 0x65, 0x64,
+ 0x61, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x64, 0x62, 0x65,
+ 0x65, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4d, 0x69, 0x62, 0x73,
+ 0x61, 0x6d, 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4d, 0x69, 0x73,
+ 0x68, 0x6d, 0x61, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x44, 0x75, 0x6d,
+ 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4d, 0x61, 0x73, 0x73,
+ 0x61, 0x2c, 0x20, 0x0a, 0x48, 0x61, 0x64, 0x61, 0x72, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x54, 0x65, 0x6d, 0x61, 0x2c, 0x20, 0x4a, 0x65, 0x74,
+ 0x75, 0x72, 0x2c, 0x20, 0x4e, 0x61, 0x70, 0x68, 0x69, 0x73, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4b, 0x65, 0x64, 0x65, 0x6d, 0x61, 0x68,
+ 0x3a, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x49, 0x73, 0x68, 0x6d, 0x61, 0x65, 0x6c, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x2c,
+ 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x74, 0x6f,
+ 0x77, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x79, 0x20,
+ 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x63, 0x61, 0x73, 0x74, 0x6c, 0x65,
+ 0x73, 0x3b, 0x20, 0x74, 0x77, 0x65, 0x6c, 0x76, 0x65, 0x20, 0x70, 0x72,
+ 0x69, 0x6e, 0x63, 0x65, 0x73, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64,
+ 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72,
+ 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x49, 0x73, 0x68, 0x6d, 0x61, 0x65, 0x6c, 0x2c, 0x20, 0x61,
+ 0x6e, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x67, 0x61, 0x76,
+ 0x65, 0x20, 0x75, 0x70, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x68, 0x6f,
+ 0x73, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x65, 0x64, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x64, 0x77, 0x65,
+ 0x6c, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x48, 0x61, 0x76, 0x69,
+ 0x6c, 0x61, 0x68, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x53, 0x68, 0x75,
+ 0x72, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x62,
+ 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x45, 0x67, 0x79, 0x70, 0x74, 0x2c,
+ 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x67, 0x6f, 0x65,
+ 0x73, 0x74, 0x20, 0x74, 0x6f, 0x77, 0x61, 0x72, 0x64, 0x20, 0x41, 0x73,
+ 0x73, 0x79, 0x72, 0x69, 0x61, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x64, 0x69, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72,
+ 0x65, 0x74, 0x68, 0x72, 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x2c,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x27, 0x73, 0x20, 0x73,
+ 0x6f, 0x6e, 0x3a, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x3a,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x79, 0x20, 0x79, 0x65,
+ 0x61, 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e,
+ 0x20, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x52, 0x65, 0x62,
+ 0x65, 0x6b, 0x61, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x69, 0x66, 0x65,
+ 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74,
+ 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x42, 0x65, 0x74, 0x68, 0x75, 0x65,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x79, 0x72, 0x69, 0x61, 0x6e,
+ 0x20, 0x6f, 0x66, 0x20, 0x50, 0x61, 0x64, 0x61, 0x6e, 0x61, 0x72, 0x61,
+ 0x6d, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x73, 0x74, 0x65,
+ 0x72, 0x20, 0x74, 0x6f, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x53, 0x79, 0x72, 0x69, 0x61, 0x6e, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x69, 0x6e,
+ 0x74, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75,
+ 0x73, 0x65, 0x20, 0x73, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x62,
+ 0x61, 0x72, 0x72, 0x65, 0x6e, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x69, 0x6e, 0x74, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x52, 0x65,
+ 0x62, 0x65, 0x6b, 0x61, 0x68, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69,
+ 0x66, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20, 0x73, 0x74, 0x72, 0x75,
+ 0x67, 0x67, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68,
+ 0x65, 0x72, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x68, 0x65,
+ 0x72, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x66, 0x20, 0x69, 0x74, 0x20, 0x62,
+ 0x65, 0x20, 0x73, 0x6f, 0x2c, 0x20, 0x77, 0x68, 0x79, 0x20, 0x61, 0x6d,
+ 0x20, 0x49, 0x20, 0x74, 0x68, 0x75, 0x73, 0x3f, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x73, 0x68, 0x65, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f,
+ 0x20, 0x65, 0x6e, 0x71, 0x75, 0x69, 0x72, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x65,
+ 0x72, 0x2c, 0x20, 0x54, 0x77, 0x6f, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x79, 0x20, 0x77, 0x6f, 0x6d, 0x62, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x77, 0x6f, 0x20, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x20, 0x6f,
+ 0x66, 0x20, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61,
+ 0x74, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x62, 0x6f, 0x77, 0x65, 0x6c, 0x73, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x70, 0x65, 0x6f,
+ 0x70, 0x6c, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65,
+ 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68,
+ 0x61, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6c, 0x64, 0x65, 0x72, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x79, 0x6f, 0x75, 0x6e, 0x67, 0x65, 0x72, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x68, 0x65,
+ 0x72, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65,
+ 0x20, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x77,
+ 0x65, 0x72, 0x65, 0x20, 0x66, 0x75, 0x6c, 0x66, 0x69, 0x6c, 0x6c, 0x65,
+ 0x64, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x77,
+ 0x69, 0x6e, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x65, 0x72, 0x20, 0x77,
+ 0x6f, 0x6d, 0x62, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x63, 0x61, 0x6d, 0x65,
+ 0x20, 0x6f, 0x75, 0x74, 0x20, 0x72, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20,
+ 0x61, 0x6e, 0x20, 0x68, 0x61, 0x69, 0x72, 0x79, 0x20, 0x67, 0x61, 0x72,
+ 0x6d, 0x65, 0x6e, 0x74, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x45, 0x73, 0x61, 0x75, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x75,
+ 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x68, 0x6f, 0x6c,
+ 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x45, 0x73, 0x61, 0x75, 0x27, 0x73, 0x20,
+ 0x68, 0x65, 0x65, 0x6c, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x63,
+ 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x73, 0x63, 0x6f, 0x72,
+ 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x20,
+ 0x77, 0x68, 0x65, 0x6e, 0x20, 0x73, 0x68, 0x65, 0x20, 0x62, 0x61, 0x72,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x79, 0x73, 0x20, 0x67, 0x72,
+ 0x65, 0x77, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x45, 0x73, 0x61, 0x75,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x20, 0x63, 0x75, 0x6e, 0x6e, 0x69,
+ 0x6e, 0x67, 0x20, 0x68, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x61,
+ 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x69, 0x65, 0x6c, 0x64, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4a,
+ 0x61, 0x63, 0x6f, 0x62, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x20, 0x70,
+ 0x6c, 0x61, 0x69, 0x6e, 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x64, 0x77,
+ 0x65, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x65,
+ 0x6e, 0x74, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x73,
+ 0x61, 0x61, 0x63, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x45, 0x73,
+ 0x61, 0x75, 0x2c, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20,
+ 0x68, 0x65, 0x20, 0x64, 0x69, 0x64, 0x20, 0x65, 0x61, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x76, 0x65, 0x6e, 0x69, 0x73, 0x6f,
+ 0x6e, 0x3a, 0x20, 0x62, 0x75, 0x74, 0x20, 0x52, 0x65, 0x62, 0x65, 0x6b,
+ 0x61, 0x68, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x4a, 0x61, 0x63,
+ 0x6f, 0x62, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63,
+ 0x6f, 0x62, 0x20, 0x73, 0x6f, 0x64, 0x20, 0x70, 0x6f, 0x74, 0x74, 0x61,
+ 0x67, 0x65, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x45, 0x73, 0x61, 0x75,
+ 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x66, 0x61, 0x69,
+ 0x6e, 0x74, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x73, 0x61,
+ 0x75, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x4a, 0x61,
+ 0x63, 0x6f, 0x62, 0x2c, 0x20, 0x46, 0x65, 0x65, 0x64, 0x20, 0x6d, 0x65,
+ 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72, 0x61, 0x79, 0x20, 0x74, 0x68, 0x65,
+ 0x65, 0x2c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x72, 0x65, 0x64, 0x20, 0x70, 0x6f,
+ 0x74, 0x74, 0x61, 0x67, 0x65, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x49,
+ 0x20, 0x61, 0x6d, 0x20, 0x66, 0x61, 0x69, 0x6e, 0x74, 0x3a, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x63, 0x61,
+ 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x45, 0x64, 0x6f, 0x6d, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x2c, 0x20, 0x53, 0x65, 0x6c, 0x6c, 0x20, 0x6d, 0x65, 0x20,
+ 0x74, 0x68, 0x69, 0x73, 0x20, 0x64, 0x61, 0x79, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x62, 0x69, 0x72, 0x74, 0x68, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x73, 0x61, 0x75, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c,
+ 0x20, 0x49, 0x20, 0x61, 0x6d, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x69,
+ 0x65, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20,
+ 0x70, 0x72, 0x6f, 0x66, 0x69, 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c,
+ 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x62, 0x69, 0x72, 0x74, 0x68, 0x72,
+ 0x69, 0x67, 0x68, 0x74, 0x20, 0x64, 0x6f, 0x20, 0x74, 0x6f, 0x20, 0x6d,
+ 0x65, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f,
+ 0x62, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x53, 0x77, 0x65, 0x61,
+ 0x72, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x64, 0x61, 0x79, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x73, 0x77, 0x61, 0x72, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x68, 0x69, 0x6d, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x73, 0x6f, 0x6c, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x69, 0x72,
+ 0x74, 0x68, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65,
+ 0x6e, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x67, 0x61, 0x76, 0x65,
+ 0x20, 0x45, 0x73, 0x61, 0x75, 0x20, 0x62, 0x72, 0x65, 0x61, 0x64, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x70, 0x6f, 0x74, 0x74, 0x61, 0x67, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x6c, 0x65, 0x6e, 0x74, 0x69, 0x6c, 0x65, 0x73, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x64, 0x20,
+ 0x65, 0x61, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x72, 0x69, 0x6e,
+ 0x6b, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x6f, 0x73, 0x65, 0x20,
+ 0x75, 0x70, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x6e, 0x74,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x61, 0x79, 0x3a, 0x20, 0x74, 0x68,
+ 0x75, 0x73, 0x20, 0x45, 0x73, 0x61, 0x75, 0x20, 0x64, 0x65, 0x73, 0x70,
+ 0x69, 0x73, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x69, 0x72,
+ 0x74, 0x68, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x61, 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6e, 0x65, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x62, 0x65,
+ 0x73, 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72,
+ 0x73, 0x74, 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6e, 0x65, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x68, 0x61, 0x6d, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x49,
+ 0x73, 0x61, 0x61, 0x63, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68,
+ 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x65, 0x73,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x47, 0x65, 0x72, 0x61, 0x72, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x65, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x47, 0x6f, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x6f,
+ 0x20, 0x45, 0x67, 0x79, 0x70, 0x74, 0x3b, 0x20, 0x64, 0x77, 0x65, 0x6c,
+ 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x49, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x65, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65,
+ 0x65, 0x20, 0x6f, 0x66, 0x3a, 0x20, 0x0a, 0x53, 0x6f, 0x6a, 0x6f, 0x75,
+ 0x72, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c,
+ 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69,
+ 0x6c, 0x6c, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x65,
+ 0x65, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64, 0x2c,
+ 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x67, 0x69, 0x76, 0x65,
+ 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x63,
+ 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x70, 0x65, 0x72,
+ 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x61, 0x74,
+ 0x68, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x49, 0x20, 0x73, 0x77,
+ 0x61, 0x72, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x68, 0x61, 0x6d, 0x20, 0x74, 0x68, 0x79, 0x20, 0x66, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x3b, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x74, 0x68,
+ 0x79, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x75,
+ 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x74, 0x61, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x68,
+ 0x65, 0x61, 0x76, 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x63, 0x6f, 0x75,
+ 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x62,
+ 0x65, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x3b, 0x20, 0x0a,
+ 0x42, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x6f, 0x62, 0x65,
+ 0x79, 0x65, 0x64, 0x20, 0x6d, 0x79, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x70, 0x74, 0x20, 0x6d,
+ 0x79, 0x20, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x2c, 0x20, 0x6d, 0x79,
+ 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x6d, 0x65, 0x6e, 0x74,
+ 0x73, 0x2c, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x74,
+ 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x79, 0x20, 0x6c,
+ 0x61, 0x77, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x73,
+ 0x61, 0x61, 0x63, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x74, 0x20, 0x69, 0x6e,
+ 0x20, 0x47, 0x65, 0x72, 0x61, 0x72, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x61, 0x73,
+ 0x6b, 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x6f, 0x66, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x53, 0x68,
+ 0x65, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x69, 0x73, 0x74,
+ 0x65, 0x72, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68, 0x65, 0x20, 0x66,
+ 0x65, 0x61, 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x61, 0x79,
+ 0x2c, 0x20, 0x53, 0x68, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x79, 0x20,
+ 0x77, 0x69, 0x66, 0x65, 0x3b, 0x20, 0x6c, 0x65, 0x73, 0x74, 0x2c, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x20, 0x68, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64,
+ 0x20, 0x6b, 0x69, 0x6c, 0x6c, 0x20, 0x6d, 0x65, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x52, 0x65, 0x62, 0x65, 0x6b, 0x61, 0x68, 0x3b, 0x20, 0x62, 0x65,
+ 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x73, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x66, 0x61, 0x69, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x6f,
+ 0x6f, 0x6b, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f,
+ 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20,
+ 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61, 0x20, 0x6c, 0x6f, 0x6e, 0x67,
+ 0x20, 0x74, 0x69, 0x6d, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68, 0x20, 0x6b, 0x69,
+ 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x50, 0x68,
+ 0x69, 0x6c, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x6c, 0x6f,
+ 0x6f, 0x6b, 0x65, 0x64, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x61, 0x74, 0x20,
+ 0x61, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x61, 0x77, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20,
+ 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x49, 0x73, 0x61, 0x61,
+ 0x63, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x69,
+ 0x6e, 0x67, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x52, 0x65, 0x62, 0x65,
+ 0x6b, 0x61, 0x68, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x69, 0x6d, 0x65,
+ 0x6c, 0x65, 0x63, 0x68, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20,
+ 0x49, 0x73, 0x61, 0x61, 0x63, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c,
+ 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x73, 0x75, 0x72, 0x65, 0x74, 0x79,
+ 0x20, 0x73, 0x68, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x77, 0x69, 0x66, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x6f,
+ 0x77, 0x20, 0x73, 0x61, 0x69, 0x64, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x2c, 0x20, 0x53, 0x68, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x79,
+ 0x20, 0x73, 0x69, 0x73, 0x74, 0x65, 0x72, 0x3f, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x42, 0x65,
+ 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x49, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x4c, 0x65, 0x73, 0x74, 0x20, 0x49, 0x20, 0x64, 0x69, 0x65,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x57, 0x68, 0x61, 0x74, 0x20,
+ 0x69, 0x73, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x75, 0x73, 0x3f, 0x20, 0x6f, 0x6e, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x65, 0x6f, 0x70, 0x6c,
+ 0x65, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x20, 0x6c, 0x69, 0x67, 0x68,
+ 0x74, 0x6c, 0x79, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x6c, 0x69, 0x65,
+ 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x79, 0x20, 0x77,
+ 0x69, 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x65, 0x73, 0x74, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74,
+ 0x20, 0x67, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x75, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68, 0x20,
+ 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x2c, 0x20,
+ 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x48, 0x65, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x74, 0x68,
+ 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x6f, 0x72,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x73, 0x75, 0x72, 0x65, 0x6c, 0x79, 0x20, 0x62,
+ 0x65, 0x20, 0x70, 0x75, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x65, 0x61,
+ 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x6e, 0x20, 0x49, 0x73,
+ 0x61, 0x61, 0x63, 0x20, 0x73, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x75, 0x6e,
+ 0x64, 0x72, 0x65, 0x64, 0x66, 0x6f, 0x6c, 0x64, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x62,
+ 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e,
+ 0x20, 0x77, 0x61, 0x78, 0x65, 0x64, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x66,
+ 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x67, 0x72, 0x65, 0x77, 0x20, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x20, 0x68,
+ 0x65, 0x20, 0x62, 0x65, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x3a, 0x20, 0x0a, 0x46, 0x6f,
+ 0x72, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x70, 0x6f, 0x73,
+ 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x66,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70,
+ 0x6f, 0x73, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66,
+ 0x20, 0x68, 0x65, 0x72, 0x64, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x50, 0x68, 0x69,
+ 0x6c, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x65, 0x6e, 0x76,
+ 0x69, 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x46, 0x6f,
+ 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x65,
+ 0x6c, 0x6c, 0x73, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x73,
+ 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73, 0x20, 0x68, 0x61, 0x64, 0x20,
+ 0x64, 0x69, 0x67, 0x67, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x61,
+ 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x50, 0x68,
+ 0x69, 0x6c, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x73, 0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x6c, 0x6c,
+ 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x49, 0x73, 0x61,
+ 0x61, 0x63, 0x2c, 0x20, 0x47, 0x6f, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x75, 0x73, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x61, 0x72, 0x74, 0x20, 0x6d, 0x75, 0x63, 0x68, 0x20, 0x6d, 0x69,
+ 0x67, 0x68, 0x74, 0x69, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20,
+ 0x77, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x61,
+ 0x61, 0x63, 0x20, 0x64, 0x65, 0x70, 0x61, 0x72, 0x74, 0x65, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x6e, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x70, 0x69, 0x74, 0x63, 0x68, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x74, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x76, 0x61, 0x6c, 0x6c, 0x65, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x47, 0x65,
+ 0x72, 0x61, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x77, 0x65,
+ 0x6c, 0x74, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x64, 0x69, 0x67,
+ 0x67, 0x65, 0x64, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x68, 0x61, 0x64, 0x20, 0x64, 0x69, 0x67,
+ 0x67, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68,
+ 0x61, 0x6d, 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x50,
+ 0x68, 0x69, 0x6c, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x68,
+ 0x61, 0x64, 0x20, 0x73, 0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x65, 0x61, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x41,
+ 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x69, 0x72, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x20, 0x61, 0x66,
+ 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65,
+ 0x73, 0x20, 0x62, 0x79, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x61, 0x61,
+ 0x63, 0x27, 0x73, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73,
+ 0x20, 0x64, 0x69, 0x67, 0x67, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x6c, 0x65, 0x79, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x61, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x6f, 0x66,
+ 0x20, 0x73, 0x70, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x6e, 0x67, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x68, 0x65, 0x72, 0x64, 0x6d, 0x65, 0x6e, 0x20, 0x6f,
+ 0x66, 0x20, 0x47, 0x65, 0x72, 0x61, 0x72, 0x20, 0x64, 0x69, 0x64, 0x20,
+ 0x73, 0x74, 0x72, 0x69, 0x76, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x49, 0x73, 0x61, 0x61, 0x63, 0x27, 0x73, 0x20, 0x68, 0x65, 0x72, 0x64,
+ 0x6d, 0x65, 0x6e, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c,
+ 0x20, 0x54, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x20, 0x69,
+ 0x73, 0x20, 0x6f, 0x75, 0x72, 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x45, 0x73, 0x65, 0x6b, 0x3b,
+ 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65,
+ 0x79, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x76, 0x65, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x64, 0x69, 0x67, 0x67, 0x65, 0x64, 0x20,
+ 0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x65, 0x6c, 0x6c,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x76, 0x65,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x6c,
+ 0x73, 0x6f, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x63,
+ 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x20, 0x53, 0x69, 0x74,
+ 0x6e, 0x61, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x64, 0x69, 0x67, 0x67, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x6f,
+ 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x3b, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x76, 0x65, 0x20,
+ 0x6e, 0x6f, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e,
+ 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x20, 0x52, 0x65,
+ 0x68, 0x6f, 0x62, 0x6f, 0x74, 0x68, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x46, 0x6f, 0x72,
+ 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20,
+ 0x72, 0x6f, 0x6f, 0x6d, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x75, 0x73, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c,
+ 0x6c, 0x20, 0x62, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x66, 0x75,
+ 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x77,
+ 0x65, 0x6e, 0x74, 0x20, 0x75, 0x70, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x74, 0x68, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x42, 0x65,
+ 0x65, 0x72, 0x73, 0x68, 0x65, 0x62, 0x61, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x61,
+ 0x70, 0x70, 0x65, 0x61, 0x72, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x69, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d,
+ 0x65, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x61, 0x6d, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x41,
+ 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x74, 0x68, 0x79, 0x20, 0x66,
+ 0x61, 0x74, 0x68, 0x65, 0x72, 0x3a, 0x20, 0x66, 0x65, 0x61, 0x72, 0x20,
+ 0x6e, 0x6f, 0x74, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x49, 0x20, 0x61,
+ 0x6d, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x6c,
+ 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x6d, 0x79, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x20, 0x41,
+ 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x27, 0x73, 0x20, 0x73, 0x61, 0x6b,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x62,
+ 0x75, 0x69, 0x6c, 0x64, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c,
+ 0x74, 0x61, 0x72, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x75, 0x70,
+ 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x69, 0x74, 0x63, 0x68, 0x65, 0x64,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x72, 0x65, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x27, 0x73, 0x20, 0x73,
+ 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73, 0x20, 0x64, 0x69, 0x67, 0x67,
+ 0x65, 0x64, 0x20, 0x61, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x2e, 0x20, 0x0a,
+ 0x54, 0x68, 0x65, 0x6e, 0x20, 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65,
+ 0x63, 0x68, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x68,
+ 0x69, 0x6d, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x47, 0x65, 0x72, 0x61,
+ 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x68, 0x75, 0x7a, 0x7a,
+ 0x61, 0x74, 0x68, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x66, 0x72, 0x69, 0x65, 0x6e, 0x64, 0x73, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x50, 0x68, 0x69, 0x63, 0x68, 0x6f, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x69, 0x65, 0x66, 0x20, 0x63, 0x61,
+ 0x70, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x61, 0x72, 0x6d, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x57, 0x68,
+ 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x65,
+ 0x20, 0x79, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x73,
+ 0x65, 0x65, 0x69, 0x6e, 0x67, 0x20, 0x79, 0x65, 0x20, 0x68, 0x61, 0x74,
+ 0x65, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x65, 0x20, 0x61,
+ 0x77, 0x61, 0x79, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x79, 0x6f, 0x75,
+ 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x57, 0x65, 0x20, 0x73, 0x61, 0x77,
+ 0x20, 0x63, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6e, 0x6c, 0x79, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x61, 0x6e,
+ 0x20, 0x6f, 0x61, 0x74, 0x68, 0x20, 0x62, 0x65, 0x74, 0x77, 0x69, 0x78,
+ 0x74, 0x20, 0x75, 0x73, 0x2c, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x62,
+ 0x65, 0x74, 0x77, 0x69, 0x78, 0x74, 0x20, 0x75, 0x73, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6c, 0x65, 0x74, 0x20, 0x75, 0x73, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20,
+ 0x61, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3b, 0x20, 0x0a, 0x54,
+ 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x77, 0x69, 0x6c,
+ 0x74, 0x20, 0x64, 0x6f, 0x20, 0x75, 0x73, 0x20, 0x6e, 0x6f, 0x20, 0x68,
+ 0x75, 0x72, 0x74, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x77, 0x65, 0x20, 0x68,
+ 0x61, 0x76, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x6f, 0x75, 0x63,
+ 0x68, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x61, 0x73, 0x20, 0x77, 0x65, 0x20, 0x68, 0x61, 0x76, 0x65,
+ 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20,
+ 0x62, 0x75, 0x74, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x20, 0x61, 0x77, 0x61, 0x79, 0x20, 0x69, 0x6e,
+ 0x20, 0x70, 0x65, 0x61, 0x63, 0x65, 0x3a, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x61, 0x72, 0x74, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x20, 0x61, 0x20, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x64, 0x69,
+ 0x64, 0x20, 0x65, 0x61, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x72,
+ 0x69, 0x6e, 0x6b, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x72, 0x6f, 0x73, 0x65, 0x20, 0x75, 0x70, 0x20, 0x62,
+ 0x65, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x73, 0x77, 0x61, 0x72, 0x65, 0x20, 0x6f, 0x6e, 0x65,
+ 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x73,
+ 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x61, 0x77, 0x61,
+ 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x64, 0x65, 0x70, 0x61, 0x72, 0x74, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x65, 0x61,
+ 0x63, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20,
+ 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x64, 0x61,
+ 0x79, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x73, 0x61, 0x61,
+ 0x63, 0x27, 0x73, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73,
+ 0x20, 0x63, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x6f, 0x6c, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x63, 0x6f, 0x6e, 0x63,
+ 0x65, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x65, 0x6c, 0x6c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x68, 0x61, 0x64, 0x20, 0x64, 0x69, 0x67, 0x67, 0x65,
+ 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x57, 0x65,
+ 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20,
+ 0x77, 0x61, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x69, 0x74,
+ 0x20, 0x53, 0x68, 0x65, 0x62, 0x61, 0x68, 0x3a, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e,
+ 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, 0x42, 0x65, 0x65, 0x72, 0x73,
+ 0x68, 0x65, 0x62, 0x61, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68,
+ 0x69, 0x73, 0x20, 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x45, 0x73, 0x61, 0x75, 0x20, 0x77, 0x61, 0x73, 0x20, 0x66, 0x6f,
+ 0x72, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x6f, 0x6c,
+ 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x68, 0x65, 0x20, 0x74, 0x6f,
+ 0x6f, 0x6b, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x69, 0x66, 0x65, 0x20, 0x4a,
+ 0x75, 0x64, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61,
+ 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x42, 0x65,
+ 0x65, 0x72, 0x69, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x69, 0x74, 0x74,
+ 0x69, 0x74, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x42, 0x61, 0x73,
+ 0x68, 0x65, 0x6d, 0x61, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x45,
+ 0x6c, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x69, 0x74, 0x74,
+ 0x69, 0x74, 0x65, 0x3a, 0x20, 0x0a, 0x57, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x77, 0x65, 0x72, 0x65, 0x20, 0x61, 0x20, 0x67, 0x72, 0x69, 0x65, 0x66,
+ 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x69, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x52, 0x65, 0x62, 0x65, 0x6b, 0x61, 0x68, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d, 0x65,
+ 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x49, 0x73, 0x61, 0x61,
+ 0x63, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x65, 0x79, 0x65, 0x73, 0x20,
+ 0x77, 0x65, 0x72, 0x65, 0x20, 0x64, 0x69, 0x6d, 0x2c, 0x20, 0x73, 0x6f,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x75,
+ 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x65, 0x65, 0x2c, 0x20,
+ 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x45, 0x73,
+ 0x61, 0x75, 0x20, 0x68, 0x69, 0x73, 0x20, 0x65, 0x6c, 0x64, 0x65, 0x73,
+ 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d,
+ 0x2c, 0x20, 0x4d, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f,
+ 0x6c, 0x64, 0x2c, 0x20, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61, 0x6d, 0x20,
+ 0x49, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x20,
+ 0x6e, 0x6f, 0x77, 0x2c, 0x20, 0x49, 0x20, 0x61, 0x6d, 0x20, 0x6f, 0x6c,
+ 0x64, 0x2c, 0x20, 0x49, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20, 0x6e, 0x6f,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x6f, 0x66,
+ 0x20, 0x6d, 0x79, 0x20, 0x64, 0x65, 0x61, 0x74, 0x68, 0x3a, 0x20, 0x0a,
+ 0x4e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72,
+ 0x65, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72,
+ 0x61, 0x79, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x77, 0x65, 0x61, 0x70, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x74, 0x68,
+ 0x79, 0x20, 0x71, 0x75, 0x69, 0x76, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x6f, 0x77, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x67, 0x6f, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x6d, 0x65, 0x20, 0x73,
+ 0x6f, 0x6d, 0x65, 0x20, 0x76, 0x65, 0x6e, 0x69, 0x73, 0x6f, 0x6e, 0x3b,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x6d,
+ 0x65, 0x20, 0x73, 0x61, 0x76, 0x6f, 0x75, 0x72, 0x79, 0x20, 0x6d, 0x65,
+ 0x61, 0x74, 0x2c, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20,
+ 0x49, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20,
+ 0x6d, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x6d,
+ 0x61, 0x79, 0x20, 0x65, 0x61, 0x74, 0x3b, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x6d, 0x79, 0x20, 0x73, 0x6f, 0x75, 0x6c, 0x20, 0x6d, 0x61, 0x79,
+ 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20,
+ 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x49, 0x20, 0x64, 0x69, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x52, 0x65, 0x62, 0x65, 0x6b,
+ 0x61, 0x68, 0x20, 0x68, 0x65, 0x61, 0x72, 0x64, 0x20, 0x77, 0x68, 0x65,
+ 0x6e, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x73, 0x70, 0x61, 0x6b,
+ 0x65, 0x20, 0x74, 0x6f, 0x20, 0x45, 0x73, 0x61, 0x75, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x45,
+ 0x73, 0x61, 0x75, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x74, 0x6f,
+ 0x20, 0x68, 0x75, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x76, 0x65,
+ 0x6e, 0x69, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x6f, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x74, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x52, 0x65, 0x62, 0x65, 0x6b, 0x61, 0x68,
+ 0x20, 0x73, 0x70, 0x61, 0x6b, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x68, 0x65, 0x72, 0x20, 0x73, 0x6f,
+ 0x6e, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x42,
+ 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x68, 0x65, 0x61,
+ 0x72, 0x64, 0x20, 0x74, 0x68, 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x20, 0x73, 0x70, 0x65, 0x61, 0x6b, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x45, 0x73, 0x61, 0x75, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x72,
+ 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e,
+ 0x67, 0x2c, 0x20, 0x0a, 0x42, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x65,
+ 0x20, 0x76, 0x65, 0x6e, 0x69, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x6d, 0x65, 0x20, 0x73, 0x61,
+ 0x76, 0x6f, 0x75, 0x72, 0x79, 0x20, 0x6d, 0x65, 0x61, 0x74, 0x2c, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x65,
+ 0x61, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x6c, 0x65, 0x73,
+ 0x73, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x62,
+ 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x6d, 0x79, 0x20, 0x64, 0x65, 0x61,
+ 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x4e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x2c, 0x20, 0x6d, 0x79, 0x20, 0x73,
+ 0x6f, 0x6e, 0x2c, 0x20, 0x6f, 0x62, 0x65, 0x79, 0x20, 0x6d, 0x79, 0x20,
+ 0x76, 0x6f, 0x69, 0x63, 0x65, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64,
+ 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x49, 0x20, 0x63, 0x6f, 0x6d, 0x6d,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2e, 0x20, 0x0a, 0x47,
+ 0x6f, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x66, 0x65, 0x74, 0x63, 0x68, 0x20, 0x6d, 0x65, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x74, 0x77, 0x6f,
+ 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x6b, 0x69, 0x64, 0x73, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x6f, 0x61, 0x74, 0x73, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x73, 0x61,
+ 0x76, 0x6f, 0x75, 0x72, 0x79, 0x20, 0x6d, 0x65, 0x61, 0x74, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x74, 0x68, 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x2c, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20, 0x68,
+ 0x65, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x74, 0x68, 0x3a, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c,
+ 0x74, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x74, 0x20, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x20, 0x6d, 0x61,
+ 0x79, 0x20, 0x65, 0x61, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62,
+ 0x6c, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x62, 0x65,
+ 0x66, 0x6f, 0x72, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x64, 0x65, 0x61,
+ 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63,
+ 0x6f, 0x62, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x52,
+ 0x65, 0x62, 0x65, 0x6b, 0x61, 0x68, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6d,
+ 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x2c, 0x20, 0x45, 0x73, 0x61, 0x75, 0x20, 0x6d, 0x79, 0x20, 0x62,
+ 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20,
+ 0x68, 0x61, 0x69, 0x72, 0x79, 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x49, 0x20, 0x61, 0x6d, 0x20, 0x61, 0x20, 0x73, 0x6d,
+ 0x6f, 0x6f, 0x74, 0x68, 0x20, 0x6d, 0x61, 0x6e, 0x3a, 0x20, 0x0a, 0x4d,
+ 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x70, 0x65, 0x72,
+ 0x61, 0x64, 0x76, 0x65, 0x6e, 0x74, 0x75, 0x72, 0x65, 0x20, 0x77, 0x69,
+ 0x6c, 0x6c, 0x20, 0x66, 0x65, 0x65, 0x6c, 0x20, 0x6d, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x73, 0x65, 0x65, 0x6d, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x20,
+ 0x61, 0x73, 0x20, 0x61, 0x20, 0x64, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
+ 0x72, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x63,
+ 0x75, 0x72, 0x73, 0x65, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x6d, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x20,
+ 0x62, 0x6c, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x6f, 0x74, 0x68, 0x65,
+ 0x72, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x55, 0x70, 0x6f, 0x6e, 0x20, 0x6d, 0x65,
+ 0x20, 0x62, 0x65, 0x20, 0x74, 0x68, 0x79, 0x20, 0x63, 0x75, 0x72, 0x73,
+ 0x65, 0x2c, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x3a, 0x20, 0x6f,
+ 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x62, 0x65, 0x79, 0x20, 0x6d, 0x79, 0x20,
+ 0x76, 0x6f, 0x69, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67,
+ 0x6f, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x20, 0x6d, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x77, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66,
+ 0x65, 0x74, 0x63, 0x68, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x6f, 0x74, 0x68,
+ 0x65, 0x72, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20,
+ 0x73, 0x61, 0x76, 0x6f, 0x75, 0x72, 0x79, 0x20, 0x6d, 0x65, 0x61, 0x74,
+ 0x2c, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6c, 0x6f, 0x76,
+ 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x52, 0x65, 0x62,
+ 0x65, 0x6b, 0x61, 0x68, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x67, 0x6f,
+ 0x6f, 0x64, 0x6c, 0x79, 0x20, 0x72, 0x61, 0x69, 0x6d, 0x65, 0x6e, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65, 0x72, 0x20, 0x65, 0x6c, 0x64, 0x65,
+ 0x73, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x45, 0x73, 0x61, 0x75, 0x2c,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x70, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x68,
+ 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x73,
+ 0x6f, 0x6e, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65,
+ 0x20, 0x70, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6b, 0x69,
+ 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 0x69,
+ 0x64, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x6f,
+ 0x61, 0x74, 0x73, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6d, 0x6f,
+ 0x6f, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e,
+ 0x65, 0x63, 0x6b, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x73, 0x68,
+ 0x65, 0x20, 0x67, 0x61, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x76, 0x6f, 0x75, 0x72, 0x79, 0x20, 0x6d, 0x65, 0x61, 0x74, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x72, 0x65, 0x61,
+ 0x64, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x73, 0x68, 0x65,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x70, 0x72, 0x65, 0x70, 0x61, 0x72, 0x65,
+ 0x64, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x68, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65, 0x72, 0x20,
+ 0x73, 0x6f, 0x6e, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x4d, 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x48, 0x65, 0x72, 0x65, 0x20, 0x61, 0x6d, 0x20, 0x49,
+ 0x3b, 0x20, 0x77, 0x68, 0x6f, 0x20, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x2c, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x3f, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x49, 0x20, 0x61,
+ 0x6d, 0x20, 0x45, 0x73, 0x61, 0x75, 0x20, 0x74, 0x68, 0x79, 0x20, 0x66,
+ 0x69, 0x72, 0x73, 0x74, 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x3b, 0x20, 0x49,
+ 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x61,
+ 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x73, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x62, 0x61, 0x64, 0x65, 0x73, 0x74, 0x20,
+ 0x6d, 0x65, 0x3a, 0x20, 0x61, 0x72, 0x69, 0x73, 0x65, 0x2c, 0x20, 0x49,
+ 0x20, 0x70, 0x72, 0x61, 0x79, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20,
+ 0x73, 0x69, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x61, 0x74, 0x20,
+ 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x76, 0x65, 0x6e, 0x69, 0x73, 0x6f,
+ 0x6e, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x73, 0x6f, 0x75, 0x6c, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x6c, 0x65,
+ 0x73, 0x73, 0x20, 0x6d, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x2c,
+ 0x20, 0x48, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x69, 0x74, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73,
+ 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x73,
+ 0x6f, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x6c, 0x79, 0x2c, 0x20, 0x6d,
+ 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x3f, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x63, 0x61,
+ 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x62, 0x72, 0x6f,
+ 0x75, 0x67, 0x68, 0x74, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x6d,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x61, 0x61,
+ 0x63, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x2c, 0x20, 0x43, 0x6f, 0x6d, 0x65, 0x20,
+ 0x6e, 0x65, 0x61, 0x72, 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72, 0x61, 0x79,
+ 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x49, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x66, 0x65, 0x65, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x65, 0x2c, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x2c,
+ 0x20, 0x77, 0x68, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x62, 0x65, 0x20, 0x6d, 0x79, 0x20, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x45, 0x73, 0x61, 0x75, 0x20, 0x6f, 0x72,
+ 0x20, 0x6e, 0x6f, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a,
+ 0x61, 0x63, 0x6f, 0x62, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x6e, 0x65,
+ 0x61, 0x72, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x49, 0x73, 0x61, 0x61,
+ 0x63, 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x66, 0x65, 0x6c,
+ 0x74, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x65, 0x20, 0x76, 0x6f, 0x69,
+ 0x63, 0x65, 0x20, 0x69, 0x73, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x27,
+ 0x73, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x2c, 0x20, 0x62, 0x75, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x61,
+ 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x45, 0x73, 0x61, 0x75, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x73, 0x63, 0x65, 0x72,
+ 0x6e, 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x6e, 0x6f, 0x74, 0x2c,
+ 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x68, 0x61, 0x69, 0x72, 0x79, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x45, 0x73,
+ 0x61, 0x75, 0x27, 0x73, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x3a, 0x20,
+ 0x73, 0x6f, 0x20, 0x68, 0x65, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65,
+ 0x64, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x41, 0x72, 0x74,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x6d, 0x79, 0x20, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x45, 0x73, 0x61, 0x75, 0x3f, 0x20,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x49, 0x20, 0x61, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x72, 0x69,
+ 0x6e, 0x67, 0x20, 0x69, 0x74, 0x20, 0x6e, 0x65, 0x61, 0x72, 0x20, 0x74,
+ 0x6f, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x65, 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20,
+ 0x6d, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x27, 0x73, 0x20, 0x76, 0x65, 0x6e,
+ 0x69, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d,
+ 0x79, 0x20, 0x73, 0x6f, 0x75, 0x6c, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62,
+ 0x6c, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2e, 0x20, 0x41,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68,
+ 0x74, 0x20, 0x69, 0x74, 0x20, 0x6e, 0x65, 0x61, 0x72, 0x20, 0x74, 0x6f,
+ 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x64, 0x69, 0x64, 0x20, 0x65, 0x61, 0x74, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74,
+ 0x20, 0x68, 0x69, 0x6d, 0x20, 0x77, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x72, 0x61, 0x6e, 0x6b, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c,
+ 0x20, 0x43, 0x6f, 0x6d, 0x65, 0x20, 0x6e, 0x65, 0x61, 0x72, 0x20, 0x6e,
+ 0x6f, 0x77, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6b, 0x69, 0x73, 0x73,
+ 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6d,
+ 0x65, 0x20, 0x6e, 0x65, 0x61, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6b, 0x69, 0x73, 0x73, 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x6d, 0x65, 0x6c, 0x6c,
+ 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6d, 0x65, 0x6c, 0x6c,
+ 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x72, 0x61, 0x69, 0x6d,
+ 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x6c, 0x65,
+ 0x73, 0x73, 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x53, 0x65, 0x65, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6d, 0x65, 0x6c, 0x6c, 0x20, 0x6f,
+ 0x66, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20,
+ 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6d, 0x65, 0x6c, 0x6c,
+ 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20,
+ 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x62, 0x6c, 0x65, 0x73,
+ 0x73, 0x65, 0x64, 0x3a, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x72, 0x65, 0x66,
+ 0x6f, 0x72, 0x65, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x67, 0x69, 0x76, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x64, 0x65, 0x77, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65, 0x61, 0x76,
+ 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x61, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x70, 0x6c, 0x65, 0x6e, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x20,
+ 0x63, 0x6f, 0x72, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x6e,
+ 0x65, 0x3a, 0x20, 0x0a, 0x4c, 0x65, 0x74, 0x20, 0x70, 0x65, 0x6f, 0x70,
+ 0x6c, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65,
+ 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x20, 0x62, 0x6f, 0x77, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3a, 0x20, 0x62, 0x65, 0x20,
+ 0x6c, 0x6f, 0x72, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68,
+ 0x79, 0x20, 0x62, 0x72, 0x65, 0x74, 0x68, 0x72, 0x65, 0x6e, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x6d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x73, 0x6f, 0x6e,
+ 0x73, 0x20, 0x62, 0x6f, 0x77, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x20, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3a, 0x20, 0x63, 0x75, 0x72, 0x73,
+ 0x65, 0x64, 0x20, 0x62, 0x65, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20,
+ 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x75, 0x72,
+ 0x73, 0x65, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x62,
+ 0x65, 0x20, 0x68, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x62, 0x6c,
+ 0x65, 0x73, 0x73, 0x65, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d,
+ 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x61,
+ 0x73, 0x20, 0x73, 0x6f, 0x6f, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x49, 0x73,
+ 0x61, 0x61, 0x63, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65,
+ 0x20, 0x61, 0x6e, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x62,
+ 0x6c, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x4a, 0x61, 0x63, 0x6f,
+ 0x62, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x79, 0x65, 0x74, 0x20, 0x73, 0x63, 0x61,
+ 0x72, 0x63, 0x65, 0x20, 0x67, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x75, 0x74,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72,
+ 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x49, 0x73,
+ 0x61, 0x61, 0x63, 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x61, 0x74, 0x68,
+ 0x65, 0x72, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x45, 0x73, 0x61,
+ 0x75, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65,
+ 0x72, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x66, 0x72,
+ 0x6f, 0x6d, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x75, 0x6e, 0x74, 0x69,
+ 0x6e, 0x67, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x64,
+ 0x65, 0x20, 0x73, 0x61, 0x76, 0x6f, 0x75, 0x72, 0x79, 0x20, 0x6d, 0x65,
+ 0x61, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x75,
+ 0x67, 0x68, 0x74, 0x20, 0x69, 0x74, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72,
+ 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x6d, 0x79, 0x20, 0x66, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x61, 0x72, 0x69, 0x73, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x65, 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x27, 0x73, 0x20, 0x76, 0x65, 0x6e, 0x69,
+ 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68,
+ 0x79, 0x20, 0x73, 0x6f, 0x75, 0x6c, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62,
+ 0x6c, 0x65, 0x73, 0x73, 0x20, 0x6d, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x57, 0x68,
+ 0x6f, 0x20, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x3f, 0x20,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x49, 0x20, 0x61, 0x6d, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x6f,
+ 0x6e, 0x2c, 0x20, 0x74, 0x68, 0x79, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74,
+ 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x45, 0x73, 0x61, 0x75, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x74, 0x72,
+ 0x65, 0x6d, 0x62, 0x6c, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x79, 0x20,
+ 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x69, 0x6e, 0x67, 0x6c, 0x79, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x57,
+ 0x68, 0x6f, 0x3f, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73,
+ 0x20, 0x68, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x74,
+ 0x68, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x76, 0x65, 0x6e, 0x69,
+ 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x72, 0x6f,
+ 0x75, 0x67, 0x68, 0x74, 0x20, 0x69, 0x74, 0x20, 0x6d, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x65,
+ 0x61, 0x74, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x63, 0x61, 0x6d, 0x65, 0x73, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64,
+ 0x20, 0x68, 0x69, 0x6d, 0x3f, 0x20, 0x79, 0x65, 0x61, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x62, 0x65, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x45, 0x73,
+ 0x61, 0x75, 0x20, 0x68, 0x65, 0x61, 0x72, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x68, 0x65,
+ 0x20, 0x63, 0x72, 0x69, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x61, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x62, 0x69,
+ 0x74, 0x74, 0x65, 0x72, 0x20, 0x63, 0x72, 0x79, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20,
+ 0x42, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x65, 0x76,
+ 0x65, 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x2c, 0x20,
+ 0x4f, 0x20, 0x6d, 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x54, 0x68, 0x79, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68,
+ 0x65, 0x72, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x73, 0x75, 0x62, 0x74, 0x69, 0x6c, 0x74, 0x79, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x74, 0x61, 0x6b, 0x65,
+ 0x6e, 0x20, 0x61, 0x77, 0x61, 0x79, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62,
+ 0x6c, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49,
+ 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x68, 0x65, 0x20, 0x72, 0x69, 0x67,
+ 0x68, 0x74, 0x6c, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x64, 0x20, 0x4a,
+ 0x61, 0x63, 0x6f, 0x62, 0x3f, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68, 0x65,
+ 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x61,
+ 0x6e, 0x74, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x20, 0x74, 0x68, 0x65, 0x73,
+ 0x65, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x3a,
+ 0x20, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x61, 0x77, 0x61,
+ 0x79, 0x20, 0x6d, 0x79, 0x20, 0x62, 0x69, 0x72, 0x74, 0x68, 0x72, 0x69,
+ 0x67, 0x68, 0x74, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x62, 0x65,
+ 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x68, 0x65,
+ 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20,
+ 0x61, 0x77, 0x61, 0x79, 0x20, 0x6d, 0x79, 0x20, 0x62, 0x6c, 0x65, 0x73,
+ 0x73, 0x69, 0x6e, 0x67, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x48, 0x61, 0x73, 0x74, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x73,
+ 0x65, 0x72, 0x76, 0x65, 0x64, 0x20, 0x61, 0x20, 0x62, 0x6c, 0x65, 0x73,
+ 0x73, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x65, 0x3f,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20,
+ 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x45,
+ 0x73, 0x61, 0x75, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c,
+ 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x6d, 0x61, 0x64, 0x65,
+ 0x20, 0x68, 0x69, 0x6d, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6c, 0x6f, 0x72,
+ 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x62, 0x72, 0x65, 0x74, 0x68, 0x72, 0x65, 0x6e, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x49, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e,
+ 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x63, 0x6f, 0x72, 0x6e, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x61, 0x76,
+ 0x65, 0x20, 0x49, 0x20, 0x73, 0x75, 0x73, 0x74, 0x61, 0x69, 0x6e, 0x65,
+ 0x64, 0x20, 0x68, 0x69, 0x6d, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77,
+ 0x68, 0x61, 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x49, 0x20,
+ 0x64, 0x6f, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x6f, 0x6e,
+ 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x73, 0x61, 0x75, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x48, 0x61,
+ 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x62, 0x75, 0x74, 0x20,
+ 0x6f, 0x6e, 0x65, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67,
+ 0x2c, 0x20, 0x6d, 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x3f,
+ 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x65,
+ 0x76, 0x65, 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x2c,
+ 0x20, 0x4f, 0x20, 0x6d, 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72,
+ 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x73, 0x61, 0x75, 0x20, 0x6c,
+ 0x69, 0x66, 0x74, 0x65, 0x64, 0x20, 0x75, 0x70, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x77, 0x65, 0x70, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49,
+ 0x73, 0x61, 0x61, 0x63, 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x65, 0x64,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f,
+ 0x6c, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x79, 0x20, 0x64, 0x77, 0x65, 0x6c,
+ 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74, 0x6e, 0x65, 0x73,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x65, 0x77, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65,
+ 0x61, 0x76, 0x65, 0x6e, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x62,
+ 0x6f, 0x76, 0x65, 0x3b, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x62, 0x79,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x6c, 0x69,
+ 0x76, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c,
+ 0x74, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x69, 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f,
+ 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x20, 0x77,
+ 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c,
+ 0x74, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x79, 0x6f, 0x6b, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6f, 0x66,
+ 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6e, 0x65, 0x63, 0x6b, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x73, 0x61, 0x75, 0x20, 0x68, 0x61,
+ 0x74, 0x65, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x62, 0x65,
+ 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x68,
+ 0x65, 0x72, 0x65, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73,
+ 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x45, 0x73, 0x61, 0x75, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x69, 0x6e,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x65, 0x61, 0x72, 0x74, 0x2c, 0x20,
+ 0x54, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x6d, 0x6f, 0x75, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x6d, 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x61,
+ 0x72, 0x65, 0x20, 0x61, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x3b, 0x20,
+ 0x74, 0x68, 0x65, 0x6e, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x49, 0x20,
+ 0x73, 0x6c, 0x61, 0x79, 0x20, 0x6d, 0x79, 0x20, 0x62, 0x72, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x77, 0x6f,
+ 0x72, 0x64, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x73, 0x61, 0x75, 0x20,
+ 0x68, 0x65, 0x72, 0x20, 0x65, 0x6c, 0x64, 0x65, 0x72, 0x20, 0x73, 0x6f,
+ 0x6e, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x6c, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x52, 0x65, 0x62, 0x65, 0x6b, 0x61, 0x68, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x74,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20,
+ 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x68, 0x65, 0x72, 0x20, 0x79, 0x6f,
+ 0x75, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64,
+ 0x2c, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65,
+ 0x72, 0x20, 0x45, 0x73, 0x61, 0x75, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x74,
+ 0x6f, 0x75, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x65,
+ 0x2c, 0x20, 0x64, 0x6f, 0x74, 0x68, 0x20, 0x63, 0x6f, 0x6d, 0x66, 0x6f,
+ 0x72, 0x74, 0x20, 0x68, 0x69, 0x6d, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20,
+ 0x70, 0x75, 0x72, 0x70, 0x6f, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f,
+ 0x20, 0x6b, 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2e, 0x20,
+ 0x0a, 0x4e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f,
+ 0x72, 0x65, 0x2c, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20,
+ 0x6f, 0x62, 0x65, 0x79, 0x20, 0x6d, 0x79, 0x20, 0x76, 0x6f, 0x69, 0x63,
+ 0x65, 0x3b, 0x20, 0x61, 0x72, 0x69, 0x73, 0x65, 0x2c, 0x20, 0x66, 0x6c,
+ 0x65, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x74, 0x6f, 0x20, 0x4c,
+ 0x61, 0x62, 0x61, 0x6e, 0x20, 0x6d, 0x79, 0x20, 0x62, 0x72, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x48, 0x61, 0x72, 0x61, 0x6e,
+ 0x3b, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x61, 0x72, 0x72, 0x79,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61, 0x20,
+ 0x66, 0x65, 0x77, 0x20, 0x64, 0x61, 0x79, 0x73, 0x2c, 0x20, 0x75, 0x6e,
+ 0x74, 0x69, 0x6c, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x72, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x66, 0x75, 0x72, 0x79, 0x20, 0x74,
+ 0x75, 0x72, 0x6e, 0x20, 0x61, 0x77, 0x61, 0x79, 0x3b, 0x20, 0x0a, 0x55,
+ 0x6e, 0x74, 0x69, 0x6c, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x72, 0x6f,
+ 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x61, 0x6e, 0x67, 0x65, 0x72,
+ 0x20, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x77, 0x61, 0x79, 0x20, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x67, 0x65, 0x74, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x64, 0x6f, 0x6e,
+ 0x65, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x3a, 0x20, 0x74, 0x68,
+ 0x65, 0x6e, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x73, 0x65,
+ 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x65, 0x74, 0x63,
+ 0x68, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x74, 0x68, 0x65, 0x6e, 0x63, 0x65, 0x3a, 0x20, 0x77, 0x68, 0x79, 0x20,
+ 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x49, 0x20, 0x62, 0x65, 0x20,
+ 0x64, 0x65, 0x70, 0x72, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x6c, 0x73,
+ 0x6f, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x62, 0x6f, 0x74,
+ 0x68, 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x64, 0x61, 0x79,
+ 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x52, 0x65, 0x62, 0x65, 0x6b,
+ 0x61, 0x68, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x49,
+ 0x73, 0x61, 0x61, 0x63, 0x2c, 0x20, 0x49, 0x20, 0x61, 0x6d, 0x20, 0x77,
+ 0x65, 0x61, 0x72, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x6c,
+ 0x69, 0x66, 0x65, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68,
+ 0x74, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x65, 0x74, 0x68,
+ 0x3a, 0x20, 0x69, 0x66, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x74,
+ 0x61, 0x6b, 0x65, 0x20, 0x61, 0x20, 0x77, 0x69, 0x66, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74,
+ 0x65, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x65, 0x74, 0x68, 0x2c,
+ 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65,
+ 0x73, 0x65, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, 0x72, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x75, 0x67,
+ 0x68, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20,
+ 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6d,
+ 0x79, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x20, 0x64, 0x6f, 0x20, 0x6d, 0x65,
+ 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63,
+ 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f,
+ 0x62, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73,
+ 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x54, 0x68, 0x6f, 0x75,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74,
+ 0x61, 0x6b, 0x65, 0x20, 0x61, 0x20, 0x77, 0x69, 0x66, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74,
+ 0x65, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61,
+ 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x72, 0x69, 0x73, 0x65, 0x2c, 0x20, 0x67,
+ 0x6f, 0x20, 0x74, 0x6f, 0x20, 0x50, 0x61, 0x64, 0x61, 0x6e, 0x61, 0x72,
+ 0x61, 0x6d, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68,
+ 0x6f, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x42, 0x65, 0x74, 0x68,
+ 0x75, 0x65, 0x6c, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6d, 0x6f, 0x74, 0x68,
+ 0x65, 0x72, 0x27, 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x20, 0x61, 0x20, 0x77, 0x69, 0x66, 0x65, 0x20, 0x66, 0x72,
+ 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x65, 0x72,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x6d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20,
+ 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x41, 0x6c, 0x6d, 0x69, 0x67, 0x68,
+ 0x74, 0x79, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x65,
+ 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x66, 0x75,
+ 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69,
+ 0x70, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x65,
+ 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x6d, 0x75, 0x6c, 0x74,
+ 0x69, 0x74, 0x75, 0x64, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x70, 0x65, 0x6f,
+ 0x70, 0x6c, 0x65, 0x3b, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x67, 0x69,
+ 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x62, 0x6c, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20,
+ 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3b, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x65, 0x73,
+ 0x74, 0x20, 0x69, 0x6e, 0x68, 0x65, 0x72, 0x69, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x61, 0x72, 0x74, 0x20,
+ 0x61, 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x2c, 0x20,
+ 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x67, 0x61,
+ 0x76, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72, 0x61,
+ 0x68, 0x61, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x73,
+ 0x61, 0x61, 0x63, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x77, 0x61,
+ 0x79, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20,
+ 0x50, 0x61, 0x64, 0x61, 0x6e, 0x61, 0x72, 0x61, 0x6d, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x2c, 0x20, 0x73, 0x6f,
+ 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x42, 0x65, 0x74, 0x68, 0x75, 0x65, 0x6c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x79, 0x72, 0x69, 0x61, 0x6e, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x6f, 0x66, 0x20, 0x52, 0x65, 0x62, 0x65, 0x6b, 0x61, 0x68, 0x2c,
+ 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x27, 0x73, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x45, 0x73, 0x61, 0x75, 0x27, 0x73, 0x20, 0x6d, 0x6f, 0x74, 0x68,
+ 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x57, 0x68, 0x65, 0x6e, 0x20, 0x45, 0x73,
+ 0x61, 0x75, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x68, 0x61, 0x64, 0x20, 0x62, 0x6c,
+ 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x68, 0x69,
+ 0x6d, 0x20, 0x61, 0x77, 0x61, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x50, 0x61,
+ 0x64, 0x61, 0x6e, 0x61, 0x72, 0x61, 0x6d, 0x2c, 0x20, 0x74, 0x6f, 0x20,
+ 0x74, 0x61, 0x6b, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61, 0x20, 0x77,
+ 0x69, 0x66, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x6e, 0x63, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x61, 0x73, 0x20, 0x68, 0x65, 0x20, 0x62, 0x6c, 0x65, 0x73,
+ 0x73, 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x68, 0x65, 0x20, 0x67,
+ 0x61, 0x76, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61, 0x20, 0x63, 0x68,
+ 0x61, 0x72, 0x67, 0x65, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67,
+ 0x2c, 0x20, 0x54, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x61, 0x20,
+ 0x77, 0x69, 0x66, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x64, 0x61, 0x75, 0x67, 0x68, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x3b, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20,
+ 0x6f, 0x62, 0x65, 0x79, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x66,
+ 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x6d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f, 0x6e, 0x65, 0x20, 0x74,
+ 0x6f, 0x20, 0x50, 0x61, 0x64, 0x61, 0x6e, 0x61, 0x72, 0x61, 0x6d, 0x3b,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x73, 0x61, 0x75, 0x20, 0x73,
+ 0x65, 0x65, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x20, 0x70,
+ 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x49,
+ 0x73, 0x61, 0x61, 0x63, 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x3b, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x6e, 0x20, 0x77,
+ 0x65, 0x6e, 0x74, 0x20, 0x45, 0x73, 0x61, 0x75, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x49, 0x73, 0x68, 0x6d, 0x61, 0x65, 0x6c, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20,
+ 0x4d, 0x61, 0x68, 0x61, 0x6c, 0x61, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x20, 0x6f, 0x66,
+ 0x20, 0x49, 0x73, 0x68, 0x6d, 0x61, 0x65, 0x6c, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x68, 0x61, 0x6d, 0x27, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x73, 0x74, 0x65, 0x72, 0x20, 0x6f,
+ 0x66, 0x20, 0x4e, 0x65, 0x62, 0x61, 0x6a, 0x6f, 0x74, 0x68, 0x2c, 0x20,
+ 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69,
+ 0x66, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63,
+ 0x6f, 0x62, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20,
+ 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x42, 0x65, 0x65, 0x72, 0x73, 0x68, 0x65,
+ 0x62, 0x61, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x6e, 0x74,
+ 0x20, 0x74, 0x6f, 0x77, 0x61, 0x72, 0x64, 0x20, 0x48, 0x61, 0x72, 0x61,
+ 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x6c,
+ 0x69, 0x67, 0x68, 0x74, 0x65, 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20,
+ 0x61, 0x20, 0x63, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x70, 0x6c,
+ 0x61, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x61, 0x72,
+ 0x72, 0x69, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x2c, 0x20, 0x62, 0x65,
+ 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x75,
+ 0x6e, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x65, 0x74, 0x3b, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x6e, 0x65, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x6c, 0x61,
+ 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x75, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x70, 0x69, 0x6c, 0x6c, 0x6f, 0x77, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6c, 0x61, 0x79, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65,
+ 0x20, 0x74, 0x6f, 0x20, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x72, 0x65, 0x61, 0x6d,
+ 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x68, 0x6f,
+ 0x6c, 0x64, 0x20, 0x61, 0x20, 0x6c, 0x61, 0x64, 0x64, 0x65, 0x72, 0x20,
+ 0x73, 0x65, 0x74, 0x20, 0x75, 0x70, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x70, 0x20, 0x6f, 0x66, 0x20,
+ 0x69, 0x74, 0x20, 0x72, 0x65, 0x61, 0x63, 0x68, 0x65, 0x64, 0x20, 0x74,
+ 0x6f, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x61, 0x73, 0x63, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x65, 0x73, 0x63, 0x65, 0x6e, 0x64,
+ 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x6e, 0x20, 0x69, 0x74, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x74,
+ 0x6f, 0x6f, 0x64, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20, 0x69, 0x74,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20,
+ 0x49, 0x20, 0x61, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x68, 0x61, 0x6d, 0x20, 0x74, 0x68, 0x79, 0x20, 0x66, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x49, 0x73, 0x61, 0x61,
+ 0x63, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20,
+ 0x77, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x6c, 0x69, 0x65, 0x73, 0x74, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x49, 0x20, 0x67,
+ 0x69, 0x76, 0x65, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64, 0x3b,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65,
+ 0x65, 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20,
+ 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x75, 0x73, 0x74, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x74, 0x20, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x20,
+ 0x61, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x65, 0x73, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x73, 0x74, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6e, 0x6f, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x75, 0x74, 0x68, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x65,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x73, 0x65, 0x65, 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6c,
+ 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x20, 0x62, 0x65, 0x20, 0x62, 0x6c, 0x65, 0x73,
+ 0x73, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x2c, 0x20, 0x62,
+ 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x61, 0x6d, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6b, 0x65, 0x65, 0x70,
+ 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x6c, 0x6c,
+ 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x73, 0x20, 0x77, 0x68, 0x69, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x67, 0x6f, 0x65,
+ 0x73, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20,
+ 0x61, 0x67, 0x61, 0x69, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x69, 0x73, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x3b, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74,
+ 0x20, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c,
+ 0x20, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76,
+ 0x65, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65,
+ 0x20, 0x73, 0x70, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x61, 0x77, 0x61, 0x6b, 0x65,
+ 0x64, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x53, 0x75, 0x72,
+ 0x65, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20,
+ 0x70, 0x6c, 0x61, 0x63, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49,
+ 0x20, 0x6b, 0x6e, 0x65, 0x77, 0x20, 0x69, 0x74, 0x20, 0x6e, 0x6f, 0x74,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x61, 0x66, 0x72, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x48, 0x6f, 0x77, 0x20,
+ 0x64, 0x72, 0x65, 0x61, 0x64, 0x66, 0x75, 0x6c, 0x20, 0x69, 0x73, 0x20,
+ 0x74, 0x68, 0x69, 0x73, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x21, 0x20,
+ 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x6e, 0x65,
+ 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x62, 0x75, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x47, 0x6f, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69,
+ 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x74,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20,
+ 0x72, 0x6f, 0x73, 0x65, 0x20, 0x75, 0x70, 0x20, 0x65, 0x61, 0x72, 0x6c,
+ 0x79, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72,
+ 0x6e, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f,
+ 0x6f, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x6e, 0x65,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64,
+ 0x20, 0x70, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x70, 0x69, 0x6c, 0x6c, 0x6f, 0x77, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x65, 0x74, 0x20, 0x69, 0x74, 0x20, 0x75, 0x70, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x70, 0x69, 0x6c, 0x6c, 0x61, 0x72,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x6f, 0x75, 0x72, 0x65, 0x64,
+ 0x20, 0x6f, 0x69, 0x6c, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x74, 0x6f, 0x70, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c,
+ 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x6c, 0x61,
+ 0x63, 0x65, 0x20, 0x42, 0x65, 0x74, 0x68, 0x65, 0x6c, 0x3a, 0x20, 0x62,
+ 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x69, 0x74, 0x79,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20,
+ 0x4c, 0x75, 0x7a, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x69, 0x72, 0x73, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a,
+ 0x61, 0x63, 0x6f, 0x62, 0x20, 0x76, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x61,
+ 0x20, 0x76, 0x6f, 0x77, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67,
+ 0x2c, 0x20, 0x49, 0x66, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x77, 0x69, 0x6c,
+ 0x6c, 0x20, 0x62, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6b,
+ 0x65, 0x65, 0x70, 0x20, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x69, 0x73, 0x20, 0x77, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x49, 0x20, 0x67, 0x6f, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69,
+ 0x6c, 0x6c, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x6d, 0x65, 0x20, 0x62,
+ 0x72, 0x65, 0x61, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x61, 0x74, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x61, 0x69, 0x6d, 0x65, 0x6e, 0x74,
+ 0x20, 0x74, 0x6f, 0x20, 0x70, 0x75, 0x74, 0x20, 0x6f, 0x6e, 0x2c, 0x20,
+ 0x0a, 0x53, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x63,
+ 0x6f, 0x6d, 0x65, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x20, 0x74, 0x6f,
+ 0x20, 0x6d, 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73,
+ 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x65,
+ 0x61, 0x63, 0x65, 0x3b, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x62, 0x65, 0x20, 0x6d, 0x79, 0x20, 0x47, 0x6f, 0x64, 0x3a, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x74,
+ 0x6f, 0x6e, 0x65, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x49,
+ 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x73, 0x65, 0x74, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x61, 0x20, 0x70, 0x69, 0x6c, 0x6c, 0x61, 0x72, 0x2c, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x47, 0x6f, 0x64,
+ 0x27, 0x73, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74,
+ 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x6d, 0x65, 0x20, 0x49, 0x20, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x73, 0x75, 0x72, 0x65, 0x6c, 0x79, 0x20, 0x67,
+ 0x69, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x6e, 0x74,
+ 0x68, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2e,
+ 0x20, 0x0a, 0x54, 0x68, 0x65, 0x6e, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62,
+ 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x6e, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x6c, 0x6f, 0x6f, 0x6b,
+ 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x68, 0x6f,
+ 0x6c, 0x64, 0x20, 0x61, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x72, 0x65,
+ 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x73, 0x68, 0x65, 0x65, 0x70, 0x20, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x20,
+ 0x62, 0x79, 0x20, 0x69, 0x74, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6f,
+ 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77,
+ 0x65, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x61, 0x74,
+ 0x65, 0x72, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x67,
+ 0x72, 0x65, 0x61, 0x74, 0x20, 0x73, 0x74, 0x6f, 0x6e, 0x65, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x65, 0x6c, 0x6c, 0x27, 0x73, 0x20, 0x6d, 0x6f, 0x75, 0x74, 0x68,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x74, 0x68,
+ 0x65, 0x72, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x20, 0x67,
+ 0x61, 0x74, 0x68, 0x65, 0x72, 0x65, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x6e, 0x65, 0x20, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x65, 0x6c, 0x6c,
+ 0x27, 0x73, 0x20, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x68, 0x65, 0x65, 0x70, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x70, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f,
+ 0x6e, 0x65, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x20, 0x75, 0x70, 0x6f,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x27, 0x73,
+ 0x20, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20,
+ 0x4d, 0x79, 0x20, 0x62, 0x72, 0x65, 0x74, 0x68, 0x72, 0x65, 0x6e, 0x2c,
+ 0x20, 0x77, 0x68, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x62, 0x65, 0x20, 0x79,
+ 0x65, 0x3f, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4f, 0x66, 0x20, 0x48, 0x61, 0x72,
+ 0x61, 0x6e, 0x20, 0x61, 0x72, 0x65, 0x20, 0x77, 0x65, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x4b,
+ 0x6e, 0x6f, 0x77, 0x20, 0x79, 0x65, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20,
+ 0x4e, 0x61, 0x68, 0x6f, 0x72, 0x3f, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x57, 0x65,
+ 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x49,
+ 0x73, 0x20, 0x68, 0x65, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x3f, 0x20, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x48, 0x65, 0x20, 0x69, 0x73, 0x20, 0x77, 0x65, 0x6c, 0x6c,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x2c, 0x20, 0x52, 0x61, 0x63, 0x68, 0x65, 0x6c, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x20, 0x63,
+ 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x68, 0x65, 0x65, 0x70, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20,
+ 0x4c, 0x6f, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x79, 0x65,
+ 0x74, 0x20, 0x68, 0x69, 0x67, 0x68, 0x20, 0x64, 0x61, 0x79, 0x2c, 0x20,
+ 0x6e, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x69,
+ 0x74, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x73,
+ 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x67, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68,
+ 0x65, 0x72, 0x3a, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x20, 0x79, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x68, 0x65, 0x65, 0x70, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x67, 0x6f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66,
+ 0x65, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x57, 0x65, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x2c,
+ 0x20, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x20, 0x62, 0x65,
+ 0x20, 0x67, 0x61, 0x74, 0x68, 0x65, 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f,
+ 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x72, 0x6f,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x6e, 0x65,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x65,
+ 0x6c, 0x6c, 0x27, 0x73, 0x20, 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x3b, 0x20,
+ 0x74, 0x68, 0x65, 0x6e, 0x20, 0x77, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65,
+ 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x68, 0x65, 0x65, 0x70, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20,
+ 0x68, 0x65, 0x20, 0x79, 0x65, 0x74, 0x20, 0x73, 0x70, 0x61, 0x6b, 0x65,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20,
+ 0x52, 0x61, 0x63, 0x68, 0x65, 0x6c, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x65, 0x72, 0x20, 0x66, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x73, 0x68, 0x65, 0x65, 0x70, 0x3b,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x68, 0x65, 0x20, 0x6b, 0x65, 0x70,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20,
+ 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x4a,
+ 0x61, 0x63, 0x6f, 0x62, 0x20, 0x73, 0x61, 0x77, 0x20, 0x52, 0x61, 0x63,
+ 0x68, 0x65, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x75, 0x67,
+ 0x68, 0x74, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x4c, 0x61, 0x62, 0x61,
+ 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x27, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x68, 0x65, 0x65,
+ 0x70, 0x20, 0x6f, 0x66, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x6d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20,
+ 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x77, 0x65, 0x6e, 0x74,
+ 0x20, 0x6e, 0x65, 0x61, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72,
+ 0x6f, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74,
+ 0x6f, 0x6e, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x27, 0x73, 0x20, 0x6d, 0x6f, 0x75, 0x74,
+ 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72,
+ 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x63, 0x6b,
+ 0x20, 0x6f, 0x66, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x6d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x62,
+ 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x6b, 0x69, 0x73, 0x73, 0x65,
+ 0x64, 0x20, 0x52, 0x61, 0x63, 0x68, 0x65, 0x6c, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6c, 0x69, 0x66, 0x74, 0x65, 0x64, 0x20, 0x75, 0x70, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x77, 0x65, 0x70, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x74, 0x6f, 0x6c, 0x64,
+ 0x20, 0x52, 0x61, 0x63, 0x68, 0x65, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x68, 0x65, 0x72, 0x20,
+ 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x62, 0x72, 0x6f,
+ 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x52, 0x65,
+ 0x62, 0x65, 0x6b, 0x61, 0x68, 0x27, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x72, 0x61, 0x6e,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x6c, 0x64, 0x20, 0x68, 0x65,
+ 0x72, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74,
+ 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e,
+ 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20, 0x68, 0x65, 0x61, 0x72, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x69, 0x64, 0x69, 0x6e, 0x67, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x73, 0x69, 0x73, 0x74, 0x65, 0x72, 0x27, 0x73, 0x20, 0x73,
+ 0x6f, 0x6e, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x20,
+ 0x72, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x65, 0x74, 0x20,
+ 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6d, 0x62,
+ 0x72, 0x61, 0x63, 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x6b, 0x69, 0x73, 0x73, 0x65, 0x64, 0x20, 0x68, 0x69,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67,
+ 0x68, 0x74, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x6c, 0x64, 0x20, 0x4c, 0x61, 0x62,
+ 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65,
+ 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x53, 0x75, 0x72,
+ 0x65, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x61, 0x72, 0x74,
+ 0x20, 0x6d, 0x79, 0x20, 0x62, 0x6f, 0x6e, 0x65, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x6d, 0x79, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x2e, 0x20, 0x41,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x61, 0x62, 0x6f, 0x64, 0x65, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20,
+ 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x2c, 0x20, 0x42,
+ 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x61, 0x72, 0x74, 0x20, 0x6d, 0x79, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68,
+ 0x65, 0x72, 0x2c, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x65, 0x73,
+ 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65,
+ 0x66, 0x6f, 0x72, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x20, 0x6d,
+ 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x74,
+ 0x3f, 0x20, 0x74, 0x65, 0x6c, 0x6c, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x77,
+ 0x68, 0x61, 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68,
+ 0x79, 0x20, 0x77, 0x61, 0x67, 0x65, 0x73, 0x20, 0x62, 0x65, 0x3f, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20, 0x68,
+ 0x61, 0x64, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68,
+ 0x74, 0x65, 0x72, 0x73, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6c,
+ 0x64, 0x65, 0x72, 0x20, 0x77, 0x61, 0x73, 0x20, 0x4c, 0x65, 0x61, 0x68,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x79, 0x6f,
+ 0x75, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x77, 0x61, 0x73, 0x20, 0x52, 0x61,
+ 0x63, 0x68, 0x65, 0x6c, 0x2e, 0x20, 0x0a, 0x4c, 0x65, 0x61, 0x68, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x65,
+ 0x79, 0x65, 0x64, 0x3b, 0x20, 0x62, 0x75, 0x74, 0x20, 0x52, 0x61, 0x63,
+ 0x68, 0x65, 0x6c, 0x20, 0x77, 0x61, 0x73, 0x20, 0x62, 0x65, 0x61, 0x75,
+ 0x74, 0x69, 0x66, 0x75, 0x6c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65,
+ 0x6c, 0x6c, 0x20, 0x66, 0x61, 0x76, 0x6f, 0x75, 0x72, 0x65, 0x64, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20,
+ 0x6c, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x52, 0x61, 0x63, 0x68, 0x65, 0x6c,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20,
+ 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20,
+ 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x52, 0x61,
+ 0x63, 0x68, 0x65, 0x6c, 0x20, 0x74, 0x68, 0x79, 0x20, 0x79, 0x6f, 0x75,
+ 0x6e, 0x67, 0x65, 0x72, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65,
+ 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4c, 0x61, 0x62, 0x61,
+ 0x6e, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x74, 0x20, 0x69,
+ 0x73, 0x20, 0x62, 0x65, 0x74, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x49, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x68, 0x65, 0x72,
+ 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x74, 0x68,
+ 0x61, 0x6e, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x73, 0x68,
+ 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x68, 0x65,
+ 0x72, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x6d, 0x61, 0x6e, 0x3a, 0x20, 0x61, 0x62, 0x69, 0x64, 0x65, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x73, 0x65, 0x72, 0x76,
+ 0x65, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x52, 0x61, 0x63, 0x68, 0x65,
+ 0x6c, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x73, 0x65, 0x65, 0x6d, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x68, 0x69, 0x6d, 0x20, 0x62, 0x75, 0x74, 0x20, 0x61, 0x20, 0x66, 0x65,
+ 0x77, 0x20, 0x64, 0x61, 0x79, 0x73, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x20, 0x68, 0x65, 0x20,
+ 0x68, 0x61, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x65, 0x72, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4c, 0x61, 0x62,
+ 0x61, 0x6e, 0x2c, 0x20, 0x47, 0x69, 0x76, 0x65, 0x20, 0x6d, 0x65, 0x20,
+ 0x6d, 0x79, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x6d, 0x79, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x61, 0x72, 0x65,
+ 0x20, 0x66, 0x75, 0x6c, 0x66, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x2c, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x67,
+ 0x6f, 0x20, 0x69, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x65,
+ 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4c, 0x61, 0x62, 0x61,
+ 0x6e, 0x20, 0x67, 0x61, 0x74, 0x68, 0x65, 0x72, 0x65, 0x64, 0x20, 0x74,
+ 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x61, 0x20, 0x66, 0x65, 0x61,
+ 0x73, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20,
+ 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e,
+ 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65,
+ 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x4c, 0x65, 0x61, 0x68, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74,
+ 0x20, 0x68, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x77, 0x65, 0x6e, 0x74,
+ 0x20, 0x69, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x65, 0x72,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e,
+ 0x20, 0x67, 0x61, 0x76, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x20,
+ 0x4c, 0x65, 0x61, 0x68, 0x20, 0x5a, 0x69, 0x6c, 0x70, 0x61, 0x68, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x6d, 0x61, 0x69, 0x64, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x61, 0x6e, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6d, 0x61, 0x69, 0x64,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61,
+ 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x62, 0x65, 0x68,
+ 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x4c, 0x65, 0x61, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x4c, 0x61, 0x62,
+ 0x61, 0x6e, 0x2c, 0x20, 0x57, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20,
+ 0x74, 0x68, 0x69, 0x73, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61,
+ 0x73, 0x74, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x6d, 0x65, 0x3f, 0x20, 0x64, 0x69, 0x64, 0x20, 0x6e, 0x6f, 0x74,
+ 0x20, 0x49, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x52,
+ 0x61, 0x63, 0x68, 0x65, 0x6c, 0x3f, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65,
+ 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x68, 0x61,
+ 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x62, 0x65, 0x67, 0x75,
+ 0x69, 0x6c, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x3f, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x49, 0x74, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x6e, 0x6f,
+ 0x74, 0x20, 0x62, 0x65, 0x20, 0x73, 0x6f, 0x20, 0x64, 0x6f, 0x6e, 0x65,
+ 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x75, 0x72, 0x20, 0x63, 0x6f, 0x75, 0x6e,
+ 0x74, 0x72, 0x79, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x69, 0x76, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x79, 0x6f, 0x75, 0x6e, 0x67, 0x65, 0x72,
+ 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x69, 0x72, 0x73, 0x74, 0x62, 0x6f, 0x72, 0x6e, 0x2e, 0x20, 0x0a,
+ 0x46, 0x75, 0x6c, 0x66, 0x69, 0x6c, 0x20, 0x68, 0x65, 0x72, 0x20, 0x77,
+ 0x65, 0x65, 0x6b, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x61, 0x6c, 0x73, 0x6f,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72,
+ 0x76, 0x69, 0x63, 0x65, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x73, 0x65,
+ 0x72, 0x76, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x20,
+ 0x79, 0x65, 0x74, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x64, 0x69,
+ 0x64, 0x20, 0x73, 0x6f, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x75,
+ 0x6c, 0x66, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68, 0x65, 0x72, 0x20,
+ 0x77, 0x65, 0x65, 0x6b, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x67, 0x61, 0x76, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x52, 0x61,
+ 0x63, 0x68, 0x65, 0x6c, 0x20, 0x68, 0x69, 0x73, 0x20, 0x64, 0x61, 0x75,
+ 0x67, 0x68, 0x74, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x69, 0x66,
+ 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20, 0x67, 0x61, 0x76, 0x65, 0x20,
+ 0x74, 0x6f, 0x20, 0x52, 0x61, 0x63, 0x68, 0x65, 0x6c, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x20, 0x42,
+ 0x69, 0x6c, 0x68, 0x61, 0x68, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x61,
+ 0x6e, 0x64, 0x6d, 0x61, 0x69, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65,
+ 0x20, 0x68, 0x65, 0x72, 0x20, 0x6d, 0x61, 0x69, 0x64, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20,
+ 0x69, 0x6e, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x52, 0x61, 0x63, 0x68, 0x65, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x61, 0x6c,
+ 0x73, 0x6f, 0x20, 0x52, 0x61, 0x63, 0x68, 0x65, 0x6c, 0x20, 0x6d, 0x6f,
+ 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x4c, 0x65, 0x61, 0x68,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x79, 0x65,
+ 0x74, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x6f, 0x74, 0x68, 0x65,
+ 0x72, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x4c, 0x65, 0x61, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x68, 0x61,
+ 0x74, 0x65, 0x64, 0x2c, 0x20, 0x68, 0x65, 0x20, 0x6f, 0x70, 0x65, 0x6e,
+ 0x65, 0x64, 0x20, 0x68, 0x65, 0x72, 0x20, 0x77, 0x6f, 0x6d, 0x62, 0x3a,
+ 0x20, 0x62, 0x75, 0x74, 0x20, 0x52, 0x61, 0x63, 0x68, 0x65, 0x6c, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x62, 0x61, 0x72, 0x72, 0x65, 0x6e, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4c, 0x65, 0x61, 0x68, 0x20, 0x63, 0x6f,
+ 0x6e, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x62, 0x61, 0x72, 0x65, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c,
+ 0x6c, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65,
+ 0x20, 0x52, 0x65, 0x75, 0x62, 0x65, 0x6e, 0x3a, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x73, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x53,
+ 0x75, 0x72, 0x65, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x6c, 0x6f, 0x6f, 0x6b,
+ 0x65, 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x6d, 0x79, 0x20, 0x61,
+ 0x66, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x20, 0x6e,
+ 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65,
+ 0x20, 0x6d, 0x79, 0x20, 0x68, 0x75, 0x73, 0x62, 0x61, 0x6e, 0x64, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x20, 0x6d, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x63,
+ 0x6f, 0x6e, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x67, 0x61,
+ 0x69, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x61, 0x72, 0x65,
+ 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x63, 0x61, 0x75, 0x73,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x68,
+ 0x61, 0x74, 0x68, 0x20, 0x68, 0x65, 0x61, 0x72, 0x64, 0x20, 0x49, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x68, 0x61, 0x74, 0x65, 0x64, 0x2c, 0x20, 0x68,
+ 0x65, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65,
+ 0x66, 0x6f, 0x72, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x6d,
+ 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x61,
+ 0x6c, 0x73, 0x6f, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65,
+ 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x53, 0x69, 0x6d, 0x65, 0x6f, 0x6e, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x63, 0x6f,
+ 0x6e, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x67, 0x61, 0x69,
+ 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20,
+ 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x69,
+ 0x73, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x6d, 0x79, 0x20, 0x68, 0x75, 0x73, 0x62, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x20, 0x6a, 0x6f, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73,
+ 0x65, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x6f, 0x72,
+ 0x6e, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x20,
+ 0x73, 0x6f, 0x6e, 0x73, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x66,
+ 0x6f, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20,
+ 0x4c, 0x65, 0x76, 0x69, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64,
+ 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x61, 0x72, 0x65, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x4e, 0x6f, 0x77, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x49,
+ 0x20, 0x70, 0x72, 0x61, 0x69, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x66,
+ 0x6f, 0x72, 0x65, 0x20, 0x73, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c,
+ 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20,
+ 0x4a, 0x75, 0x64, 0x61, 0x68, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c,
+ 0x65, 0x66, 0x74, 0x20, 0x62, 0x65, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x52,
+ 0x61, 0x63, 0x68, 0x65, 0x6c, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x73, 0x68, 0x65, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20,
+ 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x6e, 0x6f, 0x20, 0x63, 0x68, 0x69,
+ 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x2c, 0x20, 0x52, 0x61, 0x63, 0x68, 0x65,
+ 0x6c, 0x20, 0x65, 0x6e, 0x76, 0x69, 0x65, 0x64, 0x20, 0x68, 0x65, 0x72,
+ 0x20, 0x73, 0x69, 0x73, 0x74, 0x65, 0x72, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4a,
+ 0x61, 0x63, 0x6f, 0x62, 0x2c, 0x20, 0x47, 0x69, 0x76, 0x65, 0x20, 0x6d,
+ 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x2c, 0x20,
+ 0x6f, 0x72, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x49, 0x20, 0x64, 0x69,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f,
+ 0x62, 0x27, 0x73, 0x20, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x6c, 0x65, 0x64, 0x20, 0x61, 0x67,
+ 0x61, 0x69, 0x6e, 0x73, 0x74, 0x20, 0x52, 0x61, 0x63, 0x68, 0x65, 0x6c,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x41, 0x6d, 0x20, 0x49, 0x20, 0x69, 0x6e, 0x20, 0x47,
+ 0x6f, 0x64, 0x27, 0x73, 0x20, 0x73, 0x74, 0x65, 0x61, 0x64, 0x2c, 0x20,
+ 0x77, 0x68, 0x6f, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x68, 0x65, 0x6c, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74,
+ 0x68, 0x65, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d,
+ 0x62, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64,
+ 0x20, 0x6d, 0x79, 0x20, 0x6d, 0x61, 0x69, 0x64, 0x20, 0x42, 0x69, 0x6c,
+ 0x68, 0x61, 0x68, 0x2c, 0x20, 0x67, 0x6f, 0x20, 0x69, 0x6e, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x65, 0x72, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x68, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62,
+ 0x65, 0x61, 0x72, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x6d, 0x79, 0x20,
+ 0x6b, 0x6e, 0x65, 0x65, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x49, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x68,
+ 0x61, 0x76, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e,
+ 0x20, 0x62, 0x79, 0x20, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x67, 0x61, 0x76, 0x65, 0x20, 0x68,
+ 0x69, 0x6d, 0x20, 0x42, 0x69, 0x6c, 0x68, 0x61, 0x68, 0x20, 0x68, 0x65,
+ 0x72, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6d, 0x61, 0x69, 0x64, 0x20, 0x74,
+ 0x6f, 0x20, 0x77, 0x69, 0x66, 0x65, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x69,
+ 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x65, 0x72, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x42, 0x69, 0x6c, 0x68, 0x61, 0x68, 0x20,
+ 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20, 0x4a, 0x61, 0x63, 0x6f,
+ 0x62, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x52, 0x61, 0x63, 0x68, 0x65, 0x6c, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20,
+ 0x6a, 0x75, 0x64, 0x67, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x61, 0x6c, 0x73, 0x6f,
+ 0x20, 0x68, 0x65, 0x61, 0x72, 0x64, 0x20, 0x6d, 0x79, 0x20, 0x76, 0x6f,
+ 0x69, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x61, 0x74,
+ 0x68, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x61,
+ 0x20, 0x73, 0x6f, 0x6e, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x66,
+ 0x6f, 0x72, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20,
+ 0x44, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x42, 0x69,
+ 0x6c, 0x68, 0x61, 0x68, 0x20, 0x52, 0x61, 0x63, 0x68, 0x65, 0x6c, 0x27,
+ 0x73, 0x20, 0x6d, 0x61, 0x69, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65,
+ 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20, 0x4a, 0x61, 0x63,
+ 0x6f, 0x62, 0x20, 0x61, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20,
+ 0x73, 0x6f, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x52, 0x61,
+ 0x63, 0x68, 0x65, 0x6c, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x57,
+ 0x69, 0x74, 0x68, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x77, 0x72,
+ 0x65, 0x73, 0x74, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x68, 0x61, 0x76,
+ 0x65, 0x20, 0x49, 0x20, 0x77, 0x72, 0x65, 0x73, 0x74, 0x6c, 0x65, 0x64,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x69, 0x73,
+ 0x74, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x68,
+ 0x61, 0x76, 0x65, 0x20, 0x70, 0x72, 0x65, 0x76, 0x61, 0x69, 0x6c, 0x65,
+ 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x63,
+ 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x20, 0x4e, 0x61, 0x70, 0x68, 0x74, 0x61, 0x6c, 0x69, 0x2e,
+ 0x20, 0x0a, 0x57, 0x68, 0x65, 0x6e, 0x20, 0x4c, 0x65, 0x61, 0x68, 0x20,
+ 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73, 0x68, 0x65,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x62, 0x65,
+ 0x61, 0x72, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x73, 0x68, 0x65, 0x20, 0x74,
+ 0x6f, 0x6f, 0x6b, 0x20, 0x5a, 0x69, 0x6c, 0x70, 0x61, 0x68, 0x20, 0x68,
+ 0x65, 0x72, 0x20, 0x6d, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x67, 0x61, 0x76, 0x65, 0x20, 0x68, 0x65, 0x72, 0x20, 0x4a, 0x61,
+ 0x63, 0x6f, 0x62, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x5a, 0x69, 0x6c, 0x70, 0x61, 0x68,
+ 0x20, 0x4c, 0x65, 0x61, 0x68, 0x27, 0x73, 0x20, 0x6d, 0x61, 0x69, 0x64,
+ 0x20, 0x62, 0x61, 0x72, 0x65, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20,
+ 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x4c, 0x65, 0x61, 0x68, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x41,
+ 0x20, 0x74, 0x72, 0x6f, 0x6f, 0x70, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x74,
+ 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x63,
+ 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x20, 0x47, 0x61, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x5a, 0x69, 0x6c, 0x70, 0x61, 0x68, 0x20, 0x4c, 0x65, 0x61, 0x68,
+ 0x27, 0x73, 0x20, 0x6d, 0x61, 0x69, 0x64, 0x20, 0x62, 0x61, 0x72, 0x65,
+ 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x61, 0x20, 0x73, 0x65, 0x63,
+ 0x6f, 0x6e, 0x64, 0x20, 0x73, 0x6f, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x4c, 0x65, 0x61, 0x68, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x48, 0x61, 0x70, 0x70, 0x79, 0x20, 0x61, 0x6d, 0x20, 0x49, 0x2c,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x75,
+ 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x6d, 0x65, 0x20, 0x62, 0x6c, 0x65, 0x73,
+ 0x73, 0x65, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65,
+ 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x41, 0x73, 0x68, 0x65, 0x72, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x52, 0x65, 0x75, 0x62, 0x65, 0x6e, 0x20,
+ 0x77, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x77, 0x68, 0x65, 0x61,
+ 0x74, 0x20, 0x68, 0x61, 0x72, 0x76, 0x65, 0x73, 0x74, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x6e,
+ 0x64, 0x72, 0x61, 0x6b, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x6d, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6d,
+ 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x4c, 0x65, 0x61, 0x68, 0x2e, 0x20,
+ 0x54, 0x68, 0x65, 0x6e, 0x20, 0x52, 0x61, 0x63, 0x68, 0x65, 0x6c, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x4c, 0x65, 0x61, 0x68,
+ 0x2c, 0x20, 0x47, 0x69, 0x76, 0x65, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x49,
+ 0x20, 0x70, 0x72, 0x61, 0x79, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x27, 0x73,
+ 0x20, 0x6d, 0x61, 0x6e, 0x64, 0x72, 0x61, 0x6b, 0x65, 0x73, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x65, 0x72, 0x2c, 0x20,
+ 0x49, 0x73, 0x20, 0x69, 0x74, 0x20, 0x61, 0x20, 0x73, 0x6d, 0x61, 0x6c,
+ 0x6c, 0x20, 0x6d, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20,
+ 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x6d, 0x79, 0x20, 0x68, 0x75, 0x73,
+ 0x62, 0x61, 0x6e, 0x64, 0x3f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x6f,
+ 0x75, 0x6c, 0x64, 0x65, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x74, 0x61, 0x6b, 0x65, 0x20, 0x61, 0x77, 0x61, 0x79, 0x20, 0x6d, 0x79,
+ 0x20, 0x73, 0x6f, 0x6e, 0x27, 0x73, 0x20, 0x6d, 0x61, 0x6e, 0x64, 0x72,
+ 0x61, 0x6b, 0x65, 0x73, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x3f, 0x20, 0x41,
+ 0x6e, 0x64, 0x20, 0x52, 0x61, 0x63, 0x68, 0x65, 0x6c, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72,
+ 0x65, 0x20, 0x68, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6c,
+ 0x69, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x65,
+ 0x20, 0x74, 0x6f, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x27, 0x73, 0x20,
+ 0x6d, 0x61, 0x6e, 0x64, 0x72, 0x61, 0x6b, 0x65, 0x73, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x63, 0x61,
+ 0x6d, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x65, 0x61, 0x68, 0x20, 0x77, 0x65, 0x6e,
+ 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x65,
+ 0x74, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x6f, 0x75, 0x20, 0x6d, 0x75,
+ 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x73, 0x75, 0x72, 0x65, 0x6c, 0x79, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76,
+ 0x65, 0x20, 0x68, 0x69, 0x72, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x65,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x6f, 0x6e,
+ 0x27, 0x73, 0x20, 0x6d, 0x61, 0x6e, 0x64, 0x72, 0x61, 0x6b, 0x65, 0x73,
+ 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x79,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68, 0x65, 0x61, 0x72, 0x6b,
+ 0x65, 0x6e, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4c, 0x65,
+ 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20,
+ 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20, 0x4a, 0x61, 0x63, 0x6f,
+ 0x62, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x66, 0x74, 0x68, 0x20,
+ 0x73, 0x6f, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4c, 0x65,
+ 0x61, 0x68, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20,
+ 0x6d, 0x65, 0x20, 0x6d, 0x79, 0x20, 0x68, 0x69, 0x72, 0x65, 0x2c, 0x20,
+ 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x49, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x6d, 0x79, 0x20,
+ 0x6d, 0x61, 0x69, 0x64, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x79,
+ 0x20, 0x68, 0x75, 0x73, 0x62, 0x61, 0x6e, 0x64, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x49, 0x73,
+ 0x73, 0x61, 0x63, 0x68, 0x61, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x4c, 0x65, 0x61, 0x68, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x69,
+ 0x76, 0x65, 0x64, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20, 0x4a, 0x61, 0x63, 0x6f,
+ 0x62, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x78, 0x74, 0x68, 0x20,
+ 0x73, 0x6f, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4c, 0x65,
+ 0x61, 0x68, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x65, 0x6e, 0x64, 0x75, 0x65, 0x64,
+ 0x20, 0x6d, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x67,
+ 0x6f, 0x6f, 0x64, 0x20, 0x64, 0x6f, 0x77, 0x72, 0x79, 0x3b, 0x20, 0x6e,
+ 0x6f, 0x77, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6d, 0x79, 0x20, 0x68,
+ 0x75, 0x73, 0x62, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x6c,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x62, 0x65,
+ 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65,
+ 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x73, 0x69,
+ 0x78, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x5a, 0x65, 0x62, 0x75,
+ 0x6c, 0x75, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x66,
+ 0x74, 0x65, 0x72, 0x77, 0x61, 0x72, 0x64, 0x73, 0x20, 0x73, 0x68, 0x65,
+ 0x20, 0x62, 0x61, 0x72, 0x65, 0x20, 0x61, 0x20, 0x64, 0x61, 0x75, 0x67,
+ 0x68, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61,
+ 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68, 0x65, 0x72, 0x20, 0x6e, 0x61, 0x6d,
+ 0x65, 0x20, 0x44, 0x69, 0x6e, 0x61, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x72, 0x65, 0x6d, 0x65, 0x6d, 0x62,
+ 0x65, 0x72, 0x65, 0x64, 0x20, 0x52, 0x61, 0x63, 0x68, 0x65, 0x6c, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68, 0x65, 0x61,
+ 0x72, 0x6b, 0x65, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x65,
+ 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x65,
+ 0x64, 0x20, 0x68, 0x65, 0x72, 0x20, 0x77, 0x6f, 0x6d, 0x62, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e,
+ 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x61, 0x72, 0x65, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e,
+ 0x20, 0x61, 0x77, 0x61, 0x79, 0x20, 0x6d, 0x79, 0x20, 0x72, 0x65, 0x70,
+ 0x72, 0x6f, 0x61, 0x63, 0x68, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x73, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x4a, 0x6f, 0x73, 0x65,
+ 0x70, 0x68, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x54, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x64, 0x64, 0x20, 0x74, 0x6f, 0x20,
+ 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73,
+ 0x6f, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20,
+ 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73,
+ 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x52, 0x61, 0x63, 0x68, 0x65,
+ 0x6c, 0x20, 0x68, 0x61, 0x64, 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x4a,
+ 0x6f, 0x73, 0x65, 0x70, 0x68, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x2c, 0x20, 0x53,
+ 0x65, 0x6e, 0x64, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x77, 0x61, 0x79, 0x2c,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x6d, 0x61, 0x79, 0x20,
+ 0x67, 0x6f, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x69, 0x6e, 0x65,
+ 0x20, 0x6f, 0x77, 0x6e, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x79, 0x20, 0x63, 0x6f,
+ 0x75, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x20, 0x0a, 0x47, 0x69, 0x76, 0x65,
+ 0x20, 0x6d, 0x65, 0x20, 0x6d, 0x79, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x79, 0x20, 0x63, 0x68, 0x69, 0x6c,
+ 0x64, 0x72, 0x65, 0x6e, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x77, 0x68,
+ 0x6f, 0x6d, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x73, 0x65,
+ 0x72, 0x76, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x6d, 0x65, 0x20, 0x67, 0x6f,
+ 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x6b,
+ 0x6e, 0x6f, 0x77, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x65,
+ 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4c,
+ 0x61, 0x62, 0x61, 0x6e, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72,
+ 0x61, 0x79, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x69, 0x66, 0x20,
+ 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64,
+ 0x20, 0x66, 0x61, 0x76, 0x6f, 0x75, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x69, 0x6e, 0x65, 0x20, 0x65, 0x79, 0x65, 0x73, 0x2c, 0x20, 0x74,
+ 0x61, 0x72, 0x72, 0x79, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x49, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x6c, 0x65, 0x61, 0x72, 0x6e, 0x65, 0x64,
+ 0x20, 0x62, 0x79, 0x20, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x65, 0x6e,
+ 0x63, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x62, 0x6c,
+ 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x61, 0x6b, 0x65, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x41, 0x70, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x20, 0x6d, 0x65, 0x20,
+ 0x74, 0x68, 0x79, 0x20, 0x77, 0x61, 0x67, 0x65, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x67, 0x69,
+ 0x76, 0x65, 0x20, 0x69, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x54, 0x68, 0x6f, 0x75, 0x20, 0x6b,
+ 0x6e, 0x6f, 0x77, 0x65, 0x73, 0x74, 0x20, 0x68, 0x6f, 0x77, 0x20, 0x49,
+ 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68,
+ 0x6f, 0x77, 0x20, 0x74, 0x68, 0x79, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c,
+ 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d,
+ 0x65, 0x2e, 0x20, 0x0a, 0x46, 0x6f, 0x72, 0x20, 0x69, 0x74, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x6c, 0x69, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x77, 0x68,
+ 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x64,
+ 0x73, 0x74, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x49, 0x20,
+ 0x63, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74,
+ 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x69, 0x6e, 0x63, 0x72,
+ 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x61,
+ 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x73, 0x69, 0x6e, 0x63, 0x65,
+ 0x20, 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x77, 0x68, 0x65, 0x6e,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x49, 0x20, 0x70, 0x72, 0x6f,
+ 0x76, 0x69, 0x64, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x69, 0x6e,
+ 0x65, 0x20, 0x6f, 0x77, 0x6e, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x20,
+ 0x61, 0x6c, 0x73, 0x6f, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x57, 0x68, 0x61, 0x74,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x49, 0x20, 0x67, 0x69, 0x76,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3f, 0x20, 0x41, 0x6e, 0x64, 0x20,
+ 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20,
+ 0x54, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x6d, 0x65, 0x20, 0x61,
+ 0x6e, 0x79, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x69, 0x66,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x77, 0x69, 0x6c, 0x74, 0x20, 0x64,
+ 0x6f, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x49, 0x20, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x20, 0x66, 0x65,
+ 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20,
+ 0x74, 0x68, 0x79, 0x20, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x20, 0x0a,
+ 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x70, 0x61, 0x73, 0x73, 0x20,
+ 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x79, 0x20, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x74, 0x6f,
+ 0x20, 0x64, 0x61, 0x79, 0x2c, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x69,
+ 0x6e, 0x67, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x6e,
+ 0x63, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x70, 0x65, 0x63, 0x6b, 0x6c, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x70, 0x6f, 0x74, 0x74, 0x65, 0x64, 0x20, 0x63, 0x61, 0x74, 0x74,
+ 0x6c, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x62, 0x72, 0x6f, 0x77, 0x6e, 0x20, 0x63, 0x61,
+ 0x74, 0x74, 0x6c, 0x65, 0x20, 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x68, 0x65, 0x65, 0x70, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x70, 0x6f, 0x74, 0x74, 0x65,
+ 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x70, 0x65, 0x63, 0x6b, 0x6c,
+ 0x65, 0x64, 0x20, 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x67, 0x6f, 0x61, 0x74, 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x66, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x73, 0x68, 0x61, 0x6c,
+ 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6d, 0x79, 0x20, 0x68, 0x69, 0x72, 0x65,
+ 0x2e, 0x20, 0x0a, 0x53, 0x6f, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x6d, 0x79, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x65, 0x6f, 0x75, 0x73,
+ 0x6e, 0x65, 0x73, 0x73, 0x20, 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x69,
+ 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x2c, 0x20,
+ 0x77, 0x68, 0x65, 0x6e, 0x20, 0x69, 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c,
+ 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d,
+ 0x79, 0x20, 0x68, 0x69, 0x72, 0x65, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72,
+ 0x65, 0x20, 0x74, 0x68, 0x79, 0x20, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x20,
+ 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x70,
+ 0x65, 0x63, 0x6b, 0x6c, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x70, 0x6f, 0x74, 0x74, 0x65, 0x64, 0x20, 0x61, 0x6d, 0x6f, 0x6e, 0x67,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x6f, 0x61, 0x74, 0x73, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x77, 0x6e, 0x20, 0x61, 0x6d,
+ 0x6f, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x68, 0x65, 0x65,
+ 0x70, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c,
+ 0x6c, 0x20, 0x62, 0x65, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x64,
+ 0x20, 0x73, 0x74, 0x6f, 0x6c, 0x65, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x6d, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4c, 0x61,
+ 0x62, 0x61, 0x6e, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65,
+ 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x6f, 0x75, 0x6c,
+ 0x64, 0x20, 0x69, 0x74, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x20, 0x62,
+ 0x65, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x72, 0x65, 0x6d,
+ 0x6f, 0x76, 0x65, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x64, 0x61,
+ 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x20, 0x67, 0x6f, 0x61,
+ 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x74, 0x72, 0x61, 0x6b, 0x65, 0x64,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x70, 0x6f, 0x74, 0x74, 0x65, 0x64,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x68, 0x65, 0x20, 0x67, 0x6f, 0x61, 0x74, 0x73, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x73, 0x70,
+ 0x65, 0x63, 0x6b, 0x6c, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x70, 0x6f, 0x74, 0x74, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x68, 0x61, 0x64, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20,
+ 0x77, 0x68, 0x69, 0x74, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x74, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x62, 0x72, 0x6f, 0x77, 0x6e, 0x20, 0x61, 0x6d, 0x6f, 0x6e, 0x67,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x68, 0x65, 0x65, 0x70, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x67, 0x61, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65,
+ 0x6d, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73,
+ 0x6f, 0x6e, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x73, 0x65, 0x74, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x20, 0x64,
+ 0x61, 0x79, 0x73, 0x27, 0x20, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79,
+ 0x20, 0x62, 0x65, 0x74, 0x77, 0x69, 0x78, 0x74, 0x20, 0x68, 0x69, 0x6d,
+ 0x73, 0x65, 0x6c, 0x66, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63,
+ 0x6f, 0x62, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f,
+ 0x62, 0x20, 0x66, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65,
+ 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x27,
+ 0x73, 0x20, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x74, 0x6f, 0x6f,
+ 0x6b, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x72, 0x6f, 0x64, 0x73, 0x20, 0x6f,
+ 0x66, 0x20, 0x67, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x70, 0x6f, 0x70, 0x6c,
+ 0x61, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x68, 0x61, 0x7a, 0x65, 0x6c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x63, 0x68, 0x65, 0x73, 0x6e, 0x75, 0x74, 0x20, 0x74, 0x72, 0x65,
+ 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x69, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x20, 0x73, 0x74, 0x72, 0x61,
+ 0x6b, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x20, 0x61, 0x70, 0x70, 0x65,
+ 0x61, 0x72, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x6f, 0x64, 0x73,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x65,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x6f, 0x64, 0x73, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20,
+ 0x70, 0x69, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x73,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x75, 0x74, 0x74,
+ 0x65, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x72, 0x6f, 0x75,
+ 0x67, 0x68, 0x73, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x20, 0x63, 0x61, 0x6d, 0x65,
+ 0x20, 0x74, 0x6f, 0x20, 0x64, 0x72, 0x69, 0x6e, 0x6b, 0x2c, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x68, 0x6f,
+ 0x75, 0x6c, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x69, 0x76, 0x65,
+ 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x63,
+ 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x72, 0x69, 0x6e, 0x6b,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x69,
+ 0x76, 0x65, 0x64, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x72, 0x6f, 0x64, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x66, 0x6f, 0x72,
+ 0x74, 0x68, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x72, 0x69,
+ 0x6e, 0x67, 0x73, 0x74, 0x72, 0x61, 0x6b, 0x65, 0x64, 0x2c, 0x20, 0x73,
+ 0x70, 0x65, 0x63, 0x6b, 0x6c, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x70, 0x6f, 0x74, 0x74, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x64, 0x69, 0x64,
+ 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6c, 0x61, 0x6d, 0x62, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63,
+ 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x73, 0x20, 0x74, 0x6f, 0x77, 0x61, 0x72, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x74, 0x72, 0x61,
+ 0x6b, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x72, 0x6f, 0x77, 0x6e, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x20,
+ 0x6f, 0x66, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x20, 0x70, 0x75, 0x74, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x6f, 0x77, 0x6e, 0x20, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x20,
+ 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x73, 0x65, 0x6c, 0x76, 0x65,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x75, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x27, 0x73, 0x20, 0x63, 0x61, 0x74,
+ 0x74, 0x6c, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74,
+ 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73,
+ 0x73, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x73, 0x6f, 0x65, 0x76, 0x65,
+ 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x72, 0x6f, 0x6e, 0x67,
+ 0x65, 0x72, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x64, 0x69,
+ 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x69, 0x76, 0x65, 0x2c, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x6c,
+ 0x61, 0x69, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x6f, 0x64, 0x73,
+ 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x79, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x67, 0x75, 0x74, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x6d, 0x69, 0x67,
+ 0x68, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
+ 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x6f,
+ 0x64, 0x73, 0x2e, 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x77, 0x68, 0x65,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x66, 0x65, 0x65, 0x62, 0x6c, 0x65,
+ 0x2c, 0x20, 0x68, 0x65, 0x20, 0x70, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x6d, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x69, 0x6e, 0x3a, 0x20, 0x73, 0x6f,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x65, 0x65, 0x62, 0x6c, 0x65, 0x72,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x27,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x74, 0x72, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x4a, 0x61, 0x63, 0x6f,
+ 0x62, 0x27, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x63, 0x72, 0x65, 0x61,
+ 0x73, 0x65, 0x64, 0x20, 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x69, 0x6e,
+ 0x67, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x61, 0x64,
+ 0x20, 0x6d, 0x75, 0x63, 0x68, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x64, 0x73, 0x65,
+ 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6d, 0x65, 0x6e, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x6c, 0x73, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x73, 0x73, 0x65, 0x73, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x72,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x20,
+ 0x6f, 0x66, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x27, 0x73, 0x20, 0x73,
+ 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c,
+ 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20,
+ 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x61, 0x77, 0x61, 0x79, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x6f, 0x75, 0x72, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x6f, 0x75, 0x72, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73,
+ 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x68, 0x65, 0x20, 0x67, 0x6f, 0x74,
+ 0x74, 0x65, 0x6e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x67, 0x6c, 0x6f, 0x72, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x62, 0x65, 0x68, 0x65, 0x6c,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65,
+ 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x4c, 0x61, 0x62,
+ 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x62, 0x65, 0x68,
+ 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x6f, 0x77, 0x61, 0x72, 0x64, 0x20, 0x68,
+ 0x69, 0x6d, 0x20, 0x61, 0x73, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x2c, 0x20, 0x52, 0x65, 0x74,
+ 0x75, 0x72, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6b, 0x69, 0x6e,
+ 0x64, 0x72, 0x65, 0x64, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x74, 0x68, 0x65, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x52, 0x61,
+ 0x63, 0x68, 0x65, 0x6c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x65, 0x61,
+ 0x68, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65,
+ 0x6c, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68,
+ 0x65, 0x6d, 0x2c, 0x20, 0x49, 0x20, 0x73, 0x65, 0x65, 0x20, 0x79, 0x6f,
+ 0x75, 0x72, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20,
+ 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x2c,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20,
+ 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x6f, 0x77, 0x61, 0x72, 0x64, 0x20, 0x6d,
+ 0x65, 0x20, 0x61, 0x73, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x3b,
+ 0x20, 0x62, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x79, 0x65, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x6d, 0x79, 0x20, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x49, 0x20, 0x68,
+ 0x61, 0x76, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x20, 0x79,
+ 0x6f, 0x75, 0x72, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x66, 0x61,
+ 0x74, 0x68, 0x65, 0x72, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x64, 0x65,
+ 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x20, 0x6d,
+ 0x79, 0x20, 0x77, 0x61, 0x67, 0x65, 0x73, 0x20, 0x74, 0x65, 0x6e, 0x20,
+ 0x74, 0x69, 0x6d, 0x65, 0x73, 0x3b, 0x20, 0x62, 0x75, 0x74, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x73, 0x75, 0x66, 0x66, 0x65, 0x72, 0x65, 0x64, 0x20,
+ 0x68, 0x69, 0x6d, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x68,
+ 0x75, 0x72, 0x74, 0x20, 0x6d, 0x65, 0x2e, 0x20, 0x0a, 0x49, 0x66, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x74, 0x68, 0x75, 0x73,
+ 0x2c, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x70, 0x65, 0x63, 0x6b, 0x6c,
+ 0x65, 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20,
+ 0x74, 0x68, 0x79, 0x20, 0x77, 0x61, 0x67, 0x65, 0x73, 0x3b, 0x20, 0x74,
+ 0x68, 0x65, 0x6e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20,
+ 0x73, 0x70, 0x65, 0x63, 0x6b, 0x6c, 0x65, 0x64, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x69, 0x66, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x20, 0x74, 0x68, 0x75, 0x73, 0x2c, 0x20, 0x54, 0x68, 0x65, 0x20, 0x72,
+ 0x69, 0x6e, 0x67, 0x73, 0x74, 0x72, 0x61, 0x6b, 0x65, 0x64, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x68, 0x69, 0x72, 0x65, 0x3b, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x62,
+ 0x61, 0x72, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x72, 0x69, 0x6e, 0x67, 0x73,
+ 0x74, 0x72, 0x61, 0x6b, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x75,
+ 0x73, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x74,
+ 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x61, 0x77, 0x61, 0x79, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x79, 0x6f, 0x75, 0x72, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20,
+ 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x20, 0x61, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x20,
+ 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x2c, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x6c, 0x69, 0x66, 0x74, 0x65, 0x64,
+ 0x20, 0x75, 0x70, 0x20, 0x6d, 0x69, 0x6e, 0x65, 0x20, 0x65, 0x79, 0x65,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x69,
+ 0x6e, 0x20, 0x61, 0x20, 0x64, 0x72, 0x65, 0x61, 0x6d, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x72, 0x61, 0x6d, 0x73, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x6c, 0x65, 0x61, 0x70, 0x65, 0x64, 0x20, 0x75, 0x70,
+ 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c,
+ 0x65, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x72, 0x69, 0x6e, 0x67, 0x73,
+ 0x74, 0x72, 0x61, 0x6b, 0x65, 0x64, 0x2c, 0x20, 0x73, 0x70, 0x65, 0x63,
+ 0x6b, 0x6c, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x72,
+ 0x69, 0x73, 0x6c, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x20, 0x6f, 0x66,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x70, 0x61, 0x6b, 0x65, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20,
+ 0x64, 0x72, 0x65, 0x61, 0x6d, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e,
+ 0x67, 0x2c, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x3a, 0x20, 0x41, 0x6e,
+ 0x64, 0x20, 0x49, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x48, 0x65,
+ 0x72, 0x65, 0x20, 0x61, 0x6d, 0x20, 0x49, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c,
+ 0x69, 0x66, 0x74, 0x20, 0x75, 0x70, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x74,
+ 0x68, 0x69, 0x6e, 0x65, 0x20, 0x65, 0x79, 0x65, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x73, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x72, 0x61, 0x6d, 0x73, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x6c, 0x65, 0x61, 0x70, 0x20, 0x75, 0x70, 0x6f, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x20,
+ 0x61, 0x72, 0x65, 0x20, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x74, 0x72, 0x61,
+ 0x6b, 0x65, 0x64, 0x2c, 0x20, 0x73, 0x70, 0x65, 0x63, 0x6b, 0x6c, 0x65,
+ 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x72, 0x69, 0x73, 0x6c,
+ 0x65, 0x64, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x49, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x73, 0x65, 0x65, 0x6e, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20, 0x64,
+ 0x6f, 0x65, 0x74, 0x68, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x2e, 0x20, 0x0a, 0x49, 0x20, 0x61, 0x6d, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x42, 0x65, 0x74,
+ 0x68, 0x65, 0x6c, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x61, 0x6e, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x64,
+ 0x73, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x69, 0x6c, 0x6c, 0x61,
+ 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x76, 0x6f, 0x77, 0x65, 0x64, 0x73,
+ 0x74, 0x20, 0x61, 0x20, 0x76, 0x6f, 0x77, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x6d, 0x65, 0x3a, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x61, 0x72, 0x69,
+ 0x73, 0x65, 0x2c, 0x20, 0x67, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x65,
+ 0x20, 0x6f, 0x75, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68,
+ 0x69, 0x73, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x72, 0x65, 0x64,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x52, 0x61, 0x63, 0x68, 0x65,
+ 0x6c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x65, 0x61, 0x68, 0x20, 0x61,
+ 0x6e, 0x73, 0x77, 0x65, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69,
+ 0x6d, 0x2c, 0x20, 0x49, 0x73, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20,
+ 0x79, 0x65, 0x74, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x70, 0x6f, 0x72, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x68, 0x65, 0x72,
+ 0x69, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x75,
+ 0x73, 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x75, 0x72, 0x20, 0x66, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x3f,
+ 0x20, 0x0a, 0x41, 0x72, 0x65, 0x20, 0x77, 0x65, 0x20, 0x6e, 0x6f, 0x74,
+ 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x68, 0x69, 0x6d, 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x72,
+ 0x73, 0x3f, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61,
+ 0x74, 0x68, 0x20, 0x73, 0x6f, 0x6c, 0x64, 0x20, 0x75, 0x73, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x71, 0x75, 0x69,
+ 0x74, 0x65, 0x20, 0x64, 0x65, 0x76, 0x6f, 0x75, 0x72, 0x65, 0x64, 0x20,
+ 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x6f, 0x75, 0x72, 0x20, 0x6d, 0x6f, 0x6e,
+ 0x65, 0x79, 0x2e, 0x20, 0x0a, 0x46, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x69, 0x63, 0x68, 0x65, 0x73, 0x20,
+ 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68, 0x61,
+ 0x74, 0x68, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x6f, 0x75, 0x72, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6f, 0x75,
+ 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x75, 0x72, 0x20,
+ 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x27, 0x73, 0x3a, 0x20,
+ 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x2c, 0x20, 0x77, 0x68,
+ 0x61, 0x74, 0x73, 0x6f, 0x65, 0x76, 0x65, 0x72, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x64, 0x6f,
+ 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x6e, 0x20, 0x4a, 0x61, 0x63, 0x6f,
+ 0x62, 0x20, 0x72, 0x6f, 0x73, 0x65, 0x20, 0x75, 0x70, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x73, 0x65, 0x74, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73,
+ 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x77, 0x69, 0x76, 0x65, 0x73, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x63,
+ 0x61, 0x6d, 0x65, 0x6c, 0x73, 0x3b, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, 0x64, 0x20, 0x61,
+ 0x77, 0x61, 0x79, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x68, 0x69, 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64,
+ 0x73, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x68, 0x65, 0x20, 0x68,
+ 0x61, 0x64, 0x20, 0x67, 0x6f, 0x74, 0x74, 0x65, 0x6e, 0x2c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x67, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67,
+ 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x68, 0x65, 0x20, 0x68,
+ 0x61, 0x64, 0x20, 0x67, 0x6f, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x69, 0x6e,
+ 0x20, 0x50, 0x61, 0x64, 0x61, 0x6e, 0x61, 0x72, 0x61, 0x6d, 0x2c, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x6f, 0x20, 0x74, 0x6f,
+ 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x68, 0x69, 0x73, 0x20, 0x66,
+ 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x61, 0x6e,
+ 0x61, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4c, 0x61,
+ 0x62, 0x61, 0x6e, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20,
+ 0x73, 0x68, 0x65, 0x61, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x68,
+ 0x65, 0x65, 0x70, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x52, 0x61, 0x63,
+ 0x68, 0x65, 0x6c, 0x20, 0x68, 0x61, 0x64, 0x20, 0x73, 0x74, 0x6f, 0x6c,
+ 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65,
+ 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x68, 0x65, 0x72, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62,
+ 0x20, 0x73, 0x74, 0x6f, 0x6c, 0x65, 0x20, 0x61, 0x77, 0x61, 0x79, 0x20,
+ 0x75, 0x6e, 0x61, 0x77, 0x61, 0x72, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20,
+ 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x79,
+ 0x72, 0x69, 0x61, 0x6e, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x6c, 0x64, 0x20, 0x68, 0x69,
+ 0x6d, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68,
+ 0x65, 0x20, 0x66, 0x6c, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x53, 0x6f, 0x20,
+ 0x68, 0x65, 0x20, 0x66, 0x6c, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65,
+ 0x20, 0x68, 0x61, 0x64, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x72, 0x6f, 0x73, 0x65, 0x20, 0x75, 0x70, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x76, 0x65,
+ 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x69, 0x76, 0x65, 0x72, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x74, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x74, 0x6f, 0x77, 0x61, 0x72, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x47,
+ 0x69, 0x6c, 0x65, 0x61, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x6f, 0x6c, 0x64, 0x20,
+ 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x74, 0x68, 0x69, 0x72, 0x64, 0x20, 0x64, 0x61, 0x79, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x66, 0x6c, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x62, 0x72, 0x65, 0x74, 0x68, 0x72, 0x65, 0x6e, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x70, 0x75, 0x72, 0x73, 0x75, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20,
+ 0x64, 0x61, 0x79, 0x73, 0x27, 0x20, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x65,
+ 0x79, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x6f, 0x76, 0x65, 0x72, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x68, 0x69, 0x6d,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x75, 0x6e,
+ 0x74, 0x20, 0x47, 0x69, 0x6c, 0x65, 0x61, 0x64, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20,
+ 0x74, 0x6f, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x53, 0x79, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x61,
+ 0x20, 0x64, 0x72, 0x65, 0x61, 0x6d, 0x20, 0x62, 0x79, 0x20, 0x6e, 0x69,
+ 0x67, 0x68, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20,
+ 0x54, 0x61, 0x6b, 0x65, 0x20, 0x68, 0x65, 0x65, 0x64, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x70, 0x65, 0x61,
+ 0x6b, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x4a, 0x61, 0x63,
+ 0x6f, 0x62, 0x20, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x67, 0x6f,
+ 0x6f, 0x64, 0x20, 0x6f, 0x72, 0x20, 0x62, 0x61, 0x64, 0x2e, 0x20, 0x0a,
+ 0x54, 0x68, 0x65, 0x6e, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20, 0x6f,
+ 0x76, 0x65, 0x72, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x4a, 0x61, 0x63, 0x6f,
+ 0x62, 0x2e, 0x20, 0x4e, 0x6f, 0x77, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x70, 0x69, 0x74, 0x63, 0x68, 0x65, 0x64,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x65, 0x74, 0x68,
+ 0x72, 0x65, 0x6e, 0x20, 0x70, 0x69, 0x74, 0x63, 0x68, 0x65, 0x64, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x47, 0x69, 0x6c, 0x65, 0x61, 0x64, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62,
+ 0x2c, 0x20, 0x57, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x2c, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73,
+ 0x74, 0x20, 0x73, 0x74, 0x6f, 0x6c, 0x65, 0x6e, 0x20, 0x61, 0x77, 0x61,
+ 0x79, 0x20, 0x75, 0x6e, 0x61, 0x77, 0x61, 0x72, 0x65, 0x73, 0x20, 0x74,
+ 0x6f, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61,
+ 0x72, 0x72, 0x69, 0x65, 0x64, 0x20, 0x61, 0x77, 0x61, 0x79, 0x20, 0x6d,
+ 0x79, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x2c,
+ 0x20, 0x61, 0x73, 0x20, 0x63, 0x61, 0x70, 0x74, 0x69, 0x76, 0x65, 0x73,
+ 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x3f, 0x20, 0x0a,
+ 0x57, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x64, 0x69,
+ 0x64, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x66, 0x6c, 0x65,
+ 0x65, 0x20, 0x61, 0x77, 0x61, 0x79, 0x20, 0x73, 0x65, 0x63, 0x72, 0x65,
+ 0x74, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x74, 0x65,
+ 0x61, 0x6c, 0x20, 0x61, 0x77, 0x61, 0x79, 0x20, 0x66, 0x72, 0x6f, 0x6d,
+ 0x20, 0x6d, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x64,
+ 0x73, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x65, 0x6c, 0x6c, 0x20,
+ 0x6d, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x6d,
+ 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x73, 0x65,
+ 0x6e, 0x74, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x61, 0x77, 0x61, 0x79,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x69, 0x72, 0x74, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x73, 0x6f,
+ 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x61,
+ 0x62, 0x72, 0x65, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x68, 0x61, 0x72, 0x70, 0x3f, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73,
+ 0x75, 0x66, 0x66, 0x65, 0x72, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x20, 0x74,
+ 0x6f, 0x20, 0x6b, 0x69, 0x73, 0x73, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x6f,
+ 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x79, 0x20, 0x64, 0x61,
+ 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x3f, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x64,
+ 0x6f, 0x6e, 0x65, 0x20, 0x66, 0x6f, 0x6f, 0x6c, 0x69, 0x73, 0x68, 0x6c,
+ 0x79, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x6f, 0x20, 0x64, 0x6f, 0x69, 0x6e,
+ 0x67, 0x2e, 0x20, 0x0a, 0x49, 0x74, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x6f,
+ 0x66, 0x20, 0x6d, 0x79, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f,
+ 0x20, 0x64, 0x6f, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x68, 0x75, 0x72, 0x74,
+ 0x3a, 0x20, 0x62, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x66, 0x61,
+ 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x70, 0x61, 0x6b, 0x65, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x20, 0x79, 0x65, 0x73, 0x74, 0x65,
+ 0x72, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69,
+ 0x6e, 0x67, 0x2c, 0x20, 0x54, 0x61, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x68, 0x65, 0x65, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x70, 0x65, 0x61, 0x6b, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20,
+ 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20,
+ 0x6f, 0x72, 0x20, 0x62, 0x61, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x6e, 0x6f, 0x77, 0x2c, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x67, 0x68,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x65,
+ 0x73, 0x74, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x20, 0x62, 0x65, 0x20,
+ 0x67, 0x6f, 0x6e, 0x65, 0x2c, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73,
+ 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x6f, 0x72, 0x65, 0x20,
+ 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x64, 0x73, 0x74, 0x20, 0x61, 0x66, 0x74,
+ 0x65, 0x72, 0x20, 0x74, 0x68, 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x27, 0x73, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2c, 0x20, 0x79,
+ 0x65, 0x74, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65,
+ 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73,
+ 0x74, 0x6f, 0x6c, 0x65, 0x6e, 0x20, 0x6d, 0x79, 0x20, 0x67, 0x6f, 0x64,
+ 0x73, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f,
+ 0x62, 0x20, 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x65, 0x64, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x4c,
+ 0x61, 0x62, 0x61, 0x6e, 0x2c, 0x20, 0x42, 0x65, 0x63, 0x61, 0x75, 0x73,
+ 0x65, 0x20, 0x49, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x66, 0x72, 0x61,
+ 0x69, 0x64, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x49, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x2c, 0x20, 0x50, 0x65, 0x72, 0x61, 0x64, 0x76, 0x65, 0x6e,
+ 0x74, 0x75, 0x72, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x77, 0x6f,
+ 0x75, 0x6c, 0x64, 0x65, 0x73, 0x74, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20,
+ 0x62, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x20, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x6d, 0x65, 0x2e, 0x20, 0x0a, 0x57, 0x69, 0x74,
+ 0x68, 0x20, 0x77, 0x68, 0x6f, 0x6d, 0x73, 0x6f, 0x65, 0x76, 0x65, 0x72,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x65, 0x73,
+ 0x74, 0x20, 0x74, 0x68, 0x79, 0x20, 0x67, 0x6f, 0x64, 0x73, 0x2c, 0x20,
+ 0x6c, 0x65, 0x74, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x6c, 0x69, 0x76, 0x65, 0x3a, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65,
+ 0x20, 0x6f, 0x75, 0x72, 0x20, 0x62, 0x72, 0x65, 0x74, 0x68, 0x72, 0x65,
+ 0x6e, 0x20, 0x64, 0x69, 0x73, 0x63, 0x65, 0x72, 0x6e, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74,
+ 0x68, 0x69, 0x6e, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x69,
+ 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2e, 0x20, 0x46,
+ 0x6f, 0x72, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x6b, 0x6e, 0x65,
+ 0x77, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x52,
+ 0x61, 0x63, 0x68, 0x65, 0x6c, 0x20, 0x68, 0x61, 0x64, 0x20, 0x73, 0x74,
+ 0x6f, 0x6c, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20, 0x77, 0x65,
+ 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x4a, 0x61, 0x63, 0x6f,
+ 0x62, 0x27, 0x73, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x4c, 0x65, 0x61, 0x68, 0x27,
+ 0x73, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x77, 0x6f,
+ 0x20, 0x6d, 0x61, 0x69, 0x64, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74,
+ 0x73, 0x27, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x3b, 0x20, 0x62, 0x75,
+ 0x74, 0x20, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x20, 0x6e, 0x6f, 0x74, 0x2e, 0x20, 0x54, 0x68, 0x65,
+ 0x6e, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x68, 0x65, 0x20, 0x6f, 0x75,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x4c, 0x65, 0x61, 0x68, 0x27, 0x73, 0x20,
+ 0x74, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6e,
+ 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x52,
+ 0x61, 0x63, 0x68, 0x65, 0x6c, 0x27, 0x73, 0x20, 0x74, 0x65, 0x6e, 0x74,
+ 0x2e, 0x20, 0x0a, 0x4e, 0x6f, 0x77, 0x20, 0x52, 0x61, 0x63, 0x68, 0x65,
+ 0x6c, 0x20, 0x68, 0x61, 0x64, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x73, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x70, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6d, 0x65,
+ 0x6c, 0x27, 0x73, 0x20, 0x66, 0x75, 0x72, 0x6e, 0x69, 0x74, 0x75, 0x72,
+ 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x74, 0x20, 0x75,
+ 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2e, 0x20, 0x41, 0x6e,
+ 0x64, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20, 0x73, 0x65, 0x61, 0x72,
+ 0x63, 0x68, 0x65, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x74, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x66,
+ 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x6e, 0x6f,
+ 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x65, 0x72, 0x20,
+ 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20,
+ 0x69, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c,
+ 0x65, 0x61, 0x73, 0x65, 0x20, 0x6d, 0x79, 0x20, 0x6c, 0x6f, 0x72, 0x64,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x63, 0x61, 0x6e, 0x6e,
+ 0x6f, 0x74, 0x20, 0x72, 0x69, 0x73, 0x65, 0x20, 0x75, 0x70, 0x20, 0x62,
+ 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3b, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x75, 0x73, 0x74,
+ 0x6f, 0x6d, 0x20, 0x6f, 0x66, 0x20, 0x77, 0x6f, 0x6d, 0x65, 0x6e, 0x20,
+ 0x69, 0x73, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x6d, 0x65, 0x2e, 0x20,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x65, 0x61, 0x72, 0x63,
+ 0x68, 0x65, 0x64, 0x20, 0x62, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e,
+ 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6d,
+ 0x61, 0x67, 0x65, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a,
+ 0x61, 0x63, 0x6f, 0x62, 0x20, 0x77, 0x61, 0x73, 0x20, 0x77, 0x72, 0x6f,
+ 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x68, 0x6f, 0x64,
+ 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20,
+ 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x4c, 0x61, 0x62,
+ 0x61, 0x6e, 0x2c, 0x20, 0x57, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20,
+ 0x6d, 0x79, 0x20, 0x74, 0x72, 0x65, 0x73, 0x70, 0x61, 0x73, 0x73, 0x3f,
+ 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x79, 0x20,
+ 0x73, 0x69, 0x6e, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x73, 0x6f, 0x20, 0x68,
+ 0x6f, 0x74, 0x6c, 0x79, 0x20, 0x70, 0x75, 0x72, 0x73, 0x75, 0x65, 0x64,
+ 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x6d, 0x65, 0x3f, 0x20, 0x0a,
+ 0x57, 0x68, 0x65, 0x72, 0x65, 0x61, 0x73, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68,
+ 0x65, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x74,
+ 0x75, 0x66, 0x66, 0x2c, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61,
+ 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x66, 0x6f, 0x75, 0x6e,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x20, 0x73,
+ 0x74, 0x75, 0x66, 0x66, 0x3f, 0x20, 0x73, 0x65, 0x74, 0x20, 0x69, 0x74,
+ 0x20, 0x68, 0x65, 0x72, 0x65, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65,
+ 0x20, 0x6d, 0x79, 0x20, 0x62, 0x72, 0x65, 0x74, 0x68, 0x72, 0x65, 0x6e,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x72, 0x65,
+ 0x74, 0x68, 0x72, 0x65, 0x6e, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x6a, 0x75, 0x64,
+ 0x67, 0x65, 0x20, 0x62, 0x65, 0x74, 0x77, 0x69, 0x78, 0x74, 0x20, 0x75,
+ 0x73, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x69,
+ 0x73, 0x20, 0x74, 0x77, 0x65, 0x6e, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x49, 0x20, 0x62, 0x65,
+ 0x65, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x65,
+ 0x3b, 0x20, 0x74, 0x68, 0x79, 0x20, 0x65, 0x77, 0x65, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x68, 0x65, 0x20, 0x67,
+ 0x6f, 0x61, 0x74, 0x73, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x6e, 0x6f,
+ 0x74, 0x20, 0x63, 0x61, 0x73, 0x74, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72,
+ 0x20, 0x79, 0x6f, 0x75, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x72, 0x61, 0x6d, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x79, 0x20, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x49, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x61, 0x74,
+ 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x61, 0x74, 0x20, 0x77, 0x68,
+ 0x69, 0x63, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x6f, 0x72, 0x6e,
+ 0x20, 0x6f, 0x66, 0x20, 0x62, 0x65, 0x61, 0x73, 0x74, 0x73, 0x20, 0x49,
+ 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x6e, 0x6f, 0x74,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3b, 0x20,
+ 0x49, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c,
+ 0x6f, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x3b, 0x20, 0x6f,
+ 0x66, 0x20, 0x6d, 0x79, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69,
+ 0x64, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x72, 0x65, 0x71,
+ 0x75, 0x69, 0x72, 0x65, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x77, 0x68, 0x65,
+ 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x74, 0x6f, 0x6c, 0x65, 0x6e, 0x20,
+ 0x62, 0x79, 0x20, 0x64, 0x61, 0x79, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x73,
+ 0x74, 0x6f, 0x6c, 0x65, 0x6e, 0x20, 0x62, 0x79, 0x20, 0x6e, 0x69, 0x67,
+ 0x68, 0x74, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x75, 0x73, 0x20, 0x49, 0x20,
+ 0x77, 0x61, 0x73, 0x3b, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x64, 0x61, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x72, 0x6f, 0x75,
+ 0x67, 0x68, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64,
+ 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x20, 0x62, 0x79, 0x20, 0x6e, 0x69,
+ 0x67, 0x68, 0x74, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x79, 0x20,
+ 0x73, 0x6c, 0x65, 0x65, 0x70, 0x20, 0x64, 0x65, 0x70, 0x61, 0x72, 0x74,
+ 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6d, 0x69, 0x6e, 0x65,
+ 0x20, 0x65, 0x79, 0x65, 0x73, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x75, 0x73,
+ 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x49, 0x20, 0x62, 0x65, 0x65, 0x6e,
+ 0x20, 0x74, 0x77, 0x65, 0x6e, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72,
+ 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20, 0x68, 0x6f, 0x75,
+ 0x73, 0x65, 0x3b, 0x20, 0x49, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x66, 0x6f, 0x75, 0x72, 0x74, 0x65,
+ 0x65, 0x6e, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x64, 0x61, 0x75,
+ 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x69, 0x78, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x74, 0x68, 0x79, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68,
+ 0x61, 0x73, 0x74, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x20,
+ 0x6d, 0x79, 0x20, 0x77, 0x61, 0x67, 0x65, 0x73, 0x20, 0x74, 0x65, 0x6e,
+ 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x2e, 0x20, 0x0a, 0x45, 0x78, 0x63,
+ 0x65, 0x70, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72,
+ 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x65, 0x61, 0x72, 0x20, 0x6f,
+ 0x66, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x2c, 0x20, 0x68, 0x61, 0x64,
+ 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d,
+ 0x65, 0x2c, 0x20, 0x73, 0x75, 0x72, 0x65, 0x6c, 0x79, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x68, 0x61, 0x64, 0x73, 0x74, 0x20, 0x73, 0x65, 0x6e,
+ 0x74, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x77, 0x61, 0x79, 0x20, 0x6e, 0x6f,
+ 0x77, 0x20, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x73, 0x65, 0x65, 0x6e, 0x20, 0x6d,
+ 0x69, 0x6e, 0x65, 0x20, 0x61, 0x66, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x69,
+ 0x6f, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c,
+ 0x61, 0x62, 0x6f, 0x75, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20,
+ 0x68, 0x61, 0x6e, 0x64, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72,
+ 0x65, 0x62, 0x75, 0x6b, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20,
+ 0x79, 0x65, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20,
+ 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4a,
+ 0x61, 0x63, 0x6f, 0x62, 0x2c, 0x20, 0x54, 0x68, 0x65, 0x73, 0x65, 0x20,
+ 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x20, 0x61, 0x72,
+ 0x65, 0x20, 0x6d, 0x79, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65,
+ 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x73,
+ 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20, 0x61,
+ 0x72, 0x65, 0x20, 0x6d, 0x79, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72,
+ 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x73,
+ 0x65, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x61, 0x72, 0x65,
+ 0x20, 0x6d, 0x79, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x65, 0x65, 0x73, 0x74, 0x20,
+ 0x69, 0x73, 0x20, 0x6d, 0x69, 0x6e, 0x65, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x49, 0x20,
+ 0x64, 0x6f, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x64, 0x61, 0x79, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x6d,
+ 0x79, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x2c,
+ 0x20, 0x6f, 0x72, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x69, 0x72, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20,
+ 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x68,
+ 0x61, 0x76, 0x65, 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x3f, 0x20, 0x0a, 0x4e,
+ 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65,
+ 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x2c, 0x20,
+ 0x6c, 0x65, 0x74, 0x20, 0x75, 0x73, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20,
+ 0x61, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x2c, 0x20,
+ 0x49, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x69, 0x74, 0x20, 0x62,
+ 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x77, 0x69, 0x74, 0x6e,
+ 0x65, 0x73, 0x73, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20,
+ 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20,
+ 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x61, 0x20, 0x73, 0x74, 0x6f, 0x6e, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x74, 0x20, 0x69, 0x74,
+ 0x20, 0x75, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x70, 0x69,
+ 0x6c, 0x6c, 0x61, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a,
+ 0x61, 0x63, 0x6f, 0x62, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x65, 0x74, 0x68,
+ 0x72, 0x65, 0x6e, 0x2c, 0x20, 0x47, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x73, 0x74, 0x6f, 0x6e, 0x65, 0x73, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x73, 0x74,
+ 0x6f, 0x6e, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61,
+ 0x64, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x65, 0x61, 0x70, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x64, 0x69, 0x64,
+ 0x20, 0x65, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x75,
+ 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x70,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e,
+ 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x69, 0x74, 0x20, 0x4a,
+ 0x65, 0x67, 0x61, 0x72, 0x73, 0x61, 0x68, 0x61, 0x64, 0x75, 0x74, 0x68,
+ 0x61, 0x3a, 0x20, 0x62, 0x75, 0x74, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62,
+ 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x69, 0x74, 0x20, 0x47,
+ 0x61, 0x6c, 0x65, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20,
+ 0x54, 0x68, 0x69, 0x73, 0x20, 0x68, 0x65, 0x61, 0x70, 0x20, 0x69, 0x73,
+ 0x20, 0x61, 0x20, 0x77, 0x69, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x62,
+ 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20,
+ 0x64, 0x61, 0x79, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f,
+ 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e,
+ 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61,
+ 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x47, 0x61, 0x6c, 0x65, 0x65, 0x64, 0x3b,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4d, 0x69, 0x7a, 0x70, 0x61, 0x68,
+ 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x54, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20,
+ 0x77, 0x61, 0x74, 0x63, 0x68, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65,
+ 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x65, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x77, 0x65, 0x20, 0x61,
+ 0x72, 0x65, 0x20, 0x61, 0x62, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x6e,
+ 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x6e, 0x6f, 0x74, 0x68,
+ 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x49, 0x66, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x61, 0x66, 0x66, 0x6c, 0x69,
+ 0x63, 0x74, 0x20, 0x6d, 0x79, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74,
+ 0x65, 0x72, 0x73, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x69, 0x66, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x61,
+ 0x6b, 0x65, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x69, 0x76,
+ 0x65, 0x73, 0x20, 0x62, 0x65, 0x73, 0x69, 0x64, 0x65, 0x20, 0x6d, 0x79,
+ 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20,
+ 0x6e, 0x6f, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x75, 0x73, 0x3b, 0x20, 0x73, 0x65, 0x65, 0x2c, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x69, 0x73, 0x20, 0x77, 0x69, 0x74, 0x6e, 0x65,
+ 0x73, 0x73, 0x20, 0x62, 0x65, 0x74, 0x77, 0x69, 0x78, 0x74, 0x20, 0x6d,
+ 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62,
+ 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x20, 0x74, 0x68, 0x69,
+ 0x73, 0x20, 0x68, 0x65, 0x61, 0x70, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20,
+ 0x70, 0x69, 0x6c, 0x6c, 0x61, 0x72, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63,
+ 0x68, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x63, 0x61, 0x73,
+ 0x74, 0x20, 0x62, 0x65, 0x74, 0x77, 0x69, 0x78, 0x74, 0x20, 0x6d, 0x65,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3a, 0x20, 0x0a,
+ 0x54, 0x68, 0x69, 0x73, 0x20, 0x68, 0x65, 0x61, 0x70, 0x20, 0x62, 0x65,
+ 0x20, 0x77, 0x69, 0x74, 0x6e, 0x65, 0x73, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x70, 0x69, 0x6c, 0x6c, 0x61,
+ 0x72, 0x20, 0x62, 0x65, 0x20, 0x77, 0x69, 0x74, 0x6e, 0x65, 0x73, 0x73,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c,
+ 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x70, 0x61, 0x73, 0x73, 0x20, 0x6f,
+ 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x68, 0x65, 0x61,
+ 0x70, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x70,
+ 0x61, 0x73, 0x73, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x69,
+ 0x73, 0x20, 0x68, 0x65, 0x61, 0x70, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x69, 0x73, 0x20, 0x70, 0x69, 0x6c, 0x6c, 0x61, 0x72, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x68, 0x61, 0x72, 0x6d, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x4e, 0x61, 0x68, 0x6f, 0x72, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72,
+ 0x2c, 0x20, 0x6a, 0x75, 0x64, 0x67, 0x65, 0x20, 0x62, 0x65, 0x74, 0x77,
+ 0x69, 0x78, 0x74, 0x20, 0x75, 0x73, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20,
+ 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x73, 0x77, 0x61, 0x72, 0x65, 0x20,
+ 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x65, 0x61, 0x72, 0x20,
+ 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x2e, 0x20, 0x0a, 0x54, 0x68,
+ 0x65, 0x6e, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x6f, 0x66, 0x66,
+ 0x65, 0x72, 0x65, 0x64, 0x20, 0x73, 0x61, 0x63, 0x72, 0x69, 0x66, 0x69,
+ 0x63, 0x65, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63,
+ 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72,
+ 0x65, 0x74, 0x68, 0x72, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x61,
+ 0x74, 0x20, 0x62, 0x72, 0x65, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x64, 0x69, 0x64, 0x20, 0x65, 0x61,
+ 0x74, 0x20, 0x62, 0x72, 0x65, 0x61, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x61, 0x72, 0x72, 0x69, 0x65, 0x64, 0x20, 0x61, 0x6c, 0x6c,
+ 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x65, 0x61, 0x72, 0x6c, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x4c,
+ 0x61, 0x62, 0x61, 0x6e, 0x20, 0x72, 0x6f, 0x73, 0x65, 0x20, 0x75, 0x70,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6b, 0x69, 0x73, 0x73, 0x65, 0x64,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74,
+ 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x6c, 0x65,
+ 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x20, 0x64, 0x65, 0x70,
+ 0x61, 0x72, 0x74, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72,
+ 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x77,
+ 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77,
+ 0x61, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x6d, 0x65, 0x74, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x4a, 0x61, 0x63,
+ 0x6f, 0x62, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c,
+ 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x54, 0x68,
+ 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x47, 0x6f, 0x64, 0x27, 0x73, 0x20,
+ 0x68, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x4d, 0x61, 0x68, 0x61, 0x6e,
+ 0x61, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61,
+ 0x63, 0x6f, 0x62, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x65, 0x73,
+ 0x73, 0x65, 0x6e, 0x67, 0x65, 0x72, 0x73, 0x20, 0x62, 0x65, 0x66, 0x6f,
+ 0x72, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x74, 0x6f, 0x20, 0x45, 0x73,
+ 0x61, 0x75, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68,
+ 0x65, 0x72, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x65, 0x69, 0x72,
+ 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72,
+ 0x79, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x64, 0x6f, 0x6d, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
+ 0x6e, 0x64, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x73,
+ 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x73, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x79, 0x65, 0x20, 0x73, 0x70, 0x65,
+ 0x61, 0x6b, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x79, 0x20, 0x6c,
+ 0x6f, 0x72, 0x64, 0x20, 0x45, 0x73, 0x61, 0x75, 0x3b, 0x20, 0x54, 0x68,
+ 0x79, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x20, 0x4a, 0x61,
+ 0x63, 0x6f, 0x62, 0x20, 0x73, 0x61, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+ 0x75, 0x73, 0x2c, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x73,
+ 0x6f, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x74, 0x61, 0x79, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72,
+ 0x65, 0x20, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x20, 0x6e, 0x6f, 0x77, 0x3a,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65,
+ 0x20, 0x6f, 0x78, 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61,
+ 0x73, 0x73, 0x65, 0x73, 0x2c, 0x20, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x73,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x65, 0x6e, 0x73, 0x65, 0x72,
+ 0x76, 0x61, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77,
+ 0x6f, 0x6d, 0x65, 0x6e, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65,
+ 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x65, 0x6c,
+ 0x6c, 0x20, 0x6d, 0x79, 0x20, 0x6c, 0x6f, 0x72, 0x64, 0x2c, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x66, 0x69,
+ 0x6e, 0x64, 0x20, 0x67, 0x72, 0x61, 0x63, 0x65, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x79, 0x20, 0x73, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73,
+ 0x65, 0x6e, 0x67, 0x65, 0x72, 0x73, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72,
+ 0x6e, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62,
+ 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x57, 0x65,
+ 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x45, 0x73, 0x61,
+ 0x75, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20,
+ 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x20, 0x74, 0x6f,
+ 0x20, 0x6d, 0x65, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x75, 0x72, 0x20, 0x68, 0x75, 0x6e,
+ 0x64, 0x72, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x6e,
+ 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67,
+ 0x72, 0x65, 0x61, 0x74, 0x6c, 0x79, 0x20, 0x61, 0x66, 0x72, 0x61, 0x69,
+ 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x73, 0x74, 0x72, 0x65,
+ 0x73, 0x73, 0x65, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x72, 0x64, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x6c, 0x73, 0x2c, 0x20, 0x69, 0x6e,
+ 0x74, 0x6f, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x62, 0x61, 0x6e, 0x64, 0x73,
+ 0x3b, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x49, 0x66, 0x20, 0x45, 0x73, 0x61, 0x75, 0x20, 0x63, 0x6f, 0x6d,
+ 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x6e, 0x65,
+ 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x6d, 0x69, 0x74, 0x65, 0x20, 0x69, 0x74, 0x2c, 0x20,
+ 0x74, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x74, 0x68,
+ 0x65, 0x72, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x6c, 0x65, 0x66, 0x74,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x65, 0x73, 0x63, 0x61, 0x70,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f,
+ 0x62, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4f, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x66, 0x61, 0x74, 0x68,
+ 0x65, 0x72, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x6d,
+ 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x49, 0x73, 0x61,
+ 0x61, 0x63, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x73, 0x61, 0x69, 0x64, 0x73,
+ 0x74, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x52,
+ 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6b,
+ 0x69, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x64, 0x65, 0x61, 0x6c, 0x20,
+ 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x3a, 0x20, 0x0a, 0x49, 0x20, 0x61, 0x6d, 0x20, 0x6e, 0x6f,
+ 0x74, 0x20, 0x77, 0x6f, 0x72, 0x74, 0x68, 0x79, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x72,
+ 0x63, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x75,
+ 0x74, 0x68, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x73, 0x68, 0x65, 0x77,
+ 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x3b, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x74, 0x61,
+ 0x66, 0x66, 0x20, 0x49, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x20,
+ 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4a, 0x6f,
+ 0x72, 0x64, 0x61, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x6f,
+ 0x77, 0x20, 0x49, 0x20, 0x61, 0x6d, 0x20, 0x62, 0x65, 0x63, 0x6f, 0x6d,
+ 0x65, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x62, 0x61, 0x6e, 0x64, 0x73, 0x2e,
+ 0x20, 0x0a, 0x44, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x20, 0x6d, 0x65,
+ 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72, 0x61, 0x79, 0x20, 0x74, 0x68, 0x65,
+ 0x65, 0x2c, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x68, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x62,
+ 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x66, 0x72, 0x6f, 0x6d,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x45, 0x73, 0x61, 0x75, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x49,
+ 0x20, 0x66, 0x65, 0x61, 0x72, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x6c,
+ 0x65, 0x73, 0x74, 0x20, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x6d, 0x69,
+ 0x74, 0x65, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64,
+ 0x72, 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x73, 0x61, 0x69, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x49,
+ 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x73, 0x75, 0x72, 0x65, 0x6c, 0x79,
+ 0x20, 0x64, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x67, 0x6f, 0x6f,
+ 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20,
+ 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x61, 0x2c, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65,
+ 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x65, 0x64, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x6c, 0x6f, 0x64,
+ 0x67, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x6e, 0x69, 0x67, 0x68,
+ 0x74, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63,
+ 0x68, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x70, 0x72, 0x65,
+ 0x73, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x45, 0x73, 0x61,
+ 0x75, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65,
+ 0x72, 0x3b, 0x20, 0x0a, 0x54, 0x77, 0x6f, 0x20, 0x68, 0x75, 0x6e, 0x64,
+ 0x72, 0x65, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x67, 0x6f, 0x61, 0x74,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x77, 0x65, 0x6e, 0x74,
+ 0x79, 0x20, 0x68, 0x65, 0x20, 0x67, 0x6f, 0x61, 0x74, 0x73, 0x2c, 0x20,
+ 0x74, 0x77, 0x6f, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20,
+ 0x65, 0x77, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x77,
+ 0x65, 0x6e, 0x74, 0x79, 0x20, 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x20, 0x0a,
+ 0x54, 0x68, 0x69, 0x72, 0x74, 0x79, 0x20, 0x6d, 0x69, 0x6c, 0x63, 0x68,
+ 0x20, 0x63, 0x61, 0x6d, 0x65, 0x6c, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x63, 0x6f, 0x6c, 0x74, 0x73,
+ 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x79, 0x20, 0x6b, 0x69, 0x6e, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x65, 0x6e, 0x20, 0x62, 0x75,
+ 0x6c, 0x6c, 0x73, 0x2c, 0x20, 0x74, 0x77, 0x65, 0x6e, 0x74, 0x79, 0x20,
+ 0x73, 0x68, 0x65, 0x20, 0x61, 0x73, 0x73, 0x65, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x65, 0x6e, 0x20, 0x66, 0x6f, 0x61, 0x6c, 0x73,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x65,
+ 0x6c, 0x69, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61,
+ 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x65,
+ 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x64, 0x72, 0x6f, 0x76, 0x65, 0x20, 0x62, 0x79, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x73, 0x65, 0x6c, 0x76, 0x65, 0x73, 0x3b, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74,
+ 0x73, 0x2c, 0x20, 0x50, 0x61, 0x73, 0x73, 0x20, 0x6f, 0x76, 0x65, 0x72,
+ 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x6d, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x70, 0x75, 0x74, 0x20, 0x61, 0x20, 0x73, 0x70,
+ 0x61, 0x63, 0x65, 0x20, 0x62, 0x65, 0x74, 0x77, 0x69, 0x78, 0x74, 0x20,
+ 0x64, 0x72, 0x6f, 0x76, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x72,
+ 0x6f, 0x76, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x65, 0x6d, 0x6f, 0x73, 0x74, 0x2c,
+ 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x57, 0x68, 0x65,
+ 0x6e, 0x20, 0x45, 0x73, 0x61, 0x75, 0x20, 0x6d, 0x79, 0x20, 0x62, 0x72,
+ 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6d, 0x65, 0x65, 0x74, 0x65, 0x74,
+ 0x68, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x61, 0x73, 0x6b, 0x65, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c,
+ 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x57, 0x68, 0x6f,
+ 0x73, 0x65, 0x20, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x3f,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x69, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x67, 0x6f, 0x65, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x3f,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x61,
+ 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x62, 0x65, 0x66,
+ 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3f, 0x20, 0x0a, 0x54,
+ 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x74, 0x20, 0x73, 0x61, 0x79, 0x2c, 0x20, 0x54, 0x68, 0x65, 0x79,
+ 0x20, 0x62, 0x65, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x72, 0x76,
+ 0x61, 0x6e, 0x74, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x27, 0x73, 0x3b,
+ 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x70, 0x72, 0x65,
+ 0x73, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x6d, 0x79, 0x20, 0x6c, 0x6f, 0x72, 0x64, 0x20, 0x45,
+ 0x73, 0x61, 0x75, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x62, 0x65,
+ 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x68,
+ 0x65, 0x20, 0x69, 0x73, 0x20, 0x62, 0x65, 0x68, 0x69, 0x6e, 0x64, 0x20,
+ 0x75, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x73, 0x6f, 0x20,
+ 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x69,
+ 0x72, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x72, 0x6f, 0x76, 0x65, 0x73,
+ 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x4f, 0x6e,
+ 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x72,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x79, 0x65, 0x20, 0x73, 0x70,
+ 0x65, 0x61, 0x6b, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x45, 0x73, 0x61,
+ 0x75, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x79, 0x65, 0x20, 0x66,
+ 0x69, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x73, 0x61, 0x79, 0x20, 0x79, 0x65, 0x20, 0x6d, 0x6f, 0x72,
+ 0x65, 0x6f, 0x76, 0x65, 0x72, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x2c, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61,
+ 0x6e, 0x74, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x69, 0x73, 0x20,
+ 0x62, 0x65, 0x68, 0x69, 0x6e, 0x64, 0x20, 0x75, 0x73, 0x2e, 0x20, 0x46,
+ 0x6f, 0x72, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20,
+ 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61,
+ 0x73, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x67, 0x6f, 0x65, 0x74, 0x68, 0x20, 0x62,
+ 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x77, 0x61, 0x72, 0x64, 0x20,
+ 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x73, 0x65, 0x65, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x66, 0x61, 0x63, 0x65, 0x3b, 0x20, 0x70, 0x65, 0x72,
+ 0x61, 0x64, 0x76, 0x65, 0x6e, 0x74, 0x75, 0x72, 0x65, 0x20, 0x68, 0x65,
+ 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x65, 0x2e, 0x20, 0x0a, 0x53, 0x6f, 0x20,
+ 0x77, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x65,
+ 0x73, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x62, 0x65,
+ 0x66, 0x6f, 0x72, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x69, 0x6d, 0x73, 0x65, 0x6c, 0x66, 0x20, 0x6c, 0x6f,
+ 0x64, 0x67, 0x65, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6e, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x72, 0x6f, 0x73, 0x65, 0x20, 0x75, 0x70, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x74, 0x77, 0x6f, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x74, 0x77, 0x6f, 0x20,
+ 0x77, 0x6f, 0x6d, 0x65, 0x6e, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x65,
+ 0x6c, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x20, 0x6f,
+ 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x64,
+ 0x20, 0x4a, 0x61, 0x62, 0x62, 0x6f, 0x6b, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x74, 0x68,
+ 0x65, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x6e, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x62, 0x72, 0x6f, 0x6f, 0x6b, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x61, 0x6c, 0x6f,
+ 0x6e, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72,
+ 0x65, 0x20, 0x77, 0x72, 0x65, 0x73, 0x74, 0x6c, 0x65, 0x64, 0x20, 0x61,
+ 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69,
+ 0x6d, 0x20, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x62, 0x72, 0x65, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61,
+ 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x20, 0x70, 0x72,
+ 0x65, 0x76, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x61, 0x67, 0x61, 0x69, 0x6e, 0x73, 0x74, 0x20, 0x68, 0x69, 0x6d, 0x2c,
+ 0x20, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x68, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x6f,
+ 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x74, 0x68, 0x69, 0x67, 0x68, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x6f, 0x6c,
+ 0x6c, 0x6f, 0x77, 0x20, 0x6f, 0x66, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62,
+ 0x27, 0x73, 0x20, 0x74, 0x68, 0x69, 0x67, 0x68, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x6a, 0x6f, 0x69, 0x6e,
+ 0x74, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x68, 0x65, 0x20, 0x77, 0x72, 0x65,
+ 0x73, 0x74, 0x6c, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68,
+ 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x6d, 0x65,
+ 0x20, 0x67, 0x6f, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x64, 0x61, 0x79, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x65, 0x74,
+ 0x68, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20,
+ 0x67, 0x6f, 0x2c, 0x20, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x6d, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c,
+ 0x20, 0x57, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3f, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4a, 0x61, 0x63, 0x6f,
+ 0x62, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x79, 0x20, 0x6e, 0x61, 0x6d,
+ 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x63,
+ 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x6e, 0x6f, 0x20, 0x6d, 0x6f, 0x72,
+ 0x65, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x2c, 0x20, 0x62, 0x75, 0x74,
+ 0x20, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x3a, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x65,
+ 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x70,
+ 0x6f, 0x77, 0x65, 0x72, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d,
+ 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x61, 0x73, 0x74,
+ 0x20, 0x70, 0x72, 0x65, 0x76, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x61,
+ 0x73, 0x6b, 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x54, 0x65, 0x6c, 0x6c,
+ 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72, 0x61, 0x79, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x57, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f,
+ 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x69, 0x74, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x64, 0x6f, 0x73, 0x74, 0x20,
+ 0x61, 0x73, 0x6b, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x6d, 0x79,
+ 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3f, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x68, 0x69,
+ 0x6d, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x63, 0x61, 0x6c, 0x6c,
+ 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65,
+ 0x20, 0x50, 0x65, 0x6e, 0x69, 0x65, 0x6c, 0x3a, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x73, 0x65, 0x65, 0x6e,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x74, 0x6f,
+ 0x20, 0x66, 0x61, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d,
+ 0x79, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x20, 0x69, 0x73, 0x20, 0x70, 0x72,
+ 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x61, 0x73, 0x20, 0x68, 0x65, 0x20, 0x70, 0x61, 0x73, 0x73,
+ 0x65, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x50, 0x65, 0x6e, 0x75,
+ 0x65, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x75, 0x6e, 0x20, 0x72,
+ 0x6f, 0x73, 0x65, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x68, 0x69, 0x6d,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x6c,
+ 0x74, 0x65, 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x74, 0x68, 0x69, 0x67, 0x68, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65,
+ 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x49,
+ 0x73, 0x72, 0x61, 0x65, 0x6c, 0x20, 0x65, 0x61, 0x74, 0x20, 0x6e, 0x6f,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x6e,
+ 0x65, 0x77, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x73, 0x68, 0x72,
+ 0x61, 0x6e, 0x6b, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x69,
+ 0x73, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68,
+ 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x74, 0x68, 0x69, 0x67, 0x68, 0x2c, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x64, 0x61, 0x79, 0x3a, 0x20, 0x62,
+ 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x68, 0x65, 0x20, 0x74, 0x6f,
+ 0x75, 0x63, 0x68, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x6f,
+ 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x6f, 0x66, 0x20, 0x4a, 0x61, 0x63, 0x6f,
+ 0x62, 0x27, 0x73, 0x20, 0x74, 0x68, 0x69, 0x67, 0x68, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x6e, 0x65, 0x77, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x73, 0x68, 0x72, 0x61, 0x6e, 0x6b, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x6c,
+ 0x69, 0x66, 0x74, 0x65, 0x64, 0x20, 0x75, 0x70, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x65, 0x79, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c,
+ 0x6f, 0x6f, 0x6b, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20,
+ 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x45, 0x73, 0x61, 0x75,
+ 0x20, 0x63, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x66, 0x6f, 0x75, 0x72,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x6e,
+ 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x76,
+ 0x69, 0x64, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x69,
+ 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4c,
+ 0x65, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x52, 0x61, 0x63, 0x68, 0x65, 0x6c, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
+ 0x77, 0x6f, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6d, 0x61, 0x69, 0x64, 0x73,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x70, 0x75,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6d, 0x61,
+ 0x69, 0x64, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x69,
+ 0x72, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20, 0x66,
+ 0x6f, 0x72, 0x65, 0x6d, 0x6f, 0x73, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x4c, 0x65, 0x61, 0x68, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x72, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20, 0x61,
+ 0x66, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x52, 0x61,
+ 0x63, 0x68, 0x65, 0x6c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x6f, 0x73,
+ 0x65, 0x70, 0x68, 0x20, 0x68, 0x69, 0x6e, 0x64, 0x65, 0x72, 0x6d, 0x6f,
+ 0x73, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20,
+ 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x68,
+ 0x69, 0x6d, 0x73, 0x65, 0x6c, 0x66, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x76,
+ 0x65, 0x6e, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x2c, 0x20, 0x75, 0x6e,
+ 0x74, 0x69, 0x6c, 0x20, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20,
+ 0x6e, 0x65, 0x61, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x45, 0x73, 0x61, 0x75, 0x20, 0x72, 0x61, 0x6e, 0x20, 0x74,
+ 0x6f, 0x20, 0x6d, 0x65, 0x65, 0x74, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x63, 0x65, 0x64,
+ 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x65,
+ 0x6c, 0x6c, 0x20, 0x6f, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x65,
+ 0x63, 0x6b, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6b, 0x69, 0x73, 0x73,
+ 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x65, 0x70, 0x74, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x66, 0x74, 0x65,
+ 0x64, 0x20, 0x75, 0x70, 0x20, 0x68, 0x69, 0x73, 0x20, 0x65, 0x79, 0x65,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65,
+ 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x57, 0x68, 0x6f, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x6f,
+ 0x73, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x65,
+ 0x3f, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x54, 0x68, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64,
+ 0x72, 0x65, 0x6e, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x67, 0x72, 0x61, 0x63, 0x69,
+ 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20,
+ 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x2e,
+ 0x20, 0x0a, 0x54, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68,
+ 0x61, 0x6e, 0x64, 0x6d, 0x61, 0x69, 0x64, 0x65, 0x6e, 0x73, 0x20, 0x63,
+ 0x61, 0x6d, 0x65, 0x20, 0x6e, 0x65, 0x61, 0x72, 0x2c, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72,
+ 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x62, 0x6f, 0x77, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x73, 0x65, 0x6c, 0x76, 0x65, 0x73,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4c, 0x65, 0x61, 0x68, 0x20,
+ 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x65,
+ 0x72, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20, 0x63,
+ 0x61, 0x6d, 0x65, 0x20, 0x6e, 0x65, 0x61, 0x72, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x62, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x73, 0x65, 0x6c, 0x76, 0x65, 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x4a,
+ 0x6f, 0x73, 0x65, 0x70, 0x68, 0x20, 0x6e, 0x65, 0x61, 0x72, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x52, 0x61, 0x63, 0x68, 0x65, 0x6c, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x62, 0x6f, 0x77, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x73, 0x65, 0x6c, 0x76, 0x65, 0x73,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x2c, 0x20, 0x57, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x65, 0x61,
+ 0x6e, 0x65, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x62, 0x79,
+ 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x64, 0x72,
+ 0x6f, 0x76, 0x65, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x49, 0x20,
+ 0x6d, 0x65, 0x74, 0x3f, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x65, 0x73, 0x65, 0x20,
+ 0x61, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x20,
+ 0x67, 0x72, 0x61, 0x63, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x69, 0x67, 0x68, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79,
+ 0x20, 0x6c, 0x6f, 0x72, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x45, 0x73, 0x61, 0x75, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49,
+ 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x65, 0x6e, 0x6f, 0x75, 0x67, 0x68,
+ 0x2c, 0x20, 0x6d, 0x79, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x3b, 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4e, 0x61, 0x79, 0x2c, 0x20, 0x49, 0x20,
+ 0x70, 0x72, 0x61, 0x79, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x69,
+ 0x66, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65,
+ 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x67, 0x72, 0x61, 0x63, 0x65,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x69, 0x67, 0x68,
+ 0x74, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x63, 0x65,
+ 0x69, 0x76, 0x65, 0x20, 0x6d, 0x79, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65,
+ 0x6e, 0x74, 0x20, 0x61, 0x74, 0x20, 0x6d, 0x79, 0x20, 0x68, 0x61, 0x6e,
+ 0x64, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65,
+ 0x66, 0x6f, 0x72, 0x65, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20,
+ 0x73, 0x65, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20, 0x66, 0x61, 0x63,
+ 0x65, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x67, 0x68,
+ 0x20, 0x49, 0x20, 0x68, 0x61, 0x64, 0x20, 0x73, 0x65, 0x65, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x47, 0x6f, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x77, 0x61, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x65, 0x61, 0x73,
+ 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x2e, 0x20,
+ 0x0a, 0x54, 0x61, 0x6b, 0x65, 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72, 0x61,
+ 0x79, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x6d, 0x79, 0x20, 0x62,
+ 0x6c, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3b, 0x20, 0x62, 0x65, 0x63,
+ 0x61, 0x75, 0x73, 0x65, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68, 0x61, 0x74,
+ 0x68, 0x20, 0x64, 0x65, 0x61, 0x6c, 0x74, 0x20, 0x67, 0x72, 0x61, 0x63,
+ 0x69, 0x6f, 0x75, 0x73, 0x6c, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x63, 0x61,
+ 0x75, 0x73, 0x65, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x65,
+ 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x75, 0x72, 0x67, 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x6b,
+ 0x20, 0x69, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x75,
+ 0x73, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x6f, 0x75, 0x72, 0x20, 0x6a,
+ 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6c, 0x65, 0x74, 0x20, 0x75, 0x73, 0x20, 0x67, 0x6f, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x67, 0x6f,
+ 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c,
+ 0x20, 0x4d, 0x79, 0x20, 0x6c, 0x6f, 0x72, 0x64, 0x20, 0x6b, 0x6e, 0x6f,
+ 0x77, 0x65, 0x74, 0x68, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20, 0x61,
+ 0x72, 0x65, 0x20, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x63, 0x6b,
+ 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x72, 0x64, 0x73, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x79, 0x6f, 0x75, 0x6e, 0x67, 0x20, 0x61,
+ 0x72, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x69, 0x66, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x73,
+ 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x64, 0x72,
+ 0x69, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x6f, 0x6e, 0x65,
+ 0x20, 0x64, 0x61, 0x79, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x64, 0x69, 0x65, 0x2e, 0x20, 0x0a, 0x4c, 0x65, 0x74, 0x20, 0x6d,
+ 0x79, 0x20, 0x6c, 0x6f, 0x72, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72,
+ 0x61, 0x79, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x70, 0x61, 0x73,
+ 0x73, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72,
+ 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e,
+ 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c,
+ 0x6c, 0x20, 0x6c, 0x65, 0x61, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x73, 0x6f,
+ 0x66, 0x74, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64,
+ 0x69, 0x6e, 0x67, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x61, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x67,
+ 0x6f, 0x65, 0x74, 0x68, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20,
+ 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x61,
+ 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x6e, 0x64, 0x75, 0x72,
+ 0x65, 0x2c, 0x20, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x20, 0x49, 0x20, 0x63,
+ 0x6f, 0x6d, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x79, 0x20,
+ 0x6c, 0x6f, 0x72, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x53, 0x65,
+ 0x69, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x73, 0x61,
+ 0x75, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20,
+ 0x6d, 0x65, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x6c, 0x65, 0x61, 0x76, 0x65,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x73,
+ 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x6f, 0x6c, 0x6b, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x2e, 0x20, 0x41, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x57,
+ 0x68, 0x61, 0x74, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x65, 0x74, 0x68, 0x20,
+ 0x69, 0x74, 0x3f, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x6d, 0x65, 0x20, 0x66,
+ 0x69, 0x6e, 0x64, 0x20, 0x67, 0x72, 0x61, 0x63, 0x65, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x67, 0x68, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x6d, 0x79, 0x20, 0x6c, 0x6f, 0x72, 0x64, 0x2e, 0x20, 0x0a,
+ 0x53, 0x6f, 0x20, 0x45, 0x73, 0x61, 0x75, 0x20, 0x72, 0x65, 0x74, 0x75,
+ 0x72, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x64, 0x61,
+ 0x79, 0x20, 0x6f, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x61, 0x79,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x53, 0x65, 0x69, 0x72, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x6a,
+ 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20,
+ 0x53, 0x75, 0x63, 0x63, 0x6f, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61,
+ 0x6e, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x62, 0x6f, 0x6f, 0x74, 0x68, 0x73,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x63, 0x61, 0x74,
+ 0x74, 0x6c, 0x65, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f,
+ 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65,
+ 0x20, 0x69, 0x73, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x53,
+ 0x75, 0x63, 0x63, 0x6f, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20,
+ 0x74, 0x6f, 0x20, 0x53, 0x68, 0x61, 0x6c, 0x65, 0x6d, 0x2c, 0x20, 0x61,
+ 0x20, 0x63, 0x69, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x68, 0x65,
+ 0x63, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61,
+ 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e,
+ 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x68, 0x65, 0x20, 0x63, 0x61,
+ 0x6d, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x50, 0x61, 0x64, 0x61,
+ 0x6e, 0x61, 0x72, 0x61, 0x6d, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70,
+ 0x69, 0x74, 0x63, 0x68, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x74,
+ 0x65, 0x6e, 0x74, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x63, 0x69, 0x74, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20,
+ 0x61, 0x20, 0x70, 0x61, 0x72, 0x63, 0x65, 0x6c, 0x20, 0x6f, 0x66, 0x20,
+ 0x61, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2c, 0x20, 0x77, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x73, 0x70,
+ 0x72, 0x65, 0x61, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x74, 0x65, 0x6e,
+ 0x74, 0x2c, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61,
+ 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68,
+ 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x61,
+ 0x6d, 0x6f, 0x72, 0x2c, 0x20, 0x53, 0x68, 0x65, 0x63, 0x68, 0x65, 0x6d,
+ 0x27, 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65,
+ 0x64, 0x20, 0x70, 0x69, 0x65, 0x63, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x6d, 0x6f, 0x6e, 0x65, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x65, 0x72, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x74, 0x61,
+ 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x69, 0x74, 0x20, 0x45, 0x6c, 0x65, 0x6c, 0x6f, 0x68, 0x65,
+ 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x44, 0x69, 0x6e, 0x61, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x4c,
+ 0x65, 0x61, 0x68, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x2c, 0x20, 0x77, 0x65, 0x6e, 0x74,
+ 0x20, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x65, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e,
+ 0x20, 0x53, 0x68, 0x65, 0x63, 0x68, 0x65, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x61, 0x6d, 0x6f,
+ 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x69, 0x76, 0x69, 0x74, 0x65,
+ 0x2c, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x2c,
+ 0x20, 0x73, 0x61, 0x77, 0x20, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x68, 0x65,
+ 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x6c, 0x61, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x68, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x65, 0x66,
+ 0x69, 0x6c, 0x65, 0x64, 0x20, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x75, 0x6c, 0x20,
+ 0x63, 0x6c, 0x61, 0x76, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x44,
+ 0x69, 0x6e, 0x61, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x75,
+ 0x67, 0x68, 0x74, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x4a, 0x61, 0x63,
+ 0x6f, 0x62, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x6c,
+ 0x6f, 0x76, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x6d,
+ 0x73, 0x65, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x70, 0x61,
+ 0x6b, 0x65, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x6c, 0x79, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x6d, 0x73, 0x65,
+ 0x6c, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x68, 0x65, 0x63,
+ 0x68, 0x65, 0x6d, 0x20, 0x73, 0x70, 0x61, 0x6b, 0x65, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x20, 0x48, 0x61, 0x6d, 0x6f, 0x72, 0x2c, 0x20, 0x73, 0x61, 0x79,
+ 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x47, 0x65, 0x74, 0x20, 0x6d, 0x65, 0x20,
+ 0x74, 0x68, 0x69, 0x73, 0x20, 0x64, 0x61, 0x6d, 0x73, 0x65, 0x6c, 0x20,
+ 0x74, 0x6f, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x68, 0x65, 0x61, 0x72,
+ 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x44, 0x69,
+ 0x6e, 0x61, 0x68, 0x20, 0x68, 0x69, 0x73, 0x20, 0x64, 0x61, 0x75, 0x67,
+ 0x68, 0x74, 0x65, 0x72, 0x3a, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x73, 0x20, 0x63, 0x61, 0x74,
+ 0x74, 0x6c, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x69, 0x65, 0x6c, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x61,
+ 0x63, 0x6f, 0x62, 0x20, 0x68, 0x65, 0x6c, 0x64, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x70, 0x65, 0x61, 0x63, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x69, 0x6c,
+ 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x63,
+ 0x6f, 0x6d, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x48, 0x61,
+ 0x6d, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74, 0x68,
+ 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x68, 0x65, 0x63, 0x68, 0x65,
+ 0x6d, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x74, 0x6f,
+ 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x65, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x6f,
+ 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69,
+ 0x65, 0x6c, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x79, 0x20, 0x68, 0x65, 0x61, 0x72, 0x64, 0x20, 0x69, 0x74, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20,
+ 0x77, 0x65, 0x72, 0x65, 0x20, 0x67, 0x72, 0x69, 0x65, 0x76, 0x65, 0x64,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x77,
+ 0x65, 0x72, 0x65, 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x77, 0x72, 0x6f,
+ 0x74, 0x68, 0x2c, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20,
+ 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x77, 0x72, 0x6f, 0x75, 0x67,
+ 0x68, 0x74, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x79, 0x20, 0x69, 0x6e, 0x20,
+ 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x79,
+ 0x69, 0x6e, 0x67, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x4a, 0x61, 0x63,
+ 0x6f, 0x62, 0x27, 0x73, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65,
+ 0x72, 0x3a, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x69,
+ 0x6e, 0x67, 0x20, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x6e, 0x6f, 0x74,
+ 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x48, 0x61, 0x6d, 0x6f, 0x72, 0x20,
+ 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69,
+ 0x6e, 0x67, 0x2c, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x75, 0x6c,
+ 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x53,
+ 0x68, 0x65, 0x63, 0x68, 0x65, 0x6d, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x65,
+ 0x74, 0x68, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20,
+ 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x3a, 0x20, 0x49, 0x20,
+ 0x70, 0x72, 0x61, 0x79, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x67, 0x69, 0x76,
+ 0x65, 0x20, 0x68, 0x65, 0x72, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x74, 0x6f,
+ 0x20, 0x77, 0x69, 0x66, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x79, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x72,
+ 0x69, 0x61, 0x67, 0x65, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x75,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20,
+ 0x79, 0x6f, 0x75, 0x72, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65,
+ 0x72, 0x73, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x75, 0x73, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x6f, 0x75, 0x72,
+ 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x79, 0x6f, 0x75, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x79, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x64,
+ 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x75, 0x73,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61,
+ 0x6e, 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20,
+ 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x79, 0x6f, 0x75, 0x3b, 0x20,
+ 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x72,
+ 0x61, 0x64, 0x65, 0x20, 0x79, 0x65, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65,
+ 0x69, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x65, 0x74, 0x20,
+ 0x79, 0x6f, 0x75, 0x20, 0x70, 0x6f, 0x73, 0x73, 0x65, 0x73, 0x73, 0x69,
+ 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x68, 0x65, 0x63, 0x68, 0x65,
+ 0x6d, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x68, 0x65, 0x72, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x65, 0x72, 0x20,
+ 0x62, 0x72, 0x65, 0x74, 0x68, 0x72, 0x65, 0x6e, 0x2c, 0x20, 0x4c, 0x65,
+ 0x74, 0x20, 0x6d, 0x65, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x67, 0x72,
+ 0x61, 0x63, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20,
+ 0x65, 0x79, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68,
+ 0x61, 0x74, 0x20, 0x79, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x73, 0x61, 0x79, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x20,
+ 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x67, 0x69, 0x76, 0x65, 0x2e,
+ 0x20, 0x0a, 0x41, 0x73, 0x6b, 0x20, 0x6d, 0x65, 0x20, 0x6e, 0x65, 0x76,
+ 0x65, 0x72, 0x20, 0x73, 0x6f, 0x20, 0x6d, 0x75, 0x63, 0x68, 0x20, 0x64,
+ 0x6f, 0x77, 0x72, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x69, 0x66,
+ 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c,
+ 0x6c, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x72,
+ 0x64, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x73, 0x20, 0x79, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x73, 0x61, 0x79, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x6d, 0x65, 0x3a, 0x20, 0x62, 0x75, 0x74, 0x20, 0x67, 0x69,
+ 0x76, 0x65, 0x20, 0x6d, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61,
+ 0x6d, 0x73, 0x65, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x69, 0x66, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62,
+ 0x20, 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x65, 0x64, 0x20, 0x53, 0x68,
+ 0x65, 0x63, 0x68, 0x65, 0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48, 0x61,
+ 0x6d, 0x6f, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x61, 0x74, 0x68,
+ 0x65, 0x72, 0x20, 0x64, 0x65, 0x63, 0x65, 0x69, 0x74, 0x66, 0x75, 0x6c,
+ 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x68, 0x65,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6c, 0x65, 0x64,
+ 0x20, 0x44, 0x69, 0x6e, 0x61, 0x68, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72,
+ 0x20, 0x73, 0x69, 0x73, 0x74, 0x65, 0x72, 0x3a, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x57,
+ 0x65, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x64, 0x6f, 0x20,
+ 0x74, 0x68, 0x69, 0x73, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2c, 0x20,
+ 0x74, 0x6f, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x6f, 0x75, 0x72, 0x20,
+ 0x73, 0x69, 0x73, 0x74, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x6f, 0x6e,
+ 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x75, 0x6e,
+ 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x63, 0x69, 0x73, 0x65, 0x64, 0x3b,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x61, 0x20, 0x72, 0x65, 0x70, 0x72, 0x6f, 0x61, 0x63,
+ 0x68, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x75, 0x73, 0x3a, 0x20, 0x0a,
+ 0x42, 0x75, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x77, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73,
+ 0x65, 0x6e, 0x74, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x79, 0x6f, 0x75,
+ 0x3a, 0x20, 0x49, 0x66, 0x20, 0x79, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x62, 0x65, 0x20, 0x61, 0x73, 0x20, 0x77, 0x65, 0x20, 0x62, 0x65,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x6d, 0x61, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x6f, 0x75,
+ 0x20, 0x62, 0x65, 0x20, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x63, 0x69,
+ 0x73, 0x65, 0x64, 0x3b, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x6e, 0x20, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x77, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20,
+ 0x6f, 0x75, 0x72, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72,
+ 0x73, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x79, 0x6f, 0x75, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x74, 0x61, 0x6b, 0x65, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x64, 0x61,
+ 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x75,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x20, 0x77, 0x69,
+ 0x6c, 0x6c, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x79, 0x6f, 0x75, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77,
+ 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x63, 0x6f, 0x6d,
+ 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65,
+ 0x2e, 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x69, 0x66, 0x20, 0x79, 0x65,
+ 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x68, 0x65,
+ 0x61, 0x72, 0x6b, 0x65, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x75,
+ 0x73, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x63, 0x69, 0x72,
+ 0x63, 0x75, 0x6d, 0x63, 0x69, 0x73, 0x65, 0x64, 0x3b, 0x20, 0x74, 0x68,
+ 0x65, 0x6e, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x77, 0x65, 0x20, 0x74,
+ 0x61, 0x6b, 0x65, 0x20, 0x6f, 0x75, 0x72, 0x20, 0x64, 0x61, 0x75, 0x67,
+ 0x68, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65,
+ 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x67, 0x6f, 0x6e,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x69,
+ 0x72, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x20, 0x70, 0x6c, 0x65, 0x61,
+ 0x73, 0x65, 0x64, 0x20, 0x48, 0x61, 0x6d, 0x6f, 0x72, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x53, 0x68, 0x65, 0x63, 0x68, 0x65, 0x6d, 0x20, 0x48,
+ 0x61, 0x6d, 0x6f, 0x72, 0x27, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x79, 0x6f, 0x75,
+ 0x6e, 0x67, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x64, 0x65, 0x66, 0x65, 0x72,
+ 0x72, 0x65, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x64,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2c,
+ 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x68, 0x65, 0x20,
+ 0x68, 0x61, 0x64, 0x20, 0x64, 0x65, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x20,
+ 0x69, 0x6e, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x27, 0x73, 0x20, 0x64,
+ 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6d, 0x6f, 0x72, 0x65,
+ 0x20, 0x68, 0x6f, 0x6e, 0x6f, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x20,
+ 0x74, 0x68, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x48, 0x61, 0x6d, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x53, 0x68, 0x65, 0x63, 0x68, 0x65, 0x6d, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x74, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x63, 0x69, 0x74,
+ 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x75,
+ 0x6e, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x69,
+ 0x72, 0x20, 0x63, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69,
+ 0x6e, 0x67, 0x2c, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x73, 0x65, 0x20, 0x6d,
+ 0x65, 0x6e, 0x20, 0x61, 0x72, 0x65, 0x20, 0x70, 0x65, 0x61, 0x63, 0x65,
+ 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x75, 0x73,
+ 0x3b, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20,
+ 0x6c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x64, 0x77, 0x65,
+ 0x6c, 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61,
+ 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x72, 0x61, 0x64,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x3b, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x2c,
+ 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x69, 0x74, 0x20,
+ 0x69, 0x73, 0x20, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x20, 0x65, 0x6e, 0x6f,
+ 0x75, 0x67, 0x68, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x3b, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x75, 0x73, 0x20, 0x74, 0x61, 0x6b,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x64, 0x61, 0x75, 0x67,
+ 0x68, 0x74, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x73, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x75, 0x73, 0x20, 0x67, 0x69,
+ 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x6f, 0x75, 0x72, 0x20,
+ 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a,
+ 0x4f, 0x6e, 0x6c, 0x79, 0x20, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e,
+ 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x75, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x6f, 0x20,
+ 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x75,
+ 0x73, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x6f, 0x6e, 0x65,
+ 0x20, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x2c, 0x20, 0x69, 0x66, 0x20,
+ 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6d, 0x61, 0x6c, 0x65, 0x20, 0x61,
+ 0x6d, 0x6f, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x20, 0x62, 0x65, 0x20, 0x63,
+ 0x69, 0x72, 0x63, 0x75, 0x6d, 0x63, 0x69, 0x73, 0x65, 0x64, 0x2c, 0x20,
+ 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x61, 0x72, 0x65, 0x20,
+ 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x63, 0x69, 0x73, 0x65, 0x64, 0x2e,
+ 0x20, 0x0a, 0x53, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x73,
+ 0x75, 0x62, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x62, 0x65, 0x61, 0x73, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x27, 0x73, 0x20,
+ 0x62, 0x65, 0x20, 0x6f, 0x75, 0x72, 0x27, 0x73, 0x3f, 0x20, 0x6f, 0x6e,
+ 0x6c, 0x79, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x75, 0x73, 0x20, 0x63, 0x6f,
+ 0x6e, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x79, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x6c,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x75, 0x73, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x48, 0x61, 0x6d, 0x6f,
+ 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x53,
+ 0x68, 0x65, 0x63, 0x68, 0x65, 0x6d, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73,
+ 0x6f, 0x6e, 0x20, 0x68, 0x65, 0x61, 0x72, 0x6b, 0x65, 0x6e, 0x65, 0x64,
+ 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65,
+ 0x6e, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x67, 0x61, 0x74, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x63, 0x69, 0x74, 0x79, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6d, 0x61, 0x6c, 0x65, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x63, 0x69, 0x73,
+ 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x74, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x63, 0x69, 0x74, 0x79, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20,
+ 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64, 0x20, 0x64, 0x61, 0x79,
+ 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x77, 0x65, 0x72, 0x65, 0x20, 0x73, 0x6f, 0x72, 0x65, 0x2c, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4a,
+ 0x61, 0x63, 0x6f, 0x62, 0x2c, 0x20, 0x53, 0x69, 0x6d, 0x65, 0x6f, 0x6e,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x65, 0x76, 0x69, 0x2c, 0x20, 0x44,
+ 0x69, 0x6e, 0x61, 0x68, 0x27, 0x73, 0x20, 0x62, 0x72, 0x65, 0x74, 0x68,
+ 0x72, 0x65, 0x6e, 0x2c, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x65, 0x61,
+ 0x63, 0x68, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73,
+ 0x77, 0x6f, 0x72, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61,
+ 0x6d, 0x65, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x63, 0x69, 0x74, 0x79, 0x20, 0x62, 0x6f, 0x6c, 0x64, 0x6c, 0x79, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x6c, 0x65, 0x77, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6c, 0x65, 0x73, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x73,
+ 0x6c, 0x65, 0x77, 0x20, 0x48, 0x61, 0x6d, 0x6f, 0x72, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x53, 0x68, 0x65, 0x63, 0x68, 0x65, 0x6d, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x64, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x44, 0x69, 0x6e, 0x61, 0x68,
+ 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x68, 0x65, 0x63,
+ 0x68, 0x65, 0x6d, 0x27, 0x73, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x75,
+ 0x74, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x63, 0x61,
+ 0x6d, 0x65, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x6c, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x70, 0x6f, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x69, 0x74, 0x79, 0x2c, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x68, 0x61, 0x64, 0x20, 0x64, 0x65,
+ 0x66, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20,
+ 0x73, 0x69, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65,
+ 0x79, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72,
+ 0x20, 0x73, 0x68, 0x65, 0x65, 0x70, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6f, 0x78, 0x65, 0x6e, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x61, 0x73,
+ 0x73, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x69, 0x74, 0x79, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x68,
+ 0x69, 0x63, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2c, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72,
+ 0x20, 0x77, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6c,
+ 0x69, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x73, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x77, 0x69,
+ 0x76, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x74, 0x68, 0x65,
+ 0x79, 0x20, 0x63, 0x61, 0x70, 0x74, 0x69, 0x76, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x73, 0x70, 0x6f, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x65,
+ 0x76, 0x65, 0x6e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x74,
+ 0x6f, 0x20, 0x53, 0x69, 0x6d, 0x65, 0x6f, 0x6e, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x4c, 0x65, 0x76, 0x69, 0x2c, 0x20, 0x59, 0x65, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x74, 0x72, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x64, 0x20,
+ 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x6d,
+ 0x65, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x74, 0x69, 0x6e, 0x6b, 0x20, 0x61,
+ 0x6d, 0x6f, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x68,
+ 0x61, 0x62, 0x69, 0x74, 0x61, 0x6e, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6d,
+ 0x6f, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x61, 0x6e, 0x61,
+ 0x61, 0x6e, 0x69, 0x74, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x50, 0x65, 0x72, 0x69, 0x7a, 0x7a, 0x69, 0x74, 0x65,
+ 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x62, 0x65, 0x69,
+ 0x6e, 0x67, 0x20, 0x66, 0x65, 0x77, 0x20, 0x69, 0x6e, 0x20, 0x6e, 0x75,
+ 0x6d, 0x62, 0x65, 0x72, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x67, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x73, 0x65, 0x6c, 0x76, 0x65, 0x73, 0x20, 0x74,
+ 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x61, 0x67, 0x61, 0x69,
+ 0x6e, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x6c, 0x61, 0x79, 0x20, 0x6d, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x49, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20,
+ 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x65, 0x64, 0x2c, 0x20, 0x49,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x79, 0x20, 0x68, 0x6f, 0x75, 0x73,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x53, 0x68, 0x6f, 0x75, 0x6c,
+ 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x65, 0x61, 0x6c, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x69, 0x73, 0x74, 0x65,
+ 0x72, 0x20, 0x61, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6e,
+ 0x20, 0x68, 0x61, 0x72, 0x6c, 0x6f, 0x74, 0x3f, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x2c, 0x20, 0x41,
+ 0x72, 0x69, 0x73, 0x65, 0x2c, 0x20, 0x67, 0x6f, 0x20, 0x75, 0x70, 0x20,
+ 0x74, 0x6f, 0x20, 0x42, 0x65, 0x74, 0x68, 0x65, 0x6c, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x6b, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c,
+ 0x74, 0x61, 0x72, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x47, 0x6f, 0x64,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61,
+ 0x72, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x65, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x66, 0x6c, 0x65, 0x64, 0x64, 0x65, 0x73, 0x74, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x45, 0x73, 0x61, 0x75, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62,
+ 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65,
+ 0x6e, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x6f,
+ 0x75, 0x73, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68,
+ 0x69, 0x6d, 0x2c, 0x20, 0x50, 0x75, 0x74, 0x20, 0x61, 0x77, 0x61, 0x79,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x67, 0x65,
+ 0x20, 0x67, 0x6f, 0x64, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61,
+ 0x72, 0x65, 0x20, 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x20, 0x79, 0x6f, 0x75,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x20, 0x63, 0x6c, 0x65,
+ 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x68, 0x61, 0x6e,
+ 0x67, 0x65, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x67, 0x61, 0x72, 0x6d,
+ 0x65, 0x6e, 0x74, 0x73, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x6c,
+ 0x65, 0x74, 0x20, 0x75, 0x73, 0x20, 0x61, 0x72, 0x69, 0x73, 0x65, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x6f, 0x20, 0x75, 0x70, 0x20, 0x74,
+ 0x6f, 0x20, 0x42, 0x65, 0x74, 0x68, 0x65, 0x6c, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6d, 0x61, 0x6b,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61,
+ 0x6c, 0x74, 0x61, 0x72, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x47, 0x6f,
+ 0x64, 0x2c, 0x20, 0x77, 0x68, 0x6f, 0x20, 0x61, 0x6e, 0x73, 0x77, 0x65,
+ 0x72, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20,
+ 0x64, 0x69, 0x73, 0x74, 0x72, 0x65, 0x73, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x77, 0x61, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d,
+ 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x79,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x49, 0x20, 0x77, 0x65, 0x6e,
+ 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x67, 0x61, 0x76, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4a,
+ 0x61, 0x63, 0x6f, 0x62, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x20, 0x67, 0x6f, 0x64,
+ 0x73, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x68, 0x61,
+ 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x65, 0x61, 0x72, 0x72, 0x69, 0x6e,
+ 0x67, 0x73, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x65,
+ 0x61, 0x72, 0x73, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x63,
+ 0x6f, 0x62, 0x20, 0x68, 0x69, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20,
+ 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x61,
+ 0x6b, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x62, 0x79, 0x20, 0x53, 0x68, 0x65, 0x63, 0x68, 0x65, 0x6d, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x6a, 0x6f,
+ 0x75, 0x72, 0x6e, 0x65, 0x79, 0x65, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20,
+ 0x6f, 0x66, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x77, 0x61, 0x73, 0x20, 0x75,
+ 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x69, 0x74, 0x69,
+ 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x61, 0x62, 0x6f, 0x75, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x64, 0x69, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x70, 0x75, 0x72, 0x73, 0x75, 0x65, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x2e, 0x20, 0x0a, 0x53, 0x6f, 0x20,
+ 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74,
+ 0x6f, 0x20, 0x4c, 0x75, 0x7a, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61,
+ 0x6e, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x2c, 0x20,
+ 0x42, 0x65, 0x74, 0x68, 0x65, 0x6c, 0x2c, 0x20, 0x68, 0x65, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70,
+ 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77,
+ 0x65, 0x72, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x62, 0x75,
+ 0x69, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61, 0x6e,
+ 0x20, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70,
+ 0x6c, 0x61, 0x63, 0x65, 0x20, 0x45, 0x6c, 0x62, 0x65, 0x74, 0x68, 0x65,
+ 0x6c, 0x3a, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x61, 0x70, 0x70,
+ 0x65, 0x61, 0x72, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68,
+ 0x69, 0x6d, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x68, 0x65, 0x20,
+ 0x66, 0x6c, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a,
+ 0x42, 0x75, 0x74, 0x20, 0x44, 0x65, 0x62, 0x6f, 0x72, 0x61, 0x68, 0x20,
+ 0x52, 0x65, 0x62, 0x65, 0x6b, 0x61, 0x68, 0x27, 0x73, 0x20, 0x6e, 0x75,
+ 0x72, 0x73, 0x65, 0x20, 0x64, 0x69, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x62, 0x75,
+ 0x72, 0x69, 0x65, 0x64, 0x20, 0x62, 0x65, 0x6e, 0x65, 0x61, 0x74, 0x68,
+ 0x20, 0x42, 0x65, 0x74, 0x68, 0x65, 0x6c, 0x20, 0x75, 0x6e, 0x64, 0x65,
+ 0x72, 0x20, 0x61, 0x6e, 0x20, 0x6f, 0x61, 0x6b, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x63, 0x61, 0x6c,
+ 0x6c, 0x65, 0x64, 0x20, 0x41, 0x6c, 0x6c, 0x6f, 0x6e, 0x62, 0x61, 0x63,
+ 0x68, 0x75, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x65, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x20, 0x61,
+ 0x67, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x68,
+ 0x65, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x50, 0x61, 0x64, 0x61, 0x6e, 0x61, 0x72, 0x61, 0x6d, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64,
+ 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x54, 0x68, 0x79, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x20, 0x69, 0x73, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x3a,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x63,
+ 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6d, 0x6f,
+ 0x72, 0x65, 0x20, 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x2c, 0x20, 0x62, 0x75,
+ 0x74, 0x20, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x63,
+ 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x20, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x49,
+ 0x20, 0x61, 0x6d, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x41, 0x6c, 0x6d, 0x69,
+ 0x67, 0x68, 0x74, 0x79, 0x3a, 0x20, 0x62, 0x65, 0x20, 0x66, 0x72, 0x75,
+ 0x69, 0x74, 0x66, 0x75, 0x6c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75,
+ 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x3b, 0x20, 0x61, 0x20, 0x6e, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x63,
+ 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x6e, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x62, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x75, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6c, 0x6f, 0x69, 0x6e,
+ 0x73, 0x3b, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20
+};
+unsigned int bible_txt_128k_len = 131072;
diff --git a/drivers/staging/fsl_dce/tests/common/bible.txt.16k.h b/drivers/staging/fsl_dce/tests/common/bible.txt.16k.h
new file mode 100644
index 0000000..98b03e7
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/common/bible.txt.16k.h
@@ -0,0 +1,1369 @@
+unsigned char bible_txt_16k[] = {
+ 0x49, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e,
+ 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65,
+ 0x61, 0x74, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61,
+ 0x76, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e, 0x65, 0x73,
+ 0x73, 0x20, 0x77, 0x61, 0x73, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x65, 0x65, 0x70, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x70, 0x69, 0x72, 0x69, 0x74, 0x20,
+ 0x6f, 0x66, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x6f, 0x76, 0x65, 0x64,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61,
+ 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x6c, 0x69,
+ 0x67, 0x68, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73,
+ 0x61, 0x77, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x20, 0x66, 0x72,
+ 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e,
+ 0x65, 0x73, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x20, 0x44, 0x61, 0x79, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x72, 0x6b,
+ 0x6e, 0x65, 0x73, 0x73, 0x20, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c,
+ 0x65, 0x64, 0x20, 0x4e, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x20, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f,
+ 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x64, 0x61, 0x79,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x66, 0x69, 0x72, 0x6d,
+ 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x69, 0x64, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x69, 0x74, 0x20, 0x64, 0x69, 0x76,
+ 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65,
+ 0x72, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20,
+ 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x75,
+ 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72,
+ 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x61, 0x62,
+ 0x6f, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d,
+ 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69,
+ 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d,
+ 0x65, 0x6e, 0x74, 0x20, 0x48, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x2e, 0x20,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e,
+ 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20,
+ 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x75,
+ 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61,
+ 0x76, 0x65, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x67, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x70, 0x6c,
+ 0x61, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x72, 0x79, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61,
+ 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x72, 0x79,
+ 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x45, 0x61, 0x72, 0x74, 0x68, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x53, 0x65, 0x61, 0x73, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f,
+ 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x62, 0x72, 0x69,
+ 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x67, 0x72, 0x61,
+ 0x73, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x72, 0x62,
+ 0x20, 0x79, 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65,
+ 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x79,
+ 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x77, 0x68, 0x6f, 0x73, 0x65, 0x20,
+ 0x73, 0x65, 0x65, 0x64, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x69,
+ 0x74, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x67, 0x72, 0x61, 0x73, 0x73,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x72, 0x62, 0x20, 0x79,
+ 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65, 0x65, 0x64,
+ 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b,
+ 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x79, 0x69, 0x65, 0x6c, 0x64, 0x69,
+ 0x6e, 0x67, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x2c, 0x20, 0x77, 0x68,
+ 0x6f, 0x73, 0x65, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x69, 0x6e, 0x20, 0x69, 0x74, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69,
+ 0x6e, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69,
+ 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x6f, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64, 0x20, 0x64, 0x61,
+ 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
+ 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72,
+ 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20,
+ 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x79, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6e, 0x69, 0x67, 0x68, 0x74, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c,
+ 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x62, 0x65, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x65, 0x61, 0x73, 0x6f, 0x6e,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64,
+ 0x61, 0x79, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x76,
+ 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x6c,
+ 0x69, 0x67, 0x68, 0x74, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64,
+ 0x65, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20,
+ 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x3b, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x67, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x67, 0x68,
+ 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x61, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x6c, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x68,
+ 0x65, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x74, 0x61, 0x72, 0x73, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x65, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x20,
+ 0x74, 0x6f, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68,
+ 0x74, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x6f, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x69, 0x67,
+ 0x68, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64,
+ 0x69, 0x76, 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e, 0x65, 0x73, 0x73, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67,
+ 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x6f, 0x75, 0x72, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x74, 0x65, 0x72, 0x73, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66,
+ 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x62, 0x75, 0x6e, 0x64, 0x61, 0x6e,
+ 0x74, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x76, 0x69,
+ 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x6c, 0x69,
+ 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x77, 0x6c,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x66, 0x6c,
+ 0x79, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d,
+ 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65,
+ 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x67, 0x72, 0x65, 0x61,
+ 0x74, 0x20, 0x77, 0x68, 0x61, 0x6c, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69,
+ 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x6f, 0x76, 0x65, 0x74, 0x68, 0x2c,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68,
+ 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x62, 0x75, 0x6e,
+ 0x64, 0x61, 0x6e, 0x74, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e, 0x64,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20,
+ 0x77, 0x69, 0x6e, 0x67, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69,
+ 0x6e, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73,
+ 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x73, 0x61, 0x79,
+ 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x42, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75,
+ 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x66, 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74,
+ 0x65, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x61, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70,
+ 0x6c, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x69, 0x66, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e,
+ 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x61,
+ 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e,
+ 0x64, 0x2c, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20,
+ 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61,
+ 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x61, 0x73, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74,
+ 0x68, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61,
+ 0x74, 0x74, 0x6c, 0x65, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x68, 0x69,
+ 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x72, 0x65, 0x65,
+ 0x70, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74,
+ 0x20, 0x75, 0x73, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x6d, 0x61, 0x6e,
+ 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x75, 0x72, 0x20, 0x69, 0x6d, 0x61, 0x67,
+ 0x65, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x6f, 0x75, 0x72,
+ 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x6f,
+ 0x6e, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x69, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x61, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f,
+ 0x76, 0x65, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f,
+ 0x76, 0x65, 0x72, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x72,
+ 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x65,
+ 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x53, 0x6f, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6d,
+ 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x77,
+ 0x6e, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x3b, 0x20, 0x6d, 0x61, 0x6c,
+ 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65,
+ 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x42, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75,
+ 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x72, 0x65, 0x70, 0x6c, 0x65, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x75, 0x62, 0x64, 0x75, 0x65, 0x20, 0x69, 0x74, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x64, 0x6f, 0x6d,
+ 0x69, 0x6e, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x65, 0x61, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x77,
+ 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x65,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x20,
+ 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d,
+ 0x6f, 0x76, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x68,
+ 0x61, 0x76, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x79, 0x6f,
+ 0x75, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x68, 0x65, 0x72, 0x62,
+ 0x20, 0x62, 0x65, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65, 0x65,
+ 0x64, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x72, 0x65, 0x65, 0x2c, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20,
+ 0x79, 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65, 0x65,
+ 0x64, 0x3b, 0x20, 0x74, 0x6f, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x69, 0x74,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x6d, 0x65, 0x61, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x62, 0x65,
+ 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x63, 0x72, 0x65, 0x65, 0x70, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c,
+ 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x2c, 0x20,
+ 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x67, 0x72, 0x65, 0x65, 0x6e,
+ 0x20, 0x68, 0x65, 0x72, 0x62, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x65,
+ 0x61, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x76, 0x65,
+ 0x72, 0x79, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e, 0x67,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72,
+ 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x69, 0x78, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79, 0x2e,
+ 0x20, 0x0a, 0x54, 0x68, 0x75, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68,
+ 0x65, 0x61, 0x76, 0x65, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x68, 0x6f, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x64, 0x61,
+ 0x79, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61,
+ 0x64, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x72,
+ 0x65, 0x73, 0x74, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x62,
+ 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x76, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x6e, 0x63, 0x74, 0x69, 0x66, 0x69,
+ 0x65, 0x64, 0x20, 0x69, 0x74, 0x3a, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75,
+ 0x73, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x69,
+ 0x74, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x72, 0x65, 0x73,
+ 0x74, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x6c, 0x6c,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x68,
+ 0x69, 0x63, 0x68, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65, 0x61,
+ 0x74, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65,
+ 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x77,
+ 0x65, 0x72, 0x65, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x2c,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x73,
+ 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x66, 0x6f,
+ 0x72, 0x65, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x68, 0x65,
+ 0x72, 0x62, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69,
+ 0x65, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x69,
+ 0x74, 0x20, 0x67, 0x72, 0x65, 0x77, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x61, 0x75,
+ 0x73, 0x65, 0x64, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x61,
+ 0x69, 0x6e, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x74,
+ 0x20, 0x61, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x69,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2e, 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x72,
+ 0x65, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x70, 0x20, 0x61, 0x20,
+ 0x6d, 0x69, 0x73, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x68, 0x6f, 0x6c, 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72,
+ 0x6d, 0x65, 0x64, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x75, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x62, 0x72, 0x65, 0x61, 0x74, 0x68, 0x65, 0x64, 0x20,
+ 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x73,
+ 0x74, 0x72, 0x69, 0x6c, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x72,
+ 0x65, 0x61, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x69, 0x66, 0x65,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x62, 0x65,
+ 0x63, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e,
+ 0x67, 0x20, 0x73, 0x6f, 0x75, 0x6c, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x61, 0x20,
+ 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x20, 0x65, 0x61, 0x73, 0x74, 0x77,
+ 0x61, 0x72, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x45, 0x64, 0x65, 0x6e, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x68,
+ 0x65, 0x20, 0x70, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61,
+ 0x6e, 0x20, 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x64,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x72, 0x6f, 0x77, 0x20, 0x65,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x70, 0x6c, 0x65, 0x61, 0x73, 0x61,
+ 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69,
+ 0x67, 0x68, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x6f, 0x6f,
+ 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x66, 0x6f, 0x6f, 0x64, 0x3b, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x6c, 0x69, 0x66, 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x69, 0x64, 0x73, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72,
+ 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x6c, 0x65,
+ 0x64, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x69, 0x6c, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x61, 0x20, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x77,
+ 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x45,
+ 0x64, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68,
+ 0x65, 0x6e, 0x63, 0x65, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x70, 0x61, 0x72, 0x74, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20,
+ 0x66, 0x6f, 0x75, 0x72, 0x20, 0x68, 0x65, 0x61, 0x64, 0x73, 0x2e, 0x20,
+ 0x0a, 0x54, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x69,
+ 0x73, 0x20, 0x50, 0x69, 0x73, 0x6f, 0x6e, 0x3a, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x69, 0x73, 0x20, 0x69, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63,
+ 0x68, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x73, 0x73, 0x65, 0x74, 0x68,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x6f, 0x6c, 0x65, 0x20, 0x6c,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x61, 0x76, 0x69, 0x6c,
+ 0x61, 0x68, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x67, 0x6f, 0x6c, 0x64, 0x3b,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x6f,
+ 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6c,
+ 0x61, 0x6e, 0x64, 0x20, 0x69, 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x3a,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x62, 0x64,
+ 0x65, 0x6c, 0x6c, 0x69, 0x75, 0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6f, 0x6e, 0x79, 0x78, 0x20, 0x73, 0x74, 0x6f, 0x6e,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20, 0x72, 0x69, 0x76, 0x65, 0x72,
+ 0x20, 0x69, 0x73, 0x20, 0x47, 0x69, 0x68, 0x6f, 0x6e, 0x3a, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x73, 0x20, 0x69,
+ 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61,
+ 0x73, 0x73, 0x65, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68,
+ 0x6f, 0x6c, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x45, 0x74, 0x68, 0x69, 0x6f, 0x70, 0x69, 0x61, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64,
+ 0x20, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x48, 0x69,
+ 0x64, 0x64, 0x65, 0x6b, 0x65, 0x6c, 0x3a, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x69, 0x73, 0x20, 0x69, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x67, 0x6f, 0x65, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x77, 0x61, 0x72,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x41, 0x73, 0x73, 0x79, 0x72, 0x69, 0x61, 0x2e, 0x20, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x75, 0x72, 0x74,
+ 0x68, 0x20, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x45,
+ 0x75, 0x70, 0x68, 0x72, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x75,
+ 0x74, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x20, 0x6f, 0x66,
+ 0x20, 0x45, 0x64, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x72, 0x65,
+ 0x73, 0x73, 0x20, 0x69, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f,
+ 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x69, 0x74, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x73,
+ 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x4f, 0x66, 0x20, 0x65, 0x76,
+ 0x65, 0x72, 0x79, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x65, 0x73, 0x74, 0x20, 0x66,
+ 0x72, 0x65, 0x65, 0x6c, 0x79, 0x20, 0x65, 0x61, 0x74, 0x3a, 0x20, 0x0a,
+ 0x42, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
+ 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b,
+ 0x6e, 0x6f, 0x77, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x69,
+ 0x6c, 0x2c, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c,
+ 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x61, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x69, 0x74, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x65, 0x61, 0x74, 0x65, 0x73, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x73, 0x75, 0x72, 0x65,
+ 0x6c, 0x79, 0x20, 0x64, 0x69, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x74, 0x20, 0x69,
+ 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x20,
+ 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6c,
+ 0x6f, 0x6e, 0x65, 0x3b, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61, 0x6e, 0x20,
+ 0x68, 0x65, 0x6c, 0x70, 0x20, 0x6d, 0x65, 0x65, 0x74, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x65,
+ 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x62, 0x65, 0x61, 0x73,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65,
+ 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x61, 0x69, 0x72, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x74, 0x6f,
+ 0x20, 0x73, 0x65, 0x65, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65,
+ 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68,
+ 0x61, 0x74, 0x73, 0x6f, 0x65, 0x76, 0x65, 0x72, 0x20, 0x41, 0x64, 0x61,
+ 0x6d, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x65, 0x76, 0x65,
+ 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x72,
+ 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x67, 0x61, 0x76,
+ 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f,
+ 0x77, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69,
+ 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x76,
+ 0x65, 0x72, 0x79, 0x20, 0x62, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x3b, 0x20,
+ 0x62, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x41, 0x64, 0x61, 0x6d,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x20,
+ 0x68, 0x65, 0x6c, 0x70, 0x20, 0x6d, 0x65, 0x65, 0x74, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x63, 0x61, 0x75, 0x73, 0x65, 0x64, 0x20, 0x61, 0x20, 0x64, 0x65,
+ 0x65, 0x70, 0x20, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x20, 0x74, 0x6f, 0x20,
+ 0x66, 0x61, 0x6c, 0x6c, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x41, 0x64,
+ 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73,
+ 0x6c, 0x65, 0x70, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x72, 0x69, 0x62, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x20, 0x75, 0x70,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20, 0x69,
+ 0x6e, 0x73, 0x74, 0x65, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65,
+ 0x6f, 0x66, 0x3b, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x72, 0x69, 0x62, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x6d, 0x61, 0x64,
+ 0x65, 0x20, 0x68, 0x65, 0x20, 0x61, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68,
+ 0x74, 0x20, 0x68, 0x65, 0x72, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20,
+ 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20,
+ 0x62, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x62,
+ 0x6f, 0x6e, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6c,
+ 0x65, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x66, 0x6c,
+ 0x65, 0x73, 0x68, 0x3a, 0x20, 0x73, 0x68, 0x65, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x57, 0x6f, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x62, 0x65, 0x63, 0x61,
+ 0x75, 0x73, 0x65, 0x20, 0x73, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x4d, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x72, 0x65,
+ 0x66, 0x6f, 0x72, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x61,
+ 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x63, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c,
+ 0x20, 0x62, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x66, 0x6c, 0x65, 0x73,
+ 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6e,
+ 0x61, 0x6b, 0x65, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61,
+ 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69,
+ 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x73, 0x68, 0x61, 0x6d, 0x65, 0x64,
+ 0x2e, 0x20, 0x0a, 0x4e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x72, 0x70, 0x65, 0x6e, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6d,
+ 0x6f, 0x72, 0x65, 0x20, 0x73, 0x75, 0x62, 0x74, 0x69, 0x6c, 0x20, 0x74,
+ 0x68, 0x61, 0x6e, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x62, 0x65, 0x61, 0x73,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65,
+ 0x6c, 0x64, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x2c, 0x20,
+ 0x59, 0x65, 0x61, 0x2c, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x59, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x61, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x72,
+ 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61,
+ 0x72, 0x64, 0x65, 0x6e, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x72, 0x70, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x57, 0x65, 0x20, 0x6d,
+ 0x61, 0x79, 0x20, 0x65, 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x3a, 0x20,
+ 0x0a, 0x42, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x69,
+ 0x64, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67,
+ 0x61, 0x72, 0x64, 0x65, 0x6e, 0x2c, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68,
+ 0x61, 0x74, 0x68, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x59, 0x65,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65,
+ 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x6e, 0x65,
+ 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x79, 0x65, 0x20, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x20, 0x69, 0x74, 0x2c,
+ 0x20, 0x6c, 0x65, 0x73, 0x74, 0x20, 0x79, 0x65, 0x20, 0x64, 0x69, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x72, 0x70, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d,
+ 0x61, 0x6e, 0x2c, 0x20, 0x59, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x72, 0x65, 0x6c, 0x79, 0x20,
+ 0x64, 0x69, 0x65, 0x3a, 0x20, 0x0a, 0x46, 0x6f, 0x72, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x64, 0x6f, 0x74, 0x68, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x64, 0x61, 0x79, 0x20, 0x79, 0x65, 0x20, 0x65, 0x61, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x6e,
+ 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x65, 0x79, 0x65, 0x73, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6f, 0x70, 0x65, 0x6e,
+ 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x73, 0x20, 0x67,
+ 0x6f, 0x64, 0x73, 0x2c, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x69, 0x6e, 0x67,
+ 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76,
+ 0x69, 0x6c, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20,
+ 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f,
+ 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x66, 0x6f, 0x6f, 0x64, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x70, 0x6c, 0x65, 0x61, 0x73, 0x61, 0x6e,
+ 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x79, 0x65,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x74, 0x72, 0x65,
+ 0x65, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x64, 0x65, 0x73, 0x69,
+ 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20,
+ 0x6f, 0x6e, 0x65, 0x20, 0x77, 0x69, 0x73, 0x65, 0x2c, 0x20, 0x73, 0x68,
+ 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x74, 0x68, 0x65, 0x72,
+ 0x65, 0x6f, 0x66, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x64,
+ 0x20, 0x65, 0x61, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x61,
+ 0x76, 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x65, 0x72, 0x20, 0x68, 0x75, 0x73, 0x62, 0x61, 0x6e, 0x64,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x65, 0x72, 0x3b, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x64, 0x20, 0x65, 0x61,
+ 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x79, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6f,
+ 0x70, 0x65, 0x6e, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x6b, 0x6e, 0x65, 0x77, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x6e, 0x61, 0x6b, 0x65, 0x64, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x73, 0x65, 0x77, 0x65, 0x64, 0x20, 0x66, 0x69,
+ 0x67, 0x20, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x67,
+ 0x65, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d,
+ 0x61, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x73, 0x65, 0x6c, 0x76,
+ 0x65, 0x73, 0x20, 0x61, 0x70, 0x72, 0x6f, 0x6e, 0x73, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x68, 0x65, 0x61,
+ 0x72, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64,
+ 0x65, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f,
+ 0x6f, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61,
+ 0x79, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65,
+ 0x20, 0x68, 0x69, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x73, 0x65, 0x6c,
+ 0x76, 0x65, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x73, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x57, 0x68, 0x65, 0x72, 0x65, 0x20,
+ 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x3f, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20,
+ 0x49, 0x20, 0x68, 0x65, 0x61, 0x72, 0x64, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x76, 0x6f, 0x69, 0x63, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x49, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x66, 0x72, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x49,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e, 0x61, 0x6b, 0x65, 0x64, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x68, 0x69, 0x64, 0x20, 0x6d, 0x79,
+ 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x57, 0x68, 0x6f, 0x20,
+ 0x74, 0x6f, 0x6c, 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x77, 0x61, 0x73, 0x74,
+ 0x20, 0x6e, 0x61, 0x6b, 0x65, 0x64, 0x3f, 0x20, 0x48, 0x61, 0x73, 0x74,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x65, 0x61, 0x74, 0x65, 0x6e, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x2c,
+ 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x20, 0x49, 0x20, 0x63,
+ 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x6f,
+ 0x74, 0x20, 0x65, 0x61, 0x74, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x54, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20,
+ 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x67, 0x61,
+ 0x76, 0x65, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x68, 0x65, 0x20,
+ 0x67, 0x61, 0x76, 0x65, 0x20, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x49, 0x20, 0x64, 0x69, 0x64, 0x20, 0x65, 0x61, 0x74, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61,
+ 0x6e, 0x2c, 0x20, 0x57, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74,
+ 0x68, 0x69, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x3f,
+ 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d,
+ 0x61, 0x6e, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x65,
+ 0x20, 0x73, 0x65, 0x72, 0x70, 0x65, 0x6e, 0x74, 0x20, 0x62, 0x65, 0x67,
+ 0x75, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x49, 0x20, 0x64, 0x69, 0x64, 0x20, 0x65, 0x61, 0x74, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72,
+ 0x70, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x42, 0x65, 0x63, 0x61, 0x75, 0x73,
+ 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20,
+ 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2c, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x61, 0x72, 0x74, 0x20, 0x63, 0x75, 0x72, 0x73,
+ 0x65, 0x64, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20, 0x61, 0x6c, 0x6c,
+ 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x62, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x3b, 0x20, 0x75, 0x70, 0x6f,
+ 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x65, 0x6c, 0x6c, 0x79, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x67,
+ 0x6f, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x75, 0x73, 0x74, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x65,
+ 0x61, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6c,
+ 0x69, 0x66, 0x65, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x70, 0x75, 0x74, 0x20, 0x65, 0x6e, 0x6d,
+ 0x69, 0x74, 0x79, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x73, 0x65, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x72,
+ 0x20, 0x73, 0x65, 0x65, 0x64, 0x3b, 0x20, 0x69, 0x74, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x72, 0x75, 0x69, 0x73, 0x65, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x68, 0x65, 0x61, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20,
+ 0x62, 0x72, 0x75, 0x69, 0x73, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68,
+ 0x65, 0x65, 0x6c, 0x2e, 0x20, 0x0a, 0x55, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20, 0x68, 0x65, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x6c, 0x79, 0x20, 0x6d, 0x75, 0x6c,
+ 0x74, 0x69, 0x70, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x6f,
+ 0x72, 0x72, 0x6f, 0x77, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3b,
+ 0x20, 0x69, 0x6e, 0x20, 0x73, 0x6f, 0x72, 0x72, 0x6f, 0x77, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x62, 0x72,
+ 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x63, 0x68,
+ 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x79, 0x20, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x68, 0x75, 0x73, 0x62, 0x61, 0x6e, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c,
+ 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x68,
+ 0x65, 0x61, 0x72, 0x6b, 0x65, 0x6e, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x65, 0x61,
+ 0x74, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
+ 0x72, 0x65, 0x65, 0x2c, 0x20, 0x6f, 0x66, 0x20, 0x77, 0x68, 0x69, 0x63,
+ 0x68, 0x20, 0x49, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69,
+ 0x6e, 0x67, 0x2c, 0x20, 0x54, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x61, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x69, 0x74, 0x3a, 0x20, 0x63, 0x75, 0x72, 0x73, 0x65, 0x64,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75,
+ 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73,
+ 0x61, 0x6b, 0x65, 0x3b, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x6f, 0x72, 0x72,
+ 0x6f, 0x77, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x65, 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6c, 0x69, 0x66, 0x65,
+ 0x3b, 0x20, 0x0a, 0x54, 0x68, 0x6f, 0x72, 0x6e, 0x73, 0x20, 0x61, 0x6c,
+ 0x73, 0x6f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x74,
+ 0x6c, 0x65, 0x73, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x69, 0x74,
+ 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68,
+ 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74,
+ 0x20, 0x65, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x72,
+ 0x62, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65,
+ 0x6c, 0x64, 0x3b, 0x20, 0x0a, 0x49, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x77, 0x65, 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x65, 0x61, 0x74, 0x20, 0x62, 0x72, 0x65,
+ 0x61, 0x64, 0x2c, 0x20, 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x3a, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x64, 0x75, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x61,
+ 0x72, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x64, 0x75, 0x73, 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x63,
+ 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69,
+ 0x66, 0x65, 0x27, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x45, 0x76,
+ 0x65, 0x3b, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c,
+ 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x20, 0x0a, 0x55, 0x6e,
+ 0x74, 0x6f, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x61, 0x6c, 0x73, 0x6f,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x77, 0x69, 0x66, 0x65, 0x20, 0x64, 0x69, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61,
+ 0x6b, 0x65, 0x20, 0x63, 0x6f, 0x61, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x73, 0x6b, 0x69, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63,
+ 0x6c, 0x6f, 0x74, 0x68, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x62, 0x65, 0x63, 0x6f,
+ 0x6d, 0x65, 0x20, 0x61, 0x73, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x75, 0x73, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x6b, 0x6e, 0x6f, 0x77,
+ 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76,
+ 0x69, 0x6c, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x6f, 0x77, 0x2c,
+ 0x20, 0x6c, 0x65, 0x73, 0x74, 0x20, 0x68, 0x65, 0x20, 0x70, 0x75, 0x74,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68,
+ 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x61, 0x6b,
+ 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x69,
+ 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x61, 0x74, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x65, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x0a, 0x54, 0x68, 0x65,
+ 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x65, 0x6e, 0x74,
+ 0x20, 0x68, 0x69, 0x6d, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64,
+ 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x64, 0x65, 0x6e, 0x2c, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x77, 0x68, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x53, 0x6f,
+ 0x20, 0x68, 0x65, 0x20, 0x64, 0x72, 0x6f, 0x76, 0x65, 0x20, 0x6f, 0x75,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x3b, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x64,
+ 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x73, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64,
+ 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x64, 0x65, 0x6e, 0x20, 0x43,
+ 0x68, 0x65, 0x72, 0x75, 0x62, 0x69, 0x6d, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x61, 0x20, 0x66, 0x6c, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x20,
+ 0x73, 0x77, 0x6f, 0x72, 0x64, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x77, 0x61, 0x79, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x6b, 0x65, 0x65,
+ 0x70, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x79, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x6c, 0x69, 0x66, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x41, 0x64, 0x61, 0x6d, 0x20, 0x6b, 0x6e, 0x65, 0x77, 0x20, 0x45, 0x76,
+ 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x63,
+ 0x65, 0x69, 0x76, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x61, 0x72, 0x65, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x67, 0x6f, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x61, 0x20,
+ 0x6d, 0x61, 0x6e, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x73, 0x68, 0x65, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x20, 0x62, 0x61,
+ 0x72, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68,
+ 0x65, 0x72, 0x20, 0x41, 0x62, 0x65, 0x6c, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x62, 0x65, 0x6c, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x20,
+ 0x6b, 0x65, 0x65, 0x70, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x68,
+ 0x65, 0x65, 0x70, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x43, 0x61, 0x69,
+ 0x6e, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x20, 0x74, 0x69, 0x6c, 0x6c,
+ 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69,
+ 0x6e, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d,
+ 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20, 0x62, 0x72, 0x6f,
+ 0x75, 0x67, 0x68, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x6f,
+ 0x66, 0x66, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x68, 0x65,
+ 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72,
+ 0x73, 0x74, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63, 0x74, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x41, 0x62, 0x65, 0x6c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72,
+ 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72,
+ 0x69, 0x6e, 0x67, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63, 0x74, 0x2e, 0x20,
+ 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x77, 0x72, 0x6f, 0x74, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x75,
+ 0x6e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x66, 0x65, 0x6c,
+ 0x6c, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x57, 0x68, 0x79,
+ 0x20, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x77, 0x72,
+ 0x6f, 0x74, 0x68, 0x3f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x79,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x79, 0x20, 0x63, 0x6f, 0x75, 0x6e,
+ 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x66, 0x61, 0x6c, 0x6c,
+ 0x65, 0x6e, 0x3f, 0x20, 0x0a, 0x49, 0x66, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x64, 0x6f, 0x65, 0x73, 0x74, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x2c,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70,
+ 0x74, 0x65, 0x64, 0x3f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x66, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x74, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x2c, 0x20, 0x73, 0x69, 0x6e,
+ 0x20, 0x6c, 0x69, 0x65, 0x74, 0x68, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x6f, 0x6f, 0x72, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x64,
+ 0x65, 0x73, 0x69, 0x72, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x72, 0x75,
+ 0x6c, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x68, 0x69, 0x6d, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20, 0x74,
+ 0x61, 0x6c, 0x6b, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x41,
+ 0x62, 0x65, 0x6c, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20,
+ 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73,
+ 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x77, 0x65, 0x72, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x43, 0x61, 0x69, 0x6e, 0x20, 0x72, 0x6f, 0x73, 0x65, 0x20, 0x75, 0x70,
+ 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x73, 0x74, 0x20, 0x41, 0x62, 0x65,
+ 0x6c, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65,
+ 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x6c, 0x65, 0x77, 0x20,
+ 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x57,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x41, 0x62, 0x65, 0x6c,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x3f, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x49, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20, 0x6e, 0x6f,
+ 0x74, 0x3a, 0x20, 0x41, 0x6d, 0x20, 0x49, 0x20, 0x6d, 0x79, 0x20, 0x62,
+ 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x6b, 0x65, 0x65,
+ 0x70, 0x65, 0x72, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x57, 0x68, 0x61, 0x74, 0x20,
+ 0x68, 0x61, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x64, 0x6f,
+ 0x6e, 0x65, 0x3f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x63,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x72, 0x6f,
+ 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x62, 0x6c, 0x6f, 0x6f, 0x64,
+ 0x20, 0x63, 0x72, 0x69, 0x65, 0x74, 0x68, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x6d, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x63, 0x75, 0x72, 0x73, 0x65, 0x64, 0x20, 0x66, 0x72,
+ 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x68, 0x61, 0x74, 0x68,
+ 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x65, 0x64, 0x20, 0x68, 0x65, 0x72, 0x20,
+ 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, 0x63,
+ 0x65, 0x69, 0x76, 0x65, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x72, 0x6f,
+ 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x62, 0x6c, 0x6f, 0x6f, 0x64,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x79, 0x20, 0x68, 0x61,
+ 0x6e, 0x64, 0x3b, 0x20, 0x0a, 0x57, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x74, 0x69, 0x6c, 0x6c, 0x65, 0x73, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2c, 0x20, 0x69,
+ 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x68, 0x65, 0x6e, 0x63, 0x65, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x79,
+ 0x69, 0x65, 0x6c, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x20, 0x68, 0x65, 0x72, 0x20, 0x73, 0x74, 0x72, 0x65, 0x6e,
+ 0x67, 0x74, 0x68, 0x3b, 0x20, 0x61, 0x20, 0x66, 0x75, 0x67, 0x69, 0x74,
+ 0x69, 0x76, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x76, 0x61,
+ 0x67, 0x61, 0x62, 0x6f, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x62, 0x65, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x2c, 0x20, 0x4d, 0x79, 0x20, 0x70, 0x75, 0x6e, 0x69,
+ 0x73, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x73, 0x20, 0x67, 0x72,
+ 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x49,
+ 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x61, 0x72, 0x2e, 0x20, 0x0a,
+ 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x64, 0x72, 0x69, 0x76, 0x65, 0x6e,
+ 0x20, 0x6d, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x64, 0x61, 0x79, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x79, 0x20, 0x66, 0x61,
+ 0x63, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x49, 0x20, 0x62,
+ 0x65, 0x20, 0x68, 0x69, 0x64, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20,
+ 0x66, 0x75, 0x67, 0x69, 0x74, 0x69, 0x76, 0x65, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x61, 0x20, 0x76, 0x61, 0x67, 0x61, 0x62, 0x6f, 0x6e, 0x64, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70,
+ 0x61, 0x73, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x65, 0x76,
+ 0x65, 0x72, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x66, 0x69, 0x6e, 0x64, 0x65, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x73, 0x6c, 0x61, 0x79, 0x20, 0x6d,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x54, 0x68, 0x65, 0x72,
+ 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x77, 0x68, 0x6f, 0x73, 0x6f, 0x65,
+ 0x76, 0x65, 0x72, 0x20, 0x73, 0x6c, 0x61, 0x79, 0x65, 0x74, 0x68, 0x20,
+ 0x43, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x76, 0x65, 0x6e, 0x67, 0x65, 0x61,
+ 0x6e, 0x63, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65,
+ 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x6f, 0x6e, 0x20, 0x68, 0x69,
+ 0x6d, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x66, 0x6f, 0x6c, 0x64, 0x2e,
+ 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x73, 0x65, 0x74, 0x20, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x2c, 0x20,
+ 0x6c, 0x65, 0x73, 0x74, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x66, 0x69, 0x6e,
+ 0x64, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x73, 0x68, 0x6f,
+ 0x75, 0x6c, 0x64, 0x20, 0x6b, 0x69, 0x6c, 0x6c, 0x20, 0x68, 0x69, 0x6d,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20,
+ 0x77, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e,
+ 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x77, 0x65, 0x6c,
+ 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x4e, 0x6f, 0x64, 0x2c, 0x20, 0x6f, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x45, 0x64, 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x43, 0x61, 0x69, 0x6e, 0x20, 0x6b, 0x6e, 0x65, 0x77, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x69, 0x76, 0x65,
+ 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20,
+ 0x45, 0x6e, 0x6f, 0x63, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x64, 0x20, 0x61, 0x20,
+ 0x63, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61,
+ 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x69, 0x74,
+ 0x79, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x45, 0x6e, 0x6f, 0x63, 0x68, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x45,
+ 0x6e, 0x6f, 0x63, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x62, 0x6f, 0x72,
+ 0x6e, 0x20, 0x49, 0x72, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x49, 0x72, 0x61, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4d,
+ 0x65, 0x68, 0x75, 0x6a, 0x61, 0x65, 0x6c, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x4d, 0x65, 0x68, 0x75, 0x6a, 0x61, 0x65, 0x6c, 0x20, 0x62, 0x65,
+ 0x67, 0x61, 0x74, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x75, 0x73, 0x61, 0x65,
+ 0x6c, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x75,
+ 0x73, 0x61, 0x65, 0x6c, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4c,
+ 0x61, 0x6d, 0x65, 0x63, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x74, 0x77, 0x6f,
+ 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6f, 0x6e, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x41, 0x64, 0x61, 0x68,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x5a, 0x69, 0x6c, 0x6c, 0x61, 0x68, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x64, 0x61, 0x68, 0x20, 0x62, 0x61,
+ 0x72, 0x65, 0x20, 0x4a, 0x61, 0x62, 0x61, 0x6c, 0x3a, 0x20, 0x68, 0x65,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20,
+ 0x61, 0x73, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f,
+ 0x66, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x4a, 0x75, 0x62, 0x61, 0x6c, 0x3a, 0x20, 0x68, 0x65,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x73,
+ 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x72, 0x70, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x5a, 0x69, 0x6c, 0x6c, 0x61, 0x68, 0x2c, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x62, 0x61, 0x72, 0x65,
+ 0x20, 0x54, 0x75, 0x62, 0x61, 0x6c, 0x63, 0x61, 0x69, 0x6e, 0x2c, 0x20,
+ 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x65,
+ 0x72, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x61,
+ 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20,
+ 0x62, 0x72, 0x61, 0x73, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x72,
+ 0x6f, 0x6e, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x69, 0x73, 0x74, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x54, 0x75,
+ 0x62, 0x61, 0x6c, 0x63, 0x61, 0x69, 0x6e, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x4e, 0x61, 0x61, 0x6d, 0x61, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69,
+ 0x76, 0x65, 0x73, 0x2c, 0x20, 0x41, 0x64, 0x61, 0x68, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x5a, 0x69, 0x6c, 0x6c, 0x61, 0x68, 0x2c, 0x20, 0x48, 0x65,
+ 0x61, 0x72, 0x20, 0x6d, 0x79, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x3b,
+ 0x20, 0x79, 0x65, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68, 0x2c, 0x20, 0x68, 0x65, 0x61,
+ 0x72, 0x6b, 0x65, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x79,
+ 0x20, 0x73, 0x70, 0x65, 0x65, 0x63, 0x68, 0x3a, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x73, 0x6c, 0x61, 0x69,
+ 0x6e, 0x20, 0x61, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6d,
+ 0x79, 0x20, 0x77, 0x6f, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x79, 0x6f, 0x75, 0x6e, 0x67, 0x20,
+ 0x6d, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x79, 0x20, 0x68, 0x75,
+ 0x72, 0x74, 0x2e, 0x20, 0x0a, 0x49, 0x66, 0x20, 0x43, 0x61, 0x69, 0x6e,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x76,
+ 0x65, 0x6e, 0x67, 0x65, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x66,
+ 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x74, 0x72, 0x75, 0x6c, 0x79, 0x20, 0x4c,
+ 0x61, 0x6d, 0x65, 0x63, 0x68, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x74,
+ 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x66,
+ 0x6f, 0x6c, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x64,
+ 0x61, 0x6d, 0x20, 0x6b, 0x6e, 0x65, 0x77, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x77, 0x69, 0x66, 0x65, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x62, 0x61, 0x72, 0x65,
+ 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e,
+ 0x61, 0x6d, 0x65, 0x20, 0x53, 0x65, 0x74, 0x68, 0x3a, 0x20, 0x46, 0x6f,
+ 0x72, 0x20, 0x47, 0x6f, 0x64, 0x2c, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x73, 0x68, 0x65, 0x2c, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x61, 0x70,
+ 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x20, 0x61,
+ 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20,
+ 0x69, 0x6e, 0x73, 0x74, 0x65, 0x61, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x41,
+ 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x43, 0x61,
+ 0x69, 0x6e, 0x20, 0x73, 0x6c, 0x65, 0x77, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x6f, 0x20, 0x53, 0x65, 0x74, 0x68, 0x2c, 0x20, 0x74,
+ 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x62, 0x6f, 0x72,
+ 0x6e, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x45, 0x6e, 0x6f, 0x73,
+ 0x3a, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x62, 0x65, 0x67, 0x61, 0x6e,
+ 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x61, 0x6c, 0x6c,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x6f, 0x6b, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x64, 0x61, 0x6d,
+ 0x2e, 0x20, 0x49, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72,
+ 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x6e, 0x65,
+ 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61,
+ 0x64, 0x65, 0x20, 0x68, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x3b, 0x20, 0x0a,
+ 0x4d, 0x61, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x65, 0x6d,
+ 0x61, 0x6c, 0x65, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6e, 0x61, 0x6d, 0x65,
+ 0x20, 0x41, 0x64, 0x61, 0x6d, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x63, 0x72, 0x65,
+ 0x61, 0x74, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41,
+ 0x64, 0x61, 0x6d, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x6e,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74,
+ 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x6f, 0x77, 0x6e, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x6e, 0x65,
+ 0x73, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x53, 0x65, 0x74,
+ 0x68, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x64, 0x61, 0x6d,
+ 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x62, 0x65, 0x67, 0x6f, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x53,
+ 0x65, 0x74, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x65, 0x69, 0x67,
+ 0x68, 0x74, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x79,
+ 0x65, 0x61, 0x72, 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72,
+ 0x73, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x20, 0x68,
+ 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x69, 0x72, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x65, 0x64,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x65, 0x74, 0x68, 0x20,
+ 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x75, 0x6e,
+ 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x76,
+ 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x45, 0x6e, 0x6f, 0x73, 0x3a,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x65, 0x74, 0x68, 0x20, 0x6c,
+ 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68,
+ 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x45, 0x6e, 0x6f, 0x73,
+ 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72,
+ 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73,
+ 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x53,
+ 0x65, 0x74, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6e, 0x69, 0x6e,
+ 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x77, 0x65, 0x6c, 0x76, 0x65, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64,
+ 0x69, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x6e,
+ 0x6f, 0x73, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x6e, 0x69, 0x6e,
+ 0x65, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x43, 0x61, 0x69,
+ 0x6e, 0x61, 0x6e, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x6e,
+ 0x6f, 0x73, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74,
+ 0x65, 0x72, 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20,
+ 0x43, 0x61, 0x69, 0x6e, 0x61, 0x6e, 0x20, 0x65, 0x69, 0x67, 0x68, 0x74,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x66, 0x69, 0x66, 0x74, 0x65, 0x65, 0x6e, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61,
+ 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64,
+ 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x3a, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x6e, 0x6f, 0x73, 0x20,
+ 0x77, 0x65, 0x72, 0x65, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x75,
+ 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69,
+ 0x76, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x65, 0x64, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x61, 0x6e, 0x20, 0x6c,
+ 0x69, 0x76, 0x65, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x79,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x67, 0x61, 0x74, 0x20, 0x4d, 0x61, 0x68, 0x61, 0x6c, 0x61, 0x6c,
+ 0x65, 0x65, 0x6c, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61,
+ 0x69, 0x6e, 0x61, 0x6e, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61,
+ 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61,
+ 0x74, 0x20, 0x4d, 0x61, 0x68, 0x61, 0x6c, 0x61, 0x6c, 0x65, 0x65, 0x6c,
+ 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72,
+ 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x79,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73,
+ 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x43,
+ 0x61, 0x69, 0x6e, 0x61, 0x6e, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6e,
+ 0x69, 0x6e, 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x65, 0x6e, 0x20, 0x79, 0x65, 0x61, 0x72,
+ 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69,
+ 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4d, 0x61, 0x68,
+ 0x61, 0x6c, 0x61, 0x6c, 0x65, 0x65, 0x6c, 0x20, 0x6c, 0x69, 0x76, 0x65,
+ 0x64, 0x20, 0x73, 0x69, 0x78, 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x66, 0x69, 0x76, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4a, 0x61,
+ 0x72, 0x65, 0x64, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4d, 0x61,
+ 0x68, 0x61, 0x6c, 0x61, 0x6c, 0x65, 0x65, 0x6c, 0x20, 0x6c, 0x69, 0x76,
+ 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x65, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4a, 0x61, 0x72, 0x65, 0x64, 0x20,
+ 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65,
+ 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73,
+ 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4d,
+ 0x61, 0x68, 0x61, 0x6c, 0x61, 0x6c, 0x65, 0x65, 0x6c, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x75, 0x6e,
+ 0x64, 0x72, 0x65, 0x64, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x74, 0x79, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64,
+ 0x69, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61,
+ 0x72, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x6e,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x73, 0x69, 0x78,
+ 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x79,
+ 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x45, 0x6e, 0x6f, 0x63, 0x68,
+ 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x72, 0x65, 0x64,
+ 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x45, 0x6e,
+ 0x6f, 0x63, 0x68, 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x75,
+ 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73,
+ 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67,
+ 0x68, 0x74, 0x65, 0x72, 0x73, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x4a, 0x61, 0x72, 0x65, 0x64, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64,
+ 0x72, 0x65, 0x64, 0x20, 0x73, 0x69, 0x78, 0x74, 0x79, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x65, 0x64,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x6e, 0x6f, 0x63, 0x68,
+ 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x73, 0x69, 0x78, 0x74, 0x79,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20, 0x79, 0x65,
+ 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67,
+ 0x61, 0x74, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x75, 0x73, 0x65, 0x6c, 0x61,
+ 0x68, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x6e, 0x6f, 0x63,
+ 0x68, 0x20, 0x77, 0x61, 0x6c, 0x6b, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4d, 0x65, 0x74,
+ 0x68, 0x75, 0x73, 0x65, 0x6c, 0x61, 0x68, 0x20, 0x74, 0x68, 0x72, 0x65,
+ 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x79, 0x65,
+ 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67,
+ 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x3a, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x6e, 0x6f, 0x63,
+ 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x73, 0x69, 0x78,
+ 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20,
+ 0x79, 0x65, 0x61, 0x72, 0x73, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x45, 0x6e, 0x6f, 0x63, 0x68, 0x20, 0x77, 0x61, 0x6c, 0x6b, 0x65, 0x64,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x6f, 0x64, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e, 0x6f,
+ 0x74, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x74,
+ 0x6f, 0x6f, 0x6b, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x75, 0x73, 0x65, 0x6c, 0x61, 0x68,
+ 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x75,
+ 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x79,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x79,
+ 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65,
+ 0x67, 0x61, 0x74, 0x20, 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x75, 0x73, 0x65,
+ 0x6c, 0x61, 0x68, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66,
+ 0x74, 0x65, 0x72, 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74,
+ 0x20, 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68, 0x20, 0x73, 0x65, 0x76, 0x65,
+ 0x6e, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x65, 0x69,
+ 0x67, 0x68, 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x77, 0x6f,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73,
+ 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4d,
+ 0x65, 0x74, 0x68, 0x75, 0x73, 0x65, 0x6c, 0x61, 0x68, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64,
+ 0x72, 0x65, 0x64, 0x20, 0x73, 0x69, 0x78, 0x74, 0x79, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x65,
+ 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4c, 0x61, 0x6d, 0x65,
+ 0x63, 0x68, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20,
+ 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x79,
+ 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65,
+ 0x67, 0x61, 0x74, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x3a, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x4e,
+ 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c,
+ 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x66, 0x6f, 0x72, 0x74,
+ 0x20, 0x75, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x72, 0x6e, 0x69,
+ 0x6e, 0x67, 0x20, 0x6f, 0x75, 0x72, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x69, 0x6c, 0x20, 0x6f, 0x66, 0x20,
+ 0x6f, 0x75, 0x72, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x2c, 0x20, 0x62,
+ 0x65, 0x63, 0x61, 0x75
+};
+unsigned int bible_txt_16k_len = 16384;
diff --git a/drivers/staging/fsl_dce/tests/common/bible.txt.1k.h b/drivers/staging/fsl_dce/tests/common/bible.txt.1k.h
new file mode 100644
index 0000000..c0d49d4
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/common/bible.txt.1k.h
@@ -0,0 +1,89 @@
+unsigned char bible_txt_1k[] = {
+ 0x49, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e,
+ 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65,
+ 0x61, 0x74, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61,
+ 0x76, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e, 0x65, 0x73,
+ 0x73, 0x20, 0x77, 0x61, 0x73, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x65, 0x65, 0x70, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x70, 0x69, 0x72, 0x69, 0x74, 0x20,
+ 0x6f, 0x66, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x6f, 0x76, 0x65, 0x64,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61,
+ 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x6c, 0x69,
+ 0x67, 0x68, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73,
+ 0x61, 0x77, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x20, 0x66, 0x72,
+ 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e,
+ 0x65, 0x73, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x20, 0x44, 0x61, 0x79, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x72, 0x6b,
+ 0x6e, 0x65, 0x73, 0x73, 0x20, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c,
+ 0x65, 0x64, 0x20, 0x4e, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x20, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f,
+ 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x64, 0x61, 0x79,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x66, 0x69, 0x72, 0x6d,
+ 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x69, 0x64, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x69, 0x74, 0x20, 0x64, 0x69, 0x76,
+ 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65,
+ 0x72, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20,
+ 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x75,
+ 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72,
+ 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x61, 0x62,
+ 0x6f, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d,
+ 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69,
+ 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d,
+ 0x65, 0x6e, 0x74, 0x20, 0x48, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x2e, 0x20,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e,
+ 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20,
+ 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x75,
+ 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61,
+ 0x76, 0x65, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x67, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x70, 0x6c,
+ 0x61, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x72, 0x79, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61,
+ 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x72, 0x79,
+ 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x45, 0x61, 0x72, 0x74, 0x68, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x68, 0x65, 0x20
+};
+unsigned int bible_txt_1k_len = 1024;
diff --git a/drivers/staging/fsl_dce/tests/common/bible.txt.2k.h b/drivers/staging/fsl_dce/tests/common/bible.txt.2k.h
new file mode 100644
index 0000000..3b773fb
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/common/bible.txt.2k.h
@@ -0,0 +1,174 @@
+unsigned char bible_txt_2k[] = {
+ 0x49, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e,
+ 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65,
+ 0x61, 0x74, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61,
+ 0x76, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e, 0x65, 0x73,
+ 0x73, 0x20, 0x77, 0x61, 0x73, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x65, 0x65, 0x70, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x70, 0x69, 0x72, 0x69, 0x74, 0x20,
+ 0x6f, 0x66, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x6f, 0x76, 0x65, 0x64,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61,
+ 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x6c, 0x69,
+ 0x67, 0x68, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73,
+ 0x61, 0x77, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x20, 0x66, 0x72,
+ 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e,
+ 0x65, 0x73, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x20, 0x44, 0x61, 0x79, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x72, 0x6b,
+ 0x6e, 0x65, 0x73, 0x73, 0x20, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c,
+ 0x65, 0x64, 0x20, 0x4e, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x20, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f,
+ 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x64, 0x61, 0x79,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x66, 0x69, 0x72, 0x6d,
+ 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x69, 0x64, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x69, 0x74, 0x20, 0x64, 0x69, 0x76,
+ 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65,
+ 0x72, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20,
+ 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x75,
+ 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72,
+ 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x61, 0x62,
+ 0x6f, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d,
+ 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69,
+ 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d,
+ 0x65, 0x6e, 0x74, 0x20, 0x48, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x2e, 0x20,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e,
+ 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20,
+ 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x75,
+ 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61,
+ 0x76, 0x65, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x67, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x70, 0x6c,
+ 0x61, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x72, 0x79, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61,
+ 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x72, 0x79,
+ 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x45, 0x61, 0x72, 0x74, 0x68, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x53, 0x65, 0x61, 0x73, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f,
+ 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x62, 0x72, 0x69,
+ 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x67, 0x72, 0x61,
+ 0x73, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x72, 0x62,
+ 0x20, 0x79, 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65,
+ 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x79,
+ 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x77, 0x68, 0x6f, 0x73, 0x65, 0x20,
+ 0x73, 0x65, 0x65, 0x64, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x69,
+ 0x74, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x67, 0x72, 0x61, 0x73, 0x73,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x72, 0x62, 0x20, 0x79,
+ 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65, 0x65, 0x64,
+ 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b,
+ 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x79, 0x69, 0x65, 0x6c, 0x64, 0x69,
+ 0x6e, 0x67, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x2c, 0x20, 0x77, 0x68,
+ 0x6f, 0x73, 0x65, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x69, 0x6e, 0x20, 0x69, 0x74, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69,
+ 0x6e, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69,
+ 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x6f, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64, 0x20, 0x64, 0x61,
+ 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
+ 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72,
+ 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20,
+ 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x79, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6e, 0x69, 0x67, 0x68, 0x74, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c,
+ 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x62, 0x65, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x65, 0x61, 0x73, 0x6f, 0x6e,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64,
+ 0x61, 0x79, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x76,
+ 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x6c,
+ 0x69, 0x67, 0x68, 0x74, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64,
+ 0x65, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20,
+ 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x3b, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x67, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x67, 0x68,
+ 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x61, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x6c, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x68,
+ 0x65, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x74, 0x61, 0x72, 0x73, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x65, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x20,
+ 0x74, 0x6f, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68,
+ 0x74, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x6f, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x69, 0x67,
+ 0x68, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64,
+ 0x69, 0x76, 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e, 0x65, 0x73, 0x73, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73
+};
+unsigned int bible_txt_2k_len = 2048;
diff --git a/drivers/staging/fsl_dce/tests/common/bible.txt.32k.h b/drivers/staging/fsl_dce/tests/common/bible.txt.32k.h
new file mode 100644
index 0000000..02ccb86
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/common/bible.txt.32k.h
@@ -0,0 +1,2734 @@
+unsigned char bible_txt_32k[] = {
+ 0x49, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e,
+ 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65,
+ 0x61, 0x74, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61,
+ 0x76, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e, 0x65, 0x73,
+ 0x73, 0x20, 0x77, 0x61, 0x73, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x65, 0x65, 0x70, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x70, 0x69, 0x72, 0x69, 0x74, 0x20,
+ 0x6f, 0x66, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x6f, 0x76, 0x65, 0x64,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61,
+ 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x6c, 0x69,
+ 0x67, 0x68, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73,
+ 0x61, 0x77, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x20, 0x66, 0x72,
+ 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e,
+ 0x65, 0x73, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x20, 0x44, 0x61, 0x79, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x72, 0x6b,
+ 0x6e, 0x65, 0x73, 0x73, 0x20, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c,
+ 0x65, 0x64, 0x20, 0x4e, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x20, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f,
+ 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x64, 0x61, 0x79,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x66, 0x69, 0x72, 0x6d,
+ 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x69, 0x64, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x69, 0x74, 0x20, 0x64, 0x69, 0x76,
+ 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65,
+ 0x72, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20,
+ 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x75,
+ 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72,
+ 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x61, 0x62,
+ 0x6f, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d,
+ 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69,
+ 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d,
+ 0x65, 0x6e, 0x74, 0x20, 0x48, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x2e, 0x20,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e,
+ 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20,
+ 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x75,
+ 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61,
+ 0x76, 0x65, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x67, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x70, 0x6c,
+ 0x61, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x72, 0x79, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61,
+ 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x72, 0x79,
+ 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x45, 0x61, 0x72, 0x74, 0x68, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x53, 0x65, 0x61, 0x73, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f,
+ 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x62, 0x72, 0x69,
+ 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x67, 0x72, 0x61,
+ 0x73, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x72, 0x62,
+ 0x20, 0x79, 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65,
+ 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x79,
+ 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x77, 0x68, 0x6f, 0x73, 0x65, 0x20,
+ 0x73, 0x65, 0x65, 0x64, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x69,
+ 0x74, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x67, 0x72, 0x61, 0x73, 0x73,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x72, 0x62, 0x20, 0x79,
+ 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65, 0x65, 0x64,
+ 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b,
+ 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x79, 0x69, 0x65, 0x6c, 0x64, 0x69,
+ 0x6e, 0x67, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x2c, 0x20, 0x77, 0x68,
+ 0x6f, 0x73, 0x65, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x69, 0x6e, 0x20, 0x69, 0x74, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69,
+ 0x6e, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69,
+ 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x6f, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64, 0x20, 0x64, 0x61,
+ 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
+ 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72,
+ 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20,
+ 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x79, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6e, 0x69, 0x67, 0x68, 0x74, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c,
+ 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x62, 0x65, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x65, 0x61, 0x73, 0x6f, 0x6e,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64,
+ 0x61, 0x79, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x76,
+ 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x6c,
+ 0x69, 0x67, 0x68, 0x74, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64,
+ 0x65, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20,
+ 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x3b, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x67, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x67, 0x68,
+ 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x61, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x6c, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x68,
+ 0x65, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x74, 0x61, 0x72, 0x73, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x65, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x20,
+ 0x74, 0x6f, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68,
+ 0x74, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x6f, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x69, 0x67,
+ 0x68, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64,
+ 0x69, 0x76, 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e, 0x65, 0x73, 0x73, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67,
+ 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x6f, 0x75, 0x72, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x74, 0x65, 0x72, 0x73, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66,
+ 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x62, 0x75, 0x6e, 0x64, 0x61, 0x6e,
+ 0x74, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x76, 0x69,
+ 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x6c, 0x69,
+ 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x77, 0x6c,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x66, 0x6c,
+ 0x79, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d,
+ 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65,
+ 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x67, 0x72, 0x65, 0x61,
+ 0x74, 0x20, 0x77, 0x68, 0x61, 0x6c, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69,
+ 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x6f, 0x76, 0x65, 0x74, 0x68, 0x2c,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68,
+ 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x62, 0x75, 0x6e,
+ 0x64, 0x61, 0x6e, 0x74, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e, 0x64,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20,
+ 0x77, 0x69, 0x6e, 0x67, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69,
+ 0x6e, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73,
+ 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x73, 0x61, 0x79,
+ 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x42, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75,
+ 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x66, 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74,
+ 0x65, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x61, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70,
+ 0x6c, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x69, 0x66, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e,
+ 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x61,
+ 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e,
+ 0x64, 0x2c, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20,
+ 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61,
+ 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x61, 0x73, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74,
+ 0x68, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61,
+ 0x74, 0x74, 0x6c, 0x65, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x68, 0x69,
+ 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x72, 0x65, 0x65,
+ 0x70, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74,
+ 0x20, 0x75, 0x73, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x6d, 0x61, 0x6e,
+ 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x75, 0x72, 0x20, 0x69, 0x6d, 0x61, 0x67,
+ 0x65, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x6f, 0x75, 0x72,
+ 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x6f,
+ 0x6e, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x69, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x61, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f,
+ 0x76, 0x65, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f,
+ 0x76, 0x65, 0x72, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x72,
+ 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x65,
+ 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x53, 0x6f, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6d,
+ 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x77,
+ 0x6e, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x3b, 0x20, 0x6d, 0x61, 0x6c,
+ 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65,
+ 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x42, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75,
+ 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x72, 0x65, 0x70, 0x6c, 0x65, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x75, 0x62, 0x64, 0x75, 0x65, 0x20, 0x69, 0x74, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x64, 0x6f, 0x6d,
+ 0x69, 0x6e, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x65, 0x61, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x77,
+ 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x65,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x20,
+ 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d,
+ 0x6f, 0x76, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x68,
+ 0x61, 0x76, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x79, 0x6f,
+ 0x75, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x68, 0x65, 0x72, 0x62,
+ 0x20, 0x62, 0x65, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65, 0x65,
+ 0x64, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x72, 0x65, 0x65, 0x2c, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20,
+ 0x79, 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65, 0x65,
+ 0x64, 0x3b, 0x20, 0x74, 0x6f, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x69, 0x74,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x6d, 0x65, 0x61, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x62, 0x65,
+ 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x63, 0x72, 0x65, 0x65, 0x70, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c,
+ 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x2c, 0x20,
+ 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x67, 0x72, 0x65, 0x65, 0x6e,
+ 0x20, 0x68, 0x65, 0x72, 0x62, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x65,
+ 0x61, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x76, 0x65,
+ 0x72, 0x79, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e, 0x67,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72,
+ 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x69, 0x78, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79, 0x2e,
+ 0x20, 0x0a, 0x54, 0x68, 0x75, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68,
+ 0x65, 0x61, 0x76, 0x65, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x68, 0x6f, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x64, 0x61,
+ 0x79, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61,
+ 0x64, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x72,
+ 0x65, 0x73, 0x74, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x62,
+ 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x76, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x6e, 0x63, 0x74, 0x69, 0x66, 0x69,
+ 0x65, 0x64, 0x20, 0x69, 0x74, 0x3a, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75,
+ 0x73, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x69,
+ 0x74, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x72, 0x65, 0x73,
+ 0x74, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x6c, 0x6c,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x68,
+ 0x69, 0x63, 0x68, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65, 0x61,
+ 0x74, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65,
+ 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x77,
+ 0x65, 0x72, 0x65, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x2c,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x73,
+ 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x66, 0x6f,
+ 0x72, 0x65, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x68, 0x65,
+ 0x72, 0x62, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69,
+ 0x65, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x69,
+ 0x74, 0x20, 0x67, 0x72, 0x65, 0x77, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x61, 0x75,
+ 0x73, 0x65, 0x64, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x61,
+ 0x69, 0x6e, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x74,
+ 0x20, 0x61, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x69,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2e, 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x72,
+ 0x65, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x70, 0x20, 0x61, 0x20,
+ 0x6d, 0x69, 0x73, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x68, 0x6f, 0x6c, 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72,
+ 0x6d, 0x65, 0x64, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x75, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x62, 0x72, 0x65, 0x61, 0x74, 0x68, 0x65, 0x64, 0x20,
+ 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x73,
+ 0x74, 0x72, 0x69, 0x6c, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x72,
+ 0x65, 0x61, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x69, 0x66, 0x65,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x62, 0x65,
+ 0x63, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e,
+ 0x67, 0x20, 0x73, 0x6f, 0x75, 0x6c, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x61, 0x20,
+ 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x20, 0x65, 0x61, 0x73, 0x74, 0x77,
+ 0x61, 0x72, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x45, 0x64, 0x65, 0x6e, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x68,
+ 0x65, 0x20, 0x70, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61,
+ 0x6e, 0x20, 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x64,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x72, 0x6f, 0x77, 0x20, 0x65,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x70, 0x6c, 0x65, 0x61, 0x73, 0x61,
+ 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69,
+ 0x67, 0x68, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x6f, 0x6f,
+ 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x66, 0x6f, 0x6f, 0x64, 0x3b, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x6c, 0x69, 0x66, 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x69, 0x64, 0x73, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72,
+ 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x6c, 0x65,
+ 0x64, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x69, 0x6c, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x61, 0x20, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x77,
+ 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x45,
+ 0x64, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68,
+ 0x65, 0x6e, 0x63, 0x65, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x70, 0x61, 0x72, 0x74, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20,
+ 0x66, 0x6f, 0x75, 0x72, 0x20, 0x68, 0x65, 0x61, 0x64, 0x73, 0x2e, 0x20,
+ 0x0a, 0x54, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x69,
+ 0x73, 0x20, 0x50, 0x69, 0x73, 0x6f, 0x6e, 0x3a, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x69, 0x73, 0x20, 0x69, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63,
+ 0x68, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x73, 0x73, 0x65, 0x74, 0x68,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x6f, 0x6c, 0x65, 0x20, 0x6c,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x61, 0x76, 0x69, 0x6c,
+ 0x61, 0x68, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x67, 0x6f, 0x6c, 0x64, 0x3b,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x6f,
+ 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6c,
+ 0x61, 0x6e, 0x64, 0x20, 0x69, 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x3a,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x62, 0x64,
+ 0x65, 0x6c, 0x6c, 0x69, 0x75, 0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6f, 0x6e, 0x79, 0x78, 0x20, 0x73, 0x74, 0x6f, 0x6e,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20, 0x72, 0x69, 0x76, 0x65, 0x72,
+ 0x20, 0x69, 0x73, 0x20, 0x47, 0x69, 0x68, 0x6f, 0x6e, 0x3a, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x73, 0x20, 0x69,
+ 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61,
+ 0x73, 0x73, 0x65, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68,
+ 0x6f, 0x6c, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x45, 0x74, 0x68, 0x69, 0x6f, 0x70, 0x69, 0x61, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64,
+ 0x20, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x48, 0x69,
+ 0x64, 0x64, 0x65, 0x6b, 0x65, 0x6c, 0x3a, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x69, 0x73, 0x20, 0x69, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x67, 0x6f, 0x65, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x77, 0x61, 0x72,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x41, 0x73, 0x73, 0x79, 0x72, 0x69, 0x61, 0x2e, 0x20, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x75, 0x72, 0x74,
+ 0x68, 0x20, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x45,
+ 0x75, 0x70, 0x68, 0x72, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x75,
+ 0x74, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x20, 0x6f, 0x66,
+ 0x20, 0x45, 0x64, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x72, 0x65,
+ 0x73, 0x73, 0x20, 0x69, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f,
+ 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x69, 0x74, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x73,
+ 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x4f, 0x66, 0x20, 0x65, 0x76,
+ 0x65, 0x72, 0x79, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x65, 0x73, 0x74, 0x20, 0x66,
+ 0x72, 0x65, 0x65, 0x6c, 0x79, 0x20, 0x65, 0x61, 0x74, 0x3a, 0x20, 0x0a,
+ 0x42, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
+ 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b,
+ 0x6e, 0x6f, 0x77, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x69,
+ 0x6c, 0x2c, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c,
+ 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x61, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x69, 0x74, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x65, 0x61, 0x74, 0x65, 0x73, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x73, 0x75, 0x72, 0x65,
+ 0x6c, 0x79, 0x20, 0x64, 0x69, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x74, 0x20, 0x69,
+ 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x20,
+ 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6c,
+ 0x6f, 0x6e, 0x65, 0x3b, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61, 0x6e, 0x20,
+ 0x68, 0x65, 0x6c, 0x70, 0x20, 0x6d, 0x65, 0x65, 0x74, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x65,
+ 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x62, 0x65, 0x61, 0x73,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65,
+ 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x61, 0x69, 0x72, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x74, 0x6f,
+ 0x20, 0x73, 0x65, 0x65, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65,
+ 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68,
+ 0x61, 0x74, 0x73, 0x6f, 0x65, 0x76, 0x65, 0x72, 0x20, 0x41, 0x64, 0x61,
+ 0x6d, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x65, 0x76, 0x65,
+ 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x72,
+ 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x67, 0x61, 0x76,
+ 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f,
+ 0x77, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69,
+ 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x76,
+ 0x65, 0x72, 0x79, 0x20, 0x62, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x3b, 0x20,
+ 0x62, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x41, 0x64, 0x61, 0x6d,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x20,
+ 0x68, 0x65, 0x6c, 0x70, 0x20, 0x6d, 0x65, 0x65, 0x74, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x63, 0x61, 0x75, 0x73, 0x65, 0x64, 0x20, 0x61, 0x20, 0x64, 0x65,
+ 0x65, 0x70, 0x20, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x20, 0x74, 0x6f, 0x20,
+ 0x66, 0x61, 0x6c, 0x6c, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x41, 0x64,
+ 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73,
+ 0x6c, 0x65, 0x70, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x72, 0x69, 0x62, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x20, 0x75, 0x70,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20, 0x69,
+ 0x6e, 0x73, 0x74, 0x65, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65,
+ 0x6f, 0x66, 0x3b, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x72, 0x69, 0x62, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x6d, 0x61, 0x64,
+ 0x65, 0x20, 0x68, 0x65, 0x20, 0x61, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68,
+ 0x74, 0x20, 0x68, 0x65, 0x72, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20,
+ 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20,
+ 0x62, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x62,
+ 0x6f, 0x6e, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6c,
+ 0x65, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x66, 0x6c,
+ 0x65, 0x73, 0x68, 0x3a, 0x20, 0x73, 0x68, 0x65, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x57, 0x6f, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x62, 0x65, 0x63, 0x61,
+ 0x75, 0x73, 0x65, 0x20, 0x73, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x4d, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x72, 0x65,
+ 0x66, 0x6f, 0x72, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x61,
+ 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x63, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c,
+ 0x20, 0x62, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x66, 0x6c, 0x65, 0x73,
+ 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6e,
+ 0x61, 0x6b, 0x65, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61,
+ 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69,
+ 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x73, 0x68, 0x61, 0x6d, 0x65, 0x64,
+ 0x2e, 0x20, 0x0a, 0x4e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x72, 0x70, 0x65, 0x6e, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6d,
+ 0x6f, 0x72, 0x65, 0x20, 0x73, 0x75, 0x62, 0x74, 0x69, 0x6c, 0x20, 0x74,
+ 0x68, 0x61, 0x6e, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x62, 0x65, 0x61, 0x73,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65,
+ 0x6c, 0x64, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x2c, 0x20,
+ 0x59, 0x65, 0x61, 0x2c, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x59, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x61, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x72,
+ 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61,
+ 0x72, 0x64, 0x65, 0x6e, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x72, 0x70, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x57, 0x65, 0x20, 0x6d,
+ 0x61, 0x79, 0x20, 0x65, 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x3a, 0x20,
+ 0x0a, 0x42, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x69,
+ 0x64, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67,
+ 0x61, 0x72, 0x64, 0x65, 0x6e, 0x2c, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68,
+ 0x61, 0x74, 0x68, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x59, 0x65,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65,
+ 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x6e, 0x65,
+ 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x79, 0x65, 0x20, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x20, 0x69, 0x74, 0x2c,
+ 0x20, 0x6c, 0x65, 0x73, 0x74, 0x20, 0x79, 0x65, 0x20, 0x64, 0x69, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x72, 0x70, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d,
+ 0x61, 0x6e, 0x2c, 0x20, 0x59, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x72, 0x65, 0x6c, 0x79, 0x20,
+ 0x64, 0x69, 0x65, 0x3a, 0x20, 0x0a, 0x46, 0x6f, 0x72, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x64, 0x6f, 0x74, 0x68, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x64, 0x61, 0x79, 0x20, 0x79, 0x65, 0x20, 0x65, 0x61, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x6e,
+ 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x65, 0x79, 0x65, 0x73, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6f, 0x70, 0x65, 0x6e,
+ 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x73, 0x20, 0x67,
+ 0x6f, 0x64, 0x73, 0x2c, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x69, 0x6e, 0x67,
+ 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76,
+ 0x69, 0x6c, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20,
+ 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f,
+ 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x66, 0x6f, 0x6f, 0x64, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x70, 0x6c, 0x65, 0x61, 0x73, 0x61, 0x6e,
+ 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x79, 0x65,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x74, 0x72, 0x65,
+ 0x65, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x64, 0x65, 0x73, 0x69,
+ 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20,
+ 0x6f, 0x6e, 0x65, 0x20, 0x77, 0x69, 0x73, 0x65, 0x2c, 0x20, 0x73, 0x68,
+ 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x74, 0x68, 0x65, 0x72,
+ 0x65, 0x6f, 0x66, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x64,
+ 0x20, 0x65, 0x61, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x61,
+ 0x76, 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x65, 0x72, 0x20, 0x68, 0x75, 0x73, 0x62, 0x61, 0x6e, 0x64,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x65, 0x72, 0x3b, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x64, 0x20, 0x65, 0x61,
+ 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x79, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6f,
+ 0x70, 0x65, 0x6e, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x6b, 0x6e, 0x65, 0x77, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x6e, 0x61, 0x6b, 0x65, 0x64, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x73, 0x65, 0x77, 0x65, 0x64, 0x20, 0x66, 0x69,
+ 0x67, 0x20, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x67,
+ 0x65, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d,
+ 0x61, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x73, 0x65, 0x6c, 0x76,
+ 0x65, 0x73, 0x20, 0x61, 0x70, 0x72, 0x6f, 0x6e, 0x73, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x68, 0x65, 0x61,
+ 0x72, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64,
+ 0x65, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f,
+ 0x6f, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61,
+ 0x79, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65,
+ 0x20, 0x68, 0x69, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x73, 0x65, 0x6c,
+ 0x76, 0x65, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x73, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x57, 0x68, 0x65, 0x72, 0x65, 0x20,
+ 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x3f, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20,
+ 0x49, 0x20, 0x68, 0x65, 0x61, 0x72, 0x64, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x76, 0x6f, 0x69, 0x63, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x49, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x66, 0x72, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x49,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e, 0x61, 0x6b, 0x65, 0x64, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x68, 0x69, 0x64, 0x20, 0x6d, 0x79,
+ 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x57, 0x68, 0x6f, 0x20,
+ 0x74, 0x6f, 0x6c, 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x77, 0x61, 0x73, 0x74,
+ 0x20, 0x6e, 0x61, 0x6b, 0x65, 0x64, 0x3f, 0x20, 0x48, 0x61, 0x73, 0x74,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x65, 0x61, 0x74, 0x65, 0x6e, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x2c,
+ 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x20, 0x49, 0x20, 0x63,
+ 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x6f,
+ 0x74, 0x20, 0x65, 0x61, 0x74, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x54, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20,
+ 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x67, 0x61,
+ 0x76, 0x65, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x68, 0x65, 0x20,
+ 0x67, 0x61, 0x76, 0x65, 0x20, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x49, 0x20, 0x64, 0x69, 0x64, 0x20, 0x65, 0x61, 0x74, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61,
+ 0x6e, 0x2c, 0x20, 0x57, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74,
+ 0x68, 0x69, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x3f,
+ 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d,
+ 0x61, 0x6e, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x65,
+ 0x20, 0x73, 0x65, 0x72, 0x70, 0x65, 0x6e, 0x74, 0x20, 0x62, 0x65, 0x67,
+ 0x75, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x49, 0x20, 0x64, 0x69, 0x64, 0x20, 0x65, 0x61, 0x74, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72,
+ 0x70, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x42, 0x65, 0x63, 0x61, 0x75, 0x73,
+ 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20,
+ 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2c, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x61, 0x72, 0x74, 0x20, 0x63, 0x75, 0x72, 0x73,
+ 0x65, 0x64, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20, 0x61, 0x6c, 0x6c,
+ 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x62, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x3b, 0x20, 0x75, 0x70, 0x6f,
+ 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x65, 0x6c, 0x6c, 0x79, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x67,
+ 0x6f, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x75, 0x73, 0x74, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x65,
+ 0x61, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6c,
+ 0x69, 0x66, 0x65, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x70, 0x75, 0x74, 0x20, 0x65, 0x6e, 0x6d,
+ 0x69, 0x74, 0x79, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x73, 0x65, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x72,
+ 0x20, 0x73, 0x65, 0x65, 0x64, 0x3b, 0x20, 0x69, 0x74, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x72, 0x75, 0x69, 0x73, 0x65, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x68, 0x65, 0x61, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20,
+ 0x62, 0x72, 0x75, 0x69, 0x73, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68,
+ 0x65, 0x65, 0x6c, 0x2e, 0x20, 0x0a, 0x55, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20, 0x68, 0x65, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x6c, 0x79, 0x20, 0x6d, 0x75, 0x6c,
+ 0x74, 0x69, 0x70, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x6f,
+ 0x72, 0x72, 0x6f, 0x77, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3b,
+ 0x20, 0x69, 0x6e, 0x20, 0x73, 0x6f, 0x72, 0x72, 0x6f, 0x77, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x62, 0x72,
+ 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x63, 0x68,
+ 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x79, 0x20, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x68, 0x75, 0x73, 0x62, 0x61, 0x6e, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c,
+ 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x68,
+ 0x65, 0x61, 0x72, 0x6b, 0x65, 0x6e, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x65, 0x61,
+ 0x74, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
+ 0x72, 0x65, 0x65, 0x2c, 0x20, 0x6f, 0x66, 0x20, 0x77, 0x68, 0x69, 0x63,
+ 0x68, 0x20, 0x49, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69,
+ 0x6e, 0x67, 0x2c, 0x20, 0x54, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x61, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x69, 0x74, 0x3a, 0x20, 0x63, 0x75, 0x72, 0x73, 0x65, 0x64,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75,
+ 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73,
+ 0x61, 0x6b, 0x65, 0x3b, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x6f, 0x72, 0x72,
+ 0x6f, 0x77, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x65, 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6c, 0x69, 0x66, 0x65,
+ 0x3b, 0x20, 0x0a, 0x54, 0x68, 0x6f, 0x72, 0x6e, 0x73, 0x20, 0x61, 0x6c,
+ 0x73, 0x6f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x74,
+ 0x6c, 0x65, 0x73, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x69, 0x74,
+ 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68,
+ 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74,
+ 0x20, 0x65, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x72,
+ 0x62, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65,
+ 0x6c, 0x64, 0x3b, 0x20, 0x0a, 0x49, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x77, 0x65, 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x65, 0x61, 0x74, 0x20, 0x62, 0x72, 0x65,
+ 0x61, 0x64, 0x2c, 0x20, 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x3a, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x64, 0x75, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x61,
+ 0x72, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x64, 0x75, 0x73, 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x63,
+ 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69,
+ 0x66, 0x65, 0x27, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x45, 0x76,
+ 0x65, 0x3b, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c,
+ 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x20, 0x0a, 0x55, 0x6e,
+ 0x74, 0x6f, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x61, 0x6c, 0x73, 0x6f,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x77, 0x69, 0x66, 0x65, 0x20, 0x64, 0x69, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61,
+ 0x6b, 0x65, 0x20, 0x63, 0x6f, 0x61, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x73, 0x6b, 0x69, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63,
+ 0x6c, 0x6f, 0x74, 0x68, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x62, 0x65, 0x63, 0x6f,
+ 0x6d, 0x65, 0x20, 0x61, 0x73, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x75, 0x73, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x6b, 0x6e, 0x6f, 0x77,
+ 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76,
+ 0x69, 0x6c, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x6f, 0x77, 0x2c,
+ 0x20, 0x6c, 0x65, 0x73, 0x74, 0x20, 0x68, 0x65, 0x20, 0x70, 0x75, 0x74,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68,
+ 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x61, 0x6b,
+ 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x69,
+ 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x61, 0x74, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x65, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x0a, 0x54, 0x68, 0x65,
+ 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x65, 0x6e, 0x74,
+ 0x20, 0x68, 0x69, 0x6d, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64,
+ 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x64, 0x65, 0x6e, 0x2c, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x77, 0x68, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x53, 0x6f,
+ 0x20, 0x68, 0x65, 0x20, 0x64, 0x72, 0x6f, 0x76, 0x65, 0x20, 0x6f, 0x75,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x3b, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x64,
+ 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x73, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64,
+ 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x64, 0x65, 0x6e, 0x20, 0x43,
+ 0x68, 0x65, 0x72, 0x75, 0x62, 0x69, 0x6d, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x61, 0x20, 0x66, 0x6c, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x20,
+ 0x73, 0x77, 0x6f, 0x72, 0x64, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x77, 0x61, 0x79, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x6b, 0x65, 0x65,
+ 0x70, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x79, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x6c, 0x69, 0x66, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x41, 0x64, 0x61, 0x6d, 0x20, 0x6b, 0x6e, 0x65, 0x77, 0x20, 0x45, 0x76,
+ 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x63,
+ 0x65, 0x69, 0x76, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x61, 0x72, 0x65, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x67, 0x6f, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x61, 0x20,
+ 0x6d, 0x61, 0x6e, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x73, 0x68, 0x65, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x20, 0x62, 0x61,
+ 0x72, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68,
+ 0x65, 0x72, 0x20, 0x41, 0x62, 0x65, 0x6c, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x62, 0x65, 0x6c, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x20,
+ 0x6b, 0x65, 0x65, 0x70, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x68,
+ 0x65, 0x65, 0x70, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x43, 0x61, 0x69,
+ 0x6e, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x20, 0x74, 0x69, 0x6c, 0x6c,
+ 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69,
+ 0x6e, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d,
+ 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20, 0x62, 0x72, 0x6f,
+ 0x75, 0x67, 0x68, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x6f,
+ 0x66, 0x66, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x68, 0x65,
+ 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72,
+ 0x73, 0x74, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63, 0x74, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x41, 0x62, 0x65, 0x6c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72,
+ 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72,
+ 0x69, 0x6e, 0x67, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63, 0x74, 0x2e, 0x20,
+ 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x77, 0x72, 0x6f, 0x74, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x75,
+ 0x6e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x66, 0x65, 0x6c,
+ 0x6c, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x57, 0x68, 0x79,
+ 0x20, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x77, 0x72,
+ 0x6f, 0x74, 0x68, 0x3f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x79,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x79, 0x20, 0x63, 0x6f, 0x75, 0x6e,
+ 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x66, 0x61, 0x6c, 0x6c,
+ 0x65, 0x6e, 0x3f, 0x20, 0x0a, 0x49, 0x66, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x64, 0x6f, 0x65, 0x73, 0x74, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x2c,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70,
+ 0x74, 0x65, 0x64, 0x3f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x66, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x74, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x2c, 0x20, 0x73, 0x69, 0x6e,
+ 0x20, 0x6c, 0x69, 0x65, 0x74, 0x68, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x6f, 0x6f, 0x72, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x64,
+ 0x65, 0x73, 0x69, 0x72, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x72, 0x75,
+ 0x6c, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x68, 0x69, 0x6d, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20, 0x74,
+ 0x61, 0x6c, 0x6b, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x41,
+ 0x62, 0x65, 0x6c, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20,
+ 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73,
+ 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x77, 0x65, 0x72, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x43, 0x61, 0x69, 0x6e, 0x20, 0x72, 0x6f, 0x73, 0x65, 0x20, 0x75, 0x70,
+ 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x73, 0x74, 0x20, 0x41, 0x62, 0x65,
+ 0x6c, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65,
+ 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x6c, 0x65, 0x77, 0x20,
+ 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x57,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x41, 0x62, 0x65, 0x6c,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x3f, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x49, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20, 0x6e, 0x6f,
+ 0x74, 0x3a, 0x20, 0x41, 0x6d, 0x20, 0x49, 0x20, 0x6d, 0x79, 0x20, 0x62,
+ 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x6b, 0x65, 0x65,
+ 0x70, 0x65, 0x72, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x57, 0x68, 0x61, 0x74, 0x20,
+ 0x68, 0x61, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x64, 0x6f,
+ 0x6e, 0x65, 0x3f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x63,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x72, 0x6f,
+ 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x62, 0x6c, 0x6f, 0x6f, 0x64,
+ 0x20, 0x63, 0x72, 0x69, 0x65, 0x74, 0x68, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x6d, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x63, 0x75, 0x72, 0x73, 0x65, 0x64, 0x20, 0x66, 0x72,
+ 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x68, 0x61, 0x74, 0x68,
+ 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x65, 0x64, 0x20, 0x68, 0x65, 0x72, 0x20,
+ 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, 0x63,
+ 0x65, 0x69, 0x76, 0x65, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x72, 0x6f,
+ 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x62, 0x6c, 0x6f, 0x6f, 0x64,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x79, 0x20, 0x68, 0x61,
+ 0x6e, 0x64, 0x3b, 0x20, 0x0a, 0x57, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x74, 0x69, 0x6c, 0x6c, 0x65, 0x73, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2c, 0x20, 0x69,
+ 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x68, 0x65, 0x6e, 0x63, 0x65, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x79,
+ 0x69, 0x65, 0x6c, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x20, 0x68, 0x65, 0x72, 0x20, 0x73, 0x74, 0x72, 0x65, 0x6e,
+ 0x67, 0x74, 0x68, 0x3b, 0x20, 0x61, 0x20, 0x66, 0x75, 0x67, 0x69, 0x74,
+ 0x69, 0x76, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x76, 0x61,
+ 0x67, 0x61, 0x62, 0x6f, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x62, 0x65, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x2c, 0x20, 0x4d, 0x79, 0x20, 0x70, 0x75, 0x6e, 0x69,
+ 0x73, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x73, 0x20, 0x67, 0x72,
+ 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x49,
+ 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x61, 0x72, 0x2e, 0x20, 0x0a,
+ 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x64, 0x72, 0x69, 0x76, 0x65, 0x6e,
+ 0x20, 0x6d, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x64, 0x61, 0x79, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x79, 0x20, 0x66, 0x61,
+ 0x63, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x49, 0x20, 0x62,
+ 0x65, 0x20, 0x68, 0x69, 0x64, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20,
+ 0x66, 0x75, 0x67, 0x69, 0x74, 0x69, 0x76, 0x65, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x61, 0x20, 0x76, 0x61, 0x67, 0x61, 0x62, 0x6f, 0x6e, 0x64, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70,
+ 0x61, 0x73, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x65, 0x76,
+ 0x65, 0x72, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x66, 0x69, 0x6e, 0x64, 0x65, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x73, 0x6c, 0x61, 0x79, 0x20, 0x6d,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x54, 0x68, 0x65, 0x72,
+ 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x77, 0x68, 0x6f, 0x73, 0x6f, 0x65,
+ 0x76, 0x65, 0x72, 0x20, 0x73, 0x6c, 0x61, 0x79, 0x65, 0x74, 0x68, 0x20,
+ 0x43, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x76, 0x65, 0x6e, 0x67, 0x65, 0x61,
+ 0x6e, 0x63, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65,
+ 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x6f, 0x6e, 0x20, 0x68, 0x69,
+ 0x6d, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x66, 0x6f, 0x6c, 0x64, 0x2e,
+ 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x73, 0x65, 0x74, 0x20, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x2c, 0x20,
+ 0x6c, 0x65, 0x73, 0x74, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x66, 0x69, 0x6e,
+ 0x64, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x73, 0x68, 0x6f,
+ 0x75, 0x6c, 0x64, 0x20, 0x6b, 0x69, 0x6c, 0x6c, 0x20, 0x68, 0x69, 0x6d,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20,
+ 0x77, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e,
+ 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x77, 0x65, 0x6c,
+ 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x4e, 0x6f, 0x64, 0x2c, 0x20, 0x6f, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x45, 0x64, 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x43, 0x61, 0x69, 0x6e, 0x20, 0x6b, 0x6e, 0x65, 0x77, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x69, 0x76, 0x65,
+ 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20,
+ 0x45, 0x6e, 0x6f, 0x63, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x64, 0x20, 0x61, 0x20,
+ 0x63, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61,
+ 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x69, 0x74,
+ 0x79, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x45, 0x6e, 0x6f, 0x63, 0x68, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x45,
+ 0x6e, 0x6f, 0x63, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x62, 0x6f, 0x72,
+ 0x6e, 0x20, 0x49, 0x72, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x49, 0x72, 0x61, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4d,
+ 0x65, 0x68, 0x75, 0x6a, 0x61, 0x65, 0x6c, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x4d, 0x65, 0x68, 0x75, 0x6a, 0x61, 0x65, 0x6c, 0x20, 0x62, 0x65,
+ 0x67, 0x61, 0x74, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x75, 0x73, 0x61, 0x65,
+ 0x6c, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x75,
+ 0x73, 0x61, 0x65, 0x6c, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4c,
+ 0x61, 0x6d, 0x65, 0x63, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x74, 0x77, 0x6f,
+ 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6f, 0x6e, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x41, 0x64, 0x61, 0x68,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x5a, 0x69, 0x6c, 0x6c, 0x61, 0x68, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x64, 0x61, 0x68, 0x20, 0x62, 0x61,
+ 0x72, 0x65, 0x20, 0x4a, 0x61, 0x62, 0x61, 0x6c, 0x3a, 0x20, 0x68, 0x65,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20,
+ 0x61, 0x73, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f,
+ 0x66, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x4a, 0x75, 0x62, 0x61, 0x6c, 0x3a, 0x20, 0x68, 0x65,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x73,
+ 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x72, 0x70, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x5a, 0x69, 0x6c, 0x6c, 0x61, 0x68, 0x2c, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x62, 0x61, 0x72, 0x65,
+ 0x20, 0x54, 0x75, 0x62, 0x61, 0x6c, 0x63, 0x61, 0x69, 0x6e, 0x2c, 0x20,
+ 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x65,
+ 0x72, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x61,
+ 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20,
+ 0x62, 0x72, 0x61, 0x73, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x72,
+ 0x6f, 0x6e, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x69, 0x73, 0x74, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x54, 0x75,
+ 0x62, 0x61, 0x6c, 0x63, 0x61, 0x69, 0x6e, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x4e, 0x61, 0x61, 0x6d, 0x61, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69,
+ 0x76, 0x65, 0x73, 0x2c, 0x20, 0x41, 0x64, 0x61, 0x68, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x5a, 0x69, 0x6c, 0x6c, 0x61, 0x68, 0x2c, 0x20, 0x48, 0x65,
+ 0x61, 0x72, 0x20, 0x6d, 0x79, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x3b,
+ 0x20, 0x79, 0x65, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68, 0x2c, 0x20, 0x68, 0x65, 0x61,
+ 0x72, 0x6b, 0x65, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x79,
+ 0x20, 0x73, 0x70, 0x65, 0x65, 0x63, 0x68, 0x3a, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x73, 0x6c, 0x61, 0x69,
+ 0x6e, 0x20, 0x61, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6d,
+ 0x79, 0x20, 0x77, 0x6f, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x79, 0x6f, 0x75, 0x6e, 0x67, 0x20,
+ 0x6d, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x79, 0x20, 0x68, 0x75,
+ 0x72, 0x74, 0x2e, 0x20, 0x0a, 0x49, 0x66, 0x20, 0x43, 0x61, 0x69, 0x6e,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x76,
+ 0x65, 0x6e, 0x67, 0x65, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x66,
+ 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x74, 0x72, 0x75, 0x6c, 0x79, 0x20, 0x4c,
+ 0x61, 0x6d, 0x65, 0x63, 0x68, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x74,
+ 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x66,
+ 0x6f, 0x6c, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x64,
+ 0x61, 0x6d, 0x20, 0x6b, 0x6e, 0x65, 0x77, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x77, 0x69, 0x66, 0x65, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x62, 0x61, 0x72, 0x65,
+ 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e,
+ 0x61, 0x6d, 0x65, 0x20, 0x53, 0x65, 0x74, 0x68, 0x3a, 0x20, 0x46, 0x6f,
+ 0x72, 0x20, 0x47, 0x6f, 0x64, 0x2c, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x73, 0x68, 0x65, 0x2c, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x61, 0x70,
+ 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x20, 0x61,
+ 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20,
+ 0x69, 0x6e, 0x73, 0x74, 0x65, 0x61, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x41,
+ 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x43, 0x61,
+ 0x69, 0x6e, 0x20, 0x73, 0x6c, 0x65, 0x77, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x6f, 0x20, 0x53, 0x65, 0x74, 0x68, 0x2c, 0x20, 0x74,
+ 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x62, 0x6f, 0x72,
+ 0x6e, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x45, 0x6e, 0x6f, 0x73,
+ 0x3a, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x62, 0x65, 0x67, 0x61, 0x6e,
+ 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x61, 0x6c, 0x6c,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x6f, 0x6b, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x64, 0x61, 0x6d,
+ 0x2e, 0x20, 0x49, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72,
+ 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x6e, 0x65,
+ 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61,
+ 0x64, 0x65, 0x20, 0x68, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x3b, 0x20, 0x0a,
+ 0x4d, 0x61, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x65, 0x6d,
+ 0x61, 0x6c, 0x65, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6e, 0x61, 0x6d, 0x65,
+ 0x20, 0x41, 0x64, 0x61, 0x6d, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x63, 0x72, 0x65,
+ 0x61, 0x74, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41,
+ 0x64, 0x61, 0x6d, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x6e,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74,
+ 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x6f, 0x77, 0x6e, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x6e, 0x65,
+ 0x73, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x53, 0x65, 0x74,
+ 0x68, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x64, 0x61, 0x6d,
+ 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x62, 0x65, 0x67, 0x6f, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x53,
+ 0x65, 0x74, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x65, 0x69, 0x67,
+ 0x68, 0x74, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x79,
+ 0x65, 0x61, 0x72, 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72,
+ 0x73, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x20, 0x68,
+ 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x69, 0x72, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x65, 0x64,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x65, 0x74, 0x68, 0x20,
+ 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x75, 0x6e,
+ 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x76,
+ 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x45, 0x6e, 0x6f, 0x73, 0x3a,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x65, 0x74, 0x68, 0x20, 0x6c,
+ 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68,
+ 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x45, 0x6e, 0x6f, 0x73,
+ 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72,
+ 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73,
+ 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x53,
+ 0x65, 0x74, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6e, 0x69, 0x6e,
+ 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x77, 0x65, 0x6c, 0x76, 0x65, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64,
+ 0x69, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x6e,
+ 0x6f, 0x73, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x6e, 0x69, 0x6e,
+ 0x65, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x43, 0x61, 0x69,
+ 0x6e, 0x61, 0x6e, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x6e,
+ 0x6f, 0x73, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74,
+ 0x65, 0x72, 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20,
+ 0x43, 0x61, 0x69, 0x6e, 0x61, 0x6e, 0x20, 0x65, 0x69, 0x67, 0x68, 0x74,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x66, 0x69, 0x66, 0x74, 0x65, 0x65, 0x6e, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61,
+ 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64,
+ 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x3a, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x6e, 0x6f, 0x73, 0x20,
+ 0x77, 0x65, 0x72, 0x65, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x75,
+ 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69,
+ 0x76, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x65, 0x64, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x61, 0x6e, 0x20, 0x6c,
+ 0x69, 0x76, 0x65, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x79,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x67, 0x61, 0x74, 0x20, 0x4d, 0x61, 0x68, 0x61, 0x6c, 0x61, 0x6c,
+ 0x65, 0x65, 0x6c, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61,
+ 0x69, 0x6e, 0x61, 0x6e, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61,
+ 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61,
+ 0x74, 0x20, 0x4d, 0x61, 0x68, 0x61, 0x6c, 0x61, 0x6c, 0x65, 0x65, 0x6c,
+ 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72,
+ 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x79,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73,
+ 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x43,
+ 0x61, 0x69, 0x6e, 0x61, 0x6e, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6e,
+ 0x69, 0x6e, 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x65, 0x6e, 0x20, 0x79, 0x65, 0x61, 0x72,
+ 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69,
+ 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4d, 0x61, 0x68,
+ 0x61, 0x6c, 0x61, 0x6c, 0x65, 0x65, 0x6c, 0x20, 0x6c, 0x69, 0x76, 0x65,
+ 0x64, 0x20, 0x73, 0x69, 0x78, 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x66, 0x69, 0x76, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4a, 0x61,
+ 0x72, 0x65, 0x64, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4d, 0x61,
+ 0x68, 0x61, 0x6c, 0x61, 0x6c, 0x65, 0x65, 0x6c, 0x20, 0x6c, 0x69, 0x76,
+ 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x65, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4a, 0x61, 0x72, 0x65, 0x64, 0x20,
+ 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65,
+ 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73,
+ 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4d,
+ 0x61, 0x68, 0x61, 0x6c, 0x61, 0x6c, 0x65, 0x65, 0x6c, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x75, 0x6e,
+ 0x64, 0x72, 0x65, 0x64, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x74, 0x79, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64,
+ 0x69, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61,
+ 0x72, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x6e,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x73, 0x69, 0x78,
+ 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x79,
+ 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x45, 0x6e, 0x6f, 0x63, 0x68,
+ 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x72, 0x65, 0x64,
+ 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x45, 0x6e,
+ 0x6f, 0x63, 0x68, 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x75,
+ 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73,
+ 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67,
+ 0x68, 0x74, 0x65, 0x72, 0x73, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x4a, 0x61, 0x72, 0x65, 0x64, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64,
+ 0x72, 0x65, 0x64, 0x20, 0x73, 0x69, 0x78, 0x74, 0x79, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x65, 0x64,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x6e, 0x6f, 0x63, 0x68,
+ 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x73, 0x69, 0x78, 0x74, 0x79,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20, 0x79, 0x65,
+ 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67,
+ 0x61, 0x74, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x75, 0x73, 0x65, 0x6c, 0x61,
+ 0x68, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x6e, 0x6f, 0x63,
+ 0x68, 0x20, 0x77, 0x61, 0x6c, 0x6b, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4d, 0x65, 0x74,
+ 0x68, 0x75, 0x73, 0x65, 0x6c, 0x61, 0x68, 0x20, 0x74, 0x68, 0x72, 0x65,
+ 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x79, 0x65,
+ 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67,
+ 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x3a, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x6e, 0x6f, 0x63,
+ 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x73, 0x69, 0x78,
+ 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20,
+ 0x79, 0x65, 0x61, 0x72, 0x73, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x45, 0x6e, 0x6f, 0x63, 0x68, 0x20, 0x77, 0x61, 0x6c, 0x6b, 0x65, 0x64,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x6f, 0x64, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e, 0x6f,
+ 0x74, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x74,
+ 0x6f, 0x6f, 0x6b, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x75, 0x73, 0x65, 0x6c, 0x61, 0x68,
+ 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x75,
+ 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x79,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x79,
+ 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65,
+ 0x67, 0x61, 0x74, 0x20, 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x75, 0x73, 0x65,
+ 0x6c, 0x61, 0x68, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66,
+ 0x74, 0x65, 0x72, 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74,
+ 0x20, 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68, 0x20, 0x73, 0x65, 0x76, 0x65,
+ 0x6e, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x65, 0x69,
+ 0x67, 0x68, 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x77, 0x6f,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73,
+ 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4d,
+ 0x65, 0x74, 0x68, 0x75, 0x73, 0x65, 0x6c, 0x61, 0x68, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64,
+ 0x72, 0x65, 0x64, 0x20, 0x73, 0x69, 0x78, 0x74, 0x79, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x65,
+ 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4c, 0x61, 0x6d, 0x65,
+ 0x63, 0x68, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20,
+ 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x79,
+ 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65,
+ 0x67, 0x61, 0x74, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x3a, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x4e,
+ 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c,
+ 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x66, 0x6f, 0x72, 0x74,
+ 0x20, 0x75, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x72, 0x6e, 0x69,
+ 0x6e, 0x67, 0x20, 0x6f, 0x75, 0x72, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x69, 0x6c, 0x20, 0x6f, 0x66, 0x20,
+ 0x6f, 0x75, 0x72, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x2c, 0x20, 0x62,
+ 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20,
+ 0x68, 0x61, 0x74, 0x68, 0x20, 0x63, 0x75, 0x72, 0x73, 0x65, 0x64, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68,
+ 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4e, 0x6f,
+ 0x61, 0x68, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64,
+ 0x72, 0x65, 0x64, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x74, 0x79, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74,
+ 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61,
+ 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x3a, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61,
+ 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20,
+ 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65,
+ 0x6e, 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65,
+ 0x6e, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x66, 0x69, 0x76, 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x62, 0x65, 0x67,
+ 0x61, 0x74, 0x20, 0x53, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x48, 0x61, 0x6d,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x70, 0x68, 0x65, 0x74,
+ 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63,
+ 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c,
+ 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x62, 0x65,
+ 0x67, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69,
+ 0x70, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61,
+ 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x0a, 0x54, 0x68, 0x61, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x6d, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x79, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x66, 0x61, 0x69, 0x72, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x74, 0x6f,
+ 0x6f, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x77, 0x69, 0x76, 0x65,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x68, 0x6f, 0x73,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4d,
+ 0x79, 0x20, 0x73, 0x70, 0x69, 0x72, 0x69, 0x74, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x6c, 0x77, 0x61, 0x79,
+ 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x76, 0x65, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20,
+ 0x69, 0x73, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x3a, 0x20, 0x79, 0x65,
+ 0x74, 0x20, 0x68, 0x69, 0x73, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x68,
+ 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x77, 0x65, 0x6e, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2e,
+ 0x20, 0x0a, 0x54, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x67, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x61, 0x66, 0x74,
+ 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x2c, 0x20, 0x77, 0x68, 0x65,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f,
+ 0x66, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x69,
+ 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x6d, 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x79, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64,
+ 0x72, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x62, 0x65,
+ 0x63, 0x61, 0x6d, 0x65, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x79, 0x20,
+ 0x6d, 0x65, 0x6e, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x6d,
+ 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x6e, 0x6f, 0x77, 0x6e,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73,
+ 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x6f,
+ 0x66, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x72,
+ 0x65, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x69, 0x6d, 0x61,
+ 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x65, 0x61, 0x72,
+ 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x65,
+ 0x76, 0x69, 0x6c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61,
+ 0x6c, 0x6c, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74,
+ 0x20, 0x72, 0x65, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20,
+ 0x6d, 0x61, 0x6e, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74,
+ 0x20, 0x67, 0x72, 0x69, 0x65, 0x76, 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d,
+ 0x20, 0x61, 0x74, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x65, 0x61, 0x72,
+ 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49,
+ 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f,
+ 0x79, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x49,
+ 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
+ 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x3b, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6d,
+ 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x61, 0x73,
+ 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x72, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e,
+ 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x6f, 0x77, 0x6c, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x61, 0x69, 0x72, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x74, 0x20,
+ 0x72, 0x65, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x74, 0x68, 0x20, 0x6d, 0x65,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65,
+ 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2e, 0x20,
+ 0x0a, 0x42, 0x75, 0x74, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x66, 0x6f,
+ 0x75, 0x6e, 0x64, 0x20, 0x67, 0x72, 0x61, 0x63, 0x65, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x79, 0x65, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2e, 0x20, 0x0a,
+ 0x54, 0x68, 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x3a, 0x20, 0x4e,
+ 0x6f, 0x61, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x20, 0x6a, 0x75,
+ 0x73, 0x74, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70,
+ 0x65, 0x72, 0x66, 0x65, 0x63, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20,
+ 0x77, 0x61, 0x6c, 0x6b, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x47, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4e, 0x6f,
+ 0x61, 0x68, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x74, 0x68, 0x72,
+ 0x65, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x53, 0x68, 0x65,
+ 0x6d, 0x2c, 0x20, 0x48, 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x4a, 0x61, 0x70, 0x68, 0x65, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x54, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x61, 0x6c, 0x73, 0x6f,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x63, 0x6f, 0x72, 0x72, 0x75, 0x70, 0x74,
+ 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x47, 0x6f, 0x64, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x76, 0x69, 0x6f, 0x6c, 0x65,
+ 0x6e, 0x63, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x65, 0x64, 0x20, 0x75, 0x70, 0x6f,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64,
+ 0x2c, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x63, 0x6f, 0x72,
+ 0x72, 0x75, 0x70, 0x74, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20, 0x68, 0x61, 0x64, 0x20,
+ 0x63, 0x6f, 0x72, 0x72, 0x75, 0x70, 0x74, 0x65, 0x64, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x61, 0x79, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x54,
+ 0x68, 0x65, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20, 0x69, 0x73, 0x20, 0x63,
+ 0x6f, 0x6d, 0x65, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x6d,
+ 0x65, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x20, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x6c,
+ 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x76, 0x69, 0x6f, 0x6c,
+ 0x65, 0x6e, 0x63, 0x65, 0x20, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20,
+ 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69,
+ 0x6c, 0x6c, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x4d, 0x61, 0x6b,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x72,
+ 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x67, 0x6f, 0x70, 0x68, 0x65, 0x72, 0x20,
+ 0x77, 0x6f, 0x6f, 0x64, 0x3b, 0x20, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x6d,
+ 0x61, 0x6b, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61,
+ 0x72, 0x6b, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c,
+ 0x74, 0x20, 0x70, 0x69, 0x74, 0x63, 0x68, 0x20, 0x69, 0x74, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x70,
+ 0x69, 0x74, 0x63, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x61, 0x73, 0x68, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20,
+ 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x69, 0x74, 0x20, 0x6f, 0x66, 0x3a, 0x20,
+ 0x54, 0x68, 0x65, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x63, 0x75, 0x62,
+ 0x69, 0x74, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x72, 0x65,
+ 0x61, 0x64, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x20, 0x66,
+ 0x69, 0x66, 0x74, 0x79, 0x20, 0x63, 0x75, 0x62, 0x69, 0x74, 0x73, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x20, 0x74, 0x68,
+ 0x69, 0x72, 0x74, 0x79, 0x20, 0x63, 0x75, 0x62, 0x69, 0x74, 0x73, 0x2e,
+ 0x20, 0x0a, 0x41, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x6d, 0x61,
+ 0x6b, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72,
+ 0x6b, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20,
+ 0x63, 0x75, 0x62, 0x69, 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x20,
+ 0x69, 0x74, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x6f, 0x6f, 0x72, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x65, 0x74,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x64, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x3b, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x2c, 0x20, 0x73, 0x65,
+ 0x63, 0x6f, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x69, 0x72, 0x64, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x6d,
+ 0x61, 0x6b, 0x65, 0x20, 0x69, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x49, 0x2c,
+ 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x49, 0x2c, 0x20, 0x64, 0x6f, 0x20,
+ 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x66, 0x6c, 0x6f, 0x6f,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72,
+ 0x6f, 0x79, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68,
+ 0x2c, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x20, 0x69, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x72, 0x65, 0x61, 0x74, 0x68, 0x20,
+ 0x6f, 0x66, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x68, 0x65, 0x61, 0x76,
+ 0x65, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x64,
+ 0x69, 0x65, 0x2e, 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x49, 0x20, 0x65, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x20,
+ 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x27, 0x20, 0x77,
+ 0x69, 0x76, 0x65, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67,
+ 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x2c, 0x20, 0x74, 0x77, 0x6f,
+ 0x20, 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x73, 0x6f,
+ 0x72, 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x74, 0x6f,
+ 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x61,
+ 0x6c, 0x69, 0x76, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x3b, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6d, 0x61, 0x6c, 0x65, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65, 0x2e, 0x20, 0x0a,
+ 0x4f, 0x66, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x73, 0x20, 0x61, 0x66, 0x74,
+ 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e,
+ 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x61,
+ 0x74, 0x74, 0x6c, 0x65, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x6f,
+ 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x72, 0x65, 0x65,
+ 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69,
+ 0x6e, 0x64, 0x2c, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x6f, 0x66, 0x20, 0x65,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x73, 0x6f, 0x72, 0x74, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x6b,
+ 0x65, 0x65, 0x70, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x61, 0x6c, 0x69,
+ 0x76, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x61, 0x6b,
+ 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x66, 0x6f, 0x6f, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73,
+ 0x20, 0x65, 0x61, 0x74, 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x67,
+ 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x66, 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x75, 0x73,
+ 0x20, 0x64, 0x69, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x3b, 0x20, 0x61,
+ 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x68,
+ 0x69, 0x6d, 0x2c, 0x20, 0x73, 0x6f, 0x20, 0x64, 0x69, 0x64, 0x20, 0x68,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x43, 0x6f, 0x6d,
+ 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x79, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65,
+ 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72,
+ 0x6b, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x49, 0x20, 0x73, 0x65, 0x65, 0x6e, 0x20,
+ 0x72, 0x69, 0x67, 0x68, 0x74, 0x65, 0x6f, 0x75, 0x73, 0x20, 0x62, 0x65,
+ 0x66, 0x6f, 0x72, 0x65, 0x20, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x69, 0x73, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x2e, 0x20, 0x0a, 0x4f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x63, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x61, 0x73,
+ 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74,
+ 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x65, 0x20, 0x62, 0x79, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x73, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6c, 0x65, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x62, 0x65, 0x61,
+ 0x73, 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x62,
+ 0x79, 0x20, 0x74, 0x77, 0x6f, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x61, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65, 0x2e, 0x20, 0x0a, 0x4f, 0x66, 0x20,
+ 0x66, 0x6f, 0x77, 0x6c, 0x73, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72, 0x20, 0x62, 0x79,
+ 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x61, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65, 0x3b, 0x20, 0x74, 0x6f,
+ 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x61,
+ 0x6c, 0x69, 0x76, 0x65, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e,
+ 0x20, 0x0a, 0x46, 0x6f, 0x72, 0x20, 0x79, 0x65, 0x74, 0x20, 0x73, 0x65,
+ 0x76, 0x65, 0x6e, 0x20, 0x64, 0x61, 0x79, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x63, 0x61, 0x75,
+ 0x73, 0x65, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x61, 0x69,
+ 0x6e, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x79, 0x20, 0x64,
+ 0x61, 0x79, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x74,
+ 0x79, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x73, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69,
+ 0x6e, 0x67, 0x20, 0x73, 0x75, 0x62, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65,
+ 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x49,
+ 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x6f, 0x66, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61,
+ 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4e, 0x6f,
+ 0x61, 0x68, 0x20, 0x64, 0x69, 0x64, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x72,
+ 0x64, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65,
+ 0x64, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x69, 0x78,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x6f, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61,
+ 0x68, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66,
+ 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73,
+ 0x6f, 0x6e, 0x73, 0x27, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x69, 0x6e, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x62,
+ 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a,
+ 0x4f, 0x66, 0x20, 0x63, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x61,
+ 0x73, 0x74, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x62, 0x65, 0x61, 0x73, 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6c, 0x65, 0x61,
+ 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x6f,
+ 0x77, 0x6c, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x65, 0x74,
+ 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x72, 0x65,
+ 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x77, 0x6f,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x61, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65, 0x2c, 0x20, 0x61, 0x73,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68, 0x61, 0x64, 0x20, 0x63, 0x6f, 0x6d,
+ 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d,
+ 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x20, 0x61, 0x66,
+ 0x74, 0x65, 0x72, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x64, 0x61,
+ 0x79, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x6f, 0x64, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x49, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x69, 0x78, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65,
+ 0x64, 0x74, 0x68, 0x20, 0x79, 0x65, 0x61, 0x72, 0x20, 0x6f, 0x66, 0x20,
+ 0x4e, 0x6f, 0x61, 0x68, 0x27, 0x73, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x2c,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6f,
+ 0x6e, 0x64, 0x20, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x2c, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x74,
+ 0x68, 0x20, 0x64, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x61, 0x6d, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f,
+ 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x64, 0x65, 0x65,
+ 0x70, 0x20, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x75, 0x70, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6e,
+ 0x64, 0x6f, 0x77, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65, 0x61, 0x76,
+ 0x65, 0x6e, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6f, 0x70, 0x65, 0x6e,
+ 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x72, 0x61, 0x69, 0x6e, 0x20, 0x77, 0x61, 0x73, 0x20, 0x75, 0x70,
+ 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x79, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x69,
+ 0x67, 0x68, 0x74, 0x73, 0x2e, 0x20, 0x0a, 0x49, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x64,
+ 0x61, 0x79, 0x20, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x4e,
+ 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x68, 0x65,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48, 0x61, 0x6d, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x70, 0x68, 0x65, 0x74, 0x68, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4e,
+ 0x6f, 0x61, 0x68, 0x27, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x72, 0x65,
+ 0x65, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x3b, 0x20, 0x0a, 0x54, 0x68,
+ 0x65, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x62, 0x65, 0x61, 0x73, 0x74, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63,
+ 0x72, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e,
+ 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70,
+ 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x66, 0x6f, 0x77,
+ 0x6c, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20,
+ 0x62, 0x69, 0x72, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x73, 0x6f, 0x72, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x69,
+ 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20,
+ 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b,
+ 0x2c, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x77,
+ 0x6f, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c, 0x65,
+ 0x73, 0x68, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x20,
+ 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x72, 0x65, 0x61, 0x74,
+ 0x68, 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x2c, 0x20, 0x77,
+ 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x6d, 0x61, 0x6c, 0x65, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x2c,
+ 0x20, 0x61, 0x73, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68, 0x61, 0x64, 0x20,
+ 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x68, 0x69,
+ 0x6d, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x20, 0x73, 0x68, 0x75, 0x74, 0x20, 0x68, 0x69, 0x6d,
+ 0x20, 0x69, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x6f, 0x64, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x66, 0x6f, 0x72, 0x74, 0x79, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x75,
+ 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74,
+ 0x68, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x72, 0x65, 0x61,
+ 0x73, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x61, 0x72,
+ 0x65, 0x20, 0x75, 0x70, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x6c, 0x69, 0x66, 0x74, 0x20, 0x75, 0x70, 0x20, 0x61, 0x62, 0x6f,
+ 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x70, 0x72, 0x65, 0x76, 0x61, 0x69,
+ 0x6c, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x69, 0x6e, 0x63, 0x72, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20,
+ 0x67, 0x72, 0x65, 0x61, 0x74, 0x6c, 0x79, 0x20, 0x75, 0x70, 0x6f, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x20,
+ 0x77, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72,
+ 0x73, 0x20, 0x70, 0x72, 0x65, 0x76, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20,
+ 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x69, 0x6e, 0x67, 0x6c, 0x79, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x68, 0x69, 0x67, 0x68, 0x20, 0x68, 0x69, 0x6c,
+ 0x6c, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x68, 0x6f, 0x6c, 0x65, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e,
+ 0x2c, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72,
+ 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x46, 0x69, 0x66, 0x74, 0x65, 0x65, 0x6e,
+ 0x20, 0x63, 0x75, 0x62, 0x69, 0x74, 0x73, 0x20, 0x75, 0x70, 0x77, 0x61,
+ 0x72, 0x64, 0x20, 0x64, 0x69, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x70, 0x72, 0x65, 0x76, 0x61, 0x69,
+ 0x6c, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73,
+ 0x68, 0x20, 0x64, 0x69, 0x65, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x62, 0x6f,
+ 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c,
+ 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x62, 0x65,
+ 0x61, 0x73, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x69,
+ 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x65, 0x74, 0x68, 0x20, 0x75,
+ 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74,
+ 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x6d, 0x61, 0x6e, 0x3a, 0x20, 0x0a, 0x41, 0x6c, 0x6c, 0x20, 0x69,
+ 0x6e, 0x20, 0x77, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x6e, 0x6f, 0x73, 0x74,
+ 0x72, 0x69, 0x6c, 0x73, 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x62, 0x72, 0x65, 0x61, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x6c,
+ 0x69, 0x66, 0x65, 0x2c, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x72, 0x79, 0x20, 0x6c, 0x61, 0x6e, 0x64,
+ 0x2c, 0x20, 0x64, 0x69, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e,
+ 0x67, 0x20, 0x73, 0x75, 0x62, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x65,
+ 0x64, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2c, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6d, 0x61,
+ 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c,
+ 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x72, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e,
+ 0x67, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x6f, 0x77, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x64, 0x65,
+ 0x73, 0x74, 0x72, 0x6f, 0x79, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x6f, 0x6e, 0x6c,
+ 0x79, 0x20, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x61,
+ 0x6c, 0x69, 0x76, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72,
+ 0x73, 0x20, 0x70, 0x72, 0x65, 0x76, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65,
+ 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x66, 0x74, 0x79, 0x20,
+ 0x64, 0x61, 0x79, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x72, 0x65, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x65,
+ 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67,
+ 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x74, 0x74,
+ 0x6c, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x61, 0x20,
+ 0x77, 0x69, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73,
+ 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x61, 0x73, 0x73, 0x77,
+ 0x61, 0x67, 0x65, 0x64, 0x3b, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x66,
+ 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x61, 0x6c, 0x73,
+ 0x6f, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x65,
+ 0x70, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69,
+ 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65, 0x61,
+ 0x76, 0x65, 0x6e, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x73, 0x74, 0x6f,
+ 0x70, 0x70, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x72, 0x61, 0x69, 0x6e, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x20, 0x77, 0x61, 0x73, 0x20, 0x72,
+ 0x65, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x3b, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65,
+ 0x72, 0x73, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x20,
+ 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6f, 0x66, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x69,
+ 0x6e, 0x75, 0x61, 0x6c, 0x6c, 0x79, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x75, 0x6e,
+ 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x66,
+ 0x74, 0x79, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x61, 0x62, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x20, 0x72, 0x65, 0x73,
+ 0x74, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x76, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x6d, 0x6f, 0x6e, 0x74, 0x68,
+ 0x2c, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x76,
+ 0x65, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6e, 0x74,
+ 0x68, 0x2c, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x41, 0x72, 0x61, 0x72, 0x61, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73,
+ 0x20, 0x64, 0x65, 0x63, 0x72, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x63,
+ 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x75,
+ 0x6e, 0x74, 0x69, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x6e,
+ 0x74, 0x68, 0x20, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x3a, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x6d,
+ 0x6f, 0x6e, 0x74, 0x68, 0x2c, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x64, 0x61, 0x79, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x2c,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x6f,
+ 0x70, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f,
+ 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x73, 0x65, 0x65, 0x6e,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61,
+ 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x20, 0x61,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x79, 0x20, 0x64, 0x61, 0x79, 0x73, 0x2c,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x6f,
+ 0x70, 0x65, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69,
+ 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x61, 0x72, 0x6b, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x68, 0x65,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20,
+ 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x20, 0x72, 0x61, 0x76, 0x65,
+ 0x6e, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x6e,
+ 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x2c, 0x20, 0x75, 0x6e, 0x74, 0x69,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x64, 0x72, 0x69, 0x65, 0x64, 0x20,
+ 0x75, 0x70, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6f, 0x66, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6c, 0x73, 0x6f, 0x20, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x74,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x20, 0x64, 0x6f, 0x76,
+ 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20,
+ 0x74, 0x6f, 0x20, 0x73, 0x65, 0x65, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x61, 0x62, 0x61, 0x74, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x6f, 0x66, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61,
+ 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x6f, 0x76, 0x65, 0x20, 0x66, 0x6f, 0x75, 0x6e,
+ 0x64, 0x20, 0x6e, 0x6f, 0x20, 0x72, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6c, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x68, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x6f, 0x74, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x72, 0x65, 0x74, 0x75,
+ 0x72, 0x6e, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69,
+ 0x6d, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61,
+ 0x72, 0x6b, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x6f, 0x6c, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x6e,
+ 0x20, 0x68, 0x65, 0x20, 0x70, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74,
+ 0x68, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x68, 0x65, 0x72,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x75, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x68, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x69, 0x6d, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x74, 0x61, 0x79, 0x65, 0x64, 0x20, 0x79, 0x65,
+ 0x74, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x65, 0x76, 0x65,
+ 0x6e, 0x20, 0x64, 0x61, 0x79, 0x73, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x61, 0x67, 0x61, 0x69, 0x6e, 0x20, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e,
+ 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x64, 0x6f, 0x76, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x3b, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x6f, 0x76, 0x65, 0x20, 0x63,
+ 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69,
+ 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65,
+ 0x6e, 0x69, 0x6e, 0x67, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x6c,
+ 0x6f, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x65, 0x72, 0x20, 0x6d, 0x6f,
+ 0x75, 0x74, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x6f,
+ 0x6c, 0x69, 0x76, 0x65, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x20, 0x70, 0x6c,
+ 0x75, 0x63, 0x6b, 0x74, 0x20, 0x6f, 0x66, 0x66, 0x3a, 0x20, 0x73, 0x6f,
+ 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x6b, 0x6e, 0x65, 0x77, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65,
+ 0x72, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x61, 0x62, 0x61, 0x74,
+ 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6f, 0x66, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x74, 0x61, 0x79, 0x65,
+ 0x64, 0x20, 0x79, 0x65, 0x74, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x64, 0x61, 0x79, 0x73, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x6f, 0x76, 0x65, 0x3b,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72,
+ 0x6e, 0x65, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x67, 0x61, 0x69,
+ 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61,
+ 0x6e, 0x79, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f,
+ 0x20, 0x70, 0x61, 0x73, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x69, 0x78, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64,
+ 0x74, 0x68, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x6d, 0x6f, 0x6e, 0x74,
+ 0x68, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74,
+ 0x20, 0x64, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x64,
+ 0x72, 0x69, 0x65, 0x64, 0x20, 0x75, 0x70, 0x20, 0x66, 0x72, 0x6f, 0x6d,
+ 0x20, 0x6f, 0x66, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68,
+ 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x64, 0x72, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e,
+ 0x64, 0x20, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x2c, 0x20, 0x6f, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x77, 0x65, 0x6e, 0x74, 0x69, 0x65, 0x74, 0x68, 0x20,
+ 0x64, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x6f, 0x6e, 0x74, 0x68, 0x2c, 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x64, 0x72, 0x69, 0x65,
+ 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x70, 0x61, 0x6b, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4e,
+ 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c,
+ 0x20, 0x0a, 0x47, 0x6f, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x27, 0x20, 0x77,
+ 0x69, 0x76, 0x65, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x2e, 0x20, 0x0a, 0x42, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66,
+ 0x6f, 0x72, 0x74, 0x68, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76,
+ 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74,
+ 0x68, 0x65, 0x65, 0x2c, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x66, 0x6c, 0x65, 0x73, 0x68, 0x2c, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20,
+ 0x6f, 0x66, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x6f, 0x66, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68,
+ 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x72, 0x65,
+ 0x65, 0x70, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3b, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x6d, 0x61, 0x79, 0x20,
+ 0x62, 0x72, 0x65, 0x65, 0x64, 0x20, 0x61, 0x62, 0x75, 0x6e, 0x64, 0x61,
+ 0x6e, 0x74, 0x6c, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x66, 0x75, 0x6c, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4e, 0x6f,
+ 0x61, 0x68, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74,
+ 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73,
+ 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x27, 0x20, 0x77, 0x69, 0x76,
+ 0x65, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x3a,
+ 0x20, 0x0a, 0x45, 0x76, 0x65, 0x72, 0x79, 0x20, 0x62, 0x65, 0x61, 0x73,
+ 0x74, 0x2c, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x72, 0x65,
+ 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x66,
+ 0x6f, 0x77, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x61,
+ 0x74, 0x73, 0x6f, 0x65, 0x76, 0x65, 0x72, 0x20, 0x63, 0x72, 0x65, 0x65,
+ 0x70, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x66, 0x74,
+ 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e,
+ 0x64, 0x73, 0x2c, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72,
+ 0x74, 0x68, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x64,
+ 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x6f, 0x66,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x6c, 0x65, 0x61, 0x6e,
+ 0x20, 0x62, 0x65, 0x61, 0x73, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x6c, 0x65,
+ 0x61, 0x6e, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x65, 0x64, 0x20, 0x62, 0x75, 0x72,
+ 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x73,
+ 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6c, 0x74, 0x61,
+ 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x6d, 0x65, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x61, 0x20, 0x73, 0x77, 0x65, 0x65, 0x74, 0x20, 0x73, 0x61, 0x76,
+ 0x6f, 0x75, 0x72, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x69,
+ 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x65, 0x61, 0x72, 0x74, 0x2c,
+ 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x61, 0x67, 0x61, 0x69, 0x6e, 0x20, 0x63, 0x75, 0x72, 0x73, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x61,
+ 0x6e, 0x79, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x6d, 0x61, 0x6e, 0x27, 0x73, 0x20, 0x73, 0x61, 0x6b, 0x65, 0x3b, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6d, 0x61, 0x67,
+ 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x6d,
+ 0x61, 0x6e, 0x27, 0x73, 0x20, 0x68, 0x65, 0x61, 0x72, 0x74, 0x20, 0x69,
+ 0x73, 0x20, 0x65, 0x76, 0x69, 0x6c, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x79, 0x6f, 0x75, 0x74, 0x68, 0x3b, 0x20, 0x6e,
+ 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x49, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x20, 0x73, 0x6d, 0x69, 0x74,
+ 0x65, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x65,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x6c,
+ 0x69, 0x76, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x49, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x2e, 0x20, 0x0a,
+ 0x57, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x72, 0x74, 0x68, 0x20, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x65, 0x74,
+ 0x68, 0x2c, 0x20, 0x73, 0x65, 0x65, 0x64, 0x74, 0x69, 0x6d, 0x65, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x61, 0x72, 0x76, 0x65, 0x73, 0x74, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6c, 0x64, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x61, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x75, 0x6d, 0x6d, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64,
+ 0x61, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63,
+ 0x65, 0x61, 0x73, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x4e,
+ 0x6f, 0x61, 0x68, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x73, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x2c, 0x20, 0x42, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x66, 0x75,
+ 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69,
+ 0x70, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x70,
+ 0x6c, 0x65, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x65, 0x61, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x79,
+ 0x6f, 0x75, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x72, 0x65, 0x61, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x75, 0x70, 0x6f,
+ 0x6e, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x62, 0x65, 0x61, 0x73,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72, 0x2c, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x6d, 0x6f, 0x76, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x73, 0x68, 0x65, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x61, 0x3b,
+ 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x68,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x65, 0x64, 0x2e, 0x20,
+ 0x0a, 0x45, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6d, 0x6f, 0x76, 0x69, 0x6e,
+ 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x6c, 0x69, 0x76, 0x65, 0x74, 0x68, 0x20, 0x73, 0x68, 0x61, 0x6c,
+ 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6d, 0x65, 0x61, 0x74, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x79, 0x6f, 0x75, 0x3b, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20,
+ 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x65, 0x65, 0x6e,
+ 0x20, 0x68, 0x65, 0x72, 0x62, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x49,
+ 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x20, 0x0a,
+ 0x42, 0x75, 0x74, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x2c, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6c,
+ 0x6f, 0x6f, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x2c,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x79, 0x65, 0x20, 0x6e, 0x6f,
+ 0x74, 0x20, 0x65, 0x61, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x73, 0x75, 0x72, 0x65, 0x6c, 0x79, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20,
+ 0x62, 0x6c, 0x6f, 0x6f, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x6f, 0x75,
+ 0x72, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x49, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x3b, 0x20,
+ 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x62, 0x65, 0x61,
+ 0x73, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x49, 0x20, 0x72, 0x65,
+ 0x71, 0x75, 0x69, 0x72, 0x65, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x6e,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x61, 0x6e, 0x3b, 0x20, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6d, 0x61, 0x6e, 0x27, 0x73,
+ 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x69, 0x6c,
+ 0x6c, 0x20, 0x49, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x6d, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x57, 0x68, 0x6f, 0x73, 0x6f, 0x20,
+ 0x73, 0x68, 0x65, 0x64, 0x64, 0x65, 0x74, 0x68, 0x20, 0x6d, 0x61, 0x6e,
+ 0x27, 0x73, 0x20, 0x62, 0x6c, 0x6f, 0x6f, 0x64, 0x2c, 0x20, 0x62, 0x79,
+ 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x62, 0x6c, 0x6f, 0x6f, 0x64, 0x20, 0x62, 0x65, 0x20,
+ 0x73, 0x68, 0x65, 0x64, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x68,
+ 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x79, 0x6f, 0x75, 0x2c, 0x20, 0x62, 0x65, 0x20, 0x79, 0x65, 0x20, 0x66,
+ 0x72, 0x75, 0x69, 0x74, 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x3b, 0x20, 0x62,
+ 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61,
+ 0x62, 0x75, 0x6e, 0x64, 0x61, 0x6e, 0x74, 0x6c, 0x79, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x70, 0x61, 0x6b, 0x65,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73,
+ 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d,
+ 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x49, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64,
+ 0x2c, 0x20, 0x49, 0x20, 0x65, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73,
+ 0x68, 0x20, 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e,
+ 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x79, 0x6f, 0x75, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x79, 0x6f, 0x75,
+ 0x72, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x79, 0x6f, 0x75, 0x3b, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69,
+ 0x76, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72,
+ 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x79, 0x6f, 0x75, 0x2c, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x2c, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x62, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x79, 0x6f, 0x75, 0x3b, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x67, 0x6f, 0x20, 0x6f,
+ 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72,
+ 0x6b, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20,
+ 0x62, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x65, 0x73, 0x74, 0x61,
+ 0x62, 0x6c, 0x69, 0x73, 0x68, 0x20, 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x76,
+ 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x79,
+ 0x6f, 0x75, 0x2c, 0x20, 0x6e, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c,
+ 0x65, 0x73, 0x68, 0x20, 0x62, 0x65, 0x20, 0x63, 0x75, 0x74, 0x20, 0x6f,
+ 0x66, 0x66, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20,
+ 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x66, 0x6c, 0x6f, 0x6f, 0x64,
+ 0x3b, 0x20, 0x6e, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61, 0x6e,
+ 0x79, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20,
+ 0x66, 0x6c, 0x6f, 0x6f, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x65, 0x73,
+ 0x74, 0x72, 0x6f, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20,
+ 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x76, 0x65,
+ 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x49,
+ 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65,
+ 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79, 0x6f, 0x75,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c,
+ 0x69, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75,
+ 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x79, 0x6f, 0x75, 0x2c, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x70, 0x65, 0x72, 0x70, 0x65, 0x74, 0x75, 0x61, 0x6c, 0x20, 0x67,
+ 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x20,
+ 0x0a, 0x49, 0x20, 0x64, 0x6f, 0x20, 0x73, 0x65, 0x74, 0x20, 0x6d, 0x79,
+ 0x20, 0x62, 0x6f, 0x77, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69,
+ 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x61, 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x6f,
+ 0x66, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74,
+ 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x6d, 0x65, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74,
+ 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x6f,
+ 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20,
+ 0x49, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x63, 0x6c,
+ 0x6f, 0x75, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x77, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x73, 0x65, 0x65, 0x6e, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x3a,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x72, 0x65, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6d, 0x79,
+ 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x2c, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x62, 0x65, 0x74, 0x77,
+ 0x65, 0x65, 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79,
+ 0x6f, 0x75, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61,
+ 0x74, 0x75, 0x72, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x66, 0x6c, 0x65, 0x73, 0x68, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20,
+ 0x62, 0x65, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x61, 0x20, 0x66, 0x6c, 0x6f,
+ 0x6f, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f,
+ 0x79, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f,
+ 0x77, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x6c, 0x6f, 0x6f, 0x6b, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x69, 0x74,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x6d, 0x61, 0x79,
+ 0x20, 0x72, 0x65, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x62,
+ 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76,
+ 0x69, 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73,
+ 0x68, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x75, 0x70,
+ 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4e, 0x6f, 0x61,
+ 0x68, 0x2c, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74,
+ 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x49, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x65, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68,
+ 0x65, 0x64, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x6d,
+ 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c,
+ 0x65, 0x73, 0x68, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4e, 0x6f, 0x61,
+ 0x68, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x6e, 0x74,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x53, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48, 0x61,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x70, 0x68, 0x65,
+ 0x74, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48, 0x61, 0x6d, 0x20,
+ 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x2e,
+ 0x20, 0x0a, 0x54, 0x68, 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x20, 0x73, 0x6f,
+ 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x6f, 0x6c,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x6f, 0x76, 0x65, 0x72,
+ 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x62, 0x65, 0x67, 0x61, 0x6e, 0x20,
+ 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x75, 0x73,
+ 0x62, 0x61, 0x6e, 0x64, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x20,
+ 0x61, 0x20, 0x76, 0x69, 0x6e, 0x65, 0x79, 0x61, 0x72, 0x64, 0x3a, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x72, 0x61, 0x6e,
+ 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6e,
+ 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x61, 0x73, 0x20, 0x64,
+ 0x72, 0x75, 0x6e, 0x6b, 0x65, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x75, 0x6e, 0x63, 0x6f, 0x76,
+ 0x65, 0x72, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x48, 0x61, 0x6d, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x61,
+ 0x6e, 0x61, 0x61, 0x6e, 0x2c, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6e, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x65, 0x73, 0x73, 0x20,
+ 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x6c, 0x64, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x62, 0x72, 0x65, 0x74,
+ 0x68, 0x72, 0x65, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x68, 0x65, 0x6d, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x70, 0x68, 0x65, 0x74, 0x68, 0x20,
+ 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x61, 0x20, 0x67, 0x61, 0x72, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x61, 0x69, 0x64,
+ 0x20, 0x69, 0x74, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x62, 0x6f, 0x74,
+ 0x68, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x73, 0x68, 0x6f, 0x75,
+ 0x6c, 0x64, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77,
+ 0x65, 0x6e, 0x74, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x77, 0x61, 0x72, 0x64,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6b, 0x65, 0x64, 0x6e,
+ 0x65, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72,
+ 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x66, 0x61, 0x63, 0x65, 0x73,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x77, 0x61,
+ 0x72, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x73, 0x61, 0x77, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x69, 0x72, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20,
+ 0x6e, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x65, 0x73, 0x73, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x61, 0x77, 0x6f,
+ 0x6b, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x77, 0x69, 0x6e, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6b, 0x6e,
+ 0x65, 0x77, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x79, 0x6f, 0x75, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x73, 0x6f, 0x6e, 0x20,
+ 0x68, 0x61, 0x64, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x43, 0x75, 0x72,
+ 0x73, 0x65, 0x64, 0x20, 0x62, 0x65, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61,
+ 0x6e, 0x3b, 0x20, 0x61, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x68, 0x65, 0x20, 0x62, 0x65,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72,
+ 0x65, 0x74, 0x68, 0x72, 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x6c,
+ 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x62, 0x65, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x53, 0x68, 0x65, 0x6d, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43,
+ 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x62, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61,
+ 0x6e, 0x74, 0x2e, 0x20, 0x0a, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x65, 0x6e, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x20, 0x4a,
+ 0x61, 0x70, 0x68, 0x65, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x64, 0x77, 0x65,
+ 0x6c, 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65,
+ 0x6e, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x68, 0x65, 0x6d, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x6c, 0x69, 0x76, 0x65,
+ 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x6c, 0x6f, 0x6f, 0x64, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x20,
+ 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x66, 0x69, 0x66, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4e, 0x6f,
+ 0x61, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6e, 0x69, 0x6e, 0x65,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x66, 0x69, 0x66, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x65,
+ 0x64, 0x2e, 0x20, 0x0a, 0x4e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65, 0x73,
+ 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65,
+ 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x53, 0x68, 0x65, 0x6d, 0x2c,
+ 0x20, 0x48, 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x61,
+ 0x70, 0x68, 0x65, 0x74, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c,
+ 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x73, 0x6f,
+ 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4a, 0x61, 0x70, 0x68, 0x65, 0x74,
+ 0x68, 0x3b, 0x20, 0x47, 0x6f, 0x6d, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x4d, 0x61, 0x67, 0x6f, 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x4d, 0x61, 0x64, 0x61, 0x69, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x4a, 0x61, 0x76, 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x54,
+ 0x75, 0x62, 0x61, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4d, 0x65,
+ 0x73, 0x68, 0x65, 0x63, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x54,
+ 0x69, 0x72, 0x61, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x47,
+ 0x6f, 0x6d, 0x65, 0x72, 0x3b, 0x20, 0x41, 0x73, 0x68, 0x6b, 0x65, 0x6e,
+ 0x61, 0x7a, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x52, 0x69, 0x70, 0x68,
+ 0x61, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x54, 0x6f, 0x67,
+ 0x61, 0x72, 0x6d, 0x61, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x4a, 0x61, 0x76, 0x61, 0x6e, 0x3b, 0x20, 0x45, 0x6c, 0x69, 0x73, 0x68,
+ 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x54, 0x61, 0x72, 0x73,
+ 0x68, 0x69, 0x73, 0x68, 0x2c, 0x20, 0x4b, 0x69, 0x74, 0x74, 0x69, 0x6d,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x44, 0x6f, 0x64, 0x61, 0x6e, 0x69,
+ 0x6d, 0x2e, 0x20, 0x0a, 0x42, 0x79, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x73,
+ 0x6c, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47,
+ 0x65, 0x6e, 0x74, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x64, 0x69, 0x76, 0x69,
+ 0x64, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72,
+ 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x3b, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x74, 0x6f, 0x6e, 0x67, 0x75, 0x65, 0x2c, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20,
+ 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x61, 0x6d,
+ 0x3b, 0x20, 0x43, 0x75, 0x73, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x4d, 0x69, 0x7a, 0x72, 0x61, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x50, 0x68, 0x75, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43,
+ 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x43, 0x75, 0x73, 0x68, 0x3b, 0x20, 0x53, 0x65, 0x62, 0x61, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x48, 0x61, 0x76, 0x69, 0x6c, 0x61, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x62, 0x74, 0x61, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x52, 0x61, 0x61, 0x6d, 0x61, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x62, 0x74, 0x65, 0x63, 0x68,
+ 0x61, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x52, 0x61, 0x61, 0x6d,
+ 0x61, 0x68, 0x3b, 0x20, 0x53, 0x68, 0x65, 0x62, 0x61, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x44, 0x65, 0x64, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x43, 0x75, 0x73, 0x68, 0x20, 0x62, 0x65, 0x67, 0x61,
+ 0x74, 0x20, 0x4e, 0x69, 0x6d, 0x72, 0x6f, 0x64, 0x3a, 0x20, 0x68, 0x65,
+ 0x20, 0x62, 0x65, 0x67, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65,
+ 0x20, 0x61, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x79, 0x20, 0x6f, 0x6e,
+ 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x48, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x61, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x79, 0x20, 0x68, 0x75, 0x6e,
+ 0x74, 0x65, 0x72, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x3a, 0x20, 0x77, 0x68, 0x65,
+ 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x45, 0x76, 0x65, 0x6e, 0x20,
+ 0x61, 0x73, 0x20, 0x4e, 0x69, 0x6d, 0x72, 0x6f, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x79, 0x20, 0x68, 0x75, 0x6e,
+ 0x74, 0x65, 0x72, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x6e,
+ 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b,
+ 0x69, 0x6e, 0x67, 0x64, 0x6f, 0x6d, 0x20, 0x77, 0x61, 0x73, 0x20, 0x42,
+ 0x61, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x45, 0x72,
+ 0x65, 0x63, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x63, 0x63,
+ 0x61, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x6c, 0x6e,
+ 0x65, 0x68, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x68, 0x69, 0x6e, 0x61,
+ 0x72, 0x2e, 0x20, 0x0a, 0x4f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x6e,
+ 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x41, 0x73, 0x73, 0x68,
+ 0x75, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x75, 0x69, 0x6c,
+ 0x64, 0x65, 0x64, 0x20, 0x4e, 0x69, 0x6e, 0x65, 0x76, 0x65, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x69, 0x74,
+ 0x79, 0x20, 0x52, 0x65, 0x68, 0x6f, 0x62, 0x6f, 0x74, 0x68, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x6c, 0x61, 0x68, 0x2c, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x6e, 0x20, 0x62, 0x65,
+ 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x4e, 0x69, 0x6e, 0x65, 0x76, 0x65,
+ 0x68, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x6c, 0x61, 0x68, 0x3a,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x73,
+ 0x20, 0x61, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x63, 0x69, 0x74,
+ 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4d, 0x69, 0x7a, 0x72,
+ 0x61, 0x69, 0x6d, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4c, 0x75,
+ 0x64, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x6e, 0x61,
+ 0x6d, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x65, 0x68,
+ 0x61, 0x62, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4e, 0x61,
+ 0x70, 0x68, 0x74, 0x75, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x50, 0x61, 0x74, 0x68, 0x72, 0x75, 0x73, 0x69, 0x6d, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x73, 0x6c, 0x75, 0x68, 0x69,
+ 0x6d, 0x2c, 0x20, 0x28, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x77,
+ 0x68, 0x6f, 0x6d, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x50, 0x68, 0x69,
+ 0x6c, 0x69, 0x73, 0x74, 0x69, 0x6d, 0x2c, 0x29, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x43, 0x61, 0x70, 0x68, 0x74, 0x6f, 0x72, 0x69, 0x6d, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x53, 0x69, 0x64, 0x6f, 0x6e, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x62, 0x6f,
+ 0x72, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48, 0x65, 0x74, 0x68,
+ 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4a,
+ 0x65, 0x62, 0x75, 0x73, 0x69, 0x74, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x6d, 0x6f, 0x72, 0x69, 0x74, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x69,
+ 0x72, 0x67, 0x61, 0x73, 0x69, 0x74, 0x65, 0x2c, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x69, 0x76, 0x69, 0x74, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x72,
+ 0x6b, 0x69, 0x74, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x53, 0x69, 0x6e, 0x69, 0x74, 0x65, 0x2c, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x72, 0x76, 0x61, 0x64,
+ 0x69, 0x74, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x5a, 0x65, 0x6d, 0x61, 0x72, 0x69, 0x74, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x61, 0x6d, 0x61, 0x74,
+ 0x68, 0x69, 0x74, 0x65, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x66,
+ 0x74, 0x65, 0x72, 0x77, 0x61, 0x72, 0x64, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x61, 0x6e,
+ 0x61, 0x61, 0x6e, 0x69, 0x74, 0x65, 0x73, 0x20, 0x73, 0x70, 0x72, 0x65,
+ 0x61, 0x64, 0x20, 0x61, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x61,
+ 0x6e, 0x61, 0x61, 0x6e, 0x69, 0x74, 0x65, 0x73, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x53, 0x69, 0x64, 0x6f, 0x6e, 0x2c,
+ 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x63, 0x6f, 0x6d,
+ 0x65, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x47, 0x65, 0x72, 0x61, 0x72,
+ 0x2c, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x47, 0x61, 0x7a, 0x61, 0x3b,
+ 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x67, 0x6f, 0x65,
+ 0x73, 0x74, 0x2c, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x53, 0x6f, 0x64,
+ 0x6f, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x6d, 0x6f,
+ 0x72, 0x72, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x64,
+ 0x6d, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x5a, 0x65, 0x62,
+ 0x6f, 0x69, 0x6d, 0x2c, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x4c, 0x61, 0x73, 0x68, 0x61, 0x2e, 0x20, 0x0a, 0x54,
+ 0x68, 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x61, 0x6d,
+ 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69,
+ 0x72, 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x2c, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20,
+ 0x74, 0x6f, 0x6e, 0x67, 0x75, 0x65, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72,
+ 0x69, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x2e, 0x20, 0x0a, 0x55, 0x6e, 0x74, 0x6f, 0x20, 0x53, 0x68, 0x65,
+ 0x6d, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72,
+ 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x62, 0x65, 0x72, 0x2c, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x6f, 0x66, 0x20, 0x4a, 0x61, 0x70, 0x68, 0x65, 0x74, 0x68, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x6c, 0x64, 0x65, 0x72, 0x2c, 0x20, 0x65, 0x76,
+ 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20,
+ 0x62, 0x6f, 0x72, 0x6e, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x63,
+ 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x53,
+ 0x68, 0x65, 0x6d, 0x3b, 0x20, 0x45, 0x6c, 0x61, 0x6d, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x41, 0x73, 0x73, 0x68, 0x75, 0x72, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x41, 0x72, 0x70, 0x68, 0x61, 0x78, 0x61, 0x64, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x75, 0x64, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x41, 0x72, 0x61, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65,
+ 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x72, 0x61, 0x6d, 0x3b, 0x20, 0x55,
+ 0x7a, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48, 0x75, 0x6c, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x47, 0x65, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4d, 0x61, 0x73, 0x68, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x41, 0x72, 0x70, 0x68, 0x61, 0x78, 0x61, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x53, 0x61, 0x6c, 0x61, 0x68, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x6c, 0x61, 0x68, 0x20, 0x62,
+ 0x65, 0x67, 0x61, 0x74, 0x20, 0x45, 0x62, 0x65, 0x72, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x45, 0x62, 0x65,
+ 0x72, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x20,
+ 0x74, 0x77, 0x6f, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x3a, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6f, 0x6e,
+ 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x50, 0x65, 0x6c, 0x65, 0x67, 0x3b,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x64, 0x61, 0x79, 0x73, 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64,
+ 0x65, 0x64, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x4a, 0x6f, 0x6b, 0x74, 0x61,
+ 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x6f, 0x6b, 0x74,
+ 0x61, 0x6e, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x41, 0x6c, 0x6d,
+ 0x6f, 0x64, 0x61, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x68,
+ 0x65, 0x6c, 0x65, 0x70, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48,
+ 0x61, 0x7a, 0x61, 0x72, 0x6d, 0x61, 0x76, 0x65, 0x74, 0x68, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x65, 0x72, 0x61, 0x68, 0x2c, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x48, 0x61, 0x64, 0x6f, 0x72, 0x61, 0x6d, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x55, 0x7a, 0x61, 0x6c, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x44, 0x69, 0x6b, 0x6c, 0x61, 0x68, 0x2c, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x4f, 0x62, 0x61, 0x6c, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x41, 0x62, 0x69, 0x6d, 0x61, 0x65, 0x6c, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x53, 0x68, 0x65, 0x62, 0x61, 0x2c, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x4f, 0x70, 0x68, 0x69, 0x72, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x48, 0x61, 0x76, 0x69, 0x6c, 0x61, 0x68, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x4a, 0x6f, 0x62, 0x61, 0x62, 0x3a, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x4a, 0x6f, 0x6b, 0x74, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x64, 0x77, 0x65, 0x6c,
+ 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x61, 0x73, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x4d, 0x65, 0x73, 0x68, 0x61, 0x2c, 0x20, 0x61, 0x73, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x67, 0x6f, 0x65, 0x73, 0x74, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x53, 0x65, 0x70, 0x68, 0x61, 0x72, 0x20, 0x61,
+ 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65,
+ 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x68, 0x65, 0x6d, 0x2c,
+ 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72,
+ 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x61,
+ 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x74,
+ 0x6f, 0x6e, 0x67, 0x75, 0x65, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x69, 0x72, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x2c, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20,
+ 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x20, 0x0a, 0x54, 0x68,
+ 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x4e, 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x69, 0x72, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x73,
+ 0x65, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64,
+ 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x72, 0x74, 0x68, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x6f, 0x6c, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67,
+ 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x6f, 0x6e,
+ 0x65, 0x20, 0x73, 0x70, 0x65, 0x65, 0x63, 0x68, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74,
+ 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x65,
+ 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x73, 0x74, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x70,
+ 0x6c, 0x61, 0x69, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x68, 0x69, 0x6e,
+ 0x61, 0x72, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x64, 0x77, 0x65, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x6f, 0x20,
+ 0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x47, 0x6f, 0x20,
+ 0x74, 0x6f, 0x2c, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x75, 0x73, 0x20, 0x6d,
+ 0x61, 0x6b, 0x65, 0x20, 0x62, 0x72, 0x69, 0x63, 0x6b, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x62, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x20, 0x74, 0x68, 0x6f, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x6c, 0x79, 0x2e,
+ 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x62, 0x72, 0x69, 0x63, 0x6b, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x73, 0x74, 0x6f, 0x6e, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x6c, 0x69, 0x6d, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x6f, 0x72, 0x74, 0x65, 0x72,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x47, 0x6f, 0x20, 0x74, 0x6f, 0x2c,
+ 0x20, 0x6c, 0x65, 0x74, 0x20, 0x75, 0x73, 0x20, 0x62, 0x75, 0x69, 0x6c,
+ 0x64, 0x20, 0x75, 0x73, 0x20, 0x61, 0x20, 0x63, 0x69, 0x74, 0x79, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x74, 0x6f, 0x77, 0x65, 0x72, 0x2c,
+ 0x20, 0x77, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x74, 0x6f, 0x70, 0x20, 0x6d,
+ 0x61, 0x79, 0x20, 0x72, 0x65, 0x61, 0x63, 0x68, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x75, 0x73, 0x20, 0x6d, 0x61, 0x6b,
+ 0x65, 0x20, 0x75, 0x73, 0x20, 0x61, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2c,
+ 0x20, 0x6c, 0x65, 0x73, 0x74, 0x20, 0x77, 0x65, 0x20, 0x62, 0x65, 0x20,
+ 0x73, 0x63, 0x61, 0x74, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x61, 0x62,
+ 0x72, 0x6f, 0x61, 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x68, 0x6f, 0x6c, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74,
+ 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x64, 0x6f,
+ 0x77, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x65, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x63, 0x69, 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x6f, 0x77, 0x65, 0x72, 0x2c, 0x20, 0x77, 0x68,
+ 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c,
+ 0x64, 0x72, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x65, 0x6e, 0x20,
+ 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x20,
+ 0x69, 0x73, 0x20, 0x6f, 0x6e, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61,
+ 0x67, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x20,
+ 0x74, 0x6f, 0x20, 0x64, 0x6f, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e,
+ 0x6f, 0x77, 0x20, 0x6e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72,
+ 0x61, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x69, 0x6d, 0x61,
+ 0x67, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x6f, 0x2e,
+ 0x20, 0x0a, 0x47, 0x6f, 0x20, 0x74, 0x6f, 0x2c, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x75, 0x73, 0x20, 0x67, 0x6f, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x63,
+ 0x6f, 0x6e, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x69,
+ 0x72, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x2c, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x6d, 0x61,
+ 0x79, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x73,
+ 0x74, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x61, 0x6e, 0x6f,
+ 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x73
+};
+unsigned int bible_txt_32k_len = 32768;
diff --git a/drivers/staging/fsl_dce/tests/common/bible.txt.4k.h b/drivers/staging/fsl_dce/tests/common/bible.txt.4k.h
new file mode 100644
index 0000000..c7346c8
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/common/bible.txt.4k.h
@@ -0,0 +1,345 @@
+unsigned char bible_txt_4k[] = {
+ 0x49, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e,
+ 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65,
+ 0x61, 0x74, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61,
+ 0x76, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e, 0x65, 0x73,
+ 0x73, 0x20, 0x77, 0x61, 0x73, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x65, 0x65, 0x70, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x70, 0x69, 0x72, 0x69, 0x74, 0x20,
+ 0x6f, 0x66, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x6f, 0x76, 0x65, 0x64,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61,
+ 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x6c, 0x69,
+ 0x67, 0x68, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73,
+ 0x61, 0x77, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x20, 0x66, 0x72,
+ 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e,
+ 0x65, 0x73, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x20, 0x44, 0x61, 0x79, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x72, 0x6b,
+ 0x6e, 0x65, 0x73, 0x73, 0x20, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c,
+ 0x65, 0x64, 0x20, 0x4e, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x20, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f,
+ 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x64, 0x61, 0x79,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x66, 0x69, 0x72, 0x6d,
+ 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x69, 0x64, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x69, 0x74, 0x20, 0x64, 0x69, 0x76,
+ 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65,
+ 0x72, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20,
+ 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x75,
+ 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72,
+ 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x61, 0x62,
+ 0x6f, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d,
+ 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69,
+ 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d,
+ 0x65, 0x6e, 0x74, 0x20, 0x48, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x2e, 0x20,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e,
+ 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20,
+ 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x75,
+ 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61,
+ 0x76, 0x65, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x67, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x70, 0x6c,
+ 0x61, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x72, 0x79, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61,
+ 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x72, 0x79,
+ 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x45, 0x61, 0x72, 0x74, 0x68, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x53, 0x65, 0x61, 0x73, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f,
+ 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x62, 0x72, 0x69,
+ 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x67, 0x72, 0x61,
+ 0x73, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x72, 0x62,
+ 0x20, 0x79, 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65,
+ 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x79,
+ 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x77, 0x68, 0x6f, 0x73, 0x65, 0x20,
+ 0x73, 0x65, 0x65, 0x64, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x69,
+ 0x74, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x67, 0x72, 0x61, 0x73, 0x73,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x72, 0x62, 0x20, 0x79,
+ 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65, 0x65, 0x64,
+ 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b,
+ 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x79, 0x69, 0x65, 0x6c, 0x64, 0x69,
+ 0x6e, 0x67, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x2c, 0x20, 0x77, 0x68,
+ 0x6f, 0x73, 0x65, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x69, 0x6e, 0x20, 0x69, 0x74, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69,
+ 0x6e, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69,
+ 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x6f, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64, 0x20, 0x64, 0x61,
+ 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
+ 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72,
+ 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20,
+ 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x79, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6e, 0x69, 0x67, 0x68, 0x74, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c,
+ 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x62, 0x65, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x65, 0x61, 0x73, 0x6f, 0x6e,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64,
+ 0x61, 0x79, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x76,
+ 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x6c,
+ 0x69, 0x67, 0x68, 0x74, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64,
+ 0x65, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20,
+ 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x3b, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x67, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x67, 0x68,
+ 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x61, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x6c, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x68,
+ 0x65, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x74, 0x61, 0x72, 0x73, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x65, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x20,
+ 0x74, 0x6f, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68,
+ 0x74, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x6f, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x69, 0x67,
+ 0x68, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64,
+ 0x69, 0x76, 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e, 0x65, 0x73, 0x73, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67,
+ 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x6f, 0x75, 0x72, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x74, 0x65, 0x72, 0x73, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66,
+ 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x62, 0x75, 0x6e, 0x64, 0x61, 0x6e,
+ 0x74, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x76, 0x69,
+ 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x6c, 0x69,
+ 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x77, 0x6c,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x66, 0x6c,
+ 0x79, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d,
+ 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65,
+ 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x67, 0x72, 0x65, 0x61,
+ 0x74, 0x20, 0x77, 0x68, 0x61, 0x6c, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69,
+ 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x6f, 0x76, 0x65, 0x74, 0x68, 0x2c,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68,
+ 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x62, 0x75, 0x6e,
+ 0x64, 0x61, 0x6e, 0x74, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e, 0x64,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20,
+ 0x77, 0x69, 0x6e, 0x67, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69,
+ 0x6e, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73,
+ 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x73, 0x61, 0x79,
+ 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x42, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75,
+ 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x66, 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74,
+ 0x65, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x61, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70,
+ 0x6c, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x69, 0x66, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e,
+ 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x61,
+ 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e,
+ 0x64, 0x2c, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20,
+ 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61,
+ 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x61, 0x73, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74,
+ 0x68, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61,
+ 0x74, 0x74, 0x6c, 0x65, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x68, 0x69,
+ 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x72, 0x65, 0x65,
+ 0x70, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74,
+ 0x20, 0x75, 0x73, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x6d, 0x61, 0x6e,
+ 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x75, 0x72, 0x20, 0x69, 0x6d, 0x61, 0x67,
+ 0x65, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x6f, 0x75, 0x72,
+ 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x6f,
+ 0x6e, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x69, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x61, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f,
+ 0x76, 0x65, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f,
+ 0x76, 0x65, 0x72, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x72,
+ 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x65,
+ 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x53, 0x6f, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6d,
+ 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x77,
+ 0x6e, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x3b, 0x20, 0x6d, 0x61, 0x6c,
+ 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65,
+ 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x42, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75,
+ 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x72, 0x65, 0x70, 0x6c, 0x65, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x75, 0x62, 0x64, 0x75, 0x65, 0x20, 0x69, 0x74, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x64, 0x6f, 0x6d,
+ 0x69, 0x6e, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x65, 0x61, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x77,
+ 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x65,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x20,
+ 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d,
+ 0x6f, 0x76, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x68,
+ 0x61, 0x76, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x79, 0x6f,
+ 0x75, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x68, 0x65, 0x72, 0x62,
+ 0x20, 0x62, 0x65, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65, 0x65,
+ 0x64, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x72, 0x65, 0x65, 0x2c, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20,
+ 0x79, 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65, 0x65,
+ 0x64, 0x3b, 0x20, 0x74, 0x6f, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x69, 0x74,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x6d, 0x65, 0x61, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x62, 0x65,
+ 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x63, 0x72, 0x65, 0x65, 0x70, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c,
+ 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x2c, 0x20,
+ 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x67, 0x72, 0x65, 0x65, 0x6e,
+ 0x20, 0x68, 0x65, 0x72, 0x62, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x65,
+ 0x61, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x76, 0x65,
+ 0x72, 0x79, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e, 0x67,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72,
+ 0x6e, 0x69, 0x6e, 0x67
+};
+unsigned int bible_txt_4k_len = 4096;
diff --git a/drivers/staging/fsl_dce/tests/common/bible.txt.64k.h b/drivers/staging/fsl_dce/tests/common/bible.txt.64k.h
new file mode 100644
index 0000000..df5b8698
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/common/bible.txt.64k.h
@@ -0,0 +1,5465 @@
+unsigned char bible_txt_64k[] = {
+ 0x49, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e,
+ 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65,
+ 0x61, 0x74, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61,
+ 0x76, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e, 0x65, 0x73,
+ 0x73, 0x20, 0x77, 0x61, 0x73, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x65, 0x65, 0x70, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x70, 0x69, 0x72, 0x69, 0x74, 0x20,
+ 0x6f, 0x66, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x6f, 0x76, 0x65, 0x64,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61,
+ 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x6c, 0x69,
+ 0x67, 0x68, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73,
+ 0x61, 0x77, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x20, 0x66, 0x72,
+ 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e,
+ 0x65, 0x73, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x20, 0x44, 0x61, 0x79, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x72, 0x6b,
+ 0x6e, 0x65, 0x73, 0x73, 0x20, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c,
+ 0x65, 0x64, 0x20, 0x4e, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x20, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f,
+ 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x64, 0x61, 0x79,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x66, 0x69, 0x72, 0x6d,
+ 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x69, 0x64, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x69, 0x74, 0x20, 0x64, 0x69, 0x76,
+ 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65,
+ 0x72, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20,
+ 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x75,
+ 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72,
+ 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x61, 0x62,
+ 0x6f, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d,
+ 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69,
+ 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d,
+ 0x65, 0x6e, 0x74, 0x20, 0x48, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x2e, 0x20,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e,
+ 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20,
+ 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x75,
+ 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61,
+ 0x76, 0x65, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x67, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x70, 0x6c,
+ 0x61, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x72, 0x79, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61,
+ 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x72, 0x79,
+ 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x45, 0x61, 0x72, 0x74, 0x68, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x53, 0x65, 0x61, 0x73, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f,
+ 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x62, 0x72, 0x69,
+ 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x67, 0x72, 0x61,
+ 0x73, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x72, 0x62,
+ 0x20, 0x79, 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65,
+ 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x79,
+ 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x77, 0x68, 0x6f, 0x73, 0x65, 0x20,
+ 0x73, 0x65, 0x65, 0x64, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x69,
+ 0x74, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x67, 0x72, 0x61, 0x73, 0x73,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x72, 0x62, 0x20, 0x79,
+ 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65, 0x65, 0x64,
+ 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b,
+ 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x79, 0x69, 0x65, 0x6c, 0x64, 0x69,
+ 0x6e, 0x67, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x2c, 0x20, 0x77, 0x68,
+ 0x6f, 0x73, 0x65, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x69, 0x6e, 0x20, 0x69, 0x74, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69,
+ 0x6e, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69,
+ 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x6f, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64, 0x20, 0x64, 0x61,
+ 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
+ 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72,
+ 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20,
+ 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x79, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6e, 0x69, 0x67, 0x68, 0x74, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c,
+ 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x62, 0x65, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x65, 0x61, 0x73, 0x6f, 0x6e,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64,
+ 0x61, 0x79, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x76,
+ 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x6c,
+ 0x69, 0x67, 0x68, 0x74, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64,
+ 0x65, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20,
+ 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x3b, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x67, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x67, 0x68,
+ 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x61, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x6c, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x68,
+ 0x65, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x74, 0x61, 0x72, 0x73, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x65, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x20,
+ 0x74, 0x6f, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68,
+ 0x74, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x6f, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x69, 0x67,
+ 0x68, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64,
+ 0x69, 0x76, 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e, 0x65, 0x73, 0x73, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67,
+ 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x6f, 0x75, 0x72, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x74, 0x65, 0x72, 0x73, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66,
+ 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x62, 0x75, 0x6e, 0x64, 0x61, 0x6e,
+ 0x74, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x76, 0x69,
+ 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x6c, 0x69,
+ 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x77, 0x6c,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x66, 0x6c,
+ 0x79, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d,
+ 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65,
+ 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x67, 0x72, 0x65, 0x61,
+ 0x74, 0x20, 0x77, 0x68, 0x61, 0x6c, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69,
+ 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x6f, 0x76, 0x65, 0x74, 0x68, 0x2c,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68,
+ 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x62, 0x75, 0x6e,
+ 0x64, 0x61, 0x6e, 0x74, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e, 0x64,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20,
+ 0x77, 0x69, 0x6e, 0x67, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69,
+ 0x6e, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73,
+ 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x73, 0x61, 0x79,
+ 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x42, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75,
+ 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x66, 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74,
+ 0x65, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x61, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70,
+ 0x6c, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x69, 0x66, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e,
+ 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x61,
+ 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e,
+ 0x64, 0x2c, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20,
+ 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61,
+ 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x61, 0x73, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74,
+ 0x68, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61,
+ 0x74, 0x74, 0x6c, 0x65, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x68, 0x69,
+ 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x72, 0x65, 0x65,
+ 0x70, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74,
+ 0x20, 0x75, 0x73, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x6d, 0x61, 0x6e,
+ 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x75, 0x72, 0x20, 0x69, 0x6d, 0x61, 0x67,
+ 0x65, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x6f, 0x75, 0x72,
+ 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x6f,
+ 0x6e, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x69, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x61, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f,
+ 0x76, 0x65, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f,
+ 0x76, 0x65, 0x72, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x72,
+ 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x65,
+ 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x53, 0x6f, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6d,
+ 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x77,
+ 0x6e, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x3b, 0x20, 0x6d, 0x61, 0x6c,
+ 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65,
+ 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x42, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75,
+ 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x72, 0x65, 0x70, 0x6c, 0x65, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x75, 0x62, 0x64, 0x75, 0x65, 0x20, 0x69, 0x74, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x64, 0x6f, 0x6d,
+ 0x69, 0x6e, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x65, 0x61, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x77,
+ 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x65,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x20,
+ 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d,
+ 0x6f, 0x76, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x68,
+ 0x61, 0x76, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x79, 0x6f,
+ 0x75, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x68, 0x65, 0x72, 0x62,
+ 0x20, 0x62, 0x65, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65, 0x65,
+ 0x64, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x72, 0x65, 0x65, 0x2c, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20,
+ 0x79, 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65, 0x65,
+ 0x64, 0x3b, 0x20, 0x74, 0x6f, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x69, 0x74,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x6d, 0x65, 0x61, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x62, 0x65,
+ 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x63, 0x72, 0x65, 0x65, 0x70, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c,
+ 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x2c, 0x20,
+ 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x67, 0x72, 0x65, 0x65, 0x6e,
+ 0x20, 0x68, 0x65, 0x72, 0x62, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x65,
+ 0x61, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x76, 0x65,
+ 0x72, 0x79, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e, 0x67,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72,
+ 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x69, 0x78, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79, 0x2e,
+ 0x20, 0x0a, 0x54, 0x68, 0x75, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68,
+ 0x65, 0x61, 0x76, 0x65, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x68, 0x6f, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x64, 0x61,
+ 0x79, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61,
+ 0x64, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x72,
+ 0x65, 0x73, 0x74, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x62,
+ 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x76, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x6e, 0x63, 0x74, 0x69, 0x66, 0x69,
+ 0x65, 0x64, 0x20, 0x69, 0x74, 0x3a, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75,
+ 0x73, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x69,
+ 0x74, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x72, 0x65, 0x73,
+ 0x74, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x6c, 0x6c,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x68,
+ 0x69, 0x63, 0x68, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65, 0x61,
+ 0x74, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65,
+ 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x77,
+ 0x65, 0x72, 0x65, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x2c,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x73,
+ 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x66, 0x6f,
+ 0x72, 0x65, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x68, 0x65,
+ 0x72, 0x62, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69,
+ 0x65, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x69,
+ 0x74, 0x20, 0x67, 0x72, 0x65, 0x77, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x61, 0x75,
+ 0x73, 0x65, 0x64, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x61,
+ 0x69, 0x6e, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x74,
+ 0x20, 0x61, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x69,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2e, 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x72,
+ 0x65, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x70, 0x20, 0x61, 0x20,
+ 0x6d, 0x69, 0x73, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x68, 0x6f, 0x6c, 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72,
+ 0x6d, 0x65, 0x64, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x75, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x62, 0x72, 0x65, 0x61, 0x74, 0x68, 0x65, 0x64, 0x20,
+ 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x73,
+ 0x74, 0x72, 0x69, 0x6c, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x72,
+ 0x65, 0x61, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x69, 0x66, 0x65,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x62, 0x65,
+ 0x63, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e,
+ 0x67, 0x20, 0x73, 0x6f, 0x75, 0x6c, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x61, 0x20,
+ 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x20, 0x65, 0x61, 0x73, 0x74, 0x77,
+ 0x61, 0x72, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x45, 0x64, 0x65, 0x6e, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x68,
+ 0x65, 0x20, 0x70, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61,
+ 0x6e, 0x20, 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x64,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x72, 0x6f, 0x77, 0x20, 0x65,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x70, 0x6c, 0x65, 0x61, 0x73, 0x61,
+ 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69,
+ 0x67, 0x68, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x6f, 0x6f,
+ 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x66, 0x6f, 0x6f, 0x64, 0x3b, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x6c, 0x69, 0x66, 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x69, 0x64, 0x73, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72,
+ 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x6c, 0x65,
+ 0x64, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x69, 0x6c, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x61, 0x20, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x77,
+ 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x45,
+ 0x64, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68,
+ 0x65, 0x6e, 0x63, 0x65, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x70, 0x61, 0x72, 0x74, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20,
+ 0x66, 0x6f, 0x75, 0x72, 0x20, 0x68, 0x65, 0x61, 0x64, 0x73, 0x2e, 0x20,
+ 0x0a, 0x54, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x69,
+ 0x73, 0x20, 0x50, 0x69, 0x73, 0x6f, 0x6e, 0x3a, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x69, 0x73, 0x20, 0x69, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63,
+ 0x68, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x73, 0x73, 0x65, 0x74, 0x68,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x6f, 0x6c, 0x65, 0x20, 0x6c,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x61, 0x76, 0x69, 0x6c,
+ 0x61, 0x68, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x67, 0x6f, 0x6c, 0x64, 0x3b,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x6f,
+ 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6c,
+ 0x61, 0x6e, 0x64, 0x20, 0x69, 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x3a,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x62, 0x64,
+ 0x65, 0x6c, 0x6c, 0x69, 0x75, 0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6f, 0x6e, 0x79, 0x78, 0x20, 0x73, 0x74, 0x6f, 0x6e,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20, 0x72, 0x69, 0x76, 0x65, 0x72,
+ 0x20, 0x69, 0x73, 0x20, 0x47, 0x69, 0x68, 0x6f, 0x6e, 0x3a, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x73, 0x20, 0x69,
+ 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61,
+ 0x73, 0x73, 0x65, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68,
+ 0x6f, 0x6c, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x45, 0x74, 0x68, 0x69, 0x6f, 0x70, 0x69, 0x61, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64,
+ 0x20, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x48, 0x69,
+ 0x64, 0x64, 0x65, 0x6b, 0x65, 0x6c, 0x3a, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x69, 0x73, 0x20, 0x69, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x67, 0x6f, 0x65, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x77, 0x61, 0x72,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x41, 0x73, 0x73, 0x79, 0x72, 0x69, 0x61, 0x2e, 0x20, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x75, 0x72, 0x74,
+ 0x68, 0x20, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x45,
+ 0x75, 0x70, 0x68, 0x72, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x75,
+ 0x74, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x20, 0x6f, 0x66,
+ 0x20, 0x45, 0x64, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x72, 0x65,
+ 0x73, 0x73, 0x20, 0x69, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f,
+ 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x69, 0x74, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x73,
+ 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x4f, 0x66, 0x20, 0x65, 0x76,
+ 0x65, 0x72, 0x79, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x65, 0x73, 0x74, 0x20, 0x66,
+ 0x72, 0x65, 0x65, 0x6c, 0x79, 0x20, 0x65, 0x61, 0x74, 0x3a, 0x20, 0x0a,
+ 0x42, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
+ 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b,
+ 0x6e, 0x6f, 0x77, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x69,
+ 0x6c, 0x2c, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c,
+ 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x61, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x69, 0x74, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x65, 0x61, 0x74, 0x65, 0x73, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x73, 0x75, 0x72, 0x65,
+ 0x6c, 0x79, 0x20, 0x64, 0x69, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x74, 0x20, 0x69,
+ 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x20,
+ 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6c,
+ 0x6f, 0x6e, 0x65, 0x3b, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61, 0x6e, 0x20,
+ 0x68, 0x65, 0x6c, 0x70, 0x20, 0x6d, 0x65, 0x65, 0x74, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x65,
+ 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x62, 0x65, 0x61, 0x73,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65,
+ 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x61, 0x69, 0x72, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x74, 0x6f,
+ 0x20, 0x73, 0x65, 0x65, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65,
+ 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68,
+ 0x61, 0x74, 0x73, 0x6f, 0x65, 0x76, 0x65, 0x72, 0x20, 0x41, 0x64, 0x61,
+ 0x6d, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x65, 0x76, 0x65,
+ 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x72,
+ 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x67, 0x61, 0x76,
+ 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f,
+ 0x77, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69,
+ 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x76,
+ 0x65, 0x72, 0x79, 0x20, 0x62, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x3b, 0x20,
+ 0x62, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x41, 0x64, 0x61, 0x6d,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x20,
+ 0x68, 0x65, 0x6c, 0x70, 0x20, 0x6d, 0x65, 0x65, 0x74, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x63, 0x61, 0x75, 0x73, 0x65, 0x64, 0x20, 0x61, 0x20, 0x64, 0x65,
+ 0x65, 0x70, 0x20, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x20, 0x74, 0x6f, 0x20,
+ 0x66, 0x61, 0x6c, 0x6c, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x41, 0x64,
+ 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73,
+ 0x6c, 0x65, 0x70, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x72, 0x69, 0x62, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x20, 0x75, 0x70,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20, 0x69,
+ 0x6e, 0x73, 0x74, 0x65, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65,
+ 0x6f, 0x66, 0x3b, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x72, 0x69, 0x62, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x6d, 0x61, 0x64,
+ 0x65, 0x20, 0x68, 0x65, 0x20, 0x61, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68,
+ 0x74, 0x20, 0x68, 0x65, 0x72, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20,
+ 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20,
+ 0x62, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x62,
+ 0x6f, 0x6e, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6c,
+ 0x65, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x66, 0x6c,
+ 0x65, 0x73, 0x68, 0x3a, 0x20, 0x73, 0x68, 0x65, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x57, 0x6f, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x62, 0x65, 0x63, 0x61,
+ 0x75, 0x73, 0x65, 0x20, 0x73, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x4d, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x72, 0x65,
+ 0x66, 0x6f, 0x72, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x61,
+ 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x63, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c,
+ 0x20, 0x62, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x66, 0x6c, 0x65, 0x73,
+ 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6e,
+ 0x61, 0x6b, 0x65, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61,
+ 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69,
+ 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x73, 0x68, 0x61, 0x6d, 0x65, 0x64,
+ 0x2e, 0x20, 0x0a, 0x4e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x72, 0x70, 0x65, 0x6e, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6d,
+ 0x6f, 0x72, 0x65, 0x20, 0x73, 0x75, 0x62, 0x74, 0x69, 0x6c, 0x20, 0x74,
+ 0x68, 0x61, 0x6e, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x62, 0x65, 0x61, 0x73,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65,
+ 0x6c, 0x64, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x2c, 0x20,
+ 0x59, 0x65, 0x61, 0x2c, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x59, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x61, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x72,
+ 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61,
+ 0x72, 0x64, 0x65, 0x6e, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x72, 0x70, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x57, 0x65, 0x20, 0x6d,
+ 0x61, 0x79, 0x20, 0x65, 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x3a, 0x20,
+ 0x0a, 0x42, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x69,
+ 0x64, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67,
+ 0x61, 0x72, 0x64, 0x65, 0x6e, 0x2c, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68,
+ 0x61, 0x74, 0x68, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x59, 0x65,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65,
+ 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x6e, 0x65,
+ 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x79, 0x65, 0x20, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x20, 0x69, 0x74, 0x2c,
+ 0x20, 0x6c, 0x65, 0x73, 0x74, 0x20, 0x79, 0x65, 0x20, 0x64, 0x69, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x72, 0x70, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d,
+ 0x61, 0x6e, 0x2c, 0x20, 0x59, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x72, 0x65, 0x6c, 0x79, 0x20,
+ 0x64, 0x69, 0x65, 0x3a, 0x20, 0x0a, 0x46, 0x6f, 0x72, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x64, 0x6f, 0x74, 0x68, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x64, 0x61, 0x79, 0x20, 0x79, 0x65, 0x20, 0x65, 0x61, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x6e,
+ 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x65, 0x79, 0x65, 0x73, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6f, 0x70, 0x65, 0x6e,
+ 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x73, 0x20, 0x67,
+ 0x6f, 0x64, 0x73, 0x2c, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x69, 0x6e, 0x67,
+ 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76,
+ 0x69, 0x6c, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20,
+ 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f,
+ 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x66, 0x6f, 0x6f, 0x64, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x70, 0x6c, 0x65, 0x61, 0x73, 0x61, 0x6e,
+ 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x79, 0x65,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x74, 0x72, 0x65,
+ 0x65, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x64, 0x65, 0x73, 0x69,
+ 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20,
+ 0x6f, 0x6e, 0x65, 0x20, 0x77, 0x69, 0x73, 0x65, 0x2c, 0x20, 0x73, 0x68,
+ 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x74, 0x68, 0x65, 0x72,
+ 0x65, 0x6f, 0x66, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x64,
+ 0x20, 0x65, 0x61, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x61,
+ 0x76, 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x65, 0x72, 0x20, 0x68, 0x75, 0x73, 0x62, 0x61, 0x6e, 0x64,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x65, 0x72, 0x3b, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x64, 0x20, 0x65, 0x61,
+ 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x79, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6f,
+ 0x70, 0x65, 0x6e, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x6b, 0x6e, 0x65, 0x77, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x6e, 0x61, 0x6b, 0x65, 0x64, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x73, 0x65, 0x77, 0x65, 0x64, 0x20, 0x66, 0x69,
+ 0x67, 0x20, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x67,
+ 0x65, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d,
+ 0x61, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x73, 0x65, 0x6c, 0x76,
+ 0x65, 0x73, 0x20, 0x61, 0x70, 0x72, 0x6f, 0x6e, 0x73, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x68, 0x65, 0x61,
+ 0x72, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x77, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64,
+ 0x65, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f,
+ 0x6f, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61,
+ 0x79, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65,
+ 0x20, 0x68, 0x69, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x73, 0x65, 0x6c,
+ 0x76, 0x65, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x73, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x57, 0x68, 0x65, 0x72, 0x65, 0x20,
+ 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x3f, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20,
+ 0x49, 0x20, 0x68, 0x65, 0x61, 0x72, 0x64, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x76, 0x6f, 0x69, 0x63, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x49, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x66, 0x72, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x49,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e, 0x61, 0x6b, 0x65, 0x64, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x68, 0x69, 0x64, 0x20, 0x6d, 0x79,
+ 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x57, 0x68, 0x6f, 0x20,
+ 0x74, 0x6f, 0x6c, 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x77, 0x61, 0x73, 0x74,
+ 0x20, 0x6e, 0x61, 0x6b, 0x65, 0x64, 0x3f, 0x20, 0x48, 0x61, 0x73, 0x74,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x65, 0x61, 0x74, 0x65, 0x6e, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x2c,
+ 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x20, 0x49, 0x20, 0x63,
+ 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x65, 0x73, 0x74, 0x20, 0x6e, 0x6f,
+ 0x74, 0x20, 0x65, 0x61, 0x74, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x54, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20,
+ 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x67, 0x61,
+ 0x76, 0x65, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x68, 0x65, 0x20,
+ 0x67, 0x61, 0x76, 0x65, 0x20, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x49, 0x20, 0x64, 0x69, 0x64, 0x20, 0x65, 0x61, 0x74, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61,
+ 0x6e, 0x2c, 0x20, 0x57, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74,
+ 0x68, 0x69, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x3f,
+ 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d,
+ 0x61, 0x6e, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x65,
+ 0x20, 0x73, 0x65, 0x72, 0x70, 0x65, 0x6e, 0x74, 0x20, 0x62, 0x65, 0x67,
+ 0x75, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x49, 0x20, 0x64, 0x69, 0x64, 0x20, 0x65, 0x61, 0x74, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72,
+ 0x70, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x42, 0x65, 0x63, 0x61, 0x75, 0x73,
+ 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20,
+ 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2c, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x61, 0x72, 0x74, 0x20, 0x63, 0x75, 0x72, 0x73,
+ 0x65, 0x64, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20, 0x61, 0x6c, 0x6c,
+ 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x62, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x3b, 0x20, 0x75, 0x70, 0x6f,
+ 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x65, 0x6c, 0x6c, 0x79, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x67,
+ 0x6f, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x75, 0x73, 0x74, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x65,
+ 0x61, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6c,
+ 0x69, 0x66, 0x65, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x70, 0x75, 0x74, 0x20, 0x65, 0x6e, 0x6d,
+ 0x69, 0x74, 0x79, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x73, 0x65, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x72,
+ 0x20, 0x73, 0x65, 0x65, 0x64, 0x3b, 0x20, 0x69, 0x74, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x72, 0x75, 0x69, 0x73, 0x65, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x68, 0x65, 0x61, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20,
+ 0x62, 0x72, 0x75, 0x69, 0x73, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68,
+ 0x65, 0x65, 0x6c, 0x2e, 0x20, 0x0a, 0x55, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20, 0x68, 0x65, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x6c, 0x79, 0x20, 0x6d, 0x75, 0x6c,
+ 0x74, 0x69, 0x70, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x6f,
+ 0x72, 0x72, 0x6f, 0x77, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3b,
+ 0x20, 0x69, 0x6e, 0x20, 0x73, 0x6f, 0x72, 0x72, 0x6f, 0x77, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x62, 0x72,
+ 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x63, 0x68,
+ 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x79, 0x20, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x68, 0x75, 0x73, 0x62, 0x61, 0x6e, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c,
+ 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x68,
+ 0x65, 0x61, 0x72, 0x6b, 0x65, 0x6e, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x65, 0x61,
+ 0x74, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
+ 0x72, 0x65, 0x65, 0x2c, 0x20, 0x6f, 0x66, 0x20, 0x77, 0x68, 0x69, 0x63,
+ 0x68, 0x20, 0x49, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69,
+ 0x6e, 0x67, 0x2c, 0x20, 0x54, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x61, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x69, 0x74, 0x3a, 0x20, 0x63, 0x75, 0x72, 0x73, 0x65, 0x64,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75,
+ 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73,
+ 0x61, 0x6b, 0x65, 0x3b, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x6f, 0x72, 0x72,
+ 0x6f, 0x77, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x65, 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6c, 0x69, 0x66, 0x65,
+ 0x3b, 0x20, 0x0a, 0x54, 0x68, 0x6f, 0x72, 0x6e, 0x73, 0x20, 0x61, 0x6c,
+ 0x73, 0x6f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x74,
+ 0x6c, 0x65, 0x73, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x69, 0x74,
+ 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68,
+ 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74,
+ 0x20, 0x65, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x72,
+ 0x62, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65,
+ 0x6c, 0x64, 0x3b, 0x20, 0x0a, 0x49, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x77, 0x65, 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x65, 0x61, 0x74, 0x20, 0x62, 0x72, 0x65,
+ 0x61, 0x64, 0x2c, 0x20, 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x3a, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x64, 0x75, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x61,
+ 0x72, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x64, 0x75, 0x73, 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x63,
+ 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69,
+ 0x66, 0x65, 0x27, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x45, 0x76,
+ 0x65, 0x3b, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c,
+ 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x2e, 0x20, 0x0a, 0x55, 0x6e,
+ 0x74, 0x6f, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x61, 0x6c, 0x73, 0x6f,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x77, 0x69, 0x66, 0x65, 0x20, 0x64, 0x69, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61,
+ 0x6b, 0x65, 0x20, 0x63, 0x6f, 0x61, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x73, 0x6b, 0x69, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63,
+ 0x6c, 0x6f, 0x74, 0x68, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x62, 0x65, 0x63, 0x6f,
+ 0x6d, 0x65, 0x20, 0x61, 0x73, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x75, 0x73, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x6b, 0x6e, 0x6f, 0x77,
+ 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76,
+ 0x69, 0x6c, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x6f, 0x77, 0x2c,
+ 0x20, 0x6c, 0x65, 0x73, 0x74, 0x20, 0x68, 0x65, 0x20, 0x70, 0x75, 0x74,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68,
+ 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x61, 0x6b,
+ 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x69,
+ 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x61, 0x74, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x65, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x0a, 0x54, 0x68, 0x65,
+ 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x65, 0x6e, 0x74,
+ 0x20, 0x68, 0x69, 0x6d, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64,
+ 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x64, 0x65, 0x6e, 0x2c, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x77, 0x68, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x53, 0x6f,
+ 0x20, 0x68, 0x65, 0x20, 0x64, 0x72, 0x6f, 0x76, 0x65, 0x20, 0x6f, 0x75,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x3b, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x64,
+ 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x73, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64,
+ 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x64, 0x65, 0x6e, 0x20, 0x43,
+ 0x68, 0x65, 0x72, 0x75, 0x62, 0x69, 0x6d, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x61, 0x20, 0x66, 0x6c, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x20,
+ 0x73, 0x77, 0x6f, 0x72, 0x64, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x77, 0x61, 0x79, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x6b, 0x65, 0x65,
+ 0x70, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x79, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x6c, 0x69, 0x66, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x41, 0x64, 0x61, 0x6d, 0x20, 0x6b, 0x6e, 0x65, 0x77, 0x20, 0x45, 0x76,
+ 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x63,
+ 0x65, 0x69, 0x76, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x61, 0x72, 0x65, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x67, 0x6f, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x61, 0x20,
+ 0x6d, 0x61, 0x6e, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x73, 0x68, 0x65, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x20, 0x62, 0x61,
+ 0x72, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68,
+ 0x65, 0x72, 0x20, 0x41, 0x62, 0x65, 0x6c, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x62, 0x65, 0x6c, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x20,
+ 0x6b, 0x65, 0x65, 0x70, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x68,
+ 0x65, 0x65, 0x70, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x43, 0x61, 0x69,
+ 0x6e, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x20, 0x74, 0x69, 0x6c, 0x6c,
+ 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69,
+ 0x6e, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d,
+ 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20, 0x62, 0x72, 0x6f,
+ 0x75, 0x67, 0x68, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x6f,
+ 0x66, 0x66, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x68, 0x65,
+ 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72,
+ 0x73, 0x74, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63, 0x74, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x41, 0x62, 0x65, 0x6c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72,
+ 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72,
+ 0x69, 0x6e, 0x67, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63, 0x74, 0x2e, 0x20,
+ 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x77, 0x72, 0x6f, 0x74, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x75,
+ 0x6e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x66, 0x65, 0x6c,
+ 0x6c, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x57, 0x68, 0x79,
+ 0x20, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x77, 0x72,
+ 0x6f, 0x74, 0x68, 0x3f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x79,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x79, 0x20, 0x63, 0x6f, 0x75, 0x6e,
+ 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x66, 0x61, 0x6c, 0x6c,
+ 0x65, 0x6e, 0x3f, 0x20, 0x0a, 0x49, 0x66, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x64, 0x6f, 0x65, 0x73, 0x74, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x2c,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70,
+ 0x74, 0x65, 0x64, 0x3f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x66, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x74, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x2c, 0x20, 0x73, 0x69, 0x6e,
+ 0x20, 0x6c, 0x69, 0x65, 0x74, 0x68, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x6f, 0x6f, 0x72, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x64,
+ 0x65, 0x73, 0x69, 0x72, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x72, 0x75,
+ 0x6c, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x68, 0x69, 0x6d, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20, 0x74,
+ 0x61, 0x6c, 0x6b, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x41,
+ 0x62, 0x65, 0x6c, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20,
+ 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73,
+ 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x77, 0x65, 0x72, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x69, 0x65, 0x6c, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x43, 0x61, 0x69, 0x6e, 0x20, 0x72, 0x6f, 0x73, 0x65, 0x20, 0x75, 0x70,
+ 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x73, 0x74, 0x20, 0x41, 0x62, 0x65,
+ 0x6c, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65,
+ 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x6c, 0x65, 0x77, 0x20,
+ 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x57,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x41, 0x62, 0x65, 0x6c,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x3f, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x49, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20, 0x6e, 0x6f,
+ 0x74, 0x3a, 0x20, 0x41, 0x6d, 0x20, 0x49, 0x20, 0x6d, 0x79, 0x20, 0x62,
+ 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x6b, 0x65, 0x65,
+ 0x70, 0x65, 0x72, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x57, 0x68, 0x61, 0x74, 0x20,
+ 0x68, 0x61, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x64, 0x6f,
+ 0x6e, 0x65, 0x3f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x63,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x72, 0x6f,
+ 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x62, 0x6c, 0x6f, 0x6f, 0x64,
+ 0x20, 0x63, 0x72, 0x69, 0x65, 0x74, 0x68, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x6d, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x63, 0x75, 0x72, 0x73, 0x65, 0x64, 0x20, 0x66, 0x72,
+ 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x68, 0x61, 0x74, 0x68,
+ 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x65, 0x64, 0x20, 0x68, 0x65, 0x72, 0x20,
+ 0x6d, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, 0x63,
+ 0x65, 0x69, 0x76, 0x65, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x72, 0x6f,
+ 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x62, 0x6c, 0x6f, 0x6f, 0x64,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x79, 0x20, 0x68, 0x61,
+ 0x6e, 0x64, 0x3b, 0x20, 0x0a, 0x57, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x74, 0x69, 0x6c, 0x6c, 0x65, 0x73, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2c, 0x20, 0x69,
+ 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x68, 0x65, 0x6e, 0x63, 0x65, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x79,
+ 0x69, 0x65, 0x6c, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x20, 0x68, 0x65, 0x72, 0x20, 0x73, 0x74, 0x72, 0x65, 0x6e,
+ 0x67, 0x74, 0x68, 0x3b, 0x20, 0x61, 0x20, 0x66, 0x75, 0x67, 0x69, 0x74,
+ 0x69, 0x76, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x76, 0x61,
+ 0x67, 0x61, 0x62, 0x6f, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x62, 0x65, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x2c, 0x20, 0x4d, 0x79, 0x20, 0x70, 0x75, 0x6e, 0x69,
+ 0x73, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x73, 0x20, 0x67, 0x72,
+ 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x20, 0x49,
+ 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x61, 0x72, 0x2e, 0x20, 0x0a,
+ 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x64, 0x72, 0x69, 0x76, 0x65, 0x6e,
+ 0x20, 0x6d, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x64, 0x61, 0x79, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x79, 0x20, 0x66, 0x61,
+ 0x63, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x49, 0x20, 0x62,
+ 0x65, 0x20, 0x68, 0x69, 0x64, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20,
+ 0x66, 0x75, 0x67, 0x69, 0x74, 0x69, 0x76, 0x65, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x61, 0x20, 0x76, 0x61, 0x67, 0x61, 0x62, 0x6f, 0x6e, 0x64, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70,
+ 0x61, 0x73, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x65, 0x76,
+ 0x65, 0x72, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x66, 0x69, 0x6e, 0x64, 0x65, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x73, 0x6c, 0x61, 0x79, 0x20, 0x6d,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x54, 0x68, 0x65, 0x72,
+ 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x77, 0x68, 0x6f, 0x73, 0x6f, 0x65,
+ 0x76, 0x65, 0x72, 0x20, 0x73, 0x6c, 0x61, 0x79, 0x65, 0x74, 0x68, 0x20,
+ 0x43, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x76, 0x65, 0x6e, 0x67, 0x65, 0x61,
+ 0x6e, 0x63, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65,
+ 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x6f, 0x6e, 0x20, 0x68, 0x69,
+ 0x6d, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x66, 0x6f, 0x6c, 0x64, 0x2e,
+ 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x73, 0x65, 0x74, 0x20, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x2c, 0x20,
+ 0x6c, 0x65, 0x73, 0x74, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x66, 0x69, 0x6e,
+ 0x64, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x73, 0x68, 0x6f,
+ 0x75, 0x6c, 0x64, 0x20, 0x6b, 0x69, 0x6c, 0x6c, 0x20, 0x68, 0x69, 0x6d,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x20,
+ 0x77, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e,
+ 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x77, 0x65, 0x6c,
+ 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x4e, 0x6f, 0x64, 0x2c, 0x20, 0x6f, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x45, 0x64, 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x43, 0x61, 0x69, 0x6e, 0x20, 0x6b, 0x6e, 0x65, 0x77, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x69, 0x76, 0x65,
+ 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20,
+ 0x45, 0x6e, 0x6f, 0x63, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x64, 0x20, 0x61, 0x20,
+ 0x63, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61,
+ 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x69, 0x74,
+ 0x79, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x45, 0x6e, 0x6f, 0x63, 0x68, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x45,
+ 0x6e, 0x6f, 0x63, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x62, 0x6f, 0x72,
+ 0x6e, 0x20, 0x49, 0x72, 0x61, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x49, 0x72, 0x61, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4d,
+ 0x65, 0x68, 0x75, 0x6a, 0x61, 0x65, 0x6c, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x4d, 0x65, 0x68, 0x75, 0x6a, 0x61, 0x65, 0x6c, 0x20, 0x62, 0x65,
+ 0x67, 0x61, 0x74, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x75, 0x73, 0x61, 0x65,
+ 0x6c, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x75,
+ 0x73, 0x61, 0x65, 0x6c, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4c,
+ 0x61, 0x6d, 0x65, 0x63, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x74, 0x77, 0x6f,
+ 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6f, 0x6e, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x41, 0x64, 0x61, 0x68,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x5a, 0x69, 0x6c, 0x6c, 0x61, 0x68, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x64, 0x61, 0x68, 0x20, 0x62, 0x61,
+ 0x72, 0x65, 0x20, 0x4a, 0x61, 0x62, 0x61, 0x6c, 0x3a, 0x20, 0x68, 0x65,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20,
+ 0x61, 0x73, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f,
+ 0x66, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x4a, 0x75, 0x62, 0x61, 0x6c, 0x3a, 0x20, 0x68, 0x65,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x73,
+ 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x72, 0x70, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x5a, 0x69, 0x6c, 0x6c, 0x61, 0x68, 0x2c, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x62, 0x61, 0x72, 0x65,
+ 0x20, 0x54, 0x75, 0x62, 0x61, 0x6c, 0x63, 0x61, 0x69, 0x6e, 0x2c, 0x20,
+ 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x65,
+ 0x72, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x61,
+ 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20,
+ 0x62, 0x72, 0x61, 0x73, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x72,
+ 0x6f, 0x6e, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x69, 0x73, 0x74, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x54, 0x75,
+ 0x62, 0x61, 0x6c, 0x63, 0x61, 0x69, 0x6e, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x4e, 0x61, 0x61, 0x6d, 0x61, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69,
+ 0x76, 0x65, 0x73, 0x2c, 0x20, 0x41, 0x64, 0x61, 0x68, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x5a, 0x69, 0x6c, 0x6c, 0x61, 0x68, 0x2c, 0x20, 0x48, 0x65,
+ 0x61, 0x72, 0x20, 0x6d, 0x79, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x3b,
+ 0x20, 0x79, 0x65, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68, 0x2c, 0x20, 0x68, 0x65, 0x61,
+ 0x72, 0x6b, 0x65, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x79,
+ 0x20, 0x73, 0x70, 0x65, 0x65, 0x63, 0x68, 0x3a, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x73, 0x6c, 0x61, 0x69,
+ 0x6e, 0x20, 0x61, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6d,
+ 0x79, 0x20, 0x77, 0x6f, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x79, 0x6f, 0x75, 0x6e, 0x67, 0x20,
+ 0x6d, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x79, 0x20, 0x68, 0x75,
+ 0x72, 0x74, 0x2e, 0x20, 0x0a, 0x49, 0x66, 0x20, 0x43, 0x61, 0x69, 0x6e,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x76,
+ 0x65, 0x6e, 0x67, 0x65, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x66,
+ 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x74, 0x72, 0x75, 0x6c, 0x79, 0x20, 0x4c,
+ 0x61, 0x6d, 0x65, 0x63, 0x68, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x74,
+ 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x66,
+ 0x6f, 0x6c, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x64,
+ 0x61, 0x6d, 0x20, 0x6b, 0x6e, 0x65, 0x77, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x77, 0x69, 0x66, 0x65, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x62, 0x61, 0x72, 0x65,
+ 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e,
+ 0x61, 0x6d, 0x65, 0x20, 0x53, 0x65, 0x74, 0x68, 0x3a, 0x20, 0x46, 0x6f,
+ 0x72, 0x20, 0x47, 0x6f, 0x64, 0x2c, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x73, 0x68, 0x65, 0x2c, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x61, 0x70,
+ 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x20, 0x61,
+ 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20,
+ 0x69, 0x6e, 0x73, 0x74, 0x65, 0x61, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x41,
+ 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x43, 0x61,
+ 0x69, 0x6e, 0x20, 0x73, 0x6c, 0x65, 0x77, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x6f, 0x20, 0x53, 0x65, 0x74, 0x68, 0x2c, 0x20, 0x74,
+ 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x62, 0x6f, 0x72,
+ 0x6e, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x45, 0x6e, 0x6f, 0x73,
+ 0x3a, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x62, 0x65, 0x67, 0x61, 0x6e,
+ 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x61, 0x6c, 0x6c,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x6f, 0x6b, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x64, 0x61, 0x6d,
+ 0x2e, 0x20, 0x49, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72,
+ 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x6e, 0x65,
+ 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61,
+ 0x64, 0x65, 0x20, 0x68, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x3b, 0x20, 0x0a,
+ 0x4d, 0x61, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x65, 0x6d,
+ 0x61, 0x6c, 0x65, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6e, 0x61, 0x6d, 0x65,
+ 0x20, 0x41, 0x64, 0x61, 0x6d, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x63, 0x72, 0x65,
+ 0x61, 0x74, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41,
+ 0x64, 0x61, 0x6d, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x6e,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74,
+ 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x6f, 0x77, 0x6e, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x6e, 0x65,
+ 0x73, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x53, 0x65, 0x74,
+ 0x68, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x64, 0x61, 0x6d,
+ 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x62, 0x65, 0x67, 0x6f, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x53,
+ 0x65, 0x74, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x65, 0x69, 0x67,
+ 0x68, 0x74, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x79,
+ 0x65, 0x61, 0x72, 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72,
+ 0x73, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x20, 0x68,
+ 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x69, 0x72, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x65, 0x64,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x65, 0x74, 0x68, 0x20,
+ 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x75, 0x6e,
+ 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x76,
+ 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x45, 0x6e, 0x6f, 0x73, 0x3a,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x65, 0x74, 0x68, 0x20, 0x6c,
+ 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68,
+ 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x45, 0x6e, 0x6f, 0x73,
+ 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72,
+ 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73,
+ 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x53,
+ 0x65, 0x74, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6e, 0x69, 0x6e,
+ 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x77, 0x65, 0x6c, 0x76, 0x65, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64,
+ 0x69, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x6e,
+ 0x6f, 0x73, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x6e, 0x69, 0x6e,
+ 0x65, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x43, 0x61, 0x69,
+ 0x6e, 0x61, 0x6e, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x6e,
+ 0x6f, 0x73, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74,
+ 0x65, 0x72, 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20,
+ 0x43, 0x61, 0x69, 0x6e, 0x61, 0x6e, 0x20, 0x65, 0x69, 0x67, 0x68, 0x74,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x66, 0x69, 0x66, 0x74, 0x65, 0x65, 0x6e, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61,
+ 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64,
+ 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x3a, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x6e, 0x6f, 0x73, 0x20,
+ 0x77, 0x65, 0x72, 0x65, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x75,
+ 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69,
+ 0x76, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x65, 0x64, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x69, 0x6e, 0x61, 0x6e, 0x20, 0x6c,
+ 0x69, 0x76, 0x65, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x79,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x67, 0x61, 0x74, 0x20, 0x4d, 0x61, 0x68, 0x61, 0x6c, 0x61, 0x6c,
+ 0x65, 0x65, 0x6c, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61,
+ 0x69, 0x6e, 0x61, 0x6e, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61,
+ 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61,
+ 0x74, 0x20, 0x4d, 0x61, 0x68, 0x61, 0x6c, 0x61, 0x6c, 0x65, 0x65, 0x6c,
+ 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72,
+ 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x79,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73,
+ 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x43,
+ 0x61, 0x69, 0x6e, 0x61, 0x6e, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6e,
+ 0x69, 0x6e, 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x65, 0x6e, 0x20, 0x79, 0x65, 0x61, 0x72,
+ 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69,
+ 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4d, 0x61, 0x68,
+ 0x61, 0x6c, 0x61, 0x6c, 0x65, 0x65, 0x6c, 0x20, 0x6c, 0x69, 0x76, 0x65,
+ 0x64, 0x20, 0x73, 0x69, 0x78, 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x66, 0x69, 0x76, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4a, 0x61,
+ 0x72, 0x65, 0x64, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4d, 0x61,
+ 0x68, 0x61, 0x6c, 0x61, 0x6c, 0x65, 0x65, 0x6c, 0x20, 0x6c, 0x69, 0x76,
+ 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x65, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4a, 0x61, 0x72, 0x65, 0x64, 0x20,
+ 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65,
+ 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73,
+ 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4d,
+ 0x61, 0x68, 0x61, 0x6c, 0x61, 0x6c, 0x65, 0x65, 0x6c, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x75, 0x6e,
+ 0x64, 0x72, 0x65, 0x64, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x74, 0x79, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64,
+ 0x69, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61,
+ 0x72, 0x65, 0x64, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x6e,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x73, 0x69, 0x78,
+ 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x79,
+ 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x45, 0x6e, 0x6f, 0x63, 0x68,
+ 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x72, 0x65, 0x64,
+ 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x45, 0x6e,
+ 0x6f, 0x63, 0x68, 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x75,
+ 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73,
+ 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67,
+ 0x68, 0x74, 0x65, 0x72, 0x73, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x4a, 0x61, 0x72, 0x65, 0x64, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64,
+ 0x72, 0x65, 0x64, 0x20, 0x73, 0x69, 0x78, 0x74, 0x79, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x65, 0x64,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x6e, 0x6f, 0x63, 0x68,
+ 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x73, 0x69, 0x78, 0x74, 0x79,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20, 0x79, 0x65,
+ 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67,
+ 0x61, 0x74, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x75, 0x73, 0x65, 0x6c, 0x61,
+ 0x68, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x6e, 0x6f, 0x63,
+ 0x68, 0x20, 0x77, 0x61, 0x6c, 0x6b, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4d, 0x65, 0x74,
+ 0x68, 0x75, 0x73, 0x65, 0x6c, 0x61, 0x68, 0x20, 0x74, 0x68, 0x72, 0x65,
+ 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x79, 0x65,
+ 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67,
+ 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x3a, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x6e, 0x6f, 0x63,
+ 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x73, 0x69, 0x78,
+ 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20,
+ 0x79, 0x65, 0x61, 0x72, 0x73, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x45, 0x6e, 0x6f, 0x63, 0x68, 0x20, 0x77, 0x61, 0x6c, 0x6b, 0x65, 0x64,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x6f, 0x64, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e, 0x6f,
+ 0x74, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x74,
+ 0x6f, 0x6f, 0x6b, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x75, 0x73, 0x65, 0x6c, 0x61, 0x68,
+ 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x75,
+ 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x79,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x79,
+ 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65,
+ 0x67, 0x61, 0x74, 0x20, 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x75, 0x73, 0x65,
+ 0x6c, 0x61, 0x68, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66,
+ 0x74, 0x65, 0x72, 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74,
+ 0x20, 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68, 0x20, 0x73, 0x65, 0x76, 0x65,
+ 0x6e, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x65, 0x69,
+ 0x67, 0x68, 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x77, 0x6f,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73,
+ 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4d,
+ 0x65, 0x74, 0x68, 0x75, 0x73, 0x65, 0x6c, 0x61, 0x68, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64,
+ 0x72, 0x65, 0x64, 0x20, 0x73, 0x69, 0x78, 0x74, 0x79, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x65,
+ 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4c, 0x61, 0x6d, 0x65,
+ 0x63, 0x68, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20,
+ 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x79,
+ 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65,
+ 0x67, 0x61, 0x74, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x3a, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x4e,
+ 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c,
+ 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x66, 0x6f, 0x72, 0x74,
+ 0x20, 0x75, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x72, 0x6e, 0x69,
+ 0x6e, 0x67, 0x20, 0x6f, 0x75, 0x72, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x69, 0x6c, 0x20, 0x6f, 0x66, 0x20,
+ 0x6f, 0x75, 0x72, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x2c, 0x20, 0x62,
+ 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20,
+ 0x68, 0x61, 0x74, 0x68, 0x20, 0x63, 0x75, 0x72, 0x73, 0x65, 0x64, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68,
+ 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4e, 0x6f,
+ 0x61, 0x68, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64,
+ 0x72, 0x65, 0x64, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x74, 0x79, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74,
+ 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61,
+ 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x3a, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61,
+ 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4c, 0x61, 0x6d, 0x65, 0x63, 0x68,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20,
+ 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65,
+ 0x6e, 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65,
+ 0x6e, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x66, 0x69, 0x76, 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x62, 0x65, 0x67,
+ 0x61, 0x74, 0x20, 0x53, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x48, 0x61, 0x6d,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x70, 0x68, 0x65, 0x74,
+ 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63,
+ 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c,
+ 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x62, 0x65,
+ 0x67, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69,
+ 0x70, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61,
+ 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x0a, 0x54, 0x68, 0x61, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x6d, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x79, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x66, 0x61, 0x69, 0x72, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x74, 0x6f,
+ 0x6f, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x77, 0x69, 0x76, 0x65,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x68, 0x6f, 0x73,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4d,
+ 0x79, 0x20, 0x73, 0x70, 0x69, 0x72, 0x69, 0x74, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x6c, 0x77, 0x61, 0x79,
+ 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x76, 0x65, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20,
+ 0x69, 0x73, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x3a, 0x20, 0x79, 0x65,
+ 0x74, 0x20, 0x68, 0x69, 0x73, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x68,
+ 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x77, 0x65, 0x6e, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2e,
+ 0x20, 0x0a, 0x54, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x67, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x61, 0x66, 0x74,
+ 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x2c, 0x20, 0x77, 0x68, 0x65,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f,
+ 0x66, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x69,
+ 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x6d, 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x79, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64,
+ 0x72, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x62, 0x65,
+ 0x63, 0x61, 0x6d, 0x65, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x79, 0x20,
+ 0x6d, 0x65, 0x6e, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x6d,
+ 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x6e, 0x6f, 0x77, 0x6e,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73,
+ 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x6f,
+ 0x66, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x72,
+ 0x65, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x69, 0x6d, 0x61,
+ 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x65, 0x61, 0x72,
+ 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x65,
+ 0x76, 0x69, 0x6c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61,
+ 0x6c, 0x6c, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74,
+ 0x20, 0x72, 0x65, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20,
+ 0x6d, 0x61, 0x6e, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74,
+ 0x20, 0x67, 0x72, 0x69, 0x65, 0x76, 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d,
+ 0x20, 0x61, 0x74, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x65, 0x61, 0x72,
+ 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49,
+ 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f,
+ 0x79, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x49,
+ 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
+ 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x3b, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6d,
+ 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x61, 0x73,
+ 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x72, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e,
+ 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x6f, 0x77, 0x6c, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x61, 0x69, 0x72, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x74, 0x20,
+ 0x72, 0x65, 0x70, 0x65, 0x6e, 0x74, 0x65, 0x74, 0x68, 0x20, 0x6d, 0x65,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65,
+ 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2e, 0x20,
+ 0x0a, 0x42, 0x75, 0x74, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x66, 0x6f,
+ 0x75, 0x6e, 0x64, 0x20, 0x67, 0x72, 0x61, 0x63, 0x65, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x79, 0x65, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2e, 0x20, 0x0a,
+ 0x54, 0x68, 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x3a, 0x20, 0x4e,
+ 0x6f, 0x61, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x20, 0x6a, 0x75,
+ 0x73, 0x74, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70,
+ 0x65, 0x72, 0x66, 0x65, 0x63, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20,
+ 0x77, 0x61, 0x6c, 0x6b, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x47, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4e, 0x6f,
+ 0x61, 0x68, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x74, 0x68, 0x72,
+ 0x65, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x53, 0x68, 0x65,
+ 0x6d, 0x2c, 0x20, 0x48, 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x4a, 0x61, 0x70, 0x68, 0x65, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x54, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x61, 0x6c, 0x73, 0x6f,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x63, 0x6f, 0x72, 0x72, 0x75, 0x70, 0x74,
+ 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x47, 0x6f, 0x64, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x76, 0x69, 0x6f, 0x6c, 0x65,
+ 0x6e, 0x63, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x65, 0x64, 0x20, 0x75, 0x70, 0x6f,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64,
+ 0x2c, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x63, 0x6f, 0x72,
+ 0x72, 0x75, 0x70, 0x74, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20, 0x68, 0x61, 0x64, 0x20,
+ 0x63, 0x6f, 0x72, 0x72, 0x75, 0x70, 0x74, 0x65, 0x64, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x61, 0x79, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x54,
+ 0x68, 0x65, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20, 0x69, 0x73, 0x20, 0x63,
+ 0x6f, 0x6d, 0x65, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x6d,
+ 0x65, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x20, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x6c,
+ 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x76, 0x69, 0x6f, 0x6c,
+ 0x65, 0x6e, 0x63, 0x65, 0x20, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20,
+ 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69,
+ 0x6c, 0x6c, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x4d, 0x61, 0x6b,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x72,
+ 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x67, 0x6f, 0x70, 0x68, 0x65, 0x72, 0x20,
+ 0x77, 0x6f, 0x6f, 0x64, 0x3b, 0x20, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x6d,
+ 0x61, 0x6b, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61,
+ 0x72, 0x6b, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c,
+ 0x74, 0x20, 0x70, 0x69, 0x74, 0x63, 0x68, 0x20, 0x69, 0x74, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x70,
+ 0x69, 0x74, 0x63, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x61, 0x73, 0x68, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20,
+ 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x69, 0x74, 0x20, 0x6f, 0x66, 0x3a, 0x20,
+ 0x54, 0x68, 0x65, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x63, 0x75, 0x62,
+ 0x69, 0x74, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x72, 0x65,
+ 0x61, 0x64, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x20, 0x66,
+ 0x69, 0x66, 0x74, 0x79, 0x20, 0x63, 0x75, 0x62, 0x69, 0x74, 0x73, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x20, 0x74, 0x68,
+ 0x69, 0x72, 0x74, 0x79, 0x20, 0x63, 0x75, 0x62, 0x69, 0x74, 0x73, 0x2e,
+ 0x20, 0x0a, 0x41, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x6d, 0x61,
+ 0x6b, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72,
+ 0x6b, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20,
+ 0x63, 0x75, 0x62, 0x69, 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x20,
+ 0x69, 0x74, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x6f, 0x6f, 0x72, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x65, 0x74,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69, 0x64, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x3b, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x2c, 0x20, 0x73, 0x65,
+ 0x63, 0x6f, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x69, 0x72, 0x64, 0x20, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x6d,
+ 0x61, 0x6b, 0x65, 0x20, 0x69, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x49, 0x2c,
+ 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x49, 0x2c, 0x20, 0x64, 0x6f, 0x20,
+ 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x66, 0x6c, 0x6f, 0x6f,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72,
+ 0x6f, 0x79, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68,
+ 0x2c, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x20, 0x69, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x72, 0x65, 0x61, 0x74, 0x68, 0x20,
+ 0x6f, 0x66, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x68, 0x65, 0x61, 0x76,
+ 0x65, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x64,
+ 0x69, 0x65, 0x2e, 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x49, 0x20, 0x65, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x20,
+ 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x27, 0x20, 0x77,
+ 0x69, 0x76, 0x65, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67,
+ 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x2c, 0x20, 0x74, 0x77, 0x6f,
+ 0x20, 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x73, 0x6f,
+ 0x72, 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x74, 0x6f,
+ 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x61,
+ 0x6c, 0x69, 0x76, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x3b, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6d, 0x61, 0x6c, 0x65, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65, 0x2e, 0x20, 0x0a,
+ 0x4f, 0x66, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x73, 0x20, 0x61, 0x66, 0x74,
+ 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e,
+ 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x61,
+ 0x74, 0x74, 0x6c, 0x65, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x6f,
+ 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x72, 0x65, 0x65,
+ 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69,
+ 0x6e, 0x64, 0x2c, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x6f, 0x66, 0x20, 0x65,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x73, 0x6f, 0x72, 0x74, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x6b,
+ 0x65, 0x65, 0x70, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x61, 0x6c, 0x69,
+ 0x76, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x61, 0x6b,
+ 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x66, 0x6f, 0x6f, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73,
+ 0x20, 0x65, 0x61, 0x74, 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x67,
+ 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x66, 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x75, 0x73,
+ 0x20, 0x64, 0x69, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x3b, 0x20, 0x61,
+ 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x68,
+ 0x69, 0x6d, 0x2c, 0x20, 0x73, 0x6f, 0x20, 0x64, 0x69, 0x64, 0x20, 0x68,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x43, 0x6f, 0x6d,
+ 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x79, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65,
+ 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72,
+ 0x6b, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x49, 0x20, 0x73, 0x65, 0x65, 0x6e, 0x20,
+ 0x72, 0x69, 0x67, 0x68, 0x74, 0x65, 0x6f, 0x75, 0x73, 0x20, 0x62, 0x65,
+ 0x66, 0x6f, 0x72, 0x65, 0x20, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x69, 0x73, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x2e, 0x20, 0x0a, 0x4f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x63, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x61, 0x73,
+ 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74,
+ 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x65, 0x20, 0x62, 0x79, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x73, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6c, 0x65, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x62, 0x65, 0x61,
+ 0x73, 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x62,
+ 0x79, 0x20, 0x74, 0x77, 0x6f, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x61, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65, 0x2e, 0x20, 0x0a, 0x4f, 0x66, 0x20,
+ 0x66, 0x6f, 0x77, 0x6c, 0x73, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72, 0x20, 0x62, 0x79,
+ 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x61, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65, 0x3b, 0x20, 0x74, 0x6f,
+ 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x61,
+ 0x6c, 0x69, 0x76, 0x65, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e,
+ 0x20, 0x0a, 0x46, 0x6f, 0x72, 0x20, 0x79, 0x65, 0x74, 0x20, 0x73, 0x65,
+ 0x76, 0x65, 0x6e, 0x20, 0x64, 0x61, 0x79, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x63, 0x61, 0x75,
+ 0x73, 0x65, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x61, 0x69,
+ 0x6e, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x79, 0x20, 0x64,
+ 0x61, 0x79, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x74,
+ 0x79, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x73, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69,
+ 0x6e, 0x67, 0x20, 0x73, 0x75, 0x62, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65,
+ 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x49,
+ 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x6f, 0x66, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61,
+ 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4e, 0x6f,
+ 0x61, 0x68, 0x20, 0x64, 0x69, 0x64, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x72,
+ 0x64, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65,
+ 0x64, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x69, 0x78,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x6f, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61,
+ 0x68, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66,
+ 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73,
+ 0x6f, 0x6e, 0x73, 0x27, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x69, 0x6e, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x62,
+ 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a,
+ 0x4f, 0x66, 0x20, 0x63, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x61,
+ 0x73, 0x74, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x62, 0x65, 0x61, 0x73, 0x74, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6c, 0x65, 0x61,
+ 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x6f,
+ 0x77, 0x6c, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x65, 0x74,
+ 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x72, 0x65,
+ 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x77, 0x6f,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x61, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65, 0x2c, 0x20, 0x61, 0x73,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68, 0x61, 0x64, 0x20, 0x63, 0x6f, 0x6d,
+ 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d,
+ 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x20, 0x61, 0x66,
+ 0x74, 0x65, 0x72, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x64, 0x61,
+ 0x79, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x6f, 0x64, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x49, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x69, 0x78, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65,
+ 0x64, 0x74, 0x68, 0x20, 0x79, 0x65, 0x61, 0x72, 0x20, 0x6f, 0x66, 0x20,
+ 0x4e, 0x6f, 0x61, 0x68, 0x27, 0x73, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x2c,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6f,
+ 0x6e, 0x64, 0x20, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x2c, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x74,
+ 0x68, 0x20, 0x64, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x61, 0x6d, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f,
+ 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x64, 0x65, 0x65,
+ 0x70, 0x20, 0x62, 0x72, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x75, 0x70, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6e,
+ 0x64, 0x6f, 0x77, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65, 0x61, 0x76,
+ 0x65, 0x6e, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6f, 0x70, 0x65, 0x6e,
+ 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x72, 0x61, 0x69, 0x6e, 0x20, 0x77, 0x61, 0x73, 0x20, 0x75, 0x70,
+ 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x79, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x69,
+ 0x67, 0x68, 0x74, 0x73, 0x2e, 0x20, 0x0a, 0x49, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x64,
+ 0x61, 0x79, 0x20, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x4e,
+ 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x68, 0x65,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48, 0x61, 0x6d, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x70, 0x68, 0x65, 0x74, 0x68, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4e,
+ 0x6f, 0x61, 0x68, 0x27, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x72, 0x65,
+ 0x65, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x3b, 0x20, 0x0a, 0x54, 0x68,
+ 0x65, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x62, 0x65, 0x61, 0x73, 0x74, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63,
+ 0x72, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e,
+ 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70,
+ 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x66, 0x6f, 0x77,
+ 0x6c, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20,
+ 0x62, 0x69, 0x72, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x73, 0x6f, 0x72, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x69,
+ 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20,
+ 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b,
+ 0x2c, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x77,
+ 0x6f, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c, 0x65,
+ 0x73, 0x68, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x20,
+ 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x72, 0x65, 0x61, 0x74,
+ 0x68, 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x2c, 0x20, 0x77,
+ 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x6d, 0x61, 0x6c, 0x65, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x2c,
+ 0x20, 0x61, 0x73, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68, 0x61, 0x64, 0x20,
+ 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x68, 0x69,
+ 0x6d, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x20, 0x73, 0x68, 0x75, 0x74, 0x20, 0x68, 0x69, 0x6d,
+ 0x20, 0x69, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x6f, 0x64, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x66, 0x6f, 0x72, 0x74, 0x79, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x75,
+ 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74,
+ 0x68, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x72, 0x65, 0x61,
+ 0x73, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x61, 0x72,
+ 0x65, 0x20, 0x75, 0x70, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x6c, 0x69, 0x66, 0x74, 0x20, 0x75, 0x70, 0x20, 0x61, 0x62, 0x6f,
+ 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x70, 0x72, 0x65, 0x76, 0x61, 0x69,
+ 0x6c, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x69, 0x6e, 0x63, 0x72, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20,
+ 0x67, 0x72, 0x65, 0x61, 0x74, 0x6c, 0x79, 0x20, 0x75, 0x70, 0x6f, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x20,
+ 0x77, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72,
+ 0x73, 0x20, 0x70, 0x72, 0x65, 0x76, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20,
+ 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x69, 0x6e, 0x67, 0x6c, 0x79, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x68, 0x69, 0x67, 0x68, 0x20, 0x68, 0x69, 0x6c,
+ 0x6c, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x68, 0x6f, 0x6c, 0x65, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e,
+ 0x2c, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72,
+ 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x46, 0x69, 0x66, 0x74, 0x65, 0x65, 0x6e,
+ 0x20, 0x63, 0x75, 0x62, 0x69, 0x74, 0x73, 0x20, 0x75, 0x70, 0x77, 0x61,
+ 0x72, 0x64, 0x20, 0x64, 0x69, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x70, 0x72, 0x65, 0x76, 0x61, 0x69,
+ 0x6c, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73,
+ 0x68, 0x20, 0x64, 0x69, 0x65, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x62, 0x6f,
+ 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c,
+ 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x62, 0x65,
+ 0x61, 0x73, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x69,
+ 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x65, 0x74, 0x68, 0x20, 0x75,
+ 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74,
+ 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x6d, 0x61, 0x6e, 0x3a, 0x20, 0x0a, 0x41, 0x6c, 0x6c, 0x20, 0x69,
+ 0x6e, 0x20, 0x77, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x6e, 0x6f, 0x73, 0x74,
+ 0x72, 0x69, 0x6c, 0x73, 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x62, 0x72, 0x65, 0x61, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x6c,
+ 0x69, 0x66, 0x65, 0x2c, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x72, 0x79, 0x20, 0x6c, 0x61, 0x6e, 0x64,
+ 0x2c, 0x20, 0x64, 0x69, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e,
+ 0x67, 0x20, 0x73, 0x75, 0x62, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x65,
+ 0x64, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2c, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6d, 0x61,
+ 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c,
+ 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x72, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e,
+ 0x67, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x6f, 0x77, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x64, 0x65,
+ 0x73, 0x74, 0x72, 0x6f, 0x79, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x6f, 0x6e, 0x6c,
+ 0x79, 0x20, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x61,
+ 0x6c, 0x69, 0x76, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72,
+ 0x73, 0x20, 0x70, 0x72, 0x65, 0x76, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65,
+ 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x66, 0x74, 0x79, 0x20,
+ 0x64, 0x61, 0x79, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x72, 0x65, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x65,
+ 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67,
+ 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x74, 0x74,
+ 0x6c, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x61, 0x20,
+ 0x77, 0x69, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73,
+ 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x61, 0x73, 0x73, 0x77,
+ 0x61, 0x67, 0x65, 0x64, 0x3b, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x66,
+ 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x61, 0x6c, 0x73,
+ 0x6f, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x65,
+ 0x70, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69,
+ 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65, 0x61,
+ 0x76, 0x65, 0x6e, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x73, 0x74, 0x6f,
+ 0x70, 0x70, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x72, 0x61, 0x69, 0x6e, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x20, 0x77, 0x61, 0x73, 0x20, 0x72,
+ 0x65, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x3b, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65,
+ 0x72, 0x73, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x20,
+ 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6f, 0x66, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x69,
+ 0x6e, 0x75, 0x61, 0x6c, 0x6c, 0x79, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x75, 0x6e,
+ 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x66,
+ 0x74, 0x79, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x61, 0x62, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x20, 0x72, 0x65, 0x73,
+ 0x74, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x76, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x6d, 0x6f, 0x6e, 0x74, 0x68,
+ 0x2c, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x76,
+ 0x65, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6e, 0x74,
+ 0x68, 0x2c, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x41, 0x72, 0x61, 0x72, 0x61, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73,
+ 0x20, 0x64, 0x65, 0x63, 0x72, 0x65, 0x61, 0x73, 0x65, 0x64, 0x20, 0x63,
+ 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x75,
+ 0x6e, 0x74, 0x69, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x6e,
+ 0x74, 0x68, 0x20, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x3a, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x6d,
+ 0x6f, 0x6e, 0x74, 0x68, 0x2c, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x64, 0x61, 0x79, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x2c,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x6f,
+ 0x70, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f,
+ 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x73, 0x65, 0x65, 0x6e,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61,
+ 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x20, 0x61,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x79, 0x20, 0x64, 0x61, 0x79, 0x73, 0x2c,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x6f,
+ 0x70, 0x65, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69,
+ 0x6e, 0x64, 0x6f, 0x77, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x61, 0x72, 0x6b, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x68, 0x65,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x3a, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20,
+ 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x20, 0x72, 0x61, 0x76, 0x65,
+ 0x6e, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x6e,
+ 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x2c, 0x20, 0x75, 0x6e, 0x74, 0x69,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x64, 0x72, 0x69, 0x65, 0x64, 0x20,
+ 0x75, 0x70, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6f, 0x66, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6c, 0x73, 0x6f, 0x20, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x74,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x20, 0x64, 0x6f, 0x76,
+ 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20,
+ 0x74, 0x6f, 0x20, 0x73, 0x65, 0x65, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x61, 0x62, 0x61, 0x74, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x6f, 0x66, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61,
+ 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x6f, 0x76, 0x65, 0x20, 0x66, 0x6f, 0x75, 0x6e,
+ 0x64, 0x20, 0x6e, 0x6f, 0x20, 0x72, 0x65, 0x73, 0x74, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6c, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x68, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x6f, 0x74, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x72, 0x65, 0x74, 0x75,
+ 0x72, 0x6e, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69,
+ 0x6d, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61,
+ 0x72, 0x6b, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x6f, 0x6c, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x6e,
+ 0x20, 0x68, 0x65, 0x20, 0x70, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74,
+ 0x68, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x68, 0x65, 0x72,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x75, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x68, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x69, 0x6d, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x74, 0x61, 0x79, 0x65, 0x64, 0x20, 0x79, 0x65,
+ 0x74, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x65, 0x76, 0x65,
+ 0x6e, 0x20, 0x64, 0x61, 0x79, 0x73, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x61, 0x67, 0x61, 0x69, 0x6e, 0x20, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e,
+ 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x64, 0x6f, 0x76, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x3b, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x6f, 0x76, 0x65, 0x20, 0x63,
+ 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69,
+ 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65,
+ 0x6e, 0x69, 0x6e, 0x67, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x6c,
+ 0x6f, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x65, 0x72, 0x20, 0x6d, 0x6f,
+ 0x75, 0x74, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x6f,
+ 0x6c, 0x69, 0x76, 0x65, 0x20, 0x6c, 0x65, 0x61, 0x66, 0x20, 0x70, 0x6c,
+ 0x75, 0x63, 0x6b, 0x74, 0x20, 0x6f, 0x66, 0x66, 0x3a, 0x20, 0x73, 0x6f,
+ 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x6b, 0x6e, 0x65, 0x77, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65,
+ 0x72, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x61, 0x62, 0x61, 0x74,
+ 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6f, 0x66, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x74, 0x61, 0x79, 0x65,
+ 0x64, 0x20, 0x79, 0x65, 0x74, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x64, 0x61, 0x79, 0x73, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x6f, 0x76, 0x65, 0x3b,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72,
+ 0x6e, 0x65, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x67, 0x61, 0x69,
+ 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61,
+ 0x6e, 0x79, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f,
+ 0x20, 0x70, 0x61, 0x73, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x69, 0x78, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64,
+ 0x74, 0x68, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x6d, 0x6f, 0x6e, 0x74,
+ 0x68, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74,
+ 0x20, 0x64, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x64,
+ 0x72, 0x69, 0x65, 0x64, 0x20, 0x75, 0x70, 0x20, 0x66, 0x72, 0x6f, 0x6d,
+ 0x20, 0x6f, 0x66, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68,
+ 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x64, 0x72, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e,
+ 0x64, 0x20, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x2c, 0x20, 0x6f, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x77, 0x65, 0x6e, 0x74, 0x69, 0x65, 0x74, 0x68, 0x20,
+ 0x64, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x6f, 0x6e, 0x74, 0x68, 0x2c, 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x64, 0x72, 0x69, 0x65,
+ 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x70, 0x61, 0x6b, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4e,
+ 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c,
+ 0x20, 0x0a, 0x47, 0x6f, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x27, 0x20, 0x77,
+ 0x69, 0x76, 0x65, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x2e, 0x20, 0x0a, 0x42, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66,
+ 0x6f, 0x72, 0x74, 0x68, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76,
+ 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74,
+ 0x68, 0x65, 0x65, 0x2c, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x66, 0x6c, 0x65, 0x73, 0x68, 0x2c, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20,
+ 0x6f, 0x66, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x6f, 0x66, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68,
+ 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x72, 0x65,
+ 0x65, 0x70, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3b, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x6d, 0x61, 0x79, 0x20,
+ 0x62, 0x72, 0x65, 0x65, 0x64, 0x20, 0x61, 0x62, 0x75, 0x6e, 0x64, 0x61,
+ 0x6e, 0x74, 0x6c, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x66, 0x75, 0x6c, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4e, 0x6f,
+ 0x61, 0x68, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74,
+ 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73,
+ 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x27, 0x20, 0x77, 0x69, 0x76,
+ 0x65, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x3a,
+ 0x20, 0x0a, 0x45, 0x76, 0x65, 0x72, 0x79, 0x20, 0x62, 0x65, 0x61, 0x73,
+ 0x74, 0x2c, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x72, 0x65,
+ 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x66,
+ 0x6f, 0x77, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x61,
+ 0x74, 0x73, 0x6f, 0x65, 0x76, 0x65, 0x72, 0x20, 0x63, 0x72, 0x65, 0x65,
+ 0x70, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x66, 0x74,
+ 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e,
+ 0x64, 0x73, 0x2c, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72,
+ 0x74, 0x68, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x64,
+ 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x6f, 0x66,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x6c, 0x65, 0x61, 0x6e,
+ 0x20, 0x62, 0x65, 0x61, 0x73, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x6c, 0x65,
+ 0x61, 0x6e, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x65, 0x64, 0x20, 0x62, 0x75, 0x72,
+ 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x73,
+ 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6c, 0x74, 0x61,
+ 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x6d, 0x65, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x61, 0x20, 0x73, 0x77, 0x65, 0x65, 0x74, 0x20, 0x73, 0x61, 0x76,
+ 0x6f, 0x75, 0x72, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x69,
+ 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x65, 0x61, 0x72, 0x74, 0x2c,
+ 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x61, 0x67, 0x61, 0x69, 0x6e, 0x20, 0x63, 0x75, 0x72, 0x73, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x61,
+ 0x6e, 0x79, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x6d, 0x61, 0x6e, 0x27, 0x73, 0x20, 0x73, 0x61, 0x6b, 0x65, 0x3b, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6d, 0x61, 0x67,
+ 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x6d,
+ 0x61, 0x6e, 0x27, 0x73, 0x20, 0x68, 0x65, 0x61, 0x72, 0x74, 0x20, 0x69,
+ 0x73, 0x20, 0x65, 0x76, 0x69, 0x6c, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x79, 0x6f, 0x75, 0x74, 0x68, 0x3b, 0x20, 0x6e,
+ 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x49, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x20, 0x73, 0x6d, 0x69, 0x74,
+ 0x65, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x65,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x6c,
+ 0x69, 0x76, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x49, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x2e, 0x20, 0x0a,
+ 0x57, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x72, 0x74, 0x68, 0x20, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x65, 0x74,
+ 0x68, 0x2c, 0x20, 0x73, 0x65, 0x65, 0x64, 0x74, 0x69, 0x6d, 0x65, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x61, 0x72, 0x76, 0x65, 0x73, 0x74, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6c, 0x64, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x61, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x75, 0x6d, 0x6d, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64,
+ 0x61, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63,
+ 0x65, 0x61, 0x73, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x4e,
+ 0x6f, 0x61, 0x68, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x73, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x2c, 0x20, 0x42, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x66, 0x75,
+ 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69,
+ 0x70, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x70,
+ 0x6c, 0x65, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x65, 0x61, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x79,
+ 0x6f, 0x75, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x72, 0x65, 0x61, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x75, 0x70, 0x6f,
+ 0x6e, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x62, 0x65, 0x61, 0x73,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72, 0x2c, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x6d, 0x6f, 0x76, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x73, 0x68, 0x65, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x61, 0x3b,
+ 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x68,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x65, 0x64, 0x2e, 0x20,
+ 0x0a, 0x45, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6d, 0x6f, 0x76, 0x69, 0x6e,
+ 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x6c, 0x69, 0x76, 0x65, 0x74, 0x68, 0x20, 0x73, 0x68, 0x61, 0x6c,
+ 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6d, 0x65, 0x61, 0x74, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x79, 0x6f, 0x75, 0x3b, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20,
+ 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x65, 0x65, 0x6e,
+ 0x20, 0x68, 0x65, 0x72, 0x62, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x49,
+ 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x20, 0x0a,
+ 0x42, 0x75, 0x74, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x2c, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6c,
+ 0x6f, 0x6f, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x2c,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x79, 0x65, 0x20, 0x6e, 0x6f,
+ 0x74, 0x20, 0x65, 0x61, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x73, 0x75, 0x72, 0x65, 0x6c, 0x79, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20,
+ 0x62, 0x6c, 0x6f, 0x6f, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x6f, 0x75,
+ 0x72, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x49, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x3b, 0x20,
+ 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x62, 0x65, 0x61,
+ 0x73, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x49, 0x20, 0x72, 0x65,
+ 0x71, 0x75, 0x69, 0x72, 0x65, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x6e,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x61, 0x6e, 0x3b, 0x20, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6d, 0x61, 0x6e, 0x27, 0x73,
+ 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x69, 0x6c,
+ 0x6c, 0x20, 0x49, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x6d, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x57, 0x68, 0x6f, 0x73, 0x6f, 0x20,
+ 0x73, 0x68, 0x65, 0x64, 0x64, 0x65, 0x74, 0x68, 0x20, 0x6d, 0x61, 0x6e,
+ 0x27, 0x73, 0x20, 0x62, 0x6c, 0x6f, 0x6f, 0x64, 0x2c, 0x20, 0x62, 0x79,
+ 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x62, 0x6c, 0x6f, 0x6f, 0x64, 0x20, 0x62, 0x65, 0x20,
+ 0x73, 0x68, 0x65, 0x64, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x68,
+ 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x79, 0x6f, 0x75, 0x2c, 0x20, 0x62, 0x65, 0x20, 0x79, 0x65, 0x20, 0x66,
+ 0x72, 0x75, 0x69, 0x74, 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x3b, 0x20, 0x62,
+ 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61,
+ 0x62, 0x75, 0x6e, 0x64, 0x61, 0x6e, 0x74, 0x6c, 0x79, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x70, 0x61, 0x6b, 0x65,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73,
+ 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d,
+ 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x49, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64,
+ 0x2c, 0x20, 0x49, 0x20, 0x65, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73,
+ 0x68, 0x20, 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e,
+ 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x79, 0x6f, 0x75, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x79, 0x6f, 0x75,
+ 0x72, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x79, 0x6f, 0x75, 0x3b, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69,
+ 0x76, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72,
+ 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x79, 0x6f, 0x75, 0x2c, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x2c, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x62, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x79, 0x6f, 0x75, 0x3b, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x67, 0x6f, 0x20, 0x6f,
+ 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72,
+ 0x6b, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20,
+ 0x62, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x65, 0x73, 0x74, 0x61,
+ 0x62, 0x6c, 0x69, 0x73, 0x68, 0x20, 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x76,
+ 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x79,
+ 0x6f, 0x75, 0x2c, 0x20, 0x6e, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c,
+ 0x65, 0x73, 0x68, 0x20, 0x62, 0x65, 0x20, 0x63, 0x75, 0x74, 0x20, 0x6f,
+ 0x66, 0x66, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20,
+ 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x66, 0x6c, 0x6f, 0x6f, 0x64,
+ 0x3b, 0x20, 0x6e, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61, 0x6e,
+ 0x79, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20,
+ 0x66, 0x6c, 0x6f, 0x6f, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x65, 0x73,
+ 0x74, 0x72, 0x6f, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20,
+ 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x76, 0x65,
+ 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x49,
+ 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65,
+ 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79, 0x6f, 0x75,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c,
+ 0x69, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75,
+ 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x79, 0x6f, 0x75, 0x2c, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x70, 0x65, 0x72, 0x70, 0x65, 0x74, 0x75, 0x61, 0x6c, 0x20, 0x67,
+ 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x20,
+ 0x0a, 0x49, 0x20, 0x64, 0x6f, 0x20, 0x73, 0x65, 0x74, 0x20, 0x6d, 0x79,
+ 0x20, 0x62, 0x6f, 0x77, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69,
+ 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x61, 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x6f,
+ 0x66, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74,
+ 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x6d, 0x65, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74,
+ 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x6f,
+ 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20,
+ 0x49, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x63, 0x6c,
+ 0x6f, 0x75, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x77, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x73, 0x65, 0x65, 0x6e, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x3a,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x72, 0x65, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x6d, 0x79,
+ 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x2c, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x62, 0x65, 0x74, 0x77,
+ 0x65, 0x65, 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79,
+ 0x6f, 0x75, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61,
+ 0x74, 0x75, 0x72, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x66, 0x6c, 0x65, 0x73, 0x68, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20,
+ 0x62, 0x65, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x61, 0x20, 0x66, 0x6c, 0x6f,
+ 0x6f, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f,
+ 0x79, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f,
+ 0x77, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x6c, 0x6f, 0x6f, 0x6b, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x69, 0x74,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x6d, 0x61, 0x79,
+ 0x20, 0x72, 0x65, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x62,
+ 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76,
+ 0x69, 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c, 0x65, 0x73,
+ 0x68, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x75, 0x70,
+ 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4e, 0x6f, 0x61,
+ 0x68, 0x2c, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74,
+ 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x49, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x65, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68,
+ 0x65, 0x64, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x6d,
+ 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x6c,
+ 0x65, 0x73, 0x68, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4e, 0x6f, 0x61,
+ 0x68, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x6e, 0x74,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x53, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48, 0x61,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x70, 0x68, 0x65,
+ 0x74, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48, 0x61, 0x6d, 0x20,
+ 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x2e,
+ 0x20, 0x0a, 0x54, 0x68, 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x20, 0x73, 0x6f,
+ 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x6f, 0x6c,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x6f, 0x76, 0x65, 0x72,
+ 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x62, 0x65, 0x67, 0x61, 0x6e, 0x20,
+ 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x75, 0x73,
+ 0x62, 0x61, 0x6e, 0x64, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x20,
+ 0x61, 0x20, 0x76, 0x69, 0x6e, 0x65, 0x79, 0x61, 0x72, 0x64, 0x3a, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x72, 0x61, 0x6e,
+ 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6e,
+ 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x61, 0x73, 0x20, 0x64,
+ 0x72, 0x75, 0x6e, 0x6b, 0x65, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x75, 0x6e, 0x63, 0x6f, 0x76,
+ 0x65, 0x72, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x48, 0x61, 0x6d, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x61,
+ 0x6e, 0x61, 0x61, 0x6e, 0x2c, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6e, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x65, 0x73, 0x73, 0x20,
+ 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x6c, 0x64, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x62, 0x72, 0x65, 0x74,
+ 0x68, 0x72, 0x65, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x68, 0x65, 0x6d, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x61, 0x70, 0x68, 0x65, 0x74, 0x68, 0x20,
+ 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x61, 0x20, 0x67, 0x61, 0x72, 0x6d, 0x65,
+ 0x6e, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x61, 0x69, 0x64,
+ 0x20, 0x69, 0x74, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x62, 0x6f, 0x74,
+ 0x68, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x73, 0x68, 0x6f, 0x75,
+ 0x6c, 0x64, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77,
+ 0x65, 0x6e, 0x74, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x77, 0x61, 0x72, 0x64,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6b, 0x65, 0x64, 0x6e,
+ 0x65, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72,
+ 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x66, 0x61, 0x63, 0x65, 0x73,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x77, 0x61,
+ 0x72, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x73, 0x61, 0x77, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x69, 0x72, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20,
+ 0x6e, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x65, 0x73, 0x73, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x61, 0x77, 0x6f,
+ 0x6b, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x77, 0x69, 0x6e, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6b, 0x6e,
+ 0x65, 0x77, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x79, 0x6f, 0x75, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x73, 0x6f, 0x6e, 0x20,
+ 0x68, 0x61, 0x64, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x43, 0x75, 0x72,
+ 0x73, 0x65, 0x64, 0x20, 0x62, 0x65, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61,
+ 0x6e, 0x3b, 0x20, 0x61, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x68, 0x65, 0x20, 0x62, 0x65,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72,
+ 0x65, 0x74, 0x68, 0x72, 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x6c,
+ 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x62, 0x65, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x53, 0x68, 0x65, 0x6d, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43,
+ 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x62, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61,
+ 0x6e, 0x74, 0x2e, 0x20, 0x0a, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x65, 0x6e, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x20, 0x4a,
+ 0x61, 0x70, 0x68, 0x65, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x64, 0x77, 0x65,
+ 0x6c, 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65,
+ 0x6e, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x68, 0x65, 0x6d, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x20, 0x6c, 0x69, 0x76, 0x65,
+ 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x6c, 0x6f, 0x6f, 0x64, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x20,
+ 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x66, 0x69, 0x66, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4e, 0x6f,
+ 0x61, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6e, 0x69, 0x6e, 0x65,
+ 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x66, 0x69, 0x66, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x65,
+ 0x64, 0x2e, 0x20, 0x0a, 0x4e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65, 0x73,
+ 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65,
+ 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x4e, 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x53, 0x68, 0x65, 0x6d, 0x2c,
+ 0x20, 0x48, 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x61,
+ 0x70, 0x68, 0x65, 0x74, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c,
+ 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x73, 0x6f,
+ 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4a, 0x61, 0x70, 0x68, 0x65, 0x74,
+ 0x68, 0x3b, 0x20, 0x47, 0x6f, 0x6d, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x4d, 0x61, 0x67, 0x6f, 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x4d, 0x61, 0x64, 0x61, 0x69, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x4a, 0x61, 0x76, 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x54,
+ 0x75, 0x62, 0x61, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4d, 0x65,
+ 0x73, 0x68, 0x65, 0x63, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x54,
+ 0x69, 0x72, 0x61, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x47,
+ 0x6f, 0x6d, 0x65, 0x72, 0x3b, 0x20, 0x41, 0x73, 0x68, 0x6b, 0x65, 0x6e,
+ 0x61, 0x7a, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x52, 0x69, 0x70, 0x68,
+ 0x61, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x54, 0x6f, 0x67,
+ 0x61, 0x72, 0x6d, 0x61, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x4a, 0x61, 0x76, 0x61, 0x6e, 0x3b, 0x20, 0x45, 0x6c, 0x69, 0x73, 0x68,
+ 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x54, 0x61, 0x72, 0x73,
+ 0x68, 0x69, 0x73, 0x68, 0x2c, 0x20, 0x4b, 0x69, 0x74, 0x74, 0x69, 0x6d,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x44, 0x6f, 0x64, 0x61, 0x6e, 0x69,
+ 0x6d, 0x2e, 0x20, 0x0a, 0x42, 0x79, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x73,
+ 0x6c, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47,
+ 0x65, 0x6e, 0x74, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x64, 0x69, 0x76, 0x69,
+ 0x64, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72,
+ 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x3b, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x74, 0x6f, 0x6e, 0x67, 0x75, 0x65, 0x2c, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20,
+ 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x61, 0x6d,
+ 0x3b, 0x20, 0x43, 0x75, 0x73, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x4d, 0x69, 0x7a, 0x72, 0x61, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x50, 0x68, 0x75, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43,
+ 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x43, 0x75, 0x73, 0x68, 0x3b, 0x20, 0x53, 0x65, 0x62, 0x61, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x48, 0x61, 0x76, 0x69, 0x6c, 0x61, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x62, 0x74, 0x61, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x52, 0x61, 0x61, 0x6d, 0x61, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x62, 0x74, 0x65, 0x63, 0x68,
+ 0x61, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x52, 0x61, 0x61, 0x6d,
+ 0x61, 0x68, 0x3b, 0x20, 0x53, 0x68, 0x65, 0x62, 0x61, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x44, 0x65, 0x64, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x43, 0x75, 0x73, 0x68, 0x20, 0x62, 0x65, 0x67, 0x61,
+ 0x74, 0x20, 0x4e, 0x69, 0x6d, 0x72, 0x6f, 0x64, 0x3a, 0x20, 0x68, 0x65,
+ 0x20, 0x62, 0x65, 0x67, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65,
+ 0x20, 0x61, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x79, 0x20, 0x6f, 0x6e,
+ 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x48, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x61, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x79, 0x20, 0x68, 0x75, 0x6e,
+ 0x74, 0x65, 0x72, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x3a, 0x20, 0x77, 0x68, 0x65,
+ 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x45, 0x76, 0x65, 0x6e, 0x20,
+ 0x61, 0x73, 0x20, 0x4e, 0x69, 0x6d, 0x72, 0x6f, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x79, 0x20, 0x68, 0x75, 0x6e,
+ 0x74, 0x65, 0x72, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x6e,
+ 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b,
+ 0x69, 0x6e, 0x67, 0x64, 0x6f, 0x6d, 0x20, 0x77, 0x61, 0x73, 0x20, 0x42,
+ 0x61, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x45, 0x72,
+ 0x65, 0x63, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x63, 0x63,
+ 0x61, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x6c, 0x6e,
+ 0x65, 0x68, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x68, 0x69, 0x6e, 0x61,
+ 0x72, 0x2e, 0x20, 0x0a, 0x4f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x6e,
+ 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x41, 0x73, 0x73, 0x68,
+ 0x75, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x75, 0x69, 0x6c,
+ 0x64, 0x65, 0x64, 0x20, 0x4e, 0x69, 0x6e, 0x65, 0x76, 0x65, 0x68, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x69, 0x74,
+ 0x79, 0x20, 0x52, 0x65, 0x68, 0x6f, 0x62, 0x6f, 0x74, 0x68, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x6c, 0x61, 0x68, 0x2c, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x6e, 0x20, 0x62, 0x65,
+ 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x4e, 0x69, 0x6e, 0x65, 0x76, 0x65,
+ 0x68, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x6c, 0x61, 0x68, 0x3a,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x73,
+ 0x20, 0x61, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x63, 0x69, 0x74,
+ 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4d, 0x69, 0x7a, 0x72,
+ 0x61, 0x69, 0x6d, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4c, 0x75,
+ 0x64, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x6e, 0x61,
+ 0x6d, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x65, 0x68,
+ 0x61, 0x62, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4e, 0x61,
+ 0x70, 0x68, 0x74, 0x75, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x50, 0x61, 0x74, 0x68, 0x72, 0x75, 0x73, 0x69, 0x6d, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x73, 0x6c, 0x75, 0x68, 0x69,
+ 0x6d, 0x2c, 0x20, 0x28, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x77,
+ 0x68, 0x6f, 0x6d, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x50, 0x68, 0x69,
+ 0x6c, 0x69, 0x73, 0x74, 0x69, 0x6d, 0x2c, 0x29, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x43, 0x61, 0x70, 0x68, 0x74, 0x6f, 0x72, 0x69, 0x6d, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x53, 0x69, 0x64, 0x6f, 0x6e, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x62, 0x6f,
+ 0x72, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48, 0x65, 0x74, 0x68,
+ 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4a,
+ 0x65, 0x62, 0x75, 0x73, 0x69, 0x74, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x6d, 0x6f, 0x72, 0x69, 0x74, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x69,
+ 0x72, 0x67, 0x61, 0x73, 0x69, 0x74, 0x65, 0x2c, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x69, 0x76, 0x69, 0x74, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x72,
+ 0x6b, 0x69, 0x74, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x53, 0x69, 0x6e, 0x69, 0x74, 0x65, 0x2c, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x72, 0x76, 0x61, 0x64,
+ 0x69, 0x74, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x5a, 0x65, 0x6d, 0x61, 0x72, 0x69, 0x74, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x61, 0x6d, 0x61, 0x74,
+ 0x68, 0x69, 0x74, 0x65, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x66,
+ 0x74, 0x65, 0x72, 0x77, 0x61, 0x72, 0x64, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x61, 0x6e,
+ 0x61, 0x61, 0x6e, 0x69, 0x74, 0x65, 0x73, 0x20, 0x73, 0x70, 0x72, 0x65,
+ 0x61, 0x64, 0x20, 0x61, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x61,
+ 0x6e, 0x61, 0x61, 0x6e, 0x69, 0x74, 0x65, 0x73, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x53, 0x69, 0x64, 0x6f, 0x6e, 0x2c,
+ 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x63, 0x6f, 0x6d,
+ 0x65, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x47, 0x65, 0x72, 0x61, 0x72,
+ 0x2c, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x47, 0x61, 0x7a, 0x61, 0x3b,
+ 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x67, 0x6f, 0x65,
+ 0x73, 0x74, 0x2c, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x53, 0x6f, 0x64,
+ 0x6f, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x6d, 0x6f,
+ 0x72, 0x72, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x64,
+ 0x6d, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x5a, 0x65, 0x62,
+ 0x6f, 0x69, 0x6d, 0x2c, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x4c, 0x61, 0x73, 0x68, 0x61, 0x2e, 0x20, 0x0a, 0x54,
+ 0x68, 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x61, 0x6d,
+ 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69,
+ 0x72, 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x2c, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20,
+ 0x74, 0x6f, 0x6e, 0x67, 0x75, 0x65, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72,
+ 0x69, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x2e, 0x20, 0x0a, 0x55, 0x6e, 0x74, 0x6f, 0x20, 0x53, 0x68, 0x65,
+ 0x6d, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72,
+ 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x62, 0x65, 0x72, 0x2c, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x6f, 0x66, 0x20, 0x4a, 0x61, 0x70, 0x68, 0x65, 0x74, 0x68, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x6c, 0x64, 0x65, 0x72, 0x2c, 0x20, 0x65, 0x76,
+ 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x77, 0x65,
+ 0x72, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20,
+ 0x62, 0x6f, 0x72, 0x6e, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x63,
+ 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x53,
+ 0x68, 0x65, 0x6d, 0x3b, 0x20, 0x45, 0x6c, 0x61, 0x6d, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x41, 0x73, 0x73, 0x68, 0x75, 0x72, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x41, 0x72, 0x70, 0x68, 0x61, 0x78, 0x61, 0x64, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x75, 0x64, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x41, 0x72, 0x61, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65,
+ 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x72, 0x61, 0x6d, 0x3b, 0x20, 0x55,
+ 0x7a, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48, 0x75, 0x6c, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x47, 0x65, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4d, 0x61, 0x73, 0x68, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x41, 0x72, 0x70, 0x68, 0x61, 0x78, 0x61, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x53, 0x61, 0x6c, 0x61, 0x68, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x6c, 0x61, 0x68, 0x20, 0x62,
+ 0x65, 0x67, 0x61, 0x74, 0x20, 0x45, 0x62, 0x65, 0x72, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x45, 0x62, 0x65,
+ 0x72, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x20,
+ 0x74, 0x77, 0x6f, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x3a, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6f, 0x6e,
+ 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x50, 0x65, 0x6c, 0x65, 0x67, 0x3b,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x64, 0x61, 0x79, 0x73, 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64,
+ 0x65, 0x64, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x6e, 0x61,
+ 0x6d, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x4a, 0x6f, 0x6b, 0x74, 0x61,
+ 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4a, 0x6f, 0x6b, 0x74,
+ 0x61, 0x6e, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x41, 0x6c, 0x6d,
+ 0x6f, 0x64, 0x61, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x68,
+ 0x65, 0x6c, 0x65, 0x70, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48,
+ 0x61, 0x7a, 0x61, 0x72, 0x6d, 0x61, 0x76, 0x65, 0x74, 0x68, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x65, 0x72, 0x61, 0x68, 0x2c, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x48, 0x61, 0x64, 0x6f, 0x72, 0x61, 0x6d, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x55, 0x7a, 0x61, 0x6c, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x44, 0x69, 0x6b, 0x6c, 0x61, 0x68, 0x2c, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x4f, 0x62, 0x61, 0x6c, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x41, 0x62, 0x69, 0x6d, 0x61, 0x65, 0x6c, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x53, 0x68, 0x65, 0x62, 0x61, 0x2c, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x4f, 0x70, 0x68, 0x69, 0x72, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x48, 0x61, 0x76, 0x69, 0x6c, 0x61, 0x68, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x4a, 0x6f, 0x62, 0x61, 0x62, 0x3a, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x4a, 0x6f, 0x6b, 0x74, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x64, 0x77, 0x65, 0x6c,
+ 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x61, 0x73, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x4d, 0x65, 0x73, 0x68, 0x61, 0x2c, 0x20, 0x61, 0x73, 0x20,
+ 0x74, 0x68, 0x6f, 0x75, 0x20, 0x67, 0x6f, 0x65, 0x73, 0x74, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x53, 0x65, 0x70, 0x68, 0x61, 0x72, 0x20, 0x61,
+ 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x73, 0x74, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65,
+ 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x68, 0x65, 0x6d, 0x2c,
+ 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72,
+ 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x61,
+ 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x74,
+ 0x6f, 0x6e, 0x67, 0x75, 0x65, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x69, 0x72, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x2c, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20,
+ 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x20, 0x0a, 0x54, 0x68,
+ 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x4e, 0x6f, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x69, 0x72, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x73,
+ 0x65, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64,
+ 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x72, 0x74, 0x68, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x6f, 0x6c, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67,
+ 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x6f, 0x6e,
+ 0x65, 0x20, 0x73, 0x70, 0x65, 0x65, 0x63, 0x68, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74,
+ 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x65,
+ 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x73, 0x74, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x70,
+ 0x6c, 0x61, 0x69, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x68, 0x69, 0x6e,
+ 0x61, 0x72, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x64, 0x77, 0x65, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x6f, 0x20,
+ 0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x47, 0x6f, 0x20,
+ 0x74, 0x6f, 0x2c, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x75, 0x73, 0x20, 0x6d,
+ 0x61, 0x6b, 0x65, 0x20, 0x62, 0x72, 0x69, 0x63, 0x6b, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x62, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x20, 0x74, 0x68, 0x6f, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x6c, 0x79, 0x2e,
+ 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x62, 0x72, 0x69, 0x63, 0x6b, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x73, 0x74, 0x6f, 0x6e, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x6c, 0x69, 0x6d, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x6f, 0x72, 0x74, 0x65, 0x72,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x47, 0x6f, 0x20, 0x74, 0x6f, 0x2c,
+ 0x20, 0x6c, 0x65, 0x74, 0x20, 0x75, 0x73, 0x20, 0x62, 0x75, 0x69, 0x6c,
+ 0x64, 0x20, 0x75, 0x73, 0x20, 0x61, 0x20, 0x63, 0x69, 0x74, 0x79, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x74, 0x6f, 0x77, 0x65, 0x72, 0x2c,
+ 0x20, 0x77, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x74, 0x6f, 0x70, 0x20, 0x6d,
+ 0x61, 0x79, 0x20, 0x72, 0x65, 0x61, 0x63, 0x68, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x75, 0x73, 0x20, 0x6d, 0x61, 0x6b,
+ 0x65, 0x20, 0x75, 0x73, 0x20, 0x61, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2c,
+ 0x20, 0x6c, 0x65, 0x73, 0x74, 0x20, 0x77, 0x65, 0x20, 0x62, 0x65, 0x20,
+ 0x73, 0x63, 0x61, 0x74, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x61, 0x62,
+ 0x72, 0x6f, 0x61, 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x68, 0x6f, 0x6c, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74,
+ 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x64, 0x6f,
+ 0x77, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x65, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x63, 0x69, 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x6f, 0x77, 0x65, 0x72, 0x2c, 0x20, 0x77, 0x68,
+ 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c,
+ 0x64, 0x72, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x65, 0x6e, 0x20,
+ 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x20,
+ 0x69, 0x73, 0x20, 0x6f, 0x6e, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61,
+ 0x67, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x20,
+ 0x74, 0x6f, 0x20, 0x64, 0x6f, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e,
+ 0x6f, 0x77, 0x20, 0x6e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72,
+ 0x61, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x69, 0x6d, 0x61,
+ 0x67, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x6f, 0x2e,
+ 0x20, 0x0a, 0x47, 0x6f, 0x20, 0x74, 0x6f, 0x2c, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x75, 0x73, 0x20, 0x67, 0x6f, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x63,
+ 0x6f, 0x6e, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x69,
+ 0x72, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x2c, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x6d, 0x61,
+ 0x79, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x73,
+ 0x74, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x61, 0x6e, 0x6f,
+ 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20, 0x73, 0x70, 0x65, 0x65, 0x63,
+ 0x68, 0x2e, 0x20, 0x0a, 0x53, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x20, 0x73, 0x63, 0x61, 0x74, 0x74, 0x65, 0x72, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x61, 0x62, 0x72, 0x6f, 0x61,
+ 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x63,
+ 0x65, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20,
+ 0x6f, 0x66, 0x66, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x69, 0x74, 0x79, 0x2e, 0x20, 0x0a,
+ 0x54, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x69, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x42,
+ 0x61, 0x62, 0x65, 0x6c, 0x3b, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x64,
+ 0x69, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x63, 0x6f, 0x6e,
+ 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61,
+ 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68,
+ 0x65, 0x6e, 0x63, 0x65, 0x20, 0x64, 0x69, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x63, 0x61, 0x74, 0x74, 0x65,
+ 0x72, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x61, 0x62, 0x72, 0x6f, 0x61,
+ 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x54,
+ 0x68, 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x53, 0x68, 0x65, 0x6d, 0x3a, 0x20, 0x53, 0x68,
+ 0x65, 0x6d, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x75,
+ 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20,
+ 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67,
+ 0x61, 0x74, 0x20, 0x41, 0x72, 0x70, 0x68, 0x61, 0x78, 0x61, 0x64, 0x20,
+ 0x74, 0x77, 0x6f, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x61, 0x66,
+ 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x6f,
+ 0x64, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x68, 0x65, 0x6d,
+ 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x41, 0x72,
+ 0x70, 0x68, 0x61, 0x78, 0x61, 0x64, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20,
+ 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x79, 0x65, 0x61, 0x72,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74,
+ 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61,
+ 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x41, 0x72, 0x70, 0x68, 0x61, 0x78, 0x61, 0x64, 0x20, 0x6c,
+ 0x69, 0x76, 0x65, 0x64, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61,
+ 0x74, 0x20, 0x53, 0x61, 0x6c, 0x61, 0x68, 0x3a, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x41, 0x72, 0x70, 0x68, 0x61, 0x78, 0x61, 0x64, 0x20, 0x6c,
+ 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68,
+ 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x53, 0x61, 0x6c, 0x61,
+ 0x68, 0x20, 0x66, 0x6f, 0x75, 0x72, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72,
+ 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x6c, 0x61, 0x68,
+ 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x74, 0x68, 0x69, 0x72, 0x74,
+ 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x45, 0x62, 0x65, 0x72, 0x3a,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x6c, 0x61, 0x68, 0x20,
+ 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x45, 0x62, 0x65,
+ 0x72, 0x20, 0x66, 0x6f, 0x75, 0x72, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72,
+ 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x45, 0x62, 0x65, 0x72, 0x20,
+ 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x75, 0x72, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79, 0x20, 0x79, 0x65,
+ 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67,
+ 0x61, 0x74, 0x20, 0x50, 0x65, 0x6c, 0x65, 0x67, 0x3a, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x45, 0x62, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x76, 0x65,
+ 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x65, 0x20, 0x62,
+ 0x65, 0x67, 0x61, 0x74, 0x20, 0x50, 0x65, 0x6c, 0x65, 0x67, 0x20, 0x66,
+ 0x6f, 0x75, 0x72, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79, 0x20, 0x79,
+ 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65,
+ 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x50, 0x65, 0x6c, 0x65, 0x67, 0x20, 0x6c,
+ 0x69, 0x76, 0x65, 0x64, 0x20, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79, 0x20,
+ 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x67, 0x61, 0x74, 0x20, 0x52, 0x65, 0x75, 0x3a, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x50, 0x65, 0x6c, 0x65, 0x67, 0x20, 0x6c, 0x69, 0x76,
+ 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x65, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x52, 0x65, 0x75, 0x20, 0x74, 0x77,
+ 0x6f, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20,
+ 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75,
+ 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x52, 0x65, 0x75, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x74,
+ 0x77, 0x6f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x72, 0x74,
+ 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x53, 0x65, 0x72, 0x75, 0x67,
+ 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x52, 0x65, 0x75, 0x20, 0x6c,
+ 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68,
+ 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x53, 0x65, 0x72, 0x75,
+ 0x67, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65,
+ 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x20,
+ 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x65, 0x72, 0x75, 0x67, 0x20,
+ 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4e, 0x61, 0x68, 0x6f, 0x72, 0x3a,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x65, 0x72, 0x75, 0x67, 0x20,
+ 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4e, 0x61, 0x68,
+ 0x6f, 0x72, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72,
+ 0x65, 0x64, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65,
+ 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4e, 0x61, 0x68,
+ 0x6f, 0x72, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x6e, 0x69, 0x6e,
+ 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x77, 0x65, 0x6e, 0x74, 0x79,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x54, 0x65, 0x72, 0x61, 0x68, 0x3a,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4e, 0x61, 0x68, 0x6f, 0x72, 0x20,
+ 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x54, 0x65, 0x72,
+ 0x61, 0x68, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65,
+ 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x74, 0x65,
+ 0x65, 0x6e, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x73, 0x6f, 0x6e, 0x73,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65,
+ 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x54, 0x65, 0x72,
+ 0x61, 0x68, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x64, 0x20, 0x73, 0x65, 0x76,
+ 0x65, 0x6e, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x6d, 0x2c, 0x20, 0x4e, 0x61, 0x68, 0x6f, 0x72, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x48, 0x61, 0x72, 0x61, 0x6e, 0x2e, 0x20, 0x0a,
+ 0x4e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x61, 0x72,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x54, 0x65, 0x72,
+ 0x61, 0x68, 0x3a, 0x20, 0x54, 0x65, 0x72, 0x61, 0x68, 0x20, 0x62, 0x65,
+ 0x67, 0x61, 0x74, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x2c, 0x20, 0x4e,
+ 0x61, 0x68, 0x6f, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48, 0x61,
+ 0x72, 0x61, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48, 0x61, 0x72,
+ 0x61, 0x6e, 0x20, 0x62, 0x65, 0x67, 0x61, 0x74, 0x20, 0x4c, 0x6f, 0x74,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x48, 0x61, 0x72, 0x61, 0x6e,
+ 0x20, 0x64, 0x69, 0x65, 0x64, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x54, 0x65, 0x72, 0x61, 0x68, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x69,
+ 0x6e, 0x20, 0x55, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x43, 0x68, 0x61, 0x6c, 0x64, 0x65, 0x65, 0x73, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x4e, 0x61, 0x68, 0x6f, 0x72, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x3a, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x41, 0x62, 0x72, 0x61, 0x6d, 0x27, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x4e, 0x61, 0x68, 0x6f, 0x72, 0x27, 0x73, 0x20,
+ 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x4d, 0x69, 0x6c, 0x63, 0x61, 0x68,
+ 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74,
+ 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x61, 0x72, 0x61, 0x6e, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x6f, 0x66, 0x20, 0x4d, 0x69, 0x6c, 0x63, 0x61, 0x68, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x20, 0x6f, 0x66, 0x20, 0x49, 0x73, 0x63, 0x61, 0x68, 0x2e, 0x20,
+ 0x0a, 0x42, 0x75, 0x74, 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x62, 0x61, 0x72, 0x72, 0x65, 0x6e, 0x3b, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6e, 0x6f, 0x20, 0x63, 0x68,
+ 0x69, 0x6c, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x54, 0x65,
+ 0x72, 0x61, 0x68, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x6d, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x61, 0x72, 0x61, 0x6e,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x27, 0x73, 0x20, 0x73,
+ 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x72, 0x61,
+ 0x69, 0x20, 0x68, 0x69, 0x73, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74,
+ 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x61, 0x77, 0x2c, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d,
+ 0x27, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x66,
+ 0x6f, 0x72, 0x74, 0x68, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x6d, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x55, 0x72, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x68, 0x61, 0x6c, 0x64, 0x65,
+ 0x65, 0x73, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x6f, 0x20, 0x69, 0x6e,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x66, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x3b, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x61, 0x6d, 0x65,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x48, 0x61, 0x72, 0x61, 0x6e, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x54,
+ 0x65, 0x72, 0x61, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x77,
+ 0x6f, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x54, 0x65, 0x72, 0x61, 0x68, 0x20,
+ 0x64, 0x69, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x48, 0x61, 0x72, 0x61,
+ 0x6e, 0x2e, 0x20, 0x0a, 0x4e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x68, 0x61, 0x64, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d,
+ 0x2c, 0x20, 0x47, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x6f,
+ 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x63, 0x6f,
+ 0x75, 0x6e, 0x74, 0x72, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6b, 0x69, 0x6e, 0x64,
+ 0x72, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x74, 0x68, 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72,
+ 0x27, 0x73, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2c, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x61, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x73, 0x68,
+ 0x65, 0x77, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3a, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6d, 0x61, 0x6b,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x61, 0x20,
+ 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x74, 0x68,
+ 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x62, 0x6c,
+ 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x6c, 0x65, 0x73,
+ 0x73, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x62, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x63, 0x75, 0x72, 0x73, 0x65, 0x20, 0x68, 0x69,
+ 0x6d, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x75, 0x72, 0x73, 0x65,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6c,
+ 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x20, 0x62, 0x65, 0x20, 0x62, 0x6c, 0x65, 0x73,
+ 0x73, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x53, 0x6f, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x6d, 0x20, 0x64, 0x65, 0x70, 0x61, 0x72, 0x74, 0x65, 0x64, 0x2c,
+ 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x73, 0x70, 0x6f, 0x6b, 0x65, 0x6e, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73,
+ 0x65, 0x76, 0x65, 0x6e, 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66,
+ 0x69, 0x76, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x6f, 0x6c,
+ 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x68, 0x65, 0x20, 0x64, 0x65,
+ 0x70, 0x61, 0x72, 0x74, 0x65, 0x64, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x48, 0x61, 0x72, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x74, 0x6f, 0x6f, 0x6b,
+ 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77,
+ 0x69, 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x6f, 0x74,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x27, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x73, 0x75,
+ 0x62, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x68, 0x61, 0x64, 0x20, 0x67, 0x61,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x75, 0x6c, 0x73, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x68, 0x61, 0x64, 0x20,
+ 0x67, 0x6f, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x48, 0x61,
+ 0x72, 0x61, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x79, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68,
+ 0x20, 0x74, 0x6f, 0x20, 0x67, 0x6f, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x70, 0x61,
+ 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x72, 0x6f, 0x75, 0x67, 0x68,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x53, 0x69, 0x63, 0x68, 0x65, 0x6d, 0x2c, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61,
+ 0x69, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x4d, 0x6f, 0x72, 0x65, 0x68, 0x2e,
+ 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x61, 0x6e,
+ 0x61, 0x61, 0x6e, 0x69, 0x74, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x74,
+ 0x68, 0x65, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c,
+ 0x61, 0x6e, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61,
+ 0x72, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x55, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73,
+ 0x65, 0x65, 0x64, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x49, 0x20, 0x67,
+ 0x69, 0x76, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65,
+ 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2c, 0x20,
+ 0x77, 0x68, 0x6f, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x65, 0x64,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76,
+ 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x6e,
+ 0x63, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x6d, 0x6f,
+ 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x42, 0x65,
+ 0x74, 0x68, 0x65, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x69,
+ 0x74, 0x63, 0x68, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x74, 0x65,
+ 0x6e, 0x74, 0x2c, 0x20, 0x68, 0x61, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x42,
+ 0x65, 0x74, 0x68, 0x65, 0x6c, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x65, 0x73, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48,
+ 0x61, 0x69, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x73, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72,
+ 0x65, 0x20, 0x68, 0x65, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x64,
+ 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61,
+ 0x6d, 0x20, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x65, 0x64, 0x2c,
+ 0x20, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x6e, 0x20, 0x73, 0x74,
+ 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x6f, 0x77, 0x61, 0x72, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x6f, 0x75, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x61, 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6e, 0x65, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x77, 0x65, 0x6e,
+ 0x74, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20,
+ 0x45, 0x67, 0x79, 0x70, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x6f, 0x6a,
+ 0x6f, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x3b, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x6d, 0x69,
+ 0x6e, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x72, 0x69, 0x65, 0x76,
+ 0x6f, 0x75, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c,
+ 0x61, 0x6e, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74,
+ 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73,
+ 0x73, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x6e, 0x65, 0x61, 0x72,
+ 0x20, 0x74, 0x6f, 0x20, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x69, 0x6e,
+ 0x74, 0x6f, 0x20, 0x45, 0x67, 0x79, 0x70, 0x74, 0x2c, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f,
+ 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x77, 0x2c, 0x20, 0x49, 0x20, 0x6b, 0x6e,
+ 0x6f, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x61, 0x72, 0x74, 0x20, 0x61, 0x20, 0x66, 0x61, 0x69, 0x72, 0x20,
+ 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x6f,
+ 0x6b, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x3a, 0x20, 0x0a, 0x54, 0x68, 0x65,
+ 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x69, 0x74, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20,
+ 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x45, 0x67, 0x79, 0x70, 0x74, 0x69, 0x61, 0x6e, 0x73,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x73, 0x65, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x73, 0x61, 0x79,
+ 0x2c, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6b, 0x69,
+ 0x6c, 0x6c, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x73, 0x61, 0x76,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x61, 0x6c, 0x69, 0x76, 0x65,
+ 0x2e, 0x20, 0x0a, 0x53, 0x61, 0x79, 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72,
+ 0x61, 0x79, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x61, 0x72, 0x74, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x69, 0x73,
+ 0x74, 0x65, 0x72, 0x3a, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74,
+ 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x77, 0x65, 0x6c, 0x6c,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x61, 0x6b, 0x65, 0x3b, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x6f, 0x75, 0x6c, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x20, 0x62, 0x65,
+ 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63,
+ 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20,
+ 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x77, 0x61, 0x73, 0x20, 0x63, 0x6f,
+ 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x45, 0x67, 0x79, 0x70,
+ 0x74, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x45, 0x67, 0x79, 0x70, 0x74,
+ 0x69, 0x61, 0x6e, 0x73, 0x20, 0x62, 0x65, 0x68, 0x65, 0x6c, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x73, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x76,
+ 0x65, 0x72, 0x79, 0x20, 0x66, 0x61, 0x69, 0x72, 0x2e, 0x20, 0x0a, 0x54,
+ 0x68, 0x65, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x73, 0x20, 0x61,
+ 0x6c, 0x73, 0x6f, 0x20, 0x6f, 0x66, 0x20, 0x50, 0x68, 0x61, 0x72, 0x61,
+ 0x6f, 0x68, 0x20, 0x73, 0x61, 0x77, 0x20, 0x68, 0x65, 0x72, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x65,
+ 0x64, 0x20, 0x68, 0x65, 0x72, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65,
+ 0x20, 0x50, 0x68, 0x61, 0x72, 0x61, 0x6f, 0x68, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x69, 0x6e,
+ 0x74, 0x6f, 0x20, 0x50, 0x68, 0x61, 0x72, 0x61, 0x6f, 0x68, 0x27, 0x73,
+ 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x65, 0x6e, 0x74, 0x72, 0x65, 0x61, 0x74, 0x65,
+ 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x77, 0x65, 0x6c, 0x6c,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68, 0x65, 0x72, 0x20, 0x73, 0x61, 0x6b,
+ 0x65, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x73, 0x68, 0x65, 0x65, 0x70, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x6f, 0x78, 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x61, 0x73, 0x73, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x6d, 0x65, 0x6e, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x64, 0x73, 0x65,
+ 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x68, 0x65, 0x20, 0x61, 0x73, 0x73, 0x65, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x6c, 0x73, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x70, 0x6c, 0x61, 0x67, 0x75, 0x65, 0x64, 0x20, 0x50, 0x68, 0x61,
+ 0x72, 0x61, 0x6f, 0x68, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x67, 0x75, 0x65,
+ 0x73, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d,
+ 0x27, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x50, 0x68, 0x61, 0x72, 0x61, 0x6f, 0x68, 0x20, 0x63, 0x61,
+ 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x57, 0x68, 0x61,
+ 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74,
+ 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d,
+ 0x65, 0x3f, 0x20, 0x77, 0x68, 0x79, 0x20, 0x64, 0x69, 0x64, 0x73, 0x74,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x65,
+ 0x6c, 0x6c, 0x20, 0x6d, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x79, 0x20, 0x77,
+ 0x69, 0x66, 0x65, 0x3f, 0x20, 0x0a, 0x57, 0x68, 0x79, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x2c, 0x20, 0x53,
+ 0x68, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x69, 0x73,
+ 0x74, 0x65, 0x72, 0x3f, 0x20, 0x73, 0x6f, 0x20, 0x49, 0x20, 0x6d, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x61, 0x6b,
+ 0x65, 0x6e, 0x20, 0x68, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x65,
+ 0x20, 0x74, 0x6f, 0x20, 0x77, 0x69, 0x66, 0x65, 0x3a, 0x20, 0x6e, 0x6f,
+ 0x77, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20,
+ 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x20, 0x74, 0x68, 0x79, 0x20, 0x77,
+ 0x69, 0x66, 0x65, 0x2c, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x68, 0x65,
+ 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x6f, 0x20, 0x74, 0x68,
+ 0x79, 0x20, 0x77, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x50, 0x68, 0x61, 0x72, 0x61, 0x6f, 0x68, 0x20, 0x63, 0x6f, 0x6d, 0x6d,
+ 0x61, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x65,
+ 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x72, 0x6e, 0x69, 0x6e, 0x67,
+ 0x20, 0x68, 0x69, 0x6d, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x68, 0x69, 0x6d, 0x20,
+ 0x61, 0x77, 0x61, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x20,
+ 0x68, 0x61, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x6d, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x70, 0x20,
+ 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x67, 0x79, 0x70, 0x74,
+ 0x2c, 0x20, 0x68, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x20,
+ 0x68, 0x61, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x6f, 0x74,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x69,
+ 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x75, 0x74,
+ 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61,
+ 0x6d, 0x20, 0x77, 0x61, 0x73, 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x72,
+ 0x69, 0x63, 0x68, 0x20, 0x69, 0x6e, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c,
+ 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x69, 0x6c, 0x76, 0x65, 0x72,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x67, 0x6f, 0x6c,
+ 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x77,
+ 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6a,
+ 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x65,
+ 0x76, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x42, 0x65, 0x74, 0x68, 0x65,
+ 0x6c, 0x2c, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x68, 0x61, 0x64,
+ 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x2c, 0x20,
+ 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x42, 0x65, 0x74, 0x68,
+ 0x65, 0x6c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x48, 0x61, 0x69, 0x3b, 0x20,
+ 0x0a, 0x55, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c,
+ 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61,
+ 0x6c, 0x74, 0x61, 0x72, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20,
+ 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x2c, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x2c, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x66, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x72, 0x64, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74,
+ 0x6f, 0x20, 0x62, 0x65, 0x61, 0x72, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x6d,
+ 0x69, 0x67, 0x68, 0x74, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x74,
+ 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x3a, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x73, 0x75, 0x62, 0x73, 0x74,
+ 0x61, 0x6e, 0x63, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x72, 0x65,
+ 0x61, 0x74, 0x2c, 0x20, 0x73, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x74, 0x6f, 0x67,
+ 0x65, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x61, 0x20,
+ 0x73, 0x74, 0x72, 0x69, 0x66, 0x65, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65,
+ 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x72, 0x64, 0x6d,
+ 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x27,
+ 0x73, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x72, 0x64, 0x6d, 0x65, 0x6e,
+ 0x20, 0x6f, 0x66, 0x20, 0x4c, 0x6f, 0x74, 0x27, 0x73, 0x20, 0x63, 0x61,
+ 0x74, 0x74, 0x6c, 0x65, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x69, 0x74, 0x65, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x50, 0x65, 0x72, 0x69,
+ 0x7a, 0x7a, 0x69, 0x74, 0x65, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4c, 0x6f, 0x74, 0x2c, 0x20, 0x4c, 0x65,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x6e,
+ 0x6f, 0x20, 0x73, 0x74, 0x72, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x49, 0x20,
+ 0x70, 0x72, 0x61, 0x79, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x62,
+ 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x6d, 0x79, 0x20, 0x68,
+ 0x65, 0x72, 0x64, 0x6d, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x68, 0x65, 0x72, 0x64, 0x6d, 0x65, 0x6e, 0x3b, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x77, 0x65, 0x20, 0x62, 0x65, 0x20, 0x62, 0x72,
+ 0x65, 0x74, 0x68, 0x72, 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x49, 0x73, 0x20,
+ 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x6f, 0x6c,
+ 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3f, 0x20, 0x73, 0x65, 0x70, 0x61,
+ 0x72, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68, 0x79, 0x73, 0x65, 0x6c, 0x66,
+ 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72, 0x61, 0x79, 0x20, 0x74, 0x68, 0x65,
+ 0x65, 0x2c, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x6d, 0x65, 0x3a, 0x20,
+ 0x69, 0x66, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x77, 0x69, 0x6c, 0x74,
+ 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x65,
+ 0x66, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65,
+ 0x6e, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x67, 0x6f, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74,
+ 0x3b, 0x20, 0x6f, 0x72, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x64, 0x65, 0x70, 0x61, 0x72, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x68, 0x61, 0x6e,
+ 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x49, 0x20, 0x77, 0x69,
+ 0x6c, 0x6c, 0x20, 0x67, 0x6f, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6c, 0x65, 0x66, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x4c, 0x6f, 0x74, 0x20, 0x6c, 0x69, 0x66, 0x74, 0x65, 0x64, 0x20, 0x75,
+ 0x70, 0x20, 0x68, 0x69, 0x73, 0x20, 0x65, 0x79, 0x65, 0x73, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x68, 0x65, 0x6c, 0x64, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x69, 0x6e,
+ 0x20, 0x6f, 0x66, 0x20, 0x4a, 0x6f, 0x72, 0x64, 0x61, 0x6e, 0x2c, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x65, 0x64,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65,
+ 0x2c, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f,
+ 0x79, 0x65, 0x64, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x47, 0x6f, 0x6d, 0x6f, 0x72, 0x72, 0x61, 0x68, 0x2c, 0x20,
+ 0x65, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2c, 0x20, 0x6c, 0x69, 0x6b, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x45, 0x67, 0x79, 0x70, 0x74, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x73, 0x74, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x5a, 0x6f, 0x61, 0x72, 0x2e, 0x20, 0x0a, 0x54,
+ 0x68, 0x65, 0x6e, 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x63, 0x68, 0x6f, 0x73,
+ 0x65, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x4a,
+ 0x6f, 0x72, 0x64, 0x61, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c,
+ 0x6f, 0x74, 0x20, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x65, 0x64,
+ 0x20, 0x65, 0x61, 0x73, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x73, 0x65, 0x6c, 0x76, 0x65, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x2e,
+ 0x20, 0x0a, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x64, 0x77, 0x65, 0x6c,
+ 0x6c, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61,
+ 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x64,
+ 0x77, 0x65, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x63, 0x69, 0x74, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x70, 0x69, 0x74, 0x63, 0x68, 0x65, 0x64, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x77, 0x61,
+ 0x72, 0x64, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x2e, 0x20, 0x0a, 0x42,
+ 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x6f,
+ 0x66, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x77, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x20, 0x62, 0x65, 0x66, 0x6f,
+ 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20,
+ 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x69, 0x6e, 0x67, 0x6c, 0x79, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x64,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x4c,
+ 0x69, 0x66, 0x74, 0x20, 0x75, 0x70, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x74,
+ 0x68, 0x69, 0x6e, 0x65, 0x20, 0x65, 0x79, 0x65, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x20, 0x66, 0x72, 0x6f, 0x6d,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x77,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x61, 0x72,
+ 0x74, 0x20, 0x6e, 0x6f, 0x72, 0x74, 0x68, 0x77, 0x61, 0x72, 0x64, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x6f, 0x75, 0x74, 0x68, 0x77, 0x61,
+ 0x72, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x61, 0x73, 0x74,
+ 0x77, 0x61, 0x72, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65,
+ 0x73, 0x74, 0x77, 0x61, 0x72, 0x64, 0x3a, 0x20, 0x0a, 0x46, 0x6f, 0x72,
+ 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x73, 0x65, 0x65, 0x73, 0x74, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x49, 0x20, 0x67,
+ 0x69, 0x76, 0x65, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x65, 0x76, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6d, 0x61,
+ 0x6b, 0x65, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20,
+ 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x75, 0x73, 0x74, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x3a, 0x20, 0x73, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x66,
+ 0x20, 0x61, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x6e,
+ 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x75,
+ 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x72, 0x74, 0x68, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64,
+ 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x6e, 0x75, 0x6d,
+ 0x62, 0x65, 0x72, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x72, 0x69, 0x73,
+ 0x65, 0x2c, 0x20, 0x77, 0x61, 0x6c, 0x6b, 0x20, 0x74, 0x68, 0x72, 0x6f,
+ 0x75, 0x67, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x65, 0x6e, 0x67,
+ 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x72, 0x65, 0x61,
+ 0x64, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x3b, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x67, 0x69,
+ 0x76, 0x65, 0x20, 0x69, 0x74, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x65, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x6e, 0x20, 0x41,
+ 0x62, 0x72, 0x61, 0x6d, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x64, 0x77, 0x65, 0x6c, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x4d, 0x61,
+ 0x6d, 0x72, 0x65, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x69,
+ 0x73, 0x20, 0x69, 0x6e, 0x20, 0x48, 0x65, 0x62, 0x72, 0x6f, 0x6e, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x74, 0x61,
+ 0x72, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74,
+ 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73,
+ 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x6d, 0x72, 0x61, 0x70, 0x68, 0x65,
+ 0x6c, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x68,
+ 0x69, 0x6e, 0x61, 0x72, 0x2c, 0x20, 0x41, 0x72, 0x69, 0x6f, 0x63, 0x68,
+ 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x6c, 0x6c,
+ 0x61, 0x73, 0x61, 0x72, 0x2c, 0x20, 0x43, 0x68, 0x65, 0x64, 0x6f, 0x72,
+ 0x6c, 0x61, 0x6f, 0x6d, 0x65, 0x72, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20,
+ 0x6f, 0x66, 0x20, 0x45, 0x6c, 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x54, 0x69, 0x64, 0x61, 0x6c, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20,
+ 0x6f, 0x66, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3b, 0x20,
+ 0x0a, 0x54, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20,
+ 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x61, 0x72, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x42, 0x65, 0x72, 0x61, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20,
+ 0x6f, 0x66, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x42, 0x69, 0x72, 0x73, 0x68,
+ 0x61, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x47, 0x6f,
+ 0x6d, 0x6f, 0x72, 0x72, 0x61, 0x68, 0x2c, 0x20, 0x53, 0x68, 0x69, 0x6e,
+ 0x61, 0x62, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x41,
+ 0x64, 0x6d, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x68,
+ 0x65, 0x6d, 0x65, 0x62, 0x65, 0x72, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20,
+ 0x6f, 0x66, 0x20, 0x5a, 0x65, 0x62, 0x6f, 0x69, 0x69, 0x6d, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 0x69, 0x6e, 0x67,
+ 0x20, 0x6f, 0x66, 0x20, 0x42, 0x65, 0x6c, 0x61, 0x2c, 0x20, 0x77, 0x68,
+ 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x5a, 0x6f, 0x61, 0x72, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20,
+ 0x77, 0x65, 0x72, 0x65, 0x20, 0x6a, 0x6f, 0x69, 0x6e, 0x65, 0x64, 0x20,
+ 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x53, 0x69, 0x64, 0x64, 0x69, 0x6d, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63,
+ 0x68, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6c,
+ 0x74, 0x20, 0x73, 0x65, 0x61, 0x2e, 0x20, 0x0a, 0x54, 0x77, 0x65, 0x6c,
+ 0x76, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x74, 0x68, 0x65,
+ 0x79, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x20, 0x43, 0x68, 0x65,
+ 0x64, 0x6f, 0x72, 0x6c, 0x61, 0x6f, 0x6d, 0x65, 0x72, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x68,
+ 0x69, 0x72, 0x74, 0x65, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x72, 0x65, 0x62, 0x65, 0x6c,
+ 0x6c, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x75, 0x72, 0x74, 0x65, 0x65,
+ 0x6e, 0x74, 0x68, 0x20, 0x79, 0x65, 0x61, 0x72, 0x20, 0x63, 0x61, 0x6d,
+ 0x65, 0x20, 0x43, 0x68, 0x65, 0x64, 0x6f, 0x72, 0x6c, 0x61, 0x6f, 0x6d,
+ 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6b, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77,
+ 0x65, 0x72, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x6d, 0x6f, 0x74, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x52, 0x65, 0x70, 0x68, 0x61, 0x69, 0x6d, 0x73,
+ 0x20, 0x69, 0x6e, 0x20, 0x41, 0x73, 0x68, 0x74, 0x65, 0x72, 0x6f, 0x74,
+ 0x68, 0x20, 0x4b, 0x61, 0x72, 0x6e, 0x61, 0x69, 0x6d, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x5a, 0x75, 0x7a, 0x69, 0x6d,
+ 0x73, 0x20, 0x69, 0x6e, 0x20, 0x48, 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x45, 0x6d, 0x69, 0x6e, 0x73, 0x20,
+ 0x69, 0x6e, 0x20, 0x53, 0x68, 0x61, 0x76, 0x65, 0x68, 0x20, 0x4b, 0x69,
+ 0x72, 0x69, 0x61, 0x74, 0x68, 0x61, 0x69, 0x6d, 0x2c, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x6f, 0x72, 0x69, 0x74,
+ 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20,
+ 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x53, 0x65, 0x69, 0x72, 0x2c, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x45, 0x6c, 0x70, 0x61, 0x72, 0x61, 0x6e,
+ 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x62,
+ 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x64, 0x65, 0x72,
+ 0x6e, 0x65, 0x73, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74,
+ 0x6f, 0x20, 0x45, 0x6e, 0x6d, 0x69, 0x73, 0x68, 0x70, 0x61, 0x74, 0x2c,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x4b, 0x61,
+ 0x64, 0x65, 0x73, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x6d,
+ 0x6f, 0x74, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x41, 0x6d, 0x61, 0x6c, 0x65, 0x6b, 0x69, 0x74, 0x65,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x41, 0x6d, 0x6f, 0x72, 0x69, 0x74, 0x65, 0x73,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x74,
+ 0x20, 0x69, 0x6e, 0x20, 0x48, 0x61, 0x7a, 0x65, 0x7a, 0x6f, 0x6e, 0x74,
+ 0x61, 0x6d, 0x61, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x75,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6f,
+ 0x66, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66,
+ 0x20, 0x47, 0x6f, 0x6d, 0x6f, 0x72, 0x72, 0x61, 0x68, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20,
+ 0x6f, 0x66, 0x20, 0x41, 0x64, 0x6d, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6f,
+ 0x66, 0x20, 0x5a, 0x65, 0x62, 0x6f, 0x69, 0x69, 0x6d, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20,
+ 0x6f, 0x66, 0x20, 0x42, 0x65, 0x6c, 0x61, 0x20, 0x28, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x73, 0x20, 0x5a, 0x6f, 0x61,
+ 0x72, 0x3b, 0x29, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x6a, 0x6f, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x61, 0x74, 0x74,
+ 0x6c, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x53, 0x69, 0x64, 0x64, 0x69, 0x6d, 0x3b, 0x20,
+ 0x0a, 0x57, 0x69, 0x74, 0x68, 0x20, 0x43, 0x68, 0x65, 0x64, 0x6f, 0x72,
+ 0x6c, 0x61, 0x6f, 0x6d, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b,
+ 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x6c, 0x61, 0x6d, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x54, 0x69,
+ 0x64, 0x61, 0x6c, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20,
+ 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x41, 0x6d, 0x72, 0x61, 0x70, 0x68, 0x65, 0x6c, 0x20, 0x6b, 0x69,
+ 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x68, 0x69, 0x6e, 0x61, 0x72,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x72, 0x69, 0x6f, 0x63, 0x68,
+ 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x6c, 0x6c,
+ 0x61, 0x73, 0x61, 0x72, 0x3b, 0x20, 0x66, 0x6f, 0x75, 0x72, 0x20, 0x6b,
+ 0x69, 0x6e, 0x67, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x66, 0x69,
+ 0x76, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x76, 0x61, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x69, 0x64,
+ 0x64, 0x69, 0x6d, 0x20, 0x77, 0x61, 0x73, 0x20, 0x66, 0x75, 0x6c, 0x6c,
+ 0x20, 0x6f, 0x66, 0x20, 0x73, 0x6c, 0x69, 0x6d, 0x65, 0x70, 0x69, 0x74,
+ 0x73, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b,
+ 0x69, 0x6e, 0x67, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x6f, 0x64, 0x6f,
+ 0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x6d, 0x6f, 0x72, 0x72,
+ 0x61, 0x68, 0x20, 0x66, 0x6c, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x66, 0x65, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x20,
+ 0x66, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x74, 0x6f, 0x6f, 0x6b,
+ 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x6f, 0x6f,
+ 0x64, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x6d, 0x6f, 0x72, 0x72, 0x61, 0x68,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68,
+ 0x65, 0x69, 0x72, 0x20, 0x76, 0x69, 0x63, 0x74, 0x75, 0x61, 0x6c, 0x73,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x69, 0x72, 0x20, 0x77, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x74, 0x6f, 0x6f, 0x6b,
+ 0x20, 0x4c, 0x6f, 0x74, 0x2c, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x27,
+ 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73, 0x20,
+ 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x77, 0x68, 0x6f, 0x20, 0x64, 0x77, 0x65,
+ 0x6c, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x67, 0x6f, 0x6f,
+ 0x64, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x65, 0x70, 0x61,
+ 0x72, 0x74, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x6e,
+ 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x64, 0x20, 0x65,
+ 0x73, 0x63, 0x61, 0x70, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x6f, 0x6c, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x48, 0x65, 0x62, 0x72, 0x65, 0x77, 0x3b, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x68, 0x65, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x74, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x69, 0x6e,
+ 0x20, 0x6f, 0x66, 0x20, 0x4d, 0x61, 0x6d, 0x72, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x41, 0x6d, 0x6f, 0x72, 0x69, 0x74, 0x65, 0x2c, 0x20, 0x62,
+ 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x45, 0x73,
+ 0x68, 0x63, 0x6f, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x72,
+ 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x6e, 0x65,
+ 0x72, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x65, 0x64,
+ 0x65, 0x72, 0x61, 0x74, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x41,
+ 0x62, 0x72, 0x61, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x77,
+ 0x68, 0x65, 0x6e, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x68, 0x65,
+ 0x61, 0x72, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x63, 0x61, 0x70, 0x74, 0x69,
+ 0x76, 0x65, 0x2c, 0x20, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6d, 0x65, 0x64,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x65, 0x64,
+ 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x62,
+ 0x6f, 0x72, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6f,
+ 0x77, 0x6e, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2c, 0x20, 0x74, 0x68,
+ 0x72, 0x65, 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x65, 0x65, 0x6e,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x75, 0x72, 0x73, 0x75, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x44, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d,
+ 0x73, 0x65, 0x6c, 0x66, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x73, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x68, 0x65, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e,
+ 0x74, 0x73, 0x2c, 0x20, 0x62, 0x79, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x6d, 0x6f, 0x74, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x75,
+ 0x72, 0x73, 0x75, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x48, 0x6f, 0x62, 0x61, 0x68, 0x2c, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64,
+ 0x20, 0x6f, 0x66, 0x20, 0x44, 0x61, 0x6d, 0x61, 0x73, 0x63, 0x75, 0x73,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x62, 0x72,
+ 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x73,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x62,
+ 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x4c, 0x6f, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x65, 0x6e, 0x20, 0x61,
+ 0x6c, 0x73, 0x6f, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6f,
+ 0x66, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x20, 0x77, 0x65, 0x6e, 0x74,
+ 0x20, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x65, 0x74,
+ 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x72,
+ 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6c, 0x61, 0x75, 0x67,
+ 0x68, 0x74, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x68, 0x65, 0x64,
+ 0x6f, 0x72, 0x6c, 0x61, 0x6f, 0x6d, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 0x69, 0x6e,
+ 0x67, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x61,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x76, 0x61, 0x6c, 0x6c, 0x65, 0x79,
+ 0x20, 0x6f, 0x66, 0x20, 0x53, 0x68, 0x61, 0x76, 0x65, 0x68, 0x2c, 0x20,
+ 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x27, 0x73, 0x20, 0x64, 0x61, 0x6c, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x4d, 0x65, 0x6c, 0x63, 0x68,
+ 0x69, 0x7a, 0x65, 0x64, 0x65, 0x6b, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20,
+ 0x6f, 0x66, 0x20, 0x53, 0x61, 0x6c, 0x65, 0x6d, 0x20, 0x62, 0x72, 0x6f,
+ 0x75, 0x67, 0x68, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x62,
+ 0x72, 0x65, 0x61, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x6e,
+ 0x65, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x69, 0x65, 0x73, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x73, 0x74,
+ 0x20, 0x68, 0x69, 0x67, 0x68, 0x20, 0x47, 0x6f, 0x64, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73,
+ 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x6c, 0x65, 0x73, 0x73, 0x65,
+ 0x64, 0x20, 0x62, 0x65, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x73, 0x74, 0x20, 0x68,
+ 0x69, 0x67, 0x68, 0x20, 0x47, 0x6f, 0x64, 0x2c, 0x20, 0x70, 0x6f, 0x73,
+ 0x73, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65,
+ 0x61, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x62, 0x6c, 0x65,
+ 0x73, 0x73, 0x65, 0x64, 0x20, 0x62, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x6f, 0x73, 0x74, 0x20, 0x68, 0x69, 0x67, 0x68, 0x20, 0x47, 0x6f,
+ 0x64, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x68, 0x61, 0x74,
+ 0x68, 0x20, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x65, 0x64, 0x20,
+ 0x74, 0x68, 0x69, 0x6e, 0x65, 0x20, 0x65, 0x6e, 0x65, 0x6d, 0x69, 0x65,
+ 0x73, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79, 0x20, 0x68,
+ 0x61, 0x6e, 0x64, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x67, 0x61, 0x76, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x74, 0x69, 0x74,
+ 0x68, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 0x69, 0x6e,
+ 0x67, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x6d, 0x2c, 0x20, 0x47, 0x69, 0x76, 0x65, 0x20, 0x6d, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x73, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x79, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x20,
+ 0x6f, 0x66, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x2c, 0x20, 0x49, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x6c, 0x69, 0x66, 0x74, 0x20, 0x75, 0x70,
+ 0x20, 0x6d, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x73, 0x74, 0x20, 0x68,
+ 0x69, 0x67, 0x68, 0x20, 0x47, 0x6f, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x70, 0x6f, 0x73, 0x73, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x20, 0x6f,
+ 0x66, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x0a, 0x54, 0x68, 0x61,
+ 0x74, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74,
+ 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61,
+ 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x20, 0x65, 0x76, 0x65, 0x6e,
+ 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x73, 0x68, 0x6f, 0x65, 0x6c, 0x61,
+ 0x74, 0x63, 0x68, 0x65, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20, 0x61, 0x6e, 0x79, 0x20,
+ 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69,
+ 0x73, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x65, 0x2c, 0x20, 0x6c, 0x65, 0x73,
+ 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c,
+ 0x64, 0x65, 0x73, 0x74, 0x20, 0x73, 0x61, 0x79, 0x2c, 0x20, 0x49, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x6d, 0x20, 0x72, 0x69, 0x63, 0x68, 0x3a, 0x20, 0x0a, 0x53,
+ 0x61, 0x76, 0x65, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x79, 0x6f, 0x75, 0x6e, 0x67, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x65, 0x61, 0x74, 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x41, 0x6e, 0x65,
+ 0x72, 0x2c, 0x20, 0x45, 0x73, 0x68, 0x63, 0x6f, 0x6c, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x4d, 0x61, 0x6d, 0x72, 0x65, 0x3b, 0x20, 0x6c, 0x65,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6f,
+ 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68,
+ 0x65, 0x73, 0x65, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x63, 0x61, 0x6d, 0x65,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20,
+ 0x69, 0x6e, 0x20, 0x61, 0x20, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2c,
+ 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x46, 0x65, 0x61,
+ 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x2c, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d,
+ 0x3a, 0x20, 0x49, 0x20, 0x61, 0x6d, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73,
+ 0x68, 0x69, 0x65, 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x69, 0x6e, 0x67,
+ 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x72, 0x65, 0x77, 0x61, 0x72,
+ 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61,
+ 0x6d, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x47, 0x6f, 0x64, 0x2c, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x77,
+ 0x69, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x67, 0x69, 0x76,
+ 0x65, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x73, 0x65, 0x65, 0x69, 0x6e, 0x67,
+ 0x20, 0x49, 0x20, 0x67, 0x6f, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x6c,
+ 0x65, 0x73, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x74, 0x65, 0x77, 0x61, 0x72, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x6d, 0x79, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20,
+ 0x74, 0x68, 0x69, 0x73, 0x20, 0x45, 0x6c, 0x69, 0x65, 0x7a, 0x65, 0x72,
+ 0x20, 0x6f, 0x66, 0x20, 0x44, 0x61, 0x6d, 0x61, 0x73, 0x63, 0x75, 0x73,
+ 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e,
+ 0x20, 0x6e, 0x6f, 0x20, 0x73, 0x65, 0x65, 0x64, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x2c, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x62,
+ 0x6f, 0x72, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x6d, 0x79, 0x20, 0x68, 0x6f,
+ 0x75, 0x73, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x69, 0x6e, 0x65, 0x20,
+ 0x68, 0x65, 0x69, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x2c, 0x20,
+ 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x6f, 0x72, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69,
+ 0x6e, 0x67, 0x2c, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x74, 0x68,
+ 0x69, 0x6e, 0x65, 0x20, 0x68, 0x65, 0x69, 0x72, 0x3b, 0x20, 0x62, 0x75,
+ 0x74, 0x20, 0x68, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x66, 0x6f, 0x72,
+ 0x74, 0x68, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x69, 0x6e, 0x65, 0x20, 0x6f, 0x77, 0x6e, 0x20, 0x62, 0x6f, 0x77, 0x65,
+ 0x6c, 0x73, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20,
+ 0x74, 0x68, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x65, 0x69, 0x72, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x62, 0x72, 0x6f, 0x75,
+ 0x67, 0x68, 0x74, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x66, 0x6f, 0x72, 0x74,
+ 0x68, 0x20, 0x61, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x6f, 0x6f, 0x6b,
+ 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x6f, 0x77, 0x61, 0x72, 0x64, 0x20,
+ 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x65, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x61,
+ 0x72, 0x73, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x62, 0x65, 0x20, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x6e,
+ 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x53, 0x6f,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73,
+ 0x65, 0x65, 0x64, 0x20, 0x62, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x6c, 0x69, 0x65, 0x76, 0x65, 0x64,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x75,
+ 0x6e, 0x74, 0x65, 0x64, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x68,
+ 0x69, 0x6d, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74,
+ 0x65, 0x6f, 0x75, 0x73, 0x6e, 0x65, 0x73, 0x73, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x49, 0x20, 0x61,
+ 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20,
+ 0x55, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x68,
+ 0x61, 0x6c, 0x64, 0x65, 0x65, 0x73, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x67,
+ 0x69, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x74, 0x68, 0x69,
+ 0x73, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e,
+ 0x68, 0x65, 0x72, 0x69, 0x74, 0x20, 0x69, 0x74, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x2c, 0x20, 0x77, 0x68,
+ 0x65, 0x72, 0x65, 0x62, 0x79, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x49, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x49, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x69, 0x6e, 0x68, 0x65,
+ 0x72, 0x69, 0x74, 0x20, 0x69, 0x74, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x54, 0x61, 0x6b, 0x65, 0x20,
+ 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x65, 0x69, 0x66, 0x65, 0x72,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x20, 0x79, 0x65,
+ 0x61, 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x61, 0x20, 0x73, 0x68, 0x65, 0x20, 0x67, 0x6f, 0x61, 0x74, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x61, 0x20, 0x72, 0x61, 0x6d, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x72,
+ 0x65, 0x65, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x74, 0x75, 0x72, 0x74,
+ 0x6c, 0x65, 0x64, 0x6f, 0x76, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x61, 0x20, 0x79, 0x6f, 0x75, 0x6e, 0x67, 0x20, 0x70, 0x69, 0x67, 0x65,
+ 0x6f, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69,
+ 0x6d, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x69, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6c, 0x61, 0x69, 0x64, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x70, 0x69,
+ 0x65, 0x63, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x61, 0x67, 0x61, 0x69,
+ 0x6e, 0x73, 0x74, 0x20, 0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x3a,
+ 0x20, 0x62, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x72,
+ 0x64, 0x73, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x77,
+ 0x6c, 0x73, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x64, 0x6f, 0x77, 0x6e,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61,
+ 0x72, 0x63, 0x61, 0x73, 0x65, 0x73, 0x2c, 0x20, 0x41, 0x62, 0x72, 0x61,
+ 0x6d, 0x20, 0x64, 0x72, 0x6f, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x20, 0x61, 0x77, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x75, 0x6e,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x20, 0x64,
+ 0x6f, 0x77, 0x6e, 0x2c, 0x20, 0x61, 0x20, 0x64, 0x65, 0x65, 0x70, 0x20,
+ 0x73, 0x6c, 0x65, 0x65, 0x70, 0x20, 0x66, 0x65, 0x6c, 0x6c, 0x20, 0x75,
+ 0x70, 0x6f, 0x6e, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x3b, 0x20, 0x61,
+ 0x6e, 0x64, 0x2c, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x61, 0x6e, 0x20, 0x68,
+ 0x6f, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x67, 0x72, 0x65,
+ 0x61, 0x74, 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e, 0x65, 0x73, 0x73, 0x20,
+ 0x66, 0x65, 0x6c, 0x6c, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x68, 0x69,
+ 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x6d, 0x2c, 0x20, 0x4b, 0x6e, 0x6f, 0x77, 0x20, 0x6f, 0x66, 0x20,
+ 0x61, 0x20, 0x73, 0x75, 0x72, 0x65, 0x74, 0x79, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x73, 0x74,
+ 0x72, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20,
+ 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x27, 0x73,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x73, 0x65, 0x72, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x61, 0x66, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x20, 0x66, 0x6f, 0x75, 0x72, 0x20, 0x68, 0x75, 0x6e,
+ 0x64, 0x72, 0x65, 0x64, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x3b, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x77,
+ 0x68, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x2c, 0x20, 0x77, 0x69,
+ 0x6c, 0x6c, 0x20, 0x49, 0x20, 0x6a, 0x75, 0x64, 0x67, 0x65, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x77, 0x61, 0x72,
+ 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x73, 0x75, 0x62,
+ 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20,
+ 0x67, 0x6f, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79, 0x20, 0x66, 0x61,
+ 0x74, 0x68, 0x65, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x65, 0x61,
+ 0x63, 0x65, 0x3b, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x74, 0x20, 0x62, 0x65, 0x20, 0x62, 0x75, 0x72, 0x69, 0x65, 0x64,
+ 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x6f,
+ 0x6c, 0x64, 0x20, 0x61, 0x67, 0x65, 0x2e, 0x20, 0x0a, 0x42, 0x75, 0x74,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x75, 0x72,
+ 0x74, 0x68, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c,
+ 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x68, 0x69, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x69, 0x71, 0x75, 0x69, 0x74, 0x79,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x41, 0x6d, 0x6f, 0x72,
+ 0x69, 0x74, 0x65, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x79, 0x65, 0x74, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74,
+ 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x75, 0x6e, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x64, 0x6f, 0x77, 0x6e,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x64, 0x61, 0x72, 0x6b, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x20, 0x61, 0x20, 0x73, 0x6d, 0x6f, 0x6b, 0x69, 0x6e, 0x67, 0x20,
+ 0x66, 0x75, 0x72, 0x6e, 0x61, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x61, 0x20, 0x62, 0x75, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x6c,
+ 0x61, 0x6d, 0x70, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x61, 0x73,
+ 0x73, 0x65, 0x64, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20,
+ 0x74, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x70, 0x69, 0x65, 0x63, 0x65, 0x73,
+ 0x2e, 0x20, 0x0a, 0x49, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61,
+ 0x6d, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x61, 0x20, 0x63,
+ 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69,
+ 0x6e, 0x67, 0x2c, 0x20, 0x55, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x49,
+ 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20,
+ 0x6c, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20,
+ 0x45, 0x67, 0x79, 0x70, 0x74, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x72, 0x69, 0x76,
+ 0x65, 0x72, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x69, 0x76, 0x65,
+ 0x72, 0x20, 0x45, 0x75, 0x70, 0x68, 0x72, 0x61, 0x74, 0x65, 0x73, 0x3a,
+ 0x20, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x4b, 0x65, 0x6e, 0x69, 0x74, 0x65,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4b,
+ 0x65, 0x6e, 0x69, 0x7a, 0x7a, 0x69, 0x74, 0x65, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4b, 0x61, 0x64, 0x6d, 0x6f,
+ 0x6e, 0x69, 0x74, 0x65, 0x73, 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x48, 0x69, 0x74, 0x74, 0x69, 0x74, 0x65, 0x73,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x50, 0x65,
+ 0x72, 0x69, 0x7a, 0x7a, 0x69, 0x74, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x52, 0x65, 0x70, 0x68, 0x61, 0x69,
+ 0x6d, 0x73, 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x41, 0x6d, 0x6f, 0x72, 0x69, 0x74, 0x65, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61,
+ 0x6e, 0x69, 0x74, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x47, 0x69, 0x72, 0x67, 0x61, 0x73, 0x68, 0x69, 0x74,
+ 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4a, 0x65, 0x62, 0x75, 0x73, 0x69, 0x74, 0x65, 0x73, 0x2e, 0x20, 0x0a,
+ 0x4e, 0x6f, 0x77, 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x6d, 0x27, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x20, 0x62,
+ 0x61, 0x72, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x6e, 0x6f, 0x20, 0x63,
+ 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x61, 0x6e, 0x20,
+ 0x68, 0x61, 0x6e, 0x64, 0x6d, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x61, 0x6e,
+ 0x20, 0x45, 0x67, 0x79, 0x70, 0x74, 0x69, 0x61, 0x6e, 0x2c, 0x20, 0x77,
+ 0x68, 0x6f, 0x73, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x48, 0x61, 0x67, 0x61, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x2c,
+ 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x77, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x68, 0x61,
+ 0x74, 0x68, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x65,
+ 0x64, 0x20, 0x6d, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x62, 0x65,
+ 0x61, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x49, 0x20, 0x70, 0x72, 0x61,
+ 0x79, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x67, 0x6f, 0x20, 0x69,
+ 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x79, 0x20, 0x6d, 0x61,
+ 0x69, 0x64, 0x3b, 0x20, 0x69, 0x74, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62,
+ 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x6d, 0x61, 0x79,
+ 0x20, 0x6f, 0x62, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x63, 0x68, 0x69, 0x6c,
+ 0x64, 0x72, 0x65, 0x6e, 0x20, 0x62, 0x79, 0x20, 0x68, 0x65, 0x72, 0x2e,
+ 0x20, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x68,
+ 0x65, 0x61, 0x72, 0x6b, 0x65, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d,
+ 0x27, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x6b,
+ 0x20, 0x48, 0x61, 0x67, 0x61, 0x72, 0x20, 0x68, 0x65, 0x72, 0x20, 0x6d,
+ 0x61, 0x69, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x45, 0x67, 0x79, 0x70,
+ 0x74, 0x69, 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x68, 0x61, 0x64, 0x20, 0x64, 0x77,
+ 0x65, 0x6c, 0x74, 0x20, 0x74, 0x65, 0x6e, 0x20, 0x79, 0x65, 0x61, 0x72,
+ 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x61, 0x76, 0x65, 0x20, 0x68, 0x65,
+ 0x72, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x65, 0x72, 0x20, 0x68, 0x75, 0x73,
+ 0x62, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x74,
+ 0x6f, 0x20, 0x62, 0x65, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x77,
+ 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x48, 0x61, 0x67, 0x61, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x73, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x63,
+ 0x65, 0x69, 0x76, 0x65, 0x64, 0x2c, 0x20, 0x68, 0x65, 0x72, 0x20, 0x6d,
+ 0x69, 0x73, 0x74, 0x72, 0x65, 0x73, 0x73, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x64, 0x65, 0x73, 0x70, 0x69, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20,
+ 0x68, 0x65, 0x72, 0x20, 0x65, 0x79, 0x65, 0x73, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d,
+ 0x2c, 0x20, 0x4d, 0x79, 0x20, 0x77, 0x72, 0x6f, 0x6e, 0x67, 0x20, 0x62,
+ 0x65, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3a,
+ 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65,
+ 0x6e, 0x20, 0x6d, 0x79, 0x20, 0x6d, 0x61, 0x69, 0x64, 0x20, 0x69, 0x6e,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x6f, 0x73, 0x6f, 0x6d,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x73, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x63,
+ 0x65, 0x69, 0x76, 0x65, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x64, 0x65, 0x73, 0x70, 0x69, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e,
+ 0x20, 0x68, 0x65, 0x72, 0x20, 0x65, 0x79, 0x65, 0x73, 0x3a, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x6a, 0x75, 0x64, 0x67,
+ 0x65, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x6d, 0x65,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2e, 0x20, 0x0a,
+ 0x42, 0x75, 0x74, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x53, 0x61, 0x72, 0x61,
+ 0x69, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x6d, 0x61, 0x69, 0x64, 0x20, 0x69, 0x73, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x61, 0x6e, 0x64,
+ 0x3b, 0x20, 0x64, 0x6f, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x65, 0x72, 0x20,
+ 0x61, 0x73, 0x20, 0x69, 0x74, 0x20, 0x70, 0x6c, 0x65, 0x61, 0x73, 0x65,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x20,
+ 0x64, 0x65, 0x61, 0x6c, 0x74, 0x20, 0x68, 0x61, 0x72, 0x64, 0x6c, 0x79,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x73,
+ 0x68, 0x65, 0x20, 0x66, 0x6c, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d,
+ 0x20, 0x68, 0x65, 0x72, 0x20, 0x66, 0x61, 0x63, 0x65, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6e, 0x67, 0x65,
+ 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x72, 0x20,
+ 0x62, 0x79, 0x20, 0x61, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69,
+ 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x64, 0x65, 0x72,
+ 0x6e, 0x65, 0x73, 0x73, 0x2c, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x79, 0x20, 0x74, 0x6f, 0x20,
+ 0x53, 0x68, 0x75, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x48, 0x61, 0x67, 0x61,
+ 0x72, 0x2c, 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x27, 0x73, 0x20, 0x6d,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x63, 0x65, 0x20,
+ 0x63, 0x61, 0x6d, 0x65, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x3f,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x69, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x77, 0x69, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x67,
+ 0x6f, 0x3f, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x66, 0x6c, 0x65, 0x65, 0x20,
+ 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x6d, 0x69, 0x73, 0x74,
+ 0x72, 0x65, 0x73, 0x73, 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6e, 0x67,
+ 0x65, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e,
+ 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6d, 0x69, 0x73, 0x74,
+ 0x72, 0x65, 0x73, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x75,
+ 0x62, 0x6d, 0x69, 0x74, 0x20, 0x74, 0x68, 0x79, 0x73, 0x65, 0x6c, 0x66,
+ 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x68, 0x65, 0x72, 0x20, 0x68,
+ 0x61, 0x6e, 0x64, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x65, 0x72, 0x2c, 0x20,
+ 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69,
+ 0x70, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64,
+ 0x20, 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x69, 0x6e, 0x67, 0x6c, 0x79,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x6e,
+ 0x75, 0x6d, 0x62, 0x65, 0x72, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6e, 0x67, 0x65,
+ 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x68, 0x65, 0x72, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x61, 0x72, 0x74, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x62, 0x65, 0x61, 0x72, 0x20,
+ 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x74, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x49, 0x73, 0x68, 0x6d, 0x61,
+ 0x65, 0x6c, 0x3b, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x68, 0x61, 0x74,
+ 0x68, 0x20, 0x68, 0x65, 0x61, 0x72, 0x64, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x61, 0x66, 0x66, 0x6c, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x77, 0x69, 0x6c, 0x64, 0x20, 0x6d,
+ 0x61, 0x6e, 0x3b, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x61, 0x6e, 0x64,
+ 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x67, 0x61,
+ 0x69, 0x6e, 0x73, 0x74, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6d,
+ 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x6d, 0x61, 0x6e, 0x27, 0x73, 0x20, 0x68, 0x61, 0x6e, 0x64,
+ 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x73, 0x74, 0x20, 0x68, 0x69, 0x6d,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x62, 0x72, 0x65, 0x74, 0x68, 0x72, 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x73, 0x70, 0x61, 0x6b, 0x65, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x54, 0x68, 0x6f, 0x75,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x65, 0x65, 0x73, 0x74, 0x20, 0x6d,
+ 0x65, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x48, 0x61, 0x76, 0x65, 0x20, 0x49, 0x20,
+ 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x68, 0x65, 0x72, 0x65, 0x20, 0x6c, 0x6f,
+ 0x6f, 0x6b, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68,
+ 0x69, 0x6d, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73, 0x65, 0x65, 0x74,
+ 0x68, 0x20, 0x6d, 0x65, 0x3f, 0x20, 0x0a, 0x57, 0x68, 0x65, 0x72, 0x65,
+ 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x65, 0x6c,
+ 0x6c, 0x20, 0x77, 0x61, 0x73, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x42, 0x65, 0x65, 0x72, 0x6c, 0x61, 0x68, 0x61, 0x69, 0x72, 0x6f,
+ 0x69, 0x3b, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x69,
+ 0x74, 0x20, 0x69, 0x73, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e,
+ 0x20, 0x4b, 0x61, 0x64, 0x65, 0x73, 0x68, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x42, 0x65, 0x72, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x48, 0x61, 0x67, 0x61, 0x72, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20, 0x41,
+ 0x62, 0x72, 0x61, 0x6d, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61,
+ 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e,
+ 0x27, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x48, 0x61, 0x67, 0x61, 0x72, 0x20, 0x62, 0x61, 0x72,
+ 0x65, 0x2c, 0x20, 0x49, 0x73, 0x68, 0x6d, 0x61, 0x65, 0x6c, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x66, 0x6f, 0x75, 0x72, 0x73, 0x63, 0x6f, 0x72, 0x65,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x69, 0x78, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e,
+ 0x20, 0x48, 0x61, 0x67, 0x61, 0x72, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20,
+ 0x49, 0x73, 0x68, 0x6d, 0x61, 0x65, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x41,
+ 0x62, 0x72, 0x61, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x77,
+ 0x68, 0x65, 0x6e, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e,
+ 0x69, 0x6e, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x65, 0x64, 0x20, 0x74,
+ 0x6f, 0x20, 0x41, 0x62, 0x72, 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68,
+ 0x69, 0x6d, 0x2c, 0x20, 0x49, 0x20, 0x61, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x41, 0x6c, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x79, 0x20, 0x47, 0x6f,
+ 0x64, 0x3b, 0x20, 0x77, 0x61, 0x6c, 0x6b, 0x20, 0x62, 0x65, 0x66, 0x6f,
+ 0x72, 0x65, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x70, 0x65, 0x72, 0x66, 0x65,
+ 0x63, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x6d, 0x79, 0x20,
+ 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x62, 0x65, 0x74,
+ 0x77, 0x65, 0x65, 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69,
+ 0x6c, 0x6c, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x20, 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x69,
+ 0x6e, 0x67, 0x6c, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41,
+ 0x62, 0x72, 0x61, 0x6d, 0x20, 0x66, 0x65, 0x6c, 0x6c, 0x20, 0x6f, 0x6e,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x66, 0x61, 0x63, 0x65, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x74, 0x61, 0x6c, 0x6b, 0x65,
+ 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20,
+ 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x0a, 0x41, 0x73, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f,
+ 0x6c, 0x64, 0x2c, 0x20, 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e,
+ 0x61, 0x6e, 0x74, 0x20, 0x69, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x62, 0x65, 0x20,
+ 0x61, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20,
+ 0x6d, 0x61, 0x6e, 0x79, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+ 0x2e, 0x20, 0x0a, 0x4e, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6e, 0x61, 0x6d,
+ 0x65, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x62,
+ 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x6d, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62,
+ 0x65, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x3b, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x61, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x6f, 0x66, 0x20, 0x6d, 0x61, 0x6e, 0x79, 0x20, 0x6e, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x49, 0x20, 0x6d,
+ 0x61, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6d, 0x61,
+ 0x6b, 0x65, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x65, 0x78, 0x63, 0x65,
+ 0x65, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x66,
+ 0x75, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69,
+ 0x6c, 0x6c, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x6e, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6b, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x75,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x65,
+ 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x20, 0x6d, 0x79, 0x20,
+ 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x62, 0x65, 0x74,
+ 0x77, 0x65, 0x65, 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x69,
+ 0x72, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x76, 0x65,
+ 0x72, 0x6c, 0x61, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x6f, 0x76,
+ 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65,
+ 0x20, 0x61, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x61, 0x66,
+ 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x67, 0x69,
+ 0x76, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61,
+ 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x61, 0x72, 0x74, 0x20, 0x61, 0x20, 0x73, 0x74,
+ 0x72, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x43, 0x61, 0x6e, 0x61, 0x61, 0x6e, 0x2c, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x61, 0x6e, 0x20, 0x65, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x73, 0x74, 0x69,
+ 0x6e, 0x67, 0x20, 0x70, 0x6f, 0x73, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f,
+ 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c,
+ 0x6c, 0x20, 0x62, 0x65, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x47,
+ 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41,
+ 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x54, 0x68, 0x6f, 0x75,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20,
+ 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x2c, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x69,
+ 0x72, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
+ 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x2c,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x79, 0x65, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x6b, 0x65, 0x65, 0x70, 0x2c, 0x20, 0x62, 0x65,
+ 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x79, 0x6f, 0x75, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x3b, 0x20, 0x45, 0x76, 0x65, 0x72, 0x79, 0x20,
+ 0x6d, 0x61, 0x6e, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x61, 0x6d,
+ 0x6f, 0x6e, 0x67, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c,
+ 0x6c, 0x20, 0x62, 0x65, 0x20, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x63,
+ 0x69, 0x73, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x79,
+ 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x69, 0x72, 0x63,
+ 0x75, 0x6d, 0x63, 0x69, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x6c, 0x65, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x72,
+ 0x20, 0x66, 0x6f, 0x72, 0x65, 0x73, 0x6b, 0x69, 0x6e, 0x3b, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x62, 0x65, 0x20, 0x61, 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61,
+ 0x6e, 0x74, 0x20, 0x62, 0x65, 0x74, 0x77, 0x69, 0x78, 0x74, 0x20, 0x6d,
+ 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79, 0x6f, 0x75, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x69, 0x73, 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x64, 0x61, 0x79,
+ 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x62, 0x65, 0x20, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x63, 0x69, 0x73,
+ 0x65, 0x64, 0x20, 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x20, 0x79, 0x6f, 0x75,
+ 0x2c, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6d, 0x61, 0x6e, 0x20,
+ 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x79, 0x6f, 0x75,
+ 0x72, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x2c, 0x20, 0x68, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69,
+ 0x73, 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2c, 0x20, 0x6f, 0x72, 0x20,
+ 0x62, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x6d, 0x6f, 0x6e, 0x65, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x79,
+ 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x72, 0x2c, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x65, 0x64, 0x2e,
+ 0x20, 0x0a, 0x48, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73,
+ 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x62,
+ 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x6d, 0x6f, 0x6e, 0x65, 0x79, 0x2c, 0x20, 0x6d, 0x75,
+ 0x73, 0x74, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x20, 0x62, 0x65, 0x20,
+ 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x63, 0x69, 0x73, 0x65, 0x64, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x76, 0x65,
+ 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62,
+ 0x65, 0x20, 0x69, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x66, 0x6c,
+ 0x65, 0x73, 0x68, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6e, 0x20, 0x65,
+ 0x76, 0x65, 0x72, 0x6c, 0x61, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x63,
+ 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x6e, 0x63, 0x69, 0x72, 0x63,
+ 0x75, 0x6d, 0x63, 0x69, 0x73, 0x65, 0x64, 0x20, 0x6d, 0x61, 0x6e, 0x20,
+ 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x77, 0x68, 0x6f, 0x73, 0x65, 0x20,
+ 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x66, 0x6f, 0x72, 0x65, 0x73, 0x6b, 0x69, 0x6e, 0x20, 0x69, 0x73,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x63,
+ 0x69, 0x73, 0x65, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73,
+ 0x6f, 0x75, 0x6c, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65,
+ 0x20, 0x63, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x66, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x68, 0x69, 0x73, 0x20, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65,
+ 0x3b, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x62, 0x72,
+ 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x76, 0x65,
+ 0x6e, 0x61, 0x6e, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x41, 0x73,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x68, 0x65, 0x72, 0x20, 0x6e, 0x61, 0x6d,
+ 0x65, 0x20, 0x53, 0x61, 0x72, 0x61, 0x69, 0x2c, 0x20, 0x62, 0x75, 0x74,
+ 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c,
+ 0x20, 0x68, 0x65, 0x72, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x62, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c,
+ 0x6c, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x20, 0x68, 0x65, 0x72, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x61, 0x6c, 0x73,
+ 0x6f, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65, 0x72, 0x3a, 0x20, 0x79, 0x65,
+ 0x61, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x6c,
+ 0x65, 0x73, 0x73, 0x20, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x68, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62,
+ 0x65, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f,
+ 0x66, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3b, 0x20, 0x6b,
+ 0x69, 0x6e, 0x67, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x70, 0x65, 0x6f, 0x70,
+ 0x6c, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65,
+ 0x6e, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x66, 0x65,
+ 0x6c, 0x6c, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x66, 0x61, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x61,
+ 0x75, 0x67, 0x68, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68,
+ 0x65, 0x61, 0x72, 0x74, 0x2c, 0x20, 0x53, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x61, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x62,
+ 0x6f, 0x72, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6e, 0x20,
+ 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x20, 0x79, 0x65, 0x61, 0x72,
+ 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x3f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x2c, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x69, 0x6e, 0x65,
+ 0x74, 0x79, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64,
+ 0x2c, 0x20, 0x62, 0x65, 0x61, 0x72, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x47, 0x6f, 0x64, 0x2c, 0x20,
+ 0x4f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x73, 0x68, 0x6d, 0x61,
+ 0x65, 0x6c, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x20, 0x6c, 0x69, 0x76,
+ 0x65, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65,
+ 0x65, 0x21, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x20,
+ 0x74, 0x68, 0x79, 0x20, 0x77, 0x69, 0x66, 0x65, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x61, 0x72, 0x20, 0x74, 0x68, 0x65, 0x65,
+ 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x65,
+ 0x64, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x49, 0x73, 0x61, 0x61,
+ 0x63, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c,
+ 0x6c, 0x20, 0x65, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x20,
+ 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x61, 0x6e, 0x20, 0x65, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x73, 0x74,
+ 0x69, 0x6e, 0x67, 0x20, 0x63, 0x6f, 0x76, 0x65, 0x6e, 0x61, 0x6e, 0x74,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x61, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x49, 0x73, 0x68, 0x6d, 0x61,
+ 0x65, 0x6c, 0x2c, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x68,
+ 0x65, 0x61, 0x72, 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3a, 0x20, 0x42,
+ 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76,
+ 0x65, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x68, 0x69,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x66, 0x72, 0x75,
+ 0x69, 0x74, 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79,
+ 0x20, 0x68, 0x69, 0x6d, 0x20, 0x65, 0x78, 0x63, 0x65, 0x65, 0x64, 0x69,
+ 0x6e, 0x67, 0x6c, 0x79, 0x3b, 0x20, 0x74, 0x77, 0x65, 0x6c, 0x76, 0x65,
+ 0x20, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x73, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x65, 0x74, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61, 0x20, 0x67,
+ 0x72, 0x65, 0x61, 0x74, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
+ 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x6d, 0x79, 0x20, 0x63, 0x6f, 0x76,
+ 0x65, 0x6e, 0x61, 0x6e, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x49,
+ 0x20, 0x65, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x2c, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x61, 0x72, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x61, 0x74, 0x20, 0x74,
+ 0x68, 0x69, 0x73, 0x20, 0x73, 0x65, 0x74, 0x20, 0x74, 0x69, 0x6d, 0x65,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x65, 0x78, 0x74,
+ 0x20, 0x79, 0x65, 0x61, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x6f, 0x66, 0x66, 0x20,
+ 0x74, 0x61, 0x6c, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x70, 0x20, 0x66, 0x72,
+ 0x6f, 0x6d, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d,
+ 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x49, 0x73, 0x68, 0x6d, 0x61, 0x65,
+ 0x6c, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x77, 0x65, 0x72, 0x65, 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x69, 0x6e,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x62, 0x6f, 0x75, 0x67, 0x68, 0x74,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x6f,
+ 0x6e, 0x65, 0x79, 0x2c, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6d,
+ 0x61, 0x6c, 0x65, 0x20, 0x61, 0x6d, 0x6f, 0x6e, 0x67, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x68, 0x61, 0x6d, 0x27, 0x73, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d,
+ 0x63, 0x69, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c,
+ 0x65, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72,
+ 0x20, 0x66, 0x6f, 0x72, 0x65, 0x73, 0x6b, 0x69, 0x6e, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x73, 0x61, 0x6d,
+ 0x65, 0x20, 0x64, 0x61, 0x79, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x68, 0x61, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x6e, 0x69, 0x6e, 0x65, 0x74, 0x79, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e,
+ 0x69, 0x6e, 0x65, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x68, 0x65,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6d, 0x63,
+ 0x69, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x66, 0x6f, 0x72, 0x65, 0x73, 0x6b, 0x69, 0x6e, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x68, 0x6d, 0x61, 0x65, 0x6c, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x74, 0x68, 0x69, 0x72, 0x74, 0x65, 0x65, 0x6e, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e,
+ 0x20, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x63, 0x69, 0x72, 0x63,
+ 0x75, 0x6d, 0x63, 0x69, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x65, 0x73, 0x6b, 0x69, 0x6e,
+ 0x2e, 0x20, 0x0a, 0x49, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65,
+ 0x6c, 0x66, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x63,
+ 0x69, 0x72, 0x63, 0x75, 0x6d, 0x63, 0x69, 0x73, 0x65, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x68, 0x6d, 0x61, 0x65, 0x6c, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65,
+ 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x6f, 0x75,
+ 0x73, 0x65, 0x2c, 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x62, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x6d, 0x6f, 0x6e, 0x65, 0x79, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x72,
+ 0x2c, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x63, 0x69, 0x72, 0x63, 0x75,
+ 0x6d, 0x63, 0x69, 0x73, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61,
+ 0x72, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x69,
+ 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4d, 0x61, 0x6d, 0x72, 0x65, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x74, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x20,
+ 0x64, 0x6f, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x68, 0x65, 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x64, 0x61, 0x79, 0x3b, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x6c, 0x69, 0x66, 0x74, 0x20, 0x75, 0x70, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x65, 0x79, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f,
+ 0x6f, 0x6b, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x6c,
+ 0x6f, 0x2c, 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x20, 0x6d, 0x65, 0x6e,
+ 0x20, 0x73, 0x74, 0x6f, 0x6f, 0x64, 0x20, 0x62, 0x79, 0x20, 0x68, 0x69,
+ 0x6d, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c,
+ 0x20, 0x68, 0x65, 0x20, 0x72, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6d,
+ 0x65, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x64,
+ 0x6f, 0x6f, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x6f, 0x77,
+ 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x73, 0x65, 0x6c, 0x66, 0x20, 0x74,
+ 0x6f, 0x77, 0x61, 0x72, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4d, 0x79, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x2c, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x49, 0x20, 0x68,
+ 0x61, 0x76, 0x65, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x66, 0x61,
+ 0x76, 0x6f, 0x75, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x73, 0x69, 0x67, 0x68, 0x74, 0x2c, 0x20, 0x70, 0x61, 0x73, 0x73, 0x20,
+ 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x77, 0x61, 0x79, 0x2c, 0x20, 0x49, 0x20,
+ 0x70, 0x72, 0x61, 0x79, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x65, 0x72, 0x76,
+ 0x61, 0x6e, 0x74, 0x3a, 0x20, 0x0a, 0x4c, 0x65, 0x74, 0x20, 0x61, 0x20,
+ 0x6c, 0x69, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72,
+ 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72, 0x61, 0x79, 0x20, 0x79, 0x6f, 0x75,
+ 0x2c, 0x20, 0x62, 0x65, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x65, 0x64,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x61, 0x73, 0x68, 0x20, 0x79,
+ 0x6f, 0x75, 0x72, 0x20, 0x66, 0x65, 0x65, 0x74, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x72, 0x65, 0x73, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x73,
+ 0x65, 0x6c, 0x76, 0x65, 0x73, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x3a, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x66, 0x65,
+ 0x74, 0x63, 0x68, 0x20, 0x61, 0x20, 0x6d, 0x6f, 0x72, 0x73, 0x65, 0x6c,
+ 0x20, 0x6f, 0x66, 0x20, 0x62, 0x72, 0x65, 0x61, 0x64, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6d, 0x66, 0x6f, 0x72, 0x74, 0x20, 0x79,
+ 0x65, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x68, 0x65, 0x61, 0x72, 0x74,
+ 0x73, 0x3b, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x79, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x70,
+ 0x61, 0x73, 0x73, 0x20, 0x6f, 0x6e, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x61, 0x72,
+ 0x65, 0x20, 0x79, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x6f,
+ 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e,
+ 0x74, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x53, 0x6f, 0x20, 0x64, 0x6f, 0x2c,
+ 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73,
+ 0x74, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x68, 0x61, 0x73,
+ 0x74, 0x65, 0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4d, 0x61, 0x6b, 0x65, 0x20, 0x72,
+ 0x65, 0x61, 0x64, 0x79, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x6c, 0x79,
+ 0x20, 0x74, 0x68, 0x72, 0x65, 0x65, 0x20, 0x6d, 0x65, 0x61, 0x73, 0x75,
+ 0x72, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x69, 0x6e, 0x65, 0x20,
+ 0x6d, 0x65, 0x61, 0x6c, 0x2c, 0x20, 0x6b, 0x6e, 0x65, 0x61, 0x64, 0x20,
+ 0x69, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x6b, 0x65,
+ 0x20, 0x63, 0x61, 0x6b, 0x65, 0x73, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d,
+ 0x20, 0x72, 0x61, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x68, 0x65, 0x72, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x66, 0x65, 0x74, 0x63, 0x68, 0x74, 0x20, 0x61, 0x20, 0x63, 0x61, 0x6c,
+ 0x66, 0x20, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67,
+ 0x61, 0x76, 0x65, 0x20, 0x69, 0x74, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x61, 0x20, 0x79, 0x6f, 0x75, 0x6e, 0x67, 0x20, 0x6d, 0x61, 0x6e, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x73, 0x74,
+ 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20,
+ 0x69, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x62, 0x75, 0x74, 0x74, 0x65, 0x72, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x69, 0x6c, 0x6b, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x66, 0x20,
+ 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64,
+ 0x20, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x65, 0x74, 0x20, 0x69, 0x74, 0x20, 0x62, 0x65, 0x66,
+ 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x6f, 0x64, 0x20, 0x62,
+ 0x79, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x64, 0x69, 0x64, 0x20,
+ 0x65, 0x61, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x57, 0x68, 0x65, 0x72, 0x65, 0x20,
+ 0x69, 0x73, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x74, 0x68, 0x79,
+ 0x20, 0x77, 0x69, 0x66, 0x65, 0x3f, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f,
+ 0x6c, 0x64, 0x2c, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
+ 0x65, 0x6e, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c,
+ 0x6c, 0x20, 0x63, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6e, 0x6c, 0x79, 0x20,
+ 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69,
+ 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x69,
+ 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x3b, 0x20,
+ 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x6c, 0x6f, 0x2c, 0x20, 0x53, 0x61, 0x72,
+ 0x61, 0x68, 0x20, 0x74, 0x68, 0x79, 0x20, 0x77, 0x69, 0x66, 0x65, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x61,
+ 0x20, 0x73, 0x6f, 0x6e, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x61,
+ 0x72, 0x61, 0x68, 0x20, 0x68, 0x65, 0x61, 0x72, 0x64, 0x20, 0x69, 0x74,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x65, 0x6e, 0x74,
+ 0x20, 0x64, 0x6f, 0x6f, 0x72, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x62, 0x65, 0x68, 0x69, 0x6e, 0x64, 0x20,
+ 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x4e, 0x6f, 0x77, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x61,
+ 0x72, 0x61, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6f, 0x6c, 0x64,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x73, 0x74,
+ 0x72, 0x69, 0x63, 0x6b, 0x65, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x67,
+ 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x65,
+ 0x61, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x61, 0x66,
+ 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x6e,
+ 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x77, 0x6f, 0x6d, 0x65, 0x6e, 0x2e,
+ 0x20, 0x0a, 0x54, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20,
+ 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x6c, 0x61, 0x75, 0x67, 0x68, 0x65,
+ 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x68, 0x65, 0x72,
+ 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67,
+ 0x2c, 0x20, 0x41, 0x66, 0x74, 0x65, 0x72, 0x20, 0x49, 0x20, 0x61, 0x6d,
+ 0x20, 0x77, 0x61, 0x78, 0x65, 0x64, 0x20, 0x6f, 0x6c, 0x64, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20,
+ 0x70, 0x6c, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x6d, 0x79,
+ 0x20, 0x6c, 0x6f, 0x72, 0x64, 0x20, 0x62, 0x65, 0x69, 0x6e, 0x67, 0x20,
+ 0x6f, 0x6c, 0x64, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x3f, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x57, 0x68, 0x65, 0x72, 0x65,
+ 0x66, 0x6f, 0x72, 0x65, 0x20, 0x64, 0x69, 0x64, 0x20, 0x53, 0x61, 0x72,
+ 0x61, 0x68, 0x20, 0x6c, 0x61, 0x75, 0x67, 0x68, 0x2c, 0x20, 0x73, 0x61,
+ 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x53, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x49, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x73, 0x75, 0x72, 0x65, 0x74,
+ 0x79, 0x20, 0x62, 0x65, 0x61, 0x72, 0x20, 0x61, 0x20, 0x63, 0x68, 0x69,
+ 0x6c, 0x64, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, 0x6d,
+ 0x20, 0x6f, 0x6c, 0x64, 0x3f, 0x20, 0x0a, 0x49, 0x73, 0x20, 0x61, 0x6e,
+ 0x79, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x6f, 0x20,
+ 0x68, 0x61, 0x72, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x3f, 0x20, 0x41, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x61, 0x70, 0x70, 0x6f, 0x69,
+ 0x6e, 0x74, 0x65, 0x64, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64,
+ 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
+ 0x69, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x61, 0x20,
+ 0x73, 0x6f, 0x6e, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x6e, 0x20, 0x53,
+ 0x61, 0x72, 0x61, 0x68, 0x20, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, 0x2c,
+ 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x49, 0x20, 0x6c,
+ 0x61, 0x75, 0x67, 0x68, 0x65, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x3b, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x73, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x61, 0x66, 0x72, 0x61, 0x69, 0x64, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4e, 0x61, 0x79,
+ 0x3b, 0x20, 0x62, 0x75, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x64,
+ 0x69, 0x64, 0x73, 0x74, 0x20, 0x6c, 0x61, 0x75, 0x67, 0x68, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e,
+ 0x20, 0x72, 0x6f, 0x73, 0x65, 0x20, 0x75, 0x70, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x77,
+ 0x61, 0x72, 0x64, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x77,
+ 0x65, 0x6e, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65,
+ 0x6d, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20,
+ 0x53, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x49, 0x20, 0x68, 0x69, 0x64, 0x65,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61,
+ 0x6d, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x49, 0x20, 0x64, 0x6f, 0x3b,
+ 0x20, 0x0a, 0x53, 0x65, 0x65, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x73, 0x75, 0x72, 0x65, 0x6c, 0x79, 0x20, 0x62,
+ 0x65, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x61, 0x20, 0x67, 0x72, 0x65, 0x61,
+ 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x79,
+ 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x62, 0x65, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x69,
+ 0x6e, 0x20, 0x68, 0x69, 0x6d, 0x3f, 0x20, 0x0a, 0x46, 0x6f, 0x72, 0x20,
+ 0x49, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x68,
+ 0x6f, 0x6c, 0x64, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x77, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x64,
+ 0x6f, 0x20, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x63, 0x65, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6a, 0x75, 0x64, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x3b, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x68, 0x65, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x73, 0x70, 0x6f, 0x6b,
+ 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x63, 0x61, 0x75,
+ 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x72, 0x79, 0x20, 0x6f,
+ 0x66, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x47, 0x6f, 0x6d, 0x6f, 0x72, 0x72, 0x61, 0x68, 0x20, 0x69, 0x73, 0x20,
+ 0x67, 0x72, 0x65, 0x61, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72,
+ 0x20, 0x73, 0x69, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x67, 0x72, 0x69, 0x65, 0x76, 0x6f, 0x75, 0x73, 0x3b, 0x20, 0x0a,
+ 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x67, 0x6f, 0x20, 0x64, 0x6f,
+ 0x77, 0x6e, 0x20, 0x6e, 0x6f, 0x77, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x73, 0x65, 0x65, 0x20, 0x77, 0x68, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x64, 0x6f,
+ 0x6e, 0x65, 0x20, 0x61, 0x6c, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65,
+ 0x72, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x72, 0x79, 0x20, 0x6f,
+ 0x66, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x69, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x6d, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x66, 0x20,
+ 0x6e, 0x6f, 0x74, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x6b, 0x6e, 0x6f, 0x77, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x74, 0x75, 0x72, 0x6e, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x66, 0x61, 0x63, 0x65,
+ 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x63,
+ 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20,
+ 0x74, 0x6f, 0x77, 0x61, 0x72, 0x64, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d,
+ 0x3a, 0x20, 0x62, 0x75, 0x74, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61,
+ 0x6d, 0x20, 0x73, 0x74, 0x6f, 0x6f, 0x64, 0x20, 0x79, 0x65, 0x74, 0x20,
+ 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x64, 0x72, 0x65, 0x77, 0x20, 0x6e,
+ 0x65, 0x61, 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x57, 0x69, 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f,
+ 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x65,
+ 0x6f, 0x75, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x3f, 0x20, 0x0a, 0x50, 0x65,
+ 0x72, 0x61, 0x64, 0x76, 0x65, 0x6e, 0x74, 0x75, 0x72, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x66, 0x69, 0x66, 0x74,
+ 0x79, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x65, 0x6f, 0x75, 0x73, 0x20,
+ 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x69, 0x74, 0x79, 0x3a, 0x20, 0x77, 0x69, 0x6c, 0x74, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x64, 0x65, 0x73, 0x74,
+ 0x72, 0x6f, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x73, 0x70, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c,
+ 0x61, 0x63, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x69, 0x66, 0x74, 0x79, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x65,
+ 0x6f, 0x75, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x3f, 0x20, 0x0a, 0x54,
+ 0x68, 0x61, 0x74, 0x20, 0x62, 0x65, 0x20, 0x66, 0x61, 0x72, 0x20, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x74, 0x6f, 0x20,
+ 0x64, 0x6f, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x69,
+ 0x73, 0x20, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2c, 0x20, 0x74, 0x6f,
+ 0x20, 0x73, 0x6c, 0x61, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x69,
+ 0x67, 0x68, 0x74, 0x65, 0x6f, 0x75, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x65, 0x6f, 0x75, 0x73, 0x20,
+ 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x61, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x2c,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x62, 0x65, 0x20, 0x66, 0x61, 0x72,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3a, 0x20,
+ 0x53, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x4a, 0x75, 0x64, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x20, 0x64, 0x6f, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3f, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20,
+ 0x66, 0x69, 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x53, 0x6f, 0x64, 0x6f,
+ 0x6d, 0x20, 0x66, 0x69, 0x66, 0x74, 0x79, 0x20, 0x72, 0x69, 0x67, 0x68,
+ 0x74, 0x65, 0x6f, 0x75, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x74,
+ 0x68, 0x65, 0x6e, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x73,
+ 0x70, 0x61, 0x72, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x69, 0x72, 0x20, 0x73, 0x61, 0x6b, 0x65, 0x73, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d,
+ 0x20, 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f,
+ 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x77, 0x2c, 0x20, 0x49, 0x20, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x75, 0x70, 0x6f,
+ 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x70, 0x65, 0x61,
+ 0x6b, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
+ 0x6d, 0x20, 0x62, 0x75, 0x74, 0x20, 0x64, 0x75, 0x73, 0x74, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x61, 0x73, 0x68, 0x65, 0x73, 0x3a, 0x20, 0x0a, 0x50,
+ 0x65, 0x72, 0x61, 0x64, 0x76, 0x65, 0x6e, 0x74, 0x75, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x6c, 0x61, 0x63, 0x6b, 0x20, 0x66, 0x69, 0x76, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x66, 0x74, 0x79, 0x20, 0x72,
+ 0x69, 0x67, 0x68, 0x74, 0x65, 0x6f, 0x75, 0x73, 0x3a, 0x20, 0x77, 0x69,
+ 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x64, 0x65, 0x73, 0x74,
+ 0x72, 0x6f, 0x79, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x63, 0x69, 0x74, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6c, 0x61, 0x63,
+ 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x69, 0x76, 0x65, 0x3f, 0x20, 0x41,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20,
+ 0x49, 0x66, 0x20, 0x49, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x72, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x79, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x66, 0x69, 0x76, 0x65, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69,
+ 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72,
+ 0x6f, 0x79, 0x20, 0x69, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x70, 0x61, 0x6b, 0x65, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x79, 0x65, 0x74, 0x20, 0x61, 0x67,
+ 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x50, 0x65, 0x72, 0x61, 0x64, 0x76, 0x65, 0x6e, 0x74,
+ 0x75, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x73, 0x68,
+ 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x79,
+ 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65,
+ 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6e, 0x6f,
+ 0x74, 0x20, 0x64, 0x6f, 0x20, 0x69, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x66, 0x6f, 0x72, 0x74, 0x79, 0x27, 0x73, 0x20, 0x73, 0x61, 0x6b, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c,
+ 0x20, 0x4f, 0x68, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x62, 0x65, 0x20,
+ 0x61, 0x6e, 0x67, 0x72, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49,
+ 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x73, 0x70, 0x65, 0x61, 0x6b, 0x3a,
+ 0x20, 0x50, 0x65, 0x72, 0x61, 0x64, 0x76, 0x65, 0x6e, 0x74, 0x75, 0x72,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79, 0x20, 0x62, 0x65, 0x20,
+ 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x2e,
+ 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74,
+ 0x20, 0x64, 0x6f, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x69, 0x66, 0x20, 0x49,
+ 0x20, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x72, 0x74, 0x79,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65,
+ 0x68, 0x6f, 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x77, 0x2c, 0x20, 0x49, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x75,
+ 0x70, 0x6f, 0x6e, 0x20, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x70,
+ 0x65, 0x61, 0x6b, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x3a, 0x20, 0x50, 0x65, 0x72, 0x61, 0x64,
+ 0x76, 0x65, 0x6e, 0x74, 0x75, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x72,
+ 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x74,
+ 0x77, 0x65, 0x6e, 0x74, 0x79, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x77, 0x69,
+ 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72,
+ 0x6f, 0x79, 0x20, 0x69, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x77,
+ 0x65, 0x6e, 0x74, 0x79, 0x27, 0x73, 0x20, 0x73, 0x61, 0x6b, 0x65, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x4f, 0x68, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x6e, 0x6f,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x62,
+ 0x65, 0x20, 0x61, 0x6e, 0x67, 0x72, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x73, 0x70, 0x65, 0x61,
+ 0x6b, 0x20, 0x79, 0x65, 0x74, 0x20, 0x62, 0x75, 0x74, 0x20, 0x74, 0x68,
+ 0x69, 0x73, 0x20, 0x6f, 0x6e, 0x63, 0x65, 0x3a, 0x20, 0x50, 0x65, 0x72,
+ 0x61, 0x64, 0x76, 0x65, 0x6e, 0x74, 0x75, 0x72, 0x65, 0x20, 0x74, 0x65,
+ 0x6e, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x66,
+ 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x2e, 0x20,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x20, 0x69, 0x74, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x74, 0x65, 0x6e, 0x27, 0x73, 0x20, 0x73, 0x61, 0x6b,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x61, 0x79, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x73, 0x6f,
+ 0x6f, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64,
+ 0x20, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e,
+ 0x69, 0x6e, 0x67, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x68, 0x61, 0x6d, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
+ 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74,
+ 0x77, 0x6f, 0x20, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x73, 0x20, 0x74, 0x6f,
+ 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x20, 0x61, 0x74, 0x20, 0x65, 0x76,
+ 0x65, 0x6e, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x6f, 0x74, 0x20,
+ 0x73, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67,
+ 0x61, 0x74, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d,
+ 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x73, 0x65,
+ 0x65, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x72, 0x6f,
+ 0x73, 0x65, 0x20, 0x75, 0x70, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x65,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x62, 0x6f, 0x77, 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d,
+ 0x73, 0x65, 0x6c, 0x66, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x74, 0x6f, 0x77, 0x61, 0x72,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64,
+ 0x3b, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x20, 0x6e,
+ 0x6f, 0x77, 0x2c, 0x20, 0x6d, 0x79, 0x20, 0x6c, 0x6f, 0x72, 0x64, 0x73,
+ 0x2c, 0x20, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x69, 0x6e, 0x2c, 0x20, 0x49,
+ 0x20, 0x70, 0x72, 0x61, 0x79, 0x20, 0x79, 0x6f, 0x75, 0x2c, 0x20, 0x69,
+ 0x6e, 0x74, 0x6f, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x65, 0x72,
+ 0x76, 0x61, 0x6e, 0x74, 0x27, 0x73, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x61, 0x72, 0x72, 0x79, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x77, 0x61, 0x73, 0x68, 0x20, 0x79, 0x6f, 0x75, 0x72,
+ 0x20, 0x66, 0x65, 0x65, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79,
+ 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x72, 0x69, 0x73, 0x65,
+ 0x20, 0x75, 0x70, 0x20, 0x65, 0x61, 0x72, 0x6c, 0x79, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x67, 0x6f, 0x20, 0x6f, 0x6e, 0x20, 0x79, 0x6f, 0x75,
+ 0x72, 0x20, 0x77, 0x61, 0x79, 0x73, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4e,
+ 0x61, 0x79, 0x3b, 0x20, 0x62, 0x75, 0x74, 0x20, 0x77, 0x65, 0x20, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x61, 0x62, 0x69, 0x64, 0x65, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x72, 0x65, 0x65, 0x74, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x70, 0x72, 0x65, 0x73, 0x73,
+ 0x65, 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x6c, 0x79, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x74, 0x75, 0x72, 0x6e, 0x65,
+ 0x64, 0x20, 0x69, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6e, 0x74, 0x65, 0x72,
+ 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x68, 0x6f, 0x75, 0x73, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20,
+ 0x61, 0x20, 0x66, 0x65, 0x61, 0x73, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x64, 0x69, 0x64, 0x20, 0x62, 0x61, 0x6b, 0x65, 0x20, 0x75, 0x6e,
+ 0x6c, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x72, 0x65,
+ 0x61, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x64, 0x69, 0x64, 0x20, 0x65, 0x61, 0x74, 0x2e, 0x20, 0x0a, 0x42,
+ 0x75, 0x74, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x79, 0x20, 0x6c, 0x61, 0x79, 0x20, 0x64, 0x6f, 0x77, 0x6e, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x63, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x65, 0x76,
+ 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x6f,
+ 0x66, 0x20, 0x53, 0x6f, 0x64, 0x6f, 0x6d, 0x2c, 0x20, 0x63, 0x6f, 0x6d,
+ 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68,
+ 0x6f, 0x75, 0x73, 0x65, 0x20, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2c, 0x20,
+ 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6f, 0x6c, 0x64, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x79, 0x6f, 0x75, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x70, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x20, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x71, 0x75,
+ 0x61, 0x72, 0x74, 0x65, 0x72, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4c, 0x6f, 0x74, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x57, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61,
+ 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x74, 0x68, 0x69,
+ 0x73, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x3f, 0x20, 0x62, 0x72, 0x69,
+ 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x6f, 0x75, 0x74, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x75, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x6b, 0x6e, 0x6f,
+ 0x77, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x75,
+ 0x74, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x6f, 0x6f,
+ 0x72, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x75, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x6f, 0x6f, 0x72, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72, 0x61, 0x79, 0x20,
+ 0x79, 0x6f, 0x75, 0x2c, 0x20, 0x62, 0x72, 0x65, 0x74, 0x68, 0x72, 0x65,
+ 0x6e, 0x2c, 0x20, 0x64, 0x6f, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x6f,
+ 0x20, 0x77, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x6c, 0x79, 0x2e, 0x20, 0x0a,
+ 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x77, 0x2c, 0x20,
+ 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x64,
+ 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x6d, 0x61, 0x6e, 0x3b, 0x20, 0x6c,
+ 0x65, 0x74, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72, 0x61,
+ 0x79, 0x20, 0x79, 0x6f, 0x75, 0x2c, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x75, 0x6e,
+ 0x74, 0x6f, 0x20, 0x79, 0x6f, 0x75, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x64, 0x6f, 0x20, 0x79, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x6d, 0x20, 0x61, 0x73, 0x20, 0x69, 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64,
+ 0x20, 0x69, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x65, 0x79, 0x65,
+ 0x73, 0x3a, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x64,
+ 0x6f, 0x20, 0x6e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x3b, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65,
+ 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x75,
+ 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x68, 0x61,
+ 0x64, 0x6f, 0x77, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x72, 0x6f,
+ 0x6f, 0x66, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x79, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x53, 0x74, 0x61, 0x6e,
+ 0x64, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x61, 0x67,
+ 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x6e,
+ 0x65, 0x20, 0x66, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x63, 0x61, 0x6d,
+ 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x6f, 0x6a, 0x6f,
+ 0x75, 0x72, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x20, 0x62,
+ 0x65, 0x20, 0x61, 0x20, 0x6a, 0x75, 0x64, 0x67, 0x65, 0x3a, 0x20, 0x6e,
+ 0x6f, 0x77, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x77, 0x65, 0x20, 0x64,
+ 0x65, 0x61, 0x6c, 0x20, 0x77, 0x6f, 0x72, 0x73, 0x65, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x61,
+ 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2e,
+ 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x70, 0x72,
+ 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x73, 0x6f, 0x72, 0x65, 0x20, 0x75,
+ 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x2c,
+ 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x4c, 0x6f, 0x74, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x6e, 0x65, 0x61, 0x72,
+ 0x20, 0x74, 0x6f, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x6f, 0x6f, 0x72, 0x2e, 0x20, 0x0a, 0x42, 0x75, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x70, 0x75, 0x74,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72,
+ 0x20, 0x68, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70,
+ 0x75, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x69, 0x6e,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65,
+ 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x73, 0x68, 0x75, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x6f, 0x6f, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x6d, 0x6f, 0x74, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x64, 0x6f, 0x6f, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x62, 0x6c, 0x69, 0x6e, 0x64, 0x6e, 0x65, 0x73, 0x73, 0x2c, 0x20, 0x62,
+ 0x6f, 0x74, 0x68, 0x20, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x3a, 0x20, 0x73, 0x6f, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x65,
+ 0x61, 0x72, 0x69, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x73, 0x65,
+ 0x6c, 0x76, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x69, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x6f, 0x6f, 0x72, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x4c, 0x6f,
+ 0x74, 0x2c, 0x20, 0x48, 0x61, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x62, 0x65,
+ 0x73, 0x69, 0x64, 0x65, 0x73, 0x3f, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x69,
+ 0x6e, 0x20, 0x6c, 0x61, 0x77, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65,
+ 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x61, 0x74,
+ 0x73, 0x6f, 0x65, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x68, 0x61, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x63, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x69, 0x73, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x3a, 0x20,
+ 0x0a, 0x46, 0x6f, 0x72, 0x20, 0x77, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c,
+ 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x20, 0x74, 0x68, 0x69,
+ 0x73, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c, 0x20, 0x62, 0x65, 0x63,
+ 0x61, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x72, 0x79,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x69, 0x73, 0x20,
+ 0x77, 0x61, 0x78, 0x65, 0x6e, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20,
+ 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x73,
+ 0x65, 0x6e, 0x74, 0x20, 0x75, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x65,
+ 0x73, 0x74, 0x72, 0x6f, 0x79, 0x20, 0x69, 0x74, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20,
+ 0x6f, 0x75, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x70, 0x61,
+ 0x6b, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x61, 0x77, 0x2c,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x6d, 0x61, 0x72, 0x72, 0x69,
+ 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68,
+ 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x2c, 0x20, 0x55, 0x70, 0x2c, 0x20, 0x67, 0x65, 0x74, 0x20,
+ 0x79, 0x6f, 0x75, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x69, 0x73, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x3b, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x64, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79,
+ 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x63, 0x69, 0x74, 0x79, 0x2e, 0x20,
+ 0x42, 0x75, 0x74, 0x20, 0x68, 0x65, 0x20, 0x73, 0x65, 0x65, 0x6d, 0x65,
+ 0x64, 0x20, 0x61, 0x73, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x6d, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x73, 0x20, 0x69,
+ 0x6e, 0x20, 0x6c, 0x61, 0x77, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72,
+ 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x72, 0x6f, 0x73, 0x65, 0x2c, 0x20,
+ 0x74, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6e, 0x67,
+ 0x65, 0x6c, 0x73, 0x20, 0x68, 0x61, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x64,
+ 0x20, 0x4c, 0x6f, 0x74, 0x2c, 0x20, 0x73, 0x61, 0x79, 0x69, 0x6e, 0x67,
+ 0x2c, 0x20, 0x41, 0x72, 0x69, 0x73, 0x65, 0x2c, 0x20, 0x74, 0x61, 0x6b,
+ 0x65, 0x20, 0x74, 0x68, 0x79, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x79, 0x20, 0x74, 0x77, 0x6f, 0x20,
+ 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, 0x72, 0x65, 0x20, 0x68, 0x65, 0x72,
+ 0x65, 0x3b, 0x20, 0x6c, 0x65, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x62, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x69, 0x71,
+ 0x75, 0x69, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x63, 0x69, 0x74, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x77,
+ 0x68, 0x69, 0x6c, 0x65, 0x20, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x6e, 0x67,
+ 0x65, 0x72, 0x65, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65,
+ 0x6e, 0x20, 0x6c, 0x61, 0x69, 0x64, 0x20, 0x68, 0x6f, 0x6c, 0x64, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x68, 0x61, 0x6e,
+ 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x74,
+ 0x77, 0x6f, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73,
+ 0x3b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x62,
+ 0x65, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x65, 0x72, 0x63, 0x69, 0x66, 0x75,
+ 0x6c, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x62, 0x72, 0x6f,
+ 0x75, 0x67, 0x68, 0x74, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x66, 0x6f, 0x72,
+ 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x74, 0x20,
+ 0x68, 0x69, 0x6d, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x63, 0x69, 0x74, 0x79, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74,
+ 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x68, 0x61, 0x64, 0x20, 0x62, 0x72,
+ 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x66,
+ 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x2c,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x2c, 0x20, 0x45, 0x73, 0x63, 0x61, 0x70, 0x65, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x3b, 0x20,
+ 0x6c, 0x6f, 0x6f, 0x6b, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x68,
+ 0x69, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x6e, 0x65,
+ 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x74, 0x61, 0x79, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x3b, 0x20, 0x65, 0x73,
+ 0x63, 0x61, 0x70, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x6c, 0x65,
+ 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x62, 0x65, 0x20, 0x63,
+ 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x4f, 0x68,
+ 0x2c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x6f, 0x2c, 0x20, 0x6d, 0x79,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x3a, 0x20, 0x0a, 0x42, 0x65, 0x68, 0x6f,
+ 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x77, 0x2c, 0x20, 0x74, 0x68, 0x79, 0x20,
+ 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x20, 0x68, 0x61, 0x74, 0x68,
+ 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x67, 0x72, 0x61, 0x63, 0x65,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73, 0x69, 0x67, 0x68,
+ 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x68, 0x61, 0x73, 0x74, 0x20, 0x6d, 0x61, 0x67, 0x6e, 0x69, 0x66, 0x69,
+ 0x65, 0x64, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6d, 0x65, 0x72, 0x63, 0x79,
+ 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x73, 0x68, 0x65, 0x77, 0x65, 0x64,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20,
+ 0x73, 0x61, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x79, 0x20, 0x6c, 0x69,
+ 0x66, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x63, 0x61,
+ 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
+ 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x6c, 0x65, 0x73, 0x74, 0x20, 0x73, 0x6f,
+ 0x6d, 0x65, 0x20, 0x65, 0x76, 0x69, 0x6c, 0x20, 0x74, 0x61, 0x6b, 0x65,
+ 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x20, 0x64,
+ 0x69, 0x65, 0x3a, 0x20, 0x0a, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x20,
+ 0x6e, 0x6f, 0x77, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x63, 0x69,
+ 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x65, 0x61, 0x72, 0x20, 0x74,
+ 0x6f, 0x20, 0x66, 0x6c, 0x65, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x61,
+ 0x20, 0x6c, 0x69, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x3a,
+ 0x20, 0x4f, 0x68, 0x2c, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x6d, 0x65, 0x20,
+ 0x65, 0x73, 0x63, 0x61, 0x70, 0x65, 0x20, 0x74, 0x68, 0x69, 0x74, 0x68,
+ 0x65, 0x72, 0x2c, 0x20, 0x28, 0x69, 0x73, 0x20, 0x69, 0x74, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x61, 0x20, 0x6c, 0x69, 0x74, 0x74, 0x6c, 0x65, 0x20,
+ 0x6f, 0x6e, 0x65, 0x3f, 0x29, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x79,
+ 0x20, 0x73, 0x6f, 0x75, 0x6c, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x6c, 0x69, 0x76, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68,
+ 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x53, 0x65, 0x65, 0x2c, 0x20, 0x49, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65,
+ 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x74,
+ 0x68, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x2c, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x74, 0x68, 0x72, 0x6f, 0x77,
+ 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x63, 0x69, 0x74, 0x79, 0x2c, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x69, 0x63,
+ 0x68, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20,
+ 0x73, 0x70, 0x6f, 0x6b, 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x48, 0x61, 0x73,
+ 0x74, 0x65, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x65, 0x73, 0x63,
+ 0x61, 0x70, 0x65, 0x20, 0x74, 0x68, 0x69, 0x74, 0x68, 0x65, 0x72, 0x3b,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x49, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
+ 0x74, 0x20, 0x64, 0x6f, 0x20, 0x61, 0x6e, 0x79, 0x74, 0x68, 0x69, 0x6e,
+ 0x67, 0x20, 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x62, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x68, 0x69, 0x74,
+ 0x68, 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f,
+ 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x69, 0x74, 0x79, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x5a,
+ 0x6f, 0x61, 0x72, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x73, 0x75,
+ 0x6e, 0x20, 0x77, 0x61, 0x73, 0x20, 0x72, 0x69, 0x73, 0x65, 0x6e, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x4c, 0x6f, 0x74, 0x20,
+ 0x65, 0x6e, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f,
+ 0x20, 0x5a, 0x6f, 0x61, 0x72, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x72, 0x61,
+ 0x69, 0x6e, 0x65, 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x53, 0x6f,
+ 0x64, 0x6f, 0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x70, 0x6f, 0x6e,
+ 0x20, 0x47, 0x6f, 0x6d, 0x6f, 0x72, 0x72, 0x61, 0x68, 0x20, 0x62, 0x72,
+ 0x69, 0x6d, 0x73, 0x74, 0x6f, 0x6e, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x66, 0x69, 0x72, 0x65, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x3b, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x74, 0x68,
+ 0x72, 0x65, 0x77, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x63, 0x69,
+ 0x74, 0x69, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x69, 0x6e, 0x68, 0x61, 0x62, 0x69, 0x74, 0x61, 0x6e, 0x74, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x69, 0x74, 0x69,
+ 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x67, 0x72, 0x65, 0x77, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f,
+ 0x75, 0x6e, 0x64, 0x2e, 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x65,
+ 0x64, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x62, 0x65, 0x68, 0x69, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x62, 0x65, 0x63, 0x61,
+ 0x6d, 0x65, 0x20, 0x61, 0x20, 0x70, 0x69, 0x6c, 0x6c, 0x61, 0x72, 0x20,
+ 0x6f, 0x66, 0x20, 0x73, 0x61, 0x6c, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x67, 0x61,
+ 0x74, 0x20, 0x75, 0x70, 0x20, 0x65, 0x61, 0x72, 0x6c, 0x79, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61,
+ 0x63, 0x65, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x68, 0x65, 0x20,
+ 0x73, 0x74, 0x6f, 0x6f, 0x64, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x3a, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x65,
+ 0x64, 0x20, 0x74, 0x6f, 0x77, 0x61, 0x72, 0x64, 0x20, 0x53, 0x6f, 0x64,
+ 0x6f, 0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x6d, 0x6f, 0x72,
+ 0x72, 0x61, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x77,
+ 0x61, 0x72, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x68, 0x65, 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20,
+ 0x6c, 0x6f, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6d, 0x6f, 0x6b,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x75,
+ 0x6e, 0x74, 0x72, 0x79, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x70,
+ 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6d, 0x6f, 0x6b,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x66, 0x75, 0x72, 0x6e, 0x61,
+ 0x63, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20,
+ 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73,
+ 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x64,
+ 0x65, 0x73, 0x74, 0x72, 0x6f, 0x79, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x63, 0x69, 0x74, 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x72, 0x65, 0x6d, 0x65, 0x6d,
+ 0x62, 0x65, 0x72, 0x65, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x65, 0x6e, 0x74, 0x20,
+ 0x4c, 0x6f, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6d, 0x69, 0x64, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x74, 0x68, 0x72, 0x6f,
+ 0x77, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x68, 0x65, 0x20, 0x6f,
+ 0x76, 0x65, 0x72, 0x74, 0x68, 0x72, 0x65, 0x77, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x63, 0x69, 0x74, 0x69, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x4c, 0x6f, 0x74,
+ 0x20, 0x64, 0x77, 0x65, 0x6c, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x4c, 0x6f, 0x74, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x70,
+ 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x5a, 0x6f, 0x61, 0x72,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x74, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
+ 0x61, 0x69, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x74, 0x77, 0x6f, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65,
+ 0x72, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x3b,
+ 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68, 0x65, 0x20, 0x66, 0x65, 0x61, 0x72,
+ 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x20,
+ 0x69, 0x6e, 0x20, 0x5a, 0x6f, 0x61, 0x72, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x74, 0x20, 0x69, 0x6e,
+ 0x20, 0x61, 0x20, 0x63, 0x61, 0x76, 0x65, 0x2c, 0x20, 0x68, 0x65, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x74, 0x77, 0x6f, 0x20,
+ 0x64, 0x61, 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73,
+ 0x74, 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x79, 0x6f, 0x75, 0x6e,
+ 0x67, 0x65, 0x72, 0x2c, 0x20, 0x4f, 0x75, 0x72, 0x20, 0x66, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20,
+ 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x75, 0x73, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x20,
+ 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20, 0x0a, 0x43, 0x6f, 0x6d, 0x65, 0x2c,
+ 0x20, 0x6c, 0x65, 0x74, 0x20, 0x75, 0x73, 0x20, 0x6d, 0x61, 0x6b, 0x65,
+ 0x20, 0x6f, 0x75, 0x72, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x64, 0x72, 0x69, 0x6e, 0x6b, 0x20, 0x77, 0x69, 0x6e, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x6c, 0x69, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x65, 0x20, 0x6d, 0x61,
+ 0x79, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x20, 0x73,
+ 0x65, 0x65, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x6f, 0x75, 0x72, 0x20, 0x66,
+ 0x61, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x69, 0x72, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x64,
+ 0x72, 0x69, 0x6e, 0x6b, 0x20, 0x77, 0x69, 0x6e, 0x65, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x62,
+ 0x6f, 0x72, 0x6e, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x61, 0x79, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x68, 0x65, 0x72, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x70, 0x65, 0x72,
+ 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x77,
+ 0x68, 0x65, 0x6e, 0x20, 0x73, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x79, 0x20,
+ 0x64, 0x6f, 0x77, 0x6e, 0x2c, 0x20, 0x6e, 0x6f, 0x72, 0x20, 0x77, 0x68,
+ 0x65, 0x6e, 0x20, 0x73, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6f, 0x73, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61,
+ 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73, 0x73, 0x20, 0x6f,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x72, 0x6f, 0x77,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x69, 0x72, 0x73, 0x74, 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x79,
+ 0x6f, 0x75, 0x6e, 0x67, 0x65, 0x72, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f,
+ 0x6c, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x6c, 0x61, 0x79, 0x20, 0x79, 0x65,
+ 0x73, 0x74, 0x65, 0x72, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x6d, 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72,
+ 0x3a, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x75, 0x73, 0x20, 0x6d, 0x61, 0x6b,
+ 0x65, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x64, 0x72, 0x69, 0x6e, 0x6b, 0x20,
+ 0x77, 0x69, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x3b, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x67, 0x6f, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x69, 0x6e,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x69, 0x65, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x70, 0x72, 0x65, 0x73,
+ 0x65, 0x72, 0x76, 0x65, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x6f, 0x66,
+ 0x20, 0x6f, 0x75, 0x72, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x6d,
+ 0x61, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x66, 0x61,
+ 0x74, 0x68, 0x65, 0x72, 0x20, 0x64, 0x72, 0x69, 0x6e, 0x6b, 0x20, 0x77,
+ 0x69, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6e, 0x69, 0x67,
+ 0x68, 0x74, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x79, 0x6f, 0x75, 0x6e, 0x67, 0x65, 0x72,
+ 0x20, 0x61, 0x72, 0x6f, 0x73, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6c, 0x61, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x69, 0x6d,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x70, 0x65, 0x72,
+ 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x77,
+ 0x68, 0x65, 0x6e, 0x20, 0x73, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x79, 0x20,
+ 0x64, 0x6f, 0x77, 0x6e, 0x2c, 0x20, 0x6e, 0x6f, 0x72, 0x20, 0x77, 0x68,
+ 0x65, 0x6e, 0x20, 0x73, 0x68, 0x65, 0x20, 0x61, 0x72, 0x6f, 0x73, 0x65,
+ 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x75, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61,
+ 0x75, 0x67, 0x68, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x4c,
+ 0x6f, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x63, 0x68, 0x69, 0x6c,
+ 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x66,
+ 0x61, 0x74, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x62, 0x6f,
+ 0x72, 0x6e, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20, 0x61, 0x20, 0x73, 0x6f,
+ 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x4d,
+ 0x6f, 0x61, 0x62, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d,
+ 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4d,
+ 0x6f, 0x61, 0x62, 0x69, 0x74, 0x65, 0x73, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x79, 0x6f, 0x75, 0x6e,
+ 0x67, 0x65, 0x72, 0x2c, 0x20, 0x73, 0x68, 0x65, 0x20, 0x61, 0x6c, 0x73,
+ 0x6f, 0x20, 0x62, 0x61, 0x72, 0x65, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6e,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x42, 0x65,
+ 0x6e, 0x61, 0x6d, 0x6d, 0x69, 0x3a, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x6d, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20, 0x6f, 0x66,
+ 0x20, 0x41, 0x6d, 0x6d, 0x6f, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x69, 0x73, 0x20, 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x6a,
+ 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x74, 0x6f, 0x77,
+ 0x61, 0x72, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x75, 0x74,
+ 0x68, 0x20, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x62,
+ 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, 0x4b, 0x61, 0x64, 0x65, 0x73,
+ 0x68, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x53, 0x68, 0x75, 0x72, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x6f, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x65,
+ 0x64, 0x20, 0x69, 0x6e, 0x20, 0x47, 0x65, 0x72, 0x61, 0x72, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x53, 0x61, 0x72,
+ 0x61, 0x68, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2c,
+ 0x20, 0x53, 0x68, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x79, 0x20, 0x73,
+ 0x69, 0x73, 0x74, 0x65, 0x72, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x41,
+ 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68, 0x20, 0x6b, 0x69, 0x6e,
+ 0x67, 0x20, 0x6f, 0x66, 0x20, 0x47, 0x65, 0x72, 0x61, 0x72, 0x20, 0x73,
+ 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x6f,
+ 0x6b, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x2e, 0x20, 0x0a, 0x42, 0x75,
+ 0x74, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74,
+ 0x6f, 0x20, 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68, 0x20,
+ 0x69, 0x6e, 0x20, 0x61, 0x20, 0x64, 0x72, 0x65, 0x61, 0x6d, 0x20, 0x62,
+ 0x79, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d,
+ 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x20, 0x61, 0x72, 0x74, 0x20, 0x62, 0x75, 0x74, 0x20, 0x61,
+ 0x20, 0x64, 0x65, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x68, 0x61, 0x73, 0x74, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x3b, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x73, 0x68, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61,
+ 0x20, 0x6d, 0x61, 0x6e, 0x27, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2e,
+ 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c,
+ 0x65, 0x63, 0x68, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x6e, 0x65, 0x61, 0x72, 0x20, 0x68, 0x65,
+ 0x72, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x2c, 0x20, 0x77, 0x69,
+ 0x6c, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x6c, 0x61, 0x79,
+ 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x61, 0x20, 0x72, 0x69, 0x67, 0x68,
+ 0x74, 0x65, 0x6f, 0x75, 0x73, 0x20, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x3f, 0x20, 0x0a, 0x53, 0x61, 0x69, 0x64, 0x20, 0x68, 0x65, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x2c, 0x20,
+ 0x53, 0x68, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x79, 0x20, 0x73, 0x69,
+ 0x73, 0x74, 0x65, 0x72, 0x3f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68,
+ 0x65, 0x2c, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x73, 0x68, 0x65, 0x20,
+ 0x68, 0x65, 0x72, 0x73, 0x65, 0x6c, 0x66, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x48, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x79, 0x20, 0x62,
+ 0x72, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x3a, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x69, 0x74, 0x79,
+ 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x68, 0x65, 0x61, 0x72, 0x74,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x6e, 0x6f, 0x63, 0x65, 0x6e,
+ 0x63, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x68, 0x61, 0x6e,
+ 0x64, 0x73, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x49, 0x20, 0x64, 0x6f,
+ 0x6e, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e,
+ 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x61,
+ 0x20, 0x64, 0x72, 0x65, 0x61, 0x6d, 0x2c, 0x20, 0x59, 0x65, 0x61, 0x2c,
+ 0x20, 0x49, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x64, 0x69, 0x64, 0x73, 0x74, 0x20,
+ 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x69, 0x74, 0x79, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x79, 0x20, 0x68, 0x65, 0x61, 0x72, 0x74, 0x3b, 0x20,
+ 0x66, 0x6f, 0x72, 0x20, 0x49, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x77,
+ 0x69, 0x74, 0x68, 0x68, 0x65, 0x6c, 0x64, 0x20, 0x74, 0x68, 0x65, 0x65,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x73, 0x69, 0x6e, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x73, 0x74, 0x20, 0x6d, 0x65,
+ 0x3a, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20,
+ 0x73, 0x75, 0x66, 0x66, 0x65, 0x72, 0x65, 0x64, 0x20, 0x49, 0x20, 0x74,
+ 0x68, 0x65, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74,
+ 0x6f, 0x75, 0x63, 0x68, 0x20, 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x4e,
+ 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65,
+ 0x20, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66,
+ 0x65, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x68, 0x65, 0x20, 0x69, 0x73,
+ 0x20, 0x61, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x68, 0x65, 0x74, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c,
+ 0x20, 0x70, 0x72, 0x61, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68,
+ 0x65, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x6c, 0x69, 0x76, 0x65, 0x3a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x20, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x68, 0x65, 0x72,
+ 0x20, 0x6e, 0x6f, 0x74, 0x2c, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x73, 0x75, 0x72, 0x65,
+ 0x6c, 0x79, 0x20, 0x64, 0x69, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x6f, 0x75,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x65,
+ 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65,
+ 0x20, 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68, 0x20, 0x72,
+ 0x6f, 0x73, 0x65, 0x20, 0x65, 0x61, 0x72, 0x6c, 0x79, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e, 0x67,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x65, 0x72,
+ 0x76, 0x61, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x6f, 0x6c, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x73,
+ 0x65, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x65, 0x61, 0x72, 0x73, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x65, 0x6e, 0x20,
+ 0x77, 0x65, 0x72, 0x65, 0x20, 0x73, 0x6f, 0x72, 0x65, 0x20, 0x61, 0x66,
+ 0x72, 0x61, 0x69, 0x64, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x6e, 0x20,
+ 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68, 0x20, 0x63, 0x61,
+ 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20, 0x57, 0x68, 0x61,
+ 0x74, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20,
+ 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x75, 0x73,
+ 0x3f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x68,
+ 0x61, 0x76, 0x65, 0x20, 0x49, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x6e, 0x64,
+ 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20,
+ 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x6f, 0x6e, 0x20, 0x6d,
+ 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x6d, 0x79, 0x20,
+ 0x6b, 0x69, 0x6e, 0x67, 0x64, 0x6f, 0x6d, 0x20, 0x61, 0x20, 0x67, 0x72,
+ 0x65, 0x61, 0x74, 0x20, 0x73, 0x69, 0x6e, 0x3f, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x20,
+ 0x64, 0x65, 0x65, 0x64, 0x73, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d,
+ 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6f, 0x75, 0x67, 0x68, 0x74,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x64,
+ 0x6f, 0x6e, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62,
+ 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61,
+ 0x6d, 0x2c, 0x20, 0x57, 0x68, 0x61, 0x74, 0x20, 0x73, 0x61, 0x77, 0x65,
+ 0x73, 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x2c, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x68, 0x61, 0x73, 0x74, 0x20,
+ 0x64, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x74, 0x68,
+ 0x69, 0x6e, 0x67, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62,
+ 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20,
+ 0x42, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x49, 0x20, 0x74, 0x68,
+ 0x6f, 0x75, 0x67, 0x68, 0x74, 0x2c, 0x20, 0x53, 0x75, 0x72, 0x65, 0x6c,
+ 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x65, 0x61, 0x72, 0x20, 0x6f,
+ 0x66, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x70, 0x6c, 0x61,
+ 0x63, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x73, 0x6c, 0x61, 0x79, 0x20, 0x6d,
+ 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x79, 0x20, 0x77, 0x69, 0x66,
+ 0x65, 0x27, 0x73, 0x20, 0x73, 0x61, 0x6b, 0x65, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x79, 0x65, 0x74, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x65,
+ 0x64, 0x20, 0x73, 0x68, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x79, 0x20,
+ 0x73, 0x69, 0x73, 0x74, 0x65, 0x72, 0x3b, 0x20, 0x73, 0x68, 0x65, 0x20,
+ 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68,
+ 0x74, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x66, 0x61,
+ 0x74, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6e, 0x6f,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x75, 0x67, 0x68, 0x74,
+ 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x6d, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x65,
+ 0x20, 0x62, 0x65, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x6d, 0x79, 0x20, 0x77,
+ 0x69, 0x66, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x69, 0x74,
+ 0x20, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x61, 0x73,
+ 0x73, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x63, 0x61, 0x75, 0x73, 0x65, 0x64, 0x20, 0x6d, 0x65, 0x20, 0x74, 0x6f,
+ 0x20, 0x77, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x20, 0x66, 0x72, 0x6f, 0x6d,
+ 0x20, 0x6d, 0x79, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x27, 0x73,
+ 0x20, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x49, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x65, 0x72, 0x2c, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69,
+ 0x73, 0x20, 0x74, 0x68, 0x79, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x6e, 0x65,
+ 0x73, 0x73, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x73, 0x68, 0x65, 0x77,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6d, 0x65, 0x3b, 0x20, 0x61, 0x74,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65,
+ 0x20, 0x77, 0x68, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x77, 0x65, 0x20,
+ 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x65, 0x2c, 0x20,
+ 0x73, 0x61, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x65, 0x2c, 0x20, 0x48,
+ 0x65, 0x20, 0x69, 0x73, 0x20, 0x6d, 0x79, 0x20, 0x62, 0x72, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x41, 0x62,
+ 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68, 0x20, 0x74, 0x6f, 0x6f, 0x6b,
+ 0x20, 0x73, 0x68, 0x65, 0x65, 0x70, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x78, 0x65, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x65,
+ 0x6e, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x77, 0x6f, 0x6d, 0x65, 0x6e, 0x73, 0x65, 0x72, 0x76,
+ 0x61, 0x6e, 0x74, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x61,
+ 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x68,
+ 0x69, 0x6d, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x68, 0x69, 0x73,
+ 0x20, 0x77, 0x69, 0x66, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20,
+ 0x6d, 0x79, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x73, 0x20, 0x62,
+ 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x65, 0x3a, 0x20,
+ 0x64, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20,
+ 0x69, 0x74, 0x20, 0x70, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x74, 0x68, 0x20,
+ 0x74, 0x68, 0x65, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x75,
+ 0x6e, 0x74, 0x6f, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x68, 0x65,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x2c, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x67, 0x69,
+ 0x76, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20, 0x62, 0x72, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x61, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x73, 0x61,
+ 0x6e, 0x64, 0x20, 0x70, 0x69, 0x65, 0x63, 0x65, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x73, 0x69, 0x6c, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x62, 0x65, 0x68,
+ 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x68, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x65, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x76,
+ 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x79, 0x65, 0x73, 0x2c, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x65, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6c, 0x6c,
+ 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x3a, 0x20, 0x74, 0x68, 0x75, 0x73,
+ 0x20, 0x73, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x72, 0x65, 0x70,
+ 0x72, 0x6f, 0x76, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x53, 0x6f, 0x20, 0x41,
+ 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x70, 0x72, 0x61, 0x79, 0x65,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x47, 0x6f, 0x64, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68, 0x65, 0x61, 0x6c,
+ 0x65, 0x64, 0x20, 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65, 0x63, 0x68,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69,
+ 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6d, 0x61, 0x69, 0x64, 0x73, 0x65, 0x72, 0x76, 0x61, 0x6e, 0x74, 0x73,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x62,
+ 0x61, 0x72, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e,
+ 0x2e, 0x20, 0x0a, 0x46, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c,
+ 0x4f, 0x52, 0x44, 0x20, 0x68, 0x61, 0x64, 0x20, 0x66, 0x61, 0x73, 0x74,
+ 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x20, 0x75, 0x70, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x62, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x6f, 0x75, 0x73,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x41, 0x62, 0x69, 0x6d, 0x65, 0x6c, 0x65,
+ 0x63, 0x68, 0x2c, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x68, 0x61, 0x6d, 0x27, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x20, 0x76, 0x69, 0x73, 0x69, 0x74, 0x65, 0x64, 0x20, 0x53,
+ 0x61, 0x72, 0x61, 0x68, 0x20, 0x61, 0x73, 0x20, 0x68, 0x65, 0x20, 0x68,
+ 0x61, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x64, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68,
+ 0x20, 0x61, 0x73, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x73,
+ 0x70, 0x6f, 0x6b, 0x65, 0x6e, 0x2e, 0x20, 0x0a, 0x46, 0x6f, 0x72, 0x20,
+ 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x65, 0x69,
+ 0x76, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x61, 0x72,
+ 0x65, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x61, 0x20,
+ 0x73, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6f,
+ 0x6c, 0x64, 0x20, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x61, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x65, 0x74, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x73, 0x70, 0x6f, 0x6b, 0x65, 0x6e, 0x20,
+ 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6c,
+ 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x62, 0x6f, 0x72,
+ 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20,
+ 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x53, 0x61, 0x72, 0x61, 0x68, 0x20, 0x62,
+ 0x61, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x6d, 0x2c, 0x20,
+ 0x49, 0x73, 0x61, 0x61, 0x63, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x63, 0x69, 0x72, 0x63,
+ 0x75, 0x6d, 0x63, 0x69, 0x73, 0x65, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x73, 0x6f, 0x6e, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x62, 0x65,
+ 0x69, 0x6e, 0x67, 0x20, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x64, 0x61,
+ 0x79, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x73, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x68, 0x61, 0x64, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
+ 0x6e, 0x64, 0x65, 0x64, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65,
+ 0x64, 0x20, 0x79, 0x65, 0x61, 0x72, 0x73, 0x20, 0x6f, 0x6c, 0x64, 0x2c,
+ 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f,
+ 0x6e, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69,
+ 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x72, 0x61,
+ 0x68, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x68, 0x61, 0x74, 0x68, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x6d, 0x65,
+ 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x61, 0x75, 0x67, 0x68, 0x2c, 0x20, 0x73,
+ 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x68, 0x65, 0x61, 0x72, 0x20, 0x77, 0x69, 0x6c,
+ 0x6c, 0x20, 0x6c, 0x61, 0x75, 0x67, 0x68, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x6d, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x73, 0x68,
+ 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x57, 0x68, 0x6f, 0x20,
+ 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x53,
+ 0x61, 0x72, 0x61, 0x68, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x63,
+ 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x20, 0x73, 0x75, 0x63, 0x6b,
+ 0x3f, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x49, 0x20, 0x68, 0x61, 0x76, 0x65,
+ 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61, 0x20,
+ 0x73, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6f,
+ 0x6c, 0x64, 0x20, 0x61, 0x67, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x67,
+ 0x72, 0x65, 0x77, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x77, 0x65, 0x61, 0x6e, 0x65, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x20, 0x6d, 0x61, 0x64,
+ 0x65, 0x20, 0x61, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20, 0x66, 0x65,
+ 0x61, 0x73, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65,
+ 0x20, 0x64, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49, 0x73,
+ 0x61, 0x61, 0x63, 0x20, 0x77, 0x61, 0x73, 0x20, 0x77, 0x65, 0x61, 0x6e,
+ 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x72,
+ 0x61, 0x68, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x61, 0x67, 0x61, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x45, 0x67, 0x79, 0x70, 0x74, 0x69, 0x61, 0x6e,
+ 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x73, 0x68, 0x65, 0x20,
+ 0x68, 0x61, 0x64, 0x20, 0x62, 0x6f, 0x72, 0x6e, 0x20, 0x75, 0x6e, 0x74,
+ 0x6f, 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x6d,
+ 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0x20, 0x0a, 0x57, 0x68, 0x65,
+ 0x72, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x73, 0x68, 0x65, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72,
+ 0x61, 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x43, 0x61, 0x73, 0x74, 0x20, 0x6f,
+ 0x75, 0x74, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x62, 0x6f, 0x6e, 0x64,
+ 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x72, 0x20, 0x73, 0x6f, 0x6e, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x69, 0x73, 0x20, 0x62, 0x6f, 0x6e, 0x64, 0x77, 0x6f, 0x6d, 0x61, 0x6e,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x62,
+ 0x65, 0x20, 0x68, 0x65, 0x69, 0x72, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20,
+ 0x6d, 0x79, 0x20, 0x73, 0x6f, 0x6e, 0x2c, 0x20, 0x65, 0x76, 0x65, 0x6e,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x49, 0x73, 0x61, 0x61, 0x63, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x68,
+ 0x69, 0x6e, 0x67, 0x20, 0x77, 0x61, 0x73, 0x20, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x67, 0x72, 0x69, 0x65, 0x76, 0x6f, 0x75, 0x73, 0x20, 0x69, 0x6e,
+ 0x20, 0x41, 0x62, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x27, 0x73, 0x20, 0x73,
+ 0x69, 0x67, 0x68, 0x74, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x6e, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61,
+ 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x62, 0x72, 0x61,
+ 0x68, 0x61, 0x6d, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x69, 0x74, 0x20,
+ 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x67, 0x72, 0x69, 0x65, 0x76,
+ 0x6f, 0x75, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x79, 0x20, 0x73,
+ 0x69, 0x67, 0x68, 0x74, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x64, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65,
+ 0x20, 0x6f, 0x66, 0x20
+};
+unsigned int bible_txt_64k_len = 65536;
diff --git a/drivers/staging/fsl_dce/tests/common/bible.txt.8k.h b/drivers/staging/fsl_dce/tests/common/bible.txt.8k.h
new file mode 100644
index 0000000..45a5749
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/common/bible.txt.8k.h
@@ -0,0 +1,686 @@
+unsigned char bible_txt_8k[] = {
+ 0x49, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e,
+ 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65,
+ 0x61, 0x74, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61,
+ 0x76, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72,
+ 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e, 0x65, 0x73,
+ 0x73, 0x20, 0x77, 0x61, 0x73, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x65, 0x65, 0x70, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x53, 0x70, 0x69, 0x72, 0x69, 0x74, 0x20,
+ 0x6f, 0x66, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x6f, 0x76, 0x65, 0x64,
+ 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61,
+ 0x63, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x6c, 0x69,
+ 0x67, 0x68, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73,
+ 0x61, 0x77, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
+ 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61,
+ 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x20, 0x66, 0x72,
+ 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e,
+ 0x65, 0x73, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x20, 0x44, 0x61, 0x79, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x72, 0x6b,
+ 0x6e, 0x65, 0x73, 0x73, 0x20, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c,
+ 0x65, 0x64, 0x20, 0x4e, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x20, 0x41, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f,
+ 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x64, 0x61, 0x79,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73,
+ 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x66, 0x69, 0x72, 0x6d,
+ 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x69, 0x64, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x69, 0x74, 0x20, 0x64, 0x69, 0x76,
+ 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65,
+ 0x72, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20,
+ 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x75,
+ 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72,
+ 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x61, 0x62,
+ 0x6f, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d,
+ 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69,
+ 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d,
+ 0x65, 0x6e, 0x74, 0x20, 0x48, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x2e, 0x20,
+ 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e,
+ 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20,
+ 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x75,
+ 0x6e, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61,
+ 0x76, 0x65, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x67, 0x61, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x70, 0x6c,
+ 0x61, 0x63, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x72, 0x79, 0x20, 0x6c, 0x61, 0x6e,
+ 0x64, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x61,
+ 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x72, 0x79,
+ 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x45, 0x61, 0x72, 0x74, 0x68, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x74,
+ 0x68, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x53, 0x65, 0x61, 0x73, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f,
+ 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x62, 0x72, 0x69,
+ 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x67, 0x72, 0x61,
+ 0x73, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x72, 0x62,
+ 0x20, 0x79, 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65,
+ 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x79,
+ 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x77, 0x68, 0x6f, 0x73, 0x65, 0x20,
+ 0x73, 0x65, 0x65, 0x64, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x69,
+ 0x74, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74,
+ 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x67, 0x72, 0x61, 0x73, 0x73,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x72, 0x62, 0x20, 0x79,
+ 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65, 0x65, 0x64,
+ 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b,
+ 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x79, 0x69, 0x65, 0x6c, 0x64, 0x69,
+ 0x6e, 0x67, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x2c, 0x20, 0x77, 0x68,
+ 0x6f, 0x73, 0x65, 0x20, 0x73, 0x65, 0x65, 0x64, 0x20, 0x77, 0x61, 0x73,
+ 0x20, 0x69, 0x6e, 0x20, 0x69, 0x74, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69,
+ 0x6e, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69,
+ 0x6e, 0x67, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d,
+ 0x6f, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64, 0x20, 0x64, 0x61,
+ 0x79, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68,
+ 0x65, 0x72, 0x65, 0x20, 0x62, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74,
+ 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72,
+ 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20,
+ 0x64, 0x69, 0x76, 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64,
+ 0x61, 0x79, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6e, 0x69, 0x67, 0x68, 0x74, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c,
+ 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x62, 0x65, 0x20, 0x66,
+ 0x6f, 0x72, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x65, 0x61, 0x73, 0x6f, 0x6e,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64,
+ 0x61, 0x79, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79, 0x65, 0x61,
+ 0x72, 0x73, 0x3a, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6f, 0x72,
+ 0x20, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x76,
+ 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x6c,
+ 0x69, 0x67, 0x68, 0x74, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x3a, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e, 0x20,
+ 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64,
+ 0x65, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x67, 0x72, 0x65, 0x61, 0x74, 0x20,
+ 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x3b, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x67, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x6c, 0x69, 0x67, 0x68,
+ 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x64, 0x61, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x72, 0x20, 0x6c, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x68,
+ 0x65, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x74, 0x61, 0x72, 0x73, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x65, 0x74, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x20,
+ 0x74, 0x6f, 0x20, 0x67, 0x69, 0x76, 0x65, 0x20, 0x6c, 0x69, 0x67, 0x68,
+ 0x74, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x6f, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x69, 0x67,
+ 0x68, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x64,
+ 0x69, 0x76, 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x64, 0x61, 0x72, 0x6b, 0x6e, 0x65, 0x73, 0x73, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67,
+ 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x6f, 0x75, 0x72, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64,
+ 0x2c, 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61,
+ 0x74, 0x65, 0x72, 0x73, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66,
+ 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x62, 0x75, 0x6e, 0x64, 0x61, 0x6e,
+ 0x74, 0x6c, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x76, 0x69,
+ 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x6c, 0x69,
+ 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x77, 0x6c,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x66, 0x6c,
+ 0x79, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x6d,
+ 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65,
+ 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x67, 0x72, 0x65, 0x61,
+ 0x74, 0x20, 0x77, 0x68, 0x61, 0x6c, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69,
+ 0x6e, 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x6f, 0x76, 0x65, 0x74, 0x68, 0x2c,
+ 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
+ 0x61, 0x74, 0x65, 0x72, 0x73, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68,
+ 0x74, 0x20, 0x66, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x62, 0x75, 0x6e,
+ 0x64, 0x61, 0x6e, 0x74, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x74, 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e, 0x64,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20,
+ 0x77, 0x69, 0x6e, 0x67, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20,
+ 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69,
+ 0x6e, 0x64, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20,
+ 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20,
+ 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73,
+ 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x73, 0x61, 0x79,
+ 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x42, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75,
+ 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x66, 0x69, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x61, 0x74,
+ 0x65, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x61, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74,
+ 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70,
+ 0x6c, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61,
+ 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x6e, 0x69, 0x6e,
+ 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x69, 0x66, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x4c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72,
+ 0x74, 0x68, 0x20, 0x62, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e,
+ 0x67, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x61,
+ 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e,
+ 0x64, 0x2c, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20,
+ 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61,
+ 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x61, 0x73, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74,
+ 0x68, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x68, 0x69, 0x73, 0x20,
+ 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x61,
+ 0x74, 0x74, 0x6c, 0x65, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x69, 0x72, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x68, 0x69,
+ 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x72, 0x65, 0x65,
+ 0x70, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x61, 0x66, 0x74, 0x65,
+ 0x72, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6b, 0x69, 0x6e, 0x64, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x4c, 0x65, 0x74,
+ 0x20, 0x75, 0x73, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x6d, 0x61, 0x6e,
+ 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x75, 0x72, 0x20, 0x69, 0x6d, 0x61, 0x67,
+ 0x65, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x20, 0x6f, 0x75, 0x72,
+ 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x6e, 0x65, 0x73, 0x73, 0x3a, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x6f,
+ 0x6e, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66,
+ 0x69, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x61, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72, 0x2c, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
+ 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f,
+ 0x76, 0x65, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f,
+ 0x76, 0x65, 0x72, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x72,
+ 0x65, 0x65, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x72, 0x65, 0x65, 0x70, 0x65,
+ 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x53, 0x6f, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6d,
+ 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x77,
+ 0x6e, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64,
+ 0x20, 0x68, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x3b, 0x20, 0x6d, 0x61, 0x6c,
+ 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x65, 0x6d, 0x61, 0x6c, 0x65,
+ 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x68, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x62, 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x6d, 0x2c, 0x20, 0x42, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x75,
+ 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x72, 0x65, 0x70, 0x6c, 0x65, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x75, 0x62, 0x64, 0x75, 0x65, 0x20, 0x69, 0x74, 0x3a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x64, 0x6f, 0x6d,
+ 0x69, 0x6e, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x65, 0x61, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x77,
+ 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x65,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x20,
+ 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d,
+ 0x6f, 0x76, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c,
+ 0x20, 0x42, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x2c, 0x20, 0x49, 0x20, 0x68,
+ 0x61, 0x76, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x79, 0x6f,
+ 0x75, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x68, 0x65, 0x72, 0x62,
+ 0x20, 0x62, 0x65, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65, 0x65,
+ 0x64, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x69, 0x73, 0x20,
+ 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61, 0x63,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x72, 0x65, 0x65, 0x2c, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x72, 0x75, 0x69,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20,
+ 0x79, 0x69, 0x65, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x65, 0x65,
+ 0x64, 0x3b, 0x20, 0x74, 0x6f, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x69, 0x74,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x6d, 0x65, 0x61, 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x62, 0x65,
+ 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65,
+ 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69, 0x72, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20,
+ 0x63, 0x72, 0x65, 0x65, 0x70, 0x65, 0x74, 0x68, 0x20, 0x75, 0x70, 0x6f,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c,
+ 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x66, 0x65, 0x2c, 0x20,
+ 0x49, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e,
+ 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x67, 0x72, 0x65, 0x65, 0x6e,
+ 0x20, 0x68, 0x65, 0x72, 0x62, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d, 0x65,
+ 0x61, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x74, 0x20, 0x77,
+ 0x61, 0x73, 0x20, 0x73, 0x6f, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x73, 0x61, 0x77, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x62, 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x76, 0x65,
+ 0x72, 0x79, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x2e, 0x20, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x69, 0x6e, 0x67,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x72,
+ 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x69, 0x78, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79, 0x2e,
+ 0x20, 0x0a, 0x54, 0x68, 0x75, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68,
+ 0x65, 0x61, 0x76, 0x65, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x77, 0x65, 0x72,
+ 0x65, 0x20, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x68, 0x6f, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x64, 0x61,
+ 0x79, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x68, 0x69,
+ 0x63, 0x68, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61,
+ 0x64, 0x65, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x72,
+ 0x65, 0x73, 0x74, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x73, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79,
+ 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x68, 0x69,
+ 0x73, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x62,
+ 0x6c, 0x65, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x76, 0x65, 0x6e, 0x74, 0x68, 0x20, 0x64, 0x61, 0x79, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x73, 0x61, 0x6e, 0x63, 0x74, 0x69, 0x66, 0x69,
+ 0x65, 0x64, 0x20, 0x69, 0x74, 0x3a, 0x20, 0x62, 0x65, 0x63, 0x61, 0x75,
+ 0x73, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x69,
+ 0x74, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61, 0x64, 0x20, 0x72, 0x65, 0x73,
+ 0x74, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x61, 0x6c, 0x6c,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x77, 0x68,
+ 0x69, 0x63, 0x68, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x63, 0x72, 0x65, 0x61,
+ 0x74, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65,
+ 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x73, 0x65, 0x20, 0x61, 0x72, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68,
+ 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x77,
+ 0x65, 0x72, 0x65, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x2c,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52,
+ 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x76, 0x65, 0x6e, 0x73,
+ 0x2c, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79,
+ 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x66, 0x6f,
+ 0x72, 0x65, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x68, 0x65,
+ 0x72, 0x62, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69,
+ 0x65, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x69,
+ 0x74, 0x20, 0x67, 0x72, 0x65, 0x77, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x61, 0x75,
+ 0x73, 0x65, 0x64, 0x20, 0x69, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x61,
+ 0x69, 0x6e, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x74,
+ 0x20, 0x61, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x69,
+ 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2e, 0x20, 0x0a, 0x42, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x72,
+ 0x65, 0x20, 0x77, 0x65, 0x6e, 0x74, 0x20, 0x75, 0x70, 0x20, 0x61, 0x20,
+ 0x6d, 0x69, 0x73, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x61, 0x72, 0x74, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x77, 0x61, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x77, 0x68, 0x6f, 0x6c, 0x65, 0x20, 0x66, 0x61, 0x63, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e,
+ 0x64, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72,
+ 0x6d, 0x65, 0x64, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x75, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x62, 0x72, 0x65, 0x61, 0x74, 0x68, 0x65, 0x64, 0x20,
+ 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x73,
+ 0x74, 0x72, 0x69, 0x6c, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x72,
+ 0x65, 0x61, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x69, 0x66, 0x65,
+ 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x62, 0x65,
+ 0x63, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e,
+ 0x67, 0x20, 0x73, 0x6f, 0x75, 0x6c, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x61, 0x20,
+ 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x20, 0x65, 0x61, 0x73, 0x74, 0x77,
+ 0x61, 0x72, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x45, 0x64, 0x65, 0x6e, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x68,
+ 0x65, 0x20, 0x70, 0x75, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61,
+ 0x6e, 0x20, 0x77, 0x68, 0x6f, 0x6d, 0x20, 0x68, 0x65, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x65, 0x64, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x64,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47,
+ 0x6f, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x72, 0x6f, 0x77, 0x20, 0x65,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x70, 0x6c, 0x65, 0x61, 0x73, 0x61,
+ 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x69,
+ 0x67, 0x68, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x6f, 0x6f,
+ 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x66, 0x6f, 0x6f, 0x64, 0x3b, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x6c, 0x69, 0x66, 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x69, 0x6e,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x69, 0x64, 0x73, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x72,
+ 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x6c, 0x65,
+ 0x64, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x69, 0x6c, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x61, 0x20, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x77,
+ 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x45,
+ 0x64, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x77, 0x61, 0x74, 0x65, 0x72,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x3b,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68,
+ 0x65, 0x6e, 0x63, 0x65, 0x20, 0x69, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x70, 0x61, 0x72, 0x74, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x62, 0x65, 0x63, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20,
+ 0x66, 0x6f, 0x75, 0x72, 0x20, 0x68, 0x65, 0x61, 0x64, 0x73, 0x2e, 0x20,
+ 0x0a, 0x54, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x69,
+ 0x73, 0x20, 0x50, 0x69, 0x73, 0x6f, 0x6e, 0x3a, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x69, 0x73, 0x20, 0x69, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63,
+ 0x68, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x73, 0x73, 0x65, 0x74, 0x68,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68, 0x6f, 0x6c, 0x65, 0x20, 0x6c,
+ 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x48, 0x61, 0x76, 0x69, 0x6c,
+ 0x61, 0x68, 0x2c, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68,
+ 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x67, 0x6f, 0x6c, 0x64, 0x3b,
+ 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x6f,
+ 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6c,
+ 0x61, 0x6e, 0x64, 0x20, 0x69, 0x73, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x3a,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x62, 0x64,
+ 0x65, 0x6c, 0x6c, 0x69, 0x75, 0x6d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6f, 0x6e, 0x79, 0x78, 0x20, 0x73, 0x74, 0x6f, 0x6e,
+ 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20, 0x72, 0x69, 0x76, 0x65, 0x72,
+ 0x20, 0x69, 0x73, 0x20, 0x47, 0x69, 0x68, 0x6f, 0x6e, 0x3a, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x73, 0x20, 0x69,
+ 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61,
+ 0x73, 0x73, 0x65, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x68,
+ 0x6f, 0x6c, 0x65, 0x20, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20,
+ 0x45, 0x74, 0x68, 0x69, 0x6f, 0x70, 0x69, 0x61, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20,
+ 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x69, 0x72, 0x64,
+ 0x20, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x48, 0x69,
+ 0x64, 0x64, 0x65, 0x6b, 0x65, 0x6c, 0x3a, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x69, 0x73, 0x20, 0x69, 0x74, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x67, 0x6f, 0x65, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x77, 0x61, 0x72,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x41, 0x73, 0x73, 0x79, 0x72, 0x69, 0x61, 0x2e, 0x20, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x75, 0x72, 0x74,
+ 0x68, 0x20, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x45,
+ 0x75, 0x70, 0x68, 0x72, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x75,
+ 0x74, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x20, 0x6f, 0x66,
+ 0x20, 0x45, 0x64, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x72, 0x65,
+ 0x73, 0x73, 0x20, 0x69, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f,
+ 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x69, 0x74, 0x2e, 0x20, 0x0a, 0x41,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20,
+ 0x47, 0x6f, 0x64, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x73,
+ 0x61, 0x79, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x4f, 0x66, 0x20, 0x65, 0x76,
+ 0x65, 0x72, 0x79, 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x20, 0x74,
+ 0x68, 0x6f, 0x75, 0x20, 0x6d, 0x61, 0x79, 0x65, 0x73, 0x74, 0x20, 0x66,
+ 0x72, 0x65, 0x65, 0x6c, 0x79, 0x20, 0x65, 0x61, 0x74, 0x3a, 0x20, 0x0a,
+ 0x42, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
+ 0x72, 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b,
+ 0x6e, 0x6f, 0x77, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x69,
+ 0x6c, 0x2c, 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c,
+ 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x61, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x69, 0x74, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x6f, 0x75, 0x20, 0x65, 0x61, 0x74, 0x65, 0x73, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x6f,
+ 0x75, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x74, 0x20, 0x73, 0x75, 0x72, 0x65,
+ 0x6c, 0x79, 0x20, 0x64, 0x69, 0x65, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x49, 0x74, 0x20, 0x69,
+ 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x74,
+ 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x20,
+ 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x61, 0x6c,
+ 0x6f, 0x6e, 0x65, 0x3b, 0x20, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x68, 0x69, 0x6d, 0x20, 0x61, 0x6e, 0x20,
+ 0x68, 0x65, 0x6c, 0x70, 0x20, 0x6d, 0x65, 0x65, 0x74, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67,
+ 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f,
+ 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x65,
+ 0x64, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x62, 0x65, 0x61, 0x73,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65,
+ 0x6c, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76, 0x65, 0x72,
+ 0x79, 0x20, 0x66, 0x6f, 0x77, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x61, 0x69, 0x72, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62,
+ 0x72, 0x6f, 0x75, 0x67, 0x68, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x74, 0x6f,
+ 0x20, 0x73, 0x65, 0x65, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x68, 0x65,
+ 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20,
+ 0x74, 0x68, 0x65, 0x6d, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68,
+ 0x61, 0x74, 0x73, 0x6f, 0x65, 0x76, 0x65, 0x72, 0x20, 0x41, 0x64, 0x61,
+ 0x6d, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x65, 0x76, 0x65,
+ 0x72, 0x79, 0x20, 0x6c, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x72,
+ 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d,
+ 0x65, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x2e, 0x20, 0x0a,
+ 0x41, 0x6e, 0x64, 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x67, 0x61, 0x76,
+ 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61,
+ 0x6c, 0x6c, 0x20, 0x63, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f,
+ 0x77, 0x6c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x69,
+ 0x72, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x76,
+ 0x65, 0x72, 0x79, 0x20, 0x62, 0x65, 0x61, 0x73, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x3b, 0x20,
+ 0x62, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x41, 0x64, 0x61, 0x6d,
+ 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x20,
+ 0x68, 0x65, 0x6c, 0x70, 0x20, 0x6d, 0x65, 0x65, 0x74, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x68, 0x69, 0x6d, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x63, 0x61, 0x75, 0x73, 0x65, 0x64, 0x20, 0x61, 0x20, 0x64, 0x65,
+ 0x65, 0x70, 0x20, 0x73, 0x6c, 0x65, 0x65, 0x70, 0x20, 0x74, 0x6f, 0x20,
+ 0x66, 0x61, 0x6c, 0x6c, 0x20, 0x75, 0x70, 0x6f, 0x6e, 0x20, 0x41, 0x64,
+ 0x61, 0x6d, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x73,
+ 0x6c, 0x65, 0x70, 0x74, 0x3a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x65,
+ 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x68, 0x69, 0x73, 0x20, 0x72, 0x69, 0x62, 0x73, 0x2c, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x20, 0x75, 0x70,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20, 0x69,
+ 0x6e, 0x73, 0x74, 0x65, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65,
+ 0x6f, 0x66, 0x3b, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x72, 0x69, 0x62, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64,
+ 0x20, 0x68, 0x61, 0x64, 0x20, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x6d, 0x61, 0x64,
+ 0x65, 0x20, 0x68, 0x65, 0x20, 0x61, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x62, 0x72, 0x6f, 0x75, 0x67, 0x68,
+ 0x74, 0x20, 0x68, 0x65, 0x72, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64,
+ 0x20, 0x41, 0x64, 0x61, 0x6d, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20,
+ 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20,
+ 0x62, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x62,
+ 0x6f, 0x6e, 0x65, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6c,
+ 0x65, 0x73, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x79, 0x20, 0x66, 0x6c,
+ 0x65, 0x73, 0x68, 0x3a, 0x20, 0x73, 0x68, 0x65, 0x20, 0x73, 0x68, 0x61,
+ 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64,
+ 0x20, 0x57, 0x6f, 0x6d, 0x61, 0x6e, 0x2c, 0x20, 0x62, 0x65, 0x63, 0x61,
+ 0x75, 0x73, 0x65, 0x20, 0x73, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20,
+ 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66,
+ 0x20, 0x4d, 0x61, 0x6e, 0x2e, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x72, 0x65,
+ 0x66, 0x6f, 0x72, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x61,
+ 0x20, 0x6d, 0x61, 0x6e, 0x20, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x20, 0x68,
+ 0x69, 0x73, 0x20, 0x66, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x6f, 0x74, 0x68, 0x65, 0x72,
+ 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x63, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20,
+ 0x68, 0x69, 0x73, 0x20, 0x77, 0x69, 0x66, 0x65, 0x3a, 0x20, 0x61, 0x6e,
+ 0x64, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c,
+ 0x20, 0x62, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x66, 0x6c, 0x65, 0x73,
+ 0x68, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x79,
+ 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x6e,
+ 0x61, 0x6b, 0x65, 0x64, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61,
+ 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x69, 0x73, 0x20, 0x77, 0x69,
+ 0x66, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x65, 0x72, 0x65,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x73, 0x68, 0x61, 0x6d, 0x65, 0x64,
+ 0x2e, 0x20, 0x0a, 0x4e, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x72, 0x70, 0x65, 0x6e, 0x74, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6d,
+ 0x6f, 0x72, 0x65, 0x20, 0x73, 0x75, 0x62, 0x74, 0x69, 0x6c, 0x20, 0x74,
+ 0x68, 0x61, 0x6e, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x62, 0x65, 0x61, 0x73,
+ 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x65,
+ 0x6c, 0x64, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x4c, 0x4f, 0x52, 0x44, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68, 0x61,
+ 0x64, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x2e, 0x20, 0x41, 0x6e, 0x64, 0x20,
+ 0x68, 0x65, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x2c, 0x20,
+ 0x59, 0x65, 0x61, 0x2c, 0x20, 0x68, 0x61, 0x74, 0x68, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x59, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x61, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x74, 0x72,
+ 0x65, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61,
+ 0x72, 0x64, 0x65, 0x6e, 0x3f, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20, 0x73, 0x61, 0x69,
+ 0x64, 0x20, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x72, 0x70, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x57, 0x65, 0x20, 0x6d,
+ 0x61, 0x79, 0x20, 0x65, 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x72, 0x65, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 0x72, 0x64, 0x65, 0x6e, 0x3a, 0x20,
+ 0x0a, 0x42, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x69, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x69,
+ 0x64, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67,
+ 0x61, 0x72, 0x64, 0x65, 0x6e, 0x2c, 0x20, 0x47, 0x6f, 0x64, 0x20, 0x68,
+ 0x61, 0x74, 0x68, 0x20, 0x73, 0x61, 0x69, 0x64, 0x2c, 0x20, 0x59, 0x65,
+ 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65,
+ 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x6e, 0x65,
+ 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20,
+ 0x79, 0x65, 0x20, 0x74, 0x6f, 0x75, 0x63, 0x68, 0x20, 0x69, 0x74, 0x2c,
+ 0x20, 0x6c, 0x65, 0x73, 0x74, 0x20, 0x79, 0x65, 0x20, 0x64, 0x69, 0x65,
+ 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x72, 0x70, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x61, 0x69, 0x64, 0x20,
+ 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d,
+ 0x61, 0x6e, 0x2c, 0x20, 0x59, 0x65, 0x20, 0x73, 0x68, 0x61, 0x6c, 0x6c,
+ 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x72, 0x65, 0x6c, 0x79, 0x20,
+ 0x64, 0x69, 0x65, 0x3a, 0x20, 0x0a, 0x46, 0x6f, 0x72, 0x20, 0x47, 0x6f,
+ 0x64, 0x20, 0x64, 0x6f, 0x74, 0x68, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x64, 0x61, 0x79, 0x20, 0x79, 0x65, 0x20, 0x65, 0x61, 0x74, 0x20, 0x74,
+ 0x68, 0x65, 0x72, 0x65, 0x6f, 0x66, 0x2c, 0x20, 0x74, 0x68, 0x65, 0x6e,
+ 0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x65, 0x79, 0x65, 0x73, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6f, 0x70, 0x65, 0x6e,
+ 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x79, 0x65, 0x20, 0x73,
+ 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x73, 0x20, 0x67,
+ 0x6f, 0x64, 0x73, 0x2c, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x69, 0x6e, 0x67,
+ 0x20, 0x67, 0x6f, 0x6f, 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x76,
+ 0x69, 0x6c, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x65,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x6d, 0x61, 0x6e, 0x20,
+ 0x73, 0x61, 0x77, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x74, 0x72, 0x65, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x67, 0x6f,
+ 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x66, 0x6f, 0x6f, 0x64, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74,
+ 0x20, 0x77, 0x61, 0x73, 0x20, 0x70, 0x6c, 0x65, 0x61, 0x73, 0x61, 0x6e,
+ 0x74, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x79, 0x65,
+ 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x74, 0x72, 0x65,
+ 0x65, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x64, 0x65, 0x73, 0x69,
+ 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20,
+ 0x6f, 0x6e, 0x65, 0x20, 0x77, 0x69, 0x73, 0x65, 0x2c, 0x20, 0x73, 0x68,
+ 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x72, 0x75, 0x69, 0x74, 0x20, 0x74, 0x68, 0x65, 0x72,
+ 0x65, 0x6f, 0x66, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x64,
+ 0x20, 0x65, 0x61, 0x74, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x61,
+ 0x76, 0x65, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x75, 0x6e, 0x74, 0x6f,
+ 0x20, 0x68, 0x65, 0x72, 0x20, 0x68, 0x75, 0x73, 0x62, 0x61, 0x6e, 0x64,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x68, 0x65, 0x72, 0x3b, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x68, 0x65, 0x20, 0x64, 0x69, 0x64, 0x20, 0x65, 0x61,
+ 0x74, 0x2e, 0x20, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x65, 0x79, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6d,
+ 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6f,
+ 0x70, 0x65, 0x6e, 0x65, 0x64, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x6b, 0x6e, 0x65, 0x77, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+ 0x6e, 0x61, 0x6b, 0x65, 0x64, 0x3b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74,
+ 0x68, 0x65, 0x79, 0x20, 0x73, 0x65, 0x77, 0x65, 0x64, 0x20, 0x66, 0x69,
+ 0x67, 0x20, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x73
+};
+unsigned int bible_txt_8k_len = 8192;
diff --git a/drivers/staging/fsl_dce/tests/common/paper5_11954.h b/drivers/staging/fsl_dce/tests/common/paper5_11954.h
new file mode 100644
index 0000000..2ff0998
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/common/paper5_11954.h
@@ -0,0 +1,1000 @@
+unsigned char paper5_11954[] = {
+ 0x2e, 0x70, 0x6e, 0x20, 0x30, 0x0a, 0x2e, 0x45, 0x51, 0x0a, 0x64, 0x65,
+ 0x6c, 0x69, 0x6d, 0x20, 0x24, 0x24, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e,
+ 0x65, 0x20, 0x52, 0x52, 0x20, 0x27, 0x62, 0x6f, 0x6c, 0x64, 0x20, 0x52,
+ 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x53, 0x53, 0x20,
+ 0x27, 0x62, 0x6f, 0x6c, 0x64, 0x20, 0x53, 0x27, 0x0a, 0x64, 0x65, 0x66,
+ 0x69, 0x6e, 0x65, 0x20, 0x49, 0x49, 0x20, 0x27, 0x62, 0x6f, 0x6c, 0x64,
+ 0x20, 0x49, 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x6d,
+ 0x6f, 0x20, 0x27, 0x22, 0x5c, 0x28, 0x6d, 0x6f, 0x22, 0x27, 0x0a, 0x64,
+ 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x45, 0x58, 0x49, 0x53, 0x54, 0x20,
+ 0x3f, 0x22, 0x5c, 0x7a, 0x5c, 0x2d, 0x5c, 0x64, 0x5c, 0x7a, 0x5c, 0x2d,
+ 0x5c, 0x72, 0x5c, 0x2d, 0x5c, 0x64, 0x5c, 0x76, 0x27, 0x30, 0x2e, 0x32,
+ 0x6d, 0x27, 0x5c, 0x28, 0x62, 0x72, 0x5c, 0x76, 0x27, 0x2d, 0x30, 0x2e,
+ 0x32, 0x6d, 0x27, 0x22, 0x3f, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65,
+ 0x20, 0x4e, 0x45, 0x58, 0x49, 0x53, 0x54, 0x20, 0x3f, 0x22, 0x5c, 0x7a,
+ 0x5c, 0x2d, 0x5c, 0x64, 0x5c, 0x7a, 0x5c, 0x6f, 0x27, 0x5c, 0x2d, 0x5c,
+ 0x28, 0x73, 0x6c, 0x27, 0x5c, 0x72, 0x5c, 0x2d, 0x5c, 0x64, 0x5c, 0x76,
+ 0x27, 0x30, 0x2e, 0x32, 0x6d, 0x27, 0x5c, 0x28, 0x62, 0x72, 0x5c, 0x76,
+ 0x27, 0x2d, 0x30, 0x2e, 0x32, 0x6d, 0x27, 0x22, 0x3f, 0x0a, 0x64, 0x65,
+ 0x66, 0x69, 0x6e, 0x65, 0x20, 0x41, 0x4c, 0x4c, 0x20, 0x3f, 0x22, 0x5c,
+ 0x6f, 0x27, 0x56, 0x2d, 0x27, 0x22, 0x3f, 0x0a, 0x64, 0x65, 0x66, 0x69,
+ 0x6e, 0x65, 0x20, 0x73, 0x75, 0x62, 0x73, 0x65, 0x74, 0x20, 0x27, 0x5c,
+ 0x28, 0x73, 0x62, 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20,
+ 0x73, 0x75, 0x62, 0x65, 0x71, 0x20, 0x20, 0x27, 0x5c, 0x28, 0x69, 0x62,
+ 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x73, 0x75, 0x70,
+ 0x73, 0x65, 0x74, 0x20, 0x27, 0x5c, 0x28, 0x73, 0x70, 0x27, 0x0a, 0x64,
+ 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x73, 0x75, 0x70, 0x65, 0x71, 0x20,
+ 0x20, 0x27, 0x5c, 0x28, 0x69, 0x70, 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69,
+ 0x6e, 0x65, 0x20, 0x6d, 0x6f, 0x20, 0x27, 0x5c, 0x28, 0x6d, 0x6f, 0x27,
+ 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x6e, 0x6d, 0x20, 0x3f,
+ 0x22, 0x5c, 0x6f, 0x27, 0x5c, 0x28, 0x6d, 0x6f, 0x5c, 0x28, 0x73, 0x6c,
+ 0x27, 0x22, 0x3f, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x6c,
+ 0x69, 0x20, 0x27, 0x5c, 0x26, 0x20, 0x73, 0x75, 0x70, 0x20, 0x5b, 0x27,
+ 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x6f, 0x20, 0x27,
+ 0x5c, 0x26, 0x20, 0x73, 0x75, 0x70, 0x20, 0x28, 0x27, 0x0a, 0x64, 0x65,
+ 0x66, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x69, 0x20, 0x27, 0x5c, 0x26, 0x20,
+ 0x73, 0x75, 0x70, 0x20, 0x5d, 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e,
+ 0x65, 0x20, 0x68, 0x6f, 0x20, 0x27, 0x5c, 0x26, 0x20, 0x73, 0x75, 0x70,
+ 0x20, 0x29, 0x27, 0x0a, 0x2e, 0x45, 0x4e, 0x0a, 0x2e, 0x6c, 0x73, 0x20,
+ 0x31, 0x09, 0x0a, 0x2e, 0x63, 0x65, 0x0a, 0x41, 0x20, 0x4c, 0x4f, 0x47,
+ 0x49, 0x43, 0x41, 0x4c, 0x20, 0x49, 0x4d, 0x50, 0x4c, 0x45, 0x4d, 0x45,
+ 0x4e, 0x54, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x4f, 0x46, 0x20, 0x41,
+ 0x52, 0x49, 0x54, 0x48, 0x4d, 0x45, 0x54, 0x49, 0x43, 0x20, 0x0a, 0x2e,
+ 0x73, 0x70, 0x20, 0x33, 0x0a, 0x2e, 0x63, 0x65, 0x0a, 0x4a, 0x6f, 0x68,
+ 0x6e, 0x20, 0x47, 0x2e, 0x20, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x79, 0x20,
+ 0x0a, 0x2e, 0x63, 0x65, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x55, 0x6e, 0x69,
+ 0x76, 0x65, 0x72, 0x73, 0x69, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x43,
+ 0x61, 0x6c, 0x67, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x41, 0x6c, 0x62, 0x65,
+ 0x72, 0x74, 0x61, 0x2c, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2e,
+ 0x0a, 0x2e, 0x73, 0x70, 0x20, 0x32, 0x30, 0x0a, 0x5c, 0x75, 0x31, 0x5c,
+ 0x64, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x27, 0x73, 0x20, 0x50, 0x72,
+ 0x65, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
+ 0x73, 0x3a, 0x20, 0x4d, 0x61, 0x6e, 0x2d, 0x4d, 0x61, 0x63, 0x68, 0x69,
+ 0x6e, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x47,
+ 0x72, 0x6f, 0x75, 0x70, 0x2c, 0x20, 0x44, 0x65, 0x70, 0x61, 0x72, 0x74,
+ 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x0a, 0x43, 0x6f, 0x6d, 0x70,
+ 0x75, 0x74, 0x65, 0x72, 0x20, 0x53, 0x63, 0x69, 0x65, 0x6e, 0x63, 0x65,
+ 0x2c, 0x20, 0x54, 0x68, 0x65, 0x20, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72,
+ 0x73, 0x69, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x61, 0x6c, 0x67,
+ 0x61, 0x72, 0x79, 0x2c, 0x20, 0x32, 0x35, 0x30, 0x30, 0x20, 0x55, 0x6e,
+ 0x69, 0x76, 0x65, 0x72, 0x73, 0x69, 0x74, 0x79, 0x20, 0x44, 0x72, 0x69,
+ 0x76, 0x65, 0x20, 0x4e, 0x57, 0x0a, 0x43, 0x61, 0x6c, 0x67, 0x61, 0x72,
+ 0x79, 0x2c, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x20, 0x54, 0x32,
+ 0x4e, 0x20, 0x31, 0x4e, 0x34, 0x2e, 0x20, 0x50, 0x68, 0x6f, 0x6e, 0x65,
+ 0x3a, 0x20, 0x28, 0x34, 0x30, 0x33, 0x29, 0x32, 0x32, 0x30, 0x2d, 0x36,
+ 0x30, 0x38, 0x37, 0x2e, 0x20, 0x20, 0x0a, 0x2e, 0x62, 0x72, 0x0a, 0x2e,
+ 0x6e, 0x66, 0x0a, 0x55, 0x55, 0x43, 0x50, 0x3a, 0x20, 0x20, 0x2e, 0x2e,
+ 0x2e, 0x21, 0x7b, 0x69, 0x68, 0x6e, 0x70, 0x34, 0x2c, 0x75, 0x62, 0x63,
+ 0x2d, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x7d, 0x21, 0x61, 0x6c, 0x62,
+ 0x65, 0x72, 0x74, 0x61, 0x21, 0x63, 0x61, 0x6c, 0x67, 0x61, 0x72, 0x79,
+ 0x21, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x79, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x21, 0x6e, 0x72, 0x6c, 0x2d, 0x63,
+ 0x73, 0x73, 0x21, 0x63, 0x61, 0x6c, 0x67, 0x61, 0x72, 0x79, 0x21, 0x63,
+ 0x6c, 0x65, 0x61, 0x72, 0x79, 0x0a, 0x41, 0x52, 0x50, 0x41, 0x3a, 0x20,
+ 0x20, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x79, 0x2e, 0x63, 0x61, 0x6c, 0x67,
+ 0x61, 0x72, 0x79, 0x2e, 0x75, 0x62, 0x63, 0x40, 0x63, 0x73, 0x6e, 0x65,
+ 0x74, 0x2d, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x0a, 0x43, 0x44, 0x4e, 0x3a,
+ 0x20, 0x20, 0x20, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x79, 0x40, 0x63, 0x61,
+ 0x6c, 0x67, 0x61, 0x72, 0x79, 0x0a, 0x2e, 0x66, 0x69, 0x0a, 0x2e, 0x73,
+ 0x70, 0x20, 0x32, 0x0a, 0x2e, 0x6c, 0x73, 0x20, 0x32, 0x0a, 0x2e, 0x62,
+ 0x70, 0x20, 0x30, 0x0a, 0x2e, 0x6c, 0x73, 0x20, 0x32, 0x0a, 0x2e, 0x63,
+ 0x65, 0x0a, 0x41, 0x62, 0x73, 0x74, 0x72, 0x61, 0x63, 0x74, 0x0a, 0x2e,
+ 0x70, 0x70, 0x0a, 0x53, 0x6f, 0x20, 0x66, 0x61, 0x72, 0x20, 0x69, 0x6d,
+ 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x61, 0x72,
+ 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x69, 0x6e, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x20, 0x70, 0x72,
+ 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x0a, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x6e, 0x6f, 0x6e, 0x2d,
+ 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x20, 0x20, 0x41, 0x20,
+ 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x73, 0x63,
+ 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x75, 0x72,
+ 0x20, 0x6f, 0x66, 0x20, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74,
+ 0x69, 0x63, 0x0a, 0x6f, 0x6e, 0x20, 0x61, 0x63, 0x74, 0x75, 0x61, 0x6c,
+ 0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x75, 0x73,
+ 0x69, 0x6e, 0x67, 0x20, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x65, 0x20, 0x70,
+ 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x75, 0x6d,
+ 0x62, 0x65, 0x72, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x72, 0x65, 0x61, 0x64, 0x69, 0x6c, 0x79, 0x20, 0x61, 0x76, 0x61, 0x69,
+ 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x20, 0x20, 0x0a, 0x55, 0x73, 0x69,
+ 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x20,
+ 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x20, 0x61, 0x20, 0x73,
+ 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x61,
+ 0x6c, 0x20, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63,
+ 0x20, 0x69, 0x73, 0x20, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65,
+ 0x2e, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62,
+ 0x65, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65,
+ 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x69, 0x6e, 0x20, 0x50, 0x72, 0x6f, 0x6c, 0x6f, 0x67, 0x2e,
+ 0x0a, 0x41, 0x73, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
+ 0x68, 0x61, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x75,
+ 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x62,
+ 0x61, 0x73, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73,
+ 0x75, 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65,
+ 0x6d, 0x20, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x73, 0x20, 0x61, 0x20,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x69, 0x73, 0x65,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x66, 0x75,
+ 0x6c, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x69, 0x6e,
+ 0x67, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x69, 0x73, 0x20, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
+ 0x6c, 0x79, 0x0a, 0x76, 0x65, 0x72, 0x79, 0x20, 0x65, 0x66, 0x66, 0x69,
+ 0x63, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x2e, 0x62, 0x70, 0x0a, 0x2e,
+ 0x73, 0x68, 0x20, 0x22, 0x31, 0x20, 0x49, 0x6e, 0x74, 0x72, 0x6f, 0x64,
+ 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x0a, 0x2e, 0x70, 0x70, 0x0a,
+ 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61,
+ 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x69, 0x6d, 0x73, 0x20, 0x74,
+ 0x6f, 0x20, 0x75, 0x73, 0x65, 0x20, 0x73, 0x65, 0x74, 0x73, 0x20, 0x6f,
+ 0x66, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x6f,
+ 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x65, 0x20, 0x61, 0x73, 0x0a, 0x73, 0x74,
+ 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20,
+ 0x61, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x69, 0x6e,
+ 0x67, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x2e, 0x0a,
+ 0x42, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6d,
+ 0x61, 0x6e, 0x79, 0x20, 0x70, 0x72, 0x61, 0x63, 0x74, 0x69, 0x63, 0x61,
+ 0x6c, 0x20, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x69,
+ 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20,
+ 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x6f,
+ 0x66, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x0a, 0x63, 0x61, 0x6e, 0x6e,
+ 0x6f, 0x74, 0x20, 0x28, 0x79, 0x65, 0x74, 0x29, 0x20, 0x62, 0x65, 0x20,
+ 0x75, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x77, 0x61, 0x79, 0x2e, 0x20, 0x20, 0x20, 0x48, 0x6f, 0x77, 0x65,
+ 0x76, 0x65, 0x72, 0x2c, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x73, 0x74,
+ 0x72, 0x69, 0x63, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x0a,
+ 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x6f, 0x72,
+ 0x6d, 0x75, 0x6c, 0x61, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74,
+ 0x6f, 0x20, 0x48, 0x6f, 0x72, 0x6e, 0x20, 0x63, 0x6c, 0x61, 0x75, 0x73,
+ 0x65, 0x73, 0x20, 0x70, 0x72, 0x61, 0x63, 0x74, 0x69, 0x63, 0x61, 0x6c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x66, 0x66, 0x69, 0x63, 0x69, 0x65,
+ 0x6e, 0x74, 0x0a, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x73,
+ 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20, 0x50, 0x52, 0x4f,
+ 0x4c, 0x4f, 0x47, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6f, 0x62, 0x74, 0x61,
+ 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x0a, 0x4f, 0x6e, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x70, 0x72,
+ 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x6f,
+ 0x67, 0x69, 0x63, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d,
+ 0x69, 0x6e, 0x67, 0x20, 0x69, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x78,
+ 0x74, 0x65, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x61, 0x72,
+ 0x65, 0x61, 0x0a, 0x6f, 0x66, 0x20, 0x70, 0x72, 0x61, 0x63, 0x74, 0x69,
+ 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65,
+ 0x66, 0x66, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x63, 0x79, 0x20, 0x74, 0x6f,
+ 0x20, 0x61, 0x6e, 0x20, 0x65, 0x76, 0x65, 0x72, 0x20, 0x77, 0x69, 0x64,
+ 0x65, 0x72, 0x20, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x66, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x65, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x2e, 0x20, 0x20, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70,
+ 0x61, 0x70, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65,
+ 0x72, 0x73, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x6e, 0x20, 0x69,
+ 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d,
+ 0x65, 0x74, 0x69, 0x63, 0x2e, 0x0a, 0x2e, 0x70, 0x70, 0x0a, 0x54, 0x6f,
+ 0x20, 0x73, 0x65, 0x65, 0x20, 0x77, 0x68, 0x79, 0x20, 0x61, 0x72, 0x69,
+ 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x61, 0x73, 0x20, 0x69,
+ 0x74, 0x20, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x6c,
+ 0x79, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65,
+ 0x64, 0x20, 0x69, 0x6e, 0x20, 0x50, 0x52, 0x4f, 0x4c, 0x4f, 0x47, 0x20,
+ 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x0a, 0x69, 0x73, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x63,
+ 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x78,
+ 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x3a, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x2e,
+ 0x6e, 0x66, 0x0a, 0x09, 0x58, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x36, 0x37,
+ 0x2c, 0x20, 0x59, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x34, 0x35, 0x2c, 0x20,
+ 0x5a, 0x20, 0x69, 0x73, 0x20, 0x58, 0x2a, 0x59, 0x2c, 0x20, 0x5a, 0x20,
+ 0x3d, 0x20, 0x30, 0x2e, 0x33, 0x30, 0x0a, 0x2e, 0x66, 0x69, 0x0a, 0x2e,
+ 0x73, 0x70, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x27, 0x45, 0x64,
+ 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x68, 0x20, 0x73, 0x74, 0x79, 0x6c,
+ 0x65, 0x27, 0x20, 0x50, 0x72, 0x6f, 0x6c, 0x6f, 0x67, 0x73, 0x2e, 0x0a,
+ 0x28, 0x46, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d,
+ 0x65, 0x6e, 0x74, 0x20, 0x77, 0x65, 0x20, 0x61, 0x73, 0x73, 0x75, 0x6d,
+ 0x65, 0x20, 0x61, 0x6e, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x79,
+ 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x69, 0x6e, 0x67,
+ 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x0a, 0x64, 0x65, 0x63, 0x69, 0x6d,
+ 0x61, 0x6c, 0x20, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69,
+ 0x63, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x73,
+ 0x69, 0x67, 0x6e, 0x69, 0x66, 0x69, 0x63, 0x61, 0x6e, 0x74, 0x20, 0x70,
+ 0x6c, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x29, 0x0a, 0x54, 0x68, 0x65, 0x20,
+ 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x27, 0x69,
+ 0x73, 0x27, 0x20, 0x61, 0x73, 0x73, 0x75, 0x6d, 0x65, 0x73, 0x20, 0x69,
+ 0x74, 0x73, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x68, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x69, 0x64, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6e, 0x20,
+ 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x0a, 0x73,
+ 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x63, 0x6f,
+ 0x6d, 0x70, 0x75, 0x74, 0x65, 0x73, 0x20, 0x69, 0x74, 0x73, 0x20, 0x76,
+ 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e,
+ 0x69, 0x66, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65,
+ 0x73, 0x75, 0x6c, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x69, 0x74,
+ 0x73, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x68, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x69, 0x64, 0x65, 0x2e, 0x0a, 0x49, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x63, 0x61, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e,
+ 0x74, 0x69, 0x72, 0x65, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63,
+ 0x65, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x65, 0x64, 0x73, 0x2c, 0x20,
+ 0x68, 0x6f, 0x77, 0x65, 0x76, 0x65, 0x72, 0x2c, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20,
+ 0x73, 0x65, 0x72, 0x69, 0x6f, 0x75, 0x73, 0x20, 0x0a, 0x70, 0x72, 0x6f,
+ 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x2e, 0x0a, 0x2e, 0x70, 0x70, 0x0a, 0x49,
+ 0x6e, 0x20, 0x61, 0x20, 0x70, 0x75, 0x72, 0x65, 0x20, 0x6c, 0x6f, 0x67,
+ 0x69, 0x63, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20,
+ 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x73,
+ 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, 0x72, 0x72,
+ 0x65, 0x6c, 0x65, 0x76, 0x61, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x0a, 0x74,
+ 0x68, 0x65, 0x20, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x6e, 0x65,
+ 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65,
+ 0x73, 0x75, 0x6c, 0x74, 0x20, 0x28, 0x61, 0x74, 0x20, 0x77, 0x6f, 0x72,
+ 0x73, 0x74, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x65, 0x66, 0x66, 0x69, 0x63, 0x69,
+ 0x65, 0x6e, 0x63, 0x79, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x20, 0x62,
+ 0x65, 0x0a, 0x61, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x29, 0x2e,
+ 0x20, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f,
+ 0x74, 0x20, 0x74, 0x72, 0x75, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x61, 0x62,
+ 0x6f, 0x76, 0x65, 0x2e, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x64, 0x69,
+ 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x65,
+ 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x6f, 0x66, 0x20,
+ 0x27, 0x69, 0x73, 0x27, 0x20, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69,
+ 0x63, 0x74, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x77, 0x61, 0x79,
+ 0x20, 0x73, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x0a, 0x2e, 0x73, 0x70,
+ 0x0a, 0x09, 0x59, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x34, 0x35, 0x2c, 0x20,
+ 0x5a, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x33, 0x30, 0x2c, 0x20, 0x5a, 0x20,
+ 0x69, 0x73, 0x20, 0x58, 0x2a, 0x59, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x20,
+ 0x61, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x77, 0x68, 0x65,
+ 0x6e, 0x20, 0x58, 0x20, 0x69, 0x73, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x75, 0x6e, 0x69, 0x6e, 0x73,
+ 0x74, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x74, 0x65, 0x64, 0x20, 0x69, 0x6e,
+ 0x73, 0x69, 0x64, 0x65, 0x20, 0x27, 0x69, 0x73, 0x27, 0x2e, 0x0a, 0x2e,
+ 0x70, 0x70, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e,
+ 0x64, 0x20, 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x20, 0x69, 0x73,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6e,
+ 0x73, 0x77, 0x65, 0x72, 0x20, 0x5a, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x33,
+ 0x30, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x72, 0x65,
+ 0x63, 0x74, 0x21, 0x5c, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x63, 0x6f,
+ 0x72, 0x72, 0x65, 0x63, 0x74, 0x20, 0x69, 0x6e, 0x66, 0x69, 0x6e, 0x69,
+ 0x74, 0x65, 0x20, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e,
+ 0x20, 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x5a,
+ 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x33, 0x30, 0x31, 0x35, 0x2e, 0x20, 0x20,
+ 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x61, 0x63, 0x63, 0x75, 0x72,
+ 0x61, 0x63, 0x79, 0x0a, 0x69, 0x73, 0x20, 0x63, 0x61, 0x75, 0x73, 0x65,
+ 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6e,
+ 0x69, 0x74, 0x65, 0x20, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f,
+ 0x6e, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65,
+ 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x6f,
+ 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x0a,
+ 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x6f,
+ 0x66, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x72, 0x6e, 0x20, 0x63, 0x6f, 0x6d,
+ 0x70, 0x75, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x0a, 0x49, 0x74, 0x20, 0x62,
+ 0x65, 0x63, 0x6f, 0x6d, 0x65, 0x73, 0x20, 0x76, 0x65, 0x72, 0x79, 0x20,
+ 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x20,
+ 0x74, 0x6f, 0x20, 0x73, 0x61, 0x79, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20,
+ 0x69, 0x66, 0x20, 0x61, 0x6e, 0x79, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20,
+ 0x69, 0x74, 0x20, 0x6d, 0x65, 0x61, 0x6e, 0x73, 0x20, 0x77, 0x68, 0x65,
+ 0x6e, 0x0a, 0x5a, 0x20, 0x69, 0x73, 0x20, 0x62, 0x6f, 0x75, 0x6e, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x30, 0x2e, 0x33, 0x30, 0x20, 0x62, 0x79, 0x20,
+ 0x27, 0x69, 0x73, 0x27, 0x2e, 0x20, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20,
+ 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x20, 0x69, 0x73, 0x20, 0x65,
+ 0x78, 0x61, 0x63, 0x65, 0x72, 0x62, 0x61, 0x74, 0x65, 0x64, 0x20, 0x62,
+ 0x79, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65,
+ 0x6e, 0x63, 0x65, 0x73, 0x0a, 0x6f, 0x66, 0x20, 0x61, 0x72, 0x69, 0x74,
+ 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x61, 0x67, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20,
+ 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x6c,
+ 0x65, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x66, 0x69, 0x6e, 0x61,
+ 0x6c, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x74, 0x6f, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x6c, 0x69, 0x74, 0x74, 0x6c, 0x65, 0x20,
+ 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x20, 0x72, 0x65, 0x73, 0x65, 0x6d, 0x62,
+ 0x6c, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x20, 0x61, 0x6e, 0x73,
+ 0x77, 0x65, 0x72, 0x2e, 0x0a, 0x2e, 0x70, 0x70, 0x0a, 0x54, 0x68, 0x69,
+ 0x73, 0x20, 0x69, 0x73, 0x20, 0x66, 0x75, 0x72, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x72,
+ 0x72, 0x6f, 0x72, 0x73, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x69, 0x73, 0x20, 0x69, 0x6c, 0x6c, 0x75, 0x73, 0x74, 0x72, 0x61, 0x74,
+ 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61,
+ 0x63, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x0a,
+ 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x77,
+ 0x6f, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x73, 0x75,
+ 0x63, 0x63, 0x65, 0x65, 0x64, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x20,
+ 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x3a, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x09,
+ 0x58, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x36, 0x36, 0x2c, 0x20, 0x59, 0x20,
+ 0x3d, 0x20, 0x30, 0x2e, 0x34, 0x35, 0x2c, 0x20, 0x5a, 0x20, 0x3d, 0x20,
+ 0x30, 0x2e, 0x33, 0x30, 0x2c, 0x20, 0x5a, 0x20, 0x69, 0x73, 0x20, 0x58,
+ 0x2a, 0x59, 0x0a, 0x2e, 0x62, 0x72, 0x0a, 0x09, 0x58, 0x20, 0x3d, 0x20,
+ 0x30, 0x2e, 0x36, 0x37, 0x2c, 0x20, 0x59, 0x20, 0x3d, 0x20, 0x30, 0x2e,
+ 0x34, 0x35, 0x2c, 0x20, 0x5a, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x33, 0x30,
+ 0x2c, 0x20, 0x5a, 0x20, 0x69, 0x73, 0x20, 0x58, 0x2a, 0x59, 0x0a, 0x2e,
+ 0x73, 0x70, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x65, 0x61, 0x6e,
+ 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20,
+ 0x69, 0x66, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x76, 0x65,
+ 0x72, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x20,
+ 0x6f, 0x66, 0x20, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69,
+ 0x63, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x64, 0x65, 0x76, 0x69, 0x73,
+ 0x65, 0x64, 0x0a, 0x63, 0x61, 0x70, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x58, 0x20,
+ 0x77, 0x68, 0x65, 0x6e, 0x3a, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x09, 0x59,
+ 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x34, 0x35, 0x2c, 0x20, 0x5a, 0x20, 0x3d,
+ 0x20, 0x30, 0x2e, 0x33, 0x30, 0x2c, 0x20, 0x5a, 0x20, 0x69, 0x73, 0x20,
+ 0x58, 0x2a, 0x59, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x69, 0x74, 0x20, 0x69,
+ 0x73, 0x20, 0x75, 0x6e, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x20, 0x77, 0x68,
+ 0x69, 0x63, 0x68, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x73, 0x68,
+ 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65,
+ 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x74, 0x2e, 0x0a, 0x2e, 0x70, 0x70,
+ 0x0a, 0x54, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d,
+ 0x20, 0x74, 0x68, 0x65, 0x6e, 0x2c, 0x20, 0x69, 0x73, 0x20, 0x74, 0x6f,
+ 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x61,
+ 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x69, 0x6e,
+ 0x20, 0x61, 0x73, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x20,
+ 0x61, 0x20, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x0a, 0x61, 0x73, 0x20,
+ 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x68, 0x69,
+ 0x6c, 0x65, 0x20, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x6d, 0x61, 0x6b,
+ 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x65,
+ 0x66, 0x66, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x6c, 0x6f,
+ 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x20,
+ 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x2e, 0x0a,
+ 0x54, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e,
+ 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f,
+ 0x62, 0x6c, 0x65, 0x6d, 0x20, 0x68, 0x61, 0x73, 0x20, 0x74, 0x68, 0x72,
+ 0x65, 0x65, 0x20, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x20, 0x70, 0x61, 0x72,
+ 0x74, 0x73, 0x2e, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73,
+ 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, 0x70, 0x72,
+ 0x65, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x4c, 0x4f, 0x47,
+ 0x27, 0x73, 0x20, 0x0a, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74,
+ 0x69, 0x63, 0x20, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73,
+ 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x20,
+ 0x61, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x6e, 0x75, 0x6d,
+ 0x62, 0x65, 0x72, 0x73, 0x2e, 0x0a, 0x53, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x27,
+ 0x5a, 0x20, 0x69, 0x73, 0x20, 0x30, 0x2e, 0x34, 0x35, 0x2a, 0x30, 0x2e,
+ 0x36, 0x37, 0x27, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65,
+ 0x20, 0x74, 0x6f, 0x20, 0x62, 0x69, 0x6e, 0x64, 0x20, 0x5a, 0x20, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x0a, 0x6f, 0x70, 0x65, 0x6e, 0x20,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x20, 0x28, 0x30, 0x2e,
+ 0x33, 0x30, 0x2c, 0x30, 0x2e, 0x33, 0x31, 0x29, 0x2e, 0x20, 0x20, 0x0a,
+ 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x61, 0x79, 0x73, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x5a, 0x20, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x73, 0x6f,
+ 0x6d, 0x65, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x0a,
+ 0x24, 0x30, 0x2e, 0x33, 0x30, 0x20, 0x3c, 0x20, 0x5a, 0x20, 0x3c, 0x20,
+ 0x30, 0x2e, 0x33, 0x31, 0x24, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x69, 0x73, 0x20, 0x63, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6e, 0x6c,
+ 0x79, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x70, 0x72, 0x6f, 0x62, 0x61, 0x62, 0x6c, 0x79, 0x20, 0x61, 0x73, 0x20,
+ 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x76, 0x65, 0x0a,
+ 0x61, 0x73, 0x20, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x20,
+ 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x65,
+ 0x20, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x61,
+ 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x2e, 0x0a, 0x28,
+ 0x4e, 0x6f, 0x74, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x5a, 0x20,
+ 0x69, 0x73, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x62, 0x6f, 0x75, 0x6e, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x74, 0x61,
+ 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x20, 0x28,
+ 0x30, 0x2e, 0x33, 0x30, 0x2c, 0x30, 0x2e, 0x33, 0x31, 0x29, 0x2c, 0x20,
+ 0x74, 0x68, 0x69, 0x73, 0x0a, 0x69, 0x73, 0x20, 0x61, 0x20, 0x68, 0x69,
+ 0x64, 0x64, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65,
+ 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x6d,
+ 0x75, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65,
+ 0x20, 0x77, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x6f,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x75,
+ 0x73, 0x65, 0x64, 0x0a, 0x74, 0x6f, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65,
+ 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c,
+ 0x20, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x20, 0x69,
+ 0x6e, 0x20, 0x50, 0x52, 0x4f, 0x4c, 0x4f, 0x47, 0x20, 0x62, 0x75, 0x74,
+ 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x78, 0x70,
+ 0x6c, 0x69, 0x63, 0x69, 0x74, 0x6c, 0x79, 0x20, 0x76, 0x69, 0x73, 0x69,
+ 0x62, 0x6c, 0x65, 0x0a, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75,
+ 0x73, 0x65, 0x72, 0x2e, 0x20, 0x20, 0x54, 0x68, 0x72, 0x6f, 0x75, 0x67,
+ 0x68, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x70, 0x61,
+ 0x70, 0x65, 0x72, 0x20, 0x62, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73,
+ 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20, 0x28, 0x2e, 0x2e,
+ 0x2e, 0x29, 0x20, 0x6f, 0x72, 0x20, 0x5b, 0x2e, 0x2e, 0x2e, 0x5d, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x0a, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e,
+ 0x74, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63,
+ 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76,
+ 0x61, 0x6c, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x50, 0x72, 0x6f, 0x6c,
+ 0x6f, 0x67, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x73, 0x74, 0x72, 0x75,
+ 0x63, 0x74, 0x75, 0x72, 0x65, 0x73, 0x2e, 0x29, 0x0a, 0x2e, 0x70, 0x70,
+ 0x0a, 0x54, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20,
+ 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65,
+ 0x20, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73,
+ 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x0a, 0x5c, 0x26, 0x27,
+ 0x5a, 0x20, 0x69, 0x73, 0x20, 0x28, 0x58, 0x2a, 0x59, 0x29, 0x2f, 0x32,
+ 0x27, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x6c,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x66, 0x6f, 0x72, 0x6d,
+ 0x20, 0x27, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x28, 0x58,
+ 0x2c, 0x59, 0x2c, 0x54, 0x30, 0x29, 0x2c, 0x20, 0x6d, 0x75, 0x6c, 0x74,
+ 0x69, 0x70, 0x6c, 0x79, 0x28, 0x32, 0x2c, 0x5a, 0x2c, 0x54, 0x30, 0x29,
+ 0x27, 0x2e, 0x0a, 0x4e, 0x6f, 0x74, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x2a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x2f, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74,
+ 0x6f, 0x72, 0x73, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65,
+ 0x6e, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x27, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c,
+ 0x79, 0x27, 0x0a, 0x28, 0x77, 0x69, 0x74, 0x68, 0x20, 0x70, 0x61, 0x72,
+ 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x61,
+ 0x20, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x29, 0x2e, 0x20, 0x20, 0x54, 0x68, 0x69, 0x73,
+ 0x20, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20,
+ 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65,
+ 0x20, 0x73, 0x65, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x0a, 0x62, 0x65,
+ 0x20, 0x69, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65,
+ 0x20, 0x74, 0x6f, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x70, 0x61,
+ 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 0x61, 0x72, 0x65,
+ 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x74, 0x65,
+ 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x2c, 0x0a, 0x74, 0x68, 0x75,
+ 0x73, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x69, 0x6e, 0x67, 0x20,
+ 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74,
+ 0x79, 0x2e, 0x0a, 0x2e, 0x70, 0x70, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x74,
+ 0x68, 0x69, 0x72, 0x64, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x69, 0x73,
+ 0x20, 0x74, 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x20,
+ 0x61, 0x20, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x75, 0x6d, 0x62,
+ 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
+ 0x6c, 0x20, 0x27, 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65,
+ 0x73, 0x27, 0x20, 0x61, 0x62, 0x6c, 0x65, 0x0a, 0x74, 0x6f, 0x20, 0x67,
+ 0x75, 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x61,
+ 0x72, 0x63, 0x68, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x6f, 0x6c, 0x75,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x72,
+ 0x65, 0x73, 0x75, 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73,
+ 0x74, 0x65, 0x6d, 0x20, 0x69, 0x73, 0x20, 0x73, 0x75, 0x66, 0x66, 0x69,
+ 0x63, 0x69, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x20, 0x70, 0x6f, 0x77, 0x65,
+ 0x72, 0x66, 0x75, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x61,
+ 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x0a, 0x73, 0x6f, 0x6c, 0x76, 0x65,
+ 0x20, 0x65, 0x71, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x73,
+ 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20, 0x27, 0x30, 0x20, 0x69, 0x73,
+ 0x20, 0x58, 0x2a, 0x28, 0x58, 0x2d, 0x32, 0x29, 0x2b, 0x31, 0x27, 0x20,
+ 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x2e, 0x0a, 0x2e, 0x70,
+ 0x70, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x6e, 0x65, 0x78, 0x74, 0x20, 0x73,
+ 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x67, 0x69, 0x76, 0x65, 0x73,
+ 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x77, 0x68, 0x61, 0x74, 0x20,
+ 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x20,
+ 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20,
+ 0x6f, 0x66, 0x20, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69,
+ 0x63, 0x0a, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x77, 0x61, 0x79, 0x2e, 0x20,
+ 0x20, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x49, 0x49,
+ 0x20, 0x67, 0x69, 0x76, 0x65, 0x73, 0x20, 0x65, 0x78, 0x61, 0x6d, 0x70,
+ 0x6c, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x73, 0x20, 0x75,
+ 0x73, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x65,
+ 0x71, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x73, 0x6f, 0x6c, 0x75, 0x62, 0x6c,
+ 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x69, 0x74, 0x2e,
+ 0x20, 0x20, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x56,
+ 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x73, 0x20, 0x6f, 0x75,
+ 0x72, 0x20, 0x0a, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x61, 0x63, 0x68, 0x20,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x20, 0x61, 0x72, 0x69,
+ 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x73, 0x79, 0x73, 0x74,
+ 0x65, 0x6d, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x0a, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x20,
+ 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x20, 0x20, 0x53,
+ 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x56, 0x20, 0x6e, 0x6f, 0x74,
+ 0x65, 0x73, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x70, 0x6f, 0x73, 0x73,
+ 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x61, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c,
+ 0x20, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x66, 0x6c, 0x6f, 0x77, 0x20, 0x69,
+ 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, 0x76, 0x6f, 0x69,
+ 0x64, 0x73, 0x20, 0x6d, 0x61, 0x6e, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74,
+ 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x72, 0x61, 0x64, 0x69,
+ 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x66,
+ 0x6c, 0x6f, 0x77, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f,
+ 0x6e, 0x2e, 0x0a, 0x2e, 0x73, 0x68, 0x20, 0x22, 0x49, 0x49, 0x2e, 0x20,
+ 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x20, 0x52, 0x65, 0x70,
+ 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22,
+ 0x0a, 0x2e, 0x70, 0x70, 0x0a, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20,
+ 0x24, 0x49, 0x49, 0x28, 0x52, 0x52, 0x29, 0x24, 0x20, 0x74, 0x6f, 0x20,
+ 0x62, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x20,
+ 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x61,
+ 0x6c, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x24,
+ 0x52, 0x52, 0x24, 0x2e, 0x0a, 0x53, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x75, 0x70, 0x70, 0x65, 0x72, 0x20, 0x62, 0x6f, 0x75,
+ 0x6e, 0x64, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x20, 0x63, 0x61, 0x6e,
+ 0x20, 0x62, 0x65, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64,
+ 0x20, 0x6f, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x0a, 0x73, 0x69, 0x6e, 0x67,
+ 0x6c, 0x65, 0x20, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65,
+ 0x20, 0x74, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20,
+ 0x70, 0x61, 0x69, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x76, 0x61, 0x6c,
+ 0x75, 0x65, 0x73, 0x2e, 0x20, 0x20, 0x0a, 0x45, 0x61, 0x63, 0x68, 0x20,
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x68, 0x61, 0x76, 0x69, 0x6e, 0x67,
+ 0x20, 0x61, 0x6e, 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x62, 0x65, 0x69, 0x6e, 0x67, 0x20, 0x6f,
+ 0x70, 0x65, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65,
+ 0x64, 0x20, 0x0a, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x73,
+ 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6e, 0x75, 0x6d,
+ 0x62, 0x65, 0x72, 0x2e, 0x20, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x65, 0x78,
+ 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e,
+ 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x20, 0x28, 0x30, 0x2e, 0x33, 0x31,
+ 0x2c, 0x30, 0x2e, 0x33, 0x33, 0x5d, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x62, 0x65, 0x0a, 0x74, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x61,
+ 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x61,
+ 0x69, 0x72, 0x20, 0x24, 0x6c, 0x6f, 0x20, 0x30, 0x2e, 0x33, 0x31, 0x24,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x24, 0x68, 0x69, 0x20, 0x30, 0x2e, 0x33,
+ 0x33, 0x24, 0x2e, 0x20, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x62, 0x72,
+ 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x73,
+ 0x75, 0x70, 0x65, 0x72, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x65, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x69, 0x7a, 0x65,
+ 0x20, 0x76, 0x69, 0x73, 0x75, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6e, 0x66,
+ 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x77,
+ 0x72, 0x69, 0x74, 0x65, 0x69, 0x6e, 0x67, 0x20, 0x0a, 0x62, 0x6f, 0x75,
+ 0x6e, 0x64, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x70,
+ 0x61, 0x69, 0x72, 0x73, 0x2e, 0x0a, 0x41, 0x73, 0x20, 0x77, 0x65, 0x6c,
+ 0x6c, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x73, 0x75,
+ 0x61, 0x6c, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x6e, 0x75, 0x6d, 0x62,
+ 0x65, 0x72, 0x73, 0x20, 0x0a, 0x24, 0x2d, 0x20, 0x69, 0x6e, 0x66, 0x24,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x24, 0x69, 0x6e, 0x66, 0x24, 0x2c, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64,
+ 0x20, 0x61, 0x73, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20,
+ 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x2c, 0x0a, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74,
+ 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x24, 0x41, 0x4c,
+ 0x4c, 0x20, 0x78, 0x20, 0x6d, 0x6f, 0x20, 0x52, 0x52, 0x7e, 0x2d, 0x20,
+ 0x69, 0x6e, 0x66, 0x20, 0x3c, 0x20, 0x78, 0x20, 0x3c, 0x20, 0x69, 0x6e,
+ 0x66, 0x24, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x73, 0x65, 0x74, 0x20,
+ 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x75, 0x70, 0x70, 0x65, 0x72,
+ 0x20, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x20, 0x69, 0x73, 0x20, 0x64,
+ 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x61, 0x73, 0x3a, 0x0a, 0x2e,
+ 0x73, 0x70, 0x0a, 0x09, 0x24, 0x48, 0x28, 0x52, 0x52, 0x29, 0x7e, 0x3d,
+ 0x3d, 0x7e, 0x5c, 0x7b, 0x20, 0x78, 0x20, 0x73, 0x75, 0x70, 0x20, 0x62,
+ 0x20, 0x3a, 0x20, 0x78, 0x20, 0x6d, 0x6f, 0x20, 0x52, 0x52, 0x20, 0x75,
+ 0x6e, 0x69, 0x6f, 0x6e, 0x20, 0x5c, 0x7b, 0x20, 0x69, 0x6e, 0x66, 0x20,
+ 0x5c, 0x7d, 0x2c, 0x7e, 0x62, 0x20, 0x6d, 0x6f, 0x20, 0x5c, 0x7b, 0x20,
+ 0x68, 0x69, 0x20, 0x2c, 0x20, 0x68, 0x6f, 0x20, 0x5c, 0x7d, 0x20, 0x5c,
+ 0x7d, 0x20, 0x24, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x6c,
+ 0x6f, 0x77, 0x65, 0x72, 0x20, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x20,
+ 0x61, 0x73, 0x3a, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x09, 0x24, 0x4c, 0x28,
+ 0x52, 0x52, 0x29, 0x7e, 0x3d, 0x3d, 0x7e, 0x5c, 0x7b, 0x20, 0x5c, 0x26,
+ 0x20, 0x73, 0x75, 0x70, 0x20, 0x62, 0x20, 0x78, 0x20, 0x3a, 0x20, 0x78,
+ 0x20, 0x6d, 0x6f, 0x20, 0x52, 0x52, 0x20, 0x75, 0x6e, 0x69, 0x6f, 0x6e,
+ 0x20, 0x5c, 0x7b, 0x20, 0x2d, 0x69, 0x6e, 0x66, 0x20, 0x5c, 0x7d, 0x2c,
+ 0x7e, 0x62, 0x20, 0x6d, 0x6f, 0x20, 0x5c, 0x7b, 0x20, 0x6c, 0x69, 0x20,
+ 0x2c, 0x20, 0x6c, 0x6f, 0x20, 0x5c, 0x7d, 0x20, 0x5c, 0x7d, 0x20, 0x24,
+ 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x73, 0x65, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x69, 0x6e, 0x74, 0x65,
+ 0x72, 0x76, 0x61, 0x6c, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65,
+ 0x6e, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79,
+ 0x3a, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x09, 0x24, 0x49, 0x49, 0x28, 0x52,
+ 0x52, 0x29, 0x7e, 0x3d, 0x3d, 0x7e, 0x4c, 0x28, 0x52, 0x52, 0x29, 0x20,
+ 0x74, 0x69, 0x6d, 0x65, 0x73, 0x20, 0x48, 0x28, 0x52, 0x52, 0x29, 0x24,
+ 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74,
+ 0x68, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x20, 0x72, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6c, 0x6f, 0x6f, 0x73,
+ 0x65, 0x6c, 0x79, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c,
+ 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x69, 0x64,
+ 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x0a, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x70, 0x72, 0x6f, 0x70,
+ 0x72, 0x69, 0x61, 0x74, 0x65, 0x20, 0x73, 0x75, 0x62, 0x73, 0x65, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x61, 0x6c,
+ 0x73, 0x2e, 0x20, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x65, 0x78, 0x61, 0x6d,
+ 0x70, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c,
+ 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74,
+ 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x3a,
+ 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x09, 0x24, 0x5b, 0x30, 0x2e, 0x33, 0x31,
+ 0x2c, 0x31, 0x35, 0x29, 0x7e, 0x3d, 0x7e, 0x3c, 0x20, 0x6c, 0x69, 0x20,
+ 0x30, 0x2e, 0x33, 0x31, 0x2c, 0x20, 0x68, 0x6f, 0x20, 0x31, 0x35, 0x20,
+ 0x3e, 0x7e, 0x3d, 0x7e, 0x20, 0x5c, 0x7b, 0x20, 0x78, 0x20, 0x6d, 0x6f,
+ 0x20, 0x52, 0x52, 0x3a, 0x20, 0x30, 0x2e, 0x33, 0x31, 0x20, 0x3c, 0x3d,
+ 0x20, 0x78, 0x20, 0x3c, 0x20, 0x31, 0x35, 0x20, 0x5c, 0x7d, 0x24, 0x0a,
+ 0x2e, 0x62, 0x72, 0x0a, 0x09, 0x24, 0x5b, 0x2d, 0x69, 0x6e, 0x66, 0x2c,
+ 0x69, 0x6e, 0x66, 0x5d, 0x7e, 0x3d, 0x7e, 0x3c, 0x20, 0x6c, 0x69, 0x20,
+ 0x2d, 0x69, 0x6e, 0x66, 0x20, 0x2c, 0x20, 0x68, 0x69, 0x20, 0x69, 0x6e,
+ 0x66, 0x3e, 0x20, 0x7e, 0x3d, 0x7e, 0x20, 0x52, 0x52, 0x24, 0x0a, 0x2e,
+ 0x62, 0x72, 0x0a, 0x61, 0x6e, 0x64, 0x09, 0x24, 0x28, 0x2d, 0x30, 0x2e,
+ 0x35, 0x31, 0x2c, 0x69, 0x6e, 0x66, 0x5d, 0x7e, 0x3d, 0x7e, 0x3c, 0x20,
+ 0x6c, 0x6f, 0x20, 0x2d, 0x30, 0x2e, 0x35, 0x31, 0x20, 0x2c, 0x20, 0x68,
+ 0x69, 0x20, 0x69, 0x6e, 0x66, 0x20, 0x3e, 0x7e, 0x3d, 0x7e, 0x20, 0x5c,
+ 0x7b, 0x20, 0x78, 0x20, 0x6d, 0x6f, 0x20, 0x52, 0x52, 0x3a, 0x20, 0x30,
+ 0x2e, 0x35, 0x31, 0x20, 0x3c, 0x20, 0x78, 0x20, 0x5c, 0x7d, 0x24, 0x0a,
+ 0x2e, 0x73, 0x70, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x64, 0x65, 0x66, 0x69,
+ 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65,
+ 0x20, 0x63, 0x61, 0x72, 0x65, 0x66, 0x75, 0x6c, 0x6c, 0x79, 0x20, 0x65,
+ 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x20, 0x27, 0x69, 0x6e, 0x74,
+ 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x27, 0x20, 0x73, 0x75, 0x63, 0x68,
+ 0x20, 0x61, 0x73, 0x20, 0x24, 0x5b, 0x69, 0x6e, 0x66, 0x2c, 0x69, 0x6e,
+ 0x66, 0x5d, 0x24, 0x0a, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69,
+ 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x20,
+ 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6c, 0x61, 0x74, 0x65, 0x72, 0x20, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x6f,
+ 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x2e, 0x70, 0x70, 0x0a, 0x54,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x65, 0x20, 0x61, 0x72,
+ 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x61, 0x76, 0x61,
+ 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6f, 0x6e, 0x20, 0x63, 0x6f,
+ 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x73, 0x20, 0x69, 0x73, 0x20, 0x72,
+ 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x62,
+ 0x79, 0x20, 0x61, 0x0a, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x65, 0x20, 0x73,
+ 0x75, 0x62, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x24, 0x53, 0x53, 0x24, 0x2c,
+ 0x20, 0x6f, 0x66, 0x20, 0x24, 0x52, 0x52, 0x24, 0x2e, 0x20, 0x20, 0x49,
+ 0x74, 0x20, 0x69, 0x73, 0x20, 0x61, 0x73, 0x73, 0x75, 0x6d, 0x65, 0x64,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x0a, 0x24, 0x30, 0x2c, 0x31, 0x20,
+ 0x6d, 0x6f, 0x20, 0x53, 0x53, 0x24, 0x2e, 0x20, 0x20, 0x54, 0x68, 0x65,
+ 0x20, 0x73, 0x65, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x6e, 0x74, 0x65,
+ 0x72, 0x76, 0x61, 0x6c, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65,
+ 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x24, 0x53, 0x53, 0x24, 0x20,
+ 0x69, 0x73, 0x20, 0x24, 0x49, 0x49, 0x28, 0x53, 0x53, 0x29, 0x24, 0x20,
+ 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x0a,
+ 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x24, 0x52,
+ 0x52, 0x24, 0x2e, 0x20, 0x20, 0x24, 0x53, 0x53, 0x24, 0x20, 0x6d, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x62, 0x6f, 0x75,
+ 0x6e, 0x64, 0x65, 0x64, 0x20, 0x73, 0x65, 0x74, 0x20, 0x6f, 0x66, 0x20,
+ 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x72, 0x20,
+ 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x63, 0x6f,
+ 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x72, 0x65,
+ 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20,
+ 0x62, 0x79, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20,
+ 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72,
+ 0x73, 0x2e, 0x0a, 0x2e, 0x70, 0x70, 0x0a, 0x54, 0x68, 0x65, 0x72, 0x65,
+ 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x75, 0x73, 0x65, 0x66, 0x75, 0x6c,
+ 0x20, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x24, 0x49, 0x49, 0x28, 0x52, 0x52, 0x29, 0x24, 0x20, 0x74,
+ 0x6f, 0x20, 0x24, 0x49, 0x49, 0x28, 0x53, 0x53, 0x29, 0x24, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61,
+ 0x74, 0x65, 0x73, 0x0a, 0x77, 0x69, 0x74, 0x68, 0x20, 0x65, 0x61, 0x63,
+ 0x68, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72,
+ 0x76, 0x61, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x73, 0x74,
+ 0x20, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x6d, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x74, 0x3a, 0x0a, 0x2e, 0x6e,
+ 0x66, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x09, 0x24, 0x61, 0x70, 0x70, 0x72,
+ 0x6f, 0x78, 0x28, 0x3c, 0x6c, 0x2c, 0x68, 0x3e, 0x29, 0x7e, 0x3d, 0x3d,
+ 0x7e, 0x3c, 0x6c, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x2c, 0x20, 0x68,
+ 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x20, 0x3e, 0x24, 0x0a, 0x2e, 0x62,
+ 0x72, 0x0a, 0x77, 0x68, 0x65, 0x72, 0x65, 0x09, 0x24, 0x6c, 0x20, 0x70,
+ 0x72, 0x69, 0x6d, 0x65, 0x20, 0x6d, 0x6f, 0x20, 0x4c, 0x28, 0x53, 0x53,
+ 0x29, 0x2c, 0x20, 0x6c, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x20, 0x3c,
+ 0x3d, 0x20, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4e, 0x45, 0x58,
+ 0x49, 0x53, 0x54, 0x20, 0x78, 0x20, 0x6d, 0x6f, 0x20, 0x4c, 0x28, 0x53,
+ 0x53, 0x29, 0x7e, 0x6c, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x20, 0x3c,
+ 0x78, 0x3c, 0x6c, 0x24, 0x0a, 0x2e, 0x62, 0x72, 0x0a, 0x09, 0x24, 0x68,
+ 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x20, 0x6d, 0x6f, 0x20, 0x48, 0x28,
+ 0x53, 0x53, 0x29, 0x2c, 0x20, 0x68, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65,
+ 0x20, 0x3e, 0x3d, 0x20, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4e,
+ 0x45, 0x58, 0x49, 0x53, 0x54, 0x20, 0x78, 0x20, 0x6d, 0x6f, 0x20, 0x48,
+ 0x28, 0x53, 0x53, 0x29, 0x7e, 0x68, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65,
+ 0x20, 0x3e, 0x78, 0x3e, 0x68, 0x24, 0x2e, 0x0a, 0x2e, 0x70, 0x70, 0x0a,
+ 0x54, 0x68, 0x65, 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x69, 0x6e, 0x67,
+ 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x75, 0x6e,
+ 0x64, 0x73, 0x20, 0x69, 0x73, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65,
+ 0x64, 0x20, 0x61, 0x73, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x73,
+ 0x3a, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x09, 0x24, 0x6c, 0x20, 0x3c, 0x20,
+ 0x68, 0x2c, 0x20, 0x7e, 0x20, 0x6c, 0x2c, 0x68, 0x20, 0x6d, 0x6f, 0x20,
+ 0x49, 0x49, 0x28, 0x52, 0x52, 0x29, 0x7e, 0x20, 0x3c, 0x2d, 0x3e, 0x7e,
+ 0x6c, 0x3d, 0x20, 0x5c, 0x26, 0x20, 0x73, 0x75, 0x70, 0x20, 0x75, 0x20,
+ 0x78, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x20, 0x3d, 0x20, 0x5c, 0x26,
+ 0x20, 0x73, 0x75, 0x70, 0x20, 0x76, 0x20, 0x79, 0x24, 0x0a, 0x09, 0x09,
+ 0x09, 0x61, 0x6e, 0x64, 0x20, 0x24, 0x78, 0x3c, 0x79, 0x24, 0x20, 0x6f,
+ 0x72, 0x20, 0x24, 0x78, 0x3d, 0x79, 0x24, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x24, 0x75, 0x3c, 0x76, 0x24, 0x0a, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20,
+ 0x09, 0x24, 0x20, 0x68, 0x6f, 0x2c, 0x20, 0x6c, 0x69, 0x2c, 0x20, 0x68,
+ 0x69, 0x2c, 0x20, 0x6c, 0x6f, 0x24, 0x20, 0x6f, 0x63, 0x63, 0x75, 0x72,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x24, 0x78, 0x3c, 0x79, 0x24,
+ 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x73, 0x75, 0x61,
+ 0x6c, 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x0a,
+ 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x73,
+ 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x74, 0x6f,
+ 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x24, 0x2d, 0x69,
+ 0x6e, 0x66, 0x24, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x24, 0x69, 0x6e, 0x66,
+ 0x24, 0x2e, 0x20, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x6f, 0x72, 0x64,
+ 0x65, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x62, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x69, 0x73,
+ 0x20, 0x63, 0x61, 0x72, 0x65, 0x66, 0x75, 0x6c, 0x6c, 0x79, 0x20, 0x63,
+ 0x68, 0x6f, 0x73, 0x65, 0x6e, 0x20, 0x73, 0x6f, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x20,
+ 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x0a, 0x28, 0x33, 0x2e, 0x31,
+ 0x2c, 0x33, 0x2e, 0x31, 0x29, 0x20, 0x6d, 0x61, 0x70, 0x20, 0x74, 0x6f,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x20, 0x73,
+ 0x65, 0x74, 0x2e, 0x0a, 0x47, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x74, 0x68,
+ 0x69, 0x73, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x65, 0x61, 0x73, 0x69,
+ 0x6c, 0x79, 0x20, 0x76, 0x65, 0x72, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x27, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x78,
+ 0x27, 0x20, 0x67, 0x69, 0x76, 0x65, 0x73, 0x0a, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x65, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x74,
+ 0x65, 0x72, 0x76, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x24, 0x49, 0x49,
+ 0x28, 0x53, 0x53, 0x29, 0x24, 0x20, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x73,
+ 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x72, 0x69, 0x67,
+ 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61,
+ 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x24, 0x49, 0x49, 0x28, 0x52, 0x52, 0x29,
+ 0x24, 0x2e, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e,
+ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x61,
+ 0x6c, 0x6c, 0x6f, 0x77, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e,
+ 0x74, 0x65, 0x72, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76,
+ 0x61, 0x6c, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x72, 0x65,
+ 0x61, 0x64, 0x69, 0x6c, 0x79, 0x20, 0x0a, 0x63, 0x6f, 0x6d, 0x70, 0x75,
+ 0x74, 0x65, 0x64, 0x3a, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x09, 0x24, 0x3c,
+ 0x6c, 0x20, 0x73, 0x75, 0x62, 0x20, 0x31, 0x2c, 0x68, 0x20, 0x73, 0x75,
+ 0x62, 0x20, 0x31, 0x3e, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x3c,
+ 0x6c, 0x20, 0x73, 0x75, 0x62, 0x20, 0x32, 0x2c, 0x20, 0x68, 0x20, 0x73,
+ 0x75, 0x62, 0x20, 0x32, 0x3e, 0x7e, 0x3d, 0x7e, 0x24, 0x0a, 0x09, 0x09,
+ 0x24, 0x3c, 0x20, 0x6d, 0x61, 0x78, 0x28, 0x6c, 0x20, 0x73, 0x75, 0x62,
+ 0x20, 0x31, 0x20, 0x2c, 0x20, 0x6c, 0x20, 0x73, 0x75, 0x62, 0x20, 0x32,
+ 0x29, 0x2c, 0x20, 0x6d, 0x69, 0x6e, 0x28, 0x68, 0x20, 0x73, 0x75, 0x62,
+ 0x20, 0x31, 0x20, 0x2c, 0x20, 0x68, 0x20, 0x73, 0x75, 0x62, 0x20, 0x32,
+ 0x20, 0x29, 0x3e, 0x24, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x41, 0x6c, 0x73,
+ 0x6f, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76,
+ 0x61, 0x6c, 0x20, 0x24, 0x3c, 0x6c, 0x2c, 0x68, 0x3e, 0x24, 0x20, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x65, 0x6d, 0x70, 0x74, 0x79,
+ 0x20, 0x69, 0x66, 0x20, 0x24, 0x6c, 0x20, 0x3e, 0x20, 0x68, 0x24, 0x2e,
+ 0x20, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c,
+ 0x65, 0x2c, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67,
+ 0x0a, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x66, 0x69,
+ 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65,
+ 0x20, 0x24, 0x6c, 0x6f, 0x20, 0x33, 0x2e, 0x31, 0x20, 0x3e, 0x20, 0x68,
+ 0x6f, 0x20, 0x33, 0x2e, 0x31, 0x24, 0x20, 0x73, 0x6f, 0x20, 0x28, 0x33,
+ 0x2e, 0x31, 0x2c, 0x33, 0x2e, 0x31, 0x29, 0x20, 0x69, 0x73, 0x20, 0x63,
+ 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x20, 0x63, 0x6f, 0x6d,
+ 0x70, 0x75, 0x74, 0x65, 0x64, 0x0a, 0x61, 0x73, 0x20, 0x62, 0x65, 0x69,
+ 0x6e, 0x67, 0x20, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x0a, 0x2e, 0x70,
+ 0x70, 0x0a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x20,
+ 0x61, 0x72, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f, 0x64, 0x75, 0x63,
+ 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x67, 0x69,
+ 0x63, 0x20, 0x62, 0x79, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x69,
+ 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x69, 0x63,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x20, 0x41, 0x20, 0x6c, 0x6f,
+ 0x67, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62,
+ 0x6c, 0x65, 0x20, 0x49, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20,
+ 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x20,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x20, 0x24, 0x49, 0x24,
+ 0x2c, 0x0a, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x49, 0x3a,
+ 0x24, 0x49, 0x24, 0x2e, 0x20, 0x20, 0x55, 0x6e, 0x69, 0x66, 0x69, 0x63,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x49, 0x20, 0x74,
+ 0x6f, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x4a, 0x20, 0x67, 0x69, 0x76, 0x65,
+ 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77,
+ 0x69, 0x6e, 0x67, 0x0a, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x3a,
+ 0x0a, 0x2e, 0x4c, 0x42, 0x0a, 0x2e, 0x4e, 0x50, 0x0a, 0x69, 0x66, 0x20,
+ 0x4a, 0x20, 0x69, 0x73, 0x20, 0x75, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64,
+ 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20,
+ 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x2c, 0x20, 0x4a,
+ 0x3a, 0x24, 0x49, 0x24, 0x3b, 0x0a, 0x2e, 0x4e, 0x50, 0x0a, 0x69, 0x66,
+ 0x20, 0x4a, 0x20, 0x69, 0x73, 0x20, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72,
+ 0x76, 0x61, 0x6c, 0x20, 0x4a, 0x3a, 0x24, 0x4a, 0x24, 0x20, 0x74, 0x68,
+ 0x65, 0x6e, 0x0a, 0x49, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4a, 0x20, 0x61,
+ 0x72, 0x65, 0x20, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x74,
+ 0x65, 0x72, 0x76, 0x61, 0x6c, 0x20, 0x24, 0x49, 0x20, 0x69, 0x6e, 0x74,
+ 0x65, 0x72, 0x20, 0x4a, 0x24, 0x2e, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x75,
+ 0x6e, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66,
+ 0x61, 0x69, 0x6c, 0x73, 0x20, 0x69, 0x66, 0x20, 0x24, 0x49, 0x20, 0x69,
+ 0x6e, 0x74, 0x65, 0x72, 0x20, 0x4a, 0x24, 0x20, 0x69, 0x73, 0x20, 0x65,
+ 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x0a, 0x2e, 0x4e, 0x50, 0x0a, 0x61, 0x20,
+ 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x20, 0x43, 0x20, 0x69,
+ 0x73, 0x20, 0x65, 0x71, 0x75, 0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74,
+ 0x20, 0x74, 0x6f, 0x20, 0x24, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x78, 0x28,
+ 0x5b, 0x43, 0x2c, 0x43, 0x5d, 0x29, 0x24, 0x3b, 0x0a, 0x2e, 0x4e, 0x50,
+ 0x0a, 0x69, 0x66, 0x20, 0x4a, 0x20, 0x69, 0x73, 0x20, 0x62, 0x6f, 0x75,
+ 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x79, 0x74, 0x68, 0x69,
+ 0x6e, 0x67, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61,
+ 0x6e, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61,
+ 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x6e, 0x69, 0x66, 0x69, 0x63,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x73, 0x2e,
+ 0x0a, 0x2e, 0x4c, 0x45, 0x0a, 0x2e, 0x70, 0x70, 0x0a, 0x42, 0x65, 0x6c,
+ 0x6f, 0x77, 0x20, 0x61, 0x72, 0x65, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20,
+ 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x50, 0x72, 0x6f, 0x6c, 0x6f,
+ 0x67, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x73, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x69, 0x6e, 0x64, 0x69,
+ 0x6e, 0x67, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x72, 0x65, 0x73,
+ 0x75, 0x6c, 0x74, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x0a, 0x74, 0x68, 0x65,
+ 0x79, 0x20, 0x61, 0x72, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x28, 0x61,
+ 0x73, 0x73, 0x75, 0x6d, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x73, 0x20, 0x75,
+ 0x73, 0x75, 0x61, 0x6c, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x64, 0x65, 0x63,
+ 0x69, 0x6d, 0x61, 0x6c, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x73, 0x20,
+ 0x6f, 0x66, 0x20, 0x61, 0x63, 0x63, 0x75, 0x72, 0x61, 0x63, 0x79, 0x29,
+ 0x2e, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x2e, 0x6e, 0x66, 0x0a, 0x09, 0x58,
+ 0x20, 0x3d, 0x20, 0x33, 0x2e, 0x31, 0x34, 0x31, 0x35, 0x39, 0x32, 0x0a,
+ 0x09, 0x58, 0x3a, 0x28, 0x33, 0x2e, 0x31, 0x2c, 0x33, 0x2e, 0x32, 0x29,
+ 0x0a, 0x0a, 0x09, 0x58, 0x20, 0x3e, 0x20, 0x2d, 0x35, 0x2e, 0x32, 0x32,
+ 0x2c, 0x20, 0x59, 0x20, 0x3c, 0x3d, 0x20, 0x33, 0x31, 0x2c, 0x20, 0x58,
+ 0x3d, 0x59, 0x0a, 0x09, 0x58, 0x3a, 0x28, 0x2d, 0x35, 0x2e, 0x33, 0x2c,
+ 0x33, 0x32, 0x5d, 0x20, 0x20, 0x59, 0x3a, 0x28, 0x2d, 0x35, 0x2e, 0x33,
+ 0x2c, 0x33, 0x31, 0x5d, 0x0a, 0x2e, 0x66, 0x69, 0x0a, 0x2e, 0x73, 0x70,
+ 0x0a, 0x2e, 0x72, 0x68, 0x20, 0x22, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69,
+ 0x6f, 0x6e, 0x22, 0x0a, 0x2e, 0x70, 0x70, 0x0a, 0x41, 0x64, 0x64, 0x69,
+ 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6d, 0x70, 0x6c,
+ 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20,
+ 0x27, 0x61, 0x64, 0x64, 0x28, 0x49, 0x2c, 0x4a, 0x2c, 0x4b, 0x29, 0x27,
+ 0x0a, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x73, 0x61, 0x79, 0x73, 0x20,
+ 0x74, 0x68, 0x61, 0x74, 0x20, 0x4b, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x73, 0x75, 0x6d, 0x20, 0x6f, 0x66, 0x20, 0x49, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x4a, 0x2e, 0x0a, 0x5c, 0x26, 0x27, 0x61, 0x64, 0x64,
+ 0x27, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x76, 0x69, 0x65,
+ 0x77, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x72, 0x65, 0x6c,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x6e, 0x20, 0x24, 0x52, 0x52,
+ 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x20, 0x52, 0x52, 0x20, 0x74, 0x69,
+ 0x6d, 0x65, 0x73, 0x20, 0x52, 0x52, 0x24, 0x20, 0x64, 0x65, 0x66, 0x69,
+ 0x6e, 0x65, 0x64, 0x0a, 0x62, 0x79, 0x3a, 0x0a, 0x2e, 0x73, 0x70, 0x0a,
+ 0x09, 0x24, 0x61, 0x64, 0x64, 0x20, 0x7e, 0x3d, 0x3d, 0x7e, 0x20, 0x5c,
+ 0x7b, 0x3c, 0x78, 0x2c, 0x79, 0x2c, 0x7a, 0x3e, 0x3a, 0x78, 0x2c, 0x79,
+ 0x2c, 0x7a, 0x20, 0x6d, 0x6f, 0x20, 0x20, 0x52, 0x52, 0x2c, 0x7e, 0x78,
+ 0x2b, 0x79, 0x3d, 0x7a, 0x5c, 0x7d, 0x24, 0x0a, 0x2e, 0x73, 0x70, 0x0a,
+ 0x47, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x49,
+ 0x2c, 0x4a, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4b, 0x20, 0x61, 0x72,
+ 0x65, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x6c, 0x79, 0x20,
+ 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x20, 0x24,
+ 0x49, 0x2c, 0x4a, 0x2c, 0x4b, 0x24, 0x20, 0x0a, 0x72, 0x65, 0x73, 0x70,
+ 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x2c, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x79, 0x20, 0x63, 0x6f, 0x72, 0x72,
+ 0x65, 0x63, 0x74, 0x20, 0x73, 0x65, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x73,
+ 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69,
+ 0x6f, 0x6e, 0x61, 0x6c, 0x0a, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61,
+ 0x69, 0x6e, 0x20, 0x27, 0x61, 0x64, 0x64, 0x28, 0x49, 0x2c, 0x4a, 0x2c,
+ 0x4b, 0x29, 0x27, 0x20, 0x69, 0x73, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e,
+ 0x20, 0x62, 0x79, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x72, 0x69, 0x70,
+ 0x6c, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+ 0x65, 0x74, 0x20, 0x0a, 0x24, 0x61, 0x64, 0x64, 0x20, 0x69, 0x6e, 0x74,
+ 0x65, 0x72, 0x20, 0x49, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x20, 0x4a,
+ 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x20, 0x4b, 0x24, 0x2e, 0x20, 0x20,
+ 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x65, 0x74, 0x20, 0x69, 0x73,
+ 0x20, 0x68, 0x6f, 0x77, 0x65, 0x76, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x66,
+ 0x69, 0x6e, 0x69, 0x74, 0x65, 0x2c, 0x20, 0x74, 0x6f, 0x20, 0x67, 0x65,
+ 0x74, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69,
+ 0x76, 0x65, 0x6c, 0x79, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x61,
+ 0x62, 0x6c, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x64, 0x75, 0x72,
+ 0x65, 0x0a, 0x49, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x61, 0x70, 0x70,
+ 0x72, 0x6f, 0x78, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20,
+ 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x20, 0x62,
+ 0x79, 0x20, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x49, 0x2c,
+ 0x20, 0x4a, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4b, 0x0a, 0x74, 0x6f, 0x20,
+ 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x74, 0x65,
+ 0x72, 0x76, 0x61, 0x6c, 0x73, 0x2e, 0x20, 0x20, 0x0a, 0x53, 0x6f, 0x20,
+ 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x78,
+ 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x70, 0x6f,
+ 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x72, 0x69, 0x70, 0x6c,
+ 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x62,
+ 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x0a, 0x24, 0x49,
+ 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x2c, 0x20, 0x4a, 0x20, 0x70, 0x72,
+ 0x69, 0x6d, 0x65, 0x20, 0x72, 0x6f, 0x6d, 0x61, 0x6e, 0x20, 0x7e, 0x61,
+ 0x6e, 0x64, 0x7e, 0x20, 0x4b, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x24,
+ 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x6f, 0x62, 0x65, 0x79, 0x3a, 0x0a,
+ 0x2e, 0x73, 0x70, 0x0a, 0x09, 0x24, 0x61, 0x64, 0x64, 0x20, 0x69, 0x6e,
+ 0x74, 0x65, 0x72, 0x20, 0x49, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x20,
+ 0x4a, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x20, 0x4b, 0x20, 0x7e, 0x73,
+ 0x75, 0x62, 0x65, 0x71, 0x7e, 0x20, 0x49, 0x20, 0x70, 0x72, 0x69, 0x6d,
+ 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x20, 0x4a, 0x20, 0x70, 0x72,
+ 0x69, 0x6d, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x20, 0x4b, 0x20,
+ 0x70, 0x72, 0x69, 0x6d, 0x65, 0x24, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x46,
+ 0x69, 0x67, 0x75, 0x72, 0x65, 0x20, 0x31, 0x20, 0x69, 0x6c, 0x6c, 0x75,
+ 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x73, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x0a,
+ 0x2e, 0x75, 0x6c, 0x0a, 0x6e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x69, 0x6e,
+ 0x67, 0x2e, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x69,
+ 0x61, 0x6c, 0x20, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x20,
+ 0x61, 0x72, 0x65, 0x20, 0x49, 0x3a, 0x5b, 0x30, 0x2c, 0x32, 0x5d, 0x2c,
+ 0x20, 0x4a, 0x3a, 0x5b, 0x31, 0x2c, 0x33, 0x5d, 0x0a, 0x61, 0x6e, 0x64,
+ 0x20, 0x4b, 0x3a, 0x5b, 0x34, 0x2c, 0x36, 0x5d, 0x2e, 0x20, 0x20, 0x41,
+ 0x66, 0x74, 0x65, 0x72, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x69, 0x6e,
+ 0x67, 0x20, 0x27, 0x61, 0x64, 0x64, 0x28, 0x49, 0x2c, 0x4a, 0x2c, 0x4b,
+ 0x29, 0x27, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6d, 0x61, 0x6c, 0x6c,
+ 0x65, 0x73, 0x74, 0x20, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65,
+ 0x20, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x0a, 0x61, 0x72,
+ 0x65, 0x20, 0x49, 0x3a, 0x5b, 0x31, 0x2c, 0x32, 0x5d, 0x2c, 0x20, 0x4a,
+ 0x3a, 0x5b, 0x32, 0x2c, 0x33, 0x5d, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4b,
+ 0x3a, 0x5b, 0x34, 0x2c, 0x35, 0x5d, 0x2e, 0x20, 0x20, 0x4e, 0x6f, 0x74,
+ 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74,
+ 0x68, 0x72, 0x65, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61,
+ 0x6c, 0x73, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6e,
+ 0x0a, 0x6e, 0x61, 0x72, 0x72, 0x6f, 0x77, 0x65, 0x64, 0x2e, 0x0a, 0x2e,
+ 0x70, 0x70, 0x0a, 0x49, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x65, 0x61,
+ 0x73, 0x69, 0x6c, 0x79, 0x20, 0x62, 0x65, 0x20, 0x73, 0x65, 0x65, 0x6e,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x3a, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x09,
+ 0x24, 0x49, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x20, 0x73, 0x75, 0x70,
+ 0x65, 0x71, 0x20, 0x5c, 0x7b, 0x78, 0x3a, 0x3c, 0x78, 0x2c, 0x79, 0x2c,
+ 0x7a, 0x3e, 0x20, 0x7e, 0x6d, 0x6f, 0x7e, 0x20, 0x61, 0x64, 0x64, 0x20,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x20, 0x49, 0x20, 0x74, 0x69, 0x6d, 0x65,
+ 0x73, 0x20, 0x4a, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x20, 0x4b, 0x20,
+ 0x5c, 0x7d, 0x24, 0x0a, 0x2e, 0x62, 0x72, 0x0a, 0x09, 0x24, 0x4a, 0x20,
+ 0x70, 0x72, 0x69, 0x6d, 0x65, 0x20, 0x73, 0x75, 0x70, 0x65, 0x71, 0x20,
+ 0x5c, 0x7b, 0x79, 0x3a, 0x3c, 0x78, 0x2c, 0x79, 0x2c, 0x7a, 0x3e, 0x20,
+ 0x7e, 0x6d, 0x6f, 0x7e, 0x20, 0x61, 0x64, 0x64, 0x20, 0x69, 0x6e, 0x74,
+ 0x65, 0x72, 0x20, 0x49, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x20, 0x4a,
+ 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x20, 0x4b, 0x20, 0x5c, 0x7d, 0x24,
+ 0x0a, 0x2e, 0x62, 0x72, 0x0a, 0x09, 0x24, 0x4b, 0x20, 0x70, 0x72, 0x69,
+ 0x6d, 0x65, 0x20, 0x73, 0x75, 0x70, 0x65, 0x71, 0x20, 0x5c, 0x7b, 0x7a,
+ 0x3a, 0x3c, 0x78, 0x2c, 0x79, 0x2c, 0x7a, 0x3e, 0x20, 0x7e, 0x6d, 0x6f,
+ 0x7e, 0x20, 0x61, 0x64, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x20,
+ 0x49, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x20, 0x4a, 0x20, 0x74, 0x69,
+ 0x6d, 0x65, 0x73, 0x20, 0x4b, 0x20, 0x5c, 0x7d, 0x24, 0x0a, 0x2e, 0x73,
+ 0x70, 0x0a, 0x49, 0x66, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61,
+ 0x72, 0x65, 0x20, 0x27, 0x68, 0x6f, 0x6c, 0x65, 0x73, 0x27, 0x20, 0x69,
+ 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63,
+ 0x74, 0x65, 0x64, 0x20, 0x73, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6e,
+ 0x20, 0x24, 0x49, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x24, 0x20, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x73, 0x74, 0x72,
+ 0x69, 0x63, 0x74, 0x0a, 0x73, 0x75, 0x70, 0x65, 0x72, 0x73, 0x65, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x6a,
+ 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x68, 0x6f, 0x77, 0x65,
+ 0x76, 0x65, 0x72, 0x2c, 0x20, 0x24, 0x49, 0x20, 0x70, 0x72, 0x69, 0x6d,
+ 0x65, 0x24, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x73, 0x74, 0x69, 0x6c,
+ 0x6c, 0x20, 0x0a, 0x62, 0x65, 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65,
+ 0x6c, 0x79, 0x20, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65,
+ 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f,
+ 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x20, 0x54, 0x68,
+ 0x69, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x74,
+ 0x72, 0x75, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x79, 0x0a, 0x73,
+ 0x75, 0x62, 0x73, 0x65, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x24, 0x52, 0x52,
+ 0x20, 0x73, 0x75, 0x70, 0x20, 0x6e, 0x24, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x6a, 0x75, 0x73, 0x74, 0x20, 0x24, 0x61, 0x64, 0x64, 0x24, 0x2e, 0x0a,
+ 0x2e, 0x70, 0x70, 0x0a, 0x49, 0x6e, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72,
+ 0x61, 0x6c, 0x20, 0x66, 0x6f, 0x72, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x09,
+ 0x24, 0x52, 0x20, 0x73, 0x75, 0x62, 0x65, 0x71, 0x20, 0x52, 0x52, 0x20,
+ 0x73, 0x75, 0x70, 0x20, 0x6e, 0x2c, 0x7e, 0x20, 0x49, 0x20, 0x73, 0x75,
+ 0x62, 0x20, 0x31, 0x20, 0x2c, 0x20, 0x49, 0x20, 0x73, 0x75, 0x62, 0x20,
+ 0x32, 0x20, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x2c, 0x20, 0x49, 0x20,
+ 0x73, 0x75, 0x62, 0x20, 0x6e, 0x20, 0x6d, 0x6f, 0x20, 0x49, 0x49, 0x28,
+ 0x52, 0x52, 0x29, 0x24, 0x0a, 0x61, 0x6e, 0x64, 0x20, 0x24, 0x49, 0x20,
+ 0x70, 0x72, 0x69, 0x6d, 0x65, 0x20, 0x20, 0x73, 0x75, 0x62, 0x20, 0x31,
+ 0x20, 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x20, 0x20,
+ 0x73, 0x75, 0x62, 0x20, 0x32, 0x20, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x20,
+ 0x2c, 0x20, 0x49, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x20, 0x20, 0x73,
+ 0x75, 0x62, 0x20, 0x6e, 0x20, 0x6d, 0x6f, 0x20, 0x49, 0x49, 0x28, 0x52,
+ 0x52, 0x29, 0x24, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x49, 0x20, 0x77, 0x69,
+ 0x6c, 0x6c, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x0a, 0x2e, 0x62,
+ 0x72, 0x0a, 0x09, 0x24, 0x52, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x20,
+ 0x49, 0x20, 0x73, 0x75, 0x62, 0x20, 0x31, 0x20, 0x74, 0x69, 0x6d, 0x65,
+ 0x73, 0x20, 0x49, 0x20, 0x73, 0x75, 0x62, 0x20, 0x32, 0x20, 0x74, 0x69,
+ 0x6d, 0x65, 0x73, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x74, 0x69, 0x6d, 0x65,
+ 0x73, 0x20, 0x49, 0x20, 0x73, 0x75, 0x62, 0x20, 0x6e, 0x20, 0x6e, 0x61,
+ 0x72, 0x20, 0x0a, 0x49, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x20, 0x73,
+ 0x75, 0x62, 0x20, 0x31, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x20, 0x49,
+ 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x20, 0x73, 0x75, 0x62, 0x20, 0x32,
+ 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x74,
+ 0x69, 0x6d, 0x65, 0x73, 0x20, 0x49, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65,
+ 0x20, 0x73, 0x75, 0x62, 0x20, 0x24, 0x0a, 0x2e, 0x62, 0x72, 0x20, 0x0a,
+ 0x77, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x74,
+ 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x20, 0x24, 0x49, 0x20, 0x70, 0x72,
+ 0x69, 0x6d, 0x65, 0x20, 0x73, 0x75, 0x62, 0x20, 0x31, 0x20, 0x2c, 0x20,
+ 0x49, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x20, 0x73, 0x75, 0x62, 0x20,
+ 0x32, 0x20, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x2c, 0x20, 0x49, 0x20,
+ 0x70, 0x72, 0x69, 0x6d, 0x65, 0x20, 0x73, 0x75, 0x62, 0x20, 0x24, 0x0a,
+ 0x61, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x6e, 0x69, 0x71,
+ 0x75, 0x65, 0x6c, 0x6c, 0x79, 0x20, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d,
+ 0x69, 0x6e, 0x65, 0x64, 0x20, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x65, 0x73,
+ 0x74, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x20,
+ 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x6c,
+ 0x6c, 0x20, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e,
+ 0x0a, 0x0a, 0x2e, 0x73, 0x68, 0x20, 0x22, 0x49, 0x56, 0x2e, 0x20, 0x43,
+ 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x73, 0x6f, 0x6e, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x20,
+ 0x41, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x22, 0x0a,
+ 0x2e, 0x70, 0x70, 0x0a, 0x2e, 0x73, 0x68, 0x20, 0x22, 0x56, 0x2e, 0x20,
+ 0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x22, 0x0a, 0x2e, 0x70, 0x70, 0x0a, 0x2e, 0x73, 0x68,
+ 0x20, 0x22, 0x56, 0x49, 0x2e, 0x20, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72,
+ 0x79, 0x22, 0x0a, 0x2e, 0x73, 0x68, 0x20, 0x22, 0x41, 0x63, 0x6b, 0x6e,
+ 0x6f, 0x77, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73,
+ 0x22, 0x0a, 0x2e, 0x73, 0x68, 0x20, 0x22, 0x52, 0x65, 0x66, 0x65, 0x72,
+ 0x65, 0x6e, 0x63, 0x65, 0x73, 0x22, 0x0a, 0x2e, 0x6c, 0x73, 0x20, 0x31,
+ 0x0a, 0x2e, 0x5b, 0x0a, 0x24, 0x4c, 0x49, 0x53, 0x54, 0x24, 0x0a, 0x2e,
+ 0x5d, 0x0a
+};
+unsigned int paper5_11954_len = 11954;
diff --git a/drivers/staging/fsl_dce/tests/common/paper5_2048.h b/drivers/staging/fsl_dce/tests/common/paper5_2048.h
new file mode 100644
index 0000000..d202ffd
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/common/paper5_2048.h
@@ -0,0 +1,174 @@
+unsigned char paper5_2048[] = {
+ 0x2e, 0x70, 0x6e, 0x20, 0x30, 0x0a, 0x2e, 0x45, 0x51, 0x0a, 0x64, 0x65,
+ 0x6c, 0x69, 0x6d, 0x20, 0x24, 0x24, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e,
+ 0x65, 0x20, 0x52, 0x52, 0x20, 0x27, 0x62, 0x6f, 0x6c, 0x64, 0x20, 0x52,
+ 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x53, 0x53, 0x20,
+ 0x27, 0x62, 0x6f, 0x6c, 0x64, 0x20, 0x53, 0x27, 0x0a, 0x64, 0x65, 0x66,
+ 0x69, 0x6e, 0x65, 0x20, 0x49, 0x49, 0x20, 0x27, 0x62, 0x6f, 0x6c, 0x64,
+ 0x20, 0x49, 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x6d,
+ 0x6f, 0x20, 0x27, 0x22, 0x5c, 0x28, 0x6d, 0x6f, 0x22, 0x27, 0x0a, 0x64,
+ 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x45, 0x58, 0x49, 0x53, 0x54, 0x20,
+ 0x3f, 0x22, 0x5c, 0x7a, 0x5c, 0x2d, 0x5c, 0x64, 0x5c, 0x7a, 0x5c, 0x2d,
+ 0x5c, 0x72, 0x5c, 0x2d, 0x5c, 0x64, 0x5c, 0x76, 0x27, 0x30, 0x2e, 0x32,
+ 0x6d, 0x27, 0x5c, 0x28, 0x62, 0x72, 0x5c, 0x76, 0x27, 0x2d, 0x30, 0x2e,
+ 0x32, 0x6d, 0x27, 0x22, 0x3f, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65,
+ 0x20, 0x4e, 0x45, 0x58, 0x49, 0x53, 0x54, 0x20, 0x3f, 0x22, 0x5c, 0x7a,
+ 0x5c, 0x2d, 0x5c, 0x64, 0x5c, 0x7a, 0x5c, 0x6f, 0x27, 0x5c, 0x2d, 0x5c,
+ 0x28, 0x73, 0x6c, 0x27, 0x5c, 0x72, 0x5c, 0x2d, 0x5c, 0x64, 0x5c, 0x76,
+ 0x27, 0x30, 0x2e, 0x32, 0x6d, 0x27, 0x5c, 0x28, 0x62, 0x72, 0x5c, 0x76,
+ 0x27, 0x2d, 0x30, 0x2e, 0x32, 0x6d, 0x27, 0x22, 0x3f, 0x0a, 0x64, 0x65,
+ 0x66, 0x69, 0x6e, 0x65, 0x20, 0x41, 0x4c, 0x4c, 0x20, 0x3f, 0x22, 0x5c,
+ 0x6f, 0x27, 0x56, 0x2d, 0x27, 0x22, 0x3f, 0x0a, 0x64, 0x65, 0x66, 0x69,
+ 0x6e, 0x65, 0x20, 0x73, 0x75, 0x62, 0x73, 0x65, 0x74, 0x20, 0x27, 0x5c,
+ 0x28, 0x73, 0x62, 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20,
+ 0x73, 0x75, 0x62, 0x65, 0x71, 0x20, 0x20, 0x27, 0x5c, 0x28, 0x69, 0x62,
+ 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x73, 0x75, 0x70,
+ 0x73, 0x65, 0x74, 0x20, 0x27, 0x5c, 0x28, 0x73, 0x70, 0x27, 0x0a, 0x64,
+ 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x73, 0x75, 0x70, 0x65, 0x71, 0x20,
+ 0x20, 0x27, 0x5c, 0x28, 0x69, 0x70, 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69,
+ 0x6e, 0x65, 0x20, 0x6d, 0x6f, 0x20, 0x27, 0x5c, 0x28, 0x6d, 0x6f, 0x27,
+ 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x6e, 0x6d, 0x20, 0x3f,
+ 0x22, 0x5c, 0x6f, 0x27, 0x5c, 0x28, 0x6d, 0x6f, 0x5c, 0x28, 0x73, 0x6c,
+ 0x27, 0x22, 0x3f, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x6c,
+ 0x69, 0x20, 0x27, 0x5c, 0x26, 0x20, 0x73, 0x75, 0x70, 0x20, 0x5b, 0x27,
+ 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x6f, 0x20, 0x27,
+ 0x5c, 0x26, 0x20, 0x73, 0x75, 0x70, 0x20, 0x28, 0x27, 0x0a, 0x64, 0x65,
+ 0x66, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x69, 0x20, 0x27, 0x5c, 0x26, 0x20,
+ 0x73, 0x75, 0x70, 0x20, 0x5d, 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e,
+ 0x65, 0x20, 0x68, 0x6f, 0x20, 0x27, 0x5c, 0x26, 0x20, 0x73, 0x75, 0x70,
+ 0x20, 0x29, 0x27, 0x0a, 0x2e, 0x45, 0x4e, 0x0a, 0x2e, 0x6c, 0x73, 0x20,
+ 0x31, 0x09, 0x0a, 0x2e, 0x63, 0x65, 0x0a, 0x41, 0x20, 0x4c, 0x4f, 0x47,
+ 0x49, 0x43, 0x41, 0x4c, 0x20, 0x49, 0x4d, 0x50, 0x4c, 0x45, 0x4d, 0x45,
+ 0x4e, 0x54, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x4f, 0x46, 0x20, 0x41,
+ 0x52, 0x49, 0x54, 0x48, 0x4d, 0x45, 0x54, 0x49, 0x43, 0x20, 0x0a, 0x2e,
+ 0x73, 0x70, 0x20, 0x33, 0x0a, 0x2e, 0x63, 0x65, 0x0a, 0x4a, 0x6f, 0x68,
+ 0x6e, 0x20, 0x47, 0x2e, 0x20, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x79, 0x20,
+ 0x0a, 0x2e, 0x63, 0x65, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x55, 0x6e, 0x69,
+ 0x76, 0x65, 0x72, 0x73, 0x69, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x43,
+ 0x61, 0x6c, 0x67, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x41, 0x6c, 0x62, 0x65,
+ 0x72, 0x74, 0x61, 0x2c, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2e,
+ 0x0a, 0x2e, 0x73, 0x70, 0x20, 0x32, 0x30, 0x0a, 0x5c, 0x75, 0x31, 0x5c,
+ 0x64, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x27, 0x73, 0x20, 0x50, 0x72,
+ 0x65, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
+ 0x73, 0x3a, 0x20, 0x4d, 0x61, 0x6e, 0x2d, 0x4d, 0x61, 0x63, 0x68, 0x69,
+ 0x6e, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x47,
+ 0x72, 0x6f, 0x75, 0x70, 0x2c, 0x20, 0x44, 0x65, 0x70, 0x61, 0x72, 0x74,
+ 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x0a, 0x43, 0x6f, 0x6d, 0x70,
+ 0x75, 0x74, 0x65, 0x72, 0x20, 0x53, 0x63, 0x69, 0x65, 0x6e, 0x63, 0x65,
+ 0x2c, 0x20, 0x54, 0x68, 0x65, 0x20, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72,
+ 0x73, 0x69, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x61, 0x6c, 0x67,
+ 0x61, 0x72, 0x79, 0x2c, 0x20, 0x32, 0x35, 0x30, 0x30, 0x20, 0x55, 0x6e,
+ 0x69, 0x76, 0x65, 0x72, 0x73, 0x69, 0x74, 0x79, 0x20, 0x44, 0x72, 0x69,
+ 0x76, 0x65, 0x20, 0x4e, 0x57, 0x0a, 0x43, 0x61, 0x6c, 0x67, 0x61, 0x72,
+ 0x79, 0x2c, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x20, 0x54, 0x32,
+ 0x4e, 0x20, 0x31, 0x4e, 0x34, 0x2e, 0x20, 0x50, 0x68, 0x6f, 0x6e, 0x65,
+ 0x3a, 0x20, 0x28, 0x34, 0x30, 0x33, 0x29, 0x32, 0x32, 0x30, 0x2d, 0x36,
+ 0x30, 0x38, 0x37, 0x2e, 0x20, 0x20, 0x0a, 0x2e, 0x62, 0x72, 0x0a, 0x2e,
+ 0x6e, 0x66, 0x0a, 0x55, 0x55, 0x43, 0x50, 0x3a, 0x20, 0x20, 0x2e, 0x2e,
+ 0x2e, 0x21, 0x7b, 0x69, 0x68, 0x6e, 0x70, 0x34, 0x2c, 0x75, 0x62, 0x63,
+ 0x2d, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x7d, 0x21, 0x61, 0x6c, 0x62,
+ 0x65, 0x72, 0x74, 0x61, 0x21, 0x63, 0x61, 0x6c, 0x67, 0x61, 0x72, 0x79,
+ 0x21, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x79, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x21, 0x6e, 0x72, 0x6c, 0x2d, 0x63,
+ 0x73, 0x73, 0x21, 0x63, 0x61, 0x6c, 0x67, 0x61, 0x72, 0x79, 0x21, 0x63,
+ 0x6c, 0x65, 0x61, 0x72, 0x79, 0x0a, 0x41, 0x52, 0x50, 0x41, 0x3a, 0x20,
+ 0x20, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x79, 0x2e, 0x63, 0x61, 0x6c, 0x67,
+ 0x61, 0x72, 0x79, 0x2e, 0x75, 0x62, 0x63, 0x40, 0x63, 0x73, 0x6e, 0x65,
+ 0x74, 0x2d, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x0a, 0x43, 0x44, 0x4e, 0x3a,
+ 0x20, 0x20, 0x20, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x79, 0x40, 0x63, 0x61,
+ 0x6c, 0x67, 0x61, 0x72, 0x79, 0x0a, 0x2e, 0x66, 0x69, 0x0a, 0x2e, 0x73,
+ 0x70, 0x20, 0x32, 0x0a, 0x2e, 0x6c, 0x73, 0x20, 0x32, 0x0a, 0x2e, 0x62,
+ 0x70, 0x20, 0x30, 0x0a, 0x2e, 0x6c, 0x73, 0x20, 0x32, 0x0a, 0x2e, 0x63,
+ 0x65, 0x0a, 0x41, 0x62, 0x73, 0x74, 0x72, 0x61, 0x63, 0x74, 0x0a, 0x2e,
+ 0x70, 0x70, 0x0a, 0x53, 0x6f, 0x20, 0x66, 0x61, 0x72, 0x20, 0x69, 0x6d,
+ 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x61, 0x72,
+ 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x69, 0x6e, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x20, 0x70, 0x72,
+ 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x0a, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x6e, 0x6f, 0x6e, 0x2d,
+ 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x20, 0x20, 0x41, 0x20,
+ 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x73, 0x63,
+ 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x75, 0x72,
+ 0x20, 0x6f, 0x66, 0x20, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74,
+ 0x69, 0x63, 0x0a, 0x6f, 0x6e, 0x20, 0x61, 0x63, 0x74, 0x75, 0x61, 0x6c,
+ 0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x75, 0x73,
+ 0x69, 0x6e, 0x67, 0x20, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x65, 0x20, 0x70,
+ 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x75, 0x6d,
+ 0x62, 0x65, 0x72, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x72, 0x65, 0x61, 0x64, 0x69, 0x6c, 0x79, 0x20, 0x61, 0x76, 0x61, 0x69,
+ 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x20, 0x20, 0x0a, 0x55, 0x73, 0x69,
+ 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x20,
+ 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x20, 0x61, 0x20, 0x73,
+ 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x61,
+ 0x6c, 0x20, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63,
+ 0x20, 0x69, 0x73, 0x20, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65,
+ 0x2e, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62,
+ 0x65, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65,
+ 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x69, 0x6e, 0x20, 0x50, 0x72, 0x6f, 0x6c, 0x6f, 0x67, 0x2e,
+ 0x0a, 0x41, 0x73, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
+ 0x68, 0x61, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x75,
+ 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x62,
+ 0x61, 0x73, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73,
+ 0x75, 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65,
+ 0x6d, 0x20, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x73, 0x20, 0x61, 0x20,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x69, 0x73, 0x65,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x66, 0x75,
+ 0x6c, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x69, 0x6e,
+ 0x67, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x69, 0x73, 0x20, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
+ 0x6c, 0x79, 0x0a, 0x76, 0x65, 0x72, 0x79, 0x20, 0x65, 0x66, 0x66, 0x69,
+ 0x63, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x2e, 0x62, 0x70, 0x0a, 0x2e,
+ 0x73, 0x68, 0x20, 0x22, 0x31, 0x20, 0x49, 0x6e, 0x74, 0x72, 0x6f, 0x64,
+ 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x0a, 0x2e, 0x70, 0x70, 0x0a,
+ 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61,
+ 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x69, 0x6d, 0x73, 0x20, 0x74,
+ 0x6f, 0x20, 0x75, 0x73, 0x65, 0x20, 0x73, 0x65, 0x74, 0x73, 0x20, 0x6f,
+ 0x66, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x6f,
+ 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x65, 0x20, 0x61, 0x73, 0x0a, 0x73, 0x74,
+ 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20,
+ 0x61, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x69, 0x6e,
+ 0x67, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x2e, 0x0a,
+ 0x42, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6d,
+ 0x61, 0x6e, 0x79, 0x20, 0x70, 0x72, 0x61, 0x63, 0x74, 0x69, 0x63, 0x61,
+ 0x6c, 0x20, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x69,
+ 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20,
+ 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x6f,
+ 0x66, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x0a, 0x63, 0x61, 0x6e, 0x6e,
+ 0x6f, 0x74, 0x20, 0x28, 0x79, 0x65, 0x74, 0x29, 0x20, 0x62, 0x65, 0x20,
+ 0x75, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x77, 0x61, 0x79, 0x2e, 0x20, 0x20, 0x20, 0x48, 0x6f, 0x77, 0x65,
+ 0x76, 0x65, 0x72, 0x2c, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x73, 0x74,
+ 0x72, 0x69, 0x63, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x0a,
+ 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x6f, 0x72,
+ 0x6d, 0x75, 0x6c, 0x61, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74,
+ 0x6f, 0x20, 0x48, 0x6f, 0x72, 0x6e, 0x20, 0x63, 0x6c, 0x61, 0x75, 0x73,
+ 0x65, 0x73, 0x20, 0x70, 0x72, 0x61, 0x63, 0x74, 0x69, 0x63, 0x61, 0x6c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x66, 0x66, 0x69, 0x63, 0x69, 0x65,
+ 0x6e, 0x74, 0x0a, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x73,
+ 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20, 0x50, 0x52, 0x4f,
+ 0x4c, 0x4f, 0x47, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6f, 0x62, 0x74, 0x61,
+ 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x0a, 0x4f, 0x6e, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x70, 0x72,
+ 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x6f,
+ 0x67, 0x69, 0x63, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d,
+ 0x69, 0x6e, 0x67, 0x20, 0x69, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x78,
+ 0x74, 0x65, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x61, 0x72,
+ 0x65, 0x61, 0x0a, 0x6f, 0x66, 0x20, 0x70, 0x72, 0x61, 0x63, 0x74, 0x69,
+ 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65,
+ 0x66, 0x66, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x63, 0x79, 0x20, 0x74, 0x6f,
+ 0x20, 0x61, 0x6e, 0x20, 0x65, 0x76, 0x65, 0x72, 0x20, 0x77, 0x69, 0x64,
+ 0x65, 0x72, 0x20, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x66, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x65, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x2e, 0x20, 0x20, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70,
+ 0x61, 0x70, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65,
+ 0x72, 0x73, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x6e, 0x20, 0x69,
+ 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x0a
+};
+unsigned int paper5_2048_len = 2048;
diff --git a/drivers/staging/fsl_dce/tests/common/paper5_4096.h b/drivers/staging/fsl_dce/tests/common/paper5_4096.h
new file mode 100644
index 0000000..e4b77d7
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/common/paper5_4096.h
@@ -0,0 +1,345 @@
+unsigned char paper5_4096[] = {
+ 0x2e, 0x70, 0x6e, 0x20, 0x30, 0x0a, 0x2e, 0x45, 0x51, 0x0a, 0x64, 0x65,
+ 0x6c, 0x69, 0x6d, 0x20, 0x24, 0x24, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e,
+ 0x65, 0x20, 0x52, 0x52, 0x20, 0x27, 0x62, 0x6f, 0x6c, 0x64, 0x20, 0x52,
+ 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x53, 0x53, 0x20,
+ 0x27, 0x62, 0x6f, 0x6c, 0x64, 0x20, 0x53, 0x27, 0x0a, 0x64, 0x65, 0x66,
+ 0x69, 0x6e, 0x65, 0x20, 0x49, 0x49, 0x20, 0x27, 0x62, 0x6f, 0x6c, 0x64,
+ 0x20, 0x49, 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x6d,
+ 0x6f, 0x20, 0x27, 0x22, 0x5c, 0x28, 0x6d, 0x6f, 0x22, 0x27, 0x0a, 0x64,
+ 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x45, 0x58, 0x49, 0x53, 0x54, 0x20,
+ 0x3f, 0x22, 0x5c, 0x7a, 0x5c, 0x2d, 0x5c, 0x64, 0x5c, 0x7a, 0x5c, 0x2d,
+ 0x5c, 0x72, 0x5c, 0x2d, 0x5c, 0x64, 0x5c, 0x76, 0x27, 0x30, 0x2e, 0x32,
+ 0x6d, 0x27, 0x5c, 0x28, 0x62, 0x72, 0x5c, 0x76, 0x27, 0x2d, 0x30, 0x2e,
+ 0x32, 0x6d, 0x27, 0x22, 0x3f, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65,
+ 0x20, 0x4e, 0x45, 0x58, 0x49, 0x53, 0x54, 0x20, 0x3f, 0x22, 0x5c, 0x7a,
+ 0x5c, 0x2d, 0x5c, 0x64, 0x5c, 0x7a, 0x5c, 0x6f, 0x27, 0x5c, 0x2d, 0x5c,
+ 0x28, 0x73, 0x6c, 0x27, 0x5c, 0x72, 0x5c, 0x2d, 0x5c, 0x64, 0x5c, 0x76,
+ 0x27, 0x30, 0x2e, 0x32, 0x6d, 0x27, 0x5c, 0x28, 0x62, 0x72, 0x5c, 0x76,
+ 0x27, 0x2d, 0x30, 0x2e, 0x32, 0x6d, 0x27, 0x22, 0x3f, 0x0a, 0x64, 0x65,
+ 0x66, 0x69, 0x6e, 0x65, 0x20, 0x41, 0x4c, 0x4c, 0x20, 0x3f, 0x22, 0x5c,
+ 0x6f, 0x27, 0x56, 0x2d, 0x27, 0x22, 0x3f, 0x0a, 0x64, 0x65, 0x66, 0x69,
+ 0x6e, 0x65, 0x20, 0x73, 0x75, 0x62, 0x73, 0x65, 0x74, 0x20, 0x27, 0x5c,
+ 0x28, 0x73, 0x62, 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20,
+ 0x73, 0x75, 0x62, 0x65, 0x71, 0x20, 0x20, 0x27, 0x5c, 0x28, 0x69, 0x62,
+ 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x73, 0x75, 0x70,
+ 0x73, 0x65, 0x74, 0x20, 0x27, 0x5c, 0x28, 0x73, 0x70, 0x27, 0x0a, 0x64,
+ 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x73, 0x75, 0x70, 0x65, 0x71, 0x20,
+ 0x20, 0x27, 0x5c, 0x28, 0x69, 0x70, 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69,
+ 0x6e, 0x65, 0x20, 0x6d, 0x6f, 0x20, 0x27, 0x5c, 0x28, 0x6d, 0x6f, 0x27,
+ 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x6e, 0x6d, 0x20, 0x3f,
+ 0x22, 0x5c, 0x6f, 0x27, 0x5c, 0x28, 0x6d, 0x6f, 0x5c, 0x28, 0x73, 0x6c,
+ 0x27, 0x22, 0x3f, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x6c,
+ 0x69, 0x20, 0x27, 0x5c, 0x26, 0x20, 0x73, 0x75, 0x70, 0x20, 0x5b, 0x27,
+ 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x6f, 0x20, 0x27,
+ 0x5c, 0x26, 0x20, 0x73, 0x75, 0x70, 0x20, 0x28, 0x27, 0x0a, 0x64, 0x65,
+ 0x66, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x69, 0x20, 0x27, 0x5c, 0x26, 0x20,
+ 0x73, 0x75, 0x70, 0x20, 0x5d, 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e,
+ 0x65, 0x20, 0x68, 0x6f, 0x20, 0x27, 0x5c, 0x26, 0x20, 0x73, 0x75, 0x70,
+ 0x20, 0x29, 0x27, 0x0a, 0x2e, 0x45, 0x4e, 0x0a, 0x2e, 0x6c, 0x73, 0x20,
+ 0x31, 0x09, 0x0a, 0x2e, 0x63, 0x65, 0x0a, 0x41, 0x20, 0x4c, 0x4f, 0x47,
+ 0x49, 0x43, 0x41, 0x4c, 0x20, 0x49, 0x4d, 0x50, 0x4c, 0x45, 0x4d, 0x45,
+ 0x4e, 0x54, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x4f, 0x46, 0x20, 0x41,
+ 0x52, 0x49, 0x54, 0x48, 0x4d, 0x45, 0x54, 0x49, 0x43, 0x20, 0x0a, 0x2e,
+ 0x73, 0x70, 0x20, 0x33, 0x0a, 0x2e, 0x63, 0x65, 0x0a, 0x4a, 0x6f, 0x68,
+ 0x6e, 0x20, 0x47, 0x2e, 0x20, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x79, 0x20,
+ 0x0a, 0x2e, 0x63, 0x65, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x55, 0x6e, 0x69,
+ 0x76, 0x65, 0x72, 0x73, 0x69, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x43,
+ 0x61, 0x6c, 0x67, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x41, 0x6c, 0x62, 0x65,
+ 0x72, 0x74, 0x61, 0x2c, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2e,
+ 0x0a, 0x2e, 0x73, 0x70, 0x20, 0x32, 0x30, 0x0a, 0x5c, 0x75, 0x31, 0x5c,
+ 0x64, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x27, 0x73, 0x20, 0x50, 0x72,
+ 0x65, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
+ 0x73, 0x3a, 0x20, 0x4d, 0x61, 0x6e, 0x2d, 0x4d, 0x61, 0x63, 0x68, 0x69,
+ 0x6e, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x47,
+ 0x72, 0x6f, 0x75, 0x70, 0x2c, 0x20, 0x44, 0x65, 0x70, 0x61, 0x72, 0x74,
+ 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x0a, 0x43, 0x6f, 0x6d, 0x70,
+ 0x75, 0x74, 0x65, 0x72, 0x20, 0x53, 0x63, 0x69, 0x65, 0x6e, 0x63, 0x65,
+ 0x2c, 0x20, 0x54, 0x68, 0x65, 0x20, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72,
+ 0x73, 0x69, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x61, 0x6c, 0x67,
+ 0x61, 0x72, 0x79, 0x2c, 0x20, 0x32, 0x35, 0x30, 0x30, 0x20, 0x55, 0x6e,
+ 0x69, 0x76, 0x65, 0x72, 0x73, 0x69, 0x74, 0x79, 0x20, 0x44, 0x72, 0x69,
+ 0x76, 0x65, 0x20, 0x4e, 0x57, 0x0a, 0x43, 0x61, 0x6c, 0x67, 0x61, 0x72,
+ 0x79, 0x2c, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x20, 0x54, 0x32,
+ 0x4e, 0x20, 0x31, 0x4e, 0x34, 0x2e, 0x20, 0x50, 0x68, 0x6f, 0x6e, 0x65,
+ 0x3a, 0x20, 0x28, 0x34, 0x30, 0x33, 0x29, 0x32, 0x32, 0x30, 0x2d, 0x36,
+ 0x30, 0x38, 0x37, 0x2e, 0x20, 0x20, 0x0a, 0x2e, 0x62, 0x72, 0x0a, 0x2e,
+ 0x6e, 0x66, 0x0a, 0x55, 0x55, 0x43, 0x50, 0x3a, 0x20, 0x20, 0x2e, 0x2e,
+ 0x2e, 0x21, 0x7b, 0x69, 0x68, 0x6e, 0x70, 0x34, 0x2c, 0x75, 0x62, 0x63,
+ 0x2d, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x7d, 0x21, 0x61, 0x6c, 0x62,
+ 0x65, 0x72, 0x74, 0x61, 0x21, 0x63, 0x61, 0x6c, 0x67, 0x61, 0x72, 0x79,
+ 0x21, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x79, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x21, 0x6e, 0x72, 0x6c, 0x2d, 0x63,
+ 0x73, 0x73, 0x21, 0x63, 0x61, 0x6c, 0x67, 0x61, 0x72, 0x79, 0x21, 0x63,
+ 0x6c, 0x65, 0x61, 0x72, 0x79, 0x0a, 0x41, 0x52, 0x50, 0x41, 0x3a, 0x20,
+ 0x20, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x79, 0x2e, 0x63, 0x61, 0x6c, 0x67,
+ 0x61, 0x72, 0x79, 0x2e, 0x75, 0x62, 0x63, 0x40, 0x63, 0x73, 0x6e, 0x65,
+ 0x74, 0x2d, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x0a, 0x43, 0x44, 0x4e, 0x3a,
+ 0x20, 0x20, 0x20, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x79, 0x40, 0x63, 0x61,
+ 0x6c, 0x67, 0x61, 0x72, 0x79, 0x0a, 0x2e, 0x66, 0x69, 0x0a, 0x2e, 0x73,
+ 0x70, 0x20, 0x32, 0x0a, 0x2e, 0x6c, 0x73, 0x20, 0x32, 0x0a, 0x2e, 0x62,
+ 0x70, 0x20, 0x30, 0x0a, 0x2e, 0x6c, 0x73, 0x20, 0x32, 0x0a, 0x2e, 0x63,
+ 0x65, 0x0a, 0x41, 0x62, 0x73, 0x74, 0x72, 0x61, 0x63, 0x74, 0x0a, 0x2e,
+ 0x70, 0x70, 0x0a, 0x53, 0x6f, 0x20, 0x66, 0x61, 0x72, 0x20, 0x69, 0x6d,
+ 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x61, 0x72,
+ 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x69, 0x6e, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x20, 0x70, 0x72,
+ 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x0a, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x6e, 0x6f, 0x6e, 0x2d,
+ 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x20, 0x20, 0x41, 0x20,
+ 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x73, 0x63,
+ 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x75, 0x72,
+ 0x20, 0x6f, 0x66, 0x20, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74,
+ 0x69, 0x63, 0x0a, 0x6f, 0x6e, 0x20, 0x61, 0x63, 0x74, 0x75, 0x61, 0x6c,
+ 0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x75, 0x73,
+ 0x69, 0x6e, 0x67, 0x20, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x65, 0x20, 0x70,
+ 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x75, 0x6d,
+ 0x62, 0x65, 0x72, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x72, 0x65, 0x61, 0x64, 0x69, 0x6c, 0x79, 0x20, 0x61, 0x76, 0x61, 0x69,
+ 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x20, 0x20, 0x0a, 0x55, 0x73, 0x69,
+ 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x20,
+ 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x20, 0x61, 0x20, 0x73,
+ 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x61,
+ 0x6c, 0x20, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63,
+ 0x20, 0x69, 0x73, 0x20, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65,
+ 0x2e, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62,
+ 0x65, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65,
+ 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x69, 0x6e, 0x20, 0x50, 0x72, 0x6f, 0x6c, 0x6f, 0x67, 0x2e,
+ 0x0a, 0x41, 0x73, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
+ 0x68, 0x61, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x75,
+ 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x62,
+ 0x61, 0x73, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73,
+ 0x75, 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65,
+ 0x6d, 0x20, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x73, 0x20, 0x61, 0x20,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x69, 0x73, 0x65,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x66, 0x75,
+ 0x6c, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x69, 0x6e,
+ 0x67, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x69, 0x73, 0x20, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
+ 0x6c, 0x79, 0x0a, 0x76, 0x65, 0x72, 0x79, 0x20, 0x65, 0x66, 0x66, 0x69,
+ 0x63, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x2e, 0x62, 0x70, 0x0a, 0x2e,
+ 0x73, 0x68, 0x20, 0x22, 0x31, 0x20, 0x49, 0x6e, 0x74, 0x72, 0x6f, 0x64,
+ 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x0a, 0x2e, 0x70, 0x70, 0x0a,
+ 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61,
+ 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x69, 0x6d, 0x73, 0x20, 0x74,
+ 0x6f, 0x20, 0x75, 0x73, 0x65, 0x20, 0x73, 0x65, 0x74, 0x73, 0x20, 0x6f,
+ 0x66, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x6f,
+ 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x65, 0x20, 0x61, 0x73, 0x0a, 0x73, 0x74,
+ 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20,
+ 0x61, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x69, 0x6e,
+ 0x67, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x2e, 0x0a,
+ 0x42, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6d,
+ 0x61, 0x6e, 0x79, 0x20, 0x70, 0x72, 0x61, 0x63, 0x74, 0x69, 0x63, 0x61,
+ 0x6c, 0x20, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x69,
+ 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20,
+ 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x6f,
+ 0x66, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x0a, 0x63, 0x61, 0x6e, 0x6e,
+ 0x6f, 0x74, 0x20, 0x28, 0x79, 0x65, 0x74, 0x29, 0x20, 0x62, 0x65, 0x20,
+ 0x75, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x77, 0x61, 0x79, 0x2e, 0x20, 0x20, 0x20, 0x48, 0x6f, 0x77, 0x65,
+ 0x76, 0x65, 0x72, 0x2c, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x73, 0x74,
+ 0x72, 0x69, 0x63, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x0a,
+ 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x6f, 0x72,
+ 0x6d, 0x75, 0x6c, 0x61, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74,
+ 0x6f, 0x20, 0x48, 0x6f, 0x72, 0x6e, 0x20, 0x63, 0x6c, 0x61, 0x75, 0x73,
+ 0x65, 0x73, 0x20, 0x70, 0x72, 0x61, 0x63, 0x74, 0x69, 0x63, 0x61, 0x6c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x66, 0x66, 0x69, 0x63, 0x69, 0x65,
+ 0x6e, 0x74, 0x0a, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x73,
+ 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20, 0x50, 0x52, 0x4f,
+ 0x4c, 0x4f, 0x47, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6f, 0x62, 0x74, 0x61,
+ 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x0a, 0x4f, 0x6e, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x70, 0x72,
+ 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x6f,
+ 0x67, 0x69, 0x63, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d,
+ 0x69, 0x6e, 0x67, 0x20, 0x69, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x78,
+ 0x74, 0x65, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x61, 0x72,
+ 0x65, 0x61, 0x0a, 0x6f, 0x66, 0x20, 0x70, 0x72, 0x61, 0x63, 0x74, 0x69,
+ 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65,
+ 0x66, 0x66, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x63, 0x79, 0x20, 0x74, 0x6f,
+ 0x20, 0x61, 0x6e, 0x20, 0x65, 0x76, 0x65, 0x72, 0x20, 0x77, 0x69, 0x64,
+ 0x65, 0x72, 0x20, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x66, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x65, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x2e, 0x20, 0x20, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70,
+ 0x61, 0x70, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65,
+ 0x72, 0x73, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x6e, 0x20, 0x69,
+ 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d,
+ 0x65, 0x74, 0x69, 0x63, 0x2e, 0x0a, 0x2e, 0x70, 0x70, 0x0a, 0x54, 0x6f,
+ 0x20, 0x73, 0x65, 0x65, 0x20, 0x77, 0x68, 0x79, 0x20, 0x61, 0x72, 0x69,
+ 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x61, 0x73, 0x20, 0x69,
+ 0x74, 0x20, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x6c,
+ 0x79, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65,
+ 0x64, 0x20, 0x69, 0x6e, 0x20, 0x50, 0x52, 0x4f, 0x4c, 0x4f, 0x47, 0x20,
+ 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x0a, 0x69, 0x73, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x63,
+ 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x78,
+ 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x3a, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x2e,
+ 0x6e, 0x66, 0x0a, 0x09, 0x58, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x36, 0x37,
+ 0x2c, 0x20, 0x59, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x34, 0x35, 0x2c, 0x20,
+ 0x5a, 0x20, 0x69, 0x73, 0x20, 0x58, 0x2a, 0x59, 0x2c, 0x20, 0x5a, 0x20,
+ 0x3d, 0x20, 0x30, 0x2e, 0x33, 0x30, 0x0a, 0x2e, 0x66, 0x69, 0x0a, 0x2e,
+ 0x73, 0x70, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x27, 0x45, 0x64,
+ 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x68, 0x20, 0x73, 0x74, 0x79, 0x6c,
+ 0x65, 0x27, 0x20, 0x50, 0x72, 0x6f, 0x6c, 0x6f, 0x67, 0x73, 0x2e, 0x0a,
+ 0x28, 0x46, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d,
+ 0x65, 0x6e, 0x74, 0x20, 0x77, 0x65, 0x20, 0x61, 0x73, 0x73, 0x75, 0x6d,
+ 0x65, 0x20, 0x61, 0x6e, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x79,
+ 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x69, 0x6e, 0x67,
+ 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x0a, 0x64, 0x65, 0x63, 0x69, 0x6d,
+ 0x61, 0x6c, 0x20, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69,
+ 0x63, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x73,
+ 0x69, 0x67, 0x6e, 0x69, 0x66, 0x69, 0x63, 0x61, 0x6e, 0x74, 0x20, 0x70,
+ 0x6c, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x29, 0x0a, 0x54, 0x68, 0x65, 0x20,
+ 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x27, 0x69,
+ 0x73, 0x27, 0x20, 0x61, 0x73, 0x73, 0x75, 0x6d, 0x65, 0x73, 0x20, 0x69,
+ 0x74, 0x73, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x68, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x69, 0x64, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6e, 0x20,
+ 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x0a, 0x73,
+ 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x63, 0x6f,
+ 0x6d, 0x70, 0x75, 0x74, 0x65, 0x73, 0x20, 0x69, 0x74, 0x73, 0x20, 0x76,
+ 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e,
+ 0x69, 0x66, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65,
+ 0x73, 0x75, 0x6c, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x69, 0x74,
+ 0x73, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x68, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x69, 0x64, 0x65, 0x2e, 0x0a, 0x49, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x63, 0x61, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e,
+ 0x74, 0x69, 0x72, 0x65, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63,
+ 0x65, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x65, 0x64, 0x73, 0x2c, 0x20,
+ 0x68, 0x6f, 0x77, 0x65, 0x76, 0x65, 0x72, 0x2c, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20,
+ 0x73, 0x65, 0x72, 0x69, 0x6f, 0x75, 0x73, 0x20, 0x0a, 0x70, 0x72, 0x6f,
+ 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x2e, 0x0a, 0x2e, 0x70, 0x70, 0x0a, 0x49,
+ 0x6e, 0x20, 0x61, 0x20, 0x70, 0x75, 0x72, 0x65, 0x20, 0x6c, 0x6f, 0x67,
+ 0x69, 0x63, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20,
+ 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x73,
+ 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, 0x72, 0x72,
+ 0x65, 0x6c, 0x65, 0x76, 0x61, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x0a, 0x74,
+ 0x68, 0x65, 0x20, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x6e, 0x65,
+ 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65,
+ 0x73, 0x75, 0x6c, 0x74, 0x20, 0x28, 0x61, 0x74, 0x20, 0x77, 0x6f, 0x72,
+ 0x73, 0x74, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x65, 0x66, 0x66, 0x69, 0x63, 0x69,
+ 0x65, 0x6e, 0x63, 0x79, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x20, 0x62,
+ 0x65, 0x0a, 0x61, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x29, 0x2e,
+ 0x20, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f,
+ 0x74, 0x20, 0x74, 0x72, 0x75, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x61, 0x62,
+ 0x6f, 0x76, 0x65, 0x2e, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x64, 0x69,
+ 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x65,
+ 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x6f, 0x66, 0x20,
+ 0x27, 0x69, 0x73, 0x27, 0x20, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69,
+ 0x63, 0x74, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x77, 0x61, 0x79,
+ 0x20, 0x73, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x0a, 0x2e, 0x73, 0x70,
+ 0x0a, 0x09, 0x59, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x34, 0x35, 0x2c, 0x20,
+ 0x5a, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x33, 0x30, 0x2c, 0x20, 0x5a, 0x20,
+ 0x69, 0x73, 0x20, 0x58, 0x2a, 0x59, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x20,
+ 0x61, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x77, 0x68, 0x65,
+ 0x6e, 0x20, 0x58, 0x20, 0x69, 0x73, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x75, 0x6e, 0x69, 0x6e, 0x73,
+ 0x74, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x74, 0x65, 0x64, 0x20, 0x69, 0x6e,
+ 0x73, 0x69, 0x64, 0x65, 0x20, 0x27, 0x69, 0x73, 0x27, 0x2e, 0x0a, 0x2e,
+ 0x70, 0x70, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e,
+ 0x64, 0x20, 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x20, 0x69, 0x73,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6e,
+ 0x73, 0x77, 0x65, 0x72, 0x20, 0x5a, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x33,
+ 0x30, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x72, 0x65,
+ 0x63, 0x74, 0x21, 0x5c, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x63, 0x6f,
+ 0x72, 0x72, 0x65, 0x63, 0x74, 0x20, 0x69, 0x6e, 0x66, 0x69, 0x6e, 0x69,
+ 0x74, 0x65, 0x20, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e,
+ 0x20, 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x5a,
+ 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x33, 0x30, 0x31, 0x35, 0x2e, 0x20, 0x20,
+ 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x61, 0x63, 0x63, 0x75, 0x72,
+ 0x61, 0x63, 0x79, 0x0a, 0x69, 0x73, 0x20, 0x63, 0x61, 0x75, 0x73, 0x65,
+ 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6e,
+ 0x69, 0x74, 0x65, 0x20, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f,
+ 0x6e, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65,
+ 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x6f,
+ 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x0a,
+ 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x6f,
+ 0x66, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x72, 0x6e, 0x20, 0x63, 0x6f, 0x6d,
+ 0x70, 0x75, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x0a, 0x49, 0x74, 0x20, 0x62,
+ 0x65, 0x63, 0x6f, 0x6d, 0x65, 0x73, 0x20, 0x76, 0x65, 0x72, 0x79, 0x20,
+ 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x20,
+ 0x74, 0x6f, 0x20, 0x73, 0x61, 0x79, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20,
+ 0x69, 0x66, 0x20, 0x61, 0x6e, 0x79, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20,
+ 0x69, 0x74, 0x20, 0x6d, 0x65, 0x61, 0x6e, 0x73, 0x20, 0x77, 0x68, 0x65,
+ 0x6e, 0x0a, 0x5a, 0x20, 0x69, 0x73, 0x20, 0x62, 0x6f, 0x75, 0x6e, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x30, 0x2e, 0x33, 0x30, 0x20, 0x62, 0x79, 0x20,
+ 0x27, 0x69, 0x73, 0x27, 0x2e, 0x20, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20,
+ 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x20, 0x69, 0x73, 0x20, 0x65,
+ 0x78, 0x61, 0x63, 0x65, 0x72, 0x62, 0x61, 0x74, 0x65, 0x64, 0x20, 0x62,
+ 0x79, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65,
+ 0x6e, 0x63, 0x65, 0x73, 0x0a, 0x6f, 0x66, 0x20, 0x61, 0x72, 0x69, 0x74,
+ 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x61, 0x67, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20,
+ 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x6c,
+ 0x65, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x66, 0x69, 0x6e, 0x61,
+ 0x6c, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x74, 0x6f, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x6c, 0x69, 0x74, 0x74, 0x6c, 0x65, 0x20,
+ 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x20, 0x72, 0x65, 0x73, 0x65, 0x6d, 0x62,
+ 0x6c, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x20, 0x61, 0x6e, 0x73,
+ 0x77, 0x65, 0x72, 0x2e, 0x0a, 0x2e, 0x70, 0x70, 0x0a, 0x54, 0x68, 0x69,
+ 0x73, 0x20, 0x69, 0x73, 0x20, 0x66, 0x75, 0x72, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x72,
+ 0x72, 0x6f, 0x72, 0x73, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x69, 0x73, 0x20, 0x69, 0x6c, 0x6c, 0x75, 0x73, 0x74, 0x72, 0x61, 0x74,
+ 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61,
+ 0x63, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x0a,
+ 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x77,
+ 0x6f, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x73, 0x75,
+ 0x63, 0x63, 0x65, 0x65, 0x64, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x20,
+ 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x3a, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x09,
+ 0x58, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x36, 0x36, 0x2c, 0x20, 0x59, 0x20,
+ 0x3d, 0x20, 0x30, 0x2e, 0x34, 0x35, 0x2c, 0x20, 0x5a, 0x20, 0x3d, 0x20,
+ 0x30, 0x2e, 0x33, 0x30, 0x2c, 0x20, 0x5a, 0x20, 0x69, 0x73, 0x20, 0x58,
+ 0x2a, 0x59, 0x0a, 0x2e, 0x62, 0x72, 0x0a, 0x09, 0x58, 0x20, 0x3d, 0x20,
+ 0x30, 0x2e, 0x36, 0x37, 0x2c, 0x20, 0x59, 0x20, 0x3d, 0x20, 0x30, 0x2e,
+ 0x34, 0x35, 0x2c, 0x20, 0x5a, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x33, 0x30,
+ 0x2c, 0x20, 0x5a, 0x20, 0x69, 0x73, 0x20, 0x58, 0x2a, 0x59, 0x0a, 0x2e,
+ 0x73, 0x70, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x65, 0x61, 0x6e,
+ 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20,
+ 0x69, 0x66, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x76, 0x65,
+ 0x72, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x20,
+ 0x6f, 0x66, 0x20, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69,
+ 0x63, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x64, 0x65, 0x76, 0x69, 0x73,
+ 0x65, 0x64, 0x0a, 0x63, 0x61, 0x70, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x58, 0x20,
+ 0x77, 0x68, 0x65, 0x6e, 0x3a, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x09, 0x59,
+ 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x34, 0x35, 0x2c, 0x20, 0x5a, 0x20, 0x3d,
+ 0x20, 0x30, 0x2e, 0x33, 0x30, 0x2c, 0x20, 0x5a, 0x20, 0x69, 0x73, 0x20,
+ 0x58, 0x2a, 0x59, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x69, 0x74, 0x20, 0x69,
+ 0x73, 0x20, 0x75, 0x6e, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x20, 0x77, 0x68,
+ 0x69, 0x63, 0x68, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x73, 0x68,
+ 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65,
+ 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x74, 0x2e, 0x0a, 0x2e, 0x70, 0x70,
+ 0x0a, 0x54, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d,
+ 0x20, 0x74, 0x68, 0x65, 0x6e, 0x2c, 0x20, 0x69, 0x73, 0x20, 0x74, 0x6f,
+ 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x61,
+ 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x69, 0x6e,
+ 0x20, 0x61, 0x73, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x20,
+ 0x61, 0x20, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x0a, 0x61, 0x73, 0x20,
+ 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x68, 0x69,
+ 0x6c, 0x65, 0x20, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x6d, 0x61, 0x6b,
+ 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x65,
+ 0x66, 0x66, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x6c, 0x6f,
+ 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x20,
+ 0x61, 0x72, 0x69, 0x0a
+};
+unsigned int paper5_4096_len = 4096;
diff --git a/drivers/staging/fsl_dce/tests/common/paper5_8192.h b/drivers/staging/fsl_dce/tests/common/paper5_8192.h
new file mode 100644
index 0000000..87fb0db
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/common/paper5_8192.h
@@ -0,0 +1,686 @@
+unsigned char paper5_8192[] = {
+ 0x2e, 0x70, 0x6e, 0x20, 0x30, 0x0a, 0x2e, 0x45, 0x51, 0x0a, 0x64, 0x65,
+ 0x6c, 0x69, 0x6d, 0x20, 0x24, 0x24, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e,
+ 0x65, 0x20, 0x52, 0x52, 0x20, 0x27, 0x62, 0x6f, 0x6c, 0x64, 0x20, 0x52,
+ 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x53, 0x53, 0x20,
+ 0x27, 0x62, 0x6f, 0x6c, 0x64, 0x20, 0x53, 0x27, 0x0a, 0x64, 0x65, 0x66,
+ 0x69, 0x6e, 0x65, 0x20, 0x49, 0x49, 0x20, 0x27, 0x62, 0x6f, 0x6c, 0x64,
+ 0x20, 0x49, 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x6d,
+ 0x6f, 0x20, 0x27, 0x22, 0x5c, 0x28, 0x6d, 0x6f, 0x22, 0x27, 0x0a, 0x64,
+ 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x45, 0x58, 0x49, 0x53, 0x54, 0x20,
+ 0x3f, 0x22, 0x5c, 0x7a, 0x5c, 0x2d, 0x5c, 0x64, 0x5c, 0x7a, 0x5c, 0x2d,
+ 0x5c, 0x72, 0x5c, 0x2d, 0x5c, 0x64, 0x5c, 0x76, 0x27, 0x30, 0x2e, 0x32,
+ 0x6d, 0x27, 0x5c, 0x28, 0x62, 0x72, 0x5c, 0x76, 0x27, 0x2d, 0x30, 0x2e,
+ 0x32, 0x6d, 0x27, 0x22, 0x3f, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65,
+ 0x20, 0x4e, 0x45, 0x58, 0x49, 0x53, 0x54, 0x20, 0x3f, 0x22, 0x5c, 0x7a,
+ 0x5c, 0x2d, 0x5c, 0x64, 0x5c, 0x7a, 0x5c, 0x6f, 0x27, 0x5c, 0x2d, 0x5c,
+ 0x28, 0x73, 0x6c, 0x27, 0x5c, 0x72, 0x5c, 0x2d, 0x5c, 0x64, 0x5c, 0x76,
+ 0x27, 0x30, 0x2e, 0x32, 0x6d, 0x27, 0x5c, 0x28, 0x62, 0x72, 0x5c, 0x76,
+ 0x27, 0x2d, 0x30, 0x2e, 0x32, 0x6d, 0x27, 0x22, 0x3f, 0x0a, 0x64, 0x65,
+ 0x66, 0x69, 0x6e, 0x65, 0x20, 0x41, 0x4c, 0x4c, 0x20, 0x3f, 0x22, 0x5c,
+ 0x6f, 0x27, 0x56, 0x2d, 0x27, 0x22, 0x3f, 0x0a, 0x64, 0x65, 0x66, 0x69,
+ 0x6e, 0x65, 0x20, 0x73, 0x75, 0x62, 0x73, 0x65, 0x74, 0x20, 0x27, 0x5c,
+ 0x28, 0x73, 0x62, 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20,
+ 0x73, 0x75, 0x62, 0x65, 0x71, 0x20, 0x20, 0x27, 0x5c, 0x28, 0x69, 0x62,
+ 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x73, 0x75, 0x70,
+ 0x73, 0x65, 0x74, 0x20, 0x27, 0x5c, 0x28, 0x73, 0x70, 0x27, 0x0a, 0x64,
+ 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x73, 0x75, 0x70, 0x65, 0x71, 0x20,
+ 0x20, 0x27, 0x5c, 0x28, 0x69, 0x70, 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69,
+ 0x6e, 0x65, 0x20, 0x6d, 0x6f, 0x20, 0x27, 0x5c, 0x28, 0x6d, 0x6f, 0x27,
+ 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x6e, 0x6d, 0x20, 0x3f,
+ 0x22, 0x5c, 0x6f, 0x27, 0x5c, 0x28, 0x6d, 0x6f, 0x5c, 0x28, 0x73, 0x6c,
+ 0x27, 0x22, 0x3f, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x6c,
+ 0x69, 0x20, 0x27, 0x5c, 0x26, 0x20, 0x73, 0x75, 0x70, 0x20, 0x5b, 0x27,
+ 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x6c, 0x6f, 0x20, 0x27,
+ 0x5c, 0x26, 0x20, 0x73, 0x75, 0x70, 0x20, 0x28, 0x27, 0x0a, 0x64, 0x65,
+ 0x66, 0x69, 0x6e, 0x65, 0x20, 0x68, 0x69, 0x20, 0x27, 0x5c, 0x26, 0x20,
+ 0x73, 0x75, 0x70, 0x20, 0x5d, 0x27, 0x0a, 0x64, 0x65, 0x66, 0x69, 0x6e,
+ 0x65, 0x20, 0x68, 0x6f, 0x20, 0x27, 0x5c, 0x26, 0x20, 0x73, 0x75, 0x70,
+ 0x20, 0x29, 0x27, 0x0a, 0x2e, 0x45, 0x4e, 0x0a, 0x2e, 0x6c, 0x73, 0x20,
+ 0x31, 0x09, 0x0a, 0x2e, 0x63, 0x65, 0x0a, 0x41, 0x20, 0x4c, 0x4f, 0x47,
+ 0x49, 0x43, 0x41, 0x4c, 0x20, 0x49, 0x4d, 0x50, 0x4c, 0x45, 0x4d, 0x45,
+ 0x4e, 0x54, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x4f, 0x46, 0x20, 0x41,
+ 0x52, 0x49, 0x54, 0x48, 0x4d, 0x45, 0x54, 0x49, 0x43, 0x20, 0x0a, 0x2e,
+ 0x73, 0x70, 0x20, 0x33, 0x0a, 0x2e, 0x63, 0x65, 0x0a, 0x4a, 0x6f, 0x68,
+ 0x6e, 0x20, 0x47, 0x2e, 0x20, 0x43, 0x6c, 0x65, 0x61, 0x72, 0x79, 0x20,
+ 0x0a, 0x2e, 0x63, 0x65, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x55, 0x6e, 0x69,
+ 0x76, 0x65, 0x72, 0x73, 0x69, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x43,
+ 0x61, 0x6c, 0x67, 0x61, 0x72, 0x79, 0x2c, 0x20, 0x41, 0x6c, 0x62, 0x65,
+ 0x72, 0x74, 0x61, 0x2c, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2e,
+ 0x0a, 0x2e, 0x73, 0x70, 0x20, 0x32, 0x30, 0x0a, 0x5c, 0x75, 0x31, 0x5c,
+ 0x64, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x27, 0x73, 0x20, 0x50, 0x72,
+ 0x65, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
+ 0x73, 0x3a, 0x20, 0x4d, 0x61, 0x6e, 0x2d, 0x4d, 0x61, 0x63, 0x68, 0x69,
+ 0x6e, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20, 0x47,
+ 0x72, 0x6f, 0x75, 0x70, 0x2c, 0x20, 0x44, 0x65, 0x70, 0x61, 0x72, 0x74,
+ 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6f, 0x66, 0x0a, 0x43, 0x6f, 0x6d, 0x70,
+ 0x75, 0x74, 0x65, 0x72, 0x20, 0x53, 0x63, 0x69, 0x65, 0x6e, 0x63, 0x65,
+ 0x2c, 0x20, 0x54, 0x68, 0x65, 0x20, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72,
+ 0x73, 0x69, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x43, 0x61, 0x6c, 0x67,
+ 0x61, 0x72, 0x79, 0x2c, 0x20, 0x32, 0x35, 0x30, 0x30, 0x20, 0x55, 0x6e,
+ 0x69, 0x76, 0x65, 0x72, 0x73, 0x69, 0x74, 0x79, 0x20, 0x44, 0x72, 0x69,
+ 0x76, 0x65, 0x20, 0x4e, 0x57, 0x0a, 0x43, 0x61, 0x6c, 0x67, 0x61, 0x72,
+ 0x79, 0x2c, 0x20, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x20, 0x54, 0x32,
+ 0x4e, 0x20, 0x31, 0x4e, 0x34, 0x2e, 0x20, 0x50, 0x68, 0x6f, 0x6e, 0x65,
+ 0x3a, 0x20, 0x28, 0x34, 0x30, 0x33, 0x29, 0x32, 0x32, 0x30, 0x2d, 0x36,
+ 0x30, 0x38, 0x37, 0x2e, 0x20, 0x20, 0x0a, 0x2e, 0x62, 0x72, 0x0a, 0x2e,
+ 0x6e, 0x66, 0x0a, 0x55, 0x55, 0x43, 0x50, 0x3a, 0x20, 0x20, 0x2e, 0x2e,
+ 0x2e, 0x21, 0x7b, 0x69, 0x68, 0x6e, 0x70, 0x34, 0x2c, 0x75, 0x62, 0x63,
+ 0x2d, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x7d, 0x21, 0x61, 0x6c, 0x62,
+ 0x65, 0x72, 0x74, 0x61, 0x21, 0x63, 0x61, 0x6c, 0x67, 0x61, 0x72, 0x79,
+ 0x21, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x79, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x2e, 0x2e, 0x2e, 0x21, 0x6e, 0x72, 0x6c, 0x2d, 0x63,
+ 0x73, 0x73, 0x21, 0x63, 0x61, 0x6c, 0x67, 0x61, 0x72, 0x79, 0x21, 0x63,
+ 0x6c, 0x65, 0x61, 0x72, 0x79, 0x0a, 0x41, 0x52, 0x50, 0x41, 0x3a, 0x20,
+ 0x20, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x79, 0x2e, 0x63, 0x61, 0x6c, 0x67,
+ 0x61, 0x72, 0x79, 0x2e, 0x75, 0x62, 0x63, 0x40, 0x63, 0x73, 0x6e, 0x65,
+ 0x74, 0x2d, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x0a, 0x43, 0x44, 0x4e, 0x3a,
+ 0x20, 0x20, 0x20, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x79, 0x40, 0x63, 0x61,
+ 0x6c, 0x67, 0x61, 0x72, 0x79, 0x0a, 0x2e, 0x66, 0x69, 0x0a, 0x2e, 0x73,
+ 0x70, 0x20, 0x32, 0x0a, 0x2e, 0x6c, 0x73, 0x20, 0x32, 0x0a, 0x2e, 0x62,
+ 0x70, 0x20, 0x30, 0x0a, 0x2e, 0x6c, 0x73, 0x20, 0x32, 0x0a, 0x2e, 0x63,
+ 0x65, 0x0a, 0x41, 0x62, 0x73, 0x74, 0x72, 0x61, 0x63, 0x74, 0x0a, 0x2e,
+ 0x70, 0x70, 0x0a, 0x53, 0x6f, 0x20, 0x66, 0x61, 0x72, 0x20, 0x69, 0x6d,
+ 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x61, 0x72,
+ 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x77, 0x69, 0x74,
+ 0x68, 0x69, 0x6e, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x20, 0x70, 0x72,
+ 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x0a, 0x68, 0x61,
+ 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x6e, 0x6f, 0x6e, 0x2d,
+ 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x2e, 0x20, 0x20, 0x41, 0x20,
+ 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x73, 0x63,
+ 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x62, 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x75, 0x72,
+ 0x20, 0x6f, 0x66, 0x20, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74,
+ 0x69, 0x63, 0x0a, 0x6f, 0x6e, 0x20, 0x61, 0x63, 0x74, 0x75, 0x61, 0x6c,
+ 0x0a, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x75, 0x73,
+ 0x69, 0x6e, 0x67, 0x20, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x65, 0x20, 0x70,
+ 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x75, 0x6d,
+ 0x62, 0x65, 0x72, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20,
+ 0x72, 0x65, 0x61, 0x64, 0x69, 0x6c, 0x79, 0x20, 0x61, 0x76, 0x61, 0x69,
+ 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x20, 0x20, 0x0a, 0x55, 0x73, 0x69,
+ 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x20,
+ 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x20, 0x61, 0x20, 0x73,
+ 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x61,
+ 0x6c, 0x20, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63,
+ 0x20, 0x69, 0x73, 0x20, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65,
+ 0x2e, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62,
+ 0x65, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65,
+ 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x69, 0x6e, 0x20, 0x50, 0x72, 0x6f, 0x6c, 0x6f, 0x67, 0x2e,
+ 0x0a, 0x41, 0x73, 0x20, 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
+ 0x68, 0x61, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x75,
+ 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x62,
+ 0x61, 0x73, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73,
+ 0x75, 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65,
+ 0x6d, 0x20, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x73, 0x20, 0x61, 0x20,
+ 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x63, 0x69, 0x73, 0x65,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x66, 0x75,
+ 0x6c, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x69, 0x6e,
+ 0x67, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x69, 0x73, 0x20, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
+ 0x6c, 0x79, 0x0a, 0x76, 0x65, 0x72, 0x79, 0x20, 0x65, 0x66, 0x66, 0x69,
+ 0x63, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x2e, 0x62, 0x70, 0x0a, 0x2e,
+ 0x73, 0x68, 0x20, 0x22, 0x31, 0x20, 0x49, 0x6e, 0x74, 0x72, 0x6f, 0x64,
+ 0x75, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x0a, 0x2e, 0x70, 0x70, 0x0a,
+ 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61,
+ 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x69, 0x6d, 0x73, 0x20, 0x74,
+ 0x6f, 0x20, 0x75, 0x73, 0x65, 0x20, 0x73, 0x65, 0x74, 0x73, 0x20, 0x6f,
+ 0x66, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x6f,
+ 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x65, 0x20, 0x61, 0x73, 0x0a, 0x73, 0x74,
+ 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20,
+ 0x61, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x69, 0x6e,
+ 0x67, 0x20, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x2e, 0x0a,
+ 0x42, 0x65, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6d,
+ 0x61, 0x6e, 0x79, 0x20, 0x70, 0x72, 0x61, 0x63, 0x74, 0x69, 0x63, 0x61,
+ 0x6c, 0x20, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74, 0x69,
+ 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20,
+ 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x6f,
+ 0x66, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x0a, 0x63, 0x61, 0x6e, 0x6e,
+ 0x6f, 0x74, 0x20, 0x28, 0x79, 0x65, 0x74, 0x29, 0x20, 0x62, 0x65, 0x20,
+ 0x75, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x77, 0x61, 0x79, 0x2e, 0x20, 0x20, 0x20, 0x48, 0x6f, 0x77, 0x65,
+ 0x76, 0x65, 0x72, 0x2c, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x73, 0x74,
+ 0x72, 0x69, 0x63, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x0a,
+ 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x6f, 0x72,
+ 0x6d, 0x75, 0x6c, 0x61, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x74,
+ 0x6f, 0x20, 0x48, 0x6f, 0x72, 0x6e, 0x20, 0x63, 0x6c, 0x61, 0x75, 0x73,
+ 0x65, 0x73, 0x20, 0x70, 0x72, 0x61, 0x63, 0x74, 0x69, 0x63, 0x61, 0x6c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65, 0x66, 0x66, 0x69, 0x63, 0x69, 0x65,
+ 0x6e, 0x74, 0x0a, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x73,
+ 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20, 0x50, 0x52, 0x4f,
+ 0x4c, 0x4f, 0x47, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6f, 0x62, 0x74, 0x61,
+ 0x69, 0x6e, 0x65, 0x64, 0x2e, 0x0a, 0x4f, 0x6e, 0x65, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x70, 0x72,
+ 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x6f,
+ 0x67, 0x69, 0x63, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d,
+ 0x69, 0x6e, 0x67, 0x20, 0x69, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x78,
+ 0x74, 0x65, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x61, 0x72,
+ 0x65, 0x61, 0x0a, 0x6f, 0x66, 0x20, 0x70, 0x72, 0x61, 0x63, 0x74, 0x69,
+ 0x63, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x65,
+ 0x66, 0x66, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x63, 0x79, 0x20, 0x74, 0x6f,
+ 0x20, 0x61, 0x6e, 0x20, 0x65, 0x76, 0x65, 0x72, 0x20, 0x77, 0x69, 0x64,
+ 0x65, 0x72, 0x20, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x66, 0x6f, 0x72, 0x6d, 0x75, 0x6c, 0x61, 0x65, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x0a, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x2e, 0x20, 0x20, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70,
+ 0x61, 0x70, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65,
+ 0x72, 0x73, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x6e, 0x20, 0x69,
+ 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d,
+ 0x65, 0x74, 0x69, 0x63, 0x2e, 0x0a, 0x2e, 0x70, 0x70, 0x0a, 0x54, 0x6f,
+ 0x20, 0x73, 0x65, 0x65, 0x20, 0x77, 0x68, 0x79, 0x20, 0x61, 0x72, 0x69,
+ 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x61, 0x73, 0x20, 0x69,
+ 0x74, 0x20, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x6c,
+ 0x79, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65,
+ 0x64, 0x20, 0x69, 0x6e, 0x20, 0x50, 0x52, 0x4f, 0x4c, 0x4f, 0x47, 0x20,
+ 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x0a, 0x69, 0x73, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x63,
+ 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x78,
+ 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x3a, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x2e,
+ 0x6e, 0x66, 0x0a, 0x09, 0x58, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x36, 0x37,
+ 0x2c, 0x20, 0x59, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x34, 0x35, 0x2c, 0x20,
+ 0x5a, 0x20, 0x69, 0x73, 0x20, 0x58, 0x2a, 0x59, 0x2c, 0x20, 0x5a, 0x20,
+ 0x3d, 0x20, 0x30, 0x2e, 0x33, 0x30, 0x0a, 0x2e, 0x66, 0x69, 0x0a, 0x2e,
+ 0x73, 0x70, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x27, 0x45, 0x64,
+ 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x68, 0x20, 0x73, 0x74, 0x79, 0x6c,
+ 0x65, 0x27, 0x20, 0x50, 0x72, 0x6f, 0x6c, 0x6f, 0x67, 0x73, 0x2e, 0x0a,
+ 0x28, 0x46, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d,
+ 0x65, 0x6e, 0x74, 0x20, 0x77, 0x65, 0x20, 0x61, 0x73, 0x73, 0x75, 0x6d,
+ 0x65, 0x20, 0x61, 0x6e, 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x79,
+ 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x69, 0x6e, 0x67,
+ 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x0a, 0x64, 0x65, 0x63, 0x69, 0x6d,
+ 0x61, 0x6c, 0x20, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69,
+ 0x63, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x73,
+ 0x69, 0x67, 0x6e, 0x69, 0x66, 0x69, 0x63, 0x61, 0x6e, 0x74, 0x20, 0x70,
+ 0x6c, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x29, 0x0a, 0x54, 0x68, 0x65, 0x20,
+ 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x27, 0x69,
+ 0x73, 0x27, 0x20, 0x61, 0x73, 0x73, 0x75, 0x6d, 0x65, 0x73, 0x20, 0x69,
+ 0x74, 0x73, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x68, 0x61, 0x6e, 0x64,
+ 0x20, 0x73, 0x69, 0x64, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6e, 0x20,
+ 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x0a, 0x73,
+ 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2c, 0x20, 0x63, 0x6f,
+ 0x6d, 0x70, 0x75, 0x74, 0x65, 0x73, 0x20, 0x69, 0x74, 0x73, 0x20, 0x76,
+ 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x75, 0x6e,
+ 0x69, 0x66, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65,
+ 0x73, 0x75, 0x6c, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x69, 0x74,
+ 0x73, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x68, 0x61, 0x6e, 0x64, 0x20, 0x73,
+ 0x69, 0x64, 0x65, 0x2e, 0x0a, 0x49, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73,
+ 0x20, 0x63, 0x61, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x6e,
+ 0x74, 0x69, 0x72, 0x65, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63,
+ 0x65, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x65, 0x64, 0x73, 0x2c, 0x20,
+ 0x68, 0x6f, 0x77, 0x65, 0x76, 0x65, 0x72, 0x2c, 0x20, 0x74, 0x68, 0x65,
+ 0x72, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20,
+ 0x73, 0x65, 0x72, 0x69, 0x6f, 0x75, 0x73, 0x20, 0x0a, 0x70, 0x72, 0x6f,
+ 0x62, 0x6c, 0x65, 0x6d, 0x73, 0x2e, 0x0a, 0x2e, 0x70, 0x70, 0x0a, 0x49,
+ 0x6e, 0x20, 0x61, 0x20, 0x70, 0x75, 0x72, 0x65, 0x20, 0x6c, 0x6f, 0x67,
+ 0x69, 0x63, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20,
+ 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x73,
+ 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, 0x72, 0x72,
+ 0x65, 0x6c, 0x65, 0x76, 0x61, 0x6e, 0x74, 0x20, 0x74, 0x6f, 0x0a, 0x74,
+ 0x68, 0x65, 0x20, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x6e, 0x65,
+ 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65,
+ 0x73, 0x75, 0x6c, 0x74, 0x20, 0x28, 0x61, 0x74, 0x20, 0x77, 0x6f, 0x72,
+ 0x73, 0x74, 0x20, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x65, 0x66, 0x66, 0x69, 0x63, 0x69,
+ 0x65, 0x6e, 0x63, 0x79, 0x20, 0x6d, 0x69, 0x67, 0x68, 0x74, 0x20, 0x62,
+ 0x65, 0x0a, 0x61, 0x66, 0x66, 0x65, 0x63, 0x74, 0x65, 0x64, 0x29, 0x2e,
+ 0x20, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6e, 0x6f,
+ 0x74, 0x20, 0x74, 0x72, 0x75, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x20, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x61, 0x62,
+ 0x6f, 0x76, 0x65, 0x2e, 0x20, 0x20, 0x54, 0x68, 0x65, 0x20, 0x64, 0x69,
+ 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x65,
+ 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x6f, 0x66, 0x20,
+ 0x27, 0x69, 0x73, 0x27, 0x20, 0x69, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69,
+ 0x63, 0x74, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x77, 0x61, 0x79,
+ 0x20, 0x73, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74, 0x0a, 0x2e, 0x73, 0x70,
+ 0x0a, 0x09, 0x59, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x34, 0x35, 0x2c, 0x20,
+ 0x5a, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x33, 0x30, 0x2c, 0x20, 0x5a, 0x20,
+ 0x69, 0x73, 0x20, 0x58, 0x2a, 0x59, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x20,
+ 0x61, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x77, 0x68, 0x65,
+ 0x6e, 0x20, 0x58, 0x20, 0x69, 0x73, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x75, 0x6e, 0x69, 0x6e, 0x73,
+ 0x74, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x74, 0x65, 0x64, 0x20, 0x69, 0x6e,
+ 0x73, 0x69, 0x64, 0x65, 0x20, 0x27, 0x69, 0x73, 0x27, 0x2e, 0x0a, 0x2e,
+ 0x70, 0x70, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e,
+ 0x64, 0x20, 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x20, 0x69, 0x73,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x6e,
+ 0x73, 0x77, 0x65, 0x72, 0x20, 0x5a, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x33,
+ 0x30, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6f, 0x72, 0x72, 0x65,
+ 0x63, 0x74, 0x21, 0x5c, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x63, 0x6f,
+ 0x72, 0x72, 0x65, 0x63, 0x74, 0x20, 0x69, 0x6e, 0x66, 0x69, 0x6e, 0x69,
+ 0x74, 0x65, 0x20, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e,
+ 0x20, 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x20, 0x69, 0x73, 0x20, 0x5a,
+ 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x33, 0x30, 0x31, 0x35, 0x2e, 0x20, 0x20,
+ 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x61, 0x63, 0x63, 0x75, 0x72,
+ 0x61, 0x63, 0x79, 0x0a, 0x69, 0x73, 0x20, 0x63, 0x61, 0x75, 0x73, 0x65,
+ 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6e,
+ 0x69, 0x74, 0x65, 0x20, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f,
+ 0x6e, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65,
+ 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6c, 0x6f,
+ 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x0a,
+ 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x6f,
+ 0x66, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x72, 0x6e, 0x20, 0x63, 0x6f, 0x6d,
+ 0x70, 0x75, 0x74, 0x65, 0x72, 0x73, 0x2e, 0x0a, 0x49, 0x74, 0x20, 0x62,
+ 0x65, 0x63, 0x6f, 0x6d, 0x65, 0x73, 0x20, 0x76, 0x65, 0x72, 0x79, 0x20,
+ 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x20,
+ 0x74, 0x6f, 0x20, 0x73, 0x61, 0x79, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20,
+ 0x69, 0x66, 0x20, 0x61, 0x6e, 0x79, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20,
+ 0x69, 0x74, 0x20, 0x6d, 0x65, 0x61, 0x6e, 0x73, 0x20, 0x77, 0x68, 0x65,
+ 0x6e, 0x0a, 0x5a, 0x20, 0x69, 0x73, 0x20, 0x62, 0x6f, 0x75, 0x6e, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x30, 0x2e, 0x33, 0x30, 0x20, 0x62, 0x79, 0x20,
+ 0x27, 0x69, 0x73, 0x27, 0x2e, 0x20, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20,
+ 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x20, 0x69, 0x73, 0x20, 0x65,
+ 0x78, 0x61, 0x63, 0x65, 0x72, 0x62, 0x61, 0x74, 0x65, 0x64, 0x20, 0x62,
+ 0x79, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65,
+ 0x6e, 0x63, 0x65, 0x73, 0x0a, 0x6f, 0x66, 0x20, 0x61, 0x72, 0x69, 0x74,
+ 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x61, 0x67, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20,
+ 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x6c,
+ 0x65, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x66, 0x69, 0x6e, 0x61,
+ 0x6c, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x74, 0x6f, 0x20,
+ 0x68, 0x61, 0x76, 0x65, 0x20, 0x6c, 0x69, 0x74, 0x74, 0x6c, 0x65, 0x20,
+ 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x20, 0x72, 0x65, 0x73, 0x65, 0x6d, 0x62,
+ 0x6c, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x20, 0x61, 0x6e, 0x73,
+ 0x77, 0x65, 0x72, 0x2e, 0x0a, 0x2e, 0x70, 0x70, 0x0a, 0x54, 0x68, 0x69,
+ 0x73, 0x20, 0x69, 0x73, 0x20, 0x66, 0x75, 0x72, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x72,
+ 0x72, 0x6f, 0x72, 0x73, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x69, 0x73, 0x20, 0x69, 0x6c, 0x6c, 0x75, 0x73, 0x74, 0x72, 0x61, 0x74,
+ 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x61,
+ 0x63, 0x74, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x0a,
+ 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x77,
+ 0x6f, 0x20, 0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x73, 0x75,
+ 0x63, 0x63, 0x65, 0x65, 0x64, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x20,
+ 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x72,
+ 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x3a, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x09,
+ 0x58, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x36, 0x36, 0x2c, 0x20, 0x59, 0x20,
+ 0x3d, 0x20, 0x30, 0x2e, 0x34, 0x35, 0x2c, 0x20, 0x5a, 0x20, 0x3d, 0x20,
+ 0x30, 0x2e, 0x33, 0x30, 0x2c, 0x20, 0x5a, 0x20, 0x69, 0x73, 0x20, 0x58,
+ 0x2a, 0x59, 0x0a, 0x2e, 0x62, 0x72, 0x0a, 0x09, 0x58, 0x20, 0x3d, 0x20,
+ 0x30, 0x2e, 0x36, 0x37, 0x2c, 0x20, 0x59, 0x20, 0x3d, 0x20, 0x30, 0x2e,
+ 0x34, 0x35, 0x2c, 0x20, 0x5a, 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x33, 0x30,
+ 0x2c, 0x20, 0x5a, 0x20, 0x69, 0x73, 0x20, 0x58, 0x2a, 0x59, 0x0a, 0x2e,
+ 0x73, 0x70, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20, 0x6d, 0x65, 0x61, 0x6e,
+ 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20,
+ 0x69, 0x66, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x76, 0x65,
+ 0x72, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x20,
+ 0x6f, 0x66, 0x20, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69,
+ 0x63, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x64, 0x65, 0x76, 0x69, 0x73,
+ 0x65, 0x64, 0x0a, 0x63, 0x61, 0x70, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6f,
+ 0x66, 0x20, 0x62, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x58, 0x20,
+ 0x77, 0x68, 0x65, 0x6e, 0x3a, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x09, 0x59,
+ 0x20, 0x3d, 0x20, 0x30, 0x2e, 0x34, 0x35, 0x2c, 0x20, 0x5a, 0x20, 0x3d,
+ 0x20, 0x30, 0x2e, 0x33, 0x30, 0x2c, 0x20, 0x5a, 0x20, 0x69, 0x73, 0x20,
+ 0x58, 0x2a, 0x59, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x69, 0x74, 0x20, 0x69,
+ 0x73, 0x20, 0x75, 0x6e, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x20, 0x77, 0x68,
+ 0x69, 0x63, 0x68, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x73, 0x68,
+ 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x67, 0x69, 0x76, 0x65,
+ 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x74, 0x2e, 0x0a, 0x2e, 0x70, 0x70,
+ 0x0a, 0x54, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d,
+ 0x20, 0x74, 0x68, 0x65, 0x6e, 0x2c, 0x20, 0x69, 0x73, 0x20, 0x74, 0x6f,
+ 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x61,
+ 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x69, 0x6e,
+ 0x20, 0x61, 0x73, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x20,
+ 0x61, 0x20, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x0a, 0x61, 0x73, 0x20,
+ 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x68, 0x69,
+ 0x6c, 0x65, 0x20, 0x73, 0x74, 0x69, 0x6c, 0x6c, 0x20, 0x6d, 0x61, 0x6b,
+ 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x65,
+ 0x66, 0x66, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x66, 0x6c, 0x6f,
+ 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x20,
+ 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x2e, 0x0a,
+ 0x54, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e,
+ 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f,
+ 0x62, 0x6c, 0x65, 0x6d, 0x20, 0x68, 0x61, 0x73, 0x20, 0x74, 0x68, 0x72,
+ 0x65, 0x65, 0x20, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x20, 0x70, 0x61, 0x72,
+ 0x74, 0x73, 0x2e, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73,
+ 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, 0x70, 0x72,
+ 0x65, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x4c, 0x4f, 0x47,
+ 0x27, 0x73, 0x20, 0x0a, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74,
+ 0x69, 0x63, 0x20, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73,
+ 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x6c, 0x79, 0x20,
+ 0x61, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73,
+ 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x6e, 0x75, 0x6d,
+ 0x62, 0x65, 0x72, 0x73, 0x2e, 0x0a, 0x53, 0x6f, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x27,
+ 0x5a, 0x20, 0x69, 0x73, 0x20, 0x30, 0x2e, 0x34, 0x35, 0x2a, 0x30, 0x2e,
+ 0x36, 0x37, 0x27, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65,
+ 0x20, 0x74, 0x6f, 0x20, 0x62, 0x69, 0x6e, 0x64, 0x20, 0x5a, 0x20, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x0a, 0x6f, 0x70, 0x65, 0x6e, 0x20,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x20, 0x28, 0x30, 0x2e,
+ 0x33, 0x30, 0x2c, 0x30, 0x2e, 0x33, 0x31, 0x29, 0x2e, 0x20, 0x20, 0x0a,
+ 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x61, 0x79, 0x73, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x5a, 0x20, 0x6c, 0x69, 0x65, 0x73, 0x20, 0x73, 0x6f,
+ 0x6d, 0x65, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x0a,
+ 0x24, 0x30, 0x2e, 0x33, 0x30, 0x20, 0x3c, 0x20, 0x5a, 0x20, 0x3c, 0x20,
+ 0x30, 0x2e, 0x33, 0x31, 0x24, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68,
+ 0x20, 0x69, 0x73, 0x20, 0x63, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6e, 0x6c,
+ 0x79, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
+ 0x70, 0x72, 0x6f, 0x62, 0x61, 0x62, 0x6c, 0x79, 0x20, 0x61, 0x73, 0x20,
+ 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x76, 0x65, 0x0a,
+ 0x61, 0x73, 0x20, 0x70, 0x6f, 0x73, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x20,
+ 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x65,
+ 0x20, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x61,
+ 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x2e, 0x0a, 0x28,
+ 0x4e, 0x6f, 0x74, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x5a, 0x20,
+ 0x69, 0x73, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x62, 0x6f, 0x75, 0x6e, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x61, 0x74, 0x61,
+ 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x20, 0x28,
+ 0x30, 0x2e, 0x33, 0x30, 0x2c, 0x30, 0x2e, 0x33, 0x31, 0x29, 0x2c, 0x20,
+ 0x74, 0x68, 0x69, 0x73, 0x0a, 0x69, 0x73, 0x20, 0x61, 0x20, 0x68, 0x69,
+ 0x64, 0x64, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65,
+ 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x6d,
+ 0x75, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65,
+ 0x20, 0x77, 0x61, 0x79, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x70, 0x6f,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x75,
+ 0x73, 0x65, 0x64, 0x0a, 0x74, 0x6f, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65,
+ 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c,
+ 0x20, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x20, 0x69,
+ 0x6e, 0x20, 0x50, 0x52, 0x4f, 0x4c, 0x4f, 0x47, 0x20, 0x62, 0x75, 0x74,
+ 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x78, 0x70,
+ 0x6c, 0x69, 0x63, 0x69, 0x74, 0x6c, 0x79, 0x20, 0x76, 0x69, 0x73, 0x69,
+ 0x62, 0x6c, 0x65, 0x0a, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75,
+ 0x73, 0x65, 0x72, 0x2e, 0x20, 0x20, 0x54, 0x68, 0x72, 0x6f, 0x75, 0x67,
+ 0x68, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x70, 0x61,
+ 0x70, 0x65, 0x72, 0x20, 0x62, 0x72, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73,
+ 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20, 0x28, 0x2e, 0x2e,
+ 0x2e, 0x29, 0x20, 0x6f, 0x72, 0x20, 0x5b, 0x2e, 0x2e, 0x2e, 0x5d, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x0a, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e,
+ 0x74, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63,
+ 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76,
+ 0x61, 0x6c, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x50, 0x72, 0x6f, 0x6c,
+ 0x6f, 0x67, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x73, 0x74, 0x72, 0x75,
+ 0x63, 0x74, 0x75, 0x72, 0x65, 0x73, 0x2e, 0x29, 0x0a, 0x2e, 0x70, 0x70,
+ 0x0a, 0x54, 0x68, 0x65, 0x20, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x20,
+ 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20,
+ 0x74, 0x6f, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65,
+ 0x20, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73,
+ 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x0a, 0x5c, 0x26, 0x27,
+ 0x5a, 0x20, 0x69, 0x73, 0x20, 0x28, 0x58, 0x2a, 0x59, 0x29, 0x2f, 0x32,
+ 0x27, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x6c,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x66, 0x6f, 0x72, 0x6d,
+ 0x20, 0x27, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x28, 0x58,
+ 0x2c, 0x59, 0x2c, 0x54, 0x30, 0x29, 0x2c, 0x20, 0x6d, 0x75, 0x6c, 0x74,
+ 0x69, 0x70, 0x6c, 0x79, 0x28, 0x32, 0x2c, 0x5a, 0x2c, 0x54, 0x30, 0x29,
+ 0x27, 0x2e, 0x0a, 0x4e, 0x6f, 0x74, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x2a, 0x20,
+ 0x61, 0x6e, 0x64, 0x20, 0x2f, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74,
+ 0x6f, 0x72, 0x73, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65,
+ 0x6e, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x65, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x27, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c,
+ 0x79, 0x27, 0x0a, 0x28, 0x77, 0x69, 0x74, 0x68, 0x20, 0x70, 0x61, 0x72,
+ 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x61,
+ 0x20, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x6f,
+ 0x72, 0x64, 0x65, 0x72, 0x29, 0x2e, 0x20, 0x20, 0x54, 0x68, 0x69, 0x73,
+ 0x20, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20,
+ 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65,
+ 0x20, 0x73, 0x65, 0x65, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x0a, 0x62, 0x65,
+ 0x20, 0x69, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65,
+ 0x20, 0x74, 0x6f, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x70, 0x61,
+ 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 0x61, 0x72, 0x65,
+ 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x74, 0x65,
+ 0x64, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
+ 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x2c, 0x0a, 0x74, 0x68, 0x75,
+ 0x73, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x69, 0x6e, 0x67, 0x20,
+ 0x69, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74,
+ 0x79, 0x2e, 0x0a, 0x2e, 0x70, 0x70, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x74,
+ 0x68, 0x69, 0x72, 0x64, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x69, 0x73,
+ 0x20, 0x74, 0x6f, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x20,
+ 0x61, 0x20, 0x73, 0x6d, 0x61, 0x6c, 0x6c, 0x20, 0x6e, 0x75, 0x6d, 0x62,
+ 0x65, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
+ 0x6c, 0x20, 0x27, 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65,
+ 0x73, 0x27, 0x20, 0x61, 0x62, 0x6c, 0x65, 0x0a, 0x74, 0x6f, 0x20, 0x67,
+ 0x75, 0x69, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x61,
+ 0x72, 0x63, 0x68, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x6f, 0x6c, 0x75,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x72,
+ 0x65, 0x73, 0x75, 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73,
+ 0x74, 0x65, 0x6d, 0x20, 0x69, 0x73, 0x20, 0x73, 0x75, 0x66, 0x66, 0x69,
+ 0x63, 0x69, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x20, 0x70, 0x6f, 0x77, 0x65,
+ 0x72, 0x66, 0x75, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x61,
+ 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x0a, 0x73, 0x6f, 0x6c, 0x76, 0x65,
+ 0x20, 0x65, 0x71, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x73,
+ 0x75, 0x63, 0x68, 0x20, 0x61, 0x73, 0x20, 0x27, 0x30, 0x20, 0x69, 0x73,
+ 0x20, 0x58, 0x2a, 0x28, 0x58, 0x2d, 0x32, 0x29, 0x2b, 0x31, 0x27, 0x20,
+ 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x2e, 0x0a, 0x2e, 0x70,
+ 0x70, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x6e, 0x65, 0x78, 0x74, 0x20, 0x73,
+ 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x67, 0x69, 0x76, 0x65, 0x73,
+ 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x77, 0x68, 0x61, 0x74, 0x20,
+ 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x20,
+ 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20,
+ 0x6f, 0x66, 0x20, 0x61, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69,
+ 0x63, 0x0a, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x65,
+ 0x64, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x77, 0x61, 0x79, 0x2e, 0x20,
+ 0x20, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x49, 0x49,
+ 0x20, 0x67, 0x69, 0x76, 0x65, 0x73, 0x20, 0x65, 0x78, 0x61, 0x6d, 0x70,
+ 0x6c, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x74, 0x73, 0x20, 0x75,
+ 0x73, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68,
+ 0x65, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x65,
+ 0x71, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x73, 0x6f, 0x6c, 0x75, 0x62, 0x6c,
+ 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x69, 0x74, 0x2e,
+ 0x20, 0x20, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x56,
+ 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x65, 0x73, 0x20, 0x6f, 0x75,
+ 0x72, 0x20, 0x0a, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x61, 0x63, 0x68, 0x20,
+ 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+ 0x61, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x20, 0x61, 0x72, 0x69,
+ 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x73, 0x79, 0x73, 0x74,
+ 0x65, 0x6d, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68,
+ 0x0a, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x20,
+ 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x20, 0x20, 0x53,
+ 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x56, 0x20, 0x6e, 0x6f, 0x74,
+ 0x65, 0x73, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x70, 0x6f, 0x73, 0x73,
+ 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x61, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c,
+ 0x20, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x66, 0x6c, 0x6f, 0x77, 0x20, 0x69,
+ 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, 0x76, 0x6f, 0x69,
+ 0x64, 0x73, 0x20, 0x6d, 0x61, 0x6e, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x64, 0x69, 0x66, 0x66, 0x69, 0x63, 0x75, 0x6c, 0x74,
+ 0x69, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x72, 0x61, 0x64, 0x69,
+ 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x66,
+ 0x6c, 0x6f, 0x77, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f,
+ 0x6e, 0x2e, 0x0a, 0x2e, 0x73, 0x68, 0x20, 0x22, 0x49, 0x49, 0x2e, 0x20,
+ 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x20, 0x52, 0x65, 0x70,
+ 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22,
+ 0x0a, 0x2e, 0x70, 0x70, 0x0a, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20,
+ 0x24, 0x49, 0x49, 0x28, 0x52, 0x52, 0x29, 0x24, 0x20, 0x74, 0x6f, 0x20,
+ 0x62, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x74, 0x20, 0x6f,
+ 0x66, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x20,
+ 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x61,
+ 0x6c, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x24,
+ 0x52, 0x52, 0x24, 0x2e, 0x0a, 0x53, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x74,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x61,
+ 0x6e, 0x64, 0x20, 0x75, 0x70, 0x70, 0x65, 0x72, 0x20, 0x62, 0x6f, 0x75,
+ 0x6e, 0x64, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x20, 0x63, 0x61, 0x6e,
+ 0x20, 0x62, 0x65, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64,
+ 0x20, 0x6f, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x0a, 0x73, 0x69, 0x6e, 0x67,
+ 0x6c, 0x65, 0x20, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x20,
+ 0x74, 0x68, 0x65, 0x79, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65,
+ 0x20, 0x74, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20,
+ 0x70, 0x61, 0x69, 0x72, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x76, 0x61, 0x6c,
+ 0x75, 0x65, 0x73, 0x2e, 0x20, 0x20, 0x0a, 0x45, 0x61, 0x63, 0x68, 0x20,
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x68, 0x61, 0x76, 0x69, 0x6e, 0x67,
+ 0x20, 0x61, 0x6e, 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74,
+ 0x65, 0x20, 0x6f, 0x66, 0x20, 0x62, 0x65, 0x69, 0x6e, 0x67, 0x20, 0x6f,
+ 0x70, 0x65, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65,
+ 0x64, 0x20, 0x0a, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x73,
+ 0x73, 0x6f, 0x63, 0x69, 0x61, 0x74, 0x65, 0x64, 0x20, 0x6e, 0x75, 0x6d,
+ 0x62, 0x65, 0x72, 0x2e, 0x20, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x65, 0x78,
+ 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e,
+ 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x20, 0x28, 0x30, 0x2e, 0x33, 0x31,
+ 0x2c, 0x30, 0x2e, 0x33, 0x33, 0x5d, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
+ 0x62, 0x65, 0x0a, 0x74, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x61,
+ 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x61,
+ 0x69, 0x72, 0x20, 0x24, 0x6c, 0x6f, 0x20, 0x30, 0x2e, 0x33, 0x31, 0x24,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x24, 0x68, 0x69, 0x20, 0x30, 0x2e, 0x33,
+ 0x33, 0x24, 0x2e, 0x20, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x62, 0x72,
+ 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x73,
+ 0x75, 0x70, 0x65, 0x72, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x65, 0x64,
+ 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x69, 0x7a, 0x65,
+ 0x20, 0x76, 0x69, 0x73, 0x75, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6e, 0x66,
+ 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x77,
+ 0x72, 0x69, 0x74, 0x65, 0x69, 0x6e, 0x67, 0x20, 0x0a, 0x62, 0x6f, 0x75,
+ 0x6e, 0x64, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x70,
+ 0x61, 0x69, 0x72, 0x73, 0x2e, 0x0a, 0x41, 0x73, 0x20, 0x77, 0x65, 0x6c,
+ 0x6c, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x73, 0x75,
+ 0x61, 0x6c, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x6e, 0x75, 0x6d, 0x62,
+ 0x65, 0x72, 0x73, 0x20, 0x0a, 0x24, 0x2d, 0x20, 0x69, 0x6e, 0x66, 0x24,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x24, 0x69, 0x6e, 0x66, 0x24, 0x2c, 0x20,
+ 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64,
+ 0x20, 0x61, 0x73, 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20,
+ 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x2c, 0x0a, 0x77, 0x69, 0x74, 0x68,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74,
+ 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x24, 0x41, 0x4c,
+ 0x4c, 0x20, 0x78, 0x20, 0x6d, 0x6f, 0x20, 0x52, 0x52, 0x7e, 0x2d, 0x20,
+ 0x69, 0x6e, 0x66, 0x20, 0x3c, 0x20, 0x78, 0x20, 0x3c, 0x20, 0x69, 0x6e,
+ 0x66, 0x24, 0x20, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x73, 0x65, 0x74, 0x20,
+ 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x75, 0x70, 0x70, 0x65, 0x72,
+ 0x20, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x20, 0x69, 0x73, 0x20, 0x64,
+ 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x61, 0x73, 0x3a, 0x0a, 0x2e,
+ 0x73, 0x70, 0x0a, 0x09, 0x24, 0x48, 0x28, 0x52, 0x52, 0x29, 0x7e, 0x3d,
+ 0x3d, 0x7e, 0x5c, 0x7b, 0x20, 0x78, 0x20, 0x73, 0x75, 0x70, 0x20, 0x62,
+ 0x20, 0x3a, 0x20, 0x78, 0x20, 0x6d, 0x6f, 0x20, 0x52, 0x52, 0x20, 0x75,
+ 0x6e, 0x69, 0x6f, 0x6e, 0x20, 0x5c, 0x7b, 0x20, 0x69, 0x6e, 0x66, 0x20,
+ 0x5c, 0x7d, 0x2c, 0x7e, 0x62, 0x20, 0x6d, 0x6f, 0x20, 0x5c, 0x7b, 0x20,
+ 0x68, 0x69, 0x20, 0x2c, 0x20, 0x68, 0x6f, 0x20, 0x5c, 0x7d, 0x20, 0x5c,
+ 0x7d, 0x20, 0x24, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x61, 0x6e, 0x64, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x6c,
+ 0x6f, 0x77, 0x65, 0x72, 0x20, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x20,
+ 0x61, 0x73, 0x3a, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x09, 0x24, 0x4c, 0x28,
+ 0x52, 0x52, 0x29, 0x7e, 0x3d, 0x3d, 0x7e, 0x5c, 0x7b, 0x20, 0x5c, 0x26,
+ 0x20, 0x73, 0x75, 0x70, 0x20, 0x62, 0x20, 0x78, 0x20, 0x3a, 0x20, 0x78,
+ 0x20, 0x6d, 0x6f, 0x20, 0x52, 0x52, 0x20, 0x75, 0x6e, 0x69, 0x6f, 0x6e,
+ 0x20, 0x5c, 0x7b, 0x20, 0x2d, 0x69, 0x6e, 0x66, 0x20, 0x5c, 0x7d, 0x2c,
+ 0x7e, 0x62, 0x20, 0x6d, 0x6f, 0x20, 0x5c, 0x7b, 0x20, 0x6c, 0x69, 0x20,
+ 0x2c, 0x20, 0x6c, 0x6f, 0x20, 0x5c, 0x7d, 0x20, 0x5c, 0x7d, 0x20, 0x24,
+ 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x73, 0x65, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x69, 0x6e, 0x74, 0x65,
+ 0x72, 0x76, 0x61, 0x6c, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65,
+ 0x6e, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79,
+ 0x3a, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x09, 0x24, 0x49, 0x49, 0x28, 0x52,
+ 0x52, 0x29, 0x7e, 0x3d, 0x3d, 0x7e, 0x4c, 0x28, 0x52, 0x52, 0x29, 0x20,
+ 0x74, 0x69, 0x6d, 0x65, 0x73, 0x20, 0x48, 0x28, 0x52, 0x52, 0x29, 0x24,
+ 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74,
+ 0x68, 0x69, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x20, 0x72, 0x61, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6c, 0x6f, 0x6f, 0x73,
+ 0x65, 0x6c, 0x79, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c,
+ 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x69, 0x64,
+ 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x0a, 0x77, 0x69,
+ 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x70, 0x72, 0x6f, 0x70,
+ 0x72, 0x69, 0x61, 0x74, 0x65, 0x20, 0x73, 0x75, 0x62, 0x73, 0x65, 0x74,
+ 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x61, 0x6c,
+ 0x73, 0x2e, 0x20, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x65, 0x78, 0x61, 0x6d,
+ 0x70, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c,
+ 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74,
+ 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77,
+ 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x6d, 0x61, 0x64, 0x65, 0x3a,
+ 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x09, 0x24, 0x5b, 0x30, 0x2e, 0x33, 0x31,
+ 0x2c, 0x31, 0x35, 0x29, 0x7e, 0x3d, 0x7e, 0x3c, 0x20, 0x6c, 0x69, 0x20,
+ 0x30, 0x2e, 0x33, 0x31, 0x2c, 0x20, 0x68, 0x6f, 0x20, 0x31, 0x35, 0x20,
+ 0x3e, 0x7e, 0x3d, 0x7e, 0x20, 0x5c, 0x7b, 0x20, 0x78, 0x20, 0x6d, 0x6f,
+ 0x20, 0x52, 0x52, 0x3a, 0x20, 0x30, 0x2e, 0x33, 0x31, 0x20, 0x3c, 0x3d,
+ 0x20, 0x78, 0x20, 0x3c, 0x20, 0x31, 0x35, 0x20, 0x5c, 0x7d, 0x24, 0x0a,
+ 0x2e, 0x62, 0x72, 0x0a, 0x09, 0x24, 0x5b, 0x2d, 0x69, 0x6e, 0x66, 0x2c,
+ 0x69, 0x6e, 0x66, 0x5d, 0x7e, 0x3d, 0x7e, 0x3c, 0x20, 0x6c, 0x69, 0x20,
+ 0x2d, 0x69, 0x6e, 0x66, 0x20, 0x2c, 0x20, 0x68, 0x69, 0x20, 0x69, 0x6e,
+ 0x66, 0x3e, 0x20, 0x7e, 0x3d, 0x7e, 0x20, 0x52, 0x52, 0x24, 0x0a, 0x2e,
+ 0x62, 0x72, 0x0a, 0x61, 0x6e, 0x64, 0x09, 0x24, 0x28, 0x2d, 0x30, 0x2e,
+ 0x35, 0x31, 0x2c, 0x69, 0x6e, 0x66, 0x5d, 0x7e, 0x3d, 0x7e, 0x3c, 0x20,
+ 0x6c, 0x6f, 0x20, 0x2d, 0x30, 0x2e, 0x35, 0x31, 0x20, 0x2c, 0x20, 0x68,
+ 0x69, 0x20, 0x69, 0x6e, 0x66, 0x20, 0x3e, 0x7e, 0x3d, 0x7e, 0x20, 0x5c,
+ 0x7b, 0x20, 0x78, 0x20, 0x6d, 0x6f, 0x20, 0x52, 0x52, 0x3a, 0x20, 0x30,
+ 0x2e, 0x35, 0x31, 0x20, 0x3c, 0x20, 0x78, 0x20, 0x5c, 0x7d, 0x24, 0x0a,
+ 0x2e, 0x73, 0x70, 0x0a, 0x54, 0x68, 0x65, 0x20, 0x64, 0x65, 0x66, 0x69,
+ 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65,
+ 0x20, 0x63, 0x61, 0x72, 0x65, 0x66, 0x75, 0x6c, 0x6c, 0x79, 0x20, 0x65,
+ 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x20, 0x27, 0x69, 0x6e, 0x74,
+ 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x27, 0x20, 0x73, 0x75, 0x63, 0x68,
+ 0x20, 0x61, 0x73, 0x20, 0x24, 0x5b, 0x69, 0x6e, 0x66, 0x2c, 0x69, 0x6e,
+ 0x66, 0x5d, 0x24, 0x0a, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69,
+ 0x6e, 0x74, 0x65, 0x72, 0x65, 0x73, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20,
+ 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x79, 0x69, 0x6e, 0x67, 0x20,
+ 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6c, 0x61, 0x74, 0x65, 0x72, 0x20, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x6f,
+ 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x0a, 0x2e, 0x70, 0x70, 0x0a, 0x54,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x65, 0x20, 0x61, 0x72,
+ 0x69, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x20, 0x61, 0x76, 0x61,
+ 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6f, 0x6e, 0x20, 0x63, 0x6f,
+ 0x6d, 0x70, 0x75, 0x74, 0x65, 0x72, 0x73, 0x20, 0x69, 0x73, 0x20, 0x72,
+ 0x65, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x62,
+ 0x79, 0x20, 0x61, 0x0a, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x65, 0x20, 0x73,
+ 0x75, 0x62, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x24, 0x53, 0x53, 0x24, 0x2c,
+ 0x20, 0x6f, 0x66, 0x20, 0x24, 0x52, 0x52, 0x24, 0x2e, 0x20, 0x20, 0x49,
+ 0x74, 0x20, 0x69, 0x73, 0x20, 0x61, 0x73, 0x73, 0x75, 0x6d, 0x65, 0x64,
+ 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x0a, 0x24, 0x30, 0x2c, 0x31, 0x20,
+ 0x6d, 0x6f, 0x20, 0x53, 0x53, 0x24, 0x2e, 0x20, 0x20, 0x54, 0x68, 0x65,
+ 0x20, 0x73, 0x65, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x69, 0x6e, 0x74, 0x65,
+ 0x72, 0x76, 0x61, 0x6c, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65,
+ 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x24, 0x53, 0x53, 0x24, 0x20,
+ 0x69, 0x73, 0x20, 0x24, 0x49, 0x49, 0x28, 0x53, 0x53, 0x29, 0x24, 0x20,
+ 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x0a,
+ 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x24, 0x52,
+ 0x52, 0x24, 0x2e, 0x20, 0x20, 0x24, 0x53, 0x53, 0x24, 0x20, 0x6d, 0x69,
+ 0x67, 0x68, 0x74, 0x20, 0x62, 0x65, 0x20, 0x61, 0x20, 0x62, 0x6f, 0x75,
+ 0x6e, 0x64, 0x65, 0x64, 0x20, 0x73, 0x65, 0x74, 0x20, 0x6f, 0x66, 0x20,
+ 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x73, 0x20, 0x6f, 0x72, 0x20,
+ 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x63, 0x6f,
+ 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x72, 0x65,
+ 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20,
+ 0x62, 0x79, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20,
+ 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72,
+ 0x73, 0x2e, 0x0a, 0x2e, 0x70, 0x70, 0x0a, 0x54, 0x68, 0x65, 0x72, 0x65,
+ 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x75, 0x73, 0x65, 0x66, 0x75, 0x6c,
+ 0x20, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x72, 0x6f,
+ 0x6d, 0x20, 0x24, 0x49, 0x49, 0x28, 0x52, 0x52, 0x29, 0x24, 0x20, 0x74,
+ 0x6f, 0x20, 0x24, 0x49, 0x49, 0x28, 0x53, 0x53, 0x29, 0x24, 0x20, 0x77,
+ 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, 0x73, 0x73, 0x6f, 0x63, 0x69, 0x61,
+ 0x74, 0x65, 0x73, 0x0a, 0x77, 0x69, 0x74, 0x68, 0x20, 0x65, 0x61, 0x63,
+ 0x68, 0x20, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72,
+ 0x76, 0x61, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x73, 0x74,
+ 0x20, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x6d, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x74, 0x3a, 0x0a, 0x2e, 0x6e,
+ 0x66, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x09, 0x24, 0x61, 0x70, 0x70, 0x72,
+ 0x6f, 0x78, 0x28, 0x3c, 0x6c, 0x2c, 0x68, 0x3e, 0x29, 0x7e, 0x3d, 0x3d,
+ 0x7e, 0x3c, 0x6c, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x2c, 0x20, 0x68,
+ 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x20, 0x3e, 0x24, 0x0a, 0x2e, 0x62,
+ 0x72, 0x0a, 0x77, 0x68, 0x65, 0x72, 0x65, 0x09, 0x24, 0x6c, 0x20, 0x70,
+ 0x72, 0x69, 0x6d, 0x65, 0x20, 0x6d, 0x6f, 0x20, 0x4c, 0x28, 0x53, 0x53,
+ 0x29, 0x2c, 0x20, 0x6c, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x20, 0x3c,
+ 0x3d, 0x20, 0x6c, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4e, 0x45, 0x58,
+ 0x49, 0x53, 0x54, 0x20, 0x78, 0x20, 0x6d, 0x6f, 0x20, 0x4c, 0x28, 0x53,
+ 0x53, 0x29, 0x7e, 0x6c, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x20, 0x3c,
+ 0x78, 0x3c, 0x6c, 0x24, 0x0a, 0x2e, 0x62, 0x72, 0x0a, 0x09, 0x24, 0x68,
+ 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x20, 0x6d, 0x6f, 0x20, 0x48, 0x28,
+ 0x53, 0x53, 0x29, 0x2c, 0x20, 0x68, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65,
+ 0x20, 0x3e, 0x3d, 0x20, 0x68, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x4e,
+ 0x45, 0x58, 0x49, 0x53, 0x54, 0x20, 0x78, 0x20, 0x6d, 0x6f, 0x20, 0x48,
+ 0x28, 0x53, 0x53, 0x29, 0x7e, 0x68, 0x20, 0x70, 0x72, 0x69, 0x6d, 0x65,
+ 0x20, 0x3e, 0x78, 0x3e, 0x68, 0x24, 0x2e, 0x0a, 0x2e, 0x70, 0x70, 0x0a,
+ 0x54, 0x68, 0x65, 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x69, 0x6e, 0x67,
+ 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, 0x75, 0x6e,
+ 0x64, 0x73, 0x20, 0x69, 0x73, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65,
+ 0x64, 0x20, 0x61, 0x73, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x73,
+ 0x3a, 0x0a, 0x2e, 0x73, 0x70, 0x0a, 0x09, 0x24, 0x6c, 0x20, 0x3c, 0x20,
+ 0x68, 0x2c, 0x20, 0x7e, 0x20, 0x6c, 0x2c, 0x68, 0x20, 0x6d, 0x6f, 0x20,
+ 0x49, 0x49, 0x28, 0x52, 0x52, 0x29, 0x7e, 0x20, 0x3c, 0x2d, 0x3e, 0x7e,
+ 0x6c, 0x3d, 0x20, 0x5c, 0x26, 0x20, 0x73, 0x75, 0x70, 0x20, 0x75, 0x20,
+ 0x78, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x0a
+};
+unsigned int paper5_8192_len = 8192;
diff --git a/drivers/staging/fsl_dce/tests/common/paper6_12K_compressed.gz.h b/drivers/staging/fsl_dce/tests/common/paper6_12K_compressed.gz.h
new file mode 100644
index 0000000..8d791fb
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/common/paper6_12K_compressed.gz.h
@@ -0,0 +1,1029 @@
+unsigned char paper6_12K_compressed_gz[] = {
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0xdd, 0x7d,
+ 0x6b, 0x73, 0xdb, 0x46, 0x96, 0xe8, 0x67, 0xf5, 0xaf, 0xe8, 0xe5, 0x20,
+ 0x6b, 0xa9, 0x4c, 0x32, 0x24, 0xf5, 0xf2, 0x23, 0xce, 0x94, 0xa2, 0x38,
+ 0xb1, 0x12, 0xd9, 0xf1, 0x95, 0x3d, 0xce, 0xdd, 0x8a, 0x74, 0xab, 0x40,
+ 0xa2, 0x29, 0x22, 0x02, 0x01, 0x0e, 0x1e, 0x52, 0x34, 0x4e, 0xf8, 0xdb,
+ 0xef, 0x79, 0xf5, 0x03, 0x20, 0xa5, 0xcc, 0xce, 0xdd, 0xda, 0xda, 0xba,
+ 0xa9, 0x8a, 0x4c, 0x12, 0x40, 0xf7, 0xe9, 0xd3, 0xe7, 0x7d, 0x4e, 0x1f,
+ 0x0c, 0x5f, 0xff, 0x2f, 0x95, 0x98, 0x2c, 0x5d, 0xea, 0x28, 0x82, 0x0f,
+ 0xf3, 0x34, 0x37, 0xfa, 0xab, 0x81, 0xfe, 0xeb, 0x57, 0xba, 0x77, 0xb9,
+ 0x78, 0x32, 0x18, 0x0d, 0x0f, 0x97, 0x4f, 0x7a, 0xba, 0x59, 0xe9, 0xf1,
+ 0x08, 0x7e, 0xd9, 0x35, 0xcb, 0x9e, 0x4e, 0x8a, 0xbb, 0x1c, 0xbf, 0xfe,
+ 0xd5, 0xde, 0x7f, 0x5d, 0x17, 0x65, 0x62, 0x4a, 0xfd, 0xd7, 0xde, 0xe5,
+ 0x3f, 0xbe, 0xbe, 0x4c, 0x2e, 0xd7, 0x97, 0x4d, 0xcf, 0x5d, 0x7c, 0xfd,
+ 0xbf, 0xcf, 0x3e, 0x7c, 0xa4, 0x4b, 0x97, 0x03, 0xb8, 0x86, 0x7f, 0x4b,
+ 0xfa, 0x74, 0xfb, 0x64, 0x34, 0x9c, 0x2c, 0x9f, 0x5c, 0xee, 0x4e, 0x4b,
+ 0xf8, 0x3c, 0xa0, 0x2f, 0xfe, 0xb1, 0x93, 0xf3, 0x73, 0x7c, 0xa8, 0x78,
+ 0xf2, 0x69, 0x10, 0xfc, 0x3a, 0x7a, 0xab, 0x9f, 0x8c, 0xd6, 0xc3, 0xe1,
+ 0x70, 0xfd, 0x76, 0x30, 0x7e, 0x62, 0x7f, 0x3d, 0x7f, 0xa3, 0x9f, 0x64,
+ 0x05, 0xfd, 0xbc, 0x48, 0xdd, 0xaf, 0x17, 0x17, 0xfa, 0xc9, 0xb4, 0xc8,
+ 0x12, 0x7d, 0xe1, 0x7e, 0x7a, 0xf3, 0x46, 0x7e, 0x7a, 0xe3, 0x7e, 0xfa,
+ 0xf1, 0x47, 0xf9, 0xe9, 0x47, 0xf7, 0x53, 0x51, 0xea, 0x27, 0xbd, 0xcb,
+ 0xf9, 0x37, 0x45, 0x79, 0x39, 0x3f, 0xeb, 0xad, 0xdd, 0xef, 0x71, 0x9e,
+ 0xf0, 0x05, 0xf8, 0xd0, 0xbe, 0x92, 0xce, 0xf9, 0x42, 0x3a, 0x6f, 0xff,
+ 0x5e, 0x2f, 0x4c, 0xce, 0x57, 0xf0, 0x53, 0xfb, 0x9a, 0xc9, 0x2a, 0xc3,
+ 0xd7, 0xf0, 0x53, 0xfb, 0x5a, 0x69, 0x56, 0x26, 0xae, 0xf9, 0x2a, 0x7f,
+ 0x6e, 0x5f, 0x6f, 0xf2, 0x3a, 0xcd, 0xf8, 0x32, 0x7d, 0x6c, 0x5f, 0xbd,
+ 0x5b, 0xa4, 0x99, 0x0c, 0x4d, 0x1f, 0xdb, 0x57, 0x93, 0x82, 0x2f, 0x25,
+ 0x45, 0xfb, 0xf7, 0x59, 0x6c, 0xe1, 0xc1, 0x4f, 0x1d, 0x58, 0xed, 0xca,
+ 0x4d, 0x77, 0xe5, 0x53, 0x73, 0x9d, 0xca, 0x12, 0xe9, 0xe3, 0xe6, 0x1a,
+ 0x2d, 0x6e, 0xf8, 0x33, 0x5f, 0xd7, 0xf6, 0x86, 0xb9, 0xc5, 0xf5, 0xbc,
+ 0x8b, 0xec, 0xef, 0xca, 0x62, 0x29, 0x97, 0xe0, 0x53, 0xfb, 0xda, 0x47,
+ 0x59, 0x42, 0xdd, 0x59, 0x82, 0xf9, 0x2d, 0x15, 0xa4, 0xe1, 0x27, 0xb9,
+ 0x36, 0x7c, 0xfd, 0x4e, 0x0d, 0xb3, 0x4a, 0x8f, 0x77, 0xd4, 0x70, 0x66,
+ 0xd4, 0xe9, 0x4f, 0x6f, 0xdf, 0x9f, 0x9c, 0x7e, 0xd4, 0x6f, 0x4e, 0x3e,
+ 0xbc, 0xd1, 0x1f, 0x4f, 0xbe, 0x39, 0x7f, 0xfd, 0x41, 0xff, 0xed, 0xc3,
+ 0xd9, 0xbb, 0xef, 0xf5, 0x37, 0x67, 0xdf, 0x9e, 0x5d, 0xbc, 0x3e, 0xfd,
+ 0x78, 0xf6, 0xd3, 0xbb, 0x93, 0x73, 0x7d, 0x7e, 0xf6, 0xee, 0xf5, 0xc9,
+ 0x85, 0x7e, 0x7f, 0xf1, 0xd3, 0x37, 0x70, 0x51, 0x0d, 0xab, 0x95, 0xde,
+ 0xa7, 0x01, 0x7e, 0x28, 0x16, 0xb9, 0xfe, 0x7e, 0xa8, 0x4f, 0x33, 0x13,
+ 0x97, 0xf7, 0xf4, 0xd3, 0xc7, 0x85, 0xd1, 0x7f, 0xcb, 0xd3, 0x5b, 0x53,
+ 0x56, 0x69, 0x7d, 0xaf, 0x8b, 0xb9, 0x3e, 0x8d, 0xb3, 0x6b, 0xb8, 0xda,
+ 0xd7, 0x27, 0xd9, 0xd4, 0x94, 0x75, 0xdc, 0x87, 0x5f, 0xf2, 0x38, 0x89,
+ 0x87, 0x76, 0x20, 0xf8, 0x3b, 0x19, 0xa9, 0xcb, 0x66, 0x7c, 0x99, 0x9c,
+ 0x34, 0xf5, 0xa2, 0x28, 0x2b, 0xfd, 0xbe, 0x34, 0x95, 0xc9, 0x6b, 0x7d,
+ 0x92, 0x24, 0xf0, 0xa9, 0x7a, 0xa1, 0xdf, 0xc6, 0xf9, 0xe0, 0x6d, 0x3c,
+ 0x5b, 0xe0, 0xd2, 0x3e, 0xdc, 0x57, 0xb5, 0x59, 0x56, 0xfa, 0xfb, 0xb2,
+ 0x68, 0x56, 0x7d, 0xfd, 0xad, 0x59, 0xc5, 0x65, 0xbd, 0xc4, 0xdb, 0x8b,
+ 0xb9, 0x3a, 0x2d, 0x96, 0xab, 0xa6, 0x06, 0x06, 0xfc, 0x30, 0x4b, 0x4d,
+ 0x3e, 0x33, 0x7d, 0xfd, 0x08, 0x44, 0x93, 0xc3, 0xd1, 0x28, 0xbc, 0xf6,
+ 0x6d, 0x09, 0x1f, 0xf5, 0xbb, 0x9f, 0x95, 0xbb, 0x83, 0x41, 0xd5, 0x1f,
+ 0x27, 0xef, 0xf4, 0xf8, 0xdd, 0x01, 0x81, 0x0c, 0x90, 0x4e, 0x2e, 0x93,
+ 0x8f, 0x8b, 0xb4, 0xd2, 0x08, 0x65, 0x5c, 0xce, 0x16, 0xfa, 0x2e, 0xae,
+ 0x74, 0xd5, 0xac, 0x56, 0x45, 0x59, 0x9b, 0x44, 0x4f, 0xef, 0x15, 0xd0,
+ 0xb8, 0x7e, 0x17, 0xd7, 0x4d, 0x19, 0x67, 0x16, 0x92, 0x8a, 0x98, 0xe6,
+ 0x75, 0x0e, 0x94, 0x61, 0x4c, 0x99, 0xe6, 0xd7, 0xfa, 0xc2, 0x3e, 0x7e,
+ 0x5a, 0x34, 0xf9, 0x0c, 0xa8, 0x98, 0x60, 0xf3, 0xb8, 0x99, 0xd0, 0x66,
+ 0xc1, 0xdf, 0xe9, 0x4a, 0x9d, 0xe5, 0x89, 0xf9, 0x4d, 0x7f, 0x34, 0x25,
+ 0x2c, 0x7c, 0x30, 0xd0, 0xfa, 0x03, 0x3d, 0x09, 0xa3, 0xf4, 0xf5, 0x22,
+ 0xae, 0x16, 0xba, 0x02, 0xb9, 0x13, 0x5f, 0xc3, 0x72, 0x8b, 0x15, 0xf0,
+ 0x59, 0xcc, 0x78, 0xa3, 0xcb, 0x6a, 0x9a, 0x26, 0x69, 0x69, 0x66, 0x75,
+ 0x5a, 0xe4, 0x00, 0x4d, 0x06, 0xd3, 0xc7, 0xa5, 0x5e, 0x95, 0xc5, 0x14,
+ 0x2f, 0x2b, 0xb9, 0x15, 0x68, 0x3e, 0x9b, 0x35, 0x59, 0x8c, 0x77, 0xf5,
+ 0x75, 0x9a, 0x03, 0x11, 0x2e, 0xe9, 0x0b, 0x2c, 0xb2, 0x2e, 0x53, 0x73,
+ 0x1b, 0x67, 0x7d, 0x5d, 0xcd, 0xe2, 0x1a, 0x71, 0xeb, 0x26, 0x53, 0x2b,
+ 0x53, 0xd2, 0x9d, 0xb0, 0x3e, 0x58, 0x5e, 0x9c, 0xdd, 0x57, 0x69, 0xd5,
+ 0xd7, 0x4b, 0xb3, 0x2c, 0xca, 0x7b, 0x3d, 0x83, 0xbd, 0x88, 0x69, 0xde,
+ 0x21, 0xad, 0x61, 0xb8, 0x5a, 0xa9, 0x93, 0x69, 0x55, 0x97, 0xf0, 0x23,
+ 0x2e, 0xe2, 0x04, 0x00, 0xcd, 0xae, 0x8b, 0x32, 0xad, 0x17, 0x4b, 0x0d,
+ 0xe8, 0x4c, 0xcc, 0xad, 0xc9, 0x00, 0xfe, 0x04, 0xd9, 0x16, 0xd0, 0x52,
+ 0x9a, 0xa4, 0x41, 0xbc, 0x21, 0x32, 0x65, 0x48, 0x55, 0x9a, 0xbf, 0x37,
+ 0xb0, 0x1a, 0xdc, 0xee, 0x0a, 0xf1, 0x45, 0x8b, 0xaf, 0xe3, 0x69, 0x66,
+ 0xaa, 0xa1, 0xa2, 0x4d, 0xc1, 0x91, 0x90, 0x52, 0x60, 0x30, 0xdc, 0x0a,
+ 0x02, 0x16, 0xb1, 0x5d, 0xe4, 0xd9, 0xbd, 0x8a, 0xb5, 0x46, 0x6a, 0xc1,
+ 0x27, 0x0d, 0xdc, 0xa4, 0x6f, 0xcc, 0x3d, 0xc0, 0x50, 0xc0, 0xe5, 0x3b,
+ 0x80, 0x42, 0xc7, 0x7a, 0x6e, 0xee, 0x80, 0x77, 0x00, 0x44, 0x3d, 0x4d,
+ 0x61, 0x06, 0xd8, 0xaa, 0x04, 0x86, 0xa9, 0x0b, 0xe0, 0xfb, 0xaa, 0x29,
+ 0x51, 0x8c, 0xc5, 0xb5, 0x8a, 0xb3, 0x0c, 0x9f, 0x84, 0x79, 0xe0, 0x17,
+ 0x1c, 0x1f, 0x6e, 0x69, 0xf2, 0x78, 0x39, 0x4d, 0xaf, 0x9b, 0xa2, 0xa9,
+ 0xb2, 0xfb, 0xa1, 0x26, 0xb2, 0x9b, 0x97, 0xbc, 0xfc, 0xd6, 0x74, 0x7c,
+ 0x3f, 0xf0, 0xe9, 0xac, 0x34, 0x20, 0x5d, 0x60, 0x10, 0x5e, 0x61, 0x95,
+ 0xfe, 0xc3, 0xe0, 0x8d, 0xf8, 0xd9, 0xaf, 0x0a, 0xb6, 0x42, 0xee, 0x83,
+ 0x31, 0x3f, 0xa4, 0xd7, 0x79, 0x3a, 0x4f, 0x67, 0x31, 0xd0, 0x3a, 0x21,
+ 0x07, 0x07, 0xaf, 0x14, 0x48, 0x9d, 0xba, 0xa8, 0x61, 0x6f, 0x05, 0x49,
+ 0x4d, 0x05, 0x9b, 0x03, 0x1b, 0x9a, 0x83, 0x48, 0xf2, 0xa8, 0x30, 0xd5,
+ 0xca, 0xcc, 0x52, 0x00, 0xfd, 0x1e, 0xd0, 0x0b, 0x34, 0x82, 0xf3, 0x10,
+ 0x3c, 0x38, 0x2f, 0xe0, 0x2c, 0x2f, 0x6a, 0xb5, 0x6c, 0x00, 0xc8, 0x2c,
+ 0x2e, 0xaf, 0x61, 0x93, 0x61, 0xa5, 0x79, 0x0b, 0xb0, 0xd8, 0x8e, 0x9f,
+ 0x12, 0x2d, 0x22, 0x35, 0xd3, 0x40, 0x88, 0x58, 0xb8, 0x58, 0x2d, 0x11,
+ 0x2d, 0xf1, 0x12, 0x68, 0xb9, 0x56, 0x70, 0x7b, 0x12, 0xd7, 0x31, 0x8e,
+ 0x2b, 0xf8, 0x21, 0xfc, 0x5a, 0x24, 0x0c, 0x49, 0x4e, 0xb4, 0x36, 0x5f,
+ 0x4f, 0x61, 0x91, 0x09, 0x0c, 0xf6, 0x38, 0xc1, 0x0e, 0x15, 0x53, 0x3e,
+ 0x4d, 0x9f, 0xe6, 0x15, 0x48, 0x14, 0x44, 0x70, 0x9d, 0x2e, 0x8d, 0x6c,
+ 0xc7, 0x02, 0x55, 0x32, 0xee, 0x7b, 0xba, 0x14, 0x7a, 0xd6, 0x0a, 0xf6,
+ 0x6f, 0x8a, 0x0b, 0x59, 0xa6, 0xb0, 0x38, 0xdc, 0x4d, 0x10, 0x33, 0x95,
+ 0x51, 0x28, 0x72, 0x41, 0x5d, 0xa7, 0x39, 0xf0, 0xba, 0x7e, 0x7c, 0x56,
+ 0xa2, 0x5f, 0xd8, 0x94, 0xde, 0x58, 0x9f, 0xe5, 0x75, 0x59, 0x08, 0xf2,
+ 0x7b, 0x44, 0xd4, 0xb8, 0x18, 0xc7, 0x26, 0x8c, 0x2a, 0xe4, 0x3d, 0xdc,
+ 0x3d, 0x90, 0x54, 0x1a, 0xa5, 0x36, 0x22, 0x06, 0xa8, 0x0c, 0x38, 0x05,
+ 0x44, 0x10, 0x60, 0x15, 0x84, 0x1c, 0xd2, 0x29, 0xf2, 0x08, 0x5c, 0xa0,
+ 0x79, 0x32, 0xb3, 0xc4, 0xad, 0x9c, 0x59, 0x09, 0x56, 0xb1, 0xdc, 0x80,
+ 0x7d, 0x3f, 0x83, 0xa7, 0x89, 0x6e, 0x53, 0x64, 0xd1, 0x32, 0x43, 0xd6,
+ 0x82, 0x2b, 0x65, 0x0e, 0x08, 0x83, 0xa1, 0x0c, 0x23, 0x17, 0xf7, 0x8a,
+ 0x34, 0xd7, 0x1d, 0xfd, 0x46, 0x32, 0x88, 0xe6, 0x27, 0x49, 0x45, 0xd0,
+ 0x31, 0x82, 0xf1, 0x02, 0x60, 0x3b, 0xad, 0x5a, 0xa0, 0x66, 0xf1, 0xd4,
+ 0x64, 0x0a, 0x30, 0x42, 0x3c, 0x51, 0xd7, 0xb0, 0x55, 0x42, 0xf9, 0xb8,
+ 0x69, 0xc0, 0x6f, 0x80, 0x23, 0xd9, 0x73, 0xe2, 0x03, 0xe3, 0x59, 0x00,
+ 0x48, 0x47, 0x93, 0xd9, 0x63, 0x70, 0x4f, 0xe0, 0xae, 0x7b, 0xe5, 0xa1,
+ 0x05, 0xe1, 0xc8, 0xfb, 0x5d, 0x1a, 0x5e, 0xf2, 0x9d, 0x41, 0xf6, 0xc9,
+ 0x71, 0x9b, 0xaa, 0x22, 0x6b, 0x10, 0x8d, 0x8a, 0xb6, 0x04, 0xae, 0x0a,
+ 0x1e, 0x70, 0x14, 0x9c, 0x01, 0x65, 0xcb, 0x06, 0x97, 0xff, 0x98, 0x83,
+ 0x96, 0xd0, 0xbf, 0x3c, 0xbb, 0xea, 0xeb, 0x1f, 0x61, 0xe6, 0x5a, 0xff,
+ 0x72, 0x7c, 0x45, 0x90, 0xbd, 0x8d, 0x81, 0x43, 0x4b, 0xfa, 0x78, 0x6e,
+ 0xee, 0x60, 0xb4, 0x5f, 0xc6, 0xe3, 0x2b, 0x1c, 0xf2, 0x36, 0x4d, 0xc0,
+ 0x32, 0x2b, 0x0a, 0x84, 0xce, 0xef, 0x5d, 0x85, 0x8b, 0x53, 0x34, 0x6d,
+ 0xd5, 0x4c, 0x7f, 0x85, 0xad, 0x1f, 0xb2, 0x88, 0xca, 0xb5, 0x99, 0x03,
+ 0x97, 0xa5, 0xa8, 0x52, 0x48, 0x35, 0x30, 0x07, 0x23, 0x10, 0x28, 0x48,
+ 0x40, 0x52, 0x66, 0xc0, 0xc0, 0xc3, 0x26, 0x7b, 0x94, 0x52, 0xb5, 0xda,
+ 0xfd, 0xe6, 0xfc, 0xfd, 0x5e, 0x5f, 0xa1, 0x72, 0xf0, 0xa2, 0x0d, 0x28,
+ 0xf3, 0x64, 0x89, 0x8c, 0x8d, 0x60, 0xca, 0x52, 0xc6, 0x57, 0x43, 0x75,
+ 0x02, 0x04, 0x51, 0xd3, 0x82, 0xab, 0xf6, 0x06, 0xdd, 0x81, 0xc4, 0x81,
+ 0xdf, 0xb3, 0xac, 0xb8, 0xa3, 0x5b, 0x48, 0x50, 0x56, 0xb3, 0x32, 0x9d,
+ 0x32, 0xb6, 0x81, 0x25, 0xc1, 0x92, 0x31, 0x75, 0x0c, 0x0a, 0x84, 0xd1,
+ 0xa6, 0xf8, 0x6e, 0x84, 0xa1, 0x62, 0xe0, 0x50, 0x76, 0xf0, 0x27, 0xbd,
+ 0x4f, 0x1c, 0x52, 0x69, 0xf8, 0x83, 0xa3, 0x89, 0x94, 0x58, 0x16, 0x09,
+ 0x08, 0x16, 0x18, 0xb0, 0x2a, 0x48, 0x1e, 0x01, 0x62, 0x2a, 0x2f, 0x6c,
+ 0x80, 0xe0, 0x58, 0x16, 0x6b, 0x94, 0x89, 0x22, 0x05, 0x42, 0x49, 0x4c,
+ 0xf2, 0x2e, 0x25, 0x92, 0x4e, 0x0a, 0x34, 0x85, 0x36, 0xc4, 0x2e, 0x4b,
+ 0x87, 0x0d, 0xd9, 0x0b, 0x5a, 0x60, 0x43, 0xe6, 0x12, 0x45, 0x75, 0xe5,
+ 0xae, 0x42, 0xc1, 0xab, 0x01, 0xc8, 0x39, 0xd0, 0x11, 0xec, 0x0b, 0xd2,
+ 0x5e, 0x9f, 0xa4, 0xb1, 0xce, 0x8a, 0xe2, 0x86, 0x05, 0x55, 0xbc, 0x04,
+ 0xb4, 0xce, 0x91, 0x77, 0xea, 0x12, 0x34, 0xaa, 0x28, 0x33, 0x1c, 0x6f,
+ 0x56, 0x94, 0xb8, 0x4f, 0x00, 0x4a, 0x92, 0x56, 0x35, 0xc0, 0xd5, 0xa4,
+ 0x15, 0x90, 0xf7, 0xd0, 0xb1, 0xaf, 0xf9, 0xcd, 0xcc, 0x1a, 0x27, 0x4a,
+ 0x58, 0x0e, 0xc3, 0x6a, 0x44, 0x85, 0xb9, 0xbd, 0x6f, 0x89, 0x2c, 0x60,
+ 0xc2, 0x2a, 0xb5, 0x54, 0xaf, 0x2c, 0x82, 0x0f, 0x90, 0x61, 0x69, 0x9b,
+ 0xb6, 0x89, 0x22, 0x96, 0x44, 0x2a, 0x10, 0x45, 0x5e, 0x02, 0x01, 0xb9,
+ 0x90, 0x48, 0x9a, 0x82, 0x80, 0x00, 0x92, 0x9c, 0x81, 0xee, 0xab, 0xe6,
+ 0x4d, 0xa6, 0xd9, 0x4a, 0x10, 0x03, 0xc2, 0xc9, 0x3c, 0x3f, 0x4d, 0xb8,
+ 0x51, 0x6a, 0x6a, 0x48, 0x45, 0xe3, 0x38, 0x4d, 0xbe, 0x65, 0x10, 0x78,
+ 0x8c, 0xa9, 0xdc, 0xad, 0xa9, 0x82, 0x9f, 0x97, 0x2d, 0xe9, 0xd8, 0x5d,
+ 0x35, 0x91, 0x15, 0x60, 0x1a, 0xf9, 0x1c, 0xb7, 0x51, 0xb4, 0x14, 0x6e,
+ 0x60, 0x5a, 0x29, 0x11, 0xf0, 0x70, 0x33, 0x2c, 0xcd, 0x90, 0x2c, 0x5b,
+ 0x15, 0x95, 0x90, 0x7a, 0x0e, 0xd6, 0x45, 0x6c, 0xf4, 0x2f, 0x93, 0x2b,
+ 0xbd, 0x7b, 0xba, 0x88, 0x57, 0x08, 0xdb, 0x78, 0x0f, 0x80, 0x78, 0x53,
+ 0xdc, 0x01, 0x4f, 0x94, 0x60, 0xbe, 0xc0, 0x12, 0x6a, 0x33, 0x5b, 0xe4,
+ 0xe9, 0xdf, 0x1b, 0xc0, 0x0c, 0x0e, 0x63, 0xc9, 0x65, 0xda, 0x00, 0xe5,
+ 0xa7, 0x39, 0x08, 0x31, 0x62, 0xaa, 0x78, 0x9a, 0x66, 0x62, 0xc2, 0x89,
+ 0x3c, 0xa3, 0x2d, 0xc9, 0x51, 0x47, 0xf2, 0xfe, 0xb2, 0x6e, 0x39, 0xc9,
+ 0x40, 0xbc, 0x37, 0xd7, 0x8b, 0xee, 0x3a, 0x14, 0x6b, 0x39, 0xaf, 0x69,
+ 0x68, 0x8b, 0x01, 0x2f, 0x59, 0x8a, 0x24, 0xe3, 0x60, 0x00, 0xb6, 0x10,
+ 0xa1, 0x91, 0xd0, 0x3a, 0xd3, 0xe5, 0xca, 0xd4, 0x0d, 0x72, 0x85, 0xaa,
+ 0x8c, 0x61, 0x5a, 0x9b, 0x35, 0x25, 0xd1, 0xa1, 0x95, 0x60, 0x4c, 0x49,
+ 0x67, 0xf9, 0x26, 0xa5, 0x54, 0xa0, 0x8f, 0x05, 0xce, 0x02, 0x16, 0x3c,
+ 0x07, 0xce, 0x44, 0x92, 0x8c, 0x69, 0x37, 0x63, 0x14, 0x1a, 0x37, 0x30,
+ 0x4f, 0x06, 0x64, 0x89, 0x0b, 0xab, 0xee, 0xf3, 0x22, 0xbf, 0x5f, 0x56,
+ 0x28, 0x88, 0x01, 0x7f, 0xb7, 0x71, 0x99, 0xc6, 0x2c, 0xac, 0x2c, 0x49,
+ 0xf2, 0x68, 0xd3, 0x66, 0x76, 0x63, 0x80, 0x59, 0x76, 0x01, 0xa2, 0xed,
+ 0x82, 0x6f, 0x8f, 0x15, 0x33, 0xca, 0x03, 0xe0, 0xd2, 0x18, 0x95, 0x76,
+ 0xd9, 0xe2, 0x3d, 0xe4, 0x31, 0x52, 0x8b, 0xb4, 0x7f, 0x96, 0x85, 0xdd,
+ 0x36, 0x8a, 0x84, 0x4e, 0xc9, 0xb4, 0x03, 0x2e, 0x03, 0x23, 0xa4, 0x56,
+ 0xe3, 0xe7, 0x47, 0x87, 0x7a, 0xf7, 0x3b, 0x93, 0x25, 0xa0, 0xc9, 0x78,
+ 0x42, 0x58, 0xce, 0x2f, 0x47, 0x57, 0xa1, 0x38, 0x7b, 0x76, 0x85, 0x72,
+ 0x67, 0xa8, 0x8f, 0x86, 0x07, 0x7d, 0x64, 0xac, 0x72, 0x96, 0x82, 0x56,
+ 0x1a, 0xef, 0xf7, 0xf5, 0xea, 0xf0, 0x60, 0x1f, 0x37, 0x5f, 0xb9, 0xdd,
+ 0x0f, 0x94, 0xcb, 0x2e, 0x4c, 0x95, 0x35, 0x09, 0xae, 0x0e, 0x31, 0x0c,
+ 0xd8, 0x03, 0x53, 0x19, 0xc4, 0x2a, 0x09, 0xff, 0xac, 0x60, 0x76, 0xde,
+ 0xb3, 0x72, 0x07, 0xa9, 0x64, 0x55, 0x80, 0x3c, 0x37, 0x25, 0x6b, 0x0f,
+ 0x14, 0x1a, 0xbf, 0xd5, 0x1e, 0xc7, 0x40, 0x0f, 0xc0, 0x59, 0x76, 0x59,
+ 0x72, 0x2b, 0x68, 0x4a, 0x34, 0x52, 0xa6, 0x05, 0x50, 0x96, 0x13, 0x19,
+ 0x64, 0xe0, 0xb0, 0x15, 0xa6, 0x9c, 0x59, 0x65, 0x55, 0x90, 0x35, 0x91,
+ 0x50, 0x84, 0x16, 0x28, 0x71, 0x44, 0x8f, 0xe5, 0x05, 0xcc, 0x57, 0x5b,
+ 0x61, 0x58, 0xc5, 0x44, 0x8b, 0x34, 0xbb, 0xea, 0x98, 0xe0, 0x9e, 0xb2,
+ 0x50, 0xd1, 0xa0, 0xe9, 0x52, 0x21, 0xab, 0x8b, 0xb2, 0x41, 0xb3, 0xa0,
+ 0x62, 0x60, 0x80, 0x6b, 0xaa, 0x94, 0x54, 0xc3, 0x6a, 0x95, 0xa5, 0x33,
+ 0xbf, 0xef, 0x1b, 0xfc, 0x28, 0x16, 0x23, 0x9b, 0xe1, 0x68, 0x6c, 0xd5,
+ 0xa5, 0x11, 0xf9, 0xf0, 0xf1, 0xe2, 0x0c, 0xdc, 0x38, 0x34, 0x08, 0xec,
+ 0x1a, 0x9b, 0x8a, 0xe4, 0x99, 0x60, 0xa0, 0x22, 0xae, 0x02, 0x19, 0x88,
+ 0xe2, 0x18, 0x1d, 0x98, 0x12, 0x21, 0x07, 0x09, 0x1d, 0x65, 0xc5, 0xb5,
+ 0x7e, 0x17, 0x05, 0x86, 0x0c, 0x4a, 0xc2, 0xa1, 0x56, 0x2c, 0x65, 0x16,
+ 0xa4, 0xbd, 0x00, 0xd3, 0xe0, 0x84, 0x17, 0x28, 0xc5, 0x85, 0x7d, 0x02,
+ 0x58, 0xbb, 0xda, 0x08, 0x44, 0x9e, 0x29, 0x79, 0x99, 0xef, 0x63, 0xf0,
+ 0x1d, 0x32, 0xab, 0x4d, 0x2b, 0x2b, 0x41, 0x02, 0x26, 0xf1, 0x3a, 0x0d,
+ 0xcc, 0x10, 0x66, 0x11, 0x1d, 0xdf, 0xc2, 0x30, 0xa8, 0xf5, 0x15, 0x99,
+ 0x50, 0xf4, 0x04, 0x79, 0x88, 0x43, 0xb6, 0xc5, 0x26, 0xfa, 0x9b, 0xc7,
+ 0x8c, 0x36, 0x36, 0xce, 0xce, 0x78, 0xcf, 0x73, 0xd4, 0x77, 0xa2, 0xfd,
+ 0xd9, 0x7c, 0x79, 0x70, 0x9b, 0xc4, 0xfd, 0xe8, 0xe8, 0x62, 0xb5, 0xb9,
+ 0x11, 0x6c, 0xc6, 0x92, 0x25, 0xe0, 0x2d, 0x14, 0xb4, 0xe1, 0x78, 0x00,
+ 0x67, 0x23, 0x11, 0x00, 0x8e, 0xd3, 0xc8, 0x0a, 0x82, 0x99, 0xcb, 0x32,
+ 0xbe, 0xd7, 0xd1, 0xc7, 0x5f, 0x30, 0x92, 0x73, 0x15, 0x69, 0xb2, 0xf3,
+ 0xf0, 0x4e, 0x10, 0xe1, 0x81, 0x7d, 0x47, 0x4c, 0xec, 0xec, 0x3b, 0x37,
+ 0x24, 0x7c, 0x58, 0x56, 0x26, 0xbb, 0xf5, 0xfe, 0x83, 0x4a, 0xc9, 0x2b,
+ 0x8e, 0xab, 0xaa, 0x00, 0x33, 0xbf, 0xee, 0x9a, 0xdc, 0x18, 0xec, 0x40,
+ 0xe1, 0xd7, 0xd1, 0xeb, 0x31, 0x28, 0xd4, 0x59, 0xdd, 0xd9, 0x0c, 0x04,
+ 0x25, 0x67, 0x8b, 0xce, 0xaa, 0x03, 0xb0, 0x48, 0xe9, 0x26, 0xcb, 0x87,
+ 0xa4, 0xa8, 0xdc, 0xd8, 0x82, 0x63, 0xa4, 0xb4, 0xfa, 0xae, 0xd0, 0x73,
+ 0x50, 0xbe, 0x44, 0xbc, 0x2f, 0x74, 0x54, 0x47, 0xd6, 0x9b, 0x03, 0xea,
+ 0x2c, 0x96, 0x69, 0x25, 0x0e, 0x9d, 0x65, 0x6f, 0xc5, 0x9a, 0x1c, 0x49,
+ 0x37, 0x5a, 0xd8, 0x7b, 0x65, 0x46, 0xe4, 0x71, 0x20, 0x44, 0x14, 0xc9,
+ 0xcc, 0x8c, 0x30, 0x06, 0x78, 0x36, 0xd1, 0xe8, 0x6d, 0x64, 0xd5, 0xd8,
+ 0x39, 0xf0, 0x60, 0xf4, 0xe3, 0x8f, 0x11, 0xa2, 0x97, 0x78, 0xc2, 0x90,
+ 0x18, 0x25, 0x63, 0xc3, 0xb2, 0x13, 0xdb, 0xa9, 0x38, 0xc1, 0x9b, 0x37,
+ 0x8f, 0xdd, 0xa8, 0xc0, 0x04, 0xc9, 0x2b, 0xdc, 0x76, 0x40, 0x1e, 0x3e,
+ 0xc4, 0x6e, 0x5c, 0x0e, 0x8b, 0x78, 0x81, 0xc1, 0xb1, 0xc1, 0xd7, 0x1a,
+ 0x07, 0xe0, 0xed, 0x4b, 0xf3, 0x5b, 0xd4, 0xc3, 0x38, 0xbe, 0x5d, 0xae,
+ 0x38, 0xa0, 0xf6, 0x2b, 0xde, 0xe8, 0x28, 0x2e, 0x51, 0x6d, 0x1f, 0xd2,
+ 0xef, 0xa4, 0x10, 0x05, 0xd2, 0xbb, 0xe0, 0x88, 0x60, 0xad, 0x40, 0xd8,
+ 0xc4, 0xec, 0x21, 0x80, 0xc6, 0x07, 0xaa, 0xc4, 0x60, 0x86, 0xb2, 0xce,
+ 0x21, 0xb2, 0x2c, 0x90, 0x39, 0x8c, 0x8b, 0x03, 0x8a, 0xce, 0x84, 0x8d,
+ 0xa9, 0xe6, 0x40, 0x9e, 0x20, 0x90, 0x54, 0x0c, 0xd0, 0xa1, 0x17, 0x18,
+ 0x38, 0xe8, 0xbc, 0xab, 0x2d, 0x73, 0x12, 0x86, 0xc3, 0x2d, 0xf3, 0xcb,
+ 0x56, 0x2d, 0x7a, 0x6d, 0x50, 0x4f, 0x96, 0x31, 0xca, 0x3c, 0xef, 0x0e,
+ 0x3a, 0xb9, 0x2c, 0x18, 0xfa, 0x0e, 0x09, 0xe1, 0xb7, 0x78, 0xb9, 0xca,
+ 0x4c, 0x5f, 0xec, 0x53, 0x22, 0xc7, 0x2e, 0x32, 0x79, 0xd9, 0x81, 0xc7,
+ 0x0c, 0x7b, 0x1a, 0x7d, 0xc4, 0x8d, 0xdc, 0x1d, 0x8c, 0x35, 0x29, 0x36,
+ 0x16, 0x30, 0xa0, 0xa9, 0x50, 0xa0, 0xa0, 0x85, 0x0c, 0x26, 0x4c, 0x31,
+ 0x9b, 0x35, 0x2b, 0xb0, 0x4c, 0x95, 0xa5, 0x3c, 0xfb, 0xdc, 0x1e, 0xed,
+ 0x7f, 0xb4, 0x78, 0x81, 0xa1, 0xcc, 0xc1, 0xd7, 0xbd, 0xcf, 0x3d, 0x64,
+ 0xa4, 0xde, 0x1f, 0xbd, 0x88, 0xf0, 0xb7, 0xb0, 0x6c, 0x81, 0xe6, 0x08,
+ 0xec, 0xd4, 0x3d, 0xcf, 0x0f, 0x00, 0xa9, 0xe8, 0x0d, 0x1a, 0xfc, 0x7a,
+ 0xac, 0xd7, 0x7d, 0xcd, 0x1f, 0x27, 0x7a, 0x8d, 0x11, 0xdd, 0x65, 0xd1,
+ 0xc3, 0x1d, 0x0e, 0x6e, 0xf8, 0xea, 0xd5, 0xda, 0xde, 0xb2, 0xc6, 0x5b,
+ 0x30, 0xae, 0x39, 0xbf, 0x9c, 0xbf, 0xef, 0xad, 0xd7, 0x8b, 0x5d, 0x7b,
+ 0xd7, 0x1e, 0xdf, 0x67, 0x7f, 0x98, 0xe8, 0x3d, 0x22, 0xcf, 0x93, 0xce,
+ 0xee, 0x6d, 0xca, 0x83, 0x25, 0x08, 0x4f, 0x58, 0x33, 0x48, 0x0c, 0xd1,
+ 0x60, 0x2d, 0xbf, 0xdf, 0x2b, 0x28, 0xe6, 0x44, 0x59, 0x10, 0x31, 0x84,
+ 0x95, 0xa0, 0x69, 0xb9, 0xb1, 0x7b, 0x38, 0x35, 0xd1, 0x21, 0x3d, 0x25,
+ 0xea, 0x02, 0x44, 0x1c, 0x28, 0xd9, 0x14, 0x85, 0x3a, 0xcf, 0xe4, 0x63,
+ 0x33, 0xe4, 0xeb, 0xa5, 0x28, 0x6a, 0x44, 0x5e, 0x7f, 0x68, 0x52, 0x06,
+ 0xc1, 0xb1, 0x31, 0x71, 0xb1, 0xe5, 0xd0, 0x05, 0x90, 0x16, 0x5b, 0x08,
+ 0xa0, 0x6e, 0x81, 0xa2, 0x53, 0xf0, 0x6c, 0x40, 0xba, 0xa4, 0xd5, 0xac,
+ 0xa9, 0x70, 0x07, 0xd5, 0xee, 0x29, 0x58, 0xf9, 0x62, 0x8e, 0xfc, 0x6c,
+ 0xae, 0x81, 0xf6, 0xfa, 0xfa, 0x97, 0xfd, 0xab, 0x97, 0xde, 0x5b, 0x7b,
+ 0xa9, 0xcf, 0x9b, 0x25, 0xfc, 0xf8, 0xdc, 0x7e, 0xfa, 0x8f, 0xc6, 0xb0,
+ 0x35, 0xf1, 0x6d, 0x91, 0x24, 0x70, 0x61, 0x3c, 0xba, 0xda, 0x23, 0xe1,
+ 0x5a, 0x59, 0x89, 0xcf, 0xd6, 0xb4, 0x63, 0x1d, 0x54, 0x0e, 0x65, 0x08,
+ 0x21, 0xcb, 0x8d, 0x38, 0x5b, 0x16, 0x15, 0xda, 0xa8, 0xe0, 0x73, 0x82,
+ 0xa3, 0x12, 0xdf, 0x18, 0xe2, 0x18, 0xb4, 0xf9, 0x41, 0xb7, 0x34, 0x36,
+ 0x16, 0xb3, 0x41, 0x9a, 0xcc, 0x77, 0x4e, 0x02, 0x93, 0xa0, 0xb4, 0xd6,
+ 0x7d, 0xd7, 0x9d, 0xf5, 0x73, 0xa2, 0x08, 0x24, 0xcc, 0x58, 0x7b, 0xb3,
+ 0x2a, 0x96, 0xc6, 0xf2, 0x02, 0xed, 0x10, 0x49, 0x34, 0xd9, 0xec, 0x40,
+ 0x14, 0x04, 0x8a, 0xf1, 0x63, 0xe1, 0x7c, 0x73, 0xa0, 0x16, 0x00, 0xa6,
+ 0x0f, 0xe2, 0x2c, 0xea, 0x6b, 0xa7, 0xf0, 0x02, 0x92, 0x20, 0x05, 0xd0,
+ 0x06, 0x9d, 0x90, 0x46, 0x64, 0xde, 0xb2, 0x92, 0x18, 0x39, 0x69, 0x59,
+ 0xd5, 0x56, 0x94, 0xa2, 0x21, 0x74, 0xc6, 0x4a, 0x77, 0x37, 0x18, 0x63,
+ 0x2f, 0x08, 0x49, 0x69, 0x46, 0x6d, 0x67, 0x24, 0x20, 0x9e, 0x6b, 0xb0,
+ 0x56, 0x6b, 0x2b, 0x02, 0xa2, 0x7a, 0xf7, 0xc7, 0xbd, 0x88, 0xc3, 0xf9,
+ 0x04, 0x10, 0x53, 0x6b, 0x65, 0x1d, 0x8c, 0x44, 0x37, 0xab, 0xbb, 0xb8,
+ 0x04, 0x3a, 0xe0, 0xc8, 0x3c, 0xba, 0x83, 0x44, 0xab, 0x60, 0xa1, 0xa0,
+ 0xc5, 0x00, 0xd6, 0x0e, 0xac, 0x09, 0xe8, 0x1e, 0x1d, 0x98, 0xd7, 0x29,
+ 0xc9, 0x16, 0x18, 0xd6, 0x2c, 0x57, 0xc0, 0xa2, 0x6e, 0x56, 0x8b, 0xb4,
+ 0x79, 0xd1, 0xe4, 0x49, 0x5f, 0x81, 0x96, 0xfc, 0xf5, 0xea, 0xd5, 0x60,
+ 0x0c, 0x88, 0x29, 0x4a, 0xe6, 0x0b, 0x44, 0x38, 0xd9, 0xfb, 0x9d, 0x7b,
+ 0x35, 0xdf, 0x4b, 0x50, 0xd2, 0xdd, 0x84, 0x55, 0xbb, 0x06, 0xe5, 0xa3,
+ 0x5a, 0x8f, 0x0f, 0xf0, 0x35, 0x0d, 0xe0, 0x91, 0xc6, 0xc8, 0xc4, 0xbb,
+ 0x71, 0x7f, 0x91, 0x5d, 0xd0, 0x9b, 0xc8, 0x30, 0x72, 0xba, 0x81, 0x16,
+ 0xb2, 0x8c, 0x63, 0x30, 0xa7, 0x8a, 0xc6, 0xa2, 0xc5, 0x79, 0xc6, 0x94,
+ 0x30, 0x6a, 0xef, 0x2b, 0x5b, 0x11, 0xfe, 0xbe, 0xc0, 0x69, 0x4b, 0xe7,
+ 0x5d, 0x58, 0x51, 0xbf, 0x30, 0x98, 0xc4, 0x0a, 0x60, 0x96, 0xc8, 0x3d,
+ 0x19, 0x98, 0xe7, 0x1e, 0x7f, 0x16, 0x48, 0xe2, 0xfd, 0xbf, 0x37, 0xcc,
+ 0xf7, 0x91, 0x20, 0x85, 0xdc, 0xc8, 0xaa, 0xe5, 0x1e, 0x2a, 0x8a, 0x49,
+ 0x81, 0xeb, 0x80, 0x5a, 0x62, 0xf7, 0x03, 0x6c, 0xd5, 0x96, 0x20, 0x05,
+ 0x11, 0x3c, 0xf1, 0x13, 0xd9, 0x77, 0xde, 0x25, 0x71, 0x96, 0xc3, 0x1e,
+ 0x13, 0xf5, 0x77, 0x84, 0xf6, 0x6b, 0x90, 0x0c, 0xb9, 0xd5, 0xb3, 0xd6,
+ 0x68, 0x11, 0xc6, 0xa5, 0x38, 0x18, 0x31, 0xa9, 0xe5, 0xe8, 0x7b, 0x17,
+ 0xb0, 0x2c, 0x49, 0xcb, 0x5b, 0xfd, 0xa0, 0xaa, 0xc2, 0x2b, 0x4c, 0x41,
+ 0x92, 0xf7, 0xc2, 0xc1, 0x92, 0xbf, 0x35, 0xbc, 0x81, 0x62, 0xd3, 0xde,
+ 0x15, 0xe5, 0x8d, 0x77, 0xf7, 0x83, 0xc0, 0x53, 0xbd, 0x68, 0x2a, 0xb0,
+ 0x23, 0xc1, 0xe9, 0x29, 0x40, 0xe2, 0x50, 0xe4, 0x12, 0x6c, 0x4e, 0x34,
+ 0x86, 0xd8, 0x39, 0xf3, 0x83, 0x92, 0x0e, 0x42, 0x2f, 0x1b, 0x2c, 0xfc,
+ 0x3b, 0x1b, 0x69, 0x00, 0x33, 0x68, 0x51, 0x80, 0x5b, 0x1b, 0xc4, 0x20,
+ 0x14, 0x86, 0xb2, 0x6b, 0x73, 0x9d, 0x1a, 0x96, 0x05, 0x60, 0x47, 0xa4,
+ 0x88, 0x7d, 0xeb, 0xc1, 0x90, 0x34, 0x16, 0x00, 0x70, 0xd1, 0x68, 0x1a,
+ 0x81, 0x54, 0x49, 0x52, 0x89, 0x3e, 0xe1, 0xaa, 0x96, 0x0d, 0x6c, 0x1b,
+ 0x9a, 0x86, 0xa4, 0xbc, 0x53, 0x23, 0x31, 0xd5, 0xd8, 0x4e, 0xcd, 0x46,
+ 0x04, 0x02, 0x83, 0xd1, 0x8a, 0x9f, 0x72, 0x59, 0x4a, 0xcc, 0x8e, 0x38,
+ 0x61, 0x55, 0x34, 0x85, 0x78, 0x22, 0x34, 0x20, 0x3b, 0x7c, 0x14, 0x8b,
+ 0xab, 0x66, 0x26, 0x27, 0x9f, 0x8a, 0xd4, 0x81, 0xb2, 0xf2, 0x82, 0xf6,
+ 0xdb, 0x8d, 0xc5, 0x1b, 0x63, 0x61, 0x01, 0xd7, 0xa6, 0xcd, 0x8e, 0xe8,
+ 0x11, 0xd6, 0x77, 0xc6, 0xe4, 0x9b, 0x8e, 0x99, 0x57, 0xcb, 0x68, 0x4c,
+ 0xc1, 0xa6, 0x5a, 0xa1, 0x44, 0x91, 0x9c, 0x59, 0x8d, 0xa4, 0x27, 0x7e,
+ 0x8a, 0xc3, 0x0f, 0x9b, 0x55, 0x15, 0x39, 0xd6, 0xd9, 0xbd, 0x5b, 0x0d,
+ 0xdb, 0x1e, 0xd5, 0x22, 0x2e, 0x2d, 0x02, 0x49, 0xf9, 0xa1, 0xff, 0x9f,
+ 0x76, 0xdd, 0x40, 0x86, 0x95, 0xc2, 0x83, 0x2e, 0x80, 0xd9, 0xe4, 0xd3,
+ 0xb2, 0xb8, 0x01, 0x20, 0xaf, 0x31, 0x31, 0xc4, 0x94, 0xf8, 0x73, 0x8a,
+ 0x22, 0x47, 0xec, 0x1c, 0x94, 0xe8, 0xb0, 0x63, 0x29, 0xa5, 0x0e, 0x30,
+ 0x39, 0x58, 0x34, 0x19, 0x7a, 0xde, 0x37, 0x26, 0xd8, 0x72, 0x8f, 0x79,
+ 0x17, 0x0a, 0x03, 0x4e, 0x4a, 0xd1, 0x70, 0xd5, 0x2c, 0xb8, 0x3b, 0x1e,
+ 0x52, 0xe5, 0x64, 0x30, 0x45, 0x8e, 0xe0, 0xfe, 0x84, 0x55, 0xac, 0x8f,
+ 0x4e, 0x03, 0x2e, 0x4c, 0x36, 0x27, 0xfb, 0xab, 0x06, 0xe5, 0x4a, 0x1a,
+ 0x53, 0x2c, 0x2d, 0x52, 0x5b, 0xb8, 0x66, 0xf3, 0x67, 0x2b, 0x06, 0xfd,
+ 0x87, 0xe0, 0xa2, 0x73, 0x60, 0xd0, 0x91, 0x23, 0x9b, 0x11, 0x45, 0x01,
+ 0xe7, 0x24, 0xec, 0x43, 0xe2, 0xd0, 0x30, 0x8e, 0x03, 0xc2, 0x23, 0x66,
+ 0x83, 0x3d, 0x12, 0xa8, 0x00, 0xc3, 0x01, 0x00, 0xb3, 0x18, 0x4d, 0xf7,
+ 0x2c, 0xad, 0x6b, 0xb0, 0x82, 0x51, 0x5b, 0x36, 0xe5, 0x94, 0x72, 0x3a,
+ 0x62, 0x2d, 0x30, 0x6d, 0xc1, 0x98, 0x96, 0x00, 0x0b, 0x8c, 0xcb, 0x24,
+ 0xd6, 0x6b, 0x4d, 0x59, 0x66, 0x87, 0x81, 0x61, 0x01, 0x17, 0x7d, 0x99,
+ 0x55, 0x16, 0xcf, 0x10, 0xd8, 0xd9, 0x8c, 0x22, 0x5d, 0xd7, 0x84, 0xec,
+ 0x3a, 0xb0, 0x4f, 0x04, 0x7f, 0x14, 0x1c, 0x9b, 0x91, 0x9c, 0x46, 0xe9,
+ 0x11, 0xaf, 0x88, 0xa9, 0xc0, 0xa2, 0x9c, 0xde, 0xab, 0x65, 0x41, 0xfe,
+ 0x35, 0xb9, 0x5a, 0xcd, 0x4a, 0x53, 0x06, 0x06, 0xa3, 0x06, 0xc4, 0x7a,
+ 0xac, 0x2a, 0xc9, 0xc9, 0x17, 0x50, 0xe0, 0x96, 0x30, 0x26, 0xd0, 0xa6,
+ 0x66, 0x49, 0xce, 0x54, 0x06, 0x79, 0x11, 0xf1, 0x42, 0x41, 0xac, 0xfb,
+ 0xe5, 0x12, 0xb7, 0x75, 0xa6, 0x6d, 0x28, 0x1a, 0xa1, 0x62, 0x68, 0x2a,
+ 0x01, 0x67, 0x0a, 0xdc, 0xc5, 0x70, 0xd8, 0xa9, 0x09, 0x1e, 0x12, 0xe9,
+ 0x0a, 0x09, 0xca, 0xcd, 0x40, 0x12, 0xdd, 0xef, 0xbf, 0x17, 0x2d, 0x2c,
+ 0x13, 0x61, 0xa0, 0xad, 0xf2, 0x95, 0x25, 0x8c, 0xdd, 0x14, 0xb6, 0xf0,
+ 0x2a, 0x30, 0x61, 0x60, 0xfb, 0x60, 0x62, 0xc3, 0xc4, 0x08, 0x46, 0x8d,
+ 0x8d, 0x28, 0x69, 0x11, 0x40, 0xf7, 0xf2, 0x04, 0xa6, 0x51, 0xae, 0x9b,
+ 0x18, 0xe4, 0x67, 0x6d, 0xd8, 0x96, 0x76, 0xa4, 0x4b, 0xb8, 0x68, 0x96,
+ 0x53, 0x0c, 0x4f, 0xcc, 0x03, 0xc6, 0x66, 0x21, 0x6b, 0xcd, 0xa7, 0xd2,
+ 0x78, 0xcd, 0x01, 0x9e, 0x05, 0x4e, 0xc2, 0x24, 0x1f, 0xe8, 0xa4, 0x4e,
+ 0x60, 0x51, 0xd9, 0xc0, 0x62, 0xdf, 0xdb, 0x41, 0xec, 0x05, 0xa0, 0x11,
+ 0xf5, 0x08, 0x34, 0xed, 0xe4, 0x8d, 0xe5, 0x11, 0xe2, 0x5a, 0xa4, 0xb2,
+ 0x96, 0xe5, 0x6c, 0x15, 0x8d, 0x7f, 0xc6, 0xad, 0xdc, 0x8a, 0x30, 0xb4,
+ 0xbd, 0x98, 0x1d, 0x65, 0x76, 0x83, 0x00, 0x62, 0x5a, 0xba, 0x66, 0xec,
+ 0xb9, 0x4d, 0xe3, 0xf8, 0xc2, 0x88, 0xe3, 0x6f, 0xa4, 0x3f, 0xa2, 0xb7,
+ 0x91, 0x95, 0xa2, 0xd6, 0x2b, 0x8f, 0x84, 0xd8, 0x6d, 0x7c, 0xcf, 0x92,
+ 0x85, 0xba, 0xb3, 0x5c, 0x68, 0xf7, 0xc2, 0x3f, 0x35, 0x4b, 0x4b, 0x36,
+ 0x11, 0x71, 0xe4, 0xd6, 0x94, 0x44, 0xa2, 0x23, 0xd2, 0xc1, 0x6f, 0xc1,
+ 0x8a, 0xc1, 0x1b, 0xd4, 0x6d, 0x0a, 0x0b, 0xc3, 0x80, 0x48, 0x1c, 0x46,
+ 0x43, 0x7d, 0xe8, 0x7e, 0x0b, 0x81, 0xf4, 0xad, 0x7d, 0x0a, 0x78, 0xa8,
+ 0x4d, 0x9c, 0xb0, 0x05, 0x9e, 0xa8, 0x16, 0xe0, 0xf4, 0x08, 0x8b, 0x77,
+ 0xfa, 0xad, 0x92, 0x98, 0x33, 0x17, 0x06, 0x88, 0x95, 0x2f, 0xb6, 0x1e,
+ 0xba, 0x0f, 0xc5, 0x8a, 0x9e, 0x98, 0x82, 0x6d, 0x0e, 0x26, 0x30, 0xbb,
+ 0x0e, 0x48, 0xa6, 0x95, 0x7e, 0x32, 0x45, 0xf2, 0xa7, 0x88, 0x53, 0x59,
+ 0x14, 0xcb, 0x27, 0x4e, 0xff, 0xf3, 0x5c, 0xe8, 0xd0, 0xfe, 0xb6, 0x82,
+ 0x67, 0x01, 0xfe, 0x93, 0x5c, 0x22, 0xf8, 0x93, 0x91, 0x5d, 0xb4, 0x12,
+ 0x9d, 0xdd, 0x9e, 0x40, 0xdf, 0xa1, 0x90, 0x98, 0xb3, 0xdc, 0x22, 0xb8,
+ 0xfe, 0xde, 0x60, 0x7c, 0xb7, 0x6a, 0x5c, 0xca, 0x05, 0x67, 0x41, 0x75,
+ 0xc0, 0xb9, 0x47, 0x17, 0x39, 0x2f, 0x81, 0xea, 0x24, 0xf8, 0xc4, 0xc6,
+ 0x41, 0x18, 0x70, 0x3f, 0xb1, 0xc2, 0x25, 0x73, 0xc1, 0x08, 0x5e, 0xaf,
+ 0x8a, 0xb2, 0x42, 0xaf, 0x5f, 0xad, 0x07, 0x93, 0x91, 0x75, 0x61, 0x52,
+ 0xf8, 0xfa, 0xf6, 0xe9, 0xf8, 0x39, 0x7f, 0xf7, 0xe5, 0x29, 0x01, 0x0a,
+ 0x31, 0x8c, 0xe7, 0x03, 0x0e, 0x38, 0x46, 0x44, 0x9b, 0xb7, 0x48, 0x23,
+ 0x09, 0x3d, 0xed, 0xeb, 0x53, 0x89, 0x05, 0xbd, 0x91, 0xa0, 0xdc, 0xdf,
+ 0x88, 0x27, 0xdb, 0x01, 0xa9, 0x73, 0x0e, 0x48, 0xbd, 0xe7, 0x80, 0xd4,
+ 0x46, 0x3c, 0xaa, 0xe5, 0xd2, 0x74, 0xf2, 0x2a, 0x84, 0x1e, 0x32, 0xcc,
+ 0xbd, 0xdf, 0x08, 0x8b, 0xfe, 0xe6, 0xfc, 0xbd, 0x18, 0x4a, 0x5b, 0x13,
+ 0x34, 0xb8, 0x17, 0xdf, 0x89, 0xdd, 0x2f, 0xee, 0x4b, 0x98, 0x16, 0xcc,
+ 0x95, 0x97, 0x03, 0x1c, 0x13, 0x0c, 0x43, 0x24, 0x28, 0x0b, 0x30, 0x94,
+ 0xd2, 0x36, 0x6c, 0xdf, 0x46, 0x7d, 0x96, 0xce, 0x48, 0xa0, 0xf7, 0xad,
+ 0x47, 0x94, 0x35, 0xd9, 0x2a, 0x84, 0xc5, 0xb0, 0xd2, 0x47, 0x69, 0xd8,
+ 0xf1, 0xd5, 0x5d, 0x38, 0x92, 0x1f, 0x76, 0x51, 0xfc, 0x19, 0x10, 0x7b,
+ 0x5a, 0x91, 0xc0, 0x3c, 0x93, 0x70, 0x22, 0x41, 0x8a, 0x8f, 0x24, 0xe6,
+ 0xda, 0xe4, 0xa6, 0x24, 0xf1, 0x0b, 0x98, 0x88, 0x73, 0x9f, 0x27, 0xa1,
+ 0xfc, 0x33, 0xa9, 0x3f, 0xdc, 0x2f, 0xab, 0x7d, 0x69, 0x09, 0x18, 0xd3,
+ 0x56, 0x39, 0x42, 0xda, 0x8a, 0x6c, 0x9f, 0xd4, 0x68, 0x17, 0xa2, 0x67,
+ 0x68, 0x8d, 0x85, 0x29, 0x48, 0x89, 0x65, 0x8a, 0x56, 0xf5, 0x34, 0xcc,
+ 0x36, 0x55, 0x31, 0x65, 0xc7, 0x91, 0x7b, 0x54, 0x1c, 0xa4, 0x5c, 0x49,
+ 0xa5, 0xb9, 0xd0, 0xb8, 0xf8, 0x4b, 0x40, 0xa7, 0x20, 0xe3, 0x6c, 0x84,
+ 0x19, 0x0c, 0x0b, 0x1b, 0xdb, 0xc2, 0x50, 0xaf, 0xb5, 0x89, 0xec, 0x68,
+ 0x1d, 0xa9, 0x84, 0x93, 0x2d, 0xb0, 0xd6, 0x0a, 0xef, 0x47, 0xd7, 0xbc,
+ 0x94, 0x7c, 0x4a, 0xee, 0xb2, 0xec, 0x3e, 0xc9, 0x52, 0x01, 0xa1, 0x19,
+ 0xb7, 0x37, 0x55, 0x86, 0x70, 0x83, 0x05, 0x11, 0x26, 0xea, 0x23, 0x0a,
+ 0x89, 0x05, 0xb1, 0x18, 0x7c, 0x9e, 0x9e, 0x40, 0x86, 0xeb, 0xe3, 0xc2,
+ 0x50, 0xb8, 0x34, 0xa5, 0xd8, 0x2c, 0x9d, 0x67, 0x15, 0xed, 0x70, 0x88,
+ 0x13, 0xb7, 0xcf, 0x16, 0x50, 0xce, 0x26, 0x80, 0x2a, 0xa2, 0x24, 0x5d,
+ 0x90, 0x02, 0xea, 0x06, 0x88, 0x78, 0x35, 0x68, 0xdf, 0x88, 0xa6, 0xc5,
+ 0xfa, 0x05, 0xb6, 0x8a, 0xbd, 0x2d, 0x6e, 0x69, 0x1e, 0xcd, 0x54, 0x17,
+ 0x30, 0x93, 0x41, 0x05, 0xbd, 0x4c, 0x93, 0x94, 0x76, 0x09, 0x03, 0x67,
+ 0x56, 0xa6, 0xda, 0x48, 0x21, 0x90, 0x50, 0x62, 0x74, 0x1c, 0xc4, 0xf3,
+ 0x1d, 0xf5, 0x09, 0x79, 0xfa, 0xe4, 0x5f, 0x85, 0xb5, 0x42, 0x31, 0x99,
+ 0xd2, 0xef, 0x6d, 0x86, 0x07, 0x7d, 0x74, 0xf2, 0xba, 0x28, 0xea, 0x71,
+ 0x8f, 0x4a, 0xb8, 0x42, 0x0b, 0x1c, 0x70, 0x51, 0x90, 0x8d, 0xd9, 0x94,
+ 0x0c, 0x8a, 0x4d, 0x95, 0x72, 0xd0, 0x06, 0x69, 0x12, 0x83, 0xa9, 0x9c,
+ 0x3b, 0x6f, 0x9b, 0x16, 0x0e, 0x4b, 0x8c, 0x4d, 0xc2, 0xed, 0xb4, 0x25,
+ 0xe3, 0x1c, 0x6f, 0xe3, 0xf0, 0xca, 0xbb, 0x14, 0x12, 0xdc, 0x11, 0x41,
+ 0x5b, 0x19, 0x3f, 0xbd, 0x4b, 0xf7, 0x21, 0xc2, 0x50, 0xee, 0xa8, 0x70,
+ 0x87, 0x00, 0xc5, 0x19, 0x2b, 0x56, 0x50, 0x51, 0xad, 0x1c, 0x86, 0x47,
+ 0xa6, 0xe4, 0x39, 0xac, 0x92, 0x8e, 0xc1, 0x84, 0x23, 0x2e, 0xa2, 0x8a,
+ 0x0d, 0xca, 0x0c, 0x91, 0x04, 0x0f, 0x6b, 0x7f, 0x28, 0x63, 0x46, 0xcc,
+ 0x81, 0xd2, 0x9c, 0xc2, 0xbd, 0x21, 0x6b, 0x07, 0x11, 0x62, 0xc1, 0x30,
+ 0xf0, 0x48, 0x9e, 0x64, 0xc6, 0x73, 0x76, 0xc5, 0x1a, 0xfd, 0x83, 0x38,
+ 0x71, 0x67, 0x84, 0xc5, 0x3a, 0xce, 0x6e, 0x82, 0x24, 0x8c, 0xcd, 0x0a,
+ 0x5b, 0x82, 0x72, 0xc6, 0x4c, 0x8a, 0x5a, 0x05, 0x19, 0x46, 0xae, 0xba,
+ 0x62, 0x25, 0x66, 0x88, 0xad, 0x91, 0xfd, 0x98, 0x8d, 0x32, 0x9f, 0xf2,
+ 0xb2, 0xd4, 0xa5, 0xa2, 0x12, 0x59, 0x04, 0xfe, 0xe2, 0x16, 0x56, 0x3e,
+ 0xc2, 0xb2, 0x11, 0x0d, 0xa2, 0x30, 0x31, 0xed, 0xaf, 0x38, 0xaf, 0x6e,
+ 0x30, 0xb0, 0xf8, 0xa2, 0x8b, 0x8b, 0xf5, 0xab, 0x57, 0xeb, 0xde, 0xe7,
+ 0xde, 0xa8, 0xbf, 0x1e, 0xf7, 0xd7, 0x93, 0x3e, 0x16, 0x5b, 0xf6, 0xd7,
+ 0x17, 0xcb, 0xc1, 0x18, 0x83, 0x8f, 0x18, 0x7e, 0x83, 0x8d, 0x92, 0x30,
+ 0x68, 0x65, 0xc2, 0x87, 0x09, 0x05, 0xdd, 0x64, 0x00, 0x48, 0xcb, 0xd4,
+ 0x34, 0x4a, 0xd6, 0xbf, 0x25, 0x04, 0xcd, 0xf9, 0x69, 0x17, 0xc0, 0xb3,
+ 0xf1, 0x4c, 0x7c, 0x02, 0x17, 0x63, 0xd9, 0x29, 0x2a, 0x77, 0xdf, 0xec,
+ 0x59, 0x1d, 0x47, 0x1f, 0xeb, 0xe2, 0xda, 0x88, 0x1d, 0xd0, 0x25, 0xbe,
+ 0x86, 0x12, 0x1d, 0xb0, 0x5f, 0x0a, 0x7c, 0x79, 0x53, 0xa2, 0xc5, 0x07,
+ 0xcb, 0x76, 0x51, 0xf5, 0x21, 0x7c, 0x7d, 0x8e, 0x6e, 0x3c, 0xa6, 0x61,
+ 0xef, 0xfb, 0x54, 0xf6, 0xb6, 0x03, 0x2b, 0xd7, 0x6b, 0x5c, 0xfb, 0x5a,
+ 0x3f, 0xb8, 0x7a, 0xb9, 0xb3, 0x94, 0xa0, 0xac, 0xbe, 0xb8, 0xe0, 0x9f,
+ 0x00, 0xaa, 0x1d, 0x80, 0x4a, 0xbb, 0x90, 0x29, 0xe8, 0x60, 0xf7, 0x75,
+ 0x02, 0x5f, 0xe1, 0x86, 0x75, 0xd9, 0xbe, 0x5e, 0x06, 0xd7, 0x55, 0x3b,
+ 0xfa, 0x0a, 0x70, 0xb8, 0x5b, 0x01, 0x24, 0xf7, 0x6d, 0x12, 0x69, 0xae,
+ 0xd1, 0x0b, 0x23, 0x10, 0x4e, 0xbc, 0x20, 0xa7, 0xfb, 0x10, 0x44, 0x53,
+ 0x35, 0x54, 0x0c, 0x45, 0xa1, 0x08, 0xc7, 0x4b, 0x41, 0xcc, 0x13, 0xc8,
+ 0x85, 0x2c, 0xd1, 0x56, 0xe1, 0x4d, 0x95, 0x92, 0x70, 0x5d, 0xc5, 0x29,
+ 0x29, 0x50, 0x77, 0x7b, 0x1f, 0xf6, 0x19, 0x78, 0x58, 0xf4, 0x36, 0x18,
+ 0xf8, 0x5b, 0x72, 0xb2, 0xa3, 0x2b, 0x65, 0x83, 0xd2, 0xe4, 0x37, 0xa4,
+ 0xb7, 0xc4, 0x22, 0x20, 0xf0, 0x81, 0x25, 0x93, 0x3e, 0x71, 0x1b, 0x6d,
+ 0x1d, 0x2f, 0x29, 0x33, 0x73, 0x10, 0x3f, 0x59, 0x51, 0x94, 0xff, 0x47,
+ 0xbf, 0xf9, 0xf2, 0x62, 0xa9, 0x4b, 0x92, 0x26, 0xf4, 0x0b, 0x9b, 0x90,
+ 0xb4, 0xe5, 0xb2, 0x7e, 0xc6, 0xcf, 0xb2, 0x48, 0x28, 0x3a, 0x7d, 0xb1,
+ 0xc4, 0x84, 0x12, 0xa1, 0xe2, 0x67, 0xca, 0x60, 0x30, 0xa1, 0x58, 0x1b,
+ 0x10, 0xf3, 0x05, 0x64, 0xf9, 0x12, 0xb5, 0xe0, 0xcd, 0xa9, 0xf7, 0xf1,
+ 0xa3, 0x09, 0xd6, 0x32, 0xea, 0x44, 0x68, 0x49, 0xbe, 0x3d, 0x05, 0xb3,
+ 0xb5, 0x63, 0x3d, 0x74, 0x2a, 0xe4, 0x14, 0x15, 0x98, 0xcd, 0xb1, 0x16,
+ 0xcc, 0x73, 0x9f, 0x64, 0x03, 0x3a, 0x0f, 0x05, 0xb9, 0x55, 0xb2, 0x34,
+ 0xa2, 0x24, 0x62, 0x39, 0x71, 0xea, 0x82, 0xae, 0xe4, 0x86, 0x93, 0x86,
+ 0x07, 0x96, 0xd3, 0xbf, 0x60, 0x61, 0xf3, 0x15, 0x5a, 0xe9, 0x30, 0x91,
+ 0xcf, 0xae, 0x05, 0xbc, 0xd5, 0x66, 0x2b, 0x20, 0x64, 0xad, 0xba, 0xd9,
+ 0x8e, 0xe8, 0xc2, 0x47, 0x63, 0x6f, 0xcc, 0xaa, 0x46, 0x30, 0xc8, 0x39,
+ 0xa5, 0x50, 0x2d, 0xd8, 0x1c, 0x98, 0x19, 0x4d, 0xeb, 0x30, 0xfd, 0x81,
+ 0x0e, 0x0f, 0xe8, 0x9f, 0x40, 0x60, 0x91, 0x85, 0x5d, 0xa1, 0x76, 0xc5,
+ 0x3b, 0x0d, 0xa5, 0x33, 0xf0, 0x7e, 0x22, 0x2c, 0x94, 0x2f, 0x17, 0x91,
+ 0x33, 0x49, 0x40, 0x5c, 0xa5, 0x62, 0x09, 0x3a, 0x53, 0x5c, 0xb5, 0x42,
+ 0xc1, 0x68, 0x02, 0x96, 0x28, 0x37, 0x2d, 0xee, 0x7e, 0x6d, 0x24, 0x19,
+ 0x1c, 0x8a, 0x61, 0xb6, 0xa2, 0xd0, 0xc1, 0x9a, 0x9a, 0xb4, 0x56, 0x94,
+ 0x63, 0x95, 0x00, 0x3e, 0xd5, 0x1a, 0xbe, 0x46, 0xc1, 0xcc, 0x89, 0x32,
+ 0xc4, 0x55, 0x7a, 0x25, 0xeb, 0x74, 0x06, 0x86, 0x5c, 0x2b, 0x77, 0x3f,
+ 0xc2, 0xc5, 0xbd, 0xc8, 0xe5, 0x13, 0x15, 0x8a, 0xd7, 0x15, 0xfb, 0x37,
+ 0x24, 0x9b, 0x88, 0x56, 0x3e, 0xd2, 0x08, 0x48, 0x8c, 0xe8, 0xab, 0xec,
+ 0x2e, 0xe3, 0xf2, 0x46, 0x62, 0x64, 0x6d, 0x47, 0x7a, 0x8f, 0x35, 0x5b,
+ 0x74, 0x81, 0xf7, 0x2b, 0x8a, 0x03, 0x56, 0x05, 0xc9, 0x4c, 0xb4, 0x95,
+ 0xe1, 0x59, 0x0a, 0x9f, 0x2a, 0x66, 0x39, 0x9f, 0x36, 0xc8, 0x8b, 0x40,
+ 0x3d, 0x88, 0x69, 0x89, 0x0b, 0xe0, 0x71, 0x88, 0xb5, 0x6c, 0xf2, 0x32,
+ 0x80, 0x3d, 0x8d, 0x54, 0xab, 0xc4, 0x52, 0x7c, 0x94, 0x6d, 0x31, 0x71,
+ 0x5e, 0x0a, 0xf9, 0x69, 0x7e, 0xd6, 0x30, 0xe9, 0x84, 0xf3, 0x0c, 0x7d,
+ 0x0d, 0x02, 0x5b, 0x5a, 0x2d, 0x18, 0x03, 0x00, 0xbd, 0x33, 0xeb, 0xf3,
+ 0x84, 0xa0, 0xcd, 0xb0, 0x88, 0x2d, 0x9d, 0xbb, 0x04, 0x25, 0x52, 0xd0,
+ 0x85, 0xc5, 0x1b, 0x06, 0x66, 0x6b, 0x4c, 0x99, 0x87, 0xc6, 0x08, 0xc6,
+ 0x32, 0x88, 0x68, 0x9c, 0x19, 0x89, 0x2e, 0x62, 0x42, 0xa9, 0x6d, 0xb1,
+ 0xcf, 0xa2, 0x54, 0x9c, 0x43, 0x56, 0xa8, 0xd5, 0xaa, 0xc8, 0x13, 0xb6,
+ 0x7e, 0x25, 0x33, 0xf0, 0x26, 0xea, 0x4b, 0x98, 0x85, 0x59, 0xff, 0xd5,
+ 0x5a, 0xf3, 0xa4, 0x4e, 0xea, 0xc3, 0x4f, 0x38, 0x08, 0x18, 0xd4, 0x76,
+ 0x51, 0x4c, 0xa3, 0x08, 0xca, 0x1d, 0x3b, 0x6d, 0x04, 0x11, 0xd7, 0x9b,
+ 0x87, 0x78, 0xe7, 0x71, 0x91, 0xa8, 0xe3, 0xca, 0xc5, 0xf8, 0x50, 0x43,
+ 0x60, 0x18, 0xca, 0x24, 0x3e, 0xe2, 0xdf, 0x4a, 0x00, 0x02, 0xa4, 0x88,
+ 0xe7, 0x58, 0x38, 0xa6, 0xb5, 0x43, 0x4e, 0xb5, 0x24, 0xe2, 0x56, 0x8a,
+ 0x05, 0x65, 0x4b, 0xc4, 0x90, 0x77, 0x31, 0xf5, 0x44, 0x31, 0xa1, 0xbb,
+ 0x42, 0xec, 0x0f, 0xe1, 0x14, 0x11, 0x15, 0x7d, 0xa6, 0x81, 0xb4, 0xc4,
+ 0xda, 0x7a, 0x71, 0xd0, 0x3e, 0x45, 0x7d, 0x17, 0xc7, 0x9c, 0x2d, 0x28,
+ 0x25, 0x2c, 0x57, 0x4e, 0x23, 0x5f, 0xd1, 0x15, 0x3e, 0xa3, 0xa2, 0x4f,
+ 0x56, 0x82, 0x20, 0x35, 0x57, 0x5c, 0xff, 0xa9, 0x95, 0x8f, 0x83, 0xb0,
+ 0x4c, 0x21, 0x02, 0xb0, 0xee, 0x83, 0xe1, 0x62, 0x1e, 0x12, 0x6e, 0x64,
+ 0xd8, 0x51, 0xbc, 0x1d, 0x76, 0xe1, 0x13, 0xe1, 0x8b, 0x93, 0xae, 0x7e,
+ 0xf7, 0xc7, 0x91, 0xad, 0x84, 0x4a, 0x39, 0x12, 0xba, 0xcd, 0x9a, 0xed,
+ 0xc6, 0xfe, 0x69, 0x14, 0xa0, 0x6d, 0x12, 0x29, 0x75, 0xc5, 0x21, 0x55,
+ 0xb1, 0x72, 0x24, 0x29, 0x0e, 0x7e, 0x6b, 0x18, 0x9c, 0x87, 0xd5, 0x23,
+ 0x89, 0x59, 0xdc, 0x71, 0x99, 0x95, 0x04, 0xff, 0x52, 0x72, 0x41, 0x53,
+ 0xe6, 0xbf, 0x51, 0x64, 0x91, 0x04, 0xc6, 0x21, 0x15, 0xc5, 0x01, 0x67,
+ 0x52, 0xe0, 0x0f, 0x16, 0x80, 0xa4, 0x72, 0xa5, 0xbf, 0x1a, 0xac, 0xc7,
+ 0xb4, 0xf1, 0xbc, 0x64, 0xce, 0x94, 0x44, 0x9c, 0xe2, 0xb6, 0x41, 0x67,
+ 0x5b, 0x53, 0xe8, 0x42, 0x80, 0x1e, 0xb7, 0xe2, 0xc5, 0xc5, 0xad, 0x64,
+ 0x11, 0x90, 0x00, 0x95, 0x14, 0x30, 0x60, 0x64, 0xe3, 0xa3, 0xa2, 0x41,
+ 0x9b, 0x85, 0x51, 0xad, 0x24, 0xb0, 0xe4, 0x0b, 0xd9, 0x68, 0xbb, 0x70,
+ 0x5d, 0xbc, 0x8b, 0x54, 0xd2, 0x16, 0x54, 0xea, 0xda, 0xdd, 0x45, 0x7f,
+ 0x15, 0x3c, 0x4d, 0xd6, 0x20, 0x58, 0xdd, 0xb3, 0x5c, 0x9a, 0x3c, 0x61,
+ 0x08, 0xa9, 0x84, 0x52, 0xf2, 0x69, 0x0d, 0x29, 0x84, 0xfa, 0x01, 0x0a,
+ 0x71, 0x9a, 0x64, 0xd3, 0x1f, 0xa3, 0x42, 0x42, 0x16, 0xae, 0x19, 0x90,
+ 0x07, 0xd6, 0x2d, 0xb2, 0x2c, 0xee, 0xe6, 0x0f, 0x7d, 0x0a, 0x96, 0x79,
+ 0xc7, 0x05, 0xb4, 0x03, 0x7d, 0x24, 0xb4, 0x4e, 0xb1, 0x68, 0xcc, 0x8a,
+ 0xb6, 0xc2, 0x9f, 0xe2, 0x14, 0x8a, 0x07, 0xc9, 0xe9, 0x8f, 0x4e, 0x10,
+ 0xb8, 0x5d, 0xfe, 0x64, 0xa3, 0xba, 0xea, 0x04, 0x45, 0x2c, 0x2c, 0x3e,
+ 0x26, 0x95, 0x23, 0xf0, 0x79, 0x7a, 0xa2, 0x9a, 0x01, 0x0e, 0x13, 0xf4,
+ 0xb5, 0xcd, 0x01, 0x1b, 0xb0, 0x2d, 0xaa, 0xa2, 0xaf, 0xf8, 0x99, 0x16,
+ 0x94, 0xc8, 0x20, 0xa1, 0x9b, 0x4b, 0xe0, 0xb2, 0xf2, 0xc0, 0xc4, 0x3b,
+ 0xc5, 0x89, 0x14, 0x45, 0xe2, 0xb0, 0x3a, 0xf2, 0xd6, 0x8b, 0x33, 0x30,
+ 0x4c, 0x69, 0xdb, 0x04, 0xbb, 0xb4, 0x27, 0x80, 0x5c, 0x92, 0x45, 0xa5,
+ 0x71, 0xb9, 0x7c, 0x3a, 0x4e, 0x95, 0x32, 0x94, 0x6a, 0x8a, 0x51, 0x9f,
+ 0x98, 0x9c, 0x37, 0x1b, 0xdb, 0xe4, 0x09, 0xb7, 0xd5, 0x8f, 0x5a, 0xad,
+ 0xe3, 0x93, 0x6f, 0x0e, 0x6c, 0xb5, 0x4b, 0x62, 0x28, 0x37, 0xed, 0xc4,
+ 0x25, 0xc0, 0x76, 0x67, 0xd0, 0xc7, 0x67, 0x5c, 0xed, 0xb9, 0x62, 0x37,
+ 0xbb, 0x28, 0x2a, 0xf0, 0x8f, 0x48, 0x2d, 0x9d, 0xe0, 0x02, 0x69, 0x0b,
+ 0x90, 0xb0, 0xa7, 0x88, 0x0a, 0xa2, 0x64, 0xbe, 0x95, 0xc4, 0x00, 0xad,
+ 0xe6, 0xd5, 0x88, 0x36, 0xb7, 0x60, 0xbb, 0x0f, 0x15, 0x74, 0x98, 0x86,
+ 0x0a, 0xcb, 0x31, 0x55, 0x50, 0xcb, 0xc4, 0xb4, 0x45, 0xda, 0x10, 0x70,
+ 0x07, 0x36, 0xa8, 0xf3, 0xf9, 0xb0, 0x5a, 0x85, 0xb1, 0x04, 0xdf, 0xc6,
+ 0x36, 0xd4, 0xe5, 0xb1, 0xaa, 0x82, 0x40, 0x2c, 0xe9, 0xda, 0x5d, 0xa2,
+ 0x30, 0x4c, 0x7d, 0x52, 0x42, 0xbc, 0x01, 0x49, 0x25, 0x7a, 0xca, 0xd6,
+ 0x47, 0xc7, 0x12, 0xea, 0x4a, 0x83, 0x32, 0x41, 0xa3, 0x02, 0x12, 0xfd,
+ 0x24, 0xea, 0xe1, 0x94, 0x83, 0x9c, 0x74, 0x84, 0x44, 0x64, 0x13, 0xba,
+ 0x4e, 0x40, 0x80, 0x81, 0x89, 0x42, 0xf6, 0xcd, 0xae, 0x63, 0x3a, 0x15,
+ 0x9d, 0x44, 0xed, 0x8a, 0x63, 0x0a, 0x1f, 0xee, 0xbd, 0xe0, 0x82, 0xf8,
+ 0x7c, 0xce, 0xe7, 0x89, 0xd4, 0xb0, 0x8e, 0xf5, 0x68, 0x78, 0x98, 0xea,
+ 0xa7, 0xa3, 0xe1, 0x31, 0xff, 0xf3, 0x3c, 0x55, 0x3b, 0x3b, 0x97, 0xbb,
+ 0x59, 0x7d, 0xf9, 0xbb, 0x33, 0x3c, 0x76, 0x48, 0xf7, 0xea, 0x7f, 0x7b,
+ 0xa5, 0x61, 0x41, 0xe8, 0x51, 0xc0, 0x37, 0x76, 0x29, 0x22, 0xbc, 0xf5,
+ 0xe6, 0xf2, 0x77, 0x7e, 0x66, 0x0a, 0xcf, 0xa0, 0x2a, 0xe4, 0xfb, 0x71,
+ 0xf5, 0xec, 0x58, 0xd8, 0xf1, 0xc6, 0x3b, 0x74, 0x94, 0x6e, 0xad, 0x7f,
+ 0x05, 0x2f, 0x02, 0xd3, 0xb5, 0x7b, 0xaf, 0x52, 0x1c, 0xef, 0xd3, 0x23,
+ 0xe3, 0x8d, 0xa2, 0x1d, 0x27, 0x47, 0xbb, 0xa3, 0x59, 0xa8, 0xe0, 0xdf,
+ 0xc1, 0xf8, 0x6a, 0xad, 0x41, 0x25, 0x53, 0xc0, 0x49, 0xaf, 0xdd, 0xfc,
+ 0x3b, 0xb4, 0x6f, 0xff, 0xec, 0xe0, 0x7a, 0xe2, 0x87, 0x8f, 0x77, 0xd3,
+ 0xbd, 0x9d, 0xc1, 0xbb, 0x58, 0x7f, 0xf5, 0x4a, 0xe3, 0x67, 0xfc, 0xf7,
+ 0x5d, 0x8c, 0x23, 0x9e, 0x3c, 0x32, 0x22, 0xd8, 0x7f, 0x1b, 0x00, 0x93,
+ 0x8a, 0x16, 0xd8, 0x23, 0x18, 0x70, 0xfd, 0x35, 0x18, 0x00, 0x20, 0xe7,
+ 0x87, 0xd3, 0x12, 0x7f, 0xc1, 0xc1, 0x71, 0x34, 0x30, 0xd8, 0xe5, 0xd0,
+ 0xc1, 0xaf, 0xaf, 0xb2, 0x82, 0xd2, 0x2d, 0xfa, 0xf7, 0x53, 0xcc, 0x8a,
+ 0x8f, 0xd7, 0x3d, 0x20, 0x05, 0x70, 0x0f, 0xe0, 0x0b, 0xef, 0xc2, 0xef,
+ 0xeb, 0xc1, 0x5a, 0x6d, 0xb9, 0xff, 0x13, 0xdc, 0x01, 0x03, 0xcf, 0x53,
+ 0x7b, 0x06, 0x29, 0xd8, 0xe0, 0x7f, 0xf9, 0xaf, 0x1a, 0x96, 0x0b, 0xdd,
+ 0x73, 0x47, 0x97, 0x86, 0xe4, 0xa6, 0x71, 0x58, 0x91, 0x19, 0xaf, 0xed,
+ 0x6b, 0x8b, 0xfd, 0x82, 0xc2, 0x08, 0xed, 0x17, 0x36, 0x50, 0x30, 0xdc,
+ 0x48, 0x34, 0x8d, 0x11, 0x3c, 0x9f, 0xda, 0x46, 0xef, 0x84, 0x0b, 0x6a,
+ 0x81, 0xce, 0x15, 0x5e, 0x43, 0xa9, 0x00, 0x5e, 0x44, 0x91, 0x0f, 0x3a,
+ 0xb5, 0x05, 0xe1, 0x43, 0x81, 0x5e, 0xe7, 0x8a, 0x36, 0x02, 0xc6, 0x0e,
+ 0xef, 0x02, 0x11, 0x38, 0x7c, 0xed, 0x4f, 0x30, 0x78, 0xeb, 0x8c, 0xd4,
+ 0xe9, 0x29, 0xdf, 0xad, 0xdc, 0xed, 0xc4, 0xf9, 0x38, 0xba, 0x1a, 0x7e,
+ 0x77, 0xaa, 0x7b, 0xdf, 0xa5, 0xd7, 0x43, 0x3d, 0x1e, 0xf6, 0xc4, 0x08,
+ 0x72, 0x0f, 0x53, 0x6a, 0x83, 0x54, 0x2d, 0x17, 0x3c, 0x91, 0x26, 0x53,
+ 0x7c, 0xb7, 0x55, 0x9e, 0x49, 0x51, 0xd7, 0x54, 0x1e, 0x9c, 0x53, 0xe9,
+ 0x36, 0x39, 0x73, 0x95, 0x45, 0x20, 0xcb, 0x0f, 0xaf, 0xb5, 0x83, 0x8a,
+ 0x0c, 0x15, 0x16, 0xeb, 0xd9, 0x80, 0x00, 0x16, 0x03, 0x48, 0x7a, 0xc7,
+ 0x57, 0x36, 0xd8, 0xc5, 0xe2, 0x32, 0x47, 0x41, 0x61, 0x87, 0x08, 0x39,
+ 0x8a, 0xf1, 0x82, 0x9c, 0x5d, 0xa9, 0x14, 0xf4, 0x6d, 0x82, 0x95, 0x85,
+ 0xe4, 0x73, 0xfc, 0x64, 0x49, 0x93, 0xc2, 0x24, 0xb6, 0x76, 0x61, 0x19,
+ 0x27, 0xc6, 0xa5, 0x09, 0xfe, 0x0c, 0x4d, 0x82, 0x7f, 0x49, 0x98, 0x12,
+ 0x66, 0x3b, 0x23, 0x51, 0x6a, 0x6d, 0x17, 0x33, 0x4e, 0xab, 0xbd, 0xae,
+ 0xe5, 0x44, 0xe5, 0x25, 0x6a, 0xb3, 0x74, 0xc4, 0x56, 0x48, 0x88, 0xa9,
+ 0xe2, 0x3d, 0x4f, 0x59, 0x68, 0x15, 0x24, 0xbb, 0xd0, 0x68, 0x23, 0xc2,
+ 0x77, 0x11, 0x13, 0xa9, 0x09, 0xc7, 0x21, 0x55, 0xab, 0x9a, 0x66, 0x86,
+ 0x51, 0x32, 0x63, 0x47, 0xb5, 0xf5, 0xe6, 0x76, 0x51, 0xa9, 0x38, 0x32,
+ 0x9c, 0xd8, 0x98, 0xde, 0xf3, 0xed, 0x54, 0xa8, 0x1d, 0xcf, 0x6e, 0x30,
+ 0x65, 0x89, 0xab, 0xc0, 0xe5, 0xec, 0x05, 0x16, 0x8d, 0x0b, 0x41, 0xb5,
+ 0x97, 0xa0, 0x2c, 0x02, 0xc9, 0x10, 0x08, 0x16, 0x70, 0xba, 0x6d, 0x01,
+ 0x00, 0xd1, 0xb7, 0x0f, 0xd5, 0x63, 0xc8, 0x49, 0x90, 0xa1, 0x95, 0xd2,
+ 0x20, 0x98, 0x58, 0x68, 0x03, 0x37, 0x8f, 0x87, 0x87, 0x33, 0xfd, 0x74,
+ 0x3c, 0xdc, 0xff, 0x17, 0xfe, 0x21, 0x19, 0x84, 0x41, 0xa2, 0x89, 0xfa,
+ 0x50, 0x9b, 0x95, 0x1e, 0xbf, 0xd8, 0xf9, 0xec, 0x6c, 0x50, 0xc3, 0x55,
+ 0xeb, 0x78, 0x58, 0xe7, 0x0f, 0x10, 0x72, 0x6f, 0xd0, 0xcc, 0xd4, 0x58,
+ 0x7a, 0xf2, 0x72, 0xbd, 0xfe, 0x95, 0xbe, 0x20, 0xb2, 0xe1, 0x0b, 0xb0,
+ 0x3a, 0x7d, 0x2d, 0xe9, 0x6b, 0x4a, 0x9f, 0x7f, 0x85, 0xdf, 0x09, 0x77,
+ 0xf4, 0x6d, 0xf4, 0x12, 0xc4, 0xe4, 0xe7, 0xd9, 0xc2, 0xcc, 0x6e, 0xac,
+ 0x3d, 0x0f, 0x08, 0xc0, 0x51, 0xd3, 0xf9, 0x9a, 0x64, 0xd4, 0xab, 0xd1,
+ 0x1a, 0x11, 0x1f, 0xe9, 0xcf, 0x42, 0x3a, 0x61, 0x6e, 0xf2, 0x0f, 0x1d,
+ 0xd1, 0x39, 0xd8, 0x97, 0x91, 0x03, 0x78, 0x9f, 0x01, 0x9e, 0x00, 0xc0,
+ 0x94, 0xc1, 0x66, 0xd3, 0xa2, 0x43, 0x42, 0xae, 0x48, 0x87, 0x28, 0x0d,
+ 0xa7, 0xe3, 0x73, 0xc4, 0xeb, 0x0b, 0xa7, 0xbd, 0xd6, 0x49, 0xb1, 0x5e,
+ 0xd3, 0x31, 0xdf, 0x00, 0x5e, 0xfe, 0x30, 0xd0, 0xa8, 0x86, 0xec, 0x82,
+ 0x40, 0xa1, 0xe8, 0x35, 0x1e, 0x1a, 0x0e, 0x80, 0x38, 0x60, 0x20, 0xf6,
+ 0x01, 0x08, 0x81, 0x1a, 0xa9, 0xc4, 0x65, 0xd5, 0x9b, 0x15, 0x18, 0xcb,
+ 0x14, 0x7c, 0x66, 0xdb, 0x84, 0xc5, 0x62, 0x66, 0x6e, 0xf1, 0xdc, 0x1f,
+ 0x09, 0x4a, 0x0f, 0x92, 0xcc, 0xad, 0x47, 0x1a, 0x21, 0x62, 0x80, 0x34,
+ 0xcd, 0x9c, 0x3e, 0x1d, 0xbf, 0xec, 0x82, 0xf6, 0xf4, 0x94, 0x20, 0x13,
+ 0x70, 0x76, 0x3e, 0xa3, 0xe7, 0x81, 0x36, 0x00, 0xd5, 0x86, 0x57, 0xd6,
+ 0x8e, 0x22, 0x9c, 0xec, 0xb2, 0x35, 0xb5, 0x17, 0xc0, 0x80, 0xd7, 0x58,
+ 0x4e, 0xfb, 0x22, 0x63, 0x80, 0xe4, 0xb3, 0x73, 0xd5, 0x9d, 0xcd, 0xea,
+ 0x05, 0xcf, 0xaf, 0xd1, 0x1f, 0x6e, 0xd9, 0x47, 0xbc, 0xec, 0x03, 0xbf,
+ 0xec, 0xee, 0x68, 0x6c, 0xa4, 0xd1, 0x43, 0x76, 0x81, 0x80, 0xf2, 0xa7,
+ 0xe3, 0x2b, 0xd4, 0x99, 0x48, 0x2e, 0x18, 0x27, 0xd4, 0xa7, 0xf4, 0x13,
+ 0xec, 0x7c, 0x52, 0xb8, 0xa5, 0xea, 0x80, 0x52, 0xda, 0xa5, 0x50, 0x64,
+ 0x76, 0x51, 0x3a, 0x04, 0xe5, 0x24, 0x31, 0x28, 0x13, 0x10, 0xb9, 0xce,
+ 0xaf, 0x60, 0xd4, 0x35, 0x19, 0x9b, 0xba, 0x4d, 0x47, 0x01, 0x15, 0xc1,
+ 0xdd, 0x28, 0x7f, 0x01, 0xd2, 0xe0, 0x3f, 0x3c, 0xc3, 0xfd, 0x10, 0xd5,
+ 0xbd, 0x6c, 0x1f, 0xdf, 0x45, 0x25, 0x2a, 0xe7, 0xca, 0x24, 0x37, 0xe3,
+ 0xc5, 0x1c, 0x28, 0xb7, 0x86, 0x73, 0xd9, 0x24, 0xfd, 0x45, 0xf8, 0x5b,
+ 0x01, 0x80, 0x10, 0x1f, 0x1f, 0xb2, 0x9e, 0x64, 0xc1, 0x24, 0x03, 0x48,
+ 0xd2, 0xc2, 0x16, 0xf7, 0xa1, 0xc4, 0xc1, 0x70, 0x22, 0x09, 0x5a, 0xf8,
+ 0x3c, 0xe6, 0xec, 0x36, 0x95, 0x87, 0xe0, 0x4f, 0x48, 0xd0, 0x7d, 0xad,
+ 0x24, 0x0a, 0x18, 0x3e, 0x55, 0xc7, 0xce, 0xca, 0xf6, 0x41, 0xbb, 0x65,
+ 0x91, 0x34, 0x60, 0x08, 0x8c, 0x47, 0x14, 0x0f, 0x06, 0xe3, 0x42, 0x98,
+ 0x5c, 0x73, 0x59, 0xc3, 0x96, 0xea, 0x14, 0x12, 0x59, 0xc7, 0x87, 0x38,
+ 0xfa, 0xb1, 0x2b, 0xff, 0x69, 0x45, 0x01, 0x0f, 0x45, 0x72, 0x5a, 0x75,
+ 0x13, 0x07, 0x5b, 0x74, 0x8c, 0x37, 0x8c, 0x75, 0xc5, 0xde, 0x9e, 0x54,
+ 0x14, 0xa0, 0xe9, 0x0c, 0x12, 0xb4, 0xc1, 0x23, 0x7f, 0x0e, 0x86, 0xc9,
+ 0x0b, 0xf2, 0x3a, 0xb6, 0x72, 0xad, 0x93, 0xbd, 0x5e, 0x3f, 0xb6, 0x19,
+ 0x59, 0x42, 0x33, 0xee, 0x81, 0xfd, 0x56, 0x71, 0x16, 0x15, 0x28, 0x7a,
+ 0x1d, 0xc1, 0xde, 0x82, 0x73, 0xef, 0xc7, 0x2e, 0x3c, 0xca, 0xeb, 0xdb,
+ 0x0f, 0x47, 0xaa, 0xb4, 0x3a, 0xe8, 0xeb, 0x23, 0xba, 0x70, 0x1c, 0x40,
+ 0xbb, 0xff, 0x42, 0x9d, 0x86, 0x7a, 0x80, 0x05, 0xbe, 0x9f, 0xdf, 0x4e,
+ 0x6a, 0xe5, 0x3a, 0xc2, 0x31, 0x6e, 0x0f, 0x0c, 0xe3, 0x1e, 0xd2, 0xb8,
+ 0xcf, 0x86, 0x9c, 0x44, 0x71, 0xb7, 0xb7, 0x96, 0xf2, 0xac, 0x1b, 0x31,
+ 0xaa, 0xdb, 0xa8, 0x26, 0xbc, 0x6e, 0x3f, 0x51, 0xd3, 0x82, 0xf8, 0x80,
+ 0xf1, 0xbb, 0xcd, 0x1a, 0x7b, 0xb4, 0x54, 0x29, 0xd8, 0xca, 0x19, 0xa7,
+ 0x01, 0xc9, 0xfb, 0x55, 0xbc, 0x27, 0x69, 0x1e, 0xac, 0xe8, 0x19, 0x2d,
+ 0xe7, 0x39, 0x91, 0x43, 0x53, 0x75, 0x28, 0xef, 0xb0, 0xbb, 0x2a, 0x4e,
+ 0x75, 0xb7, 0xe3, 0x4a, 0x5d, 0x79, 0xd1, 0x0d, 0x4a, 0x21, 0x21, 0x72,
+ 0x09, 0xbd, 0x3f, 0xe1, 0x88, 0x4e, 0x2c, 0x9e, 0x2e, 0x32, 0x89, 0x77,
+ 0x9b, 0xc3, 0x10, 0xeb, 0xb6, 0x31, 0x65, 0x28, 0x3a, 0x96, 0xca, 0xfd,
+ 0x08, 0x54, 0x1b, 0xba, 0x56, 0xe5, 0x9d, 0x9c, 0x00, 0xb3, 0x67, 0x6b,
+ 0x78, 0x4d, 0xb4, 0x17, 0x36, 0xb6, 0x4b, 0x87, 0x71, 0x56, 0x09, 0x4c,
+ 0xa2, 0x82, 0x0a, 0x46, 0x2e, 0x84, 0x70, 0x99, 0x2d, 0x0c, 0xd4, 0xa5,
+ 0x55, 0x25, 0xce, 0x9b, 0x3d, 0x88, 0x3a, 0xbb, 0x67, 0x4b, 0x89, 0x85,
+ 0x00, 0xd9, 0xb9, 0xf0, 0xb1, 0x4c, 0x14, 0x1b, 0x12, 0x36, 0x62, 0x0d,
+ 0xa3, 0xd0, 0xa1, 0x46, 0x32, 0xb3, 0x57, 0xc6, 0x10, 0xf3, 0xc3, 0x4e,
+ 0x32, 0x47, 0x80, 0x05, 0x7a, 0xc6, 0xe1, 0x3d, 0xde, 0x16, 0x09, 0xc4,
+ 0xb4, 0xeb, 0x2c, 0x1e, 0xa8, 0xb1, 0x90, 0x03, 0x98, 0x1c, 0xcf, 0xc1,
+ 0x10, 0x35, 0xd6, 0xec, 0x60, 0x60, 0xa0, 0x59, 0x52, 0x41, 0x54, 0x66,
+ 0xa4, 0x03, 0x03, 0x83, 0xc8, 0x13, 0x2a, 0x3a, 0xfe, 0x8d, 0x6c, 0xeb,
+ 0x8f, 0x9c, 0xfb, 0x7a, 0x61, 0xd8, 0x18, 0x0c, 0x5f, 0x91, 0x0d, 0x9b,
+ 0x6f, 0xaf, 0xd1, 0x72, 0x59, 0x2f, 0x55, 0x16, 0x19, 0x55, 0x92, 0xdd,
+ 0xfb, 0xb8, 0x52, 0xb7, 0x46, 0xd1, 0x25, 0x97, 0x0b, 0x77, 0xe6, 0x37,
+ 0xc6, 0xf3, 0x74, 0xb3, 0x45, 0x59, 0xe4, 0x69, 0xc5, 0x72, 0x2a, 0x2c,
+ 0x64, 0x1c, 0xb7, 0x92, 0x11, 0xa1, 0x9f, 0xcc, 0x31, 0xc8, 0xa1, 0x14,
+ 0xd2, 0x67, 0x26, 0xbf, 0xae, 0x17, 0x56, 0xae, 0x48, 0xc4, 0x73, 0x8a,
+ 0x2d, 0x3d, 0x52, 0x58, 0x7c, 0x2c, 0x92, 0xb4, 0x1b, 0xcd, 0xdc, 0x08,
+ 0xfe, 0xf7, 0x55, 0xf4, 0x17, 0x17, 0x7e, 0xa2, 0x99, 0xfe, 0x62, 0xa3,
+ 0x92, 0x7d, 0x97, 0xcd, 0x46, 0x2d, 0xed, 0xcc, 0xc2, 0xaa, 0x96, 0xcc,
+ 0xa8, 0x94, 0x04, 0xb4, 0x33, 0x29, 0x8a, 0x20, 0xc5, 0x71, 0x36, 0x0d,
+ 0xdb, 0xb1, 0x77, 0x6c, 0x5e, 0xb0, 0x7b, 0x88, 0x73, 0x83, 0xf1, 0xf2,
+ 0x67, 0xfe, 0x21, 0xe6, 0xe1, 0xbc, 0x77, 0xa8, 0x7f, 0x67, 0xe7, 0x92,
+ 0xd2, 0x77, 0x7f, 0xf9, 0xf4, 0xd8, 0x00, 0xe4, 0x30, 0x6a, 0x16, 0x25,
+ 0x72, 0x14, 0xd2, 0xa5, 0x87, 0x5d, 0xad, 0xa0, 0x15, 0x5d, 0x6d, 0xcf,
+ 0x00, 0x59, 0x04, 0xc9, 0x9e, 0xdc, 0xf7, 0x57, 0x63, 0x5b, 0x45, 0x6d,
+ 0x23, 0x5c, 0xaa, 0x15, 0xa7, 0xe3, 0x0d, 0x0e, 0x8f, 0x24, 0xd9, 0xec,
+ 0x39, 0x96, 0x48, 0x38, 0x7b, 0x87, 0x56, 0x3b, 0x20, 0x90, 0x39, 0x25,
+ 0x3b, 0x97, 0x8b, 0xa4, 0x01, 0xff, 0x61, 0xca, 0xc2, 0x7b, 0x3a, 0x5e,
+ 0xfc, 0xf8, 0x78, 0x12, 0x5a, 0x46, 0xed, 0x40, 0x78, 0x10, 0x07, 0x2f,
+ 0x8d, 0x3b, 0x62, 0x42, 0xe7, 0x49, 0x5d, 0x30, 0x9f, 0xbd, 0xaa, 0x60,
+ 0x22, 0xae, 0x48, 0xbc, 0x95, 0xf6, 0x37, 0xec, 0x28, 0xa8, 0x56, 0xd0,
+ 0x11, 0xd9, 0xc0, 0xeb, 0x29, 0xdb, 0xc1, 0x81, 0x4a, 0xe7, 0xa3, 0x27,
+ 0x34, 0xd0, 0x93, 0xc8, 0x6b, 0x08, 0xe7, 0xbb, 0x8e, 0x83, 0x64, 0x85,
+ 0xb2, 0xfe, 0x4e, 0x7b, 0xee, 0xdc, 0x5c, 0xc7, 0xdd, 0xb9, 0x37, 0xa7,
+ 0xc6, 0x52, 0x49, 0x37, 0xb1, 0xb2, 0x13, 0x0f, 0x36, 0x66, 0x0e, 0x68,
+ 0x2b, 0x98, 0xda, 0xce, 0x4c, 0x76, 0xcb, 0x44, 0x8e, 0x96, 0xe3, 0x66,
+ 0xaa, 0xf0, 0x18, 0x04, 0xa7, 0x71, 0xca, 0x94, 0xea, 0xe1, 0xd3, 0xba,
+ 0x69, 0xc5, 0xdc, 0x67, 0x74, 0x16, 0x0e, 0x83, 0xdb, 0x81, 0xb7, 0x3c,
+ 0xb1, 0x87, 0xf7, 0xb8, 0xd8, 0xa1, 0x1f, 0x64, 0x61, 0xda, 0x4b, 0xa0,
+ 0x22, 0x0a, 0xa0, 0x6d, 0xc7, 0x51, 0x11, 0x16, 0xa5, 0x65, 0x20, 0x34,
+ 0xeb, 0xec, 0xde, 0x3e, 0xa6, 0x82, 0xe4, 0xf7, 0x12, 0x76, 0x2f, 0xbb,
+ 0x6f, 0x17, 0x57, 0x79, 0x0a, 0xaa, 0x74, 0xd4, 0xa1, 0x9c, 0xc0, 0x3d,
+ 0xc5, 0xb8, 0x1a, 0x26, 0x6e, 0x4f, 0x6a, 0x4a, 0xed, 0xb0, 0xec, 0xed,
+ 0xeb, 0xe8, 0xc4, 0x73, 0x71, 0x70, 0x70, 0x4a, 0xce, 0x77, 0xd6, 0xb6,
+ 0x34, 0x15, 0xa4, 0x83, 0x2f, 0xb0, 0x01, 0x8b, 0x74, 0xe9, 0xcb, 0xb8,
+ 0xed, 0x11, 0xe4, 0x6b, 0xd2, 0x18, 0x1e, 0xbb, 0x59, 0x41, 0x05, 0xd9,
+ 0x54, 0x9d, 0xab, 0xac, 0xb2, 0xc1, 0xdf, 0x30, 0x53, 0x82, 0x67, 0xb6,
+ 0xb9, 0x5a, 0x2a, 0x80, 0x18, 0x4b, 0xdb, 0x6c, 0xc4, 0x92, 0x96, 0x17,
+ 0x66, 0x28, 0x4e, 0x22, 0x75, 0xc7, 0xaa, 0x89, 0x2a, 0xcc, 0x30, 0x54,
+ 0x4c, 0xc9, 0x6f, 0xb6, 0x3d, 0xaa, 0x6e, 0x83, 0x8f, 0xc1, 0x00, 0xf5,
+ 0x1e, 0x9e, 0xdd, 0xe5, 0x63, 0xc4, 0x04, 0x1e, 0xfb, 0xe5, 0xd3, 0x7b,
+ 0x65, 0xcf, 0xf7, 0x07, 0x16, 0x42, 0x58, 0x08, 0x84, 0xe9, 0x8e, 0x7f,
+ 0xbb, 0xd4, 0x41, 0x65, 0x23, 0x2e, 0x54, 0xb6, 0x10, 0xd7, 0x65, 0x33,
+ 0x09, 0x1c, 0xa7, 0x54, 0x0c, 0x9f, 0xc6, 0x72, 0x46, 0xe2, 0x6f, 0xb4,
+ 0x8a, 0x61, 0x2c, 0x09, 0xc4, 0x4b, 0xee, 0x75, 0x44, 0x3d, 0x50, 0xac,
+ 0xa6, 0x52, 0x4c, 0x6d, 0x8c, 0x45, 0xb6, 0x69, 0x04, 0x7e, 0x17, 0x61,
+ 0x78, 0x7e, 0xf8, 0x85, 0x06, 0x8b, 0x9c, 0x2c, 0x1e, 0xfd, 0xfc, 0xf9,
+ 0x17, 0x96, 0x18, 0x71, 0x2a, 0x9e, 0x59, 0xb5, 0x4e, 0x16, 0x0e, 0xc6,
+ 0x87, 0x38, 0xfb, 0xd3, 0xf1, 0xa1, 0xad, 0x9f, 0x9e, 0x5b, 0x1a, 0x09,
+ 0x7a, 0x2a, 0xd8, 0xd2, 0x53, 0xb1, 0x2c, 0xe2, 0xa4, 0x58, 0x71, 0x64,
+ 0xe0, 0x84, 0xea, 0xe0, 0x5c, 0x65, 0x4d, 0x27, 0xe9, 0x8d, 0x8a, 0xce,
+ 0x62, 0xcd, 0xf8, 0x8c, 0x2d, 0xaf, 0x9c, 0x32, 0x80, 0xea, 0x90, 0xee,
+ 0x84, 0x91, 0xfe, 0xc6, 0x45, 0xb2, 0x95, 0x44, 0xd6, 0xf9, 0xd8, 0xad,
+ 0x18, 0x21, 0x08, 0xcd, 0xfe, 0xd8, 0x62, 0xce, 0x83, 0x2c, 0x07, 0xca,
+ 0xf7, 0x27, 0x58, 0x5c, 0x4a, 0x43, 0xd3, 0x01, 0x25, 0x0c, 0x24, 0xda,
+ 0x83, 0x8c, 0xb0, 0xdb, 0xb6, 0x4a, 0x1b, 0x65, 0x5c, 0x48, 0x38, 0x5f,
+ 0xad, 0x61, 0xa4, 0x75, 0xaf, 0x28, 0x7b, 0xeb, 0xaf, 0x61, 0xb0, 0x48,
+ 0x8a, 0xfa, 0xf8, 0x79, 0xcc, 0x78, 0x52, 0xb4, 0x32, 0xc8, 0x45, 0xd9,
+ 0x1b, 0x38, 0x03, 0xdb, 0x84, 0x5c, 0x24, 0xb5, 0xf7, 0x0f, 0xc5, 0xaa,
+ 0x62, 0x96, 0x3c, 0xf8, 0x3f, 0x3a, 0x9f, 0x36, 0x23, 0xb8, 0x11, 0xec,
+ 0x69, 0xc9, 0xa4, 0x20, 0xcb, 0x44, 0xb2, 0x99, 0xb3, 0xa0, 0x27, 0xe2,
+ 0x90, 0x23, 0x90, 0x61, 0xe4, 0x67, 0xd7, 0x55, 0xfc, 0x11, 0xf7, 0xf9,
+ 0x84, 0x86, 0x0a, 0x7d, 0xdc, 0xe0, 0x78, 0x61, 0x70, 0xf4, 0xc8, 0x8f,
+ 0xec, 0xcb, 0x05, 0x50, 0x61, 0x0c, 0xf7, 0x80, 0x9e, 0xbf, 0x13, 0xdd,
+ 0x5c, 0xc2, 0xbe, 0x8b, 0xba, 0x76, 0x75, 0x61, 0x09, 0x9a, 0x77, 0x9d,
+ 0x40, 0x8f, 0x50, 0xa4, 0xab, 0x9c, 0x5d, 0x61, 0xf9, 0x0e, 0x9e, 0xe9,
+ 0x0f, 0x34, 0xb9, 0xda, 0x26, 0x64, 0x5d, 0x43, 0x01, 0x7f, 0xe0, 0x06,
+ 0x35, 0x53, 0xb7, 0x92, 0x9c, 0x6a, 0x99, 0x49, 0x7b, 0x86, 0x42, 0xcc,
+ 0x5b, 0x10, 0x54, 0xae, 0x52, 0x5a, 0x7b, 0x4c, 0x40, 0x05, 0x1e, 0x44,
+ 0xf9, 0x74, 0x96, 0xb3, 0x75, 0xb6, 0xdf, 0x77, 0x6a, 0x43, 0x6e, 0xc0,
+ 0x0e, 0x14, 0xca, 0xe9, 0x2e, 0xa4, 0x2b, 0xab, 0x4c, 0x5a, 0x7c, 0x31,
+ 0x2b, 0x12, 0x09, 0x60, 0x5a, 0xd3, 0x5a, 0x94, 0x0a, 0x75, 0xb0, 0x68,
+ 0xb8, 0xee, 0x17, 0x71, 0xa1, 0x02, 0x54, 0xc4, 0x55, 0x88, 0x05, 0x2e,
+ 0xce, 0xe4, 0xb2, 0xc1, 0x84, 0x1a, 0x20, 0x58, 0x88, 0x52, 0x07, 0x0d,
+ 0xc9, 0x4e, 0xaa, 0x40, 0xa8, 0xe9, 0x30, 0xde, 0xe3, 0x11, 0x89, 0x2d,
+ 0x3e, 0x41, 0xcb, 0xdf, 0x21, 0xea, 0xc0, 0xe2, 0x17, 0x65, 0x75, 0xbc,
+ 0x1c, 0x17, 0xa4, 0x7a, 0x9b, 0x70, 0xae, 0x20, 0xa7, 0xd4, 0x9e, 0x52,
+ 0xf1, 0x09, 0x13, 0xa4, 0x87, 0x47, 0xd1, 0x41, 0x1c, 0x8f, 0x66, 0x2e,
+ 0x39, 0x80, 0x1d, 0x9c, 0xd8, 0xac, 0xaa, 0x4d, 0x3e, 0xb9, 0xb5, 0x74,
+ 0x4e, 0x5f, 0x03, 0xdb, 0xdf, 0x1a, 0x69, 0xf8, 0x94, 0x27, 0x18, 0x02,
+ 0xa2, 0x28, 0x07, 0x1d, 0xe9, 0x09, 0x2a, 0xf9, 0x15, 0x59, 0xc5, 0xe4,
+ 0xdd, 0x93, 0xe1, 0x3b, 0xcf, 0xe2, 0x6b, 0x1d, 0xb9, 0x62, 0xe4, 0xc8,
+ 0x9e, 0xb0, 0xe5, 0x3a, 0x42, 0xae, 0xc2, 0xbb, 0x31, 0x7c, 0x8c, 0x1f,
+ 0x9d, 0x50, 0x11, 0x87, 0x89, 0x59, 0xd9, 0xf3, 0x42, 0x42, 0x7a, 0x76,
+ 0x04, 0x0b, 0xa3, 0xed, 0x78, 0x00, 0x43, 0xbc, 0xd0, 0x51, 0xaf, 0x59,
+ 0xf5, 0x40, 0x78, 0x45, 0x3d, 0x5c, 0x52, 0x2f, 0xb2, 0x07, 0xb9, 0x01,
+ 0x25, 0x91, 0xda, 0xcd, 0xf1, 0x28, 0x78, 0x49, 0x4a, 0xc1, 0xcb, 0x01,
+ 0xdb, 0x76, 0x02, 0x79, 0x7e, 0xef, 0xd1, 0xc8, 0xe4, 0x41, 0xeb, 0x9f,
+ 0xff, 0x74, 0x64, 0xf2, 0xb3, 0x74, 0x8a, 0x92, 0xc3, 0x12, 0xf5, 0x80,
+ 0xea, 0x31, 0x88, 0xd0, 0xff, 0xf8, 0xaf, 0x0b, 0x5b, 0xfe, 0x37, 0xc5,
+ 0x2d, 0x0f, 0xb7, 0xc6, 0x2d, 0xa9, 0x95, 0x92, 0x2d, 0xea, 0x72, 0x4a,
+ 0xad, 0x6b, 0x4e, 0x06, 0x01, 0x4c, 0x92, 0x97, 0x24, 0x2e, 0x7d, 0xb8,
+ 0xf0, 0xb1, 0xf0, 0x65, 0x18, 0xbd, 0xdc, 0x89, 0xba, 0xd1, 0x44, 0x1c,
+ 0x2d, 0x80, 0x71, 0x7c, 0xe4, 0xe3, 0x9a, 0x82, 0x7b, 0xc3, 0x07, 0x3c,
+ 0x31, 0x98, 0xc0, 0x52, 0x51, 0x5b, 0x69, 0xee, 0x39, 0x4a, 0x4e, 0x37,
+ 0x32, 0x1f, 0x5b, 0x19, 0x8e, 0x71, 0x45, 0xca, 0x75, 0x4b, 0xe9, 0x6f,
+ 0x87, 0x92, 0x31, 0x91, 0x8a, 0xdc, 0xc5, 0x41, 0x8b, 0xa1, 0x04, 0xf4,
+ 0x82, 0x60, 0x28, 0x21, 0x17, 0x93, 0x62, 0x9e, 0x7e, 0x01, 0x6e, 0xa4,
+ 0xd6, 0x97, 0xf4, 0xb3, 0xb4, 0x95, 0x7c, 0x3c, 0x52, 0xba, 0x16, 0x68,
+ 0xf9, 0xa7, 0x57, 0x30, 0x2e, 0x3f, 0x2c, 0xb1, 0x43, 0xce, 0xbf, 0x51,
+ 0x58, 0x92, 0x4c, 0xec, 0xd6, 0x54, 0xc8, 0x02, 0x84, 0x34, 0x6a, 0x6e,
+ 0xe9, 0x80, 0xfb, 0xfa, 0x11, 0xe0, 0x88, 0x85, 0x5a, 0xe0, 0x6d, 0xec,
+ 0xcd, 0x69, 0x6b, 0x6b, 0xfe, 0x14, 0xbe, 0xaf, 0xfe, 0x49, 0xf8, 0xa2,
+ 0xcf, 0x91, 0x1b, 0x03, 0x63, 0xaf, 0x7e, 0x88, 0xaf, 0x1f, 0x7a, 0x5e,
+ 0x18, 0x1e, 0xef, 0xb5, 0x2b, 0xa4, 0x07, 0xbe, 0x7a, 0xf0, 0x01, 0x94,
+ 0x14, 0xee, 0xf6, 0x0d, 0x58, 0xf4, 0x16, 0x42, 0xfa, 0x67, 0x23, 0xc5,
+ 0x64, 0x06, 0xbb, 0x11, 0xb9, 0x12, 0xb2, 0xa0, 0x42, 0x51, 0x5c, 0x20,
+ 0x8e, 0xfe, 0x62, 0xe7, 0x65, 0xf4, 0x99, 0x3b, 0x60, 0xa0, 0x10, 0xc2,
+ 0x87, 0x78, 0x01, 0x2f, 0x76, 0x18, 0xd5, 0x3b, 0x00, 0xff, 0x29, 0x33,
+ 0xc7, 0xf8, 0x21, 0x74, 0x21, 0xf4, 0x82, 0x2f, 0xfa, 0x44, 0xec, 0x43,
+ 0x1f, 0x01, 0x5f, 0xb2, 0x25, 0x2f, 0xed, 0xf7, 0xff, 0xc4, 0x16, 0xe0,
+ 0xa0, 0x79, 0x42, 0xb8, 0xe1, 0xfd, 0xf4, 0x77, 0xbd, 0xd2, 0x16, 0x37,
+ 0x3b, 0x24, 0x6a, 0x3b, 0xe0, 0x62, 0x64, 0xfc, 0xff, 0x09, 0xe0, 0xa7,
+ 0x9b, 0x00, 0x7f, 0xfd, 0x5f, 0x06, 0xf0, 0xf6, 0xac, 0xc7, 0xe1, 0x8b,
+ 0xff, 0xc9, 0x71, 0x7a, 0xe7, 0x81, 0xee, 0x8b, 0x07, 0xca, 0x5f, 0xfa,
+ 0x52, 0x6e, 0x18, 0xfb, 0x18, 0x7e, 0x3b, 0xd4, 0xd5, 0x6a, 0xf9, 0x24,
+ 0x27, 0xba, 0x31, 0x40, 0x6a, 0x8d, 0x9e, 0x9c, 0x4b, 0x13, 0x77, 0x8f,
+ 0x0f, 0xf7, 0xa4, 0x44, 0x47, 0x42, 0xfd, 0xb6, 0x5a, 0x46, 0x4e, 0x6f,
+ 0xa0, 0x51, 0xb0, 0x6a, 0xca, 0x15, 0x9d, 0x03, 0x14, 0x8d, 0x6b, 0x67,
+ 0xe4, 0x6a, 0x3d, 0x27, 0xe5, 0x29, 0xd1, 0xc7, 0xc5, 0x7c, 0x09, 0x55,
+ 0xc3, 0x80, 0x8a, 0xb1, 0x85, 0x34, 0x31, 0x57, 0xbc, 0x2a, 0x77, 0x68,
+ 0x43, 0xbc, 0x05, 0xce, 0x0b, 0x04, 0x3e, 0x81, 0x0d, 0x6a, 0x51, 0x33,
+ 0x11, 0x93, 0x90, 0x1f, 0x28, 0xf5, 0xb2, 0x2f, 0xfe, 0xa7, 0x85, 0xfe,
+ 0x75, 0x10, 0xfb, 0xf7, 0x68, 0x40, 0x87, 0xd2, 0xa7, 0xf4, 0xc9, 0x11,
+ 0xf8, 0xf3, 0x4c, 0x80, 0xea, 0xa4, 0x02, 0x8e, 0x82, 0x83, 0xe2, 0x88,
+ 0x4a, 0x57, 0x01, 0xf0, 0x27, 0x69, 0x80, 0xa3, 0x7e, 0x7b, 0x35, 0x43,
+ 0x15, 0x04, 0x60, 0xea, 0x85, 0x9c, 0x7f, 0x67, 0xef, 0xe9, 0xe8, 0xea,
+ 0xe9, 0x18, 0xfc, 0x73, 0xca, 0xd8, 0x7e, 0x28, 0xac, 0x7d, 0x45, 0x07,
+ 0x54, 0xc9, 0xe8, 0xa5, 0x79, 0xa5, 0x78, 0xc1, 0x55, 0x33, 0x93, 0x6e,
+ 0x7c, 0x2c, 0xa5, 0x00, 0xd4, 0x4e, 0xd6, 0xfe, 0x51, 0xe0, 0xd6, 0xd8,
+ 0x30, 0x5b, 0x10, 0x2d, 0xea, 0xac, 0xf7, 0xff, 0xcb, 0x6c, 0xc2, 0x9f,
+ 0x25, 0x12, 0xb0, 0x03, 0xc0, 0xbf, 0x9e, 0x4d, 0xf8, 0xef, 0x4d, 0x25,
+ 0x60, 0x04, 0xff, 0xcc, 0x55, 0x48, 0xf6, 0x94, 0xfb, 0xcc, 0x75, 0x6a,
+ 0xae, 0x3b, 0x40, 0xde, 0x3a, 0xa1, 0xed, 0x9b, 0xa3, 0xb1, 0x51, 0xcf,
+ 0xcd, 0x0e, 0x67, 0x4c, 0x60, 0xc0, 0xd0, 0x4c, 0x1e, 0x3c, 0x2d, 0xf6,
+ 0xbc, 0xa5, 0xda, 0x50, 0x0c, 0xad, 0x74, 0xbb, 0x08, 0xf8, 0xf6, 0x7e,
+ 0x72, 0x4a, 0x93, 0x0f, 0x71, 0xbf, 0x54, 0x72, 0x6a, 0x3a, 0x31, 0x33,
+ 0x4e, 0x36, 0xf2, 0x09, 0x46, 0xf7, 0x9c, 0xbb, 0x1f, 0xc6, 0xb5, 0x7d,
+ 0x1c, 0xec, 0x41, 0x59, 0x3c, 0x43, 0xea, 0x1c, 0x61, 0x58, 0x00, 0x9e,
+ 0x10, 0x7b, 0x29, 0xb5, 0xf2, 0x69, 0x99, 0xd8, 0xb3, 0xd5, 0xdd, 0xba,
+ 0x7e, 0x30, 0x5c, 0xab, 0x3a, 0x38, 0x61, 0xe4, 0x9b, 0x96, 0x91, 0xb0,
+ 0x44, 0x41, 0x60, 0xc3, 0xf6, 0x2c, 0xe4, 0xd0, 0xc1, 0x0b, 0xc4, 0x8d,
+ 0x15, 0x46, 0x12, 0x94, 0x09, 0x92, 0x1e, 0x18, 0xb2, 0x25, 0x27, 0x4e,
+ 0x85, 0xc2, 0xcd, 0x8a, 0xa0, 0xa0, 0x56, 0x39, 0xae, 0x28, 0xa8, 0xc8,
+ 0xe5, 0xb6, 0xb6, 0xe5, 0x84, 0xec, 0xac, 0xb4, 0xbd, 0x95, 0x60, 0x3f,
+ 0x9f, 0xc5, 0xaf, 0x83, 0x0a, 0x11, 0x7f, 0x64, 0x99, 0x43, 0x80, 0xd4,
+ 0xb8, 0x80, 0x53, 0x44, 0x53, 0xa9, 0xd0, 0xb1, 0x4d, 0x1f, 0x02, 0xa4,
+ 0x53, 0xb9, 0x39, 0x53, 0x8a, 0x6d, 0x0f, 0x42, 0x78, 0xf7, 0xd8, 0xa2,
+ 0x1d, 0x15, 0x51, 0xdd, 0x6e, 0xdf, 0x85, 0x5b, 0xb9, 0xe5, 0xf0, 0xb0,
+ 0x72, 0x20, 0xb7, 0x80, 0xdd, 0xec, 0x29, 0x44, 0xb2, 0x95, 0xf3, 0x4a,
+ 0xb6, 0x23, 0x44, 0x69, 0x06, 0xb6, 0x3f, 0xb4, 0x49, 0x94, 0x3b, 0x1d,
+ 0x5b, 0x2d, 0xd2, 0x39, 0x42, 0x2f, 0x9b, 0xef, 0xb9, 0x32, 0x0e, 0xe3,
+ 0xfd, 0x4d, 0x6d, 0x8b, 0x5c, 0xfd, 0x96, 0xe0, 0xc0, 0x6a, 0xca, 0x5b,
+ 0xd0, 0x66, 0x13, 0x3a, 0xf1, 0xd4, 0x2d, 0x68, 0x91, 0xcd, 0x70, 0xfc,
+ 0x8f, 0x6a, 0x58, 0x62, 0xa6, 0x49, 0x19, 0xcf, 0x7d, 0xde, 0x69, 0x15,
+ 0xaf, 0x30, 0xd6, 0xf8, 0xcb, 0xc1, 0x95, 0x9c, 0xd3, 0x3d, 0xd0, 0xef,
+ 0x7d, 0x07, 0x2c, 0xd6, 0xe8, 0xef, 0x00, 0x61, 0x67, 0xfe, 0x7c, 0x2c,
+ 0x52, 0x30, 0x75, 0x80, 0xe6, 0x78, 0x5b, 0x50, 0xc6, 0x49, 0x42, 0x98,
+ 0xbc, 0x64, 0x8c, 0xbf, 0x35, 0x36, 0x29, 0xb5, 0x34, 0x31, 0xb9, 0x24,
+ 0x98, 0x82, 0x81, 0x5f, 0xa5, 0xed, 0x03, 0x9f, 0x6e, 0x73, 0x6d, 0xd0,
+ 0x36, 0xce, 0xbd, 0x50, 0xe4, 0x18, 0x3b, 0xd3, 0x81, 0x93, 0xcd, 0xe7,
+ 0x18, 0xe3, 0x56, 0x27, 0x13, 0x64, 0x91, 0xca, 0x75, 0x75, 0xe9, 0x77,
+ 0x9e, 0x96, 0x43, 0x9b, 0xe1, 0xb1, 0x7d, 0xdf, 0xf5, 0x87, 0x55, 0x5a,
+ 0xeb, 0xf0, 0x3e, 0x45, 0xd1, 0x92, 0x98, 0xc3, 0x92, 0xea, 0xf4, 0xfd,
+ 0xdf, 0x18, 0x4a, 0x01, 0xbd, 0xe2, 0x43, 0x01, 0xb8, 0x34, 0x14, 0x57,
+ 0xec, 0x46, 0xba, 0x63, 0x07, 0xb8, 0xc9, 0xfc, 0x93, 0xdb, 0x17, 0xb3,
+ 0x5c, 0xa5, 0x65, 0x8a, 0x1d, 0xfc, 0x14, 0xa9, 0x37, 0xda, 0x19, 0x5e,
+ 0x4c, 0x18, 0x88, 0x92, 0x08, 0xfe, 0x47, 0x82, 0xe7, 0xac, 0xd7, 0xfa,
+ 0x86, 0x5f, 0xdb, 0xd5, 0x7f, 0x3d, 0x64, 0x3c, 0xf2, 0xb7, 0xb1, 0xc1,
+ 0x31, 0xcc, 0x7e, 0x76, 0xc6, 0x6d, 0x30, 0x59, 0x02, 0x54, 0x4d, 0xc6,
+ 0xf3, 0x04, 0xb9, 0x49, 0xb2, 0x35, 0x82, 0x5e, 0x04, 0xf8, 0xd4, 0xd6,
+ 0x2e, 0xa7, 0xf8, 0xfc, 0x0a, 0x4d, 0xd2, 0x5b, 0xae, 0x56, 0xbb, 0x90,
+ 0xe1, 0x48, 0xdd, 0xc4, 0x53, 0x21, 0xe4, 0x56, 0xff, 0x67, 0x3c, 0x59,
+ 0x8d, 0xe3, 0xe1, 0x8f, 0xdd, 0x86, 0x8b, 0x84, 0x08, 0x1d, 0x9c, 0xd3,
+ 0x74, 0x14, 0x1f, 0x27, 0xd4, 0xd1, 0x88, 0x82, 0x3a, 0xee, 0x2a, 0x1e,
+ 0xb4, 0xa4, 0x78, 0xaf, 0xb2, 0xec, 0x34, 0x4f, 0x4d, 0x16, 0xd4, 0xdc,
+ 0xf9, 0x8d, 0x0d, 0x5a, 0xc0, 0xa9, 0xb6, 0x08, 0xc6, 0x02, 0xb9, 0x77,
+ 0x41, 0x3d, 0x5e, 0x7b, 0x4a, 0x2a, 0x91, 0xe3, 0xdd, 0x24, 0x4b, 0x47,
+ 0x45, 0x71, 0xb6, 0x5a, 0xc4, 0x94, 0x9e, 0x7b, 0xf7, 0xa5, 0x9c, 0xd9,
+ 0x6e, 0x35, 0x20, 0xdf, 0x20, 0x9e, 0x56, 0xb0, 0x9c, 0xbb, 0x69, 0x65,
+ 0xd9, 0x50, 0xab, 0x4f, 0x56, 0x18, 0xa8, 0x77, 0x31, 0x13, 0x8a, 0x1c,
+ 0x89, 0xb5, 0x07, 0x3d, 0xc9, 0x2e, 0x60, 0xa3, 0x46, 0x56, 0x26, 0x29,
+ 0x52, 0xda, 0xae, 0x71, 0x5f, 0x4f, 0xfa, 0x60, 0x31, 0x63, 0x49, 0x04,
+ 0xa2, 0xe5, 0xd0, 0x9d, 0xe3, 0x20, 0xca, 0x26, 0xfc, 0xc2, 0xc0, 0xce,
+ 0x36, 0x19, 0xf5, 0xf1, 0x11, 0xb0, 0xb0, 0x8f, 0xf9, 0xfe, 0xf1, 0x61,
+ 0x6b, 0xf3, 0xf8, 0xa8, 0x07, 0x55, 0x54, 0xba, 0xba, 0x42, 0xdf, 0xe4,
+ 0x3a, 0x0f, 0x81, 0xc0, 0x58, 0x1e, 0x67, 0x5e, 0xce, 0xb8, 0x69, 0xba,
+ 0xcf, 0x6e, 0xfb, 0xd6, 0xea, 0xfe, 0xf6, 0xa9, 0xb9, 0x2f, 0x1c, 0x7c,
+ 0xb0, 0xd5, 0x09, 0x35, 0xbe, 0xe1, 0x7e, 0x88, 0x22, 0xc4, 0xbb, 0xdb,
+ 0x8c, 0x4d, 0xff, 0x40, 0x76, 0x5f, 0x0b, 0x63, 0x81, 0x09, 0x15, 0xae,
+ 0x64, 0x4c, 0x0a, 0x9e, 0x47, 0xe0, 0xae, 0x68, 0xa8, 0xa0, 0xb8, 0x2b,
+ 0x71, 0xc5, 0xdd, 0xec, 0xa8, 0x04, 0x1e, 0x8f, 0x7d, 0x21, 0x44, 0x76,
+ 0x3d, 0x3e, 0x1b, 0x61, 0xcf, 0x5f, 0xb6, 0xdb, 0x87, 0xf8, 0x46, 0x7f,
+ 0x98, 0xcb, 0x6a, 0xb7, 0xd4, 0x98, 0xe2, 0xd1, 0x0a, 0xe0, 0xed, 0x66,
+ 0xc9, 0x07, 0xb4, 0x71, 0x4c, 0x2a, 0xfe, 0x47, 0x91, 0xbb, 0x85, 0x94,
+ 0x99, 0x06, 0x73, 0xd0, 0x6a, 0xca, 0x25, 0xe6, 0x68, 0xbb, 0xf1, 0x60,
+ 0x14, 0xd7, 0x7a, 0xb3, 0x0d, 0x1d, 0xd4, 0x81, 0xfa, 0x26, 0x1c, 0x9e,
+ 0x86, 0x9c, 0xa4, 0x99, 0xde, 0x2b, 0x99, 0x42, 0x75, 0xdb, 0x93, 0xca,
+ 0xc2, 0x05, 0x24, 0x5b, 0x92, 0xc1, 0x89, 0x6d, 0xdb, 0xb7, 0x84, 0x8a,
+ 0x7b, 0xad, 0x36, 0x94, 0x95, 0x0c, 0xd5, 0xae, 0x3d, 0x0d, 0x80, 0x9b,
+ 0x88, 0xa7, 0xe3, 0x0c, 0x77, 0x4d, 0xc1, 0x5a, 0x75, 0xda, 0xd3, 0x98,
+ 0x0e, 0xef, 0x75, 0xfb, 0xfb, 0x82, 0x91, 0xbd, 0xd8, 0xc5, 0x90, 0xdd,
+ 0xde, 0x55, 0xe4, 0x4f, 0x1f, 0x55, 0xed, 0x38, 0xa6, 0x5d, 0xb7, 0xe8,
+ 0xf9, 0x56, 0xc0, 0xd3, 0x9e, 0xcb, 0xe0, 0xb4, 0xa1, 0x0b, 0x80, 0xe3,
+ 0x31, 0x0d, 0x1f, 0xff, 0xfe, 0xd6, 0x5b, 0x10, 0xaa, 0x6a, 0xa6, 0x8c,
+ 0x9f, 0xda, 0x8e, 0x97, 0x17, 0xc1, 0xa9, 0xa2, 0x55, 0x2c, 0xe2, 0x6c,
+ 0x4b, 0xb7, 0x31, 0x12, 0x9f, 0x49, 0x70, 0xf2, 0x01, 0x50, 0x4a, 0x06,
+ 0x8e, 0xc5, 0x9d, 0xb2, 0x8d, 0xc4, 0xa7, 0x66, 0x11, 0xdf, 0xa6, 0x78,
+ 0x10, 0xdc, 0x1d, 0xee, 0x40, 0xb3, 0xa5, 0x75, 0x80, 0x4d, 0x18, 0xc1,
+ 0x9d, 0xa0, 0x99, 0x1a, 0x2a, 0xfd, 0xa8, 0x58, 0x17, 0xa4, 0x73, 0xce,
+ 0x11, 0x04, 0xa7, 0x02, 0x4e, 0xf8, 0xa0, 0x86, 0xa4, 0x77, 0x16, 0xc6,
+ 0x36, 0xf0, 0xf0, 0xc0, 0xe7, 0x9e, 0xc4, 0x18, 0x56, 0x97, 0xca, 0xdf,
+ 0x2c, 0xba, 0x45, 0x41, 0x9a, 0x4b, 0xe3, 0x54, 0xdb, 0x66, 0xb9, 0xed,
+ 0x94, 0x49, 0x3a, 0x94, 0x2c, 0x29, 0x3e, 0x1e, 0xc4, 0xfe, 0xca, 0x35,
+ 0xe9, 0x23, 0x58, 0x95, 0xe8, 0x89, 0xa0, 0x29, 0x86, 0x48, 0x0a, 0xf8,
+ 0x24, 0xc9, 0x2d, 0x8e, 0xe4, 0x0a, 0x95, 0xa8, 0xa0, 0x81, 0xcc, 0xc2,
+ 0x58, 0x6d, 0xc4, 0x59, 0xa6, 0x0d, 0x8d, 0xc0, 0xed, 0x64, 0xb9, 0x3b,
+ 0xe0, 0x16, 0xda, 0x24, 0x8a, 0xb3, 0xb6, 0x5c, 0x98, 0x48, 0xa1, 0xc7,
+ 0x66, 0x52, 0xfb, 0x4b, 0x77, 0x53, 0x6b, 0x73, 0x6c, 0xd6, 0x55, 0x93,
+ 0x3e, 0x9c, 0x67, 0xcd, 0xcc, 0x26, 0xb4, 0xad, 0x00, 0x0f, 0x9b, 0x96,
+ 0xb0, 0xde, 0xe1, 0x54, 0x01, 0x62, 0x80, 0xda, 0x42, 0xbe, 0x8b, 0xf9,
+ 0x4c, 0x05, 0xbf, 0xd9, 0x21, 0xe9, 0xa8, 0x04, 0x59, 0x89, 0x1c, 0xac,
+ 0x25, 0x8d, 0xe7, 0xdc, 0x58, 0xff, 0x36, 0x08, 0x2a, 0x4d, 0x51, 0xa5,
+ 0x99, 0x67, 0x80, 0xcd, 0x4a, 0xb2, 0x07, 0xdc, 0xa7, 0x0f, 0xad, 0xfe,
+ 0x38, 0xe7, 0x37, 0x67, 0x04, 0x2d, 0xc6, 0x60, 0x77, 0xb1, 0xdd, 0x4c,
+ 0xb8, 0x8f, 0xde, 0xb1, 0x25, 0x3b, 0x7a, 0xcb, 0xae, 0xd9, 0xae, 0x03,
+ 0x70, 0x89, 0xcf, 0xab, 0x31, 0xcd, 0x49, 0x2b, 0x86, 0x5b, 0x6a, 0x55,
+ 0x16, 0xb4, 0xd4, 0x70, 0x01, 0x09, 0xdb, 0x93, 0xd9, 0x89, 0xdb, 0x0a,
+ 0x2d, 0x35, 0xf4, 0x90, 0x66, 0x74, 0xaa, 0x30, 0x5d, 0x62, 0x8d, 0x8e,
+ 0xf0, 0x66, 0xbb, 0x49, 0xe9, 0xeb, 0x5b, 0x6e, 0xbf, 0x10, 0xcb, 0x99,
+ 0x33, 0x40, 0x54, 0x6e, 0x5f, 0xdd, 0x32, 0x1a, 0x3e, 0x3f, 0x64, 0x52,
+ 0x9e, 0x1c, 0x52, 0x36, 0x77, 0xb3, 0xbe, 0x5f, 0x12, 0xe8, 0x5e, 0xa8,
+ 0xf2, 0x73, 0x4e, 0xae, 0xae, 0xe8, 0x1d, 0x26, 0xf9, 0xc3, 0x1d, 0xd2,
+ 0x89, 0x7d, 0x4a, 0x10, 0xf9, 0x01, 0x2f, 0x22, 0xad, 0x54, 0x37, 0xa6,
+ 0xa6, 0x06, 0x87, 0xe4, 0x01, 0x74, 0x4d, 0x11, 0xf7, 0x34, 0x1f, 0xa9,
+ 0x75, 0x32, 0x8a, 0xbb, 0x98, 0x64, 0xdb, 0xa7, 0x52, 0x48, 0x5f, 0xe0,
+ 0xb1, 0xcd, 0x6e, 0x6c, 0xde, 0x3c, 0x6c, 0xb4, 0xc4, 0x25, 0xff, 0x56,
+ 0x3c, 0xc4, 0x42, 0x4c, 0x4e, 0x91, 0x89, 0x2d, 0x6d, 0x8f, 0x0c, 0x91,
+ 0x23, 0x40, 0xf9, 0xfc, 0xed, 0xab, 0x92, 0x77, 0x60, 0xd4, 0x05, 0xb5,
+ 0xaf, 0xe0, 0x13, 0x81, 0x6e, 0xef, 0x88, 0xe6, 0x40, 0xf7, 0x87, 0x0d,
+ 0x44, 0x8c, 0xec, 0x03, 0xf7, 0xe9, 0xf8, 0x8d, 0x74, 0x8c, 0x3b, 0x27,
+ 0xbf, 0xb9, 0x35, 0x63, 0xde, 0x97, 0xfd, 0xa3, 0x2f, 0x28, 0xa5, 0xf9,
+ 0x29, 0xa8, 0x69, 0xa4, 0xec, 0xa9, 0x6d, 0x93, 0x22, 0x96, 0xd8, 0xa6,
+ 0xf8, 0x16, 0x99, 0x35, 0x8f, 0x2b, 0xdb, 0x6c, 0x52, 0xb1, 0x25, 0x28,
+ 0xe5, 0x68, 0x41, 0x6f, 0x8c, 0xd0, 0x68, 0x6b, 0xb5, 0x13, 0x6f, 0x2d,
+ 0x1d, 0x95, 0x8e, 0x5b, 0xbe, 0xad, 0xda, 0x52, 0x42, 0x79, 0xd2, 0xc1,
+ 0xc3, 0x9e, 0x34, 0x4c, 0xcc, 0x35, 0x3a, 0xcc, 0x74, 0x96, 0x12, 0x8c,
+ 0x1c, 0x98, 0x32, 0x96, 0xb3, 0x92, 0xbc, 0x8e, 0xb6, 0x69, 0xeb, 0xac,
+ 0xd9, 0xd0, 0x45, 0xff, 0xe8, 0xa5, 0xd0, 0xb6, 0x76, 0x72, 0x36, 0xb5,
+ 0xca, 0x3d, 0xea, 0x28, 0x1e, 0x25, 0xde, 0x3b, 0x4e, 0x8c, 0xb8, 0x80,
+ 0x0d, 0x07, 0xd3, 0x1a, 0x9b, 0xfc, 0xe2, 0xe1, 0x54, 0x7f, 0xb0, 0x5e,
+ 0x0e, 0xec, 0x3e, 0xd2, 0x6c, 0xcd, 0xb9, 0xdd, 0xf6, 0xd4, 0xa6, 0x1d,
+ 0x84, 0x8e, 0xe0, 0xcd, 0xb0, 0x14, 0x6e, 0x23, 0x97, 0x87, 0xae, 0xd7,
+ 0x92, 0x23, 0x11, 0xe4, 0xad, 0xc9, 0xed, 0xc6, 0x37, 0x84, 0x76, 0x77,
+ 0xb4, 0x32, 0x7f, 0xc3, 0x20, 0x0a, 0xe7, 0x8e, 0xf1, 0xb9, 0x78, 0x95,
+ 0xf4, 0xa6, 0x09, 0xfb, 0xcb, 0xa8, 0xad, 0xf2, 0xd8, 0x1b, 0x03, 0x81,
+ 0xa9, 0x6f, 0x75, 0x00, 0x9f, 0xc3, 0xb5, 0xa5, 0x55, 0x1c, 0xf2, 0xe6,
+ 0x53, 0xc4, 0xce, 0x13, 0xa6, 0x12, 0x3b, 0x34, 0x89, 0x72, 0xd6, 0xe0,
+ 0x02, 0x27, 0xea, 0x8b, 0x8a, 0x0f, 0x54, 0xc6, 0xd4, 0x89, 0xdc, 0x5d,
+ 0x43, 0xeb, 0xa8, 0x60, 0x92, 0x0a, 0xac, 0xd5, 0x29, 0x20, 0xf7, 0x86,
+ 0x0f, 0xff, 0x25, 0xbf, 0xc6, 0xd8, 0x59, 0x6f, 0x9b, 0x48, 0x69, 0x15,
+ 0xab, 0x28, 0xdf, 0x9d, 0x05, 0x05, 0x79, 0x30, 0xbf, 0xdf, 0x44, 0x9a,
+ 0x1c, 0x9d, 0x19, 0x2e, 0xa3, 0x74, 0x64, 0x43, 0x49, 0x77, 0xd2, 0x42,
+ 0x68, 0xc4, 0x56, 0xfc, 0xf6, 0x91, 0x87, 0x46, 0x21, 0x1b, 0x7f, 0xeb,
+ 0x1b, 0x79, 0x6c, 0x94, 0x54, 0x6e, 0x1c, 0xca, 0x2b, 0x2c, 0xec, 0x59,
+ 0x7e, 0xaa, 0x74, 0xa8, 0xf0, 0xa4, 0x4d, 0x60, 0x23, 0x0b, 0xfb, 0xc4,
+ 0x74, 0x86, 0xca, 0x1a, 0x07, 0xfd, 0xa0, 0x30, 0xf3, 0xae, 0x08, 0x16,
+ 0xa0, 0x62, 0xdb, 0x63, 0xa0, 0xe4, 0x1e, 0xa5, 0xd4, 0x9d, 0x81, 0xde,
+ 0xf3, 0xa5, 0x7f, 0x39, 0xbc, 0xb2, 0xf6, 0x1f, 0x89, 0x25, 0x6e, 0x5a,
+ 0xbd, 0xa5, 0x37, 0x5b, 0x97, 0x55, 0x05, 0x20, 0x8f, 0x73, 0xdb, 0xcb,
+ 0x67, 0xf3, 0x5c, 0x34, 0x35, 0x09, 0x25, 0x36, 0xa5, 0x23, 0xaa, 0x3c,
+ 0x87, 0xeb, 0xce, 0xa3, 0xbc, 0x35, 0x87, 0x5c, 0x0c, 0x0a, 0x7a, 0x59,
+ 0x24, 0xd4, 0x37, 0x50, 0x21, 0xbb, 0xf1, 0xfb, 0x04, 0xc2, 0x72, 0x24,
+ 0x99, 0xc0, 0x9a, 0xca, 0x78, 0x12, 0x3e, 0x68, 0x38, 0x0f, 0xee, 0xd3,
+ 0xd6, 0x77, 0xb2, 0x84, 0xaf, 0xf1, 0x90, 0x58, 0x09, 0x55, 0xb4, 0xfa,
+ 0xfa, 0x1f, 0x2b, 0x4d, 0x36, 0x5e, 0x45, 0x34, 0xc5, 0x32, 0x17, 0x6e,
+ 0xc6, 0x8d, 0x0b, 0x3d, 0xb0, 0x82, 0x14, 0xad, 0x9f, 0x9c, 0x1b, 0xf2,
+ 0x8b, 0xb5, 0x01, 0x82, 0x27, 0x4e, 0xc4, 0x80, 0xd8, 0xb5, 0x5d, 0x87,
+ 0xc6, 0x87, 0x5f, 0xec, 0x21, 0xd0, 0x9d, 0x56, 0x93, 0xf6, 0xa0, 0xb1,
+ 0x2a, 0x03, 0x7f, 0xf6, 0x81, 0xd7, 0x8c, 0x70, 0x6f, 0xb8, 0x2d, 0xaf,
+ 0xf3, 0xa0, 0x72, 0x48, 0x20, 0x35, 0x6b, 0x5c, 0x10, 0x18, 0xb7, 0xa1,
+ 0xd3, 0x17, 0xa2, 0x8a, 0xce, 0x11, 0xf0, 0x0e, 0x07, 0xed, 0x4e, 0xc9,
+ 0x48, 0xcb, 0x8b, 0xf0, 0xdd, 0x23, 0x2d, 0xbb, 0x29, 0xcd, 0x55, 0x17,
+ 0x74, 0x16, 0x98, 0x27, 0xf8, 0x92, 0x30, 0x30, 0x02, 0xb8, 0x06, 0x04,
+ 0x94, 0x4a, 0x2c, 0xd2, 0xf3, 0x67, 0x4a, 0x50, 0xc7, 0xf6, 0x72, 0xb8,
+ 0x40, 0x7a, 0xed, 0x88, 0x7d, 0x15, 0x80, 0x8f, 0x20, 0x76, 0x0d, 0x26,
+ 0x15, 0x58, 0x4c, 0xc1, 0xdb, 0x98, 0xca, 0xb0, 0x11, 0x23, 0x08, 0xa3,
+ 0x70, 0x5e, 0x17, 0xe5, 0x73, 0xaf, 0xe7, 0x21, 0x8c, 0x14, 0x4b, 0xe7,
+ 0x2e, 0xce, 0xe4, 0xd5, 0x5b, 0xed, 0x37, 0xba, 0x6c, 0x23, 0x97, 0xce,
+ 0x1b, 0x30, 0x76, 0xed, 0xab, 0x8c, 0x8e, 0x86, 0x07, 0x83, 0x83, 0xe3,
+ 0x3d, 0x1f, 0x6c, 0x93, 0xd6, 0xec, 0x8a, 0xa5, 0x10, 0xc7, 0x73, 0x89,
+ 0x25, 0xb8, 0x25, 0x9a, 0x3f, 0x6b, 0xbd, 0xcd, 0xb6, 0x21, 0x76, 0x25,
+ 0x3b, 0x58, 0x85, 0xbb, 0xb4, 0xbd, 0x31, 0xa2, 0x5f, 0x2b, 0x1e, 0x66,
+ 0x8f, 0x76, 0xc7, 0x03, 0xcd, 0x51, 0x82, 0x3d, 0xea, 0xe9, 0x32, 0x98,
+ 0xe8, 0xf5, 0x80, 0xf3, 0x11, 0xd4, 0x47, 0x9f, 0xa8, 0x9b, 0x21, 0x11,
+ 0xd8, 0x00, 0x35, 0xd1, 0xb9, 0xeb, 0x0a, 0x74, 0xba, 0xd1, 0x52, 0x8e,
+ 0xdf, 0x1f, 0xb5, 0x21, 0xdc, 0x09, 0xc8, 0x96, 0x6b, 0x6e, 0x8b, 0x4f,
+ 0xd4, 0x49, 0xeb, 0x76, 0x44, 0x7f, 0xb0, 0x7e, 0x7e, 0x51, 0x16, 0x96,
+ 0x83, 0x82, 0xca, 0x2d, 0xb1, 0x77, 0xa3, 0xd3, 0x77, 0x62, 0x4e, 0x12,
+ 0x45, 0x63, 0xa4, 0x0c, 0xbd, 0x35, 0xdb, 0xe3, 0x3e, 0x3a, 0xff, 0x72,
+ 0xb2, 0x7e, 0xba, 0x1e, 0x7f, 0x39, 0x89, 0x84, 0x16, 0x28, 0x86, 0xe8,
+ 0xdd, 0x34, 0x17, 0xda, 0xdd, 0x56, 0x6b, 0xbb, 0x61, 0xb4, 0x57, 0xad,
+ 0x67, 0x38, 0x55, 0x29, 0xa7, 0xaa, 0x5d, 0x0e, 0x24, 0xb7, 0xee, 0x0b,
+ 0x26, 0x09, 0xba, 0xe7, 0x4b, 0xad, 0x6b, 0x4c, 0xb1, 0x13, 0x0a, 0xf3,
+ 0x59, 0x07, 0x82, 0xfb, 0xf4, 0x87, 0x26, 0x57, 0xd8, 0x6f, 0x31, 0x96,
+ 0xd7, 0xb8, 0xa1, 0x7b, 0xc6, 0x4b, 0x3a, 0xf4, 0x4b, 0x72, 0x74, 0xbf,
+ 0xb1, 0x98, 0xa1, 0x76, 0xee, 0x32, 0xbe, 0xc3, 0x8d, 0xdc, 0x48, 0x5b,
+ 0x35, 0x1a, 0x9e, 0xa1, 0xa5, 0x93, 0xb3, 0x36, 0xc2, 0x87, 0x80, 0x86,
+ 0xb5, 0xf0, 0x0e, 0xd1, 0x8a, 0xf6, 0x03, 0x8c, 0x8a, 0x27, 0xdd, 0x06,
+ 0x26, 0x77, 0xdc, 0x4b, 0xd7, 0x6e, 0x96, 0x6b, 0xc1, 0xd1, 0x09, 0x66,
+ 0x59, 0x6b, 0xae, 0x96, 0x96, 0x5f, 0xad, 0x41, 0xf6, 0x44, 0x87, 0x13,
+ 0xdf, 0x49, 0xfa, 0xca, 0x0e, 0xe8, 0xc3, 0xad, 0xbc, 0xfa, 0x60, 0x3f,
+ 0xf5, 0x2e, 0xaf, 0xea, 0x01, 0xef, 0x6e, 0xaf, 0x85, 0xc6, 0x6d, 0x74,
+ 0xfe, 0x74, 0x12, 0x39, 0x04, 0x5a, 0x07, 0x54, 0x6d, 0x48, 0x10, 0xc9,
+ 0x0d, 0x6c, 0x99, 0xc1, 0x75, 0x78, 0x08, 0xb4, 0xe8, 0x86, 0x7a, 0xe7,
+ 0x48, 0x55, 0xc9, 0xe7, 0x22, 0xf0, 0x22, 0x35, 0x66, 0x44, 0xb3, 0x7c,
+ 0x6a, 0x2b, 0x58, 0xc7, 0xa3, 0x2f, 0x82, 0x16, 0xd9, 0xf9, 0x36, 0x53,
+ 0x9d, 0x83, 0x8d, 0x2d, 0xee, 0x79, 0x98, 0x86, 0xad, 0x8b, 0xd4, 0xc5,
+ 0x5d, 0x48, 0x38, 0xae, 0xd9, 0xd3, 0x6e, 0x4c, 0x15, 0xbc, 0xbe, 0x22,
+ 0x92, 0x2d, 0x2c, 0xdd, 0xa2, 0x18, 0x65, 0x9d, 0xe9, 0xe0, 0x6d, 0x4b,
+ 0xfe, 0xc0, 0x35, 0x5b, 0x0e, 0xe4, 0xea, 0x0b, 0x49, 0xb9, 0x90, 0x71,
+ 0x10, 0xc6, 0x57, 0xfe, 0x95, 0x81, 0xbc, 0xb5, 0x92, 0x16, 0xf6, 0xec,
+ 0x7c, 0xe7, 0xfa, 0x32, 0xf3, 0x1d, 0xb0, 0x83, 0x27, 0x5d, 0x6c, 0x74,
+ 0x84, 0x03, 0xb3, 0xfd, 0x56, 0x5e, 0x67, 0xfa, 0x8f, 0xab, 0xaa, 0x59,
+ 0x92, 0x4d, 0x65, 0x5a, 0xdd, 0x56, 0x04, 0x84, 0x32, 0xe8, 0xe3, 0x41,
+ 0xef, 0x6b, 0x4c, 0xd1, 0xe7, 0xa4, 0xe8, 0x70, 0x48, 0x3d, 0xed, 0x5a,
+ 0x5f, 0x8f, 0x88, 0xd4, 0x54, 0x1b, 0x7d, 0xc8, 0x25, 0x7a, 0x85, 0x0d,
+ 0x4e, 0xd1, 0xd2, 0x0f, 0xdf, 0x12, 0x10, 0xb6, 0xc9, 0x73, 0x40, 0xbc,
+ 0x08, 0x72, 0xb4, 0xf6, 0x86, 0xbe, 0x8e, 0x60, 0x31, 0xe7, 0xd1, 0xcb,
+ 0x40, 0xc8, 0x4f, 0xf0, 0xb4, 0x4d, 0x49, 0x5d, 0xfa, 0x40, 0xfc, 0xd2,
+ 0x1d, 0x78, 0x83, 0x3f, 0xf4, 0x12, 0xed, 0x9e, 0x3f, 0x1d, 0xef, 0x45,
+ 0xdd, 0x61, 0xd6, 0x30, 0x8e, 0xb0, 0x42, 0xb8, 0xbf, 0x54, 0x9d, 0xbb,
+ 0x2d, 0xac, 0x1d, 0x08, 0x89, 0xee, 0x96, 0x93, 0x9f, 0x68, 0x6b, 0x2e,
+ 0xa9, 0xd7, 0x67, 0x90, 0xb1, 0xad, 0xb6, 0xb4, 0x37, 0x92, 0x4c, 0x39,
+ 0x99, 0xaa, 0x81, 0x48, 0xe0, 0x26, 0x1b, 0xed, 0xb7, 0xe0, 0xa0, 0xc1,
+ 0x61, 0x7d, 0x83, 0x79, 0x18, 0x39, 0xf2, 0xa3, 0xf3, 0x70, 0xf8, 0x62,
+ 0x38, 0x7e, 0x59, 0x22, 0x06, 0x50, 0x2e, 0xf5, 0x87, 0x66, 0xb9, 0x4c,
+ 0x5d, 0xa6, 0x06, 0x0d, 0x56, 0xee, 0x66, 0x21, 0x7c, 0x7f, 0x0e, 0x84,
+ 0x71, 0x0c, 0x84, 0x21, 0x69, 0x96, 0xa1, 0xfa, 0x9e, 0x52, 0x13, 0xed,
+ 0xd7, 0xad, 0x74, 0xe9, 0xc0, 0x59, 0x96, 0xc1, 0xf9, 0xfe, 0x0e, 0x2e,
+ 0x54, 0x64, 0x48, 0x8e, 0x7c, 0x16, 0xb1, 0xf2, 0x47, 0x64, 0x8b, 0xce,
+ 0x39, 0xf7, 0xe1, 0x8b, 0x05, 0x82, 0x62, 0x61, 0x8a, 0x0e, 0x87, 0xe2,
+ 0xc6, 0x22, 0x45, 0x79, 0x79, 0x83, 0x89, 0x34, 0x34, 0xbe, 0xe6, 0x0f,
+ 0x0b, 0x03, 0x8c, 0xf8, 0x76, 0xa7, 0x87, 0x65, 0x82, 0x88, 0xeb, 0xfc,
+ 0xb8, 0xa7, 0x67, 0x09, 0x6c, 0xf7, 0xee, 0x36, 0xe1, 0xa7, 0x41, 0x1c,
+ 0xec, 0x45, 0xf6, 0x85, 0x1a, 0x8f, 0x89, 0x30, 0x4e, 0xc4, 0x3c, 0x2e,
+ 0xc3, 0x0e, 0xbf, 0x68, 0xf7, 0x6a, 0xb3, 0x6f, 0xf9, 0xeb, 0x74, 0x75,
+ 0xf6, 0x6e, 0x4c, 0xd0, 0xcf, 0xb1, 0xeb, 0xab, 0x61, 0xe0, 0x51, 0xb9,
+ 0x68, 0xab, 0x6b, 0x67, 0x89, 0xa3, 0x52, 0xe1, 0x31, 0x62, 0x8f, 0xde,
+ 0xcf, 0x54, 0xe4, 0x0f, 0x1a, 0x7e, 0xe1, 0xcb, 0x25, 0x73, 0x2b, 0x27,
+ 0x15, 0x89, 0x0f, 0xdb, 0xfa, 0x39, 0x50, 0xf7, 0x24, 0x3a, 0x7d, 0xe7,
+ 0x16, 0x9b, 0x8c, 0x0e, 0x1a, 0x4f, 0x32, 0x57, 0xd3, 0xb1, 0x14, 0x5a,
+ 0xef, 0x22, 0xce, 0xe6, 0xdc, 0xfa, 0x8e, 0x25, 0xc9, 0xee, 0xa6, 0x72,
+ 0xde, 0xb3, 0xcd, 0x27, 0xc2, 0x78, 0x70, 0xa8, 0xe3, 0x6c, 0x25, 0x0f,
+ 0x37, 0x7a, 0x75, 0xe3, 0xa0, 0x24, 0x73, 0x63, 0xa0, 0x20, 0x7a, 0x6d,
+ 0x13, 0x6d, 0x82, 0xce, 0x80, 0x12, 0xfd, 0x01, 0xbc, 0xd6, 0x28, 0x0c,
+ 0xad, 0x9b, 0x16, 0x9e, 0x73, 0x69, 0x55, 0x3b, 0x39, 0xd1, 0x34, 0xad,
+ 0x82, 0x17, 0x48, 0xec, 0xa2, 0x18, 0xb9, 0x4c, 0x9a, 0x28, 0x82, 0x76,
+ 0x09, 0x9a, 0x3d, 0x27, 0x56, 0x55, 0x87, 0xdb, 0x24, 0x4c, 0x91, 0xbb,
+ 0x4e, 0x48, 0x8e, 0xef, 0x26, 0xdb, 0x0c, 0xcb, 0xa7, 0x6b, 0x60, 0x44,
+ 0x69, 0x77, 0xd8, 0x65, 0x01, 0xcf, 0x01, 0x42, 0xf9, 0x9e, 0x6a, 0x40,
+ 0xd1, 0x87, 0x2f, 0x81, 0x13, 0x2e, 0x40, 0x0f, 0x02, 0x54, 0xc4, 0xa7,
+ 0xb0, 0x3b, 0x2a, 0x45, 0xcc, 0x1d, 0x71, 0xb4, 0x12, 0x7b, 0xba, 0xe5,
+ 0x73, 0xf7, 0x7d, 0x38, 0x00, 0xe3, 0x71, 0xf8, 0x1a, 0x50, 0x15, 0x63,
+ 0xb4, 0x87, 0x62, 0x1b, 0x5b, 0x72, 0x9c, 0x92, 0x8b, 0xe1, 0x04, 0xf2,
+ 0xc9, 0x0c, 0x5f, 0x84, 0x97, 0x99, 0xe4, 0x9a, 0x5f, 0x75, 0xe9, 0x9a,
+ 0x38, 0xb7, 0x5e, 0x1e, 0x80, 0xb2, 0xec, 0x46, 0x9f, 0xc1, 0x52, 0x7e,
+ 0x4e, 0xeb, 0xda, 0x30, 0xb1, 0xce, 0x60, 0x4a, 0x64, 0xe5, 0xb0, 0x5e,
+ 0x3b, 0x96, 0x84, 0xb5, 0xbc, 0x09, 0x4d, 0x1a, 0x3a, 0xd1, 0x8b, 0xb4,
+ 0xed, 0xbb, 0x12, 0xf1, 0x51, 0x79, 0x9d, 0x4e, 0x70, 0x4c, 0x0a, 0x5d,
+ 0x0f, 0x5b, 0x71, 0x42, 0xbd, 0xce, 0x49, 0x82, 0xd3, 0xfc, 0xdd, 0xfc,
+ 0xcb, 0x46, 0x0f, 0x5f, 0x59, 0xca, 0x85, 0xb1, 0xfe, 0x59, 0xcf, 0x96,
+ 0x5d, 0x9f, 0x7f, 0xa3, 0x7b, 0xf8, 0xf6, 0x3e, 0xf8, 0xaf, 0xc7, 0x85,
+ 0x7a, 0xef, 0xce, 0xe0, 0x17, 0xf0, 0x66, 0xe0, 0x3b, 0xfc, 0x83, 0x52,
+ 0xf7, 0xa7, 0xe1, 0x65, 0x50, 0x4f, 0xf0, 0x2d, 0x7c, 0x7b, 0x0d, 0xff,
+ 0x93, 0xa7, 0xd3, 0xd7, 0xbd, 0x9f, 0xe4, 0xbd, 0xaf, 0xd8, 0x06, 0x9b,
+ 0x71, 0x5e, 0xf5, 0x7b, 0x94, 0xec, 0x76, 0xaf, 0xe2, 0xfe, 0xa1, 0x68,
+ 0x4a, 0xb0, 0x93, 0xfb, 0xea, 0xb6, 0xc8, 0x86, 0x7a, 0x7c, 0xdc, 0xd7,
+ 0xab, 0xd5, 0x78, 0xff, 0x70, 0x30, 0x3e, 0x98, 0xf4, 0xf5, 0xf8, 0xf9,
+ 0xb1, 0xbc, 0x57, 0xbb, 0x35, 0xf5, 0x84, 0xa6, 0xfe, 0x01, 0x26, 0x7a,
+ 0x83, 0xd3, 0x33, 0x6a, 0xfa, 0x34, 0x2e, 0xe8, 0xb7, 0xfc, 0xc6, 0x65,
+ 0x65, 0x29, 0x74, 0x81, 0x46, 0x36, 0x6d, 0xf7, 0x92, 0xdf, 0x11, 0x3e,
+ 0x54, 0xe7, 0x05, 0x88, 0xf5, 0xfc, 0x85, 0x3e, 0x99, 0xc5, 0x89, 0x59,
+ 0x82, 0x43, 0xf9, 0x9e, 0x5b, 0xaa, 0xc1, 0x74, 0xc7, 0x5b, 0xa6, 0xdb,
+ 0x77, 0xd3, 0x9d, 0xc3, 0xff, 0xc1, 0x0b, 0x8c, 0xde, 0xc2, 0xd7, 0x77,
+ 0xf0, 0xbf, 0x7d, 0x91, 0x51, 0x4f, 0x5e, 0x17, 0x8e, 0x9e, 0x41, 0x06,
+ 0x16, 0x87, 0xf1, 0x6f, 0xa1, 0x56, 0xbe, 0x19, 0x28, 0x23, 0xe0, 0x87,
+ 0xa1, 0xf6, 0xaf, 0x23, 0xa7, 0x97, 0x96, 0xe3, 0xbb, 0xc0, 0x87, 0x16,
+ 0x0f, 0xcf, 0x08, 0x0f, 0x07, 0xfb, 0x83, 0xf1, 0xe1, 0x01, 0x01, 0xf6,
+ 0x3c, 0x04, 0x6c, 0xc2, 0x80, 0x1d, 0x38, 0xc0, 0xbe, 0x47, 0xc0, 0x28,
+ 0x00, 0x03, 0x50, 0x9c, 0x06, 0x9a, 0x5c, 0x5e, 0x8c, 0x0b, 0x93, 0xba,
+ 0x17, 0x8a, 0x5f, 0x50, 0xcc, 0xb4, 0xaf, 0x9f, 0x4d, 0xbe, 0x1c, 0x8f,
+ 0x46, 0x5f, 0x8e, 0x9f, 0xf7, 0x55, 0xeb, 0x35, 0xe9, 0x7a, 0xf3, 0x35,
+ 0xe9, 0x0f, 0xbc, 0x22, 0xfd, 0x87, 0x06, 0x24, 0xca, 0xf8, 0xf9, 0xb3,
+ 0x49, 0x08, 0xdb, 0x3e, 0xc3, 0x76, 0xb8, 0x1d, 0xb6, 0x8b, 0x6e, 0x3c,
+ 0x88, 0xd2, 0x26, 0x8f, 0xbc, 0xa8, 0xcf, 0x1e, 0x4b, 0x91, 0x57, 0x97,
+ 0x52, 0xc0, 0x46, 0x1c, 0xdb, 0x7e, 0x4f, 0x3f, 0xb0, 0x2a, 0x90, 0xbe,
+ 0x07, 0xff, 0xf2, 0xaa, 0x3e, 0x98, 0x55, 0xcd, 0xf5, 0xe7, 0xdd, 0xa5,
+ 0x1d, 0xf2, 0xd2, 0x8e, 0x64, 0x69, 0xfa, 0x64, 0xa8, 0xc3, 0xb7, 0x5d,
+ 0xc2, 0x2f, 0x17, 0x43, 0x7c, 0xe7, 0x25, 0xef, 0x01, 0x4f, 0x9c, 0xeb,
+ 0x6f, 0x30, 0xed, 0x0f, 0x0e, 0xd3, 0x07, 0x79, 0x41, 0xfa, 0x07, 0x79,
+ 0xe3, 0x09, 0x70, 0xb7, 0xd4, 0x77, 0x58, 0x9e, 0x38, 0x39, 0x7d, 0x6b,
+ 0xf7, 0xff, 0x08, 0xf6, 0xff, 0x78, 0xb4, 0x4f, 0x5b, 0xbf, 0x1f, 0xc2,
+ 0x70, 0xcc, 0x30, 0x1c, 0x13, 0x0c, 0xdf, 0x0f, 0x81, 0xe5, 0xf8, 0xd5,
+ 0x59, 0x30, 0xa7, 0x6d, 0x36, 0xdf, 0x25, 0x35, 0x74, 0xaa, 0x1e, 0xe2,
+ 0x37, 0xa2, 0xb3, 0xc9, 0xd1, 0xe1, 0x60, 0x72, 0xfc, 0x8c, 0x26, 0x3b,
+ 0xdc, 0x32, 0xd9, 0x33, 0x9a, 0xac, 0xc3, 0xdc, 0x6e, 0x68, 0x39, 0x86,
+ 0xec, 0x5e, 0x4d, 0x0d, 0x1b, 0x77, 0x5d, 0xc6, 0xa4, 0x1e, 0x5e, 0x7c,
+ 0x28, 0xf8, 0x75, 0x22, 0x14, 0xd1, 0xf5, 0xad, 0x9d, 0x3e, 0x15, 0x19,
+ 0x07, 0x3c, 0x2f, 0x0c, 0x25, 0xcf, 0xfb, 0xfa, 0x2d, 0xb0, 0x0b, 0xb0,
+ 0x67, 0x83, 0x6d, 0x08, 0x2b, 0xe0, 0xcc, 0x04, 0x84, 0x1c, 0xe0, 0xee,
+ 0x67, 0x53, 0x65, 0xd8, 0xdc, 0xb2, 0x8b, 0x85, 0x67, 0x0c, 0xd8, 0x73,
+ 0x02, 0xec, 0x13, 0x00, 0xf5, 0x1f, 0xc8, 0x9d, 0xf8, 0xb6, 0xb0, 0xde,
+ 0xf7, 0x92, 0x53, 0xd9, 0xf6, 0xf6, 0x79, 0xf1, 0x43, 0x07, 0x75, 0x31,
+ 0xb0, 0x67, 0xea, 0xfd, 0xab, 0xe8, 0xe4, 0xdd, 0x31, 0xd4, 0x6f, 0x37,
+ 0x78, 0x2f, 0x6b, 0x6c, 0x5f, 0x4a, 0x3f, 0xe7, 0x96, 0x2a, 0x39, 0x06,
+ 0x52, 0x1f, 0xd8, 0xb1, 0xd5, 0xd1, 0x68, 0x7f, 0x70, 0x34, 0x9e, 0x6c,
+ 0x02, 0x3c, 0x16, 0x96, 0x1d, 0x8f, 0x36, 0x40, 0xbe, 0xd4, 0xef, 0xe1,
+ 0xd3, 0x07, 0xf8, 0xff, 0x23, 0xfe, 0x6a, 0xdf, 0x76, 0x86, 0xc2, 0x85,
+ 0xdf, 0x78, 0xd6, 0xfb, 0xb1, 0x05, 0x72, 0x17, 0x62, 0xff, 0x06, 0xd1,
+ 0x2d, 0x50, 0x1d, 0xd0, 0xfe, 0x4e, 0x9e, 0x0d, 0x26, 0xfb, 0xcf, 0x09,
+ 0xaa, 0x71, 0x0b, 0x2a, 0x61, 0xd6, 0x31, 0x0b, 0xf3, 0x9f, 0x89, 0x9c,
+ 0x82, 0xe6, 0xc4, 0x1f, 0x87, 0x48, 0x62, 0xd4, 0xa2, 0x58, 0xe8, 0x4b,
+ 0x22, 0xb0, 0x82, 0xa5, 0x40, 0x98, 0x0f, 0xc1, 0x00, 0x2f, 0x6f, 0xf1,
+ 0x75, 0x48, 0x3c, 0x33, 0x09, 0x72, 0x10, 0xe3, 0xcf, 0x1d, 0x55, 0x71,
+ 0x1d, 0x35, 0x68, 0xd9, 0x11, 0xf6, 0x87, 0x83, 0xbf, 0x97, 0xff, 0x7e,
+ 0x09, 0x54, 0x74, 0xf1, 0xdd, 0xb6, 0x06, 0x71, 0x0f, 0xfd, 0x43, 0xe7,
+ 0x80, 0xb0, 0xf2, 0x9b, 0xda, 0xb2, 0xed, 0x60, 0xf5, 0xf7, 0x0e, 0x1e,
+ 0x49, 0xd9, 0xa1, 0xc6, 0x79, 0x6a, 0xe7, 0x32, 0x7b, 0xb2, 0x0f, 0x23,
+ 0x3d, 0xa1, 0x3a, 0x53, 0xb5, 0x33, 0x9e, 0xec, 0x5c, 0x8e, 0x2e, 0xf5,
+ 0x60, 0xbc, 0x43, 0x7f, 0x46, 0x3b, 0x63, 0x3e, 0xf0, 0x3e, 0x1e, 0xef,
+ 0x8c, 0x47, 0xf0, 0xe3, 0x28, 0xfc, 0x6d, 0x04, 0xdf, 0x9f, 0x1d, 0xc3,
+ 0x9f, 0xe3, 0x9d, 0xb1, 0xfd, 0xf1, 0x72, 0xf4, 0x1c, 0x7f, 0x38, 0x82,
+ 0x3f, 0x47, 0x70, 0xeb, 0xc8, 0xfe, 0xfa, 0x0c, 0x7f, 0x3d, 0x84, 0x3f,
+ 0x87, 0xe1, 0xbd, 0xf8, 0xf0, 0x91, 0x1d, 0x61, 0xa4, 0xa5, 0x41, 0x0a,
+ 0x3d, 0x0b, 0xff, 0xf3, 0x20, 0x63, 0x3f, 0x08, 0x3e, 0x7f, 0xc4, 0x83,
+ 0x8c, 0xfc, 0x20, 0x07, 0xf8, 0x3f, 0xc1, 0xa6, 0xfe, 0x2f, 0x79, 0xdc,
+ 0xcf, 0x16, 0x75, 0x86, 0x00, 0x00
+};
+unsigned int paper6_12K_compressed_gz_len = 12306;
diff --git a/drivers/staging/fsl_dce/tests/common/paper6_2K_compressed.gz.h b/drivers/staging/fsl_dce/tests/common/paper6_2K_compressed.gz.h
new file mode 100644
index 0000000..65cd86d5
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/common/paper6_2K_compressed.gz.h
@@ -0,0 +1,173 @@
+unsigned char paper6_2K_compressed_gz[] = {
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x7d, 0x57,
+ 0x5d, 0x6f, 0xdb, 0x38, 0x16, 0x7d, 0x5e, 0xfe, 0x8a, 0x8b, 0xa0, 0x80,
+ 0x53, 0xc0, 0x11, 0xe2, 0xf4, 0x63, 0x67, 0x17, 0x83, 0x2d, 0x9c, 0x34,
+ 0xd3, 0x78, 0xf3, 0xd1, 0x6e, 0xe2, 0xd9, 0x5d, 0x20, 0xce, 0x03, 0x25,
+ 0xd1, 0x36, 0xb7, 0x94, 0xa8, 0x21, 0xa9, 0xb8, 0x9e, 0x87, 0xfe, 0xf6,
+ 0x3d, 0x97, 0x94, 0xe4, 0x38, 0x29, 0xfa, 0x62, 0x30, 0xbc, 0xd4, 0xe5,
+ 0xfd, 0x38, 0xe7, 0x5c, 0x26, 0x3b, 0xff, 0x97, 0x28, 0x95, 0xd1, 0x15,
+ 0xbd, 0x7a, 0x85, 0xc5, 0x52, 0xd7, 0x8a, 0x7e, 0x3d, 0xa2, 0x0f, 0xbf,
+ 0xd2, 0xc1, 0x62, 0x3d, 0x3a, 0x3a, 0xce, 0xde, 0x55, 0xa3, 0x03, 0x6a,
+ 0x1b, 0x9a, 0x1c, 0x63, 0xe7, 0x50, 0x55, 0x07, 0x54, 0xda, 0x4d, 0xcd,
+ 0x7f, 0x7e, 0xe8, 0xcf, 0xaf, 0x82, 0x75, 0xa5, 0x72, 0xf4, 0xe1, 0x60,
+ 0xf1, 0xe7, 0x3f, 0x16, 0xe5, 0xe2, 0xfb, 0xa2, 0x3d, 0x18, 0x8c, 0xe7,
+ 0xff, 0x9d, 0xdd, 0xcd, 0xa3, 0x69, 0x71, 0x04, 0x1b, 0xff, 0xba, 0xb8,
+ 0x7a, 0x1c, 0x1d, 0x67, 0x27, 0xd5, 0x68, 0x71, 0x98, 0x3b, 0xac, 0x8f,
+ 0xe2, 0x1f, 0xbb, 0xcf, 0xa6, 0x57, 0x57, 0xfc, 0x91, 0x1d, 0xfd, 0xfb,
+ 0xe8, 0xc9, 0xee, 0xf1, 0x35, 0x8d, 0x8e, 0xbf, 0x67, 0x59, 0xf6, 0xfd,
+ 0xfa, 0x68, 0x32, 0xea, 0x77, 0xaf, 0x2e, 0x68, 0x64, 0x6c, 0xdc, 0x5e,
+ 0xeb, 0x61, 0xf7, 0xf6, 0x96, 0x46, 0xb9, 0x35, 0x25, 0xdd, 0x0e, 0x5b,
+ 0x17, 0x17, 0xdd, 0xd6, 0xc5, 0xb0, 0x75, 0x79, 0xd9, 0x6d, 0x5d, 0x0e,
+ 0x5b, 0xd6, 0xd1, 0xe8, 0x60, 0xb1, 0x3c, 0xb5, 0x6e, 0xb1, 0x9c, 0x1d,
+ 0x7c, 0x1f, 0xf6, 0x65, 0x5d, 0x26, 0x03, 0x16, 0xfb, 0x16, 0xbd, 0x4c,
+ 0x06, 0xbd, 0xdc, 0xdf, 0x0f, 0x6b, 0x55, 0x27, 0x0b, 0xaf, 0xf6, 0x6d,
+ 0xca, 0x78, 0x95, 0x6c, 0xbc, 0xda, 0xb7, 0x39, 0xd5, 0x28, 0x19, 0x92,
+ 0x35, 0xad, 0xf7, 0xed, 0x6d, 0x1d, 0xb4, 0x49, 0xe6, 0xb8, 0xdc, 0xb7,
+ 0x6e, 0xd6, 0xda, 0x74, 0xae, 0xe3, 0x72, 0xdf, 0x5a, 0xda, 0x64, 0x2a,
+ 0xed, 0xfe, 0x7e, 0x21, 0xfb, 0x78, 0x78, 0xf5, 0x2c, 0xd6, 0x3e, 0x73,
+ 0xf5, 0x3c, 0xf3, 0x5c, 0xad, 0x74, 0x97, 0x62, 0x5c, 0xbe, 0xcc, 0xb1,
+ 0xaf, 0x4d, 0x5a, 0x27, 0x3b, 0xf5, 0x07, 0x96, 0x7d, 0xad, 0x97, 0xcf,
+ 0x8b, 0xfd, 0x9b, 0xb3, 0x55, 0x67, 0xc2, 0x6a, 0xdf, 0x36, 0xef, 0x52,
+ 0x08, 0xcf, 0x52, 0x50, 0xdf, 0x74, 0x57, 0x34, 0x5e, 0x75, 0xb6, 0xec,
+ 0xfc, 0x46, 0x64, 0xc6, 0xd3, 0xe4, 0x2f, 0x22, 0x2b, 0x94, 0x38, 0xfb,
+ 0x7c, 0xfd, 0x65, 0x7a, 0x36, 0xa7, 0x8b, 0xe9, 0xdd, 0x05, 0xcd, 0xa7,
+ 0xa7, 0x57, 0xe7, 0x77, 0xf4, 0xfb, 0xdd, 0xec, 0xe6, 0x13, 0x9d, 0xce,
+ 0x3e, 0xce, 0x6e, 0xcf, 0xcf, 0xe6, 0xb3, 0xcf, 0x37, 0xd3, 0x2b, 0xba,
+ 0x9a, 0xdd, 0x9c, 0x4f, 0x6f, 0xe9, 0xcb, 0xed, 0xe7, 0x53, 0x18, 0x45,
+ 0xe6, 0x1b, 0x7a, 0x13, 0x1d, 0xfc, 0xd3, 0xae, 0x6b, 0xfa, 0x94, 0xd1,
+ 0x99, 0x51, 0xd2, 0x6d, 0xe3, 0xd6, 0x7c, 0xad, 0xe8, 0xf7, 0x5a, 0x3f,
+ 0x2a, 0xe7, 0x75, 0xd8, 0x92, 0x5d, 0xd2, 0x99, 0x34, 0x2b, 0x58, 0xc7,
+ 0x34, 0x35, 0xb9, 0x72, 0x41, 0x8e, 0xb1, 0x53, 0xcb, 0x52, 0x66, 0xbd,
+ 0x23, 0xfc, 0x9e, 0x1c, 0x8b, 0x45, 0x3b, 0x59, 0x94, 0xd3, 0x36, 0xac,
+ 0xad, 0xf3, 0xf4, 0xc5, 0x29, 0xaf, 0xea, 0x40, 0xd3, 0xb2, 0xc4, 0xca,
+ 0xff, 0x9d, 0xae, 0x65, 0x7d, 0x74, 0x2d, 0x8b, 0x35, 0xa7, 0x76, 0xb7,
+ 0xf5, 0x41, 0x55, 0x9e, 0x3e, 0x39, 0xdb, 0x36, 0x63, 0xfa, 0xa8, 0x1a,
+ 0xe9, 0x42, 0xc5, 0xc7, 0xed, 0x52, 0x9c, 0xd9, 0xaa, 0x69, 0x03, 0x08,
+ 0x78, 0x57, 0x68, 0x55, 0x17, 0x6a, 0x4c, 0x3f, 0x89, 0xe8, 0xe4, 0xdd,
+ 0xf1, 0xf1, 0x53, 0xdb, 0x47, 0x87, 0x25, 0xdd, 0xfc, 0x47, 0x0c, 0x27,
+ 0x52, 0xa8, 0x34, 0x3f, 0xb9, 0xa1, 0xc9, 0xcd, 0xdb, 0x18, 0x32, 0x22,
+ 0x3d, 0x59, 0x94, 0xf3, 0xb5, 0xf6, 0xc4, 0x51, 0x4a, 0x57, 0xac, 0x69,
+ 0x23, 0x3d, 0xf9, 0xb6, 0x69, 0xac, 0x0b, 0xaa, 0xa4, 0x7c, 0x2b, 0x80,
+ 0x71, 0xba, 0x91, 0xa1, 0x75, 0xd2, 0xf4, 0x91, 0xf8, 0x48, 0x9a, 0xf3,
+ 0x1a, 0xc8, 0x50, 0xca, 0xe9, 0x7a, 0x45, 0xb7, 0xfd, 0xe7, 0x67, 0xb6,
+ 0xad, 0x0b, 0xa0, 0x38, 0xc6, 0xb6, 0xab, 0xcd, 0x49, 0x6c, 0x16, 0x7e,
+ 0xf3, 0x46, 0xcc, 0xea, 0x52, 0x7d, 0xa3, 0xb9, 0x72, 0x48, 0xfc, 0xe8,
+ 0x88, 0xe8, 0x2e, 0x7e, 0x09, 0x2f, 0x63, 0x5a, 0x4b, 0xbf, 0x26, 0x0f,
+ 0xdd, 0x91, 0x2b, 0xa4, 0x6b, 0x1b, 0xf0, 0x4c, 0xa6, 0xba, 0x45, 0xb3,
+ 0xc8, 0x75, 0xa9, 0x9d, 0x2a, 0x82, 0xb6, 0x35, 0xa2, 0x31, 0xb8, 0x5e,
+ 0x3a, 0x6a, 0x9c, 0xcd, 0xd9, 0x2c, 0xba, 0xa3, 0xc0, 0xbc, 0x29, 0x5a,
+ 0x23, 0xf9, 0xd4, 0x98, 0x74, 0x0d, 0x10, 0x56, 0xf1, 0x0f, 0x24, 0x19,
+ 0x9c, 0x56, 0x8f, 0xd2, 0x8c, 0xc9, 0x17, 0x32, 0x70, 0x6d, 0x87, 0xcb,
+ 0x44, 0xa3, 0x5c, 0x3c, 0x89, 0xfc, 0x90, 0x9e, 0x34, 0x5b, 0xaf, 0xfd,
+ 0x98, 0x2a, 0x55, 0x59, 0xb7, 0xa5, 0x02, 0xbd, 0x90, 0xf1, 0xde, 0x2c,
+ 0xe6, 0x90, 0x35, 0x8d, 0x98, 0xe6, 0x3e, 0x38, 0x6c, 0x72, 0x12, 0x53,
+ 0x04, 0x6a, 0x56, 0xd6, 0xe9, 0xb0, 0xae, 0x08, 0xe5, 0x2c, 0xd5, 0xa3,
+ 0x32, 0x88, 0xbf, 0x64, 0xda, 0xa2, 0x2c, 0x4e, 0x95, 0x2d, 0xd7, 0x8d,
+ 0x8b, 0xd9, 0xb9, 0x14, 0x4e, 0xfd, 0xd1, 0x22, 0x1b, 0x6e, 0xb7, 0xe7,
+ 0x7a, 0xc5, 0xe4, 0x83, 0xcc, 0x8d, 0xf2, 0x99, 0x88, 0x4d, 0x61, 0x4f,
+ 0x8c, 0x14, 0x38, 0xe3, 0x56, 0xc4, 0x60, 0xb9, 0xda, 0xb6, 0x36, 0x5b,
+ 0x21, 0x89, 0x18, 0x2d, 0xfc, 0xa5, 0xc2, 0x21, 0xfa, 0xaa, 0xb6, 0x88,
+ 0xc1, 0xc2, 0xbc, 0x41, 0x14, 0x24, 0x69, 0xa9, 0x36, 0xe0, 0x0e, 0x42,
+ 0xa4, 0x5c, 0xe3, 0x06, 0xb4, 0xaa, 0x84, 0x9b, 0x60, 0xc1, 0x7b, 0xdf,
+ 0x3a, 0x96, 0x31, 0x19, 0x84, 0x34, 0x86, 0xbf, 0xc4, 0x3d, 0xd8, 0x61,
+ 0xff, 0x38, 0xd2, 0xd6, 0xb2, 0xca, 0xf5, 0xaa, 0xb5, 0xad, 0x37, 0xdb,
+ 0x8c, 0x22, 0xec, 0x96, 0x2e, 0xa5, 0xbf, 0x77, 0x5d, 0x3a, 0x0f, 0x9e,
+ 0x16, 0x4e, 0x41, 0x5d, 0xe0, 0x24, 0x65, 0xe8, 0xf5, 0x9f, 0x8a, 0x0f,
+ 0xf2, 0x7a, 0x97, 0x15, 0x5a, 0xd1, 0x9d, 0x83, 0xcf, 0x3b, 0xbd, 0xaa,
+ 0xf5, 0x52, 0x17, 0x12, 0x58, 0x8f, 0xc5, 0x61, 0xe7, 0x5e, 0x40, 0x75,
+ 0x82, 0x0d, 0xe8, 0x6d, 0x57, 0xa4, 0xd6, 0xa3, 0x39, 0x68, 0x68, 0x0d,
+ 0x49, 0xda, 0x95, 0x42, 0xf9, 0x46, 0x15, 0x1a, 0xa1, 0x6f, 0x51, 0x5e,
+ 0x60, 0x84, 0xef, 0x89, 0xf1, 0xf0, 0xbd, 0xa8, 0x59, 0x6d, 0x83, 0xa8,
+ 0x5a, 0x04, 0x69, 0xa4, 0x5b, 0xa1, 0xc9, 0xc8, 0xb4, 0xde, 0x0b, 0x4c,
+ 0xf6, 0xfe, 0x75, 0xc4, 0x22, 0xa3, 0x39, 0x3a, 0xe2, 0xc2, 0xc2, 0xe8,
+ 0x2b, 0x2e, 0x8b, 0xac, 0x80, 0xe5, 0x20, 0x70, 0xbc, 0x94, 0x41, 0xb2,
+ 0xdf, 0xae, 0x3e, 0xb1, 0xbe, 0x7d, 0x11, 0xb2, 0xa8, 0x13, 0x7b, 0xcd,
+ 0xa7, 0x1c, 0x49, 0x96, 0x70, 0xf6, 0x73, 0xc0, 0x66, 0x22, 0x21, 0x3f,
+ 0x5e, 0xaf, 0x6b, 0x0f, 0x45, 0xe1, 0x02, 0x07, 0x5d, 0xa9, 0xae, 0x1d,
+ 0x6b, 0x1e, 0xc9, 0xdc, 0x77, 0x5d, 0x75, 0x78, 0x26, 0x81, 0xfe, 0xe5,
+ 0x9c, 0x48, 0xa5, 0x91, 0x1c, 0x77, 0x13, 0x32, 0xe3, 0x95, 0x60, 0xc9,
+ 0xc5, 0xb8, 0xd6, 0x35, 0xb8, 0x4e, 0x3f, 0xbf, 0x35, 0xe2, 0x17, 0x4d,
+ 0x39, 0x98, 0xd0, 0xac, 0x0e, 0xce, 0x76, 0xc5, 0x3f, 0x88, 0xa0, 0xe6,
+ 0x64, 0x06, 0x9a, 0xa4, 0x52, 0x31, 0xf7, 0xb8, 0x7b, 0x50, 0x2a, 0x62,
+ 0xd5, 0xe6, 0xc2, 0x00, 0x65, 0x60, 0x0a, 0x24, 0x08, 0x55, 0x85, 0xc8,
+ 0x31, 0x4e, 0x99, 0x23, 0x30, 0xc4, 0x7b, 0x8c, 0xaa, 0xb8, 0x95, 0x45,
+ 0xaf, 0x60, 0x3e, 0xe9, 0x06, 0xfa, 0x3e, 0xc3, 0xd7, 0x11, 0xb7, 0x9a,
+ 0x29, 0xea, 0x0c, 0x53, 0x0b, 0x16, 0x57, 0xa3, 0x60, 0x70, 0xa5, 0x52,
+ 0x71, 0xb9, 0x57, 0x71, 0x72, 0x6d, 0xe2, 0x5e, 0xd4, 0xa0, 0x78, 0x7f,
+ 0x54, 0xaa, 0x18, 0x5d, 0x2a, 0x30, 0x1b, 0x50, 0x6d, 0xed, 0xf7, 0x42,
+ 0x35, 0x32, 0x57, 0x46, 0xa0, 0x22, 0x91, 0x13, 0x21, 0xa0, 0x55, 0x1d,
+ 0xf2, 0xb9, 0x69, 0xe0, 0x1b, 0x6a, 0xd4, 0xf5, 0x3c, 0xf2, 0x40, 0xed,
+ 0x28, 0x00, 0xe8, 0x50, 0x7c, 0xf6, 0x28, 0xee, 0x09, 0x4e, 0x6d, 0xc5,
+ 0x2e, 0x5a, 0x88, 0x63, 0xea, 0xb7, 0x53, 0x29, 0xe5, 0x8d, 0x62, 0xfa,
+ 0xd4, 0xdc, 0x26, 0x6f, 0x4d, 0xcb, 0x65, 0x14, 0xb1, 0x25, 0xb0, 0x76,
+ 0x75, 0x60, 0x2f, 0x7c, 0x03, 0x6b, 0xcb, 0x0b, 0x96, 0x5f, 0xd6, 0x98,
+ 0x12, 0x74, 0xff, 0xcb, 0xc3, 0x98, 0x2e, 0x71, 0x73, 0xa0, 0xfb, 0xbf,
+ 0x3e, 0xc4, 0xc8, 0xae, 0x25, 0x18, 0xea, 0xe2, 0xf2, 0x4a, 0x6d, 0xe0,
+ 0xed, 0x7e, 0x32, 0x79, 0x60, 0x97, 0x8f, 0xba, 0xc4, 0xcb, 0xcc, 0x5a,
+ 0x8e, 0x6e, 0xd7, 0x3b, 0xcf, 0xc9, 0x89, 0x78, 0xad, 0x6f, 0xf3, 0xff,
+ 0xa1, 0xf5, 0x59, 0x92, 0xa8, 0x9a, 0xd4, 0x12, 0x2c, 0xd3, 0x3c, 0x52,
+ 0xe2, 0x68, 0x48, 0x0c, 0xe6, 0x20, 0x58, 0x48, 0xa0, 0x94, 0x06, 0x04,
+ 0xce, 0x5a, 0xf3, 0x53, 0xa4, 0x92, 0x38, 0x3c, 0xbd, 0xfa, 0xf2, 0x7a,
+ 0x2c, 0x78, 0x38, 0xec, 0xa4, 0x0d, 0xc8, 0x9c, 0x56, 0x4c, 0x6c, 0x0e,
+ 0xb3, 0x4b, 0x65, 0xf2, 0x90, 0x89, 0x29, 0x00, 0x11, 0x62, 0xc2, 0x7e,
+ 0xbf, 0x41, 0x1b, 0x28, 0x0e, 0xf6, 0x8d, 0xb1, 0x9b, 0x78, 0x24, 0x0a,
+ 0xa5, 0x2f, 0x9c, 0xce, 0x53, 0xb5, 0x41, 0x49, 0xbc, 0x64, 0x54, 0x90,
+ 0x18, 0x20, 0xa9, 0x6c, 0x22, 0x9d, 0xe6, 0x18, 0x7c, 0x0a, 0x8e, 0xb5,
+ 0x23, 0xad, 0xe8, 0x4d, 0x64, 0x88, 0x27, 0xfc, 0xb0, 0xb7, 0x4e, 0x25,
+ 0x2a, 0x5b, 0x42, 0x58, 0xe0, 0xd0, 0xdb, 0xa8, 0x47, 0x28, 0x8c, 0xdf,
+ 0x89, 0x0d, 0x00, 0x97, 0xb4, 0x98, 0x58, 0x13, 0x3b, 0x15, 0x78, 0xaa,
+ 0xc4, 0x51, 0xef, 0x74, 0x84, 0x74, 0x69, 0xf9, 0x29, 0xf4, 0x42, 0x76,
+ 0x93, 0x3a, 0xbc, 0xd0, 0x5e, 0x4c, 0x81, 0x17, 0x9a, 0x1b, 0x11, 0xf5,
+ 0x5c, 0x77, 0x05, 0x0b, 0x2f, 0x21, 0xc8, 0x25, 0x70, 0x84, 0xbe, 0x30,
+ 0xf6, 0xc6, 0x51, 0x8d, 0xc9, 0x58, 0xfb, 0x35, 0x09, 0x95, 0xac, 0x50,
+ 0xd6, 0x25, 0x73, 0x27, 0x38, 0x4c, 0xd4, 0x6e, 0x98, 0xb1, 0xbf, 0xc2,
+ 0x3a, 0xee, 0x13, 0x42, 0x29, 0xb5, 0x0f, 0x88, 0xab, 0xd5, 0x1e, 0xf0,
+ 0xce, 0x06, 0xfa, 0xaa, 0x6f, 0xaa, 0x68, 0x07, 0x29, 0x49, 0x3a, 0x8c,
+ 0x6c, 0xba, 0x11, 0x36, 0xf4, 0x7e, 0x4f, 0xb2, 0x40, 0x42, 0xaf, 0x7b,
+ 0xd4, 0x8b, 0xbe, 0xc0, 0x6f, 0x99, 0xb0, 0xb1, 0x4d, 0x3f, 0x92, 0xa2,
+ 0xa4, 0x44, 0xe2, 0x89, 0x14, 0xed, 0x14, 0x08, 0x70, 0x89, 0x92, 0x94,
+ 0x43, 0x20, 0x00, 0xc9, 0x02, 0xb3, 0xcf, 0x2f, 0x5b, 0x43, 0xe9, 0x95,
+ 0xd0, 0x3d, 0x20, 0x06, 0xcd, 0xdb, 0x5d, 0xf3, 0xb4, 0x51, 0x22, 0x57,
+ 0x71, 0x44, 0xb3, 0x9f, 0xb6, 0xfe, 0x81, 0x13, 0x7c, 0x96, 0x50, 0x3e,
+ 0xe4, 0xe4, 0xb1, 0x5d, 0xed, 0xa9, 0xe3, 0xf3, 0xac, 0x23, 0xac, 0x50,
+ 0x69, 0xe6, 0x39, 0xb7, 0xb1, 0x9b, 0x52, 0xdc, 0x40, 0xed, 0x45, 0x27,
+ 0xf0, 0x38, 0x8c, 0xd4, 0x54, 0xd4, 0xb2, 0xc6, 0xfa, 0x0e, 0xea, 0x35,
+ 0x5e, 0x17, 0x52, 0xd1, 0xfd, 0xc9, 0x03, 0x1d, 0x9e, 0xad, 0x65, 0xc3,
+ 0xb1, 0x4d, 0x5e, 0x23, 0x88, 0x0b, 0xbb, 0x01, 0x27, 0x1c, 0x9e, 0x2f,
+ 0x48, 0x21, 0xa8, 0x62, 0x5d, 0xeb, 0x3f, 0x5a, 0x54, 0x86, 0xdd, 0xf4,
+ 0x70, 0xc9, 0x5b, 0x20, 0x5f, 0xd7, 0x10, 0xb1, 0x48, 0x2a, 0x99, 0x6b,
+ 0xd3, 0x3d, 0xe1, 0x3a, 0x3d, 0x8b, 0x2d, 0xa9, 0x79, 0x46, 0xa6, 0xfe,
+ 0xa6, 0xd9, 0x32, 0x35, 0x90, 0xf7, 0x76, 0xb5, 0x7e, 0x9e, 0x87, 0x48,
+ 0x53, 0x6e, 0x37, 0x69, 0x62, 0x8b, 0x51, 0x17, 0xa3, 0x19, 0x32, 0x43,
+ 0x0c, 0xa0, 0x45, 0x27, 0x1a, 0x65, 0xcc, 0x53, 0x57, 0x8d, 0x0a, 0x2d,
+ 0xb3, 0x42, 0x78, 0xa5, 0x12, 0xd6, 0x8a, 0xd6, 0x45, 0x1c, 0xf6, 0x0a,
+ 0x96, 0x90, 0x34, 0xab, 0x5f, 0x22, 0xc5, 0x63, 0x1e, 0x77, 0x71, 0x5a,
+ 0x24, 0xbc, 0x04, 0x33, 0x19, 0x92, 0x32, 0x76, 0x53, 0xb2, 0x68, 0x7c,
+ 0xc5, 0x3d, 0x06, 0xb0, 0xe4, 0xc4, 0xfc, 0xb6, 0xb6, 0xf5, 0xb6, 0xf2,
+ 0x2c, 0xc4, 0xa8, 0xdf, 0xa3, 0x74, 0x5a, 0x26, 0xb1, 0xea, 0x21, 0x99,
+ 0xbc, 0xe5, 0x6d, 0xf1, 0x55, 0x81, 0x2c, 0x87, 0x88, 0xe8, 0xc7, 0xc2,
+ 0xf7, 0x3a, 0x0d, 0x66, 0xd6, 0x03, 0xb0, 0x54, 0xf2, 0xd0, 0x76, 0x7b,
+ 0xdc, 0x63, 0x8e, 0xc5, 0xb1, 0x18, 0xfb, 0xd7, 0x53, 0x78, 0x68, 0x63,
+ 0xa7, 0xd0, 0x3a, 0x3e, 0xed, 0xc0, 0x32, 0x3c, 0x42, 0x82, 0x98, 0xfc,
+ 0xed, 0xfd, 0x3b, 0x3a, 0xfc, 0x4d, 0x99, 0x12, 0x93, 0x2c, 0x5d, 0x88,
+ 0x74, 0xee, 0xdf, 0x3f, 0x3c, 0x95, 0xb3, 0x5f, 0x1e, 0x58, 0x77, 0x32,
+ 0x7a, 0x9f, 0xbd, 0x1d, 0x33, 0xb1, 0x5c, 0xa1, 0x31, 0x95, 0x26, 0x6f,
+ 0xc6, 0xd4, 0xbc, 0x7b, 0xfb, 0x86, 0x9b, 0x2f, 0x86, 0xee, 0x3f, 0x19,
+ 0x2e, 0x87, 0xb8, 0xca, 0xb4, 0x25, 0x67, 0xc7, 0x15, 0x46, 0xf5, 0xf0,
+ 0x54, 0x86, 0xac, 0x46, 0xf1, 0x37, 0x36, 0xd1, 0xf9, 0x75, 0xaf, 0x3b,
+ 0x8c, 0x92, 0xc6, 0x42, 0xcf, 0x95, 0x4b, 0xd3, 0x83, 0x45, 0xe3, 0x5b,
+ 0xd8, 0xd5, 0x18, 0x78, 0x00, 0xb3, 0xfa, 0xb4, 0xba, 0xa3, 0x98, 0x94,
+ 0xfc, 0x48, 0xc9, 0x2d, 0x90, 0x35, 0x48, 0x46, 0x7c, 0xe0, 0xa4, 0x57,
+ 0x98, 0x18, 0x9e, 0x55, 0xfd, 0x08, 0xea, 0x9f, 0x48, 0x2c, 0xa1, 0x96,
+ 0x15, 0xa7, 0x9b, 0x63, 0xb5, 0xc5, 0x7d, 0xa1, 0x17, 0x43, 0x2f, 0x23,
+ 0x16, 0xe3, 0xed, 0xe2, 0xd9, 0x13, 0x7c, 0x87, 0x2c, 0x1e, 0x34, 0xfc,
+ 0x74, 0xf1, 0x4c, 0xf5, 0x6e, 0xd8, 0xf0, 0xb3, 0xc0, 0xa7, 0x60, 0xc0,
+ 0x1a, 0xaf, 0xe3, 0x68, 0x68, 0x1a, 0xa3, 0x8b, 0x5d, 0xdf, 0x5f, 0xf0,
+ 0xb1, 0x7b, 0x31, 0xa6, 0x67, 0x38, 0x3f, 0xb6, 0x82, 0x53, 0x9d, 0x3e,
+ 0xcc, 0x6f, 0x67, 0xf8, 0x37, 0x8e, 0x1f, 0x04, 0x7d, 0x8e, 0xad, 0x8f,
+ 0x7a, 0xd6, 0x55, 0xc0, 0x47, 0x56, 0x41, 0x03, 0x59, 0x8e, 0xf9, 0x1f,
+ 0x18, 0xc7, 0x91, 0x43, 0xa1, 0x5f, 0x19, 0xbb, 0xa2, 0x9b, 0x57, 0x4f,
+ 0x1e, 0x32, 0xac, 0x84, 0x19, 0x89, 0xff, 0x03, 0x00, 0xee, 0x4f, 0x9c,
+ 0x17, 0x11, 0x00, 0x00
+};
+unsigned int paper6_2K_compressed_gz_len = 2032;
diff --git a/drivers/staging/fsl_dce/tests/common/paper6_4K_compressed.gz.h b/drivers/staging/fsl_dce/tests/common/paper6_4K_compressed.gz.h
new file mode 100644
index 0000000..7b11e67
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/common/paper6_4K_compressed.gz.h
@@ -0,0 +1,344 @@
+unsigned char paper6_4K_compressed_gz[] = {
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x85, 0x5a,
+ 0x6b, 0x73, 0xdb, 0x46, 0xb2, 0xfd, 0x7c, 0xe7, 0x57, 0x4c, 0xa9, 0x58,
+ 0x25, 0xa9, 0x2e, 0xc5, 0x92, 0xe4, 0x24, 0xbb, 0xc9, 0xe6, 0x51, 0xb4,
+ 0x62, 0x47, 0x5a, 0x4b, 0x8e, 0xd7, 0x52, 0x36, 0xf7, 0x96, 0xa5, 0x0f,
+ 0x43, 0x60, 0x48, 0xce, 0x1a, 0xc0, 0x30, 0x18, 0x40, 0x34, 0xf7, 0xd6,
+ 0xea, 0xb7, 0xef, 0xe9, 0xee, 0x19, 0x3c, 0x28, 0xaf, 0xef, 0x17, 0x15,
+ 0x08, 0x0c, 0x66, 0xfa, 0x79, 0xfa, 0x74, 0x43, 0xb3, 0x57, 0x7f, 0x53,
+ 0xb9, 0x2d, 0x5c, 0xa9, 0x27, 0x13, 0x5c, 0x2c, 0x5d, 0x65, 0xf5, 0xf7,
+ 0x27, 0xfa, 0xa7, 0xef, 0xf5, 0xc1, 0xfd, 0xfa, 0xf0, 0xe4, 0x74, 0xf6,
+ 0x75, 0x79, 0x78, 0xa0, 0xdb, 0x8d, 0x3e, 0x3b, 0xc5, 0x9d, 0x23, 0x5b,
+ 0x1e, 0xe8, 0xdc, 0x6f, 0x2b, 0xfa, 0xf9, 0x53, 0x5a, 0xbf, 0x6a, 0x7c,
+ 0x9d, 0xdb, 0x5a, 0xff, 0x74, 0x70, 0xff, 0xcf, 0x1f, 0xef, 0xf3, 0xfb,
+ 0xa7, 0xfb, 0xf6, 0xa0, 0x7b, 0xf8, 0xea, 0x7f, 0xae, 0x6e, 0xef, 0xf8,
+ 0xd1, 0xfd, 0x09, 0x9e, 0xd1, 0xdf, 0x9a, 0xaf, 0x1e, 0x0f, 0x4f, 0x67,
+ 0xe7, 0xe5, 0xe1, 0xfd, 0xd1, 0xa2, 0xc6, 0xf5, 0x09, 0xff, 0xe8, 0x5f,
+ 0x9b, 0x5f, 0x5f, 0xd3, 0x4b, 0xfe, 0xf0, 0xef, 0x27, 0x83, 0xbb, 0xa7,
+ 0x37, 0xfa, 0xf0, 0xf4, 0x69, 0x36, 0x9b, 0x3d, 0xdd, 0x9c, 0x9c, 0x1d,
+ 0xa6, 0xbb, 0xd7, 0x97, 0xfa, 0xb0, 0xf0, 0x7c, 0x7b, 0xed, 0xba, 0xbb,
+ 0xef, 0xdf, 0xeb, 0xc3, 0x85, 0x2f, 0x72, 0xfd, 0xbe, 0xbb, 0x75, 0x79,
+ 0x19, 0x6f, 0x5d, 0x76, 0xb7, 0xde, 0xbc, 0x89, 0xb7, 0xde, 0x74, 0xb7,
+ 0x7c, 0xad, 0x0f, 0x0f, 0xee, 0x97, 0x2f, 0x7d, 0x7d, 0xbf, 0xbc, 0x3a,
+ 0x78, 0xea, 0xee, 0x9b, 0x2a, 0x97, 0x07, 0xb8, 0x18, 0x3f, 0x71, 0x4b,
+ 0x79, 0xe0, 0x96, 0xe3, 0xfb, 0xcd, 0xda, 0x56, 0xf2, 0x84, 0xae, 0xc6,
+ 0xcf, 0x6c, 0x11, 0xac, 0x3c, 0xa3, 0xab, 0xf1, 0xb3, 0xda, 0x6e, 0xac,
+ 0x69, 0xe4, 0xa9, 0x5c, 0x8f, 0x9f, 0xb7, 0x55, 0xe3, 0x0a, 0x79, 0xcc,
+ 0x97, 0xe3, 0xa7, 0xdb, 0xb5, 0x2b, 0xe2, 0xd6, 0x7c, 0x39, 0x7e, 0x9a,
+ 0x7b, 0x79, 0x94, 0xfb, 0xf1, 0xfd, 0xcc, 0x24, 0x79, 0xe8, 0x6a, 0x4f,
+ 0xd6, 0xa4, 0xb9, 0xdd, 0xd7, 0x7c, 0x61, 0x57, 0x2e, 0xaa, 0xc8, 0x97,
+ 0xcf, 0x75, 0x4c, 0xb6, 0x91, 0x6b, 0x79, 0xae, 0xd3, 0x82, 0x65, 0xb2,
+ 0xf5, 0x72, 0xdf, 0xd8, 0xaf, 0x6b, 0x5f, 0xc6, 0x47, 0xb8, 0x1a, 0x3f,
+ 0xbb, 0x8b, 0x2a, 0x34, 0x7b, 0x2a, 0xd8, 0x4f, 0x2e, 0x1a, 0x8d, 0xae,
+ 0xe2, 0xb3, 0xd9, 0xab, 0xb7, 0x6a, 0x56, 0x04, 0x7d, 0xf6, 0x5f, 0x6a,
+ 0x96, 0x59, 0x75, 0xf1, 0xeb, 0xcd, 0xbb, 0xf9, 0xc5, 0x9d, 0xbe, 0x9c,
+ 0xdf, 0x5e, 0xea, 0xbb, 0xf9, 0xcb, 0xeb, 0x57, 0xb7, 0xfa, 0xb7, 0xdb,
+ 0xab, 0xb7, 0xbf, 0xe8, 0x97, 0x57, 0x3f, 0x5f, 0xbd, 0x7f, 0x75, 0x71,
+ 0x77, 0xf5, 0xeb, 0xdb, 0xf9, 0xb5, 0xbe, 0xbe, 0x7a, 0xfb, 0x6a, 0xfe,
+ 0x5e, 0xbf, 0x7b, 0xff, 0xeb, 0x4b, 0x3c, 0x54, 0xb3, 0xb0, 0xd1, 0x2f,
+ 0x78, 0x83, 0xbf, 0xfa, 0x75, 0xa5, 0x7f, 0x99, 0xe9, 0x8b, 0xc2, 0x9a,
+ 0x7a, 0xc7, 0xb7, 0xee, 0xd6, 0x56, 0xff, 0x56, 0xb9, 0x47, 0x5b, 0x07,
+ 0xd7, 0xec, 0xb4, 0x5f, 0xea, 0x0b, 0x53, 0xac, 0xf0, 0x74, 0xaa, 0xe7,
+ 0xc5, 0xc2, 0xd6, 0x8d, 0x99, 0xe2, 0x4e, 0x65, 0x72, 0x33, 0x4b, 0x1b,
+ 0xe1, 0xef, 0xf9, 0xa9, 0xba, 0x6f, 0xcf, 0xee, 0xf3, 0x79, 0xdb, 0xac,
+ 0x7d, 0x1d, 0xf4, 0xbb, 0xda, 0x06, 0x5b, 0x35, 0x7a, 0x9e, 0xe7, 0xb8,
+ 0x0a, 0xdf, 0xe9, 0x1b, 0x53, 0x9d, 0xdc, 0x98, 0x6c, 0x4d, 0xaa, 0xdd,
+ 0xee, 0x42, 0x63, 0xcb, 0xa0, 0x7f, 0xa9, 0x7d, 0xbb, 0x99, 0xea, 0x9f,
+ 0xed, 0xc6, 0xd4, 0x4d, 0x49, 0xcb, 0xfd, 0x52, 0x5d, 0xf8, 0x72, 0xd3,
+ 0x36, 0x48, 0xc0, 0xdb, 0xcc, 0xd9, 0x2a, 0xb3, 0x53, 0xfd, 0x05, 0x89,
+ 0xce, 0xbf, 0x3e, 0x3d, 0x1d, 0x3e, 0xfb, 0xb9, 0xc6, 0xa5, 0x7e, 0xfb,
+ 0xbb, 0xea, 0x56, 0x88, 0xa8, 0xfa, 0xee, 0xfc, 0xad, 0x3e, 0x7b, 0xfb,
+ 0x15, 0x8b, 0x0c, 0x49, 0xcf, 0xef, 0xf3, 0xbb, 0xb5, 0x0b, 0x9a, 0xa4,
+ 0x34, 0x75, 0xb6, 0xd6, 0x5b, 0x13, 0x74, 0x68, 0x37, 0x1b, 0x5f, 0x37,
+ 0x36, 0xd7, 0x8b, 0x9d, 0x42, 0x8c, 0xeb, 0xb7, 0xa6, 0x69, 0x6b, 0x53,
+ 0x24, 0x49, 0x02, 0x27, 0xcd, 0xab, 0x0a, 0x91, 0x61, 0x6d, 0xed, 0xaa,
+ 0x95, 0x7e, 0x9f, 0x5e, 0xbf, 0xf0, 0x6d, 0x95, 0x21, 0x8a, 0x59, 0xb6,
+ 0xde, 0x36, 0xe7, 0xec, 0x2c, 0xfc, 0x5d, 0x6c, 0xd4, 0x55, 0x95, 0xdb,
+ 0x4f, 0xfa, 0xce, 0xd6, 0x50, 0xfc, 0xe4, 0x44, 0xeb, 0x5b, 0x7e, 0x13,
+ 0xbb, 0x4c, 0xf5, 0xda, 0x84, 0xb5, 0x0e, 0xc0, 0x1d, 0xb3, 0x82, 0xba,
+ 0x7e, 0x83, 0x3c, 0x33, 0x62, 0x37, 0x7e, 0xac, 0x16, 0x2e, 0x77, 0xb5,
+ 0xcd, 0x1a, 0xe7, 0x2b, 0x48, 0x53, 0xe0, 0x78, 0x53, 0xeb, 0x4d, 0xed,
+ 0x17, 0xf4, 0x58, 0xc5, 0xa5, 0x88, 0xf9, 0x22, 0x6b, 0x0b, 0x43, 0xab,
+ 0xa6, 0xda, 0x55, 0x08, 0xc2, 0x92, 0x7f, 0x40, 0xc9, 0xa6, 0x76, 0xf6,
+ 0xd1, 0x14, 0x53, 0x1d, 0x32, 0xd3, 0x90, 0x6d, 0xbb, 0xc3, 0xd4, 0xc6,
+ 0xd6, 0xbc, 0x12, 0xfa, 0x41, 0x3d, 0x53, 0xec, 0x82, 0x0b, 0x53, 0x5d,
+ 0xda, 0xd2, 0xd7, 0x3b, 0x9d, 0xc1, 0x17, 0x86, 0xcf, 0x9d, 0xb1, 0x0e,
+ 0xb3, 0xcd, 0x46, 0xcd, 0x17, 0xa1, 0xa9, 0x71, 0x93, 0x94, 0x98, 0x43,
+ 0xd0, 0x62, 0xe5, 0x6b, 0xd7, 0xac, 0x4b, 0x0d, 0x73, 0xe6, 0xf6, 0xd1,
+ 0x16, 0x90, 0x3f, 0xa7, 0xb4, 0x85, 0x59, 0x6a, 0x9b, 0xb7, 0x64, 0x37,
+ 0x32, 0x66, 0xdc, 0x52, 0xd5, 0xf6, 0x8f, 0x16, 0xda, 0x90, 0xbb, 0x03,
+ 0xd9, 0x8b, 0x95, 0x6f, 0xcc, 0xa2, 0xb0, 0x61, 0xa6, 0xd8, 0x29, 0xb4,
+ 0x13, 0x45, 0x0a, 0x36, 0x23, 0x57, 0xb0, 0xb0, 0x64, 0x6d, 0x5f, 0x15,
+ 0x3b, 0x65, 0xb4, 0xa6, 0x68, 0xa1, 0x37, 0x2d, 0x16, 0xe9, 0x8f, 0x76,
+ 0x07, 0x19, 0x3c, 0x1e, 0x6f, 0x21, 0x85, 0x36, 0x7a, 0x69, 0xb7, 0xc8,
+ 0x1d, 0x88, 0xa8, 0x17, 0x0e, 0x27, 0xc0, 0x55, 0x39, 0xb6, 0x69, 0x3c,
+ 0xf2, 0x3e, 0xb4, 0x35, 0xc1, 0x98, 0x69, 0x94, 0x29, 0x0a, 0x7a, 0x13,
+ 0xe7, 0xe0, 0x0e, 0xed, 0x8f, 0x25, 0x6d, 0x65, 0xca, 0x85, 0x5b, 0xb5,
+ 0xbe, 0x0d, 0xc5, 0x6e, 0xa6, 0x39, 0xec, 0x96, 0xb5, 0xa8, 0x3f, 0x3a,
+ 0x4e, 0xd6, 0x23, 0x4f, 0xb3, 0xda, 0x02, 0x5d, 0xb0, 0x89, 0x68, 0x18,
+ 0xdc, 0x3f, 0x2d, 0x2d, 0xa4, 0xeb, 0x5e, 0x2b, 0xb8, 0x22, 0xae, 0xc3,
+ 0x9e, 0xb7, 0x6e, 0x55, 0xb9, 0xa5, 0xcb, 0x0c, 0x62, 0x9d, 0x8d, 0x43,
+ 0x9b, 0x07, 0x05, 0xd4, 0x69, 0x7c, 0x03, 0xdf, 0x46, 0x23, 0xb5, 0x01,
+ 0xce, 0x81, 0x43, 0x2b, 0x40, 0x52, 0x6f, 0x0a, 0x1b, 0x36, 0x36, 0x73,
+ 0x10, 0x7d, 0x07, 0xf3, 0x22, 0x46, 0xe8, 0x1c, 0x96, 0x87, 0xce, 0x85,
+ 0xcd, 0x2a, 0xdf, 0xa8, 0xb2, 0x85, 0x90, 0x85, 0xa9, 0x57, 0x70, 0x32,
+ 0x34, 0xad, 0x46, 0x82, 0x99, 0xb4, 0xbf, 0xe3, 0x58, 0xa4, 0x68, 0xe6,
+ 0x8d, 0xc8, 0xb0, 0x78, 0x18, 0x4a, 0x32, 0x8b, 0x29, 0x11, 0xcb, 0x8d,
+ 0xc2, 0xf2, 0xdc, 0x34, 0x86, 0xf6, 0x8d, 0xf6, 0x61, 0xfb, 0x26, 0x23,
+ 0xcc, 0x18, 0x27, 0x46, 0xce, 0xd7, 0x0b, 0x28, 0x99, 0x63, 0xb3, 0x2f,
+ 0x07, 0xec, 0x4c, 0x49, 0xe4, 0xf3, 0xf1, 0xae, 0x0a, 0x40, 0x14, 0x32,
+ 0x70, 0xe3, 0x4a, 0x1b, 0xdd, 0xb1, 0xa6, 0x92, 0x4c, 0x7e, 0x77, 0x65,
+ 0x8c, 0x67, 0xad, 0xe0, 0xbf, 0x05, 0x29, 0x52, 0x3a, 0x28, 0x47, 0xde,
+ 0x04, 0xcc, 0x04, 0xab, 0x08, 0x72, 0x51, 0xae, 0x5d, 0x85, 0x5c, 0xd7,
+ 0x5f, 0x3e, 0x95, 0xe3, 0x17, 0x4e, 0x39, 0x38, 0xd3, 0x57, 0x55, 0x53,
+ 0xfb, 0x68, 0xfc, 0x03, 0x0e, 0x6a, 0x52, 0xa6, 0x4b, 0x13, 0x31, 0x15,
+ 0xe5, 0x1e, 0x79, 0x0f, 0x48, 0xa5, 0x09, 0xb5, 0xc9, 0x30, 0x88, 0x32,
+ 0x64, 0x0a, 0x20, 0x08, 0x56, 0x05, 0xc8, 0x51, 0x9c, 0x52, 0x8e, 0xe0,
+ 0x01, 0x9f, 0x53, 0xd8, 0x92, 0x5c, 0x99, 0x25, 0x04, 0x0b, 0x82, 0x1b,
+ 0xf0, 0xfb, 0x15, 0xde, 0xe6, 0xb8, 0x75, 0x94, 0xa2, 0x75, 0x41, 0xa9,
+ 0x85, 0x27, 0x75, 0x05, 0x83, 0x61, 0x2b, 0x2b, 0xc6, 0x25, 0x5f, 0x71,
+ 0xe5, 0xda, 0xf2, 0x3d, 0xc6, 0x20, 0x3e, 0x9f, 0x91, 0x8a, 0xa5, 0x13,
+ 0x03, 0xd3, 0x03, 0x58, 0xdb, 0x85, 0x91, 0xa8, 0x85, 0x59, 0xd8, 0x42,
+ 0xc1, 0x22, 0x9c, 0x13, 0x4d, 0x03, 0x57, 0xc5, 0xc8, 0x27, 0xa7, 0x21,
+ 0xdf, 0x60, 0xa3, 0xe8, 0x73, 0xce, 0x03, 0xdb, 0xa7, 0x00, 0x42, 0x47,
+ 0x33, 0xed, 0xb1, 0xe4, 0x13, 0xac, 0xda, 0xa9, 0x5e, 0x5a, 0x80, 0xa3,
+ 0xf8, 0xbb, 0xb6, 0xa2, 0xf2, 0xd6, 0x52, 0xfa, 0x54, 0xe4, 0xa6, 0xe0,
+ 0x8b, 0x96, 0xcc, 0xa8, 0xd8, 0x25, 0x78, 0x1a, 0xed, 0x40, 0xbb, 0xd0,
+ 0x09, 0x84, 0x2d, 0xcf, 0xb2, 0xfc, 0x4d, 0x85, 0x2a, 0xa1, 0x3f, 0xfc,
+ 0xf9, 0x61, 0xaa, 0xdf, 0xe0, 0xe4, 0x46, 0x7f, 0xf8, 0xd3, 0x03, 0x4b,
+ 0x76, 0x63, 0x90, 0xa1, 0x35, 0x5f, 0x5e, 0xdb, 0x2d, 0x76, 0xfb, 0x70,
+ 0x76, 0xf6, 0x40, 0x5b, 0x3e, 0xba, 0x1c, 0xcc, 0xcc, 0x7b, 0x92, 0xae,
+ 0xf7, 0x5d, 0x20, 0xe5, 0x14, 0x1f, 0x1b, 0xda, 0xc5, 0x3f, 0xe0, 0xfa,
+ 0x99, 0x40, 0x54, 0xa5, 0xed, 0x12, 0x59, 0xe6, 0xa8, 0xa4, 0x70, 0x69,
+ 0x90, 0x0c, 0x26, 0x21, 0x08, 0x48, 0x80, 0x94, 0x05, 0x12, 0x78, 0xd6,
+ 0x16, 0x5f, 0x8c, 0x54, 0xad, 0x8e, 0x5e, 0x5e, 0xbf, 0x3b, 0x9e, 0x2a,
+ 0x2a, 0x0e, 0x3d, 0xb4, 0x21, 0x32, 0xe7, 0x25, 0x25, 0x36, 0x89, 0x19,
+ 0x55, 0x39, 0x7b, 0x98, 0xa9, 0x39, 0x02, 0xa2, 0x61, 0x85, 0xc3, 0xd8,
+ 0x41, 0x5b, 0x20, 0x0e, 0xee, 0x17, 0x85, 0xdf, 0xf2, 0x12, 0x06, 0xca,
+ 0x90, 0xd5, 0x6e, 0x21, 0xd6, 0x46, 0x4a, 0x82, 0xc9, 0xd8, 0xc6, 0xa0,
+ 0x80, 0x88, 0xd9, 0x94, 0xac, 0x26, 0x19, 0x82, 0x08, 0x47, 0xd8, 0x21,
+ 0x57, 0xfa, 0x05, 0x67, 0x48, 0xd0, 0xf8, 0x43, 0xbb, 0x45, 0x94, 0x28,
+ 0x7d, 0x0e, 0x60, 0xc1, 0x86, 0xc1, 0x33, 0x1e, 0xc1, 0x30, 0xa1, 0x07,
+ 0x1b, 0x04, 0x9c, 0x60, 0xb1, 0x26, 0x4c, 0x8c, 0x28, 0x30, 0x44, 0x62,
+ 0xc6, 0x3b, 0xc7, 0x21, 0x9d, 0x7b, 0xa2, 0x42, 0xcf, 0x60, 0x57, 0xd0,
+ 0xe1, 0x19, 0xf6, 0xa2, 0x0a, 0x3c, 0xc3, 0x5c, 0x8e, 0xa8, 0x7d, 0xdc,
+ 0x55, 0x04, 0xbc, 0x1a, 0x42, 0x2e, 0x11, 0x47, 0xf0, 0x0b, 0xc5, 0xde,
+ 0x94, 0xd1, 0x58, 0x17, 0xde, 0x7f, 0x14, 0xa0, 0x32, 0x25, 0xcc, 0xba,
+ 0xa4, 0xdc, 0x69, 0x6a, 0x54, 0xd4, 0x58, 0xcc, 0x68, 0xbf, 0xcc, 0xd7,
+ 0xe4, 0x27, 0x88, 0x92, 0xbb, 0xd0, 0x40, 0xae, 0xd6, 0x05, 0x84, 0xf7,
+ 0xac, 0x4b, 0x5f, 0xfb, 0xc9, 0x66, 0x6d, 0x07, 0x25, 0x82, 0xc3, 0xd0,
+ 0x26, 0x96, 0xb0, 0xce, 0xf7, 0x23, 0xc8, 0x42, 0x12, 0x06, 0x97, 0xa2,
+ 0x5e, 0x25, 0x03, 0x7f, 0x45, 0x09, 0xcb, 0x6e, 0xfa, 0x1c, 0x14, 0x09,
+ 0x12, 0xa9, 0x01, 0x14, 0xf5, 0x08, 0x84, 0x70, 0x61, 0x48, 0x5a, 0x00,
+ 0x20, 0x10, 0x92, 0x19, 0x6a, 0x5f, 0x58, 0xb6, 0x85, 0x16, 0x96, 0x10,
+ 0x09, 0x44, 0x87, 0x79, 0xfd, 0x31, 0x43, 0x47, 0xa9, 0x85, 0xe5, 0x12,
+ 0x4d, 0xfb, 0xb4, 0xd5, 0x67, 0x36, 0xc1, 0x6b, 0x12, 0xe5, 0x9d, 0x4e,
+ 0x01, 0xb7, 0xcb, 0x11, 0x3a, 0xee, 0x6b, 0xcd, 0x61, 0x05, 0x4b, 0x53,
+ 0x9e, 0x93, 0x1b, 0x63, 0x95, 0x22, 0x07, 0xba, 0xa0, 0x22, 0xc0, 0x63,
+ 0x31, 0x54, 0xb3, 0x8c, 0x65, 0x1b, 0x1f, 0x62, 0xa8, 0x57, 0x60, 0x17,
+ 0xc6, 0xea, 0x0f, 0xe7, 0x0f, 0xfa, 0xe8, 0x62, 0x6d, 0x36, 0x24, 0xdb,
+ 0xd9, 0x31, 0x84, 0xb8, 0xf4, 0x5b, 0xe4, 0x44, 0x0d, 0xfa, 0x02, 0x15,
+ 0x1a, 0x9b, 0xad, 0x2b, 0xf7, 0x47, 0x0b, 0xcb, 0xd0, 0x36, 0x29, 0x5c,
+ 0x16, 0x2d, 0x22, 0xdf, 0x55, 0x00, 0x31, 0x4e, 0x2a, 0xb3, 0x70, 0x45,
+ 0xa4, 0x70, 0x11, 0xcf, 0xd8, 0x25, 0x15, 0xd5, 0x48, 0xf1, 0xaf, 0xd4,
+ 0x96, 0x79, 0x01, 0x78, 0x6f, 0x57, 0xeb, 0x7d, 0x3d, 0x94, 0x54, 0xb9,
+ 0xbe, 0xd2, 0xb0, 0x8b, 0x61, 0x97, 0xc2, 0x51, 0xc8, 0x74, 0x32, 0x20,
+ 0x2d, 0x22, 0x68, 0xe4, 0xac, 0xa7, 0x2b, 0x37, 0xb6, 0x69, 0x29, 0x2b,
+ 0x54, 0xb0, 0x56, 0x62, 0x2d, 0x6b, 0x6b, 0x8e, 0xc3, 0x84, 0x60, 0x12,
+ 0x49, 0x57, 0xd5, 0xf3, 0x48, 0x09, 0xa8, 0xc7, 0x51, 0x4e, 0x0f, 0x85,
+ 0x97, 0xc8, 0x4c, 0x0a, 0x49, 0xc3, 0xde, 0x34, 0x04, 0x1a, 0x1f, 0x71,
+ 0x4e, 0x81, 0xb0, 0x24, 0xc5, 0xc2, 0xae, 0xf2, 0xd5, 0xae, 0x0c, 0x04,
+ 0xc4, 0xb0, 0xdf, 0xa3, 0xa9, 0x9d, 0x11, 0xb0, 0x4a, 0x21, 0x29, 0xbb,
+ 0x2d, 0xda, 0xec, 0xa3, 0x45, 0xb2, 0x1c, 0x41, 0xa2, 0xcf, 0x03, 0xdf,
+ 0xb1, 0x14, 0x66, 0xc2, 0x03, 0x64, 0xa9, 0xa1, 0xa2, 0x5d, 0x8f, 0x72,
+ 0x8f, 0x72, 0x8c, 0xcb, 0x22, 0xfb, 0x2f, 0xa5, 0x70, 0xe7, 0xc6, 0x88,
+ 0xd0, 0x8e, 0xa9, 0x1d, 0xb2, 0x0c, 0x24, 0xa4, 0x51, 0x67, 0xdf, 0x7e,
+ 0xf3, 0xb5, 0x3e, 0x7a, 0x6d, 0x8b, 0x1c, 0x95, 0x4c, 0x0e, 0x84, 0x3a,
+ 0x1f, 0xbe, 0x79, 0x18, 0xc2, 0xd9, 0x9f, 0x1f, 0x08, 0x77, 0x66, 0xfa,
+ 0x9b, 0xd9, 0x57, 0x53, 0x4a, 0xac, 0x3a, 0x73, 0xa8, 0x4a, 0x67, 0x2f,
+ 0xa6, 0x7a, 0xf3, 0xf5, 0x57, 0x2f, 0xc8, 0xf9, 0xaa, 0xf3, 0xfe, 0xa0,
+ 0xb8, 0x1c, 0xe1, 0xa8, 0xa2, 0xcd, 0x49, 0x3b, 0xb2, 0x30, 0xac, 0x07,
+ 0xaa, 0x0c, 0x58, 0x65, 0xf0, 0x2f, 0xbc, 0xa4, 0xf3, 0x71, 0xc2, 0x1d,
+ 0x8a, 0x92, 0x8d, 0x07, 0x9e, 0xdb, 0x5a, 0xaa, 0x07, 0x81, 0xc6, 0xa7,
+ 0xa6, 0xb7, 0x31, 0xe2, 0x01, 0x99, 0x95, 0xd4, 0x8a, 0x4b, 0x51, 0x29,
+ 0x89, 0xa4, 0x2c, 0x3c, 0x22, 0xab, 0x83, 0x0c, 0x26, 0x38, 0xc2, 0xc2,
+ 0x54, 0x47, 0xab, 0x52, 0x09, 0x4a, 0x14, 0x89, 0x20, 0xd4, 0x13, 0xe2,
+ 0xc4, 0x3a, 0x56, 0x79, 0x9c, 0xd7, 0x24, 0x30, 0x0c, 0x86, 0x63, 0x91,
+ 0x4f, 0x57, 0x7b, 0x14, 0xbc, 0x8f, 0x2c, 0x2a, 0x34, 0x44, 0x5d, 0x02,
+ 0xa5, 0x7a, 0x2c, 0x36, 0x44, 0x0b, 0x82, 0x08, 0x83, 0xac, 0x09, 0x8e,
+ 0x4b, 0xc3, 0x66, 0x53, 0xb8, 0xac, 0xf7, 0xfb, 0xb3, 0x7c, 0x8c, 0x8c,
+ 0x51, 0x68, 0x38, 0x91, 0xad, 0xa6, 0xb6, 0x11, 0x1f, 0xee, 0xde, 0x5f,
+ 0xa1, 0x8d, 0x23, 0x42, 0x90, 0x74, 0x6c, 0x03, 0xe3, 0x59, 0xb4, 0x40,
+ 0xe0, 0xac, 0x02, 0x06, 0x12, 0x1c, 0x53, 0x03, 0x53, 0x93, 0xe4, 0x40,
+ 0xe8, 0x49, 0xe1, 0x57, 0xfa, 0xed, 0x64, 0x40, 0x64, 0x08, 0x09, 0x67,
+ 0x5a, 0x09, 0xca, 0xac, 0xb9, 0x7a, 0xc1, 0xd2, 0x68, 0xc2, 0x3d, 0xa1,
+ 0x78, 0x4c, 0x9f, 0x81, 0xac, 0xfb, 0xd5, 0x08, 0x90, 0x67, 0x6b, 0x51,
+ 0xf3, 0x9d, 0x41, 0xef, 0x50, 0xa4, 0x6a, 0x1a, 0x12, 0x82, 0x0c, 0x92,
+ 0xa4, 0xaf, 0x69, 0xa0, 0x21, 0x92, 0x22, 0xda, 0x3c, 0x62, 0x1b, 0xaa,
+ 0xfa, 0x8a, 0x29, 0x14, 0xbf, 0xc1, 0x1d, 0xe2, 0x4c, 0xb8, 0xd8, 0xb9,
+ 0x7e, 0xf9, 0x25, 0xd2, 0x26, 0xe4, 0xec, 0x4a, 0x7c, 0x5e, 0x51, 0xbd,
+ 0x8b, 0xd5, 0x5f, 0xe8, 0xcb, 0x7f, 0x74, 0x53, 0x6c, 0x3f, 0xf6, 0x6a,
+ 0xb1, 0x7a, 0xee, 0x08, 0xa1, 0xb1, 0xcc, 0x04, 0x7a, 0x86, 0x42, 0x1c,
+ 0x4e, 0x36, 0xe8, 0x38, 0x12, 0x0b, 0xd0, 0x65, 0x1a, 0xb3, 0x20, 0x9c,
+ 0x5c, 0xd7, 0x66, 0xa7, 0x27, 0x77, 0x1f, 0x68, 0x92, 0xf3, 0x30, 0xd1,
+ 0xcc, 0xf3, 0x68, 0x25, 0x20, 0x7c, 0xc0, 0xef, 0x38, 0x89, 0x3b, 0x7e,
+ 0xd7, 0x6d, 0x89, 0x8b, 0x32, 0xd8, 0xe2, 0xb1, 0xef, 0x1f, 0x94, 0xe3,
+ 0xae, 0xd8, 0x84, 0xe0, 0x41, 0xf3, 0x9b, 0x7d, 0xca, 0x4d, 0xc3, 0x0e,
+ 0x02, 0xbf, 0xbd, 0xba, 0x6e, 0x50, 0x50, 0xb3, 0x66, 0xcf, 0x19, 0x24,
+ 0x4a, 0x25, 0x8c, 0x2e, 0x95, 0x03, 0x30, 0x52, 0x5e, 0x94, 0xf2, 0x90,
+ 0x0b, 0x55, 0xb7, 0x77, 0xb4, 0x31, 0x45, 0x5a, 0xb3, 0xf5, 0x7a, 0x89,
+ 0xe2, 0xcb, 0xc1, 0xfb, 0x9d, 0x9e, 0x34, 0x93, 0xd4, 0xcd, 0x21, 0x3a,
+ 0x7d, 0xe9, 0x42, 0x6c, 0xe8, 0x52, 0x7a, 0x2b, 0xa9, 0xe4, 0x14, 0xba,
+ 0x93, 0x75, 0x5a, 0x1b, 0x4f, 0xa4, 0x1c, 0x47, 0x20, 0x12, 0x24, 0x4b,
+ 0x32, 0x62, 0x0f, 0x74, 0x36, 0x93, 0xd3, 0x9b, 0x49, 0x2a, 0x63, 0xd7,
+ 0xc8, 0xc1, 0xc9, 0x9b, 0x37, 0x13, 0x32, 0x2f, 0xe7, 0x84, 0x65, 0x18,
+ 0x65, 0xb2, 0x91, 0xd2, 0x49, 0x78, 0x2a, 0x1d, 0x70, 0x79, 0xf9, 0xa5,
+ 0x85, 0x0a, 0x14, 0xa4, 0x0a, 0xe4, 0x76, 0x18, 0x8f, 0x5e, 0x92, 0x36,
+ 0xae, 0x82, 0x12, 0xdf, 0xd1, 0x70, 0xec, 0xe4, 0x47, 0x4d, 0x1b, 0x88,
+ 0xfb, 0x5c, 0xf5, 0x48, 0x75, 0x98, 0xf6, 0x4f, 0xea, 0xc6, 0x06, 0x34,
+ 0xfd, 0xa4, 0x85, 0x5d, 0xc4, 0xe5, 0x6a, 0xdc, 0x43, 0xf6, 0x9e, 0x8c,
+ 0x41, 0x41, 0xf1, 0x1e, 0x6d, 0xc4, 0xb2, 0x06, 0x80, 0x8d, 0x91, 0x0e,
+ 0x01, 0x15, 0x1f, 0x51, 0x49, 0xc3, 0x0c, 0x95, 0x9a, 0x43, 0x4a, 0x59,
+ 0x84, 0x39, 0xf6, 0xa5, 0x0d, 0x63, 0xcd, 0x84, 0x63, 0xc2, 0x12, 0xe1,
+ 0x09, 0x40, 0x52, 0x06, 0xd2, 0x51, 0x17, 0x38, 0x68, 0xd0, 0xc5, 0xab,
+ 0x23, 0x3a, 0x89, 0xed, 0xc8, 0x65, 0xbd, 0xda, 0x6a, 0x14, 0xaf, 0x2d,
+ 0xd5, 0xc9, 0xda, 0x10, 0xe6, 0xf5, 0xed, 0x60, 0x87, 0xcb, 0xd1, 0x42,
+ 0xaf, 0x29, 0x10, 0x3e, 0x99, 0x72, 0x53, 0xd8, 0x69, 0xe4, 0xa7, 0x1c,
+ 0x8e, 0xfb, 0xc6, 0x14, 0xb5, 0x07, 0x1d, 0x33, 0x7c, 0x3a, 0xb9, 0x23,
+ 0x47, 0x1e, 0x9d, 0x9c, 0x69, 0x2e, 0x6c, 0x02, 0x30, 0xa8, 0x54, 0x04,
+ 0x28, 0xc4, 0x90, 0x41, 0x61, 0x7c, 0x96, 0xb5, 0x1b, 0x30, 0x53, 0x95,
+ 0x22, 0x2f, 0xbd, 0x77, 0xcc, 0xfe, 0x9f, 0xac, 0xbf, 0xa3, 0x51, 0xe6,
+ 0xc9, 0x8f, 0x07, 0xff, 0x77, 0x40, 0x89, 0x74, 0xf0, 0xaf, 0x83, 0x09,
+ 0xdb, 0x6f, 0x9d, 0xd2, 0x82, 0xe8, 0x08, 0x3c, 0xb5, 0x93, 0xf3, 0x21,
+ 0x90, 0x9a, 0x5c, 0x12, 0xe1, 0xd7, 0x67, 0xfa, 0x69, 0xaa, 0xe5, 0xf2,
+ 0x5c, 0x3f, 0xd1, 0x44, 0xb7, 0xf4, 0x07, 0xe4, 0xe1, 0xc1, 0x82, 0xef,
+ 0x7f, 0x78, 0x4a, 0x4b, 0x9e, 0x68, 0x09, 0xcd, 0x35, 0x97, 0xf7, 0xcb,
+ 0x77, 0x07, 0x4f, 0x4f, 0xeb, 0xa3, 0xb4, 0xea, 0x58, 0xd6, 0xa5, 0x1b,
+ 0xe7, 0xfa, 0x98, 0xc3, 0x73, 0xbe, 0xe7, 0xbd, 0xe7, 0x78, 0x50, 0x02,
+ 0x3c, 0xa1, 0x33, 0x10, 0x23, 0x56, 0xb0, 0x51, 0xdf, 0xdf, 0x17, 0x28,
+ 0xc9, 0xc4, 0xa8, 0x10, 0x27, 0x44, 0x42, 0x50, 0x57, 0x3f, 0xf3, 0x1e,
+ 0x1d, 0xcd, 0x71, 0xc8, 0x6f, 0xc5, 0x72, 0x01, 0x88, 0x43, 0x91, 0x75,
+ 0x04, 0xea, 0x72, 0x52, 0x3f, 0x9b, 0xe1, 0x5e, 0xcf, 0x11, 0xd4, 0x44,
+ 0xbc, 0xbe, 0x6d, 0x9d, 0x88, 0xd0, 0xa5, 0x31, 0x67, 0x71, 0xca, 0xd0,
+ 0x35, 0x42, 0x4b, 0x18, 0x02, 0xca, 0x2d, 0x22, 0xda, 0xa1, 0xb3, 0x01,
+ 0xba, 0xb8, 0x90, 0xb5, 0x81, 0x3c, 0xa8, 0x8e, 0x2e, 0xc0, 0xf2, 0x23,
+ 0x1d, 0xf9, 0xdd, 0xae, 0x10, 0x7b, 0x53, 0xfd, 0xe1, 0xc5, 0xc3, 0x5f,
+ 0xfa, 0x6e, 0xed, 0x2f, 0xfa, 0xba, 0x2d, 0x71, 0xf3, 0xdb, 0x74, 0xf5,
+ 0xbf, 0xad, 0x15, 0x36, 0xf1, 0xb3, 0xcf, 0x73, 0x3c, 0x38, 0x3b, 0x7d,
+ 0x38, 0x66, 0x70, 0x0d, 0x09, 0xf1, 0x85, 0x4d, 0x77, 0xa9, 0x43, 0xc5,
+ 0xa1, 0x1e, 0x4a, 0x28, 0xb8, 0x61, 0x8a, 0xd2, 0x07, 0xe2, 0xa8, 0xe8,
+ 0x39, 0xd1, 0xa8, 0x98, 0x8f, 0x96, 0x33, 0x86, 0x38, 0x3f, 0x6a, 0x4b,
+ 0x9b, 0x66, 0x31, 0xcf, 0x42, 0x53, 0xf2, 0xae, 0x43, 0x60, 0x06, 0xca,
+ 0xc4, 0xee, 0xf7, 0xdb, 0xd9, 0xfe, 0x4c, 0x82, 0x40, 0xb6, 0x4c, 0xe2,
+ 0x9b, 0xc1, 0x97, 0x36, 0xe5, 0x02, 0x7b, 0x88, 0x11, 0x2d, 0x3a, 0x7b,
+ 0x00, 0x05, 0x83, 0xc2, 0x78, 0xe7, 0xbb, 0xde, 0x1c, 0xd1, 0x02, 0x61,
+ 0xa6, 0x80, 0xb3, 0xc9, 0x54, 0x77, 0x05, 0x6f, 0x10, 0x12, 0x5c, 0x00,
+ 0xc6, 0xa2, 0xb3, 0xd1, 0x38, 0xcc, 0x47, 0x2c, 0x49, 0x8c, 0xe3, 0xea,
+ 0xd0, 0x24, 0x28, 0x25, 0x22, 0x74, 0x25, 0x45, 0xf7, 0x68, 0xb0, 0xc7,
+ 0xf1, 0x60, 0x24, 0xa5, 0xc5, 0xb4, 0x7b, 0x3b, 0x21, 0x78, 0x56, 0x60,
+ 0xab, 0x4d, 0x82, 0x80, 0x49, 0x73, 0xf4, 0xe6, 0x78, 0x22, 0xe3, 0x7c,
+ 0x16, 0x48, 0xa2, 0x35, 0xa4, 0x06, 0x23, 0xd7, 0xed, 0x66, 0x6b, 0x6a,
+ 0xc4, 0x81, 0x4c, 0xe6, 0xa9, 0x1d, 0xe4, 0x58, 0x05, 0x43, 0x21, 0xc6,
+ 0x00, 0xb6, 0x03, 0x9d, 0x10, 0xf7, 0xd4, 0xc0, 0xbc, 0x72, 0x8c, 0x2d,
+ 0xd8, 0xd6, 0x96, 0x1b, 0xa4, 0x68, 0x77, 0x6a, 0x32, 0xda, 0xd2, 0xb7,
+ 0x55, 0x3e, 0x55, 0xa8, 0x92, 0xff, 0x78, 0xf8, 0xe1, 0xe4, 0x0c, 0x86,
+ 0xf1, 0xb5, 0xe4, 0x05, 0x19, 0x9c, 0xf9, 0xfe, 0xde, 0x5a, 0x2d, 0x6b,
+ 0x59, 0x4a, 0x5e, 0xcd, 0x56, 0x4d, 0x3a, 0xa8, 0x7e, 0xaa, 0xf5, 0xe5,
+ 0x0d, 0x7e, 0xe4, 0x0d, 0x7a, 0xa3, 0x89, 0x31, 0x69, 0x35, 0xf9, 0x97,
+ 0xd2, 0x85, 0xba, 0x89, 0x82, 0x26, 0xa7, 0xcf, 0xcc, 0xc2, 0xcc, 0xd8,
+ 0x80, 0x4e, 0xf9, 0x36, 0x99, 0xa5, 0xeb, 0x8c, 0xf9, 0x83, 0xd1, 0xd8,
+ 0xaf, 0xc2, 0x22, 0xfa, 0x75, 0x83, 0xa6, 0xcd, 0x2d, 0xf7, 0x65, 0xa5,
+ 0xfa, 0x22, 0x62, 0x72, 0x2a, 0x80, 0x96, 0xc4, 0x35, 0x05, 0xe8, 0x79,
+ 0x6f, 0xbf, 0x24, 0x24, 0xe7, 0xfe, 0x1f, 0xad, 0xe4, 0xfd, 0x24, 0x1a,
+ 0x85, 0xdb, 0xc8, 0x30, 0x6a, 0x0f, 0x15, 0xcf, 0xa4, 0xd0, 0x3a, 0x50,
+ 0x95, 0x38, 0xba, 0x85, 0xab, 0x3e, 0x33, 0xa4, 0xe0, 0x80, 0xe7, 0x7c,
+ 0x62, 0x7e, 0xd7, 0xb7, 0x24, 0x1d, 0x73, 0x38, 0x96, 0xa0, 0x7e, 0xcd,
+ 0x66, 0x5f, 0x01, 0x19, 0xaa, 0x54, 0x67, 0x13, 0x69, 0x89, 0x89, 0xcb,
+ 0x73, 0x30, 0x4e, 0xd2, 0x94, 0xd1, 0xbb, 0x6e, 0x60, 0x59, 0x73, 0x95,
+ 0x4f, 0xf5, 0x41, 0x05, 0xdf, 0x17, 0xcc, 0x68, 0xa4, 0xbe, 0x0b, 0x07,
+ 0x93, 0x7f, 0xb4, 0xe2, 0xc0, 0xc8, 0x69, 0xb7, 0xbe, 0xfe, 0xd8, 0xb7,
+ 0xfb, 0x83, 0xc1, 0x53, 0xb3, 0x6e, 0x03, 0x78, 0x24, 0x9a, 0x1e, 0x0f,
+ 0xc4, 0xe1, 0xc9, 0x25, 0x38, 0x27, 0x91, 0x21, 0x69, 0xce, 0xfa, 0x4d,
+ 0xb9, 0x06, 0x51, 0x97, 0x0d, 0x86, 0xbf, 0x4d, 0x93, 0x06, 0xd0, 0xa0,
+ 0xb5, 0x47, 0x5b, 0x3b, 0x98, 0x41, 0x28, 0x1a, 0x65, 0x37, 0x76, 0xe5,
+ 0xac, 0x60, 0x01, 0x78, 0x84, 0x23, 0xeb, 0xa7, 0x0e, 0x86, 0xd1, 0x38,
+ 0x0a, 0x40, 0x4a, 0x13, 0x35, 0x02, 0xaa, 0xe4, 0x2e, 0x4e, 0x9f, 0x48,
+ 0xab, 0xb2, 0x85, 0xdb, 0x88, 0x1a, 0x72, 0xf1, 0x76, 0x36, 0xce, 0x54,
+ 0x4d, 0x3a, 0x5a, 0x48, 0x04, 0x09, 0x43, 0xd3, 0x8a, 0x5f, 0xab, 0xa8,
+ 0x8a, 0x91, 0x46, 0x9c, 0xad, 0x1a, 0x2b, 0x45, 0xec, 0x44, 0x78, 0x43,
+ 0x69, 0xf8, 0x78, 0x16, 0x17, 0x32, 0x5b, 0x71, 0x4f, 0xc5, 0xe5, 0x40,
+ 0x25, 0xbc, 0x60, 0x7f, 0x77, 0x7b, 0x89, 0x63, 0x92, 0x2c, 0x68, 0x6d,
+ 0xc6, 0xe9, 0x48, 0x1d, 0x61, 0xb3, 0xb5, 0xb6, 0x7a, 0xde, 0x98, 0xf5,
+ 0x65, 0x99, 0xc8, 0x14, 0x9c, 0x9a, 0x40, 0x89, 0x27, 0x39, 0x59, 0x43,
+ 0xa1, 0x17, 0xfb, 0x94, 0xce, 0x3e, 0x42, 0xab, 0x02, 0x37, 0xd6, 0xc5,
+ 0xae, 0xd3, 0x46, 0xb8, 0x47, 0x58, 0x9b, 0x3a, 0x19, 0x90, 0x8b, 0x1f,
+ 0xf5, 0xff, 0x6e, 0xbf, 0x0d, 0x14, 0x59, 0x79, 0x3c, 0xd8, 0x0d, 0x30,
+ 0xdb, 0x6a, 0x51, 0xfb, 0x8f, 0x10, 0x72, 0x45, 0x1f, 0x86, 0x24, 0x12,
+ 0x7f, 0x77, 0x04, 0x39, 0x91, 0xe7, 0x10, 0xa2, 0xc3, 0x63, 0x8e, 0x3f,
+ 0x1d, 0xd0, 0xc7, 0x41, 0xdf, 0x16, 0xd4, 0x79, 0x7f, 0xb4, 0x03, 0x97,
+ 0xf7, 0x96, 0xef, 0x46, 0x61, 0xc8, 0x24, 0x47, 0xc4, 0x55, 0x0b, 0x70,
+ 0xef, 0x75, 0x48, 0xa1, 0xc3, 0x60, 0x9e, 0x1c, 0x61, 0x7d, 0x2e, 0x25,
+ 0xb6, 0x9f, 0x4e, 0xc3, 0x16, 0xb6, 0x58, 0x32, 0xff, 0x6a, 0x50, 0x5c,
+ 0xb9, 0x62, 0x46, 0xa6, 0xc5, 0x65, 0x8b, 0x74, 0xb6, 0xff, 0x9f, 0xc6,
+ 0xa8, 0x7f, 0x24, 0x2e, 0x35, 0x07, 0x96, 0x1a, 0x39, 0xe6, 0x8c, 0x04,
+ 0x05, 0xf2, 0x4d, 0x22, 0xbd, 0x14, 0x1b, 0x1a, 0xb1, 0xf1, 0x20, 0xf0,
+ 0x38, 0xd9, 0xe0, 0xa3, 0x28, 0x15, 0x2c, 0x3c, 0x10, 0x20, 0x33, 0x44,
+ 0xdd, 0x0b, 0xd7, 0x34, 0x60, 0xc1, 0x54, 0x2d, 0xdb, 0x7a, 0xc1, 0xdf,
+ 0x74, 0x22, 0x5b, 0x90, 0xd8, 0xc2, 0x9e, 0x29, 0x00, 0x3d, 0xcd, 0x65,
+ 0xf2, 0xd4, 0xb5, 0x3a, 0xc1, 0xec, 0xe1, 0x60, 0x38, 0x8a, 0x4b, 0xbd,
+ 0xcc, 0xa6, 0x30, 0x19, 0x09, 0x9b, 0x65, 0x3c, 0xe9, 0x5a, 0xb1, 0xb1,
+ 0x9b, 0x01, 0x3f, 0x89, 0xf6, 0xe3, 0xe1, 0x58, 0xc6, 0x38, 0x4d, 0xe8,
+ 0x61, 0x36, 0x9c, 0x54, 0x60, 0x94, 0x8b, 0x9d, 0x2a, 0x3d, 0xf7, 0xd7,
+ 0xdc, 0x6a, 0xb5, 0x1b, 0xcd, 0x5f, 0x60, 0x68, 0x6a, 0xc0, 0xa9, 0x27,
+ 0xa5, 0x92, 0x9b, 0xfc, 0x28, 0x0a, 0x96, 0x0c, 0x67, 0x02, 0xe3, 0x68,
+ 0x8e, 0x1f, 0x67, 0x82, 0xa5, 0x5c, 0x24, 0xbb, 0xf0, 0x10, 0x6b, 0x57,
+ 0x96, 0xe4, 0xd6, 0x4c, 0xa7, 0x51, 0x34, 0x49, 0x25, 0xd2, 0x84, 0x28,
+ 0xce, 0x02, 0xd9, 0x25, 0x72, 0xa4, 0xa3, 0x59, 0x1e, 0x86, 0x74, 0x45,
+ 0x01, 0xd5, 0x9d, 0xc0, 0x88, 0xde, 0xfb, 0xbf, 0x87, 0x16, 0xc1, 0x44,
+ 0x6c, 0xf4, 0x59, 0x7c, 0x15, 0x84, 0x49, 0x4e, 0x11, 0x86, 0x17, 0x40,
+ 0x61, 0xe0, 0x3e, 0x1c, 0x6c, 0x25, 0x18, 0x41, 0x6a, 0xd2, 0x44, 0x49,
+ 0x47, 0x00, 0xda, 0xc5, 0x37, 0xe8, 0x33, 0xca, 0xaa, 0x35, 0xc0, 0xcf,
+ 0xc6, 0x0a, 0x97, 0xee, 0x42, 0x97, 0x6d, 0xd1, 0x96, 0x0b, 0x1a, 0x4f,
+ 0x2c, 0x07, 0x89, 0x2d, 0x20, 0x9b, 0xe8, 0x53, 0x6d, 0xfb, 0xca, 0x81,
+ 0xce, 0x82, 0x0e, 0x91, 0x90, 0x1f, 0xd4, 0xa4, 0xbd, 0xc1, 0xa2, 0x4a,
+ 0x83, 0xc5, 0x69, 0xcf, 0x83, 0xa4, 0x0b, 0x20, 0x12, 0xf5, 0x05, 0x69,
+ 0xc6, 0x1f, 0x6f, 0x52, 0x8e, 0x70, 0xd6, 0x52, 0x94, 0x8d, 0x98, 0x73,
+ 0x2a, 0x34, 0xfd, 0x3b, 0x9d, 0xe6, 0x09, 0xc2, 0x88, 0x7b, 0x49, 0x3a,
+ 0xc6, 0xd3, 0x2d, 0x09, 0x48, 0x9f, 0xa5, 0x1b, 0xb1, 0x5e, 0xe7, 0x34,
+ 0x99, 0x2f, 0x9c, 0xca, 0xfc, 0x8d, 0xeb, 0xc7, 0xe4, 0x66, 0x92, 0x50,
+ 0x34, 0x75, 0xe5, 0x93, 0x18, 0xec, 0x69, 0xbe, 0x97, 0xc2, 0x42, 0x6d,
+ 0x53, 0x16, 0x26, 0x5f, 0xf4, 0x6f, 0x65, 0xae, 0x16, 0x8a, 0x48, 0x3b,
+ 0x8f, 0x8e, 0xe4, 0x10, 0x3d, 0xe5, 0x1a, 0x7c, 0x03, 0x16, 0x43, 0x0b,
+ 0xd4, 0xa3, 0x83, 0x62, 0x34, 0x10, 0x31, 0xc3, 0x69, 0x68, 0x3f, 0xba,
+ 0xff, 0x4c, 0x80, 0x4c, 0x13, 0x3f, 0x85, 0x1d, 0x1a, 0x6b, 0x72, 0x61,
+ 0xe0, 0xb9, 0x1a, 0x09, 0xce, 0xaf, 0x08, 0xbc, 0xf3, 0xbd, 0x10, 0x67,
+ 0xce, 0xf2, 0x8f, 0x01, 0x91, 0xe5, 0x47, 0xae, 0x47, 0xed, 0x83, 0xdf,
+ 0xf0, 0x1b, 0x0b, 0x70, 0x73, 0x50, 0x60, 0x69, 0x1d, 0x28, 0x4c, 0x83,
+ 0x3e, 0x5c, 0x50, 0xf8, 0xf3, 0xc4, 0xa9, 0xf6, 0xbe, 0x3c, 0xec, 0xea,
+ 0xbf, 0x9c, 0x45, 0x0d, 0xed, 0xa7, 0x0d, 0xde, 0x85, 0xfc, 0xf3, 0x2a,
+ 0x4e, 0xf0, 0xcf, 0x4f, 0x93, 0xd2, 0x2a, 0xd6, 0xec, 0xf1, 0x01, 0x7a,
+ 0x4b, 0x20, 0xb1, 0x14, 0xdc, 0x62, 0xb9, 0xfe, 0x68, 0x69, 0xbe, 0x1b,
+ 0xda, 0xee, 0x93, 0x0b, 0x9d, 0x42, 0xe5, 0x40, 0xbe, 0x3d, 0x76, 0x93,
+ 0xf3, 0x1a, 0x51, 0x17, 0x87, 0x4f, 0x42, 0x0e, 0x86, 0x03, 0xf7, 0x79,
+ 0x02, 0x97, 0xa2, 0x1b, 0x46, 0x88, 0xbe, 0x6a, 0x52, 0x78, 0xfd, 0xf4,
+ 0xc3, 0xd3, 0xc9, 0xf9, 0x69, 0x6a, 0x61, 0x1c, 0x7e, 0xde, 0xfc, 0xf7,
+ 0xd9, 0xb7, 0xf2, 0xbb, 0xff, 0xf7, 0x94, 0x81, 0x09, 0x69, 0x8c, 0xd7,
+ 0x0f, 0x1c, 0x68, 0x8f, 0x09, 0x3b, 0x6f, 0xed, 0x26, 0x71, 0xf4, 0xf4,
+ 0x42, 0x5f, 0xc4, 0x59, 0xd0, 0x65, 0x1c, 0xca, 0xfd, 0xc6, 0x39, 0x39,
+ 0x1e, 0x48, 0x5d, 0xcb, 0x40, 0xea, 0x9d, 0x0c, 0xa4, 0x9e, 0xcd, 0xa3,
+ 0x46, 0x2d, 0xcd, 0xde, 0x77, 0x15, 0x36, 0x0f, 0x13, 0xf3, 0xbe, 0x6f,
+ 0x84, 0xd2, 0x2f, 0xaf, 0xdf, 0x45, 0xa2, 0xf4, 0xd9, 0x0f, 0x34, 0xe4,
+ 0x8b, 0xd7, 0x91, 0xf7, 0xc7, 0xf6, 0x65, 0xf8, 0x59, 0xb0, 0x52, 0x3d,
+ 0x0e, 0xc8, 0x4c, 0x70, 0x38, 0x22, 0x21, 0x2c, 0xa0, 0x51, 0xca, 0x98,
+ 0xd8, 0xde, 0x4c, 0xa6, 0x82, 0xce, 0x14, 0xa0, 0xbb, 0xd1, 0x2b, 0x2a,
+ 0x51, 0xb6, 0x40, 0xb2, 0x58, 0x29, 0xfa, 0x84, 0x86, 0x7b, 0xbd, 0x7a,
+ 0x37, 0x8e, 0x94, 0x97, 0xbb, 0x29, 0x7e, 0x86, 0x60, 0x77, 0x81, 0x01,
+ 0xf3, 0x2a, 0x8e, 0x13, 0x59, 0x52, 0x7a, 0x25, 0xb7, 0x2b, 0x5b, 0xd9,
+ 0x9a, 0xe1, 0x17, 0x96, 0x30, 0x55, 0xff, 0x9d, 0x84, 0xbf, 0x3f, 0x73,
+ 0xf9, 0x23, 0x7f, 0xa5, 0xea, 0xcb, 0x2a, 0xd0, 0x4c, 0x5b, 0x55, 0x24,
+ 0xe9, 0x68, 0xb2, 0x3d, 0x6f, 0x88, 0x17, 0x52, 0x67, 0x98, 0xc8, 0xc2,
+ 0x02, 0x28, 0x51, 0x3a, 0x62, 0xd5, 0x8b, 0xe1, 0xd7, 0xa6, 0x60, 0xf8,
+ 0xeb, 0x38, 0x65, 0x8f, 0xfa, 0x37, 0x2d, 0xac, 0x77, 0xfa, 0x0f, 0x26,
+ 0x00, 0x00
+};
+unsigned int paper6_4K_compressed_gz_len = 4082;
diff --git a/drivers/staging/fsl_dce/tests/common/paper6_8K_compressed.gz.h b/drivers/staging/fsl_dce/tests/common/paper6_8K_compressed.gz.h
new file mode 100644
index 0000000..273a790
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/common/paper6_8K_compressed.gz.h
@@ -0,0 +1,682 @@
+unsigned char paper6_8K_compressed_gz[] = {
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0xbd, 0x5c,
+ 0xfb, 0x73, 0x1b, 0x47, 0x72, 0xfe, 0x59, 0xf3, 0x57, 0xcc, 0xf1, 0xf6,
+ 0x4a, 0x64, 0x09, 0x44, 0x08, 0x52, 0xb4, 0x2d, 0xd9, 0xf2, 0x15, 0x4d,
+ 0x4b, 0x27, 0x46, 0x0f, 0x2b, 0x14, 0xad, 0x4b, 0x4a, 0x64, 0xaa, 0x16,
+ 0xd8, 0x01, 0xb1, 0xd2, 0x62, 0x17, 0xde, 0xd9, 0x25, 0xcd, 0x93, 0x8d,
+ 0xbf, 0x3d, 0xfd, 0x75, 0xcf, 0x6b, 0x41, 0x9a, 0x97, 0xa4, 0x52, 0x71,
+ 0x95, 0x29, 0x60, 0x1f, 0x33, 0x3d, 0x3d, 0xdd, 0x5f, 0x3f, 0x07, 0xe3,
+ 0xe7, 0xff, 0xa6, 0x0a, 0x53, 0x95, 0x4b, 0x9d, 0x65, 0xf4, 0x61, 0x5e,
+ 0xd6, 0x46, 0x7f, 0xb7, 0xab, 0xff, 0xfa, 0x9d, 0xde, 0x3a, 0x5f, 0x3c,
+ 0xdc, 0xdd, 0x1b, 0x1f, 0x2e, 0x1f, 0x6e, 0xe9, 0x7e, 0xa5, 0x27, 0x7b,
+ 0x74, 0x65, 0xdb, 0x2c, 0xb7, 0x74, 0xd1, 0x5c, 0xd7, 0xf8, 0xfa, 0x57,
+ 0xff, 0xfc, 0x65, 0xd7, 0xb4, 0x85, 0x69, 0xf5, 0x5f, 0xb7, 0xce, 0xff,
+ 0xf1, 0xfd, 0x79, 0x71, 0xbe, 0x3e, 0xef, 0xb7, 0xc2, 0xcd, 0xe7, 0xff,
+ 0x7e, 0xf2, 0xfe, 0x8c, 0x6f, 0x9d, 0xef, 0xd2, 0x3d, 0xfc, 0x6d, 0xf9,
+ 0xd3, 0xd5, 0xc3, 0xbd, 0xf1, 0xfe, 0xf2, 0xe1, 0xf9, 0xf6, 0xb4, 0xa5,
+ 0xcf, 0xbb, 0xfc, 0x25, 0xbe, 0x76, 0xf4, 0xfa, 0x35, 0x5e, 0x6a, 0x1e,
+ 0x7e, 0xd8, 0x4d, 0xae, 0xee, 0xbd, 0xd1, 0x0f, 0xf7, 0xd6, 0xe3, 0xf1,
+ 0x78, 0xfd, 0x66, 0x77, 0xf2, 0xd0, 0x5f, 0x7d, 0xfd, 0x52, 0x3f, 0xac,
+ 0x1a, 0xbe, 0xbc, 0x28, 0xc3, 0xd5, 0xd3, 0x53, 0xfd, 0x70, 0xda, 0x54,
+ 0x85, 0x3e, 0x0d, 0x97, 0x5e, 0xbe, 0x74, 0x97, 0x5e, 0x86, 0x4b, 0xaf,
+ 0x5e, 0xb9, 0x4b, 0xaf, 0xc2, 0xa5, 0xa6, 0xd5, 0x0f, 0xb7, 0xce, 0xe7,
+ 0x3f, 0x34, 0xed, 0xf9, 0xfc, 0x64, 0x6b, 0x1d, 0xae, 0xe7, 0x75, 0x21,
+ 0x37, 0xe8, 0xc3, 0xf0, 0x4e, 0x39, 0x97, 0x1b, 0xe5, 0x7c, 0x78, 0xbd,
+ 0x5b, 0x98, 0x5a, 0xee, 0xe0, 0xd3, 0xf0, 0x9e, 0xa9, 0xac, 0x91, 0x7b,
+ 0xf8, 0x34, 0xbc, 0xd7, 0x9a, 0x95, 0xc9, 0x3b, 0xb9, 0x2b, 0x9f, 0x87,
+ 0xf7, 0xfb, 0xba, 0x2b, 0x2b, 0xb9, 0xcd, 0x1f, 0x87, 0x77, 0xaf, 0x17,
+ 0x65, 0xe5, 0x86, 0xe6, 0x8f, 0xc3, 0xbb, 0x45, 0x23, 0xb7, 0x8a, 0x66,
+ 0x78, 0x7d, 0x96, 0x7b, 0x7a, 0xf0, 0x69, 0x83, 0x56, 0xbf, 0x72, 0xb3,
+ 0xb9, 0xf2, 0xa9, 0xb9, 0x2c, 0xdd, 0x12, 0xf9, 0xe3, 0xed, 0x35, 0x7a,
+ 0xde, 0xc8, 0x67, 0xb9, 0xaf, 0xfd, 0x03, 0x73, 0xcf, 0xeb, 0xf9, 0x26,
+ 0xb3, 0x5f, 0xb4, 0xcd, 0xd2, 0xdd, 0xa2, 0x4f, 0xc3, 0x7b, 0x67, 0x6e,
+ 0x09, 0xdd, 0xc6, 0x12, 0xcc, 0xaf, 0xa5, 0x63, 0x1a, 0x3e, 0xb9, 0x7b,
+ 0xe3, 0xe7, 0x6f, 0xd5, 0xb8, 0xb2, 0x7a, 0xf2, 0x40, 0x8d, 0x67, 0x46,
+ 0x1d, 0xff, 0xf4, 0xe6, 0xdd, 0xd1, 0xf1, 0x99, 0x7e, 0x79, 0xf4, 0xfe,
+ 0xa5, 0x3e, 0x3b, 0xfa, 0xe1, 0xf5, 0xf3, 0xf7, 0xfa, 0xe7, 0xf7, 0x27,
+ 0x6f, 0xff, 0xa6, 0x7f, 0x38, 0xf9, 0xf1, 0xe4, 0xf4, 0xf9, 0xf1, 0xd9,
+ 0xc9, 0x4f, 0x6f, 0x8f, 0x5e, 0xeb, 0xd7, 0x27, 0x6f, 0x9f, 0x1f, 0x9d,
+ 0xea, 0x77, 0xa7, 0x3f, 0xfd, 0x40, 0x37, 0xd5, 0xd8, 0xae, 0xf4, 0x01,
+ 0x0f, 0xf0, 0xaf, 0xcd, 0xa2, 0xd6, 0x7f, 0x1b, 0xeb, 0xe3, 0xca, 0xe4,
+ 0xed, 0x0d, 0x5f, 0x3a, 0x5b, 0x18, 0xfd, 0x73, 0x5d, 0x5e, 0x99, 0xd6,
+ 0x96, 0xdd, 0x8d, 0x6e, 0xe6, 0xfa, 0x38, 0xaf, 0x2e, 0xe9, 0xee, 0x48,
+ 0x1f, 0x55, 0x53, 0xd3, 0x76, 0xf9, 0x88, 0xae, 0xd4, 0x79, 0x91, 0x8f,
+ 0xfd, 0x40, 0xf4, 0x77, 0x7f, 0x4f, 0x9d, 0xf7, 0x93, 0xf3, 0xe2, 0xa8,
+ 0xef, 0x16, 0x4d, 0x6b, 0xf5, 0xbb, 0xd6, 0x58, 0x53, 0x77, 0xfa, 0xa8,
+ 0x28, 0xe8, 0x93, 0x7d, 0xaa, 0xdf, 0xe4, 0xf5, 0xee, 0x9b, 0x7c, 0xb6,
+ 0xc0, 0xd2, 0xde, 0xdf, 0xd8, 0xce, 0x2c, 0xad, 0xfe, 0x5b, 0xdb, 0xf4,
+ 0xab, 0x91, 0xfe, 0xd1, 0xac, 0xf2, 0xb6, 0x5b, 0xe2, 0xf1, 0x66, 0xae,
+ 0x8e, 0x9b, 0xe5, 0xaa, 0xef, 0x48, 0x01, 0xdf, 0xcf, 0x4a, 0x53, 0xcf,
+ 0xcc, 0x48, 0xdf, 0x43, 0xd1, 0xfe, 0xe1, 0xde, 0x5e, 0x7a, 0xef, 0xc7,
+ 0x96, 0x3e, 0xea, 0xb7, 0x7f, 0x57, 0xe1, 0x09, 0x21, 0x55, 0x9f, 0xed,
+ 0xbf, 0xd5, 0x93, 0xb7, 0x8f, 0x99, 0x64, 0xa2, 0x74, 0xff, 0xbc, 0x38,
+ 0x5b, 0x94, 0x56, 0x83, 0xca, 0xbc, 0x9d, 0x2d, 0xf4, 0x75, 0x6e, 0xb5,
+ 0xed, 0x57, 0xab, 0xa6, 0xed, 0x4c, 0xa1, 0xa7, 0x37, 0x8a, 0x64, 0x5c,
+ 0xbf, 0xcd, 0xbb, 0xbe, 0xcd, 0x2b, 0x4f, 0x89, 0x65, 0xa5, 0x79, 0x5e,
+ 0x93, 0x64, 0x18, 0xd3, 0x96, 0xf5, 0xa5, 0x3e, 0xf5, 0xaf, 0x1f, 0x37,
+ 0x7d, 0x3d, 0x23, 0x29, 0x66, 0xda, 0x22, 0x6f, 0xf6, 0x79, 0xb3, 0xe8,
+ 0xef, 0x74, 0xa5, 0x4e, 0xea, 0xc2, 0xfc, 0xaa, 0xcf, 0x4c, 0x4b, 0x0b,
+ 0xdf, 0xdd, 0xd5, 0xfa, 0x3d, 0xbf, 0x49, 0xa3, 0x8c, 0xf4, 0x22, 0xb7,
+ 0x0b, 0x6d, 0x09, 0x77, 0xf2, 0x4b, 0x5a, 0x6e, 0xb3, 0x22, 0x3d, 0xcb,
+ 0x85, 0x6f, 0x7c, 0x5b, 0x4d, 0xcb, 0xa2, 0x6c, 0xcd, 0xac, 0x2b, 0x9b,
+ 0x9a, 0xa8, 0xa9, 0x68, 0xfa, 0xbc, 0xd5, 0xab, 0xb6, 0x99, 0xe2, 0xb6,
+ 0x72, 0x8f, 0x92, 0xcc, 0x57, 0xb3, 0xbe, 0xca, 0xf1, 0xd4, 0x48, 0x97,
+ 0x35, 0x09, 0xe1, 0x92, 0xbf, 0xd0, 0x22, 0xbb, 0xb6, 0x34, 0x57, 0x79,
+ 0x35, 0xd2, 0x76, 0x96, 0x77, 0xe0, 0x6d, 0x98, 0x4c, 0xad, 0x4c, 0xcb,
+ 0x4f, 0xd2, 0xfa, 0x68, 0x79, 0x79, 0x75, 0x63, 0x4b, 0x3b, 0xd2, 0x4b,
+ 0xb3, 0x6c, 0xda, 0x1b, 0x3d, 0xa3, 0xbd, 0xc8, 0x79, 0xde, 0x31, 0xaf,
+ 0x61, 0xbc, 0x5a, 0xa9, 0xa3, 0xa9, 0xed, 0x5a, 0xba, 0x88, 0x45, 0x1c,
+ 0x11, 0xa1, 0xd5, 0x65, 0xd3, 0x96, 0xdd, 0x62, 0xa9, 0x89, 0x9d, 0x85,
+ 0xb9, 0x32, 0x15, 0xd1, 0x5f, 0x40, 0x6d, 0x89, 0x2d, 0xad, 0x29, 0x7a,
+ 0xf0, 0x0d, 0xcc, 0x74, 0x43, 0xaa, 0xd6, 0xfc, 0xd2, 0xd3, 0x6a, 0xb0,
+ 0xdd, 0x16, 0xfc, 0xe2, 0xc5, 0x77, 0xf9, 0xb4, 0x32, 0x76, 0xac, 0x78,
+ 0x53, 0x30, 0x12, 0x24, 0x85, 0x06, 0xc3, 0x56, 0x30, 0xb1, 0xe0, 0x76,
+ 0x53, 0x57, 0x37, 0x2a, 0xd7, 0x1a, 0xd2, 0x82, 0x37, 0x0d, 0x3d, 0xa4,
+ 0x3f, 0x9b, 0x1b, 0xa2, 0xa1, 0xa1, 0xdb, 0xd7, 0x44, 0x85, 0xce, 0xf5,
+ 0xdc, 0x5c, 0x93, 0xee, 0x10, 0x89, 0x7a, 0x5a, 0xd2, 0x0c, 0xb4, 0x55,
+ 0x05, 0x0d, 0xd3, 0x35, 0xa4, 0xf7, 0xb6, 0x6f, 0x01, 0x63, 0x79, 0xa7,
+ 0xf2, 0xaa, 0xc2, 0x9b, 0x34, 0x0f, 0x5d, 0xc1, 0xf8, 0xf4, 0x48, 0x5f,
+ 0xe7, 0xcb, 0x69, 0x79, 0xd9, 0x37, 0xbd, 0xad, 0x6e, 0xc6, 0x9a, 0xc5,
+ 0x6e, 0xde, 0xca, 0xf2, 0x07, 0xd3, 0xc9, 0xf3, 0xa4, 0xa7, 0xb3, 0xd6,
+ 0x10, 0xba, 0xd0, 0x20, 0xb2, 0x42, 0x5b, 0xfe, 0xc3, 0xe0, 0x41, 0x7c,
+ 0x8e, 0xab, 0xa2, 0xad, 0x70, 0xcf, 0xd1, 0x98, 0xef, 0xcb, 0xcb, 0xba,
+ 0x9c, 0x97, 0xb3, 0x9c, 0x64, 0x9d, 0x99, 0x83, 0xc1, 0xad, 0x22, 0xd4,
+ 0xe9, 0x9a, 0x8e, 0xf6, 0xd6, 0x31, 0xa9, 0xb7, 0xb4, 0x39, 0xb4, 0xa1,
+ 0x35, 0x41, 0x52, 0x64, 0x85, 0xb1, 0x2b, 0x33, 0x2b, 0x89, 0xf4, 0x1b,
+ 0x62, 0x2f, 0xc9, 0x08, 0xe6, 0x61, 0x7a, 0x30, 0x2f, 0xf1, 0xac, 0x6e,
+ 0x3a, 0xb5, 0xec, 0x89, 0xc8, 0x2a, 0x6f, 0x2f, 0x69, 0x93, 0x69, 0xa5,
+ 0xf5, 0x80, 0xb0, 0xdc, 0x8f, 0x5f, 0xb2, 0x2c, 0x42, 0x9a, 0x79, 0x20,
+ 0x30, 0x96, 0x6e, 0xda, 0x25, 0xd8, 0x92, 0x2f, 0x49, 0x96, 0x3b, 0x45,
+ 0x8f, 0x17, 0x79, 0x97, 0x63, 0x5c, 0xc7, 0x1f, 0xe6, 0xaf, 0x67, 0xc2,
+ 0x98, 0x71, 0x62, 0xb0, 0xf9, 0x7a, 0x4a, 0x8b, 0x2c, 0x68, 0xb0, 0xfb,
+ 0x05, 0x76, 0xac, 0x44, 0xf2, 0x79, 0xfa, 0xb2, 0xb6, 0x84, 0x28, 0x60,
+ 0x70, 0x57, 0x2e, 0x8d, 0xdb, 0x8e, 0x05, 0x4c, 0x32, 0xf6, 0xbd, 0x5c,
+ 0x3a, 0x79, 0xd6, 0x8a, 0xf6, 0x6f, 0x8a, 0x85, 0x2c, 0x4b, 0x5a, 0x1c,
+ 0x76, 0x93, 0x60, 0xc6, 0x1a, 0x05, 0xc8, 0x25, 0x73, 0x5d, 0xd6, 0xa4,
+ 0xeb, 0xfa, 0xfe, 0x59, 0x59, 0x7e, 0x69, 0x53, 0xb6, 0x26, 0xfa, 0xa4,
+ 0xee, 0xda, 0xc6, 0x31, 0x7f, 0x8b, 0x85, 0x1a, 0x8b, 0x09, 0x6a, 0x22,
+ 0xac, 0x82, 0xee, 0x61, 0xf7, 0x08, 0xa9, 0x34, 0x50, 0x1b, 0x8c, 0x21,
+ 0x29, 0x23, 0x4d, 0x21, 0x08, 0x22, 0xae, 0x12, 0xc8, 0x41, 0x4e, 0xa1,
+ 0x23, 0x74, 0x83, 0xe7, 0xa9, 0xcc, 0x12, 0x5b, 0x39, 0xf3, 0x08, 0x66,
+ 0x05, 0x37, 0x68, 0xdf, 0x4f, 0xe8, 0x6d, 0x96, 0xdb, 0x12, 0x2a, 0xda,
+ 0x56, 0x50, 0x2d, 0xba, 0xd3, 0xd6, 0xc4, 0x30, 0x1a, 0xca, 0x08, 0x73,
+ 0xb1, 0x57, 0x6c, 0xb9, 0xae, 0xf9, 0x1a, 0x63, 0x10, 0xcf, 0xcf, 0x48,
+ 0xc5, 0xd4, 0x09, 0x83, 0x71, 0x83, 0xb8, 0x5d, 0xda, 0x01, 0xa9, 0x55,
+ 0x3e, 0x35, 0x95, 0x22, 0x8e, 0xb0, 0x4e, 0x74, 0x1d, 0x6d, 0x95, 0x93,
+ 0x7c, 0x6c, 0x1a, 0xe9, 0x1b, 0xf1, 0xc8, 0xed, 0x39, 0xeb, 0x81, 0x89,
+ 0x2a, 0x40, 0xa2, 0xa3, 0xd9, 0xed, 0x31, 0xd8, 0x13, 0x7a, 0xea, 0x46,
+ 0x45, 0x6a, 0x09, 0x1c, 0x65, 0xbf, 0x5b, 0x23, 0x4b, 0xbe, 0x36, 0x50,
+ 0x9f, 0x1a, 0xdb, 0x64, 0x9b, 0xaa, 0x07, 0x1b, 0x15, 0x6f, 0x09, 0xdd,
+ 0x75, 0x7c, 0xc0, 0x28, 0x98, 0x01, 0xd8, 0x72, 0x4b, 0xcb, 0x5f, 0xd5,
+ 0x64, 0x25, 0xf4, 0xc7, 0x6f, 0x2e, 0x46, 0xfa, 0x15, 0xcd, 0xdc, 0xe9,
+ 0x8f, 0x5f, 0x5f, 0x30, 0x65, 0x6f, 0x72, 0xd2, 0xd0, 0x96, 0x3f, 0xbe,
+ 0x36, 0xd7, 0x34, 0xda, 0xc7, 0xc9, 0xe4, 0x02, 0x43, 0x5e, 0x95, 0x05,
+ 0x79, 0x66, 0x4d, 0x03, 0xea, 0xe2, 0xde, 0x59, 0x2c, 0x4e, 0xf1, 0xb4,
+ 0xb6, 0x9f, 0x7e, 0xa2, 0xad, 0x1f, 0x0b, 0x44, 0xd5, 0xda, 0xcc, 0x49,
+ 0xcb, 0x4a, 0x98, 0x14, 0x36, 0x0d, 0xa2, 0xc1, 0x20, 0x02, 0x40, 0x42,
+ 0x48, 0x59, 0x91, 0x02, 0x8f, 0xfb, 0xea, 0x5e, 0x49, 0xd5, 0x6a, 0xfb,
+ 0x87, 0xd7, 0xef, 0x76, 0x46, 0x0a, 0xc6, 0x21, 0x42, 0x1b, 0x49, 0xe6,
+ 0xd1, 0x12, 0x8a, 0x0d, 0x32, 0xdd, 0x52, 0x26, 0x17, 0x63, 0x75, 0x44,
+ 0x02, 0xd1, 0xf1, 0x82, 0xed, 0x70, 0x83, 0xae, 0x09, 0x71, 0xe8, 0x7a,
+ 0x55, 0x35, 0xd7, 0xfc, 0x08, 0x03, 0xa5, 0x9d, 0xb5, 0xe5, 0x54, 0xb8,
+ 0x4d, 0x2a, 0x49, 0x9e, 0x8c, 0xe9, 0x72, 0x32, 0x20, 0xc2, 0x36, 0x25,
+ 0x4f, 0x83, 0x06, 0x2b, 0xc4, 0x01, 0x3b, 0xe4, 0x93, 0x3e, 0x60, 0x0d,
+ 0xb1, 0x9a, 0xfe, 0x60, 0x34, 0x87, 0x12, 0xcb, 0xa6, 0x20, 0x60, 0xa1,
+ 0x01, 0x6d, 0xc3, 0x78, 0x44, 0x8c, 0xb1, 0x11, 0x6c, 0x48, 0xe0, 0x04,
+ 0x8b, 0x35, 0x30, 0xd1, 0xa1, 0x40, 0x8a, 0xc4, 0x8c, 0x77, 0x25, 0x8b,
+ 0x74, 0xd1, 0xc0, 0x15, 0xba, 0x05, 0xbb, 0x82, 0x0e, 0xb7, 0xb0, 0x97,
+ 0xac, 0xc0, 0x2d, 0xcc, 0x65, 0x89, 0xda, 0xc4, 0x5d, 0x05, 0xe0, 0xd5,
+ 0x44, 0xe4, 0x9c, 0xe4, 0x88, 0xf6, 0x05, 0xb2, 0x37, 0x62, 0x34, 0xd6,
+ 0x55, 0xd3, 0x7c, 0x16, 0xa0, 0xca, 0x97, 0xc4, 0xd6, 0x39, 0x74, 0xa7,
+ 0x6b, 0xc9, 0xa2, 0x3a, 0x63, 0x86, 0xf1, 0x66, 0x4d, 0x8b, 0x7d, 0x22,
+ 0x52, 0x8a, 0xd2, 0x76, 0x44, 0x57, 0x5f, 0x5a, 0x12, 0xef, 0x71, 0x50,
+ 0x5f, 0xf3, 0xab, 0x99, 0xf5, 0x01, 0x4a, 0x04, 0x87, 0x69, 0x35, 0xce,
+ 0x84, 0x85, 0xbd, 0x1f, 0x40, 0x16, 0x29, 0xa1, 0x2d, 0xbd, 0xd4, 0x2b,
+ 0xcf, 0xe0, 0xc7, 0x50, 0x58, 0xde, 0xa6, 0xbb, 0xa0, 0x48, 0x90, 0x48,
+ 0x25, 0x50, 0x14, 0x11, 0x88, 0xc4, 0x85, 0x21, 0x69, 0x4a, 0x00, 0x41,
+ 0x22, 0x39, 0x23, 0xdb, 0x67, 0xe7, 0x7d, 0xa5, 0xc5, 0x4b, 0x70, 0x0e,
+ 0x44, 0xc0, 0xbc, 0x38, 0x4d, 0xba, 0x51, 0x6a, 0x6a, 0xd8, 0x44, 0x63,
+ 0x9c, 0xbe, 0xbe, 0x63, 0x10, 0x7a, 0x4d, 0xa4, 0x3c, 0xac, 0xc9, 0xd2,
+ 0xe5, 0xe5, 0x00, 0x1d, 0x37, 0x57, 0xcd, 0x62, 0x45, 0x9c, 0x86, 0x9e,
+ 0x63, 0x1b, 0x9d, 0x95, 0xc2, 0x06, 0x96, 0x56, 0x39, 0x80, 0xa7, 0x87,
+ 0x69, 0x69, 0x86, 0xb1, 0x6c, 0xd5, 0x58, 0x27, 0xea, 0x35, 0x79, 0x17,
+ 0xb9, 0xd1, 0x1f, 0xf7, 0x2f, 0xf4, 0xf6, 0xf1, 0x22, 0x5f, 0x81, 0xb6,
+ 0xc9, 0x0e, 0x11, 0xf1, 0xb2, 0xb9, 0x26, 0x9d, 0x68, 0xc9, 0x7d, 0xa1,
+ 0x25, 0x74, 0x66, 0xb6, 0xa8, 0xcb, 0x5f, 0x7a, 0xe2, 0x0c, 0x86, 0xf1,
+ 0xe2, 0x32, 0xed, 0x49, 0xf2, 0xcb, 0x9a, 0x40, 0x8c, 0x95, 0x2a, 0x9f,
+ 0x96, 0x95, 0x73, 0xe1, 0x1c, 0x9e, 0xf1, 0x96, 0xd4, 0xb0, 0x91, 0xb2,
+ 0xbf, 0x62, 0x5b, 0x8e, 0x2a, 0x82, 0xf7, 0xfe, 0x72, 0xb1, 0xb9, 0x0e,
+ 0x25, 0x56, 0x2e, 0x5a, 0x1a, 0xde, 0x62, 0xe2, 0x4b, 0x55, 0x42, 0x64,
+ 0x02, 0x0d, 0xa4, 0x16, 0x0e, 0x34, 0x0a, 0x5e, 0x67, 0xb9, 0x5c, 0x99,
+ 0xae, 0x87, 0x56, 0x28, 0x6b, 0x8c, 0xc8, 0xda, 0xac, 0x6f, 0x59, 0x0e,
+ 0x3d, 0x82, 0x89, 0x24, 0x9d, 0xd4, 0xb7, 0x25, 0xc5, 0x92, 0x3d, 0x76,
+ 0x74, 0x36, 0xb4, 0xe0, 0x39, 0x69, 0x26, 0x44, 0x32, 0xe7, 0xdd, 0xcc,
+ 0x01, 0x1a, 0x9f, 0x69, 0x9e, 0x8a, 0xc4, 0x12, 0x0b, 0xb3, 0x37, 0x75,
+ 0x53, 0xdf, 0x2c, 0x2d, 0x80, 0x98, 0xf8, 0x77, 0x95, 0xb7, 0x65, 0x2e,
+ 0x60, 0xe5, 0x45, 0x52, 0x46, 0x9b, 0xf6, 0xb3, 0xcf, 0x86, 0x94, 0x65,
+ 0x9b, 0x28, 0xba, 0x1b, 0xf8, 0x76, 0xc4, 0x30, 0x03, 0x0f, 0x48, 0x4b,
+ 0x73, 0x18, 0xed, 0x76, 0xa0, 0x7b, 0xd0, 0x31, 0x36, 0x8b, 0xbc, 0x7f,
+ 0x5e, 0x85, 0xc3, 0x36, 0x3a, 0x84, 0x2e, 0xd9, 0xb5, 0x23, 0x2d, 0x23,
+ 0x27, 0xa4, 0x53, 0x93, 0x27, 0x5f, 0x1d, 0xea, 0xed, 0x17, 0xa6, 0x2a,
+ 0xc8, 0x92, 0xc9, 0x84, 0xb4, 0x9c, 0x8f, 0x5f, 0x5d, 0xa4, 0x70, 0xf6,
+ 0xcd, 0x05, 0x70, 0x67, 0xac, 0xbf, 0x1a, 0x3f, 0x1e, 0x41, 0xb1, 0xda,
+ 0x59, 0x49, 0x56, 0x69, 0x72, 0x30, 0xd2, 0xab, 0xc3, 0xc7, 0x07, 0xd8,
+ 0x7c, 0x15, 0x76, 0x3f, 0x31, 0x2e, 0xdb, 0x34, 0x55, 0xd5, 0x17, 0x58,
+ 0x1d, 0x38, 0x4c, 0xdc, 0x23, 0x57, 0x99, 0x60, 0x95, 0xc1, 0xbf, 0x6a,
+ 0x44, 0x9d, 0x77, 0x3c, 0xee, 0x40, 0x4a, 0x56, 0x0d, 0xe1, 0xb9, 0x69,
+ 0xc5, 0x7a, 0x00, 0x34, 0x7e, 0xed, 0x22, 0x8f, 0x49, 0x1e, 0x48, 0xb3,
+ 0xfc, 0xb2, 0xdc, 0xa3, 0x64, 0x29, 0xe1, 0xa4, 0x4c, 0x1b, 0x92, 0xac,
+ 0x00, 0x19, 0xec, 0xe0, 0x88, 0x17, 0xa6, 0x82, 0x5b, 0xe5, 0x4d, 0x90,
+ 0x77, 0x91, 0x00, 0xa1, 0x0d, 0x10, 0xc7, 0xd9, 0xb1, 0xba, 0xa1, 0xf9,
+ 0x3a, 0x0f, 0x86, 0x36, 0x67, 0x59, 0xe4, 0xd9, 0xd5, 0x86, 0x0b, 0x1e,
+ 0x25, 0x0b, 0x86, 0x06, 0xae, 0x8b, 0x85, 0xaa, 0x3b, 0x63, 0x03, 0xb7,
+ 0xc0, 0x0a, 0x31, 0xa4, 0x35, 0xb6, 0x64, 0xd3, 0xb0, 0x5a, 0x55, 0xe5,
+ 0x2c, 0xee, 0xfb, 0x2d, 0x7d, 0x74, 0x1e, 0xa3, 0xb8, 0xe1, 0x70, 0xb6,
+ 0xba, 0xd6, 0x38, 0x7c, 0x38, 0x3b, 0x3d, 0xa1, 0x30, 0x0e, 0x0e, 0x81,
+ 0x5f, 0x63, 0x6f, 0x19, 0xcf, 0x1c, 0x07, 0x2c, 0x6b, 0x15, 0x61, 0x20,
+ 0xe0, 0x18, 0x01, 0x4c, 0x0b, 0xca, 0x09, 0xa1, 0xb3, 0xaa, 0xb9, 0xd4,
+ 0x6f, 0xb3, 0xc4, 0x91, 0x01, 0x12, 0x8e, 0xb5, 0x12, 0x94, 0x59, 0xb0,
+ 0xf5, 0x22, 0x4e, 0x53, 0x10, 0xde, 0x00, 0xc5, 0x9d, 0xfa, 0x24, 0xb4,
+ 0x6e, 0x5a, 0x23, 0x82, 0x3c, 0xd3, 0xca, 0x32, 0xdf, 0xe5, 0x14, 0x3b,
+ 0x54, 0xde, 0x9a, 0x5a, 0x8f, 0x20, 0x89, 0x92, 0x44, 0x9b, 0x46, 0x6e,
+ 0x88, 0xa8, 0x88, 0xce, 0xaf, 0x68, 0x18, 0x58, 0x7d, 0xc5, 0x2e, 0x14,
+ 0xbf, 0xc1, 0x11, 0xe2, 0x58, 0x7c, 0xb1, 0x7d, 0xfd, 0xc3, 0x7d, 0x4e,
+ 0x9b, 0x38, 0x67, 0x27, 0xb2, 0xe7, 0x35, 0xec, 0x9d, 0xb3, 0xfe, 0xe2,
+ 0xbe, 0xfc, 0xe1, 0x36, 0xb9, 0xf0, 0x63, 0xc3, 0x16, 0xab, 0xdb, 0x1b,
+ 0x21, 0x6e, 0x2c, 0x7b, 0x02, 0xd1, 0x43, 0x81, 0x0f, 0x27, 0x03, 0x04,
+ 0x1f, 0x89, 0x09, 0x08, 0x9a, 0xc6, 0x5e, 0x10, 0xcd, 0xdc, 0xb6, 0xf9,
+ 0x8d, 0xce, 0xce, 0x3e, 0x22, 0x93, 0x73, 0x91, 0x69, 0xf6, 0xf3, 0xf0,
+ 0x24, 0x41, 0x78, 0xe2, 0xdf, 0xb1, 0x12, 0x07, 0xff, 0x2e, 0x0c, 0x49,
+ 0x1f, 0x96, 0xd6, 0x54, 0x57, 0x31, 0x7e, 0x50, 0x25, 0x47, 0xc5, 0xb9,
+ 0xb5, 0x0d, 0xb9, 0xf9, 0xdd, 0xa6, 0xcb, 0x8d, 0x64, 0x07, 0xc0, 0x6f,
+ 0xc3, 0xae, 0xe7, 0x64, 0x50, 0x67, 0xdd, 0xc6, 0x66, 0x80, 0x94, 0x5a,
+ 0x3c, 0x3a, 0x6f, 0x0e, 0xc8, 0x23, 0xe5, 0x87, 0xbc, 0x1e, 0xb2, 0xa1,
+ 0x0a, 0x63, 0x3b, 0x1e, 0x43, 0xd2, 0xba, 0xeb, 0x46, 0xcf, 0xc9, 0xf8,
+ 0xb2, 0xf0, 0x3e, 0xd5, 0x59, 0x97, 0xf9, 0x68, 0x8e, 0xa4, 0xb3, 0x59,
+ 0x96, 0xd6, 0x05, 0x74, 0x5e, 0xbd, 0x95, 0x58, 0x72, 0x88, 0x6e, 0xb6,
+ 0xf0, 0xcf, 0xba, 0x19, 0xa1, 0xe3, 0x24, 0x88, 0x80, 0x64, 0x51, 0x46,
+ 0x1a, 0x83, 0x22, 0x9b, 0x6c, 0xef, 0x4d, 0xe6, 0xcd, 0xd8, 0x6b, 0xd2,
+ 0xc1, 0xec, 0xd5, 0xab, 0x0c, 0xec, 0x65, 0x9d, 0x30, 0x0c, 0xa3, 0xec,
+ 0x6c, 0x78, 0x75, 0x12, 0x3f, 0x15, 0x13, 0xbc, 0x7c, 0x79, 0xdf, 0x83,
+ 0x8a, 0x5c, 0x90, 0xda, 0x62, 0xdb, 0x89, 0x79, 0x78, 0x49, 0xc2, 0xb8,
+ 0x9a, 0x16, 0xf1, 0x14, 0xc9, 0xb1, 0xdd, 0xef, 0x35, 0x06, 0x90, 0xed,
+ 0x2b, 0xeb, 0x2b, 0xd8, 0x61, 0x8c, 0xef, 0x97, 0xeb, 0x02, 0x50, 0xff,
+ 0x15, 0x0f, 0x06, 0x89, 0x2b, 0xd4, 0x30, 0x86, 0x8c, 0x3b, 0xe9, 0x84,
+ 0x02, 0xf2, 0xee, 0x78, 0xc4, 0xb4, 0x5a, 0x02, 0x9b, 0x5c, 0x22, 0x04,
+ 0xb2, 0xf8, 0x24, 0x95, 0x48, 0x66, 0x28, 0x1f, 0x1c, 0x42, 0x65, 0x49,
+ 0xcc, 0x69, 0x5c, 0x0c, 0xe8, 0x6c, 0x26, 0x6d, 0x8c, 0x9d, 0x93, 0x78,
+ 0x12, 0x20, 0xa9, 0x9c, 0xa8, 0x43, 0x14, 0x98, 0x04, 0xe8, 0xb2, 0xab,
+ 0x03, 0x77, 0x92, 0x86, 0xc3, 0x96, 0xc5, 0x65, 0xab, 0x81, 0xbc, 0xf6,
+ 0xb0, 0x93, 0x6d, 0x0e, 0xcc, 0x8b, 0xe1, 0x60, 0xc0, 0x65, 0xc7, 0xa1,
+ 0x17, 0x10, 0x84, 0x5f, 0xf3, 0xe5, 0xaa, 0x32, 0x23, 0xe7, 0x9f, 0xb2,
+ 0x38, 0x6e, 0x32, 0x53, 0x96, 0x9d, 0x44, 0xcc, 0xb4, 0xa7, 0xd9, 0x19,
+ 0x36, 0x72, 0x7b, 0x77, 0xa2, 0xd9, 0xb0, 0x09, 0xc0, 0x90, 0xa5, 0x02,
+ 0xa0, 0xc0, 0x43, 0x26, 0x17, 0xa6, 0x99, 0xcd, 0xfa, 0x15, 0x79, 0xa6,
+ 0xca, 0x4b, 0x9e, 0x7f, 0x6f, 0x87, 0xf7, 0x3f, 0x5b, 0x3c, 0x45, 0x2a,
+ 0x73, 0xf7, 0xfb, 0xad, 0x2f, 0x5b, 0x50, 0xa4, 0xad, 0xdf, 0xb7, 0x32,
+ 0xe6, 0xdf, 0xc2, 0xab, 0x05, 0xdc, 0x11, 0xda, 0xa9, 0x1b, 0x99, 0x9f,
+ 0x08, 0x52, 0xd9, 0x4b, 0x38, 0xfc, 0x7a, 0xa2, 0xd7, 0x23, 0x2d, 0x1f,
+ 0xf7, 0xf5, 0x1a, 0x19, 0xdd, 0x65, 0xb3, 0x85, 0x1d, 0x4e, 0x1e, 0xf8,
+ 0xee, 0xd9, 0xda, 0x3f, 0xb2, 0xc6, 0x23, 0xc8, 0x6b, 0xce, 0xcf, 0xe7,
+ 0xef, 0xb6, 0xd6, 0xeb, 0xc5, 0xb6, 0x7f, 0x6a, 0x47, 0x9e, 0xf3, 0x17,
+ 0xf6, 0xf5, 0x0e, 0x8b, 0xe7, 0xd1, 0xc6, 0xee, 0xdd, 0xc6, 0x83, 0x25,
+ 0x81, 0x27, 0xad, 0x99, 0x10, 0xc3, 0x59, 0xb0, 0x41, 0xdc, 0x1f, 0x0d,
+ 0x94, 0x68, 0xa2, 0x5b, 0x10, 0x2b, 0x84, 0x47, 0xd0, 0xb2, 0xbd, 0xb5,
+ 0x7b, 0x98, 0x9a, 0xe5, 0x90, 0xdf, 0x72, 0xe6, 0x82, 0x20, 0x8e, 0x8c,
+ 0x6c, 0x09, 0x50, 0x97, 0x99, 0x62, 0x6e, 0x86, 0x63, 0xbd, 0x12, 0x50,
+ 0xe3, 0xf0, 0xfa, 0x7d, 0x5f, 0x0a, 0x09, 0x41, 0x8d, 0x59, 0x8b, 0xbd,
+ 0x86, 0x2e, 0x48, 0xb4, 0xc4, 0x43, 0x20, 0x73, 0x4b, 0x12, 0x5d, 0x52,
+ 0x64, 0x43, 0xe8, 0x52, 0xda, 0x59, 0x6f, 0xb1, 0x83, 0x6a, 0xfb, 0x98,
+ 0xbc, 0x7c, 0xe7, 0x8e, 0xfc, 0xdd, 0x5c, 0x92, 0xec, 0x8d, 0xf4, 0xc7,
+ 0x83, 0x8b, 0x6f, 0x63, 0xb4, 0xf6, 0xad, 0x7e, 0xdd, 0x2f, 0xe9, 0xe2,
+ 0x13, 0xff, 0xe9, 0x3f, 0x7a, 0x23, 0xde, 0xc4, 0x8f, 0x4d, 0x51, 0xd0,
+ 0x8d, 0xc9, 0xde, 0xc5, 0x0e, 0x83, 0xab, 0xf5, 0x88, 0x2f, 0xde, 0x74,
+ 0x50, 0x1d, 0x18, 0x87, 0x36, 0xa5, 0x50, 0x70, 0x23, 0xaf, 0x96, 0x8d,
+ 0x85, 0x8f, 0x4a, 0x31, 0x27, 0x05, 0x2a, 0xf9, 0x67, 0xc3, 0x1a, 0x03,
+ 0x9f, 0x9f, 0x6c, 0x4b, 0xef, 0x73, 0x31, 0xb7, 0x44, 0x53, 0xf4, 0x2e,
+ 0x20, 0x30, 0x03, 0xa5, 0xf7, 0xee, 0x37, 0xc3, 0xd9, 0x38, 0x27, 0x20,
+ 0x90, 0x39, 0xe3, 0xfd, 0x4d, 0xdb, 0x2c, 0x8d, 0xd7, 0x05, 0xde, 0x21,
+ 0x46, 0x34, 0xb7, 0xd9, 0x09, 0x14, 0x24, 0x86, 0xf1, 0xac, 0x09, 0xb1,
+ 0x39, 0x49, 0x0b, 0x11, 0x33, 0x22, 0x38, 0xcb, 0x46, 0x3a, 0x18, 0xbc,
+ 0x44, 0x24, 0xd8, 0x00, 0x0c, 0x49, 0x67, 0xa6, 0xb1, 0x98, 0x0f, 0xbc,
+ 0x24, 0x61, 0x4e, 0xd9, 0xda, 0xce, 0x43, 0x29, 0x1c, 0xa1, 0x13, 0x31,
+ 0xba, 0xdb, 0xc9, 0x18, 0x3b, 0x49, 0x4a, 0x4a, 0x0b, 0x6b, 0x37, 0x46,
+ 0x22, 0xe1, 0xb9, 0x24, 0x6f, 0xb5, 0xf3, 0x10, 0x90, 0x75, 0xdb, 0xaf,
+ 0x76, 0x32, 0x49, 0xe7, 0x33, 0x41, 0x22, 0xad, 0xd6, 0x07, 0x18, 0x85,
+ 0xee, 0x57, 0xd7, 0x79, 0x4b, 0x72, 0x20, 0x99, 0x79, 0x84, 0x83, 0x2c,
+ 0xab, 0xe4, 0xa1, 0xc0, 0x63, 0x20, 0x6f, 0x87, 0xd6, 0x44, 0x72, 0x8f,
+ 0x00, 0xe6, 0x79, 0xc9, 0xd8, 0x42, 0xc3, 0x9a, 0xe5, 0x8a, 0x54, 0x34,
+ 0xcc, 0xea, 0x99, 0x36, 0x6f, 0xfa, 0xba, 0x18, 0x29, 0xb2, 0x92, 0x9f,
+ 0x2e, 0x9e, 0xed, 0x4e, 0x88, 0x31, 0x4d, 0x2b, 0x7a, 0x01, 0x86, 0xb3,
+ 0xbf, 0xbf, 0xf1, 0xac, 0x96, 0x67, 0x99, 0x4a, 0x7e, 0x9a, 0xb9, 0xea,
+ 0xd7, 0xa0, 0x62, 0x56, 0xeb, 0xfe, 0x01, 0xbe, 0xe7, 0x01, 0x22, 0xd3,
+ 0x84, 0x99, 0x78, 0x1a, 0xfb, 0x0b, 0x75, 0x41, 0x34, 0x51, 0x21, 0x73,
+ 0x7a, 0x8b, 0x2d, 0xec, 0x19, 0xe7, 0xe4, 0x4e, 0x35, 0xbd, 0x67, 0x4b,
+ 0x88, 0x8c, 0xb9, 0x60, 0x34, 0xdc, 0x57, 0xf1, 0x22, 0xe2, 0x73, 0x49,
+ 0xd0, 0x56, 0xce, 0x37, 0x69, 0x85, 0x7d, 0x11, 0x32, 0x59, 0x15, 0xc8,
+ 0x2d, 0x71, 0xcf, 0x54, 0xe4, 0x9e, 0x47, 0xfe, 0x79, 0x22, 0x59, 0xf7,
+ 0x7f, 0xe9, 0x45, 0xef, 0x33, 0xc7, 0x14, 0x0e, 0x23, 0xed, 0x20, 0x3c,
+ 0x54, 0x9c, 0x93, 0xa2, 0xd0, 0x01, 0x56, 0x62, 0xfb, 0x3d, 0x6d, 0xd5,
+ 0x1d, 0x49, 0x0a, 0x16, 0x78, 0xd6, 0x27, 0xf6, 0xef, 0x62, 0x48, 0x12,
+ 0x3c, 0x87, 0x1d, 0x11, 0xea, 0x17, 0xcc, 0xf6, 0x4b, 0x42, 0x86, 0xda,
+ 0xdb, 0x59, 0xef, 0xb4, 0x38, 0xc5, 0xe5, 0x3c, 0x18, 0x2b, 0xa9, 0xd7,
+ 0xe8, 0x9b, 0x90, 0xb0, 0x6c, 0xd9, 0xca, 0x7b, 0xfb, 0xa0, 0x6c, 0x13,
+ 0x0d, 0xa6, 0x63, 0x52, 0x8c, 0xc2, 0xc9, 0x93, 0xbf, 0x32, 0xb2, 0x81,
+ 0xce, 0xa7, 0xbd, 0x6e, 0xda, 0xcf, 0x31, 0xdc, 0x4f, 0x12, 0x4f, 0xdd,
+ 0xa2, 0xb7, 0xe4, 0x47, 0x52, 0xd0, 0xd3, 0x10, 0xe2, 0x70, 0xe6, 0x92,
+ 0x7c, 0x4e, 0x38, 0x43, 0x12, 0x9c, 0xc5, 0x41, 0xd9, 0x06, 0x21, 0xca,
+ 0x26, 0x0f, 0xff, 0xda, 0x67, 0x1a, 0xc8, 0x0d, 0x5a, 0x34, 0x14, 0xd6,
+ 0x26, 0x39, 0x08, 0x85, 0x54, 0x76, 0x67, 0x2e, 0x4b, 0x23, 0x58, 0x40,
+ 0x7e, 0x44, 0x09, 0xee, 0xfb, 0x08, 0x86, 0xd1, 0xd8, 0x11, 0x80, 0x45,
+ 0xc3, 0x35, 0x22, 0x54, 0x29, 0x4a, 0x97, 0x7d, 0xc2, 0xaa, 0x96, 0x3d,
+ 0x6d, 0x1b, 0x5c, 0x43, 0x36, 0xde, 0xa5, 0x71, 0x39, 0xd5, 0xdc, 0x4f,
+ 0x2d, 0x4e, 0x04, 0x88, 0x41, 0xb6, 0xe2, 0xa7, 0xda, 0x2d, 0x25, 0x97,
+ 0x40, 0x9c, 0xb9, 0xea, 0x2c, 0x85, 0x8b, 0x44, 0x78, 0x40, 0x09, 0xf8,
+ 0x38, 0x17, 0x67, 0x67, 0xa6, 0xe6, 0x98, 0x8a, 0xcd, 0x81, 0xf2, 0x78,
+ 0xc1, 0xfb, 0x1d, 0xc6, 0x92, 0x8d, 0xf1, 0xb4, 0x50, 0x68, 0x33, 0x54,
+ 0x47, 0x44, 0x84, 0xdd, 0xb5, 0x31, 0xf5, 0xed, 0xc0, 0x2c, 0x9a, 0x65,
+ 0x38, 0x53, 0xb4, 0xa9, 0x1e, 0x94, 0x38, 0x93, 0x33, 0xeb, 0x20, 0x7a,
+ 0x2e, 0x4e, 0x09, 0xfc, 0x11, 0xb7, 0xca, 0x72, 0x60, 0x5d, 0xdd, 0x84,
+ 0xd5, 0x88, 0xef, 0x61, 0x17, 0x79, 0xeb, 0x19, 0xc8, 0xc6, 0x0f, 0xf1,
+ 0x7f, 0xb9, 0x19, 0x06, 0x0a, 0xad, 0x9c, 0x1e, 0x0c, 0x09, 0xcc, 0xbe,
+ 0x9e, 0xb6, 0xcd, 0x67, 0x22, 0xf2, 0x12, 0x85, 0x21, 0x91, 0xc4, 0xbf,
+ 0x97, 0x80, 0x1c, 0xe7, 0xe7, 0x00, 0xd1, 0x69, 0xc7, 0x4a, 0x2e, 0x1d,
+ 0xa0, 0x38, 0xd8, 0xf4, 0x15, 0x22, 0xef, 0xcf, 0x26, 0xd9, 0xf2, 0xc8,
+ 0xf9, 0x90, 0x0a, 0x23, 0x4d, 0x2a, 0xe1, 0xb8, 0x6a, 0x01, 0xee, 0x8d,
+ 0x08, 0xc9, 0x06, 0x0c, 0xe6, 0xcc, 0x11, 0x3d, 0x5f, 0x88, 0x89, 0x8d,
+ 0xd9, 0x69, 0xe2, 0x85, 0xa9, 0xe6, 0xec, 0x7f, 0x75, 0x64, 0x5c, 0xd9,
+ 0x62, 0x3a, 0x4f, 0x8b, 0xcd, 0x16, 0xd6, 0x6c, 0xfe, 0xd9, 0x8a, 0xc9,
+ 0xfe, 0x81, 0x5c, 0x04, 0x07, 0x06, 0x81, 0x1c, 0xfb, 0x8c, 0x80, 0x02,
+ 0xa9, 0x49, 0xf8, 0x97, 0x5c, 0x40, 0x23, 0x3c, 0x4e, 0x04, 0x8f, 0x95,
+ 0x8d, 0xf6, 0xc8, 0x51, 0x45, 0x1c, 0x4e, 0x08, 0x98, 0xe5, 0x70, 0xdd,
+ 0xab, 0xb2, 0xeb, 0xc8, 0x0b, 0x86, 0xb5, 0xec, 0xdb, 0x29, 0xd7, 0x74,
+ 0x9c, 0xb7, 0x20, 0xb2, 0x45, 0x63, 0x7a, 0x01, 0x6c, 0x90, 0x97, 0x29,
+ 0x7c, 0xd4, 0x5a, 0x0a, 0x66, 0xa7, 0x89, 0x61, 0x47, 0x2e, 0x62, 0x99,
+ 0x55, 0x95, 0xcf, 0x40, 0xec, 0x6c, 0xc6, 0x99, 0xae, 0x4b, 0x66, 0x76,
+ 0x97, 0xf8, 0x27, 0x8e, 0x7f, 0x9c, 0x1c, 0x9b, 0x31, 0x4e, 0x03, 0x3d,
+ 0xf2, 0x15, 0x2b, 0x15, 0x79, 0x94, 0xd3, 0x1b, 0xb5, 0x6c, 0x38, 0xbe,
+ 0xe6, 0x50, 0xab, 0x5f, 0x69, 0xae, 0xc0, 0x20, 0x6b, 0xc0, 0xaa, 0x27,
+ 0xa6, 0x92, 0x83, 0x7c, 0x47, 0x0a, 0x3d, 0x92, 0xe6, 0x04, 0x86, 0xd2,
+ 0xec, 0x8a, 0x33, 0xd6, 0x40, 0x17, 0xc1, 0x17, 0x4e, 0x62, 0xdd, 0x2c,
+ 0x97, 0xd8, 0xd6, 0x99, 0xf6, 0xa9, 0x68, 0x50, 0x25, 0xd4, 0x58, 0x47,
+ 0xce, 0x94, 0xb4, 0x4b, 0xe8, 0xf0, 0x53, 0x33, 0x3d, 0x0c, 0xe9, 0x0a,
+ 0x02, 0x15, 0x66, 0x60, 0x44, 0x8f, 0xfb, 0x1f, 0xa1, 0x45, 0x30, 0x91,
+ 0x06, 0xba, 0x13, 0x5f, 0x05, 0x61, 0xfc, 0xa6, 0x88, 0x87, 0x67, 0xc9,
+ 0x85, 0xa1, 0xed, 0xa3, 0x89, 0x8d, 0x08, 0x23, 0x39, 0x35, 0x3e, 0xa3,
+ 0xa4, 0x1d, 0x00, 0xdd, 0xb8, 0x37, 0x50, 0x46, 0xb9, 0xec, 0x73, 0xc2,
+ 0xcf, 0xce, 0x88, 0x2f, 0x1d, 0x44, 0x97, 0x79, 0xd1, 0x2f, 0xa7, 0x48,
+ 0x4f, 0xcc, 0x13, 0xc5, 0x16, 0x90, 0xf5, 0xee, 0x53, 0x6b, 0xa2, 0xe5,
+ 0xa0, 0xc8, 0x02, 0x93, 0x88, 0xc8, 0x27, 0x36, 0x69, 0x23, 0xb1, 0xa8,
+ 0x7c, 0x62, 0x71, 0x14, 0xfd, 0x20, 0x89, 0x02, 0xe0, 0x44, 0xdd, 0x43,
+ 0xcd, 0xb0, 0x78, 0xe3, 0x75, 0x84, 0xb5, 0x16, 0x52, 0x36, 0xf0, 0x9c,
+ 0xbd, 0xa1, 0x89, 0xef, 0x84, 0x95, 0x7b, 0x08, 0x83, 0xef, 0x25, 0xea,
+ 0xe8, 0x66, 0x37, 0x20, 0x10, 0x65, 0xe9, 0x4e, 0xb8, 0x17, 0x36, 0x4d,
+ 0xf2, 0x0b, 0x7b, 0x92, 0x7f, 0x63, 0xfb, 0x91, 0xbd, 0xc9, 0x3c, 0x8a,
+ 0xfa, 0xa8, 0x3c, 0x73, 0xc2, 0xee, 0xf3, 0x7b, 0x5e, 0x2c, 0xd4, 0xb5,
+ 0xd7, 0x42, 0xbf, 0x17, 0xf1, 0xad, 0x59, 0xd9, 0x8a, 0x8b, 0x88, 0x91,
+ 0x07, 0x53, 0xb2, 0x88, 0xee, 0xb1, 0x0d, 0x7e, 0x43, 0x5e, 0x0c, 0x1e,
+ 0x50, 0x57, 0x25, 0x2d, 0x0c, 0x09, 0x91, 0x3c, 0xcd, 0x86, 0xc6, 0xd4,
+ 0xfd, 0x1d, 0x02, 0x32, 0xf2, 0xfe, 0x29, 0xf1, 0xa1, 0x33, 0x79, 0x21,
+ 0x1e, 0x78, 0xa1, 0x06, 0x84, 0xf3, 0x2b, 0x02, 0xef, 0x7c, 0xcd, 0xba,
+ 0x9c, 0xb3, 0x34, 0x06, 0x38, 0x2f, 0xdf, 0xf9, 0x7a, 0x08, 0x1f, 0x9a,
+ 0x15, 0xbf, 0x31, 0x25, 0xdf, 0x9c, 0x5c, 0x60, 0x09, 0x1d, 0x20, 0xa6,
+ 0x56, 0x3f, 0x9c, 0x42, 0xfc, 0x39, 0xe3, 0xd4, 0x36, 0xcd, 0xf2, 0x61,
+ 0xb0, 0xff, 0x32, 0x17, 0x02, 0xda, 0x5f, 0x57, 0xf4, 0x2e, 0xd1, 0x7f,
+ 0x54, 0xbb, 0x0c, 0xfe, 0xfe, 0x9e, 0x5f, 0xb4, 0x72, 0x36, 0x7b, 0x38,
+ 0x81, 0xbe, 0x06, 0x48, 0xcc, 0x05, 0xb7, 0x98, 0xae, 0x5f, 0x7a, 0xe4,
+ 0x77, 0x6d, 0x1f, 0x4a, 0x2e, 0x98, 0x05, 0xe6, 0x40, 0x6a, 0x8f, 0x21,
+ 0x73, 0xde, 0x92, 0xd4, 0xb9, 0xe4, 0x93, 0x38, 0x07, 0x69, 0xc2, 0xfd,
+ 0xc8, 0x83, 0x4b, 0x15, 0x92, 0x11, 0xb2, 0x5e, 0x95, 0x55, 0x8d, 0x5e,
+ 0x3f, 0x5b, 0xef, 0xee, 0xef, 0xf9, 0x10, 0xa6, 0xa4, 0xaf, 0x6f, 0x1e,
+ 0x4d, 0x9e, 0xc8, 0xf7, 0xd8, 0x9e, 0x92, 0xb0, 0x10, 0x69, 0xbc, 0x98,
+ 0x70, 0xc0, 0x18, 0x19, 0x6f, 0xde, 0xa2, 0xcc, 0x5c, 0xea, 0xe9, 0x40,
+ 0x1f, 0xbb, 0x5c, 0xd0, 0x4b, 0x97, 0x94, 0xfb, 0x99, 0x75, 0x72, 0x98,
+ 0x90, 0x7a, 0x2d, 0x09, 0xa9, 0x77, 0x92, 0x90, 0xba, 0x95, 0x8f, 0x1a,
+ 0x84, 0x34, 0x1b, 0x75, 0x15, 0x66, 0x0f, 0x3b, 0xe6, 0x31, 0x6e, 0xa4,
+ 0x45, 0xff, 0xf0, 0xfa, 0x9d, 0x73, 0x94, 0xee, 0x2c, 0xd0, 0x60, 0x2f,
+ 0x5e, 0x38, 0xbf, 0xdf, 0x85, 0x2f, 0x69, 0x59, 0xb0, 0x56, 0x11, 0x07,
+ 0x24, 0x27, 0x98, 0xa6, 0x48, 0x80, 0x05, 0x48, 0xa5, 0x0c, 0x1d, 0xdb,
+ 0x37, 0xd9, 0x48, 0xd0, 0x19, 0x02, 0x7a, 0x33, 0x78, 0x45, 0x79, 0x97,
+ 0xcd, 0x82, 0x16, 0x23, 0x46, 0x1f, 0x68, 0xb8, 0x11, 0xab, 0x87, 0x74,
+ 0xa4, 0xbc, 0x1c, 0xb2, 0xf8, 0x33, 0x12, 0xf6, 0xd2, 0x32, 0x60, 0x9e,
+ 0xb8, 0x74, 0x22, 0x53, 0x8a, 0x57, 0x0a, 0x73, 0x69, 0x6a, 0xd3, 0x32,
+ 0xfc, 0x12, 0x27, 0xf2, 0x3a, 0xd6, 0x49, 0xb8, 0xfe, 0xcc, 0xe6, 0x0f,
+ 0xfb, 0xe5, 0xad, 0x2f, 0x2f, 0x01, 0x39, 0x6d, 0x55, 0x83, 0xd2, 0x41,
+ 0x66, 0xfb, 0xa8, 0x83, 0x5f, 0x88, 0xc8, 0xd0, 0x3b, 0x0b, 0x53, 0x42,
+ 0x89, 0x65, 0x09, 0xaf, 0x7a, 0x9a, 0x56, 0x9b, 0x6c, 0xce, 0xd5, 0x71,
+ 0x68, 0x8f, 0xca, 0x93, 0x92, 0x2b, 0x9b, 0xb4, 0x90, 0x1a, 0x77, 0xf1,
+ 0x12, 0xc9, 0x29, 0x61, 0x9c, 0xcf, 0x30, 0x93, 0x63, 0xe1, 0x73, 0x5b,
+ 0x48, 0xf5, 0x7a, 0x9f, 0xc8, 0x8f, 0xb6, 0x81, 0x4a, 0x98, 0x6c, 0x81,
+ 0x5e, 0x2b, 0x3c, 0x8f, 0xd0, 0xbc, 0x75, 0xf5, 0x94, 0x3a, 0x54, 0xd9,
+ 0x63, 0x91, 0xc5, 0x92, 0xa0, 0x99, 0xb0, 0x37, 0xb6, 0x02, 0xdd, 0xe4,
+ 0x41, 0xa4, 0x85, 0xfa, 0x8c, 0x53, 0x62, 0x49, 0x2e, 0x06, 0xef, 0xf3,
+ 0x1b, 0x50, 0xb8, 0x11, 0x16, 0x06, 0x70, 0xe9, 0x5b, 0xe7, 0xb3, 0x6c,
+ 0xbc, 0xab, 0x78, 0x87, 0x53, 0x9e, 0x84, 0x7d, 0xf6, 0x84, 0x4a, 0x35,
+ 0x81, 0x4c, 0x11, 0x17, 0xe9, 0x92, 0x12, 0xd0, 0x66, 0x82, 0x48, 0x56,
+ 0x03, 0xff, 0xc6, 0x59, 0x5a, 0xf4, 0x2f, 0x88, 0x57, 0x1c, 0x7d, 0x71,
+ 0x2f, 0xf3, 0x70, 0x53, 0x43, 0xc2, 0xcc, 0x0d, 0xea, 0xd8, 0x2b, 0x32,
+ 0xc9, 0x65, 0x97, 0x34, 0x71, 0xe6, 0x31, 0xd5, 0x67, 0x0a, 0x49, 0x84,
+ 0x0a, 0xa3, 0xf3, 0x24, 0x9f, 0x1f, 0xa4, 0xcf, 0x89, 0x67, 0x2c, 0xfe,
+ 0x59, 0xf4, 0x0a, 0xe5, 0xec, 0x4a, 0xbf, 0xf3, 0x15, 0x1e, 0xc4, 0xe8,
+ 0x1c, 0x75, 0x71, 0xd6, 0xe3, 0x06, 0x46, 0xd8, 0xc2, 0x03, 0x27, 0x5e,
+ 0x34, 0xec, 0x63, 0xf6, 0xad, 0x90, 0xe2, 0x4b, 0xa5, 0x92, 0xb4, 0x81,
+ 0x4c, 0x22, 0x99, 0x2a, 0xb5, 0xf3, 0xa1, 0x6b, 0x11, 0xb8, 0x24, 0xdc,
+ 0x64, 0xde, 0x4e, 0x07, 0x18, 0x17, 0x74, 0x1b, 0xc3, 0xab, 0x18, 0x52,
+ 0xb8, 0xe4, 0x8e, 0x03, 0x5a, 0x6b, 0xe2, 0xf4, 0xa1, 0xdc, 0x07, 0x86,
+ 0x01, 0x77, 0x54, 0xba, 0x43, 0xc4, 0xe2, 0x4a, 0x0c, 0x2b, 0x99, 0xa8,
+ 0x41, 0x0d, 0x23, 0x32, 0xd3, 0xd5, 0x39, 0xbc, 0x91, 0xce, 0xc9, 0x85,
+ 0x63, 0x2d, 0xe2, 0x8e, 0x0d, 0xae, 0x0c, 0x31, 0x82, 0xa7, 0xbd, 0x3f,
+ 0x5c, 0x31, 0x63, 0xe5, 0x00, 0x9a, 0x73, 0xba, 0x37, 0x55, 0xed, 0x24,
+ 0x43, 0xec, 0x38, 0x4c, 0x3a, 0x52, 0x17, 0x95, 0x89, 0x9a, 0x6d, 0xc5,
+ 0xa2, 0xbf, 0x77, 0x41, 0xdc, 0x09, 0x73, 0xb1, 0xcb, 0xab, 0xcf, 0x49,
+ 0x11, 0xc6, 0x57, 0x85, 0xbd, 0x40, 0x05, 0x67, 0xa6, 0x84, 0x55, 0x81,
+ 0xc2, 0xb8, 0xbb, 0xa1, 0x59, 0x49, 0x14, 0xe2, 0xce, 0xcc, 0x7e, 0x2e,
+ 0x4e, 0x59, 0x2c, 0x79, 0x79, 0xe9, 0x52, 0x59, 0x0b, 0x15, 0xa1, 0xbf,
+ 0xd8, 0x42, 0x1b, 0x33, 0x2c, 0xb7, 0xb2, 0x41, 0x9c, 0x26, 0xe6, 0xfd,
+ 0x75, 0xc1, 0x6b, 0x18, 0x8c, 0x3c, 0xbe, 0xec, 0xf4, 0x74, 0xfd, 0xec,
+ 0xd9, 0x7a, 0xeb, 0xcb, 0xd6, 0xde, 0x68, 0x3d, 0x19, 0xad, 0xf7, 0x47,
+ 0x68, 0xb6, 0x1c, 0xad, 0x4f, 0x97, 0xbb, 0x13, 0x24, 0x1f, 0x91, 0x7e,
+ 0xa3, 0x8d, 0x72, 0x69, 0x50, 0x6b, 0xd2, 0x97, 0x99, 0x05, 0x9b, 0xc5,
+ 0x00, 0x42, 0xcb, 0xd2, 0xf4, 0xca, 0xad, 0xff, 0x8e, 0x14, 0xb4, 0xd4,
+ 0xa7, 0x43, 0x02, 0xcf, 0xe7, 0x33, 0xf1, 0x06, 0x16, 0xe3, 0xd5, 0x29,
+ 0x6b, 0xb7, 0x5f, 0xee, 0x78, 0x1b, 0xc7, 0x1f, 0xbb, 0xe6, 0xd2, 0x38,
+ 0x3f, 0x60, 0x53, 0xf8, 0x7a, 0x2e, 0x74, 0xd0, 0x7e, 0x29, 0x8a, 0xe5,
+ 0x4d, 0x0b, 0x8f, 0x8f, 0x96, 0x1d, 0xb2, 0xea, 0x63, 0xfa, 0xfa, 0x04,
+ 0x61, 0x3c, 0xca, 0xb0, 0x37, 0x23, 0x6e, 0x7b, 0x7b, 0x40, 0x2b, 0xd7,
+ 0x6b, 0xac, 0x7d, 0xad, 0xff, 0x70, 0xf5, 0xee, 0xc9, 0xd6, 0x25, 0x65,
+ 0xf5, 0xe9, 0xa9, 0x5c, 0x22, 0xaa, 0x1e, 0x10, 0x55, 0x3a, 0xa4, 0x4c,
+ 0xc9, 0x06, 0x87, 0xaf, 0xfb, 0xf4, 0x95, 0x1e, 0x58, 0xb7, 0xc3, 0xfb,
+ 0x6d, 0x72, 0x5f, 0x0d, 0xb3, 0xaf, 0x44, 0x47, 0x78, 0x94, 0x48, 0x0a,
+ 0xdf, 0xf6, 0x33, 0x2d, 0x3d, 0x7a, 0x69, 0x06, 0x22, 0xc0, 0x0b, 0x34,
+ 0x3d, 0xa6, 0x20, 0x7a, 0xdb, 0x73, 0x33, 0x14, 0xa7, 0x22, 0x82, 0x2e,
+ 0x25, 0x39, 0x4f, 0x12, 0x17, 0xf6, 0x44, 0x07, 0x8d, 0x37, 0xb6, 0x64,
+ 0x70, 0x5d, 0xe5, 0x25, 0x1b, 0xd0, 0xf0, 0xf8, 0x88, 0xf6, 0x99, 0x74,
+ 0xd8, 0xd9, 0x6d, 0x72, 0xf0, 0xef, 0xa8, 0xc9, 0xee, 0x5d, 0x28, 0x9f,
+ 0x94, 0xe6, 0xb8, 0xa1, 0xbc, 0x62, 0x15, 0x21, 0xc0, 0x27, 0x95, 0x2c,
+ 0x46, 0xac, 0x6d, 0xbc, 0x75, 0xb2, 0xa4, 0xca, 0xcc, 0x09, 0x7e, 0xaa,
+ 0xa6, 0x69, 0xff, 0x53, 0xbf, 0xfc, 0x97, 0xd3, 0xa5, 0x6e, 0x19, 0x4d,
+ 0xf8, 0x8a, 0xb8, 0x90, 0xbc, 0xe5, 0x6e, 0xfd, 0xc2, 0x9f, 0x65, 0x53,
+ 0x70, 0x76, 0xfa, 0x74, 0x89, 0x82, 0x12, 0xb3, 0xe2, 0xef, 0x5c, 0xc1,
+ 0x10, 0x41, 0xf1, 0x3e, 0x20, 0xea, 0x05, 0xec, 0xf9, 0xb2, 0xb4, 0xe0,
+ 0xe1, 0x32, 0xc6, 0xf8, 0xd9, 0x3e, 0x7a, 0x19, 0x75, 0xe1, 0x64, 0xc9,
+ 0x7d, 0x7b, 0x44, 0x6e, 0xeb, 0x86, 0xf7, 0xb0, 0xd1, 0x21, 0xa7, 0xb8,
+ 0xc1, 0x6c, 0x8e, 0x5e, 0xb0, 0xa8, 0x7d, 0xae, 0x1a, 0xb0, 0xf1, 0x52,
+ 0x52, 0x5b, 0x65, 0x4f, 0x23, 0x2b, 0x32, 0xc1, 0x89, 0xe3, 0x90, 0x74,
+ 0xe5, 0x30, 0x9c, 0x2d, 0x3c, 0xa9, 0x9c, 0xfe, 0x88, 0xc6, 0xe6, 0x0b,
+ 0x78, 0xe9, 0x34, 0x51, 0xac, 0xae, 0x25, 0xba, 0x35, 0x54, 0x2b, 0x12,
+ 0x64, 0xad, 0x36, 0xab, 0x1d, 0xd9, 0x69, 0xcc, 0xc6, 0x7e, 0x36, 0xab,
+ 0x0e, 0x64, 0x70, 0x70, 0xca, 0xa9, 0x5a, 0xf2, 0x39, 0x50, 0x19, 0x2d,
+ 0xbb, 0xb4, 0xfc, 0x81, 0x80, 0x87, 0xec, 0x4f, 0x02, 0x58, 0xec, 0x61,
+ 0x5b, 0x58, 0x57, 0x3c, 0x69, 0xb8, 0x9c, 0x81, 0xe7, 0x59, 0xb0, 0x80,
+ 0x2f, 0xa7, 0x59, 0x70, 0x49, 0x08, 0xae, 0x4a, 0xe7, 0x09, 0x06, 0x57,
+ 0x5c, 0x0d, 0x52, 0xc1, 0x70, 0x01, 0x5b, 0xe0, 0xa6, 0xe7, 0xdd, 0xa7,
+ 0xde, 0x15, 0x83, 0x53, 0x18, 0x16, 0x2f, 0x0a, 0x01, 0xd6, 0xd4, 0x94,
+ 0x9d, 0xe2, 0x1a, 0xab, 0x4b, 0xe0, 0x73, 0xaf, 0xe1, 0x73, 0x00, 0xb3,
+ 0x14, 0xca, 0xc0, 0xab, 0xf2, 0xc2, 0xad, 0x33, 0x38, 0x18, 0xee, 0x5e,
+ 0xbb, 0x7d, 0x46, 0x37, 0x77, 0xb2, 0x50, 0x4f, 0x54, 0x80, 0xd7, 0x95,
+ 0xc4, 0x37, 0x8c, 0x4d, 0x2c, 0x2b, 0x67, 0x3c, 0x02, 0x84, 0x11, 0xb1,
+ 0xca, 0xf6, 0x32, 0x6f, 0x3f, 0xbb, 0x1c, 0xd9, 0x30, 0x90, 0xde, 0x11,
+ 0xcb, 0x96, 0x9d, 0xe2, 0x79, 0xc5, 0x79, 0x40, 0xdb, 0x30, 0x66, 0xc2,
+ 0x57, 0xa6, 0x77, 0x39, 0x7d, 0xaa, 0x44, 0xe5, 0x62, 0xd9, 0xa0, 0x6e,
+ 0x12, 0xf3, 0xe0, 0x5c, 0x4b, 0x2c, 0x40, 0xc6, 0x61, 0xd5, 0xf2, 0xc5,
+ 0xcb, 0x84, 0xf6, 0x32, 0x53, 0x83, 0x16, 0x4b, 0x17, 0xa3, 0xdc, 0x95,
+ 0x13, 0x97, 0xa5, 0x70, 0x9c, 0x16, 0x67, 0x4d, 0x8b, 0x4e, 0x98, 0x67,
+ 0x1c, 0x7b, 0x10, 0xc4, 0xd3, 0x1a, 0xd0, 0x98, 0x10, 0x18, 0x83, 0xd9,
+ 0x58, 0x27, 0x24, 0x6b, 0x86, 0x26, 0xb6, 0x72, 0x1e, 0x0a, 0x94, 0x90,
+ 0xa0, 0x53, 0xcf, 0x37, 0x24, 0x66, 0x3b, 0x94, 0xcc, 0x53, 0x67, 0x04,
+ 0xb9, 0x0c, 0x16, 0x9a, 0xe0, 0x46, 0x22, 0x44, 0x2c, 0xb8, 0xb4, 0xed,
+ 0xfc, 0xb3, 0xac, 0x74, 0xc1, 0xa1, 0x18, 0x54, 0xbb, 0x6a, 0xea, 0x42,
+ 0xbc, 0x5f, 0x57, 0x19, 0x78, 0x99, 0x8d, 0x5c, 0x9a, 0x45, 0x54, 0xff,
+ 0xd9, 0x5a, 0xcb, 0xa4, 0x01, 0xf5, 0xe9, 0x12, 0x06, 0x21, 0x87, 0xda,
+ 0x2f, 0x4a, 0x64, 0x14, 0xa4, 0x5c, 0x4b, 0xd0, 0xc6, 0x14, 0x49, 0xbf,
+ 0x79, 0xca, 0x77, 0x19, 0x17, 0x42, 0x9d, 0xdb, 0x90, 0xe3, 0x83, 0x85,
+ 0x40, 0x1a, 0xca, 0x14, 0x31, 0xe3, 0x3f, 0x28, 0x00, 0x12, 0xa5, 0xe0,
+ 0x73, 0xee, 0x34, 0x66, 0xb0, 0x43, 0xc1, 0xb4, 0x14, 0x2e, 0xac, 0x74,
+ 0x1e, 0x94, 0x6f, 0x11, 0x83, 0xee, 0xa2, 0xf4, 0xc4, 0x39, 0xa1, 0xeb,
+ 0xc6, 0xf9, 0x1f, 0x4e, 0x53, 0x1c, 0x54, 0x8c, 0x44, 0x06, 0xca, 0x16,
+ 0xbd, 0xf5, 0x2e, 0x40, 0xfb, 0x90, 0x8d, 0x42, 0x1e, 0x73, 0xb6, 0xe0,
+ 0x92, 0xb0, 0xbb, 0x73, 0x9c, 0xc5, 0x8e, 0xae, 0xf4, 0x1d, 0x95, 0x7d,
+ 0xf0, 0x08, 0x02, 0x69, 0xb6, 0xd2, 0xff, 0xa9, 0x55, 0xcc, 0x83, 0x08,
+ 0xa6, 0xb0, 0x00, 0xf8, 0xf0, 0xc1, 0x48, 0x33, 0x0f, 0x83, 0x1b, 0x3b,
+ 0x76, 0x9c, 0x6f, 0xa7, 0x5d, 0xf8, 0xc0, 0xfc, 0x92, 0xa2, 0x6b, 0xdc,
+ 0xfd, 0x49, 0xe6, 0x3b, 0xa1, 0x4a, 0xc9, 0x84, 0xde, 0xe5, 0xcd, 0x6e,
+ 0xe6, 0xfe, 0x79, 0x14, 0x92, 0x6d, 0x86, 0x94, 0xce, 0x4a, 0x4a, 0xd5,
+ 0x79, 0x39, 0xae, 0x28, 0x4e, 0x71, 0x6b, 0x9a, 0x9c, 0xa7, 0xd5, 0x43,
+ 0xc4, 0x3c, 0xef, 0xa4, 0xcd, 0xca, 0x25, 0xff, 0x4a, 0x0e, 0x41, 0x4b,
+ 0xd1, 0xbf, 0xbd, 0xcc, 0x33, 0x89, 0x9c, 0x43, 0x6e, 0x8a, 0x23, 0xcd,
+ 0xe4, 0xc4, 0x1f, 0x2d, 0x00, 0xa2, 0x72, 0xa1, 0xbf, 0xdb, 0x5d, 0x4f,
+ 0x78, 0xe3, 0x65, 0xc9, 0x52, 0x29, 0xc9, 0xa4, 0xc4, 0xed, 0x93, 0xce,
+ 0xbe, 0xa7, 0x30, 0xa4, 0x00, 0x23, 0x6f, 0x5d, 0x14, 0x97, 0x0f, 0x8a,
+ 0x45, 0x24, 0x02, 0xdc, 0x52, 0x20, 0x84, 0xb1, 0x8f, 0x0f, 0x43, 0x03,
+ 0x9f, 0x45, 0x58, 0xad, 0x5c, 0x62, 0x29, 0x36, 0xb2, 0xf1, 0x76, 0x61,
+ 0x5d, 0xb2, 0x8b, 0xdc, 0xd2, 0x96, 0x74, 0xea, 0xfa, 0xdd, 0x45, 0xbc,
+ 0x4a, 0x91, 0xa6, 0x58, 0x10, 0x74, 0xf7, 0x2c, 0x97, 0xa6, 0x2e, 0x84,
+ 0x42, 0x6e, 0xa1, 0x74, 0xf5, 0xb4, 0x9e, 0x0d, 0x42, 0xf7, 0x07, 0x12,
+ 0x12, 0x2c, 0xc9, 0xed, 0x78, 0x8c, 0x1b, 0x09, 0x05, 0x5c, 0x2b, 0x12,
+ 0x0f, 0xf4, 0x2d, 0x0a, 0x16, 0x6f, 0xd6, 0x0f, 0x63, 0x09, 0x56, 0x74,
+ 0x27, 0x24, 0xb4, 0x13, 0x7b, 0xe4, 0x64, 0x9d, 0x73, 0xd1, 0xa8, 0x8a,
+ 0x0e, 0xd2, 0x9f, 0x2e, 0x28, 0x74, 0x11, 0xa4, 0x94, 0x3f, 0x36, 0x92,
+ 0xc0, 0xc3, 0xf6, 0x27, 0x9f, 0xd5, 0x55, 0x47, 0x80, 0x58, 0x5a, 0x7c,
+ 0xce, 0x26, 0xc7, 0xd1, 0x17, 0xe5, 0x89, 0x7b, 0x06, 0x24, 0x4d, 0x30,
+ 0xd2, 0xbe, 0x06, 0x6c, 0xc8, 0xb7, 0xb0, 0xcd, 0x48, 0xc9, 0x3b, 0x03,
+ 0x2a, 0xa1, 0x20, 0x69, 0x98, 0xcb, 0xe4, 0x8a, 0xf1, 0x40, 0xe1, 0x9d,
+ 0xf3, 0x44, 0x8a, 0x33, 0x71, 0xe8, 0x8e, 0xbc, 0x8a, 0x70, 0x46, 0x8e,
+ 0x29, 0x6f, 0x9b, 0xe3, 0x2e, 0xef, 0x09, 0x31, 0x97, 0xb1, 0xa8, 0x35,
+ 0xa1, 0x96, 0xcf, 0xc7, 0xa9, 0x4a, 0xa1, 0x52, 0x4d, 0x91, 0xf5, 0xc9,
+ 0x39, 0x78, 0xf3, 0xb9, 0x4d, 0x99, 0xf0, 0xae, 0xfe, 0x51, 0x6f, 0x75,
+ 0x62, 0xf1, 0x2d, 0x90, 0xad, 0xb6, 0x19, 0x86, 0x6a, 0x33, 0x2c, 0x5c,
+ 0x12, 0x6d, 0xd7, 0x06, 0x31, 0xbe, 0xf0, 0x6a, 0x27, 0x34, 0xbb, 0xf9,
+ 0x45, 0x71, 0x83, 0x7f, 0xc6, 0x66, 0xe9, 0x08, 0x0b, 0xe4, 0x2d, 0x80,
+ 0x60, 0x4f, 0xc1, 0x0a, 0x96, 0x64, 0x79, 0x94, 0x61, 0x80, 0x57, 0xf3,
+ 0x6c, 0x8f, 0x37, 0xb7, 0x11, 0xbf, 0x0f, 0x06, 0x3a, 0x2d, 0x43, 0xa5,
+ 0xed, 0x98, 0x2a, 0xe9, 0x65, 0x12, 0xd9, 0x62, 0x6b, 0x48, 0xbc, 0x23,
+ 0x1f, 0x34, 0xc4, 0x7c, 0xe8, 0x56, 0x11, 0x2e, 0xd1, 0xb7, 0x89, 0x4f,
+ 0x75, 0x45, 0xae, 0xaa, 0x24, 0x11, 0xcb, 0xb6, 0x76, 0x9b, 0x25, 0x0c,
+ 0xa5, 0x4f, 0x2e, 0x88, 0xf7, 0x84, 0x54, 0xce, 0x4e, 0xf9, 0xfe, 0xe8,
+ 0xdc, 0xa5, 0xba, 0xca, 0xa4, 0x4d, 0xd0, 0xa8, 0x44, 0x44, 0x3f, 0x38,
+ 0xf3, 0x70, 0x2c, 0x49, 0x4e, 0x3e, 0x42, 0xe2, 0xb0, 0x09, 0xa1, 0x13,
+ 0x09, 0x60, 0xe2, 0xa2, 0xb0, 0x7f, 0xb3, 0x1d, 0x94, 0x4e, 0x65, 0x47,
+ 0xd9, 0xb0, 0xe3, 0x98, 0xd3, 0x87, 0x3b, 0x4f, 0xa5, 0x21, 0xbe, 0x9e,
+ 0xcb, 0x79, 0x22, 0x35, 0xee, 0x72, 0xbd, 0x37, 0x3e, 0x2c, 0xf5, 0xa3,
+ 0xbd, 0xf1, 0xd7, 0xf2, 0xcf, 0x93, 0x52, 0x3d, 0x78, 0x70, 0xbe, 0x5d,
+ 0x75, 0xe7, 0xbf, 0x05, 0xc7, 0xe3, 0x01, 0xdb, 0x5e, 0xfd, 0xa7, 0x67,
+ 0x9a, 0x16, 0x84, 0x88, 0x82, 0xbe, 0x49, 0x48, 0x91, 0xe1, 0xd1, 0xcf,
+ 0xe7, 0xbf, 0xc9, 0x3b, 0x53, 0x7a, 0x07, 0xa6, 0x50, 0x9e, 0xc7, 0xea,
+ 0x25, 0xb0, 0xf0, 0xe3, 0x4d, 0x1e, 0xf0, 0x51, 0xba, 0xb5, 0xfe, 0x44,
+ 0x51, 0x04, 0xca, 0xb5, 0x3b, 0xcf, 0x4a, 0x8c, 0xf7, 0xe1, 0x9e, 0xf1,
+ 0xf6, 0xb2, 0x07, 0x01, 0x47, 0x37, 0x47, 0xf3, 0x54, 0xd1, 0xbf, 0xbb,
+ 0x93, 0x8b, 0xb5, 0x26, 0x93, 0xcc, 0x09, 0x27, 0xbd, 0x0e, 0xf3, 0x3f,
+ 0xe0, 0x7d, 0xfb, 0xef, 0x0e, 0xae, 0xf7, 0xe3, 0xf0, 0xf9, 0x76, 0xb9,
+ 0xf3, 0x60, 0xf7, 0x6d, 0xae, 0xbf, 0x7b, 0xa6, 0xf1, 0x19, 0xff, 0xbe,
+ 0xcd, 0x31, 0xe2, 0xd1, 0x3d, 0x23, 0x92, 0xff, 0x77, 0x8b, 0x60, 0x36,
+ 0xd1, 0x8e, 0xf6, 0x8c, 0x06, 0x5c, 0x7f, 0x4f, 0x0e, 0x00, 0xe1, 0xfc,
+ 0x78, 0xda, 0xe2, 0x0a, 0x06, 0xc7, 0x68, 0xe4, 0xb0, 0xbb, 0x43, 0x07,
+ 0x9f, 0x9e, 0x55, 0x0d, 0x97, 0x5b, 0xf4, 0x6f, 0xc7, 0xa8, 0x8a, 0x4f,
+ 0xd6, 0x5b, 0x24, 0x0a, 0x14, 0x1e, 0xd0, 0x17, 0xd9, 0x85, 0xdf, 0xd6,
+ 0xbb, 0x6b, 0x75, 0xc7, 0xf3, 0x1f, 0xe8, 0x09, 0x1a, 0x78, 0x5e, 0xfa,
+ 0x33, 0x48, 0xc9, 0x06, 0xff, 0xaf, 0xff, 0xaa, 0x71, 0xbb, 0xd0, 0x5b,
+ 0xe1, 0xe8, 0xd2, 0x98, 0xc3, 0x34, 0x49, 0x2b, 0x8a, 0xe2, 0x0d, 0x63,
+ 0x6d, 0xe7, 0xbf, 0x00, 0x8c, 0xe0, 0xbf, 0x88, 0x83, 0x82, 0x74, 0x23,
+ 0xcb, 0x34, 0x32, 0x78, 0xb1, 0xb4, 0x8d, 0xe8, 0x44, 0x1a, 0x6a, 0x49,
+ 0xce, 0x15, 0xee, 0x01, 0x15, 0x28, 0x8a, 0x68, 0xea, 0xdd, 0x8d, 0xde,
+ 0x82, 0xf4, 0xa5, 0xc4, 0xae, 0x4b, 0x47, 0x1b, 0x13, 0xe3, 0x87, 0x0f,
+ 0x89, 0x08, 0x0c, 0xdf, 0xc5, 0x13, 0x0c, 0xd1, 0x3b, 0x63, 0x73, 0x7a,
+ 0x2c, 0x4f, 0xab, 0xf0, 0x38, 0x6b, 0x3e, 0x46, 0x57, 0xe3, 0x17, 0xc7,
+ 0x7a, 0xeb, 0x45, 0x79, 0x39, 0xd6, 0x93, 0xf1, 0x96, 0x73, 0x82, 0xc2,
+ 0xcb, 0x5c, 0xda, 0x60, 0x53, 0x2b, 0x0d, 0x4f, 0x6c, 0xc9, 0x94, 0x3c,
+ 0xed, 0x8d, 0x67, 0xd1, 0x74, 0x1d, 0xb7, 0x07, 0xd7, 0xdc, 0xba, 0xcd,
+ 0xc1, 0x9c, 0xf5, 0x0c, 0x14, 0xfc, 0x88, 0x56, 0x3b, 0xe9, 0xc8, 0x50,
+ 0x69, 0xb3, 0x9e, 0x4f, 0x08, 0xa0, 0x19, 0xc0, 0x95, 0x77, 0x62, 0x67,
+ 0x83, 0x5f, 0x2c, 0x96, 0xb9, 0x97, 0x34, 0x76, 0x38, 0x90, 0xe3, 0x1c,
+ 0x2f, 0xe1, 0xec, 0x4a, 0x95, 0x64, 0x6f, 0x0b, 0x74, 0x16, 0x72, 0xcc,
+ 0xf1, 0x93, 0x17, 0x4d, 0x4e, 0x93, 0xf8, 0xde, 0x85, 0x65, 0x5e, 0x98,
+ 0x50, 0x26, 0xf8, 0x67, 0x6c, 0x72, 0xfc, 0x77, 0x05, 0x53, 0xe6, 0xec,
+ 0xc6, 0x48, 0x5c, 0x5a, 0xdb, 0x46, 0xc5, 0x69, 0xb5, 0xb3, 0xe9, 0x39,
+ 0x71, 0x7b, 0x89, 0xba, 0xdd, 0x3a, 0xe2, 0x3b, 0x24, 0x9c, 0xab, 0x12,
+ 0x23, 0x4f, 0xb7, 0x50, 0x9b, 0x14, 0xbb, 0xe0, 0xb4, 0xb1, 0xe0, 0x87,
+ 0x8c, 0x89, 0xeb, 0x09, 0xc7, 0x90, 0x6a, 0xd0, 0x4d, 0x33, 0x43, 0x96,
+ 0xcc, 0xf8, 0x51, 0x7d, 0xbf, 0xb9, 0x5f, 0x54, 0xe9, 0x02, 0x19, 0x29,
+ 0x6c, 0x4c, 0x6f, 0xe4, 0x71, 0x6e, 0xd4, 0xce, 0x67, 0x9f, 0x51, 0xb2,
+ 0xc4, 0x2a, 0xb0, 0x9c, 0x9d, 0xc4, 0xa3, 0x09, 0x29, 0xa8, 0xe1, 0x12,
+ 0x94, 0x67, 0x20, 0x3b, 0x02, 0xc9, 0x02, 0x8e, 0xef, 0x5a, 0x00, 0x51,
+ 0xf4, 0xe3, 0x1f, 0xf5, 0x63, 0xb8, 0x93, 0x20, 0x63, 0x8f, 0xd2, 0x04,
+ 0x4c, 0x02, 0xda, 0xa4, 0xcd, 0x93, 0xf1, 0xe1, 0x4c, 0x3f, 0x9a, 0x8c,
+ 0x0f, 0xfe, 0x17, 0xff, 0x30, 0x06, 0x21, 0x49, 0xb4, 0xaf, 0xde, 0x77,
+ 0x66, 0xa5, 0x27, 0x4f, 0x1f, 0x7c, 0x09, 0x3e, 0xa8, 0x91, 0xae, 0x75,
+ 0x1c, 0xd6, 0xf9, 0x9d, 0x40, 0xee, 0x25, 0xdc, 0x4c, 0x8d, 0xd6, 0x93,
+ 0x6f, 0xd7, 0xeb, 0x4f, 0xfc, 0x05, 0xcc, 0xa6, 0x2f, 0xa4, 0xea, 0xfc,
+ 0xb5, 0xe5, 0xaf, 0x25, 0x7f, 0xfe, 0x44, 0xd7, 0x99, 0x77, 0xfc, 0x6d,
+ 0xef, 0x5b, 0x82, 0xc9, 0x2f, 0xb3, 0x85, 0x99, 0x7d, 0xf6, 0xfe, 0x3c,
+ 0x31, 0x00, 0xa3, 0x96, 0xf3, 0x35, 0x63, 0xd4, 0xb3, 0xbd, 0x35, 0x18,
+ 0x9f, 0xe9, 0x2f, 0x4e, 0x74, 0xd2, 0xda, 0xe4, 0xef, 0x3a, 0xe3, 0x73,
+ 0xb0, 0xdf, 0x66, 0x81, 0xe0, 0x03, 0x21, 0x78, 0x9f, 0x08, 0xe6, 0x0a,
+ 0xb6, 0xb8, 0x16, 0x1b, 0x22, 0x14, 0x9a, 0x74, 0x58, 0xd2, 0x30, 0x9d,
+ 0x9c, 0x23, 0x5e, 0x9f, 0x06, 0xeb, 0xb5, 0x2e, 0x9a, 0xf5, 0x9a, 0x8f,
+ 0xf9, 0x26, 0xf4, 0xca, 0x87, 0x5d, 0x0d, 0x33, 0xe4, 0x17, 0x44, 0x06,
+ 0x45, 0xaf, 0x71, 0x68, 0x38, 0x21, 0xe2, 0xb1, 0x10, 0x71, 0x40, 0x44,
+ 0x38, 0xaa, 0x21, 0x25, 0xa1, 0xaa, 0xde, 0xaf, 0xc8, 0x59, 0xe6, 0xe4,
+ 0xb3, 0xf8, 0x26, 0x02, 0x8b, 0x95, 0xb9, 0xc2, 0xb9, 0x3f, 0x06, 0xca,
+ 0x48, 0x92, 0x9b, 0x5b, 0xef, 0x69, 0x50, 0x24, 0x04, 0x69, 0x9e, 0xb9,
+ 0x7c, 0x34, 0xf9, 0x76, 0x93, 0xb4, 0x47, 0xc7, 0x4c, 0x99, 0x23, 0xe7,
+ 0xc1, 0x17, 0x44, 0x1e, 0xf0, 0x01, 0xb8, 0x37, 0xdc, 0x7a, 0x3f, 0x8a,
+ 0x79, 0xb2, 0x2d, 0xde, 0xd4, 0x4e, 0x42, 0x03, 0xee, 0x09, 0x4e, 0xc7,
+ 0x26, 0x63, 0xa2, 0xe4, 0x4b, 0x08, 0xd5, 0x83, 0xcf, 0x1a, 0x81, 0xe7,
+ 0x53, 0xf6, 0x7b, 0x58, 0xf6, 0x57, 0xb2, 0xec, 0xc7, 0x71, 0xd9, 0x9b,
+ 0xa3, 0x89, 0x93, 0xc6, 0x2f, 0xf9, 0x05, 0x12, 0xcb, 0x1f, 0x4d, 0x2e,
+ 0x60, 0x33, 0x21, 0x2e, 0xc8, 0x13, 0xea, 0x63, 0xbe, 0x44, 0x3b, 0x5f,
+ 0x34, 0x61, 0xa9, 0x3a, 0x91, 0x94, 0x61, 0x2b, 0x14, 0xbb, 0x5d, 0x5c,
+ 0x0e, 0x01, 0x4e, 0xb2, 0x82, 0x8a, 0x00, 0x71, 0xe8, 0xfc, 0x8c, 0x46,
+ 0x5d, 0xb3, 0xb3, 0xa9, 0x87, 0x72, 0x94, 0x48, 0x11, 0x3d, 0x0d, 0xfc,
+ 0x25, 0x4a, 0x93, 0xff, 0x70, 0x86, 0xfb, 0x8f, 0xa4, 0xee, 0xdb, 0xe1,
+ 0xf1, 0x5d, 0x18, 0x51, 0x77, 0xae, 0xcc, 0xd5, 0x66, 0x22, 0xcc, 0x91,
+ 0x71, 0xeb, 0xa5, 0x96, 0xcd, 0xe8, 0xef, 0xc0, 0xdf, 0x03, 0x00, 0x28,
+ 0xfe, 0xfa, 0x50, 0xec, 0xa4, 0x00, 0x93, 0x1b, 0xc0, 0x15, 0x2d, 0x7c,
+ 0x73, 0x1f, 0x10, 0x07, 0xe9, 0x44, 0x06, 0x5a, 0xfa, 0x3c, 0x91, 0xea,
+ 0x36, 0xb7, 0x87, 0xe0, 0x12, 0x04, 0x7a, 0xa4, 0x95, 0xcb, 0x02, 0xa6,
+ 0x6f, 0x75, 0x79, 0xf0, 0xb2, 0x63, 0xd2, 0x6e, 0xd9, 0x14, 0x3d, 0x39,
+ 0x02, 0x93, 0x3d, 0xce, 0x07, 0x93, 0x73, 0xe1, 0x94, 0x5c, 0x4b, 0x5b,
+ 0xc3, 0x1d, 0xdd, 0x29, 0x0c, 0x59, 0x5f, 0x1f, 0x62, 0xf4, 0xaf, 0x43,
+ 0xfb, 0xcf, 0x20, 0x0b, 0x78, 0xe8, 0x90, 0xd3, 0x9b, 0x9b, 0x3c, 0xd9,
+ 0xa2, 0xaf, 0xf1, 0xc0, 0x44, 0x5b, 0x89, 0xf6, 0x5c, 0x47, 0x01, 0x5c,
+ 0x67, 0x42, 0xd0, 0x1e, 0x47, 0xfe, 0x02, 0x0d, 0xfb, 0x4f, 0x39, 0xea,
+ 0xb8, 0x53, 0x6b, 0x03, 0xf6, 0x46, 0xfb, 0x38, 0x54, 0x64, 0x97, 0x9a,
+ 0x09, 0x2f, 0x1c, 0x0c, 0x9a, 0xb3, 0xb8, 0x41, 0x31, 0xda, 0x08, 0x89,
+ 0x16, 0x42, 0x78, 0x3f, 0x09, 0xe9, 0x51, 0x59, 0xdf, 0x41, 0x3a, 0x92,
+ 0xd5, 0xea, 0xf1, 0x48, 0x7f, 0xc5, 0x37, 0xbe, 0x4e, 0xa8, 0x3d, 0x78,
+ 0xaa, 0x8e, 0x53, 0x3b, 0x20, 0x80, 0x1f, 0xe7, 0xf7, 0x93, 0x7a, 0x5c,
+ 0x07, 0x1d, 0x93, 0xe1, 0xc0, 0x34, 0xee, 0x21, 0x8f, 0xfb, 0xcd, 0x58,
+ 0x8a, 0x28, 0xe1, 0xf1, 0xc1, 0x52, 0xbe, 0xd9, 0xcc, 0x18, 0x75, 0x43,
+ 0x56, 0x33, 0x5f, 0xef, 0x3e, 0x51, 0x33, 0xa0, 0xf8, 0xb1, 0xf0, 0xf7,
+ 0x2e, 0x6f, 0xec, 0xde, 0x56, 0xa5, 0x64, 0x2b, 0x67, 0x52, 0x06, 0xe4,
+ 0xe8, 0x57, 0xc9, 0x9e, 0x94, 0x75, 0xb2, 0xa2, 0x6f, 0x78, 0x39, 0x4f,
+ 0x58, 0x1c, 0x7a, 0xbb, 0x21, 0x79, 0x87, 0x9b, 0xab, 0x92, 0x52, 0xf7,
+ 0x30, 0xaf, 0xb4, 0x89, 0x17, 0x9b, 0x49, 0x29, 0x08, 0xa2, 0xb4, 0xd0,
+ 0xc7, 0x13, 0x8e, 0x08, 0x62, 0x71, 0xba, 0xc8, 0x14, 0x31, 0x6c, 0x4e,
+ 0x53, 0xac, 0x77, 0x8d, 0xe9, 0x86, 0xe2, 0x63, 0xa9, 0xf2, 0x7b, 0x04,
+ 0x6a, 0x48, 0xdd, 0xa0, 0xf3, 0xce, 0x9d, 0x00, 0xf3, 0x67, 0x6b, 0x64,
+ 0x4d, 0xbc, 0x17, 0x3e, 0xb7, 0xcb, 0x87, 0x71, 0x56, 0x05, 0x4d, 0xa2,
+ 0x92, 0x0e, 0x46, 0x69, 0x84, 0x08, 0x95, 0x2d, 0x24, 0xea, 0x4a, 0x6b,
+ 0x5d, 0xf0, 0xe6, 0x0f, 0xa2, 0xce, 0x6e, 0xc4, 0x53, 0x12, 0x10, 0x60,
+ 0x3f, 0x97, 0x3e, 0xb6, 0x85, 0x12, 0x47, 0xc2, 0x67, 0xac, 0x69, 0x14,
+ 0x3e, 0xd4, 0xc8, 0x6e, 0xf6, 0xca, 0x18, 0x56, 0x7e, 0xda, 0x49, 0xd1,
+ 0x08, 0xf2, 0x40, 0x4f, 0x24, 0xbd, 0x27, 0xdb, 0xe2, 0x12, 0x31, 0xc3,
+ 0x3e, 0x8b, 0x3f, 0xe8, 0xb1, 0x70, 0x07, 0x30, 0x25, 0x9f, 0x83, 0x14,
+ 0x35, 0x7a, 0x76, 0x90, 0x18, 0xe8, 0x97, 0xdc, 0x10, 0x55, 0x19, 0xf7,
+ 0x0b, 0x0c, 0x42, 0xa2, 0x4c, 0xa8, 0xf8, 0xf8, 0x37, 0xd4, 0x36, 0x1e,
+ 0x39, 0x8f, 0xfd, 0xc2, 0xb4, 0x31, 0x48, 0x5f, 0xb1, 0x0f, 0x5b, 0xdf,
+ 0xdd, 0xa3, 0x15, 0xaa, 0x5e, 0xaa, 0x6d, 0x2a, 0xee, 0x24, 0xbb, 0x89,
+ 0x79, 0xa5, 0xcd, 0x1e, 0xc5, 0x50, 0x5c, 0x6e, 0xc2, 0x99, 0xdf, 0x1c,
+ 0xe7, 0xe9, 0x66, 0x8b, 0xb6, 0xa9, 0x4b, 0x2b, 0x38, 0x95, 0x36, 0x32,
+ 0x4e, 0x06, 0xc5, 0x88, 0x34, 0x4e, 0x96, 0x1c, 0xe4, 0xd8, 0x35, 0xd2,
+ 0x57, 0xa6, 0xbe, 0xec, 0x16, 0x1e, 0x57, 0x5c, 0xc6, 0x73, 0x8a, 0x9f,
+ 0xf4, 0x28, 0x69, 0xf1, 0xb9, 0x43, 0xd2, 0xcd, 0x6c, 0xe6, 0xad, 0xe4,
+ 0xff, 0x48, 0x65, 0x7f, 0x0e, 0xe9, 0x27, 0x9e, 0xe9, 0xcf, 0x3e, 0x2b,
+ 0x39, 0x0a, 0xd5, 0x6c, 0x58, 0xe9, 0xe0, 0x16, 0xda, 0xce, 0x55, 0x46,
+ 0x5d, 0x4b, 0xc0, 0xb0, 0x92, 0xa2, 0x98, 0x52, 0x8c, 0x73, 0xdb, 0xb1,
+ 0x9d, 0xc4, 0xc0, 0xe6, 0xa9, 0x84, 0x87, 0x98, 0x9b, 0x9c, 0x97, 0x7f,
+ 0x16, 0x1f, 0xa2, 0x0e, 0x17, 0xa3, 0x43, 0xfd, 0x9b, 0x04, 0x97, 0x5c,
+ 0xbe, 0xfb, 0xf3, 0x87, 0xfb, 0x06, 0xe0, 0x80, 0x51, 0x0b, 0x94, 0xb8,
+ 0xa3, 0x90, 0xa1, 0x3c, 0x1c, 0x7a, 0x05, 0x3d, 0x74, 0x0d, 0x23, 0x03,
+ 0xa8, 0x08, 0xc4, 0x9e, 0xc3, 0xf7, 0x67, 0x13, 0xdf, 0x45, 0xed, 0x33,
+ 0x5c, 0x6a, 0x90, 0xa7, 0x93, 0x0d, 0x4e, 0x8f, 0x24, 0xf9, 0xea, 0x39,
+ 0x5a, 0x24, 0x82, 0xbf, 0xc3, 0xab, 0xdd, 0x65, 0x92, 0xa5, 0x24, 0x3b,
+ 0x77, 0x37, 0xd9, 0x02, 0xfe, 0xc3, 0xb4, 0x4d, 0x8c, 0x74, 0x22, 0xfc,
+ 0xc4, 0x7c, 0x12, 0x3c, 0xa3, 0x61, 0x22, 0x3c, 0xc9, 0x83, 0xb7, 0x26,
+ 0x1c, 0x31, 0xe1, 0xf3, 0xa4, 0x21, 0x99, 0x2f, 0x51, 0x55, 0x32, 0x91,
+ 0x74, 0x24, 0x5e, 0xb9, 0x9f, 0xbf, 0x91, 0x40, 0x41, 0x0d, 0x92, 0x8e,
+ 0x50, 0x83, 0x68, 0xa7, 0xfc, 0x2f, 0x38, 0x70, 0xeb, 0x7c, 0xf6, 0x90,
+ 0x07, 0x7a, 0x98, 0x45, 0x0b, 0x11, 0x62, 0xd7, 0x49, 0x52, 0xac, 0x50,
+ 0x3e, 0xde, 0x19, 0xce, 0x5d, 0x9b, 0xcb, 0x7c, 0x73, 0xee, 0xdb, 0x53,
+ 0xa3, 0x55, 0x32, 0x4c, 0xac, 0xfc, 0xc4, 0xbb, 0xb7, 0x66, 0x4e, 0x64,
+ 0x2b, 0x99, 0xda, 0xcf, 0xcc, 0x7e, 0xcb, 0xbe, 0x3b, 0x5a, 0x8e, 0xcd,
+ 0x54, 0xe9, 0x31, 0x08, 0x29, 0xe3, 0xb4, 0x25, 0xf7, 0xc3, 0x97, 0x5d,
+ 0x3f, 0xc8, 0xb9, 0xcf, 0xf8, 0x2c, 0x1c, 0x92, 0xdb, 0x49, 0xb4, 0xbc,
+ 0xef, 0x0f, 0xef, 0x49, 0xb3, 0xc3, 0x28, 0xa9, 0xc2, 0x0c, 0x97, 0xc0,
+ 0x4d, 0x14, 0x24, 0xdb, 0x41, 0xa3, 0x32, 0x34, 0xa5, 0x55, 0x04, 0x9a,
+ 0x5d, 0x75, 0xe3, 0x5f, 0x53, 0x49, 0xf1, 0x7b, 0x49, 0xbb, 0x57, 0xdd,
+ 0x0c, 0x9b, 0xab, 0xa2, 0x04, 0x59, 0x9d, 0x6d, 0x48, 0x4e, 0x12, 0x9e,
+ 0x22, 0xaf, 0x86, 0xc2, 0xed, 0x51, 0xc7, 0xa5, 0x1d, 0xc1, 0xde, 0x91,
+ 0xce, 0x8e, 0xa2, 0x16, 0x27, 0x07, 0xa7, 0xdc, 0xf9, 0xce, 0xce, 0xb7,
+ 0xa6, 0x12, 0x3a, 0xc4, 0x06, 0x1b, 0xf2, 0x48, 0x97, 0xb1, 0x8d, 0xdb,
+ 0x1f, 0x41, 0xbe, 0x64, 0x8b, 0x11, 0xb9, 0x5b, 0x35, 0xdc, 0x90, 0xcd,
+ 0xdd, 0xb9, 0xca, 0x1b, 0x1b, 0x5c, 0x43, 0xa5, 0x04, 0x67, 0xb6, 0xa5,
+ 0x5b, 0x2a, 0xa1, 0x18, 0xad, 0x6d, 0x3e, 0x63, 0xc9, 0xcb, 0x4b, 0x2b,
+ 0x14, 0x47, 0x99, 0xba, 0x16, 0xd3, 0xc4, 0x1d, 0x66, 0x48, 0x15, 0x73,
+ 0xf1, 0x5b, 0x7c, 0x0f, 0xbb, 0xf9, 0x03, 0x1f, 0xbb, 0xbb, 0xb0, 0x7b,
+ 0x38, 0xbb, 0x2b, 0xc7, 0x88, 0x99, 0x3c, 0x89, 0xcb, 0xa7, 0x37, 0xca,
+ 0x9f, 0xef, 0x4f, 0x3c, 0x84, 0xb4, 0x11, 0x08, 0xe5, 0x8e, 0x3f, 0x9d,
+ 0xeb, 0xa4, 0xb3, 0x11, 0x0b, 0x75, 0x5b, 0x88, 0x75, 0xf9, 0x4a, 0x82,
+ 0xe4, 0x29, 0x95, 0xd0, 0xa7, 0xd1, 0xce, 0xc8, 0xfa, 0x0d, 0xaf, 0x98,
+ 0xc6, 0x72, 0x89, 0x78, 0x57, 0x7b, 0xdd, 0xe3, 0xdf, 0x40, 0xf1, 0x96,
+ 0x4a, 0x89, 0xb4, 0x09, 0x17, 0xc5, 0xa7, 0x71, 0xf4, 0x87, 0x0c, 0xc3,
+ 0x93, 0xc3, 0xbf, 0x68, 0xf2, 0xc8, 0xd9, 0xe3, 0xd1, 0x4f, 0x9e, 0xfc,
+ 0xc5, 0x0b, 0x23, 0xa6, 0x92, 0x99, 0xd5, 0xe0, 0x64, 0xe1, 0xee, 0xe4,
+ 0x10, 0xb3, 0x3f, 0x9a, 0x1c, 0xfa, 0xfe, 0xe9, 0xb9, 0x97, 0x91, 0xe4,
+ 0x37, 0x15, 0x7c, 0xeb, 0xa9, 0xf3, 0x2c, 0xf2, 0xa2, 0x59, 0x49, 0x66,
+ 0xe0, 0x88, 0xfb, 0xe0, 0x42, 0x67, 0xcd, 0x46, 0xd1, 0x1b, 0x86, 0xce,
+ 0x73, 0xcd, 0xc4, 0x8a, 0xad, 0xac, 0x9c, 0x2b, 0x80, 0xea, 0x90, 0x9f,
+ 0xa4, 0x91, 0x7e, 0x96, 0x26, 0x59, 0xeb, 0x32, 0xeb, 0x72, 0xec, 0xd6,
+ 0x39, 0x21, 0xa0, 0xe6, 0x60, 0xe2, 0x39, 0x17, 0x49, 0x76, 0x07, 0xca,
+ 0x0f, 0xf6, 0xd1, 0x5c, 0xca, 0x43, 0xf3, 0x01, 0x25, 0x24, 0x12, 0xfd,
+ 0x41, 0x46, 0xda, 0x6d, 0xdf, 0xa5, 0x0d, 0x8c, 0x4b, 0x05, 0xe7, 0xbb,
+ 0x35, 0x8d, 0xb4, 0xde, 0x6a, 0xda, 0xad, 0xf5, 0xf7, 0x34, 0x58, 0xe6,
+ 0x9a, 0xfa, 0xe4, 0x7d, 0x54, 0x3c, 0x39, 0x5b, 0x99, 0xd4, 0xa2, 0xfc,
+ 0x03, 0x52, 0x81, 0xed, 0x53, 0x2d, 0x72, 0xbd, 0xf7, 0x7f, 0x94, 0xab,
+ 0xca, 0x05, 0x79, 0xf0, 0x3f, 0x82, 0x4f, 0x5f, 0x11, 0xbc, 0x95, 0xec,
+ 0x19, 0x60, 0x52, 0x52, 0x65, 0x62, 0x6c, 0x96, 0x2a, 0xe8, 0x91, 0x0b,
+ 0xc8, 0x41, 0x64, 0x9a, 0xf9, 0xd9, 0x0e, 0x1d, 0x7f, 0xac, 0x7d, 0xb1,
+ 0xa0, 0xa1, 0xd2, 0x18, 0x37, 0x39, 0x5e, 0x98, 0x1c, 0x3d, 0x8a, 0x23,
+ 0xc7, 0x76, 0x01, 0x18, 0x8c, 0xf1, 0x0e, 0xc9, 0xf3, 0x0b, 0x67, 0x9b,
+ 0x5b, 0xda, 0x77, 0x67, 0xae, 0x43, 0x5f, 0x58, 0x01, 0xf7, 0x6e, 0x23,
+ 0xd1, 0xe3, 0x24, 0x32, 0x74, 0xce, 0xae, 0xd0, 0xbe, 0x83, 0x33, 0xfd,
+ 0x89, 0x25, 0x57, 0x77, 0x81, 0x6c, 0xf8, 0x41, 0x81, 0x78, 0xe0, 0x06,
+ 0x96, 0x69, 0xb3, 0x93, 0x9c, 0x7b, 0x99, 0xd9, 0x7a, 0xa6, 0x20, 0x16,
+ 0x3d, 0x08, 0x6e, 0x57, 0x69, 0xbd, 0x3f, 0xe6, 0x48, 0x25, 0x1d, 0x04,
+ 0x3e, 0x9d, 0xd4, 0xe2, 0x9d, 0x1d, 0x8c, 0x82, 0xd9, 0x70, 0x0f, 0xe0,
+ 0x17, 0x28, 0x54, 0xb0, 0x5d, 0x90, 0x2b, 0x6f, 0x4c, 0x06, 0x7a, 0x31,
+ 0x6b, 0x0a, 0x97, 0xc0, 0xf4, 0xae, 0xb5, 0x33, 0x2a, 0xfc, 0x0b, 0x16,
+ 0xbd, 0xf4, 0xfd, 0x82, 0x17, 0x2a, 0x61, 0x45, 0x6e, 0x53, 0x2e, 0x48,
+ 0x73, 0xa6, 0xb4, 0x0d, 0x16, 0xfc, 0x03, 0x08, 0x9e, 0xa2, 0x32, 0x50,
+ 0xc3, 0xd8, 0xc9, 0x1d, 0x08, 0x1d, 0x1f, 0xc6, 0xbb, 0x3f, 0x23, 0x71,
+ 0x47, 0x4c, 0x30, 0x88, 0x77, 0x58, 0x3a, 0xd0, 0xfc, 0xa2, 0xbc, 0x8d,
+ 0x77, 0xc7, 0x05, 0xb9, 0xdf, 0x26, 0x9d, 0x2b, 0xa9, 0x29, 0x0d, 0xa7,
+ 0x54, 0x72, 0xc2, 0x04, 0xf2, 0x70, 0x2f, 0x3b, 0x58, 0xe3, 0xe1, 0xe6,
+ 0x72, 0x00, 0xb8, 0xc1, 0x13, 0x5f, 0x55, 0xf5, 0xc5, 0xa7, 0xb0, 0x96,
+ 0x8d, 0xd3, 0xd7, 0xa4, 0xf6, 0x57, 0xc6, 0xfd, 0xe0, 0x53, 0x5d, 0x20,
+ 0x05, 0xc4, 0x59, 0x0e, 0x3e, 0xd2, 0x93, 0x74, 0xf2, 0x2b, 0xf6, 0x8a,
+ 0x39, 0xba, 0x67, 0xc7, 0x77, 0x5e, 0xe5, 0x97, 0x3a, 0x0b, 0xcd, 0xc8,
+ 0x99, 0x3f, 0x61, 0x2b, 0x7d, 0x84, 0xd2, 0x85, 0xf7, 0xd9, 0xc8, 0x31,
+ 0x7e, 0x04, 0xa1, 0x0e, 0x0e, 0x0b, 0xb3, 0xf2, 0xe7, 0x85, 0x9c, 0xe8,
+ 0xf9, 0x11, 0x3c, 0x8d, 0xfe, 0x17, 0x0f, 0x68, 0x88, 0xa7, 0x3a, 0xdb,
+ 0xea, 0x57, 0x5b, 0x04, 0x5e, 0xd9, 0x16, 0x96, 0xb4, 0x95, 0xf9, 0x83,
+ 0xdc, 0xc4, 0x92, 0x4c, 0x6d, 0xd7, 0x38, 0x0a, 0xde, 0xb2, 0x51, 0x88,
+ 0x38, 0xe0, 0x7f, 0x76, 0x02, 0x3a, 0xbf, 0x73, 0x6f, 0x66, 0xf2, 0xf1,
+ 0xe0, 0x9f, 0xff, 0x71, 0x66, 0xf2, 0x8b, 0xfb, 0xa5, 0x28, 0x77, 0x58,
+ 0xa2, 0xdb, 0xe5, 0x7e, 0x0c, 0x16, 0xf4, 0xdf, 0xff, 0xef, 0xd2, 0x96,
+ 0xff, 0x4f, 0x79, 0xcb, 0xc3, 0x3b, 0xf3, 0x96, 0xfc, 0x53, 0x4a, 0xbe,
+ 0xa9, 0x2b, 0x18, 0xb5, 0x4d, 0x77, 0x32, 0x49, 0x60, 0x32, 0x5e, 0x32,
+ 0x5c, 0xc6, 0x74, 0xe1, 0x7d, 0xe9, 0xcb, 0x34, 0x7b, 0xf9, 0x20, 0xdb,
+ 0xcc, 0x26, 0x62, 0xb4, 0x84, 0xc6, 0x89, 0x4b, 0xf0, 0xa9, 0xff, 0x02,
+ 0x75, 0x29, 0x45, 0x9f, 0x49, 0x53, 0x00, 0x00
+};
+unsigned int paper6_8K_compressed_gz_len = 8144;
diff --git a/drivers/staging/fsl_dce/tests/common/test_frame_helpers.c b/drivers/staging/fsl_dce/tests/common/test_frame_helpers.c
new file mode 100644
index 0000000..3274f0e
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/common/test_frame_helpers.c
@@ -0,0 +1,723 @@
+/* Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * This software is provided by Freescale Semiconductor "as is" and any
+ * express or implied warranties, including, but not limited to, the implied
+ * warranties of merchantability and fitness for a particular purpose are
+ * disclaimed. In no event shall Freescale Semiconductor be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential damages
+ * (including, but not limited to, procurement of substitute goods or services;
+ * on any theory of liability, whether in contract, strict liability, or tort
+ * (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 <linux/errno.h>
+#include <linux/spinlock.h>
+#include <linux/cpumask.h>
+#include <linux/rbtree.h>
+#include <linux/fsl_qman.h>
+#include <linux/stringify.h>
+#include "../../dce_sys.h"
+#include "../../flib/dce_defs.h"
+#include "test_frame_helpers.h"
+
+void print_compression_input_scf(struct scf_64b *scf)
+{
+ pr_info(" Compression Input SCF @ %p:\n", scf);
+ pr_info(" TOTAL IN ----------- %u\n", get_total_in(scf));
+ pr_info(" TOTAL OUT ---------- %u\n", get_total_out(scf));
+ pr_info(" ADLER32 ------------ %#x\n", get_adler32(scf));
+
+ pr_info(" ID1 ---------------- %#x\n", get_id1(scf));
+ pr_info(" ID2 ---------------- %#x\n", get_id2(scf));
+ pr_info(" CM ----------------- %#x\n", get_cm(scf));
+ pr_info(" FLG ---------------- %#x\n", get_flg(scf));
+ pr_info(" MTIME -------------- %u\n", get_mtime(scf));
+ pr_info(" XFL ---------------- %#x\n", get_xfl(scf));
+ pr_info(" OS ----------------- %#x\n", get_os(scf));
+ pr_info(" XLEN --------------- %u\n", get_xlen(scf));
+ pr_info(" NLEN --------------- %u\n", get_nlen(scf));
+ pr_info(" CLEN --------------- %u\n", get_clen(scf));
+ pr_info(" EXTRA PTR ---------- %#010llx\n", get_extra_ptr(scf));
+ pr_info(" PENDING OUTPUT PTR - %#010llx\n",
+ get_pending_output_ptr(scf));
+ pr_info(" HISTORY PTR -------- %#010llx\n", get_history_ptr(scf));
+ pr_info(" PMODE -------------- %u\n", get_pmode(scf));
+}
+EXPORT_SYMBOL(print_compression_input_scf);
+
+void print_compression_output_scf_debug(struct scf_64b *scf)
+{
+ pr_info(" Compression Output DEBUG SCF @ %p:\n", scf);
+ pr_info(" TOTAL IN ----------- %u\n", get_total_in(scf));
+ pr_info(" TOTAL OUT ---------- %u\n", get_total_out(scf));
+ pr_info(" ADLER32 ------------ %#x\n", get_adler32(scf));
+ pr_info(" OUTPUT PHASE ------- %u\n", get_output_phase(scf));
+ pr_info(" B64 RESIDUE LEN ---- %u\n", get_b64_residue_len(scf));
+ pr_info(" B64 RESIDUE -------- %#x\n", get_b64_residue(scf));
+ pr_info(" ID1 ---------------- %#x\n", get_id1(scf));
+ pr_info(" ID2 ---------------- %#x\n", get_id2(scf));
+ pr_info(" CM ----------------- %#x\n", get_cm(scf));
+ pr_info(" FLG ---------------- %#x\n", get_flg(scf));
+ pr_info(" MTIME -------------- %u\n", get_mtime(scf));
+ pr_info(" XFL ---------------- %#x\n", get_xfl(scf));
+ pr_info(" OS ----------------- %#x\n", get_os(scf));
+ pr_info(" XLEN --------------- %u\n", get_xlen(scf));
+ pr_info(" NLEN --------------- %u\n", get_nlen(scf));
+ pr_info(" CLEN --------------- %u\n", get_clen(scf));
+ pr_info(" RESIDUE DATA ------- %#x\n", get_residue_data(scf));
+ pr_info(" EXTRA PTR ---------- %#010llx\n", get_extra_ptr(scf));
+ pr_info(" PENDING OUTPUT LEN - %u\n", get_pending_output_len(scf));
+ pr_info(" PENDING WRKING PTR - %#x\n", get_pending_working_ptr(scf));
+ pr_info(" PENDING_OUTPUT_PTR - %#010llx\n",
+ get_pending_output_ptr(scf));
+ pr_info(" HISTORY LEN -------- %u\n", get_history_len(scf));
+ pr_info(" HISTORY_PTR -------- %#010llx\n", get_history_ptr(scf));
+ pr_info(" PMODE -------------- %u\n", get_pmode(scf));
+ pr_info(" SUSP --------------- %u\n", get_susp(scf));
+ pr_info(" TERMINATED --------- %u\n", get_terminated(scf));
+ pr_info(" RBC ---------------- %u\n", get_rbc(scf));
+ pr_info(" HEADER REMAINING --- %#x\n", get_header_remaining(scf));
+ pr_info(" CRC16 -------------- %#x\n", get_crc16(scf));
+}
+EXPORT_SYMBOL(print_compression_output_scf_debug);
+
+void print_compression_output_scf(struct scf_64b *scf)
+{
+ pr_info(" Compression Output SCF @ %p:\n", scf);
+ pr_info(" TOTAL IN ----------- %u\n", get_total_in(scf));
+ pr_info(" TOTAL OUT ---------- %u\n", get_total_out(scf));
+ pr_info(" ADLER32 ------------ %#x\n", get_adler32(scf));
+ pr_info(" BYTES PROCESSED ---- %u\n", get_bytes_processed(scf));
+}
+EXPORT_SYMBOL(print_compression_output_scf);
+
+void print_decompression_input_scf(struct scf_64b *scf)
+{
+ pr_info(" Decompression Input SCF @ %p:\n", scf);
+ pr_info(" TOTAL IN ----------- %u\n", get_total_in(scf));
+ pr_info(" TOTAL OUT ---------- %u\n", get_total_out(scf));
+ pr_info(" ADLER32 ------------ %#x\n", get_adler32(scf));
+
+ pr_info(" EXTRA_LIMIT -------- %u\n", get_extra_limit(scf));
+ pr_info(" EXTRA_PTR ---------- %#010llx\n", get_extra_ptr(scf));
+ pr_info(" PENDING_OUTPUT_PTR - %#010llx\n",
+ get_pending_output_ptr(scf));
+ pr_info(" HISTORY_PTR -------- %#010llx\n", get_history_ptr(scf));
+ pr_info(" PMODE -------------- %u\n", get_pmode(scf));
+ pr_info(" DECOMP_CTXT_PTR ---- %#010llx\n", get_decomp_ctxt_ptr(scf));
+}
+EXPORT_SYMBOL(print_decompression_input_scf);
+
+void print_decompression_output_scf(struct scf_64b *scf)
+{
+ pr_info(" Decompression Output SCF @ %p:\n", scf);
+ pr_info(" TOTAL IN ----------- %u\n", get_total_in(scf));
+ pr_info(" TOTAL OUT ---------- %u\n", get_total_out(scf));
+ pr_info(" ADLER32 ------------ %#x\n", get_adler32(scf));
+ pr_info(" XO ----------------- %u\n", get_xo(scf));
+ pr_info(" NO ----------------- %u\n", get_no(scf));
+ pr_info(" CO ----------------- %u\n", get_co(scf));
+ pr_info(" BYTES PROCESSED ---- %u\n", get_bytes_processed(scf));
+ pr_info(" ID1 ---------------- %#x\n", get_id1(scf));
+ pr_info(" ID2 ---------------- %#x\n", get_id2(scf));
+ pr_info(" CM ----------------- %#x\n", get_cm(scf));
+ pr_info(" FLG ---------------- %#x\n", get_flg(scf));
+ pr_info(" MTIME -------------- %u\n", get_mtime(scf));
+ pr_info(" XFL ---------------- %#x\n", get_xfl(scf));
+ pr_info(" OS ----------------- %#x\n", get_os(scf));
+ pr_info(" XLEN --------------- %u\n", get_xlen(scf));
+ pr_info(" NLEN --------------- %u\n", get_nlen(scf));
+ pr_info(" CLEN --------------- %u\n", get_clen(scf));
+ pr_info(" EXTRA_LIMIT -------- %u\n", get_extra_limit(scf));
+ pr_info(" EXTRA_PTR ---------- %#010llx\n", get_extra_ptr(scf));
+}
+EXPORT_SYMBOL(print_decompression_output_scf);
+
+void print_decompression_output_scf_debug(struct scf_128b *scf)
+{
+ struct scf_64b *cl1 = (struct scf_64b *)scf;
+
+ pr_info(" Decompression Output DEBUG SCF @ %p:\n", scf);
+ pr_info(" TOTAL IN ----------- %u\n", get_total_in(cl1));
+ pr_info(" TOTAL OUT ---------- %u\n", get_total_out(cl1));
+ pr_info(" ADLER32 ------------ %#x\n", get_adler32(cl1));
+ pr_info(" XO ----------------- %u\n", get_xo(cl1));
+ pr_info(" NO ----------------- %u\n", get_no(cl1));
+ pr_info(" CO ----------------- %u\n", get_co(cl1));
+ pr_info(" OUTPUT PHASE ------- %u\n", get_output_phase(cl1));
+ pr_info(" B64 RESIDUE LEN ---- %u\n", get_b64_residue_len(cl1));
+ pr_info(" B64 RESIDUE -------- %#x\n", get_b64_residue(cl1));
+ pr_info(" ID1 ---------------- %#x\n", get_id1(cl1));
+ pr_info(" ID2 ---------------- %#x\n", get_id2(cl1));
+ pr_info(" CM ----------------- %#x\n", get_cm(cl1));
+ pr_info(" FLG ---------------- %#x\n", get_flg(cl1));
+ pr_info(" MTIME -------------- %u\n", get_mtime(cl1));
+ pr_info(" XFL ---------------- %#x\n", get_xfl(cl1));
+ pr_info(" OS ----------------- %#x\n", get_os(cl1));
+ pr_info(" XLEN --------------- %u\n", get_xlen(cl1));
+ pr_info(" NLEN --------------- %u\n", get_nlen(cl1));
+ pr_info(" CLEN --------------- %u\n", get_clen(cl1));
+ pr_info(" EXTRA_LIMIT -------- %u\n", get_extra_limit(cl1));
+ pr_info(" EXTRA_PTR ---------- %#010llx\n", get_extra_ptr(cl1));
+ pr_info(" PENDING OUTPUT LEN - %u\n", get_pending_output_len(cl1));
+ pr_info(" PENDING WRKING PTR - %#x\n", get_pending_working_ptr(cl1));
+ pr_info(" PENDING_OUTPUT_PTR - %#010llx\n",
+ get_pending_output_ptr(cl1));
+ pr_info(" HISTORY LEN -------- %u\n", get_history_len(cl1));
+ pr_info(" HISTORY_PTR -------- %#010llx\n", get_history_ptr(cl1));
+ pr_info(" PMODE -------------- %u\n", get_pmode(cl1));
+ pr_info(" SUSP --------------- %u\n", get_susp(cl1));
+ pr_info(" TERMINATED --------- %u\n", get_terminated(cl1));
+ pr_info(" CRC16 -------------- %#x\n", get_crc16(cl1));
+
+ /* next 64-byte cache line */
+ pr_info(" DECOMP CTXT PTR ---- %#010llx\n",
+ get_decomp_ctxt_ptr_cl2(scf));
+ pr_info(" PREVIOUS CODE LEN -- %u\n", get_previous_code_len_cl2(scf));
+ pr_info(" BFINAL ------------- %u\n", get_bfinal_cl2(scf));
+ pr_info(" BTYPE -------------- %u\n", get_btype_cl2(scf));
+ pr_info(" FRAME PARSE STATE -- %u\n", get_frame_parse_state_cl2(scf));
+ pr_info(" NUM CODE LEN ------- %u\n", get_num_code_len_cl2(scf));
+ pr_info(" NCBB REMAINING ----- %u\n", get_ncbb_remaining_cl2(scf));
+ pr_info(" HLIT --------------- %u\n", get_hlit_cl2(scf));
+ pr_info(" HDIST -------------- %u\n", get_hdist_cl2(scf));
+ pr_info(" HCLEN -------------- %u\n", get_hclen_cl2(scf));
+ pr_info(" HUFFMAN RBC -------- %u\n", get_huffman_rbc_cl2(scf));
+ pr_info(" HUFFMAN RESIDUE ---- %#012llx\n",
+ get_huffman_residue_cl2(scf));
+}
+EXPORT_SYMBOL(print_decompression_output_scf_debug);
+
+void print_dce_fd(struct qm_fd fd)
+{
+ pr_info(" Frame Descriptor:\n");
+ pr_info(" DD --------------- %#x\n", fd.dd);
+ pr_info(" LIODN ------------ %#x\n", fd.liodn_offset);
+ pr_info(" BPID ------------- %#x\n", fd.bpid);
+ pr_info(" ELIODN ----------- %#x\n", fd.eliodn_offset);
+ pr_info(" ADDRESS ---------- %#010llx\n", (uint64_t)fd.addr);
+ if (fd.format == 0 || fd.format == 4)
+ pr_info(" - ADDRESS + OFFSET %#010llx\n",
+ (uint64_t)fd.addr + fd.offset);
+ if (fd.format == 0)
+ pr_info(" FORMAT ----------- Short_SingleFrame\n");
+ else if (fd.format == 2)
+ pr_info(" FORMAT ----------- Long_SingleFrame\n");
+ else if (fd.format == 4)
+ pr_info(" FORMAT ----------- Short_MultiFrame\n");
+ else if (fd.format == 6)
+ pr_info(" FORMAT ----------- Long_MultiFrame\n");
+ else if (fd.format == 1)
+ pr_info(" FORMAT ----------- CompoundFrame\n");
+ else
+ pr_info(" FORMAT ----------- UNKNOWN Frame\n");
+ if (fd.format == 0 || fd.format == 4) {
+ pr_info(" OFFSET ----------- %#x\n", fd.offset);
+ pr_info(" SHORT LENGTH ----- %#x\n", fd.length20);
+ }
+ if (fd.format == 2 || fd.format == 6)
+ pr_info(" LONG LENGTH ----- %#x\n", fd.length29);
+ if (fd.format == 1)
+ pr_info(" CONG WEIGHT ----- %#x\n", fd.cong_weight);
+ pr_info(" STATUS/CMD ------ %#0x\n", fd.cmd);
+}
+EXPORT_SYMBOL(print_dce_fd);
+
+void print_dce_sg(struct qm_sg_entry sg)
+{
+ pr_info(" Scatter/Gather Table Entry:\n");
+ pr_info(" RESERVED --------- %#06x\n", sg.__notaddress);
+ pr_info(" ADDRESS ---------- %#010llx\n", (uint64_t)sg.addr);
+ pr_info(" E ---------------- %#x\n", sg.extension);
+ pr_info(" F ---------------- %#x\n", sg.final);
+ pr_info(" LENGTH ----------- %#x\n", sg.length);
+ pr_info(" RESERVED2 -------- %#02x\n", sg.__reserved2);
+ pr_info(" BPID ------------- %#x\n", sg.bpid);
+ pr_info(" RESERVED3 -------- %#x\n", sg.__reserved3);
+ pr_info(" OFFSET ----------- %#x\n", sg.offset);
+}
+EXPORT_SYMBOL(print_dce_sg);
+
+void print_dce_data_list(struct dce_data_list_t *data_list)
+{
+ int i;
+
+ pr_info("dce_data_list = %p\n", data_list);
+
+ pr_info(" sg = %p, nents = %u, data_item = %p\n",
+ data_list->sg, data_list->nents, data_list->data_item);
+
+ if (data_list->sg) {
+ pr_info("Multi-Buffer\n");
+ for (i = 0; i < data_list->nents; i++) {
+ pr_info(" cpumem = %p, size = %zu\n",
+ data_list->data_item[i].cpumem,
+ data_list->data_item[i].size);
+ print_hex_dump(KERN_ERR, " data@"AT": ",
+ DUMP_PREFIX_ADDRESS, 16, 4,
+ data_list->data_item[i].cpumem, 16, false);
+ }
+ for (i = 0; i < data_list->nents; i++)
+ print_dce_sg(data_list->sg[i]);
+ } else {
+ pr_info("Single Buffer\n");
+ pr_info(" cpumem = %p, size = %zu\n",
+ data_list->data_item->cpumem,
+ data_list->data_item->size);
+ print_hex_dump(KERN_ERR, " data@"AT": ",
+ DUMP_PREFIX_ADDRESS, 16, 4,
+ data_list->data_item->cpumem, 16, false);
+
+ }
+}
+EXPORT_SYMBOL(print_dce_data_list);
+
+bool is_multi_buffer(struct dce_data_list_t *data)
+{
+ return (data->sg != NULL);
+}
+EXPORT_SYMBOL(is_multi_buffer);
+
+
+int alloc_dce_data(size_t length, size_t block_size,
+ struct dce_data_list_t *dce_data)
+{
+ size_t num_entries;
+ struct dce_data_item_t *data_item = NULL;
+ size_t last_buf_size;
+ int i;
+
+ if ((block_size == 0) || !dce_data)
+ return -EINVAL;
+
+ memset(dce_data, 0, sizeof(*dce_data));
+
+ if (block_size >= length) {
+ num_entries = 1;
+ last_buf_size = length;
+ } else {
+ num_entries = length / block_size;
+ last_buf_size = length - (num_entries * block_size);
+ if (last_buf_size == 0)
+ last_buf_size = block_size;
+ else
+ num_entries++;
+ }
+
+ /* determine if multi-buffer or not */
+ if (num_entries == 1) {
+ dce_data->sg = NULL;
+ dce_data->nents = 0;
+ dce_data->data_item = kmalloc(sizeof(struct dce_data_item_t),
+ GFP_KERNEL);
+ if (!dce_data->data_item)
+ return -ENOMEM;
+ dce_data->data_item->cpumem = kmalloc(last_buf_size,
+ GFP_KERNEL);
+ if (!dce_data->data_item->cpumem) {
+ kfree(dce_data->data_item);
+ return -ENOMEM;
+ }
+ memset(dce_data->data_item->cpumem, 0xff, last_buf_size);
+ dce_data->data_item->size = last_buf_size;
+ return 0;
+ }
+
+ /* create multi-buffer */
+ dce_data->sg = kzalloc(sizeof(struct qm_sg_entry) * num_entries,
+ GFP_KERNEL);
+ if (!dce_data->sg)
+ return -ENOMEM;
+ dce_data->nents = num_entries;
+ dce_data->data_item = kzalloc(
+ sizeof(struct dce_data_item_t) * num_entries, GFP_KERNEL);
+ if (!dce_data->data_item) {
+ kfree(dce_data->sg);
+ return -ENOMEM;
+ }
+
+ data_item = dce_data->data_item;
+
+ for (i = 0; i < num_entries; i++) {
+ size_t size_to_alloc = block_size;
+
+ /* if last entry, only allocate remaining */
+ if (i == num_entries-1) {
+ size_to_alloc = last_buf_size;
+ dce_data->sg[i].final = 1;
+ }
+
+ data_item[i].cpumem = kzalloc(size_to_alloc, GFP_KERNEL);
+ if (!data_item[i].cpumem)
+ goto fail_allocs;
+ data_item[i].size = size_to_alloc;
+ dce_data->sg[i].length = size_to_alloc;
+ }
+ return 0;
+fail_allocs:
+ /* release all allocated memory */
+ for (i = 0; i < dce_data->nents; i++)
+ kfree(dce_data->data_item[i].cpumem);
+ kfree(dce_data->data_item);
+ kfree(dce_data->sg);
+ return -EINVAL;
+}
+EXPORT_SYMBOL(alloc_dce_data);
+
+int free_dce_data(struct dce_data_list_t *dce_data)
+{
+ int i;
+
+ if (!dce_data)
+ return -EINVAL;
+
+ /* release all allocated memory */
+ for (i = 0; i < dce_data->nents; i++)
+ kfree(dce_data->data_item[i].cpumem);
+ kfree(dce_data->data_item);
+ kfree(dce_data->sg);
+ memset(dce_data, 0, sizeof(*dce_data));
+ return 0;
+}
+EXPORT_SYMBOL(free_dce_data);
+
+size_t total_size_dce_data(struct dce_data_list_t *dce_data)
+{
+ size_t total_size = 0;
+ int i;
+
+ if (!dce_data->sg) {
+ if (!dce_data->data_item)
+ return 0;
+ return dce_data->data_item->size;
+ }
+
+ for (i = 0; i < dce_data->nents; i++)
+ total_size += dce_data->data_item[i].size;
+
+ return total_size;
+}
+EXPORT_SYMBOL(total_size_dce_data);
+
+int copy_input_to_dce_data(char *input, size_t ilen,
+ struct dce_data_list_t *data_list)
+{
+ char *data_p = input;
+ size_t len = ilen;
+ int i = 0;
+
+ if (!data_p || !data_list || !data_list->data_item)
+ return -EINVAL;
+
+ if (total_size_dce_data(data_list) < ilen)
+ return -EINVAL;
+
+ while (len) {
+ size_t to_copy = min(data_list->data_item[i].size, len);
+ memcpy(data_list->data_item[i].cpumem, data_p, to_copy);
+ if (to_copy != data_list->data_item[i].size)
+ pr_err("Size not the same\n");
+ data_p += to_copy;
+ len -= to_copy;
+ i++;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(copy_input_to_dce_data);
+
+int copy_dce_data_to_buffer(struct dce_data_list_t *data_list, size_t cpylen,
+ char *buffer, size_t buf_size)
+{
+ int i = 0;
+
+ if (!buffer || !data_list || !data_list->data_item)
+ return -EINVAL;
+
+ if (cpylen > total_size_dce_data(data_list))
+ return -EINVAL;
+
+ if (cpylen > buf_size)
+ return -EINVAL;
+
+ if (!is_multi_buffer(data_list)) {
+ memcpy(buffer, data_list->data_item->cpumem, cpylen);
+ return 0;
+ }
+
+ while (cpylen) {
+ size_t to_copy = min(data_list->data_item[i].size, cpylen);
+ memcpy(buffer, data_list->data_item[i].cpumem, to_copy);
+ cpylen -= to_copy;
+ buffer += to_copy;
+ i++;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(copy_dce_data_to_buffer);
+
+int dma_map_dce_data(struct dce_data_list_t *data_list,
+ enum dma_data_direction dir)
+{
+ int i;
+ struct device *dce_device = fsl_dce_get_device();
+ dma_addr_t addr;
+
+ if (!data_list || !dce_device)
+ return -EINVAL;
+
+ if (data_list->sg == NULL)
+ return 0;
+
+ for (i = 0; i < data_list->nents; i++) {
+ addr = dma_map_single(dce_device,
+ data_list->data_item[i].cpumem,
+ data_list->data_item[i].size,
+ dir);
+ if (dma_mapping_error(dce_device, addr)) {
+ pr_err("unable to map i/o memory\n");
+ goto fail_map;
+ }
+ qm_sg_entry_set64(&data_list->sg[i], addr);
+ }
+ return 0;
+
+fail_map:
+ for (i = 0; i < data_list->nents; i++) {
+ dma_addr_t addr = qm_sg_addr(&data_list->sg[i]);
+ if (addr) {
+ dma_unmap_single(dce_device, addr,
+ data_list->data_item[i].size, dir);
+ }
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL(dma_map_dce_data);
+
+int dma_unmap_dce_data(struct dce_data_list_t *data_list,
+ enum dma_data_direction dir)
+{
+ int i;
+ struct device *dce_device = fsl_dce_get_device();
+
+ if (!data_list || !dce_device)
+ return -EINVAL;
+
+ for (i = 0; i < data_list->nents; i++) {
+ dma_addr_t addr = qm_sg_addr(&data_list->sg[i]);
+ if (addr) {
+ dma_unmap_single(dce_device, addr,
+ data_list->data_item[i].size, dir);
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(dma_unmap_dce_data);
+
+int attach_data_list_to_sg(struct qm_sg_entry *sg,
+ struct dce_data_list_t *data_list,
+ enum dma_data_direction dir)
+{
+ dma_addr_t addr;
+ struct device *dce_device = fsl_dce_get_device();
+
+ if (!data_list || !dce_device)
+ return -EINVAL;
+
+ if (is_multi_buffer(data_list)) {
+ sg->extension = 1;
+ addr = dma_map_single(dce_device,
+ data_list->sg,
+ sizeof(struct qm_sg_entry) * data_list->nents,
+ dir);
+ if (dma_mapping_error(dce_device, addr)) {
+ pr_err("unable to map i/o memory\n");
+ return -ENOMEM;
+ }
+ qm_sg_entry_set64(sg, addr);
+ sg->length = total_size_dce_data(data_list);
+ } else {
+ sg->extension = 0;
+ addr = dma_map_single(dce_device,
+ data_list->data_item->cpumem,
+ data_list->data_item->size,
+ dir);
+ if (dma_mapping_error(dce_device, addr)) {
+ pr_err("unable to map i/o memory\n");
+ return -ENOMEM;
+ }
+ qm_sg_entry_set64(sg, addr);
+ sg->length = total_size_dce_data(data_list);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(attach_data_list_to_sg);
+
+int detach_data_list_from_sg(struct qm_sg_entry *sg,
+ struct dce_data_list_t *data_list,
+ enum dma_data_direction dir)
+{
+ dma_addr_t addr;
+ struct device *dce_device = fsl_dce_get_device();
+
+ if (!data_list || !dce_device)
+ return -EINVAL;
+
+ if (is_multi_buffer(data_list)) {
+ addr = qm_sg_addr(sg);
+ dma_unmap_single(dce_device, addr,
+ sizeof(struct qm_sg_entry) * data_list->nents, dir);
+ } else {
+ addr = qm_sg_addr(sg);
+ dma_unmap_single(dce_device, addr,
+ data_list->data_item->size, dir);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(detach_data_list_from_sg);
+
+int attach_scf64_to_sg(struct qm_sg_entry *sg,
+ struct scf_64b *scf,
+ enum dma_data_direction dir)
+{
+ dma_addr_t addr;
+ struct device *dce_device = fsl_dce_get_device();
+
+ if (!scf || !dce_device)
+ return -EINVAL;
+
+ sg->extension = 0;
+ addr = dma_map_single(dce_device, scf, sizeof(*scf), dir);
+ if (dma_mapping_error(dce_device, addr)) {
+ pr_err("unable to map i/o memory\n");
+ return -ENOMEM;
+ }
+ qm_sg_entry_set64(sg, addr);
+ sg->length = sizeof(*scf);
+ return 0;
+}
+EXPORT_SYMBOL(attach_scf64_to_sg);
+
+int detach_scf64_from_sg(struct qm_sg_entry *sg,
+ struct scf_64b *scf,
+ enum dma_data_direction dir)
+{
+ dma_addr_t addr;
+ struct device *dce_device = fsl_dce_get_device();
+
+ if (!scf || !dce_device)
+ return -EINVAL;
+
+ addr = qm_sg_addr(sg);
+ dma_unmap_single(dce_device, addr, sizeof(*scf), dir);
+ return 0;
+}
+EXPORT_SYMBOL(detach_scf64_from_sg);
+
+int attach_scf128_to_sg(struct qm_sg_entry *sg,
+ struct scf_128b *scf,
+ enum dma_data_direction dir)
+{
+ dma_addr_t addr;
+ struct device *dce_device = fsl_dce_get_device();
+
+ if (!scf || !dce_device)
+ return -EINVAL;
+
+ sg->extension = 0;
+ addr = dma_map_single(dce_device, scf, sizeof(*scf), dir);
+ if (dma_mapping_error(dce_device, addr)) {
+ pr_err("unable to map i/o memory\n");
+ return -ENOMEM;
+ }
+ qm_sg_entry_set64(sg, addr);
+ sg->length = sizeof(*scf);
+ return 0;
+}
+EXPORT_SYMBOL(attach_scf128_to_sg);
+
+int detach_scf128_from_sg(struct qm_sg_entry *sg,
+ struct scf_128b *scf,
+ enum dma_data_direction dir)
+{
+ dma_addr_t addr;
+ struct device *dce_device = fsl_dce_get_device();
+
+ if (!scf || !dce_device)
+ return -EINVAL;
+
+ addr = qm_sg_addr(sg);
+ dma_unmap_single(dce_device, addr, sizeof(*scf), dir);
+ return 0;
+}
+EXPORT_SYMBOL(detach_scf128_from_sg);
+
+int alloc_set_gzip_filename(struct dce_process_cf_gzip_req *req, char *name)
+{
+ if (name == NULL) {
+ req->filename = NULL;
+ return 0;
+ }
+
+ req->filename = kmalloc(strlen(name) + 1, GFP_KERNEL);
+ if (req->filename == NULL)
+ return -ENOMEM;
+
+ memcpy(req->filename, name, strlen(name) + 1);
+ return 0;
+}
+EXPORT_SYMBOL(alloc_set_gzip_filename);
+
+int free_clear_gzip_filename(struct dce_process_cf_gzip_req *req)
+{
+ kfree(req->filename);
+ req->filename = NULL;
+ return 0;
+}
+EXPORT_SYMBOL(free_clear_gzip_filename);
+
+int alloc_set_gzip_comment(struct dce_process_cf_gzip_req *req, char *name)
+{
+ if (name == NULL) {
+ req->comment = NULL;
+ return 0;
+ }
+
+ req->comment = kmalloc(strlen(name) + 1, GFP_KERNEL);
+ if (req->comment == NULL)
+ return -ENOMEM;
+
+ memcpy(req->comment, name, strlen(name) + 1);
+ return 0;
+}
+EXPORT_SYMBOL(alloc_set_gzip_comment);
+
+int free_clear_gzip_comment(struct dce_process_cf_gzip_req *req)
+{
+ kfree(req->comment);
+ req->comment = NULL;
+ return 0;
+}
+EXPORT_SYMBOL(free_clear_gzip_comment);
+
+
+
diff --git a/drivers/staging/fsl_dce/tests/common/test_frame_helpers.h b/drivers/staging/fsl_dce/tests/common/test_frame_helpers.h
new file mode 100644
index 0000000..e4c8782
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/common/test_frame_helpers.h
@@ -0,0 +1,172 @@
+/* Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * This software is provided by Freescale Semiconductor "as is" and any
+ * express or implied warranties, including, but not limited to, the implied
+ * warranties of merchantability and fitness for a particular purpose are
+ * disclaimed. In no event shall Freescale Semiconductor be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential damages
+ * (including, but not limited to, procurement of substitute goods or services;
+ * loss of use, data, or profits; or business interruption) however caused and
+ * on any theory of liability, whether in contract, strict liability, or tort
+ * (including negligence or otherwise) arising in any way out of the use of
+ * this software, even if advised of the possibility of such damage.
+ */
+
+#ifndef TEST_FRAME_HELPERS_H
+#define TEST_FRAME_HELPERS_H
+
+#include <linux/kernel.h>
+#include <linux/fsl_qman.h>
+#include <linux/dma-direction.h>
+#define AT __stringify(__LINE__)
+
+/**
+ * struct dce_data_t - hold cpu virtual address input or output data
+ * @is_sg: Inidcated if @data references a qm_sg_entry array or not.
+ * @data: cpu virtual address of either data or an array of
+ * qm_sq_entry
+ * @length Size of memory pointed by @data.
+ */
+struct dce_data_item_t {
+ void *cpumem;
+ size_t size;
+};
+
+/**
+ * struct dce_data_t - hold cpu virtual address input or output data
+ * @sg: Inidcated if sg is required
+ * @nents: number of entries @sg points to as well as @data_item
+ * @data_item: points to an array of dce_data_item_t. If @sg is NULL then
+ * it will point up to one element. Otherwise it will point to
+ * @nents elements.
+ */
+struct dce_data_list_t {
+ struct qm_sg_entry *sg;
+ unsigned int nents;
+ struct dce_data_item_t *data_item;
+};
+
+void print_compression_input_scf(struct scf_64b *scf);
+void print_compression_output_scf(struct scf_64b *scf);
+void print_compression_output_scf_debug(struct scf_64b *scf);
+void print_decompression_input_scf(struct scf_64b *scf);
+void print_decompression_output_scf(struct scf_64b *scf);
+void print_decompression_output_scf_debug(struct scf_128b *scf);
+void print_dce_data_list(struct dce_data_list_t *data_list);
+void print_dce_fd(struct qm_fd fd);
+void print_dce_sg(struct qm_sg_entry sg);
+
+
+bool is_multi_buffer(struct dce_data_list_t *data);
+
+int alloc_dce_data(size_t length, size_t block_size,
+ struct dce_data_list_t *dce_data);
+
+int free_dce_data(struct dce_data_list_t *dce_data);
+
+int copy_input_to_dce_data(char *input, size_t ilen,
+ struct dce_data_list_t *data_list);
+
+int copy_dce_data_to_buffer(struct dce_data_list_t *data_list, size_t cpylen,
+ char *buffer, size_t buf_size);
+
+int dma_map_dce_data(struct dce_data_list_t *data_list,
+ enum dma_data_direction dir);
+
+int dma_unmap_dce_data(struct dce_data_list_t *data_list,
+ enum dma_data_direction dir);
+
+int attach_data_list_to_sg(struct qm_sg_entry *sg,
+ struct dce_data_list_t *data_list,
+ enum dma_data_direction dir);
+
+int detach_data_list_from_sg(struct qm_sg_entry *sg,
+ struct dce_data_list_t *data_list,
+ enum dma_data_direction dir);
+
+int attach_scf64_to_sg(struct qm_sg_entry *sg,
+ struct scf_64b *scf,
+ enum dma_data_direction);
+
+int detach_scf64_from_sg(struct qm_sg_entry *sg,
+ struct scf_64b *scf,
+ enum dma_data_direction dir);
+
+int attach_scf128_to_sg(struct qm_sg_entry *sg,
+ struct scf_128b *scf,
+ enum dma_data_direction);
+
+int detach_scf128_from_sg(struct qm_sg_entry *sg,
+ struct scf_128b *scf,
+ enum dma_data_direction dir);
+
+struct dce_process_cf_req {
+ struct qm_sg_entry dce_cf[3];
+ struct dce_data_list_t output_data;
+ struct dce_data_list_t input_data;
+ struct qm_fd input_fd;
+ struct qm_fd output_fd;
+ struct completion cb_done;
+ char *v_output;
+ size_t v_output_size;
+};
+
+struct dce_process_cf_zlib_req {
+ struct qm_sg_entry dce_cf[3];
+ struct scf_64b scf;
+ struct dce_data_list_t output_data;
+ struct dce_data_list_t input_data;
+ struct qm_fd input_fd;
+ struct qm_fd output_fd;
+ struct completion cb_done;
+ char *v_output;
+ size_t v_output_size;
+};
+
+struct dce_process_cf_gzip_req {
+ struct qm_sg_entry dce_cf[3];
+ struct scf_64b scf;
+ struct scf_128b scf_debug;
+ struct qm_fd input_fd;
+ struct qm_fd output_fd;
+ struct completion cb_done;
+ char *v_output;
+ size_t v_output_size;
+
+ void *extra_data;
+ size_t extra_data_size;
+ char *filename;
+ char *comment;
+ struct dce_data_item_t extra_data_ptr;
+ struct dce_data_list_t output_data;
+ struct dce_data_list_t input_data;
+};
+
+struct dce_nop_req {
+ struct qm_fd output_fd;
+ struct completion cb_done;
+};
+
+int alloc_set_gzip_filename(struct dce_process_cf_gzip_req *req, char *name);
+int free_clear_gzip_filename(struct dce_process_cf_gzip_req *req);
+int alloc_set_gzip_comment(struct dce_process_cf_gzip_req *req, char *name);
+int free_clear_gzip_comment(struct dce_process_cf_gzip_req *req);
+
+#endif /* TEST_FRAME_HELPERS_H */
diff --git a/drivers/staging/fsl_dce/tests/performance_simple/Makefile b/drivers/staging/fsl_dce/tests/performance_simple/Makefile
new file mode 100644
index 0000000..2931ba6
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/performance_simple/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_FSL_DCE_TESTS) += dce_simple_perf_tester.o
+dce_simple_perf_tester-objs := dce_perf_simple.o
+
diff --git a/drivers/staging/fsl_dce/tests/performance_simple/README b/drivers/staging/fsl_dce/tests/performance_simple/README
new file mode 100644
index 0000000..d9bcdbf
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/performance_simple/README
@@ -0,0 +1,89 @@
+This module demonstrates the DCE throughput performance using a single file.
+
+When the module is unloaded here is a sample output:
+
+Compression thoughput: 9453 Mbps (12600 Mbps for 400 Mhz DCE)
+
+The indivial throughput is displayed. In this case the compression was
+9.4 Gbps (giga bit per second). This hardware was not configured for maximum
+clock frequencies. In this case the test case prints out what the approximate
+ideal thoughput would have been if the DCE engine was clocked at its max
+frequency. In this case it would have been about 12.6 Gbps.
+
+The module can read the input for (de)compression from a specified file or can
+use a choice of statically linked in data.
+The resulting (de)compressed file can be written to a specified file.
+
+Either compression or decompression can be done. Not both at the same time.
+This is a limitation of the test and not the hw/driver.
+
+Module parameters:
+
+test_mode : 0 is gzip compression, 1 is gzip decompression
+
+use_local_file: Permitted values are 0, 2, 4, 8, 12. If non-zero use the
+ statically linked in data for (de)compression. 2 means 2k file.
+ 4 means 4k file, etc.
+
+in_file : Specifies the file to read in for (de)compression. If
+ use_local_file is non-zero this value is ignored.
+
+out_file: specifies the file to write out the result of the (de)compression
+ operation. Only one of the (de)compression result is writing at the
+ end of the test. This value is optional.
+
+b_sg_block_size_code : When using Bman as output this specifies the size of
+ s/g blocks. This value is directly linked to the value used be the DCE
+ hw.
+ 0 : 64 bytes (4 table entries)
+ 1 : 128 bytes (8 table entries)
+ 2 : 256 bytes
+ 3 : 512 bytes
+ 4 : 1024 bytes
+ 5 : 2048 bytes
+ 6 : 4096 bytes
+ 7 : 8192 bytes (512 table entries)
+
+b_sg_block_count : Specified the number of sg blocks to release into a BMan
+ buffer pool.
+
+bman_data_size : Specifies the total size of all the bman buffers released
+ to the bman data buffer pool. The default value is 22,000,000 bytes.
+ For instance, if the expected size of the output file is larger than
+ 22Mb, then this value should be increated.
+
+comp_effort : value of compression effort to use.
+ 0 :
+
+b_dexp : Specifies the exponent part of BMan data buffer output size.
+ values: 7..22
+b_dmant : Specifies the mantissa part of BMan data buffer output size.
+ values: 1..16
+
+Therefore the size of the BMan data buffer will be size = b_dmant * 2^b_dexp
+The default is 1 * 2^12 = 4096 bytes
+
+block_size : This is the size of each data block used for INPUT s/g. The module
+ will read in a file and then build s/g input. This value defines the
+ size of each data block referenced by the sg table entries.
+
+Example:
+root@t4240qds:# insmod ./dce_perf_simple_test.ko test_mode=0 in_file="InputData1" out_file="InputData1.1_1.gz" comp_effort=1
+Loading dce_perf_simple_test module
+BMan data block size is 4096
+Size of file: InputData1 is 20000000
+Released 5372 data blocks of size 4096
+DCE thread on cpu 1
+Output length is 13249938
+
+root@t4240qds:# rmmod dce_perf_test.ko
+DCE Freq = 299999997 hz
+CPU Freq: 1666666650
+Cycles to complete = 28197315
+Time (usec) to complete = 16925
+Scaling factor (by 1000) = 1333
+Total Input Bytes to Compress: 20000000
+Input file size compression: 20000000 bytes
+Compression thoughput: 9453 Mbps (12600 Mbps for 400 Mhz DCE)
+Decompression thoughput: None
+
diff --git a/drivers/staging/fsl_dce/tests/performance_simple/dce_perf_simple.c b/drivers/staging/fsl_dce/tests/performance_simple/dce_perf_simple.c
new file mode 100644
index 0000000..d14a6d7
--- /dev/null
+++ b/drivers/staging/fsl_dce/tests/performance_simple/dce_perf_simple.c
@@ -0,0 +1,985 @@
+/* Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * This software is provided by Freescale Semiconductor "as is" and any
+ * express or implied warranties, including, but not limited to, the implied
+ * warranties of merchantability and fitness for a particular purpose are
+ * disclaimed. In no event shall Freescale Semiconductor be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential damages
+ * (including, but not limited to, procurement of substitute goods or services;
+ * loss of use, data, or profits; or business interruption) however caused and
+ * on any theory of liability, whether in contract, strict liability, or tort
+ * (including negligence or otherwise) arising in any way out of the use of
+ * this software, even if advised of the possibility of such damage.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/time.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/kthread.h>
+#include <linux/file.h>
+#include <linux/vmalloc.h>
+#include <linux/of.h>
+#include <linux/cpufreq.h>
+#include <sysdev/fsl_soc.h>
+#include "../../fsl_dce.h"
+#include "../../fsl_dce_chunk.h"
+#include "../../dce_sys.h"
+#include "../../flib/dce_helper.h"
+#include "../../flib/dce_gzip_helper.h"
+
+#include "../common/test_frame_helpers.h"
+
+#include "../common/paper5_2048.h"
+#include "../common/paper5_4096.h"
+#include "../common/paper5_8192.h"
+#include "../common/paper5_11954.h"
+
+#include "../common/paper6_2K_compressed.gz.h"
+#include "../common/paper6_4K_compressed.gz.h"
+#include "../common/paper6_8K_compressed.gz.h"
+#include "../common/paper6_12K_compressed.gz.h"
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DCE loopback example");
+
+#define USE_BMAN_OUTPUT
+#undef VERBOSE
+
+static int test_mode;
+module_param(test_mode, int, S_IRUGO);
+MODULE_PARM_DESC(test_mode, "test_mode: 0 is compression, 1 is decompression"
+ " (default=0)");
+
+static int b_sg_block_size_code = DCE_TSIZE_4096B;
+module_param(b_sg_block_size_code, int, S_IRUGO);
+MODULE_PARM_DESC(b_sg_block_size_code, "Size of bman buffers used to create"
+ " s/g tables (default=4096)");
+
+/* This is used for actual kmalloc */
+static int b_sg_block_size = 4096;
+
+static int b_sg_block_count = 50;
+module_param(b_sg_block_count, int, S_IRUGO);
+MODULE_PARM_DESC(b_sg_block_count, "Number of s/g bman buffers to release"
+ " (default=50)");
+
+static int b_dexp = 12;
+module_param(b_dexp, int, S_IRUGO);
+MODULE_PARM_DESC(b_dexp, "Bman dexp value, default=");
+
+static int b_dmant = 1;
+module_param(b_dmant, int, S_IRUGO);
+MODULE_PARM_DESC(b_dmant, "Bman dmant value, default=");
+
+static uint32_t bman_data_buff_size;
+
+static int block_size = 4096;
+module_param(block_size, int, S_IRUGO);
+MODULE_PARM_DESC(block_size, "Size of individual input data blocks in s/g"
+ " (default=4096)");
+
+static int use_local_file;
+module_param(use_local_file, int, S_IRUGO);
+MODULE_PARM_DESC(use_local_file, "Use the included local header file for"
+ " (de)compression. The value specifies the input size."
+ " Supported value are 0, 2, 4, 8, 12 (default=0)");
+
+static int comp_effort = DCE_PROCESS_CE_STATIC_HUFF_STRMATCH;
+module_param(comp_effort, int, S_IRUGO);
+MODULE_PARM_DESC(comp_effort, "Compression Effort, default=1");
+
+static char *in_file;
+module_param(in_file, charp, 0000);
+MODULE_PARM_DESC(in_file, "Input file to (de)compress");
+
+static char *out_file;
+module_param(out_file, charp, 0000);
+MODULE_PARM_DESC(out_file, "Output file result of (de)compression");
+
+static int comp_ratio = 4;
+module_param(comp_ratio, int, S_IRUGO);
+MODULE_PARM_DESC(comp_ratio, "The compresstion ratio to be used for allocat"
+ " output data buffer");
+
+static int output_size;
+module_param(output_size, int, S_IRUGO);
+MODULE_PARM_DESC(output_size, "The extra output size to allocate");
+
+static int bman_data_size = 22000000;
+module_param(bman_data_size, int, S_IRUGO);
+MODULE_PARM_DESC(bman_data_size, "The size of the data buffer pool");
+
+static int b_data_block_count;
+
+extern unsigned long ppc_proc_freq;
+
+/* Break up data used for each channel to avoid contention for the
+ * cache lines */
+struct test_data_s {
+ struct fsl_dce_chunk ctx;
+
+ int mode; /* compression, decompression */
+ char *out_data;
+ int out_data_len;
+ char *input_data;
+ int input_data_len;
+} __aligned(32);
+
+struct test_data_s *test_data;
+
+static uint64_t start_time, end_time;
+
+/* Loopback support */
+static int do_operation(void);
+
+/* Alternate Time Base */
+#define SPR_ATBL 526
+#define SPR_ATBU 527
+static inline uint64_t mfatb(void)
+{
+ return mfspr(SPR_ATBL);
+}
+
+static struct bman_pool *pool_data;
+static struct bman_pool *pool_sg;
+
+static int setup_buffer_pools(void)
+{
+ struct bman_pool_params pparams = {
+ .flags = BMAN_POOL_FLAG_DYNAMIC_BPID,
+ .thresholds = {
+ 0,
+ 0,
+ 0,
+ 0
+ }
+ };
+
+ pool_data = bman_new_pool(&pparams);
+ if (!pool_data) {
+ pr_err("can't get data buffer pool\n");
+ return -EINVAL;
+ }
+
+ pool_sg = bman_new_pool(&pparams);
+ if (!pool_sg) {
+ pr_err("can't get sg buffer pool\n");
+ return -EINVAL;
+ }
+#ifdef VERBOSE
+ pr_info("Allocated bpool data %d and bpool sg %d\n",
+ bman_get_params(pool_data)->bpid,
+ bman_get_params(pool_sg)->bpid);
+#endif
+ return 0;
+}
+
+static void release_data_buffer(dma_addr_t addr)
+{
+ struct bm_buffer bufs_in;
+ bm_buffer_set64(&bufs_in, addr);
+ if (bman_release(pool_data, &bufs_in, 1, BMAN_RELEASE_FLAG_WAIT))
+ panic("bman_release() failed\n");
+}
+
+static void release_sg_buffer(dma_addr_t addr)
+{
+ struct bm_buffer bufs_in;
+ bm_buffer_set64(&bufs_in, addr);
+ if (bman_release(pool_sg, &bufs_in, 1, BMAN_RELEASE_FLAG_WAIT))
+ panic("bman_release() failed\n");
+}
+
+static int populate_bman_data_pool(void)
+{
+ dma_addr_t addr;
+ int i, ret;
+ void *cpumem;
+
+ for (i = 0; i < b_data_block_count; i++) {
+ cpumem = kmalloc(bman_data_buff_size, GFP_KERNEL);
+ if (!cpumem) {
+ pr_err("Can't allocate data buffers\n");
+ return -ENOMEM;
+ }
+ addr = fsl_dce_map(cpumem);
+ ret = fsl_dce_map_error(addr);
+ if (ret) {
+ pr_err("unable to map i/o memory\n");
+ kfree(cpumem);
+ return ret;
+ }
+ release_data_buffer(addr);
+ }
+ pr_info("Released %u data blocks of size %u\n",
+ b_data_block_count, bman_data_buff_size);
+ return 0;
+}
+
+static int empty_bman_data_pool(void)
+{
+ struct bm_buffer bufs_in;
+ int ret;
+ int count = 0;
+
+ do {
+ ret = bman_acquire(pool_data, &bufs_in, 1, 0);
+ if (ret == 1) {
+ dma_addr_t addr = bm_buf_addr(&bufs_in);
+ fsl_dce_unmap(addr);
+ kfree(phys_to_virt(addr));
+ count++;
+ }
+ } while (ret > 0);
+#ifdef VERBOSE
+ pr_info("Freed %d data buffers\n", count);
+#endif
+ return 0;
+}
+
+static int populate_bman_sg_pool(void)
+{
+ dma_addr_t addr;
+ int i;
+ void *cpumem;
+ int ret;
+
+ for (i = 0; i < b_sg_block_count ; i++) {
+ cpumem = kmalloc(b_sg_block_size, GFP_KERNEL);
+ if (!cpumem) {
+ pr_err("Can't allocate s/g buffers\n");
+ return -ENOMEM;
+ }
+ addr = fsl_dce_map(cpumem);
+ ret = fsl_dce_map_error(addr);
+ if (ret) {
+ pr_err("unable to map i/o memory\n");
+ kfree(cpumem);
+ return ret;
+ }
+ release_sg_buffer(addr);
+ }
+ return 0;
+}
+
+static int empty_bman_sg_pool(void)
+{
+ struct bm_buffer bufs_in;
+ int ret;
+ int count = 0;
+
+ do {
+ ret = bman_acquire(pool_sg, &bufs_in, 1, 0);
+ if (ret == 1) {
+ dma_addr_t addr = bm_buf_addr(&bufs_in);
+ fsl_dce_unmap(addr);
+ kfree(phys_to_virt(addr));
+ count++;
+ }
+ } while (ret > 0);
+#ifdef VERBOSE
+ pr_info("Freed %d sg entries\n", count);
+#endif
+ return 0;
+}
+
+
+static int teardown_buffer_pool(void)
+{
+ empty_bman_sg_pool();
+ empty_bman_data_pool();
+ if (pool_data) {
+ bman_free_pool(pool_data);
+ pool_data = NULL;
+ }
+ if (pool_sg) {
+ bman_free_pool(pool_sg);
+ pool_sg = NULL;
+ }
+ return 0;
+}
+
+
+static int copy_bman_output_to_buffer(struct qm_sg_entry *sg, size_t cpylen,
+ char *buffer, size_t buf_size)
+{
+ dma_addr_t phy_addr;
+ void *cpumem;
+ uint64_t cal_total_lenght = 0;
+ char *pos = buffer;
+ struct qm_sg_entry *entry;
+ uint64_t remaining = cpylen;
+
+ /*
+ * As per DPAA:
+ * Processing also stops when the number of bytes specified by the
+ * overall length have been processed determine if the s/g entry is
+ * pointing to a s/g table or a simple frame
+ */
+ if (sg->extension) {
+ struct qm_sg_entry *s_entry;
+
+ /* read in address of sg table */
+ phy_addr = (dma_addr_t)qm_sg_entry_get64(sg);
+ fsl_dce_unmap(phy_addr);
+ cpumem = phys_to_virt(phy_addr);
+ s_entry = (struct qm_sg_entry *)cpumem;
+ entry = s_entry;
+ do {
+ if (!entry->extension) {
+ uint64_t to_copy;
+
+ phy_addr = (dma_addr_t)qm_sg_entry_get64(entry);
+ fsl_dce_unmap(phy_addr);
+ cpumem = phys_to_virt(phy_addr);
+ to_copy = min_t(uint64_t, entry->length,
+ remaining);
+ cal_total_lenght += to_copy;
+ remaining -= to_copy;
+ memcpy(pos, cpumem, to_copy);
+ pos += to_copy;
+ /* release buffer back to bman */
+ phy_addr = fsl_dce_map(cpumem);
+ release_data_buffer(phy_addr);
+ if (!entry->final)
+ entry++;
+ else {
+ phy_addr = fsl_dce_map(s_entry);
+ release_sg_buffer(phy_addr);
+ break;
+ }
+ } else {
+ /* address is pointing to another s/g table */
+ phy_addr = (dma_addr_t)qm_sg_entry_get64(entry);
+ fsl_dce_unmap(phy_addr);
+ cpumem = phys_to_virt(phy_addr);
+ entry = (struct qm_sg_entry *)cpumem;
+ /* free previous table */
+ phy_addr = fsl_dce_map(s_entry);
+ release_sg_buffer(phy_addr);
+ s_entry = entry;
+ }
+ } while (1);
+
+ if (cpylen != cal_total_lenght) {
+ pr_info("total frame length != calulated length (%zu)"
+ " (%llu)\n", cpylen, cal_total_lenght);
+ }
+ } else {
+ pr_info("output is simple frame from bman pool %u\n",
+ (uint32_t)sg->bpid);
+ phy_addr = (dma_addr_t)qm_sg_entry_get64(sg);
+ fsl_dce_unmap(phy_addr);
+ cpumem = phys_to_virt(phy_addr);
+ if (cpylen != sg->length) {
+ pr_info("sg length != frame output length (%zu) (%u)\n",
+ cpylen, sg->length);
+ }
+ memcpy(buffer, cpumem, sg->length);
+ /* release buffer back to bman */
+ phy_addr = fsl_dce_map(cpumem);
+ release_data_buffer(phy_addr);
+ }
+ return 0;
+}
+
+
+
+static void chunk_process_cb(struct fsl_dce_flow *flow,
+ const struct qm_fd *fd, void *callback_tag)
+{
+ struct dce_process_cf_gzip_req *data =
+ (struct dce_process_cf_gzip_req *)callback_tag;
+
+ if (unlikely(fsl_dce_get_status(fd->status) != STREAM_END)) {
+ pr_err("Error expected STREAM_END result but got 0x%x\n",
+ fsl_dce_get_status(fd->status));
+ print_dce_fd(*fd);
+ }
+ end_time = mfatb();
+ data->output_fd = *fd;
+ complete(&data->cb_done);
+}
+
+static void chunk_nop_cb(struct fsl_dce_flow *flow,
+ const struct qm_fd *fd, void *callback_tag)
+{
+}
+
+static int read_file(const char *file, char **data, int *data_len)
+{
+ struct file *filp;
+ int rc = -EINVAL;
+ struct inode *inode = NULL;
+ loff_t size, pos;
+
+ mm_segment_t oldfs = get_fs();
+
+ filp = filp_open(file, O_RDONLY | O_LARGEFILE, 0);
+ if (IS_ERR(filp)) {
+ pr_err("unable to open file: %s\n", file);
+ return PTR_ERR(filp);
+ }
+
+ inode = filp->f_path.dentry->d_inode;
+ if ((!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))) {
+ pr_err("invalid file type: %s\n", file);
+ goto out;
+ }
+
+ /*
+ * If we can't read the file, it's no good.
+ * If we can't write the file, use it read-only.
+ */
+ if (!(filp->f_op->read || filp->f_op->aio_read)) {
+ pr_err("file not readable: %s\n", file);
+ goto out;
+ }
+
+ size = i_size_read(inode->i_mapping->host);
+ if (size < 0) {
+ pr_err("unable to find file size: %s\n", file);
+ rc = (int)size;
+ goto out;
+ }
+
+ pr_info("Size of file: %s is %d\n", file, (int)size);
+
+ *data = vmalloc(size);
+ if (*data == NULL) {
+ pr_err("Out of memory loading file\n");
+ goto out;
+ }
+ pos = 0;
+ set_fs(KERNEL_DS);
+ if (vfs_read(filp, *data, size, &pos) != size) {
+ pr_info("Failed to read '%s'.\n", file);
+ rc = -1;
+ goto out;
+ }
+
+ *data_len = size;
+ set_fs(oldfs);
+ fput(filp);
+
+ return 0;
+out:
+ set_fs(oldfs);
+ fput(filp);
+ if (*data) {
+ vfree(*data);
+ *data = NULL;
+ }
+ return rc;
+}
+
+static int write_file(const char *file, char *data, size_t data_len)
+{
+ struct file *filp;
+ int rc = -EINVAL;
+ loff_t pos;
+
+ mm_segment_t oldfs = get_fs();
+
+ filp = filp_open(file, O_CREAT | O_WRONLY | O_LARGEFILE, 0666);
+ if (IS_ERR(filp)) {
+ pr_err("unable to open file: %s\n", file);
+ return PTR_ERR(filp);
+ }
+
+ if (data == NULL) {
+ pr_err("No data to write\n");
+ goto out;
+ }
+ pos = 0;
+ set_fs(KERNEL_DS);
+ rc = vfs_write(filp, data, data_len, &pos);
+ if (rc != data_len) {
+ pr_info("Failed to write '%s'.\n", file);
+ pr_info("Error %d, data_len %zu\n", rc, data_len);
+ goto out;
+ }
+
+ set_fs(oldfs);
+ fput(filp);
+
+ return 0;
+out:
+ set_fs(oldfs);
+ fput(filp);
+ return rc;
+}
+
+#define COMP_ONLY 0
+#define DECOMP_ONLY 1
+
+static int validate_module_params(void)
+{
+ if (b_sg_block_size_code < 0 ||
+ b_sg_block_size_code > DCE_TSIZE_8192B) {
+ pr_err("Invalid b_sg_block_size_code value %d\n",
+ b_sg_block_size_code);
+ return -ERANGE;
+ }
+ b_sg_block_size = 1 << (6 + b_sg_block_size_code);
+
+ if (!bman_data_size) {
+ pr_err("bman_data_size is zero. This is the size of all the"
+ " data in the bman data pool.\n");
+ return -EINVAL;
+ }
+
+ bman_data_buff_size = b_dmant * (1 << b_dexp);
+
+ pr_info("BMan data block size is %u\n", bman_data_buff_size);
+
+ b_data_block_count = (bman_data_size / bman_data_buff_size) + 1;
+
+ if (!in_file && !use_local_file) {
+ pr_err("Missing input data\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int get_input_data(struct test_data_s *test)
+{
+ char *data = NULL;
+ int len = 0;
+
+ /* check if we are using included local file */
+ if (use_local_file) {
+ /* check if we are using included local file */
+ if (test_mode == COMP_ONLY) {
+ switch (use_local_file) {
+ case 2:
+ len = paper5_2048_len;
+ data = paper5_2048;
+ break;
+ case 4:
+ len = paper5_4096_len;
+ data = paper5_4096;
+ break;
+ case 8:
+ len = paper5_8192_len;
+ data = paper5_8192;
+ break;
+ case 12:
+ len = paper5_11954_len;
+ data = paper5_11954;
+ break;
+
+ default:
+ pr_err("Unvalid use_local_file value %d\n",
+ use_local_file);
+ return -EINVAL;
+ }
+ } else {
+ test_mode = DECOMP_ONLY;
+ switch (use_local_file) {
+ case 2:
+ len = paper6_2K_compressed_gz_len;
+ data = paper6_2K_compressed_gz;
+ break;
+ case 4:
+ len = paper6_4K_compressed_gz_len;
+ data = paper6_4K_compressed_gz;
+ break;
+
+ case 8:
+ len = paper6_8K_compressed_gz_len;
+ data = paper6_8K_compressed_gz;
+ break;
+ case 12:
+ len = paper6_8K_compressed_gz_len;
+ data = paper6_8K_compressed_gz;
+ break;
+ default:
+ pr_err("Unvalid use_local_file value %d\n",
+ use_local_file);
+ return -EINVAL;
+ }
+ }
+ if (data && len) {
+ test->input_data_len = len;
+ test->input_data = vmalloc(len);
+ if (!test->input_data)
+ return -ENOMEM;
+ memcpy(test->input_data, data, len);
+ }
+ }
+
+ /* If specified input file and NOT use local data, read file */
+ if (in_file && !use_local_file) {
+ if (read_file(in_file, &test->input_data,
+ &test->input_data_len)) {
+ pr_err("Error reading in_file file: %s\n", in_file);
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+int dce_loopback_init(void)
+{
+ int ret;
+
+ pr_info("Loading dce_perf_simple_test module\n");
+
+ ret = validate_module_params();
+ if (ret)
+ return ret;
+
+ /* create test data */
+ test_data = kzalloc(sizeof(*test_data), GFP_KERNEL);
+ if (!test_data) {
+ pr_info("Error allocating test_data\n");
+ return -ENOMEM;
+ }
+
+ ret = get_input_data(test_data);
+
+ fsl_dce_clear_stat(DCE_COMP_INPUT_BYTES);
+ fsl_dce_clear_stat(DCE_DECOMP_OUTPUT_BYTES);
+
+ ret = setup_buffer_pools();
+ ret = populate_bman_data_pool();
+ ret = populate_bman_sg_pool();
+
+ ret = do_operation();
+
+ return 0;
+}
+
+void dce_loopback_shutdown(void)
+{
+ uint64_t run_time_cycle;
+ uint64_t total_compress_bytes = 0;
+ uint64_t total_decompress_bytes = 0;
+ uint64_t comp_Mbps = 0;
+ uint64_t decomp_Mbps = 0;
+ unsigned int cpufreq = 0;
+ uint64_t run_time_usec = 0;
+ uint32_t sysfreq = 0;
+ uint64_t dce_freq = 0, dce_max_freq = 400000000; /* Hz */
+ uint64_t scaled_val;
+ uint64_t temp;
+
+ sysfreq = fsl_get_sys_freq();
+ dce_freq = sysfreq;
+ do_div(dce_freq, 2);
+ cpufreq = ppc_proc_freq;
+ run_time_cycle = end_time - start_time;
+
+ temp = cpufreq;
+ run_time_usec = run_time_cycle;
+ do_div(temp, 1000000);
+ do_div(run_time_usec, temp);
+
+ /* calculated scalling factor multiple of 1000 */
+ /* 400000/300 */
+ scaled_val = dce_max_freq * 1000;
+ do_div(scaled_val, dce_freq);
+
+ pr_info("DCE Freq = %llu hz\n", dce_freq);
+ pr_info("CPU Freq: %u\n", cpufreq);
+ pr_info("Cycles to complete = %llu\n", run_time_cycle);
+ pr_info("Time (usec) to complete = %llu\n", run_time_usec);
+ pr_info("Scaling factor (by 1000) = %llu\n", scaled_val);
+
+ fsl_dce_get_stat(DCE_COMP_INPUT_BYTES, &total_compress_bytes, 1);
+ fsl_dce_get_stat(DCE_DECOMP_OUTPUT_BYTES, &total_decompress_bytes, 1);
+
+ if (total_compress_bytes) {
+ pr_info("Total Input Bytes to Compress: %llu\n",
+ total_compress_bytes);
+ pr_info("Input file size compression: %u bytes\n",
+ test_data->input_data_len);
+ }
+ if (total_decompress_bytes) {
+ pr_info("Total Input Bytes to Decompress: %llu\n",
+ total_decompress_bytes);
+ pr_info("Input file size decompression: %u bytes\n",
+ test_data->input_data_len);
+ }
+
+ /* Calculate Compression Mbps */
+ if (total_compress_bytes) {
+ uint64_t estimate_Mbps;
+
+ comp_Mbps = total_compress_bytes * 8;
+ do_div(comp_Mbps, run_time_usec);
+
+ estimate_Mbps = comp_Mbps;
+ estimate_Mbps *= scaled_val;
+ do_div(estimate_Mbps, 1000);
+
+ pr_info("Compression thoughput: %llu Mbps"
+ " (%llu Mbps for 400 Mhz DCE)\n",
+ comp_Mbps, estimate_Mbps);
+
+ } else {
+ pr_info("Compression thoughput: None\n");
+ }
+
+ /* Calculate Decompression Mbps */
+ if (total_decompress_bytes) {
+ uint64_t estimate_Mbps;
+
+ decomp_Mbps = total_decompress_bytes * 8;
+ do_div(decomp_Mbps, run_time_usec);
+
+ estimate_Mbps = decomp_Mbps;
+ estimate_Mbps *= scaled_val;
+ do_div(estimate_Mbps, 1000);
+
+ pr_info("Decompression thoughput: %llu Mbps"
+ " (%llu Mbps for 400 Mhz DCE)\n",
+ decomp_Mbps, estimate_Mbps);
+ } else {
+ pr_info("Decompression thoughput: None\n");
+ }
+ /* write output date */
+ if (out_file) {
+ write_file(out_file, test_data->out_data,
+ test_data->out_data_len);
+ }
+
+ teardown_buffer_pool();
+ vfree(test_data->out_data);
+ vfree(test_data->input_data);
+ kfree(test_data);
+}
+
+/* Module load/unload handlers */
+module_init(dce_loopback_init);
+module_exit(dce_loopback_shutdown);
+
+static int do_operation(void)
+{
+ int ret;
+ int dce_flags = 0;
+ struct dce_process_cf_gzip_req *def_process_req;
+ struct dce_bman_cfg bcfg;
+
+ pr_info("DCE thread on cpu %d\n", smp_processor_id());
+
+ bcfg.tsize = b_sg_block_size_code;
+ bcfg.tbpid = bman_get_params(pool_sg)->bpid;
+ bcfg.dbpid = bman_get_params(pool_data)->bpid;
+ bcfg.dmant = b_dmant;
+ bcfg.dexp = b_dexp;
+
+ /* initialize a compression deflate stream */
+ if (test_mode == COMP_ONLY) {
+ ret = fsl_dce_chunk_setup2(&test_data->ctx, dce_flags,
+ DCE_COMPRESSION, DCE_CF_GZIP, &bcfg,
+ chunk_process_cb, chunk_nop_cb);
+ } else {
+ ret = fsl_dce_chunk_setup2(&test_data->ctx, dce_flags,
+ DCE_DECOMPRESSION, DCE_CF_GZIP, &bcfg,
+ chunk_process_cb, chunk_nop_cb);
+ }
+ if (ret)
+ pr_err("fsl_dce_chunk_setup2 failed %d\n", ret);
+
+ ret = fsl_dce_chunk_deflate_params(&test_data->ctx,
+ DCE_PROCESS_OO_NONE_LONG, false, false,
+ comp_effort);
+
+ if (ret)
+ pr_err("fsl_dce_chunk_deflate_params failed %d\n", ret);
+
+ def_process_req = kzalloc(sizeof(*def_process_req), GFP_KERNEL);
+ if (!def_process_req)
+ pr_err("Line %d\n", __LINE__);
+
+ init_completion(&def_process_req->cb_done);
+
+ if (test_mode == COMP_ONLY)
+ init_gzip_header(&def_process_req->scf);
+
+ /* allocate input dma memory */
+ ret = alloc_dce_data(test_data->input_data_len, block_size,
+ &def_process_req->input_data);
+ if (ret)
+ pr_err("Error Allocating input data Line %d\n", __LINE__);
+#if 0
+ pr_info("Printing input_list info\n");
+ print_dce_data_list(&def_process_req->input_data);
+#endif
+
+#ifndef USE_BMAN_OUTPUT
+ /* allocate output dma contiguous memory. If compression allocate
+ * 512 bytes more. If decompression, allocate x times more. */
+ if (test_mode == COMP_ONLY) {
+ ret = alloc_dce_data(test_data->input_data_len + output_size,
+ block_size,
+ &def_process_req->output_data);
+ } else {
+ /* maximum decompression size is 20 MB */
+ ret = alloc_dce_data(test_data->input_data_len * comp_ratio,
+ block_size,
+ &def_process_req->output_data);
+ }
+ if (ret)
+ pr_err("Error Allocating Output Mem Line %d\n", __LINE__);
+#endif
+
+#if 0
+ pr_info("Printing output_list info\n");
+ print_dce_data_list(&def_process_req->output_data);
+#endif
+
+ ret = copy_input_to_dce_data(test_data->input_data,
+ test_data->input_data_len, &def_process_req->input_data);
+ if (ret)
+ pr_err("Line %d\n", __LINE__);
+#if 0
+ pr_info("Printing input after copy info\n");
+ print_dce_data_list(&def_process_req->input_data);
+#endif
+
+ ret = dma_map_dce_data(&def_process_req->input_data, DMA_BIDIRECTIONAL);
+ if (ret)
+ pr_err("Line %d\n", __LINE__);
+#if 0
+ pr_info("Printing input after dma_map info\n");
+ print_dce_data_list(&def_process_req->input_data);
+#endif
+
+#ifndef USE_BMAN_OUTPUT
+ ret = dma_map_dce_data(&def_process_req->output_data,
+ DMA_BIDIRECTIONAL);
+ if (ret)
+ pr_err("Line %d\n", __LINE__);
+
+#ifdef VERBOSE
+ pr_info("Printing output after dma_map info\n");
+ print_dce_data_list(&def_process_req->output_data);
+#endif
+ ret = attach_data_list_to_sg(&def_process_req->dce_cf[0],
+ &def_process_req->output_data,
+ DMA_BIDIRECTIONAL);
+ if (ret)
+ pr_err("Line %d\n", __LINE__);
+#endif /* !USE_BMAN_OUTPUT */
+
+ ret = attach_data_list_to_sg(&def_process_req->dce_cf[1],
+ &def_process_req->input_data,
+ DMA_BIDIRECTIONAL);
+ if (ret)
+ pr_err("Line %d\n", __LINE__);
+
+ ret = attach_scf64_to_sg(&def_process_req->dce_cf[2],
+ &def_process_req->scf,
+ DMA_BIDIRECTIONAL);
+ if (ret)
+ pr_err("Line %d\n", __LINE__);
+
+ def_process_req->dce_cf[2].final = 1;
+ def_process_req->input_fd._format2 = qm_fd_compound;
+ def_process_req->input_fd.cong_weight = 1;
+ qm_fd_addr_set64(&def_process_req->input_fd,
+ fsl_dce_map(def_process_req->dce_cf));
+#if 0
+ print_dce_fd(def_process_req->input_fd);
+ print_dce_sg(def_process_req->dce_cf[0]);
+ print_dce_sg(def_process_req->dce_cf[1]);
+ print_dce_sg(def_process_req->dce_cf[2]);
+#endif
+ start_time = mfatb();
+
+ ret = fsl_dce_chunk_process(&test_data->ctx, 0,
+ &def_process_req->input_fd, def_process_req);
+ if (unlikely(ret)) {
+ pr_err("fsl_dce_chunk_process failed %d\n", ret);
+ print_dce_fd(def_process_req->input_fd);
+ }
+ wait_for_completion(&def_process_req->cb_done);
+
+done:
+ if (fsl_dce_chunk_fifo_len(&test_data->ctx)) {
+ schedule();
+ goto done;
+
+ }
+
+ ret = fsl_dce_chunk_destroy(&test_data->ctx, 0, NULL);
+ if (ret)
+ pr_info("Error destroying fsl_chunk\n");
+
+ /* unmap the ouput frame */
+ fsl_dce_unmap(qm_fd_addr_get64(&def_process_req->output_fd));
+
+ /* save output */
+ pr_info("Output length is %u\n", def_process_req->dce_cf[0].length);
+ test_data->out_data = vmalloc(def_process_req->dce_cf[0].length);
+ if (!test_data->out_data)
+ pr_err("Unable to allocate output data\n");
+ test_data->out_data_len = def_process_req->dce_cf[0].length;
+
+#ifndef USE_BMAN_OUTPUT
+ ret = copy_dce_data_to_buffer(&def_process_req->output_data,
+ test_data->out_data_len,
+ test_data->out_data, test_data->out_data_len);
+
+ if (ret)
+ pr_err("Error %d\n", __LINE__);
+#else
+ ret = copy_bman_output_to_buffer(&def_process_req->dce_cf[0],
+ test_data->out_data_len,
+ test_data->out_data, test_data->out_data_len);
+
+ if (ret)
+ pr_err("Error %d\n", __LINE__);
+#endif
+
+ ret = detach_scf64_from_sg(&def_process_req->dce_cf[2],
+ &def_process_req->scf,
+ DMA_BIDIRECTIONAL);
+ ret = detach_data_list_from_sg(&def_process_req->dce_cf[1],
+ &def_process_req->input_data, DMA_BIDIRECTIONAL);
+
+#ifndef USE_BMAN_OUTPUT
+ ret = detach_data_list_from_sg(&def_process_req->dce_cf[0],
+ &def_process_req->output_data, DMA_BIDIRECTIONAL);
+ ret = dma_unmap_dce_data(&def_process_req->output_data,
+ DMA_BIDIRECTIONAL);
+#endif
+
+ ret = dma_unmap_dce_data(&def_process_req->input_data,
+ DMA_BIDIRECTIONAL);
+
+#ifndef USE_BMAN_OUTPUT
+ free_dce_data(&def_process_req->output_data);
+#endif
+
+ free_dce_data(&def_process_req->input_data);
+ kfree(def_process_req);
+ return 0;
+}
diff --git a/drivers/staging/fsl_dpa_offload/Kconfig b/drivers/staging/fsl_dpa_offload/Kconfig
new file mode 100644
index 0000000..baeaab3
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/Kconfig
@@ -0,0 +1,17 @@
+
+config FSL_DPA_OFFLOAD
+ tristate "Freescale Datapath Offloading Driver"
+ depends on FSL_FMAN
+ select CRC8
+ select CRC64_ECMA
+ default n
+ ---help---
+ The driver supports DPAA offloading capabilities.
+ * Classifier component makes possible the offloading of
+ classification rules by configuring the FMAN hardware.
+ * DPA IPsec component makes possible the offloading of
+ security operations (ESP) by configuring the onboard
+ SEC 4.x.
+
+ To compile this driver as a module, choose M here. The module
+ will be called dpa_offload.
diff --git a/drivers/staging/fsl_dpa_offload/Makefile b/drivers/staging/fsl_dpa_offload/Makefile
new file mode 100644
index 0000000..e4d4f3f
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/Makefile
@@ -0,0 +1,49 @@
+################################################################################
+#Copyright 2008-2013 Freescale Semiconductor, Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# Neither the name of Freescale Semiconductor nor the
+# names of its contributors may be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# ALTERNATIVELY, this software may be distributed under the terms of the
+# GNU General Public License ("GPL") as published by the Free Software
+# Foundation, either version 2 of that License or (at your option) any
+# later version.
+#
+# THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+################################################################################
+
+#
+# Makefile for the DPA Offloading driver
+#
+
+#Include NetComm SW specific definitions
+include $(srctree)/drivers/net/ethernet/freescale/fman/ncsw_config.mk
+
+EXTRA_CFLAGS += \
+ -Idrivers/crypto/caam \
+ -Idrivers/net/ethernet/freescale/fman/src/wrapper \
+ -Idrivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd \
+ -Idrivers/net/ethernet/freescale/fman/Peripherals/FM/inc
+
+obj-$(CONFIG_FSL_DPA_OFFLOAD) += dpa_offload.o
+
+dpa_offload-objs := dpa_classifier.o dpa_ipsec.o dpa_ipsec_desc.o \
+ cq.o dpa_stats.o wrp_dpa_classifier.o wrp_dpa_ipsec.o \
+ wrp_dpa_stats.o dpa_offload_module.o
diff --git a/drivers/staging/fsl_dpa_offload/cq.c b/drivers/staging/fsl_dpa_offload/cq.c
new file mode 100644
index 0000000..c8615a3
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/cq.c
@@ -0,0 +1,289 @@
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Source file for the Circular Queue object.
+ * Elements are put in and taken out of the queue in FIFO order.
+ * In addition any position in the queue may be read (without
+ * affecting the contents of the queue). The size of each item
+ * in the queue is set when the queue is initialized.
+ */
+
+#include "cq.h"
+
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+struct cq *cq_new(int max_items, int item_size)
+{
+ struct cq *cq;
+
+ BUG_ON(!max_items);
+ BUG_ON(!item_size);
+
+ cq = kmalloc(sizeof(*cq) + max_items * item_size, GFP_KERNEL);
+ if (cq) {
+ cq->max_items = max_items;
+ cq->item_size = item_size;
+ cq->items_in_queue = 0;
+ cq->first = 0;
+ mutex_init(&cq->cq_lock);
+ memset(cq->items, 0, max_items * item_size);
+ }
+
+ return cq;
+}
+
+void cq_delete(struct cq *cq)
+{
+ BUG_ON(!cq);
+ while (mutex_is_locked(&cq->cq_lock)) {
+ udelay(100);
+ cpu_relax();
+ }
+ kfree(cq);
+}
+
+int cq_flush(struct cq *cq)
+{
+ int items_in_queue;
+
+ BUG_ON(!cq);
+
+ /* Acquire circular queue lock */
+ mutex_lock(&cq->cq_lock);
+
+ items_in_queue = cq->items_in_queue;
+ cq->first = 0;
+ cq->items_in_queue = 0;
+ memset(cq->items, 0, cq->max_items * cq->item_size);
+
+ /* Release circular queue lock */
+ mutex_unlock(&cq->cq_lock);
+
+ return items_in_queue;
+}
+
+int cq_put(struct cq *cq, void *item)
+{
+ int put_pos, max_items, first, items_in_queue, item_size;
+ uint8_t *byte = (uint8_t *)item;
+
+ BUG_ON(!cq);
+
+ /* Acquire circular queue lock */
+ mutex_lock(&cq->cq_lock);
+
+ first = cq->first;
+ max_items = cq->max_items;
+ items_in_queue = cq->items_in_queue;
+ item_size = cq->item_size;
+
+ /* Check if queue is full */
+ if (items_in_queue == max_items) {
+ mutex_unlock(&cq->cq_lock);
+ return -1;
+ }
+
+ if ((first + items_in_queue) < max_items)
+ put_pos = (first + items_in_queue) * item_size;
+ else
+ put_pos = (first + items_in_queue - max_items) * item_size;
+
+ /* add element to queue */
+ memcpy(cq->items + put_pos, byte, item_size);
+
+ cq->items_in_queue++;
+
+ /* Release circular queue lock */
+ mutex_unlock(&cq->cq_lock);
+
+ return items_in_queue + 1;
+}
+
+int cq_put_1byte(struct cq *cq, uint8_t item)
+{
+ BUG_ON(!cq);
+ BUG_ON(cq->item_size != 1);
+
+ return cq_put(cq, &item);
+}
+
+int cq_put_2bytes(struct cq *cq, uint16_t item)
+{
+ BUG_ON(!cq);
+ BUG_ON(cq->item_size != 2);
+
+ return cq_put(cq, &item);
+}
+
+int cq_put_4bytes(struct cq *cq, uint32_t item)
+{
+ BUG_ON(!cq);
+ BUG_ON(cq->item_size != 4);
+
+ return cq_put(cq, &item);
+}
+
+int cq_put_8bytes(struct cq *cq, uint64_t item)
+{
+ BUG_ON(!cq);
+ BUG_ON(cq->item_size != 8);
+
+ return cq_put(cq, &item);
+}
+
+int cq_get(struct cq *cq, void *item)
+{
+ int get_pos, items_in_queue, item_size, first;
+ uint8_t *byte = (uint8_t *)item;
+
+ BUG_ON(!cq);
+ BUG_ON(!item);
+
+ /* Acquire circular queue lock */
+ mutex_lock(&cq->cq_lock);
+
+ items_in_queue = cq->items_in_queue;
+ /* Check if queue is empty */
+ if (items_in_queue == 0) {
+ /* Release circular queue lock */
+ mutex_unlock(&cq->cq_lock);
+ return -1;
+ }
+
+ first = cq->first;
+ item_size = cq->item_size;
+ get_pos = first * item_size;
+
+ /* Get item from queue */
+ memcpy(byte, cq->items + get_pos, item_size);
+ cq->items_in_queue--;
+
+ if (++first >= cq->max_items)
+ first = 0;
+ cq->first = first;
+
+ /* Release circular queue lock */
+ mutex_unlock(&cq->cq_lock);
+
+ return items_in_queue - 1;
+}
+
+int cq_get_1byte(struct cq *cq, uint8_t *item)
+{
+ BUG_ON(!cq);
+ BUG_ON(!item);
+ BUG_ON(cq->item_size != 1);
+
+ return cq_get(cq, item);
+}
+
+int cq_get_2bytes(struct cq *cq, uint16_t *item)
+{
+ BUG_ON(!cq);
+ BUG_ON(!item);
+ BUG_ON(cq->item_size != 2);
+
+ return cq_get(cq, item);
+}
+
+int cq_get_4bytes(struct cq *cq, uint32_t *item)
+{
+ BUG_ON(!cq);
+ BUG_ON(!item);
+ BUG_ON(cq->item_size != 4);
+
+ return cq_get(cq, item);
+}
+
+int cq_get_8bytes(struct cq *cq, uint64_t *item)
+{
+ BUG_ON(!cq);
+ BUG_ON(!item);
+ BUG_ON(cq->item_size != 8);
+
+ return cq_get(cq, item);
+}
+
+int cq_items_in_queue(struct cq *cq)
+{
+ int items_in_queue;
+
+ BUG_ON(!cq);
+
+ /* Acquire circular queue lock */
+ mutex_lock(&cq->cq_lock);
+
+ items_in_queue = cq->items_in_queue;
+
+ /* Release circular queue lock */
+ mutex_unlock(&cq->cq_lock);
+
+ return items_in_queue;
+}
+
+int cq_read(struct cq *cq, void *read_item, int position)
+{
+ int item_size, first, items_in_queue, bytePosition;
+ uint8_t *read_byte = (uint8_t *)read_item;
+
+ BUG_ON(!cq);
+ BUG_ON(!read_item);
+
+ /* Acquire circular queue lock */
+ mutex_lock(&cq->cq_lock);
+
+ items_in_queue = cq->items_in_queue;
+ /* Check if queue is empty and if position is valid */
+ if (items_in_queue == 0 || position > items_in_queue) {
+ mutex_unlock(&cq->cq_lock);
+ return -1;
+ }
+
+ item_size = cq->item_size;
+ first = cq->first;
+
+ /* Find byte position */
+ if (first + position - 1 > cq->max_items)
+ bytePosition =
+ (first + position - 1 - cq->max_items) * item_size;
+ else
+ bytePosition = (first + position - 1) * item_size;
+
+ /* Read from queue */
+ memcpy(read_byte, cq->items + bytePosition, item_size);
+
+ /* Release circular queue lock */
+ mutex_unlock(&cq->cq_lock);
+
+ return items_in_queue;
+}
diff --git a/drivers/staging/fsl_dpa_offload/cq.h b/drivers/staging/fsl_dpa_offload/cq.h
new file mode 100644
index 0000000..c7d8e2a
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/cq.h
@@ -0,0 +1,141 @@
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * External prototypes for the circular queue object.
+ */
+
+#ifndef __CQ_H
+#define __CQ_H
+
+#include <linux/types.h>
+#include <linux/mutex.h>
+
+/* Circular queue structure */
+struct cq {
+ int max_items; /* Size of queue */
+ int item_size; /* Size of each item in the queue */
+ int items_in_queue; /* Number of items in the queue */
+ int first; /* Index of first item in queue */
+ struct mutex cq_lock; /* Circular queue lock */
+ uint8_t items[0]; /* Holds the elements in the queue -
+ * fake size */
+};
+
+/* Allocate and initialize a new circular queue */
+struct cq *cq_new(int max_items, int item_size);
+
+/* Delete a circular queue */
+void cq_delete(struct cq *cq);
+
+/* Empty the circular queue (clear all items) */
+int cq_flush(struct cq *cq);
+
+/*
+ * Put a new item in the circular queue
+ * Return number of items in the queue (including the added item) is successful
+ * or (-1) if failed to put the item (queue is full)
+ */
+int cq_put(struct cq *cq, void *item);
+
+/* Put a new 1-byte item in the circular queue
+ * Return number of items in the queue (including the added item) is successful
+ * or (-1) if failed to put the item (queue is full)
+ */
+int cq_put_1byte(struct cq *cq, uint8_t item);
+
+/*
+ * Put a new 2-byte item in the circular queue
+ * Return number of items in the queue (including the added item) is successful
+ * or (-1) if failed to put the item (queue is full)
+ */
+int cq_put_2bytes(struct cq *cq, uint16_t item);
+
+/*
+ * Put a new 4-byte item in the circular queue
+ * Return number of items in the queue (including the added item) is successful
+ * or (-1) if failed to put the item (queue is full)
+ */
+int cq_put_4bytes(struct cq *cq, uint32_t item);
+
+/*
+ * Put a new 8-byte item in the circular queue
+ * Return number of items in the queue (including the added item) is successful
+ * or (-1) if failed to put the item (queue is full)
+ */
+int cq_put_8bytes(struct cq *cq, uint64_t item);
+
+/* Get (and removes) an item from the circular queue
+ * Return number of items left in the queue if successful or (-1) if failed to
+ * get an item (queue is empty)
+ */
+int cq_get(struct cq *cq, void *item);
+
+/*
+ * Get and removes a 1-byte item from the circular queue
+ * Return number of items left in the queue if successful or (-1) if failed to
+ * get an item (queue is empty)
+ */
+int cq_get_1byte(struct cq *cq, uint8_t *item);
+
+/*
+ * Get and removes a 2-byte item from the circular queue
+ * Return number of items left in the queue if successful or (-1) if failed to
+ * get an item (queue is empty)
+ */
+int cq_get_2bytes(struct cq *cq, uint16_t *item);
+
+/*
+ * Get and removes a 4-byte item from the circular queue
+ * Return number of items left in the queue if successful or (-1) if failed to
+ * get an item (queue is empty)
+ */
+int cq_get_4bytes(struct cq *cq, uint32_t *item);
+
+/*
+ * Get and removes a 8-byte item from the circular queue
+ * Return number of items left in the queue if successful or (-1) if failed to
+ * get an item (queue is empty)
+ */
+int cq_get_8bytes(struct cq *cq, uint64_t *item);
+
+/* Return the number of items that are currently in the queue */
+int cq_items_in_queue(struct cq *cq);
+
+/*
+ * Read an item in the queue. The contents of the queue are not altered.
+ * Return number of items left in the queue if successful or (-1) if failed to
+ * read the item (either the queue is empty, or the requested position exceeds
+ * number of items)
+ */
+int cq_read(struct cq *cq, void *item, int position);
+
+#endif /* __CQ_H */
diff --git a/drivers/staging/fsl_dpa_offload/dpa_classifier.c b/drivers/staging/fsl_dpa_offload/dpa_classifier.c
new file mode 100644
index 0000000..e4610d4
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dpa_classifier.c
@@ -0,0 +1,8030 @@
+
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * DPA Classifier Application Programming Interface implementation
+ */
+
+
+#define __DPA_CLASSIFIER_C
+
+
+#include <linux/crc8.h>
+#include <linux/crc64_ecma.h>
+#include <linux/module.h>
+
+/* DPA offloading layer includes */
+#include "dpa_classifier.h"
+
+/* FMD includes */
+#include "error_ext.h"
+#include "fm_pcd_ext.h"
+#include "fm_cc.h"
+#include "crc64.h"
+
+
+/* Granularity of the descriptor tables */
+#define DPA_CLS_ARRAYSIZEGRANULARITY 10
+
+#define PPP_HEADER_OFFSET 0
+#define PPP_HEADER_SIZE 2 /* bytes */
+#define ETHERTYPE_OFFSET 12
+#define ETHERTYPE_SIZE 2 /* bytes */
+
+#define CRC8_WCDMA_POLY 0x9b
+
+#ifdef DPA_CLASSIFIER_DEBUG
+#define dpa_cls_dbg(message) printk message
+#else
+#define dpa_cls_dbg(message)
+#endif /* DPA_CLASSIFIER_DEBUG */
+
+#define LOCK_OBJECT(desc_table, desc, object, einval) \
+ lock_desc_table(&(desc_table)); \
+ (object) = desc_to_object(&(desc_table), (desc)); \
+ if (!(object)) { \
+ release_desc_table(&(desc_table)); \
+ log_err("Invalid descriptor (%d).\n", (desc)); \
+ return (einval); \
+ } \
+ mutex_lock(&(object)->access); \
+ release_desc_table(&(desc_table))
+
+#define RELEASE_OBJECT(object) \
+ mutex_unlock(&(object)->access)
+
+#define LOCK_HM_OP_CHAIN(hm) \
+ list_for_each_entry(pcurrent, \
+ &(hm)->list_node, \
+ list_node) { \
+ mutex_lock(&pcurrent->access); \
+ } \
+ mutex_lock(&(hm)->access)
+
+#define RELEASE_HM_OP_CHAIN(hm) \
+ list_for_each_entry(pcurrent, \
+ &(hm)->list_node, \
+ list_node) { \
+ mutex_unlock(&pcurrent->access); \
+ } \
+ mutex_unlock(&(hm)->access)
+
+DEFINE_MUTEX(table_array_lock);
+DEFINE_MUTEX(hm_array_lock);
+#if (DPAA_VERSION >= 11)
+DEFINE_MUTEX(mcast_array_lock);
+#endif
+
+/* DPA Classifier table descriptor table */
+struct dpa_cls_descriptor_table table_array = {
+ .num_descriptors = 0,
+ .used_descriptors = 0,
+ .object = NULL,
+ .access = &table_array_lock
+};
+
+/* Header manipulation descriptor table */
+struct dpa_cls_descriptor_table hm_array = {
+ .num_descriptors = 0,
+ .used_descriptors = 0,
+ .object = NULL,
+ .access = &hm_array_lock
+};
+
+#if (DPAA_VERSION >= 11)
+/* Multicast group descriptor table */
+struct dpa_cls_descriptor_table mcast_grp_array = {
+ .num_descriptors = 0,
+ .used_descriptors = 0,
+ .object = NULL,
+ .access = &mcast_array_lock
+};
+#endif
+
+DECLARE_CRC8_TABLE(crc8_table);
+static bool crc8_initialized = false;
+
+/*
+ * Gets the first free descriptor in the indicated descriptor table and fills
+ * it with the provided object pointer. If there are no available descriptors,
+ * the function fails. This function is not thread safe.
+ */
+static int get_descriptor(struct dpa_cls_descriptor_table *desc_table,
+ void *object, int *desc);
+
+/*
+ * Extends with one more step an existing descriptor table. The array is
+ * reallocated with a constant number of new elements which is defined by the
+ * DPA Classifier implementation. This function is not thread safe.
+ */
+static int extend_descriptor_table(struct dpa_cls_descriptor_table
+ *desc_table);
+
+
+int dpa_classif_table_create(const struct dpa_cls_tbl_params *params,
+ int *td)
+{
+ int err = 0;
+ struct dpa_cls_table *ptable;
+ unsigned int i;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ /* Parameters sanity checks: */
+ if (!params) {
+ log_err("\"params\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+ if (!td) {
+ log_err("\"td\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ *td = DPA_OFFLD_DESC_NONE;
+
+ err = verify_table_params(params);
+ if (err < 0)
+ return err;
+
+ ptable = kzalloc(sizeof(*ptable), GFP_KERNEL);
+ if (!ptable) {
+ log_err("No more memory for DPA classifier table. Requested "
+ "table type=%d.\n", params->type);
+ err = -ENOMEM;
+ goto dpa_classif_table_create_error;
+ }
+
+ mutex_init(&ptable->access);
+
+ /* Copy over the table params into the control block */
+ memcpy(&ptable->params, params, sizeof(struct dpa_cls_tbl_params));
+
+ switch (ptable->params.type) {
+ case DPA_CLS_TBL_INDEXED:
+ ptable->int_cc_nodes_count = 1;
+ if (ptable->params.entry_mgmt == DPA_CLS_TBL_MANAGE_BY_KEY) {
+ ptable->shadow_table =
+ kzalloc(sizeof(*ptable->shadow_table),
+ GFP_KERNEL);
+ if (!ptable->shadow_table) {
+ log_err("No more memory for classifier shadow "
+ "table while creating INDEXED "
+ "table.\n");
+ err = -ENOMEM;
+ goto dpa_classif_table_create_error;
+ }
+ /*
+ * Shadow table is directly indexed with the index in
+ * the entry key
+ */
+ ptable->shadow_table->size =
+ ptable->params.indexed_params.entries_cnt;
+ }
+
+ break;
+
+ case DPA_CLS_TBL_EXACT_MATCH:
+ ptable->int_cc_nodes_count = 1;
+ if (ptable->params.entry_mgmt ==
+ DPA_CLS_TBL_MANAGE_BY_KEY) {
+ ptable->shadow_table =
+ kzalloc(sizeof(*ptable->shadow_table),
+ GFP_KERNEL);
+ if (!ptable->shadow_table) {
+ log_err("No more memory for classifier shadow "
+ "table while creating EXACT MATCH "
+ "table.\n");
+ err = -ENOMEM;
+ goto dpa_classif_table_create_error;
+ }
+
+ /* Set shadow table size */
+ ptable->shadow_table->size =
+ DPA_CLS_TBL_MAXSHADOWTABLESIZE;
+ }
+
+ break;
+
+ case DPA_CLS_TBL_HASH:
+ if (!ptable->params.prefilled_entries) {
+ ptable->int_cc_nodes_count =
+ ptable->params.hash_params.num_sets;
+ if (ptable->params.entry_mgmt ==
+ DPA_CLS_TBL_MANAGE_BY_KEY) {
+ ptable->shadow_table =
+ kzalloc(sizeof(*ptable->shadow_table),
+ GFP_KERNEL);
+ if (!ptable->shadow_table) {
+ log_err("No more memory for classifier "
+ "shadow table while creating "
+ "HASH table.\n");
+ err = -ENOMEM;
+ goto dpa_classif_table_create_error;
+ }
+
+ /*
+ * Shadow table is indexed using a CRC8 HASH on
+ * the key
+ */
+ ptable->shadow_table->size =
+ DPA_CLS_TBL_MAXSHADOWTABLESIZE;
+ }
+ }
+ break;
+ default:
+ log_err("Unsupported DPA Classifier table type (%d).\n",
+ ptable->params.type);
+ goto dpa_classif_table_create_error;
+ }
+
+ /* Init shadow table if necessary */
+ if (ptable->shadow_table) {
+ /* Allocate entries in the shadow table */
+ ptable->shadow_table->shadow_entry =
+ kmalloc(ptable->shadow_table->size *
+ sizeof(struct list_head), GFP_KERNEL);
+ if (!ptable->shadow_table->shadow_entry) {
+ log_err("No more memory for DPA Classifier shadow "
+ "table buckets (%d buckets). Requested table "
+ "type=%d.\n", ptable->shadow_table->size,
+ ptable->params.type);
+ err = -ENOMEM;
+ goto dpa_classif_table_create_error;
+ }
+
+ /* Initialize the entries in shadow table */
+ for (i = 0; i < ptable->shadow_table->size; i++)
+ INIT_LIST_HEAD(&ptable->shadow_table->shadow_entry[i]);
+ }
+
+ switch (ptable->params.type) {
+ case DPA_CLS_TBL_INDEXED:
+ err = table_init_indexed(ptable);
+ if (err < 0)
+ log_err("Failed to create INDEXED table.\n");
+ break;
+ case DPA_CLS_TBL_EXACT_MATCH:
+ err = table_init_exact_match(ptable);
+ if (err < 0)
+ log_err("Failed to create EXACT MATCH table.\n");
+ break;
+ case DPA_CLS_TBL_HASH:
+ err = table_init_hash(ptable);
+ if (err < 0)
+ log_err("Failed to create HASH table.\n");
+ break;
+ }
+ if (err < 0)
+ goto dpa_classif_table_create_error;
+
+ if (!crc8_initialized) {
+ crc8_populate_msb(crc8_table, CRC8_WCDMA_POLY);
+ crc8_initialized = true;
+ }
+
+ lock_desc_table(&table_array);
+ err = acquire_descriptor(&table_array, ptable, td);
+ release_desc_table(&table_array);
+ if (err < 0)
+ goto dpa_classif_table_create_error;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+
+dpa_classif_table_create_error:
+ /* Something went wrong. Release allocated memory and exit */
+ if (ptable) {
+ if (ptable->shadow_table) {
+ kfree(ptable->shadow_table->shadow_entry);
+ kfree(ptable->shadow_table);
+ }
+
+ free_table_management(ptable);
+
+ /* Free entry index management */
+ kfree(ptable->entry);
+ ptable->entry = NULL;
+ ptable->entries_cnt = 0;
+
+ kfree(ptable);
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(dpa_classif_table_create);
+
+int dpa_classif_table_free(int td)
+{
+ int err;
+ struct dpa_cls_table *ptable;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ lock_desc_table(&table_array);
+ ptable = desc_to_object(&table_array, td);
+ if (!ptable) {
+ release_desc_table(&table_array);
+ log_err("No such table (td=%d).\n", td);
+ return -EINVAL;
+ }
+
+ mutex_lock(&ptable->access);
+
+ /* Flush the entries in the table */
+ err = flush_table(ptable);
+
+ switch (ptable->params.type) {
+ case DPA_CLS_TBL_EXACT_MATCH:
+ break;
+ case DPA_CLS_TBL_INDEXED:
+ table_cleanup_indexed(ptable);
+ break;
+ case DPA_CLS_TBL_HASH:
+ break;
+ }
+
+ /* Check shadow table if it exists */
+ if (ptable->shadow_table) {
+ /* Release shadow table */
+ kfree(ptable->shadow_table->shadow_entry);
+ kfree(ptable->shadow_table);
+ }
+
+ /* Free entry index management */
+ kfree(ptable->entry);
+ ptable->entry = NULL;
+ ptable->entries_cnt = 0;
+
+ free_table_management(ptable);
+
+ put_descriptor(&table_array, td);
+ release_desc_table(&table_array);
+
+ kfree(ptable);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+}
+EXPORT_SYMBOL(dpa_classif_table_free);
+
+int dpa_classif_table_modify_miss_action(int td,
+ const struct dpa_cls_tbl_action *miss_action)
+{
+ int errno;
+ t_Error err;
+ t_FmPcdCcNextEngineParams miss_engine_params;
+ struct dpa_cls_table *ptable;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ /* Parameters sanity checks: */
+ if (!miss_action) {
+ log_err("\"miss_action\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ LOCK_OBJECT(table_array, td, ptable, -EINVAL);
+
+ if (ptable->params.type == DPA_CLS_TBL_INDEXED) {
+ RELEASE_OBJECT(ptable);
+ log_err("Miss Action for DPA Classifier Indexed Tables (td=%d) "
+ "is not supported.\n", td);
+ return -ENOSYS;
+ }
+
+ /* Fill the [miss_engine_params] structure w/ data */
+ errno = action_to_next_engine_params(miss_action, &miss_engine_params,
+ NULL, ptable->params.distribution,
+ ptable->params.classification);
+ if (errno < 0) {
+ RELEASE_OBJECT(ptable);
+ log_err("Failed verification of miss action params for table "
+ "td=%d.\n", td);
+ return errno;
+ }
+
+ if (ptable->params.type == DPA_CLS_TBL_HASH) {
+ err = FM_PCD_HashTableModifyMissNextEngine(ptable->params.
+ cc_node, &miss_engine_params);
+ if (err != E_OK) {
+ RELEASE_OBJECT(ptable);
+ log_err("FMan driver call failed - "
+ "FM_PCD_HashTableModifyMissNextEngine "
+ "(td=%d, Cc node handle=0x%p).\n", td,
+ ptable->params.cc_node);
+ return -EBUSY;
+ }
+ } else {
+ err = FM_PCD_MatchTableModifyMissNextEngine((t_Handle)ptable->
+ int_cc_node[0].cc_node, &miss_engine_params);
+ if (err != E_OK) {
+ RELEASE_OBJECT(ptable);
+ log_err("FMan driver call failed - "
+ "FM_PCD_MatchTableModifyMissNextEngine (td=%d, "
+ "Cc node handle=0x%p).\n", td,
+ ptable->int_cc_node[0].cc_node);
+ return -EBUSY;
+ }
+ }
+
+ memcpy(&ptable->miss_action, miss_action, sizeof(*miss_action));
+
+ RELEASE_OBJECT(ptable);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return 0;
+}
+EXPORT_SYMBOL(dpa_classif_table_modify_miss_action);
+
+int dpa_classif_table_insert_entry(int td,
+ const struct dpa_offload_lookup_key *key,
+ const struct dpa_cls_tbl_action *action,
+ int priority,
+ int *entry_id)
+{
+ int err = 0;
+ struct dpa_cls_table *ptable;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ /* Parameters sanity checks: */
+ if (!key) {
+ log_err("\"key\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+ if (!key->byte) {
+ log_err("\"key->byte\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+ if ((key->size <= 0) || (key->size > DPA_OFFLD_MAXENTRYKEYSIZE)) {
+ log_err("Key size should be between %d and %d.\n", 1,
+ DPA_OFFLD_MAXENTRYKEYSIZE);
+ return -EINVAL;
+ }
+ if (!action) {
+ log_err("\"action\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ LOCK_OBJECT(table_array, td, ptable, -EINVAL);
+
+ if (ptable->params.type == DPA_CLS_TBL_INDEXED) {
+ RELEASE_OBJECT(ptable);
+ log_err("Insert entry in an indexed table (td=%d) makes no "
+ "sense. Please use modify_entry instead.\n", td);
+ return -EINVAL;
+ }
+
+ /*
+ * Verify if there is already an entry in the table which conflicts with
+ * this one (this verification is only possible if a shadow table is
+ * used)
+ */
+ if ((ptable->shadow_table) &&
+ (find_shadow_entry(ptable, key) != NULL)) {
+ RELEASE_OBJECT(ptable);
+ log_err("DPA Classifier table entry already exists in table "
+ "td=%d. Attempted to add twice the following key (hex) "
+ "(%d byte(s)):", td, key->size);
+ dump_lookup_key(key);
+ pr_err("\n");
+ return -EEXIST;
+ }
+
+ switch (ptable->params.type) {
+ case DPA_CLS_TBL_HASH:
+ err = table_insert_entry_hash(ptable,
+ key,
+ action,
+ entry_id);
+ break;
+ case DPA_CLS_TBL_EXACT_MATCH:
+ err = table_insert_entry_exact_match(ptable,
+ key,
+ action,
+ priority,
+ entry_id);
+ break;
+ default:
+ BUG_ON(1);
+ }
+
+ RELEASE_OBJECT(ptable);
+ if (err < 0) {
+ log_err("Failed to insert entry in table td=%d. Table type=%d. "
+ "Lookup key was (hex) (%d byte(s)):", td,
+ ptable->params.type, key->size);
+ dump_lookup_key(key);
+ pr_err("\n");
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+}
+EXPORT_SYMBOL(dpa_classif_table_insert_entry);
+
+int dpa_classif_table_modify_entry_by_key(int td,
+ const struct dpa_offload_lookup_key *key,
+ const struct dpa_cls_tbl_entry_mod_params *mod_params)
+{
+ int entry_id;
+ int ret = 0;
+ struct dpa_cls_table *ptable;
+ t_Error err;
+ uint8_t key_data[DPA_OFFLD_MAXENTRYKEYSIZE];
+ uint8_t new_key_data[DPA_OFFLD_MAXENTRYKEYSIZE];
+ uint8_t mask_data[DPA_OFFLD_MAXENTRYKEYSIZE];
+ uint8_t new_mask_data[DPA_OFFLD_MAXENTRYKEYSIZE];
+ uint8_t *mask;
+ uint8_t *new_mask;
+ t_FmPcdCcKeyParams key_params;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ /* Parameters sanity checks: */
+ if (!key) {
+ log_err("\"key\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+ if (!key->byte) {
+ log_err("\"key->byte\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+ if ((key->size <= 0) || (key->size > DPA_OFFLD_MAXENTRYKEYSIZE)) {
+ log_err("Key size should be between %d and %d.\n", 1,
+ DPA_OFFLD_MAXENTRYKEYSIZE);
+ return -EINVAL;
+ }
+ if (!mod_params) {
+ log_err("\"mod_params\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ LOCK_OBJECT(table_array, td, ptable, -EINVAL);
+
+ /* Check for unsupported modifications */
+ if (ptable->params.type == DPA_CLS_TBL_INDEXED && mod_params->type !=
+ DPA_CLS_TBL_MODIFY_ACTION) {
+ RELEASE_OBJECT(ptable);
+ log_err("Modify entry key is supported only on exact match and hash tables. You attempted to use it on table td=%d which is of type=%d.\n",
+ td, ptable->params.type);
+ return -ENOSYS;
+ }
+
+ entry_id = key_to_entry_id(ptable, key);
+ if (entry_id < 0) {
+ if ((entry_id == -ENODEV) &&
+ (ptable->params.prefilled_entries)) {
+ /*
+ * This entry may have been added to the Cc node before
+ * the DPA Classifier was created. Try to modify it by
+ * key directly using the FMan driver.
+ */
+ memset(&key_params, 0, sizeof(key_params));
+ switch (mod_params->type) {
+ case DPA_CLS_TBL_MODIFY_ACTION:
+ /* Parameter sanity check: */
+ if (!mod_params->action) {
+ RELEASE_OBJECT(ptable);
+ log_err("\"mod_params->action\" cannot "
+ "be NULL.\n");
+ return -EINVAL;
+ }
+
+ ret = action_to_next_engine_params(
+ mod_params->action,
+ &key_params.ccNextEngineParams,
+ NULL,
+ (t_Handle)ptable->params.
+ distribution,
+ (t_Handle)ptable->params.
+ classification);
+ if (ret < 0) {
+ RELEASE_OBJECT(ptable);
+ log_err("Failed verification of new "
+ "action params while modifying "
+ "entry by KEY in table td=%d. "
+ "Lookup key (hex) (%d byte(s)):",
+ td, key->size);
+ dump_lookup_key(key);
+ pr_err("\n");
+ return ret;
+ }
+
+ memcpy(key_data, key->byte, key->size);
+ if (key->mask) {
+ memcpy(mask_data, key->mask, key->size);
+ mask = mask_data;
+ } else
+ mask = NULL;
+
+ if (ptable->params.type == DPA_CLS_TBL_EXACT_MATCH) {
+ err = FM_PCD_MatchTableFindNModifyNextEngine(
+ (t_Handle)ptable->int_cc_node[0].cc_node,
+ key->size,
+ key_data,
+ mask,
+ &key_params.ccNextEngineParams);
+ if (err != E_OK) {
+ RELEASE_OBJECT(ptable);
+ log_err("FMan driver call failed - "
+ "FM_PCD_MatchTableFindNModifyNextEngine"
+ ". td=%d, Cc node handle=0x%p, entry "
+ "key (hex) (%d byte(s)):", td,
+ ptable->int_cc_node[0].cc_node,
+ key->size);
+ dump_lookup_key(key);
+ pr_err("\n");
+ return -EBUSY;
+ }
+ } else { /* Table is HASH */
+ err = FM_PCD_HashTableModifyNextEngine(
+ (t_Handle)ptable->params.cc_node,
+ key->size,
+ key_data,
+ &key_params.ccNextEngineParams);
+ if (err != E_OK) {
+ RELEASE_OBJECT(ptable);
+ log_err("FMan driver call failed - "
+ "FM_PCD_HashTableModifyNextEngine. "
+ "td=%d, Cc node handle=0x%p, entry key "
+ "(hex) (%d byte(s)):", td,
+ ptable->params.cc_node, key->size);
+ dump_lookup_key(key);
+ pr_err("\n");
+ return -EBUSY;
+ }
+ }
+
+ break;
+ case DPA_CLS_TBL_MODIFY_KEY_AND_ACTION:
+ /*
+ * Only exact match tables support this type of
+ * modification.
+ */
+ BUG_ON(ptable->params.type !=
+ DPA_CLS_TBL_EXACT_MATCH);
+ /* Parameter sanity check: */
+ if (!mod_params->action) {
+ log_err("\"mod_params->action\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ ret = action_to_next_engine_params(
+ mod_params->action,
+ &key_params.ccNextEngineParams,
+ NULL,
+ (t_Handle)ptable->params.
+ distribution,
+ (t_Handle)ptable->params.
+ classification);
+ if (ret < 0) {
+ RELEASE_OBJECT(ptable);
+ log_err("Failed verification of new action params while modifying entry by KEY in table td=%d. Lookup key (hex) (%d byte(s)):",
+ td, key->size);
+ dump_lookup_key(key);
+ pr_err("\n");
+ return ret;
+ }
+
+ /* Fall into DPA_CLS_TBL_MODIFY_KEY */
+ case DPA_CLS_TBL_MODIFY_KEY:
+ /*
+ * Only exact match tables support this type of
+ * modification.
+ */
+ BUG_ON(ptable->params.type !=
+ DPA_CLS_TBL_EXACT_MATCH);
+ /* Parameter sanity check: */
+ if (!mod_params->key) {
+ log_err("\"mod_params->key\" cannot "
+ "be NULL.\n");
+ return -EINVAL;
+ }
+
+ memcpy(key_data, key->byte, key->size);
+ if (key->mask) {
+ memcpy(mask_data, key->mask, key->size);
+ mask = mask_data;
+ } else
+ mask = NULL;
+
+ memcpy(new_key_data, mod_params->key->byte,
+ mod_params->key->size);
+ if (mod_params->key->mask) {
+ memcpy(new_mask_data,
+ mod_params->key->mask,
+ mod_params->key->size);
+ new_mask = new_mask_data;
+ } else
+ new_mask = NULL;
+
+ if (mod_params->type == DPA_CLS_TBL_MODIFY_KEY) {
+ err = FM_PCD_MatchTableFindNModifyKey(
+ (t_Handle)ptable->int_cc_node[0].cc_node,
+ key->size,
+ key_data,
+ mask,
+ new_key_data,
+ new_mask);
+ if (err != E_OK) {
+ RELEASE_OBJECT(ptable);
+ log_err("FMan driver call failed - "
+ "FM_PCD_MatchTableFindNModifyKey. "
+ "td=%d, Cc node handle=0x%p, trying to "
+ "modify entry w/ key (hex) (%d "
+ "byte(s)):", td,
+ ptable->int_cc_node[0].cc_node,
+ key->size);
+ dump_lookup_key(key);
+ pr_err("\n");
+ return -EBUSY;
+ }
+ } else {
+ key_params.p_Key = new_key_data;
+ key_params.p_Mask = new_mask;
+ err = FM_PCD_MatchTableFindNModifyKeyAndNextEngine(
+ (t_Handle)ptable->int_cc_node[0].cc_node,
+ key->size,
+ key_data,
+ mask,
+ &key_params);
+ if (err != E_OK) {
+ RELEASE_OBJECT(ptable);
+ log_err("FMan driver call failed - "
+ "FM_PCD_MatchTableFindNModifyKeyAndNextEngine. "
+ "td=%d, Cc node handle=0x%p, trying to modify "
+ "entry w/ key (hex) (%d byte(s)):", td,
+ ptable->int_cc_node[0].cc_node, key->size);
+ dump_lookup_key(key);
+ pr_err("\n");
+ return -EBUSY;
+ }
+ }
+
+ break;
+ }
+
+ RELEASE_OBJECT(ptable);
+ return ret;
+ } else {
+ RELEASE_OBJECT(ptable);
+ log_err("Unable to determine entry_id associated with "
+ "this lookup key for table td=%d. Lookup key "
+ "was (hex) (%d byte(s)):", td, key->size);
+ dump_lookup_key(key);
+ pr_err("\n");
+ return entry_id;
+ }
+ }
+
+ ret = table_modify_entry_by_ref(ptable, entry_id, mod_params);
+ RELEASE_OBJECT(ptable);
+ if (ret < 0) {
+ log_err("Failed to MODIFY entry by KEY in table td=%d. "
+ "Translated entry ref=%d. Lookup key was (hex) (%d "
+ "byte(s)):", td, entry_id, key->size);
+ dump_lookup_key(key);
+ pr_err("\n");
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+EXPORT_SYMBOL(dpa_classif_table_modify_entry_by_key);
+
+void dump_lookup_key(const struct dpa_offload_lookup_key *key)
+{
+ int i, offset;
+ char data[3 * FM_PCD_MAX_SIZE_OF_KEY + 10];
+
+ offset = 0;
+ for (i = 0; i < key->size; i++) {
+ sprintf(&data[offset], " %02x", key->byte[i]);
+ offset += 3;
+ }
+ data[offset] = 0;
+ pr_err("%s. Mask was (hex):", data);
+ offset = 0;
+ if (key->mask) {
+ for (i = 0; i < key->size; i++) {
+ sprintf(&data[offset], " %02x", key->mask[i]);
+ offset += 3;
+ }
+ data[offset] = 0;
+ pr_err("%s", data);
+ } else
+ pr_err("n/a");
+}
+
+int dpa_classif_table_modify_entry_by_ref(int td,
+ int entry_id,
+ const struct dpa_cls_tbl_entry_mod_params *mod_params)
+{
+ int err;
+ struct dpa_cls_table *ptable;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ LOCK_OBJECT(table_array, td, ptable, -EINVAL);
+
+ /* Check for unsupported modifications */
+ if ((mod_params->type != DPA_CLS_TBL_MODIFY_ACTION) &&
+ (ptable->params.type == DPA_CLS_TBL_INDEXED)) {
+ log_err("Modify entry key is supported only on exact match and hash tables. You attempted to use it on table td=%d which is of type=%d.\n",
+ td, ptable->params.type);
+ return -ENOSYS;
+ }
+
+ err = table_modify_entry_by_ref(ptable, entry_id, mod_params);
+ RELEASE_OBJECT(ptable);
+ if (err < 0)
+ log_err("Failed to MODIFY entry by REF in table td=%d. Entry "
+ "ref=%d.\n", td, entry_id);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+}
+EXPORT_SYMBOL(dpa_classif_table_modify_entry_by_ref);
+
+static int hash_table_modify_entry(
+ struct dpa_cls_table *ptable,
+ int entry_id,
+ const struct dpa_offload_lookup_key *key,
+ struct dpa_cls_tbl_action *action)
+{
+ int hmd, errno;
+ unsigned int cc_node_index;
+ uint8_t entry_index;
+ u64 hash_set_index;
+ t_Error err;
+
+ t_Handle cc_node;
+ struct list_head *shadow_list_entry;
+ t_FmPcdCcKeyParams key_params;
+
+ struct dpa_cls_tbl_shadow_entry *shadow_entry;
+ struct dpa_cls_tbl_action *local_action;
+
+ hash_set_index = crc64_ecma_seed();
+ hash_set_index = crc64_ecma(key->byte,
+ ptable->params.hash_params.key_size,
+ hash_set_index);
+ hash_set_index =
+ (u64)(hash_set_index & ptable->hash_mask) >>
+ (8 * (6 - ptable->params.hash_params.hash_offs) + 4);
+
+ /*
+ * Check if there are entries still available in the
+ * selected set
+ */
+ if (ptable->int_cc_node[hash_set_index].used >=
+ ptable->int_cc_node[hash_set_index].table_size) {
+ log_err("Hash set #%llu is full (%d entries). Unable to modify this entry.\n",
+ hash_set_index,
+ ptable->int_cc_node[hash_set_index].table_size);
+ return -ENOSPC;
+ }
+
+ memset(&key_params, 0, sizeof(t_FmPcdCcKeyParams));
+
+ cc_node_index =
+ ptable->entry[entry_id].int_cc_node_index;
+ entry_index = ptable->entry[entry_id].entry_index;
+
+ cc_node =
+ (t_Handle)ptable->int_cc_node[cc_node_index].cc_node;
+
+ if (!action) {
+ /* Save action to next engine params */
+ if (ptable->shadow_table) {
+ shadow_list_entry =
+ ptable->entry[entry_id].shadow_entry;
+ shadow_entry = list_entry(shadow_list_entry,
+ struct dpa_cls_tbl_shadow_entry,
+ list_node);
+ local_action = &shadow_entry->action;
+ dpa_classif_hm_release_chain(
+ ptable->entry[entry_id].hmd);
+ errno = action_to_next_engine_params(
+ local_action,
+ &key_params.ccNextEngineParams,
+ &hmd,
+ (t_Handle)ptable->params.distribution,
+ (t_Handle)ptable->params.classification);
+ if (errno < 0)
+ return errno;
+ } else {
+ err = FM_PCD_MatchTableGetNextEngine(
+ cc_node,
+ entry_index,
+ &key_params.ccNextEngineParams);
+ if (err)
+ return -err;
+
+ hmd = ptable->entry[entry_id].hmd;
+ }
+ } else {
+ /*
+ * Release old header manip chain if available and save
+ * the action
+ */
+ dpa_classif_hm_release_chain(
+ ptable->entry[entry_id].hmd);
+ errno = action_to_next_engine_params(
+ action,
+ &key_params.ccNextEngineParams,
+ &hmd,
+ (t_Handle)ptable->params.distribution,
+ (t_Handle)ptable->params.classification);
+ if (errno < 0)
+ return errno;
+ }
+
+ if (hash_set_index != ptable->entry[entry_id].int_cc_node_index) {
+ BUG_ON(hash_set_index >= ptable->int_cc_nodes_count);
+ key_params.p_Key = key->byte;
+
+ /* Remove the key */
+ err = FM_PCD_MatchTableRemoveKey(cc_node, entry_index);
+ if (err != E_OK) {
+ log_err("FMan driver call failed - FM_PCD_MatchTableRemoveKey. Entry ref=%d, Cc node handle=0x%p, entry index=%d.\n",
+ entry_id, cc_node, entry_index);
+ return -EBUSY;
+ }
+ ptable->int_cc_node[ptable->entry[entry_id].int_cc_node_index].used--;
+
+ /* Insert the new key */
+ ptable->entry[entry_id].int_cc_node_index =
+ (unsigned int)hash_set_index;
+ ptable->entry[entry_id].entry_index =
+ (uint8_t)ptable->int_cc_node[hash_set_index].used;
+
+ /* Add the key to the selected Cc node */
+ err = FM_PCD_MatchTableAddKey((t_Handle)ptable->
+ int_cc_node[hash_set_index].cc_node,
+ ptable->entry[entry_id].entry_index,
+ ptable->params.hash_params.key_size,
+ &key_params);
+ if (err != E_OK) {
+ log_err("FMan driver call failed - FM_PCD_MatchTableAddKey. Entry ref=%d, HASH set=%llu, Cc node handle=0x%p, entry index=%d.\n",
+ entry_id, hash_set_index,
+ ptable->int_cc_node[hash_set_index].cc_node,
+ ptable->entry[entry_id].entry_index);
+ return -EBUSY;
+ }
+
+ ptable->int_cc_node[hash_set_index].used++;
+ } else {
+ if (!action) {
+ err = FM_PCD_MatchTableModifyKey((t_Handle)ptable->
+ int_cc_node[hash_set_index].cc_node,
+ ptable->entry[entry_id].entry_index,
+ ptable->params.hash_params.key_size,
+ key->mask, key->mask);
+ if (err != E_OK) {
+ log_err("FMan driver call failed - FM_PCD_MatchTableModifyKey. Entry ref=%d, HASH set=%llu, Cc node handle=0x%p, entry index=%d.\n",
+ entry_id, hash_set_index,
+ ptable->int_cc_node[hash_set_index].cc_node,
+ ptable->entry[entry_id].entry_index);
+ return -EBUSY;
+ }
+ } else {
+ err = FM_PCD_MatchTableModifyKeyAndNextEngine(
+ (t_Handle)ptable->int_cc_node[hash_set_index].cc_node,
+ ptable->entry[entry_id].entry_index,
+ ptable->params.hash_params.key_size,
+ &key_params);
+ if (err != E_OK) {
+ log_err("FMan driver call failed - FM_PCD_MatchTableModifyKeyAndNextEngine. Entry ref=%d, HASH set=%llu, Cc node handle=0x%p, entry index=%d.\n",
+ entry_id, hash_set_index,
+ ptable->int_cc_node[hash_set_index].cc_node,
+ ptable->entry[entry_id].entry_index);
+ return -EBUSY;
+ }
+ }
+ }
+ return E_OK;
+}
+
+static int hash_table_check_key(struct dpa_cls_table *ptable,
+ const struct dpa_offload_lookup_key *key)
+{
+ int i = 0;
+ if (key->size !=
+ ptable->params.hash_params.key_size) {
+ log_err("New key size (%d bytes) doesn't match the table key size (%d bytes).\n",
+ key->size,
+ ptable->params.hash_params.key_size);
+ return -EINVAL;
+ }
+ if (key->mask) {
+ /* Only full 0xFF masks supported: */
+ for (i = 0; i < key->size; i++)
+ if (key->mask[i] ^ 0xff) {
+ log_err("Only key masks 0xff all over are supported by HASH tables.\n");
+ return -EINVAL;
+ }
+ }
+ return E_OK;
+}
+
+static int table_modify_entry_by_ref(struct dpa_cls_table *ptable,
+ int entry_id,
+ const struct dpa_cls_tbl_entry_mod_params *mod_params)
+{
+ struct dpa_cls_tbl_shadow_entry *shadow_entry = NULL;
+ struct dpa_cls_tbl_shadow_entry_indexed *shadow_entry_indexed;
+ struct dpa_cls_tbl_action *action;
+ struct dpa_offload_lookup_key *key;
+ t_FmPcdCcNextEngineParams next_engine_params;
+ t_FmPcdCcKeyParams key_params;
+ uint8_t key_data[DPA_OFFLD_MAXENTRYKEYSIZE];
+ uint8_t mask_data[DPA_OFFLD_MAXENTRYKEYSIZE];
+ uint8_t masked_key[DPA_OFFLD_MAXENTRYKEYSIZE];
+ uint8_t entry_index, shadow_table_index;
+ unsigned int cc_node_index, key_size;
+ int errno;
+ t_Error err;
+ t_Handle cc_node;
+ struct list_head *shadow_list_entry, *new_bucket_list;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!ptable);
+
+ /* Parameters sanity checks: */
+ if ((entry_id < 0) || (entry_id >= ptable->entries_cnt)) {
+ log_err("Invalid \"entry_id\" (%d). Should be between %d and "
+ "%d for this table.\n", entry_id, 0,
+ ptable->entries_cnt-1);
+ return -EINVAL;
+ }
+ if (!(ptable->entry[entry_id].flags & DPA_CLS_TBL_ENTRY_VALID)) {
+ log_err("Invalid \"entry_id\" (%d).\n", entry_id);
+ return -EINVAL;
+ }
+ if (!mod_params) {
+ log_err("\"mod_params\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ if (ptable->params.type == DPA_CLS_TBL_INDEXED) {
+ cc_node_index = 0;
+ entry_index = (uint8_t) entry_id;
+ } else {
+ cc_node_index = ptable->entry[entry_id].int_cc_node_index;
+ entry_index = ptable->entry[entry_id].entry_index;
+ }
+
+ cc_node = (t_Handle)ptable->int_cc_node[cc_node_index].cc_node;
+
+ if (mod_params->type == DPA_CLS_TBL_MODIFY_ACTION) {
+ /* Parameter sanity check: */
+ if (!mod_params->action) {
+ log_err("\"mod_params->action\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ /* Release old header manip chain if available */
+ dpa_classif_hm_release_chain(ptable->entry[entry_id].hmd);
+ errno = action_to_next_engine_params(mod_params->action,
+ &next_engine_params,
+ &ptable->entry[entry_id].hmd,
+ (t_Handle)ptable->params.distribution,
+ (t_Handle)ptable->params.classification);
+ if (errno < 0)
+ return errno;
+
+ err = FM_PCD_MatchTableModifyNextEngine(cc_node,
+ entry_index,
+ &next_engine_params);
+ if (err != E_OK) {
+ log_err("FMan driver call failed - FM_PCD_MatchTableModifyNextEngine. Entry ref=%d, Cc node handle=0x%p, entry index=%d.\n",
+ entry_id, cc_node, entry_index);
+ return -EBUSY;
+ }
+ } else {
+ /*
+ * Only exact match and hash tables support this type of
+ * modification.
+ */
+ BUG_ON(ptable->params.type == DPA_CLS_TBL_INDEXED);
+
+ /* Parameters sanity checks: */
+ if (!mod_params->key) {
+ log_err("\"mod_params->key\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Have to copy the data from the key and mask because
+ * the FMD is not using const pointers and we cannot
+ * provide it the const pointers that the user provided.
+ */
+ memset(&key_params, 0, sizeof(key_params));
+ memcpy(key_data, mod_params->key->byte, mod_params->key->size);
+ key_params.p_Key = key_data;
+
+ switch (mod_params->type) {
+ case DPA_CLS_TBL_MODIFY_ACTION:
+ break;
+ case DPA_CLS_TBL_MODIFY_KEY:
+ switch (ptable->params.type) {
+ case DPA_CLS_TBL_EXACT_MATCH:
+ key_size =
+ ptable->params.exact_match_params.key_size;
+ if (mod_params->key->size != key_size) {
+ log_err("New key size (%d bytes) doesn't match the table key size (%d bytes).\n",
+ mod_params->key->size,
+ key_size);
+ return -EINVAL;
+ }
+ if (mod_params->key->mask) {
+ memcpy(mask_data, mod_params->key->mask,
+ mod_params->key->size);
+ key_params.p_Mask = mask_data;
+ }
+ err = FM_PCD_MatchTableModifyKey(cc_node,
+ entry_index,
+ key_size,
+ key_params.p_Key,
+ key_params.p_Mask);
+ if (err != E_OK) {
+ log_err("FMan driver call failed - FM_PCD_MatchTableModifyKey. Entry ref=%d, Cc node handle=0x%p, entry index=%d.\n",
+ entry_id, cc_node, entry_index);
+ return -EBUSY;
+ }
+ break;
+ case DPA_CLS_TBL_HASH:
+ /* Check the key parameter */
+ err = hash_table_check_key(ptable,
+ mod_params->key);
+ if (err)
+ return err;
+ err = hash_table_modify_entry(ptable,
+ entry_id,
+ mod_params->key,
+ NULL);
+ if (err)
+ return err;
+ break;
+ case DPA_CLS_TBL_INDEXED:
+ break;
+ }
+
+ break;
+ case DPA_CLS_TBL_MODIFY_KEY_AND_ACTION:
+ /* Parameter sanity checks */
+ if (!mod_params->action) {
+ log_err("\"mod_params->action\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ switch (ptable->params.type) {
+ case DPA_CLS_TBL_EXACT_MATCH:
+ key_size =
+ ptable->params.exact_match_params.key_size;
+ if (mod_params->key->size != key_size) {
+ log_err("New key size (%d bytes) doesn't match the table key size (%d bytes).\n",
+ mod_params->key->size,
+ key_size);
+ return -EINVAL;
+ }
+ /*
+ * Have to copy the data from the key
+ * and mask because the FMD is not
+ * using const pointers and we cannot
+ * provide it the const pointers that
+ * the user provided.
+ */
+ if (mod_params->key->mask) {
+ memcpy(mask_data,
+ mod_params->key->mask,
+ mod_params->key->size);
+ key_params.p_Mask = mask_data;
+ }
+ /*
+ * Release old header manip chain
+ * if available
+ */
+ dpa_classif_hm_release_chain(
+ ptable->entry[entry_id].hmd);
+ errno = action_to_next_engine_params(
+ mod_params->action,
+ &key_params.ccNextEngineParams,
+ &ptable->entry[entry_id].hmd,
+ (t_Handle)ptable->
+ params.distribution,
+ (t_Handle)ptable->
+ params.classification);
+ if (errno < 0)
+ return errno;
+ err =
+ FM_PCD_MatchTableModifyKeyAndNextEngine(
+ cc_node,
+ entry_index,
+ key_size,
+ &key_params);
+ if (err != E_OK) {
+ log_err("FMan driver call failed - FM_PCD_MatchTableModifyKeyAndNextEngine. Entry ref=%d, Cc node handle=0x%p, entry index=%d.\n",
+ entry_id,
+ cc_node,
+ entry_index);
+ return -EBUSY;
+ }
+ break;
+ case DPA_CLS_TBL_HASH:
+ /* Check the key parameter */
+ err = hash_table_check_key(ptable,
+ mod_params->key);
+ if (err)
+ return err;
+ err = hash_table_modify_entry(
+ ptable,
+ entry_id,
+ mod_params->key,
+ mod_params->action);
+ if (err)
+ return err;
+ break;
+ case DPA_CLS_TBL_INDEXED:
+ break;
+ }
+ break;
+ }
+ }
+
+ /* If a shadow table exists, update the data in the shadow table */
+ if (ptable->shadow_table) {
+ if (ptable->params.type == DPA_CLS_TBL_INDEXED) {
+ shadow_list_entry =
+ ptable->shadow_table->
+ shadow_entry[entry_index].next;
+ shadow_entry_indexed = list_entry(shadow_list_entry,
+ struct dpa_cls_tbl_shadow_entry_indexed,
+ list_node);
+
+ action = &shadow_entry_indexed->action;
+ } else {
+ shadow_list_entry =
+ ptable->entry[entry_id].shadow_entry;
+ shadow_entry = list_entry(shadow_list_entry,
+ struct dpa_cls_tbl_shadow_entry,
+ list_node);
+
+ key = &shadow_entry->key;
+ action = &shadow_entry->action;
+
+ if (mod_params->type == DPA_CLS_TBL_MODIFY_KEY ||
+ mod_params->type == DPA_CLS_TBL_MODIFY_KEY_AND_ACTION) {
+ /*
+ * The entry needs to be re-hashed with the new
+ * key
+ */
+ key_size =
+ ptable->params.exact_match_params.key_size;
+ key_apply_mask(mod_params->key,
+ masked_key);
+ shadow_table_index = crc8(crc8_table,
+ masked_key,
+ key_size,
+ 0);
+
+ new_bucket_list =
+ &ptable->shadow_table->shadow_entry[shadow_table_index];
+ list_del(&shadow_entry->list_node);
+ list_add(&shadow_entry->list_node,
+ new_bucket_list);
+ }
+
+ if (mod_params->type == DPA_CLS_TBL_MODIFY_KEY ||
+ mod_params->type == DPA_CLS_TBL_MODIFY_KEY_AND_ACTION) {
+ memcpy(key->byte, mod_params->key->byte,
+ key->size);
+ if ((key->mask) && (mod_params->key->mask))
+ memcpy(key->mask, mod_params->key->mask,
+ key->size);
+ }
+ }
+
+ if (mod_params->type == DPA_CLS_TBL_MODIFY_ACTION ||
+ mod_params->type == DPA_CLS_TBL_MODIFY_KEY_AND_ACTION)
+ memcpy(action, mod_params->action,
+ sizeof(struct dpa_cls_tbl_action));
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return 0;
+}
+
+int dpa_classif_table_delete_entry_by_key(int td,
+ const struct dpa_offload_lookup_key *key)
+{
+ int entry_id;
+ int err = 0;
+ t_Error error;
+ struct dpa_cls_table *ptable;
+ uint8_t key_data[DPA_OFFLD_MAXENTRYKEYSIZE];
+ uint8_t mask_data[DPA_OFFLD_MAXENTRYKEYSIZE];
+ uint8_t *mask;
+ struct list_head *list_current;
+ struct dpa_cls_tbl_entry *index_entry;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ /* Parameters sanity checks: */
+ if (!key) {
+ log_err("\"key\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+ if (!key->byte) {
+ log_err("\"key->byte\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+ if ((key->size <= 0) || (key->size > DPA_OFFLD_MAXENTRYKEYSIZE)) {
+ log_err("Key size should be between %d and %d.\n", 1,
+ DPA_OFFLD_MAXENTRYKEYSIZE);
+ return -EINVAL;
+ }
+
+ LOCK_OBJECT(table_array, td, ptable, -EINVAL);
+
+ entry_id = key_to_entry_id((struct dpa_cls_table *)
+ ptable, key);
+ if (entry_id < 0) {
+ if ((entry_id == -ENODEV) &&
+ (ptable->params.prefilled_entries)) {
+ /*
+ * This entry may have been added to the Cc node before
+ * the DPA Classifier was created. Try to delete it by
+ * key directly using the FMan driver.
+ */
+
+ memcpy(key_data, key->byte, key->size);
+ if (key->mask) {
+ memcpy(mask_data, key->mask, key->size);
+ mask = mask_data;
+ } else
+ mask = NULL;
+
+ switch (ptable->params.type) {
+ case DPA_CLS_TBL_EXACT_MATCH:
+
+ error = FM_PCD_MatchTableFindNRemoveKey(
+ (t_Handle)ptable->int_cc_node[0].cc_node,
+ key->size,
+ key_data,
+ mask);
+ if (error != E_OK) {
+ RELEASE_OBJECT(ptable);
+ log_err("FMan driver call failed - "
+ "FM_PCD_MatchTableFindNRemoveKey. "
+ "td=%d, Cc node handle=0x%p, trying to "
+ "remove entry w/ key (hex) (%d byte(s)):",
+ td, ptable->int_cc_node[0].cc_node,
+ key->size);
+ dump_lookup_key(key);
+ pr_err("\n");
+ return -EBUSY;
+ }
+
+ /* Update the index management for all entries. */
+ list_current = ptable->entry_list.next;
+ while (list_current != &ptable->entry_list) {
+ index_entry = list_entry(list_current,
+ struct dpa_cls_tbl_entry,
+ list_node);
+ index_entry->entry_index--;
+ list_current = list_current->next;
+ }
+
+ break;
+ case DPA_CLS_TBL_HASH:
+
+ error = FM_PCD_HashTableRemoveKey(
+ (t_Handle)ptable->params.cc_node,
+ key->size,
+ key_data);
+ if (error != E_OK) {
+ RELEASE_OBJECT(ptable);
+ log_err("FMan driver call failed - "
+ "FM_PCD_HashTableRemoveKey. "
+ "td=%d, Cc node handle=0x%p, "
+ "trying to remove entry w/ key "
+ "(hex) (%d byte(s)):", td,
+ ptable->params.cc_node,
+ key->size);
+ dump_lookup_key(key);
+ pr_err("\n");
+ return -EBUSY;
+ }
+
+ /* No entry management at all. */
+
+ break;
+ default:
+ BUG_ON(1);
+ break;
+ }
+
+ RELEASE_OBJECT(ptable);
+ return err;
+ } else {
+ RELEASE_OBJECT(ptable);
+ log_err("Unable to determine entry_id associated with "
+ "this lookup key (hex) (%d bytes):", key->size);
+ dump_lookup_key(key);
+ pr_err("\n");
+ return entry_id;
+ }
+ }
+
+ err = table_delete_entry_by_ref(ptable, entry_id);
+ RELEASE_OBJECT(ptable);
+ if (err < 0) {
+ log_err("Failed to DELETE entry by KEY in table td=%d. "
+ "Translated entry ref=%d. Lookup key was (hex) (%d "
+ "byte(s)):", td, entry_id, key->size);
+ dump_lookup_key(key);
+ pr_err("\n");
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+}
+EXPORT_SYMBOL(dpa_classif_table_delete_entry_by_key);
+
+int dpa_classif_table_delete_entry_by_ref(int td, int entry_id)
+{
+ int err;
+ struct dpa_cls_table *ptable;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ LOCK_OBJECT(table_array, td, ptable, -EINVAL);
+
+ err = table_delete_entry_by_ref(ptable, entry_id);
+ RELEASE_OBJECT(ptable);
+ if (err < 0)
+ log_err("Failed to DELETE entry by REF in table td=%d. Entry "
+ "ref=%d.\n", td, entry_id);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+}
+EXPORT_SYMBOL(dpa_classif_table_delete_entry_by_ref);
+
+static int table_delete_entry_by_ref(struct dpa_cls_table *ptable, int entry_id)
+{
+ t_Error err;
+ struct dpa_cls_tbl_shadow_entry *shadow_entry;
+ struct dpa_cls_tbl_shadow_entry_indexed *shadow_entry_indexed;
+ uint8_t entry_index;
+ unsigned int cc_node_index;
+ t_Handle cc_node;
+ struct list_head *shadow_list_entry, *list_current;
+ struct dpa_cls_tbl_cc_node_info *int_cc_node;
+ struct dpa_cls_tbl_entry *index_entry;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!ptable);
+
+ /* Parameters sanity checks: */
+ if ((entry_id < 0) || (entry_id >= ptable->entries_cnt)) {
+ log_err("Invalid \"entry_id\" (%d). Should be between %d and "
+ "%d for this table.\n", entry_id, 0,
+ ptable->entries_cnt-1);
+ return -EINVAL;
+ }
+ if (!(ptable->entry[entry_id].flags & DPA_CLS_TBL_ENTRY_VALID)) {
+ log_err("Invalid \"entry_id\" (%d).\n", entry_id);
+ return -EINVAL;
+ }
+
+ cc_node_index = ptable->entry[entry_id].int_cc_node_index;
+ entry_index = ptable->entry[entry_id].entry_index;
+
+ cc_node = (t_Handle)ptable->int_cc_node[cc_node_index].cc_node;
+ int_cc_node = &ptable->int_cc_node[cc_node_index];
+ if (ptable->params.type == DPA_CLS_TBL_INDEXED) {
+ log_err("Delete entry is not allowed on an indexed table.\n");
+ return -EINVAL;
+ } else {
+ /* For all the other tables types we can remove the key */
+ err = FM_PCD_MatchTableRemoveKey(cc_node,
+ entry_index);
+ if (err != E_OK) {
+ log_err("FMan driver call failed - "
+ "FM_PCD_MatchTableRemoveKey. Entry ref=%d, Cc "
+ "node handle=0x%p, entry index=%d.\n",
+ entry_id, cc_node, entry_index);
+ return -EBUSY;
+ }
+
+ /*
+ * Update the index management for the Cc node that this entry
+ * was removed from.
+ */
+ list_current = ptable->entry[entry_id].list_node.next;
+ while (list_current != &ptable->entry_list) {
+ index_entry = list_entry(list_current,
+ struct dpa_cls_tbl_entry,
+ list_node);
+ if (index_entry->int_cc_node_index >
+ cc_node_index)
+ break;
+ index_entry->entry_index--;
+ list_current = list_current->next;
+ }
+
+ list_del(&ptable->entry[entry_id].list_node);
+ }
+
+ ptable->entry[entry_id].flags &= (~DPA_CLS_TBL_ENTRY_VALID);
+ dpa_classif_hm_release_chain(ptable->entry[entry_id].hmd);
+
+ int_cc_node->used--;
+
+ if (ptable->shadow_table) {
+ if (ptable->params.type == DPA_CLS_TBL_INDEXED) {
+ shadow_list_entry = ptable->shadow_table[0].
+ shadow_entry[entry_index].next;
+ shadow_entry_indexed = list_entry(shadow_list_entry,
+ struct dpa_cls_tbl_shadow_entry_indexed,
+ list_node);
+
+ list_del(&shadow_entry_indexed->list_node);
+
+ kfree(shadow_entry_indexed);
+ } else {
+ shadow_list_entry =
+ ptable->entry[entry_id].shadow_entry;
+ shadow_entry = list_entry(shadow_list_entry,
+ struct dpa_cls_tbl_shadow_entry,
+ list_node);
+
+ list_del(&shadow_entry->list_node);
+
+ kfree(shadow_entry->key.byte);
+ kfree(shadow_entry->key.mask);
+ kfree(shadow_entry);
+ }
+
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return 0;
+}
+
+int dpa_classif_table_lookup_by_key(int td,
+ const struct dpa_offload_lookup_key *key,
+ struct dpa_cls_tbl_action *action)
+{
+ struct list_head *pos;
+ struct dpa_cls_tbl_shadow_entry *shadow_entry;
+ struct dpa_cls_tbl_shadow_entry_indexed *shadow_entry_indexed;
+ struct dpa_cls_table *ptable;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ /* Parameters sanity checks: */
+ if (!key) {
+ log_err("\"key\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+ if (!key->byte) {
+ log_err("\"key->byte\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+ if ((key->size <= 0) || (key->size > DPA_OFFLD_MAXENTRYKEYSIZE)) {
+ log_err("Key size should be between %d and %d.\n", 1,
+ DPA_OFFLD_MAXENTRYKEYSIZE);
+ return -EINVAL;
+ }
+ if (!action) {
+ log_err("\"action\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ LOCK_OBJECT(table_array, td, ptable, -EINVAL);
+
+ if (!ptable->shadow_table) {
+ RELEASE_OBJECT(ptable);
+ log_err("Cannot lookup by key in a DPA_CLS_TBL_MANAGE_BY_REF "
+ "table (td=%d).\n", td);
+ return -ENOSYS;
+ }
+
+ pos = find_shadow_entry(ptable, key);
+ if (!pos) {
+ RELEASE_OBJECT(ptable);
+ return -ENODEV;
+ }
+
+ if (ptable->params.type == DPA_CLS_TBL_INDEXED) {
+ shadow_entry_indexed = list_entry(pos,
+ struct dpa_cls_tbl_shadow_entry_indexed,
+ list_node);
+ memcpy(action, &shadow_entry_indexed->action,
+ sizeof(struct dpa_cls_tbl_action));
+ } else {
+ shadow_entry = list_entry(pos,
+ struct dpa_cls_tbl_shadow_entry,
+ list_node);
+ memcpy(action, &shadow_entry->action,
+ sizeof(struct dpa_cls_tbl_action));
+ }
+
+ RELEASE_OBJECT(ptable);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return 0;
+}
+EXPORT_SYMBOL(dpa_classif_table_lookup_by_key);
+
+int dpa_classif_table_lookup_by_ref(int td,
+ int entry_id,
+ struct dpa_cls_tbl_action *action)
+{
+ struct dpa_cls_table *ptable;
+ struct dpa_cls_tbl_shadow_entry *shadow_entry;
+ struct dpa_cls_tbl_shadow_entry_indexed *shadow_entry_indexed;
+ struct list_head *shadow_list_entry;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ /* Parameters sanity checks: */
+ if (!action) {
+ log_err("\"action\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ LOCK_OBJECT(table_array, td, ptable, -EINVAL);
+
+ /* Parameters sanity checks: */
+ if ((entry_id < 0) || (entry_id >= ptable->entries_cnt)) {
+ RELEASE_OBJECT(ptable);
+ log_err("Invalid \"entry_id\" (%d). Should be between %d and "
+ "%d for this table.\n", entry_id, 0,
+ ptable->entries_cnt-1);
+ return -EINVAL;
+ }
+ if (!(ptable->entry[entry_id].flags & DPA_CLS_TBL_ENTRY_VALID)) {
+ RELEASE_OBJECT(ptable);
+ log_err("Invalid \"entry_id\" (%d).\n", entry_id);
+ return -EINVAL;
+ }
+
+ if (!ptable->shadow_table) {
+ RELEASE_OBJECT(ptable);
+ log_err("Cannot lookup in a DPA_CLS_TBL_MANAGE_BY_REF table "
+ "(td=%d).\n", td);
+ return -ENOSYS;
+ }
+
+ if (ptable->params.type == DPA_CLS_TBL_INDEXED) {
+ shadow_list_entry = ptable->shadow_table->
+ shadow_entry[entry_id].next;
+ shadow_entry_indexed = list_entry(shadow_list_entry,
+ struct dpa_cls_tbl_shadow_entry_indexed,
+ list_node);
+
+ memcpy(action, &shadow_entry_indexed->action,
+ sizeof(struct dpa_cls_tbl_action));
+ } else {
+ shadow_list_entry = ptable->entry[entry_id].shadow_entry;
+ shadow_entry = list_entry(shadow_list_entry,
+ struct dpa_cls_tbl_shadow_entry,
+ list_node);
+
+ memcpy(action, &shadow_entry->action,
+ sizeof(struct dpa_cls_tbl_action));
+ }
+
+ RELEASE_OBJECT(ptable);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return 0;
+}
+EXPORT_SYMBOL(dpa_classif_table_lookup_by_ref);
+
+int dpa_classif_table_flush(int td)
+{
+ int err;
+ struct dpa_cls_table *ptable;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ LOCK_OBJECT(table_array, td, ptable, -EINVAL);
+
+ err = flush_table(ptable);
+ RELEASE_OBJECT(ptable);
+ if (err < 0)
+ log_err("Failed to flush table td=%d. Table type=%d.\n", td,
+ ptable->params.type);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+}
+EXPORT_SYMBOL(dpa_classif_table_flush);
+
+static int flush_table(struct dpa_cls_table *ptable)
+{
+ struct dpa_cls_tbl_shadow_entry *shadow_entry;
+ unsigned int cc_node_index, i;
+ t_Error err;
+ t_Handle cc_node;
+ struct list_head *list_current, *tmp;
+ struct dpa_cls_tbl_cc_node_info *int_cc_node;
+ struct dpa_cls_tbl_entry *index_entry;
+ t_FmPcdCcNextEngineParams next_engine_params;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ if ((ptable->params.type == DPA_CLS_TBL_HASH) &&
+ (ptable->params.prefilled_entries))
+ /* Flush not available for pre-filled HASH tables */
+ return 0;
+
+ if (list_empty(&ptable->entry_list))
+ /* Table is already empty. Nothing to do */
+ return 0;
+
+ if (ptable->params.type == DPA_CLS_TBL_INDEXED) {
+ cc_node = ptable->params.cc_node;
+
+ /* Replace all indexed entries with DROP */
+ memset(&next_engine_params, 0, sizeof(next_engine_params));
+ next_engine_params.nextEngine = e_FM_PCD_DONE;
+ next_engine_params.params.enqueueParams.action =
+ e_FM_PCD_DROP_FRAME;
+
+ for (i = 0; i < ptable->params.indexed_params.entries_cnt;
+ i++) {
+ err = FM_PCD_MatchTableModifyNextEngine(cc_node,
+ (uint16_t)i,
+ &next_engine_params);
+ if (err != E_OK) {
+ log_err("FMan driver call failed - "
+ "FM_PCD_MatchTableModifyNextEngine. "
+ "Cc node handle=0x%p, entry index=%d.\n",
+ cc_node, i);
+ return -EBUSY;
+ }
+
+ dpa_classif_hm_release_chain(ptable->entry[i].hmd);
+ ptable->entry[i].hmd = DPA_OFFLD_DESC_NONE;
+ }
+ } else {
+ /* Flush the table from tail to head to avoid having to update
+ * the remaining entry indexes all the time */
+ list_current = ptable->entry_list.prev;
+ while (list_current != &ptable->entry_list) {
+ index_entry = list_entry(list_current,
+ struct dpa_cls_tbl_entry,
+ list_node);
+ if (index_entry->shadow_entry) {
+ /* Clean up shadow entry as well */
+ shadow_entry =
+ list_entry(index_entry->shadow_entry,
+ struct dpa_cls_tbl_shadow_entry,
+ list_node);
+
+ list_del(&shadow_entry->list_node);
+
+ kfree(shadow_entry->key.byte);
+ kfree(shadow_entry->key.mask);
+ kfree(shadow_entry);
+ }
+
+ cc_node_index = index_entry->int_cc_node_index;
+ cc_node = (t_Handle)ptable->int_cc_node[cc_node_index].
+ cc_node;
+ int_cc_node = &ptable->int_cc_node[cc_node_index];
+
+ dpa_classif_hm_release_chain(index_entry->hmd);
+#ifdef DPA_CLASSIFIER_DEBUG
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d): Remove "
+ "entry #%d from table cc_node=0x%p.\n",
+ __func__, __LINE__, index_entry->entry_index,
+ cc_node));
+#endif /* DPA_CLASSIFIER_DEBUG */
+ err = FM_PCD_MatchTableRemoveKey(cc_node,
+ index_entry->entry_index);
+ if (err != E_OK) {
+ log_err("FMan driver call failed - "
+ "FM_PCD_MatchTableRemoveKey. Cc node "
+ "handle=0x%p, entry index=%d.\n",
+ cc_node, index_entry->entry_index);
+ return -EBUSY;
+ }
+
+ int_cc_node->used--;
+ index_entry->flags &= (~DPA_CLS_TBL_ENTRY_VALID);
+ tmp = list_current;
+ list_current = list_current->prev;
+ list_del(tmp);
+ }
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return 0;
+}
+
+int dpa_classif_table_get_entry_stats_by_key(int td,
+ const struct dpa_offload_lookup_key *key,
+ struct dpa_cls_tbl_entry_stats *stats)
+{
+ int entry_id;
+ int err;
+ struct dpa_cls_table *ptable;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ /* Parameters sanity checks: */
+ if (!key) {
+ log_err("\"key\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+ if (!key->byte) {
+ log_err("\"key->byte\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+ if ((key->size <= 0) || (key->size > DPA_OFFLD_MAXENTRYKEYSIZE)) {
+ log_err("Key size should be between %d and %d.\n", 1,
+ DPA_OFFLD_MAXENTRYKEYSIZE);
+ return -EINVAL;
+ }
+ if (!stats) {
+ log_err("\"stats\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ LOCK_OBJECT(table_array, td, ptable, -EINVAL);
+
+ if ((ptable->params.type == DPA_CLS_TBL_HASH) &&
+ (ptable->params.prefilled_entries)) {
+ RELEASE_OBJECT(ptable);
+ /* get_entry_stats not supported on prefilled HASH tables */
+ log_err("get_entry_stats_by_key is not supported on prefilled "
+ "HASH tables (td=%d).\n", td);
+ return -ENOSYS;
+ }
+ entry_id = key_to_entry_id(ptable, key);
+ if (entry_id < 0) {
+ RELEASE_OBJECT(ptable);
+ log_err("Unable to determine entry_id associated with this "
+ "lookup key (hex) (%d byte(s)):", key->size);
+ dump_lookup_key(key);
+ pr_err("\n");
+ return entry_id;
+ }
+
+ err = table_get_entry_stats_by_ref(ptable, entry_id, stats);
+ RELEASE_OBJECT(ptable);
+ if (err < 0) {
+ log_err("Failed to get entry STATS by KEY in table td=%d. "
+ "Translated entry ref=%d. Lookup key was (hex) (%d "
+ "byte(s)):", td, entry_id, key->size);
+ dump_lookup_key(key);
+ pr_err("\n");
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+}
+EXPORT_SYMBOL(dpa_classif_table_get_entry_stats_by_key);
+
+int dpa_classif_table_get_entry_stats_by_ref(int td,
+ int entry_id,
+ struct dpa_cls_tbl_entry_stats *stats)
+{
+ struct dpa_cls_table *ptable;
+ int err;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ LOCK_OBJECT(table_array, td, ptable, -EINVAL);
+
+ err = table_get_entry_stats_by_ref(ptable, entry_id, stats);
+ RELEASE_OBJECT(ptable);
+ if (err < 0)
+ log_err("Failed to get entry STATS by REF in table td=%d. "
+ "Entry ref=%d.\n", td, entry_id);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+}
+EXPORT_SYMBOL(dpa_classif_table_get_entry_stats_by_ref);
+
+static int table_get_entry_stats_by_ref(struct dpa_cls_table *ptable,
+ int entry_id,
+ struct dpa_cls_tbl_entry_stats *stats)
+{
+ unsigned int cc_node_index;
+ uint8_t entry_index;
+ t_Handle cc_node;
+ struct dpa_cls_tbl_entry *index_entry;
+ t_FmPcdCcKeyStatistics key_stats;
+ t_Error err;
+ int ret = 0;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!ptable);
+
+ /* Parameters sanity checks: */
+ if ((entry_id < 0) || (entry_id >= ptable->entries_cnt)) {
+ log_err("Invalid \"entry_id\" (%d). Should be between %d and "
+ "%d for this table.\n", entry_id, 0,
+ ptable->entries_cnt-1);
+ return -EINVAL;
+ }
+ if (!(ptable->entry[entry_id].flags & DPA_CLS_TBL_ENTRY_VALID)) {
+ log_err("Invalid \"entry_id\" (%d).\n", entry_id);
+ return -EINVAL;
+ }
+ if (!stats) {
+ log_err("\"stats\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ cc_node_index = ptable->entry[entry_id].int_cc_node_index;
+ index_entry = &ptable->entry[entry_id];
+ entry_index = index_entry->entry_index;
+
+ cc_node = (t_Handle)ptable->int_cc_node[cc_node_index].cc_node;
+ err = FM_PCD_MatchTableGetKeyStatistics(cc_node, entry_index,
+ &key_stats);
+ if (err != E_OK) {
+ log_warn("FMan driver call failed - FM_PCD_MatchTableGetKeyStatistics. Failed to acquire key statistics.\n");
+ memset(stats, 0, sizeof(*stats));
+ ret = -EPERM;
+ } else {
+ stats->pkts = key_stats.frameCount;
+ stats->bytes = key_stats.byteCount;
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+
+int dpa_classif_table_get_params(int td, struct dpa_cls_tbl_params *params)
+{
+ struct dpa_cls_table *ptable;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ /* Parameters sanity checks: */
+ if (!params) {
+ log_err("\"params\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ LOCK_OBJECT(table_array, td, ptable, -EINVAL);
+
+ memcpy(params, &ptable->params, sizeof(struct dpa_cls_tbl_params));
+
+ RELEASE_OBJECT(ptable);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return 0;
+}
+EXPORT_SYMBOL(dpa_classif_table_get_params);
+
+static int alloc_table_management(struct dpa_cls_table *cls_table)
+{
+ int err = 0;
+
+ BUG_ON(!cls_table);
+
+ /* Allocate the necessary table management tools */
+ if (!cls_table->int_cc_nodes_count)
+ return 0;
+
+ cls_table->int_cc_node =
+ kzalloc(cls_table->int_cc_nodes_count *
+ sizeof(*cls_table->int_cc_node), GFP_KERNEL);
+ if (!cls_table->int_cc_node) {
+ log_err("No more memory for DPA Classifier table "
+ "management.\n");
+ err = -ENOMEM;
+ goto alloc_table_mgmt_error;
+ }
+
+ return err;
+
+alloc_table_mgmt_error:
+ free_table_management(cls_table);
+
+ return err;
+}
+
+static void free_table_management(struct dpa_cls_table *cls_table)
+{
+ BUG_ON(!cls_table);
+
+ kfree(cls_table->int_cc_node);
+
+ cls_table->int_cc_nodes_count = 0;
+}
+
+static int table_init_indexed(struct dpa_cls_table *cls_table)
+{
+ t_Error err;
+ int errno;
+ uint8_t i;
+ t_FmPcdCcNextEngineParams next_engine_params;
+ t_Handle cc_node;
+ struct dpa_cls_tbl_shadow_entry_indexed *shadow_entry;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!cls_table);
+ BUG_ON(cls_table->params.type != DPA_CLS_TBL_INDEXED);
+ BUG_ON(cls_table->int_cc_nodes_count != 1);
+
+ errno = alloc_table_management(cls_table);
+ if (errno < 0)
+ return errno;
+
+ /* The only managed Cc node is the one provided by the application */
+ cls_table->int_cc_node[0].cc_node = cls_table->params.cc_node;
+ cls_table->int_cc_node[0].table_size =
+ cls_table->params.indexed_params.entries_cnt;
+ /* Indexed table is always pre-populated: */
+ cls_table->int_cc_node[0].used =
+ cls_table->params.indexed_params.entries_cnt;
+ cls_table->params.prefilled_entries = 0;
+
+ /* Allocate and initialize the index management array */
+ cls_table->entries_cnt = cls_table->params.indexed_params.entries_cnt;
+ cls_table->entry =
+ kzalloc(cls_table->entries_cnt * sizeof(*cls_table->entry),
+ GFP_KERNEL);
+ if (!cls_table->entry) {
+ log_err("No more memory for DPA Classifier table index "
+ "management.\n");
+ cls_table->entries_cnt = 0;
+ return -ENOMEM;
+ }
+ INIT_LIST_HEAD(&cls_table->entry_list);
+
+ for (i = 0; i < cls_table->entries_cnt; i++) {
+ /* Clean up and prepare the index entry */
+ memset(&cls_table->entry[i], 0,
+ sizeof(struct dpa_cls_tbl_entry));
+ cls_table->entry[i].flags |= DPA_CLS_TBL_ENTRY_VALID;
+ cls_table->entry[i].entry_index = i;
+ cls_table->entry[i].hmd = DPA_OFFLD_DESC_NONE;
+
+ list_add(&cls_table->entry[i].list_node,
+ &cls_table->entry_list);
+ }
+
+ /*
+ * If we have a shadow table, import the actions from the indexed Cc
+ * node now
+ */
+ if (cls_table->shadow_table) {
+ cc_node = (t_Handle)cls_table->params.cc_node;
+ for (i = 0; i < cls_table->params.indexed_params.entries_cnt;
+ i++) {
+ err = FM_PCD_MatchTableGetNextEngine(cc_node,
+ i,
+ &next_engine_params);
+ if (err != E_OK) {
+ log_err("FMan driver call failed - "
+ "FM_PCD_MatchTableGetNextEngine. Cc "
+ "node handle=0x%p, entry index=%d.\n",
+ cc_node, i);
+ return -EBUSY;
+ }
+
+ shadow_entry = kzalloc(sizeof(*shadow_entry),
+ GFP_KERNEL);
+ if (!shadow_entry) {
+ log_err("Out of memory while populating shadow "
+ "table.\n");
+ return -ENOMEM;
+ }
+
+ next_engine_params_to_action(&next_engine_params,
+ &shadow_entry->action);
+
+ cls_table->entry[i].shadow_entry =
+ &shadow_entry->list_node;
+
+ /* Add entry to the shadow table. */
+ list_add(&shadow_entry->list_node,
+ &cls_table->shadow_table->shadow_entry[i]);
+ }
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return 0;
+}
+
+static int table_init_hash(struct dpa_cls_table *cls_table)
+{
+ uint16_t i;
+ int err = 0;
+ t_FmPcdCcNextEngineParams next_engine_params;
+ t_Handle cc_node;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!cls_table);
+ BUG_ON(cls_table->params.type != DPA_CLS_TBL_HASH);
+
+ err = alloc_table_management(cls_table);
+ if (err < 0)
+ return err;
+
+ cc_node = (t_Handle)cls_table->params.cc_node;
+ if (!cls_table->params.prefilled_entries) {
+ for (i = 0; i < cls_table->params.hash_params.num_sets; i++) {
+ /*
+ * Acquire next engine parameters for each index entry
+ * in the main HASH Cc node.
+ */
+ if (FM_PCD_MatchTableGetNextEngine(cc_node,
+ i,
+ &next_engine_params) != E_OK) {
+ log_err("FMan driver call failed - "
+ "FM_PCD_MatchTableGetNextEngine. Cc "
+ "node handle=0x%p, entry index=%d.\n",
+ cc_node, i);
+ err = -EBUSY;
+ goto table_init_hash_error;
+ }
+
+ /*
+ * Store the HASH set handle into the internal Cc nodes
+ * data structures.
+ */
+ BUG_ON(next_engine_params.nextEngine != e_FM_PCD_CC);
+ cls_table->int_cc_node[i].cc_node =
+ next_engine_params.params.ccParams.h_CcNode;
+ cls_table->int_cc_node[i].table_size =
+ cls_table->params.hash_params.max_ways;
+ }
+
+ /* Allocate the index management array */
+ cls_table->entries_cnt = cls_table->params.hash_params.
+ num_sets * cls_table->params.hash_params.max_ways;
+ cls_table->entry = kzalloc(cls_table->entries_cnt *
+ sizeof(*cls_table->entry), GFP_KERNEL);
+ if (!cls_table->entry) {
+ log_err("No more memory for DPA Classifier table index "
+ "management.\n");
+ cls_table->entries_cnt = 0;
+ err = -ENOMEM;
+ goto table_init_hash_error;
+ }
+ INIT_LIST_HEAD(&cls_table->entry_list);
+
+ cls_table->hash_mask =
+ (uint64_t)(cls_table->params.hash_params.num_sets - 1)
+ << (8 * (6 - cls_table->params.hash_params.hash_offs)
+ + 4) ;
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+
+table_init_hash_error:
+ free_table_management(cls_table);
+
+ return err;
+}
+
+static int table_init_exact_match(struct dpa_cls_table *cls_table)
+{
+ int err = 0;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!cls_table);
+ BUG_ON(cls_table->params.type != DPA_CLS_TBL_EXACT_MATCH);
+
+ err = alloc_table_management(cls_table);
+ if (err < 0)
+ return err;
+
+ /* First Cc node is the one that the user provided */
+ cls_table->int_cc_node[0].cc_node = cls_table->params.cc_node;
+ cls_table->int_cc_node[0].table_size =
+ cls_table->params.exact_match_params.entries_cnt;
+ cls_table->int_cc_node[0].used = cls_table->params.prefilled_entries;
+
+ /* Allocate the index management array */
+ cls_table->entries_cnt =
+ cls_table->params.exact_match_params.entries_cnt;
+ cls_table->entry =
+ kzalloc(cls_table->entries_cnt * sizeof(*cls_table->entry),
+ GFP_KERNEL);
+ if (!cls_table->entry) {
+ log_err("No more memory for DPA Classifier table index "
+ "management.\n");
+ cls_table->entries_cnt = 0;
+ err = -ENOMEM;
+ goto table_init_exact_match_error;
+ }
+ INIT_LIST_HEAD(&cls_table->entry_list);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+
+table_init_exact_match_error:
+ free_table_management(cls_table);
+
+ return err;
+}
+
+static void table_cleanup_indexed(struct dpa_cls_table *cls_table)
+{
+ struct dpa_cls_tbl_shadow_entry_indexed *shadow_entry_indexed;
+ int i;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!cls_table);
+ BUG_ON(cls_table->params.type != DPA_CLS_TBL_INDEXED);
+
+ for (i = 0; i < cls_table->params.indexed_params.entries_cnt; i++)
+ if (cls_table->entry[i].shadow_entry) {
+
+ shadow_entry_indexed =
+ list_entry(cls_table->entry[i].shadow_entry,
+ struct dpa_cls_tbl_shadow_entry_indexed,
+ list_node);
+
+ list_del(&shadow_entry_indexed->list_node);
+ kfree(shadow_entry_indexed);
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+}
+
+static int verify_table_params(const struct dpa_cls_tbl_params *params)
+{
+ int err = 0;
+ unsigned int num_sets;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!params);
+
+ switch (params->type) {
+ case DPA_CLS_TBL_EXACT_MATCH:
+ if (params->exact_match_params.entries_cnt >
+ FM_PCD_MAX_NUM_OF_KEYS) {
+ log_err("Specified number of entries (%d) for exact "
+ "match table exceeds the maximum capacity of "
+ "this type of table (%d).\n",
+ params->exact_match_params.entries_cnt,
+ FM_PCD_MAX_NUM_OF_KEYS);
+ err = -EINVAL;
+ break;
+ }
+
+ if (params->exact_match_params.key_size >
+ FM_PCD_MAX_SIZE_OF_KEY) {
+ log_err("DPA Classifier exact match table key size (%d "
+ "bytes) exceeds maximum (%d bytes).\n",
+ params->exact_match_params.key_size,
+ FM_PCD_MAX_SIZE_OF_KEY);
+ err = -EINVAL;
+ break;
+ }
+ break;
+ case DPA_CLS_TBL_HASH:
+ if (params->hash_params.num_sets > FM_PCD_MAX_NUM_OF_KEYS) {
+ log_err("DPA Classifier hash table number of sets (%d) "
+ "exceeds maximum (%d).\n",
+ params->hash_params.num_sets,
+ FM_PCD_MAX_NUM_OF_KEYS);
+ err = -EINVAL;
+ break;
+ }
+
+ /* Verify that the number of sets is a power of 2 */
+ num_sets = 0x02; /* 0b00000010 - the smallest acceptable
+ value */
+ while (num_sets < params->hash_params.num_sets)
+ num_sets <<= 1;
+ if (num_sets != params->hash_params.num_sets) {
+ log_err("DPA Classifier hash table number of sets (%d) "
+ "must be a power of 2.\n",
+ params->hash_params.num_sets);
+ err = -EINVAL;
+ break;
+ }
+
+ if (params->hash_params.max_ways > FM_PCD_MAX_NUM_OF_KEYS) {
+ log_err("DPA Classifier hash table number of ways (%d) "
+ "exceeds maximum (%d).\n",
+ params->hash_params.max_ways,
+ FM_PCD_MAX_NUM_OF_KEYS);
+ err = -EINVAL;
+ break;
+ }
+
+ if (params->hash_params.key_size > FM_PCD_MAX_SIZE_OF_KEY) {
+ log_err("DPA Classifier hash table key size (%d bytes) "
+ "exceeds maximum (%d bytes).\n",
+ params->hash_params.key_size,
+ FM_PCD_MAX_SIZE_OF_KEY);
+ err = -EINVAL;
+ break;
+ }
+ break;
+ case DPA_CLS_TBL_INDEXED:
+ if (params->indexed_params.entries_cnt >
+ FM_PCD_MAX_NUM_OF_KEYS) {
+ log_err("DPA Classifier indexed table size (%d "
+ "entries) exceeds maximum (%d entries).\n",
+ params->indexed_params.entries_cnt,
+ FM_PCD_MAX_NUM_OF_KEYS);
+ err = -EINVAL;
+ break;
+ }
+
+ if (params->indexed_params.entries_cnt == 0) {
+ log_err("Indexed table size zero is invalid.\n");
+ err = -EINVAL;
+ break;
+ }
+ break;
+ default:
+ log_err("Unsupported DPA Classifier table type (%d).\n",
+ params->type);
+ err = -EINVAL;
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+}
+
+static struct list_head *find_shadow_entry(const struct dpa_cls_table
+ *cls_table, const struct dpa_offload_lookup_key *key)
+{
+ uint8_t shadow_table_index;
+ struct dpa_cls_tbl_shadow_entry *entry;
+ bool found = false;
+ struct list_head *pos, *bucket_list;
+ struct dpa_cls_tbl_shadow_table *shadow_table;
+ uint8_t masked_key[DPA_OFFLD_MAXENTRYKEYSIZE];
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!cls_table);
+ BUG_ON(!key);
+ BUG_ON(!key->byte);
+ BUG_ON((key->size <= 0) ||
+ (key->size > DPA_OFFLD_MAXENTRYKEYSIZE));
+ BUG_ON(!cls_table->shadow_table);
+
+ shadow_table = cls_table->shadow_table;
+ if (cls_table->params.type == DPA_CLS_TBL_INDEXED) {
+ if (list_empty(&shadow_table->shadow_entry[key->byte[0]]))
+ return NULL;
+ else
+ return shadow_table->shadow_entry[key->byte[0]].next;
+ } else {
+ key_apply_mask(key, masked_key);
+ shadow_table_index = crc8(crc8_table, masked_key, key->size, 0);
+
+ bucket_list =
+ &shadow_table->shadow_entry[shadow_table_index];
+
+ if (list_empty(bucket_list))
+ return NULL;
+
+ /*
+ * Look into the HASH bucket to find the entry with the
+ * specified key
+ */
+ list_for_each(pos, bucket_list) {
+ entry = list_entry(pos, struct dpa_cls_tbl_shadow_entry,
+ list_node);
+ found = false;
+
+ if (entry->key.size != key->size)
+ break;
+
+ /* Verify if the key and mask are identical */
+ if (memcmp(entry->key.byte, key->byte, key->size) == 0) {
+ if (entry->key.mask) {
+ if ((key->mask) &&
+ (memcmp(entry->key.mask, key->mask,
+ key->size) == 0))
+ found = true;
+ } else
+ if (!key->mask)
+ found = true;
+ }
+
+ if (found)
+ break;
+ }
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ if (found)
+ return pos;
+
+ return NULL;
+}
+
+static int table_insert_entry_exact_match(struct dpa_cls_table *cls_table,
+ const struct dpa_offload_lookup_key *key,
+ const struct dpa_cls_tbl_action *action,
+ int priority,
+ int *entry_id)
+{
+ t_Error err;
+ int errno = 0;
+ struct dpa_cls_tbl_shadow_entry *shadow_entry = NULL;
+ t_FmPcdCcKeyParams key_params;
+ int i = 0;
+ int k, hmd;
+ uint8_t shadow_table_index;
+ uint8_t key_data[DPA_OFFLD_MAXENTRYKEYSIZE];
+ uint8_t mask_data[DPA_OFFLD_MAXENTRYKEYSIZE];
+ struct dpa_cls_tbl_shadow_table *shadow_table;
+ struct dpa_cls_tbl_entry *index_entry;
+ struct list_head *list_current;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!cls_table);
+ BUG_ON(!key);
+ BUG_ON(!action);
+ BUG_ON(cls_table->params.type != DPA_CLS_TBL_EXACT_MATCH);
+
+ if (key->size != cls_table->params.exact_match_params.key_size) {
+ log_err("Key size (%d) doesn't match table key size (%d).\n",
+ key->size,
+ cls_table->params.exact_match_params.key_size);
+ return -EINVAL;
+ }
+
+ if (cls_table->int_cc_node[0].used >=
+ cls_table->int_cc_node[0].table_size) {
+ /* No more space to add a new entry */
+ log_err("DPA Classifier exact match table is full. Unable to "
+ "add a new entry.\n");
+ return -ENOSPC;
+ }
+
+ memset(&key_params, 0, sizeof(t_FmPcdCcKeyParams));
+
+ /*
+ * Have to copy the data from the key and mask because the FMD is not
+ * using const pointers and we cannot provide it the const pointers that
+ * the user provided.
+ */
+ memcpy(key_data, key->byte, key->size);
+ key_params.p_Key = key_data;
+ if (key->mask) {
+ memcpy(mask_data, key->mask, key->size);
+ key_params.p_Mask = mask_data;
+ }
+
+ errno = action_to_next_engine_params(action,
+ &key_params.ccNextEngineParams,
+ &hmd,
+ (t_Handle)cls_table->params.distribution,
+ (t_Handle)cls_table->params.classification);
+ if (errno < 0)
+ return errno;
+
+ /* Find an empty index management entry */
+ for (k = 0; k < cls_table->entries_cnt; k++)
+ if (!(cls_table->entry[k].flags & DPA_CLS_TBL_ENTRY_VALID))
+ break;
+
+ BUG_ON(k == cls_table->entries_cnt);
+
+ /* Clean up and prepare the index entry */
+ memset(&cls_table->entry[k], 0,
+ sizeof(struct dpa_cls_tbl_entry));
+ cls_table->entry[k].priority = priority;
+ cls_table->entry[k].entry_index =
+ (uint8_t)cls_table->int_cc_node[0].used;
+ cls_table->entry[k].hmd = hmd;
+
+ /* Calculate the position in the index management list where this entry
+ * should go */
+ if (list_empty(&cls_table->entry_list))
+ /* List is empty. Just add to its tail. */
+ list_current = &cls_table->entry_list;
+ else {
+ if (cls_table->params.exact_match_params.use_priorities) {
+ /*
+ * Have to recalculate the position of this entry based
+ * on its priority.
+ */
+ /*
+ * Find the first entry with a priority value which is
+ * higher than or equal to the one to add
+ */
+ list_for_each_entry(index_entry,
+ &cls_table->entry_list,
+ list_node) {
+ if (index_entry->priority >= priority)
+ break;
+ }
+ /* If there are such entries in the list */
+ if (&index_entry->list_node != &cls_table->entry_list) {
+ /* We shall add this entry in the position of
+ * the [current] one */
+ cls_table->entry[k].entry_index =
+ index_entry->entry_index;
+ list_current = &index_entry->list_node;
+ } else
+ /*
+ * Otherwise let the entry be added at the end
+ * of the table
+ */
+ list_current = &cls_table->entry_list;
+ } else
+ /*
+ * If priorities are not used add the entry at the end
+ * of the table
+ */
+ list_current = &cls_table->entry_list;
+ }
+
+ /* Add the key to the selected Cc node */
+#ifdef DPA_CLASSIFIER_DEBUG
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d): Insert new entry in table "
+ "cc_node=0x%p.\n", __func__, __LINE__,
+ cls_table->int_cc_node[0].cc_node));
+ dpa_cls_dbg((" index=%d; action type (id)=%d; hmd=%d; h_Manip=0x%p\n",
+ cls_table->entry[k].entry_index, action->type, hmd,
+ key_params.ccNextEngineParams.h_Manip));
+ dpa_cls_dbg((" Lookup key (%d bytes): ",
+ cls_table->params.exact_match_params.key_size));
+ dump_lookup_key(key);
+ pr_err("\n");
+#endif /* DPA_CLASSIFIER_DEBUG */
+ err = FM_PCD_MatchTableAddKey((t_Handle)cls_table->
+ int_cc_node[0].cc_node,
+ cls_table->entry[k].entry_index,
+ cls_table->params.exact_match_params.key_size,
+ &key_params);
+ if (err != E_OK) {
+ log_err("FMan driver call failed - FM_PCD_MatchTableAddKey. "
+ "Entry ref=%d, Cc node handle=0x%p, entry index=%d.\n",
+ k, cls_table->int_cc_node[0].cc_node,
+ cls_table->entry[k].entry_index);
+ return -EBUSY;
+ }
+
+ /* Add the index entry to the index management list */
+ list_add_tail(&cls_table->entry[k].list_node, list_current);
+
+ cls_table->entry[k].flags |= DPA_CLS_TBL_ENTRY_VALID;
+
+ /* Increment all entry indexes in the current cc node starting from
+ * [current] on */
+ while (list_current != &cls_table->entry_list) {
+ index_entry = list_entry(list_current,
+ struct dpa_cls_tbl_entry,
+ list_node);
+ if (index_entry->int_cc_node_index != i)
+ break;
+
+ index_entry->entry_index++;
+
+ list_current = list_current->next;
+ }
+
+ cls_table->int_cc_node[0].used++;
+
+ /* If shadow table exists, add the entry to it */
+ if (cls_table->shadow_table) {
+ shadow_entry = kzalloc(sizeof(*shadow_entry), GFP_KERNEL);
+ if (!shadow_entry) {
+ log_err("Out of memory while populating shadow "
+ "table.\n");
+ return -ENOMEM;
+ }
+
+ memcpy(&shadow_entry->action, action,
+ sizeof(struct dpa_cls_tbl_action));
+ shadow_entry->key.byte = kzalloc(key->size, GFP_KERNEL);
+ if (!shadow_entry->key.byte) {
+ log_err("Out of memory while populating shadow "
+ "table.\n");
+ kfree(shadow_entry);
+ return -ENOMEM;
+ }
+ memcpy(shadow_entry->key.byte, key->byte, key->size);
+ if (key->mask) {
+ shadow_entry->key.mask = kzalloc(key->size, GFP_KERNEL);
+ if (!shadow_entry->key.mask) {
+ log_err("Out of memory while populating shadow "
+ "table.\n");
+ kfree(shadow_entry->key.byte);
+ kfree(shadow_entry);
+ return -ENOMEM;
+ }
+ memcpy(shadow_entry->key.mask, key->mask, key->size);
+ }
+ shadow_entry->key.size = key->size;
+
+ /* Connect index management entry with the shadow table entry */
+ shadow_entry->entry_id = k;
+ cls_table->entry[k].shadow_entry = &shadow_entry->list_node;
+
+ /* Add entry to the proper shadow table. */
+ key_apply_mask(key, key_data);
+ shadow_table_index = crc8(crc8_table,
+ key_data,
+ cls_table->params.exact_match_params.key_size,
+ 0);
+ shadow_table = cls_table->shadow_table;
+ list_add_tail(&shadow_entry->list_node,
+ &shadow_table->shadow_entry[shadow_table_index]);
+ }
+
+ if (entry_id)
+ *entry_id = k;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return 0;
+}
+
+static int table_insert_entry_hash(struct dpa_cls_table *cls_table,
+ const struct dpa_offload_lookup_key *key,
+ const struct dpa_cls_tbl_action *action,
+ int *entry_id)
+{
+ t_Error err;
+ int errno = 0;
+ struct dpa_cls_tbl_shadow_entry *shadow_entry = NULL;
+ t_FmPcdCcKeyParams key_params;
+ uint8_t shadow_table_index;
+ u64 hash_set_index;
+ uint8_t key_data[DPA_OFFLD_MAXENTRYKEYSIZE];
+ int j, hmd;
+ struct dpa_cls_tbl_shadow_table *shadow_table;
+ struct list_head *list_current;
+ struct dpa_cls_tbl_entry *index_entry;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!cls_table);
+ BUG_ON(!key);
+ BUG_ON(!action);
+ BUG_ON(cls_table->params.type != DPA_CLS_TBL_HASH);
+
+ if (key->size != cls_table->params.hash_params.key_size) {
+ log_err("Key size (%d bytes) doesn't match table key size (%d "
+ "bytes).\n", key->size,
+ cls_table->params.hash_params.key_size);
+ return -EINVAL;
+ }
+
+ if (key->mask) {
+ /* Only full 0xFF masks supported: */
+ for (j = 0; j < key->size; j++)
+ if (key->mask[j] ^ 0xff) {
+ log_err("Only key masks 0xff all over are supported by HASH tables.\n");
+ return -EINVAL;
+ }
+ }
+
+ memset(&key_params, 0, sizeof(t_FmPcdCcKeyParams));
+
+ /*
+ * Have to copy the data from the key because the FMD is not
+ * using const pointers and we cannot provide it the const pointers that
+ * the user provided.
+ */
+ memcpy(key_data, key->byte, key->size);
+ key_params.p_Key = key_data;
+
+ if (cls_table->params.prefilled_entries) {
+ errno = action_to_next_engine_params(action,
+ &key_params.ccNextEngineParams,
+ NULL,
+ (t_Handle)cls_table->params.
+ distribution,
+ (t_Handle)cls_table->params.
+ classification);
+ if (errno < 0)
+ return errno;
+
+ /*
+ * If pre-filled entries exist, fall through to the low level
+ * driver only
+ */
+ err = FM_PCD_HashTableAddKey(
+ (t_Handle)cls_table->params.cc_node,
+ cls_table->params.hash_params.key_size,
+ &key_params);
+ if (err != E_OK) {
+ log_err("FMan driver call failed - "
+ "FM_PCD_HashTableAddKey. HASH table "
+ "handle=0x%p.\n", cls_table->params.cc_node);
+ return -EBUSY;
+ }
+
+ return 0;
+ }
+
+ errno = action_to_next_engine_params(action,
+ &key_params.ccNextEngineParams,
+ &hmd,
+ (t_Handle)cls_table->params.distribution,
+ (t_Handle)cls_table->params.classification);
+ if (errno < 0)
+ return errno;
+
+ hash_set_index = crc64_ecma_seed();
+ hash_set_index = crc64_ecma(key_data,
+ cls_table->params.hash_params.key_size,
+ hash_set_index);
+ hash_set_index = (u64)(hash_set_index & cls_table->hash_mask) >>
+ (8 * (6 - cls_table->params.hash_params.hash_offs) + 4);
+
+ BUG_ON(hash_set_index >= cls_table->int_cc_nodes_count);
+
+ /* Check if there are entries still available in the selected set */
+ if (cls_table->int_cc_node[hash_set_index].used >=
+ cls_table->int_cc_node[hash_set_index].table_size) {
+ log_err("Hash set #%llu is full (%d entries). Unable to add "
+ "this entry.\n", hash_set_index,
+ cls_table->int_cc_node[hash_set_index].table_size);
+ return -ENOSPC;
+ }
+
+ /* Find an empty index entry */
+ for (j = 0; j < cls_table->entries_cnt; j++)
+ if (!(cls_table->entry[j].flags & DPA_CLS_TBL_ENTRY_VALID))
+ break;
+
+ BUG_ON(j == cls_table->entries_cnt);
+
+ /* Clean up and prepare the index entry */
+ memset(&cls_table->entry[j], 0,
+ sizeof(struct dpa_cls_tbl_entry));
+ cls_table->entry[j].flags |= DPA_CLS_TBL_ENTRY_VALID;
+ cls_table->entry[j].int_cc_node_index = (unsigned int)hash_set_index;
+ cls_table->entry[j].entry_index =
+ (uint8_t)cls_table->int_cc_node[hash_set_index].used;
+ cls_table->entry[j].hmd = hmd;
+
+ /* Calculate the position in the index management list where this entry
+ * should go */
+ if ((list_empty(&cls_table->entry_list)) ||
+ (hash_set_index >= cls_table->int_cc_nodes_count - 1))
+ /* Just add to the tail of the list. */
+ list_current = &cls_table->entry_list;
+ else {
+ /* Sort the index management list based on [cc_node_index] and
+ * [entry_index]. In other words, add the current entry
+ * before the first entry of the next cc node */
+ list_for_each(list_current, &cls_table->entry_list) {
+ index_entry = list_entry(list_current,
+ struct dpa_cls_tbl_entry,
+ list_node);
+ if (index_entry->int_cc_node_index > hash_set_index)
+ break;
+ }
+ }
+
+ /* Add the key to the selected Cc node */
+ err = FM_PCD_MatchTableAddKey((t_Handle)cls_table->
+ int_cc_node[hash_set_index].cc_node,
+ cls_table->entry[j].entry_index,
+ cls_table->params.hash_params.key_size,
+ &key_params);
+ if (err != E_OK) {
+ log_err("FMan driver call failed - FM_PCD_MatchTableAddKey. "
+ "Entry ref=%d, HASH set=%llu, Cc node handle=0x%p, "
+ "entry index=%d.\n", j, hash_set_index,
+ cls_table->int_cc_node[hash_set_index].cc_node,
+ cls_table->entry[j].entry_index);
+ return -EBUSY;
+ }
+
+ /* Add the index entry to the index management list */
+ list_add_tail(&cls_table->entry[j].list_node, list_current);
+
+ cls_table->int_cc_node[hash_set_index].used++;
+
+ /* If shadow tables exist, add the entry to them */
+ if (cls_table->shadow_table) {
+ shadow_entry = kzalloc(sizeof(*shadow_entry), GFP_KERNEL);
+ if (!shadow_entry) {
+ log_err("Out of memory while populating shadow "
+ "table.\n");
+ return -ENOMEM;
+ }
+
+ memcpy(&shadow_entry->action, action,
+ sizeof(struct dpa_cls_tbl_action));
+ shadow_entry->key.byte = kzalloc(key->size, GFP_KERNEL);
+ if (!shadow_entry->key.byte) {
+ log_err("Out of memory while populating shadow table "
+ "entry.\n");
+ kfree(shadow_entry);
+ return -ENOMEM;
+ }
+ memcpy(shadow_entry->key.byte, key->byte, key->size);
+ shadow_entry->key.size = key->size;
+
+ /* Connect index management entry with the shadow table entry */
+ shadow_entry->entry_id = j;
+ cls_table->entry[j].shadow_entry = &shadow_entry->list_node;
+
+ /* Add entry to the proper shadow table. */
+ shadow_table_index = crc8(crc8_table,
+ key_data,
+ cls_table->params.hash_params.key_size,
+ 0);
+ shadow_table = cls_table->shadow_table;
+ list_add_tail(&shadow_entry->list_node,
+ &shadow_table->shadow_entry[shadow_table_index]);
+ }
+
+ if (entry_id)
+ *entry_id = j;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return 0;
+}
+
+static int action_to_next_engine_params(const struct dpa_cls_tbl_action *action,
+ t_FmPcdCcNextEngineParams *next_engine_params,
+ int *hmd,
+ t_Handle distribution,
+ t_Handle classification)
+{
+ struct dpa_cls_table *next_table;
+#if (DPAA_VERSION >= 11)
+ struct dpa_cls_mcast_group *pgroup;
+#endif
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!action);
+ BUG_ON(!next_engine_params);
+
+ memset(next_engine_params, 0, sizeof(t_FmPcdCcNextEngineParams));
+
+ if (hmd)
+ *hmd = DPA_OFFLD_DESC_NONE;
+
+ switch (action->type) {
+ case DPA_CLS_TBL_ACTION_DROP:
+ next_engine_params->nextEngine = e_FM_PCD_DONE;
+ next_engine_params->params.enqueueParams.action =
+ e_FM_PCD_DROP_FRAME;
+ break;
+ case DPA_CLS_TBL_ACTION_ENQ:
+ if (distribution && classification) {
+ t_FmPcdKgSchemeParams *scheme_params =
+ kzalloc(sizeof(t_FmPcdKgSchemeParams),
+ GFP_KERNEL);
+ if (!scheme_params) {
+ log_err("Failed to alocate direct scheme "
+ "params.\n");
+ return -ENOMEM;
+ }
+ memset(scheme_params, 0, sizeof(*scheme_params));
+ scheme_params->modify = true;
+ scheme_params->alwaysDirect = true;
+#if (DPAA_VERSION >= 11)
+ scheme_params->bypassFqidGeneration = true;
+#else
+ scheme_params->bypassFqidGeneration = false;
+#endif
+ scheme_params->id.h_Scheme = distribution;
+ scheme_params->nextEngine = e_FM_PCD_CC;
+ scheme_params->kgNextEngineParams.cc.h_CcTree =
+ classification;
+ scheme_params->kgNextEngineParams.cc.grpId = 0;
+ scheme_params->keyExtractAndHashParams.
+ hashDistributionNumOfFqids = 1;
+
+ distribution = FM_PCD_KgSchemeSet(
+ ((t_FmPcdCcTree *)classification)->h_FmPcd,
+ scheme_params);
+ kfree(scheme_params);
+ if (!distribution) {
+ log_err("Failed to set direct scheme.\n");
+ return -EINVAL;
+ }
+
+ /* Redirect frames to KeyGen direct scheme */
+ next_engine_params->nextEngine = e_FM_PCD_KG;
+ next_engine_params->params.kgParams.h_DirectScheme =
+ distribution;
+ next_engine_params->params.kgParams.newFqid =
+ action->enq_params.new_fqid;
+ if (action->enq_params.override_fqid)
+ next_engine_params->params.kgParams.
+ overrideFqid = TRUE;
+ } else {
+ if (action->enq_params.policer_params != NULL) {
+ next_engine_params->nextEngine = e_FM_PCD_PLCR;
+ next_engine_params->params.plcrParams.
+ sharedProfile = action->enq_params.
+ policer_params->shared_profile;
+ next_engine_params->params.plcrParams.
+ newRelativeProfileId = (uint16_t)action->enq_params.
+ policer_params->new_rel_profile_id;
+ next_engine_params->params.plcrParams.
+ overrideParams = action->enq_params.
+ policer_params->modify_policer_params;
+ next_engine_params->params.plcrParams.
+ newFqid = action->enq_params.new_fqid;
+ } else {
+ next_engine_params->nextEngine = e_FM_PCD_DONE;
+ next_engine_params->params.enqueueParams.
+ action = e_FM_PCD_ENQ_FRAME;
+ next_engine_params->params.enqueueParams.
+ newFqid = action->enq_params.new_fqid;
+ if (action->enq_params.override_fqid)
+ next_engine_params->params.
+ enqueueParams.overrideFqid =
+ TRUE;
+#if (DPAA_VERSION >= 11)
+ next_engine_params->params.enqueueParams.
+ newRelativeStorageProfileId =
+ action->enq_params.new_rel_vsp_id;
+#endif
+ }
+ }
+
+ if (action->enq_params.hmd != DPA_OFFLD_DESC_NONE) {
+ if (!hmd) {
+ log_err("Header manipulations are not allowed "
+ "on this action.\n");
+ return -EINVAL;
+ }
+ if (!dpa_classif_hm_is_chain_head(
+ action->enq_params.hmd)) {
+ log_err("hmd=%d is not a header manipulation "
+ "chain head. Only chain heads can be "
+ "attached to table entries.\n",
+ action->enq_params.hmd);
+ return -EINVAL;
+ }
+ next_engine_params->h_Manip = (t_Handle)
+ dpa_classif_hm_lock_chain(action->enq_params.hmd);
+ if (!next_engine_params->h_Manip) {
+ log_err("Failed to attach HM op hmd=%d to "
+ "classification entry.\n",
+ action->enq_params.hmd);
+ return -EINVAL;
+ }
+
+ *hmd = action->enq_params.hmd;
+ } else
+ next_engine_params->h_Manip = NULL;
+
+ break;
+ case DPA_CLS_TBL_ACTION_NEXT_TABLE:
+ if ((action->next_table_params.next_td >=
+ table_array.num_descriptors) ||
+ (!table_array.object[action->next_table_params.
+ next_td])) {
+ log_err("Invalid next table descriptor "
+ "(next_td=%d).\n",
+ (unsigned)action->next_table_params.next_td);
+ return -EINVAL;
+ }
+
+ if (action->next_table_params.hmd != DPA_OFFLD_DESC_NONE) {
+ if (!hmd) {
+ log_err("Header manipulations are not allowed on "
+ "this action.\n");
+ return -EINVAL;
+ }
+ if (!dpa_classif_hm_is_chain_head(
+ action->next_table_params.hmd)) {
+ log_err("hmd=%d is not a header manipulation "
+ "chain head. Only chain heads can be "
+ "used by the classifier table.\n",
+ action->next_table_params.hmd);
+ return -EINVAL;
+ }
+ next_engine_params->h_Manip = (t_Handle)
+ dpa_classif_hm_lock_chain(action->next_table_params.hmd);
+ if (!next_engine_params->h_Manip) {
+ log_err("Failed to attach HM op hmd=%d to "
+ "classification entry.",
+ action->next_table_params.hmd);
+ return -EINVAL;
+ }
+
+ *hmd = action->next_table_params.hmd;
+ } else
+ next_engine_params->h_Manip = NULL;
+
+ next_engine_params->nextEngine = e_FM_PCD_CC;
+ next_table = (struct dpa_cls_table *)
+ table_array.object[action->next_table_params.next_td];
+ next_engine_params->params.ccParams.h_CcNode =
+ (t_Handle)next_table->params.cc_node;
+
+ break;
+#if (DPAA_VERSION >= 11)
+ case DPA_CLS_TBL_ACTION_MCAST:
+ if (action->mcast_params.hmd != DPA_OFFLD_DESC_NONE) {
+ if (!hmd) {
+ log_err("Header manipulations are not allowed "
+ "on this action.\n");
+ return -EINVAL;
+ }
+ next_engine_params->h_Manip = (t_Handle)
+ dpa_classif_hm_lock_chain(action->enq_params.hmd);
+ if (!next_engine_params->h_Manip) {
+ log_err("Failed to attach HM op hmd=%d to "
+ "classification entry.\n",
+ action->enq_params.hmd);
+ return -EINVAL;
+ }
+
+ *hmd = action->enq_params.hmd;
+ } else
+ next_engine_params->h_Manip = NULL;
+ next_engine_params->nextEngine = e_FM_PCD_FR;
+ pgroup = desc_to_object(&mcast_grp_array,
+ action->mcast_params.grpd);
+ if (!pgroup) {
+ log_err("No such group (grpd=%d).\n",
+ action->mcast_params.grpd);
+ return -EINVAL;
+ }
+
+ next_engine_params->params.frParams.h_FrmReplic = pgroup->group;
+ break;
+#endif
+ default:
+ log_err("Unsupported DPA Classifier action type (%d).\n",
+ action->type);
+ return -EINVAL;
+ }
+
+ if (action->enable_statistics)
+ next_engine_params->statisticsEn = TRUE;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return 0;
+}
+
+static int next_engine_params_to_action(const t_FmPcdCcNextEngineParams
+ *next_engine_params, struct dpa_cls_tbl_action *action)
+{
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!action);
+ BUG_ON(!next_engine_params);
+
+ if (next_engine_params->statisticsEn == TRUE)
+ action->enable_statistics = true;
+
+ switch (next_engine_params->nextEngine) {
+ case e_FM_PCD_DONE:
+ switch (next_engine_params->params.enqueueParams.action) {
+ case e_FM_PCD_ENQ_FRAME:
+ action->type = DPA_CLS_TBL_ACTION_ENQ;
+ action->enq_params.hmd = DPA_OFFLD_DESC_NONE;
+ action->enq_params.new_fqid =
+ next_engine_params->params.enqueueParams.newFqid;
+ if (next_engine_params->params.enqueueParams.overrideFqid ==
+ TRUE)
+ action->enq_params.override_fqid = true;
+ action->enq_params.policer_params = NULL;
+ break;
+ case e_FM_PCD_DROP_FRAME:
+ action->type = DPA_CLS_TBL_ACTION_DROP;
+ break;
+ default:
+ log_warn("DPA Classifier does not directly support "
+ "this type of e_FM_PCD_DONE action (%d).\n",
+ next_engine_params->params.
+ enqueueParams.action);
+ action->type = DPA_CLS_TBL_ACTION_NONE;
+ break;
+ }
+ break;
+ case e_FM_PCD_PLCR:
+ action->type = DPA_CLS_TBL_ACTION_ENQ;
+ action->enq_params.new_fqid =
+ next_engine_params->params.plcrParams.newFqid;
+ action->enq_params.override_fqid = true;
+ action->enq_params.hmd = DPA_OFFLD_DESC_NONE;
+ if (next_engine_params->params.plcrParams.overrideParams ==
+ TRUE)
+ action->enq_params.policer_params->
+ modify_policer_params = true;
+ action->enq_params.policer_params->new_rel_profile_id =
+ next_engine_params->params.plcrParams.
+ newRelativeProfileId;
+ if (next_engine_params->params.plcrParams.sharedProfile ==
+ TRUE)
+ action->enq_params.policer_params->shared_profile =
+ next_engine_params->params.plcrParams.
+ sharedProfile;
+ break;
+ case e_FM_PCD_CC:
+ case e_FM_PCD_HASH:
+ action->type = DPA_CLS_TBL_ACTION_NEXT_TABLE;
+ action->next_table_params.next_td =
+ handle_to_td(next_engine_params->params.ccParams.
+ h_CcNode);
+ break;
+ default:
+ log_warn("DPA Classifier does not directly support "
+ "this type of NextEngine parameters (%d).\n",
+ next_engine_params->nextEngine);
+ action->type = DPA_CLS_TBL_ACTION_NONE;
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return 0;
+}
+
+static int key_to_entry_id(const struct dpa_cls_table *cls_table,
+ const struct dpa_offload_lookup_key *key)
+{
+ struct dpa_cls_tbl_shadow_entry *shadow_entry;
+ struct list_head *shadow_list_entry;
+
+ if (cls_table->params.type == DPA_CLS_TBL_INDEXED) {
+ if (key->size != 1) {
+ log_err("Bad key format for index table. Key size must "
+ "be 1.\n");
+ return -EINVAL;
+ }
+ return (int)key->byte[0];
+ }
+
+ if ((cls_table->params.type == DPA_CLS_TBL_HASH) &&
+ (cls_table->params.prefilled_entries))
+ /* Cannot lookup in a prefilled HASH table */
+ return -ENODEV;
+
+ if (!cls_table->shadow_table) {
+ log_err("No shadow table.\n");
+ return -ENOSYS;
+ }
+
+ /* Find the shadow entry associated with this key */
+ shadow_list_entry = find_shadow_entry(cls_table, key);
+ if (shadow_list_entry == NULL)
+ return -ENODEV;
+
+ shadow_entry = list_entry(shadow_list_entry,
+ struct dpa_cls_tbl_shadow_entry,
+ list_node);
+
+ return shadow_entry->entry_id;
+}
+
+static int handle_to_td(void *cc_node)
+{
+ int i;
+ struct dpa_cls_table *table;
+
+ for (i = 0; i < table_array.num_descriptors; i++) {
+ if (table_array.object[i]) {
+ table = (struct dpa_cls_table *) table_array.object[i];
+ if ((unsigned long)table->params.cc_node ==
+ (unsigned long)cc_node)
+ break;
+ }
+ }
+
+ if (i < table_array.num_descriptors)
+ return i;
+ else
+ /* No matching classification table found */
+ return DPA_OFFLD_DESC_NONE;
+}
+
+static int extend_descriptor_table(struct dpa_cls_descriptor_table *desc_table)
+{
+ unsigned int new_table_size = 0;
+ void **new_objects_array;
+
+ if (desc_table->object)
+ new_table_size = desc_table->num_descriptors;
+
+ new_table_size += DPA_CLS_ARRAYSIZEGRANULARITY;
+
+ new_objects_array = kzalloc(new_table_size * sizeof(void *),
+ GFP_KERNEL);
+ if (!new_objects_array) {
+ log_err("No more memory for DPA Classifier descriptor "
+ "table.\n");
+ return -ENOMEM;
+ }
+
+ if (desc_table->num_descriptors)
+ /*
+ * Transfer pointers to existing objects into the new
+ * descriptor array
+ */
+ memcpy(new_objects_array, desc_table->object,
+ desc_table->num_descriptors * sizeof(void *));
+
+ kfree(desc_table->object);
+
+ desc_table->object = new_objects_array;
+ desc_table->num_descriptors = new_table_size;
+
+ return 0;
+}
+
+static int get_descriptor(struct dpa_cls_descriptor_table *desc_table,
+ void *object, int *desc)
+{
+ int i;
+
+ if (desc_table->used_descriptors >= desc_table->num_descriptors)
+ return -ENOSPC;
+
+ for (i = 0; i < desc_table->num_descriptors; i++)
+ if (desc_table->object[i] == NULL) {
+ desc_table->object[i] = object;
+ *desc = i;
+ break;
+ }
+
+ desc_table->used_descriptors++;
+
+ return 0;
+}
+
+static int acquire_descriptor(struct dpa_cls_descriptor_table *desc_table,
+ void *object, int *desc)
+{
+ int err;
+
+ BUG_ON(!desc_table);
+ BUG_ON(!object);
+ BUG_ON(!desc);
+
+ if (get_descriptor(desc_table, object, desc) < 0) {
+ err = extend_descriptor_table(desc_table);
+ if (err < 0)
+ return err;
+
+ /*
+ * If extending the table was successful it is impossible for
+ * the following function to fail
+ */
+ get_descriptor(desc_table, object, desc);
+ }
+
+ return 0;
+}
+
+static inline void put_descriptor(struct dpa_cls_descriptor_table *desc_table,
+ int desc)
+{
+ BUG_ON(!desc_table);
+
+ if (desc_table->object[desc] != NULL) {
+ if (--desc_table->used_descriptors == 0) {
+ kfree(desc_table->object);
+ desc_table->object = NULL;
+ desc_table->num_descriptors = 0;
+ } else
+ desc_table->object[desc] = NULL;
+ }
+}
+
+static inline void lock_desc_table(struct dpa_cls_descriptor_table
+ *desc_table)
+{
+ mutex_lock(desc_table->access);
+}
+
+static inline void release_desc_table(struct dpa_cls_descriptor_table
+ *desc_table)
+{
+ mutex_unlock(desc_table->access);
+}
+
+static void *desc_to_object(struct dpa_cls_descriptor_table *desc_table,
+ int desc)
+{
+ BUG_ON(!desc_table);
+
+ if ((desc >= 0) && (desc < desc_table->num_descriptors))
+ return desc_table->object[desc];
+ else
+ return NULL;
+}
+
+static inline void key_apply_mask(const struct dpa_offload_lookup_key *key,
+ uint8_t *new_key)
+{
+ int i;
+
+ BUG_ON(!new_key);
+ BUG_ON(!key);
+ BUG_ON(!key->byte);
+
+ if (key->mask == NULL) {
+ memcpy(new_key, key->byte, key->size);
+ return;
+ }
+
+ memset(new_key, 0, key->size);
+ for (i = 0; i < key->size; i++)
+ new_key[i] = key->byte[i] & key->mask[i];
+}
+
+int dpa_classif_get_miss_action(int td, struct dpa_cls_tbl_action *miss_action)
+{
+ struct dpa_cls_table *ptable;
+
+ if (!miss_action)
+ return -EINVAL;
+
+ LOCK_OBJECT(table_array, td, ptable, -EINVAL);
+ if (ptable->miss_action.type == DPA_CLS_TBL_ACTION_NONE) {
+ /* No miss action was specified for this table */
+ RELEASE_OBJECT(ptable);
+ return -ENODEV;
+ } else
+ memcpy(miss_action, &ptable->miss_action, sizeof(*miss_action));
+
+ RELEASE_OBJECT(ptable);
+
+ return 0;
+}
+
+static int nat_hm_check_params(const struct dpa_cls_hm_nat_params *nat_params)
+{
+ unsigned int ip_ver = 0;
+
+ BUG_ON(!nat_params);
+
+ /* Check that all IP address versions are the same: */
+ if (nat_params->type == DPA_CLS_HM_NAT_TYPE_TRADITIONAL) {
+
+ if (nat_params->flags & DPA_CLS_HM_NAT_UPDATE_SIP)
+ ip_ver = nat_params->nat.sip.version;
+ if (nat_params->flags & DPA_CLS_HM_NAT_UPDATE_DIP) {
+ if ((ip_ver) &&
+ (ip_ver != nat_params->nat.dip.version)) {
+ log_err("Inconsistent SIP DIP address "
+ "versions.\n");
+ return -EINVAL;
+ }
+ ip_ver = nat_params->nat.dip.version;
+ }
+
+ if ((ip_ver) && (ip_ver != 4) && (ip_ver != 6)) {
+ log_err("Unsupported IP version (%d). Only IPv4 and "
+ "IPv6 are supported\n", ip_ver);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static int fwd_hm_check_params(const struct dpa_cls_hm_fwd_params *fwd_params)
+{
+ BUG_ON(!fwd_params);
+
+ if (fwd_params->out_if_type == DPA_CLS_HM_IF_TYPE_PPPoE) {
+ log_err("Forwarding HM: PPPoE output interface not supported "
+ "yet.\n");
+ return -ENOSYS;
+ }
+
+ if (fwd_params->ip_frag_params.mtu != 0) {
+ log_err("Forwarding HM: IP fragmentation is not supported "
+ "yet.\n");
+ return -ENOSYS;
+ }
+
+ return 0;
+}
+
+static int remove_hm_check_params(const struct dpa_cls_hm_remove_params
+ *remove_params)
+{
+ BUG_ON(!remove_params);
+
+ switch (remove_params->type) {
+ case DPA_CLS_HM_REMOVE_PPPoE:
+ log_err("Unsupported HM: remove PPPoE.\n");
+ return -ENOSYS;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int insert_hm_check_params(const struct dpa_cls_hm_insert_params
+ *insert_params)
+{
+ BUG_ON(!insert_params);
+
+ switch (insert_params->type) {
+ case DPA_CLS_HM_INSERT_PPPoE:
+ log_err("Unsupported HM: insert PPPoE.\n");
+ return -ENOSYS;
+ break;
+ case DPA_CLS_HM_INSERT_ETHERNET:
+ if (insert_params->eth.num_tags >
+ DPA_CLS_HM_MAX_VLANs) {
+ log_err("Insert HM: Can only insert a maximum of %d "
+ "VLAN tags.\n", DPA_CLS_HM_MAX_VLANs);
+ return -EINVAL;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int update_hm_check_params(const struct dpa_cls_hm_update_params
+ *update_params)
+{
+ const int update_ops_mask = DPA_CLS_HM_UPDATE_IPv4_UPDATE |
+ DPA_CLS_HM_UPDATE_IPv6_UPDATE |
+ DPA_CLS_HM_UPDATE_UDP_TCP_UPDATE;
+ const int replace_ops_mask = DPA_CLS_HM_REPLACE_IPv4_BY_IPv6 |
+ DPA_CLS_HM_REPLACE_IPv6_BY_IPv4;
+ int ops;
+
+ BUG_ON(!update_params);
+
+ if ((update_params->op_flags == DPA_CLS_HM_UPDATE_NONE) &&
+ (update_params->ip_frag_params.mtu == 0)) {
+ log_err("Cannot create an empty update HM.\n");
+ return -EINVAL;
+ }
+
+ ops = update_params->op_flags & update_ops_mask;
+ if (ops) {
+ while ((ops & 0x1) == 0)
+ ops >>= 1;
+ if (ops > 1) {
+ log_err("Only one UPDATE operation is allowed.\n");
+ return -EINVAL;
+ }
+
+ if (update_params->op_flags & DPA_CLS_HM_UPDATE_IPv4_UPDATE) {
+ if ((update_params->update.l3.field_flags &
+ DPA_CLS_HM_IP_UPDATE_IPSA) &&
+ (update_params->update.l3.ipsa.version != 4)) {
+ log_err("Only IPv4 addresses are accepted for "
+ "IPv4 IPSA update.\n");
+ return -EINVAL;
+ }
+
+ if ((update_params->update.l3.field_flags &
+ DPA_CLS_HM_IP_UPDATE_IPDA) &&
+ (update_params->update.l3.ipda.version != 4)) {
+ log_err("Only IPv4 addresses are accepted for "
+ "IPv4 IPDA update.\n");
+ return -EINVAL;
+ }
+ }
+
+ if (update_params->op_flags & DPA_CLS_HM_UPDATE_IPv6_UPDATE) {
+ if ((update_params->update.l3.field_flags &
+ DPA_CLS_HM_IP_UPDATE_IPSA) &&
+ (update_params->update.l3.ipsa.version != 6)) {
+ log_err("Only IPv6 addresses are accepted for "
+ "IPv6 IPSA update.\n");
+ return -EINVAL;
+ }
+
+ if ((update_params->update.l3.field_flags &
+ DPA_CLS_HM_IP_UPDATE_IPDA) &&
+ (update_params->update.l3.ipda.version != 6)) {
+ log_err("Only IPv6 addresses are accepted for "
+ "IPv6 IPDA update.\n");
+ return -EINVAL;
+ }
+ }
+ }
+
+ ops = update_params->op_flags & replace_ops_mask;
+ if (ops) {
+ while ((ops & 0x1) == 0)
+ ops >>= 1;
+ if (ops > 1) {
+ log_err("Only one REPLACE operation is allowed.\n");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static int
+ vlan_hm_check_params(const struct dpa_cls_hm_vlan_params *vlan_params)
+{
+ BUG_ON(!vlan_params);
+
+ switch (vlan_params->type) {
+ case DPA_CLS_HM_VLAN_INGRESS:
+ if (vlan_params->ingress.num_tags !=
+ DPA_CLS_HM_VLAN_CNT_ALL_QTAGS) {
+ log_err("Ingress VLAN QTags remove HM: Only \"remove "
+ "all QTags\" is currenly supported.\n");
+ return -EINVAL;
+ }
+ break;
+ case DPA_CLS_HM_VLAN_EGRESS:
+ if (vlan_params->egress.num_tags >
+ DPA_CLS_HM_MAX_VLANs) {
+ log_err("Egress VLAN HM: Can only insert a maximum of "
+ "%d VLANs.\n", DPA_CLS_HM_MAX_VLANs);
+ return -EINVAL;
+ }
+ break;
+ default:
+ log_err("Invalid VLAN specific HM type (%d).\n",
+ vlan_params->type);
+ return -EINVAL;
+ break;
+ }
+
+ return 0;
+}
+
+static int
+ mpls_hm_check_params(const struct dpa_cls_hm_mpls_params *mpls_params)
+{
+ BUG_ON(!mpls_params);
+
+ if ((mpls_params->type == DPA_CLS_HM_MPLS_INSERT_LABELS) &&
+ (mpls_params->num_labels > DPA_CLS_HM_MAX_MPLS_LABELS)) {
+ log_err("MPLS HM: Can only insert a maximum of %d MPLS "
+ "labels.\n", DPA_CLS_HM_MAX_MPLS_LABELS);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int import_hm_nodes_to_chain(void * const *node_array,
+ unsigned int num_nodes, struct dpa_cls_hm *hm)
+{
+ struct dpa_cls_hm_node *hm_node;
+ int i;
+ bool found;
+
+ if (!num_nodes)
+ /* Nothing to do */
+ return 0;
+
+ BUG_ON(!node_array);
+ BUG_ON(!hm);
+
+ /* This HM operation is linked to another HM op */
+ for (i = num_nodes - 1; i >= 0; i--) {
+ /*
+ * If the node is empty, save an empty space and skip
+ * to the next
+ */
+ if (!node_array[i]) {
+ hm->hm_node[i] = NULL;
+ continue;
+ }
+
+ /* Check if this node is already in the chain */
+ found = false;
+ if (!list_empty(&hm->list_node)) {
+ list_for_each_entry(hm_node, hm->hm_chain, list_node) {
+ if ((unsigned long)hm_node->node ==
+ (unsigned long)node_array[i]) {
+ /*
+ * This node already exists in the chain
+ */
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (found)
+ /*
+ * This node already exists in the chain hence
+ * point to the existing node
+ */
+ hm->hm_node[i] = hm_node;
+ else {
+ /* Node does not exist, we need to create it */
+ hm->hm_node[i] = kzalloc(sizeof(struct dpa_cls_hm_node),
+ GFP_KERNEL);
+ if (!hm->hm_node[i]) {
+ log_err("Not enough memory for HM node "
+ "management.\n");
+ return -ENOMEM;
+ }
+
+ /* Fill in the node */
+ hm->hm_node[i]->node = node_array[i];
+ INIT_LIST_HEAD(&hm->hm_node[i]->list_node);
+
+ /* Add this new node to the HM chain: */
+ list_add(&hm->hm_node[i]->list_node,
+ hm->hm_chain);
+ }
+ }
+
+ return 0;
+}
+
+static int add_local_hm_nodes_to_chain(struct dpa_cls_hm *phm)
+{
+ int i;
+
+ BUG_ON(!phm);
+
+ for (i = phm->num_nodes - 1; i >= 0; i--)
+ /*
+ * If the node exists and it is not already integrated in a HM
+ * chain...
+ */
+ if ((phm->hm_node[i]) &&
+ (list_empty(&phm->hm_node[i]->list_node)))
+ list_add(&phm->hm_node[i]->list_node, phm->hm_chain);
+
+ return 0;
+}
+
+static int init_hm_chain(void *fm_pcd, struct list_head *chain_head,
+ struct list_head *item)
+{
+ int err = 0;
+ t_Error error;
+ struct dpa_cls_hm_node *pcurrent, *pnext;
+ t_FmPcdManipParams params;
+ static int index = 0;
+ static int num_int_nodes;
+
+ BUG_ON(!chain_head);
+ BUG_ON(!item);
+
+ if (index++ == 0)
+ num_int_nodes = 0;
+
+ if (item->next != chain_head) {
+ /* Initialize the rest of the HM chain */
+ err = init_hm_chain(fm_pcd, chain_head, item->next);
+ if (err)
+ return err;
+ pnext = list_entry(item->next,
+ struct dpa_cls_hm_node,
+ list_node);
+ } else
+ pnext = NULL;
+
+ /* Initialize the current node: */
+ pcurrent = list_entry(item, struct dpa_cls_hm_node, list_node);
+ pcurrent->params.h_NextManip = (pnext) ? (t_Handle)pnext->node : NULL;
+
+#ifdef DPA_CLASSIFIER_DEBUG
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d): Dumping HM node params.\n",
+ __func__, __LINE__));
+ switch (pcurrent->params.type) {
+ case e_FM_PCD_MANIP_HDR:
+ dpa_cls_dbg((" hm_node_params.type = "
+ "e_FM_PCD_MANIP_HDR\n"));
+ dpa_cls_dbg((" hm_node_params.u.hdr.rmv = %d\n",
+ pcurrent->params.u.hdr.rmv));
+ if (pcurrent->params.u.hdr.rmv) {
+ dpa_cls_dbg((" hm_node_params.u.hdr.rmvParams"
+ ".type = %d\n",
+ pcurrent->params.u.hdr.rmvParams.type));
+ }
+ dpa_cls_dbg((" hm_node_params.u.hdr.insrt = %d\n",
+ pcurrent->params.u.hdr.insrt));
+ if (pcurrent->params.u.hdr.insrt) {
+ dpa_cls_dbg((" hm_node_params.u.hdr.insrtParams"
+ ".type = %d\n",
+ pcurrent->params.u.hdr.insrtParams.type));
+ }
+ dpa_cls_dbg((" hm_node_params.u.hdr.fieldUpdate = %d\n",
+ pcurrent->params.u.hdr.fieldUpdate));
+ if (pcurrent->params.u.hdr.fieldUpdate) {
+ switch (pcurrent->params.u.hdr.fieldUpdateParams.
+ type) {
+ case e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN:
+ dpa_cls_dbg((" hm_node_params.u.hdr."
+ "fieldUpdateParams.type = "
+ "HDR_FIELD_UPDATE_VLAN\n"));
+ break;
+ case e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV4:
+ dpa_cls_dbg((" hm_node_params.u.hdr."
+ "fieldUpdateParams.type = "
+ "HDR_FIELD_UPDATE_IPv4\n"));
+ dpa_cls_dbg((" hm_node_params.u.hdr."
+ "fieldUpdateParams.u.ipv4."
+ "validUpdates = 0x%x\n",
+ pcurrent->params.u.hdr.
+ fieldUpdateParams.u.ipv4.
+ validUpdates));
+ dpa_cls_dbg((" hm_node_params.u.hdr."
+ "fieldUpdateParams.u.ipv4."
+ "tos = 0x%02x\n",
+ pcurrent->params.u.hdr.
+ fieldUpdateParams.u.ipv4.
+ tos));
+ dpa_cls_dbg((" hm_node_params.u.hdr."
+ "fieldUpdateParams.u.ipv4."
+ "id = 0x%04x\n",
+ pcurrent->params.u.hdr.
+ fieldUpdateParams.u.ipv4.
+ id));
+ dpa_cls_dbg((" hm_node_params.u.hdr."
+ "fieldUpdateParams.u.ipv4."
+ "src = 0x%08x\n",
+ pcurrent->params.u.hdr.
+ fieldUpdateParams.u.ipv4.
+ src));
+ dpa_cls_dbg((" hm_node_params.u.hdr."
+ "fieldUpdateParams.u.ipv4."
+ "dst = 0x%08x\n",
+ pcurrent->params.u.hdr.
+ fieldUpdateParams.u.ipv4.
+ dst));
+ break;
+ case e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV6:
+ dpa_cls_dbg((" hm_node_params.u.hdr."
+ "fieldUpdateParams.type = "
+ "HDR_FIELD_UPDATE_IPv6\n"));
+ break;
+ case e_FM_PCD_MANIP_HDR_FIELD_UPDATE_TCP_UDP:
+ dpa_cls_dbg((" hm_node_params.u.hdr."
+ "fieldUpdateParams.type = "
+ "HDR_FIELD_UPDATE_TCP_UDP\n"));
+ dpa_cls_dbg((" hm_node_params.u.hdr."
+ "fieldUpdateParams.u.tcpUdp."
+ "validUpdates = 0x%x\n",
+ pcurrent->params.u.hdr.
+ fieldUpdateParams.u.tcpUdp.
+ validUpdates));
+ dpa_cls_dbg((" hm_node_params.u.hdr."
+ "fieldUpdateParams.u.tcpUdp."
+ "src = 0x%04x\n",
+ pcurrent->params.u.hdr.
+ fieldUpdateParams.u.tcpUdp.
+ src));
+ dpa_cls_dbg((" hm_node_params.u.hdr."
+ "fieldUpdateParams.u.tcpUdp."
+ "dst = 0x%04x\n",
+ pcurrent->params.u.hdr.
+ fieldUpdateParams.u.tcpUdp.
+ dst));
+ break;
+ default:
+ dpa_cls_dbg((" hm_node_params.u.hdr."
+ "fieldUpdateParams.type = %d "
+ "(unknown)\n",
+ pcurrent->params.u.hdr.
+ fieldUpdateParams.type));
+ }
+ }
+ dpa_cls_dbg((" hm_node_params.u.hdr.custom = %d\n",
+ pcurrent->params.u.hdr.custom));
+ if (pcurrent->params.u.hdr.custom) {
+ dpa_cls_dbg((" hm_node_params.u.hdr."
+ "custom.type = %d\n",
+ pcurrent->params.u.hdr.customParams.type));
+ }
+ break;
+ case e_FM_PCD_MANIP_FRAG:
+ dpa_cls_dbg((" hm_node_params.type = "
+ "e_FM_PCD_MANIP_FRAG\n"));
+ break;
+ default:
+ dpa_cls_dbg((" hm_node_params.type = %d (unspecified)\n",
+ pcurrent->params.type));
+ break;
+ }
+ dpa_cls_dbg((" hm_node_params.h_NextManip = 0x%p\n",
+ pcurrent->params.h_NextManip));
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d): End of HM node params.\n",
+ __func__, __LINE__));
+#endif /* DPA_CLASSIFIER_DEBUG */
+ if (!pcurrent->node) {
+ pcurrent->node = (void *) FM_PCD_ManipNodeSet(
+ (t_Handle) fm_pcd,
+ &pcurrent->params);
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d): CREATE new HM "
+ "node (h_node=0x%p).\n", __func__, __LINE__,
+ pcurrent->node));
+ if (!pcurrent->node) {
+ log_err("FMan driver call failed - "
+ "FM_PCD_ManipNodeSet. Failed to initialize low "
+ "level HM #%d from this chain.\n", index);
+ err = -EBUSY;
+ }
+
+ pcurrent->flags |= DPA_CLS_HM_NODE_INTERNAL;
+
+ num_int_nodes++;
+ } else { /* This can be either a STATIC node or an IMPORTED node */
+ if (num_int_nodes) {
+ /*
+ * When working with header manipulation chains that are
+ * half created / half imported, the imported or static
+ * nodes MUST always be LAST in chain. Rechaining low
+ * level header manipulation nodes that are already
+ * initialized is not possible.
+ */
+ log_err("Unsupported hybrid header manipulation chain. "
+ "The imported/static HM ops must be LAST in "
+ "chain.\n");
+ return -EINVAL;
+ }
+ /* For STATIC HM ops we don't need to do anything here */
+ if (pcurrent->params.type != -1) {
+ /* Imported HM - need to sync with an existing node */
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d): REPLACE "
+ "existing HM node (h_node=0x%p).\n", __func__,
+ __LINE__, pcurrent->node));
+
+ /*
+ * Have to make a copy of the manip node params because
+ * ManipNodeReplace does not accept h_NextManip != NULL.
+ */
+ memcpy(&params, &pcurrent->params, sizeof(params));
+ params.h_NextManip = NULL;
+ error = FM_PCD_ManipNodeReplace(pcurrent->node,
+ &params);
+ if (error != E_OK) {
+ log_err("FMan driver call failed - "
+ "FM_PCD_ManipNodeReplace. Failed to "
+ "initialize low level HM #%d "
+ "from this chain.\n", index);
+ err = -EBUSY;
+ }
+ }
+ }
+
+ index--;
+ return err;
+}
+
+int remove_hm_chain(struct list_head *chain_head, struct list_head *item)
+{
+ int err = 0;
+ struct dpa_cls_hm_node *pcurrent;
+ t_Error error;
+ static int index = 0;
+
+ BUG_ON(!chain_head);
+ BUG_ON(!item);
+
+ index++;
+ /* Remove the current node: */
+ pcurrent = list_entry(item, struct dpa_cls_hm_node, list_node);
+
+ if ((pcurrent->flags & DPA_CLS_HM_NODE_INTERNAL) && (pcurrent->node)) {
+ error = FM_PCD_ManipNodeDelete((t_Handle) pcurrent->node);
+ if (error != E_OK) {
+ log_warn("Memory leak: failed to remove low "
+ "level HM #%d from this chain. Manip node "
+ "handle=0x%p.\n", index, pcurrent->node);
+ log_warn("FMan driver call failed - "
+ "FM_PCD_ManipNodeDelete.\n");
+ }
+ }
+
+ if (item->next != chain_head) {
+ /* Remove the rest of the HM chain */
+ err = remove_hm_chain(chain_head, item->next);
+ if (err < 0)
+ return err;
+ }
+
+ list_del(item);
+
+ remove_hm_node(pcurrent);
+
+ index--;
+
+ return err;
+}
+
+static void remove_hm_node(struct dpa_cls_hm_node *node)
+{
+ /* Check and remove all allocated buffers from the HM params: */
+ switch (node->params.type) {
+ case e_FM_PCD_MANIP_HDR:
+ if ((node->params.u.hdr.insrt) &&
+ (node->params.u.hdr.insrtParams.type ==
+ e_FM_PCD_MANIP_INSRT_GENERIC))
+ kfree(node->params.u.hdr.insrtParams.u.generic.p_Data);
+
+ break;
+ default:
+ break;
+ }
+
+ /* Remove the node */
+ kfree(node);
+}
+
+static struct dpa_cls_hm_node
+ *find_compatible_hm_node(enum dpa_cls_hm_node_type type,
+ struct list_head *list)
+{
+ struct dpa_cls_hm_node *phm_node;
+ e_FmPcdManipHdrFieldUpdateType val;
+
+ BUG_ON(!list);
+
+ switch (type) {
+ case DPA_CLS_HM_NODE_IPv4_HDR_UPDATE:
+ val = e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV4;
+ break;
+ case DPA_CLS_HM_NODE_IPv6_HDR_UPDATE:
+ val = e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV6;
+ break;
+ case DPA_CLS_HM_NODE_TCPUDP_HDR_UPDATE:
+ val = e_FM_PCD_MANIP_HDR_FIELD_UPDATE_TCP_UDP;
+ break;
+ default:
+ log_err("Don't know how to search for nodes compatible with "
+ "type=%d.\n", type);
+ return NULL;
+ }
+
+ list_for_each_entry(phm_node, list, list_node) {
+ if ((phm_node->params.type == e_FM_PCD_MANIP_HDR) &&
+ (phm_node->params.u.hdr.fieldUpdate) &&
+ (phm_node->params.u.hdr.fieldUpdateParams.type == val))
+ return phm_node;
+ }
+
+ return NULL;
+}
+
+static int create_new_hm_op(int *hmd, int next_hmd)
+{
+ int err;
+ struct dpa_cls_hm *hm;
+ struct dpa_cls_hm *next_hm, *pcurrent;
+
+ BUG_ON(!hmd);
+
+ *hmd = DPA_OFFLD_DESC_NONE;
+
+ /* Allocate header manipulation object */
+ hm = kzalloc(sizeof(struct dpa_cls_hm), GFP_KERNEL);
+ if (!hm) {
+ log_err("No more memory for header manip ops.\n");
+ return -ENOMEM;
+ }
+
+ lock_desc_table(&hm_array);
+ err = acquire_descriptor(&hm_array, hm, hmd);
+ if (err < 0) {
+ release_desc_table(&hm_array);
+ return err;
+ }
+
+ INIT_LIST_HEAD(&hm->list_node);
+
+ mutex_init(&hm->access);
+ mutex_lock(&hm->access);
+
+ if (next_hmd != DPA_OFFLD_DESC_NONE) {
+ /* Check whether [next_hmd] is a valid descriptor */
+ if ((next_hmd < 0) || (next_hmd >= hm_array.num_descriptors)) {
+ release_desc_table(&hm_array);
+ log_err("Invalid next HM descriptor (next_hmd=%d). "
+ "Should be between %d and %d.\n",
+ next_hmd, 0, hm_array.num_descriptors-1);
+ return -EINVAL;
+ }
+ next_hm = (struct dpa_cls_hm *)hm_array.object[next_hmd];
+ if (!next_hm) {
+ release_desc_table(&hm_array);
+ log_err("Link to an invalid HM (next_hmd=%d).\n",
+ next_hmd);
+ return -EINVAL;
+ }
+
+ /* Lock entire high level HM op chain */
+ LOCK_HM_OP_CHAIN(next_hm);
+ release_desc_table(&hm_array);
+
+ /*
+ * In case this high level op is chained with another high
+ * level op, add it to the list.
+ */
+
+ list_add_tail(&hm->list_node, &next_hm->list_node);
+
+ hm->hm_chain = next_hm->hm_chain;
+ } else { /* Isolated header manip op, or first in chain. */
+ hm->hm_chain = kmalloc(sizeof(struct list_head), GFP_KERNEL);
+ if (!hm->hm_chain) {
+ remove_hm_op(*hmd);
+ release_desc_table(&hm_array);
+ log_err("No more memory for header manip ops.\n");
+ *hmd = DPA_OFFLD_DESC_NONE;
+ return -ENOMEM;
+ }
+ release_desc_table(&hm_array);
+
+ INIT_LIST_HEAD(hm->hm_chain);
+ }
+
+ return err;
+}
+
+static void remove_hm_op(int hmd)
+{
+ struct dpa_cls_hm *phm, *pcurrent, *pnext;
+
+ BUG_ON((hmd < 0) || (hmd >= hm_array.num_descriptors));
+
+ phm = (struct dpa_cls_hm *) hm_array.object[hmd];
+
+ if (!phm) {
+ /* Descriptor already free. Nothing to do */
+ return;
+ }
+
+ if (list_empty(&phm->list_node))
+ kfree(phm->hm_chain);
+ else {
+ LOCK_HM_OP_CHAIN(phm);
+
+ pnext = list_entry(phm->list_node.next,
+ struct dpa_cls_hm,
+ list_node);
+ /* If this op is attached to others, detach it from the list */
+ list_del(&phm->list_node);
+
+ RELEASE_HM_OP_CHAIN(pnext);
+ }
+
+ put_descriptor(&hm_array, hmd);
+
+ kfree(phm);
+}
+
+int dpa_classif_set_nat_hm(const struct dpa_cls_hm_nat_params *nat_params,
+ int next_hmd,
+ int *hmd,
+ bool chain_head,
+ const struct dpa_cls_hm_nat_resources *res)
+{
+ int err;
+ struct dpa_cls_hm *pnat_hm, *pcurrent;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ /* Parameters sanity checks: */
+ if (!nat_params) {
+ log_err("\"nat_params\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+ if (!hmd) {
+ log_err("\"hmd\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ *hmd = DPA_OFFLD_DESC_NONE;
+
+ err = nat_hm_check_params(nat_params);
+ if (err < 0) {
+ log_err("Invalid NAT HM parameters.\n");
+ return err;
+ }
+
+ err = create_new_hm_op(hmd, next_hmd);
+ if (err < 0) {
+ log_err("Failed to create NAT HM op.\n");
+ return err;
+ }
+
+ pnat_hm = (struct dpa_cls_hm *) hm_array.object[*hmd];
+
+ pnat_hm->type = DPA_CLS_HM_TYPE_NAT;
+ pnat_hm->chain_head = chain_head;
+
+ /* Copy the NAT parameters locally */
+ memcpy(&pnat_hm->nat_params, nat_params, sizeof(*nat_params));
+
+ err = nat_hm_prepare_nodes(pnat_hm, res);
+ if (err < 0) {
+ log_err("Failed to acquire necessary HM nodes.\n");
+ goto nat_hm_error;
+ }
+
+ err = nat_hm_update_params(pnat_hm);
+ if (err < 0) {
+ log_err("Failed to update low level header manipulation "
+ "parameters.\n");
+ goto nat_hm_error;
+ }
+
+ if (chain_head) {
+ err = init_hm_chain(pnat_hm->nat_params.fm_pcd,
+ pnat_hm->hm_chain,
+ pnat_hm->hm_chain->next);
+ if (err < 0)
+ log_err("Failed to initialize low level HM chain.\n");
+ }
+
+ /* Release the high level HM op chain */
+ RELEASE_HM_OP_CHAIN(pnat_hm);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+
+nat_hm_error:
+
+ /* Release the high level HM op chain */
+ RELEASE_HM_OP_CHAIN(pnat_hm);
+
+ lock_desc_table(&hm_array);
+ remove_hm_op(*hmd);
+ release_desc_table(&hm_array);
+
+ *hmd = DPA_OFFLD_DESC_NONE;
+
+ return err;
+}
+EXPORT_SYMBOL(dpa_classif_set_nat_hm);
+
+static int nat_hm_prepare_nodes(struct dpa_cls_hm *pnat_hm,
+ const struct dpa_cls_hm_nat_resources *res)
+{
+ struct dpa_cls_hm_node *hm_node = NULL;
+ struct dpa_cls_hm *pnext_hm = NULL;
+ void * const *phm_nodes;
+ int err = 0;
+ enum dpa_cls_hm_node_type l3_update_node = DPA_CLS_HM_NODE_LAST_ENTRY;
+ enum dpa_cls_hm_node_type l4_update_node = DPA_CLS_HM_NODE_LAST_ENTRY;
+ unsigned int ip_ver = 0;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!pnat_hm);
+
+ pnat_hm->num_nodes = 2;
+
+ if (res) { /* Import HM nodes */
+ phm_nodes = &res->l3_update_node;
+
+ return import_hm_nodes_to_chain(phm_nodes,
+ pnat_hm->num_nodes,
+ pnat_hm);
+ }
+
+ /* Create HM nodes */
+ if (pnat_hm->nat_params.type == DPA_CLS_HM_NAT_TYPE_TRADITIONAL) {
+ if (pnat_hm->nat_params.flags &
+ DPA_CLS_HM_NAT_UPDATE_SIP)
+ ip_ver = pnat_hm->nat_params.nat.sip.version;
+ if (pnat_hm->nat_params.flags &
+ DPA_CLS_HM_NAT_UPDATE_DIP)
+ ip_ver = pnat_hm->nat_params.nat.dip.version;
+ if ((pnat_hm->nat_params.flags &
+ DPA_CLS_HM_NAT_UPDATE_SPORT) ||
+ (pnat_hm->nat_params.flags &
+ DPA_CLS_HM_NAT_UPDATE_DPORT))
+ l4_update_node = DPA_CLS_HM_NODE_TCPUDP_HDR_UPDATE;
+ if (ip_ver) {
+ if (ip_ver == 4)
+ l3_update_node =
+ DPA_CLS_HM_NODE_IPv4_HDR_UPDATE;
+ else
+ l3_update_node =
+ DPA_CLS_HM_NODE_IPv6_HDR_UPDATE;
+ }
+ } else {
+ if (pnat_hm->nat_params.nat_pt.type ==
+ DPA_CLS_HM_NAT_PT_IPv6_TO_IPv4)
+ l3_update_node =
+ DPA_CLS_HM_NODE_HDR_REPLACE_IPv6_BY_IPv4;
+ else
+ l3_update_node =
+ DPA_CLS_HM_NODE_HDR_REPLACE_IPv4_BY_IPv6;
+ }
+
+ /* Check if we can attach to an existing update node */
+ if (!list_empty(&pnat_hm->list_node))
+ pnext_hm = list_entry(pnat_hm->list_node.next,
+ struct dpa_cls_hm,
+ list_node);
+
+ if (l3_update_node != DPA_CLS_HM_NODE_LAST_ENTRY) {
+ /* Check if we can attach to an existing L3 update node */
+ if (pnext_hm)
+ hm_node = find_compatible_hm_node(l3_update_node,
+ pnext_hm->hm_chain);
+ /* If not, create an L3 update node: */
+ if (!hm_node) {
+ hm_node = kzalloc(sizeof(*hm_node), GFP_KERNEL);
+ if (!hm_node) {
+ log_err("No more memory for header manip "
+ "nodes.\n");
+ return -ENOMEM;
+ }
+ INIT_LIST_HEAD(&hm_node->list_node);
+ pnat_hm->hm_node[0] = hm_node;
+ }
+ }
+
+ hm_node = NULL;
+ if (l4_update_node != DPA_CLS_HM_NODE_LAST_ENTRY) {
+ /* Check if we can attach to an existing L4 update node */
+ if (pnext_hm)
+ hm_node = find_compatible_hm_node(l4_update_node,
+ pnext_hm->hm_chain);
+ /* If not create an L4 update node: */
+ if (!hm_node) {
+ hm_node = kzalloc(sizeof(*hm_node), GFP_KERNEL);
+ if (!hm_node) {
+ log_err("No more memory for header manip "
+ "nodes.\n");
+ return -ENOMEM;
+ }
+ INIT_LIST_HEAD(&hm_node->list_node);
+ pnat_hm->hm_node[1] = hm_node;
+ }
+ }
+
+ add_local_hm_nodes_to_chain(pnat_hm);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+}
+
+static int nat_hm_update_params(struct dpa_cls_hm *pnat_hm)
+{
+ struct dpa_cls_hm_node *hm_node;
+ unsigned int ip_ver = 0;
+
+ BUG_ON(!pnat_hm);
+ BUG_ON(pnat_hm->num_nodes < 1);
+ BUG_ON(pnat_hm->num_nodes > 2);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ if (pnat_hm->hm_node[0]) {
+ hm_node = pnat_hm->hm_node[0];
+
+ hm_node->params.type = e_FM_PCD_MANIP_HDR;
+ hm_node->params.u.hdr.dontParseAfterManip = TRUE;
+
+ if (pnat_hm->nat_params.type ==
+ DPA_CLS_HM_NAT_TYPE_TRADITIONAL) {
+ hm_node->params.u.hdr.fieldUpdate = TRUE;
+
+ if (pnat_hm->nat_params.flags &
+ DPA_CLS_HM_NAT_UPDATE_SIP)
+ ip_ver = pnat_hm->nat_params.nat.sip.version;
+ if (pnat_hm->nat_params.flags &
+ DPA_CLS_HM_NAT_UPDATE_DIP)
+ ip_ver = pnat_hm->nat_params.nat.dip.version;
+
+ if (ip_ver == 4) {
+ hm_node->params.u.hdr.fieldUpdateParams.type =
+ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV4;
+
+ if (pnat_hm->nat_params.flags &
+ DPA_CLS_HM_NAT_UPDATE_SIP) {
+ hm_node->params.u.hdr.
+ fieldUpdateParams.u.ipv4.
+ validUpdates |=
+ HDR_MANIP_IPV4_SRC;
+ hm_node->params.u.hdr.
+ fieldUpdateParams.u.ipv4.
+ src = pnat_hm->nat_params.nat.
+ sip.addr.ipv4.word;
+ }
+
+ if (pnat_hm->nat_params.flags &
+ DPA_CLS_HM_NAT_UPDATE_DIP) {
+ hm_node->params.u.hdr.
+ fieldUpdateParams.u.ipv4.
+ validUpdates |=
+ HDR_MANIP_IPV4_DST;
+ hm_node->params.u.hdr.
+ fieldUpdateParams.u.ipv4.
+ dst = pnat_hm->nat_params.nat.
+ dip.addr.ipv4.word;
+ }
+ } else { /* We're dealing with IPv6 */
+ hm_node->params.u.hdr.fieldUpdateParams.type =
+ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV6;
+
+ if (pnat_hm->nat_params.flags &
+ DPA_CLS_HM_NAT_UPDATE_SIP) {
+ hm_node->params.u.hdr.
+ fieldUpdateParams.u.ipv6.
+ validUpdates |=
+ HDR_MANIP_IPV6_SRC;
+ memcpy(hm_node->params.u.hdr.
+ fieldUpdateParams.u.ipv6.src,
+ pnat_hm->nat_params.nat.sip.
+ addr.ipv6.byte,
+ DPA_OFFLD_IPv6_ADDR_LEN_BYTES);
+ }
+
+ if (pnat_hm->nat_params.flags &
+ DPA_CLS_HM_NAT_UPDATE_DIP) {
+ hm_node->params.u.hdr.
+ fieldUpdateParams.u.ipv4.
+ validUpdates |=
+ HDR_MANIP_IPV6_DST;
+ memcpy(hm_node->params.u.hdr.
+ fieldUpdateParams.u.ipv6.dst,
+ pnat_hm->nat_params.nat.dip.
+ addr.ipv6.byte,
+ DPA_OFFLD_IPv6_ADDR_LEN_BYTES);
+ }
+ }
+ } else { /* NAT-PT */
+ hm_node->params.u.hdr.custom = TRUE;
+ hm_node->params.u.hdr.customParams.type =
+ e_FM_PCD_MANIP_HDR_CUSTOM_IP_REPLACE;
+
+ if (pnat_hm->nat_params.nat_pt.type ==
+ DPA_CLS_HM_NAT_PT_IPv6_TO_IPv4) {
+ hm_node->params.u.hdr.customParams.u.
+ ipHdrReplace.replaceType =
+ e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4;
+ hm_node->params.u.hdr.customParams.u.
+ ipHdrReplace.hdrSize =
+ sizeof(struct iphdr) +
+ pnat_hm->nat_params.nat_pt.new_header.ipv4.options_size;
+ memcpy(hm_node->params.u.hdr.customParams.u.
+ ipHdrReplace.hdr,
+ &pnat_hm->nat_params.nat_pt.new_header.
+ ipv4.header, sizeof(struct iphdr));
+ if ((pnat_hm->nat_params.nat_pt.new_header.ipv4.options_size)
+ && (pnat_hm->nat_params.nat_pt.new_header.ipv4.options)) {
+ memcpy(&hm_node->params.u.hdr.customParams.u.ipHdrReplace.
+ hdr[sizeof(struct iphdr)],
+ &pnat_hm->nat_params.nat_pt.new_header.ipv4.options,
+ pnat_hm->nat_params.nat_pt.new_header.ipv4.options_size);
+ }
+ } else {
+ hm_node->params.u.hdr.customParams.u.
+ ipHdrReplace.replaceType =
+ e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV4_BY_IPV6;
+ hm_node->params.u.hdr.customParams.u.
+ ipHdrReplace.hdrSize =
+ (uint8_t)sizeof(struct ipv6_header);
+ memcpy(hm_node->params.u.hdr.customParams.u.
+ ipHdrReplace.hdr,
+ &pnat_hm->nat_params.nat_pt.new_header.
+ ipv6, sizeof(struct ipv6_header));
+ }
+ }
+ }
+
+ if (pnat_hm->hm_node[1]) {
+ hm_node = pnat_hm->hm_node[1];
+
+ hm_node->params.type = e_FM_PCD_MANIP_HDR;
+ hm_node->params.u.hdr.fieldUpdate = TRUE;
+ hm_node->params.u.hdr.dontParseAfterManip = TRUE;
+ hm_node->params.u.hdr.fieldUpdateParams.type =
+ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_TCP_UDP;
+
+ if (pnat_hm->nat_params.flags & DPA_CLS_HM_NAT_UPDATE_SPORT) {
+ hm_node->params.u.hdr.fieldUpdateParams.u.tcpUdp.
+ validUpdates |= HDR_MANIP_TCP_UDP_SRC;
+ hm_node->params.u.hdr.fieldUpdateParams.u.tcpUdp.src =
+ pnat_hm->nat_params.sport;
+ }
+
+ if (pnat_hm->nat_params.flags & DPA_CLS_HM_NAT_UPDATE_DPORT) {
+ hm_node->params.u.hdr.fieldUpdateParams.u.tcpUdp.
+ validUpdates |= HDR_MANIP_TCP_UDP_DST;
+ hm_node->params.u.hdr.fieldUpdateParams.u.tcpUdp.dst =
+ pnat_hm->nat_params.dport;
+ }
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return 0;
+}
+
+int dpa_classif_modify_nat_hm(int hmd,
+ const struct dpa_cls_hm_nat_params *new_nat_params, int modify_flags)
+{
+ struct dpa_cls_hm_node *hm_node;
+ struct dpa_cls_hm *pnat_hm;
+ bool update[2] = { false, false };
+ t_Error error;
+ int ret = 0;
+ int i;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ if (!modify_flags)
+ /* Nothing to do */
+ return 0;
+
+ /* Parameters sanity checks: */
+ if (!new_nat_params) {
+ log_err("\"new_nat_params\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ lock_desc_table(&hm_array);
+ pnat_hm = desc_to_object(&hm_array, hmd);
+ if (!pnat_hm) {
+ release_desc_table(&hm_array);
+ log_err("Invalid descriptor (%d).\n", hmd);
+ return -EINVAL;
+ }
+ mutex_lock(&pnat_hm->access);
+ /*
+ * Hold the lock on the descriptor table to prevent other runtime
+ * modifications of header manipulations until we're finished. The FMan
+ * driver doesn't allow parallel modification of HM nodes when they
+ * belong to the same PCD.
+ */
+
+ if (pnat_hm->type != DPA_CLS_HM_TYPE_NAT) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&pnat_hm->access);
+ log_err("hmd=%d is not an NAT type header manip.\n", hmd);
+ return -EINVAL;
+ }
+
+ if (pnat_hm->nat_params.type == DPA_CLS_HM_NAT_TYPE_TRADITIONAL) {
+ if (modify_flags & DPA_CLS_HM_NAT_MOD_SIP) {
+ if (new_nat_params->nat.sip.version !=
+ pnat_hm->nat_params.nat.sip.version) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&pnat_hm->access);
+ log_err("New SIP adress version (%d) in NAT "
+ "header manipulation hmd=%d cannot be "
+ "different from the old one (%d).\n",
+ new_nat_params->nat.sip.version, hmd,
+ pnat_hm->nat_params.nat.sip.version);
+ return -EINVAL;
+ }
+ update[0] = true;
+ memcpy(&pnat_hm->nat_params.nat.sip,
+ &new_nat_params->nat.sip,
+ sizeof(struct dpa_offload_ip_address));
+ }
+
+ if (modify_flags & DPA_CLS_HM_NAT_MOD_DIP) {
+ if (new_nat_params->nat.dip.version !=
+ pnat_hm->nat_params.nat.dip.version) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&pnat_hm->access);
+ log_err("New DIP adress version (%d) in NAT "
+ "header manipulation hmd=%d cannot be "
+ "different from the old one (%d).\n",
+ new_nat_params->nat.dip.version, hmd,
+ pnat_hm->nat_params.nat.dip.version);
+ return -EINVAL;
+ }
+ update[0] = true;
+ memcpy(&pnat_hm->nat_params.nat.dip,
+ &new_nat_params->nat.dip,
+ sizeof(struct dpa_offload_ip_address));
+ }
+ } else { /* NAT-PT */
+ if (modify_flags & DPA_CLS_HM_NAT_MOD_IP_HDR) {
+ if (pnat_hm->nat_params.nat_pt.type ==
+ DPA_CLS_HM_NAT_PT_IPv6_TO_IPv4) {
+ memcpy(&pnat_hm->nat_params.nat_pt.new_header.
+ ipv4.header, &new_nat_params->nat_pt.
+ new_header.ipv4.header,
+ sizeof(struct iphdr));
+ /* Update IPv4 options */
+ kfree(pnat_hm->nat_params.nat_pt.new_header.
+ ipv4.options);
+ if (new_nat_params->nat_pt.new_header.ipv4.
+ options_size) {
+ pnat_hm->nat_params.nat_pt.new_header.
+ ipv4.options = kzalloc(
+ new_nat_params->nat_pt.
+ new_header.ipv4.options_size,
+ GFP_KERNEL);
+ if (!pnat_hm->update_params.replace.
+ new_ipv4_hdr.options) {
+ pnat_hm->nat_params.nat_pt.
+ new_header.ipv4.
+ options_size = 0;
+ release_desc_table(&hm_array);
+ mutex_unlock(&pnat_hm->access);
+ log_err("Out of memory while "
+ "modifying IPv6 header "
+ "replace header "
+ "manipulation "
+ "hmd=%d.\n", hmd);
+ return -EINVAL;
+ }
+ } else
+ pnat_hm->nat_params.nat_pt.new_header.
+ ipv4.options = NULL;
+ pnat_hm->nat_params.nat_pt.new_header.ipv4.
+ options_size = new_nat_params->nat_pt.
+ new_header.ipv4.options_size;
+ } else { /* DPA_CLS_HM_NAT_PT_IPv4_TO_IPv6 */
+ memcpy(&pnat_hm->nat_params.nat_pt.new_header.
+ ipv6, &new_nat_params->nat_pt.
+ new_header.ipv6,
+ sizeof(struct ipv6_header));
+ }
+ update[0] = true;
+ }
+ }
+
+ if ((modify_flags & DPA_CLS_HM_NAT_MOD_SPORT) &&
+ (new_nat_params->sport != pnat_hm->nat_params.sport)) {
+ update[1] = true;
+ pnat_hm->nat_params.sport = new_nat_params->sport;
+ }
+
+ if ((modify_flags & DPA_CLS_HM_NAT_MOD_DPORT) &&
+ (new_nat_params->dport != pnat_hm->nat_params.dport)) {
+ update[1] = true;
+ pnat_hm->nat_params.dport = new_nat_params->dport;
+ }
+
+ if ((modify_flags & DPA_CLS_HM_NAT_MOD_FLAGS) &&
+ (new_nat_params->flags != pnat_hm->nat_params.flags)) {
+ update[0] = true;
+ update[1] = true;
+ pnat_hm->nat_params.flags = new_nat_params->flags;
+ }
+
+ if (update[0] || update[1]) {
+ ret = nat_hm_update_params(pnat_hm);
+ if (ret == 0) {
+ t_FmPcdManipParams new_hm_node_params;
+
+ for (i = 0; i < 2; i++) {
+ if (!update[i])
+ continue;
+
+ hm_node = pnat_hm->hm_node[i];
+ memcpy(&new_hm_node_params,
+ &hm_node->params,
+ sizeof(t_FmPcdManipParams));
+ /*
+ * Must make sure that h_NextManip is NULL
+ * before calling FM_PCD_ManipNodeReplace
+ */
+ new_hm_node_params.h_NextManip = NULL;
+
+ error = FM_PCD_ManipNodeReplace(hm_node->node,
+ &new_hm_node_params);
+ if (error != E_OK) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&pnat_hm->access);
+ log_err("FMan driver call failed - "
+ "FM_PCD_ManipNodeReplace, "
+ "while trying to modify "
+ "hmd=%d, manip node "
+ "handle=0x%p (node #%d).\n",
+ hmd, hm_node->node, i);
+ return -EBUSY;
+ }
+ }
+ }
+ }
+
+ release_desc_table(&hm_array);
+ mutex_unlock(&pnat_hm->access);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+EXPORT_SYMBOL(dpa_classif_modify_nat_hm);
+
+int dpa_classif_set_fwd_hm(const struct dpa_cls_hm_fwd_params *fwd_params,
+ int next_hmd,
+ int *hmd,
+ bool chain_head,
+ const struct dpa_cls_hm_fwd_resources *res)
+{
+ int err;
+ struct dpa_cls_hm *pfwd_hm, *pcurrent;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ /* Parameters sanity checks: */
+ if (!fwd_params) {
+ log_err("\"fwd_params\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+ if (!hmd) {
+ log_err("\"hmd\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ *hmd = DPA_OFFLD_DESC_NONE;
+
+ err = fwd_hm_check_params(fwd_params);
+ if (err < 0) {
+ log_err("Invalid forwarding HM parameters.\n");
+ return err;
+ }
+
+ err = create_new_hm_op(hmd, next_hmd);
+ if (err < 0) {
+ log_err("Failed to create forwarding HM op.\n");
+ return err;
+ }
+
+ pfwd_hm = (struct dpa_cls_hm *) hm_array.object[*hmd];
+
+ pfwd_hm->type = DPA_CLS_HM_TYPE_FORWARDING;
+ pfwd_hm->chain_head = chain_head;
+
+ /* Copy the NAT parameters locally */
+ memcpy(&pfwd_hm->fwd_params, fwd_params, sizeof(*fwd_params));
+
+ err = fwd_hm_prepare_nodes(pfwd_hm, res);
+ if (err < 0) {
+ log_err("Failed to acquire necessary HM nodes.\n");
+ goto fwd_hm_error;
+ }
+
+ err = fwd_hm_update_params(pfwd_hm);
+ if (err < 0) {
+ log_err("Failed to update low level header manipulation "
+ "parameters.\n");
+ goto fwd_hm_error;
+ }
+
+ if (chain_head) {
+ err = init_hm_chain(pfwd_hm->fwd_params.fm_pcd,
+ pfwd_hm->hm_chain,
+ pfwd_hm->hm_chain->next);
+ if (err < 0)
+ log_err("Failed to initialize low level HM chain.\n");
+ }
+
+ /* Release the high level HM op chain */
+ RELEASE_HM_OP_CHAIN(pfwd_hm);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+
+fwd_hm_error:
+
+ /* Release the high level HM op chain */
+ RELEASE_HM_OP_CHAIN(pfwd_hm);
+
+ lock_desc_table(&hm_array);
+ remove_hm_op(*hmd);
+ release_desc_table(&hm_array);
+
+ *hmd = DPA_OFFLD_DESC_NONE;
+
+ return err;
+}
+EXPORT_SYMBOL(dpa_classif_set_fwd_hm);
+
+static int fwd_hm_prepare_nodes(struct dpa_cls_hm *pfwd_hm,
+ const struct dpa_cls_hm_fwd_resources *res)
+{
+ struct dpa_cls_hm_node *hm_node;
+ void * const *phm_nodes;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!pfwd_hm);
+
+ pfwd_hm->num_nodes = 3;
+
+ if (res) { /* Import HM nodes */
+ phm_nodes = &res->fwd_node;
+
+ return import_hm_nodes_to_chain(phm_nodes,
+ pfwd_hm->num_nodes,
+ pfwd_hm);
+ }
+
+ hm_node = kzalloc(sizeof(*hm_node), GFP_KERNEL);
+ if (!hm_node) {
+ log_err("Not enough memory for header manip nodes.\n");
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&hm_node->list_node);
+ pfwd_hm->hm_node[0] = hm_node;
+
+ if (pfwd_hm->update_params.ip_frag_params.mtu) {
+ /* IP fragmentation option is enabled */
+ /* Create a header manip node: */
+ hm_node = kzalloc(sizeof(*hm_node), GFP_KERNEL);
+ if (!hm_node) {
+ log_err("No more memory for header manip nodes.\n");
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&hm_node->list_node);
+ pfwd_hm->hm_node[1] = hm_node;
+ }
+
+ add_local_hm_nodes_to_chain(pfwd_hm);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return 0;
+}
+
+static int fwd_hm_update_params(struct dpa_cls_hm *pfwd_hm)
+{
+ struct dpa_cls_hm_node *hm_node;
+ uint8_t size;
+ uint8_t *pdata;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!pfwd_hm);
+ BUG_ON(pfwd_hm->num_nodes < 1);
+ BUG_ON(!pfwd_hm->hm_node[0]);
+
+ hm_node = pfwd_hm->hm_node[0];
+
+ hm_node->params.type = e_FM_PCD_MANIP_HDR;
+ hm_node->params.u.hdr.dontParseAfterManip = TRUE;
+ switch (pfwd_hm->fwd_params.out_if_type) {
+ case DPA_CLS_HM_IF_TYPE_ETHERNET:
+ /* Update Ethernet MACS */
+ hm_node->params.u.hdr.insrt = TRUE;
+ hm_node->params.u.hdr.insrtParams.type =
+ e_FM_PCD_MANIP_INSRT_GENERIC;
+ hm_node->params.u.hdr.insrtParams.u.generic.replace = TRUE;
+ hm_node->params.u.hdr.dontParseAfterManip = TRUE;
+
+ size = (uint8_t)(sizeof(struct ethhdr) - ETHERTYPE_SIZE);
+ pdata = kzalloc(size, GFP_KERNEL);
+ if (!pdata) {
+ log_err("Not enough memory for forwarding HM.\n");
+ return -ENOMEM;
+ }
+
+ memcpy(pdata, pfwd_hm->fwd_params.eth.macda, ETH_ALEN);
+ memcpy(&pdata[ETH_ALEN], pfwd_hm->fwd_params.eth.macsa,
+ ETH_ALEN);
+
+ kfree(hm_node->params.u.hdr.insrtParams.u.generic.p_Data);
+
+ hm_node->params.u.hdr.insrtParams.u.generic.offset = 0;
+ hm_node->params.u.hdr.insrtParams.u.generic.size = size;
+ hm_node->params.u.hdr.insrtParams.u.generic.p_Data = pdata;
+ case DPA_CLS_HM_IF_TYPE_PPPoE:
+ /* Update Ethernet MACS; insert PPPoE */
+ /* Insert PPPoE is not supported yet */
+ break;
+ case DPA_CLS_HM_IF_TYPE_PPP:
+ /* Remove Ethernet and VLANs; insert PPP */
+ hm_node->params.u.hdr.rmv = TRUE;
+ hm_node->params.u.hdr.rmvParams.type =
+ e_FM_PCD_MANIP_RMV_BY_HDR;
+ hm_node->params.u.hdr.rmvParams.u.byHdr.type =
+ e_FM_PCD_MANIP_RMV_BY_HDR_SPECIFIC_L2;
+ hm_node->params.u.hdr.rmvParams.u.byHdr.u.specificL2 =
+ e_FM_PCD_MANIP_HDR_RMV_ETHERNET;
+
+ hm_node->params.u.hdr.insrt = TRUE;
+ hm_node->params.u.hdr.insrtParams.type =
+ e_FM_PCD_MANIP_INSRT_GENERIC;
+
+ size = PPP_HEADER_SIZE;
+ pdata = kzalloc(size, GFP_KERNEL);
+ if (!pdata) {
+ log_err("Not enough memory for forwarding HM.\n");
+ return -ENOMEM;
+ }
+
+ memcpy(pdata, &pfwd_hm->fwd_params.ppp.ppp_pid,
+ PPP_HEADER_SIZE);
+
+ kfree(hm_node->params.u.hdr.insrtParams.u.generic.p_Data);
+
+ hm_node->params.u.hdr.insrtParams.u.generic.offset = 0;
+ hm_node->params.u.hdr.insrtParams.u.generic.size = size;
+ hm_node->params.u.hdr.insrtParams.u.generic.p_Data = pdata;
+ break;
+ default:
+ log_err("Forwarding HM: Unknown output port type (%d).\n",
+ pfwd_hm->fwd_params.out_if_type);
+ return -EINVAL;
+ }
+
+ hm_node = pfwd_hm->hm_node[1];
+
+ if (pfwd_hm->fwd_params.ip_frag_params.mtu) {
+ /* IP fragmentation option is enabled */
+ BUG_ON(!hm_node);
+
+ hm_node->params.type = e_FM_PCD_MANIP_FRAG;
+ hm_node->params.u.frag.hdr = HEADER_TYPE_IPv4;
+ hm_node->params.u.frag.u.ipFrag.sizeForFragmentation =
+ pfwd_hm->fwd_params.ip_frag_params.mtu;
+#if (DPAA_VERSION == 10)
+ hm_node->params.u.frag.u.ipFrag.scratchBpid =
+ pfwd_hm->fwd_params.ip_frag_params.
+ scratch_bpid;
+#endif /* (DPAA_VERSION == 10) */
+ switch (pfwd_hm->fwd_params.ip_frag_params.df_action) {
+ case DPA_CLS_HM_DF_ACTION_FRAG_ANYWAY:
+ hm_node->params.u.frag.u.ipFrag.dontFragAction =
+ e_FM_PCD_MANIP_FRAGMENT_PACKET;
+ break;
+ case DPA_CLS_HM_DF_ACTION_DONT_FRAG:
+ hm_node->params.u.frag.u.ipFrag.dontFragAction =
+ e_FM_PCD_MANIP_CONTINUE_WITHOUT_FRAG;
+ break;
+ case DPA_CLS_HM_DF_ACTION_DROP:
+ hm_node->params.u.frag.u.ipFrag.dontFragAction =
+ e_FM_PCD_MANIP_ENQ_TO_ERR_Q_OR_DISCARD_PACKET;
+ break;
+ }
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return 0;
+}
+
+int dpa_classif_modify_fwd_hm(int hmd,
+ const struct dpa_cls_hm_fwd_params *new_fwd_params, int modify_flags)
+{
+ struct dpa_cls_hm_node *hm_node;
+ struct dpa_cls_hm *pfwd_hm;
+ bool update[3] = { false, false, false };
+ t_Error error;
+ int ret = 0;
+ int i;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ if (!modify_flags)
+ /* Nothing to do */
+ return 0;
+
+ /* Parameters sanity checks: */
+ if (!new_fwd_params) {
+ log_err("\"new_fwd_params\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ lock_desc_table(&hm_array);
+ pfwd_hm = desc_to_object(&hm_array, hmd);
+ if (!pfwd_hm) {
+ release_desc_table(&hm_array);
+ log_err("Invalid descriptor (%d).\n", hmd);
+ return -EINVAL;
+ }
+ mutex_lock(&pfwd_hm->access);
+ /*
+ * Hold the lock on the descriptor table to prevent other runtime
+ * modifications of header manipulations until we're finished. The FMan
+ * driver doesn't allow parallel modification of HM nodes when they
+ * belong to the same PCD.
+ */
+
+ if (pfwd_hm->type != DPA_CLS_HM_TYPE_FORWARDING) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&pfwd_hm->access);
+ log_err("hmd=%d is not an FORWARDING type header manip.\n",
+ hmd);
+ return -EINVAL;
+ }
+
+ if (modify_flags & DPA_CLS_HM_FWD_MOD_ETH_MACSA) {
+ if (pfwd_hm->fwd_params.out_if_type ==
+ DPA_CLS_HM_IF_TYPE_PPPoE) {
+ memcpy(pfwd_hm->fwd_params.pppoe.l2.macsa,
+ new_fwd_params->pppoe.l2.macsa,
+ ETH_ALEN);
+ update[0] = true;
+ }
+
+ if (pfwd_hm->fwd_params.out_if_type ==
+ DPA_CLS_HM_IF_TYPE_ETHERNET) {
+ memcpy(pfwd_hm->fwd_params.eth.macsa,
+ new_fwd_params->eth.macsa,
+ ETH_ALEN);
+ update[0] = true;
+ }
+ }
+
+ if (modify_flags & DPA_CLS_HM_FWD_MOD_ETH_MACDA) {
+ if (pfwd_hm->fwd_params.out_if_type ==
+ DPA_CLS_HM_IF_TYPE_PPPoE) {
+ memcpy(pfwd_hm->fwd_params.pppoe.l2.macda,
+ new_fwd_params->pppoe.l2.macda,
+ ETH_ALEN);
+ update[0] = true;
+ }
+
+ if (pfwd_hm->fwd_params.out_if_type ==
+ DPA_CLS_HM_IF_TYPE_ETHERNET) {
+ memcpy(pfwd_hm->fwd_params.eth.macda,
+ new_fwd_params->eth.macda,
+ ETH_ALEN);
+ update[0] = true;
+ }
+ }
+
+ if ((modify_flags & DPA_CLS_HM_FWD_MOD_PPPoE_HEADER) &&
+ (pfwd_hm->fwd_params.out_if_type == DPA_CLS_HM_IF_TYPE_PPPoE)) {
+ update[1] = true;
+ memcpy(&pfwd_hm->fwd_params.pppoe.pppoe_header,
+ &new_fwd_params->pppoe.pppoe_header,
+ sizeof(struct pppoe_header));
+ }
+
+ if ((modify_flags & DPA_CLS_HM_FWD_MOD_PPP_PID) &&
+ (pfwd_hm->fwd_params.out_if_type == DPA_CLS_HM_IF_TYPE_PPP) &&
+ (pfwd_hm->fwd_params.ppp.ppp_pid !=
+ new_fwd_params->ppp.ppp_pid)) {
+ update[0] = true;
+ pfwd_hm->fwd_params.ppp.ppp_pid = new_fwd_params->ppp.ppp_pid;
+ }
+
+ if (pfwd_hm->fwd_params.ip_frag_params.mtu) {
+ if ((modify_flags & DPA_CLS_HM_FWD_MOD_IP_FRAG_MTU) &&
+ (pfwd_hm->fwd_params.ip_frag_params.mtu !=
+ new_fwd_params->ip_frag_params.mtu)) {
+ pfwd_hm->fwd_params.ip_frag_params.mtu =
+ new_fwd_params->ip_frag_params.mtu;
+ update[2] = true;
+ }
+
+ if ((modify_flags & DPA_CLS_HM_FWD_MOD_IP_FRAG_SCRATCH_BPID) &&
+ (pfwd_hm->fwd_params.ip_frag_params.scratch_bpid !=
+ new_fwd_params->ip_frag_params.scratch_bpid)) {
+ pfwd_hm->fwd_params.ip_frag_params.scratch_bpid =
+ new_fwd_params->ip_frag_params.scratch_bpid;
+ update[2] = true;
+ }
+
+ if ((modify_flags & DPA_CLS_HM_FWD_MOD_IP_FRAG_DF_ACTION) &&
+ (pfwd_hm->fwd_params.ip_frag_params.df_action !=
+ new_fwd_params->ip_frag_params.df_action)) {
+ pfwd_hm->fwd_params.ip_frag_params.df_action =
+ new_fwd_params->ip_frag_params.df_action;
+ update[2] = true;
+ }
+ }
+
+ if (update[0] || update[1] || update[2]) {
+ ret = fwd_hm_update_params(pfwd_hm);
+ if (ret == 0) {
+ t_FmPcdManipParams new_hm_node_params;
+
+ for (i = 0; i < 3; i++) {
+ if (!update[i])
+ continue;
+
+ hm_node = pfwd_hm->hm_node[i];
+ memcpy(&new_hm_node_params,
+ &hm_node->params,
+ sizeof(t_FmPcdManipParams));
+ /*
+ * Must make sure that h_NextManip is NULL
+ * before calling FM_PCD_ManipNodeReplace
+ */
+ new_hm_node_params.h_NextManip = NULL;
+ error = FM_PCD_ManipNodeReplace(hm_node->node,
+ &new_hm_node_params);
+ if (error != E_OK) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&pfwd_hm->access);
+ log_err("FMan driver call failed - "
+ "FM_PCD_ManipNodeReplace, "
+ "while trying to modify "
+ "hmd=%d, manip node "
+ "handle=0x%p (node #%d).\n",
+ hmd, hm_node->node, i);
+ return -EBUSY;
+ }
+ }
+ }
+ }
+
+ release_desc_table(&hm_array);
+ mutex_unlock(&pfwd_hm->access);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+EXPORT_SYMBOL(dpa_classif_modify_fwd_hm);
+
+int dpa_classif_set_remove_hm(const struct dpa_cls_hm_remove_params
+ *remove_params, int next_hmd, int *hmd, bool chain_head,
+ const struct dpa_cls_hm_remove_resources *res)
+{
+ int err;
+ struct dpa_cls_hm *premove_hm, *pcurrent;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ /* Parameters sanity checks: */
+ if (!remove_params) {
+ log_err("\"remove_params\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+ if (!hmd) {
+ log_err("\"hmd\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ *hmd = DPA_OFFLD_DESC_NONE;
+
+ err = remove_hm_check_params(remove_params);
+ if (err < 0) {
+ log_err("Invalid remove HM parameters.\n");
+ return err;
+ }
+
+ err = create_new_hm_op(hmd, next_hmd);
+ if (err < 0) {
+ log_err("Failed to create remove HM op.\n");
+ return err;
+ }
+
+ premove_hm = (struct dpa_cls_hm *) hm_array.object[*hmd];
+
+ premove_hm->type = DPA_CLS_HM_TYPE_REMOVE;
+ premove_hm->chain_head = chain_head;
+
+ /* Copy the remove HM parameters locally */
+ memcpy(&premove_hm->remove_params, remove_params,
+ sizeof(*remove_params));
+
+ err = remove_hm_prepare_nodes(premove_hm, res);
+ if (err < 0) {
+ log_err("Failed to acquire necessary HM nodes.\n");
+ goto remove_hm_error;
+ }
+
+ err = remove_hm_update_params(premove_hm);
+ if (err < 0) {
+ log_err("Failed to update low level header manipulation "
+ "parameters.\n");
+ goto remove_hm_error;
+ }
+
+ if (chain_head) {
+ err = init_hm_chain(premove_hm->remove_params.fm_pcd,
+ premove_hm->hm_chain,
+ premove_hm->hm_chain->next);
+ if (err < 0)
+ log_err("Failed to initialize low level HM chain.\n");
+ }
+
+ /* Release the high level HM op chain */
+ RELEASE_HM_OP_CHAIN(premove_hm);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+
+remove_hm_error:
+
+ /* Release the high level HM op chain */
+ RELEASE_HM_OP_CHAIN(premove_hm);
+
+ lock_desc_table(&hm_array);
+ remove_hm_op(*hmd);
+ release_desc_table(&hm_array);
+
+ *hmd = DPA_OFFLD_DESC_NONE;
+
+ return err;
+}
+EXPORT_SYMBOL(dpa_classif_set_remove_hm);
+
+static int remove_hm_prepare_nodes(struct dpa_cls_hm *premove_hm,
+ const struct dpa_cls_hm_remove_resources *res)
+{
+ struct dpa_cls_hm_node *hm_node;
+ void * const *phm_nodes;
+ int err = 0;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!premove_hm);
+
+ premove_hm->num_nodes = 1;
+
+ if (res) { /* Import HM nodes */
+ phm_nodes = &res->remove_node;
+
+ err = import_hm_nodes_to_chain(phm_nodes,
+ premove_hm->num_nodes,
+ premove_hm);
+ } else { /* Create HM nodes */
+ hm_node = kzalloc(sizeof(*hm_node), GFP_KERNEL);
+ if (!hm_node) {
+ log_err("Not enough memory for header manip nodes.\n");
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&hm_node->list_node);
+ premove_hm->hm_node[0] = hm_node;
+
+ add_local_hm_nodes_to_chain(premove_hm);
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+}
+
+static int remove_hm_update_params(struct dpa_cls_hm *premove_hm)
+{
+ struct dpa_cls_hm_node *hm_node;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!premove_hm);
+ BUG_ON(premove_hm->num_nodes != 1);
+ BUG_ON(!premove_hm->hm_node[0]);
+
+ hm_node = premove_hm->hm_node[0];
+
+ hm_node->params.type = e_FM_PCD_MANIP_HDR;
+ hm_node->params.u.hdr.rmv = TRUE;
+ hm_node->params.u.hdr.dontParseAfterManip = TRUE;
+
+ switch (premove_hm->remove_params.type) {
+ case DPA_CLS_HM_REMOVE_ETHERNET:
+ hm_node->params.u.hdr.rmvParams.type =
+ e_FM_PCD_MANIP_RMV_BY_HDR;
+ hm_node->params.u.hdr.rmvParams.u.byHdr.type =
+ e_FM_PCD_MANIP_RMV_BY_HDR_SPECIFIC_L2;
+ hm_node->params.u.hdr.rmvParams.u.byHdr.u.specificL2 =
+ e_FM_PCD_MANIP_HDR_RMV_ETHERNET;
+ break;
+ case DPA_CLS_HM_REMOVE_PPP:
+ hm_node->params.u.hdr.rmvParams.type =
+ e_FM_PCD_MANIP_RMV_GENERIC;
+ hm_node->params.u.hdr.rmvParams.u.generic.offset =
+ PPP_HEADER_OFFSET;
+ hm_node->params.u.hdr.rmvParams.u.generic.size =
+ PPP_HEADER_SIZE;
+ break;
+ case DPA_CLS_HM_REMOVE_CUSTOM:
+ hm_node->params.u.hdr.rmvParams.type =
+ e_FM_PCD_MANIP_RMV_GENERIC;
+ hm_node->params.u.hdr.rmvParams.u.generic.offset =
+ premove_hm->remove_params.custom.offset;
+ hm_node->params.u.hdr.rmvParams.u.generic.size =
+ premove_hm->remove_params.custom.size;
+ break;
+ default:
+ /* Should never get here */
+ BUG_ON(1);
+ break;
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return 0;
+}
+
+int dpa_classif_modify_remove_hm(int hmd,
+ const struct dpa_cls_hm_remove_params *new_remove_params,
+ int modify_flags)
+{
+ struct dpa_cls_hm_node *hm_node;
+ struct dpa_cls_hm *premove_hm;
+ bool update = false;
+ t_Error error;
+ int ret = 0;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ if (!modify_flags)
+ /* Nothing to do */
+ return 0;
+
+ /* Parameters sanity checks: */
+ if (!new_remove_params) {
+ log_err("\"new_remove_params\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ lock_desc_table(&hm_array);
+ premove_hm = desc_to_object(&hm_array, hmd);
+ if (!premove_hm) {
+ release_desc_table(&hm_array);
+ log_err("Invalid descriptor (%d).\n", hmd);
+ return -EINVAL;
+ }
+ mutex_lock(&premove_hm->access);
+ /*
+ * Hold the lock on the descriptor table to prevent other runtime
+ * modifications of header manipulations until we're finished. The FMan
+ * driver doesn't allow parallel modification of HM nodes when they
+ * belong to the same PCD.
+ */
+
+ if (premove_hm->type != DPA_CLS_HM_TYPE_REMOVE) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&premove_hm->access);
+ log_err("hmd=%d is not an REMOVE type header manip.\n", hmd);
+ return -EINVAL;
+ }
+
+ if ((modify_flags & DPA_CLS_HM_RM_MOD_TYPE) &&
+ (new_remove_params->type != premove_hm->remove_params.type)) {
+ update = true;
+ premove_hm->remove_params.type = new_remove_params->type;
+ }
+
+ if ((modify_flags & DPA_CLS_HM_RM_MOD_CUSTOM_OFFSET) &&
+ (new_remove_params->custom.offset !=
+ premove_hm->remove_params.custom.offset)) {
+ update = true;
+ premove_hm->remove_params.custom.offset =
+ new_remove_params->custom.offset;
+ }
+
+ if ((modify_flags & DPA_CLS_HM_RM_MOD_CUSTOM_SIZE) &&
+ (new_remove_params->custom.size !=
+ premove_hm->remove_params.custom.size)) {
+ update = true;
+ premove_hm->remove_params.custom.size =
+ new_remove_params->custom.size;
+ }
+
+ if (update) {
+ ret = remove_hm_update_params(premove_hm);
+ if (ret == 0) {
+ t_FmPcdManipParams new_hm_node_params;
+
+ hm_node = premove_hm->hm_node[0];
+
+ /*
+ * Have to make a copy of the manip node params because
+ * ManipNodeReplace does not accept h_NextManip != NULL.
+ */
+ memcpy(&new_hm_node_params, &hm_node->params,
+ sizeof(new_hm_node_params));
+ new_hm_node_params.h_NextManip = NULL;
+ error = FM_PCD_ManipNodeReplace(hm_node->node,
+ &new_hm_node_params);
+ if (error != E_OK) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&premove_hm->access);
+ log_err("FMan driver call failed - "
+ "FM_PCD_ManipNodeReplace, while trying "
+ "to modify hmd=%d, manip node "
+ "handle=0x%p.\n", hmd, hm_node->node);
+ return -EBUSY;
+ }
+ }
+ }
+
+ release_desc_table(&hm_array);
+ mutex_unlock(&premove_hm->access);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+EXPORT_SYMBOL(dpa_classif_modify_remove_hm);
+
+int dpa_classif_set_insert_hm(const struct dpa_cls_hm_insert_params
+ *insert_params, int next_hmd, int *hmd, bool chain_head,
+ const struct dpa_cls_hm_insert_resources *res)
+{
+ int err;
+ struct dpa_cls_hm *pinsert_hm, *pcurrent;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ /* Parameters sanity checks: */
+ if (!insert_params) {
+ log_err("\"insert_params\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+ if (!hmd) {
+ log_err("\"hmd\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ *hmd = DPA_OFFLD_DESC_NONE;
+
+ err = insert_hm_check_params(insert_params);
+ if (err < 0) {
+ log_err("Invalid insert HM parameters.\n");
+ return err;
+ }
+
+ err = create_new_hm_op(hmd, next_hmd);
+ if (err < 0) {
+ log_err("Failed to create insert HM op.\n");
+ return err;
+ }
+
+ pinsert_hm = (struct dpa_cls_hm *) hm_array.object[*hmd];
+
+ pinsert_hm->type = DPA_CLS_HM_TYPE_INSERT;
+ pinsert_hm->chain_head = chain_head;
+
+ /* Copy the insert HM parameters locally */
+ memcpy(&pinsert_hm->insert_params, insert_params,
+ sizeof(*insert_params));
+
+ err = insert_hm_prepare_nodes(pinsert_hm, res);
+ if (err < 0) {
+ log_err("Failed to acquire necessary HM nodes.\n");
+ goto insert_hm_error;
+ }
+
+ err = insert_hm_update_params(pinsert_hm);
+ if (err < 0) {
+ log_err("Failed to update low level header manipulation "
+ "parameters.\n");
+ goto insert_hm_error;
+ }
+
+ if (chain_head) {
+ err = init_hm_chain(pinsert_hm->insert_params.fm_pcd,
+ pinsert_hm->hm_chain,
+ pinsert_hm->hm_chain->next);
+ if (err < 0)
+ log_err("Failed to initialize low level HM chain.\n");
+ }
+
+ /* Release the high level HM op chain */
+ RELEASE_HM_OP_CHAIN(pinsert_hm);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+
+insert_hm_error:
+
+ /* Release the high level HM op chain */
+ RELEASE_HM_OP_CHAIN(pinsert_hm);
+
+ lock_desc_table(&hm_array);
+ remove_hm_op(*hmd);
+ release_desc_table(&hm_array);
+
+ *hmd = DPA_OFFLD_DESC_NONE;
+
+ return err;
+}
+EXPORT_SYMBOL(dpa_classif_set_insert_hm);
+
+static int insert_hm_prepare_nodes(struct dpa_cls_hm *pinsert_hm,
+ const struct dpa_cls_hm_insert_resources *res)
+{
+ struct dpa_cls_hm_node *hm_node;
+ void * const *phm_nodes;
+ int err = 0;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!pinsert_hm);
+
+ pinsert_hm->num_nodes = 1;
+
+ if (res) { /* Import HM nodes */
+ phm_nodes = &res->insert_node;
+
+ err = import_hm_nodes_to_chain(phm_nodes,
+ pinsert_hm->num_nodes,
+ pinsert_hm);
+ } else { /* Create HM nodes */
+ hm_node = kzalloc(sizeof(*hm_node), GFP_KERNEL);
+ if (!hm_node) {
+ log_err("Not enough memory for header manip nodes.\n");
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&hm_node->list_node);
+ pinsert_hm->hm_node[0] = hm_node;
+
+ add_local_hm_nodes_to_chain(pinsert_hm);
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+}
+
+static int insert_hm_update_params(struct dpa_cls_hm *pinsert_hm)
+{
+ uint8_t size = 0;
+ uint8_t offset = 0;
+ uint8_t *pdata = NULL;
+ struct dpa_cls_hm_node *hm_node;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!pinsert_hm);
+ BUG_ON(pinsert_hm->num_nodes != 1);
+ BUG_ON(!pinsert_hm->hm_node[0]);
+
+ hm_node = pinsert_hm->hm_node[0];
+
+ hm_node->params.type = e_FM_PCD_MANIP_HDR;
+ hm_node->params.u.hdr.insrt = TRUE;
+ hm_node->params.u.hdr.insrtParams.type = e_FM_PCD_MANIP_INSRT_GENERIC;
+ hm_node->params.u.hdr.dontParseAfterManip = TRUE;
+
+ switch (pinsert_hm->insert_params.type) {
+ case DPA_CLS_HM_INSERT_ETHERNET:
+ size = (uint8_t) (sizeof(struct ethhdr) +
+ (pinsert_hm->insert_params.eth.num_tags *
+ sizeof(struct vlan_header)));
+ pdata = kzalloc(size, GFP_KERNEL);
+ if (!pdata) {
+ log_err("Not enough memory for insert HM.\n");
+ return -ENOMEM;
+ }
+
+ if (pinsert_hm->insert_params.eth.num_tags) {
+ /* Copy Ethernet header data except the EtherType */
+ memcpy(pdata,
+ &pinsert_hm->insert_params.eth.eth_header,
+ sizeof(struct ethhdr) - ETHERTYPE_SIZE);
+ offset += (uint8_t)(sizeof(struct ethhdr) -
+ ETHERTYPE_SIZE);
+ /* Copy the VLAN tags */
+ memcpy(&pdata[offset],
+ &pinsert_hm->insert_params.eth.qtag,
+ pinsert_hm->insert_params.eth.num_tags *
+ sizeof(struct vlan_header));
+ offset += (uint8_t) (pinsert_hm->insert_params.eth.
+ num_tags * sizeof(struct vlan_header));
+ /* Copy the EtherType */
+ memcpy(&pdata[offset],
+ &pinsert_hm->insert_params.eth.eth_header.h_proto,
+ ETHERTYPE_SIZE);
+ offset = 0;
+ } else
+ /* Copy the entire Ethernet header */
+ memcpy(pdata,
+ &pinsert_hm->insert_params.eth.eth_header,
+ sizeof(struct ethhdr));
+ break;
+ case DPA_CLS_HM_INSERT_PPP:
+ size = PPP_HEADER_SIZE;
+ pdata = kzalloc(size, GFP_KERNEL);
+ if (!pdata) {
+ log_err("Not enough memory for insert HM.\n");
+ return -ENOMEM;
+ }
+
+ /* Copy the PPP PID */
+ memcpy(pdata, &pinsert_hm->insert_params.ppp_pid,
+ PPP_HEADER_SIZE);
+ break;
+ case DPA_CLS_HM_INSERT_CUSTOM:
+ size = pinsert_hm->insert_params.custom.size;
+ pdata = kzalloc(size, GFP_KERNEL);
+ if (!pdata) {
+ log_err("Not enough memory for insert HM.\n");
+ return -ENOMEM;
+ }
+ memcpy(pdata, pinsert_hm->insert_params.custom.data, size);
+ offset = pinsert_hm->insert_params.custom.offset;
+ break;
+ default:
+ /* Should never get here */
+ BUG_ON(1);
+ break;
+ }
+
+ kfree(hm_node->params.u.hdr.insrtParams.u.generic.p_Data);
+
+ hm_node->params.u.hdr.insrtParams.u.generic.offset = offset;
+ hm_node->params.u.hdr.insrtParams.u.generic.size = size;
+ hm_node->params.u.hdr.insrtParams.u.generic.p_Data = pdata;
+ hm_node->params.u.hdr.insrtParams.u.generic.replace = FALSE;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return 0;
+}
+
+int dpa_classif_modify_insert_hm(int hmd,
+ const struct dpa_cls_hm_insert_params *new_insert_params,
+ int modify_flags)
+{
+ struct dpa_cls_hm_node *hm_node;
+ struct dpa_cls_hm *pinsert_hm;
+ bool update = false;
+ t_Error error;
+ int ret = 0;
+ int mask;
+ uint8_t *pdata;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ if (!modify_flags)
+ /* Nothing to do */
+ return 0;
+
+ /* Parameters sanity checks: */
+ if (!new_insert_params) {
+ log_err("\"new_insert_params\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ lock_desc_table(&hm_array);
+ pinsert_hm = desc_to_object(&hm_array, hmd);
+ if (!pinsert_hm) {
+ release_desc_table(&hm_array);
+ log_err("Invalid descriptor (%d).\n", hmd);
+ return -EINVAL;
+ }
+ mutex_lock(&pinsert_hm->access);
+ /*
+ * Hold the lock on the descriptor table to prevent other runtime
+ * modifications of header manipulations until we're finished. The FMan
+ * driver doesn't allow parallel modification of HM nodes when they
+ * belong to the same PCD.
+ */
+
+ if (pinsert_hm->type != DPA_CLS_HM_TYPE_INSERT) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&pinsert_hm->access);
+ log_err("hmd=%d is not an INSERT type header manip.\n", hmd);
+ return -EINVAL;
+ }
+
+ mask = DPA_CLS_HM_INS_MOD_ETH_HEADER |
+ DPA_CLS_HM_INS_MOD_QTAGS |
+ DPA_CLS_HM_INS_MOD_PPPoE_HEADER;
+ if ((modify_flags & mask) && (pinsert_hm->insert_params.type !=
+ DPA_CLS_HM_INSERT_ETHERNET)) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&pinsert_hm->access);
+ log_err("modify_flags=0x%x doesn't work on hmd=%d. It only "
+ "works on INSERT ETHERNET header manipulations.\n",
+ modify_flags, hmd);
+ return -EINVAL;
+ }
+
+ mask = DPA_CLS_HM_INS_MOD_CUSTOM_OFFSET |
+ DPA_CLS_HM_INS_MOD_CUSTOM_DATA;
+ if ((modify_flags & mask) && (pinsert_hm->insert_params.type !=
+ DPA_CLS_HM_INSERT_CUSTOM)) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&pinsert_hm->access);
+ log_err("modify_flags=0x%x doesn't work on hmd=%d. It only "
+ "works on CUSTOM INSERT header manipulations.\n",
+ modify_flags, hmd);
+ return -EINVAL;
+ }
+
+ if ((modify_flags & DPA_CLS_HM_INS_MOD_PPP_PID) &&
+ (pinsert_hm->insert_params.ppp_pid !=
+ new_insert_params->ppp_pid)) {
+ if (pinsert_hm->insert_params.type !=
+ DPA_CLS_HM_INSERT_PPP) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&pinsert_hm->access);
+ log_err("modify_flags=0x%x doesn't work on hmd=%d. It "
+ "only works on INSERT PPP header "
+ "manipulations.\n", modify_flags, hmd);
+ return -EINVAL;
+ }
+
+ update = true;
+ pinsert_hm->insert_params.ppp_pid = new_insert_params->ppp_pid;
+ }
+
+ if ((modify_flags & DPA_CLS_HM_INS_MOD_CUSTOM_OFFSET) &&
+ (pinsert_hm->insert_params.custom.offset !=
+ new_insert_params->custom.offset)) {
+ update = true;
+ pinsert_hm->insert_params.custom.offset =
+ new_insert_params->custom.offset;
+ }
+
+ if ((modify_flags & DPA_CLS_HM_INS_MOD_CUSTOM_OFFSET) &&
+ (pinsert_hm->insert_params.custom.offset !=
+ new_insert_params->custom.offset)) {
+ update = true;
+ pinsert_hm->insert_params.custom.offset =
+ new_insert_params->custom.offset;
+ }
+
+ if (modify_flags & DPA_CLS_HM_INS_MOD_CUSTOM_DATA) {
+ update = true;
+ pdata = kzalloc(new_insert_params->custom.size, GFP_KERNEL);
+ if (!pdata) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&pinsert_hm->access);
+ log_err("Not enough memory to adjust custom insert "
+ "header manipulation.\n");
+ return -ENOMEM;
+ }
+ /* Replace old data buffer with the new data buffer */
+ kfree(pinsert_hm->insert_params.custom.data);
+ pinsert_hm->insert_params.custom.data = pdata;
+
+ pinsert_hm->insert_params.custom.size =
+ new_insert_params->custom.size;
+ memcpy(pdata, new_insert_params->custom.data,
+ new_insert_params->custom.size);
+ }
+
+ if (modify_flags & DPA_CLS_HM_INS_MOD_QTAGS) {
+ update = true;
+ pinsert_hm->insert_params.eth.num_tags =
+ new_insert_params->eth.num_tags;
+ memcpy(pinsert_hm->insert_params.eth.qtag,
+ new_insert_params->eth.qtag,
+ pinsert_hm->insert_params.eth.num_tags *
+ sizeof(struct vlan_header));
+ }
+
+ if (modify_flags & DPA_CLS_HM_INS_MOD_ETH_HEADER) {
+ update = true;
+ memcpy(&pinsert_hm->insert_params.eth.eth_header,
+ &new_insert_params->eth.eth_header,
+ sizeof(struct ethhdr));
+ }
+
+ if (update) {
+ ret = insert_hm_update_params(pinsert_hm);
+ if (ret == 0) {
+ t_FmPcdManipParams new_hm_node_params;
+
+ hm_node = pinsert_hm->hm_node[0];
+
+ /*
+ * Have to make a copy of the manip node params because
+ * ManipNodeReplace does not accept h_NextManip != NULL.
+ */
+ memcpy(&new_hm_node_params, &hm_node->params,
+ sizeof(new_hm_node_params));
+ new_hm_node_params.h_NextManip = NULL;
+ error = FM_PCD_ManipNodeReplace(hm_node->node,
+ &new_hm_node_params);
+ if (error != E_OK) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&pinsert_hm->access);
+ log_err("FMan driver call failed - "
+ "FM_PCD_ManipNodeReplace, while trying "
+ "to modify hmd=%d, manip node "
+ "handle=0x%p.\n", hmd, hm_node->node);
+ return -EBUSY;
+ }
+ }
+ }
+
+ release_desc_table(&hm_array);
+ mutex_unlock(&pinsert_hm->access);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+EXPORT_SYMBOL(dpa_classif_modify_insert_hm);
+
+int dpa_classif_set_update_hm(const struct dpa_cls_hm_update_params
+ *update_params, int next_hmd, int *hmd, bool chain_head,
+ const struct dpa_cls_hm_update_resources *res)
+{
+ int err;
+ struct dpa_cls_hm *pupdate_hm, *pcurrent;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ /* Parameters sanity checks: */
+ if (!update_params) {
+ log_err("\"update_params\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+ if (!hmd) {
+ log_err("\"hmd\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ *hmd = DPA_OFFLD_DESC_NONE;
+
+ err = update_hm_check_params(update_params);
+ if (err < 0) {
+ log_err("Invalid update HM parameters.\n");
+ return err;
+ }
+
+ err = create_new_hm_op(hmd, next_hmd);
+ if (err < 0) {
+ log_err("Failed to create update HM op.\n");
+ return err;
+ }
+
+ pupdate_hm = (struct dpa_cls_hm *) hm_array.object[*hmd];
+
+ pupdate_hm->type = DPA_CLS_HM_TYPE_UPDATE;
+ pupdate_hm->chain_head = chain_head;
+
+ /* Copy the update HM parameters locally */
+ memcpy(&pupdate_hm->update_params, update_params,
+ sizeof(*update_params));
+
+ err = update_hm_prepare_nodes(pupdate_hm, res);
+ if (err < 0) {
+ log_err("Failed to acquire necessary HM nodes.\n");
+ goto update_hm_error;
+ }
+
+ err = update_hm_update_params(pupdate_hm);
+ if (err < 0) {
+ log_err("Failed to update low level header manipulation "
+ "parameters.\n");
+ goto update_hm_error;
+ }
+
+ if (chain_head) {
+ err = init_hm_chain(pupdate_hm->update_params.fm_pcd,
+ pupdate_hm->hm_chain,
+ pupdate_hm->hm_chain->next);
+ if (err < 0)
+ log_err("Failed to initialize low level HM chain.\n");
+ }
+
+ /* Release the high level HM op chain */
+ RELEASE_HM_OP_CHAIN(pupdate_hm);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+
+update_hm_error:
+
+ /* Release the high level HM op chain */
+ RELEASE_HM_OP_CHAIN(pupdate_hm);
+
+ lock_desc_table(&hm_array);
+ remove_hm_op(*hmd);
+ release_desc_table(&hm_array);
+
+ *hmd = DPA_OFFLD_DESC_NONE;
+
+ return err;
+}
+EXPORT_SYMBOL(dpa_classif_set_update_hm);
+
+static int update_hm_prepare_nodes(struct dpa_cls_hm *pupdate_hm,
+ const struct dpa_cls_hm_update_resources *res)
+{
+ struct dpa_cls_hm_node *hm_node = NULL;
+ void * const *phm_nodes;
+ struct dpa_cls_hm *pnext_hm = NULL;
+ int update_ops, replace_ops;
+ int err = 0;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!pupdate_hm);
+
+ pupdate_hm->num_nodes = 2;
+
+ if (res) { /* Import HM nodes */
+ phm_nodes = &res->update_node;
+
+ return import_hm_nodes_to_chain(phm_nodes,
+ pupdate_hm->num_nodes,
+ pupdate_hm);
+ }
+
+ update_ops = DPA_CLS_HM_UPDATE_IPv4_UPDATE |
+ DPA_CLS_HM_UPDATE_IPv6_UPDATE |
+ DPA_CLS_HM_UPDATE_UDP_TCP_UPDATE;
+
+ replace_ops = DPA_CLS_HM_REPLACE_IPv4_BY_IPv6 |
+ DPA_CLS_HM_REPLACE_IPv6_BY_IPv4;
+
+ if ((pupdate_hm->update_params.op_flags & update_ops) ||
+ (pupdate_hm->update_params.op_flags & replace_ops)) {
+ /* Create HM nodes */
+ /* Check if we can attach to an existing update node */
+ if (!list_empty(&pupdate_hm->list_node)) {
+ pnext_hm = list_entry(pupdate_hm->list_node.next,
+ struct dpa_cls_hm,
+ list_node);
+
+ if (pupdate_hm->update_params.op_flags &
+ DPA_CLS_HM_UPDATE_IPv4_UPDATE)
+ /*
+ * See if there is any other IPv4 update node
+ * in this chain
+ */
+ hm_node = find_compatible_hm_node(
+ DPA_CLS_HM_NODE_IPv4_HDR_UPDATE,
+ pnext_hm->hm_chain);
+
+ if (pupdate_hm->update_params.op_flags &
+ DPA_CLS_HM_UPDATE_IPv6_UPDATE)
+ /*
+ * See if there is any other IPv6 update node
+ * in this chain
+ */
+ hm_node = find_compatible_hm_node(
+ DPA_CLS_HM_NODE_IPv6_HDR_UPDATE,
+ pnext_hm->hm_chain);
+
+ if (pupdate_hm->update_params.op_flags &
+ DPA_CLS_HM_UPDATE_UDP_TCP_UPDATE)
+ /*
+ * See if there is any other TCP/UDP header
+ * update node in this chain
+ */
+ hm_node = find_compatible_hm_node(
+ DPA_CLS_HM_NODE_TCPUDP_HDR_UPDATE,
+ pnext_hm->hm_chain);
+ }
+
+ /*
+ * If no compatible HM node was found for the header update
+ * operations...
+ */
+ if (!hm_node) {
+ /* Create a header manip node for this update: */
+ hm_node = kzalloc(sizeof(*hm_node), GFP_KERNEL);
+
+ if (!hm_node) {
+ log_err("No more memory for header manip "
+ "nodes.\n");
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&hm_node->list_node);
+ }
+
+ pupdate_hm->hm_node[0] = hm_node;
+ }
+
+ if (pupdate_hm->update_params.ip_frag_params.mtu) {
+ /* IP fragmentation option is enabled */
+ /* Create a header manip node: */
+ hm_node = kzalloc(sizeof(*hm_node), GFP_KERNEL);
+ if (!hm_node) {
+ log_err("No more memory for header manip nodes.\n");
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&hm_node->list_node);
+ pupdate_hm->hm_node[1] = hm_node;
+ }
+
+ add_local_hm_nodes_to_chain(pupdate_hm);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+}
+
+static int update_hm_update_params(struct dpa_cls_hm *pupdate_hm)
+{
+ struct dpa_cls_hm_node *hm_node;
+ int update_ops, replace_ops;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!pupdate_hm);
+ BUG_ON(pupdate_hm->num_nodes < 1);
+
+ update_ops = DPA_CLS_HM_UPDATE_IPv4_UPDATE |
+ DPA_CLS_HM_UPDATE_IPv6_UPDATE |
+ DPA_CLS_HM_UPDATE_UDP_TCP_UPDATE;
+
+ replace_ops = DPA_CLS_HM_REPLACE_IPv4_BY_IPv6 |
+ DPA_CLS_HM_REPLACE_IPv6_BY_IPv4;
+
+ hm_node = pupdate_hm->hm_node[0];
+
+ if (pupdate_hm->update_params.op_flags & update_ops) {
+ hm_node->params.type = e_FM_PCD_MANIP_HDR;
+ hm_node->params.u.hdr.fieldUpdate = TRUE;
+ hm_node->params.u.hdr.dontParseAfterManip = TRUE;
+
+ if (pupdate_hm->update_params.op_flags &
+ DPA_CLS_HM_UPDATE_IPv4_UPDATE) {
+ hm_node->params.u.hdr.fieldUpdateParams.type =
+ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV4;
+
+ if (pupdate_hm->update_params.update.l3.field_flags &
+ DPA_CLS_HM_IP_UPDATE_IPSA) {
+ hm_node->params.u.hdr.fieldUpdateParams.u.ipv4.
+ validUpdates |=
+ HDR_MANIP_IPV4_SRC;
+ hm_node->params.u.hdr.fieldUpdateParams.u.ipv4.
+ src =
+ pupdate_hm->update_params.update.l3.
+ ipsa.addr.ipv4.word;
+ }
+
+ if (pupdate_hm->update_params.update.l3.field_flags &
+ DPA_CLS_HM_IP_UPDATE_IPDA) {
+ hm_node->params.u.hdr.fieldUpdateParams.u.ipv4.
+ validUpdates |=
+ HDR_MANIP_IPV4_DST;
+ hm_node->params.u.hdr.fieldUpdateParams.u.ipv4.
+ dst =
+ pupdate_hm->update_params.update.l3.
+ ipda.addr.ipv4.word;
+ }
+
+ if (pupdate_hm->update_params.update.l3.field_flags &
+ DPA_CLS_HM_IP_UPDATE_TOS_TC) {
+ hm_node->params.u.hdr.fieldUpdateParams.u.ipv4.
+ validUpdates |=
+ HDR_MANIP_IPV4_TOS;
+ hm_node->params.u.hdr.fieldUpdateParams.u.ipv4.
+ tos =
+ pupdate_hm->update_params.update.l3.
+ tos_tc;
+ }
+
+ if (pupdate_hm->update_params.update.l3.field_flags &
+ DPA_CLS_HM_IP_UPDATE_ID) {
+ hm_node->params.u.hdr.fieldUpdateParams.u.ipv4.
+ validUpdates |=
+ HDR_MANIP_IPV4_ID;
+ hm_node->params.u.hdr.fieldUpdateParams.u.ipv4.
+ id =
+ pupdate_hm->update_params.update.l3.
+ initial_id;
+ }
+
+ if (pupdate_hm->update_params.update.l3.field_flags &
+ DPA_CLS_HM_IP_UPDATE_TTL_HOPL_DECREMENT)
+ hm_node->params.u.hdr.fieldUpdateParams.u.ipv4.
+ validUpdates |=
+ HDR_MANIP_IPV4_TTL;
+ }
+
+ if (pupdate_hm->update_params.op_flags &
+ DPA_CLS_HM_UPDATE_IPv6_UPDATE) {
+ hm_node->params.u.hdr.fieldUpdateParams.type =
+ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_IPV6;
+
+ if (pupdate_hm->update_params.update.l3.field_flags &
+ DPA_CLS_HM_IP_UPDATE_IPSA) {
+ hm_node->params.u.hdr.fieldUpdateParams.u.ipv6.
+ validUpdates |=
+ HDR_MANIP_IPV6_SRC;
+ memcpy(hm_node->params.u.hdr.fieldUpdateParams.
+ u.ipv6.src, pupdate_hm->update_params.
+ update.l3.ipsa.addr.ipv6.byte,
+ DPA_OFFLD_IPv6_ADDR_LEN_BYTES);
+ }
+
+ if (pupdate_hm->update_params.update.l3.field_flags &
+ DPA_CLS_HM_IP_UPDATE_IPDA) {
+ hm_node->params.u.hdr.fieldUpdateParams.u.ipv4.
+ validUpdates |=
+ HDR_MANIP_IPV6_DST;
+ memcpy(hm_node->params.u.hdr.fieldUpdateParams.
+ u.ipv6.dst, pupdate_hm->update_params.
+ update.l3.ipda.addr.ipv6.byte,
+ DPA_OFFLD_IPv6_ADDR_LEN_BYTES);
+ }
+
+ if (pupdate_hm->update_params.update.l3.field_flags &
+ DPA_CLS_HM_IP_UPDATE_TOS_TC) {
+ hm_node->params.u.hdr.fieldUpdateParams.u.ipv6.
+ validUpdates |=
+ HDR_MANIP_IPV6_TC;
+ hm_node->params.u.hdr.fieldUpdateParams.u.ipv6.
+ trafficClass =
+ pupdate_hm->update_params.update.l3.
+ tos_tc;
+ }
+
+ if (pupdate_hm->update_params.update.l3.field_flags &
+ DPA_CLS_HM_IP_UPDATE_TTL_HOPL_DECREMENT)
+ hm_node->params.u.hdr.fieldUpdateParams.u.ipv6.
+ validUpdates |=
+ HDR_MANIP_IPV6_HL;
+ }
+
+ if (pupdate_hm->update_params.op_flags &
+ DPA_CLS_HM_UPDATE_UDP_TCP_UPDATE) {
+ hm_node->params.u.hdr.fieldUpdateParams.type =
+ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_TCP_UDP;
+
+ if (pupdate_hm->update_params.update.l4.field_flags &
+ DPA_CLS_HM_L4_UPDATE_SPORT) {
+ hm_node->params.u.hdr.fieldUpdateParams.u.
+ tcpUdp.validUpdates |=
+ HDR_MANIP_TCP_UDP_SRC;
+ hm_node->params.u.hdr.fieldUpdateParams.u.
+ tcpUdp.src =
+ pupdate_hm->update_params.update.l4.
+ sport;
+ }
+
+ if (pupdate_hm->update_params.update.l4.field_flags &
+ DPA_CLS_HM_L4_UPDATE_DPORT) {
+ hm_node->params.u.hdr.fieldUpdateParams.u.
+ tcpUdp.validUpdates |=
+ HDR_MANIP_TCP_UDP_DST;
+ hm_node->params.u.hdr.fieldUpdateParams.u.
+ tcpUdp.dst =
+ pupdate_hm->update_params.update.l4.
+ dport;
+ }
+
+ if (pupdate_hm->update_params.update.l4.field_flags &
+ DPA_CLS_HM_L4_UPDATE_CALCULATE_CKSUM) {
+ hm_node->params.u.hdr.fieldUpdateParams.u.
+ tcpUdp.validUpdates |=
+ HDR_MANIP_TCP_UDP_CHECKSUM;
+ }
+ }
+ }
+
+ if (pupdate_hm->update_params.op_flags & replace_ops) {
+ hm_node->params.type = e_FM_PCD_MANIP_HDR;
+ hm_node->params.u.hdr.custom = TRUE;
+ hm_node->params.u.hdr.customParams.type =
+ e_FM_PCD_MANIP_HDR_CUSTOM_IP_REPLACE;
+ hm_node->params.u.hdr.dontParseAfterManip = TRUE;
+
+ if (pupdate_hm->update_params.op_flags &
+ DPA_CLS_HM_REPLACE_IPv4_BY_IPv6) {
+
+ hm_node->params.u.hdr.customParams.u.ipHdrReplace.
+ replaceType =
+ e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV4_BY_IPV6;
+ hm_node->params.u.hdr.customParams.u.ipHdrReplace.
+ hdrSize = (uint8_t)sizeof(struct ipv6_header);
+
+ memcpy(hm_node->params.u.hdr.customParams.u.
+ ipHdrReplace.hdr,
+ &pupdate_hm->update_params.replace.new_ipv6_hdr,
+ sizeof(struct ipv6_header));
+ }
+
+ if (pupdate_hm->update_params.op_flags &
+ DPA_CLS_HM_REPLACE_IPv6_BY_IPv4) {
+
+ hm_node->params.u.hdr.customParams.u.ipHdrReplace.
+ replaceType =
+ e_FM_PCD_MANIP_HDR_CUSTOM_REPLACE_IPV6_BY_IPV4;
+ hm_node->params.u.hdr.customParams.u.ipHdrReplace.
+ hdrSize = (uint8_t)sizeof(struct iphdr);
+ memcpy(hm_node->params.u.hdr.customParams.u.
+ ipHdrReplace.hdr,
+ &pupdate_hm->update_params.replace.new_ipv4_hdr.header,
+ sizeof(struct iphdr));
+ if ((pupdate_hm->update_params.replace.new_ipv4_hdr.options_size)
+ && (pupdate_hm->update_params.replace.new_ipv4_hdr.options)) {
+ memcpy(&hm_node->params.u.hdr.customParams.u.ipHdrReplace.
+ hdr[sizeof(struct iphdr)],
+ &pupdate_hm->update_params.replace.new_ipv4_hdr.options,
+ pupdate_hm->update_params.replace.new_ipv4_hdr.options_size);
+ }
+ }
+ }
+
+ hm_node = pupdate_hm->hm_node[1];
+
+ if (pupdate_hm->update_params.ip_frag_params.mtu) {
+ /* IP fragmentation option is enabled */
+ BUG_ON(!hm_node);
+
+ hm_node->params.type = e_FM_PCD_MANIP_FRAG;
+ hm_node->params.u.frag.hdr = HEADER_TYPE_IPv4;
+ hm_node->params.u.frag.u.ipFrag.sizeForFragmentation =
+ pupdate_hm->update_params.ip_frag_params.mtu;
+#if (DPAA_VERSION == 10)
+ hm_node->params.u.frag.u.ipFrag.scratchBpid =
+ pupdate_hm->update_params.ip_frag_params.
+ scratch_bpid;
+#endif /* (DPAA_VERSION == 10) */
+ switch (pupdate_hm->update_params.ip_frag_params.df_action) {
+ case DPA_CLS_HM_DF_ACTION_FRAG_ANYWAY:
+ hm_node->params.u.frag.u.ipFrag.dontFragAction =
+ e_FM_PCD_MANIP_FRAGMENT_PACKET;
+ break;
+ case DPA_CLS_HM_DF_ACTION_DONT_FRAG:
+ hm_node->params.u.frag.u.ipFrag.dontFragAction =
+ e_FM_PCD_MANIP_CONTINUE_WITHOUT_FRAG;
+ break;
+ case DPA_CLS_HM_DF_ACTION_DROP:
+ hm_node->params.u.frag.u.ipFrag.dontFragAction =
+ e_FM_PCD_MANIP_ENQ_TO_ERR_Q_OR_DISCARD_PACKET;
+ break;
+ }
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return 0;
+}
+
+int dpa_classif_modify_update_hm(int hmd,
+ const struct dpa_cls_hm_update_params *new_update_params,
+ int modify_flags)
+{
+ struct dpa_cls_hm_node *hm_node;
+ struct dpa_cls_hm *pupdate_hm;
+ bool update[2] = { false, false };
+ t_Error error;
+ int ret = 0;
+ int ip_update;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ if (!modify_flags)
+ /* Nothing to do */
+ return 0;
+
+ /* Parameters sanity checks: */
+ if (!new_update_params) {
+ log_err("\"new_update_params\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ lock_desc_table(&hm_array);
+ pupdate_hm = desc_to_object(&hm_array, hmd);
+ if (!pupdate_hm) {
+ release_desc_table(&hm_array);
+ log_err("Invalid descriptor (%d).\n", hmd);
+ return -EINVAL;
+ }
+ mutex_lock(&pupdate_hm->access);
+ /*
+ * Hold the lock on the descriptor table to prevent other runtime
+ * modifications of header manipulations until we're finished. The FMan
+ * driver doesn't allow parallel modification of HM nodes when they
+ * belong to the same PCD.
+ */
+
+ if (pupdate_hm->type != DPA_CLS_HM_TYPE_UPDATE) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&pupdate_hm->access);
+ log_err("hmd=%d is not an UPDATE type header manip.\n", hmd);
+ return -EINVAL;
+ }
+
+ if (modify_flags & DPA_CLS_HM_UPDATE_MOD_IPHDR) {
+ if (pupdate_hm->update_params.op_flags &
+ DPA_CLS_HM_REPLACE_IPv4_BY_IPv6) {
+ memcpy(&pupdate_hm->update_params.replace.new_ipv6_hdr,
+ &new_update_params->replace.new_ipv6_hdr,
+ sizeof(struct ipv6_header));
+ } else if (pupdate_hm->update_params.op_flags &
+ DPA_CLS_HM_REPLACE_IPv6_BY_IPv4) {
+ memcpy(&pupdate_hm->update_params.replace.new_ipv4_hdr.
+ header, &new_update_params->replace.
+ new_ipv4_hdr.header, sizeof(struct iphdr));
+ /* Update IPv4 options */
+ kfree(pupdate_hm->update_params.replace.new_ipv4_hdr.
+ options);
+ if (new_update_params->replace.new_ipv4_hdr.
+ options_size) {
+ pupdate_hm->update_params.replace.new_ipv4_hdr.
+ options = kzalloc(new_update_params->
+ replace.new_ipv4_hdr.options_size,
+ GFP_KERNEL);
+ if (!pupdate_hm->update_params.replace.
+ new_ipv4_hdr.options) {
+ pupdate_hm->update_params.replace.
+ new_ipv4_hdr.options_size = 0;
+ release_desc_table(&hm_array);
+ mutex_unlock(&pupdate_hm->access);
+ log_err("Out of memory while modifying "
+ "IPv6 header replace header "
+ "manipulation hmd=%d.\n", hmd);
+ return -EINVAL;
+ }
+ } else
+ pupdate_hm->update_params.replace.new_ipv4_hdr.
+ options = NULL;
+ pupdate_hm->update_params.replace.new_ipv4_hdr.
+ options_size = new_update_params->replace.
+ new_ipv4_hdr.options_size;
+ } else {
+ release_desc_table(&hm_array);
+ mutex_unlock(&pupdate_hm->access);
+ log_err("modify_flags=0x%x doesn't work on hmd=%d. It "
+ "only works on REPLACE header manipulations.\n",
+ modify_flags, hmd);
+ return -EINVAL;
+ }
+ update[0] = true;
+ }
+
+ ip_update = DPA_CLS_HM_UPDATE_IPv4_UPDATE |
+ DPA_CLS_HM_UPDATE_IPv6_UPDATE;
+ if (pupdate_hm->update_params.op_flags & ip_update) {
+ if (modify_flags & DPA_CLS_HM_UPDATE_MOD_SIP) {
+ if (new_update_params->update.l3.ipsa.version !=
+ pupdate_hm->update_params.update.l3.ipsa.
+ version) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&pupdate_hm->access);
+ log_err("New SIP adress version (%d) in UPDATE "
+ "header manipulation hmd=%d cannot be "
+ "different from the old one (%d).\n",
+ new_update_params->update.l3.ipsa.
+ version, hmd, pupdate_hm->
+ update_params.update.l3.ipsa.version);
+ return -EINVAL;
+ }
+ memcpy(&pupdate_hm->update_params.update.l3.ipsa,
+ &new_update_params->update.l3.ipsa,
+ sizeof(struct dpa_offload_ip_address));
+ update[0] = true;
+ }
+
+ if (modify_flags & DPA_CLS_HM_UPDATE_MOD_DIP) {
+ if (new_update_params->update.l3.ipda.version !=
+ pupdate_hm->update_params.update.l3.ipda.
+ version) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&pupdate_hm->access);
+ log_err("New DIP adress version (%d) in UPDATE "
+ "header manipulation hmd=%d cannot be "
+ "different from the old one (%d).\n",
+ new_update_params->update.l3.ipda.
+ version, hmd, pupdate_hm->
+ update_params.update.l3.ipda.version);
+ return -EINVAL;
+ }
+ memcpy(&pupdate_hm->update_params.update.l3.ipda,
+ &new_update_params->update.l3.ipda,
+ sizeof(struct dpa_offload_ip_address));
+ update[0] = true;
+ }
+
+ if ((modify_flags & DPA_CLS_HM_UPDATE_MOD_TOS_TC) &&
+ (new_update_params->update.l3.tos_tc !=
+ pupdate_hm->update_params.update.l3.tos_tc)) {
+ update[0] = true;
+ pupdate_hm->update_params.update.l3.tos_tc =
+ new_update_params->update.l3.tos_tc;
+ }
+
+ if ((modify_flags & DPA_CLS_HM_UPDATE_MOD_IP_ID) &&
+ (new_update_params->update.l3.initial_id !=
+ pupdate_hm->update_params.update.l3.initial_id)) {
+ update[0] = true;
+ pupdate_hm->update_params.update.l3.initial_id =
+ new_update_params->update.l3.initial_id;
+ }
+
+ if ((modify_flags & DPA_CLS_HM_UPDATE_MOD_L3_FLAGS) &&
+ (new_update_params->update.l3.field_flags !=
+ pupdate_hm->update_params.update.l3.field_flags)) {
+ update[0] = true;
+ pupdate_hm->update_params.update.l3.field_flags =
+ new_update_params->update.l3.field_flags;
+ }
+ }
+
+ if (pupdate_hm->update_params.op_flags &
+ DPA_CLS_HM_UPDATE_UDP_TCP_UPDATE) {
+ if ((modify_flags & DPA_CLS_HM_UPDATE_MOD_SPORT) &&
+ (new_update_params->update.l4.sport !=
+ pupdate_hm->update_params.update.l4.sport)) {
+ update[0] = true;
+ pupdate_hm->update_params.update.l4.sport =
+ new_update_params->update.l4.sport;
+ }
+
+ if ((modify_flags & DPA_CLS_HM_UPDATE_MOD_DPORT) &&
+ (new_update_params->update.l4.dport !=
+ pupdate_hm->update_params.update.l4.dport)) {
+ update[0] = true;
+ pupdate_hm->update_params.update.l4.dport =
+ new_update_params->update.l4.dport;
+ }
+
+ if ((modify_flags & DPA_CLS_HM_UPDATE_MOD_L4_FLAGS) &&
+ (new_update_params->update.l4.field_flags !=
+ pupdate_hm->update_params.update.l4.field_flags)) {
+ update[0] = true;
+ pupdate_hm->update_params.update.l4.field_flags =
+ new_update_params->update.l4.field_flags;
+ }
+ }
+
+ if (update[0]) {
+ ret = update_hm_update_params(pupdate_hm);
+ if (ret == 0) {
+ t_FmPcdManipParams new_hm_node_params;
+
+ hm_node = pupdate_hm->hm_node[0];
+
+ /*
+ * Have to make a copy of the manip node params because
+ * ManipNodeReplace does not accept h_NextManip != NULL.
+ */
+ memcpy(&new_hm_node_params, &hm_node->params,
+ sizeof(new_hm_node_params));
+ new_hm_node_params.h_NextManip = NULL;
+ error = FM_PCD_ManipNodeReplace(hm_node->node,
+ &new_hm_node_params);
+ if (error != E_OK) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&pupdate_hm->access);
+ log_err("FMan driver call failed - "
+ "FM_PCD_ManipNodeReplace, while trying "
+ "to modify hmd=%d, manip node "
+ "handle=0x%p.\n", hmd, hm_node->node);
+ return -EBUSY;
+ }
+ }
+ }
+
+ /* update[1] not supported at this time */
+
+ release_desc_table(&hm_array);
+ mutex_unlock(&pupdate_hm->access);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+EXPORT_SYMBOL(dpa_classif_modify_update_hm);
+
+int dpa_classif_set_vlan_hm(const struct dpa_cls_hm_vlan_params *vlan_params,
+ int next_hmd,
+ int *hmd,
+ bool chain_head,
+ const struct dpa_cls_hm_vlan_resources *res)
+{
+ int err;
+ struct dpa_cls_hm *pvlan_hm, *pcurrent;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ /* Parameters sanity checks: */
+ if (!vlan_params) {
+ log_err("\"vlan_params\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+ if (!hmd) {
+ log_err("\"hmd\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ *hmd = DPA_OFFLD_DESC_NONE;
+
+ err = vlan_hm_check_params(vlan_params);
+ if (err < 0) {
+ log_err("Invalid VLAN specific HM parameters.\n");
+ return err;
+ }
+
+ err = create_new_hm_op(hmd, next_hmd);
+ if (err < 0) {
+ log_err("Failed to create VLAN specific HM op.\n");
+ return err;
+ }
+
+ pvlan_hm = (struct dpa_cls_hm *) hm_array.object[*hmd];
+
+ pvlan_hm->type = DPA_CLS_HM_TYPE_VLAN;
+ pvlan_hm->chain_head = chain_head;
+
+ /* Copy the VLAN specific HM parameters locally */
+ memcpy(&pvlan_hm->vlan_params, vlan_params, sizeof(*vlan_params));
+
+ err = vlan_hm_prepare_nodes(pvlan_hm, res);
+ if (err < 0) {
+ log_err("Failed to acquire necessary HM nodes.\n");
+ goto vlan_hm_error;
+ }
+
+ err = vlan_hm_update_params(pvlan_hm);
+ if (err < 0) {
+ log_err("Failed to update low level header manipulation "
+ "parameters.\n");
+ goto vlan_hm_error;
+ }
+
+ if (chain_head) {
+ err = init_hm_chain(pvlan_hm->vlan_params.fm_pcd,
+ pvlan_hm->hm_chain,
+ pvlan_hm->hm_chain->next);
+ if (err < 0)
+ log_err("Failed to initialize low level HM chain.\n");
+ }
+
+ /* Release the high level HM op chain */
+ RELEASE_HM_OP_CHAIN(pvlan_hm);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+
+vlan_hm_error:
+
+ /* Release the high level HM op chain */
+ RELEASE_HM_OP_CHAIN(pvlan_hm);
+
+ lock_desc_table(&hm_array);
+ remove_hm_op(*hmd);
+ release_desc_table(&hm_array);
+
+ *hmd = DPA_OFFLD_DESC_NONE;
+
+ return err;
+}
+EXPORT_SYMBOL(dpa_classif_set_vlan_hm);
+
+static int vlan_hm_prepare_nodes(struct dpa_cls_hm *pvlan_hm,
+ const struct dpa_cls_hm_vlan_resources *res)
+{
+ struct dpa_cls_hm_node *hm_node;
+ void * const *phm_nodes;
+ int err = 0;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!pvlan_hm);
+
+ pvlan_hm->num_nodes = 1;
+
+ if (res) { /* Import HM nodes */
+ phm_nodes = &res->vlan_node;
+
+ err = import_hm_nodes_to_chain(phm_nodes,
+ pvlan_hm->num_nodes,
+ pvlan_hm);
+ } else { /* Create HM nodes */
+ hm_node = kzalloc(sizeof(*hm_node), GFP_KERNEL);
+ if (!hm_node) {
+ log_err("Not enough memory for header manip nodes.\n");
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&hm_node->list_node);
+ pvlan_hm->hm_node[0] = hm_node;
+
+ add_local_hm_nodes_to_chain(pvlan_hm);
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+}
+
+static int vlan_hm_update_params(struct dpa_cls_hm *pvlan_hm)
+{
+ struct dpa_cls_hm_node *hm_node;
+ uint8_t size;
+ uint8_t *pdata;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!pvlan_hm);
+ BUG_ON(pvlan_hm->num_nodes != 1);
+ BUG_ON(!pvlan_hm->hm_node[0]);
+
+ hm_node = pvlan_hm->hm_node[0];
+
+ hm_node->params.type = e_FM_PCD_MANIP_HDR;
+
+ switch (pvlan_hm->vlan_params.type) {
+ case DPA_CLS_HM_VLAN_INGRESS:
+ hm_node->params.u.hdr.rmv = TRUE;
+ hm_node->params.u.hdr.rmvParams.type =
+ e_FM_PCD_MANIP_RMV_BY_HDR;
+ hm_node->params.u.hdr.rmvParams.u.byHdr.type =
+ e_FM_PCD_MANIP_RMV_BY_HDR_SPECIFIC_L2;
+ hm_node->params.u.hdr.rmvParams.u.byHdr.u.specificL2 =
+ e_FM_PCD_MANIP_HDR_RMV_STACKED_QTAGS;
+ hm_node->params.u.hdr.dontParseAfterManip = TRUE;
+
+ break;
+ case DPA_CLS_HM_VLAN_EGRESS:
+ if (pvlan_hm->vlan_params.egress.num_tags) {
+
+ hm_node->params.u.hdr.insrt = TRUE;
+ hm_node->params.u.hdr.insrtParams.type =
+ e_FM_PCD_MANIP_INSRT_GENERIC;
+ hm_node->params.u.hdr.insrtParams.u.generic.offset =
+ ETHERTYPE_OFFSET;
+
+ size = (uint8_t) (pvlan_hm->vlan_params.egress.
+ num_tags * sizeof(struct vlan_header));
+ pdata = kzalloc(size, GFP_KERNEL);
+ if (!pdata) {
+ log_err("Not enough memory for VLAN specific "
+ "egress HM.\n");
+ kfree(hm_node);
+ return -ENOMEM;
+ }
+
+ memcpy(pdata, pvlan_hm->vlan_params.egress.qtag,
+ size);
+
+ kfree(hm_node->params.u.hdr.insrtParams.u.generic.
+ p_Data);
+
+ hm_node->params.u.hdr.insrtParams.u.generic.size =
+ size;
+ hm_node->params.u.hdr.insrtParams.u.generic.p_Data =
+ pdata;
+ hm_node->params.u.hdr.insrtParams.u.generic.replace =
+ FALSE;
+ }
+
+ if (pvlan_hm->vlan_params.egress.update_op !=
+ DPA_CLS_HM_VLAN_UPDATE_NONE) {
+
+ hm_node->params.u.hdr.fieldUpdate = TRUE;
+ hm_node->params.u.hdr.fieldUpdateParams.type =
+ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN;
+ hm_node->params.u.hdr.dontParseAfterManip = TRUE;
+
+ switch (pvlan_hm->vlan_params.egress.update_op) {
+ case DPA_CLS_HM_VLAN_UPDATE_VPri:
+ hm_node->params.u.hdr.fieldUpdateParams.u.vlan.
+ updateType =
+ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_VLAN_VPRI;
+ hm_node->params.u.hdr.fieldUpdateParams.u.vlan.
+ u.vpri = pvlan_hm->vlan_params.egress.
+ update.vpri;
+ break;
+ case DPA_CLS_HM_VLAN_UPDATE_VPri_BY_DSCP:
+ hm_node->params.u.hdr.fieldUpdateParams.u.vlan.
+ updateType =
+ e_FM_PCD_MANIP_HDR_FIELD_UPDATE_DSCP_TO_VLAN;
+ memcpy(hm_node->params.u.hdr.fieldUpdateParams.
+ u.vlan.u.dscpToVpri.dscpToVpriTable,
+ pvlan_hm->vlan_params.egress.update.
+ dscp_to_vpri,
+ FM_PCD_MANIP_DSCP_TO_VLAN_TRANS);
+ break;
+ default:
+ log_err("Unknown VLAN update type.\n");
+ kfree(hm_node);
+ return -EINVAL;
+ break;
+ }
+ }
+
+ break;
+ default:
+ /* Should never get here */
+ BUG_ON(1);
+ break;
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return 0;
+}
+
+int dpa_classif_modify_vlan_hm(int hmd,
+ const struct dpa_cls_hm_vlan_params *new_vlan_params, int modify_flags)
+{
+ struct dpa_cls_hm_node *hm_node;
+ struct dpa_cls_hm *pvlan_hm;
+ bool update = false;
+ t_Error error;
+ int ret = 0;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ if (!modify_flags)
+ /* Nothing to do */
+ return 0;
+
+ if ((modify_flags & DPA_CLS_HM_VLAN_MOD_INGRESS_NUM_QTAGS) &&
+ (modify_flags != DPA_CLS_HM_VLAN_MOD_INGRESS_NUM_QTAGS)) {
+ log_err("MOD_INGRESS_NUM_QTAGS flag cannot be combined with "
+ "other flags.\n");
+ return -EINVAL;
+ }
+
+ /* Parameters sanity checks: */
+ if (!new_vlan_params) {
+ log_err("\"new_vlan_params\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ lock_desc_table(&hm_array);
+ pvlan_hm = desc_to_object(&hm_array, hmd);
+ if (!pvlan_hm) {
+ release_desc_table(&hm_array);
+ log_err("Invalid descriptor (%d).\n", hmd);
+ return -EINVAL;
+ }
+ mutex_lock(&pvlan_hm->access);
+ /*
+ * Hold the lock on the descriptor table to prevent other runtime
+ * modifications of header manipulations until we're finished. The FMan
+ * driver doesn't allow parallel modification of HM nodes when they
+ * belong to the same PCD.
+ */
+
+ if (pvlan_hm->type != DPA_CLS_HM_TYPE_VLAN) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&pvlan_hm->access);
+ log_err("hmd=%d is not an VLAN type header manip.\n", hmd);
+ return -EINVAL;
+ }
+
+ if (modify_flags == DPA_CLS_HM_VLAN_MOD_INGRESS_NUM_QTAGS) {
+ if (pvlan_hm->vlan_params.type != DPA_CLS_HM_VLAN_INGRESS) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&pvlan_hm->access);
+ log_err("hmd=%d is not an INGRESS VLAN type header "
+ "manipulation.\n", hmd);
+ return -EINVAL;
+ }
+
+ if (new_vlan_params->ingress.num_tags !=
+ pvlan_hm->vlan_params.ingress.num_tags) {
+ update = true;
+ pvlan_hm->vlan_params.ingress.num_tags =
+ new_vlan_params->ingress.num_tags;
+ }
+ } else {
+ if (pvlan_hm->vlan_params.type != DPA_CLS_HM_VLAN_EGRESS) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&pvlan_hm->access);
+ log_err("hmd=%d is not an EGRESS VLAN type header "
+ "manipulation.\n", hmd);
+ return -EINVAL;
+ }
+
+ if ((modify_flags & DPA_CLS_HM_VLAN_MOD_EGRESS_QTAGS) &&
+ (new_vlan_params->egress.num_tags !=
+ pvlan_hm->vlan_params.egress.num_tags)) {
+ update = true;
+ pvlan_hm->vlan_params.egress.num_tags =
+ new_vlan_params->egress.num_tags;
+ memcpy(pvlan_hm->vlan_params.egress.qtag,
+ new_vlan_params->egress.qtag,
+ pvlan_hm->vlan_params.egress.num_tags *
+ sizeof(struct vlan_header));
+ }
+
+ if ((modify_flags & DPA_CLS_HM_VLAN_MOD_EGRESS_UPDATE_OP) &&
+ (new_vlan_params->egress.update_op !=
+ pvlan_hm->vlan_params.egress.update_op)) {
+ update = true;
+ pvlan_hm->vlan_params.egress.update_op =
+ new_vlan_params->egress.update_op;
+ }
+
+ if ((modify_flags & DPA_CLS_HM_VLAN_MOD_EGRESS_VPRI) &&
+ (new_vlan_params->egress.update.vpri !=
+ pvlan_hm->vlan_params.egress.update.vpri)) {
+ update = true;
+ pvlan_hm->vlan_params.egress.update.vpri =
+ new_vlan_params->egress.update.vpri;
+ }
+
+ if (modify_flags &
+ DPA_CLS_HM_VLAN_MOD_EGRESS_DSCP_TO_VPRI_ARRAY) {
+ update = true;
+ memcpy(pvlan_hm->vlan_params.egress.update.dscp_to_vpri,
+ new_vlan_params->egress.update.dscp_to_vpri,
+ DPA_CLS_HM_DSCP_TO_VPRI_TABLE_SIZE);
+ }
+ }
+
+ if (update) {
+ ret = vlan_hm_update_params(pvlan_hm);
+ if (ret == 0) {
+ t_FmPcdManipParams new_hm_node_params;
+
+ hm_node = pvlan_hm->hm_node[0];
+
+ /*
+ * Have to make a copy of the manip node params because
+ * ManipNodeReplace does not accept h_NextManip != NULL.
+ */
+ memcpy(&new_hm_node_params, &hm_node->params,
+ sizeof(new_hm_node_params));
+ new_hm_node_params.h_NextManip = NULL;
+ error = FM_PCD_ManipNodeReplace(hm_node->node,
+ &new_hm_node_params);
+ if (error != E_OK) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&pvlan_hm->access);
+ log_err("FMan driver call failed - "
+ "FM_PCD_ManipNodeReplace, while trying "
+ "to modify hmd=%d, manip node "
+ "handle=0x%p.\n", hmd, hm_node->node);
+ return -EBUSY;
+ }
+ }
+ }
+
+ release_desc_table(&hm_array);
+ mutex_unlock(&pvlan_hm->access);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+EXPORT_SYMBOL(dpa_classif_modify_vlan_hm);
+
+int dpa_classif_set_mpls_hm(const struct dpa_cls_hm_mpls_params *mpls_params,
+ int next_hmd,
+ int *hmd,
+ bool chain_head,
+ const struct dpa_cls_hm_mpls_resources *res)
+{
+ int err;
+ struct dpa_cls_hm *pmpls_hm, *pcurrent;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ /* Parameters sanity checks: */
+ if (!mpls_params) {
+ log_err("\"mpls_params\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+ if (!hmd) {
+ log_err("\"hmd\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ *hmd = DPA_OFFLD_DESC_NONE;
+
+ err = mpls_hm_check_params(mpls_params);
+ if (err < 0) {
+ log_err("Invalid MPLS specific HM parameters.\n");
+ return err;
+ }
+
+ err = create_new_hm_op(hmd, next_hmd);
+ if (err < 0) {
+ log_err("Failed to create MPLS specific HM op.\n");
+ return err;
+ }
+
+ pmpls_hm = (struct dpa_cls_hm *) hm_array.object[*hmd];
+
+ pmpls_hm->type = DPA_CLS_HM_TYPE_MPLS;
+ pmpls_hm->chain_head = chain_head;
+
+ /* Copy the VLAN specific HM parameters locally */
+ memcpy(&pmpls_hm->mpls_params, mpls_params, sizeof(*mpls_params));
+
+ err = mpls_hm_prepare_nodes(pmpls_hm, res);
+ if (err < 0) {
+ log_err("Failed to acquire necessary HM nodes.\n");
+ goto mpls_hm_error;
+ }
+
+ err = mpls_hm_update_params(pmpls_hm);
+ if (err < 0) {
+ log_err("Failed to update low level header manipulation "
+ "parameters.\n");
+ goto mpls_hm_error;
+ }
+
+ if (chain_head) {
+ err = init_hm_chain(pmpls_hm->mpls_params.fm_pcd,
+ pmpls_hm->hm_chain,
+ pmpls_hm->hm_chain->next);
+ if (err < 0)
+ log_err("Failed to initialize low level HM chain.\n");
+ }
+
+ /* Release the high level HM op chain */
+ RELEASE_HM_OP_CHAIN(pmpls_hm);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+
+mpls_hm_error:
+
+ /* Release the high level HM op chain */
+ RELEASE_HM_OP_CHAIN(pmpls_hm);
+
+ lock_desc_table(&hm_array);
+ remove_hm_op(*hmd);
+ release_desc_table(&hm_array);
+
+ *hmd = DPA_OFFLD_DESC_NONE;
+
+ return err;
+}
+EXPORT_SYMBOL(dpa_classif_set_mpls_hm);
+
+static int mpls_hm_prepare_nodes(struct dpa_cls_hm *pmpls_hm,
+ const struct dpa_cls_hm_mpls_resources *res)
+{
+ struct dpa_cls_hm_node *hm_node;
+ void * const *phm_nodes;
+ int err = 0;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!pmpls_hm);
+
+ pmpls_hm->num_nodes = 1;
+
+ if (res) { /* Import HM nodes */
+ phm_nodes = &res->ins_rm_node;
+
+ err = import_hm_nodes_to_chain(phm_nodes,
+ pmpls_hm->num_nodes,
+ pmpls_hm);
+ } else { /* Create HM nodes */
+ hm_node = kzalloc(sizeof(*hm_node), GFP_KERNEL);
+ if (!hm_node) {
+ log_err("Not enough memory for header manip nodes.\n");
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&hm_node->list_node);
+ pmpls_hm->hm_node[0] = hm_node;
+
+ add_local_hm_nodes_to_chain(pmpls_hm);
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return err;
+}
+
+static int mpls_hm_update_params(struct dpa_cls_hm *pmpls_hm)
+{
+ struct dpa_cls_hm_node *hm_node = NULL;
+ uint8_t size;
+ uint8_t *pdata;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ BUG_ON(!pmpls_hm);
+ BUG_ON(pmpls_hm->num_nodes != 1);
+ BUG_ON(!pmpls_hm->hm_node[0]);
+
+ hm_node = pmpls_hm->hm_node[0];
+
+ hm_node->params.type = e_FM_PCD_MANIP_HDR;
+
+ switch (pmpls_hm->mpls_params.type) {
+ case DPA_CLS_HM_MPLS_REMOVE_ALL_LABELS:
+ hm_node->params.u.hdr.rmv = TRUE;
+ hm_node->params.u.hdr.rmvParams.type =
+ e_FM_PCD_MANIP_RMV_BY_HDR;
+ hm_node->params.u.hdr.rmvParams.u.byHdr.type =
+ e_FM_PCD_MANIP_RMV_BY_HDR_SPECIFIC_L2;
+ hm_node->params.u.hdr.rmvParams.u.byHdr.u.specificL2 =
+ e_FM_PCD_MANIP_HDR_RMV_MPLS;
+
+ break;
+ case DPA_CLS_HM_MPLS_INSERT_LABELS:
+ hm_node->params.u.hdr.insrt = TRUE;
+ hm_node->params.u.hdr.insrtParams.type =
+ e_FM_PCD_MANIP_INSRT_BY_HDR;
+ hm_node->params.u.hdr.insrtParams.u.byHdr.type =
+ e_FM_PCD_MANIP_INSRT_BY_HDR_SPECIFIC_L2;
+ hm_node->params.u.hdr.insrtParams.u.byHdr.u.specificL2Params.
+ specificL2 =
+ e_FM_PCD_MANIP_HDR_INSRT_MPLS;
+
+ size = (uint8_t) (pmpls_hm->mpls_params.num_labels *
+ sizeof(struct mpls_header));
+ pdata = kzalloc(size, GFP_KERNEL);
+ if (!pdata) {
+ log_err("Not enough memory for MPLS specific HM.\n");
+ kfree(hm_node);
+ return -ENOMEM;
+ }
+
+ memcpy(pdata, pmpls_hm->mpls_params.mpls_hdr, size);
+
+ kfree(hm_node->params.u.hdr.insrtParams.u.byHdr.u.
+ specificL2Params.p_Data);
+
+ hm_node->params.u.hdr.insrtParams.u.byHdr.u.specificL2Params.
+ size = size;
+ hm_node->params.u.hdr.insrtParams.u.byHdr.u.specificL2Params.
+ p_Data = pdata;
+
+ break;
+ default:
+ /* Should never get here */
+ BUG_ON(1);
+ break;
+ }
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return 0;
+}
+
+int dpa_classif_modify_mpls_hm(int hmd,
+ const struct dpa_cls_hm_mpls_params *new_mpls_params, int modify_flags)
+{
+ struct dpa_cls_hm_node *hm_node;
+ struct dpa_cls_hm *pmpls_hm;
+ bool update = false;
+ t_Error error;
+ int ret = 0;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ if (!modify_flags)
+ /* Nothing to do */
+ return 0;
+
+ /* Parameters sanity checks: */
+ if (!new_mpls_params) {
+ log_err("\"new_mpls_params\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ lock_desc_table(&hm_array);
+ pmpls_hm = desc_to_object(&hm_array, hmd);
+ if (!pmpls_hm) {
+ release_desc_table(&hm_array);
+ log_err("Invalid descriptor (%d).\n", hmd);
+ return -EINVAL;
+ }
+ mutex_lock(&pmpls_hm->access);
+ /*
+ * Hold the lock on the descriptor table to prevent other runtime
+ * modifications of header manipulations until we're finished. The FMan
+ * driver doesn't allow parallel modification of HM nodes when they
+ * belong to the same PCD.
+ */
+
+ if (pmpls_hm->type != DPA_CLS_HM_TYPE_MPLS) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&pmpls_hm->access);
+ log_err("hmd=%d is not an MPLS type header manip.\n", hmd);
+ return -EINVAL;
+ }
+
+ if ((modify_flags && DPA_CLS_HM_MPLS_MOD_NUM_LABELS) &&
+ (pmpls_hm->mpls_params.num_labels !=
+ new_mpls_params->num_labels)) {
+ update = true;
+ pmpls_hm->mpls_params.num_labels =
+ new_mpls_params->num_labels;
+ }
+
+ if (modify_flags && DPA_CLS_HM_MPLS_MOD_HDR_ARRAY) {
+ update = true;
+ memcpy(pmpls_hm->mpls_params.mpls_hdr,
+ new_mpls_params->mpls_hdr,
+ pmpls_hm->mpls_params.num_labels *
+ sizeof(struct mpls_header));
+ }
+
+ if (update) {
+ ret = mpls_hm_update_params(pmpls_hm);
+ if (ret == 0) {
+ t_FmPcdManipParams new_hm_node_params;
+
+ hm_node = pmpls_hm->hm_node[0];
+
+ /*
+ * Have to make a copy of the manip node params because
+ * ManipNodeReplace does not accept h_NextManip != NULL.
+ */
+ memcpy(&new_hm_node_params, &hm_node->params,
+ sizeof(new_hm_node_params));
+ new_hm_node_params.h_NextManip = NULL;
+ error = FM_PCD_ManipNodeReplace(hm_node->node,
+ &new_hm_node_params);
+ if (error != E_OK) {
+ release_desc_table(&hm_array);
+ mutex_unlock(&pmpls_hm->access);
+ log_err("FMan driver call failed - "
+ "FM_PCD_ManipNodeReplace, while trying "
+ "to modify hmd=%d, manip node "
+ "handle=0x%p.\n", hmd, hm_node->node);
+ return -EBUSY;
+ }
+ }
+ }
+
+ release_desc_table(&hm_array);
+ mutex_unlock(&pmpls_hm->access);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+EXPORT_SYMBOL(dpa_classif_modify_mpls_hm);
+
+int dpa_classif_import_static_hm(void *hm, int next_hmd, int *hmd)
+{
+ int err;
+ struct dpa_cls_hm *pstatic_hm, *pcurrent;
+ struct dpa_cls_hm_node *hm_node;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ /* Parameters sanity checks: */
+ if (!hm) {
+ log_err("\"hm\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+ if (!hmd) {
+ log_err("\"hmd\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+
+ err = create_new_hm_op(hmd, next_hmd);
+ if (err < 0) {
+ log_err("Failed to create static HM op.\n");
+ return err;
+ }
+
+ pstatic_hm = (struct dpa_cls_hm *) hm_array.object[*hmd];
+
+ pstatic_hm->type = DPA_CLS_HM_TYPE_STATIC;
+
+ /* Create a header manip node: */
+ hm_node = kzalloc(sizeof(*hm_node), GFP_KERNEL);
+ if (!hm_node) {
+ RELEASE_HM_OP_CHAIN(pstatic_hm);
+ log_err("No more memory for header manip nodes.\n");
+ return -ENOMEM;
+ }
+
+ hm_node->node = hm;
+ hm_node->params.type = -1; /* to identify an unknown HM */
+ INIT_LIST_HEAD(&hm_node->list_node);
+
+ pstatic_hm->hm_node[0] = hm_node;
+ pstatic_hm->num_nodes = 1;
+
+ add_local_hm_nodes_to_chain(pstatic_hm);
+
+ if (!list_empty(&pstatic_hm->list_node))
+ /*
+ * Move the "chain head" flag on the current header
+ * manipulation
+ */
+ list_for_each_entry(pcurrent,
+ &pstatic_hm->list_node,
+ list_node) {
+ pcurrent->chain_head = false;
+ }
+ pstatic_hm->chain_head = true;
+
+ RELEASE_HM_OP_CHAIN(pstatic_hm);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return 0;
+}
+
+void *dpa_classif_get_static_hm_handle(int hmd)
+{
+ struct dpa_cls_hm *hm;
+ void *node;
+
+ if (hmd == DPA_OFFLD_DESC_NONE)
+ /* Nothing to do */
+ return NULL;
+
+ LOCK_OBJECT(hm_array, hmd, hm, NULL);
+
+ if (hm->type != DPA_CLS_HM_TYPE_STATIC) {
+ RELEASE_OBJECT(hm);
+ return NULL;
+ }
+
+ node = hm->hm_node[0]->node;
+
+ RELEASE_OBJECT(hm);
+
+ return node;
+}
+
+void *dpa_classif_hm_lock_chain(int hmd)
+{
+ struct dpa_cls_hm *hm, *pcurrent;
+ struct dpa_cls_hm_node *hm_node;
+ void *node;
+
+ if (hmd == DPA_OFFLD_DESC_NONE)
+ /* Nothing to do */
+ return NULL;
+
+ lock_desc_table(&hm_array);
+ hm = desc_to_object(&hm_array, hmd);
+ if (!hm) {
+ release_desc_table(&hm_array);
+ log_err("Invalid descriptor (%d).\n", hmd);
+ return NULL;
+ }
+ LOCK_HM_OP_CHAIN(hm);
+ release_desc_table(&hm_array);
+
+ /* Lock all HM nodes */
+ list_for_each_entry(hm_node, hm->hm_chain, list_node)
+ hm_node->ref++;
+
+ /*
+ * Acquire the hm_node structure that is head of the header manipulation
+ * chain
+ */
+ hm_node = list_entry(hm->hm_chain->next,
+ struct dpa_cls_hm_node,
+ list_node);
+ node = hm_node->node;
+
+ RELEASE_HM_OP_CHAIN(hm);
+
+ return node;
+}
+
+void dpa_classif_hm_release_chain(int hmd)
+{
+ struct dpa_cls_hm *hm, *pcurrent;
+ struct dpa_cls_hm_node *hm_node;
+
+ if (hmd == DPA_OFFLD_DESC_NONE)
+ /* Nothing to do */
+ return;
+
+ lock_desc_table(&hm_array);
+ hm = desc_to_object(&hm_array, hmd);
+ if (!hm) {
+ release_desc_table(&hm_array);
+ log_err("Invalid descriptor (%d).\n", hmd);
+ return;
+ }
+ LOCK_HM_OP_CHAIN(hm);
+ release_desc_table(&hm_array);
+
+ /* Release all HM nodes */
+ list_for_each_entry(hm_node, hm->hm_chain, list_node)
+ if (hm_node->ref)
+ hm_node->ref--;
+ else
+ log_warn("Unbalanced HM node release on manip "
+ "node=0x%p.\n", hm_node->node);
+
+ RELEASE_HM_OP_CHAIN(hm);
+}
+
+bool dpa_classif_hm_is_chain_head(int hmd)
+{
+ struct dpa_cls_hm *hm;
+ bool chain_head;
+
+ if (hmd == DPA_OFFLD_DESC_NONE)
+ /* Nothing to do */
+ return false;
+
+ LOCK_OBJECT(hm_array, hmd, hm, NULL);
+
+ chain_head = hm->chain_head;
+
+ RELEASE_OBJECT(hm);
+
+ return chain_head;
+}
+
+void *dpa_classif_get_frag_hm_handle(int hmd)
+{
+ struct dpa_cls_hm *hm, *pcurrent;
+ struct dpa_cls_hm_node *p;
+ void *frag_hm_handle = NULL;
+
+ if (hmd == DPA_OFFLD_DESC_NONE)
+ /* Nothing to do */
+ return NULL;
+
+ lock_desc_table(&hm_array);
+ hm = desc_to_object(&hm_array, hmd);
+ if (!hm) {
+ release_desc_table(&hm_array);
+ log_err("Invalid descriptor (%d).\n", hmd);
+ return NULL;
+ }
+ LOCK_HM_OP_CHAIN(hm);
+ release_desc_table(&hm_array);
+
+ list_for_each_entry(p, hm->hm_chain, list_node)
+ if ((p->node) && (p->params.type ==
+ e_FM_PCD_MANIP_FRAG)) {
+ frag_hm_handle = p->node;
+ break;
+ }
+
+ RELEASE_HM_OP_CHAIN(hm);
+
+ return frag_hm_handle;
+}
+
+int dpa_classif_free_hm(int hmd)
+{
+ struct dpa_cls_hm *phm, *pcurrent;
+ struct dpa_cls_hm_node *hm_node;
+ int i = 1;
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) -->\n", __func__,
+ __LINE__));
+
+ lock_desc_table(&hm_array);
+ phm = desc_to_object(&hm_array, hmd);
+ if (!phm) {
+ release_desc_table(&hm_array);
+ /* Descriptor already free */
+ return 0;
+ }
+ LOCK_HM_OP_CHAIN(phm);
+
+ /* Verify whether this header manipulation chain is in use */
+ list_for_each_entry(hm_node, phm->hm_chain, list_node) {
+ if (hm_node->ref) {
+ release_desc_table(&hm_array);
+ RELEASE_HM_OP_CHAIN(phm);
+ log_err("Unable to remove HM chain hmd=%d. Manip node "
+ "#%d (0x%p) is still in use by %d "
+ "entity(ies).\n", hmd, i, hm_node->node,
+ hm_node->ref);
+ return -EBUSY;
+ }
+ i++;
+ }
+
+ if (phm->chain_head) {
+ /*
+ * This is a header manip chain head, hence remove the entire
+ * chain of low level ops
+ */
+ if (remove_hm_chain(phm->hm_chain, phm->hm_chain->next) < 0)
+ log_warn("Not all low level HM nodes could be "
+ "removed for chain hmd=%d.\n", hmd);
+ }
+
+ RELEASE_HM_OP_CHAIN(phm);
+
+ remove_hm_op(hmd);
+ release_desc_table(&hm_array);
+
+ dpa_cls_dbg(("DEBUG: dpa_classifier %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return 0;
+}
+EXPORT_SYMBOL(dpa_classif_free_hm);
+
+#if (DPAA_VERSION >= 11)
+int dpa_classif_mcast_create_group(
+ const struct dpa_cls_mcast_group_params *group_params,
+ int *grpd,
+ const struct dpa_cls_mcast_group_resources *res)
+{
+
+ int err = 0;
+ struct dpa_cls_mcast_group *pgroup;
+ int member_id;
+ uint8_t max_members;
+ struct dpa_cls_tbl_enq_action_desc *member_params;
+ t_FmPcdFrmReplicGroupParams *replic_grp_params = NULL;
+ t_FmPcdCcNextEngineParams *next_engine_params;
+
+ if (!group_params) {
+ log_err("Invalid value for group params.\n");
+ err = -EINVAL;
+ return err;
+ }
+
+ if (!grpd) {
+ log_err("Invalid group desc\n");
+ err = -EINVAL;
+ return err;
+ }
+
+ if (!group_params->max_members) {
+ log_err("Invalid value for maximum number of members in a "
+ "group\n");
+ err = -EINVAL;
+ return err;
+ }
+
+ if ((group_params->max_members > DPA_CLS_MCAST_MAX_NUM_OF_ENTRIES)) {
+ log_err("Maximum number of members in group is greater than "
+ "%d\n", DPA_CLS_MCAST_MAX_NUM_OF_ENTRIES);
+ err = -EINVAL;
+ return err;
+ }
+
+ pgroup = kzalloc(sizeof(struct dpa_cls_mcast_group), GFP_KERNEL);
+ if (!pgroup) {
+ log_err("No more memory for DPA multicast groups.\n");
+ err = -ENOMEM;
+ goto dpa_classif_mcast_create_group_error;
+ }
+
+ mutex_init(&pgroup->access);
+
+ if (group_params->prefilled_members > group_params->max_members) {
+ log_err("Number of prefilled members is greater than the "
+ "maximum number of members in group. %d > %d\n",
+ group_params->prefilled_members,
+ group_params->max_members);
+ err = -EINVAL;
+ goto dpa_classif_mcast_create_group_error;
+ }
+
+ max_members = group_params->max_members;
+ *grpd = DPA_OFFLD_DESC_NONE;
+ lock_desc_table(&mcast_grp_array);
+ err = acquire_descriptor(&mcast_grp_array, pgroup, grpd);
+ release_desc_table(&mcast_grp_array);
+ if (err < 0)
+ goto dpa_classif_mcast_create_group_error;
+
+ memcpy(&pgroup->group_params, group_params,
+ sizeof(struct dpa_cls_mcast_group_params));
+
+ /*
+ * initialize the array of used members
+ */
+ pgroup->entries = kzalloc(sizeof(struct members) * max_members,
+ GFP_KERNEL);
+ if (!pgroup->entries) {
+ log_err("No more memory for DPA multicast member entries.\n");
+ err = -ENOMEM;
+ goto dpa_classif_mcast_create_group_error;
+ }
+
+ /*
+ * initialize the array of indexes of used members
+ */
+ pgroup->member_ids = kzalloc(sizeof(int) * max_members, GFP_KERNEL);
+ if (!pgroup->member_ids) {
+ log_err("No more memory for DPA multicast index members "
+ "array.\n");
+ err = -ENOMEM;
+ goto dpa_classif_mcast_create_group_error;
+ }
+
+ for (member_id = 0; member_id < max_members; member_id++) {
+ pgroup->entries[member_id].used = false;
+ pgroup->entries[member_id].hmd = DPA_OFFLD_DESC_NONE;
+ pgroup->member_ids[member_id] = DPA_OFFLD_DESC_NONE;
+ }
+
+ /* Group is not imported */
+ if (!res) {
+ /*
+ * set parameters for the first member
+ */
+ member_params = &pgroup->group_params.first_member_params;
+ replic_grp_params = kzalloc(sizeof(t_FmPcdFrmReplicGroupParams),
+ GFP_KERNEL);
+ if (!replic_grp_params) {
+ log_err("No more memory for DPA multicast group "
+ "params.\n");
+ err = -ENOMEM;
+ goto dpa_classif_mcast_create_group_error;
+ }
+
+ replic_grp_params->maxNumOfEntries = max_members;
+ replic_grp_params->numOfEntries = pgroup->num_members + 1;
+ next_engine_params = &replic_grp_params->nextEngineParams[0];
+
+ if (group_params->distribution &&
+ group_params->classification) {
+ t_Handle classification, distribution;
+ t_FmPcdKgSchemeParams *scheme_params =
+ kzalloc(sizeof(t_FmPcdKgSchemeParams),
+ GFP_KERNEL);
+ if (!scheme_params) {
+ log_err("Failed to alocate direct scheme "
+ "params.\n");
+ err = -ENOMEM;
+ goto dpa_classif_mcast_create_group_error;
+ }
+
+ classification = group_params->classification;
+ distribution = group_params->distribution;
+
+ memset(scheme_params, 0, sizeof(*scheme_params));
+ scheme_params->modify = true;
+ scheme_params->alwaysDirect = true;
+ scheme_params->bypassFqidGeneration = true;
+ scheme_params->id.h_Scheme = distribution;
+ scheme_params->nextEngine = e_FM_PCD_CC;
+ scheme_params->kgNextEngineParams.cc.h_CcTree =
+ classification;
+ scheme_params->kgNextEngineParams.cc.grpId = 0;
+ scheme_params->keyExtractAndHashParams.
+ hashDistributionNumOfFqids = 1;
+
+ distribution = FM_PCD_KgSchemeSet(
+ ((t_FmPcdCcTree *)classification)->h_FmPcd,
+ scheme_params);
+ kfree(scheme_params);
+ if (!distribution) {
+ log_err("Failed to set direct scheme.\n");
+ err = -EINVAL;
+ goto dpa_classif_mcast_create_group_error;
+ }
+
+ /* Redirect frames to KeyGen direct scheme */
+ next_engine_params->nextEngine = e_FM_PCD_KG;
+ next_engine_params->params.kgParams.h_DirectScheme =
+ distribution;
+ next_engine_params->params.kgParams.newFqid =
+ member_params->new_fqid;
+ next_engine_params->params.kgParams.overrideFqid =
+ member_params->override_fqid;
+ } else {
+ if (member_params->policer_params) {
+ next_engine_params->nextEngine = e_FM_PCD_PLCR;
+ next_engine_params->params.plcrParams.
+ sharedProfile =
+ member_params->policer_params->shared_profile;
+ next_engine_params->params.plcrParams.
+ newRelativeProfileId =
+ member_params->policer_params->new_rel_profile_id;
+ next_engine_params->params.plcrParams.
+ overrideParams =
+ member_params->policer_params->modify_policer_params;
+ next_engine_params->params.plcrParams.
+ newFqid = member_params->new_fqid;
+ } else {
+ next_engine_params->nextEngine = e_FM_PCD_DONE;
+ next_engine_params->params.enqueueParams.
+ newRelativeStorageProfileId =
+ member_params->new_rel_vsp_id;
+ next_engine_params->params.enqueueParams.
+ action =
+ e_FM_PCD_ENQ_FRAME;
+ next_engine_params->params.enqueueParams.
+ overrideFqid =
+ member_params->override_fqid;
+ next_engine_params->params.enqueueParams.
+ newFqid =
+ member_params->new_fqid;
+ }
+
+ }
+ if (member_params->hmd != DPA_OFFLD_DESC_NONE) {
+ pgroup->entries[0].hmd = member_params->hmd;
+ next_engine_params->h_Manip = (t_Handle)
+ dpa_classif_hm_lock_chain(member_params->hmd);
+ if (!next_engine_params->h_Manip) {
+ log_err("Failed to attach HM op hmd=%d to "
+ "multicast entry.\n",
+ member_params->hmd);
+ err = -EINVAL;
+ goto dpa_classif_mcast_create_group_error;
+ }
+ } else
+ next_engine_params->h_Manip = NULL;
+
+ pgroup->group = FM_PCD_FrmReplicSetGroup(group_params->fm_pcd,
+ replic_grp_params);
+ /* A newly created group has at least one member - member 0 */
+ pgroup->entries[0].used = true;
+ pgroup->member_ids[0] = 0;
+ pgroup->num_members++;
+ } else {
+ pgroup->group = res->group_node;
+ /* mark prefilled members in index array member */
+ for (member_id = 0; member_id < group_params->prefilled_members;
+ member_id++) {
+ pgroup->entries[member_id].used = true;
+ pgroup->member_ids[member_id] = member_id;
+ pgroup->last_index = member_id;
+ }
+ pgroup->num_members = group_params->prefilled_members;
+ }
+
+ kfree(replic_grp_params);
+
+ if (!pgroup->group) {
+ log_err("Could not create %s group %d\n",
+ (group_params->prefilled_members > 0) ? "imported" :
+ "", *grpd);
+ err = -EINVAL;
+ goto dpa_classif_mcast_create_group_error;
+ }
+
+ return 0;
+
+dpa_classif_mcast_create_group_error:
+ if (pgroup) {
+ dpa_classif_hm_release_chain(pgroup->entries[0].hmd);
+ kfree(pgroup->entries);
+ kfree(pgroup->member_ids);
+ mutex_destroy(&pgroup->access);
+ if (*grpd != DPA_OFFLD_DESC_NONE) {
+ lock_desc_table(&mcast_grp_array);
+ put_descriptor(&mcast_grp_array, *grpd);
+ release_desc_table(&mcast_grp_array);
+ }
+ kfree(pgroup);
+ }
+
+ *grpd = DPA_OFFLD_DESC_NONE;
+
+ return err;
+}
+EXPORT_SYMBOL(dpa_classif_mcast_create_group);
+
+int dpa_classif_mcast_add_member(int grpd,
+ const struct dpa_cls_tbl_enq_action_desc *member_params,
+ int *md)
+{
+ struct dpa_cls_mcast_group *pgroup;
+ int member_id;
+ unsigned int prefill_start;
+ uint8_t max_members;
+ t_Error err = 0;
+ t_FmPcdFrmReplicGroupParams *replic_grp_params = NULL;
+ t_FmPcdCcNextEngineParams *next_engine_params;
+
+ lock_desc_table(&mcast_grp_array);
+ pgroup = desc_to_object(&mcast_grp_array, grpd);
+ if (!pgroup) {
+ release_desc_table(&mcast_grp_array);
+ log_err("Invalid group descriptor (grpd=%d).\n", grpd);
+ return -EINVAL;
+ }
+
+ mutex_lock(&pgroup->access);
+ release_desc_table(&mcast_grp_array);
+
+ if (!member_params) {
+ mutex_unlock(&pgroup->access);
+ log_err("Invalid value for member params.\n");
+ return -EINVAL;
+ }
+
+ if (!md) {
+ mutex_unlock(&pgroup->access);
+ log_err("Invalid member desc.\n");
+ return -EINVAL;
+ }
+
+ *md = DPA_OFFLD_DESC_NONE;
+ if (pgroup->num_members == pgroup->group_params.max_members) {
+ mutex_unlock(&pgroup->access);
+ log_err("Current number of members reached maximum value %d.\n",
+ pgroup->group_params.max_members);
+ return -ENOSPC;
+ }
+
+ max_members = pgroup->group_params.max_members;
+ prefill_start = pgroup->group_params.prefilled_members;
+ for (member_id = prefill_start; member_id < max_members; member_id++)
+ if (pgroup->entries[member_id].used == false) {
+ *md = member_id;
+ break;
+ }
+
+ pgroup->entries[*md].used = true;
+ pgroup->num_members++;
+
+ if (unlikely(pgroup->member_ids[*md] != DPA_OFFLD_DESC_NONE)) {
+ log_err("Current member index %d is already in use.\n", *md);
+ mutex_unlock(&pgroup->access);
+ return -ENOSPC;
+ }
+
+ /* A newly added member is always the last member in the group */
+ pgroup->last_index++;
+ pgroup->member_ids[*md] = pgroup->last_index;
+
+ replic_grp_params = kzalloc(sizeof(t_FmPcdFrmReplicGroupParams),
+ GFP_KERNEL);
+ if (!replic_grp_params) {
+ log_err("No more memory for DPA multicast group params.\n");
+ err = -ENOMEM;
+ goto dpa_classif_mcast_add_member_error;
+ }
+
+ replic_grp_params->maxNumOfEntries = max_members;
+ replic_grp_params->numOfEntries = pgroup->num_members;
+ next_engine_params = &replic_grp_params->nextEngineParams[0];
+ if (pgroup->group_params.distribution &&
+ pgroup->group_params.classification) {
+ t_Handle classification, distribution;
+ t_FmPcdKgSchemeParams *scheme_params =
+ kzalloc(sizeof(t_FmPcdKgSchemeParams),
+ GFP_KERNEL);
+ if (!scheme_params) {
+ log_err("Failed to alocate direct scheme params.\n");
+ err = -ENOMEM;
+ goto dpa_classif_mcast_add_member_error;
+
+ }
+
+ classification = pgroup->group_params.classification;
+ distribution = pgroup->group_params.distribution;
+
+ memset(scheme_params, 0, sizeof(*scheme_params));
+ scheme_params->modify = true;
+ scheme_params->alwaysDirect = true;
+ scheme_params->bypassFqidGeneration = true;
+ scheme_params->id.h_Scheme = distribution;
+ scheme_params->nextEngine = e_FM_PCD_CC;
+ scheme_params->kgNextEngineParams.cc.h_CcTree = classification;
+ scheme_params->kgNextEngineParams.cc.grpId = 0;
+ scheme_params->keyExtractAndHashParams.
+ hashDistributionNumOfFqids = 1;
+
+ distribution = FM_PCD_KgSchemeSet(
+ ((t_FmPcdCcTree *)classification)->h_FmPcd,
+ scheme_params);
+ kfree(scheme_params);
+ if (!distribution) {
+ log_err("Failed to set direct scheme.\n");
+ err = -EINVAL;
+ goto dpa_classif_mcast_add_member_error;
+ }
+
+ /* Redirect frames to KeyGen direct scheme */
+ next_engine_params->nextEngine = e_FM_PCD_KG;
+ next_engine_params->params.kgParams.h_DirectScheme =
+ distribution;
+ next_engine_params->params.kgParams.newFqid =
+ member_params->new_fqid;
+ next_engine_params->params.kgParams.overrideFqid =
+ member_params->override_fqid;
+ } else {
+ if (member_params->policer_params) {
+ next_engine_params->nextEngine = e_FM_PCD_PLCR;
+ next_engine_params->params.plcrParams.
+ sharedProfile =
+ member_params->policer_params->shared_profile;
+
+ next_engine_params->params.plcrParams.
+ newRelativeProfileId =
+ member_params->policer_params->new_rel_profile_id;
+ next_engine_params->params.plcrParams.overrideParams =
+ member_params->policer_params->modify_policer_params;
+ next_engine_params->params.plcrParams.newFqid =
+ member_params->new_fqid;
+ } else {
+ next_engine_params->nextEngine = e_FM_PCD_DONE;
+ next_engine_params->params.enqueueParams.
+ newRelativeStorageProfileId =
+ member_params->new_rel_vsp_id;
+ next_engine_params->params.enqueueParams.action =
+ e_FM_PCD_ENQ_FRAME;
+ next_engine_params->params.enqueueParams.overrideFqid =
+ member_params->override_fqid;
+ next_engine_params->params.enqueueParams.newFqid =
+ member_params->new_fqid;
+ }
+ }
+
+ if (member_params->hmd != DPA_OFFLD_DESC_NONE) {
+ pgroup->entries[*md].hmd = member_params->hmd;
+ next_engine_params->h_Manip = (t_Handle)
+ dpa_classif_hm_lock_chain(member_params->hmd);
+ if (!next_engine_params->h_Manip) {
+ log_err("Failed to attach HM op hmd=%d to multicast "
+ "entry.\n", member_params->hmd);
+ err = -EINVAL;
+ goto dpa_classif_mcast_add_member_error;
+ }
+ } else
+ next_engine_params->h_Manip = NULL;
+
+ err = FM_PCD_FrmReplicAddMember(pgroup->group,
+ pgroup->member_ids[*md],
+ next_engine_params);
+ if (err != E_OK) {
+ log_err("Could not add member (%d) to the group (%d)\n", *md,
+ grpd);
+ err = -EINVAL;
+ goto dpa_classif_mcast_add_member_error;
+ }
+ mutex_unlock(&pgroup->access);
+ kfree(replic_grp_params);
+ return 0;
+
+dpa_classif_mcast_add_member_error:
+
+ pgroup->entries[*md].used = false;
+ dpa_classif_hm_release_chain(pgroup->entries[*md].hmd);
+ pgroup->entries[*md].hmd = DPA_OFFLD_DESC_NONE;
+ pgroup->num_members--;
+ *md = DPA_OFFLD_DESC_NONE;
+
+ pgroup->member_ids[*md] = DPA_OFFLD_DESC_NONE;
+ pgroup->last_index--;
+ mutex_unlock(&pgroup->access);
+ kfree(replic_grp_params);
+
+ return err;
+}
+EXPORT_SYMBOL(dpa_classif_mcast_add_member);
+
+int dpa_classif_mcast_remove_member(int grpd, int md)
+{
+ struct dpa_cls_mcast_group *pgroup;
+ int member_id;
+ uint8_t max_members;
+ t_Error err = 0;
+
+ lock_desc_table(&mcast_grp_array);
+ pgroup = desc_to_object(&mcast_grp_array, grpd);
+ if (!pgroup) {
+ release_desc_table(&mcast_grp_array);
+ log_err("Invalid group descriptor (grpd=%d).\n", grpd);
+ return -EINVAL;
+ }
+
+ mutex_lock(&pgroup->access);
+ release_desc_table(&mcast_grp_array);
+
+ if ((md <= 0) || (md > pgroup->group_params.max_members)) {
+ mutex_unlock(&pgroup->access);
+ log_err("Invalid member descriptor (grpd=%d).\n", md);
+ return -EINVAL;
+ }
+
+ if (pgroup->member_ids[md] == DPA_OFFLD_DESC_NONE) {
+ mutex_unlock(&pgroup->access);
+ log_err("Member was already removed (md=%d).\n", md);
+ return -EINVAL;
+ }
+
+ err = FM_PCD_FrmReplicRemoveMember(pgroup->group,
+ pgroup->member_ids[md]);
+ if (err != E_OK) {
+ mutex_unlock(&pgroup->access);
+ log_err("Could not remove member %d from group %d\n", md, grpd);
+ return -EINVAL;
+ }
+
+ pgroup->num_members--;
+ pgroup->entries[md].used = false;
+ dpa_classif_hm_release_chain(pgroup->entries[md].hmd);
+ pgroup->entries[md].hmd = DPA_OFFLD_DESC_NONE;
+ max_members = pgroup->group_params.max_members;
+
+ /* update indexes in index array when removing a member */
+ for (member_id = 0; member_id < max_members; member_id++) {
+ /* update all indexes greater than the removed index */
+ if (pgroup->member_ids[member_id] > pgroup->member_ids[md])
+ pgroup->member_ids[member_id]--;
+ }
+
+ pgroup->member_ids[md] = DPA_OFFLD_DESC_NONE;
+ pgroup->last_index--;
+ mutex_unlock(&pgroup->access);
+
+ return 0;
+}
+EXPORT_SYMBOL(dpa_classif_mcast_remove_member);
+
+int dpa_classif_mcast_free_group(int grpd)
+{
+ struct dpa_cls_mcast_group *pgroup;
+ int member_id;
+ uint8_t max_members;
+ t_Error err = 0;
+
+ lock_desc_table(&mcast_grp_array);
+ pgroup = desc_to_object(&mcast_grp_array, grpd);
+ if (!pgroup) {
+ release_desc_table(&mcast_grp_array);
+ log_err("Invalid group descriptor (grpd=%d).\n", grpd);
+ return -EINVAL;
+ }
+
+ mutex_lock(&pgroup->access);
+ /* If no prefilled members are present, the group was not imported*/
+ if (!pgroup->group_params.prefilled_members) {
+ err = FM_PCD_FrmReplicDeleteGroup(pgroup->group);
+ if (err != E_OK) {
+ release_desc_table(&mcast_grp_array);
+ mutex_unlock(&pgroup->access);
+ log_err("Could not delete group (%d)\n", grpd);
+ return -EINVAL;
+ }
+ }
+
+ max_members = pgroup->group_params.max_members;
+ for (member_id = 0; member_id < max_members; member_id++)
+ dpa_classif_hm_release_chain(pgroup->entries[member_id].hmd);
+
+ kfree(pgroup->entries);
+ kfree(pgroup->member_ids);
+ put_descriptor(&mcast_grp_array, grpd);
+ mutex_unlock(&pgroup->access);
+ mutex_destroy(&pgroup->access);
+ kfree(pgroup);
+ release_desc_table(&mcast_grp_array);
+ return 0;
+}
+EXPORT_SYMBOL(dpa_classif_mcast_free_group);
+#endif
diff --git a/drivers/staging/fsl_dpa_offload/dpa_classifier.h b/drivers/staging/fsl_dpa_offload/dpa_classifier.h
new file mode 100644
index 0000000..659e1b7
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dpa_classifier.h
@@ -0,0 +1,708 @@
+
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Internal DPA Classifier Application Programming Interface
+ */
+
+#ifndef __DPA_CLASSIFIER_H
+#define __DPA_CLASSIFIER_H
+
+
+/* DPA offloading layer includes */
+#include "linux/fsl_dpa_classifier.h"
+
+/* FMD includes */
+#include "fm_pcd_ext.h"
+
+
+/* API functions, definitions and enums */
+
+/* Internal API functions, definitions and enums */
+
+
+/*
+ * The maximum possible size of a shadow table. A DPA Classifier
+ * table can have multiple shadow tables depending on its type
+ * and size.
+ */
+#define DPA_CLS_TBL_MAXSHADOWTABLESIZE 256
+
+/*
+ * Max number of low level header manip nodes per header manipulation
+ * operation.
+ */
+#define DPA_CLS_HM_MAX_NODES_PER_OP 3
+
+/* Available flags for a header manipulation node: */
+
+/* HM node is external (i.e. not created by DPA Classifier) */
+#define DPA_CLS_HM_NODE_EXTERNAL 0x0
+/* HM node is internal (i.e. created & managed by DPA Classifier) */
+#define DPA_CLS_HM_NODE_INTERNAL 0x1
+
+/* Available flags for an index management entry: */
+
+/* Indication that the entry is valid */
+#define DPA_CLS_TBL_ENTRY_VALID 0x1
+
+#define unused(x) (x = x)
+
+
+#if (DPAA_VERSION >= 11)
+#define DPA_CLS_MCAST_MAX_NUM_OF_ENTRIES 64
+#endif
+/* Index management entry */
+struct dpa_cls_tbl_entry {
+
+ /* Entry flags */
+ unsigned flags;
+
+ /* Internal Cc node index where this entry resides */
+ unsigned int int_cc_node_index;
+
+ /* The index of this entry in the Cc node table */
+ uint8_t entry_index;
+
+ /* The priority value of this entry in the table */
+ int priority;
+
+ /* Header manipulation descriptor associated with this entry (if any) */
+ int hmd;
+
+ /*
+ * Pointer to the shadow entry (if there is one) associated
+ * with this index management entry
+ */
+ struct list_head *shadow_entry;
+
+ /*
+ * List node which allows linking this entry in the index
+ * management list.
+ */
+ struct list_head list_node;
+};
+
+/*
+ * Shadow Table Entry (for all types of tables except indexed
+ * tables)
+ */
+struct dpa_cls_tbl_shadow_entry {
+
+ struct dpa_offload_lookup_key key; /* Lookup key info */
+
+ struct dpa_cls_tbl_action action; /* Action info */
+
+ /* Id of this entry (helps find the index management entry faster) */
+ int entry_id;
+
+ /* Pointers to other shadow entries in the current set (bucket) */
+ struct list_head list_node;
+};
+
+/* Shadow Table Entry for indexed tables */
+struct dpa_cls_tbl_shadow_entry_indexed {
+
+ struct dpa_cls_tbl_action action; /* Action info */
+
+ /* Pointers to other shadow entries in the current set (bucket) */
+ struct list_head list_node;
+};
+
+/* Shadow Table */
+struct dpa_cls_tbl_shadow_table {
+
+ /* Shadow table sets (buckets) */
+ struct list_head *shadow_entry;
+
+ /* The size of the shadow table in number of sets (buckets) */
+ unsigned int size;
+};
+
+/* Internal FMan Cc Node Management Info */
+struct dpa_cls_tbl_cc_node_info {
+
+ /* Low level driver (FMD) handle of the Cc node */
+ void *cc_node;
+
+ /* The size of this Cc node's lookup table */
+ unsigned int table_size;
+
+ /*
+ * Number of entries in the lookup table that are
+ * currently in use
+ */
+ unsigned int used;
+};
+
+/* DPA Classifier Table Control Data Structure */
+struct dpa_cls_table {
+
+ /* Array of shadow tables. NULL if there are none. */
+ struct dpa_cls_tbl_shadow_table *shadow_table;
+
+ /*
+ * Array of internally managed FMan Cc nodes. NULL
+ * if there are none beside the initial Cc node (provided
+ * by the application).
+ */
+ struct dpa_cls_tbl_cc_node_info *int_cc_node;
+
+ /*
+ * Number of internally managed FMan Cc nodes in the
+ * int_cc_node array
+ */
+ unsigned int int_cc_nodes_count;
+
+ /*
+ * The mask that is used on the CRC64 HASH result to find
+ * the HASH set for DPA Classifier HASH tables. This is of
+ * no use for types of DPA Classifier tables other than
+ * HASH.
+ */
+ uint64_t hash_mask;
+
+ /* Index management array. */
+ struct dpa_cls_tbl_entry *entry;
+
+ /* Number of entries in the index management array. */
+ unsigned int entries_cnt;
+
+ /*
+ * Linked list storing the index management entries
+ * which are in use.
+ */
+ struct list_head entry_list;
+
+ /* (Initial) parameters of the DPA Classifier table. */
+ struct dpa_cls_tbl_params params;
+
+ /* Table miss action. */
+ struct dpa_cls_tbl_action miss_action;
+
+ /* Access control object for this table to avoid race conditions. */
+ struct mutex access;
+};
+
+/* Definition of a generic descriptor table */
+struct dpa_cls_descriptor_table {
+ /* Total number of descriptors in the table */
+ unsigned int num_descriptors;
+
+ /* Number of currently used descriptors */
+ unsigned int used_descriptors;
+
+ /* Array of descriptors */
+ void **object;
+
+ /*
+ * Access control object for this descriptor table to avoid race
+ * conditions
+ */
+ struct mutex *access;
+};
+
+struct dpa_cls_hm_node {
+ /* Handle to the FMan header manip node */
+ void *node;
+
+ /* The flags indicate certain properties of the current nodes */
+ unsigned flags;
+
+ /* Used to keep count of the references to this header manip node */
+ unsigned ref;
+
+ /* Stores the low level driver parameters of this header manip node */
+ t_FmPcdManipParams params;
+
+ /* Links to other header manip nodes in the current chain */
+ struct list_head list_node;
+};
+
+enum dpa_cls_hm_node_type {
+ DPA_CLS_HM_NODE_IPv4_HDR_UPDATE,
+ DPA_CLS_HM_NODE_IPv6_HDR_UPDATE,
+ DPA_CLS_HM_NODE_TCPUDP_HDR_UPDATE,
+ DPA_CLS_HM_NODE_HDR_REPLACE_IPv4_BY_IPv6,
+ DPA_CLS_HM_NODE_HDR_REPLACE_IPv6_BY_IPv4,
+ DPA_CLS_HM_NODE_LAST_ENTRY
+};
+
+enum dpa_cls_hm_type {
+ DPA_CLS_HM_TYPE_NAT,
+ DPA_CLS_HM_TYPE_FORWARDING,
+ DPA_CLS_HM_TYPE_REMOVE,
+ DPA_CLS_HM_TYPE_INSERT,
+ DPA_CLS_HM_TYPE_UPDATE,
+ DPA_CLS_HM_TYPE_VLAN,
+ DPA_CLS_HM_TYPE_MPLS,
+ DPA_CLS_HM_TYPE_STATIC,
+ DPA_CLS_HM_LAST_ENTRY
+};
+
+struct dpa_cls_hm {
+ /* Type of this high level HM operation */
+ enum dpa_cls_hm_type type;
+
+ /* Indicates whether this op is the chain head or not */
+ bool chain_head;
+
+ union {
+ /* Stores parameters for a NAT type header manipulation op */
+ struct dpa_cls_hm_nat_params nat_params;
+
+ /*
+ * Stores parameters for a Forwarding type header manipulation
+ * op
+ */
+ struct dpa_cls_hm_fwd_params fwd_params;
+
+ /* Stores parameters for a remove header manipulation op */
+ struct dpa_cls_hm_remove_params remove_params;
+
+ /* Stores parameters for an insert header manipulation op */
+ struct dpa_cls_hm_insert_params insert_params;
+
+ /* Stores parameters for an update header manipulation op */
+ struct dpa_cls_hm_update_params update_params;
+
+ /*
+ * Stores parameters for a VLAN specific header manipulation
+ * op
+ */
+ struct dpa_cls_hm_vlan_params vlan_params;
+
+ /*
+ * Stores parameters for a MPLS specific header manipulation
+ * op
+ */
+ struct dpa_cls_hm_mpls_params mpls_params;
+ };
+
+ /*
+ * Holds references to the low level driver manip nodes used to
+ * implement the current high level header manipulation op
+ */
+ struct dpa_cls_hm_node *hm_node[DPA_CLS_HM_MAX_NODES_PER_OP];
+
+ /* Specifies the number of used items in the [hm_node] array */
+ unsigned int num_nodes;
+
+ /* Pointer to the low level driver HM manip node chain */
+ struct list_head *hm_chain;
+
+ /*
+ * Links to other high level header manipulation ops in the current
+ * chain
+ */
+ struct list_head list_node;
+
+ /*
+ * Access control object for this header manipulation op to avoid race
+ * conditions.
+ */
+ struct mutex access;
+};
+
+#if (DPAA_VERSION >= 11)
+
+struct members {
+ bool used;
+ int hmd;
+};
+
+struct dpa_cls_mcast_group {
+ /*
+ * Group descriptor
+ */
+ int grpd;
+
+ /*
+ * Group parameters
+ */
+ struct dpa_cls_mcast_group_params group_params;
+
+ /*
+ * Current number of members
+ */
+ unsigned int num_members;
+
+ /*
+ * Members' ids used in the group
+ */
+ struct members *entries;
+
+ /*
+ * Members' id array.
+ */
+ int *member_ids;
+
+ /*
+ * Index of the last member in group
+ */
+ int last_index;
+
+ /*
+ * Group handle
+ */
+ void *group;
+
+ /* Access control object for the group to avoid race conditions. */
+ struct mutex access;
+};
+#endif /* (DPAA_VERSION >= 11) */
+
+#ifdef __DPA_CLASSIFIER_C
+/*
+ * Allocates the array of internally managed Cc nodes based on
+ * their number. The number of internally managed Cc nodes must
+ * be set in the table control structure before calling this
+ * function.
+ */
+static int alloc_table_management(struct dpa_cls_table *cls_table);
+
+/*
+ * Releases resources related to the array of internally managed
+ * Cc nodes.
+ */
+static void free_table_management(struct dpa_cls_table *cls_table);
+
+/* Initialize an indexed table. */
+static int table_init_indexed(struct dpa_cls_table *cls_table);
+
+/* Initialize a hash table. */
+static int table_init_hash(struct dpa_cls_table *cls_table);
+
+/* Initialize an exact match table. */
+static int table_init_exact_match(struct dpa_cls_table *cls_table);
+
+/* Clean up after an indexed table */
+static void table_cleanup_indexed(struct dpa_cls_table *cls_table);
+
+/*
+ * Runs a verification of the table parameters against certain
+ * ranges and limitations.
+ */
+static int verify_table_params(const struct dpa_cls_tbl_params *params);
+
+static int flush_table(struct dpa_cls_table *ptable);
+
+static int table_modify_entry_by_ref(struct dpa_cls_table *ptable,
+ int entry_id,
+ const struct dpa_cls_tbl_entry_mod_params *mod_params);
+
+static int table_delete_entry_by_ref(struct dpa_cls_table *ptable,
+ int entry_id);
+
+static int table_get_entry_stats_by_ref(struct dpa_cls_table *ptable,
+ int entry_id,
+ struct dpa_cls_tbl_entry_stats *stats);
+
+/*
+ * Finds a specified entry in the shadow tables. The entry is
+ * identified by its lookup key.
+ */
+static struct list_head *find_shadow_entry(const struct dpa_cls_table
+ *cls_table, const struct dpa_offload_lookup_key *key);
+
+/* Add a new entry in an exact match table. */
+static int table_insert_entry_exact_match(struct dpa_cls_table *cls_table,
+ const struct dpa_offload_lookup_key *key,
+ const struct dpa_cls_tbl_action *action,
+ int priority,
+ int *entry_id);
+
+/* Add a new entry in a hash table. */
+static int table_insert_entry_hash(struct dpa_cls_table *cls_table,
+ const struct dpa_offload_lookup_key *key,
+ const struct dpa_cls_tbl_action *action,
+ int *entry_id);
+
+/*
+ * Translates action parameters into next engine parameters for use with the
+ * low level driver (FMD).
+ */
+static int action_to_next_engine_params(const struct dpa_cls_tbl_action
+ *action, t_FmPcdCcNextEngineParams *next_engine_params, int *hmd,
+ t_Handle distribution, t_Handle classification);
+
+/*
+ * Translates next engine parameters (from FMD) into action parameters for use
+ * with the DPA Classifier.
+ */
+static int next_engine_params_to_action(const t_FmPcdCcNextEngineParams
+ *next_engine_params, struct dpa_cls_tbl_action *action);
+
+/*
+ * Finds the entry_id reference of a table entry specified
+ * by key. This works only on tables managed by key.
+ */
+static int key_to_entry_id(const struct dpa_cls_table *cls_table,
+ const struct dpa_offload_lookup_key *key);
+
+/*
+ * Finds the table which is based on a specified Cc node and returns its
+ * descriptor.
+ */
+static int handle_to_td(void *cc_node);
+
+static inline void lock_desc_table(struct dpa_cls_descriptor_table
+ *desc_table);
+
+static inline void release_desc_table(struct dpa_cls_descriptor_table
+ *desc_table);
+
+static void *desc_to_object(struct dpa_cls_descriptor_table *desc_table,
+ int desc);
+
+/*
+ * Gets the first free descriptor in the indicated descriptor table and fills
+ * it with the provided object pointer. In case there are no available
+ * descriptors (or the descriptor table doesn't exist at all), the function
+ * will attempt to extend the descriptor table (or create it).
+ */
+static int acquire_descriptor(struct dpa_cls_descriptor_table
+ *desc_table, void *object, int *desc);
+
+/*
+ * Releases a descriptor to a descriptor table. In case the descriptor table
+ * is completely empty, the function removes the descriptor table.
+ */
+static inline void put_descriptor(struct dpa_cls_descriptor_table *desc_table,
+ int desc);
+
+/*
+ * Applies the key mask on the key and provides the updated key
+ * in a new buffer.
+ */
+static inline void key_apply_mask(const struct dpa_offload_lookup_key *key,
+ uint8_t *new_key);
+
+/*
+ * Finds in a chain of low level header manipulation nodes a node which is
+ * compatible with a specific operation, so that the node can be reused.
+ */
+static struct dpa_cls_hm_node
+ *find_compatible_hm_node(enum dpa_cls_hm_node_type type,
+ struct list_head *list);
+
+/*
+ * Import a set of low level header manipulation nodes into an existing
+ * low level header manipulation nodes list (associated with a classifier
+ * header manipulation op).
+ */
+static int import_hm_nodes_to_chain(void * const *node_array,
+ unsigned int num_nodes, struct dpa_cls_hm *hm);
+
+/* Initializes a chain (list) of low level header manipulation nodes. */
+static int init_hm_chain(void *fm_pcd, struct list_head *chain_head,
+ struct list_head *item);
+
+/* Removes a chain (list) of low level header manipulation nodes. */
+static int remove_hm_chain(struct list_head *chain_head,
+ struct list_head *item);
+
+/* Removes a low level (FMD) header manipulation node */
+static void remove_hm_node(struct dpa_cls_hm_node *node);
+
+/*
+ * Creates a new classifier header manipulation object and links it to an
+ * existing object if needed.
+ */
+static int create_new_hm_op(int *hmd, int next_hmd);
+
+static void remove_hm_op(int hmd);
+
+/*
+ * Verifies that the parameters provided for a NAT type header manipulation op
+ * are correct.
+ */
+static int nat_hm_check_params(const struct dpa_cls_hm_nat_params *nat_params);
+
+/*
+ * Prepares (creates or imports) the header manipulation nodes for a NAT type
+ * header manipulation op.
+ */
+static int nat_hm_prepare_nodes(struct dpa_cls_hm *pnat_hm,
+ const struct dpa_cls_hm_nat_resources *res);
+
+/* Fills in the parameters of the header manipulation nodes */
+static int nat_hm_update_params(struct dpa_cls_hm *pnat_hm);
+
+/*
+ * Verifies that the parameters provided for a Forwarding type header
+ * manipulation op are correct.
+ */
+static int fwd_hm_check_params(const struct dpa_cls_hm_fwd_params *fwd_params);
+
+/*
+ * Prepares (creates or imports) the header manipulation nodes for a Forwarding
+ * type header manipulation op.
+ */
+static int fwd_hm_prepare_nodes(struct dpa_cls_hm *pfwd_hm,
+ const struct dpa_cls_hm_fwd_resources *res);
+
+/* Fills in the parameters of the header manipulation nodes */
+static int fwd_hm_update_params(struct dpa_cls_hm *pfwd_hm);
+
+/*
+ * Verifies that the parameters provided for a header remove header
+ * manipulation op are correct.
+ */
+static int remove_hm_check_params(const struct dpa_cls_hm_remove_params
+ *remove_params);
+
+/*
+ * Prepares (creates or imports) the header manipulation nodes for a remove
+ * header manipulation op.
+ */
+static int remove_hm_prepare_nodes(struct dpa_cls_hm *premove_hm,
+ const struct dpa_cls_hm_remove_resources *res);
+
+/* Fills in the parameters of the header manipulation nodes */
+static int remove_hm_update_params(struct dpa_cls_hm *premove_hm);
+
+/*
+ * Verifies that the parameters provided for a header insert header
+ * manipulation op are correct.
+ */
+static int insert_hm_check_params(const struct dpa_cls_hm_insert_params
+ *insert_params);
+
+/*
+ * Prepares (creates or imports) the header manipulation nodes for an insert
+ * header manipulation op.
+ */
+static int insert_hm_prepare_nodes(struct dpa_cls_hm *pinsert_hm,
+ const struct dpa_cls_hm_insert_resources *res);
+
+/* Fills in the parameters of the header manipulation nodes */
+static int insert_hm_update_params(struct dpa_cls_hm *pinsert_hm);
+
+/*
+ * Verifies that the parameters provided for a header update header
+ * manipulation op are correct.
+ */
+static int update_hm_check_params(const struct dpa_cls_hm_update_params
+ *update_params);
+
+/*
+ * Prepares (creates or imports) the header manipulation nodes for an update
+ * header manipulation op.
+ */
+static int update_hm_prepare_nodes(struct dpa_cls_hm *pupdate_hm,
+ const struct dpa_cls_hm_update_resources *res);
+
+/* Fills in the parameters of the header manipulation nodes */
+static int update_hm_update_params(struct dpa_cls_hm *pupdate_hm);
+
+/*
+ * Verifies that the parameters provided for a VLAN specific header
+ * manipulation op are correct.
+ */
+static int
+ vlan_hm_check_params(const struct dpa_cls_hm_vlan_params *vlan_params);
+
+/*
+ * Prepares (creates or imports) the header manipulation nodes for a VLAN
+ * specific header manipulation.
+ */
+static int vlan_hm_prepare_nodes(struct dpa_cls_hm *pvlan_hm,
+ const struct dpa_cls_hm_vlan_resources *res);
+
+/* Fills in the parameters of the header manipulation nodes */
+static int vlan_hm_update_params(struct dpa_cls_hm *pvlan_hm);
+
+/*
+ * Verifies that the parameters provided for a MPLS specific header
+ * manipulation op are correct.
+ */
+static int mpls_hm_check_params(const struct dpa_cls_hm_mpls_params
+ *mpls_params);
+
+/*
+ * Prepares (creates or imports) the header manipulation nodes for a MPLS
+ * specific header manipulation.
+ */
+static int mpls_hm_prepare_nodes(struct dpa_cls_hm *pmpls_hm,
+ const struct dpa_cls_hm_mpls_resources *res);
+
+/* Fills in the parameters of the header manipulation nodes */
+static int mpls_hm_update_params(struct dpa_cls_hm *pmpls_hm);
+
+
+#endif /*__DPA_CLASSIFIER_C */
+
+/* Display a lookup key and its mask */
+void dump_lookup_key(const struct dpa_offload_lookup_key *key);
+
+/*
+ * Imports a header manipulation defined using the low level driver (FMD) API,
+ * for use with DPA Classifier
+ */
+int dpa_classif_import_static_hm(void *hm, int next_hmd, int *hmd);
+
+/*
+ * Provides the FMan driver handle of the static header manipulation associated
+ * with a specified header manipulation descriptor
+ */
+void *dpa_classif_get_static_hm_handle(int hmd);
+
+/*
+ * Provides details about the miss action configured on a classification
+ * table.
+ */
+int dpa_classif_get_miss_action(int td, struct dpa_cls_tbl_action *miss_action);
+
+/*
+ * Locks a header manipulation chain (marks as "used"). The header manipulation
+ * operations cannot be removed as long as they are locked. The function
+ * provides the FMan driver handle of the manip node which is chain head.
+ */
+void *dpa_classif_hm_lock_chain(int hmd);
+
+/* Releases a locked header manipulation chain. */
+void dpa_classif_hm_release_chain(int hmd);
+
+/* Tells whether a specific header manipulation operation is a chain head */
+bool dpa_classif_hm_is_chain_head(int hmd);
+
+/*
+ * Given a header manipulation object descriptor, this function searches
+ * through the header manipulation chain that this object belongs to and
+ * provides the FMan driver handle of the IP fragmentation header manipulation
+ * node.
+ */
+void *dpa_classif_get_frag_hm_handle(int hmd);
+
+
+#endif /* __DPA_CLASSIFIER_H */
diff --git a/drivers/staging/fsl_dpa_offload/dpa_classifier_ioctl.h b/drivers/staging/fsl_dpa_offload/dpa_classifier_ioctl.h
new file mode 100644
index 0000000..88a157c
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dpa_classifier_ioctl.h
@@ -0,0 +1,847 @@
+
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * DPA Classifier Wrapper Application Programming Interface
+ */
+
+#ifndef __DPA_CLASSIFIER_IOCTL_H
+#define __DPA_CLASSIFIER_IOCTL_H
+
+
+/* Other includes */
+#include "linux/ioctl.h"
+#include <linux/compat.h>
+
+
+#define DPA_CLS_IOC_MAGIC 0xbe
+
+
+struct ioc_dpa_cls_tbl_params {
+ struct dpa_cls_tbl_params table_params;
+ int td;
+};
+
+struct ioc_dpa_cls_tbl_miss_action {
+ int td;
+ struct dpa_cls_tbl_action miss_action;
+};
+
+struct ioc_dpa_cls_tbl_entry_params {
+ int td;
+ struct dpa_offload_lookup_key key;
+ struct dpa_cls_tbl_action action;
+ int priority;
+ int entry_id;
+};
+
+struct ioc_dpa_cls_tbl_entry_mod_by_key {
+ int td;
+ struct dpa_offload_lookup_key key;
+ struct dpa_cls_tbl_entry_mod_params mod_params;
+};
+
+struct ioc_dpa_cls_tbl_entry_mod_by_ref {
+ int td;
+ int entry_id;
+ struct dpa_cls_tbl_entry_mod_params mod_params;
+};
+
+struct ioc_dpa_cls_tbl_entry_by_key {
+ int td;
+ struct dpa_offload_lookup_key key;
+};
+
+struct ioc_dpa_cls_tbl_entry_by_ref {
+ int td;
+ int entry_id;
+};
+
+struct ioc_dpa_cls_tbl_lookup_by_key {
+ int td;
+ struct dpa_offload_lookup_key key;
+ struct dpa_cls_tbl_action action;
+};
+
+struct ioc_dpa_cls_tbl_lookup_by_ref {
+ int td;
+ int entry_id;
+ struct dpa_cls_tbl_action action;
+};
+
+struct ioc_dpa_cls_tbl_entry_stats_by_key {
+ int td;
+ struct dpa_offload_lookup_key key;
+ struct dpa_cls_tbl_entry_stats stats;
+};
+
+struct ioc_dpa_cls_tbl_entry_stats_by_ref {
+ int td;
+ int entry_id;
+ struct dpa_cls_tbl_entry_stats stats;
+};
+
+struct ioc_dpa_cls_hm_remove_params {
+ struct dpa_cls_hm_remove_params rm_params;
+ int next_hmd;
+ int hmd;
+ struct dpa_cls_hm_remove_resources res;
+ bool chain_head;
+ int modify_flags;
+};
+
+struct ioc_dpa_cls_hm_insert_params {
+ struct dpa_cls_hm_insert_params ins_params;
+ int next_hmd;
+ int hmd;
+ struct dpa_cls_hm_insert_resources res;
+ bool chain_head;
+ int modify_flags;
+};
+
+struct ioc_dpa_cls_hm_vlan_params {
+ struct dpa_cls_hm_vlan_params vlan_params;
+ int next_hmd;
+ int hmd;
+ struct dpa_cls_hm_vlan_resources res;
+ bool chain_head;
+ int modify_flags;
+};
+
+struct ioc_dpa_cls_hm_nat_params {
+ struct dpa_cls_hm_nat_params nat_params;
+ int next_hmd;
+ int hmd;
+ struct dpa_cls_hm_nat_resources res;
+ bool chain_head;
+ int modify_flags;
+};
+
+struct ioc_dpa_cls_hm_update_params {
+ struct dpa_cls_hm_update_params update_params;
+ int next_hmd;
+ int hmd;
+ struct dpa_cls_hm_update_resources res;
+ bool chain_head;
+ int modify_flags;
+};
+
+struct ioc_dpa_cls_hm_fwd_params {
+ struct dpa_cls_hm_fwd_params fwd_params;
+ int next_hmd;
+ int hmd;
+ struct dpa_cls_hm_fwd_resources res;
+ bool chain_head;
+ int modify_flags;
+};
+
+struct ioc_dpa_cls_hm_mpls_params {
+ struct dpa_cls_hm_mpls_params mpls_params;
+ int next_hmd;
+ int hmd;
+ struct dpa_cls_hm_mpls_resources res;
+ bool chain_head;
+ int modify_flags;
+};
+
+struct ioc_dpa_cls_mcast_group_params {
+ struct dpa_cls_mcast_group_params mcast_grp_params;
+ int grpd;
+ struct dpa_cls_mcast_group_resources res;
+};
+
+struct ioc_dpa_cls_mcast_member_params {
+ int grpd;
+ struct dpa_cls_tbl_enq_action_desc member_params;
+ int md;
+};
+
+struct ioc_dpa_cls_mcast_remove_params {
+ int grpd;
+ int md;
+};
+
+
+#ifdef CONFIG_COMPAT
+
+struct dpa_cls_compat_tbl_params {
+ compat_uptr_t cc_node;
+ compat_uptr_t distribution;
+ compat_uptr_t classification;
+ enum dpa_cls_tbl_type type;
+ enum dpa_cls_tbl_entry_mgmt entry_mgmt;
+ union {
+ struct dpa_cls_tbl_hash_params hash_params;
+ struct dpa_cls_tbl_indexed_params indexed_params;
+ struct dpa_cls_tbl_exact_match_params exact_match_params;
+ };
+ unsigned int prefilled_entries;
+};
+
+struct compat_ioc_dpa_cls_tbl_params {
+ struct dpa_cls_compat_tbl_params table_params;
+ int td;
+};
+
+struct dpa_cls_compat_tbl_enq_action_desc {
+ bool override_fqid;
+ uint32_t new_fqid;
+ compat_uptr_t policer_params;
+ int hmd;
+ uint8_t new_rel_vsp_id;
+};
+
+struct dpa_cls_compat_tbl_action {
+ enum dpa_cls_tbl_action_type type;
+ bool enable_statistics;
+ union {
+ struct dpa_cls_compat_tbl_enq_action_desc enq_params;
+ struct dpa_cls_tbl_next_table_desc next_table_params;
+ struct dpa_cls_tbl_mcast_group_desc mcast_params;
+ };
+};
+
+struct compat_ioc_dpa_cls_tbl_miss_action {
+ int td;
+ struct dpa_cls_compat_tbl_action miss_action;
+};
+
+struct compat_ioc_dpa_offld_lookup_key {
+ compat_uptr_t byte;
+ compat_uptr_t mask;
+ uint8_t size;
+};
+
+struct compat_ioc_dpa_cls_tbl_entry_by_key {
+ int td;
+ struct compat_ioc_dpa_offld_lookup_key key;
+};
+
+struct compat_ioc_dpa_cls_tbl_entry_stats_by_key {
+ int td;
+ struct compat_ioc_dpa_offld_lookup_key key;
+ struct dpa_cls_tbl_entry_stats stats;
+};
+
+struct compat_ioc_dpa_cls_tbl_entry_params {
+ int td;
+ struct compat_ioc_dpa_offld_lookup_key key;
+ struct dpa_cls_compat_tbl_action action;
+ int priority;
+ int entry_id;
+};
+
+struct dpa_cls_compat_tbl_entry_mod_params {
+ enum dpa_cls_tbl_modify_type type;
+ compat_uptr_t key;
+ compat_uptr_t action;
+};
+
+struct compat_ioc_dpa_cls_tbl_entry_mod_by_key {
+ int td;
+ struct compat_ioc_dpa_offld_lookup_key key;
+ struct dpa_cls_compat_tbl_entry_mod_params mod_params;
+};
+
+struct compat_ioc_dpa_cls_tbl_entry_mod_by_ref {
+ int td;
+ int entry_id;
+ struct dpa_cls_compat_tbl_entry_mod_params mod_params;
+};
+
+struct compat_ioc_dpa_cls_tbl_lookup_by_key {
+ int td;
+ struct compat_ioc_dpa_offld_lookup_key key;
+ struct dpa_cls_compat_tbl_action action;
+};
+
+struct compat_ioc_dpa_cls_tbl_lookup_by_ref {
+ int td;
+ int entry_id;
+ struct dpa_cls_compat_tbl_action action;
+};
+
+struct dpa_cls_compat_hm_remove_resources {
+ compat_uptr_t remove_node;
+};
+
+struct dpa_cls_compat_hm_remove_params {
+ enum dpa_cls_hm_remove_type type;
+ struct dpa_cls_hm_custom_rm_params custom;
+ compat_uptr_t fm_pcd;
+};
+
+struct compat_ioc_dpa_cls_hm_remove_params {
+ struct dpa_cls_compat_hm_remove_params rm_params;
+ int next_hmd;
+ int hmd;
+ struct dpa_cls_compat_hm_remove_resources res;
+ bool chain_head;
+ int modify_flags;
+};
+
+struct dpa_cls_compat_hm_insert_resources {
+ compat_uptr_t insert_node;
+};
+
+struct dpa_cls_compat_hm_custom_ins_params {
+ uint8_t offset;
+ uint8_t size;
+ compat_uptr_t data;
+};
+
+struct dpa_cls_compat_hm_insert_params {
+ enum dpa_cls_hm_insert_type type;
+ union {
+ struct dpa_cls_hm_eth_ins_params eth;
+ struct dpa_cls_hm_pppoe_ins_params pppoe;
+ uint16_t ppp_pid;
+ struct dpa_cls_compat_hm_custom_ins_params custom;
+ };
+ compat_uptr_t fm_pcd;
+};
+
+struct compat_ioc_dpa_cls_hm_insert_params {
+ struct dpa_cls_compat_hm_insert_params ins_params;
+ int next_hmd;
+ int hmd;
+ struct dpa_cls_compat_hm_insert_resources res;
+ bool chain_head;
+ int modify_flags;
+};
+
+struct dpa_cls_compat_hm_vlan_params {
+ enum dpa_cls_hm_vlan_type type;
+ union {
+ struct dpa_cls_hm_ingress_vlan_params ingress;
+ struct dpa_cls_hm_egress_vlan_params egress;
+ };
+ compat_uptr_t fm_pcd;
+};
+
+struct dpa_cls_compat_hm_vlan_resources {
+ compat_uptr_t vlan_node;
+};
+
+struct compat_ioc_dpa_cls_hm_vlan_params {
+ struct dpa_cls_compat_hm_vlan_params vlan_params;
+ int next_hmd;
+ int hmd;
+ struct dpa_cls_compat_hm_vlan_resources res;
+ bool chain_head;
+ int modify_flags;
+};
+
+struct compat_ipv4_header {
+ struct iphdr header;
+ compat_uptr_t options;
+ uint8_t options_size;
+};
+
+struct dpa_cls_compat_hm_nat_pt_params {
+ enum dpa_cls_hm_nat_pt_type type;
+
+ union {
+ struct compat_ipv4_header ipv4;
+ struct ipv6_header ipv6;
+ } new_header;
+};
+
+struct dpa_cls_compat_hm_nat_params {
+ int flags;
+ enum dpa_cls_hm_nat_proto proto;
+ enum dpa_cls_hm_nat_type type;
+ union {
+ struct dpa_cls_hm_traditional_nat_params nat;
+ struct dpa_cls_compat_hm_nat_pt_params nat_pt;
+ };
+ uint16_t sport;
+ uint16_t dport;
+ compat_uptr_t fm_pcd;
+};
+
+struct dpa_cls_compat_hm_nat_resources {
+ compat_uptr_t l3_update_node;
+ compat_uptr_t l4_update_node;
+};
+
+struct compat_ioc_dpa_cls_hm_nat_params {
+ struct dpa_cls_compat_hm_nat_params nat_params;
+ int next_hmd;
+ int hmd;
+ struct dpa_cls_compat_hm_nat_resources res;
+ bool chain_head;
+ int modify_flags;
+};
+
+struct dpa_cls_compat_hm_update_params {
+ int op_flags;
+ union {
+ struct compat_ipv4_header new_ipv4_hdr;
+ struct ipv6_header new_ipv6_hdr;
+ } replace;
+ union {
+ struct dpa_cls_hm_l3_update_params l3;
+ struct dpa_cls_hm_l4_update_params l4;
+ } update;
+ struct dpa_cls_hm_ip_frag_params ip_frag_params;
+ compat_uptr_t fm_pcd;
+};
+
+struct dpa_cls_compat_hm_update_resources {
+ compat_uptr_t update_node;
+ compat_uptr_t ip_frag_node;
+
+};
+
+struct compat_ioc_dpa_cls_hm_update_params {
+ struct dpa_cls_compat_hm_update_params update_params;
+ int next_hmd;
+ int hmd;
+ struct dpa_cls_compat_hm_update_resources res;
+ bool chain_head;
+ int modify_flags;
+};
+
+struct dpa_cls_compat_hm_fwd_params {
+ enum dpa_cls_hm_out_if_type out_if_type;
+ union {
+ struct dpa_cls_hm_fwd_l2_param eth;
+ struct dpa_cls_hm_fwd_pppoe_param pppoe;
+ struct dpa_cls_hm_fwd_ppp_param ppp;
+ };
+ struct dpa_cls_hm_ip_frag_params ip_frag_params;
+ compat_uptr_t fm_pcd;
+};
+
+struct dpa_cls_compat_hm_fwd_resources {
+ compat_uptr_t fwd_node;
+ compat_uptr_t pppoe_node;
+ compat_uptr_t ip_frag_node;
+};
+
+struct compat_ioc_dpa_cls_hm_fwd_params {
+ struct dpa_cls_compat_hm_fwd_params fwd_params;
+ int next_hmd;
+ int hmd;
+ struct dpa_cls_compat_hm_fwd_resources res;
+ bool chain_head;
+ int modify_flags;
+};
+
+struct dpa_cls_compat_hm_mpls_params {
+ enum dpa_cls_hm_mpls_type type;
+ struct mpls_header mpls_hdr[DPA_CLS_HM_MAX_MPLS_LABELS];
+ unsigned int num_labels;
+ compat_uptr_t fm_pcd;
+};
+
+struct dpa_cls_compat_hm_mpls_resources {
+ compat_uptr_t ins_rm_node;
+};
+
+struct compat_ioc_dpa_cls_hm_mpls_params {
+ struct dpa_cls_compat_hm_mpls_params mpls_params;
+ int next_hmd;
+ int hmd;
+ struct dpa_cls_compat_hm_mpls_resources res;
+ bool chain_head;
+ int modify_flags;
+};
+
+struct dpa_cls_compat_mcast_group_params {
+ uint8_t max_members;
+ compat_uptr_t fm_pcd;
+ struct dpa_cls_compat_tbl_enq_action_desc first_member_params;
+ unsigned int prefilled_members;
+ compat_uptr_t distribution;
+ compat_uptr_t classification;
+};
+
+struct dpa_cls_compat_mcast_group_resources {
+ compat_uptr_t group_node;
+};
+
+struct compat_ioc_dpa_cls_mcast_group_params {
+ struct dpa_cls_compat_mcast_group_params mcast_grp_params;
+ int grpd;
+ struct dpa_cls_compat_mcast_group_resources res;
+};
+
+struct compat_ioc_dpa_cls_mcast_member_params {
+ int grpd;
+ struct dpa_cls_compat_tbl_enq_action_desc member_params;
+ int md;
+};
+
+int dpa_cls_tbl_entry_params_compatcpy(
+ struct ioc_dpa_cls_tbl_entry_params *kparam,
+ const struct compat_ioc_dpa_cls_tbl_entry_params *uparam);
+
+int dpa_cls_tbl_params_compatcpy(
+ struct ioc_dpa_cls_tbl_params *kparam,
+ const struct compat_ioc_dpa_cls_tbl_params *uparam);
+
+int dpa_cls_tbl_params_rcompatcpy(
+ struct compat_ioc_dpa_cls_tbl_params *uparam,
+ const struct ioc_dpa_cls_tbl_params *kparam);
+
+int dpa_cls_tbl_miss_action_params_compatcpy(
+ struct ioc_dpa_cls_tbl_miss_action *kparam,
+ const struct compat_ioc_dpa_cls_tbl_miss_action *uparam);
+
+int dpa_cls_tbl_action_params_compatcpy(
+ struct dpa_cls_tbl_action *kparam,
+ const struct dpa_cls_compat_tbl_action *uparam);
+
+int dpa_cls_tbl_action_params_rcompatcpy(
+ struct dpa_cls_compat_tbl_action *uparam,
+ const struct dpa_cls_tbl_action *kparam);
+
+int dpa_cls_tbl_entry_mod_by_key_params_compatcpy(
+ struct ioc_dpa_cls_tbl_entry_mod_by_key *kparam,
+ const struct compat_ioc_dpa_cls_tbl_entry_mod_by_key *uparam);
+
+int dpa_cls_tbl_entry_mod_by_ref_params_compatcpy(
+ struct ioc_dpa_cls_tbl_entry_mod_by_ref *kparam,
+ const struct compat_ioc_dpa_cls_tbl_entry_mod_by_ref *uparam);
+
+int dpa_cls_tbl_entry_mod_params_compatcpy(
+ struct dpa_cls_tbl_entry_mod_params *kparam,
+ const struct dpa_cls_compat_tbl_entry_mod_params *uparam);
+
+int dpa_cls_tbl_entry_by_key_params_compatcpy(
+ struct ioc_dpa_cls_tbl_entry_by_key *kparam,
+ const struct compat_ioc_dpa_cls_tbl_entry_by_key *uparam);
+
+int dpa_cls_tbl_lookup_by_key_params_compatcpy(
+ struct ioc_dpa_cls_tbl_lookup_by_key *kparam,
+ const struct compat_ioc_dpa_cls_tbl_lookup_by_key *uparam);
+
+int dpa_cls_tbl_lookup_by_ref_params_compatcpy(
+ struct ioc_dpa_cls_tbl_lookup_by_ref *kparam,
+ const struct compat_ioc_dpa_cls_tbl_lookup_by_ref *uparam);
+
+int dpa_cls_tbl_entry_stats_by_key_params_compatcpy(
+ struct ioc_dpa_cls_tbl_entry_stats_by_key *kparam,
+ const struct compat_ioc_dpa_cls_tbl_entry_stats_by_key *uparam);
+
+int dpa_lookup_key_params_compatcpy(
+ struct dpa_offload_lookup_key *kparam,
+ const struct compat_ioc_dpa_offld_lookup_key *uparam);
+
+int dpa_cls_hm_remove_params_compatcpy(
+ struct ioc_dpa_cls_hm_remove_params *kparam,
+ const struct compat_ioc_dpa_cls_hm_remove_params *uparam);
+
+int dpa_cls_hm_insert_params_compatcpy(
+ struct ioc_dpa_cls_hm_insert_params *kparam,
+ const struct compat_ioc_dpa_cls_hm_insert_params *uparam);
+
+int dpa_cls_hm_vlan_params_compatcpy(
+ struct ioc_dpa_cls_hm_vlan_params *kparam,
+ const struct compat_ioc_dpa_cls_hm_vlan_params *uparam);
+
+int dpa_cls_hm_nat_params_compatcpy(
+ struct ioc_dpa_cls_hm_nat_params *kparam,
+ const struct compat_ioc_dpa_cls_hm_nat_params *uparam);
+
+int dpa_cls_hm_update_params_compatcpy(
+ struct ioc_dpa_cls_hm_update_params *kparam,
+ const struct compat_ioc_dpa_cls_hm_update_params *uparam);
+
+int dpa_cls_hm_fwd_params_compatcpy(
+ struct ioc_dpa_cls_hm_fwd_params *kparam,
+ const struct compat_ioc_dpa_cls_hm_fwd_params *uparam);
+
+int dpa_cls_hm_mpls_params_compatcpy(
+ struct ioc_dpa_cls_hm_mpls_params *kparam,
+ const struct compat_ioc_dpa_cls_hm_mpls_params *uparam);
+
+int dpa_cls_mcast_group_params_compatcpy(
+ struct ioc_dpa_cls_mcast_group_params *kparam,
+ const struct compat_ioc_dpa_cls_mcast_group_params *uparam);
+
+int dpa_cls_mcast_member_params_compatcpy(
+ struct ioc_dpa_cls_mcast_member_params *kparam,
+ const struct compat_ioc_dpa_cls_mcast_member_params *uparam);
+#endif /* CONFIG_COMPAT */
+
+
+#define DPA_CLS_IOC_TBL_CREATE \
+ _IOWR(DPA_CLS_IOC_MAGIC, 0, struct ioc_dpa_cls_tbl_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_TBL_CREATE \
+ _IOWR(DPA_CLS_IOC_MAGIC, 0, struct compat_ioc_dpa_cls_tbl_params)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_CLS_IOC_TBL_FREE \
+ _IOW(DPA_CLS_IOC_MAGIC, 1, int)
+
+#define DPA_CLS_IOC_TBL_MODIFY_MISS_ACTION \
+ _IOW(DPA_CLS_IOC_MAGIC, 2, struct ioc_dpa_cls_tbl_miss_action)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_TBL_MODIFY_MISS_ACTION \
+ _IOW(DPA_CLS_IOC_MAGIC, 2, struct compat_ioc_dpa_cls_tbl_miss_action)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_CLS_IOC_TBL_INSERT_ENTRY \
+ _IOWR(DPA_CLS_IOC_MAGIC, 3, struct ioc_dpa_cls_tbl_entry_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_TBL_INSERT_ENTRY \
+ _IOWR(DPA_CLS_IOC_MAGIC, 3, struct compat_ioc_dpa_cls_tbl_entry_params)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_CLS_IOC_TBL_MODIFY_ENTRY_BY_KEY \
+ _IOW(DPA_CLS_IOC_MAGIC, 4, struct ioc_dpa_cls_tbl_entry_mod_by_key)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_TBL_MODIFY_ENTRY_BY_KEY \
+ _IOW(DPA_CLS_IOC_MAGIC, 4, \
+ struct compat_ioc_dpa_cls_tbl_entry_mod_by_key)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_CLS_IOC_TBL_MODIFY_ENTRY_BY_REF \
+ _IOW(DPA_CLS_IOC_MAGIC, 5, struct ioc_dpa_cls_tbl_entry_mod_by_ref)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_TBL_MODIFY_ENTRY_BY_REF \
+ _IOW(DPA_CLS_IOC_MAGIC, 5, \
+ struct compat_ioc_dpa_cls_tbl_entry_mod_by_ref)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_CLS_IOC_TBL_DELETE_ENTRY_BY_KEY \
+ _IOW(DPA_CLS_IOC_MAGIC, 6, struct ioc_dpa_cls_tbl_entry_by_key)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_TBL_DELETE_ENTRY_BY_KEY \
+ _IOW(DPA_CLS_IOC_MAGIC, 6, \
+ struct compat_ioc_dpa_cls_tbl_entry_by_key)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_CLS_IOC_TBL_DELETE_ENTRY_BY_REF \
+ _IOW(DPA_CLS_IOC_MAGIC, 7, struct ioc_dpa_cls_tbl_entry_by_ref)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_TBL_DELETE_ENTRY_BY_REF \
+ _IOW(DPA_CLS_IOC_MAGIC, 7, \
+ struct compat_ioc_dpa_cls_tbl_entry_by_ref)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_CLS_IOC_TBL_LOOKUP_BY_KEY \
+ _IOR(DPA_CLS_IOC_MAGIC, 8, struct ioc_dpa_cls_tbl_lookup_by_key)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_TBL_LOOKUP_BY_KEY \
+ _IOR(DPA_CLS_IOC_MAGIC, 8, struct compat_ioc_dpa_cls_tbl_lookup_by_key)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_CLS_IOC_TBL_LOOKUP_BY_REF \
+ _IOR(DPA_CLS_IOC_MAGIC, 9, struct ioc_dpa_cls_tbl_lookup_by_ref)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_TBL_LOOKUP_BY_REF \
+ _IOR(DPA_CLS_IOC_MAGIC, 9, struct compat_ioc_dpa_cls_tbl_lookup_by_ref)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_CLS_IOC_TBL_FLUSH \
+ _IOW(DPA_CLS_IOC_MAGIC, 10, int)
+
+#define DPA_CLS_IOC_TBL_GET_STATS_BY_KEY \
+ _IOR(DPA_CLS_IOC_MAGIC, 11, struct ioc_dpa_cls_tbl_entry_stats_by_key)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_TBL_GET_STATS_BY_KEY \
+ _IOR(DPA_CLS_IOC_MAGIC, 11, \
+ struct compat_ioc_dpa_cls_tbl_entry_stats_by_key)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_CLS_IOC_TBL_GET_STATS_BY_REF \
+ _IOR(DPA_CLS_IOC_MAGIC, 12, struct ioc_dpa_cls_tbl_entry_stats_by_ref)
+
+#define DPA_CLS_IOC_TBL_GET_PARAMS \
+ _IOWR(DPA_CLS_IOC_MAGIC, 15, struct ioc_dpa_cls_tbl_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_TBL_GET_PARAMS \
+ _IOWR(DPA_CLS_IOC_MAGIC, 15, struct compat_ioc_dpa_cls_tbl_params)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_CLS_IOC_SET_REMOVE_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 16, struct ioc_dpa_cls_hm_remove_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_SET_REMOVE_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 16, \
+ struct compat_ioc_dpa_cls_hm_remove_params)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_CLS_IOC_MODIFY_REMOVE_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 17, struct ioc_dpa_cls_hm_remove_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_MODIFY_REMOVE_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 17, \
+ struct compat_ioc_dpa_cls_hm_remove_params)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_CLS_IOC_SET_INSERT_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 18, struct ioc_dpa_cls_hm_insert_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_SET_INSERT_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 18, \
+ struct compat_ioc_dpa_cls_hm_insert_params)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_CLS_IOC_MODIFY_INSERT_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 19, struct ioc_dpa_cls_hm_insert_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_MODIFY_INSERT_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 19, \
+ struct compat_ioc_dpa_cls_hm_insert_params)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_CLS_IOC_SET_VLAN_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 20, struct ioc_dpa_cls_hm_vlan_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_SET_VLAN_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 20, struct compat_ioc_dpa_cls_hm_vlan_params)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_CLS_IOC_MODIFY_VLAN_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 21, struct ioc_dpa_cls_hm_vlan_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_MODIFY_VLAN_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 21, struct compat_ioc_dpa_cls_hm_vlan_params)
+#endif /* CONFIG_COMPAT */
+
+
+#define DPA_CLS_IOC_SET_NAT_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 22, struct ioc_dpa_cls_hm_nat_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_SET_NAT_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 22, struct compat_ioc_dpa_cls_hm_nat_params)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_CLS_IOC_MODIFY_NAT_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 23, struct ioc_dpa_cls_hm_nat_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_MODIFY_NAT_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 23, struct compat_ioc_dpa_cls_hm_nat_params)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_CLS_IOC_SET_UPDATE_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 24, struct ioc_dpa_cls_hm_update_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_SET_UPDATE_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 24, struct compat_ioc_dpa_cls_hm_update_params)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_CLS_IOC_MODIFY_UPDATE_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 25, struct ioc_dpa_cls_hm_update_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_MODIFY_UPDATE_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 25, struct compat_ioc_dpa_cls_hm_update_params)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_CLS_IOC_SET_FWD_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 26, struct ioc_dpa_cls_hm_fwd_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_SET_FWD_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 26, struct compat_ioc_dpa_cls_hm_fwd_params)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_CLS_IOC_MODIFY_FWD_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 27, struct ioc_dpa_cls_hm_fwd_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_MODIFY_FWD_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 27, struct compat_ioc_dpa_cls_hm_fwd_params)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_CLS_IOC_SET_MPLS_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 28, struct ioc_dpa_cls_hm_mpls_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_SET_MPLS_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 28, struct compat_ioc_dpa_cls_hm_mpls_params)
+#endif
+
+#define DPA_CLS_IOC_MODIFY_MPLS_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 29, struct ioc_dpa_cls_hm_mpls_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_MODIFY_MPLS_HM \
+ _IOWR(DPA_CLS_IOC_MAGIC, 29, struct compat_ioc_dpa_cls_hm_mpls_params)
+#endif
+
+#define DPA_CLS_IOC_FREE_HM \
+ _IOR(DPA_CLS_IOC_MAGIC, 30, int)
+
+#define DPA_CLS_IOC_MCAST_CREATE_GROUP \
+ _IOWR(DPA_CLS_IOC_MAGIC, 31, struct ioc_dpa_cls_mcast_group_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_MCAST_CREATE_GROUP \
+ _IOWR(DPA_CLS_IOC_MAGIC, 31, \
+ struct compat_ioc_dpa_cls_mcast_group_params)
+#endif
+
+#define DPA_CLS_IOC_MCAST_ADD_MEMBER \
+ _IOWR(DPA_CLS_IOC_MAGIC, 32, struct ioc_dpa_cls_mcast_member_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_CLS_IOC_COMPAT_MCAST_ADD_MEMBER \
+ _IOWR(DPA_CLS_IOC_MAGIC, 32, \
+ struct compat_ioc_dpa_cls_mcast_member_params)
+#endif
+
+#define DPA_CLS_IOC_MCAST_REMOVE_MEMBER \
+ _IOWR(DPA_CLS_IOC_MAGIC, 33, struct ioc_dpa_cls_mcast_remove_params)
+
+#define DPA_CLS_IOC_MCAST_FREE_GROUP \
+ _IOWR(DPA_CLS_IOC_MAGIC, 34, int)
+
+
+#endif /* __DPA_CLASSIFIER_IOCTL_H */
diff --git a/drivers/staging/fsl_dpa_offload/dpa_ipsec.c b/drivers/staging/fsl_dpa_offload/dpa_ipsec.c
new file mode 100644
index 0000000..f6fcdbd
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dpa_ipsec.c
@@ -0,0 +1,5882 @@
+/* Copyright 2008-2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <linux/wait.h>
+
+#include "dpa_ipsec.h"
+#include "dpa_ipsec_desc.h"
+#include "dpa_classifier.h"
+
+#include "fm_common.h"
+#include "fm_pcd.h"
+
+/* DPA IPsec Mapping between API algorithm suites and SEC algorithm IDs */
+struct ipsec_alg_suite ipsec_algs[] = IPSEC_ALGS;
+
+/* globally allocated because of performance constraints */
+static t_FmPcdCcNodeParams cc_node_prms;
+
+/* Global dpa_ipsec component */
+struct dpa_ipsec *gbl_dpa_ipsec[MAX_DPA_IPSEC_INSTANCES];
+
+/* Spinlock protecting the global dpa ipsec vector */
+DEFINE_SPINLOCK(gbl_dpa_ipsec_lock);
+
+/* Wait for other tasks to finish when doing instance free */
+DECLARE_WAIT_QUEUE_HEAD(wait_queue);
+
+static int sa_flush_policies(struct dpa_ipsec_sa *sa);
+static int sa_rekeying_outbound(struct dpa_ipsec_sa *new_sa);
+static void *alloc_ipsec_manip(struct dpa_ipsec *dpa_ipsec);
+static void mark_unused_gbl_dpa_ipsec(int instance);
+static int remove_inbound_sa(struct dpa_ipsec_sa *sa);
+static int remove_outbound_sa(struct dpa_ipsec_sa *sa);
+static inline bool table_in_use(int td);
+
+/* Debug support functions */
+
+#ifdef DEBUG_PARAM
+int print_sa_sec_param(struct dpa_ipsec_sa *sa)
+{
+ int i;
+ struct dpa_ipsec_policy_entry *policy_entry, *tmp_policy_entry;
+ struct dpa_ipsec_policy_selectors *policy_selectors;
+
+ BUG_ON(!sa);
+
+ pr_info("\n Printing SA SEC PARAM for sa %p\n", sa);
+ pr_info("\n sa_dir = %d\n", sa->sa_dir);
+ pr_info("\n id = %d\n", sa->id);
+ pr_info(" dpa_ipsec addr = %p\n", sa->dpa_ipsec);
+ pr_info(" from_sec_fq addr = %p\n", sa->from_sec_fq);
+
+ pr_info("\n auth_data.auth_type = %d\n", sa->auth_data.auth_type);
+ pr_info("auth_data.auth_key_len = %d\n",
+ sa->auth_data.auth_key_len);
+ pr_info("auth_data.auth_key is\n");
+ for (i = 0; i < sa->auth_data.auth_key_len; i++)
+ pr_info("%x, ", sa->auth_data.auth_key[i]);
+
+ pr_info("\n cipher_data.cipher_type = %d\n",
+ sa->cipher_data.cipher_type);
+ pr_info("cipher_data.cipher_key_len = %d\n",
+ sa->cipher_data.cipher_key_len);
+ pr_info("cipher_data.cipher_key is\n");
+ for (i = 0; i < sa->cipher_data.cipher_key_len; i++)
+ pr_info("%x, ", sa->cipher_data.cipher_key[i]);
+
+ pr_info("\n sa_bpid = %d\n", sa->sa_bpid);
+ pr_info("\n sa_bufsize = %d\n", sa->sa_bufsize);
+ pr_info(" spi = %d\n", sa->spi);
+ pr_info(" sa_wqid = %d\n", sa->sa_wqid);
+ pr_info(" outbound_flowid = %d\n", sa->outbound_flowid);
+
+ pr_info("dest_addr.version = %d\n", sa->dest_addr.version);
+ pr_info("dest_addr = %x.%x.%x.%x\n",
+ sa->dest_addr.ipv4.byte[0],
+ sa->dest_addr.ipv4.byte[1],
+ sa->dest_addr.ipv4.byte[2], sa->dest_addr.ipv4.byte[3]);
+ pr_info("src_addr.version = %d\n", sa->src_addr.version);
+ pr_info("src_addr = %x.%x.%x.%x\n",
+ sa->src_addr.ipv4.byte[0],
+ sa->src_addr.ipv4.byte[1],
+ sa->src_addr.ipv4.byte[2], sa->src_addr.ipv4.byte[3]);
+
+ if (sa_is_outbound(sa)) {
+ uint8_t *out_hdr;
+ out_hdr = &sa->sec_desc->pdb_en.ip_hdr[0];
+ pr_info("Outer Header length %d\n",
+ sa->sec_desc->pdb_en.ip_hdr_len);
+ pr_info("Outer Header is:\n");
+ for (i = 0; i < sa->sec_desc->pdb_en.ip_hdr_len; i++)
+ pr_info("%x, ", *(out_hdr + i));
+
+ pr_info("pdb_en.ip_hdr_len %d\n",
+ sa->sec_desc->pdb_en.ip_hdr_len);
+ pr_info("pdb_en.spi = %d\n", sa->sec_desc->pdb_en.spi);
+ pr_info("pdb_en.seq_num = %d\n",
+ sa->sec_desc->pdb_en.seq_num);
+ pr_info("pdb_en.options = 0x%x\n",
+ sa->sec_desc->pdb_en.options);
+ pr_info("pdb_en.desc_hdr = 0x%x\n",
+ sa->sec_desc->pdb_en.desc_hdr);
+ pr_info("pdb_en.ip_nh = 0x%x\n",
+ sa->sec_desc->pdb_en.ip_nh);
+ } else {
+ pr_info("pdb_dec.hmo_ip_hdr_len %d\n",
+ sa->sec_desc->pdb_dec.hmo_ip_hdr_len);
+ pr_info("pdb_dec.options %d\n",
+ sa->sec_desc->pdb_dec.options);
+ pr_info("pdb_dec.seq_num %d\n",
+ sa->sec_desc->pdb_dec.seq_num);
+ }
+
+ pr_info("\n Printing all policies from this SA policy_list\n");
+ list_for_each_entry_safe(policy_entry, tmp_policy_entry,
+ &sa->policy_headlist, node) {
+ policy_selectors = &policy_entry->policy_selectors;
+ pr_info("policy_selectors src_addr.version = %d\n",
+ policy_selectors->src_addr.version);
+ pr_info("policy_selectors src_addr = %x.%x.%x.%x\n",
+ policy_selectors->src_addr.ipv4.byte[0],
+ policy_selectors->src_addr.ipv4.byte[1],
+ policy_selectors->src_addr.ipv4.byte[2],
+ policy_selectors->src_addr.ipv4.byte[3]);
+ pr_info("\n policy_selectors dest_addr.version = %d\n",
+ policy_selectors->dest_addr.version);
+ pr_info("policy_selectors dest_addr = %x.%x.%x.%x\n",
+ policy_selectors->dest_addr.ipv4.byte[0],
+ policy_selectors->dest_addr.ipv4.byte[1],
+ policy_selectors->dest_addr.ipv4.byte[2],
+ policy_selectors->dest_addr.ipv4.byte[3]);
+
+ pr_info("\n policy_selectors dest_port = %d\n",
+ policy_selectors->dest_port);
+ pr_info(" policy_selectors src_port = %d\n",
+ policy_selectors->src_port);
+ pr_info(" policy_selectors dest_port = %d\n",
+ policy_selectors->dest_port_mask);
+ pr_info(" policy_selectors dest_port = %d\n",
+ policy_selectors->src_port_mask);
+ pr_info(" policy_selectors proto = %d\n",
+ policy_selectors->protocol);
+ pr_info(" policy_selectors dest_prefix_len = %d\n",
+ policy_selectors->dest_prefix_len);
+ pr_info(" policy_selectors src_prefix_len = %d\n",
+ policy_selectors->src_prefix_len);
+ }
+ pr_info("\n Done printing SA SEC PARAM for sa %p\n", sa);
+
+ return 0;
+}
+#endif
+
+/* Initialization functions */
+
+/* store params needed during runtime or free */
+static inline void store_ipsec_params(struct dpa_ipsec *dpa_ipsec,
+ const struct dpa_ipsec_params *params)
+{
+ struct dpa_ipsec_pre_sec_out_params *pre_sec_out_params;
+ struct dpa_ipsec_pol_table *any_ipv4_table, *any_ipv6_table;
+ int i;
+
+ /* copy config params */
+ dpa_ipsec->config = *params;
+
+ /*
+ * reconfigure the array of outbound policy table parameters, in order
+ * to simplify the process of choosing the correct table during runtime
+ * add / remove policies operations
+ */
+
+ pre_sec_out_params = &dpa_ipsec->config.pre_sec_out_params;
+ /* get the desc for the ANY tables */
+ any_ipv4_table = &pre_sec_out_params->table[DPA_IPSEC_PROTO_ANY_IPV4];
+ any_ipv6_table = &pre_sec_out_params->table[DPA_IPSEC_PROTO_ANY_IPV6];
+
+ /*
+ * replace the parameters of a table for a specific protocol, if an
+ * invalid table desc was provided, with those of the corresponding ANY
+ * table for that IP version
+ */
+ for (i = 0; i < DPA_IPSEC_MAX_SUPPORTED_PROTOS - 2; i++) {
+ if (pre_sec_out_params->table[i].dpa_cls_td ==
+ DPA_OFFLD_DESC_NONE) {
+ /* IPV4 table desc are at even indexes (IPV6 at odd) */
+ if (i & 0x01)
+ pre_sec_out_params->table[i] = *any_ipv6_table;
+ else
+ pre_sec_out_params->table[i] = *any_ipv4_table;
+ }
+ }
+}
+
+/* check that the provided params are valid */
+static int check_ipsec_params(const struct dpa_ipsec_params *prms)
+{
+ const struct dpa_ipsec_pre_sec_out_params *pre_sec_out_prms;
+ const struct dpa_ipsec_pre_sec_in_params *pre_sec_in_prms;
+ struct dpa_cls_tbl_params table_params;
+ int i, err, valid_tables = 0, fqid_range_size, min_fqid_num;
+
+ if (!prms) {
+ log_err("Invalid DPA IPsec parameters handle\n");
+ return -EINVAL;
+ }
+
+ if ((prms->post_sec_in_params.do_pol_check) && (!prms->fm_pcd)) {
+ log_err("Provide a valid PCD handle to enable inbound policy check!\n");
+ return -EINVAL;
+ }
+
+ /*
+ * check that all required table descriptors were provided:
+ * - at least one table for outbound policy lookup
+ * - one table for index lookup after decryption
+ * - one table for SA lookup
+ */
+
+ /* check outbound policy tables */
+ pre_sec_out_prms = &prms->pre_sec_out_params;
+ for (i = 0; i < DPA_IPSEC_MAX_SUPPORTED_PROTOS; i++) {
+ int dpa_cls_td = pre_sec_out_prms->table[i].dpa_cls_td;
+ if (dpa_cls_td != DPA_OFFLD_DESC_NONE) {
+ /* verify that a valid key structure was configured */
+ if (!pre_sec_out_prms->table[i].key_fields) {
+ log_err("Invalid key struct. for out table %d\n",
+ i);
+ return -EINVAL;
+ }
+
+ /* verify that it is not an indexed table */
+ err = dpa_classif_table_get_params(dpa_cls_td,
+ &table_params);
+ if (err < 0) {
+ log_err("Couldn't check type of outbound policy lookup table\n");
+ return -EINVAL;
+ }
+
+ if (table_params.type == DPA_CLS_TBL_INDEXED) {
+ log_err("Outbound policy lookup table cannot be of type INDEXED\n");
+ return -EINVAL;
+ }
+ valid_tables++;
+
+ /* Check if this table is in use on other DPA instance*/
+ if (table_in_use(dpa_cls_td)) {
+ log_err("Table with ID %d is in use by another DPA IPsec instance\n",
+ dpa_cls_td);
+ return -EINVAL;
+ }
+ }
+ }
+
+ if (!valid_tables) {
+ log_err("Specify at least one table for outbound policy lookup\n");
+ return -EINVAL;
+ }
+
+ /*
+ * In classification base on SA that decrypted traffic is not required
+ * than the post decryption classification table could be invalid.
+ * In this case inbound policy verification is not supported.
+ */
+ if (prms->post_sec_in_params.dpa_cls_td == DPA_OFFLD_DESC_NONE) {
+ if (prms->post_sec_in_params.do_pol_check) {
+ log_err("Index table required policy check enabled\n");
+ return -EINVAL;
+ }
+ goto skip_post_decryption_check;
+ }
+
+ /* get post decryption table parameters */
+ err = dpa_classif_table_get_params(prms->post_sec_in_params.dpa_cls_td,
+ &table_params);
+ if (err < 0) {
+ log_err("Could not check type of post decryption table\n");
+ return -EINVAL;
+ }
+
+ /* verify that it is an indexed table */
+ if (table_params.type != DPA_CLS_TBL_INDEXED) {
+ log_err("Post decryption table must be of type INDEXED\n");
+ return -EINVAL;
+ }
+
+ /*
+ * verify that it can hold a flow ID value for each possible IN SA plus
+ * the reserved number of flow ID values (base_flow_id)
+ */
+ if (table_params.indexed_params.entries_cnt <
+ (prms->max_sa_pairs + prms->post_sec_in_params.base_flow_id)) {
+ log_err("The post decryption table size is to small!\n");
+ return -EINVAL;
+ }
+
+ if (prms->post_sec_in_params.dpa_cls_td > 0 &&
+ table_in_use(prms->post_sec_in_params.dpa_cls_td)) {
+ log_err("Table with ID %d is in use by another DPA IPsec instance\n",
+ prms->post_sec_in_params.dpa_cls_td);
+ return -EINVAL;
+ }
+
+
+skip_post_decryption_check:
+ /* check pre decryption SA lookup tables */
+ valid_tables = 0;
+ pre_sec_in_prms = &prms->pre_sec_in_params;
+ for (i = 0; i < DPA_IPSEC_MAX_SA_TYPE; i++)
+ if (pre_sec_in_prms->dpa_cls_td[i] != DPA_OFFLD_DESC_NONE) {
+ if (table_in_use(pre_sec_in_prms->dpa_cls_td[i])) {
+ log_err("Table with ID %d is in use by another DPA IPsec instance\n",
+ pre_sec_in_prms->dpa_cls_td[i]);
+ return -EINVAL;
+ }
+
+ /* verify that it is not an indexed table */
+ err = dpa_classif_table_get_params(
+ pre_sec_in_prms->dpa_cls_td[i],
+ &table_params);
+ if (err < 0) {
+ log_err("Couldn't check type of SA table\n");
+ return -EINVAL;
+ }
+
+ if (table_params.type == DPA_CLS_TBL_INDEXED) {
+ log_err("SA tables mustn't be of type index\n");
+ return -EINVAL;
+ }
+ valid_tables++;
+ }
+ if (!valid_tables) {
+ log_err("Specify at least one valid table for SA lookup\n");
+ return -EINVAL;
+ }
+
+ /*
+ * verify that at least one field was selected for building inbound
+ * policy keys
+ */
+ if (prms->post_sec_in_params.do_pol_check &&
+ prms->post_sec_in_params.key_fields == 0) {
+ log_err("At least one field must be specified IN policy keys\n");
+ return -EINVAL;
+ }
+
+ /*
+ * verify that the instance is configured
+ * for offloading at least one SA pair
+ */
+ if (prms->max_sa_pairs == 0) {
+ log_err("The instance must be configured for offloading at least one SA pair\n");
+ return -EINVAL;
+ }
+
+ /* Verify the parameters of the FQID range - if one was provided */
+ if (prms->fqid_range) {
+ fqid_range_size = prms->fqid_range->end_fqid -
+ prms->fqid_range->start_fqid;
+ min_fqid_num = prms->max_sa_pairs * 2 * NUM_FQS_PER_SA;
+ if (fqid_range_size <= 0 || fqid_range_size < min_fqid_num) {
+ log_err("Insufficient number of FQIDs in range!\n");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static void calc_in_pol_key_size(struct dpa_ipsec *dpa_ipsec, uint8_t *key_size)
+{
+ uint8_t key_fields, field_mask = 0;
+ int i;
+
+ BUG_ON(!dpa_ipsec);
+ BUG_ON(!key_size);
+
+ /* default value for key_size (set now in case a failure occurs later)*/
+ *key_size = 0;
+
+ key_fields = dpa_ipsec->config.post_sec_in_params.key_fields;
+
+ for (i = 0; i < DPA_IPSEC_MAX_KEY_FIELDS; i++) {
+ field_mask = (uint8_t)(1 << i);
+ switch (key_fields & field_mask) {
+ case DPA_IPSEC_KEY_FIELD_SIP:
+ if (dpa_ipsec->config.post_sec_in_params.use_ipv6_pol)
+ *key_size += DPA_OFFLD_IPv6_ADDR_LEN_BYTES;
+ else
+ *key_size += DPA_OFFLD_IPv4_ADDR_LEN_BYTES;
+ break;
+
+ case DPA_IPSEC_KEY_FIELD_DIP:
+ if (dpa_ipsec->config.post_sec_in_params.use_ipv6_pol)
+ *key_size += DPA_OFFLD_IPv6_ADDR_LEN_BYTES;
+ else
+ *key_size += DPA_OFFLD_IPv4_ADDR_LEN_BYTES;
+ break;
+
+ case DPA_IPSEC_KEY_FIELD_PROTO:
+ *key_size += IP_PROTO_FIELD_LEN;
+ break;
+
+ case DPA_IPSEC_KEY_FIELD_SPORT:
+ *key_size += PORT_FIELD_LEN;
+ break;
+
+ case DPA_IPSEC_KEY_FIELD_DPORT:
+ *key_size += PORT_FIELD_LEN;
+ break;
+ case DPA_IPSEC_KEY_FIELD_DSCP:
+ *key_size += DSCP_FIELD_LEN;
+ break;
+ }
+ }
+}
+
+static int create_inpol_node(struct dpa_ipsec *dpa_ipsec, void **cc_node)
+{
+ t_FmPcdCcNextEngineParams *next_engine_miss_action;
+
+ BUG_ON(!dpa_ipsec);
+ BUG_ON(!cc_node);
+
+ /* default value for cc_node (set now in case a failure occurs later) */
+ *cc_node = NULL;
+
+ memset(&cc_node_prms, 0, sizeof(cc_node_prms));
+ cc_node_prms.extractCcParams.type = e_FM_PCD_EXTRACT_NON_HDR;
+ cc_node_prms.extractCcParams.extractNonHdr.src =
+ e_FM_PCD_EXTRACT_FROM_KEY;
+ cc_node_prms.extractCcParams.extractNonHdr.action =
+ e_FM_PCD_ACTION_EXACT_MATCH;
+ cc_node_prms.extractCcParams.extractNonHdr.offset = 0;
+ cc_node_prms.extractCcParams.extractNonHdr.size =
+ dpa_ipsec->sa_mng.inpol_key_size;
+
+ cc_node_prms.keysParams.numOfKeys = 0;
+ cc_node_prms.keysParams.keySize = dpa_ipsec->sa_mng.inpol_key_size;
+
+ next_engine_miss_action =
+ &cc_node_prms.keysParams.ccNextEngineParamsForMiss;
+ next_engine_miss_action->nextEngine = e_FM_PCD_DONE;
+
+ *cc_node = FM_PCD_MatchTableSet(dpa_ipsec->config.fm_pcd,
+ &cc_node_prms);
+ if (!*cc_node) {
+ log_err("%s: FM_PCD_MatchTableSet failed!\n", __func__);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static inline void destroy_inpol_node(struct dpa_ipsec *dpa_ipsec,
+ void *cc_node)
+{
+ t_Error fmd_err;
+
+ BUG_ON(!dpa_ipsec);
+ BUG_ON(!cc_node);
+
+ fmd_err = FM_PCD_MatchTableDelete(cc_node);
+ if (fmd_err != E_OK) {
+ log_err("%s: FM_PCD_MatchTableDelete failed!\n", __func__);
+ log_err("Could not free policy check CC Node\n");
+ }
+}
+
+static int create_inpol_cls_tbl(struct dpa_ipsec *dpa_ipsec,
+ void *cc_node,
+ int *td)
+{
+ struct dpa_cls_tbl_params params;
+ int err;
+
+ BUG_ON(!dpa_ipsec);
+ BUG_ON(!cc_node);
+ BUG_ON(!td);
+
+ *td = DPA_OFFLD_DESC_NONE;
+
+ memset(&params, 0, sizeof(params));
+ params.entry_mgmt = DPA_CLS_TBL_MANAGE_BY_REF;
+ params.type = DPA_CLS_TBL_EXACT_MATCH;
+ params.exact_match_params.entries_cnt = DPA_IPSEC_MAX_IN_POL_PER_SA;
+ params.exact_match_params.key_size = dpa_ipsec->sa_mng.inpol_key_size;
+ params.exact_match_params.use_priorities = true;
+ params.cc_node = cc_node;
+ err = dpa_classif_table_create(&params, td);
+ if (err < 0) {
+ log_err("Could not create exact match tbl");
+ return err;
+ }
+
+ return 0;
+}
+
+static inline void destroy_inpol_cls_tbl(int td)
+{
+ int err;
+
+ if (td != DPA_OFFLD_DESC_NONE) {
+ err = dpa_classif_table_free(td);
+ if (err < 0)
+ log_err("Could not free EM table\n");
+ }
+}
+
+static int get_inbound_flowid(struct dpa_ipsec *dpa_ipsec, uint16_t *flowid)
+{
+ BUG_ON(!dpa_ipsec);
+ BUG_ON(!dpa_ipsec->sa_mng.inbound_flowid_cq);
+ BUG_ON(!flowid);
+
+ if (cq_get_2bytes(dpa_ipsec->sa_mng.inbound_flowid_cq, flowid) < 0) {
+ log_err("Could not retrieve a valid inbound flow ID\n");
+ return -EDOM;
+ }
+
+ return 0;
+}
+
+static int put_inbound_flowid(struct dpa_ipsec *dpa_ipsec, uint16_t flowid)
+{
+ BUG_ON(!dpa_ipsec);
+ BUG_ON(!dpa_ipsec->sa_mng.inbound_flowid_cq);
+
+ if (cq_put_2bytes(dpa_ipsec->sa_mng.inbound_flowid_cq, flowid) < 0) {
+ log_err("Could not release inbound flow id\n");
+ return -EDOM;
+ }
+
+ return 0;
+}
+
+static int create_inbound_flowid_cq(struct dpa_ipsec *dpa_ipsec)
+{
+ void *cq;
+ uint16_t base_flow_id;
+ int i, err;
+
+ BUG_ON(!dpa_ipsec);
+
+ cq = cq_new(dpa_ipsec->sa_mng.max_num_sa / 2, sizeof(uint16_t));
+ if (!cq) {
+ log_err("Could not create inbound flow ID management CQ\n");
+ return -ENOMEM;
+ }
+
+ dpa_ipsec->sa_mng.inbound_flowid_cq = cq;
+
+ /* Populate the created CQ with flow ids */
+ base_flow_id = dpa_ipsec->config.post_sec_in_params.base_flow_id;
+ for (i = base_flow_id;
+ i < dpa_ipsec->sa_mng.max_num_sa / 2 + base_flow_id; i++) {
+ err = put_inbound_flowid(dpa_ipsec, (uint16_t) i);
+ if (err < 0) {
+ log_err("Couldn't fill flow id management queue\n");
+ cq_delete(cq);
+ dpa_ipsec->sa_mng.inbound_flowid_cq = NULL;
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static inline void destroy_inbound_flowid_cq(struct cq *inbound_flowid_cq)
+{
+ /* sanity checks */
+ if (inbound_flowid_cq)
+ cq_delete(inbound_flowid_cq);
+}
+
+static int get_free_inbpol_tbl(struct dpa_ipsec *dpa_ipsec, int *table_desc)
+{
+ struct inpol_tbl *inpol_tbl;
+ struct list_head *head;
+ int ret = 0;
+
+ BUG_ON(!dpa_ipsec);
+ BUG_ON(!table_desc);
+
+ /* Lock inbound policy list */
+ mutex_lock(&dpa_ipsec->sa_mng.inpol_tables_lock);
+
+ head = &dpa_ipsec->sa_mng.inpol_tables;
+
+ list_for_each_entry(inpol_tbl, head, table_list)
+ if (!inpol_tbl->used)
+ break;
+
+ if (!inpol_tbl->used) {
+ BUG_ON(inpol_tbl->td < 0);
+ inpol_tbl->used = true;
+ *table_desc = inpol_tbl->td;
+ } else {
+ log_err("No more free EM tables for inbound policy verification\n");
+ ret = -ENOMEM;
+ }
+
+ /* Unlock inbound policy list */
+ mutex_unlock(&dpa_ipsec->sa_mng.inpol_tables_lock);
+
+ return ret;
+}
+
+static void put_free_inbpol_tbl(struct dpa_ipsec *dpa_ipsec, int table_desc)
+{
+ struct inpol_tbl *inpol_tbl;
+ struct list_head *head;
+
+ BUG_ON(!dpa_ipsec);
+ BUG_ON(table_desc < 0);
+
+ /* Lock inbound policy list */
+ mutex_lock(&dpa_ipsec->sa_mng.inpol_tables_lock);
+
+ head = &dpa_ipsec->sa_mng.inpol_tables;
+
+ list_for_each_entry(inpol_tbl, head, table_list)
+ if (inpol_tbl->td == table_desc)
+ break;
+
+ if (inpol_tbl->used)
+ inpol_tbl->used = FALSE;
+ else
+ pr_warn("Exact match table %d is not used\n", table_desc);
+
+ /* Unlock inbound policy list */
+ mutex_unlock(&dpa_ipsec->sa_mng.inpol_tables_lock);
+}
+
+static int get_free_ipsec_manip_node(struct dpa_ipsec *dpa_ipsec, void **hm)
+{
+ struct ipsec_manip_node *ipsec_manip_node;
+ struct list_head *head;
+ int ret = 0;
+
+ BUG_ON(!dpa_ipsec);
+ BUG_ON(!hm);
+
+ mutex_lock(&dpa_ipsec->lock);
+
+ /* Lock IPSec manip node list */
+ mutex_lock(&dpa_ipsec->sa_mng.ipsec_manip_node_lock);
+
+ head = &dpa_ipsec->sa_mng.ipsec_manip_node_list;
+
+ list_for_each_entry(ipsec_manip_node, head, ipsec_manip_node_list)
+ if (!ipsec_manip_node->used)
+ break;
+
+ if (!ipsec_manip_node->used) {
+ BUG_ON(!ipsec_manip_node->hm);
+ ipsec_manip_node->used = true;
+ *hm = ipsec_manip_node->hm;
+ } else {
+ log_err("No more free IPSec manip nodes for special operations\n");
+ ret = -ENOMEM;
+ }
+
+ /* Unlock IPSec manip node list */
+ mutex_unlock(&dpa_ipsec->sa_mng.ipsec_manip_node_lock);
+ mutex_unlock(&dpa_ipsec->lock);
+
+ return ret;
+}
+
+static void put_free_ipsec_manip_node(struct dpa_ipsec *dpa_ipsec, void *hm)
+{
+ struct ipsec_manip_node *ipsec_manip_node;
+ struct list_head *head;
+ bool found = false;
+
+ BUG_ON(!dpa_ipsec);
+ BUG_ON(!hm);
+
+ mutex_lock(&dpa_ipsec->lock);
+
+ /* Lock IPSec manip node list */
+ mutex_lock(&dpa_ipsec->sa_mng.ipsec_manip_node_lock);
+
+ head = &dpa_ipsec->sa_mng.ipsec_manip_node_list;
+
+ list_for_each_entry(ipsec_manip_node, head, ipsec_manip_node_list)
+ if (ipsec_manip_node->hm == hm) {
+ found = true;
+ break;
+ }
+
+ BUG_ON(!found);
+
+ if (ipsec_manip_node->used)
+ ipsec_manip_node->used = false;
+ else
+ pr_warn("IPSec manip node %p is not used\n", hm);
+
+ /* Unlock IPSec manip node list */
+ mutex_unlock(&dpa_ipsec->sa_mng.ipsec_manip_node_lock);
+ mutex_unlock(&dpa_ipsec->lock);
+}
+
+static void replace_ipsec_manip_node(struct dpa_ipsec *dpa_ipsec, void *hm_old,
+ void *hm_new)
+{
+ struct ipsec_manip_node *ipsec_manip_node;
+ struct list_head *head;
+ bool found = false;
+
+ BUG_ON(!dpa_ipsec);
+ BUG_ON(!hm_old);
+ BUG_ON(!hm_new);
+
+ /*
+ * Lock IPSec manip node list
+ */
+ mutex_lock(&dpa_ipsec->sa_mng.ipsec_manip_node_lock);
+
+ head = &dpa_ipsec->sa_mng.ipsec_manip_node_list;
+
+ list_for_each_entry(ipsec_manip_node, head, ipsec_manip_node_list)
+ if (ipsec_manip_node->hm == hm_old) {
+ found = true;
+ break;
+ }
+
+ BUG_ON(!found);
+
+ if (ipsec_manip_node->used)
+ ipsec_manip_node->hm = hm_new;
+ else
+ pr_warn("IPSec manip node %p is not used\n", hm_old);
+
+ /*
+ * Unlock IPSec manip node list
+ */
+ mutex_unlock(&dpa_ipsec->sa_mng.ipsec_manip_node_lock);
+}
+
+/* initialize fqid management CQ */
+static int create_fqid_cq(struct dpa_ipsec *dpa_ipsec)
+{
+ struct dpa_ipsec_fqid_range *fqid_range;
+ struct cq *fqid_cq;
+ int i;
+
+ BUG_ON(!dpa_ipsec);
+
+ if (dpa_ipsec->config.fqid_range) {
+ fqid_range = dpa_ipsec->config.fqid_range;
+ fqid_cq = cq_new(fqid_range->end_fqid - fqid_range->start_fqid,
+ sizeof(uint32_t));
+ if (!fqid_cq) {
+ log_err("Could not create CQ for FQID management!\n");
+ return -ENOMEM;
+ }
+
+ dpa_ipsec->sa_mng.fqid_cq = fqid_cq;
+
+ /* fill the CQ */
+ for (i = fqid_range->start_fqid; i < fqid_range->end_fqid; i++)
+ if (cq_put_4bytes(fqid_cq, (uint16_t)i) < 0) {
+ log_err("Could not fill fqid management CQ!\n");
+ return -EDOM;
+ }
+ }
+
+ return 0;
+}
+
+/* destroy the FQID management CQ - if one was initialized */
+static inline void destroy_fqid_cq(struct dpa_ipsec *dpa_ipsec)
+{
+ if (dpa_ipsec->sa_mng.fqid_cq) {
+ cq_delete(dpa_ipsec->sa_mng.fqid_cq);
+ dpa_ipsec->sa_mng.fqid_cq = NULL;
+ }
+}
+
+/* Determine if get_instance returned error */
+static inline int check_instance(struct dpa_ipsec *instance)
+{
+ if (PTR_ERR(instance) == -EPERM) {
+ log_err("Instance is not initialized\n");
+ return -EPERM;
+ }
+
+ if (PTR_ERR(instance) == -EINVAL) {
+ log_err("Instance is being freed\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct dpa_ipsec *get_instance(int instance_id)
+{
+ struct dpa_ipsec *dpa_ipsec;
+ int ret = 0;
+
+ BUG_ON(instance_id < 0 || instance_id >= MAX_DPA_IPSEC_INSTANCES);
+
+ spin_lock(&gbl_dpa_ipsec_lock);
+
+ if (!gbl_dpa_ipsec[instance_id])
+ ret = -EPERM;
+
+ dpa_ipsec = gbl_dpa_ipsec[instance_id];
+
+ if (ret == 0 && !atomic_read(&dpa_ipsec->valid))
+ ret = -EINVAL;
+
+ if (!ret)
+ instance_refinc(dpa_ipsec);
+
+ spin_unlock(&gbl_dpa_ipsec_lock);
+
+ return !ret ? dpa_ipsec : ERR_PTR(ret);
+}
+
+static void put_instance(struct dpa_ipsec *dpa_ipsec)
+{
+ BUG_ON(!dpa_ipsec);
+ instance_refdec(dpa_ipsec);
+ if (atomic_read(&dpa_ipsec->ref) == 1)
+ wake_up(&wait_queue);
+}
+
+/* Returns true it table is in use on other DPA instance */
+static inline bool table_in_use(int td)
+{
+ struct dpa_ipsec *instance;
+ int i, j;
+
+ for (i = 0; i < MAX_DPA_IPSEC_INSTANCES; i++) {
+ struct dpa_ipsec_pre_sec_out_params *pre_sec_out_prms;
+ struct dpa_ipsec_pre_sec_in_params *pre_sec_in_params;
+
+ instance = get_instance(i);
+ if (IS_ERR(instance))
+ continue;
+
+ /* Acquire instance lock */
+ mutex_lock(&instance->lock);
+
+ pre_sec_out_prms = &instance->config.pre_sec_out_params;
+ for (j = 0; j < DPA_IPSEC_MAX_SUPPORTED_PROTOS; j++) {
+ int dpa_cls_td = pre_sec_out_prms->table[i].dpa_cls_td;
+ if (td == dpa_cls_td) {
+ mutex_unlock(&instance->lock);
+ put_instance(instance);
+ return true;
+ }
+ }
+
+ if (!ignore_post_ipsec_action(instance) &&
+ td == instance->config.post_sec_in_params.dpa_cls_td) {
+ mutex_unlock(&instance->lock);
+ put_instance(instance);
+ return true;
+ }
+
+ pre_sec_in_params = &instance->config.pre_sec_in_params;
+ for (j = 0; j < DPA_IPSEC_MAX_SA_TYPE; j++) {
+ int dpa_cls_td = pre_sec_in_params->dpa_cls_td[j];
+ if (td == dpa_cls_td) {
+ mutex_unlock(&instance->lock);
+ put_instance(instance);
+ return true;
+ }
+ }
+
+ /* Release the instance lock */
+ mutex_unlock(&instance->lock);
+ put_instance(instance);
+ }
+
+ return false;
+}
+
+/*
+ * Create a circular queue with id's for aquiring SA's handles
+ * Allocate a maximum number of SA internal structures to be used at runtime.
+ * Param[in] dpa_ipsec - Instance for which SA manager is initialized
+ * Return value 0 on success. Error code otherwise.
+ * Cleanup provided by free_sa_mng().
+ */
+static int init_sa_manager(struct dpa_ipsec *dpa_ipsec)
+{
+ struct dpa_ipsec_sa_mng *sa_mng;
+ struct dpa_ipsec_sa *sa;
+ int i = 0, err, start_sa_id;
+
+ BUG_ON(!dpa_ipsec);
+
+ sa_mng = &dpa_ipsec->sa_mng;
+ sa_mng->max_num_sa = dpa_ipsec->config.max_sa_pairs * 2;
+
+ /* Initialize the SA IPSec manip node list and its protective lock */
+ INIT_LIST_HEAD(&dpa_ipsec->sa_mng.ipsec_manip_node_list);
+ mutex_init(&sa_mng->ipsec_manip_node_lock);
+
+ INIT_LIST_HEAD(&sa_mng->inpol_tables);
+
+ /* create queue that holds free SA IDs */
+ sa_mng->sa_id_cq = cq_new(sa_mng->max_num_sa, sizeof(int));
+ if (!sa_mng->sa_id_cq) {
+ log_err("Could not create SA IDs circular queue\n");
+ return -ENOMEM;
+ }
+
+ /* fill with IDs */
+ start_sa_id = dpa_ipsec->id * MAX_NUM_OF_SA;
+ for (i = start_sa_id; i < start_sa_id + sa_mng->max_num_sa; i++)
+ if (cq_put_4bytes(sa_mng->sa_id_cq, i) < 0) {
+ log_err("Could not fill SA ID management CQ\n");
+ return -EDOM;
+ }
+
+ /* initialize the circular queue for FQIDs management */
+ err = create_fqid_cq(dpa_ipsec);
+ if (err < 0) {
+ log_err("Could not initialize FQID management mechanism!\n");
+ return err;
+ }
+
+ /* alloc SA array */
+ sa = kzalloc(sa_mng->max_num_sa * sizeof(*sa_mng->sa), GFP_KERNEL);
+ if (!sa) {
+ log_err("Could not allocate memory for SAs\n");
+ return -ENOMEM;
+ }
+ sa_mng->sa = sa;
+
+ /* alloc cipher/auth stuff */
+ for (i = 0; i < sa_mng->max_num_sa; i++) {
+ mutex_init(&sa_mng->sa[i].lock);
+ sa[i].cipher_data.cipher_key =
+ kzalloc(MAX_CIPHER_KEY_LEN, GFP_KERNEL);
+ if (!sa[i].cipher_data.cipher_key) {
+ log_err("Could not allocate memory for cipher key\n");
+ return -ENOMEM;
+ }
+ sa[i].auth_data.auth_key =
+ kzalloc(MAX_AUTH_KEY_LEN, GFP_KERNEL);
+ if (!sa[i].auth_data.auth_key) {
+ log_err("Could not allocate memory for authentication key\n");
+ return -ENOMEM;
+ }
+
+ sa[i].auth_data.split_key =
+ kzalloc(MAX_AUTH_KEY_LEN, GFP_KERNEL);
+ if (!sa[i].auth_data.split_key) {
+ log_err("Could not allocate memory for authentication split key\n");
+ return -ENOMEM;
+ }
+
+ sa[i].from_sec_fq = kzalloc(sizeof(struct qman_fq), GFP_KERNEL);
+ if (!sa[i].from_sec_fq) {
+ log_err("Can't allocate space for 'from SEC FQ'\n");
+ return -ENOMEM;
+ }
+
+ sa[i].to_sec_fq = kzalloc(sizeof(struct qman_fq), GFP_KERNEL);
+ if (!sa[i].to_sec_fq) {
+ log_err("Can't allocate space for 'to SEC FQ'\n");
+ return -ENOMEM;
+ }
+
+ /*
+ * Allocate space for the SEC descriptor which is holding the
+ * preheader information and the share descriptor.
+ * Required 64 byte align.
+ */
+ sa[i].sec_desc_unaligned =
+ kzalloc(sizeof(struct sec_descriptor) + 64, GFP_KERNEL);
+ if (!sa[i].sec_desc_unaligned) {
+ log_err("Could not allocate memory for SEC descriptor\n");
+ return -ENOMEM;
+ }
+ sa[i].sec_desc = PTR_ALIGN(sa[i].sec_desc_unaligned, 64);
+
+ /* Allocate space for extra material space in case when the
+ * descriptor is greater than 64 words */
+ sa[i].sec_desc_extra_cmds_unaligned =
+ kzalloc(2 * MAX_EXTRA_DESC_COMMANDS + L1_CACHE_BYTES,
+ GFP_KERNEL);
+ if (!sa[i].sec_desc_extra_cmds_unaligned) {
+ log_err("Allocation failed for CAAM extra commands\n");
+ return -ENOMEM;
+ }
+ sa[i].sec_desc_extra_cmds =
+ PTR_ALIGN(sa[i].sec_desc_extra_cmds_unaligned,
+ L1_CACHE_BYTES);
+ if (sa[i].sec_desc_extra_cmds_unaligned ==
+ sa[i].sec_desc_extra_cmds)
+ sa[i].sec_desc_extra_cmds += L1_CACHE_BYTES / 4;
+
+ /*
+ * Allocate space for the SEC replacement job descriptor
+ * Required 64 byte alignment
+ */
+ sa[i].rjob_desc_unaligned =
+ kzalloc(MAX_CAAM_DESCSIZE * sizeof(uint32_t) + 64,
+ GFP_KERNEL);
+ if (!sa[i].rjob_desc_unaligned) {
+ log_err("No memory for replacement job descriptor\n");
+ return -ENOMEM;
+ }
+ sa[i].rjob_desc = PTR_ALIGN(sa[i].rjob_desc_unaligned, 64);
+
+ /*
+ * Initialize the policy parameter list which will hold all
+ * inbound or outbound policy parameters which were use to
+ * generate PCD entries
+ */
+ INIT_LIST_HEAD(&sa[i].policy_headlist);
+
+ /* init the inbound SA lookup table desc with an invalid value*/
+ sa[i].inbound_sa_td = DPA_OFFLD_DESC_NONE;
+ }
+
+ /*
+ * Inbound flow id circular queue is required only if a valid index
+ * table is set.
+ */
+ if (!ignore_post_ipsec_action(dpa_ipsec)) {
+ err = create_inbound_flowid_cq(dpa_ipsec);
+ if (err < 0) {
+ log_err("Could not create inbound policy flow id cq\n");
+ return err;
+ }
+ } else {
+ /* Not required */
+ dpa_ipsec->sa_mng.inbound_flowid_cq = NULL;
+ }
+
+ /*
+ * If policy check is enabled than for every possible inbound SA create
+ * an Exact Match Table and link it to the Inbound Index Table
+ */
+ if (dpa_ipsec->config.post_sec_in_params.do_pol_check == true) {
+ struct inpol_tbl *pol_table;
+ void *cc_node;
+
+ /* calculate key size for policy verification tables */
+ calc_in_pol_key_size(dpa_ipsec,
+ &dpa_ipsec->sa_mng.inpol_key_size);
+
+ if (dpa_ipsec->sa_mng.inpol_key_size == 0) {
+ log_err("Invalid argument: in policy table key size\n");
+ return -EFAULT;
+ }
+
+ mutex_init(&sa_mng->inpol_tables_lock);
+
+ mutex_lock(&sa_mng->inpol_tables_lock);
+ for (i = 0; i < dpa_ipsec->config.max_sa_pairs; i++) {
+ pol_table = kzalloc(sizeof(*pol_table), GFP_KERNEL);
+ if (!pol_table) {
+ log_err("Could not allocate memory for policy table");
+ mutex_unlock(&sa_mng->inpol_tables_lock);
+ return -ENOMEM;
+ }
+
+ /* create cc node for inbound policy */
+ err = create_inpol_node(dpa_ipsec, &cc_node);
+ if (err < 0) {
+ log_err("Could not create cc node for EM table\n");
+ kfree(pol_table);
+ mutex_unlock(&sa_mng->inpol_tables_lock);
+ return err;
+ }
+ pol_table->cc_node = cc_node;
+ err = create_inpol_cls_tbl(dpa_ipsec,
+ cc_node,
+ &pol_table->td);
+ if (err < 0) {
+ log_err("Failed create in policy table\n");
+ destroy_inpol_node(dpa_ipsec, cc_node);
+ kfree(pol_table);
+ mutex_unlock(&sa_mng->inpol_tables_lock);
+ return err;
+ }
+
+ list_add(&pol_table->table_list,
+ &dpa_ipsec->sa_mng.inpol_tables);
+ }
+ mutex_unlock(&sa_mng->inpol_tables_lock);
+ }
+
+ /* Populate the list of IPSec manip node */
+ mutex_lock(&sa_mng->ipsec_manip_node_lock);
+ for (i = 0; i < dpa_ipsec->config.max_sa_manip_ops; i++) {
+ struct ipsec_manip_node *node;
+ node = kzalloc(sizeof(*node), GFP_KERNEL);
+ if (!node) {
+ log_err("Could not allocate memory for IPSec manip node\n");
+ mutex_unlock(&sa_mng->ipsec_manip_node_lock);
+ return -ENOMEM;
+ }
+
+ node->hm = alloc_ipsec_manip(dpa_ipsec);
+ if (!node->hm) {
+ log_err("Could not create IPSec manip node\n");
+ kfree(node);
+ mutex_unlock(&sa_mng->ipsec_manip_node_lock);
+ return -ENOMEM;
+ }
+
+ node->used = false;
+ list_add(&node->ipsec_manip_node_list,
+ &dpa_ipsec->sa_mng.ipsec_manip_node_list);
+
+ }
+ mutex_unlock(&sa_mng->ipsec_manip_node_lock);
+
+ /* Initialize the SA rekeying list and its protective lock */
+ INIT_LIST_HEAD(&dpa_ipsec->sa_mng.sa_rekeying_headlist);
+ mutex_init(&sa_mng->sa_rekeying_headlist_lock);
+
+ /*
+ * Creating a single thread work queue used to defer work when there are
+ * inbound SAs in rekeying process
+ */
+ dpa_ipsec->sa_mng.sa_rekeying_wq =
+ create_singlethread_workqueue("sa_rekeying_wq");
+ if (!dpa_ipsec->sa_mng.sa_rekeying_wq) {
+ log_err("Creating SA rekeying work queue failed\n");
+ return -ENOSPC;
+ }
+
+ /* Initialize the work needed to be done rekeying inbound process */
+ INIT_DELAYED_WORK(&dpa_ipsec->sa_mng.sa_rekeying_work,
+ sa_rekeying_work_func);
+
+ return 0;
+}
+
+/* cleanup SA manager */
+static void free_sa_mng(struct dpa_ipsec *dpa_ipsec)
+{
+ struct dpa_ipsec_sa_mng *sa_mng;
+ struct inpol_tbl *pol_tbl, *tmp;
+ struct list_head *head;
+ struct list_head *pos, *n;
+ struct ipsec_manip_node *node;
+ int i = 0;
+
+ /* sanity checks */
+ if (!dpa_ipsec) {
+ log_err("Invalid argument: NULL DPA IPSec instance\n");
+ return;
+ }
+
+ sa_mng = (struct dpa_ipsec_sa_mng *)&dpa_ipsec->sa_mng;
+ /* Remove the DPA IPsec created tables for policy verification */
+ if (dpa_ipsec->config.post_sec_in_params.do_pol_check) {
+ head = &sa_mng->inpol_tables;
+ list_for_each_entry_safe(pol_tbl, tmp, head, table_list) {
+ destroy_inpol_cls_tbl(pol_tbl->td);
+ list_del(&pol_tbl->table_list);
+ destroy_inpol_node(dpa_ipsec, pol_tbl->cc_node);
+ kfree(pol_tbl);
+ }
+ }
+
+ /* dealloc cipher/auth stuff */
+ if (sa_mng->sa) {
+ for (i = 0; i < sa_mng->max_num_sa; i++) {
+ kfree(sa_mng->sa[i].cipher_data.cipher_key);
+ sa_mng->sa[i].cipher_data.cipher_key = NULL;
+
+ kfree(sa_mng->sa[i].auth_data.auth_key);
+ sa_mng->sa[i].auth_data.auth_key = NULL;
+
+ kfree(sa_mng->sa[i].auth_data.split_key);
+ sa_mng->sa[i].auth_data.split_key = NULL;
+
+ kfree(sa_mng->sa[i].from_sec_fq);
+ sa_mng->sa[i].from_sec_fq = NULL;
+
+ kfree(sa_mng->sa[i].to_sec_fq);
+ sa_mng->sa[i].to_sec_fq = NULL;
+
+ kfree(sa_mng->sa[i].sec_desc_unaligned);
+ sa_mng->sa[i].sec_desc_unaligned = NULL;
+ sa_mng->sa[i].sec_desc = NULL;
+
+ kfree(sa_mng->sa[i].sec_desc_extra_cmds_unaligned);
+ sa_mng->sa[i].sec_desc_extra_cmds_unaligned = NULL;
+
+ kfree(sa_mng->sa[i].rjob_desc_unaligned);
+ sa_mng->sa[i].rjob_desc_unaligned = NULL;
+
+ mutex_destroy(&sa_mng->sa[i].lock);
+ }
+
+ kfree(sa_mng->sa);
+ sa_mng->sa = NULL;
+ }
+
+ /* release SA ID management CQ */
+ if (sa_mng->sa_id_cq) {
+ cq_delete(sa_mng->sa_id_cq);
+ sa_mng->sa_id_cq = NULL;
+ }
+
+ /* destroy fqid management CQ */
+ destroy_fqid_cq(dpa_ipsec);
+
+ /* release inbound flow ID management CQ */
+ destroy_inbound_flowid_cq(dpa_ipsec->sa_mng.inbound_flowid_cq);
+ dpa_ipsec->sa_mng.inbound_flowid_cq = NULL;
+
+ /* destroy rekeying workqueue */
+ if (sa_mng->sa_rekeying_wq) {
+ destroy_workqueue(sa_mng->sa_rekeying_wq);
+ sa_mng->sa_rekeying_wq = NULL;
+ }
+
+ /* cleanup hmanips */
+ list_for_each_safe(pos, n, &dpa_ipsec->sa_mng.ipsec_manip_node_list) {
+ node = container_of(pos, struct ipsec_manip_node,
+ ipsec_manip_node_list);
+ list_del(&node->ipsec_manip_node_list);
+ kfree(node->hm);
+ kfree(node);
+ }
+
+ mutex_destroy(&sa_mng->inpol_tables_lock);
+ mutex_destroy(&sa_mng->sa_rekeying_headlist_lock);
+ mutex_destroy(&sa_mng->ipsec_manip_node_lock);
+
+}
+
+/* Cleanup for DPA IPsec instance */
+static void free_resources(int dpa_ipsec_id)
+{
+ struct dpa_ipsec *dpa_ipsec;
+
+ BUG_ON(dpa_ipsec_id < 0 || dpa_ipsec_id >= MAX_DPA_IPSEC_INSTANCES);
+
+ dpa_ipsec = gbl_dpa_ipsec[dpa_ipsec_id];
+
+ /* free all SA related stuff */
+ free_sa_mng(dpa_ipsec);
+
+ kfree(dpa_ipsec->used_sa_ids);
+
+ mutex_destroy(&dpa_ipsec->lock);
+ kfree(dpa_ipsec);
+
+ mark_unused_gbl_dpa_ipsec(dpa_ipsec_id);
+}
+
+/* Runtime functions */
+
+/* Convert prefixLen into IP address's netmask. */
+static int set_ip_addr_mask(uint8_t *mask, uint8_t prefix_len,
+ uint8_t mask_len)
+{
+ static const uint8_t mask_bits[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8,
+ 0xfc, 0xfe, 0xff};
+ uint8_t bit, off;
+
+ BUG_ON(!mask);
+
+ off = prefix_len / 8;
+ bit = prefix_len % 8;
+ while (off--)
+ *mask++ = 0xff;
+ if (bit)
+ *mask = mask_bits[bit];
+
+ return 0;
+}
+
+static int set_flow_id_action(struct dpa_ipsec_sa *sa,
+ struct dpa_cls_tbl_action *action)
+{
+ struct dpa_ipsec *dpa_ipsec;
+ struct dpa_offload_lookup_key tbl_key;
+ struct dpa_cls_tbl_entry_mod_params mod_params;
+ int table, err;
+ uint8_t key_data;
+
+ BUG_ON(!sa);
+ BUG_ON(!action);
+
+ dpa_ipsec = sa->dpa_ipsec;
+
+ /* Currently the flowid cannot be greater than 255 */
+ key_data = (uint8_t)sa->inbound_flowid;
+
+ memset(&tbl_key, 0, sizeof(tbl_key));
+ tbl_key.byte = &key_data;
+ tbl_key.mask = NULL;
+ tbl_key.size = sizeof(uint8_t);
+
+ memset(&mod_params, 0, sizeof(mod_params));
+ mod_params.action = action;
+ mod_params.type = DPA_CLS_TBL_MODIFY_ACTION;
+ table = dpa_ipsec->config.post_sec_in_params.dpa_cls_td;
+ err = dpa_classif_table_modify_entry_by_key(table, &tbl_key,
+ &mod_params);
+ if (err < 0) {
+ log_err("Couldn't set flowID action for SA id %d\n", sa->id);
+ return err;
+ }
+ sa->valid_flowid_entry = true;
+
+ return 0;
+}
+
+static int fill_policy_key(int td,
+ struct dpa_ipsec_policy_params *pol_params,
+ uint8_t key_fields,
+ uint8_t *key, uint8_t *mask, uint8_t *key_len,
+ uint8_t dscp_value)
+{
+ struct dpa_cls_tbl_params tbl_params;
+ uint8_t offset = 0, field_mask = 0, tbl_key_size = 0;
+ int err = 0, i;
+
+ BUG_ON(!pol_params);
+ BUG_ON(!key);
+ BUG_ON(!mask);
+ BUG_ON(!key_len);
+
+ /* Fill in the key components */
+ for (i = 0; i < DPA_IPSEC_MAX_KEY_FIELDS; i++) {
+ field_mask = (uint8_t) (1 << i);
+ switch (key_fields & field_mask) {
+ case DPA_IPSEC_KEY_FIELD_SIP:
+ memcpy(key + offset,
+ IP_ADDR(pol_params->src_addr),
+ IP_ADDR_LEN(pol_params->src_addr));
+ err = set_ip_addr_mask(mask + offset,
+ pol_params->src_prefix_len,
+ IP_ADDR_LEN(pol_params->src_addr));
+ if (err < 0)
+ return err;
+ offset += IP_ADDR_LEN(pol_params->src_addr);
+ break;
+
+ case DPA_IPSEC_KEY_FIELD_DIP:
+ memcpy(key + offset,
+ IP_ADDR(pol_params->dest_addr),
+ IP_ADDR_LEN(pol_params->dest_addr));
+ err = set_ip_addr_mask(mask + offset,
+ pol_params->dest_prefix_len,
+ IP_ADDR_LEN(pol_params->dest_addr));
+ if (err < 0)
+ return err;
+ offset += IP_ADDR_LEN(pol_params->dest_addr);
+ break;
+
+ case DPA_IPSEC_KEY_FIELD_PROTO:
+ SET_BYTE_VAL_IN_ARRAY(key, offset, pol_params->protocol);
+ SET_IP_PROTO_MASK(mask, offset, pol_params->masked_proto);
+ offset += IP_PROTO_FIELD_LEN;
+ break;
+
+ /* case DPA_IPSEC_KEY_FIELD_ICMP_TYPE: */
+ case DPA_IPSEC_KEY_FIELD_SPORT:
+ if ((pol_params->protocol == IPPROTO_ICMP) ||
+ (pol_params->protocol == IPPROTO_ICMPV6)) {
+ SET_BYTE_VAL_IN_ARRAY(key, offset,
+ pol_params->icmp.icmp_type);
+ SET_BYTE_VAL_IN_ARRAY(mask, offset,
+ pol_params->icmp.icmp_type_mask);
+ offset += ICMP_HDR_FIELD_LEN;
+ } else {
+ memcpy(key + offset,
+ (uint8_t *) &(pol_params->l4.src_port),
+ PORT_FIELD_LEN);
+ SET_L4_PORT_MASK(mask, offset,
+ pol_params->l4.src_port_mask);
+ offset += PORT_FIELD_LEN;
+ }
+ break;
+
+ /* case DPA_IPSEC_KEY_FIELD_ICMP_CODE: */
+ case DPA_IPSEC_KEY_FIELD_DPORT:
+ if ((pol_params->protocol == IPPROTO_ICMP) ||
+ (pol_params->protocol == IPPROTO_ICMPV6)) {
+ SET_BYTE_VAL_IN_ARRAY(key, offset,
+ pol_params->icmp.icmp_code);
+ SET_BYTE_VAL_IN_ARRAY(mask, offset,
+ pol_params->icmp.icmp_code_mask);
+ offset += ICMP_HDR_FIELD_LEN;
+ } else {
+ memcpy(key + offset,
+ (uint8_t *) &(pol_params->l4.dest_port),
+ PORT_FIELD_LEN);
+ SET_L4_PORT_MASK(mask, offset,
+ pol_params->l4.dest_port_mask);
+ offset += PORT_FIELD_LEN;
+ }
+ break;
+
+ case DPA_IPSEC_KEY_FIELD_DSCP:
+ if (pol_params->use_dscp) {
+ *(uint8_t *)(key + offset) = dscp_value << 2;
+ SET_BYTE_VAL_IN_ARRAY(mask, offset, 0xFC);
+ } else {
+ *(uint8_t *)(key + offset) = 0;
+ SET_BYTE_VAL_IN_ARRAY(mask, offset, 0);
+ }
+ offset += DSCP_FIELD_LEN;
+ break;
+ }
+ }
+
+ /*
+ * Add padding to compensate difference in size between table maximum
+ * key size and computed key size.
+ */
+
+ /* get table params (including maximum key size) */
+ err = dpa_classif_table_get_params(td, &tbl_params);
+ if (err < 0) {
+ log_err("Could not retrieve table maximum key size\n");
+ return -EINVAL;
+ }
+ tbl_key_size = TABLE_KEY_SIZE(tbl_params);
+
+ if (tbl_key_size < offset) {
+ log_err("Policy key is greater than maximum table key size\n");
+ return -EINVAL;
+ }
+
+ if (tbl_key_size > offset) {
+ for (i = 0; i < tbl_key_size - offset; i++) {
+ *(key + offset + i) = DPA_IPSEC_DEF_PAD_VAL;
+ /* ignore padding during classification (mask it) */
+ *(mask + offset + i) = 0x00;
+ }
+ offset = tbl_key_size;
+ }
+
+ /* Store key length */
+ *key_len = offset;
+
+ return 0;
+}
+
+/*
+ * fill dpa_cls_action structure with common values
+ * if new_fqid = 0, the FQID will not be overridden
+ */
+static inline void fill_cls_action_enq(struct dpa_cls_tbl_action *action_prm,
+ int en_stats, uint32_t new_fqid,
+ int hmd)
+{
+ action_prm->type = DPA_CLS_TBL_ACTION_ENQ;
+ action_prm->enable_statistics = en_stats;
+ if (new_fqid != 0) {
+ action_prm->enq_params.new_fqid = new_fqid;
+ action_prm->enq_params.override_fqid = true;
+ } else
+ action_prm->enq_params.override_fqid = FALSE;
+ action_prm->enq_params.policer_params = NULL;
+ action_prm->enq_params.hmd = hmd;
+}
+
+static inline void fill_cls_action_drop(struct dpa_cls_tbl_action *action,
+ int en_stats)
+{
+ memset(action, 0, sizeof(struct dpa_cls_tbl_action));
+ action->type = DPA_CLS_TBL_ACTION_DROP;
+ action->enable_statistics = en_stats;
+}
+
+/* Used at runtime when preallocation of IPSec manip node is not enabled */
+static int create_ipsec_manip(struct dpa_ipsec_sa *sa, int next_hmd, int *hmd)
+{
+ t_FmPcdManipParams pcd_manip_params;
+ t_FmPcdManipSpecialOffloadParams *offld_params;
+ t_Handle hm;
+ int err;
+
+ BUG_ON(!sa);
+ BUG_ON(!hmd);
+
+ if (!sa->use_var_iphdr_len && !sa->dscp_copy && !sa->ecn_copy &&
+ !(sa_is_outbound(sa) && sa->enable_dpovrd)) {
+ /* no need to create a new manipulation objects chain */
+ *hmd = next_hmd;
+ return 0;
+ }
+
+ memset(&pcd_manip_params, 0, sizeof(struct t_FmPcdManipParams));
+ pcd_manip_params.type = e_FM_PCD_MANIP_SPECIAL_OFFLOAD;
+ offld_params = &pcd_manip_params.u.specialOffload;
+ offld_params->type = e_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC;
+ if (sa_is_inbound(sa)) {
+ offld_params->u.ipsec.decryption = true;
+ offld_params->u.ipsec.variableIpHdrLen = sa->use_var_iphdr_len;
+ } else {
+ offld_params->u.ipsec.variableIpVersion = true;
+ offld_params->u.ipsec.outerIPHdrLen = (uint8_t)
+ sa->sec_desc->pdb_en.ip_hdr_len;
+ }
+ offld_params->u.ipsec.ecnCopy = sa->ecn_copy;
+ offld_params->u.ipsec.dscpCopy = sa->dscp_copy;
+
+ pcd_manip_params.h_NextManip = dpa_classif_hm_lock_chain(next_hmd);
+ dpa_classif_hm_release_chain(next_hmd);
+
+ hm = FM_PCD_ManipNodeSet(sa->dpa_ipsec->config.fm_pcd,
+ &pcd_manip_params);
+ if (!hm) {
+ log_err("%s: FM_PCD_ManipNodeSet failed!\n", __func__);
+ return -EBUSY;
+ }
+
+ err = dpa_classif_import_static_hm(hm, next_hmd, hmd);
+ if (err < 0)
+ log_err("Failed to import header manipulation into DPA Classifier.\n");
+
+ return err;
+}
+
+/*
+ * If preallocation of IPSec manip node(s) was specified the code is using this
+ * function to allocate and populate the list of IPSec manip objects
+ */
+static void *alloc_ipsec_manip(struct dpa_ipsec *dpa_ipsec)
+{
+ t_FmPcdManipParams pcd_manip_params;
+ t_FmPcdManipSpecialOffloadParams *offld_params;
+ t_Handle hm;
+
+ BUG_ON(!dpa_ipsec);
+
+ memset(&pcd_manip_params, 0, sizeof(struct t_FmPcdManipParams));
+ pcd_manip_params.type = e_FM_PCD_MANIP_SPECIAL_OFFLOAD;
+ offld_params = &pcd_manip_params.u.specialOffload;
+ offld_params->type = e_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC;
+ offld_params->u.ipsec.decryption = true;
+ offld_params->u.ipsec.variableIpHdrLen = false;
+ offld_params->u.ipsec.ecnCopy = false;
+ offld_params->u.ipsec.dscpCopy = false;
+ offld_params->u.ipsec.variableIpVersion = false;
+ offld_params->u.ipsec.outerIPHdrLen = 0;
+ pcd_manip_params.h_NextManip = NULL;
+
+ hm = FM_PCD_ManipNodeSet(dpa_ipsec->config.fm_pcd, &pcd_manip_params);
+ if (!hm) {
+ log_err("%s: FM_PCD_ManipSetNode failed!\n", __func__);
+ return NULL;
+ }
+
+ return hm;
+}
+
+/* Used at runtime when preallocation of IPSec manip nodes was enabled */
+static int update_ipsec_manip(struct dpa_ipsec_sa *sa, int next_hmd, int *hmd)
+{
+ t_FmPcdManipParams pcd_manip_params;
+ t_FmPcdManipSpecialOffloadParams *offld_params;
+ t_Handle ipsec_hm = NULL, new_hm = NULL;
+ t_Error err;
+ int ret;
+
+ BUG_ON(!sa);
+ BUG_ON(!hmd);
+
+ if (!sa->use_var_iphdr_len && !sa->dscp_copy && !sa->ecn_copy &&
+ !(sa_is_outbound(sa) && sa->enable_dpovrd)) {
+ /* no need to create a new manipulation objects chain */
+ *hmd = next_hmd;
+ return 0;
+ }
+
+ memset(&pcd_manip_params, 0, sizeof(struct t_FmPcdManipParams));
+ pcd_manip_params.type = e_FM_PCD_MANIP_SPECIAL_OFFLOAD;
+ offld_params = &pcd_manip_params.u.specialOffload;
+ offld_params->type = e_FM_PCD_MANIP_SPECIAL_OFFLOAD_IPSEC;
+ if (sa_is_inbound(sa)) {
+ offld_params->u.ipsec.decryption = true;
+ offld_params->u.ipsec.variableIpHdrLen = sa->use_var_iphdr_len;
+ } else {
+ offld_params->u.ipsec.variableIpVersion = true;
+ offld_params->u.ipsec.outerIPHdrLen = (uint8_t)
+ sa->sec_desc->pdb_en.ip_hdr_len;
+ }
+ offld_params->u.ipsec.ecnCopy = sa->ecn_copy;
+ offld_params->u.ipsec.dscpCopy = sa->dscp_copy;
+
+ pcd_manip_params.h_NextManip = dpa_classif_hm_lock_chain(next_hmd);
+ dpa_classif_hm_release_chain(next_hmd);
+
+ ret = get_free_ipsec_manip_node(sa->dpa_ipsec, &ipsec_hm);
+ if (ret < 0) {
+ log_err("%s: get_free_ipsec_manip_node failed for %s SA %d!\n",
+ __func__, sa_is_inbound(sa) ?
+ "inbound" : "outbound", sa->id);
+ return ret;
+ }
+
+ /* Should not be NULL */
+ BUG_ON(!ipsec_hm);
+
+ new_hm = FM_PCD_ManipNodeSet(sa->dpa_ipsec->config.fm_pcd,
+ &pcd_manip_params);
+ if (!new_hm) {
+ log_err("%s: FM_PCD_ManipSetNode failed!\n", __func__);
+ put_free_ipsec_manip_node(sa->dpa_ipsec, ipsec_hm);
+ return -EBUSY;
+ }
+
+ replace_ipsec_manip_node(sa->dpa_ipsec, ipsec_hm, new_hm);
+
+ err = FM_PCD_ManipNodeDelete(ipsec_hm);
+ if (err != E_OK) {
+ log_err("%s: FM_PCD_ManipNodeDelete failed for %s SA %d!\n",
+ __func__, sa_is_inbound(sa) ?
+ "inbound" : "outbound", sa->id);
+ put_free_ipsec_manip_node(sa->dpa_ipsec, new_hm);
+ return -EBUSY;
+ }
+
+ ret = dpa_classif_import_static_hm(new_hm, next_hmd, hmd);
+ if (ret < 0) {
+ log_err("Failed to import header manipulation into DPA Classifier.\n");
+ put_free_ipsec_manip_node(sa->dpa_ipsec, new_hm);
+ }
+
+ return ret;
+}
+
+/* Destroy the DPA IPSec Special header manip or put it in the pool */
+static int destroy_recycle_manip(struct dpa_ipsec_sa *sa,
+ struct hmd_entry *entry)
+{
+ t_Handle hm;
+ int hmd, err = 0;
+
+ BUG_ON(!sa);
+ BUG_ON(!entry);
+
+ hmd = entry->hmd;
+ BUG_ON(hmd == DPA_OFFLD_DESC_NONE);
+
+ hm = dpa_classif_get_static_hm_handle(hmd);
+ BUG_ON(!hm);
+
+ if (sa->dpa_ipsec->config.max_sa_manip_ops > 0) {
+ /* return to pool */
+ put_free_ipsec_manip_node(sa->dpa_ipsec, hm);
+ goto remove_hm;
+ }
+
+ if (entry->hmd_special_op) {
+ /*
+ * Destroy only the IPSec special operation that was created
+ * inside IPSec
+ */
+ err = FM_PCD_ManipNodeDelete(hm);
+ if (err != E_OK) {
+ log_err("%s: FM_PCD_ManipNodeDelete failed for SA %d!\n",
+ __func__, sa->id);
+ return -EBUSY;
+ }
+ }
+
+ /* Removed from classifier but not from memory. HM is still usable */
+remove_hm:
+ err = dpa_classif_free_hm(hmd);
+ if (err < 0) {
+ log_err("%s: Failed to remove header manip!\n", __func__);
+ return err;
+ }
+
+ return 0;
+}
+
+static int update_inbound_policy(struct dpa_ipsec_sa *sa,
+ struct dpa_ipsec_policy_entry *policy_entry,
+ enum mng_op_type op_type)
+{
+ struct dpa_ipsec *dpa_ipsec;
+ struct dpa_ipsec_policy_params *pol_params;
+ uint8_t key_len;
+ struct dpa_cls_tbl_action *action;
+ struct dpa_offload_lookup_key tbl_key;
+ uint8_t key_data[DPA_OFFLD_MAXENTRYKEYSIZE];
+ uint8_t mask_data[DPA_OFFLD_MAXENTRYKEYSIZE];
+ int entry_id, err;
+
+ BUG_ON(!sa);
+ BUG_ON(!policy_entry);
+
+ memset(key_data, 0, DPA_OFFLD_MAXENTRYKEYSIZE);
+ memset(mask_data, 0, DPA_OFFLD_MAXENTRYKEYSIZE);
+ if (sa->em_inpol_td < 0) {
+ log_err("Invalid exact match table for SA %d.\n", sa->id);
+ return -EINVAL;
+ }
+
+ dpa_ipsec = sa->dpa_ipsec;
+ BUG_ON(!dpa_ipsec);
+ pol_params = &policy_entry->pol_params;
+
+ switch (op_type) {
+ case MNG_OP_ADD:
+ tbl_key.byte = key_data;
+ tbl_key.mask = mask_data;
+
+ /*
+ * Key contains:
+ * IP SRC ADDR - from Policy handle
+ * IP DST ADDR - from Policy handle
+ * IP_PROTO - from Policy handle
+ * SRC_PORT - from Policy handle (for UDP & TCP)
+ * DST_PORT - from Policy handle (for UDP & TCP)
+ */
+ err = fill_policy_key(sa->em_inpol_td,
+ pol_params,
+ dpa_ipsec->config.post_sec_in_params.
+ key_fields, tbl_key.byte, tbl_key.mask,
+ &key_len, 0);
+ if (err < 0)
+ return err;
+
+ tbl_key.size = key_len;
+
+ if (pol_params->dir_params.type == DPA_IPSEC_POL_DIR_PARAMS_ACT)
+ action = &pol_params->dir_params.in_action;
+ else
+ action = &sa->def_sa_action;
+ err = dpa_classif_table_insert_entry(sa->em_inpol_td, &tbl_key,
+ action,
+ policy_entry->pol_params.priority,
+ &entry_id);
+ if (err < 0) {
+ log_err("Could not insert key in EM table\n");
+ return err;
+ }
+ *policy_entry->entry_id = entry_id;
+ break;
+ case MNG_OP_REMOVE:
+ entry_id = *policy_entry->entry_id;
+ err = dpa_classif_table_delete_entry_by_ref(sa->em_inpol_td,
+ entry_id);
+ if (err < 0) {
+ log_err("Could not remove key in EM table\n");
+ return err;
+ }
+ break;
+ case MNG_OP_MODIFY:
+ log_err("Modify operation unsupported for IN Policy PCD\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static inline int remove_dscp_policy(struct dpa_ipsec_sa *sa,
+ struct dpa_ipsec_policy_entry *pol_entry,
+ int table)
+{
+ int dscp_idx = 0, err = 0, ret = 0;
+ do {
+ ret = dpa_classif_table_delete_entry_by_ref(
+ table,
+ pol_entry->entry_id[dscp_idx]);
+ if (ret < 0) {
+ log_err("Cannot remove key from EM table\n");
+ err = ret;
+ }
+ dscp_idx += 1;
+ } while (dscp_idx <= sa->dscp_end - sa->dscp_start);
+
+ return err;
+}
+
+static int update_outbound_policy(struct dpa_ipsec_sa *sa,
+ struct dpa_ipsec_policy_entry *policy_entry,
+ enum mng_op_type op_type)
+{
+ struct dpa_ipsec *dpa_ipsec;
+ struct dpa_ipsec_pre_sec_out_params *pre_sec_out_params;
+ struct dpa_ipsec_policy_params *pol_params;
+ uint8_t key_len, table_idx, key_fields, dscp_value;
+ struct dpa_offload_lookup_key tbl_key;
+ struct dpa_cls_tbl_action action;
+ struct dpa_cls_tbl_entry_mod_params params;
+ int table, err, dscp_idx = 0;
+ int manip_hmd = DPA_OFFLD_DESC_NONE, pol_hmd = DPA_OFFLD_DESC_NONE;
+ uint8_t key_data[DPA_OFFLD_MAXENTRYKEYSIZE];
+ uint8_t mask_data[DPA_OFFLD_MAXENTRYKEYSIZE];
+
+ BUG_ON(!sa);
+ BUG_ON(!policy_entry);
+
+ memset(key_data, 0, DPA_OFFLD_MAXENTRYKEYSIZE);
+ memset(mask_data, 0, DPA_OFFLD_MAXENTRYKEYSIZE);
+ dpa_ipsec = sa->dpa_ipsec;
+ BUG_ON(!dpa_ipsec);
+ pre_sec_out_params = &dpa_ipsec->config.pre_sec_out_params;
+
+ pol_params = &policy_entry->pol_params;
+ if (IP_ADDR_TYPE_IPV4(pol_params->dest_addr))
+ table_idx = GET_POL_TABLE_IDX(pol_params->protocol, IPV4);
+ else
+ table_idx = GET_POL_TABLE_IDX(pol_params->protocol, IPV6);
+ table = pre_sec_out_params->table[table_idx].dpa_cls_td;
+ key_fields = pre_sec_out_params->table[table_idx].key_fields;
+
+ /*
+ * check if a valid desc for a proto specific table or an ANY table was
+ * provided
+ */
+ if (table == DPA_OFFLD_DESC_NONE) {
+ log_err("No suitable table found for this policy type!\n");
+ return -EBADF;
+ }
+
+ switch (op_type) {
+ case MNG_OP_ADD:
+ dscp_value = sa->dscp_start;
+ tbl_key.byte = key_data;
+ tbl_key.mask = mask_data;
+
+ /* Configure fragmentation */
+ if (pol_params->dir_params.type ==
+ DPA_IPSEC_POL_DIR_PARAMS_MANIP) {
+ manip_hmd = pol_params->dir_params.manip_desc;
+ /*
+ * check_policy_params validated manip descriptor
+ */
+ BUG_ON(manip_hmd < 0);
+ }
+
+ /* Init IPSec Manip. object (if required) for outbound policy */
+ if (manip_hmd == DPA_OFFLD_DESC_NONE)
+ goto no_frag_or_manip;
+
+ /* need to chain the IPSec Manip and Frag/Manip */
+ if (sa->dpa_ipsec->config.max_sa_manip_ops == 0)
+ err = create_ipsec_manip(sa, manip_hmd,
+ &policy_entry->hmd);
+ else
+ err = update_ipsec_manip(sa, manip_hmd,
+ &policy_entry->hmd);
+ if (err < 0) {
+ log_err("Couldn't create policy manip chain!\n");
+ return err;
+ }
+
+ pol_hmd = policy_entry->hmd;
+ if (pol_hmd == manip_hmd)
+ policy_entry->hmd_special_op = false;
+ else
+ policy_entry->hmd_special_op = true;
+
+ goto set_manipulation;
+
+no_frag_or_manip:
+ if (sa->ipsec_hmd == DPA_OFFLD_DESC_NONE) {
+ /*
+ * need to create the IPSec Manip (per SA),
+ * if it was not created earlier
+ */
+ if (sa->dpa_ipsec->config.max_sa_manip_ops == 0)
+ err = create_ipsec_manip(sa,
+ DPA_OFFLD_DESC_NONE,
+ &sa->ipsec_hmd);
+ else
+ err = update_ipsec_manip(sa,
+ DPA_OFFLD_DESC_NONE,
+ &sa->ipsec_hmd);
+ if (err < 0) {
+ log_err("Couldn't create SA manip!\n");
+ return err;
+ }
+ }
+ pol_hmd = sa->ipsec_hmd;
+
+set_manipulation:
+ memset(&action, 0, sizeof(action));
+ fill_cls_action_enq(&action,
+ sa->enable_extended_stats ? true : false,
+ qman_fq_fqid(sa->to_sec_fq), pol_hmd);
+ /*
+ * Key may contain:
+ * IP SRC ADDR - from Policy handle
+ * IP DST ADDR - from Policy handle
+ * IP_PROTO - from Policy handle
+ * DSCP - from Policy handle
+ * SRC_PORT - from Policy handle (for UDP & TCP & SCTP)
+ * DST_PORT - from Policy handle (for UDP & TCP & SCTP)
+ */
+
+ /*
+ * If SA per DSCP feature is disabled only one key is inserted
+ * and then will go out
+ */
+ if (!pol_params->use_dscp) {
+ err = fill_policy_key(table, pol_params, key_fields,
+ tbl_key.byte, tbl_key.mask,
+ &key_len, 0);
+ if (err < 0)
+ return err;
+
+ tbl_key.size = key_len;
+
+ err = dpa_classif_table_insert_entry(table, &tbl_key,
+ &action,
+ policy_entry->pol_params.priority,
+ &policy_entry->entry_id[dscp_idx]);
+ if (err < 0) {
+ log_err("Could not add key in exact match table\n");
+ return err;
+ }
+ break;
+ }
+
+ /*
+ * In case the SA per DSCP feature will be used, it will iterate
+ * through all DSCP values and insert a key for each one.
+ */
+ do {
+ err = fill_policy_key(table, pol_params, key_fields,
+ tbl_key.byte, tbl_key.mask,
+ &key_len, dscp_value);
+ if (err < 0)
+ return err;
+
+ tbl_key.size = key_len;
+
+ err = dpa_classif_table_insert_entry(table, &tbl_key,
+ &action,
+ policy_entry->pol_params.priority,
+ &policy_entry->entry_id[dscp_idx]);
+ if (err < 0) {
+ log_err("Could not add key in exact match table\n");
+ return err;
+ }
+
+ dscp_value += 1;
+ dscp_idx += 1;
+ } while (dscp_value <= sa->dscp_end);
+
+ break;
+ case MNG_OP_REMOVE:
+ if (pol_params->use_dscp) {
+ err = remove_dscp_policy(sa, policy_entry, table);
+ if (err < 0)
+ return err;
+
+ } else {
+ err = dpa_classif_table_delete_entry_by_ref(table,
+ *policy_entry->entry_id);
+ if (err < 0) {
+ log_err("Could not remove key from EM table\n");
+ return err;
+ }
+ }
+
+ if (policy_entry->hmd != DPA_OFFLD_DESC_NONE) {
+ struct hmd_entry hmd_entry;
+ hmd_entry.hmd = policy_entry->hmd;
+ hmd_entry.hmd_special_op = policy_entry->hmd_special_op;
+ err = destroy_recycle_manip(sa, &hmd_entry);
+ if (err < 0) {
+ log_err("Couldn't delete frag & ipsec manip\n");
+ return err;
+ }
+ policy_entry->hmd = DPA_OFFLD_DESC_NONE;
+ }
+
+ break;
+ case MNG_OP_MODIFY:
+ if (policy_entry->hmd != DPA_OFFLD_DESC_NONE)
+ pol_hmd = policy_entry->hmd;
+ else
+ pol_hmd = sa->ipsec_hmd;
+
+ memset(&action, 0, sizeof(action));
+ fill_cls_action_enq(&action,
+ sa->enable_extended_stats ? true : false,
+ qman_fq_fqid(sa->to_sec_fq), pol_hmd);
+
+ memset(&params, 0, sizeof(params));
+ params.type = DPA_CLS_TBL_MODIFY_ACTION;
+ params.key = NULL;
+ params.action = &action;
+
+ err = dpa_classif_table_modify_entry_by_ref(table,
+ *policy_entry->entry_id,
+ &params);
+ if (err < 0) {
+ log_err("Could not modify key in EM table\n");
+ return err;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static int update_pre_sec_inbound_table(struct dpa_ipsec_sa *sa,
+ enum mng_op_type op_type)
+{
+ struct dpa_ipsec *dpa_ipsec;
+ int table, table_idx, entry_id, offset, err = 0, tbl_key_size = 0, i;
+ struct dpa_offload_lookup_key tbl_key;
+ struct dpa_cls_tbl_action action;
+ struct dpa_cls_tbl_params tbl_params;
+ struct dpa_cls_tbl_entry_mod_params mod_params;
+ uint8_t key[DPA_OFFLD_MAXENTRYKEYSIZE];
+
+ BUG_ON(!sa);
+
+ dpa_ipsec = sa->dpa_ipsec;
+ BUG_ON(!dpa_ipsec);
+
+ switch (op_type) {
+ case MNG_OP_ADD:
+ /* Determine the correct table to be used for this type of SA */
+ table_idx = GET_SA_TABLE_IDX(sa->dest_addr, sa->use_udp_encap);
+ table =
+ dpa_ipsec->config.pre_sec_in_params.dpa_cls_td[table_idx];
+ if (table == DPA_OFFLD_DESC_NONE) {
+ log_err("No SA table defined for this type of SA\n");
+ return -EBADF;
+ }
+
+ /* Store the table descriptor to be used in subsequent ops */
+ sa->inbound_sa_td = table;
+
+ /*
+ * Mark classifier entry id as invalid until it's properly
+ * inserted
+ */
+ sa->inbound_hash_entry = DPA_OFFLD_INVALID_OBJECT_ID;
+ sa->valid_flowid_entry = false;
+
+ tbl_key.byte = key;
+ /* Key masks are not supported by HASH tables*/
+ tbl_key.mask = NULL;
+
+ /*
+ * Key contains:
+ * IP DST ADDR - from SA handle
+ * IP_PROTO - always ESP (SEC limitation)
+ * UDP_SPORT - in case of UDP encapsulated ESP
+ * UDP_DPORT - in case of UDP encapsulated ESP
+ * SPI - from SA handle
+ */
+
+ /* Fill in the key components */
+ memcpy(key, IP_ADDR(sa->dest_addr), IP_ADDR_LEN(sa->dest_addr));
+
+ offset = IP_ADDR_LEN(sa->dest_addr);
+ if (sa->use_udp_encap) {
+ SET_BYTE_VAL_IN_ARRAY(key, offset, IPPROTO_UDP);
+ offset += IP_PROTO_FIELD_LEN;
+ memcpy(key + offset, (uint8_t *) &(sa->udp_src_port),
+ PORT_FIELD_LEN);
+ offset += PORT_FIELD_LEN;
+ memcpy(key + offset, (uint8_t *) &(sa->udp_dest_port),
+ PORT_FIELD_LEN);
+ offset += PORT_FIELD_LEN;
+ } else {
+ SET_BYTE_VAL_IN_ARRAY(key, offset, IPPROTO_ESP);
+ offset += IP_PROTO_FIELD_LEN;
+ }
+
+ memcpy(key + offset, (uint8_t *) &sa->spi, ESP_SPI_FIELD_LEN);
+ offset += ESP_SPI_FIELD_LEN;
+
+ /* determine padding length based on the table params */
+ err = dpa_classif_table_get_params(table, &tbl_params);
+ if (err < 0) {
+ log_err("Could not get table maximum key size\n");
+ return err;
+ }
+ tbl_key_size = TABLE_KEY_SIZE(tbl_params);
+
+ if (tbl_key_size < offset) {
+ log_err("SA lookup key is greater than maximum table key size\n");
+ return -EINVAL;
+ }
+
+ if (tbl_key_size > offset) {
+ for (i = 0; i < tbl_key_size - offset; i++)
+ *(key + offset + i) = DPA_IPSEC_DEF_PAD_VAL;
+ offset = tbl_key_size;
+ }
+
+ /* Key size cannot be greater than 56 bytes */
+ tbl_key.size = (uint8_t)offset;
+
+ /* Complete the parameters for table insert function */
+ memset(&action, 0, sizeof(action));
+ fill_cls_action_enq(&action,
+ sa->enable_extended_stats ? true : false,
+ qman_fq_fqid(sa->to_sec_fq), sa->ipsec_hmd);
+
+ err = dpa_classif_table_insert_entry(table, &tbl_key, &action,
+ 0, &entry_id);
+ if (err < 0) {
+ log_err("Could not add key for inbound SA!\n");
+ return err;
+ }
+ sa->inbound_hash_entry = entry_id;
+ break;
+
+ case MNG_OP_REMOVE:
+ entry_id = sa->inbound_hash_entry;
+ err = dpa_classif_table_delete_entry_by_ref(sa->inbound_sa_td,
+ entry_id);
+ if (err < 0) {
+ log_err("Could not remove key for inbound SA!\n");
+ return err;
+ }
+ sa->inbound_hash_entry = DPA_OFFLD_INVALID_OBJECT_ID;
+ break;
+
+ case MNG_OP_MODIFY:
+ fill_cls_action_drop(&action, FALSE);
+
+ memset(&mod_params, 0, sizeof(mod_params));
+ mod_params.type = DPA_CLS_TBL_MODIFY_ACTION;
+ mod_params.key = NULL;
+ mod_params.action = &action;
+
+ entry_id = sa->inbound_hash_entry;
+ err = dpa_classif_table_modify_entry_by_ref(sa->inbound_sa_td,
+ entry_id,
+ &mod_params);
+ if (err < 0) {
+ log_err("Failed set drop action for inbound SA %d\n",
+ sa->id);
+ return err;
+ }
+ sa->inbound_hash_entry = DPA_OFFLD_INVALID_OBJECT_ID;
+ break;
+ }
+
+ return err;
+}
+
+static int remove_inbound_hash_entry(struct dpa_ipsec_sa *sa)
+{
+ int err;
+
+ BUG_ON(!sa);
+
+ err = update_pre_sec_inbound_table(sa, MNG_OP_REMOVE);
+ if (unlikely(err < 0)) {
+ pr_crit("Failed to remove inbound key for SA %d\n", sa->id);
+ return -ENOTRECOVERABLE;
+ }
+
+ return 0;
+}
+
+static inline int remove_inbound_flow_id_classif(struct dpa_ipsec_sa *sa)
+{
+ struct dpa_ipsec *dpa_ipsec;
+ struct dpa_cls_tbl_action action;
+ int err;
+
+ dpa_ipsec = sa->dpa_ipsec;
+
+ memset(&action, 0, sizeof(action));
+ action.type = DPA_CLS_TBL_ACTION_DROP;
+ err = set_flow_id_action(sa, &action);
+ if (err < 0) {
+ log_err("Could not remove SA entry in indexed table\n");
+ return err;
+ }
+
+ if (dpa_ipsec->config.post_sec_in_params.do_pol_check)
+ put_free_inbpol_tbl(dpa_ipsec, sa->em_inpol_td);
+
+ sa->valid_flowid_entry = false;
+
+ return 0;
+}
+
+static int get_new_fqid(struct dpa_ipsec *dpa_ipsec, uint32_t *fqid)
+{
+ int err = 0;
+
+ BUG_ON(!dpa_ipsec);
+ BUG_ON(!fqid);
+
+ if (dpa_ipsec->sa_mng.fqid_cq != NULL) {
+ err = cq_get_4bytes(dpa_ipsec->sa_mng.fqid_cq, fqid);
+ if (err < 0)
+ log_err("FQID allocation (from range) failure.\n");
+ return err;
+ }
+
+ /* No pool defined. Get FQID from default allocator. */
+ err = qman_alloc_fqid(fqid);
+ if (err < 0) {
+ log_err("FQID allocation (no pool) failure.\n");
+ return -ERANGE;
+ }
+
+ return 0;
+}
+
+static void put_free_fqid(struct dpa_ipsec *dpa_ipsec, uint32_t fqid)
+{
+ int err;
+
+ BUG_ON(!dpa_ipsec);
+
+ /* recycle the FQID */
+ if (dpa_ipsec->sa_mng.fqid_cq != NULL) {
+ err = cq_put_4bytes(dpa_ipsec->sa_mng.fqid_cq, fqid);
+ BUG_ON(err < 0);
+ } else {
+ qman_release_fqid(fqid);
+ }
+}
+
+static int wait_until_fq_empty(struct qman_fq *fq, int timeout)
+{
+ struct qm_mcr_queryfq_np queryfq_np;
+
+ BUG_ON(!fq);
+
+ do {
+ qman_query_fq_np(fq, &queryfq_np);
+ cpu_relax();
+ udelay(1);
+ timeout = timeout - 1;
+ } while (queryfq_np.frm_cnt && timeout);
+
+ if (timeout == 0) {
+ log_err("Timeout. Fq with id %d not empty.\n", fq->fqid);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int remove_sa_sec_fq(struct dpa_ipsec_sa *sa, struct qman_fq *sec_fq)
+{
+ int err, flags, timeout = WAIT4_FQ_EMPTY_TIMEOUT;
+
+ BUG_ON(!sa);
+ BUG_ON(!sa->dpa_ipsec);
+ BUG_ON(!sec_fq);
+
+ /* Check if already removed, and return success if so. */
+ if (sec_fq->fqid == 0)
+ return 0;
+
+ err = wait_until_fq_empty(sec_fq, timeout);
+ if (err < 0)
+ return err;
+
+ err = qman_retire_fq(sec_fq, &flags);
+ if (err < 0) {
+ log_err("Failed to retire FQ %d\n", sec_fq->fqid);
+ return err;
+ }
+
+ err = qman_oos_fq(sec_fq);
+ if (err < 0) {
+ log_err("Failed to OOS FQ %d\n", sec_fq->fqid);
+ return err;
+ }
+
+ qman_destroy_fq(sec_fq, 0);
+
+ /* release FQID */
+ put_free_fqid(sa->dpa_ipsec, sec_fq->fqid);
+
+ /* Clean the FQ structure for reuse */
+ memset(sec_fq, 0, sizeof(struct qman_fq));
+
+ return 0;
+}
+
+static int remove_sa_fq_pair(struct dpa_ipsec_sa *sa)
+{
+ int err;
+
+ BUG_ON(!sa);
+
+ err = remove_sa_sec_fq(sa, sa->to_sec_fq);
+ if (err < 0)
+ return err;
+
+ if (sa_is_single(sa)) {
+ err = remove_sa_sec_fq(sa, sa->from_sec_fq);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static int create_sec_frame_queue(uint32_t fq_id, uint16_t channel,
+ uint16_t wq_id, uint32_t ctx_a_hi,
+ uint32_t ctx_a_lo, uint32_t ctxB,
+ uint32_t sp_op, void *fm_pcd, bool parked,
+ struct qman_fq *fq)
+{
+ struct qm_mcc_initfq fq_opts;
+ uint32_t flags;
+ int err = 0;
+
+ BUG_ON(!fq);
+
+ memset(fq, 0, sizeof(struct qman_fq));
+
+ flags = QMAN_FQ_FLAG_LOCKED | QMAN_FQ_FLAG_TO_DCPORTAL;
+
+ err = qman_create_fq(fq_id, flags, fq);
+ if (unlikely(err < 0)) {
+ log_err("Could not create FQ with ID: %u\n", fq_id);
+ goto create_sec_fq_err;
+ }
+
+ /*
+ * generate a parked queue or a scheduled one depending on the function
+ * input parameters.
+ */
+ flags = (parked == true) ? 0 : QMAN_INITFQ_FLAG_SCHED;
+ memset(&fq_opts, 0, sizeof(fq_opts));
+ fq_opts.we_mask = QM_INITFQ_WE_DESTWQ | QM_INITFQ_WE_CONTEXTA |
+ QM_INITFQ_WE_CONTEXTB;
+ if (ctx_a_lo) {
+ fq_opts.fqd.context_a.hi = ctx_a_hi;
+ fq_opts.fqd.context_a.lo = ctx_a_lo;
+ fq_opts.fqd.context_b = ctxB;
+ } else {
+ uint8_t sp_op_code = 0;
+ t_Error error;
+
+ /*
+ * configure uCode commands for handling flowID and other update
+ * operations:
+ * - retrieve special operation code (for IPSec and possibly
+ * other updates on UDP header fields)
+ * - enable ctxB;
+ * - set ctxA override;
+ * - set in ctxB the FlowID and special operation code
+ */
+ if (sp_op) {
+ void *fm = NULL;
+
+ /* get FMan handle from the PCD handle*/
+ fm = ((t_FmPcd *)fm_pcd)->h_Fm;
+
+ error = FM_GetSpecialOperationCoding(fm, sp_op,
+ &sp_op_code);
+ if (error != E_OK) {
+ log_err("FM_GetSpecialOperationCoding failed\n");
+ log_err("Could not retrieve special op code");
+ goto create_sec_fq_err;
+ }
+ /* the opcode is a 4-bit value */
+ sp_op_code &= NIA_OPCODE_MASK;
+ }
+#if (DPAA_VERSION == 10)
+ /* FMAN v2 devices: opcode and flow id are stored in contextB */
+ FM_CONTEXTA_SET_OVERRIDE(&fq_opts.fqd.context_a, true);
+ FM_CONTEXTB_SET_FQID(&(fq_opts.fqd.context_b), ctxB |
+ (sp_op_code << 20));
+#elif (DPAA_VERSION == 11)
+ /* FMAN v3 devices: opcode and flow id are stored in contextA */
+ FM_CONTEXTA_SET_A1_VALID(&fq_opts.fqd.context_a, true);
+ FM_CONTEXTA_SET_A1(&fq_opts.fqd.context_a,
+ ((ctxB << 4) | sp_op_code));
+#endif
+ }
+
+ fq_opts.fqd.dest.wq = wq_id;
+ fq_opts.fqd.dest.channel = channel;
+
+ err = qman_init_fq(fq, flags, &fq_opts);
+ if (unlikely(err < 0)) {
+ log_err("Could not init FQ with ID: %u\n", fq->fqid);
+ goto create_sec_fq_err;
+ }
+
+ return 0;
+
+ create_sec_fq_err:
+ /*Reset all fields of FQ structure (including FQID) to mark it invalid*/
+ memset(fq, 0, sizeof(struct qman_fq));
+
+ return err;
+}
+
+static int create_sa_fq_pair(struct dpa_ipsec_sa *sa,
+ bool reuse_from_secfq, bool parked_to_secfq)
+{
+ void *ctxtA;
+ uint32_t ctxtA_hi, ctxtA_lo;
+ phys_addr_t addr;
+ struct dpa_ipsec *dpa_ipsec;
+ uint32_t fqid_from_sec = 0, fqid_to_sec = 0;
+ int err;
+
+ BUG_ON(!sa);
+
+ dpa_ipsec = sa->dpa_ipsec;
+ BUG_ON(!dpa_ipsec);
+
+ err = create_sec_descriptor(sa);
+ if (err < 0) {
+ log_err("Could not create sec descriptor\n");
+ return err;
+ }
+
+ ctxtA = sa->sec_desc;
+ addr = virt_to_phys(ctxtA);
+ ctxtA_hi = (uint32_t) (addr >> 32);
+ ctxtA_lo = (uint32_t) (addr);
+
+ /*
+ * If reuse FROM SEC FQ is false than create other FROM SEC FQ
+ * and set it as output frame queue for this SA. Otherwise
+ * profit that you poses a valid FROM SEC FQ from the OLD SA
+ * and use it accordingly.
+ */
+ if (!reuse_from_secfq) {
+ uint16_t chan, flow_id;
+ uint32_t sp_op = 0;
+
+ sp_op = FM_SP_OP_IPSEC;
+ if (sa_is_outbound(sa) && sa->use_udp_encap)
+ sp_op |= FM_SP_OP_IPSEC_UPDATE_UDP_LEN;
+ if (sa->dscp_copy || sa->ecn_copy)
+ sp_op |= FM_SP_OP_IPSEC_MANIP | FM_SP_OP_RPD;
+
+ /* acquire fqid for 'FROM SEC' fq */
+ err = get_new_fqid(dpa_ipsec, &fqid_from_sec);
+ if (err < 0)
+ return err;
+
+ if (sa_is_outbound(sa)) {
+ chan = dpa_ipsec->config.post_sec_out_params.qm_tx_ch;
+ flow_id = sa->outbound_flowid;
+ } else {
+ chan = dpa_ipsec->config.post_sec_in_params.qm_tx_ch;
+ flow_id = sa->inbound_flowid;
+ }
+
+ err = create_sec_frame_queue(fqid_from_sec,
+ chan, sa->sa_wqid, 0, 0, /* ctxA */
+ flow_id, /*ctxB forwarding info*/
+ sp_op,
+ sa->dpa_ipsec->config.fm_pcd,
+ FALSE, sa->from_sec_fq);
+ if (err < 0) {
+ log_err("From SEC FQ couldn't be created\n");
+ goto create_fq_pair_err;
+ }
+ }
+
+ /* acquire fqid for 'TO SEC' fq */
+ err = get_new_fqid(dpa_ipsec, &fqid_to_sec);
+ if (err < 0)
+ goto create_fq_pair_err;
+
+ err = create_sec_frame_queue(fqid_to_sec,
+ dpa_ipsec->config.qm_sec_ch,
+ sa->sa_wqid, ctxtA_hi, ctxtA_lo, /* ctxA */
+ qman_fq_fqid(sa->from_sec_fq), /*ctxB - output SEC fq*/
+ 0, NULL, parked_to_secfq, sa->to_sec_fq);
+ if (err < 0) {
+ log_err("%s FQ (to SEC) couldn't be created\n",
+ sa_is_outbound(sa) ? "Encrypt" : "Decrypt");
+ goto create_fq_pair_err;
+ }
+
+ return 0;
+
+ create_fq_pair_err:
+ if (qman_fq_fqid(sa->from_sec_fq) != 0)
+ remove_sa_sec_fq(sa, sa->from_sec_fq);
+ else
+ put_free_fqid(dpa_ipsec, fqid_from_sec); /* recycle the FQID */
+
+ if (fqid_to_sec != 0)
+ put_free_fqid(dpa_ipsec, fqid_to_sec); /*recycle the FQID */
+
+ return err;
+}
+
+static inline int set_cipher_auth_alg(enum dpa_ipsec_cipher_alg alg_suite,
+ uint16_t *cipher, uint16_t *auth)
+{
+ *cipher = ipsec_algs[alg_suite].enc_alg;
+ *auth = ipsec_algs[alg_suite].auth_alg;
+
+ if (*cipher == OP_PCL_IPSEC_INVALID_ALG_ID ||
+ *auth == OP_PCL_IPSEC_INVALID_ALG_ID) {
+ log_err("Invalid algorithm suite selected\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int copy_sa_params_to_out_sa(struct dpa_ipsec_sa *sa,
+ struct dpa_ipsec_sa_params *sa_params)
+{
+ struct iphdr *outer_ip_hdr;
+ unsigned int ip_addr_type;
+ int err;
+
+ BUG_ON(!sa);
+ BUG_ON(!sa_params);
+
+ sa->sa_dir = DPA_IPSEC_OUTBOUND;
+ sa->sa_bpid = sa_params->sa_bpid;
+ sa->sa_bufsize = sa_params->sa_bufsize;
+ sa->sa_wqid = sa_params->sa_wqid;
+ ip_addr_type = sa_params->sa_out_params.ip_ver;
+
+ sa->alg_suite = sa_params->crypto_params.alg_suite;
+ err = set_cipher_auth_alg(sa_params->crypto_params.alg_suite,
+ &sa->cipher_data.cipher_type,
+ &sa->auth_data.auth_type);
+ if (err < 0)
+ return err;
+
+ sa->auth_data.auth_key_len = sa_params->crypto_params.auth_key_len;
+ memcpy(sa->auth_data.auth_key,
+ sa_params->crypto_params.auth_key,
+ sa_params->crypto_params.auth_key_len);
+
+ sa->cipher_data.cipher_key_len =
+ sa_params->crypto_params.cipher_key_len;
+ memcpy(sa->cipher_data.cipher_key,
+ sa_params->crypto_params.cipher_key,
+ sa_params->crypto_params.cipher_key_len);
+ sa->sec_desc->pdb_en.spi = sa_params->spi;
+ sa->sec_desc->pdb_en.options = PDBOPTS_ESP_TUNNEL |
+ PDBOPTS_ESP_INCIPHDR |
+ PDBOPTS_ESP_IPHDRSRC;
+ if (sa_params->hdr_upd_flags) {
+ if (sa_params->hdr_upd_flags & DPA_IPSEC_HDR_COPY_TOS)
+ sa->sec_desc->pdb_en.options |= PDBOPTS_ESP_DIFFSERV;
+ if (sa_params->hdr_upd_flags & DPA_IPSEC_HDR_COPY_DF) {
+ if (ip_addr_type == DPA_IPSEC_ADDR_T_IPv4)
+ sa->sec_desc->pdb_en.hmo_rsvd |=
+ PDBHMO_ESP_DFBIT;
+ else
+ pr_warn("Copy DF not supported for IPv6 SA");
+ }
+ if (sa_params->hdr_upd_flags & DPA_IPSEC_HDR_DEC_TTL)
+ sa->sec_desc->pdb_en.hmo_rsvd |=
+ PDBHMO_ESP_ENCAP_DEC_TTL;
+
+ sa->dscp_copy =
+ sa_params->hdr_upd_flags & DPA_IPSEC_HDR_COPY_DSCP;
+ sa->ecn_copy =
+ sa_params->hdr_upd_flags & DPA_IPSEC_HDR_COPY_ECN;
+ }
+
+ sa->enable_dpovrd = true;
+
+ if (sa_params->use_ext_seq_num) {
+ sa->sec_desc->pdb_en.seq_num_ext_hi =
+ (sa_params->start_seq_num & SEQ_NUM_HI_MASK) >> 32;
+ sa->sec_desc->pdb_en.options |= PDBOPTS_ESP_ESN;
+ }
+ sa->sec_desc->pdb_en.seq_num =
+ sa_params->start_seq_num & SEQ_NUM_LOW_MASK;
+
+ if (ip_addr_type == DPA_IPSEC_ADDR_T_IPv6)
+ sa->sec_desc->pdb_en.options |= PDBOPTS_ESP_IPV6;
+ else
+ sa->sec_desc->pdb_en.options |= PDBOPTS_ESP_UPDATE_CSUM;
+
+ if (!sa_params->sa_out_params.init_vector)
+ sa->sec_desc->pdb_en.options |= PDBOPTS_ESP_IVSRC;
+ else
+ memcpy(&sa->sec_desc->pdb_en.cbc,
+ sa_params->sa_out_params.init_vector->init_vector,
+ sa_params->sa_out_params.init_vector->length);
+
+ sa->outbound_flowid = sa_params->sa_out_params.post_sec_flow_id;
+
+ /* Copy the outer header and generate the original header checksum */
+ memcpy(&sa->sec_desc->pdb_en.ip_hdr[0],
+ sa_params->sa_out_params.outer_ip_header,
+ sa_params->sa_out_params.ip_hdr_size);
+
+ if (sa_params->sa_out_params.outer_udp_header) {
+ uint8_t *tmp;
+ struct udphdr *udp_hdr;
+
+ tmp = (uint8_t *) &sa->sec_desc->pdb_en.ip_hdr[0];
+ memcpy(tmp + sa_params->sa_out_params.ip_hdr_size,
+ sa_params->sa_out_params.outer_udp_header,
+ UDP_HEADER_LEN);
+ sa->sec_desc->pdb_en.ip_hdr_len =
+ sa_params->sa_out_params.ip_hdr_size + UDP_HEADER_LEN;
+ sa->use_udp_encap = true;
+
+ /* disable UDP checksum calculation, because for now there is
+ * no mechanism for UDP checksum update */
+ udp_hdr = (struct udphdr *) (tmp +
+ sa_params->sa_out_params.ip_hdr_size);
+ udp_hdr->check = 0x0000;
+
+ if (ip_addr_type == DPA_IPSEC_ADDR_T_IPv4) {
+ outer_ip_hdr = (struct iphdr *)
+ &sa->sec_desc->pdb_en.ip_hdr[0];
+ outer_ip_hdr->protocol = IPPROTO_UDP;
+ } else {
+ /*
+ * this should never be reached - it should be checked
+ * before in check SA params function
+ */
+ log_err("NAT-T is not supported for IPv6 SAs\n");
+ return -EINVAL;
+ }
+ } else {
+ sa->sec_desc->pdb_en.ip_hdr_len =
+ sa_params->sa_out_params.ip_hdr_size;
+ }
+
+ if (ip_addr_type == DPA_IPSEC_ADDR_T_IPv4) {
+ outer_ip_hdr = (struct iphdr *) &sa->sec_desc->pdb_en.ip_hdr[0];
+ outer_ip_hdr->check =
+ ip_fast_csum((unsigned char *)outer_ip_hdr,
+ outer_ip_hdr->ihl);
+ }
+
+ /* Only IPv4 inner packets are currently supported */
+ sa->sec_desc->pdb_en.ip_nh = 0x04;
+
+ sa->l2_hdr_size = sa_params->l2_hdr_size;
+ sa->enable_stats = sa_params->enable_stats;
+ sa->enable_extended_stats = sa_params->enable_extended_stats;
+ if (sa_params->sa_out_params.dscp_end <
+ sa_params->sa_out_params.dscp_start) {
+ log_err("Wrong DSCP interval, dscp_start (%d) cannot be greater than dscp_end (%d)\n",
+ sa_params->sa_out_params.dscp_start,
+ sa_params->sa_out_params.dscp_end);
+ return -EINVAL;
+ }
+ sa->dscp_start = sa_params->sa_out_params.dscp_start;
+ sa->dscp_end = sa_params->sa_out_params.dscp_end;
+#ifdef DEBUG_PARAM
+ /* Printing all the parameters */
+ print_sa_sec_param(sa);
+#endif
+
+ return 0;
+}
+
+static int copy_sa_params_to_in_sa(struct dpa_ipsec_sa *sa,
+ struct dpa_ipsec_sa_params *sa_params,
+ bool rekeying)
+{
+ struct dpa_ipsec *dpa_ipsec;
+ int err;
+
+ BUG_ON(!sa);
+ BUG_ON(!sa_params);
+
+ dpa_ipsec = sa->dpa_ipsec;
+ BUG_ON(!dpa_ipsec);
+
+ /* reserve a FlowID for this SA only if we are not rekeying */
+ if (!ignore_post_ipsec_action(dpa_ipsec) && !rekeying) {
+ err = get_inbound_flowid(dpa_ipsec, &sa->inbound_flowid);
+ if (err < 0) {
+ log_err("Can't get valid inbound flow id\n");
+ sa->inbound_flowid = INVALID_INB_FLOW_ID;
+ return -EINVAL;
+ }
+ }
+
+ sa->sa_dir = DPA_IPSEC_INBOUND;
+ sa->sa_bpid = sa_params->sa_bpid;
+ sa->sa_bufsize = sa_params->sa_bufsize;
+ sa->sa_wqid = sa_params->sa_wqid;
+ sa->spi = sa_params->spi;
+
+ sa->alg_suite = sa_params->crypto_params.alg_suite;
+ err = set_cipher_auth_alg(sa_params->crypto_params.alg_suite,
+ &sa->cipher_data.cipher_type,
+ &sa->auth_data.auth_type);
+ if (err < 0)
+ return err;
+
+ sa->auth_data.auth_key_len = sa_params->crypto_params.auth_key_len;
+ memcpy(sa->auth_data.auth_key,
+ sa_params->crypto_params.auth_key,
+ sa_params->crypto_params.auth_key_len);
+
+ sa->cipher_data.cipher_key_len =
+ sa_params->crypto_params.cipher_key_len;
+ memcpy(sa->cipher_data.cipher_key,
+ sa_params->crypto_params.cipher_key,
+ sa_params->crypto_params.cipher_key_len);
+
+ sa->use_udp_encap = sa_params->sa_in_params.use_udp_encap;
+ sa->udp_src_port = sa_params->sa_in_params.src_port;
+ sa->udp_dest_port = sa_params->sa_in_params.dest_port;
+ sa->use_var_iphdr_len = sa_params->sa_in_params.use_var_iphdr_len;
+
+ memcpy(&sa->def_sa_action,
+ &sa_params->sa_in_params.post_ipsec_action,
+ sizeof(struct dpa_cls_tbl_action));
+
+ if (sa->def_sa_action.type == DPA_CLS_TBL_ACTION_ENQ &&
+ sa->def_sa_action.enq_params.policer_params) {
+ struct dpa_cls_tbl_policer_params *policer_params;
+ policer_params = kzalloc(sizeof(*policer_params), GFP_KERNEL);
+ if (!policer_params) {
+ log_err("Could not allocate memory for policer parameters\n");
+ return -ENOMEM;
+ }
+ memcpy(policer_params,
+ sa->def_sa_action.enq_params.policer_params,
+ sizeof(*policer_params));
+ sa->def_sa_action.enq_params.policer_params = policer_params;
+ }
+
+ sa->sec_desc->pdb_dec.seq_num =
+ sa_params->start_seq_num & SEQ_NUM_LOW_MASK;
+ sa->sec_desc->pdb_dec.options = PDBOPTS_ESP_TUNNEL |
+ PDBOPTS_ESP_OUTFMT;
+
+ if (dpa_ipsec->sec_ver >= SEC_VER_5_3)
+ sa->sec_desc->pdb_dec.options |= PDBOPTS_ESP_AOFL;
+
+ if (sa_params->use_ext_seq_num) {
+ sa->sec_desc->pdb_dec.seq_num_ext_hi =
+ (sa_params->start_seq_num & SEQ_NUM_HI_MASK) >> 32;
+ sa->sec_desc->pdb_dec.options |= PDBOPTS_ESP_ESN;
+ }
+
+ if (sa_params->sa_in_params.dest_addr.version ==
+ DPA_IPSEC_ADDR_T_IPv6)
+ sa->sec_desc->pdb_dec.options |= PDBOPTS_ESP_IPVSN;
+ else
+ sa->sec_desc->pdb_dec.options |= PDBOPTS_ESP_VERIFY_CSUM;
+
+ switch (sa_params->sa_in_params.arw) {
+ case DPA_IPSEC_ARSNONE:
+ sa->sec_desc->pdb_dec.options |= PDBOPTS_ESP_ARSNONE;
+ break;
+ case DPA_IPSEC_ARS32:
+ sa->sec_desc->pdb_dec.options |= PDBOPTS_ESP_ARS32;
+ break;
+ case DPA_IPSEC_ARS64:
+ sa->sec_desc->pdb_dec.options |= PDBOPTS_ESP_ARS64;
+ break;
+ default:
+ log_err("Invalid ARS mode specified\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Updated the offset to the point in frame were the encrypted
+ * stuff starts.
+ */
+ if (sa_params->sa_in_params.dest_addr.version ==
+ DPA_IPSEC_ADDR_T_IPv6)
+ sa->sec_desc->pdb_dec.hmo_ip_hdr_len =
+ (uint16_t) sizeof(struct ipv6hdr);
+ else
+ sa->sec_desc->pdb_dec.hmo_ip_hdr_len =
+ (uint16_t) sizeof(struct iphdr);
+ if (sa->use_udp_encap)
+ sa->sec_desc->pdb_dec.hmo_ip_hdr_len += UDP_HEADER_LEN;
+
+ if (sa_params->hdr_upd_flags) {
+ if (sa_params->hdr_upd_flags & DPA_IPSEC_HDR_COPY_TOS)
+ sa->sec_desc->pdb_dec.hmo_ip_hdr_len |=
+ PDBHMO_ESP_DIFFSERV;
+ if (sa_params->hdr_upd_flags & DPA_IPSEC_HDR_DEC_TTL)
+ sa->sec_desc->pdb_dec.hmo_ip_hdr_len |=
+ PDBHMO_ESP_DECAP_DEC_TTL;
+ if (sa_params->hdr_upd_flags & DPA_IPSEC_HDR_COPY_DF)
+ pr_info("Copy DF bit not supported for inbound SAs");
+
+ sa->dscp_copy =
+ sa_params->hdr_upd_flags & DPA_IPSEC_HDR_COPY_DSCP;
+ sa->ecn_copy =
+ sa_params->hdr_upd_flags & DPA_IPSEC_HDR_COPY_ECN;
+ }
+
+ /* Only for outbound */
+ sa->enable_dpovrd = false;
+
+ memcpy(&sa->src_addr,
+ &sa_params->sa_in_params.src_addr,
+ sizeof(struct dpa_offload_ip_address));
+
+ memcpy(&sa->dest_addr,
+ &sa_params->sa_in_params.dest_addr,
+ sizeof(struct dpa_offload_ip_address));
+
+ sa->policy_miss_action = sa_params->sa_in_params.policy_miss_action;
+ sa->l2_hdr_size = sa_params->l2_hdr_size;
+ sa->enable_stats = sa_params->enable_stats;
+ sa->enable_extended_stats = sa_params->enable_extended_stats;
+#ifdef DEBUG_PARAM
+ /* Printing all the parameters */
+ print_sa_sec_param(sa);
+#endif
+
+ return 0;
+}
+
+static int check_policy_params(struct dpa_ipsec_sa *sa,
+ struct dpa_ipsec_policy_params *pol_params)
+{
+ BUG_ON(!sa);
+ BUG_ON(!pol_params);
+
+ /* check if both IP address are of the same type */
+ if (pol_params->src_addr.version != pol_params->dest_addr.version) {
+ log_err("Src and dest IP address types must be the same!\n");
+ return -EINVAL;
+ }
+
+ /* check if IP address version is valid */
+ if (pol_params->src_addr.version != DPA_IPSEC_ADDR_T_IPv4 &&
+ pol_params->src_addr.version != DPA_IPSEC_ADDR_T_IPv6) {
+ log_err("Src and dest IP address types either 4 or 6!\n");
+ return -EINVAL;
+ }
+
+ /* check if fragmentation is enabled for inbound SAs */
+ if (pol_params->dir_params.type == DPA_IPSEC_POL_DIR_PARAMS_MANIP &&
+ sa_is_inbound(sa)) {
+ log_err("Fragmentation or header manipulation can't be enabled for inbound policy!\n");
+ return -EINVAL;
+ }
+
+ if (pol_params->dir_params.type == DPA_IPSEC_POL_DIR_PARAMS_MANIP &&
+ pol_params->dir_params.manip_desc < 0) {
+ log_err("Invalid manip descriptor for SA id %d\n", sa->id);
+ return -EINVAL;
+ }
+
+ /*
+ * check if post inbound policy verification action was configured for
+ * outbound policies
+ */
+ if (pol_params->dir_params.type == DPA_IPSEC_POL_DIR_PARAMS_ACT &&
+ sa_is_outbound(sa)) {
+ log_err("Action cannot be configured for outbound policy!\n");
+ return -EINVAL;
+ }
+
+ /* check if DF bit was set and an IPv6 policy is being offloaded */
+ if (sa_is_outbound(sa) &&
+ sa->sec_desc->pdb_en.hmo_rsvd == PDBHMO_ESP_DFBIT &&
+ pol_params->src_addr.version == DPA_IPSEC_ADDR_T_IPv6) {
+ log_err("Can't add IPv6 policy to IPv4 SA w/ DF bit copy set\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int store_policy_param_to_sa_pol_list(struct dpa_ipsec_sa *sa,
+ struct dpa_ipsec_policy_params *policy_params,
+ struct dpa_ipsec_policy_entry **policy_entry)
+{
+ struct dpa_ipsec_policy_entry *pol_entry;
+ struct dpa_ipsec_pol_dir_params *dir = NULL;
+ int size = 1; /* By default the size of the entry_id array is one */
+
+ BUG_ON(!sa);
+ BUG_ON(!policy_params);
+ BUG_ON(!policy_entry);
+
+ pol_entry = kzalloc(sizeof(*pol_entry), GFP_KERNEL);
+ if (!pol_entry) {
+ log_err("Could not allocate memory for policy\n");
+ return -ENOMEM;
+ }
+
+ /* Initialize the policy Manip handle to an invalid value */
+ pol_entry->hmd = DPA_OFFLD_DESC_NONE;
+
+ /* copy policy parameters */
+ pol_entry->pol_params = *policy_params;
+
+ /* if necessary, allocate memory to hold policer parameters */
+ dir = &policy_params->dir_params;
+ if (dir->type == DPA_IPSEC_POL_DIR_PARAMS_ACT &&
+ dir->in_action.type == DPA_CLS_TBL_ACTION_ENQ &&
+ dir->in_action.enq_params.policer_params) {
+ struct dpa_cls_tbl_policer_params *plcr = NULL;
+
+ plcr = kzalloc(sizeof(*plcr), GFP_KERNEL);
+ if (!plcr) {
+ log_err("Could not allocate memory for policer\n");
+ kfree(pol_entry);
+ return -ENOMEM;
+ }
+ memcpy(plcr, dir->in_action.enq_params.policer_params,
+ sizeof(*plcr));
+ pol_entry->pol_params.dir_params.in_action.
+ enq_params.policer_params = plcr;
+ }
+
+ if (policy_params->use_dscp)
+ size = sa->dscp_end - sa->dscp_start + 1;
+
+ /*
+ * allocate memory for entry id: a single value or an array in case
+ * of SA per DSCP
+ */
+ pol_entry->entry_id = kcalloc(size, sizeof(int), GFP_KERNEL);
+
+ /* add policy to the SA's policy list */
+ list_add(&pol_entry->node, &sa->policy_headlist);
+
+ *policy_entry = pol_entry;
+
+ return 0;
+}
+
+static inline int addr_match(struct dpa_offload_ip_address *addr1,
+ struct dpa_offload_ip_address *addr2)
+{
+ if (addr1->version != addr2->version)
+ return false;
+
+ switch (addr1->version) {
+ case DPA_IPSEC_ADDR_T_IPv4:
+ if (addr1->addr.ipv4.word != addr2->addr.ipv4.word)
+ return false;
+ break;
+ case DPA_IPSEC_ADDR_T_IPv6:
+ if (memcmp(&addr1->addr.ipv6.byte, &addr2->addr.ipv6.byte,
+ DPA_OFFLD_IPv6_ADDR_LEN_BYTES))
+ return false;
+ break;
+ default:
+ /*
+ * IP's version was checked for validity when policy was
+ * off-loaded so it can be invalid only if DPA IPsec component
+ * messed it up.
+ */
+ log_err("Invalid IP version\n");
+ BUG();
+ }
+
+ return true;
+}
+
+
+static int find_policy(struct dpa_ipsec_sa *sa,
+ struct dpa_ipsec_policy_params *pol,
+ struct dpa_ipsec_policy_entry **policy_entry)
+{
+ struct dpa_ipsec_policy_entry *pol_entry, *tmp;
+
+ BUG_ON(!sa);
+ BUG_ON(!pol);
+ BUG_ON(!policy_entry);
+
+ if (list_empty(&sa->policy_headlist)) {
+ log_err("Policy list is empty\n");
+ return -EDOM;
+ }
+
+ list_for_each_entry_safe(pol_entry, tmp, &sa->policy_headlist, node) {
+ struct dpa_ipsec_policy_params *cpol;
+ uint8_t cproto;
+
+ cpol = &pol_entry->pol_params;
+ cproto = cpol->protocol;
+
+ if (cpol->dest_prefix_len != pol->dest_prefix_len ||
+ cpol->src_prefix_len != pol->src_prefix_len ||
+ !addr_match(&cpol->dest_addr, &pol->dest_addr) ||
+ !addr_match(&cpol->src_addr, &pol->src_addr) ||
+ cpol->protocol != pol->protocol ||
+ cpol->masked_proto != pol->masked_proto ||
+ cpol->priority != pol->priority)
+ continue;
+
+ if (cproto == IPPROTO_UDP || cproto == IPPROTO_TCP ||
+ cproto == IPPROTO_SCTP)
+ if (cpol->l4.dest_port != pol->l4.dest_port ||
+ cpol->l4.dest_port_mask != pol->l4.dest_port_mask ||
+ cpol->l4.src_port != pol->l4.src_port ||
+ cpol->l4.src_port_mask != pol->l4.src_port_mask)
+ continue;
+
+ if (cproto == IPPROTO_ICMP || cproto == IPPROTO_ICMPV6) {
+ struct dpa_ipsec_icmp_params *c;
+ c = &cpol->icmp;
+ if (c->icmp_code != pol->icmp.icmp_code ||
+ c->icmp_code_mask != pol->icmp.icmp_code_mask ||
+ c->icmp_type != pol->icmp.icmp_type ||
+ c->icmp_type_mask != pol->icmp.icmp_type_mask)
+ continue;
+ }
+
+ /* found entry matching the input policy parameters */
+ *policy_entry = pol_entry;
+ return 0;
+ }
+
+ /* did not find the entry that matches the input policy parameters */
+ return -EDOM;
+}
+
+static inline int get_policy_count_for_sa(struct dpa_ipsec_sa *sa)
+{
+ struct dpa_ipsec_policy_entry *policy_entry, *tmp_policy_entry;
+ int pol_count = 0;
+
+ if (list_empty(&sa->policy_headlist)) {
+ pr_debug("Policy parameter list is empty\n");
+ return 0;
+ }
+
+
+ list_for_each_entry_safe(policy_entry, tmp_policy_entry,
+ &sa->policy_headlist, node)
+ pol_count++;
+
+ return pol_count;
+}
+
+static int copy_all_policies(struct dpa_ipsec_sa *sa,
+ struct dpa_ipsec_policy_params *policy_params,
+ int num_pol)
+{
+ struct dpa_ipsec_policy_entry *policy_entry, *tmp_policy_entry;
+ int pol_count = 0;
+
+ BUG_ON(!sa);
+ BUG_ON(!policy_params);
+
+ if (list_empty(&sa->policy_headlist)) {
+ log_err("Policy parameter list is empty\n");
+ return 0;
+ }
+
+ list_for_each_entry_safe(policy_entry, tmp_policy_entry,
+ &sa->policy_headlist, node) {
+ pol_count++;
+ if (pol_count > num_pol) {
+ log_err("Num policies in this SA greater than %d",
+ num_pol);
+ return -EAGAIN;
+ }
+
+ policy_params[pol_count - 1] = policy_entry->pol_params;
+ }
+
+ return 0;
+}
+
+static int remove_policy_from_sa_policy_list(struct dpa_ipsec_sa *sa,
+ struct dpa_ipsec_policy_entry
+ *policy_entry)
+{
+ struct dpa_ipsec_pol_dir_params *dir = NULL;
+
+ BUG_ON(!sa);
+ BUG_ON(!policy_entry);
+
+ if (list_empty(&sa->policy_headlist)) {
+ log_err("Policy parameter list is empty\n");
+ return -EINVAL;
+ }
+
+ /* unlink this policy from SA's list */
+ list_del(&policy_entry->node);
+
+ /* release memory used for holding policer parameters */
+ dir = &policy_entry->pol_params.dir_params;
+ if (dir->type == DPA_IPSEC_POL_DIR_PARAMS_ACT &&
+ dir->in_action.type == DPA_CLS_TBL_ACTION_ENQ &&
+ dir->in_action.enq_params.policer_params)
+ kfree(dir->in_action.enq_params.policer_params);
+
+ /* release memory used for holding policy entry id array*/
+ kfree(policy_entry->entry_id);
+ /* release memory used for holding policy general parameters */
+ kfree(policy_entry);
+
+ return 0;
+}
+
+static int remove_policy(struct dpa_ipsec_sa *sa,
+ struct dpa_ipsec_policy_entry *policy_entry)
+{
+ int err;
+
+ BUG_ON(!sa);
+ BUG_ON(!policy_entry);
+
+ if (sa_is_inbound(sa)) {
+ err = update_inbound_policy(sa, policy_entry, MNG_OP_REMOVE);
+ if (err < 0) {
+ log_err("Could not remove the inbound policy\n");
+ return err;
+ }
+
+ err = remove_policy_from_sa_policy_list(sa, policy_entry);
+ if (err < 0) {
+ log_err("Couldn't remove inbound policy from SA policy list\n");
+ return err;
+ }
+ } else { /* DPA_IPSEC_OUTBOUND */
+ err = update_outbound_policy(sa, policy_entry, MNG_OP_REMOVE);
+ if (err < 0) {
+ log_err("Could not remove the outbound policy\n");
+ return err;
+ }
+
+ err = remove_policy_from_sa_policy_list(sa, policy_entry);
+ if (err < 0) {
+ log_err("Could not remove outbound policy from SA policy list\n");
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static struct dpa_ipsec_sa *get_sa_from_sa_id(struct dpa_ipsec *dpa_ipsec,
+ int sa_id)
+{
+ struct dpa_ipsec_sa_mng *sa_mng;
+ struct dpa_ipsec_sa *sa = NULL;
+
+ BUG_ON(!dpa_ipsec);
+
+ sa_mng = &dpa_ipsec->sa_mng;
+
+ if (sa_id < dpa_ipsec->id * MAX_NUM_OF_SA ||
+ sa_id >= dpa_ipsec->id * MAX_NUM_OF_SA + sa_mng->max_num_sa) {
+ log_err("Invalid SA id %d provided\n", sa_id);
+ return NULL;
+ }
+
+ sa = &sa_mng->sa[sa_id_to_sa_index(sa_id)];
+
+ return sa;
+}
+
+static int check_sa_params(struct dpa_ipsec_sa_params *sa_params)
+{
+ uint16_t cipher_alg, auth_alg;
+ int err = 0;
+
+ /* sanity checks */
+ if (!sa_params) {
+ log_err("Invalid SA parameters handle\n");
+ return -EINVAL;
+ }
+
+ /*
+ * check crypto params:
+ * - an authentication key must always be provided
+ * - a cipher key must be provided if algorithm != NULL encryption
+ */
+
+ err = set_cipher_auth_alg(sa_params->crypto_params.alg_suite,
+ &cipher_alg, &auth_alg);
+ if (err < 0)
+ return err;
+
+ if (!sa_params->crypto_params.auth_key ||
+ sa_params->crypto_params.auth_key_len == 0) {
+ log_err("A valid authentication key must be provided\n");
+ return -EINVAL;
+ }
+
+ /* Check cipher_key only if the cipher algorithm isn't NULL encryption*/
+ if (cipher_alg != OP_PCL_IPSEC_NULL_ENC &&
+ (!sa_params->crypto_params.cipher_key ||
+ sa_params->crypto_params.cipher_key_len == 0)) {
+ log_err("A valid cipher key must be provided\n");
+ return -EINVAL;
+ }
+
+ if (sa_params->sa_dir == DPA_IPSEC_OUTBOUND) {
+ if (sa_params->sa_out_params.ip_hdr_size == 0 ||
+ !sa_params->sa_out_params.outer_ip_header) {
+ log_err("Transport mode is not currently supported. Specify a valid encapsulation header\n");
+ return -EINVAL;
+ }
+
+ if (sa_params->sa_out_params.outer_udp_header &&
+ sa_params->sa_out_params.ip_ver ==
+ DPA_IPSEC_ADDR_T_IPv6) {
+ log_err("NAT-T is not supported for IPV6 SAs\n");
+ return -EINVAL;
+ }
+ } else {
+ /* Inbound SA */
+ if (sa_params->sa_in_params.src_addr.version !=
+ sa_params->sa_in_params.dest_addr.version) {
+ log_err("Source and destination IP address must be of same type\n");
+ return -EINVAL;
+ }
+
+ if (sa_params->sa_in_params.use_udp_encap &&
+ sa_params->sa_in_params.src_addr.version ==
+ DPA_IPSEC_ADDR_T_IPv6) {
+ log_err("NAT-T is not supported for IPV6 SAs\n");
+ return -EINVAL;
+ }
+ }
+
+ /* check buffer pool ID validity */
+ if (sa_params->sa_bpid > MAX_BUFFER_POOL_ID) {
+ log_err("Invalid SA buffer pool ID.\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int get_new_sa(struct dpa_ipsec *dpa_ipsec,
+ struct dpa_ipsec_sa **new_sa,
+ uint32_t *sa_id)
+{
+ struct dpa_ipsec_sa *sa;
+ uint32_t id;
+ int i;
+
+ BUG_ON(!dpa_ipsec);
+
+ BUG_ON(!new_sa);
+ *new_sa = NULL;
+
+ BUG_ON(!sa_id);
+
+ /* Acquire DPA IPSec instance lock */
+ mutex_lock(&dpa_ipsec->lock);
+
+ /* Get an id for new SA */
+ if (cq_get_4bytes(dpa_ipsec->sa_mng.sa_id_cq, &id) < 0) {
+ log_err("No more unused SA handles\n");
+ /* Release DPA IPSec instance lock */
+ mutex_unlock(&dpa_ipsec->lock);
+ return -EDOM;
+ }
+
+ for (i = 0; i < dpa_ipsec->sa_mng.max_num_sa; i++)
+ if (dpa_ipsec->used_sa_ids[i] == DPA_OFFLD_INVALID_OBJECT_ID)
+ break;
+ if (i == dpa_ipsec->sa_mng.max_num_sa) {
+ log_err("No more unused SAs ID holders");
+ cq_put_4bytes(dpa_ipsec->sa_mng.sa_id_cq, id);
+ /* Release DPA IPSec instance lock */
+ mutex_unlock(&dpa_ipsec->lock);
+ return -EDOM;
+ }
+
+ /* Acquire a preallocated SA structure */
+ sa = &dpa_ipsec->sa_mng.sa[sa_id_to_sa_index(id)];
+ sa->id = id;
+ sa->used_sa_index = i;
+ dpa_ipsec->used_sa_ids[sa->used_sa_index] = sa->id;
+ dpa_ipsec->num_used_sas++;
+
+ /* Release DPA IPSec instance lock */
+ mutex_unlock(&dpa_ipsec->lock);
+
+ *sa_id = id;
+ *new_sa = sa;
+
+ return 0;
+}
+
+/*
+ * Expects that SA lock is acquired for this SA structure and parent/child SA.
+ * Always acquire parent SA lock before child SA lock.
+ */
+static int put_sa(struct dpa_ipsec_sa *sa)
+{
+ struct dpa_ipsec *dpa_ipsec;
+ struct dpa_ipsec_sa_mng *sa_mng;
+ int err;
+
+ BUG_ON(!sa);
+
+ dpa_ipsec = sa->dpa_ipsec;
+ BUG_ON(!dpa_ipsec);
+
+ if (sa->used_sa_index < 0) {
+ pr_crit("Invalid used_sa_index for SA with id %d\n", sa->id);
+ return -EFAULT;
+ }
+
+ /* Acquire DPA IPSec instance lock */
+ mutex_lock(&dpa_ipsec->lock);
+ sa_mng = &dpa_ipsec->sa_mng;
+
+ /*
+ * AV's TODO: create a cleaning function for preallocated SA structure
+ * and call here that function
+ */
+
+ /* Release the SA id in the SA IDs circular queue */
+ err = cq_put_4bytes(sa_mng->sa_id_cq, sa->id);
+ if (err < 0) {
+ log_err("Could not release the sa id %d\n", sa->id);
+ /* Release DPA IPSec instance lock */
+ mutex_unlock(&dpa_ipsec->lock);
+ return -EDOM;
+ }
+
+ /* Release the flow ID - only for inbound SAs */
+ if (sa_is_inbound(sa) && !ignore_post_ipsec_action(dpa_ipsec) &&
+ sa->inbound_flowid != INVALID_INB_FLOW_ID && !sa_is_parent(sa)) {
+ err = put_inbound_flowid(dpa_ipsec, sa->inbound_flowid);
+ if (err < 0) {
+ log_err("Could not put flow id in circular queue.\n");
+ mutex_unlock(&dpa_ipsec->lock);
+ return err;
+ }
+ sa->inbound_flowid = INVALID_INB_FLOW_ID;
+ }
+
+ sa->child_sa = NULL;
+
+ /* Mark as free index in used SA IDs vector of this DPA IPSEC instance*/
+ dpa_ipsec->used_sa_ids[sa->used_sa_index] = DPA_OFFLD_INVALID_OBJECT_ID;
+ dpa_ipsec->num_used_sas--;
+ sa->used_sa_index = -1;
+
+ /* Release DPA IPSec instance lock */
+ mutex_unlock(&dpa_ipsec->lock);
+
+ return 0;
+}
+
+static int rollback_create_sa(struct dpa_ipsec_sa *sa)
+{
+ struct dpa_ipsec *dpa_ipsec;
+ int err_rb;
+
+ BUG_ON(!sa);
+ dpa_ipsec = sa->dpa_ipsec;
+ BUG_ON(!dpa_ipsec);
+
+ if (sa_is_outbound(sa))
+ goto remove_fq_pair;
+
+ /* Inbound SA */
+ if (sa->inbound_hash_entry != DPA_OFFLD_INVALID_OBJECT_ID) {
+ err_rb = update_pre_sec_inbound_table(sa, MNG_OP_REMOVE);
+ if (err_rb < 0) {
+ log_err("Couln't remove SA lookup table entry\n");
+ return err_rb;
+ }
+ }
+
+ if (sa->ipsec_hmd != DPA_OFFLD_DESC_NONE) {
+ struct hmd_entry hmd_entry;
+ hmd_entry.hmd = sa->ipsec_hmd;
+ hmd_entry.hmd_special_op = true;
+ err_rb = destroy_recycle_manip(sa, &hmd_entry);
+ if (err_rb < 0) {
+ log_err("Could not delete manip object!\n");
+ return err_rb;
+ }
+ sa->ipsec_hmd = DPA_OFFLD_DESC_NONE;
+ }
+
+ if (dpa_ipsec->config.post_sec_in_params.do_pol_check == true &&
+ sa->valid_flowid_entry) {
+ err_rb = remove_inbound_flow_id_classif(sa);
+ if (err_rb < 0) {
+ log_err("Couldn't remove post decrypt tbl entry\n");
+ return err_rb;
+ }
+ }
+
+remove_fq_pair:
+ err_rb = remove_sa_fq_pair(sa);
+ if (err_rb < 0) {
+ log_err("Could not remove SA FQs.\n");
+ return err_rb;
+ }
+
+ /* Release the SA */
+ err_rb = put_sa(sa);
+
+ return err_rb;
+}
+
+static int rollback_rekeying_sa(struct dpa_ipsec_sa *sa)
+{
+ struct dpa_ipsec *dpa_ipsec;
+ int err_rb;
+
+ BUG_ON(!sa);
+ dpa_ipsec = sa->dpa_ipsec;
+ BUG_ON(!dpa_ipsec);
+
+ if (sa_is_outbound(sa))
+ goto remove_fq_pair;
+
+ /* Inbound SA */
+ if (sa->inbound_hash_entry != DPA_OFFLD_INVALID_OBJECT_ID) {
+ err_rb = update_pre_sec_inbound_table(sa, MNG_OP_REMOVE);
+ if (err_rb < 0) {
+ log_err("Couln't remove SA lookup table entry\n");
+ return err_rb;
+ }
+ }
+
+ if (sa->ipsec_hmd != DPA_OFFLD_DESC_NONE) {
+ struct hmd_entry hmd_entry;
+ hmd_entry.hmd = sa->ipsec_hmd;
+ hmd_entry.hmd_special_op = true;
+ err_rb = destroy_recycle_manip(sa, &hmd_entry);
+ if (err_rb < 0) {
+ log_err("Could not delete manip object!\n");
+ return err_rb;
+ }
+ sa->ipsec_hmd = DPA_OFFLD_DESC_NONE;
+ }
+
+remove_fq_pair:
+ err_rb = remove_sa_fq_pair(sa);
+ if (err_rb < 0) {
+ log_err("Could not remove SA FQs.\n");
+ return err_rb;
+ }
+
+ err_rb = put_sa(sa);
+
+ return err_rb;
+}
+
+/* Find unused global DPA IPsec instance holder */
+int find_unused_gbl_dpa_ipsec(void)
+{
+ int i, instance_id = -1;
+
+ spin_lock(&gbl_dpa_ipsec_lock);
+
+ for (i = 0; i < MAX_DPA_IPSEC_INSTANCES; i++)
+ if (!gbl_dpa_ipsec[i]) {
+ instance_id = i;
+ /* mark this as used */
+ gbl_dpa_ipsec[i] = (struct dpa_ipsec *)i;
+ break;
+ }
+
+ spin_unlock(&gbl_dpa_ipsec_lock);
+
+ return instance_id;
+}
+
+/* Mark unused global DPA IPsec instance holder */
+static void mark_unused_gbl_dpa_ipsec(int instance)
+{
+ BUG_ON(instance < 0 || instance >= MAX_DPA_IPSEC_INSTANCES);
+
+ spin_lock(&gbl_dpa_ipsec_lock);
+
+ gbl_dpa_ipsec[instance] = NULL;
+
+ spin_unlock(&gbl_dpa_ipsec_lock);
+}
+
+int dpa_ipsec_init(const struct dpa_ipsec_params *params, int *dpa_ipsec_id)
+{
+ struct dpa_ipsec *dpa_ipsec = NULL;
+ uint32_t max_num_sa;
+ int err = 0, instance_id;
+
+ /* make sure all user params are OK and init can start */
+ err = check_ipsec_params(params);
+ if (err < 0)
+ return err;
+
+ instance_id = find_unused_gbl_dpa_ipsec();
+ if (instance_id < 0) {
+ log_err("The limit of active DPA IPsec instances has been reached\n");
+ return -EDOM;
+ }
+
+ /* alloc control block */
+ dpa_ipsec = kzalloc(sizeof(*dpa_ipsec), GFP_KERNEL);
+ if (!dpa_ipsec) {
+ log_err("Could not allocate memory for control block.\n");
+ mark_unused_gbl_dpa_ipsec(instance_id);
+ return -ENOMEM;
+ }
+
+ /* Set instance reference count to 1 */
+ atomic_set(&dpa_ipsec->ref, 1);
+
+ /* store the control block */
+ spin_lock(&gbl_dpa_ipsec_lock);
+ gbl_dpa_ipsec[instance_id] = dpa_ipsec;
+ spin_unlock(&gbl_dpa_ipsec_lock);
+ dpa_ipsec->id = instance_id;
+
+ /* Initialize DPA IPSec instance lock */
+ mutex_init(&dpa_ipsec->lock);
+
+ /* store parameters */
+ store_ipsec_params(dpa_ipsec, params);
+
+ /* init SA manager */
+ err = init_sa_manager(dpa_ipsec);
+ if (err < 0) {
+ free_resources(instance_id);
+ return err;
+ }
+
+ /* Init used sa vector */
+ max_num_sa = dpa_ipsec->sa_mng.max_num_sa;
+ dpa_ipsec->used_sa_ids = kmalloc(max_num_sa * sizeof(u32), GFP_KERNEL);
+ if (!dpa_ipsec->used_sa_ids) {
+ log_err("No more memory for used sa id's vector ");
+ free_resources(instance_id);
+ return -ENOMEM;
+ }
+ memset(dpa_ipsec->used_sa_ids, DPA_OFFLD_INVALID_OBJECT_ID,
+ max_num_sa * sizeof(uint32_t));
+ dpa_ipsec->num_used_sas = 0;
+
+ /* retrieve and store SEC ERA information */
+ err = get_sec_info(dpa_ipsec);
+ if (err < 0) {
+ free_resources(instance_id);
+ return err;
+ }
+
+ /* Give to the user the valid DPA IPsec instance ID */
+ *dpa_ipsec_id = instance_id;
+ atomic_set(&dpa_ipsec->valid, 1);
+
+ return 0;
+}
+EXPORT_SYMBOL(dpa_ipsec_init);
+
+int dpa_ipsec_free(int dpa_ipsec_id)
+{
+ struct dpa_ipsec *instance;
+ struct dpa_ipsec_sa *sa;
+ int i, sa_id;
+ DEFINE_WAIT(wait);
+
+ instance = get_instance(dpa_ipsec_id);
+ if (PTR_ERR(instance) == -EPERM || PTR_ERR(instance) == -EINVAL)
+ return PTR_ERR(instance);
+
+ /* Invalidate instance */
+ atomic_set(&instance->valid, 0);
+
+ put_instance(instance);
+
+ add_wait_queue(&wait_queue, &wait);
+ while (1) {
+ prepare_to_wait(&wait_queue, &wait, TASK_UNINTERRUPTIBLE);
+ /* Avoid sleeping if condition became true */
+ if (atomic_dec_and_test(&instance->ref))
+ break;
+ schedule();
+ }
+ finish_wait(&wait_queue, &wait);
+
+ /* destroy all SAs offloaded in this DPA IPsec instance */
+ flush_delayed_work(&instance->sa_mng.sa_rekeying_work);
+ for (i = 0; i < instance->sa_mng.max_num_sa; i++) {
+ sa_id = instance->used_sa_ids[i];
+ if (sa_id != DPA_OFFLD_INVALID_OBJECT_ID) {
+ sa = get_sa_from_sa_id(instance, sa_id);
+ if (sa_is_inbound(sa)) {
+ if (sa_is_child(sa))
+ remove_inbound_sa(sa->parent_sa);
+ remove_inbound_sa(sa);
+ } /* outbound */
+ else {
+ if (sa_is_child(sa))
+ remove_outbound_sa(sa->parent_sa);
+ remove_outbound_sa(sa);
+ }
+ }
+ }
+
+ free_resources(dpa_ipsec_id);
+
+ mark_unused_gbl_dpa_ipsec(instance->id);
+
+ return 0;
+}
+EXPORT_SYMBOL(dpa_ipsec_free);
+
+int dpa_ipsec_create_sa(int dpa_ipsec_id,
+ struct dpa_ipsec_sa_params *sa_params, int *sa_id)
+{
+ struct dpa_ipsec *dpa_ipsec;
+ struct dpa_ipsec_sa *sa;
+ uint32_t id;
+ int err = 0, err_rb = 0;
+
+ if (!valid_instance_id(dpa_ipsec_id))
+ return -EINVAL;
+
+ if (!sa_id) {
+ log_err("Invalid SA ID holder\n");
+ return -EINVAL;
+ }
+ *sa_id = DPA_OFFLD_INVALID_OBJECT_ID;
+
+ /* Get the DPA IPsec instance */
+ dpa_ipsec = get_instance(dpa_ipsec_id);
+ err = check_instance(dpa_ipsec);
+ if (unlikely(err < 0))
+ return err;
+
+ err = check_sa_params(sa_params);
+ if (err < 0) {
+ put_instance(dpa_ipsec);
+ return err;
+ }
+
+ err = get_new_sa(dpa_ipsec, &sa, &id);
+ if (err < 0) {
+ log_err("Failed retrieving a preallocated SA\n");
+ put_instance(dpa_ipsec);
+ return err;
+ }
+
+ /* Update internal SA structure. First acquire its lock */
+ mutex_lock(&sa->lock);
+
+ sa->sa_dir = sa_params->sa_dir;
+ sa->dpa_ipsec = dpa_ipsec;
+ sa->parent_sa = NULL;
+ sa->child_sa = NULL;
+ sa->sa_rekeying_node.next = LIST_POISON1;
+ sa->sa_rekeying_node.prev = LIST_POISON2;
+ sa->read_seq_in_progress = false;
+
+ /* Copy SA params into the internal SA structure */
+ if (sa_is_outbound(sa))
+ err = copy_sa_params_to_out_sa(sa, sa_params);
+ else /* DPA_IPSEC_INBOUND */
+ err = copy_sa_params_to_in_sa(sa, sa_params, FALSE);
+
+ if (err < 0) {
+ log_err("Could not copy SA parameters into SA\n");
+ goto create_sa_err;
+ }
+
+ /* Initialize the SA Manip handle to an invalid value */
+ sa->ipsec_hmd = DPA_OFFLD_DESC_NONE;
+
+ /* Initialize the IPSec Manip. object (if required) for inbound SAs */
+ if (sa_is_inbound(sa)) {
+ if (sa->dpa_ipsec->config.max_sa_manip_ops == 0)
+ err = create_ipsec_manip(sa, DPA_OFFLD_DESC_NONE,
+ &sa->ipsec_hmd);
+ else
+ err = update_ipsec_manip(sa, DPA_OFFLD_DESC_NONE,
+ &sa->ipsec_hmd);
+ if (err < 0) {
+ log_err("Could not create Manip object for in SA!\n");
+ goto create_sa_err;
+ }
+ }
+
+ /* Generate the split key from the normal auth key */
+ err = generate_split_key(&sa->auth_data);
+ if (err < 0)
+ goto create_sa_err;
+
+ /* Call internal function to create SEC FQ according to SA parameters */
+ err = create_sa_fq_pair(sa, FALSE, FALSE);
+ if (err < 0) {
+ log_err("Could not create SEC frame queues\n");
+ goto create_sa_err;
+ }
+
+ if (sa_is_inbound(sa)) {
+ err = update_pre_sec_inbound_table(sa, MNG_OP_ADD);
+ if (err < 0) {
+ log_err("Could not update PCD entry\n");
+ goto create_sa_err;
+ }
+
+ if (dpa_ipsec->config.post_sec_in_params.do_pol_check) {
+ int inbpol_td;
+ struct dpa_cls_tbl_action action;
+
+ err = get_free_inbpol_tbl(dpa_ipsec, &inbpol_td);
+ if (err < 0) {
+ log_err("Could not get a free EM table\n");
+ goto create_sa_err;
+ }
+ sa->em_inpol_td = inbpol_td;
+
+ /*
+ * Link Exact Match table with the index table on
+ * inbound_flowid
+ */
+ memset(&action, 0, sizeof(action));
+ action.type = DPA_CLS_TBL_ACTION_NEXT_TABLE;
+ action.next_table_params.next_td = inbpol_td;
+ action.next_table_params.hmd = DPA_OFFLD_DESC_NONE;
+ action.enable_statistics = FALSE;
+ err = set_flow_id_action(sa, &action);
+ if (err < 0) {
+ log_err("Can't link EM table with index table\n");
+ goto create_sa_err;
+ }
+
+ err = dpa_classif_table_modify_miss_action(inbpol_td,
+ &sa->policy_miss_action);
+ if (err < 0) {
+ log_err("Can't set policy miss action\n");
+ goto create_sa_err;
+ }
+ } else {
+ if (ignore_post_ipsec_action(sa->dpa_ipsec))
+ goto sa_done;
+
+ /* Set the post decryption default action */
+ err = set_flow_id_action(sa, &sa->def_sa_action);
+ if (err < 0) {
+ log_err("Could not set default action for post decryption\n");
+ goto create_sa_err;
+ }
+ }
+ }
+
+ /* SA done OK. Return the SA id */
+sa_done:
+ *sa_id = id;
+
+ /* Unlock the SA structure */
+ mutex_unlock(&sa->lock);
+
+ /* Release the DPA IPsec instance */
+ put_instance(dpa_ipsec);
+
+ return 0;
+
+ /* Something went wrong. Begin roll-back */
+ create_sa_err:
+
+ /* A invalid SA ID is returned if roll-back succeeds and the actual
+ * reserved SA ID if it fails. The SA ID can be used to try again to
+ * free resources by calling dpa_ipsec_remove_sa
+ */
+ err_rb = rollback_create_sa(sa);
+ if (err_rb < 0)
+ *sa_id = id;
+
+ /* Unlock the SA structure */
+ mutex_unlock(&sa->lock);
+
+ /* Release the DPA IPsec instance */
+ put_instance(dpa_ipsec);
+
+ return err;
+}
+EXPORT_SYMBOL(dpa_ipsec_create_sa);
+
+/*
+ * Expects that locks are acquired for this SA and its child if any.
+ * Expects that no child SA is passed to it
+ *
+ * Function description:
+ * Steps done for a parent SA:
+ * 1. Remove the PCD entry that makes traffic to go to SEC
+ * 2. Wait until SEC consumes the frames in the TO_SEC queue of this SA
+ * 3. Schedule the TO SEC FQ of the child SA even if no traffic arrived on it
+ * 4. Inherit parent SA's inbound post decryption classification
+ * 5. If policy verification is enabled inherit parent SA's policies.
+ * 6. Remove the child SA for the rekeying list
+ * 7. Remove the parent SA's TO_SEC FQ
+ * 8. Free all memory used for this SA i.e recycle this SA
+ *
+ * Steps done for a single SA:
+ * 1. Remove the PCD entries that make traffic to go to SEC
+ * 2. Remove TO_SEC FQ and FROM_SEC FQ
+ * 2.1. Wait until SEC consumes the frames in the TO_SEC queue of this SA
+ * 2.2. Wait until FROM_SEC queue gets empty, frames are distributed by the
+ * post SEC offline port according to its PCD entries
+ * 3. If policy verification is enabled, flush SA policies.
+ * 4. Remove the index entry from the post SEC offline port index table
+ * 5. Free all memory used for this SA i.e recycle this SA
+ */
+static int remove_inbound_sa(struct dpa_ipsec_sa *sa)
+{
+ struct dpa_ipsec_sa *child_sa;
+ int err, timeout = WAIT4_FQ_EMPTY_TIMEOUT;
+
+ if (sa_is_parent(sa)) {
+ child_sa = sa->child_sa;
+ /* Remove PCD entry that makes traffic go to SEC */
+ if (sa->inbound_hash_entry != DPA_OFFLD_INVALID_OBJECT_ID) {
+ err = remove_inbound_hash_entry(sa);
+ if (err == -ENOTRECOVERABLE)
+ return err;
+ }
+
+ /* destroy SA manip */
+ if (sa->ipsec_hmd != DPA_OFFLD_DESC_NONE) {
+ struct hmd_entry hmd_entry;
+ hmd_entry.hmd = sa->ipsec_hmd;
+ hmd_entry.hmd_special_op = true;
+ err = destroy_recycle_manip(sa, &hmd_entry);
+ if (err < 0) {
+ log_err("Could not delete manip object!\n");
+ return err;
+ }
+ sa->ipsec_hmd = DPA_OFFLD_DESC_NONE;
+ }
+
+ err = wait_until_fq_empty(sa->to_sec_fq, timeout);
+ if (err < 0) {
+ log_err("Waiting old SA's TO SEC FQ to get empty\n");
+ return -ETIME;
+ }
+
+ /* schedule child SA */
+ err = schedule_sa(child_sa);
+ if (unlikely(err < 0)) {
+ log_err("Scheduling child SA %d failed\n",
+ child_sa->id);
+ return -EIO;
+ }
+
+ /* Update the child SA with parent SA's inbound indx entry */
+ child_sa->valid_flowid_entry = sa->valid_flowid_entry;
+
+ /* Inherit parent SA's policy list and then set it empty */
+ if (sa->dpa_ipsec->config.post_sec_in_params.do_pol_check)
+ list_splice_init(&sa->policy_headlist,
+ &child_sa->policy_headlist);
+
+ /* Acquire protective lock for the SA rekeying list */
+ mutex_lock(&sa->dpa_ipsec->sa_mng.sa_rekeying_headlist_lock);
+
+ child_sa->parent_sa = NULL;
+
+ /* Remove the child SA from rekeying list */
+ if (child_sa->sa_rekeying_node.next != LIST_POISON1 &&
+ child_sa->sa_rekeying_node.prev != LIST_POISON2)
+ list_del(&child_sa->sa_rekeying_node);
+
+ /* Invalidate the FROM SEC FQ of parent SA */
+ memset(sa->from_sec_fq, 0, sizeof(struct qman_fq));
+ sa->from_sec_fq->fqid = 0;
+
+ /* Release the list lock so other threads may use it */
+ mutex_unlock(&sa->dpa_ipsec->sa_mng.sa_rekeying_headlist_lock);
+
+ /* Call rekeying callback to inform upper layer that rekeying
+ * process was finished for this SA and is ready for use */
+ if (child_sa->rekey_event_cb)
+ child_sa->rekey_event_cb(0, child_sa->id, 0);
+
+ /* Now free the parent SA structure and all its resources */
+ err = remove_sa_sec_fq(sa, sa->to_sec_fq);
+ if (err < 0) {
+ log_err("Couln't remove SA %d TO SEC FQ\n", sa->id);
+ return -EUCLEAN;
+ }
+
+ /* Recycle parent SA memory */
+ err = put_sa(sa);
+ if (unlikely(err < 0)) {
+ log_err("Could not recycle parent SA.\n");
+ return -EDQUOT;
+ }
+
+ return 0;
+ }
+
+ BUG_ON(sa_is_child(sa));
+
+ /* SA is single i.e has no child and can't be child for other SA */
+
+ /* Remove PCD entry that makes traffic go to SEC entry is valid */
+ if (sa->inbound_hash_entry != DPA_OFFLD_INVALID_OBJECT_ID) {
+ err = remove_inbound_hash_entry(sa);
+ if (err == -ENOTRECOVERABLE)
+ return err;
+ }
+
+ /* destroy SA manip */
+ if (sa->ipsec_hmd != DPA_OFFLD_DESC_NONE) {
+ struct hmd_entry hmd_entry;
+ hmd_entry.hmd = sa->ipsec_hmd;
+ hmd_entry.hmd_special_op = true;
+ err = destroy_recycle_manip(sa, &hmd_entry);
+ if (err < 0) {
+ log_err("Could not delete manip object!\n");
+ return err;
+ }
+ sa->ipsec_hmd = DPA_OFFLD_DESC_NONE;
+ }
+
+ /* Destroy the TO_SEC and FROM_SEC queues */
+ err = remove_sa_fq_pair(sa);
+ if (err != 0) {
+ log_err("Could not remove the SEC frame queues\n");
+ return err;
+ }
+
+ /* Flush policy if policy check is enabled */
+ if (sa->dpa_ipsec->config.post_sec_in_params.do_pol_check) {
+ err = sa_flush_policies(sa);
+ if (err < 0) {
+ log_err("Could not flush inbound policies");
+ return err;
+ }
+ }
+
+ /* Remove the flow id classification after decryption */
+ if (!ignore_post_ipsec_action(sa->dpa_ipsec) &&
+ sa->valid_flowid_entry) {
+ err = remove_inbound_flow_id_classif(sa);
+ if (err < 0)
+ return err;
+ }
+
+ /* Free policer pointer */
+ if (sa->def_sa_action.type == DPA_CLS_TBL_ACTION_ENQ &&
+ sa->def_sa_action.enq_params.policer_params)
+ kfree(sa->def_sa_action.enq_params.policer_params);
+
+ /* Mark SA as free */
+ err = put_sa(sa);
+ if (err < 0) {
+ log_err("Could not recycle the sa with id %d\n", sa->id);
+ return err;
+ }
+
+ return 0;
+}
+
+/*
+ * Expects that locks are acquired for this SA and its child if any.
+ * Expects that no child SA is passed to it
+ *
+ * Function description:
+ * Steps done for a parent SA:
+ * 1. Call the sa_rekeying_outbound function which is going to:
+ * a. wait until TO SEC FQ is empty or timeout
+ * b. schedule the child TO SEC FQ
+ * c. remove the parent TO SEC FQ
+ * d. free all memory used for this SA i.e recycle this SA
+ * 2. In case error code is telling that child SA is ready to use, i.e
+ * sa_rekeying_outbound returned 0, -EUCLEAN, -EDQUOT:
+ * a. lock SA rekeying list
+ * b. set as single the parent SA and child SA i.e parent SA has no child
+ * and child SA has no parent
+ * c. remove the child SA from the rekeying list, rekeying was complete
+ * d. invalidate parent SA's TO SEC FQ
+ * e. unlock SA rekeying list
+ * f. if child SA has a valid callback trigger this call to inform upper
+ * layer that this SA was rekeyed successfully.
+ *
+ * Steps done for a single SA:
+ * 1. Flush SA policies i.e remove the PCD entries that direct traffic to SEC
+ * 2. Remove TO_SEC FQ and FROM_SEC FQ
+ * 2.1. Wait until SEC consumes the frames in the TO_SEC queue of this SA
+ * 2.2. Wait until FROM_SEC queue gets empty, frames are distributed by the
+ * post SEC offline port according to its PCD entries
+ * 3. Free all memory used for this SA i.e recycle this SA
+ */
+static int remove_outbound_sa(struct dpa_ipsec_sa *sa)
+{
+ struct dpa_ipsec_sa *child_sa;
+ int err;
+
+ if (sa_is_parent(sa)) {
+ struct dpa_ipsec_sa_mng *sa_mng;
+
+ BUG_ON(!sa->dpa_ipsec);
+ sa_mng = &sa->dpa_ipsec->sa_mng;
+
+ child_sa = sa->child_sa;
+
+ err = sa_rekeying_outbound(child_sa);
+
+ /* Remove child SA from rekeying list if processing was OK */
+ if (err == 0 || err == -EUCLEAN || err == -EDQUOT) {
+ /* Acquire protective lock for the SA rekeying list */
+ mutex_lock(&sa_mng->sa_rekeying_headlist_lock);
+
+ sa->child_sa = NULL;
+ child_sa->parent_sa = NULL;
+
+ /* Remove the child SA from rekeying list */
+ list_del(&child_sa->sa_rekeying_node);
+
+ /* Invalidate the FROM SEC FQ of parent SA */
+ memset(sa->from_sec_fq, 0, sizeof(struct qman_fq));
+ sa->from_sec_fq->fqid = 0;
+
+ /* Release the list lock so other threads may use it */
+ mutex_unlock(&sa_mng->sa_rekeying_headlist_lock);
+
+ /*
+ * Call rekeying callback to inform upper layer that
+ * rekeying process was finished for this SA and is
+ * ready for used
+ */
+ if (child_sa->rekey_event_cb)
+ child_sa->rekey_event_cb(0, child_sa->id, 0);
+ }
+
+ return err;
+ }
+
+ BUG_ON(sa_is_child(sa));
+
+ /* SA is single i.e has no child and can't be child for other SA */
+
+ /* Flush policies i.e remove PCD entries that direct traffic to SEC */
+ err = sa_flush_policies(sa);
+ if (err < 0) {
+ log_err("Could not flush outbound policies\n");
+ return err;
+ }
+
+ /* destroy SA manip, if one was initialized */
+ if (sa->ipsec_hmd != DPA_OFFLD_DESC_NONE) {
+ struct hmd_entry hmd_entry;
+ hmd_entry.hmd = sa->ipsec_hmd;
+ hmd_entry.hmd_special_op = true;
+ err = destroy_recycle_manip(sa, &hmd_entry);
+ if (err < 0) {
+ log_err("Couldn't delete SA manip\n");
+ return err;
+ }
+ sa->ipsec_hmd = DPA_OFFLD_DESC_NONE;
+ }
+
+ /* Destroy the TO_SEC and FROM_SEC queues */
+ err = remove_sa_fq_pair(sa);
+ if (err < 0) {
+ log_err("Could not remove the SEC frame queues\n");
+ return err;
+ }
+
+ /* Mark SA as free */
+ err = put_sa(sa);
+ if (err < 0) {
+ log_err("Could not recycle the SA id %d\n", sa->id);
+ return err;
+ }
+
+ return 0;
+}
+
+/*
+ * Function description:
+ *
+ * SA is single (has no child SA and its not a child for other SA):
+ * - acquire lock for SA, return -EAGAIN if lock is contended.
+ * SA is child:
+ * - return error code -EINPROGRESS since this SA is in rekeying process
+ * - to remove this SA first must be removed its parent SA using API or the
+ * rekeying process finished successfully for this SA
+ * SA is parent:
+ * - always acquire parent SA lock before child SA lock
+ * - acquire lock for SA, return -EAGAIN if lock is contended
+ * - acquire lock for SA's child, return -EAGAIN if lock is contended
+ * - call remove_inbound_sa or remove_outbound_sa depending on the SA
+ * direction, which will do the work required and call the rekeying
+ * callback to inform upper layer about the child SA success.
+ * Returned code:
+ * a. -ENOTRECOVERABLE if failed to removed the
+ * PCD entry of the inbound SA that makes traffic go to SEC.
+ * recommended action: recall this function for several times
+ * and if the returned code is the same, then reboot the system
+ * b. -ETIME if the parent SA's TO SEC FQ is not yet empty
+ * c. -EIO if failed to schedule the child's TO SEC FQ. Unlikely.
+ * d. -EUCLEAN if parent SA needs cleaning (its TO SEC FQ couldn't
+ * be removed)
+ * e. -EDQUOT if failed to recycle the parent SA.
+ * In case of -EUCLEAN and -EDQUOT the recommended action is to call
+ * dpa_ipsec_remove with the parent SA id. Child SA id is ready to work.
+ * - release SA's child lock
+ * - release SA lock
+ */
+int dpa_ipsec_remove_sa(int sa_id)
+{
+ struct dpa_ipsec_sa *sa, *child_sa = NULL;
+ struct dpa_ipsec *dpa_ipsec;
+ int ret = 0;
+
+ if (!valid_sa_id(sa_id))
+ return -EINVAL;
+
+ dpa_ipsec = get_instance(sa_id_to_instance_id(sa_id));
+ ret = check_instance(dpa_ipsec);
+ if (unlikely(ret < 0))
+ return ret;
+
+ sa = get_sa_from_sa_id(dpa_ipsec, sa_id);
+ if (!sa) {
+ log_err("Invalid SA handle for SA id %d\n", sa_id);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* Always acquire parent lock before child's lock */
+ ret = mutex_trylock(&sa->lock);
+ if (ret == 0) {
+ log_err("Failed to acquire lock for SA %d\n", sa->id);
+ ret = -EAGAIN;
+ goto out;
+ }
+
+ /* Abort if this SA is not being used */
+ if (!sa_in_use(sa)) {
+ log_err("SA with id %d is not in use\n", sa_id);
+ mutex_unlock(&sa->lock);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (sa_is_child(sa)) {
+ log_err("This SA %d is a child in rekeying process\n", sa_id);
+ mutex_unlock(&sa->lock);
+ ret = -EINPROGRESS;
+ goto out;
+ }
+
+ /* SA is parent? If so acquire its child's lock */
+ if (sa_is_parent(sa)) {
+ child_sa = sa->child_sa;
+ ret = mutex_trylock(&child_sa->lock);
+ if (ret == 0) {
+ mutex_unlock(&sa->lock);
+ ret = -EAGAIN;
+ goto out;
+ }
+ }
+
+ if (sa_is_inbound(sa))
+ ret = remove_inbound_sa(sa);
+ else
+ ret = remove_outbound_sa(sa);
+
+ /* Release child's lock first */
+ if (child_sa)
+ mutex_unlock(&child_sa->lock);
+
+ /* Release parent lock */
+ mutex_unlock(&sa->lock);
+
+out:
+ put_instance(dpa_ipsec);
+
+ return ret;
+}
+EXPORT_SYMBOL(dpa_ipsec_remove_sa);
+
+int dpa_ipsec_sa_add_policy(int sa_id,
+ struct dpa_ipsec_policy_params *policy_params)
+{
+ struct dpa_ipsec_policy_entry *policy_entry;
+ struct dpa_ipsec *dpa_ipsec;
+ struct dpa_ipsec_sa *sa;
+ int ret = 0;
+
+ if (!policy_params) {
+ log_err("Invalid policy params handle\n");
+ return -EINVAL;
+ }
+
+ if (!valid_sa_id(sa_id))
+ return -EINVAL;
+
+ dpa_ipsec = get_instance(sa_id_to_instance_id(sa_id));
+ ret = check_instance(dpa_ipsec);
+ if (unlikely(ret < 0))
+ return ret;
+
+ sa = get_sa_from_sa_id(dpa_ipsec, sa_id);
+ if (!sa) {
+ log_err("Invalid SA handle for SA id %d\n", sa_id);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = mutex_trylock(&sa->lock);
+ if (ret == 0) {
+ log_err("Failed to acquire lock for SA %d\n", sa->id);
+ ret = -EAGAIN;
+ goto out;
+ }
+
+ /* Abort if this SA is not being used */
+ if (!sa_in_use(sa)) {
+ log_err("SA with id %d is not in use\n", sa_id);
+ mutex_unlock(&sa->lock);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ BUG_ON(!sa->dpa_ipsec);
+ mutex_lock(&sa->dpa_ipsec->lock);
+ if (sa_is_inbound(sa) &&
+ !sa->dpa_ipsec->config.post_sec_in_params.do_pol_check) {
+ log_err("Inbound policy verification is disabled.\n");
+ mutex_unlock(&sa->dpa_ipsec->lock);
+ mutex_unlock(&sa->lock);
+ ret = -EPERM;
+ goto out;
+ }
+ mutex_unlock(&sa->dpa_ipsec->lock);
+
+ ret = check_policy_params(sa, policy_params);
+ if (ret < 0) {
+ mutex_unlock(&sa->lock);
+ goto out;
+ }
+
+ if (sa_is_parent(sa) && sa_is_outbound(sa)) {
+ log_err("Illegal to set out policy - parent SA %d\n", sa->id);
+ mutex_unlock(&sa->lock);
+ ret = -EPERM;
+ goto out;
+ }
+
+ if (sa_is_child(sa) && sa_is_inbound(sa)) {
+ log_err("Illegal to set in policy on child SA %d\n", sa->id);
+ mutex_unlock(&sa->lock);
+ ret = -EPERM;
+ goto out;
+ }
+
+ /*
+ * One SA could have more in/out policies
+ * Store all the in/out policies into the SA policy param list in order
+ * to know what to remove when SA expires.
+ */
+ ret = store_policy_param_to_sa_pol_list(sa, policy_params,
+ &policy_entry);
+ if (ret < 0) {
+ log_err("Could not store the policy in the SA\n");
+ mutex_unlock(&sa->lock);
+ goto out;
+ }
+
+ /*Insert inbound or outbound policy for this SA depending on it's type*/
+ if (sa_is_inbound(sa)) {
+ ret = update_inbound_policy(sa, policy_entry, MNG_OP_ADD);
+ if (ret < 0) {
+ remove_policy_from_sa_policy_list(sa, policy_entry);
+ log_err("Could not add the inbound policy\n");
+ }
+ } else { /* DPA_IPSEC_OUTBOUND */
+ ret = update_outbound_policy(sa, policy_entry, MNG_OP_ADD);
+ if (ret < 0) {
+ remove_policy_from_sa_policy_list(sa, policy_entry);
+ log_err("Could not add the outbound policy\n");
+ }
+ }
+
+ mutex_unlock(&sa->lock);
+out:
+ put_instance(dpa_ipsec);
+
+ return ret;
+}
+EXPORT_SYMBOL(dpa_ipsec_sa_add_policy);
+
+int dpa_ipsec_sa_remove_policy(int sa_id,
+ struct dpa_ipsec_policy_params *policy_params)
+{
+ struct dpa_ipsec_policy_entry *policy_entry;
+ struct dpa_ipsec *dpa_ipsec;
+ struct dpa_ipsec_sa *sa;
+ int ret = 0;
+
+ if (!policy_params) {
+ log_err("Invalid policy parameters handle\n");
+ return -EINVAL;
+ }
+
+ if (!valid_sa_id(sa_id))
+ return -EINVAL;
+
+ dpa_ipsec = get_instance(sa_id_to_instance_id(sa_id));
+ ret = check_instance(dpa_ipsec);
+ if (unlikely(ret < 0))
+ return ret;
+
+ sa = get_sa_from_sa_id(dpa_ipsec, sa_id);
+ if (!sa) {
+ log_err("Invalid SA handle for SA id %d\n", sa_id);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = mutex_trylock(&sa->lock);
+ if (ret == 0) {
+ log_err("Failed to acquire lock for SA %d\n", sa->id);
+ ret = -EAGAIN;
+ goto out;
+ }
+
+ /* Abort if this SA is not being used */
+ if (!sa_in_use(sa)) {
+ log_err("SA with id %d is not in use\n", sa_id);
+ mutex_unlock(&sa->lock);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (sa_is_inbound(sa) &&
+ !sa->dpa_ipsec->config.post_sec_in_params.do_pol_check) {
+ log_err("Inbound policy verification is disabled.\n");
+ mutex_unlock(&sa->lock);
+ ret = -EPERM;
+ goto out;
+ }
+
+ if (sa_is_parent(sa) && sa_is_outbound(sa)) {
+ log_err("Illegal removing out policy parent SA %d\n", sa->id);
+ mutex_unlock(&sa->lock);
+ ret = -EPERM;
+ goto out;
+ }
+
+ if (sa_is_child(sa) && sa_is_inbound(sa)) {
+ log_err("Illegal removing in policy, child SA %d\n", sa->id);
+ mutex_unlock(&sa->lock);
+ ret = -EPERM;
+ goto out;
+ }
+
+ ret = find_policy(sa, policy_params, &policy_entry);
+ if (ret < 0) {
+ log_err("Could not find policy entry in SA policy list\n");
+ mutex_unlock(&sa->lock);
+ goto out;
+ }
+
+ /*
+ * found the policy entry in SA policy parameter list;
+ * depending on the type of the SA remove the PCD entry for this policy
+ * and afterwards remove the policy param from SA policy param list
+ */
+ ret = remove_policy(sa, policy_entry);
+
+ mutex_unlock(&sa->lock);
+
+out:
+ put_instance(dpa_ipsec);
+
+ return ret;
+}
+EXPORT_SYMBOL(dpa_ipsec_sa_remove_policy);
+
+/*
+ * Returned error code: -EUSERS
+ * - if both parent SA and child SA are in invalid state, some or none of
+ * the old's policies were safely transfered to the child SA but some
+ * policies remained offloaded through parent SA.
+ */
+int dpa_ipsec_sa_rekeying(int sa_id,
+ struct dpa_ipsec_sa_params *sa_params,
+ dpa_ipsec_rekey_event_cb rekey_event_cb,
+ bool auto_rmv_old_sa,
+ int *new_sa_id)
+{
+ struct dpa_ipsec *dpa_ipsec = NULL;
+ struct dpa_ipsec_sa_mng *sa_mng = NULL;
+ struct dpa_ipsec_sa *old_sa, *new_sa;
+ struct dpa_ipsec_policy_entry *policy_entry, *tmp_policy_entry;
+ struct timeval timeval;
+ unsigned long jiffies_to_wait;
+ uint32_t id;
+ int ret = 0, err_rb;
+
+ if (!new_sa_id) {
+ log_err("Invalid SA ID holder\n");
+ return -EINVAL;
+ }
+ *new_sa_id = DPA_OFFLD_INVALID_OBJECT_ID;
+
+ ret = check_sa_params(sa_params);
+ if (ret < 0)
+ return ret;
+
+ if (!valid_sa_id(sa_id))
+ return -EINVAL;
+
+ dpa_ipsec = get_instance(sa_id_to_instance_id(sa_id));
+ ret = check_instance(dpa_ipsec);
+ if (unlikely(ret < 0))
+ return ret;
+
+ old_sa = get_sa_from_sa_id(dpa_ipsec, sa_id);
+ if (!old_sa) {
+ log_err("Invalid SA handle for SA id %d\n", sa_id);
+ put_instance(dpa_ipsec);
+ return -EINVAL;
+ }
+
+ /* Acquire parent SA's lock */
+ ret = mutex_trylock(&old_sa->lock);
+ if (ret == 0) {
+ log_err("Failed to acquire lock for SA %d\n", old_sa->id);
+ put_instance(dpa_ipsec);
+ return -EBUSY;
+ }
+
+ /* Abort if this SA is not being used */
+ if (!sa_in_use(old_sa)) {
+ log_err("SA with id %d is not in use\n", sa_id);
+ mutex_unlock(&old_sa->lock);
+ put_instance(dpa_ipsec);
+ return -ENODEV;
+ }
+
+ /* Check if SA is currently in rekeying process */
+ if (sa_currently_in_rekeying(old_sa)) {
+ log_err("SA with id %d is already in rekeying process\n",
+ old_sa->id);
+ mutex_unlock(&old_sa->lock);
+ put_instance(dpa_ipsec);
+ return -EEXIST;
+ }
+
+ /* Check if new SA parameters are matching the rekeyed SA */
+ if (old_sa->sa_dir != sa_params->sa_dir) {
+ log_err("New SA parameters don't match the parent SA %d\n",
+ old_sa->sa_dir);
+ mutex_unlock(&old_sa->lock);
+ put_instance(dpa_ipsec);
+ return -EINVAL;
+ }
+
+ ret = get_new_sa(dpa_ipsec, &new_sa, &id);
+ if (ret < 0) {
+ log_err("Failed retrieving a preallocated SA\n");
+ mutex_unlock(&old_sa->lock);
+ put_instance(dpa_ipsec);
+ return ret;
+ }
+
+ /* Update the new SA structure */
+ mutex_lock(&new_sa->lock);
+ new_sa->dpa_ipsec = old_sa->dpa_ipsec;
+ new_sa->inbound_flowid = old_sa->inbound_flowid;
+ new_sa->ipsec_hmd = old_sa->ipsec_hmd;
+ new_sa->valid_flowid_entry = false;
+ new_sa->rekey_event_cb = rekey_event_cb;
+ new_sa->parent_sa = old_sa;
+ new_sa->child_sa = NULL;
+ new_sa->sa_rekeying_node.next = LIST_POISON1;
+ new_sa->sa_rekeying_node.prev = LIST_POISON2;
+ old_sa->child_sa = new_sa;
+ old_sa->parent_sa = NULL;
+
+ /* Copy SA params into the internal SA structure */
+ if (sa_is_outbound(old_sa))
+ ret = copy_sa_params_to_out_sa(new_sa, sa_params);
+ else
+ ret = copy_sa_params_to_in_sa(new_sa, sa_params, true);
+
+ if (ret < 0) {
+ log_err("Could not copy SA parameters into SA\n");
+ goto rekey_sa_err;
+ }
+
+ /* Initialize the IPSec Manip. object (if required) for inbound SAs */
+ if (sa_is_inbound(new_sa)) {
+ if (new_sa->dpa_ipsec->config.max_sa_manip_ops == 0)
+ ret = create_ipsec_manip(new_sa, DPA_OFFLD_DESC_NONE,
+ &new_sa->ipsec_hmd);
+ else
+ ret = update_ipsec_manip(new_sa, DPA_OFFLD_DESC_NONE,
+ &new_sa->ipsec_hmd);
+ if (ret < 0) {
+ log_err("Could not create Manip object for in SA!\n");
+ goto rekey_sa_err;
+ }
+ }
+
+ /* Generate the split key from the normal auth key */
+ ret = generate_split_key(&new_sa->auth_data);
+ if (ret < 0)
+ goto rekey_sa_err;
+
+ /*
+ * Update the new SA with information from the old SA
+ * The from SEC frame queue of the old SA will be used by the new SA
+ */
+ memcpy(new_sa->from_sec_fq, old_sa->from_sec_fq,
+ sizeof(struct qman_fq));
+
+ /* Exact match table will be reused by the new SA. */
+ new_sa->em_inpol_td = old_sa->em_inpol_td;
+
+ /* Create SEC queues according to SA parameters */
+ ret = create_sa_fq_pair(new_sa, true, true);
+ if (ret < 0) {
+ log_err("Could not create SEC frame queues\n");
+ goto rekey_sa_err;
+ }
+
+ timeval.tv_sec = 0;
+ timeval.tv_usec = REKEY_SCHED_DELAY;
+ jiffies_to_wait = timeval_to_jiffies(&timeval);
+
+ /*
+ * AV's note: Since we have reused the FROM SEC FQ it is not needed to
+ * make another entry in the table of the post SEC OH PORT.
+ */
+ if (sa_is_outbound(new_sa)) {
+ INIT_LIST_HEAD(&new_sa->policy_headlist);
+
+ /* Update child's SA policies if its parent SA has policies */
+ list_for_each_entry_safe(policy_entry, tmp_policy_entry,
+ &old_sa->policy_headlist, node) {
+ ret = update_outbound_policy(new_sa, policy_entry,
+ MNG_OP_MODIFY);
+ if (ret < 0) {
+ /* Keep both SAs and delete the using remove*/
+ *new_sa_id = new_sa->id;
+ log_err("Could't modify outbound policy for rekeying SA %d\n",
+ new_sa->id);
+ new_sa->parent_sa = NULL;
+ new_sa->child_sa = NULL;
+ old_sa->child_sa = NULL;
+ old_sa->parent_sa = NULL;
+ /*
+ * AV's note TODO: investigate the removal of FQ
+ * to SEC even is it has frames in it and is in
+ * parked state
+ */
+ mutex_unlock(&new_sa->lock);
+ mutex_unlock(&old_sa->lock);
+ put_instance(dpa_ipsec);
+ return -EUSERS;
+ }
+ list_del(&policy_entry->node);
+ list_add(&policy_entry->node, &new_sa->policy_headlist);
+ }
+
+ /*
+ * Need to destroy the old SA. Have to wail until its TO SEC
+ * FQ is empty. This is done in work queue, schedule it.
+ */
+ sa_mng = &dpa_ipsec->sa_mng;
+
+ mutex_lock(&sa_mng->sa_rekeying_headlist_lock);
+ list_add_tail(&new_sa->sa_rekeying_node,
+ &sa_mng->sa_rekeying_headlist);
+ mutex_unlock(&sa_mng->sa_rekeying_headlist_lock);
+
+ queue_delayed_work(sa_mng->sa_rekeying_wq,
+ &sa_mng->sa_rekeying_work,
+ jiffies_to_wait);
+ } else { /* DPA_IPSEC_INBOUND */
+ /* Need to update the IN SA PCD entry */
+ ret = update_pre_sec_inbound_table(new_sa, MNG_OP_ADD);
+ if (ret < 0) {
+ log_err("Could not add PCD entry for new SA\n");
+ goto rekey_sa_err;
+ }
+
+ if (auto_rmv_old_sa) {
+ sa_mng = &dpa_ipsec->sa_mng;
+ /* Add new SA into the sa_rekeying_headlist */
+ mutex_lock(&sa_mng->sa_rekeying_headlist_lock);
+ list_add_tail(&new_sa->sa_rekeying_node,
+ &sa_mng->sa_rekeying_headlist);
+ mutex_unlock(&sa_mng->sa_rekeying_headlist_lock);
+
+ /* schedule inbound SA's rekeying */
+ queue_delayed_work(sa_mng->sa_rekeying_wq,
+ &sa_mng->sa_rekeying_work,
+ jiffies_to_wait);
+ } else {
+ /*
+ * The old SA has to be removed using the
+ * dpa_ipsec_remove_sa function when the hard SA
+ * expiration time limit is reached.
+ *
+ * Since the difference between soft and hard limit
+ * can be several seconds it is required to schedule the
+ * TO SEC FQ of the new SA.
+ */
+ ret = qman_schedule_fq(new_sa->to_sec_fq);
+ if (ret < 0) {
+ mutex_unlock(&new_sa->lock);
+ mutex_unlock(&old_sa->lock);
+ put_instance(dpa_ipsec);
+ return ret;
+ }
+ }
+ }
+
+ /* Rekeying done ok. */
+ *new_sa_id = new_sa->id;
+ mutex_unlock(&new_sa->lock);
+ mutex_unlock(&old_sa->lock);
+
+ put_instance(dpa_ipsec);
+
+ return 0;
+
+/*
+ * Rekeying failed before updating/adding any table entry.
+ * It is safe to remove new SA
+ */
+rekey_sa_err:
+ /*
+ * If rollback was successful return an invalid ID for new SA,
+ * otherwise return the acquired SA id so that upper layer could use it
+ * in subsequent attempts of removing it by calling dpa_ipsec_remove_sa
+ */
+
+ err_rb = rollback_rekeying_sa(new_sa);
+ if (err_rb < 0)
+ *new_sa_id = new_sa->id;
+
+ mutex_unlock(&new_sa->lock);
+ mutex_unlock(&old_sa->lock);
+
+ put_instance(dpa_ipsec);
+
+ return ret;
+}
+EXPORT_SYMBOL(dpa_ipsec_sa_rekeying);
+
+/*
+ * Expects that SA's parent and SA's lock are acquired in this order.
+ *
+ * Function description:
+ * 1. wait until TO SEC FQ is empty or timeout
+ * 2. schedule the child TO SEC FQ
+ * 3. remove the parent TO SEC FQ
+ * 4. free all memory used for this SA i.e recycle this SA
+ *
+ * Rekeying process successful if the returned error was: 0, -EUCLEAN, -EDQUOT
+ * - error code 0 for perfect rekeying
+ * - error code -EUCLEAN if during rekeying process the removal of the
+ * TO SEC FQ of old SA failed. Upper layer has to call the
+ * dpa_ipsec_remove_sa at a later time (not from callback) to try again
+ * freeing old SA resources. New SA is working perfectly.
+ * - error code -EDQUOT if failed to recycle old SA memory. Upper layer
+ * has to call the dpa_ipsec_remove_sa at a later time (not from
+ * callback)to try again recycling old SA.
+ *
+ * Rekeying process in progress if the returned error is: -ETIME or -EIO.
+ * - error code -ETIME if timeout occurred when waiting for old SA TO SEC
+ * FQ to get empty. Upper layer has nothing to do since the old SA TO
+ * SEC FQ will get empty eventually.
+ * - error code -EIO if rekeying failed to schedule the new SA. Upper layer
+ * has nothing to do since the new SA TO SEC FQ will get scheduled
+ * eventually.
+ */
+static int sa_rekeying_outbound(struct dpa_ipsec_sa *new_sa)
+{
+ struct dpa_ipsec_sa *old_sa;
+ int err, timeout = WAIT4_FQ_EMPTY_TIMEOUT; /* microseconds */
+
+ old_sa = new_sa->parent_sa;
+ BUG_ON(!old_sa);
+
+ err = wait_until_fq_empty(old_sa->to_sec_fq, timeout);
+ if (err < 0) {
+ log_err("Waiting old SA's TO SEC FQ to get empty. Timeout\n");
+ return -ETIME;
+ }
+
+ /* Schedule the new SA */
+ err = qman_schedule_fq(new_sa->to_sec_fq);
+ if (unlikely(err < 0)) {
+ log_err("Scheduling the new SA %d failed\n", new_sa->id);
+ return -EIO;
+ }
+
+ /* Now free the old SA structure and all its resources */
+ err = remove_sa_sec_fq(old_sa, old_sa->to_sec_fq);
+ if (err < 0) {
+ log_err("Couln't remove old SA's %d TO SEC FQ\n", old_sa->id);
+ rekey_err_report(new_sa->rekey_event_cb, 0, new_sa->id,
+ -EUCLEAN);
+ return -EUCLEAN;
+ }
+
+ /* Recycle SA memory */
+ err = put_sa(old_sa);
+ if (unlikely(err < 0)) {
+ log_err("Could not recycle parent SA.\n");
+ rekey_err_report(new_sa->rekey_event_cb, 0, new_sa->id,
+ -EDQUOT);
+ return -EDQUOT;
+ }
+
+ return 0;
+}
+
+/*
+ * Expects that SA's parent and SA's lock are acquired in this order.
+ *
+ * Function description:
+ * Rekeying process successful if the returned error was: 0, -EUCLEAN, -EDQUOT
+ * - error code 0 for perfect rekeying
+ * - error code -EUCLEAN if during rekeying process the removal of the
+ * TO SEC FQ of old SA failed. Upper layer has to call the
+ * dpa_ipsec_remove_sa at a later time (not from callback) to try again
+ * freeing old SA resources. New SA is working perfectly.
+ * - error code -EDQUOT if failed to recycle old SA memory. Upper layer
+ * has to call the dpa_ipsec_remove_sa at a later time (not from
+ * callback)to try again recycling old SA.
+ *
+ * Rekeying process in progress if the returned error is: -EINPROGRESS, -ETIME
+ * or -EIO.
+ * - error code -EINPROGRESS if no frame arrived on the new SA TO SEC FQ.
+ * If HARD expiration event occurs on the old SA and rekeying is still
+ * in progress the upper layer should call the dpa_ipsec_remove_sa with
+ * old SA id which will remove old SA and will automatically schedule
+ * new SA even if no frames have arrived on the new SA TO SEC FQ.
+ * - error code -ETIME if timeout occurred when waiting for old SA TO SEC
+ * FQ to get empty. Upper layer has nothing to do since the old SA TO
+ * SEC FQ will get empty eventually.
+ * - error code -EIO if rekeying failed to schedule the new SA. Upper layer
+ * has nothing to do since the old SA TO SEC FQ will get scheduled
+ * eventually.
+ *
+ * Rekeying in critical state: -ENOTRECOVERABLE
+ * - Failed to delete the hash entry formed by old SA (SPI, ...)
+ * - If an attacker would sent frames matching the old SA (SPI, ...) than
+ * FMAN will direct those frames to old SA FQ. In this case the wait
+ * until old SA FQ is empty is not valid, since being attacked this FQ
+ * might not get empty.
+ * There is a tiny probability that above scenario to happen, but if it
+ * does for several times on the same SA the recommended action would
+ * be to call the dpa_ipsec_remove_sa with the parent SA id. In case this
+ * function also fails several times then we recommend to reboot the
+ * system.
+ */
+static int sa_rekeying_inbound(struct dpa_ipsec_sa *new_sa)
+{
+ struct dpa_ipsec_sa *old_sa;
+ struct qm_mcr_queryfq_np queryfq_np;
+ int err = 0, timeout = WAIT4_FQ_EMPTY_TIMEOUT; /* microseconds */
+
+ /* Check if the new SA TO SEC FQ has frame descriptors enqueued in it */
+ qman_query_fq_np(new_sa->to_sec_fq, &queryfq_np);
+ if (queryfq_np.frm_cnt == 0)
+ return -EINPROGRESS;
+
+ /*
+ * Received at least one packet encrypted with the new SA.
+ * Remove PCD entry that makes traffic go to SEC if the entry is valid.
+ */
+ old_sa = new_sa->parent_sa;
+ BUG_ON(!old_sa);
+
+ if (old_sa->inbound_hash_entry != DPA_OFFLD_INVALID_OBJECT_ID) {
+ err = remove_inbound_hash_entry(old_sa);
+ if (err < 0) {
+ rekey_err_report(new_sa->rekey_event_cb, 0, new_sa->id,
+ err);
+ if (err == -ENOTRECOVERABLE)
+ return err;
+ }
+
+ /* destroy SA manip */
+ if (old_sa->ipsec_hmd != DPA_OFFLD_DESC_NONE) {
+ struct hmd_entry hmd_entry;
+ hmd_entry.hmd = old_sa->ipsec_hmd;
+ hmd_entry.hmd_special_op = true;
+ err = destroy_recycle_manip(old_sa, &hmd_entry);
+ if (err < 0) {
+ log_err("Could not delete manip object!\n");
+ return err;
+ }
+ old_sa->ipsec_hmd = DPA_OFFLD_DESC_NONE;
+ }
+ }
+
+ err = wait_until_fq_empty(old_sa->to_sec_fq, timeout);
+ if (err < 0) {
+ log_err("Waiting old SA's TO SEC FQ to get empty. Timeout\n");
+ return -ETIME;
+ }
+
+ /* schedule new inbound SA */
+ err = qman_schedule_fq(new_sa->to_sec_fq);
+ if (unlikely(err < 0)) {
+ log_err("Scheduling the new SA %d failed\n", new_sa->id);
+ return -EIO;
+ }
+
+ /* Update the new SA with old SA's inbound indx entry */
+ new_sa->valid_flowid_entry = old_sa->valid_flowid_entry;
+
+ /* Inherit old SA policy list and then set it empty */
+ if (old_sa->dpa_ipsec->config.post_sec_in_params.do_pol_check)
+ list_splice_init(&old_sa->policy_headlist,
+ &new_sa->policy_headlist);
+
+ /* Now free the old SA structure and all its resources */
+ err = remove_sa_sec_fq(old_sa, old_sa->to_sec_fq);
+ if (err < 0) {
+ log_err("Couln't remove old SA's %d TO SEC FQ\n", old_sa->id);
+ rekey_err_report(new_sa->rekey_event_cb, 0, new_sa->id,
+ -EUCLEAN);
+ return -EUCLEAN;
+ }
+
+ /* Recycle SA memory */
+ err = put_sa(old_sa);
+ if (unlikely(err < 0)) {
+ log_err("Could not recycle parent SA.\n");
+ rekey_err_report(new_sa->rekey_event_cb, 0, new_sa->id,
+ -EDQUOT);
+ return -EDQUOT;
+ }
+
+ return 0;
+}
+
+static inline struct dpa_ipsec_sa *find_and_lock_sa_to_work_on(
+ struct dpa_ipsec_sa *child_sa,
+ struct dpa_ipsec_sa_mng *sa_mng)
+{
+ struct dpa_ipsec_sa *parent_sa;
+ struct list_head *head;
+ int err;
+
+ head = &sa_mng->sa_rekeying_headlist;
+
+ list_for_each_entry_continue(child_sa, head, sa_rekeying_node) {
+ parent_sa = child_sa->parent_sa;
+ BUG_ON(!parent_sa);
+
+ /* Always acquire parent SA lock before child SA lock */
+ err = mutex_trylock(&parent_sa->lock);
+ if (err == 0)
+ continue;
+
+ /* Acquire child SA lock */
+ err = mutex_trylock(&child_sa->lock);
+ if (err == 0) {
+ mutex_unlock(&parent_sa->lock);
+ continue;
+ }
+
+ return child_sa;
+ }
+
+ return NULL;
+}
+
+void sa_rekeying_work_func(struct work_struct *work)
+{
+ struct dpa_ipsec_sa_mng *sa_mng;
+ struct dpa_ipsec_sa *child_sa, *parent_sa, *next_child_sa, *pos;
+ struct list_head *head;
+ int err;
+
+ sa_mng = container_of((struct delayed_work *)work,
+ struct dpa_ipsec_sa_mng, sa_rekeying_work);
+
+ /* Acquire protective lock for the SA rekeying list */
+ mutex_lock(&sa_mng->sa_rekeying_headlist_lock);
+
+ head = &sa_mng->sa_rekeying_headlist;
+ pos = container_of(head, struct dpa_ipsec_sa, sa_rekeying_node);
+
+ child_sa = find_and_lock_sa_to_work_on(pos, sa_mng);
+
+ /* Release the list lock so other threads may use it */
+ mutex_unlock(&sa_mng->sa_rekeying_headlist_lock);
+
+ while (child_sa) {
+ parent_sa = child_sa->parent_sa;
+ BUG_ON(!parent_sa);
+
+ /* Process this child SA accordingly */
+ if (sa_is_outbound(child_sa))
+ err = sa_rekeying_outbound(child_sa);
+ else /* DPA_IPSEC_INBOUND */
+ err = sa_rekeying_inbound(child_sa);
+
+ /* Acquire protective lock for the SA rekeying list */
+ mutex_lock(&sa_mng->sa_rekeying_headlist_lock);
+
+ next_child_sa = find_and_lock_sa_to_work_on(child_sa, sa_mng);
+
+ /* Remove child SA from rekeying list if processing was OK */
+ if (err == 0 || err == -EUCLEAN || err == -EDQUOT) {
+ parent_sa->child_sa = NULL;
+ child_sa->parent_sa = NULL;
+ list_del(&child_sa->sa_rekeying_node);
+ }
+
+ /* Release the list lock so other threads may use it */
+ mutex_unlock(&sa_mng->sa_rekeying_headlist_lock);
+
+ if (err == 0 && child_sa->rekey_event_cb)
+ child_sa->rekey_event_cb(0, child_sa->id, err);
+
+ /*
+ * Parent SA lock is always acquired before child SA lock so
+ * unlocking them is done backwards
+ */
+ mutex_unlock(&child_sa->lock);
+ mutex_unlock(&parent_sa->lock);
+
+ child_sa = next_child_sa;
+ }
+
+ /* Acquire protective lock for the sa rekeying list */
+ mutex_lock(&sa_mng->sa_rekeying_headlist_lock);
+
+ /* Reschedule work if there is at least one SA in rekeying process */
+ if (!list_empty(head)) {
+ struct dpa_ipsec *instance;
+ struct timeval timeval;
+ unsigned long jiffies_to_wait;
+
+ timeval.tv_sec = 0;
+ timeval.tv_usec = REKEY_SCHED_DELAY;
+ jiffies_to_wait = timeval_to_jiffies(&timeval);
+
+ instance = container_of(sa_mng, struct dpa_ipsec, sa_mng);
+ if (atomic_read(&instance->valid))
+ queue_delayed_work(sa_mng->sa_rekeying_wq,
+ &sa_mng->sa_rekeying_work,
+ jiffies_to_wait);
+ }
+
+ /* Release protective lock for the SA rekeying list */
+ mutex_unlock(&sa_mng->sa_rekeying_headlist_lock);
+
+ return;
+}
+
+/*
+ * Functional description:
+ *
+ * Removes the PCD entries that make traffic go to SEC for the SA given as input
+ *
+ * Returns:
+ * - operation successful, returned code 0
+ * - resource currently busy try again, returned code -EAGAIN
+ * - remove inbound entry failed, returned code -ENOTRECOVERABLE
+ * - remove outbound policies failed, at least one policy for this SA is
+ * still in the system, returned code -EBADSLT
+ */
+int dpa_ipsec_disable_sa(int sa_id)
+{
+ struct dpa_ipsec *dpa_ipsec;
+ struct dpa_ipsec_sa *sa;
+ int ret = 0, err = 0;
+
+ if (!valid_sa_id(sa_id))
+ return -EINVAL;
+
+ dpa_ipsec = get_instance(sa_id_to_instance_id(sa_id));
+ ret = check_instance(dpa_ipsec);
+ if (unlikely(ret < 0))
+ return ret;
+
+ sa = get_sa_from_sa_id(dpa_ipsec, sa_id);
+ if (!sa) {
+ log_err("Invalid SA handle for SA id %d\n", sa_id);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* Acquire protective lock for this SA */
+ ret = mutex_trylock(&sa->lock);
+ if (ret == 0) {
+ ret = -EAGAIN;
+ goto out;
+ }
+
+ /* Abort if this SA is not being used */
+ if (!sa_in_use(sa)) {
+ log_err("SA with id %d is not in use\n", sa_id);
+ mutex_unlock(&sa->lock);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (!sa_is_single(sa)) {
+ log_err("SA %d is a parent or child in rekeying\n", sa_id);
+ mutex_unlock(&sa->lock);
+ ret = -EINPROGRESS;
+ goto out;
+ }
+
+ if (sa_is_inbound(sa) &&
+ sa->inbound_hash_entry != DPA_OFFLD_INVALID_OBJECT_ID)
+ ret = remove_inbound_hash_entry(sa);
+ else { /* DPA_IPSEC_OUTBOUND */
+ err = sa_flush_policies(sa);
+ if (err < 0)
+ ret = -EBADSLT;
+ }
+
+ /* Release protective lock for this SA */
+ mutex_unlock(&sa->lock);
+out:
+ put_instance(dpa_ipsec);
+
+ return ret;
+}
+EXPORT_SYMBOL(dpa_ipsec_disable_sa);
+
+/*
+ * Flush all SAs. If an error occurs while removing an SA, the flush process
+ * will continue with the next SAs and the return value will be -EAGAIN,
+ * which informs the upper layer that there is still at least one SA left
+ */
+int dpa_ipsec_flush_all_sa(int dpa_ipsec_id)
+{
+ struct dpa_ipsec *dpa_ipsec;
+ uint32_t i, sa_id;
+ int err = 0, ret;
+
+ dpa_ipsec = get_instance(dpa_ipsec_id);
+ ret = check_instance(dpa_ipsec);
+ if (unlikely(ret < 0))
+ return ret;
+
+ flush_delayed_work(&dpa_ipsec->sa_mng.sa_rekeying_work);
+
+ for (i = 0; i < dpa_ipsec->sa_mng.max_num_sa; i++) {
+ mutex_lock(&dpa_ipsec->lock);
+ sa_id = dpa_ipsec->used_sa_ids[i];
+ mutex_unlock(&dpa_ipsec->lock);
+
+ if (sa_id != DPA_OFFLD_INVALID_OBJECT_ID) {
+ ret = dpa_ipsec_remove_sa(sa_id);
+ if (ret < 0)
+ err = -EAGAIN;
+ }
+ }
+
+ put_instance(dpa_ipsec);
+
+ return err;
+}
+EXPORT_SYMBOL(dpa_ipsec_flush_all_sa);
+
+int dpa_ipsec_sa_get_policies(int sa_id,
+ struct dpa_ipsec_policy_params *policy_params,
+ int *num_pol)
+{
+ struct dpa_ipsec *dpa_ipsec;
+ struct dpa_ipsec_sa *sa;
+ int ret;
+
+ if (!num_pol) {
+ log_err("Invalid num_pol parameter handle\n");
+ return -EINVAL;
+ }
+
+ if (!valid_sa_id(sa_id))
+ return -EINVAL;
+
+ dpa_ipsec = get_instance(sa_id_to_instance_id(sa_id));
+ ret = check_instance(dpa_ipsec);
+ if (unlikely(ret < 0))
+ return ret;
+
+ sa = get_sa_from_sa_id(dpa_ipsec, sa_id);
+ if (!sa) {
+ log_err("Invalid SA handle for SA id %d\n", sa_id);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = mutex_trylock(&sa->lock);
+ if (ret == 0) {
+ log_err("Failed to acquire lock for SA %d\n", sa->id);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ /* Abort if this SA is not being used */
+ if (!sa_in_use(sa)) {
+ log_err("SA with id %d is not in use\n", sa_id);
+ mutex_unlock(&sa->lock);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (sa_is_inbound(sa) &&
+ !sa->dpa_ipsec->config.post_sec_in_params.do_pol_check) {
+ log_err("Inbound policy verification is disabled.\n");
+ mutex_unlock(&sa->lock);
+ ret = -EPERM;
+ goto out;
+ }
+
+ if (!policy_params) {
+ /* get the number of policies for SA with id sa_id */
+ *num_pol = get_policy_count_for_sa(sa);
+ mutex_unlock(&sa->lock);
+ ret = 0;
+ goto out;
+ }
+
+ ret = copy_all_policies(sa, policy_params, *num_pol);
+
+ mutex_unlock(&sa->lock);
+out:
+ put_instance(dpa_ipsec);
+
+ return ret;
+}
+EXPORT_SYMBOL(dpa_ipsec_sa_get_policies);
+
+/* Expects that SA structure is locked */
+static int sa_flush_policies(struct dpa_ipsec_sa *sa)
+{
+ struct dpa_ipsec_policy_entry *pol_entry, *tmp;
+ int err = 0, ret = 0;
+
+ BUG_ON(!sa);
+
+ list_for_each_entry_safe(pol_entry, tmp, &sa->policy_headlist, node) {
+ err = remove_policy(sa, pol_entry);
+ if (err < 0) {
+ log_err("Failed remove policy entry SA %d\n", sa->id);
+ ret = -EAGAIN;
+ /*
+ * continue with the other policies even if error
+ * occured for this policy
+ */
+ }
+ }
+
+ return ret;
+}
+
+int dpa_ipsec_sa_flush_policies(int sa_id)
+{
+ struct dpa_ipsec *dpa_ipsec;
+ struct dpa_ipsec_sa *sa;
+ int ret = 0;
+
+ if (!valid_sa_id(sa_id))
+ return -EINVAL;
+
+ dpa_ipsec = get_instance(sa_id_to_instance_id(sa_id));
+ ret = check_instance(dpa_ipsec);
+ if (unlikely(ret < 0))
+ return ret;
+
+ sa = get_sa_from_sa_id(dpa_ipsec, sa_id);
+ if (!sa) {
+ log_err("Invalid SA handle for SA id %d\n", sa_id);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = mutex_trylock(&sa->lock);
+ if (ret == 0) {
+ log_err("Failed to acquire lock for SA %d\n", sa->id);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ /* Abort if this SA is not being used */
+ if (!sa_in_use(sa)) {
+ log_err("SA with id %d is not in use\n", sa_id);
+ mutex_unlock(&sa->lock);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (sa_is_inbound(sa) &&
+ !sa->dpa_ipsec->config.post_sec_in_params.do_pol_check) {
+ log_err("Inbound policy verification is disabled.\n");
+ mutex_unlock(&sa->lock);
+ ret = -EPERM;
+ goto out;
+ }
+
+ ret = sa_flush_policies(sa);
+
+ mutex_unlock(&sa->lock);
+out:
+ put_instance(dpa_ipsec);
+
+ return ret;
+}
+EXPORT_SYMBOL(dpa_ipsec_sa_flush_policies);
+
+int dpa_ipsec_sa_get_stats(int sa_id, struct dpa_ipsec_sa_stats *sa_stats)
+{
+ struct dpa_ipsec *dpa_ipsec;
+ struct dpa_ipsec_sa *sa;
+ int ret = 0, dscp_idx = 0;
+ uint32_t *desc;
+ struct dpa_cls_tbl_entry_stats stats;
+
+ if (!sa_stats) {
+ log_err("Invalid SA statistics storage pointer\n");
+ return -EINVAL;
+ }
+
+ if (!valid_sa_id(sa_id))
+ return -EINVAL;
+
+ dpa_ipsec = get_instance(sa_id_to_instance_id(sa_id));
+ ret = check_instance(dpa_ipsec);
+ if (unlikely(ret < 0))
+ return ret;
+
+ sa = get_sa_from_sa_id(dpa_ipsec, sa_id);
+ if (!sa) {
+ log_err("Invalid SA handle for SA id %d\n", sa_id);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = mutex_trylock(&sa->lock);
+ if (ret == 0) {
+ log_err("Failed to acquire lock for SA %d\n", sa->id);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ /* Abort if this SA is not being used */
+ if (!sa_in_use(sa)) {
+ log_err("SA with id %d is not in use\n", sa_id);
+ mutex_unlock(&sa->lock);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ memset(sa_stats, 0, sizeof(*sa_stats));
+
+ if (!sa->enable_stats) {
+ log_err("Statistics are not enabled for SA id %d\n", sa_id);
+ mutex_unlock(&sa->lock);
+ ret = -EPERM;
+ goto out;
+ }
+
+ desc = (uint32_t *)sa->sec_desc->desc;
+ if (!sa->sec_desc_extended) {
+ sa_stats->packets_count = *(desc + sa->stats_offset / 4);
+ sa_stats->bytes_count = *(desc + sa->stats_offset / 4 + 1);
+ } else {
+ sa_stats->bytes_count = *(desc + sa->stats_offset / 4);
+ sa_stats->packets_count = *(desc + sa->stats_offset / 4 + 1);
+ }
+
+ if (!sa->enable_extended_stats)
+ goto sa_get_stats_return;
+
+ memset(&stats, 0, sizeof(stats));
+
+ if (sa_is_inbound(sa)) { /* Inbound SA */
+ ret = dpa_classif_table_get_entry_stats_by_ref(
+ sa->inbound_sa_td,
+ sa->inbound_hash_entry,
+ &stats);
+ if (ret != 0) {
+ log_err("Failed to acquire total packets counter for inbound SA Id=%d.\n",
+ sa_id);
+ mutex_unlock(&sa->lock);
+ goto out;
+ } else {
+ sa_stats->input_packets = stats.pkts;
+ }
+ } else { /* Outbound SA */
+ struct dpa_ipsec_policy_entry *out_policy;
+ struct dpa_ipsec_policy_params *policy_params;
+ struct dpa_ipsec_pre_sec_out_params *psop;
+ int table_idx, td;
+
+ psop = &sa->dpa_ipsec->config.pre_sec_out_params;
+
+ list_for_each_entry(out_policy, &sa->policy_headlist, node) {
+ policy_params = &out_policy->pol_params;
+ if (IP_ADDR_TYPE_IPV4(policy_params->dest_addr))
+ table_idx = GET_POL_TABLE_IDX(
+ policy_params->protocol,
+ IPV4);
+ else
+ table_idx = GET_POL_TABLE_IDX(
+ policy_params->protocol,
+ IPV6);
+ td = psop->table[table_idx].dpa_cls_td;
+
+ /*
+ * In case the SA per DSCP feature is disabled, will
+ * acquire statistics for the policy and exit
+ */
+ if (!policy_params->use_dscp) {
+ ret = dpa_classif_table_get_entry_stats_by_ref(
+ td,
+ *out_policy->entry_id,
+ &stats);
+ if (ret != 0) {
+ log_err("Failed to acquire total packets counter for outbound SA Id=%d. Failure occured on outbound policy table %d (td=%d).\n",
+ sa_id, table_idx, td);
+ mutex_unlock(&sa->lock);
+ goto out;
+ } else {
+ sa_stats->input_packets += stats.pkts;
+ goto sa_get_stats_return;
+ }
+ }
+
+ /*
+ * In case the SA per DSCP feature is enabled, will
+ * iterate through all DSCP values defined for the
+ * SA and totalize statistics
+ */
+ do {
+ ret = dpa_classif_table_get_entry_stats_by_ref(
+ td,
+ out_policy->entry_id[dscp_idx],
+ &stats);
+
+ if (ret != 0) {
+ /*
+ * In case of error just print the
+ * message and get to the next value
+ */
+ log_err("Failed to acquire packets counter for outbound SA Id=%d. Failure occured on outbound policy table %d (td=%d).\n",
+ sa_id, table_idx, td);
+ } else {
+ sa_stats->input_packets += stats.pkts;
+ }
+ dscp_idx += 1;
+ } while (dscp_idx <= sa->dscp_end - sa->dscp_start);
+ }
+ }
+
+sa_get_stats_return:
+ mutex_unlock(&sa->lock);
+/* fall through */
+out:
+ put_instance(dpa_ipsec);
+
+ return ret;
+}
+EXPORT_SYMBOL(dpa_ipsec_sa_get_stats);
+
+int dpa_ipsec_get_stats(int dpa_ipsec_id, struct dpa_ipsec_stats *stats)
+{
+ t_FmPcdCcKeyStatistics miss_stats;
+ struct dpa_cls_tbl_params table_params;
+ int i, j, td, ret;
+ t_Error err;
+ struct dpa_ipsec *dpa_ipsec;
+
+ if (!stats) {
+ log_err("\"stats\" cannot be NULL.\n");
+ return -EINVAL;
+ }
+ memset(stats, 0, sizeof(*stats));
+
+ dpa_ipsec = get_instance(dpa_ipsec_id);
+ ret = check_instance(dpa_ipsec);
+ if (unlikely(ret < 0))
+ return ret;
+
+ mutex_lock(&dpa_ipsec->lock);
+
+ /* On inbound add up miss counters from all inbound pre-SEC tables: */
+ for (i = 0; i < DPA_IPSEC_MAX_SA_TYPE; i++) {
+ td = dpa_ipsec->config.pre_sec_in_params.dpa_cls_td[i];
+
+ /*
+ * Check if this policy table is defined by the user. If not,
+ * skip to the next.
+ */
+ if (td == DPA_OFFLD_DESC_NONE)
+ continue;
+
+ if (dpa_classif_table_get_params(td, &table_params)) {
+ log_err("Failed to acquire params for inbound table type %d (td=%d).\n",
+ i, td);
+ mutex_unlock(&dpa_ipsec->lock);
+ put_instance(dpa_ipsec);
+ return -EINVAL;
+ }
+ if (table_params.type == DPA_CLS_TBL_HASH)
+ err = FM_PCD_HashTableGetMissStatistics(
+ table_params.cc_node,
+ &miss_stats);
+ else
+ err = FM_PCD_MatchTableGetMissStatistics(
+ table_params.cc_node,
+ &miss_stats);
+ if (err != E_OK) {
+ log_err("Failed to acquire miss statistics for inbound table type %d (td=%d, Cc node handle=0x%p).\n",
+ i, td, table_params.cc_node);
+ mutex_unlock(&dpa_ipsec->lock);
+ put_instance(dpa_ipsec);
+ return -EINVAL;
+ } else {
+ stats->inbound_miss_pkts += miss_stats.frameCount;
+ stats->inbound_miss_bytes += miss_stats.byteCount;
+ }
+ }
+
+ /* On outbound add miss statistics from all outbound pre-SEC tables: */
+ for (i = 0; i < DPA_IPSEC_MAX_SUPPORTED_PROTOS; i++) {
+ td = dpa_ipsec->config.pre_sec_out_params.table[i].dpa_cls_td;
+
+ /*
+ * Check if this protocol table is defined by the user. If not,
+ * skip to the next.
+ */
+ if (td == DPA_OFFLD_DESC_NONE)
+ continue;
+
+ /*
+ * Some applications are using the same tables in more than one
+ * role on the outbound, hence we need to check whether we
+ * haven't already processed this table:
+ */
+ for (j = 0; j < i; j++) {
+ if (td == dpa_ipsec->config.pre_sec_out_params.
+ table[j].dpa_cls_td)
+ break;
+ }
+
+ if (j < i)
+ continue;
+
+ if (dpa_classif_table_get_params(td, &table_params)) {
+ log_err("Failed to acquire table params for outbound proto type #%d (td=%d).\n",
+ i, td);
+ mutex_unlock(&dpa_ipsec->lock);
+ put_instance(dpa_ipsec);
+ return -EINVAL;
+ }
+ if (table_params.type == DPA_CLS_TBL_HASH)
+ err = FM_PCD_HashTableGetMissStatistics(
+ table_params.cc_node,
+ &miss_stats);
+ else
+ err = FM_PCD_MatchTableGetMissStatistics(
+ table_params.cc_node,
+ &miss_stats);
+ if (err != E_OK) {
+ log_err("Failed to acquire miss statistics for outbound proto type %d (td=%d, Cc node handle=0x%p).\n",
+ i, td, table_params.cc_node);
+ mutex_unlock(&dpa_ipsec->lock);
+ put_instance(dpa_ipsec);
+ return -EINVAL;
+ } else {
+ stats->outbound_miss_pkts += miss_stats.frameCount;
+ stats->outbound_miss_bytes += miss_stats.byteCount;
+ }
+ }
+
+ mutex_unlock(&dpa_ipsec->lock);
+ put_instance(dpa_ipsec);
+
+ return 0;
+}
+EXPORT_SYMBOL(dpa_ipsec_get_stats);
+
+int dpa_ipsec_sa_modify(int sa_id, struct dpa_ipsec_sa_modify_prm *modify_prm)
+{
+ struct dpa_ipsec *dpa_ipsec;
+ struct dpa_ipsec_sa *sa;
+ dma_addr_t dma_rjobd;
+ uint32_t *rjobd;
+ struct qm_fd fd;
+ char msg[5];
+ const size_t msg_len = 5;
+ int ret;
+
+ if (!modify_prm) {
+ log_err("Invalid modify SA parameter\n");
+ return -EINVAL;
+ }
+
+ if (!valid_sa_id(sa_id))
+ return -EINVAL;
+
+ dpa_ipsec = get_instance(sa_id_to_instance_id(sa_id));
+ ret = check_instance(dpa_ipsec);
+ if (unlikely(ret < 0))
+ return ret;
+
+ sa = get_sa_from_sa_id(dpa_ipsec, sa_id);
+ if (!sa) {
+ log_err("Invalid SA handle for SA id %d\n", sa_id);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = mutex_trylock(&sa->lock);
+ if (ret == 0) {
+ log_err("SA %d is being used\n", sa->id);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ /* Abort if this SA is not being used */
+ if (!sa_in_use(sa)) {
+ log_err("SA with id %d is not in use\n", sa_id);
+ mutex_unlock(&sa->lock);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ BUG_ON(!sa->dpa_ipsec);
+
+ /* Set the SA id in the message that will be in the output SEC frame */
+ *(u32 *)(&msg[1]) = sa->id;
+
+ switch (modify_prm->type) {
+ case DPA_IPSEC_SA_MODIFY_ARS:
+ msg[0] = DPA_IPSEC_SA_MODIFY_ARS_DONE;
+ if (sa_is_outbound(sa)) {
+ log_err("ARS update supported only for inbound SA\n");
+ ret = -EINVAL;
+ goto out;
+ }
+ ret = build_rjob_desc_ars_update(sa, modify_prm->arw, msg_len);
+ if (ret < 0)
+ goto out;
+ break;
+ case DPA_IPSEC_SA_MODIFY_SEQ_NUM:
+ msg[0] = DPA_IPSEC_SA_MODIFY_SEQ_NUM_DONE;
+ sa->w_seq_num = modify_prm->seq_num;
+
+ ret = build_rjob_desc_seq_write(sa, msg_len);
+ if (ret < 0)
+ goto out;
+ break;
+ case DPA_IPSEC_SA_MODIFY_EXT_SEQ_NUM:
+ msg[0] = DPA_IPSEC_SA_MODIFY_EXT_SEQ_NUM_DONE;
+ sa->w_seq_num = modify_prm->seq_num;
+
+ ret = build_rjob_desc_seq_write(sa, msg_len);
+ if (ret < 0)
+ goto out;
+ break;
+ case DPA_IPSEC_SA_MODIFY_CRYPTO:
+ log_err("Modifying cryptographic parameters is unsupported\n");
+ ret = -EOPNOTSUPP;
+ goto out;
+ default:
+ log_err("Invalid type for modify parameters\n");
+ mutex_unlock(&sa->lock);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ rjobd = sa->rjob_desc;
+
+ /* Copy completion message to the end of the RJOB */
+ memcpy(((char *)rjobd) + desc_len(rjobd) * CAAM_CMD_SZ, msg, msg_len);
+
+ dma_rjobd = dma_map_single(sa->dpa_ipsec->jrdev, rjobd,
+ desc_len(rjobd) * CAAM_CMD_SZ + msg_len,
+ DMA_BIDIRECTIONAL);
+ if (!dma_rjobd) {
+ log_err("Failed DMA mapping the RJD for SA %d\n", sa->id);
+ mutex_unlock(&sa->lock);
+ ret = -ENXIO;
+ goto out;
+ }
+
+ memset(&fd, 0x00, sizeof(struct qm_fd));
+ /* fill frame descriptor parameters */
+ fd.format = qm_fd_contig;
+ qm_fd_addr_set64(&fd, dma_rjobd);
+ fd.length20 = desc_len(rjobd) * sizeof(uint32_t) + msg_len;
+ fd.offset = 0;
+ fd.bpid = 0;
+ fd.cmd = FD_CMD_REPLACE_JOB_DESC;
+ ret = qman_enqueue(sa->to_sec_fq, &fd, 0);
+ if (ret != 0) {
+ log_err("Could not enqueue frame with RJAD for SA %d\n",
+ sa->id);
+ ret = -ETXTBSY;
+ }
+
+ dma_unmap_single(sa->dpa_ipsec->jrdev, dma_rjobd,
+ desc_len(rjobd) * CAAM_CMD_SZ + msg_len,
+ DMA_BIDIRECTIONAL);
+
+ mutex_unlock(&sa->lock);
+out:
+ put_instance(dpa_ipsec);
+
+ return ret;
+}
+EXPORT_SYMBOL(dpa_ipsec_sa_modify);
+
+int dpa_ipsec_sa_request_seq_number(int sa_id)
+{
+ struct dpa_ipsec *dpa_ipsec;
+ struct dpa_ipsec_sa *sa;
+ dma_addr_t dma_rjobd;
+ uint32_t *rjobd;
+ struct qm_fd fd;
+ char msg[5];
+ const size_t msg_len = 5;
+ int ret;
+
+ if (!valid_sa_id(sa_id))
+ return -EINVAL;
+
+ dpa_ipsec = get_instance(sa_id_to_instance_id(sa_id));
+ ret = check_instance(dpa_ipsec);
+ if (unlikely(ret < 0))
+ return ret;
+
+ sa = get_sa_from_sa_id(dpa_ipsec, sa_id);
+ if (!sa) {
+ log_err("Invalid SA handle for SA id %d\n", sa_id);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = mutex_trylock(&sa->lock);
+ if (ret == 0) {
+ log_err("SA %d is being used\n", sa->id);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ /* Abort if this SA is not being used */
+ if (!sa_in_use(sa)) {
+ log_err("SA with id %d is not in use\n", sa_id);
+ mutex_unlock(&sa->lock);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ BUG_ON(!sa->dpa_ipsec);
+
+ if (sa->read_seq_in_progress) {
+ log_err("A new request for SA %d can be done only after a get SEQ is done\n",
+ sa->id);
+ mutex_unlock(&sa->lock);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ msg[0] = DPA_IPSEC_SA_GET_SEQ_NUM_DONE;
+ *(u32 *)(&msg[1]) = sa->id;
+
+ ret = build_rjob_desc_seq_read(sa, msg_len);
+ if (ret < 0) {
+ log_err("Failed to create RJOB for reading SEQ number\n");
+ mutex_unlock(&sa->lock);
+ goto out;
+ }
+
+ rjobd = sa->rjob_desc;
+
+ /* Copy completion message to the end of the RJOB */
+ memcpy(((char *)rjobd) + desc_len(rjobd) * CAAM_CMD_SZ, msg, msg_len);
+
+ dma_rjobd = dma_map_single(sa->dpa_ipsec->jrdev, rjobd,
+ desc_len(rjobd) * CAAM_CMD_SZ + msg_len,
+ DMA_BIDIRECTIONAL);
+ if (!dma_rjobd) {
+ log_err("Failed DMA mapping the RJD for SA %d\n", sa->id);
+ mutex_unlock(&sa->lock);
+ ret = -ENXIO;
+ goto out;
+ }
+
+ memset(&fd, 0x00, sizeof(struct qm_fd));
+ /* fill frame descriptor parameters */
+ fd.format = qm_fd_contig;
+ qm_fd_addr_set64(&fd, dma_rjobd);
+ fd.length20 = desc_len(rjobd) * sizeof(uint32_t) + msg_len;
+ fd.offset = 0;
+ fd.bpid = 0;
+ fd.cmd = FD_CMD_REPLACE_JOB_DESC;
+ ret = qman_enqueue(sa->to_sec_fq, &fd, 0);
+ if (ret != 0) {
+ log_err("Could not enqueue frame with RJAD for SA %d\n",
+ sa->id);
+ ret = -ETXTBSY;
+ }
+
+ /* Request has been done successfully */
+ sa->read_seq_in_progress = true;
+
+ dma_unmap_single(sa->dpa_ipsec->jrdev, dma_rjobd,
+ desc_len(rjobd) * CAAM_CMD_SZ + msg_len,
+ DMA_BIDIRECTIONAL);
+
+ mutex_unlock(&sa->lock);
+
+out:
+ put_instance(dpa_ipsec);
+
+ return ret;
+}
+EXPORT_SYMBOL(dpa_ipsec_sa_request_seq_number);
+
+int dpa_ipsec_sa_get_seq_number(int sa_id, uint64_t *seq)
+{
+ struct dpa_ipsec *dpa_ipsec;
+ struct dpa_ipsec_sa *sa;
+ int ret;
+
+ if (!seq) {
+ log_err("Invalid SEQ parameter handle\n");
+ return -EINVAL;
+ }
+
+ if (!valid_sa_id(sa_id))
+ return -EINVAL;
+
+ dpa_ipsec = get_instance(sa_id_to_instance_id(sa_id));
+ ret = check_instance(dpa_ipsec);
+ if (unlikely(ret < 0))
+ return ret;
+
+ sa = get_sa_from_sa_id(dpa_ipsec, sa_id);
+ if (!sa) {
+ log_err("Invalid SA handle for SA id %d\n", sa_id);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = mutex_trylock(&sa->lock);
+ if (ret == 0) {
+ log_err("SA %d is being used\n", sa_id);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ /* Abort if this SA is not being used */
+ if (!sa_in_use(sa)) {
+ log_err("SA with id %d is not in use\n", sa_id);
+ mutex_unlock(&sa->lock);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ BUG_ON(!sa->dpa_ipsec);
+
+ if (!sa->read_seq_in_progress) {
+ log_err("Prior to getting the SEQ number for SA %d a request must be made\n",
+ sa->id);
+ mutex_unlock(&sa->lock);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ *seq = sa->r_seq_num;
+ sa->read_seq_in_progress = false;
+
+ mutex_unlock(&sa->lock);
+out:
+ put_instance(dpa_ipsec);
+
+ return 0;
+}
+EXPORT_SYMBOL(dpa_ipsec_sa_get_seq_number);
+
+int dpa_ipsec_sa_get_out_path(int sa_id, uint32_t *fqid)
+{
+ struct dpa_ipsec *dpa_ipsec;
+ struct dpa_ipsec_sa *sa;
+ int ret;
+
+ if (!fqid) {
+ log_err("Invalid fqid handle\n");
+ return -EINVAL;
+ }
+
+ if (!valid_sa_id(sa_id))
+ return -EINVAL;
+
+ dpa_ipsec = get_instance(sa_id_to_instance_id(sa_id));
+ ret = check_instance(dpa_ipsec);
+ if (unlikely(ret < 0))
+ return ret;
+
+ sa = get_sa_from_sa_id(dpa_ipsec, sa_id);
+ if (!sa) {
+ log_err("Invalid SA handle for SA %d\n", sa_id);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = mutex_trylock(&sa->lock);
+ if (ret == 0) {
+ log_err("SA %d is being used\n", sa_id);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ if (!sa_in_use(sa)) {
+ log_err("SA %d is not in use\n", sa_id);
+ mutex_unlock(&sa->lock);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (sa_is_inbound(sa)) {
+ log_err("Illegal to acquire the to SEC frame queue ID for inbound SA %d.\n",
+ sa_id);
+ mutex_unlock(&sa->lock);
+ ret = -EPERM;
+ goto out;
+ }
+
+ *fqid = qman_fq_fqid(sa->to_sec_fq);
+
+ mutex_unlock(&sa->lock);
+ ret = 0;
+out:
+ put_instance(dpa_ipsec);
+
+ return ret;
+}
+EXPORT_SYMBOL(dpa_ipsec_sa_get_out_path);
diff --git a/drivers/staging/fsl_dpa_offload/dpa_ipsec.h b/drivers/staging/fsl_dpa_offload/dpa_ipsec.h
new file mode 100644
index 0000000..353c817
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dpa_ipsec.h
@@ -0,0 +1,539 @@
+/* Copyright 2008-2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DPA_IPSEC_H__
+#define __DPA_IPSEC_H__
+
+#include <linux/fsl_qman.h>
+#include <linux/fsl_bman.h>
+#include <linux/fsl_dpa_ipsec.h>
+
+/* From Linux for Shared Descriptor auxiliary structures */
+#include <linux/bitops.h>
+#include <linux/compiler.h>
+#include <linux/workqueue.h>
+
+/*For IP header structure definition */
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+
+/*For UDP header structure definition */
+#include <linux/udp.h>
+
+#include "desc.h"
+
+#include "fm_pcd_ext.h"
+#include "cq.h"
+
+#define OP_PCL_IPSEC_INVALID_ALG_ID 0xFFFF
+
+#define IPSEC_ALGS_ENTRY(enc, auth) { \
+ .enc_alg = OP_PCL_IPSEC_ ## enc, \
+ .auth_alg = OP_PCL_IPSEC_ ## auth \
+ }
+
+#define IPSEC_ALGS { \
+ /* DPA_IPSEC_CIPHER_ALG_3DES_CBC_HMAC_96_MD5_128 */ \
+ IPSEC_ALGS_ENTRY(3DES, HMAC_MD5_96), \
+ /* DPA_IPSEC_CIPHER_ALG_3DES_CBC_HMAC_96_SHA_160 */ \
+ IPSEC_ALGS_ENTRY(3DES, HMAC_SHA1_96), \
+ /* DPA_IPSEC_CIPHER_ALG_3DES_CBC_HMAC_MD5_128 */ \
+ IPSEC_ALGS_ENTRY(3DES, HMAC_MD5_128), \
+ /* DPA_IPSEC_CIPHER_ALG_3DES_CBC_HMAC_SHA_160 */ \
+ IPSEC_ALGS_ENTRY(3DES, HMAC_SHA1_160), \
+ /* DPA_IPSEC_CIPHER_ALG_3DES_CBC_HMAC_SHA_256_128 */ \
+ IPSEC_ALGS_ENTRY(3DES, HMAC_SHA2_256_128), \
+ /* DPA_IPSEC_CIPHER_ALG_3DES_CBC_HMAC_SHA_384_192 */ \
+ IPSEC_ALGS_ENTRY(3DES, HMAC_SHA2_384_192), \
+ /* DPA_IPSEC_CIPHER_ALG_3DES_CBC_HMAC_SHA_512_256 */ \
+ IPSEC_ALGS_ENTRY(3DES, HMAC_SHA2_512_256), \
+ /* DPA_IPSEC_CIPHER_ALG_NULL_ENC_HMAC_96_MD5_128 */ \
+ IPSEC_ALGS_ENTRY(NULL_ENC, HMAC_MD5_96), \
+ /* DPA_IPSEC_CIPHER_ALG_NULL_ENC_HMAC_96_SHA_160 */ \
+ IPSEC_ALGS_ENTRY(NULL_ENC, HMAC_SHA1_96), \
+ /* DPA_IPSEC_CIPHER_ALG_NULL_ENC_AES_XCBC_MAC_96 */ \
+ IPSEC_ALGS_ENTRY(NULL_ENC, AES_XCBC_MAC_96), \
+ /* DPA_IPSEC_CIPHER_ALG_NULL_ENC_HMAC_MD5_128 */ \
+ IPSEC_ALGS_ENTRY(NULL_ENC, HMAC_MD5_128), \
+ /* DPA_IPSEC_CIPHER_ALG_NULL_ENC_HMAC_SHA_160 */ \
+ IPSEC_ALGS_ENTRY(NULL_ENC, HMAC_SHA1_160), \
+ /* DPA_IPSEC_CIPHER_ALG_NULL_ENC_HMAC_SHA_256_128 */ \
+ IPSEC_ALGS_ENTRY(NULL_ENC, HMAC_SHA2_256_128), \
+ /* DPA_IPSEC_CIPHER_ALG_NULL_ENC_HMAC_SHA_384_192 */ \
+ IPSEC_ALGS_ENTRY(NULL_ENC, HMAC_SHA2_384_192), \
+ /* DPA_IPSEC_CIPHER_ALG_NULL_ENC_HMAC_SHA_512_256 */ \
+ IPSEC_ALGS_ENTRY(NULL_ENC, HMAC_SHA2_512_256), \
+ /* DPA_IPSEC_CIPHER_ALG_AES_CBC_HMAC_96_MD5_128 */ \
+ IPSEC_ALGS_ENTRY(AES_CBC, HMAC_MD5_96), \
+ /* DPA_IPSEC_CIPHER_ALG_AES_CBC_HMAC_96_SHA_160 */ \
+ IPSEC_ALGS_ENTRY(AES_CBC, HMAC_SHA1_96), \
+ /* DPA_IPSEC_CIPHER_ALG_AES_CBC_AES_XCBC_MAC_96 */ \
+ IPSEC_ALGS_ENTRY(AES_CBC, AES_XCBC_MAC_96), \
+ /* DPA_IPSEC_CIPHER_ALG_AES_CBC_HMAC_MD5_128 */ \
+ IPSEC_ALGS_ENTRY(AES_CBC, HMAC_MD5_128), \
+ /* DPA_IPSEC_CIPHER_ALG_AES_CBC_HMAC_SHA_160 */ \
+ IPSEC_ALGS_ENTRY(AES_CBC, HMAC_SHA1_160), \
+ /* DPA_IPSEC_CIPHER_ALG_AES_CBC_HMAC_SHA_256_128 */ \
+ IPSEC_ALGS_ENTRY(AES_CBC, HMAC_SHA2_256_128), \
+ /* DPA_IPSEC_CIPHER_ALG_AES_CBC_HMAC_SHA_384_192 */ \
+ IPSEC_ALGS_ENTRY(AES_CBC, HMAC_SHA2_384_192), \
+ /* DPA_IPSEC_CIPHER_ALG_AES_CBC_HMAC_SHA_512_256 */ \
+ IPSEC_ALGS_ENTRY(AES_CBC, HMAC_SHA2_512_256), \
+ /* DPA_IPSEC_CIPHER_ALG_AES_CTR_HMAC_96_MD5_128 */ \
+ IPSEC_ALGS_ENTRY(AES_CTR, HMAC_MD5_96), \
+ /* DPA_IPSEC_CIPHER_ALG_AES_CTR_HMAC_96_SHA_160 */ \
+ IPSEC_ALGS_ENTRY(AES_CTR, HMAC_SHA1_96), \
+ /* DPA_IPSEC_CIPHER_ALG_AES_CTR_AES_XCBC_MAC_96 */ \
+ IPSEC_ALGS_ENTRY(AES_CTR, AES_XCBC_MAC_96), \
+ /* DPA_IPSEC_CIPHER_ALG_AES_CTR_HMAC_MD5_128 */ \
+ IPSEC_ALGS_ENTRY(AES_CTR, HMAC_MD5_128), \
+ /* DPA_IPSEC_CIPHER_ALG_AES_CTR_HMAC_SHA_160 */ \
+ IPSEC_ALGS_ENTRY(AES_CTR, HMAC_SHA1_160), \
+ /* DPA_IPSEC_CIPHER_ALG_AES_CTR_HMAC_SHA_256_128 */ \
+ IPSEC_ALGS_ENTRY(AES_CTR, HMAC_SHA2_256_128), \
+ /* DPA_IPSEC_CIPHER_ALG_AES_CTR_HMAC_SHA_384_192 */ \
+ IPSEC_ALGS_ENTRY(AES_CTR, HMAC_SHA2_384_192), \
+ /* DPA_IPSEC_CIPHER_ALG_AES_CTR_HMAC_SHA_512_256 */ \
+ IPSEC_ALGS_ENTRY(AES_CTR, HMAC_SHA2_512_256) \
+}
+
+#define GET_POL_TABLE_IDX(_proto, _ip_ver) \
+ ((_proto == IPPROTO_TCP) ? DPA_IPSEC_PROTO_TCP_##_ip_ver : \
+ (_proto == IPPROTO_UDP) ? DPA_IPSEC_PROTO_UDP_##_ip_ver : \
+ ((_proto == IPPROTO_ICMP) || \
+ (_proto == IPPROTO_ICMPV6)) ? DPA_IPSEC_PROTO_ICMP_##_ip_ver : \
+ (_proto == IPPROTO_SCTP) ? DPA_IPSEC_PROTO_SCTP_##_ip_ver : \
+ DPA_IPSEC_PROTO_ANY_##_ip_ver)
+
+#define DPA_IPSEC_ADDR_T_IPv4 4
+#define DPA_IPSEC_ADDR_T_IPv6 6
+
+#define IP_ADDR_TYPE_IPV4(_ipAddr) (_ipAddr.version == DPA_IPSEC_ADDR_T_IPv4)
+#define IP_ADDR(_ipAddr) \
+ (IP_ADDR_TYPE_IPV4(_ipAddr) ? \
+ (_ipAddr.addr.ipv4.byte) : (_ipAddr.addr.ipv6.byte))
+#define IP_ADDR_LEN(_ipAddr) \
+ (IP_ADDR_TYPE_IPV4(_ipAddr) ? \
+ (DPA_OFFLD_IPv4_ADDR_LEN_BYTES) : (DPA_OFFLD_IPv6_ADDR_LEN_BYTES))
+
+#define SET_BYTE_VAL_IN_ARRAY(_key, _off, _val) (_key[_off] = _val)
+#define SET_IP_PROTO_MASK(_mask, _off, _is_masked) \
+ (_mask[_off] = _is_masked ? 0x00 : 0xFF)
+#define SET_L4_PORT_MASK(_mask, _off, _val) \
+ (*(uint16_t *) &(_mask[_off]) = _val)
+
+#define TABLE_KEY_SIZE(_tbl_params) \
+ ((_tbl_params.type == DPA_CLS_TBL_HASH) ? \
+ tbl_params.hash_params.key_size : \
+ (_tbl_params.type == DPA_CLS_TBL_EXACT_MATCH) ? \
+ tbl_params.exact_match_params.key_size : 0)
+
+#define GET_SA_TABLE_IDX(_dest_addr, _use_udp_encap) \
+ (!IP_ADDR_TYPE_IPV4(_dest_addr) ? DPA_IPSEC_SA_IPV6 : \
+ _use_udp_encap ? DPA_IPSEC_SA_IPV4_NATT : DPA_IPSEC_SA_IPV4)
+
+#define SEQ_NUM_HI_MASK 0xFFFFFFFF00000000
+#define SEQ_NUM_LOW_MASK 0x00000000FFFFFFFF
+
+#define MAX_DPA_IPSEC_INSTANCES 10
+
+#define MAX_NUM_OF_SA 1000
+#define MAX_CIPHER_KEY_LEN 100
+#define MAX_AUTH_KEY_LEN 256
+#define MAX_BUFFER_POOL_ID 63
+
+/* number of FQs that will be created internally for each SA */
+#define NUM_FQS_PER_SA 2
+
+#define UDP_HEADER_LEN 8
+#define NEXT_HEADER_IS_IPv4 0x04
+
+#define WAIT4_FQ_EMPTY_TIMEOUT 100000 /* Time in microseconds */
+#define REKEY_SCHED_DELAY 100 /* Time in microseconds */
+
+#define INVALID_INB_FLOW_ID 0xFFFF
+
+/* The maximum length (in bytes) for the CAAM extra commands */
+#define MAX_EXTRA_DESC_COMMANDS (64 * sizeof(uint32_t))
+
+#define NIA_OPCODE_MASK 0x0F
+
+#define SEC_DEF_VER 40 /* like in P4080 */
+#define SEC_VER_5_3 53
+
+/* DPA IPSec Encryption & authentication algorithm identifiers */
+struct ipsec_alg_suite {
+ uint16_t enc_alg;
+ uint16_t auth_alg;
+};
+
+/* DPA IPsec PCD management operation types */
+enum mng_op_type {
+ MNG_OP_ADD = 0,
+ MNG_OP_REMOVE,
+ MNG_OP_MODIFY
+};
+
+/* DPA IPsec Cipher Parameters */
+struct cipher_params {
+ uint16_t cipher_type; /* Algorithm type as defined by SEC driver */
+ uint8_t *cipher_key; /* Address to the encryption key */
+ uint32_t cipher_key_len; /* Length in bytes of the normal key */
+};
+
+/* DPA IPsec Authentication Parameters */
+struct auth_params {
+ uint16_t auth_type; /* Algorithm type as defined by SEC driver */
+ uint8_t *auth_key; /* Address to the normal key */
+ uint32_t auth_key_len; /* Length in bytes of the normal key */
+ uint8_t *split_key; /* Address to the generated split key */
+ uint32_t split_key_len; /* Length in bytes of the split key */
+ uint32_t split_key_pad_len;/* Length in bytes of the padded split key */
+};
+
+/*
+ * DPA IPsec Security Association
+ * This structure will represent a SA. All SA structures will be allocated
+ * in the initialization part for performance reasons.
+ */
+struct dpa_ipsec_sa {
+ struct dpa_ipsec *dpa_ipsec; /* Pointer to DPA_IPSEC */
+ enum dpa_ipsec_direction sa_dir; /* SA direction */
+ uint32_t id; /* Used to index in circular queue*/
+ enum dpa_ipsec_cipher_alg alg_suite; /* DPA IPSEC algorithm suite */
+ struct cipher_params cipher_data; /* Encryption parameters */
+ struct auth_params auth_data; /* Authentication key parameters */
+ struct sec_descriptor *sec_desc_unaligned; /* Allocated at init time.
+ * When releasing memory only free
+ * this pointer and do not act on
+ * sec_desc address */
+ struct sec_descriptor *sec_desc; /* 64 byte aligned address where is
+ * computed the SEC 4.x descriptor
+ * according to the SA information.
+ * do not free this pointer! */
+ uint32_t *sec_desc_extra_cmds_unaligned;
+ uint32_t *sec_desc_extra_cmds; /* aligned to CORE cache line size */
+ bool sec_desc_extended; /* true if SEC descriptor is extended */
+ uint32_t *rjob_desc_unaligned;
+ uint32_t *rjob_desc; /* replacement job descriptor address */
+ uint64_t w_seq_num; /* RJD will write this SEQ number when modify */
+ uint64_t r_seq_num; /* RJD will read here the SEQ number for this SA */
+ bool read_seq_in_progress; /* true if a request came but a get not*/
+ uint32_t stats_offset; /* Offset of the statistics (in bytes) */
+ uint32_t stats_indx; /* Index of the lifetime counter in descriptor */
+ uint32_t next_cmd_indx; /* Next command index after SHD header */
+ uint8_t job_desc_len; /* Number of words CAAM Job Descriptor occupies
+ * form the CAAM Descriptor length
+ * MAX_CAAM_DESCSIZE */
+ bool enable_stats; /* Enable counting packets and bytes processed */
+ bool enable_extended_stats; /* Enable extended statistics per SA */
+ bool dscp_copy; /* Enable DSCP propagation support */
+ bool ecn_copy; /* Enable DSCP propagation support */
+ bool enable_dpovrd; /* Enable DECO Protocol Override Register */
+ struct qman_fq *to_sec_fq; /*From this Frame Queue SEC consumes frames*/
+ struct qman_fq *from_sec_fq; /*In this Frame Queue SEC will enqueue the
+ encryption/decryption result (FD). */
+ uint16_t sa_wqid; /* Work queue id in which the TO SEC FQ will be put */
+ uint8_t sa_bpid; /* Buffer pool id used by SEC for acquiring buffers,
+ comes from user. Default buffer pool 63 */
+ uint16_t sa_bufsize; /* Buffer pool buffer size */
+ uint32_t spi; /* IPsec Security parameter index */
+ struct dpa_offload_ip_address src_addr; /* Source IP address */
+ struct dpa_offload_ip_address dest_addr; /* Destination IP address */
+ uint16_t outbound_flowid; /* Value used to classify frames encrypted
+ with this SA */
+ bool use_udp_encap; /* NAT-T is activated for this SA. */
+ uint16_t udp_src_port; /* Source UDP port (for UDP encapsulated ESP)
+ Only for inbound SAs. */
+ uint16_t udp_dest_port; /* Destination UDP port (for UDP encap ESP)
+ Only for inbound SAs. */
+ uint16_t inbound_flowid; /* Value used for identifying an inbound SA. */
+ bool valid_flowid_entry; /* Valid entry in the flowID table */
+ int inbound_hash_entry; /* Entry in the hash table
+ corresponding to SPI extended key */
+ int inbound_sa_td; /* Descriptor for the SA lookup table in which this
+ * SA's key will be placed */
+ struct dpa_cls_tbl_action def_sa_action;
+ struct list_head policy_headlist; /* Head of the policy param list
+ used to store all the in/out policy parameters in order
+ to know how to remove the corresponding PCD entries */
+ struct dpa_cls_tbl_action policy_miss_action; /* Action for frames that
+ * fail inbound policy
+ * verification */
+ int em_inpol_td; /* Exact match table descriptor for inbound policy
+ check */
+ struct dpa_ipsec_sa *parent_sa; /* Address of the parent SA or NULL */
+ struct dpa_ipsec_sa *child_sa; /* Address of the child SA or NULL */
+ struct list_head sa_rekeying_node; /* For linking in SA rekeying list */
+ int used_sa_index; /* Index in the used_sa_ids vector of the dpa ipsec
+ instance this SA is part of. */
+ bool use_var_iphdr_len; /* Enable variable IP header length support */
+ int ipsec_hmd; /* Manip object for special IPSec functions */
+ dpa_ipsec_rekey_event_cb rekey_event_cb;
+ uint32_t l2_hdr_size; /* Size of the Ethernet header, including any
+ * VLAN information. */
+ uint8_t dscp_start; /* DSCP range start value */
+ uint8_t dscp_end; /* DSCP range end value */
+ struct mutex lock; /* Lock for this SA structure */
+};
+
+/*
+ * Parameters for inbound policy verification tables
+ * Global list lock - inpol_tables_lock from SA manager
+ */
+struct inpol_tbl {
+ void *cc_node; /* Cc node handle on top of which the table is created */
+ int td; /* Exact match table used for inbound policy verification */
+ bool used;
+ struct list_head table_list;
+};
+
+/*
+ * Parameters for IPsec special manipulations eg. DSCP/ECN update
+ * Global list lock - ipsec_manip_node_lock from SA manager
+ */
+struct ipsec_manip_node {
+ /*
+ * IPsec manip node handle; returned by FM_PCD_ManipNodeSet
+ */
+ void *hm;
+ bool used;
+ struct list_head ipsec_manip_node_list;
+};
+
+/* DPA IPSEC - Security Associations Management */
+struct dpa_ipsec_sa_mng {
+ struct dpa_ipsec_sa *sa; /* Array of SAs. Use indexes from sa_id_cq */
+ struct cq *sa_id_cq; /* Circular Queue with id's for SAs */
+ uint32_t max_num_sa; /* Maximum number of SAs */
+
+ /* Circular queue with flow IDs for identifying an inbound SA */
+ struct cq *inbound_flowid_cq;
+
+ /* Inbound policy verification tables key size.*/
+ uint8_t inpol_key_size;
+
+ /*
+ * Head list of tables used for inbound
+ * policy verification. List of inpol_tbl structures.
+ * Populated only if inbound policy verification is enabled
+ */
+ struct list_head inpol_tables;
+ struct mutex inpol_tables_lock; /* List lock inbound policy table */
+
+ /* ipsec_manip_node head list */
+ struct list_head ipsec_manip_node_list;
+
+ /* Lock for IPsec manip node list */
+ struct mutex ipsec_manip_node_lock;
+ struct delayed_work sa_rekeying_work;
+
+ /* Work queue used to defer the work to be done during rekeying */
+ struct workqueue_struct *sa_rekeying_wq;
+
+ /* Head list with inbound SA's currently in the rekeying process */
+ struct list_head sa_rekeying_headlist;
+ struct mutex sa_rekeying_headlist_lock; /* Lock for the rekeying list */
+ struct cq *fqid_cq; /* Circular queue with FQIDs for internal FQs */
+};
+
+/* DPA IPsec - Control Block */
+struct dpa_ipsec {
+ int id; /* the instance ID */
+ /* Configuration parameters as provided in dap_ipsec_config_and_init */
+ struct dpa_ipsec_params config;
+ struct dpa_ipsec_sa_mng sa_mng; /* Internal DPA IPsec SA manager */
+ int *used_sa_ids; /* SA IDs used by this DPA IPsec instance */
+ int num_used_sas; /* The current number of sa's used by this instance*/
+ int sec_era; /* SEC ERA information */
+ int sec_ver; /* SEC version information */
+ struct device *jrdev; /* Job ring device */
+ atomic_t ref;
+ atomic_t valid;
+ struct mutex lock; /* Lock for this dpa_ipsec instance */
+};
+
+struct hmd_entry {
+ int hmd;
+ bool hmd_special_op;
+};
+
+/* DPA IPSEC - Security Policy Parameter Entry */
+struct dpa_ipsec_policy_entry {
+ /* Policy parameters */
+ struct dpa_ipsec_policy_params pol_params;
+
+ /* Entry id array that is set by dpa_classif_table_insert_entry */
+ int *entry_id;
+
+ /*
+ * Header manip for IPSec special operation or
+ * if none Header manip for fragmentation or
+ * manipulation
+ */
+ int hmd;
+
+ /*
+ * true is hmd is IPSec special operation, false
+ * is hmd refers to an outside manip object
+ */
+ bool hmd_special_op;
+
+ /* Node in linked list */
+ struct list_head node;
+};
+
+void sa_rekeying_work_func(struct work_struct *work);
+
+static inline int sa_currently_on_rekeying_list(struct dpa_ipsec_sa *sa)
+{
+ return (sa->sa_rekeying_node.next == LIST_POISON1 &&
+ sa->sa_rekeying_node.prev == LIST_POISON2) ? FALSE : TRUE;
+}
+
+static inline int sa_currently_in_rekeying(struct dpa_ipsec_sa *sa)
+{
+ return (sa->parent_sa || sa->child_sa) ? TRUE : FALSE;
+}
+
+static inline int sa_is_parent(struct dpa_ipsec_sa *sa)
+{
+ return sa->child_sa ? TRUE : FALSE;
+}
+
+static inline int sa_is_child(struct dpa_ipsec_sa *sa)
+{
+ return sa->parent_sa ? TRUE : FALSE;
+}
+
+static inline int sa_is_single(struct dpa_ipsec_sa *sa)
+{
+ return (!sa_is_parent(sa) && !sa_is_child(sa)) ? TRUE : FALSE;
+}
+
+static inline int sa_is_outbound(struct dpa_ipsec_sa *sa)
+{
+ return sa->sa_dir == DPA_IPSEC_OUTBOUND ? TRUE : FALSE;
+}
+
+static inline int sa_is_inbound(struct dpa_ipsec_sa *sa)
+{
+ return sa->sa_dir == DPA_IPSEC_INBOUND ? TRUE : FALSE;
+}
+
+static inline int schedule_sa(struct dpa_ipsec_sa *sa)
+{
+ enum qman_fq_state state;
+ u32 flags;
+ int err;
+
+ qman_fq_state(sa->to_sec_fq, &state, &flags);
+ if (state == qman_fq_state_parked) {
+ err = qman_schedule_fq(sa->to_sec_fq);
+ if (unlikely(err < 0))
+ return -EIO;
+ return 0;
+ }
+
+ return state == qman_fq_state_sched ? 0 : -EPERM;
+}
+
+static inline void rekey_err_report(dpa_ipsec_rekey_event_cb rekey_event_cb,
+ int dpa_ipsec_id, uint32_t sa_id, int err)
+{
+ if (rekey_event_cb)
+ rekey_event_cb(dpa_ipsec_id, sa_id, err);
+}
+
+/* If index table is invalid the IPsec action per inbound SA will be ignored */
+static inline int ignore_post_ipsec_action(struct dpa_ipsec *dpa_ipsec)
+{
+ if (dpa_ipsec->config.post_sec_in_params.dpa_cls_td > 0)
+ return FALSE;
+ return TRUE;
+}
+
+static inline void instance_refinc(struct dpa_ipsec *instance)
+{
+ BUG_ON(atomic_read(&instance->ref) <= 0);
+ atomic_inc(&instance->ref);
+}
+
+static inline void instance_refdec(struct dpa_ipsec *instance)
+{
+ atomic_dec(&instance->ref);
+}
+
+static inline int sa_id_to_instance_id(int sa_id)
+{
+ return sa_id / MAX_NUM_OF_SA;
+}
+
+/* SA index refers to the position of SA with id sa_id in the sa_mng.sa */
+static inline int sa_id_to_sa_index(int sa_id)
+{
+ if (sa_id_to_instance_id(sa_id) == 0)
+ return sa_id;
+
+ return sa_id % (sa_id_to_instance_id(sa_id) * MAX_NUM_OF_SA);
+}
+
+/* Check if SA ID is in possible range */
+static inline int valid_sa_id(int sa_id)
+{
+ if (sa_id < 0 || sa_id >= MAX_DPA_IPSEC_INSTANCES * MAX_NUM_OF_SA) {
+ log_err("Invalid SA id %d provided\n", sa_id);
+ return false;
+ }
+
+ return true;
+}
+
+static inline int valid_instance_id(int instance_id)
+{
+ if (instance_id < 0 || instance_id >= MAX_DPA_IPSEC_INSTANCES) {
+ log_err("Invalid DPA IPsec instance ID\n");
+ return false;
+ }
+
+ return true;
+}
+
+/* Check if SA is being used i.e created */
+static inline int sa_in_use(struct dpa_ipsec_sa *sa)
+{
+ if (sa->used_sa_index == -1)
+ return false;
+
+ return true;
+}
+
+#endif /* __DPA_IPSEC_H__ */
diff --git a/drivers/staging/fsl_dpa_offload/dpa_ipsec_desc.c b/drivers/staging/fsl_dpa_offload/dpa_ipsec_desc.c
new file mode 100644
index 0000000..c233aaa
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dpa_ipsec_desc.c
@@ -0,0 +1,2089 @@
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/version.h>
+#include <linux/platform_device.h>
+
+#include "compat.h"
+#include "desc.h"
+#include "error.h"
+#include "jr.h"
+#include "ctrl.h"
+
+#include "dpa_ipsec_desc.h"
+
+static struct device *get_jrdev(struct dpa_ipsec *dpa_ipsec);
+
+/* If SEC ERA is unknown default to this value */
+#define SEC_DEF_ERA 2 /* like in P4080 */
+
+/*
+ * to retrieve a 256 byte aligned buffer address from an address
+ * we need to copy only the first 7 bytes
+ */
+#define ALIGNED_PTR_ADDRESS_SZ (CAAM_PTR_SZ - 1)
+
+#define JOB_DESC_HDR_LEN CAAM_CMD_SZ
+#define SEQ_OUT_PTR_SGF_MASK 0x01000000;
+/* relative offset where the input pointer should be updated in the descriptor*/
+#define IN_PTR_REL_OFF 4 /* words from current location */
+/* dummy pointer value */
+#define DUMMY_PTR_VAL 0x00000000
+#define PTR_LEN 2 /* Descriptor is created only for 8 byte
+ * pointer. PTR_LEN is in words. */
+
+static const struct of_device_id sec_jr_match[] = {
+ {
+ .compatible = "fsl,sec-v4.0-job-ring"
+ }
+};
+
+/* retrieve and store SEC information */
+int get_sec_info(struct dpa_ipsec *dpa_ipsec)
+{
+ struct device_node *sec_node;
+ const u32 *sec_era;
+ int prop_size;
+
+ sec_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v5.3");
+ if (sec_node)
+ dpa_ipsec->sec_ver = SEC_VER_5_3;
+ else {
+ dpa_ipsec->sec_ver = SEC_DEF_VER;
+ sec_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+ if (!sec_node) {
+ log_err("Can't find device node for SEC! Check device tree!\n");
+ return -ENODEV;
+ }
+ }
+
+ sec_era = of_get_property(sec_node, "fsl,sec-era", &prop_size);
+ if (sec_era && prop_size == sizeof(*sec_era) && *sec_era > 0)
+ dpa_ipsec->sec_era = *sec_era;
+ else
+ dpa_ipsec->sec_era = SEC_DEF_ERA;
+
+ dpa_ipsec->jrdev = get_jrdev(dpa_ipsec);
+ if (!dpa_ipsec->jrdev)
+ return -ENODEV;
+
+ return 0;
+}
+
+
+static struct device *get_jrdev(struct dpa_ipsec *dpa_ipsec)
+{
+ struct device_node *sec_jr_node;
+ struct platform_device *sec_of_jr_dev;
+
+ if (dpa_ipsec->jrdev)
+ return dpa_ipsec->jrdev;
+
+ sec_jr_node = of_find_matching_node(NULL, &sec_jr_match[0]);
+ if (!sec_jr_node) {
+ log_err("Couln't find the device_node SEC job-ring, check the device tree\n");
+ return NULL;
+ }
+
+ sec_of_jr_dev = of_find_device_by_node(sec_jr_node);
+ if (!sec_of_jr_dev) {
+ log_err("SEC job-ring of_device null\n");
+ return NULL;
+ }
+
+ return &sec_of_jr_dev->dev;
+}
+
+static inline u32 get_ipsec_op_type(enum dpa_ipsec_direction sa_dir)
+{
+ return sa_dir == DPA_IPSEC_INBOUND ? OP_TYPE_DECAP_PROTOCOL :
+ OP_TYPE_ENCAP_PROTOCOL;
+}
+
+static inline int get_cipher_params(enum dpa_ipsec_cipher_alg cipher_alg,
+ uint32_t *iv_length, uint32_t *icv_length,
+ uint32_t *max_pad_length)
+{
+ switch (cipher_alg) {
+ case DPA_IPSEC_CIPHER_ALG_3DES_CBC_HMAC_96_MD5_128:
+ case DPA_IPSEC_CIPHER_ALG_3DES_CBC_HMAC_96_SHA_160:
+ *iv_length = 8;
+ *max_pad_length = 8;
+ *icv_length = 12;
+ break;
+ case DPA_IPSEC_CIPHER_ALG_3DES_CBC_HMAC_MD5_128:
+ *iv_length = 8;
+ *max_pad_length = 8;
+ *icv_length = 16;
+ break;
+ case DPA_IPSEC_CIPHER_ALG_3DES_CBC_HMAC_SHA_160:
+ case DPA_IPSEC_CIPHER_ALG_3DES_CBC_HMAC_SHA_256_128:
+ *iv_length = 8;
+ *max_pad_length = 8;
+ *icv_length = 20;
+ break;
+ case DPA_IPSEC_CIPHER_ALG_3DES_CBC_HMAC_SHA_384_192:
+ *iv_length = 8;
+ *max_pad_length = 8;
+ *icv_length = 24;
+ break;
+ case DPA_IPSEC_CIPHER_ALG_3DES_CBC_HMAC_SHA_512_256:
+ *iv_length = 8;
+ *max_pad_length = 8;
+ *icv_length = 32;
+ break;
+ case DPA_IPSEC_CIPHER_ALG_AES_CBC_HMAC_96_MD5_128:
+ case DPA_IPSEC_CIPHER_ALG_AES_CBC_HMAC_96_SHA_160:
+ case DPA_IPSEC_CIPHER_ALG_AES_CBC_AES_XCBC_MAC_96:
+ *iv_length = 16;
+ *max_pad_length = 16;
+ *icv_length = 12;
+ break;
+ case DPA_IPSEC_CIPHER_ALG_AES_CBC_HMAC_MD5_128:
+ case DPA_IPSEC_CIPHER_ALG_AES_CBC_HMAC_SHA_256_128:
+ *iv_length = 16;
+ *max_pad_length = 16;
+ *icv_length = 16;
+ break;
+ case DPA_IPSEC_CIPHER_ALG_AES_CBC_HMAC_SHA_160:
+ *iv_length = 16;
+ *max_pad_length = 16;
+ *icv_length = 20;
+ break;
+ case DPA_IPSEC_CIPHER_ALG_AES_CBC_HMAC_SHA_384_192:
+ *iv_length = 16;
+ *max_pad_length = 16;
+ *icv_length = 24;
+ break;
+ case DPA_IPSEC_CIPHER_ALG_AES_CBC_HMAC_SHA_512_256:
+ *iv_length = 16;
+ *max_pad_length = 16;
+ *icv_length = 32;
+ break;
+ case DPA_IPSEC_CIPHER_ALG_AES_CTR_HMAC_96_MD5_128:
+ case DPA_IPSEC_CIPHER_ALG_AES_CTR_HMAC_96_SHA_160:
+ case DPA_IPSEC_CIPHER_ALG_AES_CTR_AES_XCBC_MAC_96:
+ *iv_length = 16;
+ *max_pad_length = 16;
+ *icv_length = 12;
+ break;
+ case DPA_IPSEC_CIPHER_ALG_AES_CTR_HMAC_MD5_128:
+ case DPA_IPSEC_CIPHER_ALG_AES_CTR_HMAC_SHA_256_128:
+ *iv_length = 8;
+ *max_pad_length = 4;
+ *icv_length = 16;
+ break;
+ case DPA_IPSEC_CIPHER_ALG_AES_CTR_HMAC_SHA_160:
+ *iv_length = 8;
+ *max_pad_length = 4;
+ *icv_length = 20;
+ break;
+ case DPA_IPSEC_CIPHER_ALG_AES_CTR_HMAC_SHA_384_192:
+ *iv_length = 8;
+ *max_pad_length = 4;
+ *icv_length = 24;
+ break;
+ case DPA_IPSEC_CIPHER_ALG_AES_CTR_HMAC_SHA_512_256:
+ *iv_length = 8;
+ *max_pad_length = 4;
+ *icv_length = 32;
+ break;
+ default:
+ *iv_length = 0;
+ *icv_length = 0;
+ *max_pad_length = 0;
+ log_err("Unsupported cipher suite %d\n", cipher_alg);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static inline void build_stats_descriptor_part(struct dpa_ipsec_sa *sa,
+ size_t pdb_len)
+{
+ u32 *desc, *padding_jump;
+ u32 block_size, stats_offset, offset;
+
+ BUG_ON(!sa);
+
+ desc = (u32 *) sa->sec_desc->desc;
+
+ stats_offset = sizeof(sa->sec_desc->hdr_word) + pdb_len -
+ DPA_IPSEC_STATS_LEN * sizeof(u32);
+ sa->stats_offset = stats_offset;
+ memset((u8 *)desc + stats_offset, 0, DPA_IPSEC_STATS_LEN * sizeof(u32));
+
+ /* Copy from descriptor to MATH REG 0 the current statistics */
+ append_move(desc, MOVE_SRC_DESCBUF | MOVE_DEST_MATH0 | MOVE_WAITCOMP |
+ (stats_offset << MOVE_OFFSET_SHIFT) | sizeof(u64));
+
+ /* Load 1 in MATH REG 1 */
+ append_math_add(desc, REG1, ZERO, ONE, MATH_LEN_8BYTE);
+
+ /*
+ * Perform 32-bit left shift of DEST and concatenate with left 32 bits
+ * of SRC1 i.e MATH REG 1 = 0x00000001_00000000
+ */
+ append_math_shld(desc, REG1, REG0, REG1, MATH_LEN_8BYTE);
+
+ if (sa->sa_dir == DPA_IPSEC_INBOUND) {
+ /* MATH REG 2 = Sequence in length */
+ append_math_add_imm_u32(desc, REG2, SEQINLEN, IMM, 0);
+ goto after_padding;
+ } else {
+ /* MATH REG 2 = Sequence in length + 2 */
+ append_math_add_imm_u32(desc, REG2, SEQINLEN, IMM, 2);
+ }
+
+ switch (sa->cipher_data.cipher_type) {
+ case OP_PCL_IPSEC_3DES:
+ block_size = 8; /* block size in bytes */
+ break;
+ case OP_PCL_IPSEC_AES_CBC:
+ case OP_PCL_IPSEC_AES_CTR:
+ case OP_PCL_IPSEC_AES_XTS:
+ case OP_PCL_IPSEC_AES_CCM8:
+ case OP_PCL_IPSEC_AES_CCM12:
+ case OP_PCL_IPSEC_AES_CCM16:
+ case OP_PCL_IPSEC_AES_GCM8:
+ case OP_PCL_IPSEC_AES_GCM12:
+ case OP_PCL_IPSEC_AES_GCM16:
+ block_size = 16; /* block size in bytes */
+ break;
+ default:
+ pr_crit("Invalid cipher algorithm for SA %d\n", sa->id);
+ return;
+ }
+
+ /* Adding padding to byte counter */
+ append_math_and_imm_u32(desc, REG3, REG2, IMM, block_size - 1);
+
+ /* Previous operation result is 0 i.e padding added to bytes count */
+ padding_jump = append_jump(desc, CLASS_BOTH | JUMP_TEST_ALL |
+ JUMP_COND_MATH_Z);
+
+ /* MATH REG 2 = MATH REG 2 + 1 */
+ append_math_add(desc, REG2, REG2, ONE, MATH_LEN_8BYTE);
+
+ /* jump back to adding padding i.e jump back 4 words */
+ offset = (-4) & 0x000000FF;
+ append_jump(desc, (offset << JUMP_OFFSET_SHIFT));
+
+ set_jump_tgt_here(desc, padding_jump);
+ /* Done adding padding to byte counter */
+
+after_padding:
+ /* MATH REG 1 = MATH REG 1 + MATH REG 2 */
+ append_math_add(desc, REG1, REG1, REG2, MATH_LEN_8BYTE);
+
+ /* MATH REG0 = MATH REG 0 + MATH REG1 */
+ append_math_add(desc, REG0, REG0, REG1, MATH_LEN_8BYTE);
+
+ /* Store in the descriptor but not in external memory */
+ append_move(desc, MOVE_SRC_MATH0 | MOVE_DEST_DESCBUF | MOVE_WAITCOMP |
+ (stats_offset << MOVE_OFFSET_SHIFT) | sizeof(u64));
+}
+
+static inline void save_stats_in_external_mem(struct dpa_ipsec_sa *sa)
+{
+ u32 *desc;
+ u32 stats_offset;
+
+ desc = (u32 *) sa->sec_desc->desc;
+
+ /* statistics offset = predetermined offset */
+ stats_offset = sa->stats_offset;
+
+ /* Store command: in the case of the Descriptor Buffer the length
+ * is specified in 4-byte words, but in all other cases the length
+ * is specified in bytes. Offset in 4 byte words */
+ append_store(desc, 0, DPA_IPSEC_STATS_LEN, LDST_CLASS_DECO |
+ ((stats_offset / 4) << LDST_OFFSET_SHIFT) |
+ LDST_SRCDST_WORD_DESCBUF_SHARED);
+
+ /* Jump with CALM to be sure previous operation was finished */
+ append_jump(desc, JUMP_COND_CALM | (1 << JUMP_OFFSET_SHIFT));
+}
+
+/* insert a cmd in the desc at a given index and optionally update desc len */
+static void insert_sec_cmd(uint32_t *desc, uint32_t index, uint32_t cmd,
+ bool update_len)
+{
+ uint32_t *desc_cmd;
+
+ desc_cmd = desc + index;
+ *desc_cmd = cmd;
+
+ if (update_len)
+ (*desc)++;
+}
+
+/* insert cmds for SEQ_IN/OUT_PTR copy with specified offset (shr_desc_len) */
+static void insert_ptr_copy_cmds(uint32_t *desc, uint32_t index,
+ uint32_t shr_desc_len, bool update_desc_len)
+{
+ uint32_t cmd, off, len;
+
+ /*
+ * insert the commands at the specified index
+ * if index == 0 insert at next position in desc
+ */
+ if (!index)
+ index = desc_len(desc);
+
+ /*
+ * move out ptr (from job desc) to math reg 1 & 2, except the last byte;
+ * assuming all buffers are 256 bits aligned, setting the last address
+ * byte to 0x00 will give the buffer address;
+ */
+ off = CAAM_PTR_SZ;
+ off = (shr_desc_len * CAAM_CMD_SZ + off) << MOVE_OFFSET_SHIFT;
+ len = CAAM_CMD_SZ + JOB_DESC_HDR_LEN + ALIGNED_PTR_ADDRESS_SZ;
+ cmd = CMD_MOVE | MOVE_SRC_DESCBUF | MOVE_DEST_MATH1 | off | len;
+ insert_sec_cmd(desc, index, cmd, update_desc_len);
+
+ /*
+ * move in ptr (from job desc) to math reg 0, except the last byte;
+ * assuming all buffers are 256 bits aligned, setting the last address
+ * byte to 0x00 will give the buffer address;
+ */
+ off = JOB_DESC_HDR_LEN + 3 * CAAM_CMD_SZ + 2 * CAAM_PTR_SZ;
+ off = (shr_desc_len * CAAM_CMD_SZ + off) << MOVE_OFFSET_SHIFT;
+ len = ALIGNED_PTR_ADDRESS_SZ;
+ cmd = CMD_MOVE | MOVE_SRC_DESCBUF | MOVE_DEST_MATH0 | off | len;
+ insert_sec_cmd(desc, ++index, cmd, update_desc_len);
+}
+
+/* build the command set for copying the frame meta data */
+static void build_meta_data_desc_cmds(struct dpa_ipsec_sa *sa,
+ unsigned int sec_era,
+ unsigned int move_size)
+{
+ uint32_t *desc, off, len, opt, *no_sg_jump;
+ uint32_t sg_mask = SEQ_OUT_PTR_SGF_MASK;
+
+ BUG_ON(!sa);
+
+ desc = (uint32_t *) sa->sec_desc->desc;
+
+ /* insert cmds to copy SEQ_IN/OUT_PTR - offset will be updated later */
+ insert_ptr_copy_cmds(desc, 0, 0, true);
+
+ /* detect & handle scatter / gather frames */
+
+ /*
+ * the SEQ OUT PTR command is now in math reg 1, so the SGF bit can be
+ * checked using a math command;
+ */
+ append_math_and_imm_u32(desc, NONE, REG1, IMM, sg_mask);
+
+ opt = CLASS_NONE | JUMP_TYPE_LOCAL | JUMP_COND_MATH_Z | JUMP_TEST_ALL;
+ no_sg_jump = append_jump(desc, opt);
+
+ if (sec_era == 2) {
+ /* disable iNFO FIFO entries for p4080rev2 & ??? */
+ len = 0x10 << LDST_LEN_SHIFT;
+ append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO | len);
+
+ /*
+ * load in IN FIFO the S/G Entry located in the 5th reg after
+ * MATH3 -> offset = sizeof(GT_REG) * 4 + offset_math3_to_GT_REG
+ * len = sizeof(S/G entry)
+ */
+ opt = MOVE_SRC_MATH3 | MOVE_DEST_CLASS1INFIFO;
+ off = 127 << MOVE_OFFSET_SHIFT;
+ len = 49 << MOVE_LEN_SHIFT;
+ append_move(desc, opt | off | len);
+
+ /* enable iNFO FIFO entries */
+ append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
+ } else {
+ /* ????? */
+ opt = LDST_IMM | LDST_CLASS_DECO | LDST_SRCDST_WORD_DECOCTRL;
+ len = 0x10 << LDST_LEN_SHIFT;
+ append_cmd(desc, CMD_LOAD | opt | len);
+
+ /*
+ * load in IN FIFO the S/G Entry located in the 5th reg after
+ * MATH3 -> offset = sizeof(GT_REG) * 4 + offset_math3_to_GT_REG
+ * len = sizeof(S/G entry)
+ */
+ opt = MOVE_SRC_MATH3 | MOVE_DEST_INFIFO_NOINFO;
+ off = 127 << MOVE_OFFSET_SHIFT;
+ len = 49 << MOVE_LEN_SHIFT;
+ append_move(desc, opt | off | len);
+ }
+
+ /*
+ * throw away the first part of the S/G table and keep only the buffer
+ * address;
+ * offset = undefined memory after MATH3;
+ * len =
+ */
+ opt = MOVE_SRC_INFIFO | MOVE_DEST_MATH3;
+ off = 8 << MOVE_OFFSET_SHIFT;
+ len = 41 << MOVE_LEN_SHIFT;
+ append_move(desc, opt | off | len);
+
+ /* put the buffer address (still in the IN FIFO) in MATH2 */
+ opt = MOVE_SRC_INFIFO | MOVE_DEST_MATH2;
+ off = 0 << MOVE_OFFSET_SHIFT;
+ len = 8 << MOVE_LEN_SHIFT;
+ append_move(desc, opt | off | len);
+
+ /* update no S/G jump location */
+ set_jump_tgt_here(desc, no_sg_jump);
+
+ /* save input pointer to predefined location in descriptor */
+ opt = MOVE_SRC_MATH0 | MOVE_DEST_DESCBUF;
+ off = ((desc_len(desc) + IN_PTR_REL_OFF) << 2) << MOVE_OFFSET_SHIFT;
+ len = ALIGNED_PTR_ADDRESS_SZ << MOVE_LEN_SHIFT;
+ append_move(desc, opt | off | len);
+
+ /* save output pointer to predefined location in descriptor */
+ opt = MOVE_WAITCOMP | MOVE_SRC_MATH2 | MOVE_DEST_DESCBUF;
+ off += (CAAM_PTR_SZ + 2 * CAAM_CMD_SZ) << MOVE_OFFSET_SHIFT;
+ len = ALIGNED_PTR_ADDRESS_SZ << MOVE_LEN_SHIFT;
+ append_move(desc, opt | off | len);
+
+ /* fix LIODN */
+ opt = LDST_IMM | LDST_CLASS_DECO | LDST_SRCDST_WORD_DECOCTRL;
+ off = 0x40 << LDST_OFFSET_SHIFT; /* SEQ LIODN */
+ append_cmd(desc, CMD_LOAD | opt | off);
+
+ /* actual move commands - pointers will be updated at runtime */
+
+ /* load the data to be moved - insert dummy pointer */
+ opt = LDST_CLASS_2_CCB | LDST_SRCDST_WORD_CLASS_CTX;
+ off = 0 << LDST_OFFSET_SHIFT;
+ len = move_size << LDST_LEN_SHIFT;
+ append_load(desc, DUMMY_PTR_VAL, len, opt | off);
+
+ /* wait for completion */
+ opt = JUMP_COND_CALM | (1 << JUMP_OFFSET_SHIFT);
+ append_jump(desc, opt);
+
+ /* store the data to the output fifo - insert dummy pointer */
+ opt = LDST_CLASS_2_CCB | LDST_SRCDST_WORD_CLASS_CTX;
+ off = 0 << LDST_OFFSET_SHIFT;
+ len = move_size << LDST_LEN_SHIFT;
+ append_store(desc, DUMMY_PTR_VAL, len, opt | off);
+
+ /* fix LIODN */
+ opt = LDST_IMM | LDST_CLASS_DECO | LDST_SRCDST_WORD_DECOCTRL;
+ off = 0x80 << LDST_OFFSET_SHIFT; /* NON_SEQ LIODN */
+ append_cmd(desc, CMD_LOAD | opt | off);
+}
+
+int build_shared_descriptor(struct dpa_ipsec_sa *sa,
+ dma_addr_t auth_key_dma,
+ dma_addr_t crypto_key_dma, u32 bytes_to_copy)
+{
+ uint32_t *desc, *key_jump_cmd, copy_ptr_index = 0;
+ int opthdrsz;
+ size_t pdb_len = 0;
+
+ desc = (u32 *) sa->sec_desc->desc;
+
+ /* Reserve 2 words for statistics */
+ if (sa->enable_stats)
+ pdb_len = DPA_IPSEC_STATS_LEN * sizeof(u32);
+
+ if (sa->sa_dir == DPA_IPSEC_OUTBOUND) {
+ /* Compute optional header size, rounded up to descriptor
+ * word size */
+ opthdrsz = (sa->sec_desc->pdb_en.ip_hdr_len + 3) & ~3;
+ pdb_len += sizeof(struct ipsec_encap_pdb) + opthdrsz;
+ init_sh_desc_pdb(desc, HDR_SAVECTX | HDR_SHARE_SERIAL, pdb_len);
+ } else {
+ pdb_len += sizeof(struct ipsec_decap_pdb);
+ init_sh_desc_pdb(desc, HDR_SAVECTX | HDR_SHARE_SERIAL, pdb_len);
+ }
+
+ /* Key jump */
+ key_jump_cmd = append_jump(desc, CLASS_BOTH | JUMP_TEST_ALL |
+ JUMP_COND_SHRD | JUMP_COND_SELF);
+
+ /* check whether a split of a normal key is used */
+ if (sa->auth_data.split_key_len)
+ /* Append split authentication key */
+ append_key(desc, auth_key_dma, sa->auth_data.split_key_len,
+ CLASS_2 | KEY_ENC | KEY_DEST_MDHA_SPLIT);
+ else
+ /* Append normal authentication key */
+ append_key(desc, auth_key_dma, sa->auth_data.auth_key_len,
+ CLASS_2 | KEY_DEST_CLASS_REG);
+
+ /* Append cipher key */
+ append_key(desc, crypto_key_dma, sa->cipher_data.cipher_key_len,
+ CLASS_1 | KEY_DEST_CLASS_REG);
+
+ set_jump_tgt_here(desc, key_jump_cmd);
+
+ /* copy frame meta data (IC) to enable DSCP / ECN propagation */
+ if (sa->dscp_copy || sa->ecn_copy) {
+ /* save location of ptr copy commands to update offset later */
+ copy_ptr_index = desc_len(desc);
+ build_meta_data_desc_cmds(sa, sa->dpa_ipsec->sec_era, 64);
+ }
+
+ if (bytes_to_copy == 0)
+ goto skip_byte_copy;
+
+ /* Copy L2 header from the original packet to the outer packet */
+
+ /* ld: deco-deco-ctrl len=0 offs=8 imm -auto-nfifo-entries */
+ append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
+
+ /* seqfifold: both msgdata-last2-last1-flush1 len=4 */
+ append_seq_fifo_load(desc, bytes_to_copy, FIFOLD_TYPE_MSG |
+ FIFOLD_CLASS_BOTH | FIFOLD_TYPE_LAST1 |
+ FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_FLUSH1);
+
+ /* ld: deco-deco-ctrl len=0 offs=4 imm +auto-nfifo-entries */
+ append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
+
+ /* move: ififo->deco-alnblk -> ofifo, len=4 */
+ append_move(desc, MOVE_SRC_INFIFO | MOVE_DEST_OUTFIFO | bytes_to_copy);
+
+ /* seqfifostr: msgdata len=4 */
+ append_seq_fifo_store(desc, FIFOST_TYPE_MESSAGE_DATA, bytes_to_copy);
+
+ /* Done coping L2 header from the original packet to the outer packet */
+
+skip_byte_copy:
+
+ if (sa->enable_stats)
+ build_stats_descriptor_part(sa, pdb_len);
+
+ /* Protocol specific operation */
+ append_operation(desc, OP_PCLID_IPSEC |
+ get_ipsec_op_type(sa->sa_dir) |
+ sa->cipher_data.cipher_type | sa->auth_data.auth_type);
+
+ if (sa->enable_stats)
+ save_stats_in_external_mem(sa);
+
+ if (sa->dscp_copy || sa->ecn_copy)
+ /* insert cmds to copy SEQ_IN/OUT_PTR - with updated offset */
+ insert_ptr_copy_cmds(desc, copy_ptr_index,
+ desc_len(desc), false);
+
+ if (desc_len(desc) >= MAX_CAAM_SHARED_DESCSIZE) {
+ if (sa->enable_stats)
+ memset((uint8_t *)desc + sa->stats_offset, 0,
+ MAX_CAAM_DESCSIZE * sizeof(u32) -
+ sa->stats_offset);
+ return -EPERM;
+ }
+
+ return 0;
+}
+
+/* Move size should be set to 64 bytes */
+int built_encap_extra_material(struct dpa_ipsec_sa *sa,
+ dma_addr_t auth_key_dma,
+ dma_addr_t crypto_key_dma,
+ unsigned int move_size)
+{
+ uint32_t *extra_cmds, *padding_jump, *key_jump_cmd;
+ uint32_t len, off_b, off_w, off, opt;
+ unsigned char job_desc_len, block_size;
+
+ /*
+ * sec_desc_extra_cmds is the address were the first SEC extra command
+ * is located, from here SEC will overwrite Job descriptor part. Need
+ * to insert a dummy command because the LINUX CAAM API uses first word
+ * for storing the length of the descriptor.
+ */
+ extra_cmds = sa->sec_desc_extra_cmds - 1;
+
+ /*
+ * Dummy command - will not be executed at all. Only for setting to 1
+ * the length of the extra_cmds descriptor so that first extra material
+ * command will be located exactly at sec_desc_extra_cmds address.
+ */
+ append_cmd(extra_cmds, 0xdead0000);
+
+ /* Start Extra Material Group 1 */
+ /* Load from the input address 64 bytes into internal register */
+ /* load the data to be moved - insert dummy pointer */
+ opt = LDST_CLASS_2_CCB | LDST_SRCDST_WORD_CLASS_CTX;
+ off = 0 << LDST_OFFSET_SHIFT;
+ len = move_size << LDST_LEN_SHIFT;
+ append_load(extra_cmds, DUMMY_PTR_VAL, len, opt | off);
+
+ /* Wait to finish previous operation */
+ opt = JUMP_COND_CALM | (1 << JUMP_OFFSET_SHIFT);
+ append_jump(extra_cmds, opt);
+
+ /* Store the data to the output FIFO - insert dummy pointer */
+ opt = LDST_CLASS_2_CCB | LDST_SRCDST_WORD_CLASS_CTX;
+ off = 0 << LDST_OFFSET_SHIFT;
+ len = move_size << LDST_LEN_SHIFT;
+ append_store(extra_cmds, DUMMY_PTR_VAL, len, opt | off);
+
+ /* Fix LIODN */
+ opt = LDST_IMM | LDST_CLASS_DECO | LDST_SRCDST_WORD_DECOCTRL;
+ off = 0x80 << LDST_OFFSET_SHIFT; /* NON_SEQ LIODN */
+ append_cmd(extra_cmds, CMD_LOAD | opt | off);
+
+ /* MATH0 += 1 (packet counter) */
+ append_math_add(extra_cmds, REG0, REG0, ONE, MATH_LEN_8BYTE);
+
+ /* Overwrite the job-desc location (word 51 or 53) with the second
+ * group (10 words) */
+ job_desc_len = sa->job_desc_len;
+ opt = MOVE_SRC_INFIFO | MOVE_DEST_DESCBUF | MOVE_WAITCOMP;
+ off_w = MAX_CAAM_DESCSIZE - job_desc_len;
+ off_b = off_w * sizeof(uint32_t); /* calculate off in bytes */
+ len = (10 * sizeof(uint32_t)) << MOVE_LEN_SHIFT;
+ append_move(extra_cmds, opt | (off_b << MOVE_OFFSET_SHIFT) | len);
+
+ /*
+ * Jump to the beginning of the JOB Descriptor to start executing
+ * the extra material group 2
+ */
+ append_cmd(extra_cmds, 0xa00000f6);
+
+ /* End of Extra Material Group 1 */
+
+ /* Start Extra Material Group 2 */
+ /* MATH REG 2 = Sequence in length + 2; 2 for pad-len and NH field */
+ append_math_add_imm_u32(extra_cmds, REG2, SEQINLEN, IMM, 2);
+
+ switch (sa->cipher_data.cipher_type) {
+ case OP_PCL_IPSEC_3DES:
+ block_size = 8; /* block size in bytes */
+ break;
+ case OP_PCL_IPSEC_AES_CBC:
+ case OP_PCL_IPSEC_AES_CTR:
+ case OP_PCL_IPSEC_AES_XTS:
+ case OP_PCL_IPSEC_AES_CCM8:
+ case OP_PCL_IPSEC_AES_CCM12:
+ case OP_PCL_IPSEC_AES_CCM16:
+ case OP_PCL_IPSEC_AES_GCM8:
+ case OP_PCL_IPSEC_AES_GCM12:
+ case OP_PCL_IPSEC_AES_GCM16:
+ block_size = 16; /* block size in bytes */
+ break;
+ default:
+ pr_crit("Invalid cipher algorithm for SA %d\n", sa->id);
+ return -EINVAL;
+ }
+
+ /* Adding padding to byte counter */
+ append_math_and_imm_u32(extra_cmds, REG3, REG2, IMM, block_size - 1);
+
+ /* Previous operation result is 0 i.e padding added to bytes count */
+ padding_jump = append_jump(extra_cmds, CLASS_BOTH | JUMP_TEST_ALL |
+ JUMP_COND_MATH_Z);
+
+ /* MATH REG 2 = MATH REG 2 + 1 */
+ append_math_add(extra_cmds, REG2, REG2, ONE, MATH_LEN_4BYTE);
+
+ /* jump back to adding padding i.e jump back 4 words */
+ off = (-4) & 0x000000FF;
+ append_jump(extra_cmds, (off << JUMP_OFFSET_SHIFT));
+
+ set_jump_tgt_here(extra_cmds, padding_jump);
+ /* Done adding padding to byte counter */
+
+ /*
+ * Perform 32-bit left shift of DEST and concatenate with left 32 bits
+ * of SRC1 i.e MATH REG 2 = 0x00bytecount_00000000
+ */
+ append_math_shld(extra_cmds, REG2, REG0, REG2, MATH_LEN_8BYTE);
+
+ /* MATH REG 0 = MATH REG 0 + MATH REG 2 */
+ append_math_add(extra_cmds, REG0, REG0, REG2, MATH_LEN_8BYTE);
+
+ /*
+ * Overwrite the job-desc location (word 51 or 53) with the third
+ * group (11 words)
+ */
+ opt = MOVE_SRC_INFIFO | MOVE_DEST_DESCBUF | MOVE_WAITCOMP;
+ off_w = MAX_CAAM_DESCSIZE - job_desc_len;
+ off_b = off_w * sizeof(uint32_t); /* calculate off in bytes */
+ len = (11 * sizeof(uint32_t)) << MOVE_LEN_SHIFT;
+ append_move(extra_cmds, opt | (off_b << MOVE_OFFSET_SHIFT) | len);
+
+ /*
+ * Jump to the beginning of the JOB Descriptor to start executing
+ * the extra material group 3. The command for jumping back is already
+ * here from extra material group 1
+ */
+
+ /* End of Extra Material Group 2 */
+
+ /* Start Extra Material Group 3 */
+
+ if (sa->enable_stats) {
+ /* Store statistics in the CAAM internal descriptor */
+ off_b = sa->stats_indx * CAAM_CMD_SZ;
+ append_move(extra_cmds, MOVE_SRC_MATH0 | MOVE_DEST_DESCBUF |
+ (off_b << MOVE_OFFSET_SHIFT) |
+ sizeof(uint64_t));
+ } else {
+ /* Statistics are disabled. Do not update descriptor counter */
+ append_cmd(extra_cmds, 0xA0000001); /* NOP for SEC */
+ }
+
+ /* Key jump */
+ key_jump_cmd = append_jump(extra_cmds, CLASS_BOTH | JUMP_TEST_ALL |
+ JUMP_COND_SHRD);
+
+ /* check whether a split of a normal key is used */
+ if (sa->auth_data.split_key_len)
+ /* Append split authentication key */
+ append_key(extra_cmds, auth_key_dma,
+ sa->auth_data.split_key_len,
+ CLASS_2 | KEY_ENC | KEY_DEST_MDHA_SPLIT);
+ else
+ /* Append normal authentication key */
+ append_key(extra_cmds, auth_key_dma, sa->auth_data.auth_key_len,
+ CLASS_2 | KEY_DEST_CLASS_REG);
+
+ /* Append cipher key */
+ append_key(extra_cmds, crypto_key_dma, sa->cipher_data.cipher_key_len,
+ CLASS_1 | KEY_DEST_CLASS_REG);
+
+ set_jump_tgt_here(extra_cmds, key_jump_cmd);
+
+ /* Protocol specific operation */
+ append_operation(extra_cmds, OP_PCLID_IPSEC | OP_TYPE_ENCAP_PROTOCOL |
+ sa->cipher_data.cipher_type | sa->auth_data.auth_type);
+
+ if (sa->enable_stats) {
+ /*
+ * Store command: in the case of the Descriptor Buffer the
+ * length is specified in 4-byte words, but in all other cases
+ * the length is specified in bytes. Offset in 4 byte words
+ */
+ off_w = sa->stats_indx;
+ append_store(extra_cmds, 0, DPA_IPSEC_STATS_LEN,
+ LDST_CLASS_DECO | (off_w << LDST_OFFSET_SHIFT) |
+ LDST_SRCDST_WORD_DESCBUF_SHARED);
+ } else {
+ /* Do not store lifetime counter in external memory */
+ append_cmd(extra_cmds, 0xA0000001); /* NOP for SEC */
+ }
+
+ /* Jump with CALM to be sure previous operation was finished */
+ append_jump(extra_cmds, JUMP_TYPE_HALT_USER | JUMP_COND_CALM);
+
+ /* End of Extra Material Group 3 */
+
+ return 0;
+}
+
+/* Move size should be set to 64 bytes */
+void built_decap_extra_material(struct dpa_ipsec_sa *sa,
+ dma_addr_t auth_key_dma,
+ dma_addr_t crypto_key_dma)
+{
+ uint32_t *extra_cmds;
+ uint32_t off_b, off_w, data;
+
+ /*
+ * sec_desc_extra_cmds is the address were the first SEC extra command
+ * is located, from here SEC will overwrite Job descriptor part. Need
+ * to insert a dummy command because the LINUX CAAM API uses first word
+ * for storing the length of the descriptor.
+ */
+ extra_cmds = sa->sec_desc_extra_cmds - 1;
+
+ /*
+ * Dummy command - will not be executed at all. Only for setting to 1
+ * the length of the extra_cmds descriptor so that first extra material
+ * command will be located exactly at sec_desc_extra_cmds address.
+ */
+ append_cmd(extra_cmds, 0xdead0000);
+
+ data = 16;
+ append_math_rshift_imm_u64(extra_cmds, REG2, REG2, IMM, data);
+
+ /* math: (math1 - math2)->math1 len=8 */
+ append_math_sub(extra_cmds, REG1, REG1, REG2, MATH_LEN_8BYTE);
+
+ /* math: (math0 + 1)->math0 len=8 */
+ append_math_add(extra_cmds, REG0, REG0, ONE, MATH_LEN_8BYTE);
+
+ append_math_shld(extra_cmds, REG1, REG0, REG1, MATH_LEN_8BYTE);
+
+ append_math_add(extra_cmds, REG0, REG0, REG1, MATH_LEN_8BYTE);
+
+ append_cmd(extra_cmds, 0x7883c824);
+
+ /* Store in the descriptor but not in external memory */
+ off_b = sa->stats_offset;
+ append_move(extra_cmds, MOVE_SRC_MATH0 | MOVE_DEST_DESCBUF |
+ MOVE_WAITCOMP | (off_b << MOVE_OFFSET_SHIFT) | sizeof(u64));
+
+ append_cmd(extra_cmds, 0xa70040fe);
+
+ append_cmd(extra_cmds, 0xa00000f7);
+
+ /* check whether a split of a normal key is used */
+ if (sa->auth_data.split_key_len)
+ /* Append split authentication key */
+ append_key(extra_cmds, auth_key_dma,
+ sa->auth_data.split_key_len,
+ CLASS_2 | KEY_ENC | KEY_DEST_MDHA_SPLIT);
+ else
+ /* Append normal authentication key */
+ append_key(extra_cmds, auth_key_dma, sa->auth_data.auth_key_len,
+ CLASS_2 | KEY_DEST_CLASS_REG);
+
+ /* Append cipher key */
+ append_key(extra_cmds, crypto_key_dma, sa->cipher_data.cipher_key_len,
+ CLASS_1 | KEY_DEST_CLASS_REG);
+
+ /* Protocol specific operation */
+ append_operation(extra_cmds, OP_PCLID_IPSEC | OP_TYPE_DECAP_PROTOCOL |
+ sa->cipher_data.cipher_type | sa->auth_data.auth_type);
+
+ /*
+ * Store command: in the case of the Descriptor Buffer the length
+ * is specified in 4-byte words, but in all other cases the length
+ * is specified in bytes. Offset in 4 byte words
+ */
+ off_w = sa->stats_indx;
+ append_store(extra_cmds, 0, DPA_IPSEC_STATS_LEN,
+ LDST_CLASS_DECO | (off_w << LDST_OFFSET_SHIFT) |
+ LDST_SRCDST_WORD_DESCBUF_SHARED);
+
+ append_jump(extra_cmds, JUMP_TYPE_HALT_USER | JUMP_COND_CALM);
+}
+
+int build_extended_encap_shared_descriptor(struct dpa_ipsec_sa *sa,
+ dma_addr_t auth_key_dma,
+ dma_addr_t crypto_key_dma,
+ uint32_t bytes_to_copy,
+ int sec_era)
+{
+ uint32_t *desc, *no_sg_jump, *extra_cmds;
+ uint32_t len, off_b, off_w, opt, stats_off_b, sg_mask;
+ struct device *jrdev;
+ unsigned int extra_cmds_len;
+ unsigned char job_desc_len;
+ dma_addr_t dma_extra_cmds;
+ int ret;
+
+ desc = (uint32_t *)sa->sec_desc->desc;
+
+ if (sec_era == 2) {
+ if (sa->enable_stats)
+ sa->stats_indx = 27;
+ sa->next_cmd_indx = 29;
+ } else {
+ if (sa->enable_stats)
+ sa->stats_indx = 28;
+ sa->next_cmd_indx = 30;
+ }
+
+ /* This code only works when SEC is configured to use PTR on 64 bit
+ * so the Job Descriptor length is 13 words long when DPOWRD is set */
+ job_desc_len = 13;
+
+ /* Set CAAM Job Descriptor length */
+ sa->job_desc_len = job_desc_len;
+
+ /* Set lifetime counter stats offset */
+ sa->stats_offset = sa->stats_indx * sizeof(uint32_t);
+
+ ret = built_encap_extra_material(sa, auth_key_dma, crypto_key_dma, 64);
+ if (ret < 0) {
+ log_err("Failed to create extra CAAM commands\n");
+ return -EAGAIN;
+ }
+
+ extra_cmds = sa->sec_desc_extra_cmds - 1;
+ extra_cmds_len = desc_len(extra_cmds) - 1;
+
+ /* get the jr device */
+ jrdev = get_jrdev(sa->dpa_ipsec);
+ if (!jrdev) {
+ log_err("Failed to get the job ring device, check the dts\n");
+ return -EINVAL;
+ }
+
+ dma_extra_cmds = dma_map_single(jrdev, sa->sec_desc_extra_cmds,
+ extra_cmds_len * sizeof(uint32_t),
+ DMA_TO_DEVICE);
+ if (!dma_extra_cmds) {
+ log_err("Could not DMA map extra CAAM commands\n");
+ return -ENXIO;
+ }
+
+ init_sh_desc_pdb(desc, HDR_SAVECTX | HDR_SHARE_SERIAL,
+ (sa->next_cmd_indx - 1) * sizeof(uint32_t));
+
+ if (sec_era == 2) {
+ /* disable iNFO FIFO entries for p4080rev2 & ??? */
+ len = 0x10 << LDST_LEN_SHIFT;
+ append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO | len);
+
+ /*
+ * load in IN FIFO the S/G Entry located in the 5th reg after
+ * MATH3 -> offset = sizeof(GT_REG) * 4 + offset_math3_to_GT_REG
+ * len = sizeof(S/G entry)
+ * Offset refers to SRC
+ */
+ opt = MOVE_SRC_MATH3 | MOVE_DEST_CLASS1INFIFO;
+ off_b = 127 << MOVE_OFFSET_SHIFT;
+ len = 49 << MOVE_LEN_SHIFT;
+ append_move(desc, opt | off_b | len);
+
+ /*
+ * L2 part 1
+ * Load from input packet to INPUT DATA FIFO first bytes_to_copy
+ * bytes.
+ */
+ append_seq_fifo_load(desc, bytes_to_copy, FIFOLD_TYPE_MSG |
+ FIFOLD_CLASS_BOTH | FIFOLD_TYPE_LAST1 |
+ FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_FLUSH1);
+
+ /*
+ * Extra word part 1
+ * Load extra words for this descriptor into the INPUT DATA FIFO
+ */
+ append_fifo_load(desc, dma_extra_cmds,
+ extra_cmds_len * sizeof(uint32_t),
+ FIFOLD_TYPE_MSG | FIFOLD_CLASS_BOTH |
+ FIFOLD_TYPE_LAST1 | FIFOLD_TYPE_LAST2 |
+ FIFOLD_TYPE_FLUSH1);
+
+ /* enable iNFO FIFO entries */
+ append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
+ } else {
+ /* ????? */
+ opt = LDST_IMM | LDST_CLASS_DECO | LDST_SRCDST_WORD_DECOCTRL;
+ len = 0x10 << LDST_LEN_SHIFT;
+ append_cmd(desc, CMD_LOAD | opt | len);
+
+ /*
+ * load in IN FIFO the S/G Entry located in the 5th reg after
+ * MATH3 -> offset = sizeof(GT_REG) * 4 + offset_math3_to_GT_REG
+ * len = sizeof(S/G entry)
+ */
+ opt = MOVE_SRC_MATH3 | MOVE_DEST_INFIFO_NOINFO;
+ off_b = 127 << MOVE_OFFSET_SHIFT;
+ len = 49 << MOVE_LEN_SHIFT;
+ append_move(desc, opt | off_b | len);
+
+ /*
+ * L2 part 1
+ * Load from input packet to INPUT DATA FIFO first bytes_to_copy
+ * bytes. No information FIFO entry even if automatic
+ * iNformation FIFO entries are enabled.
+ */
+ append_seq_fifo_load(desc, bytes_to_copy, FIFOLD_CLASS_BOTH |
+ FIFOLD_TYPE_NOINFOFIFO);
+
+ /*
+ * Extra word part 1
+ * Load extra words for this descriptor into the INPUT DATA FIFO
+ */
+ append_fifo_load(desc, dma_extra_cmds,
+ extra_cmds_len * sizeof(uint32_t),
+ FIFOLD_CLASS_BOTH | FIFOLD_TYPE_NOINFOFIFO);
+ }
+
+ /*
+ * throw away the first part of the S/G table and keep only the buffer
+ * address;
+ * offset = undefined memory after MATH3; Refers to the destination.
+ * len = 41 bytes to discard
+ */
+ opt = MOVE_SRC_INFIFO | MOVE_DEST_MATH3;
+ off_b = 8 << MOVE_OFFSET_SHIFT;
+ len = 41 << MOVE_LEN_SHIFT;
+ append_move(desc, opt | off_b | len);
+
+ /* put the buffer address (still in the IN FIFO) in MATH2 */
+ opt = MOVE_SRC_INFIFO | MOVE_DEST_MATH3;
+ off_b = 0 << MOVE_OFFSET_SHIFT;
+ len = 8 << MOVE_LEN_SHIFT;
+ append_move(desc, opt | off_b | len);
+
+ /* copy 15 bytes starting at 4 bytes before the OUT-PTR-CMD in
+ * the job-desc into math1
+ * i.e. in the low-part of math1 we have the out-ptr-cmd and
+ * in the math2 we will have the address of the out-ptr
+ */
+ opt = MOVE_SRC_DESCBUF | MOVE_DEST_MATH1;
+ off_b = (MAX_CAAM_DESCSIZE - job_desc_len + PTR_LEN) * sizeof(uint32_t);
+ len = (8 + 4 * PTR_LEN - 1) << MOVE_LEN_SHIFT;
+ append_move(desc, opt | (off_b << MOVE_OFFSET_SHIFT) | len);
+
+ /* Copy 7 bytes of the in-ptr into math0 */
+ opt = MOVE_SRC_DESCBUF | MOVE_DEST_MATH0;
+ off_w = MAX_CAAM_DESCSIZE - job_desc_len + 1 + 3 + 2 * PTR_LEN;
+ off_b = off_w * sizeof(uint32_t); /* calculate off in bytes */
+ len = ALIGNED_PTR_ADDRESS_SZ << MOVE_LEN_SHIFT;
+ append_move(desc, opt | (off_b << MOVE_OFFSET_SHIFT) | len);
+
+ /*
+ * the SEQ OUT PTR command is now in math reg 1, so the SGF bit can be
+ * checked using a math command;
+ */
+ sg_mask = SEQ_OUT_PTR_SGF_MASK;
+ append_math_and_imm_u32(desc, NONE, REG1, IMM, sg_mask);
+
+ opt = CLASS_NONE | JUMP_TYPE_LOCAL | JUMP_COND_MATH_Z | JUMP_TEST_ALL;
+ no_sg_jump = append_jump(desc, opt);
+
+ append_math_add(desc, REG2, ZERO, REG3, MATH_LEN_8BYTE);
+
+ /* update no S/G jump location */
+ set_jump_tgt_here(desc, no_sg_jump);
+
+ /* seqfifostr: msgdata len=4 */
+ append_seq_fifo_store(desc, FIFOST_TYPE_MESSAGE_DATA, bytes_to_copy);
+
+ /* move: ififo->deco-alnblk -> ofifo, len=4 */
+ append_move(desc, MOVE_SRC_INFIFO | MOVE_DEST_OUTFIFO | bytes_to_copy);
+
+ /* Overwrite the job-desc location (word 51 or 53) with the first
+ * group (11 words)*/
+ opt = MOVE_SRC_INFIFO | MOVE_DEST_DESCBUF;
+ off_w = MAX_CAAM_DESCSIZE - job_desc_len;
+ off_b = off_w * sizeof(uint32_t); /* calculate off in bytes */
+ len = (11 * sizeof(uint32_t)) << MOVE_LEN_SHIFT;
+ append_move(desc, opt | (off_b << MOVE_OFFSET_SHIFT) | len);
+
+ /*
+ * Copy the context of math0 (input address) to words 52+53 or 54+56
+ * depending where the Job Descriptor starts.
+ * They will be used later by the load command.
+ */
+ opt = MOVE_SRC_MATH0 | MOVE_DEST_DESCBUF;
+ off_w = MAX_CAAM_DESCSIZE - job_desc_len + 1; /* 52 + 53 or 54 + 55 */
+ off_b = off_w * sizeof(uint32_t);
+ len = ALIGNED_PTR_ADDRESS_SZ << MOVE_LEN_SHIFT;
+ append_move(desc, opt | (off_b << MOVE_OFFSET_SHIFT) | len);
+
+ /*
+ * Copy the context of math2 (output address) to words 56+57 or 58+59
+ * depending where the Job Descriptor starts.
+ * They will be used later by the store command.
+ */
+ opt = MOVE_SRC_MATH2 | MOVE_DEST_DESCBUF;
+ off_w = MAX_CAAM_DESCSIZE - job_desc_len + 5; /* 56 + 57 or 58 + 59 */
+ off_b = off_w * sizeof(uint32_t);
+ len = ALIGNED_PTR_ADDRESS_SZ << MOVE_LEN_SHIFT;
+ append_move(desc, opt | (off_b << MOVE_OFFSET_SHIFT) | len);
+
+ /* Fix LIODN - OFFSET[0:1] - 01 = SEQ LIODN */
+ opt = LDST_IMM | LDST_CLASS_DECO | LDST_SRCDST_WORD_DECOCTRL;
+ off_b = 0x40; /* SEQ LIODN */
+ append_cmd(desc, CMD_LOAD | opt | (off_b << LDST_OFFSET_SHIFT));
+
+ /* Copy the context of the counters from word 29 into math0 */
+ /* Copy from descriptor to MATH REG 0 the current statistics */
+ stats_off_b = sa->stats_indx * CAAM_CMD_SZ;
+ append_move(desc, MOVE_SRC_DESCBUF | MOVE_DEST_MATH0 |
+ (stats_off_b << MOVE_OFFSET_SHIFT) | sizeof(uint64_t));
+
+ dma_unmap_single(sa->dpa_ipsec->jrdev, dma_extra_cmds,
+ extra_cmds_len * sizeof(uint32_t), DMA_TO_DEVICE);
+
+ return 0;
+}
+
+int build_extended_decap_shared_descriptor(struct dpa_ipsec_sa *sa,
+ dma_addr_t auth_key_dma,
+ dma_addr_t crypto_key_dma,
+ uint32_t bytes_to_copy,
+ uint8_t move_size,
+ int sec_era)
+{
+ uint32_t *desc, *no_sg_jump, *extra_cmds;
+ uint32_t len, off_b, off_w, opt, stats_off_b, sg_mask, extra_cmds_len,
+ esp_length, iv_length, icv_length, max_pad, data;
+ dma_addr_t dma_extra_cmds;
+ struct device *jrdev;
+
+ desc = (uint32_t *)sa->sec_desc->desc;
+
+ /* CAAM hdr cmd + PDB size in words */
+ sa->next_cmd_indx =
+ sizeof(struct ipsec_decap_pdb) / sizeof(uint32_t) + 1;
+ if (sa->enable_stats) {
+ sa->stats_indx = sa->next_cmd_indx;
+ sa->next_cmd_indx += 2;
+ if (sec_era != 2) {
+ sa->stats_indx += 1;
+ sa->next_cmd_indx += 1;
+ }
+ }
+
+ /* Set lifetime counter stats offset */
+ sa->stats_offset = sa->stats_indx * sizeof(uint32_t);
+
+ built_decap_extra_material(sa, auth_key_dma, crypto_key_dma);
+
+ extra_cmds = sa->sec_desc_extra_cmds - 1;
+ extra_cmds_len = desc_len(extra_cmds) - 1;
+
+ /* get the jr device */
+ jrdev = get_jrdev(sa->dpa_ipsec);
+ if (!jrdev) {
+ log_err("Failed to get the job ring device, check the dts\n");
+ return -EINVAL;
+ }
+
+ dma_extra_cmds = dma_map_single(jrdev, sa->sec_desc_extra_cmds,
+ extra_cmds_len * sizeof(uint32_t),
+ DMA_TO_DEVICE);
+ if (!dma_extra_cmds) {
+ log_err("Could not DMA map extra CAAM commands\n");
+ return -ENXIO;
+ }
+
+ init_sh_desc_pdb(desc, HDR_SAVECTX | HDR_SHARE_SERIAL,
+ (sa->next_cmd_indx - 1) * sizeof(uint32_t));
+
+ if (sec_era == 2) {
+ /* disable iNFO FIFO entries for p4080rev2 & ??? */
+ len = 0x10 << LDST_LEN_SHIFT;
+ append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO | len);
+
+ /*
+ * load in IN FIFO the S/G Entry located in the 5th reg after
+ * MATH3 -> offset = sizeof(GT_REG) * 4 + offset_math3_to_GT_REG
+ * len = sizeof(S/G entry)
+ * Offset refers to SRC
+ */
+ opt = MOVE_SRC_MATH3 | MOVE_DEST_CLASS1INFIFO;
+ off_b = 127 << MOVE_OFFSET_SHIFT;
+ len = 49 << MOVE_LEN_SHIFT;
+ append_move(desc, opt | off_b | len);
+
+ /*
+ * L2 part 1
+ * Load from input packet to INPUT DATA FIFO first bytes_to_copy
+ * bytes.
+ */
+ append_seq_fifo_load(desc, bytes_to_copy, FIFOLD_TYPE_MSG |
+ FIFOLD_CLASS_BOTH | FIFOLD_TYPE_LAST1 |
+ FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_FLUSH1);
+
+ /*
+ * Extra word part 1
+ * Load extra words for this descriptor into the INPUT DATA FIFO
+ */
+ append_fifo_load(desc, dma_extra_cmds,
+ extra_cmds_len * sizeof(uint32_t),
+ FIFOLD_TYPE_MSG | FIFOLD_CLASS_BOTH |
+ FIFOLD_TYPE_LAST1 | FIFOLD_TYPE_LAST2 |
+ FIFOLD_TYPE_FLUSH1);
+
+ /* enable iNFO FIFO entries */
+ append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
+ } else {
+ /* ????? */
+ opt = LDST_IMM | LDST_CLASS_DECO | LDST_SRCDST_WORD_DECOCTRL;
+ len = 0x10 << LDST_LEN_SHIFT;
+ append_cmd(desc, CMD_LOAD | opt | len);
+
+ /*
+ * load in IN FIFO the S/G Entry located in the 5th reg after
+ * MATH3 -> offset = sizeof(GT_REG) * 4 + offset_math3_to_GT_REG
+ * len = sizeof(S/G entry)
+ */
+ opt = MOVE_SRC_MATH3 | MOVE_DEST_INFIFO_NOINFO;
+ off_b = 127 << MOVE_OFFSET_SHIFT;
+ len = 49 << MOVE_LEN_SHIFT;
+ append_move(desc, opt | off_b | len);
+
+ /*
+ * L2 part 1
+ * Load from input packet to INPUT DATA FIFO first bytes_to_copy
+ * bytes. No information FIFO entry even if automatic
+ * iNformation FIFO entries are enabled.
+ */
+ append_seq_fifo_load(desc, bytes_to_copy, FIFOLD_CLASS_BOTH |
+ FIFOLD_TYPE_NOINFOFIFO);
+
+ /*
+ * Extra word part 1
+ * Load extra words for this descriptor into the INPUT DATA FIFO
+ */
+ append_fifo_load(desc, dma_extra_cmds,
+ extra_cmds_len * sizeof(uint32_t),
+ FIFOLD_CLASS_BOTH | FIFOLD_TYPE_NOINFOFIFO);
+ }
+
+ /*
+ * throw away the first part of the S/G table and keep only the buffer
+ * address;
+ * offset = undefined memory after MATH3; Refers to the destination.
+ * len = 41 bytes to discard
+ */
+ opt = MOVE_SRC_INFIFO | MOVE_DEST_MATH3;
+ off_b = 8 << MOVE_OFFSET_SHIFT;
+ len = 41 << MOVE_LEN_SHIFT;
+ append_move(desc, opt | off_b | len);
+
+ /* put the buffer address (still in the IN FIFO) in MATH2 */
+ opt = MOVE_SRC_INFIFO | MOVE_DEST_MATH3;
+ off_b = 0 << MOVE_OFFSET_SHIFT;
+ len = 8 << MOVE_LEN_SHIFT;
+ append_move(desc, opt | off_b | len);
+
+ /*
+ * Copy 15 bytes starting at 4 bytes before the OUT-PTR-CMD in
+ * the job-desc into math1
+ * i.e. in the low-part of math1 we have the out-ptr-cmd and
+ * in the math2 we will have the address of the out-ptr
+ */
+ opt = MOVE_SRC_DESCBUF | MOVE_DEST_MATH1;
+ off_b = (50 + 1 * PTR_LEN) * sizeof(uint32_t);
+ len = (8 + 4 * PTR_LEN - 1) << MOVE_LEN_SHIFT;
+ append_move(desc, opt | (off_b << MOVE_OFFSET_SHIFT) | len);
+
+ /* Copy 7 bytes of the in-ptr into math0 */
+ opt = MOVE_SRC_DESCBUF | MOVE_DEST_MATH0;
+ off_w = 50 + 1 + 3 + 2 * PTR_LEN;
+ off_b = off_w * sizeof(uint32_t); /* calculate off in bytes */
+ len = ALIGNED_PTR_ADDRESS_SZ << MOVE_LEN_SHIFT;
+ append_move(desc, opt | (off_b << MOVE_OFFSET_SHIFT) | len);
+
+ /*
+ * the SEQ OUT PTR command is now in math reg 1, so the SGF bit can be
+ * checked using a math command;
+ */
+ sg_mask = SEQ_OUT_PTR_SGF_MASK;
+ append_math_and_imm_u32(desc, NONE, REG1, IMM, sg_mask);
+
+ opt = CLASS_NONE | JUMP_TYPE_LOCAL | JUMP_COND_MATH_Z | JUMP_TEST_ALL;
+ no_sg_jump = append_jump(desc, opt);
+
+ append_math_add(desc, REG2, ZERO, REG3, MATH_LEN_8BYTE);
+
+ /* update no S/G jump location */
+ set_jump_tgt_here(desc, no_sg_jump);
+
+ /* seqfifostr: msgdata len=4 */
+ append_seq_fifo_store(desc, FIFOST_TYPE_MESSAGE_DATA, bytes_to_copy);
+
+ /* move: ififo->deco-alnblk -> ofifo, len */
+ append_move(desc, MOVE_SRC_INFIFO | MOVE_DEST_OUTFIFO | bytes_to_copy);
+
+ /* Overwrite the job-desc location (word 50) with the first
+ * group (10 words)*/
+ opt = MOVE_SRC_INFIFO | MOVE_DEST_DESCBUF;
+ off_w = 50;
+ off_b = off_w * sizeof(uint32_t); /* calculate off in bytes */
+ len = (10 * sizeof(uint32_t)) << MOVE_LEN_SHIFT;
+ append_move(desc, opt | (off_b << MOVE_OFFSET_SHIFT) | len);
+
+ /*
+ * Copy the context of math0 (input address) to words 32+33
+ * They will be used later by the load command.
+ */
+ opt = MOVE_SRC_MATH0 | MOVE_DEST_DESCBUF;
+ off_w = 32;
+ off_b = off_w * sizeof(uint32_t);
+ len = ALIGNED_PTR_ADDRESS_SZ << MOVE_LEN_SHIFT;
+ append_move(desc, opt | (off_b << MOVE_OFFSET_SHIFT) | len);
+
+ /*
+ * Copy the context of math2 (output address) to words 56+57 or 58+59
+ * depending where the Job Descriptor starts.
+ * They will be used later by the store command.
+ */
+ opt = MOVE_SRC_MATH2 | MOVE_DEST_DESCBUF | MOVE_WAITCOMP;
+ off_w = 36;
+ off_b = off_w * sizeof(uint32_t);
+ len = ALIGNED_PTR_ADDRESS_SZ << MOVE_LEN_SHIFT;
+ append_move(desc, opt | (off_b << MOVE_OFFSET_SHIFT) | len);
+
+ /* Fix LIODN - OFFSET[0:1] - 01 = SEQ LIODN */
+ opt = LDST_IMM | LDST_CLASS_DECO | LDST_SRCDST_WORD_DECOCTRL;
+ off_b = 0x40; /* SEQ LIODN */
+ append_cmd(desc, CMD_LOAD | opt | (off_b << LDST_OFFSET_SHIFT));
+
+ /* Load from the input address 64 bytes into internal register */
+ /* load the data to be moved - insert dummy pointer */
+ opt = LDST_CLASS_2_CCB | LDST_SRCDST_WORD_CLASS_CTX;
+ off_b = 0 << LDST_OFFSET_SHIFT;
+ len = move_size << LDST_LEN_SHIFT;
+ append_load(desc, DUMMY_PTR_VAL, len, opt | off_b);
+
+ /* Wait to finish previous operation */
+ opt = JUMP_COND_CALM | (1 << JUMP_OFFSET_SHIFT);
+ append_jump(desc, opt);
+
+ /* Store the data to the output FIFO - insert dummy pointer */
+ opt = LDST_CLASS_2_CCB | LDST_SRCDST_WORD_CLASS_CTX;
+ off_b = 0 << LDST_OFFSET_SHIFT;
+ len = move_size << LDST_LEN_SHIFT;
+ append_store(desc, DUMMY_PTR_VAL, len, opt | off_b);
+
+ /* Fix LIODN */
+ opt = LDST_IMM | LDST_CLASS_DECO | LDST_SRCDST_WORD_DECOCTRL;
+ off_b = 0x80 << LDST_OFFSET_SHIFT; /* NON_SEQ LIODN */
+ append_cmd(desc, CMD_LOAD | opt | off_b);
+
+ /* Copy from descriptor to MATH REG 0 the current statistics */
+ stats_off_b = sa->stats_indx * CAAM_CMD_SZ;
+ append_move(desc, MOVE_SRC_DESCBUF | MOVE_DEST_MATH0 | MOVE_WAITCOMP |
+ (stats_off_b << MOVE_OFFSET_SHIFT) | sizeof(uint64_t));
+
+ /* Remove unnecessary headers
+ * MATH1 = 0 - (esp_length + iv_length + icv_length) */
+ esp_length = 8; /* SPI + SEQ NUM */
+ get_cipher_params(sa->alg_suite, &iv_length, &icv_length, &max_pad);
+ data = (uint32_t) (esp_length + iv_length + icv_length);
+ append_math_sub_imm_u64(desc, REG1, ZERO, IMM, data);
+
+ /* MATH1 += SIL (bytes counter) */
+ append_math_add(desc, REG1, SEQINLEN, REG1, MATH_LEN_8BYTE);
+
+ /* data = outer IP header - should be read from DPOVRD register
+ * MATH 2 = outer IP header length */
+ data = 20;
+ opt = LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_MATH2;
+ len = sizeof(data) << LDST_LEN_SHIFT;
+ append_load_as_imm(desc, &data, len, opt);
+
+ off_w = 7;
+ append_jump(desc, (off_w << JUMP_OFFSET_SHIFT));
+
+ /* jump: all-match[] always-jump offset=0 local->[00] */
+ append_jump(desc, (0 << JUMP_OFFSET_SHIFT));
+
+ /* jump: all-match[] always-jump offset=0 local->[00] */
+ append_jump(desc, (0 << JUMP_OFFSET_SHIFT));
+
+ data = 0x00ff0000;
+ append_math_and_imm_u64(desc, REG2, DPOVRD, IMM, data);
+
+ dma_unmap_single(sa->dpa_ipsec->jrdev, dma_extra_cmds,
+ extra_cmds_len * sizeof(uint32_t), DMA_TO_DEVICE);
+
+ return 0;
+}
+
+
+int create_sec_descriptor(struct dpa_ipsec_sa *sa)
+{
+ struct sec_descriptor *sec_desc;
+ struct device *jrdev;
+ dma_addr_t auth_key_dma;
+ dma_addr_t crypto_key_dma;
+ int ret = 0;
+
+ /* get the jr device */
+ jrdev = get_jrdev(sa->dpa_ipsec);
+ if (!jrdev) {
+ log_err("Failed to get the job ring device, check the dts\n");
+ return -EINVAL;
+ }
+
+ /* check whether a split of a normal key is used */
+ if (sa->auth_data.split_key_len)
+ auth_key_dma = dma_map_single(jrdev, sa->auth_data.split_key,
+ sa->auth_data.split_key_pad_len,
+ DMA_TO_DEVICE);
+ else
+ auth_key_dma = dma_map_single(jrdev, sa->auth_data.auth_key,
+ sa->auth_data.auth_key_len,
+ DMA_TO_DEVICE);
+ if (!auth_key_dma) {
+ log_err("Could not DMA map authentication key\n");
+ return -EINVAL;
+ }
+
+ crypto_key_dma = dma_map_single(jrdev, sa->cipher_data.cipher_key,
+ sa->cipher_data.cipher_key_len,
+ DMA_TO_DEVICE);
+ if (!crypto_key_dma) {
+ log_err("Could not DMA map cipher key\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Build the shared descriptor and see if its length is less than
+ * 64 words. If build_shared_descriptor returns -EPERM than it is
+ * required to build the extended shared descriptor in order to have
+ * all the SA features that were required.
+ */
+ ret = build_shared_descriptor(sa, auth_key_dma, crypto_key_dma,
+ sa->l2_hdr_size);
+ switch (ret) {
+ case 0:
+ sa->sec_desc_extended = false;
+ goto done_shared_desc;
+ case -EPERM:
+ sa->sec_desc_extended = true;
+ goto build_extended_shared_desc;
+ default:
+ log_err("Failed to create SEC descriptor for SA %d\n", sa->id);
+ return -EFAULT;
+ }
+
+build_extended_shared_desc:
+ /* Build the extended shared descriptor */
+ if (sa->sa_dir == DPA_IPSEC_INBOUND)
+ ret = build_extended_decap_shared_descriptor(sa, auth_key_dma,
+ crypto_key_dma, sa->l2_hdr_size, 64,
+ sa->dpa_ipsec->sec_era);
+ else
+ ret = build_extended_encap_shared_descriptor(sa, auth_key_dma,
+ crypto_key_dma, sa->l2_hdr_size,
+ sa->dpa_ipsec->sec_era);
+ if (ret < 0) {
+ log_err("Failed to create SEC descriptor for SA %d\n", sa->id);
+ return -EFAULT;
+ }
+
+done_shared_desc:
+ sec_desc = sa->sec_desc;
+ /* setup preheader */
+ sec_desc->preheader.hi.field.idlen = desc_len((u32 *) sec_desc->desc);
+ sec_desc->preheader.lo.field.pool_id = sa->sa_bpid;
+ sec_desc->preheader.lo.field.pool_buffer_size = sa->sa_bufsize;
+ sec_desc->preheader.lo.field.offset =
+ (sa->sa_dir == DPA_IPSEC_INBOUND) ?
+ sa->dpa_ipsec->config.post_sec_in_params.data_off :
+ sa->dpa_ipsec->config.post_sec_out_params.data_off;
+
+ dma_unmap_single(jrdev, auth_key_dma,
+ sa->auth_data.split_key_pad_len, DMA_TO_DEVICE);
+ dma_unmap_single(jrdev, crypto_key_dma,
+ sa->cipher_data.cipher_key_len, DMA_TO_DEVICE);
+ return 0;
+}
+
+/*
+ * Create descriptor for updating the anti replay window size
+ * [21] B0951A1D jobhdr: shrsz=21 shr share=serial reo len=29
+ * [22] 00000000 sharedesc->@0x029a9a608
+ * [23] 29A9A608
+ * [24] 79340008 move: descbuf+0[00] -> math0, len=8 wait
+ * [25] A82CC108 math: (0 - 1)->math1 len=8
+ * [26] AC214108 math: (math1 - imm1)->math1 len=8 ifb
+ * [27] 000000C0 imm1=192
+ * [28] A8501008 math: (math0 & math1)->math0 len=8
+ * [29] 1640180A ld: deco-descbuf len=10 offs=24
+ * [30] 00000000 ptr->@0x02965ca34
+ * [31] 2965CA34
+ * [32] A1001001 jump: jsl1 all-match[calm] offset=1 local->[33]
+ * [33] A00000F7 jump: all-match[] always-jump offset=-9 local->[24]
+ * [34] AC404008 math: (math0 | imm1)->math0 len=8 ifb
+ * [35] 000000C0 imm1=192
+ * [36] 79430008 move: math0 -> descbuf+0[00], len=8 wait
+ * [37] 79631804 move: math2 -> descbuf+24[06], len=4 wait
+ * [38] 56420107 str: deco-shrdesc+1 len=7
+ * [39] 16401806 ld: deco-descbuf len=6 offs=24
+ * [40] 00000000 ptr->@0x02965ca5c
+ * [41] 2965CA5C
+ * [42] A1001001 jump: jsl1 all-match[calm] offset=1 local->[43]
+ * [43] A00000F7 jump: all-match[] always-jump offset=-9 local->[34]
+ * [44] 16860800 ld: deco-ctrl len=0 offs=8 imm -auto-nfifo-entries
+ * [45] 2E17000A seqfifold: both msgdata-last2-last1-flush1 len=10
+ * [46] 16860400 ld: deco-ctrl len=0 offs=4 imm +auto-nfifo-entries
+ * [47] 7882000A move: ififo->deco-alnblk -> ofifo, len=10
+ * [48] 6830000A seqfifostr: msgdata len=10
+ * [49] A1C01002 jump: jsl1 all-match[calm] halt-user status=2
+ *
+ * The msg_len represent the length of the message written in the output frame
+ * in order to differentiate between modify operations
+ */
+int build_rjob_desc_ars_update(struct dpa_ipsec_sa *sa, enum dpa_ipsec_arw arw,
+ u32 msg_len)
+{
+ uint32_t *desc, *rjobd, off;
+ uint8_t options;
+ enum dpa_ipsec_arw c_arw;
+ size_t ars_off;
+ dma_addr_t dma_shdesc;
+
+ /* Check input parameters */
+ BUG_ON(!sa);
+ BUG_ON(!sa->sec_desc);
+ desc = (uint32_t *)sa->sec_desc->desc;
+ options = (uint8_t)(*(desc + 1) & 0x000000FF);
+ c_arw = options >> 6;
+ if (c_arw == arw) {
+ log_err("SA %d has already set this ARS %d\n", sa->id, arw);
+ return -EALREADY;
+ }
+
+ /* Get DMA address for this SA shared descriptor */
+ dma_shdesc = dma_map_single(sa->dpa_ipsec->jrdev, sa->sec_desc->desc,
+ desc_len(sa->sec_desc->desc) * sizeof(u32),
+ DMA_BIDIRECTIONAL);
+ if (!dma_shdesc) {
+ log_err("Failed DMA map shared descriptor for SA %d\n", sa->id);
+ return -ENXIO;
+ }
+
+ /* Create replacement job descriptor for ARS update */
+ BUG_ON(!sa->rjob_desc);
+ rjobd = sa->rjob_desc;
+
+ init_job_desc(rjobd, HDR_SHARE_SERIAL | HDR_SHARED | HDR_REVERSE |
+ (desc_len(sa->sec_desc->desc) << HDR_START_IDX_SHIFT));
+
+ /* Set DMA address of the shared descriptor */
+ append_ptr(rjobd, dma_shdesc);
+
+ /* Retrieve header and options from PDB in MATH 0 */
+ append_move(rjobd, MOVE_SRC_DESCBUF | MOVE_DEST_MATH0 | MOVE_WAITCOMP |
+ (0 << MOVE_OFFSET_SHIFT) | sizeof(u64));
+
+ /* MATH_REG1 = 0xFFFFFFFF_FFFFFFFF */
+ append_math_sub(rjobd, REG1, ZERO, ONE, MATH_LEN_8BYTE);
+
+ /* MATH_REG1 = 0xFFFFFFFF_FFFFFF3F */
+ append_math_sub_imm_u64(rjobd, REG1, REG1, IMM, 0xC0);
+
+ /* Reset ARS bits */
+ append_math_and(rjobd, REG0, REG0, REG1, MATH_LEN_8BYTE);
+
+ /*
+ * Overwrite RJD immediately after the SHD pointer i.e shared descriptor
+ * length plus 1 plus another 3 words
+ * Offset and length are expressed in words
+ * 3w - RJD header + SHD pointer
+ * 5w - five instructions for doing some part of ARS modification
+ * 3w - load instruction + pointer
+ * 1w - jump calm
+ * 1w - jump back to the remaining descriptor
+ */
+ append_load(rjobd, virt_to_phys((void *)(rjobd + 3 + 5 + 3 + 1 + 1)),
+ 10, LDST_CLASS_DECO | LDST_SRCDST_WORD_DESCBUF |
+ ((desc_len(sa->sec_desc->desc) + 3) << LDST_OFFSET_SHIFT));
+
+ /* wait for completion o previous operation */
+ append_jump(rjobd, JUMP_COND_CALM | (1 << JUMP_OFFSET_SHIFT));
+
+ /* jump back to remaining descriptor i.e jump back 9 words */
+ off = (-9) & 0x000000FF;
+ append_jump(rjobd, (off << JUMP_OFFSET_SHIFT));
+
+ /* Convert PDB ARS to new size */
+ switch (arw) {
+ case DPA_IPSEC_ARSNONE:
+ /*
+ * nothing to do because previous command reseted ARS bits
+ * add 2 NOPs to conserve descriptor size
+ */
+ append_cmd(rjobd, 0xA0000001); /* NOP for SEC */
+ append_cmd(rjobd, 0xA0000001); /* NOP for SEC */
+ break;
+ case DPA_IPSEC_ARS32:
+ append_math_or_imm_u64(rjobd, REG0, REG0, IMM,
+ PDBOPTS_ESP_ARS32);
+ break;
+ case DPA_IPSEC_ARS64:
+ append_math_or_imm_u64(rjobd, REG0, REG0, IMM,
+ PDBOPTS_ESP_ARS64);
+ break;
+ default:
+ log_err("Invalid ARS\n");
+ BUG();
+ }
+
+ /* Put header and options back to PDB */
+ append_move(rjobd, MOVE_SRC_MATH0 | MOVE_DEST_DESCBUF | MOVE_WAITCOMP |
+ (0 << MOVE_OFFSET_SHIFT) | sizeof(u64));
+
+ /*
+ * anti_replay[0] - used for 32ARS - LS bit represent the frame with
+ * highest SEQ number that has been successfully authenticated so far
+ * i.e the frame that had SEQ/ESN from PDB seq_num/seq_num_ext_hi
+ *
+ * anti_replay[1] - used when 64ARS is configured - LS bit represent
+ * a frame with a immediate older SEQ number than the MS bit of the
+ * anti_replay[0] i.e
+ * SEQ(LS bit of anti_replay[1]) = SEQ(MS bit of anti_replay[0]) - 1;
+ *
+ * always reset to 0 all bits from anti_replay[1]
+ * reset to 0 all bits from anti_replay[0] only if updating from ARS to
+ * no ARS.
+ * MOVE_SRC_MATH2 was not used until now i.e has value 0
+ */
+ ars_off = offsetof(struct ipsec_decap_pdb, anti_replay);
+ if (arw == DPA_IPSEC_ARSNONE)
+ append_move(rjobd, MOVE_SRC_MATH2 | MOVE_DEST_DESCBUF |
+ MOVE_WAITCOMP | (ars_off << MOVE_OFFSET_SHIFT) |
+ sizeof(u64));
+ else
+ append_move(rjobd, MOVE_SRC_MATH2 | MOVE_DEST_DESCBUF |
+ MOVE_WAITCOMP |
+ ((ars_off + 4) << MOVE_OFFSET_SHIFT) | sizeof(u32));
+
+ /*
+ * Update shared descriptor in memory - only PDB
+ * special case - offset and length are in words
+ */
+ append_store(rjobd, 0, sizeof(struct ipsec_decap_pdb) / sizeof(u32),
+ LDST_CLASS_DECO | (1 << LDST_OFFSET_SHIFT) |
+ LDST_SRCDST_WORD_DESCBUF_SHARED);
+
+ append_load(rjobd,
+ virt_to_phys((void *)(rjobd + 3 + 5 + 3 + 1 + 1 + 10)), 6,
+ LDST_CLASS_DECO | LDST_SRCDST_WORD_DESCBUF |
+ ((desc_len(sa->sec_desc->desc) + 3) << LDST_OFFSET_SHIFT));
+
+ /* wait for completion of the previous operation */
+ append_jump(rjobd, JUMP_COND_CALM | (1 << JUMP_OFFSET_SHIFT));
+
+ /* jump back to remaining descriptor i.e jump back 9 words */
+ off = (-9) & 0x000000FF;
+ append_jump(rjobd, (off << JUMP_OFFSET_SHIFT));
+
+ /* ld: deco-deco-ctrl len=0 offs=8 imm -auto-nfifo-entries */
+ append_cmd(rjobd, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
+
+ /* seqfifold: both msgdata-last2-last1-flush1 len=4 */
+ append_seq_fifo_load(rjobd, msg_len, FIFOLD_TYPE_MSG |
+ FIFOLD_CLASS_BOTH | FIFOLD_TYPE_LAST1 |
+ FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_FLUSH1);
+
+ /* ld: deco-deco-ctrl len=0 offs=4 imm +auto-nfifo-entries */
+ append_cmd(rjobd, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
+
+ /* message "Modify anti replay window for SA n" */
+ append_move(rjobd, MOVE_SRC_INFIFO | MOVE_DEST_OUTFIFO | msg_len);
+
+ /* seqfifostr: msgdata len=4 */
+ append_seq_fifo_store(rjobd, FIFOST_TYPE_MESSAGE_DATA, msg_len);
+
+ /*
+ * Exit replacement job descriptor, halt with user error
+ * FD status will be a special user error, generated only on request by
+ * a descriptor command (not by any other circumstance) i.e no confusing
+ * this frame for any other error. Jump with CALM to be sure previous
+ * operation was finished
+ */
+ append_cmd(rjobd, 0xA1C01002);
+
+ dma_unmap_single(sa->dpa_ipsec->jrdev, dma_shdesc,
+ desc_len(sa->sec_desc->desc) * sizeof(u32),
+ DMA_BIDIRECTIONAL);
+
+ return 0;
+}
+
+/*
+ * The SEQ number value will be placed at the address specified by SEQ pointer
+ */
+int build_rjob_desc_seq_read(struct dpa_ipsec_sa *sa, u32 msg_len)
+{
+ uint32_t *rjobd, off_b = 0, off;
+ dma_addr_t dma_shdesc, out_addr;
+
+ /* Check input parameters */
+ BUG_ON(!sa);
+ BUG_ON(!sa->sec_desc);
+
+ /* Get DMA address for this SA shared descriptor */
+ dma_shdesc = dma_map_single(sa->dpa_ipsec->jrdev, sa->sec_desc->desc,
+ desc_len(sa->sec_desc->desc) * sizeof(u32),
+ DMA_BIDIRECTIONAL);
+ if (!dma_shdesc) {
+ log_err("Failed DMA map shared descriptor for SA %d\n", sa->id);
+ return -ENXIO;
+ }
+
+ /* Get DMA address for this SA shared descriptor */
+ out_addr = dma_map_single(sa->dpa_ipsec->jrdev, &sa->r_seq_num,
+ sizeof(sa->r_seq_num), DMA_BIDIRECTIONAL);
+ if (!out_addr) {
+ log_err("Failed DMA map output address for SA %d\n", sa->id);
+ dma_unmap_single(sa->dpa_ipsec->jrdev, dma_shdesc,
+ desc_len(sa->sec_desc->desc) * sizeof(u32),
+ DMA_BIDIRECTIONAL);
+ return -ENXIO;
+ }
+
+ /* Create replacement job descriptor for SEQ/ESEQ Number update */
+ BUG_ON(!sa->rjob_desc);
+ rjobd = sa->rjob_desc;
+
+ init_job_desc(rjobd, HDR_SHARE_SERIAL | HDR_SHARED | HDR_REVERSE |
+ (desc_len(sa->sec_desc->desc) << HDR_START_IDX_SHIFT));
+
+ /* Set DMA address of the shared descriptor */
+ append_ptr(rjobd, dma_shdesc);
+
+ /* Retrieve SEQ number from PDB in MATH 0 - offset is in bytes */
+ off_b = sa_is_inbound(sa) ?
+ offsetof(struct ipsec_decap_pdb, seq_num_ext_hi) + sizeof(u32) :
+ offsetof(struct ipsec_encap_pdb, seq_num_ext_hi) + sizeof(u32);
+
+ append_move(rjobd, MOVE_SRC_DESCBUF | MOVE_DEST_MATH0 | MOVE_WAITCOMP |
+ (off_b << MOVE_OFFSET_SHIFT) | sizeof(u64));
+
+ /* Store SEQ number - length is in bytes */
+ append_store(rjobd, out_addr, sizeof(sa->r_seq_num),
+ LDST_CLASS_DECO | LDST_SRCDST_WORD_DECO_MATH0);
+
+ /* wait for completion of previous operation */
+ append_jump(rjobd, JUMP_COND_CALM | (1 << JUMP_OFFSET_SHIFT));
+
+ /*
+ * Overwrite RJD immediately after the SHD pointer i.e shared descriptor
+ * length plus 1 plus another 3 words
+ * Offset and length are expressed in words
+ * 3w - RJD header + SHD pointer
+ * 5w - five instructions for doing some part of SEQ number modification
+ * 3w - load instruction + pointer
+ * 1w - jump calm
+ * 1w - jump back to the remaining descriptor
+ */
+ append_load(rjobd, virt_to_phys((void *)(rjobd + 3 + 5 + 3 + 1 + 1)),
+ 6, LDST_CLASS_DECO | LDST_SRCDST_WORD_DESCBUF |
+ ((desc_len(sa->sec_desc->desc) + 3) << LDST_OFFSET_SHIFT));
+
+ /* wait for completion of previous operation */
+ append_jump(rjobd, JUMP_COND_CALM | (1 << JUMP_OFFSET_SHIFT));
+
+ /* jump back to remaining descriptor i.e jump back 9 words */
+ off = (-9) & 0x000000FF;
+ append_jump(rjobd, (off << JUMP_OFFSET_SHIFT));
+
+ /*
+ * The following instructions are used to copy the completion
+ * message into the output frame
+ */
+
+ /* ld: deco-deco-ctrl len=0 offs=8 imm -auto-nfifo-entries */
+ append_cmd(rjobd, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
+
+ /* seqfifold: both msgdata-last2-last1-flush1 len=4 */
+ append_seq_fifo_load(rjobd, msg_len, FIFOLD_TYPE_MSG |
+ FIFOLD_CLASS_BOTH | FIFOLD_TYPE_LAST1 |
+ FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_FLUSH1);
+
+ /* ld: deco-deco-ctrl len=0 offs=4 imm +auto-nfifo-entries */
+ append_cmd(rjobd, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
+
+ /* copy completion message */
+ append_move(rjobd, MOVE_SRC_INFIFO | MOVE_DEST_OUTFIFO | msg_len);
+
+ /* seqfifostr: msgdata len=4 */
+ append_seq_fifo_store(rjobd, FIFOST_TYPE_MESSAGE_DATA, msg_len);
+
+ /*
+ * Exit replacement job descriptor, halt with user error
+ * FD status will be a special user error, generated only on request by
+ * a descriptor command
+ */
+ append_cmd(rjobd, 0xA1C01002);
+
+ dma_unmap_single(sa->dpa_ipsec->jrdev, dma_shdesc,
+ desc_len(sa->sec_desc->desc) * sizeof(u32),
+ DMA_BIDIRECTIONAL);
+
+ dma_unmap_single(sa->dpa_ipsec->jrdev, out_addr,
+ sizeof(sa->r_seq_num),
+ DMA_BIDIRECTIONAL);
+
+ return 0;
+}
+
+/*
+ * The SEQ number value will be read from the SA structure and written to PDB of
+ * the shared descriptor corresponding to this SA
+ */
+int build_rjob_desc_seq_write(struct dpa_ipsec_sa *sa, u32 msg_len)
+{
+ uint32_t *rjobd, off_b, off = 0;
+ dma_addr_t dma_shdesc, in_addr;
+
+ /* Check input parameters */
+ BUG_ON(!sa);
+ BUG_ON(!sa->sec_desc);
+
+ /* Get DMA address for this SA shared descriptor */
+ dma_shdesc = dma_map_single(sa->dpa_ipsec->jrdev, sa->sec_desc->desc,
+ desc_len(sa->sec_desc->desc) * sizeof(u32),
+ DMA_BIDIRECTIONAL);
+ if (!dma_shdesc) {
+ log_err("Failed DMA map shared descriptor for SA %d\n", sa->id);
+ return -ENXIO;
+ }
+
+ in_addr = dma_map_single(sa->dpa_ipsec->jrdev, &sa->w_seq_num,
+ sizeof(sa->w_seq_num), DMA_BIDIRECTIONAL);
+ if (!in_addr) {
+ log_err("Failed DMA map output address for SA %d\n", sa->id);
+ dma_unmap_single(sa->dpa_ipsec->jrdev, dma_shdesc,
+ desc_len(sa->sec_desc->desc) * sizeof(u32),
+ DMA_BIDIRECTIONAL);
+ return -ENXIO;
+ }
+
+ /* Create replacement job descriptor for SEQ/ESEQ Number update */
+ BUG_ON(!sa->rjob_desc);
+ rjobd = sa->rjob_desc;
+
+ init_job_desc(rjobd, HDR_SHARE_SERIAL | HDR_SHARED | HDR_REVERSE |
+ (desc_len(sa->sec_desc->desc) << HDR_START_IDX_SHIFT));
+
+ /* Set DMA address of the shared descriptor */
+ append_ptr(rjobd, dma_shdesc);
+
+ /* Copy from SA SEQ to descriptor - offset & length is in words */
+ off_b = sa_is_inbound(sa) ?
+ offsetof(struct ipsec_decap_pdb, seq_num_ext_hi) + sizeof(u32) :
+ offsetof(struct ipsec_encap_pdb, seq_num_ext_hi) + sizeof(u32);
+
+ append_load(rjobd, in_addr, sizeof(sa->w_seq_num) / sizeof(u32),
+ LDST_CLASS_DECO | LDST_SRCDST_WORD_DESCBUF |
+ (off_b / sizeof(u32)) << LDST_OFFSET_SHIFT);
+
+ /* wait for completion of previous operation */
+ append_jump(rjobd, JUMP_COND_CALM | (1 << JUMP_OFFSET_SHIFT));
+
+ /*
+ * Update shared descriptor in memory - only PDB
+ * special case - offset and length are in words
+ */
+ append_store(rjobd, 0, sizeof(sa->w_seq_num) / sizeof(u32),
+ LDST_CLASS_DECO |
+ (off_b / sizeof(u32) << LDST_OFFSET_SHIFT) |
+ LDST_SRCDST_WORD_DESCBUF_SHARED);
+
+ /*
+ * Overwrite RJD immediately after the SHD pointer i.e shared descriptor
+ * length plus 1 plus another 3 words
+ * Offset and length are expressed in words
+ * 3w - RJD header + SHD pointer
+ * 5w - five instructions for doing some part of SEQ number modification
+ * 3w - load instruction + pointer
+ * 1w - jump calm
+ * 1w - jump back to the remaining descriptor
+ */
+ append_load(rjobd, virt_to_phys((void *)(rjobd + 3 + 5 + 3 + 1 + 1)),
+ 6, LDST_CLASS_DECO | LDST_SRCDST_WORD_DESCBUF |
+ ((desc_len(sa->sec_desc->desc) + 3) << LDST_OFFSET_SHIFT));
+
+ /* wait for completion o previous operation */
+ append_jump(rjobd, JUMP_COND_CALM | (1 << JUMP_OFFSET_SHIFT));
+
+ /* jump back to remaining descriptor i.e jump back 9 words */
+ off = (-9) & 0x000000FF;
+ append_jump(rjobd, (off << JUMP_OFFSET_SHIFT));
+
+ /*
+ * The following instructions are used to copy the completion
+ * message into the output frame
+ */
+
+ /* ld: deco-deco-ctrl len=0 offs=8 imm -auto-nfifo-entries */
+ append_cmd(rjobd, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
+
+ /* seqfifold: both msgdata-last2-last1-flush1 len=4 */
+ append_seq_fifo_load(rjobd, msg_len, FIFOLD_TYPE_MSG |
+ FIFOLD_CLASS_BOTH | FIFOLD_TYPE_LAST1 |
+ FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_FLUSH1);
+
+ /* ld: deco-deco-ctrl len=0 offs=4 imm +auto-nfifo-entries */
+ append_cmd(rjobd, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
+
+ /* copy completion message */
+ append_move(rjobd, MOVE_SRC_INFIFO | MOVE_DEST_OUTFIFO | msg_len);
+
+ /* seqfifostr: msgdata len=4 */
+ append_seq_fifo_store(rjobd, FIFOST_TYPE_MESSAGE_DATA, msg_len);
+
+ /*
+ * Exit replacement job descriptor, halt with user error
+ * FD status will be a special user error, generated only on request by
+ * a descriptor command (not by any other error)
+ */
+ append_cmd(rjobd, 0xA1C01002);
+
+ dma_unmap_single(sa->dpa_ipsec->jrdev, dma_shdesc,
+ desc_len(sa->sec_desc->desc) * sizeof(u32),
+ DMA_BIDIRECTIONAL);
+
+ dma_unmap_single(sa->dpa_ipsec->jrdev, in_addr,
+ sizeof(sa->w_seq_num),
+ DMA_BIDIRECTIONAL);
+
+ return 0;
+}
+
+static void split_key_done(struct device *dev, u32 *desc, u32 err,
+ void *context)
+{
+ register atomic_t *done = context;
+
+ if (err) {
+ char tmp[256];
+ dev_err(dev, "%s\n", caam_jr_strstatus(tmp, err));
+ }
+ atomic_set(done, 1);
+}
+
+/* determine the HASH algorithm and the coresponding split key length */
+int get_split_key_info(struct auth_params *auth_param, u32 *hmac_alg)
+{
+ /*
+ * Sizes for MDHA pads (*not* keys): MD5, SHA1, 224, 256, 384, 512
+ * Running digest size
+ */
+ const u8 mdpadlen[] = {16, 20, 32, 32, 64, 64};
+
+ switch (auth_param->auth_type) {
+ case OP_PCL_IPSEC_HMAC_MD5_96:
+ case OP_PCL_IPSEC_HMAC_MD5_128:
+ *hmac_alg = OP_ALG_ALGSEL_MD5;
+ break;
+ case OP_PCL_IPSEC_HMAC_SHA1_96:
+ case OP_PCL_IPSEC_HMAC_SHA1_160:
+ *hmac_alg = OP_ALG_ALGSEL_SHA1;
+ break;
+ case OP_PCL_IPSEC_HMAC_SHA2_256_128:
+ *hmac_alg = OP_ALG_ALGSEL_SHA256;
+ break;
+ case OP_PCL_IPSEC_HMAC_SHA2_384_192:
+ *hmac_alg = OP_ALG_ALGSEL_SHA384;
+ break;
+ case OP_PCL_IPSEC_HMAC_SHA2_512_256:
+ *hmac_alg = OP_ALG_ALGSEL_SHA512;
+ break;
+ case OP_PCL_IPSEC_AES_XCBC_MAC_96:
+ *hmac_alg = 0;
+ auth_param->split_key_len = 0;
+ break;
+ default:
+ log_err("Unsupported authentication algorithm\n");
+ return -EINVAL;
+ }
+
+ if (*hmac_alg)
+ auth_param->split_key_len =
+ mdpadlen[(*hmac_alg & OP_ALG_ALGSEL_SUBMASK) >>
+ OP_ALG_ALGSEL_SHIFT] * 2;
+
+ return 0;
+}
+
+int generate_split_key(struct auth_params *auth_param)
+{
+ struct device *jrdev;
+ dma_addr_t dma_addr_in, dma_addr_out;
+ u32 *desc, timeout = 1000000, alg_sel = 0;
+ struct dpa_ipsec_sa *sa;
+ atomic_t done;
+ int ret = 0;
+
+ sa = container_of(auth_param, struct dpa_ipsec_sa, auth_data);
+ BUG_ON(!sa->dpa_ipsec);
+
+ ret = get_split_key_info(auth_param, &alg_sel);
+ /* exit if error or there is no need to compute a split key */
+ if (ret < 0 || alg_sel == 0)
+ return ret;
+
+ jrdev = get_jrdev(sa->dpa_ipsec);
+ if (!jrdev) {
+ log_err("Could not get job ring device, please check dts\n");
+ return -ENODEV;
+ }
+
+ desc = kmalloc(CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA);
+ if (!desc) {
+ log_err("Allocate memory failed for split key desc\n");
+ return -ENOMEM;
+ }
+
+ auth_param->split_key_pad_len = ALIGN(auth_param->split_key_len, 16);
+
+ dma_addr_in = dma_map_single(jrdev, auth_param->auth_key,
+ auth_param->auth_key_len, DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, dma_addr_in)) {
+ dev_err(jrdev, "Unable to DMA map the input key address\n");
+ kfree(desc);
+ return -ENOMEM;
+ }
+
+ dma_addr_out = dma_map_single(jrdev, auth_param->split_key,
+ auth_param->split_key_pad_len,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(jrdev, dma_addr_out)) {
+ dev_err(jrdev, "Unable to DMA map the output key address\n");
+ dma_unmap_single(jrdev, dma_addr_in, auth_param->auth_key_len,
+ DMA_TO_DEVICE);
+ kfree(desc);
+ return -ENOMEM;
+ }
+
+ init_job_desc(desc, 0);
+
+ append_key(desc, dma_addr_in, auth_param->auth_key_len,
+ CLASS_2 | KEY_DEST_CLASS_REG);
+
+ /* Sets MDHA up into an HMAC-INIT */
+ append_operation(desc, (OP_ALG_TYPE_CLASS2 << OP_ALG_TYPE_SHIFT) |
+ alg_sel | OP_ALG_AAI_HMAC |
+ OP_ALG_DECRYPT | OP_ALG_AS_INIT);
+
+ /* Do a FIFO_LOAD of zero, this will trigger the internal key expansion
+ into both pads inside MDHA */
+ append_fifo_load_as_imm(desc, NULL, 0, LDST_CLASS_2_CCB |
+ FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST2);
+
+ /* FIFO_STORE with the explicit split-key content store
+ * (0x26 output type) */
+ append_fifo_store(desc, dma_addr_out, auth_param->split_key_len,
+ LDST_CLASS_2_CCB | FIFOST_TYPE_SPLIT_KEK);
+
+ atomic_set(&done, 0);
+ ret = caam_jr_enqueue(jrdev, desc, split_key_done, &done);
+
+ while (!atomic_read(&done) && --timeout) {
+ udelay(1);
+ cpu_relax();
+ }
+
+ if (timeout == 0)
+ log_err("Timeout waiting for job ring to complete\n");
+
+ dma_unmap_single(jrdev, dma_addr_out, auth_param->split_key_pad_len,
+ DMA_FROM_DEVICE);
+ dma_unmap_single(jrdev, dma_addr_in, auth_param->auth_key_len,
+ DMA_TO_DEVICE);
+ kfree(desc);
+ return ret;
+}
diff --git a/drivers/staging/fsl_dpa_offload/dpa_ipsec_desc.h b/drivers/staging/fsl_dpa_offload/dpa_ipsec_desc.h
new file mode 100644
index 0000000..15fc056
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dpa_ipsec_desc.h
@@ -0,0 +1,98 @@
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _DPA_IPSEC_DESC_H_
+#define _DPA_IPSEC_DESC_H_
+
+#include "pdb.h"
+#include "dpa_ipsec.h"
+#include "desc_constr.h"
+
+#define DPA_IPSEC_STATS_LEN 2 /* length in words */
+#define MAX_CAAM_SHARED_DESCSIZE 50 /* If CAAM used with QI the maximum
+ * shared descriptor length is 50 words
+ */
+
+/* preheader */
+struct preheader {
+ union {
+ uint32_t word;
+ struct {
+ uint16_t rsvd63_48;
+ unsigned int rsvd47_39:9;
+ unsigned int idlen:7;
+ } field;
+ } __packed hi;
+
+ union {
+ uint32_t word;
+ struct {
+ unsigned int rsvd31_30:2;
+ unsigned int fsgt:1;
+ unsigned int lng:1;
+ unsigned int offset:2;
+ unsigned int abs:1;
+ unsigned int add_buf:1;
+ uint8_t pool_id;
+ uint16_t pool_buffer_size;
+ } field;
+ } __packed lo;
+} __packed;
+
+struct desc_hdr {
+ uint32_t hdr_word;
+ union {
+ struct ipsec_encap_pdb pdb_en;
+ struct ipsec_decap_pdb pdb_dec;
+ };
+};
+
+struct sec_descriptor {
+ struct preheader preheader; /* SEC preheader */
+ /* SEC Shared Descriptor */
+ union {
+ uint32_t desc[MAX_CAAM_DESCSIZE];
+ struct desc_hdr desc_hdr;
+#define hdr_word desc_hdr.hdr_word
+#define pdb_en desc_hdr.pdb_en
+#define pdb_dec desc_hdr.pdb_dec
+ };
+};
+
+int get_sec_info(struct dpa_ipsec *dpa_ipsec);
+int create_sec_descriptor(struct dpa_ipsec_sa *sa);
+int generate_split_key(struct auth_params *auth_param);
+int build_rjob_desc_ars_update(struct dpa_ipsec_sa *sa, enum dpa_ipsec_arw arw,
+ u32 msg_len);
+int build_rjob_desc_seq_read(struct dpa_ipsec_sa *sa, u32 msg_len);
+int build_rjob_desc_seq_write(struct dpa_ipsec_sa *sa, u32 msg_len);
+
+#endif /* _DPA_IPSEC_DESC_H_ */
diff --git a/drivers/staging/fsl_dpa_offload/dpa_ipsec_ioctl.h b/drivers/staging/fsl_dpa_offload/dpa_ipsec_ioctl.h
new file mode 100644
index 0000000..9d1da46
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dpa_ipsec_ioctl.h
@@ -0,0 +1,331 @@
+
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * DPA IPsec Wrapper Application Programming Interface
+ */
+
+#ifndef __DPA_IPSEC_IOCTL_H
+#define __DPA_IPSEC_IOCTL_H
+
+#include "linux/ioctl.h"
+#ifdef CONFIG_COMPAT
+#include "linux/compat.h"
+#include "dpa_classifier_ioctl.h"
+#endif
+
+struct ioc_dpa_ipsec_params {
+ struct dpa_ipsec_params dpa_ipsec_params;
+ int dpa_ipsec_id;
+};
+
+#ifdef CONFIG_COMPAT
+struct ioc_compat_ipsec_init_params {
+ struct dpa_ipsec_pre_sec_in_params pre_sec_in_params;
+ struct dpa_ipsec_post_sec_in_params post_sec_in_params;
+ struct dpa_ipsec_pre_sec_out_params pre_sec_out_params;
+ struct dpa_ipsec_post_sec_out_params post_sec_out_params;
+ compat_uptr_t fm_pcd;
+ uint16_t qm_sec_ch;
+ uint16_t max_sa_pairs;
+ uint32_t max_sa_manip_ops;
+ compat_uptr_t fqid_range;
+ uint8_t ipf_bpid;
+};
+
+struct ioc_compat_dpa_ipsec_params {
+ struct ioc_compat_ipsec_init_params dpa_ipsec_params;
+ int dpa_ipsec_id;
+};
+#endif
+
+struct ioc_dpa_ipsec_sa_params {
+ int dpa_ipsec_id;
+ struct dpa_ipsec_sa_params sa_params;
+ int sa_id;
+};
+
+#ifdef CONFIG_COMPAT
+struct ioc_compat_sa_init_vector {
+ compat_uptr_t init_vector;
+ uint8_t length;
+};
+
+struct ioc_compat_sa_crypto_params {
+ enum dpa_ipsec_cipher_alg alg_suite;
+ compat_uptr_t cipher_key;
+ uint8_t cipher_key_len;
+ compat_uptr_t auth_key;
+ uint8_t auth_key_len;
+};
+
+struct ioc_compat_sa_out_params {
+ compat_uptr_t init_vector;
+ unsigned int ip_ver;
+ uint16_t ip_hdr_size;
+ compat_uptr_t outer_ip_header;
+ compat_uptr_t outer_udp_header;
+ uint16_t post_sec_flow_id;
+};
+
+struct ioc_compat_sa_in_params {
+ enum dpa_ipsec_arw arw;
+ bool use_var_iphdr_len;
+ struct dpa_offload_ip_address src_addr;
+ struct dpa_offload_ip_address dest_addr;
+ bool use_udp_encap;
+ uint16_t src_port;
+ uint16_t dest_port;
+ struct dpa_cls_compat_tbl_action policy_miss_action;
+ struct dpa_cls_compat_tbl_action post_ipsec_action;
+};
+
+struct ioc_compat_sa_params {
+ uint32_t spi;
+ bool use_ext_seq_num;
+ uint64_t start_seq_num;
+ uint32_t l2_hdr_size;
+ enum dpa_ipsec_sa_mode sa_mode;
+ enum dpa_ipsec_sa_proto sa_proto;
+ uint8_t hdr_upd_flags;
+ uint8_t sa_wqid;
+ uint8_t sa_bpid;
+ uint16_t sa_bufsize;
+ bool enable_stats;
+ bool enable_extended_stats;
+ struct ioc_compat_sa_crypto_params crypto_params;
+ enum dpa_ipsec_direction sa_dir;
+ union {
+ struct ioc_compat_sa_in_params sa_in_params;
+ struct ioc_compat_sa_out_params sa_out_params;
+ };
+};
+
+struct ioc_compat_dpa_ipsec_sa_params {
+ int dpa_ipsec_id;
+ struct ioc_compat_sa_params sa_params;
+ int sa_id;
+};
+#endif
+
+struct ioc_dpa_ipsec_add_rem_policy {
+ struct dpa_ipsec_policy_params pol_params;
+ int sa_id;
+};
+
+#ifdef CONFIG_COMPAT
+struct ioc_compat_pol_dir_params {
+ enum dpa_ipsec_pol_dir_params_type type;
+ union {
+ int manip_desc;
+ struct dpa_cls_compat_tbl_action in_action;
+ };
+};
+
+struct ioc_compat_policy_params {
+ struct dpa_offload_ip_address src_addr;
+ uint8_t src_prefix_len;
+ struct dpa_offload_ip_address dest_addr;
+ uint8_t dest_prefix_len;
+ uint8_t protocol;
+ bool masked_proto;
+ union {
+ struct dpa_ipsec_l4_params l4;
+ struct dpa_ipsec_icmp_params icmp;
+ };
+ struct ioc_compat_pol_dir_params dir_params;
+ int priority; /* Policy priority */
+};
+
+struct ioc_compat_dpa_ipsec_add_rem_policy {
+ struct ioc_compat_policy_params pol_params;
+ int sa_id;
+};
+#endif
+
+struct ioc_dpa_ipsec_rekey_prm {
+ struct dpa_ipsec_sa_params sa_params;
+ int auto_rmv_old_sa;
+ int sa_id; /* old sa id */
+ int new_sa_id; /* newly created sa id */
+};
+
+#ifdef CONFIG_COMPAT
+struct ioc_compat_dpa_ipsec_rekey_prm {
+ struct ioc_compat_sa_params sa_params;
+ int auto_rmv_old_sa;
+ int sa_id; /* old sa id */
+ int new_sa_id; /* newly created sa id */
+};
+#endif
+
+struct ioc_dpa_ipsec_get_policies {
+ int sa_id; /* sa id */
+ struct dpa_ipsec_policy_params *policy_params;
+ int num_pol; /* number of policies */
+};
+
+#ifdef CONFIG_COMPAT
+struct ioc_compat_dpa_ipsec_get_policies {
+ int sa_id; /* sa id */
+ compat_uptr_t policy_params;
+ int num_pol; /* number of policies */
+};
+#endif
+
+struct ioc_dpa_ipsec_sa_get_stats {
+ int sa_id; /* sa id */
+ struct dpa_ipsec_sa_stats sa_stats;
+};
+
+struct ioc_dpa_ipsec_instance_stats {
+ int instance_id;
+ struct dpa_ipsec_stats stats;
+};
+
+struct ioc_dpa_ipsec_sa_modify_prm {
+ int sa_id; /* security association id */
+ struct dpa_ipsec_sa_modify_prm modify_prm;
+};
+
+struct ioc_dpa_ipsec_sa_get_seq_num {
+ int sa_id; /* security association id */
+ uint64_t seq; /* where to write the SEQ number */
+};
+
+#ifdef CONFIG_COMPAT
+struct compat_dpa_ipsec_sa_modify_prm {
+ enum dpa_ipsec_sa_modify_type type;
+ union {
+ enum dpa_ipsec_arw arw;
+ uint32_t seq;
+ uint64_t ext_seq;
+ struct ioc_compat_sa_crypto_params crypto_params;
+ };
+};
+
+struct ioc_compat_dpa_ipsec_sa_modify_prm {
+ int sa_id; /* security association id */
+ struct compat_dpa_ipsec_sa_modify_prm modify_prm;
+};
+#endif
+
+struct ioc_dpa_ipsec_sa_get_out_path {
+ int sa_id; /* security association id */
+ uint32_t fqid; /* where to write the frame queue id number */
+};
+
+#define DPA_IPSEC_IOC_MAGIC 0xee
+
+#define DPA_IPSEC_IOC_INIT \
+ _IOWR(DPA_IPSEC_IOC_MAGIC, 0, struct ioc_dpa_ipsec_params)
+#ifdef CONFIG_COMPAT
+#define DPA_IPSEC_IOC_INIT_COMPAT \
+ _IOWR(DPA_IPSEC_IOC_MAGIC, 0, \
+ struct ioc_compat_dpa_ipsec_params)
+#endif
+
+#define DPA_IPSEC_IOC_FREE \
+ _IOW(DPA_IPSEC_IOC_MAGIC, 1, int)
+
+#define DPA_IPSEC_IOC_CREATE_SA \
+ _IOWR(DPA_IPSEC_IOC_MAGIC, 2, struct ioc_dpa_ipsec_sa_params)
+#ifdef CONFIG_COMPAT
+#define DPA_IPSEC_IOC_CREATE_SA_COMPAT \
+ _IOWR(DPA_IPSEC_IOC_MAGIC, 2, \
+ struct ioc_compat_dpa_ipsec_sa_params)
+#endif
+
+#define DPA_IPSEC_IOC_REMOVE_SA \
+ _IOW(DPA_IPSEC_IOC_MAGIC, 3, int)
+
+#define DPA_IPSEC_IOC_ADD_POLICY \
+ _IOW(DPA_IPSEC_IOC_MAGIC, 4, struct ioc_dpa_ipsec_add_rem_policy)
+#ifdef CONFIG_COMPAT
+#define DPA_IPSEC_IOC_ADD_POLICY_COMPAT \
+ _IOW(DPA_IPSEC_IOC_MAGIC, 4, struct ioc_compat_dpa_ipsec_add_rem_policy)
+#endif
+
+#define DPA_IPSEC_IOC_REMOVE_POLICY \
+ _IOW(DPA_IPSEC_IOC_MAGIC, 5, struct ioc_dpa_ipsec_add_rem_policy)
+#ifdef CONFIG_COMPAT
+#define DPA_IPSEC_IOC_REMOVE_POLICY_COMPAT \
+ _IOW(DPA_IPSEC_IOC_MAGIC, 5, struct ioc_compat_dpa_ipsec_add_rem_policy)
+#endif
+
+#define DPA_IPSEC_IOC_SA_REKEYING \
+ _IOWR(DPA_IPSEC_IOC_MAGIC, 6, struct ioc_dpa_ipsec_rekey_prm)
+#ifdef CONFIG_COMPAT
+#define DPA_IPSEC_IOC_SA_REKEYING_COMPAT \
+ _IOWR(DPA_IPSEC_IOC_MAGIC, 6, struct ioc_compat_dpa_ipsec_rekey_prm)
+#endif
+
+#define DPA_IPSEC_IOC_FLUSH_ALL_SA \
+ _IOW(DPA_IPSEC_IOC_MAGIC, 7, int)
+
+#define DPA_IPSEC_IOC_GET_SA_POLICIES \
+ _IOWR(DPA_IPSEC_IOC_MAGIC, 8, struct ioc_dpa_ipsec_get_policies)
+#ifdef CONFIG_COMPAT
+#define DPA_IPSEC_IOC_GET_SA_POLICIES_COMPAT \
+ _IOWR(DPA_IPSEC_IOC_MAGIC, 8, struct ioc_compat_dpa_ipsec_get_policies)
+#endif
+
+#define DPA_IPSEC_IOC_FLUSH_SA_POLICIES \
+ _IOW(DPA_IPSEC_IOC_MAGIC, 9, int)
+
+#define DPA_IPSEC_IOC_DISABLE_SA \
+ _IOW(DPA_IPSEC_IOC_MAGIC, 10, int)
+
+#define DPA_IPSEC_IOC_GET_SA_STATS \
+ _IOWR(DPA_IPSEC_IOC_MAGIC, 11, struct ioc_dpa_ipsec_sa_get_stats)
+
+#define DPA_IPSEC_IOC_SA_MODIFY \
+ _IOW(DPA_IPSEC_IOC_MAGIC, 12, struct ioc_dpa_ipsec_sa_modify_prm)
+#ifdef CONFIG_COMPAT
+#define DPA_IPSEC_IOC_SA_MODIFY_COMPAT \
+ _IOW(DPA_IPSEC_IOC_MAGIC, 12, \
+ struct ioc_compat_dpa_ipsec_sa_modify_prm)
+#endif
+
+#define DPA_IPSEC_IOC_GET_STATS \
+ _IOWR(DPA_IPSEC_IOC_MAGIC, 13, struct ioc_dpa_ipsec_instance_stats)
+
+#define DPA_IPSEC_IOC_SA_REQUEST_SEQ_NUMBER \
+ _IOW(DPA_IPSEC_IOC_MAGIC, 14, int)
+
+#define DPA_IPSEC_IOC_SA_GET_SEQ_NUMBER \
+ _IOWR(DPA_IPSEC_IOC_MAGIC, 15, struct ioc_dpa_ipsec_sa_get_seq_num)
+
+#define DPA_IPSEC_IOC_SA_GET_OUT_PATH \
+ _IOWR(DPA_IPSEC_IOC_MAGIC, 16, struct ioc_dpa_ipsec_sa_get_out_path)
+
+#endif /* __DPA_IPSEC_IOCTL_H */
diff --git a/drivers/staging/fsl_dpa_offload/dpa_offload_module.c b/drivers/staging/fsl_dpa_offload/dpa_offload_module.c
new file mode 100644
index 0000000..aaf6693
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dpa_offload_module.c
@@ -0,0 +1,102 @@
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * DPA Offloading driver implementation
+ */
+
+#include <linux/module.h>
+
+#include "dpa_offload_module.h"
+#include "wrp_dpa_classifier.h"
+#include "wrp_dpa_ipsec.h"
+#include "wrp_dpa_stats.h"
+
+static int __init dpa_offload_drv_init(void)
+{
+ int err;
+
+ /* Initialize DPA Classifier wrapper to listen to [ioctl] calls */
+ err = wrp_dpa_classif_init();
+ if (err == 0)
+ printk(KERN_INFO"DPA Classifier Driver initialized.\n");
+ else {
+ printk(KERN_ERR"DPA Classifier Driver failed to initialize.\n");
+ return err;
+ }
+
+ /* Initialize DPA IPSec wrapper to listen to [ioctl] calls */
+ err = wrp_dpa_ipsec_init();
+ if (err == 0)
+ printk(KERN_INFO"DPA IPSec Driver initialized.\n");
+ else {
+ printk(KERN_ERR"DPA IPSec Driver failed to initialize.\n");
+ return err;
+ }
+
+ /* Initialize DPA Stats wrapper to listen to [ioctl] calls */
+ err = wrp_dpa_stats_init();
+ if (err == 0)
+ printk(KERN_INFO"DPA Stats Driver initialized.\n");
+ else {
+ printk(KERN_ERR"DPA Stats Driver failed to initialize.\n");
+ return err;
+ }
+ return err;
+}
+module_init(dpa_offload_drv_init);
+
+static void __exit dpa_offload_drv_exit(void)
+{
+ /* Shut down DPA Classifier wrapper */
+ if (wrp_dpa_classif_exit() < 0)
+ printk(KERN_ERR"DPA Classifier Driver failed to unload.\n");
+ else
+ printk(KERN_INFO"DPA Classifier Driver unloaded.\n");
+
+ /* Shut down DPA IPSec wrapper */
+ if (wrp_dpa_ipsec_exit() < 0)
+ printk(KERN_ERR"DPA IPSec Driver failed to unload.\n");
+ else
+ printk(KERN_INFO"INFO: DPA IPSec Driver unloaded.\n");
+
+ /* Shut down DPA Stats wrapper */
+ if (wrp_dpa_stats_exit() < 0)
+ printk(KERN_ERR"DPA Stats Driver failed to unload.\n");
+ else
+ printk(KERN_INFO"INFO: DPA Stats Driver unloaded.\n");
+}
+module_exit(dpa_offload_drv_exit);
+
+MODULE_AUTHOR("Freescale, <freescale.com>");
+MODULE_DESCRIPTION("DPA Offloading Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/staging/fsl_dpa_offload/dpa_offload_module.h b/drivers/staging/fsl_dpa_offload/dpa_offload_module.h
new file mode 100644
index 0000000..e4f3ad1
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dpa_offload_module.h
@@ -0,0 +1,46 @@
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * DPA Offloading driver internal interface
+ */
+
+#ifndef __DPA_OFFLOAD_DRIVER_H
+#define __DPA_OFFLOAD_DRIVER_H
+
+#define DRV_VERSION "1.0"
+
+static int __init dpa_offload_drv_init(void);
+
+static void __exit dpa_offload_drv_exit(void);
+
+
+#endif /* __DPA_OFFLOAD_DRIVER_H */
diff --git a/drivers/staging/fsl_dpa_offload/dpa_stats.c b/drivers/staging/fsl_dpa_offload/dpa_stats.c
new file mode 100644
index 0000000..b3902d0
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dpa_stats.c
@@ -0,0 +1,4534 @@
+/* Copyright 2008-2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * DPA Statistics Application Programming Interface implementation
+ */
+
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include "lnxwrp_fm.h"
+#include "mac.h"
+#include <linux/fsl_qman.h>
+
+/* DPA offloading layer includes */
+#include "dpa_stats.h"
+#include "dpa_classifier.h"
+
+/* FMD includes */
+#include "fm_pcd_ext.h"
+
+#define STATS_VAL_SIZE 4
+#define UNSUPPORTED_CNT_SEL -1
+#define CLASSIF_STATS_SHIFT 4
+#define WORKQUEUE_MAX_ACTIVE 3
+
+#define DPA_STATS_US_CNT 0x80000000
+
+
+/* Global dpa_stats component */
+struct dpa_stats *gbl_dpa_stats;
+
+static int alloc_cnt_stats(struct stats_info *stats_info,
+ unsigned int num_members);
+
+static void init_cnt_32bit_stats(struct stats_info *stats_info,
+ void *stats, uint32_t idx);
+
+static void init_cnt_64bit_stats(struct stats_info *stats_info,
+ void *stats, uint32_t idx);
+
+static int get_cnt_cls_tbl_frag_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb);
+
+static int get_cnt_cls_tbl_match_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb);
+
+static int get_cnt_cls_tbl_hash_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb);
+
+static int get_cnt_cls_tbl_index_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb);
+
+static int get_cnt_ccnode_match_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb);
+
+static int get_cnt_ccnode_hash_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb);
+
+static int get_cnt_ccnode_index_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb);
+
+static int get_cnt_traffic_mng_cq_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb);
+
+static int get_cnt_traffic_mng_ccg_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb);
+
+static int get_cnt_us_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb);
+
+static void async_req_work_func(struct work_struct *work);
+
+/* check that the provided params are valid */
+static int check_dpa_stats_params(const struct dpa_stats_params *params)
+{
+ /* Check init parameters */
+ if (!params) {
+ log_err("DPA Stats instance parameters cannot be NULL\n");
+ return -EINVAL;
+ }
+
+ /* There must be at least one counter */
+ if (params->max_counters == 0 ||
+ params->max_counters > DPA_STATS_MAX_NUM_OF_COUNTERS) {
+ log_err("Parameter max_counters %d must be in range (1 - %d)\n",
+ params->max_counters, DPA_STATS_MAX_NUM_OF_COUNTERS);
+ return -EDOM;
+ }
+
+ if (!params->storage_area) {
+ log_err("Parameter storage_area cannot be NULL\n");
+ return -EINVAL;
+ }
+
+ if (params->storage_area_len < STATS_VAL_SIZE) {
+ log_err("Parameter storage_area_len %d cannot be bellow %d\n",
+ params->storage_area_len, STATS_VAL_SIZE);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int set_cnt_classif_tbl_retrieve_func(struct dpa_stats_cnt_cb *cnt_cb)
+{
+ switch (cnt_cb->tbl_cb.type) {
+ case DPA_CLS_TBL_HASH:
+ cnt_cb->f_get_cnt_stats = get_cnt_cls_tbl_hash_stats;
+ break;
+ case DPA_CLS_TBL_INDEXED:
+ cnt_cb->f_get_cnt_stats = get_cnt_cls_tbl_index_stats;
+ break;
+ case DPA_CLS_TBL_EXACT_MATCH:
+ cnt_cb->f_get_cnt_stats = get_cnt_cls_tbl_match_stats;
+ break;
+ default:
+ log_err("Unsupported DPA Classifier table type %d\n",
+ cnt_cb->tbl_cb.type);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int set_cnt_classif_node_retrieve_func(struct dpa_stats_cnt_cb *cnt_cb,
+ enum dpa_stats_classif_node_type ccnode_type)
+{
+ switch (ccnode_type) {
+ case DPA_CLS_TBL_HASH:
+ cnt_cb->f_get_cnt_stats = get_cnt_ccnode_hash_stats;
+ break;
+ case DPA_CLS_TBL_INDEXED:
+ cnt_cb->f_get_cnt_stats = get_cnt_ccnode_index_stats;
+ break;
+ case DPA_CLS_TBL_EXACT_MATCH:
+ cnt_cb->f_get_cnt_stats = get_cnt_ccnode_match_stats;
+ break;
+ default:
+ log_err("Unsupported Classification Node type %d", ccnode_type);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+
+static int get_classif_tbl_key_stats(struct dpa_stats_cnt_cb *cnt_cb,
+ uint32_t idx)
+{
+ struct dpa_stats_lookup_key *entry = &cnt_cb->tbl_cb.keys[idx];
+ t_FmPcdCcKeyStatistics stats;
+ uint8_t *mask_data;
+ int err;
+
+ switch (cnt_cb->tbl_cb.type) {
+ case DPA_CLS_TBL_HASH:
+ err = FM_PCD_HashTableFindNGetKeyStatistics(entry->cc_node,
+ entry->key.data.size, entry->key.data.byte,
+ &stats);
+ if (err != 0) {
+ log_err("Check failed for Classifier Hash Table counter id %d due to incorrect parameters: handle=0x%p, keysize=%d, keybyte=\n",
+ cnt_cb->id, entry->cc_node,
+ entry->key.data.size);
+ dump_lookup_key(&entry->key.data);
+ return -EIO;
+ }
+ break;
+ case DPA_CLS_TBL_INDEXED:
+ err = FM_PCD_MatchTableGetKeyStatistics(
+ entry->cc_node, entry->key.data.byte[0],
+ &stats);
+ if (err != 0) {
+ log_err("Check failed for Classifier Indexed Table counter id %d due to incorrect parameters: handle=0x%p, keysize=%d keybyte=\n",
+ cnt_cb->id, entry->cc_node,
+ entry->key.data.size);
+ dump_lookup_key(&entry->key.data);
+ return -EIO;
+ }
+ break;
+ case DPA_CLS_TBL_EXACT_MATCH:
+ if (entry->key.valid_mask)
+ mask_data = entry->key.data.mask;
+ else
+ mask_data = NULL;
+ err = FM_PCD_MatchTableFindNGetKeyStatistics(entry->cc_node,
+ entry->key.data.size, entry->key.data.byte,
+ mask_data, &stats);
+ if (err != 0) {
+ log_err("Check failed for Classifier Exact Match Table counter id %d due to incorrect parameters: handle=0x%p, keysize=%d, keybyte=\n",
+ cnt_cb->id, entry->cc_node,
+ entry->key.data.size);
+ dump_lookup_key(&entry->key.data);
+ return -EINVAL;
+ }
+ break;
+ default:
+ log_err("Unsupported DPA Classifier table type %d\n",
+ cnt_cb->tbl_cb.type);
+ return -EINVAL;
+ }
+
+ init_cnt_32bit_stats(&cnt_cb->info, &stats, idx);
+
+ return 0;
+}
+
+static int get_ccnode_key_stats(struct dpa_stats_cnt_cb *cnt_cb,
+ enum dpa_stats_classif_node_type ccnode_type,
+ uint32_t idx)
+{
+ struct dpa_stats_allocated_lookup_key *key =
+ &cnt_cb->ccnode_cb.keys[idx];
+ t_FmPcdCcKeyStatistics stats;
+ int err;
+ uint8_t *mask_data;
+
+ switch (ccnode_type) {
+ case DPA_STATS_CLASSIF_NODE_HASH:
+ err = FM_PCD_HashTableFindNGetKeyStatistics(
+ cnt_cb->ccnode_cb.cc_node,
+ key->data.size, key->data.byte, &stats);
+ if (err != 0) {
+ log_err("Check failed for Classification Node counter id %d due to incorrect parameters: handle=0x%p, keysize=%d, keybyte=\n",
+ cnt_cb->id, cnt_cb->ccnode_cb.cc_node,
+ key->data.size);
+ dump_lookup_key(&key->data);
+ return -EINVAL;
+ }
+ break;
+ case DPA_STATS_CLASSIF_NODE_INDEXED:
+ err = FM_PCD_MatchTableGetKeyStatistics(
+ cnt_cb->ccnode_cb.cc_node,
+ key->data.byte[0], &stats);
+ if (err != 0) {
+ log_err("Check failed for Classification Node counter id %d due to incorrect parameters: handle=0x%p, keysize=%d, keybyte=\n",
+ cnt_cb->id, cnt_cb->ccnode_cb.cc_node,
+ key->data.size);
+ dump_lookup_key(&key->data);
+ return -EINVAL;
+ }
+ break;
+ case DPA_STATS_CLASSIF_NODE_EXACT_MATCH:
+ if (key->valid_mask)
+ mask_data = key->data.mask;
+ else
+ mask_data = NULL;
+ err = FM_PCD_MatchTableFindNGetKeyStatistics(
+ cnt_cb->ccnode_cb.cc_node, key->data.size,
+ key->data.byte, mask_data, &stats);
+ if (err != 0) {
+ log_err("Check failed for Classification Node counter id %d due to incorrect parameters: handle=0x%p, keysize=%d, keybyte=\n",
+ cnt_cb->id, cnt_cb->ccnode_cb.cc_node,
+ key->data.size);
+ dump_lookup_key(&key->data);
+ return -EINVAL;
+ }
+ break;
+ default:
+ log_err("Unsupported Classification Node type %d",
+ cnt_cb->tbl_cb.type);
+ return -EINVAL;
+ }
+
+ init_cnt_32bit_stats(&cnt_cb->info, &stats, idx);
+
+ return 0;
+}
+
+static int get_classif_tbl_miss_stats(struct dpa_stats_cnt_cb *cnt_cb,
+ uint32_t idx)
+{
+ struct dpa_stats_lookup_key *key = &cnt_cb->tbl_cb.keys[idx];
+ t_FmPcdCcKeyStatistics stats;
+ int err;
+
+ switch (cnt_cb->tbl_cb.type) {
+ case DPA_CLS_TBL_HASH:
+ err = FM_PCD_HashTableGetMissStatistics(key->cc_node, &stats);
+ if (err != 0) {
+ log_err("Check failed for Classifier Table counter id %d due to incorrect parameters: handle=0x%p\n",
+ cnt_cb->id, key->cc_node);
+ return -EINVAL;
+ }
+ break;
+ case DPA_CLS_TBL_INDEXED:
+ err = FM_PCD_MatchTableGetMissStatistics(key->cc_node, &stats);
+ if (err != 0) {
+ log_err("Check failed for Classifier Table counter id %d due to incorrect parameters: handle=0x%p\n",
+ cnt_cb->id, key->cc_node);
+ return -EINVAL;
+ }
+ break;
+ case DPA_CLS_TBL_EXACT_MATCH:
+ err = FM_PCD_MatchTableGetMissStatistics(key->cc_node, &stats);
+ if (err != 0) {
+ log_err("Check failed for Classifier Table counter id %d due to incorrect parameters: handle=0x%p\n",
+ cnt_cb->id, key->cc_node);
+ return -EINVAL;
+ }
+ break;
+ default:
+ log_err("Unsupported Classifier Table type %d",
+ cnt_cb->tbl_cb.type);
+ return -EINVAL;
+ }
+
+ init_cnt_32bit_stats(&cnt_cb->info, &stats, idx);
+
+ return 0;
+}
+
+
+static int get_ccnode_miss_stats(struct dpa_stats_cnt_cb *cnt_cb,
+ enum dpa_stats_classif_node_type type,
+ uint32_t idx)
+{
+ t_FmPcdCcKeyStatistics stats;
+ int err;
+
+ switch (type) {
+ case DPA_STATS_CLASSIF_NODE_HASH:
+ err = FM_PCD_HashTableGetMissStatistics(
+ cnt_cb->ccnode_cb.cc_node, &stats);
+ if (err != 0) {
+ log_err("Check failed for Classification Node counter id %d due to incorrect parameters: handle=0x%p\n",
+ cnt_cb->id, cnt_cb->ccnode_cb.cc_node);
+ return -EINVAL;
+ }
+ break;
+ case DPA_STATS_CLASSIF_NODE_INDEXED:
+ err = FM_PCD_MatchTableGetMissStatistics(
+ cnt_cb->ccnode_cb.cc_node, &stats);
+ if (err != 0) {
+ log_err("Check failed for Classification Node counter id %d due to incorrect parameters: handle=0x%p\n",
+ cnt_cb->id, cnt_cb->ccnode_cb.cc_node);
+ return -EINVAL;
+ }
+ break;
+ case DPA_STATS_CLASSIF_NODE_EXACT_MATCH:
+ err = FM_PCD_MatchTableGetMissStatistics(
+ cnt_cb->ccnode_cb.cc_node, &stats);
+ if (err != 0) {
+ log_err("Check failed for Classification Node counter id %d due to incorrect parameters: handle=0x%p\n",
+ cnt_cb->id, cnt_cb->ccnode_cb.cc_node);
+ return -EINVAL;
+ }
+ break;
+ default:
+ log_err("Unsupported Classification Node type %d", type);
+ return -EINVAL;
+ }
+
+ init_cnt_32bit_stats(&cnt_cb->info, &stats, idx);
+
+ return 0;
+}
+
+static int get_new_cnt(struct dpa_stats *dpa_stats,
+ struct dpa_stats_cnt_cb **cnt_cb)
+{
+ struct dpa_stats_cnt_cb *new_cnt;
+ uint32_t id;
+ int i;
+
+ /* Acquire DPA Stats instance lock */
+ mutex_lock(&dpa_stats->lock);
+
+ /* Get an id for new Counter */
+ if (cq_get_4bytes(dpa_stats->cnt_id_cq, &id) < 0) {
+ log_err("Cannot create new counter, no more free counter ids available\n");
+ mutex_unlock(&dpa_stats->lock);
+ return -EDOM;
+ }
+
+ /*
+ * Use 'used_cnt_ids' array in order to store counter ids that are
+ * 'in use' . Array can be further used to remove counters
+ */
+ for (i = 0; i < dpa_stats->config.max_counters; i++)
+ if (dpa_stats->used_cnt_ids[i] == DPA_OFFLD_INVALID_OBJECT_ID)
+ break;
+
+ if (i == dpa_stats->config.max_counters) {
+ log_err("Maximum number of available counters %d was reached\n",
+ dpa_stats->config.max_counters);
+ cq_put_4bytes(dpa_stats->cnt_id_cq, id);
+ mutex_unlock(&dpa_stats->lock);
+ return -EDOM;
+ }
+
+ /* Acquire a preallocated Counter Control Block */
+ new_cnt = &dpa_stats->cnts_cb[id];
+ new_cnt->id = id;
+ new_cnt->index = i;
+
+ /* Store on the current position the counter id */
+ dpa_stats->used_cnt_ids[i] = id;
+
+ /* Release DPA Stats instance lock */
+ mutex_unlock(&dpa_stats->lock);
+
+ *cnt_cb = new_cnt;
+
+ return 0;
+}
+
+static int get_new_req(struct dpa_stats *dpa_stats,
+ int *dpa_stats_req_id,
+ struct dpa_stats_req_cb **req_cb)
+{
+ struct dpa_stats_req_cb *new_req;
+ uint32_t id;
+ int i;
+
+ /* Acquire DPA Stats instance lock */
+ mutex_lock(&dpa_stats->lock);
+
+ /* Get an id for a new request */
+ if (cq_get_4bytes(dpa_stats->req_id_cq, &id) < 0) {
+ log_err("Cannot create new request, no more free request ids available\n");
+ mutex_unlock(&dpa_stats->lock);
+ return -EDOM;
+ }
+
+ /*
+ * Use 'used_req_ids' array in order to store requests ids that are
+ * 'in use' . Array can be further used to remove requests
+ */
+ for (i = 0; i < DPA_STATS_MAX_NUM_OF_REQUESTS; i++)
+ if (dpa_stats->used_req_ids[i] == DPA_OFFLD_INVALID_OBJECT_ID)
+ break;
+
+ if (i == DPA_STATS_MAX_NUM_OF_REQUESTS) {
+ log_err("Maximum number of available requests %d was reached\n",
+ DPA_STATS_MAX_NUM_OF_REQUESTS);
+ cq_put_4bytes(dpa_stats->req_id_cq, id);
+ mutex_unlock(&dpa_stats->lock);
+ return -EDOM;
+ }
+
+ /* Acquire a preallocated Request Control Block */
+ new_req = &dpa_stats->reqs_cb[id];
+ new_req->id = id;
+ new_req->index = i;
+
+ /* Store on the current position the request id */
+ dpa_stats->used_req_ids[i] = id;
+
+ /* Release DPA Stats instance lock */
+ mutex_unlock(&dpa_stats->lock);
+
+ *req_cb = new_req;
+ *dpa_stats_req_id = id;
+
+ return 0;
+}
+
+static int put_cnt(struct dpa_stats *dpa_stats, struct dpa_stats_cnt_cb *cnt_cb)
+{
+ int err = 0;
+
+ /* Acquire DPA Stats instance lock */
+ mutex_lock(&dpa_stats->lock);
+
+ /* Release the Counter id in the Counter IDs circular queue */
+ err = cq_put_4bytes(dpa_stats->cnt_id_cq, cnt_cb->id);
+ if (err < 0) {
+ log_err("Cannot release the counter id %d\n", cnt_cb->id);
+ return -EDOM;
+ }
+
+ /* Mark the Counter id as 'not used' */
+ dpa_stats->used_cnt_ids[cnt_cb->index] = DPA_OFFLD_INVALID_OBJECT_ID;
+
+ /* Clear all 'cnt_cb' information */
+ cnt_cb->index = DPA_OFFLD_INVALID_OBJECT_ID;
+ cnt_cb->id = DPA_STATS_MAX_NUM_OF_COUNTERS;
+ cnt_cb->bytes_num = 0;
+ cnt_cb->f_get_cnt_stats = NULL;
+
+ switch (cnt_cb->type) {
+ case DPA_STATS_CNT_ETH:
+ case DPA_STATS_CNT_REASS:
+ case DPA_STATS_CNT_FRAG:
+ case DPA_STATS_CNT_POLICER:
+ memset(&cnt_cb->gen_cb, 0, sizeof(cnt_cb->gen_cb));
+ break;
+ case DPA_STATS_CNT_CLASSIF_TBL:
+ memset(&cnt_cb->tbl_cb, 0, sizeof(cnt_cb->tbl_cb));
+ break;
+ case DPA_STATS_CNT_CLASSIF_NODE:
+ memset(&cnt_cb->ccnode_cb, 0, sizeof(cnt_cb->ccnode_cb));
+ break;
+ case DPA_STATS_CNT_IPSEC:
+ memset(&cnt_cb->ipsec_cb, 0, sizeof(cnt_cb->ipsec_cb));
+ break;
+ default:
+ break;
+ }
+
+ /* Release DPA Stats instance lock */
+ mutex_unlock(&dpa_stats->lock);
+
+ return 0;
+}
+
+static int put_req(struct dpa_stats *dpa_stats, struct dpa_stats_req_cb *req_cb)
+{
+ int err = 0;
+
+ /* Acquire DPA Stats instance lock */
+ mutex_lock(&dpa_stats->lock);
+
+ /* Release the Counter id in the Counter IDs circular queue */
+ err = cq_put_4bytes(dpa_stats->req_id_cq, req_cb->id);
+ if (err < 0) {
+ log_err("Cannot release the request id %d\n", req_cb->id);
+ mutex_unlock(&dpa_stats->lock);
+ return -EDOM;
+ }
+
+ /* Mark the Counter id as 'not used' */
+ dpa_stats->used_req_ids[req_cb->index] = DPA_OFFLD_INVALID_OBJECT_ID;
+
+ /* Clear all 'req_cb' information by setting them to a maximum value */
+ req_cb->index = DPA_OFFLD_INVALID_OBJECT_ID;
+ req_cb->id = DPA_STATS_MAX_NUM_OF_REQUESTS;
+ req_cb->bytes_num = 0;
+ req_cb->cnts_num = 0;
+ req_cb->request_area = NULL;
+ req_cb->request_done = NULL;
+
+ /* Release DPA Stats instance lock */
+ mutex_unlock(&dpa_stats->lock);
+
+ return 0;
+}
+
+static int init_cnts_resources(struct dpa_stats *dpa_stats)
+{
+ struct dpa_stats_params config = dpa_stats->config;
+ int i;
+
+ /* Create circular queue that holds free counter IDs */
+ dpa_stats->cnt_id_cq = cq_new(config.max_counters, sizeof(int));
+ if (!dpa_stats->cnt_id_cq) {
+ log_err("Cannot create circular queue to store counter ids\n");
+ return -ENOMEM;
+ }
+
+ /* Fill the circular queue with ids */
+ for (i = 0; i < config.max_counters; i++)
+ if (cq_put_4bytes(dpa_stats->cnt_id_cq, i) < 0) {
+ log_err("Cannot fill circular queue with counter ids\n");
+ return -EDOM;
+ }
+
+ /* Allocate array to store counter ids that are 'in use' */
+ dpa_stats->used_cnt_ids = kcalloc(
+ config.max_counters, sizeof(uint32_t), GFP_KERNEL);
+ if (!dpa_stats->used_cnt_ids) {
+ log_err("Cannot allocate memory to store %d \'in use\' counter ids\n",
+ config.max_counters);
+ return -ENOMEM;
+ }
+ memset(dpa_stats->used_cnt_ids, DPA_OFFLD_INVALID_OBJECT_ID,
+ config.max_counters * sizeof(uint32_t));
+
+ /* Allocate array to store counter ids scheduled for retrieve */
+ dpa_stats->sched_cnt_ids = kcalloc(
+ config.max_counters, sizeof(bool), GFP_KERNEL);
+ if (!dpa_stats->sched_cnt_ids) {
+ log_err("Cannot allocate memory to store %d scheduled counter ids\n",
+ config.max_counters);
+ return -ENOMEM;
+ }
+
+ /* Allocate array of counters control blocks */
+ dpa_stats->cnts_cb = kzalloc(config.max_counters *
+ sizeof(struct dpa_stats_cnt_cb), GFP_KERNEL);
+ if (!dpa_stats->cnts_cb) {
+ log_err("Cannot allocate memory to store %d internal counter structures\n",
+ config.max_counters);
+ return -ENOMEM;
+ }
+
+ /* Initialize every counter control block */
+ for (i = 0; i < config.max_counters; i++) {
+ /* Initialize counter lock */
+ mutex_init(&dpa_stats->cnts_cb[i].lock);
+ /* Store dpa_stats instance */
+ dpa_stats->cnts_cb[i].dpa_stats = dpa_stats;
+ /* Counter is not initialized, set the index to invalid value */
+ dpa_stats->cnts_cb[i].index = DPA_OFFLD_INVALID_OBJECT_ID;
+ }
+ return 0;
+}
+
+static int free_cnts_resources(struct dpa_stats *dpa_stats)
+{
+ uint32_t id, i;
+ int err = 0;
+
+ for (i = 0; i < dpa_stats->config.max_counters; i++) {
+ mutex_lock(&dpa_stats->lock);
+ id = dpa_stats->used_cnt_ids[i];
+ mutex_unlock(&dpa_stats->lock);
+
+ if (id != DPA_OFFLD_INVALID_OBJECT_ID) {
+ /* Release the counter id in the Counter IDs cq */
+ err = dpa_stats_remove_counter(id);
+ BUG_ON(err < 0);
+ }
+ }
+
+ /* Release counters IDs circular queue */
+ if (dpa_stats->cnt_id_cq) {
+ cq_delete(dpa_stats->cnt_id_cq);
+ dpa_stats->cnt_id_cq = NULL;
+ }
+
+ /* Release counters control blocks */
+ kfree(dpa_stats->cnts_cb);
+ dpa_stats->cnts_cb = NULL;
+
+ /* Release counters 'used ids' array */
+ kfree(dpa_stats->used_cnt_ids);
+ dpa_stats->used_cnt_ids = NULL;
+
+ /* Release scheduled counters ids array */
+ kfree(dpa_stats->sched_cnt_ids);
+ dpa_stats->sched_cnt_ids = NULL;
+
+ return 0;
+}
+
+static int init_reqs_resources(struct dpa_stats *dpa_stats)
+{
+ int i;
+
+ /*
+ * Create work queue to defer work when asynchronous
+ * counters requests are received
+ */
+ dpa_stats->async_req_workqueue = alloc_workqueue("async_req_workqueue",
+ WQ_UNBOUND | WQ_MEM_RECLAIM, WORKQUEUE_MAX_ACTIVE);
+ if (!dpa_stats->async_req_workqueue) {
+ log_err("Cannot allocate asynchronous requests work queue\n");
+ return -ENOSPC;
+ }
+
+ /* Create circular queue that holds free counter request IDs */
+ dpa_stats->req_id_cq = cq_new(
+ DPA_STATS_MAX_NUM_OF_REQUESTS, sizeof(int));
+ if (!dpa_stats->req_id_cq) {
+ log_err("Cannot create circular queue to store request ids\n");
+ return -ENOMEM;
+ }
+
+ /* Fill the circular queue with ids */
+ for (i = 0; i < DPA_STATS_MAX_NUM_OF_REQUESTS; i++)
+ if (cq_put_4bytes(dpa_stats->req_id_cq, i) < 0) {
+ log_err("Cannot fill circular queue with request ids\n");
+ return -EDOM;
+ }
+
+ /* Allocate array to store requests ids that are 'in use' */
+ dpa_stats->used_req_ids = kmalloc(DPA_STATS_MAX_NUM_OF_REQUESTS *
+ sizeof(uint32_t), GFP_KERNEL);
+ if (!dpa_stats->used_req_ids) {
+ log_err("Cannot allocate memory to store \'in use\' request ids\n");
+ return -ENOMEM;
+ }
+ memset(dpa_stats->used_req_ids, DPA_OFFLD_INVALID_OBJECT_ID,
+ DPA_STATS_MAX_NUM_OF_REQUESTS * sizeof(uint32_t));
+
+ /* Allocate array to store requests control blocks */
+ dpa_stats->reqs_cb = kzalloc(DPA_STATS_MAX_NUM_OF_REQUESTS *
+ sizeof(struct dpa_stats_req_cb), GFP_KERNEL);
+ if (!dpa_stats->reqs_cb) {
+ log_err("Cannot allocate memory to store internal requests structure\n");
+ return -ENOMEM;
+ }
+
+ /* Allocate array to store the counter ids */
+ for (i = 0; i < DPA_STATS_MAX_NUM_OF_REQUESTS; i++) {
+ dpa_stats->reqs_cb[i].cnts_ids =
+ kzalloc(dpa_stats->config.max_counters *
+ sizeof(int), GFP_KERNEL);
+ if (!dpa_stats->reqs_cb[i].cnts_ids) {
+ log_err("Cannot allocate memory for array of counter ids\n");
+ return -ENOMEM;
+ }
+
+ /* Initialize work to be done for each request */
+ INIT_WORK(&dpa_stats->reqs_cb[i].async_req_work,
+ async_req_work_func);
+ }
+
+ return 0;
+}
+
+static int free_reqs_resources(struct dpa_stats *dpa_stats)
+{
+ struct dpa_stats_req_cb *req_cb = NULL;
+ uint32_t id, i;
+ int err = 0;
+
+ for (i = 0; i < DPA_STATS_MAX_NUM_OF_REQUESTS; i++) {
+ mutex_lock(&dpa_stats->lock);
+ id = dpa_stats->used_req_ids[i];
+ mutex_unlock(&dpa_stats->lock);
+
+ if (id != DPA_OFFLD_INVALID_OBJECT_ID) {
+ req_cb = &dpa_stats->reqs_cb[id];
+
+ flush_work(&req_cb->async_req_work);
+
+ /* Release the request id in the Requests IDs cq */
+ err = put_req(dpa_stats, req_cb);
+ BUG_ON(err < 0);
+
+ /* Release the array of counter ids */
+ kfree(req_cb->cnts_ids);
+ req_cb->cnts_ids = NULL;
+ }
+ }
+
+ /* Release requests IDs circular queue */
+ if (dpa_stats->req_id_cq) {
+ cq_delete(dpa_stats->req_id_cq);
+ dpa_stats->req_id_cq = NULL;
+ }
+
+ /* Release requests control blocks */
+ kfree(dpa_stats->reqs_cb);
+ dpa_stats->reqs_cb = NULL;
+
+ /* Release requests 'used ids' array */
+ kfree(dpa_stats->used_req_ids);
+ dpa_stats->used_req_ids = NULL;
+
+ /* destroy asynchronous requests workqueue */
+ if (dpa_stats->async_req_workqueue) {
+ destroy_workqueue(dpa_stats->async_req_workqueue);
+ dpa_stats->async_req_workqueue = NULL;
+ }
+
+ return 0;
+}
+
+/* cleanup DPA Stats */
+static int free_resources(void)
+{
+ struct dpa_stats *dpa_stats;
+ int err = 0;
+
+ /* Sanity check */
+ if (!gbl_dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return 0;
+ }
+ dpa_stats = gbl_dpa_stats;
+
+ /* free resources occupied by counters control blocks */
+ err = free_cnts_resources(dpa_stats);
+ if (err < 0)
+ return err;
+
+ /* free resources occupied by requests control blocks */
+ err = free_reqs_resources(dpa_stats);
+ if (err < 0)
+ return err;
+
+ kfree(dpa_stats);
+ gbl_dpa_stats = NULL;
+ return 0;
+}
+
+static int treat_cnts_request(struct dpa_stats *dpa_stats,
+ struct dpa_stats_req_cb *req_cb)
+{
+ struct dpa_stats_cnt_request_params params = req_cb->config;
+ struct dpa_stats_cnt_cb *cnt_cb = NULL;
+ int err = 0;
+ uint32_t i = 0;
+
+ for (i = 0; i < params.cnts_ids_len; i++) {
+
+ /* Get counter's control block */
+ cnt_cb = &dpa_stats->cnts_cb[req_cb->cnts_ids[i]];
+
+ /* Acquire counter lock */
+ mutex_lock(&cnt_cb->lock);
+
+ cnt_cb->info.reset = req_cb->config.reset_cnts;
+
+ /* Call counter's retrieve function */
+ err = cnt_cb->f_get_cnt_stats(req_cb, cnt_cb);
+ if (err < 0) {
+ log_err("Cannot retrieve the value for counter id %d\n",
+ req_cb->cnts_ids[i]);
+ mutex_unlock(&cnt_cb->lock);
+ unblock_sched_cnts(dpa_stats, req_cb->cnts_ids,
+ params.cnts_ids_len);
+ return err;
+ }
+
+ /*
+ * Update number of bytes and number of counters
+ * successfully written so far
+ */
+ req_cb->bytes_num += cnt_cb->bytes_num;
+ req_cb->cnts_num += 1;
+
+ mutex_unlock(&cnt_cb->lock);
+ }
+
+ unblock_sched_cnts(dpa_stats, req_cb->cnts_ids, params.cnts_ids_len);
+
+ return 0;
+}
+
+static void create_cnt_eth_stats(struct dpa_stats *dpa_stats)
+{
+ /* DPA_STATS_CNT_ETH_DROP_PKTS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH][0] =
+ offsetof(struct t_FmMacStatistics, eStatsDropEvents);
+ /* DPA_STATS_CNT_ETH_BYTES */
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH][1] =
+ offsetof(struct t_FmMacStatistics, ifInOctets);
+ /* DPA_STATS_CNT_ETH_PKTS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH][2] =
+ offsetof(struct t_FmMacStatistics, ifInPkts);
+ /* DPA_STATS_CNT_ETH_BC_PKTS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH][3] =
+ offsetof(struct t_FmMacStatistics, ifInBcastPkts);
+ /* DPA_STATS_CNT_ETH_MC_PKTS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH][4] =
+ offsetof(struct t_FmMacStatistics, ifInMcastPkts);
+ /* DPA_STATS_CNT_ETH_CRC_ALIGN_ERR */
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH][5] =
+ offsetof(struct t_FmMacStatistics, eStatCRCAlignErrors);
+ /* DPA_STATS_CNT_ETH_UNDERSIZE_PKTS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH][6] =
+ offsetof(struct t_FmMacStatistics, eStatUndersizePkts);
+ /* DPA_STATS_CNT_ETH_OVERSIZE_PKTS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH][7] =
+ offsetof(struct t_FmMacStatistics, eStatOversizePkts);
+ /* DPA_STATS_CNT_ETH_FRAGMENTS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH][8] =
+ offsetof(struct t_FmMacStatistics, eStatFragments);
+ /* DPA_STATS_CNT_ETH_JABBERS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH][9] =
+ offsetof(struct t_FmMacStatistics, eStatJabbers);
+ /* DPA_STATS_CNT_ETH_64BYTE_PKTS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH][10] =
+ offsetof(struct t_FmMacStatistics, eStatPkts64);
+ /* DPA_STATS_CNT_ETH_65_127BYTE_PKTS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH][11] =
+ offsetof(struct t_FmMacStatistics, eStatPkts65to127);
+ /* DPA_STATS_CNT_ETH_128_255BYTE_PKTS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH][12] =
+ offsetof(struct t_FmMacStatistics, eStatPkts128to255);
+ /* DPA_STATS_CNT_ETH_256_511BYTE_PKTS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH][13] =
+ offsetof(struct t_FmMacStatistics, eStatPkts256to511);
+ /* DPA_STATS_CNT_ETH_512_1023BYTE_PKTS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH][14] =
+ offsetof(struct t_FmMacStatistics, eStatPkts512to1023);
+ /* DPA_STATS_CNT_ETH_1024_1518BYTE_PKTS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH][15] =
+ offsetof(struct t_FmMacStatistics, eStatPkts1024to1518);
+ /* DPA_STATS_CNT_ETH_OUT_PKTS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH][16] =
+ offsetof(struct t_FmMacStatistics, ifOutPkts);
+ /* DPA_STATS_CNT_ETH_OUT_DROP_PKTS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH][17] =
+ offsetof(struct t_FmMacStatistics, ifOutDiscards);
+ /* DPA_STATS_CNT_ETH_OUT_BYTES */
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH][18] =
+ offsetof(struct t_FmMacStatistics, ifOutOctets);
+ /* DPA_STATS_CNT_ETH_IN_ERRORS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH][19] =
+ offsetof(struct t_FmMacStatistics, ifInErrors);
+ /* DPA_STATS_CNT_ETH_OUT_ERRORS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH][20] =
+ offsetof(struct t_FmMacStatistics, ifOutErrors);
+ /* DPA_STATS_CNT_ETH_IN_UNICAST_PKTS : not supported on dTSEC MAC */
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH][21] =
+ offsetof(struct t_FmMacStatistics, ifInUcastPkts);
+ /* DPA_STATS_CNT_ETH_OUT_UNICAST_PKTS : not supported on dTSEC MAC*/
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH][22] =
+ offsetof(struct t_FmMacStatistics, ifOutUcastPkts);
+}
+
+static void create_cnt_reass_stats(struct dpa_stats *dpa_stats)
+{
+ /* DPA_STATS_CNT_REASS_TIMEOUT */
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS][0] =
+ offsetof(struct t_FmPcdManipReassemIpStats, timeout);
+ /* DPA_STATS_CNT_REASS_RFD_POOL_BUSY */
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS][1] = offsetof(
+ struct t_FmPcdManipReassemIpStats, rfdPoolBusy);
+ /* DPA_STATS_CNT_REASS_INT_BUFF_BUSY */
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS][2] = offsetof(
+ struct t_FmPcdManipReassemIpStats, internalBufferBusy);
+ /* DPA_STATS_CNT_REASS_EXT_BUFF_BUSY */
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS][3] = offsetof(
+ struct t_FmPcdManipReassemIpStats, externalBufferBusy);
+ /* DPA_STATS_CNT_REASS_SG_FRAGS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS][4] = offsetof(
+ struct t_FmPcdManipReassemIpStats, sgFragments);
+ /* DPA_STATS_CNT_REASS_DMA_SEM */
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS][5] = offsetof(
+ struct t_FmPcdManipReassemIpStats,
+ dmaSemaphoreDepletion);
+#if (DPAA_VERSION >= 11)
+ /* DPA_STATS_CNT_REASS_NON_CONSISTENT_SP */
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS][6] = offsetof(
+ struct t_FmPcdManipReassemIpStats,
+ nonConsistentSp);
+#else
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS][6] = UNSUPPORTED_CNT_SEL;
+#endif /* (DPAA_VERSION >= 11) */
+ /* DPA_STATS_CNT_REASS_IPv4_FRAMES */
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS][8] = offsetof(
+ struct t_FmPcdManipReassemIpStats,
+ specificHdrStatistics[0].successfullyReassembled);
+ /* DPA_STATS_CNT_REASS_IPv4_FRAGS_VALID */
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS][9] = offsetof(
+ struct t_FmPcdManipReassemIpStats,
+ specificHdrStatistics[0].validFragments);
+ /* DPA_STATS_CNT_REASS_IPv4_FRAGS_TOTAL */
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS][10] = offsetof(
+ struct t_FmPcdManipReassemIpStats,
+ specificHdrStatistics[0].processedFragments);
+ /* DPA_STATS_CNT_REASS_IPv4_FRAGS_MALFORMED */
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS][11] = offsetof(
+ struct t_FmPcdManipReassemIpStats,
+ specificHdrStatistics[0].malformedFragments);
+ /* DPA_STATS_CNT_REASS_IPv4_FRAGS_DISCARDED */
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS][12] = offsetof(
+ struct t_FmPcdManipReassemIpStats,
+ specificHdrStatistics[0].discardedFragments);
+ /* DPA_STATS_CNT_REASS_IPv4_AUTOLEARN_BUSY */
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS][13] = offsetof(
+ struct t_FmPcdManipReassemIpStats,
+ specificHdrStatistics[0].autoLearnBusy);
+ /* DPA_STATS_CNT_REASS_IPv4_EXCEED_16FRAGS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS][14] = offsetof(
+ struct t_FmPcdManipReassemIpStats,
+ specificHdrStatistics[0].moreThan16Fragments);
+ /* DPA_STATS_CNT_REASS_IPv6_FRAMES */
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS][16] = offsetof(
+ struct t_FmPcdManipReassemIpStats,
+ specificHdrStatistics[1].successfullyReassembled);
+ /* DPA_STATS_CNT_REASS_IPv6_FRAGS_VALID */
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS][17] = offsetof(
+ struct t_FmPcdManipReassemIpStats,
+ specificHdrStatistics[1].validFragments);
+ /* DPA_STATS_CNT_REASS_IPv6_FRAGS_TOTAL */
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS][18] = offsetof(
+ struct t_FmPcdManipReassemIpStats,
+ specificHdrStatistics[1].processedFragments);
+ /* DPA_STATS_CNT_REASS_IPv6_FRAGS_MALFORMED */
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS][19] = offsetof(
+ struct t_FmPcdManipReassemIpStats,
+ specificHdrStatistics[1].malformedFragments);
+ /* DPA_STATS_CNT_REASS_IPv6_FRAGS_DISCARDED */
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS][20] = offsetof(
+ struct t_FmPcdManipReassemIpStats,
+ specificHdrStatistics[1].discardedFragments);
+ /* DPA_STATS_CNT_REASS_IPv6_AUTOLEARN_BUSY */
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS][21] = offsetof(
+ struct t_FmPcdManipReassemIpStats,
+ specificHdrStatistics[1].autoLearnBusy);
+ /* DPA_STATS_CNT_REASS_IPv6_EXCEED_16FRAGS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS][22] = offsetof(
+ struct t_FmPcdManipReassemIpStats,
+ specificHdrStatistics[1].moreThan16Fragments);
+}
+
+static void create_cnt_frag_stats(struct dpa_stats *dpa_stats)
+{
+ /* DPA_STATS_CNT_FRAG_TOTAL_FRAMES */
+ dpa_stats->stats_sel[DPA_STATS_CNT_FRAG][0] =
+ offsetof(struct t_FmPcdManipFragIpStats, totalFrames);
+ /* DPA_STATS_CNT_FRAG_FRAMES */
+ dpa_stats->stats_sel[DPA_STATS_CNT_FRAG][1] = offsetof(
+ struct t_FmPcdManipFragIpStats, fragmentedFrames);
+ /* DPA_STATS_CNT_FRAG_GEN_FRAGS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_FRAG][2] = offsetof(
+ struct t_FmPcdManipFragIpStats, generatedFragments);
+}
+
+static void create_cnt_plcr_stats(struct dpa_stats *dpa_stats)
+{
+ /* DPA_STATS_CNT_PLCR_GREEN_PKTS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_POLICER][0] =
+ e_FM_PCD_PLCR_PROFILE_GREEN_PACKET_TOTAL_COUNTER;
+ /* DPA_STATS_CNT_PLCR_YELLOW_PKTS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_POLICER][1] =
+ e_FM_PCD_PLCR_PROFILE_YELLOW_PACKET_TOTAL_COUNTER;
+ /* DPA_STATS_CNT_PLCR_RED_PKTS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_POLICER][2] =
+ e_FM_PCD_PLCR_PROFILE_RED_PACKET_TOTAL_COUNTER;
+ /* DPA_STATS_CNT_PLCR_RECOLOR_YELLOW_PKTS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_POLICER][3] =
+ e_FM_PCD_PLCR_PROFILE_RECOLOURED_YELLOW_PACKET_TOTAL_COUNTER;
+ /* DPA_STATS_CNT_PLCR_RECOLOR_RED_PKTS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_POLICER][4] =
+ e_FM_PCD_PLCR_PROFILE_RECOLOURED_RED_PACKET_TOTAL_COUNTER;
+}
+
+static void create_classif_stats(struct dpa_stats *dpa_stats)
+{
+ /* DPA_STATS_CNT_CLASSIF_BYTES */
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE][0] =
+ offsetof(struct t_FmPcdCcKeyStatistics, byteCount);
+ /* DPA_STATS_CNT_CLASSIF_PACKETS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE][1] =
+ offsetof(struct t_FmPcdCcKeyStatistics, frameCount);
+#if (DPAA_VERSION >= 11)
+ /* DPA_STATS_CNT_CLASSIF_RANGE1 */
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE][2] = offsetof(
+ struct t_FmPcdCcKeyStatistics,
+ frameLengthRangeCount[0]);
+ /* DPA_STATS_CNT_CLASSIF_RANGE2 */
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE][3] = offsetof(
+ struct t_FmPcdCcKeyStatistics,
+ frameLengthRangeCount[1]);
+ /* DPA_STATS_CNT_CLASSIF_RANGE3 */
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE][4] = offsetof(
+ struct t_FmPcdCcKeyStatistics,
+ frameLengthRangeCount[2]);
+ /* DPA_STATS_CNT_CLASSIF_RANGE4 */
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE][5] = offsetof(
+ struct t_FmPcdCcKeyStatistics,
+ frameLengthRangeCount[3]);
+ /* DPA_STATS_CNT_CLASSIF_RANGE5 */
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE][6] = offsetof(
+ struct t_FmPcdCcKeyStatistics,
+ frameLengthRangeCount[4]);
+ /* DPA_STATS_CNT_CLASSIF_RANGE6 */
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE][7] = offsetof(
+ struct t_FmPcdCcKeyStatistics,
+ frameLengthRangeCount[5]);
+ /* DPA_STATS_CNT_CLASSIF_RANGE7 */
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE][8] = offsetof(
+ struct t_FmPcdCcKeyStatistics,
+ frameLengthRangeCount[6]);
+ /* DPA_STATS_CNT_CLASSIF_RANGE8 */
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE][9] = offsetof(
+ struct t_FmPcdCcKeyStatistics,
+ frameLengthRangeCount[7]);
+ /* DPA_STATS_CNT_CLASSIF_RANGE9 */
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE][10] = offsetof(
+ struct t_FmPcdCcKeyStatistics,
+ frameLengthRangeCount[8]);
+ /* DPA_STATS_CNT_CLASSIF_RANGE10 */
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE][11] = offsetof(
+ struct t_FmPcdCcKeyStatistics,
+ frameLengthRangeCount[9]);
+#else
+ /* DPA_STATS_CNT_CLASSIF_RANGE1 */
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE][2] =
+ UNSUPPORTED_CNT_SEL;
+ /* DPA_STATS_CNT_CLASSIF_RANGE2 */
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE][3] =
+ UNSUPPORTED_CNT_SEL;
+ /* DPA_STATS_CNT_CLASSIF_RANGE3 */
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE][4] =
+ UNSUPPORTED_CNT_SEL;
+ /* DPA_STATS_CNT_CLASSIF_RANGE4 */
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE][5] =
+ UNSUPPORTED_CNT_SEL;
+ /* DPA_STATS_CNT_CLASSIF_RANGE5 */
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE][6] =
+ UNSUPPORTED_CNT_SEL;
+ /* DPA_STATS_CNT_CLASSIF_RANGE6 */
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE][7] =
+ UNSUPPORTED_CNT_SEL;
+ /* DPA_STATS_CNT_CLASSIF_RANGE7 */
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE][8] =
+ UNSUPPORTED_CNT_SEL;
+ /* DPA_STATS_CNT_CLASSIF_RANGE8 */
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE][9] =
+ UNSUPPORTED_CNT_SEL;
+ /* DPA_STATS_CNT_CLASSIF_RANGE9 */
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE][10] =
+ UNSUPPORTED_CNT_SEL;
+ /* DPA_STATS_CNT_CLASSIF_RANGE10 */
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE][11] =
+ UNSUPPORTED_CNT_SEL;
+#endif
+}
+
+static void create_cnt_ipsec_stats(struct dpa_stats *dpa_stats)
+{
+ /* DPA_STATS_CNT_NUM_OF_BYTES */
+ dpa_stats->stats_sel[DPA_STATS_CNT_IPSEC][0] = offsetof(
+ struct dpa_ipsec_sa_stats, bytes_count);
+ /* DPA_STATS_CNT_NUM_OF_PACKETS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_IPSEC][1] = offsetof(
+ struct dpa_ipsec_sa_stats, packets_count);
+}
+
+static void create_cnt_traffic_mng_stats(struct dpa_stats *dpa_stats)
+{
+ /* DPA_STATS_CNT_NUM_OF_BYTES */
+ dpa_stats->stats_sel[DPA_STATS_CNT_TRAFFIC_MNG][0] =
+ DPA_STATS_CNT_NUM_OF_BYTES * sizeof(uint64_t);
+ /* DPA_STATS_CNT_NUM_OF_PACKETS */
+ dpa_stats->stats_sel[DPA_STATS_CNT_TRAFFIC_MNG][1] =
+ DPA_STATS_CNT_NUM_OF_PACKETS * sizeof(uint64_t);
+}
+
+static int copy_key_descriptor(const struct dpa_offload_lookup_key *src,
+ struct dpa_stats_allocated_lookup_key *dst)
+{
+ /* Check that key byte pointer is valid */
+ if (!src->byte) {
+ log_err("Lookup key descriptor byte cannot be NULL\n");
+ return -EINVAL;
+ }
+
+ /* Check that key size is not zero */
+ if (src->size == 0) {
+ log_err("Lookup key descriptor size (%d) must be in range (1 - %d) bytes\n",
+ src->size, DPA_OFFLD_MAXENTRYKEYSIZE);
+ return -EINVAL;
+ }
+
+ BUG_ON(dst->data.byte == NULL);
+ memcpy(dst->data.byte, src->byte, src->size);
+ dst->valid_key = true;
+
+ /* If there is a valid key mask pointer */
+ if (src->mask) {
+ BUG_ON(dst->data.mask == NULL);
+ memcpy(dst->data.mask, src->mask, src->size);
+ dst->valid_mask = true;
+ } else
+ dst->valid_mask = false;
+
+ /* Store the key size */
+ dst->data.size = src->size;
+
+ return 0;
+}
+
+static t_Handle get_fman_mac_handle(struct device_node *parent_dev_node,
+ int port_id,
+ char *mac_name,
+ bool xg_port)
+{
+ struct device_node *dev_node, *tmp_node = NULL;
+ struct mac_device *mac_dev = NULL;
+ const uint32_t *cell_index;
+ const char *phy_connection;
+ struct platform_device *device;
+ int lenp;
+
+ while ((dev_node = of_find_compatible_node(tmp_node, NULL,
+ mac_name)) != NULL) {
+
+ if (parent_dev_node != of_get_parent(dev_node)) {
+ tmp_node = dev_node;
+ continue;
+ }
+
+ cell_index = of_get_property(dev_node, "cell-index", &lenp);
+ if (*cell_index != port_id) {
+ tmp_node = dev_node;
+ continue;
+ }
+
+ phy_connection = of_get_property(dev_node,
+ "phy-connection-type",
+ &lenp);
+ if (((xg_port) && (strcmp(phy_connection, "xgmii") == 0)) ||
+ ((!xg_port) &&
+ (strcmp(phy_connection, "xgmii") != 0))) {
+
+ device = of_find_device_by_node(dev_node);
+ if (!device)
+ return NULL;
+ mac_dev = dev_get_drvdata(&device->dev);
+ if (!mac_dev)
+ return NULL;
+
+ return mac_dev->get_mac_handle(mac_dev);
+ }
+
+ tmp_node = dev_node;
+ }
+
+ return NULL;
+}
+
+static struct device_node *get_fman_dev_node(int fman_id)
+{
+ struct device_node *dev_node, *tmp_node = NULL;
+ const uint32_t *cell_index;
+ int lenp;
+
+ while ((dev_node = of_find_compatible_node(tmp_node, NULL, "fsl,fman"))
+ != NULL) {
+ cell_index = of_get_property(dev_node, "cell-index", &lenp);
+ if (*cell_index == fman_id)
+ break;
+
+ tmp_node = dev_node;
+ }
+
+ return dev_node;
+}
+
+static int get_fm_mac(struct dpa_stats_cnt_eth_src src, void **mac)
+{
+ struct device_node *dev_node = NULL;
+ t_Handle *fm_mac = NULL;
+ char *mac_name;
+
+ /* Get FMAN device node */
+ dev_node = get_fman_dev_node(src.engine_id);
+ if (!dev_node) {
+ log_err("Cannot find FMan device node\n");
+ return -EINVAL;
+ }
+
+ if (src.eth_id > DPA_STATS_ETH_1G_PORT5) {
+ /* Get Ethernet device node first for DTSEC case 10G port*/
+ mac_name = "fsl,fman-10g-mac";
+ src.eth_id -= DPA_STATS_ETH_10G_PORT0;
+
+ fm_mac = get_fman_mac_handle(dev_node,
+ src.eth_id,
+ mac_name,
+ true);
+ if (!fm_mac) {
+ /* Get Ethernet device node for MEMAC case 10G port */
+ mac_name = "fsl,fman-memac";
+ fm_mac = get_fman_mac_handle(
+ dev_node, src.eth_id, mac_name, true);
+ if (!fm_mac) {
+ log_err("Cannot find Ethernet device node\n");
+ return -EINVAL;
+ }
+ }
+ } else {
+ /* Get Ethernet device node first for DTSEC case 1G port*/
+ mac_name = "fsl,fman-1g-mac";
+
+ fm_mac = get_fman_mac_handle(dev_node,
+ src.eth_id,
+ mac_name,
+ false);
+ if (!fm_mac) {
+ /* Get Ethernet device node for MEMAC case 1G port*/
+ mac_name = "fsl,fman-memac";
+ fm_mac = get_fman_mac_handle(
+ dev_node, src.eth_id, mac_name, false);
+ if (!fm_mac) {
+ log_err("Cannot find Ethernet device node\n");
+ return -EINVAL;
+ }
+ }
+ }
+
+ /* Return FM MAC handle */
+ *mac = fm_mac;
+
+ return 0;
+}
+
+static int cnt_sel_to_stats(struct stats_info *stats_info,
+ int *stats_sel,
+ uint32_t cnt_sel)
+{
+ uint32_t bit_val = 0, bit_pos = 0, cnt_pos = 1;
+ int stats_off[MAX_NUM_OF_STATS];
+
+ memset(stats_off, 0, sizeof(int) * MAX_NUM_OF_STATS);
+
+ while (cnt_sel > 0) {
+ bit_val = cnt_sel & 0x00000001;
+ stats_off[cnt_pos - bit_val] = stats_sel[bit_pos++];
+ cnt_pos += bit_val;
+ cnt_sel >>= 1;
+ }
+
+ stats_info->stats_num = cnt_pos - 1;
+
+ /*
+ * Allocate the stats offsets array and copy the calculated offsets
+ * into it
+ */
+ stats_info->stats_off = kcalloc(stats_info->stats_num, sizeof(int),
+ GFP_KERNEL);
+ if (!stats_info->stats_off) {
+ log_err("Failed to allocate stats offsets for new counter\n");
+ return -ENOMEM;
+ }
+
+ memcpy(stats_info->stats_off, stats_off,
+ stats_info->stats_num * sizeof(int));
+ return 0;
+}
+
+static int cnt_gen_sel_to_stats(struct dpa_stats_cnt_cb *cnt_cb,
+ enum dpa_stats_cnt_sel cnt_sel)
+{
+ struct dpa_stats *dpa_stats = cnt_cb->dpa_stats;
+ int stats_off[MAX_NUM_OF_STATS];
+
+ if (cnt_sel == DPA_STATS_CNT_NUM_OF_BYTES) {
+ stats_off[0] =
+ dpa_stats->stats_sel[cnt_cb->type][DPA_STATS_CNT_NUM_OF_BYTES];
+ cnt_cb->info.stats_num = 1;
+ } else if (cnt_sel == DPA_STATS_CNT_NUM_OF_PACKETS) {
+ stats_off[0] =
+ dpa_stats->stats_sel[cnt_cb->type][DPA_STATS_CNT_NUM_OF_PACKETS];
+ cnt_cb->info.stats_num = 1;
+ } else if (cnt_sel == DPA_STATS_CNT_NUM_ALL) {
+ stats_off[0] =
+ dpa_stats->stats_sel[cnt_cb->type][DPA_STATS_CNT_NUM_OF_BYTES];
+ stats_off[1] =
+ dpa_stats->stats_sel[cnt_cb->type][DPA_STATS_CNT_NUM_OF_PACKETS];
+ cnt_cb->info.stats_num = 2;
+ } else {
+ log_err("Parameter cnt_sel %d must be in range (%d - %d) for counter id %d\n",
+ cnt_sel, DPA_STATS_CNT_NUM_OF_BYTES,
+ DPA_STATS_CNT_NUM_ALL, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ /*
+ * Allocate the stats offsets array and copy the calculated offsets
+ * into it
+ */
+ cnt_cb->info.stats_off = kcalloc(cnt_cb->info.stats_num,
+ sizeof(int), GFP_KERNEL);
+ if (!cnt_cb->info.stats_off) {
+ log_err("Failed to allocate stats offsets for new counter\n");
+ return -ENOMEM;
+ }
+
+ memcpy(cnt_cb->info.stats_off, stats_off,
+ cnt_cb->info.stats_num * sizeof(int));
+
+ /* Set number of bytes that will be written by this counter */
+ cnt_cb->bytes_num = cnt_cb->members_num *
+ STATS_VAL_SIZE * cnt_cb->info.stats_num;
+
+ return 0;
+}
+
+static int set_frag_manip(int td, struct dpa_stats_lookup_key *entry)
+{
+ struct dpa_cls_tbl_action action;
+ struct t_FmPcdManipStats stats;
+ struct dpa_offload_lookup_key local_key;
+ int err = 0;
+
+ if (entry->miss_key) {
+ err = dpa_classif_get_miss_action(td, &action);
+ if (err != 0) {
+ log_err("Cannot retrieve miss action parameters from table %d\n",
+ td);
+ return -EINVAL;
+ }
+ } else {
+ local_key.byte = entry->key.data.byte;
+ local_key.size = entry->key.data.size;
+ if (entry->key.valid_mask)
+ local_key.mask = entry->key.data.mask;
+ else
+ local_key.mask = NULL;
+
+ err = dpa_classif_table_lookup_by_key(td, &local_key, &action);
+ if (err != 0) {
+ log_err("Cannot retrieve next action parameters from table %d\n",
+ td);
+ return -EINVAL;
+ }
+ }
+
+ if (action.type != DPA_CLS_TBL_ACTION_ENQ) {
+ log_err("Fragmentation statistics per flow are supported only for action enqueue\n");
+ return -EINVAL;
+ }
+
+ entry->frag = dpa_classif_get_frag_hm_handle(action.enq_params.hmd);
+ if (!entry->frag) {
+ log_err("Cannot retrieve Fragmentation handle from hmd %d\n",
+ action.enq_params.hmd);
+ return -EINVAL;
+ }
+
+ /* Check the user-provided fragmentation handle */
+ err = FM_PCD_ManipGetStatistics(entry->frag, &stats);
+ if (err < 0) {
+ log_err("Invalid Fragmentation manip handle\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int alloc_cnt_stats(struct stats_info *stats_info,
+ unsigned int num_members)
+{
+ /* Allocate array of currently read statistics */
+ stats_info->stats = kcalloc(num_members * stats_info->stats_num,
+ sizeof(uint64_t), GFP_KERNEL);
+ if (!stats_info->stats) {
+ log_err("Cannot allocate memory to store array of statistics\n");
+ return -ENOMEM;
+ }
+
+ /* Allocate array of previously read statistics */
+ stats_info->last_stats = kcalloc(num_members * stats_info->stats_num,
+ sizeof(uint64_t), GFP_KERNEL);
+ if (!stats_info->last_stats) {
+ log_err("Cannot allocate memory to store array of previous read statistics for all members\n");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int set_cnt_eth_cb(struct dpa_stats_cnt_cb *cnt_cb,
+ const struct dpa_stats_cnt_params *params)
+{
+ struct dpa_stats *dpa_stats = cnt_cb->dpa_stats;
+ uint32_t cnt_sel = params->eth_params.cnt_sel;
+ t_FmMacStatistics stats;
+ t_Handle fm_mac = NULL;
+ int err = 0;
+
+ if (!dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return -EFAULT;
+ }
+
+ /* Check Ethernet counter selection */
+ if (cnt_sel == 0 || cnt_sel > DPA_STATS_CNT_ETH_ALL) {
+ log_err("Parameter cnt_sel %d must be in range (1 - %d) for counter id %d\n",
+ cnt_sel, DPA_STATS_CNT_ETH_ALL, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ /* Decrease one to obtain the mask for all statistics */
+ if (cnt_sel == DPA_STATS_CNT_ETH_ALL)
+ cnt_sel -= 1;
+
+ if (params->eth_params.src.eth_id < DPA_STATS_ETH_1G_PORT0 ||
+ params->eth_params.src.eth_id > DPA_STATS_ETH_10G_PORT1) {
+ log_err("Parameter src.eth_id %d must be in range (%d - %d) for counter id %d\n",
+ params->eth_params.src.eth_id, DPA_STATS_ETH_1G_PORT0,
+ DPA_STATS_ETH_10G_PORT1, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ cnt_cb->members_num = 1;
+
+ /* Map Ethernet counter selection to FM MAC statistics */
+ err = cnt_sel_to_stats(&cnt_cb->info,
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH], cnt_sel);
+ if (err)
+ return err;
+
+ /* Set number of bytes that will be written by this counter */
+ cnt_cb->bytes_num = STATS_VAL_SIZE * cnt_cb->info.stats_num;
+
+ /* Get FM MAC handle */
+ err = get_fm_mac(params->eth_params.src, &fm_mac);
+ if (err != 0) {
+ log_err("Cannot retrieve Ethernet MAC handle for counter id %d\n",
+ cnt_cb->id);
+ return -EINVAL;
+ }
+ cnt_cb->gen_cb.objs = kzalloc(sizeof(t_Handle), GFP_KERNEL);
+ if (!cnt_cb->gen_cb.objs) {
+ log_err("No more memory for new Ethernet counter\n");
+ return -ENOMEM;
+ }
+ cnt_cb->gen_cb.objs[0] = fm_mac;
+
+ err = FM_MAC_GetStatistics(cnt_cb->gen_cb.objs[0], &stats);
+ if (err != 0) {
+ log_err("Invalid Ethernet counter source for counter id %d\n",
+ cnt_cb->id);
+ return -ENOENT;
+ }
+
+ err = alloc_cnt_stats(&cnt_cb->info, cnt_cb->members_num);
+ if (err)
+ return err;
+
+ init_cnt_64bit_stats(&cnt_cb->info, &stats, 0);
+
+ return 0;
+}
+
+static int set_cnt_reass_cb(struct dpa_stats_cnt_cb *cnt_cb,
+ const struct dpa_stats_cnt_params *params)
+{
+ struct dpa_stats *dpa_stats = cnt_cb->dpa_stats;
+ uint32_t cnt_sel = params->reass_params.cnt_sel;
+ struct t_FmPcdManipStats stats;
+ int err;
+
+ if (!dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return -EFAULT;
+ }
+
+ /* User can combine counters only from a group */
+ if (!((cnt_sel != 0 && cnt_sel <= DPA_STATS_CNT_REASS_GEN_ALL) ||
+ (cnt_sel >= DPA_STATS_CNT_REASS_IPv4_FRAMES &&
+ cnt_sel <= DPA_STATS_CNT_REASS_IPv4_ALL) ||
+ (cnt_sel >= DPA_STATS_CNT_REASS_IPv6_FRAMES &&
+ cnt_sel <= DPA_STATS_CNT_REASS_IPv6_ALL))) {
+ log_err("Parameter cnt_sel %d must be in one of the ranges (1 -%d), (%d - %d), (%d - %d) for counter id %d\n",
+ cnt_sel, DPA_STATS_CNT_REASS_GEN_ALL,
+ DPA_STATS_CNT_REASS_IPv4_FRAMES,
+ DPA_STATS_CNT_REASS_IPv4_ALL,
+ DPA_STATS_CNT_REASS_IPv6_FRAMES,
+ DPA_STATS_CNT_REASS_IPv6_ALL, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ if (!params->reass_params.reass) {
+ log_err("Parameter Reassembly handle cannot be NULL for counter id %d\n",
+ cnt_cb->id);
+ return -EFAULT;
+ }
+
+ cnt_cb->gen_cb.objs = kzalloc(sizeof(t_Handle), GFP_KERNEL);
+ if (!cnt_cb->gen_cb.objs) {
+ log_err("No more memory for new IP reass counter\n");
+ return -ENOMEM;
+ }
+ cnt_cb->gen_cb.objs[0] = params->reass_params.reass;
+ cnt_cb->members_num = 1;
+
+ /* Based on user option, change mask to all statistics in one group */
+ if (cnt_sel == DPA_STATS_CNT_REASS_GEN_ALL)
+ cnt_sel -= 1;
+ else if (cnt_sel == DPA_STATS_CNT_REASS_IPv4_ALL)
+ cnt_sel = (cnt_sel - 1) &
+ ~(DPA_STATS_CNT_REASS_IPv4_FRAMES - 1);
+ else if (cnt_sel == DPA_STATS_CNT_REASS_IPv6_ALL)
+ cnt_sel = (cnt_sel - 1) &
+ ~(DPA_STATS_CNT_REASS_IPv6_FRAMES - 1);
+
+ /* Map Reassembly counter selection to Manip statistics */
+ err = cnt_sel_to_stats(&cnt_cb->info,
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS], cnt_sel);
+ if (err)
+ return err;
+
+ /* Set number of bytes that will be written by this counter */
+ cnt_cb->bytes_num = STATS_VAL_SIZE * cnt_cb->info.stats_num;
+
+ /* Check the user-provided reassembly manip */
+ err = FM_PCD_ManipGetStatistics(params->reass_params.reass, &stats);
+ if (err < 0) {
+ log_err("Invalid Reassembly manip handle for counter id %d\n",
+ cnt_cb->id);
+ return -EINVAL;
+ }
+
+ err = alloc_cnt_stats(&cnt_cb->info, cnt_cb->members_num);
+ if (err)
+ return err;
+
+ init_cnt_32bit_stats(&cnt_cb->info, &stats, 0);
+
+ return 0;
+}
+
+static int set_cnt_frag_cb(struct dpa_stats_cnt_cb *cnt_cb,
+ const struct dpa_stats_cnt_params *params)
+{
+ struct dpa_stats *dpa_stats = cnt_cb->dpa_stats;
+ uint32_t cnt_sel = params->frag_params.cnt_sel;
+ struct t_FmPcdManipStats stats;
+ int err;
+
+ if (!dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return -EFAULT;
+ }
+
+ /* Check Fragmentation counter selection */
+ if (cnt_sel == 0 || cnt_sel > DPA_STATS_CNT_FRAG_ALL) {
+ log_err("Parameter cnt_sel %d must be in range (1 - %d) for counter id %d\n",
+ cnt_sel, DPA_STATS_CNT_FRAG_ALL, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ if (!params->frag_params.frag) {
+ log_err("Parameter Fragmentation handle cannot be NULL for counter id %d\n",
+ cnt_cb->id);
+ return -EFAULT;
+ }
+
+ cnt_cb->gen_cb.objs = kzalloc(sizeof(t_Handle), GFP_KERNEL);
+ if (!cnt_cb->gen_cb.objs) {
+ log_err("No more memory for new IP frag counter\n");
+ return -ENOMEM;
+ }
+ cnt_cb->gen_cb.objs[0] = params->frag_params.frag;
+ cnt_cb->members_num = 1;
+
+ /* Decrease one to obtain the mask for all statistics */
+ if (cnt_sel == DPA_STATS_CNT_FRAG_ALL)
+ cnt_sel -= 1;
+
+ /* Map Fragmentation counter selection to Manip statistics */
+ err = cnt_sel_to_stats(&cnt_cb->info,
+ dpa_stats->stats_sel[DPA_STATS_CNT_FRAG], cnt_sel);
+ if (err)
+ return err;
+
+ /* Set number of bytes that will be written by this counter */
+ cnt_cb->bytes_num = STATS_VAL_SIZE * cnt_cb->info.stats_num;
+
+ /* Check the user-provided fragmentation handle */
+ err = FM_PCD_ManipGetStatistics(params->frag_params.frag, &stats);
+ if (err < 0) {
+ log_err("Invalid Fragmentation manip handle for counter id %d\n",
+ cnt_cb->id);
+ return -EINVAL;
+ }
+
+ err = alloc_cnt_stats(&cnt_cb->info, cnt_cb->members_num);
+ if (err)
+ return err;
+
+ init_cnt_32bit_stats(&cnt_cb->info, &stats, 0);
+
+ return 0;
+}
+
+static int set_cnt_plcr_cb(struct dpa_stats_cnt_cb *cnt_cb,
+ const struct dpa_stats_cnt_params *params)
+{
+ struct dpa_stats *dpa_stats = cnt_cb->dpa_stats;
+ uint32_t cnt_sel = params->plcr_params.cnt_sel;
+ uint64_t stats_val;
+ uint32_t i;
+ int err;
+
+ if (!dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return -EFAULT;
+ }
+
+ /* Check Policer counter selection */
+ if (cnt_sel == 0 || cnt_sel > DPA_STATS_CNT_PLCR_ALL) {
+ log_err("Parameter cnt_sel %d must be in range (1 - %d) for counter id %d\n",
+ cnt_sel, DPA_STATS_CNT_PLCR_ALL, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ if (!params->plcr_params.plcr) {
+ log_err("Parameter Policer handle cannot be NULL for counter id %d\n",
+ cnt_cb->id);
+ return -EFAULT;
+ }
+
+ cnt_cb->gen_cb.objs = kzalloc(sizeof(t_Handle), GFP_KERNEL);
+ if (!cnt_cb->gen_cb.objs) {
+ log_err("No more memory for new policer counter\n");
+ return -ENOMEM;
+ }
+ cnt_cb->gen_cb.objs[0] = params->plcr_params.plcr;
+ cnt_cb->members_num = 1;
+
+ /* Decrease one to obtain the mask for all statistics */
+ if (cnt_sel == DPA_STATS_CNT_PLCR_ALL)
+ cnt_sel -= 1;
+
+ /* Map Policer counter selection to policer statistics */
+ err = cnt_sel_to_stats(&cnt_cb->info,
+ dpa_stats->stats_sel[DPA_STATS_CNT_POLICER], cnt_sel);
+ if (err)
+ return err;
+
+ /* Set number of bytes that will be written by this counter */
+ cnt_cb->bytes_num = STATS_VAL_SIZE * cnt_cb->info.stats_num;
+
+ err = alloc_cnt_stats(&cnt_cb->info, cnt_cb->members_num);
+ if (err)
+ return err;
+
+ for (i = 0; i < cnt_cb->info.stats_num; i++) {
+ stats_val = (uint64_t)FM_PCD_PlcrProfileGetCounter(
+ cnt_cb->gen_cb.objs[0], cnt_cb->info.stats_off[i]);
+
+ /* Store the current value as the last read value */
+ cnt_cb->info.stats[i] = 0;
+ cnt_cb->info.last_stats[i] = stats_val;
+ }
+ return 0;
+}
+
+static int set_cnt_classif_tbl_cb(struct dpa_stats_cnt_cb *cnt_cb,
+ const struct dpa_stats_cnt_params *params)
+{
+ struct dpa_stats_cnt_classif_tbl_cb *cnt_tbl_cb = &cnt_cb->tbl_cb;
+ struct dpa_stats *dpa_stats = cnt_cb->dpa_stats;
+ struct dpa_stats_cnt_classif_tbl prm = params->classif_tbl_params;
+ struct dpa_cls_tbl_params cls_tbl;
+ uint32_t cnt_sel = prm.cnt_sel;
+ int err = 0, frag_stats = -1;
+
+ if (!dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return -EFAULT;
+ }
+
+ /* Check Classifier Table counter selection */
+ if (cnt_sel >= DPA_STATS_CNT_CLASSIF_BYTES &&
+ cnt_sel <= DPA_STATS_CNT_CLASSIF_ALL) {
+
+ /* Entire group of counters was selected */
+ if (cnt_sel == DPA_STATS_CNT_CLASSIF_ALL)
+ cnt_sel -= 1;
+
+ /* Map Classifier Table counter selection to CcNode stats */
+ err = cnt_sel_to_stats(&cnt_cb->info,
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE],
+ cnt_sel >> CLASSIF_STATS_SHIFT);
+ if (err)
+ return err;
+
+ frag_stats = 0;
+
+ } else if (cnt_sel >= DPA_STATS_CNT_FRAG_TOTAL_FRAMES &&
+ cnt_sel <= DPA_STATS_CNT_FRAG_ALL) {
+
+ /* Entire group of counters was selected */
+ if (cnt_sel == DPA_STATS_CNT_FRAG_ALL)
+ cnt_sel -= 1;
+
+ /* Map Classifier Table counter selection to Frag stats */
+ err = cnt_sel_to_stats(&cnt_cb->info,
+ dpa_stats->stats_sel[DPA_STATS_CNT_FRAG], cnt_sel);
+ if (err)
+ return err;
+
+ frag_stats = 1;
+
+ } else {
+ log_err("Parameter cnt_sel %d must be in one of the ranges (%d - %d), (%d - %d), for counter id %d\n",
+ cnt_sel, DPA_STATS_CNT_CLASSIF_BYTES,
+ DPA_STATS_CNT_CLASSIF_ALL,
+ DPA_STATS_CNT_FRAG_TOTAL_FRAMES, DPA_STATS_CNT_FRAG_ALL,
+ cnt_cb->id);
+ return -EINVAL;
+ }
+
+ if (prm.td == DPA_OFFLD_DESC_NONE) {
+ log_err("Invalid table descriptor %d for counter id %d\n",
+ prm.td, cnt_cb->id);
+ return -EINVAL;
+ }
+ err = dpa_classif_table_get_params(prm.td, &cls_tbl);
+ if (err != 0) {
+ log_err("Invalid table descriptor %d for counter id %d\n",
+ prm.td, cnt_cb->id);
+ return -EINVAL;
+ }
+ /* Allocate memory for one key descriptor */
+ cnt_tbl_cb->keys = kzalloc(sizeof(*cnt_tbl_cb->keys), GFP_KERNEL);
+ if (!cnt_tbl_cb->keys) {
+ log_err("Cannot allocate memory for key descriptor for counter id %d\n",
+ cnt_cb->id);
+ return -ENOMEM;
+ }
+
+ /* Store CcNode handle and set number of keys to one */
+ cnt_tbl_cb->keys[0].cc_node = cls_tbl.cc_node;
+ cnt_tbl_cb->keys[0].valid = TRUE;
+ cnt_cb->members_num = 1;
+
+ /* Set number of bytes that will be written by this counter */
+ cnt_cb->bytes_num = STATS_VAL_SIZE * cnt_cb->info.stats_num;
+
+ err = alloc_cnt_stats(&cnt_cb->info, cnt_cb->members_num);
+ if (err)
+ return err;
+
+ /* Store DPA Classifier Table type */
+ cnt_tbl_cb->type = cls_tbl.type;
+
+ /* Set retrieve function depending on table type */
+ err = set_cnt_classif_tbl_retrieve_func(cnt_cb);
+ if (err != 0)
+ return -EINVAL;
+
+ /* Allocate the single key: */
+ cnt_tbl_cb->keys[0].key.data.byte = kzalloc(
+ DPA_OFFLD_MAXENTRYKEYSIZE, GFP_KERNEL);
+ if (!cnt_tbl_cb->keys[0].key.data.byte)
+ log_err("Cannot allocate memory for the key of for counter id %d\n",
+ cnt_cb->id);
+ cnt_tbl_cb->keys[0].key.data.mask = kzalloc(
+ DPA_OFFLD_MAXENTRYKEYSIZE, GFP_KERNEL);
+ if (!cnt_tbl_cb->keys[0].key.data.mask)
+ log_err("Cannot allocate memory for the mask of counter id %d\n",
+ cnt_cb->id);
+
+ if (!prm.key) {
+ cnt_tbl_cb->keys[0].miss_key = TRUE;
+ } else {
+ /* Copy the key descriptor */
+ err = copy_key_descriptor(prm.key, &cnt_tbl_cb->keys[0].key);
+ if (err != 0) {
+ log_err("Cannot copy key descriptor from user parameters\n");
+ return -EINVAL;
+ }
+ }
+
+ if (!frag_stats) {
+ if (cnt_tbl_cb->keys[0].miss_key) {
+ /*
+ * Retrieve Classifier Table counter statistics for
+ * 'miss'
+ */
+ err = get_classif_tbl_miss_stats(cnt_cb, 0);
+ if (err != 0)
+ return -EINVAL;
+ } else {
+ /*
+ * Retrieve Classifier Table counter statistics for a
+ * key
+ */
+ err = get_classif_tbl_key_stats(cnt_cb, 0);
+ if (err != 0)
+ return err;
+ }
+ } else {
+ err = set_frag_manip(prm.td, &cnt_tbl_cb->keys[0]);
+ if (err < 0) {
+ log_err("Invalid Fragmentation manip handle for counter id %d\n",
+ cnt_cb->id);
+ return -EINVAL;
+ }
+ /* Change the retrieve routine */
+ cnt_cb->f_get_cnt_stats = get_cnt_cls_tbl_frag_stats;
+ }
+ return 0;
+}
+
+static int set_cnt_ccnode_cb(struct dpa_stats_cnt_cb *cnt_cb,
+ const struct dpa_stats_cnt_params *params)
+{
+ struct dpa_stats *dpa_stats = cnt_cb->dpa_stats;
+ struct dpa_stats_cnt_classif_node prm = params->classif_node_params;
+ int err = 0;
+
+ if (!dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return -EFAULT;
+ }
+
+ /* Check Classification Node counter selection */
+ if (prm.cnt_sel == 0 || prm.cnt_sel > DPA_STATS_CNT_CLASSIF_ALL) {
+ log_err("Parameter cnt_sel %d must be in range (1 - %d) for counter id %d\n",
+ prm.cnt_sel, DPA_STATS_CNT_CLASSIF_ALL, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ if (!params->classif_node_params.cc_node) {
+ log_err("Parameter classification CC Node handle cannot be NULL for counter id %d\n",
+ cnt_cb->id);
+ return -EFAULT;
+ }
+
+ /* Store CcNode handle and set number of keys to one */
+ cnt_cb->ccnode_cb.cc_node = prm.cc_node;
+ cnt_cb->members_num = 1;
+
+ /* Map Classif Node counter selection to CcNode statistics */
+ err = cnt_sel_to_stats(&cnt_cb->info,
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE],
+ prm.cnt_sel >> CLASSIF_STATS_SHIFT);
+ if (err)
+ return err;
+
+ /* Set number of bytes that will be written by this counter */
+ cnt_cb->bytes_num = STATS_VAL_SIZE * cnt_cb->info.stats_num;
+
+ err = alloc_cnt_stats(&cnt_cb->info, cnt_cb->members_num);
+ if (err)
+ return err;
+
+ /* Allocate memory for one key descriptor */
+ cnt_cb->ccnode_cb.keys = kzalloc(sizeof(*cnt_cb->ccnode_cb.keys),
+ GFP_KERNEL);
+ if (!cnt_cb->ccnode_cb.keys) {
+ log_err("Cannot allocate memory for key descriptor for counter id %d\n",
+ cnt_cb->id);
+ return -ENOMEM;
+ }
+
+ /* Set retrieve function depending on counter type */
+ err = set_cnt_classif_node_retrieve_func(cnt_cb, prm.ccnode_type);
+ if (err != 0)
+ return -EINVAL;
+
+ /* Allocate memory for every key */
+ cnt_cb->ccnode_cb.keys[0].data.byte = kzalloc(
+ DPA_OFFLD_MAXENTRYKEYSIZE, GFP_KERNEL);
+ if (!cnt_cb->ccnode_cb.keys[0].data.byte)
+ log_err("Cannot allocate memory for the key of the counter id %d\n",
+ cnt_cb->id);
+ cnt_cb->ccnode_cb.keys[0].data.mask = kzalloc(
+ DPA_OFFLD_MAXENTRYKEYSIZE, GFP_KERNEL);
+ if (!cnt_cb->ccnode_cb.keys[0].data.mask)
+ log_err("Cannot allocate memory for the mask of the counter id %d\n",
+ cnt_cb->id);
+
+ if (!params->classif_node_params.key) {
+ /* Set the key byte to NULL, to mark it for 'miss' entry */
+ cnt_cb->ccnode_cb.keys[0].valid_key = false;
+
+ /* Retrieve Classifier Node counter statistics for 'miss' */
+ err = get_ccnode_miss_stats(cnt_cb, prm.ccnode_type, 0);
+ } else {
+ /* Copy the key descriptor */
+ err = copy_key_descriptor(prm.key, &cnt_cb->ccnode_cb.keys[0]);
+ if (err != 0) {
+ log_err("Cannot copy key descriptor from user parameters\n");
+ return -EINVAL;
+ }
+ /* Retrieve Classifier Node counter statistics for key */
+ err = get_ccnode_key_stats(cnt_cb, prm.ccnode_type, 0);
+ }
+ return err;
+}
+
+static int set_cnt_ipsec_cb(struct dpa_stats_cnt_cb *cnt_cb,
+ const struct dpa_stats_cnt_params *params)
+{
+ struct dpa_ipsec_sa_stats stats;
+ int err = 0;
+
+ if (!cnt_cb->dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return -EFAULT;
+ }
+
+ /* Allocate memory for one security association id */
+ cnt_cb->ipsec_cb.sa_id = kzalloc(sizeof(*cnt_cb->ipsec_cb.sa_id),
+ GFP_KERNEL);
+ if (!cnt_cb->ipsec_cb.sa_id) {
+ log_err("Cannot allocate memory for security association id for counter id %d\n",
+ cnt_cb->id);
+ return -ENOMEM;
+ }
+
+ /* Allocate memory to store if security association is valid */
+ cnt_cb->ipsec_cb.valid = kzalloc(sizeof(*cnt_cb->ipsec_cb.valid),
+ GFP_KERNEL);
+ if (!cnt_cb->ipsec_cb.valid) {
+ log_err("Cannot allocate memory to store if security association is valid for counter id %d\n",
+ cnt_cb->id);
+ return -ENOMEM;
+ }
+
+ cnt_cb->ipsec_cb.sa_id[0] = params->ipsec_params.sa_id;
+ cnt_cb->ipsec_cb.valid[0] = TRUE;
+ cnt_cb->members_num = 1;
+
+ /* Map IPSec counter selection to statistics */
+ err = cnt_gen_sel_to_stats(cnt_cb, params->ipsec_params.cnt_sel);
+ if (err < 0)
+ return err;
+
+ err = dpa_ipsec_sa_get_stats(cnt_cb->ipsec_cb.sa_id[0], &stats);
+ if (err < 0) {
+ log_err("Check failed for IPSec counter id %d due to incorrect parameters: sa_id=%d\n",
+ cnt_cb->id, cnt_cb->ipsec_cb.sa_id[0]);
+ return -EINVAL;
+ }
+
+ err = alloc_cnt_stats(&cnt_cb->info, cnt_cb->members_num);
+ if (err)
+ return err;
+
+ init_cnt_32bit_stats(&cnt_cb->info, &stats, 0);
+
+ return 0;
+}
+
+static int set_cnt_traffic_mng_cb(struct dpa_stats_cnt_cb *cnt_cb,
+ const struct dpa_stats_cnt_params *params)
+{
+ uint32_t cnt_sel = params->traffic_mng_params.cnt_sel;
+ uint32_t cnt_src = params->traffic_mng_params.src;
+ uint64_t stats[2];
+ int err = 0;
+ bool us_cnt = FALSE;
+
+ if (!cnt_cb->dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return -EFAULT;
+ }
+
+ /* Check if this is an users-space counter and if so, reset the flag */
+ if (cnt_sel & DPA_STATS_US_CNT) {
+ us_cnt = TRUE;
+ cnt_sel &= ~DPA_STATS_US_CNT;
+ }
+
+ if (!params->traffic_mng_params.traffic_mng && !us_cnt) {
+ log_err("Parameter traffic_mng handle cannot be NULL for counter id %d\n",
+ cnt_cb->id);
+ return -EINVAL;
+ }
+
+ /* Check and store the counter source */
+ if (cnt_src > DPA_STATS_CNT_TRAFFIC_CG) {
+ log_err("Parameter src %d must be in range (%d - %d) for counter id %d\n",
+ cnt_src, DPA_STATS_CNT_TRAFFIC_CLASS,
+ DPA_STATS_CNT_TRAFFIC_CG, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ cnt_cb->gen_cb.objs = kzalloc(sizeof(t_Handle), GFP_KERNEL);
+ if (!cnt_cb->gen_cb.objs) {
+ log_err("No more memory for new policer counter\n");
+ return -ENOMEM;
+ }
+ cnt_cb->gen_cb.objs[0] = params->traffic_mng_params.traffic_mng;
+ cnt_cb->members_num = 1;
+
+ /* Map Traffic Manager counter selection to statistics */
+ err = cnt_gen_sel_to_stats(cnt_cb, cnt_sel);
+ if (err < 0)
+ return err;
+
+ /* For user-space counters there is a different retrieve function */
+ if (us_cnt) {
+ cnt_cb->f_get_cnt_stats = get_cnt_us_stats;
+ return 0;
+ }
+
+ /* Check the counter source and the Traffic Manager object */
+ switch (cnt_src) {
+ case DPA_STATS_CNT_TRAFFIC_CLASS:
+ cnt_cb->f_get_cnt_stats = get_cnt_traffic_mng_cq_stats;
+ err = qman_ceetm_cq_get_dequeue_statistics(
+ params->traffic_mng_params.traffic_mng,
+ 0, &stats[0], &stats[1]);
+ if (err < 0) {
+ log_err("Invalid Traffic Manager qm_ceetm_cq object for counter id %d\n",
+ cnt_cb->id);
+ return -EINVAL;
+ }
+ break;
+ case DPA_STATS_CNT_TRAFFIC_CG:
+ cnt_cb->f_get_cnt_stats = get_cnt_traffic_mng_ccg_stats;
+ err = qman_ceetm_ccg_get_reject_statistics(
+ params->traffic_mng_params.traffic_mng,
+ 0, &stats[0], &stats[1]);
+ if (err < 0) {
+ log_err("Invalid Traffic Manager qm_ceetm_ccg object for counter id %d\n",
+ cnt_cb->id);
+ return -EINVAL;
+ }
+ break;
+ }
+
+ err = alloc_cnt_stats(&cnt_cb->info, cnt_cb->members_num);
+ if (err)
+ return err;
+
+ init_cnt_64bit_stats(&cnt_cb->info, &stats, 0);
+
+ return 0;
+}
+
+static int set_cls_cnt_eth_cb(struct dpa_stats_cnt_cb *cnt_cb,
+ const struct dpa_stats_cls_cnt_params *params)
+{
+ struct dpa_stats *dpa_stats = cnt_cb->dpa_stats;
+ uint32_t cnt_sel = params->eth_params.cnt_sel;
+ t_FmMacStatistics stats;
+ t_Handle fm_mac = NULL;
+ uint32_t i = 0;
+ int err = 0;
+
+ if (!dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return -EFAULT;
+ }
+
+ /* Check Ethernet counter selection */
+ if (params->eth_params.cnt_sel == 0 ||
+ params->eth_params.cnt_sel > DPA_STATS_CNT_ETH_ALL) {
+ log_err("Parameter cnt_sel %d must be in range (1 - %d) for counter id %d\n",
+ cnt_sel, DPA_STATS_CNT_ETH_ALL, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ /* Decrease one to obtain the mask for all statistics */
+ if (cnt_sel == DPA_STATS_CNT_ETH_ALL)
+ cnt_sel -= 1;
+
+ cnt_cb->members_num = params->class_members;
+
+ /* Map Ethernet counter selection to FM MAC statistics */
+ err = cnt_sel_to_stats(&cnt_cb->info,
+ dpa_stats->stats_sel[DPA_STATS_CNT_ETH], cnt_sel);
+ if (err)
+ return err;
+
+ /* Set number of bytes that will be written by this counter */
+ cnt_cb->bytes_num = cnt_cb->members_num *
+ STATS_VAL_SIZE * cnt_cb->info.stats_num;
+
+ cnt_cb->gen_cb.objs = kcalloc(cnt_cb->members_num, sizeof(t_Handle),
+ GFP_KERNEL);
+ if (!cnt_cb->gen_cb.objs) {
+ log_err("No more memory for new Ethernet class counter\n");
+ return -ENOMEM;
+ }
+
+ err = alloc_cnt_stats(&cnt_cb->info, cnt_cb->members_num);
+ if (err)
+ return err;
+
+ for (i = 0; i < params->class_members; i++) {
+ /* Get FM MAC handle */
+ err = get_fm_mac(params->eth_params.src[i], &fm_mac);
+ if (err != 0) {
+ log_err("Cannot obtain Ethernet MAC handle for counter id %d\n",
+ cnt_cb->id);
+ return -EINVAL;
+ }
+
+ cnt_cb->gen_cb.objs[i] = fm_mac;
+
+ err = FM_MAC_GetStatistics(cnt_cb->gen_cb.objs[i], &stats);
+ if (err != 0) {
+ log_err("Invalid Ethernet counter source for counter id %d\n",
+ cnt_cb->id);
+ return -ENOENT;
+ }
+ init_cnt_64bit_stats(&cnt_cb->info, &stats, i);
+ }
+ return 0;
+}
+
+static int set_cls_cnt_reass_cb(struct dpa_stats_cnt_cb *cnt_cb,
+ const struct dpa_stats_cls_cnt_params *params)
+{
+ struct dpa_stats *dpa_stats = cnt_cb->dpa_stats;
+ struct t_FmPcdManipStats stats;
+ uint32_t cnt_sel = params->reass_params.cnt_sel;
+ uint32_t i = 0;
+ int err = 0;
+
+ if (!dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return -EFAULT;
+ }
+
+ /* User can combine counters only from a group */
+ if (!((cnt_sel != 0 && cnt_sel <= DPA_STATS_CNT_REASS_GEN_ALL) ||
+ (cnt_sel >= DPA_STATS_CNT_REASS_IPv4_FRAMES &&
+ cnt_sel <= DPA_STATS_CNT_REASS_IPv4_ALL) ||
+ (cnt_sel >= DPA_STATS_CNT_REASS_IPv6_FRAMES &&
+ cnt_sel <= DPA_STATS_CNT_REASS_IPv6_ALL))) {
+ log_err("Parameter cnt_sel %d must be in one of the ranges (1 - %d), (%d - %d), (%d - %d) for counter id %d\n",
+ cnt_sel, DPA_STATS_CNT_REASS_GEN_ALL,
+ DPA_STATS_CNT_REASS_IPv4_FRAMES,
+ DPA_STATS_CNT_REASS_IPv4_ALL,
+ DPA_STATS_CNT_REASS_IPv6_FRAMES,
+ DPA_STATS_CNT_REASS_IPv6_ALL, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ cnt_cb->members_num = params->class_members;
+
+ /* Based on user option, change mask to all statistics in one group */
+ if (cnt_sel == DPA_STATS_CNT_REASS_GEN_ALL)
+ cnt_sel -= 1;
+ else if (cnt_sel == DPA_STATS_CNT_REASS_IPv4_ALL)
+ cnt_sel = (cnt_sel - 1) &
+ ~(DPA_STATS_CNT_REASS_IPv4_FRAMES - 1);
+ else if (cnt_sel == DPA_STATS_CNT_REASS_IPv6_ALL)
+ cnt_sel = (cnt_sel - 1) &
+ ~(DPA_STATS_CNT_REASS_IPv6_FRAMES - 1);
+
+ /* Map Reassembly counter selection to Manip statistics */
+ err = cnt_sel_to_stats(&cnt_cb->info,
+ dpa_stats->stats_sel[DPA_STATS_CNT_REASS], cnt_sel);
+ if (err)
+ return err;
+
+ /* Set number of bytes that will be written by this counter */
+ cnt_cb->bytes_num = cnt_cb->members_num *
+ STATS_VAL_SIZE * cnt_cb->info.stats_num;
+
+ cnt_cb->gen_cb.objs = kcalloc(cnt_cb->members_num, sizeof(t_Handle),
+ GFP_KERNEL);
+ if (!cnt_cb->gen_cb.objs) {
+ log_err("No more memory for new IP reass class counter\n");
+ return -ENOMEM;
+ }
+
+ err = alloc_cnt_stats(&cnt_cb->info, cnt_cb->members_num);
+ if (err)
+ return err;
+
+ for (i = 0; i < params->class_members; i++) {
+ if (!params->reass_params.reass[i]) {
+ log_err("Parameter Reassembly handle cannot be NULL for member %d, counter id %d\n",
+ i, cnt_cb->id);
+ return -EFAULT;
+ }
+ cnt_cb->gen_cb.objs[i] = params->reass_params.reass[i];
+
+ /* Check the user-provided reassembly manip */
+ err = FM_PCD_ManipGetStatistics(cnt_cb->gen_cb.objs[i], &stats);
+ if (err < 0) {
+ log_err("Invalid Reassembly manip handle for counter id %d\n",
+ cnt_cb->id);
+ return -EINVAL;
+ }
+ init_cnt_32bit_stats(&cnt_cb->info, &stats, i);
+ }
+
+ return 0;
+}
+
+static int set_cls_cnt_frag_cb(struct dpa_stats_cnt_cb *cnt_cb,
+ const struct dpa_stats_cls_cnt_params *params)
+{
+ struct dpa_stats *dpa_stats = cnt_cb->dpa_stats;
+ uint32_t cnt_sel = params->frag_params.cnt_sel, i;
+ struct t_FmPcdManipStats stats;
+ int err;
+
+ if (!dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return -EFAULT;
+ }
+
+ /* Check Fragmentation counter selection */
+ if ((cnt_sel == 0) || (cnt_sel > DPA_STATS_CNT_FRAG_ALL)) {
+ log_err("Parameter cnt_sel %d must be in range (1 - %d) for counter id %d\n",
+ cnt_sel, DPA_STATS_CNT_FRAG_ALL, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ cnt_cb->members_num = params->class_members;
+
+ /* Decrease one to obtain the mask for all statistics */
+ if (cnt_sel == DPA_STATS_CNT_FRAG_ALL)
+ cnt_sel -= 1;
+
+ /* Map Fragmentation counter selection to Manip statistics */
+ err = cnt_sel_to_stats(&cnt_cb->info,
+ dpa_stats->stats_sel[DPA_STATS_CNT_FRAG], cnt_sel);
+ if (err)
+ return err;
+
+ /* Set number of bytes that will be written by this counter */
+ cnt_cb->bytes_num = cnt_cb->members_num *
+ STATS_VAL_SIZE * cnt_cb->info.stats_num;
+
+ cnt_cb->gen_cb.objs = kcalloc(cnt_cb->members_num, sizeof(t_Handle),
+ GFP_KERNEL);
+ if (!cnt_cb->gen_cb.objs) {
+ log_err("No more memory for new IP frag class counter\n");
+ return -ENOMEM;
+ }
+
+ err = alloc_cnt_stats(&cnt_cb->info, cnt_cb->members_num);
+ if (err)
+ return err;
+
+ for (i = 0; i < params->class_members; i++) {
+ if (!params->frag_params.frag[i]) {
+ log_err("Parameter Fragmentation handle cannot be NULL for member %d, counter id %d\n",
+ i, cnt_cb->id);
+ return -EFAULT;
+ }
+ cnt_cb->gen_cb.objs[i] = params->frag_params.frag[i];
+
+ /* Check the user-provided fragmentation handle */
+ err = FM_PCD_ManipGetStatistics(cnt_cb->gen_cb.objs[i], &stats);
+ if (err < 0) {
+ log_err("Invalid Fragmentation manip handle for counter id %d\n",
+ cnt_cb->id);
+ return -EINVAL;
+ }
+ init_cnt_32bit_stats(&cnt_cb->info, &stats, i);
+ }
+
+ return 0;
+}
+
+static int set_cls_cnt_plcr_cb(struct dpa_stats_cnt_cb *cnt_cb,
+ const struct dpa_stats_cls_cnt_params *params)
+{
+ struct dpa_stats *dpa_stats = cnt_cb->dpa_stats;
+ uint32_t cnt_sel = params->plcr_params.cnt_sel;
+ uint32_t i, j, stats, stats_idx, stats_base_idx;
+ int err;
+
+ if (!dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return -EFAULT;
+ }
+
+ /* Check Policer counter selection */
+ if (cnt_sel == 0 || cnt_sel > DPA_STATS_CNT_PLCR_ALL) {
+ log_err("Parameter cnt_sel %d must be in range (1 - %d) for counter id %d\n",
+ cnt_sel, DPA_STATS_CNT_PLCR_ALL, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ /* Decrease one to obtain the mask for all statistics */
+ if (cnt_sel == DPA_STATS_CNT_PLCR_ALL)
+ cnt_sel -= 1;
+
+ cnt_cb->members_num = params->class_members;
+
+ /* Map Policer counter selection to policer statistics */
+ err = cnt_sel_to_stats(&cnt_cb->info,
+ dpa_stats->stats_sel[DPA_STATS_CNT_POLICER], cnt_sel);
+ if (err)
+ return err;
+
+ /* Set number of bytes that will be written by this counter */
+ cnt_cb->bytes_num = cnt_cb->members_num *
+ STATS_VAL_SIZE * cnt_cb->info.stats_num;
+
+ cnt_cb->gen_cb.objs = kcalloc(cnt_cb->members_num, sizeof(t_Handle),
+ GFP_KERNEL);
+ if (!cnt_cb->gen_cb.objs) {
+ log_err("No more memory for new policer class counter\n");
+ return -ENOMEM;
+ }
+
+ err = alloc_cnt_stats(&cnt_cb->info, cnt_cb->members_num);
+ if (err)
+ return err;
+
+ for (i = 0; i < params->class_members; i++) {
+ if (!params->plcr_params.plcr[i]) {
+ log_err("Parameter Policer handle cannot be NULL for member %d, counter id %d\n",
+ i, cnt_cb->id);
+ return -EFAULT;
+ }
+ cnt_cb->gen_cb.objs[i] = params->plcr_params.plcr[i];
+
+ stats_base_idx = cnt_cb->info.stats_num * i;
+ for (j = 0; j < cnt_cb->info.stats_num; j++) {
+ stats = (uint64_t)FM_PCD_PlcrProfileGetCounter(
+ cnt_cb->gen_cb.objs[i],
+ cnt_cb->info.stats_off[j]);
+
+ /* Store the current value as the last read value */
+ stats_idx = stats_base_idx + j;
+ cnt_cb->info.stats[stats_idx] = 0;
+ cnt_cb->info.last_stats[stats_idx] = stats;
+ }
+ }
+
+ return 0;
+}
+
+static int set_cls_cnt_classif_tbl_pair(
+ struct dpa_stats_cnt_cb *cnt_cb, int td,
+ const struct dpa_offload_lookup_key_pair *pair,
+ uint32_t idx)
+{
+ struct dpa_stats_cnt_classif_tbl_cb *cnt_tbl_cb = &cnt_cb->tbl_cb;
+ struct dpa_stats_lookup_key *lookup_key = &cnt_tbl_cb->keys[idx];
+ struct dpa_cls_tbl_params cls_tbl;
+ struct dpa_cls_tbl_action action;
+ int err = 0;
+
+ /* If either the entire 'pair' or the first key is NULL, then retrieve
+ * the action associated with the 'miss action '*/
+ if ((!pair) || (pair && !pair->first_key)) {
+ err = dpa_classif_get_miss_action(td, &action);
+ if (err != 0) {
+ log_err("Cannot retrieve miss action parameters for table descriptor %d\n",
+ td);
+ return -EINVAL;
+ }
+ } else {
+ /* Check that key byte is not NULL */
+ if (!pair->first_key->byte) {
+ log_err("First key descriptor byte of the user pair cannot be NULL for table descriptor %d\n",
+ td);
+ return -EFAULT;
+ }
+
+ /* Use the first key of the pair to lookup in the classifier
+ * table the next table connected on a "next-action" */
+ err = dpa_classif_table_lookup_by_key(td, pair->first_key,
+ &action);
+ if (err != 0) {
+ log_err("Cannot retrieve next action parameters for table descriptor %d\n",
+ td);
+ return -EINVAL;
+ }
+ }
+
+ if (action.type != DPA_CLS_TBL_ACTION_NEXT_TABLE) {
+ log_err("Pair key is supported only if two tables are connected");
+ return -EINVAL;
+ }
+
+ /* Get CcNode from new table descriptor */
+ err = dpa_classif_table_get_params(
+ action.next_table_params.next_td, &cls_tbl);
+ if (err != 0) {
+ log_err("Cannot retrieve next table %d parameters\n", td);
+ return -EINVAL;
+ }
+
+ /* Store DPA Classifier Table type */
+ cnt_tbl_cb->type = cls_tbl.type;
+
+ /* Set retrieve function depending on table type */
+ set_cnt_classif_tbl_retrieve_func(cnt_cb);
+
+ /* Store CcNode handle */
+ lookup_key->cc_node = cls_tbl.cc_node;
+
+ if (!pair || (pair && !pair->second_key)) {
+ /* Set as the key as "for miss" */
+ lookup_key->miss_key = TRUE;
+ } else {
+ lookup_key->miss_key = FALSE;
+
+ /* Set as lookup key the second key descriptor from the pair */
+ err = copy_key_descriptor(pair->second_key,
+ &lookup_key->key);
+ if (err != 0) {
+ log_err("Cannot copy second key descriptor of the user pair\n");
+ return -EINVAL;
+ }
+ }
+
+ return err;
+}
+
+static int set_cls_cnt_classif_tbl_cb(struct dpa_stats_cnt_cb *cnt_cb,
+ const struct dpa_stats_cls_cnt_params *params)
+{
+ struct dpa_stats_cnt_classif_tbl_cb *tbl_cb = &cnt_cb->tbl_cb;
+ struct dpa_stats_cls_cnt_classif_tbl prm = params->classif_tbl_params;
+ struct dpa_stats *dpa_stats = cnt_cb->dpa_stats;
+ struct dpa_cls_tbl_params cls_tbl;
+ uint32_t i = 0, cnt_sel = prm.cnt_sel;
+ int err = 0, frag_stats = -1;
+
+ /* Check Classifier Table descriptor */
+ if (params->classif_tbl_params.td == DPA_OFFLD_INVALID_OBJECT_ID) {
+ log_err("Invalid table descriptor %d for counter id %d\n",
+ params->classif_tbl_params.td, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ /* Check Classifier Table counter selection */
+ if (cnt_sel >= DPA_STATS_CNT_CLASSIF_BYTES &&
+ cnt_sel <= DPA_STATS_CNT_CLASSIF_ALL) {
+
+ /* Entire group of counters was selected */
+ if (cnt_sel == DPA_STATS_CNT_CLASSIF_ALL)
+ cnt_sel -= 1;
+
+ /* Map Classif Node counter selection to CcNode statistics */
+ err = cnt_sel_to_stats(&cnt_cb->info,
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE],
+ cnt_sel >> CLASSIF_STATS_SHIFT);
+ if (err)
+ return err;
+
+ frag_stats = 0;
+
+ } else if (cnt_sel >= DPA_STATS_CNT_FRAG_TOTAL_FRAMES &&
+ cnt_sel <= DPA_STATS_CNT_FRAG_ALL) {
+
+ /* Entire group of counters was selected */
+ if (cnt_sel == DPA_STATS_CNT_FRAG_ALL)
+ cnt_sel -= 1;
+
+ /* Map Classif Node counter selection to fragmentation stats */
+ err = cnt_sel_to_stats(&cnt_cb->info,
+ dpa_stats->stats_sel[DPA_STATS_CNT_FRAG], cnt_sel);
+ if (err)
+ return err;
+
+ frag_stats = 1;
+
+ } else {
+ log_err("Parameter cnt_sel %d must be in one of the ranges (%d - %d), (%d - %d), for counter id %d\n",
+ cnt_sel, DPA_STATS_CNT_CLASSIF_BYTES,
+ DPA_STATS_CNT_CLASSIF_ALL,
+ DPA_STATS_CNT_FRAG_TOTAL_FRAMES, DPA_STATS_CNT_FRAG_ALL,
+ cnt_cb->id);
+ return -EINVAL;
+ }
+
+ tbl_cb->td = params->classif_tbl_params.td;
+ cnt_cb->members_num = params->class_members;
+
+ /* Set number of bytes that will be written by this counter */
+ cnt_cb->bytes_num = cnt_cb->members_num *
+ STATS_VAL_SIZE * cnt_cb->info.stats_num;
+
+ /* Allocate memory for key descriptors */
+ tbl_cb->keys = kcalloc(params->class_members, sizeof(*tbl_cb->keys),
+ GFP_KERNEL);
+ if (!tbl_cb->keys) {
+ log_err("Cannot allocate memory for array of key descriptors for counter id %d\n",
+ cnt_cb->id);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < cnt_cb->members_num; i++) {
+ /* Allocate memory for every key */
+ tbl_cb->keys[i].key.data.byte = kzalloc(
+ DPA_OFFLD_MAXENTRYKEYSIZE, GFP_KERNEL);
+ if (!tbl_cb->keys[i].key.data.byte)
+ log_err("Cannot allocate memory for key %d of counter id %d\n",
+ i, cnt_cb->id);
+ tbl_cb->keys[i].key.data.mask = kzalloc(
+ DPA_OFFLD_MAXENTRYKEYSIZE, GFP_KERNEL);
+ if (!tbl_cb->keys[i].key.data.mask)
+ log_err("Cannot allocate memory for mask %d of counter id %d\n",
+ i, cnt_cb->id);
+ }
+
+ switch (prm.key_type) {
+ case DPA_STATS_CLASSIF_SINGLE_KEY:
+ if (!prm.keys) {
+ log_err("Pointer to the array of keys cannot be NULL for counter id %d\n",
+ cnt_cb->id);
+ return -EINVAL;
+ }
+
+ /* Get CcNode from table descriptor */
+ err = dpa_classif_table_get_params(prm.td, &cls_tbl);
+ if (err != 0) {
+ log_err("Invalid table descriptor %d for counter id %d\n",
+ prm.td, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ /* Store DPA Classifier Table type */
+ tbl_cb->type = cls_tbl.type;
+
+ /* Set retrieve function depending on table type */
+ set_cnt_classif_tbl_retrieve_func(cnt_cb);
+
+ for (i = 0; i < params->class_members; i++) {
+ /* Store CcNode handle */
+ tbl_cb->keys[i].cc_node = cls_tbl.cc_node;
+
+ /* Determine if key represents a 'miss' entry */
+ if (!prm.keys[i]) {
+ tbl_cb->keys[i].miss_key = TRUE;
+ tbl_cb->keys[i].valid = TRUE;
+ continue;
+ }
+ /* Key is not valid for now */
+ if (!prm.keys[i]->byte) {
+ tbl_cb->keys[i].valid = FALSE;
+ continue;
+ }
+ /* Copy the key descriptor */
+ err = copy_key_descriptor(prm.keys[i],
+ &tbl_cb->keys[i].key);
+ if (err != 0) {
+ log_err("Cannot copy key descriptor from user parameters\n");
+ return -EINVAL;
+ }
+ tbl_cb->keys[i].valid = TRUE;
+ }
+ break;
+ case DPA_STATS_CLASSIF_PAIR_KEY:
+ if (!prm.pairs) {
+ log_err("Pointer to the array of pairs cannot be NULL for counter id %d\n",
+ cnt_cb->id);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < params->class_members; i++) {
+ if (prm.pairs[i]) {
+ if (prm.pairs[i]->first_key) {
+ if (!prm.pairs[i]->first_key->byte) {
+ /* Key is not valid for now */
+ tbl_cb->keys[i].valid = FALSE;
+ continue;
+ }
+ }
+ }
+
+ err = set_cls_cnt_classif_tbl_pair(cnt_cb, prm.td,
+ prm.pairs[i], i);
+ if (err != 0) {
+ log_err("Cannot set classifier table pair key for counter id %d\n",
+ cnt_cb->id);
+ return -EINVAL;
+ }
+ tbl_cb->keys[i].valid = TRUE;
+ }
+ break;
+ default:
+ log_err("Parameter key_type %d must be in range (%d - %d) for counter id %d\n",
+ prm.key_type, DPA_STATS_CLASSIF_SINGLE_KEY,
+ DPA_STATS_CLASSIF_PAIR_KEY, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ err = alloc_cnt_stats(&cnt_cb->info, cnt_cb->members_num);
+ if (err)
+ return err;
+
+ if (!frag_stats) {
+ for (i = 0; i < params->class_members; i++) {
+ if (!tbl_cb->keys[i].valid)
+ continue;
+
+ /* Get Classif Table counter stats for 'miss' */
+ if (tbl_cb->keys[i].miss_key) {
+ err = get_classif_tbl_miss_stats(cnt_cb, i);
+ if (err != 0)
+ return -EINVAL;
+ } else {
+ /*
+ * Get Classifier Table counter statistics for
+ * a key
+ */
+ err = get_classif_tbl_key_stats(cnt_cb, i);
+ if (err != 0)
+ return -EINVAL;
+ }
+ }
+ } else {
+ /* For every valid key, retrieve the hmcd */
+ for (i = 0; i < params->class_members; i++) {
+ if (!tbl_cb->keys[i].valid)
+ continue;
+
+ err = set_frag_manip(prm.td, &cnt_cb->tbl_cb.keys[i]);
+ if (err < 0) {
+ log_err("Invalid Fragmentation manip handle for counter id %d\n",
+ cnt_cb->id);
+ return -EINVAL;
+ }
+ }
+ /* Set the retrieve routine */
+ cnt_cb->f_get_cnt_stats = get_cnt_cls_tbl_frag_stats;
+ }
+
+ return 0;
+}
+
+static int set_cls_cnt_ccnode_cb(struct dpa_stats_cnt_cb *cnt_cb,
+ const struct dpa_stats_cls_cnt_params *params)
+{
+ struct dpa_stats *dpa_stats = cnt_cb->dpa_stats;
+ struct dpa_stats_cls_cnt_classif_node prm = params->classif_node_params;
+ uint32_t i = 0;
+ int err = 0;
+
+ if (!dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return -EFAULT;
+ }
+
+ /* Check Classification Cc Node counter selection */
+ if (prm.cnt_sel == 0 || prm.cnt_sel > DPA_STATS_CNT_CLASSIF_ALL) {
+ log_err("Parameter cnt_sel %d must be in range (1 - %d) for counter id %d\n",
+ prm.cnt_sel, DPA_STATS_CNT_CLASSIF_ALL, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ if (!params->classif_node_params.cc_node) {
+ log_err("Parameter classification CC Node handle cannot be NULL for counter id %d\n",
+ cnt_cb->id);
+ return -EFAULT;
+ }
+
+ if (!prm.keys) {
+ log_err("Pointer to the array of keys cannot be NULL for counter id %d\n",
+ cnt_cb->id);
+ return -EINVAL;
+ }
+
+ cnt_cb->ccnode_cb.cc_node = prm.cc_node;
+ cnt_cb->members_num = params->class_members;
+
+ /* Map Classif Node counter selection to CcNode statistics */
+ err = cnt_sel_to_stats(&cnt_cb->info,
+ dpa_stats->stats_sel[DPA_STATS_CNT_CLASSIF_NODE],
+ prm.cnt_sel >> CLASSIF_STATS_SHIFT);
+ if (err)
+ return err;
+
+ /* Set number of bytes that will be written by this counter */
+ cnt_cb->bytes_num = cnt_cb->members_num *
+ STATS_VAL_SIZE * cnt_cb->info.stats_num;
+
+ /* Set retrieve function depending on counter type */
+ err = set_cnt_classif_node_retrieve_func(cnt_cb, prm.ccnode_type);
+ if (err != 0)
+ return -EINVAL;
+
+ err = alloc_cnt_stats(&cnt_cb->info, cnt_cb->members_num);
+ if (err)
+ return err;
+
+ /* Allocate memory for one key descriptor */
+ cnt_cb->ccnode_cb.keys = kcalloc(cnt_cb->members_num,
+ sizeof(*cnt_cb->ccnode_cb.keys),
+ GFP_KERNEL);
+ if (!cnt_cb->ccnode_cb.keys) {
+ log_err("Cannot allocate memory for key descriptors for class counter id %d\n",
+ cnt_cb->id);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < cnt_cb->members_num; i++) {
+ /* Allocate memory for every key */
+ cnt_cb->ccnode_cb.keys[i].data.byte = kzalloc(
+ DPA_OFFLD_MAXENTRYKEYSIZE, GFP_KERNEL);
+ if (!cnt_cb->ccnode_cb.keys[i].data.byte)
+ log_err("Cannot allocate memory for key %d of counter id %d\n",
+ i, cnt_cb->id);
+ cnt_cb->ccnode_cb.keys[i].data.mask = kzalloc(
+ DPA_OFFLD_MAXENTRYKEYSIZE, GFP_KERNEL);
+ if (!cnt_cb->ccnode_cb.keys[i].data.mask)
+ log_err("Cannot allocate memory for mask %d of counter id %d\n",
+ i, cnt_cb->id);
+ }
+
+ for (i = 0; i < params->class_members; i++) {
+ if (!prm.keys[i]) {
+ /* Invalidate key data, to mark it for 'miss' */
+ cnt_cb->ccnode_cb.keys[i].valid_key = false;
+
+ /* Retrieve Classif Node counter statistics for 'miss'*/
+ err = get_ccnode_miss_stats(cnt_cb, prm.ccnode_type, i);
+ if (err != 0)
+ return err;
+ } else {
+ /* Copy the key descriptor */
+ err = copy_key_descriptor(prm.keys[i],
+ &cnt_cb->ccnode_cb.keys[i]);
+ if (err != 0) {
+ log_err("Cannot copy key descriptor from user parameters\n");
+ return -EINVAL;
+ }
+
+ /* Retrieve Classifier Node counter statistics for key*/
+ err = get_ccnode_key_stats(cnt_cb, prm.ccnode_type, i);
+ if (err != 0)
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static int set_cls_cnt_ipsec_cb(struct dpa_stats_cnt_cb *cnt_cb,
+ const struct dpa_stats_cls_cnt_params *prm)
+{
+ struct dpa_stats_cnt_ipsec_cb *cnt_ipsec_cb = &cnt_cb->ipsec_cb;
+ struct dpa_stats *dpa_stats = cnt_cb->dpa_stats;
+ struct dpa_ipsec_sa_stats stats;
+ uint32_t i = 0;
+ int err = 0;
+
+ if (!dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return -EFAULT;
+ }
+
+ /* Allocate memory for array of security association ids */
+ cnt_cb->ipsec_cb.sa_id = kcalloc(prm->class_members,
+ sizeof(*cnt_cb->ipsec_cb.sa_id), GFP_KERNEL);
+ if (!cnt_cb->ipsec_cb.sa_id) {
+ log_err("Cannot allocate memory for array of security association ids, for counter id %d\n",
+ cnt_cb->id);
+ return -ENOMEM;
+ }
+
+ /* Allocate memory for array that stores if SA id is valid */
+ cnt_cb->ipsec_cb.valid = kcalloc(prm->class_members,
+ sizeof(*cnt_cb->ipsec_cb.valid), GFP_KERNEL);
+ if (!cnt_cb->ipsec_cb.valid) {
+ log_err("Cannot allocate memory for array that stores if security association ids are valid for counter id %d\n",
+ cnt_cb->id);
+ return -ENOMEM;
+ }
+
+ cnt_cb->members_num = prm->class_members;
+
+ /* Map IPSec counter selection to statistics */
+ err = cnt_gen_sel_to_stats(cnt_cb, prm->ipsec_params.cnt_sel);
+ if (err < 0)
+ return err;
+
+ err = alloc_cnt_stats(&cnt_cb->info, cnt_cb->members_num);
+ if (err)
+ return err;
+
+ for (i = 0; i < prm->class_members; i++) {
+ if (prm->ipsec_params.sa_id[i] != DPA_OFFLD_INVALID_OBJECT_ID) {
+ cnt_ipsec_cb->sa_id[i] = prm->ipsec_params.sa_id[i];
+ cnt_ipsec_cb->valid[i] = TRUE;
+
+ err = dpa_ipsec_sa_get_stats(cnt_cb->ipsec_cb.sa_id[i],
+ &stats);
+ if (err < 0) {
+ log_err("Check failed for IPSec counter id %d due to incorrect parameters: sa_id=%d\n",
+ cnt_cb->id, cnt_cb->ipsec_cb.sa_id[i]);
+ return -EINVAL;
+ }
+ init_cnt_32bit_stats(&cnt_cb->info, &stats, i);
+ } else
+ cnt_ipsec_cb->valid[i] = FALSE;
+ }
+
+ return 0;
+}
+
+static int set_cls_cnt_traffic_mng_cb(struct dpa_stats_cnt_cb *cnt_cb,
+ const struct dpa_stats_cls_cnt_params *params)
+{
+ struct dpa_stats_cls_cnt_traffic_mng prm = params->traffic_mng_params;
+ uint32_t cnt_sel = prm.cnt_sel, i;
+ uint64_t stats[2];
+ int err = 0;
+ bool us_cnt = FALSE;
+
+ if (!cnt_cb->dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return -EFAULT;
+ }
+
+ /* Check if this is an users-space counter and if so, reset the flag */
+ if (cnt_sel & DPA_STATS_US_CNT) {
+ us_cnt = TRUE;
+ cnt_sel &= ~DPA_STATS_US_CNT;
+ }
+
+ cnt_cb->members_num = params->class_members;
+
+ /* Map Traffic Manager counter selection to statistics */
+ err = cnt_gen_sel_to_stats(cnt_cb, cnt_sel);
+ if (err < 0)
+ return err;
+
+ /* For user-space counters there is a different retrieve function */
+ if (us_cnt) {
+ cnt_cb->f_get_cnt_stats = get_cnt_us_stats;
+ return 0;
+ }
+
+ err = alloc_cnt_stats(&cnt_cb->info, cnt_cb->members_num);
+ if (err)
+ return err;
+
+ cnt_cb->gen_cb.objs = kcalloc(cnt_cb->members_num, sizeof(t_Handle),
+ GFP_KERNEL);
+ if (!cnt_cb->gen_cb.objs) {
+ log_err("No more memory for new traffic manager class counter\n");
+ return -ENOMEM;
+ }
+
+ /* Check the counter source and the Traffic Manager object */
+ switch (prm.src) {
+ case DPA_STATS_CNT_TRAFFIC_CLASS:
+ cnt_cb->f_get_cnt_stats = get_cnt_traffic_mng_cq_stats;
+ for (i = 0; i < params->class_members; i++) {
+ if (!prm.traffic_mng[i]) {
+ log_err("Parameter traffic_mng handle cannot be NULL for member %d\n",
+ i);
+ return -EFAULT;
+ }
+
+ /* Check the provided Traffic Manager object */
+ err = qman_ceetm_cq_get_dequeue_statistics(
+ prm.traffic_mng[i], 0, &stats[0], &stats[1]);
+ if (err < 0) {
+ log_err("Invalid traffic_mng handle for counter id %d\n",
+ cnt_cb->id);
+ return -EINVAL;
+ }
+ init_cnt_64bit_stats(&cnt_cb->info, &stats, i);
+ cnt_cb->gen_cb.objs[i] = prm.traffic_mng[i];
+ }
+ break;
+ case DPA_STATS_CNT_TRAFFIC_CG:
+ cnt_cb->f_get_cnt_stats = get_cnt_traffic_mng_ccg_stats;
+ for (i = 0; i < params->class_members; i++) {
+ if (!prm.traffic_mng[i]) {
+ log_err("Parameter traffic_mng handle cannot be NULL for member %d\n",
+ i);
+ return -EFAULT;
+ }
+
+ /* Check the provided Traffic Manager object */
+ err = qman_ceetm_ccg_get_reject_statistics(
+ prm.traffic_mng[i], 0, &stats[0], &stats[1]);
+ if (err < 0) {
+ log_err("Invalid traffic_mng handle for counter id %d\n",
+ cnt_cb->id);
+ return -EINVAL;
+ }
+ init_cnt_64bit_stats(&cnt_cb->info, &stats, i);
+ cnt_cb->gen_cb.objs[i] = prm.traffic_mng[i];
+ }
+ break;
+ default:
+ log_err("Parameter src %d must be in range (%d - %d) for counter id %d\n",
+ prm.src, DPA_STATS_CNT_TRAFFIC_CLASS,
+ DPA_STATS_CNT_TRAFFIC_CG, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int set_classif_tbl_member(const struct dpa_stats_cls_member_params *prm,
+ int mbr_idx, struct dpa_stats_cnt_cb *cnt_cb)
+{
+ struct dpa_stats_cnt_classif_tbl_cb *tbl_cb = &cnt_cb->tbl_cb;
+ struct dpa_stats_lookup_key *lookup_key = &tbl_cb->keys[mbr_idx];
+ struct dpa_stats_allocated_lookup_key *key = &lookup_key->key;
+ uint32_t i = 0;
+ uint32_t stats_base_idx;
+ int err = 0;
+
+ /* Check that counter is of type Classifier table */
+ if (cnt_cb->type != DPA_STATS_CNT_CLASSIF_TBL) {
+ log_err("Operation permitted only on counter type DPA_STATS_CNT_CLASSIF_TBL %d for counter id %d\n",
+ DPA_STATS_CNT_CLASSIF_TBL, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ /* Check that member index does not exceeds class size */
+ if (mbr_idx < 0 || mbr_idx >= cnt_cb->members_num) {
+ log_err("Parameter member_index %d must be in range (0 - %d) for counter id %d\n",
+ mbr_idx, cnt_cb->members_num - 1, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ if (prm->type == DPA_STATS_CLS_MEMBER_SINGLE_KEY) {
+ if (!prm->key) {
+ /* Mark the key as 'miss' entry */
+ tbl_cb->keys[mbr_idx].miss_key = TRUE;
+ tbl_cb->keys[mbr_idx].valid = TRUE;
+ } else if (!prm->key->byte) {
+ /* Mark the key as invalid */
+ tbl_cb->keys[mbr_idx].valid = FALSE;
+ tbl_cb->keys[mbr_idx].miss_key = FALSE;
+ /* Reset the statistics */
+ stats_base_idx = cnt_cb->info.stats_num * mbr_idx;
+ for (i = 0; i < cnt_cb->info.stats_num; i++) {
+ cnt_cb->info.stats[stats_base_idx + i] = 0;
+ cnt_cb->info.last_stats[stats_base_idx + i] = 0;
+ }
+ return 0;
+ } else {
+ /* Copy the key descriptor */
+ err = copy_key_descriptor(prm->key, key);
+ if (err != 0) {
+ log_err("Cannot copy key descriptor from user parameters\n");
+ return -EINVAL;
+ }
+ tbl_cb->keys[mbr_idx].miss_key = FALSE;
+ tbl_cb->keys[mbr_idx].valid = TRUE;
+ }
+ } else {
+ if (prm->pair)
+ if (prm->pair->first_key)
+ if (!prm->pair->first_key->byte) {
+ /* Mark the key as invalid */
+ tbl_cb->keys[mbr_idx].valid = FALSE;
+ tbl_cb->keys[mbr_idx].miss_key = FALSE;
+
+ /* Reset the statistics */
+ stats_base_idx =
+ cnt_cb->info.stats_num *
+ mbr_idx;
+ for (i = 0; i < cnt_cb->info.stats_num;
+ i++) {
+
+ cnt_cb->info.stats[
+ stats_base_idx + i] = 0;
+ cnt_cb->info.last_stats[
+ stats_base_idx + i] = 0;
+
+ }
+ return 0;
+ }
+ err = set_cls_cnt_classif_tbl_pair(cnt_cb, tbl_cb->td,
+ prm->pair, mbr_idx);
+ if (err != 0) {
+ log_err("Cannot configure the pair key for counter id %d of member %d\n",
+ cnt_cb->id, mbr_idx);
+ return -EINVAL;
+ }
+ }
+
+ if (cnt_cb->f_get_cnt_stats != get_cnt_cls_tbl_frag_stats) {
+ if (tbl_cb->keys[mbr_idx].miss_key) {
+ /* Get Classifier Table counter statistics for 'miss' */
+ return get_classif_tbl_miss_stats(cnt_cb, mbr_idx);
+ } else {
+ /* Get Classifier Table counter statistics for a key */
+ return get_classif_tbl_key_stats(cnt_cb, mbr_idx);
+ }
+ } else{
+ err = set_frag_manip(tbl_cb->td, &tbl_cb->keys[mbr_idx]);
+ if (err < 0) {
+ log_err("Invalid Fragmentation manip handle for counter id %d\n",
+ cnt_cb->id);
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+int set_ipsec_member(const struct dpa_stats_cls_member_params *params,
+ int mbr_idx,
+ struct dpa_stats_cnt_cb *cnt_cb)
+{
+ struct dpa_stats_cnt_ipsec_cb *ipsec_cb = &cnt_cb->ipsec_cb;
+ struct dpa_ipsec_sa_stats stats;
+ uint32_t i = 0;
+ uint32_t stats_base_idx;
+ int err = 0;
+
+ /* Check that counter is of type IPSec */
+ if (cnt_cb->type != DPA_STATS_CNT_IPSEC) {
+ log_err("Operation permitted only on counter type DPA_STATS_CNT_IPSEC %d for counter id %d\n",
+ DPA_STATS_CNT_IPSEC, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ /* Check that member index does not exceeds class size */
+ if (mbr_idx < 0 || mbr_idx >= cnt_cb->members_num) {
+ log_err("Parameter member_index %d must be in range (0 - %d) for counter id %d\n",
+ mbr_idx, cnt_cb->members_num - 1, cnt_cb->id);
+ return -EINVAL;
+ }
+
+ if (params->sa_id == DPA_OFFLD_INVALID_OBJECT_ID) {
+ /* Mark that corresponding SA id as invalid */
+ ipsec_cb->valid[mbr_idx] = FALSE;
+ /* Reset the statistics */
+ stats_base_idx = cnt_cb->info.stats_num * mbr_idx;
+ for (i = 0; i < cnt_cb->info.stats_num; i++) {
+ cnt_cb->info.stats[stats_base_idx + i] = 0;
+ cnt_cb->info.last_stats[stats_base_idx + i] = 0;
+ }
+ } else {
+ /* Mark the corresponding SA id as valid */
+ ipsec_cb->valid[mbr_idx] = TRUE;
+ ipsec_cb->sa_id[mbr_idx] = params->sa_id;
+
+ err = dpa_ipsec_sa_get_stats(
+ cnt_cb->ipsec_cb.sa_id[mbr_idx], &stats);
+ if (err < 0) {
+ log_err("Get failed for IPSec counter id %d due to incorrect parameters: sa_id=%d\n",
+ cnt_cb->id, cnt_cb->ipsec_cb.sa_id[mbr_idx]);
+ return -EINVAL;
+ }
+ init_cnt_32bit_stats(&cnt_cb->info, &stats, 0);
+ }
+ return 0;
+}
+
+static void init_cnt_32bit_stats(struct stats_info *stats_info,
+ void *stats, uint32_t idx)
+{
+ uint32_t j = 0;
+ uint32_t stats_val, stats_base_idx;
+
+ stats_base_idx = stats_info->stats_num * idx;
+
+ for (j = 0; j < stats_info->stats_num; j++) {
+ if (stats_info->stats_off[j] == UNSUPPORTED_CNT_SEL)
+ continue;
+
+ /* Get statistics value */
+ stats_val = *((uint32_t *)(stats + stats_info->stats_off[j]));
+
+ /* Store the current value as the last read value */
+ stats_info->stats[stats_base_idx + j] = 0;
+ stats_info->last_stats[stats_base_idx + j] = stats_val;
+ }
+}
+
+static void init_cnt_64bit_stats(struct stats_info *stats_info,
+ void *stats, uint32_t idx)
+{
+ uint32_t j = 0;
+ uint32_t stats_base_idx;
+ uint64_t stats_val;
+
+ stats_base_idx = stats_info->stats_num * idx;
+
+ for (j = 0; j < stats_info->stats_num; j++) {
+ /* Get statistics value */
+ stats_val = *((uint64_t *)(stats + stats_info->stats_off[j]));
+
+ /* Store the current value as the last read value */
+ stats_info->stats[stats_base_idx + j] = 0;
+ stats_info->last_stats[stats_base_idx + j] = stats_val;
+ }
+}
+
+static inline void get_cnt_32bit_stats(struct dpa_stats_req_cb *req_cb,
+ struct stats_info *stats_info,
+ void *stats, uint32_t idx)
+{
+ uint32_t j = 0;
+ uint32_t stats_val;
+ uint32_t stats_base_idx, stats_index;
+
+ stats_base_idx = stats_info->stats_num * idx;
+
+ for (j = 0; j < stats_info->stats_num; j++) {
+ if (stats_info->stats_off[j] == UNSUPPORTED_CNT_SEL) {
+ /* Write the memory location */
+ memset(req_cb->request_area, 0, STATS_VAL_SIZE);
+
+ /* Update the memory pointer */
+ req_cb->request_area += STATS_VAL_SIZE;
+ continue;
+ }
+
+ /* Get statistics value */
+ stats_val = *((uint32_t *)(stats + stats_info->stats_off[j]));
+
+ stats_index = stats_base_idx + j;
+
+ /* Check for rollover */
+ if (stats_val < stats_info->last_stats[stats_index])
+ stats_info->stats[stats_index] +=
+ ((unsigned long int)0xffffffff -
+ stats_info->last_stats[stats_index]) +
+ stats_val;
+ else
+ stats_info->stats[stats_index] += stats_val -
+ stats_info->last_stats[stats_index];
+
+ /* Store the current value as the last read value */
+ stats_info->last_stats[stats_index] = stats_val;
+
+ /* Write the memory location */
+ *(uint32_t *)(req_cb->request_area) =
+ stats_info->stats[stats_index];
+
+ /* Update the memory pointer */
+ req_cb->request_area += STATS_VAL_SIZE;
+
+ if (stats_info->reset)
+ stats_info->stats[stats_index] = 0;
+ }
+}
+
+static inline void get_cnt_64bit_stats(struct dpa_stats_req_cb *req_cb,
+ struct stats_info *stats_info,
+ void *stats, uint32_t idx)
+{
+ uint32_t j = 0;
+ uint64_t stats_val;
+ uint32_t stats_base_idx, stats_index;
+
+ stats_base_idx = stats_info->stats_num * idx;
+
+ for (j = 0; j < stats_info->stats_num; j++) {
+ /* Get statistics value */
+ stats_val = *((uint64_t *)(stats + stats_info->stats_off[j]));
+
+ stats_index = stats_base_idx + j;
+
+ /* Check for rollover */
+ if (stats_val < stats_info->last_stats[stats_index])
+ stats_info->stats[stats_index] +=
+ ((unsigned long int)0xffffffff -
+ stats_info->last_stats[stats_index]) +
+ stats_val;
+ else
+ stats_info->stats[stats_index] += stats_val -
+ stats_info->last_stats[stats_index];
+
+ /* Store the current value as the last read value */
+ stats_info->last_stats[stats_index] = stats_val;
+
+ /* Write the memory location */
+ *(uint32_t *)(req_cb->request_area) =
+ (uint32_t)stats_info->stats[stats_index];
+
+ /* Update the memory pointer */
+ req_cb->request_area += STATS_VAL_SIZE;
+
+ if (stats_info->reset)
+ stats_info->stats[stats_index] = 0;
+ }
+}
+
+static int get_cnt_eth_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb)
+{
+ t_FmMacStatistics stats;
+ uint32_t i = 0;
+ int err = 0;
+
+ for (i = 0; i < cnt_cb->members_num; i++) {
+ err = FM_MAC_GetStatistics(cnt_cb->gen_cb.objs[i], &stats);
+ if (err != 0) {
+ log_err("Cannot retrieve Ethernet statistics for counter id %d\n",
+ cnt_cb->id);
+ return -ENOENT;
+ }
+
+ get_cnt_64bit_stats(req_cb, &cnt_cb->info, (void *)&stats, i);
+ }
+
+ return 0;
+}
+
+static int get_cnt_reass_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb)
+{
+ struct t_FmPcdManipStats stats;
+ uint32_t i = 0;
+ int err = 0;
+
+ for (i = 0; i < cnt_cb->members_num; i++) {
+ err = FM_PCD_ManipGetStatistics(cnt_cb->gen_cb.objs[i], &stats);
+ if (err < 0) {
+ log_err("Cannot retrieve Reassembly statistics for counter id %d\n",
+ cnt_cb->id);
+ return -ESRCH;
+ }
+
+ get_cnt_32bit_stats(req_cb, &cnt_cb->info,
+ &stats.u.reassem.u.ipReassem, i);
+ }
+
+ return 0;
+}
+
+static int get_cnt_frag_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb)
+{
+ struct t_FmPcdManipStats stats;
+ uint32_t i = 0;
+ int err = 0;
+
+ for (i = 0; i < cnt_cb->members_num; i++) {
+ err = FM_PCD_ManipGetStatistics(cnt_cb->gen_cb.objs[i], &stats);
+ if (err < 0) {
+ log_err("Cannot retrieve Fragmentation statistics for counter id %d\n",
+ cnt_cb->id);
+ return -EINTR;
+ }
+
+ get_cnt_32bit_stats(req_cb, &cnt_cb->info,
+ &stats.u.frag.u.ipFrag, i);
+ }
+
+ return 0;
+}
+
+static int get_cnt_plcr_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb)
+{
+ struct stats_info *info = &cnt_cb->info;
+ uint64_t stats_val = 0;
+ uint32_t i = 0, j = 0;
+ uint32_t stats_index, stats_base_idx;
+
+ for (i = 0; i < cnt_cb->members_num; i++) {
+
+ stats_base_idx = info->stats_num * i;
+
+ for (j = 0; j < info->stats_num; j++) {
+ stats_val = (uint64_t)FM_PCD_PlcrProfileGetCounter(
+ cnt_cb->gen_cb.objs[i], info->stats_off[j]);
+
+ stats_index = stats_base_idx + j;
+
+ /* Check for rollover */
+ if (stats_val < info->last_stats[stats_index])
+ info->stats[stats_index] +=
+ ((unsigned long int)0xffffffff -
+ info->last_stats[stats_index]) +
+ stats_val;
+ else
+ info->stats[stats_index] += stats_val -
+ info->last_stats[stats_index];
+
+ /* Store the current value as the last read value */
+ info->last_stats[stats_index] = stats_val;
+
+ /* Write the memory location */
+ *(uint32_t *)(req_cb->request_area) =
+ (uint32_t)info->stats[stats_index];
+
+ /* Update the memory pointer */
+ req_cb->request_area += STATS_VAL_SIZE;
+
+ if (info->reset)
+ info->stats[stats_index] = 0;
+ }
+ }
+
+ return 0;
+}
+
+static int get_cnt_cls_tbl_match_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb)
+{
+ t_FmPcdCcKeyStatistics stats;
+ uint32_t i = 0;
+ int err = 0;
+
+ for (i = 0; i < cnt_cb->members_num; i++) {
+ if (!cnt_cb->tbl_cb.keys[i].valid) {
+ /* Write the memory location */
+ memset(req_cb->request_area, 0,
+ cnt_cb->info.stats_num * STATS_VAL_SIZE);
+
+ /* Update the memory pointer */
+ req_cb->request_area += STATS_VAL_SIZE *
+ cnt_cb->info.stats_num;
+ continue;
+ }
+
+ if (cnt_cb->tbl_cb.keys[i].miss_key) {
+ err = FM_PCD_MatchTableGetMissStatistics(
+ cnt_cb->tbl_cb.keys[i].cc_node, &stats);
+ } else {
+ uint8_t *mask_data;
+
+ if (cnt_cb->tbl_cb.keys[i].key.valid_mask)
+ mask_data =
+ cnt_cb->tbl_cb.keys[i].key.data.mask;
+ else
+ mask_data = NULL;
+
+ err = FM_PCD_MatchTableFindNGetKeyStatistics(
+ cnt_cb->tbl_cb.keys[i].cc_node,
+ cnt_cb->tbl_cb.keys[i].key.data.size,
+ cnt_cb->tbl_cb.keys[i].key.data.byte,
+ mask_data,
+ &stats);
+ }
+
+ if (err != 0) {
+ log_err("Cannot retrieve Classifier Exact Match Table statistics for counter id %d\n",
+ cnt_cb->id);
+ return -EIO;
+ }
+ get_cnt_32bit_stats(req_cb, &cnt_cb->info, &stats, i);
+ }
+
+ return 0;
+}
+
+static int get_cnt_cls_tbl_hash_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb)
+{
+ t_FmPcdCcKeyStatistics stats;
+ uint32_t i = 0;
+ int err = 0;
+
+ for (i = 0; i < cnt_cb->members_num; i++) {
+ if (!cnt_cb->tbl_cb.keys[i].valid) {
+ /* Write the memory location */
+ memset(req_cb->request_area, 0,
+ cnt_cb->info.stats_num * STATS_VAL_SIZE);
+
+ /* Update the memory pointer */
+ req_cb->request_area += STATS_VAL_SIZE *
+ cnt_cb->info.stats_num;
+ continue;
+ }
+
+ if (cnt_cb->tbl_cb.keys[i].miss_key) {
+ err = FM_PCD_HashTableGetMissStatistics(
+ cnt_cb->tbl_cb.keys[i].cc_node, &stats);
+ } else {
+ err = FM_PCD_HashTableFindNGetKeyStatistics(
+ cnt_cb->tbl_cb.keys[i].cc_node,
+ cnt_cb->tbl_cb.keys[i].key.data.size,
+ cnt_cb->tbl_cb.keys[i].key.data.byte,
+ &stats);
+ }
+ if (err != 0) {
+ log_err("Cannot retrieve Classifier Hash Table statistics for counter id %d\n",
+ cnt_cb->id);
+ return -EIO;
+ }
+ get_cnt_32bit_stats(req_cb, &cnt_cb->info, &stats, i);
+ }
+
+ return 0;
+}
+
+static int get_cnt_cls_tbl_index_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb)
+{
+ t_FmPcdCcKeyStatistics stats;
+ uint32_t i = 0;
+ int err = 0;
+
+ for (i = 0; i < cnt_cb->members_num; i++) {
+ if (!cnt_cb->tbl_cb.keys[i].valid) {
+ /* Write the memory location */
+ memset(req_cb->request_area, 0,
+ cnt_cb->info.stats_num * STATS_VAL_SIZE);
+
+ /* Update the memory pointer */
+ req_cb->request_area += STATS_VAL_SIZE *
+ cnt_cb->info.stats_num;
+ continue;
+ }
+
+ if (cnt_cb->tbl_cb.keys[i].miss_key) {
+ err = FM_PCD_MatchTableGetMissStatistics(
+ cnt_cb->tbl_cb.keys[i].cc_node, &stats);
+ } else {
+ err = FM_PCD_MatchTableGetKeyStatistics(
+ cnt_cb->tbl_cb.keys[i].cc_node,
+ cnt_cb->tbl_cb.keys[i].key.data.byte[0],
+ &stats);
+ }
+
+ if (err != 0) {
+ log_err("Cannot retrieve Classifier Indexed Table statistics for counter id %d\n",
+ cnt_cb->id);
+ return -EIO;
+ }
+ get_cnt_32bit_stats(req_cb, &cnt_cb->info, &stats, i);
+ }
+
+ return 0;
+}
+
+static int get_cnt_cls_tbl_frag_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb)
+{
+ struct t_FmPcdManipStats stats;
+ uint32_t i = 0;
+ int err = 0;
+
+ for (i = 0; i < cnt_cb->members_num; i++) {
+ if (!cnt_cb->tbl_cb.keys[i].valid) {
+ /* Write the memory location */
+ memset(req_cb->request_area, 0,
+ cnt_cb->info.stats_num * STATS_VAL_SIZE);
+
+ /* Update the memory pointer */
+ req_cb->request_area += STATS_VAL_SIZE *
+ cnt_cb->info.stats_num;
+ continue;
+ }
+
+ err = FM_PCD_ManipGetStatistics(
+ cnt_cb->tbl_cb.keys[i].frag, &stats);
+ if (err < 0) {
+ log_err("Cannot retrieve Fragmentation statistics for counter id %d\n",
+ cnt_cb->id);
+ return -EINTR;
+ }
+ get_cnt_32bit_stats(req_cb,
+ &cnt_cb->info, &stats.u.frag.u.ipFrag, i);
+ }
+
+ return 0;
+}
+
+static int get_cnt_ccnode_match_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb)
+{
+ t_FmPcdCcKeyStatistics stats;
+ uint32_t i = 0;
+ int err = 0;
+
+ for (i = 0; i < cnt_cb->members_num; i++) {
+ if (!cnt_cb->ccnode_cb.keys[i].valid_key) {
+ err = FM_PCD_MatchTableGetMissStatistics(
+ cnt_cb->ccnode_cb.cc_node, &stats);
+ } else {
+ uint8_t *mask_data;
+
+ if (cnt_cb->ccnode_cb.keys[i].valid_mask)
+ mask_data = cnt_cb->ccnode_cb.keys[i].data.mask;
+ else
+ mask_data = NULL;
+
+ err = FM_PCD_MatchTableFindNGetKeyStatistics(
+ cnt_cb->ccnode_cb.cc_node,
+ cnt_cb->ccnode_cb.keys[i].data.size,
+ cnt_cb->ccnode_cb.keys[i].data.byte,
+ mask_data, &stats);
+ }
+ if (err != 0) {
+ log_err("Cannot retrieve Classification Cc Node Exact Match statistics for counter id %d\n",
+ cnt_cb->id);
+ return -ENXIO;
+ }
+
+ get_cnt_32bit_stats(req_cb, &cnt_cb->info, (void *)&stats, i);
+ }
+ return 0;
+}
+
+static int get_cnt_ccnode_hash_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb)
+{
+ t_FmPcdCcKeyStatistics stats;
+ uint32_t i = 0;
+ int err = 0;
+
+ for (i = 0; i < cnt_cb->members_num; i++) {
+ if (!cnt_cb->ccnode_cb.keys[i].valid_key) {
+ err = FM_PCD_HashTableGetMissStatistics(
+ cnt_cb->ccnode_cb.cc_node, &stats);
+ } else {
+ err = FM_PCD_HashTableFindNGetKeyStatistics(
+ cnt_cb->ccnode_cb.cc_node,
+ cnt_cb->ccnode_cb.keys[i].data.size,
+ cnt_cb->ccnode_cb.keys[i].data.byte, &stats);
+ }
+
+ if (err != 0) {
+ log_err("Cannot retrieve Classification Cc Node Hash statistics for counter id %d\n",
+ cnt_cb->id);
+ return -ENXIO;
+ }
+
+ get_cnt_32bit_stats(req_cb, &cnt_cb->info, (void *)&stats, i);
+ }
+ return 0;
+}
+
+static int get_cnt_ccnode_index_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb)
+{
+ t_FmPcdCcKeyStatistics stats;
+ uint32_t i = 0;
+ int err = 0;
+
+ for (i = 0; i < cnt_cb->members_num; i++) {
+ if (!cnt_cb->ccnode_cb.keys[i].valid_key) {
+ err = FM_PCD_MatchTableGetMissStatistics(
+ cnt_cb->ccnode_cb.cc_node, &stats);
+ } else {
+ err = FM_PCD_MatchTableGetKeyStatistics(
+ cnt_cb->ccnode_cb.cc_node,
+ cnt_cb->ccnode_cb.keys[i].data.byte[0], &stats);
+ }
+ if (err != 0) {
+ log_err("Cannot retrieve Classification Cc Node Index statistics for counter id %d\n",
+ cnt_cb->id);
+ return -ENXIO;
+ }
+
+ get_cnt_32bit_stats(req_cb, &cnt_cb->info, (void *)&stats, i);
+ }
+ return 0;
+}
+
+static int get_cnt_ipsec_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb)
+{
+ struct dpa_ipsec_sa_stats stats;
+ uint32_t i = 0;
+ int err = 0;
+
+ for (i = 0; i < cnt_cb->members_num; i++) {
+ if (!cnt_cb->ipsec_cb.valid[i]) {
+ /* Write the memory location */
+ memset(req_cb->request_area, 0,
+ cnt_cb->info.stats_num * STATS_VAL_SIZE);
+
+ /* Update the memory pointer */
+ req_cb->request_area +=
+ STATS_VAL_SIZE * cnt_cb->info.stats_num;
+
+ continue;
+ }
+
+ err = dpa_ipsec_sa_get_stats(cnt_cb->ipsec_cb.sa_id[i], &stats);
+ if (err < 0) {
+ log_err("Cannot retrieve IPSec statistics for counter id %d\n",
+ cnt_cb->id);
+ return -E2BIG;
+ }
+
+ get_cnt_32bit_stats(req_cb, &cnt_cb->info, &stats, i);
+ }
+
+ return 0;
+}
+
+static int get_cnt_traffic_mng_cq_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb)
+{
+ uint32_t i = 0;
+ u64 stats_val[2];
+ int err = 0;
+
+ for (i = 0; i < cnt_cb->members_num; i++) {
+ /* Retrieve statistics for the current member */
+ err = qman_ceetm_cq_get_dequeue_statistics(
+ cnt_cb->gen_cb.objs[i], 0,
+ &stats_val[1], &stats_val[0]);
+ if (err < 0) {
+ log_err("Cannot retrieve Traffic Manager Class Queue statistics for counter id %d\n",
+ cnt_cb->id);
+ return -EINVAL;
+ }
+ get_cnt_64bit_stats(req_cb, &cnt_cb->info, stats_val, i);
+ }
+ return 0;
+}
+
+static int get_cnt_traffic_mng_ccg_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb)
+{
+ uint32_t i = 0;
+ u64 stats_val[2];
+ int err = 0;
+
+ for (i = 0; i < cnt_cb->members_num; i++) {
+ err = qman_ceetm_ccg_get_reject_statistics(
+ cnt_cb->gen_cb.objs[i], 0,
+ &stats_val[1], &stats_val[0]);
+ if (err < 0) {
+ log_err("Cannot retrieve Traffic Manager Class Congestion Group statistics for counter id %d\n",
+ cnt_cb->id);
+ return -EINVAL;
+ }
+ get_cnt_64bit_stats(req_cb, &cnt_cb->info, stats_val, i);
+ }
+ return 0;
+}
+
+static int get_cnt_us_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb)
+{
+ uint32_t i = 0, j = 0;
+ req_cb->config.cnts_ids[req_cb->cnts_num] = req_cb->bytes_num;
+
+ for (i = 0; i < cnt_cb->members_num; i++) {
+ for (j = 0; j < cnt_cb->info.stats_num; j++) {
+ /* Write the memory location */
+ *(uint32_t *)(req_cb->request_area) = 0;
+ /* Update the memory pointer */
+ req_cb->request_area += STATS_VAL_SIZE;
+ }
+ }
+ return 0;
+}
+
+static void async_req_work_func(struct work_struct *work)
+{
+ struct dpa_stats_req_cb *req_cb = NULL;
+ struct dpa_stats *dpa_stats = NULL;
+ int err = 0;
+
+ dpa_stats = gbl_dpa_stats;
+
+ req_cb = container_of(work, struct dpa_stats_req_cb, async_req_work);
+ BUG_ON(!req_cb);
+
+ err = treat_cnts_request(dpa_stats, req_cb);
+ if (err < 0) {
+ log_err("Cannot obtain counter values in asynchronous mode\n");
+ req_cb->bytes_num = err;
+ }
+
+ /* Notify the application */
+ req_cb->request_done(0, req_cb->config.storage_area_offset,
+ req_cb->cnts_num, req_cb->bytes_num);
+
+ /* Release the request control block */
+ err = put_req(dpa_stats, req_cb);
+ if (err < 0)
+ log_err("Cannot release internal request structure\n");
+
+ return;
+}
+
+int dpa_stats_init(const struct dpa_stats_params *params, int *dpa_stats_id)
+{
+ struct dpa_stats *dpa_stats = NULL;
+ int err = 0;
+
+ /* Multiple DPA Stats instances are not currently supported */
+ unused(dpa_stats_id);
+
+ /* Sanity checks */
+ if (gbl_dpa_stats) {
+ log_err("DPA Stats component already initialized. Multiple DPA Stats instances are not supported.\n");
+ return -EPERM;
+ }
+
+ /* Check user-provided parameters */
+ err = check_dpa_stats_params(params);
+ if (err < 0)
+ return err;
+
+ /* Control block allocation */
+ dpa_stats = kzalloc(sizeof(struct dpa_stats), GFP_KERNEL);
+ if (!dpa_stats) {
+ log_err("Cannot allocate memory for internal DPA Stats structure.\n");
+ return -ENOMEM;
+ }
+
+ /* Store parameters */
+ dpa_stats->config = *params;
+
+ /* Initialize DPA Stats instance lock */
+ mutex_init(&dpa_stats->lock);
+ mutex_init(&dpa_stats->sched_cnt_lock);
+
+ /* Allocate and initialize resources occupied by counters */
+ err = init_cnts_resources(dpa_stats);
+ if (err < 0) {
+ free_resources();
+ return err;
+ }
+
+ /* Allocate and initialize requests control block */
+ err = init_reqs_resources(dpa_stats);
+ if (err < 0) {
+ free_resources();
+ return err;
+ }
+
+ /* Map each Ethernet counter selection to a FM-MAC statistics */
+ create_cnt_eth_stats(dpa_stats);
+
+ /* Map Reassembly counters to FMAN Reassembly statistics */
+ create_cnt_reass_stats(dpa_stats);
+
+ /* Map Fragmentation counters to FMAN Fragmentation statistics */
+ create_cnt_frag_stats(dpa_stats);
+
+ /* Map Policer counters to FMAN Policer statistics */
+ create_cnt_plcr_stats(dpa_stats);
+
+ /* Map Classifier counters to FMAN Classifier statistics */
+ create_classif_stats(dpa_stats);
+
+ /* Map IPSec counters */
+ create_cnt_ipsec_stats(dpa_stats);
+
+ /* Map Traffic Manager counters to QMan CEETM statistics */
+ create_cnt_traffic_mng_stats(dpa_stats);
+
+ gbl_dpa_stats = dpa_stats;
+
+ return 0;
+}
+EXPORT_SYMBOL(dpa_stats_init);
+
+int dpa_stats_create_counter(int dpa_stats_id,
+ const struct dpa_stats_cnt_params *params,
+ int *dpa_stats_cnt_id)
+{
+ struct dpa_stats *dpa_stats = NULL;
+ struct dpa_stats_cnt_cb *cnt_cb = NULL;
+ int err = 0, err_rb = 0;
+
+ /* multiple DPA Stats instances are not currently supported */
+ unused(dpa_stats_id);
+
+ if (!gbl_dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return -EPERM;
+ }
+
+ if (!dpa_stats_cnt_id) {
+ log_err("Parameter dpa_stats_cnt_id cannot be NULL\n");
+ return -EINVAL;
+ }
+ *dpa_stats_cnt_id = DPA_OFFLD_INVALID_OBJECT_ID;
+
+ if (!params) {
+ log_err("Parameter params cannot be NULL\n");
+ return -EFAULT;
+ }
+
+ dpa_stats = gbl_dpa_stats;
+
+ err = get_new_cnt(dpa_stats, &cnt_cb);
+ if (err < 0) {
+ log_err("Cannot retrieve preallocated internal counter structure\n");
+ return err;
+ }
+
+ /* Acquire the lock for the counter control block */
+ mutex_lock(&cnt_cb->lock);
+
+ switch (params->type) {
+ case DPA_STATS_CNT_ETH:
+ cnt_cb->type = DPA_STATS_CNT_ETH;
+ cnt_cb->f_get_cnt_stats = get_cnt_eth_stats;
+
+ err = set_cnt_eth_cb(cnt_cb, params);
+ if (err != 0) {
+ log_err("Cannot create Ethernet counter id %d\n",
+ cnt_cb->id);
+ goto create_counter_err;
+ }
+ break;
+ case DPA_STATS_CNT_REASS:
+ cnt_cb->type = DPA_STATS_CNT_REASS;
+ cnt_cb->f_get_cnt_stats = get_cnt_reass_stats;
+
+ err = set_cnt_reass_cb(cnt_cb, params);
+ if (err != 0) {
+ log_err("Cannot create Reassembly counter id %d\n",
+ cnt_cb->id);
+ goto create_counter_err;
+ }
+ break;
+ case DPA_STATS_CNT_FRAG:
+ cnt_cb->type = DPA_STATS_CNT_FRAG;
+ cnt_cb->f_get_cnt_stats = get_cnt_frag_stats;
+
+ err = set_cnt_frag_cb(cnt_cb, params);
+ if (err != 0) {
+ log_err("Cannot create Fragmentation counter id %d\n",
+ cnt_cb->id);
+ goto create_counter_err;
+ }
+ break;
+ case DPA_STATS_CNT_POLICER:
+ cnt_cb->type = DPA_STATS_CNT_POLICER;
+ cnt_cb->f_get_cnt_stats = get_cnt_plcr_stats;
+
+ err = set_cnt_plcr_cb(cnt_cb, params);
+ if (err != 0) {
+ log_err("Cannot create Policer counter id %d\n",
+ cnt_cb->id);
+ goto create_counter_err;
+ }
+ break;
+ case DPA_STATS_CNT_CLASSIF_TBL:
+ cnt_cb->type = DPA_STATS_CNT_CLASSIF_TBL;
+
+ err = set_cnt_classif_tbl_cb(cnt_cb, params);
+ if (err != 0) {
+ log_err("Cannot create Classifier Table counter id %d\n",
+ cnt_cb->id);
+ goto create_counter_err;
+ }
+ break;
+ case DPA_STATS_CNT_CLASSIF_NODE:
+ cnt_cb->type = DPA_STATS_CNT_CLASSIF_NODE;
+
+ err = set_cnt_ccnode_cb(cnt_cb, params);
+ if (err != 0) {
+ log_err("Cannot create Classification Cc Node counter id %d\n",
+ cnt_cb->id);
+ goto create_counter_err;
+ }
+ break;
+ case DPA_STATS_CNT_IPSEC:
+ cnt_cb->type = DPA_STATS_CNT_IPSEC;
+ cnt_cb->f_get_cnt_stats = get_cnt_ipsec_stats;
+
+ err = set_cnt_ipsec_cb(cnt_cb, params);
+ if (err != 0) {
+ log_err("Cannot create IPSec counter id %d\n",
+ cnt_cb->id);
+ goto create_counter_err;
+ }
+ break;
+ case DPA_STATS_CNT_TRAFFIC_MNG:
+ cnt_cb->type = DPA_STATS_CNT_TRAFFIC_MNG;
+
+ err = set_cnt_traffic_mng_cb(cnt_cb, params);
+ if (err != 0) {
+ log_err("Cannot crate Traffic Manager counter id %d\n",
+ cnt_cb->id);
+ goto create_counter_err;
+ }
+ break;
+ default:
+ log_err("Unsupported counter type %d for counter id %d\n",
+ params->type, cnt_cb->id);
+ mutex_unlock(&cnt_cb->lock);
+ return -EINVAL;
+ };
+
+ /* Counter was created. Return the counter id */
+ *dpa_stats_cnt_id = cnt_cb->id;
+
+ /* Unlock the counter control block structure */
+ mutex_unlock(&cnt_cb->lock);
+
+ return 0;
+
+create_counter_err:
+ /*
+ * An invalid Counter ID is returned if 'put_cnt' succeeds and the
+ * actual reserved Counter ID if it fails. The Counter ID can be used
+ * to try again to free resources by calling dpa_stats_remove_counter
+ */
+
+ *dpa_stats_cnt_id = cnt_cb->id;
+
+ err_rb = put_cnt(dpa_stats, cnt_cb);
+ if (!err_rb)
+ *dpa_stats_cnt_id = DPA_OFFLD_INVALID_OBJECT_ID;
+
+ /* Unlock the counter control block structure */
+ mutex_unlock(&cnt_cb->lock);
+
+ return err;
+}
+EXPORT_SYMBOL(dpa_stats_create_counter);
+
+int dpa_stats_create_class_counter(int dpa_stats_id,
+ const struct dpa_stats_cls_cnt_params *params,
+ int *dpa_stats_cnt_id)
+{
+ struct dpa_stats *dpa_stats = NULL;
+ struct dpa_stats_cnt_cb *cnt_cb = NULL;
+ int err = 0, err_rb = 0;
+
+ /* multiple DPA Stats instances are not currently supported */
+ unused(dpa_stats_id);
+
+ if (!gbl_dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return -EPERM;
+ }
+
+ if (!dpa_stats_cnt_id) {
+ log_err("Parameter dpa_stats_cnt_id cannot be NULL\n");
+ return -EINVAL;
+ }
+ *dpa_stats_cnt_id = DPA_OFFLD_INVALID_OBJECT_ID;
+
+ if (!params) {
+ log_err("Parameter params cannot be NULL\n");
+ return -EFAULT;
+ }
+
+ if (params->class_members > DPA_STATS_MAX_NUM_OF_CLASS_MEMBERS) {
+ log_err("Parameter class_members %d exceeds maximum number of class members: %d\n",
+ params->class_members,
+ DPA_STATS_MAX_NUM_OF_CLASS_MEMBERS);
+ return -EINVAL;
+ }
+
+ dpa_stats = gbl_dpa_stats;
+
+ err = get_new_cnt(dpa_stats, &cnt_cb);
+ if (err < 0) {
+ log_err("Cannot retrieve preallocated internal counter structure\n");
+ return err;
+ }
+
+ /* Acquire the lock for the counter control block */
+ mutex_lock(&cnt_cb->lock);
+
+ switch (params->type) {
+ case DPA_STATS_CNT_ETH:
+ cnt_cb->type = DPA_STATS_CNT_ETH;
+ cnt_cb->f_get_cnt_stats = get_cnt_eth_stats;
+
+ err = set_cls_cnt_eth_cb(cnt_cb, params);
+ if (err != 0) {
+ log_err("Cannot create Ethernet counter id %d\n",
+ cnt_cb->id);
+ goto create_counter_err;
+ }
+ break;
+ case DPA_STATS_CNT_REASS:
+ cnt_cb->type = DPA_STATS_CNT_REASS;
+ cnt_cb->f_get_cnt_stats = get_cnt_reass_stats;
+
+ err = set_cls_cnt_reass_cb(cnt_cb, params);
+ if (err != 0) {
+ log_err("Cannot create Reassembly counter id %d\n",
+ cnt_cb->id);
+ goto create_counter_err;
+ }
+ break;
+ case DPA_STATS_CNT_FRAG:
+ cnt_cb->type = DPA_STATS_CNT_FRAG;
+ cnt_cb->f_get_cnt_stats = get_cnt_frag_stats;
+
+ err = set_cls_cnt_frag_cb(cnt_cb, params);
+ if (err != 0) {
+ log_err("Cannot create Fragmentation counter id %d\n",
+ cnt_cb->id);
+ goto create_counter_err;
+ }
+ break;
+ case DPA_STATS_CNT_POLICER:
+ cnt_cb->type = DPA_STATS_CNT_POLICER;
+ cnt_cb->f_get_cnt_stats = get_cnt_plcr_stats;
+
+ err = set_cls_cnt_plcr_cb(cnt_cb, params);
+ if (err != 0) {
+ log_err("Cannot create Policer counter id %d\n",
+ cnt_cb->id);
+ goto create_counter_err;
+ }
+ break;
+ case DPA_STATS_CNT_CLASSIF_TBL:
+ cnt_cb->type = DPA_STATS_CNT_CLASSIF_TBL;
+ cnt_cb->f_get_cnt_stats = get_cnt_cls_tbl_match_stats;
+
+ err = set_cls_cnt_classif_tbl_cb(cnt_cb, params);
+ if (err != 0) {
+ log_err("Cannot create Classifier Table counter id %d\n",
+ cnt_cb->id);
+ goto create_counter_err;
+ }
+ break;
+ case DPA_STATS_CNT_CLASSIF_NODE:
+ cnt_cb->type = DPA_STATS_CNT_CLASSIF_NODE;
+
+ err = set_cls_cnt_ccnode_cb(cnt_cb, params);
+ if (err != 0) {
+ log_err("Cannot create Classification Cc Node counter id %d\n",
+ cnt_cb->id);
+ goto create_counter_err;
+ }
+ break;
+ case DPA_STATS_CNT_IPSEC:
+ cnt_cb->type = DPA_STATS_CNT_IPSEC;
+ cnt_cb->f_get_cnt_stats = get_cnt_ipsec_stats;
+
+ err = set_cls_cnt_ipsec_cb(cnt_cb, params);
+ if (err != 0) {
+ log_err("Cannot create IPSec counter id %d\n",
+ cnt_cb->id);
+ goto create_counter_err;
+ }
+ break;
+ case DPA_STATS_CNT_TRAFFIC_MNG:
+ cnt_cb->type = DPA_STATS_CNT_TRAFFIC_MNG;
+
+ err = set_cls_cnt_traffic_mng_cb(cnt_cb, params);
+ if (err != 0) {
+ log_err("Cannot create Traffic Manager counter id %d\n",
+ cnt_cb->id);
+ goto create_counter_err;
+ }
+ break;
+ default:
+ log_err("Unsupported counter type %d for counter id %d\n",
+ params->type, cnt_cb->id);
+ mutex_unlock(&cnt_cb->lock);
+ return -EINVAL;
+ };
+
+ /* Counter was created. Return the counter id */
+ *dpa_stats_cnt_id = cnt_cb->id;
+
+ /* Unlock the counter control block */
+ mutex_unlock(&cnt_cb->lock);
+
+ return 0;
+
+create_counter_err:
+ /*
+ * An invalid Counter ID is returned if 'put_cnt' succeeds and the
+ * actual reserved Counter ID if it fails. The Counter ID can be used
+ * to try again to free resources by calling dpa_stats_remove_counter
+ */
+ *dpa_stats_cnt_id = cnt_cb->id;
+
+ err_rb = put_cnt(dpa_stats, cnt_cb);
+ if (!err_rb)
+ *dpa_stats_cnt_id = DPA_OFFLD_INVALID_OBJECT_ID;
+
+ /* Unlock the counter control block */
+ mutex_unlock(&cnt_cb->lock);
+
+ return err;
+}
+EXPORT_SYMBOL(dpa_stats_create_class_counter);
+
+int dpa_stats_modify_class_counter(int dpa_stats_cnt_id,
+ const struct dpa_stats_cls_member_params *params,
+ int member_index)
+{
+ struct dpa_stats *dpa_stats = NULL;
+ struct dpa_stats_cnt_cb *cnt_cb = NULL;
+ int err = 0;
+
+ if (!gbl_dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return -EPERM;
+ }
+
+ dpa_stats = gbl_dpa_stats;
+
+ if (dpa_stats_cnt_id < 0 ||
+ dpa_stats_cnt_id > dpa_stats->config.max_counters) {
+ log_err("Parameter dpa_stats_cnt_id %d must be in range (0 - %d)\n",
+ dpa_stats_cnt_id, dpa_stats->config.max_counters - 1);
+ return -EINVAL;
+ }
+
+ if (!params) {
+ log_err("Parameter params cannot be NULL\n");
+ return -EFAULT;
+ }
+
+ /* Counter scheduled for the retrieve mechanism can't be modified */
+ if (cnt_is_sched(dpa_stats, dpa_stats_cnt_id)) {
+ log_err("Counter id %d is in use\n", dpa_stats_cnt_id);
+ return -EBUSY;
+ }
+
+ /* Get counter control block */
+ cnt_cb = &dpa_stats->cnts_cb[dpa_stats_cnt_id];
+
+ /* Acquire counter control block lock */
+ err = mutex_trylock(&cnt_cb->lock);
+ if (err == 0)
+ return -EAGAIN;
+
+ /* Validity check for this counter */
+ if (cnt_cb->index == DPA_OFFLD_INVALID_OBJECT_ID) {
+ log_err("Counter id %d is not initialized\n", dpa_stats_cnt_id);
+ mutex_unlock(&cnt_cb->lock);
+ return -EINVAL;
+ }
+
+ if (params->type == DPA_STATS_CLS_MEMBER_SINGLE_KEY ||
+ params->type == DPA_STATS_CLS_MEMBER_PAIR_KEY) {
+ /* Modify classifier table class member */
+ err = set_classif_tbl_member(params, member_index, cnt_cb);
+ if (err < 0) {
+ log_err("Cannot modify member %d of counter id %d\n",
+ member_index, dpa_stats_cnt_id);
+ mutex_unlock(&cnt_cb->lock);
+ return -EINVAL;
+ }
+
+ } else if (params->type == DPA_STATS_CLS_MEMBER_SA_ID) {
+ /* Modify IPSec class member */
+ err = set_ipsec_member(params, member_index, cnt_cb);
+ if (err < 0) {
+ log_err("Cannot modify member %d of counter id %d\n",
+ member_index, dpa_stats_cnt_id);
+ mutex_unlock(&cnt_cb->lock);
+ return -EINVAL;
+ }
+ } else {
+ log_err("Parameter type %d for counter id %d must be in range (%d - %d)\n",
+ params->type, dpa_stats_cnt_id,
+ DPA_STATS_CLS_MEMBER_SINGLE_KEY,
+ DPA_STATS_CLS_MEMBER_SA_ID);
+ mutex_unlock(&cnt_cb->lock);
+ return -EINVAL;
+ }
+
+ /* Unlock the counter control block */
+ mutex_unlock(&cnt_cb->lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(dpa_stats_modify_class_counter);
+
+int dpa_stats_remove_counter(int dpa_stats_cnt_id)
+{
+ struct dpa_stats *dpa_stats = NULL;
+ struct dpa_stats_cnt_cb *cnt_cb = NULL;
+ int err = 0;
+ uint32_t i;
+
+ if (!gbl_dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return -EPERM;
+ }
+
+ dpa_stats = gbl_dpa_stats;
+
+ if (dpa_stats_cnt_id < 0 ||
+ dpa_stats_cnt_id > dpa_stats->config.max_counters) {
+ log_err("Parameter dpa_stats_cnt_id %d must be in range (0 - %d)\n",
+ dpa_stats_cnt_id, dpa_stats->config.max_counters - 1);
+ return -EINVAL;
+ }
+
+ /* Counter scheduled for the retrieve mechanism can't be removed */
+ if (cnt_is_sched(dpa_stats, dpa_stats_cnt_id)) {
+ log_err("Counter id %d is in use\n", dpa_stats_cnt_id);
+ return -EBUSY;
+ }
+
+ /* Get counter control block */
+ cnt_cb = &dpa_stats->cnts_cb[dpa_stats_cnt_id];
+
+ /* Acquire counter control block lock */
+ err = mutex_trylock(&cnt_cb->lock);
+ if (err == 0)
+ return -EAGAIN;
+
+ /* Validity check for this counter */
+ if (cnt_cb->index == DPA_OFFLD_INVALID_OBJECT_ID) {
+ log_err("Counter id %d is not initialized\n", dpa_stats_cnt_id);
+ mutex_unlock(&cnt_cb->lock);
+ return -EINVAL;
+ }
+
+ switch (cnt_cb->type) {
+ case DPA_STATS_CNT_ETH:
+ case DPA_STATS_CNT_REASS:
+ case DPA_STATS_CNT_FRAG:
+ case DPA_STATS_CNT_POLICER:
+ case DPA_STATS_CNT_TRAFFIC_MNG:
+ kfree(cnt_cb->gen_cb.objs);
+ break;
+ case DPA_STATS_CNT_CLASSIF_NODE:
+ /* Remove the allocated memory for keys bytes and masks */
+ for (i = 0; i < cnt_cb->members_num; i++) {
+ kfree(cnt_cb->ccnode_cb.keys[i].data.byte);
+ kfree(cnt_cb->ccnode_cb.keys[i].data.mask);
+ }
+ kfree(cnt_cb->ccnode_cb.keys);
+ break;
+ case DPA_STATS_CNT_CLASSIF_TBL:
+ /* Remove the allocated memory for keys bytes, masks and keys */
+ for (i = 0; i < cnt_cb->members_num; i++) {
+ kfree(cnt_cb->tbl_cb.keys[i].key.data.byte);
+ kfree(cnt_cb->tbl_cb.keys[i].key.data.mask);
+ }
+ kfree(cnt_cb->tbl_cb.keys);
+ break;
+ case DPA_STATS_CNT_IPSEC:
+ /* Remove the allocated memory for security associations */
+ kfree(cnt_cb->ipsec_cb.sa_id);
+ kfree(cnt_cb->ipsec_cb.valid);
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * In case of user space counters, the [stats] and [last_stats] members
+ * may not be initialized.
+ */
+ if (cnt_cb->info.stats) {
+ kfree(cnt_cb->info.last_stats);
+ kfree(cnt_cb->info.stats);
+ cnt_cb->info.stats = NULL;
+ cnt_cb->info.last_stats = NULL;
+ }
+ kfree(cnt_cb->info.stats_off);
+
+ /* Release the counter id in the Counter IDs circular queue */
+ err = put_cnt(dpa_stats, cnt_cb);
+ if (err < 0) {
+ log_err("Cannot release preallocated internal structure\n");
+ mutex_unlock(&cnt_cb->lock);
+ return -EINVAL;
+ }
+
+ /* Release counter lock */
+ mutex_unlock(&cnt_cb->lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(dpa_stats_remove_counter);
+
+int dpa_stats_get_counters(struct dpa_stats_cnt_request_params params,
+ int *cnts_len,
+ dpa_stats_request_cb request_done)
+{
+ struct dpa_stats *dpa_stats = NULL;
+ struct dpa_stats_req_cb *req_cb = NULL;
+ struct dpa_stats_cnt_cb *cnt_cb = NULL;
+ int err = 0, cnt_id = 0, req_id = 0;
+ uint32_t i = 0;
+
+ if (!gbl_dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return -EPERM;
+ }
+
+ /* Check user-provided cnts_len pointer */
+ if (!cnts_len) {
+ log_err("Parameter cnts_len cannot be NULL\n");
+ return -EINVAL;
+ }
+
+ /* Check user-provided params.cnts_ids pointer */
+ if (!params.cnts_ids) {
+ log_err("Parameter cnts_ids cannot be NULL\n");
+ return -EINVAL;
+ }
+
+ dpa_stats = gbl_dpa_stats;
+
+ *cnts_len = 0;
+
+ for (i = 0; i < params.cnts_ids_len; i++) {
+ if (params.cnts_ids[i] == DPA_OFFLD_INVALID_OBJECT_ID ||
+ params.cnts_ids[i] > dpa_stats->config.max_counters) {
+ log_err("Counter id (cnt_ids[%d]) %d is not initialized or is greater than maximum counters %d\n",
+ i, params.cnts_ids[i],
+ dpa_stats->config.max_counters);
+ return -EINVAL;
+ }
+ }
+
+ block_sched_cnts(dpa_stats, params.cnts_ids, params.cnts_ids_len);
+
+ /* Calculate number of bytes occupied by the counters */
+ for (i = 0; i < params.cnts_ids_len; i++) {
+ cnt_id = params.cnts_ids[i];
+
+ /* Get counter's control block */
+ cnt_cb = &dpa_stats->cnts_cb[cnt_id];
+
+ /* Acquire counter lock */
+ mutex_lock(&cnt_cb->lock);
+
+ /* Check if counter control block is initialized */
+ if (cnt_cb->index == DPA_OFFLD_INVALID_OBJECT_ID) {
+ log_err("Counter id (cnt_ids[%d]) %d is not initialized\n",
+ i, cnt_id);
+ mutex_unlock(&cnt_cb->lock);
+ unblock_sched_cnts(dpa_stats, params.cnts_ids,
+ params.cnts_ids_len);
+ return -EINVAL;
+ }
+
+ *cnts_len += cnt_cb->bytes_num;
+ mutex_unlock(&cnt_cb->lock);
+ }
+
+ /* Check user-provided parameters */
+ if ((params.storage_area_offset + *cnts_len) >
+ dpa_stats->config.storage_area_len) {
+ log_err("Parameter storage_area_offset %d and counters length %d exceeds configured storage_area_len %d\n",
+ params.storage_area_offset, *cnts_len,
+ dpa_stats->config.storage_area_len);
+ unblock_sched_cnts(dpa_stats, params.cnts_ids,
+ params.cnts_ids_len);
+ return -EINVAL;
+ }
+
+ /* Create a new request */
+ err = get_new_req(dpa_stats, &req_id, &req_cb);
+ if (err < 0) {
+ log_err("Cannot retrieve preallocated internal request structure\n");
+ /* Release counters locks */
+ unblock_sched_cnts(dpa_stats, params.cnts_ids,
+ params.cnts_ids_len);
+ return err;
+ }
+
+ req_cb->config.cnts_ids = params.cnts_ids;
+ req_cb->config.reset_cnts = params.reset_cnts;
+ req_cb->config.storage_area_offset = params.storage_area_offset;
+ req_cb->config.cnts_ids_len = params.cnts_ids_len;
+ req_cb->request_done = request_done;
+
+ /* Copy user-provided array of counter ids */
+ memcpy(req_cb->cnts_ids,
+ params.cnts_ids, params.cnts_ids_len * sizeof(int));
+
+ /* Set memory area where the request should write */
+ req_cb->request_area = dpa_stats->config.storage_area +
+ params.storage_area_offset;
+
+ if (!req_cb->request_done) {
+ /* Call is synchronous */
+ err = treat_cnts_request(dpa_stats, req_cb);
+ if (err < 0)
+ log_err("Cannot retrieve counter values\n");
+
+ err = put_req(dpa_stats, req_cb);
+
+ return err;
+ } else {
+ /* Call is asynchronous */
+ queue_work(dpa_stats->async_req_workqueue,
+ &req_cb->async_req_work);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(dpa_stats_get_counters);
+
+int dpa_stats_reset_counters(int *cnts_ids, unsigned int cnts_ids_len)
+{
+ struct dpa_stats *dpa_stats = NULL;
+ struct dpa_stats_cnt_cb *cnt_cb = NULL;
+ uint32_t i = 0;
+ int err = 0;
+
+ if (!gbl_dpa_stats) {
+ log_err("DPA Stats component is not initialized\n");
+ return -EPERM;
+ }
+
+ /* Check user-provided cnts_len pointer */
+ if (cnts_ids_len == 0) {
+ log_err("Parameter cnts_ids_len cannot be 0\n");
+ return -EINVAL;
+ }
+
+ /* Check user-provided cnts_ids pointer */
+ if (!cnts_ids) {
+ log_err("Parameter cnts_ids cannot be NULL\n");
+ return -EINVAL;
+ }
+
+ dpa_stats = gbl_dpa_stats;
+
+ for (i = 0; i < cnts_ids_len; i++)
+ if (cnts_ids[i] == DPA_OFFLD_INVALID_OBJECT_ID ||
+ cnts_ids[i] > dpa_stats->config.max_counters) {
+ log_err("Counter id (cnts_ids[%d]) %d is not initialized or is greater than maximum counters %d\n",
+ i, cnts_ids[i],
+ dpa_stats->config.max_counters - 1);
+ return -EINVAL;
+ }
+
+ block_sched_cnts(dpa_stats, cnts_ids, cnts_ids_len);
+
+ /* Calculate number of bytes occupied by the counters */
+ for (i = 0; i < cnts_ids_len; i++) {
+ /* Get counter's control block */
+ cnt_cb = &dpa_stats->cnts_cb[cnts_ids[i]];
+
+ /* Acquire counter lock */
+ err = mutex_trylock(&cnt_cb->lock);
+ if (err == 0) {
+ log_err("Counter id (cnt_ids[%d]) %d is in use\n", i,
+ cnts_ids[i]);
+ unblock_sched_cnts(dpa_stats,
+ cnts_ids, cnts_ids_len);
+ return -EBUSY;
+ }
+
+ /* Check if counter control block is initialized */
+ if (cnt_cb->index == DPA_OFFLD_INVALID_OBJECT_ID) {
+ log_err("Counter id (cnt_ids[%d]) %d is not initialized\n",
+ i, cnts_ids[i]);
+ mutex_unlock(&cnt_cb->lock);
+ unblock_sched_cnts(dpa_stats,
+ cnts_ids, cnts_ids_len);
+ return -EINVAL;
+ }
+
+ /* User space counters make no sense in being reset. */
+ if (cnt_cb->info.stats) {
+ /* Reset stored statistics values */
+ memset(cnt_cb->info.stats, 0,
+ (cnt_cb->members_num * cnt_cb->info.stats_num) *
+ sizeof(uint64_t));
+ }
+
+ mutex_unlock(&cnt_cb->lock);
+ }
+
+ unblock_sched_cnts(dpa_stats, cnts_ids, cnts_ids_len);
+
+ return 0;
+}
+EXPORT_SYMBOL(dpa_stats_reset_counters);
+
+int dpa_stats_free(int dpa_stats_id)
+{
+ /* multiple DPA Stats instances are not currently supported */
+ unused(dpa_stats_id);
+
+ return free_resources();
+}
+EXPORT_SYMBOL(dpa_stats_free);
diff --git a/drivers/staging/fsl_dpa_offload/dpa_stats.h b/drivers/staging/fsl_dpa_offload/dpa_stats.h
new file mode 100644
index 0000000..6099712
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dpa_stats.h
@@ -0,0 +1,214 @@
+
+/* Copyright 2008-2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Internal DPA Statistics Application Programming Interface
+ */
+
+#ifndef __DPA_STATS_H
+#define __DPA_STATS_H
+
+/* DPA offloading layer includes */
+#include "linux/fsl_dpa_stats.h"
+#include "linux/fsl_dpa_ipsec.h"
+#include "cq.h"
+
+#define MAX_NUM_OF_STATS 23
+#define NUM_OF_CNT_TYPES (DPA_STATS_CNT_TRAFFIC_MNG + 1)
+#define MAX_NUM_OF_MEMBERS DPA_STATS_MAX_NUM_OF_CLASS_MEMBERS
+
+
+/* DPA Stats - Control Block */
+struct dpa_stats {
+ struct dpa_stats_params config; /* Configuration parameters */
+ struct cq *cnt_id_cq; /* Circular Queue with ids for stats counters */
+ int *used_cnt_ids; /* Counter ids used by this dpa_stats instance*/
+ struct dpa_stats_cnt_cb *cnts_cb; /* Array of counters control blocks */
+
+ int *used_req_ids; /* Request ids used by this dpa_stats instance*/
+ struct dpa_stats_req_cb *reqs_cb; /* Array of counter requests */
+ struct cq *req_id_cq; /* Circular Queue with ids for counters request */
+ /*
+ * Array that stores the mapping
+ * between counter selection and statistics values
+ */
+ int stats_sel[NUM_OF_CNT_TYPES][MAX_NUM_OF_STATS];
+ /*
+ * Multi threaded work queue used to defer the work to be
+ * done when an asynchronous counters request is received
+ */
+ struct workqueue_struct *async_req_workqueue;
+ struct mutex lock; /* Lock for this dpa_stats instance */
+ bool *sched_cnt_ids; /* Counters scheduled for a retrieve operation */
+ struct mutex sched_cnt_lock; /* Lock for array of scheduled counters */
+};
+
+/* DPA Stats request control block */
+struct dpa_stats_req_cb {
+ struct work_struct async_req_work; /* Asynchronous request work */
+ struct dpa_stats_cnt_request_params config;
+ /* Parameters provided to the request */
+ int *cnts_ids; /* Copy of user-provided array of counter IDs */
+ uint32_t id; /* Request id */
+ int index; /* Request index in the 'used_req_ids'*/
+ void *request_area;
+ /* Address in the storage area associated with this request */
+ uint32_t bytes_num; /* Number of bytes written by this request */
+ uint32_t cnts_num; /* Number of counters written by this request */
+ dpa_stats_request_cb request_done; /* Callback to notify upper layer */
+};
+
+/* DPA Stats - statistics information */
+struct stats_info {
+ /*
+ * Array of statistics offsets relative to
+ * corresponding statistics area
+ */
+ int *stats_off;
+ unsigned int stats_num; /* Number of statistics to retrieve */
+ uint64_t *stats; /* Array to store statistics values */
+ uint64_t *last_stats; /* Array to store previous statistics values */
+ bool reset; /* Reset counter's statistics */
+};
+
+/* DPA Stats General Counter control block */
+struct dpa_stats_cnt_gen_cb {
+ /* Array of objects for which to retrieve statistics */
+ void **objs;
+};
+
+/*
+ * DPA Stats allocated lookup key descriptor. This is used in the context of
+ * lookup keys being preallocated for the classification type counters. In this
+ * case, the pointers to key data or key mask will always exist, hence there
+ * is no more way to tell whether the key data or mask are valid except by using
+ * a set of individual indicators like "valid_mask" and "valid_key".
+ */
+struct dpa_stats_allocated_lookup_key {
+ /* The key data (preallocated key & mask). */
+ struct dpa_offload_lookup_key data;
+
+ /* Indicates whether the mask is present or not. */
+ bool valid_mask;
+
+ /* Indicates whether the key data is present or not. */
+ bool valid_key;
+};
+
+/* DPA Stats Classifier Table key descriptor */
+struct dpa_stats_lookup_key {
+ void *cc_node; /* Handle of Cc Node the lookup key belongs to */
+ struct dpa_stats_allocated_lookup_key key; /* Key descriptor */
+ bool valid; /* Lookup key is valid */
+ void *frag; /* Fragmentation handle corresponding to this key */
+ bool miss_key; /* Provide statistics for miss entry */
+};
+
+/* DPA Stats Classif Table control block */
+struct dpa_stats_cnt_classif_tbl_cb {
+ int td; /* Table descriptor */
+ enum dpa_cls_tbl_type type; /* The type of the DPA Classifier table */
+ struct dpa_stats_lookup_key *keys; /* Array of
+ key descriptors for which to provide statistics */
+};
+
+/* DPA Stats Classif Node control block */
+struct dpa_stats_cnt_classif_cb {
+ void *cc_node; /* Handle of Cc Node the lookup keys belong to */
+ struct dpa_stats_allocated_lookup_key *keys;
+ /* Array of key descriptors for which to provide statistics */
+};
+
+/* DPA Stats IPSec Counter control block */
+struct dpa_stats_cnt_ipsec_cb {
+ int *sa_id; /* Array of Security Association ids */
+ bool *valid; /* Security Association id is valid */
+};
+
+typedef int get_cnt_stats(struct dpa_stats_req_cb *req_cb,
+ struct dpa_stats_cnt_cb *cnt_cb);
+
+/* DPA Stats counter control block */
+struct dpa_stats_cnt_cb {
+ struct dpa_stats *dpa_stats; /* Pointer to DPA Stats */
+ uint32_t id; /* Counter identifier */
+ int index; /* Counter index in the 'used_cnt_ids'*/
+ uint32_t bytes_num; /* Number of bytes occupied by this counter */
+ struct mutex lock; /* Lock for this counter control block */
+ bool used; /* Counter has been scheduled for retrieve */
+ enum dpa_stats_cnt_type type; /* Counter type */
+ struct stats_info info; /* Counter's statistics information */
+ unsigned int members_num; /* Number of objects to retrieve statistics */
+ union {
+ struct dpa_stats_cnt_gen_cb gen_cb;
+ struct dpa_stats_cnt_classif_tbl_cb tbl_cb;
+ struct dpa_stats_cnt_classif_cb ccnode_cb;
+ struct dpa_stats_cnt_ipsec_cb ipsec_cb;
+ };
+ /* Function used to retrieve the statistics for a specific counter */
+ get_cnt_stats *f_get_cnt_stats;
+};
+
+static inline void block_sched_cnts(struct dpa_stats *dpa_stats,
+ int *cnts_ids, int cnts_ids_len)
+{
+ int i;
+
+ mutex_lock(&dpa_stats->sched_cnt_lock);
+ for (i = 0; i < cnts_ids_len; i++)
+ dpa_stats->sched_cnt_ids[cnts_ids[i]] = TRUE;
+ mutex_unlock(&dpa_stats->sched_cnt_lock);
+}
+
+static inline void unblock_sched_cnts(struct dpa_stats *dpa_stats,
+ int *cnts_ids, int cnts_ids_len)
+{
+ int i;
+
+ mutex_lock(&dpa_stats->sched_cnt_lock);
+ for (i = 0; i < cnts_ids_len; i++)
+ dpa_stats->sched_cnt_ids[cnts_ids[i]] = FALSE;
+ mutex_unlock(&dpa_stats->sched_cnt_lock);
+}
+
+static inline int cnt_is_sched(struct dpa_stats *dpa_stats, int cnt_id)
+{
+ int ret = 0;
+
+ mutex_lock(&dpa_stats->sched_cnt_lock);
+ ret = dpa_stats->sched_cnt_ids[cnt_id];
+ mutex_unlock(&dpa_stats->sched_cnt_lock);
+
+ return ret;
+}
+
+#endif /* __DPA_STATS_H */
diff --git a/drivers/staging/fsl_dpa_offload/dpa_stats_ioctl.h b/drivers/staging/fsl_dpa_offload/dpa_stats_ioctl.h
new file mode 100644
index 0000000..a1bd323
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dpa_stats_ioctl.h
@@ -0,0 +1,312 @@
+
+/* Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * DPA Stats Wrapper Application Programming Interface
+ */
+
+#ifndef __DPA_STATS_IOCTL_H
+#define __DPA_STATS_IOCTL_H
+
+/* Other includes */
+#include "linux/ioctl.h"
+#include <linux/compat.h>
+
+struct ioc_dpa_stats_params {
+ unsigned int max_counters;
+ void *virt_stg_area;
+ uint64_t phys_stg_area;
+ bool stg_area_mapped;
+ unsigned int storage_area_len;
+ int dpa_stats_id;
+};
+
+struct ioc_dpa_stats_cnt_params {
+ int stats_id;
+ struct dpa_stats_cnt_params cnt_params;
+ int cnt_id;
+};
+
+struct ioc_dpa_stats_cls_cnt_params {
+ int stats_id;
+ struct dpa_stats_cls_cnt_params cnt_params;
+ int cnt_id;
+};
+
+struct ioc_dpa_stats_cls_member_params {
+ int cnt_id;
+ struct dpa_stats_cls_member_params params;
+ int member_index;
+};
+
+struct ioc_dpa_stats_cnt_request_params {
+ struct dpa_stats_cnt_request_params req_params;
+ int cnts_len;
+ dpa_stats_request_cb request_done;
+};
+
+struct ioc_dpa_stats_cnts_reset_params {
+ int *cnts_ids;
+ unsigned int cnts_ids_len;
+};
+
+#ifdef CONFIG_COMPAT
+struct dpa_stats_compat_params {
+ unsigned int max_counters;
+ compat_uptr_t virt_stg_area;
+ uint64_t phys_stg_area;
+ bool stg_area_mapped;
+ unsigned int storage_area_len;
+};
+
+struct compat_ioc_dpa_stats_params {
+ struct dpa_stats_compat_params stats_params;
+ int dpa_stats_id;
+};
+
+struct dpa_stats_compat_cnt_reass {
+ compat_uptr_t reass;
+ unsigned int cnt_sel;
+};
+
+struct dpa_stats_compat_cnt_frag {
+ compat_uptr_t frag;
+ unsigned int cnt_sel;
+};
+
+struct dpa_stats_compat_cnt_plcr {
+ compat_uptr_t plcr;
+ unsigned int cnt_sel;
+};
+
+struct compat_ioc_dpa_offld_lookup_key {
+ compat_uptr_t byte;
+ compat_uptr_t mask;
+ uint8_t size;
+};
+
+struct dpa_stats_compat_cnt_classif_tbl {
+ int td;
+ compat_uptr_t key;
+ unsigned int cnt_sel;
+};
+
+struct dpa_stats_compat_cnt_classif_node {
+ compat_uptr_t cc_node;
+ enum dpa_stats_classif_node_type ccnode_type;
+ compat_uptr_t key;
+ unsigned int cnt_sel;
+};
+
+struct dpa_stats_compat_cnt_traffic_mng {
+ enum dpa_stats_cnt_traffic_mng_src src;
+ compat_uptr_t traffic_mng;
+ enum dpa_stats_cnt_sel cnt_sel;
+};
+
+struct dpa_stats_compat_cnt_params {
+ enum dpa_stats_cnt_type type;
+ union {
+ struct dpa_stats_cnt_eth eth_params;
+ struct dpa_stats_compat_cnt_reass reass_params;
+ struct dpa_stats_compat_cnt_frag frag_params;
+ struct dpa_stats_compat_cnt_plcr plcr_params;
+ struct dpa_stats_compat_cnt_classif_tbl classif_tbl_params;
+ struct dpa_stats_compat_cnt_classif_node classif_node_params;
+ struct dpa_stats_cnt_ipsec ipsec_params;
+ struct dpa_stats_compat_cnt_traffic_mng traffic_mng_params;
+ };
+};
+
+struct compat_ioc_dpa_stats_cnt_params {
+ int stats_id;
+ struct dpa_stats_compat_cnt_params cnt_params;
+ int cnt_id;
+};
+
+struct dpa_stats_compat_cls_cnt_eth {
+ compat_uptr_t src;
+ enum dpa_stats_cnt_eth_sel cnt_sel;
+};
+
+struct dpa_stats_compat_cls_cnt_classif_tbl {
+ int td;
+ enum dpa_stats_classif_key_type key_type;
+ union {
+ compat_uptr_t keys;
+ compat_uptr_t pairs;
+ };
+ unsigned int cnt_sel;
+};
+
+struct dpa_stats_compat_cls_cnt_classif_node {
+ compat_uptr_t cc_node;
+ enum dpa_stats_classif_node_type ccnode_type;
+ compat_uptr_t keys;
+ unsigned int cnt_sel;
+};
+
+struct dpa_stats_compat_cls_cnt_ipsec {
+ compat_uptr_t sa_id;
+ enum dpa_stats_cnt_sel cnt_sel;
+};
+
+struct dpa_stats_compat_cls_cnt_params {
+ unsigned int class_members;
+ enum dpa_stats_cnt_type type;
+ union {
+ struct dpa_stats_compat_cls_cnt_eth eth_params;
+ struct dpa_stats_compat_cnt_reass reass_params;
+ struct dpa_stats_compat_cnt_frag frag_params;
+ struct dpa_stats_compat_cnt_plcr plcr_params;
+ struct dpa_stats_compat_cls_cnt_classif_tbl classif_tbl_params;
+ struct dpa_stats_compat_cls_cnt_classif_node ccnode_params;
+ struct dpa_stats_compat_cls_cnt_ipsec ipsec_params;
+ struct dpa_stats_compat_cnt_traffic_mng traffic_mng_params;
+ };
+};
+
+struct compat_ioc_dpa_stats_cls_cnt_params {
+ int stats_id;
+ struct dpa_stats_compat_cls_cnt_params cnt_params;
+ int cnt_id;
+};
+
+struct compat_ioc_dpa_offld_lookup_key_pair {
+ compat_uptr_t first_key;
+ compat_uptr_t second_key;
+};
+
+struct dpa_stats_compat_cls_member_params {
+ enum dpa_stats_cls_member_type type;
+ union {
+ compat_uptr_t key;
+ compat_uptr_t pair;
+ int sa_id;
+ };
+};
+
+struct compat_ioc_dpa_stats_cls_member_params {
+ int cnt_id;
+ struct dpa_stats_compat_cls_member_params params;
+ int member_index;
+};
+
+struct dpa_stats_compat_cnt_request_params {
+ compat_uptr_t cnts_ids;
+ unsigned int cnts_ids_len;
+ bool reset_cnts;
+ unsigned int storage_area_offset;
+};
+
+struct compat_ioc_dpa_stats_cnt_request_params {
+ struct dpa_stats_compat_cnt_request_params req_params;
+ int cnts_len;
+ compat_uptr_t request_done;
+};
+
+struct compat_ioc_dpa_stats_cnts_reset_params {
+ compat_uptr_t cnts_ids;
+ unsigned int cnts_ids_len;
+};
+
+struct compat_dpa_stats_event_params {
+ int dpa_stats_id;
+ unsigned int storage_area_offset;
+ unsigned int cnts_written;
+ int bytes_written;
+ compat_uptr_t us_cnt_ids;
+ unsigned int cnt_ids_len;
+ compat_uptr_t request_done;
+};
+#endif
+#define DPA_STATS_IOC_MAGIC 0xde
+
+#define DPA_STATS_IOC_INIT \
+ _IOWR(DPA_STATS_IOC_MAGIC, 0, struct ioc_dpa_stats_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_STATS_IOC_COMPAT_INIT \
+ _IOWR(DPA_STATS_IOC_MAGIC, 0, struct compat_ioc_dpa_stats_params)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_STATS_IOC_FREE \
+ _IOW(DPA_STATS_IOC_MAGIC, 1, int)
+
+#define DPA_STATS_IOC_CREATE_COUNTER \
+ _IOWR(DPA_STATS_IOC_MAGIC, 2, struct ioc_dpa_stats_cnt_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_STATS_IOC_COMPAT_CREATE_COUNTER \
+ _IOWR(DPA_STATS_IOC_MAGIC, 2, struct compat_ioc_dpa_stats_cnt_params)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_STATS_IOC_CREATE_CLASS_COUNTER \
+ _IOWR(DPA_STATS_IOC_MAGIC, 3, struct ioc_dpa_stats_cls_cnt_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_STATS_IOC_COMPAT_CREATE_CLASS_COUNTER \
+ _IOWR(DPA_STATS_IOC_MAGIC, 3, \
+ struct compat_ioc_dpa_stats_cls_cnt_params)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_STATS_IOC_MODIFY_CLASS_COUNTER \
+ _IOWR(DPA_STATS_IOC_MAGIC, 4, struct ioc_dpa_stats_cls_member_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_STATS_IOC_COMPAT_MODIFY_CLASS_COUNTER \
+ _IOWR(DPA_STATS_IOC_MAGIC, 4, \
+ struct compat_ioc_dpa_stats_cls_member_params)
+#endif /* CONFIG_COMPAT */
+
+#define DPA_STATS_IOC_REMOVE_COUNTER \
+ _IOW(DPA_STATS_IOC_MAGIC, 5, int)
+
+#define DPA_STATS_IOC_GET_COUNTERS \
+ _IOWR(DPA_STATS_IOC_MAGIC, 6, struct ioc_dpa_stats_cnt_request_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_STATS_IOC_COMPAT_GET_COUNTERS \
+ _IOWR(DPA_STATS_IOC_MAGIC, 6, \
+ struct compat_ioc_dpa_stats_cnt_request_params)
+#endif
+
+#define DPA_STATS_IOC_RESET_COUNTERS \
+ _IOWR(DPA_STATS_IOC_MAGIC, 7, struct ioc_dpa_stats_cnts_reset_params)
+
+#ifdef CONFIG_COMPAT
+#define DPA_STATS_IOC_COMPAT_RESET_COUNTERS \
+ _IOWR(DPA_STATS_IOC_MAGIC, 7, \
+ struct compat_ioc_dpa_stats_cnts_reset_params)
+#endif
+
+#endif /* __DPA_STATS_IOCTL_H */
diff --git a/drivers/staging/fsl_dpa_offload/dts/b4420qds-usdpaa-shared-interfaces.dts b/drivers/staging/fsl_dpa_offload/dts/b4420qds-usdpaa-shared-interfaces.dts
new file mode 100644
index 0000000..b2184a1
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/b4420qds-usdpaa-shared-interfaces.dts
@@ -0,0 +1,160 @@
+/*
+ * B4420QDS Device Tree Source
+ *
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "b4420qds.dts"
+
+/ {
+ /* NB: "bpool-ethernet-seeds" is not set to avoid buffer seeding,
+ * because apps seed these pools with buffers allocated at
+ * run-time.
+ * HOWEVER, the kernel driver requires the buffer-size so
+ * "fsl,bpool-ethernet-cfg" is set. It also mis-interprets
+ * things if the base-address is zero (hence the 0xdeadbeef
+ * values).
+ */
+ bp7: buffer-pool@7 {
+ compatible = "fsl,b4420-bpool", "fsl,bpool";
+ fsl,bpid = <7>;
+ fsl,bpool-ethernet-cfg = <0 0 0 192 0 0xdeadbeef>;
+ fsl,bpool-thresholds = <0x400 0xc00 0x0 0x0>;
+ };
+ bp8: buffer-pool@8 {
+ compatible = "fsl,b4420-bpool", "fsl,bpool";
+ fsl,bpid = <8>;
+ fsl,bpool-ethernet-cfg = <0 0 0 576 0 0xabbaf00d>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp9: buffer-pool@9 {
+ compatible = "fsl,b4420-bpool", "fsl,bpool";
+ fsl,bpid = <9>;
+ fsl,bpool-ethernet-cfg = <0 0 0 1728 0 0xfeedabba>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ bp10: buffer-pool@10 {
+ compatible = "fsl,b4420-bpool", "fsl,bpool";
+ fsl,bpid = <10>;
+ fsl,bpool-thresholds = <0x10 0x30 0x0 0x0>;
+ };
+ bp11: buffer-pool@11 {
+ compatible = "fsl,b4420-bpool", "fsl,bpool";
+ fsl,bpid = <11>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp12: buffer-pool@12 {
+ compatible = "fsl,b4420-bpool", "fsl,bpool";
+ fsl,bpid = <12>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp16: buffer-pool@16 {
+ compatible = "fsl,b4420-bpool", "fsl,bpool";
+ fsl,bpid = <16>;
+ fsl,bpool-ethernet-cfg = <0 2048 0 1728 0 0>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ fsl,dpaa {
+ ethernet@0 {
+ compatible = "fsl,b4420-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x50 1 0x51 1>;
+ fsl,qman-frame-queues-tx = <0x70 1 0x71 1>;
+ };
+ ethernet@1 {
+ compatible = "fsl,b4420-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x52 1 0x53 1>;
+ fsl,qman-frame-queues-tx = <0x72 1 0x73 1>;
+ };
+ ethernet@2 {
+ compatible = "fsl,b4420-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x54 1 0x55 1>;
+ fsl,qman-frame-queues-tx = <0x74 1 0x75 1>;
+ };
+ ethernet@3 {
+ compatible = "fsl,b4420-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x5c 1 0x5d 1>;
+ fsl,qman-frame-queues-tx = <0x7c 1 0x7d 1>;
+ };
+
+ /* ethernet@16 declared as MAC-less interface with no "fsl,fman-mac" property.
+ * USDPAA will seed buffers to this buffer pool and initialize 8 TX Frame
+ * queues. The ethernet driver will initialize 8 RX default Frame queues.
+ * On receiving frame at this interface, the ethernet driver will do
+ * kmap_atomic/kunmap_atomic for that frame. */
+ ethernet@16 {
+ compatible = "fsl,b4420-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <4000 8>;
+ fsl,qman-frame-queues-tx = <4008 8>;
+ local-mac-address = [00 11 22 33 44 55];
+ };
+ ethernet@17 {
+ compatible = "fsl,b4420-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <5000 8>;
+ fsl,qman-frame-queues-tx = <5008 8>;
+ local-mac-address = [00 11 22 33 44 66];
+ };
+ ethernet@18 {
+ compatible = "fsl,b4420-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <6000 8>;
+ fsl,qman-frame-queues-tx = <6008 8>;
+ local-mac-address = [00 11 22 33 44 77];
+ };
+ dpa-fman0-oh@2 {
+ compatible = "fsl,dpa-oh";
+ /* Define frame queues for the OH port*/
+ /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x6e 1 0x6f 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh2>;
+ };
+ dpa_fman0_oh3: dpa-fman0-oh@3 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x68 1 0x69 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh3>;
+ };
+ dpa_fman0_oh4: dpa-fman0-oh@4 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x70 1 0x71 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh4>;
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/b4420qds-usdpaa.dts b/drivers/staging/fsl_dpa_offload/dts/b4420qds-usdpaa.dts
new file mode 100644
index 0000000..8165f70
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/b4420qds-usdpaa.dts
@@ -0,0 +1,154 @@
+/*
+ * B4420QDS Device Tree Source
+ *
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "b4420qds.dts"
+
+/ {
+ /* NB: "bpool-ethernet-seeds" is not set to avoid buffer seeding,
+ * because apps seed these pools with buffers allocated at
+ * run-time.
+ * HOWEVER, the kernel driver requires the buffer-size so
+ * "fsl,bpool-ethernet-cfg" is set. It also mis-interprets
+ * things if the base-address is zero (hence the 0xdeadbeef
+ * values).
+ */
+ bp7: buffer-pool@7 {
+ compatible = "fsl,b4420-bpool", "fsl,bpool";
+ fsl,bpid = <7>;
+ fsl,bpool-ethernet-cfg = <0 0 0 192 0 0xdeadbeef>;
+ fsl,bpool-thresholds = <0x400 0xc00 0x0 0x0>;
+ };
+ bp8: buffer-pool@8 {
+ compatible = "fsl,b4420-bpool", "fsl,bpool";
+ fsl,bpid = <8>;
+ fsl,bpool-ethernet-cfg = <0 0 0 576 0 0xabbaf00d>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp9: buffer-pool@9 {
+ compatible = "fsl,b4420-bpool", "fsl,bpool";
+ fsl,bpid = <9>;
+ fsl,bpool-ethernet-cfg = <0 0 0 1728 0 0xfeedabba>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ bp10: buffer-pool@10 {
+ compatible = "fsl,b4420-bpool", "fsl,bpool";
+ fsl,bpid = <10>;
+ fsl,bpool-thresholds = <0x10 0x30 0x0 0x0>;
+ };
+ bp11: buffer-pool@11 {
+ compatible = "fsl,b4420-bpool", "fsl,bpool";
+ fsl,bpid = <11>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp12: buffer-pool@12 {
+ compatible = "fsl,b4420-bpool", "fsl,bpool";
+ fsl,bpid = <12>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp16: buffer-pool@16 {
+ compatible = "fsl,b4420-bpool", "fsl,bpool";
+ fsl,bpid = <16>;
+ fsl,bpool-ethernet-cfg = <0 2048 0 1728 0 0>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ fsl,dpaa {
+ ethernet@0 {
+ compatible = "fsl,b4420-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x50 1 0x51 1>;
+ fsl,qman-frame-queues-tx = <0x70 1 0x71 1>;
+ };
+ ethernet@1 {
+ compatible = "fsl,b4420-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x52 1 0x53 1>;
+ fsl,qman-frame-queues-tx = <0x72 1 0x73 1>;
+ };
+ ethernet@2 {
+ compatible = "fsl,b4420-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x54 1 0x55 1>;
+ fsl,qman-frame-queues-tx = <0x74 1 0x75 1>;
+ };
+ ethernet@3 {
+ compatible = "fsl,b4420-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x56 1 0x57 1>;
+ fsl,qman-frame-queues-tx = <0x76 1 0x77 1>;
+ };
+
+ /* ethernet@16 declared as MAC-less interface with no "fsl,fman-mac" property.
+ * USDPAA will seed buffers to this buffer pool and initialize 8 TX Frame
+ * queues. The ethernet driver will initialize 8 RX default Frame queues.
+ * On receiving frame at this interface, the ethernet driver will do
+ * kmap_atomic/kunmap_atomic for that frame. */
+ ethernet@16 {
+ compatible = "fsl,b4420-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <4000 8>;
+ fsl,qman-frame-queues-tx = <4008 8>;
+ local-mac-address = [00 11 22 33 44 55];
+ };
+ ethernet@17 {
+ compatible = "fsl,b4420-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <5000 8>;
+ fsl,qman-frame-queues-tx = <5008 8>;
+ local-mac-address = [00 11 22 33 44 66];
+ };
+
+ dpa-fman0-oh@2 {
+ compatible = "fsl,dpa-oh";
+ /* Define frame queues for the OH port*/
+ /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x6e 1 0x6f 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh2>;
+ };
+ dpa_fman0_oh3: dpa-fman0-oh@3 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x68 1 0x69 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh3>;
+ };
+ dpa_fman0_oh4: dpa-fman0-oh@4 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x70 1 0x71 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh4>;
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/b4420si-chosen-offld.dtsi b/drivers/staging/fsl_dpa_offload/dts/b4420si-chosen-offld.dtsi
new file mode 100644
index 0000000..91ec766
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/b4420si-chosen-offld.dtsi
@@ -0,0 +1,31 @@
+chosen {
+ name = "chosen";
+
+ dpaa-extended-args {
+ fman0-extd-args {
+ cell-index = <0>;
+ compatible = "fsl,fman-extended-args";
+ dma-aid-mode = "port";
+ /* Inbound O/H post decryption */
+ fman0_oh2-extd-args {
+ cell-index = <1>;
+ compatible = "fsl,fman-port-op-extended-args";
+ errors-to-discard = <0x00420000>;
+ /* Define Virtual storage profile */
+ /* <number of profiles, default profile id> */
+ vsp-window = <8 0>;
+ };
+ /* Outbound O/H pre encryption */
+ fman0_oh3-extd-args {
+ cell-index = <2>;
+ compatible = "fsl,fman-port-op-extended-args";
+ errors-to-discard = <0x00420000>;
+ /* Define buffer layout parameters. Can be used
+ * in fragmentation or header manip operations
+ */
+ /* <manip extra space, data alignment> */
+ buffer-layout = <128 64>;
+ };
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/b4420si-chosen-reass.dtsi b/drivers/staging/fsl_dpa_offload/dts/b4420si-chosen-reass.dtsi
new file mode 100644
index 0000000..ec7b0b9
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/b4420si-chosen-reass.dtsi
@@ -0,0 +1,29 @@
+chosen {
+ name = "chosen";
+
+ dpaa-extended-args {
+ fman0-extd-args {
+ cell-index = <0>;
+ compatible = "fsl,fman-extended-args";
+ dma-aid-mode = "port";
+ fman0_rx3-extd-args {
+ cell-index = <3>;
+ compatible = "fsl,fman-port-1g-rx-extended-args";
+ errors-to-discard = <0x00020000>;
+ /* Define Virtual storage profile */
+ /* <number of profiles, default profile id> */
+ vsp-window = <8 0>;
+ };
+ fman0_oh2-extd-args {
+ cell-index = <1>;
+ compatible = "fsl,fman-port-op-extended-args";
+ errors-to-discard = <0x00420000>;
+ /* Define buffer layout parameters. Can be used
+ * in fragmentation or header manip operations
+ */
+ /* <manip extra space, data alignment> */
+ buffer-layout = <128 64>;
+ };
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/b4420si-pre.dtsi b/drivers/staging/fsl_dpa_offload/dts/b4420si-pre.dtsi
new file mode 100644
index 0000000..52c7613
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/b4420si-pre.dtsi
@@ -0,0 +1,116 @@
+/*
+ * B4420 Silicon/SoC Device Tree Source (pre include)
+ *
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * This software is provided by Freescale Semiconductor "as is" and any
+ * express or implied warranties, including, but not limited to, the implied
+ * warranties of merchantability and fitness for a particular purpose are
+ * disclaimed. In no event shall Freescale Semiconductor be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential damages
+ * (including, but not limited to, procurement of substitute goods or services;
+ * loss of use, data, or profits; or business interruption) however caused and
+ * on any theory of liability, whether in contract, strict liability, or tort
+ * (including negligence or otherwise) arising in any way out of the use of
+ * this software, even if advised of the possibility of such damage.
+ */
+
+/dts-v1/;
+
+/include/ "e6500_power_isa.dtsi"
+
+/ {
+ compatible = "fsl,B4420";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ aliases {
+ ccsr = &soc;
+ dcsr = &dcsr;
+
+ serial0 = &serial0;
+ serial1 = &serial1;
+ serial2 = &serial2;
+ serial3 = &serial3;
+
+ crypto = &crypto;
+ qman = &qman;
+ bman = &bman;
+ fman0 = &fman0;
+ ethernet0 = &fm1mac1;
+ ethernet1 = &fm1mac2;
+ ethernet2 = &fm1mac3;
+ ethernet3 = &fm1mac4;
+
+ pci0 = &pci0;
+ usb0 = &usb0;
+ dma0 = &dma0;
+ dma1 = &dma1;
+ sdhc = &sdhc;
+ };
+
+/include/ "b4420si-chosen.dtsi"
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /*
+ * Temporarily add next-level-cache info in each cpu node so
+ * that uboot can do L2 cache fixup. This can be removed once
+ * u-boot can create cpu node with cache info.
+ */
+ cpu0: PowerPC,e6500@0 {
+ device_type = "cpu";
+ reg = <0 1>;
+ clocks = <&mux0>;
+ next-level-cache = <&L2>;
+ };
+ cpu1: PowerPC,e6500@2 {
+ device_type = "cpu";
+ reg = <2 3>;
+ clocks = <&mux0>;
+ next-level-cache = <&L2>;
+ };
+ };
+
+ dsp-clusters {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dsp-cluster0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,sc3900-cluster";
+ reg = <0>;
+
+ dsp0: dsp@0 {
+ compatible = "fsl,sc3900";
+ reg = <0>;
+ next-level-cache = <&L2_2>;
+ };
+ dsp1: dsp@1 {
+ compatible = "fsl,sc3900";
+ reg = <1>;
+ next-level-cache = <&L2_2>;
+ };
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/b4860qds-usdpaa-shared-interfaces.dts b/drivers/staging/fsl_dpa_offload/dts/b4860qds-usdpaa-shared-interfaces.dts
new file mode 100644
index 0000000..a792dce
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/b4860qds-usdpaa-shared-interfaces.dts
@@ -0,0 +1,187 @@
+/*
+ * B4860QDS Device Tree Source
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "b4860qds.dts"
+
+/ {
+ /* NB: "bpool-ethernet-seeds" is not set to avoid buffer seeding,
+ * because apps seed these pools with buffers allocated at
+ * run-time.
+ * HOWEVER, the kernel driver requires the buffer-size so
+ * "fsl,bpool-ethernet-cfg" is set. It also mis-interprets
+ * things if the base-address is zero (hence the 0xdeadbeef
+ * values).
+ */
+ bp7: buffer-pool@7 {
+ compatible = "fsl,b4860-bpool", "fsl,bpool";
+ fsl,bpid = <7>;
+ fsl,bpool-ethernet-cfg = <0 0 0 192 0 0xdeadbeef>;
+ fsl,bpool-thresholds = <0x400 0xc00 0x0 0x0>;
+ };
+ bp8: buffer-pool@8 {
+ compatible = "fsl,b4860-bpool", "fsl,bpool";
+ fsl,bpid = <8>;
+ fsl,bpool-ethernet-cfg = <0 0 0 576 0 0xabbaf00d>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp9: buffer-pool@9 {
+ compatible = "fsl,b4860-bpool", "fsl,bpool";
+ fsl,bpid = <9>;
+ fsl,bpool-ethernet-cfg = <0 0 0 1728 0 0xfeedabba>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ bp10: buffer-pool@10 {
+ compatible = "fsl,b4860-bpool", "fsl,bpool";
+ fsl,bpid = <10>;
+ fsl,bpool-thresholds = <0x10 0x30 0x0 0x0>;
+ };
+ bp11: buffer-pool@11 {
+ compatible = "fsl,b4860-bpool", "fsl,bpool";
+ fsl,bpid = <11>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp12: buffer-pool@12 {
+ compatible = "fsl,b4860-bpool", "fsl,bpool";
+ fsl,bpid = <12>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp16: buffer-pool@16 {
+ compatible = "fsl,b4860-bpool", "fsl,bpool";
+ fsl,bpid = <16>;
+ fsl,bpool-ethernet-cfg = <0 2048 0 1728 0 0>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp17: buffer-pool@17 {
+ compatible = "fsl,b4860-bpool", "fsl,bpool";
+ fsl,bpid = <17>;
+ fsl,bpool-ethernet-cfg = <0 2048 0 1728 0 0>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ fsl,bpool-ethernet-seeds;
+ };
+
+ fsl,dpaa {
+ ethernet@0 {
+ compatible = "fsl,b4860-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x50 1 0x51 1>;
+ fsl,qman-frame-queues-tx = <0x70 1 0x71 1>;
+ };
+ ethernet@1 {
+ compatible = "fsl,b4860-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x52 1 0x53 1>;
+ fsl,qman-frame-queues-tx = <0x72 1 0x73 1>;
+ };
+ ethernet@2 {
+ compatible = "fsl,b4860-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x54 1 0x55 1>;
+ fsl,qman-frame-queues-tx = <0x74 1 0x75 1>;
+ };
+ ethernet@3 {
+ compatible = "fsl,b4860-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x56 1 0x57 1>;
+ fsl,qman-frame-queues-tx = <0x76 1 0x77 1>;
+ };
+ ethernet@4 {
+ compatible = "fsl,b4860-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x58 1 0x59 1>;
+ fsl,qman-frame-queues-tx = <0x78 1 0x79 1>;
+ };
+ ethernet@5 {
+ compatible = "fsl,b4860-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x5a 1 0x5b 1>;
+ fsl,qman-frame-queues-tx = <0x7a 1 0x7b 1>;
+ };
+
+ /* ethernet@16 declared as MAC-less interface with no "fsl,fman-mac" property.
+ * USDPAA will seed buffers to this buffer pool and initialize 8 TX Frame
+ * queues. The ethernet driver will initialize 8 RX default Frame queues.
+ * On receiving frame at this interface, the ethernet driver will do
+ * kmap_atomic/kunmap_atomic for that frame. */
+ ethernet@16 {
+ compatible = "fsl,b4860-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <4000 8>;
+ fsl,qman-frame-queues-tx = <4008 8>;
+ local-mac-address = [00 11 22 33 44 55];
+ };
+ ethernet@17 {
+ compatible = "fsl,b4860-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <5000 8>;
+ fsl,qman-frame-queues-tx = <5008 8>;
+ local-mac-address = [00 11 22 33 44 66];
+ };
+ ethernet@18 {
+ compatible = "fsl,b4860-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <6000 8>;
+ fsl,qman-frame-queues-tx = <6008 8>;
+ local-mac-address = [00 11 22 33 44 77];
+ };
+ ethernet@19 {
+ compatible = "fsl,b4860-dpa-ethernet-generic", "fsl,dpa-ethernet-generic";
+ fsl,qman-frame-queues-rx = <7000 2>;
+ fsl,qman-frame-queues-tx = <7008 1>;
+ fsl,oh-ports = <&oh2 &oh3>;
+ local-mac-address = [00 11 22 33 44 88];
+ };
+
+ oh2: dpa-fman0-oh@2 {
+ compatible = "fsl,dpa-oh";
+ /* Define frame queues for the OH port*/
+ /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x6e 1 0x6f 1>;
+ fsl,bman-buffer-pools = <&bp17>;
+ fsl,fman-oh-port = <&fman0_oh2>;
+ };
+ oh3: dpa_fman0_oh3: dpa-fman0-oh@3 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x68 1 0x69 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh3>;
+ };
+ dpa_fman0_oh4: dpa-fman0-oh@4 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x70 1 0x71 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh4>;
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/b4860qds-usdpaa-srio-eth-shared-interfaces.dts b/drivers/staging/fsl_dpa_offload/dts/b4860qds-usdpaa-srio-eth-shared-interfaces.dts
new file mode 100644
index 0000000..5a82583
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/b4860qds-usdpaa-srio-eth-shared-interfaces.dts
@@ -0,0 +1,150 @@
+/*
+ * B4860QDS Device Tree Source
+ *
+ * Copyright 2014 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "b4860qds.dts"
+
+/ {
+ /* NB: "bpool-ethernet-seeds" is not set to avoid buffer seeding,
+ * because apps seed these pools with buffers allocated at
+ * run-time.
+ * HOWEVER, the kernel driver requires the buffer-size so
+ * "fsl,bpool-ethernet-cfg" is set. It also mis-interprets
+ * things if the base-address is zero (hence the 0xdeadbeef
+ * values).
+ */
+ bp7: buffer-pool@7 {
+ compatible = "fsl,b4860-bpool", "fsl,bpool";
+ fsl,bpid = <7>;
+ fsl,bpool-ethernet-cfg = <0 0 0 192 0 0xdeadbeef>;
+ fsl,bpool-thresholds = <0x400 0xc00 0x0 0x0>;
+ };
+ bp8: buffer-pool@8 {
+ compatible = "fsl,b4860-bpool", "fsl,bpool";
+ fsl,bpid = <8>;
+ fsl,bpool-ethernet-cfg = <0 0 0 576 0 0xabbaf00d>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp9: buffer-pool@9 {
+ compatible = "fsl,b4860-bpool", "fsl,bpool";
+ fsl,bpid = <9>;
+ fsl,bpool-ethernet-cfg = <0 0 0 1728 0 0xfeedabba>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ bp10: buffer-pool@10 {
+ compatible = "fsl,b4860-bpool", "fsl,bpool";
+ fsl,bpid = <10>;
+ fsl,bpool-thresholds = <0x10 0x30 0x0 0x0>;
+ };
+ bp11: buffer-pool@11 {
+ compatible = "fsl,b4860-bpool", "fsl,bpool";
+ fsl,bpid = <11>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp12: buffer-pool@12 {
+ compatible = "fsl,b4860-bpool", "fsl,bpool";
+ fsl,bpid = <12>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp16: buffer-pool@16 {
+ compatible = "fsl,b4860-bpool", "fsl,bpool";
+ fsl,bpid = <16>;
+ fsl,bpool-ethernet-cfg = <0 2048 0 1728 0 0>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ fsl,dpaa {
+ ethernet@4 {
+ compatible = "fsl,b4860-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x58 1 0x59 1>;
+ fsl,qman-frame-queues-tx = <0x78 1 0x79 1>;
+ };
+
+ /* ethernet@16 declared as MAC-less interface with no "fsl,fman-mac" property.
+ * USDPAA will seed buffers to this buffer pool and initialize 8 TX Frame
+ * queues. The ethernet driver will initialize 8 RX default Frame queues.
+ * On receiving frame at this interface, the ethernet driver will do
+ * kmap_atomic/kunmap_atomic for that frame. */
+ ethernet@16 {
+ compatible = "fsl,b4860-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <4000 8>;
+ fsl,qman-frame-queues-tx = <4008 8>;
+ local-mac-address = [00 11 22 33 44 55];
+ };
+ ethernet@17 {
+ compatible = "fsl,b4860-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <5000 8>;
+ fsl,qman-frame-queues-tx = <5008 8>;
+ local-mac-address = [00 11 22 33 44 66];
+ };
+ ethernet@18 {
+ compatible = "fsl,b4860-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <6000 8>;
+ fsl,qman-frame-queues-tx = <6008 8>;
+ local-mac-address = [00 11 22 33 44 77];
+ };
+
+
+ dpa-fman0-oh@2 {
+ compatible = "fsl,dpa-oh";
+ /* Define frame queues for the OH port*/
+ /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x6e 1 0x6f 1>;
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,fman-oh-port = <&fman0_oh2>;
+ };
+ dpa_fman0_oh3: dpa-fman0-oh@3 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x68 1 0x69 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh3>;
+ };
+ dpa_fman0_oh4: dpa-fman0-oh@4 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x84 1 0x85 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh4>;
+ };
+ dpa_fman0_oh5: dpa-fman0-oh@5 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x86 1 0x87 1>;
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,fman-oh-port = <&fman0_oh5>;
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/b4860qds-usdpaa.dts b/drivers/staging/fsl_dpa_offload/dts/b4860qds-usdpaa.dts
new file mode 100644
index 0000000..621b52e
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/b4860qds-usdpaa.dts
@@ -0,0 +1,166 @@
+/*
+ * B4860QDS Device Tree Source
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "b4860qds.dts"
+
+/ {
+ /* NB: "bpool-ethernet-seeds" is not set to avoid buffer seeding,
+ * because apps seed these pools with buffers allocated at
+ * run-time.
+ * HOWEVER, the kernel driver requires the buffer-size so
+ * "fsl,bpool-ethernet-cfg" is set. It also mis-interprets
+ * things if the base-address is zero (hence the 0xdeadbeef
+ * values).
+ */
+ bp7: buffer-pool@7 {
+ compatible = "fsl,b4860-bpool", "fsl,bpool";
+ fsl,bpid = <7>;
+ fsl,bpool-ethernet-cfg = <0 0 0 192 0 0xdeadbeef>;
+ fsl,bpool-thresholds = <0x400 0xc00 0x0 0x0>;
+ };
+ bp8: buffer-pool@8 {
+ compatible = "fsl,b4860-bpool", "fsl,bpool";
+ fsl,bpid = <8>;
+ fsl,bpool-ethernet-cfg = <0 0 0 576 0 0xabbaf00d>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp9: buffer-pool@9 {
+ compatible = "fsl,b4860-bpool", "fsl,bpool";
+ fsl,bpid = <9>;
+ fsl,bpool-ethernet-cfg = <0 0 0 1728 0 0xfeedabba>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ bp10: buffer-pool@10 {
+ compatible = "fsl,b4860-bpool", "fsl,bpool";
+ fsl,bpid = <10>;
+ fsl,bpool-thresholds = <0x10 0x30 0x0 0x0>;
+ };
+ bp11: buffer-pool@11 {
+ compatible = "fsl,b4860-bpool", "fsl,bpool";
+ fsl,bpid = <11>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp12: buffer-pool@12 {
+ compatible = "fsl,b4860-bpool", "fsl,bpool";
+ fsl,bpid = <12>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp16: buffer-pool@16 {
+ compatible = "fsl,b4860-bpool", "fsl,bpool";
+ fsl,bpid = <16>;
+ fsl,bpool-ethernet-cfg = <0 2048 0 1728 0 0>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ fsl,dpaa {
+ ethernet@0 {
+ compatible = "fsl,b4860-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x50 1 0x51 1>;
+ fsl,qman-frame-queues-tx = <0x70 1 0x71 1>;
+ };
+ ethernet@1 {
+ compatible = "fsl,b4860-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x52 1 0x53 1>;
+ fsl,qman-frame-queues-tx = <0x72 1 0x73 1>;
+ };
+ ethernet@2 {
+ compatible = "fsl,b4860-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x54 1 0x55 1>;
+ fsl,qman-frame-queues-tx = <0x74 1 0x75 1>;
+ };
+ ethernet@3 {
+ compatible = "fsl,b4860-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x56 1 0x57 1>;
+ fsl,qman-frame-queues-tx = <0x76 1 0x77 1>;
+ };
+ ethernet@4 {
+ compatible = "fsl,b4860-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x58 1 0x59 1>;
+ fsl,qman-frame-queues-tx = <0x78 1 0x79 1>;
+ };
+ ethernet@5 {
+ compatible = "fsl,b4860-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x5a 1 0x5b 1>;
+ fsl,qman-frame-queues-tx = <0x7a 1 0x7b 1>;
+ };
+
+ /* ethernet@16 declared as MAC-less interface with no "fsl,fman-mac" property.
+ * USDPAA will seed buffers to this buffer pool and initialize 8 TX Frame
+ * queues. The ethernet driver will initialize 8 RX default Frame queues.
+ * On receiving frame at this interface, the ethernet driver will do
+ * kmap_atomic/kunmap_atomic for that frame. */
+ ethernet@16 {
+ compatible = "fsl,b4860-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <4000 8>;
+ fsl,qman-frame-queues-tx = <4008 8>;
+ local-mac-address = [00 11 22 33 44 55];
+ };
+ ethernet@17 {
+ compatible = "fsl,b4860-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <5000 8>;
+ fsl,qman-frame-queues-tx = <5008 8>;
+ local-mac-address = [00 11 22 33 44 66];
+ };
+
+ dpa-fman0-oh@2 {
+ compatible = "fsl,dpa-oh";
+ /* Define frame queues for the OH port*/
+ /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x6e 1 0x6f 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh2>;
+ };
+ dpa_fman0_oh3: dpa-fman0-oh@3 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x68 1 0x69 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh3>;
+ };
+ dpa_fman0_oh4: dpa-fman0-oh@4 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x70 1 0x71 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh4>;
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/b4860si-chosen-offld.dtsi b/drivers/staging/fsl_dpa_offload/dts/b4860si-chosen-offld.dtsi
new file mode 100644
index 0000000..91ec766
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/b4860si-chosen-offld.dtsi
@@ -0,0 +1,31 @@
+chosen {
+ name = "chosen";
+
+ dpaa-extended-args {
+ fman0-extd-args {
+ cell-index = <0>;
+ compatible = "fsl,fman-extended-args";
+ dma-aid-mode = "port";
+ /* Inbound O/H post decryption */
+ fman0_oh2-extd-args {
+ cell-index = <1>;
+ compatible = "fsl,fman-port-op-extended-args";
+ errors-to-discard = <0x00420000>;
+ /* Define Virtual storage profile */
+ /* <number of profiles, default profile id> */
+ vsp-window = <8 0>;
+ };
+ /* Outbound O/H pre encryption */
+ fman0_oh3-extd-args {
+ cell-index = <2>;
+ compatible = "fsl,fman-port-op-extended-args";
+ errors-to-discard = <0x00420000>;
+ /* Define buffer layout parameters. Can be used
+ * in fragmentation or header manip operations
+ */
+ /* <manip extra space, data alignment> */
+ buffer-layout = <128 64>;
+ };
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/b4860si-chosen-reass.dtsi b/drivers/staging/fsl_dpa_offload/dts/b4860si-chosen-reass.dtsi
new file mode 100644
index 0000000..c0c92f6
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/b4860si-chosen-reass.dtsi
@@ -0,0 +1,29 @@
+chosen {
+ name = "chosen";
+
+ dpaa-extended-args {
+ fman0-extd-args {
+ cell-index = <0>;
+ compatible = "fsl,fman-extended-args";
+ dma-aid-mode = "port";
+ fman0_rx5-extd-args {
+ cell-index = <5>;
+ compatible = "fsl,fman-port-1g-rx-extended-args";
+ errors-to-discard = <0x00020000>;
+ /* Define Virtual storage profile */
+ /* <number of profiles, default profile id> */
+ vsp-window = <8 0>;
+ };
+ fman0_oh2-extd-args {
+ cell-index = <1>;
+ compatible = "fsl,fman-port-op-extended-args";
+ errors-to-discard = <0x00420000>;
+ /* Define buffer layout parameters. Can be used
+ * in fragmentation or header manip operations
+ */
+ /* <manip extra space, data alignment> */
+ buffer-layout = <128 64>;
+ };
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/b4860si-pre.dtsi b/drivers/staging/fsl_dpa_offload/dts/b4860si-pre.dtsi
new file mode 100644
index 0000000..78cb451
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/b4860si-pre.dtsi
@@ -0,0 +1,169 @@
+/*
+ * B4860 Silicon/SoC Device Tree Source (pre include)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/dts-v1/;
+
+/include/ "e6500_power_isa.dtsi"
+
+/ {
+ compatible = "fsl,B4860";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ aliases {
+ ccsr = &soc;
+ dcsr = &dcsr;
+
+ serial0 = &serial0;
+ serial1 = &serial1;
+ serial2 = &serial2;
+ serial3 = &serial3;
+
+ crypto = &crypto;
+ qman = &qman;
+ bman = &bman;
+ fman0 = &fman0;
+ ethernet0 = &fm1mac1;
+ ethernet1 = &fm1mac2;
+ ethernet2 = &fm1mac3;
+ ethernet3 = &fm1mac4;
+ ethernet4 = &fm1mac5;
+ ethernet5 = &fm1mac6;
+ ethernet8 = &fm1mac9;
+ ethernet9 = &fm1mac10;
+
+ pci0 = &pci0;
+ usb0 = &usb0;
+ dma0 = &dma0;
+ dma1 = &dma1;
+ sdhc = &sdhc;
+ };
+
+/include/ "b4860si-chosen.dtsi"
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /*
+ * Temporarily add next-level-cache info in each cpu node so
+ * that uboot can do L2 cache fixup. This can be removed once
+ * u-boot can create cpu node with cache info.
+ */
+ cpu0: PowerPC,e6500@0 {
+ device_type = "cpu";
+ reg = <0 1>;
+ clocks = <&mux0>;
+ next-level-cache = <&L2>;
+ };
+ cpu1: PowerPC,e6500@2 {
+ device_type = "cpu";
+ reg = <2 3>;
+ clocks = <&mux0>;
+ next-level-cache = <&L2>;
+ };
+ cpu2: PowerPC,e6500@4 {
+ device_type = "cpu";
+ reg = <4 5>;
+ clocks = <&mux0>;
+ next-level-cache = <&L2>;
+ };
+ cpu3: PowerPC,e6500@6 {
+ device_type = "cpu";
+ reg = <6 7>;
+ clocks = <&mux0>;
+ next-level-cache = <&L2>;
+ };
+ };
+
+ dsp-clusters {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dsp-cluster0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,sc3900-cluster";
+ reg = <0>;
+
+ dsp0: dsp@0 {
+ compatible = "fsl,sc3900";
+ reg = <0>;
+ next-level-cache = <&L2_2>;
+ };
+ dsp1: dsp@1 {
+ compatible = "fsl,sc3900";
+ reg = <1>;
+ next-level-cache = <&L2_2>;
+ };
+ };
+
+ dsp-cluster1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,sc3900-cluster";
+ reg = <1>;
+
+ dsp2: dsp@2 {
+ compatible = "fsl,sc3900";
+ reg = <2>;
+ next-level-cache = <&L2_3>;
+ };
+ dsp3: dsp@3 {
+ compatible = "fsl,sc3900";
+ reg = <3>;
+ next-level-cache = <&L2_3>;
+ };
+ };
+
+ dsp-cluster2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,sc3900-cluster";
+ reg = <2>;
+
+ dsp4: dsp@4 {
+ compatible = "fsl,sc3900";
+ reg = <4>;
+ next-level-cache = <&L2_4>;
+ };
+ dsp5: dsp@5 {
+ compatible = "fsl,sc3900";
+ reg = <5>;
+ next-level-cache = <&L2_4>;
+ };
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/p2041rdb-usdpaa-shared-interfaces.dts b/drivers/staging/fsl_dpa_offload/dts/p2041rdb-usdpaa-shared-interfaces.dts
new file mode 100644
index 0000000..f68dc8f
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/p2041rdb-usdpaa-shared-interfaces.dts
@@ -0,0 +1,162 @@
+/*
+ * P2041RDB Device Tree Source
+ *
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "p2041rdb.dts"
+
+/ {
+ /* NB: "bpool-ethernet-seeds" is not set to avoid buffer seeding,
+ * because apps seed these pools with buffers allocated at
+ * run-time.
+ * HOWEVER, the kernel driver requires the buffer-size so
+ * "fsl,bpool-ethernet-cfg" is set. It also mis-interprets
+ * things if the base-address is zero (hence the 0xdeadbeef
+ * values).
+ */
+ bp7: buffer-pool@7 {
+ compatible = "fsl,p2041-bpool", "fsl,bpool";
+ fsl,bpid = <7>;
+ fsl,bpool-ethernet-cfg = <0 0 0 192 0 0xdeadbeef>;
+ fsl,bpool-thresholds = <0x400 0xc00 0x0 0x0>;
+ };
+ bp8: buffer-pool@8 {
+ compatible = "fsl,p2041-bpool", "fsl,bpool";
+ fsl,bpid = <8>;
+ fsl,bpool-ethernet-cfg = <0 0 0 576 0 0xabbaf00d>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp9: buffer-pool@9 {
+ compatible = "fsl,p2041-bpool", "fsl,bpool";
+ fsl,bpid = <9>;
+ fsl,bpool-ethernet-cfg = <0 0 0 1728 0 0xfeedabba>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp16: buffer-pool@16 {
+ compatible = "fsl,p2041-bpool", "fsl,bpool";
+ fsl,bpid = <16>;
+ fsl,bpool-ethernet-cfg = <0 2048 0 1728 0 0>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp17: buffer-pool@17 {
+ compatible = "fsl,p2041-bpool", "fsl,bpool";
+ fsl,bpid = <17>;
+ fsl,bpool-ethernet-cfg = <0 2048 0 1728 0 0>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ fsl,dpaa {
+ ethernet@0 {
+ compatible = "fsl,p2041-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x50 1 0x51 1>;
+ fsl,qman-frame-queues-tx = <0x70 1 0x71 1>;
+ };
+ ethernet@1 {
+ compatible = "fsl,p2041-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x52 1 0x53 1>;
+ fsl,qman-frame-queues-tx = <0x72 1 0x73 1>;
+ };
+ ethernet@2 {
+ compatible = "fsl,p2041-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x54 1 0x55 1>;
+ fsl,qman-frame-queues-tx = <0x74 1 0x75 1>;
+ };
+ ethernet@3 {
+ compatible = "fsl,p2041-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x56 1 0x57 1>;
+ fsl,qman-frame-queues-tx = <0x76 1 0x77 1>;
+ };
+ ethernet@4 {
+ compatible = "fsl,p2041-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x58 1 0x59 1>;
+ fsl,qman-frame-queues-tx = <0x78 1 0x79 1>;
+ };
+
+ ethernet@5 {
+ compatible = "fsl,p2041-dpa-ethernet-shared", "fsl,dpa-ethernet-shared";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x60 1 0x61 1>;
+ fsl,qman-frame-queues-tx = <0x80 1 0x81 1>;
+ };
+
+ /* ethernet@6 declared as MAC-less interface with no "fsl,fman-mac" property.
+ * USDPAA will seed buffers to this buffer pool and initialize 8 TX Frame
+ * queues. The ethernet driver will initialize 8 RX default Frame queues.
+ * On receiving frame at this interface, the ethernet driver will do
+ * kmap_atomic/kunmap_atomic for that frame. */
+ ethernet@16 {
+ compatible = "fsl,p2041-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <4000 8>;
+ fsl,qman-frame-queues-tx = <4008 8>;
+ local-mac-address = [00 11 22 33 44 55];
+ };
+ ethernet@17 {
+ compatible = "fsl,p2041-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <5000 8>;
+ fsl,qman-frame-queues-tx = <5008 8>;
+ local-mac-address = [00 11 22 33 44 66];
+ };
+ ethernet@18 {
+ compatible = "fsl,p2041-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <6000 8>;
+ fsl,qman-frame-queues-tx = <6008 8>;
+ local-mac-address = [00 11 22 33 44 77];
+ };
+
+ dpa-fman0-oh@1 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x64 1 0x65 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh1>;
+ };
+ dpa-fman0-oh@2 { /* Define frame queues for the OH port*/
+ compatible = "fsl,dpa-oh"; /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x68 1 0x69 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh2>;
+ };
+ dpa-fman0-oh@3 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x70 1 0x71 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh3>;
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/p2041rdb-usdpaa.dts b/drivers/staging/fsl_dpa_offload/dts/p2041rdb-usdpaa.dts
new file mode 100644
index 0000000..99a71f1
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/p2041rdb-usdpaa.dts
@@ -0,0 +1,154 @@
+/*
+ * P2041RDB Device Tree Source
+ *
+ * Copyright 2011-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "p2041rdb.dts"
+
+/ {
+ /* NB: "bpool-ethernet-seeds" is not set to avoid buffer seeding,
+ * because apps seed these pools with buffers allocated at
+ * run-time.
+ * HOWEVER, the kernel driver requires the buffer-size so
+ * "fsl,bpool-ethernet-cfg" is set. It also mis-interprets
+ * things if the base-address is zero (hence the 0xdeadbeef
+ * values).
+ */
+ bp7: buffer-pool@7 {
+ compatible = "fsl,p2041-bpool", "fsl,bpool";
+ fsl,bpid = <7>;
+ fsl,bpool-ethernet-cfg = <0 0 0 192 0 0xdeadbeef>;
+ fsl,bpool-thresholds = <0x400 0xc00 0x0 0x0>;
+ };
+ bp8: buffer-pool@8 {
+ compatible = "fsl,p2041-bpool", "fsl,bpool";
+ fsl,bpid = <8>;
+ fsl,bpool-ethernet-cfg = <0 0 0 576 0 0xabbaf00d>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp9: buffer-pool@9 {
+ compatible = "fsl,p2041-bpool", "fsl,bpool";
+ fsl,bpid = <9>;
+ fsl,bpool-ethernet-cfg = <0 0 0 1728 0 0xfeedabba>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ bp16: buffer-pool@16 {
+ compatible = "fsl,p2041-bpool", "fsl,bpool";
+ fsl,bpid = <16>;
+ fsl,bpool-ethernet-cfg = <0 2048 0 1728 0 0>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ fsl,dpaa {
+ ethernet@0 {
+ compatible = "fsl,p2041-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x50 1 0x51 1>;
+ fsl,qman-frame-queues-tx = <0x70 1 0x71 1>;
+ };
+ ethernet@1 {
+ compatible = "fsl,p2041-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x52 1 0x53 1>;
+ fsl,qman-frame-queues-tx = <0x72 1 0x73 1>;
+ };
+ ethernet@2 {
+ compatible = "fsl,p2041-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x54 1 0x55 1>;
+ fsl,qman-frame-queues-tx = <0x74 1 0x75 1>;
+ };
+ ethernet@3 {
+ compatible = "fsl,p2041-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x56 1 0x57 1>;
+ fsl,qman-frame-queues-tx = <0x76 1 0x77 1>;
+ };
+ ethernet@4 {
+ compatible = "fsl,p2041-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x58 1 0x59 1>;
+ fsl,qman-frame-queues-tx = <0x78 1 0x79 1>;
+ };
+ ethernet@5 {
+ compatible = "fsl,p2041-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x5a 1 0x5b 1>;
+ fsl,qman-frame-queues-tx = <0x7a 1 0x7b 1>;
+ };
+
+ /* ethernet@16 declared as MAC-less interface with no "fsl,fman-mac" property.
+ * USDPAA will seed buffers to this buffer pool and initialize 8 TX Frame
+ * queues. The ethernet driver will initialize 8 RX default Frame queues.
+ * On receiving frame at this interface, the ethernet driver will do
+ * kmap_atomic/kunmap_atomic for that frame. */
+ ethernet@16 {
+ compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <4000 8>;
+ fsl,qman-frame-queues-tx = <4008 8>;
+ local-mac-address = [00 11 22 33 44 55];
+ };
+ ethernet@17 {
+ compatible = "fsl,p2041-dpa-ethernet", "fsl,dpa-ethernet";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <5000 8>;
+ fsl,qman-frame-queues-tx = <5008 8>;
+ local-mac-address = [00 11 22 33 44 66];
+ };
+
+ dpa-fman0-oh@1 {
+ compatible = "fsl,dpa-oh";
+ /* Define frame queues for the OH port*/
+ /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x64 1 0x65 1>;
+ fsl,fman-oh-port = <&fman0_oh1>;
+ };
+ dpa-fman0-oh@2 {
+ compatible = "fsl,dpa-oh";
+ /* Define frame queues for the OH port*/
+ /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x66 1 0x67 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh2>;
+ };
+ dpa-fman0-oh@3 {
+ compatible = "fsl,dpa-oh";
+ /* Define frame queues for the OH port*/
+ /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x68 1 0x69 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh3>;
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/p2041si-chosen-offld.dtsi b/drivers/staging/fsl_dpa_offload/dts/p2041si-chosen-offld.dtsi
new file mode 100644
index 0000000..294d592
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/p2041si-chosen-offld.dtsi
@@ -0,0 +1,21 @@
+chosen {
+ name = "chosen";
+
+ dpaa-extended-args {
+ fman0-extd-args {
+ cell-index = <0>;
+ compatible = "fsl,fman-extended-args";
+ dma-aid-mode = "port";
+ fman0_oh2-extd-args {
+ cell-index = <2>;
+ compatible = "fsl,fman-port-op-extended-args";
+ errors-to-discard = <0x00420000>;
+ /* Define buffer layout parameters. Can be used
+ * in fragmentation or header manip operations
+ */
+ /* <manip extra space, data alignment> */
+ buffer-layout = <128 64>;
+ };
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/p2041si-pre.dtsi b/drivers/staging/fsl_dpa_offload/dts/p2041si-pre.dtsi
new file mode 100644
index 0000000..4570eb1
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/p2041si-pre.dtsi
@@ -0,0 +1,124 @@
+/*
+ * P2041 Silicon/SoC Device Tree Source (pre include)
+ *
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/dts-v1/;
+
+/include/ "e500mc_power_isa.dtsi"
+
+/ {
+ compatible = "fsl,P2041";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ aliases {
+ ccsr = &soc;
+ dcsr = &dcsr;
+
+ serial0 = &serial0;
+ serial1 = &serial1;
+ serial2 = &serial2;
+ serial3 = &serial3;
+ pci0 = &pci0;
+ pci1 = &pci1;
+ pci2 = &pci2;
+ usb0 = &usb0;
+ usb1 = &usb1;
+ dma0 = &dma0;
+ dma1 = &dma1;
+ sdhc = &sdhc;
+ msi0 = &msi0;
+ msi1 = &msi1;
+ msi2 = &msi2;
+
+ crypto = &crypto;
+ sec_jr0 = &sec_jr0;
+ sec_jr1 = &sec_jr1;
+ sec_jr2 = &sec_jr2;
+ sec_jr3 = &sec_jr3;
+ rtic_a = &rtic_a;
+ rtic_b = &rtic_b;
+ rtic_c = &rtic_c;
+ rtic_d = &rtic_d;
+ sec_mon = &sec_mon;
+
+ rman = &rman;
+ pme = &pme;
+ qman = &qman;
+ bman = &bman;
+ fman0 = &fman0;
+ };
+/include/ "p2041si-chosen.dtsi"
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: PowerPC,e500mc@0 {
+ device_type = "cpu";
+ reg = <0>;
+ clocks = <&mux0>;
+ next-level-cache = <&L2_0>;
+ L2_0: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu1: PowerPC,e500mc@1 {
+ device_type = "cpu";
+ reg = <1>;
+ clocks = <&mux1>;
+ next-level-cache = <&L2_1>;
+ L2_1: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu2: PowerPC,e500mc@2 {
+ device_type = "cpu";
+ reg = <2>;
+ clocks = <&mux2>;
+ next-level-cache = <&L2_2>;
+ L2_2: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu3: PowerPC,e500mc@3 {
+ device_type = "cpu";
+ reg = <3>;
+ clocks = <&mux3>;
+ next-level-cache = <&L2_3>;
+ L2_3: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/p4080ds-usdpaa-shared-interfaces-for-ipsec-multiple-intances.dts b/drivers/staging/fsl_dpa_offload/dts/p4080ds-usdpaa-shared-interfaces-for-ipsec-multiple-intances.dts
new file mode 100644
index 0000000..95dc9c6
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/p4080ds-usdpaa-shared-interfaces-for-ipsec-multiple-intances.dts
@@ -0,0 +1,218 @@
+/*
+ * P4080DS Device Tree Source
+ *
+ * Copyright 2009-2014 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "p4080ds.dts"
+
+/ {
+ /* NB: "bpool-ethernet-seeds" is not set to avoid buffer seeding,
+ * because apps seed these pools with buffers allocated at
+ * run-time.
+ * HOWEVER, the kernel driver requires the buffer-size so
+ * "fsl,bpool-ethernet-cfg" is set. It also mis-interprets
+ * things if the base-address is zero (hence the 0xdeadbeef
+ * values).
+ */
+ bp7: buffer-pool@7 {
+ compatible = "fsl,p4080-bpool", "fsl,bpool";
+ fsl,bpid = <7>;
+ fsl,bpool-ethernet-cfg = <0 0 0 192 0 0xdeadbeef>;
+ fsl,bpool-thresholds = <0x400 0xc00 0x0 0x0>;
+ };
+ bp8: buffer-pool@8 {
+ compatible = "fsl,p4080-bpool", "fsl,bpool";
+ fsl,bpid = <8>;
+ fsl,bpool-ethernet-cfg = <0 0 0 576 0 0xabbaf00d>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp9: buffer-pool@9 {
+ compatible = "fsl,p4080-bpool", "fsl,bpool";
+ fsl,bpid = <9>;
+ fsl,bpool-ethernet-cfg = <0 0 0 1728 0 0xfeedabba>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp16: buffer-pool@16 {
+ compatible = "fsl,p4080-bpool", "fsl,bpool";
+ fsl,bpid = <16>;
+ fsl,bpool-ethernet-cfg = <0 2048 0 1728 0 0>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp17: buffer-pool@17 {
+ compatible = "fsl,p4080-bpool", "fsl,bpool";
+ fsl,bpid = <17>;
+ fsl,bpool-ethernet-cfg = <0 2048 0 1728 0 0>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ fsl,dpaa {
+ ethernet@0 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x50 1 0x51 1>;
+ fsl,qman-frame-queues-tx = <0x70 1 0x71 1>;
+ };
+
+ /* this inteface should be init by usdpaa */
+ ethernet@1 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x48 1 0x49 1>;
+ fsl,qman-frame-queues-tx = <0x68 1 0x69 1>;
+ };
+
+ ethernet@2 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x54 1 0x55 1>;
+ fsl,qman-frame-queues-tx = <0x74 1 0x75 1>;
+ };
+ ethernet@3 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x56 1 0x57 1>;
+ fsl,qman-frame-queues-tx = <0x76 1 0x77 1>;
+ };
+ ethernet@4 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x5a 1 0x5b 1>;
+ fsl,qman-frame-queues-tx = <0x7a 1 0x7b 1>;
+ };
+ ethernet@5 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x5c 1 0x5d 1>;
+ fsl,qman-frame-queues-tx = <0x7c 1 0x7d 1>;
+ };
+ ethernet@6 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x5e 1 0x5f 1>;
+ fsl,qman-frame-queues-tx = <0x7e 1 0x7f 1>;
+ };
+ ethernet@7 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x60 1 0x61 1>;
+ fsl,qman-frame-queues-tx = <0x80 1 0x81 1>;
+ };
+ ethernet@8 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x62 1 0x63 1>;
+ fsl,qman-frame-queues-tx = <0x82 1 0x83 1>;
+ };
+ /* ethernet@9 declared as shared MAC. USDPAA will seed buffers to
+ * this buffer pool. The ethernet driver will initialize the RX default,
+ * RX error, TX error, TX confirm and 8 TX Frame queues. On receiving frame
+ * at this interface, the ethernet driver will do kmap_atomic/kunmap_atomic
+ * for that frame. */
+ ethernet@9 {
+ compatible = "fsl,p4080-dpa-ethernet-shared", "fsl,dpa-ethernet-shared";
+ fsl,bman-buffer-pools = <&bp17>;
+ fsl,qman-frame-queues-rx = <0x66 1 0x67 1 0x2000 3>;
+ fsl,qman-frame-queues-tx = <0 1 0 1 0x3000 8>;
+ };
+ /* ethernet@16 declared as MAC-less interface with no "fsl,fman-mac" property.
+ * USDPAA will seed buffers to this buffer pool and initialize 8 TX Frame
+ * queues. The ethernet driver will initialize 8 RX default Frame queues.
+ * On receiving frame at this interface, the ethernet driver will do
+ * kmap_atomic/kunmap_atomic for that frame. */
+ ethernet@16 {
+ compatible = "fsl,p4080-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <4000 8>;
+ fsl,qman-frame-queues-tx = <4008 8>;
+ local-mac-address = [00 11 22 33 44 55];
+ };
+ ethernet@17 {
+ compatible = "fsl,p4080-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <5000 8>;
+ fsl,qman-frame-queues-tx = <5008 8>;
+ local-mac-address = [00 11 22 33 44 66];
+ };
+ ethernet@18 {
+ compatible = "fsl,p4080-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <6000 8>;
+ fsl,qman-frame-queues-tx = <6008 8>;
+ local-mac-address = [00 11 22 33 44 77];
+ };
+ ethernet@19 {
+ compatible = "fsl,p4080-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <7000 8>;
+ fsl,qman-frame-queues-tx = <7008 8>;
+ local-mac-address = [00 11 22 33 44 88];
+ };
+
+ dpa_fman1_oh1: dpa-fman1-oh@1 {
+ compatible = "fsl,dpa-oh";
+ /* Define frame queues for the OH port*/
+ /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x64 1 0x65 1>;
+ fsl,fman-oh-port = <&fman1_oh1>;
+ };
+ dpa_fman1_oh2: dpa-fman1-oh@2 { /* Define frame queues for the OH port*/
+ compatible = "fsl,dpa-oh"; /* <OH Rx error, OH Rx default> */
+ /* Define frame queues for the OH port*/
+ /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x68 1 0x69 1>;
+ fsl,bman-buffer-pools = <&bp8>;
+ fsl,fman-oh-port = <&fman1_oh2>;
+ };
+ dpa_fman1_oh3: dpa-fman1-oh@3 {
+ compatible = "fsl,dpa-oh";
+ /* Define frame queues for the OH port*/
+ /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x70 1 0x71 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman1_oh3>;
+ };
+ dpa_fman0_oh1: dpa-fman0-oh@1 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x77 1 0x78 1>;
+ fsl,fman-oh-port = <&fman0_oh1>;
+ };
+ dpa_fman0_oh2: dpa-fman0-oh@2 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x79 1 0x80 1>;
+ fsl,fman-oh-port = <&fman0_oh2>;
+ };
+ dpa_fman0_oh3: dpa-fman0-oh@3 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x81 1 0x82 1>;
+ fsl,fman-oh-port = <&fman0_oh3>;
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/p4080ds-usdpaa-shared-interfaces.dts b/drivers/staging/fsl_dpa_offload/dts/p4080ds-usdpaa-shared-interfaces.dts
new file mode 100644
index 0000000..1486ceb
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/p4080ds-usdpaa-shared-interfaces.dts
@@ -0,0 +1,191 @@
+/*
+ * P4080DS Device Tree Source
+ *
+ * Copyright 2009-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "p4080ds.dts"
+
+/ {
+ /* NB: "bpool-ethernet-seeds" is not set to avoid buffer seeding,
+ * because apps seed these pools with buffers allocated at
+ * run-time.
+ * HOWEVER, the kernel driver requires the buffer-size so
+ * "fsl,bpool-ethernet-cfg" is set. It also mis-interprets
+ * things if the base-address is zero (hence the 0xdeadbeef
+ * values).
+ */
+ bp7: buffer-pool@7 {
+ compatible = "fsl,p4080-bpool", "fsl,bpool";
+ fsl,bpid = <7>;
+ fsl,bpool-ethernet-cfg = <0 0 0 192 0 0xdeadbeef>;
+ fsl,bpool-thresholds = <0x400 0xc00 0x0 0x0>;
+ };
+ bp8: buffer-pool@8 {
+ compatible = "fsl,p4080-bpool", "fsl,bpool";
+ fsl,bpid = <8>;
+ fsl,bpool-ethernet-cfg = <0 0 0 576 0 0xabbaf00d>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp9: buffer-pool@9 {
+ compatible = "fsl,p4080-bpool", "fsl,bpool";
+ fsl,bpid = <9>;
+ fsl,bpool-ethernet-cfg = <0 0 0 1728 0 0xfeedabba>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp16: buffer-pool@16 {
+ compatible = "fsl,p4080-bpool", "fsl,bpool";
+ fsl,bpid = <16>;
+ fsl,bpool-ethernet-cfg = <0 2048 0 1728 0 0>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp17: buffer-pool@17 {
+ compatible = "fsl,p4080-bpool", "fsl,bpool";
+ fsl,bpid = <17>;
+ fsl,bpool-ethernet-cfg = <0 2048 0 1728 0 0>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ fsl,dpaa {
+ ethernet@0 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x50 1 0x51 1>;
+ fsl,qman-frame-queues-tx = <0x70 1 0x71 1>;
+ };
+
+ /* ethernet@1 will be used as a normal Linux ethernet that
+ * interfaces to the kernel network stack. All others will be
+ * dedicated for use by usdpaa */
+
+ ethernet@2 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x54 1 0x55 1>;
+ fsl,qman-frame-queues-tx = <0x74 1 0x75 1>;
+ };
+ ethernet@3 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x56 1 0x57 1>;
+ fsl,qman-frame-queues-tx = <0x76 1 0x77 1>;
+ };
+ ethernet@4 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x5a 1 0x5b 1>;
+ fsl,qman-frame-queues-tx = <0x7a 1 0x7b 1>;
+ };
+ ethernet@5 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x5c 1 0x5d 1>;
+ fsl,qman-frame-queues-tx = <0x7c 1 0x7d 1>;
+ };
+ ethernet@6 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x5e 1 0x5f 1>;
+ fsl,qman-frame-queues-tx = <0x7e 1 0x7f 1>;
+ };
+ ethernet@7 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x60 1 0x61 1>;
+ fsl,qman-frame-queues-tx = <0x80 1 0x81 1>;
+ };
+ ethernet@8 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x62 1 0x63 1>;
+ fsl,qman-frame-queues-tx = <0x82 1 0x83 1>;
+ };
+ /* ethernet@9 declared as shared MAC. USDPAA will seed buffers to
+ * this buffer pool. The ethernet driver will initialize the RX default,
+ * RX error, TX error, TX confirm and 8 TX Frame queues. On receiving frame
+ * at this interface, the ethernet driver will do kmap_atomic/kunmap_atomic
+ * for that frame. */
+ ethernet@9 {
+ compatible = "fsl,p4080-dpa-ethernet-shared", "fsl,dpa-ethernet-shared";
+ fsl,bman-buffer-pools = <&bp17>;
+ fsl,qman-frame-queues-rx = <0x66 1 0x67 1 0x2000 3>;
+ fsl,qman-frame-queues-tx = <0 1 0 1 0x3000 8>;
+ };
+ /* ethernet@16 declared as MAC-less interface with no "fsl,fman-mac" property.
+ * USDPAA will seed buffers to this buffer pool and initialize 8 TX Frame
+ * queues. The ethernet driver will initialize 8 RX default Frame queues.
+ * On receiving frame at this interface, the ethernet driver will do
+ * kmap_atomic/kunmap_atomic for that frame. */
+ ethernet@16 {
+ compatible = "fsl,p4080-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <4000 8>;
+ fsl,qman-frame-queues-tx = <4008 8>;
+ local-mac-address = [00 11 22 33 44 55];
+ };
+ ethernet@17 {
+ compatible = "fsl,p4080-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <5000 8>;
+ fsl,qman-frame-queues-tx = <5008 8>;
+ local-mac-address = [00 11 22 33 44 66];
+ };
+ ethernet@18 {
+ compatible = "fsl,p4080-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <6000 8>;
+ fsl,qman-frame-queues-tx = <6008 8>;
+ local-mac-address = [00 11 22 33 44 77];
+ };
+ dpa_fman1_oh1: dpa-fman1-oh@1 {
+ compatible = "fsl,dpa-oh";
+ /* Define frame queues for the OH port*/
+ /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x64 1 0x65 1>;
+ fsl,fman-oh-port = <&fman1_oh1>;
+ };
+ dpa_fman1_oh2: dpa-fman1-oh@2 { /* Define frame queues for the OH port*/
+ compatible = "fsl,dpa-oh"; /* <OH Rx error, OH Rx default> */
+ /* Define frame queues for the OH port*/
+ /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x68 1 0x69 1>;
+ fsl,bman-buffer-pools = <&bp8>;
+ fsl,fman-oh-port = <&fman1_oh2>;
+ };
+ dpa_fman1_oh3: dpa-fman1-oh@3 {
+ compatible = "fsl,dpa-oh";
+ /* Define frame queues for the OH port*/
+ /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x70 1 0x71 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman1_oh3>;
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/p4080ds-usdpaa.dts b/drivers/staging/fsl_dpa_offload/dts/p4080ds-usdpaa.dts
new file mode 100644
index 0000000..5f889e3
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/p4080ds-usdpaa.dts
@@ -0,0 +1,176 @@
+/*
+ * P4080DS Device Tree Source
+ *
+ * Copyright 2009-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "p4080ds.dts"
+
+/ {
+ /* NB: "bpool-ethernet-seeds" is not set to avoid buffer seeding,
+ * because apps seed these pools with buffers allocated at
+ * run-time.
+ * HOWEVER, the kernel driver requires the buffer-size so
+ * "fsl,bpool-ethernet-cfg" is set. It also mis-interprets
+ * things if the base-address is zero (hence the 0xdeadbeef
+ * values).
+ */
+ bp7: buffer-pool@7 {
+ compatible = "fsl,p4080-bpool", "fsl,bpool";
+ fsl,bpid = <7>;
+ fsl,bpool-ethernet-cfg = <0 0 0 192 0 0xdeadbeef>;
+ fsl,bpool-thresholds = <0x400 0xc00 0x0 0x0>;
+ };
+ bp8: buffer-pool@8 {
+ compatible = "fsl,p4080-bpool", "fsl,bpool";
+ fsl,bpid = <8>;
+ fsl,bpool-ethernet-cfg = <0 0 0 576 0 0xabbaf00d>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp9: buffer-pool@9 {
+ compatible = "fsl,p4080-bpool", "fsl,bpool";
+ fsl,bpid = <9>;
+ fsl,bpool-ethernet-cfg = <0 0 0 1728 0 0xfeedabba>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp16: buffer-pool@16 {
+ compatible = "fsl,p4080-bpool", "fsl,bpool";
+ fsl,bpid = <16>;
+ fsl,bpool-ethernet-cfg = <0 2048 0 1728 0 0>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ fsl,dpaa {
+ ethernet@0 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x50 1 0x51 1>;
+ fsl,qman-frame-queues-tx = <0x70 1 0x71 1>;
+ };
+
+ /* ethernet@1 will be used as a normal Linux ethernet that
+ * interfaces to the kernel network stack. All others will be
+ * dedicated for use by usdpaa */
+
+ ethernet@2 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x54 1 0x55 1>;
+ fsl,qman-frame-queues-tx = <0x74 1 0x75 1>;
+ };
+ ethernet@3 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x56 1 0x57 1>;
+ fsl,qman-frame-queues-tx = <0x76 1 0x77 1>;
+ };
+ ethernet@4 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x5a 1 0x5b 1>;
+ fsl,qman-frame-queues-tx = <0x7a 1 0x7b 1>;
+ };
+ ethernet@5 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x5c 1 0x5d 1>;
+ fsl,qman-frame-queues-tx = <0x7c 1 0x7d 1>;
+ };
+ ethernet@6 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x5e 1 0x5f 1>;
+ fsl,qman-frame-queues-tx = <0x7e 1 0x7f 1>;
+ };
+ ethernet@7 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x60 1 0x61 1>;
+ fsl,qman-frame-queues-tx = <0x80 1 0x81 1>;
+ };
+ ethernet@8 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x62 1 0x63 1>;
+ fsl,qman-frame-queues-tx = <0x82 1 0x83 1>;
+ };
+ ethernet@9 {
+ compatible = "fsl,p4080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x66 1 0x67 1>;
+ fsl,qman-frame-queues-tx = <0x86 1 0x87 1>;
+ };
+
+ /* ethernet@16 declared as MAC-less interface with no "fsl,fman-mac" property.
+ * USDPAA will seed buffers to this buffer pool and initialize 8 TX Frame
+ * queues. The ethernet driver will initialize 8 RX default Frame queues.
+ * On receiving frame at this interface, the ethernet driver will do
+ * kmap_atomic/kunmap_atomic for that frame. */
+ ethernet@16 {
+ compatible = "fsl,p4080-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <4000 8>;
+ fsl,qman-frame-queues-tx = <4008 8>;
+ local-mac-address = [00 11 22 33 44 55];
+ };
+ ethernet@17 {
+ compatible = "fsl,p4080-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <5000 8>;
+ fsl,qman-frame-queues-tx = <5008 8>;
+ local-mac-address = [00 11 22 33 44 66];
+ };
+
+ dpa_fman1_oh1: dpa-fman1-oh@1 {
+ compatible = "fsl,dpa-oh";
+ /* Define frame queues for the OH port*/
+ /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x64 1 0x65 1>;
+ fsl,fman-oh-port = <&fman1_oh1>;
+ };
+ dpa_fman1_oh2: dpa-fman1-oh@2 {
+ compatible = "fsl,dpa-oh";
+ /* Define frame queues for the OH port*/
+ /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x68 1 0x69 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman1_oh2>;
+ };
+ dpa_fman1_oh3: dpa-fman1-oh@3 {
+ compatible = "fsl,dpa-oh";
+ /* Define frame queues for the OH port*/
+ /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x70 1 0x71 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman1_oh3>;
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/p4080si-chosen-offld.dtsi b/drivers/staging/fsl_dpa_offload/dts/p4080si-chosen-offld.dtsi
new file mode 100644
index 0000000..1b9f530
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/p4080si-chosen-offld.dtsi
@@ -0,0 +1,21 @@
+chosen {
+ name = "chosen";
+
+ dpaa-extended-args {
+ fman1-extd-args {
+ cell-index = <1>;
+ compatible = "fsl,fman-extended-args";
+ dma-aid-mode = "port";
+ fman1_oh2-extd-args {
+ cell-index = <2>;
+ compatible = "fsl,fman-port-op-extended-args";
+ errors-to-discard = <0x00420000>;
+ /* Define buffer layout parameters. Can be used
+ * in fragmentation or header manip operations
+ */
+ /* <manip extra space, data alignment> */
+ buffer-layout = <128 64>;
+ };
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/p4080si-pre.dtsi b/drivers/staging/fsl_dpa_offload/dts/p4080si-pre.dtsi
new file mode 100644
index 0000000..9945479
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/p4080si-pre.dtsi
@@ -0,0 +1,162 @@
+/*
+ * P4080/P4040 Silicon/SoC Device Tree Source (pre include)
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/dts-v1/;
+
+/include/ "e500mc_power_isa.dtsi"
+
+/ {
+ compatible = "fsl,P4080";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ aliases {
+ ccsr = &soc;
+ dcsr = &dcsr;
+
+ serial0 = &serial0;
+ serial1 = &serial1;
+ serial2 = &serial2;
+ serial3 = &serial3;
+ pci0 = &pci0;
+ pci1 = &pci1;
+ pci2 = &pci2;
+ usb0 = &usb0;
+ usb1 = &usb1;
+ dma0 = &dma0;
+ dma1 = &dma1;
+ sdhc = &sdhc;
+ msi0 = &msi0;
+ msi1 = &msi1;
+ msi2 = &msi2;
+
+ crypto = &crypto;
+ sec_jr0 = &sec_jr0;
+ sec_jr1 = &sec_jr1;
+ sec_jr2 = &sec_jr2;
+ sec_jr3 = &sec_jr3;
+ rtic_a = &rtic_a;
+ rtic_b = &rtic_b;
+ rtic_c = &rtic_c;
+ rtic_d = &rtic_d;
+ sec_mon = &sec_mon;
+
+ pme = &pme;
+ qman = &qman;
+ bman = &bman;
+ fman0 = &fman0;
+ fman1 = &fman1;
+ };
+
+/include/ "p4080si-chosen.dtsi"
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: PowerPC,e500mc@0 {
+ device_type = "cpu";
+ reg = <0>;
+ clocks = <&mux0>;
+ next-level-cache = <&L2_0>;
+ L2_0: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu1: PowerPC,e500mc@1 {
+ device_type = "cpu";
+ reg = <1>;
+ clocks = <&mux1>;
+ next-level-cache = <&L2_1>;
+ L2_1: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu2: PowerPC,e500mc@2 {
+ device_type = "cpu";
+ reg = <2>;
+ clocks = <&mux2>;
+ next-level-cache = <&L2_2>;
+ L2_2: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu3: PowerPC,e500mc@3 {
+ device_type = "cpu";
+ reg = <3>;
+ clocks = <&mux3>;
+ next-level-cache = <&L2_3>;
+ L2_3: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu4: PowerPC,e500mc@4 {
+ device_type = "cpu";
+ reg = <4>;
+ clocks = <&mux4>;
+ next-level-cache = <&L2_4>;
+ L2_4: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu5: PowerPC,e500mc@5 {
+ device_type = "cpu";
+ reg = <5>;
+ clocks = <&mux5>;
+ next-level-cache = <&L2_5>;
+ L2_5: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu6: PowerPC,e500mc@6 {
+ device_type = "cpu";
+ reg = <6>;
+ clocks = <&mux6>;
+ next-level-cache = <&L2_6>;
+ L2_6: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ cpu7: PowerPC,e500mc@7 {
+ device_type = "cpu";
+ reg = <7>;
+ clocks = <&mux7>;
+ next-level-cache = <&L2_7>;
+ L2_7: l2-cache {
+ next-level-cache = <&cpc>;
+ };
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/p5020ds-usdpaa.dts b/drivers/staging/fsl_dpa_offload/dts/p5020ds-usdpaa.dts
new file mode 100644
index 0000000..eaa4657
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/p5020ds-usdpaa.dts
@@ -0,0 +1,129 @@
+/*
+ * P5020DS Device Tree Source
+ *
+ * Copyright 2010-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "p5020ds.dts"
+
+/ {
+ /* NB: "bpool-ethernet-seeds" is not set to avoid buffer seeding,
+ * because apps seed these pools with buffers allocated at
+ * run-time.
+ * HOWEVER, the kernel driver requires the buffer-size so
+ * "fsl,bpool-ethernet-cfg" is set. It also mis-interprets
+ * things if the base-address is zero (hence the 0xdeadbeef
+ * values).
+ */
+ bp7: buffer-pool@7 {
+ compatible = "fsl,p5020-bpool", "fsl,bpool";
+ fsl,bpid = <7>;
+ fsl,bpool-ethernet-cfg = <0 0 0 192 0 0xdeadbeef>;
+ fsl,bpool-thresholds = <0x400 0xc00 0x0 0x0>;
+ };
+ bp8: buffer-pool@8 {
+ compatible = "fsl,p5020-bpool", "fsl,bpool";
+ fsl,bpid = <8>;
+ fsl,bpool-ethernet-cfg = <0 0 0 576 0 0xabbaf00d>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp9: buffer-pool@9 {
+ compatible = "fsl,p5020-bpool", "fsl,bpool";
+ fsl,bpid = <9>;
+ fsl,bpool-ethernet-cfg = <0 0 0 1600 0 0xfeedabba>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp10: buffer-pool@10 {
+ compatible = "fsl,p5020-bpool", "fsl,bpool";
+ fsl,bpid = <10>;
+ fsl,bpool-thresholds = <0x10 0x30 0x0 0x0>;
+ };
+ bp11: buffer-pool@11 {
+ compatible = "fsl,p5020-bpool", "fsl,bpool";
+ fsl,bpid = <11>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp12: buffer-pool@12 {
+ compatible = "fsl,p5020-bpool", "fsl,bpool";
+ fsl,bpid = <12>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ fsl,dpaa {
+ ethernet@0 {
+ compatible = "fsl,p5020-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x50 1 0x51 1>;
+ fsl,qman-frame-queues-tx = <0x70 1 0x71 1>;
+ };
+ ethernet@1 {
+ compatible = "fsl,p5020-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x52 1 0x53 1>;
+ fsl,qman-frame-queues-tx = <0x72 1 0x73 1>;
+ };
+ ethernet@2 {
+ compatible = "fsl,p5020-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x54 1 0x55 1>;
+ fsl,qman-frame-queues-tx = <0x74 1 0x75 1>;
+ };
+ ethernet@3 {
+ compatible = "fsl,p5020-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x56 1 0x57 1>;
+ fsl,qman-frame-queues-tx = <0x76 1 0x77 1>;
+ };
+ ethernet@4 {
+ compatible = "fsl,p5020-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x58 1 0x59 1>;
+ fsl,qman-frame-queues-tx = <0x78 1 0x79 1>;
+ };
+ dpa_fman0_oh1: dpa-fman0-oh@1 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x64 1 0x65 1>;
+ fsl,fman-oh-port = <&fman0_oh1>;
+ };
+ dpa_fman0_oh2: dpa-fman0-oh@2 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x68 1 0x69 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh2>;
+ };
+ dpa_fman0_oh3: dpa-fman0-oh@3 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x70 1 0x71 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh3>;
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/p5020si-post.dtsi b/drivers/staging/fsl_dpa_offload/dts/p5020si-post.dtsi
new file mode 100644
index 0000000..4772553
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/p5020si-post.dtsi
@@ -0,0 +1,437 @@
+/*
+ * P5020/5010 Silicon/SoC Device Tree Source (post include)
+ *
+ * Copyright 2011 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+&lbc {
+ compatible = "fsl,p5020-rev1.0-elbc", "simple-bus";
+ interrupts = <
+ 25 2 0 0
+ 16 2 1 19
+ >;
+ #address-cells = <2>;
+ #size-cells = <1>;
+};
+
+/* controller at 0x200000 */
+&pci0 {
+ compatible = "fsl,p5020-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0x0 0xff>;
+ clock-frequency = <33333333>;
+ interrupts = <16 2 1 15>;
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 15>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 40 1 0 0
+ 0000 0 0 2 &mpic 1 1 0 0
+ 0000 0 0 3 &mpic 2 1 0 0
+ 0000 0 0 4 &mpic 3 1 0 0
+ >;
+ };
+};
+
+/* controller at 0x201000 */
+&pci1 {
+ compatible = "fsl,p5020-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0 0xff>;
+ clock-frequency = <33333333>;
+ interrupts = <16 2 1 14>;
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 14>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 41 1 0 0
+ 0000 0 0 2 &mpic 5 1 0 0
+ 0000 0 0 3 &mpic 6 1 0 0
+ 0000 0 0 4 &mpic 7 1 0 0
+ >;
+ };
+};
+
+/* controller at 0x202000 */
+&pci2 {
+ compatible = "fsl,p5020-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0x0 0xff>;
+ clock-frequency = <33333333>;
+ interrupts = <16 2 1 13>;
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 13>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 42 1 0 0
+ 0000 0 0 2 &mpic 9 1 0 0
+ 0000 0 0 3 &mpic 10 1 0 0
+ 0000 0 0 4 &mpic 11 1 0 0
+ >;
+ };
+};
+
+/* controller at 0x203000 */
+&pci3 {
+ compatible = "fsl,p5020-pcie", "fsl,qoriq-pcie-v2.2";
+ device_type = "pci";
+ #size-cells = <2>;
+ #address-cells = <3>;
+ bus-range = <0x0 0xff>;
+ clock-frequency = <33333333>;
+ interrupts = <16 2 1 12>;
+ pcie@0 {
+ reg = <0 0 0 0 0>;
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ interrupts = <16 2 1 12>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x0 */
+ 0000 0 0 1 &mpic 43 1 0 0
+ 0000 0 0 2 &mpic 0 1 0 0
+ 0000 0 0 3 &mpic 4 1 0 0
+ 0000 0 0 4 &mpic 8 1 0 0
+ >;
+ };
+};
+
+&rio {
+ compatible = "fsl,srio";
+ interrupts = <16 2 1 11>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ port1 {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ cell-index = <1>;
+ };
+
+ port2 {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ cell-index = <2>;
+ };
+};
+
+&dcsr {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,dcsr", "simple-bus";
+
+ dcsr-epu@0 {
+ compatible = "fsl,dcsr-epu";
+ interrupts = <52 2 0 0
+ 84 2 0 0
+ 85 2 0 0>;
+ reg = <0x0 0x1000>;
+ };
+ dcsr-npc {
+ compatible = "fsl,dcsr-npc";
+ reg = <0x1000 0x1000 0x1000000 0x8000>;
+ };
+ dcsr-nxc@2000 {
+ compatible = "fsl,dcsr-nxc";
+ reg = <0x2000 0x1000>;
+ };
+ dcsr-corenet {
+ compatible = "fsl,dcsr-corenet";
+ reg = <0x8000 0x1000 0xB0000 0x1000>;
+ };
+ dcsr-dpaa@9000 {
+ compatible = "fsl,p5020-dcsr-dpaa", "fsl,dcsr-dpaa";
+ reg = <0x9000 0x1000>;
+ };
+ dcsr-ocn@11000 {
+ compatible = "fsl,p5020-dcsr-ocn", "fsl,dcsr-ocn";
+ reg = <0x11000 0x1000>;
+ };
+ dcsr-ddr@12000 {
+ compatible = "fsl,dcsr-ddr";
+ dev-handle = <&ddr1>;
+ reg = <0x12000 0x1000>;
+ };
+ dcsr-ddr@13000 {
+ compatible = "fsl,dcsr-ddr";
+ dev-handle = <&ddr2>;
+ reg = <0x13000 0x1000>;
+ };
+ dcsr-nal@18000 {
+ compatible = "fsl,p5020-dcsr-nal", "fsl,dcsr-nal";
+ reg = <0x18000 0x1000>;
+ };
+ dcsr-rcpm@22000 {
+ compatible = "fsl,p5020-dcsr-rcpm", "fsl,dcsr-rcpm";
+ reg = <0x22000 0x1000>;
+ };
+ dcsr-cpu-sb-proxy@40000 {
+ compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+ cpu-handle = <&cpu0>;
+ reg = <0x40000 0x1000>;
+ };
+ dcsr-cpu-sb-proxy@41000 {
+ compatible = "fsl,dcsr-e5500-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
+ cpu-handle = <&cpu1>;
+ reg = <0x41000 0x1000>;
+ };
+};
+
+&bportals {
+/include/ "qoriq-bman1-portals.dtsi"
+};
+
+&qportals {
+/include/ "qoriq-qman1-portals.dtsi"
+};
+
+&soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "soc";
+ compatible = "simple-bus";
+
+ soc-sram-error {
+ compatible = "fsl,soc-sram-error";
+ interrupts = <16 2 1 29>;
+ };
+
+ corenet-law@0 {
+ compatible = "fsl,corenet-law";
+ reg = <0x0 0x1000>;
+ fsl,num-laws = <32>;
+ };
+
+ ddr1: memory-controller@8000 {
+ compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller";
+ reg = <0x8000 0x1000>;
+ interrupts = <16 2 1 23>;
+ };
+
+ ddr2: memory-controller@9000 {
+ compatible = "fsl,qoriq-memory-controller-v4.5","fsl,qoriq-memory-controller";
+ reg = <0x9000 0x1000>;
+ interrupts = <16 2 1 22>;
+ };
+
+ cpc: l3-cache-controller@10000 {
+ compatible = "fsl,p5020-l3-cache-controller", "fsl,p4080-l3-cache-controller", "cache";
+ reg = <0x10000 0x1000
+ 0x11000 0x1000>;
+ interrupts = <16 2 1 27
+ 16 2 1 26>;
+ };
+
+ corenet-cf@18000 {
+ compatible = "fsl,corenet-cf";
+ reg = <0x18000 0x1000>;
+ interrupts = <16 2 1 31>;
+ fsl,ccf-num-csdids = <32>;
+ fsl,ccf-num-snoopids = <32>;
+ };
+
+ iommu@20000 {
+ compatible = "fsl,pamu-v1.0", "fsl,pamu";
+ reg = <0x20000 0x4000>;
+ interrupts = <
+ 24 2 0 0
+ 16 2 1 30>;
+ };
+
+/include/ "qoriq-mpic.dtsi"
+
+ guts: global-utilities@e0000 {
+ compatible = "fsl,qoriq-device-config-1.0";
+ reg = <0xe0000 0xe00>;
+ fsl,has-rstcr;
+ #sleep-cells = <1>;
+ fsl,liodn-bits = <12>;
+ };
+
+ pins: global-utilities@e0e00 {
+ compatible = "fsl,qoriq-pin-control-1.0";
+ reg = <0xe0e00 0x200>;
+ #sleep-cells = <2>;
+ };
+
+ clockgen: global-utilities@e1000 {
+ compatible = "fsl,p5020-clockgen", "fsl,qoriq-clockgen-1.0";
+ reg = <0xe1000 0x1000>;
+ clock-frequency = <0>;
+ };
+
+ rcpm: global-utilities@e2000 {
+ compatible = "fsl,qoriq-rcpm-1.0";
+ reg = <0xe2000 0x1000>;
+ #sleep-cells = <1>;
+ };
+
+ sfp: sfp@e8000 {
+ compatible = "fsl,p5020-sfp", "fsl,qoriq-sfp-1.0";
+ reg = <0xe8000 0x1000>;
+ };
+
+ serdes: serdes@ea000 {
+ compatible = "fsl,p5020-serdes";
+ reg = <0xea000 0x1000>;
+ };
+
+/include/ "qoriq-dma-0.dtsi"
+/include/ "qoriq-dma-1.dtsi"
+/include/ "qoriq-espi-0.dtsi"
+ spi@110000 {
+ fsl,espi-num-chipselects = <4>;
+ };
+
+/include/ "qoriq-esdhc-0.dtsi"
+ sdhc@114000 {
+ sdhci,auto-cmd12;
+ };
+
+/include/ "qoriq-i2c-0.dtsi"
+/include/ "qoriq-i2c-1.dtsi"
+/include/ "qoriq-duart-0.dtsi"
+/include/ "qoriq-duart-1.dtsi"
+/include/ "qoriq-gpio-0.dtsi"
+/include/ "qoriq-usb2-mph-0.dtsi"
+ usb0: usb@210000 {
+ compatible = "fsl-usb2-mph-v1.6", "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
+ phy_type = "utmi";
+ port0;
+ };
+
+/include/ "qoriq-usb2-dr-0.dtsi"
+ usb1: usb@211000 {
+ compatible = "fsl-usb2-dr-v1.6", "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
+ dr_mode = "host";
+ phy_type = "utmi";
+ };
+
+/include/ "qoriq-sata2-0.dtsi"
+ sata@220000 {
+ compatible = "fsl,p5020-sata", "fsl,pq-sata-v2";
+ };
+/include/ "qoriq-sata2-1.dtsi"
+ sata@221000 {
+ compatible = "fsl,p5020-sata", "fsl,pq-sata-v2";
+ };
+/include/ "qoriq-sec4.2-0.dtsi"
+/include/ "qoriq-pme-0.dtsi"
+/include/ "qoriq-rman-0.dtsi"
+/include/ "qoriq-qman1.dtsi"
+/include/ "qoriq-bman1.dtsi"
+
+/include/ "qoriq-fman-0.dtsi"
+/include/ "qoriq-fman-0-1g-0.dtsi"
+/include/ "qoriq-fman-0-1g-1.dtsi"
+/include/ "qoriq-fman-0-1g-2.dtsi"
+/include/ "qoriq-fman-0-1g-3.dtsi"
+/include/ "qoriq-fman-0-1g-4.dtsi"
+ fman0: fman@400000 {
+ /* tx - 1g - 0 */
+ port@a8000 {
+ fsl,qman-channel-id = <0x41>;
+ };
+ /* tx - 1g - 1 */
+ port@a9000 {
+ fsl,qman-channel-id = <0x42>;
+ };
+ /* tx - 1g - 2 */
+ port@aa000 {
+ fsl,qman-channel-id = <0x43>;
+ };
+ /* tx - 1g - 3 */
+ port@ab000 {
+ fsl,qman-channel-id = <0x44>;
+ };
+ /* tx - 1g - 4 */
+ port@ac000 {
+ fsl,qman-channel-id = <0x45>;
+ };
+ /* tx - 10g - 0 */
+ port@b0000 {
+ fsl,qman-channel-id = <0x40>;
+ };
+ /* offline 0 */
+ port@81000 {
+ fsl,qman-channel-id = <0x46>;
+ };
+ /* offline 1 */
+ port@82000 {
+ fsl,qman-channel-id = <0x47>;
+ };
+ /* offline 2 */
+ port@83000 {
+ fsl,qman-channel-id = <0x48>;
+ };
+ /* offline 3 */
+ port@84000 {
+ fsl,qman-channel-id = <0x49>;
+ };
+ /* offline 4 */
+ port@85000 {
+ fsl,qman-channel-id = <0x4a>;
+ };
+ /* offline 5 */
+ port@86000 {
+ fsl,qman-channel-id = <0x4b>;
+ };
+ };
+
+/include/ "qoriq-raid1.0-0.dtsi"
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/t2080qds-usdpaa-shared-interfaces.dts b/drivers/staging/fsl_dpa_offload/dts/t2080qds-usdpaa-shared-interfaces.dts
new file mode 100644
index 0000000..af253fc
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/t2080qds-usdpaa-shared-interfaces.dts
@@ -0,0 +1,182 @@
+/*
+ * T2080QDS USDPAA Device Tree Source
+ *
+ * Copyright 2014 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "t2080qds.dts"
+
+/ {
+ /* NB: "bpool-ethernet-seeds" is not set to avoid buffer seeding,
+ * because apps seed these pools with buffers allocated at
+ * run-time.
+ * HOWEVER, the kernel driver requires the buffer-size so
+ * "fsl,bpool-ethernet-cfg" is set. It also mis-interprets
+ * things if the base-address is zero (hence the 0xdeadbeef
+ * values).
+ */
+ bp7: buffer-pool@7 {
+ compatible = "fsl,t2080-bpool", "fsl,bpool";
+ fsl,bpid = <7>;
+ fsl,bpool-ethernet-cfg = <0 0 0 192 0 0xdeadbeef>;
+ fsl,bpool-thresholds = <0x400 0xc00 0x0 0x0>;
+ };
+ bp8: buffer-pool@8 {
+ compatible = "fsl,t2080-bpool", "fsl,bpool";
+ fsl,bpid = <8>;
+ fsl,bpool-ethernet-cfg = <0 0 0 576 0 0xabbaf00d>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp9: buffer-pool@9 {
+ compatible = "fsl,t2080-bpool", "fsl,bpool";
+ fsl,bpid = <9>;
+ fsl,bpool-ethernet-cfg = <0 0 0 1728 0 0xfeedabba>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ bp10: buffer-pool@10 {
+ compatible = "fsl,t2080-bpool", "fsl,bpool";
+ fsl,bpid = <10>;
+ fsl,bpool-thresholds = <0x10 0x30 0x0 0x0>;
+ };
+ bp11: buffer-pool@11 {
+ compatible = "fsl,t2080-bpool", "fsl,bpool";
+ fsl,bpid = <11>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp12: buffer-pool@12 {
+ compatible = "fsl,t2080-bpool", "fsl,bpool";
+ fsl,bpid = <12>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp16: buffer-pool@16 {
+ compatible = "fsl,t2080-bpool", "fsl,bpool";
+ fsl,bpid = <16>;
+ fsl,bpool-ethernet-cfg = <0 2048 0 1728 0 0>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp17: buffer-pool@17 {
+ compatible = "fsl,t2080-bpool", "fsl,bpool";
+ fsl,bpid = <17>;
+ fsl,bpool-ethernet-cfg = <0 2048 0 1728 0 0>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ fsl,dpaa {
+ ethernet@0 {/* 10G */
+ compatible = "fsl,t2080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x90 1 0x91 1>;
+ fsl,qman-frame-queues-tx = <0x98 1 0x99 1>;
+ };
+ /* ethernet@1 declared as shared MAC. USDPAA will seed buffers to
+ * this buffer pool. The ethernet driver will initialize the RX default,
+ * RX error, TX error, TX confirm and 8 TX Frame queues. On receiving frame
+ * at this interface, the ethernet driver will do kmap_atomic/kunmap_atomic
+ * for that frame. */
+ ethernet@1 {/* 10G */
+ compatible = "fsl,t2080-dpa-ethernet-shared", "fsl,dpa-ethernet-shared";
+ fsl,bman-buffer-pools = <&bp17>;
+ fsl,qman-frame-queues-rx = <0x92 1 0x93 1 0x2000 3>;
+ fsl,qman-frame-queues-tx = <0 1 0 1 0x3000 8>;
+ };
+ ethernet@2 {/* 1G */
+ compatible = "fsl,t2080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x54 1 0x55 1>;
+ fsl,qman-frame-queues-tx = <0x74 1 0x75 1>;
+ };
+ ethernet@3 {/* 1G */
+ compatible = "fsl,t2080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x56 1 0x57 1>;
+ fsl,qman-frame-queues-tx = <0x76 1 0x77 1>;
+ };
+ ethernet@8 {/* 10G */
+ compatible = "fsl,t2080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x5c 1 0x5d 1>;
+ fsl,qman-frame-queues-tx = <0x7c 1 0x7d 1>;
+ };
+ ethernet@9 {/* 10G */
+ compatible = "fsl,t2080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x5e 1 0x5f 1>;
+ fsl,qman-frame-queues-tx = <0x7e 1 0x7f 1>;
+ };
+ /* ethernet@10 declared as MAC-less interface with no "fsl,fman-mac" property.
+ * USDPAA will seed buffers to this buffer pool and initialize 8 TX Frame
+ * queues. The ethernet driver will initialize 8 RX default Frame queues.
+ * On receiving frame at this interface, the ethernet driver will do
+ * kmap_atomic/kunmap_atomic for that frame. */
+ ethernet@10 {
+ compatible = "fsl,t2080-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <4000 8>;
+ fsl,qman-frame-queues-tx = <4008 8>;
+ local-mac-address = [00 11 22 33 44 55];
+ };
+ ethernet@11 {
+ compatible = "fsl,t2080-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <5000 8>;
+ fsl,qman-frame-queues-tx = <5008 8>;
+ local-mac-address = [00 11 22 33 44 66];
+ };
+ ethernet@12 {
+ compatible = "fsl,t2080-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <6000 8>;
+ fsl,qman-frame-queues-tx = <6008 8>;
+ local-mac-address = [00 11 22 33 44 77];
+ };
+ dpa-fman0-oh@2 {
+ compatible = "fsl,dpa-oh";
+ /* Define frame queues for the OH port*/
+ /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x6e 1 0x6f 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh2>;
+ };
+ dpa_fman0_oh3: dpa-fman0-oh@3 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x68 1 0x69 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh3>;
+ };
+ dpa_fman0_oh4: dpa-fman0-oh@4 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x70 1 0x71 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh4>;
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/t2080qds-usdpaa.dts b/drivers/staging/fsl_dpa_offload/dts/t2080qds-usdpaa.dts
new file mode 100644
index 0000000..7d56796
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/t2080qds-usdpaa.dts
@@ -0,0 +1,165 @@
+/*
+ * T2080QDS USDPAA Device Tree Source
+ *
+ * Copyright 2014 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "t2080qds.dts"
+
+/ {
+ /* NB: "bpool-ethernet-seeds" is not set to avoid buffer seeding,
+ * because apps seed these pools with buffers allocated at
+ * run-time.
+ * HOWEVER, the kernel driver requires the buffer-size so
+ * "fsl,bpool-ethernet-cfg" is set. It also mis-interprets
+ * things if the base-address is zero (hence the 0xdeadbeef
+ * values).
+ */
+ bp7: buffer-pool@7 {
+ compatible = "fsl,t2080-bpool", "fsl,bpool";
+ fsl,bpid = <7>;
+ fsl,bpool-ethernet-cfg = <0 0 0 192 0 0xdeadbeef>;
+ fsl,bpool-thresholds = <0x400 0xc00 0x0 0x0>;
+ };
+ bp8: buffer-pool@8 {
+ compatible = "fsl,t2080-bpool", "fsl,bpool";
+ fsl,bpid = <8>;
+ fsl,bpool-ethernet-cfg = <0 0 0 576 0 0xabbaf00d>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp9: buffer-pool@9 {
+ compatible = "fsl,t2080-bpool", "fsl,bpool";
+ fsl,bpid = <9>;
+ fsl,bpool-ethernet-cfg = <0 0 0 1728 0 0xfeedabba>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ bp10: buffer-pool@10 {
+ compatible = "fsl,t2080-bpool", "fsl,bpool";
+ fsl,bpid = <10>;
+ fsl,bpool-thresholds = <0x10 0x30 0x0 0x0>;
+ };
+ bp11: buffer-pool@11 {
+ compatible = "fsl,t2080-bpool", "fsl,bpool";
+ fsl,bpid = <11>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp12: buffer-pool@12 {
+ compatible = "fsl,t2080-bpool", "fsl,bpool";
+ fsl,bpid = <12>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp16: buffer-pool@16 {
+ compatible = "fsl,t2080-bpool", "fsl,bpool";
+ fsl,bpid = <16>;
+ fsl,bpool-ethernet-cfg = <0 2048 0 1728 0 0>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ fsl,dpaa {
+ ethernet@0 {/* 10G */
+ compatible = "fsl,t2080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x90 1 0x91 1>;
+ fsl,qman-frame-queues-tx = <0x98 1 0x99 1>;
+ };
+ ethernet@1 {/* 10G */
+ compatible = "fsl,t2080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x92 1 0x93 1>;
+ fsl,qman-frame-queues-tx = <0x9a 1 0x9b 1>;
+ };
+ ethernet@2 {/* 1G */
+ compatible = "fsl,t2080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x54 1 0x55 1>;
+ fsl,qman-frame-queues-tx = <0x74 1 0x75 1>;
+ };
+ ethernet@3 {/* 1G */
+ compatible = "fsl,t2080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x56 1 0x57 1>;
+ fsl,qman-frame-queues-tx = <0x76 1 0x77 1>;
+ };
+ ethernet@8 {/* 10G */
+ compatible = "fsl,t2080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x5c 1 0x5d 1>;
+ fsl,qman-frame-queues-tx = <0x7c 1 0x7d 1>;
+ };
+ ethernet@9 {/* 10G */
+ compatible = "fsl,t2080-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x5e 1 0x5f 1>;
+ fsl,qman-frame-queues-tx = <0x7e 1 0x7f 1>;
+ };
+ /* ethernet@16 declared as MAC-less interface with no "fsl,fman-mac" property.
+ * USDPAA will seed buffers to this buffer pool and initialize 8 TX Frame
+ * queues. The ethernet driver will initialize 8 RX default Frame queues.
+ * On receiving frame at this interface, the ethernet driver will do
+ * kmap_atomic/kunmap_atomic for that frame. */
+ ethernet@16 {
+ compatible = "fsl,t2080-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <4000 8>;
+ fsl,qman-frame-queues-tx = <4008 8>;
+ local-mac-address = [00 11 22 33 44 55];
+ };
+ ethernet@17 {
+ compatible = "fsl,t2080-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <5000 8>;
+ fsl,qman-frame-queues-tx = <5008 8>;
+ local-mac-address = [00 11 22 33 44 66];
+ };
+ dpa-fman0-oh@2 {
+ compatible = "fsl,dpa-oh";
+ /* Define frame queues for the OH port*/
+ /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x6e 1 0x6f 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh2>;
+ };
+ dpa_fman0_oh3: dpa-fman0-oh@3 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x68 1 0x69 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh3>;
+ };
+ dpa_fman0_oh4: dpa-fman0-oh@4 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x70 1 0x71 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh4>;
+ };
+
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/t2080si-chosen-offld.dtsi b/drivers/staging/fsl_dpa_offload/dts/t2080si-chosen-offld.dtsi
new file mode 100644
index 0000000..91ec766
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/t2080si-chosen-offld.dtsi
@@ -0,0 +1,31 @@
+chosen {
+ name = "chosen";
+
+ dpaa-extended-args {
+ fman0-extd-args {
+ cell-index = <0>;
+ compatible = "fsl,fman-extended-args";
+ dma-aid-mode = "port";
+ /* Inbound O/H post decryption */
+ fman0_oh2-extd-args {
+ cell-index = <1>;
+ compatible = "fsl,fman-port-op-extended-args";
+ errors-to-discard = <0x00420000>;
+ /* Define Virtual storage profile */
+ /* <number of profiles, default profile id> */
+ vsp-window = <8 0>;
+ };
+ /* Outbound O/H pre encryption */
+ fman0_oh3-extd-args {
+ cell-index = <2>;
+ compatible = "fsl,fman-port-op-extended-args";
+ errors-to-discard = <0x00420000>;
+ /* Define buffer layout parameters. Can be used
+ * in fragmentation or header manip operations
+ */
+ /* <manip extra space, data alignment> */
+ buffer-layout = <128 64>;
+ };
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/t2080si-chosen-reass.dtsi b/drivers/staging/fsl_dpa_offload/dts/t2080si-chosen-reass.dtsi
new file mode 100644
index 0000000..ec7b0b9
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/t2080si-chosen-reass.dtsi
@@ -0,0 +1,29 @@
+chosen {
+ name = "chosen";
+
+ dpaa-extended-args {
+ fman0-extd-args {
+ cell-index = <0>;
+ compatible = "fsl,fman-extended-args";
+ dma-aid-mode = "port";
+ fman0_rx3-extd-args {
+ cell-index = <3>;
+ compatible = "fsl,fman-port-1g-rx-extended-args";
+ errors-to-discard = <0x00020000>;
+ /* Define Virtual storage profile */
+ /* <number of profiles, default profile id> */
+ vsp-window = <8 0>;
+ };
+ fman0_oh2-extd-args {
+ cell-index = <1>;
+ compatible = "fsl,fman-port-op-extended-args";
+ errors-to-discard = <0x00420000>;
+ /* Define buffer layout parameters. Can be used
+ * in fragmentation or header manip operations
+ */
+ /* <manip extra space, data alignment> */
+ buffer-layout = <128 64>;
+ };
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/t208xsi-pre.dtsi b/drivers/staging/fsl_dpa_offload/dts/t208xsi-pre.dtsi
new file mode 100644
index 0000000..02a0230
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/t208xsi-pre.dtsi
@@ -0,0 +1,117 @@
+/*
+ * T2080/T2081 Silicon/SoC Device Tree Source (pre include)
+ *
+ * Copyright 2014 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/dts-v1/;
+
+/include/ "e6500_power_isa.dtsi"
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ aliases {
+ ccsr = &soc;
+ dcsr = &dcsr;
+
+ serial0 = &serial0;
+ serial1 = &serial1;
+ serial2 = &serial2;
+ serial3 = &serial3;
+
+ crypto = &crypto;
+ rman = &rman;
+ dce = &dce;
+ pme = &pme;
+ qman = &qman;
+ bman = &bman;
+ fman0 = &fman0;
+ ethernet0 = &fm1mac1;
+ ethernet1 = &fm1mac2;
+ ethernet2 = &fm1mac3;
+ ethernet3 = &fm1mac4;
+ ethernet4 = &fm1mac5;
+ ethernet5 = &fm1mac6;
+ ethernet8 = &fm1mac9;
+ ethernet9 = &fm1mac10;
+
+ pci0 = &pci0;
+ pci1 = &pci1;
+ pci2 = &pci2;
+ pci3 = &pci3;
+ usb0 = &usb0;
+ usb1 = &usb1;
+ dma0 = &dma0;
+ dma1 = &dma1;
+ dma2 = &dma2;
+ sdhc = &sdhc;
+ };
+
+/include/ "t2080si-chosen.dtsi"
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /*
+ * Temporarily add next-level-cache info in each cpu node so
+ * that uboot can do L2 cache fixup. This can be removed once
+ * u-boot can create cpu node with cache info.
+ */
+ cpu0: PowerPC,e6500@0 {
+ device_type = "cpu";
+ reg = <0 1>;
+ clocks = <&mux0>;
+ next-level-cache = <&L2_1>;
+ };
+ cpu1: PowerPC,e6500@2 {
+ device_type = "cpu";
+ reg = <2 3>;
+ clocks = <&mux0>;
+ next-level-cache = <&L2_1>;
+ };
+ cpu2: PowerPC,e6500@4 {
+ device_type = "cpu";
+ reg = <4 5>;
+ clocks = <&mux0>;
+ next-level-cache = <&L2_1>;
+ };
+ cpu3: PowerPC,e6500@6 {
+ device_type = "cpu";
+ reg = <6 7>;
+ clocks = <&mux0>;
+ next-level-cache = <&L2_1>;
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/t4240qds-usdpaa-shared-interfaces.dts b/drivers/staging/fsl_dpa_offload/dts/t4240qds-usdpaa-shared-interfaces.dts
new file mode 100644
index 0000000..9253e59
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/t4240qds-usdpaa-shared-interfaces.dts
@@ -0,0 +1,184 @@
+/*
+ * T4240QDS USDPAA Device Tree Source
+ *
+ * Copyright 2013 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "t4240qds.dts"
+
+/ {
+ /* NB: "bpool-ethernet-seeds" is not set to avoid buffer seeding,
+ * because apps seed these pools with buffers allocated at
+ * run-time.
+ * HOWEVER, the kernel driver requires the buffer-size so
+ * "fsl,bpool-ethernet-cfg" is set. It also mis-interprets
+ * things if the base-address is zero (hence the 0xdeadbeef
+ * values).
+ */
+ bp7: buffer-pool@7 {
+ compatible = "fsl,t4240-bpool", "fsl,bpool";
+ fsl,bpid = <7>;
+ fsl,bpool-ethernet-cfg = <0 0 0 192 0 0xdeadbeef>;
+ fsl,bpool-thresholds = <0x400 0xc00 0x0 0x0>;
+ };
+ bp8: buffer-pool@8 {
+ compatible = "fsl,t4240-bpool", "fsl,bpool";
+ fsl,bpid = <8>;
+ fsl,bpool-ethernet-cfg = <0 0 0 576 0 0xabbaf00d>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp9: buffer-pool@9 {
+ compatible = "fsl,t4240-bpool", "fsl,bpool";
+ fsl,bpid = <9>;
+ fsl,bpool-ethernet-cfg = <0 0 0 1728 0 0xfeedabba>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ bp10: buffer-pool@10 {
+ compatible = "fsl,t4240-bpool", "fsl,bpool";
+ fsl,bpid = <10>;
+ fsl,bpool-thresholds = <0x10 0x30 0x0 0x0>;
+ };
+ bp11: buffer-pool@11 {
+ compatible = "fsl,t4240-bpool", "fsl,bpool";
+ fsl,bpid = <11>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp12: buffer-pool@12 {
+ compatible = "fsl,t4240-bpool", "fsl,bpool";
+ fsl,bpid = <12>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp16: buffer-pool@16 {
+ compatible = "fsl,t4240-bpool", "fsl,bpool";
+ fsl,bpid = <16>;
+ fsl,bpool-ethernet-cfg = <0 2048 0 1728 0 0>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp17: buffer-pool@17 {
+ compatible = "fsl,t4240-bpool", "fsl,bpool";
+ fsl,bpid = <17>;
+ fsl,bpool-ethernet-cfg = <0 2048 0 1728 0 0>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ fsl,dpaa {
+ ethernet@4 {
+ compatible = "fsl,t4240-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x58 1 0x59 1>;
+ fsl,qman-frame-queues-tx = <0x78 1 0x79 1>;
+ };
+ ethernet@6 {
+ compatible = "fsl,t4240-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x5c 1 0x5d 1>;
+ fsl,qman-frame-queues-tx = <0x7c 1 0x7d 1>;
+ };
+ ethernet@7 {
+ compatible = "fsl,t4240-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x5e 1 0x5f 1>;
+ fsl,qman-frame-queues-tx = <0x7e 1 0x7f 1>;
+ };
+ ethernet@12 {
+ compatible = "fsl,t4240-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x68 1 0x69 1>;
+ fsl,qman-frame-queues-tx = <0x88 1 0x89 1>;
+ };
+ ethernet@14 {
+ compatible = "fsl,t4240-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x6c 1 0x6d 1>;
+ fsl,qman-frame-queues-tx = <0x8c 1 0x8d 1>;
+ };
+ /* ethernet@15 declared as shared MAC. USDPAA will seed buffers to
+ * this buffer pool. The ethernet driver will initialize the RX default,
+ * RX error, TX error, TX confirm and 8 TX Frame queues. On receiving frame
+ * at this interface, the ethernet driver will do kmap_atomic/kunmap_atomic
+ * for that frame. */
+ ethernet@15 {
+ compatible = "fsl,t4240-dpa-ethernet-shared", "fsl,dpa-ethernet-shared";
+ fsl,bman-buffer-pools = <&bp17>;
+ fsl,qman-frame-queues-rx = <0x6e 1 0x6f 1 0x2000 3>;
+ fsl,qman-frame-queues-tx = <0 1 0 1 0x3000 8>;
+ };
+ /* ethernet@16 declared as MAC-less interface with no "fsl,fman-mac" property.
+ * USDPAA will seed buffers to this buffer pool and initialize 8 TX Frame
+ * queues. The ethernet driver will initialize 8 RX default Frame queues.
+ * On receiving frame at this interface, the ethernet driver will do
+ * kmap_atomic/kunmap_atomic for that frame. */
+ ethernet@16 {
+ compatible = "fsl,t4240-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <4000 8>;
+ fsl,qman-frame-queues-tx = <4008 8>;
+ local-mac-address = [00 11 22 33 44 55];
+ };
+ ethernet@17 {
+ compatible = "fsl,t4240-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <5000 8>;
+ fsl,qman-frame-queues-tx = <5008 8>;
+ local-mac-address = [00 11 22 33 44 66];
+ };
+ ethernet@18 {
+ compatible = "fsl,t4240-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <6000 8>;
+ fsl,qman-frame-queues-tx = <6008 8>;
+ local-mac-address = [00 11 22 33 44 77];
+ };
+
+
+ dpa-fman0-oh@2 {
+ compatible = "fsl,dpa-oh";
+ /* Define frame queues for the OH port*/
+ /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x90 1 0x91 1>;
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,fman-oh-port = <&fman0_oh2>;
+ };
+ dpa_fman0_oh3: dpa-fman0-oh@3 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x92 1 0x93 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh3>;
+ };
+ dpa_fman0_oh4: dpa-fman0-oh@4 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x94 1 0x795 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh4>;
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/t4240qds-usdpaa-shared-interfaces_for_ipsec_multiple_instances.dts b/drivers/staging/fsl_dpa_offload/dts/t4240qds-usdpaa-shared-interfaces_for_ipsec_multiple_instances.dts
new file mode 100644
index 0000000..75ffece
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/t4240qds-usdpaa-shared-interfaces_for_ipsec_multiple_instances.dts
@@ -0,0 +1,210 @@
+/*
+ * T4240QDS USDPAA Device Tree Source
+ *
+ * Copyright 2014 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "t4240qds.dts"
+
+/ {
+ /* NB: "bpool-ethernet-seeds" is not set to avoid buffer seeding,
+ * because apps seed these pools with buffers allocated at
+ * run-time.
+ * HOWEVER, the kernel driver requires the buffer-size so
+ * "fsl,bpool-ethernet-cfg" is set. It also mis-interprets
+ * things if the base-address is zero (hence the 0xdeadbeef
+ * values).
+ */
+ bp7: buffer-pool@7 {
+ compatible = "fsl,t4240-bpool", "fsl,bpool";
+ fsl,bpid = <7>;
+ fsl,bpool-ethernet-cfg = <0 0 0 192 0 0xdeadbeef>;
+ fsl,bpool-thresholds = <0x400 0xc00 0x0 0x0>;
+ };
+ bp8: buffer-pool@8 {
+ compatible = "fsl,t4240-bpool", "fsl,bpool";
+ fsl,bpid = <8>;
+ fsl,bpool-ethernet-cfg = <0 0 0 576 0 0xabbaf00d>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp9: buffer-pool@9 {
+ compatible = "fsl,t4240-bpool", "fsl,bpool";
+ fsl,bpid = <9>;
+ fsl,bpool-ethernet-cfg = <0 0 0 1728 0 0xfeedabba>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ bp10: buffer-pool@10 {
+ compatible = "fsl,t4240-bpool", "fsl,bpool";
+ fsl,bpid = <10>;
+ fsl,bpool-thresholds = <0x10 0x30 0x0 0x0>;
+ };
+ bp11: buffer-pool@11 {
+ compatible = "fsl,t4240-bpool", "fsl,bpool";
+ fsl,bpid = <11>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp12: buffer-pool@12 {
+ compatible = "fsl,t4240-bpool", "fsl,bpool";
+ fsl,bpid = <12>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp16: buffer-pool@16 {
+ compatible = "fsl,t4240-bpool", "fsl,bpool";
+ fsl,bpid = <16>;
+ fsl,bpool-ethernet-cfg = <0 2048 0 1728 0 0>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp17: buffer-pool@17 {
+ compatible = "fsl,t4240-bpool", "fsl,bpool";
+ fsl,bpid = <17>;
+ fsl,bpool-ethernet-cfg = <0 2048 0 1728 0 0>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ fsl,dpaa {
+ ethernet@4 {
+ compatible = "fsl,t4240-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x58 1 0x59 1>;
+ fsl,qman-frame-queues-tx = <0x78 1 0x79 1>;
+ };
+ ethernet@6 {
+ compatible = "fsl,t4240-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x5c 1 0x5d 1>;
+ fsl,qman-frame-queues-tx = <0x7c 1 0x7d 1>;
+ };
+ ethernet@7 {
+ compatible = "fsl,t4240-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x5e 1 0x5f 1>;
+ fsl,qman-frame-queues-tx = <0x7e 1 0x7f 1>;
+ };
+ ethernet@12 {
+ compatible = "fsl,t4240-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x68 1 0x69 1>;
+ fsl,qman-frame-queues-tx = <0x88 1 0x89 1>;
+ };
+ ethernet@14 {
+ compatible = "fsl,t4240-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <0x6c 1 0x6d 1>;
+ fsl,qman-frame-queues-tx = <0x8c 1 0x8d 1>;
+ };
+ /* ethernet@15 declared as shared MAC. USDPAA will seed buffers to
+ * this buffer pool. The ethernet driver will initialize the RX default,
+ * RX error, TX error, TX confirm and 8 TX Frame queues. On receiving frame
+ * at this interface, the ethernet driver will do kmap_atomic/kunmap_atomic
+ * for that frame. */
+ ethernet@15 {
+ compatible = "fsl,t4240-dpa-ethernet-shared", "fsl,dpa-ethernet-shared";
+ fsl,bman-buffer-pools = <&bp17>;
+ fsl,qman-frame-queues-rx = <0x6e 1 0x6f 1 0x2000 3>;
+ fsl,qman-frame-queues-tx = <0 1 0 1 0x3000 8>;
+ };
+ /* ethernet@16 declared as MAC-less interface with no "fsl,fman-mac" property.
+ * USDPAA will seed buffers to this buffer pool and initialize 8 TX Frame
+ * queues. The ethernet driver will initialize 8 RX default Frame queues.
+ * On receiving frame at this interface, the ethernet driver will do
+ * kmap_atomic/kunmap_atomic for that frame. */
+ ethernet@16 {
+ compatible = "fsl,t4240-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <4000 8>;
+ fsl,qman-frame-queues-tx = <4008 8>;
+ local-mac-address = [00 11 22 33 44 55];
+ };
+ ethernet@17 {
+ compatible = "fsl,t4240-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <5000 8>;
+ fsl,qman-frame-queues-tx = <5008 8>;
+ local-mac-address = [00 11 22 33 44 66];
+ };
+ ethernet@18 {
+ compatible = "fsl,t4240-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <6000 8>;
+ fsl,qman-frame-queues-tx = <6008 8>;
+ local-mac-address = [00 11 22 33 44 77];
+ };
+ ethernet@19 {
+ compatible = "fsl,p4080-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <7000 8>;
+ fsl,qman-frame-queues-tx = <7008 8>;
+ local-mac-address = [00 11 22 33 44 88];
+ };
+
+ dpa-fman0-oh2: dpa-fman0-oh@2 {
+ compatible = "fsl,dpa-oh";
+ /* Define frame queues for the OH port*/
+ /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x90 1 0x91 1>;
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,fman-oh-port = <&fman0_oh2>;
+ };
+ dpa_fman0_oh3: dpa-fman0-oh@3 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x92 1 0x93 1>;
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,fman-oh-port = <&fman0_oh3>;
+ };
+ dpa_fman0_oh4: dpa-fman0-oh@4 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x94 1 0x95 1>;
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,fman-oh-port = <&fman0_oh4>;
+ };
+ dpa-fman1-oh2: dpa-fman1-oh@2 {
+ compatible = "fsl,dpa-oh";
+ /* Define frame queues for the OH port*/
+ /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x96 1 0x97 1>;
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,fman-oh-port = <&fman1_oh2>;
+ };
+ dpa_fman1_oh3: dpa-fman1-oh@3 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x98 1 0x99 1>;
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,fman-oh-port = <&fman1_oh3>;
+ };
+ dpa_fman1_oh4: dpa-fman1-oh@4 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x100 1 0x101 1>;
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,fman-oh-port = <&fman1_oh4>;
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/t4240qds-usdpaa.dts b/drivers/staging/fsl_dpa_offload/dts/t4240qds-usdpaa.dts
new file mode 100644
index 0000000..fa6534a
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/t4240qds-usdpaa.dts
@@ -0,0 +1,162 @@
+/*
+ * T4240QDS USDPAA Device Tree Source
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "t4240qds.dts"
+
+/ {
+ /* NB: "bpool-ethernet-seeds" is not set to avoid buffer seeding,
+ * because apps seed these pools with buffers allocated at
+ * run-time.
+ * HOWEVER, the kernel driver requires the buffer-size so
+ * "fsl,bpool-ethernet-cfg" is set. It also mis-interprets
+ * things if the base-address is zero (hence the 0xdeadbeef
+ * values).
+ */
+ bp7: buffer-pool@7 {
+ compatible = "fsl,t4240-bpool", "fsl,bpool";
+ fsl,bpid = <7>;
+ fsl,bpool-ethernet-cfg = <0 0 0 192 0 0xdeadbeef>;
+ fsl,bpool-thresholds = <0x400 0xc00 0x0 0x0>;
+ };
+ bp8: buffer-pool@8 {
+ compatible = "fsl,t4240-bpool", "fsl,bpool";
+ fsl,bpid = <8>;
+ fsl,bpool-ethernet-cfg = <0 0 0 576 0 0xabbaf00d>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp9: buffer-pool@9 {
+ compatible = "fsl,t4240-bpool", "fsl,bpool";
+ fsl,bpid = <9>;
+ fsl,bpool-ethernet-cfg = <0 0 0 1728 0 0xfeedabba>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ bp10: buffer-pool@10 {
+ compatible = "fsl,t4240-bpool", "fsl,bpool";
+ fsl,bpid = <10>;
+ fsl,bpool-thresholds = <0x10 0x30 0x0 0x0>;
+ };
+ bp11: buffer-pool@11 {
+ compatible = "fsl,t4240-bpool", "fsl,bpool";
+ fsl,bpid = <11>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+ bp12: buffer-pool@12 {
+ compatible = "fsl,t4240-bpool", "fsl,bpool";
+ fsl,bpid = <12>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ bp16: buffer-pool@16 {
+ compatible = "fsl,t4240-bpool", "fsl,bpool";
+ fsl,bpid = <16>;
+ fsl,bpool-ethernet-cfg = <0 2048 0 1728 0 0>;
+ fsl,bpool-thresholds = <0x100 0x300 0x0 0x0>;
+ };
+
+ fsl,dpaa {
+ ethernet@4 {
+ compatible = "fsl,t4240-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x58 1 0x59 1>;
+ fsl,qman-frame-queues-tx = <0x78 1 0x79 1>;
+ };
+ ethernet@6 {
+ compatible = "fsl,t4240-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x5c 1 0x5d 1>;
+ fsl,qman-frame-queues-tx = <0x7c 1 0x7d 1>;
+ };
+ ethernet@7 {
+ compatible = "fsl,t4240-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x5e 1 0x5f 1>;
+ fsl,qman-frame-queues-tx = <0x7e 1 0x7f 1>;
+ };
+ ethernet@12 {
+ compatible = "fsl,t4240-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x68 1 0x69 1>;
+ fsl,qman-frame-queues-tx = <0x88 1 0x89 1>;
+ };
+ ethernet@14 {
+ compatible = "fsl,t4240-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x6c 1 0x6d 1>;
+ fsl,qman-frame-queues-tx = <0x8c 1 0x8d 1>;
+ };
+ ethernet@15 {
+ compatible = "fsl,t4240-dpa-ethernet-init", "fsl,dpa-ethernet-init";
+ fsl,bman-buffer-pools = <&bp7 &bp8 &bp9>;
+ fsl,qman-frame-queues-rx = <0x6e 1 0x6f 1>;
+ fsl,qman-frame-queues-tx = <0x8e 1 0x8f 1>;
+ };
+
+ ethernet@16 {
+ compatible = "fsl,t4240-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <4000 8>;
+ fsl,qman-frame-queues-tx = <4008 8>;
+ local-mac-address = [00 11 22 33 44 55];
+ };
+ ethernet@17 {
+ compatible = "fsl,t4240-dpa-ethernet-macless", "fsl,dpa-ethernet-macless";
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,qman-frame-queues-rx = <5000 8>;
+ fsl,qman-frame-queues-tx = <5008 8>;
+ local-mac-address = [00 11 22 33 44 66];
+ };
+
+ dpa-fman0-oh@2 {
+ compatible = "fsl,dpa-oh";
+ /* Define frame queues for the OH port*/
+ /* <OH Rx error, OH Rx default> */
+ fsl,qman-frame-queues-oh = <0x90 1 0x91 1>;
+ fsl,bman-buffer-pools = <&bp16>;
+ fsl,fman-oh-port = <&fman0_oh2>;
+ };
+ dpa_fman0_oh3: dpa-fman0-oh@3 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x92 1 0x93 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh3>;
+ };
+ dpa_fman0_oh4: dpa-fman0-oh@4 {
+ compatible = "fsl,dpa-oh";
+ fsl,qman-frame-queues-oh = <0x94 1 0x795 1>;
+ fsl,bman-buffer-pools = <&bp9>;
+ fsl,fman-oh-port = <&fman0_oh4>;
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/t4240si-chosen-offld.dtsi b/drivers/staging/fsl_dpa_offload/dts/t4240si-chosen-offld.dtsi
new file mode 100644
index 0000000..ae36e38
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/t4240si-chosen-offld.dtsi
@@ -0,0 +1,32 @@
+chosen {
+ name = "chosen";
+
+ dpaa-extended-args {
+ fman0-extd-args {
+ cell-index = <0>;
+ compatible = "fsl,fman-extended-args";
+ dma-aid-mode = "port";
+ /* Inbound O/H post decryption */
+ fman0_oh2-extd-args {
+ cell-index = <1>;
+ compatible = "fsl,fman-port-op-extended-args";
+ errors-to-discard = <0x00420000>;
+ /* Define Virtual storage profile */
+ /* <number of profiles, default profile id> */
+ vsp-window = <8 0>;
+ };
+ /* Outbound O/H pre encryption */
+ fman0_oh3-extd-args {
+ cell-index = <2>;
+ compatible = "fsl,fman-port-op-extended-args";
+ errors-to-discard = <0x00420000>;
+ /* Define buffer layout parameters. Can be used
+ * in fragmentation or header manip operations
+ */
+ /* <manip extra space, data alignment> */
+ buffer-layout = <128 64>;
+ };
+
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/t4240si-chosen-reass.dtsi b/drivers/staging/fsl_dpa_offload/dts/t4240si-chosen-reass.dtsi
new file mode 100644
index 0000000..8decfd2
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/t4240si-chosen-reass.dtsi
@@ -0,0 +1,29 @@
+chosen {
+ name = "chosen";
+
+ dpaa-extended-args {
+ fman0-extd-args {
+ cell-index = <0>;
+ compatible = "fsl,fman-extended-args";
+ dma-aid-mode = "port";
+ fman0_rx4-extd-args {
+ cell-index = <4>;
+ compatible = "fsl,fman-port-1g-rx-extended-args";
+ errors-to-discard = <0x00020000>;
+ /* Define Virtual storage profile */
+ /* <number of profiles, default profile id> */
+ vsp-window = <8 0>;
+ };
+ fman0_oh2-extd-args {
+ cell-index = <1>;
+ compatible = "fsl,fman-port-op-extended-args";
+ errors-to-discard = <0x00420000>;
+ /* Define buffer layout parameters. Can be used
+ * in fragmentation or header manip operations
+ */
+ /* <manip extra space, data alignment> */
+ buffer-layout = <128 64>;
+ };
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/dts/t4240si-pre.dtsi b/drivers/staging/fsl_dpa_offload/dts/t4240si-pre.dtsi
new file mode 100644
index 0000000..948b87e
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/dts/t4240si-pre.dtsi
@@ -0,0 +1,175 @@
+/*
+ * T4240 Silicon/SoC Device Tree Source (pre include)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/dts-v1/;
+
+/include/ "e6500_power_isa.dtsi"
+
+/ {
+ compatible = "fsl,T4240";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ interrupt-parent = <&mpic>;
+
+ aliases {
+ ccsr = &soc;
+ dcsr = &dcsr;
+
+ serial0 = &serial0;
+ serial1 = &serial1;
+ serial2 = &serial2;
+ serial3 = &serial3;
+
+ rman = &rman;
+ lac = &lac;
+ crypto = &crypto;
+ dce = &dce;
+ pme = &pme;
+ qman = &qman;
+ bman = &bman;
+ fman0 = &fman0;
+ fman1 = &fman1;
+ ethernet0 = &enet0;
+ ethernet1 = &enet1;
+ ethernet2 = &enet2;
+ ethernet3 = &enet3;
+ ethernet4 = &enet4;
+ ethernet5 = &enet5;
+ ethernet6 = &enet6;
+ ethernet7 = &enet7;
+ ethernet8 = &enet8;
+ ethernet9 = &enet9;
+ ethernet10 = &enet10;
+ ethernet11 = &enet11;
+ ethernet12 = &enet12;
+ ethernet13 = &enet13;
+ ethernet14 = &enet14;
+ ethernet15 = &enet15;
+
+ pci0 = &pci0;
+ pci1 = &pci1;
+ pci2 = &pci2;
+ pci3 = &pci3;
+ usb0 = &usb0;
+ usb1 = &usb1;
+ dma0 = &dma0;
+ dma1 = &dma1;
+ sdhc = &sdhc;
+ };
+/include/ "t4240si-chosen.dtsi"
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /*
+ * Temporarily add next-level-cache info in each cpu node so
+ * that uboot can do L2 cache fixup. This can be removed once
+ * u-boot can create cpu node with cache info.
+ */
+ cpu0: PowerPC,e6500@0 {
+ device_type = "cpu";
+ reg = <0 1>;
+ clocks = <&mux0>;
+ next-level-cache = <&L2_1>;
+ };
+ cpu1: PowerPC,e6500@1 {
+ device_type = "cpu";
+ reg = <2 3>;
+ clocks = <&mux0>;
+ next-level-cache = <&L2_1>;
+ };
+ cpu2: PowerPC,e6500@2 {
+ device_type = "cpu";
+ reg = <4 5>;
+ clocks = <&mux0>;
+ next-level-cache = <&L2_1>;
+ };
+ cpu3: PowerPC,e6500@3 {
+ device_type = "cpu";
+ reg = <6 7>;
+ clocks = <&mux0>;
+ next-level-cache = <&L2_1>;
+ };
+
+ cpu4: PowerPC,e6500@4 {
+ device_type = "cpu";
+ reg = <8 9>;
+ clocks = <&mux1>;
+ next-level-cache = <&L2_2>;
+ };
+ cpu5: PowerPC,e6500@5 {
+ device_type = "cpu";
+ reg = <10 11>;
+ clocks = <&mux1>;
+ next-level-cache = <&L2_2>;
+ };
+ cpu6: PowerPC,e6500@6 {
+ device_type = "cpu";
+ reg = <12 13>;
+ clocks = <&mux1>;
+ next-level-cache = <&L2_2>;
+ };
+ cpu7: PowerPC,e6500@7 {
+ device_type = "cpu";
+ reg = <14 15>;
+ clocks = <&mux1>;
+ next-level-cache = <&L2_2>;
+ };
+
+ cpu8: PowerPC,e6500@8 {
+ device_type = "cpu";
+ reg = <16 17>;
+ clocks = <&mux2>;
+ next-level-cache = <&L2_3>;
+ };
+ cpu9: PowerPC,e6500@9 {
+ device_type = "cpu";
+ reg = <18 19>;
+ clocks = <&mux2>;
+ next-level-cache = <&L2_3>;
+ };
+ cpu10: PowerPC,e6500@10 {
+ device_type = "cpu";
+ reg = <20 21>;
+ clocks = <&mux2>;
+ next-level-cache = <&L2_3>;
+ };
+ cpu11: PowerPC,e6500@11 {
+ device_type = "cpu";
+ reg = <22 23>;
+ clocks = <&mux2>;
+ next-level-cache = <&L2_3>;
+ };
+ };
+};
diff --git a/drivers/staging/fsl_dpa_offload/wrp_dpa_classifier.c b/drivers/staging/fsl_dpa_offload/wrp_dpa_classifier.c
new file mode 100644
index 0000000..1e35b09
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/wrp_dpa_classifier.c
@@ -0,0 +1,3032 @@
+
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * DPA Classifier Wrapper implementation.
+ */
+
+/* DPA offloading layer includes */
+#include <linux/fsl_dpa_classifier.h>
+#include "wrp_dpa_classifier.h"
+#include "dpa_classifier_ioctl.h"
+
+/* Other includes */
+#include <linux/uaccess.h>
+#include <linux/fdtable.h>
+#include <linux/export.h>
+#include "lnxwrp_fm.h"
+#include "fm_pcd_ioctls.h"
+#include "fm_port_ioctls.h"
+#ifdef CONFIG_COMPAT
+#include "lnxwrp_ioctls_fm_compat.h"
+#endif /* CONFIG_COMPAT */
+
+
+#define COPY_KEY_PARAMS \
+do { \
+ if ((kparam.key.size <= 0) || \
+ (kparam.key.size > DPA_OFFLD_MAXENTRYKEYSIZE)) { \
+ log_err("Invalid lookup key size (%d bytes).\n", \
+ kparam.key.size); \
+ return -EINVAL; \
+ } \
+ \
+ if (copy_from_user(key_buf, kparam.key.byte, \
+ kparam.key.size)) { \
+ log_err("Read failed: lookup key.\n"); \
+ return -EBUSY; \
+ } \
+ kparam.key.byte = key_buf; \
+ \
+ if (kparam.key.mask) { \
+ if (copy_from_user(mask_buf, kparam.key.mask, \
+ kparam.key.size)) { \
+ log_err("Read failed: key mask.\n"); \
+ return -EBUSY; \
+ } \
+ \
+ kparam.key.mask = mask_buf; \
+ } \
+} while (0)
+
+#define COPY_NEW_KEY_PARAMS \
+do { \
+ if (kparam.mod_params.key) { \
+ if (copy_from_user(&new_key, \
+ kparam.mod_params.key, \
+ sizeof(struct dpa_offload_lookup_key))) { \
+ log_err("Read failed: new lookup key.\n"); \
+ return -EBUSY; \
+ } \
+ kparam.mod_params.key = &new_key; \
+ \
+ if ((kparam.mod_params.key->size <= 0) || \
+ (kparam.mod_params.key->size > \
+ DPA_OFFLD_MAXENTRYKEYSIZE)) { \
+ log_err("Invalid new lookup key size (%d " \
+ "bytes).\n", \
+ kparam.mod_params.key->size); \
+ return -EINVAL; \
+ } \
+ \
+ if (kparam.mod_params.key->byte) { \
+ if (copy_from_user(new_key_buf, \
+ kparam.mod_params.key->byte, \
+ kparam.mod_params.key->size)) { \
+ log_err("Read failed: new lookup key " \
+ "data.\n"); \
+ return -EBUSY; \
+ } \
+ kparam.mod_params.key->byte = new_key_buf; \
+ } \
+ if (kparam.mod_params.key->mask) { \
+ if (copy_from_user(new_mask_buf, \
+ kparam.mod_params.key->mask, \
+ kparam.mod_params.key->size)) { \
+ log_err("Read failed: new key mask.\n");\
+ return -EBUSY; \
+ } \
+ kparam.mod_params.key->mask = new_mask_buf; \
+ } \
+ } \
+} while (0)
+
+#ifdef DPA_CLASSIFIER_WRP_DEBUG
+#define dpa_cls_wrp_dbg(message) printk message
+#else
+#define dpa_cls_wrp_dbg(message)
+#endif /* DPA_CLASSIFIER_DEBUG */
+
+
+static long do_ioctl_table_create(unsigned long args, bool compat_mode);
+
+static long do_ioctl_table_modify_miss_action(unsigned long args,
+ bool compat_mode);
+
+static long do_ioctl_table_insert_entry(unsigned long args, bool compat_mode);
+
+static long do_ioctl_table_modify_entry_by_key(unsigned long args,
+ bool compat_mode);
+
+static long do_ioctl_table_modify_entry_by_ref(unsigned long args,
+ bool compat_mode);
+
+static long do_ioctl_table_lookup_by_key(unsigned long args, bool compat_mode);
+
+static long do_ioctl_table_lookup_by_ref(unsigned long args, bool compat_mode);
+
+static long do_ioctl_table_delete_entry_by_key(unsigned long args,
+ bool compat_mode);
+
+static long do_ioctl_table_get_stats_by_key(unsigned long args,
+ bool compat_mode);
+
+static long do_ioctl_set_remove_hm(unsigned long args,
+ bool compat_mode);
+
+static long do_ioctl_modify_remove_hm(unsigned long args,
+ bool compat_mode);
+
+static long do_ioctl_set_insert_hm(unsigned long args,
+ bool compat_mode);
+
+static long do_ioctl_modify_insert_hm(unsigned long args,
+ bool compat_mode);
+
+static long do_ioctl_set_vlan_hm(unsigned long args, bool compat_mode);
+
+static long do_ioctl_modify_vlan_hm(unsigned long args, bool compat_mode);
+
+static long do_ioctl_set_nat_hm(unsigned long args, bool compat_mode);
+
+static long do_ioctl_modify_nat_hm(unsigned long args, bool compat_mode);
+
+static long do_ioctl_set_update_hm(unsigned long args, bool compat_mode);
+
+static long do_ioctl_modify_update_hm(unsigned long args, bool compat_mode);
+
+static long do_ioctl_set_fwd_hm(unsigned long args, bool compat_mode);
+
+static long do_ioctl_modify_fwd_hm(unsigned long args, bool compat_mode);
+
+static long do_ioctl_set_mpls_hm(unsigned long args, bool compat_mode);
+
+static long do_ioctl_modify_mpls_hm(unsigned long args, bool compat_mode);
+
+static long do_ioctl_mcast_create_group(unsigned long args, bool compat_mode);
+
+static long do_ioctl_mcast_add_member(unsigned long args, bool compat_mode);
+
+void *translate_fm_pcd_handle(void *fm_pcd);
+
+static const struct file_operations dpa_classif_fops = {
+ .owner = THIS_MODULE,
+ .open = wrp_dpa_classif_open,
+ .read = wrp_dpa_classif_read,
+ .write = wrp_dpa_classif_write,
+ .unlocked_ioctl = wrp_dpa_classif_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = wrp_dpa_classif_compat_ioctl,
+#endif /* CONFIG_COMPAT */
+ .release = wrp_dpa_classif_release
+};
+
+static int dpa_cls_cdev_major = -1;
+static struct class *classifier_class;
+static struct device *classifier_dev;
+
+
+int wrp_dpa_classif_init(void)
+{
+ /* Cannot initialize the wrapper twice */
+ if (dpa_cls_cdev_major >= 0)
+ return 0;
+
+ dpa_cls_cdev_major = register_chrdev(
+ 0,
+ WRP_DPA_CLS_CDEVNAME,
+ &dpa_classif_fops);
+ if (dpa_cls_cdev_major < 0) {
+ log_err("Could not register DPA Classifier Control Device.\n");
+ return -EBUSY;
+ }
+
+ classifier_class = class_create(THIS_MODULE, WRP_DPA_CLS_CLASS_NAME);
+ if (IS_ERR(classifier_class)) {
+ log_err("Failed to create the DPA classifier class device\n");
+ unregister_chrdev(dpa_cls_cdev_major, WRP_DPA_CLS_CDEVNAME);
+ dpa_cls_cdev_major = -1;
+ return PTR_ERR(classifier_class);
+ }
+
+ classifier_dev = device_create( classifier_class,
+ NULL,
+ MKDEV(dpa_cls_cdev_major, 0),
+ NULL,
+ WRP_DPA_CLS_CDEVNAME);
+ if (IS_ERR(classifier_dev)) {
+ log_err("Failed to create the DPA Classifier device\n");
+ class_destroy(classifier_class);
+ unregister_chrdev(dpa_cls_cdev_major, WRP_DPA_CLS_CDEVNAME);
+ dpa_cls_cdev_major = -1;
+ return PTR_ERR(classifier_dev);
+ }
+
+ return 0;
+}
+
+
+int wrp_dpa_classif_exit(void)
+{
+ if (dpa_cls_cdev_major < 0)
+ return 0;
+
+ device_destroy(classifier_class, MKDEV(dpa_cls_cdev_major, 0));
+ class_destroy(classifier_class);
+
+ unregister_chrdev(dpa_cls_cdev_major, WRP_DPA_CLS_CDEVNAME);
+
+ dpa_cls_cdev_major = -1;
+
+ return 0;
+}
+
+
+int wrp_dpa_classif_open(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+
+int wrp_dpa_classif_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+
+ssize_t wrp_dpa_classif_read(
+ struct file *filp,
+ char __user *buf,
+ size_t len,
+ loff_t *offp)
+{
+ return 0;
+}
+
+
+ssize_t wrp_dpa_classif_write(
+ struct file *filp,
+ const char __user *buf,
+ size_t len,
+ loff_t *offp)
+{
+ return 0;
+}
+
+
+#ifdef CONFIG_COMPAT
+long wrp_dpa_classif_compat_ioctl(
+ struct file *filp,
+ unsigned int cmd,
+ unsigned long args)
+{
+ return wrp_dpa_classif_do_ioctl(filp, cmd, args, true);
+}
+#endif /* CONFIG_COMPAT */
+
+
+long wrp_dpa_classif_ioctl(
+ struct file *filp,
+ unsigned int cmd,
+ unsigned long args)
+{
+ return wrp_dpa_classif_do_ioctl(filp, cmd, args, false);
+}
+
+
+long wrp_dpa_classif_do_ioctl(
+ struct file *filp,
+ unsigned int cmd,
+ unsigned long args,
+ bool compat_mode)
+{
+ long ret = 0;
+
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) --> Processing ioctl "
+ "cmd=0x%x\n", __func__, __LINE__, cmd));
+
+ switch (cmd) {
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_TBL_CREATE:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_TBL_CREATE:
+ ret = do_ioctl_table_create(args, compat_mode);
+ break;
+
+ case DPA_CLS_IOC_TBL_FREE:
+ ret = dpa_classif_table_free((int)args);
+ break;
+
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_TBL_MODIFY_MISS_ACTION:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_TBL_MODIFY_MISS_ACTION:
+ ret = do_ioctl_table_modify_miss_action(args, compat_mode);
+ break;
+
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_TBL_INSERT_ENTRY:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_TBL_INSERT_ENTRY:
+ ret = do_ioctl_table_insert_entry(args, compat_mode);
+ break;
+
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_TBL_MODIFY_ENTRY_BY_KEY:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_TBL_MODIFY_ENTRY_BY_KEY:
+ ret = do_ioctl_table_modify_entry_by_key(args, compat_mode);
+ break;
+
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_TBL_MODIFY_ENTRY_BY_REF:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_TBL_MODIFY_ENTRY_BY_REF:
+ ret = do_ioctl_table_modify_entry_by_ref(args, compat_mode);
+ break;
+
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_TBL_DELETE_ENTRY_BY_KEY:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_TBL_DELETE_ENTRY_BY_KEY:
+ ret = do_ioctl_table_delete_entry_by_key(args, compat_mode);
+ break;
+
+ case DPA_CLS_IOC_TBL_DELETE_ENTRY_BY_REF:
+ {
+ struct ioc_dpa_cls_tbl_entry_by_ref param;
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d): "
+ "delete_entry_by_ref\n", __func__, __LINE__));
+
+ /* Prepare arguments */
+ if (copy_from_user(&param, (void *) args, sizeof(param))) {
+ log_err("Read failed: "
+ "dpa_classif_table_delete_entry_by_ref user "
+ "space args.\n");
+ return -EBUSY;
+ }
+
+ /* Call function */
+ ret = dpa_classif_table_delete_entry_by_ref(param.td,
+ param.entry_id);
+
+ break;
+ }
+
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_TBL_LOOKUP_BY_KEY:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_TBL_LOOKUP_BY_KEY:
+ ret = do_ioctl_table_lookup_by_key(args, compat_mode);
+ break;
+
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_TBL_LOOKUP_BY_REF:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_TBL_LOOKUP_BY_REF:
+ ret = do_ioctl_table_lookup_by_ref(args, compat_mode);
+ break;
+
+ case DPA_CLS_IOC_TBL_FLUSH:
+ ret = dpa_classif_table_flush((int)args);
+ break;
+
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_TBL_GET_STATS_BY_KEY:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_TBL_GET_STATS_BY_KEY:
+ ret = do_ioctl_table_get_stats_by_key(args, compat_mode);
+ break;
+
+ case DPA_CLS_IOC_TBL_GET_STATS_BY_REF:
+ {
+ struct ioc_dpa_cls_tbl_entry_stats_by_ref param;
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d): "
+ "get_stats_by_ref\n", __func__, __LINE__));
+
+ /* Prepare arguments */
+ if (copy_from_user(&param, (void *) args, sizeof(param))) {
+ log_err("Read failed: "
+ "dpa_classif_table_get_entry_stats_by_ref user "
+ "space args.\n");
+ return -EBUSY;
+ }
+
+ /* Call function */
+ ret = dpa_classif_table_get_entry_stats_by_ref(param.td,
+ param.entry_id,
+ &param.stats);
+ if (ret < 0)
+ return ret;
+
+ /* Return results to user space */
+ if (copy_to_user((void *) args, &param, sizeof(param))) {
+ log_err("Write failed: "
+ "dpa_classif_table_get_entry_stats_by_ref "
+ "result.\n");
+ return -EBUSY;
+ }
+
+ break;
+ }
+
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_TBL_GET_PARAMS:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_TBL_GET_PARAMS:
+ {
+ struct ioc_dpa_cls_tbl_params kparam;
+#ifdef CONFIG_COMPAT
+ struct compat_ioc_dpa_cls_tbl_params uparam;
+
+ /* Prepare arguments */
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args,
+ sizeof(uparam))) {
+ log_err("Read failed: "
+ "dpa_classif_table_lookup_by_key user "
+ "space args.\n");
+ return -EBUSY;
+ }
+
+ /* Transfer the data into the kernel space params: */
+ kparam.td = uparam.td;
+ } else
+#endif /* CONFIG_COMPAT */
+ /* Prepare arguments */
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: "
+ "dpa_classif_table_lookup_by_key user space "
+ "args.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d): "
+ "table_get_params\n", __func__, __LINE__));
+
+ /* Call function */
+ ret = dpa_classif_table_get_params(kparam.td,
+ &kparam.table_params);
+ if (ret < 0)
+ return ret;
+
+#ifdef CONFIG_COMPAT
+ if (compat_mode) {
+ ret = dpa_cls_tbl_params_rcompatcpy(&uparam, &kparam);
+ if (ret < 0)
+ return ret;
+
+ if (copy_to_user((void *) args, &uparam, sizeof(uparam))) {
+ log_err("Write failed: "
+ "dpa_classif_table_get_params result.\n");
+ return -EBUSY;
+ }
+ } else
+#endif /* CONFIG_COMPAT */
+ /* Return results to user space */
+ if (copy_to_user((void *) args, &kparam, sizeof(kparam))) {
+ log_err("Write failed: "
+ "dpa_classif_table_get_params result.\n");
+ return -EBUSY;
+ }
+
+ break;
+ }
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_SET_REMOVE_HM:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_SET_REMOVE_HM:
+ ret = do_ioctl_set_remove_hm(args, compat_mode);
+ break;
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_MODIFY_REMOVE_HM:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_MODIFY_REMOVE_HM:
+ ret = do_ioctl_modify_remove_hm(args, compat_mode);
+ break;
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_SET_INSERT_HM:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_SET_INSERT_HM:
+ ret = do_ioctl_set_insert_hm(args, compat_mode);
+ break;
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_MODIFY_INSERT_HM:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_MODIFY_INSERT_HM:
+ ret = do_ioctl_modify_insert_hm(args, compat_mode);
+ break;
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_SET_VLAN_HM:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_SET_VLAN_HM:
+ ret = do_ioctl_set_vlan_hm(args, compat_mode);
+ break;
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_MODIFY_VLAN_HM:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_MODIFY_VLAN_HM:
+ ret = do_ioctl_modify_vlan_hm(args, compat_mode);
+ break;
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_SET_NAT_HM:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_SET_NAT_HM:
+ ret = do_ioctl_set_nat_hm(args, compat_mode);
+ break;
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_MODIFY_NAT_HM:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_MODIFY_NAT_HM:
+ ret = do_ioctl_modify_nat_hm(args, compat_mode);
+ break;
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_SET_UPDATE_HM:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_SET_UPDATE_HM:
+ ret = do_ioctl_set_update_hm(args, compat_mode);
+ break;
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_MODIFY_UPDATE_HM:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_MODIFY_UPDATE_HM:
+ ret = do_ioctl_modify_update_hm(args, compat_mode);
+ break;
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_SET_FWD_HM:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_SET_FWD_HM:
+ ret = do_ioctl_set_fwd_hm(args, compat_mode);
+ break;
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_MODIFY_FWD_HM:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_MODIFY_FWD_HM:
+ ret = do_ioctl_modify_fwd_hm(args, compat_mode);
+ break;
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_SET_MPLS_HM:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_SET_MPLS_HM:
+ ret = do_ioctl_set_mpls_hm(args, compat_mode);
+ break;
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_MODIFY_MPLS_HM:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_MODIFY_MPLS_HM:
+ ret = do_ioctl_modify_mpls_hm(args, compat_mode);
+ break;
+ case DPA_CLS_IOC_FREE_HM:
+ ret = dpa_classif_free_hm((int)args);
+ break;
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_MCAST_CREATE_GROUP:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_MCAST_CREATE_GROUP:
+ ret = do_ioctl_mcast_create_group(args, compat_mode);
+ break;
+#ifdef CONFIG_COMPAT
+ case DPA_CLS_IOC_COMPAT_MCAST_ADD_MEMBER:
+#endif /* CONFIG_COMPAT */
+ case DPA_CLS_IOC_MCAST_ADD_MEMBER:
+ ret = do_ioctl_mcast_add_member(args, compat_mode);
+ break;
+ case DPA_CLS_IOC_MCAST_REMOVE_MEMBER: {
+ struct ioc_dpa_cls_mcast_remove_params params;
+ int sz;
+ sz = sizeof(struct ioc_dpa_cls_mcast_remove_params);
+ if (copy_from_user(&params,
+ (struct ioc_dpa_cls_mcast_remove_params *)args,
+ sz)) {
+ log_err("Could not copy parameters.\n");
+ return -EINVAL;
+ }
+#if (DPAA_VERSION >= 11)
+ ret = dpa_classif_mcast_remove_member(params.grpd,
+ params.md);
+#else
+ log_err("Multicast not supported on this platform.\n");
+ ret = -EINVAL;
+ return ret;
+#endif
+ break;
+ }
+ case DPA_CLS_IOC_MCAST_FREE_GROUP: {
+ int grpd;
+ if (copy_from_user(&grpd, (int *)args, sizeof(int))) {
+ log_err("Could not copy parameters.\n");
+ return -EINVAL;
+ }
+#if (DPAA_VERSION >= 11)
+ ret = dpa_classif_mcast_free_group(grpd);
+ if (ret < 0)
+ return ret;
+#else
+ log_err("Multicast not supported on this platform.\n");
+ ret = -EINVAL;
+ return ret;
+#endif
+ break;
+ }
+ default:
+ log_err("DPA Classifier ioctl command (0x%x) not supported.\n",
+ cmd);
+ return -EINVAL;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d): Done <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+
+static long do_ioctl_table_create(unsigned long args, bool compat_mode)
+{
+ long ret = 0;
+ struct ioc_dpa_cls_tbl_params kparam;
+#ifdef CONFIG_COMPAT
+ struct compat_ioc_dpa_cls_tbl_params uparam;
+
+ /* Prepare arguments */
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ memset(&kparam, 0, sizeof(struct ioc_dpa_cls_tbl_params));
+ /* Transfer the data into the kernel space params: */
+ ret = dpa_cls_tbl_params_compatcpy(&kparam, &uparam);
+ if (ret < 0)
+ return ret;
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__,
+ __LINE__));
+
+ /* Call function */
+ ret = dpa_classif_table_create(&kparam.table_params,
+ &kparam.td);
+ if (ret < 0)
+ return ret;
+
+ /* Return results to user space */
+#ifdef CONFIG_COMPAT
+ if (compat_mode) {
+ uparam.td = kparam.td;
+ if (copy_to_user((void *) args, &uparam, sizeof(uparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_to_user((void *) args, &kparam, sizeof(kparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+
+static long do_ioctl_set_remove_hm(unsigned long args, bool compat_mode)
+{
+ long ret = 0;
+ struct ioc_dpa_cls_hm_remove_params kparam;
+ struct dpa_cls_hm_remove_resources *p_res = NULL;
+#ifdef CONFIG_COMPAT
+ struct compat_ioc_dpa_cls_hm_remove_params uparam;
+
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ /* Transfer the data into the kernel space params: */
+ ret = dpa_cls_hm_remove_params_compatcpy(&kparam, &uparam);
+ if (ret < 0)
+ return ret;
+
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__,
+ __LINE__));
+
+ if (kparam.res.remove_node)
+ p_res = &kparam.res;
+
+ /* Translate FM_PCD file descriptor */
+ if (!p_res) {
+ kparam.rm_params.fm_pcd =
+ translate_fm_pcd_handle(kparam.rm_params.fm_pcd);
+ if (!kparam.rm_params.fm_pcd)
+ return -EINVAL;
+ }
+
+ ret = dpa_classif_set_remove_hm(&kparam.rm_params, kparam.next_hmd,
+ &kparam.hmd, kparam.chain_head,
+ p_res);
+ if (ret < 0)
+ return ret;
+
+ /* Return results to user space */
+#ifdef CONFIG_COMPAT
+ if (compat_mode) {
+ uparam.hmd = kparam.hmd;
+ if (copy_to_user((void *) args, &uparam, sizeof(uparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_to_user((void *) args, &kparam, sizeof(kparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+
+static long do_ioctl_modify_remove_hm(unsigned long args, bool compat_mode)
+{
+ struct ioc_dpa_cls_hm_remove_params kparam;
+#ifdef CONFIG_COMPAT
+ long ret = 0;
+ struct compat_ioc_dpa_cls_hm_remove_params uparam;
+
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ /* Transfer the data into the kernel space params: */
+ ret = dpa_cls_hm_remove_params_compatcpy(&kparam, &uparam);
+ if (ret < 0)
+ return ret;
+
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d)\n", __func__,
+ __LINE__));
+
+ return dpa_classif_modify_remove_hm(kparam.hmd, &kparam.rm_params,
+ kparam.modify_flags);
+}
+
+static long do_ioctl_set_insert_hm(unsigned long args, bool compat_mode)
+{
+ long ret = 0;
+ struct ioc_dpa_cls_hm_insert_params kparam;
+ struct dpa_cls_hm_insert_resources *p_res = NULL;
+ uint8_t *data = NULL;
+ uint8_t sz;
+#ifdef CONFIG_COMPAT
+ struct compat_ioc_dpa_cls_hm_insert_params uparam;
+
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ /* Transfer the data into the kernel space params: */
+ ret = dpa_cls_hm_insert_params_compatcpy(&kparam, &uparam);
+ if (ret < 0)
+ return ret;
+
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: space args.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__,
+ __LINE__));
+
+ if (kparam.res.insert_node)
+ p_res = &kparam.res;
+
+ /* Translate FM_PCD file descriptor */
+ if (!p_res) {
+ kparam.ins_params.fm_pcd =
+ translate_fm_pcd_handle(kparam.ins_params.fm_pcd);
+ if (!kparam.ins_params.fm_pcd)
+ return -EINVAL;
+ }
+
+ if (kparam.ins_params.type == DPA_CLS_HM_INSERT_CUSTOM) {
+ sz = kparam.ins_params.custom.size;
+ data = kzalloc(sz * sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ log_err("Failed to allocate memory for data param for "
+ "DPA_CLS_HM_INSERT_CUSTOM parameter type.\n");
+ return -ENOMEM;
+ }
+
+ copy_from_user(data, kparam.ins_params.custom.data, sz);
+ kparam.ins_params.custom.data = data;
+ }
+
+ ret = dpa_classif_set_insert_hm(&kparam.ins_params, kparam.next_hmd,
+ &kparam.hmd, kparam.chain_head,
+ p_res);
+ kfree(data);
+ if (ret < 0)
+ return ret;
+
+#ifdef CONFIG_COMPAT
+ if (compat_mode) {
+ uparam.hmd = kparam.hmd;
+ if (copy_to_user((void *) args, &uparam, sizeof(uparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_to_user((void *) args, &kparam, sizeof(kparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+
+static long do_ioctl_modify_insert_hm(unsigned long args, bool compat_mode)
+{
+ long ret = 0;
+ struct ioc_dpa_cls_hm_insert_params kparam;
+ uint8_t *data = NULL;
+ uint8_t sz;
+#ifdef CONFIG_COMPAT
+ struct compat_ioc_dpa_cls_hm_insert_params uparam;
+
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ /* Transfer the data into the kernel space params: */
+ ret = dpa_cls_hm_insert_params_compatcpy(&kparam, &uparam);
+ if (ret < 0)
+ return ret;
+
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__,
+ __LINE__));
+
+ if (kparam.ins_params.type == DPA_CLS_HM_INSERT_CUSTOM) {
+ sz = kparam.ins_params.custom.size;
+ data = kzalloc(sz * sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ log_err("Failed to allocate memory for data param for "
+ "DPA_CLS_HM_INSERT_CUSTOM parameter type.\n");
+ return -ENOMEM;
+ }
+
+ copy_from_user(data, kparam.ins_params.custom.data, sz);
+ kparam.ins_params.custom.data = data;
+ }
+
+ ret = dpa_classif_modify_insert_hm(kparam.hmd, &kparam.ins_params,
+ kparam.modify_flags);
+ kfree(data);
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+
+static long do_ioctl_set_vlan_hm(unsigned long args, bool compat_mode)
+{
+ long ret = 0;
+ struct ioc_dpa_cls_hm_vlan_params kparam;
+ struct dpa_cls_hm_vlan_resources *p_res = NULL;
+#ifdef CONFIG_COMPAT
+ struct compat_ioc_dpa_cls_hm_vlan_params uparam;
+
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ /* Transfer the data into the kernel space params: */
+ ret = dpa_cls_hm_vlan_params_compatcpy(&kparam, &uparam);
+ if (ret < 0)
+ return ret;
+
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__,
+ __LINE__));
+
+ if (kparam.res.vlan_node)
+ p_res = &kparam.res;
+
+ /* Translate FM_PCD file descriptor */
+ if (!p_res) {
+ kparam.vlan_params.fm_pcd =
+ translate_fm_pcd_handle(kparam.vlan_params.fm_pcd);
+ if (!kparam.vlan_params.fm_pcd)
+ return -EINVAL;
+ }
+
+ ret = dpa_classif_set_vlan_hm(&kparam.vlan_params, kparam.next_hmd,
+ &kparam.hmd, kparam.chain_head,
+ p_res);
+ if (ret < 0)
+ return ret;
+
+#ifdef CONFIG_COMPAT
+ if (compat_mode) {
+ uparam.hmd = kparam.hmd;
+ if (copy_to_user((void *) args, &uparam, sizeof(uparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_to_user((void *) args, &kparam, sizeof(kparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+
+}
+
+static long do_ioctl_modify_vlan_hm(unsigned long args, bool compat_mode)
+{
+ struct ioc_dpa_cls_hm_vlan_params kparam;
+#ifdef CONFIG_COMPAT
+ long ret = 0;
+ struct compat_ioc_dpa_cls_hm_vlan_params uparam;
+
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ /* Transfer the data into the kernel space params: */
+ ret = dpa_cls_hm_vlan_params_compatcpy(&kparam, &uparam);
+ if (ret < 0)
+ return ret;
+
+ } else
+#endif
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d)\n", __func__,
+ __LINE__));
+
+ return dpa_classif_modify_vlan_hm(kparam.hmd, &kparam.vlan_params,
+ kparam.modify_flags);
+}
+
+static long do_ioctl_set_nat_hm(unsigned long args, bool compat_mode)
+{
+ long ret = 0;
+ struct ioc_dpa_cls_hm_nat_params kparam;
+ struct dpa_cls_hm_nat_resources *p_res = NULL;
+ int type;
+ unsigned int sz;
+ uint8_t *options = NULL;
+#ifdef CONFIG_COMPAT
+ struct compat_ioc_dpa_cls_hm_nat_params uparam;
+
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ /* Transfer the data into the kernel space params: */
+ ret = dpa_cls_hm_nat_params_compatcpy(&kparam, &uparam);
+ if (ret < 0)
+ return ret;
+
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__,
+ __LINE__));
+
+ if (kparam.res.l3_update_node || kparam.res.l4_update_node)
+ p_res = &kparam.res;
+
+ /* Translate FM_PCD file descriptor */
+ if (!p_res) {
+ kparam.nat_params.fm_pcd =
+ translate_fm_pcd_handle(kparam.nat_params.fm_pcd);
+ if (!kparam.nat_params.fm_pcd)
+ return -EINVAL;
+ }
+
+ if (kparam.nat_params.type == DPA_CLS_HM_NAT_TYPE_NAT_PT) {
+ type = kparam.nat_params.nat_pt.type;
+ if (type == DPA_CLS_HM_NAT_PT_IPv6_TO_IPv4) {
+ sz = kparam.nat_params.nat_pt.new_header.ipv4.
+ options_size;
+ options = kzalloc(sz * sizeof(*options), GFP_KERNEL);
+ if (!options) {
+ log_err("Failed to allocate memory for "
+ "options param for "
+ "DPA_CLS_HM_NAT_TYPE_NAT_PT parameter "
+ "type.\n");
+ return -ENOMEM;
+ }
+ copy_from_user(options,
+ kparam.nat_params.nat_pt.new_header.
+ ipv4.options, sz);
+ kparam.nat_params.nat_pt.new_header.ipv4.options =
+ options;
+ }
+ }
+
+ ret = dpa_classif_set_nat_hm(&kparam.nat_params, kparam.next_hmd,
+ &kparam.hmd, kparam.chain_head,
+ p_res);
+ kfree(options);
+ if (ret < 0)
+ return ret;
+
+#ifdef CONFIG_COMPAT
+ if (compat_mode) {
+ uparam.hmd = kparam.hmd;
+ if (copy_to_user((void *) args, &uparam, sizeof(uparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_to_user((void *) args, &kparam, sizeof(kparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+
+static long do_ioctl_modify_nat_hm(unsigned long args, bool compat_mode)
+{
+ struct ioc_dpa_cls_hm_nat_params kparam;
+ uint8_t *options = NULL;
+ long ret = 0;
+ int type;
+ unsigned int sz;
+#ifdef CONFIG_COMPAT
+ struct compat_ioc_dpa_cls_hm_nat_params uparam;
+
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ /* Transfer the data into the kernel space params: */
+ ret = dpa_cls_hm_nat_params_compatcpy(&kparam, &uparam);
+ if (ret < 0)
+ return ret;
+
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ if (kparam.nat_params.type == DPA_CLS_HM_NAT_TYPE_NAT_PT) {
+ type = kparam.nat_params.nat_pt.type;
+ if (type == DPA_CLS_HM_NAT_PT_IPv6_TO_IPv4) {
+ sz = kparam.nat_params.nat_pt.new_header.ipv4.
+ options_size;
+ options = kzalloc(sz * sizeof(*options), GFP_KERNEL);
+ if (!options) {
+ log_err("Failed to allocate memory for "
+ "options param for "
+ "DPA_CLS_HM_NAT_TYPE_NAT_PT parameter "
+ "type.\n");
+ return -ENOMEM;
+ }
+ copy_from_user(options,
+ kparam.nat_params.nat_pt.new_header.
+ ipv4.options, sz);
+ kparam.nat_params.nat_pt.new_header.ipv4.options =
+ options;
+ }
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d)\n", __func__,
+ __LINE__));
+
+ ret = dpa_classif_modify_nat_hm(kparam.hmd, &kparam.nat_params,
+ kparam.modify_flags);
+ kfree(options);
+
+ return ret;
+}
+
+static long do_ioctl_set_update_hm(unsigned long args, bool compat_mode)
+{
+ long ret = 0;
+ struct ioc_dpa_cls_hm_update_params kparam;
+ struct dpa_cls_hm_update_resources *p_res = NULL;
+ unsigned int sz;
+ uint8_t *options = NULL;
+#ifdef CONFIG_COMPAT
+ struct compat_ioc_dpa_cls_hm_update_params uparam;
+
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ /* Transfer the data into the kernel space params: */
+ ret = dpa_cls_hm_update_params_compatcpy(&kparam, &uparam);
+ if (ret < 0)
+ return ret;
+
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__,
+ __LINE__));
+
+ if (kparam.res.ip_frag_node || kparam.res.update_node)
+ p_res = &kparam.res;
+
+ /* Translate FM_PCD file descriptor */
+ if (!p_res) {
+ kparam.update_params.fm_pcd =
+ translate_fm_pcd_handle(kparam.update_params.fm_pcd);
+ if (!kparam.update_params.fm_pcd)
+ return -EINVAL;
+ }
+
+ if (kparam.update_params.op_flags == DPA_CLS_HM_REPLACE_IPv6_BY_IPv4) {
+ sz = kparam.update_params.replace.new_ipv4_hdr.options_size;
+ options = kzalloc(sz * sizeof(*options), GFP_KERNEL);
+ if (!options) {
+ log_err("Failed to allocate memory for options param "
+ "for DPA_CLS_HM_REPLACE_IPv6_BY_IPv4 "
+ "parameter type.\n");
+ return -ENOMEM;
+ }
+
+ copy_from_user(options,
+ kparam.update_params.replace.new_ipv4_hdr.
+ options, sz);
+ kparam.update_params.replace.new_ipv4_hdr.options = options;
+ }
+
+ ret = dpa_classif_set_update_hm(&kparam.update_params, kparam.next_hmd,
+ &kparam.hmd, kparam.chain_head,
+ p_res);
+ kfree(options);
+ if (ret < 0)
+ return ret;
+
+#ifdef CONFIG_COMPAT
+ if (compat_mode) {
+ uparam.hmd = kparam.hmd;
+ if (copy_to_user((void *) args, &uparam, sizeof(uparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_to_user((void *) args, &kparam, sizeof(kparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+
+static long do_ioctl_modify_update_hm(unsigned long args, bool compat_mode)
+{
+ struct ioc_dpa_cls_hm_update_params kparam;
+ uint8_t *options = NULL;
+ long ret = 0;
+ unsigned int sz;
+#ifdef CONFIG_COMPAT
+ struct compat_ioc_dpa_cls_hm_update_params uparam;
+
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ /* Transfer the data into the kernel space params: */
+ ret = dpa_cls_hm_update_params_compatcpy(&kparam, &uparam);
+ if (ret < 0)
+ return ret;
+
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d)\n", __func__,
+ __LINE__));
+
+ if (kparam.update_params.op_flags == DPA_CLS_HM_REPLACE_IPv6_BY_IPv4) {
+ sz = kparam.update_params.replace.new_ipv4_hdr.options_size;
+ options = kzalloc(sz * sizeof(*options), GFP_KERNEL);
+ if (!options) {
+ log_err("Failed to allocate memory for options param "
+ "for DPA_CLS_HM_REPLACE_IPv6_BY_IPv4 "
+ "parameter type.\n");
+ return -ENOMEM;
+ }
+
+ copy_from_user(options,
+ kparam.update_params.replace.new_ipv4_hdr.
+ options, sz);
+ kparam.update_params.replace.new_ipv4_hdr.options = options;
+ }
+
+ ret = dpa_classif_modify_update_hm(kparam.hmd, &kparam.update_params,
+ kparam.modify_flags);
+
+ kfree(options);
+
+ return ret;
+}
+
+static long do_ioctl_set_fwd_hm(unsigned long args, bool compat_mode)
+{
+ long ret = 0;
+ struct ioc_dpa_cls_hm_fwd_params kparam;
+ struct dpa_cls_hm_fwd_resources *p_res = NULL;
+#ifdef CONFIG_COMPAT
+ struct compat_ioc_dpa_cls_hm_fwd_params uparam;
+
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ /* Transfer the data into the kernel space params: */
+ ret = dpa_cls_hm_fwd_params_compatcpy(&kparam, &uparam);
+ if (ret < 0)
+ return ret;
+
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__,
+ __LINE__));
+
+ if (kparam.res.ip_frag_node || kparam.res.fwd_node ||
+ kparam.res.pppoe_node)
+ p_res = &kparam.res;
+
+ /* Translate FM_PCD file descriptor */
+ if (!p_res) {
+ kparam.fwd_params.fm_pcd =
+ translate_fm_pcd_handle(kparam.fwd_params.fm_pcd);
+ if (!kparam.fwd_params.fm_pcd)
+ return -EINVAL;
+ }
+
+ ret = dpa_classif_set_fwd_hm(&kparam.fwd_params, kparam.next_hmd,
+ &kparam.hmd, kparam.chain_head,
+ p_res);
+ if (ret < 0)
+ return ret;
+
+#ifdef CONFIG_COMPAT
+ if (compat_mode) {
+ uparam.hmd = kparam.hmd;
+ if (copy_to_user((void *) args, &uparam, sizeof(uparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_to_user((void *) args, &kparam, sizeof(kparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+
+static long do_ioctl_modify_fwd_hm(unsigned long args, bool compat_mode)
+{
+ struct ioc_dpa_cls_hm_fwd_params kparam;
+#ifdef CONFIG_COMPAT
+ long ret = 0;
+ struct compat_ioc_dpa_cls_hm_fwd_params uparam;
+
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ /* Transfer the data into the kernel space params: */
+ ret = dpa_cls_hm_fwd_params_compatcpy(&kparam, &uparam);
+ if (ret < 0)
+ return ret;
+
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d)\n", __func__,
+ __LINE__));
+
+ return dpa_classif_modify_fwd_hm(kparam.hmd, &kparam.fwd_params,
+ kparam.modify_flags);
+}
+
+static long do_ioctl_set_mpls_hm(unsigned long args, bool compat_mode)
+{
+ long ret = 0;
+ struct ioc_dpa_cls_hm_mpls_params kparam;
+ struct dpa_cls_hm_mpls_resources *p_res = NULL;
+#ifdef CONFIG_COMPAT
+ struct compat_ioc_dpa_cls_hm_mpls_params uparam;
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ /* Transfer the data into the kernel space params: */
+ ret = dpa_cls_hm_mpls_params_compatcpy(&kparam, &uparam);
+ if (ret < 0)
+ return ret;
+
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__,
+ __LINE__));
+
+ if (kparam.res.ins_rm_node)
+ p_res = &kparam.res;
+
+ /* Translate FM_PCD file descriptor */
+ if (!p_res) {
+ kparam.mpls_params.fm_pcd =
+ translate_fm_pcd_handle(kparam.mpls_params.fm_pcd);
+ if (!kparam.mpls_params.fm_pcd)
+ return -EINVAL;
+ }
+
+ ret = dpa_classif_set_mpls_hm(&kparam.mpls_params, kparam.next_hmd,
+ &kparam.hmd, kparam.chain_head,
+ p_res);
+ if (ret < 0)
+ return ret;
+
+#ifdef CONFIG_COMPAT
+ if (compat_mode) {
+ uparam.hmd = kparam.hmd;
+ if (copy_to_user((void *) args, &uparam, sizeof(uparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_to_user((void *) args, &kparam, sizeof(kparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+
+static long do_ioctl_modify_mpls_hm(unsigned long args, bool compat_mode)
+{
+ struct ioc_dpa_cls_hm_mpls_params kparam;
+#ifdef CONFIG_COMPAT
+ long ret = 0;
+ struct compat_ioc_dpa_cls_hm_mpls_params uparam;
+
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ /* Transfer the data into the kernel space params: */
+ ret = dpa_cls_hm_mpls_params_compatcpy(&kparam, &uparam);
+ if (ret < 0)
+ return ret;
+
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d)\n", __func__,
+ __LINE__));
+
+ return dpa_classif_modify_mpls_hm(kparam.hmd, &kparam.mpls_params,
+ kparam.modify_flags);
+}
+
+static long do_ioctl_mcast_create_group(unsigned long args, bool compat_mode)
+{
+ long ret = 0;
+ struct ioc_dpa_cls_mcast_group_params kparam;
+ struct dpa_cls_tbl_policer_params policer_params;
+ struct dpa_cls_mcast_group_resources *p_res = NULL;
+#ifdef CONFIG_COMPAT
+ struct compat_ioc_dpa_cls_mcast_group_params uparam;
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ kparam.mcast_grp_params.first_member_params.policer_params =
+ &policer_params;
+ /*
+ * Transfer the data into the kernel space params:
+ */
+ ret = dpa_cls_mcast_group_params_compatcpy(&kparam, &uparam);
+ if (ret < 0)
+ return ret;
+
+ } else
+#endif /* CONFIG_COMPAT */
+ {
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ if (kparam.mcast_grp_params.first_member_params.
+ policer_params) {
+ if (copy_from_user(&policer_params,
+ kparam.mcast_grp_params.
+ first_member_params.policer_params,
+ sizeof(policer_params))) {
+ log_err("Read failed: policer params.\n");
+ return -EBUSY;
+ }
+ kparam.mcast_grp_params.first_member_params.
+ policer_params =
+ &policer_params;
+ }
+ }
+
+ if (kparam.res.group_node)
+ p_res = &kparam.res;
+ /*
+ * Translate FM_PCD file descriptor
+ */
+ if (!p_res) {
+ kparam.mcast_grp_params.fm_pcd =
+ translate_fm_pcd_handle(kparam.
+ mcast_grp_params.fm_pcd);
+ if (!kparam.mcast_grp_params.fm_pcd)
+ return -EINVAL;
+ }
+
+#if (DPAA_VERSION >= 11)
+ ret = dpa_classif_mcast_create_group(&kparam.mcast_grp_params,
+ &kparam.grpd, p_res);
+#else
+ log_err("Multicast not supported on this platform.\n");
+ return -EINVAL;
+#endif
+
+ if (ret < 0)
+ return ret;
+
+#ifdef CONFIG_COMPAT
+ if (compat_mode) {
+ uparam.grpd = kparam.grpd;
+ if (copy_to_user((void *) args, &uparam, sizeof(uparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_to_user((void *) args, &kparam, sizeof(kparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+
+static long do_ioctl_mcast_add_member(unsigned long args, bool compat_mode)
+{
+ long ret = 0;
+ struct ioc_dpa_cls_mcast_member_params kparam;
+ struct dpa_cls_tbl_policer_params policer_params;
+#ifdef CONFIG_COMPAT
+ struct compat_ioc_dpa_cls_mcast_member_params uparam;
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ kparam.member_params.policer_params = &policer_params;
+ /*
+ * Transfer the data into the kernel space params:
+ */
+ ret = dpa_cls_mcast_member_params_compatcpy(&kparam, &uparam);
+ if (ret < 0)
+ return ret;
+
+ } else
+#endif /* CONFIG_COMPAT */
+ {
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ if (kparam.member_params.policer_params) {
+ if (copy_from_user(&policer_params,
+ kparam.member_params.policer_params,
+ sizeof(policer_params))) {
+ log_err("Read failed: policer params.\n");
+ return -EBUSY;
+ }
+
+ kparam.member_params.policer_params = &policer_params;
+ }
+ }
+#if (DPAA_VERSION >= 11)
+ ret = dpa_classif_mcast_add_member(kparam.grpd, &kparam.member_params,
+ &kparam.md);
+ if (ret < 0)
+ return ret;
+#else
+ log_err("Multicast not supported on this platform.\n");
+ return -EINVAL;
+#endif
+
+#ifdef CONFIG_COMPAT
+ if (compat_mode) {
+ uparam.md = kparam.md;
+ if (copy_to_user((void *) args, &uparam, sizeof(uparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_to_user((void *) args, &kparam, sizeof(kparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+
+
+static long do_ioctl_table_modify_miss_action(unsigned long args,
+ bool compat_mode)
+{
+ struct ioc_dpa_cls_tbl_miss_action kparam;
+ struct dpa_cls_tbl_policer_params policer_params;
+#ifdef CONFIG_COMPAT
+ long ret = 0;
+ struct compat_ioc_dpa_cls_tbl_miss_action uparam;
+
+ /* Prepare arguments */
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ kparam.miss_action.enq_params.policer_params = &policer_params;
+ /* Transfer the data into the kernel space params: */
+ ret = dpa_cls_tbl_miss_action_params_compatcpy(&kparam,
+ &uparam);
+ if (ret < 0)
+ return ret;
+ } else
+#endif /* CONFIG_COMPAT */
+ {
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ if (kparam.miss_action.enq_params.policer_params) {
+ if (copy_from_user(&policer_params,
+ kparam.miss_action.enq_params.policer_params,
+ sizeof(policer_params))) {
+ log_err("Read failed: policer params.\n");
+ return -EBUSY;
+ }
+
+ kparam.miss_action.enq_params.policer_params =
+ &policer_params;
+ }
+ }
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d)\n", __func__,
+ __LINE__));
+
+ /* Call function */
+ return dpa_classif_table_modify_miss_action(kparam.td,
+ &kparam.miss_action);
+}
+
+static long do_ioctl_table_insert_entry(unsigned long args, bool compat_mode)
+{
+ long ret = 0;
+ struct ioc_dpa_cls_tbl_entry_params kparam;
+ struct dpa_cls_tbl_policer_params policer_params;
+ uint8_t key_buf[DPA_OFFLD_MAXENTRYKEYSIZE];
+ uint8_t mask_buf[DPA_OFFLD_MAXENTRYKEYSIZE];
+#ifdef CONFIG_COMPAT
+ struct compat_ioc_dpa_cls_tbl_entry_params uparam;
+
+ /* Prepare arguments */
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ kparam.key.byte = key_buf;
+ kparam.key.mask = mask_buf;
+ kparam.key.size = DPA_OFFLD_MAXENTRYKEYSIZE;
+
+ kparam.action.enq_params.policer_params = &policer_params;
+
+ /* Transfer the data into the kernel space params: */
+ ret = dpa_cls_tbl_entry_params_compatcpy(&kparam, &uparam);
+ if (ret < 0)
+ return ret;
+ } else
+#endif /* CONFIG_COMPAT */
+ {
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ COPY_KEY_PARAMS;
+
+ /* Check if we need to copy also the policer params */
+ if ((kparam.action.type == DPA_CLS_TBL_ACTION_ENQ) &&
+ (kparam.action.enq_params.policer_params)) {
+ if (copy_from_user(&policer_params,
+ kparam.action.enq_params.policer_params,
+ sizeof(policer_params))) {
+ log_err("Read failed: policer params.\n");
+ return -EBUSY;
+ }
+ kparam.action.enq_params.policer_params = &policer_params;
+ }
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__,
+ __LINE__));
+
+ /* Call function */
+ ret = dpa_classif_table_insert_entry(kparam.td,
+ &kparam.key,
+ &kparam.action,
+ kparam.priority,
+ &kparam.entry_id);
+ if (ret < 0)
+ return ret;
+
+ /* In case of success return results to user space */
+#ifdef CONFIG_COMPAT
+ if (compat_mode) {
+ uparam.entry_id = kparam.entry_id;
+
+ if (copy_to_user((void *) args, &uparam, sizeof(uparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_to_user((void *) args, &kparam, sizeof(kparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+
+static long do_ioctl_table_modify_entry_by_key(unsigned long args,
+ bool compat_mode)
+{
+ struct ioc_dpa_cls_tbl_entry_mod_by_key kparam;
+ struct dpa_offload_lookup_key new_key;
+ struct dpa_cls_tbl_action action;
+ struct dpa_cls_tbl_policer_params policer_params;
+ uint8_t key_buf[DPA_OFFLD_MAXENTRYKEYSIZE];
+ uint8_t new_key_buf[DPA_OFFLD_MAXENTRYKEYSIZE];
+ uint8_t mask_buf[DPA_OFFLD_MAXENTRYKEYSIZE];
+ uint8_t new_mask_buf[DPA_OFFLD_MAXENTRYKEYSIZE];
+#ifdef CONFIG_COMPAT
+ long ret = 0;
+ struct compat_ioc_dpa_cls_tbl_entry_mod_by_key uparam;
+
+ /* Prepare arguments */
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ kparam.key.byte = key_buf;
+ kparam.key.mask = mask_buf;
+ kparam.key.size = DPA_OFFLD_MAXENTRYKEYSIZE;
+
+ new_key.byte = new_key_buf;
+ new_key.mask = new_mask_buf;
+ new_key.size = DPA_OFFLD_MAXENTRYKEYSIZE;
+
+ kparam.mod_params.key = &new_key;
+ kparam.mod_params.action = &action;
+ kparam.mod_params.action->enq_params.policer_params =
+ &policer_params;
+
+ /* Transfer the data into the kernel space params: */
+ ret = dpa_cls_tbl_entry_mod_by_key_params_compatcpy(&kparam,
+ &uparam);
+ if (ret < 0)
+ return ret;
+ } else
+#endif /* CONFIG_COMPAT */
+ {
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ COPY_KEY_PARAMS;
+
+ /* Check if we need to copy the new key */
+ COPY_NEW_KEY_PARAMS;
+
+ if (kparam.mod_params.action) {
+ if (copy_from_user(&action,
+ kparam.mod_params.action,
+ sizeof(struct dpa_cls_tbl_action))) {
+ log_err("Read failed: new action params.\n");
+ return -EBUSY;
+ }
+ kparam.mod_params.action = &action;
+
+ /* Check if we need to copy policer params */
+ if ((kparam.mod_params.action->type ==
+ DPA_CLS_TBL_ACTION_ENQ) &&
+ (kparam.mod_params.action->enq_params.
+ policer_params)) {
+ if (copy_from_user(&policer_params,
+ kparam.mod_params.
+ action->enq_params.
+ policer_params,
+ sizeof(policer_params))) {
+ log_err("Read failed: new policer "
+ "params.\n");
+ return -EBUSY;
+ }
+ kparam.mod_params.action->enq_params.
+ policer_params =
+ &policer_params;
+ }
+ }
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d)\n", __func__,
+ __LINE__));
+
+ /* Call function */
+ return dpa_classif_table_modify_entry_by_key(kparam.td,
+ &kparam.key,
+ &kparam.mod_params);
+
+}
+
+static long do_ioctl_table_modify_entry_by_ref(unsigned long args,
+ bool compat_mode)
+{
+ struct ioc_dpa_cls_tbl_entry_mod_by_ref kparam;
+ struct dpa_offload_lookup_key new_key;
+ struct dpa_cls_tbl_action action;
+ struct dpa_cls_tbl_policer_params policer_params;
+ uint8_t new_key_buf[DPA_OFFLD_MAXENTRYKEYSIZE];
+ uint8_t new_mask_buf[DPA_OFFLD_MAXENTRYKEYSIZE];
+#ifdef CONFIG_COMPAT
+ long ret = 0;
+ struct compat_ioc_dpa_cls_tbl_entry_mod_by_ref uparam;
+
+ /* Prepare arguments */
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ new_key.byte = new_key_buf;
+ new_key.mask = new_mask_buf;
+ new_key.size = DPA_OFFLD_MAXENTRYKEYSIZE;
+
+ memset(&kparam, 0,
+ sizeof(struct ioc_dpa_cls_tbl_entry_mod_by_ref));
+ kparam.mod_params.key = &new_key;
+ kparam.mod_params.action = &action;
+ kparam.mod_params.action->enq_params.policer_params =
+ &policer_params;
+
+ /* Transfer the data into the kernel space params: */
+ ret = dpa_cls_tbl_entry_mod_by_ref_params_compatcpy(&kparam,
+ &uparam);
+ if (ret < 0)
+ return ret;
+ } else
+#endif /* CONFIG_COMPAT */
+ {
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ /* Check if we need to copy the new key */
+ COPY_NEW_KEY_PARAMS;
+
+ if (kparam.mod_params.action) {
+ if (copy_from_user(&action,
+ kparam.mod_params.action,
+ sizeof(struct dpa_cls_tbl_action))) {
+ log_err("Read failed: new action params.\n");
+ return -EBUSY;
+ }
+ kparam.mod_params.action = &action;
+
+ /* Check if we need to copy policer params */
+ if ((kparam.mod_params.action->type ==
+ DPA_CLS_TBL_ACTION_ENQ) &&
+ (kparam.mod_params.action->enq_params.
+ policer_params)) {
+ if (copy_from_user(&policer_params,
+ kparam.mod_params.
+ action->enq_params.
+ policer_params,
+ sizeof(policer_params))) {
+ log_err("Read failed: new policer "
+ "params.\n");
+ return -EBUSY;
+ }
+ kparam.mod_params.action->enq_params.
+ policer_params =
+ &policer_params;
+ }
+ }
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d)\n", __func__,
+ __LINE__));
+
+ /* Call function */
+ return dpa_classif_table_modify_entry_by_ref(kparam.td,
+ kparam.entry_id,
+ &kparam.mod_params);
+}
+
+static long do_ioctl_table_lookup_by_key(unsigned long args, bool compat_mode)
+{
+ long ret = 0;
+ struct ioc_dpa_cls_tbl_lookup_by_key kparam;
+ uint8_t key_buf[DPA_OFFLD_MAXENTRYKEYSIZE];
+ uint8_t mask_buf[DPA_OFFLD_MAXENTRYKEYSIZE];
+#ifdef CONFIG_COMPAT
+ struct compat_ioc_dpa_cls_tbl_lookup_by_key uparam;
+
+ /* Prepare arguments */
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ kparam.key.byte = key_buf;
+ kparam.key.mask = mask_buf;
+ kparam.key.size = DPA_OFFLD_MAXENTRYKEYSIZE;
+
+ /* Transfer the data into the kernel space params: */
+ ret = dpa_cls_tbl_lookup_by_key_params_compatcpy(&kparam,
+ &uparam);
+ if (ret < 0)
+ return ret;
+ } else
+#endif /* CONFIG_COMPAT */
+ {
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ COPY_KEY_PARAMS;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__,
+ __LINE__));
+
+ /* Call function */
+ ret = dpa_classif_table_lookup_by_key(kparam.td,
+ &kparam.key,
+ &kparam.action);
+ if (ret < 0)
+ return ret;
+
+ /* Return results to user space */
+#ifdef CONFIG_COMPAT
+ if (compat_mode) {
+ ret = dpa_cls_tbl_action_params_rcompatcpy(&uparam.action,
+ &kparam.action);
+ if (ret < 0)
+ return ret;
+
+ if (copy_to_user((void *) args, &uparam, sizeof(uparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_to_user((void *) args, &kparam, sizeof(kparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+
+static long do_ioctl_table_lookup_by_ref(unsigned long args, bool compat_mode)
+{
+ long ret = 0;
+ struct ioc_dpa_cls_tbl_lookup_by_ref kparam;
+#ifdef CONFIG_COMPAT
+ struct compat_ioc_dpa_cls_tbl_lookup_by_ref uparam;
+
+ /* Prepare arguments */
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ /* Transfer the data into the kernel space params: */
+ ret = dpa_cls_tbl_lookup_by_ref_params_compatcpy(&kparam,
+ &uparam);
+ if (ret < 0)
+ return ret;
+ } else
+#endif /* CONFIG_COMPAT */
+ /* Prepare arguments */
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__,
+ __LINE__));
+
+ /* Call function */
+ ret = dpa_classif_table_lookup_by_ref(kparam.td,
+ kparam.entry_id,
+ &kparam.action);
+ if (ret < 0)
+ return ret;
+
+ /* Return results to user space */
+#ifdef CONFIG_COMPAT
+ if (compat_mode) {
+ ret = dpa_cls_tbl_action_params_rcompatcpy(&uparam.action,
+ &kparam.action);
+ if (ret < 0)
+ return ret;
+
+ if (copy_to_user((void *)args, &uparam, sizeof(uparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_to_user((void *) args, &kparam, sizeof(kparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+
+static long do_ioctl_table_delete_entry_by_key(unsigned long args,
+ bool compat_mode)
+{
+ struct ioc_dpa_cls_tbl_entry_by_key kparam;
+ uint8_t key_buf[DPA_OFFLD_MAXENTRYKEYSIZE];
+ uint8_t mask_buf[DPA_OFFLD_MAXENTRYKEYSIZE];
+#ifdef CONFIG_COMPAT
+ long ret = 0;
+ struct compat_ioc_dpa_cls_tbl_entry_by_key uparam;
+
+ /* Prepare arguments */
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ kparam.key.byte = key_buf;
+ kparam.key.mask = mask_buf;
+ kparam.key.size = DPA_OFFLD_MAXENTRYKEYSIZE;
+
+ /* Transfer the data into the kernel space params: */
+ ret = dpa_cls_tbl_entry_by_key_params_compatcpy(&kparam,
+ &uparam);
+ if (ret < 0)
+ return ret;
+ } else
+#endif /* CONFIG_COMPAT */
+ {
+ /* Prepare arguments */
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ COPY_KEY_PARAMS;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d)\n", __func__,
+ __LINE__));
+
+ /* Call function */
+ return dpa_classif_table_delete_entry_by_key(kparam.td,
+ &kparam.key);
+}
+
+static long do_ioctl_table_get_stats_by_key(unsigned long args,
+ bool compat_mode)
+{
+ long ret = 0;
+ struct ioc_dpa_cls_tbl_entry_stats_by_key kparam;
+ uint8_t key_buf[DPA_OFFLD_MAXENTRYKEYSIZE];
+ uint8_t mask_buf[DPA_OFFLD_MAXENTRYKEYSIZE];
+#ifdef CONFIG_COMPAT
+ struct compat_ioc_dpa_cls_tbl_entry_stats_by_key uparam;
+
+ /* Prepare arguments */
+ if (compat_mode) {
+ if (copy_from_user(&uparam, (void *) args, sizeof(uparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ kparam.key.byte = key_buf;
+ kparam.key.mask = mask_buf;
+ kparam.key.size = DPA_OFFLD_MAXENTRYKEYSIZE;
+
+ /* Transfer the data into the kernel space params: */
+ ret = dpa_cls_tbl_entry_stats_by_key_params_compatcpy(&kparam,
+ &uparam);
+ if (ret < 0)
+ return ret;
+ } else
+#endif /* CONFIG_COMPAT */
+ {
+ /* Prepare arguments */
+ if (copy_from_user(&kparam, (void *) args, sizeof(kparam))) {
+ log_err("Read failed: user space args.\n");
+ return -EBUSY;
+ }
+
+ COPY_KEY_PARAMS;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) -->\n", __func__,
+ __LINE__));
+
+ /* Call function */
+ ret = dpa_classif_table_get_entry_stats_by_key(kparam.td,
+ &kparam.key,
+ &kparam.stats);
+ if (ret < 0)
+ return ret;
+
+ /* Return results to user space */
+#ifdef CONFIG_COMPAT
+ if (compat_mode) {
+ memcpy(&uparam.stats, &kparam.stats,
+ sizeof(struct dpa_cls_tbl_entry_stats));
+
+ if (copy_to_user((void *) args, &uparam, sizeof(uparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+ } else
+#endif /* CONFIG_COMPAT */
+ if (copy_to_user((void *) args, &kparam, sizeof(kparam))) {
+ log_err("Write failed: result.\n");
+ return -EBUSY;
+ }
+
+ dpa_cls_wrp_dbg(("DEBUG: classifier_wrp %s (%d) <--\n", __func__,
+ __LINE__));
+
+ return ret;
+}
+
+void *translate_fm_pcd_handle(void *fm_pcd)
+{
+ struct file *fm_pcd_file;
+ t_LnxWrpFmDev *fm_wrapper_dev;
+
+ fm_pcd_file = fcheck((unsigned long)fm_pcd);
+ if (!fm_pcd_file) {
+ log_err("Could not translate PCD handle fm_pcd=0x%p.\n",
+ fm_pcd);
+ return NULL;
+ }
+ fm_wrapper_dev = (t_LnxWrpFmDev *)fm_pcd_file->private_data;
+ BUG_ON(!fm_wrapper_dev);
+ BUG_ON(!fm_wrapper_dev->h_PcdDev);
+
+ return (void *)fm_wrapper_dev->h_PcdDev;
+}
+
+#ifdef CONFIG_COMPAT
+
+int dpa_cls_tbl_entry_by_key_params_compatcpy(
+ struct ioc_dpa_cls_tbl_entry_by_key *kparam,
+ const struct compat_ioc_dpa_cls_tbl_entry_by_key *uparam)
+{
+ kparam->td = uparam->td;
+ return dpa_lookup_key_params_compatcpy(&kparam->key, &uparam->key);
+}
+
+int dpa_cls_tbl_entry_stats_by_key_params_compatcpy(
+ struct ioc_dpa_cls_tbl_entry_stats_by_key *kparam,
+ const struct compat_ioc_dpa_cls_tbl_entry_stats_by_key *uparam)
+{
+ int err = 0;
+
+ kparam->td = uparam->td;
+
+ err = dpa_lookup_key_params_compatcpy(&kparam->key, &uparam->key);
+ if (err < 0)
+ return err;
+
+ memcpy(&kparam->stats,
+ &uparam->stats,
+ sizeof(struct dpa_cls_tbl_entry_stats));
+
+ return 0;
+}
+
+int dpa_lookup_key_params_compatcpy(
+ struct dpa_offload_lookup_key *kparam,
+ const struct compat_ioc_dpa_offld_lookup_key *uparam)
+{
+ BUG_ON(!uparam->byte);
+ BUG_ON(!kparam->byte);
+ BUG_ON(kparam->size < uparam->size);
+ BUG_ON(uparam->size <= 0);
+
+ kparam->size = uparam->size;
+ if (copy_from_user(kparam->byte, compat_ptr(uparam->byte),
+ uparam->size)) {
+ log_err("Read failed: lookup key.\n");
+ return -EBUSY;
+ }
+
+ if (compat_ptr(uparam->mask)) {
+ BUG_ON(!kparam->mask);
+ if (copy_from_user(kparam->mask, compat_ptr(uparam->mask),
+ uparam->size)) {
+ log_err("Read failed: key mask.\n");
+ return -EBUSY;
+ }
+ } else
+ kparam->mask = NULL;
+
+ return 0;
+}
+
+int dpa_cls_tbl_entry_params_compatcpy(
+ struct ioc_dpa_cls_tbl_entry_params *kparam,
+ const struct compat_ioc_dpa_cls_tbl_entry_params *uparam)
+{
+ int err;
+
+ kparam->td = uparam->td;
+ kparam->priority = uparam->priority;
+ kparam->entry_id = uparam->entry_id;
+
+ err = dpa_lookup_key_params_compatcpy(&kparam->key, &uparam->key);
+ if (err < 0)
+ return err;
+
+ return dpa_cls_tbl_action_params_compatcpy(&kparam->action,
+ &uparam->action);
+}
+
+int dpa_cls_tbl_action_params_compatcpy(
+ struct dpa_cls_tbl_action *kparam,
+ const struct dpa_cls_compat_tbl_action *uparam)
+{
+ kparam->type = uparam->type;
+ kparam->enable_statistics = uparam->enable_statistics;
+
+ switch (uparam->type) {
+ case DPA_CLS_TBL_ACTION_ENQ:
+ kparam->enq_params.override_fqid =
+ uparam->enq_params.override_fqid;
+ kparam->enq_params.new_fqid =
+ uparam->enq_params.new_fqid;
+ kparam->enq_params.hmd = uparam->enq_params.hmd;
+ kparam->enq_params.new_rel_vsp_id =
+ uparam->enq_params.new_rel_vsp_id;
+ if (compat_ptr(uparam->enq_params.policer_params)) {
+ BUG_ON(!kparam->enq_params.policer_params);
+ if (copy_from_user(kparam->enq_params.policer_params,
+ compat_ptr(uparam->enq_params.policer_params),
+ sizeof(struct dpa_cls_tbl_policer_params))) {
+ log_err("Read failed: policer params.\n");
+ return -EBUSY;
+ }
+ } else
+ kparam->enq_params.policer_params = NULL;
+ break;
+ case DPA_CLS_TBL_ACTION_NEXT_TABLE:
+ kparam->next_table_params.next_td =
+ uparam->next_table_params.next_td;
+ kparam->next_table_params.hmd = uparam->next_table_params.hmd;
+ break;
+ case DPA_CLS_TBL_ACTION_MCAST:
+ kparam->mcast_params.grpd = uparam->mcast_params.grpd;
+ kparam->mcast_params.hmd = uparam->mcast_params.hmd;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int dpa_cls_tbl_action_params_rcompatcpy(
+ struct dpa_cls_compat_tbl_action *uparam,
+ const struct dpa_cls_tbl_action *kparam)
+{
+ uparam->type = kparam->type;
+ uparam->enable_statistics = kparam->enable_statistics;
+
+ switch (kparam->type) {
+ case DPA_CLS_TBL_ACTION_ENQ:
+ uparam->enq_params.override_fqid =
+ kparam->enq_params.override_fqid;
+ uparam->enq_params.new_fqid =
+ kparam->enq_params.new_fqid;
+ uparam->enq_params.hmd = kparam->enq_params.hmd;
+ uparam->enq_params.new_rel_vsp_id =
+ kparam->enq_params.new_rel_vsp_id;
+ if (kparam->enq_params.policer_params) {
+ BUG_ON(!compat_ptr(uparam->enq_params.policer_params));
+ if (copy_to_user(
+ compat_ptr(uparam->enq_params.policer_params),
+ kparam->enq_params.policer_params,
+ sizeof(struct dpa_cls_tbl_policer_params))) {
+ log_err("Read failed: policer params.\n");
+ return -EBUSY;
+ }
+ } else
+ uparam->enq_params.policer_params = 0;
+ break;
+ case DPA_CLS_TBL_ACTION_NEXT_TABLE:
+ uparam->next_table_params.next_td =
+ kparam->next_table_params.next_td;
+ uparam->next_table_params.hmd = kparam->next_table_params.hmd;
+ break;
+ case DPA_CLS_TBL_ACTION_MCAST:
+ uparam->mcast_params.grpd = kparam->mcast_params.grpd;
+ uparam->mcast_params.hmd = kparam->mcast_params.hmd;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int dpa_cls_tbl_params_compatcpy(
+ struct ioc_dpa_cls_tbl_params *kparam,
+ const struct compat_ioc_dpa_cls_tbl_params *uparam)
+{
+ kparam->table_params.cc_node = compat_get_id2ptr(
+ uparam->table_params.cc_node,
+ FM_MAP_TYPE_PCD_NODE);
+ if (compat_ptr(uparam->table_params.distribution))
+ kparam->table_params.distribution = compat_get_id2ptr(
+ uparam->table_params.distribution,
+ FM_MAP_TYPE_PCD_NODE);
+ if (compat_ptr(uparam->table_params.classification))
+ kparam->table_params.classification = compat_get_id2ptr(
+ uparam->table_params.classification,
+ FM_MAP_TYPE_PCD_NODE);
+
+ kparam->table_params.type = uparam->table_params.type;
+ kparam->table_params.entry_mgmt = uparam->table_params.entry_mgmt;
+ kparam->table_params.prefilled_entries =
+ uparam->table_params.prefilled_entries;
+
+ switch (uparam->table_params.type) {
+ case DPA_CLS_TBL_INDEXED:
+ memcpy(&kparam->table_params.indexed_params,
+ &uparam->table_params.indexed_params,
+ sizeof(struct dpa_cls_tbl_indexed_params));
+ break;
+ case DPA_CLS_TBL_HASH:
+ memcpy(&kparam->table_params.hash_params,
+ &uparam->table_params.hash_params,
+ sizeof(struct dpa_cls_tbl_hash_params));
+
+ break;
+ case DPA_CLS_TBL_EXACT_MATCH:
+ memcpy(&kparam->table_params.exact_match_params,
+ &uparam->table_params.exact_match_params,
+ sizeof(struct dpa_cls_tbl_exact_match_params));
+
+ break;
+ }
+
+ return 0;
+}
+
+int dpa_cls_tbl_params_rcompatcpy(
+ struct compat_ioc_dpa_cls_tbl_params *uparam,
+ const struct ioc_dpa_cls_tbl_params *kparam)
+{
+ uparam->table_params.cc_node = compat_get_ptr2id(
+ kparam->table_params.cc_node,
+ FM_MAP_TYPE_PCD_NODE);
+ if (kparam->table_params.distribution)
+ uparam->table_params.distribution = compat_get_ptr2id(
+ kparam->table_params.distribution,
+ FM_MAP_TYPE_PCD_NODE);
+ if (kparam->table_params.classification)
+ uparam->table_params.classification = compat_get_ptr2id(
+ kparam->table_params.classification,
+ FM_MAP_TYPE_PCD_NODE);
+
+ uparam->table_params.type = kparam->table_params.type;
+ uparam->table_params.entry_mgmt = kparam->table_params.entry_mgmt;
+ uparam->table_params.prefilled_entries =
+ kparam->table_params.prefilled_entries;
+
+ switch (kparam->table_params.type) {
+ case DPA_CLS_TBL_INDEXED:
+ memcpy(&uparam->table_params.indexed_params,
+ &kparam->table_params.indexed_params,
+ sizeof(struct dpa_cls_tbl_indexed_params));
+ break;
+ case DPA_CLS_TBL_HASH:
+ memcpy(&uparam->table_params.hash_params,
+ &kparam->table_params.hash_params,
+ sizeof(struct dpa_cls_tbl_hash_params));
+
+ break;
+ case DPA_CLS_TBL_EXACT_MATCH:
+ memcpy(&uparam->table_params.exact_match_params,
+ &kparam->table_params.exact_match_params,
+ sizeof(struct dpa_cls_tbl_exact_match_params));
+
+ break;
+ }
+
+ return 0;
+}
+
+int dpa_cls_tbl_miss_action_params_compatcpy(
+ struct ioc_dpa_cls_tbl_miss_action *kparam,
+ const struct compat_ioc_dpa_cls_tbl_miss_action *uparam)
+{
+ kparam->td = uparam->td;
+
+ return dpa_cls_tbl_action_params_compatcpy(&kparam->miss_action,
+ &uparam->miss_action);
+}
+
+int dpa_cls_tbl_entry_mod_by_key_params_compatcpy(
+ struct ioc_dpa_cls_tbl_entry_mod_by_key *kparam,
+ const struct compat_ioc_dpa_cls_tbl_entry_mod_by_key *uparam)
+{
+ int err;
+
+ kparam->td = uparam->td;
+
+ err = dpa_lookup_key_params_compatcpy(&kparam->key, &uparam->key);
+ if (err < 0)
+ return err;
+
+ return dpa_cls_tbl_entry_mod_params_compatcpy(&kparam->mod_params,
+ &uparam->mod_params);
+}
+
+int dpa_cls_tbl_entry_mod_params_compatcpy(
+ struct dpa_cls_tbl_entry_mod_params *kparam,
+ const struct dpa_cls_compat_tbl_entry_mod_params *uparam)
+{
+ int err = 0;
+
+ kparam->type = uparam->type;
+
+ if (compat_ptr(uparam->key)) {
+ struct compat_ioc_dpa_offld_lookup_key key;
+
+ BUG_ON(!kparam->key);
+ if (copy_from_user(&key, compat_ptr(uparam->key),
+ sizeof(struct compat_ioc_dpa_offld_lookup_key))) {
+ log_err("Read failed: New key parameters.\n");
+ return -EBUSY;
+ }
+
+ err = dpa_lookup_key_params_compatcpy(kparam->key, &key);
+ } else
+ kparam->key = NULL;
+
+ if (err < 0)
+ return err;
+
+ if (compat_ptr(uparam->action)) {
+ struct dpa_cls_compat_tbl_action action;
+
+ BUG_ON(!kparam->action);
+
+ if (copy_from_user(&action, compat_ptr(uparam->action),
+ sizeof(struct dpa_cls_compat_tbl_action))) {
+ log_err("Read failed: New action parameters.\n");
+ return -EBUSY;
+ }
+
+ err = dpa_cls_tbl_action_params_compatcpy(kparam->action,
+ &action);
+ } else
+ kparam->action = NULL;
+
+ return err;
+}
+
+int dpa_cls_tbl_entry_mod_by_ref_params_compatcpy(
+ struct ioc_dpa_cls_tbl_entry_mod_by_ref *kparam,
+ const struct compat_ioc_dpa_cls_tbl_entry_mod_by_ref *uparam)
+{
+ kparam->td = uparam->td;
+ kparam->entry_id = uparam->entry_id;
+
+ return dpa_cls_tbl_entry_mod_params_compatcpy(&kparam->mod_params,
+ &uparam->mod_params);
+}
+
+int dpa_cls_tbl_lookup_by_key_params_compatcpy(
+ struct ioc_dpa_cls_tbl_lookup_by_key *kparam,
+ const struct compat_ioc_dpa_cls_tbl_lookup_by_key *uparam)
+{
+ kparam->td = uparam->td;
+
+ return dpa_lookup_key_params_compatcpy(&kparam->key, &uparam->key);
+}
+
+int dpa_cls_tbl_lookup_by_ref_params_compatcpy(
+ struct ioc_dpa_cls_tbl_lookup_by_ref *kparam,
+ const struct compat_ioc_dpa_cls_tbl_lookup_by_ref *uparam)
+{
+ kparam->td = uparam->td;
+ kparam->entry_id = uparam->entry_id;
+
+ return 0;
+}
+
+int dpa_cls_hm_remove_params_compatcpy(
+ struct ioc_dpa_cls_hm_remove_params *kparam,
+ const struct compat_ioc_dpa_cls_hm_remove_params *uparam)
+{
+ kparam->rm_params.type = uparam->rm_params.type;
+ memcpy(&kparam->rm_params.custom, &uparam->rm_params.custom,
+ sizeof(struct dpa_cls_hm_custom_rm_params));
+
+ kparam->rm_params.fm_pcd = compat_ptr(uparam->rm_params.fm_pcd);
+ kparam->next_hmd = uparam->next_hmd;
+ kparam->hmd = uparam->hmd;
+
+ if (uparam->res.remove_node)
+ kparam->res.remove_node = compat_get_id2ptr(
+ uparam->res.remove_node,
+ FM_MAP_TYPE_PCD_NODE);
+ else
+ kparam->res.remove_node = NULL;
+
+ kparam->chain_head = uparam->chain_head;
+ kparam->modify_flags = uparam->modify_flags;
+
+ return 0;
+}
+
+int dpa_cls_hm_insert_params_compatcpy(
+ struct ioc_dpa_cls_hm_insert_params *kparam,
+ const struct compat_ioc_dpa_cls_hm_insert_params *uparam)
+{
+ int type;
+
+ kparam->ins_params.type = uparam->ins_params.type;
+
+ type = kparam->ins_params.type;
+ switch (type) {
+ case DPA_CLS_HM_INSERT_CUSTOM:
+ kparam->ins_params.custom.offset = uparam->ins_params.
+ custom.offset;
+ kparam->ins_params.custom.size = uparam->ins_params.
+ custom.size;
+ kparam->ins_params.custom.data = compat_ptr(uparam->ins_params.
+ custom.data);
+ break;
+ case DPA_CLS_HM_INSERT_ETHERNET:
+ memcpy(&kparam->ins_params.eth, &uparam->ins_params.eth,
+ sizeof(struct dpa_cls_hm_eth_ins_params));
+ break;
+ case DPA_CLS_HM_INSERT_PPPoE:
+ memcpy(&kparam->ins_params.pppoe, &uparam->ins_params.pppoe,
+ sizeof(struct dpa_cls_hm_pppoe_ins_params));
+ break;
+ case DPA_CLS_HM_INSERT_PPP:
+ kparam->ins_params.ppp_pid = uparam->ins_params.ppp_pid;
+ break;
+ default:
+ break;
+ }
+
+ kparam->ins_params.fm_pcd = compat_ptr(uparam->ins_params.fm_pcd);
+ kparam->next_hmd = uparam->next_hmd;
+ kparam->hmd = uparam->hmd;
+ if (uparam->res.insert_node)
+ kparam->res.insert_node = compat_get_id2ptr(
+ uparam->res.insert_node,
+ FM_MAP_TYPE_PCD_NODE);
+ else
+ kparam->res.insert_node = NULL;
+
+ kparam->chain_head = uparam->chain_head;
+ kparam->modify_flags = uparam->modify_flags;
+
+ return 0;
+}
+
+int dpa_cls_hm_vlan_params_compatcpy(
+ struct ioc_dpa_cls_hm_vlan_params *kparam,
+ const struct compat_ioc_dpa_cls_hm_vlan_params *uparam)
+{
+ int type;
+
+ kparam->vlan_params.type = uparam->vlan_params.type;
+ type = kparam->vlan_params.type;
+ switch (type) {
+ case DPA_CLS_HM_VLAN_INGRESS:
+ memcpy(&kparam->vlan_params.ingress,
+ &uparam->vlan_params.ingress,
+ sizeof(struct dpa_cls_hm_ingress_vlan_params));
+ break;
+ case DPA_CLS_HM_VLAN_EGRESS:
+ memcpy(&kparam->vlan_params.egress,
+ &uparam->vlan_params.egress,
+ sizeof(struct dpa_cls_hm_egress_vlan_params));
+ break;
+ default:
+ break;
+ }
+
+ kparam->vlan_params.fm_pcd = compat_ptr(uparam->vlan_params.fm_pcd);
+ kparam->next_hmd = uparam->next_hmd;
+ kparam->hmd = uparam->hmd;
+
+ if (uparam->res.vlan_node)
+ kparam->res.vlan_node = compat_get_id2ptr(
+ uparam->res.vlan_node,
+ FM_MAP_TYPE_PCD_NODE);
+ else
+ kparam->res.vlan_node = NULL;
+
+ kparam->chain_head = uparam->chain_head;
+ kparam->modify_flags = uparam->modify_flags;
+
+ return 0;
+}
+
+int dpa_cls_hm_nat_params_compatcpy(
+ struct ioc_dpa_cls_hm_nat_params *kparam,
+ const struct compat_ioc_dpa_cls_hm_nat_params *uparam)
+{
+ int type;
+ kparam->nat_params.flags = uparam->nat_params.flags;
+ kparam->nat_params.proto = uparam->nat_params.proto;
+ kparam->nat_params.type = uparam->nat_params.type;
+
+ if (kparam->nat_params.type == DPA_CLS_HM_NAT_TYPE_NAT_PT) {
+ kparam->nat_params.nat_pt.type = uparam->nat_params.nat_pt.type;
+ type = kparam->nat_params.nat_pt.type;
+ switch (type) {
+ case DPA_CLS_HM_NAT_PT_IPv6_TO_IPv4:
+ kparam->nat_params.nat_pt.new_header.ipv4.options_size =
+ uparam->nat_params.nat_pt.new_header.ipv4.options_size;
+ kparam->nat_params.nat_pt.new_header.ipv4.options =
+ compat_ptr(uparam->nat_params.nat_pt.new_header.ipv4.
+ options);
+ memcpy(&kparam->nat_params.nat_pt.new_header.ipv4.
+ header, &uparam->nat_params.nat_pt.new_header.
+ ipv4.header, sizeof(struct iphdr));
+ break;
+ case DPA_CLS_HM_NAT_PT_IPv4_TO_IPv6:
+ memcpy(&kparam->nat_params.nat_pt.new_header.ipv6,
+ &uparam->nat_params.nat_pt.new_header.ipv6,
+ sizeof(struct ipv6_header));
+ break;
+ default:
+ break;
+ }
+ } else if (kparam->nat_params.type == DPA_CLS_HM_NAT_TYPE_TRADITIONAL)
+ memcpy(&kparam->nat_params.nat, &uparam->nat_params.nat,
+ sizeof(struct dpa_cls_hm_traditional_nat_params));
+
+ kparam->nat_params.fm_pcd = compat_ptr(uparam->nat_params.fm_pcd);
+ kparam->nat_params.sport = uparam->nat_params.sport;
+ kparam->nat_params.dport = uparam->nat_params.dport;
+ kparam->next_hmd = uparam->next_hmd;
+ kparam->hmd = uparam->hmd;
+
+ if (uparam->res.l3_update_node)
+ kparam->res.l3_update_node = compat_get_id2ptr(
+ uparam->res.l3_update_node,
+ FM_MAP_TYPE_PCD_NODE);
+ else
+ kparam->res.l3_update_node = NULL;
+
+ if (uparam->res.l4_update_node)
+ kparam->res.l4_update_node = compat_get_id2ptr(
+ uparam->res.l4_update_node,
+ FM_MAP_TYPE_PCD_NODE);
+ else
+ kparam->res.l4_update_node = NULL;
+
+ kparam->chain_head = uparam->chain_head;
+ kparam->modify_flags = uparam->modify_flags;
+
+ return 0;
+}
+
+int dpa_cls_hm_update_params_compatcpy(
+ struct ioc_dpa_cls_hm_update_params *kparam,
+ const struct compat_ioc_dpa_cls_hm_update_params *uparam)
+{
+ int op_flags;
+
+ kparam->update_params.op_flags = uparam->update_params.op_flags;
+ op_flags = kparam->update_params.op_flags;
+ memcpy(&kparam->update_params.update, &uparam->update_params.update,
+ sizeof(kparam->update_params.update));
+ memcpy(&kparam->update_params.ip_frag_params,
+ &uparam->update_params.ip_frag_params,
+ sizeof(kparam->update_params.ip_frag_params));
+
+ switch (op_flags) {
+ case DPA_CLS_HM_REPLACE_IPv4_BY_IPv6:
+ memcpy(&kparam->update_params.replace.new_ipv6_hdr,
+ &uparam->update_params.replace.new_ipv6_hdr,
+ sizeof(struct ipv6_header));
+ break;
+ case DPA_CLS_HM_REPLACE_IPv6_BY_IPv4:
+ kparam->update_params.replace.new_ipv4_hdr.options_size =
+ uparam->update_params.replace.new_ipv4_hdr.options_size;
+ kparam->update_params.replace.new_ipv4_hdr.options =
+ compat_ptr(uparam->update_params.replace.new_ipv4_hdr.
+ options);
+ memcpy(&kparam->update_params.replace.new_ipv4_hdr.header,
+ &uparam->update_params.replace.new_ipv4_hdr.header,
+ sizeof(struct iphdr));
+ break;
+ default:
+ break;
+ }
+
+
+ kparam->update_params.fm_pcd = compat_ptr(uparam->update_params.fm_pcd);
+ kparam->next_hmd = uparam->next_hmd;
+ kparam->hmd = uparam->hmd;
+
+ if (uparam->res.update_node)
+ kparam->res.update_node = compat_get_id2ptr(
+ uparam->res.update_node,
+ FM_MAP_TYPE_PCD_NODE);
+ else
+ kparam->res.update_node = NULL;
+
+ if (uparam->res.ip_frag_node)
+ kparam->res.ip_frag_node = compat_get_id2ptr(
+ uparam->res.ip_frag_node,
+ FM_MAP_TYPE_PCD_NODE);
+ else
+ kparam->res.ip_frag_node = NULL;
+
+ kparam->chain_head = uparam->chain_head;
+ kparam->modify_flags = uparam->modify_flags;
+
+ return 0;
+}
+
+int dpa_cls_hm_fwd_params_compatcpy(
+ struct ioc_dpa_cls_hm_fwd_params *kparam,
+ const struct compat_ioc_dpa_cls_hm_fwd_params *uparam)
+{
+ int type;
+
+ kparam->fwd_params.out_if_type = uparam->fwd_params.out_if_type;
+ kparam->fwd_params.fm_pcd = compat_ptr(uparam->fwd_params.fm_pcd);
+
+ type = kparam->fwd_params.out_if_type;
+ switch (type) {
+ case DPA_CLS_HM_IF_TYPE_ETHERNET:
+ memcpy(&kparam->fwd_params.eth, &uparam->fwd_params.eth,
+ sizeof(struct dpa_cls_hm_fwd_l2_param));
+ break;
+ case DPA_CLS_HM_IF_TYPE_PPPoE:
+ memcpy(&kparam->fwd_params.pppoe, &uparam->fwd_params.pppoe,
+ sizeof(struct dpa_cls_hm_fwd_pppoe_param));
+ break;
+ case DPA_CLS_HM_IF_TYPE_PPP:
+ memcpy(&kparam->fwd_params.ppp, &uparam->fwd_params.ppp,
+ sizeof(struct dpa_cls_hm_fwd_ppp_param));
+ break;
+ default:
+ break;
+ }
+
+ memcpy(&kparam->fwd_params.ip_frag_params,
+ &uparam->fwd_params.ip_frag_params,
+ sizeof(struct dpa_cls_hm_ip_frag_params));
+
+ kparam->next_hmd = uparam->next_hmd;
+ kparam->hmd = uparam->hmd;
+
+ if (uparam->res.fwd_node)
+ kparam->res.fwd_node = compat_get_id2ptr(uparam->res.fwd_node,
+ FM_MAP_TYPE_PCD_NODE);
+ else
+ kparam->res.fwd_node = NULL;
+
+ if (uparam->res.pppoe_node)
+ kparam->res.pppoe_node = compat_get_id2ptr(
+ uparam->res.pppoe_node,
+ FM_MAP_TYPE_PCD_NODE);
+ else
+ kparam->res.pppoe_node = NULL;
+
+ if (uparam->res.ip_frag_node)
+ kparam->res.ip_frag_node = compat_get_id2ptr(
+ uparam->res.ip_frag_node,
+ FM_MAP_TYPE_PCD_NODE);
+ else
+ kparam->res.ip_frag_node = NULL;
+
+ kparam->chain_head = uparam->chain_head;
+ kparam->modify_flags = uparam->modify_flags;
+
+ return 0;
+}
+
+int dpa_cls_hm_mpls_params_compatcpy(
+ struct ioc_dpa_cls_hm_mpls_params *kparam,
+ const struct compat_ioc_dpa_cls_hm_mpls_params *uparam)
+{
+ kparam->mpls_params.type = uparam->mpls_params.type;
+ memcpy(kparam->mpls_params.mpls_hdr, uparam->mpls_params.mpls_hdr,
+ sizeof(struct mpls_header) * DPA_CLS_HM_MAX_MPLS_LABELS);
+ kparam->mpls_params.num_labels = uparam->mpls_params.num_labels;
+ kparam->mpls_params.fm_pcd = compat_ptr(uparam->mpls_params.fm_pcd);
+ kparam->next_hmd = uparam->next_hmd;
+ kparam->hmd = uparam->hmd;
+
+ if (uparam->res.ins_rm_node)
+ kparam->res.ins_rm_node = compat_get_id2ptr(
+ uparam->res.ins_rm_node,
+ FM_MAP_TYPE_PCD_NODE);
+ else
+ kparam->res.ins_rm_node = NULL;
+
+ kparam->chain_head = uparam->chain_head;
+ kparam->modify_flags = uparam->modify_flags;
+
+ return 0;
+}
+
+int dpa_cls_mcast_group_params_compatcpy(
+ struct ioc_dpa_cls_mcast_group_params *kparam,
+ const struct compat_ioc_dpa_cls_mcast_group_params *uparam)
+{
+ kparam->mcast_grp_params.max_members =
+ uparam->mcast_grp_params.max_members;
+ kparam->mcast_grp_params.fm_pcd = compat_ptr(uparam->mcast_grp_params.
+ fm_pcd);
+ kparam->mcast_grp_params.first_member_params.override_fqid =
+ uparam->mcast_grp_params.first_member_params.override_fqid;
+ kparam->mcast_grp_params.first_member_params.new_fqid =
+ uparam->mcast_grp_params.first_member_params.new_fqid;
+ kparam->mcast_grp_params.first_member_params.new_rel_vsp_id =
+ uparam->mcast_grp_params.first_member_params.new_rel_vsp_id;
+ if (compat_ptr(uparam->mcast_grp_params.first_member_params.
+ policer_params)) {
+ if (copy_from_user(kparam->mcast_grp_params.first_member_params.
+ policer_params,
+ compat_ptr(uparam->mcast_grp_params.first_member_params.
+ policer_params),
+ sizeof(struct dpa_cls_tbl_policer_params))) {
+ log_err("Read failed: policer params.\n");
+ return -EBUSY;
+ }
+ } else
+ kparam->mcast_grp_params.first_member_params.policer_params =
+ NULL;
+
+ kparam->mcast_grp_params.first_member_params.hmd =
+ uparam->mcast_grp_params.first_member_params.hmd;
+ kparam->mcast_grp_params.prefilled_members =
+ uparam->mcast_grp_params.prefilled_members;
+
+ if (uparam->res.group_node)
+ kparam->res.group_node = compat_get_id2ptr(
+ uparam->res.group_node,
+ FM_MAP_TYPE_PCD_NODE);
+ else
+ kparam->res.group_node = NULL;
+
+ if (compat_ptr(uparam->mcast_grp_params.distribution))
+ kparam->mcast_grp_params.distribution = compat_get_id2ptr(
+ uparam->mcast_grp_params.distribution,
+ FM_MAP_TYPE_PCD_NODE);
+ else
+ kparam->mcast_grp_params.distribution = NULL;
+
+ if (compat_ptr(uparam->mcast_grp_params.classification))
+ kparam->mcast_grp_params.classification = compat_get_id2ptr(
+ uparam->mcast_grp_params.classification,
+ FM_MAP_TYPE_PCD_NODE);
+ else
+ kparam->mcast_grp_params.classification = NULL;
+
+ return 0;
+}
+
+int dpa_cls_mcast_member_params_compatcpy(
+ struct ioc_dpa_cls_mcast_member_params *kparam,
+ const struct compat_ioc_dpa_cls_mcast_member_params *uparam)
+{
+ kparam->grpd = uparam->grpd;
+ kparam->member_params.hmd = uparam->member_params.hmd;
+ kparam->member_params.new_fqid = uparam->member_params.new_fqid;
+ kparam->member_params.override_fqid =
+ uparam->member_params.override_fqid;
+ kparam->member_params.new_rel_vsp_id =
+ uparam->member_params.new_rel_vsp_id;
+ if (compat_ptr(uparam->member_params.policer_params)) {
+ if (copy_from_user(kparam->member_params.policer_params,
+ compat_ptr(uparam->member_params.policer_params),
+ sizeof(struct dpa_cls_tbl_policer_params))) {
+ log_err("Read failed: policer params.\n");
+ return -EBUSY;
+ }
+ } else
+ kparam->member_params.policer_params = NULL;
+
+ return 0;
+}
+
+#endif /* CONFIG_COMPAT */
diff --git a/drivers/staging/fsl_dpa_offload/wrp_dpa_classifier.h b/drivers/staging/fsl_dpa_offload/wrp_dpa_classifier.h
new file mode 100644
index 0000000..c2d441e
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/wrp_dpa_classifier.h
@@ -0,0 +1,87 @@
+
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Internal DPA Classifier Wrapper Application Programming Interface
+ */
+
+#ifndef __WRP_DPA_CLASSIFIER_H
+#define __WRP_DPA_CLASSIFIER_H
+
+
+/* Other includes */
+#include "linux/fs.h"
+
+
+#define WRP_DPA_CLS_CDEVNAME "dpa_classifier"
+#define WRP_DPA_CLS_CLASS_NAME "dpa_classifier"
+
+
+int wrp_dpa_classif_init(void);
+
+int wrp_dpa_classif_exit(void);
+
+int wrp_dpa_classif_open(struct inode *inode, struct file *filp);
+
+int wrp_dpa_classif_release(struct inode *inode, struct file *filp);
+
+ssize_t wrp_dpa_classif_read(
+ struct file *filp,
+ char __user *buf,
+ size_t len,
+ loff_t *offp);
+
+ssize_t wrp_dpa_classif_write(
+ struct file *filp,
+ const char __user *buf,
+ size_t len,
+ loff_t *offp);
+
+long wrp_dpa_classif_ioctl(
+ struct file *filp,
+ unsigned int cmd,
+ unsigned long args);
+
+long wrp_dpa_classif_do_ioctl(
+ struct file *filp,
+ unsigned int cmd,
+ unsigned long args,
+ bool compat_mode);
+
+#ifdef CONFIG_COMPAT
+long wrp_dpa_classif_compat_ioctl(
+ struct file *filp,
+ unsigned int cmd,
+ unsigned long args);
+#endif
+
+#endif /* __WRP_DPA_CLASSIFIER_H */
diff --git a/drivers/staging/fsl_dpa_offload/wrp_dpa_ipsec.c b/drivers/staging/fsl_dpa_offload/wrp_dpa_ipsec.c
new file mode 100644
index 0000000..f4b081f
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/wrp_dpa_ipsec.c
@@ -0,0 +1,1643 @@
+
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * DPA IPsec Wrapper implementation.
+ */
+
+#include <linux/uaccess.h>
+#include <linux/export.h>
+
+#include <linux/fsl_dpa_ipsec.h>
+#include "dpa_ipsec_ioctl.h"
+#include "wrp_dpa_ipsec.h"
+
+/* Other includes */
+#include <linux/fdtable.h>
+#include "lnxwrp_fm.h"
+
+#define UDP_HDR_SIZE 8
+
+static const struct file_operations dpa_ipsec_fops = {
+ .owner = THIS_MODULE,
+ .open = wrp_dpa_ipsec_open,
+ .read = NULL,
+ .write = NULL,
+ .unlocked_ioctl = wrp_dpa_ipsec_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = wrp_dpa_ipsec_ioctl_compat,
+#endif
+ .release = wrp_dpa_ipsec_release
+};
+
+static int dpa_ipsec_cdev_major = -1;
+static struct class *ipsec_class;
+static struct device *ipsec_dev;
+
+static long wrp_dpa_ipsec_do_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long args);
+
+#ifdef CONFIG_COMPAT
+static long wrp_dpa_ipsec_do_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long args);
+
+static void compat_copy_dpa_ipsec_init(struct ioc_dpa_ipsec_params *prm,
+ struct ioc_compat_dpa_ipsec_params *compat_prm)
+{
+ struct ioc_compat_ipsec_init_params *init_compat_prm;
+ struct dpa_ipsec_params *init_prm;
+
+ init_compat_prm = &compat_prm->dpa_ipsec_params;
+ init_prm = &prm->dpa_ipsec_params;
+
+ init_prm->fm_pcd = (void *)compat_ptr(init_compat_prm->fm_pcd);
+ init_prm->fqid_range = (struct dpa_ipsec_fqid_range *)
+ compat_ptr(init_compat_prm->fqid_range);
+ init_prm->ipf_bpid = init_compat_prm->ipf_bpid;
+ init_prm->max_sa_pairs = init_compat_prm->max_sa_pairs;
+ init_prm->post_sec_in_params = init_compat_prm->post_sec_in_params;
+ init_prm->max_sa_manip_ops = init_compat_prm->max_sa_manip_ops;
+ init_prm->post_sec_out_params = init_compat_prm->post_sec_out_params;
+ init_prm->pre_sec_in_params = init_compat_prm->pre_sec_in_params;
+ init_prm->pre_sec_out_params = init_compat_prm->pre_sec_out_params;
+ init_prm->qm_sec_ch = init_compat_prm->qm_sec_ch;
+}
+
+static void compat_copy_sa_in_params(struct dpa_ipsec_sa_in_params *prm,
+ struct ioc_compat_sa_in_params *compat_prm)
+{
+ prm->arw = compat_prm->arw;
+ prm->use_var_iphdr_len = compat_prm->use_var_iphdr_len;
+ prm->src_addr = compat_prm->src_addr;
+ prm->dest_addr = compat_prm->dest_addr;
+ prm->use_udp_encap = compat_prm->use_udp_encap;
+ prm->src_port = compat_prm->src_port;
+ prm->dest_port = compat_prm->dest_port;
+ dpa_cls_tbl_action_params_compatcpy(&prm->policy_miss_action,
+ &compat_prm->policy_miss_action);
+ dpa_cls_tbl_action_params_compatcpy(&prm->post_ipsec_action,
+ &compat_prm->post_ipsec_action);
+}
+static void compat_copy_sa_out_params(struct dpa_ipsec_sa_out_params *prm,
+ struct ioc_compat_sa_out_params *compat_prm)
+{
+ prm->init_vector = (struct dpa_ipsec_init_vector *)
+ compat_ptr(compat_prm->init_vector);
+ prm->ip_ver = compat_prm->ip_ver;
+ prm->ip_hdr_size = compat_prm->ip_hdr_size;
+ prm->outer_ip_header = (void *)compat_ptr(compat_prm->outer_ip_header);
+ prm->outer_udp_header = (void *)
+ compat_ptr(compat_prm->outer_udp_header);
+ prm->post_sec_flow_id = compat_prm->post_sec_flow_id;
+}
+
+static void compat_copy_sa_crypto_params(struct dpa_ipsec_sa_crypto_params *prm,
+ struct ioc_compat_sa_crypto_params *compat_prm)
+{
+ prm->alg_suite = compat_prm->alg_suite;
+ prm->auth_key = (uint8_t *)compat_ptr(compat_prm->auth_key);
+ prm->auth_key_len = compat_prm->auth_key_len;
+ prm->cipher_key = (uint8_t *)compat_ptr(compat_prm->cipher_key);
+ prm->cipher_key_len = compat_prm->cipher_key_len;
+}
+
+static void compat_copy_sa_params(struct dpa_ipsec_sa_params *sa_prm,
+ struct ioc_compat_sa_params *sa_compat_prm)
+{
+ /* copy common (both IN & OUT SA) parameters */
+ sa_prm->spi = sa_compat_prm->spi;
+ sa_prm->use_ext_seq_num = sa_compat_prm->use_ext_seq_num;
+ sa_prm->start_seq_num = sa_compat_prm->start_seq_num;
+ sa_prm->l2_hdr_size = sa_compat_prm->l2_hdr_size;
+ sa_prm->sa_mode = sa_compat_prm->sa_mode;
+ sa_prm->sa_proto = sa_compat_prm->sa_proto;
+ sa_prm->hdr_upd_flags = sa_compat_prm->hdr_upd_flags;
+ sa_prm->sa_wqid = sa_compat_prm->sa_wqid;
+ sa_prm->sa_bpid = sa_compat_prm->sa_bpid;
+ sa_prm->sa_bufsize = sa_compat_prm->sa_bufsize;
+ sa_prm->enable_stats = sa_compat_prm->enable_stats;
+ sa_prm->enable_extended_stats = sa_compat_prm->enable_extended_stats;
+ sa_prm->sa_dir = sa_compat_prm->sa_dir;
+
+ /* copy crypto parameters (containing multiple pointers) */
+ compat_copy_sa_crypto_params(&sa_prm->crypto_params,
+ &sa_compat_prm->crypto_params);
+
+ /* copy direction specific (IN / OUT) parameters */
+ if (sa_prm->sa_dir == DPA_IPSEC_INBOUND)
+ compat_copy_sa_in_params(&sa_prm->sa_in_params,
+ &sa_compat_prm->sa_in_params);
+ else
+ compat_copy_sa_out_params(&sa_prm->sa_out_params,
+ &sa_compat_prm->sa_out_params);
+}
+
+static int compat_copy_sa_out_iv(struct dpa_ipsec_init_vector *sa_iv,
+ compat_uptr_t compat_iv_ptr)
+{
+ struct ioc_compat_sa_init_vector *compat_sa_iv, tmp_sa_iv;
+
+ compat_sa_iv =
+ (struct ioc_compat_sa_init_vector *)compat_ptr(compat_iv_ptr);
+
+ if (copy_from_user(&tmp_sa_iv, compat_sa_iv, sizeof(tmp_sa_iv)))
+ return -EINVAL;
+
+ sa_iv->init_vector = (uint8_t *) compat_ptr(tmp_sa_iv.init_vector);
+ sa_iv->length = tmp_sa_iv.length;
+
+ return 0;
+}
+
+static void compat_copy_dpa_ipsec_rekey_sa(struct ioc_dpa_ipsec_rekey_prm *prm,
+ struct ioc_compat_dpa_ipsec_rekey_prm *compat_prm)
+{
+ /* copy rekeying specific params */
+ prm->auto_rmv_old_sa = compat_prm->auto_rmv_old_sa;
+ prm->sa_id = compat_prm->sa_id;
+
+ /* copy SA params from userspace */
+ compat_copy_sa_params(&prm->sa_params, &compat_prm->sa_params);
+}
+
+static void compat_copy_dpa_ipsec_add_rem_policy(
+ struct ioc_dpa_ipsec_add_rem_policy *prm,
+ struct ioc_compat_dpa_ipsec_add_rem_policy *compat_prm,
+ bool copy_from_us)
+{
+ if (copy_from_us) {
+ prm->sa_id = compat_prm->sa_id;
+ prm->pol_params.src_addr = compat_prm->pol_params.src_addr;
+ prm->pol_params.src_prefix_len =
+ compat_prm->pol_params.src_prefix_len;
+ prm->pol_params.dest_addr = compat_prm->pol_params.dest_addr;
+ prm->pol_params.dest_prefix_len =
+ compat_prm->pol_params.dest_prefix_len;
+ prm->pol_params.protocol = compat_prm->pol_params.protocol;
+ prm->pol_params.masked_proto =
+ compat_prm->pol_params.masked_proto;
+ prm->pol_params.l4 = compat_prm->pol_params.l4;
+ if (compat_prm->pol_params.dir_params.type ==
+ DPA_IPSEC_POL_DIR_PARAMS_MANIP)
+ prm->pol_params.dir_params.manip_desc =
+ compat_prm->pol_params.dir_params.manip_desc;
+ else if (compat_prm->pol_params.dir_params.type ==
+ DPA_IPSEC_POL_DIR_PARAMS_ACT) {
+ dpa_cls_tbl_action_params_compatcpy(
+ &prm->pol_params.dir_params.in_action,
+ &compat_prm->pol_params.dir_params.in_action);
+ }
+ prm->pol_params.dir_params.type =
+ compat_prm->pol_params.dir_params.type;
+ prm->pol_params.priority =
+ compat_prm->pol_params.priority;
+ } else {
+ compat_prm->sa_id = prm->sa_id;
+ compat_prm->pol_params.src_addr = prm->pol_params.src_addr;
+ compat_prm->pol_params.src_prefix_len =
+ prm->pol_params.src_prefix_len;
+ compat_prm->pol_params.dest_addr = prm->pol_params.dest_addr;
+ compat_prm->pol_params.dest_prefix_len =
+ prm->pol_params.dest_prefix_len;
+ compat_prm->pol_params.protocol = prm->pol_params.protocol;
+ compat_prm->pol_params.masked_proto =
+ prm->pol_params.masked_proto;
+ compat_prm->pol_params.l4 = prm->pol_params.l4;
+ if (prm->pol_params.dir_params.type ==
+ DPA_IPSEC_POL_DIR_PARAMS_MANIP)
+ compat_prm->pol_params.dir_params.manip_desc =
+ prm->pol_params.dir_params.manip_desc;
+ else if (prm->pol_params.dir_params.type ==
+ DPA_IPSEC_POL_DIR_PARAMS_ACT) {
+ dpa_cls_tbl_action_params_rcompatcpy(
+ &compat_prm->pol_params.dir_params.in_action,
+ &prm->pol_params.dir_params.in_action);
+ }
+ compat_prm->pol_params.dir_params.type =
+ prm->pol_params.dir_params.type;
+ compat_prm->pol_params.priority =
+ prm->pol_params.priority;
+ }
+}
+
+static void compat_copy_dpa_ipsec_get_pols(
+ struct ioc_dpa_ipsec_get_policies *prm,
+ struct ioc_compat_dpa_ipsec_get_policies *compat_prm)
+{
+ prm->num_pol = compat_prm->num_pol;
+ prm->sa_id = compat_prm->sa_id;
+ prm->policy_params = (struct dpa_ipsec_policy_params *)
+ compat_ptr(compat_prm->policy_params);
+}
+
+static int compat_alloc_plcr_params(struct dpa_cls_tbl_action *kparam,
+ const struct dpa_cls_compat_tbl_action *uparam)
+{
+ if (uparam->type == DPA_CLS_TBL_ACTION_ENQ &&
+ compat_ptr(uparam->enq_params.policer_params)) {
+ kparam->enq_params.policer_params = kmalloc(
+ sizeof(struct dpa_cls_tbl_policer_params),
+ GFP_KERNEL);
+ if (!kparam->enq_params.policer_params) {
+ log_err("Error alloc CLS POL param\n");
+ return -ENOMEM;
+ }
+ }
+ return 0;
+}
+#endif
+
+static int copy_policer_params(struct dpa_cls_tbl_action *cls_action)
+{
+ struct dpa_cls_tbl_policer_params *policer_params = NULL;
+ int err = 0;
+
+ if (cls_action->type == DPA_CLS_TBL_ACTION_ENQ &&
+ cls_action->enq_params.policer_params != NULL) {
+ policer_params = kmalloc(sizeof(*policer_params), GFP_KERNEL);
+ if (!policer_params) {
+ log_err("Error alloc CLS POL param\n");
+ err = -ENOMEM;
+ goto clean_policer_params;
+ }
+ if (copy_from_user(policer_params,
+ cls_action->enq_params.policer_params,
+ sizeof(*policer_params))) {
+ log_err("Error - copy CLS POL param\n");
+ err = -EINVAL;
+ goto clean_policer_params;
+ }
+ cls_action->enq_params.policer_params = policer_params;
+ return 0;
+ }
+
+clean_policer_params:
+ cls_action->enq_params.policer_params = NULL;
+ kfree(policer_params);
+
+ return err;
+}
+
+/* free memory allocated for copying SA params from US */
+static void free_sa_params(struct dpa_ipsec_sa_params *prm)
+{
+ struct dpa_ipsec_sa_crypto_params *crypto_params;
+
+ if (prm->sa_dir == DPA_IPSEC_OUTBOUND) {
+ struct dpa_ipsec_sa_out_params *sa_out_prm;
+
+ sa_out_prm = &prm->sa_out_params;
+ if (sa_out_prm->init_vector) {
+ kfree(sa_out_prm->init_vector->init_vector);
+ kfree(sa_out_prm->init_vector);
+ }
+ kfree(sa_out_prm->outer_ip_header);
+ kfree(sa_out_prm->outer_udp_header);
+ } else {
+ struct dpa_cls_tbl_action *cls_action;
+
+ cls_action = &prm->sa_in_params.policy_miss_action;
+ if (cls_action->type == DPA_CLS_TBL_ACTION_ENQ)
+ kfree(cls_action->enq_params.policer_params);
+
+ cls_action = &prm->sa_in_params.post_ipsec_action;
+ if (cls_action->type == DPA_CLS_TBL_ACTION_ENQ)
+ kfree(cls_action->enq_params.policer_params);
+ }
+
+ crypto_params = &prm->crypto_params;
+ kfree(crypto_params->auth_key);
+ kfree(crypto_params->cipher_key);
+}
+
+/* handle any required memory transfers (US to K) when creating/rekeying a SA */
+static int do_copy_sa_params(struct dpa_ipsec_sa_params *prm, void *args)
+{
+ struct dpa_ipsec_sa_out_params *sa_out_prm;
+ struct dpa_ipsec_sa_crypto_params *crypto_params;
+ struct dpa_ipsec_init_vector *sa_out_iv = NULL;
+ uint8_t *auth_key = NULL, *cipher_key = NULL, *iv_array = NULL;
+ void *out_ip_hdr = NULL, *out_udp_hdr = NULL;
+ int err = 0;
+#ifdef CONFIG_COMPAT
+ struct ioc_compat_sa_params *compat_prm =
+ (struct ioc_compat_sa_params *)args;
+#endif
+ /* allocate memory and copy SA out params (if required)*/
+ if (prm->sa_dir == DPA_IPSEC_OUTBOUND) {
+ sa_out_prm = &prm->sa_out_params;
+ if (sa_out_prm->outer_ip_header) {
+ out_ip_hdr = kmalloc(sa_out_prm->ip_hdr_size,
+ GFP_KERNEL);
+ if (!out_ip_hdr) {
+ log_err("Error - alloc SA out hdr\n");
+ return -ENOMEM;
+ }
+ if (copy_from_user(out_ip_hdr,
+ sa_out_prm->outer_ip_header,
+ sa_out_prm->ip_hdr_size)) {
+ log_err("Error - copy SA out hdr\n");
+ err = -EINVAL;
+ goto free_create_copied_sa_mem;
+ }
+ sa_out_prm->outer_ip_header = out_ip_hdr;
+ }
+ if (sa_out_prm->outer_udp_header) {
+ out_udp_hdr = kmalloc(UDP_HDR_SIZE, GFP_KERNEL);
+ if (!out_udp_hdr) {
+ log_err("Error - alloc SA out udp hdr\n");
+ err = -ENOMEM;
+ goto free_create_copied_sa_mem;
+ }
+ if (copy_from_user(out_udp_hdr,
+ sa_out_prm->outer_udp_header,
+ UDP_HDR_SIZE)) {
+ log_err("Error - copy SA out udp hdr\n");
+ err = -EINVAL;
+ goto free_create_copied_sa_mem;
+ }
+ sa_out_prm->outer_udp_header = out_udp_hdr;
+ }
+ if (sa_out_prm->init_vector) {
+ sa_out_iv = kmalloc(sizeof(*sa_out_iv), GFP_KERNEL);
+ if (!sa_out_iv) {
+ log_err("Error - alloc SA out IV struct\n");
+ err = -ENOMEM;
+ goto free_create_copied_sa_mem;
+ }
+#ifdef CONFIG_COMPAT
+ err = compat_copy_sa_out_iv(sa_out_iv,
+ compat_prm->sa_out_params.init_vector);
+#else
+ if (copy_from_user(sa_out_iv, sa_out_prm->init_vector,
+ sizeof(*sa_out_iv)))
+ err = -EINVAL;
+#endif
+ if (err < 0) {
+ log_err("Error - copy SA out IV struct\n");
+ kfree(sa_out_iv);
+ return err;
+ }
+ sa_out_prm->init_vector = sa_out_iv;
+
+ /* if the IV array is NULL, don't bother to copy it */
+ if (!sa_out_iv->init_vector)
+ goto copy_crypto_keys;
+
+ iv_array = kmalloc(sa_out_iv->length, GFP_KERNEL);
+ if (!iv_array) {
+ log_err("Error - alloc SA out IV array\n");
+ err = -ENOMEM;
+ goto free_create_copied_sa_mem;
+ }
+ if (copy_from_user(iv_array, sa_out_iv->init_vector,
+ sa_out_iv->length)) {
+ log_err("Error - copy SA out IV array\n");
+ err = -EINVAL;
+ goto free_create_copied_sa_mem;
+ }
+ sa_out_iv->init_vector = iv_array;
+ }
+ }
+
+copy_crypto_keys:
+ /*
+ * allocate memory and copy the keys from userspace
+ * (if required - if keys are not NULL)
+ */
+ crypto_params = &prm->crypto_params;
+ if (crypto_params->auth_key) {
+ auth_key = kmalloc(crypto_params->auth_key_len, GFP_KERNEL);
+ if (!auth_key) {
+ log_err("Couldn't allocate memory for SA auth key\n");
+ err = -ENOMEM;
+ goto free_create_sa_keys_mem;
+ }
+ if (copy_from_user(auth_key, crypto_params->auth_key,
+ crypto_params->auth_key_len)) {
+ log_err("Could not copy SA auth key!\n");
+ err = -EINVAL;
+ goto free_create_sa_keys_mem;
+ }
+ crypto_params->auth_key = auth_key;
+ }
+
+ if (crypto_params->cipher_key) {
+ cipher_key = kmalloc(crypto_params->cipher_key_len, GFP_KERNEL);
+ if (!cipher_key) {
+ log_err("Couldn't allocate memory for SA cipher key\n");
+ err = -ENOMEM;
+ goto free_create_sa_keys_mem;
+ }
+ if (copy_from_user(cipher_key, crypto_params->cipher_key,
+ crypto_params->cipher_key_len)) {
+ log_err("Could not copy SA auth key!\n");
+ err = -EINVAL;
+ goto free_create_sa_keys_mem;
+ }
+ crypto_params->cipher_key = cipher_key;
+ }
+
+ return 0;
+
+free_create_sa_keys_mem:
+ kfree(auth_key);
+ kfree(cipher_key);
+
+free_create_copied_sa_mem:
+ if (prm->sa_dir == DPA_IPSEC_OUTBOUND) {
+ kfree(iv_array);
+ kfree(sa_out_iv);
+ kfree(out_ip_hdr);
+ kfree(out_udp_hdr);
+ }
+
+ return err;
+}
+
+static int do_init_ioctl(struct ioc_dpa_ipsec_params *kprm)
+{
+ struct dpa_ipsec_fqid_range *fqid_range = NULL;
+ struct file *fm_pcd_file;
+ t_LnxWrpFmDev *fm_wrapper_dev;
+ int err;
+
+ /* copy FQID range params - if configured */
+ if (kprm->dpa_ipsec_params.fqid_range) {
+ fqid_range = kmalloc(sizeof(*fqid_range), GFP_KERNEL);
+ if (!fqid_range) {
+ log_err("FQID range allocation failed!\n");
+ return -EINVAL;
+ }
+ if (copy_from_user(fqid_range,
+ kprm->dpa_ipsec_params.fqid_range,
+ sizeof(*fqid_range))) {
+ log_err("Could not copy FQID range params!\n");
+ err = -EINVAL;
+ goto free_ipsec_init_mem;
+ }
+ kprm->dpa_ipsec_params.fqid_range = fqid_range;
+ }
+
+ /* Translate FM_PCD file descriptor */
+ fm_pcd_file = fcheck((unsigned long)kprm->dpa_ipsec_params.fm_pcd);
+ if (!fm_pcd_file) {
+ log_err("Could not acquire PCD handle\n");
+ err = -EINVAL;
+ goto free_ipsec_init_mem;
+ }
+ fm_wrapper_dev = ((t_LnxWrpFmDev *)fm_pcd_file->private_data);
+ kprm->dpa_ipsec_params.fm_pcd = (void *)fm_wrapper_dev->h_PcdDev;
+ err = dpa_ipsec_init(&kprm->dpa_ipsec_params,
+ &kprm->dpa_ipsec_id);
+ if (err < 0)
+ goto free_ipsec_init_mem;
+
+free_ipsec_init_mem:
+ kfree(fqid_range);
+
+ return err;
+}
+
+static int do_create_sa_ioctl(void *args)
+{
+ struct ioc_dpa_ipsec_sa_params prm;
+ int err = 0;
+
+ if (copy_from_user(&prm, args, sizeof(prm))) {
+ log_err("Could not copy SA parameters\n");
+ return -EINVAL;
+ }
+
+ if (prm.sa_params.sa_dir == DPA_IPSEC_INBOUND) {
+ struct dpa_ipsec_sa_in_params *sa_in_params = NULL;
+
+ sa_in_params = &prm.sa_params.sa_in_params;
+ /* copy policer params for policy miss action - if any */
+ err = copy_policer_params(&sa_in_params->policy_miss_action);
+ if (err < 0)
+ goto free_create_sa_mem;
+
+ /* copy policer params for post decryption action - if any */
+ err = copy_policer_params(&sa_in_params->post_ipsec_action);
+ if (err < 0)
+ goto free_create_sa_mem;
+ }
+
+ err = do_copy_sa_params(&prm.sa_params, NULL);
+ if (err < 0)
+ return err;
+
+ err = dpa_ipsec_create_sa(prm.dpa_ipsec_id, &prm.sa_params, &prm.sa_id);
+ if (err < 0)
+ goto free_create_sa_mem;
+
+ if (copy_to_user((void *)args, &prm, sizeof(prm))) {
+ log_err("Could not copy to user the SA ID\n");
+ err = -EINVAL;
+ }
+
+free_create_sa_mem:
+ free_sa_params(&prm.sa_params);
+
+ return err;
+}
+
+#ifdef CONFIG_COMPAT
+static int do_create_sa_compat_ioctl(void *args)
+{
+ struct ioc_dpa_ipsec_sa_params prm;
+ struct ioc_compat_dpa_ipsec_sa_params compat_prm;
+ int err = 0;
+
+ if (copy_from_user(&compat_prm, args, sizeof(compat_prm))) {
+ log_err("Could not copy SA parameters\n");
+ return -EINVAL;
+ }
+
+ memset(&prm, 0, sizeof(struct ioc_dpa_ipsec_sa_params));
+
+ /* allocate memory for policer parameters */
+ if (compat_prm.sa_params.sa_dir == DPA_IPSEC_INBOUND) {
+ memset(&prm.sa_params.sa_in_params.policy_miss_action,
+ 0, sizeof(struct dpa_cls_tbl_action));
+ err = compat_alloc_plcr_params(
+ &prm.sa_params.sa_in_params.policy_miss_action,
+ &compat_prm.sa_params.sa_in_params.policy_miss_action);
+ if (err < 0)
+ goto free_create_sa_mem;
+
+ memset(&prm.sa_params.sa_in_params.post_ipsec_action,
+ 0, sizeof(struct dpa_cls_tbl_action));
+ err = compat_alloc_plcr_params(
+ &prm.sa_params.sa_in_params.post_ipsec_action,
+ &compat_prm.sa_params.sa_in_params.post_ipsec_action);
+ if (err < 0)
+ goto free_create_sa_mem;
+ }
+
+ /* copy SA params from userspace */
+ compat_copy_sa_params(&prm.sa_params, &compat_prm.sa_params);
+
+ err = do_copy_sa_params(&prm.sa_params, &compat_prm.sa_params);
+ if (err < 0)
+ return err;
+
+ err = dpa_ipsec_create_sa(prm.dpa_ipsec_id, &prm.sa_params, &prm.sa_id);
+ if (err < 0)
+ goto free_create_sa_mem;
+
+ /* copy the ID of the newly created DPA IPSec SA */
+ compat_prm.sa_id = prm.sa_id;
+
+ if (copy_to_user((void *)args, &compat_prm, sizeof(compat_prm))) {
+ log_err("Could not copy to user the SA ID\n");
+ err = -EINVAL;
+ }
+
+free_create_sa_mem:
+ free_sa_params(&prm.sa_params);
+
+ return err;
+}
+#endif
+
+static int do_sa_rekey_ioctl(void *args)
+{
+ struct ioc_dpa_ipsec_rekey_prm prm;
+ int err = 0;
+
+ if (copy_from_user(&prm, args, sizeof(prm))) {
+ log_err("Could not copy SA rekeying params\n");
+ return -EINVAL;
+ }
+
+ err = do_copy_sa_params(&prm.sa_params, NULL);
+ if (err < 0)
+ return err;
+
+ err = dpa_ipsec_sa_rekeying(prm.sa_id, &prm.sa_params,
+ default_rekey_event_cb, prm.auto_rmv_old_sa,
+ &prm.new_sa_id);
+ if (err < 0)
+ goto free_rekey_sa_mem;
+
+ if (copy_to_user((void *)args, &prm, sizeof(prm))) {
+ log_err("Could not copy to user new SA ID\n");
+ err = -EINVAL;
+ }
+
+free_rekey_sa_mem:
+ free_sa_params(&prm.sa_params);
+
+ return err;
+}
+
+#ifdef CONFIG_COMPAT
+static int do_sa_rekey_compat_ioctl(void *args)
+{
+ struct ioc_dpa_ipsec_rekey_prm prm;
+ struct ioc_compat_dpa_ipsec_rekey_prm compat_prm;
+ int err = 0;
+
+ if (copy_from_user(&compat_prm, args, sizeof(compat_prm))) {
+ log_err("Could not copy SA rekeying params\n");
+ return -EINVAL;
+ }
+ compat_copy_dpa_ipsec_rekey_sa(&prm, &compat_prm);
+
+ err = do_copy_sa_params(&prm.sa_params, &compat_prm.sa_params);
+ if (err < 0)
+ return err;
+
+ err = dpa_ipsec_sa_rekeying(prm.sa_id, &prm.sa_params,
+ default_rekey_event_cb, prm.auto_rmv_old_sa,
+ &prm.new_sa_id);
+ if (err < 0)
+ goto free_rekey_sa_mem;
+
+ compat_prm.new_sa_id = prm.new_sa_id;
+ if (copy_to_user((void *)args, &compat_prm, sizeof(compat_prm))) {
+ log_err("Could not copy to user new SA ID\n");
+ err = -EINVAL;
+ }
+
+free_rekey_sa_mem:
+ free_sa_params(&prm.sa_params);
+
+ return err;
+}
+#endif
+
+static int do_add_rem_policy_ioctl(void *args, bool add_pol)
+{
+ struct ioc_dpa_ipsec_add_rem_policy prm;
+ int err;
+
+ if (copy_from_user(&prm,
+ (struct ioc_dpa_ipsec_add_rem_policy *)args,
+ sizeof(prm))) {
+ log_err("Could not copy parameters\n");
+ return -EINVAL;
+ }
+
+ if (prm.pol_params.dir_params.type == DPA_IPSEC_POL_DIR_PARAMS_ACT) {
+ err = copy_policer_params(&prm.pol_params.dir_params.in_action);
+ if (err < 0)
+ return err;
+ }
+
+ if (add_pol)
+ err = dpa_ipsec_sa_add_policy(prm.sa_id, &prm.pol_params);
+ else
+ err = dpa_ipsec_sa_remove_policy(prm.sa_id, &prm.pol_params);
+
+ if (prm.pol_params.dir_params.type == DPA_IPSEC_POL_DIR_PARAMS_ACT)
+ kfree(prm.pol_params.dir_params.in_action.enq_params.policer_params);
+
+ return err;
+}
+
+#ifdef CONFIG_COMPAT
+static int do_add_rem_policy_compat_ioctl(void *args, bool add_pol)
+{
+ struct ioc_dpa_ipsec_add_rem_policy kprm;
+ struct ioc_compat_dpa_ipsec_add_rem_policy uprm;
+ struct dpa_cls_tbl_action *in_action = NULL;
+ int err;
+
+ if (copy_from_user(&uprm,
+ (struct ioc_compat_dpa_ipsec_add_rem_policy *)args,
+ sizeof(uprm))) {
+ log_err("Could not copy parameters\n");
+ return -EINVAL;
+ }
+
+ memset(&kprm, 0, sizeof(struct ioc_dpa_ipsec_add_rem_policy));
+
+ in_action = &kprm.pol_params.dir_params.in_action;
+ if (uprm.pol_params.dir_params.type == DPA_IPSEC_POL_DIR_PARAMS_ACT) {
+ err = compat_alloc_plcr_params(in_action,
+ &uprm.pol_params.dir_params.in_action);
+ if (err < 0)
+ return err;
+ }
+
+ compat_copy_dpa_ipsec_add_rem_policy(&kprm, &uprm, true);
+
+ if (add_pol)
+ err = dpa_ipsec_sa_add_policy(kprm.sa_id, &kprm.pol_params);
+ else
+ err = dpa_ipsec_sa_remove_policy(kprm.sa_id, &kprm.pol_params);
+
+ if (uprm.pol_params.dir_params.type == DPA_IPSEC_POL_DIR_PARAMS_ACT)
+ kfree(in_action->enq_params.policer_params);
+
+ return err;
+}
+#endif
+
+static int do_sa_get_policies_ioctl(void *args)
+{
+ struct ioc_dpa_ipsec_get_policies prm;
+ struct dpa_ipsec_policy_params *policy_params = NULL;
+ struct dpa_cls_tbl_policer_params **uplcr = NULL, **kplcr = NULL;
+ struct dpa_ipsec_pol_dir_params *dir;
+ int sa_id, num_pol = 0, err = 0, i;
+
+ if (copy_from_user(&prm, args, sizeof(prm))) {
+ log_err("Could not copy params for policy retrieval\n");
+ return -EINVAL;
+ }
+
+ if (prm.sa_id < 0) {
+ log_err("Invalid input SA id\n");
+ return -EINVAL;
+ }
+
+ sa_id = prm.sa_id;
+ if (!prm.policy_params) {
+ err = dpa_ipsec_sa_get_policies(sa_id, NULL, &num_pol);
+ if (err < 0) {
+ log_err("Get policies count failed\n");
+ return err;
+ }
+
+ prm.num_pol = num_pol;
+
+ if (copy_to_user(args, &prm, sizeof(prm))) {
+ log_err("Cannot copy policy count to user\n");
+ return -EINVAL;
+ }
+ return 0;
+ }
+
+ num_pol = prm.num_pol;
+ if (num_pol <= 0) {
+ log_err("Invalid number of policies for SA ID# %d\n", sa_id);
+ return -EINVAL;
+ }
+
+ policy_params = kzalloc(num_pol * sizeof(*policy_params), GFP_KERNEL);
+ if (!policy_params) {
+ log_err("Could not allocate memory for policy array\n");
+ return -ENOMEM;
+ }
+
+ err = dpa_ipsec_sa_get_policies(sa_id, policy_params, &num_pol);
+ if (err < 0 && err != -EAGAIN) {
+ log_err("Could not retrieve SA policies\n");
+ goto err_pol_cleanup;
+ } else if (err == -EAGAIN)
+ log_err("Not all SA policies could be retrieved\n");
+
+ kplcr = kzalloc(num_pol * sizeof(*kplcr), GFP_KERNEL);
+ if (!kplcr) {
+ log_err("Could not allocate memory for policer array\n");
+ err = -ENOMEM;
+ goto err_pol_cleanup;
+ }
+
+ uplcr = kzalloc(num_pol * sizeof(*uplcr), GFP_KERNEL);
+ if (!uplcr) {
+ log_err("Could not allocate memory for policer array\n");
+ err = -ENOMEM;
+ goto err_pol_cleanup;
+ }
+
+ /* User needs to provide policer parameters pointer */
+ for (i = 0; i < num_pol; i++) {
+ dir = &prm.policy_params[i].dir_params;
+ if (dir->in_action.enq_params.policer_params != NULL)
+ uplcr[i] = dir->in_action.enq_params.policer_params;
+ }
+
+ for (i = 0; i < num_pol; i++) {
+ dir = &policy_params[i].dir_params;
+ if (dir->type == DPA_IPSEC_POL_DIR_PARAMS_ACT &&
+ dir->in_action.type == DPA_CLS_TBL_ACTION_ENQ &&
+ dir->in_action.enq_params.policer_params != NULL)
+ kplcr[i] = dir->in_action.enq_params.policer_params;
+ }
+
+ if (copy_to_user(prm.policy_params, policy_params,
+ num_pol * sizeof(*policy_params))) {
+ log_err("Could not return policy parameters\n");
+ err = -EINVAL;
+ }
+
+ for (i = 0; i < num_pol; i++) {
+ if (uplcr[i] && kplcr[i]) {
+ if (copy_to_user(uplcr[i], kplcr[i], sizeof(**uplcr))) {
+ log_err("Could not return policy parameters\n");
+ err = -EINVAL;
+ }
+ }
+ prm.policy_params[i].dir_params.in_action.
+ enq_params.policer_params = uplcr[i];
+ }
+
+ /*
+ * None of the values of the members in the input structure have been
+ * modified, so there is no need to copy the input structure back to the
+ * user
+ */
+
+err_pol_cleanup:
+ kfree(policy_params);
+ kfree(uplcr);
+ kfree(kplcr);
+
+ return err;
+}
+
+#ifdef CONFIG_COMPAT
+static int do_sa_get_policies_compat_ioctl(void *args)
+{
+ struct ioc_dpa_ipsec_get_policies prm;
+ struct dpa_ipsec_policy_params *policy_params = NULL;
+ struct ioc_dpa_ipsec_add_rem_policy kparam;
+ struct ioc_compat_dpa_ipsec_get_policies compat_prm;
+ struct ioc_compat_policy_params *compat_pol_params = NULL;
+ struct ioc_compat_dpa_ipsec_add_rem_policy compat_uparam;
+ struct ioc_compat_policy_params *pol = NULL;
+ int i, sa_id, num_pol, err = 0;
+
+ if (copy_from_user(&compat_prm, args, sizeof(compat_prm))) {
+ log_err("Could not copy params for policy retrieval\n");
+ return -EINVAL;
+ }
+ compat_copy_dpa_ipsec_get_pols(&prm, &compat_prm);
+
+ if (prm.sa_id < 0) {
+ log_err("Invalid input SA id\n");
+ return -EINVAL;
+ }
+
+ sa_id = prm.sa_id;
+ if (!prm.policy_params) {
+ err = dpa_ipsec_sa_get_policies(sa_id, NULL, &num_pol);
+ if (err < 0) {
+ log_err("Get policies count failed\n");
+ return err;
+ }
+
+ prm.num_pol = num_pol;
+
+ compat_prm.num_pol = prm.num_pol;
+ if (copy_to_user(args, &compat_prm, sizeof(compat_prm))) {
+ log_err("Cannot copy policy count to user\n");
+ return -EINVAL;
+ }
+ return 0;
+ }
+
+ num_pol = prm.num_pol;
+ if (num_pol <= 0) {
+ log_err("Invalid number of policies for SA ID# %d\n", sa_id);
+ return -EINVAL;
+ }
+
+ policy_params = kzalloc(num_pol * sizeof(*policy_params), GFP_KERNEL);
+ if (!policy_params) {
+ log_err("Could not allocate memory for policy array\n");
+ return -ENOMEM;
+ }
+
+ err = dpa_ipsec_sa_get_policies(sa_id, policy_params, &num_pol);
+ if (err < 0 && err != -EAGAIN) {
+ log_err("Could not retrieve SA policies\n");
+ goto err_pol_cleanup;
+ } else if (err == -EAGAIN)
+ log_err("Not all SA policies could be retrieved\n");
+
+ compat_pol_params = kzalloc(num_pol * sizeof(*compat_pol_params),
+ GFP_KERNEL);
+ if (!compat_pol_params) {
+ log_err("Could not allocate memory for compat policy array!\n");
+ kfree(policy_params);
+ return -ENOMEM;
+ }
+
+ /* Allocate memory to store the array of policy objects */
+ pol = kzalloc(sizeof(*pol) * num_pol, GFP_KERNEL);
+ if (!pol) {
+ log_err("No more memory for array of policies\n");
+ err = -ENOMEM;
+ goto err_pol_cleanup;
+ }
+
+ if (copy_from_user(pol, compat_ptr(compat_prm.policy_params),
+ (sizeof(*pol) * num_pol))) {
+ log_err("Could not copy array of objects\n");
+ err = -EBUSY;
+ goto err_pol_cleanup;
+ }
+
+ for (i = 0; i < num_pol; i++) {
+ memcpy(&kparam.pol_params, &policy_params[i],
+ sizeof(kparam.pol_params));
+ memset(&compat_uparam, 0,
+ sizeof(struct ioc_compat_dpa_ipsec_add_rem_policy));
+
+ compat_uparam.pol_params.dir_params.in_action.
+ enq_params.policer_params = pol[i].dir_params.
+ in_action.enq_params.policer_params;
+
+ compat_copy_dpa_ipsec_add_rem_policy(&kparam,
+ &compat_uparam,
+ false);
+ memcpy(&compat_pol_params[i], &compat_uparam.pol_params,
+ sizeof(compat_uparam.pol_params));
+ }
+ if (copy_to_user(prm.policy_params, compat_pol_params,
+ num_pol * sizeof(*compat_pol_params))) {
+ log_err("Could not return policy parameters\n");
+ err = -EINVAL;
+ }
+
+ /*
+ * None of the values of the members in the input structure have been
+ * modified, so there is no need to copy the input structure back to the
+ * user
+ */
+
+err_pol_cleanup:
+ kfree(compat_pol_params);
+ kfree(policy_params);
+ kfree(pol);
+
+ return err;
+}
+#endif
+
+/* Set mprm - no compat case */
+static int do_sa_modify_ioctl(unsigned long args, int *sa_id,
+ struct dpa_ipsec_sa_modify_prm *mprm)
+{
+ struct ioc_dpa_ipsec_sa_modify_prm prm;
+
+ if (copy_from_user(&prm,
+ (struct ioc_dpa_ipsec_sa_modify_prm *)args,
+ sizeof(prm))) {
+ log_err("Could not copy from user modify parameters\n");
+ return -EINVAL;
+ }
+
+ if (prm.sa_id < 0) {
+ log_err("Invalid input SA id\n");
+ return -EINVAL;
+ }
+
+ *sa_id = prm.sa_id;
+
+ if (prm.modify_prm.type == DPA_IPSEC_SA_MODIFY_CRYPTO) {
+ struct dpa_ipsec_sa_crypto_params *crypto_prm;
+ crypto_prm = &prm.modify_prm.crypto_params;
+ mprm->crypto_params.cipher_key =
+ kmalloc(crypto_prm->cipher_key_len, GFP_KERNEL);
+ if (!mprm->crypto_params.cipher_key) {
+ log_err("Allocation failed for cipher key\n");
+ return -ENOMEM;
+ }
+
+ mprm->crypto_params.auth_key =
+ kmalloc(crypto_prm->auth_key_len, GFP_KERNEL);
+ if (!mprm->crypto_params.auth_key) {
+ log_err("Allocation failed for authentication key\n");
+ return -ENOMEM;
+ }
+
+ mprm->type = prm.modify_prm.type;
+ memcpy(mprm->crypto_params.cipher_key,
+ crypto_prm->cipher_key,
+ crypto_prm->cipher_key_len);
+ memcpy(mprm->crypto_params.auth_key,
+ crypto_prm->auth_key,
+ crypto_prm->auth_key_len);
+ } else {
+ memcpy(mprm, &prm.modify_prm, sizeof(prm.modify_prm));
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_COMPAT
+/* Set mprm - compat case */
+static int do_sa_modify_ioctl_compat(unsigned long args, int *sa_id,
+ struct dpa_ipsec_sa_modify_prm *mprm)
+{
+ struct ioc_compat_dpa_ipsec_sa_modify_prm prm;
+
+ if (copy_from_user(&prm,
+ (struct ioc_compat_dpa_ipsec_sa_modify_prm *)args,
+ sizeof(prm))) {
+ log_err("Could not copy from user modify parameters\n");
+ return -EINVAL;
+ }
+
+ if (prm.sa_id < 0) {
+ log_err("Invalid input SA id\n");
+ return -EINVAL;
+ }
+
+ *sa_id = prm.sa_id;
+
+ if (prm.modify_prm.type == DPA_IPSEC_SA_MODIFY_CRYPTO) {
+ struct ioc_compat_sa_crypto_params *crypto_prm;
+ crypto_prm = &prm.modify_prm.crypto_params;
+ mprm->crypto_params.cipher_key =
+ kmalloc(crypto_prm->cipher_key_len, GFP_KERNEL);
+ if (!mprm->crypto_params.cipher_key) {
+ log_err("Allocation failed for cipher key\n");
+ return -ENOMEM;
+ }
+
+ mprm->crypto_params.auth_key =
+ kmalloc(crypto_prm->auth_key_len, GFP_KERNEL);
+ if (!mprm->crypto_params.auth_key) {
+ log_err("Allocation failed for authentication key\n");
+ return -ENOMEM;
+ }
+
+ mprm->type = prm.modify_prm.type;
+ memcpy(mprm->crypto_params.cipher_key,
+ compat_ptr(crypto_prm->cipher_key),
+ crypto_prm->cipher_key_len);
+ memcpy(mprm->crypto_params.auth_key,
+ compat_ptr(crypto_prm->auth_key),
+ crypto_prm->auth_key_len);
+ } else {
+ memcpy(mprm, &prm.modify_prm, sizeof(prm.modify_prm));
+ }
+
+ return 0;
+}
+#endif
+
+int wrp_dpa_ipsec_init(void)
+{
+ /* Cannot initialize the wrapper twice */
+ if (dpa_ipsec_cdev_major >= 0)
+ return -EBUSY;
+
+ dpa_ipsec_cdev_major =
+ register_chrdev(0, DPA_IPSEC_CDEV, &dpa_ipsec_fops);
+ if (dpa_ipsec_cdev_major < 0) {
+ log_err("Could not register Dpa IPSec character device\n");
+ return dpa_ipsec_cdev_major;
+ }
+
+ ipsec_class = class_create(THIS_MODULE, DPA_IPSEC_CDEV);
+ if (IS_ERR(ipsec_class)) {
+ log_err("Cannot create DPA IPsec class device\n");
+ unregister_chrdev(dpa_ipsec_cdev_major, DPA_IPSEC_CDEV);
+ dpa_ipsec_cdev_major = -1;
+ return PTR_ERR(ipsec_class);
+ }
+
+ ipsec_dev = device_create(ipsec_class, NULL,
+ MKDEV(dpa_ipsec_cdev_major, 0), NULL,
+ DPA_IPSEC_CDEV);
+ if (IS_ERR(ipsec_dev)) {
+ log_err("Cannot create DPA IPsec device\n");
+ class_destroy(ipsec_class);
+ unregister_chrdev(dpa_ipsec_cdev_major, DPA_IPSEC_CDEV);
+ dpa_ipsec_cdev_major = -1;
+ return PTR_ERR(ipsec_dev);
+ }
+
+ return 0;
+}
+
+
+int wrp_dpa_ipsec_exit(void)
+{
+ if (dpa_ipsec_cdev_major < 0)
+ return 0;
+
+ device_destroy(ipsec_class, MKDEV(dpa_ipsec_cdev_major, 0));
+ class_destroy(ipsec_class);
+ unregister_chrdev(dpa_ipsec_cdev_major, DPA_IPSEC_CDEV);
+ dpa_ipsec_cdev_major = -1;
+
+ return 0;
+}
+
+
+int wrp_dpa_ipsec_open(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+
+int wrp_dpa_ipsec_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+long wrp_dpa_ipsec_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long args)
+{
+ return wrp_dpa_ipsec_do_ioctl(filp, cmd, args);
+}
+
+#ifdef CONFIG_COMPAT
+long wrp_dpa_ipsec_ioctl_compat(struct file *filp, unsigned int cmd,
+ unsigned long args)
+{
+
+ return wrp_dpa_ipsec_do_compat_ioctl(filp, cmd, args);
+}
+#endif
+
+long wrp_dpa_ipsec_do_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long args)
+{
+ long ret = 0;
+
+ switch (cmd) {
+ case DPA_IPSEC_IOC_INIT: {
+ struct ioc_dpa_ipsec_params kprm;
+
+ /* Copy parameters from user-space */
+ if (copy_from_user(&kprm, (void *)args, sizeof(kprm))) {
+ log_err("Could not copy DPA IPSec init parameters\n");
+ return -EINVAL;
+ }
+
+ ret = do_init_ioctl(&kprm);
+ if (ret < 0)
+ return ret;
+
+ if (copy_to_user((void *)args, &kprm, sizeof(kprm))) {
+ log_err("Could not copy to user the ID\n");
+ return -EINVAL;
+ }
+ break;
+ }
+
+ case DPA_IPSEC_IOC_FREE: {
+ int dpa_ipsec_id;
+ if (copy_from_user(&dpa_ipsec_id, (int *)args, sizeof(int))) {
+ log_err("Could not copy parameters\n");
+ return -EINVAL;
+ }
+ ret = dpa_ipsec_free(dpa_ipsec_id);
+ break;
+ }
+
+ case DPA_IPSEC_IOC_CREATE_SA: {
+ ret = do_create_sa_ioctl((void *)args);
+ break;
+ }
+
+ case DPA_IPSEC_IOC_REMOVE_SA: {
+ int sa_id;
+ if (copy_from_user(&sa_id, (int *)args, sizeof(int))) {
+ log_err("Could not copy parameters\n");
+ return -EINVAL;
+ }
+ ret = dpa_ipsec_remove_sa(sa_id);
+ break;
+ }
+
+ case DPA_IPSEC_IOC_ADD_POLICY: {
+ ret = do_add_rem_policy_ioctl((void *)args, true);
+ break;
+ }
+
+ case DPA_IPSEC_IOC_REMOVE_POLICY: {
+ ret = do_add_rem_policy_ioctl((void *)args, false);
+ break;
+ }
+
+ case DPA_IPSEC_IOC_SA_REKEYING: {
+ ret = do_sa_rekey_ioctl((void *)args);
+ break;
+ }
+
+ case DPA_IPSEC_IOC_FLUSH_ALL_SA: {
+ int dpa_ipsec_id;
+
+ if (copy_from_user(&dpa_ipsec_id, (int *)args, sizeof(int))) {
+ log_err("Could not copy parameters\n");
+ return -EINVAL;
+ }
+
+ ret = dpa_ipsec_flush_all_sa(dpa_ipsec_id);
+ break;
+ }
+
+ case DPA_IPSEC_IOC_GET_SA_POLICIES: {
+ ret = do_sa_get_policies_ioctl((void *)args);
+ break;
+ }
+
+ case DPA_IPSEC_IOC_FLUSH_SA_POLICIES: {
+ int sa_id;
+
+ if (copy_from_user(&sa_id, (int *)args, sizeof(int))) {
+ log_err("Could not copy SA id\n");
+ return -EINVAL;
+ }
+
+ ret = dpa_ipsec_sa_flush_policies(sa_id);
+ break;
+ }
+
+ case DPA_IPSEC_IOC_DISABLE_SA: {
+ int sa_id;
+
+ if (copy_from_user(&sa_id, (int *)args, sizeof(int))) {
+ log_err("Could not copy SA id\n");
+ return -EINVAL;
+ }
+
+ ret = dpa_ipsec_disable_sa(sa_id);
+ break;
+ }
+
+ case DPA_IPSEC_IOC_GET_SA_STATS: {
+ struct ioc_dpa_ipsec_sa_get_stats prm;
+
+ if (copy_from_user(&prm,
+ (struct ioc_dpa_ipsec_sa_get_stats *)args,
+ sizeof(prm))) {
+ log_err("Could not copy from user stats params\n");
+ return -EINVAL;
+ }
+
+ if (prm.sa_id < 0) {
+ log_err("Invalid input SA id\n");
+ return -EINVAL;
+ }
+
+ ret = dpa_ipsec_sa_get_stats(prm.sa_id, &prm.sa_stats);
+ if (ret < 0) {
+ log_err("Getting stats failed\n");
+ break;
+ }
+
+ if (copy_to_user((struct ioc_dpa_ipsec_sa_get_stats *)args,
+ &prm, sizeof(prm))) {
+ log_err("Could not copy stats to user\n");
+ return -EINVAL;
+ }
+ break;
+ }
+
+ case DPA_IPSEC_IOC_GET_STATS: {
+ struct ioc_dpa_ipsec_instance_stats prm;
+
+ if (copy_from_user(&prm,
+ (struct ioc_dpa_ipsec_instance_stats *)args,
+ sizeof(prm))) {
+ log_err("Could not copy from user stats params\n");
+ return -EINVAL;
+ }
+
+ if (prm.instance_id < 0) {
+ log_err("Invalid instance id\n");
+ return -EINVAL;
+ }
+
+ ret = dpa_ipsec_get_stats(prm.instance_id, &prm.stats);
+ if (ret < 0) {
+ log_err("Failed to get statistics for instance %d\n",
+ prm.instance_id);
+ break;
+ }
+
+ if (copy_to_user((struct ioc_dpa_ipsec_instance_stats *)args,
+ &prm, sizeof(prm))) {
+ log_err("Could not copy stats to user\n");
+ return -EINVAL;
+ }
+ break;
+ }
+
+ case DPA_IPSEC_IOC_SA_MODIFY: {
+ struct dpa_ipsec_sa_modify_prm modify_prm;
+ int sa_id, ret;
+
+ ret = do_sa_modify_ioctl(args, &sa_id, &modify_prm);
+
+ if (IS_ERR_VALUE(ret))
+ goto free;
+
+ ret = dpa_ipsec_sa_modify(sa_id, &modify_prm);
+ if (IS_ERR_VALUE(ret))
+ log_err("Modifying SA %d failed\n", sa_id);
+free:
+ if (modify_prm.type == DPA_IPSEC_SA_MODIFY_CRYPTO) {
+ kfree(modify_prm.crypto_params.cipher_key);
+ kfree(modify_prm.crypto_params.auth_key);
+ }
+ break;
+ }
+
+ case DPA_IPSEC_IOC_SA_REQUEST_SEQ_NUMBER: {
+ int sa_id;
+
+ if (copy_from_user(&sa_id, (int *)args, sizeof(int))) {
+ log_err("Could not copy SA id\n");
+ return -EINVAL;
+ }
+
+ ret = dpa_ipsec_sa_request_seq_number(sa_id);
+ break;
+ }
+
+ case DPA_IPSEC_IOC_SA_GET_SEQ_NUMBER: {
+ struct ioc_dpa_ipsec_sa_get_seq_num prm;
+
+ if (copy_from_user(&prm,
+ (struct ioc_dpa_ipsec_sa_get_seq_num *)args,
+ sizeof(prm))) {
+ log_err("Could not copy from user stats params\n");
+ return -EINVAL;
+ }
+
+ if (prm.sa_id < 0) {
+ log_err("Invalid input SA id\n");
+ return -EINVAL;
+ }
+
+ ret = dpa_ipsec_sa_get_seq_number(prm.sa_id, &prm.seq);
+ if (ret < 0) {
+ log_err("Get SEQ number for SA %d failed\n", prm.sa_id);
+ break;
+ }
+
+ if (copy_to_user((struct ioc_dpa_ipsec_sa_get_seq_num *)args,
+ &prm, sizeof(prm))) {
+ log_err("Could not copy SEQ number to user for SA %d\n",
+ prm.sa_id);
+ return -EINVAL;
+ }
+ break;
+ }
+
+ case DPA_IPSEC_IOC_SA_GET_OUT_PATH: {
+ struct ioc_dpa_ipsec_sa_get_out_path prm;
+
+ if (copy_from_user(&prm,
+ (struct ioc_dpa_ipsec_sa_get_out_path *)args,
+ sizeof(prm))) {
+ log_err("Could not copy from user out_path params\n");
+ return -EINVAL;
+ }
+
+ if (prm.sa_id < 0) {
+ log_err("Invalid input SA id\n");
+ return -EINVAL;
+ }
+
+ ret = dpa_ipsec_sa_get_out_path(prm.sa_id, &prm.fqid);
+ if (ret < 0) {
+ log_err("Get out path for SA %d failed\n", prm.sa_id);
+ break;
+ }
+
+ if (copy_to_user((struct ioc_dpa_ipsec_sa_get_out_path *)args,
+ &prm, sizeof(prm))) {
+ log_err("Could not copy out_path to user for SA %d\n",
+ prm.sa_id);
+ return -EINVAL;
+ }
+
+ break;
+ }
+
+ default:
+ log_err("Invalid DPA IPsec ioctl (0x%x)\n", cmd);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+#ifdef CONFIG_COMPAT
+long wrp_dpa_ipsec_do_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long args)
+{
+ long ret = 0;
+
+ switch (cmd) {
+ case DPA_IPSEC_IOC_INIT_COMPAT: {
+ struct ioc_dpa_ipsec_params kprm;
+ struct ioc_compat_dpa_ipsec_params uprm;
+
+ if (copy_from_user(&uprm, (void *)args, sizeof(uprm))) {
+ log_err("Could not copy DPA IPSec init parameters\n");
+ return -EINVAL;
+ }
+ compat_copy_dpa_ipsec_init(&kprm, &uprm);
+
+ ret = do_init_ioctl(&kprm);
+ if (ret < 0)
+ return ret;
+
+ uprm.dpa_ipsec_id = kprm.dpa_ipsec_id;
+ if (copy_to_user((void *)args, &uprm, sizeof(uprm))) {
+ log_err("Could not copy to user the DPA IPSec ID\n");
+ return -EINVAL;
+ }
+ break;
+ }
+
+ case DPA_IPSEC_IOC_FREE: {
+ int dpa_ipsec_id;
+ if (copy_from_user(&dpa_ipsec_id, (int *)args, sizeof(int))) {
+ log_err("Could not copy parameters\n");
+ return -EINVAL;
+ }
+ ret = dpa_ipsec_free(dpa_ipsec_id);
+ break;
+ }
+
+ case DPA_IPSEC_IOC_CREATE_SA_COMPAT: {
+ ret = do_create_sa_compat_ioctl((void *)args);
+ break;
+ }
+
+ case DPA_IPSEC_IOC_REMOVE_SA: {
+ int sa_id;
+ if (copy_from_user(&sa_id, (int *)args, sizeof(int))) {
+ log_err("Could not copy parameters\n");
+ return -EINVAL;
+ }
+ ret = dpa_ipsec_remove_sa(sa_id);
+ break;
+ }
+
+ case DPA_IPSEC_IOC_ADD_POLICY_COMPAT: {
+ ret = do_add_rem_policy_compat_ioctl((void *)args, true);
+ break;
+ }
+
+ case DPA_IPSEC_IOC_REMOVE_POLICY_COMPAT: {
+ ret = do_add_rem_policy_compat_ioctl((void *)args, false);
+ break;
+ }
+
+ case DPA_IPSEC_IOC_SA_REKEYING_COMPAT: {
+ ret = do_sa_rekey_compat_ioctl((void *)args);
+ break;
+ }
+
+ case DPA_IPSEC_IOC_FLUSH_ALL_SA: {
+ int dpa_ipsec_id;
+
+ if (copy_from_user(&dpa_ipsec_id,
+ (int *)args, sizeof(int))) {
+ log_err("Could not copy parameters\n");
+ return -EINVAL;
+ }
+
+ ret = dpa_ipsec_flush_all_sa(dpa_ipsec_id);
+ break;
+ }
+
+ case DPA_IPSEC_IOC_GET_SA_POLICIES_COMPAT: {
+ ret = do_sa_get_policies_compat_ioctl((void *)args);
+ break;
+ }
+
+ case DPA_IPSEC_IOC_FLUSH_SA_POLICIES: {
+ int sa_id;
+
+ if (copy_from_user(&sa_id, (int *)args, sizeof(int))) {
+ log_err("Could not copy SA id\n");
+ return -EINVAL;
+ }
+
+ ret = dpa_ipsec_sa_flush_policies(sa_id);
+ break;
+ }
+
+ case DPA_IPSEC_IOC_DISABLE_SA: {
+ int sa_id;
+
+ if (copy_from_user(&sa_id, (int *)args, sizeof(int))) {
+ log_err("Could not copy SA id\n");
+ return -EINVAL;
+ }
+
+ ret = dpa_ipsec_disable_sa(sa_id);
+ break;
+ }
+
+ case DPA_IPSEC_IOC_GET_SA_STATS: {
+ struct ioc_dpa_ipsec_sa_get_stats prm;
+
+ if (copy_from_user(&prm,
+ (struct ioc_dpa_ipsec_sa_get_stats *)args,
+ sizeof(prm))) {
+ log_err("Could not copy from user stats params\n");
+ return -EINVAL;
+ }
+
+ if (prm.sa_id < 0) {
+ log_err("Invalid input SA id\n");
+ return -EINVAL;
+ }
+
+ ret = dpa_ipsec_sa_get_stats(prm.sa_id, &prm.sa_stats);
+ if (ret < 0) {
+ log_err("Getting stats failed\n");
+ break;
+ }
+
+ if (copy_to_user((struct ioc_dpa_ipsec_sa_get_stats *)args,
+ &prm, sizeof(prm))) {
+ log_err("Could not copy stats to user\n");
+ return -EINVAL;
+ }
+
+ break;
+ }
+
+ case DPA_IPSEC_IOC_GET_STATS: {
+ struct dpa_ipsec_stats ipsec_stats;
+
+ ret = dpa_ipsec_get_stats(0, &ipsec_stats);
+ if (ret < 0) {
+ log_err("Getting stats failed\n");
+ break;
+ }
+
+ if (copy_to_user((struct dpa_ipsec_stats *)args,
+ &ipsec_stats, sizeof(ipsec_stats))) {
+ log_err("Could not copy stats to user\n");
+ return -EINVAL;
+ }
+ break;
+ }
+
+ case DPA_IPSEC_IOC_SA_MODIFY: {
+ struct dpa_ipsec_sa_modify_prm modify_prm;
+ int sa_id, ret;
+
+ ret = do_sa_modify_ioctl_compat(args, &sa_id, &modify_prm);
+ if (IS_ERR_VALUE(ret))
+ goto free;
+
+ ret = dpa_ipsec_sa_modify(sa_id, &modify_prm);
+ if (IS_ERR_VALUE(ret))
+ log_err("Modifying SA %d failed\n", sa_id);
+free:
+ if (modify_prm.type == DPA_IPSEC_SA_MODIFY_CRYPTO) {
+ kfree(modify_prm.crypto_params.cipher_key);
+ kfree(modify_prm.crypto_params.auth_key);
+ }
+
+ break;
+ }
+ default:
+ log_err("Invalid DPA IPsec ioctl (0x%x)\n", cmd);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+#endif
+
+int default_rekey_event_cb(int dpa_ipsec_id, int sa_id, int error)
+{
+ pr_info("DPA IPSec Instance %d || new sa_id %d || error %d\n",
+ dpa_ipsec_id, sa_id, error);
+ return 0;
+}
diff --git a/drivers/staging/fsl_dpa_offload/wrp_dpa_ipsec.h b/drivers/staging/fsl_dpa_offload/wrp_dpa_ipsec.h
new file mode 100644
index 0000000..f67abad
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/wrp_dpa_ipsec.h
@@ -0,0 +1,60 @@
+
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WRP_DPA_IPSEC_H_
+#define WRP_DPA_IPSEC_H_
+
+#include <linux/fs.h>
+
+
+#define DPA_IPSEC_CDEV "dpa_ipsec"
+
+
+int wrp_dpa_ipsec_init(void);
+
+int wrp_dpa_ipsec_exit(void);
+
+int wrp_dpa_ipsec_open(struct inode *inode, struct file *filp);
+
+int wrp_dpa_ipsec_release(struct inode *inode, struct file *filp);
+
+long wrp_dpa_ipsec_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long args);
+
+#ifdef CONFIG_COMPAT
+long wrp_dpa_ipsec_ioctl_compat(struct file *filp, unsigned int cmd,
+ unsigned long args);
+#endif
+
+int default_rekey_event_cb(int dpa_ipsec_id, int sa_id, int error);
+
+#endif /* WRP_DPA_IPSEC_H_ */
diff --git a/drivers/staging/fsl_dpa_offload/wrp_dpa_stats.c b/drivers/staging/fsl_dpa_offload/wrp_dpa_stats.c
new file mode 100644
index 0000000..9a044f3
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/wrp_dpa_stats.c
@@ -0,0 +1,2486 @@
+
+/* Copyright 2008-2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * DPA Stats Wrapper implementation.
+ */
+#include "wrp_dpa_stats.h"
+#include "dpa_stats_ioctl.h"
+
+/* Other includes */
+#include <linux/crc8.h>
+#include <linux/kernel.h>
+#include <linux/uaccess.h>
+#include <linux/fdtable.h>
+#include <linux/atomic.h>
+#include <linux/export.h>
+
+#include "lnxwrp_fm.h"
+#include "fm_port_ioctls.h"
+#ifdef CONFIG_COMPAT
+#include "lnxwrp_ioctls_fm_compat.h"
+#endif /* CONFIG_COMPAT */
+
+#define CRC8_WCDMA_POLY 0x9b
+
+static const struct file_operations dpa_stats_fops = {
+ .owner = THIS_MODULE,
+ .open = wrp_dpa_stats_open,
+ .read = wrp_dpa_stats_read,
+ .write = NULL,
+ .unlocked_ioctl = wrp_dpa_stats_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = wrp_dpa_stats_compat_ioctl,
+#endif /* CONFIG_COMPAT */
+ .release = wrp_dpa_stats_release
+};
+
+DECLARE_CRC8_TABLE(crc8_table);
+
+static int dpa_stats_cdev_major = -1;
+static struct class *stats_class;
+static struct device *stats_dev;
+
+struct wrp_dpa_stats_cb wrp_dpa_stats;
+
+static void wrp_dpa_stats_event_queue_init(
+ struct dpa_stats_event_queue *ev_queue);
+
+static void wrp_dpa_stats_event_queue_free(
+ struct dpa_stats_event_queue *ev_queue);
+
+static int wrp_dpa_stats_queue_event(
+ struct dpa_stats_event_queue *ev_queue,
+ struct dpa_stats_event *event);
+
+static struct dpa_stats_event *wrp_dpa_stats_dequeue_event(
+ struct dpa_stats_event_queue *ev_queue,
+ unsigned int block);
+
+static long wrp_dpa_stats_do_ioctl(struct file *filp,
+ unsigned int cmd, unsigned long args);
+
+static int copy_key_descriptor(struct dpa_offload_lookup_key *src,
+ struct dpa_offload_lookup_key **dst);
+
+static int copy_pair_descriptor(struct dpa_offload_lookup_key_pair *src,
+ struct dpa_offload_lookup_key_pair **dst);
+
+static void **copy_class_members(unsigned int size, void **src);
+
+static long store_get_cnts_async_params(
+ struct ioc_dpa_stats_cnt_request_params *kprm,
+ struct dpa_stats_async_req_ev **async_request_event);
+
+#ifdef CONFIG_COMPAT
+static long wrp_dpa_stats_do_compat_ioctl(struct file *filp,
+ unsigned int cmd,
+ unsigned long args);
+
+static int copy_key_descriptor_compatcpy(
+ struct dpa_offload_lookup_key **kprm,
+ compat_uptr_t uparam);
+
+static int copy_pair_descriptor_compatcpy(
+ struct dpa_offload_lookup_key_pair **ks_pair,
+ struct compat_ioc_dpa_offld_lookup_key_pair pair);
+
+static void dpa_stats_init_compatcpy(
+ struct ioc_dpa_stats_params *kprm,
+ struct compat_ioc_dpa_stats_params *uprm);
+
+static void dpa_stats_reass_cnt_compatcpy(
+ struct dpa_stats_cnt_reass *kprm,
+ struct dpa_stats_compat_cnt_reass *uprm);
+
+static void dpa_stats_frag_cnt_compatcpy(
+ struct dpa_stats_cnt_frag *kprm,
+ struct dpa_stats_compat_cnt_frag *uprm);
+
+static void dpa_stats_plcr_cnt_compatcpy(
+ struct dpa_stats_cnt_plcr *kprm,
+ struct dpa_stats_compat_cnt_plcr *uprm);
+
+static long dpa_stats_tbl_cnt_compatcpy(
+ struct dpa_stats_cnt_classif_tbl *kprm,
+ struct dpa_stats_compat_cnt_classif_tbl *uprm);
+
+static long dpa_stats_ccnode_cnt_compatcpy(
+ struct dpa_stats_cnt_classif_node *kprm,
+ struct dpa_stats_compat_cnt_classif_node *uprm);
+
+static long dpa_stats_eth_cls_compatcpy(
+ struct dpa_stats_cls_cnt_eth *kprm,
+ struct dpa_stats_compat_cls_cnt_eth *uprm,
+ uint32_t cls_members);
+
+static long dpa_stats_reass_cls_compatcpy(
+ struct dpa_stats_cls_cnt_reass *kprm,
+ struct dpa_stats_compat_cnt_reass *uprm,
+ uint32_t cls_members);
+
+static long dpa_stats_frag_cls_compatcpy(
+ struct dpa_stats_cls_cnt_frag *kprm,
+ struct dpa_stats_compat_cnt_frag *uprm,
+ uint32_t cls_members);
+
+static long dpa_stats_plcr_cls_compatcpy(
+ struct dpa_stats_cls_cnt_plcr *kprm,
+ struct dpa_stats_compat_cnt_plcr *uprm,
+ uint32_t cls_members);
+
+static long dpa_stats_tbl_cls_compatcpy(
+ struct dpa_stats_cls_cnt_classif_tbl *kprm,
+ struct dpa_stats_compat_cls_cnt_classif_tbl *uprm,
+ uint32_t cls_members);
+
+static long dpa_stats_ccnode_cls_compatcpy(
+ struct dpa_stats_cls_cnt_classif_node *kprm,
+ struct dpa_stats_compat_cls_cnt_classif_node *uprm,
+ uint32_t cls_members);
+
+static long dpa_stats_ipsec_cls_compatcpy(
+ struct dpa_stats_cls_cnt_ipsec *kprm,
+ struct dpa_stats_compat_cls_cnt_ipsec *uprm,
+ uint32_t cls_members);
+#endif
+
+int wrp_dpa_stats_init(void)
+{
+ /* Cannot initialize the wrapper twice */
+ if (dpa_stats_cdev_major >= 0)
+ return -EBUSY;
+
+ dpa_stats_cdev_major =
+ register_chrdev(0, DPA_STATS_CDEV, &dpa_stats_fops);
+ if (dpa_stats_cdev_major < 0) {
+ log_err("Cannot register DPA Stats character device\n");
+ return dpa_stats_cdev_major;
+ }
+
+ stats_class = class_create(THIS_MODULE, DPA_STATS_CDEV);
+ if (IS_ERR(stats_class)) {
+ log_err("Cannot create DPA Stats class device\n");
+ unregister_chrdev(dpa_stats_cdev_major, DPA_STATS_CDEV);
+ dpa_stats_cdev_major = -1;
+ return PTR_ERR(stats_class);
+ }
+
+ stats_dev = device_create(stats_class, NULL,
+ MKDEV(dpa_stats_cdev_major, 0), NULL, DPA_STATS_CDEV);
+ if (IS_ERR(stats_dev)) {
+ log_err("Cannot create DPA Stats device\n");
+ class_destroy(stats_class);
+ unregister_chrdev(dpa_stats_cdev_major, DPA_STATS_CDEV);
+ dpa_stats_cdev_major = -1;
+ return PTR_ERR(stats_dev);
+ }
+
+ /* Initialize the event queue */
+ wrp_dpa_stats_event_queue_init(&wrp_dpa_stats.ev_queue);
+
+ return 0;
+}
+
+int wrp_dpa_stats_exit(void)
+{
+ if (dpa_stats_cdev_major < 0)
+ return 0;
+ device_destroy(stats_class, MKDEV(dpa_stats_cdev_major, 0));
+ class_destroy(stats_class);
+ unregister_chrdev(dpa_stats_cdev_major, DPA_STATS_CDEV);
+ dpa_stats_cdev_major = -1;
+
+ /* Destroy the event queue */
+ wrp_dpa_stats_event_queue_free(&wrp_dpa_stats.ev_queue);
+
+ return 0;
+}
+
+int wrp_dpa_stats_open(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+
+int wrp_dpa_stats_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+#ifdef CONFIG_COMPAT
+long wrp_dpa_stats_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long args)
+{
+ return wrp_dpa_stats_do_compat_ioctl(filp, cmd, args);
+}
+#endif /* CONFIG_COMPAT */
+
+long wrp_dpa_stats_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long args)
+{
+ return wrp_dpa_stats_do_ioctl(filp, cmd, args);
+}
+
+#ifdef CONFIG_COMPAT
+ssize_t wrp_dpa_stats_read(struct file *file,
+ char *buf, size_t count, loff_t *off)
+{
+ struct dpa_stats_event *event;
+ struct compat_dpa_stats_event_params ev_prm;
+ size_t c = 0;
+
+ /*
+ * Make sure that the size of the buffer requested by the user is
+ * at least the size of an event
+ */
+ if (count < sizeof(struct compat_dpa_stats_event_params))
+ return -EINVAL;
+
+ /* Dequeue first event by using a blocking call */
+ event = wrp_dpa_stats_dequeue_event(&wrp_dpa_stats.ev_queue, 0);
+
+ while (event) {
+ memset(&ev_prm, 0,
+ sizeof(struct compat_dpa_stats_event_params));
+
+ if (event->params.bytes_written > 0 && wrp_dpa_stats.k_mem) {
+ if (copy_to_user(wrp_dpa_stats.us_mem +
+ event->params.storage_area_offset,
+ wrp_dpa_stats.k_mem +
+ event->params.storage_area_offset,
+ event->params.bytes_written)) {
+ log_err("Cannot copy counter values to storage area\n");
+ return -EFAULT;
+ }
+ }
+
+ ev_prm.bytes_written = event->params.bytes_written;
+ ev_prm.cnts_written = event->params.cnts_written;
+ ev_prm.dpa_stats_id = event->params.dpa_stats_id;
+ ev_prm.storage_area_offset = event->params.storage_area_offset;
+ ev_prm.request_done = ptr_to_compat(event->params.request_done);
+ ev_prm.us_cnt_ids = event->params.us_cnt_ids;
+ ev_prm.cnt_ids_len = event->params.cnt_ids_len;
+
+ if (copy_to_user((compat_ptr)(ev_prm.us_cnt_ids),
+ event->ks_cnt_ids,
+ (event->params.cnt_ids_len * sizeof(int)))) {
+ kfree(event);
+ return -EFAULT;
+ }
+
+ if (copy_to_user(buf + c, &ev_prm, sizeof(ev_prm)) != 0) {
+ kfree(event);
+ return -EFAULT;
+ }
+
+ kfree(event->ks_cnt_ids);
+ kfree(event);
+
+ count -= sizeof(struct compat_dpa_stats_event_params);
+ c += sizeof(struct compat_dpa_stats_event_params);
+
+ if (count < sizeof(struct compat_dpa_stats_event_params))
+ break;
+
+ /* For subsequent events, don't block */
+ event = wrp_dpa_stats_dequeue_event(
+ &wrp_dpa_stats.ev_queue, O_NONBLOCK);
+ }
+
+ return c;
+}
+#else
+ssize_t wrp_dpa_stats_read(struct file *file,
+ char *buf, size_t count, loff_t *off)
+{
+ struct dpa_stats_event *event;
+ size_t c = 0;
+
+ /*
+ * Make sure that the size of the buffer requested by the user is
+ * at least the size of an event
+ */
+ if (count < sizeof(struct dpa_stats_event_params))
+ return -EINVAL;
+
+ /* Dequeue first event by using a blocking call */
+ event = wrp_dpa_stats_dequeue_event(&wrp_dpa_stats.ev_queue, 0);
+ while (event) {
+ if (event->params.bytes_written > 0 && wrp_dpa_stats.k_mem) {
+ if (copy_to_user(wrp_dpa_stats.us_mem +
+ event->params.storage_area_offset,
+ wrp_dpa_stats.k_mem +
+ event->params.storage_area_offset,
+ event->params.bytes_written)) {
+ log_err("Cannot copy counter values to storage area\n");
+ return -EFAULT;
+ }
+ }
+
+ if (copy_to_user(buf + c,
+ &event->params,
+ sizeof(struct dpa_stats_event_params)) != 0) {
+ kfree(event);
+ return -EFAULT;
+ }
+
+ kfree(event->ks_cnt_ids);
+ kfree(event);
+
+ count -= sizeof(struct dpa_stats_event_params);
+ c += sizeof(struct dpa_stats_event_params);
+
+ if (count < sizeof(struct dpa_stats_event_params))
+ break;
+
+ /* For subsequent events, don't block */
+ event = wrp_dpa_stats_dequeue_event(
+ &wrp_dpa_stats.ev_queue, O_NONBLOCK);
+ }
+
+ return c;
+}
+#endif
+
+static void wrp_dpa_stats_event_queue_init(
+ struct dpa_stats_event_queue *event_queue)
+{
+ INIT_LIST_HEAD(&event_queue->lh);
+ mutex_init(&wrp_dpa_stats.event_queue_lock);
+ atomic_set(&event_queue->count, 0);
+ init_waitqueue_head(&event_queue->wq);
+}
+
+static void wrp_dpa_stats_event_queue_free(
+ struct dpa_stats_event_queue *event_queue)
+{
+ struct dpa_stats_event *entry, *tmp;
+
+ /* Remove remaining events from the event queue */
+ mutex_lock(&wrp_dpa_stats.event_queue_lock);
+ list_for_each_entry_safe(entry, tmp, &event_queue->lh, lh) {
+ list_del(&entry->lh);
+ atomic_dec(&event_queue->count);
+ kfree(entry);
+ }
+ mutex_unlock(&wrp_dpa_stats.event_queue_lock);
+}
+
+static int wrp_dpa_stats_queue_event(struct dpa_stats_event_queue *event_queue,
+ struct dpa_stats_event *event)
+{
+ /* If the event queue is already full, abort: */
+ if (atomic_read(&event_queue->count) >= QUEUE_MAX_EVENTS) {
+ log_err("Cannot enqueue new event, queue is full(%d)\n",
+ QUEUE_MAX_EVENTS);
+ return -EBUSY;
+ }
+
+ /* Add the event to the event queue */
+ mutex_lock(&wrp_dpa_stats.event_queue_lock);
+ list_add_tail(&event->lh, &event_queue->lh);
+ atomic_inc(&event_queue->count);
+ mutex_unlock(&wrp_dpa_stats.event_queue_lock);
+
+ /* Wake up consumers */
+ wake_up_interruptible(&event_queue->wq);
+ return 0;
+}
+
+static struct dpa_stats_event *wrp_dpa_stats_dequeue_event(
+ struct dpa_stats_event_queue *event_queue, unsigned int block)
+{
+ struct dpa_stats_event *event;
+
+ /*
+ * If the event queue is empty we perform an interruptible sleep
+ * until an event is inserted into the queue. We use the event queue
+ * spinlock to protect ourselves from race conditions.
+ */
+ mutex_lock(&wrp_dpa_stats.event_queue_lock);
+
+ while (list_empty(&event_queue->lh)) {
+ mutex_unlock(&wrp_dpa_stats.event_queue_lock);
+
+ /* If a non blocking action was requested, return failure: */
+ if (block & O_NONBLOCK)
+ return NULL;
+
+ if (wait_event_interruptible(event_queue->wq,
+ !list_empty(&event_queue->lh)))
+ /* Woken up by some signal... */
+ return NULL;
+
+ mutex_lock(&wrp_dpa_stats.event_queue_lock);
+ }
+
+ /* Consume one event */
+ event = list_entry((&event_queue->lh)->next,
+ struct dpa_stats_event, lh);
+ list_del(&event->lh);
+ atomic_dec(&event_queue->count);
+ mutex_unlock(&wrp_dpa_stats.event_queue_lock);
+
+ return event;
+}
+
+void do_ioctl_req_done_cb(int dpa_stats_id,
+ unsigned int storage_area_offset,
+ unsigned int cnts_written, int bytes_written)
+{
+ struct dpa_stats_event *event = NULL;
+ struct dpa_stats_async_req_ev *async_req_ev;
+ struct list_head *async_req_grp, *pos;
+ uint8_t grp_idx = 0;
+ bool found = false;
+
+ /* Obtain the group the request belongs to */
+ grp_idx = crc8(crc8_table,
+ (uint8_t *)&storage_area_offset,
+ sizeof(unsigned int),
+ 0);
+ async_req_grp = &wrp_dpa_stats.async_req_group[grp_idx];
+ mutex_lock(&wrp_dpa_stats.async_req_lock);
+ BUG_ON(list_empty(async_req_grp));
+
+ /* Search in the request group the request event */
+ list_for_each(pos, async_req_grp) {
+ async_req_ev = list_entry(pos,
+ struct dpa_stats_async_req_ev, node);
+
+ if (async_req_ev->storage_area_offset == storage_area_offset) {
+ list_del(&async_req_ev->node);
+ list_add_tail(&async_req_ev->node,
+ &wrp_dpa_stats.async_req_pool);
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ log_err("Cannot find event in the event list\n");
+ mutex_unlock(&wrp_dpa_stats.async_req_lock);
+ return;
+ }
+
+ /* Generate new event description: */
+ event = kmalloc(sizeof(struct dpa_stats_event), GFP_KERNEL);
+ if (!event) {
+ log_err("Cannot allocate memory for a new event\n");
+ mutex_unlock(&wrp_dpa_stats.async_req_lock);
+ return;
+ }
+
+ /* Fill up the event parameters data structure */
+ event->params.dpa_stats_id = dpa_stats_id;
+ event->params.storage_area_offset = storage_area_offset;
+ event->params.cnts_written = cnts_written;
+ event->params.bytes_written = bytes_written;
+ event->params.request_done = async_req_ev->request_done;
+#ifdef CONFIG_COMPAT
+ event->ks_cnt_ids = async_req_ev->ks_cnt_ids;
+ event->params.us_cnt_ids = async_req_ev->us_cnt_ids;
+ event->params.cnt_ids_len = async_req_ev->cnt_ids_len;
+#else
+ event->ks_cnt_ids = NULL;
+ event->params.us_cnt_ids = NULL;
+ event->params.cnt_ids_len = 0;
+#endif /* CONFIG_COMPAT */
+
+ mutex_unlock(&wrp_dpa_stats.async_req_lock);
+
+ /* Queue this event */
+ if (wrp_dpa_stats_queue_event(&wrp_dpa_stats.ev_queue, event) != 0) {
+ log_err("Cannot enqueue a new event\n");
+ kfree(event);
+ return;
+ }
+
+ return;
+}
+
+static long do_ioctl_stats_init(struct ioc_dpa_stats_params *prm)
+{
+ struct dpa_stats_async_req_ev *async_req_ev;
+ struct dpa_stats_params params;
+ long ret = 0;
+ uint16_t i;
+
+ /* Save user-provided parameters */
+ params.max_counters = prm->max_counters;
+ params.storage_area_len = prm->storage_area_len;
+
+ if (prm->stg_area_mapped) {
+ /*
+ * Storage area is mapped, obtain the kernel-space memory area
+ * pointer from the physical address
+ */
+ params.storage_area = phys_to_virt(prm->phys_stg_area);
+ if (!params.storage_area) {
+ log_err("Invalid physical memory address for storage area\n");
+ return -EINVAL;
+ }
+ wrp_dpa_stats.k_mem = NULL;
+ } else {
+ /* Save user-space memory area pointer */
+ wrp_dpa_stats.us_mem = prm->virt_stg_area;
+
+ /* Allocate kernel-space memory to store the statistics */
+ params.storage_area = kzalloc(
+ prm->storage_area_len, GFP_KERNEL);
+ if (!params.storage_area) {
+ log_err("Cannot allocate memory for kernel storage area\n");
+ return -ENOMEM;
+ }
+
+ /* Save kernel-space memory area pointer */
+ wrp_dpa_stats.k_mem = params.storage_area;
+ }
+
+ /* Call init function */
+ ret = dpa_stats_init(&params, &prm->dpa_stats_id);
+ if (ret < 0)
+ return ret;
+
+ /* Init CRC8 table */
+ crc8_populate_msb(crc8_table, CRC8_WCDMA_POLY);
+
+ /* Allocate asynchronous requests groups lists */
+ wrp_dpa_stats.async_req_group = kmalloc(DPA_STATS_MAX_NUM_OF_REQUESTS *
+ sizeof(struct list_head), GFP_KERNEL);
+ if (!wrp_dpa_stats.async_req_group) {
+ log_err("Cannot allocate memory for asynchronous requests group\n");
+ return -ENOMEM;
+ }
+
+ /* Initialize list of free async requests nodes */
+ INIT_LIST_HEAD(&wrp_dpa_stats.async_req_pool);
+
+ for (i = 0; i < DPA_STATS_MAX_NUM_OF_REQUESTS; i++) {
+
+ /* Initialize the list of async requests in the same group */
+ INIT_LIST_HEAD(&wrp_dpa_stats.async_req_group[i]);
+
+ /* Allocate an asynchronous request event node */
+ async_req_ev = kzalloc(sizeof(*async_req_ev), GFP_KERNEL);
+ if (!async_req_ev) {
+ struct dpa_stats_async_req_ev *tmp;
+
+ list_for_each_entry_safe(async_req_ev, tmp,
+ &wrp_dpa_stats.async_req_pool, node) {
+ list_del(&async_req_ev->node);
+ kfree(async_req_ev);
+ }
+ log_err("Cannot allocate memory for asynchronous request event\n");
+ return -ENOMEM;
+ }
+
+ list_add_tail(&async_req_ev->node,
+ &wrp_dpa_stats.async_req_pool);
+ }
+
+ mutex_init(&wrp_dpa_stats.async_req_lock);
+
+ return ret;
+}
+
+static long do_ioctl_stats_free(void *args)
+{
+ struct dpa_stats_async_req_ev *async_req_ev, *tmp;
+ int dpa_stats_id;
+ long ret;
+
+ if (copy_from_user(&dpa_stats_id, (int *)args, sizeof(int))) {
+ log_err("Cannot copy user parameters\n");
+ return -EINVAL;
+ }
+
+ /* Release kernel allocated memory */
+ kfree(wrp_dpa_stats.k_mem);
+
+ mutex_lock(&wrp_dpa_stats.async_req_lock);
+ list_for_each_entry_safe(async_req_ev,
+ tmp, &wrp_dpa_stats.async_req_pool, node) {
+ list_del(&async_req_ev->node);
+ kfree(async_req_ev);
+ }
+ mutex_unlock(&wrp_dpa_stats.async_req_lock);
+
+ ret = dpa_stats_free(dpa_stats_id);
+ if (ret < 0)
+ return ret;
+
+ return ret;
+}
+
+static int do_ioctl_stats_create_counter(void *args)
+{
+ struct ioc_dpa_stats_cnt_params prm;
+ struct dpa_offload_lookup_key *us_key = NULL;
+ long ret = 0;
+
+ if (copy_from_user(&prm, args, sizeof(prm))) {
+ log_err("Could not copy counter parameters\n");
+ return -EINVAL;
+ }
+
+ if (prm.cnt_params.type == DPA_STATS_CNT_CLASSIF_NODE &&
+ prm.cnt_params.classif_node_params.key) {
+ /* Save user-space provided key */
+ us_key = prm.cnt_params.classif_node_params.key;
+
+ /* Override user-space pointers with kernel memory */
+ ret = copy_key_descriptor(us_key,
+ &prm.cnt_params.classif_node_params.key);
+ if (ret != 0) {
+ log_err("Could not copy the key descriptor\n");
+ return ret;
+ }
+ }
+
+ if (prm.cnt_params.type == DPA_STATS_CNT_CLASSIF_TBL &&
+ prm.cnt_params.classif_tbl_params.key) {
+ /* Save user-space provided key */
+ us_key = prm.cnt_params.classif_tbl_params.key;
+
+ /* Override user-space pointers with kernel memory */
+ ret = copy_key_descriptor(us_key,
+ &prm.cnt_params.classif_tbl_params.key);
+ if (ret != 0) {
+ log_err("Could not copy the key descriptor\n");
+ return ret;
+ }
+ }
+
+ ret = dpa_stats_create_counter(prm.stats_id,
+ &prm.cnt_params, &prm.cnt_id);
+
+ if (prm.cnt_params.type == DPA_STATS_CNT_CLASSIF_NODE &&
+ prm.cnt_params.classif_node_params.key) {
+ /* Release kernel-allocated memory */
+ kfree(prm.cnt_params.classif_node_params.key->byte);
+ kfree(prm.cnt_params.classif_node_params.key->mask);
+ kfree(prm.cnt_params.classif_node_params.key);
+ /* Restore user-provided key */
+ prm.cnt_params.classif_node_params.key = us_key;
+ }
+
+ if (prm.cnt_params.type == DPA_STATS_CNT_CLASSIF_TBL &&
+ prm.cnt_params.classif_tbl_params.key) {
+ /* Release kernel-allocated memory */
+ kfree(prm.cnt_params.classif_tbl_params.key->byte);
+ kfree(prm.cnt_params.classif_tbl_params.key->mask);
+ kfree(prm.cnt_params.classif_tbl_params.key);
+ /* Restore user-provided key */
+ prm.cnt_params.classif_tbl_params.key = us_key;
+ }
+
+ if (copy_to_user(args, &prm, sizeof(prm))) {
+ log_err("Could not copy to user the Counter ID\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+#ifdef CONFIG_COMPAT
+static int do_ioctl_stats_compat_create_counter(void *args)
+{
+ struct ioc_dpa_stats_cnt_params kprm;
+ struct compat_ioc_dpa_stats_cnt_params uprm;
+ long ret = 0;
+
+ if (copy_from_user(&uprm, args, sizeof(uprm))) {
+ log_err("Cannot copy from user counter parameters\n");
+ return -EINVAL;
+ }
+
+ memset(&kprm, 0, sizeof(struct ioc_dpa_stats_cnt_params));
+ kprm.stats_id = uprm.stats_id;
+ kprm.cnt_params.type = uprm.cnt_params.type;
+
+ switch (kprm.cnt_params.type) {
+ case DPA_STATS_CNT_ETH:
+ memcpy(&kprm.cnt_params.eth_params,
+ &uprm.cnt_params.eth_params,
+ sizeof(struct dpa_stats_cnt_eth));
+ break;
+ case DPA_STATS_CNT_REASS:
+ dpa_stats_reass_cnt_compatcpy(&kprm.cnt_params.reass_params,
+ &uprm.cnt_params.reass_params);
+ break;
+ case DPA_STATS_CNT_FRAG:
+ dpa_stats_frag_cnt_compatcpy(&kprm.cnt_params.frag_params,
+ &uprm.cnt_params.frag_params);
+ break;
+ case DPA_STATS_CNT_POLICER:
+ dpa_stats_plcr_cnt_compatcpy(&kprm.cnt_params.plcr_params,
+ &uprm.cnt_params.plcr_params);
+ break;
+ case DPA_STATS_CNT_CLASSIF_TBL:
+ ret = dpa_stats_tbl_cnt_compatcpy(
+ &kprm.cnt_params.classif_tbl_params,
+ &uprm.cnt_params.classif_tbl_params);
+ if (ret < 0)
+ return ret;
+ break;
+ case DPA_STATS_CNT_CLASSIF_NODE:
+ ret = dpa_stats_ccnode_cnt_compatcpy(
+ &kprm.cnt_params.classif_node_params,
+ &uprm.cnt_params.classif_node_params);
+ if (ret < 0)
+ return ret;
+ break;
+ case DPA_STATS_CNT_IPSEC:
+ memcpy(&kprm.cnt_params.ipsec_params,
+ &uprm.cnt_params.ipsec_params,
+ sizeof(struct dpa_stats_cnt_ipsec));
+ break;
+ case DPA_STATS_CNT_TRAFFIC_MNG:
+ kprm.cnt_params.traffic_mng_params.cnt_sel =
+ uprm.cnt_params.traffic_mng_params.cnt_sel;
+ kprm.cnt_params.traffic_mng_params.src =
+ uprm.cnt_params.traffic_mng_params.src;
+ break;
+ default:
+ break;
+ }
+
+ ret = dpa_stats_create_counter(kprm.stats_id,
+ &kprm.cnt_params, &kprm.cnt_id);
+
+ if (kprm.cnt_params.type == DPA_STATS_CNT_CLASSIF_NODE &&
+ compat_ptr(uprm.cnt_params.classif_node_params.key)) {
+ kfree(kprm.cnt_params.classif_node_params.key->byte);
+ kfree(kprm.cnt_params.classif_node_params.key->mask);
+ kfree(kprm.cnt_params.classif_node_params.key);
+ }
+
+ if (kprm.cnt_params.type == DPA_STATS_CNT_CLASSIF_TBL &&
+ compat_ptr(uprm.cnt_params.classif_tbl_params.key)) {
+ kfree(kprm.cnt_params.classif_tbl_params.key->byte);
+ kfree(kprm.cnt_params.classif_tbl_params.key->mask);
+ kfree(kprm.cnt_params.classif_tbl_params.key);
+ }
+
+ uprm.cnt_id = kprm.cnt_id;
+
+ if (copy_to_user(args, &uprm, sizeof(uprm))) {
+ log_err("Cannot copy to user counter parameters\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+#endif
+
+static int do_ioctl_stats_create_class_counter(void *args)
+{
+ struct ioc_dpa_stats_cls_cnt_params prm;
+ struct dpa_stats_cls_cnt_classif_node *cnode;
+ struct dpa_stats_cls_cnt_classif_tbl *tbl;
+ struct dpa_offload_lookup_key **us_keys = NULL;
+ struct dpa_offload_lookup_key_pair **us_pairs = NULL;
+ uint32_t i = 0;
+ unsigned int cls_mbrs;
+ void **cls_objs = NULL;
+ int *sa_ids = NULL;
+ long ret = 0;
+
+ if (copy_from_user(&prm, args, sizeof(prm))) {
+ log_err("Cannot copy from user class counter parameters\n");
+ return -EINVAL;
+ }
+
+ cls_mbrs = prm.cnt_params.class_members;
+
+ switch (prm.cnt_params.type) {
+ case DPA_STATS_CNT_ETH: {
+ struct dpa_stats_cnt_eth_src *eth_src = NULL;
+
+ /* Allocate memory to store the sources array */
+ eth_src = kmalloc(sizeof(*eth_src) * cls_mbrs, GFP_KERNEL);
+ if (!eth_src) {
+ log_err("Cannot allocate memory for Ethernet sources array\n");
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(eth_src,
+ prm.cnt_params.eth_params.src,
+ sizeof(*eth_src) * cls_mbrs)) {
+ log_err("Cannot copy array of Ethernet sources\n");
+ kfree(eth_src);
+ return -EBUSY;
+ }
+ prm.cnt_params.eth_params.src = eth_src;
+ break;
+ }
+ case DPA_STATS_CNT_REASS:
+ /* Save the user-space pointer */
+ cls_objs = prm.cnt_params.reass_params.reass;
+
+ prm.cnt_params.reass_params.reass = copy_class_members(cls_mbrs,
+ prm.cnt_params.reass_params.reass);
+ if (!prm.cnt_params.reass_params.reass) {
+ log_err("Cannot copy array of Reassembly objects\n");
+ prm.cnt_params.reass_params.reass = cls_objs;
+ return -EBUSY;
+ }
+ break;
+ case DPA_STATS_CNT_FRAG:
+ /* Save the user-space pointer */
+ cls_objs = prm.cnt_params.frag_params.frag;
+
+ prm.cnt_params.frag_params.frag = copy_class_members(cls_mbrs,
+ prm.cnt_params.frag_params.frag);
+ if (!prm.cnt_params.frag_params.frag) {
+ log_err("Cannot copy array of Fragmentation objects\n");
+ prm.cnt_params.frag_params.frag = cls_objs;
+ return -EBUSY;
+ }
+ break;
+ case DPA_STATS_CNT_POLICER:
+ /* Save the user-space pointer */
+ cls_objs = prm.cnt_params.plcr_params.plcr;
+
+ prm.cnt_params.plcr_params.plcr = copy_class_members(cls_mbrs,
+ prm.cnt_params.plcr_params.plcr);
+ if (!prm.cnt_params.plcr_params.plcr) {
+ log_err("Cannot copy array of Policer objects\n");
+ prm.cnt_params.plcr_params.plcr = cls_objs;
+ return -EBUSY;
+ }
+ break;
+ case DPA_STATS_CNT_CLASSIF_TBL:
+ tbl = &prm.cnt_params.classif_tbl_params;
+
+ if (tbl->key_type == DPA_STATS_CLASSIF_SINGLE_KEY) {
+ /* Save array of user-space provided key pointers */
+ us_keys = tbl->keys;
+
+ /* Override user-space pointers with kernel memory */
+ tbl->keys = kzalloc(cls_mbrs *
+ sizeof(**tbl->keys), GFP_KERNEL);
+ if (!tbl->keys) {
+ log_err("Cannot allocate kernel memory for lookup keys array\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < cls_mbrs; i++) {
+ if (!us_keys[i])
+ continue;
+ ret = copy_key_descriptor(us_keys[i],
+ &tbl->keys[i]);
+ if (ret != 0) {
+ log_err("Cannot copy key descriptor\n");
+ goto create_cls_counter_cleanup;
+ }
+ }
+ } else if (tbl->key_type == DPA_STATS_CLASSIF_PAIR_KEY) {
+ /* Save array of user-space provided pairs pointers */
+ us_pairs = tbl->pairs;
+
+ /* Override user-space pointers with kernel memory */
+ tbl->pairs = kzalloc(cls_mbrs *
+ sizeof(**tbl->pairs), GFP_KERNEL);
+ if (!tbl->pairs) {
+ log_err("Cannot allocate kernel memory for lookup pairs array\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < cls_mbrs; i++) {
+ if (!us_pairs[i])
+ continue;
+ ret = copy_pair_descriptor(us_pairs[i],
+ &tbl->pairs[i]);
+ if (ret != 0) {
+ log_err("Could not copy the pair key descriptor\n");
+ goto create_cls_counter_cleanup;
+ }
+ }
+ }
+ break;
+ case DPA_STATS_CNT_CLASSIF_NODE:
+ cnode = &prm.cnt_params.classif_node_params;
+
+ if (!cnode->keys) {
+ log_err("Pointer to array of keys can't be NULL\n");
+ return -EINVAL;
+ }
+ /* Save array of user-space provided key pointers */
+ us_keys = cnode->keys;
+
+ /* Override user-space pointers with kernel memory */
+ cnode->keys = kzalloc(cls_mbrs *
+ sizeof(**cnode->keys), GFP_KERNEL);
+ if (!cnode->keys) {
+ log_err("No more memory to store array of keys\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < cls_mbrs; i++) {
+ if (!us_keys[i])
+ continue;
+ ret = copy_key_descriptor(us_keys[i], &cnode->keys[i]);
+ if (ret != 0) {
+ log_err("Cannot copy the key descriptor\n");
+ goto create_cls_counter_cleanup;
+ }
+ }
+ break;
+ case DPA_STATS_CNT_IPSEC:
+ /* Allocate memory to store the sa ids array */
+ sa_ids = kmalloc(cls_mbrs * sizeof(*sa_ids), GFP_KERNEL);
+ if (!sa_ids) {
+ log_err("Cannot allocate memory for SA ids array\n");
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(sa_ids,
+ prm.cnt_params.ipsec_params.sa_id,
+ (cls_mbrs * sizeof(*sa_ids)))) {
+ log_err("Cannot copy from user array of SA ids\n");
+ kfree(sa_ids);
+ return -EBUSY;
+ }
+
+ prm.cnt_params.ipsec_params.sa_id = sa_ids;
+ break;
+ default:
+ break;
+ }
+
+ ret = dpa_stats_create_class_counter(prm.stats_id,
+ &prm.cnt_params, &prm.cnt_id);
+create_cls_counter_cleanup:
+ switch (prm.cnt_params.type) {
+ case DPA_STATS_CNT_ETH:
+ kfree(prm.cnt_params.eth_params.src);
+ break;
+ case DPA_STATS_CNT_REASS:
+ kfree(prm.cnt_params.reass_params.reass);
+ prm.cnt_params.reass_params.reass = cls_objs;
+ break;
+ case DPA_STATS_CNT_FRAG:
+ kfree(prm.cnt_params.frag_params.frag);
+ prm.cnt_params.frag_params.frag = cls_objs;
+ break;
+ case DPA_STATS_CNT_POLICER:
+ kfree(prm.cnt_params.plcr_params.plcr);
+ prm.cnt_params.plcr_params.plcr = cls_objs;
+ break;
+ case DPA_STATS_CNT_CLASSIF_TBL:
+ tbl = &prm.cnt_params.classif_tbl_params;
+
+ if (tbl->key_type == DPA_STATS_CLASSIF_SINGLE_KEY) {
+ for (i = 0; i < cls_mbrs; i++) {
+ if (!tbl->keys[i])
+ continue;
+ /* Free allocated memory */
+ kfree(tbl->keys[i]->byte);
+ kfree(tbl->keys[i]->mask);
+ kfree(tbl->keys[i]);
+ }
+ kfree(tbl->keys);
+ /* Restore user-space pointers */
+ tbl->keys = us_keys;
+ }
+
+ if (tbl->key_type == DPA_STATS_CLASSIF_PAIR_KEY) {
+ for (i = 0; i < cls_mbrs; i++) {
+ if (!tbl->pairs[i])
+ continue;
+
+ if (tbl->pairs[i]->first_key) {
+ kfree(tbl->pairs[i]->first_key->byte);
+ kfree(tbl->pairs[i]->first_key->mask);
+ kfree(tbl->pairs[i]->first_key);
+ }
+ if (tbl->pairs[i]->second_key) {
+ kfree(tbl->pairs[i]->second_key->byte);
+ kfree(tbl->pairs[i]->second_key->mask);
+ kfree(tbl->pairs[i]->second_key);
+ }
+ kfree(tbl->pairs[i]);
+ }
+ kfree(tbl->pairs);
+ /* Restore user-space pointers */
+ tbl->pairs = us_pairs;
+ }
+ break;
+ case DPA_STATS_CNT_CLASSIF_NODE:
+ cnode = &prm.cnt_params.classif_node_params;
+
+ for (i = 0; i < cls_mbrs; i++) {
+ if (!cnode->keys[i])
+ continue;
+ /* Free allocated memory */
+ kfree(cnode->keys[i]->byte);
+ kfree(cnode->keys[i]->mask);
+ kfree(cnode->keys[i]);
+ }
+ kfree(cnode->keys);
+ /* Restore user-space pointers */
+ cnode->keys = us_keys;
+ break;
+ case DPA_STATS_CNT_IPSEC:
+ kfree(sa_ids);
+ break;
+ default:
+ break;
+ }
+
+ if (copy_to_user(args, &prm, sizeof(prm))) {
+ log_err("Cannot copy to user class counter parameters\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+#ifdef CONFIG_COMPAT
+static int do_ioctl_stats_compat_create_class_counter(void *args)
+{
+ struct ioc_dpa_stats_cls_cnt_params kprm;
+ struct compat_ioc_dpa_stats_cls_cnt_params uprm;
+ struct dpa_stats_cls_cnt_params *kprm_cls = &kprm.cnt_params;
+ struct dpa_stats_compat_cls_cnt_params *uprm_cls = &uprm.cnt_params;
+ long ret = 0;
+ uint32_t i = 0;
+
+ if (copy_from_user(&uprm, args, sizeof(uprm))) {
+ log_err("Cannot copy from user the class counter parameters\n");
+ return -EINVAL;
+ }
+
+ memset(&kprm, 0, sizeof(struct ioc_dpa_stats_cls_cnt_params));
+ kprm.stats_id = uprm.stats_id;
+ kprm_cls->type = uprm_cls->type;
+ kprm_cls->class_members = uprm_cls->class_members;
+
+ switch (kprm.cnt_params.type) {
+ case DPA_STATS_CNT_ETH:
+ ret = dpa_stats_eth_cls_compatcpy(&kprm_cls->eth_params,
+ &uprm_cls->eth_params, kprm_cls->class_members);
+ if (ret < 0)
+ return ret;
+ break;
+ case DPA_STATS_CNT_REASS:
+ ret = dpa_stats_reass_cls_compatcpy(&kprm_cls->reass_params,
+ &uprm_cls->reass_params, kprm_cls->class_members);
+ if (ret < 0)
+ return ret;
+ break;
+ case DPA_STATS_CNT_FRAG:
+ ret = dpa_stats_frag_cls_compatcpy(&kprm_cls->frag_params,
+ &uprm_cls->frag_params, kprm_cls->class_members);
+ if (ret < 0)
+ return ret;
+ break;
+ case DPA_STATS_CNT_POLICER:
+ ret = dpa_stats_plcr_cls_compatcpy(&kprm_cls->plcr_params,
+ &uprm_cls->plcr_params, kprm_cls->class_members);
+ if (ret < 0)
+ return ret;
+ break;
+ case DPA_STATS_CNT_CLASSIF_TBL:
+ ret = dpa_stats_tbl_cls_compatcpy(&kprm_cls->classif_tbl_params,
+ &uprm_cls->classif_tbl_params, kprm_cls->class_members);
+ if (!ret)
+ break;
+ goto compat_create_cls_counter_cleanup;
+ case DPA_STATS_CNT_CLASSIF_NODE:
+ ret = dpa_stats_ccnode_cls_compatcpy(
+ &kprm_cls->classif_node_params,
+ &uprm_cls->ccnode_params, kprm_cls->class_members);
+ if (!ret)
+ break;
+ goto compat_create_cls_counter_cleanup;
+ case DPA_STATS_CNT_IPSEC:
+ ret = dpa_stats_ipsec_cls_compatcpy(&kprm_cls->ipsec_params,
+ &uprm_cls->ipsec_params, kprm_cls->class_members);
+ if (ret < 0)
+ return ret;
+ break;
+ case DPA_STATS_CNT_TRAFFIC_MNG:
+ kprm_cls->traffic_mng_params.cnt_sel =
+ uprm_cls->traffic_mng_params.cnt_sel;
+ kprm_cls->traffic_mng_params.src =
+ uprm_cls->traffic_mng_params.src;
+ break;
+ default:
+ break;
+ }
+
+ ret = dpa_stats_create_class_counter(kprm.stats_id,
+ kprm_cls, &kprm.cnt_id);
+compat_create_cls_counter_cleanup:
+ switch (uprm.cnt_params.type) {
+ case DPA_STATS_CNT_ETH:
+ kfree(kprm_cls->eth_params.src);
+ break;
+ case DPA_STATS_CNT_REASS:
+ kfree(kprm_cls->reass_params.reass);
+ break;
+ case DPA_STATS_CNT_FRAG:
+ kfree(kprm_cls->frag_params.frag);
+ break;
+ case DPA_STATS_CNT_POLICER:
+ kfree(kprm_cls->plcr_params.plcr);
+ break;
+ case DPA_STATS_CNT_CLASSIF_TBL:
+ {
+ struct dpa_stats_cls_cnt_classif_tbl *tbl =
+ &kprm_cls->classif_tbl_params;
+
+ if (tbl->key_type == DPA_STATS_CLASSIF_SINGLE_KEY) {
+ if (!tbl->keys)
+ break;
+ for (i = 0; i < kprm_cls->class_members; i++) {
+ if (!tbl->keys[i])
+ continue;
+ kfree(tbl->keys[i]->byte);
+ kfree(tbl->keys[i]->mask);
+ kfree(tbl->keys[i]);
+ }
+ kfree(tbl->keys);
+
+ } else if (tbl->key_type == DPA_STATS_CLASSIF_PAIR_KEY) {
+ if (!tbl->pairs)
+ break;
+ for (i = 0; i < kprm_cls->class_members; i++) {
+ if (!tbl->pairs[i])
+ continue;
+ if (tbl->pairs[i]->first_key) {
+ kfree(tbl->pairs[i]->first_key->byte);
+ kfree(tbl->pairs[i]->first_key->mask);
+ kfree(tbl->pairs[i]->first_key);
+ }
+ if (tbl->pairs[i]->second_key) {
+ kfree(tbl->pairs[i]->second_key->byte);
+ kfree(tbl->pairs[i]->second_key->mask);
+ kfree(tbl->pairs[i]->second_key);
+ }
+ kfree(tbl->pairs[i]);
+ }
+ kfree(tbl->pairs);
+ }
+ break;
+ }
+ case DPA_STATS_CNT_CLASSIF_NODE:
+ if (!kprm_cls->classif_node_params.keys)
+ break;
+ for (i = 0; i < kprm_cls->class_members; i++) {
+ if (!kprm_cls->classif_node_params.keys[i])
+ continue;
+ kfree(kprm_cls->classif_node_params.keys[i]->byte);
+ kfree(kprm_cls->classif_node_params.keys[i]->mask);
+ kfree(kprm_cls->classif_node_params.keys[i]);
+ }
+ kfree(kprm_cls->classif_node_params.keys);
+ break;
+
+ case DPA_STATS_CNT_IPSEC:
+ kfree(kprm_cls->ipsec_params.sa_id);
+ break;
+
+ default:
+ break;
+ }
+
+ uprm.cnt_id = kprm.cnt_id;
+
+ if (copy_to_user(args, &uprm, sizeof(uprm))) {
+ log_err("Cannot copy to user the counter id\n");
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+#endif
+
+static int do_ioctl_stats_modify_class_counter(void *args)
+{
+ struct ioc_dpa_stats_cls_member_params prm;
+ struct dpa_offload_lookup_key *us_key = NULL;
+ struct dpa_offload_lookup_key_pair *us_pair = NULL;
+ int ret = 0;
+
+ if (copy_from_user(&prm, args, sizeof(prm))) {
+ log_err("Cannot copy from user the class counter parameters\n");
+ return -EINVAL;
+ }
+
+ switch (prm.params.type) {
+ case DPA_STATS_CLS_MEMBER_SINGLE_KEY:
+ if (!prm.params.key)
+ break;
+
+ /* Save user-space provided key */
+ us_key = prm.params.key;
+
+ /* Override user-space pointers with kernel memory */
+ ret = copy_key_descriptor(us_key, &prm.params.key);
+ if (ret != 0) {
+ log_err("Could not copy the key descriptor\n");
+ return ret;
+ }
+ break;
+ case DPA_STATS_CLS_MEMBER_PAIR_KEY:
+ if (!prm.params.pair)
+ break;
+
+ /* Save array of user-space provided pairs pointers */
+ us_pair = prm.params.pair;
+
+ /* Override user-space pointers with kernel memory */
+ ret = copy_pair_descriptor(us_pair, &prm.params.pair);
+ if (ret != 0) {
+ log_err("Could not copy the pair key descriptor\n");
+ return ret;
+ }
+ break;
+ case DPA_STATS_CLS_MEMBER_SA_ID:
+ break;
+ default:
+ break;
+ }
+
+ ret = dpa_stats_modify_class_counter(prm.cnt_id,
+ &prm.params, prm.member_index);
+
+ switch (prm.params.type) {
+ case DPA_STATS_CLS_MEMBER_SINGLE_KEY:
+ if (prm.params.key) {
+ /* Release kernel-allocated memory */
+ kfree(prm.params.key->byte);
+ kfree(prm.params.key->mask);
+ kfree(prm.params.key);
+ /* Restore user-provided key */
+ prm.params.key = us_key;
+ }
+ break;
+ case DPA_STATS_CLS_MEMBER_PAIR_KEY:
+ if (prm.params.pair) {
+ if (prm.params.pair->first_key) {
+ /* Release kernel-allocated memory */
+ kfree(prm.params.pair->first_key->byte);
+ kfree(prm.params.pair->first_key->mask);
+ kfree(prm.params.pair->first_key);
+ }
+ if (prm.params.pair->second_key) {
+ /* Release kernel-allocated memory */
+ kfree(prm.params.pair->second_key->byte);
+ kfree(prm.params.pair->second_key->mask);
+ kfree(prm.params.pair->second_key);
+ }
+ kfree(prm.params.pair);
+ /* Restore user-provided key */
+ prm.params.pair->first_key = us_pair->first_key;
+ prm.params.pair->second_key = us_pair->second_key;
+ prm.params.pair = us_pair;
+ }
+ break;
+ case DPA_STATS_CLS_MEMBER_SA_ID:
+ break;
+ default:
+ log_err("Invalid class member type\n");
+ break;
+ }
+
+ if (copy_to_user(args, &prm, sizeof(prm))) {
+ log_err("Could not write dpa_stats_modify_class_counter result\n");
+ ret = -EBUSY;
+ }
+
+ return ret;
+}
+
+#ifdef CONFIG_COMPAT
+static int do_ioctl_stats_compat_modify_class_counter(void *args)
+{
+ struct ioc_dpa_stats_cls_member_params kprm;
+ struct compat_ioc_dpa_stats_cls_member_params uprm;
+ struct compat_ioc_dpa_offld_lookup_key_pair pair;
+ int ret;
+
+ if (copy_from_user(&uprm, args, sizeof(uprm))) {
+ log_err("Cannot copy from user the modify counter parameters\n");
+ return -EINVAL;
+ }
+
+ memset(&kprm, 0, sizeof(struct ioc_dpa_stats_cls_member_params));
+ kprm.cnt_id = uprm.cnt_id;
+ kprm.member_index = uprm.member_index;
+ kprm.params.type = uprm.params.type;
+
+ switch (kprm.params.type) {
+ case DPA_STATS_CLS_MEMBER_SINGLE_KEY:
+ if (!compat_ptr(uprm.params.key))
+ break;
+ /* Copy user-provided key descriptor */
+ ret = copy_key_descriptor_compatcpy(&kprm.params.key,
+ uprm.params.key);
+ if (ret < 0) {
+ log_err("Cannot copy the key descriptor\n");
+ return ret;
+ }
+ break;
+ case DPA_STATS_CLS_MEMBER_PAIR_KEY:
+ if (!compat_ptr(uprm.params.pair))
+ break;
+
+ if (copy_from_user(&pair, compat_ptr(uprm.params.pair),
+ (sizeof(pair)))) {
+ log_err("Cannot copy from user array of lookup pairs\n");
+ return -EBUSY;
+ }
+
+ /* Copy user-provided lookup pair descriptor */
+ ret = copy_pair_descriptor_compatcpy(&kprm.params.pair, pair);
+ if (ret < 0) {
+ log_err("Cannot copy the pair key descriptor\n");
+ return ret;
+ }
+ break;
+ case DPA_STATS_CLS_MEMBER_SA_ID:
+ kprm.params.sa_id = uprm.params.sa_id;
+ break;
+ default:
+ break;
+ }
+
+ ret = dpa_stats_modify_class_counter(kprm.cnt_id,
+ &kprm.params, kprm.member_index);
+
+ switch (kprm.params.type) {
+ case DPA_STATS_CLS_MEMBER_SINGLE_KEY:
+ if (!kprm.params.key)
+ break;
+ kfree(kprm.params.key->byte);
+ kfree(kprm.params.key->mask);
+ kfree(kprm.params.key);
+ break;
+ case DPA_STATS_CLS_MEMBER_PAIR_KEY:
+ if (!kprm.params.pair)
+ break;
+ if (kprm.params.pair->first_key) {
+ kfree(kprm.params.pair->first_key->byte);
+ kfree(kprm.params.pair->first_key->mask);
+ kfree(kprm.params.pair->first_key);
+ }
+ if (kprm.params.pair->second_key) {
+ kfree(kprm.params.pair->second_key->byte);
+ kfree(kprm.params.pair->second_key->mask);
+ kfree(kprm.params.pair->second_key);
+ }
+ break;
+ case DPA_STATS_CLS_MEMBER_SA_ID:
+ break;
+ default:
+ break;
+ }
+ uprm.cnt_id = kprm.cnt_id;
+
+ if (copy_to_user(args, &uprm, sizeof(uprm))) {
+ log_err("Cannot copy to user class counter result\n");
+ ret = -EBUSY;
+ }
+
+ return ret;
+}
+#endif
+
+static int do_ioctl_stats_get_counters(void *args)
+{
+ struct ioc_dpa_stats_cnt_request_params prm;
+ int *cnts_ids;
+ long ret = 0;
+
+ if (copy_from_user(&prm, args, sizeof(prm))) {
+ log_err("Cannot copy from user request parameters\n");
+ return -EINVAL;
+ }
+
+ /* Allocate kernel-space memory area to copy the counters ids */
+ cnts_ids = kzalloc(prm.req_params.cnts_ids_len *
+ sizeof(int), GFP_KERNEL);
+ if (!cnts_ids) {
+ log_err("Cannot allocate memory for requested counter ids array\n");
+ return -ENOMEM;
+ }
+
+ /* Copy the user provided counter ids */
+ if (copy_from_user(cnts_ids,
+ prm.req_params.cnts_ids,
+ (prm.req_params.cnts_ids_len * sizeof(int)))) {
+ log_err("Cannot copy from user array of requested counter ids\n");
+ kfree(prm.req_params.cnts_ids);
+ return -EINVAL;
+ }
+
+ prm.req_params.cnts_ids = cnts_ids;
+
+ /* If counters request is asynchronous */
+ if (prm.request_done) {
+ ret = store_get_cnts_async_params(&prm, NULL);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = dpa_stats_get_counters(prm.req_params,
+ &prm.cnts_len, prm.request_done);
+ if (ret < 0) {
+ kfree(prm.req_params.cnts_ids);
+ return ret;
+ }
+
+ /* If request is synchronous copy counters length to user space */
+ if (!prm.request_done) {
+ if (wrp_dpa_stats.k_mem)
+ if (copy_to_user((wrp_dpa_stats.us_mem +
+ prm.req_params.storage_area_offset),
+ (wrp_dpa_stats.k_mem +
+ prm.req_params.storage_area_offset),
+ prm.cnts_len)) {
+ log_err("Cannot copy counter values to storage area\n");
+ return -EINVAL;
+ }
+
+ if (copy_to_user(args, &prm, sizeof(prm))) {
+ log_err("Cannot copy to user the counter parameters\n");
+ ret = -EINVAL;
+ }
+
+ /* Request was sent, release the array of counter ids */
+ kfree(prm.req_params.cnts_ids);
+ }
+
+ return ret;
+}
+
+#ifdef CONFIG_COMPAT
+static int do_ioctl_stats_compat_get_counters(void *args)
+{
+ struct ioc_dpa_stats_cnt_request_params kprm;
+ struct compat_ioc_dpa_stats_cnt_request_params uprm;
+ long ret = 0;
+
+ if (copy_from_user(&uprm, args, sizeof(uprm))) {
+ log_err("Cannot copy from user request parameters\n");
+ return -EINVAL;
+ }
+
+ memset(&kprm, 0, sizeof(struct ioc_dpa_stats_cnt_request_params));
+ kprm.cnts_len = uprm.cnts_len;
+ kprm.request_done = (dpa_stats_request_cb)
+ ((compat_ptr)(uprm.request_done));
+ kprm.req_params.cnts_ids_len = uprm.req_params.cnts_ids_len;
+ kprm.req_params.reset_cnts = uprm.req_params.reset_cnts;
+ kprm.req_params.storage_area_offset =
+ uprm.req_params.storage_area_offset;
+
+ /* Allocate kernel-space memory area to copy the counters ids */
+ kprm.req_params.cnts_ids = kzalloc(kprm.req_params.cnts_ids_len *
+ sizeof(int), GFP_KERNEL);
+ if (!kprm.req_params.cnts_ids) {
+ log_err("Cannot allocate memory for requested counter ids array\n");
+ return -ENOMEM;
+ }
+
+ /* Copy the user provided counter ids */
+ if (copy_from_user(kprm.req_params.cnts_ids,
+ (compat_ptr)(uprm.req_params.cnts_ids),
+ (kprm.req_params.cnts_ids_len * sizeof(int)))) {
+ log_err("Cannot copy from user the array of requested counter ids\n");
+ kfree(kprm.req_params.cnts_ids);
+ return -EINVAL;
+ }
+
+ /* If counters request is asynchronous */
+ if (kprm.request_done) {
+ struct dpa_stats_async_req_ev *async_request_ev = NULL;
+
+ ret = store_get_cnts_async_params(&kprm, &async_request_ev);
+ if (ret < 0)
+ return ret;
+ /* Store user-space pointer to array of ids */
+ async_request_ev->us_cnt_ids = uprm.req_params.cnts_ids;
+ async_request_ev->cnt_ids_len = uprm.req_params.cnts_ids_len;
+ }
+
+ ret = dpa_stats_get_counters(kprm.req_params,
+ &kprm.cnts_len, kprm.request_done);
+ if (ret < 0) {
+ kfree(kprm.req_params.cnts_ids);
+ return ret;
+ }
+
+ /* If request is synchronous copy counters length to user space */
+ if (!kprm.request_done) {
+ if (wrp_dpa_stats.k_mem)
+ if (copy_to_user((wrp_dpa_stats.us_mem +
+ kprm.req_params.storage_area_offset),
+ (wrp_dpa_stats.k_mem +
+ kprm.req_params.storage_area_offset),
+ kprm.cnts_len)) {
+ log_err("Cannot copy counter values to storage area\n");
+ kfree(kprm.req_params.cnts_ids);
+ return -EINVAL;
+ }
+
+ uprm.cnts_len = kprm.cnts_len;
+
+ if (copy_to_user((compat_ptr)(uprm.req_params.cnts_ids),
+ kprm.req_params.cnts_ids,
+ (kprm.req_params.cnts_ids_len * sizeof(int)))) {
+ log_err("Cannot copy to user the array of requested counter ids\n");
+ kfree(kprm.req_params.cnts_ids);
+ return -EINVAL;
+ }
+
+ if (copy_to_user(args, &uprm, sizeof(uprm))) {
+ log_err("Cannot copy to user the counter parameters\n");
+ ret = -EINVAL;
+ }
+
+ /* Request was sent, release the array of counter ids */
+ kfree(kprm.req_params.cnts_ids);
+ }
+
+ return ret;
+}
+#endif
+
+static int do_ioctl_stats_reset_counters(void *args)
+{
+ struct ioc_dpa_stats_cnts_reset_params prm;
+ int *cnt_ids;
+ long ret = 0;
+
+ if (copy_from_user(&prm, args, sizeof(prm))) {
+ log_err("Cannot copy from user reset counter parameters\n");
+ return -EINVAL;
+ }
+
+ /* Allocate kernel-space memory area to copy the counters ids */
+ cnt_ids = kcalloc(prm.cnts_ids_len, sizeof(int), GFP_KERNEL);
+ if (!cnt_ids) {
+ log_err("Cannot allocate memory for counter ids array\n");
+ return -ENOMEM;
+ }
+
+ /* Copy the user provided counter ids */
+ if (copy_from_user(cnt_ids,
+ prm.cnts_ids,
+ (prm.cnts_ids_len * sizeof(int)))) {
+ log_err("Cannot copy from user array of requested counter ids\n");
+ kfree(cnt_ids);
+ return -EINVAL;
+ }
+ prm.cnts_ids = cnt_ids;
+
+ ret = dpa_stats_reset_counters(prm.cnts_ids, prm.cnts_ids_len);
+ if (ret < 0) {
+ kfree(prm.cnts_ids);
+ return ret;
+ }
+
+ kfree(cnt_ids);
+
+ if (copy_to_user(args, &prm, sizeof(prm))) {
+ log_err("Cannot copy to user the counter parameters\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_COMPAT
+static int do_ioctl_stats_compat_reset_counters(void *args)
+{
+ struct ioc_dpa_stats_cnts_reset_params kprm;
+ struct compat_ioc_dpa_stats_cnts_reset_params uprm;
+ long ret = 0;
+
+ if (copy_from_user(&uprm, args, sizeof(uprm))) {
+ log_err("Cannot copy from user counter reset parameters\n");
+ return -EINVAL;
+ }
+
+ memset(&kprm, 0, sizeof(struct ioc_dpa_stats_cnts_reset_params));
+ kprm.cnts_ids_len = uprm.cnts_ids_len;
+
+ /* Allocate kernel-space memory area to copy the counters ids */
+ kprm.cnts_ids = kcalloc(kprm.cnts_ids_len, sizeof(int), GFP_KERNEL);
+ if (!kprm.cnts_ids) {
+ log_err("Cannot allocate memory for counter ids array\n");
+ return -ENOMEM;
+ }
+
+ /* Copy the user provided counter ids */
+ if (copy_from_user(kprm.cnts_ids,
+ (compat_ptr)(uprm.cnts_ids),
+ (kprm.cnts_ids_len * sizeof(int)))) {
+ log_err("Cannot copy from user array of counter ids\n");
+ kfree(kprm.cnts_ids);
+ return -EINVAL;
+ }
+
+ ret = dpa_stats_reset_counters(kprm.cnts_ids, kprm.cnts_ids_len);
+ if (ret < 0) {
+ kfree(kprm.cnts_ids);
+ return ret;
+ }
+
+ kfree(kprm.cnts_ids);
+
+ if (copy_to_user(args, &uprm, sizeof(uprm))) {
+ log_err("Cannot copy to user the counter parameters\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+#endif
+
+static long wrp_dpa_stats_do_ioctl(struct file *filp,
+ unsigned int cmd, unsigned long args)
+{
+ long ret = 0;
+
+ switch (cmd) {
+ case DPA_STATS_IOC_INIT:
+ {
+ struct ioc_dpa_stats_params kparam;
+
+ /* Copy parameters from user-space */
+ if (copy_from_user(&kparam, (void *)args, sizeof(kparam))) {
+ log_err("Cannot copy from user dpa_stats_init arguments\n");
+ return -EBUSY;
+ }
+
+ ret = do_ioctl_stats_init(&kparam);
+ if (ret < 0)
+ return ret;
+
+ /* Copy paramters to user-space */
+ if (copy_to_user((void *)args, &kparam, sizeof(kparam))) {
+ log_err("Cannot copy to user dpa_stats_init result\n");
+ return -EBUSY;
+ }
+ break;
+ }
+ case DPA_STATS_IOC_FREE:
+ ret = do_ioctl_stats_free((void *)args);
+ if (ret < 0)
+ return ret;
+ break;
+ case DPA_STATS_IOC_CREATE_COUNTER:
+ ret = do_ioctl_stats_create_counter((void *)args);
+ if (ret < 0)
+ return ret;
+ break;
+ case DPA_STATS_IOC_CREATE_CLASS_COUNTER:
+ ret = do_ioctl_stats_create_class_counter((void *)args);
+ if (ret < 0)
+ return ret;
+ break;
+ case DPA_STATS_IOC_MODIFY_CLASS_COUNTER:
+ ret = do_ioctl_stats_modify_class_counter((void *)args);
+ if (ret < 0)
+ return ret;
+ break;
+ case DPA_STATS_IOC_REMOVE_COUNTER:{
+ int dpa_stats_cnt_id;
+ if (copy_from_user(&dpa_stats_cnt_id, (int *)args,
+ sizeof(int))) {
+ log_err("Cannot copy from user the parameters\n");
+ return -EINVAL;
+ }
+
+ ret = dpa_stats_remove_counter(dpa_stats_cnt_id);
+ if (ret < 0)
+ return ret;
+
+ break;
+ }
+ case DPA_STATS_IOC_GET_COUNTERS:
+ ret = do_ioctl_stats_get_counters((void *)args);
+ if (ret < 0)
+ return ret;
+ break;
+ case DPA_STATS_IOC_RESET_COUNTERS:
+ ret = do_ioctl_stats_reset_counters((void *)args);
+ if (ret < 0)
+ return ret;
+ break;
+ default:
+ log_err("Unsupported ioctl 0x%08x, type 0x%02x, nr 0x%02x\n",
+ cmd, _IOC_TYPE(cmd), _IOC_NR(cmd));
+ break;
+ }
+ return ret;
+}
+
+#ifdef CONFIG_COMPAT
+static long wrp_dpa_stats_do_compat_ioctl(struct file *filp,
+ unsigned int cmd,
+ unsigned long args)
+{
+ long ret = 0;
+
+ switch (cmd) {
+ case DPA_STATS_IOC_COMPAT_INIT:
+ {
+ struct ioc_dpa_stats_params kparam;
+ struct compat_ioc_dpa_stats_params uparam;
+
+ /* Copy parameters from user space */
+ if (copy_from_user(&uparam, (void *)args, sizeof(uparam))) {
+ log_err("Cannot copy from user dpa_stats_init arguments\n");
+ return -EBUSY;
+ }
+ dpa_stats_init_compatcpy(&kparam, &uparam);
+
+ ret = do_ioctl_stats_init(&kparam);
+ if (ret < 0)
+ return ret;
+
+ /* Copy result to user-space */
+ uparam.dpa_stats_id = kparam.dpa_stats_id;
+ if (copy_to_user((void *)args, &uparam, sizeof(uparam))) {
+ log_err("Cannot copy to user dpa_stats_init result\n");
+ return -EBUSY;
+ }
+ break;
+ }
+ case DPA_STATS_IOC_FREE:
+ ret = do_ioctl_stats_free((void *)args);
+ if (ret < 0)
+ return ret;
+ break;
+ case DPA_STATS_IOC_COMPAT_CREATE_COUNTER:
+ ret = do_ioctl_stats_compat_create_counter((void *)args);
+ if (ret < 0)
+ return ret;
+ break;
+ case DPA_STATS_IOC_COMPAT_CREATE_CLASS_COUNTER:
+ ret = do_ioctl_stats_compat_create_class_counter((void *)args);
+ if (ret < 0)
+ return ret;
+ break;
+ case DPA_STATS_IOC_COMPAT_MODIFY_CLASS_COUNTER:
+ ret = do_ioctl_stats_compat_modify_class_counter((void *)args);
+ if (ret < 0)
+ return ret;
+ break;
+ case DPA_STATS_IOC_REMOVE_COUNTER:{
+ int dpa_stats_cnt_id;
+
+ if (copy_from_user(&dpa_stats_cnt_id, (int *)args,
+ sizeof(int))) {
+ log_err("Cannot copy from user counter parameters\n");
+ return -EINVAL;
+ }
+
+ ret = dpa_stats_remove_counter(dpa_stats_cnt_id);
+ if (ret < 0)
+ return ret;
+ break;
+ }
+ case DPA_STATS_IOC_COMPAT_GET_COUNTERS:
+ ret = do_ioctl_stats_compat_get_counters((void *)args);
+ if (ret < 0)
+ return ret;
+ break;
+ case DPA_STATS_IOC_COMPAT_RESET_COUNTERS:
+ ret = do_ioctl_stats_compat_reset_counters((void *)args);
+ if (ret < 0)
+ return ret;
+ break;
+ default:
+ log_err("Unsupported ioctl 0x%08x, type 0x%02x, nr 0x%02x\n",
+ cmd, _IOC_TYPE(cmd), _IOC_NR(cmd));
+ break;
+ }
+ return ret;
+}
+#endif
+
+static long store_get_cnts_async_params(
+ struct ioc_dpa_stats_cnt_request_params *kprm,
+ struct dpa_stats_async_req_ev **async_request_event)
+{
+ struct dpa_stats_async_req_ev *async_req_ev;
+ struct list_head *async_req_grp;
+ uint8_t grp_idx = 0;
+
+ mutex_lock(&wrp_dpa_stats.async_req_lock);
+ if (list_empty(&wrp_dpa_stats.async_req_pool)) {
+ log_err("Reached maximum supported number of simultaneous asynchronous requests\n");
+ kfree(kprm->req_params.cnts_ids);
+ mutex_unlock(&wrp_dpa_stats.async_req_lock);
+ return -EDOM;
+ }
+ /* Add in the associated group the request event */
+ grp_idx = crc8(crc8_table,
+ (uint8_t *)&kprm->req_params.storage_area_offset,
+ sizeof(unsigned int),
+ 0);
+ async_req_grp = &wrp_dpa_stats.async_req_group[grp_idx];
+
+ /* Obtain a free request event and add in the group list */
+ async_req_ev = list_entry(wrp_dpa_stats.async_req_pool.next,
+ struct dpa_stats_async_req_ev, node);
+ list_del(&async_req_ev->node);
+ async_req_ev->request_done = kprm->request_done;
+ async_req_ev->storage_area_offset =
+ kprm->req_params.storage_area_offset;
+
+ async_req_ev->ks_cnt_ids = kprm->req_params.cnts_ids;
+ list_add_tail(&async_req_ev->node, async_req_grp);
+ mutex_unlock(&wrp_dpa_stats.async_req_lock);
+
+ /* Replace the application callback with wrapper function */
+ kprm->request_done = do_ioctl_req_done_cb;
+
+ /* If calling function requested, return the pointer to async_req_ev */
+ if (async_request_event)
+ *async_request_event = async_req_ev;
+ return 0;
+}
+
+static int copy_key_descriptor(struct dpa_offload_lookup_key *src,
+ struct dpa_offload_lookup_key **ks_key)
+{
+ struct dpa_offload_lookup_key *tmp = NULL;
+
+ /* Allocate kernel memory for key descriptor */
+ tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
+ if (!tmp) {
+ log_err("Cannot allocate kernel memory for key descriptor\n");
+ return -ENOMEM;
+ }
+
+ if (src->byte) {
+ /* Allocate memory to store the key byte array */
+ tmp->byte = kmalloc(src->size, GFP_KERNEL);
+ if (!tmp->byte) {
+ log_err("Cannot allocate memory for key descriptor byte\n");
+ kfree(tmp);
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(tmp->byte, src->byte, src->size)) {
+ log_err("Cannot copy from user the key descriptor byte\n");
+ kfree(tmp->byte);
+ kfree(tmp);
+ return -EBUSY;
+ }
+ }
+
+ if (src->mask) {
+ /* Allocate memory to store the key mask array */
+ tmp->mask = kmalloc(src->size, GFP_KERNEL);
+ if (!tmp->mask) {
+ log_err("Cannot allocate memory for key descriptor mask\n");
+ kfree(tmp->byte);
+ kfree(tmp);
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(tmp->mask, src->mask, src->size)) {
+ log_err("Cannot copy from user the key descriptor mask\n");
+ kfree(tmp->byte);
+ kfree(tmp->mask);
+ kfree(tmp);
+ return -EBUSY;
+ }
+ }
+
+ tmp->size = src->size;
+ *ks_key = tmp;
+ return 0;
+}
+
+static int copy_pair_descriptor(struct dpa_offload_lookup_key_pair *src,
+ struct dpa_offload_lookup_key_pair **ks_pair)
+{
+ struct dpa_offload_lookup_key_pair *tmp;
+ int ret = 0;
+
+ /* Allocate kernel memory for pair descriptor*/
+ tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
+ if (!tmp) {
+ log_err("Cannot allocate kernel memory for pair descriptor\n");
+ return -ENOMEM;
+ }
+
+ if (src->first_key) {
+ ret = copy_key_descriptor(src->first_key, &tmp->first_key);
+ if (ret != 0) {
+ log_err("Cannot copy the first key descriptor\n");
+ kfree(tmp);
+ return ret;
+ }
+ }
+
+ if (src->second_key) {
+ ret = copy_key_descriptor(src->second_key, &tmp->second_key);
+ if (ret != 0) {
+ log_err("Cannot copy the second key descriptor\n");
+ if (tmp->first_key) {
+ kfree(tmp->first_key->byte);
+ kfree(tmp->first_key->mask);
+ }
+ kfree(tmp);
+ return ret;
+ }
+ }
+ *ks_pair = tmp;
+ return 0;
+}
+
+#ifdef CONFIG_COMPAT
+static int copy_key_descriptor_compatcpy(
+ struct dpa_offload_lookup_key **ks_key, compat_uptr_t uparam)
+{
+ struct compat_ioc_dpa_offld_lookup_key key;
+ struct dpa_offload_lookup_key *kparam;
+
+ if (copy_from_user(&key, (compat_ptr)(uparam),
+ sizeof(struct compat_ioc_dpa_offld_lookup_key))) {
+ log_err("Cannot copy from user key descriptor\n");
+ return -EBUSY;
+ }
+
+ /* Allocate kernel memory for key descriptor */
+ kparam = kzalloc(sizeof(*kparam), GFP_KERNEL);
+ if (!kparam) {
+ log_err("Cannot allocate kernel memory for key descriptor\n");
+ return -ENOMEM;
+ }
+
+ if (compat_ptr(key.byte)) {
+ /* Allocate memory to store the key byte array */
+ kparam->byte = kmalloc(key.size, GFP_KERNEL);
+ if (!kparam->byte) {
+ log_err("Cannot allocate memory for key descriptor byte\n");
+ kfree(kparam);
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(kparam->byte,
+ compat_ptr(key.byte), key.size)) {
+ log_err("Cannot copy from user the key descriptor byte\n");
+ kfree(kparam->byte);
+ kfree(kparam);
+ return -EBUSY;
+ }
+ }
+
+ if (compat_ptr(key.mask)) {
+ /* Allocate memory to store the key mask array */
+ kparam->mask = kmalloc(key.size, GFP_KERNEL);
+ if (!kparam->mask) {
+ log_err("Cannot allocate memory for key descriptor mask\n");
+ kfree(kparam->byte);
+ kfree(kparam);
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(kparam->mask,
+ compat_ptr(key.mask), key.size)) {
+ log_err("Cannot copy from user the key descriptor mask\n");
+ kfree(kparam->byte);
+ kfree(kparam->mask);
+ kfree(kparam);
+ return -EBUSY;
+ }
+ }
+ kparam->size = key.size;
+ *ks_key = kparam;
+ return 0;
+}
+
+static int copy_pair_descriptor_compatcpy(
+ struct dpa_offload_lookup_key_pair **ks_pair,
+ struct compat_ioc_dpa_offld_lookup_key_pair pair)
+{
+ struct dpa_offload_lookup_key_pair *kpair;
+ int ret = 0;
+
+ /* Allocate kernel memory for lookup pair descriptor */
+ kpair = kzalloc(sizeof(*kpair), GFP_KERNEL);
+ if (!kpair) {
+ log_err("Cannot allocate kernel memory for pair descriptor\n");
+ return -ENOMEM;
+ }
+
+ if (compat_ptr(pair.first_key)) {
+ /* Copy user-provided key descriptor */
+ ret = copy_key_descriptor_compatcpy(
+ &kpair->first_key, pair.first_key);
+ if (ret != 0) {
+ log_err("Cannot copy first key of the pair\n");
+ kfree(kpair);
+ return ret;
+ }
+ }
+
+ if (compat_ptr(pair.second_key)) {
+ ret = copy_key_descriptor_compatcpy(
+ &kpair->second_key, pair.second_key);
+ if (ret != 0) {
+ log_err("Cannot copy second key of the pair\n");
+ if (kpair->first_key) {
+ kfree(kpair->first_key->byte);
+ kfree(kpair->first_key->mask);
+ }
+ kfree(kpair);
+ return ret;
+ }
+ }
+ *ks_pair = kpair;
+ return 0;
+}
+#endif
+
+static void **copy_class_members(unsigned int size, void **src)
+{
+ void **objs;
+
+ /* Allocate memory to store the array of objects */
+ objs = kcalloc(size, sizeof(void *), GFP_KERNEL);
+ if (!objs) {
+ log_err("Cannot allocate memory for objects array\n");
+ return NULL;
+ }
+
+ if (copy_from_user(objs, src, (size * sizeof(void *)))) {
+ log_err("Cannot copy from user array of objects\n");
+ kfree(objs);
+ return NULL;
+ }
+ return objs;
+}
+
+#ifdef CONFIG_COMPAT
+static void dpa_stats_init_compatcpy(struct ioc_dpa_stats_params *kparam,
+ struct compat_ioc_dpa_stats_params *uparam)
+{
+ kparam->dpa_stats_id = uparam->dpa_stats_id;
+ kparam->max_counters = uparam->stats_params.max_counters;
+ kparam->storage_area_len = uparam->stats_params.storage_area_len;
+ kparam->virt_stg_area = compat_ptr(uparam->stats_params.virt_stg_area);
+ kparam->phys_stg_area = uparam->stats_params.phys_stg_area;
+ kparam->stg_area_mapped = uparam->stats_params.stg_area_mapped;
+}
+
+static void dpa_stats_reass_cnt_compatcpy(struct dpa_stats_cnt_reass *kprm,
+ struct dpa_stats_compat_cnt_reass *uprm)
+{
+ kprm->reass = compat_get_id2ptr(uprm->reass, FM_MAP_TYPE_PCD_NODE);
+ kprm->cnt_sel = uprm->cnt_sel;
+}
+
+static void dpa_stats_frag_cnt_compatcpy(struct dpa_stats_cnt_frag *kprm,
+ struct dpa_stats_compat_cnt_frag *uprm)
+{
+ kprm->frag = compat_get_id2ptr(uprm->frag, FM_MAP_TYPE_PCD_NODE);
+ kprm->cnt_sel = uprm->cnt_sel;
+}
+
+static void dpa_stats_plcr_cnt_compatcpy(struct dpa_stats_cnt_plcr *kprm,
+ struct dpa_stats_compat_cnt_plcr *uprm)
+{
+ kprm->plcr = compat_get_id2ptr(uprm->plcr, FM_MAP_TYPE_PCD_NODE);
+ kprm->cnt_sel = uprm->cnt_sel;
+}
+
+
+static long dpa_stats_tbl_cnt_compatcpy(struct dpa_stats_cnt_classif_tbl *kprm,
+ struct dpa_stats_compat_cnt_classif_tbl *uprm)
+{
+ kprm->td = uprm->td;
+ kprm->cnt_sel = uprm->cnt_sel;
+ kprm->key = NULL;
+
+ if (compat_ptr(uprm->key))
+ return copy_key_descriptor_compatcpy(&kprm->key, uprm->key);
+
+ return 0;
+}
+
+static long dpa_stats_ccnode_cnt_compatcpy(
+ struct dpa_stats_cnt_classif_node *kprm,
+ struct dpa_stats_compat_cnt_classif_node *uprm)
+{
+ kprm->cnt_sel = uprm->cnt_sel;
+ kprm->ccnode_type = uprm->ccnode_type;
+ kprm->cc_node = compat_get_id2ptr(uprm->cc_node, FM_MAP_TYPE_PCD_NODE);
+ kprm->key = NULL;
+
+ if (compat_ptr(uprm->key))
+ return copy_key_descriptor_compatcpy(&kprm->key, uprm->key);
+
+ return 0;
+}
+
+static long dpa_stats_eth_cls_compatcpy(struct dpa_stats_cls_cnt_eth *kprm,
+ struct dpa_stats_compat_cls_cnt_eth *uprm, uint32_t cls_members)
+{
+ uint32_t size = 0;
+
+ size = cls_members * sizeof(struct dpa_stats_cnt_eth_src);
+
+ /* Allocate memory to store the sources array */
+ kprm->src = kzalloc(size, GFP_KERNEL);
+ if (!kprm->src) {
+ log_err("Cannot allocate kernel memory for Ethernet sources array\n");
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(kprm->src, compat_ptr(uprm->src), size)) {
+ log_err("Cannot copy from user array of Ethernet sources\n");
+ kfree(kprm->src);
+ return -EBUSY;
+ }
+ kprm->cnt_sel = uprm->cnt_sel;
+ return 0;
+}
+
+static long dpa_stats_reass_cls_compatcpy(struct dpa_stats_cls_cnt_reass *kprm,
+ struct dpa_stats_compat_cnt_reass *uprm, uint32_t cls_members)
+{
+ compat_uptr_t *reass;
+ uint32_t i = 0;
+
+ /* Allocate memory to store the array of user-space reass objects */
+ reass = kzalloc(sizeof(compat_uptr_t) * cls_members, GFP_KERNEL);
+ if (!reass) {
+ log_err("Cannot allocate memory for Reassembly objects array\n");
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(reass, compat_ptr(uprm->reass),
+ (sizeof(compat_uptr_t) * cls_members))) {
+ log_err("Cannot copy from user array of Reassembly objects\n");
+ kfree(reass);
+ return -EBUSY;
+ }
+
+ /* Allocate memory to store the array of kernel space reass objects */
+ kprm->reass = kzalloc((sizeof(void *) * cls_members), GFP_KERNEL);
+ if (!kprm->reass) {
+ log_err("Cannot allocate kernel memory for Reassembly objects array\n");
+ kfree(reass);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < cls_members; i++)
+ kprm->reass[i] = compat_get_id2ptr(
+ reass[i], FM_MAP_TYPE_PCD_NODE);
+
+ kprm->cnt_sel = uprm->cnt_sel;
+ kfree(reass);
+ return 0;
+}
+
+static long dpa_stats_frag_cls_compatcpy(struct dpa_stats_cls_cnt_frag *kprm,
+ struct dpa_stats_compat_cnt_frag *uprm,
+ uint32_t cls_members)
+{
+ compat_uptr_t *ufrag;
+ uint32_t i = 0;
+
+ /* Allocate memory to store the array of user-space frag objects */
+ ufrag = kzalloc(sizeof(compat_uptr_t) * cls_members, GFP_KERNEL);
+ if (!ufrag) {
+ log_err("Cannot allocate memory for Fragmentation objects array\n");
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(ufrag, compat_ptr(uprm->frag),
+ (sizeof(compat_uptr_t) * cls_members))) {
+ log_err("Cannot copy from user array of Fragmentation objects\n");
+ kfree(ufrag);
+ return -EBUSY;
+ }
+
+ /* Allocate memory to store the array of kernel space frag objects */
+ kprm->frag = kzalloc((sizeof(void *) * cls_members), GFP_KERNEL);
+ if (!kprm->frag) {
+ log_err("Cannot allocate kernel memory for Fragmentation objects array\n");
+ kfree(ufrag);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < cls_members; i++)
+ kprm->frag[i] = compat_get_id2ptr(
+ ufrag[i], FM_MAP_TYPE_PCD_NODE);
+
+ kprm->cnt_sel = uprm->cnt_sel;
+ kfree(ufrag);
+ return 0;
+}
+
+static long dpa_stats_plcr_cls_compatcpy(struct dpa_stats_cls_cnt_plcr *kprm,
+ struct dpa_stats_compat_cnt_plcr *uprm,
+ uint32_t cls_members)
+{
+ compat_uptr_t *uplcr;
+ uint32_t i = 0;
+
+ /* Allocate memory to store the array of user-space policer objects */
+ uplcr = kzalloc(sizeof(compat_uptr_t) * cls_members, GFP_KERNEL);
+ if (!uplcr) {
+ log_err("Cannot allocate memory for Policer objects array\n");
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(uplcr, compat_ptr(uprm->plcr),
+ (sizeof(compat_uptr_t) * cls_members))) {
+ log_err("Cannot copy from user array of Policer objects\n");
+ kfree(uplcr);
+ return -EBUSY;
+ }
+
+ /* Allocate memory to store the array of kernel space policer objects */
+ kprm->plcr = kzalloc((sizeof(void *) * cls_members), GFP_KERNEL);
+ if (!kprm->plcr) {
+ log_err("Cannot allocate kernel memory for Policer objects array\n");
+ kfree(uplcr);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < cls_members; i++)
+ kprm->plcr[i] = compat_get_id2ptr(
+ uplcr[i], FM_MAP_TYPE_PCD_NODE);
+
+ kprm->cnt_sel = uprm->cnt_sel;
+ kfree(uplcr);
+ return 0;
+}
+
+static long dpa_stats_tbl_cls_compatcpy(
+ struct dpa_stats_cls_cnt_classif_tbl *kprm,
+ struct dpa_stats_compat_cls_cnt_classif_tbl *uprm,
+ uint32_t cls_members)
+{
+ struct compat_ioc_dpa_offld_lookup_key_pair pair;
+ compat_uptr_t *us_keys;
+ uint32_t i;
+ long ret;
+
+ kprm->cnt_sel = uprm->cnt_sel;
+ kprm->td = uprm->td;
+ kprm->key_type = uprm->key_type;
+
+ /* Allocate memory to store array of user-space keys descriptors */
+ us_keys = kzalloc(sizeof(compat_uptr_t) * cls_members, GFP_KERNEL);
+ if (!us_keys) {
+ log_err("Cannot allocate memory array of lookup keys\n");
+ return -ENOMEM;
+ }
+
+ if (kprm->key_type == DPA_STATS_CLASSIF_SINGLE_KEY) {
+ if (copy_from_user(us_keys, compat_ptr(uprm->keys),
+ (sizeof(compat_uptr_t) * cls_members))) {
+ log_err("Cannot copy from user-space array of keys descriptors\n");
+ kfree(us_keys);
+ return -EBUSY;
+ }
+
+ /* Allocate memory for array of kernel-space keys descriptors */
+ kprm->keys = kzalloc((sizeof(*kprm->keys) * cls_members),
+ GFP_KERNEL);
+ if (!kprm->keys) {
+ log_err("Cannot allocate kernel memory for lookup keys array\n");
+ kfree(us_keys);
+ return -ENOMEM;
+ }
+ for (i = 0; i < cls_members; i++) {
+ if (!compat_ptr(us_keys[i]))
+ continue;
+ /* Copy user-provided key descriptor */
+ ret = copy_key_descriptor_compatcpy(&kprm->keys[i],
+ us_keys[i]);
+ if (ret != 0) {
+ log_err("Cannot copy the key descriptor\n");
+ kfree(us_keys);
+ return ret;
+ }
+ }
+ kfree(us_keys);
+ }
+
+ if (kprm->key_type == DPA_STATS_CLASSIF_PAIR_KEY) {
+ if (copy_from_user(us_keys, compat_ptr(uprm->pairs),
+ (sizeof(compat_uptr_t) * cls_members))) {
+ log_err("Cannot copy from user-space array of pair descriptors\n");
+ kfree(us_keys);
+ return -EBUSY;
+ }
+
+ /* Allocate memory for array of kernel-space pairs descriptors*/
+ kprm->pairs = kzalloc((sizeof(*kprm->pairs) * cls_members),
+ GFP_KERNEL);
+ if (!kprm->pairs) {
+ log_err("Cannot allocate kernel memory for lookup pairs array\n");
+ kfree(us_keys);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < cls_members; i++) {
+ if (!compat_ptr(us_keys[i]))
+ continue;
+
+ /* Allocate memory for kernel pair descriptor */
+ kprm->pairs[i] = kzalloc(sizeof(*kprm->pairs[i]),
+ GFP_KERNEL);
+ if (!kprm->pairs[i]) {
+ log_err("Cannot allocate kernel memory for pair descriptor\n");
+ kfree(us_keys);
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(&pair, compat_ptr(us_keys[i]),
+ (sizeof(pair)))) {
+ log_err("Cannot copy pair descriptor\n");
+ kfree(us_keys);
+ return -EBUSY;
+ }
+
+ if (compat_ptr(pair.first_key)) {
+ /* Copy user-provided first key descriptor */
+ ret = copy_key_descriptor_compatcpy(
+ &kprm->pairs[i]->first_key,
+ pair.first_key);
+ if (ret != 0) {
+ log_err("Cannot copy first key\n");
+ kfree(us_keys);
+ return ret;
+ }
+ }
+
+ if (compat_ptr(pair.second_key)) {
+ /* Copy user-provided second key descriptor */
+ ret = copy_key_descriptor_compatcpy(
+ &kprm->pairs[i]->second_key,
+ pair.second_key);
+ if (ret != 0) {
+ log_err("Cannot copy second key\n");
+ kfree(us_keys);
+ return ret;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static long dpa_stats_ccnode_cls_compatcpy(
+ struct dpa_stats_cls_cnt_classif_node *kprm,
+ struct dpa_stats_compat_cls_cnt_classif_node *uprm,
+ uint32_t cls_members)
+{
+ compat_uptr_t *us_keys;
+ uint32_t i;
+ long ret = 0;
+
+ kprm->cc_node = compat_get_id2ptr(uprm->cc_node, FM_MAP_TYPE_PCD_NODE);
+ kprm->cnt_sel = uprm->cnt_sel;
+ kprm->ccnode_type = uprm->ccnode_type;
+
+ /* Allocate memory to store array of user-space keys descriptors */
+ us_keys = kzalloc(sizeof(compat_uptr_t) * cls_members, GFP_KERNEL);
+ if (!us_keys) {
+ log_err("Cannot allocate memory array of lookup keys\n");
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(us_keys, compat_ptr(uprm->keys),
+ (sizeof(compat_uptr_t) * cls_members))) {
+ log_err("Cannot copy from user-space array of keys descriptors\n");
+ kfree(us_keys);
+ return -EBUSY;
+ }
+
+ /* Allocate memory to store array of kernel-space keys descriptors */
+ kprm->keys = kzalloc((sizeof(*kprm->keys) * cls_members), GFP_KERNEL);
+ if (!kprm->keys) {
+ log_err("Cannot allocate kernel memory for lookup keys array\n");
+ kfree(us_keys);
+ return -ENOMEM;
+ }
+ for (i = 0; i < cls_members; i++) {
+ if (!compat_ptr(us_keys[i]))
+ continue;
+ /* Copy user-provided key descriptor */
+ ret = copy_key_descriptor_compatcpy(&kprm->keys[i], us_keys[i]);
+ if (ret != 0) {
+ log_err("Cannot copy the key descriptor\n");
+ kfree(us_keys);
+ return ret;
+ }
+ }
+ kfree(us_keys);
+ return 0;
+}
+
+static long dpa_stats_ipsec_cls_compatcpy(struct dpa_stats_cls_cnt_ipsec *kprm,
+ struct dpa_stats_compat_cls_cnt_ipsec *uprm,
+ uint32_t cls_members)
+{
+ kprm->cnt_sel = uprm->cnt_sel;
+
+ /* Allocate memory to store the sa ids array */
+ kprm->sa_id = kcalloc(cls_members, sizeof(int), GFP_KERNEL);
+ if (!kprm->sa_id) {
+ log_err("Cannot allocate memory for SA ids array\n");
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(kprm->sa_id,
+ (compat_ptr)(uprm->sa_id),
+ (cls_members * sizeof(int)))) {
+ log_err("Cannot copy from user array of SA ids\n");
+ kfree(kprm->sa_id);
+ return -EBUSY;
+ }
+ return 0;
+}
+#endif
diff --git a/drivers/staging/fsl_dpa_offload/wrp_dpa_stats.h b/drivers/staging/fsl_dpa_offload/wrp_dpa_stats.h
new file mode 100644
index 0000000..506b02c
--- /dev/null
+++ b/drivers/staging/fsl_dpa_offload/wrp_dpa_stats.h
@@ -0,0 +1,113 @@
+
+/* Copyright 2008-2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WRP_DPA_STATS_H_
+#define WRP_DPA_STATS_H_
+
+/* Other includes */
+#include "linux/fs.h"
+#include <linux/fsl_dpa_stats.h>
+#include <linux/compat.h>
+
+#define DPA_STATS_CDEV "dpa_stats"
+
+int wrp_dpa_stats_init(void);
+
+int wrp_dpa_stats_exit(void);
+
+int wrp_dpa_stats_open(struct inode *inode, struct file *filp);
+
+int wrp_dpa_stats_release(struct inode *inode, struct file *filp);
+
+ssize_t wrp_dpa_stats_read(struct file *file,
+ char *buf, size_t count, loff_t *off);
+
+long wrp_dpa_stats_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long args);
+
+#ifdef CONFIG_COMPAT
+long wrp_dpa_stats_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long args);
+#endif
+
+#define QUEUE_MAX_EVENTS 2048
+
+struct dpa_stats_event_params {
+ int dpa_stats_id;
+ unsigned int storage_area_offset;
+ unsigned int cnts_written;
+ int bytes_written;
+#ifdef CONFIG_COMPAT
+ compat_uptr_t us_cnt_ids;
+#else
+ int *us_cnt_ids;
+#endif /* CONFIG_COMPAT */
+ unsigned int cnt_ids_len;
+ dpa_stats_request_cb request_done;
+};
+
+struct dpa_stats_event_queue {
+ struct list_head lh; /* Double linked list of events */
+ wait_queue_head_t wq; /* Waitqueue for reader processes */
+ atomic_t count; /* Number of events in the event queue */
+};
+
+struct dpa_stats_event {
+ struct dpa_stats_event_params params; /* Event data */
+ struct list_head lh; /* Event queue list head */
+ int *ks_cnt_ids; /* Request array of counter ids from kernel-space */
+};
+
+struct dpa_stats_async_req_ev {
+ dpa_stats_request_cb request_done; /* Request done callback */
+ unsigned int storage_area_offset; /* Storage offset for this request */
+ /* Pointers to other async requests in the current set */
+ struct list_head node;
+#ifdef CONFIG_COMPAT
+ compat_uptr_t us_cnt_ids; /* Request array of counter ids from US */
+#endif /* CONFIG COMPAT */
+ int *ks_cnt_ids; /* Request array of counter ids from KS */
+ unsigned int cnt_ids_len; /* Number of counter ids in array */
+};
+
+struct wrp_dpa_stats_cb {
+ void *us_mem; /* Pointer to user-space storage area memory */
+ void *k_mem; /* Pointer to kernel-space storage area memory */
+ struct dpa_stats_event_queue ev_queue; /* Event queue */
+ /* Group of asynchronous requests based on CRC collision */
+ struct list_head *async_req_group;
+ struct list_head async_req_pool; /* List of free async request nodes */
+ struct mutex async_req_lock; /* Mutex for operations on async reqs */
+ struct mutex event_queue_lock; /* Mutex for operations on async reqs */
+};
+
+#endif /* WRP_DPA_STATS_H_ */
diff --git a/drivers/staging/fsl_pme2/Kconfig b/drivers/staging/fsl_pme2/Kconfig
new file mode 100644
index 0000000..58c5f2d
--- /dev/null
+++ b/drivers/staging/fsl_pme2/Kconfig
@@ -0,0 +1,226 @@
+config FSL_PME2
+ bool "Freescale Datapath Pattern Matcher support"
+ depends on FSL_QMAN
+
+menu "Freescale Datapath PME options"
+ depends on FSL_PME2
+
+config FSL_PME2_CTRL
+ bool "Freescale PME2 (p4080, etc) device control"
+ default y
+ ---help---
+ This compiles device support for the Freescale PME2 pattern matching
+ part contained in datapath-enabled SoCs (ie. accessed via Qman and
+ Bman portal functionality). At least one guest operating system must
+ have this driver support, together with the appropriate device-tree
+ entry, for PME2 functionality to be available. It is responsible for
+ allocating system memory to the device and configuring it for
+ operation. For this reason, it must be built into the kernel and will
+ initialise during early kernel boot.
+
+config FSL_PME2_PDSRSIZE
+ int "Pattern Description and Stateful Rule default table size"
+ depends on FSL_PME2_CTRL
+ range 74240 1048573
+ default 131072
+ help
+ Select the default size of the Pattern Description and Stateful Rule
+ table as the number of 128 byte entries. This only takes effect if
+ the device tree node doesn't have the 'fsl,pme-pdsr' property.
+ range 74240-1048573 (9.5MB-134MB)
+ default 131072 (16MB)
+
+if FSL_PME2_CTRL
+comment "Statefule Rule Engine"
+endif
+
+config FSL_PME2_SRESIZE
+ int "SRE Session Context Entries table default table size"
+ depends on FSL_PME2_CTRL
+ range 0 134217727
+ default 327680
+ help
+ Select the default size of the SRE Context Table as the number of 32
+ byte entries. This only takes effect if the device tree node doesn't
+ have the 'fsl,pme-sre' property.
+ range 0-134217727 (0-4GB)
+ default 327680 (10MB)
+
+config FSL_PME2_SRE_AIM
+ bool "Alternate Inconclusive Mode"
+ depends on FSL_PME2_CTRL
+ default n
+ help
+ Select the inconclusive match mode treatment. When true the
+ “alternate†inconclusive mode is used. When false the “defaultâ€
+ inconclusive mode is used.
+
+config FSL_PME2_SRE_ESR
+ bool "End of SUI Simple Report"
+ depends on FSL_PME2_CTRL
+ default n
+ help
+ Select if an End of SUI will produce a Simple End of SUI report.
+
+config FSL_PME2_SRE_CTX_SIZE_PER_SESSION
+ int "Default SRE Context Size per Session (16 => 64KB, 17 => 128KB)"
+ depends on FSL_PME2_CTRL
+ range 5 17
+ default 17
+ help
+ Select SRE context size per session as a power of 2.
+ range 5-17
+ Examples:
+ 5 => 32 B
+ 6 => 64 B
+ 7 => 128 B
+ 8 => 256 B
+ 9 => 512 B
+ 10 => 1 KB
+ 11 => 2 KB
+ 12 => 4 KB
+ 13 => 8 KB
+ 14 => 16 KB
+ 15 => 32 KB
+ 16 => 64 KB
+ 17 => 128 KB
+
+config FSL_PME2_SRE_CNR
+ int "Configured Number of Stateful Rules as a multiple of 256 (128 => 32768 )"
+ depends on FSL_PME2_CTRL
+ range 0 128
+ default 128
+ help
+ Select number of stateful rules as a multiple of 256.
+ range 0-128
+ Examples:
+ 0 => 0
+ 1 => 256
+ 2 => 512
+ ...
+ 127 => 32512
+ 128 => 32768
+
+config FSL_PME2_SRE_MAX_INSTRUCTION_LIMIT
+ int "Maximum number of SRE instructions to be executed per reaction."
+ depends on FSL_PME2_CTRL
+ range 0 65535
+ default 65535
+ help
+ Select the maximum number of SRE instructions to be executed per
+ reaction.
+ range 0 65535
+
+config FSL_PME2_SRE_MAX_BLOCK_NUMBER
+ int "Maximum number of Reaction Head blocks to be traversed per pattern match event"
+ depends on FSL_PME2_CTRL
+ range 0 32767
+ default 32767
+ help
+ Select the maximum number of reaction head blocks to be traversed per
+ pattern match event (e.g. a matched pattern or an End of SUI event).
+ range 0-32767
+
+config FSL_PME2_PORTAL
+ tristate "Freescale PME2 (p4080, etc) device usage"
+ default y
+ ---help---
+ This compiles I/O support for the Freescale PME2 pattern matching
+ part contained in datapath-enabled SoCs (ie. accessed via Qman and
+ Bman portal functionality).
+
+if FSL_PME2_PORTAL
+
+config FSL_PME2_TEST_HIGH
+ tristate "PME2 high-level self-test"
+ default n
+ ---help---
+ This uses the high-level Qman driver (and the cpu-affine portals it
+ manages) to perform high-level PME2 API testing with it.
+
+config FSL_PME2_TEST_SCAN
+ tristate "PME2 scan self-test"
+ depends on FSL_PME2_CTRL
+ default n
+ ---help---
+ This uses the high-level Qman driver (and the cpu-affine portals it
+ manages) to perform scan PME2 API testing with it.
+
+config FSL_PME2_TEST_SCAN_WITH_BPID
+ bool "PME2 scan self-test with buffer pool"
+ depends on FSL_PME2_TEST_SCAN && FSL_BMAN
+ default y
+ ---help---
+ This uses a buffer pool id for scan test
+
+config FSL_PME2_TEST_SCAN_WITH_BPID_SIZE
+ int "Buffer Pool size."
+ depends on FSL_PME2_TEST_SCAN_WITH_BPID
+ range 0 11
+ default 3
+ ---help---
+ This uses the specified buffer pool size.
+
+config FSL_PME2_DB
+ tristate "PME2 Database support"
+ depends on FSL_PME2_CTRL
+ default y
+ ---help---
+ This compiles the database driver for PME2.
+
+config FSL_PME2_DB_QOSOUT_PRIORITY
+ int "PME DB output frame queue priority."
+ depends on FSL_PME2_DB
+ range 0 7
+ default 2
+ ---help---
+ The PME DB has a scheduled output frame queue. The qos priority level is configurable.
+ range 0-7
+ 0 => High Priority 0
+ 1 => High Priority 1
+ 2 => Medium Priority
+ 3 => Medium Priority
+ 4 => Medium Priority
+ 5 => Low Priority
+ 6 => Low Priority
+ 7 => Low Priority
+
+config FSL_PME2_SCAN
+ tristate "PME2 Scan support"
+ default y
+ ---help---
+ This compiles the scan driver for PME2.
+
+config FSL_PME2_SCAN_DEBUG
+ bool "Debug Statements"
+ default n
+ depends on FSL_PME2_SCAN
+ ---help---
+ The PME2_SCAN driver can optionally trace with more verbosity
+ of verbosity.
+
+config FSL_PME_BUG_4K_SCAN_REV_2_1_4
+ bool "workaround for errata in PME version 2.1.4"
+ default y
+ ---help---
+ If this option is selected, the driver will be compiled with a
+ workaround for this errata. This prevents scans of SUIs greater
+ than 4095 - 127 bytes when this revision of HW is detected.
+
+ If in doubt, say Y.
+
+
+endif
+
+config FSL_PME2_STAT_ACCUMULATOR_UPDATE_INTERVAL
+ int "Configure the pme2 statistics update interval in milliseconds"
+ depends on FSL_PME2_CTRL
+ range 0 10000
+ default 3400
+ help
+ The pme accumulator reads the current device statistics and add it
+ to a running counter. The frequency of these updates may be
+ controlled. If 0 is specified, no automatic updates is done.
+ range 0-10000
+
+endmenu
diff --git a/drivers/staging/fsl_pme2/Makefile b/drivers/staging/fsl_pme2/Makefile
new file mode 100644
index 0000000..694513b
--- /dev/null
+++ b/drivers/staging/fsl_pme2/Makefile
@@ -0,0 +1,9 @@
+# PME
+obj-$(CONFIG_FSL_PME2_CTRL) += pme2_ctrl.o pme2_sysfs.o
+obj-$(CONFIG_FSL_PME2_PORTAL) += pme2.o
+pme2-y := pme2_low.o pme2_high.o
+obj-$(CONFIG_FSL_PME2_TEST_HIGH) += pme2_test_high.o
+obj-$(CONFIG_FSL_PME2_TEST_SCAN) += pme2_test_scanning.o
+pme2_test_scanning-y = pme2_test_scan.o pme2_sample_db.o
+obj-$(CONFIG_FSL_PME2_DB) += pme2_db.o
+obj-$(CONFIG_FSL_PME2_SCAN) += pme2_scan.o
diff --git a/drivers/staging/fsl_pme2/pme2_ctrl.c b/drivers/staging/fsl_pme2/pme2_ctrl.c
new file mode 100644
index 0000000..30956c2
--- /dev/null
+++ b/drivers/staging/fsl_pme2/pme2_ctrl.c
@@ -0,0 +1,1347 @@
+/* Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include "pme2_private.h"
+#include "pme2_regs.h"
+
+/* PME HW Revision */
+#define PME_REV(rev1_reg) (rev1_reg & 0x0000FFFF)
+#define PME_REV_2_0 0x00000200
+#define PME_REV_2_1 0x00000201
+#define DEC1_MAX_REV_2_0 0x000FFFFC
+#define DEC1_MAX_REV_2_1 0x0007FFFC
+
+
+/*
+ * Driver Name is used in naming the sysfs directory
+ * /sys/bus/of_platform/drivers/DRV_NAME
+ */
+#define DRV_NAME "fsl-pme"
+
+#define DEFAULT_PDSR_SZ (CONFIG_FSL_PME2_PDSRSIZE << 7)
+#define DEFAULT_SRE_SZ (CONFIG_FSL_PME2_SRESIZE << 5)
+#define PDSR_TBL_ALIGN (1 << 7)
+#define SRE_TBL_ALIGN (1 << 5)
+#define DEFAULT_SRFCC 400
+
+/* Defaults */
+#define DEFAULT_DEC0_MTE 0x3FFF
+#define DEFAULT_DLC_MPM 0xFFFF
+#define DEFAULT_DLC_MPE 0xFFFF
+/* Boot parameters */
+DECLARE_GLOBAL(max_test_line_per_pat, unsigned int, uint,
+ DEFAULT_DEC0_MTE,
+ "Maximum allowed Test Line Executions per pattern, "
+ "scaled by a factor of 8");
+DECLARE_GLOBAL(max_pat_eval_per_sui, unsigned int, uint,
+ DEFAULT_DLC_MPE,
+ "Maximum Pattern Evaluations per SUI, scaled by a factor of 8")
+DECLARE_GLOBAL(max_pat_matches_per_sui, unsigned int, uint,
+ DEFAULT_DLC_MPM,
+ "Maximum Pattern Matches per SUI");
+/* SRE */
+DECLARE_GLOBAL(sre_rule_num, unsigned int, uint,
+ CONFIG_FSL_PME2_SRE_CNR,
+ "Configured Number of Stateful Rules");
+DECLARE_GLOBAL(sre_session_ctx_size, unsigned int, uint,
+ 1 << CONFIG_FSL_PME2_SRE_CTX_SIZE_PER_SESSION,
+ "SRE Context Size per Session");
+
+/**************************************************/
+/* Section 1 */
+
+/*
+ * This code is called during kernel early-boot and could never be made
+ * loadable.
+ */
+static dma_addr_t dxe_a, sre_a;
+static size_t dxe_sz = DEFAULT_PDSR_SZ, sre_sz = DEFAULT_SRE_SZ;
+
+/*
+ * Parse the <name> property to extract the memory location and size and
+ * memblock_reserve() it. If it isn't supplied, memblock_alloc() the default
+ * size.
+ */
+static __init int parse_mem_property(struct device_node *node, const char *name,
+ dma_addr_t *addr, size_t *sz, u64 align, int zero)
+{
+ const u32 *pint;
+ int ret;
+
+ pint = of_get_property(node, name, &ret);
+ if (!pint || (ret != 16)) {
+ pr_info("pme: No %s property '%s', using"
+ " memblock_alloc(0x%016zx)\n",
+ node->full_name, name, *sz);
+ *addr = memblock_alloc(*sz, align);
+ if (zero)
+ memset(phys_to_virt(*addr), 0, *sz);
+ return 0;
+ }
+ pr_info("pme: Using %s property '%s'\n", node->full_name, name);
+ /* If using a "zero-pma", don't try to zero it, even if you asked */
+ if (zero && of_find_property(node, "zero-pma", &ret)) {
+ pr_info(" it's a 'zero-pma', not zeroing from s/w\n");
+ zero = 0;
+ }
+ *addr = ((u64)pint[0] << 32) | (u64)pint[1];
+ *sz = ((u64)pint[2] << 32) | (u64)pint[3];
+ if ((u64)*addr & (align - 1)) {
+ pr_err("pme: Invalid alignment, address %016llx\n", (u64)*addr);
+ return -EINVAL;
+ }
+ /*
+ * Keep things simple, it's either all in the DRAM range or it's all
+ * outside.
+ */
+ if (*addr < memblock_end_of_DRAM()) {
+ if ((u64)*addr + (u64)*sz > memblock_end_of_DRAM()) {
+ pr_err("pme: outside DRAM range\n");
+ return -EINVAL;
+ }
+ if (memblock_reserve(*addr, *sz) < 0) {
+ pr_err("pme: Failed to reserve %s\n", name);
+ return -ENOMEM;
+ }
+ if (zero)
+ memset(phys_to_virt(*addr), 0, *sz);
+ } else if (zero) {
+ /* map as cacheable, non-guarded */
+ void *tmpp = ioremap_prot(*addr, *sz, 0);
+ memset(tmpp, 0, *sz);
+ iounmap(tmpp);
+ }
+ return 0;
+}
+
+/* No errors/interrupts. Physical addresses are assumed <= 32bits. */
+static int __init fsl_pme2_init(struct device_node *node)
+{
+ const char *s;
+ int ret = 0;
+
+ s = of_get_property(node, "fsl,hv-claimable", &ret);
+ if (s && !strcmp(s, "standby")) {
+ pr_info(" -> in standby mode\n");
+ return 0;
+ }
+ /* Check if pdsr memory already allocated */
+ if (dxe_a) {
+ pr_err("pme: Error fsl_pme2_init already done\n");
+ return -EINVAL;
+ }
+ ret = parse_mem_property(node, "fsl,pme-pdsr", &dxe_a, &dxe_sz,
+ PDSR_TBL_ALIGN, 0);
+ if (ret)
+ return ret;
+ ret = parse_mem_property(node, "fsl,pme-sre", &sre_a, &sre_sz,
+ SRE_TBL_ALIGN, 0);
+ return ret;
+}
+
+__init void pme2_init_early(void)
+{
+ struct device_node *dn;
+ int ret;
+ for_each_compatible_node(dn, NULL, "fsl,pme") {
+ ret = fsl_pme2_init(dn);
+ if (ret)
+ pr_err("pme: Error fsl_pme2_init\n");
+ }
+}
+
+/**************************************************/
+/* Section 2 */
+
+/*
+ * This code is called during driver initialisation. It doesn't do anything with
+ * the device-tree entries nor the PME device, it simply creates the sysfs stuff
+ * and gives the user something to hold. This could be made loadable, if there
+ * was any benefit to doing so - but as the device is already "bound" by static
+ * code, there's little point to hiding the fact.
+ */
+
+MODULE_AUTHOR("Geoff Thorpe");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("FSL PME2 (p4080) device control");
+
+/* Opaque pointer target used to represent the PME CCSR map, ... */
+struct pme;
+
+/* ... and the instance of it. */
+static struct pme *global_pme;
+static int pme_err_irq;
+
+static inline void __pme_out(struct pme *p, u32 offset, u32 val)
+{
+ u32 __iomem *regs = (void *)p;
+ out_be32(regs + (offset >> 2), val);
+}
+#define pme_out(p, r, v) __pme_out(p, PME_REG_##r, v)
+static inline u32 __pme_in(struct pme *p, u32 offset)
+{
+ u32 __iomem *regs = (void *)p;
+ return in_be32(regs + (offset >> 2));
+}
+#define pme_in(p, r) __pme_in(p, PME_REG_##r)
+
+#define PME_EFQC(en, fq) \
+ ({ \
+ /* Assume a default delay of 64 cycles */ \
+ u8 __i419 = 0x1; \
+ u32 __fq419 = (fq) & 0x00ffffff; \
+ ((en) ? 0x80000000 : 0) | (__i419 << 28) | __fq419; \
+ })
+
+#define PME_FACONF_ENABLE 0x00000002
+#define PME_FACONF_RESET 0x00000001
+
+/* pme stats accumulator work */
+static void accumulator_update(struct work_struct *work);
+void accumulator_update_interval(u32 interval);
+static DECLARE_DELAYED_WORK(accumulator_work, accumulator_update);
+u32 pme_stat_interval = CONFIG_FSL_PME2_STAT_ACCUMULATOR_UPDATE_INTERVAL;
+#define PME_SBE_ERR 0x01000000
+#define PME_DBE_ERR 0x00080000
+#define PME_PME_ERR 0x00000100
+#define PME_ALL_ERR (PME_SBE_ERR | PME_DBE_ERR | PME_PME_ERR)
+
+static struct of_device_id of_fsl_pme_ids[] = {
+ {
+ .compatible = "fsl,pme",
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, of_fsl_pme_ids);
+
+/* Pme interrupt handler */
+static irqreturn_t pme_isr(int irq, void *ptr)
+{
+ static u32 last_isrstate;
+ u32 isrstate = pme_in(global_pme, ISR) ^ last_isrstate;
+
+ /* What new ISR state has been raise */
+ if (!isrstate)
+ return IRQ_NONE;
+ if (isrstate & PME_SBE_ERR)
+ pr_crit("PME: SBE detected\n");
+ if (isrstate & PME_DBE_ERR)
+ pr_crit("PME: DBE detected\n");
+ if (isrstate & PME_PME_ERR)
+ pr_crit("PME: PME serious detected\n");
+ /* Clear the ier interrupt bit */
+ last_isrstate |= isrstate;
+ pme_out(global_pme, IER, ~last_isrstate);
+ return IRQ_HANDLED;
+}
+
+static int of_fsl_pme_remove(struct platform_device *ofdev)
+{
+ /* Cancel pme accumulator */
+ accumulator_update_interval(0);
+ cancel_delayed_work_sync(&accumulator_work);
+ /* Disable PME..TODO need to wait till it's quiet */
+ pme_out(global_pme, FACONF, PME_FACONF_RESET);
+ /* Release interrupt */
+ if (likely(pme_err_irq != NO_IRQ))
+ free_irq(pme_err_irq, &ofdev->dev);
+ /* Remove sysfs attribute */
+ pme2_remove_sysfs_dev_files(ofdev);
+ /* Unmap controller region */
+ iounmap(global_pme);
+ global_pme = NULL;
+ return 0;
+}
+
+static int of_fsl_pme_probe(struct platform_device *ofdev)
+{
+ int ret, err = 0;
+ void __iomem *regs;
+ struct device *dev = &ofdev->dev;
+ struct device_node *nprop = dev->of_node;
+ u32 clkfreq = DEFAULT_SRFCC * 1000000;
+ const u32 *value;
+ const char *s;
+ int srec_aim = 0, srec_esr = 0;
+ u32 srecontextsize_code;
+ u32 dec1;
+
+ /*
+ * TODO: This standby handling won't work properly after failover, it's
+ * just to allow bring up for now.
+ */
+ s = of_get_property(nprop, "fsl,hv-claimable", &ret);
+ if (s && !strcmp(s, "standby"))
+ return 0;
+ pme_err_irq = of_irq_to_resource(nprop, 0, NULL);
+ if (unlikely(pme_err_irq == NO_IRQ))
+ dev_warn(dev, "Can't get %s property '%s'\n", nprop->full_name,
+ "interrupts");
+
+ /* Get configuration properties from device tree */
+ /* First, get register page */
+ regs = of_iomap(nprop, 0);
+ if (regs == NULL) {
+ dev_err(dev, "of_iomap() failed\n");
+ err = -EINVAL;
+ goto out;
+ }
+
+ /* Global configuration, leave pme disabled */
+ global_pme = (struct pme *)regs;
+ pme_out(global_pme, FACONF, 0);
+ pme_out(global_pme, EFQC, PME_EFQC(0, 0));
+
+ /*
+ * TODO: these coherency settings for PMFA, DXE, and SRE force all
+ * transactions to snoop, as the kernel does not yet support flushing in
+ * dma_map_***() APIs (ie. h/w can not treat otherwise coherent memory
+ * in a non-coherent manner, temporarily or otherwise). When the kernel
+ * supports this, we should tune these settings back to;
+ * FAMCR = 0x00010001
+ * DMCR = 0x00000000
+ * SMCR = 0x00000000
+ */
+ /* PME HW rev 2.1: Added TWC field in FAMCR */
+ pme_out(global_pme, FAMCR, 0x11010101);
+ pme_out(global_pme, DMCR, 0x00000001);
+ pme_out(global_pme, SMCR, 0x00000211);
+
+ if (likely(pme_err_irq != NO_IRQ)) {
+ /* Register the pme ISR handler */
+ err = request_irq(pme_err_irq, pme_isr, IRQF_SHARED, "pme-err",
+ dev);
+ if (err) {
+ dev_err(dev, "request_irq() failed\n");
+ goto out_unmap_ctrl_region;
+ }
+ }
+
+#ifdef CONFIG_FSL_PME2_SRE_AIM
+ srec_aim = 1;
+#endif
+#ifdef CONFIG_FSL_PME2_SRE_ESR
+ srec_esr = 1;
+#endif
+ /* Validate some parameters */
+ if (!sre_session_ctx_size || !is_power_of_2(sre_session_ctx_size) ||
+ (sre_session_ctx_size < 32) ||
+ (sre_session_ctx_size > (131072))) {
+ dev_err(dev, "invalid sre_session_ctx_size\n");
+ err = -EINVAL;
+ goto out_free_irq;
+ }
+ srecontextsize_code = ilog2(sre_session_ctx_size);
+ srecontextsize_code -= 4;
+
+ /* Configure Clock Frequency */
+ value = of_get_property(nprop, "clock-frequency", NULL);
+ if (value)
+ clkfreq = *value;
+ pme_out(global_pme, SFRCC, DIV_ROUND_UP(clkfreq, 1000000));
+
+ pme_out(global_pme, PDSRBAH, upper_32_bits(dxe_a));
+ pme_out(global_pme, PDSRBAL, lower_32_bits(dxe_a));
+ pme_out(global_pme, SCBARH, upper_32_bits(sre_a));
+ pme_out(global_pme, SCBARL, lower_32_bits(sre_a));
+ /*
+ * Maximum allocated index into the PDSR table available to the DXE
+ * Rev 2.0: Max 0xF_FFFC
+ * Rev 2.1: Max 0x7_FFFC
+ */
+ if (PME_REV(pme_in(global_pme, PM_IP_REV1)) == PME_REV_2_0) {
+ if (((dxe_sz/PDSR_TBL_ALIGN)-1) > DEC1_MAX_REV_2_0)
+ dec1 = DEC1_MAX_REV_2_0;
+ else
+ dec1 = (dxe_sz/PDSR_TBL_ALIGN)-1;
+ } else {
+ if (((dxe_sz/PDSR_TBL_ALIGN)-1) > DEC1_MAX_REV_2_1)
+ dec1 = DEC1_MAX_REV_2_1;
+ else
+ dec1 = (dxe_sz/PDSR_TBL_ALIGN)-1;
+ }
+ pme_out(global_pme, DEC1, dec1);
+ /* Maximum allocated index into the PDSR table available to the SRE */
+ pme_out(global_pme, SEC2, dec1);
+ /* Maximum allocated 32-byte offset into SRE Context Table.*/
+ if (sre_sz)
+ pme_out(global_pme, SEC3, (sre_sz/SRE_TBL_ALIGN)-1);
+ /* Max test line execution */
+ pme_out(global_pme, DEC0, max_test_line_per_pat);
+ pme_out(global_pme, DLC,
+ (max_pat_eval_per_sui << 16) | max_pat_matches_per_sui);
+
+ /* SREC - SRE Config */
+ pme_out(global_pme, SREC,
+ /* Number of rules in database */
+ (sre_rule_num << 0) |
+ /* Simple Report Enabled */
+ ((srec_esr ? 1 : 0) << 18) |
+ /* Context Size per Session */
+ (srecontextsize_code << 19) |
+ /* Alternate Inclusive Mode */
+ ((srec_aim ? 1 : 0) << 29));
+ pme_out(global_pme, SEC1,
+ (CONFIG_FSL_PME2_SRE_MAX_INSTRUCTION_LIMIT << 16) |
+ CONFIG_FSL_PME2_SRE_MAX_BLOCK_NUMBER);
+
+ /* Setup Accumulator */
+ if (pme_stat_interval)
+ schedule_delayed_work(&accumulator_work,
+ msecs_to_jiffies(pme_stat_interval));
+ /* Create sysfs entries */
+ err = pme2_create_sysfs_dev_files(ofdev);
+ if (err)
+ goto out_stop_accumulator;
+
+ /* Enable interrupts */
+ pme_out(global_pme, IER, PME_ALL_ERR);
+ dev_info(dev, "ver: 0x%08x\n", pme_in(global_pme, PM_IP_REV1));
+
+ /* Enable pme */
+ pme_out(global_pme, FACONF, PME_FACONF_ENABLE);
+ return 0;
+
+out_stop_accumulator:
+ if (pme_stat_interval) {
+ accumulator_update_interval(0);
+ cancel_delayed_work_sync(&accumulator_work);
+ }
+out_free_irq:
+ if (likely(pme_err_irq != NO_IRQ))
+ free_irq(pme_err_irq, &ofdev->dev);
+out_unmap_ctrl_region:
+ pme_out(global_pme, FACONF, PME_FACONF_RESET);
+ iounmap(global_pme);
+ global_pme = NULL;
+out:
+ return err;
+}
+
+static struct platform_driver of_fsl_pme_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRV_NAME,
+ .of_match_table = of_fsl_pme_ids,
+ },
+ .probe = of_fsl_pme_probe,
+ .remove = of_fsl_pme_remove,
+};
+
+static int pme2_ctrl_init(void)
+{
+ return platform_driver_register(&of_fsl_pme_driver);
+}
+
+static void pme2_ctrl_exit(void)
+{
+ platform_driver_unregister(&of_fsl_pme_driver);
+}
+
+module_init(pme2_ctrl_init);
+module_exit(pme2_ctrl_exit);
+
+/**************************************************/
+/* Section 3 */
+
+/*
+ * These APIs are the only functional hooks into the control driver, besides the
+ * sysfs attributes.
+ */
+
+int pme2_have_control(void)
+{
+ return global_pme ? 1 : 0;
+}
+EXPORT_SYMBOL(pme2_have_control);
+
+int pme2_exclusive_set(struct qman_fq *fq)
+{
+ if (!pme2_have_control())
+ return -ENODEV;
+ pme_out(global_pme, EFQC, PME_EFQC(1, qman_fq_fqid(fq)));
+ return 0;
+}
+EXPORT_SYMBOL(pme2_exclusive_set);
+
+int pme2_exclusive_unset(void)
+{
+ if (!pme2_have_control())
+ return -ENODEV;
+ pme_out(global_pme, EFQC, PME_EFQC(0, 0));
+ return 0;
+}
+EXPORT_SYMBOL(pme2_exclusive_unset);
+
+int pme_attr_set(enum pme_attr attr, u32 val)
+{
+ u32 mask;
+ u32 attr_val;
+
+ if (!pme2_have_control())
+ return -ENODEV;
+
+ /* Check if Buffer size configuration */
+ if (attr >= pme_attr_bsc_first && attr <= pme_attr_bsc_last) {
+ u32 bsc_pool_id = attr - pme_attr_bsc_first;
+ u32 bsc_pool_offset = bsc_pool_id % 8;
+ u32 bsc_pool_mask = ~(0xF << ((7-bsc_pool_offset)*4));
+ /* range for val 0..0xB */
+ if (val > 0xb)
+ return -EINVAL;
+ /* calculate which sky-blue reg */
+ /* 0..7 -> bsc_(0..7), PME_REG_BSC0 */
+ /* 8..15 -> bsc_(8..15) PME_REG_BSC1*/
+ /* ... */
+ /* 56..63 -> bsc_(56..63) PME_REG_BSC7*/
+ attr_val = pme_in(global_pme, BSC0 + ((bsc_pool_id/8)*4));
+ /* Now mask in the new value */
+ attr_val = attr_val & bsc_pool_mask;
+ attr_val = attr_val | (val << ((7-bsc_pool_offset)*4));
+ pme_out(global_pme, BSC0 + ((bsc_pool_id/8)*4), attr_val);
+ return 0;
+ }
+
+ switch (attr) {
+ case pme_attr_efqc_int:
+ if (val > 4)
+ return -EINVAL;
+ mask = 0x8FFFFFFF;
+ attr_val = pme_in(global_pme, EFQC);
+ /* clear efqc_int */
+ attr_val &= mask;
+ val <<= 28;
+ val |= attr_val;
+ pme_out(global_pme, EFQC, val);
+ break;
+
+ case pme_attr_sw_db:
+ pme_out(global_pme, SWDB, val);
+ break;
+
+ case pme_attr_dmcr:
+ pme_out(global_pme, DMCR, val);
+ break;
+
+ case pme_attr_smcr:
+ pme_out(global_pme, SMCR, val);
+ break;
+
+ case pme_attr_famcr:
+ pme_out(global_pme, FAMCR, val);
+ break;
+
+ case pme_attr_kvlts:
+ if (val < 2 || val > 16)
+ return -EINVAL;
+ /* HW range: 1..15, SW range: 2..16 */
+ pme_out(global_pme, KVLTS, --val);
+ break;
+
+ case pme_attr_max_chain_length:
+ if (val > 0x7FFF)
+ val = 0x7FFF;
+ pme_out(global_pme, KEC, val);
+ break;
+
+ case pme_attr_pattern_range_counter_idx:
+ if (val > 0x1FFFF)
+ val = 0x1FFFF;
+ pme_out(global_pme, DRCIC, val);
+ break;
+
+ case pme_attr_pattern_range_counter_mask:
+ if (val > 0x1FFFF)
+ val = 0x1FFFF;
+ pme_out(global_pme, DRCMC, val);
+ break;
+
+ case pme_attr_max_allowed_test_line_per_pattern:
+ if (val > 0x3FFF)
+ val = 0x3FFF;
+ pme_out(global_pme, DEC0, val);
+ break;
+
+ case pme_attr_max_pattern_matches_per_sui:
+ /* mpe, mpm */
+ if (val > 0xFFFF)
+ val = 0xFFFF;
+ mask = 0xFFFF0000;
+ attr_val = pme_in(global_pme, DLC);
+ /* clear mpm */
+ attr_val &= mask;
+ val &= ~mask;
+ val |= attr_val;
+ pme_out(global_pme, DLC, val);
+ break;
+
+ case pme_attr_max_pattern_evaluations_per_sui:
+ /* mpe, mpm */
+ if (val > 0xFFFF)
+ val = 0xFFFF;
+ mask = 0x0000FFFF;
+ attr_val = pme_in(global_pme, DLC);
+ /* clear mpe */
+ attr_val &= mask;
+ /* clear unwanted bits in val*/
+ val &= mask;
+ val <<= 16;
+ val |= attr_val;
+ pme_out(global_pme, DLC, val);
+ break;
+
+ case pme_attr_report_length_limit:
+ if (val > 0xFFFF)
+ val = 0xFFFF;
+ pme_out(global_pme, RLL, val);
+ break;
+
+ case pme_attr_end_of_simple_sui_report:
+ /* bit 13 */
+ mask = 0x00040000;
+ attr_val = pme_in(global_pme, SREC);
+ if (val)
+ attr_val |= mask;
+ else
+ attr_val &= ~mask;
+ pme_out(global_pme, SREC, attr_val);
+ break;
+
+ case pme_attr_aim:
+ /* bit 2 */
+ mask = 0x20000000;
+ attr_val = pme_in(global_pme, SREC);
+ if (val)
+ attr_val |= mask;
+ else
+ attr_val &= ~mask;
+ pme_out(global_pme, SREC, attr_val);
+ break;
+
+ case pme_attr_end_of_sui_reaction_ptr:
+ if (val > 0xFFFFF)
+ val = 0xFFFFF;
+ pme_out(global_pme, ESRP, val);
+ break;
+
+ case pme_attr_sre_pscl:
+ pme_out(global_pme, SFRCC, val);
+ break;
+
+ case pme_attr_sre_max_block_num:
+ /* bits 17..31 */
+ if (val > 0x7FFF)
+ val = 0x7FFF;
+ mask = 0xFFFF8000;
+ attr_val = pme_in(global_pme, SEC1);
+ /* clear mbn */
+ attr_val &= mask;
+ /* clear unwanted bits in val*/
+ val &= ~mask;
+ val |= attr_val;
+ pme_out(global_pme, SEC1, val);
+ break;
+
+ case pme_attr_sre_max_instruction_limit:
+ /* bits 0..15 */
+ if (val > 0xFFFF)
+ val = 0xFFFF;
+ mask = 0x0000FFFF;
+ attr_val = pme_in(global_pme, SEC1);
+ /* clear mil */
+ attr_val &= mask;
+ /* clear unwanted bits in val*/
+ val &= mask;
+ val <<= 16;
+ val |= attr_val;
+ pme_out(global_pme, SEC1, val);
+ break;
+
+ case pme_attr_srrv0:
+ pme_out(global_pme, SRRV0, val);
+ break;
+ case pme_attr_srrv1:
+ pme_out(global_pme, SRRV1, val);
+ break;
+ case pme_attr_srrv2:
+ pme_out(global_pme, SRRV2, val);
+ break;
+ case pme_attr_srrv3:
+ pme_out(global_pme, SRRV3, val);
+ break;
+ case pme_attr_srrv4:
+ pme_out(global_pme, SRRV4, val);
+ break;
+ case pme_attr_srrv5:
+ pme_out(global_pme, SRRV5, val);
+ break;
+ case pme_attr_srrv6:
+ pme_out(global_pme, SRRV6, val);
+ break;
+ case pme_attr_srrv7:
+ pme_out(global_pme, SRRV7, val);
+ break;
+ case pme_attr_srrfi:
+ pme_out(global_pme, SRRFI, val);
+ break;
+ case pme_attr_srri:
+ pme_out(global_pme, SRRI, val);
+ break;
+ case pme_attr_srrwc:
+ pme_out(global_pme, SRRWC, val);
+ break;
+ case pme_attr_srrr:
+ pme_out(global_pme, SRRR, val);
+ break;
+ case pme_attr_tbt0ecc1th:
+ pme_out(global_pme, TBT0ECC1TH, val);
+ break;
+ case pme_attr_tbt1ecc1th:
+ pme_out(global_pme, TBT1ECC1TH, val);
+ break;
+ case pme_attr_vlt0ecc1th:
+ pme_out(global_pme, VLT0ECC1TH, val);
+ break;
+ case pme_attr_vlt1ecc1th:
+ pme_out(global_pme, VLT1ECC1TH, val);
+ break;
+ case pme_attr_cmecc1th:
+ pme_out(global_pme, CMECC1TH, val);
+ break;
+ case pme_attr_dxcmecc1th:
+ pme_out(global_pme, DXCMECC1TH, val);
+ break;
+ case pme_attr_dxemecc1th:
+ pme_out(global_pme, DXEMECC1TH, val);
+ break;
+ case pme_attr_esr:
+ pme_out(global_pme, ESR, val);
+ break;
+ case pme_attr_pehd:
+ pme_out(global_pme, PEHD, val);
+ break;
+ case pme_attr_ecc1bes:
+ pme_out(global_pme, ECC1BES, val);
+ break;
+ case pme_attr_ecc2bes:
+ pme_out(global_pme, ECC2BES, val);
+ break;
+ case pme_attr_miace:
+ pme_out(global_pme, MIA_CE, val);
+ break;
+ case pme_attr_miacr:
+ pme_out(global_pme, MIA_CR, val);
+ break;
+ case pme_attr_cdcr:
+ pme_out(global_pme, CDCR, val);
+ break;
+ case pme_attr_pmtr:
+ pme_out(global_pme, PMTR, val);
+ break;
+
+ default:
+ pr_err("pme: Unknown attr %u\n", attr);
+ return -EINVAL;
+ };
+ return 0;
+}
+EXPORT_SYMBOL(pme_attr_set);
+
+int pme_attr_get(enum pme_attr attr, u32 *val)
+{
+ u32 mask;
+ u32 attr_val;
+
+ if (!pme2_have_control())
+ return -ENODEV;
+
+ /* Check if Buffer size configuration */
+ if (attr >= pme_attr_bsc_first && attr <= pme_attr_bsc_last) {
+ u32 bsc_pool_id = attr - pme_attr_bsc_first;
+ u32 bsc_pool_offset = bsc_pool_id % 8;
+ /* calculate which sky-blue reg */
+ /* 0..7 -> bsc_(0..7), PME_REG_BSC0 */
+ /* 8..15 -> bsc_(8..15) PME_REG_BSC1*/
+ /* ... */
+ /* 56..63 -> bsc_(56..63) PME_REG_BSC7*/
+ attr_val = pme_in(global_pme, BSC0 + ((bsc_pool_id/8)*4));
+ attr_val = attr_val >> ((7-bsc_pool_offset)*4);
+ attr_val = attr_val & 0x0000000F;
+ *val = attr_val;
+ return 0;
+ }
+
+ switch (attr) {
+ case pme_attr_efqc_int:
+ mask = 0x8FFFFFFF;
+ attr_val = pme_in(global_pme, EFQC);
+ attr_val &= ~mask;
+ attr_val >>= 28;
+ break;
+
+ case pme_attr_sw_db:
+ attr_val = pme_in(global_pme, SWDB);
+ break;
+
+ case pme_attr_dmcr:
+ attr_val = pme_in(global_pme, DMCR);
+ break;
+
+ case pme_attr_smcr:
+ attr_val = pme_in(global_pme, SMCR);
+ break;
+
+ case pme_attr_famcr:
+ attr_val = pme_in(global_pme, FAMCR);
+ break;
+
+ case pme_attr_kvlts:
+ /* bit 28-31 */
+ attr_val = pme_in(global_pme, KVLTS);
+ attr_val &= 0x0000000F;
+ /* HW range: 1..15, SW range: 2..16 */
+ attr_val += 1;
+ break;
+
+ case pme_attr_max_chain_length:
+ /* bit 17-31 */
+ attr_val = pme_in(global_pme, KEC);
+ attr_val &= 0x00007FFF;
+ break;
+
+ case pme_attr_pattern_range_counter_idx:
+ /* bit 15-31 */
+ attr_val = pme_in(global_pme, DRCIC);
+ attr_val &= 0x0001FFFF;
+ break;
+
+ case pme_attr_pattern_range_counter_mask:
+ /* bit 15-31 */
+ attr_val = pme_in(global_pme, DRCMC);
+ attr_val &= 0x0001FFFF;
+ break;
+
+ case pme_attr_max_allowed_test_line_per_pattern:
+ /* bit 18-31 */
+ attr_val = pme_in(global_pme, DEC0);
+ attr_val &= 0x00003FFF;
+ break;
+
+ case pme_attr_max_pdsr_index:
+ /* bit 12-31 */
+ attr_val = pme_in(global_pme, DEC1);
+ attr_val &= 0x000FFFFF;
+ break;
+
+ case pme_attr_max_pattern_matches_per_sui:
+ attr_val = pme_in(global_pme, DLC);
+ attr_val &= 0x0000FFFF;
+ break;
+
+ case pme_attr_max_pattern_evaluations_per_sui:
+ attr_val = pme_in(global_pme, DLC);
+ attr_val >>= 16;
+ break;
+
+ case pme_attr_report_length_limit:
+ attr_val = pme_in(global_pme, RLL);
+ /* clear unwanted bits in val*/
+ attr_val &= 0x0000FFFF;
+ break;
+
+ case pme_attr_end_of_simple_sui_report:
+ /* bit 13 */
+ attr_val = pme_in(global_pme, SREC);
+ attr_val >>= 18;
+ /* clear unwanted bits in val*/
+ attr_val &= 0x00000001;
+ break;
+
+ case pme_attr_aim:
+ /* bit 2 */
+ attr_val = pme_in(global_pme, SREC);
+ attr_val >>= 29;
+ /* clear unwanted bits in val*/
+ attr_val &= 0x00000001;
+ break;
+
+ case pme_attr_sre_context_size:
+ /* bits 9..12 */
+ attr_val = pme_in(global_pme, SREC);
+ attr_val >>= 19;
+ /* clear unwanted bits in val*/
+ attr_val &= 0x0000000F;
+ attr_val += 4;
+ attr_val = 1 << attr_val;
+ break;
+
+ case pme_attr_sre_rule_num:
+ /* bits 24..31 */
+ attr_val = pme_in(global_pme, SREC);
+ /* clear unwanted bits in val*/
+ attr_val &= 0x000000FF;
+ /* Multiply by 256 */
+ attr_val <<= 8;
+ break;
+
+ case pme_attr_sre_session_ctx_num: {
+ u32 ctx_sz = 0;
+ /* = sre_table_size / sre_session_ctx_size */
+ attr_val = pme_in(global_pme, SEC3);
+ /* clear unwanted bits in val*/
+ attr_val &= 0x07FFFFFF;
+ attr_val += 1;
+ attr_val *= 32;
+ ctx_sz = pme_in(global_pme, SREC);
+ ctx_sz >>= 19;
+ /* clear unwanted bits in val*/
+ ctx_sz &= 0x0000000F;
+ ctx_sz += 4;
+ attr_val /= (1 << ctx_sz);
+ }
+ break;
+
+ case pme_attr_end_of_sui_reaction_ptr:
+ /* bits 12..31 */
+ attr_val = pme_in(global_pme, ESRP);
+ /* clear unwanted bits in val*/
+ attr_val &= 0x000FFFFF;
+ break;
+
+ case pme_attr_sre_pscl:
+ /* bits 22..31 */
+ attr_val = pme_in(global_pme, SFRCC);
+ break;
+
+ case pme_attr_sre_max_block_num:
+ /* bits 17..31 */
+ attr_val = pme_in(global_pme, SEC1);
+ /* clear unwanted bits in val*/
+ attr_val &= 0x00007FFF;
+ break;
+
+ case pme_attr_sre_max_instruction_limit:
+ /* bits 0..15 */
+ attr_val = pme_in(global_pme, SEC1);
+ attr_val >>= 16;
+ break;
+
+ case pme_attr_sre_max_index_size:
+ /* bits 12..31 */
+ attr_val = pme_in(global_pme, SEC2);
+ /* clear unwanted bits in val*/
+ attr_val &= 0x000FFFFF;
+ break;
+
+ case pme_attr_sre_max_offset_ctrl:
+ /* bits 5..31 */
+ attr_val = pme_in(global_pme, SEC3);
+ /* clear unwanted bits in val*/
+ attr_val &= 0x07FFFFFF;
+ break;
+
+ case pme_attr_src_id:
+ /* bits 24..31 */
+ attr_val = pme_in(global_pme, SRCIDR);
+ /* clear unwanted bits in val*/
+ attr_val &= 0x000000FF;
+ break;
+
+ case pme_attr_liodnr:
+ /* bits 20..31 */
+ attr_val = pme_in(global_pme, LIODNR);
+ /* clear unwanted bits in val*/
+ attr_val &= 0x00000FFF;
+ break;
+
+ case pme_attr_rev1:
+ /* bits 0..31 */
+ attr_val = pme_in(global_pme, PM_IP_REV1);
+ break;
+
+ case pme_attr_rev2:
+ /* bits 0..31 */
+ attr_val = pme_in(global_pme, PM_IP_REV2);
+ break;
+
+ case pme_attr_srrr:
+ attr_val = pme_in(global_pme, SRRR);
+ break;
+
+ case pme_attr_trunci:
+ attr_val = pme_in(global_pme, TRUNCI);
+ break;
+
+ case pme_attr_rbc:
+ attr_val = pme_in(global_pme, RBC);
+ break;
+
+ case pme_attr_tbt0ecc1ec:
+ attr_val = pme_in(global_pme, TBT0ECC1EC);
+ break;
+
+ case pme_attr_tbt1ecc1ec:
+ attr_val = pme_in(global_pme, TBT1ECC1EC);
+ break;
+
+ case pme_attr_vlt0ecc1ec:
+ attr_val = pme_in(global_pme, VLT0ECC1EC);
+ break;
+
+ case pme_attr_vlt1ecc1ec:
+ attr_val = pme_in(global_pme, VLT1ECC1EC);
+ break;
+
+ case pme_attr_cmecc1ec:
+ attr_val = pme_in(global_pme, CMECC1EC);
+ break;
+
+ case pme_attr_dxcmecc1ec:
+ attr_val = pme_in(global_pme, DXCMECC1EC);
+ break;
+
+ case pme_attr_dxemecc1ec:
+ attr_val = pme_in(global_pme, DXEMECC1EC);
+ break;
+
+ case pme_attr_tbt0ecc1th:
+ attr_val = pme_in(global_pme, TBT0ECC1TH);
+ break;
+
+ case pme_attr_tbt1ecc1th:
+ attr_val = pme_in(global_pme, TBT1ECC1TH);
+ break;
+
+ case pme_attr_vlt0ecc1th:
+ attr_val = pme_in(global_pme, VLT0ECC1TH);
+ break;
+
+ case pme_attr_vlt1ecc1th:
+ attr_val = pme_in(global_pme, VLT1ECC1TH);
+ break;
+
+ case pme_attr_cmecc1th:
+ attr_val = pme_in(global_pme, CMECC1TH);
+ break;
+
+ case pme_attr_dxcmecc1th:
+ attr_val = pme_in(global_pme, DXCMECC1TH);
+ break;
+
+ case pme_attr_dxemecc1th:
+ attr_val = pme_in(global_pme, DXEMECC1TH);
+ break;
+
+ case pme_attr_stnib:
+ attr_val = pme_in(global_pme, STNIB);
+ break;
+
+ case pme_attr_stnis:
+ attr_val = pme_in(global_pme, STNIS);
+ break;
+
+ case pme_attr_stnth1:
+ attr_val = pme_in(global_pme, STNTH1);
+ break;
+
+ case pme_attr_stnth2:
+ attr_val = pme_in(global_pme, STNTH2);
+ break;
+
+ case pme_attr_stnthv:
+ attr_val = pme_in(global_pme, STNTHV);
+ break;
+
+ case pme_attr_stnths:
+ attr_val = pme_in(global_pme, STNTHS);
+ break;
+
+ case pme_attr_stnch:
+ attr_val = pme_in(global_pme, STNCH);
+ break;
+
+ case pme_attr_stnpm:
+ attr_val = pme_in(global_pme, STNPM);
+ break;
+
+ case pme_attr_stns1m:
+ attr_val = pme_in(global_pme, STNS1M);
+ break;
+
+ case pme_attr_stnpmr:
+ attr_val = pme_in(global_pme, STNPMR);
+ break;
+
+ case pme_attr_stndsr:
+ attr_val = pme_in(global_pme, STNDSR);
+ break;
+
+ case pme_attr_stnesr:
+ attr_val = pme_in(global_pme, STNESR);
+ break;
+
+ case pme_attr_stns1r:
+ attr_val = pme_in(global_pme, STNS1R);
+ break;
+
+ case pme_attr_stnob:
+ attr_val = pme_in(global_pme, STNOB);
+ break;
+
+ case pme_attr_mia_byc:
+ attr_val = pme_in(global_pme, MIA_BYC);
+ break;
+
+ case pme_attr_mia_blc:
+ attr_val = pme_in(global_pme, MIA_BLC);
+ break;
+
+ case pme_attr_isr:
+ attr_val = pme_in(global_pme, ISR);
+ break;
+
+ case pme_attr_ecr0:
+ attr_val = pme_in(global_pme, ECR0);
+ break;
+
+ case pme_attr_ecr1:
+ attr_val = pme_in(global_pme, ECR1);
+ break;
+
+ case pme_attr_esr:
+ attr_val = pme_in(global_pme, ESR);
+ break;
+
+ case pme_attr_pmstat:
+ attr_val = pme_in(global_pme, PMSTAT);
+ break;
+
+ case pme_attr_pehd:
+ attr_val = pme_in(global_pme, PEHD);
+ break;
+
+ case pme_attr_ecc1bes:
+ attr_val = pme_in(global_pme, ECC1BES);
+ break;
+
+ case pme_attr_ecc2bes:
+ attr_val = pme_in(global_pme, ECC2BES);
+ break;
+
+ case pme_attr_eccaddr:
+ attr_val = pme_in(global_pme, ECCADDR);
+ break;
+
+ case pme_attr_ecccode:
+ attr_val = pme_in(global_pme, ECCCODE);
+ break;
+
+ case pme_attr_miace:
+ attr_val = pme_in(global_pme, MIA_CE);
+ break;
+
+ case pme_attr_miacr:
+ attr_val = pme_in(global_pme, MIA_CR);
+ break;
+
+ case pme_attr_cdcr:
+ attr_val = pme_in(global_pme, CDCR);
+ break;
+
+ case pme_attr_pmtr:
+ attr_val = pme_in(global_pme, PMTR);
+ break;
+
+ case pme_attr_faconf:
+ attr_val = pme_in(global_pme, FACONF);
+ break;
+
+ case pme_attr_pdsrbah:
+ attr_val = pme_in(global_pme, PDSRBAH);
+ break;
+
+ case pme_attr_pdsrbal:
+ attr_val = pme_in(global_pme, PDSRBAL);
+ break;
+
+ case pme_attr_scbarh:
+ attr_val = pme_in(global_pme, SCBARH);
+ break;
+
+ case pme_attr_scbarl:
+ attr_val = pme_in(global_pme, SCBARL);
+ break;
+
+ case pme_attr_srrv0:
+ attr_val = pme_in(global_pme, SRRV0);
+ break;
+
+ case pme_attr_srrv1:
+ attr_val = pme_in(global_pme, SRRV1);
+ break;
+
+ case pme_attr_srrv2:
+ attr_val = pme_in(global_pme, SRRV2);
+ break;
+
+ case pme_attr_srrv3:
+ attr_val = pme_in(global_pme, SRRV3);
+ break;
+
+ case pme_attr_srrv4:
+ attr_val = pme_in(global_pme, SRRV4);
+ break;
+
+ case pme_attr_srrv5:
+ attr_val = pme_in(global_pme, SRRV5);
+ break;
+
+ case pme_attr_srrv6:
+ attr_val = pme_in(global_pme, SRRV6);
+ break;
+
+ case pme_attr_srrv7:
+ attr_val = pme_in(global_pme, SRRV7);
+ break;
+
+ case pme_attr_srrfi:
+ attr_val = pme_in(global_pme, SRRFI);
+ break;
+
+ case pme_attr_srri:
+ attr_val = pme_in(global_pme, SRRI);
+ break;
+
+ case pme_attr_srrwc:
+ attr_val = pme_in(global_pme, SRRWC);
+ break;
+
+ default:
+ pr_err("pme: Unknown attr %u\n", attr);
+ return -EINVAL;
+ };
+ *val = attr_val;
+ return 0;
+}
+EXPORT_SYMBOL(pme_attr_get);
+
+static enum pme_attr stat_list[] = {
+ pme_attr_trunci,
+ pme_attr_rbc,
+ pme_attr_tbt0ecc1ec,
+ pme_attr_tbt1ecc1ec,
+ pme_attr_vlt0ecc1ec,
+ pme_attr_vlt1ecc1ec,
+ pme_attr_cmecc1ec,
+ pme_attr_dxcmecc1ec,
+ pme_attr_dxemecc1ec,
+ pme_attr_stnib,
+ pme_attr_stnis,
+ pme_attr_stnth1,
+ pme_attr_stnth2,
+ pme_attr_stnthv,
+ pme_attr_stnths,
+ pme_attr_stnch,
+ pme_attr_stnpm,
+ pme_attr_stns1m,
+ pme_attr_stnpmr,
+ pme_attr_stndsr,
+ pme_attr_stnesr,
+ pme_attr_stns1r,
+ pme_attr_stnob,
+ pme_attr_mia_byc,
+ pme_attr_mia_blc
+};
+
+static u64 pme_stats[sizeof(stat_list)/sizeof(enum pme_attr)];
+static DEFINE_SPINLOCK(stat_lock);
+
+int pme_stat_get(enum pme_attr stat, u64 *value, int reset)
+{
+ int i, ret = 0;
+ int value_set = 0;
+ u32 val;
+
+ spin_lock_irq(&stat_lock);
+ for (i = 0; i < sizeof(stat_list)/sizeof(enum pme_attr); i++) {
+ if (stat_list[i] == stat) {
+ ret = pme_attr_get(stat_list[i], &val);
+ /* Do I need to check ret */
+ pme_stats[i] += val;
+ *value = pme_stats[i];
+ value_set = 1;
+ if (reset)
+ pme_stats[i] = 0;
+ break;
+ }
+ }
+ if (!value_set) {
+ pr_err("pme: Invalid stat request %d\n", stat);
+ ret = -EINVAL;
+ }
+ spin_unlock_irq(&stat_lock);
+ return ret;
+}
+EXPORT_SYMBOL(pme_stat_get);
+
+void accumulator_update_interval(u32 interval)
+{
+ int schedule = 0;
+
+ spin_lock_irq(&stat_lock);
+ if (!pme_stat_interval && interval)
+ schedule = 1;
+ pme_stat_interval = interval;
+ spin_unlock_irq(&stat_lock);
+ if (schedule)
+ schedule_delayed_work(&accumulator_work,
+ msecs_to_jiffies(interval));
+}
+
+static void accumulator_update(struct work_struct *work)
+{
+ int i, ret;
+ u32 local_interval;
+ u32 val;
+
+ spin_lock_irq(&stat_lock);
+ local_interval = pme_stat_interval;
+ for (i = 0; i < sizeof(stat_list)/sizeof(enum pme_attr); i++) {
+ ret = pme_attr_get(stat_list[i], &val);
+ pme_stats[i] += val;
+ }
+ spin_unlock_irq(&stat_lock);
+ if (local_interval)
+ schedule_delayed_work(&accumulator_work,
+ msecs_to_jiffies(local_interval));
+}
diff --git a/drivers/staging/fsl_pme2/pme2_db.c b/drivers/staging/fsl_pme2/pme2_db.c
new file mode 100644
index 0000000..50263d5
--- /dev/null
+++ b/drivers/staging/fsl_pme2/pme2_db.c
@@ -0,0 +1,573 @@
+/* Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "pme2_private.h"
+#include <linux/compat.h>
+
+/* Forward declaration */
+static struct miscdevice fsl_pme2_db_dev;
+
+/* Global spinlock for handling exclusive inc/dec */
+static DEFINE_SPINLOCK(exclusive_lock);
+
+/* Private structure that is allocated for each open that is done on the
+ * pme_db device. This is used to maintain the state of a database session */
+struct db_session {
+ /* The ctx that is needed to communicate with the pme high level */
+ struct pme_ctx ctx;
+ /* Used to track the EXCLUSIVE_INC and EXCLUSIVE_DEC ioctls */
+ unsigned int exclusive_counter;
+};
+
+struct cmd_token {
+ /* pme high level token */
+ struct pme_ctx_token hl_token;
+ /* data */
+ struct qm_fd rx_fd;
+ /* Completion interface */
+ struct completion cb_done;
+ u8 ern;
+};
+
+#ifdef CONFIG_COMPAT
+static void compat_to_db(struct pme_db *dst, struct compat_pme_db *src)
+{
+ dst->flags = src->flags;
+ dst->status = src->status;
+ dst->input.data = compat_ptr(src->input.data);
+ dst->input.size = src->input.size;
+ dst->output.data = compat_ptr(src->output.data);
+ dst->output.size = src->output.size;
+}
+
+static void db_to_compat(struct compat_pme_db *dst, struct pme_db *src)
+{
+ dst->flags = src->flags;
+ dst->status = src->status;
+ dst->output.data = ptr_to_compat(src->output.data);
+ dst->output.size = src->output.size;
+ dst->input.data = ptr_to_compat(src->input.data);
+ dst->input.size = src->input.size;
+}
+#endif
+
+/* PME Compound Frame Index */
+#define INPUT_FRM 1
+#define OUTPUT_FRM 0
+
+/* Callback for database operations */
+static void db_cb(struct pme_ctx *ctx, const struct qm_fd *fd,
+ struct pme_ctx_token *ctx_token)
+{
+ struct cmd_token *token = (struct cmd_token *)ctx_token;
+ token->rx_fd = *fd;
+ complete(&token->cb_done);
+}
+
+static void db_ern_cb(struct pme_ctx *ctx, const struct qm_mr_entry *mr,
+ struct pme_ctx_token *ctx_token)
+{
+ struct cmd_token *token = (struct cmd_token *)ctx_token;
+ token->ern = 1;
+ token->rx_fd = mr->ern.fd;
+ complete(&token->cb_done);
+}
+
+struct ctrl_op {
+ struct pme_ctx_ctrl_token ctx_ctr;
+ struct completion cb_done;
+ enum pme_status cmd_status;
+ u8 res_flag;
+ u8 ern;
+};
+
+static void ctrl_cb(struct pme_ctx *ctx, const struct qm_fd *fd,
+ struct pme_ctx_ctrl_token *token)
+{
+ struct ctrl_op *ctrl = (struct ctrl_op *)token;
+ ctrl->cmd_status = pme_fd_res_status(fd);
+ ctrl->res_flag = pme_fd_res_flags(fd) & PME_STATUS_UNRELIABLE;
+ complete(&ctrl->cb_done);
+}
+
+static void ctrl_ern_cb(struct pme_ctx *ctx, const struct qm_mr_entry *mr,
+ struct pme_ctx_ctrl_token *token)
+{
+ struct ctrl_op *ctrl = (struct ctrl_op *)token;
+ ctrl->ern = 1;
+ complete(&ctrl->cb_done);
+}
+
+static int exclusive_inc(struct file *fp, struct db_session *db)
+{
+ int ret;
+
+ BUG_ON(!db);
+ BUG_ON(!(db->ctx.flags & PME_CTX_FLAG_EXCLUSIVE));
+ spin_lock(&exclusive_lock);
+ ret = pme_ctx_exclusive_inc(&db->ctx,
+ (PME_CTX_OP_WAIT | PME_CTX_OP_WAIT_INT));
+ if (!ret)
+ db->exclusive_counter++;
+ spin_unlock(&exclusive_lock);
+ return ret;
+}
+
+static int exclusive_dec(struct file *fp, struct db_session *db)
+{
+ int ret = 0;
+
+ BUG_ON(!db);
+ BUG_ON(!(db->ctx.flags & PME_CTX_FLAG_EXCLUSIVE));
+ spin_lock(&exclusive_lock);
+ if (!db->exclusive_counter) {
+ PMEPRERR("exclusivity counter already zero\n");
+ ret = -EINVAL;
+ } else {
+ pme_ctx_exclusive_dec(&db->ctx);
+ db->exclusive_counter--;
+ }
+ spin_unlock(&exclusive_lock);
+ return ret;
+}
+
+static int execute_cmd(struct file *fp, struct db_session *db,
+ struct pme_db *db_cmd)
+{
+ int ret = 0;
+ struct cmd_token token;
+ struct qm_sg_entry tx_comp[2];
+ struct qm_fd tx_fd;
+ void *tx_data = NULL;
+ void *rx_data = NULL;
+ u32 src_sz, dst_sz;
+ dma_addr_t dma_addr;
+
+ memset(&token, 0, sizeof(struct cmd_token));
+ memset(tx_comp, 0, sizeof(tx_comp));
+ memset(&tx_fd, 0, sizeof(struct qm_fd));
+ init_completion(&token.cb_done);
+
+ PMEPRINFO("Received User Space Contiguous mem\n");
+ PMEPRINFO("length = %d\n", db_cmd->input.size);
+ tx_data = kmalloc(db_cmd->input.size, GFP_KERNEL);
+ if (!tx_data) {
+ PMEPRERR("Err alloc %zd byte\n", db_cmd->input.size);
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(tx_data,
+ (void __user *)db_cmd->input.data,
+ db_cmd->input.size)) {
+ PMEPRERR("Error copying contigous user data\n");
+ ret = -EFAULT;
+ goto free_tx_data;
+ }
+
+ /* Setup input frame */
+ tx_comp[INPUT_FRM].final = 1;
+ tx_comp[INPUT_FRM].length = db_cmd->input.size;
+ dma_addr = pme_map(tx_data);
+ if (pme_map_error(dma_addr)) {
+ PMEPRERR("Error pme_map_error\n");
+ ret = -EIO;
+ goto free_tx_data;
+ }
+ set_sg_addr(&tx_comp[INPUT_FRM], dma_addr);
+ /* setup output frame, if output is expected */
+ if (db_cmd->output.size) {
+ PMEPRINFO("expect output %d\n", db_cmd->output.size);
+ rx_data = kmalloc(db_cmd->output.size, GFP_KERNEL);
+ if (!rx_data) {
+ PMEPRERR("Err alloc %zd byte", db_cmd->output.size);
+ ret = -ENOMEM;
+ goto unmap_input_frame;
+ }
+ /* Setup output frame */
+ tx_comp[OUTPUT_FRM].length = db_cmd->output.size;
+ dma_addr = pme_map(rx_data);
+ if (pme_map_error(dma_addr)) {
+ PMEPRERR("Error pme_map_error\n");
+ ret = -EIO;
+ goto comp_frame_free_rx;
+ }
+ set_sg_addr(&tx_comp[OUTPUT_FRM], dma_addr);
+ tx_fd.format = qm_fd_compound;
+ /* Build compound frame */
+ dma_addr = pme_map(tx_comp);
+ if (pme_map_error(dma_addr)) {
+ PMEPRERR("Error pme_map_error\n");
+ ret = -EIO;
+ goto comp_frame_unmap_output;
+ }
+ set_fd_addr(&tx_fd, dma_addr);
+ } else {
+ tx_fd.format = qm_fd_sg_big;
+ tx_fd.length29 = db_cmd->input.size;
+ /* Build sg frame */
+ dma_addr = pme_map(&tx_comp[INPUT_FRM]);
+ if (pme_map_error(dma_addr)) {
+ PMEPRERR("Error pme_map_error\n");
+ ret = -EIO;
+ goto unmap_input_frame;
+ }
+ set_fd_addr(&tx_fd, dma_addr);
+ }
+ ret = pme_ctx_pmtcc(&db->ctx, PME_CTX_OP_WAIT, &tx_fd,
+ (struct pme_ctx_token *)&token);
+ if (unlikely(ret)) {
+ PMEPRINFO("pme_ctx_pmtcc error %d\n", ret);
+ goto unmap_frame;
+ }
+ PMEPRINFO("Wait for completion\n");
+ /* Wait for the command to complete */
+ wait_for_completion(&token.cb_done);
+
+ if (token.ern) {
+ ret = -EIO;
+ goto unmap_frame;
+ }
+
+ PMEPRINFO("pme2_db: process_completed_token\n");
+ PMEPRINFO("pme2_db: received %d frame type\n", token.rx_fd.format);
+ if (token.rx_fd.format == qm_fd_compound) {
+ /* Need to copy output */
+ src_sz = tx_comp[OUTPUT_FRM].length;
+ dst_sz = db_cmd->output.size;
+ PMEPRINFO("pme gen %u data, have space for %u\n",
+ src_sz, dst_sz);
+ db_cmd->output.size = min(dst_sz, src_sz);
+ /*
+ * Doesn't make sense we generated more than available space
+ * should have got truncation.
+ */
+ BUG_ON(dst_sz < src_sz);
+ if (copy_to_user((void __user *)db_cmd->output.data, rx_data,
+ db_cmd->output.size)) {
+ PMEPRERR("Error copying to user data\n");
+ ret = -EFAULT;
+ goto comp_frame_unmap_cf;
+ }
+ } else if (token.rx_fd.format == qm_fd_sg_big)
+ db_cmd->output.size = 0;
+ else
+ panic("unexpected frame type received %d\n",
+ token.rx_fd.format);
+
+ db_cmd->flags = pme_fd_res_flags(&token.rx_fd);
+ db_cmd->status = pme_fd_res_status(&token.rx_fd);
+
+unmap_frame:
+ if (token.rx_fd.format == qm_fd_sg_big)
+ goto single_frame_unmap_frame;
+
+comp_frame_unmap_cf:
+comp_frame_unmap_output:
+comp_frame_free_rx:
+ kfree(rx_data);
+ goto unmap_input_frame;
+single_frame_unmap_frame:
+unmap_input_frame:
+free_tx_data:
+ kfree(tx_data);
+
+ return ret;
+}
+
+static int execute_nop(struct file *fp, struct db_session *db)
+{
+ int ret = 0;
+ struct ctrl_op ctx_ctrl = {
+ .ctx_ctr.cb = ctrl_cb,
+ .ctx_ctr.ern_cb = ctrl_ern_cb
+ };
+ init_completion(&ctx_ctrl.cb_done);
+
+ ret = pme_ctx_ctrl_nop(&db->ctx, PME_CTX_OP_WAIT|PME_CTX_OP_WAIT_INT,
+ &ctx_ctrl.ctx_ctr);
+ if (!ret)
+ wait_for_completion(&ctx_ctrl.cb_done);
+
+ if (ctx_ctrl.ern)
+ ret = -EIO;
+ return ret;
+}
+
+static atomic_t sre_reset_lock = ATOMIC_INIT(1);
+static int ioctl_sre_reset(unsigned long arg)
+{
+ struct pme_db_sre_reset reset_vals;
+ int i;
+ u32 srrr_val;
+ int ret = 0;
+
+ if (copy_from_user(&reset_vals, (struct pme_db_sre_reset __user *)arg,
+ sizeof(struct pme_db_sre_reset)))
+ return -EFAULT;
+ PMEPRINFO("sre_reset:\n");
+ PMEPRINFO(" rule_index = 0x%x:\n", reset_vals.rule_index);
+ PMEPRINFO(" rule_increment = 0x%x:\n", reset_vals.rule_increment);
+ PMEPRINFO(" rule_repetitions = 0x%x:\n", reset_vals.rule_repetitions);
+ PMEPRINFO(" rule_reset_interval = 0x%x:\n",
+ reset_vals.rule_reset_interval);
+ PMEPRINFO(" rule_reset_priority = 0x%x:\n",
+ reset_vals.rule_reset_priority);
+
+ /* Validate ranges */
+ if ((reset_vals.rule_index >= PME_PMFA_SRE_INDEX_MAX) ||
+ (reset_vals.rule_increment > PME_PMFA_SRE_INC_MAX) ||
+ (reset_vals.rule_repetitions >= PME_PMFA_SRE_REP_MAX) ||
+ (reset_vals.rule_reset_interval >=
+ PME_PMFA_SRE_INTERVAL_MAX))
+ return -ERANGE;
+ /* Check and make sure only one caller is present */
+ if (!atomic_dec_and_test(&sre_reset_lock)) {
+ /* Someone else is already in this call */
+ atomic_inc(&sre_reset_lock);
+ return -EBUSY;
+ };
+ /* All validated. Run the command */
+ for (i = 0; i < PME_SRE_RULE_VECTOR_SIZE; i++)
+ pme_attr_set(pme_attr_srrv0 + i, reset_vals.rule_vector[i]);
+ pme_attr_set(pme_attr_srrfi, reset_vals.rule_index);
+ pme_attr_set(pme_attr_srri, reset_vals.rule_increment);
+ pme_attr_set(pme_attr_srrwc,
+ (0xFFF & reset_vals.rule_reset_interval) << 1 |
+ (reset_vals.rule_reset_priority ? 1 : 0));
+ /* Need to set SRRR last */
+ pme_attr_set(pme_attr_srrr, reset_vals.rule_repetitions);
+ do {
+ mdelay(PME_PMFA_SRE_POLL_MS);
+ ret = pme_attr_get(pme_attr_srrr, &srrr_val);
+ if (ret) {
+ PMEPRCRIT("pme2: Error reading srrr\n");
+ /* bail */
+ break;
+ }
+ /* Check for error */
+ else if (srrr_val & 0x10000000) {
+ PMEPRERR("pme2: Error in SRRR\n");
+ ret = -EIO;
+ }
+ PMEPRINFO("pme2: srrr count %d\n", srrr_val);
+ } while (srrr_val);
+ atomic_inc(&sre_reset_lock);
+ return ret;
+}
+
+/**
+ * fsl_pme2_db_open - open the driver
+ *
+ * Open the driver and prepare for requests.
+ *
+ * Every time an application opens the driver, we create a db_session object
+ * for that file handle.
+ */
+static int fsl_pme2_db_open(struct inode *node, struct file *fp)
+{
+ int ret;
+ struct db_session *db = NULL;
+
+ db = kzalloc(sizeof(struct db_session), GFP_KERNEL);
+ if (!db)
+ return -ENOMEM;
+ fp->private_data = db;
+ db->ctx.cb = db_cb;
+ db->ctx.ern_cb = db_ern_cb;
+
+ ret = pme_ctx_init(&db->ctx,
+ PME_CTX_FLAG_EXCLUSIVE |
+ PME_CTX_FLAG_PMTCC |
+ PME_CTX_FLAG_DIRECT|
+ PME_CTX_FLAG_LOCAL,
+ 0, 4, CONFIG_FSL_PME2_DB_QOSOUT_PRIORITY, 0, NULL);
+ if (ret) {
+ PMEPRERR("pme_ctx_init %d\n", ret);
+ goto free_data;
+ }
+
+ /* enable the context */
+ ret = pme_ctx_enable(&db->ctx);
+ if (ret) {
+ PMEPRERR("error enabling ctx %d\n", ret);
+ pme_ctx_finish(&db->ctx);
+ goto free_data;
+ }
+ PMEPRINFO("pme2_db: Finish pme_db open %d\n", smp_processor_id());
+ return 0;
+free_data:
+ kfree(fp->private_data);
+ fp->private_data = NULL;
+ return ret;
+}
+
+static int fsl_pme2_db_close(struct inode *node, struct file *fp)
+{
+ int ret = 0;
+ struct db_session *db = fp->private_data;
+
+ PMEPRINFO("Start pme_db close\n");
+ while (db->exclusive_counter) {
+ pme_ctx_exclusive_dec(&db->ctx);
+ db->exclusive_counter--;
+ }
+
+ /* Disable context. */
+ ret = pme_ctx_disable(&db->ctx, PME_CTX_OP_WAIT, NULL);
+ if (ret)
+ PMEPRCRIT("Error disabling ctx %d\n", ret);
+ pme_ctx_finish(&db->ctx);
+ kfree(db);
+ PMEPRINFO("Finish pme_db close\n");
+ return 0;
+}
+
+/* Main switch loop for ioctl operations */
+static long fsl_pme2_db_ioctl(struct file *fp, unsigned int cmd,
+ unsigned long arg)
+{
+ struct db_session *db = fp->private_data;
+ int ret = 0;
+
+ switch (cmd) {
+
+ case PMEIO_PMTCC: {
+ int ret;
+ struct pme_db db_cmd;
+
+ /* Copy the command to kernel space */
+ if (copy_from_user(&db_cmd, (void __user *)arg,
+ sizeof(db_cmd)))
+ return -EFAULT;
+ ret = execute_cmd(fp, db, &db_cmd);
+ if (!ret)
+ ret = copy_to_user((struct pme_db __user *)arg,
+ &db_cmd, sizeof(db_cmd));
+ return ret;
+ }
+ break;
+
+ case PMEIO_EXL_INC:
+ return exclusive_inc(fp, db);
+ case PMEIO_EXL_DEC:
+ return exclusive_dec(fp, db);
+ case PMEIO_EXL_GET:
+ BUG_ON(!db);
+ BUG_ON(!(db->ctx.flags & PME_CTX_FLAG_EXCLUSIVE));
+ if (copy_to_user((void __user *)arg,
+ &db->exclusive_counter,
+ sizeof(db->exclusive_counter)))
+ ret = -EFAULT;
+ return ret;
+ case PMEIO_NOP:
+ return execute_nop(fp, db);
+ case PMEIO_SRE_RESET:
+ return ioctl_sre_reset(arg);
+
+#ifdef CONFIG_COMPAT
+ case PMEIO_PMTCC32: {
+ int ret;
+ struct pme_db db_cmd;
+ struct compat_pme_db db_cmd32;
+ struct compat_pme_db __user *user_db_cmd = compat_ptr(arg);
+
+ /* Copy the command to kernel space */
+ if (copy_from_user(&db_cmd32, user_db_cmd, sizeof(db_cmd32)))
+ return -EFAULT;
+ /* Convert to 64-bit struct */
+ compat_to_db(&db_cmd, &db_cmd32);
+ ret = execute_cmd(fp, db, &db_cmd);
+ if (!ret) {
+ /* Convert to compat struct */
+ db_to_compat(&db_cmd32, &db_cmd);
+ ret = copy_to_user(user_db_cmd, &db_cmd32,
+ sizeof(*user_db_cmd));
+ }
+ return ret;
+ }
+ break;
+#endif
+ }
+ pr_info("Unknown pme_db ioctl cmd %u\n", cmd);
+ return -EINVAL;
+}
+
+static const struct file_operations fsl_pme2_db_fops = {
+ .owner = THIS_MODULE,
+ .open = fsl_pme2_db_open,
+ .release = fsl_pme2_db_close,
+ .unlocked_ioctl = fsl_pme2_db_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = fsl_pme2_db_ioctl,
+#endif
+};
+
+static struct miscdevice fsl_pme2_db_dev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = PME_DEV_DB_NODE,
+ .fops = &fsl_pme2_db_fops
+};
+
+static int __init fsl_pme2_db_init(void)
+{
+ int err = 0;
+
+ pr_info("Freescale pme2 db driver\n");
+ if (!pme2_have_control()) {
+ PMEPRERR("not on ctrl-plane\n");
+ return -ENODEV;
+ }
+ err = misc_register(&fsl_pme2_db_dev);
+ if (err) {
+ PMEPRERR("cannot register device\n");
+ return err;
+ }
+ PMEPRINFO("device %s registered\n", fsl_pme2_db_dev.name);
+ return 0;
+}
+
+static void __exit fsl_pme2_db_exit(void)
+{
+ int err = misc_deregister(&fsl_pme2_db_dev);
+ if (err) {
+ PMEPRERR("Failed to deregister device %s code %d\n",
+ fsl_pme2_db_dev.name, err);
+ return;
+ }
+ PMEPRINFO("device %s deregistered\n", fsl_pme2_db_dev.name);
+}
+
+module_init(fsl_pme2_db_init);
+module_exit(fsl_pme2_db_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor - OTC");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("FSL PME2 db driver");
diff --git a/drivers/staging/fsl_pme2/pme2_high.c b/drivers/staging/fsl_pme2/pme2_high.c
new file mode 100644
index 0000000..094ee9d
--- /dev/null
+++ b/drivers/staging/fsl_pme2/pme2_high.c
@@ -0,0 +1,1043 @@
+/* Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "pme2_private.h"
+
+/*
+ * The pme_ctx state machine is described via the following list of
+ * internal PME_CTX_FLAG_*** bits and cross-referenced to the APIs (and
+ * functionality) they track.
+ *
+ * DEAD: set at any point, an error has been hit, doesn't "cause" disabling or
+ * any autonomous ref-decrement (been there, hit the gotchas, won't do it
+ * again).
+ *
+ * DISABLING: set by pme_ctx_disable() at any point that is not already
+ * disabling, disabled, or in ctrl, and the ref is decremented. DISABLING is
+ * unset by pme_ctx_enable().
+ *
+ * DISABLED: once pme_ctx_disable() has set DISABLING and refs==0, DISABLED is
+ * set before returning. (Any failure will clear DISABLING and increment the ref
+ * count.) DISABLING is unset by pme_ctx_enable().
+ *
+ * ENABLING: set by pme_ctx_enable() provided the context is disabled, not dead,
+ * not in RECONFIG, and not already enabling. Once set, the ref is incremented
+ * and the tx FQ is scheduled (for non-exclusive flows). If this fails, the ref
+ * is decremented and the context is re-disabled. ENABLING is unset once
+ * pme_ctx_enable() completes.
+ *
+ * RECONFIG: set by pme_ctx_reconfigure_[rt]x() provided the context is
+ * disabled, not dead, and not already in reconfig. RECONFIG is cleared prior to
+ * the function returning.
+ *
+ * Simplifications: the do_flag() wrapper provides synchronised modifications of
+ * the ctx 'flags', and callers can rely on the following implications to reduce
+ * the number of flags in the masks being passed in;
+ * DISABLED implies DISABLING (and enable will clear both)
+ */
+
+/* Internal-only ctx flags, mustn't conflict with exported ones */
+#define PME_CTX_FLAG_DEAD 0x80000000
+#define PME_CTX_FLAG_DISABLING 0x40000000
+#define PME_CTX_FLAG_DISABLED 0x20000000
+#define PME_CTX_FLAG_ENABLING 0x10000000
+#define PME_CTX_FLAG_RECONFIG 0x08000000
+#define PME_CTX_FLAG_PRIVATE 0xf8000000 /* mask of them all */
+
+/* Internal-only cmd flags, musn't conflict with exported ones */
+#define PME_CTX_OP_INSIDE_DISABLE 0x80000000
+#define PME_CTX_OP_PRIVATE 0x80000000 /* mask of them all */
+
+struct pme_nostash {
+ struct qman_fq fqin;
+ struct pme_ctx *parent;
+};
+
+/*
+ * This wrapper simplifies conditional (and locked) read-modify-writes to
+ * 'flags'. Inlining should allow the compiler to optimise it based on the
+ * parameters, eg. if 'must_be_set'/'must_not_be_set' are zero it will
+ * degenerate to an unconditional read-modify-write, if 'to_set'/'to_unset' are
+ * zero it will degenerate to a read-only flag-check, etc.
+ */
+static inline int do_flags(struct pme_ctx *ctx,
+ u32 must_be_set, u32 must_not_be_set,
+ u32 to_set, u32 to_unset)
+{
+ int err = -EBUSY;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&ctx->lock, irqflags);
+ if (((ctx->flags & must_be_set) == must_be_set) &&
+ !(ctx->flags & must_not_be_set)) {
+ ctx->flags |= to_set;
+ ctx->flags &= ~to_unset;
+ err = 0;
+ }
+ spin_unlock_irqrestore(&ctx->lock, irqflags);
+ return err;
+}
+
+static enum qman_cb_dqrr_result cb_dqrr(struct qman_portal *, struct qman_fq *,
+ const struct qm_dqrr_entry *);
+static void cb_ern(struct qman_portal *, struct qman_fq *,
+ const struct qm_mr_entry *);
+static void cb_fqs(struct qman_portal *, struct qman_fq *,
+ const struct qm_mr_entry *);
+static const struct qman_fq_cb pme_fq_base_in = {
+ .fqs = cb_fqs,
+ .ern = cb_ern
+};
+static const struct qman_fq_cb pme_fq_base_out = {
+ .dqrr = cb_dqrr,
+ .fqs = cb_fqs
+};
+
+/* Globals related to competition for PME_EFQC, ie. exclusivity */
+static DECLARE_WAIT_QUEUE_HEAD(exclusive_queue);
+static spinlock_t exclusive_lock = __SPIN_LOCK_UNLOCKED(exclusive_lock);
+static unsigned int exclusive_refs;
+static struct pme_ctx *exclusive_ctx;
+
+/*
+ * Index 0..255, bools do indicated which errors are serious
+ * 0x40, 0x41, 0x48, 0x49, 0x4c, 0x4e, 0x4f, 0x50, 0x51, 0x59, 0x5a, 0x5b,
+ * 0x5c, 0x5d, 0x5f, 0x60, 0x80, 0xc0, 0xc1, 0xc2, 0xc4, 0xd2,
+ * 0xd4, 0xd5, 0xd7, 0xd9, 0xda, 0xe0, 0xe7
+ */
+static u8 serious_error_vec[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/*
+ * TODO: this is hitting the rx FQ with a large blunt instrument, ie. park()
+ * does a retire, query, oos, and (re)init. It's possible to force-eligible the
+ * rx FQ instead, then use a DCA_PK within the cb_dqrr() callback to park it.
+ * Implement this optimisation later if it's an issue (and incur the additional
+ * complexity in the state-machine).
+ */
+static int park(struct qman_fq *fq, struct qm_mcc_initfq *initfq)
+{
+ int ret;
+ u32 flags;
+
+ ret = qman_retire_fq(fq, &flags);
+ if (ret)
+ return ret;
+ BUG_ON(flags & QMAN_FQ_STATE_BLOCKOOS);
+ /* We can't revert from now on */
+ ret = qman_query_fq(fq, &initfq->fqd);
+ BUG_ON(ret);
+ ret = qman_oos_fq(fq);
+ BUG_ON(ret);
+ /* can't set QM_INITFQ_WE_OAC and QM_INITFQ_WE_TDTHRESH
+ * at the same time */
+ initfq->we_mask = QM_INITFQ_WE_MASK & ~QM_INITFQ_WE_TDTHRESH;
+ ret = qman_init_fq(fq, 0, initfq);
+ BUG_ON(ret);
+ initfq->we_mask = QM_INITFQ_WE_TDTHRESH;
+ ret = qman_init_fq(fq, 0, initfq);
+ BUG_ON(ret);
+ return 0;
+}
+
+static inline int reconfigure_rx(struct pme_ctx *ctx, int to_park, u8 qosout,
+ u16 dest,
+ const struct qm_fqd_stashing *stashing)
+{
+ struct qm_mcc_initfq initfq;
+ u32 flags = QMAN_INITFQ_FLAG_SCHED;
+ int ret;
+
+ ret = do_flags(ctx, PME_CTX_FLAG_DISABLED,
+ PME_CTX_FLAG_DEAD | PME_CTX_FLAG_RECONFIG,
+ PME_CTX_FLAG_RECONFIG, 0);
+ if (ret)
+ return ret;
+ if (to_park) {
+ ret = park(&ctx->fq, &initfq);
+ if (ret)
+ goto done;
+ }
+ initfq.we_mask = QM_INITFQ_WE_DESTWQ | QM_INITFQ_WE_FQCTRL;
+ initfq.fqd.dest.wq = qosout;
+ if (stashing) {
+ initfq.we_mask |= QM_INITFQ_WE_CONTEXTA;
+ initfq.fqd.context_a.stashing = *stashing;
+ initfq.fqd.fq_ctrl = QM_FQCTRL_CTXASTASHING;
+ } else {
+ initfq.fqd.fq_ctrl = 0; /* disable stashing */
+ }
+ if (ctx->flags & PME_CTX_FLAG_LOCAL) {
+ flags |= QMAN_INITFQ_FLAG_LOCAL;
+ } else {
+ initfq.fqd.dest.channel = dest;
+ /* Set hold-active *IFF* it's a pool channel */
+ if (dest >= qm_channel_pool1)
+ initfq.fqd.fq_ctrl |= QM_FQCTRL_HOLDACTIVE;
+ }
+ ret = qman_init_fq(&ctx->fq, flags, &initfq);
+done:
+ do_flags(ctx, 0, 0, 0, PME_CTX_FLAG_RECONFIG);
+ return ret;
+}
+
+/* this code is factored out of pme_ctx_disable() and get_ctrl() */
+static int empty_pipeline(struct pme_ctx *ctx, __maybe_unused u32 flags)
+{
+ int ret;
+#ifdef CONFIG_FSL_DPA_CAN_WAIT
+ if (flags & PME_CTX_OP_WAIT) {
+ if (flags & PME_CTX_OP_WAIT_INT) {
+ ret = -EINTR;
+ wait_event_interruptible(ctx->queue,
+ !(ret = atomic_read(&ctx->refs)));
+ } else {
+ wait_event(ctx->queue,
+ !(ret = atomic_read(&ctx->refs)));
+ }
+ } else
+#endif
+ {
+ ret = atomic_read(&ctx->refs);
+ }
+ if (ret)
+ /* convert a +ve ref-count to a -ve error code */
+ ret = -EBUSY;
+ return ret;
+}
+
+/**
+ * set_pme_revision - set the pme revision in the ctx
+ *
+ * In order to make decisions based on PME HW version, read this
+ * information and store it on the ctx object.
+ */
+static int set_pme_revision(struct pme_ctx *ctx)
+{
+ int ret = 0;
+ u32 rev1, rev2;
+ struct device_node *dn;
+ const u32 *dt_rev;
+ int len;
+
+#ifdef CONFIG_FSL_PME2_CTRL
+ /* Can try and read it from CCSR */
+ if (pme2_have_control()) {
+ ret = pme_attr_get(pme_attr_rev1, &rev1);
+ if (ret)
+ return ret;
+ ret = pme_attr_get(pme_attr_rev2, &rev2);
+ if (ret)
+ return ret;
+ ctx->pme_rev1 = rev1;
+ ctx->pme_rev2 = rev2;
+ return 0;
+ }
+#endif
+
+ /* Not on control-plane, try and get it from pme portal node */
+ dn = of_find_node_with_property(NULL, "fsl,pme-rev1");
+ if (!dn)
+ return -ENODEV;
+ dt_rev = of_get_property(dn, "fsl,pme-rev1", &len);
+ if (!dt_rev || len != 4) {
+ of_node_put(dn);
+ return -ENODEV;
+ }
+ rev1 = *dt_rev;
+
+ dt_rev = of_get_property(dn, "fsl,pme-rev2", &len);
+ if (!dt_rev || len != 4) {
+ of_node_put(dn);
+ return -ENODEV;
+ }
+ rev2 = *dt_rev;
+ of_node_put(dn);
+ ctx->pme_rev1 = rev1;
+ ctx->pme_rev2 = rev2;
+ return ret;
+}
+
+int pme_ctx_init(struct pme_ctx *ctx, u32 flags, u32 bpid, u8 qosin,
+ u8 qosout, u16 dest,
+ const struct qm_fqd_stashing *stashing)
+{
+ int rxinit = 0, ret = -ENOMEM, fqin_inited = 0;
+
+ ctx->fq.cb = pme_fq_base_out;
+ atomic_set(&ctx->refs, 0);
+ ctx->flags = (flags & ~PME_CTX_FLAG_PRIVATE) | PME_CTX_FLAG_DISABLED |
+ PME_CTX_FLAG_DISABLING;
+ if (ctx->flags & PME_CTX_FLAG_PMTCC)
+ ctx->flags |= PME_CTX_FLAG_DIRECT | PME_CTX_FLAG_EXCLUSIVE;
+ spin_lock_init(&ctx->lock);
+ init_waitqueue_head(&ctx->queue);
+ INIT_LIST_HEAD(&ctx->tokens);
+ ctx->hw_flow = NULL;
+ ctx->hw_residue = NULL;
+ ret = set_pme_revision(ctx);
+ if (ret)
+ goto err;
+#ifdef CONFIG_FSL_PME_BUG_4K_SCAN_REV_2_1_4
+ if (is_version_2_1_4(ctx->pme_rev1, ctx->pme_rev2))
+ ctx->max_scan_size = PME_MAX_SCAN_SIZE_BUG_2_1_4;
+ else
+ ctx->max_scan_size = 0;
+#endif
+ ctx->us_data = kzalloc(sizeof(struct pme_nostash), GFP_KERNEL);
+ if (!ctx->us_data)
+ goto err;
+ ctx->us_data->parent = ctx;
+ if (!ctx->us_data)
+ goto err;
+ ctx->us_data->fqin.cb = pme_fq_base_in;
+ if (qman_create_fq(0, QMAN_FQ_FLAG_TO_DCPORTAL |
+ QMAN_FQ_FLAG_DYNAMIC_FQID |
+ ((flags & PME_CTX_FLAG_LOCKED) ?
+ QMAN_FQ_FLAG_LOCKED : 0),
+ &ctx->us_data->fqin))
+ goto err;
+ fqin_inited = 1;
+ if (qman_create_fq(0, QMAN_FQ_FLAG_NO_ENQUEUE |
+ QMAN_FQ_FLAG_DYNAMIC_FQID |
+ ((flags & PME_CTX_FLAG_LOCKED) ?
+ QMAN_FQ_FLAG_LOCKED : 0), &ctx->fq))
+ goto err;
+ rxinit = 1;
+ /* Input FQ */
+ if (!(flags & PME_CTX_FLAG_DIRECT)) {
+ ctx->hw_flow = pme_hw_flow_new();
+ if (!ctx->hw_flow)
+ goto err;
+ }
+ ret = pme_ctx_reconfigure_tx(ctx, bpid, qosin);
+ if (ret)
+ goto err;
+ /* Output FQ */
+ ret = reconfigure_rx(ctx, 0, qosout, dest, stashing);
+ if (ret) {
+ /* Need to OOS the FQ before it gets free'd */
+ ret = qman_oos_fq(&ctx->us_data->fqin);
+ BUG_ON(ret);
+ goto err;
+ }
+ return 0;
+err:
+ if (ctx->hw_flow)
+ pme_hw_flow_free(ctx->hw_flow);
+ if (ctx->us_data) {
+ if (fqin_inited)
+ qman_destroy_fq(&ctx->us_data->fqin, 0);
+ kfree(ctx->us_data);
+ }
+ if (rxinit)
+ qman_destroy_fq(&ctx->fq, 0);
+ return ret;
+}
+EXPORT_SYMBOL(pme_ctx_init);
+
+/*
+ * NB, we don't lock here because there must be no other callers (even if we
+ * locked, what does the loser do after we win?)
+ */
+void pme_ctx_finish(struct pme_ctx *ctx)
+{
+ u32 flags;
+ int ret;
+
+ ret = do_flags(ctx, PME_CTX_FLAG_DISABLED, PME_CTX_FLAG_RECONFIG, 0, 0);
+ BUG_ON(ret);
+ /*
+ * Rx/Tx are empty (coz ctx is disabled) so retirement should be
+ * immediate
+ */
+ ret = qman_retire_fq(&ctx->us_data->fqin, &flags);
+ BUG_ON(ret);
+ BUG_ON(flags & QMAN_FQ_STATE_BLOCKOOS);
+ ret = qman_retire_fq(&ctx->fq, &flags);
+ BUG_ON(ret);
+ BUG_ON(flags & QMAN_FQ_STATE_BLOCKOOS);
+ /* OOS and free (don't kfree fq, it's a static ctx member) */
+ ret = qman_oos_fq(&ctx->us_data->fqin);
+ BUG_ON(ret);
+ ret = qman_oos_fq(&ctx->fq);
+ BUG_ON(ret);
+ qman_destroy_fq(&ctx->us_data->fqin, 0);
+ qman_destroy_fq(&ctx->fq, 0);
+ kfree(ctx->us_data);
+ if (ctx->hw_flow)
+ pme_hw_flow_free(ctx->hw_flow);
+ if (ctx->hw_residue)
+ pme_hw_residue_free(ctx->hw_residue);
+}
+EXPORT_SYMBOL(pme_ctx_finish);
+
+int pme_ctx_is_disabled(struct pme_ctx *ctx)
+{
+ return ctx->flags & PME_CTX_FLAG_DISABLED;
+}
+EXPORT_SYMBOL(pme_ctx_is_disabled);
+
+int pme_ctx_is_dead(struct pme_ctx *ctx)
+{
+ return ctx->flags & PME_CTX_FLAG_DEAD;
+}
+EXPORT_SYMBOL(pme_ctx_is_dead);
+
+/*
+ * predeclare this here because pme_ctx_disable() may invoke it in "privileged
+ * mode". The code is down with the other ctrl commands, where it belongs.
+ */
+static inline int __update_flow(struct pme_ctx *ctx, u32 flags,
+ struct pme_flow *params, struct pme_ctx_ctrl_token *token,
+ int is_disabling);
+
+/*
+ * This gets invoked by pme_ctx_disable() if it runs to completion, otherwise
+ * it's called from cb_helper.
+ */
+static inline void __disable_done(struct pme_ctx *ctx)
+{
+ struct qm_mcc_initfq initfq;
+ int ret = 0;
+ if (!(ctx->flags & PME_CTX_FLAG_EXCLUSIVE)) {
+ /* Park fqin (exclusive is always parked) */
+ ret = park(&ctx->us_data->fqin, &initfq);
+ /*
+ * All the conditions for park() to succeed should be met. If
+ * this fails, there's a bug (s/w or h/w).
+ */
+ if (ret)
+ pr_crit("pme2: park() should never fail! (%d)\n", ret);
+ }
+ do_flags(ctx, 0, 0, PME_CTX_FLAG_DISABLED, 0);
+}
+
+int pme_ctx_disable(struct pme_ctx *ctx, u32 flags,
+ struct pme_ctx_ctrl_token *token)
+{
+ int ret;
+
+ /* We must not (already) be DISABLING */
+ ret = do_flags(ctx, 0, PME_CTX_FLAG_DISABLING,
+ PME_CTX_FLAG_DISABLING, 0);
+ if (ret)
+ return ret;
+ /* Make sure the pipeline is empty */
+ atomic_dec(&ctx->refs);
+ ret = empty_pipeline(ctx, flags);
+ if (ret)
+ goto err;
+ /*
+ * We're idle, but is the flow context flushed from PME onboard cache?
+ * If it's not flushed when the system deallocates it, that 32 bytes
+ * could be in use later when PME decides to flush a write to it. Need
+ * to make it coherent again...
+ */
+ if (!(ctx->flags & PME_CTX_FLAG_DIRECT)) {
+ /*
+ * Pass on wait flags (if any) but cancel any flow-context field
+ * writes (this is not the pme_ctx_ctrl_update_flow() API).
+ */
+ ret = __update_flow(ctx, flags & ~PME_CMD_FCW_ALL, NULL,
+ token, 1);
+ if (ret)
+ goto err;
+ return 1;
+ }
+ __disable_done(ctx);
+ return 0;
+err:
+ atomic_inc(&ctx->refs);
+ do_flags(ctx, 0, 0, 0, PME_CTX_FLAG_DISABLING);
+ wake_up(&ctx->queue);
+ return ret;
+}
+EXPORT_SYMBOL(pme_ctx_disable);
+
+int pme_ctx_enable(struct pme_ctx *ctx)
+{
+ int ret;
+ ret = do_flags(ctx, PME_CTX_FLAG_DISABLED,
+ PME_CTX_FLAG_DEAD | PME_CTX_FLAG_RECONFIG |
+ PME_CTX_FLAG_ENABLING,
+ PME_CTX_FLAG_ENABLING, 0);
+ if (ret)
+ return ret;
+ if (!(ctx->flags & PME_CTX_FLAG_EXCLUSIVE)) {
+ ret = qman_init_fq(&ctx->us_data->fqin,
+ QMAN_INITFQ_FLAG_SCHED, NULL);
+ if (ret) {
+ do_flags(ctx, 0, 0, 0, PME_CTX_FLAG_ENABLING);
+ return ret;
+ }
+ }
+ atomic_inc(&ctx->refs);
+ do_flags(ctx, 0, 0, 0, PME_CTX_FLAG_DISABLED | PME_CTX_FLAG_DISABLING |
+ PME_CTX_FLAG_ENABLING);
+ return 0;
+}
+EXPORT_SYMBOL(pme_ctx_enable);
+
+int pme_ctx_reconfigure_tx(struct pme_ctx *ctx, u32 bpid, u8 qosin)
+{
+ struct qm_mcc_initfq initfq;
+ int ret;
+
+ ret = do_flags(ctx, PME_CTX_FLAG_DISABLED,
+ PME_CTX_FLAG_DEAD | PME_CTX_FLAG_RECONFIG,
+ PME_CTX_FLAG_RECONFIG, 0);
+ if (ret)
+ return ret;
+ memset(&initfq, 0, sizeof(initfq));
+ pme_initfq(&initfq, ctx->hw_flow, qosin, bpid, qman_fq_fqid(&ctx->fq));
+ ret = qman_init_fq(&ctx->us_data->fqin, 0, &initfq);
+ do_flags(ctx, 0, 0, 0, PME_CTX_FLAG_RECONFIG);
+ return ret;
+}
+EXPORT_SYMBOL(pme_ctx_reconfigure_tx);
+
+int pme_ctx_reconfigure_rx(struct pme_ctx *ctx, u8 qosout,
+ u16 dest, const struct qm_fqd_stashing *stashing)
+{
+ return reconfigure_rx(ctx, 1, qosout, dest, stashing);
+}
+EXPORT_SYMBOL(pme_ctx_reconfigure_rx);
+
+/*
+ * Helpers for 'ctrl' and 'work' APIs. These are used when the 'ctx' in question
+ * is EXCLUSIVE.
+ */
+static inline void release_exclusive(__maybe_unused struct pme_ctx *ctx)
+{
+ unsigned long irqflags;
+
+ BUG_ON(exclusive_ctx != ctx);
+ BUG_ON(!exclusive_refs);
+ spin_lock_irqsave(&exclusive_lock, irqflags);
+ if (!(--exclusive_refs)) {
+ exclusive_ctx = NULL;
+ pme2_exclusive_unset();
+ wake_up(&exclusive_queue);
+ }
+ spin_unlock_irqrestore(&exclusive_lock, irqflags);
+}
+static int __try_exclusive(struct pme_ctx *ctx)
+{
+ int ret = 0;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&exclusive_lock, irqflags);
+ if (exclusive_refs) {
+ /* exclusivity already held, continue if we're the owner */
+ if (exclusive_ctx != ctx)
+ ret = -EBUSY;
+ } else {
+ /* it's not currently held */
+ ret = pme2_exclusive_set(&ctx->us_data->fqin);
+ if (!ret)
+ exclusive_ctx = ctx;
+ }
+ if (!ret)
+ exclusive_refs++;
+ spin_unlock_irqrestore(&exclusive_lock, irqflags);
+ return ret;
+}
+/*
+ * Use this macro as the wait expression because we don't want to continue
+ * looping if the reason we're failing is that we don't have CCSR access
+ * (-ENODEV).
+ */
+#define try_exclusive(ret, ctx) \
+ (!(ret = __try_exclusive(ctx)) || (ret == -ENODEV))
+static inline int get_exclusive(struct pme_ctx *ctx, __maybe_unused u32 flags)
+{
+ int ret;
+#ifdef CONFIG_FSL_DPA_CAN_WAIT
+ if (flags & PME_CTX_OP_WAIT) {
+ if (flags & PME_CTX_OP_WAIT_INT) {
+ ret = -EINTR;
+ wait_event_interruptible(exclusive_queue,
+ try_exclusive(ret, ctx));
+ } else {
+ wait_event(exclusive_queue,
+ try_exclusive(ret, ctx));
+ }
+ } else
+#endif
+ {
+ ret = __try_exclusive(ctx);
+ }
+ return ret;
+}
+
+/*
+ * Used for 'work' APIs, convert PME->QMAN wait flags. The PME and
+ * QMAN "wait" flags have been aligned so that the below conversion should
+ * compile with good straight-line speed.
+ */
+static inline u32 ctrl2eq(u32 flags)
+{
+#ifdef CONFIG_FSL_DPA_CAN_WAIT
+ return flags & (QMAN_ENQUEUE_FLAG_WAIT | QMAN_ENQUEUE_FLAG_WAIT_INT);
+#else
+ return flags;
+#endif
+}
+
+static inline void release_work(struct pme_ctx *ctx)
+{
+ if (atomic_dec_and_test(&ctx->refs))
+ wake_up(&ctx->queue);
+}
+
+#define BLOCK_NORMAL_WORK (PME_CTX_FLAG_DEAD | PME_CTX_FLAG_DISABLING)
+static int try_work(struct pme_ctx *ctx, u32 flags)
+{
+ atomic_inc(&ctx->refs);
+ if (unlikely(!(flags & PME_CTX_OP_INSIDE_DISABLE) &&
+ (ctx->flags & BLOCK_NORMAL_WORK))) {
+ release_work(ctx);
+ return -EIO;
+ }
+ return 0;
+}
+
+static int get_work(struct pme_ctx *ctx, u32 flags)
+{
+ int ret = 0;
+#ifdef CONFIG_FSL_DPA_CAN_WAIT
+ if (flags & PME_CTX_OP_WAIT) {
+ if (flags & PME_CTX_OP_WAIT_INT) {
+ ret = -EINTR;
+ wait_event_interruptible(ctx->queue,
+ !(ret = try_work(ctx, flags)));
+ } else {
+ wait_event(ctx->queue, !try_work(ctx, flags));
+ }
+ } else
+#endif
+ {
+ ret = try_work(ctx, flags);
+ }
+ return ret;
+}
+
+static inline int do_work(struct pme_ctx *ctx, u32 flags, struct qm_fd *fd,
+ struct pme_ctx_token *token, struct qman_fq *orp_fq, u16 seqnum)
+{
+ unsigned long irqflags;
+ int ret = get_work(ctx, flags);
+ if (ret)
+ return ret;
+ if (ctx->flags & PME_CTX_FLAG_EXCLUSIVE) {
+ ret = get_exclusive(ctx, flags);
+ if (ret) {
+ release_work(ctx);
+ return ret;
+ }
+ }
+ BUG_ON(sizeof(*fd) != sizeof(token->blob));
+ memcpy(&token->blob, fd, sizeof(*fd));
+
+ spin_lock_irqsave(&ctx->lock, irqflags);
+ list_add_tail(&token->node, &ctx->tokens);
+ spin_unlock_irqrestore(&ctx->lock, irqflags);
+
+ if (!orp_fq)
+ ret = qman_enqueue(&ctx->us_data->fqin, fd, ctrl2eq(flags));
+ else
+ ret = qman_enqueue_orp(&ctx->us_data->fqin, fd, ctrl2eq(flags),
+ orp_fq, seqnum);
+ if (ret) {
+ spin_lock_irqsave(&ctx->lock, irqflags);
+ list_del(&token->node);
+ spin_unlock_irqrestore(&ctx->lock, irqflags);
+ if (ctx->flags & PME_CTX_FLAG_EXCLUSIVE)
+ release_exclusive(ctx);
+ release_work(ctx);
+ }
+ return ret;
+}
+
+static inline int __update_flow(struct pme_ctx *ctx, u32 flags,
+ struct pme_flow *params, struct pme_ctx_ctrl_token *token,
+ int is_disabling)
+{
+ struct qm_fd fd;
+ int ret;
+ int hw_res_used = 0;
+ struct pme_hw_residue *hw_res = pme_hw_residue_new();
+ unsigned long irqflags;
+
+ BUG_ON(ctx->flags & PME_CTX_FLAG_DIRECT);
+ if (!hw_res)
+ return -ENOMEM;
+ token->internal_flow_ptr = pme_hw_flow_new();
+ if (!token->internal_flow_ptr) {
+ pme_hw_residue_free(hw_res);
+ return -ENOMEM;
+ }
+ token->base_token.cmd_type = pme_cmd_flow_write;
+
+ flags &= ~PME_CTX_OP_PRIVATE;
+ /* The callback will want to know this */
+ token->base_token.is_disable_flush = is_disabling ? 1 : 0;
+ flags |= (is_disabling ? PME_CTX_OP_INSIDE_DISABLE : 0);
+ spin_lock_irqsave(&ctx->lock, irqflags);
+ if (flags & PME_CTX_OP_RESETRESLEN) {
+ if (ctx->hw_residue) {
+ params->ren = 1;
+ flags |= PME_CMD_FCW_RES;
+ } else {
+ flags &= ~PME_CMD_FCW_RES;
+ }
+ }
+ /* allocate residue memory if it is being added */
+ if ((flags & PME_CMD_FCW_RES) && params->ren && !ctx->hw_residue) {
+ ctx->hw_residue = hw_res;
+ hw_res_used = 1;
+ }
+ spin_unlock_irqrestore(&ctx->lock, irqflags);
+ if (!hw_res_used)
+ pme_hw_residue_free(hw_res);
+ /* enqueue the FCW command to PME */
+ memset(&fd, 0, sizeof(fd));
+ if (params)
+ memcpy(token->internal_flow_ptr, params,
+ sizeof(struct pme_flow));
+ pme_fd_cmd_fcw(&fd, flags & PME_CMD_FCW_ALL,
+ (struct pme_flow *)token->internal_flow_ptr,
+ ctx->hw_residue);
+ ret = do_work(ctx, flags, &fd, &token->base_token, NULL, 0);
+ return ret;
+}
+
+int pme_ctx_ctrl_update_flow(struct pme_ctx *ctx, u32 flags,
+ struct pme_flow *params, struct pme_ctx_ctrl_token *token)
+{
+ return __update_flow(ctx, flags, params, token, 0);
+}
+EXPORT_SYMBOL(pme_ctx_ctrl_update_flow);
+
+int pme_ctx_ctrl_read_flow(struct pme_ctx *ctx, u32 flags,
+ struct pme_flow *params, struct pme_ctx_ctrl_token *token)
+{
+ struct qm_fd fd;
+
+ BUG_ON(ctx->flags & (PME_CTX_FLAG_DIRECT | PME_CTX_FLAG_PMTCC));
+ token->base_token.cmd_type = pme_cmd_flow_read;
+ /* enqueue the FCR command to PME */
+ token->usr_flow_ptr = params;
+ token->internal_flow_ptr = pme_hw_flow_new();
+ if (!token->internal_flow_ptr)
+ return -ENOMEM;
+ memset(&fd, 0, sizeof(fd));
+ pme_fd_cmd_fcr(&fd, (struct pme_flow *)token->internal_flow_ptr);
+ return do_work(ctx, flags, &fd, &token->base_token, NULL, 0);
+}
+EXPORT_SYMBOL(pme_ctx_ctrl_read_flow);
+
+int pme_ctx_ctrl_nop(struct pme_ctx *ctx, u32 flags,
+ struct pme_ctx_ctrl_token *token)
+{
+ struct qm_fd fd;
+
+ token->base_token.cmd_type = pme_cmd_nop;
+ /* enqueue the NOP command to PME */
+ memset(&fd, 0, sizeof(fd));
+ qm_fd_addr_set64(&fd, (unsigned long)token);
+ pme_fd_cmd_nop(&fd);
+ return do_work(ctx, flags, &fd, &token->base_token, NULL, 0);
+}
+EXPORT_SYMBOL(pme_ctx_ctrl_nop);
+
+static inline int __prep_scan(__maybe_unused struct pme_ctx *ctx,
+ struct qm_fd *fd, u32 args, struct pme_ctx_token *token)
+{
+ BUG_ON(ctx->flags & PME_CTX_FLAG_PMTCC);
+ token->cmd_type = pme_cmd_scan;
+ pme_fd_cmd_scan(fd, args);
+#ifdef CONFIG_FSL_PME_BUG_4K_SCAN_REV_2_1_4
+ if (ctx->max_scan_size) {
+ if (fd->format == qm_fd_contig || fd->format == qm_fd_sg) {
+ if (fd->length20 > ctx->max_scan_size)
+ return -EINVAL;
+ } else if (fd->format == qm_fd_contig_big ||
+ fd->format == qm_fd_sg_big) {
+ if (fd->length29 > ctx->max_scan_size)
+ return -EINVAL;
+ }
+ }
+#endif
+ return 0;
+}
+
+int pme_ctx_scan(struct pme_ctx *ctx, u32 flags, struct qm_fd *fd, u32 args,
+ struct pme_ctx_token *token)
+{
+ int ret;
+
+ ret = __prep_scan(ctx, fd, args, token);
+ if (ret)
+ return ret;
+ return do_work(ctx, flags, fd, token, NULL, 0);
+}
+EXPORT_SYMBOL(pme_ctx_scan);
+
+int pme_ctx_scan_orp(struct pme_ctx *ctx, u32 flags, struct qm_fd *fd, u32 args,
+ struct pme_ctx_token *token, struct qman_fq *orp_fq, u16 seqnum)
+{
+ __prep_scan(ctx, fd, args, token);
+ return do_work(ctx, flags, fd, token, orp_fq, seqnum);
+}
+EXPORT_SYMBOL(pme_ctx_scan_orp);
+
+int pme_ctx_pmtcc(struct pme_ctx *ctx, u32 flags, struct qm_fd *fd,
+ struct pme_ctx_token *token)
+{
+ BUG_ON(!(ctx->flags & PME_CTX_FLAG_PMTCC));
+ token->cmd_type = pme_cmd_pmtcc;
+ pme_fd_cmd_pmtcc(fd);
+ return do_work(ctx, flags, fd, token, NULL, 0);
+}
+EXPORT_SYMBOL(pme_ctx_pmtcc);
+
+int pme_ctx_exclusive_inc(struct pme_ctx *ctx, u32 flags)
+{
+ return get_exclusive(ctx, flags);
+}
+EXPORT_SYMBOL(pme_ctx_exclusive_inc);
+
+void pme_ctx_exclusive_dec(struct pme_ctx *ctx)
+{
+ release_exclusive(ctx);
+}
+EXPORT_SYMBOL(pme_ctx_exclusive_dec);
+
+/*
+ * The 99.99% case is that enqueues happen in order or they get order-restored
+ * by the ORP, and so dequeues of responses happen in order too, so our FIFO
+ * linked-list of tokens is append-on-enqueue and pop-on-dequeue, and all's
+ * well.
+ *
+ * *EXCEPT*, if ever an enqueue gets rejected ... what then happens is that we
+ * have dequeues and ERNs to deal with, and the order we see them in is not
+ * necessarily the linked-list order. So we need to handle this in DQRR and MR
+ * callbacks, without sacrificing fast-path performance. Ouch.
+ *
+ * We use pop_matching_token() to take care of the mess (inlined, of course).
+ */
+#define MATCH(fd1, fd2) \
+ ((qm_fd_addr_get64(fd1) == qm_fd_addr_get64(fd2)) && \
+ ((fd1)->opaque == (fd2)->opaque))
+static inline struct pme_ctx_token *pop_matching_token(struct pme_ctx *ctx,
+ const struct qm_fd *fd)
+{
+ struct pme_ctx_token *token;
+ const struct qm_fd *t_fd;
+ unsigned long irqflags;
+
+ /*
+ * The fast-path case is that the for() loop actually degenerates into;
+ * token = list_first_entry();
+ * if (likely(MATCH()))
+ * [done]
+ * The penalty of the slow-path case is the for() loop plus the fact
+ * we're optimising for a "likely" match first time, which might hurt
+ * when that assumption is wrong a few times in succession.
+ */
+ spin_lock_irqsave(&ctx->lock, irqflags);
+ list_for_each_entry(token, &ctx->tokens, node) {
+ t_fd = (const struct qm_fd *)&token->blob[0];
+ if (likely(MATCH(t_fd, fd))) {
+ list_del(&token->node);
+ goto found;
+ }
+ }
+ token = NULL;
+ pr_err("PME2 Could not find matching token!\n");
+ BUG();
+found:
+ spin_unlock_irqrestore(&ctx->lock, irqflags);
+ return token;
+}
+
+static inline void cb_helper(__always_unused struct qman_portal *portal,
+ struct pme_ctx *ctx, const struct qm_fd *fd, int error)
+{
+ struct pme_ctx_token *token;
+ struct pme_ctx_ctrl_token *ctrl_token;
+
+ /*
+ * Resist the urge to use "unlikely" - 'error' is a constant param to an
+ * inline fn, so the compiler can collapse this completely.
+ */
+ if (error)
+ do_flags(ctx, 0, 0, PME_CTX_FLAG_DEAD, 0);
+ token = pop_matching_token(ctx, fd);
+ if (likely(token->cmd_type == pme_cmd_scan)) {
+ ctx->cb(ctx, fd, token);
+ } else if (token->cmd_type == pme_cmd_pmtcc) {
+ ctx->cb(ctx, fd, token);
+ } else {
+ /* outcast ctx and call supplied callback */
+ ctrl_token = container_of(token, struct pme_ctx_ctrl_token,
+ base_token);
+ if (token->cmd_type == pme_cmd_flow_write) {
+ /* Release the allocated flow context */
+ pme_hw_flow_free(ctrl_token->internal_flow_ptr);
+ /* Is this pme_ctx_disable() completion? */
+ if (token->is_disable_flush)
+ __disable_done(ctx);
+ } else if (token->cmd_type == pme_cmd_flow_read) {
+ /* Copy read result */
+ memcpy(ctrl_token->usr_flow_ptr,
+ ctrl_token->internal_flow_ptr,
+ sizeof(struct pme_flow));
+ /* Release the allocated flow context */
+ pme_hw_flow_free(ctrl_token->internal_flow_ptr);
+ }
+ ctrl_token->cb(ctx, fd, ctrl_token);
+ }
+ /* Consume the frame */
+ if (ctx->flags & PME_CTX_FLAG_EXCLUSIVE)
+ release_exclusive(ctx);
+ if (atomic_dec_and_test(&ctx->refs))
+ wake_up(&ctx->queue);
+}
+
+/*
+ * TODO: this scheme does not allow PME receivers to use held-active at all. Eg.
+ * there's no configuration of held-active for 'fq', and if there was, there's
+ * (a) nothing in the cb_dqrr() to support "park" or "defer" logic, and (b)
+ * nothing in cb_fqs() to support a delayed FQPN (DCAP_PK) notification.
+ */
+static enum qman_cb_dqrr_result cb_dqrr(struct qman_portal *portal,
+ struct qman_fq *fq, const struct qm_dqrr_entry *dq)
+{
+ u8 status = (u8)pme_fd_res_status(&dq->fd);
+ u8 flags = pme_fd_res_flags(&dq->fd);
+ struct pme_ctx *ctx = (struct pme_ctx *)fq;
+
+ /*
+ * Put context into dead state is an unreliable or serious error is
+ * received
+ */
+ if (unlikely(flags & PME_STATUS_UNRELIABLE))
+ cb_helper(portal, ctx, &dq->fd, 1);
+ else if (unlikely((serious_error_vec[status])))
+ cb_helper(portal, ctx, &dq->fd, 1);
+ else
+ cb_helper(portal, ctx, &dq->fd, 0);
+
+ return qman_cb_dqrr_consume;
+}
+
+static void cb_ern(__always_unused struct qman_portal *portal,
+ struct qman_fq *fq, const struct qm_mr_entry *mr)
+{
+ struct pme_ctx *ctx;
+ struct pme_nostash *data;
+ struct pme_ctx_token *token;
+
+ data = container_of(fq, struct pme_nostash, fqin);
+ ctx = data->parent;
+
+ token = pop_matching_token(ctx, &mr->ern.fd);
+ if (likely(token->cmd_type == pme_cmd_scan)) {
+ BUG_ON(!ctx->ern_cb);
+ ctx->ern_cb(ctx, mr, token);
+ } else if (token->cmd_type == pme_cmd_pmtcc) {
+ BUG_ON(!ctx->ern_cb);
+ ctx->ern_cb(ctx, mr, token);
+ } else {
+ struct pme_ctx_ctrl_token *ctrl_token;
+ /* outcast ctx and call supplied callback */
+ ctrl_token = container_of(token, struct pme_ctx_ctrl_token,
+ base_token);
+ if (token->cmd_type == pme_cmd_flow_write) {
+ /* Release the allocated flow context */
+ pme_hw_flow_free(ctrl_token->internal_flow_ptr);
+ } else if (token->cmd_type == pme_cmd_flow_read) {
+ /* Copy read result */
+ memcpy(ctrl_token->usr_flow_ptr,
+ ctrl_token->internal_flow_ptr,
+ sizeof(struct pme_flow));
+ /* Release the allocated flow context */
+ pme_hw_flow_free(ctrl_token->internal_flow_ptr);
+ }
+ BUG_ON(!ctrl_token->ern_cb);
+ ctrl_token->ern_cb(ctx, mr, ctrl_token);
+ }
+ /* Consume the frame */
+ if (ctx->flags & PME_CTX_FLAG_EXCLUSIVE)
+ release_exclusive(ctx);
+ if (atomic_dec_and_test(&ctx->refs))
+ wake_up(&ctx->queue);
+}
+
+static void cb_fqs(__always_unused struct qman_portal *portal,
+ __always_unused struct qman_fq *fq,
+ const struct qm_mr_entry *mr)
+{
+ u8 verb = mr->verb & QM_MR_VERB_TYPE_MASK;
+ if (verb == QM_MR_VERB_FQRNI)
+ return;
+ /* nothing else is supposed to occur */
+ BUG();
+}
diff --git a/drivers/staging/fsl_pme2/pme2_low.c b/drivers/staging/fsl_pme2/pme2_low.c
new file mode 100644
index 0000000..fdbdc7c
--- /dev/null
+++ b/drivers/staging/fsl_pme2/pme2_low.c
@@ -0,0 +1,277 @@
+/* Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "pme2_private.h"
+
+MODULE_AUTHOR("Geoff Thorpe");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("FSL PME2 (p4080) device usage");
+
+#define PME_RESIDUE_SIZE 128
+#define PME_RESIDUE_ALIGN 64
+#define PME_FLOW_SIZE sizeof(struct pme_flow)
+#define PME_FLOW_ALIGN 32
+static struct kmem_cache *slab_residue;
+static struct kmem_cache *slab_flow;
+static struct kmem_cache *slab_fq;
+
+/*
+ * Hack to support "pme_map()". The point of this is that dma_map_single() now
+ * requires a non-NULL device, so the idea is that address mapping must be
+ * device-sensitive. Now the PAMU IO-MMU already takes care of this, as can be
+ * seen by the device-tree structure generated by the hypervisor (each portal
+ * node has sub-nodes for each h/w end-point it provides access to, and each
+ * sub-node has its own LIODN configuration). So we just need to map cpu
+ * pointers to (guest-)physical address and the PAMU takes care of the rest, so
+ * this doesn't need to be portal-sensitive nor device-sensitive.
+ */
+static struct platform_device *pdev;
+
+static int pme2_low_init(void)
+{
+ int ret = -ENOMEM;
+
+ slab_residue = kmem_cache_create("pme2_residue", PME_RESIDUE_SIZE,
+ PME_RESIDUE_ALIGN, SLAB_HWCACHE_ALIGN, NULL);
+ if (!slab_residue)
+ goto end;
+ slab_flow = kmem_cache_create("pme2_flow", PME_FLOW_SIZE,
+ PME_FLOW_ALIGN, 0, NULL);
+ if (!slab_flow)
+ goto end;
+ slab_fq = kmem_cache_create("pme2_fqslab", sizeof(struct qman_fq),
+ __alignof__(struct qman_fq), SLAB_HWCACHE_ALIGN, NULL);
+ if (!slab_fq)
+ goto end;
+ ret = -ENODEV;
+ pdev = platform_device_alloc("pme", -1);
+ if (!pdev)
+ goto end;
+ if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(40)))
+ goto end;
+ if (platform_device_add(pdev))
+ goto end;
+ return 0;
+end:
+ if (pdev) {
+ platform_device_put(pdev);
+ pdev = NULL;
+ }
+ if (slab_flow) {
+ kmem_cache_destroy(slab_flow);
+ slab_flow = NULL;
+ }
+ if (slab_residue) {
+ kmem_cache_destroy(slab_residue);
+ slab_residue = NULL;
+ }
+ if (slab_fq) {
+ kmem_cache_destroy(slab_fq);
+ slab_fq = NULL;
+ }
+ return ret;
+}
+
+static void pme2_low_exit(void)
+{
+ platform_device_del(pdev);
+ platform_device_put(pdev);
+ pdev = NULL;
+ kmem_cache_destroy(slab_fq);
+ kmem_cache_destroy(slab_flow);
+ kmem_cache_destroy(slab_residue);
+ slab_fq = slab_flow = slab_residue = NULL;
+}
+
+module_init(pme2_low_init);
+module_exit(pme2_low_exit);
+
+struct qman_fq *slabfq_alloc(void)
+{
+ return kmem_cache_alloc(slab_fq, GFP_KERNEL);
+}
+
+void slabfq_free(struct qman_fq *fq)
+{
+ kmem_cache_free(slab_fq, fq);
+}
+
+/***********************/
+/* low-level functions */
+/***********************/
+
+struct pme_hw_residue *pme_hw_residue_new(void)
+{
+ return kmem_cache_alloc(slab_residue, GFP_KERNEL);
+}
+EXPORT_SYMBOL(pme_hw_residue_new);
+
+void pme_hw_residue_free(struct pme_hw_residue *p)
+{
+ kmem_cache_free(slab_residue, p);
+}
+EXPORT_SYMBOL(pme_hw_residue_free);
+
+struct pme_hw_flow *pme_hw_flow_new(void)
+{
+ struct pme_flow *flow = kmem_cache_zalloc(slab_flow, GFP_KERNEL);
+ return (struct pme_hw_flow *)flow;
+}
+EXPORT_SYMBOL(pme_hw_flow_new);
+
+void pme_hw_flow_free(struct pme_hw_flow *p)
+{
+ kmem_cache_free(slab_flow, p);
+}
+EXPORT_SYMBOL(pme_hw_flow_free);
+
+static const struct pme_flow default_sw_flow = {
+ .sos = 1,
+ .srvm = 0,
+ .esee = 1,
+ .ren = 0,
+ .rlen = 0,
+ .seqnum_hi = 0,
+ .seqnum_lo = 0,
+ .sessionid = 0x7ffffff,
+ .rptr_hi = 0,
+ .rptr_lo = 0,
+ .clim = 0xffff,
+ .mlim = 0xffff
+};
+
+void pme_sw_flow_init(struct pme_flow *flow)
+{
+ memcpy(flow, &default_sw_flow, sizeof(*flow));
+}
+EXPORT_SYMBOL(pme_sw_flow_init);
+
+void pme_initfq(struct qm_mcc_initfq *initfq, struct pme_hw_flow *flow, u8 qos,
+ u8 rbpid, u32 rfqid)
+{
+ struct pme_context_a *pme_a =
+ (struct pme_context_a *)&initfq->fqd.context_a;
+ struct pme_context_b *pme_b =
+ (struct pme_context_b *)&initfq->fqd.context_b;
+
+ initfq->we_mask = QM_INITFQ_WE_DESTWQ | QM_INITFQ_WE_CONTEXTA |
+ QM_INITFQ_WE_CONTEXTB;
+ initfq->fqd.dest.channel = qm_channel_pme;
+ initfq->fqd.dest.wq = qos;
+ if (flow) {
+ dma_addr_t fcp = flow_map((struct pme_flow *)flow);
+ pme_a->mode = pme_mode_flow;
+ pme_context_a_set64(pme_a, fcp);
+ } else {
+ pme_a->mode = pme_mode_direct;
+ pme_context_a_set64(pme_a, 0);
+ }
+ pme_b->rbpid = rbpid;
+ pme_b->rfqid = rfqid;
+}
+EXPORT_SYMBOL(pme_initfq);
+
+void pme_fd_cmd_nop(struct qm_fd *fd)
+{
+ struct pme_cmd_nop *nop = (struct pme_cmd_nop *)&fd->cmd;
+ nop->cmd = pme_cmd_nop;
+}
+EXPORT_SYMBOL(pme_fd_cmd_nop);
+
+void pme_fd_cmd_fcw(struct qm_fd *fd, u8 flags, struct pme_flow *flow,
+ struct pme_hw_residue *residue)
+{
+ dma_addr_t f;
+ struct pme_cmd_flow_write *fcw = (struct pme_cmd_flow_write *)&fd->cmd;
+
+ BUG_ON(!flow);
+ BUG_ON((unsigned long)flow & 31);
+ fcw->cmd = pme_cmd_flow_write;
+ fcw->flags = flags;
+ if (flags & PME_CMD_FCW_RES) {
+ if (residue) {
+ dma_addr_t rptr = residue_map(residue);
+ BUG_ON(!residue);
+ BUG_ON((unsigned long)residue & 63);
+ pme_flow_rptr_set64(flow, rptr);
+ } else
+ pme_flow_rptr_set64(flow, 0);
+ }
+ f = flow_map(flow);
+ qm_fd_addr_set64(fd, f);
+ fd->format = qm_fd_contig;
+ fd->offset = 0;
+ fd->length20 = sizeof(*flow);
+}
+EXPORT_SYMBOL(pme_fd_cmd_fcw);
+
+void pme_fd_cmd_fcr(struct qm_fd *fd, struct pme_flow *flow)
+{
+ dma_addr_t f;
+ struct pme_cmd_flow_read *fcr = (struct pme_cmd_flow_read *)&fd->cmd;
+
+ BUG_ON(!flow);
+ BUG_ON((unsigned long)flow & 31);
+ fcr->cmd = pme_cmd_flow_read;
+ f = flow_map(flow);
+ qm_fd_addr_set64(fd, f);
+ fd->format = qm_fd_contig;
+ fd->offset = 0;
+ fd->length20 = sizeof(*flow);
+}
+EXPORT_SYMBOL(pme_fd_cmd_fcr);
+
+void pme_fd_cmd_pmtcc(struct qm_fd *fd)
+{
+ struct pme_cmd_pmtcc *pmtcc = (struct pme_cmd_pmtcc *)&fd->cmd;
+ pmtcc->cmd = pme_cmd_pmtcc;
+}
+EXPORT_SYMBOL(pme_fd_cmd_pmtcc);
+
+void pme_fd_cmd_scan(struct qm_fd *fd, u32 args)
+{
+ struct pme_cmd_scan *scan = (struct pme_cmd_scan *)&fd->cmd;
+ fd->cmd = args;
+ scan->cmd = pme_cmd_scan;
+}
+EXPORT_SYMBOL(pme_fd_cmd_scan);
+
+dma_addr_t pme_map(void *ptr)
+{
+ return dma_map_single(&pdev->dev, ptr, 1, DMA_BIDIRECTIONAL);
+}
+EXPORT_SYMBOL(pme_map);
+
+int pme_map_error(dma_addr_t dma_addr)
+{
+ return dma_mapping_error(&pdev->dev, dma_addr);
+}
+EXPORT_SYMBOL(pme_map_error);
diff --git a/drivers/staging/fsl_pme2/pme2_private.h b/drivers/staging/fsl_pme2/pme2_private.h
new file mode 100644
index 0000000..3968f02
--- /dev/null
+++ b/drivers/staging/fsl_pme2/pme2_private.h
@@ -0,0 +1,217 @@
+/* Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "pme2_sys.h"
+#include <linux/fsl_pme.h>
+
+#undef PME2_DEBUG
+
+#ifdef PME2_DEBUG
+#define PMEPRINFO(fmt, args...) pr_info("PME2: %s: " fmt, __func__, ## args)
+#else
+#define PMEPRINFO(fmt, args...)
+#endif
+
+#define PMEPRERR(fmt, args...) pr_err("PME2: %s: " fmt, __func__, ## args)
+#define PMEPRCRIT(fmt, args...) pr_crit("PME2: %s: " fmt, __func__, ## args)
+
+#ifdef CONFIG_FSL_PME2_CTRL
+/* Hooks */
+int pme2_create_sysfs_dev_files(struct platform_device *ofdev);
+void pme2_remove_sysfs_dev_files(struct platform_device *ofdev);
+void accumulator_update_interval(u32 interval);
+#endif
+
+static inline void set_fd_addr(struct qm_fd *fd, dma_addr_t addr)
+{
+ qm_fd_addr_set64(fd, addr);
+}
+static inline dma_addr_t get_fd_addr(const struct qm_fd *fd)
+{
+ return (dma_addr_t)qm_fd_addr_get64(fd);
+}
+static inline void set_sg_addr(struct qm_sg_entry *sg, dma_addr_t addr)
+{
+ qm_sg_entry_set64(sg, addr);
+}
+static inline dma_addr_t get_sg_addr(const struct qm_sg_entry *sg)
+{
+ return (dma_addr_t)qm_sg_entry_get64(sg);
+}
+
+/******************/
+/* Datapath types */
+/******************/
+
+enum pme_mode {
+ pme_mode_direct = 0x00,
+ pme_mode_flow = 0x80
+};
+
+struct pme_context_a {
+ enum pme_mode mode:8;
+ u8 __reserved;
+ /* Flow Context pointer (48-bit), ignored if mode==direct */
+ u16 flow_hi;
+ u32 flow_lo;
+} __packed;
+static inline u64 pme_context_a_get64(const struct pme_context_a *p)
+{
+ return ((u64)p->flow_hi << 32) | (u64)p->flow_lo;
+}
+/* Macro, so we compile better if 'v' isn't always 64-bit */
+#define pme_context_a_set64(p, v) \
+ do { \
+ struct pme_context_a *__p931 = (p); \
+ __p931->flow_hi = upper_32_bits(v); \
+ __p931->flow_lo = lower_32_bits(v); \
+ } while (0)
+
+struct pme_context_b {
+ u32 rbpid:8;
+ u32 rfqid:24;
+} __packed;
+
+
+/* This is the 32-bit frame "cmd/status" field, sent to PME */
+union pme_cmd {
+ struct pme_cmd_nop {
+ enum pme_cmd_type cmd:3;
+ } nop;
+ struct pme_cmd_flow_read {
+ enum pme_cmd_type cmd:3;
+ } fcr;
+ struct pme_cmd_flow_write {
+ enum pme_cmd_type cmd:3;
+ u8 __reserved:5;
+ u8 flags; /* See PME_CMD_FCW_*** */
+ } __packed fcw;
+ struct pme_cmd_pmtcc {
+ enum pme_cmd_type cmd:3;
+ } pmtcc;
+ struct pme_cmd_scan {
+ union {
+ struct {
+ enum pme_cmd_type cmd:3;
+ u8 flags:5; /* See PME_CMD_SCAN_*** */
+ } __packed;
+ };
+ u8 set;
+ u16 subset;
+ } __packed scan;
+};
+
+/*
+ * The exported macro forms a "scan_args" u32 from 3 inputs, these private
+ * inlines do the inverse, if you need to crack one apart.
+ */
+static inline u8 scan_args_get_flags(u32 args)
+{
+ return args >> 24;
+}
+static inline u8 scan_args_get_set(u32 args)
+{
+ return (args >> 16) & 0xff;
+}
+static inline u16 scan_args_get_subset(u32 args)
+{
+ return args & 0xffff;
+}
+
+/* Hook from pme2_high to pme2_low */
+struct qman_fq *slabfq_alloc(void);
+void slabfq_free(struct qman_fq *fq);
+
+/* Hook from pme2_high to pme2_ctrl */
+int pme2_have_control(void);
+int pme2_exclusive_set(struct qman_fq *fq);
+int pme2_exclusive_unset(void);
+
+#define DECLARE_GLOBAL(name, t, mt, def, desc) \
+ static t name = def; \
+ module_param(name, mt, 0644); \
+ MODULE_PARM_DESC(name, desc ", default: " __stringify(def));
+
+/* Constants used by the SRE ioctl. */
+#define PME_PMFA_SRE_POLL_MS 100
+#define PME_PMFA_SRE_INDEX_MAX (1 << 27)
+#define PME_PMFA_SRE_INC_MAX (1 << 12)
+#define PME_PMFA_SRE_REP_MAX (1 << 28)
+#define PME_PMFA_SRE_INTERVAL_MAX (1 << 12)
+
+/* Encapsulations for mapping */
+#define flow_map(flow) \
+({ \
+ struct pme_flow *__f913 = (flow); \
+ pme_map(__f913); \
+})
+
+#define residue_map(residue) \
+({ \
+ struct pme_hw_residue *__f913 = (residue); \
+ pme_map(__f913); \
+})
+
+/* 4k minus residue */
+#define PME_MAX_SCAN_SIZE_BUG_2_1_4 (4095 - 127)
+
+#define PME_PM_IP_REV_1_IP_MJ_MASK 0x0000ff00UL
+#define PME_PM_IP_REV_1_IP_MJ_SHIFT 8UL
+#define PME_PM_IP_REV_1_IP_MN_MASK 0x000000ffUL
+#define PME_PM_IP_REV_1_IP_MN_SHIFT 0UL
+#define PME_PM_IP_REV_2_IP_ERR_MASK 0x0000ff00UL
+#define PME_PM_IP_REV_2_IP_ERR_SHIFT 8UL
+
+static inline int get_major_rev(u32 pme_rev1)
+{
+ return (pme_rev1 & PME_PM_IP_REV_1_IP_MJ_MASK) >>
+ PME_PM_IP_REV_1_IP_MJ_SHIFT;
+}
+
+static inline int get_minor_rev(u32 pme_rev1)
+{
+ return (pme_rev1 & PME_PM_IP_REV_1_IP_MN_MASK) >>
+ PME_PM_IP_REV_1_IP_MN_SHIFT;
+}
+
+static inline int get_errata_rev(u32 pme_rev2)
+{
+ return (pme_rev2 & PME_PM_IP_REV_2_IP_ERR_MASK) >>
+ PME_PM_IP_REV_2_IP_ERR_SHIFT;
+}
+
+static inline int is_version_2_1_4(u32 pme_rev1, u32 pme_rev2)
+{
+ return (get_major_rev(pme_rev1) == 2) &&
+ (get_minor_rev(pme_rev1) == 1) &&
+ (get_errata_rev(pme_rev2) == 4);
+}
+
diff --git a/drivers/staging/fsl_pme2/pme2_regs.h b/drivers/staging/fsl_pme2/pme2_regs.h
new file mode 100644
index 0000000..1894b02
--- /dev/null
+++ b/drivers/staging/fsl_pme2/pme2_regs.h
@@ -0,0 +1,173 @@
+/* Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PME2_REGS_H
+#define PME2_REGS_H
+
+#define PME_REG_ISR 0x000
+#define PME_REG_IER 0x004
+#define PME_REG_ISDR 0x008
+#define PME_REG_IIR 0x00C
+#define PME_REG_RLL 0x014
+#define PME_REG_CDCR 0x018
+#define PME_REG_TRUNCI 0x024
+#define PME_REG_RBC 0x028
+#define PME_REG_ESR 0x02C
+#define PME_REG_ECR0 0x030
+#define PME_REG_ECR1 0x034
+#define PME_REG_EFQC 0x050
+#define PME_REG_FACONF 0x060
+#define PME_REG_PMSTAT 0x064
+#define PME_REG_FAMCR 0x068
+#define PME_REG_PMTR 0x06C
+#define PME_REG_PEHD 0x074
+#define PME_REG_BSC0 0x080
+#define PME_REG_BSC1 0x084
+#define PME_REG_BSC2 0x088
+#define PME_REG_BSC3 0x08C
+#define PME_REG_BSC4 0x090
+#define PME_REG_BSC5 0x094
+#define PME_REG_BSC6 0x098
+#define PME_REG_BSC7 0x09C
+#define PME_REG_QMBFD0 0x0E0
+#define PME_REG_QMBFD1 0x0E4
+#define PME_REG_QMBFD2 0x0E8
+#define PME_REG_QMBFD3 0x0EC
+#define PME_REG_QMBCTXTAH 0x0F0
+#define PME_REG_QMBCTXTAL 0x0F4
+#define PME_REG_QMBCTXTB 0x0F8
+#define PME_REG_QMBCTL 0x0FC
+#define PME_REG_ECC1BES 0x100
+#define PME_REG_ECC2BES 0x104
+#define PME_REG_ECCADDR 0x110
+#define PME_REG_ECCCODE 0x118
+#define PME_REG_TBT0ECC1TH 0x180
+#define PME_REG_TBT0ECC1EC 0x184
+#define PME_REG_TBT1ECC1TH 0x188
+#define PME_REG_TBT1ECC1EC 0x18C
+#define PME_REG_VLT0ECC1TH 0x190
+#define PME_REG_VLT0ECC1EC 0x194
+#define PME_REG_VLT1ECC1TH 0x198
+#define PME_REG_VLT1ECC1EC 0x19C
+#define PME_REG_CMECC1TH 0x1A0
+#define PME_REG_CMECC1EC 0x1A4
+#define PME_REG_DXCMECC1TH 0x1B0
+#define PME_REG_DXCMECC1EC 0x1B4
+#define PME_REG_DXEMECC1TH 0x1C0
+#define PME_REG_DXEMECC1EC 0x1C4
+#define PME_REG_STNIB 0x200
+#define PME_REG_STNIS 0x204
+#define PME_REG_STNTH1 0x208
+#define PME_REG_STNTH2 0x20C
+#define PME_REG_STNTHV 0x210
+#define PME_REG_STNTHS 0x214
+#define PME_REG_STNCH 0x218
+#define PME_REG_SWDB 0x21C
+#define PME_REG_KVLTS 0x220
+#define PME_REG_KEC 0x224
+#define PME_REG_STNPM 0x280
+#define PME_REG_STNS1M 0x284
+#define PME_REG_DRCIC 0x288
+#define PME_REG_DRCMC 0x28C
+#define PME_REG_STNPMR 0x290
+#define PME_REG_PDSRBAH 0x2A0
+#define PME_REG_PDSRBAL 0x2A4
+#define PME_REG_DMCR 0x2A8
+#define PME_REG_DEC0 0x2AC
+#define PME_REG_DEC1 0x2B0
+#define PME_REG_DLC 0x2C0
+#define PME_REG_STNDSR 0x300
+#define PME_REG_STNESR 0x304
+#define PME_REG_STNS1R 0x308
+#define PME_REG_STNOB 0x30C
+#define PME_REG_SCBARH 0x310
+#define PME_REG_SCBARL 0x314
+#define PME_REG_SMCR 0x318
+#define PME_REG_SREC 0x320
+#define PME_REG_ESRP 0x328
+#define PME_REG_SRRV0 0x338
+#define PME_REG_SRRV1 0x33C
+#define PME_REG_SRRV2 0x340
+#define PME_REG_SRRV3 0x344
+#define PME_REG_SRRV4 0x348
+#define PME_REG_SRRV5 0x34C
+#define PME_REG_SRRV6 0x350
+#define PME_REG_SRRV7 0x354
+#define PME_REG_SRRFI 0x358
+#define PME_REG_SRRI 0x360
+#define PME_REG_SRRR 0x364
+#define PME_REG_SRRWC 0x368
+#define PME_REG_SFRCC 0x36C
+#define PME_REG_SEC1 0x370
+#define PME_REG_SEC2 0x374
+#define PME_REG_SEC3 0x378
+#define PME_REG_MIA_BYC 0x380
+#define PME_REG_MIA_BLC 0x384
+#define PME_REG_MIA_CE 0x388
+#define PME_REG_MIA_CR 0x390
+#define PME_REG_PPIDMR0 0x800
+#define PME_REG_PPIDMR1 0x804
+#define PME_REG_PPIDMR2 0x808
+#define PME_REG_PPIDMR3 0x80C
+#define PME_REG_PPIDMR4 0x810
+#define PME_REG_PPIDMR5 0x814
+#define PME_REG_PPIDMR6 0x818
+#define PME_REG_PPIDMR7 0x81C
+#define PME_REG_PPIDMR8 0x820
+#define PME_REG_PPIDMR9 0x824
+#define PME_REG_PPIDMR10 0x828
+#define PME_REG_PPIDMR11 0x82C
+#define PME_REG_PPIDMR12 0x830
+#define PME_REG_PPIDMR13 0x834
+#define PME_REG_PPIDMR14 0x838
+#define PME_REG_PPIDMR15 0x83C
+#define PME_REG_PPIDMR16 0x840
+#define PME_REG_PPIDMR17 0x844
+#define PME_REG_PPIDMR18 0x848
+#define PME_REG_PPIDMR19 0x84C
+#define PME_REG_PPIDMR20 0x850
+#define PME_REG_PPIDMR21 0x854
+#define PME_REG_PPIDMR22 0x858
+#define PME_REG_PPIDMR23 0x85C
+#define PME_REG_PPIDMR24 0x860
+#define PME_REG_PPIDMR25 0x864
+#define PME_REG_PPIDMR26 0x868
+#define PME_REG_PPIDMR27 0x86C
+#define PME_REG_PPIDMR28 0x870
+#define PME_REG_PPIDMR29 0x874
+#define PME_REG_PPIDMR30 0x878
+#define PME_REG_PPIDMR31 0x87C
+#define PME_REG_SRCIDR 0xA00
+#define PME_REG_LIODNR 0xA0C
+#define PME_REG_PM_IP_REV1 0xBF8
+#define PME_REG_PM_IP_REV2 0xBFC
+
+#endif /* REGS_H */
diff --git a/drivers/staging/fsl_pme2/pme2_sample_db.c b/drivers/staging/fsl_pme2/pme2_sample_db.c
new file mode 100644
index 0000000..75fef4e
--- /dev/null
+++ b/drivers/staging/fsl_pme2/pme2_sample_db.c
@@ -0,0 +1,453 @@
+/* Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pme2_test.h"
+
+static u8 pme_db[] = {
+ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* Rev 2.2 */
+/* 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
+ 0x48, 0x41, 0x40, 0x20, 0x00, 0x11, */
+/* Rev 2.1 */
+ 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
+ 0x90, 0x41, 0x40, 0x20, 0x00, 0x11,
+/* Rev 2.0 */
+/* 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01,
+ 0x20, 0x41, 0x40, 0x20, 0x00, 0x11, */
+ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* Rev 2.0 */
+/* 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x48, 0x41, 0xff, 0x81, 0x00, 0x00, */
+/* Rev 2.1 */
+ 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x90, 0x41, 0xff, 0x81, 0x00, 0x00,
+/* Rev 2.0 */
+/* 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01,
+ 0x20, 0x41, 0xff, 0x81, 0x00, 0x00, */
+ 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x01,
+ 0x01, 0xff, 0x80, 0x00, 0x41, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
+ 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+ 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
+ 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
+ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
+ 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
+ 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43,
+ 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
+ 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53,
+ 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b,
+ 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x41, 0x42, 0x43,
+ 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
+ 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53,
+ 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x7b,
+ 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83,
+ 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b,
+ 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93,
+ 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b,
+ 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3,
+ 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab,
+ 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
+ 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb,
+ 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb,
+ 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3,
+ 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb,
+ 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3,
+ 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb,
+ 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3,
+ 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
+ 0xfc, 0xfd, 0xfe, 0xff
+};
+
+static u8 db_read[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+ 0x11, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* Rev 2.2 */
+/* 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
+ 0x48, 0x41 */
+/* Rev 2.1 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
+ 0x90, 0x41
+/* Rev 2.0 */
+/* 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01,
+ 0x20, 0x41 */
+};
+
+static u8 db_read_expected_result[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
+ 0x11, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* Rev 2.2 */
+/* 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
+ 0x48, 0x41, 0x40, 0x20, 0x00, 0x11*/
+/* Rev 2.1 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
+ 0x90, 0x41, 0x40, 0x20, 0x00, 0x11
+/* Rev 2.0 */
+/* 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01,
+ 0x20, 0x41, 0x40, 0x20, 0x00, 0x11*/
+};
+
+struct pmtcc_ctx {
+ struct pme_ctx base_ctx;
+ struct qm_fd result_fd;
+ struct completion done;
+ u8 ern;
+};
+
+static void pmtcc_cb(struct pme_ctx *ctx, const struct qm_fd *fd,
+ struct pme_ctx_token *ctx_token)
+{
+ struct pmtcc_ctx *my_ctx = (struct pmtcc_ctx *)ctx;
+ memcpy(&my_ctx->result_fd, fd, sizeof(*fd));
+ complete(&my_ctx->done);
+}
+
+static void pmtcc_ern_cb(struct pme_ctx *ctx, const struct qm_mr_entry *mr,
+ struct pme_ctx_token *ctx_token)
+{
+ struct pmtcc_ctx *my_ctx = (struct pmtcc_ctx *)ctx;
+ my_ctx->result_fd = mr->ern.fd;
+ my_ctx->ern = 1;
+ complete(&my_ctx->done);
+}
+
+#define FIRST_PMTCC 56
+int pme2_clear_sample_db(void)
+{
+ struct pmtcc_ctx ctx = {
+ .base_ctx.cb = pmtcc_cb,
+ .base_ctx.ern_cb = pmtcc_ern_cb,
+ .ern = 0
+ };
+ struct qm_fd fd;
+ int ret = 0;
+ enum pme_status status;
+ struct pme_ctx_token token;
+ void *mem;
+ struct cpumask backup_mask = current->cpus_allowed;
+ struct cpumask new_mask = *qman_affine_cpus();
+
+ cpumask_and(&new_mask, &new_mask, bman_affine_cpus());
+ ret = set_cpus_allowed_ptr(current, &new_mask);
+ if (ret) {
+ pr_info("cleanr_sample_db: can't set cpumask\n");
+ goto _clear_0;
+ }
+ init_completion(&ctx.done);
+ ret = pme_ctx_init(&ctx.base_ctx,
+ PME_CTX_FLAG_EXCLUSIVE |
+ PME_CTX_FLAG_PMTCC |
+ PME_CTX_FLAG_LOCAL, 0, 4, 4, 0, NULL);
+ if (ret) {
+ pr_err("clear_sample_db: can't init ctx\n");
+ goto _clear_1;
+ }
+
+ /* enable the context */
+ ret = pme_ctx_enable(&ctx.base_ctx);
+ if (ret) {
+ pr_err("clear_sample_db: can't enable ctx\n");
+ goto _clear_2;
+ }
+
+ /* Write the database */
+ memset(&fd, 0, sizeof(struct qm_fd));
+ mem = kmalloc(FIRST_PMTCC, GFP_KERNEL);
+ if (!mem)
+ goto _clear_3;
+ memcpy(mem, pme_db, FIRST_PMTCC);
+
+ fd.length20 = FIRST_PMTCC;
+ qm_fd_addr_set64(&fd, pme_map(mem));
+
+ ret = pme_ctx_pmtcc(&ctx.base_ctx, PME_CTX_OP_WAIT, &fd, &token);
+ if (ret == -ENODEV) {
+ pr_err("clear_sample_db: not the control plane, bailing\n");
+ goto _clear_4;
+ }
+ if (ret) {
+ pr_err("clear_sample_db: error with pmtcc\n");
+ goto _clear_4;
+ }
+ wait_for_completion(&ctx.done);
+ if (ctx.ern) {
+ pr_err("clear_sample_db: Rx ERN from pmtcc\n");
+ goto _clear_4;
+ }
+ status = pme_fd_res_status(&ctx.result_fd);
+ if (status) {
+ pr_info("clear_sample_db: PMTCC write status failed %d\n",
+ status);
+ goto _clear_4;
+ }
+_clear_4:
+ kfree(mem);
+_clear_3:
+ /* Disable */
+ ret = pme_ctx_disable(&ctx.base_ctx,
+ PME_CTX_OP_WAIT | PME_CTX_OP_WAIT_INT, NULL);
+_clear_2:
+ pme_ctx_finish(&ctx.base_ctx);
+_clear_1:
+ ret = set_cpus_allowed_ptr(current, &backup_mask);
+ if (ret)
+ pr_info("clear_sample_db: can't restore cpumask");
+_clear_0:
+ if (!ret)
+ pr_info("clear_sample_db: Done\n");
+ else
+ pr_info("clear_sample_db: Error 0x%x\n", ret);
+ return ret;
+
+}
+
+int pme2_sample_db(void)
+{
+ struct pmtcc_ctx ctx = {
+ .base_ctx.cb = pmtcc_cb,
+ .base_ctx.ern_cb = pmtcc_ern_cb,
+ .ern = 0
+ };
+ struct qm_fd fd;
+ struct qm_sg_entry *sg_table = NULL;
+ int ret = 0;
+ enum pme_status status;
+ struct pme_ctx_token token;
+ void *mem = NULL, *mem_result = NULL;
+ u32 pme_rev;
+ struct cpumask backup_mask = current->cpus_allowed;
+ struct cpumask new_mask = *qman_affine_cpus();
+
+ cpumask_and(&new_mask, &new_mask, bman_affine_cpus());
+ ret = set_cpus_allowed_ptr(current, &new_mask);
+ if (ret) {
+ pr_info("sample_db: can't set cpumask\n");
+ goto _finish_0;
+ }
+ ret = pme_attr_get(pme_attr_rev1, &pme_rev);
+ if (ret) {
+ pr_err("sample_db: can't read pme revision %d\n", ret);
+ goto _finish_1;
+ }
+ /* If Rev 2.0, Rev 2.2...update database */
+ switch (pme_rev & 0x0000FFFF) {
+ case 0x00000200:
+ pr_info("sample_db: db for pme ver 2.0\n");
+ pme_db[133] = 0x01;
+ pme_db[134] = 0x20;
+ pme_db[161] = 0x01;
+ pme_db[162] = 0x20;
+ db_read[21] = 0x01;
+ db_read[22] = 0x20;
+ db_read_expected_result[21] = 0x01;
+ db_read_expected_result[22] = 0x20;
+ break;
+ case 0x00000201:
+ pr_info("sample_db: db for pme ver 2.1\n");
+ break;
+ case 0x00000202:
+ pr_info("sample_db: db for pme ver 2.2\n");
+ pme_db[134] = 0x48;
+ pme_db[162] = 0x48;
+ db_read[22] = 0x48;
+ db_read_expected_result[22] = 0x48;
+ break;
+ default:
+ pr_err("sample_db: Unknown pme hw ver 0x%x\n",
+ pme_rev & 0x0000FFFF);
+ ret = -ENODEV;
+ goto _finish_1;
+ }
+ init_completion(&ctx.done);
+ ret = pme_ctx_init(&ctx.base_ctx,
+ PME_CTX_FLAG_EXCLUSIVE |
+ PME_CTX_FLAG_PMTCC |
+ PME_CTX_FLAG_LOCAL, 0, 4, 4, 0, NULL);
+ if (ret) {
+ pr_err("sample_db: can't init ctx\n");
+ goto _finish_1;
+ }
+
+ /* enable the context */
+ ret = pme_ctx_enable(&ctx.base_ctx);
+ if (ret) {
+ pr_err("sample_db: can't enable ctx\n");
+ goto _finish_2;
+ }
+
+ /* Write the database */
+ memset(&fd, 0, sizeof(struct qm_fd));
+ mem = kmalloc(sizeof(pme_db), GFP_KERNEL);
+ if (!mem)
+ goto _finish_3;
+ memcpy(mem, pme_db, sizeof(pme_db));
+
+ fd.length20 = sizeof(pme_db);
+ qm_fd_addr_set64(&fd, pme_map(mem));
+
+ ret = pme_ctx_pmtcc(&ctx.base_ctx, PME_CTX_OP_WAIT, &fd, &token);
+ if (ret == -ENODEV) {
+ pr_err("sample_db: not the control plane, bailing\n");
+ goto _finish_4;
+ }
+ if (ret) {
+ pr_err("sample_db: error with pmtcc\n");
+ goto _finish_4;
+ }
+ wait_for_completion(&ctx.done);
+ if (ctx.ern) {
+ pr_err("sample_db: Rx ERN from pmtcc\n");
+ goto _finish_4;
+ }
+ status = pme_fd_res_status(&ctx.result_fd);
+ if (status) {
+ pr_info("sample_db: PMTCC write status failed %d\n", status);
+ goto _finish_4;
+ }
+ kfree(mem);
+ mem = NULL;
+ /* Read back the database */
+ init_completion(&ctx.done);
+ memset(&fd, 0, sizeof(struct qm_fd));
+ sg_table = kzalloc(2 * sizeof(*sg_table), GFP_KERNEL | GFP_DMA);
+ mem_result = kmalloc(28, GFP_KERNEL);
+ mem = kmalloc(sizeof(db_read), GFP_KERNEL);
+ if (!sg_table || !mem || !mem_result) {
+ pr_err("sample_db: out of memory\n");
+ ret = -ENOMEM;
+ goto _finish_4;
+ }
+ memcpy(mem, db_read, sizeof(db_read));
+ qm_sg_entry_set64(&sg_table[0], pme_map(mem_result));
+ sg_table[0].length = 28;
+ qm_sg_entry_set64(&sg_table[1], pme_map(mem));
+ sg_table[1].length = sizeof(db_read);
+ sg_table[1].final = 1;
+ fd.format = qm_fd_compound;
+ qm_fd_addr_set64(&fd, pme_map(sg_table));
+ ret = pme_ctx_pmtcc(&ctx.base_ctx, PME_CTX_OP_WAIT, &fd, &token);
+ if (ret) {
+ pr_err("sample_db: error with pmtcc\n");
+ goto _finish_4;
+ }
+ wait_for_completion(&ctx.done);
+ if (ctx.ern) {
+ ret = -EINVAL;
+ pr_err("sample_db: Rx ERN from pmtcc\n");
+ goto _finish_4;
+ }
+ status = pme_fd_res_status(&ctx.result_fd);
+ if (status) {
+ ret = -EINVAL;
+ pr_err("sample_db: PMTCC read status failed %d\n", status);
+ goto _finish_4;
+ }
+ if (pme_fd_res_flags(&ctx.result_fd) & PME_STATUS_UNRELIABLE) {
+ pr_err("sample_db: flags result set %x\n",
+ pme_fd_res_flags(&ctx.result_fd));
+ ret = -EINVAL;
+ goto _finish_4;
+ }
+ if (memcmp(db_read_expected_result, mem_result, 28) != 0) {
+ pr_err("sample_db: DB read result not expected\n");
+ pr_err("Expected\n");
+ hexdump(db_read_expected_result,
+ sizeof(db_read_expected_result));
+ pr_info("Received\n");
+ hexdump(mem_result, 28);
+ ret = -EINVAL;
+ }
+_finish_4:
+ kfree(mem_result);
+ kfree(sg_table);
+ kfree(mem);
+_finish_3:
+ /* Disable */
+ ret = pme_ctx_disable(&ctx.base_ctx,
+ PME_CTX_OP_WAIT | PME_CTX_OP_WAIT_INT, NULL);
+_finish_2:
+ pme_ctx_finish(&ctx.base_ctx);
+_finish_1:
+ if (ret)
+ set_cpus_allowed_ptr(current, &backup_mask);
+ else {
+ ret = set_cpus_allowed_ptr(current, &backup_mask);
+ if (ret)
+ pr_info("sample_db: can't restore cpumask");
+ }
+
+_finish_0:
+ if (!ret)
+ pr_info("pme: sample DB initialised\n");
+ else
+ pr_info("pme: Error during sample DB 0x%x\n", ret);
+ return ret;
+}
diff --git a/drivers/staging/fsl_pme2/pme2_scan.c b/drivers/staging/fsl_pme2/pme2_scan.c
new file mode 100644
index 0000000..2c4df40
--- /dev/null
+++ b/drivers/staging/fsl_pme2/pme2_scan.c
@@ -0,0 +1,1122 @@
+/* Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "pme2_private.h"
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/poll.h>
+#include <linux/compat.h>
+
+#define WAIT_AND_INTERRUPTABLE (PME_CTX_OP_WAIT|PME_CTX_OP_WAIT_INT)
+#define INPUT_FRM 1
+#define OUTPUT_FRM 0
+/* Private structure that is allocated for each open that is done on the
+ * pme_scan device. */
+struct scan_session {
+ /* The ctx that is needed to communicate with the pme high level */
+ struct pme_ctx ctx;
+ /* Locks completed_commands */
+ spinlock_t set_subset_lock;
+ __u8 set;
+ __u16 subset;
+ /* For asynchronous processing */
+ wait_queue_head_t waiting_for_completion;
+ struct list_head completed_commands;
+ /* Locks completed_commands */
+ spinlock_t completed_commands_lock;
+ u32 completed_count;
+};
+
+/* Command Token for scan operations. One of these is created for every
+ * operation on a context. When the context operation is complete cleanup
+ * is done */
+struct cmd_token {
+ /* pme high level token */
+ struct pme_ctx_token hl_token;
+ /* The kernels copy of the user op structure */
+ struct pme_scan_cmd kernel_op;
+ /* Set to non zero if this is a synchronous request */
+ u8 synchronous;
+ /* data */
+ struct qm_fd tx_fd;
+ struct qm_sg_entry tx_comp[2];
+ struct qm_fd rx_fd;
+ void *tx_data;
+ size_t tx_size;
+ void *rx_data;
+ size_t rx_size;
+ /* For blocking requests, we need a wait point and condition */
+ wait_queue_head_t *queue;
+ /* List management for completed async requests */
+ struct list_head completed_list;
+ u8 done;
+ u8 ern;
+};
+
+struct ctrl_op {
+ struct pme_ctx_ctrl_token ctx_ctr;
+ struct completion cb_done;
+ enum pme_status cmd_status;
+ u8 res_flag;
+ u8 ern;
+};
+
+#ifdef CONFIG_COMPAT
+static void compat_to_scan_cmd(struct pme_scan_cmd *dst,
+ struct compat_pme_scan_cmd *src)
+{
+ dst->flags = src->flags;
+ dst->opaque = compat_ptr(src->opaque);
+ dst->input.data = compat_ptr(src->input.data);
+ dst->input.size = src->input.size;
+ dst->output.data = compat_ptr(src->output.data);
+ dst->output.size = src->output.size;
+}
+
+static void scan_result_to_compat(struct compat_pme_scan_result *dst,
+ struct pme_scan_result *src)
+{
+ dst->flags = src->flags;
+ dst->opaque = ptr_to_compat(src->opaque);
+ dst->status = src->status;
+ dst->output.data = ptr_to_compat(src->output.data);
+ dst->output.size = src->output.size;
+}
+
+static void compat_to_scan_result(struct pme_scan_result *dst,
+ struct compat_pme_scan_result *src)
+{
+ dst->flags = src->flags;
+ dst->opaque = compat_ptr(src->opaque);
+ dst->status = src->status;
+ dst->output.data = compat_ptr(src->output.data);
+ dst->output.size = src->output.size;
+}
+#endif
+
+static void ctrl_cb(struct pme_ctx *ctx, const struct qm_fd *fd,
+ struct pme_ctx_ctrl_token *token)
+{
+ struct ctrl_op *ctrl = (struct ctrl_op *)token;
+ ctrl->cmd_status = pme_fd_res_status(fd);
+ ctrl->res_flag = pme_fd_res_flags(fd) & PME_STATUS_UNRELIABLE;
+ complete(&ctrl->cb_done);
+}
+
+static void ctrl_ern_cb(struct pme_ctx *ctx, const struct qm_mr_entry *mr,
+ struct pme_ctx_ctrl_token *token)
+{
+ struct ctrl_op *ctrl = (struct ctrl_op *)token;
+ ctrl->ern = 1;
+ complete(&ctrl->cb_done);
+}
+
+static inline int scan_data_empty(struct scan_session *session)
+{
+ return list_empty(&session->completed_commands);
+}
+
+/* Cleanup for the execute_cmd method */
+static inline void cleanup_token(struct cmd_token *token_p)
+{
+ kfree(token_p->tx_data);
+ kfree(token_p->rx_data);
+ return;
+}
+
+/* Callback for scan operations */
+static void scan_cb(struct pme_ctx *ctx, const struct qm_fd *fd,
+ struct pme_ctx_token *ctx_token)
+{
+ struct cmd_token *token = (struct cmd_token *)ctx_token;
+ struct scan_session *session = (struct scan_session *)ctx;
+
+ token->rx_fd = *fd;
+ /* If this is a asynchronous command, queue the token */
+ if (!token->synchronous) {
+ spin_lock(&session->completed_commands_lock);
+ list_add_tail(&token->completed_list,
+ &session->completed_commands);
+ session->completed_count++;
+ spin_unlock(&session->completed_commands_lock);
+ }
+ /* Wake up the thread that's waiting for us */
+ token->done = 1;
+ wake_up(token->queue);
+ return;
+}
+
+static void scan_ern_cb(struct pme_ctx *ctx, const struct qm_mr_entry *mr,
+ struct pme_ctx_token *ctx_token)
+{
+ struct cmd_token *token = (struct cmd_token *)ctx_token;
+ struct scan_session *session = (struct scan_session *)ctx;
+
+ token->ern = 1;
+ token->rx_fd = mr->ern.fd;
+ /* If this is a asynchronous command, queue the token */
+ if (!token->synchronous) {
+ spin_lock(&session->completed_commands_lock);
+ list_add_tail(&token->completed_list,
+ &session->completed_commands);
+ session->completed_count++;
+ spin_unlock(&session->completed_commands_lock);
+ }
+ /* Wake up the thread that's waiting for us */
+ token->done = 1;
+ wake_up(token->queue);
+ return;
+}
+
+static int process_completed_token(struct file *fp, struct cmd_token *token_p,
+ struct pme_scan_result *scan_result)
+{
+ int ret = 0;
+ u32 src_sz, dst_sz;
+
+ memset(scan_result, 0, sizeof(struct pme_scan_result));
+ if (token_p->ern) {
+ ret = -EIO;
+ goto done;
+ }
+ scan_result->output.data = token_p->kernel_op.output.data;
+
+ if (token_p->rx_fd.format == qm_fd_compound) {
+ /* Need to copy output */
+ src_sz = token_p->tx_comp[OUTPUT_FRM].length;
+ dst_sz = token_p->kernel_op.output.size;
+ scan_result->output.size = min(dst_sz, src_sz);
+ /* Doesn't make sense we generated more than available space
+ * should have got truncation.
+ */
+ BUG_ON(dst_sz < src_sz);
+ if (copy_to_user(scan_result->output.data, token_p->rx_data,
+ scan_result->output.size)) {
+ pr_err("Error copying to user data\n");
+ cleanup_token(token_p);
+ return -EFAULT;
+ }
+ } else if (token_p->rx_fd.format == qm_fd_sg_big)
+ scan_result->output.size = 0;
+ else
+ pr_err("pme2_scan: unexpected frame type received\n");
+
+ scan_result->flags |= pme_fd_res_flags(&token_p->rx_fd);
+ scan_result->status |= pme_fd_res_status(&token_p->rx_fd);
+done:
+ scan_result->opaque = token_p->kernel_op.opaque;
+ cleanup_token(token_p);
+ return ret;
+}
+
+static int getscan_cmd(struct file *fp, struct scan_session *session,
+ struct pme_scan_params __user *user_scan_params)
+{
+ int ret = 0;
+ struct pme_flow params;
+ struct pme_scan_params local_scan_params;
+ struct ctrl_op ctx_ctrl = {
+ .ctx_ctr.cb = ctrl_cb,
+ .ctx_ctr.ern_cb = ctrl_ern_cb,
+ .cmd_status = 0,
+ .res_flag = 0,
+ .ern = 0
+ };
+ init_completion(&ctx_ctrl.cb_done);
+
+ memset(&local_scan_params, 0, sizeof(local_scan_params));
+
+ /* must be enabled */
+ if (pme_ctx_is_disabled(&session->ctx)) {
+ pr_err("pme2_scan: ctx is disabled\n");
+ ret = -EINVAL;
+ goto done;
+ }
+ ret = pme_ctx_ctrl_read_flow(&session->ctx, WAIT_AND_INTERRUPTABLE,
+ &params, &ctx_ctrl.ctx_ctr);
+ if (ret) {
+ PMEPRINFO("read flow error %d\n", ret);
+ goto done;
+ }
+ wait_for_completion(&ctx_ctrl.cb_done);
+
+ if (ctx_ctrl.ern || ctx_ctrl.cmd_status || ctx_ctrl.res_flag) {
+ PMEPRINFO("read flow error %d\n", ctx_ctrl.cmd_status);
+ ret = -EFAULT;
+ goto done;
+ }
+ local_scan_params.residue.enable = params.ren;
+ local_scan_params.residue.length = params.rlen;
+ local_scan_params.sre.sessionid = params.sessionid;
+ local_scan_params.sre.verbose = params.srvm;
+ local_scan_params.sre.esee = params.esee;
+ local_scan_params.dxe.clim = params.clim;
+ local_scan_params.dxe.mlim = params.mlim;
+ spin_lock(&session->set_subset_lock);
+ local_scan_params.pattern.set = session->set;
+ local_scan_params.pattern.subset = session->subset;
+ spin_unlock(&session->set_subset_lock);
+
+ if (copy_to_user(user_scan_params, &local_scan_params,
+ sizeof(local_scan_params))) {
+ pr_err("Error copying to user data\n");
+ ret = -EFAULT;
+ }
+done:
+ return ret;
+}
+
+static int setscan_cmd(struct file *fp, struct scan_session *session,
+ struct pme_scan_params __user *user_params)
+{
+ int ret = 0;
+ u32 flag = WAIT_AND_INTERRUPTABLE;
+ struct ctrl_op ctx_ctrl = {
+ .ctx_ctr.cb = ctrl_cb,
+ .ctx_ctr.ern_cb = ctrl_ern_cb,
+ .cmd_status = 0,
+ .res_flag = 0,
+ .ern = 0
+ };
+ struct pme_flow params;
+ struct pme_scan_params local_params;
+
+ pme_sw_flow_init(&params);
+ init_completion(&ctx_ctrl.cb_done);
+ if (copy_from_user(&local_params, user_params, sizeof(local_params)))
+ return -EFAULT;
+
+ /* must be enabled */
+ if (pme_ctx_is_disabled(&session->ctx)) {
+ ret = -EINVAL;
+ goto done;
+ }
+ /* Only send a flw_ctx_w if PME_SCAN_PARAMS_{RESIDUE, SRE or DXE}
+ * is being done */
+ if (local_params.flags == PME_SCAN_PARAMS_PATTERN)
+ goto set_subset;
+ if (local_params.flags & PME_SCAN_PARAMS_RESIDUE)
+ flag |= PME_CMD_FCW_RES;
+ if (local_params.flags & PME_SCAN_PARAMS_SRE)
+ flag |= PME_CMD_FCW_SRE;
+ if (local_params.flags & PME_SCAN_PARAMS_DXE)
+ flag |= PME_CMD_FCW_DXE;
+ params.ren = local_params.residue.enable;
+ params.sessionid = local_params.sre.sessionid;
+ params.srvm = local_params.sre.verbose;
+ params.esee = local_params.sre.esee;
+ params.clim = local_params.dxe.clim;
+ params.mlim = local_params.dxe.mlim;
+
+ ret = pme_ctx_ctrl_update_flow(&session->ctx, flag, &params,
+ &ctx_ctrl.ctx_ctr);
+ if (ret) {
+ PMEPRINFO("update flow error %d\n", ret);
+ goto done;
+ }
+ wait_for_completion(&ctx_ctrl.cb_done);
+ if (ctx_ctrl.ern || ctx_ctrl.cmd_status || ctx_ctrl.res_flag) {
+ PMEPRINFO("update flow err %d\n", ctx_ctrl.cmd_status);
+ ret = -EFAULT;
+ goto done;
+ }
+
+set_subset:
+ if (local_params.flags & PME_SCAN_PARAMS_PATTERN) {
+ spin_lock(&session->set_subset_lock);
+ session->set = local_params.pattern.set;
+ session->subset = local_params.pattern.subset;
+ spin_unlock(&session->set_subset_lock);
+ goto done;
+ }
+done:
+ return ret;
+}
+
+static int resetseq_cmd(struct file *fp, struct scan_session *session)
+{
+ int ret = 0;
+ struct pme_flow params;
+ struct ctrl_op ctx_ctrl = {
+ .ctx_ctr.cb = ctrl_cb,
+ .ctx_ctr.ern_cb = ctrl_ern_cb,
+ .cmd_status = 0,
+ .res_flag = 0,
+ .ern = 0
+ };
+ init_completion(&ctx_ctrl.cb_done);
+ pme_sw_flow_init(&params);
+
+ /* must be enabled */
+ if (pme_ctx_is_disabled(&session->ctx)) {
+ pr_err("pme2_scan: ctx is disabled\n");
+ ret = -EINVAL;
+ goto done;
+ }
+ pme_flow_seqnum_set64(&params, 0);
+ params.sos = 1;
+
+ ret = pme_ctx_ctrl_update_flow(&session->ctx, PME_CMD_FCW_SEQ, &params,
+ &ctx_ctrl.ctx_ctr);
+ if (ret) {
+ pr_err("pme2_scan: update flow error %d\n", ret);
+ return ret;
+ }
+ wait_for_completion(&ctx_ctrl.cb_done);
+ if (ctx_ctrl.ern || ctx_ctrl.cmd_status || ctx_ctrl.res_flag) {
+ PMEPRINFO("update flow err %d\n", ctx_ctrl.cmd_status);
+ ret = -EFAULT;
+ }
+done:
+ return ret;
+}
+
+static int resetresidue_cmd(struct file *fp, struct scan_session *session)
+{
+ int ret = 0;
+ struct pme_flow params;
+ struct ctrl_op ctx_ctrl = {
+ .ctx_ctr.cb = ctrl_cb,
+ .ctx_ctr.ern_cb = ctrl_ern_cb,
+ .cmd_status = 0,
+ .res_flag = 0,
+ .ern = 0
+ };
+
+ init_completion(&ctx_ctrl.cb_done);
+ pme_sw_flow_init(&params);
+ /* must be enabled */
+ if (pme_ctx_is_disabled(&session->ctx)) {
+ pr_err("pme2_scan: ctx is disabled\n");
+ ret = -EINVAL;
+ goto done;
+ }
+ params.rlen = 0;
+ ret = pme_ctx_ctrl_update_flow(&session->ctx,
+ WAIT_AND_INTERRUPTABLE | PME_CTX_OP_RESETRESLEN,
+ &params, &ctx_ctrl.ctx_ctr);
+ if (ret)
+ pr_info("pme2_scan: update flow error %d\n", ret);
+ wait_for_completion(&ctx_ctrl.cb_done);
+ if (ctx_ctrl.ern || ctx_ctrl.cmd_status || ctx_ctrl.res_flag) {
+ PMEPRINFO("update flow err %d\n", ctx_ctrl.cmd_status);
+ ret = -EFAULT;
+ }
+done:
+ return ret;
+}
+
+static int process_scan_cmd(
+ struct file *fp,
+ struct scan_session *session,
+ struct pme_scan_cmd *user_cmd,
+ struct pme_scan_result *user_ret,
+ u8 synchronous)
+{
+ int ret = 0;
+ struct cmd_token local_token;
+ struct cmd_token *token_p = NULL;
+ DECLARE_WAIT_QUEUE_HEAD(local_waitqueue);
+ u8 scan_flags = 0;
+
+ BUG_ON(synchronous && !user_ret);
+
+ /* If synchronous, use a local token (from the stack)
+ * If asynchronous, allocate a token to use */
+ if (synchronous)
+ token_p = &local_token;
+ else {
+ token_p = kmalloc(sizeof(*token_p), GFP_KERNEL);
+ if (!token_p)
+ return -ENOMEM;
+ }
+ memset(token_p, 0, sizeof(*token_p));
+ /* Copy the command to kernel space */
+ memcpy(&token_p->kernel_op, user_cmd, sizeof(struct pme_scan_cmd));
+
+#ifdef CONFIG_FSL_PME_BUG_4K_SCAN_REV_2_1_4
+ if (session->ctx.max_scan_size) {
+ if (token_p->kernel_op.input.size >
+ session->ctx.max_scan_size) {
+ if (!synchronous)
+ kfree(token_p);
+ return -EINVAL;
+ }
+ }
+#endif
+
+ /* Copy the input */
+ token_p->synchronous = synchronous;
+ token_p->tx_size = token_p->kernel_op.input.size;
+ token_p->tx_data = kmalloc(token_p->kernel_op.input.size, GFP_KERNEL);
+ if (!token_p->tx_data) {
+ pr_err("pme2_scan: Err alloc %zd byte", token_p->tx_size);
+ cleanup_token(token_p);
+ return -ENOMEM;
+ }
+ if (copy_from_user(token_p->tx_data,
+ token_p->kernel_op.input.data,
+ token_p->kernel_op.input.size)) {
+ pr_err("Error copying contigous user data\n");
+ cleanup_token(token_p);
+ return -EFAULT;
+ }
+ /* Setup input frame */
+ token_p->tx_comp[INPUT_FRM].final = 1;
+ token_p->tx_comp[INPUT_FRM].length = token_p->tx_size;
+ qm_sg_entry_set64(&token_p->tx_comp[INPUT_FRM],
+ pme_map(token_p->tx_data));
+ /* setup output frame, if output is expected */
+ if (token_p->kernel_op.output.size) {
+ token_p->rx_size = token_p->kernel_op.output.size;
+ PMEPRINFO("pme2_scan: expect output %d\n", token_p->rx_size);
+ token_p->rx_data = kmalloc(token_p->rx_size, GFP_KERNEL);
+ if (!token_p->rx_data) {
+ pr_err("pme2_scan: Err alloc %zd byte",
+ token_p->rx_size);
+ cleanup_token(token_p);
+ return -ENOMEM;
+ }
+ /* Setup output frame */
+ token_p->tx_comp[OUTPUT_FRM].length = token_p->rx_size;
+ qm_sg_entry_set64(&token_p->tx_comp[OUTPUT_FRM],
+ pme_map(token_p->rx_data));
+ token_p->tx_fd.format = qm_fd_compound;
+ /* Build compound frame */
+ qm_fd_addr_set64(&token_p->tx_fd,
+ pme_map(token_p->tx_comp));
+ } else {
+ token_p->tx_fd.format = qm_fd_sg_big;
+ /* Build sg frame */
+ qm_fd_addr_set64(&token_p->tx_fd,
+ pme_map(&token_p->tx_comp[INPUT_FRM]));
+ token_p->tx_fd.length29 = token_p->tx_size;
+ }
+
+ /* use the local wait queue if synchronous, the shared
+ * queue if asynchronous */
+ if (synchronous)
+ token_p->queue = &local_waitqueue;
+ else
+ token_p->queue = &session->waiting_for_completion;
+ token_p->done = 0;
+
+ if (token_p->kernel_op.flags & PME_SCAN_CMD_STARTRESET)
+ scan_flags |= PME_CMD_SCAN_SR;
+ if (token_p->kernel_op.flags & PME_SCAN_CMD_END)
+ scan_flags |= PME_CMD_SCAN_E;
+ ret = pme_ctx_scan(&session->ctx, WAIT_AND_INTERRUPTABLE,
+ &token_p->tx_fd,
+ PME_SCAN_ARGS(scan_flags, session->set, session->subset),
+ &token_p->hl_token);
+ if (unlikely(ret)) {
+ cleanup_token(token_p);
+ return ret;
+ }
+
+ if (!synchronous)
+ /* Don't wait. The command is away */
+ return 0;
+
+ PMEPRINFO("Wait for completion\n");
+ /* Wait for the command to complete */
+ /* TODO: Should this be wait_event_interruptible ?
+ * If so, will need logic to indicate */
+ wait_event(*token_p->queue, token_p->done == 1);
+ return process_completed_token(fp, token_p, user_ret);
+}
+
+/**
+ * fsl_pme2_scan_open - open the driver
+ *
+ * Open the driver and prepare for requests.
+ *
+ * Every time an application opens the driver, we create a scan_session object
+ * for that file handle.
+ */
+static int fsl_pme2_scan_open(struct inode *node, struct file *fp)
+{
+ int ret;
+ struct scan_session *session;
+ struct pme_flow flow;
+ struct ctrl_op ctx_ctrl = {
+ .ctx_ctr.cb = ctrl_cb,
+ .ctx_ctr.ern_cb = ctrl_ern_cb,
+ .cmd_status = 0,
+ .res_flag = 0,
+ .ern = 0
+ };
+
+ pme_sw_flow_init(&flow);
+ init_completion(&ctx_ctrl.cb_done);
+ PMEPRINFO("pme2_scan: open %d\n", smp_processor_id());
+ fp->private_data = kzalloc(sizeof(*session), GFP_KERNEL);
+ if (!fp->private_data)
+ return -ENOMEM;
+ session = (struct scan_session *)fp->private_data;
+ /* Set up the structures used for asynchronous requests */
+ init_waitqueue_head(&session->waiting_for_completion);
+ INIT_LIST_HEAD(&session->completed_commands);
+ spin_lock_init(&session->completed_commands_lock);
+ spin_lock_init(&session->set_subset_lock);
+ PMEPRINFO("kmalloc session %p\n", fp->private_data);
+ session = fp->private_data;
+ session->ctx.cb = scan_cb;
+ session->ctx.ern_cb = scan_ern_cb;
+
+ /* qosin, qosout should be driver attributes */
+ ret = pme_ctx_init(&session->ctx, PME_CTX_FLAG_LOCAL, 0, 4, 4, 0, NULL);
+ if (ret) {
+ pr_err("pme2_scan: pme_ctx_init %d\n", ret);
+ goto exit;
+ }
+ /* enable the context */
+ ret = pme_ctx_enable(&session->ctx);
+ if (ret) {
+ PMEPRINFO("error enabling ctx %d\n", ret);
+ pme_ctx_finish(&session->ctx);
+ goto exit;
+ }
+ /* Update flow to set sane defaults in the flow context */
+ ret = pme_ctx_ctrl_update_flow(&session->ctx,
+ PME_CTX_OP_WAIT | PME_CMD_FCW_ALL, &flow, &ctx_ctrl.ctx_ctr);
+ if (!ret) {
+ wait_for_completion(&ctx_ctrl.cb_done);
+ if (ctx_ctrl.ern || ctx_ctrl.cmd_status || ctx_ctrl.res_flag)
+ ret = -EFAULT;
+ }
+ if (ret) {
+ int my_ret;
+ PMEPRINFO("error updating flow ctx %d\n", ret);
+ my_ret = pme_ctx_disable(&session->ctx, PME_CTX_OP_WAIT,
+ &ctx_ctrl.ctx_ctr);
+ if (my_ret > 0)
+ wait_for_completion(&ctx_ctrl.cb_done);
+ else if (my_ret < 0)
+ PMEPRINFO("error disabling ctx %d\n", ret);
+ pme_ctx_finish(&session->ctx);
+ goto exit;
+ }
+ /* Set up the structures used for asynchronous requests */
+ PMEPRINFO("pme2_scan: Finish pme_scan open %d\n", smp_processor_id());
+ return 0;
+exit:
+ kfree(fp->private_data);
+ fp->private_data = NULL;
+ return ret;
+}
+
+static int fsl_pme2_scan_close(struct inode *node, struct file *fp)
+{
+ struct ctrl_op ctx_ctrl = {
+ .ctx_ctr.cb = ctrl_cb,
+ .ctx_ctr.ern_cb = ctrl_ern_cb,
+ .cmd_status = 0,
+ .res_flag = 0,
+ .ern = 0
+ };
+ int ret = 0;
+ struct scan_session *session = fp->private_data;
+
+ init_completion(&ctx_ctrl.cb_done);
+ /* Before disabling check to see if it's already disabled. This can
+ * happen if a pme serious error has occurred for instance.*/
+ if (!pme_ctx_is_disabled(&session->ctx)) {
+ ret = pme_ctx_disable(&session->ctx, PME_CTX_OP_WAIT,
+ &ctx_ctrl.ctx_ctr);
+ if (ret > 0) {
+ wait_for_completion(&ctx_ctrl.cb_done);
+ if (ctx_ctrl.ern)
+ PMEPRCRIT("Unexpected ERN\n");
+ } else if (ret < 0) {
+ pr_err("pme2_scan: Error disabling ctx %d\n", ret);
+ return ret;
+ }
+ }
+ pme_ctx_finish(&session->ctx);
+ kfree(session);
+ PMEPRINFO("pme2_scan: Finish pme_session close\n");
+ return 0;
+}
+
+static unsigned int fsl_pme2_scan_poll(struct file *fp,
+ struct poll_table_struct *wait)
+{
+ struct scan_session *session;
+ unsigned int mask = POLLOUT | POLLWRNORM;
+
+ if (!fp->private_data)
+ return -EINVAL;
+
+ session = (struct scan_session *)fp->private_data;
+
+ poll_wait(fp, &session->waiting_for_completion, wait);
+
+ if (!scan_data_empty(session))
+ mask |= (POLLIN | POLLRDNORM);
+ return mask;
+}
+
+
+/* Main switch loop for ioctl operations */
+static long fsl_pme2_scan_ioctl(struct file *fp, unsigned int cmd,
+ unsigned long arg)
+{
+ struct scan_session *session = fp->private_data;
+ int ret = 0;
+
+ switch (cmd) {
+
+ case PMEIO_GETSCAN:
+ return getscan_cmd(fp, session, (struct pme_scan_params *)arg);
+ break;
+
+ case PMEIO_SETSCAN:
+ return setscan_cmd(fp, session, (struct pme_scan_params *)arg);
+ break;
+
+ case PMEIO_RESETSEQ:
+ return resetseq_cmd(fp, session);
+ break;
+
+ case PMEIO_RESETRES:
+ return resetresidue_cmd(fp, session);
+ break;
+
+ case PMEIO_SCAN:
+ {
+ int ret;
+ struct pme_scan scan;
+
+ if (copy_from_user(&scan, (void __user *)arg, sizeof(scan)))
+ return -EFAULT;
+ ret = process_scan_cmd(fp, session, &scan.cmd, &scan.result, 1);
+ if (!ret) {
+ struct pme_scan_result __user *user_result =
+ &((struct pme_scan __user *)arg)->result;
+ ret = copy_to_user(user_result, &scan.result,
+ sizeof(*user_result));
+ }
+ return ret;
+ }
+ break;
+
+ case PMEIO_SCAN_W1:
+ {
+ struct pme_scan_cmd scan_cmd;
+
+ if (copy_from_user(&scan_cmd, (void __user *)arg,
+ sizeof(scan_cmd)))
+ return -EFAULT;
+ return process_scan_cmd(fp, session, &scan_cmd, NULL, 0);
+ }
+ break;
+
+ case PMEIO_SCAN_R1:
+ {
+ struct pme_scan_result result;
+ struct cmd_token *completed_cmd = NULL;
+ struct pme_scan_result __user *ur =
+ (struct pme_scan_result __user *)arg;
+ int ret;
+
+ if (copy_from_user(&result, (void __user *)arg,
+ sizeof(result)))
+ return -EFAULT;
+
+ /* Check to see if any results */
+ spin_lock(&session->completed_commands_lock);
+ if (!list_empty(&session->completed_commands)) {
+ completed_cmd = list_first_entry(
+ &session->completed_commands,
+ struct cmd_token,
+ completed_list);
+ list_del(&completed_cmd->completed_list);
+ session->completed_count--;
+ }
+ spin_unlock(&session->completed_commands_lock);
+ if (completed_cmd) {
+ ret = process_completed_token(fp, completed_cmd,
+ &result);
+ if (!ret)
+ ret = copy_to_user(ur, &result, sizeof(result));
+ return ret;
+ } else
+ return -EIO;
+ }
+ break;
+
+ case PMEIO_SCAN_Wn:
+ {
+ struct pme_scan_cmds scan_cmds;
+ int i, ret = 0;
+
+ /* Copy the command to kernel space */
+ if (copy_from_user(&scan_cmds, (void __user *)arg,
+ sizeof(scan_cmds)))
+ return -EFAULT;
+ PMEPRINFO("Received Wn for %d cmds\n", scan_cmds.num);
+ for (i = 0; i < scan_cmds.num; i++) {
+ struct pme_scan_cmd scan_cmd;
+
+ if (copy_from_user(&scan_cmd, &scan_cmds.cmds[i],
+ sizeof(scan_cmd))) {
+ pr_err("pme2_scan: Err with %d\n", i);
+ scan_cmds.num = i;
+ if (copy_to_user((void __user *)arg, &scan_cmds,
+ sizeof(scan_cmds))) {
+ return -EFAULT;
+ }
+ return -EFAULT;
+ }
+ ret = process_scan_cmd(fp, session, &scan_cmd, NULL, 0);
+ if (ret) {
+ pr_err("pme2_scan: Err with %d cmd %d\n",
+ i, ret);
+ scan_cmds.num = i;
+ if (copy_to_user((void *)arg, &scan_cmds,
+ sizeof(scan_cmds))) {
+ pr_err("Error copying to user data\n");
+ return -EFAULT;
+ }
+ return -EINTR;
+ }
+ }
+ return ret;
+ }
+ break;
+
+ case PMEIO_SCAN_Rn:
+ {
+ struct pme_scan_results results;
+ struct pme_scan_result result;
+ struct pme_scan_result __user *ur;
+ int i = 0, ret = 0;
+ struct cmd_token *completed_cmd = NULL;
+
+ /* Copy the command to kernel space */
+ if (copy_from_user(&results, (void __user *)arg,
+ sizeof(results)))
+ return -EFAULT;
+ ur = ((struct pme_scan_results __user *)arg)->results
+ PMEPRINFO("pme2_scan: Received Rn for %d res\n", results.num);
+ if (!results.num)
+ return 0;
+ do {
+ completed_cmd = NULL;
+ ret = 0;
+ /* Check to see if any results */
+ spin_lock(&session->completed_commands_lock);
+ if (!list_empty(&session->completed_commands)) {
+ /* Move to a different list */
+ PMEPRINFO("pme2_scan: Pop response\n");
+ completed_cmd = list_first_entry(
+ &session->completed_commands,
+ struct cmd_token,
+ completed_list);
+ list_del(&completed_cmd->completed_list);
+ session->completed_count--;
+ }
+ spin_unlock(&session->completed_commands_lock);
+ if (completed_cmd) {
+ if (copy_from_user(&result, (void __user *)ur+i,
+ sizeof(result)))
+ return -EFAULT;
+ ret = process_completed_token(fp, completed_cmd,
+ &result);
+ if (!ret)
+ ret = copy_to_user(ur, &result,
+ sizeof(struct pme_scan_result));
+ if (!ret) {
+ i++;
+ ur++;
+ }
+ }
+ } while (!ret && completed_cmd && (i != results.num));
+
+ if (i != results.num) {
+ PMEPRINFO("pme2_scan: Only filled %d responses\n", i);
+ results.num = i;
+ PMEPRINFO("pme2_scan: results.num = %d\n", results.num);
+ if (copy_to_user((void __user *)arg, &results,
+ sizeof(struct pme_scan_results))) {
+ pr_err("Error copying to user data\n");
+ return -EFAULT;
+ }
+ }
+ return ret;
+ }
+ break;
+
+ case PMEIO_RELEASE_BUFS:
+ return -EINVAL;
+ break;
+
+#ifdef CONFIG_COMPAT
+ case PMEIO_SCAN32:
+ {
+ int ret;
+ struct compat_pme_scan scan32;
+ struct compat_pme_scan __user *user_scan = compat_ptr(arg);
+ struct pme_scan scan;
+
+ if (copy_from_user(&scan32, user_scan, sizeof(scan32)))
+ return -EFAULT;
+ /* Convert to 64-bit structs */
+ compat_to_scan_cmd(&scan.cmd, &scan32.cmd);
+ compat_to_scan_result(&scan.result, &scan32.result);
+
+ ret = process_scan_cmd(fp, session, &scan.cmd, &scan.result, 1);
+ if (!ret) {
+ struct compat_pme_scan_result __user *user_result =
+ &user_scan->result;
+ /* Convert to 32-bit struct */
+ scan_result_to_compat(&scan32.result, &scan.result);
+ ret = copy_to_user(user_result, &scan32.result,
+ sizeof(*user_result));
+ }
+ return ret;
+ }
+ break;
+
+ case PMEIO_SCAN_W132:
+ {
+ struct compat_pme_scan_cmd scan_cmd32;
+ struct pme_scan_cmd scan_cmd;
+
+ if (copy_from_user(&scan_cmd32, compat_ptr(arg),
+ sizeof(scan_cmd32)))
+ return -EFAULT;
+ /* Convert to 64-bit struct */
+ compat_to_scan_cmd(&scan_cmd, &scan_cmd32);
+ return process_scan_cmd(fp, session, &scan_cmd, NULL, 0);
+ }
+ break;
+
+ case PMEIO_SCAN_R132:
+ {
+ struct compat_pme_scan_result result32;
+ struct pme_scan_result result;
+ struct cmd_token *completed_cmd = NULL;
+ struct compat_pme_scan_result __user *ur = compat_ptr(arg);
+ int ret;
+
+ if (copy_from_user(&result32, (void __user *)arg,
+ sizeof(result32)))
+ return -EFAULT;
+ /* copy to 64-bit structure */
+ compat_to_scan_result(&result, &result32);
+
+ /* Check to see if any results */
+ spin_lock(&session->completed_commands_lock);
+ if (!list_empty(&session->completed_commands)) {
+ completed_cmd = list_first_entry(
+ &session->completed_commands,
+ struct cmd_token,
+ completed_list);
+ list_del(&completed_cmd->completed_list);
+ session->completed_count--;
+ }
+ spin_unlock(&session->completed_commands_lock);
+ if (completed_cmd) {
+ ret = process_completed_token(fp, completed_cmd,
+ &result);
+ scan_result_to_compat(&result32, &result);
+ ret = copy_to_user(ur, &result32, sizeof(result32));
+ } else
+ return -EIO;
+ }
+ break;
+
+ case PMEIO_SCAN_Wn32:
+ {
+ struct compat_pme_scan_cmds scan_cmds32;
+ int i, ret = 0;
+
+ /* Copy the command to kernel space */
+ if (copy_from_user(&scan_cmds32, compat_ptr(arg),
+ sizeof(scan_cmds32)))
+ return -EFAULT;
+ PMEPRINFO("Received Wn for %d cmds\n", scan_cmds32.num);
+ for (i = 0; i < scan_cmds32.num; i++) {
+ struct pme_scan_cmd scan_cmd;
+ struct compat_pme_scan_cmd __user *u_scan_cmd32;
+ struct compat_pme_scan_cmd scan_cmd32;
+
+ u_scan_cmd32 = compat_ptr(scan_cmds32.cmds);
+ u_scan_cmd32 += i;
+
+ if (copy_from_user(&scan_cmd32, u_scan_cmd32,
+ sizeof(scan_cmd32))) {
+ pr_err("pme2_scan: Err with %d\n", i);
+ scan_cmds32.num = i;
+ if (copy_to_user(compat_ptr(arg), &scan_cmds32,
+ sizeof(scan_cmds32)))
+ return -EFAULT;
+ return -EFAULT;
+ }
+ compat_to_scan_cmd(&scan_cmd, &scan_cmd32);
+ ret = process_scan_cmd(fp, session, &scan_cmd, NULL, 0);
+ if (ret) {
+ pr_err("pme2_scan: Err with %d cmd %d\n",
+ i, ret);
+ scan_cmds32.num = i;
+ if (copy_to_user(compat_ptr(arg), &scan_cmds32,
+ sizeof(scan_cmds32)))
+ return -EFAULT;
+ return -EINTR;
+ }
+ }
+ return ret;
+ }
+ break;
+
+ case PMEIO_SCAN_Rn32:
+ {
+ struct compat_pme_scan_results results32;
+ int i = 0, ret = 0;
+ struct cmd_token *completed_cmd = NULL;
+ struct compat_pme_scan_result __user *ur;
+
+ /* Copy the command to kernel space */
+ if (copy_from_user(&results32, compat_ptr(arg),
+ sizeof(results32)))
+ return -EFAULT;
+ ur = compat_ptr(results32.results);
+ PMEPRINFO("pme2_scan: Rx Rn for %d res\n", results32.num);
+ if (!results32.num)
+ return 0;
+ do {
+ completed_cmd = NULL;
+ ret = 0;
+ /* Check to see if any results */
+ spin_lock(&session->completed_commands_lock);
+ if (!list_empty(&session->completed_commands)) {
+ /* Move to a different list */
+ PMEPRINFO("pme2_scan: Pop response\n");
+ completed_cmd = list_first_entry(
+ &session->completed_commands,
+ struct cmd_token,
+ completed_list);
+ list_del(&completed_cmd->completed_list);
+ session->completed_count--;
+ }
+ spin_unlock(&session->completed_commands_lock);
+ if (completed_cmd) {
+ struct compat_pme_scan_result l_result32;
+ struct pme_scan_result result;
+
+ if (copy_from_user(&l_result32, ur+i,
+ sizeof(l_result32)))
+ return -EFAULT;
+ compat_to_scan_result(&result, &l_result32);
+ ret = process_completed_token(fp, completed_cmd,
+ &result);
+ scan_result_to_compat(&l_result32, &result);
+ ret = copy_to_user(ur+i, &l_result32,
+ sizeof(l_result32));
+ if (!ret)
+ i++;
+ }
+ } while (!ret && completed_cmd && (i != results32.num));
+
+ if (i != results32.num) {
+ PMEPRINFO("pme2_scan: Only filled %d responses\n", i);
+ results32.num = i;
+ PMEPRINFO("pme2_scan: results32.num = %d\n",
+ results32.num);
+ if (copy_to_user(compat_ptr(arg), &results32,
+ sizeof(struct pme_scan_results))) {
+ pr_err("Error copying to user data\n");
+ return -EFAULT;
+ }
+ }
+ return ret;
+ }
+ break;
+#endif /* CONFIG_COMPAT */
+
+ default:
+ pr_err("UNKNOWN IOCTL cmd 0x%x\n", cmd);
+ return -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static const struct file_operations fsl_pme2_scan_fops = {
+ .owner = THIS_MODULE,
+ .open = fsl_pme2_scan_open,
+ .release = fsl_pme2_scan_close,
+ .poll = fsl_pme2_scan_poll,
+ .unlocked_ioctl = fsl_pme2_scan_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = fsl_pme2_scan_ioctl,
+#endif
+};
+
+static struct miscdevice fsl_pme2_scan_dev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = PME_DEV_SCAN_NODE,
+ .fops = &fsl_pme2_scan_fops
+};
+
+static int __init fsl_pme2_scan_init(void)
+{
+ int err = 0;
+
+ pr_info("Freescale pme2 scan driver\n");
+ err = misc_register(&fsl_pme2_scan_dev);
+ if (err) {
+ pr_err("fsl-pme2-scan: cannot register device\n");
+ return err;
+ }
+ pr_info("fsl-pme2-scan: device %s registered\n",
+ fsl_pme2_scan_dev.name);
+ return 0;
+}
+
+static void __exit fsl_pme2_scan_exit(void)
+{
+ int err = misc_deregister(&fsl_pme2_scan_dev);
+ if (err)
+ pr_err("Failed to deregister device %s code %d\n",
+ fsl_pme2_scan_dev.name, err);
+ pr_info("device %s deregistered\n", fsl_pme2_scan_dev.name);
+}
+
+module_init(fsl_pme2_scan_init);
+module_exit(fsl_pme2_scan_exit);
+
+MODULE_AUTHOR("Jeffrey Ladouceur <jeffrey.ladouceur@freescale.com>");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("Freescale PME2 scan driver");
diff --git a/drivers/staging/fsl_pme2/pme2_sys.h b/drivers/staging/fsl_pme2/pme2_sys.h
new file mode 100644
index 0000000..5a122cf
--- /dev/null
+++ b/drivers/staging/fsl_pme2/pme2_sys.h
@@ -0,0 +1,63 @@
+/* Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/bootmem.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/of_platform.h>
+#include <linux/kthread.h>
+#include <linux/memblock.h>
+#include <linux/completion.h>
+#include <linux/log2.h>
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/device.h>
+#include <linux/uio_driver.h>
+#include <linux/smp.h>
+#include <sysdev/fsl_soc.h>
+#include <linux/fsl_hypervisor.h>
+#include <linux/fsl_bman.h>
+#include <linux/fsl_pme.h>
+
+int pme2_create_sysfs_dev_files(struct platform_device *ofdev);
+void pme2_remove_sysfs_dev_files(struct platform_device *ofdev);
+void accumulator_update_interval(u32 interval);
diff --git a/drivers/staging/fsl_pme2/pme2_sysfs.c b/drivers/staging/fsl_pme2/pme2_sysfs.c
new file mode 100644
index 0000000..acd0fd3
--- /dev/null
+++ b/drivers/staging/fsl_pme2/pme2_sysfs.c
@@ -0,0 +1,566 @@
+/* Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADIED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "pme2_regs.h"
+#include "pme2_private.h"
+
+#define MAX_ACCUMULATOR_INTERVAL 10000
+extern u32 pme_stat_interval;
+
+/*
+ * The pme sysfs contains the following types of attributes
+ * 1) root level: general pme confuration
+ * 2) bsc: bufferpool size configuration
+ * 3) stats: pme statistics
+ */
+static ssize_t pme_store(struct device *dev, struct device_attribute *dev_attr,
+ const char *buf, size_t count, enum pme_attr attr)
+{
+ unsigned long val;
+ size_t ret;
+ if (kstrtoul(buf, 0, &val)) {
+ dev_dbg(dev, "invalid input %s\n", buf);
+ return -EINVAL;
+ }
+ ret = pme_attr_set(attr, val);
+ if (ret) {
+ dev_err(dev, "attr_set err attr=%u, val=%lu\n", attr, val);
+ return ret;
+ }
+ return count;
+}
+
+static ssize_t pme_show(struct device *dev, struct device_attribute *dev_attr,
+ char *buf, enum pme_attr attr, const char *fmt)
+{
+ u32 data;
+ int ret;
+
+ ret = pme_attr_get(attr, &data);
+ if (!ret)
+ return snprintf(buf, PAGE_SIZE, fmt, data);
+ return ret;
+}
+
+
+static ssize_t pme_stat_show(struct device *dev,
+ struct device_attribute *dev_attr, char *buf, enum pme_attr attr)
+{
+ u64 data = 0;
+ int ret = 0;
+
+ ret = pme_stat_get(attr, &data, 0);
+ if (!ret)
+ return snprintf(buf, PAGE_SIZE, "%llu\n", data);
+ else
+ return ret;
+}
+
+static ssize_t pme_stat_store(struct device *dev,
+ struct device_attribute *dev_attr, const char *buf,
+ size_t count, enum pme_attr attr)
+{
+ unsigned long val;
+ u64 data = 0;
+ size_t ret = 0;
+ if (kstrtoul(buf, 0, &val)) {
+ pr_err("pme: invalid input %s\n", buf);
+ return -EINVAL;
+ }
+ if (val) {
+ pr_err("pme: invalid input %s\n", buf);
+ return -EINVAL;
+ }
+ ret = pme_stat_get(attr, &data, 1);
+ return count;
+}
+
+
+#define PME_SYSFS_ATTR(pme_attr, perm, showhex) \
+static ssize_t pme_store_##pme_attr(struct device *dev, \
+ struct device_attribute *attr, const char *buf, size_t count) \
+{ \
+ return pme_store(dev, attr, buf, count, pme_attr_##pme_attr);\
+} \
+static ssize_t pme_show_##pme_attr(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ return pme_show(dev, attr, buf, pme_attr_##pme_attr, showhex);\
+} \
+static DEVICE_ATTR(pme_attr, perm, pme_show_##pme_attr, pme_store_##pme_attr);
+
+
+#define PME_SYSFS_STAT_ATTR(pme_attr, perm) \
+static ssize_t pme_store_##pme_attr(struct device *dev, \
+ struct device_attribute *attr, const char *buf, size_t count) \
+{ \
+ return pme_stat_store(dev, attr, buf, count, pme_attr_##pme_attr);\
+} \
+static ssize_t pme_show_##pme_attr(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ return pme_stat_show(dev, attr, buf, pme_attr_##pme_attr);\
+} \
+static DEVICE_ATTR(pme_attr, perm, pme_show_##pme_attr, pme_store_##pme_attr);
+
+
+#define PME_SYSFS_BSC_ATTR(bsc_id, perm, showhex) \
+static ssize_t pme_store_bsc_##bsc_id(struct device *dev,\
+ struct device_attribute *attr, const char *buf, size_t count) \
+{ \
+ return pme_store(dev, attr, buf, count, pme_attr_bsc(bsc_id));\
+} \
+static ssize_t pme_show_bsc_##bsc_id(struct device *dev,\
+ struct device_attribute *attr, char *buf) \
+{ \
+ return pme_show(dev, attr, buf, pme_attr_bsc(bsc_id), showhex);\
+} \
+static DEVICE_ATTR(bsc_id, perm, pme_show_bsc_##bsc_id, \
+ pme_store_bsc_##bsc_id);
+
+/* Statistics Ctrl: update interval */
+static ssize_t pme_store_update_interval(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long val;
+
+ if (!pme2_have_control()) {
+ PMEPRERR("not on ctrl-plane\n");
+ return -ENODEV;
+ }
+ if (kstrtoul(buf, 0, &val)) {
+ dev_info(dev, "invalid input %s\n", buf);
+ return -EINVAL;
+ }
+ if (val > MAX_ACCUMULATOR_INTERVAL) {
+ dev_info(dev, "invalid input %s\n", buf);
+ return -ERANGE;
+ }
+ accumulator_update_interval(val);
+ return count;
+}
+static ssize_t pme_show_update_interval(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ if (!pme2_have_control())
+ return -ENODEV;
+ return snprintf(buf, PAGE_SIZE, "%u\n", pme_stat_interval);
+}
+
+#define FMT_0HEX "0x%08x\n"
+#define FMT_HEX "0x%x\n"
+#define FMT_DEC "%u\n"
+#define PRIV_RO S_IRUSR
+#define PRIV_RW (S_IRUSR | S_IWUSR)
+
+/* Register Interfaces */
+/* read-write; */
+PME_SYSFS_ATTR(efqc_int, PRIV_RW, FMT_DEC);
+PME_SYSFS_ATTR(sw_db, PRIV_RW, FMT_DEC);
+PME_SYSFS_ATTR(dmcr, PRIV_RW, FMT_0HEX);
+PME_SYSFS_ATTR(smcr, PRIV_RW, FMT_0HEX);
+PME_SYSFS_ATTR(famcr, PRIV_RW, FMT_0HEX);
+PME_SYSFS_ATTR(kvlts, PRIV_RW, FMT_DEC);
+PME_SYSFS_ATTR(max_chain_length, PRIV_RW, FMT_DEC);
+PME_SYSFS_ATTR(pattern_range_counter_idx, PRIV_RW, FMT_0HEX);
+PME_SYSFS_ATTR(pattern_range_counter_mask, PRIV_RW, FMT_0HEX);
+PME_SYSFS_ATTR(max_allowed_test_line_per_pattern, PRIV_RW, FMT_DEC);
+PME_SYSFS_ATTR(max_pattern_matches_per_sui, PRIV_RW, FMT_DEC);
+PME_SYSFS_ATTR(max_pattern_evaluations_per_sui, PRIV_RW, FMT_DEC);
+PME_SYSFS_ATTR(report_length_limit, PRIV_RW, FMT_DEC);
+PME_SYSFS_ATTR(end_of_simple_sui_report, PRIV_RW, FMT_DEC);
+PME_SYSFS_ATTR(aim, PRIV_RW, FMT_DEC);
+PME_SYSFS_ATTR(end_of_sui_reaction_ptr, PRIV_RW, FMT_DEC);
+PME_SYSFS_ATTR(sre_pscl, PRIV_RW, FMT_DEC);
+PME_SYSFS_ATTR(sre_max_block_num, PRIV_RW, FMT_DEC);
+PME_SYSFS_ATTR(sre_max_instruction_limit, PRIV_RW, FMT_DEC);
+PME_SYSFS_ATTR(esr, PRIV_RW, FMT_0HEX);
+PME_SYSFS_ATTR(pehd, PRIV_RW, FMT_0HEX);
+PME_SYSFS_ATTR(ecc1bes, PRIV_RW, FMT_0HEX);
+PME_SYSFS_ATTR(ecc2bes, PRIV_RW, FMT_0HEX);
+PME_SYSFS_ATTR(miace, PRIV_RW, FMT_0HEX);
+PME_SYSFS_ATTR(miacr, PRIV_RW, FMT_0HEX);
+PME_SYSFS_ATTR(cdcr, PRIV_RW, FMT_0HEX);
+PME_SYSFS_ATTR(pmtr, PRIV_RW, FMT_DEC);
+
+/* read-only; */
+PME_SYSFS_ATTR(max_pdsr_index, PRIV_RO, FMT_DEC);
+PME_SYSFS_ATTR(sre_context_size, PRIV_RO, FMT_DEC);
+PME_SYSFS_ATTR(sre_rule_num, PRIV_RO, FMT_DEC);
+PME_SYSFS_ATTR(sre_session_ctx_num, PRIV_RO, FMT_DEC);
+PME_SYSFS_ATTR(sre_max_index_size, PRIV_RO, FMT_DEC);
+PME_SYSFS_ATTR(sre_max_offset_ctrl, PRIV_RO, FMT_DEC);
+PME_SYSFS_ATTR(src_id, PRIV_RO, FMT_DEC);
+PME_SYSFS_ATTR(liodnr, PRIV_RO, FMT_DEC);
+PME_SYSFS_ATTR(rev1, PRIV_RO, FMT_0HEX);
+PME_SYSFS_ATTR(rev2, PRIV_RO, FMT_0HEX);
+PME_SYSFS_ATTR(isr, PRIV_RO, FMT_0HEX);
+PME_SYSFS_ATTR(ecr0, PRIV_RO, FMT_0HEX);
+PME_SYSFS_ATTR(ecr1, PRIV_RO, FMT_0HEX);
+PME_SYSFS_ATTR(pmstat, PRIV_RO, FMT_0HEX);
+PME_SYSFS_ATTR(eccaddr, PRIV_RO, FMT_0HEX);
+PME_SYSFS_ATTR(ecccode, PRIV_RO, FMT_0HEX);
+PME_SYSFS_ATTR(faconf, PRIV_RO, FMT_0HEX);
+PME_SYSFS_ATTR(pdsrbah, PRIV_RO, FMT_0HEX);
+PME_SYSFS_ATTR(pdsrbal, PRIV_RO, FMT_0HEX);
+PME_SYSFS_ATTR(scbarh, PRIV_RO, FMT_0HEX);
+PME_SYSFS_ATTR(scbarl, PRIV_RO, FMT_0HEX);
+
+
+/* Buffer Pool Size Configuration */
+PME_SYSFS_BSC_ATTR(0, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(1, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(2, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(3, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(4, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(5, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(6, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(7, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(8, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(9, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(10, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(11, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(12, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(13, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(14, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(15, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(16, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(17, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(18, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(19, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(20, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(21, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(22, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(23, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(24, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(25, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(26, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(27, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(28, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(29, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(30, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(31, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(32, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(33, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(34, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(35, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(36, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(37, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(38, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(39, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(40, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(41, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(42, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(43, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(44, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(45, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(46, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(47, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(48, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(49, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(50, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(51, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(52, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(53, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(54, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(55, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(56, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(57, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(58, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(59, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(60, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(61, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(62, PRIV_RW, FMT_DEC);
+PME_SYSFS_BSC_ATTR(63, PRIV_RW, FMT_DEC);
+
+/* Stats Counters*/
+PME_SYSFS_STAT_ATTR(trunci, PRIV_RW);
+PME_SYSFS_STAT_ATTR(rbc, PRIV_RW);
+PME_SYSFS_STAT_ATTR(tbt0ecc1ec, PRIV_RW);
+PME_SYSFS_STAT_ATTR(tbt1ecc1ec, PRIV_RW);
+PME_SYSFS_STAT_ATTR(vlt0ecc1ec, PRIV_RW);
+PME_SYSFS_STAT_ATTR(vlt1ecc1ec, PRIV_RW);
+PME_SYSFS_STAT_ATTR(cmecc1ec, PRIV_RW);
+PME_SYSFS_STAT_ATTR(dxcmecc1ec, PRIV_RW);
+PME_SYSFS_STAT_ATTR(dxemecc1ec, PRIV_RW);
+PME_SYSFS_STAT_ATTR(stnib, PRIV_RW);
+PME_SYSFS_STAT_ATTR(stnis, PRIV_RW);
+PME_SYSFS_STAT_ATTR(stnth1, PRIV_RW);
+PME_SYSFS_STAT_ATTR(stnth2, PRIV_RW);
+PME_SYSFS_STAT_ATTR(stnthv, PRIV_RW);
+PME_SYSFS_STAT_ATTR(stnths, PRIV_RW);
+PME_SYSFS_STAT_ATTR(stnch, PRIV_RW);
+PME_SYSFS_STAT_ATTR(stnpm, PRIV_RW);
+PME_SYSFS_STAT_ATTR(stns1m, PRIV_RW);
+PME_SYSFS_STAT_ATTR(stnpmr, PRIV_RW);
+PME_SYSFS_STAT_ATTR(stndsr, PRIV_RW);
+PME_SYSFS_STAT_ATTR(stnesr, PRIV_RW);
+PME_SYSFS_STAT_ATTR(stns1r, PRIV_RW);
+PME_SYSFS_STAT_ATTR(stnob, PRIV_RW);
+PME_SYSFS_STAT_ATTR(mia_byc, PRIV_RW);
+PME_SYSFS_STAT_ATTR(mia_blc, PRIV_RW);
+
+/* Stats Control */
+PME_SYSFS_ATTR(tbt0ecc1th, PRIV_RW, FMT_DEC);
+PME_SYSFS_ATTR(tbt1ecc1th, PRIV_RW, FMT_DEC);
+PME_SYSFS_ATTR(vlt0ecc1th, PRIV_RW, FMT_DEC);
+PME_SYSFS_ATTR(vlt1ecc1th, PRIV_RW, FMT_DEC);
+PME_SYSFS_ATTR(cmecc1th, PRIV_RW, FMT_DEC);
+PME_SYSFS_ATTR(dxcmecc1th, PRIV_RW, FMT_DEC);
+PME_SYSFS_ATTR(dxemecc1th, PRIV_RW, FMT_DEC);
+
+static DEVICE_ATTR(update_interval, (S_IRUSR | S_IWUSR),
+ pme_show_update_interval, pme_store_update_interval);
+
+static struct attribute *pme_dev_bsc_attributes[] = {
+ &dev_attr_0.attr,
+ &dev_attr_1.attr,
+ &dev_attr_2.attr,
+ &dev_attr_3.attr,
+ &dev_attr_4.attr,
+ &dev_attr_5.attr,
+ &dev_attr_6.attr,
+ &dev_attr_7.attr,
+ &dev_attr_8.attr,
+ &dev_attr_9.attr,
+ &dev_attr_10.attr,
+ &dev_attr_11.attr,
+ &dev_attr_12.attr,
+ &dev_attr_13.attr,
+ &dev_attr_14.attr,
+ &dev_attr_15.attr,
+ &dev_attr_16.attr,
+ &dev_attr_17.attr,
+ &dev_attr_18.attr,
+ &dev_attr_19.attr,
+ &dev_attr_20.attr,
+ &dev_attr_21.attr,
+ &dev_attr_22.attr,
+ &dev_attr_23.attr,
+ &dev_attr_24.attr,
+ &dev_attr_25.attr,
+ &dev_attr_26.attr,
+ &dev_attr_27.attr,
+ &dev_attr_28.attr,
+ &dev_attr_29.attr,
+ &dev_attr_30.attr,
+ &dev_attr_31.attr,
+ &dev_attr_32.attr,
+ &dev_attr_33.attr,
+ &dev_attr_34.attr,
+ &dev_attr_35.attr,
+ &dev_attr_36.attr,
+ &dev_attr_37.attr,
+ &dev_attr_38.attr,
+ &dev_attr_39.attr,
+ &dev_attr_40.attr,
+ &dev_attr_41.attr,
+ &dev_attr_42.attr,
+ &dev_attr_43.attr,
+ &dev_attr_44.attr,
+ &dev_attr_45.attr,
+ &dev_attr_46.attr,
+ &dev_attr_47.attr,
+ &dev_attr_48.attr,
+ &dev_attr_49.attr,
+ &dev_attr_50.attr,
+ &dev_attr_51.attr,
+ &dev_attr_52.attr,
+ &dev_attr_53.attr,
+ &dev_attr_54.attr,
+ &dev_attr_55.attr,
+ &dev_attr_56.attr,
+ &dev_attr_57.attr,
+ &dev_attr_58.attr,
+ &dev_attr_59.attr,
+ &dev_attr_60.attr,
+ &dev_attr_61.attr,
+ &dev_attr_62.attr,
+ &dev_attr_63.attr,
+ NULL
+};
+
+static struct attribute *pme_dev_attributes[] = {
+ &dev_attr_efqc_int.attr,
+ &dev_attr_sw_db.attr,
+ &dev_attr_dmcr.attr,
+ &dev_attr_smcr.attr,
+ &dev_attr_famcr.attr,
+ &dev_attr_kvlts.attr,
+ &dev_attr_max_chain_length.attr,
+ &dev_attr_pattern_range_counter_idx.attr,
+ &dev_attr_pattern_range_counter_mask.attr,
+ &dev_attr_max_allowed_test_line_per_pattern.attr,
+ &dev_attr_max_pdsr_index.attr,
+ &dev_attr_max_pattern_matches_per_sui.attr,
+ &dev_attr_max_pattern_evaluations_per_sui.attr,
+ &dev_attr_report_length_limit.attr,
+ &dev_attr_end_of_simple_sui_report.attr,
+ &dev_attr_aim.attr,
+ &dev_attr_sre_context_size.attr,
+ &dev_attr_sre_rule_num.attr,
+ &dev_attr_sre_session_ctx_num.attr,
+ &dev_attr_end_of_sui_reaction_ptr.attr,
+ &dev_attr_sre_pscl.attr,
+ &dev_attr_sre_max_block_num.attr,
+ &dev_attr_sre_max_instruction_limit.attr,
+ &dev_attr_sre_max_index_size.attr,
+ &dev_attr_sre_max_offset_ctrl.attr,
+ &dev_attr_src_id.attr,
+ &dev_attr_liodnr.attr,
+ &dev_attr_rev1.attr,
+ &dev_attr_rev2.attr,
+ &dev_attr_isr.attr,
+ &dev_attr_ecr0.attr,
+ &dev_attr_ecr1.attr,
+ &dev_attr_esr.attr,
+ &dev_attr_pmstat.attr,
+ &dev_attr_pehd.attr,
+ &dev_attr_ecc1bes.attr,
+ &dev_attr_ecc2bes.attr,
+ &dev_attr_eccaddr.attr,
+ &dev_attr_ecccode.attr,
+ &dev_attr_miace.attr,
+ &dev_attr_miacr.attr,
+ &dev_attr_cdcr.attr,
+ &dev_attr_pmtr.attr,
+ &dev_attr_faconf.attr,
+ &dev_attr_pdsrbah.attr,
+ &dev_attr_pdsrbal.attr,
+ &dev_attr_scbarh.attr,
+ &dev_attr_scbarl.attr,
+ NULL
+};
+
+static struct attribute *pme_dev_stats_counter_attributes[] = {
+ &dev_attr_trunci.attr,
+ &dev_attr_rbc.attr,
+ &dev_attr_tbt0ecc1ec.attr,
+ &dev_attr_tbt1ecc1ec.attr,
+ &dev_attr_vlt0ecc1ec.attr,
+ &dev_attr_vlt1ecc1ec.attr,
+ &dev_attr_cmecc1ec.attr,
+ &dev_attr_dxcmecc1ec.attr,
+ &dev_attr_dxemecc1ec.attr,
+ &dev_attr_stnib.attr,
+ &dev_attr_stnis.attr,
+ &dev_attr_stnth1.attr,
+ &dev_attr_stnth2.attr,
+ &dev_attr_stnthv.attr,
+ &dev_attr_stnths.attr,
+ &dev_attr_stnch.attr,
+ &dev_attr_stnpm.attr,
+ &dev_attr_stns1m.attr,
+ &dev_attr_stnpmr.attr,
+ &dev_attr_stndsr.attr,
+ &dev_attr_stnesr.attr,
+ &dev_attr_stns1r.attr,
+ &dev_attr_stnob.attr,
+ &dev_attr_mia_byc.attr,
+ &dev_attr_mia_blc.attr,
+ NULL
+};
+
+static struct attribute *pme_dev_stats_ctrl_attributes[] = {
+ &dev_attr_update_interval.attr,
+ &dev_attr_tbt0ecc1th.attr,
+ &dev_attr_tbt1ecc1th.attr,
+ &dev_attr_vlt0ecc1th.attr,
+ &dev_attr_vlt1ecc1th.attr,
+ &dev_attr_cmecc1th.attr,
+ &dev_attr_dxcmecc1th.attr,
+ &dev_attr_dxemecc1th.attr,
+ NULL
+};
+
+/* root level */
+static const struct attribute_group pme_dev_attr_grp = {
+ .name = NULL, /* put in device directory */
+ .attrs = pme_dev_attributes
+};
+
+/* root/bsc */
+static struct attribute_group pme_dev_bsc_attr_grp = {
+ .name = "bsc",
+ .attrs = pme_dev_bsc_attributes
+};
+
+/* root/stats */
+static struct attribute_group pme_dev_stats_counters_attr_grp = {
+ .name = "stats",
+ .attrs = pme_dev_stats_counter_attributes
+};
+
+/* root/stats_ctrl */
+static struct attribute_group pme_dev_stats_ctrl_attr_grp = {
+ .name = "stats_ctrl",
+ .attrs = pme_dev_stats_ctrl_attributes
+};
+
+
+int pme2_create_sysfs_dev_files(struct platform_device *ofdev)
+{
+ int ret;
+
+ ret = sysfs_create_group(&ofdev->dev.kobj, &pme_dev_attr_grp);
+ if (ret)
+ goto done;
+ ret = sysfs_create_group(&ofdev->dev.kobj, &pme_dev_bsc_attr_grp);
+ if (ret)
+ goto del_group_1;
+ ret = sysfs_create_group(&ofdev->dev.kobj,
+ &pme_dev_stats_counters_attr_grp);
+ if (ret)
+ goto del_group_2;
+ ret = sysfs_create_group(&ofdev->dev.kobj,
+ &pme_dev_stats_ctrl_attr_grp);
+ if (ret)
+ goto del_group_3;
+ goto done;
+del_group_3:
+ sysfs_remove_group(&ofdev->dev.kobj, &pme_dev_stats_counters_attr_grp);
+del_group_2:
+ sysfs_remove_group(&ofdev->dev.kobj, &pme_dev_bsc_attr_grp);
+del_group_1:
+ sysfs_remove_group(&ofdev->dev.kobj, &pme_dev_attr_grp);
+done:
+ if (ret)
+ dev_err(&ofdev->dev,
+ "Cannot create dev attributes ret=%d\n", ret);
+ return ret;
+}
+
+void pme2_remove_sysfs_dev_files(struct platform_device *ofdev)
+{
+ sysfs_remove_group(&ofdev->dev.kobj, &pme_dev_stats_ctrl_attr_grp);
+ sysfs_remove_group(&ofdev->dev.kobj, &pme_dev_stats_counters_attr_grp);
+ sysfs_remove_group(&ofdev->dev.kobj, &pme_dev_bsc_attr_grp);
+ sysfs_remove_group(&ofdev->dev.kobj, &pme_dev_attr_grp);
+}
diff --git a/drivers/staging/fsl_pme2/pme2_test.h b/drivers/staging/fsl_pme2/pme2_test.h
new file mode 100644
index 0000000..89471cb
--- /dev/null
+++ b/drivers/staging/fsl_pme2/pme2_test.h
@@ -0,0 +1,74 @@
+/* Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "pme2_sys.h"
+
+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 & ~(unsigned long)15;
+ unsigned long end = (p + sz + 15) & ~(unsigned long)15;
+ const unsigned char *c = ptr;
+ __hexdump(start, end, p, sz, c);
+}
+
+int pme2_sample_db(void);
+int pme2_clear_sample_db(void);
diff --git a/drivers/staging/fsl_pme2/pme2_test_high.c b/drivers/staging/fsl_pme2/pme2_test_high.c
new file mode 100644
index 0000000..b29ce91
--- /dev/null
+++ b/drivers/staging/fsl_pme2/pme2_test_high.c
@@ -0,0 +1,237 @@
+/* Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "pme2_test.h"
+
+MODULE_AUTHOR("Geoff Thorpe");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("FSL PME2 (p4080) high-level self-test");
+
+/* Default Flow Context State */
+static u8 fl_ctx_exp[] = {
+ 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00
+};
+
+void scan_cb(struct pme_ctx *ctx, const struct qm_fd *fd,
+ struct pme_ctx_token *token)
+{
+ hexdump(fd, sizeof(*fd));
+}
+
+struct ctrl_op {
+ struct pme_ctx_ctrl_token ctx_ctr;
+ struct completion cb_done;
+ enum pme_status cmd_status;
+ u8 res_flag;
+};
+
+static void ctrl_cb(struct pme_ctx *ctx, const struct qm_fd *fd,
+ struct pme_ctx_ctrl_token *token)
+{
+ struct ctrl_op *ctrl = (struct ctrl_op *)token;
+ pr_info("pme2_test_high: ctrl_cb() invoked, fd;!\n");
+ ctrl->cmd_status = pme_fd_res_status(fd);
+ ctrl->res_flag = pme_fd_res_flags(fd);
+ hexdump(fd, sizeof(*fd));
+ complete(&ctrl->cb_done);
+}
+
+
+#define POST_CTRL(val) \
+do { \
+ if (ret) \
+ val = -1;\
+ else if (pme_ctx_is_dead(&ctx))\
+ val = -1;\
+ else if (ctx_ctrl.cmd_status)\
+ val = -1;\
+ else if (ctx_ctrl.res_flag)\
+ val = -1;\
+} while (0)
+
+void pme2_test_high(void)
+{
+ int post_ctrl = 0;
+ struct pme_flow flow;
+ struct qm_fqd_stashing stashing;
+ struct pme_ctx ctx = {
+ .cb = scan_cb
+ };
+ int ret;
+ struct ctrl_op ctx_ctrl = {
+ .ctx_ctr.cb = ctrl_cb,
+ .cmd_status = 0,
+ .res_flag = 0
+ };
+ struct cpumask backup_mask = current->cpus_allowed;
+ struct cpumask new_mask = *qman_affine_cpus();
+
+ pr_info("PME2: high-level test starting\n");
+
+ cpumask_and(&new_mask, &new_mask, bman_affine_cpus());
+ ret = set_cpus_allowed_ptr(current, &new_mask);
+ if (ret) {
+ post_ctrl = -1;
+ pr_info("PME2: test high: can't set cpumask\n");
+ goto done;
+ }
+
+ pme_sw_flow_init(&flow);
+ init_completion(&ctx_ctrl.cb_done);
+ ret = pme_ctx_init(&ctx, PME_CTX_FLAG_LOCAL, 0, 4, 4, 0, NULL);
+ POST_CTRL(post_ctrl);
+ if (post_ctrl)
+ goto restore_mask;
+
+ /* enable the context */
+ pme_ctx_enable(&ctx);
+ pr_info("PME2: pme_ctx_enable done\n");
+ ret = pme_ctx_ctrl_update_flow(&ctx, PME_CTX_OP_WAIT | PME_CMD_FCW_ALL,
+ &flow, &ctx_ctrl.ctx_ctr);
+ pr_info("PME2: pme_ctx_ctrl_update_flow done\n");
+ wait_for_completion(&ctx_ctrl.cb_done);
+ POST_CTRL(post_ctrl);
+ if (post_ctrl)
+ goto disable_ctx;
+ /* read back flow settings */
+ ret = pme_ctx_ctrl_read_flow(&ctx, PME_CTX_OP_WAIT, &flow,
+ &ctx_ctrl.ctx_ctr);
+ pr_info("PME2: pme_ctx_ctrl_read_flow done\n");
+ wait_for_completion(&ctx_ctrl.cb_done);
+ POST_CTRL(post_ctrl);
+ if (post_ctrl)
+ goto disable_ctx;
+ if (memcmp(&flow, fl_ctx_exp, sizeof(flow))) {
+ pr_info("Default Flow Context Read FAIL\n");
+ pr_info("Expected:\n");
+ hexdump(fl_ctx_exp, sizeof(fl_ctx_exp));
+ pr_info("Received:\n");
+ hexdump(&flow, sizeof(flow));
+ post_ctrl = -1;
+ goto disable_ctx;
+ } else
+ pr_info("Default Flow Context Read OK\n");
+ /* start a NOP */
+ ret = pme_ctx_ctrl_nop(&ctx, 0, &ctx_ctrl.ctx_ctr);
+ pr_info("PME2: pme_ctx_ctrl_nop done\n");
+ wait_for_completion(&ctx_ctrl.cb_done);
+ POST_CTRL(post_ctrl);
+ if (post_ctrl)
+ goto disable_ctx;
+ /* start an update to add residue to the context */
+ flow.ren = 1;
+ ret = pme_ctx_ctrl_update_flow(&ctx, PME_CTX_OP_WAIT | PME_CMD_FCW_RES,
+ &flow, &ctx_ctrl.ctx_ctr);
+ pr_info("PME2: pme_ctx_ctrl_update_flow done\n");
+ wait_for_completion(&ctx_ctrl.cb_done);
+ POST_CTRL(post_ctrl);
+ if (post_ctrl)
+ goto disable_ctx;
+ /* start a blocking disable */
+ ret = pme_ctx_disable(&ctx, PME_CTX_OP_WAIT, &ctx_ctrl.ctx_ctr);
+ if (ret < 1) {
+ post_ctrl = -1;
+ goto finish_ctx;
+ }
+ wait_for_completion(&ctx_ctrl.cb_done);
+ /* do some reconfiguration */
+ ret = pme_ctx_reconfigure_tx(&ctx, 63, 7);
+ if (ret) {
+ post_ctrl = -1;
+ goto finish_ctx;
+ }
+ stashing.exclusive = 0;
+ stashing.annotation_cl = 0;
+ stashing.data_cl = 2;
+ stashing.context_cl = 2;
+ ret = pme_ctx_reconfigure_rx(&ctx, 7, 0, &stashing);
+ if (ret) {
+ post_ctrl = -1;
+ goto finish_ctx;
+ }
+ /* reenable */
+ ret = pme_ctx_enable(&ctx);
+ if (ret) {
+ post_ctrl = -1;
+ goto finish_ctx;
+ }
+ /* read back flow settings */
+ ret = pme_ctx_ctrl_read_flow(&ctx,
+ PME_CTX_OP_WAIT | PME_CTX_OP_WAIT_INT | PME_CMD_FCW_RES, &flow,
+ &ctx_ctrl.ctx_ctr);
+ pr_info("PME2: pme_ctx_ctrl_read_flow done\n");
+ wait_for_completion(&ctx_ctrl.cb_done);
+ POST_CTRL(post_ctrl);
+ if (post_ctrl)
+ goto disable_ctx;
+ /* blocking NOP */
+ ret = pme_ctx_ctrl_nop(&ctx, PME_CTX_OP_WAIT | PME_CTX_OP_WAIT_INT,
+ &ctx_ctrl.ctx_ctr);
+ pr_info("PME2: pme_ctx_ctrl_nop done\n");
+ wait_for_completion(&ctx_ctrl.cb_done);
+ POST_CTRL(post_ctrl);
+ /* Disable, and done */
+disable_ctx:
+ ret = pme_ctx_disable(&ctx, PME_CTX_OP_WAIT, &ctx_ctrl.ctx_ctr);
+ BUG_ON(ret < 1);
+ wait_for_completion(&ctx_ctrl.cb_done);
+finish_ctx:
+ pme_ctx_finish(&ctx);
+restore_mask:
+ ret = set_cpus_allowed_ptr(current, &backup_mask);
+ if (ret) {
+ pr_err("PME2 test high: can't restore cpumask");
+ post_ctrl = -1;
+ }
+done:
+ if (post_ctrl)
+ pr_info("PME2: high-level test failed\n");
+ else
+ pr_info("PME2: high-level test passed\n");
+}
+
+static int pme2_test_high_init(void)
+{
+ int big_loop = 2;
+ while (big_loop--)
+ pme2_test_high();
+ return 0;
+}
+
+static void pme2_test_high_exit(void)
+{
+}
+
+module_init(pme2_test_high_init);
+module_exit(pme2_test_high_exit);
diff --git a/drivers/staging/fsl_pme2/pme2_test_scan.c b/drivers/staging/fsl_pme2/pme2_test_scan.c
new file mode 100644
index 0000000..65608db
--- /dev/null
+++ b/drivers/staging/fsl_pme2/pme2_test_scan.c
@@ -0,0 +1,653 @@
+/* Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "pme2_test.h"
+
+enum scan_ctrl_mode {
+ no_scan = 0,
+ do_scan = 1,
+};
+
+enum db_ctrl_mode {
+ create_destroy = 0,
+ create = 1,
+ destroy = 2,
+ nothing = 3
+};
+
+MODULE_AUTHOR("Jeffrey Ladouceur");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("PME scan testing");
+
+static enum db_ctrl_mode db_ctrl;
+module_param(db_ctrl, uint, 0644);
+MODULE_PARM_DESC(db_ctrl, "PME Database control");
+
+static enum scan_ctrl_mode scan_ctrl = 1;
+module_param(scan_ctrl, uint, 0644);
+MODULE_PARM_DESC(scan_ctrl, "Scan control");
+
+static u8 scan_result_direct_mode_inc_mode[] = {
+ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
+};
+
+static u8 fl_ctx_exp[] = {
+ 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00
+};
+
+/* same again with 'sos' bit cleared */
+static u8 fl_ctx_exp_post_scan[] = {
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xe0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00
+};
+
+struct scan_ctx {
+ struct pme_ctx base_ctx;
+ struct qm_fd result_fd;
+};
+
+struct ctrl_op {
+ struct pme_ctx_ctrl_token ctx_ctr;
+ struct completion cb_done;
+ enum pme_status cmd_status;
+ u8 res_flag;
+};
+
+static void ctrl_cb(struct pme_ctx *ctx, const struct qm_fd *fd,
+ struct pme_ctx_ctrl_token *token)
+{
+ struct ctrl_op *ctrl = (struct ctrl_op *)token;
+ ctrl->cmd_status = pme_fd_res_status(fd);
+ ctrl->res_flag = pme_fd_res_flags(fd) & PME_STATUS_UNRELIABLE;
+ /* hexdump(fd, sizeof(*fd)); */
+ complete(&ctrl->cb_done);
+}
+
+static DECLARE_COMPLETION(scan_comp);
+
+static void scan_cb(struct pme_ctx *ctx, const struct qm_fd *fd,
+ struct pme_ctx_token *ctx_token)
+{
+ struct scan_ctx *my_ctx = (struct scan_ctx *)ctx;
+ memcpy(&my_ctx->result_fd, fd, sizeof(*fd));
+ complete(&scan_comp);
+}
+
+#ifdef CONFIG_FSL_PME2_TEST_SCAN_WITH_BPID
+
+static struct bman_pool *pool;
+static u32 pme_bpid;
+static void *bman_buffers_virt_base;
+static dma_addr_t bman_buffers_phys_base;
+
+static void release_buffer(dma_addr_t addr)
+{
+ struct bm_buffer bufs_in;
+ bm_buffer_set64(&bufs_in, addr);
+ if (bman_release(pool, &bufs_in, 1, BMAN_RELEASE_FLAG_WAIT))
+ panic("bman_release() failed\n");
+}
+
+static void empty_buffer(void)
+{
+ struct bm_buffer bufs_in;
+ int ret;
+
+ do {
+ ret = bman_acquire(pool, &bufs_in, 1, 0);
+ } while (!ret);
+}
+#endif /*CONFIG_FSL_PME2_TEST_SCAN_WITH_BPID*/
+
+static int scan_test_direct(int trunc, int use_bp)
+{
+ struct scan_ctx a_scan_ctx = {
+ .base_ctx = {
+ .cb = scan_cb
+ }
+ };
+ struct ctrl_op ctx_ctrl = {
+ .ctx_ctr.cb = ctrl_cb,
+ .cmd_status = 0,
+ .res_flag = 0
+ };
+ struct qm_fd fd;
+ struct qm_sg_entry sg_table[2];
+ int ret;
+ enum pme_status status;
+ struct pme_ctx_token token;
+ u8 *scan_result;
+ u32 scan_result_size;
+ u8 scan_data[] = {
+ 0x41, 0x42, 0x43, 0x44, 0x45
+ };
+ u8 result_data[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00
+ };
+
+ init_completion(&ctx_ctrl.cb_done);
+ scan_result = scan_result_direct_mode_inc_mode;
+ scan_result_size = sizeof(scan_result_direct_mode_inc_mode);
+
+ ret = pme_ctx_init(&a_scan_ctx.base_ctx,
+ PME_CTX_FLAG_DIRECT | PME_CTX_FLAG_LOCAL,
+ 0, 4, 4, 0, NULL);
+ if (ret) {
+ pr_err("pme scan test failed: 0x%x\n", ret);
+ return ret;
+ }
+ /* enable the context */
+ ret = pme_ctx_enable(&a_scan_ctx.base_ctx);
+ if (ret) {
+ pr_err("pme scan test failed: 0x%x\n", ret);
+ goto ctx_finish;
+ }
+
+ /* Do a pre-built output, scan with match test */
+ /* Build a frame descriptor */
+ memset(&fd, 0, sizeof(struct qm_fd));
+ memset(&sg_table, 0, sizeof(sg_table));
+
+ if (trunc) {
+ fd.length20 = sizeof(scan_data);
+ qm_fd_addr_set64(&fd, pme_map(scan_data));
+ } else {
+ /* build the result */
+ qm_sg_entry_set64(&sg_table[0], pme_map(result_data));
+ sg_table[0].length = sizeof(result_data);
+ qm_sg_entry_set64(&sg_table[1], pme_map(scan_data));
+ sg_table[1].length = sizeof(scan_data);
+ sg_table[1].final = 1;
+ fd._format2 = qm_fd_compound;
+ qm_fd_addr_set64(&fd, pme_map(sg_table));
+ }
+
+ ret = pme_ctx_scan(&a_scan_ctx.base_ctx, 0, &fd,
+ PME_SCAN_ARGS(PME_CMD_SCAN_SR | PME_CMD_SCAN_E, 0, 0xff00),
+ &token);
+ if (ret) {
+ pr_err("pme scan test failed: 0x%x\n", ret);
+ goto ctx_disable;
+ }
+ wait_for_completion(&scan_comp);
+
+ status = pme_fd_res_status(&a_scan_ctx.result_fd);
+ if (status) {
+ pr_err("pme scan test failed 0x%x\n", status);
+ goto ctx_disable;
+ }
+ if (trunc) {
+ int res_flag = pme_fd_res_flags(&a_scan_ctx.result_fd);
+ /* Check the response...expect truncation bit to be set */
+ if (!(res_flag & PME_STATUS_TRUNCATED)) {
+ pr_err("pme scan test failed, expected truncation\n");
+ goto ctx_disable;
+ }
+ } else {
+ if (memcmp(scan_result, result_data, scan_result_size) != 0) {
+ pr_err("pme scan test result not expected\n");
+ hexdump(scan_result, scan_result_size);
+ pr_err("Received...\n");
+ hexdump(result_data, sizeof(result_data));
+ goto ctx_disable;
+ }
+ }
+
+ ret = pme_ctx_disable(&a_scan_ctx.base_ctx, PME_CTX_OP_WAIT, NULL);
+ if (ret) {
+ pr_err("pme scan test failed: 0x%x\n", ret);
+ goto ctx_finish;
+ }
+ if (!use_bp) {
+ pme_ctx_finish(&a_scan_ctx.base_ctx);
+ return 0;
+ }
+ /* use buffer pool */
+ /* Check with bman */
+ /* reconfigure */
+
+#ifdef CONFIG_FSL_PME2_TEST_SCAN_WITH_BPID
+ ret = pme_ctx_reconfigure_tx(&a_scan_ctx.base_ctx, pme_bpid, 5);
+ if (ret) {
+ pr_err("pme scan test failed: 0x%x\n", ret);
+ goto ctx_finish;
+ }
+ ret = pme_ctx_enable(&a_scan_ctx.base_ctx);
+ if (ret) {
+ pr_err("pme scan test failed: 0x%x\n", ret);
+ goto ctx_finish;
+ }
+ /* Do a pre-built output, scan with match test */
+ /* Build a frame descriptor */
+ memset(&fd, 0, sizeof(struct qm_fd));
+ memset(&sg_table, 0, sizeof(sg_table));
+
+ /* build the result */
+ /* result is all zero...use bman */
+ qm_sg_entry_set64(&sg_table[1], pme_map(scan_data));
+ sg_table[1].length = sizeof(scan_data);
+ sg_table[1].final = 1;
+
+ fd._format2 = qm_fd_compound;
+ qm_fd_addr_set64(&fd, pme_map(sg_table));
+
+ ret = pme_ctx_scan(&a_scan_ctx.base_ctx, 0, &fd,
+ PME_SCAN_ARGS(PME_CMD_SCAN_SR | PME_CMD_SCAN_E, 0, 0xff00),
+ &token);
+ if (ret) {
+ pr_err("pme scan test failed: 0x%x\n", ret);
+ goto ctx_disable;
+ }
+ wait_for_completion(&scan_comp);
+
+ status = pme_fd_res_status(&a_scan_ctx.result_fd);
+ if (status) {
+ pr_err("pme scan test failed 0x%x\n", status);
+ goto ctx_disable;
+ }
+ /* sg result should point to bman buffer */
+ if (!qm_sg_entry_get64(&sg_table[0])) {
+ pr_err("pme scan test failed, sg result not bman buffer\n");
+ goto ctx_disable;
+ }
+ if (memcmp(scan_result, bman_buffers_virt_base, scan_result_size)
+ != 0) {
+ pr_err("pme scan test not expected, Expected\n");
+ hexdump(scan_result, scan_result_size);
+ pr_err("Received...\n");
+ hexdump(bman_buffers_virt_base, scan_result_size);
+ release_buffer(qm_sg_entry_get64(&sg_table[0]));
+ goto ctx_disable;
+ }
+ release_buffer(qm_sg_entry_get64(&sg_table[0]));
+ ret = pme_ctx_disable(&a_scan_ctx.base_ctx, PME_CTX_OP_WAIT, NULL);
+ if (ret) {
+ pr_err("pme scan test failed: 0x%x\n", ret);
+ goto ctx_finish;
+ }
+ pme_ctx_finish(&a_scan_ctx.base_ctx);
+ return 0;
+#endif
+
+/* failure path */
+ctx_disable:
+ ret = pme_ctx_disable(&a_scan_ctx.base_ctx, PME_CTX_OP_WAIT, NULL);
+ctx_finish:
+ pme_ctx_finish(&a_scan_ctx.base_ctx);
+ return (!ret) ? -EINVAL : ret;
+}
+
+static int scan_test_flow(void)
+{
+ struct pme_flow flow;
+ struct pme_flow rb_flow;
+ struct scan_ctx a_scan_ctx = {
+ .base_ctx = {
+ .cb = scan_cb
+ }
+ };
+ struct ctrl_op ctx_ctrl = {
+ .ctx_ctr.cb = ctrl_cb,
+ .cmd_status = 0,
+ .res_flag = 0
+ };
+ struct qm_fd fd;
+ struct qm_sg_entry sg_table[2];
+ int ret;
+ enum pme_status status;
+ struct pme_ctx_token token;
+ u8 *scan_result;
+ u32 scan_result_size;
+ u8 scan_data[] = {
+ 0x41, 0x42, 0x43, 0x44, 0x45
+ };
+ u8 result_data[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00
+ };
+
+ pme_sw_flow_init(&flow);
+ init_completion(&ctx_ctrl.cb_done);
+ scan_result = scan_result_direct_mode_inc_mode;
+ scan_result_size = sizeof(scan_result_direct_mode_inc_mode);
+
+ ret = pme_ctx_init(&a_scan_ctx.base_ctx,
+ PME_CTX_FLAG_LOCAL, 0, 4, 4, 0, NULL);
+ if (ret) {
+ pr_err("pme scan test failed: 0x%x\n", ret);
+ return ret;
+ }
+ /* enable the context */
+ ret = pme_ctx_enable(&a_scan_ctx.base_ctx);
+ if (ret) {
+ pr_err("pme scan test failed: 0x%x\n", ret);
+ goto flow_ctx_finish;
+ }
+ ret = pme_ctx_ctrl_update_flow(&a_scan_ctx.base_ctx,
+ PME_CTX_OP_WAIT | PME_CMD_FCW_ALL, &flow, &ctx_ctrl.ctx_ctr);
+ if (ret) {
+ pr_err("pme scan test failed: 0x%x\n", ret);
+ goto flow_ctx_disable;
+ }
+ wait_for_completion(&ctx_ctrl.cb_done);
+ if (ctx_ctrl.cmd_status || ctx_ctrl.res_flag) {
+ pr_err("pme scan test failed: 0x%x\n", ret);
+ goto flow_ctx_disable;
+ }
+ /* read back flow settings */
+ ret = pme_ctx_ctrl_read_flow(&a_scan_ctx.base_ctx,
+ PME_CTX_OP_WAIT, &rb_flow, &ctx_ctrl.ctx_ctr);
+ if (ret) {
+ pr_err("pme scan test failed: 0x%x\n", ret);
+ goto flow_ctx_disable;
+ }
+ wait_for_completion(&ctx_ctrl.cb_done);
+ if (ctx_ctrl.cmd_status || ctx_ctrl.res_flag) {
+ pr_err("pme scan test failed: 0x%x\n", ret);
+ goto flow_ctx_disable;
+ }
+ if (memcmp(&rb_flow, fl_ctx_exp, sizeof(rb_flow)) != 0) {
+ pr_err("pme scan test Flow Context Read FAIL\n");
+ pr_err("Expected\n");
+ hexdump(fl_ctx_exp, sizeof(fl_ctx_exp));
+ pr_err("Received...\n");
+ hexdump(&rb_flow, sizeof(rb_flow));
+ goto flow_ctx_disable;
+ }
+
+ /* Do a pre-built output, scan with match test */
+ /* Build a frame descriptor */
+ memset(&fd, 0, sizeof(struct qm_fd));
+ memset(&sg_table, 0, sizeof(sg_table));
+
+ /* build the result */
+ qm_sg_entry_set64(&sg_table[0], pme_map(result_data));
+ sg_table[0].length = sizeof(result_data);
+ qm_sg_entry_set64(&sg_table[1], pme_map(scan_data));
+ sg_table[1].length = sizeof(scan_data);
+ sg_table[1].final = 1;
+
+ fd._format2 = qm_fd_compound;
+ qm_fd_addr_set64(&fd, pme_map(sg_table));
+
+ ret = pme_ctx_scan(&a_scan_ctx.base_ctx, 0, &fd,
+ PME_SCAN_ARGS(PME_CMD_SCAN_SR | PME_CMD_SCAN_E, 0, 0xff00),
+ &token);
+ if (ret) {
+ pr_err("pme scan test failed: 0x%x\n", ret);
+ goto flow_ctx_disable;
+ }
+ wait_for_completion(&scan_comp);
+
+ status = pme_fd_res_status(&a_scan_ctx.result_fd);
+ if (status) {
+ pr_err("pme scan test failed 0x%x\n", status);
+ goto flow_ctx_disable;
+ }
+
+ if (memcmp(scan_result, result_data, scan_result_size) != 0) {
+ pr_err("pme scan test result not expected\n");
+ hexdump(scan_result, scan_result_size);
+ pr_err("Received...\n");
+ hexdump(result_data, sizeof(result_data));
+ goto flow_ctx_disable;
+ }
+
+ /* read back flow settings */
+ ret = pme_ctx_ctrl_read_flow(&a_scan_ctx.base_ctx,
+ PME_CTX_OP_WAIT, &rb_flow, &ctx_ctrl.ctx_ctr);
+ if (ret) {
+ pr_err("pme scan test failed 0x%x\n", status);
+ goto flow_ctx_disable;
+ }
+ wait_for_completion(&ctx_ctrl.cb_done);
+ if (ctx_ctrl.cmd_status || ctx_ctrl.res_flag) {
+ pr_err("pme scan test failed: 0x%x\n", ret);
+ goto flow_ctx_disable;
+ }
+ if (memcmp(&rb_flow, fl_ctx_exp_post_scan, sizeof(rb_flow)) != 0) {
+ pr_err("pme scan test Flow Context Read FAIL\n");
+ pr_err("Expected\n");
+ hexdump(fl_ctx_exp_post_scan, sizeof(fl_ctx_exp_post_scan));
+ pr_err("Received\n");
+ hexdump(&rb_flow, sizeof(rb_flow));
+ goto flow_ctx_disable;
+ }
+
+ /* Test truncation test */
+ /* Build a frame descriptor */
+ memset(&fd, 0, sizeof(struct qm_fd));
+
+ fd.length20 = sizeof(scan_data);
+ qm_fd_addr_set64(&fd, pme_map(scan_data));
+
+ ret = pme_ctx_scan(&a_scan_ctx.base_ctx, 0, &fd,
+ PME_SCAN_ARGS(PME_CMD_SCAN_SR | PME_CMD_SCAN_E, 0, 0xff00),
+ &token);
+ if (ret) {
+ pr_err("pme scan test failed 0x%x\n", status);
+ goto flow_ctx_disable;
+ }
+ wait_for_completion(&scan_comp);
+
+ status = pme_fd_res_status(&a_scan_ctx.result_fd);
+ if (status) {
+ pr_err("pme scan test failed 0x%x\n", status);
+ goto flow_ctx_disable;
+ }
+ /* Check the response...expect truncation bit to be set */
+ if (!(pme_fd_res_flags(&a_scan_ctx.result_fd) & PME_STATUS_TRUNCATED)) {
+ pr_err("st: Scan result failed...expected trunc\n");
+ goto flow_ctx_disable;
+ }
+
+ /* read back flow settings */
+ ret = pme_ctx_ctrl_read_flow(&a_scan_ctx.base_ctx,
+ PME_CTX_OP_WAIT, &rb_flow, &ctx_ctrl.ctx_ctr);
+ if (ret) {
+ pr_err("pme scan test failed: 0x%x\n", ret);
+ goto flow_ctx_disable;
+ }
+ wait_for_completion(&ctx_ctrl.cb_done);
+ if (ctx_ctrl.cmd_status || ctx_ctrl.res_flag) {
+ pr_err("pme scan test failed: 0x%x\n", ret);
+ goto flow_ctx_disable;
+ }
+ if (memcmp(&rb_flow, fl_ctx_exp_post_scan, sizeof(rb_flow)) != 0) {
+ pr_err("pme scan test Flow Context Read FAIL\n");
+ pr_err("Expected\n");
+ hexdump(fl_ctx_exp_post_scan, sizeof(fl_ctx_exp_post_scan));
+ pr_err("Received\n");
+ hexdump(&rb_flow, sizeof(rb_flow));
+ goto flow_ctx_disable;
+ }
+
+ /* Disable */
+ ret = pme_ctx_disable(&a_scan_ctx.base_ctx, PME_CTX_OP_WAIT,
+ &ctx_ctrl.ctx_ctr);
+ if (ret < 1) {
+ pr_err("pme scan test failed 0x%x\n", ret);
+ goto flow_ctx_finish;
+ }
+ wait_for_completion(&ctx_ctrl.cb_done);
+ pme_ctx_finish(&a_scan_ctx.base_ctx);
+ return 0;
+ /* error path */
+/* failure path */
+flow_ctx_disable:
+ ret = pme_ctx_disable(&a_scan_ctx.base_ctx, PME_CTX_OP_WAIT, NULL);
+flow_ctx_finish:
+ pme_ctx_finish(&a_scan_ctx.base_ctx);
+ return (!ret) ? -EINVAL : ret;
+}
+
+void pme2_test_scan(void)
+{
+ int ret;
+
+ ret = scan_test_direct(0, 0);
+ if (ret)
+ goto done;
+ ret = scan_test_direct(1, 0);
+ if (ret)
+ goto done;
+#ifdef CONFIG_FSL_PME2_TEST_SCAN_WITH_BPID
+ ret = scan_test_direct(0, 1);
+ if (ret)
+ goto done;
+#endif
+ ret = scan_test_flow();
+done:
+ if (ret)
+ pr_info("pme scan test FAILED 0x%x\n", ret);
+ else
+ pr_info("pme Scan Test Passed\n");
+}
+
+static int setup_buffer_pool(void)
+{
+#ifdef CONFIG_FSL_PME2_TEST_SCAN_WITH_BPID
+ u32 bpid_size = CONFIG_FSL_PME2_TEST_SCAN_WITH_BPID_SIZE;
+ struct bman_pool_params pparams = {
+ .flags = BMAN_POOL_FLAG_DYNAMIC_BPID,
+ .thresholds = {
+ 0,
+ 0,
+ 0,
+ 0
+ }
+ };
+
+ if (!pme2_have_control()) {
+ pr_err("pme scan test: Not the ctrl-plane\n");
+ return -EINVAL;
+ }
+ pool = bman_new_pool(&pparams);
+ if (!pool) {
+ pr_err("pme scan test: can't get buffer pool\n");
+ return -EINVAL;
+ }
+ pme_bpid = bman_get_params(pool)->bpid;
+ bman_buffers_virt_base = kmalloc(1<<(bpid_size+5), GFP_KERNEL);
+ bman_buffers_phys_base = pme_map(bman_buffers_virt_base);
+ if (pme_map_error(bman_buffers_phys_base)) {
+ pr_info("pme scan test: pme_map_error\n");
+ bman_free_pool(pool);
+ kfree(bman_buffers_virt_base);
+ return -ENODEV;
+ }
+ release_buffer(bman_buffers_phys_base);
+ /* Configure the buffer pool */
+ pme_attr_set(pme_attr_bsc(pme_bpid), bpid_size);
+ /* realease to the specified buffer pool */
+ return 0;
+#endif
+ return 0;
+}
+
+static int teardown_buffer_pool(void)
+{
+#ifdef CONFIG_FSL_PME2_TEST_SCAN_WITH_BPID
+ pme_attr_set(pme_attr_bsc(pme_bpid), 0);
+ empty_buffer();
+ bman_free_pool(pool);
+ kfree(bman_buffers_virt_base);
+#endif
+ return 0;
+}
+
+static int pme2_test_scan_init(void)
+{
+ int big_loop = 2;
+ int ret = 0;
+ struct cpumask backup_mask = current->cpus_allowed;
+ struct cpumask new_mask = *qman_affine_cpus();
+
+ cpumask_and(&new_mask, &new_mask, bman_affine_cpus());
+ ret = set_cpus_allowed_ptr(current, &new_mask);
+ if (ret) {
+ pr_info("pme scan test: can't set cpumask\n");
+ goto done_all;
+ }
+
+ ret = setup_buffer_pool();
+ if (ret)
+ goto done_cpu_mask;
+
+ /* create sample database */
+ if (db_ctrl == create_destroy || db_ctrl == create) {
+ if (!pme2_have_control()) {
+ pr_err("pme scan test: Not the ctrl-plane\n");
+ ret = -EINVAL;
+ goto done_scan;
+ }
+ if (pme2_sample_db()) {
+ pr_err("pme scan test: error creating db\n");
+ goto done_scan;
+ }
+ }
+
+ if (scan_ctrl == do_scan) {
+ while (big_loop--)
+ pme2_test_scan();
+ }
+
+ if (db_ctrl == create_destroy || db_ctrl == destroy) {
+ /* Clear database */
+ if (pme2_clear_sample_db())
+ pr_err("pme scan test: error clearing db\n");
+ }
+
+done_scan:
+ teardown_buffer_pool();
+done_cpu_mask:
+ ret = set_cpus_allowed_ptr(current, &backup_mask);
+ if (ret)
+ pr_err("PME2 test high: can't restore cpumask");
+done_all:
+ return ret;
+}
+
+static void pme2_test_scan_exit(void)
+{
+}
+
+module_init(pme2_test_scan_init);
+module_exit(pme2_test_scan_exit);
diff --git a/drivers/staging/fsl_qbman/Kconfig b/drivers/staging/fsl_qbman/Kconfig
new file mode 100644
index 0000000..c857514
--- /dev/null
+++ b/drivers/staging/fsl_qbman/Kconfig
@@ -0,0 +1,209 @@
+config FSL_DPA
+ bool "Freescale Datapath Queue and Buffer management"
+ depends on HAS_FSL_QBMAN
+ default y
+ select FSL_QMAN_FQ_LOOKUP if PPC64
+
+menu "Freescale Datapath QMan/BMan options"
+ depends on FSL_DPA
+
+config FSL_DPA_CHECKING
+ bool "additional driver checking"
+ default n
+ ---help---
+ Compiles in additional checks to sanity-check the drivers and any
+ use of it by other code. Not recommended for performance.
+
+config FSL_DPA_CAN_WAIT
+ bool
+ default y
+
+config FSL_DPA_CAN_WAIT_SYNC
+ bool
+ default y
+
+config FSL_DPA_PIRQ_FAST
+ bool
+ default y
+
+config FSL_DPA_PIRQ_SLOW
+ bool
+ default y
+
+config FSL_DPA_PORTAL_SHARE
+ bool
+ default y
+
+config FSL_BMAN
+ bool "Freescale Buffer Manager (BMan) support"
+ default y
+
+if FSL_BMAN
+
+config FSL_BMAN_CONFIG
+ bool "BMan device management"
+ default y
+ ---help---
+ If this linux image is running natively, you need this option. If this
+ linux image is running as a guest OS under the hypervisor, only one
+ guest OS ("the control plane") needs this option.
+
+config FSL_BMAN_TEST
+ tristate "BMan self-tests"
+ default n
+ ---help---
+ This option compiles self-test code for BMan.
+
+config FSL_BMAN_TEST_HIGH
+ bool "BMan high-level self-test"
+ depends on FSL_BMAN_TEST
+ default y
+ ---help---
+ This requires the presence of cpu-affine portals, and performs
+ high-level API testing with them (whichever portal(s) are affine to
+ the cpu(s) the test executes on).
+
+config FSL_BMAN_TEST_THRESH
+ bool "BMan threshold test"
+ depends on FSL_BMAN_TEST
+ default y
+ ---help---
+ Multi-threaded (SMP) test of BMan pool depletion. A pool is seeded
+ before multiple threads (one per cpu) create pool objects to track
+ depletion state changes. The pool is then drained to empty by a
+ "drainer" thread, and the other threads that they observe exactly
+ the depletion state changes that are expected.
+
+config FSL_BMAN_DEBUGFS
+ tristate "BMan debugfs interface"
+ depends on DEBUG_FS
+ default y
+ ---help---
+ This option compiles debugfs code for BMan.
+
+endif # FSL_BMAN
+
+config FSL_QMAN
+ bool "Freescale Queue Manager (QMan) support"
+ default y
+
+if FSL_QMAN
+
+config FSL_QMAN_POLL_LIMIT
+ int
+ default 32
+
+config FSL_QMAN_CONFIG
+ bool "QMan device management"
+ default y
+ ---help---
+ If this linux image is running natively, you need this option. If this
+ linux image is running as a guest OS under the hypervisor, only one
+ guest OS ("the control plane") needs this option.
+
+config FSL_QMAN_TEST
+ tristate "QMan self-tests"
+ default n
+ ---help---
+ This option compiles self-test code for QMan.
+
+config FSL_QMAN_TEST_STASH_POTATO
+ bool "QMan 'hot potato' data-stashing self-test"
+ depends on FSL_QMAN_TEST
+ default y
+ ---help---
+ This performs a "hot potato" style test enqueuing/dequeuing a frame
+ across a series of FQs scheduled to different portals (and cpus), with
+ DQRR, data and context stashing always on.
+
+config FSL_QMAN_TEST_HIGH
+ bool "QMan high-level self-test"
+ depends on FSL_QMAN_TEST
+ default y
+ ---help---
+ This requires the presence of cpu-affine portals, and performs
+ high-level API testing with them (whichever portal(s) are affine to
+ the cpu(s) the test executes on).
+
+config FSL_QMAN_DEBUGFS
+ tristate "QMan debugfs interface"
+ depends on DEBUG_FS
+ default y
+ ---help---
+ This option compiles debugfs code for QMan.
+
+# H/w settings that can be hard-coded for now.
+config FSL_QMAN_FQD_SZ
+ int "size of Frame Queue Descriptor region"
+ default 10
+ ---help---
+ This is the size of the FQD region defined as: PAGE_SIZE * (2^value)
+ ex: 10 => PAGE_SIZE * (2^10)
+ Note: Default device-trees now require minimum Kconfig setting of 10.
+
+config FSL_QMAN_PFDR_SZ
+ int "size of the PFDR pool"
+ default 13
+ ---help---
+ This is the size of the PFDR pool defined as: PAGE_SIZE * (2^value)
+ ex: 13 => PAGE_SIZE * (2^13)
+
+# Corenet initiator settings. Stash request queues are 4-deep to match cores'
+# ability to snart. Stash priority is 3, other priorities are 2.
+config FSL_QMAN_CI_SCHED_CFG_SRCCIV
+ int
+ depends on FSL_QMAN_CONFIG
+ default 4
+config FSL_QMAN_CI_SCHED_CFG_SRQ_W
+ int
+ depends on FSL_QMAN_CONFIG
+ default 3
+config FSL_QMAN_CI_SCHED_CFG_RW_W
+ int
+ depends on FSL_QMAN_CONFIG
+ default 2
+config FSL_QMAN_CI_SCHED_CFG_BMAN_W
+ int
+ depends on FSL_QMAN_CONFIG
+ default 2
+
+# portal interrupt settings
+config FSL_QMAN_PIRQ_DQRR_ITHRESH
+ int
+ default 12
+config FSL_QMAN_PIRQ_MR_ITHRESH
+ int
+ default 4
+config FSL_QMAN_PIRQ_IPERIOD
+ int
+ default 100
+
+# 64 bit kernel support
+config FSL_QMAN_FQ_LOOKUP
+ bool
+ default n
+
+config QMAN_CEETM_UPDATE_PERIOD
+ int "Token update period for shaping, in nanoseconds"
+ default 1000
+ ---help---
+ Traffic shaping works by performing token calculations (using
+ credits) on shaper instances periodically. This update period
+ sets the granularity for how often those token rate credit
+ updates are performed, and thus determines the accuracy and
+ range of traffic rates that can be configured by users. The
+ reference manual recommends a 1 microsecond period as providing
+ a good balance between granularity and range.
+
+ Unless you know what you are doing, leave this value at its default.
+
+config FSL_QMAN_INIT_TIMEOUT
+ int "timeout for qman init stage, in seconds"
+ default 10
+ ---help---
+ The timeout setting to quit the initialization loop for non-control
+ partition in case the control partition fails to boot-up.
+
+endif # FSL_QMAN
+
+endmenu
diff --git a/drivers/staging/fsl_qbman/Makefile b/drivers/staging/fsl_qbman/Makefile
new file mode 100644
index 0000000..0e38610
--- /dev/null
+++ b/drivers/staging/fsl_qbman/Makefile
@@ -0,0 +1,26 @@
+# Common
+obj-$(CONFIG_FSL_DPA) += dpa_alloc.o
+obj-$(CONFIG_HAS_FSL_QBMAN) += qbman_driver.o
+
+# Bman
+obj-$(CONFIG_FSL_BMAN) += bman_high.o
+obj-$(CONFIG_FSL_BMAN_CONFIG) += bman_config.o bman_driver.o
+obj-$(CONFIG_FSL_BMAN_TEST) += bman_tester.o
+obj-$(CONFIG_FSL_BMAN_DEBUGFS) += bman_debugfs_interface.o
+bman_tester-y = bman_test.o
+bman_tester-$(CONFIG_FSL_BMAN_TEST_HIGH) += bman_test_high.o
+bman_tester-$(CONFIG_FSL_BMAN_TEST_THRESH) += bman_test_thresh.o
+bman_debugfs_interface-y = bman_debugfs.o
+
+# Qman
+obj-$(CONFIG_FSL_QMAN) += qman_high.o qman_utility.o
+obj-$(CONFIG_FSL_QMAN_CONFIG) += qman_config.o qman_driver.o
+obj-$(CONFIG_FSL_QMAN_TEST) += qman_tester.o
+qman_tester-y = qman_test.o
+qman_tester-$(CONFIG_FSL_QMAN_TEST_STASH_POTATO) += qman_test_hotpotato.o
+qman_tester-$(CONFIG_FSL_QMAN_TEST_HIGH) += qman_test_high.o
+obj-$(CONFIG_FSL_QMAN_DEBUGFS) += qman_debugfs_interface.o
+qman_debugfs_interface-y = qman_debugfs.o
+
+# USDPAA
+obj-$(CONFIG_FSL_USDPAA) += fsl_usdpaa.o fsl_usdpaa_irq.o
diff --git a/drivers/staging/fsl_qbman/bman_config.c b/drivers/staging/fsl_qbman/bman_config.c
new file mode 100644
index 0000000..efba359
--- /dev/null
+++ b/drivers/staging/fsl_qbman/bman_config.c
@@ -0,0 +1,726 @@
+/* Copyright (c) 2009-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <asm/cacheflush.h>
+#include "bman_private.h"
+
+/* Last updated for v00.79 of the BG */
+
+struct bman;
+
+/* Register offsets */
+#define REG_POOL_SWDET(n) (0x0000 + ((n) * 0x04))
+#define REG_POOL_HWDET(n) (0x0100 + ((n) * 0x04))
+#define REG_POOL_SWDXT(n) (0x0200 + ((n) * 0x04))
+#define REG_POOL_HWDXT(n) (0x0300 + ((n) * 0x04))
+#define REG_POOL_CONTENT(n) (0x0600 + ((n) * 0x04))
+#define REG_FBPR_FPC 0x0800
+#define REG_STATE_IDLE 0x960
+#define REG_STATE_STOP 0x964
+#define REG_ECSR 0x0a00
+#define REG_ECIR 0x0a04
+#define REG_EADR 0x0a08
+#define REG_EDATA(n) (0x0a10 + ((n) * 0x04))
+#define REG_SBEC(n) (0x0a80 + ((n) * 0x04))
+#define REG_IP_REV_1 0x0bf8
+#define REG_IP_REV_2 0x0bfc
+#define REG_FBPR_BARE 0x0c00
+#define REG_FBPR_BAR 0x0c04
+#define REG_FBPR_AR 0x0c10
+#define REG_SRCIDR 0x0d04
+#define REG_LIODNR 0x0d08
+#define REG_ERR_ISR 0x0e00 /* + "enum bm_isr_reg" */
+
+/* Used by all error interrupt registers except 'inhibit' */
+#define BM_EIRQ_IVCI 0x00000010 /* Invalid Command Verb */
+#define BM_EIRQ_FLWI 0x00000008 /* FBPR Low Watermark */
+#define BM_EIRQ_MBEI 0x00000004 /* Multi-bit ECC Error */
+#define BM_EIRQ_SBEI 0x00000002 /* Single-bit ECC Error */
+#define BM_EIRQ_BSCN 0x00000001 /* pool State Change Notification */
+
+/* BMAN_ECIR valid error bit */
+#define PORTAL_ECSR_ERR (BM_EIRQ_IVCI)
+
+union bman_ecir {
+ u32 ecir_raw;
+ struct {
+ u32 __reserved1:4;
+ u32 portal_num:4;
+ u32 __reserved2:12;
+ u32 numb:4;
+ u32 __reserved3:2;
+ u32 pid:6;
+ } __packed info;
+};
+
+union bman_eadr {
+ u32 eadr_raw;
+ struct {
+ u32 __reserved1:5;
+ u32 memid:3;
+ u32 __reserved2:14;
+ u32 eadr:10;
+ } __packed info;
+};
+
+struct bman_hwerr_txt {
+ u32 mask;
+ const char *txt;
+};
+
+#define BMAN_HWE_TXT(a, b) { .mask = BM_EIRQ_##a, .txt = b }
+
+static const struct bman_hwerr_txt bman_hwerr_txts[] = {
+ BMAN_HWE_TXT(IVCI, "Invalid Command Verb"),
+ BMAN_HWE_TXT(FLWI, "FBPR Low Watermark"),
+ BMAN_HWE_TXT(MBEI, "Multi-bit ECC Error"),
+ BMAN_HWE_TXT(SBEI, "Single-bit ECC Error"),
+ BMAN_HWE_TXT(BSCN, "Pool State Change Notification"),
+};
+#define BMAN_HWE_COUNT (sizeof(bman_hwerr_txts)/sizeof(struct bman_hwerr_txt))
+
+struct bman_error_info_mdata {
+ u16 addr_mask;
+ u16 bits;
+ const char *txt;
+};
+
+#define BMAN_ERR_MDATA(a, b, c) { .addr_mask = a, .bits = b, .txt = c}
+static const struct bman_error_info_mdata error_mdata[] = {
+ BMAN_ERR_MDATA(0x03FF, 192, "Stockpile memory"),
+ BMAN_ERR_MDATA(0x00FF, 256, "SW portal ring memory port 1"),
+ BMAN_ERR_MDATA(0x00FF, 256, "SW portal ring memory port 2"),
+};
+#define BMAN_ERR_MDATA_COUNT \
+ (sizeof(error_mdata)/sizeof(struct bman_error_info_mdata))
+
+/* Add this in Kconfig */
+#define BMAN_ERRS_TO_UNENABLE (BM_EIRQ_FLWI)
+
+/**
+ * bm_err_isr_<reg>_<verb> - Manipulate global interrupt registers
+ * @v: for accessors that write values, this is the 32-bit value
+ *
+ * Manipulates BMAN_ERR_ISR, BMAN_ERR_IER, BMAN_ERR_ISDR, BMAN_ERR_IIR. All
+ * manipulations except bm_err_isr_[un]inhibit() use 32-bit masks composed of
+ * the BM_EIRQ_*** definitions. Note that "bm_err_isr_enable_write" means
+ * "write the enable register" rather than "enable the write register"!
+ */
+#define bm_err_isr_status_read(bm) \
+ __bm_err_isr_read(bm, bm_isr_status)
+#define bm_err_isr_status_clear(bm, m) \
+ __bm_err_isr_write(bm, bm_isr_status, m)
+#define bm_err_isr_enable_read(bm) \
+ __bm_err_isr_read(bm, bm_isr_enable)
+#define bm_err_isr_enable_write(bm, v) \
+ __bm_err_isr_write(bm, bm_isr_enable, v)
+#define bm_err_isr_disable_read(bm) \
+ __bm_err_isr_read(bm, bm_isr_disable)
+#define bm_err_isr_disable_write(bm, v) \
+ __bm_err_isr_write(bm, bm_isr_disable, v)
+#define bm_err_isr_inhibit(bm) \
+ __bm_err_isr_write(bm, bm_isr_inhibit, 1)
+#define bm_err_isr_uninhibit(bm) \
+ __bm_err_isr_write(bm, bm_isr_inhibit, 0)
+
+/*
+ * TODO: unimplemented registers
+ *
+ * BMAN_POOLk_SDCNT, BMAN_POOLk_HDCNT, BMAN_FULT,
+ * BMAN_VLDPL, BMAN_EECC, BMAN_SBET, BMAN_EINJ
+ */
+
+/* Encapsulate "struct bman *" as a cast of the register space address. */
+
+static struct bman *bm_create(void *regs)
+{
+ return (struct bman *)regs;
+}
+
+static inline u32 __bm_in(struct bman *bm, u32 offset)
+{
+ return in_be32((void *)bm + offset);
+}
+static inline void __bm_out(struct bman *bm, u32 offset, u32 val)
+{
+ out_be32((void *)bm + offset, val);
+}
+#define bm_in(reg) __bm_in(bm, REG_##reg)
+#define bm_out(reg, val) __bm_out(bm, REG_##reg, val)
+
+static u32 __bm_err_isr_read(struct bman *bm, enum bm_isr_reg n)
+{
+ return __bm_in(bm, REG_ERR_ISR + (n << 2));
+}
+
+static void __bm_err_isr_write(struct bman *bm, enum bm_isr_reg n, u32 val)
+{
+ __bm_out(bm, REG_ERR_ISR + (n << 2), val);
+}
+
+static void bm_get_version(struct bman *bm, u16 *id, u8 *major, u8 *minor)
+{
+ u32 v = bm_in(IP_REV_1);
+ *id = (v >> 16);
+ *major = (v >> 8) & 0xff;
+ *minor = v & 0xff;
+}
+
+static u32 __generate_thresh(u32 val, int roundup)
+{
+ u32 e = 0; /* co-efficient, exponent */
+ int oddbit = 0;
+ while (val > 0xff) {
+ oddbit = val & 1;
+ val >>= 1;
+ e++;
+ if (roundup && oddbit)
+ val++;
+ }
+ DPA_ASSERT(e < 0x10);
+ return val | (e << 8);
+}
+
+static void bm_set_pool(struct bman *bm, u8 pool, u32 swdet, u32 swdxt,
+ u32 hwdet, u32 hwdxt)
+{
+ DPA_ASSERT(pool < bman_pool_max);
+ bm_out(POOL_SWDET(pool), __generate_thresh(swdet, 0));
+ bm_out(POOL_SWDXT(pool), __generate_thresh(swdxt, 1));
+ bm_out(POOL_HWDET(pool), __generate_thresh(hwdet, 0));
+ bm_out(POOL_HWDXT(pool), __generate_thresh(hwdxt, 1));
+}
+
+static void bm_set_memory(struct bman *bm, u64 ba, int prio, u32 size)
+{
+ u32 exp = ilog2(size);
+ /* choke if size isn't within range */
+ DPA_ASSERT((size >= 4096) && (size <= 1073741824) &&
+ is_power_of_2(size));
+ /* choke if '[e]ba' has lower-alignment than 'size' */
+ DPA_ASSERT(!(ba & (size - 1)));
+ bm_out(FBPR_BARE, upper_32_bits(ba));
+ bm_out(FBPR_BAR, lower_32_bits(ba));
+ bm_out(FBPR_AR, (prio ? 0x40000000 : 0) | (exp - 1));
+}
+
+/*****************/
+/* Config driver */
+/*****************/
+
+/* TODO: Kconfig these? */
+#define DEFAULT_FBPR_SZ (PAGE_SIZE << 12)
+
+/* We support only one of these. */
+static struct bman *bm;
+static struct device_node *bm_node;
+
+/* And this state belongs to 'bm'. It is set during fsl_bman_init(), but used
+ * during bman_init_ccsr(). */
+static dma_addr_t fbpr_a;
+static size_t fbpr_sz = DEFAULT_FBPR_SZ;
+
+/* Parse the <name> property to extract the memory location and size and
+ * memblock_reserve() it. If it isn't supplied, memblock_alloc() the default
+ * size. Also flush this memory range from data cache so that BMAN originated
+ * transactions for this memory region could be marked non-coherent.
+ */
+static __init int parse_mem_property(struct device_node *node, const char *name,
+ dma_addr_t *addr, size_t *sz, int zero)
+{
+ const u32 *pint;
+ int ret;
+ unsigned long vaddr;
+
+ pint = of_get_property(node, name, &ret);
+ if (!pint || (ret != 16)) {
+ pr_info("No %s property '%s', using memblock_alloc(%016zx)\n",
+ node->full_name, name, *sz);
+ *addr = memblock_alloc(*sz, *sz);
+ vaddr = (unsigned long)phys_to_virt(*addr);
+ if (zero)
+ memset((void *)vaddr, 0, *sz);
+ flush_dcache_range(vaddr, vaddr + *sz);
+ return 0;
+ }
+ pr_info("Using %s property '%s'\n", node->full_name, name);
+ /* If using a "zero-pma", don't try to zero it, even if you asked */
+ if (zero && of_find_property(node, "zero-pma", &ret)) {
+ pr_info(" it's a 'zero-pma', not zeroing from s/w\n");
+ zero = 0;
+ }
+ *addr = ((u64)pint[0] << 32) | (u64)pint[1];
+ *sz = ((u64)pint[2] << 32) | (u64)pint[3];
+ /* Keep things simple, it's either all in the DRAM range or it's all
+ * outside. */
+ if (*addr < memblock_end_of_DRAM()) {
+ BUG_ON((u64)*addr + (u64)*sz > memblock_end_of_DRAM());
+ if (memblock_reserve(*addr, *sz) < 0) {
+ pr_err("Failed to reserve %s\n", name);
+ return -ENOMEM;
+ }
+ vaddr = (unsigned long)phys_to_virt(*addr);
+ if (zero)
+ memset((void *)vaddr, 0, *sz);
+ flush_dcache_range(vaddr, vaddr + *sz);
+ } else if (zero) {
+ /* map as cacheable, non-guarded */
+ void __iomem *tmpp = ioremap_prot(*addr, *sz, 0);
+ memset_io(tmpp, 0, *sz);
+ vaddr = (unsigned long)tmpp;
+ flush_dcache_range(vaddr, vaddr + *sz);
+ iounmap(tmpp);
+ }
+ return 0;
+}
+
+static int __init fsl_bman_init(struct device_node *node)
+{
+ struct resource res;
+ u32 __iomem *regs;
+ const char *s;
+ int ret, standby = 0;
+ u16 id;
+ u8 major, minor;
+
+ ret = of_address_to_resource(node, 0, &res);
+ if (ret) {
+ pr_err("Can't get %s property 'reg'\n",
+ node->full_name);
+ return ret;
+ }
+ s = of_get_property(node, "fsl,hv-claimable", &ret);
+ if (s && !strcmp(s, "standby"))
+ standby = 1;
+ if (!standby) {
+ ret = parse_mem_property(node, "fsl,bman-fbpr",
+ &fbpr_a, &fbpr_sz, 0);
+ BUG_ON(ret);
+ }
+ /* Global configuration */
+ regs = ioremap(res.start, res.end - res.start + 1);
+ bm = bm_create(regs);
+ BUG_ON(!bm);
+ bm_node = node;
+ bm_get_version(bm, &id, &major, &minor);
+ pr_info("Bman ver:%04x,%02x,%02x\n", id, major, minor);
+ if ((major == 1) && (minor == 0)) {
+ bman_ip_rev = BMAN_REV10;
+ bman_pool_max = 64;
+ } else if ((major == 2) && (minor == 0)) {
+ bman_ip_rev = BMAN_REV20;
+ bman_pool_max = 8;
+ } else if ((major == 2) && (minor == 1)) {
+ bman_ip_rev = BMAN_REV21;
+ bman_pool_max = 64;
+ } else {
+ pr_warn("unknown Bman version, default to rev1.0\n");
+ }
+
+ if (standby) {
+ pr_info(" -> in standby mode\n");
+ return 0;
+ }
+ return 0;
+}
+
+int bman_have_ccsr(void)
+{
+ return bm ? 1 : 0;
+}
+
+int bm_pool_set(u32 bpid, const u32 *thresholds)
+{
+ if (!bm)
+ return -ENODEV;
+ bm_set_pool(bm, bpid, thresholds[0], thresholds[1],
+ thresholds[2], thresholds[3]);
+ return 0;
+}
+EXPORT_SYMBOL(bm_pool_set);
+
+__init void bman_init_early(void)
+{
+ struct device_node *dn;
+ int ret;
+
+ for_each_compatible_node(dn, NULL, "fsl,bman") {
+ if (bm)
+ pr_err("%s: only one 'fsl,bman' allowed\n",
+ dn->full_name);
+ else {
+ if (!of_device_is_available(dn))
+ continue;
+
+ ret = fsl_bman_init(dn);
+ BUG_ON(ret);
+ }
+ }
+}
+
+static void log_edata_bits(u32 bit_count)
+{
+ u32 i, j, mask = 0xffffffff;
+
+ pr_warn("Bman ErrInt, EDATA:\n");
+ i = bit_count/32;
+ if (bit_count%32) {
+ i++;
+ mask = ~(mask << bit_count%32);
+ }
+ j = 16-i;
+ pr_warn(" 0x%08x\n", bm_in(EDATA(j)) & mask);
+ j++;
+ for (; j < 16; j++)
+ pr_warn(" 0x%08x\n", bm_in(EDATA(j)));
+}
+
+static void log_additional_error_info(u32 isr_val, u32 ecsr_val)
+{
+ union bman_ecir ecir_val;
+ union bman_eadr eadr_val;
+
+ ecir_val.ecir_raw = bm_in(ECIR);
+ /* Is portal info valid */
+ if (ecsr_val & PORTAL_ECSR_ERR) {
+ pr_warn("Bman ErrInt: SWP id %d, numb %d, pid %d\n",
+ ecir_val.info.portal_num, ecir_val.info.numb,
+ ecir_val.info.pid);
+ }
+ if (ecsr_val & (BM_EIRQ_SBEI|BM_EIRQ_MBEI)) {
+ eadr_val.eadr_raw = bm_in(EADR);
+ pr_warn("Bman ErrInt: EADR Memory: %s, 0x%x\n",
+ error_mdata[eadr_val.info.memid].txt,
+ error_mdata[eadr_val.info.memid].addr_mask
+ & eadr_val.info.eadr);
+ log_edata_bits(error_mdata[eadr_val.info.memid].bits);
+ }
+}
+
+/* Bman interrupt handler */
+static irqreturn_t bman_isr(int irq, void *ptr)
+{
+ u32 isr_val, ier_val, ecsr_val, isr_mask, i;
+
+ ier_val = bm_err_isr_enable_read(bm);
+ isr_val = bm_err_isr_status_read(bm);
+ ecsr_val = bm_in(ECSR);
+ isr_mask = isr_val & ier_val;
+
+ if (!isr_mask)
+ return IRQ_NONE;
+ for (i = 0; i < BMAN_HWE_COUNT; i++) {
+ if (bman_hwerr_txts[i].mask & isr_mask) {
+ pr_warn("Bman ErrInt: %s\n", bman_hwerr_txts[i].txt);
+ if (bman_hwerr_txts[i].mask & ecsr_val) {
+ log_additional_error_info(isr_mask, ecsr_val);
+ /* Re-arm error capture registers */
+ bm_out(ECSR, ecsr_val);
+ }
+ if (bman_hwerr_txts[i].mask & BMAN_ERRS_TO_UNENABLE) {
+ pr_devel("Bman un-enabling error 0x%x\n",
+ bman_hwerr_txts[i].mask);
+ ier_val &= ~bman_hwerr_txts[i].mask;
+ bm_err_isr_enable_write(bm, ier_val);
+ }
+ }
+ }
+ bm_err_isr_status_clear(bm, isr_val);
+ return IRQ_HANDLED;
+}
+
+static int __bind_irq(void)
+{
+ int ret, err_irq;
+
+ err_irq = of_irq_to_resource(bm_node, 0, NULL);
+ if (err_irq == NO_IRQ) {
+ pr_info("Can't get %s property '%s'\n", bm_node->full_name,
+ "interrupts");
+ return -ENODEV;
+ }
+ ret = request_irq(err_irq, bman_isr, IRQF_SHARED, "bman-err", bm_node);
+ if (ret) {
+ pr_err("request_irq() failed %d for '%s'\n", ret,
+ bm_node->full_name);
+ return -ENODEV;
+ }
+ /* Disable Buffer Pool State Change */
+ bm_err_isr_disable_write(bm, BM_EIRQ_BSCN);
+ /* Write-to-clear any stale bits, (eg. starvation being asserted prior
+ * to resource allocation during driver init). */
+ bm_err_isr_status_clear(bm, 0xffffffff);
+ /* Enable Error Interrupts */
+ bm_err_isr_enable_write(bm, 0xffffffff);
+ return 0;
+}
+
+int bman_init_ccsr(struct device_node *node)
+{
+ int ret;
+ if (!bman_have_ccsr())
+ return 0;
+ if (node != bm_node)
+ return -EINVAL;
+ /* FBPR memory */
+ bm_set_memory(bm, fbpr_a, 0, fbpr_sz);
+ ret = __bind_irq();
+ if (ret)
+ return ret;
+ return 0;
+}
+
+u32 bm_pool_free_buffers(u32 bpid)
+{
+ return bm_in(POOL_CONTENT(bpid));
+}
+
+#ifdef CONFIG_SYSFS
+
+#define DRV_NAME "fsl-bman"
+
+static ssize_t show_fbpr_fpc(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%u\n", bm_in(FBPR_FPC));
+};
+
+static ssize_t show_pool_count(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
+{
+ u32 data;
+ int i;
+
+ if (!sscanf(dev_attr->attr.name, "%d", &i))
+ return -EINVAL;
+ data = bm_in(POOL_CONTENT(i));
+ return snprintf(buf, PAGE_SIZE, "%d\n", data);
+};
+
+static ssize_t show_err_isr(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "0x%08x\n", bm_in(ERR_ISR));
+};
+
+static ssize_t show_sbec(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
+{
+ int i;
+
+ if (!sscanf(dev_attr->attr.name, "sbec_%d", &i))
+ return -EINVAL;
+ return snprintf(buf, PAGE_SIZE, "%u\n", bm_in(SBEC(i)));
+};
+
+static DEVICE_ATTR(err_isr, S_IRUSR, show_err_isr, NULL);
+static DEVICE_ATTR(fbpr_fpc, S_IRUSR, show_fbpr_fpc, NULL);
+
+/* Didn't use DEVICE_ATTR as 64 of this would be required.
+ * Initialize them when needed. */
+static char *name_attrs_pool_count; /* "xx" + null-terminator */
+static struct device_attribute *dev_attr_buffer_pool_count;
+
+static DEVICE_ATTR(sbec_0, S_IRUSR, show_sbec, NULL);
+static DEVICE_ATTR(sbec_1, S_IRUSR, show_sbec, NULL);
+
+static struct attribute *bman_dev_attributes[] = {
+ &dev_attr_fbpr_fpc.attr,
+ &dev_attr_err_isr.attr,
+ NULL
+};
+
+static struct attribute *bman_dev_ecr_attributes[] = {
+ &dev_attr_sbec_0.attr,
+ &dev_attr_sbec_1.attr,
+ NULL
+};
+
+static struct attribute **bman_dev_pool_count_attributes;
+
+
+/* root level */
+static const struct attribute_group bman_dev_attr_grp = {
+ .name = NULL,
+ .attrs = bman_dev_attributes
+};
+static const struct attribute_group bman_dev_ecr_grp = {
+ .name = "error_capture",
+ .attrs = bman_dev_ecr_attributes
+};
+static struct attribute_group bman_dev_pool_countent_grp = {
+ .name = "pool_count",
+};
+
+static int of_fsl_bman_remove(struct platform_device *ofdev)
+{
+ sysfs_remove_group(&ofdev->dev.kobj, &bman_dev_attr_grp);
+ return 0;
+};
+
+static int of_fsl_bman_probe(struct platform_device *ofdev)
+{
+ int ret, i;
+
+ ret = sysfs_create_group(&ofdev->dev.kobj, &bman_dev_attr_grp);
+ if (ret)
+ goto done;
+ ret = sysfs_create_group(&ofdev->dev.kobj, &bman_dev_ecr_grp);
+ if (ret)
+ goto del_group_0;
+
+ name_attrs_pool_count = kmalloc(sizeof(char) * bman_pool_max * 3,
+ GFP_KERNEL);
+ if (!name_attrs_pool_count) {
+ pr_err("Can't alloc name_attrs_pool_count\n");
+ goto del_group_1;
+ }
+
+ dev_attr_buffer_pool_count = kmalloc(sizeof(struct device_attribute) *
+ bman_pool_max, GFP_KERNEL);
+ if (!dev_attr_buffer_pool_count) {
+ pr_err("Can't alloc dev_attr-buffer_pool_count\n");
+ goto del_group_2;
+ }
+
+ bman_dev_pool_count_attributes = kmalloc(sizeof(struct attribute *) *
+ (bman_pool_max + 1), GFP_KERNEL);
+ if (!bman_dev_pool_count_attributes) {
+ pr_err("can't alloc bman_dev_pool_count_attributes\n");
+ goto del_group_3;
+ }
+
+ for (i = 0; i < bman_pool_max; i++) {
+ ret = scnprintf((name_attrs_pool_count + i * 3), 3, "%d", i);
+ if (!ret)
+ goto del_group_4;
+ dev_attr_buffer_pool_count[i].attr.name =
+ (name_attrs_pool_count + i * 3);
+ dev_attr_buffer_pool_count[i].attr.mode = S_IRUSR;
+ dev_attr_buffer_pool_count[i].show = show_pool_count;
+ bman_dev_pool_count_attributes[i] =
+ &dev_attr_buffer_pool_count[i].attr;
+ sysfs_attr_init(bman_dev_pool_count_attributes[i]);
+ }
+ bman_dev_pool_count_attributes[bman_pool_max] = NULL;
+
+ bman_dev_pool_countent_grp.attrs = bman_dev_pool_count_attributes;
+
+ ret = sysfs_create_group(&ofdev->dev.kobj, &bman_dev_pool_countent_grp);
+ if (ret)
+ goto del_group_4;
+
+ goto done;
+
+del_group_4:
+ kfree(bman_dev_pool_count_attributes);
+del_group_3:
+ kfree(dev_attr_buffer_pool_count);
+del_group_2:
+ kfree(name_attrs_pool_count);
+del_group_1:
+ sysfs_remove_group(&ofdev->dev.kobj, &bman_dev_ecr_grp);
+del_group_0:
+ sysfs_remove_group(&ofdev->dev.kobj, &bman_dev_attr_grp);
+done:
+ if (ret)
+ dev_err(&ofdev->dev,
+ "Cannot create dev attributes ret=%d\n", ret);
+ return ret;
+};
+
+static struct of_device_id of_fsl_bman_ids[] = {
+ {
+ .compatible = "fsl,bman",
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, of_fsl_bman_ids);
+
+#ifdef CONFIG_SUSPEND
+static u32 saved_isdr;
+
+static int bman_pm_suspend_noirq(struct device *dev)
+{
+ suspend_unused_bportal();
+ /* save isdr, disable all, clear isr */
+ saved_isdr = bm_err_isr_disable_read(bm);
+ bm_err_isr_disable_write(bm, 0xffffffff);
+ bm_err_isr_status_clear(bm, 0xffffffff);
+ /* should be idle, otherwise abort ? */
+#ifdef CONFIG_PM_DEBUG
+ pr_info("Bman suspend code, IDLE_STAT = 0x%x\n", bm_in(STATE_IDLE));
+#endif
+ return 0;
+}
+
+static int bman_pm_resume_noirq(struct device *dev)
+{
+ /* restore isdr */
+ bm_err_isr_disable_write(bm, saved_isdr);
+ resume_unused_bportal();
+ return 0;
+}
+#else
+#define bman_pm_suspend_noirq NULL
+#define bman_pm_resume_noirq NULL
+#endif
+
+static const struct dev_pm_ops bman_pm_ops = {
+ .suspend_noirq = bman_pm_suspend_noirq,
+ .resume_noirq = bman_pm_resume_noirq,
+};
+
+static struct platform_driver of_fsl_bman_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRV_NAME,
+ .of_match_table = of_fsl_bman_ids,
+ .pm = &bman_pm_ops,
+ },
+ .probe = of_fsl_bman_probe,
+ .remove = of_fsl_bman_remove,
+};
+
+static int bman_ctrl_init(void)
+{
+ return platform_driver_register(&of_fsl_bman_driver);
+}
+
+static void bman_ctrl_exit(void)
+{
+ platform_driver_unregister(&of_fsl_bman_driver);
+}
+
+module_init(bman_ctrl_init);
+module_exit(bman_ctrl_exit);
+
+#endif /* CONFIG_SYSFS */
diff --git a/drivers/staging/fsl_qbman/bman_debugfs.c b/drivers/staging/fsl_qbman/bman_debugfs.c
new file mode 100644
index 0000000..9690934
--- /dev/null
+++ b/drivers/staging/fsl_qbman/bman_debugfs.c
@@ -0,0 +1,119 @@
+/* Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <linux/module.h>
+#include <linux/fsl_bman.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+
+static struct dentry *dfs_root; /* debugfs root directory */
+
+/*******************************************************************************
+ * Query Buffer Pool State
+ ******************************************************************************/
+static int query_bp_state_show(struct seq_file *file, void *offset)
+{
+ int ret;
+ struct bm_pool_state state;
+ int i, j;
+ u32 mask;
+
+ memset(&state, 0, sizeof(struct bm_pool_state));
+ ret = bman_query_pools(&state);
+ if (ret) {
+ seq_printf(file, "Error %d\n", ret);
+ return 0;
+ }
+ seq_puts(file, "bp_id free_buffers_avail bp_depleted\n");
+ for (i = 0; i < 2; i++) {
+ mask = 0x80000000;
+ for (j = 0; j < 32; j++) {
+ seq_printf(file,
+ " %-2u %-3s %-3s\n",
+ (i*32)+j,
+ (state.as.state.__state[i] & mask) ? "no" : "yes",
+ (state.ds.state.__state[i] & mask) ? "yes" : "no");
+ mask >>= 1;
+ }
+ }
+ return 0;
+}
+
+static int query_bp_state_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, query_bp_state_show, NULL);
+}
+
+static const struct file_operations query_bp_state_fops = {
+ .owner = THIS_MODULE,
+ .open = query_bp_state_open,
+ .read = seq_read,
+ .release = single_release,
+};
+
+static int __init bman_debugfs_module_init(void)
+{
+ int ret = 0;
+ struct dentry *d;
+
+ dfs_root = debugfs_create_dir("bman", NULL);
+
+ if (dfs_root == NULL) {
+ ret = -ENOMEM;
+ pr_err("Cannot create bman debugfs dir\n");
+ goto _return;
+ }
+ d = debugfs_create_file("query_bp_state",
+ S_IRUGO,
+ dfs_root,
+ NULL,
+ &query_bp_state_fops);
+ if (d == NULL) {
+ ret = -ENOMEM;
+ pr_err("Cannot create query_bp_state\n");
+ goto _return;
+ }
+ return 0;
+
+_return:
+ debugfs_remove_recursive(dfs_root);
+ return ret;
+}
+
+static void __exit bman_debugfs_module_exit(void)
+{
+ debugfs_remove_recursive(dfs_root);
+}
+
+
+module_init(bman_debugfs_module_init);
+module_exit(bman_debugfs_module_exit);
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/staging/fsl_qbman/bman_driver.c b/drivers/staging/fsl_qbman/bman_driver.c
new file mode 100644
index 0000000..7ef20e3
--- /dev/null
+++ b/drivers/staging/fsl_qbman/bman_driver.c
@@ -0,0 +1,547 @@
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "bman_private.h"
+#ifdef CONFIG_HOTPLUG_CPU
+#include <linux/cpu.h>
+#endif
+/*
+ * Global variables of the max portal/pool number this bman version supported
+ */
+u16 bman_ip_rev;
+EXPORT_SYMBOL(bman_ip_rev);
+u16 bman_pool_max;
+EXPORT_SYMBOL(bman_pool_max);
+static u16 bman_portal_max;
+
+/* After initialising cpus that own shared portal configs, we cache the
+ * resulting portals (ie. not just the configs) in this array. Then we
+ * initialise slave cpus that don't have their own portals, redirecting them to
+ * portals from this cache in a round-robin assignment. */
+static struct bman_portal *shared_portals[NR_CPUS];
+static int num_shared_portals;
+static int shared_portals_idx;
+static LIST_HEAD(unused_pcfgs);
+static DEFINE_SPINLOCK(unused_pcfgs_lock);
+static void *affine_bportals[NR_CPUS];
+
+static int __init fsl_bpool_init(struct device_node *node)
+{
+ int ret;
+ u32 *thresh, *bpid = (u32 *)of_get_property(node, "fsl,bpid", &ret);
+ if (!bpid || (ret != 4)) {
+ pr_err("Can't get %s property 'fsl,bpid'\n", node->full_name);
+ return -ENODEV;
+ }
+ thresh = (u32 *)of_get_property(node, "fsl,bpool-thresholds", &ret);
+ if (thresh) {
+ if (ret != 16) {
+ pr_err("Invalid %s property '%s'\n",
+ node->full_name, "fsl,bpool-thresholds");
+ return -ENODEV;
+ }
+ }
+ if (thresh) {
+#ifdef CONFIG_FSL_BMAN_CONFIG
+ ret = bm_pool_set(*bpid, thresh);
+ if (ret)
+ pr_err("No CCSR node for %s property '%s'\n",
+ node->full_name, "fsl,bpool-thresholds");
+ return ret;
+#else
+ pr_err("Ignoring %s property '%s', no CCSR support\n",
+ node->full_name, "fsl,bpool-thresholds");
+#endif
+ }
+ return 0;
+}
+
+static int __init fsl_bpid_range_init(struct device_node *node)
+{
+ int ret;
+ u32 *range = (u32 *)of_get_property(node, "fsl,bpid-range", &ret);
+ if (!range) {
+ pr_err("No 'fsl,bpid-range' property in node %s\n",
+ node->full_name);
+ return -EINVAL;
+ }
+ if (ret != 8) {
+ pr_err("'fsl,bpid-range' is not a 2-cell range in node %s\n",
+ node->full_name);
+ return -EINVAL;
+ }
+ bman_seed_bpid_range(range[0], range[1]);
+ pr_info("Bman: BPID allocator includes range %d:%d\n",
+ range[0], range[1]);
+ return 0;
+}
+
+static struct bm_portal_config * __init parse_pcfg(struct device_node *node)
+{
+ struct bm_portal_config *pcfg;
+ const u32 *index;
+ int irq, ret;
+
+ pcfg = kmalloc(sizeof(*pcfg), GFP_KERNEL);
+ if (!pcfg) {
+ pr_err("can't allocate portal config");
+ return NULL;
+ }
+
+ if (of_device_is_compatible(node, "fsl,bman-portal-1.0") ||
+ of_device_is_compatible(node, "fsl,bman-portal-1.0.0")) {
+ bman_ip_rev = BMAN_REV10;
+ bman_pool_max = 64;
+ bman_portal_max = 10;
+ } else if (of_device_is_compatible(node, "fsl,bman-portal-2.0") ||
+ of_device_is_compatible(node, "fsl,bman-portal-2.0.8")) {
+ bman_ip_rev = BMAN_REV20;
+ bman_pool_max = 8;
+ bman_portal_max = 3;
+ } else if (of_device_is_compatible(node, "fsl,bman-portal-2.1.0")) {
+ bman_ip_rev = BMAN_REV21;
+ bman_pool_max = 64;
+ bman_portal_max = 50;
+ } else if (of_device_is_compatible(node, "fsl,bman-portal-2.1.1")) {
+ bman_ip_rev = BMAN_REV21;
+ bman_pool_max = 64;
+ bman_portal_max = 25;
+ } else if (of_device_is_compatible(node, "fsl,bman-portal-2.1.2")) {
+ bman_ip_rev = BMAN_REV21;
+ bman_pool_max = 64;
+ bman_portal_max = 18;
+ } else if (of_device_is_compatible(node, "fsl,bman-portal-2.1.3")) {
+ bman_ip_rev = BMAN_REV21;
+ bman_pool_max = 64;
+ bman_portal_max = 10;
+ }
+
+ ret = of_address_to_resource(node, DPA_PORTAL_CE,
+ &pcfg->addr_phys[DPA_PORTAL_CE]);
+ if (ret) {
+ pr_err("Can't get %s property 'reg::CE'\n", node->full_name);
+ goto err;
+ }
+ ret = of_address_to_resource(node, DPA_PORTAL_CI,
+ &pcfg->addr_phys[DPA_PORTAL_CI]);
+ if (ret) {
+ pr_err("Can't get %s property 'reg::CI'\n", node->full_name);
+ goto err;
+ }
+
+ index = of_get_property(node, "cell-index", &ret);
+ if (!index || (ret != 4)) {
+ pr_err("Can't get %s property '%s'\n", node->full_name,
+ "cell-index");
+ goto err;
+ }
+ if (*index >= bman_portal_max)
+ goto err;
+
+ pcfg->public_cfg.cpu = -1;
+
+ irq = irq_of_parse_and_map(node, 0);
+ if (irq == NO_IRQ) {
+ pr_err("Can't get %s property 'interrupts'\n", node->full_name);
+ goto err;
+ }
+ pcfg->public_cfg.irq = irq;
+ pcfg->public_cfg.index = *index;
+ bman_depletion_fill(&pcfg->public_cfg.mask);
+
+ pcfg->addr_virt[DPA_PORTAL_CE] = ioremap_prot(
+ pcfg->addr_phys[DPA_PORTAL_CE].start,
+ resource_size(&pcfg->addr_phys[DPA_PORTAL_CE]),
+ 0);
+ pcfg->addr_virt[DPA_PORTAL_CI] = ioremap_prot(
+ pcfg->addr_phys[DPA_PORTAL_CI].start,
+ resource_size(&pcfg->addr_phys[DPA_PORTAL_CI]),
+ _PAGE_GUARDED | _PAGE_NO_CACHE);
+
+ /* disable bp depletion */
+ __raw_writel(0x0, pcfg->addr_virt[DPA_PORTAL_CI] + 0x200);
+ __raw_writel(0x0, pcfg->addr_virt[DPA_PORTAL_CI] + 0x204);
+ return pcfg;
+err:
+ kfree(pcfg);
+ return NULL;
+}
+
+static struct bm_portal_config *get_pcfg(struct list_head *list)
+{
+ struct bm_portal_config *pcfg;
+ if (list_empty(list))
+ return NULL;
+ pcfg = list_entry(list->prev, struct bm_portal_config, list);
+ list_del(&pcfg->list);
+ return pcfg;
+}
+
+static struct bm_portal_config *get_pcfg_idx(struct list_head *list,
+ uint32_t idx)
+{
+ struct bm_portal_config *pcfg;
+ if (list_empty(list))
+ return NULL;
+ list_for_each_entry(pcfg, list, list) {
+ if (pcfg->public_cfg.index == idx) {
+ list_del(&pcfg->list);
+ return pcfg;
+ }
+ }
+ return NULL;
+}
+
+struct bm_portal_config *bm_get_unused_portal(void)
+{
+ return bm_get_unused_portal_idx(QBMAN_ANY_PORTAL_IDX);
+}
+
+struct bm_portal_config *bm_get_unused_portal_idx(uint32_t idx)
+{
+ struct bm_portal_config *ret;
+ spin_lock(&unused_pcfgs_lock);
+ if (idx == QBMAN_ANY_PORTAL_IDX)
+ ret = get_pcfg(&unused_pcfgs);
+ else
+ ret = get_pcfg_idx(&unused_pcfgs, idx);
+ spin_unlock(&unused_pcfgs_lock);
+ return ret;
+}
+
+void bm_put_unused_portal(struct bm_portal_config *pcfg)
+{
+ spin_lock(&unused_pcfgs_lock);
+ list_add(&pcfg->list, &unused_pcfgs);
+ spin_unlock(&unused_pcfgs_lock);
+}
+
+static struct bman_portal *init_pcfg(struct bm_portal_config *pcfg)
+{
+ struct bman_portal *p;
+ p = bman_create_affine_portal(pcfg);
+ if (p) {
+#ifdef CONFIG_FSL_DPA_PIRQ_SLOW
+ bman_p_irqsource_add(p, BM_PIRQ_RCRI | BM_PIRQ_BSCN);
+#endif
+ pr_info("Bman portal %sinitialised, cpu %d\n",
+ pcfg->public_cfg.is_shared ? "(shared) " : "",
+ pcfg->public_cfg.cpu);
+ affine_bportals[pcfg->public_cfg.cpu] = p;
+ } else
+ pr_crit("Bman portal failure on cpu %d\n",
+ pcfg->public_cfg.cpu);
+ return p;
+}
+
+static void init_slave(int cpu)
+{
+ struct bman_portal *p;
+ p = bman_create_affine_slave(shared_portals[shared_portals_idx++], cpu);
+ if (!p)
+ pr_err("Bman slave portal failure on cpu %d\n", cpu);
+ else
+ pr_info("Bman portal %sinitialised, cpu %d\n", "(slave) ", cpu);
+ if (shared_portals_idx >= num_shared_portals)
+ shared_portals_idx = 0;
+ affine_bportals[cpu] = p;
+}
+
+/* Bootarg "bportals=[...]" has the same syntax as "qportals=", and so the
+ * parsing is in dpa_sys.h. The syntax is a comma-separated list of indexes
+ * and/or ranges of indexes, with each being optionally prefixed by "s" to
+ * explicitly mark it or them for sharing.
+ * Eg;
+ * bportals=s0,1-3,s4
+ * means that cpus 1,2,3 get "unshared" portals, cpus 0 and 4 get "shared"
+ * portals, and any remaining cpus share the portals that are assigned to cpus 0
+ * or 4, selected in a round-robin fashion. (In this example, cpu 5 would share
+ * cpu 0's portal, cpu 6 would share cpu4's portal, and cpu 7 would share cpu
+ * 0's portal.) */
+static struct cpumask want_unshared __initdata; /* cpus requested without "s" */
+static struct cpumask want_shared __initdata; /* cpus requested with "s" */
+
+static int __init parse_bportals(char *str)
+{
+ return parse_portals_bootarg(str, &want_shared, &want_unshared,
+ "bportals");
+}
+__setup("bportals=", parse_bportals);
+
+static void bman_offline_cpu(unsigned int cpu)
+{
+ struct bman_portal *p;
+ const struct bm_portal_config *pcfg;
+ p = (struct bman_portal *)affine_bportals[cpu];
+ if (p) {
+ pcfg = bman_get_bm_portal_config(p);
+ if (pcfg)
+ irq_set_affinity(pcfg->public_cfg.irq, cpumask_of(0));
+ }
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static void bman_online_cpu(unsigned int cpu)
+{
+ struct bman_portal *p;
+ const struct bm_portal_config *pcfg;
+ p = (struct bman_portal *)affine_bportals[cpu];
+ if (p) {
+ pcfg = bman_get_bm_portal_config(p);
+ if (pcfg)
+ irq_set_affinity(pcfg->public_cfg.irq, cpumask_of(cpu));
+ }
+}
+
+static int __cpuinit bman_hotplug_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ unsigned int cpu = (unsigned long)hcpu;
+
+ switch (action) {
+ case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
+ bman_online_cpu(cpu);
+ break;
+ case CPU_DOWN_PREPARE:
+ case CPU_DOWN_PREPARE_FROZEN:
+ bman_offline_cpu(cpu);
+ default:
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block bman_hotplug_cpu_notifier = {
+ .notifier_call = bman_hotplug_cpu_callback,
+};
+#endif /* CONFIG_HOTPLUG_CPU */
+
+/* Initialise the Bman driver. The meat of this function deals with portals. The
+ * following describes the flow of portal-handling, the code "steps" refer to
+ * this description;
+ * 1. Portal configs are parsed from the device-tree into 'unused_pcfgs', with
+ * ::cpu==-1. Regions and interrupts are mapped (but interrupts are not
+ * bound).
+ * 2. The "want_shared" and "want_unshared" lists (as filled by the
+ * "bportals=[...]" bootarg) are processed, allocating portals and assigning
+ * them to cpus, placing them in the relevant list and setting ::cpu as
+ * appropriate. If no "bportals" bootarg was present, the defaut is to try to
+ * assign portals to all online cpus at the time of driver initialisation.
+ * Any failure to allocate portals (when parsing the "want" lists or when
+ * using default behaviour) will be silently tolerated (the "fixup" logic in
+ * step 3 will determine what happens in this case).
+ * 3. Do fixups relative to cpu_online_mask(). If no portals are marked for
+ * sharing and sharing is required (because not all cpus have been assigned
+ * portals), then one portal will marked for sharing. Conversely if no
+ * sharing is required, any portals marked for sharing will not be shared. It
+ * may be that sharing occurs when it wasn't expected, if portal allocation
+ * failed to honour all the requested assignments (including the default
+ * assignments if no bootarg is present).
+ * 4. Unshared portals are initialised on their respective cpus.
+ * 5. Shared portals are initialised on their respective cpus.
+ * 6. Each remaining cpu is initialised to slave to one of the shared portals,
+ * which are selected in a round-robin fashion.
+ * Any portal configs left unused are available for USDPAA allocation.
+ */
+__init int bman_init(void)
+{
+ struct cpumask slave_cpus;
+ struct cpumask unshared_cpus = *cpu_none_mask;
+ struct cpumask shared_cpus = *cpu_none_mask;
+ LIST_HEAD(unshared_pcfgs);
+ LIST_HEAD(shared_pcfgs);
+ struct device_node *dn;
+ struct bm_portal_config *pcfg;
+ struct bman_portal *p;
+ int cpu, ret;
+ struct cpumask offline_cpus;
+
+ /* Initialise the Bman (CCSR) device */
+ for_each_compatible_node(dn, NULL, "fsl,bman") {
+ if (!bman_init_ccsr(dn))
+ pr_info("Bman err interrupt handler present\n");
+ else
+ pr_err("Bman CCSR setup failed\n");
+ }
+ /* Initialise any declared buffer pools */
+ for_each_compatible_node(dn, NULL, "fsl,bpool") {
+ ret = fsl_bpool_init(dn);
+ if (ret)
+ return ret;
+ }
+ /* Step 1. See comments at the beginning of the file. */
+ for_each_compatible_node(dn, NULL, "fsl,bman-portal") {
+ if (!of_device_is_available(dn))
+ continue;
+ pcfg = parse_pcfg(dn);
+ if (pcfg)
+ list_add_tail(&pcfg->list, &unused_pcfgs);
+ }
+ /* Step 2. */
+ for_each_possible_cpu(cpu) {
+ if (cpumask_test_cpu(cpu, &want_shared)) {
+ pcfg = get_pcfg(&unused_pcfgs);
+ if (!pcfg)
+ break;
+ pcfg->public_cfg.cpu = cpu;
+ list_add_tail(&pcfg->list, &shared_pcfgs);
+ cpumask_set_cpu(cpu, &shared_cpus);
+ }
+ if (cpumask_test_cpu(cpu, &want_unshared)) {
+ if (cpumask_test_cpu(cpu, &shared_cpus))
+ continue;
+ pcfg = get_pcfg(&unused_pcfgs);
+ if (!pcfg)
+ break;
+ pcfg->public_cfg.cpu = cpu;
+ list_add_tail(&pcfg->list, &unshared_pcfgs);
+ cpumask_set_cpu(cpu, &unshared_cpus);
+ }
+ }
+ if (list_empty(&shared_pcfgs) && list_empty(&unshared_pcfgs)) {
+ /* Default, give an unshared portal to each online cpu */
+ for_each_possible_cpu(cpu) {
+ pcfg = get_pcfg(&unused_pcfgs);
+ if (!pcfg)
+ break;
+ pcfg->public_cfg.cpu = cpu;
+ list_add_tail(&pcfg->list, &unshared_pcfgs);
+ cpumask_set_cpu(cpu, &unshared_cpus);
+ }
+ }
+ /* Step 3. */
+ cpumask_andnot(&slave_cpus, cpu_possible_mask, &shared_cpus);
+ cpumask_andnot(&slave_cpus, &slave_cpus, &unshared_cpus);
+ if (cpumask_empty(&slave_cpus)) {
+ /* No sharing required */
+ if (!list_empty(&shared_pcfgs)) {
+ /* Migrate "shared" to "unshared" */
+ cpumask_or(&unshared_cpus, &unshared_cpus,
+ &shared_cpus);
+ cpumask_clear(&shared_cpus);
+ list_splice_tail(&shared_pcfgs, &unshared_pcfgs);
+ INIT_LIST_HEAD(&shared_pcfgs);
+ }
+ } else {
+ /* Sharing required */
+ if (list_empty(&shared_pcfgs)) {
+ /* Migrate one "unshared" to "shared" */
+ pcfg = get_pcfg(&unshared_pcfgs);
+ if (!pcfg) {
+ pr_crit("No BMan portals available!\n");
+ return 0;
+ }
+ cpumask_clear_cpu(pcfg->public_cfg.cpu, &unshared_cpus);
+ cpumask_set_cpu(pcfg->public_cfg.cpu, &shared_cpus);
+ list_add_tail(&pcfg->list, &shared_pcfgs);
+ }
+ }
+ /* Step 4. */
+ list_for_each_entry(pcfg, &unshared_pcfgs, list) {
+ pcfg->public_cfg.is_shared = 0;
+ p = init_pcfg(pcfg);
+ }
+ /* Step 5. */
+ list_for_each_entry(pcfg, &shared_pcfgs, list) {
+ pcfg->public_cfg.is_shared = 1;
+ p = init_pcfg(pcfg);
+ if (p)
+ shared_portals[num_shared_portals++] = p;
+ }
+ /* Step 6. */
+ if (!cpumask_empty(&slave_cpus))
+ for_each_cpu(cpu, &slave_cpus)
+ init_slave(cpu);
+ pr_info("Bman portals initialised\n");
+ cpumask_andnot(&offline_cpus, cpu_possible_mask, cpu_online_mask);
+ for_each_cpu(cpu, &offline_cpus)
+ bman_offline_cpu(cpu);
+#ifdef CONFIG_HOTPLUG_CPU
+ register_hotcpu_notifier(&bman_hotplug_cpu_notifier);
+#endif
+ return 0;
+}
+
+__init int bman_resource_init(void)
+{
+ struct device_node *dn;
+ int ret;
+
+ /* Initialise BPID allocation ranges */
+ for_each_compatible_node(dn, NULL, "fsl,bpid-range") {
+ ret = fsl_bpid_range_init(dn);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+#ifdef CONFIG_SUSPEND
+void suspend_unused_bportal(void)
+{
+ struct bm_portal_config *pcfg;
+
+ if (list_empty(&unused_pcfgs))
+ return;
+
+ list_for_each_entry(pcfg, &unused_pcfgs, list) {
+#ifdef CONFIG_PM_DEBUG
+ pr_info("Need to save bportal %d\n", pcfg->public_cfg.index);
+#endif
+ /* save isdr, disable all via isdr, clear isr */
+ pcfg->saved_isdr =
+ __raw_readl(pcfg->addr_virt[DPA_PORTAL_CI] + 0xe08);
+ __raw_writel(0xffffffff, pcfg->addr_virt[DPA_PORTAL_CI] +
+ 0xe08);
+ __raw_writel(0xffffffff, pcfg->addr_virt[DPA_PORTAL_CI] +
+ 0xe00);
+ }
+ return;
+}
+
+void resume_unused_bportal(void)
+{
+ struct bm_portal_config *pcfg;
+
+ if (list_empty(&unused_pcfgs))
+ return;
+
+ list_for_each_entry(pcfg, &unused_pcfgs, list) {
+#ifdef CONFIG_PM_DEBUG
+ pr_info("Need to resume bportal %d\n", pcfg->public_cfg.index);
+#endif
+ /* restore isdr */
+ __raw_writel(pcfg->saved_isdr,
+ pcfg->addr_virt[DPA_PORTAL_CI] + 0xe08);
+ }
+ return;
+}
+#endif
diff --git a/drivers/staging/fsl_qbman/bman_high.c b/drivers/staging/fsl_qbman/bman_high.c
new file mode 100644
index 0000000..cc25de4
--- /dev/null
+++ b/drivers/staging/fsl_qbman/bman_high.c
@@ -0,0 +1,1108 @@
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "bman_low.h"
+
+/* Compilation constants */
+#define RCR_THRESH 2 /* reread h/w CI when running out of space */
+#define IRQNAME "BMan portal %d"
+#define MAX_IRQNAME 16 /* big enough for "BMan portal %d" */
+
+struct bman_portal {
+ struct bm_portal p;
+ /* 2-element array. pools[0] is mask, pools[1] is snapshot. */
+ struct bman_depletion *pools;
+ int thresh_set;
+ unsigned long irq_sources;
+ u32 slowpoll; /* only used when interrupts are off */
+#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC
+ struct bman_pool *rcri_owned; /* only 1 release WAIT_SYNC at a time */
+#endif
+#ifdef CONFIG_FSL_DPA_PORTAL_SHARE
+ raw_spinlock_t sharing_lock; /* only used if is_shared */
+ int is_shared;
+ struct bman_portal *sharing_redirect;
+#endif
+ /* When the cpu-affine portal is activated, this is non-NULL */
+ const struct bm_portal_config *config;
+ /* This is needed for power management */
+ struct platform_device *pdev;
+ /* 64-entry hash-table of pool objects that are tracking depletion
+ * entry/exit (ie. BMAN_POOL_FLAG_DEPLETION). This isn't fast-path, so
+ * we're not fussy about cache-misses and so forth - whereas the above
+ * members should all fit in one cacheline.
+ * BTW, with 64 entries in the hash table and 64 buffer pools to track,
+ * you'll never guess the hash-function ... */
+ struct bman_pool *cb[64];
+ char irqname[MAX_IRQNAME];
+ /* Track if the portal was alloced by the driver */
+ u8 alloced;
+ /* power management data */
+ u32 save_isdr;
+};
+
+/* For an explanation of the locking, redirection, or affine-portal logic,
+ * please consult the Qman driver for details. This is the same, only simpler
+ * (no fiddly Qman-specific bits.) */
+#ifdef CONFIG_FSL_DPA_PORTAL_SHARE
+#define PORTAL_IRQ_LOCK(p, irqflags) \
+ do { \
+ if ((p)->is_shared) \
+ raw_spin_lock_irqsave(&(p)->sharing_lock, irqflags); \
+ else \
+ local_irq_save(irqflags); \
+ } while (0)
+#define PORTAL_IRQ_UNLOCK(p, irqflags) \
+ do { \
+ if ((p)->is_shared) \
+ raw_spin_unlock_irqrestore(&(p)->sharing_lock, \
+ irqflags); \
+ else \
+ local_irq_restore(irqflags); \
+ } while (0)
+#else
+#define PORTAL_IRQ_LOCK(p, irqflags) local_irq_save(irqflags)
+#define PORTAL_IRQ_UNLOCK(p, irqflags) local_irq_restore(irqflags)
+#endif
+
+static cpumask_t affine_mask;
+static DEFINE_SPINLOCK(affine_mask_lock);
+static DEFINE_PER_CPU(struct bman_portal, bman_affine_portal);
+static inline struct bman_portal *get_raw_affine_portal(void)
+{
+ return &get_cpu_var(bman_affine_portal);
+}
+#ifdef CONFIG_FSL_DPA_PORTAL_SHARE
+static inline struct bman_portal *get_affine_portal(void)
+{
+ struct bman_portal *p = get_raw_affine_portal();
+ if (p->sharing_redirect)
+ return p->sharing_redirect;
+ return p;
+}
+#else
+#define get_affine_portal() get_raw_affine_portal()
+#endif
+static inline void put_affine_portal(void)
+{
+ put_cpu_var(bman_affine_portal);
+}
+static inline struct bman_portal *get_poll_portal(void)
+{
+ return &__get_cpu_var(bman_affine_portal);
+}
+#define put_poll_portal()
+
+/* GOTCHA: this object type refers to a pool, it isn't *the* pool. There may be
+ * more than one such object per Bman buffer pool, eg. if different users of the
+ * pool are operating via different portals. */
+struct bman_pool {
+ struct bman_pool_params params;
+ /* Used for hash-table admin when using depletion notifications. */
+ struct bman_portal *portal;
+ struct bman_pool *next;
+ /* stockpile state - NULL unless BMAN_POOL_FLAG_STOCKPILE is set */
+ struct bm_buffer *sp;
+ unsigned int sp_fill;
+#ifdef CONFIG_FSL_DPA_CHECKING
+ atomic_t in_use;
+#endif
+};
+
+/* (De)Registration of depletion notification callbacks */
+static void depletion_link(struct bman_portal *portal, struct bman_pool *pool)
+{
+ __maybe_unused unsigned long irqflags;
+ pool->portal = portal;
+ PORTAL_IRQ_LOCK(portal, irqflags);
+ pool->next = portal->cb[pool->params.bpid];
+ portal->cb[pool->params.bpid] = pool;
+ if (!pool->next)
+ /* First object for that bpid on this portal, enable the BSCN
+ * mask bit. */
+ bm_isr_bscn_mask(&portal->p, pool->params.bpid, 1);
+ PORTAL_IRQ_UNLOCK(portal, irqflags);
+}
+static void depletion_unlink(struct bman_pool *pool)
+{
+ struct bman_pool *it, *last = NULL;
+ struct bman_pool **base = &pool->portal->cb[pool->params.bpid];
+ __maybe_unused unsigned long irqflags;
+ PORTAL_IRQ_LOCK(pool->portal, irqflags);
+ it = *base; /* <-- gotcha, don't do this prior to the irq_save */
+ while (it != pool) {
+ last = it;
+ it = it->next;
+ }
+ if (!last)
+ *base = pool->next;
+ else
+ last->next = pool->next;
+ if (!last && !pool->next) {
+ /* Last object for that bpid on this portal, disable the BSCN
+ * mask bit. */
+ bm_isr_bscn_mask(&pool->portal->p, pool->params.bpid, 0);
+ /* And "forget" that we last saw this pool as depleted */
+ bman_depletion_unset(&pool->portal->pools[1],
+ pool->params.bpid);
+ }
+ PORTAL_IRQ_UNLOCK(pool->portal, irqflags);
+}
+
+/* In the case that the application's core loop calls qman_poll() and
+ * bman_poll(), we ought to balance how often we incur the overheads of the
+ * slow-path poll. We'll use two decrementer sources. The idle decrementer
+ * constant is used when the last slow-poll detected no work to do, and the busy
+ * decrementer constant when the last slow-poll had work to do. */
+#define SLOW_POLL_IDLE 1000
+#define SLOW_POLL_BUSY 10
+static u32 __poll_portal_slow(struct bman_portal *p, u32 is);
+
+/* Portal interrupt handler */
+static irqreturn_t portal_isr(__always_unused int irq, void *ptr)
+{
+ struct bman_portal *p = ptr;
+ u32 clear = p->irq_sources;
+ u32 is = bm_isr_status_read(&p->p) & p->irq_sources;
+ clear |= __poll_portal_slow(p, is);
+ bm_isr_status_clear(&p->p, clear);
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_SUSPEND
+static int _bman_portal_suspend_noirq(struct device *dev)
+{
+ struct bman_portal *p = (struct bman_portal *)dev->platform_data;
+#ifdef CONFIG_PM_DEBUG
+ struct platform_device *pdev = to_platform_device(dev);
+#endif
+ p->save_isdr = bm_isr_disable_read(&p->p);
+ bm_isr_disable_write(&p->p, 0xffffffff);
+ bm_isr_status_clear(&p->p, 0xffffffff);
+#ifdef CONFIG_PM_DEBUG
+ pr_info("Suspend for %s\n", pdev->name);
+#endif
+ return 0;
+}
+
+static int _bman_portal_resume_noirq(struct device *dev)
+{
+ struct bman_portal *p = (struct bman_portal *)dev->platform_data;
+
+ /* restore isdr */
+ bm_isr_disable_write(&p->p, p->save_isdr);
+ return 0;
+}
+#else
+#define _bman_portal_suspend_noirq NULL
+#define _bman_portal_resume_noirq NULL
+#endif
+
+struct dev_pm_domain bman_portal_device_pm_domain = {
+ .ops = {
+ USE_PLATFORM_PM_SLEEP_OPS
+ .suspend_noirq = _bman_portal_suspend_noirq,
+ .resume_noirq = _bman_portal_resume_noirq,
+ }
+};
+
+struct bman_portal *bman_create_portal(
+ struct bman_portal *portal,
+ const struct bm_portal_config *config)
+{
+ struct bm_portal *__p;
+ const struct bman_depletion *pools = &config->public_cfg.mask;
+ int ret;
+ u8 bpid = 0;
+ char buf[16];
+
+ if (!portal) {
+ portal = kmalloc(sizeof(*portal), GFP_KERNEL);
+ if (!portal)
+ return portal;
+ portal->alloced = 1;
+ } else
+ portal->alloced = 0;
+
+ __p = &portal->p;
+
+ /* prep the low-level portal struct with the mapped addresses from the
+ * config, everything that follows depends on it and "config" is more
+ * for (de)reference... */
+ __p->addr.addr_ce = config->addr_virt[DPA_PORTAL_CE];
+ __p->addr.addr_ci = config->addr_virt[DPA_PORTAL_CI];
+ if (bm_rcr_init(__p, bm_rcr_pvb, bm_rcr_cce)) {
+ pr_err("Bman RCR initialisation failed\n");
+ goto fail_rcr;
+ }
+ if (bm_mc_init(__p)) {
+ pr_err("Bman MC initialisation failed\n");
+ goto fail_mc;
+ }
+ if (bm_isr_init(__p)) {
+ pr_err("Bman ISR initialisation failed\n");
+ goto fail_isr;
+ }
+ portal->pools = kmalloc(2 * sizeof(*pools), GFP_KERNEL);
+ if (!portal->pools)
+ goto fail_pools;
+ portal->pools[0] = *pools;
+ bman_depletion_init(portal->pools + 1);
+ while (bpid < bman_pool_max) {
+ /* Default to all BPIDs disabled, we enable as required at
+ * run-time. */
+ bm_isr_bscn_mask(__p, bpid, 0);
+ bpid++;
+ }
+ portal->slowpoll = 0;
+#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC
+ portal->rcri_owned = NULL;
+#endif
+#ifdef CONFIG_FSL_DPA_PORTAL_SHARE
+ raw_spin_lock_init(&portal->sharing_lock);
+ portal->is_shared = config->public_cfg.is_shared;
+ portal->sharing_redirect = NULL;
+#endif
+ sprintf(buf, "bportal-%u", config->public_cfg.index);
+ portal->pdev = platform_device_alloc(buf, -1);
+ if (!portal->pdev)
+ goto fail_devalloc;
+ portal->pdev->dev.pm_domain = &bman_portal_device_pm_domain;
+ portal->pdev->dev.platform_data = portal;
+ ret = platform_device_add(portal->pdev);
+ if (ret)
+ goto fail_devadd;
+ memset(&portal->cb, 0, sizeof(portal->cb));
+ /* Write-to-clear any stale interrupt status bits */
+ bm_isr_disable_write(__p, 0xffffffff);
+ portal->irq_sources = 0;
+ bm_isr_enable_write(__p, portal->irq_sources);
+ bm_isr_status_clear(__p, 0xffffffff);
+ snprintf(portal->irqname, MAX_IRQNAME, IRQNAME, config->public_cfg.cpu);
+ if (request_irq(config->public_cfg.irq, portal_isr, 0, portal->irqname,
+ portal)) {
+ pr_err("request_irq() failed\n");
+ goto fail_irq;
+ }
+ if ((config->public_cfg.cpu != -1) &&
+ irq_can_set_affinity(config->public_cfg.irq) &&
+ irq_set_affinity(config->public_cfg.irq,
+ cpumask_of(config->public_cfg.cpu))) {
+ pr_err("irq_set_affinity() failed\n");
+ goto fail_affinity;
+ }
+
+ /* Need RCR to be empty before continuing */
+ ret = bm_rcr_get_fill(__p);
+ if (ret) {
+ pr_err("Bman RCR unclean\n");
+ goto fail_rcr_empty;
+ }
+ /* Success */
+ portal->config = config;
+
+ bm_isr_disable_write(__p, 0);
+ bm_isr_uninhibit(__p);
+ return portal;
+fail_rcr_empty:
+fail_affinity:
+ free_irq(config->public_cfg.irq, portal);
+fail_irq:
+ platform_device_del(portal->pdev);
+fail_devadd:
+ platform_device_put(portal->pdev);
+fail_devalloc:
+ kfree(portal->pools);
+fail_pools:
+ bm_isr_finish(__p);
+fail_isr:
+ bm_mc_finish(__p);
+fail_mc:
+ bm_rcr_finish(__p);
+fail_rcr:
+ if (portal->alloced)
+ kfree(portal);
+ return NULL;
+}
+
+struct bman_portal *bman_create_affine_portal(
+ const struct bm_portal_config *config)
+{
+ struct bman_portal *portal;
+
+ portal = &per_cpu(bman_affine_portal, config->public_cfg.cpu);
+ portal = bman_create_portal(portal, config);
+ if (portal) {
+ spin_lock(&affine_mask_lock);
+ cpumask_set_cpu(config->public_cfg.cpu, &affine_mask);
+ spin_unlock(&affine_mask_lock);
+ }
+ return portal;
+}
+
+
+struct bman_portal *bman_create_affine_slave(struct bman_portal *redirect,
+ int cpu)
+{
+#ifdef CONFIG_FSL_DPA_PORTAL_SHARE
+ struct bman_portal *p;
+ p = &per_cpu(bman_affine_portal, cpu);
+ BUG_ON(p->config);
+ BUG_ON(p->is_shared);
+ BUG_ON(!redirect->config->public_cfg.is_shared);
+ p->irq_sources = 0;
+ p->sharing_redirect = redirect;
+ return p;
+#else
+ BUG();
+ return NULL;
+#endif
+}
+
+void bman_destroy_portal(struct bman_portal *bm)
+{
+ const struct bm_portal_config *pcfg;
+ pcfg = bm->config;
+ bm_rcr_cce_update(&bm->p);
+ bm_rcr_cce_update(&bm->p);
+
+ free_irq(pcfg->public_cfg.irq, bm);
+
+ kfree(bm->pools);
+ bm_isr_finish(&bm->p);
+ bm_mc_finish(&bm->p);
+ bm_rcr_finish(&bm->p);
+ bm->config = NULL;
+ if (bm->alloced)
+ kfree(bm);
+}
+
+const struct bm_portal_config *bman_destroy_affine_portal(void)
+{
+ struct bman_portal *bm = get_raw_affine_portal();
+ const struct bm_portal_config *pcfg;
+#ifdef CONFIG_FSL_DPA_PORTAL_SHARE
+ if (bm->sharing_redirect) {
+ bm->sharing_redirect = NULL;
+ put_affine_portal();
+ return NULL;
+ }
+ bm->is_shared = 0;
+#endif
+ pcfg = bm->config;
+ bman_destroy_portal(bm);
+ spin_lock(&affine_mask_lock);
+ cpumask_clear_cpu(pcfg->public_cfg.cpu, &affine_mask);
+ spin_unlock(&affine_mask_lock);
+ put_affine_portal();
+ return pcfg;
+}
+
+/* When release logic waits on available RCR space, we need a global waitqueue
+ * in the case of "affine" use (as the waits wake on different cpus which means
+ * different portals - so we can't wait on any per-portal waitqueue). */
+static DECLARE_WAIT_QUEUE_HEAD(affine_queue);
+
+static u32 __poll_portal_slow(struct bman_portal *p, u32 is)
+{
+ struct bman_depletion tmp;
+ u32 ret = is;
+
+ /* There is a gotcha to be aware of. If we do the query before clearing
+ * the status register, we may miss state changes that occur between the
+ * two. If we write to clear the status register before the query, the
+ * cache-enabled query command may overtake the status register write
+ * unless we use a heavyweight sync (which we don't want). Instead, we
+ * write-to-clear the status register then *read it back* before doing
+ * the query, hence the odd while loop with the 'is' accumulation. */
+ if (is & BM_PIRQ_BSCN) {
+ struct bm_mc_result *mcr;
+ __maybe_unused unsigned long irqflags;
+ unsigned int i, j;
+ u32 __is;
+ bm_isr_status_clear(&p->p, BM_PIRQ_BSCN);
+ while ((__is = bm_isr_status_read(&p->p)) & BM_PIRQ_BSCN) {
+ is |= __is;
+ bm_isr_status_clear(&p->p, BM_PIRQ_BSCN);
+ }
+ is &= ~BM_PIRQ_BSCN;
+ PORTAL_IRQ_LOCK(p, irqflags);
+ bm_mc_start(&p->p);
+ bm_mc_commit(&p->p, BM_MCC_VERB_CMD_QUERY);
+ while (!(mcr = bm_mc_result(&p->p)))
+ cpu_relax();
+ tmp = mcr->query.ds.state;
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ for (i = 0; i < 2; i++) {
+ int idx = i * 32;
+ /* tmp is a mask of currently-depleted pools.
+ * pools[0] is mask of those we care about.
+ * pools[1] is our previous view (we only want to
+ * be told about changes). */
+ tmp.__state[i] &= p->pools[0].__state[i];
+ if (tmp.__state[i] == p->pools[1].__state[i])
+ /* fast-path, nothing to see, move along */
+ continue;
+ for (j = 0; j <= 31; j++, idx++) {
+ struct bman_pool *pool = p->cb[idx];
+ int b4 = bman_depletion_get(&p->pools[1], idx);
+ int af = bman_depletion_get(&tmp, idx);
+ if (b4 == af)
+ continue;
+ while (pool) {
+ pool->params.cb(p, pool,
+ pool->params.cb_ctx, af);
+ pool = pool->next;
+ }
+ }
+ }
+ p->pools[1] = tmp;
+ }
+
+ if (is & BM_PIRQ_RCRI) {
+ __maybe_unused unsigned long irqflags;
+ PORTAL_IRQ_LOCK(p, irqflags);
+ bm_rcr_cce_update(&p->p);
+#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC
+ /* If waiting for sync, we only cancel the interrupt threshold
+ * when the ring utilisation hits zero. */
+ if (p->rcri_owned) {
+ if (!bm_rcr_get_fill(&p->p)) {
+ p->rcri_owned = NULL;
+ bm_rcr_set_ithresh(&p->p, 0);
+ }
+ } else
+#endif
+ bm_rcr_set_ithresh(&p->p, 0);
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ wake_up(&affine_queue);
+ bm_isr_status_clear(&p->p, BM_PIRQ_RCRI);
+ is &= ~BM_PIRQ_RCRI;
+ }
+
+ /* There should be no status register bits left undefined */
+ DPA_ASSERT(!is);
+ return ret;
+}
+
+const struct bman_portal_config *bman_get_portal_config(void)
+{
+ struct bman_portal *p = get_affine_portal();
+ const struct bman_portal_config *ret = &p->config->public_cfg;
+ put_affine_portal();
+ return ret;
+}
+EXPORT_SYMBOL(bman_get_portal_config);
+
+u32 bman_irqsource_get(void)
+{
+ struct bman_portal *p = get_raw_affine_portal();
+ u32 ret = p->irq_sources & BM_PIRQ_VISIBLE;
+ put_affine_portal();
+ return ret;
+}
+EXPORT_SYMBOL(bman_irqsource_get);
+
+int bman_p_irqsource_add(struct bman_portal *p, __maybe_unused u32 bits)
+{
+#ifdef CONFIG_FSL_DPA_PORTAL_SHARE
+ if (p->sharing_redirect)
+ return -EINVAL;
+ else
+#endif
+ {
+ __maybe_unused unsigned long irqflags;
+ PORTAL_IRQ_LOCK(p, irqflags);
+ set_bits(bits & BM_PIRQ_VISIBLE, &p->irq_sources);
+ bm_isr_enable_write(&p->p, p->irq_sources);
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(bman_p_irqsource_add);
+
+int bman_irqsource_add(__maybe_unused u32 bits)
+{
+ struct bman_portal *p = get_raw_affine_portal();
+ int ret = 0;
+ ret = bman_p_irqsource_add(p, bits);
+ put_affine_portal();
+ return ret;
+}
+EXPORT_SYMBOL(bman_irqsource_add);
+
+int bman_irqsource_remove(u32 bits)
+{
+ struct bman_portal *p = get_raw_affine_portal();
+ __maybe_unused unsigned long irqflags;
+ u32 ier;
+#ifdef CONFIG_FSL_DPA_PORTAL_SHARE
+ if (p->sharing_redirect) {
+ put_affine_portal();
+ return -EINVAL;
+ }
+#endif
+ /* Our interrupt handler only processes+clears status register bits that
+ * are in p->irq_sources. As we're trimming that mask, if one of them
+ * were to assert in the status register just before we remove it from
+ * the enable register, there would be an interrupt-storm when we
+ * release the IRQ lock. So we wait for the enable register update to
+ * take effect in h/w (by reading it back) and then clear all other bits
+ * in the status register. Ie. we clear them from ISR once it's certain
+ * IER won't allow them to reassert. */
+ PORTAL_IRQ_LOCK(p, irqflags);
+ bits &= BM_PIRQ_VISIBLE;
+ clear_bits(bits, &p->irq_sources);
+ bm_isr_enable_write(&p->p, p->irq_sources);
+ ier = bm_isr_enable_read(&p->p);
+ /* Using "~ier" (rather than "bits" or "~p->irq_sources") creates a
+ * data-dependency, ie. to protect against re-ordering. */
+ bm_isr_status_clear(&p->p, ~ier);
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ return 0;
+}
+EXPORT_SYMBOL(bman_irqsource_remove);
+
+const cpumask_t *bman_affine_cpus(void)
+{
+ return &affine_mask;
+}
+EXPORT_SYMBOL(bman_affine_cpus);
+
+u32 bman_poll_slow(void)
+{
+ struct bman_portal *p = get_poll_portal();
+ u32 ret;
+#ifdef CONFIG_FSL_DPA_PORTAL_SHARE
+ if (unlikely(p->sharing_redirect))
+ ret = (u32)-1;
+ else
+#endif
+ {
+ u32 is = bm_isr_status_read(&p->p) & ~p->irq_sources;
+ ret = __poll_portal_slow(p, is);
+ bm_isr_status_clear(&p->p, ret);
+ }
+ put_poll_portal();
+ return ret;
+}
+EXPORT_SYMBOL(bman_poll_slow);
+
+/* Legacy wrapper */
+void bman_poll(void)
+{
+ struct bman_portal *p = get_poll_portal();
+#ifdef CONFIG_FSL_DPA_PORTAL_SHARE
+ if (unlikely(p->sharing_redirect))
+ goto done;
+#endif
+ if (!(p->slowpoll--)) {
+ u32 is = bm_isr_status_read(&p->p) & ~p->irq_sources;
+ u32 active = __poll_portal_slow(p, is);
+ if (active)
+ p->slowpoll = SLOW_POLL_BUSY;
+ else
+ p->slowpoll = SLOW_POLL_IDLE;
+ }
+#ifdef CONFIG_FSL_DPA_PORTAL_SHARE
+done:
+#endif
+ put_poll_portal();
+}
+EXPORT_SYMBOL(bman_poll);
+
+static const u32 zero_thresholds[4] = {0, 0, 0, 0};
+
+struct bman_pool *bman_new_pool(const struct bman_pool_params *params)
+{
+ struct bman_pool *pool = NULL;
+ u32 bpid;
+
+ if (params->flags & BMAN_POOL_FLAG_DYNAMIC_BPID) {
+ int ret = bman_alloc_bpid(&bpid);
+ if (ret)
+ return NULL;
+ } else {
+ if (params->bpid >= bman_pool_max)
+ return NULL;
+ bpid = params->bpid;
+ }
+#ifdef CONFIG_FSL_BMAN_CONFIG
+ if (params->flags & BMAN_POOL_FLAG_THRESH) {
+ int ret = bm_pool_set(bpid, params->thresholds);
+ if (ret)
+ goto err;
+ }
+#else
+ if (params->flags & BMAN_POOL_FLAG_THRESH)
+ goto err;
+#endif
+ pool = kmalloc(sizeof(*pool), GFP_KERNEL);
+ if (!pool)
+ goto err;
+ pool->sp = NULL;
+ pool->sp_fill = 0;
+ pool->params = *params;
+#ifdef CONFIG_FSL_DPA_CHECKING
+ atomic_set(&pool->in_use, 1);
+#endif
+ if (params->flags & BMAN_POOL_FLAG_DYNAMIC_BPID)
+ pool->params.bpid = bpid;
+ if (params->flags & BMAN_POOL_FLAG_STOCKPILE) {
+ pool->sp = kmalloc(sizeof(struct bm_buffer) * BMAN_STOCKPILE_SZ,
+ GFP_KERNEL);
+ if (!pool->sp)
+ goto err;
+ }
+ if (pool->params.flags & BMAN_POOL_FLAG_DEPLETION) {
+ struct bman_portal *p = get_affine_portal();
+ if (!p->pools || !bman_depletion_get(&p->pools[0], bpid)) {
+ pr_err("Depletion events disabled for bpid %d\n", bpid);
+ goto err;
+ }
+ depletion_link(p, pool);
+ put_affine_portal();
+ }
+ return pool;
+err:
+#ifdef CONFIG_FSL_BMAN_CONFIG
+ if (params->flags & BMAN_POOL_FLAG_THRESH)
+ bm_pool_set(bpid, zero_thresholds);
+#endif
+ if (params->flags & BMAN_POOL_FLAG_DYNAMIC_BPID)
+ bman_release_bpid(bpid);
+ if (pool) {
+ kfree(pool->sp);
+ kfree(pool);
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(bman_new_pool);
+
+void bman_free_pool(struct bman_pool *pool)
+{
+#ifdef CONFIG_FSL_BMAN_CONFIG
+ if (pool->params.flags & BMAN_POOL_FLAG_THRESH)
+ bm_pool_set(pool->params.bpid, zero_thresholds);
+#endif
+ if (pool->params.flags & BMAN_POOL_FLAG_DEPLETION)
+ depletion_unlink(pool);
+ if (pool->params.flags & BMAN_POOL_FLAG_STOCKPILE) {
+ if (pool->sp_fill)
+ pr_err("Stockpile not flushed, has %u in bpid %u.\n",
+ pool->sp_fill, pool->params.bpid);
+ kfree(pool->sp);
+ pool->sp = NULL;
+ pool->params.flags ^= BMAN_POOL_FLAG_STOCKPILE;
+ }
+ if (pool->params.flags & BMAN_POOL_FLAG_DYNAMIC_BPID)
+ bman_release_bpid(pool->params.bpid);
+ kfree(pool);
+}
+EXPORT_SYMBOL(bman_free_pool);
+
+const struct bman_pool_params *bman_get_params(const struct bman_pool *pool)
+{
+ return &pool->params;
+}
+EXPORT_SYMBOL(bman_get_params);
+
+static noinline void update_rcr_ci(struct bman_portal *p, u8 avail)
+{
+ if (avail)
+ bm_rcr_cce_prefetch(&p->p);
+ else
+ bm_rcr_cce_update(&p->p);
+}
+
+int bman_rcr_is_empty(void)
+{
+ __maybe_unused unsigned long irqflags;
+ struct bman_portal *p = get_affine_portal();
+ u8 avail;
+
+ PORTAL_IRQ_LOCK(p, irqflags);
+ update_rcr_ci(p, 0);
+ avail = bm_rcr_get_fill(&p->p);
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ return avail == 0;
+}
+EXPORT_SYMBOL(bman_rcr_is_empty);
+
+static inline struct bm_rcr_entry *try_rel_start(struct bman_portal **p,
+#ifdef CONFIG_FSL_DPA_CAN_WAIT
+ __maybe_unused struct bman_pool *pool,
+#endif
+ __maybe_unused unsigned long *irqflags,
+ __maybe_unused u32 flags)
+{
+ struct bm_rcr_entry *r;
+ u8 avail;
+
+ *p = get_affine_portal();
+ PORTAL_IRQ_LOCK(*p, (*irqflags));
+#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC
+ if (unlikely((flags & BMAN_RELEASE_FLAG_WAIT) &&
+ (flags & BMAN_RELEASE_FLAG_WAIT_SYNC))) {
+ if ((*p)->rcri_owned) {
+ PORTAL_IRQ_UNLOCK(*p, (*irqflags));
+ put_affine_portal();
+ return NULL;
+ }
+ (*p)->rcri_owned = pool;
+ }
+#endif
+ avail = bm_rcr_get_avail(&(*p)->p);
+ if (avail < 2)
+ update_rcr_ci(*p, avail);
+ r = bm_rcr_start(&(*p)->p);
+ if (unlikely(!r)) {
+#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC
+ if (unlikely((flags & BMAN_RELEASE_FLAG_WAIT) &&
+ (flags & BMAN_RELEASE_FLAG_WAIT_SYNC)))
+ (*p)->rcri_owned = NULL;
+#endif
+ PORTAL_IRQ_UNLOCK(*p, (*irqflags));
+ put_affine_portal();
+ }
+ return r;
+}
+
+#ifdef CONFIG_FSL_DPA_CAN_WAIT
+static noinline struct bm_rcr_entry *__wait_rel_start(struct bman_portal **p,
+ struct bman_pool *pool,
+ __maybe_unused unsigned long *irqflags,
+ u32 flags)
+{
+ struct bm_rcr_entry *rcr = try_rel_start(p, pool, irqflags, flags);
+ if (!rcr)
+ bm_rcr_set_ithresh(&(*p)->p, 1);
+ return rcr;
+}
+
+static noinline struct bm_rcr_entry *wait_rel_start(struct bman_portal **p,
+ struct bman_pool *pool,
+ __maybe_unused unsigned long *irqflags,
+ u32 flags)
+{
+ struct bm_rcr_entry *rcr;
+#ifndef CONFIG_FSL_DPA_CAN_WAIT_SYNC
+ pool = NULL;
+#endif
+ if (flags & BMAN_RELEASE_FLAG_WAIT_INT)
+ wait_event_interruptible(affine_queue,
+ (rcr = __wait_rel_start(p, pool, irqflags, flags)));
+ else
+ wait_event(affine_queue,
+ (rcr = __wait_rel_start(p, pool, irqflags, flags)));
+ return rcr;
+}
+#endif
+
+/* to facilitate better copying of bufs into the ring without either (a) copying
+ * noise into the first byte (prematurely triggering the command), nor (b) being
+ * very inefficient by copying small fields using read-modify-write */
+struct overlay_bm_buffer {
+ u32 first;
+ u32 second;
+};
+
+static inline int __bman_release(struct bman_pool *pool,
+ const struct bm_buffer *bufs, u8 num, u32 flags)
+{
+ struct bman_portal *p;
+ struct bm_rcr_entry *r;
+ struct overlay_bm_buffer *o_dest;
+ struct overlay_bm_buffer *o_src = (struct overlay_bm_buffer *)&bufs[0];
+ __maybe_unused unsigned long irqflags;
+ u32 i = num - 1;
+
+#ifdef CONFIG_FSL_DPA_CAN_WAIT
+ if (flags & BMAN_RELEASE_FLAG_WAIT)
+ r = wait_rel_start(&p, pool, &irqflags, flags);
+ else
+ r = try_rel_start(&p, pool, &irqflags, flags);
+#else
+ r = try_rel_start(&p, &irqflags, flags);
+#endif
+ if (!r)
+ return -EBUSY;
+ /* We can copy all but the first entry, as this can trigger badness
+ * with the valid-bit. Use the overlay to mask the verb byte. */
+ o_dest = (struct overlay_bm_buffer *)&r->bufs[0];
+ o_dest->first = (o_src->first & 0x0000ffff) |
+ (((u32)pool->params.bpid << 16) & 0x00ff0000);
+ o_dest->second = o_src->second;
+ if (i)
+ copy_words(&r->bufs[1], &bufs[1], i * sizeof(bufs[0]));
+ bm_rcr_pvb_commit(&p->p, BM_RCR_VERB_CMD_BPID_SINGLE |
+ (num & BM_RCR_VERB_BUFCOUNT_MASK));
+#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC
+ /* if we wish to sync we need to set the threshold after h/w sees the
+ * new ring entry. As we're mixing cache-enabled and cache-inhibited
+ * accesses, this requires a heavy-weight sync. */
+ if (unlikely((flags & BMAN_RELEASE_FLAG_WAIT) &&
+ (flags & BMAN_RELEASE_FLAG_WAIT_SYNC))) {
+ hwsync();
+ bm_rcr_set_ithresh(&p->p, 1);
+ }
+#endif
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC
+ if (unlikely((flags & BMAN_RELEASE_FLAG_WAIT) &&
+ (flags & BMAN_RELEASE_FLAG_WAIT_SYNC))) {
+ if (flags & BMAN_RELEASE_FLAG_WAIT_INT)
+ wait_event_interruptible(affine_queue,
+ (p->rcri_owned != pool));
+ else
+ wait_event(affine_queue, (p->rcri_owned != pool));
+ }
+#endif
+ return 0;
+}
+
+int bman_release(struct bman_pool *pool, const struct bm_buffer *bufs, u8 num,
+ u32 flags)
+{
+ int ret = 0;
+#ifdef CONFIG_FSL_DPA_CHECKING
+ if (!num || (num > 8))
+ return -EINVAL;
+ if (pool->params.flags & BMAN_POOL_FLAG_NO_RELEASE)
+ return -EINVAL;
+#endif
+ /* Without stockpile, this API is a pass-through to the h/w operation */
+ if (!(pool->params.flags & BMAN_POOL_FLAG_STOCKPILE))
+ return __bman_release(pool, bufs, num, flags);
+#ifdef CONFIG_FSL_DPA_CHECKING
+ if (!atomic_dec_and_test(&pool->in_use)) {
+ pr_crit("Parallel attempts to enter bman_released() detected.");
+ panic("only one instance of bman_released/acquired allowed");
+ }
+#endif
+ /* This needs some explanation. Adding the given buffers may take the
+ * stockpile over the threshold, but in fact the stockpile may already
+ * *be* over the threshold if a previous release-to-hw attempt had
+ * failed. So we have 3 cases to cover;
+ * 1. we add to the stockpile and don't hit the threshold,
+ * 2. we add to the stockpile, hit the threshold and release-to-hw,
+ * 3. we have to release-to-hw before adding to the stockpile
+ * (not enough room in the stockpile for case 2).
+ * Our constraints on thresholds guarantee that in case 3, there must be
+ * at least 8 bufs already in the stockpile, so all release-to-hw ops
+ * are for 8 bufs. Despite all this, the API must indicate whether the
+ * given buffers were taken off the caller's hands, irrespective of
+ * whether a release-to-hw was attempted. */
+ while (num) {
+ /* Add buffers to stockpile if they fit */
+ if ((pool->sp_fill + num) < BMAN_STOCKPILE_SZ) {
+ copy_words(pool->sp + pool->sp_fill, bufs,
+ sizeof(struct bm_buffer) * num);
+ pool->sp_fill += num;
+ num = 0; /* --> will return success no matter what */
+ }
+ /* Do hw op if hitting the high-water threshold */
+ if ((pool->sp_fill + num) >= BMAN_STOCKPILE_HIGH) {
+ ret = __bman_release(pool,
+ pool->sp + (pool->sp_fill - 8), 8, flags);
+ if (ret) {
+ ret = (num ? ret : 0);
+ goto release_done;
+ }
+ pool->sp_fill -= 8;
+ }
+ }
+release_done:
+#ifdef CONFIG_FSL_DPA_CHECKING
+ atomic_inc(&pool->in_use);
+#endif
+ return ret;
+}
+EXPORT_SYMBOL(bman_release);
+
+static inline int __bman_acquire(struct bman_pool *pool, struct bm_buffer *bufs,
+ u8 num)
+{
+ struct bman_portal *p = get_affine_portal();
+ struct bm_mc_command *mcc;
+ struct bm_mc_result *mcr;
+ __maybe_unused unsigned long irqflags;
+ int ret;
+
+ PORTAL_IRQ_LOCK(p, irqflags);
+ mcc = bm_mc_start(&p->p);
+ mcc->acquire.bpid = pool->params.bpid;
+ bm_mc_commit(&p->p, BM_MCC_VERB_CMD_ACQUIRE |
+ (num & BM_MCC_VERB_ACQUIRE_BUFCOUNT));
+ while (!(mcr = bm_mc_result(&p->p)))
+ cpu_relax();
+ ret = mcr->verb & BM_MCR_VERB_ACQUIRE_BUFCOUNT;
+ if (bufs)
+ copy_words(&bufs[0], &mcr->acquire.bufs[0],
+ num * sizeof(bufs[0]));
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ if (ret != num)
+ ret = -ENOMEM;
+ return ret;
+}
+
+int bman_acquire(struct bman_pool *pool, struct bm_buffer *bufs, u8 num,
+ u32 flags)
+{
+ int ret = 0;
+#ifdef CONFIG_FSL_DPA_CHECKING
+ if (!num || (num > 8))
+ return -EINVAL;
+ if (pool->params.flags & BMAN_POOL_FLAG_ONLY_RELEASE)
+ return -EINVAL;
+#endif
+ /* Without stockpile, this API is a pass-through to the h/w operation */
+ if (!(pool->params.flags & BMAN_POOL_FLAG_STOCKPILE))
+ return __bman_acquire(pool, bufs, num);
+#ifdef CONFIG_FSL_DPA_CHECKING
+ if (!atomic_dec_and_test(&pool->in_use)) {
+ pr_crit("Parallel attempts to enter bman_acquire() detected.");
+ panic("only one instance of bman_released/acquired allowed");
+ }
+#endif
+ /* Only need a h/w op if we'll hit the low-water thresh */
+ if (!(flags & BMAN_ACQUIRE_FLAG_STOCKPILE) &&
+ (pool->sp_fill <= (BMAN_STOCKPILE_LOW + num))) {
+ /* refill stockpile with max amount, but if max amount
+ * isn't available, try amount the user wants */
+ int bufcount = 8;
+ ret = __bman_acquire(pool, pool->sp + pool->sp_fill, bufcount);
+ if (ret < 0 && bufcount != num) {
+ bufcount = num;
+ /* Maybe buffer pool has less than 8 */
+ ret = __bman_acquire(pool, pool->sp + pool->sp_fill,
+ bufcount);
+ }
+ if (ret < 0)
+ goto hw_starved;
+ DPA_ASSERT(ret == bufcount);
+ pool->sp_fill += bufcount;
+ } else {
+hw_starved:
+ if (pool->sp_fill < num) {
+ ret = -ENOMEM;
+ goto acquire_done;
+ }
+ }
+ copy_words(bufs, pool->sp + (pool->sp_fill - num),
+ sizeof(struct bm_buffer) * num);
+ pool->sp_fill -= num;
+ ret = num;
+acquire_done:
+#ifdef CONFIG_FSL_DPA_CHECKING
+ atomic_inc(&pool->in_use);
+#endif
+ return ret;
+}
+EXPORT_SYMBOL(bman_acquire);
+
+int bman_flush_stockpile(struct bman_pool *pool, u32 flags)
+{
+ u8 num;
+ int ret;
+
+ while (pool->sp_fill) {
+ num = ((pool->sp_fill > 8) ? 8 : pool->sp_fill);
+ ret = __bman_release(pool, pool->sp + (pool->sp_fill - num),
+ num, flags);
+ if (ret)
+ return ret;
+ pool->sp_fill -= num;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(bman_flush_stockpile);
+
+int bman_query_pools(struct bm_pool_state *state)
+{
+ struct bman_portal *p = get_affine_portal();
+ struct bm_mc_result *mcr;
+ __maybe_unused unsigned long irqflags;
+
+ PORTAL_IRQ_LOCK(p, irqflags);
+ bm_mc_start(&p->p);
+ bm_mc_commit(&p->p, BM_MCC_VERB_CMD_QUERY);
+ while (!(mcr = bm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & BM_MCR_VERB_CMD_MASK) == BM_MCR_VERB_CMD_QUERY);
+ *state = mcr->query;
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ return 0;
+}
+EXPORT_SYMBOL(bman_query_pools);
+
+#ifdef CONFIG_FSL_BMAN_CONFIG
+u32 bman_query_free_buffers(struct bman_pool *pool)
+{
+ return bm_pool_free_buffers(pool->params.bpid);
+}
+EXPORT_SYMBOL(bman_query_free_buffers);
+
+int bman_update_pool_thresholds(struct bman_pool *pool, const u32 *thresholds)
+{
+ u32 bpid;
+
+ bpid = bman_get_params(pool)->bpid;
+
+ return bm_pool_set(bpid, thresholds);
+}
+EXPORT_SYMBOL(bman_update_pool_thresholds);
+#endif
+
+int bman_shutdown_pool(u32 bpid)
+{
+ struct bman_portal *p = get_affine_portal();
+ __maybe_unused unsigned long irqflags;
+ int ret;
+
+ PORTAL_IRQ_LOCK(p, irqflags);
+ ret = bm_shutdown_pool(&p->p, bpid);
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ return ret;
+}
+EXPORT_SYMBOL(bman_shutdown_pool);
+
+const struct bm_portal_config *bman_get_bm_portal_config(
+ struct bman_portal *portal)
+{
+ return portal->sharing_redirect ? NULL : portal->config;
+}
diff --git a/drivers/staging/fsl_qbman/bman_low.h b/drivers/staging/fsl_qbman/bman_low.h
new file mode 100644
index 0000000..e4ab771
--- /dev/null
+++ b/drivers/staging/fsl_qbman/bman_low.h
@@ -0,0 +1,524 @@
+/* Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "bman_private.h"
+
+/***************************/
+/* Portal register assists */
+/***************************/
+
+/* Cache-inhibited register offsets */
+#define BM_REG_RCR_PI_CINH 0x0000
+#define BM_REG_RCR_CI_CINH 0x0004
+#define BM_REG_RCR_ITR 0x0008
+#define BM_REG_CFG 0x0100
+#define BM_REG_SCN(n) (0x0200 + ((n) << 2))
+#define BM_REG_ISR 0x0e00
+#define BM_REG_IIR 0x0e0c
+
+/* Cache-enabled register offsets */
+#define BM_CL_CR 0x0000
+#define BM_CL_RR0 0x0100
+#define BM_CL_RR1 0x0140
+#define BM_CL_RCR 0x1000
+#define BM_CL_RCR_PI_CENA 0x3000
+#define BM_CL_RCR_CI_CENA 0x3100
+
+/* BTW, the drivers (and h/w programming model) already obtain the required
+ * synchronisation for portal accesses via lwsync(), hwsync(), and
+ * data-dependencies. Use of barrier()s or other order-preserving primitives
+ * simply degrade performance. Hence the use of the __raw_*() interfaces, which
+ * simply ensure that the compiler treats the portal registers as volatile (ie.
+ * non-coherent). */
+
+/* Cache-inhibited register access. */
+#define __bm_in(bm, o) __raw_readl((bm)->addr_ci + (o))
+#define __bm_out(bm, o, val) __raw_writel((val), (bm)->addr_ci + (o))
+#define bm_in(reg) __bm_in(&portal->addr, BM_REG_##reg)
+#define bm_out(reg, val) __bm_out(&portal->addr, BM_REG_##reg, val)
+
+/* Cache-enabled (index) register access */
+#define __bm_cl_touch_ro(bm, o) dcbt_ro((bm)->addr_ce + (o))
+#define __bm_cl_touch_rw(bm, o) dcbt_rw((bm)->addr_ce + (o))
+#define __bm_cl_in(bm, o) __raw_readl((bm)->addr_ce + (o))
+#define __bm_cl_out(bm, o, val) \
+ do { \
+ u32 *__tmpclout = (bm)->addr_ce + (o); \
+ __raw_writel((val), __tmpclout); \
+ dcbf(__tmpclout); \
+ } while (0)
+#define __bm_cl_invalidate(bm, o) dcbi((bm)->addr_ce + (o))
+#define bm_cl_touch_ro(reg) __bm_cl_touch_ro(&portal->addr, BM_CL_##reg##_CENA)
+#define bm_cl_touch_rw(reg) __bm_cl_touch_rw(&portal->addr, BM_CL_##reg##_CENA)
+#define bm_cl_in(reg) __bm_cl_in(&portal->addr, BM_CL_##reg##_CENA)
+#define bm_cl_out(reg, val) __bm_cl_out(&portal->addr, BM_CL_##reg##_CENA, val)
+#define bm_cl_invalidate(reg)\
+ __bm_cl_invalidate(&portal->addr, BM_CL_##reg##_CENA)
+
+/* Cyclic helper for rings. FIXME: once we are able to do fine-grain perf
+ * analysis, look at using the "extra" bit in the ring index registers to avoid
+ * cyclic issues. */
+static inline u8 bm_cyc_diff(u8 ringsize, u8 first, u8 last)
+{
+ /* 'first' is included, 'last' is excluded */
+ if (first <= last)
+ return last - first;
+ return ringsize + last - first;
+}
+
+/* Portal modes.
+ * Enum types;
+ * pmode == production mode
+ * cmode == consumption mode,
+ * Enum values use 3 letter codes. First letter matches the portal mode,
+ * remaining two letters indicate;
+ * ci == cache-inhibited portal register
+ * ce == cache-enabled portal register
+ * vb == in-band valid-bit (cache-enabled)
+ */
+enum bm_rcr_pmode { /* matches BCSP_CFG::RPM */
+ bm_rcr_pci = 0, /* PI index, cache-inhibited */
+ bm_rcr_pce = 1, /* PI index, cache-enabled */
+ bm_rcr_pvb = 2 /* valid-bit */
+};
+enum bm_rcr_cmode { /* s/w-only */
+ bm_rcr_cci, /* CI index, cache-inhibited */
+ bm_rcr_cce /* CI index, cache-enabled */
+};
+
+
+/* ------------------------- */
+/* --- Portal structures --- */
+
+#define BM_RCR_SIZE 8
+
+struct bm_rcr {
+ struct bm_rcr_entry *ring, *cursor;
+ u8 ci, available, ithresh, vbit;
+#ifdef CONFIG_FSL_DPA_CHECKING
+ u32 busy;
+ enum bm_rcr_pmode pmode;
+ enum bm_rcr_cmode cmode;
+#endif
+};
+
+struct bm_mc {
+ struct bm_mc_command *cr;
+ struct bm_mc_result *rr;
+ u8 rridx, vbit;
+#ifdef CONFIG_FSL_DPA_CHECKING
+ enum {
+ /* Can only be _mc_start()ed */
+ mc_idle,
+ /* Can only be _mc_commit()ed or _mc_abort()ed */
+ mc_user,
+ /* Can only be _mc_retry()ed */
+ mc_hw
+ } state;
+#endif
+};
+
+struct bm_addr {
+ void __iomem *addr_ce; /* cache-enabled */
+ void __iomem *addr_ci; /* cache-inhibited */
+};
+
+struct bm_portal {
+ struct bm_addr addr;
+ struct bm_rcr rcr;
+ struct bm_mc mc;
+ struct bm_portal_config config;
+} ____cacheline_aligned;
+
+
+/* --------------- */
+/* --- RCR API --- */
+
+/* Bit-wise logic to wrap a ring pointer by clearing the "carry bit" */
+#define RCR_CARRYCLEAR(p) \
+ (void *)((unsigned long)(p) & (~(unsigned long)(BM_RCR_SIZE << 6)))
+
+/* Bit-wise logic to convert a ring pointer to a ring index */
+static inline u8 RCR_PTR2IDX(struct bm_rcr_entry *e)
+{
+ return ((uintptr_t)e >> 6) & (BM_RCR_SIZE - 1);
+}
+
+/* Increment the 'cursor' ring pointer, taking 'vbit' into account */
+static inline void RCR_INC(struct bm_rcr *rcr)
+{
+ /* NB: this is odd-looking, but experiments show that it generates
+ * fast code with essentially no branching overheads. We increment to
+ * the next RCR pointer and handle overflow and 'vbit'. */
+ struct bm_rcr_entry *partial = rcr->cursor + 1;
+ rcr->cursor = RCR_CARRYCLEAR(partial);
+ if (partial != rcr->cursor)
+ rcr->vbit ^= BM_RCR_VERB_VBIT;
+}
+
+static inline int bm_rcr_init(struct bm_portal *portal, enum bm_rcr_pmode pmode,
+ __maybe_unused enum bm_rcr_cmode cmode)
+{
+ /* This use of 'register', as well as all other occurrences, is because
+ * it has been observed to generate much faster code with gcc than is
+ * otherwise the case. */
+ register struct bm_rcr *rcr = &portal->rcr;
+ u32 cfg;
+ u8 pi;
+
+ rcr->ring = portal->addr.addr_ce + BM_CL_RCR;
+ rcr->ci = bm_in(RCR_CI_CINH) & (BM_RCR_SIZE - 1);
+ pi = bm_in(RCR_PI_CINH) & (BM_RCR_SIZE - 1);
+ rcr->cursor = rcr->ring + pi;
+ rcr->vbit = (bm_in(RCR_PI_CINH) & BM_RCR_SIZE) ? BM_RCR_VERB_VBIT : 0;
+ rcr->available = BM_RCR_SIZE - 1
+ - bm_cyc_diff(BM_RCR_SIZE, rcr->ci, pi);
+ rcr->ithresh = bm_in(RCR_ITR);
+#ifdef CONFIG_FSL_DPA_CHECKING
+ rcr->busy = 0;
+ rcr->pmode = pmode;
+ rcr->cmode = cmode;
+#endif
+ cfg = (bm_in(CFG) & 0xffffffe0) | (pmode & 0x3); /* BCSP_CFG::RPM */
+ bm_out(CFG, cfg);
+ return 0;
+}
+
+static inline void bm_rcr_finish(struct bm_portal *portal)
+{
+ register struct bm_rcr *rcr = &portal->rcr;
+ u8 pi = bm_in(RCR_PI_CINH) & (BM_RCR_SIZE - 1);
+ u8 ci = bm_in(RCR_CI_CINH) & (BM_RCR_SIZE - 1);
+ DPA_ASSERT(!rcr->busy);
+ if (pi != RCR_PTR2IDX(rcr->cursor))
+ pr_crit("losing uncommited RCR entries\n");
+ if (ci != rcr->ci)
+ pr_crit("missing existing RCR completions\n");
+ if (rcr->ci != RCR_PTR2IDX(rcr->cursor))
+ pr_crit("RCR destroyed unquiesced\n");
+}
+
+static inline struct bm_rcr_entry *bm_rcr_start(struct bm_portal *portal)
+{
+ register struct bm_rcr *rcr = &portal->rcr;
+ DPA_ASSERT(!rcr->busy);
+ if (!rcr->available)
+ return NULL;
+#ifdef CONFIG_FSL_DPA_CHECKING
+ rcr->busy = 1;
+#endif
+ dcbz_64(rcr->cursor);
+ return rcr->cursor;
+}
+
+static inline void bm_rcr_abort(struct bm_portal *portal)
+{
+ __maybe_unused register struct bm_rcr *rcr = &portal->rcr;
+ DPA_ASSERT(rcr->busy);
+#ifdef CONFIG_FSL_DPA_CHECKING
+ rcr->busy = 0;
+#endif
+}
+
+static inline struct bm_rcr_entry *bm_rcr_pend_and_next(
+ struct bm_portal *portal, u8 myverb)
+{
+ register struct bm_rcr *rcr = &portal->rcr;
+ DPA_ASSERT(rcr->busy);
+ DPA_ASSERT(rcr->pmode != bm_rcr_pvb);
+ if (rcr->available == 1)
+ return NULL;
+ rcr->cursor->__dont_write_directly__verb = myverb | rcr->vbit;
+ dcbf_64(rcr->cursor);
+ RCR_INC(rcr);
+ rcr->available--;
+ dcbz_64(rcr->cursor);
+ return rcr->cursor;
+}
+
+static inline void bm_rcr_pci_commit(struct bm_portal *portal, u8 myverb)
+{
+ register struct bm_rcr *rcr = &portal->rcr;
+ DPA_ASSERT(rcr->busy);
+ DPA_ASSERT(rcr->pmode == bm_rcr_pci);
+ rcr->cursor->__dont_write_directly__verb = myverb | rcr->vbit;
+ RCR_INC(rcr);
+ rcr->available--;
+ hwsync();
+ bm_out(RCR_PI_CINH, RCR_PTR2IDX(rcr->cursor));
+#ifdef CONFIG_FSL_DPA_CHECKING
+ rcr->busy = 0;
+#endif
+}
+
+static inline void bm_rcr_pce_prefetch(struct bm_portal *portal)
+{
+ __maybe_unused register struct bm_rcr *rcr = &portal->rcr;
+ DPA_ASSERT(rcr->pmode == bm_rcr_pce);
+ bm_cl_invalidate(RCR_PI);
+ bm_cl_touch_rw(RCR_PI);
+}
+
+static inline void bm_rcr_pce_commit(struct bm_portal *portal, u8 myverb)
+{
+ register struct bm_rcr *rcr = &portal->rcr;
+ DPA_ASSERT(rcr->busy);
+ DPA_ASSERT(rcr->pmode == bm_rcr_pce);
+ rcr->cursor->__dont_write_directly__verb = myverb | rcr->vbit;
+ RCR_INC(rcr);
+ rcr->available--;
+ lwsync();
+ bm_cl_out(RCR_PI, RCR_PTR2IDX(rcr->cursor));
+#ifdef CONFIG_FSL_DPA_CHECKING
+ rcr->busy = 0;
+#endif
+}
+
+static inline void bm_rcr_pvb_commit(struct bm_portal *portal, u8 myverb)
+{
+ register struct bm_rcr *rcr = &portal->rcr;
+ struct bm_rcr_entry *rcursor;
+ DPA_ASSERT(rcr->busy);
+ DPA_ASSERT(rcr->pmode == bm_rcr_pvb);
+ lwsync();
+ rcursor = rcr->cursor;
+ rcursor->__dont_write_directly__verb = myverb | rcr->vbit;
+ dcbf_64(rcursor);
+ RCR_INC(rcr);
+ rcr->available--;
+#ifdef CONFIG_FSL_DPA_CHECKING
+ rcr->busy = 0;
+#endif
+}
+
+static inline u8 bm_rcr_cci_update(struct bm_portal *portal)
+{
+ register struct bm_rcr *rcr = &portal->rcr;
+ u8 diff, old_ci = rcr->ci;
+ DPA_ASSERT(rcr->cmode == bm_rcr_cci);
+ rcr->ci = bm_in(RCR_CI_CINH) & (BM_RCR_SIZE - 1);
+ diff = bm_cyc_diff(BM_RCR_SIZE, old_ci, rcr->ci);
+ rcr->available += diff;
+ return diff;
+}
+
+static inline void bm_rcr_cce_prefetch(struct bm_portal *portal)
+{
+ __maybe_unused register struct bm_rcr *rcr = &portal->rcr;
+ DPA_ASSERT(rcr->cmode == bm_rcr_cce);
+ bm_cl_touch_ro(RCR_CI);
+}
+
+static inline u8 bm_rcr_cce_update(struct bm_portal *portal)
+{
+ register struct bm_rcr *rcr = &portal->rcr;
+ u8 diff, old_ci = rcr->ci;
+ DPA_ASSERT(rcr->cmode == bm_rcr_cce);
+ rcr->ci = bm_cl_in(RCR_CI) & (BM_RCR_SIZE - 1);
+ bm_cl_invalidate(RCR_CI);
+ diff = bm_cyc_diff(BM_RCR_SIZE, old_ci, rcr->ci);
+ rcr->available += diff;
+ return diff;
+}
+
+static inline u8 bm_rcr_get_ithresh(struct bm_portal *portal)
+{
+ register struct bm_rcr *rcr = &portal->rcr;
+ return rcr->ithresh;
+}
+
+static inline void bm_rcr_set_ithresh(struct bm_portal *portal, u8 ithresh)
+{
+ register struct bm_rcr *rcr = &portal->rcr;
+ rcr->ithresh = ithresh;
+ bm_out(RCR_ITR, ithresh);
+}
+
+static inline u8 bm_rcr_get_avail(struct bm_portal *portal)
+{
+ register struct bm_rcr *rcr = &portal->rcr;
+ return rcr->available;
+}
+
+static inline u8 bm_rcr_get_fill(struct bm_portal *portal)
+{
+ register struct bm_rcr *rcr = &portal->rcr;
+ return BM_RCR_SIZE - 1 - rcr->available;
+}
+
+
+/* ------------------------------ */
+/* --- Management command API --- */
+
+static inline int bm_mc_init(struct bm_portal *portal)
+{
+ register struct bm_mc *mc = &portal->mc;
+ mc->cr = portal->addr.addr_ce + BM_CL_CR;
+ mc->rr = portal->addr.addr_ce + BM_CL_RR0;
+ mc->rridx = (__raw_readb(&mc->cr->__dont_write_directly__verb) &
+ BM_MCC_VERB_VBIT) ? 0 : 1;
+ mc->vbit = mc->rridx ? BM_MCC_VERB_VBIT : 0;
+#ifdef CONFIG_FSL_DPA_CHECKING
+ mc->state = mc_idle;
+#endif
+ return 0;
+}
+
+static inline void bm_mc_finish(struct bm_portal *portal)
+{
+ __maybe_unused register struct bm_mc *mc = &portal->mc;
+ DPA_ASSERT(mc->state == mc_idle);
+#ifdef CONFIG_FSL_DPA_CHECKING
+ if (mc->state != mc_idle)
+ pr_crit("Losing incomplete MC command\n");
+#endif
+}
+
+static inline struct bm_mc_command *bm_mc_start(struct bm_portal *portal)
+{
+ register struct bm_mc *mc = &portal->mc;
+ DPA_ASSERT(mc->state == mc_idle);
+#ifdef CONFIG_FSL_DPA_CHECKING
+ mc->state = mc_user;
+#endif
+ dcbz_64(mc->cr);
+ return mc->cr;
+}
+
+static inline void bm_mc_abort(struct bm_portal *portal)
+{
+ __maybe_unused register struct bm_mc *mc = &portal->mc;
+ DPA_ASSERT(mc->state == mc_user);
+#ifdef CONFIG_FSL_DPA_CHECKING
+ mc->state = mc_idle;
+#endif
+}
+
+static inline void bm_mc_commit(struct bm_portal *portal, u8 myverb)
+{
+ register struct bm_mc *mc = &portal->mc;
+ struct bm_mc_result *rr = mc->rr + mc->rridx;
+ DPA_ASSERT(mc->state == mc_user);
+ lwsync();
+ mc->cr->__dont_write_directly__verb = myverb | mc->vbit;
+ dcbf(mc->cr);
+ dcbit_ro(rr);
+#ifdef CONFIG_FSL_DPA_CHECKING
+ mc->state = mc_hw;
+#endif
+}
+
+static inline struct bm_mc_result *bm_mc_result(struct bm_portal *portal)
+{
+ register struct bm_mc *mc = &portal->mc;
+ struct bm_mc_result *rr = mc->rr + mc->rridx;
+ DPA_ASSERT(mc->state == mc_hw);
+ /* The inactive response register's verb byte always returns zero until
+ * its command is submitted and completed. This includes the valid-bit,
+ * in case you were wondering... */
+ if (!__raw_readb(&rr->verb)) {
+ dcbit_ro(rr);
+ return NULL;
+ }
+ mc->rridx ^= 1;
+ mc->vbit ^= BM_MCC_VERB_VBIT;
+#ifdef CONFIG_FSL_DPA_CHECKING
+ mc->state = mc_idle;
+#endif
+ return rr;
+}
+
+
+/* ------------------------------------- */
+/* --- Portal interrupt register API --- */
+
+static inline int bm_isr_init(__always_unused struct bm_portal *portal)
+{
+ return 0;
+}
+
+static inline void bm_isr_finish(__always_unused struct bm_portal *portal)
+{
+}
+
+#define SCN_REG(bpid) BM_REG_SCN((bpid) / 32)
+#define SCN_BIT(bpid) (0x80000000 >> (bpid & 31))
+static inline void bm_isr_bscn_mask(struct bm_portal *portal, u8 bpid,
+ int enable)
+{
+ u32 val;
+ DPA_ASSERT(bpid < bman_pool_max);
+ /* REG_SCN for bpid=0..31, REG_SCN+4 for bpid=32..63 */
+ val = __bm_in(&portal->addr, SCN_REG(bpid));
+ if (enable)
+ val |= SCN_BIT(bpid);
+ else
+ val &= ~SCN_BIT(bpid);
+ __bm_out(&portal->addr, SCN_REG(bpid), val);
+}
+
+static inline u32 __bm_isr_read(struct bm_portal *portal, enum bm_isr_reg n)
+{
+ return __bm_in(&portal->addr, BM_REG_ISR + (n << 2));
+}
+
+static inline void __bm_isr_write(struct bm_portal *portal, enum bm_isr_reg n,
+ u32 val)
+{
+ __bm_out(&portal->addr, BM_REG_ISR + (n << 2), val);
+}
+
+/* Buffer Pool Cleanup */
+static inline int bm_shutdown_pool(struct bm_portal *p, u32 bpid)
+{
+ struct bm_mc_command *bm_cmd;
+ struct bm_mc_result *bm_res;
+
+ int aq_count = 0;
+ bool stop = false;
+ while (!stop) {
+ /* Acquire buffers until empty */
+ bm_cmd = bm_mc_start(p);
+ bm_cmd->acquire.bpid = bpid;
+ bm_mc_commit(p, BM_MCC_VERB_CMD_ACQUIRE | 1);
+ while (!(bm_res = bm_mc_result(p)))
+ cpu_relax();
+ if (!(bm_res->verb & BM_MCR_VERB_ACQUIRE_BUFCOUNT)) {
+ /* Pool is empty */
+ /* TBD : Should we do a few extra iterations in
+ case some other some blocks keep buffers 'on deck',
+ which may also be problematic */
+ stop = true;
+ } else
+ ++aq_count;
+ }
+ return 0;
+}
diff --git a/drivers/staging/fsl_qbman/bman_private.h b/drivers/staging/fsl_qbman/bman_private.h
new file mode 100644
index 0000000..34e4127
--- /dev/null
+++ b/drivers/staging/fsl_qbman/bman_private.h
@@ -0,0 +1,165 @@
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "dpa_sys.h"
+#include <linux/fsl_bman.h>
+
+/* Revision info (for errata and feature handling) */
+#define BMAN_REV10 0x0100
+#define BMAN_REV20 0x0200
+#define BMAN_REV21 0x0201
+extern u16 bman_ip_rev; /* 0 if uninitialised, otherwise QMAN_REVx */
+
+/*
+ * Global variables of the max portal/pool number this bman version supported
+ */
+extern u16 bman_pool_max;
+
+/* used by CCSR and portal interrupt code */
+enum bm_isr_reg {
+ bm_isr_status = 0,
+ bm_isr_enable = 1,
+ bm_isr_disable = 2,
+ bm_isr_inhibit = 3
+};
+
+struct bm_portal_config {
+ /* Corenet portal addresses;
+ * [0]==cache-enabled, [1]==cache-inhibited. */
+ __iomem void *addr_virt[2];
+ struct resource addr_phys[2];
+ /* Allow these to be joined in lists */
+ struct list_head list;
+ /* User-visible portal configuration settings */
+ struct bman_portal_config public_cfg;
+ /* power management saved data */
+ u32 saved_isdr;
+};
+
+#ifdef CONFIG_FSL_BMAN_CONFIG
+/* Hooks from bman_driver.c to bman_config.c */
+int bman_init_ccsr(struct device_node *node);
+#endif
+
+/* Hooks from bman_driver.c in to bman_high.c */
+struct bman_portal *bman_create_portal(
+ struct bman_portal *portal,
+ const struct bm_portal_config *config);
+struct bman_portal *bman_create_affine_portal(
+ const struct bm_portal_config *config);
+struct bman_portal *bman_create_affine_slave(struct bman_portal *redirect,
+ int cpu);
+void bman_destroy_portal(struct bman_portal *bm);
+
+const struct bm_portal_config *bman_destroy_affine_portal(void);
+
+/* Hooks from fsl_usdpaa.c to bman_driver.c */
+struct bm_portal_config *bm_get_unused_portal(void);
+struct bm_portal_config *bm_get_unused_portal_idx(uint32_t idx);
+void bm_put_unused_portal(struct bm_portal_config *pcfg);
+void bm_set_liodns(struct bm_portal_config *pcfg);
+
+/* Pool logic in the portal driver, during initialisation, needs to know if
+ * there's access to CCSR or not (if not, it'll cripple the pool allocator). */
+#ifdef CONFIG_FSL_BMAN_CONFIG
+int bman_have_ccsr(void);
+#else
+#define bman_have_ccsr() 0
+#endif
+
+/* Stockpile build constants. The _LOW value: when bman_acquire() is called and
+ * the stockpile fill-level is <= _LOW, an acquire is attempted from h/w but it
+ * might fail (if the buffer pool is depleted). So this value provides some
+ * "stagger" in that the bman_acquire() function will only fail if lots of bufs
+ * are requested at once or if h/w has been tested a couple of times without
+ * luck. The _HIGH value: when bman_release() is called and the stockpile
+ * fill-level is >= _HIGH, a release is attempted to h/w but it might fail (if
+ * the release ring is full). So this value provides some "stagger" so that
+ * ring-access is retried a couple of times prior to the API returning a
+ * failure. The following *must* be true;
+ * BMAN_STOCKPILE_HIGH-BMAN_STOCKPILE_LOW > 8
+ * (to avoid thrashing)
+ * BMAN_STOCKPILE_SZ >= 16
+ * (as the release logic expects to either send 8 buffers to hw prior to
+ * adding the given buffers to the stockpile or add the buffers to the
+ * stockpile before sending 8 to hw, as the API must be an all-or-nothing
+ * success/fail.)
+ */
+#define BMAN_STOCKPILE_SZ 16u /* number of bufs in per-pool cache */
+#define BMAN_STOCKPILE_LOW 2u /* when fill is <= this, acquire from hw */
+#define BMAN_STOCKPILE_HIGH 14u /* when fill is >= this, release to hw */
+
+/*************************************************/
+/* BMan s/w corenet portal, low-level i/face */
+/*************************************************/
+
+/* Used by all portal interrupt registers except 'inhibit'
+ * This mask contains all the "irqsource" bits visible to API users
+ */
+#define BM_PIRQ_VISIBLE (BM_PIRQ_RCRI | BM_PIRQ_BSCN)
+
+/* These are bm_<reg>_<verb>(). So for example, bm_disable_write() means "write
+ * the disable register" rather than "disable the ability to write". */
+#define bm_isr_status_read(bm) __bm_isr_read(bm, bm_isr_status)
+#define bm_isr_status_clear(bm, m) __bm_isr_write(bm, bm_isr_status, m)
+#define bm_isr_enable_read(bm) __bm_isr_read(bm, bm_isr_enable)
+#define bm_isr_enable_write(bm, v) __bm_isr_write(bm, bm_isr_enable, v)
+#define bm_isr_disable_read(bm) __bm_isr_read(bm, bm_isr_disable)
+#define bm_isr_disable_write(bm, v) __bm_isr_write(bm, bm_isr_disable, v)
+#define bm_isr_inhibit(bm) __bm_isr_write(bm, bm_isr_inhibit, 1)
+#define bm_isr_uninhibit(bm) __bm_isr_write(bm, bm_isr_inhibit, 0)
+
+#ifdef CONFIG_FSL_BMAN_CONFIG
+/* Set depletion thresholds associated with a buffer pool. Requires that the
+ * operating system have access to Bman CCSR (ie. compiled in support and
+ * run-time access courtesy of the device-tree). */
+int bm_pool_set(u32 bpid, const u32 *thresholds);
+#define BM_POOL_THRESH_SW_ENTER 0
+#define BM_POOL_THRESH_SW_EXIT 1
+#define BM_POOL_THRESH_HW_ENTER 2
+#define BM_POOL_THRESH_HW_EXIT 3
+
+/* Read the free buffer count for a given buffer */
+u32 bm_pool_free_buffers(u32 bpid);
+
+__init int bman_init(void);
+__init int bman_resource_init(void);
+
+const struct bm_portal_config *bman_get_bm_portal_config(
+ struct bman_portal *portal);
+
+/* power management */
+#ifdef CONFIG_SUSPEND
+void suspend_unused_bportal(void);
+void resume_unused_bportal(void);
+#endif
+
+#endif /* CONFIG_FSL_BMAN_CONFIG */
diff --git a/drivers/staging/fsl_qbman/bman_test.c b/drivers/staging/fsl_qbman/bman_test.c
new file mode 100644
index 0000000..db5b7fd
--- /dev/null
+++ b/drivers/staging/fsl_qbman/bman_test.c
@@ -0,0 +1,56 @@
+/* Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "bman_test.h"
+
+MODULE_AUTHOR("Geoff Thorpe");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("Bman testing");
+
+static int test_init(void)
+{
+#ifdef CONFIG_FSL_BMAN_TEST_HIGH
+ int loop = 1;
+ while (loop--)
+ bman_test_high();
+#endif
+#ifdef CONFIG_FSL_BMAN_TEST_THRESH
+ bman_test_thresh();
+#endif
+ return 0;
+}
+
+static void test_exit(void)
+{
+}
+
+module_init(test_init);
+module_exit(test_exit);
diff --git a/drivers/staging/fsl_qbman/bman_test.h b/drivers/staging/fsl_qbman/bman_test.h
new file mode 100644
index 0000000..fcd6505
--- /dev/null
+++ b/drivers/staging/fsl_qbman/bman_test.h
@@ -0,0 +1,44 @@
+/* Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+
+#include <linux/fsl_bman.h>
+
+void bman_test_high(void);
+void bman_test_thresh(void);
diff --git a/drivers/staging/fsl_qbman/bman_test_high.c b/drivers/staging/fsl_qbman/bman_test_high.c
new file mode 100644
index 0000000..7bdd181
--- /dev/null
+++ b/drivers/staging/fsl_qbman/bman_test_high.c
@@ -0,0 +1,181 @@
+/* Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "bman_test.h"
+#include "bman_private.h"
+
+/*************/
+/* constants */
+/*************/
+
+#define PORTAL_OPAQUE ((void *)0xf00dbeef)
+#define POOL_OPAQUE ((void *)0xdeadabba)
+#define NUM_BUFS 93
+#define LOOPS 3
+#define BMAN_TOKEN_MASK 0x00FFFFFFFFFFLLU
+
+/***************/
+/* global vars */
+/***************/
+
+static struct bman_pool *pool;
+static int depleted;
+static struct bm_buffer bufs_in[NUM_BUFS] ____cacheline_aligned;
+static struct bm_buffer bufs_out[NUM_BUFS] ____cacheline_aligned;
+static int bufs_received;
+
+/* Predeclare the callback so we can instantiate pool parameters */
+static void depletion_cb(struct bman_portal *, struct bman_pool *, void *, int);
+
+/**********************/
+/* internal functions */
+/**********************/
+
+static void bufs_init(void)
+{
+ int i;
+ for (i = 0; i < NUM_BUFS; i++)
+ bm_buffer_set64(&bufs_in[i], 0xfedc01234567LLU * i);
+ bufs_received = 0;
+}
+
+static inline int bufs_cmp(const struct bm_buffer *a, const struct bm_buffer *b)
+{
+ if ((bman_ip_rev == BMAN_REV20) || (bman_ip_rev == BMAN_REV21)) {
+
+ /* On SoCs with Bman revison 2.0, Bman only respects the 40
+ * LS-bits of buffer addresses, masking off the upper 8-bits on
+ * release commands. The API provides for 48-bit addresses
+ * because some SoCs support all 48-bits. When generating
+ * garbage addresses for testing, we either need to zero the
+ * upper 8-bits when releasing to Bman (otherwise we'll be
+ * disappointed when the buffers we acquire back from Bman
+ * don't match), or we need to mask the upper 8-bits off when
+ * comparing. We do the latter.
+ */
+ if ((bm_buffer_get64(a) & BMAN_TOKEN_MASK)
+ < (bm_buffer_get64(b) & BMAN_TOKEN_MASK))
+ return -1;
+ if ((bm_buffer_get64(a) & BMAN_TOKEN_MASK)
+ > (bm_buffer_get64(b) & BMAN_TOKEN_MASK))
+ return 1;
+ } else {
+ if (bm_buffer_get64(a) < bm_buffer_get64(b))
+ return -1;
+ if (bm_buffer_get64(a) > bm_buffer_get64(b))
+ return 1;
+ }
+
+ return 0;
+}
+
+static void bufs_confirm(void)
+{
+ int i, j;
+ for (i = 0; i < NUM_BUFS; i++) {
+ int matches = 0;
+ for (j = 0; j < NUM_BUFS; j++)
+ if (!bufs_cmp(&bufs_in[i], &bufs_out[j]))
+ matches++;
+ BUG_ON(matches != 1);
+ }
+}
+
+/********/
+/* test */
+/********/
+
+static void depletion_cb(struct bman_portal *__portal, struct bman_pool *__pool,
+ void *pool_ctx, int __depleted)
+{
+ BUG_ON(__pool != pool);
+ BUG_ON(pool_ctx != POOL_OPAQUE);
+ depleted = __depleted;
+}
+
+void bman_test_high(void)
+{
+ struct bman_pool_params pparams = {
+ .flags = BMAN_POOL_FLAG_DEPLETION | BMAN_POOL_FLAG_DYNAMIC_BPID,
+ .cb = depletion_cb,
+ .cb_ctx = POOL_OPAQUE,
+ };
+ int i, loops = LOOPS;
+
+ bufs_init();
+
+ pr_info("BMAN: --- starting high-level test ---\n");
+
+ pool = bman_new_pool(&pparams);
+ BUG_ON(!pool);
+
+ /*******************/
+ /* Release buffers */
+ /*******************/
+do_loop:
+ i = 0;
+ while (i < NUM_BUFS) {
+ u32 flags = BMAN_RELEASE_FLAG_WAIT;
+ int num = 8;
+ if ((i + num) > NUM_BUFS)
+ num = NUM_BUFS - i;
+ if ((i + num) == NUM_BUFS)
+ flags |= BMAN_RELEASE_FLAG_WAIT_SYNC;
+ if (bman_release(pool, bufs_in + i, num, flags))
+ panic("bman_release() failed\n");
+ i += num;
+ }
+
+ /*******************/
+ /* Acquire buffers */
+ /*******************/
+ while (i > 0) {
+ int tmp, num = 8;
+ if (num > i)
+ num = i;
+ tmp = bman_acquire(pool, bufs_out + i - num, num, 0);
+ BUG_ON(tmp != num);
+ i -= num;
+ }
+ i = bman_acquire(pool, NULL, 1, 0);
+ BUG_ON(i > 0);
+
+ bufs_confirm();
+
+ if (--loops)
+ goto do_loop;
+
+ /************/
+ /* Clean up */
+ /************/
+ bman_free_pool(pool);
+ pr_info("BMAN: --- finished high-level test ---\n");
+}
diff --git a/drivers/staging/fsl_qbman/bman_test_thresh.c b/drivers/staging/fsl_qbman/bman_test_thresh.c
new file mode 100644
index 0000000..6709369
--- /dev/null
+++ b/drivers/staging/fsl_qbman/bman_test_thresh.c
@@ -0,0 +1,196 @@
+/* Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "bman_test.h"
+
+/* Test constants */
+#define TEST_NUMBUFS 129728
+#define TEST_EXIT 129536
+#define TEST_ENTRY 129024
+
+struct affine_test_data {
+ struct task_struct *t;
+ int cpu;
+ int expect_affinity;
+ int drain;
+ int num_enter;
+ int num_exit;
+ struct list_head node;
+ struct completion wakethread;
+ struct completion wakeparent;
+};
+
+static void cb_depletion(struct bman_portal *portal,
+ struct bman_pool *pool,
+ void *opaque,
+ int depleted)
+{
+ struct affine_test_data *data = opaque;
+ int c = smp_processor_id();
+ pr_info("cb_depletion: bpid=%d, depleted=%d, cpu=%d, original=%d\n",
+ bman_get_params(pool)->bpid, !!depleted, c, data->cpu);
+ /* We should be executing on the CPU of the thread that owns the pool if
+ * and that CPU has an affine portal (ie. it isn't slaved). */
+ BUG_ON((c != data->cpu) && data->expect_affinity);
+ BUG_ON((c == data->cpu) && !data->expect_affinity);
+ if (depleted)
+ data->num_enter++;
+ else
+ data->num_exit++;
+}
+
+/* Params used to set up a pool, this also dynamically allocates a BPID */
+static const struct bman_pool_params params_nocb = {
+ .flags = BMAN_POOL_FLAG_DYNAMIC_BPID | BMAN_POOL_FLAG_THRESH,
+ .thresholds = { TEST_ENTRY, TEST_EXIT, 0, 0 }
+};
+
+/* Params used to set up each cpu's pool with callbacks enabled */
+static struct bman_pool_params params_cb = {
+ .bpid = 0, /* will be replaced to match pool_nocb */
+ .flags = BMAN_POOL_FLAG_DEPLETION,
+ .cb = cb_depletion
+};
+
+static struct bman_pool *pool_nocb;
+static LIST_HEAD(threads);
+
+static int affine_test(void *__data)
+{
+ struct bman_pool *pool;
+ struct affine_test_data *data = __data;
+ struct bman_pool_params my_params = params_cb;
+
+ pr_info("thread %d: starting\n", data->cpu);
+ /* create the pool */
+ my_params.cb_ctx = data;
+ pool = bman_new_pool(&my_params);
+ BUG_ON(!pool);
+ complete(&data->wakeparent);
+ wait_for_completion(&data->wakethread);
+ init_completion(&data->wakethread);
+
+ /* if we're the drainer, we get signalled for that */
+ if (data->drain) {
+ struct bm_buffer buf;
+ int ret;
+ pr_info("thread %d: draining...\n", data->cpu);
+ do {
+ ret = bman_acquire(pool, &buf, 1, 0);
+ } while (ret > 0);
+ pr_info("thread %d: draining done.\n", data->cpu);
+ complete(&data->wakeparent);
+ wait_for_completion(&data->wakethread);
+ init_completion(&data->wakethread);
+ }
+
+ /* cleanup */
+ bman_free_pool(pool);
+ while (!kthread_should_stop())
+ cpu_relax();
+ pr_info("thread %d: exiting\n", data->cpu);
+ return 0;
+}
+
+static struct affine_test_data *start_affine_test(int cpu, int drain)
+{
+ struct affine_test_data *data = kmalloc(sizeof(*data), GFP_KERNEL);
+
+ if (!data)
+ return NULL;
+ data->cpu = cpu;
+ data->expect_affinity = cpumask_test_cpu(cpu, bman_affine_cpus());
+ data->drain = drain;
+ data->num_enter = 0;
+ data->num_exit = 0;
+ init_completion(&data->wakethread);
+ init_completion(&data->wakeparent);
+ list_add_tail(&data->node, &threads);
+ data->t = kthread_create(affine_test, data, "threshtest%d", cpu);
+ BUG_ON(IS_ERR(data->t));
+ kthread_bind(data->t, cpu);
+ wake_up_process(data->t);
+ return data;
+}
+
+void bman_test_thresh(void)
+{
+ int loop = TEST_NUMBUFS;
+ int ret, num_cpus = 0;
+ struct affine_test_data *data, *drainer = NULL;
+
+ pr_info("bman_test_thresh: start\n");
+
+ /* allocate a BPID and seed it */
+ pool_nocb = bman_new_pool(&params_nocb);
+ BUG_ON(!pool_nocb);
+ while (loop--) {
+ struct bm_buffer buf;
+ bm_buffer_set64(&buf, 0x0badbeef + loop);
+ ret = bman_release(pool_nocb, &buf, 1,
+ BMAN_RELEASE_FLAG_WAIT);
+ BUG_ON(ret);
+ }
+ while (!bman_rcr_is_empty())
+ cpu_relax();
+ pr_info("bman_test_thresh: buffers are in\n");
+
+ /* create threads and wait for them to create pools */
+ params_cb.bpid = bman_get_params(pool_nocb)->bpid;
+ for_each_cpu(loop, cpu_online_mask) {
+ data = start_affine_test(loop, drainer ? 0 : 1);
+ BUG_ON(!data);
+ if (!drainer)
+ drainer = data;
+ num_cpus++;
+ wait_for_completion(&data->wakeparent);
+ }
+
+ /* signal the drainer to start draining */
+ complete(&drainer->wakethread);
+ wait_for_completion(&drainer->wakeparent);
+ init_completion(&drainer->wakeparent);
+
+ /* tear down */
+ list_for_each_entry_safe(data, drainer, &threads, node) {
+ complete(&data->wakethread);
+ ret = kthread_stop(data->t);
+ BUG_ON(ret);
+ list_del(&data->node);
+ /* check that we get the expected callbacks (and no others) */
+ BUG_ON(data->num_enter != 1);
+ BUG_ON(data->num_exit != 0);
+ kfree(data);
+ }
+ bman_free_pool(pool_nocb);
+
+ pr_info("bman_test_thresh: done\n");
+}
diff --git a/drivers/staging/fsl_qbman/dpa_alloc.c b/drivers/staging/fsl_qbman/dpa_alloc.c
new file mode 100644
index 0000000..545adc9
--- /dev/null
+++ b/drivers/staging/fsl_qbman/dpa_alloc.c
@@ -0,0 +1,699 @@
+/* Copyright 2009-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "dpa_sys.h"
+#include <linux/fsl_qman.h>
+#include <linux/fsl_bman.h>
+
+/* Qman and Bman APIs are front-ends to the common code; */
+
+static DECLARE_DPA_ALLOC(bpalloc); /* BPID allocator */
+static DECLARE_DPA_ALLOC(fqalloc); /* FQID allocator */
+static DECLARE_DPA_ALLOC(qpalloc); /* pool-channel allocator */
+static DECLARE_DPA_ALLOC(cgralloc); /* CGR ID allocator */
+static DECLARE_DPA_ALLOC(ceetm0_challoc); /* CEETM Channel ID allocator */
+static DECLARE_DPA_ALLOC(ceetm0_lfqidalloc); /* CEETM LFQID allocator */
+static DECLARE_DPA_ALLOC(ceetm1_challoc); /* CEETM Channel ID allocator */
+static DECLARE_DPA_ALLOC(ceetm1_lfqidalloc); /* CEETM LFQID allocator */
+
+/* This is a sort-of-conditional dpa_alloc_free() routine. Eg. when releasing
+ * FQIDs (probably from user-space), it can filter out those that aren't in the
+ * OOS state (better to leak a h/w resource than to crash). This function
+ * returns the number of invalid IDs that were not released. */
+static u32 release_id_range(struct dpa_alloc *alloc, u32 id, u32 count,
+ int (*is_valid)(u32 id))
+{
+ int valid_mode = 0;
+ u32 loop = id, total_invalid = 0;
+ while (loop < (id + count)) {
+ int isvalid = is_valid ? is_valid(loop) : 1;
+ if (!valid_mode) {
+ /* We're looking for a valid ID to terminate an invalid
+ * range */
+ if (isvalid) {
+ /* We finished a range of invalid IDs, a valid
+ * range is now underway */
+ valid_mode = 1;
+ count -= (loop - id);
+ id = loop;
+ } else
+ total_invalid++;
+ } else {
+ /* We're looking for an invalid ID to terminate a
+ * valid range */
+ if (!isvalid) {
+ /* Release the range of valid IDs, an unvalid
+ * range is now underway */
+ if (loop > id)
+ dpa_alloc_free(alloc, id, loop - id);
+ valid_mode = 0;
+ }
+ }
+ loop++;
+ }
+ /* Release any unterminated range of valid IDs */
+ if (valid_mode && count)
+ dpa_alloc_free(alloc, id, count);
+ return total_invalid;
+}
+
+/* BPID allocator front-end */
+
+int bman_alloc_bpid_range(u32 *result, u32 count, u32 align, int partial)
+{
+ return dpa_alloc_new(&bpalloc, result, count, align, partial);
+}
+EXPORT_SYMBOL(bman_alloc_bpid_range);
+
+static int bp_cleanup(u32 bpid)
+{
+ return bman_shutdown_pool(bpid) == 0;
+}
+void bman_release_bpid_range(u32 bpid, u32 count)
+{
+ u32 total_invalid = release_id_range(&bpalloc, bpid, count, bp_cleanup);
+ if (total_invalid)
+ pr_err("BPID range [%d..%d] (%d) had %d leaks\n",
+ bpid, bpid + count - 1, count, total_invalid);
+}
+EXPORT_SYMBOL(bman_release_bpid_range);
+
+void bman_seed_bpid_range(u32 bpid, u32 count)
+{
+ dpa_alloc_seed(&bpalloc, bpid, count);
+}
+EXPORT_SYMBOL(bman_seed_bpid_range);
+
+int bman_reserve_bpid_range(u32 bpid, u32 count)
+{
+ return dpa_alloc_reserve(&bpalloc, bpid, count);
+}
+EXPORT_SYMBOL(bman_reserve_bpid_range);
+
+
+/* FQID allocator front-end */
+
+int qman_alloc_fqid_range(u32 *result, u32 count, u32 align, int partial)
+{
+ return dpa_alloc_new(&fqalloc, result, count, align, partial);
+}
+EXPORT_SYMBOL(qman_alloc_fqid_range);
+
+static int fq_cleanup(u32 fqid)
+{
+ return qman_shutdown_fq(fqid) == 0;
+}
+void qman_release_fqid_range(u32 fqid, u32 count)
+{
+ u32 total_invalid = release_id_range(&fqalloc, fqid, count, fq_cleanup);
+ if (total_invalid)
+ pr_err("FQID range [%d..%d] (%d) had %d leaks\n",
+ fqid, fqid + count - 1, count, total_invalid);
+}
+EXPORT_SYMBOL(qman_release_fqid_range);
+
+int qman_reserve_fqid_range(u32 fqid, u32 count)
+{
+ return dpa_alloc_reserve(&fqalloc, fqid, count);
+}
+EXPORT_SYMBOL(qman_reserve_fqid_range);
+
+void qman_seed_fqid_range(u32 fqid, u32 count)
+{
+ dpa_alloc_seed(&fqalloc, fqid, count);
+}
+EXPORT_SYMBOL(qman_seed_fqid_range);
+
+/* Pool-channel allocator front-end */
+
+int qman_alloc_pool_range(u32 *result, u32 count, u32 align, int partial)
+{
+ return dpa_alloc_new(&qpalloc, result, count, align, partial);
+}
+EXPORT_SYMBOL(qman_alloc_pool_range);
+
+static int qpool_cleanup(u32 qp)
+{
+ /* We query all FQDs starting from
+ * FQID 1 until we get an "invalid FQID" error, looking for non-OOS FQDs
+ * whose destination channel is the pool-channel being released.
+ * When a non-OOS FQD is found we attempt to clean it up */
+ struct qman_fq fq = {
+ .fqid = 1
+ };
+ int err;
+ do {
+ struct qm_mcr_queryfq_np np;
+ err = qman_query_fq_np(&fq, &np);
+ if (err)
+ /* FQID range exceeded, found no problems */
+ return 1;
+ if ((np.state & QM_MCR_NP_STATE_MASK) != QM_MCR_NP_STATE_OOS) {
+ struct qm_fqd fqd;
+ err = qman_query_fq(&fq, &fqd);
+ BUG_ON(err);
+ if (fqd.dest.channel == qp) {
+ /* The channel is the FQ's target, clean it */
+ if (qman_shutdown_fq(fq.fqid) != 0)
+ /* Couldn't shut down the FQ
+ so the pool must be leaked */
+ return 0;
+ }
+ }
+ /* Move to the next FQID */
+ fq.fqid++;
+ } while (1);
+}
+void qman_release_pool_range(u32 qp, u32 count)
+{
+ u32 total_invalid = release_id_range(&qpalloc, qp,
+ count, qpool_cleanup);
+ if (total_invalid) {
+ /* Pool channels are almost always used individually */
+ if (count == 1)
+ pr_err("Pool channel 0x%x had %d leaks\n",
+ qp, total_invalid);
+ else
+ pr_err("Pool channels [%d..%d] (%d) had %d leaks\n",
+ qp, qp + count - 1, count, total_invalid);
+ }
+}
+EXPORT_SYMBOL(qman_release_pool_range);
+
+
+void qman_seed_pool_range(u32 poolid, u32 count)
+{
+ dpa_alloc_seed(&qpalloc, poolid, count);
+
+}
+EXPORT_SYMBOL(qman_seed_pool_range);
+
+int qman_reserve_pool_range(u32 poolid, u32 count)
+{
+ return dpa_alloc_reserve(&qpalloc, poolid, count);
+}
+EXPORT_SYMBOL(qman_reserve_pool_range);
+
+
+/* CGR ID allocator front-end */
+
+int qman_alloc_cgrid_range(u32 *result, u32 count, u32 align, int partial)
+{
+ return dpa_alloc_new(&cgralloc, result, count, align, partial);
+}
+EXPORT_SYMBOL(qman_alloc_cgrid_range);
+
+static int cqr_cleanup(u32 cgrid)
+{
+ /* We query all FQDs starting from
+ * FQID 1 until we get an "invalid FQID" error, looking for non-OOS FQDs
+ * whose CGR is the CGR being released.
+ */
+ struct qman_fq fq = {
+ .fqid = 1
+ };
+ int err;
+ do {
+ struct qm_mcr_queryfq_np np;
+ err = qman_query_fq_np(&fq, &np);
+ if (err)
+ /* FQID range exceeded, found no problems */
+ return 1;
+ if ((np.state & QM_MCR_NP_STATE_MASK) != QM_MCR_NP_STATE_OOS) {
+ struct qm_fqd fqd;
+ err = qman_query_fq(&fq, &fqd);
+ BUG_ON(err);
+ if ((fqd.fq_ctrl & QM_FQCTRL_CGE) &&
+ (fqd.cgid == cgrid)) {
+ pr_err("CRGID 0x%x is being used by FQID 0x%x,"
+ " CGR will be leaked\n",
+ cgrid, fq.fqid);
+ return 1;
+ }
+ }
+ /* Move to the next FQID */
+ fq.fqid++;
+ } while (1);
+}
+
+void qman_release_cgrid_range(u32 cgrid, u32 count)
+{
+ u32 total_invalid = release_id_range(&cgralloc, cgrid,
+ count, cqr_cleanup);
+ if (total_invalid)
+ pr_err("CGRID range [%d..%d] (%d) had %d leaks\n",
+ cgrid, cgrid + count - 1, count, total_invalid);
+}
+EXPORT_SYMBOL(qman_release_cgrid_range);
+
+void qman_seed_cgrid_range(u32 cgrid, u32 count)
+{
+ dpa_alloc_seed(&cgralloc, cgrid, count);
+
+}
+EXPORT_SYMBOL(qman_seed_cgrid_range);
+
+/* CEETM CHANNEL ID allocator front-end */
+int qman_alloc_ceetm0_channel_range(u32 *result, u32 count, u32 align,
+ int partial)
+{
+ return dpa_alloc_new(&ceetm0_challoc, result, count, align, partial);
+}
+EXPORT_SYMBOL(qman_alloc_ceetm0_channel_range);
+
+int qman_alloc_ceetm1_channel_range(u32 *result, u32 count, u32 align,
+ int partial)
+{
+ return dpa_alloc_new(&ceetm1_challoc, result, count, align, partial);
+}
+EXPORT_SYMBOL(qman_alloc_ceetm1_channel_range);
+
+void qman_release_ceetm0_channel_range(u32 channelid, u32 count)
+{
+ u32 total_invalid;
+
+ total_invalid = release_id_range(&ceetm0_challoc, channelid, count,
+ NULL);
+ if (total_invalid)
+ pr_err("CEETM channel range [%d..%d] (%d) had %d leaks\n",
+ channelid, channelid + count - 1, count, total_invalid);
+}
+EXPORT_SYMBOL(qman_release_ceetm0_channel_range);
+
+void qman_seed_ceetm0_channel_range(u32 channelid, u32 count)
+{
+ dpa_alloc_seed(&ceetm0_challoc, channelid, count);
+
+}
+EXPORT_SYMBOL(qman_seed_ceetm0_channel_range);
+
+void qman_release_ceetm1_channel_range(u32 channelid, u32 count)
+{
+ u32 total_invalid;
+ total_invalid = release_id_range(&ceetm1_challoc, channelid, count,
+ NULL);
+ if (total_invalid)
+ pr_err("CEETM channel range [%d..%d] (%d) had %d leaks\n",
+ channelid, channelid + count - 1, count, total_invalid);
+}
+EXPORT_SYMBOL(qman_release_ceetm1_channel_range);
+
+void qman_seed_ceetm1_channel_range(u32 channelid, u32 count)
+{
+ dpa_alloc_seed(&ceetm1_challoc, channelid, count);
+
+}
+EXPORT_SYMBOL(qman_seed_ceetm1_channel_range);
+
+/* CEETM LFQID allocator front-end */
+int qman_alloc_ceetm0_lfqid_range(u32 *result, u32 count, u32 align,
+ int partial)
+{
+ return dpa_alloc_new(&ceetm0_lfqidalloc, result, count, align, partial);
+}
+EXPORT_SYMBOL(qman_alloc_ceetm0_lfqid_range);
+
+int qman_alloc_ceetm1_lfqid_range(u32 *result, u32 count, u32 align,
+ int partial)
+{
+ return dpa_alloc_new(&ceetm1_lfqidalloc, result, count, align, partial);
+}
+EXPORT_SYMBOL(qman_alloc_ceetm1_lfqid_range);
+
+void qman_release_ceetm0_lfqid_range(u32 lfqid, u32 count)
+{
+ u32 total_invalid;
+
+ total_invalid = release_id_range(&ceetm0_lfqidalloc, lfqid, count,
+ NULL);
+ if (total_invalid)
+ pr_err("CEETM LFQID range [0x%x..0x%x] (%d) had %d leaks\n",
+ lfqid, lfqid + count - 1, count, total_invalid);
+}
+EXPORT_SYMBOL(qman_release_ceetm0_lfqid_range);
+
+void qman_seed_ceetm0_lfqid_range(u32 lfqid, u32 count)
+{
+ dpa_alloc_seed(&ceetm0_lfqidalloc, lfqid, count);
+
+}
+EXPORT_SYMBOL(qman_seed_ceetm0_lfqid_range);
+
+void qman_release_ceetm1_lfqid_range(u32 lfqid, u32 count)
+{
+ u32 total_invalid;
+
+ total_invalid = release_id_range(&ceetm1_lfqidalloc, lfqid, count,
+ NULL);
+ if (total_invalid)
+ pr_err("CEETM LFQID range [0x%x..0x%x] (%d) had %d leaks\n",
+ lfqid, lfqid + count - 1, count, total_invalid);
+}
+EXPORT_SYMBOL(qman_release_ceetm1_lfqid_range);
+
+void qman_seed_ceetm1_lfqid_range(u32 lfqid, u32 count)
+{
+ dpa_alloc_seed(&ceetm1_lfqidalloc, lfqid, count);
+
+}
+EXPORT_SYMBOL(qman_seed_ceetm1_lfqid_range);
+
+
+/* Everything else is the common backend to all the allocators */
+
+/* The allocator is a (possibly-empty) list of these; */
+struct alloc_node {
+ struct list_head list;
+ u32 base;
+ u32 num;
+ /* refcount and is_alloced are only set
+ when the node is in the used list */
+ unsigned int refcount;
+ int is_alloced;
+};
+
+/* #define DPA_ALLOC_DEBUG */
+
+#ifdef DPA_ALLOC_DEBUG
+#define DPRINT pr_info
+static void DUMP(struct dpa_alloc *alloc)
+{
+ int off = 0;
+ char buf[256];
+ struct alloc_node *p;
+ pr_info("Free Nodes\n");
+ list_for_each_entry(p, &alloc->free, list) {
+ if (off < 255)
+ off += snprintf(buf + off, 255-off, "{%d,%d}",
+ p->base, p->base + p->num - 1);
+ }
+ pr_info("%s\n", buf);
+
+ off = 0;
+ pr_info("Used Nodes\n");
+ list_for_each_entry(p, &alloc->used, list) {
+ if (off < 255)
+ off += snprintf(buf + off, 255-off, "{%d,%d}",
+ p->base, p->base + p->num - 1);
+ }
+ pr_info("%s\n", buf);
+
+
+
+}
+#else
+#define DPRINT(x...)
+#define DUMP(a)
+#endif
+
+int dpa_alloc_new(struct dpa_alloc *alloc, u32 *result, u32 count, u32 align,
+ int partial)
+{
+ struct alloc_node *i = NULL, *next_best = NULL, *used_node = NULL;
+ u32 base, next_best_base = 0, num = 0, next_best_num = 0;
+ struct alloc_node *margin_left, *margin_right;
+
+ *result = (u32)-1;
+ DPRINT("alloc_range(%d,%d,%d)\n", count, align, partial);
+ DUMP(alloc);
+ /* If 'align' is 0, it should behave as though it was 1 */
+ if (!align)
+ align = 1;
+ margin_left = kmalloc(sizeof(*margin_left), GFP_KERNEL);
+ if (!margin_left)
+ goto err;
+ margin_right = kmalloc(sizeof(*margin_right), GFP_KERNEL);
+ if (!margin_right) {
+ kfree(margin_left);
+ goto err;
+ }
+ spin_lock_irq(&alloc->lock);
+ list_for_each_entry(i, &alloc->free, list) {
+ base = (i->base + align - 1) / align;
+ base *= align;
+ if ((base - i->base) >= i->num)
+ /* alignment is impossible, regardless of count */
+ continue;
+ num = i->num - (base - i->base);
+ if (num >= count) {
+ /* this one will do nicely */
+ num = count;
+ goto done;
+ }
+ if (num > next_best_num) {
+ next_best = i;
+ next_best_base = base;
+ next_best_num = num;
+ }
+ }
+ if (partial && next_best) {
+ i = next_best;
+ base = next_best_base;
+ num = next_best_num;
+ } else
+ i = NULL;
+done:
+ if (i) {
+ if (base != i->base) {
+ margin_left->base = i->base;
+ margin_left->num = base - i->base;
+ list_add_tail(&margin_left->list, &i->list);
+ } else
+ kfree(margin_left);
+ if ((base + num) < (i->base + i->num)) {
+ margin_right->base = base + num;
+ margin_right->num = (i->base + i->num) -
+ (base + num);
+ list_add(&margin_right->list, &i->list);
+ } else
+ kfree(margin_right);
+ list_del(&i->list);
+ kfree(i);
+ *result = base;
+ }
+ spin_unlock_irq(&alloc->lock);
+err:
+ DPRINT("returning %d\n", i ? num : -ENOMEM);
+ DUMP(alloc);
+ if (!i)
+ return -ENOMEM;
+
+ /* Add the allocation to the used list with a refcount of 1 */
+ used_node = kmalloc(sizeof(*used_node), GFP_KERNEL);
+ if (!used_node)
+ return -ENOMEM;
+ used_node->base = *result;
+ used_node->num = num;
+ used_node->refcount = 1;
+ used_node->is_alloced = 1;
+ list_add_tail(&used_node->list, &alloc->used);
+ return (int)num;
+}
+
+/* Allocate the list node using GFP_ATOMIC, because we *really* want to avoid
+ * forcing error-handling on to users in the deallocation path. */
+static void _dpa_alloc_free(struct dpa_alloc *alloc, u32 base_id, u32 count)
+{
+ struct alloc_node *i, *node = kmalloc(sizeof(*node), GFP_ATOMIC);
+ BUG_ON(!node);
+ DPRINT("release_range(%d,%d)\n", base_id, count);
+ DUMP(alloc);
+ BUG_ON(!count);
+ spin_lock_irq(&alloc->lock);
+
+
+ node->base = base_id;
+ node->num = count;
+ list_for_each_entry(i, &alloc->free, list) {
+ if (i->base >= node->base) {
+ /* BUG_ON(any overlapping) */
+ BUG_ON(i->base < (node->base + node->num));
+ list_add_tail(&node->list, &i->list);
+ goto done;
+ }
+ }
+ list_add_tail(&node->list, &alloc->free);
+done:
+ /* Merge to the left */
+ i = list_entry(node->list.prev, struct alloc_node, list);
+ if (node->list.prev != &alloc->free) {
+ BUG_ON((i->base + i->num) > node->base);
+ if ((i->base + i->num) == node->base) {
+ node->base = i->base;
+ node->num += i->num;
+ list_del(&i->list);
+ kfree(i);
+ }
+ }
+ /* Merge to the right */
+ i = list_entry(node->list.next, struct alloc_node, list);
+ if (node->list.next != &alloc->free) {
+ BUG_ON((node->base + node->num) > i->base);
+ if ((node->base + node->num) == i->base) {
+ node->num += i->num;
+ list_del(&i->list);
+ kfree(i);
+ }
+ }
+ spin_unlock_irq(&alloc->lock);
+ DUMP(alloc);
+}
+
+
+void dpa_alloc_free(struct dpa_alloc *alloc, u32 base_id, u32 count)
+{
+ struct alloc_node *i = NULL;
+ spin_lock_irq(&alloc->lock);
+
+ /* First find the node in the used list and decrement its ref count */
+ list_for_each_entry(i, &alloc->used, list) {
+ if (i->base == base_id && i->num == count) {
+ --i->refcount;
+ if (i->refcount == 0) {
+ list_del(&i->list);
+ spin_unlock_irq(&alloc->lock);
+ if (i->is_alloced)
+ _dpa_alloc_free(alloc, base_id, count);
+ kfree(i);
+ return;
+ }
+ spin_unlock_irq(&alloc->lock);
+ return;
+ }
+ }
+ /* Couldn't find the allocation */
+ pr_err("Attempt to free ID 0x%x COUNT %d that wasn't alloc'd or reserved\n",
+ base_id, count);
+ spin_unlock_irq(&alloc->lock);
+}
+
+void dpa_alloc_seed(struct dpa_alloc *alloc, u32 base_id, u32 count)
+{
+ /* Same as free but no previous allocation checking is needed */
+ _dpa_alloc_free(alloc, base_id, count);
+}
+
+
+int dpa_alloc_reserve(struct dpa_alloc *alloc, u32 base, u32 num)
+{
+ struct alloc_node *i = NULL, *used_node;
+
+ DPRINT("alloc_reserve(%d,%d)\n", base, num);
+ DUMP(alloc);
+
+ spin_lock_irq(&alloc->lock);
+
+ /* Check for the node in the used list.
+ If found, increase it's refcount */
+ list_for_each_entry(i, &alloc->used, list) {
+ if ((i->base == base) && (i->num == num)) {
+ ++i->refcount;
+ spin_unlock_irq(&alloc->lock);
+ return 0;
+ }
+ if ((base >= i->base) && (base < (i->base + i->num))) {
+ /* This is an attempt to reserve a region that was
+ already reserved or alloced with a different
+ base or num */
+ pr_err("Cannot reserve %d - %d, it overlaps with"
+ " existing reservation from %d - %d\n",
+ base, base + num - 1, i->base,
+ i->base + i->num - 1);
+ spin_unlock_irq(&alloc->lock);
+ return -1;
+ }
+ }
+ /* Check to make sure this ID isn't in the free list */
+ list_for_each_entry(i, &alloc->free, list) {
+ if ((base >= i->base) && (base < (i->base + i->num))) {
+ /* yep, the reservation is within this node */
+ pr_err("Cannot reserve %d - %d, it overlaps with"
+ " free range %d - %d and must be alloced\n",
+ base, base + num - 1,
+ i->base, i->base + i->num - 1);
+ spin_unlock_irq(&alloc->lock);
+ return -1;
+ }
+ }
+ /* Add the allocation to the used list with a refcount of 1 */
+ used_node = kmalloc(sizeof(*used_node), GFP_KERNEL);
+ if (!used_node) {
+ spin_unlock_irq(&alloc->lock);
+ return -ENOMEM;
+
+ }
+ used_node->base = base;
+ used_node->num = num;
+ used_node->refcount = 1;
+ used_node->is_alloced = 0;
+ list_add_tail(&used_node->list, &alloc->used);
+ spin_unlock_irq(&alloc->lock);
+ return 0;
+}
+
+
+int dpa_alloc_pop(struct dpa_alloc *alloc, u32 *result, u32 *count)
+{
+ struct alloc_node *i = NULL;
+ DPRINT("alloc_pop()\n");
+ DUMP(alloc);
+ spin_lock_irq(&alloc->lock);
+ if (!list_empty(&alloc->free)) {
+ i = list_entry(alloc->free.next, struct alloc_node, list);
+ list_del(&i->list);
+ }
+ spin_unlock_irq(&alloc->lock);
+ DPRINT("returning %d\n", i ? 0 : -ENOMEM);
+ DUMP(alloc);
+ if (!i)
+ return -ENOMEM;
+ *result = i->base;
+ *count = i->num;
+ kfree(i);
+ return 0;
+}
+
+int dpa_alloc_check(struct dpa_alloc *list_head, u32 item)
+{
+ struct alloc_node *i = NULL;
+ int res = 0;
+ DPRINT("alloc_check()\n");
+ spin_lock_irq(&list_head->lock);
+
+ list_for_each_entry(i, &list_head->free, list) {
+ if ((item >= i->base) && (item < (i->base + i->num))) {
+ res = 1;
+ break;
+ }
+ }
+ spin_unlock_irq(&list_head->lock);
+ return res;
+}
diff --git a/drivers/staging/fsl_qbman/dpa_sys.h b/drivers/staging/fsl_qbman/dpa_sys.h
new file mode 100644
index 0000000..7dd0640
--- /dev/null
+++ b/drivers/staging/fsl_qbman/dpa_sys.h
@@ -0,0 +1,301 @@
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DPA_SYS_H
+#define DPA_SYS_H
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/bootmem.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/kthread.h>
+#include <linux/memblock.h>
+#include <linux/completion.h>
+#include <linux/log2.h>
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/device.h>
+#include <linux/uio_driver.h>
+#include <linux/smp.h>
+#include <sysdev/fsl_soc.h>
+#include <linux/fsl_hypervisor.h>
+#include <linux/vmalloc.h>
+#include <linux/ctype.h>
+#include <linux/math64.h>
+
+#include <linux/fsl_usdpaa.h>
+
+/* When copying aligned words or shorts, try to avoid memcpy() */
+#define CONFIG_TRY_BETTER_MEMCPY
+
+/* For 2-element tables related to cache-inhibited and cache-enabled mappings */
+#define DPA_PORTAL_CE 0
+#define DPA_PORTAL_CI 1
+
+/***********************/
+/* Misc inline assists */
+/***********************/
+
+/* TODO: NB, we currently assume that hwsync() and lwsync() imply compiler
+ * barriers and that dcb*() won't fall victim to compiler or execution
+ * reordering with respect to other code/instructions that manipulate the same
+ * cacheline. */
+#define hwsync() __asm__ __volatile__ ("sync" : : : "memory")
+#define lwsync()__asm__ __volatile__ (stringify_in_c(LWSYNC) : : : "memory")
+#define dcbf(p) __asm__ __volatile__ ("dcbf 0,%0" : : "r" (p) : "memory")
+#define dcbt_ro(p) __asm__ __volatile__ ("dcbt 0,%0" : : "r" (p))
+#define dcbt_rw(p) __asm__ __volatile__ ("dcbtst 0,%0" : : "r" (p))
+#define dcbi(p) dcbf(p)
+#ifdef CONFIG_PPC_E500MC
+#define dcbzl(p) __asm__ __volatile__ ("dcbzl 0,%0" : : "r" (p))
+#define dcbz_64(p) dcbzl(p)
+#define dcbf_64(p) dcbf(p)
+/* Commonly used combo */
+#define dcbit_ro(p) \
+ do { \
+ dcbi(p); \
+ dcbt_ro(p); \
+ } while (0)
+#else
+#define dcbz(p)__asm__ __volatile__ ("dcbz 0,%0" : : "r" (p))
+#define dcbz_64(p) \
+ do { \
+ dcbz((u32)p + 32); \
+ dcbz(p); \
+ } while (0)
+#define dcbf_64(p) \
+ do { \
+ dcbf((u32)p + 32); \
+ dcbf(p); \
+ } while (0)
+/* Commonly used combo */
+#define dcbit_ro(p) \
+ do { \
+ dcbi(p); \
+ dcbi((u32)p + 32); \
+ dcbt_ro(p); \
+ dcbt_ro((u32)p + 32); \
+ } while (0)
+#endif /* CONFIG_PPC_E500MC */
+
+static inline u64 mfatb(void)
+{
+ u32 hi, lo, chk;
+ do {
+ hi = mfspr(SPRN_ATBU);
+ lo = mfspr(SPRN_ATBL);
+ chk = mfspr(SPRN_ATBU);
+ } while (unlikely(hi != chk));
+ return ((u64)hi << 32) | (u64)lo;
+}
+
+#ifdef CONFIG_FSL_DPA_CHECKING
+#define DPA_ASSERT(x) \
+ do { \
+ if (!(x)) { \
+ pr_crit("ASSERT: (%s:%d) %s\n", __FILE__, __LINE__, \
+ __stringify_1(x)); \
+ dump_stack(); \
+ panic("assertion failure"); \
+ } \
+ } while (0)
+#else
+#define DPA_ASSERT(x)
+#endif
+
+/* memcpy() stuff - when you know alignments in advance */
+#ifdef CONFIG_TRY_BETTER_MEMCPY
+static inline void copy_words(void *dest, const void *src, size_t sz)
+{
+ u32 *__dest = dest;
+ const u32 *__src = src;
+ size_t __sz = sz >> 2;
+ BUG_ON((unsigned long)dest & 0x3);
+ BUG_ON((unsigned long)src & 0x3);
+ BUG_ON(sz & 0x3);
+ while (__sz--)
+ *(__dest++) = *(__src++);
+}
+static inline void copy_shorts(void *dest, const void *src, size_t sz)
+{
+ u16 *__dest = dest;
+ const u16 *__src = src;
+ size_t __sz = sz >> 1;
+ BUG_ON((unsigned long)dest & 0x1);
+ BUG_ON((unsigned long)src & 0x1);
+ BUG_ON(sz & 0x1);
+ while (__sz--)
+ *(__dest++) = *(__src++);
+}
+static inline void copy_bytes(void *dest, const void *src, size_t sz)
+{
+ u8 *__dest = dest;
+ const u8 *__src = src;
+ while (sz--)
+ *(__dest++) = *(__src++);
+}
+#else
+#define copy_words memcpy
+#define copy_shorts memcpy
+#define copy_bytes memcpy
+#endif
+
+/************/
+/* RB-trees */
+/************/
+
+/* We encapsulate RB-trees so that its easier to use non-linux forms in
+ * non-linux systems. This also encapsulates the extra plumbing that linux code
+ * usually provides when using RB-trees. This encapsulation assumes that the
+ * data type held by the tree is u32. */
+
+struct dpa_rbtree {
+ struct rb_root root;
+};
+#define DPA_RBTREE { .root = RB_ROOT }
+
+static inline void dpa_rbtree_init(struct dpa_rbtree *tree)
+{
+ tree->root = RB_ROOT;
+}
+
+#define IMPLEMENT_DPA_RBTREE(name, type, node_field, val_field) \
+static inline int name##_push(struct dpa_rbtree *tree, type *obj) \
+{ \
+ struct rb_node *parent = NULL, **p = &tree->root.rb_node; \
+ while (*p) { \
+ u32 item; \
+ parent = *p; \
+ item = rb_entry(parent, type, node_field)->val_field; \
+ if (obj->val_field < item) \
+ p = &parent->rb_left; \
+ else if (obj->val_field > item) \
+ p = &parent->rb_right; \
+ else \
+ return -EBUSY; \
+ } \
+ rb_link_node(&obj->node_field, parent, p); \
+ rb_insert_color(&obj->node_field, &tree->root); \
+ return 0; \
+} \
+static inline void name##_del(struct dpa_rbtree *tree, type *obj) \
+{ \
+ rb_erase(&obj->node_field, &tree->root); \
+} \
+static inline type *name##_find(struct dpa_rbtree *tree, u32 val) \
+{ \
+ type *ret; \
+ struct rb_node *p = tree->root.rb_node; \
+ while (p) { \
+ ret = rb_entry(p, type, node_field); \
+ if (val < ret->val_field) \
+ p = p->rb_left; \
+ else if (val > ret->val_field) \
+ p = p->rb_right; \
+ else \
+ return ret; \
+ } \
+ return NULL; \
+}
+
+/************/
+/* Bootargs */
+/************/
+
+/* Qman has "qportals=" and Bman has "bportals=", they use the same syntax
+ * though; a comma-separated list of items, each item being a cpu index and/or a
+ * range of cpu indices, and each item optionally be prefixed by "s" to indicate
+ * that the portal associated with that cpu should be shared. See bman_driver.c
+ * for more specifics. */
+static int __parse_portals_cpu(const char **s, unsigned int *cpu)
+{
+ *cpu = 0;
+ if (!isdigit(**s))
+ return -EINVAL;
+ while (isdigit(**s))
+ *cpu = *cpu * 10 + (*((*s)++) - '0');
+ return 0;
+}
+static inline int parse_portals_bootarg(char *str, struct cpumask *want_shared,
+ struct cpumask *want_unshared,
+ const char *argname)
+{
+ const char *s = str;
+ unsigned int shared, cpu1, cpu2, loop;
+
+keep_going:
+ if (*s == 's') {
+ shared = 1;
+ s++;
+ } else
+ shared = 0;
+ if (__parse_portals_cpu(&s, &cpu1))
+ goto err;
+ if (*s == '-') {
+ s++;
+ if (__parse_portals_cpu(&s, &cpu2))
+ goto err;
+ if (cpu2 < cpu1)
+ goto err;
+ } else
+ cpu2 = cpu1;
+ for (loop = cpu1; loop <= cpu2; loop++)
+ cpumask_set_cpu(loop, shared ? want_shared : want_unshared);
+ if (*s == ',') {
+ s++;
+ goto keep_going;
+ } else if ((*s == '\0') || isspace(*s))
+ return 0;
+err:
+ pr_crit("Malformed %s argument: %s, offset: %lu\n", argname, str,
+ (unsigned long)s - (unsigned long)str);
+ return -EINVAL;
+}
+
+/* Hooks from fsl_usdpaa_irq.c to fsl_usdpaa.c */
+int usdpaa_get_portal_config(struct file *filp, void *cinh,
+ enum usdpaa_portal_type ptype, unsigned int *irq,
+ void **iir_reg);
+
+#endif /* DPA_SYS_H */
diff --git a/drivers/staging/fsl_qbman/fsl_usdpaa.c b/drivers/staging/fsl_qbman/fsl_usdpaa.c
new file mode 100644
index 0000000..34e2758
--- /dev/null
+++ b/drivers/staging/fsl_qbman/fsl_usdpaa.c
@@ -0,0 +1,1790 @@
+/* Copyright (C) 2008-2012 Freescale Semiconductor, Inc.
+ * Authors: Andy Fleming <afleming@freescale.com>
+ * Timur Tabi <timur@freescale.com>
+ * Geoff Thorpe <Geoff.Thorpe@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/fsl_usdpaa.h>
+#include "bman_low.h"
+#include "qman_low.h"
+
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/mm.h>
+#include <linux/of.h>
+#include <linux/memblock.h>
+#include <linux/slab.h>
+#include <linux/mman.h>
+
+/* Physical address range of the memory reservation, exported for mm/mem.c */
+static u64 phys_start;
+static u64 phys_size;
+/* PFN versions of the above */
+static unsigned long pfn_start;
+static unsigned long pfn_size;
+
+/* Memory reservations are manipulated under this spinlock (which is why 'refs'
+ * isn't atomic_t). */
+static DEFINE_SPINLOCK(mem_lock);
+
+/* The range of TLB1 indices */
+static unsigned int first_tlb;
+static unsigned int num_tlb;
+static unsigned int current_tlb; /* loops around for fault handling */
+
+/* Memory reservation is represented as a list of 'mem_fragment's, some of which
+ * may be mapped. Unmapped fragments are always merged where possible. */
+static LIST_HEAD(mem_list);
+
+struct mem_mapping;
+
+/* Memory fragments are in 'mem_list'. */
+struct mem_fragment {
+ u64 base;
+ u64 len;
+ unsigned long pfn_base; /* PFN version of 'base' */
+ unsigned long pfn_len; /* PFN version of 'len' */
+ unsigned int refs; /* zero if unmapped */
+ u64 root_len; /* Size of the orignal fragment */
+ struct list_head list;
+ /* if mapped, flags+name captured at creation time */
+ u32 flags;
+ char name[USDPAA_DMA_NAME_MAX];
+ /* support multi-process locks per-memory-fragment. */
+ int has_locking;
+ wait_queue_head_t wq;
+ struct mem_mapping *owner;
+};
+
+/* Mappings of memory fragments in 'struct ctx'. These are created from
+ * ioctl(USDPAA_IOCTL_DMA_MAP), though the actual mapping then happens via a
+ * mmap(). */
+struct mem_mapping {
+ struct mem_fragment *root_frag;
+ u32 frag_count;
+ u64 total_size;
+ struct list_head list;
+};
+
+struct portal_mapping {
+ struct usdpaa_ioctl_portal_map user;
+ union {
+ struct qm_portal_config *qportal;
+ struct bm_portal_config *bportal;
+ };
+ /* Declare space for the portals in case the process
+ exits unexpectedly and needs to be cleaned by the kernel */
+ union {
+ struct qm_portal qman_portal_low;
+ struct bm_portal bman_portal_low;
+ };
+ struct list_head list;
+ struct resource *phys;
+ struct iommu_domain *iommu_domain;
+};
+
+/* Track the DPAA resources the process is using */
+struct active_resource {
+ struct list_head list;
+ u32 id;
+ u32 num;
+ unsigned int refcount;
+};
+
+/* Per-FD state (which should also be per-process but we don't enforce that) */
+struct ctx {
+ /* Lock to protect the context */
+ spinlock_t lock;
+ /* Allocated resources get put here for accounting */
+ struct list_head resources[usdpaa_id_max];
+ /* list of DMA maps */
+ struct list_head maps;
+ /* list of portal maps */
+ struct list_head portals;
+};
+
+/* Different resource classes */
+static const struct alloc_backend {
+ enum usdpaa_id_type id_type;
+ int (*alloc)(u32 *, u32, u32, int);
+ void (*release)(u32 base, unsigned int count);
+ int (*reserve)(u32 base, unsigned int count);
+ const char *acronym;
+} alloc_backends[] = {
+ {
+ .id_type = usdpaa_id_fqid,
+ .alloc = qman_alloc_fqid_range,
+ .release = qman_release_fqid_range,
+ .reserve = qman_reserve_fqid_range,
+ .acronym = "FQID"
+ },
+ {
+ .id_type = usdpaa_id_bpid,
+ .alloc = bman_alloc_bpid_range,
+ .release = bman_release_bpid_range,
+ .reserve = bman_reserve_bpid_range,
+ .acronym = "BPID"
+ },
+ {
+ .id_type = usdpaa_id_qpool,
+ .alloc = qman_alloc_pool_range,
+ .release = qman_release_pool_range,
+ .reserve = qman_reserve_pool_range,
+ .acronym = "QPOOL"
+ },
+ {
+ .id_type = usdpaa_id_cgrid,
+ .alloc = qman_alloc_cgrid_range,
+ .release = qman_release_cgrid_range,
+ .acronym = "CGRID"
+ },
+ {
+ .id_type = usdpaa_id_ceetm0_lfqid,
+ .alloc = qman_alloc_ceetm0_lfqid_range,
+ .release = qman_release_ceetm0_lfqid_range,
+ .acronym = "CEETM0_LFQID"
+ },
+ {
+ .id_type = usdpaa_id_ceetm0_channelid,
+ .alloc = qman_alloc_ceetm0_channel_range,
+ .release = qman_release_ceetm0_channel_range,
+ .acronym = "CEETM0_LFQID"
+ },
+ {
+ .id_type = usdpaa_id_ceetm1_lfqid,
+ .alloc = qman_alloc_ceetm1_lfqid_range,
+ .release = qman_release_ceetm1_lfqid_range,
+ .acronym = "CEETM1_LFQID"
+ },
+ {
+ .id_type = usdpaa_id_ceetm1_channelid,
+ .alloc = qman_alloc_ceetm1_channel_range,
+ .release = qman_release_ceetm1_channel_range,
+ .acronym = "CEETM1_LFQID"
+ },
+ {
+ /* This terminates the array */
+ .id_type = usdpaa_id_max
+ }
+};
+
+/* Determines the largest acceptable page size for a given size
+ The sizes are determined by what the TLB1 acceptable page sizes are */
+static u32 largest_page_size(u32 size)
+{
+ int shift = 30; /* Start at 1G size */
+ if (size < 4096)
+ return 0;
+ do {
+ if (size >= (1<<shift))
+ return 1<<shift;
+ shift -= 2;
+ } while (shift >= 12); /* Up to 4k */
+ return 0;
+}
+
+/* Helper for ioctl_dma_map() when we have a larger fragment than we need. This
+ * splits the fragment into 4 and returns the upper-most. (The caller can loop
+ * until it has a suitable fragment size.) */
+static struct mem_fragment *split_frag(struct mem_fragment *frag)
+{
+ struct mem_fragment *x[3];
+
+ x[0] = kmalloc(sizeof(struct mem_fragment), GFP_ATOMIC);
+ x[1] = kmalloc(sizeof(struct mem_fragment), GFP_ATOMIC);
+ x[2] = kmalloc(sizeof(struct mem_fragment), GFP_ATOMIC);
+ if (!x[0] || !x[1] || !x[2]) {
+ kfree(x[0]);
+ kfree(x[1]);
+ kfree(x[2]);
+ return NULL;
+ }
+ BUG_ON(frag->refs);
+ frag->len >>= 2;
+ frag->pfn_len >>= 2;
+ x[0]->base = frag->base + frag->len;
+ x[1]->base = x[0]->base + frag->len;
+ x[2]->base = x[1]->base + frag->len;
+ x[0]->len = x[1]->len = x[2]->len = frag->len;
+ x[0]->pfn_base = frag->pfn_base + frag->pfn_len;
+ x[1]->pfn_base = x[0]->pfn_base + frag->pfn_len;
+ x[2]->pfn_base = x[1]->pfn_base + frag->pfn_len;
+ x[0]->pfn_len = x[1]->pfn_len = x[2]->pfn_len = frag->pfn_len;
+ x[0]->refs = x[1]->refs = x[2]->refs = 0;
+ x[0]->root_len = x[1]->root_len = x[2]->root_len = frag->root_len;
+ list_add_tail(&x[0]->list, &frag->list);
+ list_add_tail(&x[1]->list, &x[0]->list);
+ list_add_tail(&x[2]->list, &x[1]->list);
+ return x[2];
+}
+
+static __maybe_unused void dump_frags(void)
+{
+ struct mem_fragment *frag;
+ int i = 0;
+ list_for_each_entry(frag, &mem_list, list) {
+ pr_info("FRAG %d: base 0x%llx pfn_base 0x%lx len 0x%llx "
+ "root_len 0x%llx refs %d\n",
+ i, frag->base, frag->pfn_base,
+ frag->len, frag->root_len, frag->refs);
+ ++i;
+ }
+}
+
+/* Walk the list of fragments and adjoin neighbouring segments if possible */
+static void compress_frags(void)
+{
+ /* Walk the fragment list and combine fragments */
+ struct mem_fragment *frag, *tmpfrag;
+ list_for_each_entry_safe(frag, tmpfrag, &mem_list, list) {
+ struct mem_fragment *next_frag =
+ list_entry(frag->list.next, struct mem_fragment, list);
+ if (frag->refs == 0 &&
+ frag->len < frag->root_len &&
+ &next_frag->list != &mem_list) {
+ if (next_frag->refs == 0) {
+ /* Merge with next */
+ next_frag->len += frag->len;
+ next_frag->pfn_len += frag->pfn_len;
+ list_del(&frag->list);
+ }
+ }
+ }
+}
+
+/* Hook from arch/powerpc/mm/mem.c */
+int usdpaa_test_fault(unsigned long pfn, u64 *phys_addr, u64 *size)
+{
+ struct mem_fragment *frag;
+ int idx = -1;
+ if ((pfn < pfn_start) || (pfn >= (pfn_start + pfn_size)))
+ return -1;
+ /* It's in-range, we need to find the fragment */
+ spin_lock(&mem_lock);
+ list_for_each_entry(frag, &mem_list, list) {
+ if ((pfn >= frag->pfn_base) && (pfn < (frag->pfn_base +
+ frag->pfn_len))) {
+ *phys_addr = frag->base;
+ *size = frag->len;
+ idx = current_tlb++;
+ if (current_tlb >= (first_tlb + num_tlb))
+ current_tlb = first_tlb;
+ break;
+ }
+ }
+ spin_unlock(&mem_lock);
+ return idx;
+}
+
+static int usdpaa_open(struct inode *inode, struct file *filp)
+{
+ const struct alloc_backend *backend = &alloc_backends[0];
+ struct ctx *ctx = kmalloc(sizeof(struct ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+ filp->private_data = ctx;
+
+ while (backend->id_type != usdpaa_id_max) {
+ INIT_LIST_HEAD(&ctx->resources[backend->id_type]);
+ backend++;
+ }
+
+ INIT_LIST_HEAD(&ctx->maps);
+ INIT_LIST_HEAD(&ctx->portals);
+ spin_lock_init(&ctx->lock);
+
+ filp->f_mapping->backing_dev_info = &directly_mappable_cdev_bdi;
+
+ return 0;
+}
+
+#define DQRR_MAXFILL 15
+
+/* Reset a QMan portal to its default state */
+static int init_qm_portal(struct qm_portal_config *config,
+ struct qm_portal *portal)
+{
+ portal->addr.addr_ce = config->addr_virt[DPA_PORTAL_CE];
+ portal->addr.addr_ci = config->addr_virt[DPA_PORTAL_CI];
+
+ /* Make sure interrupts are inhibited */
+ qm_out(IIR, 1);
+
+ /* Initialize the DQRR. This will stop any dequeue
+ commands that are in progress */
+ if (qm_dqrr_init(portal, config, qm_dqrr_dpush, qm_dqrr_pvb,
+ qm_dqrr_cdc, DQRR_MAXFILL)) {
+ pr_err("qm_dqrr_init() failed when trying to"
+ " recover portal, portal will be leaked\n");
+ return 1;
+ }
+
+ /* Initialize the EQCR */
+ if (qm_eqcr_init(portal, qm_eqcr_pvb,
+ qm_eqcr_get_ci_stashing(portal), 1)) {
+ pr_err("Qman EQCR initialisation failed\n");
+ return 1;
+ }
+ /* initialize the MR */
+ if (qm_mr_init(portal, qm_mr_pvb, qm_mr_cci)) {
+ pr_err("Qman MR initialisation failed\n");
+ return 1;
+ }
+ qm_mr_pvb_update(portal);
+ while (qm_mr_current(portal)) {
+ qm_mr_next(portal);
+ qm_mr_cci_consume_to_current(portal);
+ qm_mr_pvb_update(portal);
+ }
+
+ if (qm_mc_init(portal)) {
+ pr_err("Qman MC initialisation failed\n");
+ return 1;
+ }
+ return 0;
+}
+
+static int init_bm_portal(struct bm_portal_config *config,
+ struct bm_portal *portal)
+{
+ portal->addr.addr_ce = config->addr_virt[DPA_PORTAL_CE];
+ portal->addr.addr_ci = config->addr_virt[DPA_PORTAL_CI];
+
+ if (bm_rcr_init(portal, bm_rcr_pvb, bm_rcr_cce)) {
+ pr_err("Bman RCR initialisation failed\n");
+ return 1;
+ }
+ if (bm_mc_init(portal)) {
+ pr_err("Bman MC initialisation failed\n");
+ return 1;
+ }
+ return 0;
+}
+
+/* Function that will scan all FQ's in the system. For each FQ that is not
+ OOS it will call the check_channel helper to determine if the FQ should
+ be torn down. If the check_channel helper returns true the FQ will be
+ transitioned to the OOS state */
+static int qm_check_and_destroy_fqs(struct qm_portal *portal, void *ctx,
+ bool (*check_channel)(void*, u32))
+{
+ u32 fq_id = 0;
+ while (1) {
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ u8 state;
+ u32 channel;
+
+ /* Determine the channel for the FQID */
+ mcc = qm_mc_start(portal);
+ mcc->queryfq.fqid = fq_id;
+ qm_mc_commit(portal, QM_MCC_VERB_QUERYFQ);
+ while (!(mcr = qm_mc_result(portal)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK)
+ == QM_MCR_VERB_QUERYFQ);
+ if (mcr->result != QM_MCR_RESULT_OK)
+ break; /* End of valid FQIDs */
+
+ channel = mcr->queryfq.fqd.dest.channel;
+ /* Determine the state of the FQID */
+ mcc = qm_mc_start(portal);
+ mcc->queryfq_np.fqid = fq_id;
+ qm_mc_commit(portal, QM_MCC_VERB_QUERYFQ_NP);
+ while (!(mcr = qm_mc_result(portal)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK)
+ == QM_MCR_VERB_QUERYFQ_NP);
+ state = mcr->queryfq_np.state & QM_MCR_NP_STATE_MASK;
+ if (state == QM_MCR_NP_STATE_OOS)
+ /* Already OOS, no need to do anymore checks */
+ goto next;
+
+ if (check_channel(ctx, channel))
+ qm_shutdown_fq(&portal, 1, fq_id);
+ next:
+ ++fq_id;
+ }
+ return 0;
+}
+
+static bool check_channel_device(void *_ctx, u32 channel)
+{
+ struct ctx *ctx = _ctx;
+ struct portal_mapping *portal, *tmpportal;
+ struct active_resource *res;
+
+ /* See if the FQ is destined for one of the portals we're cleaning up */
+ list_for_each_entry_safe(portal, tmpportal, &ctx->portals, list) {
+ if (portal->user.type == usdpaa_portal_qman) {
+ if (portal->qportal->public_cfg.channel == channel) {
+ /* This FQs destination is a portal
+ we're cleaning, send a retire */
+ return true;
+ }
+ }
+ }
+
+ /* Check the pool channels that will be released as well */
+ list_for_each_entry(res, &ctx->resources[usdpaa_id_qpool], list) {
+ if ((res->id >= channel) &&
+ ((res->id + res->num - 1) <= channel))
+ return true;
+ }
+ return false;
+}
+
+static bool check_portal_channel(void *ctx, u32 channel)
+{
+ u32 portal_channel = *(u32 *)ctx;
+ if (portal_channel == channel) {
+ /* This FQs destination is a portal
+ we're cleaning, send a retire */
+ return true;
+ }
+ return false;
+}
+
+
+
+
+static int usdpaa_release(struct inode *inode, struct file *filp)
+{
+ struct ctx *ctx = filp->private_data;
+ struct mem_mapping *map, *tmpmap;
+ struct portal_mapping *portal, *tmpportal;
+ const struct alloc_backend *backend = &alloc_backends[0];
+ struct active_resource *res;
+ struct qm_portal *qm_cleanup_portal = NULL;
+ struct bm_portal *bm_cleanup_portal = NULL;
+ struct qm_portal_config *qm_alloced_portal = NULL;
+ struct bm_portal_config *bm_alloced_portal = NULL;
+
+ struct qm_portal *portal_array[qman_portal_max];
+ int portal_count = 0;
+
+ /* The following logic is used to recover resources that were not
+ correctly released by the process that is closing the FD.
+ Step 1: syncronize the HW with the qm_portal/bm_portal structures
+ in the kernel
+ */
+
+ list_for_each_entry_safe(portal, tmpportal, &ctx->portals, list) {
+ /* Try to recover any portals that weren't shut down */
+ if (portal->user.type == usdpaa_portal_qman) {
+ portal_array[portal_count] = &portal->qman_portal_low;
+ ++portal_count;
+ init_qm_portal(portal->qportal,
+ &portal->qman_portal_low);
+ if (!qm_cleanup_portal) {
+ qm_cleanup_portal = &portal->qman_portal_low;
+ } else {
+ /* Clean FQs on the dedicated channel */
+ u32 chan = portal->qportal->public_cfg.channel;
+ qm_check_and_destroy_fqs(
+ &portal->qman_portal_low, &chan,
+ check_portal_channel);
+ }
+ } else {
+ /* BMAN */
+ init_bm_portal(portal->bportal,
+ &portal->bman_portal_low);
+ if (!bm_cleanup_portal)
+ bm_cleanup_portal = &portal->bman_portal_low;
+ }
+ }
+ /* If no portal was found, allocate one for cleanup */
+ if (!qm_cleanup_portal) {
+ qm_alloced_portal = qm_get_unused_portal();
+ if (!qm_alloced_portal) {
+ pr_crit("No QMan portal avalaible for cleanup\n");
+ return -1;
+ }
+ qm_cleanup_portal = kmalloc(sizeof(struct qm_portal),
+ GFP_KERNEL);
+ if (!qm_cleanup_portal)
+ return -ENOMEM;
+ init_qm_portal(qm_alloced_portal, qm_cleanup_portal);
+ portal_array[portal_count] = qm_cleanup_portal;
+ ++portal_count;
+ }
+ if (!bm_cleanup_portal) {
+ bm_alloced_portal = bm_get_unused_portal();
+ if (!bm_alloced_portal) {
+ pr_crit("No BMan portal avalaible for cleanup\n");
+ return -1;
+ }
+ bm_cleanup_portal = kmalloc(sizeof(struct bm_portal),
+ GFP_KERNEL);
+ if (!bm_cleanup_portal)
+ return -ENOMEM;
+ init_bm_portal(bm_alloced_portal, bm_cleanup_portal);
+ }
+
+ /* OOS the FQs associated with this process */
+ qm_check_and_destroy_fqs(qm_cleanup_portal, ctx, check_channel_device);
+
+ while (backend->id_type != usdpaa_id_max) {
+ int leaks = 0;
+ list_for_each_entry(res, &ctx->resources[backend->id_type],
+ list) {
+ if (backend->id_type == usdpaa_id_fqid) {
+ int i = 0;
+ for (; i < res->num; i++) {
+ /* Clean FQs with the cleanup portal */
+ qm_shutdown_fq(portal_array,
+ portal_count,
+ res->id + i);
+ }
+ }
+ leaks += res->num;
+ backend->release(res->id, res->num);
+ }
+ if (leaks)
+ pr_crit("USDPAA process leaking %d %s%s\n", leaks,
+ backend->acronym, (leaks > 1) ? "s" : "");
+ backend++;
+ }
+ /* Release any DMA regions */
+ spin_lock(&mem_lock);
+ list_for_each_entry_safe(map, tmpmap, &ctx->maps, list) {
+ struct mem_fragment *current_frag = map->root_frag;
+ int i;
+ if (map->root_frag->has_locking &&
+ (map->root_frag->owner == map)) {
+ map->root_frag->owner = NULL;
+ wake_up(&map->root_frag->wq);
+ }
+ /* Check each fragment and merge if the ref count is 0 */
+ for (i = 0; i < map->frag_count; i++) {
+ --current_frag->refs;
+ current_frag = list_entry(current_frag->list.prev,
+ struct mem_fragment, list);
+ }
+
+ compress_frags();
+ list_del(&map->list);
+ kfree(map);
+ }
+ spin_unlock(&mem_lock);
+
+ /* Return portals */
+ list_for_each_entry_safe(portal, tmpportal, &ctx->portals, list) {
+ if (portal->user.type == usdpaa_portal_qman) {
+ /* Give the portal back to the allocator */
+ qm_put_unused_portal(portal->qportal);
+ } else {
+ bm_put_unused_portal(portal->bportal);
+ }
+ list_del(&portal->list);
+ kfree(portal);
+ }
+ if (qm_alloced_portal) {
+ qm_put_unused_portal(qm_alloced_portal);
+ kfree(qm_cleanup_portal);
+ }
+ if (bm_alloced_portal) {
+ bm_put_unused_portal(bm_alloced_portal);
+ kfree(bm_cleanup_portal);
+ }
+
+ kfree(ctx);
+ return 0;
+}
+
+static int check_mmap_dma(struct ctx *ctx, struct vm_area_struct *vma,
+ int *match, unsigned long *pfn)
+{
+ struct mem_mapping *map;
+
+ list_for_each_entry(map, &ctx->maps, list) {
+ int i;
+ struct mem_fragment *frag = map->root_frag;
+
+ for (i = 0; i < map->frag_count; i++) {
+ if (frag->pfn_base == vma->vm_pgoff) {
+ *match = 1;
+ *pfn = frag->pfn_base;
+ return 0;
+ }
+ frag = list_entry(frag->list.next, struct mem_fragment,
+ list);
+ }
+ }
+ *match = 0;
+ return 0;
+}
+
+static int check_mmap_resource(struct resource *res, struct vm_area_struct *vma,
+ int *match, unsigned long *pfn)
+{
+ *pfn = res->start >> PAGE_SHIFT;
+ if (*pfn == vma->vm_pgoff) {
+ *match = 1;
+ if ((vma->vm_end - vma->vm_start) != resource_size(res))
+ return -EINVAL;
+ } else
+ *match = 0;
+ return 0;
+}
+
+static int check_mmap_portal(struct ctx *ctx, struct vm_area_struct *vma,
+ int *match, unsigned long *pfn)
+{
+ struct portal_mapping *portal;
+ int ret;
+
+ list_for_each_entry(portal, &ctx->portals, list) {
+ ret = check_mmap_resource(&portal->phys[DPA_PORTAL_CE], vma,
+ match, pfn);
+ if (*match) {
+ vma->vm_page_prot =
+ pgprot_cached_noncoherent(vma->vm_page_prot);
+ return ret;
+ }
+ ret = check_mmap_resource(&portal->phys[DPA_PORTAL_CI], vma,
+ match, pfn);
+ if (*match) {
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ return ret;
+ }
+ }
+ *match = 0;
+ return 0;
+}
+
+static int usdpaa_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ struct ctx *ctx = filp->private_data;
+ unsigned long pfn = 0;
+ int match, ret;
+
+ spin_lock(&mem_lock);
+ ret = check_mmap_dma(ctx, vma, &match, &pfn);
+ if (!match)
+ ret = check_mmap_portal(ctx, vma, &match, &pfn);
+ spin_unlock(&mem_lock);
+ if (!match)
+ return -EINVAL;
+ if (!ret)
+ ret = remap_pfn_range(vma, vma->vm_start, pfn,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+ return ret;
+}
+
+/* Return the nearest rounded-up address >= 'addr' that is 'sz'-aligned. 'sz'
+ * must be a power of 2, but both 'addr' and 'sz' can be expressions. */
+#define USDPAA_MEM_ROUNDUP(addr, sz) \
+ ({ \
+ unsigned long foo_align = (sz) - 1; \
+ ((addr) + foo_align) & ~foo_align; \
+ })
+/* Searching for a size-aligned virtual address range starting from 'addr' */
+static unsigned long usdpaa_get_unmapped_area(struct file *file,
+ unsigned long addr,
+ unsigned long len,
+ unsigned long pgoff,
+ unsigned long flags)
+{
+ struct vm_area_struct *vma;
+
+ if (len % PAGE_SIZE)
+ return -EINVAL;
+
+ addr = USDPAA_MEM_ROUNDUP(addr, len);
+ vma = find_vma(current->mm, addr);
+ /* Keep searching until we reach the end of currently-used virtual
+ * address-space or we find a big enough gap. */
+ while (vma) {
+ if ((addr + len) < vma->vm_start)
+ return addr;
+
+ addr = USDPAA_MEM_ROUNDUP(vma->vm_end, len);
+ vma = vma->vm_next;
+ }
+ if ((TASK_SIZE - len) < addr)
+ return -ENOMEM;
+ return addr;
+}
+
+static long ioctl_id_alloc(struct ctx *ctx, void __user *arg)
+{
+ struct usdpaa_ioctl_id_alloc i;
+ const struct alloc_backend *backend;
+ struct active_resource *res;
+ int ret = copy_from_user(&i, arg, sizeof(i));
+ if (ret)
+ return ret;
+ if ((i.id_type >= usdpaa_id_max) || !i.num)
+ return -EINVAL;
+ backend = &alloc_backends[i.id_type];
+ /* Allocate the required resource type */
+ ret = backend->alloc(&i.base, i.num, i.align, i.partial);
+ if (ret < 0)
+ return ret;
+ i.num = ret;
+ /* Copy the result to user-space */
+ ret = copy_to_user(arg, &i, sizeof(i));
+ if (ret) {
+ backend->release(i.base, i.num);
+ return ret;
+ }
+ /* Assign the allocated range to the FD accounting */
+ res = kmalloc(sizeof(*res), GFP_KERNEL);
+ if (!res) {
+ backend->release(i.base, i.num);
+ return -ENOMEM;
+ }
+ spin_lock(&ctx->lock);
+ res->id = i.base;
+ res->num = i.num;
+ res->refcount = 1;
+ list_add(&res->list, &ctx->resources[i.id_type]);
+ spin_unlock(&ctx->lock);
+ return 0;
+}
+
+static long ioctl_id_release(struct ctx *ctx, void __user *arg)
+{
+ struct usdpaa_ioctl_id_release i;
+ const struct alloc_backend *backend;
+ struct active_resource *tmp, *pos;
+
+ int ret = copy_from_user(&i, arg, sizeof(i));
+ if (ret)
+ return ret;
+ if ((i.id_type >= usdpaa_id_max) || !i.num)
+ return -EINVAL;
+ backend = &alloc_backends[i.id_type];
+ /* Pull the range out of the FD accounting - the range is valid iff this
+ * succeeds. */
+ spin_lock(&ctx->lock);
+ list_for_each_entry_safe(pos, tmp, &ctx->resources[i.id_type], list) {
+ if (pos->id == i.base && pos->num == i.num) {
+ pos->refcount--;
+ if (pos->refcount) {
+ spin_unlock(&ctx->lock);
+ return 0; /* Still being used */
+ }
+ list_del(&pos->list);
+ kfree(pos);
+ spin_unlock(&ctx->lock);
+ goto found;
+ }
+ }
+ /* Failed to find the resource */
+ spin_unlock(&ctx->lock);
+ pr_err("Couldn't find resource type %d base 0x%x num %d\n",
+ i.id_type, i.base, i.num);
+ return -EINVAL;
+found:
+ /* Release the resource to the backend */
+ backend->release(i.base, i.num);
+ return 0;
+}
+
+static long ioctl_id_reserve(struct ctx *ctx, void __user *arg)
+{
+ struct usdpaa_ioctl_id_reserve i;
+ const struct alloc_backend *backend;
+ struct active_resource *tmp, *pos;
+
+ int ret = copy_from_user(&i, arg, sizeof(i));
+ if (ret)
+ return ret;
+ if ((i.id_type >= usdpaa_id_max) || !i.num)
+ return -EINVAL;
+ backend = &alloc_backends[i.id_type];
+ if (!backend->reserve)
+ return -EINVAL;
+ /* Pull the range out of the FD accounting - the range is valid iff this
+ * succeeds. */
+ spin_lock(&ctx->lock);
+ list_for_each_entry_safe(pos, tmp, &ctx->resources[i.id_type], list) {
+ if (pos->id == i.base && pos->num == i.num) {
+ pos->refcount++;
+ spin_unlock(&ctx->lock);
+ return 0;
+ }
+ }
+
+ /* Failed to find the resource */
+ spin_unlock(&ctx->lock);
+
+ /* Reserve the resource in the backend */
+ ret = backend->reserve(i.base, i.num);
+ if (ret)
+ return ret;
+ /* Assign the reserved range to the FD accounting */
+ pos = kmalloc(sizeof(*pos), GFP_KERNEL);
+ if (!pos) {
+ backend->release(i.base, i.num);
+ return -ENOMEM;
+ }
+ spin_lock(&ctx->lock);
+ pos->id = i.base;
+ pos->num = i.num;
+ pos->refcount = 1;
+ list_add(&pos->list, &ctx->resources[i.id_type]);
+ spin_unlock(&ctx->lock);
+ return 0;
+}
+
+static long ioctl_dma_map(struct file *fp, struct ctx *ctx,
+ struct usdpaa_ioctl_dma_map *i)
+{
+ struct mem_fragment *frag, *start_frag, *next_frag;
+ struct mem_mapping *map, *tmp;
+ int ret = 0;
+ u32 largest_page, so_far = 0;
+ int frag_count = 0;
+ unsigned long next_addr = PAGE_SIZE, populate;
+
+ if (i->len && i->len % PAGE_SIZE)
+ return -EINVAL;
+
+ map = kmalloc(sizeof(*map), GFP_KERNEL);
+ if (!map)
+ return -ENOMEM;
+
+ spin_lock(&mem_lock);
+ if (i->flags & USDPAA_DMA_FLAG_SHARE) {
+ list_for_each_entry(frag, &mem_list, list) {
+ if (frag->refs && (frag->flags &
+ USDPAA_DMA_FLAG_SHARE) &&
+ !strncmp(i->name, frag->name,
+ USDPAA_DMA_NAME_MAX)) {
+ /* Matching entry */
+ if ((i->flags & USDPAA_DMA_FLAG_CREATE) &&
+ !(i->flags & USDPAA_DMA_FLAG_LAZY)) {
+ ret = -EBUSY;
+ goto out;
+ }
+ /* Check if this has already been mapped
+ to this process */
+ list_for_each_entry(tmp, &ctx->maps, list)
+ if (tmp->root_frag == frag) {
+ ret = -EBUSY;
+ goto out;
+ }
+ i->has_locking = frag->has_locking;
+ i->did_create = 0;
+ i->len = frag->len;
+ start_frag = frag;
+ goto do_map;
+ }
+ }
+ /* No matching entry */
+ if (!(i->flags & USDPAA_DMA_FLAG_CREATE)) {
+ pr_err("ioctl_dma_map() No matching entry\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+ }
+ /* New fragment required, size must be provided. */
+ if (!i->len) {
+ ret = -EINVAL;
+ goto out;
+ }
+ /* Verify there is sufficient space to do the mapping */
+ down_write(&current->mm->mmap_sem);
+ next_addr = usdpaa_get_unmapped_area(fp, next_addr, i->len, 0, 0);
+ up_write(&current->mm->mmap_sem);
+
+ if (next_addr & ~PAGE_MASK) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* Find one of more contiguous fragments that satisfy the total length
+ trying to minimize the number of fragments
+ compute the largest page size that the allocation could use */
+ largest_page = largest_page_size(i->len);
+ start_frag = NULL;
+ while (largest_page &&
+ largest_page <= largest_page_size(phys_size) &&
+ start_frag == NULL) {
+ /* Search the list for a frag of that size */
+ list_for_each_entry(frag, &mem_list, list) {
+ if (!frag->refs && (frag->len == largest_page)) {
+ /* See if the next x fragments are free
+ and can accomidate the size */
+ u32 found_size = largest_page;
+ next_frag = list_entry(frag->list.prev,
+ struct mem_fragment,
+ list);
+ /* If the fragement is too small check
+ if the neighbours cab support it */
+ while (found_size < i->len) {
+ if (&mem_list == &next_frag->list)
+ break; /* End of list */
+ if (next_frag->refs != 0 ||
+ next_frag->len == 0)
+ break; /* not enough space */
+ found_size += next_frag->len;
+ next_frag = list_entry(
+ next_frag->list.prev,
+ struct mem_fragment,
+ list);
+ }
+ if (found_size >= i->len) {
+ /* Success! there is enough contigous
+ free space */
+ start_frag = frag;
+ break;
+ }
+ }
+ } /* next frag loop */
+ /* Couldn't statisfy the request with this
+ largest page size, try a smaller one */
+ largest_page <<= 2;
+ }
+ if (start_frag == NULL) {
+ /* Couldn't find proper amount of space */
+ ret = -ENOMEM;
+ goto out;
+ }
+ i->did_create = 1;
+do_map:
+ /* We may need to divide the final fragment to accomidate the mapping */
+ next_frag = start_frag;
+ while (so_far != i->len) {
+ BUG_ON(next_frag->len == 0);
+ while ((next_frag->len + so_far) > i->len) {
+ /* Split frag until they match */
+ split_frag(next_frag);
+ }
+ so_far += next_frag->len;
+ next_frag->refs++;
+ ++frag_count;
+ next_frag = list_entry(next_frag->list.prev,
+ struct mem_fragment, list);
+ }
+
+ start_frag->flags = i->flags;
+ strncpy(start_frag->name, i->name, USDPAA_DMA_NAME_MAX);
+ start_frag->has_locking = i->has_locking;
+ init_waitqueue_head(&start_frag->wq);
+ if (i->did_create == 1)
+ start_frag->owner = NULL;
+
+ /* Setup the map entry */
+ map->root_frag = start_frag;
+ map->total_size = i->len;
+ map->frag_count = frag_count;
+ list_add(&map->list, &ctx->maps);
+ i->phys_addr = start_frag->base;
+out:
+ spin_unlock(&mem_lock);
+
+ if (!ret) {
+ unsigned long longret;
+ down_write(&current->mm->mmap_sem);
+ longret = do_mmap_pgoff(fp, PAGE_SIZE, map->total_size,
+ PROT_READ |
+ (i->flags &
+ USDPAA_DMA_FLAG_RDONLY ? 0
+ : PROT_WRITE),
+ MAP_SHARED,
+ start_frag->pfn_base,
+ &populate);
+ up_write(&current->mm->mmap_sem);
+ if (longret & ~PAGE_MASK)
+ ret = (int)longret;
+ else
+ i->ptr = (void *)longret;
+
+ } else
+ kfree(map);
+ return ret;
+}
+
+static long ioctl_dma_unmap(struct ctx *ctx, void __user *arg)
+{
+ struct mem_mapping *map;
+ struct vm_area_struct *vma;
+ int ret, i;
+ struct mem_fragment *current_frag;
+
+ down_write(&current->mm->mmap_sem);
+ vma = find_vma(current->mm, (unsigned long)arg);
+ if (!vma || (vma->vm_start > (unsigned long)arg)) {
+ up_write(&current->mm->mmap_sem);
+ return -EFAULT;
+ }
+ spin_lock(&mem_lock);
+ list_for_each_entry(map, &ctx->maps, list) {
+ if (map->root_frag->pfn_base == vma->vm_pgoff) {
+ /* Drop the map lock if we hold it */
+ if (map->root_frag->has_locking &&
+ (map->root_frag->owner == map)) {
+ map->root_frag->owner = NULL;
+ wake_up(&map->root_frag->wq);
+ }
+ goto map_match;
+ }
+ }
+ map = NULL;
+map_match:
+ current_frag = map->root_frag;
+ for (i = 0; i < map->frag_count; i++) {
+ DPA_ASSERT(current_frag->refs > 0);
+ --current_frag->refs;
+ current_frag = list_entry(current_frag->list.prev,
+ struct mem_fragment, list);
+ }
+ list_del(&map->list);
+ compress_frags();
+ spin_unlock(&mem_lock);
+ if (map) {
+ unsigned long base = vma->vm_start;
+ size_t sz = vma->vm_end - vma->vm_start;
+ do_munmap(current->mm, base, sz);
+ ret = 0;
+ } else
+ ret = -EFAULT;
+ up_write(&current->mm->mmap_sem);
+ return ret;
+}
+
+static long ioctl_dma_stats(struct ctx *ctx, void __user *arg)
+{
+ struct mem_fragment *frag;
+ struct usdpaa_ioctl_dma_used result;
+
+ result.free_bytes = 0;
+ result.total_bytes = phys_size;
+
+ list_for_each_entry(frag, &mem_list, list) {
+ if (frag->refs == 0)
+ result.free_bytes += frag->len;
+ }
+
+ return copy_to_user(arg, &result, sizeof(result)); }
+
+static int test_lock(struct mem_mapping *map)
+{
+ int ret = 0;
+ spin_lock(&mem_lock);
+ if (!map->root_frag->owner) {
+ map->root_frag->owner = map;
+ ret = 1;
+ }
+ spin_unlock(&mem_lock);
+ return ret;
+}
+
+static long ioctl_dma_lock(struct ctx *ctx, void __user *arg)
+{
+ struct mem_mapping *map;
+ struct vm_area_struct *vma;
+
+ down_read(&current->mm->mmap_sem);
+ vma = find_vma(current->mm, (unsigned long)arg);
+ if (!vma || (vma->vm_start > (unsigned long)arg)) {
+ up_read(&current->mm->mmap_sem);
+ return -EFAULT;
+ }
+ spin_lock(&mem_lock);
+ list_for_each_entry(map, &ctx->maps, list) {
+ if (map->root_frag->pfn_base == vma->vm_pgoff)
+ goto map_match;
+ }
+ map = NULL;
+map_match:
+ spin_unlock(&mem_lock);
+ up_read(&current->mm->mmap_sem);
+
+ if (!map->root_frag->has_locking)
+ return -ENODEV;
+ return wait_event_interruptible(map->root_frag->wq, test_lock(map));
+}
+
+static long ioctl_dma_unlock(struct ctx *ctx, void __user *arg)
+{
+ struct mem_mapping *map;
+ struct vm_area_struct *vma;
+ int ret;
+
+ down_read(&current->mm->mmap_sem);
+ vma = find_vma(current->mm, (unsigned long)arg);
+ if (!vma || (vma->vm_start > (unsigned long)arg))
+ ret = -EFAULT;
+ else {
+ spin_lock(&mem_lock);
+ list_for_each_entry(map, &ctx->maps, list) {
+ if (map->root_frag->pfn_base == vma->vm_pgoff) {
+ if (!map->root_frag->has_locking)
+ ret = -ENODEV;
+ else if (map->root_frag->owner == map) {
+ map->root_frag->owner = NULL;
+ wake_up(&map->root_frag->wq);
+ ret = 0;
+ } else
+ ret = -EBUSY;
+ goto map_match;
+ }
+ }
+ ret = -EINVAL;
+map_match:
+ spin_unlock(&mem_lock);
+ }
+ up_read(&current->mm->mmap_sem);
+ return ret;
+}
+
+static int portal_mmap(struct file *fp, struct resource *res, void **ptr)
+{
+ unsigned long longret = 0, populate;
+
+ down_write(&current->mm->mmap_sem);
+ longret = do_mmap_pgoff(fp, PAGE_SIZE, resource_size(res),
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ res->start >> PAGE_SHIFT, &populate);
+ up_write(&current->mm->mmap_sem);
+
+ if (longret & ~PAGE_MASK)
+ return (int)longret;
+
+ *ptr = (void *) longret;
+ return 0;
+}
+
+static void portal_munmap(struct resource *res, void *ptr)
+{
+ down_write(&current->mm->mmap_sem);
+ do_munmap(current->mm, (unsigned long)ptr, resource_size(res));
+ up_write(&current->mm->mmap_sem);
+}
+
+static long ioctl_portal_map(struct file *fp, struct ctx *ctx,
+ struct usdpaa_ioctl_portal_map *arg)
+{
+ struct portal_mapping *mapping = kmalloc(sizeof(*mapping), GFP_KERNEL);
+ int ret;
+
+ if (!mapping)
+ return -ENOMEM;
+
+ mapping->user = *arg;
+ mapping->iommu_domain = NULL;
+
+ if (mapping->user.type == usdpaa_portal_qman) {
+ mapping->qportal =
+ qm_get_unused_portal_idx(mapping->user.index);
+ if (!mapping->qportal) {
+ ret = -ENODEV;
+ goto err_get_portal;
+ }
+ mapping->phys = &mapping->qportal->addr_phys[0];
+ mapping->user.channel = mapping->qportal->public_cfg.channel;
+ mapping->user.pools = mapping->qportal->public_cfg.pools;
+ mapping->user.index = mapping->qportal->public_cfg.index;
+ } else if (mapping->user.type == usdpaa_portal_bman) {
+ mapping->bportal =
+ bm_get_unused_portal_idx(mapping->user.index);
+ if (!mapping->bportal) {
+ ret = -ENODEV;
+ goto err_get_portal;
+ }
+ mapping->phys = &mapping->bportal->addr_phys[0];
+ mapping->user.index = mapping->bportal->public_cfg.index;
+ } else {
+ ret = -EINVAL;
+ goto err_copy_from_user;
+ }
+ /* Need to put pcfg in ctx's list before the mmaps because the mmap
+ * handlers look it up. */
+ spin_lock(&mem_lock);
+ list_add(&mapping->list, &ctx->portals);
+ spin_unlock(&mem_lock);
+ ret = portal_mmap(fp, &mapping->phys[DPA_PORTAL_CE],
+ &mapping->user.addr.cena);
+ if (ret)
+ goto err_mmap_cena;
+ ret = portal_mmap(fp, &mapping->phys[DPA_PORTAL_CI],
+ &mapping->user.addr.cinh);
+ if (ret)
+ goto err_mmap_cinh;
+ *arg = mapping->user;
+ return ret;
+
+err_mmap_cinh:
+ portal_munmap(&mapping->phys[DPA_PORTAL_CE], mapping->user.addr.cena);
+err_mmap_cena:
+ if ((mapping->user.type == usdpaa_portal_qman) && mapping->qportal)
+ qm_put_unused_portal(mapping->qportal);
+ else if ((mapping->user.type == usdpaa_portal_bman) && mapping->bportal)
+ bm_put_unused_portal(mapping->bportal);
+ spin_lock(&mem_lock);
+ list_del(&mapping->list);
+ spin_unlock(&mem_lock);
+err_get_portal:
+err_copy_from_user:
+ kfree(mapping);
+ return ret;
+}
+
+static long ioctl_portal_unmap(struct ctx *ctx, struct usdpaa_portal_map *i)
+{
+ struct portal_mapping *mapping;
+ struct vm_area_struct *vma;
+ unsigned long pfn;
+ u32 channel;
+
+ /* Get the PFN corresponding to one of the virt addresses */
+ down_read(&current->mm->mmap_sem);
+ vma = find_vma(current->mm, (unsigned long)i->cinh);
+ if (!vma || (vma->vm_start > (unsigned long)i->cinh)) {
+ up_read(&current->mm->mmap_sem);
+ return -EFAULT;
+ }
+ pfn = vma->vm_pgoff;
+ up_read(&current->mm->mmap_sem);
+
+ /* Find the corresponding portal */
+ spin_lock(&mem_lock);
+ list_for_each_entry(mapping, &ctx->portals, list) {
+ if (pfn == (mapping->phys[DPA_PORTAL_CI].start >> PAGE_SHIFT))
+ goto found;
+ }
+ mapping = NULL;
+found:
+ if (mapping)
+ list_del(&mapping->list);
+ spin_unlock(&mem_lock);
+ if (!mapping)
+ return -ENODEV;
+ portal_munmap(&mapping->phys[DPA_PORTAL_CI], mapping->user.addr.cinh);
+ portal_munmap(&mapping->phys[DPA_PORTAL_CE], mapping->user.addr.cena);
+ if (mapping->user.type == usdpaa_portal_qman) {
+ init_qm_portal(mapping->qportal,
+ &mapping->qman_portal_low);
+
+ /* Tear down any FQs this portal is referencing */
+ channel = mapping->qportal->public_cfg.channel;
+ qm_check_and_destroy_fqs(&mapping->qman_portal_low,
+ &channel,
+ check_portal_channel);
+ qm_put_unused_portal(mapping->qportal);
+ } else if (mapping->user.type == usdpaa_portal_bman) {
+ init_bm_portal(mapping->bportal,
+ &mapping->bman_portal_low);
+ bm_put_unused_portal(mapping->bportal);
+ }
+ kfree(mapping);
+ return 0;
+}
+
+static void portal_config_pamu(struct qm_portal_config *pcfg, uint8_t sdest,
+ uint32_t cpu, uint32_t cache, uint32_t window)
+{
+#ifdef CONFIG_FSL_PAMU
+ int ret;
+ int window_count = 1;
+ struct iommu_domain_geometry geom_attr;
+ struct pamu_stash_attribute stash_attr;
+
+ pcfg->iommu_domain = iommu_domain_alloc(&platform_bus_type);
+ if (!pcfg->iommu_domain) {
+ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_alloc() failed",
+ __func__);
+ goto _no_iommu;
+ }
+ geom_attr.aperture_start = 0;
+ geom_attr.aperture_end =
+ ((dma_addr_t)1 << min(8 * sizeof(dma_addr_t), (size_t)36)) - 1;
+ geom_attr.force_aperture = true;
+ ret = iommu_domain_set_attr(pcfg->iommu_domain, DOMAIN_ATTR_GEOMETRY,
+ &geom_attr);
+ if (ret < 0) {
+ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_set_attr() = %d",
+ __func__, ret);
+ goto _iommu_domain_free;
+ }
+ ret = iommu_domain_set_attr(pcfg->iommu_domain, DOMAIN_ATTR_WINDOWS,
+ &window_count);
+ if (ret < 0) {
+ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_set_attr() = %d",
+ __func__, ret);
+ goto _iommu_domain_free;
+ }
+ stash_attr.cpu = cpu;
+ stash_attr.cache = cache;
+ /* set stash information for the window */
+ stash_attr.window = 0;
+
+ ret = iommu_domain_set_attr(pcfg->iommu_domain,
+ DOMAIN_ATTR_FSL_PAMU_STASH,
+ &stash_attr);
+ if (ret < 0) {
+ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_set_attr() = %d",
+ __func__, ret);
+ goto _iommu_domain_free;
+ }
+ ret = iommu_domain_window_enable(pcfg->iommu_domain, 0, 0, 1ULL << 36,
+ IOMMU_READ | IOMMU_WRITE);
+ if (ret < 0) {
+ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_window_enable() = %d",
+ __func__, ret);
+ goto _iommu_domain_free;
+ }
+ ret = iommu_attach_device(pcfg->iommu_domain, &pcfg->dev);
+ if (ret < 0) {
+ pr_err(KBUILD_MODNAME ":%s(): iommu_device_attach() = %d",
+ __func__, ret);
+ goto _iommu_domain_free;
+ }
+ ret = iommu_domain_set_attr(pcfg->iommu_domain,
+ DOMAIN_ATTR_FSL_PAMU_ENABLE,
+ &window_count);
+ if (ret < 0) {
+ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_set_attr() = %d",
+ __func__, ret);
+ goto _iommu_detach_device;
+ }
+_no_iommu:
+#endif
+
+#ifdef CONFIG_FSL_QMAN_CONFIG
+ if (qman_set_sdest(pcfg->public_cfg.channel, sdest))
+#endif
+ pr_warn("Failed to set QMan portal's stash request queue\n");
+
+ return;
+
+#ifdef CONFIG_FSL_PAMU
+_iommu_detach_device:
+ iommu_detach_device(pcfg->iommu_domain, NULL);
+_iommu_domain_free:
+ iommu_domain_free(pcfg->iommu_domain);
+#endif
+}
+
+static long ioctl_allocate_raw_portal(struct file *fp, struct ctx *ctx,
+ struct usdpaa_ioctl_raw_portal *arg)
+{
+ struct portal_mapping *mapping = kmalloc(sizeof(*mapping), GFP_KERNEL);
+ int ret;
+
+ if (!mapping)
+ return -ENOMEM;
+
+ mapping->user.type = arg->type;
+ mapping->iommu_domain = NULL;
+ if (arg->type == usdpaa_portal_qman) {
+ mapping->qportal = qm_get_unused_portal_idx(arg->index);
+ if (!mapping->qportal) {
+ ret = -ENODEV;
+ goto err;
+ }
+ mapping->phys = &mapping->qportal->addr_phys[0];
+ arg->index = mapping->qportal->public_cfg.index;
+ arg->cinh = mapping->qportal->addr_phys[DPA_PORTAL_CI].start;
+ arg->cena = mapping->qportal->addr_phys[DPA_PORTAL_CE].start;
+ if (arg->enable_stash) {
+ /* Setup the PAMU with the supplied parameters */
+ portal_config_pamu(mapping->qportal, arg->sdest,
+ arg->cpu, arg->cache, arg->window);
+ }
+ } else if (mapping->user.type == usdpaa_portal_bman) {
+ mapping->bportal =
+ bm_get_unused_portal_idx(arg->index);
+ if (!mapping->bportal) {
+ ret = -ENODEV;
+ goto err;
+ }
+ mapping->phys = &mapping->bportal->addr_phys[0];
+ arg->index = mapping->bportal->public_cfg.index;
+ arg->cinh = mapping->bportal->addr_phys[DPA_PORTAL_CI].start;
+ arg->cena = mapping->bportal->addr_phys[DPA_PORTAL_CE].start;
+ } else {
+ ret = -EINVAL;
+ goto err;
+ }
+ /* Need to put pcfg in ctx's list before the mmaps because the mmap
+ * handlers look it up. */
+ spin_lock(&mem_lock);
+ list_add(&mapping->list, &ctx->portals);
+ spin_unlock(&mem_lock);
+ return 0;
+err:
+ kfree(mapping);
+ return ret;
+}
+
+static long ioctl_free_raw_portal(struct file *fp, struct ctx *ctx,
+ struct usdpaa_ioctl_raw_portal *arg)
+{
+ struct portal_mapping *mapping;
+ u32 channel;
+
+ /* Find the corresponding portal */
+ spin_lock(&mem_lock);
+ list_for_each_entry(mapping, &ctx->portals, list) {
+ if (mapping->phys[DPA_PORTAL_CI].start == arg->cinh)
+ goto found;
+ }
+ mapping = NULL;
+found:
+ if (mapping)
+ list_del(&mapping->list);
+ spin_unlock(&mem_lock);
+ if (!mapping)
+ return -ENODEV;
+ if (mapping->user.type == usdpaa_portal_qman) {
+ init_qm_portal(mapping->qportal,
+ &mapping->qman_portal_low);
+
+ /* Tear down any FQs this portal is referencing */
+ channel = mapping->qportal->public_cfg.channel;
+ qm_check_and_destroy_fqs(&mapping->qman_portal_low,
+ &channel,
+ check_portal_channel);
+ qm_put_unused_portal(mapping->qportal);
+ } else if (mapping->user.type == usdpaa_portal_bman) {
+ init_bm_portal(mapping->bportal,
+ &mapping->bman_portal_low);
+ bm_put_unused_portal(mapping->bportal);
+ }
+ kfree(mapping);
+ return 0;
+}
+
+static long usdpaa_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
+{
+ struct ctx *ctx = fp->private_data;
+ void __user *a = (void __user *)arg;
+ switch (cmd) {
+ case USDPAA_IOCTL_ID_ALLOC:
+ return ioctl_id_alloc(ctx, a);
+ case USDPAA_IOCTL_ID_RELEASE:
+ return ioctl_id_release(ctx, a);
+ case USDPAA_IOCTL_ID_RESERVE:
+ return ioctl_id_reserve(ctx, a);
+ case USDPAA_IOCTL_DMA_MAP:
+ {
+ struct usdpaa_ioctl_dma_map input;
+ int ret;
+ if (copy_from_user(&input, a, sizeof(input)))
+ return -EFAULT;
+ ret = ioctl_dma_map(fp, ctx, &input);
+ if (copy_to_user(a, &input, sizeof(input)))
+ return -EFAULT;
+ return ret;
+ }
+ case USDPAA_IOCTL_DMA_UNMAP:
+ return ioctl_dma_unmap(ctx, a);
+ case USDPAA_IOCTL_DMA_LOCK:
+ return ioctl_dma_lock(ctx, a);
+ case USDPAA_IOCTL_DMA_UNLOCK:
+ return ioctl_dma_unlock(ctx, a);
+ case USDPAA_IOCTL_PORTAL_MAP:
+ {
+ struct usdpaa_ioctl_portal_map input;
+ int ret;
+ if (copy_from_user(&input, a, sizeof(input)))
+ return -EFAULT;
+ ret = ioctl_portal_map(fp, ctx, &input);
+ if (copy_to_user(a, &input, sizeof(input)))
+ return -EFAULT;
+ return ret;
+ }
+ case USDPAA_IOCTL_PORTAL_UNMAP:
+ {
+ struct usdpaa_portal_map input;
+ if (copy_from_user(&input, a, sizeof(input)))
+ return -EFAULT;
+ return ioctl_portal_unmap(ctx, &input);
+ }
+ case USDPAA_IOCTL_DMA_USED:
+ return ioctl_dma_stats(ctx, a);
+ case USDPAA_IOCTL_ALLOC_RAW_PORTAL:
+ {
+ struct usdpaa_ioctl_raw_portal input;
+ int ret;
+ if (copy_from_user(&input, a, sizeof(input)))
+ return -EFAULT;
+ ret = ioctl_allocate_raw_portal(fp, ctx, &input);
+ if (copy_to_user(a, &input, sizeof(input)))
+ return -EFAULT;
+ return ret;
+ }
+ case USDPAA_IOCTL_FREE_RAW_PORTAL:
+ {
+ struct usdpaa_ioctl_raw_portal input;
+ if (copy_from_user(&input, a, sizeof(input)))
+ return -EFAULT;
+ return ioctl_free_raw_portal(fp, ctx, &input);
+ }
+ }
+ return -EINVAL;
+}
+
+static long usdpaa_ioctl_compat(struct file *fp, unsigned int cmd,
+ unsigned long arg)
+{
+#ifdef CONFIG_COMPAT
+ struct ctx *ctx = fp->private_data;
+ void __user *a = (void __user *)arg;
+#endif
+ switch (cmd) {
+#ifdef CONFIG_COMPAT
+ case USDPAA_IOCTL_DMA_MAP_COMPAT:
+ {
+ int ret;
+ struct usdpaa_ioctl_dma_map_compat input;
+ struct usdpaa_ioctl_dma_map converted;
+
+ if (copy_from_user(&input, a, sizeof(input)))
+ return -EFAULT;
+
+ converted.ptr = compat_ptr(input.ptr);
+ converted.phys_addr = input.phys_addr;
+ converted.len = input.len;
+ converted.flags = input.flags;
+ strncpy(converted.name, input.name, USDPAA_DMA_NAME_MAX);
+ converted.has_locking = input.has_locking;
+ converted.did_create = input.did_create;
+
+ ret = ioctl_dma_map(fp, ctx, &converted);
+ input.ptr = ptr_to_compat(converted.ptr);
+ input.phys_addr = converted.phys_addr;
+ strncpy(input.name, converted.name, USDPAA_DMA_NAME_MAX);
+ input.has_locking = converted.has_locking;
+ input.did_create = converted.did_create;
+ if (copy_to_user(a, &input, sizeof(input)))
+ return -EFAULT;
+ return ret;
+ }
+ case USDPAA_IOCTL_PORTAL_MAP_COMPAT:
+ {
+ int ret;
+ struct compat_usdpaa_ioctl_portal_map input;
+ struct usdpaa_ioctl_portal_map converted;
+ if (copy_from_user(&input, a, sizeof(input)))
+ return -EFAULT;
+ converted.type = input.type;
+ converted.index = input.index;
+ ret = ioctl_portal_map(fp, ctx, &converted);
+ input.addr.cinh = ptr_to_compat(converted.addr.cinh);
+ input.addr.cena = ptr_to_compat(converted.addr.cena);
+ input.channel = converted.channel;
+ input.pools = converted.pools;
+ input.index = converted.index;
+ if (copy_to_user(a, &input, sizeof(input)))
+ return -EFAULT;
+ return ret;
+ }
+ case USDPAA_IOCTL_PORTAL_UNMAP_COMPAT:
+ {
+ struct usdpaa_portal_map_compat input;
+ struct usdpaa_portal_map converted;
+
+ if (copy_from_user(&input, a, sizeof(input)))
+ return -EFAULT;
+ converted.cinh = compat_ptr(input.cinh);
+ converted.cena = compat_ptr(input.cena);
+ return ioctl_portal_unmap(ctx, &converted);
+ }
+ case USDPAA_IOCTL_ALLOC_RAW_PORTAL_COMPAT:
+ {
+ int ret;
+ struct usdpaa_ioctl_raw_portal converted;
+ struct compat_ioctl_raw_portal input;
+ if (copy_from_user(&input, a, sizeof(input)))
+ return -EFAULT;
+ converted.type = input.type;
+ converted.index = input.index;
+ converted.enable_stash = input.enable_stash;
+ converted.cpu = input.cpu;
+ converted.cache = input.cache;
+ converted.window = input.window;
+ converted.sdest = input.sdest;
+ ret = ioctl_allocate_raw_portal(fp, ctx, &converted);
+
+ input.cinh = converted.cinh;
+ input.cena = converted.cena;
+ input.index = converted.index;
+
+ if (copy_to_user(a, &input, sizeof(input)))
+ return -EFAULT;
+ return ret;
+ }
+ case USDPAA_IOCTL_FREE_RAW_PORTAL_COMPAT:
+ {
+ struct usdpaa_ioctl_raw_portal converted;
+ struct compat_ioctl_raw_portal input;
+ if (copy_from_user(&input, a, sizeof(input)))
+ return -EFAULT;
+ converted.type = input.type;
+ converted.index = input.index;
+ converted.cinh = input.cinh;
+ converted.cena = input.cena;
+ return ioctl_free_raw_portal(fp, ctx, &converted);
+ }
+#endif
+ default:
+ return usdpaa_ioctl(fp, cmd, arg);
+ }
+ return -EINVAL;
+}
+
+int usdpaa_get_portal_config(struct file *filp, void *cinh,
+ enum usdpaa_portal_type ptype, unsigned int *irq,
+ void **iir_reg)
+{
+ /* Walk the list of portals for filp and return the config
+ for the portal that matches the hint */
+ struct ctx *context;
+ struct portal_mapping *portal;
+
+ /* First sanitize the filp */
+ if (filp->f_op->open != usdpaa_open)
+ return -ENODEV;
+ context = filp->private_data;
+ spin_lock(&context->lock);
+ list_for_each_entry(portal, &context->portals, list) {
+ if (portal->user.type == ptype &&
+ portal->user.addr.cinh == cinh) {
+ if (ptype == usdpaa_portal_qman) {
+ *irq = portal->qportal->public_cfg.irq;
+ *iir_reg = portal->qportal->addr_virt[1] +
+ QM_REG_IIR;
+ } else {
+ *irq = portal->bportal->public_cfg.irq;
+ *iir_reg = portal->bportal->addr_virt[1] +
+ BM_REG_IIR;
+ }
+ spin_unlock(&context->lock);
+ return 0;
+ }
+ }
+ spin_unlock(&context->lock);
+ return -EINVAL;
+}
+
+static const struct file_operations usdpaa_fops = {
+ .open = usdpaa_open,
+ .release = usdpaa_release,
+ .mmap = usdpaa_mmap,
+ .get_unmapped_area = usdpaa_get_unmapped_area,
+ .unlocked_ioctl = usdpaa_ioctl,
+ .compat_ioctl = usdpaa_ioctl_compat
+};
+
+static struct miscdevice usdpaa_miscdev = {
+ .name = "fsl-usdpaa",
+ .fops = &usdpaa_fops,
+ .minor = MISC_DYNAMIC_MINOR,
+};
+
+/* Early-boot memory allocation. The boot-arg "usdpaa_mem=<x>" is used to
+ * indicate how much memory (if any) to allocate during early boot. If the
+ * format "usdpaa_mem=<x>,<y>" is used, then <y> will be interpreted as the
+ * number of TLB1 entries to reserve (default is 1). If there are more mappings
+ * than there are TLB1 entries, fault-handling will occur. */
+static __init int usdpaa_mem(char *arg)
+{
+ phys_size = memparse(arg, &arg);
+ num_tlb = 1;
+ if (*arg == ',') {
+ unsigned long ul;
+ int err = kstrtoul(arg + 1, 0, &ul);
+ if (err < 0) {
+ num_tlb = 1;
+ pr_warn("ERROR, usdpaa_mem arg is invalid\n");
+ } else
+ num_tlb = (unsigned int)ul;
+ }
+ return 0;
+}
+early_param("usdpaa_mem", usdpaa_mem);
+
+__init void fsl_usdpaa_init_early(void)
+{
+ if (!phys_size) {
+ pr_info("No USDPAA memory, no 'usdpaa_mem' bootarg\n");
+ return;
+ }
+ if (phys_size % PAGE_SIZE) {
+ pr_err("'usdpaa_mem' bootarg must be a multiple of page size\n");
+ phys_size = 0;
+ return;
+ }
+ phys_start = __memblock_alloc_base(phys_size,
+ largest_page_size(phys_size),
+ MEMBLOCK_ALLOC_ACCESSIBLE);
+ if (!phys_start) {
+ pr_err("Failed to reserve USDPAA region (sz:%llx)\n",
+ phys_size);
+ return;
+ }
+ pfn_start = phys_start >> PAGE_SHIFT;
+ pfn_size = phys_size >> PAGE_SHIFT;
+ first_tlb = current_tlb = tlbcam_index;
+ tlbcam_index += num_tlb;
+ pr_info("USDPAA region at %llx:%llx(%lx:%lx), %d TLB1 entries)\n",
+ phys_start, phys_size, pfn_start, pfn_size, num_tlb);
+}
+
+static int __init usdpaa_init(void)
+{
+ struct mem_fragment *frag;
+ int ret;
+ u64 tmp_size = phys_size;
+ u64 tmp_start = phys_start;
+ u64 tmp_pfn_size = pfn_size;
+ u64 tmp_pfn_start = pfn_start;
+
+ pr_info("Freescale USDPAA process driver\n");
+ if (!phys_start) {
+ pr_warn("fsl-usdpaa: no region found\n");
+ return 0;
+ }
+
+ while (tmp_size != 0) {
+ u32 frag_size = largest_page_size(tmp_size);
+ frag = kmalloc(sizeof(*frag), GFP_KERNEL);
+ if (!frag) {
+ pr_err("Failed to setup USDPAA memory accounting\n");
+ return -ENOMEM;
+ }
+ frag->base = tmp_start;
+ frag->len = frag->root_len = frag_size;
+ frag->pfn_base = tmp_pfn_start;
+ frag->pfn_len = frag_size / PAGE_SIZE;
+ frag->refs = 0;
+ init_waitqueue_head(&frag->wq);
+ frag->owner = NULL;
+ list_add(&frag->list, &mem_list);
+
+ /* Adjust for this frag */
+ tmp_start += frag_size;
+ tmp_size -= frag_size;
+ tmp_pfn_start += frag_size / PAGE_SIZE;
+ tmp_pfn_size -= frag_size / PAGE_SIZE;
+ }
+ ret = misc_register(&usdpaa_miscdev);
+ if (ret)
+ pr_err("fsl-usdpaa: failed to register misc device\n");
+ return ret;
+}
+
+static void __exit usdpaa_exit(void)
+{
+ misc_deregister(&usdpaa_miscdev);
+}
+
+module_init(usdpaa_init);
+module_exit(usdpaa_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Freescale Semiconductor");
+MODULE_DESCRIPTION("Freescale USDPAA process driver");
diff --git a/drivers/staging/fsl_qbman/fsl_usdpaa_irq.c b/drivers/staging/fsl_qbman/fsl_usdpaa_irq.c
new file mode 100644
index 0000000..ca93593
--- /dev/null
+++ b/drivers/staging/fsl_qbman/fsl_usdpaa_irq.c
@@ -0,0 +1,275 @@
+/* Copyright (c) 2013 Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* define a device that allows USPDAA processes to open a file
+ descriptor and specify which IRQ it wants to montior using an ioctl()
+ When an IRQ is received, the device becomes readable so that a process
+ can use read() or select() type calls to monitor for IRQs */
+
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/poll.h>
+#include <linux/uaccess.h>
+#include <linux/fsl_usdpaa.h>
+#include <linux/module.h>
+#include <linux/fdtable.h>
+#include <linux/file.h>
+
+#include "qman_low.h"
+#include "bman_low.h"
+
+struct usdpaa_irq_ctx {
+ int irq_set; /* Set to true once the irq is set via ioctl */
+ unsigned int irq_num;
+ u32 last_irq_count; /* Last value returned from read */
+ u32 irq_count; /* Number of irqs since last read */
+ wait_queue_head_t wait_queue; /* Waiting processes */
+ spinlock_t lock;
+ void *inhibit_addr; /* inhibit register address */
+ struct file *usdpaa_filp;
+};
+
+static int usdpaa_irq_open(struct inode *inode, struct file *filp)
+{
+ struct usdpaa_irq_ctx *ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+ ctx->irq_set = 0;
+ ctx->irq_count = 0;
+ ctx->last_irq_count = 0;
+ init_waitqueue_head(&ctx->wait_queue);
+ spin_lock_init(&ctx->lock);
+ filp->private_data = ctx;
+ return 0;
+}
+
+static int usdpaa_irq_release(struct inode *inode, struct file *filp)
+{
+ struct usdpaa_irq_ctx *ctx = filp->private_data;
+ if (ctx->irq_set) {
+ /* Inhibit the IRQ */
+ out_be32(ctx->inhibit_addr, 0x1);
+ free_irq(ctx->irq_num, ctx);
+ ctx->irq_set = 0;
+ fput(ctx->usdpaa_filp);
+ }
+ kfree(filp->private_data);
+ return 0;
+}
+
+static irqreturn_t usdpaa_irq_handler(int irq, void *_ctx)
+{
+ unsigned long flags;
+ struct usdpaa_irq_ctx *ctx = _ctx;
+ spin_lock_irqsave(&ctx->lock, flags);
+ ++ctx->irq_count;
+ spin_unlock_irqrestore(&ctx->lock, flags);
+ wake_up_all(&ctx->wait_queue);
+ /* Set the inhibit register. This will be reenabled
+ once the USDPAA code handles the IRQ */
+ out_be32(ctx->inhibit_addr, 0x1);
+ return IRQ_HANDLED;
+}
+
+static int map_irq(struct file *fp, struct usdpaa_ioctl_irq_map *irq_map)
+{
+ struct usdpaa_irq_ctx *ctx = fp->private_data;
+ int ret;
+
+ if (ctx->irq_set) {
+ pr_debug("Setting USDPAA IRQ when it was already set!\n");
+ return -EBUSY;
+ }
+
+ ctx->usdpaa_filp = fget(irq_map->fd);
+ if (!ctx->usdpaa_filp) {
+ pr_debug("USDPAA fget(%d) returned NULL\n", irq_map->fd);
+ return -EINVAL;
+ }
+
+ ret = usdpaa_get_portal_config(ctx->usdpaa_filp, irq_map->portal_cinh,
+ irq_map->type, &ctx->irq_num,
+ &ctx->inhibit_addr);
+ if (ret) {
+ pr_debug("USDPAA IRQ couldn't identify portal\n");
+ fput(ctx->usdpaa_filp);
+ return ret;
+ }
+
+ ctx->irq_set = 1;
+
+ ret = request_irq(ctx->irq_num, usdpaa_irq_handler, 0,
+ "usdpaa_irq", ctx);
+ if (ret) {
+ pr_err("USDPAA request_irq(%d) failed, ret= %d\n",
+ ctx->irq_num, ret);
+ ctx->irq_set = 0;
+ fput(ctx->usdpaa_filp);
+ return ret;
+ }
+ return 0;
+}
+
+static long usdpaa_irq_ioctl(struct file *fp, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret;
+ struct usdpaa_ioctl_irq_map irq_map;
+
+ if (cmd != USDPAA_IOCTL_PORTAL_IRQ_MAP) {
+ pr_debug("USDPAA IRQ unknown command 0x%x\n", cmd);
+ return -EINVAL;
+ }
+
+ ret = copy_from_user(&irq_map, (void __user *)arg,
+ sizeof(irq_map));
+ if (ret)
+ return ret;
+ return map_irq(fp, &irq_map);
+}
+
+static ssize_t usdpaa_irq_read(struct file *filp, char __user *buff,
+ size_t count, loff_t *offp)
+{
+ struct usdpaa_irq_ctx *ctx = filp->private_data;
+ int ret;
+
+ if (!ctx->irq_set) {
+ pr_debug("Reading USDPAA IRQ before it was set\n");
+ return -EINVAL;
+ }
+
+ if (count < sizeof(ctx->irq_count)) {
+ pr_debug("USDPAA IRQ Read too small\n");
+ return -EINVAL;
+ }
+ if (ctx->irq_count == ctx->last_irq_count) {
+ if (filp->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+
+ ret = wait_event_interruptible(ctx->wait_queue,
+ ctx->irq_count != ctx->last_irq_count);
+ if (ret == -ERESTARTSYS)
+ return ret;
+ }
+
+ ctx->last_irq_count = ctx->irq_count;
+
+ if (copy_to_user(buff, &ctx->last_irq_count,
+ sizeof(ctx->last_irq_count)))
+ return -EFAULT;
+ return sizeof(ctx->irq_count);
+}
+
+static unsigned int usdpaa_irq_poll(struct file *filp, poll_table *wait)
+{
+ struct usdpaa_irq_ctx *ctx = filp->private_data;
+ unsigned int ret = 0;
+ unsigned long flags;
+
+ if (!ctx->irq_set)
+ return POLLHUP;
+
+ poll_wait(filp, &ctx->wait_queue, wait);
+
+ spin_lock_irqsave(&ctx->lock, flags);
+ if (ctx->irq_count != ctx->last_irq_count)
+ ret |= POLLIN | POLLRDNORM;
+ spin_unlock_irqrestore(&ctx->lock, flags);
+ return ret;
+}
+
+static long usdpaa_irq_ioctl_compat(struct file *fp, unsigned int cmd,
+ unsigned long arg)
+{
+#ifdef CONFIG_COMPAT
+ void __user *a = (void __user *)arg;
+#endif
+ switch (cmd) {
+#ifdef CONFIG_COMPAT
+ case USDPAA_IOCTL_PORTAL_IRQ_MAP_COMPAT:
+ {
+ struct compat_ioctl_irq_map input;
+ struct usdpaa_ioctl_irq_map converted;
+ if (copy_from_user(&input, a, sizeof(input)))
+ return -EFAULT;
+ converted.type = input.type;
+ converted.fd = input.fd;
+ converted.portal_cinh = compat_ptr(input.portal_cinh);
+ return map_irq(fp, &converted);
+ }
+#endif
+ default:
+ return usdpaa_irq_ioctl(fp, cmd, arg);
+ }
+}
+
+static const struct file_operations usdpaa_irq_fops = {
+ .open = usdpaa_irq_open,
+ .release = usdpaa_irq_release,
+ .unlocked_ioctl = usdpaa_irq_ioctl,
+ .compat_ioctl = usdpaa_irq_ioctl_compat,
+ .read = usdpaa_irq_read,
+ .poll = usdpaa_irq_poll
+};
+
+static struct miscdevice usdpaa_miscdev = {
+ .name = "fsl-usdpaa-irq",
+ .fops = &usdpaa_irq_fops,
+ .minor = MISC_DYNAMIC_MINOR,
+};
+
+static int __init usdpaa_irq_init(void)
+{
+ int ret;
+
+ pr_info("Freescale USDPAA process IRQ driver\n");
+ ret = misc_register(&usdpaa_miscdev);
+ if (ret)
+ pr_err("fsl-usdpaa-irq: failed to register misc device\n");
+ return ret;
+}
+
+static void __exit usdpaa_irq_exit(void)
+{
+ misc_deregister(&usdpaa_miscdev);
+}
+
+module_init(usdpaa_irq_init);
+module_exit(usdpaa_irq_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Freescale Semiconductor");
+MODULE_DESCRIPTION("Freescale USDPAA process IRQ driver");
diff --git a/drivers/staging/fsl_qbman/qbman_driver.c b/drivers/staging/fsl_qbman/qbman_driver.c
new file mode 100644
index 0000000..a2904bd
--- /dev/null
+++ b/drivers/staging/fsl_qbman/qbman_driver.c
@@ -0,0 +1,86 @@
+/* Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/time.h>
+#include "qman_private.h"
+#include "bman_private.h"
+
+static __init int qbman_init(void)
+{
+ struct device_node *dn;
+ u32 is_portal_available;
+
+ bman_init();
+ qman_init();
+
+ is_portal_available = 0;
+ for_each_compatible_node(dn, NULL, "fsl,qman-portal") {
+ if (!of_device_is_available(dn))
+ continue;
+ else
+ is_portal_available = 1;
+ }
+
+ if (!qman_have_ccsr() && is_portal_available) {
+ struct qman_fq fq = {
+ .fqid = 1
+ };
+ struct qm_mcr_queryfq_np np;
+ int err, retry = CONFIG_FSL_QMAN_INIT_TIMEOUT;
+ struct timespec nowts, diffts, startts = current_kernel_time();
+ /* Loop while querying given fqid succeeds or time out */
+ while (1) {
+ err = qman_query_fq_np(&fq, &np);
+ if (!err) {
+ /* success, control-plane has configured QMan */
+ break;
+ } else if (err != -ERANGE) {
+ pr_err("QMan: I/O error, continuing anyway\n");
+ break;
+ }
+ nowts = current_kernel_time();
+ diffts = timespec_sub(nowts, startts);
+ if (diffts.tv_sec > 0) {
+ if (!retry--) {
+ pr_err("QMan: time out, control-plane"
+ " dead?\n");
+ break;
+ }
+ pr_warn("QMan: polling for the control-plane"
+ " (%d)\n", retry);
+ }
+ }
+ }
+ bman_resource_init();
+ qman_resource_init();
+ return 0;
+}
+subsys_initcall(qbman_init);
diff --git a/drivers/staging/fsl_qbman/qman_config.c b/drivers/staging/fsl_qbman/qman_config.c
new file mode 100644
index 0000000..8a10c22
--- /dev/null
+++ b/drivers/staging/fsl_qbman/qman_config.c
@@ -0,0 +1,1146 @@
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <asm/cacheflush.h>
+#include "qman_private.h"
+
+/* Last updated for v00.800 of the BG */
+
+/* Register offsets */
+#define REG_QCSP_LIO_CFG(n) (0x0000 + ((n) * 0x10))
+#define REG_QCSP_IO_CFG(n) (0x0004 + ((n) * 0x10))
+#define REG_QCSP_DD_CFG(n) (0x000c + ((n) * 0x10))
+#define REG_DD_CFG 0x0200
+#define REG_DCP_CFG(n) (0x0300 + ((n) * 0x10))
+#define REG_DCP_DD_CFG(n) (0x0304 + ((n) * 0x10))
+#define REG_DCP_DLM_AVG(n) (0x030c + ((n) * 0x10))
+#define REG_PFDR_FPC 0x0400
+#define REG_PFDR_FP_HEAD 0x0404
+#define REG_PFDR_FP_TAIL 0x0408
+#define REG_PFDR_FP_LWIT 0x0410
+#define REG_PFDR_CFG 0x0414
+#define REG_SFDR_CFG 0x0500
+#define REG_SFDR_IN_USE 0x0504
+#define REG_WQ_CS_CFG(n) (0x0600 + ((n) * 0x04))
+#define REG_WQ_DEF_ENC_WQID 0x0630
+#define REG_WQ_SC_DD_CFG(n) (0x640 + ((n) * 0x04))
+#define REG_WQ_PC_DD_CFG(n) (0x680 + ((n) * 0x04))
+#define REG_WQ_DC0_DD_CFG(n) (0x6c0 + ((n) * 0x04))
+#define REG_WQ_DC1_DD_CFG(n) (0x700 + ((n) * 0x04))
+#define REG_WQ_DCn_DD_CFG(n) (0x6c0 + ((n) * 0x40)) /* n=2,3 */
+#define REG_CM_CFG 0x0800
+#define REG_ECSR 0x0a00
+#define REG_ECIR 0x0a04
+#define REG_EADR 0x0a08
+#define REG_ECIR2 0x0a0c
+#define REG_EDATA(n) (0x0a10 + ((n) * 0x04))
+#define REG_SBEC(n) (0x0a80 + ((n) * 0x04))
+#define REG_MCR 0x0b00
+#define REG_MCP(n) (0x0b04 + ((n) * 0x04))
+#define REG_MISC_CFG 0x0be0
+#define REG_HID_CFG 0x0bf0
+#define REG_IDLE_STAT 0x0bf4
+#define REG_IP_REV_1 0x0bf8
+#define REG_IP_REV_2 0x0bfc
+#define REG_FQD_BARE 0x0c00
+#define REG_PFDR_BARE 0x0c20
+#define REG_offset_BAR 0x0004 /* relative to REG_[FQD|PFDR]_BARE */
+#define REG_offset_AR 0x0010 /* relative to REG_[FQD|PFDR]_BARE */
+#define REG_QCSP_BARE 0x0c80
+#define REG_QCSP_BAR 0x0c84
+#define REG_CI_SCHED_CFG 0x0d00
+#define REG_SRCIDR 0x0d04
+#define REG_LIODNR 0x0d08
+#define REG_CI_RLM_AVG 0x0d14
+#define REG_ERR_ISR 0x0e00 /* + "enum qm_isr_reg" */
+#define REG_REV3_QCSP_LIO_CFG(n) (0x1000 + ((n) * 0x10))
+#define REG_REV3_QCSP_IO_CFG(n) (0x1004 + ((n) * 0x10))
+#define REG_REV3_QCSP_DD_CFG(n) (0x100c + ((n) * 0x10))
+#define REG_CEETM_CFG_IDX 0x900
+#define REG_CEETM_CFG_PRES 0x904
+#define REG_CEETM_XSFDR_IN_USE 0x908
+
+/* Assists for QMAN_MCR */
+#define MCR_INIT_PFDR 0x01000000
+#define MCR_get_rslt(v) (u8)((v) >> 24)
+#define MCR_rslt_idle(r) (!rslt || (rslt >= 0xf0))
+#define MCR_rslt_ok(r) (rslt == 0xf0)
+#define MCR_rslt_eaccess(r) (rslt == 0xf8)
+#define MCR_rslt_inval(r) (rslt == 0xff)
+
+struct qman;
+
+/* Follows WQ_CS_CFG0-5 */
+enum qm_wq_class {
+ qm_wq_portal = 0,
+ qm_wq_pool = 1,
+ qm_wq_fman0 = 2,
+ qm_wq_fman1 = 3,
+ qm_wq_caam = 4,
+ qm_wq_pme = 5,
+ qm_wq_first = qm_wq_portal,
+ qm_wq_last = qm_wq_pme
+};
+
+/* Follows FQD_[BARE|BAR|AR] and PFDR_[BARE|BAR|AR] */
+enum qm_memory {
+ qm_memory_fqd,
+ qm_memory_pfdr
+};
+
+/* Used by all error interrupt registers except 'inhibit' */
+#define QM_EIRQ_CIDE 0x20000000 /* Corenet Initiator Data Error */
+#define QM_EIRQ_CTDE 0x10000000 /* Corenet Target Data Error */
+#define QM_EIRQ_CITT 0x08000000 /* Corenet Invalid Target Transaction */
+#define QM_EIRQ_PLWI 0x04000000 /* PFDR Low Watermark */
+#define QM_EIRQ_MBEI 0x02000000 /* Multi-bit ECC Error */
+#define QM_EIRQ_SBEI 0x01000000 /* Single-bit ECC Error */
+#define QM_EIRQ_PEBI 0x00800000 /* PFDR Enqueues Blocked Interrupt */
+#define QM_EIRQ_IFSI 0x00020000 /* Invalid FQ Flow Control State */
+#define QM_EIRQ_ICVI 0x00010000 /* Invalid Command Verb */
+#define QM_EIRQ_IDDI 0x00000800 /* Invalid Dequeue (Direct-connect) */
+#define QM_EIRQ_IDFI 0x00000400 /* Invalid Dequeue FQ */
+#define QM_EIRQ_IDSI 0x00000200 /* Invalid Dequeue Source */
+#define QM_EIRQ_IDQI 0x00000100 /* Invalid Dequeue Queue */
+#define QM_EIRQ_IECE 0x00000010 /* Invalid Enqueue Configuration */
+#define QM_EIRQ_IEOI 0x00000008 /* Invalid Enqueue Overflow */
+#define QM_EIRQ_IESI 0x00000004 /* Invalid Enqueue State */
+#define QM_EIRQ_IECI 0x00000002 /* Invalid Enqueue Channel */
+#define QM_EIRQ_IEQI 0x00000001 /* Invalid Enqueue Queue */
+
+/* QMAN_ECIR valid error bit */
+#define PORTAL_ECSR_ERR (QM_EIRQ_IEQI | QM_EIRQ_IESI | QM_EIRQ_IEOI | \
+ QM_EIRQ_IDQI | QM_EIRQ_IDSI | QM_EIRQ_IDFI | \
+ QM_EIRQ_IDDI | QM_EIRQ_ICVI | QM_EIRQ_IFSI)
+#define FQID_ECSR_ERR (QM_EIRQ_IEQI | QM_EIRQ_IECI | QM_EIRQ_IESI | \
+ QM_EIRQ_IEOI | QM_EIRQ_IDQI | QM_EIRQ_IDFI | \
+ QM_EIRQ_IFSI)
+
+union qman_ecir {
+ u32 ecir_raw;
+ struct {
+ u32 __reserved:2;
+ u32 portal_type:1;
+ u32 portal_num:5;
+ u32 fqid:24;
+ } __packed info;
+};
+
+union qman_ecir2 {
+ u32 ecir2_raw;
+ struct {
+ u32 portal_type:1;
+ u32 __reserved:21;
+ u32 portal_num:10;
+ } __packed info;
+};
+
+union qman_eadr {
+ u32 eadr_raw;
+ struct {
+ u32 __reserved1:4;
+ u32 memid:4;
+ u32 __reserved2:12;
+ u32 eadr:12;
+ } __packed info;
+ struct {
+ u32 __reserved1:3;
+ u32 memid:5;
+ u32 __reserved:8;
+ u32 eadr:16;
+ } __packed info_rev3;
+};
+
+struct qman_hwerr_txt {
+ u32 mask;
+ const char *txt;
+};
+
+#define QMAN_HWE_TXT(a, b) { .mask = QM_EIRQ_##a, .txt = b }
+
+static const struct qman_hwerr_txt qman_hwerr_txts[] = {
+ QMAN_HWE_TXT(CIDE, "Corenet Initiator Data Error"),
+ QMAN_HWE_TXT(CTDE, "Corenet Target Data Error"),
+ QMAN_HWE_TXT(CITT, "Corenet Invalid Target Transaction"),
+ QMAN_HWE_TXT(PLWI, "PFDR Low Watermark"),
+ QMAN_HWE_TXT(MBEI, "Multi-bit ECC Error"),
+ QMAN_HWE_TXT(SBEI, "Single-bit ECC Error"),
+ QMAN_HWE_TXT(PEBI, "PFDR Enqueues Blocked Interrupt"),
+ QMAN_HWE_TXT(ICVI, "Invalid Command Verb"),
+ QMAN_HWE_TXT(IFSI, "Invalid Flow Control State"),
+ QMAN_HWE_TXT(IDDI, "Invalid Dequeue (Direct-connect)"),
+ QMAN_HWE_TXT(IDFI, "Invalid Dequeue FQ"),
+ QMAN_HWE_TXT(IDSI, "Invalid Dequeue Source"),
+ QMAN_HWE_TXT(IDQI, "Invalid Dequeue Queue"),
+ QMAN_HWE_TXT(IECE, "Invalid Enqueue Configuration"),
+ QMAN_HWE_TXT(IEOI, "Invalid Enqueue Overflow"),
+ QMAN_HWE_TXT(IESI, "Invalid Enqueue State"),
+ QMAN_HWE_TXT(IECI, "Invalid Enqueue Channel"),
+ QMAN_HWE_TXT(IEQI, "Invalid Enqueue Queue")
+};
+#define QMAN_HWE_COUNT (sizeof(qman_hwerr_txts)/sizeof(struct qman_hwerr_txt))
+
+struct qman_error_info_mdata {
+ u16 addr_mask;
+ u16 bits;
+ const char *txt;
+};
+
+#define QMAN_ERR_MDATA(a, b, c) { .addr_mask = a, .bits = b, .txt = c}
+static const struct qman_error_info_mdata error_mdata[] = {
+ QMAN_ERR_MDATA(0x01FF, 24, "FQD cache tag memory 0"),
+ QMAN_ERR_MDATA(0x01FF, 24, "FQD cache tag memory 1"),
+ QMAN_ERR_MDATA(0x01FF, 24, "FQD cache tag memory 2"),
+ QMAN_ERR_MDATA(0x01FF, 24, "FQD cache tag memory 3"),
+ QMAN_ERR_MDATA(0x0FFF, 512, "FQD cache memory"),
+ QMAN_ERR_MDATA(0x07FF, 128, "SFDR memory"),
+ QMAN_ERR_MDATA(0x01FF, 72, "WQ context memory"),
+ QMAN_ERR_MDATA(0x00FF, 240, "CGR memory"),
+ QMAN_ERR_MDATA(0x00FF, 302, "Internal Order Restoration List memory"),
+ QMAN_ERR_MDATA(0x01FF, 256, "SW portal ring memory"),
+ QMAN_ERR_MDATA(0x07FF, 181, "CEETM class queue descriptor memory"),
+ QMAN_ERR_MDATA(0x0FFF, 140, "CEETM extended SFDR memory"),
+ QMAN_ERR_MDATA(0x0FFF, 25, "CEETM logical FQ mapping memory"),
+ QMAN_ERR_MDATA(0x0FFF, 96, "CEETM dequeue context memory"),
+ QMAN_ERR_MDATA(0x07FF, 396, "CEETM ccgr memory"),
+ QMAN_ERR_MDATA(0x00FF, 146, "CEETM CQ channel shaping memory"),
+ QMAN_ERR_MDATA(0x007F, 256, "CEETM CQ channel scheduling memory"),
+ QMAN_ERR_MDATA(0x01FF, 88, "CEETM dequeue statistics memory"),
+};
+#define QMAN_ERR_MDATA_COUNT \
+ (sizeof(error_mdata)/sizeof(struct qman_error_info_mdata))
+
+/* Add this in Kconfig */
+#define QMAN_ERRS_TO_UNENABLE (QM_EIRQ_PLWI | QM_EIRQ_PEBI)
+
+/**
+ * qm_err_isr_<reg>_<verb> - Manipulate global interrupt registers
+ * @v: for accessors that write values, this is the 32-bit value
+ *
+ * Manipulates QMAN_ERR_ISR, QMAN_ERR_IER, QMAN_ERR_ISDR, QMAN_ERR_IIR. All
+ * manipulations except qm_err_isr_[un]inhibit() use 32-bit masks composed of
+ * the QM_EIRQ_*** definitions. Note that "qm_err_isr_enable_write" means
+ * "write the enable register" rather than "enable the write register"!
+ */
+#define qm_err_isr_status_read(qm) \
+ __qm_err_isr_read(qm, qm_isr_status)
+#define qm_err_isr_status_clear(qm, m) \
+ __qm_err_isr_write(qm, qm_isr_status, m)
+#define qm_err_isr_enable_read(qm) \
+ __qm_err_isr_read(qm, qm_isr_enable)
+#define qm_err_isr_enable_write(qm, v) \
+ __qm_err_isr_write(qm, qm_isr_enable, v)
+#define qm_err_isr_disable_read(qm) \
+ __qm_err_isr_read(qm, qm_isr_disable)
+#define qm_err_isr_disable_write(qm, v) \
+ __qm_err_isr_write(qm, qm_isr_disable, v)
+#define qm_err_isr_inhibit(qm) \
+ __qm_err_isr_write(qm, qm_isr_inhibit, 1)
+#define qm_err_isr_uninhibit(qm) \
+ __qm_err_isr_write(qm, qm_isr_inhibit, 0)
+
+/*
+ * TODO: unimplemented registers
+ *
+ * Keeping a list here of Qman registers I have not yet covered;
+ * QCSP_DD_IHRSR, QCSP_DD_IHRFR, QCSP_DD_HASR,
+ * DCP_DD_IHRSR, DCP_DD_IHRFR, DCP_DD_HASR, CM_CFG,
+ * QMAN_EECC, QMAN_SBET, QMAN_EINJ, QMAN_SBEC0-12
+ */
+
+/* Encapsulate "struct qman *" as a cast of the register space address. */
+
+static struct qman *qm_create(void *regs)
+{
+ return (struct qman *)regs;
+}
+
+static inline u32 __qm_in(struct qman *qm, u32 offset)
+{
+ return in_be32((void *)qm + offset);
+}
+static inline void __qm_out(struct qman *qm, u32 offset, u32 val)
+{
+ out_be32((void *)qm + offset, val);
+}
+#define qm_in(reg) __qm_in(qm, REG_##reg)
+#define qm_out(reg, val) __qm_out(qm, REG_##reg, val)
+
+static u32 __qm_err_isr_read(struct qman *qm, enum qm_isr_reg n)
+{
+ return __qm_in(qm, REG_ERR_ISR + (n << 2));
+}
+
+static void __qm_err_isr_write(struct qman *qm, enum qm_isr_reg n, u32 val)
+{
+ __qm_out(qm, REG_ERR_ISR + (n << 2), val);
+}
+
+static void qm_set_dc(struct qman *qm, enum qm_dc_portal portal,
+ int ed, u8 sernd)
+{
+ DPA_ASSERT(!ed || (portal == qm_dc_portal_fman0) ||
+ (portal == qm_dc_portal_fman1));
+ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30)
+ qm_out(DCP_CFG(portal), (ed ? 0x1000 : 0) | (sernd & 0x3ff));
+ else
+ qm_out(DCP_CFG(portal), (ed ? 0x100 : 0) | (sernd & 0x1f));
+}
+
+static void qm_set_wq_scheduling(struct qman *qm, enum qm_wq_class wq_class,
+ u8 cs_elev, u8 csw2, u8 csw3, u8 csw4, u8 csw5,
+ u8 csw6, u8 csw7)
+{
+ qm_out(WQ_CS_CFG(wq_class), ((cs_elev & 0xff) << 24) |
+ ((csw2 & 0x7) << 20) | ((csw3 & 0x7) << 16) |
+ ((csw4 & 0x7) << 12) | ((csw5 & 0x7) << 8) |
+ ((csw6 & 0x7) << 4) | (csw7 & 0x7));
+}
+
+static void qm_set_hid(struct qman *qm)
+{
+ qm_out(HID_CFG, 0);
+}
+
+static void qm_set_corenet_initiator(struct qman *qm)
+{
+ qm_out(CI_SCHED_CFG,
+ 0x80000000 | /* write srcciv enable */
+ (CONFIG_FSL_QMAN_CI_SCHED_CFG_SRCCIV << 24) |
+ (CONFIG_FSL_QMAN_CI_SCHED_CFG_SRQ_W << 8) |
+ (CONFIG_FSL_QMAN_CI_SCHED_CFG_RW_W << 4) |
+ CONFIG_FSL_QMAN_CI_SCHED_CFG_BMAN_W);
+}
+
+static void qm_get_version(struct qman *qm, u16 *id, u8 *major, u8 *minor)
+{
+ u32 v = qm_in(IP_REV_1);
+ *id = (v >> 16);
+ *major = (v >> 8) & 0xff;
+ *minor = v & 0xff;
+}
+
+static void qm_set_memory(struct qman *qm, enum qm_memory memory, u64 ba,
+ int enable, int prio, int stash, u32 size)
+{
+ u32 offset = (memory == qm_memory_fqd) ? REG_FQD_BARE : REG_PFDR_BARE;
+ u32 exp = ilog2(size);
+ /* choke if size isn't within range */
+ DPA_ASSERT((size >= 4096) && (size <= 1073741824) &&
+ is_power_of_2(size));
+ /* choke if 'ba' has lower-alignment than 'size' */
+ DPA_ASSERT(!(ba & (size - 1)));
+ __qm_out(qm, offset, upper_32_bits(ba));
+ __qm_out(qm, offset + REG_offset_BAR, lower_32_bits(ba));
+ __qm_out(qm, offset + REG_offset_AR,
+ (enable ? 0x80000000 : 0) |
+ (prio ? 0x40000000 : 0) |
+ (stash ? 0x20000000 : 0) |
+ (exp - 1));
+}
+
+static void qm_set_pfdr_threshold(struct qman *qm, u32 th, u8 k)
+{
+ qm_out(PFDR_FP_LWIT, th & 0xffffff);
+ qm_out(PFDR_CFG, k);
+}
+
+static void qm_set_sfdr_threshold(struct qman *qm, u16 th)
+{
+ qm_out(SFDR_CFG, th & 0x3ff);
+}
+
+static int qm_init_pfdr(struct qman *qm, u32 pfdr_start, u32 num)
+{
+ u8 rslt = MCR_get_rslt(qm_in(MCR));
+
+ DPA_ASSERT(pfdr_start && !(pfdr_start & 7) && !(num & 7) && num);
+ /* Make sure the command interface is 'idle' */
+ if (!MCR_rslt_idle(rslt))
+ panic("QMAN_MCR isn't idle");
+
+ /* Write the MCR command params then the verb */
+ qm_out(MCP(0), pfdr_start);
+ /* TODO: remove this - it's a workaround for a model bug that is
+ * corrected in more recent versions. We use the workaround until
+ * everyone has upgraded. */
+ qm_out(MCP(1), (pfdr_start + num - 16));
+ lwsync();
+ qm_out(MCR, MCR_INIT_PFDR);
+ /* Poll for the result */
+ do {
+ rslt = MCR_get_rslt(qm_in(MCR));
+ } while (!MCR_rslt_idle(rslt));
+ if (MCR_rslt_ok(rslt))
+ return 0;
+ if (MCR_rslt_eaccess(rslt))
+ return -EACCES;
+ if (MCR_rslt_inval(rslt))
+ return -EINVAL;
+ pr_crit("Unexpected result from MCR_INIT_PFDR: %02x\n", rslt);
+ return -ENOSYS;
+}
+
+/*****************/
+/* Config driver */
+/*****************/
+
+#define DEFAULT_FQD_SZ (PAGE_SIZE << CONFIG_FSL_QMAN_FQD_SZ)
+#define DEFAULT_PFDR_SZ (PAGE_SIZE << CONFIG_FSL_QMAN_PFDR_SZ)
+
+/* We support only one of these */
+static struct qman *qm;
+static struct device_node *qm_node;
+
+/* And this state belongs to 'qm'. It is set during fsl_qman_init(), but used
+ * during qman_init_ccsr(). */
+static dma_addr_t fqd_a, pfdr_a;
+static size_t fqd_sz = DEFAULT_FQD_SZ, pfdr_sz = DEFAULT_PFDR_SZ;
+
+/* Parse the <name> property to extract the memory location and size and
+ * memblock_reserve() it. If it isn't supplied, memblock_alloc() the default
+ * size. Also flush this memory range from data cache so that QMAN originated
+ * transactions for this memory region could be marked non-coherent.
+ */
+static __init int parse_mem_property(struct device_node *node, const char *name,
+ dma_addr_t *addr, size_t *sz, int zero)
+{
+ const u32 *pint;
+ int ret;
+ unsigned long vaddr;
+
+ pint = of_get_property(node, name, &ret);
+ if (!pint || (ret != 16)) {
+ pr_info("No %s property '%s', using memblock_alloc(%016zx)\n",
+ node->full_name, name, *sz);
+ *addr = memblock_alloc(*sz, *sz);
+ vaddr = (unsigned long)phys_to_virt(*addr);
+ if (zero)
+ memset((void *)vaddr, 0, *sz);
+ flush_dcache_range(vaddr, vaddr + *sz);
+ return 0;
+ }
+ pr_info("Using %s property '%s'\n", node->full_name, name);
+ /* If using a "zero-pma", don't try to zero it, even if you asked */
+ if (zero && of_find_property(node, "zero-pma", &ret)) {
+ pr_info(" it's a 'zero-pma', not zeroing from s/w\n");
+ zero = 0;
+ }
+ *addr = ((u64)pint[0] << 32) | (u64)pint[1];
+ *sz = ((u64)pint[2] << 32) | (u64)pint[3];
+ /* Keep things simple, it's either all in the DRAM range or it's all
+ * outside. */
+ if (*addr < memblock_end_of_DRAM()) {
+ BUG_ON((u64)*addr + (u64)*sz > memblock_end_of_DRAM());
+ if (memblock_reserve(*addr, *sz) < 0) {
+ pr_err("Failed to reserve %s\n", name);
+ return -ENOMEM;
+ }
+ vaddr = (unsigned long)phys_to_virt(*addr);
+ if (zero)
+ memset(phys_to_virt(*addr), 0, *sz);
+ flush_dcache_range(vaddr, vaddr + *sz);
+ } else if (zero) {
+ /* map as cacheable, non-guarded */
+ void __iomem *tmpp = ioremap_prot(*addr, *sz, 0);
+ memset_io(tmpp, 0, *sz);
+ vaddr = (unsigned long)tmpp;
+ flush_dcache_range(vaddr, vaddr + *sz);
+ iounmap(tmpp);
+ }
+ return 0;
+}
+
+/* TODO:
+ * - there is obviously no handling of errors,
+ * - the calls to qm_set_memory() hard-code the priority and CPC-stashing for
+ * both memory resources to zero.
+ */
+static int __init fsl_qman_init(struct device_node *node)
+{
+ struct resource res;
+ u32 __iomem *regs;
+ const char *s;
+ int ret, standby = 0;
+ u16 id;
+ u8 major, minor;
+ ret = of_address_to_resource(node, 0, &res);
+ if (ret) {
+ pr_err("Can't get %s property '%s'\n", node->full_name, "reg");
+ return ret;
+ }
+ s = of_get_property(node, "fsl,hv-claimable", &ret);
+ if (s && !strcmp(s, "standby"))
+ standby = 1;
+ if (!standby) {
+ ret = parse_mem_property(node, "fsl,qman-fqd",
+ &fqd_a, &fqd_sz, 1);
+ BUG_ON(ret);
+ ret = parse_mem_property(node, "fsl,qman-pfdr",
+ &pfdr_a, &pfdr_sz, 0);
+ BUG_ON(ret);
+ }
+ /* Global configuration */
+ regs = ioremap(res.start, res.end - res.start + 1);
+ qm = qm_create(regs);
+ qm_node = node;
+ qm_get_version(qm, &id, &major, &minor);
+ pr_info("Qman ver:%04x,%02x,%02x\n", id, major, minor);
+ if (!qman_ip_rev) {
+ if ((major == 1) && (minor == 0)) {
+ pr_err("QMAN rev1.0 on P4080 rev1 is not supported!\n");
+ iounmap(regs);
+ return -ENODEV;
+ } else if ((major == 1) && (minor == 1))
+ qman_ip_rev = QMAN_REV11;
+ else if ((major == 1) && (minor == 2))
+ qman_ip_rev = QMAN_REV12;
+ else if ((major == 2) && (minor == 0))
+ qman_ip_rev = QMAN_REV20;
+ else if ((major == 3) && (minor == 0))
+ qman_ip_rev = QMAN_REV30;
+ else if ((major == 3) && (minor == 1))
+ qman_ip_rev = QMAN_REV31;
+ else {
+ pr_warn("unknown Qman version, default to rev1.1\n");
+ qman_ip_rev = QMAN_REV11;
+ }
+ }
+
+ if (standby) {
+ pr_info(" -> in standby mode\n");
+ return 0;
+ }
+ return 0;
+}
+
+int qman_have_ccsr(void)
+{
+ return qm ? 1 : 0;
+}
+
+__init void qman_init_early(void)
+{
+ struct device_node *dn;
+ int ret;
+
+ for_each_compatible_node(dn, NULL, "fsl,qman") {
+ if (qm)
+ pr_err("%s: only one 'fsl,qman' allowed\n",
+ dn->full_name);
+ else {
+ if (!of_device_is_available(dn))
+ continue;
+
+ ret = fsl_qman_init(dn);
+ BUG_ON(ret);
+ }
+ }
+}
+
+static void log_edata_bits(u32 bit_count)
+{
+ u32 i, j, mask = 0xffffffff;
+
+ pr_warn("Qman ErrInt, EDATA:\n");
+ i = bit_count/32;
+ if (bit_count%32) {
+ i++;
+ mask = ~(mask << bit_count%32);
+ }
+ j = 16-i;
+ pr_warn(" 0x%08x\n", qm_in(EDATA(j)) & mask);
+ j++;
+ for (; j < 16; j++)
+ pr_warn(" 0x%08x\n", qm_in(EDATA(j)));
+}
+
+static void log_additional_error_info(u32 isr_val, u32 ecsr_val)
+{
+ union qman_ecir ecir_val;
+ union qman_eadr eadr_val;
+
+ ecir_val.ecir_raw = qm_in(ECIR);
+ /* Is portal info valid */
+ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30) {
+ union qman_ecir2 ecir2_val;
+ ecir2_val.ecir2_raw = qm_in(ECIR2);
+ if (ecsr_val & PORTAL_ECSR_ERR) {
+ pr_warn("Qman ErrInt: %s id %d\n",
+ (ecir2_val.info.portal_type) ?
+ "DCP" : "SWP", ecir2_val.info.portal_num);
+ }
+ if (ecsr_val & (FQID_ECSR_ERR | QM_EIRQ_IECE)) {
+ pr_warn("Qman ErrInt: ecir.fqid 0x%x\n",
+ ecir_val.info.fqid);
+ }
+ if (ecsr_val & (QM_EIRQ_SBEI|QM_EIRQ_MBEI)) {
+ eadr_val.eadr_raw = qm_in(EADR);
+ pr_warn("Qman ErrInt: EADR Memory: %s, 0x%x\n",
+ error_mdata[eadr_val.info_rev3.memid].txt,
+ error_mdata[eadr_val.info_rev3.memid].addr_mask
+ & eadr_val.info_rev3.eadr);
+ log_edata_bits(
+ error_mdata[eadr_val.info_rev3.memid].bits);
+ }
+ } else {
+ if (ecsr_val & PORTAL_ECSR_ERR) {
+ pr_warn("Qman ErrInt: %s id %d\n",
+ (ecir_val.info.portal_type) ?
+ "DCP" : "SWP", ecir_val.info.portal_num);
+ }
+ if (ecsr_val & FQID_ECSR_ERR) {
+ pr_warn("Qman ErrInt: ecir.fqid 0x%x\n",
+ ecir_val.info.fqid);
+ }
+ if (ecsr_val & (QM_EIRQ_SBEI|QM_EIRQ_MBEI)) {
+ eadr_val.eadr_raw = qm_in(EADR);
+ pr_warn("Qman ErrInt: EADR Memory: %s, 0x%x\n",
+ error_mdata[eadr_val.info.memid].txt,
+ error_mdata[eadr_val.info.memid].addr_mask
+ & eadr_val.info.eadr);
+ log_edata_bits(error_mdata[eadr_val.info.memid].bits);
+ }
+ }
+}
+
+/* Qman interrupt handler */
+static irqreturn_t qman_isr(int irq, void *ptr)
+{
+ u32 isr_val, ier_val, ecsr_val, isr_mask, i;
+
+ ier_val = qm_err_isr_enable_read(qm);
+ isr_val = qm_err_isr_status_read(qm);
+ ecsr_val = qm_in(ECSR);
+ isr_mask = isr_val & ier_val;
+
+ if (!isr_mask)
+ return IRQ_NONE;
+ for (i = 0; i < QMAN_HWE_COUNT; i++) {
+ if (qman_hwerr_txts[i].mask & isr_mask) {
+ pr_warn("Qman ErrInt: %s\n", qman_hwerr_txts[i].txt);
+ if (qman_hwerr_txts[i].mask & ecsr_val) {
+ log_additional_error_info(isr_mask, ecsr_val);
+ /* Re-arm error capture registers */
+ qm_out(ECSR, ecsr_val);
+ }
+ if (qman_hwerr_txts[i].mask & QMAN_ERRS_TO_UNENABLE) {
+ pr_devel("Qman un-enabling error 0x%x\n",
+ qman_hwerr_txts[i].mask);
+ ier_val &= ~qman_hwerr_txts[i].mask;
+ qm_err_isr_enable_write(qm, ier_val);
+ }
+ }
+ }
+ qm_err_isr_status_clear(qm, isr_val);
+ return IRQ_HANDLED;
+}
+
+static int __bind_irq(void)
+{
+ int ret, err_irq;
+
+ err_irq = of_irq_to_resource(qm_node, 0, NULL);
+ if (err_irq == NO_IRQ) {
+ pr_info("Can't get %s property '%s'\n", qm_node->full_name,
+ "interrupts");
+ return -ENODEV;
+ }
+ ret = request_irq(err_irq, qman_isr, IRQF_SHARED, "qman-err", qm_node);
+ if (ret) {
+ pr_err("request_irq() failed %d for '%s'\n", ret,
+ qm_node->full_name);
+ return -ENODEV;
+ }
+ /* Write-to-clear any stale bits, (eg. starvation being asserted prior
+ * to resource allocation during driver init). */
+ qm_err_isr_status_clear(qm, 0xffffffff);
+ /* Enable Error Interrupts */
+ qm_err_isr_enable_write(qm, 0xffffffff);
+ return 0;
+}
+
+int qman_init_ccsr(struct device_node *node)
+{
+ int ret;
+ if (!qman_have_ccsr())
+ return 0;
+ if (node != qm_node)
+ return -EINVAL;
+ /* FQD memory */
+ qm_set_memory(qm, qm_memory_fqd, fqd_a, 1, 0, 0, fqd_sz);
+ /* PFDR memory */
+ qm_set_memory(qm, qm_memory_pfdr, pfdr_a, 1, 0, 0, pfdr_sz);
+ qm_init_pfdr(qm, 8, pfdr_sz / 64 - 8);
+ /* thresholds */
+ qm_set_pfdr_threshold(qm, 512, 64);
+ qm_set_sfdr_threshold(qm, 128);
+ /* clear stale PEBI bit from interrupt status register */
+ qm_err_isr_status_clear(qm, QM_EIRQ_PEBI);
+ /* corenet initiator settings */
+ qm_set_corenet_initiator(qm);
+ /* HID settings */
+ qm_set_hid(qm);
+ /* Set scheduling weights to defaults */
+ for (ret = qm_wq_first; ret <= qm_wq_last; ret++)
+ qm_set_wq_scheduling(qm, ret, 0, 0, 0, 0, 0, 0, 0);
+ /* We are not prepared to accept ERNs for hardware enqueues */
+ qm_set_dc(qm, qm_dc_portal_fman0, 1, 0);
+ qm_set_dc(qm, qm_dc_portal_fman1, 1, 0);
+ /* Initialise Error Interrupt Handler */
+ ret = __bind_irq();
+ if (ret)
+ return ret;
+ return 0;
+}
+
+#define LIO_CFG_LIODN_MASK 0x0fff0000
+void qman_liodn_fixup(u16 channel)
+{
+ static int done;
+ static u32 liodn_offset;
+ u32 before, after;
+ int idx = channel - QM_CHANNEL_SWPORTAL0;
+
+ if (!qman_have_ccsr())
+ return;
+ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30)
+ before = qm_in(REV3_QCSP_LIO_CFG(idx));
+ else
+ before = qm_in(QCSP_LIO_CFG(idx));
+ if (!done) {
+ liodn_offset = before & LIO_CFG_LIODN_MASK;
+ done = 1;
+ return;
+ }
+ after = (before & (~LIO_CFG_LIODN_MASK)) | liodn_offset;
+ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30)
+ qm_out(REV3_QCSP_LIO_CFG(idx), after);
+ else
+ qm_out(QCSP_LIO_CFG(idx), after);
+}
+
+#define IO_CFG_SDEST_MASK 0x00ff0000
+int qman_set_sdest(u16 channel, unsigned int cpu_idx)
+{
+ int idx = channel - QM_CHANNEL_SWPORTAL0;
+ u32 before, after;
+
+ if (!qman_have_ccsr())
+ return -ENODEV;
+
+ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30) {
+ before = qm_in(REV3_QCSP_IO_CFG(idx));
+ /* Each pair of vcpu share the same SRQ(SDEST) */
+ cpu_idx /= 2;
+ after = (before & (~IO_CFG_SDEST_MASK)) | (cpu_idx << 16);
+ qm_out(REV3_QCSP_IO_CFG(idx), after);
+ } else {
+ before = qm_in(QCSP_IO_CFG(idx));
+ after = (before & (~IO_CFG_SDEST_MASK)) | (cpu_idx << 16);
+ qm_out(QCSP_IO_CFG(idx), after);
+ }
+ return 0;
+}
+
+#define MISC_CFG_WPM_MASK 0x00000002
+int qm_set_wpm(int wpm)
+{
+ u32 before;
+ u32 after;
+
+ if (!qman_have_ccsr())
+ return -ENODEV;
+
+ before = qm_in(MISC_CFG);
+ after = (before & (~MISC_CFG_WPM_MASK)) | (wpm << 1);
+ qm_out(MISC_CFG, after);
+ return 0;
+}
+
+int qm_get_wpm(int *wpm)
+{
+ u32 before;
+
+ if (!qman_have_ccsr())
+ return -ENODEV;
+
+ before = qm_in(MISC_CFG);
+ *wpm = (before & MISC_CFG_WPM_MASK) >> 1;
+ return 0;
+}
+
+/* CEETM_CFG_PRES register has PRES field which is calculated by:
+ * PRES = (2^22 / credit update reference period) * QMan clock period
+ * = (2^22 * 10^9)/ CONFIG_QMAN_CEETM_UPDATE_PERIOD) / qman_clk
+ */
+
+int qman_ceetm_set_prescaler(enum qm_dc_portal portal)
+{
+ u64 temp;
+ u16 pres;
+
+ if (!qman_have_ccsr())
+ return -ENODEV;
+
+ temp = 0x400000 * 100;
+ temp /= CONFIG_QMAN_CEETM_UPDATE_PERIOD;
+ temp *= 10000000;
+ pres = (u16)(temp / qman_clk);
+
+ qm_out(CEETM_CFG_IDX, portal);
+ qm_out(CEETM_CFG_PRES, pres);
+ return 0;
+}
+
+int qman_ceetm_get_prescaler(u16 *pres)
+{
+ if (!qman_have_ccsr())
+ return -ENODEV;
+ *pres = (u16)qm_in(CEETM_CFG_PRES);
+ return 0;
+}
+
+#define DCP_CFG_CEETME_MASK 0xFFFF0000
+#define QM_SP_ENABLE_CEETM(n) (0x80000000 >> (n))
+int qman_sp_enable_ceetm_mode(enum qm_dc_portal portal, u16 sub_portal)
+{
+ u32 dcp_cfg;
+
+ if (!qman_have_ccsr())
+ return -ENODEV;
+
+ dcp_cfg = qm_in(DCP_CFG(portal));
+ dcp_cfg |= QM_SP_ENABLE_CEETM(sub_portal);
+ qm_out(DCP_CFG(portal), dcp_cfg);
+ return 0;
+}
+
+int qman_sp_disable_ceetm_mode(enum qm_dc_portal portal, u16 sub_portal)
+{
+ u32 dcp_cfg;
+
+ if (!qman_have_ccsr())
+ return -ENODEV;
+ dcp_cfg = qm_in(DCP_CFG(portal));
+ dcp_cfg &= ~(QM_SP_ENABLE_CEETM(sub_portal));
+ qm_out(DCP_CFG(portal), dcp_cfg);
+ return 0;
+}
+
+int qman_ceetm_get_xsfdr(enum qm_dc_portal portal, unsigned int *num)
+{
+ if (!qman_have_ccsr())
+ return -ENODEV;
+ *num = qm_in(CEETM_XSFDR_IN_USE);
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_get_xsfdr);
+
+#ifdef CONFIG_SYSFS
+
+#define DRV_NAME "fsl-qman"
+
+static ssize_t show_pfdr_fpc(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%u\n", qm_in(PFDR_FPC));
+};
+
+static ssize_t show_dlm_avg(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
+{
+ u32 data;
+ int i;
+
+ if (!sscanf(dev_attr->attr.name, "dcp%d_dlm_avg", &i))
+ return -EINVAL;
+ data = qm_in(DCP_DLM_AVG(i));
+ return snprintf(buf, PAGE_SIZE, "%d.%08d\n", data>>8,
+ (data & 0x000000ff)*390625);
+};
+
+static ssize_t set_dlm_avg(struct device *dev,
+ struct device_attribute *dev_attr, const char *buf, size_t count)
+{
+ unsigned long val;
+ int i;
+
+ if (!sscanf(dev_attr->attr.name, "dcp%d_dlm_avg", &i))
+ return -EINVAL;
+ if (kstrtoul(buf, 0, &val)) {
+ dev_dbg(dev, "invalid input %s\n", buf);
+ return -EINVAL;
+ }
+ qm_out(DCP_DLM_AVG(i), val);
+ return count;
+};
+
+static ssize_t show_pfdr_cfg(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%u\n", qm_in(PFDR_CFG));
+};
+
+static ssize_t set_pfdr_cfg(struct device *dev,
+ struct device_attribute *dev_attr, const char *buf, size_t count)
+{
+ unsigned long val;
+
+ if (kstrtoul(buf, 0, &val)) {
+ dev_dbg(dev, "invalid input %s\n", buf);
+ return -EINVAL;
+ }
+ qm_out(PFDR_CFG, val);
+ return count;
+};
+
+static ssize_t show_sfdr_in_use(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%u\n", qm_in(SFDR_IN_USE));
+};
+
+static ssize_t show_idle_stat(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%u\n", qm_in(IDLE_STAT));
+};
+
+static ssize_t show_ci_rlm_avg(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
+{
+ u32 data = qm_in(CI_RLM_AVG);
+ return snprintf(buf, PAGE_SIZE, "%d.%08d\n", data>>8,
+ (data & 0x000000ff)*390625);
+};
+
+static ssize_t set_ci_rlm_avg(struct device *dev,
+ struct device_attribute *dev_attr, const char *buf, size_t count)
+{
+ unsigned long val;
+
+ if (kstrtoul(buf, 0, &val)) {
+ dev_dbg(dev, "invalid input %s\n", buf);
+ return -EINVAL;
+ }
+ qm_out(CI_RLM_AVG, val);
+ return count;
+};
+
+static ssize_t show_err_isr(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "0x%08x\n", qm_in(ERR_ISR));
+};
+
+
+static ssize_t show_sbec(struct device *dev,
+ struct device_attribute *dev_attr, char *buf)
+{
+ int i;
+
+ if (!sscanf(dev_attr->attr.name, "sbec_%d", &i))
+ return -EINVAL;
+ return snprintf(buf, PAGE_SIZE, "%u\n", qm_in(SBEC(i)));
+};
+
+static DEVICE_ATTR(pfdr_fpc, S_IRUSR, show_pfdr_fpc, NULL);
+static DEVICE_ATTR(pfdr_cfg, S_IRUSR, show_pfdr_cfg, set_pfdr_cfg);
+static DEVICE_ATTR(idle_stat, S_IRUSR, show_idle_stat, NULL);
+static DEVICE_ATTR(ci_rlm_avg, (S_IRUSR|S_IWUSR),
+ show_ci_rlm_avg, set_ci_rlm_avg);
+static DEVICE_ATTR(err_isr, S_IRUSR, show_err_isr, NULL);
+static DEVICE_ATTR(sfdr_in_use, S_IRUSR, show_sfdr_in_use, NULL);
+
+static DEVICE_ATTR(dcp0_dlm_avg, (S_IRUSR|S_IWUSR), show_dlm_avg, set_dlm_avg);
+static DEVICE_ATTR(dcp1_dlm_avg, (S_IRUSR|S_IWUSR), show_dlm_avg, set_dlm_avg);
+static DEVICE_ATTR(dcp2_dlm_avg, (S_IRUSR|S_IWUSR), show_dlm_avg, set_dlm_avg);
+static DEVICE_ATTR(dcp3_dlm_avg, (S_IRUSR|S_IWUSR), show_dlm_avg, set_dlm_avg);
+
+static DEVICE_ATTR(sbec_0, S_IRUSR, show_sbec, NULL);
+static DEVICE_ATTR(sbec_1, S_IRUSR, show_sbec, NULL);
+static DEVICE_ATTR(sbec_2, S_IRUSR, show_sbec, NULL);
+static DEVICE_ATTR(sbec_3, S_IRUSR, show_sbec, NULL);
+static DEVICE_ATTR(sbec_4, S_IRUSR, show_sbec, NULL);
+static DEVICE_ATTR(sbec_5, S_IRUSR, show_sbec, NULL);
+static DEVICE_ATTR(sbec_6, S_IRUSR, show_sbec, NULL);
+static DEVICE_ATTR(sbec_7, S_IRUSR, show_sbec, NULL);
+static DEVICE_ATTR(sbec_8, S_IRUSR, show_sbec, NULL);
+static DEVICE_ATTR(sbec_9, S_IRUSR, show_sbec, NULL);
+static DEVICE_ATTR(sbec_10, S_IRUSR, show_sbec, NULL);
+static DEVICE_ATTR(sbec_11, S_IRUSR, show_sbec, NULL);
+static DEVICE_ATTR(sbec_12, S_IRUSR, show_sbec, NULL);
+static DEVICE_ATTR(sbec_13, S_IRUSR, show_sbec, NULL);
+static DEVICE_ATTR(sbec_14, S_IRUSR, show_sbec, NULL);
+
+static struct attribute *qman_dev_attributes[] = {
+ &dev_attr_pfdr_fpc.attr,
+ &dev_attr_pfdr_cfg.attr,
+ &dev_attr_idle_stat.attr,
+ &dev_attr_ci_rlm_avg.attr,
+ &dev_attr_err_isr.attr,
+ &dev_attr_dcp0_dlm_avg.attr,
+ &dev_attr_dcp1_dlm_avg.attr,
+ &dev_attr_dcp2_dlm_avg.attr,
+ &dev_attr_dcp3_dlm_avg.attr,
+ /* sfdr_in_use will be added if necessary */
+ NULL
+};
+
+static struct attribute *qman_dev_ecr_attributes[] = {
+ &dev_attr_sbec_0.attr,
+ &dev_attr_sbec_1.attr,
+ &dev_attr_sbec_2.attr,
+ &dev_attr_sbec_3.attr,
+ &dev_attr_sbec_4.attr,
+ &dev_attr_sbec_5.attr,
+ &dev_attr_sbec_6.attr,
+ &dev_attr_sbec_7.attr,
+ &dev_attr_sbec_8.attr,
+ &dev_attr_sbec_9.attr,
+ &dev_attr_sbec_10.attr,
+ &dev_attr_sbec_11.attr,
+ &dev_attr_sbec_12.attr,
+ &dev_attr_sbec_13.attr,
+ &dev_attr_sbec_14.attr,
+ NULL
+};
+
+/* root level */
+static const struct attribute_group qman_dev_attr_grp = {
+ .name = NULL,
+ .attrs = qman_dev_attributes
+};
+static const struct attribute_group qman_dev_ecr_grp = {
+ .name = "error_capture",
+ .attrs = qman_dev_ecr_attributes
+};
+
+static int of_fsl_qman_remove(struct platform_device *ofdev)
+{
+ sysfs_remove_group(&ofdev->dev.kobj, &qman_dev_attr_grp);
+ return 0;
+};
+
+static int of_fsl_qman_probe(struct platform_device *ofdev)
+{
+ int ret;
+
+ ret = sysfs_create_group(&ofdev->dev.kobj, &qman_dev_attr_grp);
+ if (ret)
+ goto done;
+ ret = sysfs_add_file_to_group(&ofdev->dev.kobj,
+ &dev_attr_sfdr_in_use.attr, qman_dev_attr_grp.name);
+ if (ret)
+ goto del_group_0;
+ ret = sysfs_create_group(&ofdev->dev.kobj, &qman_dev_ecr_grp);
+ if (ret)
+ goto del_group_0;
+
+ goto done;
+
+del_group_0:
+ sysfs_remove_group(&ofdev->dev.kobj, &qman_dev_attr_grp);
+done:
+ if (ret)
+ dev_err(&ofdev->dev,
+ "Cannot create dev attributes ret=%d\n", ret);
+ return ret;
+};
+
+static struct of_device_id of_fsl_qman_ids[] = {
+ {
+ .compatible = "fsl,qman",
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, of_fsl_qman_ids);
+
+#ifdef CONFIG_PM
+
+static u32 saved_isdr;
+static int qman_pm_suspend_noirq(struct device *dev)
+{
+ suspend_unused_qportal();
+ /* save isdr, disable all, clear isr */
+ saved_isdr = qm_err_isr_disable_read(qm);
+ qm_err_isr_disable_write(qm, 0xffffffff);
+ qm_err_isr_status_clear(qm, 0xffffffff);
+ /* should be idle, otherwise abort ? */
+#ifdef CONFIG_PM_DEBUG
+ pr_info("Qman suspend code, IDLE_STAT = 0x%x\n", qm_in(IDLE_STAT));
+#endif
+ return 0;
+}
+
+static int qman_pm_resume_noirq(struct device *dev)
+{
+ /* restore isdr */
+ qm_err_isr_disable_write(qm, saved_isdr);
+ resume_unused_qportal();
+ return 0;
+}
+#else
+#define qman_pm_suspend_noirq NULL
+#define qman_pm_resume_noirq NULL
+#endif
+
+static const struct dev_pm_ops qman_pm_ops = {
+ .suspend_noirq = qman_pm_suspend_noirq,
+ .resume_noirq = qman_pm_resume_noirq,
+};
+
+static struct platform_driver of_fsl_qman_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRV_NAME,
+ .of_match_table = of_fsl_qman_ids,
+ .pm = &qman_pm_ops,
+ },
+ .probe = of_fsl_qman_probe,
+ .remove = of_fsl_qman_remove,
+};
+
+static int qman_ctrl_init(void)
+{
+ return platform_driver_register(&of_fsl_qman_driver);
+}
+
+static void qman_ctrl_exit(void)
+{
+ platform_driver_unregister(&of_fsl_qman_driver);
+}
+
+module_init(qman_ctrl_init);
+module_exit(qman_ctrl_exit);
+
+#endif /* CONFIG_SYSFS */
diff --git a/drivers/staging/fsl_qbman/qman_debugfs.c b/drivers/staging/fsl_qbman/qman_debugfs.c
new file mode 100644
index 0000000..06e52b1
--- /dev/null
+++ b/drivers/staging/fsl_qbman/qman_debugfs.c
@@ -0,0 +1,1595 @@
+/* Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "qman_private.h"
+
+#define MAX_FQID (0x00ffffff)
+#define QM_FQD_BLOCK_SIZE 64
+#define QM_FQD_AR (0xC10)
+
+static u32 fqid_max;
+static u64 qman_ccsr_start;
+static u64 qman_ccsr_size;
+
+static const char * const state_txt[] = {
+ "Out of Service",
+ "Retired",
+ "Tentatively Scheduled",
+ "Truly Scheduled",
+ "Parked",
+ "Active, Active Held or Held Suspended",
+ "Unknown State 6",
+ "Unknown State 7",
+ NULL,
+};
+
+static const u8 fqd_states[] = {
+ QM_MCR_NP_STATE_OOS, QM_MCR_NP_STATE_RETIRED, QM_MCR_NP_STATE_TEN_SCHED,
+ QM_MCR_NP_STATE_TRU_SCHED, QM_MCR_NP_STATE_PARKED,
+ QM_MCR_NP_STATE_ACTIVE};
+
+struct mask_to_text {
+ u16 mask;
+ const char *txt;
+};
+
+struct mask_filter_s {
+ u16 mask;
+ u8 filter;
+};
+
+static const struct mask_filter_s mask_filter[] = {
+ {QM_FQCTRL_PREFERINCACHE, 0},
+ {QM_FQCTRL_PREFERINCACHE, 1},
+ {QM_FQCTRL_HOLDACTIVE, 0},
+ {QM_FQCTRL_HOLDACTIVE, 1},
+ {QM_FQCTRL_AVOIDBLOCK, 0},
+ {QM_FQCTRL_AVOIDBLOCK, 1},
+ {QM_FQCTRL_FORCESFDR, 0},
+ {QM_FQCTRL_FORCESFDR, 1},
+ {QM_FQCTRL_CPCSTASH, 0},
+ {QM_FQCTRL_CPCSTASH, 1},
+ {QM_FQCTRL_CTXASTASHING, 0},
+ {QM_FQCTRL_CTXASTASHING, 1},
+ {QM_FQCTRL_ORP, 0},
+ {QM_FQCTRL_ORP, 1},
+ {QM_FQCTRL_TDE, 0},
+ {QM_FQCTRL_TDE, 1},
+ {QM_FQCTRL_CGE, 0},
+ {QM_FQCTRL_CGE, 1}
+};
+
+static const struct mask_to_text fq_ctrl_text_list[] = {
+ {
+ .mask = QM_FQCTRL_PREFERINCACHE,
+ .txt = "Prefer in cache",
+ },
+ {
+ .mask = QM_FQCTRL_HOLDACTIVE,
+ .txt = "Hold active in portal",
+ },
+ {
+ .mask = QM_FQCTRL_AVOIDBLOCK,
+ .txt = "Avoid Blocking",
+ },
+ {
+ .mask = QM_FQCTRL_FORCESFDR,
+ .txt = "High-priority SFDRs",
+ },
+ {
+ .mask = QM_FQCTRL_CPCSTASH,
+ .txt = "CPC Stash Enable",
+ },
+ {
+ .mask = QM_FQCTRL_CTXASTASHING,
+ .txt = "Context-A stashing",
+ },
+ {
+ .mask = QM_FQCTRL_ORP,
+ .txt = "ORP Enable",
+ },
+ {
+ .mask = QM_FQCTRL_TDE,
+ .txt = "Tail-Drop Enable",
+ },
+ {
+ .mask = QM_FQCTRL_CGE,
+ .txt = "Congestion Group Enable",
+ },
+ {
+ .mask = 0,
+ .txt = NULL,
+ }
+};
+
+static const char *get_fqd_ctrl_text(u16 mask)
+{
+ int i = 0;
+
+ while (fq_ctrl_text_list[i].txt != NULL) {
+ if (fq_ctrl_text_list[i].mask == mask)
+ return fq_ctrl_text_list[i].txt;
+ i++;
+ }
+ return NULL;
+}
+
+static const struct mask_to_text stashing_text_list[] = {
+ {
+ .mask = QM_STASHING_EXCL_CTX,
+ .txt = "FQ Ctx Stash"
+ },
+ {
+ .mask = QM_STASHING_EXCL_DATA,
+ .txt = "Frame Data Stash",
+ },
+ {
+ .mask = QM_STASHING_EXCL_ANNOTATION,
+ .txt = "Frame Annotation Stash",
+ },
+ {
+ .mask = 0,
+ .txt = NULL,
+ },
+};
+
+static int user_input_convert(const char __user *user_buf, size_t count,
+ unsigned long *val)
+{
+ char buf[12];
+
+ if (count > sizeof(buf) - 1)
+ return -EINVAL;
+ if (copy_from_user(buf, user_buf, count))
+ return -EFAULT;
+ buf[count] = '\0';
+ if (kstrtoul(buf, 0, val))
+ return -EINVAL;
+ return 0;
+}
+
+struct line_buffer_fq {
+ u32 buf[8];
+ u32 buf_cnt;
+ int line_cnt;
+};
+
+static void add_to_line_buffer(struct line_buffer_fq *line_buf, u32 fqid,
+ struct seq_file *file)
+{
+ line_buf->buf[line_buf->buf_cnt] = fqid;
+ line_buf->buf_cnt++;
+ if (line_buf->buf_cnt == 8) {
+ /* Buffer is full, flush it */
+ if (line_buf->line_cnt != 0)
+ seq_puts(file, ",\n");
+ seq_printf(file, "0x%06x,0x%06x,0x%06x,0x%06x,0x%06x,"
+ "0x%06x,0x%06x,0x%06x",
+ line_buf->buf[0], line_buf->buf[1], line_buf->buf[2],
+ line_buf->buf[3], line_buf->buf[4], line_buf->buf[5],
+ line_buf->buf[6], line_buf->buf[7]);
+ line_buf->buf_cnt = 0;
+ line_buf->line_cnt++;
+ }
+}
+
+static void flush_line_buffer(struct line_buffer_fq *line_buf,
+ struct seq_file *file)
+{
+ if (line_buf->buf_cnt) {
+ int y = 0;
+ if (line_buf->line_cnt != 0)
+ seq_puts(file, ",\n");
+ while (y != line_buf->buf_cnt) {
+ if (y+1 == line_buf->buf_cnt)
+ seq_printf(file, "0x%06x", line_buf->buf[y]);
+ else
+ seq_printf(file, "0x%06x,", line_buf->buf[y]);
+ y++;
+ }
+ line_buf->line_cnt++;
+ }
+ if (line_buf->line_cnt)
+ seq_putc(file, '\n');
+}
+
+static struct dentry *dfs_root; /* debugfs root directory */
+
+/*******************************************************************************
+ * Query Frame Queue Non Programmable Fields
+ ******************************************************************************/
+struct query_fq_np_fields_data_s {
+ u32 fqid;
+};
+static struct query_fq_np_fields_data_s query_fq_np_fields_data = {
+ .fqid = 1,
+};
+
+static int query_fq_np_fields_show(struct seq_file *file, void *offset)
+{
+ int ret;
+ struct qm_mcr_queryfq_np np;
+ struct qman_fq fq;
+
+ fq.fqid = query_fq_np_fields_data.fqid;
+ ret = qman_query_fq_np(&fq, &np);
+ if (ret)
+ return ret;
+ /* Print state */
+ seq_printf(file, "Query FQ Non Programmable Fields Result fqid 0x%x\n",
+ fq.fqid);
+ seq_printf(file, " force eligible pending: %s\n",
+ (np.state & QM_MCR_NP_STATE_FE) ? "yes" : "no");
+ seq_printf(file, " retirement pending: %s\n",
+ (np.state & QM_MCR_NP_STATE_R) ? "yes" : "no");
+ seq_printf(file, " state: %s\n",
+ state_txt[np.state & QM_MCR_NP_STATE_MASK]);
+ seq_printf(file, " fq_link: 0x%x\n", np.fqd_link);
+ seq_printf(file, " odp_seq: %u\n", np.odp_seq);
+ seq_printf(file, " orp_nesn: %u\n", np.orp_nesn);
+ seq_printf(file, " orp_ea_hseq: %u\n", np.orp_ea_hseq);
+ seq_printf(file, " orp_ea_tseq: %u\n", np.orp_ea_tseq);
+ seq_printf(file, " orp_ea_hptr: 0x%x\n", np.orp_ea_hptr);
+ seq_printf(file, " orp_ea_tptr: 0x%x\n", np.orp_ea_tptr);
+ seq_printf(file, " pfdr_hptr: 0x%x\n", np.pfdr_hptr);
+ seq_printf(file, " pfdr_tptr: 0x%x\n", np.pfdr_tptr);
+ seq_printf(file, " is: ics_surp contains a %s\n",
+ (np.is) ? "deficit" : "surplus");
+ seq_printf(file, " ics_surp: %u\n", np.ics_surp);
+ seq_printf(file, " byte_cnt: %u\n", np.byte_cnt);
+ seq_printf(file, " frm_cnt: %u\n", np.frm_cnt);
+ seq_printf(file, " ra1_sfdr: 0x%x\n", np.ra1_sfdr);
+ seq_printf(file, " ra2_sfdr: 0x%x\n", np.ra2_sfdr);
+ seq_printf(file, " od1_sfdr: 0x%x\n", np.od1_sfdr);
+ seq_printf(file, " od2_sfdr: 0x%x\n", np.od2_sfdr);
+ seq_printf(file, " od3_sfdr: 0x%x\n", np.od3_sfdr);
+ return 0;
+}
+
+static int query_fq_np_fields_open(struct inode *inode,
+ struct file *file)
+{
+ return single_open(file, query_fq_np_fields_show, NULL);
+}
+
+static ssize_t query_fq_np_fields_write(struct file *f,
+ const char __user *buf, size_t count, loff_t *off)
+{
+ int ret;
+ unsigned long val;
+
+ ret = user_input_convert(buf, count, &val);
+ if (ret)
+ return ret;
+ if (val > MAX_FQID)
+ return -EINVAL;
+ query_fq_np_fields_data.fqid = (u32)val;
+ return count;
+}
+
+static const struct file_operations query_fq_np_fields_fops = {
+ .owner = THIS_MODULE,
+ .open = query_fq_np_fields_open,
+ .read = seq_read,
+ .write = query_fq_np_fields_write,
+ .release = single_release,
+};
+
+/*******************************************************************************
+ * Frame Queue Programmable Fields
+ ******************************************************************************/
+struct query_fq_fields_data_s {
+ u32 fqid;
+};
+
+static struct query_fq_fields_data_s query_fq_fields_data = {
+ .fqid = 1,
+};
+
+static int query_fq_fields_show(struct seq_file *file, void *offset)
+{
+ int ret;
+ struct qm_fqd fqd;
+ struct qman_fq fq;
+ int i = 0;
+
+ memset(&fqd, 0, sizeof(struct qm_fqd));
+ fq.fqid = query_fq_fields_data.fqid;
+ ret = qman_query_fq(&fq, &fqd);
+ if (ret)
+ return ret;
+ seq_printf(file, "Query FQ Programmable Fields Result fqid 0x%x\n",
+ fq.fqid);
+ seq_printf(file, " orprws: %u\n", fqd.orprws);
+ seq_printf(file, " oa: %u\n", fqd.oa);
+ seq_printf(file, " olws: %u\n", fqd.olws);
+
+ seq_printf(file, " cgid: %u\n", fqd.cgid);
+
+ if ((fqd.fq_ctrl & QM_FQCTRL_MASK) == 0)
+ seq_puts(file, " fq_ctrl: None\n");
+ else {
+ i = 0;
+ seq_puts(file, " fq_ctrl:\n");
+ while (fq_ctrl_text_list[i].txt != NULL) {
+ if ((fqd.fq_ctrl & QM_FQCTRL_MASK) &
+ fq_ctrl_text_list[i].mask)
+ seq_printf(file, " %s\n",
+ fq_ctrl_text_list[i].txt);
+ i++;
+ }
+ }
+ seq_printf(file, " dest_channel: %u\n", fqd.dest.channel);
+ seq_printf(file, " dest_wq: %u\n", fqd.dest.wq);
+ seq_printf(file, " ics_cred: %u\n", fqd.ics_cred);
+ seq_printf(file, " td_mant: %u\n", fqd.td.mant);
+ seq_printf(file, " td_exp: %u\n", fqd.td.exp);
+
+ seq_printf(file, " ctx_b: 0x%x\n", fqd.context_b);
+
+ seq_printf(file, " ctx_a: 0x%llx\n", qm_fqd_stashing_get64(&fqd));
+ /* Any stashing configured */
+ if ((fqd.context_a.stashing.exclusive & 0x7) == 0)
+ seq_puts(file, " ctx_a_stash_exclusive: None\n");
+ else {
+ seq_puts(file, " ctx_a_stash_exclusive:\n");
+ i = 0;
+ while (stashing_text_list[i].txt != NULL) {
+ if ((fqd.fq_ctrl & 0x7) & stashing_text_list[i].mask)
+ seq_printf(file, " %s\n",
+ stashing_text_list[i].txt);
+ i++;
+ }
+ }
+ seq_printf(file, " ctx_a_stash_annotation_cl: %u\n",
+ fqd.context_a.stashing.annotation_cl);
+ seq_printf(file, " ctx_a_stash_data_cl: %u\n",
+ fqd.context_a.stashing.data_cl);
+ seq_printf(file, " ctx_a_stash_context_cl: %u\n",
+ fqd.context_a.stashing.context_cl);
+ return 0;
+}
+
+static int query_fq_fields_open(struct inode *inode,
+ struct file *file)
+{
+ return single_open(file, query_fq_fields_show, NULL);
+}
+
+static ssize_t query_fq_fields_write(struct file *f,
+ const char __user *buf, size_t count, loff_t *off)
+{
+ int ret;
+ unsigned long val;
+
+ ret = user_input_convert(buf, count, &val);
+ if (ret)
+ return ret;
+ if (val > MAX_FQID)
+ return -EINVAL;
+ query_fq_fields_data.fqid = (u32)val;
+ return count;
+}
+
+static const struct file_operations query_fq_fields_fops = {
+ .owner = THIS_MODULE,
+ .open = query_fq_fields_open,
+ .read = seq_read,
+ .write = query_fq_fields_write,
+ .release = single_release,
+};
+
+/*******************************************************************************
+ * Query WQ lengths
+ ******************************************************************************/
+struct query_wq_lengths_data_s {
+ union {
+ u16 channel_wq; /* ignores wq (3 lsbits) */
+ struct {
+ u16 id:13; /* qm_channel */
+ u16 __reserved:3;
+ } __packed channel;
+ };
+};
+static struct query_wq_lengths_data_s query_wq_lengths_data;
+static int query_wq_lengths_show(struct seq_file *file, void *offset)
+{
+ int ret;
+ struct qm_mcr_querywq wq;
+ int i;
+
+ memset(&wq, 0, sizeof(struct qm_mcr_querywq));
+ wq.channel.id = query_wq_lengths_data.channel.id;
+ ret = qman_query_wq(0, &wq);
+ if (ret)
+ return ret;
+ seq_printf(file, "Query Result For Channel: 0x%x\n", wq.channel.id);
+ for (i = 0; i < 8; i++)
+ /* mask out upper 4 bits since they are not part of length */
+ seq_printf(file, " wq%d_len : %u\n", i, wq.wq_len[i] & 0x0fff);
+ return 0;
+}
+
+static int query_wq_lengths_open(struct inode *inode,
+ struct file *file)
+{
+ return single_open(file, query_wq_lengths_show, NULL);
+}
+
+static ssize_t query_wq_lengths_write(struct file *f,
+ const char __user *buf, size_t count, loff_t *off)
+{
+ int ret;
+ unsigned long val;
+
+ ret = user_input_convert(buf, count, &val);
+ if (ret)
+ return ret;
+ if (val > 0xfff8)
+ return -EINVAL;
+ query_wq_lengths_data.channel.id = (u16)val;
+ return count;
+}
+
+static const struct file_operations query_wq_lengths_fops = {
+ .owner = THIS_MODULE,
+ .open = query_wq_lengths_open,
+ .read = seq_read,
+ .write = query_wq_lengths_write,
+ .release = single_release,
+};
+
+/*******************************************************************************
+ * Query CGR
+ ******************************************************************************/
+struct query_cgr_s {
+ u8 cgid;
+};
+static struct query_cgr_s query_cgr_data;
+
+static int query_cgr_show(struct seq_file *file, void *offset)
+{
+ int ret;
+ struct qm_mcr_querycgr cgrd;
+ struct qman_cgr cgr;
+ int i, j;
+ u32 mask;
+
+ memset(&cgr, 0, sizeof(cgr));
+ memset(&cgrd, 0, sizeof(cgrd));
+ cgr.cgrid = query_cgr_data.cgid;
+ ret = qman_query_cgr(&cgr, &cgrd);
+ if (ret)
+ return ret;
+ seq_printf(file, "Query CGR id 0x%x\n", cgr.cgrid);
+ seq_printf(file, " wr_parm_g MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n",
+ cgrd.cgr.wr_parm_g.MA, cgrd.cgr.wr_parm_g.Mn,
+ cgrd.cgr.wr_parm_g.SA, cgrd.cgr.wr_parm_g.Sn,
+ cgrd.cgr.wr_parm_g.Pn);
+
+ seq_printf(file, " wr_parm_y MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n",
+ cgrd.cgr.wr_parm_y.MA, cgrd.cgr.wr_parm_y.Mn,
+ cgrd.cgr.wr_parm_y.SA, cgrd.cgr.wr_parm_y.Sn,
+ cgrd.cgr.wr_parm_y.Pn);
+
+ seq_printf(file, " wr_parm_r MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n",
+ cgrd.cgr.wr_parm_r.MA, cgrd.cgr.wr_parm_r.Mn,
+ cgrd.cgr.wr_parm_r.SA, cgrd.cgr.wr_parm_r.Sn,
+ cgrd.cgr.wr_parm_r.Pn);
+
+ seq_printf(file, " wr_en_g: %u, wr_en_y: %u, we_en_r: %u\n",
+ cgrd.cgr.wr_en_g, cgrd.cgr.wr_en_y, cgrd.cgr.wr_en_r);
+
+ seq_printf(file, " cscn_en: %u\n", cgrd.cgr.cscn_en);
+ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30) {
+ seq_puts(file, " cscn_targ_dcp:\n");
+ mask = 0x80000000;
+ for (i = 0; i < 32; i++) {
+ if (cgrd.cgr.cscn_targ & mask)
+ seq_printf(file, " send CSCN to dcp %u\n",
+ (31 - i));
+ mask >>= 1;
+ }
+
+ seq_puts(file, " cscn_targ_swp:\n");
+ for (i = 0; i < 4; i++) {
+ mask = 0x80000000;
+ for (j = 0; j < 32; j++) {
+ if (cgrd.cscn_targ_swp[i] & mask)
+ seq_printf(file, " send CSCN to swp"
+ " %u\n", (127 - (i * 32) - j));
+ mask >>= 1;
+ }
+ }
+ } else {
+ seq_printf(file, " cscn_targ: %u\n", cgrd.cgr.cscn_targ);
+ }
+ seq_printf(file, " cstd_en: %u\n", cgrd.cgr.cstd_en);
+ seq_printf(file, " cs: %u\n", cgrd.cgr.cs);
+
+ seq_printf(file, " cs_thresh_TA: %u, cs_thresh_Tn: %u\n",
+ cgrd.cgr.cs_thres.TA, cgrd.cgr.cs_thres.Tn);
+
+ seq_printf(file, " mode: %s\n",
+ (cgrd.cgr.mode & QMAN_CGR_MODE_FRAME) ?
+ "frame count" : "byte count");
+ seq_printf(file, " i_bcnt: %llu\n", qm_mcr_querycgr_i_get64(&cgrd));
+ seq_printf(file, " a_bcnt: %llu\n", qm_mcr_querycgr_a_get64(&cgrd));
+
+ return 0;
+}
+
+static int query_cgr_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, query_cgr_show, NULL);
+}
+
+static ssize_t query_cgr_write(struct file *f, const char __user *buf,
+ size_t count, loff_t *off)
+{
+ int ret;
+ unsigned long val;
+
+ ret = user_input_convert(buf, count, &val);
+ if (ret)
+ return ret;
+ if (val > 0xff)
+ return -EINVAL;
+ query_cgr_data.cgid = (u8)val;
+ return count;
+}
+
+static const struct file_operations query_cgr_fops = {
+ .owner = THIS_MODULE,
+ .open = query_cgr_open,
+ .read = seq_read,
+ .write = query_cgr_write,
+ .release = single_release,
+};
+
+/*******************************************************************************
+ * Test Write CGR
+ ******************************************************************************/
+struct test_write_cgr_s {
+ u64 i_bcnt;
+ u8 cgid;
+};
+static struct test_write_cgr_s test_write_cgr_data;
+
+static int testwrite_cgr_show(struct seq_file *file, void *offset)
+{
+ int ret;
+ struct qm_mcr_cgrtestwrite result;
+ struct qman_cgr cgr;
+ u64 i_bcnt;
+
+ memset(&cgr, 0, sizeof(struct qman_cgr));
+ memset(&result, 0, sizeof(struct qm_mcr_cgrtestwrite));
+ cgr.cgrid = test_write_cgr_data.cgid;
+ i_bcnt = test_write_cgr_data.i_bcnt;
+ ret = qman_testwrite_cgr(&cgr, i_bcnt, &result);
+ if (ret)
+ return ret;
+ seq_printf(file, "CGR Test Write CGR id 0x%x\n", cgr.cgrid);
+ seq_printf(file, " wr_parm_g MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n",
+ result.cgr.wr_parm_g.MA, result.cgr.wr_parm_g.Mn,
+ result.cgr.wr_parm_g.SA, result.cgr.wr_parm_g.Sn,
+ result.cgr.wr_parm_g.Pn);
+ seq_printf(file, " wr_parm_y MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n",
+ result.cgr.wr_parm_y.MA, result.cgr.wr_parm_y.Mn,
+ result.cgr.wr_parm_y.SA, result.cgr.wr_parm_y.Sn,
+ result.cgr.wr_parm_y.Pn);
+ seq_printf(file, " wr_parm_r MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n",
+ result.cgr.wr_parm_r.MA, result.cgr.wr_parm_r.Mn,
+ result.cgr.wr_parm_r.SA, result.cgr.wr_parm_r.Sn,
+ result.cgr.wr_parm_r.Pn);
+ seq_printf(file, " wr_en_g: %u, wr_en_y: %u, we_en_r: %u\n",
+ result.cgr.wr_en_g, result.cgr.wr_en_y, result.cgr.wr_en_r);
+ seq_printf(file, " cscn_en: %u\n", result.cgr.cscn_en);
+ seq_printf(file, " cscn_targ: %u\n", result.cgr.cscn_targ);
+ seq_printf(file, " cstd_en: %u\n", result.cgr.cstd_en);
+ seq_printf(file, " cs: %u\n", result.cgr.cs);
+ seq_printf(file, " cs_thresh_TA: %u, cs_thresh_Tn: %u\n",
+ result.cgr.cs_thres.TA, result.cgr.cs_thres.Tn);
+
+ /* Add Mode for Si 2 */
+ seq_printf(file, " mode: %s\n",
+ (result.cgr.mode & QMAN_CGR_MODE_FRAME) ?
+ "frame count" : "byte count");
+
+ seq_printf(file, " i_bcnt: %llu\n",
+ qm_mcr_cgrtestwrite_i_get64(&result));
+ seq_printf(file, " a_bcnt: %llu\n",
+ qm_mcr_cgrtestwrite_a_get64(&result));
+ seq_printf(file, " wr_prob_g: %u\n", result.wr_prob_g);
+ seq_printf(file, " wr_prob_y: %u\n", result.wr_prob_y);
+ seq_printf(file, " wr_prob_r: %u\n", result.wr_prob_r);
+ return 0;
+}
+
+static int testwrite_cgr_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, testwrite_cgr_show, NULL);
+}
+
+static const struct file_operations testwrite_cgr_fops = {
+ .owner = THIS_MODULE,
+ .open = testwrite_cgr_open,
+ .read = seq_read,
+ .release = single_release,
+};
+
+
+static int testwrite_cgr_ibcnt_show(struct seq_file *file, void *offset)
+{
+ seq_printf(file, "i_bcnt: %llu\n", test_write_cgr_data.i_bcnt);
+ return 0;
+}
+static int testwrite_cgr_ibcnt_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, testwrite_cgr_ibcnt_show, NULL);
+}
+
+static ssize_t testwrite_cgr_ibcnt_write(struct file *f, const char __user *buf,
+ size_t count, loff_t *off)
+{
+ int ret;
+ unsigned long val;
+
+ ret = user_input_convert(buf, count, &val);
+ if (ret)
+ return ret;
+ test_write_cgr_data.i_bcnt = val;
+ return count;
+}
+
+static const struct file_operations teswrite_cgr_ibcnt_fops = {
+ .owner = THIS_MODULE,
+ .open = testwrite_cgr_ibcnt_open,
+ .read = seq_read,
+ .write = testwrite_cgr_ibcnt_write,
+ .release = single_release,
+};
+
+static int testwrite_cgr_cgrid_show(struct seq_file *file, void *offset)
+{
+ seq_printf(file, "cgrid: %u\n", (u32)test_write_cgr_data.cgid);
+ return 0;
+}
+static int testwrite_cgr_cgrid_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, testwrite_cgr_cgrid_show, NULL);
+}
+
+static ssize_t testwrite_cgr_cgrid_write(struct file *f, const char __user *buf,
+ size_t count, loff_t *off)
+{
+ int ret;
+ unsigned long val;
+
+ ret = user_input_convert(buf, count, &val);
+ if (ret)
+ return ret;
+ if (val > 0xff)
+ return -EINVAL;
+ test_write_cgr_data.cgid = (u8)val;
+ return count;
+}
+
+static const struct file_operations teswrite_cgr_cgrid_fops = {
+ .owner = THIS_MODULE,
+ .open = testwrite_cgr_cgrid_open,
+ .read = seq_read,
+ .write = testwrite_cgr_cgrid_write,
+ .release = single_release,
+};
+
+/*******************************************************************************
+ * Query Congestion State
+ ******************************************************************************/
+static int query_congestion_show(struct seq_file *file, void *offset)
+{
+ int ret;
+ struct qm_mcr_querycongestion cs;
+ int i, j, in_cong = 0;
+ u32 mask;
+
+ memset(&cs, 0, sizeof(struct qm_mcr_querycongestion));
+ ret = qman_query_congestion(&cs);
+ if (ret)
+ return ret;
+ seq_puts(file, "Query Congestion Result\n");
+ for (i = 0; i < 8; i++) {
+ mask = 0x80000000;
+ for (j = 0; j < 32; j++) {
+ if (cs.state.__state[i] & mask) {
+ in_cong = 1;
+ seq_printf(file, " cg %u: %s\n", (i*32)+j,
+ "in congestion");
+ }
+ mask >>= 1;
+ }
+ }
+ if (!in_cong)
+ seq_puts(file, " All congestion groups not congested.\n");
+ return 0;
+}
+
+static int query_congestion_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, query_congestion_show, NULL);
+}
+
+static const struct file_operations query_congestion_fops = {
+ .owner = THIS_MODULE,
+ .open = query_congestion_open,
+ .read = seq_read,
+ .release = single_release,
+};
+
+/*******************************************************************************
+ * Query CCGR
+ ******************************************************************************/
+struct query_ccgr_s {
+ u32 ccgid;
+};
+static struct query_ccgr_s query_ccgr_data;
+
+static int query_ccgr_show(struct seq_file *file, void *offset)
+{
+ int ret;
+ struct qm_mcr_ceetm_ccgr_query ccgr_query;
+ struct qm_mcc_ceetm_ccgr_query query_opts;
+ int i, j;
+ u32 mask;
+
+ memset(&ccgr_query, 0, sizeof(struct qm_mcr_ceetm_ccgr_query));
+ memset(&query_opts, 0, sizeof(struct qm_mcc_ceetm_ccgr_query));
+
+ if ((qman_ip_rev & 0xFF00) < QMAN_REV30)
+ return -EINVAL;
+
+ seq_printf(file, "Query CCGID %x\n", query_ccgr_data.ccgid);
+ query_opts.dcpid = ((query_ccgr_data.ccgid & 0xFF000000) >> 24);
+ query_opts.ccgrid = query_ccgr_data.ccgid & 0x000001FF;
+ ret = qman_ceetm_query_ccgr(&query_opts, &ccgr_query);
+ if (ret)
+ return ret;
+ seq_printf(file, "Query CCGR id %x in DCP %d\n", query_opts.ccgrid,
+ query_opts.dcpid);
+ seq_printf(file, " wr_parm_g MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n",
+ ccgr_query.cm_query.wr_parm_g.MA,
+ ccgr_query.cm_query.wr_parm_g.Mn,
+ ccgr_query.cm_query.wr_parm_g.SA,
+ ccgr_query.cm_query.wr_parm_g.Sn,
+ ccgr_query.cm_query.wr_parm_g.Pn);
+
+ seq_printf(file, " wr_parm_y MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n",
+ ccgr_query.cm_query.wr_parm_y.MA,
+ ccgr_query.cm_query.wr_parm_y.Mn,
+ ccgr_query.cm_query.wr_parm_y.SA,
+ ccgr_query.cm_query.wr_parm_y.Sn,
+ ccgr_query.cm_query.wr_parm_y.Pn);
+
+ seq_printf(file, " wr_parm_r MA: %u, Mn: %u, SA: %u, Sn: %u, Pn: %u\n",
+ ccgr_query.cm_query.wr_parm_r.MA,
+ ccgr_query.cm_query.wr_parm_r.Mn,
+ ccgr_query.cm_query.wr_parm_r.SA,
+ ccgr_query.cm_query.wr_parm_r.Sn,
+ ccgr_query.cm_query.wr_parm_r.Pn);
+
+ seq_printf(file, " wr_en_g: %u, wr_en_y: %u, we_en_r: %u\n",
+ ((ccgr_query.cm_query.ctl >> 6) & 0x1),
+ ((ccgr_query.cm_query.ctl >> 5 & 0x1)),
+ ((ccgr_query.cm_query.ctl >> 4) & 0x1));
+
+ seq_printf(file, " cscn_en: %u\n", ((ccgr_query.cm_query.ctl >> 1) &
+ 0x1));
+ seq_puts(file, " cscn_targ_dcp:\n");
+ mask = 0x80000000;
+ for (i = 0; i < 32; i++) {
+ if (ccgr_query.cm_query.cscn_targ_dcp & mask)
+ seq_printf(file, " send CSCN to dcp %u\n", (31 - i));
+ mask >>= 1;
+ }
+
+ seq_puts(file, " cscn_targ_swp:\n");
+ for (i = 0; i < 4; i++) {
+ mask = 0x80000000;
+ for (j = 0; j < 32; j++) {
+ if (ccgr_query.cm_query.cscn_targ_swp[i] & mask)
+ seq_printf(file, " send CSCN to swp"
+ "%u\n", (127 - (i * 32) - j));
+ mask >>= 1;
+ }
+ }
+
+ seq_printf(file, " td_en: %u\n", (ccgr_query.cm_query.ctl >> 3));
+
+ seq_printf(file, " cs_thresh_in_TA: %u, cs_thresh_in_Tn: %u\n",
+ ccgr_query.cm_query.cs_thres.TA,
+ ccgr_query.cm_query.cs_thres.Tn);
+
+ seq_printf(file, " cs_thresh_out_TA: %u, cs_thresh_out_Tn: %u\n",
+ ccgr_query.cm_query.cs_thres_x.TA,
+ ccgr_query.cm_query.cs_thres_x.Tn);
+
+ seq_printf(file, " td_thresh_TA: %u, td_thresh_Tn: %u\n",
+ ccgr_query.cm_query.td_thres.TA,
+ ccgr_query.cm_query.td_thres.Tn);
+
+ seq_printf(file, " mode: %s\n",
+ ((ccgr_query.cm_query.ctl & 0x1) &
+ QMAN_CGR_MODE_FRAME) ?
+ "frame count" : "byte count");
+ seq_printf(file, " i_cnt: %llu\n", (u64)ccgr_query.cm_query.i_cnt);
+ seq_printf(file, " a_cnt: %llu\n", (u64)ccgr_query.cm_query.a_cnt);
+
+ return 0;
+}
+
+static int query_ccgr_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, query_ccgr_show, NULL);
+}
+
+static ssize_t query_ccgr_write(struct file *f, const char __user *buf,
+ size_t count, loff_t *off)
+{
+ int ret;
+ unsigned long val;
+
+ ret = user_input_convert(buf, count, &val);
+ if (ret)
+ return ret;
+ query_ccgr_data.ccgid = val;
+ return count;
+}
+
+static const struct file_operations query_ccgr_fops = {
+ .owner = THIS_MODULE,
+ .open = query_ccgr_open,
+ .read = seq_read,
+ .write = query_ccgr_write,
+ .release = single_release,
+};
+/*******************************************************************************
+ * QMan register
+ ******************************************************************************/
+struct qman_register_s {
+ u32 val;
+};
+static struct qman_register_s qman_register_data;
+
+static void init_ccsrmempeek(void)
+{
+ struct device_node *dn;
+ const u32 *regaddr_p;
+
+ dn = of_find_compatible_node(NULL, NULL, "fsl,qman");
+ if (!dn) {
+ pr_info("No fsl,qman node\n");
+ return;
+ }
+ regaddr_p = of_get_address(dn, 0, &qman_ccsr_size, NULL);
+ if (!regaddr_p) {
+ of_node_put(dn);
+ return;
+ }
+ qman_ccsr_start = of_translate_address(dn, regaddr_p);
+ of_node_put(dn);
+}
+/* This function provides access to QMan ccsr memory map */
+static int qman_ccsrmempeek(u32 *val, u32 offset)
+{
+ void __iomem *addr;
+ u64 phys_addr;
+
+ if (!qman_ccsr_start)
+ return -EINVAL;
+
+ if (offset > (qman_ccsr_size - sizeof(u32)))
+ return -EINVAL;
+
+ phys_addr = qman_ccsr_start + offset;
+ addr = ioremap(phys_addr, sizeof(u32));
+ if (!addr) {
+ pr_err("ccsrmempeek, ioremap failed\n");
+ return -EINVAL;
+ }
+ *val = in_be32(addr);
+ iounmap(addr);
+ return 0;
+}
+
+static int qman_ccsrmempeek_show(struct seq_file *file, void *offset)
+{
+ u32 b;
+
+ qman_ccsrmempeek(&b, qman_register_data.val);
+ seq_printf(file, "QMan register offset = 0x%x\n",
+ qman_register_data.val);
+ seq_printf(file, "value = 0x%08x\n", b);
+
+ return 0;
+}
+
+static int qman_ccsrmempeek_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, qman_ccsrmempeek_show, NULL);
+}
+
+static ssize_t qman_ccsrmempeek_write(struct file *f, const char __user *buf,
+ size_t count, loff_t *off)
+{
+ int ret;
+ unsigned long val;
+
+ ret = user_input_convert(buf, count, &val);
+ if (ret)
+ return ret;
+ /* multiple of 4 */
+ if (val > (qman_ccsr_size - sizeof(u32))) {
+ pr_info("Input 0x%lx > 0x%llx\n",
+ val, (qman_ccsr_size - sizeof(u32)));
+ return -EINVAL;
+ }
+ if (val & 0x3) {
+ pr_info("Input 0x%lx not multiple of 4\n", val);
+ return -EINVAL;
+ }
+ qman_register_data.val = val;
+ return count;
+}
+
+static const struct file_operations qman_ccsrmempeek_fops = {
+ .owner = THIS_MODULE,
+ .open = qman_ccsrmempeek_open,
+ .read = seq_read,
+ .write = qman_ccsrmempeek_write,
+};
+
+/*******************************************************************************
+ * QMan state
+ ******************************************************************************/
+static int qman_fqd_state_show(struct seq_file *file, void *offset)
+{
+ struct qm_mcr_queryfq_np np;
+ struct qman_fq fq;
+ struct line_buffer_fq line_buf;
+ int ret, i;
+ u8 *state = file->private;
+ u32 qm_fq_state_cnt[ARRAY_SIZE(fqd_states)];
+
+ memset(qm_fq_state_cnt, 0, sizeof(qm_fq_state_cnt));
+ memset(&line_buf, 0, sizeof(line_buf));
+
+ seq_printf(file, "List of fq ids in state: %s\n", state_txt[*state]);
+
+ for (i = 1; i < fqid_max; i++) {
+ fq.fqid = i;
+ ret = qman_query_fq_np(&fq, &np);
+ if (ret)
+ return ret;
+ if (*state == (np.state & QM_MCR_NP_STATE_MASK))
+ add_to_line_buffer(&line_buf, fq.fqid, file);
+ /* Keep a summary count of all states */
+ if ((np.state & QM_MCR_NP_STATE_MASK) < ARRAY_SIZE(fqd_states))
+ qm_fq_state_cnt[(np.state & QM_MCR_NP_STATE_MASK)]++;
+ }
+ flush_line_buffer(&line_buf, file);
+
+ for (i = 0; i < ARRAY_SIZE(fqd_states); i++) {
+ seq_printf(file, "%s count = %u\n", state_txt[i],
+ qm_fq_state_cnt[i]);
+ }
+ return 0;
+}
+
+static int qman_fqd_state_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, qman_fqd_state_show, inode->i_private);
+}
+
+static const struct file_operations qman_fqd_state_fops = {
+ .owner = THIS_MODULE,
+ .open = qman_fqd_state_open,
+ .read = seq_read,
+};
+
+static int qman_fqd_ctrl_show(struct seq_file *file, void *offset)
+{
+ struct qm_fqd fqd;
+ struct qman_fq fq;
+ u32 fq_en_cnt = 0, fq_di_cnt = 0;
+ int ret, i;
+ struct mask_filter_s *data = file->private;
+ const char *ctrl_txt = get_fqd_ctrl_text(data->mask);
+ struct line_buffer_fq line_buf;
+
+ memset(&line_buf, 0, sizeof(line_buf));
+ seq_printf(file, "List of fq ids with: %s :%s\n",
+ ctrl_txt, (data->filter) ? "enabled" : "disabled");
+ for (i = 1; i < fqid_max; i++) {
+ fq.fqid = i;
+ memset(&fqd, 0, sizeof(struct qm_fqd));
+ ret = qman_query_fq(&fq, &fqd);
+ if (ret)
+ return ret;
+ if (data->filter) {
+ if (fqd.fq_ctrl & data->mask)
+ add_to_line_buffer(&line_buf, fq.fqid, file);
+ } else {
+ if (!(fqd.fq_ctrl & data->mask))
+ add_to_line_buffer(&line_buf, fq.fqid, file);
+ }
+ if (fqd.fq_ctrl & data->mask)
+ fq_en_cnt++;
+ else
+ fq_di_cnt++;
+ }
+ flush_line_buffer(&line_buf, file);
+
+ seq_printf(file, "Total FQD with: %s : enabled = %u\n",
+ ctrl_txt, fq_en_cnt);
+ seq_printf(file, "Total FQD with: %s : disabled = %u\n",
+ ctrl_txt, fq_di_cnt);
+ return 0;
+}
+
+/*******************************************************************************
+ * QMan ctrl CGE, TDE, ORP, CTX, CPC, SFDR, BLOCK, HOLD, CACHE
+ ******************************************************************************/
+static int qman_fqd_ctrl_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, qman_fqd_ctrl_show, inode->i_private);
+}
+
+static const struct file_operations qman_fqd_ctrl_fops = {
+ .owner = THIS_MODULE,
+ .open = qman_fqd_ctrl_open,
+ .read = seq_read,
+};
+
+/*******************************************************************************
+ * QMan ctrl summary
+ ******************************************************************************/
+/*******************************************************************************
+ * QMan summary state
+ ******************************************************************************/
+static int qman_fqd_non_prog_summary_show(struct seq_file *file, void *offset)
+{
+ struct qm_mcr_queryfq_np np;
+ struct qman_fq fq;
+ int ret, i;
+ u32 qm_fq_state_cnt[ARRAY_SIZE(fqd_states)];
+
+ memset(qm_fq_state_cnt, 0, sizeof(qm_fq_state_cnt));
+
+ for (i = 1; i < fqid_max; i++) {
+ fq.fqid = i;
+ ret = qman_query_fq_np(&fq, &np);
+ if (ret)
+ return ret;
+ /* Keep a summary count of all states */
+ if ((np.state & QM_MCR_NP_STATE_MASK) < ARRAY_SIZE(fqd_states))
+ qm_fq_state_cnt[(np.state & QM_MCR_NP_STATE_MASK)]++;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(fqd_states); i++) {
+ seq_printf(file, "%s count = %u\n", state_txt[i],
+ qm_fq_state_cnt[i]);
+ }
+ return 0;
+}
+
+static int qman_fqd_prog_summary_show(struct seq_file *file, void *offset)
+{
+ struct qm_fqd fqd;
+ struct qman_fq fq;
+ int ret, i , j;
+ u32 qm_prog_cnt[ARRAY_SIZE(mask_filter)/2];
+
+ memset(qm_prog_cnt, 0, sizeof(qm_prog_cnt));
+
+ for (i = 1; i < fqid_max; i++) {
+ memset(&fqd, 0, sizeof(struct qm_fqd));
+ fq.fqid = i;
+ ret = qman_query_fq(&fq, &fqd);
+ if (ret)
+ return ret;
+ /* Keep a summary count of all states */
+ for (j = 0; j < ARRAY_SIZE(mask_filter); j += 2)
+ if ((fqd.fq_ctrl & QM_FQCTRL_MASK) &
+ mask_filter[j].mask)
+ qm_prog_cnt[j/2]++;
+ }
+ for (i = 0; i < ARRAY_SIZE(mask_filter) / 2; i++) {
+ seq_printf(file, "%s count = %u\n",
+ get_fqd_ctrl_text(mask_filter[i*2].mask),
+ qm_prog_cnt[i]);
+ }
+ return 0;
+}
+
+static int qman_fqd_summary_show(struct seq_file *file, void *offset)
+{
+ int ret;
+
+ /* Display summary of non programmable fields */
+ ret = qman_fqd_non_prog_summary_show(file, offset);
+ if (ret)
+ return ret;
+ seq_puts(file, "-----------------------------------------\n");
+ /* Display programmable fields */
+ ret = qman_fqd_prog_summary_show(file, offset);
+ if (ret)
+ return ret;
+ return 0;
+}
+
+static int qman_fqd_summary_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, qman_fqd_summary_show, NULL);
+}
+
+static const struct file_operations qman_fqd_summary_fops = {
+ .owner = THIS_MODULE,
+ .open = qman_fqd_summary_open,
+ .read = seq_read,
+};
+
+/*******************************************************************************
+ * QMan destination work queue
+ ******************************************************************************/
+struct qman_dest_wq_s {
+ u16 wq_id;
+};
+static struct qman_dest_wq_s qman_dest_wq_data = {
+ .wq_id = 0,
+};
+
+static int qman_fqd_dest_wq_show(struct seq_file *file, void *offset)
+{
+ struct qm_fqd fqd;
+ struct qman_fq fq;
+ int ret, i;
+ u16 *wq, wq_id = qman_dest_wq_data.wq_id;
+ struct line_buffer_fq line_buf;
+
+ memset(&line_buf, 0, sizeof(line_buf));
+ /* use vmalloc : need to allocate large memory region and don't
+ * require the memory to be physically contiguous. */
+ wq = vzalloc(sizeof(u16) * (0xFFFF+1));
+ if (!wq)
+ return -ENOMEM;
+
+ seq_printf(file, "List of fq ids with destination work queue id"
+ " = 0x%x\n", wq_id);
+
+ for (i = 1; i < fqid_max; i++) {
+ fq.fqid = i;
+ memset(&fqd, 0, sizeof(struct qm_fqd));
+ ret = qman_query_fq(&fq, &fqd);
+ if (ret) {
+ vfree(wq);
+ return ret;
+ }
+ if (wq_id == fqd.dest_wq)
+ add_to_line_buffer(&line_buf, fq.fqid, file);
+ wq[fqd.dest_wq]++;
+ }
+ flush_line_buffer(&line_buf, file);
+
+ seq_puts(file, "Summary of all FQD destination work queue values\n");
+ for (i = 0; i < 0xFFFF; i++) {
+ if (wq[i])
+ seq_printf(file, "Channel: 0x%x WQ: 0x%x WQ_ID: 0x%x, "
+ "count = %u\n", i >> 3, i & 0x3, i, wq[i]);
+ }
+ vfree(wq);
+ return 0;
+}
+
+static ssize_t qman_fqd_dest_wq_write(struct file *f, const char __user *buf,
+ size_t count, loff_t *off)
+{
+ int ret;
+ unsigned long val;
+
+ ret = user_input_convert(buf, count, &val);
+ if (ret)
+ return ret;
+ if (val > 0xFFFF)
+ return -EINVAL;
+ qman_dest_wq_data.wq_id = val;
+ return count;
+}
+
+static int qman_fqd_dest_wq_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, qman_fqd_dest_wq_show, NULL);
+}
+
+static const struct file_operations qman_fqd_dest_wq_fops = {
+ .owner = THIS_MODULE,
+ .open = qman_fqd_dest_wq_open,
+ .read = seq_read,
+ .write = qman_fqd_dest_wq_write,
+};
+
+/*******************************************************************************
+ * QMan Intra-Class Scheduling Credit
+ ******************************************************************************/
+static int qman_fqd_cred_show(struct seq_file *file, void *offset)
+{
+ struct qm_fqd fqd;
+ struct qman_fq fq;
+ int ret, i;
+ u32 fq_cnt = 0;
+ struct line_buffer_fq line_buf;
+
+ memset(&line_buf, 0, sizeof(line_buf));
+ seq_puts(file, "List of fq ids with Intra-Class Scheduling Credit > 0"
+ "\n");
+
+ for (i = 1; i < fqid_max; i++) {
+ fq.fqid = i;
+ memset(&fqd, 0, sizeof(struct qm_fqd));
+ ret = qman_query_fq(&fq, &fqd);
+ if (ret)
+ return ret;
+ if (fqd.ics_cred > 0) {
+ add_to_line_buffer(&line_buf, fq.fqid, file);
+ fq_cnt++;
+ }
+ }
+ flush_line_buffer(&line_buf, file);
+
+ seq_printf(file, "Total FQD with ics_cred > 0 = %d\n", fq_cnt);
+ return 0;
+}
+
+static int qman_fqd_cred_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, qman_fqd_cred_show, NULL);
+}
+
+static const struct file_operations qman_fqd_cred_fops = {
+ .owner = THIS_MODULE,
+ .open = qman_fqd_cred_open,
+ .read = seq_read,
+};
+
+/*******************************************************************************
+ * Class Queue Fields
+ ******************************************************************************/
+struct query_cq_fields_data_s {
+ u32 cqid;
+};
+
+static struct query_cq_fields_data_s query_cq_fields_data = {
+ .cqid = 1,
+};
+
+static int query_cq_fields_show(struct seq_file *file, void *offset)
+{
+ int ret;
+ struct qm_mcr_ceetm_cq_query query_result;
+ unsigned int cqid;
+ unsigned int portal;
+
+ if ((qman_ip_rev & 0xFF00) < QMAN_REV30)
+ return -EINVAL;
+
+ cqid = query_cq_fields_data.cqid & 0x00FFFFFF;
+ portal = query_cq_fields_data.cqid >> 24;
+ if (portal > qm_dc_portal_fman1)
+ return -EINVAL;
+
+ ret = qman_ceetm_query_cq(cqid, portal, &query_result);
+ if (ret)
+ return ret;
+ seq_printf(file, "Query CQ Fields Result cqid 0x%x on DCP %d\n",
+ cqid, portal);
+ seq_printf(file, " ccgid: %u\n", query_result.ccgid);
+ seq_printf(file, " state: %u\n", query_result.state);
+ seq_printf(file, " pfdr_hptr: %u\n", query_result.pfdr_hptr);
+ seq_printf(file, " pfdr_tptr: %u\n", query_result.pfdr_tptr);
+ seq_printf(file, " od1_xsfdr: %u\n", query_result.od1_xsfdr);
+ seq_printf(file, " od2_xsfdr: %u\n", query_result.od2_xsfdr);
+ seq_printf(file, " od3_xsfdr: %u\n", query_result.od3_xsfdr);
+ seq_printf(file, " od4_xsfdr: %u\n", query_result.od4_xsfdr);
+ seq_printf(file, " od5_xsfdr: %u\n", query_result.od5_xsfdr);
+ seq_printf(file, " od6_xsfdr: %u\n", query_result.od6_xsfdr);
+ seq_printf(file, " ra1_xsfdr: %u\n", query_result.ra1_xsfdr);
+ seq_printf(file, " ra2_xsfdr: %u\n", query_result.ra2_xsfdr);
+ seq_printf(file, " frame_count: %u\n", query_result.frm_cnt);
+
+ return 0;
+}
+
+static int query_cq_fields_open(struct inode *inode,
+ struct file *file)
+{
+ return single_open(file, query_cq_fields_show, NULL);
+}
+
+static ssize_t query_cq_fields_write(struct file *f,
+ const char __user *buf, size_t count, loff_t *off)
+{
+ int ret;
+ unsigned long val;
+
+ ret = user_input_convert(buf, count, &val);
+ if (ret)
+ return ret;
+ query_cq_fields_data.cqid = (u32)val;
+ return count;
+}
+
+static const struct file_operations query_cq_fields_fops = {
+ .owner = THIS_MODULE,
+ .open = query_cq_fields_open,
+ .read = seq_read,
+ .write = query_cq_fields_write,
+ .release = single_release,
+};
+
+/*******************************************************************************
+ * READ CEETM_XSFDR_IN_USE
+ ******************************************************************************/
+struct query_ceetm_xsfdr_data_s {
+ enum qm_dc_portal dcp_portal;
+};
+
+static struct query_ceetm_xsfdr_data_s query_ceetm_xsfdr_data;
+
+static int query_ceetm_xsfdr_show(struct seq_file *file, void *offset)
+{
+ int ret;
+ unsigned int xsfdr_in_use;
+ enum qm_dc_portal portal;
+
+
+ if (qman_ip_rev < QMAN_REV31)
+ return -EINVAL;
+
+ portal = query_ceetm_xsfdr_data.dcp_portal;
+ ret = qman_ceetm_get_xsfdr(portal, &xsfdr_in_use);
+ if (ret) {
+ seq_printf(file, "Read CEETM_XSFDR_IN_USE on DCP %d failed\n",
+ portal);
+ return ret;
+ }
+
+ seq_printf(file, "DCP%d: CEETM_XSFDR_IN_USE number is %u\n", portal,
+ (xsfdr_in_use & 0x1FFF));
+ return 0;
+}
+
+static int query_ceetm_xsfdr_open(struct inode *inode,
+ struct file *file)
+{
+ return single_open(file, query_ceetm_xsfdr_show, NULL);
+}
+
+static ssize_t query_ceetm_xsfdr_write(struct file *f,
+ const char __user *buf, size_t count, loff_t *off)
+{
+ int ret;
+ unsigned long val;
+
+ ret = user_input_convert(buf, count, &val);
+ if (ret)
+ return ret;
+ if (val > qm_dc_portal_fman1)
+ return -EINVAL;
+ query_ceetm_xsfdr_data.dcp_portal = (u32)val;
+ return count;
+}
+
+static const struct file_operations query_ceetm_xsfdr_fops = {
+ .owner = THIS_MODULE,
+ .open = query_ceetm_xsfdr_open,
+ .read = seq_read,
+ .write = query_ceetm_xsfdr_write,
+ .release = single_release,
+};
+
+/* helper macros used in qman_debugfs_module_init */
+#define QMAN_DBGFS_ENTRY(name, mode, parent, data, fops) \
+ do { \
+ d = debugfs_create_file(name, \
+ mode, parent, \
+ data, \
+ fops); \
+ if (d == NULL) { \
+ ret = -ENOMEM; \
+ goto _return; \
+ } \
+ } while (0)
+
+/* dfs_root as parent */
+#define QMAN_DBGFS_ENTRY_ROOT(name, mode, data, fops) \
+ QMAN_DBGFS_ENTRY(name, mode, dfs_root, data, fops)
+
+/* fqd_root as parent */
+#define QMAN_DBGFS_ENTRY_FQDROOT(name, mode, data, fops) \
+ QMAN_DBGFS_ENTRY(name, mode, fqd_root, data, fops)
+
+/* fqd state */
+#define QMAN_DBGFS_ENTRY_FQDSTATE(name, index) \
+ QMAN_DBGFS_ENTRY_FQDROOT(name, S_IRUGO, \
+ (void *)&mask_filter[index], &qman_fqd_ctrl_fops)
+
+static int __init qman_debugfs_module_init(void)
+{
+ int ret = 0;
+ struct dentry *d, *fqd_root;
+ u32 reg;
+
+ fqid_max = 0;
+ init_ccsrmempeek();
+ if (qman_ccsr_start) {
+ if (!qman_ccsrmempeek(&reg, QM_FQD_AR)) {
+ /* extract the size of the FQD window */
+ reg = reg & 0x3f;
+ /* calculate valid frame queue descriptor range */
+ fqid_max = (1 << (reg + 1)) / QM_FQD_BLOCK_SIZE;
+ }
+ }
+ dfs_root = debugfs_create_dir("qman", NULL);
+ fqd_root = debugfs_create_dir("fqd", dfs_root);
+ if (dfs_root == NULL || fqd_root == NULL) {
+ ret = -ENOMEM;
+ pr_err("Cannot create qman/fqd debugfs dir\n");
+ goto _return;
+ }
+ if (fqid_max) {
+ QMAN_DBGFS_ENTRY_ROOT("ccsrmempeek", S_IRUGO | S_IWUGO,
+ NULL, &qman_ccsrmempeek_fops);
+ }
+ QMAN_DBGFS_ENTRY_ROOT("query_fq_np_fields", S_IRUGO | S_IWUGO,
+ &query_fq_np_fields_data, &query_fq_np_fields_fops);
+
+ QMAN_DBGFS_ENTRY_ROOT("query_fq_fields", S_IRUGO | S_IWUGO,
+ &query_fq_fields_data, &query_fq_fields_fops);
+
+ QMAN_DBGFS_ENTRY_ROOT("query_wq_lengths", S_IRUGO | S_IWUGO,
+ &query_wq_lengths_data, &query_wq_lengths_fops);
+
+ QMAN_DBGFS_ENTRY_ROOT("query_cgr", S_IRUGO | S_IWUGO,
+ &query_cgr_data, &query_cgr_fops);
+
+ QMAN_DBGFS_ENTRY_ROOT("query_congestion", S_IRUGO,
+ NULL, &query_congestion_fops);
+
+ QMAN_DBGFS_ENTRY_ROOT("testwrite_cgr", S_IRUGO,
+ NULL, &testwrite_cgr_fops);
+
+ QMAN_DBGFS_ENTRY_ROOT("testwrite_cgr_cgrid", S_IRUGO | S_IWUGO,
+ NULL, &teswrite_cgr_cgrid_fops);
+
+ QMAN_DBGFS_ENTRY_ROOT("testwrite_cgr_ibcnt", S_IRUGO | S_IWUGO,
+ NULL, &teswrite_cgr_ibcnt_fops);
+
+ QMAN_DBGFS_ENTRY_ROOT("query_ceetm_ccgr", S_IRUGO | S_IWUGO,
+ &query_ccgr_data, &query_ccgr_fops);
+ /* Create files with fqd_root as parent */
+
+ QMAN_DBGFS_ENTRY_FQDROOT("stateoos", S_IRUGO,
+ (void *)&fqd_states[QM_MCR_NP_STATE_OOS], &qman_fqd_state_fops);
+
+ QMAN_DBGFS_ENTRY_FQDROOT("state_retired", S_IRUGO,
+ (void *)&fqd_states[QM_MCR_NP_STATE_RETIRED],
+ &qman_fqd_state_fops);
+
+ QMAN_DBGFS_ENTRY_FQDROOT("state_tentatively_sched", S_IRUGO,
+ (void *)&fqd_states[QM_MCR_NP_STATE_TEN_SCHED],
+ &qman_fqd_state_fops);
+
+ QMAN_DBGFS_ENTRY_FQDROOT("state_truly_sched", S_IRUGO,
+ (void *)&fqd_states[QM_MCR_NP_STATE_TRU_SCHED],
+ &qman_fqd_state_fops);
+
+ QMAN_DBGFS_ENTRY_FQDROOT("state_parked", S_IRUGO,
+ (void *)&fqd_states[QM_MCR_NP_STATE_PARKED],
+ &qman_fqd_state_fops);
+
+ QMAN_DBGFS_ENTRY_FQDROOT("state_active", S_IRUGO,
+ (void *)&fqd_states[QM_MCR_NP_STATE_ACTIVE],
+ &qman_fqd_state_fops);
+ QMAN_DBGFS_ENTRY_ROOT("query_cq_fields", S_IRUGO | S_IWUGO,
+ &query_cq_fields_data, &query_cq_fields_fops);
+ QMAN_DBGFS_ENTRY_ROOT("query_ceetm_xsfdr_in_use", S_IRUGO | S_IWUGO,
+ &query_ceetm_xsfdr_data, &query_ceetm_xsfdr_fops);
+
+
+ QMAN_DBGFS_ENTRY_FQDSTATE("cge_enable", 17);
+
+ QMAN_DBGFS_ENTRY_FQDSTATE("cge_disable", 16);
+
+ QMAN_DBGFS_ENTRY_FQDSTATE("tde_enable", 15);
+
+ QMAN_DBGFS_ENTRY_FQDSTATE("tde_disable", 14);
+
+ QMAN_DBGFS_ENTRY_FQDSTATE("orp_enable", 13);
+
+ QMAN_DBGFS_ENTRY_FQDSTATE("orp_disable", 12);
+
+ QMAN_DBGFS_ENTRY_FQDSTATE("ctx_a_stashing_enable", 11);
+
+ QMAN_DBGFS_ENTRY_FQDSTATE("ctx_a_stashing_disable", 10);
+
+ QMAN_DBGFS_ENTRY_FQDSTATE("cpc_enable", 9);
+
+ QMAN_DBGFS_ENTRY_FQDSTATE("cpc_disable", 8);
+
+ QMAN_DBGFS_ENTRY_FQDSTATE("sfdr_enable", 7);
+
+ QMAN_DBGFS_ENTRY_FQDSTATE("sfdr_disable", 6);
+
+ QMAN_DBGFS_ENTRY_FQDSTATE("avoid_blocking_enable", 5);
+
+ QMAN_DBGFS_ENTRY_FQDSTATE("avoid_blocking_disable", 4);
+
+ QMAN_DBGFS_ENTRY_FQDSTATE("hold_active_enable", 3);
+
+ QMAN_DBGFS_ENTRY_FQDSTATE("hold_active_disable", 2);
+
+ QMAN_DBGFS_ENTRY_FQDSTATE("prefer_in_cache_enable", 1);
+
+ QMAN_DBGFS_ENTRY_FQDSTATE("prefer_in_cache_disable", 0);
+
+ QMAN_DBGFS_ENTRY_FQDROOT("summary", S_IRUGO,
+ NULL, &qman_fqd_summary_fops);
+
+ QMAN_DBGFS_ENTRY_FQDROOT("wq", S_IRUGO | S_IWUGO,
+ NULL, &qman_fqd_dest_wq_fops);
+
+ QMAN_DBGFS_ENTRY_FQDROOT("cred", S_IRUGO,
+ NULL, &qman_fqd_cred_fops);
+
+ return 0;
+
+_return:
+ debugfs_remove_recursive(dfs_root);
+ return ret;
+}
+
+static void __exit qman_debugfs_module_exit(void)
+{
+ debugfs_remove_recursive(dfs_root);
+}
+
+module_init(qman_debugfs_module_init);
+module_exit(qman_debugfs_module_exit);
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/staging/fsl_qbman/qman_driver.c b/drivers/staging/fsl_qbman/qman_driver.c
new file mode 100644
index 0000000..f5049b1
--- /dev/null
+++ b/drivers/staging/fsl_qbman/qman_driver.c
@@ -0,0 +1,942 @@
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "qman_private.h"
+
+#include <asm/smp.h> /* hard_smp_processor_id() if !CONFIG_SMP */
+#ifdef CONFIG_HOTPLUG_CPU
+#include <linux/cpu.h>
+#endif
+
+/* Global variable containing revision id (even on non-control plane systems
+ * where CCSR isn't available) */
+u16 qman_ip_rev;
+EXPORT_SYMBOL(qman_ip_rev);
+u16 qm_channel_pool1 = QMAN_CHANNEL_POOL1;
+EXPORT_SYMBOL(qm_channel_pool1);
+u16 qm_channel_caam = QMAN_CHANNEL_CAAM;
+EXPORT_SYMBOL(qm_channel_caam);
+u16 qm_channel_pme = QMAN_CHANNEL_PME;
+EXPORT_SYMBOL(qm_channel_pme);
+u16 qm_channel_dce = QMAN_CHANNEL_DCE;
+EXPORT_SYMBOL(qm_channel_dce);
+u16 qman_portal_max;
+EXPORT_SYMBOL(qman_portal_max);
+
+u32 qman_clk;
+struct qm_ceetm qman_ceetms[QMAN_CEETM_MAX];
+/* the qman ceetm instances on the given SoC */
+u8 num_ceetms;
+
+/* size of the fqd region in bytes */
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+static u32 fqd_size = (PAGE_SIZE << CONFIG_FSL_QMAN_FQD_SZ);
+#endif
+
+/* For these variables, and the portal-initialisation logic, the
+ * comments in bman_driver.c apply here so won't be repeated. */
+static struct qman_portal *shared_portals[NR_CPUS];
+static int num_shared_portals;
+static int shared_portals_idx;
+static LIST_HEAD(unused_pcfgs);
+static DEFINE_SPINLOCK(unused_pcfgs_lock);
+
+/* A SDQCR mask comprising all the available/visible pool channels */
+static u32 pools_sdqcr;
+
+#define STR_ERR_NOPROP "No '%s' property in node %s\n"
+#define STR_ERR_CELL "'%s' is not a %d-cell range in node %s\n"
+#define STR_FQID_RANGE "fsl,fqid-range"
+#define STR_POOL_CHAN_RANGE "fsl,pool-channel-range"
+#define STR_CGRID_RANGE "fsl,cgrid-range"
+
+/* A "fsl,fqid-range" node; release the given range to the allocator */
+static __init int fsl_fqid_range_init(struct device_node *node)
+{
+ int ret;
+ const u32 *range = of_get_property(node, STR_FQID_RANGE, &ret);
+ if (!range) {
+ pr_err(STR_ERR_NOPROP, STR_FQID_RANGE, node->full_name);
+ return -EINVAL;
+ }
+ if (ret != 8) {
+ pr_err(STR_ERR_CELL, STR_FQID_RANGE, 2, node->full_name);
+ return -EINVAL;
+ }
+ qman_seed_fqid_range(range[0], range[1]);
+ pr_info("Qman: FQID allocator includes range %d:%d\n",
+ range[0], range[1]);
+ return 0;
+}
+
+/* A "fsl,pool-channel-range" node; add to the SDQCR mask only */
+static __init int fsl_pool_channel_range_sdqcr(struct device_node *node)
+{
+ int ret;
+ const u32 *chanid = of_get_property(node, STR_POOL_CHAN_RANGE, &ret);
+ if (!chanid) {
+ pr_err(STR_ERR_NOPROP, STR_POOL_CHAN_RANGE, node->full_name);
+ return -EINVAL;
+ }
+ if (ret != 8) {
+ pr_err(STR_ERR_CELL, STR_POOL_CHAN_RANGE, 1, node->full_name);
+ return -EINVAL;
+ }
+ for (ret = 0; ret < chanid[1]; ret++)
+ pools_sdqcr |= QM_SDQCR_CHANNELS_POOL_CONV(chanid[0] + ret);
+ return 0;
+}
+
+/* A "fsl,pool-channel-range" node; release the given range to the allocator */
+static __init int fsl_pool_channel_range_init(struct device_node *node)
+{
+ int ret;
+ const u32 *chanid = of_get_property(node, STR_POOL_CHAN_RANGE, &ret);
+ if (!chanid) {
+ pr_err(STR_ERR_NOPROP, STR_POOL_CHAN_RANGE, node->full_name);
+ return -EINVAL;
+ }
+ if (ret != 8) {
+ pr_err(STR_ERR_CELL, STR_POOL_CHAN_RANGE, 1, node->full_name);
+ return -EINVAL;
+ }
+ qman_seed_pool_range(chanid[0], chanid[1]);
+ pr_info("Qman: pool channel allocator includes range %d:%d\n",
+ chanid[0], chanid[1]);
+ return 0;
+}
+
+/* A "fsl,cgrid-range" node; release the given range to the allocator */
+static __init int fsl_cgrid_range_init(struct device_node *node)
+{
+ struct qman_cgr cgr;
+ int ret, errors = 0;
+ const u32 *range = of_get_property(node, STR_CGRID_RANGE, &ret);
+ if (!range) {
+ pr_err(STR_ERR_NOPROP, STR_CGRID_RANGE, node->full_name);
+ return -EINVAL;
+ }
+ if (ret != 8) {
+ pr_err(STR_ERR_CELL, STR_CGRID_RANGE, 2, node->full_name);
+ return -EINVAL;
+ }
+ qman_seed_cgrid_range(range[0], range[1]);
+ pr_info("Qman: CGRID allocator includes range %d:%d\n",
+ range[0], range[1]);
+ for (cgr.cgrid = 0; cgr.cgrid < __CGR_NUM; cgr.cgrid++) {
+ ret = qman_modify_cgr(&cgr, QMAN_CGR_FLAG_USE_INIT, NULL);
+ if (ret)
+ errors++;
+ }
+ if (errors)
+ pr_err("Warning: %d error%s while initialising CGRs %d:%d\n",
+ errors, (errors > 1) ? "s" : "", range[0], range[1]);
+ return 0;
+}
+
+static __init int fsl_ceetm_init(struct device_node *node)
+{
+ enum qm_dc_portal dcp_portal;
+ struct qm_ceetm_sp *sp;
+ struct qm_ceetm_lni *lni;
+ int ret, i;
+ const u32 *range;
+
+ /* Find LFQID range */
+ range = of_get_property(node, "fsl,ceetm-lfqid-range", &ret);
+ if (!range) {
+ pr_err("No fsl,ceetm-lfqid-range in node %s\n",
+ node->full_name);
+ return -EINVAL;
+ }
+ if (ret != 8) {
+ pr_err("fsl,ceetm-lfqid-range is not a 2-cell range in node"
+ " %s\n", node->full_name);
+ return -EINVAL;
+ }
+
+ dcp_portal = (range[0] & 0x0F0000) >> 16;
+ if (dcp_portal > qm_dc_portal_fman1) {
+ pr_err("The DCP portal %d doesn't support CEETM\n", dcp_portal);
+ return -EINVAL;
+ }
+
+ if (dcp_portal == qm_dc_portal_fman0)
+ qman_seed_ceetm0_lfqid_range(range[0], range[1]);
+ if (dcp_portal == qm_dc_portal_fman1)
+ qman_seed_ceetm1_lfqid_range(range[0], range[1]);
+ pr_debug("Qman: The lfqid allocator of CEETM %d includes range"
+ " 0x%x:0x%x\n", dcp_portal, range[0], range[1]);
+
+ qman_ceetms[dcp_portal].idx = dcp_portal;
+ INIT_LIST_HEAD(&qman_ceetms[dcp_portal].sub_portals);
+ INIT_LIST_HEAD(&qman_ceetms[dcp_portal].lnis);
+
+ /* Find Sub-portal range */
+ range = of_get_property(node, "fsl,ceetm-sp-range", &ret);
+ if (!range) {
+ pr_err("No fsl,ceetm-sp-range in node %s\n", node->full_name);
+ return -EINVAL;
+ }
+ if (ret != 8) {
+ pr_err("fsl,ceetm-sp-range is not a 2-cell range in node %s\n",
+ node->full_name);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < range[1]; i++) {
+ sp = kzalloc(sizeof(*sp), GFP_KERNEL);
+ if (!sp) {
+ pr_err("Can't alloc memory for sub-portal %d\n",
+ range[0] + i);
+ return -ENOMEM;
+ }
+ sp->idx = range[0] + i;
+ sp->dcp_idx = dcp_portal;
+ sp->is_claimed = 0;
+ list_add_tail(&sp->node, &qman_ceetms[dcp_portal].sub_portals);
+ sp++;
+ }
+ pr_debug("Qman: Reserve sub-portal %d:%d for CEETM %d\n",
+ range[0], range[1], dcp_portal);
+ qman_ceetms[dcp_portal].sp_range[0] = range[0];
+ qman_ceetms[dcp_portal].sp_range[1] = range[1];
+
+ /* Find LNI range */
+ range = of_get_property(node, "fsl,ceetm-lni-range", &ret);
+ if (!range) {
+ pr_err("No fsl,ceetm-lni-range in node %s\n", node->full_name);
+ return -EINVAL;
+ }
+ if (ret != 8) {
+ pr_err("fsl,ceetm-lni-range is not a 2-cell range in node %s\n",
+ node->full_name);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < range[1]; i++) {
+ lni = kzalloc(sizeof(*lni), GFP_KERNEL);
+ if (!lni) {
+ pr_err("Can't alloc memory for LNI %d\n",
+ range[0] + i);
+ return -ENOMEM;
+ }
+ lni->idx = range[0] + i;
+ lni->dcp_idx = dcp_portal;
+ lni->is_claimed = 0;
+ INIT_LIST_HEAD(&lni->channels);
+ list_add_tail(&lni->node, &qman_ceetms[dcp_portal].lnis);
+ lni++;
+ }
+ pr_debug("Qman: Reserve LNI %d:%d for CEETM %d\n",
+ range[0], range[1], dcp_portal);
+ qman_ceetms[dcp_portal].lni_range[0] = range[0];
+ qman_ceetms[dcp_portal].lni_range[1] = range[1];
+
+ /* Find CEETM channel range */
+ range = of_get_property(node, "fsl,ceetm-channel-range", &ret);
+ if (!range) {
+ pr_err("No fsl,ceetm-channel-range in node %s\n",
+ node->full_name);
+ return -EINVAL;
+ }
+ if (ret != 8) {
+ pr_err("fsl,ceetm-channel-range is not a 2-cell range in node"
+ "%s\n", node->full_name);
+ return -EINVAL;
+ }
+
+ if (dcp_portal == qm_dc_portal_fman0)
+ qman_seed_ceetm0_channel_range(range[0], range[1]);
+ if (dcp_portal == qm_dc_portal_fman1)
+ qman_seed_ceetm1_channel_range(range[0], range[1]);
+ pr_debug("Qman: The channel allocator of CEETM %d includes"
+ " range %d:%d\n", dcp_portal, range[0], range[1]);
+
+ /* Set CEETM PRES register */
+ ret = qman_ceetm_set_prescaler(dcp_portal);
+ if (ret)
+ return ret;
+ return 0;
+}
+
+static void qman_get_ip_revision(struct device_node *dn)
+{
+ u16 ip_rev = 0;
+ for_each_compatible_node(dn, NULL, "fsl,qman-portal") {
+ if (!of_device_is_available(dn))
+ continue;
+ if (of_device_is_compatible(dn, "fsl,qman-portal-1.0") ||
+ of_device_is_compatible(dn, "fsl,qman-portal-1.0.0")) {
+ pr_err("QMAN rev1.0 on P4080 rev1 is not supported!\n");
+ BUG_ON(1);
+ } else if (of_device_is_compatible(dn, "fsl,qman-portal-1.1") ||
+ of_device_is_compatible(dn, "fsl,qman-portal-1.1.0")) {
+ ip_rev = QMAN_REV11;
+ qman_portal_max = 10;
+ } else if (of_device_is_compatible(dn, "fsl,qman-portal-1.2") ||
+ of_device_is_compatible(dn, "fsl,qman-portal-1.2.0")) {
+ ip_rev = QMAN_REV12;
+ qman_portal_max = 10;
+ } else if (of_device_is_compatible(dn, "fsl,qman-portal-2.0") ||
+ of_device_is_compatible(dn, "fsl,qman-portal-2.0.0")) {
+ ip_rev = QMAN_REV20;
+ qman_portal_max = 3;
+ } else if (of_device_is_compatible(dn,
+ "fsl,qman-portal-3.0.0")) {
+ ip_rev = QMAN_REV30;
+ qman_portal_max = 50;
+ } else if (of_device_is_compatible(dn,
+ "fsl,qman-portal-3.0.1")) {
+ ip_rev = QMAN_REV30;
+ qman_portal_max = 25;
+ } else if (of_device_is_compatible(dn,
+ "fsl,qman-portal-3.1.0")) {
+ ip_rev = QMAN_REV31;
+ qman_portal_max = 50;
+ } else if (of_device_is_compatible(dn,
+ "fsl,qman-portal-3.1.1")) {
+ ip_rev = QMAN_REV31;
+ qman_portal_max = 25;
+ } else if (of_device_is_compatible(dn,
+ "fsl,qman-portal-3.1.2")) {
+ ip_rev = QMAN_REV31;
+ qman_portal_max = 18;
+ } else if (of_device_is_compatible(dn,
+ "fsl,qman-portal-3.1.3")) {
+ ip_rev = QMAN_REV31;
+ qman_portal_max = 10;
+ } else {
+ pr_warn("unknown QMan version in portal node,"
+ "default to rev1.1\n");
+ ip_rev = QMAN_REV11;
+ qman_portal_max = 10;
+ }
+
+ if (!qman_ip_rev) {
+ if (ip_rev) {
+ qman_ip_rev = ip_rev;
+ } else {
+ pr_warn("unknown Qman version,"
+ " default to rev1.1\n");
+ qman_ip_rev = QMAN_REV11;
+ }
+ } else if (ip_rev && (qman_ip_rev != ip_rev))
+ pr_warn("Revision=0x%04x, but portal '%s' has"
+ " 0x%04x\n",
+ qman_ip_rev, dn->full_name, ip_rev);
+ if (qman_ip_rev == ip_rev)
+ break;
+ }
+}
+
+/* Parse a portal node, perform generic mapping duties and return the config. It
+ * is not known at this stage for what purpose (or even if) the portal will be
+ * used. */
+static struct qm_portal_config * __init parse_pcfg(struct device_node *node)
+{
+ struct qm_portal_config *pcfg;
+ const u32 *index, *channel;
+ int irq, ret;
+
+ pcfg = kmalloc(sizeof(*pcfg), GFP_KERNEL);
+ if (!pcfg) {
+ pr_err("can't allocate portal config");
+ return NULL;
+ }
+
+ /*
+ * This is a *horrible hack*, but the IOMMU/PAMU driver needs a
+ * 'struct device' in order to get the PAMU stashing setup and the QMan
+ * portal [driver] won't function at all without ring stashing
+ *
+ * Making the QMan portal driver nice and proper is part of the
+ * upstreaming effort
+ */
+ pcfg->dev.bus = &platform_bus_type;
+ pcfg->dev.of_node = node;
+#ifdef CONFIG_IOMMU_API
+ pcfg->dev.archdata.iommu_domain = NULL;
+#endif
+
+ ret = of_address_to_resource(node, DPA_PORTAL_CE,
+ &pcfg->addr_phys[DPA_PORTAL_CE]);
+ if (ret) {
+ pr_err("Can't get %s property '%s'\n", node->full_name,
+ "reg::CE");
+ goto err;
+ }
+ ret = of_address_to_resource(node, DPA_PORTAL_CI,
+ &pcfg->addr_phys[DPA_PORTAL_CI]);
+ if (ret) {
+ pr_err("Can't get %s property '%s'\n", node->full_name,
+ "reg::CI");
+ goto err;
+ }
+ index = of_get_property(node, "cell-index", &ret);
+ if (!index || (ret != 4)) {
+ pr_err("Can't get %s property '%s'\n", node->full_name,
+ "cell-index");
+ goto err;
+ }
+ if (*index >= qman_portal_max)
+ goto err;
+
+ channel = of_get_property(node, "fsl,qman-channel-id", &ret);
+ if (!channel || (ret != 4)) {
+ pr_err("Can't get %s property '%s'\n", node->full_name,
+ "fsl,qman-channel-id");
+ goto err;
+ }
+ if (*channel != (*index + QM_CHANNEL_SWPORTAL0))
+ pr_err("Warning: node %s has mismatched %s and %s\n",
+ node->full_name, "cell-index", "fsl,qman-channel-id");
+ pcfg->public_cfg.channel = *channel;
+ pcfg->public_cfg.cpu = -1;
+ irq = irq_of_parse_and_map(node, 0);
+ if (irq == NO_IRQ) {
+ pr_err("Can't get %s property '%s'\n", node->full_name,
+ "interrupts");
+ goto err;
+ }
+ pcfg->public_cfg.irq = irq;
+ pcfg->public_cfg.index = *index;
+#ifdef CONFIG_FSL_QMAN_CONFIG
+ /* We need the same LIODN offset for all portals */
+ qman_liodn_fixup(pcfg->public_cfg.channel);
+#endif
+
+ pcfg->addr_virt[DPA_PORTAL_CE] = ioremap_prot(
+ pcfg->addr_phys[DPA_PORTAL_CE].start,
+ resource_size(&pcfg->addr_phys[DPA_PORTAL_CE]),
+ 0);
+ pcfg->addr_virt[DPA_PORTAL_CI] = ioremap_prot(
+ pcfg->addr_phys[DPA_PORTAL_CI].start,
+ resource_size(&pcfg->addr_phys[DPA_PORTAL_CI]),
+ _PAGE_GUARDED | _PAGE_NO_CACHE);
+
+ return pcfg;
+err:
+ kfree(pcfg);
+ return NULL;
+}
+
+static struct qm_portal_config *get_pcfg(struct list_head *list)
+{
+ struct qm_portal_config *pcfg;
+ if (list_empty(list))
+ return NULL;
+ pcfg = list_entry(list->prev, struct qm_portal_config, list);
+ list_del(&pcfg->list);
+ return pcfg;
+}
+
+static struct qm_portal_config *get_pcfg_idx(struct list_head *list, u32 idx)
+{
+ struct qm_portal_config *pcfg;
+ if (list_empty(list))
+ return NULL;
+ list_for_each_entry(pcfg, list, list) {
+ if (pcfg->public_cfg.index == idx) {
+ list_del(&pcfg->list);
+ return pcfg;
+ }
+ }
+ return NULL;
+}
+
+static void portal_set_cpu(struct qm_portal_config *pcfg, int cpu)
+{
+#ifdef CONFIG_FSL_PAMU
+ int ret;
+ int window_count = 1;
+ struct iommu_domain_geometry geom_attr;
+ struct pamu_stash_attribute stash_attr;
+
+ pcfg->iommu_domain = iommu_domain_alloc(&platform_bus_type);
+ if (!pcfg->iommu_domain) {
+ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_alloc() failed",
+ __func__);
+ goto _no_iommu;
+ }
+ geom_attr.aperture_start = 0;
+ geom_attr.aperture_end =
+ ((dma_addr_t)1 << min(8 * sizeof(dma_addr_t), (size_t)36)) - 1;
+ geom_attr.force_aperture = true;
+ ret = iommu_domain_set_attr(pcfg->iommu_domain, DOMAIN_ATTR_GEOMETRY,
+ &geom_attr);
+ if (ret < 0) {
+ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_set_attr() = %d",
+ __func__, ret);
+ goto _iommu_domain_free;
+ }
+ ret = iommu_domain_set_attr(pcfg->iommu_domain, DOMAIN_ATTR_WINDOWS,
+ &window_count);
+ if (ret < 0) {
+ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_set_attr() = %d",
+ __func__, ret);
+ goto _iommu_domain_free;
+ }
+ stash_attr.cpu = cpu;
+ stash_attr.cache = PAMU_ATTR_CACHE_L1;
+ /* set stash information for the window */
+ stash_attr.window = 0;
+ ret = iommu_domain_set_attr(pcfg->iommu_domain,
+ DOMAIN_ATTR_FSL_PAMU_STASH,
+ &stash_attr);
+ if (ret < 0) {
+ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_set_attr() = %d",
+ __func__, ret);
+ goto _iommu_domain_free;
+ }
+ ret = iommu_domain_window_enable(pcfg->iommu_domain, 0, 0, 1ULL << 36,
+ IOMMU_READ | IOMMU_WRITE);
+ if (ret < 0) {
+ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_window_enable() = %d",
+ __func__, ret);
+ goto _iommu_domain_free;
+ }
+ ret = iommu_attach_device(pcfg->iommu_domain, &pcfg->dev);
+ if (ret < 0) {
+ pr_err(KBUILD_MODNAME ":%s(): iommu_device_attach() = %d",
+ __func__, ret);
+ goto _iommu_domain_free;
+ }
+ ret = iommu_domain_set_attr(pcfg->iommu_domain,
+ DOMAIN_ATTR_FSL_PAMU_ENABLE,
+ &window_count);
+ if (ret < 0) {
+ pr_err(KBUILD_MODNAME ":%s(): iommu_domain_set_attr() = %d",
+ __func__, ret);
+ goto _iommu_detach_device;
+ }
+
+_no_iommu:
+#endif
+#ifdef CONFIG_FSL_QMAN_CONFIG
+ if (qman_set_sdest(pcfg->public_cfg.channel, cpu))
+#endif
+ pr_warn("Failed to set QMan portal's stash request queue\n");
+
+ return;
+
+#ifdef CONFIG_FSL_PAMU
+_iommu_detach_device:
+ iommu_detach_device(pcfg->iommu_domain, NULL);
+_iommu_domain_free:
+ iommu_domain_free(pcfg->iommu_domain);
+#endif
+}
+
+struct qm_portal_config *qm_get_unused_portal_idx(u32 idx)
+{
+ struct qm_portal_config *ret;
+ spin_lock(&unused_pcfgs_lock);
+ if (idx == QBMAN_ANY_PORTAL_IDX)
+ ret = get_pcfg(&unused_pcfgs);
+ else
+ ret = get_pcfg_idx(&unused_pcfgs, idx);
+ spin_unlock(&unused_pcfgs_lock);
+ /* Bind stashing LIODNs to the CPU we are currently executing on, and
+ * set the portal to use the stashing request queue corresonding to the
+ * cpu as well. The user-space driver assumption is that the pthread has
+ * to already be affine to one cpu only before opening a portal. If that
+ * check is circumvented, the only risk is a performance degradation -
+ * stashing will go to whatever cpu they happened to be running on when
+ * opening the device file, and if that isn't the cpu they subsequently
+ * bind to and do their polling on, tough. */
+ if (ret)
+ portal_set_cpu(ret, hard_smp_processor_id());
+ return ret;
+}
+
+struct qm_portal_config *qm_get_unused_portal(void)
+{
+ return qm_get_unused_portal_idx(QBMAN_ANY_PORTAL_IDX);
+}
+
+void qm_put_unused_portal(struct qm_portal_config *pcfg)
+{
+ spin_lock(&unused_pcfgs_lock);
+ list_add(&pcfg->list, &unused_pcfgs);
+ spin_unlock(&unused_pcfgs_lock);
+}
+
+static struct qman_portal *init_pcfg(struct qm_portal_config *pcfg)
+{
+ struct qman_portal *p;
+
+ pcfg->iommu_domain = NULL;
+ portal_set_cpu(pcfg, pcfg->public_cfg.cpu);
+ p = qman_create_affine_portal(pcfg, NULL);
+ if (p) {
+ u32 irq_sources = 0;
+ /* Determine what should be interrupt-vs-poll driven */
+#ifdef CONFIG_FSL_DPA_PIRQ_SLOW
+ irq_sources |= QM_PIRQ_EQCI | QM_PIRQ_EQRI | QM_PIRQ_MRI |
+ QM_PIRQ_CSCI | QM_PIRQ_CCSCI;
+#endif
+#ifdef CONFIG_FSL_DPA_PIRQ_FAST
+ irq_sources |= QM_PIRQ_DQRI;
+#endif
+ qman_p_irqsource_add(p, irq_sources);
+ pr_info("Qman portal %sinitialised, cpu %d\n",
+ pcfg->public_cfg.is_shared ? "(shared) " : "",
+ pcfg->public_cfg.cpu);
+ } else
+ pr_crit("Qman portal failure on cpu %d\n",
+ pcfg->public_cfg.cpu);
+ return p;
+}
+
+static void init_slave(int cpu)
+{
+ struct qman_portal *p;
+ struct cpumask oldmask = *tsk_cpus_allowed(current);
+ set_cpus_allowed_ptr(current, get_cpu_mask(cpu));
+ p = qman_create_affine_slave(shared_portals[shared_portals_idx++], cpu);
+ if (!p)
+ pr_err("Qman slave portal failure on cpu %d\n", cpu);
+ else
+ pr_info("Qman portal %sinitialised, cpu %d\n", "(slave) ", cpu);
+ set_cpus_allowed_ptr(current, &oldmask);
+ if (shared_portals_idx >= num_shared_portals)
+ shared_portals_idx = 0;
+}
+
+static struct cpumask want_unshared __initdata;
+static struct cpumask want_shared __initdata;
+
+static int __init parse_qportals(char *str)
+{
+ return parse_portals_bootarg(str, &want_shared, &want_unshared,
+ "qportals");
+}
+__setup("qportals=", parse_qportals);
+
+static void qman_portal_update_sdest(const struct qm_portal_config *pcfg,
+ unsigned int cpu)
+{
+ struct pamu_stash_attribute stash_attr;
+ int ret;
+
+ if (pcfg->iommu_domain) {
+ stash_attr.cpu = cpu;
+ stash_attr.cache = PAMU_ATTR_CACHE_L1;
+ /* set stash information for the window */
+ stash_attr.window = 0;
+ ret = iommu_domain_set_attr(pcfg->iommu_domain,
+ DOMAIN_ATTR_FSL_PAMU_STASH, &stash_attr);
+ if (ret < 0) {
+ pr_err("Failed to update pamu stash setting\n");
+ return;
+ }
+ }
+#ifdef CONFIG_FSL_QMAN_CONFIG
+ if (qman_set_sdest(pcfg->public_cfg.channel, cpu))
+#endif
+ pr_warn("Failed to update portal's stash request queue\n");
+}
+
+static void qman_offline_cpu(unsigned int cpu)
+{
+ struct qman_portal *p;
+ const struct qm_portal_config *pcfg;
+ p = (struct qman_portal *)affine_portals[cpu];
+ if (p) {
+ pcfg = qman_get_qm_portal_config(p);
+ if (pcfg) {
+ irq_set_affinity(pcfg->public_cfg.irq, cpumask_of(0));
+ qman_portal_update_sdest(pcfg, 0);
+ }
+ }
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static void qman_online_cpu(unsigned int cpu)
+{
+ struct qman_portal *p;
+ const struct qm_portal_config *pcfg;
+ p = (struct qman_portal *)affine_portals[cpu];
+ if (p) {
+ pcfg = qman_get_qm_portal_config(p);
+ if (pcfg) {
+ irq_set_affinity(pcfg->public_cfg.irq, cpumask_of(cpu));
+ qman_portal_update_sdest(pcfg, cpu);
+ }
+ }
+}
+
+static int __cpuinit qman_hotplug_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ unsigned int cpu = (unsigned long)hcpu;
+
+ switch (action) {
+ case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
+ qman_online_cpu(cpu);
+ break;
+ case CPU_DOWN_PREPARE:
+ case CPU_DOWN_PREPARE_FROZEN:
+ qman_offline_cpu(cpu);
+ default:
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block qman_hotplug_cpu_notifier = {
+ .notifier_call = qman_hotplug_cpu_callback,
+};
+#endif /* CONFIG_HOTPLUG_CPU */
+
+__init int qman_init(void)
+{
+ struct cpumask slave_cpus;
+ struct cpumask unshared_cpus = *cpu_none_mask;
+ struct cpumask shared_cpus = *cpu_none_mask;
+ LIST_HEAD(unshared_pcfgs);
+ LIST_HEAD(shared_pcfgs);
+ struct device_node *dn;
+ struct qm_portal_config *pcfg;
+ struct qman_portal *p;
+ int cpu, ret;
+ const u32 *clk;
+ struct cpumask offline_cpus;
+
+ /* Initialise the Qman (CCSR) device */
+ for_each_compatible_node(dn, NULL, "fsl,qman") {
+ if (!qman_init_ccsr(dn))
+ pr_info("Qman err interrupt handler present\n");
+ else
+ pr_err("Qman CCSR setup failed\n");
+
+ clk = of_get_property(dn, "clock-frequency", NULL);
+ if (!clk)
+ pr_warn("Can't find Qman clock frequency\n");
+ else
+ qman_clk = *clk;
+ }
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+ /* Setup lookup table for FQ demux */
+ ret = qman_setup_fq_lookup_table(fqd_size/64);
+ if (ret)
+ return ret;
+#endif
+
+ /* Get qman ip revision */
+ qman_get_ip_revision(dn);
+ if ((qman_ip_rev & 0xff00) >= QMAN_REV30) {
+ qm_channel_pool1 = QMAN_CHANNEL_POOL1_REV3;
+ qm_channel_caam = QMAN_CHANNEL_CAAM_REV3;
+ qm_channel_pme = QMAN_CHANNEL_PME_REV3;
+ }
+
+ /*
+ * Parse the ceetm node to get how many ceetm instances are supported
+ * on the current silicon. num_ceetms must be confirmed before portals
+ * are intiailized.
+ */
+ num_ceetms = 0;
+ for_each_compatible_node(dn, NULL, "fsl,qman-ceetm")
+ num_ceetms++;
+
+ /* Parse pool channels into the SDQCR mask. (Must happen before portals
+ * are initialised.) */
+ for_each_compatible_node(dn, NULL, "fsl,pool-channel-range") {
+ ret = fsl_pool_channel_range_sdqcr(dn);
+ if (ret)
+ return ret;
+ }
+
+ memset(affine_portals, 0, sizeof(void *) * num_possible_cpus());
+ /* Initialise portals. See bman_driver.c for comments */
+ for_each_compatible_node(dn, NULL, "fsl,qman-portal") {
+ if (!of_device_is_available(dn))
+ continue;
+ pcfg = parse_pcfg(dn);
+ if (pcfg) {
+ pcfg->public_cfg.pools = pools_sdqcr;
+ list_add_tail(&pcfg->list, &unused_pcfgs);
+ }
+ }
+ for_each_possible_cpu(cpu) {
+ if (cpumask_test_cpu(cpu, &want_shared)) {
+ pcfg = get_pcfg(&unused_pcfgs);
+ if (!pcfg)
+ break;
+ pcfg->public_cfg.cpu = cpu;
+ list_add_tail(&pcfg->list, &shared_pcfgs);
+ cpumask_set_cpu(cpu, &shared_cpus);
+ }
+ if (cpumask_test_cpu(cpu, &want_unshared)) {
+ if (cpumask_test_cpu(cpu, &shared_cpus))
+ continue;
+ pcfg = get_pcfg(&unused_pcfgs);
+ if (!pcfg)
+ break;
+ pcfg->public_cfg.cpu = cpu;
+ list_add_tail(&pcfg->list, &unshared_pcfgs);
+ cpumask_set_cpu(cpu, &unshared_cpus);
+ }
+ }
+ if (list_empty(&shared_pcfgs) && list_empty(&unshared_pcfgs)) {
+ for_each_possible_cpu(cpu) {
+ pcfg = get_pcfg(&unused_pcfgs);
+ if (!pcfg)
+ break;
+ pcfg->public_cfg.cpu = cpu;
+ list_add_tail(&pcfg->list, &unshared_pcfgs);
+ cpumask_set_cpu(cpu, &unshared_cpus);
+ }
+ }
+ cpumask_andnot(&slave_cpus, cpu_possible_mask, &shared_cpus);
+ cpumask_andnot(&slave_cpus, &slave_cpus, &unshared_cpus);
+ if (cpumask_empty(&slave_cpus)) {
+ if (!list_empty(&shared_pcfgs)) {
+ cpumask_or(&unshared_cpus, &unshared_cpus,
+ &shared_cpus);
+ cpumask_clear(&shared_cpus);
+ list_splice_tail(&shared_pcfgs, &unshared_pcfgs);
+ INIT_LIST_HEAD(&shared_pcfgs);
+ }
+ } else {
+ if (list_empty(&shared_pcfgs)) {
+ pcfg = get_pcfg(&unshared_pcfgs);
+ if (!pcfg) {
+ pr_crit("No QMan portals available!\n");
+ return 0;
+ }
+ cpumask_clear_cpu(pcfg->public_cfg.cpu, &unshared_cpus);
+ cpumask_set_cpu(pcfg->public_cfg.cpu, &shared_cpus);
+ list_add_tail(&pcfg->list, &shared_pcfgs);
+ }
+ }
+ list_for_each_entry(pcfg, &unshared_pcfgs, list) {
+ pcfg->public_cfg.is_shared = 0;
+ p = init_pcfg(pcfg);
+ }
+ list_for_each_entry(pcfg, &shared_pcfgs, list) {
+ pcfg->public_cfg.is_shared = 1;
+ p = init_pcfg(pcfg);
+ if (p)
+ shared_portals[num_shared_portals++] = p;
+ }
+ if (!cpumask_empty(&slave_cpus))
+ for_each_cpu(cpu, &slave_cpus)
+ init_slave(cpu);
+ pr_info("Qman portals initialised\n");
+ cpumask_andnot(&offline_cpus, cpu_possible_mask, cpu_online_mask);
+ for_each_cpu(cpu, &offline_cpus)
+ qman_offline_cpu(cpu);
+#ifdef CONFIG_HOTPLUG_CPU
+ register_hotcpu_notifier(&qman_hotplug_cpu_notifier);
+#endif
+ return 0;
+}
+
+__init int qman_resource_init(void)
+{
+ struct device_node *dn;
+ int ret;
+
+ /* Initialise FQID allocation ranges */
+ for_each_compatible_node(dn, NULL, "fsl,fqid-range") {
+ ret = fsl_fqid_range_init(dn);
+ if (ret)
+ return ret;
+ }
+ /* Initialise CGRID allocation ranges */
+ for_each_compatible_node(dn, NULL, "fsl,cgrid-range") {
+ ret = fsl_cgrid_range_init(dn);
+ if (ret)
+ return ret;
+ }
+ /* Parse pool channels into the allocator. (Must happen after portals
+ * are initialised.) */
+ for_each_compatible_node(dn, NULL, "fsl,pool-channel-range") {
+ ret = fsl_pool_channel_range_init(dn);
+ if (ret)
+ return ret;
+ }
+
+ /* Parse CEETM */
+ for_each_compatible_node(dn, NULL, "fsl,qman-ceetm") {
+ ret = fsl_ceetm_init(dn);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+#ifdef CONFIG_SUSPEND
+void suspend_unused_qportal(void)
+{
+ struct qm_portal_config *pcfg;
+
+ if (list_empty(&unused_pcfgs))
+ return;
+
+ list_for_each_entry(pcfg, &unused_pcfgs, list) {
+#ifdef CONFIG_PM_DEBUG
+ pr_info("Need to save qportal %d\n", pcfg->public_cfg.index);
+#endif
+ /* save isdr, disable all via isdr, clear isr */
+ pcfg->saved_isdr =
+ __raw_readl(pcfg->addr_virt[DPA_PORTAL_CI] + 0xe08);
+ __raw_writel(0xffffffff, pcfg->addr_virt[DPA_PORTAL_CI] +
+ 0xe08);
+ __raw_writel(0xffffffff, pcfg->addr_virt[DPA_PORTAL_CI] +
+ 0xe00);
+ }
+ return;
+}
+
+void resume_unused_qportal(void)
+{
+ struct qm_portal_config *pcfg;
+
+ if (list_empty(&unused_pcfgs))
+ return;
+
+ list_for_each_entry(pcfg, &unused_pcfgs, list) {
+#ifdef CONFIG_PM_DEBUG
+ pr_info("Need to resume qportal %d\n", pcfg->public_cfg.index);
+#endif
+ /* restore isdr */
+ __raw_writel(pcfg->saved_isdr,
+ pcfg->addr_virt[DPA_PORTAL_CI] + 0xe08);
+ }
+ return;
+}
+#endif
+
diff --git a/drivers/staging/fsl_qbman/qman_high.c b/drivers/staging/fsl_qbman/qman_high.c
new file mode 100644
index 0000000..6b9f56d
--- /dev/null
+++ b/drivers/staging/fsl_qbman/qman_high.c
@@ -0,0 +1,4948 @@
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "qman_low.h"
+
+/* Compilation constants */
+#define DQRR_MAXFILL 15
+#define EQCR_ITHRESH 4 /* if EQCR congests, interrupt threshold */
+#define IRQNAME "QMan portal %d"
+#define MAX_IRQNAME 16 /* big enough for "QMan portal %d" */
+
+/* Divide 'n' by 'd', rounding down if 'r' is negative, rounding up if it's
+ * positive, and rounding to the closest value if it's zero. NB, this macro
+ * implicitly upgrades parameters to unsigned 64-bit, so feed it with types
+ * that are compatible with this. NB, these arguments should not be expressions
+ * unless it is safe for them to be evaluated multiple times. Eg. do not pass
+ * in "some_value++" as a parameter to the macro! */
+#define ROUNDING(n, d, r) \
+ (((r) < 0) ? div64_u64((n), (d)) : \
+ (((r) > 0) ? div64_u64(((n) + (d) - 1), (d)) : \
+ div64_u64(((n) + ((d) / 2)), (d))))
+
+/* Lock/unlock frame queues, subject to the "LOCKED" flag. This is about
+ * inter-processor locking only. Note, FQLOCK() is always called either under a
+ * local_irq_save() or from interrupt context - hence there's no need for irq
+ * protection (and indeed, attempting to nest irq-protection doesn't work, as
+ * the "irq en/disable" machinery isn't recursive...). */
+#define FQLOCK(fq) \
+ do { \
+ struct qman_fq *__fq478 = (fq); \
+ if (fq_isset(__fq478, QMAN_FQ_FLAG_LOCKED)) \
+ spin_lock(&__fq478->fqlock); \
+ } while (0)
+#define FQUNLOCK(fq) \
+ do { \
+ struct qman_fq *__fq478 = (fq); \
+ if (fq_isset(__fq478, QMAN_FQ_FLAG_LOCKED)) \
+ spin_unlock(&__fq478->fqlock); \
+ } while (0)
+
+static inline void fq_set(struct qman_fq *fq, u32 mask)
+{
+ set_bits(mask, &fq->flags);
+}
+static inline void fq_clear(struct qman_fq *fq, u32 mask)
+{
+ clear_bits(mask, &fq->flags);
+}
+static inline int fq_isset(struct qman_fq *fq, u32 mask)
+{
+ return fq->flags & mask;
+}
+static inline int fq_isclear(struct qman_fq *fq, u32 mask)
+{
+ return !(fq->flags & mask);
+}
+
+struct qman_portal {
+ struct qm_portal p;
+ unsigned long bits; /* PORTAL_BITS_*** - dynamic, strictly internal */
+ unsigned long irq_sources;
+ u32 use_eqcr_ci_stashing;
+ u32 slowpoll; /* only used when interrupts are off */
+ struct qman_fq *vdqcr_owned; /* only 1 volatile dequeue at a time */
+#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC
+ struct qman_fq *eqci_owned; /* only 1 enqueue WAIT_SYNC at a time */
+#endif
+#ifdef CONFIG_FSL_DPA_PORTAL_SHARE
+ raw_spinlock_t sharing_lock; /* only used if is_shared */
+ int is_shared;
+ struct qman_portal *sharing_redirect;
+#endif
+ u32 sdqcr;
+ int dqrr_disable_ref;
+ /* A portal-specific handler for DCP ERNs. If this is NULL, the global
+ * handler is called instead. */
+ qman_cb_dc_ern cb_dc_ern;
+ /* When the cpu-affine portal is activated, this is non-NULL */
+ const struct qm_portal_config *config;
+ /* This is needed for providing a non-NULL device to dma_map_***() */
+ struct platform_device *pdev;
+ struct dpa_rbtree retire_table;
+ char irqname[MAX_IRQNAME];
+ /* 2-element array. cgrs[0] is mask, cgrs[1] is snapshot. */
+ struct qman_cgrs *cgrs;
+ /* linked-list of CSCN handlers. */
+ struct list_head cgr_cbs;
+ /* list lock */
+ spinlock_t cgr_lock;
+ /* 2-element array. ccgrs[0] is mask, ccgrs[1] is snapshot. */
+ struct qman_ccgrs *ccgrs[QMAN_CEETM_MAX];
+ /* 256-element array, each is a linked-list of CCSCN handlers. */
+ struct list_head ccgr_cbs[QMAN_CEETM_MAX];
+ /* list lock */
+ spinlock_t ccgr_lock;
+ /* track if memory was allocated by the driver */
+ u8 alloced;
+ /* power management data */
+ u32 save_isdr;
+};
+
+#ifdef CONFIG_FSL_DPA_PORTAL_SHARE
+#define PORTAL_IRQ_LOCK(p, irqflags) \
+ do { \
+ if ((p)->is_shared) \
+ raw_spin_lock_irqsave(&(p)->sharing_lock, irqflags); \
+ else \
+ local_irq_save(irqflags); \
+ } while (0)
+#define PORTAL_IRQ_UNLOCK(p, irqflags) \
+ do { \
+ if ((p)->is_shared) \
+ raw_spin_unlock_irqrestore(&(p)->sharing_lock, \
+ irqflags); \
+ else \
+ local_irq_restore(irqflags); \
+ } while (0)
+#else
+#define PORTAL_IRQ_LOCK(p, irqflags) local_irq_save(irqflags)
+#define PORTAL_IRQ_UNLOCK(p, irqflags) local_irq_restore(irqflags)
+#endif
+
+/* Global handler for DCP ERNs. Used when the portal receiving the message does
+ * not have a portal-specific handler. */
+static qman_cb_dc_ern cb_dc_ern;
+
+static cpumask_t affine_mask;
+static DEFINE_SPINLOCK(affine_mask_lock);
+static u16 affine_channels[NR_CPUS];
+static DEFINE_PER_CPU(struct qman_portal, qman_affine_portal);
+void *affine_portals[NR_CPUS];
+
+/* "raw" gets the cpu-local struct whether it's a redirect or not. */
+static inline struct qman_portal *get_raw_affine_portal(void)
+{
+ return &get_cpu_var(qman_affine_portal);
+}
+/* For ops that can redirect, this obtains the portal to use */
+#ifdef CONFIG_FSL_DPA_PORTAL_SHARE
+static inline struct qman_portal *get_affine_portal(void)
+{
+ struct qman_portal *p = get_raw_affine_portal();
+ if (p->sharing_redirect)
+ return p->sharing_redirect;
+ return p;
+}
+#else
+#define get_affine_portal() get_raw_affine_portal()
+#endif
+/* For every "get", there must be a "put" */
+static inline void put_affine_portal(void)
+{
+ put_cpu_var(qman_affine_portal);
+}
+/* Exception: poll functions assume the caller is cpu-affine and in no risk of
+ * re-entrance, which are the two reasons we usually use the get/put_cpu_var()
+ * semantic - ie. to disable pre-emption. Some use-cases expect the execution
+ * context to remain as non-atomic during poll-triggered callbacks as it was
+ * when the poll API was first called (eg. NAPI), so we go out of our way in
+ * this case to not disable pre-emption. */
+static inline struct qman_portal *get_poll_portal(void)
+{
+ return &__get_cpu_var(qman_affine_portal);
+}
+#define put_poll_portal()
+
+/* This gives a FQID->FQ lookup to cover the fact that we can't directly demux
+ * retirement notifications (the fact they are sometimes h/w-consumed means that
+ * contextB isn't always a s/w demux - and as we can't know which case it is
+ * when looking at the notification, we have to use the slow lookup for all of
+ * them). NB, it's possible to have multiple FQ objects refer to the same FQID
+ * (though at most one of them should be the consumer), so this table isn't for
+ * all FQs - FQs are added when retirement commands are issued, and removed when
+ * they complete, which also massively reduces the size of this table. */
+IMPLEMENT_DPA_RBTREE(fqtree, struct qman_fq, node, fqid);
+
+/* This is what everything can wait on, even if it migrates to a different cpu
+ * to the one whose affine portal it is waiting on. */
+static DECLARE_WAIT_QUEUE_HEAD(affine_queue);
+
+static inline int table_push_fq(struct qman_portal *p, struct qman_fq *fq)
+{
+ int ret = fqtree_push(&p->retire_table, fq);
+ if (ret)
+ pr_err("ERROR: double FQ-retirement %d\n", fq->fqid);
+ return ret;
+}
+
+static inline void table_del_fq(struct qman_portal *p, struct qman_fq *fq)
+{
+ fqtree_del(&p->retire_table, fq);
+}
+
+static inline struct qman_fq *table_find_fq(struct qman_portal *p, u32 fqid)
+{
+ return fqtree_find(&p->retire_table, fqid);
+}
+
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+static void **qman_fq_lookup_table;
+static size_t qman_fq_lookup_table_size;
+
+int qman_setup_fq_lookup_table(size_t num_entries)
+{
+ num_entries++;
+ /* Allocate 1 more entry since the first entry is not used */
+ qman_fq_lookup_table = vzalloc((num_entries * sizeof(void *)));
+ if (!qman_fq_lookup_table) {
+ pr_err("QMan: Could not allocate fq lookup table\n");
+ return -ENOMEM;
+ }
+ qman_fq_lookup_table_size = num_entries;
+ pr_info("QMan: Allocated lookup table at %p, entry count %lu\n",
+ qman_fq_lookup_table,
+ (unsigned long)qman_fq_lookup_table_size);
+ return 0;
+}
+
+/* global structure that maintains fq object mapping */
+static DEFINE_SPINLOCK(fq_hash_table_lock);
+
+static int find_empty_fq_table_entry(u32 *entry, struct qman_fq *fq)
+{
+ u32 i;
+
+ spin_lock(&fq_hash_table_lock);
+ /* Can't use index zero because this has special meaning
+ * in context_b field. */
+ for (i = 1; i < qman_fq_lookup_table_size; i++) {
+ if (qman_fq_lookup_table[i] == NULL) {
+ *entry = i;
+ qman_fq_lookup_table[i] = fq;
+ spin_unlock(&fq_hash_table_lock);
+ return 0;
+ }
+ }
+ spin_unlock(&fq_hash_table_lock);
+ return -ENOMEM;
+}
+
+static void clear_fq_table_entry(u32 entry)
+{
+ spin_lock(&fq_hash_table_lock);
+ BUG_ON(entry >= qman_fq_lookup_table_size);
+ qman_fq_lookup_table[entry] = NULL;
+ spin_unlock(&fq_hash_table_lock);
+}
+
+static inline struct qman_fq *get_fq_table_entry(u32 entry)
+{
+ BUG_ON(entry >= qman_fq_lookup_table_size);
+ return qman_fq_lookup_table[entry];
+}
+#endif
+
+/* In the case that slow- and fast-path handling are both done by qman_poll()
+ * (ie. because there is no interrupt handling), we ought to balance how often
+ * we do the fast-path poll versus the slow-path poll. We'll use two decrementer
+ * sources, so we call the fast poll 'n' times before calling the slow poll
+ * once. The idle decrementer constant is used when the last slow-poll detected
+ * no work to do, and the busy decrementer constant when the last slow-poll had
+ * work to do. */
+#define SLOW_POLL_IDLE 1000
+#define SLOW_POLL_BUSY 10
+static u32 __poll_portal_slow(struct qman_portal *p, u32 is);
+static inline unsigned int __poll_portal_fast(struct qman_portal *p,
+ unsigned int poll_limit);
+
+/* Portal interrupt handler */
+static irqreturn_t portal_isr(__always_unused int irq, void *ptr)
+{
+ struct qman_portal *p = ptr;
+ /*
+ * The CSCI/CCSCI source is cleared inside __poll_portal_slow(), because
+ * it could race against a Query Congestion State command also given
+ * as part of the handling of this interrupt source. We mustn't
+ * clear it a second time in this top-level function.
+ */
+ u32 clear = QM_DQAVAIL_MASK | (p->irq_sources &
+ ~(QM_PIRQ_CSCI | QM_PIRQ_CCSCI));
+ u32 is = qm_isr_status_read(&p->p) & p->irq_sources;
+ /* DQRR-handling if it's interrupt-driven */
+ if (is & QM_PIRQ_DQRI)
+ __poll_portal_fast(p, CONFIG_FSL_QMAN_POLL_LIMIT);
+ /* Handling of anything else that's interrupt-driven */
+ clear |= __poll_portal_slow(p, is);
+ qm_isr_status_clear(&p->p, clear);
+ return IRQ_HANDLED;
+}
+
+/* This inner version is used privately by qman_create_affine_portal(), as well
+ * as by the exported qman_stop_dequeues(). */
+static inline void qman_stop_dequeues_ex(struct qman_portal *p)
+{
+ unsigned long irqflags __maybe_unused;
+ PORTAL_IRQ_LOCK(p, irqflags);
+ if (!(p->dqrr_disable_ref++))
+ qm_dqrr_set_maxfill(&p->p, 0);
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+}
+
+static int drain_mr_fqrni(struct qm_portal *p)
+{
+ const struct qm_mr_entry *msg;
+loop:
+ msg = qm_mr_current(p);
+ if (!msg) {
+ /* if MR was full and h/w had other FQRNI entries to produce, we
+ * need to allow it time to produce those entries once the
+ * existing entries are consumed. A worst-case situation
+ * (fully-loaded system) means h/w sequencers may have to do 3-4
+ * other things before servicing the portal's MR pump, each of
+ * which (if slow) may take ~50 qman cycles (which is ~200
+ * processor cycles). So rounding up and then multiplying this
+ * worst-case estimate by a factor of 10, just to be
+ * ultra-paranoid, goes as high as 10,000 cycles. NB, we consume
+ * one entry at a time, so h/w has an opportunity to produce new
+ * entries well before the ring has been fully consumed, so
+ * we're being *really* paranoid here. */
+ u64 now, then = mfatb();
+ do {
+ now = mfatb();
+ } while ((then + 10000) > now);
+ msg = qm_mr_current(p);
+ if (!msg)
+ return 0;
+ }
+ if ((msg->verb & QM_MR_VERB_TYPE_MASK) != QM_MR_VERB_FQRNI) {
+ /* We aren't draining anything but FQRNIs */
+ pr_err("QMan found verb 0x%x in MR\n", msg->verb);
+ return -1;
+ }
+ qm_mr_next(p);
+ qm_mr_cci_consume(p, 1);
+ goto loop;
+}
+
+#ifdef CONFIG_SUSPEND
+static int _qman_portal_suspend_noirq(struct device *dev)
+{
+ struct qman_portal *p = (struct qman_portal *)dev->platform_data;
+#ifdef CONFIG_PM_DEBUG
+ struct platform_device *pdev = to_platform_device(dev);
+#endif
+
+ p->save_isdr = qm_isr_disable_read(&p->p);
+ qm_isr_disable_write(&p->p, 0xffffffff);
+ qm_isr_status_clear(&p->p, 0xffffffff);
+#ifdef CONFIG_PM_DEBUG
+ pr_info("Suspend for %s\n", pdev->name);
+#endif
+ return 0;
+}
+
+static int _qman_portal_resume_noirq(struct device *dev)
+{
+ struct qman_portal *p = (struct qman_portal *)dev->platform_data;
+
+ /* restore isdr */
+ qm_isr_disable_write(&p->p, p->save_isdr);
+ return 0;
+}
+#else
+#define _qman_portal_suspend_noirq NULL
+#define _qman_portal_resume_noirq NULL
+#endif
+
+struct dev_pm_domain qman_portal_device_pm_domain = {
+ .ops = {
+ USE_PLATFORM_PM_SLEEP_OPS
+ .suspend_noirq = _qman_portal_suspend_noirq,
+ .resume_noirq = _qman_portal_resume_noirq,
+ }
+};
+
+struct qman_portal *qman_create_portal(
+ struct qman_portal *portal,
+ const struct qm_portal_config *config,
+ const struct qman_cgrs *cgrs)
+{
+ struct qm_portal *__p;
+ char buf[16];
+ int ret;
+ u32 isdr;
+
+ if (!portal) {
+ portal = kmalloc(sizeof(*portal), GFP_KERNEL);
+ if (!portal)
+ return portal;
+ portal->alloced = 1;
+ } else
+ portal->alloced = 0;
+
+ __p = &portal->p;
+
+ portal->use_eqcr_ci_stashing = ((qman_ip_rev >= QMAN_REV30) ?
+ 1 : 0);
+
+ /* prep the low-level portal struct with the mapped addresses from the
+ * config, everything that follows depends on it and "config" is more
+ * for (de)reference... */
+ __p->addr.addr_ce = config->addr_virt[DPA_PORTAL_CE];
+ __p->addr.addr_ci = config->addr_virt[DPA_PORTAL_CI];
+ /*
+ * If CI-stashing is used, the current defaults use a threshold of 3,
+ * and stash with high-than-DQRR priority.
+ */
+ if (qm_eqcr_init(__p, qm_eqcr_pvb,
+ portal->use_eqcr_ci_stashing ? 3 : 0, 1)) {
+ pr_err("Qman EQCR initialisation failed\n");
+ goto fail_eqcr;
+ }
+ if (qm_dqrr_init(__p, config, qm_dqrr_dpush, qm_dqrr_pvb,
+ qm_dqrr_cdc, DQRR_MAXFILL)) {
+ pr_err("Qman DQRR initialisation failed\n");
+ goto fail_dqrr;
+ }
+ if (qm_mr_init(__p, qm_mr_pvb, qm_mr_cci)) {
+ pr_err("Qman MR initialisation failed\n");
+ goto fail_mr;
+ }
+ if (qm_mc_init(__p)) {
+ pr_err("Qman MC initialisation failed\n");
+ goto fail_mc;
+ }
+ if (qm_isr_init(__p)) {
+ pr_err("Qman ISR initialisation failed\n");
+ goto fail_isr;
+ }
+ /* static interrupt-gating controls */
+ qm_dqrr_set_ithresh(__p, CONFIG_FSL_QMAN_PIRQ_DQRR_ITHRESH);
+ qm_mr_set_ithresh(__p, CONFIG_FSL_QMAN_PIRQ_MR_ITHRESH);
+ qm_isr_set_iperiod(__p, CONFIG_FSL_QMAN_PIRQ_IPERIOD);
+ portal->cgrs = kmalloc(2 * sizeof(*cgrs), GFP_KERNEL);
+ if (!portal->cgrs)
+ goto fail_cgrs;
+ /* initial snapshot is no-depletion */
+ qman_cgrs_init(&portal->cgrs[1]);
+ if (cgrs)
+ portal->cgrs[0] = *cgrs;
+ else
+ /* if the given mask is NULL, assume all CGRs can be seen */
+ qman_cgrs_fill(&portal->cgrs[0]);
+ INIT_LIST_HEAD(&portal->cgr_cbs);
+ spin_lock_init(&portal->cgr_lock);
+ if (num_ceetms) {
+ for (ret = 0; ret < num_ceetms; ret++) {
+ portal->ccgrs[ret] = kmalloc(2 *
+ sizeof(struct qman_ccgrs), GFP_KERNEL);
+ if (!portal->ccgrs[ret])
+ goto fail_ccgrs;
+ qman_ccgrs_init(&portal->ccgrs[ret][1]);
+ qman_ccgrs_fill(&portal->ccgrs[ret][0]);
+ INIT_LIST_HEAD(&portal->ccgr_cbs[ret]);
+ }
+ }
+ spin_lock_init(&portal->ccgr_lock);
+ portal->bits = 0;
+ portal->slowpoll = 0;
+#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC
+ portal->eqci_owned = NULL;
+#endif
+#ifdef CONFIG_FSL_DPA_PORTAL_SHARE
+ raw_spin_lock_init(&portal->sharing_lock);
+ portal->is_shared = config->public_cfg.is_shared;
+ portal->sharing_redirect = NULL;
+#endif
+ portal->sdqcr = QM_SDQCR_SOURCE_CHANNELS | QM_SDQCR_COUNT_UPTO3 |
+ QM_SDQCR_DEDICATED_PRECEDENCE | QM_SDQCR_TYPE_PRIO_QOS |
+ QM_SDQCR_TOKEN_SET(0xab) | QM_SDQCR_CHANNELS_DEDICATED;
+ portal->dqrr_disable_ref = 0;
+ portal->cb_dc_ern = NULL;
+ sprintf(buf, "qportal-%d", config->public_cfg.channel);
+ portal->pdev = platform_device_alloc(buf, -1);
+ if (!portal->pdev)
+ goto fail_devalloc;
+ if (dma_set_mask(&portal->pdev->dev, DMA_BIT_MASK(40)))
+ goto fail_devadd;
+ portal->pdev->dev.pm_domain = &qman_portal_device_pm_domain;
+ portal->pdev->dev.platform_data = portal;
+ ret = platform_device_add(portal->pdev);
+ if (ret)
+ goto fail_devadd;
+ dpa_rbtree_init(&portal->retire_table);
+ isdr = 0xffffffff;
+ qm_isr_disable_write(__p, isdr);
+ portal->irq_sources = 0;
+ qm_isr_enable_write(__p, portal->irq_sources);
+ qm_isr_status_clear(__p, 0xffffffff);
+ snprintf(portal->irqname, MAX_IRQNAME, IRQNAME, config->public_cfg.cpu);
+ if (request_irq(config->public_cfg.irq, portal_isr, 0, portal->irqname,
+ portal)) {
+ pr_err("request_irq() failed\n");
+ goto fail_irq;
+ }
+ if ((config->public_cfg.cpu != -1) &&
+ irq_can_set_affinity(config->public_cfg.irq) &&
+ irq_set_affinity(config->public_cfg.irq,
+ cpumask_of(config->public_cfg.cpu))) {
+ pr_err("irq_set_affinity() failed\n");
+ goto fail_affinity;
+ }
+
+ /* Need EQCR to be empty before continuing */
+ isdr ^= QM_PIRQ_EQCI;
+ qm_isr_disable_write(__p, isdr);
+ ret = qm_eqcr_get_fill(__p);
+ if (ret) {
+ pr_err("Qman EQCR unclean\n");
+ goto fail_eqcr_empty;
+ }
+ isdr ^= (QM_PIRQ_DQRI | QM_PIRQ_MRI);
+ qm_isr_disable_write(__p, isdr);
+ if (qm_dqrr_current(__p) != NULL) {
+ pr_err("Qman DQRR unclean\n");
+ qm_dqrr_cdc_consume_n(__p, 0xffff);
+ }
+ if (qm_mr_current(__p) != NULL) {
+ /* special handling, drain just in case it's a few FQRNIs */
+ if (drain_mr_fqrni(__p)) {
+ const struct qm_mr_entry *e = qm_mr_current(__p);
+ pr_err("Qman MR unclean, MR VERB 0x%x, "
+ "rc 0x%x\n, addr 0x%x",
+ e->verb, e->ern.rc, e->ern.fd.addr_lo);
+ goto fail_dqrr_mr_empty;
+ }
+ }
+ /* Success */
+ portal->config = config;
+ qm_isr_disable_write(__p, 0);
+ qm_isr_uninhibit(__p);
+ /* Write a sane SDQCR */
+ qm_dqrr_sdqcr_set(__p, portal->sdqcr);
+ return portal;
+fail_dqrr_mr_empty:
+fail_eqcr_empty:
+fail_affinity:
+ free_irq(config->public_cfg.irq, portal);
+fail_irq:
+ platform_device_del(portal->pdev);
+fail_devadd:
+ platform_device_put(portal->pdev);
+fail_devalloc:
+ if (num_ceetms)
+ for (ret = 0; ret < num_ceetms; ret++)
+ kfree(portal->ccgrs[ret]);
+fail_ccgrs:
+ kfree(portal->cgrs);
+fail_cgrs:
+ qm_isr_finish(__p);
+fail_isr:
+ qm_mc_finish(__p);
+fail_mc:
+ qm_mr_finish(__p);
+fail_mr:
+ qm_dqrr_finish(__p);
+fail_dqrr:
+ qm_eqcr_finish(__p);
+fail_eqcr:
+ return NULL;
+}
+
+struct qman_portal *qman_create_affine_portal(
+ const struct qm_portal_config *config,
+ const struct qman_cgrs *cgrs)
+{
+ struct qman_portal *res;
+ struct qman_portal *portal;
+
+ portal = &per_cpu(qman_affine_portal, config->public_cfg.cpu);
+ res = qman_create_portal(portal, config, cgrs);
+ if (res) {
+ spin_lock(&affine_mask_lock);
+ cpumask_set_cpu(config->public_cfg.cpu, &affine_mask);
+ affine_channels[config->public_cfg.cpu] =
+ config->public_cfg.channel;
+ affine_portals[config->public_cfg.cpu] = portal;
+ spin_unlock(&affine_mask_lock);
+ }
+ return res;
+}
+
+/* These checks are BUG_ON()s because the driver is already supposed to avoid
+ * these cases. */
+struct qman_portal *qman_create_affine_slave(struct qman_portal *redirect,
+ int cpu)
+{
+#ifdef CONFIG_FSL_DPA_PORTAL_SHARE
+ struct qman_portal *p;
+ p = &per_cpu(qman_affine_portal, cpu);
+ /* Check that we don't already have our own portal */
+ BUG_ON(p->config);
+ /* Check that we aren't already slaving to another portal */
+ BUG_ON(p->is_shared);
+ /* Check that 'redirect' is prepared to have us */
+ BUG_ON(!redirect->config->public_cfg.is_shared);
+ /* These are the only elements to initialise when redirecting */
+ p->irq_sources = 0;
+ p->sharing_redirect = redirect;
+ affine_portals[cpu] = p;
+ return p;
+#else
+ BUG();
+ return NULL;
+#endif
+}
+
+void qman_destroy_portal(struct qman_portal *qm)
+{
+ const struct qm_portal_config *pcfg;
+ int i;
+
+ /* Stop dequeues on the portal */
+ qm_dqrr_sdqcr_set(&qm->p, 0);
+
+ /* NB we do this to "quiesce" EQCR. If we add enqueue-completions or
+ * something related to QM_PIRQ_EQCI, this may need fixing.
+ * Also, due to the prefetching model used for CI updates in the enqueue
+ * path, this update will only invalidate the CI cacheline *after*
+ * working on it, so we need to call this twice to ensure a full update
+ * irrespective of where the enqueue processing was at when the teardown
+ * began. */
+ qm_eqcr_cce_update(&qm->p);
+ qm_eqcr_cce_update(&qm->p);
+ pcfg = qm->config;
+
+ free_irq(pcfg->public_cfg.irq, qm);
+
+ kfree(qm->cgrs);
+ if (num_ceetms)
+ for (i = 0; i < num_ceetms; i++)
+ kfree(qm->ccgrs[i]);
+ qm_isr_finish(&qm->p);
+ qm_mc_finish(&qm->p);
+ qm_mr_finish(&qm->p);
+ qm_dqrr_finish(&qm->p);
+ qm_eqcr_finish(&qm->p);
+
+ platform_device_del(qm->pdev);
+ platform_device_put(qm->pdev);
+
+ qm->config = NULL;
+ if (qm->alloced)
+ kfree(qm);
+}
+
+const struct qm_portal_config *qman_destroy_affine_portal(void)
+{
+ /* We don't want to redirect if we're a slave, use "raw" */
+ struct qman_portal *qm = get_raw_affine_portal();
+ const struct qm_portal_config *pcfg;
+ int cpu;
+#ifdef CONFIG_FSL_DPA_PORTAL_SHARE
+ if (qm->sharing_redirect) {
+ qm->sharing_redirect = NULL;
+ put_affine_portal();
+ return NULL;
+ }
+ qm->is_shared = 0;
+#endif
+ pcfg = qm->config;
+ cpu = pcfg->public_cfg.cpu;
+
+ qman_destroy_portal(qm);
+
+ spin_lock(&affine_mask_lock);
+ cpumask_clear_cpu(cpu, &affine_mask);
+ spin_unlock(&affine_mask_lock);
+ put_affine_portal();
+ return pcfg;
+}
+
+const struct qman_portal_config *qman_p_get_portal_config(struct qman_portal *p)
+{
+ return &p->config->public_cfg;
+}
+EXPORT_SYMBOL(qman_p_get_portal_config);
+
+const struct qman_portal_config *qman_get_portal_config(void)
+{
+ struct qman_portal *p = get_affine_portal();
+ const struct qman_portal_config *ret = qman_p_get_portal_config(p);
+ put_affine_portal();
+ return ret;
+}
+EXPORT_SYMBOL(qman_get_portal_config);
+
+/* Inline helper to reduce nesting in __poll_portal_slow() */
+static inline void fq_state_change(struct qman_portal *p, struct qman_fq *fq,
+ const struct qm_mr_entry *msg, u8 verb)
+{
+ FQLOCK(fq);
+ switch (verb) {
+ case QM_MR_VERB_FQRL:
+ DPA_ASSERT(fq_isset(fq, QMAN_FQ_STATE_ORL));
+ fq_clear(fq, QMAN_FQ_STATE_ORL);
+ table_del_fq(p, fq);
+ break;
+ case QM_MR_VERB_FQRN:
+ DPA_ASSERT((fq->state == qman_fq_state_parked) ||
+ (fq->state == qman_fq_state_sched));
+ DPA_ASSERT(fq_isset(fq, QMAN_FQ_STATE_CHANGING));
+ fq_clear(fq, QMAN_FQ_STATE_CHANGING);
+ if (msg->fq.fqs & QM_MR_FQS_NOTEMPTY)
+ fq_set(fq, QMAN_FQ_STATE_NE);
+ if (msg->fq.fqs & QM_MR_FQS_ORLPRESENT)
+ fq_set(fq, QMAN_FQ_STATE_ORL);
+ else
+ table_del_fq(p, fq);
+ fq->state = qman_fq_state_retired;
+ break;
+ case QM_MR_VERB_FQPN:
+ DPA_ASSERT(fq->state == qman_fq_state_sched);
+ DPA_ASSERT(fq_isclear(fq, QMAN_FQ_STATE_CHANGING));
+ fq->state = qman_fq_state_parked;
+ }
+ FQUNLOCK(fq);
+}
+
+static u32 __poll_portal_slow(struct qman_portal *p, u32 is)
+{
+ const struct qm_mr_entry *msg;
+
+ if (is & QM_PIRQ_CSCI) {
+ struct qman_cgrs rr, c;
+ struct qm_mc_result *mcr;
+ struct qman_cgr *cgr;
+ unsigned long irqflags __maybe_unused;
+
+ spin_lock_irqsave(&p->cgr_lock, irqflags);
+ /*
+ * The CSCI bit must be cleared _before_ issuing the
+ * Query Congestion State command, to ensure that a long
+ * CGR State Change callback cannot miss an intervening
+ * state change.
+ */
+ qm_isr_status_clear(&p->p, QM_PIRQ_CSCI);
+ qm_mc_start(&p->p);
+ qm_mc_commit(&p->p, QM_MCC_VERB_QUERYCONGESTION);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ /* mask out the ones I'm not interested in */
+ qman_cgrs_and(&rr, (const struct qman_cgrs *)
+ &mcr->querycongestion.state, &p->cgrs[0]);
+ /* check previous snapshot for delta, enter/exit congestion */
+ qman_cgrs_xor(&c, &rr, &p->cgrs[1]);
+ /* update snapshot */
+ qman_cgrs_cp(&p->cgrs[1], &rr);
+ /* Invoke callback */
+ list_for_each_entry(cgr, &p->cgr_cbs, node)
+ if (cgr->cb && qman_cgrs_get(&c, cgr->cgrid))
+ cgr->cb(p, cgr, qman_cgrs_get(&rr, cgr->cgrid));
+ spin_unlock_irqrestore(&p->cgr_lock, irqflags);
+ }
+ if (is & QM_PIRQ_CCSCI) {
+ struct qman_ccgrs rr, c, congestion_result;
+ struct qm_mc_result *mcr;
+ struct qm_mc_command *mcc;
+ struct qm_ceetm_ccg *ccg;
+ unsigned long irqflags __maybe_unused;
+ int i, j;
+
+ spin_lock_irqsave(&p->ccgr_lock, irqflags);
+ /*
+ * The CCSCI bit must be cleared _before_ issuing the
+ * Query Congestion State command, to ensure that a long
+ * CCGR State Change callback cannot miss an intervening
+ * state change.
+ */
+ qm_isr_status_clear(&p->p, QM_PIRQ_CCSCI);
+
+ for (i = 0; i < num_ceetms; i++) {
+ for (j = 0; j < 2; j++) {
+ mcc = qm_mc_start(&p->p);
+ mcc->ccgr_query.ccgrid =
+ CEETM_QUERY_CONGESTION_STATE | j;
+ mcc->ccgr_query.dcpid = i;
+ qm_mc_commit(&p->p, QM_CEETM_VERB_CCGR_QUERY);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ congestion_result.q[j] =
+ mcr->ccgr_query.congestion_state.state;
+ }
+ /* mask out the ones I'm not interested in */
+ qman_ccgrs_and(&rr, &congestion_result,
+ &p->ccgrs[i][0]);
+ /*
+ * check previous snapshot for delta, enter/exit
+ * congestion.
+ */
+ qman_ccgrs_xor(&c, &rr, &p->ccgrs[i][1]);
+ /* update snapshot */
+ qman_ccgrs_cp(&p->ccgrs[i][1], &rr);
+ /* Invoke callback */
+ list_for_each_entry(ccg, &p->ccgr_cbs[i], cb_node)
+ if (ccg->cb && qman_ccgrs_get(&c,
+ (ccg->parent->idx << 4) | ccg->idx))
+ ccg->cb(ccg, ccg->cb_ctx,
+ qman_ccgrs_get(&rr,
+ (ccg->parent->idx << 4)
+ | ccg->idx));
+ }
+ spin_unlock_irqrestore(&p->ccgr_lock, irqflags);
+ }
+
+#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC
+ if (is & QM_PIRQ_EQCI) {
+ unsigned long irqflags;
+ PORTAL_IRQ_LOCK(p, irqflags);
+ p->eqci_owned = NULL;
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ wake_up(&affine_queue);
+ }
+#endif
+
+ if (is & QM_PIRQ_EQRI) {
+ unsigned long irqflags __maybe_unused;
+ PORTAL_IRQ_LOCK(p, irqflags);
+ qm_eqcr_cce_update(&p->p);
+ qm_eqcr_set_ithresh(&p->p, 0);
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ wake_up(&affine_queue);
+ }
+
+ if (is & QM_PIRQ_MRI) {
+ struct qman_fq *fq;
+ u8 verb, num = 0;
+mr_loop:
+ qm_mr_pvb_update(&p->p);
+ msg = qm_mr_current(&p->p);
+ if (!msg)
+ goto mr_done;
+ verb = msg->verb & QM_MR_VERB_TYPE_MASK;
+ /* The message is a software ERN iff the 0x20 bit is set */
+ if (verb & 0x20) {
+ switch (verb) {
+ case QM_MR_VERB_FQRNI:
+ /* nada, we drop FQRNIs on the floor */
+ break;
+ case QM_MR_VERB_FQRN:
+ case QM_MR_VERB_FQRL:
+ /* Lookup in the retirement table */
+ fq = table_find_fq(p, msg->fq.fqid);
+ BUG_ON(!fq);
+ fq_state_change(p, fq, msg, verb);
+ if (fq->cb.fqs)
+ fq->cb.fqs(p, fq, msg);
+ break;
+ case QM_MR_VERB_FQPN:
+ /* Parked */
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+ fq = get_fq_table_entry(msg->fq.contextB);
+#else
+ fq = (void *)(uintptr_t)msg->fq.contextB;
+#endif
+ fq_state_change(p, fq, msg, verb);
+ if (fq->cb.fqs)
+ fq->cb.fqs(p, fq, msg);
+ break;
+ case QM_MR_VERB_DC_ERN:
+ /* DCP ERN */
+ if (p->cb_dc_ern)
+ p->cb_dc_ern(p, msg);
+ else if (cb_dc_ern)
+ cb_dc_ern(p, msg);
+ else {
+ static int warn_once;
+ if (!warn_once) {
+ pr_crit("Leaking DCP ERNs!\n");
+ warn_once = 1;
+ }
+ }
+ break;
+ default:
+ pr_crit("Invalid MR verb 0x%02x\n", verb);
+ }
+ } else {
+ /* Its a software ERN */
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+ fq = get_fq_table_entry(msg->ern.tag);
+#else
+ fq = (void *)(uintptr_t)msg->ern.tag;
+#endif
+ fq->cb.ern(p, fq, msg);
+ }
+ num++;
+ qm_mr_next(&p->p);
+ goto mr_loop;
+mr_done:
+ qm_mr_cci_consume(&p->p, num);
+ }
+ /*
+ * QM_PIRQ_CSCI/CCSCI has already been cleared, as part of its specific
+ * processing. If that interrupt source has meanwhile been re-asserted,
+ * we mustn't clear it here (or in the top-level interrupt handler).
+ */
+ return is & (QM_PIRQ_EQCI | QM_PIRQ_EQRI | QM_PIRQ_MRI);
+}
+
+/* remove some slowish-path stuff from the "fast path" and make sure it isn't
+ * inlined. */
+static noinline void clear_vdqcr(struct qman_portal *p, struct qman_fq *fq)
+{
+ p->vdqcr_owned = NULL;
+ FQLOCK(fq);
+ fq_clear(fq, QMAN_FQ_STATE_VDQCR);
+ FQUNLOCK(fq);
+ wake_up(&affine_queue);
+}
+
+/* Look: no locks, no irq_save()s, no preempt_disable()s! :-) The only states
+ * that would conflict with other things if they ran at the same time on the
+ * same cpu are;
+ *
+ * (i) setting/clearing vdqcr_owned, and
+ * (ii) clearing the NE (Not Empty) flag.
+ *
+ * Both are safe. Because;
+ *
+ * (i) this clearing can only occur after qman_volatile_dequeue() has set the
+ * vdqcr_owned field (which it does before setting VDQCR), and
+ * qman_volatile_dequeue() blocks interrupts and preemption while this is
+ * done so that we can't interfere.
+ * (ii) the NE flag is only cleared after qman_retire_fq() has set it, and as
+ * with (i) that API prevents us from interfering until it's safe.
+ *
+ * The good thing is that qman_volatile_dequeue() and qman_retire_fq() run far
+ * less frequently (ie. per-FQ) than __poll_portal_fast() does, so the nett
+ * advantage comes from this function not having to "lock" anything at all.
+ *
+ * Note also that the callbacks are invoked at points which are safe against the
+ * above potential conflicts, but that this function itself is not re-entrant
+ * (this is because the function tracks one end of each FIFO in the portal and
+ * we do *not* want to lock that). So the consequence is that it is safe for
+ * user callbacks to call into any Qman API *except* qman_poll() (as that's the
+ * sole API that could be invoking the callback through this function).
+ */
+static inline unsigned int __poll_portal_fast(struct qman_portal *p,
+ unsigned int poll_limit)
+{
+ const struct qm_dqrr_entry *dq;
+ struct qman_fq *fq;
+ enum qman_cb_dqrr_result res;
+ unsigned int limit = 0;
+
+loop:
+ qm_dqrr_pvb_update(&p->p);
+ dq = qm_dqrr_current(&p->p);
+ if (!dq)
+ goto done;
+ if (dq->stat & QM_DQRR_STAT_UNSCHEDULED) {
+ /* VDQCR: don't trust contextB as the FQ may have been
+ * configured for h/w consumption and we're draining it
+ * post-retirement. */
+ fq = p->vdqcr_owned;
+ /* We only set QMAN_FQ_STATE_NE when retiring, so we only need
+ * to check for clearing it when doing volatile dequeues. It's
+ * one less thing to check in the critical path (SDQCR). */
+ if (dq->stat & QM_DQRR_STAT_FQ_EMPTY)
+ fq_clear(fq, QMAN_FQ_STATE_NE);
+ /* this is duplicated from the SDQCR code, but we have stuff to
+ * do before *and* after this callback, and we don't want
+ * multiple if()s in the critical path (SDQCR). */
+ res = fq->cb.dqrr(p, fq, dq);
+ if (res == qman_cb_dqrr_stop)
+ goto done;
+ /* Check for VDQCR completion */
+ if (dq->stat & QM_DQRR_STAT_DQCR_EXPIRED)
+ clear_vdqcr(p, fq);
+ } else {
+ /* SDQCR: contextB points to the FQ */
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+ fq = get_fq_table_entry(dq->contextB);
+#else
+ fq = (void *)(uintptr_t)dq->contextB;
+#endif
+ /* Now let the callback do its stuff */
+ res = fq->cb.dqrr(p, fq, dq);
+ /* The callback can request that we exit without consuming this
+ * entry nor advancing; */
+ if (res == qman_cb_dqrr_stop)
+ goto done;
+ }
+ /* Interpret 'dq' from a driver perspective. */
+ /* Parking isn't possible unless HELDACTIVE was set. NB,
+ * FORCEELIGIBLE implies HELDACTIVE, so we only need to
+ * check for HELDACTIVE to cover both. */
+ DPA_ASSERT((dq->stat & QM_DQRR_STAT_FQ_HELDACTIVE) ||
+ (res != qman_cb_dqrr_park));
+ /* Defer just means "skip it, I'll consume it myself later on" */
+ if (res != qman_cb_dqrr_defer)
+ qm_dqrr_cdc_consume_1ptr(&p->p, dq, (res == qman_cb_dqrr_park));
+ /* Move forward */
+ qm_dqrr_next(&p->p);
+ /* Entry processed and consumed, increment our counter. The callback can
+ * request that we exit after consuming the entry, and we also exit if
+ * we reach our processing limit, so loop back only if neither of these
+ * conditions is met. */
+ if ((++limit < poll_limit) && (res != qman_cb_dqrr_consume_stop))
+ goto loop;
+done:
+ return limit;
+}
+
+u32 qman_irqsource_get(void)
+{
+ /* "irqsource" and "poll" APIs mustn't redirect when sharing, they
+ * should shut the user out if they are not the primary CPU hosting the
+ * portal. That's why we use the "raw" interface. */
+ struct qman_portal *p = get_raw_affine_portal();
+ u32 ret = p->irq_sources & QM_PIRQ_VISIBLE;
+ put_affine_portal();
+ return ret;
+}
+EXPORT_SYMBOL(qman_irqsource_get);
+
+int qman_p_irqsource_add(struct qman_portal *p, u32 bits __maybe_unused)
+{
+ __maybe_unused unsigned long irqflags;
+#ifdef CONFIG_FSL_DPA_PORTAL_SHARE
+ if (p->sharing_redirect)
+ return -EINVAL;
+ else
+#endif
+ {
+ PORTAL_IRQ_LOCK(p, irqflags);
+ set_bits(bits & QM_PIRQ_VISIBLE, &p->irq_sources);
+ qm_isr_enable_write(&p->p, p->irq_sources);
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(qman_p_irqsource_add);
+
+int qman_irqsource_add(u32 bits __maybe_unused)
+{
+ struct qman_portal *p = get_raw_affine_portal();
+ int ret;
+ ret = qman_p_irqsource_add(p, bits);
+ put_affine_portal();
+ return ret;
+}
+EXPORT_SYMBOL(qman_irqsource_add);
+
+int qman_p_irqsource_remove(struct qman_portal *p, u32 bits)
+{
+ __maybe_unused unsigned long irqflags;
+ u32 ier;
+#ifdef CONFIG_FSL_DPA_PORTAL_SHARE
+ if (p->sharing_redirect) {
+ put_affine_portal();
+ return -EINVAL;
+ }
+#endif
+ /* Our interrupt handler only processes+clears status register bits that
+ * are in p->irq_sources. As we're trimming that mask, if one of them
+ * were to assert in the status register just before we remove it from
+ * the enable register, there would be an interrupt-storm when we
+ * release the IRQ lock. So we wait for the enable register update to
+ * take effect in h/w (by reading it back) and then clear all other bits
+ * in the status register. Ie. we clear them from ISR once it's certain
+ * IER won't allow them to reassert. */
+ PORTAL_IRQ_LOCK(p, irqflags);
+ bits &= QM_PIRQ_VISIBLE;
+ clear_bits(bits, &p->irq_sources);
+ qm_isr_enable_write(&p->p, p->irq_sources);
+ ier = qm_isr_enable_read(&p->p);
+ /* Using "~ier" (rather than "bits" or "~p->irq_sources") creates a
+ * data-dependency, ie. to protect against re-ordering. */
+ qm_isr_status_clear(&p->p, ~ier);
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ return 0;
+}
+EXPORT_SYMBOL(qman_p_irqsource_remove);
+
+int qman_irqsource_remove(u32 bits)
+{
+ struct qman_portal *p = get_raw_affine_portal();
+ int ret;
+ ret = qman_p_irqsource_remove(p, bits);
+ put_affine_portal();
+ return ret;
+}
+EXPORT_SYMBOL(qman_irqsource_remove);
+
+const cpumask_t *qman_affine_cpus(void)
+{
+ return &affine_mask;
+}
+EXPORT_SYMBOL(qman_affine_cpus);
+
+u16 qman_affine_channel(int cpu)
+{
+ if (cpu < 0) {
+ struct qman_portal *portal = get_raw_affine_portal();
+#ifdef CONFIG_FSL_DPA_PORTAL_SHARE
+ BUG_ON(portal->sharing_redirect);
+#endif
+ cpu = portal->config->public_cfg.cpu;
+ put_affine_portal();
+ }
+ BUG_ON(!cpumask_test_cpu(cpu, &affine_mask));
+ return affine_channels[cpu];
+}
+EXPORT_SYMBOL(qman_affine_channel);
+
+void *qman_get_affine_portal(int cpu)
+{
+ return affine_portals[cpu];
+}
+EXPORT_SYMBOL(qman_get_affine_portal);
+
+int qman_p_poll_dqrr(struct qman_portal *p, unsigned int limit)
+{
+ int ret;
+
+#ifdef CONFIG_FSL_DPA_PORTAL_SHARE
+ if (unlikely(p->sharing_redirect))
+ ret = -EINVAL;
+ else
+#endif
+ {
+ BUG_ON(p->irq_sources & QM_PIRQ_DQRI);
+ ret = __poll_portal_fast(p, limit);
+ }
+ return ret;
+}
+EXPORT_SYMBOL(qman_p_poll_dqrr);
+
+int qman_poll_dqrr(unsigned int limit)
+{
+ struct qman_portal *p = get_poll_portal();
+ int ret;
+ ret = qman_p_poll_dqrr(p, limit);
+ put_poll_portal();
+ return ret;
+}
+EXPORT_SYMBOL(qman_poll_dqrr);
+
+u32 qman_p_poll_slow(struct qman_portal *p)
+{
+ u32 ret;
+#ifdef CONFIG_FSL_DPA_PORTAL_SHARE
+ if (unlikely(p->sharing_redirect))
+ ret = (u32)-1;
+ else
+#endif
+ {
+ u32 is = qm_isr_status_read(&p->p) & ~p->irq_sources;
+ ret = __poll_portal_slow(p, is);
+ qm_isr_status_clear(&p->p, ret);
+ }
+ return ret;
+}
+EXPORT_SYMBOL(qman_p_poll_slow);
+
+u32 qman_poll_slow(void)
+{
+ struct qman_portal *p = get_poll_portal();
+ u32 ret;
+ ret = qman_p_poll_slow(p);
+ put_poll_portal();
+ return ret;
+}
+EXPORT_SYMBOL(qman_poll_slow);
+
+/* Legacy wrapper */
+void qman_p_poll(struct qman_portal *p)
+{
+#ifdef CONFIG_FSL_DPA_PORTAL_SHARE
+ if (unlikely(p->sharing_redirect))
+ return;
+#endif
+ if ((~p->irq_sources) & QM_PIRQ_SLOW) {
+ if (!(p->slowpoll--)) {
+ u32 is = qm_isr_status_read(&p->p) & ~p->irq_sources;
+ u32 active = __poll_portal_slow(p, is);
+ if (active) {
+ qm_isr_status_clear(&p->p, active);
+ p->slowpoll = SLOW_POLL_BUSY;
+ } else
+ p->slowpoll = SLOW_POLL_IDLE;
+ }
+ }
+ if ((~p->irq_sources) & QM_PIRQ_DQRI)
+ __poll_portal_fast(p, CONFIG_FSL_QMAN_POLL_LIMIT);
+}
+EXPORT_SYMBOL(qman_p_poll);
+
+void qman_poll(void)
+{
+ struct qman_portal *p = get_poll_portal();
+ qman_p_poll(p);
+ put_poll_portal();
+}
+EXPORT_SYMBOL(qman_poll);
+
+void qman_p_stop_dequeues(struct qman_portal *p)
+{
+ qman_stop_dequeues_ex(p);
+}
+EXPORT_SYMBOL(qman_p_stop_dequeues);
+
+void qman_stop_dequeues(void)
+{
+ struct qman_portal *p = get_affine_portal();
+ qman_p_stop_dequeues(p);
+ put_affine_portal();
+}
+EXPORT_SYMBOL(qman_stop_dequeues);
+
+void qman_p_start_dequeues(struct qman_portal *p)
+{
+ unsigned long irqflags __maybe_unused;
+ PORTAL_IRQ_LOCK(p, irqflags);
+ DPA_ASSERT(p->dqrr_disable_ref > 0);
+ if (!(--p->dqrr_disable_ref))
+ qm_dqrr_set_maxfill(&p->p, DQRR_MAXFILL);
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+}
+EXPORT_SYMBOL(qman_p_start_dequeues);
+
+void qman_start_dequeues(void)
+{
+ struct qman_portal *p = get_affine_portal();
+ qman_p_start_dequeues(p);
+ put_affine_portal();
+}
+EXPORT_SYMBOL(qman_start_dequeues);
+
+void qman_p_static_dequeue_add(struct qman_portal *p, u32 pools)
+{
+ unsigned long irqflags __maybe_unused;
+ PORTAL_IRQ_LOCK(p, irqflags);
+ pools &= p->config->public_cfg.pools;
+ p->sdqcr |= pools;
+ qm_dqrr_sdqcr_set(&p->p, p->sdqcr);
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+}
+EXPORT_SYMBOL(qman_p_static_dequeue_add);
+
+void qman_static_dequeue_add(u32 pools)
+{
+ struct qman_portal *p = get_affine_portal();
+ qman_p_static_dequeue_add(p, pools);
+ put_affine_portal();
+}
+EXPORT_SYMBOL(qman_static_dequeue_add);
+
+void qman_p_static_dequeue_del(struct qman_portal *p, u32 pools)
+{
+ unsigned long irqflags __maybe_unused;
+ PORTAL_IRQ_LOCK(p, irqflags);
+ pools &= p->config->public_cfg.pools;
+ p->sdqcr &= ~pools;
+ qm_dqrr_sdqcr_set(&p->p, p->sdqcr);
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+}
+EXPORT_SYMBOL(qman_p_static_dequeue_del);
+
+void qman_static_dequeue_del(u32 pools)
+{
+ struct qman_portal *p = get_affine_portal();
+ qman_p_static_dequeue_del(p, pools);
+ put_affine_portal();
+}
+EXPORT_SYMBOL(qman_static_dequeue_del);
+
+u32 qman_p_static_dequeue_get(struct qman_portal *p)
+{
+ return p->sdqcr;
+}
+EXPORT_SYMBOL(qman_p_static_dequeue_get);
+
+u32 qman_static_dequeue_get(void)
+{
+ struct qman_portal *p = get_affine_portal();
+ u32 ret = qman_p_static_dequeue_get(p);
+ put_affine_portal();
+ return ret;
+}
+EXPORT_SYMBOL(qman_static_dequeue_get);
+
+void qman_p_dca(struct qman_portal *p, struct qm_dqrr_entry *dq,
+ int park_request)
+{
+ qm_dqrr_cdc_consume_1ptr(&p->p, dq, park_request);
+}
+EXPORT_SYMBOL(qman_p_dca);
+
+void qman_dca(struct qm_dqrr_entry *dq, int park_request)
+{
+ struct qman_portal *p = get_affine_portal();
+ qman_p_dca(p, dq, park_request);
+ put_affine_portal();
+}
+EXPORT_SYMBOL(qman_dca);
+
+/*******************/
+/* Frame queue API */
+/*******************/
+
+static const char *mcr_result_str(u8 result)
+{
+ switch (result) {
+ case QM_MCR_RESULT_NULL:
+ return "QM_MCR_RESULT_NULL";
+ case QM_MCR_RESULT_OK:
+ return "QM_MCR_RESULT_OK";
+ case QM_MCR_RESULT_ERR_FQID:
+ return "QM_MCR_RESULT_ERR_FQID";
+ case QM_MCR_RESULT_ERR_FQSTATE:
+ return "QM_MCR_RESULT_ERR_FQSTATE";
+ case QM_MCR_RESULT_ERR_NOTEMPTY:
+ return "QM_MCR_RESULT_ERR_NOTEMPTY";
+ case QM_MCR_RESULT_PENDING:
+ return "QM_MCR_RESULT_PENDING";
+ case QM_MCR_RESULT_ERR_BADCOMMAND:
+ return "QM_MCR_RESULT_ERR_BADCOMMAND";
+ }
+ return "<unknown MCR result>";
+}
+
+int qman_create_fq(u32 fqid, u32 flags, struct qman_fq *fq)
+{
+ struct qm_fqd fqd;
+ struct qm_mcr_queryfq_np np;
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p;
+ unsigned long irqflags __maybe_unused;
+
+ if (flags & QMAN_FQ_FLAG_DYNAMIC_FQID) {
+ int ret = qman_alloc_fqid(&fqid);
+ if (ret)
+ return ret;
+ }
+ spin_lock_init(&fq->fqlock);
+ fq->fqid = fqid;
+ fq->flags = flags;
+ fq->state = qman_fq_state_oos;
+ fq->cgr_groupid = 0;
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+ if (unlikely(find_empty_fq_table_entry(&fq->key, fq)))
+ return -ENOMEM;
+#endif
+ if (!(flags & QMAN_FQ_FLAG_AS_IS) || (flags & QMAN_FQ_FLAG_NO_MODIFY))
+ return 0;
+ /* Everything else is AS_IS support */
+ p = get_affine_portal();
+ PORTAL_IRQ_LOCK(p, irqflags);
+ mcc = qm_mc_start(&p->p);
+ mcc->queryfq.fqid = fqid;
+ qm_mc_commit(&p->p, QM_MCC_VERB_QUERYFQ);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYFQ);
+ if (mcr->result != QM_MCR_RESULT_OK) {
+ pr_err("QUERYFQ failed: %s\n", mcr_result_str(mcr->result));
+ goto err;
+ }
+ fqd = mcr->queryfq.fqd;
+ mcc = qm_mc_start(&p->p);
+ mcc->queryfq_np.fqid = fqid;
+ qm_mc_commit(&p->p, QM_MCC_VERB_QUERYFQ_NP);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYFQ_NP);
+ if (mcr->result != QM_MCR_RESULT_OK) {
+ pr_err("QUERYFQ_NP failed: %s\n", mcr_result_str(mcr->result));
+ goto err;
+ }
+ np = mcr->queryfq_np;
+ /* Phew, have queryfq and queryfq_np results, stitch together
+ * the FQ object from those. */
+ fq->cgr_groupid = fqd.cgid;
+ switch (np.state & QM_MCR_NP_STATE_MASK) {
+ case QM_MCR_NP_STATE_OOS:
+ break;
+ case QM_MCR_NP_STATE_RETIRED:
+ fq->state = qman_fq_state_retired;
+ if (np.frm_cnt)
+ fq_set(fq, QMAN_FQ_STATE_NE);
+ break;
+ case QM_MCR_NP_STATE_TEN_SCHED:
+ case QM_MCR_NP_STATE_TRU_SCHED:
+ case QM_MCR_NP_STATE_ACTIVE:
+ fq->state = qman_fq_state_sched;
+ if (np.state & QM_MCR_NP_STATE_R)
+ fq_set(fq, QMAN_FQ_STATE_CHANGING);
+ break;
+ case QM_MCR_NP_STATE_PARKED:
+ fq->state = qman_fq_state_parked;
+ break;
+ default:
+ DPA_ASSERT(NULL == "invalid FQ state");
+ }
+ if (fqd.fq_ctrl & QM_FQCTRL_CGE)
+ fq->state |= QMAN_FQ_STATE_CGR_EN;
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ return 0;
+err:
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ if (flags & QMAN_FQ_FLAG_DYNAMIC_FQID)
+ qman_release_fqid(fqid);
+ return -EIO;
+}
+EXPORT_SYMBOL(qman_create_fq);
+
+void qman_destroy_fq(struct qman_fq *fq, u32 flags __maybe_unused)
+{
+
+ /* We don't need to lock the FQ as it is a pre-condition that the FQ be
+ * quiesced. Instead, run some checks. */
+ switch (fq->state) {
+ case qman_fq_state_parked:
+ DPA_ASSERT(flags & QMAN_FQ_DESTROY_PARKED);
+ case qman_fq_state_oos:
+ if (fq_isset(fq, QMAN_FQ_FLAG_DYNAMIC_FQID))
+ qman_release_fqid(fq->fqid);
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+ clear_fq_table_entry(fq->key);
+#endif
+ return;
+ default:
+ break;
+ }
+ DPA_ASSERT(NULL == "qman_free_fq() on unquiesced FQ!");
+}
+EXPORT_SYMBOL(qman_destroy_fq);
+
+u32 qman_fq_fqid(struct qman_fq *fq)
+{
+ return fq->fqid;
+}
+EXPORT_SYMBOL(qman_fq_fqid);
+
+void qman_fq_state(struct qman_fq *fq, enum qman_fq_state *state, u32 *flags)
+{
+ if (state)
+ *state = fq->state;
+ if (flags)
+ *flags = fq->flags;
+}
+EXPORT_SYMBOL(qman_fq_state);
+
+int qman_init_fq(struct qman_fq *fq, u32 flags, struct qm_mcc_initfq *opts)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p;
+ unsigned long irqflags __maybe_unused;
+ u8 res, myverb = (flags & QMAN_INITFQ_FLAG_SCHED) ?
+ QM_MCC_VERB_INITFQ_SCHED : QM_MCC_VERB_INITFQ_PARKED;
+
+ if ((fq->state != qman_fq_state_oos) &&
+ (fq->state != qman_fq_state_parked))
+ return -EINVAL;
+#ifdef CONFIG_FSL_DPA_CHECKING
+ if (unlikely(fq_isset(fq, QMAN_FQ_FLAG_NO_MODIFY)))
+ return -EINVAL;
+#endif
+ if (opts && (opts->we_mask & QM_INITFQ_WE_OAC)) {
+ /* And can't be set at the same time as TDTHRESH */
+ if (opts->we_mask & QM_INITFQ_WE_TDTHRESH)
+ return -EINVAL;
+ }
+ /* Issue an INITFQ_[PARKED|SCHED] management command */
+ p = get_affine_portal();
+ PORTAL_IRQ_LOCK(p, irqflags);
+ FQLOCK(fq);
+ if (unlikely((fq_isset(fq, QMAN_FQ_STATE_CHANGING)) ||
+ ((fq->state != qman_fq_state_oos) &&
+ (fq->state != qman_fq_state_parked)))) {
+ FQUNLOCK(fq);
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ return -EBUSY;
+ }
+ mcc = qm_mc_start(&p->p);
+ if (opts)
+ mcc->initfq = *opts;
+ mcc->initfq.fqid = fq->fqid;
+ mcc->initfq.count = 0;
+ /* If the FQ does *not* have the TO_DCPORTAL flag, contextB is set as a
+ * demux pointer. Otherwise, the caller-provided value is allowed to
+ * stand, don't overwrite it. */
+ if (fq_isclear(fq, QMAN_FQ_FLAG_TO_DCPORTAL)) {
+ dma_addr_t phys_fq;
+ mcc->initfq.we_mask |= QM_INITFQ_WE_CONTEXTB;
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+ mcc->initfq.fqd.context_b = fq->key;
+#else
+ mcc->initfq.fqd.context_b = (u32)(uintptr_t)fq;
+#endif
+ /* and the physical address - NB, if the user wasn't trying to
+ * set CONTEXTA, clear the stashing settings. */
+ if (!(mcc->initfq.we_mask & QM_INITFQ_WE_CONTEXTA)) {
+ mcc->initfq.we_mask |= QM_INITFQ_WE_CONTEXTA;
+ memset(&mcc->initfq.fqd.context_a, 0,
+ sizeof(mcc->initfq.fqd.context_a));
+ } else {
+ phys_fq = dma_map_single(&p->pdev->dev, fq, sizeof(*fq),
+ DMA_TO_DEVICE);
+ qm_fqd_stashing_set64(&mcc->initfq.fqd, phys_fq);
+ }
+ }
+ if (flags & QMAN_INITFQ_FLAG_LOCAL) {
+ mcc->initfq.fqd.dest.channel = p->config->public_cfg.channel;
+ if (!(mcc->initfq.we_mask & QM_INITFQ_WE_DESTWQ)) {
+ mcc->initfq.we_mask |= QM_INITFQ_WE_DESTWQ;
+ mcc->initfq.fqd.dest.wq = 4;
+ }
+ }
+ qm_mc_commit(&p->p, myverb);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == myverb);
+ res = mcr->result;
+ if (res != QM_MCR_RESULT_OK) {
+ FQUNLOCK(fq);
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ return -EIO;
+ }
+ if (opts) {
+ if (opts->we_mask & QM_INITFQ_WE_FQCTRL) {
+ if (opts->fqd.fq_ctrl & QM_FQCTRL_CGE)
+ fq_set(fq, QMAN_FQ_STATE_CGR_EN);
+ else
+ fq_clear(fq, QMAN_FQ_STATE_CGR_EN);
+ }
+ if (opts->we_mask & QM_INITFQ_WE_CGID)
+ fq->cgr_groupid = opts->fqd.cgid;
+ }
+ fq->state = (flags & QMAN_INITFQ_FLAG_SCHED) ?
+ qman_fq_state_sched : qman_fq_state_parked;
+ FQUNLOCK(fq);
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ return 0;
+}
+EXPORT_SYMBOL(qman_init_fq);
+
+int qman_schedule_fq(struct qman_fq *fq)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p;
+ unsigned long irqflags __maybe_unused;
+ int ret = 0;
+ u8 res;
+
+ if (fq->state != qman_fq_state_parked)
+ return -EINVAL;
+#ifdef CONFIG_FSL_DPA_CHECKING
+ if (unlikely(fq_isset(fq, QMAN_FQ_FLAG_NO_MODIFY)))
+ return -EINVAL;
+#endif
+ /* Issue a ALTERFQ_SCHED management command */
+ p = get_affine_portal();
+ PORTAL_IRQ_LOCK(p, irqflags);
+ FQLOCK(fq);
+ if (unlikely((fq_isset(fq, QMAN_FQ_STATE_CHANGING)) ||
+ (fq->state != qman_fq_state_parked))) {
+ ret = -EBUSY;
+ goto out;
+ }
+ mcc = qm_mc_start(&p->p);
+ mcc->alterfq.fqid = fq->fqid;
+ qm_mc_commit(&p->p, QM_MCC_VERB_ALTER_SCHED);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_ALTER_SCHED);
+ res = mcr->result;
+ if (res != QM_MCR_RESULT_OK) {
+ ret = -EIO;
+ goto out;
+ }
+ fq->state = qman_fq_state_sched;
+out:
+ FQUNLOCK(fq);
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ return ret;
+}
+EXPORT_SYMBOL(qman_schedule_fq);
+
+int qman_retire_fq(struct qman_fq *fq, u32 *flags)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p;
+ unsigned long irqflags __maybe_unused;
+ int rval;
+ u8 res;
+
+ if ((fq->state != qman_fq_state_parked) &&
+ (fq->state != qman_fq_state_sched))
+ return -EINVAL;
+#ifdef CONFIG_FSL_DPA_CHECKING
+ if (unlikely(fq_isset(fq, QMAN_FQ_FLAG_NO_MODIFY)))
+ return -EINVAL;
+#endif
+ p = get_affine_portal();
+ PORTAL_IRQ_LOCK(p, irqflags);
+ FQLOCK(fq);
+ if (unlikely((fq_isset(fq, QMAN_FQ_STATE_CHANGING)) ||
+ (fq->state == qman_fq_state_retired) ||
+ (fq->state == qman_fq_state_oos))) {
+ rval = -EBUSY;
+ goto out;
+ }
+ rval = table_push_fq(p, fq);
+ if (rval)
+ goto out;
+ mcc = qm_mc_start(&p->p);
+ mcc->alterfq.fqid = fq->fqid;
+ qm_mc_commit(&p->p, QM_MCC_VERB_ALTER_RETIRE);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_ALTER_RETIRE);
+ res = mcr->result;
+ /* "Elegant" would be to treat OK/PENDING the same way; set CHANGING,
+ * and defer the flags until FQRNI or FQRN (respectively) show up. But
+ * "Friendly" is to process OK immediately, and not set CHANGING. We do
+ * friendly, otherwise the caller doesn't necessarily have a fully
+ * "retired" FQ on return even if the retirement was immediate. However
+ * this does mean some code duplication between here and
+ * fq_state_change(). */
+ if (likely(res == QM_MCR_RESULT_OK)) {
+ rval = 0;
+ /* Process 'fq' right away, we'll ignore FQRNI */
+ if (mcr->alterfq.fqs & QM_MCR_FQS_NOTEMPTY)
+ fq_set(fq, QMAN_FQ_STATE_NE);
+ if (mcr->alterfq.fqs & QM_MCR_FQS_ORLPRESENT)
+ fq_set(fq, QMAN_FQ_STATE_ORL);
+ else
+ table_del_fq(p, fq);
+ if (flags)
+ *flags = fq->flags;
+ fq->state = qman_fq_state_retired;
+ if (fq->cb.fqs) {
+ /* Another issue with supporting "immediate" retirement
+ * is that we're forced to drop FQRNIs, because by the
+ * time they're seen it may already be "too late" (the
+ * fq may have been OOS'd and free()'d already). But if
+ * the upper layer wants a callback whether it's
+ * immediate or not, we have to fake a "MR" entry to
+ * look like an FQRNI... */
+ struct qm_mr_entry msg;
+ msg.verb = QM_MR_VERB_FQRNI;
+ msg.fq.fqs = mcr->alterfq.fqs;
+ msg.fq.fqid = fq->fqid;
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+ msg.fq.contextB = fq->key;
+#else
+ msg.fq.contextB = (u32)(uintptr_t)fq;
+#endif
+ fq->cb.fqs(p, fq, &msg);
+ }
+ } else if (res == QM_MCR_RESULT_PENDING) {
+ rval = 1;
+ fq_set(fq, QMAN_FQ_STATE_CHANGING);
+ } else {
+ rval = -EIO;
+ table_del_fq(p, fq);
+ }
+out:
+ FQUNLOCK(fq);
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ return rval;
+}
+EXPORT_SYMBOL(qman_retire_fq);
+
+int qman_oos_fq(struct qman_fq *fq)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p;
+ unsigned long irqflags __maybe_unused;
+ int ret = 0;
+ u8 res;
+
+ if (fq->state != qman_fq_state_retired)
+ return -EINVAL;
+#ifdef CONFIG_FSL_DPA_CHECKING
+ if (unlikely(fq_isset(fq, QMAN_FQ_FLAG_NO_MODIFY)))
+ return -EINVAL;
+#endif
+ p = get_affine_portal();
+ PORTAL_IRQ_LOCK(p, irqflags);
+ FQLOCK(fq);
+ if (unlikely((fq_isset(fq, QMAN_FQ_STATE_BLOCKOOS)) ||
+ (fq->state != qman_fq_state_retired))) {
+ ret = -EBUSY;
+ goto out;
+ }
+ mcc = qm_mc_start(&p->p);
+ mcc->alterfq.fqid = fq->fqid;
+ qm_mc_commit(&p->p, QM_MCC_VERB_ALTER_OOS);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_ALTER_OOS);
+ res = mcr->result;
+ if (res != QM_MCR_RESULT_OK) {
+ ret = -EIO;
+ goto out;
+ }
+ fq->state = qman_fq_state_oos;
+out:
+ FQUNLOCK(fq);
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ return ret;
+}
+EXPORT_SYMBOL(qman_oos_fq);
+
+int qman_fq_flow_control(struct qman_fq *fq, int xon)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p;
+ unsigned long irqflags __maybe_unused;
+ int ret = 0;
+ u8 res;
+ u8 myverb;
+
+ if ((fq->state == qman_fq_state_oos) ||
+ (fq->state == qman_fq_state_retired) ||
+ (fq->state == qman_fq_state_parked))
+ return -EINVAL;
+
+#ifdef CONFIG_FSL_DPA_CHECKING
+ if (unlikely(fq_isset(fq, QMAN_FQ_FLAG_NO_MODIFY)))
+ return -EINVAL;
+#endif
+ /* Issue a ALTER_FQXON or ALTER_FQXOFF management command */
+ p = get_affine_portal();
+ PORTAL_IRQ_LOCK(p, irqflags);
+ FQLOCK(fq);
+ if (unlikely((fq_isset(fq, QMAN_FQ_STATE_CHANGING)) ||
+ (fq->state == qman_fq_state_parked) ||
+ (fq->state == qman_fq_state_oos) ||
+ (fq->state == qman_fq_state_retired))) {
+ ret = -EBUSY;
+ goto out;
+ }
+ mcc = qm_mc_start(&p->p);
+ mcc->alterfq.fqid = fq->fqid;
+ mcc->alterfq.count = 0;
+ myverb = xon ? QM_MCC_VERB_ALTER_FQXON : QM_MCC_VERB_ALTER_FQXOFF;
+
+ qm_mc_commit(&p->p, myverb);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == myverb);
+
+ res = mcr->result;
+ if (res != QM_MCR_RESULT_OK) {
+ ret = -EIO;
+ goto out;
+ }
+out:
+ FQUNLOCK(fq);
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ return ret;
+}
+EXPORT_SYMBOL(qman_fq_flow_control);
+
+int qman_query_fq(struct qman_fq *fq, struct qm_fqd *fqd)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p = get_affine_portal();
+ unsigned long irqflags __maybe_unused;
+ u8 res;
+
+ PORTAL_IRQ_LOCK(p, irqflags);
+ mcc = qm_mc_start(&p->p);
+ mcc->queryfq.fqid = fq->fqid;
+ qm_mc_commit(&p->p, QM_MCC_VERB_QUERYFQ);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_QUERYFQ);
+ res = mcr->result;
+ if (res == QM_MCR_RESULT_OK)
+ *fqd = mcr->queryfq.fqd;
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ if (res != QM_MCR_RESULT_OK)
+ return -EIO;
+ return 0;
+}
+EXPORT_SYMBOL(qman_query_fq);
+
+int qman_query_fq_np(struct qman_fq *fq, struct qm_mcr_queryfq_np *np)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p = get_affine_portal();
+ unsigned long irqflags __maybe_unused;
+ u8 res;
+
+ PORTAL_IRQ_LOCK(p, irqflags);
+ mcc = qm_mc_start(&p->p);
+ mcc->queryfq.fqid = fq->fqid;
+ qm_mc_commit(&p->p, QM_MCC_VERB_QUERYFQ_NP);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_QUERYFQ_NP);
+ res = mcr->result;
+ if (res == QM_MCR_RESULT_OK)
+ *np = mcr->queryfq_np;
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ if (res == QM_MCR_RESULT_ERR_FQID)
+ return -ERANGE;
+ else if (res != QM_MCR_RESULT_OK)
+ return -EIO;
+ return 0;
+}
+EXPORT_SYMBOL(qman_query_fq_np);
+
+int qman_query_wq(u8 query_dedicated, struct qm_mcr_querywq *wq)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p = get_affine_portal();
+ unsigned long irqflags __maybe_unused;
+ u8 res, myverb;
+
+ PORTAL_IRQ_LOCK(p, irqflags);
+ myverb = (query_dedicated) ? QM_MCR_VERB_QUERYWQ_DEDICATED :
+ QM_MCR_VERB_QUERYWQ;
+ mcc = qm_mc_start(&p->p);
+ mcc->querywq.channel.id = wq->channel.id;
+ qm_mc_commit(&p->p, myverb);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == myverb);
+ res = mcr->result;
+ if (res == QM_MCR_RESULT_OK)
+ *wq = mcr->querywq;
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ if (res != QM_MCR_RESULT_OK) {
+ pr_err("QUERYWQ failed: %s\n", mcr_result_str(res));
+ return -EIO;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(qman_query_wq);
+
+int qman_testwrite_cgr(struct qman_cgr *cgr, u64 i_bcnt,
+ struct qm_mcr_cgrtestwrite *result)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p = get_affine_portal();
+ unsigned long irqflags __maybe_unused;
+ u8 res;
+
+ PORTAL_IRQ_LOCK(p, irqflags);
+ mcc = qm_mc_start(&p->p);
+ mcc->cgrtestwrite.cgid = cgr->cgrid;
+ mcc->cgrtestwrite.i_bcnt_hi = (u8)(i_bcnt >> 32);
+ mcc->cgrtestwrite.i_bcnt_lo = (u32)i_bcnt;
+ qm_mc_commit(&p->p, QM_MCC_VERB_CGRTESTWRITE);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_CGRTESTWRITE);
+ res = mcr->result;
+ if (res == QM_MCR_RESULT_OK)
+ *result = mcr->cgrtestwrite;
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ if (res != QM_MCR_RESULT_OK) {
+ pr_err("CGR TEST WRITE failed: %s\n", mcr_result_str(res));
+ return -EIO;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(qman_testwrite_cgr);
+
+int qman_query_cgr(struct qman_cgr *cgr, struct qm_mcr_querycgr *cgrd)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p = get_affine_portal();
+ unsigned long irqflags __maybe_unused;
+ u8 res;
+
+ PORTAL_IRQ_LOCK(p, irqflags);
+ mcc = qm_mc_start(&p->p);
+ mcc->querycgr.cgid = cgr->cgrid;
+ qm_mc_commit(&p->p, QM_MCC_VERB_QUERYCGR);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCC_VERB_QUERYCGR);
+ res = mcr->result;
+ if (res == QM_MCR_RESULT_OK)
+ *cgrd = mcr->querycgr;
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ if (res != QM_MCR_RESULT_OK) {
+ pr_err("QUERY_CGR failed: %s\n", mcr_result_str(res));
+ return -EIO;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(qman_query_cgr);
+
+int qman_query_congestion(struct qm_mcr_querycongestion *congestion)
+{
+ struct qm_mc_result *mcr;
+ struct qman_portal *p = get_affine_portal();
+ unsigned long irqflags __maybe_unused;
+ u8 res;
+
+ PORTAL_IRQ_LOCK(p, irqflags);
+ qm_mc_start(&p->p);
+ qm_mc_commit(&p->p, QM_MCC_VERB_QUERYCONGESTION);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) ==
+ QM_MCC_VERB_QUERYCONGESTION);
+ res = mcr->result;
+ if (res == QM_MCR_RESULT_OK)
+ *congestion = mcr->querycongestion;
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ if (res != QM_MCR_RESULT_OK) {
+ pr_err("QUERY_CONGESTION failed: %s\n", mcr_result_str(res));
+ return -EIO;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(qman_query_congestion);
+
+/* internal function used as a wait_event() expression */
+static int set_p_vdqcr(struct qman_portal *p, struct qman_fq *fq, u32 vdqcr)
+{
+ unsigned long irqflags __maybe_unused;
+ int ret = -EBUSY;
+ PORTAL_IRQ_LOCK(p, irqflags);
+ if (!p->vdqcr_owned) {
+ FQLOCK(fq);
+ if (fq_isset(fq, QMAN_FQ_STATE_VDQCR))
+ goto escape;
+ fq_set(fq, QMAN_FQ_STATE_VDQCR);
+ FQUNLOCK(fq);
+ p->vdqcr_owned = fq;
+ ret = 0;
+ }
+escape:
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ if (!ret)
+ qm_dqrr_vdqcr_set(&p->p, vdqcr);
+ return ret;
+}
+
+static int set_vdqcr(struct qman_portal **p, struct qman_fq *fq, u32 vdqcr)
+{
+ int ret;
+ *p = get_affine_portal();
+ ret = set_p_vdqcr(*p, fq, vdqcr);
+ put_affine_portal();
+ return ret;
+}
+
+#ifdef CONFIG_FSL_DPA_CAN_WAIT
+static int wait_p_vdqcr_start(struct qman_portal *p, struct qman_fq *fq,
+ u32 vdqcr, u32 flags)
+{
+ int ret = 0;
+ if (flags & QMAN_VOLATILE_FLAG_WAIT_INT)
+ ret = wait_event_interruptible(affine_queue,
+ !(ret = set_p_vdqcr(p, fq, vdqcr)));
+ else
+ wait_event(affine_queue, !(ret = set_p_vdqcr(p, fq, vdqcr)));
+ return ret;
+}
+
+static int wait_vdqcr_start(struct qman_portal **p, struct qman_fq *fq,
+ u32 vdqcr, u32 flags)
+{
+ int ret = 0;
+ if (flags & QMAN_VOLATILE_FLAG_WAIT_INT)
+ ret = wait_event_interruptible(affine_queue,
+ !(ret = set_vdqcr(p, fq, vdqcr)));
+ else
+ wait_event(affine_queue, !(ret = set_vdqcr(p, fq, vdqcr)));
+ return ret;
+}
+#endif
+
+int qman_p_volatile_dequeue(struct qman_portal *p, struct qman_fq *fq,
+ u32 flags __maybe_unused, u32 vdqcr)
+{
+ int ret;
+
+ if ((fq->state != qman_fq_state_parked) &&
+ (fq->state != qman_fq_state_retired))
+ return -EINVAL;
+ if (vdqcr & QM_VDQCR_FQID_MASK)
+ return -EINVAL;
+ if (fq_isset(fq, QMAN_FQ_STATE_VDQCR))
+ return -EBUSY;
+ vdqcr = (vdqcr & ~QM_VDQCR_FQID_MASK) | fq->fqid;
+#ifdef CONFIG_FSL_DPA_CAN_WAIT
+ if (flags & QMAN_VOLATILE_FLAG_WAIT)
+ ret = wait_p_vdqcr_start(p, fq, vdqcr, flags);
+ else
+#endif
+ ret = set_p_vdqcr(p, fq, vdqcr);
+ if (ret)
+ return ret;
+ /* VDQCR is set */
+#ifdef CONFIG_FSL_DPA_CAN_WAIT
+ if (flags & QMAN_VOLATILE_FLAG_FINISH) {
+ if (flags & QMAN_VOLATILE_FLAG_WAIT_INT)
+ /* NB: don't propagate any error - the caller wouldn't
+ * know whether the VDQCR was issued or not. A signal
+ * could arrive after returning anyway, so the caller
+ * can check signal_pending() if that's an issue. */
+ wait_event_interruptible(affine_queue,
+ !fq_isset(fq, QMAN_FQ_STATE_VDQCR));
+ else
+ wait_event(affine_queue,
+ !fq_isset(fq, QMAN_FQ_STATE_VDQCR));
+ }
+#endif
+ return 0;
+}
+EXPORT_SYMBOL(qman_p_volatile_dequeue);
+
+int qman_volatile_dequeue(struct qman_fq *fq, u32 flags __maybe_unused,
+ u32 vdqcr)
+{
+ struct qman_portal *p;
+ int ret;
+
+ if ((fq->state != qman_fq_state_parked) &&
+ (fq->state != qman_fq_state_retired))
+ return -EINVAL;
+ if (vdqcr & QM_VDQCR_FQID_MASK)
+ return -EINVAL;
+ if (fq_isset(fq, QMAN_FQ_STATE_VDQCR))
+ return -EBUSY;
+ vdqcr = (vdqcr & ~QM_VDQCR_FQID_MASK) | fq->fqid;
+#ifdef CONFIG_FSL_DPA_CAN_WAIT
+ if (flags & QMAN_VOLATILE_FLAG_WAIT)
+ ret = wait_vdqcr_start(&p, fq, vdqcr, flags);
+ else
+#endif
+ ret = set_vdqcr(&p, fq, vdqcr);
+ if (ret)
+ return ret;
+ /* VDQCR is set */
+#ifdef CONFIG_FSL_DPA_CAN_WAIT
+ if (flags & QMAN_VOLATILE_FLAG_FINISH) {
+ if (flags & QMAN_VOLATILE_FLAG_WAIT_INT)
+ /* NB: don't propagate any error - the caller wouldn't
+ * know whether the VDQCR was issued or not. A signal
+ * could arrive after returning anyway, so the caller
+ * can check signal_pending() if that's an issue. */
+ wait_event_interruptible(affine_queue,
+ !fq_isset(fq, QMAN_FQ_STATE_VDQCR));
+ else
+ wait_event(affine_queue,
+ !fq_isset(fq, QMAN_FQ_STATE_VDQCR));
+ }
+#endif
+ return 0;
+}
+EXPORT_SYMBOL(qman_volatile_dequeue);
+
+static noinline void update_eqcr_ci(struct qman_portal *p, u8 avail)
+{
+ if (avail)
+ qm_eqcr_cce_prefetch(&p->p);
+ else
+ qm_eqcr_cce_update(&p->p);
+}
+
+int qman_eqcr_is_empty(void)
+{
+ unsigned long irqflags __maybe_unused;
+ struct qman_portal *p = get_affine_portal();
+ u8 avail;
+
+ PORTAL_IRQ_LOCK(p, irqflags);
+ update_eqcr_ci(p, 0);
+ avail = qm_eqcr_get_fill(&p->p);
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ return avail == 0;
+}
+EXPORT_SYMBOL(qman_eqcr_is_empty);
+
+void qman_set_dc_ern(qman_cb_dc_ern handler, int affine)
+{
+ if (affine) {
+ unsigned long irqflags __maybe_unused;
+ struct qman_portal *p = get_affine_portal();
+ PORTAL_IRQ_LOCK(p, irqflags);
+ p->cb_dc_ern = handler;
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ } else
+ cb_dc_ern = handler;
+}
+EXPORT_SYMBOL(qman_set_dc_ern);
+
+static inline struct qm_eqcr_entry *try_p_eq_start(struct qman_portal *p,
+ unsigned long *irqflags __maybe_unused,
+ struct qman_fq *fq,
+ const struct qm_fd *fd,
+ u32 flags)
+{
+ struct qm_eqcr_entry *eq;
+ u8 avail;
+ PORTAL_IRQ_LOCK(p, (*irqflags));
+#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC
+ if (unlikely((flags & QMAN_ENQUEUE_FLAG_WAIT) &&
+ (flags & QMAN_ENQUEUE_FLAG_WAIT_SYNC))) {
+ if (p->eqci_owned) {
+ PORTAL_IRQ_UNLOCK(p, (*irqflags));
+ return NULL;
+ }
+ p->eqci_owned = fq;
+ }
+#endif
+ if (p->use_eqcr_ci_stashing) {
+ /*
+ * The stashing case is easy, only update if we need to in
+ * order to try and liberate ring entries.
+ */
+ eq = qm_eqcr_start_stash(&p->p);
+ } else {
+ /*
+ * The non-stashing case is harder, need to prefetch ahead of
+ * time.
+ */
+ avail = qm_eqcr_get_avail(&p->p);
+ if (avail < 2)
+ update_eqcr_ci(p, avail);
+ eq = qm_eqcr_start_no_stash(&p->p);
+ }
+
+ if (unlikely(!eq)) {
+#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC
+ if (unlikely((flags & QMAN_ENQUEUE_FLAG_WAIT) &&
+ (flags & QMAN_ENQUEUE_FLAG_WAIT_SYNC)))
+ p->eqci_owned = NULL;
+#endif
+ PORTAL_IRQ_UNLOCK(p, (*irqflags));
+ return NULL;
+ }
+ if (flags & QMAN_ENQUEUE_FLAG_DCA)
+ eq->dca = QM_EQCR_DCA_ENABLE |
+ ((flags & QMAN_ENQUEUE_FLAG_DCA_PARK) ?
+ QM_EQCR_DCA_PARK : 0) |
+ ((flags >> 8) & QM_EQCR_DCA_IDXMASK);
+ eq->fqid = fq->fqid;
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+ eq->tag = fq->key;
+#else
+ eq->tag = (u32)(uintptr_t)fq;
+#endif
+ eq->fd = *fd;
+ return eq;
+}
+
+static inline struct qm_eqcr_entry *try_eq_start(struct qman_portal **p,
+ unsigned long *irqflags __maybe_unused,
+ struct qman_fq *fq,
+ const struct qm_fd *fd,
+ u32 flags)
+{
+ struct qm_eqcr_entry *eq;
+ *p = get_affine_portal();
+ eq = try_p_eq_start(*p, irqflags, fq, fd, flags);
+ if (!eq)
+ put_affine_portal();
+ return eq;
+}
+
+#ifdef CONFIG_FSL_DPA_CAN_WAIT
+static noinline struct qm_eqcr_entry *__wait_eq_start(struct qman_portal **p,
+ unsigned long *irqflags __maybe_unused,
+ struct qman_fq *fq,
+ const struct qm_fd *fd,
+ u32 flags)
+{
+ struct qm_eqcr_entry *eq = try_eq_start(p, irqflags, fq, fd, flags);
+ if (!eq)
+ qm_eqcr_set_ithresh(&(*p)->p, EQCR_ITHRESH);
+ return eq;
+}
+static noinline struct qm_eqcr_entry *wait_eq_start(struct qman_portal **p,
+ unsigned long *irqflags __maybe_unused,
+ struct qman_fq *fq,
+ const struct qm_fd *fd,
+ u32 flags)
+{
+ struct qm_eqcr_entry *eq;
+ if (flags & QMAN_ENQUEUE_FLAG_WAIT_INT)
+ wait_event_interruptible(affine_queue,
+ (eq = __wait_eq_start(p, irqflags, fq, fd, flags)));
+ else
+ wait_event(affine_queue,
+ (eq = __wait_eq_start(p, irqflags, fq, fd, flags)));
+ return eq;
+}
+static noinline struct qm_eqcr_entry *__wait_p_eq_start(struct qman_portal *p,
+ unsigned long *irqflags __maybe_unused,
+ struct qman_fq *fq,
+ const struct qm_fd *fd,
+ u32 flags)
+{
+ struct qm_eqcr_entry *eq = try_p_eq_start(p, irqflags, fq, fd, flags);
+ if (!eq)
+ qm_eqcr_set_ithresh(&p->p, EQCR_ITHRESH);
+ return eq;
+}
+static noinline struct qm_eqcr_entry *wait_p_eq_start(struct qman_portal *p,
+ unsigned long *irqflags __maybe_unused,
+ struct qman_fq *fq,
+ const struct qm_fd *fd,
+ u32 flags)
+{
+ struct qm_eqcr_entry *eq;
+ if (flags & QMAN_ENQUEUE_FLAG_WAIT_INT)
+ wait_event_interruptible(affine_queue,
+ (eq = __wait_p_eq_start(p, irqflags, fq, fd, flags)));
+ else
+ wait_event(affine_queue,
+ (eq = __wait_p_eq_start(p, irqflags, fq, fd, flags)));
+ return eq;
+}
+#endif
+
+int qman_p_enqueue(struct qman_portal *p, struct qman_fq *fq,
+ const struct qm_fd *fd, u32 flags)
+{
+ struct qm_eqcr_entry *eq;
+ unsigned long irqflags __maybe_unused;
+
+#ifdef CONFIG_FSL_DPA_CAN_WAIT
+ if (flags & QMAN_ENQUEUE_FLAG_WAIT)
+ eq = wait_p_eq_start(p, &irqflags, fq, fd, flags);
+ else
+#endif
+ eq = try_p_eq_start(p, &irqflags, fq, fd, flags);
+ if (!eq)
+ return -EBUSY;
+ /* Note: QM_EQCR_VERB_INTERRUPT == QMAN_ENQUEUE_FLAG_WAIT_SYNC */
+ qm_eqcr_pvb_commit(&p->p, QM_EQCR_VERB_CMD_ENQUEUE |
+ (flags & (QM_EQCR_VERB_COLOUR_MASK | QM_EQCR_VERB_INTERRUPT)));
+ /* Factor the below out, it's used from qman_enqueue_orp() too */
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC
+ if (unlikely((flags & QMAN_ENQUEUE_FLAG_WAIT) &&
+ (flags & QMAN_ENQUEUE_FLAG_WAIT_SYNC))) {
+ if (flags & QMAN_ENQUEUE_FLAG_WAIT_INT)
+ wait_event_interruptible(affine_queue,
+ (p->eqci_owned != fq));
+ else
+ wait_event(affine_queue, (p->eqci_owned != fq));
+ }
+#endif
+ return 0;
+}
+EXPORT_SYMBOL(qman_p_enqueue);
+
+int qman_enqueue(struct qman_fq *fq, const struct qm_fd *fd, u32 flags)
+{
+ struct qman_portal *p;
+ struct qm_eqcr_entry *eq;
+ unsigned long irqflags __maybe_unused;
+
+#ifdef CONFIG_FSL_DPA_CAN_WAIT
+ if (flags & QMAN_ENQUEUE_FLAG_WAIT)
+ eq = wait_eq_start(&p, &irqflags, fq, fd, flags);
+ else
+#endif
+ eq = try_eq_start(&p, &irqflags, fq, fd, flags);
+ if (!eq)
+ return -EBUSY;
+ /* Note: QM_EQCR_VERB_INTERRUPT == QMAN_ENQUEUE_FLAG_WAIT_SYNC */
+ qm_eqcr_pvb_commit(&p->p, QM_EQCR_VERB_CMD_ENQUEUE |
+ (flags & (QM_EQCR_VERB_COLOUR_MASK | QM_EQCR_VERB_INTERRUPT)));
+ /* Factor the below out, it's used from qman_enqueue_orp() too */
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC
+ if (unlikely((flags & QMAN_ENQUEUE_FLAG_WAIT) &&
+ (flags & QMAN_ENQUEUE_FLAG_WAIT_SYNC))) {
+ if (flags & QMAN_ENQUEUE_FLAG_WAIT_INT)
+ wait_event_interruptible(affine_queue,
+ (p->eqci_owned != fq));
+ else
+ wait_event(affine_queue, (p->eqci_owned != fq));
+ }
+#endif
+ return 0;
+}
+EXPORT_SYMBOL(qman_enqueue);
+
+int qman_p_enqueue_orp(struct qman_portal *p, struct qman_fq *fq,
+ const struct qm_fd *fd, u32 flags,
+ struct qman_fq *orp, u16 orp_seqnum)
+{
+ struct qm_eqcr_entry *eq;
+ unsigned long irqflags __maybe_unused;
+
+#ifdef CONFIG_FSL_DPA_CAN_WAIT
+ if (flags & QMAN_ENQUEUE_FLAG_WAIT)
+ eq = wait_p_eq_start(p, &irqflags, fq, fd, flags);
+ else
+#endif
+ eq = try_p_eq_start(p, &irqflags, fq, fd, flags);
+ if (!eq)
+ return -EBUSY;
+ /* Process ORP-specifics here */
+ if (flags & QMAN_ENQUEUE_FLAG_NLIS)
+ orp_seqnum |= QM_EQCR_SEQNUM_NLIS;
+ else {
+ orp_seqnum &= ~QM_EQCR_SEQNUM_NLIS;
+ if (flags & QMAN_ENQUEUE_FLAG_NESN)
+ orp_seqnum |= QM_EQCR_SEQNUM_NESN;
+ else
+ /* No need to check 4 QMAN_ENQUEUE_FLAG_HOLE */
+ orp_seqnum &= ~QM_EQCR_SEQNUM_NESN;
+ }
+ eq->seqnum = orp_seqnum;
+ eq->orp = orp->fqid;
+ /* Note: QM_EQCR_VERB_INTERRUPT == QMAN_ENQUEUE_FLAG_WAIT_SYNC */
+ qm_eqcr_pvb_commit(&p->p, QM_EQCR_VERB_ORP |
+ ((flags & (QMAN_ENQUEUE_FLAG_HOLE | QMAN_ENQUEUE_FLAG_NESN)) ?
+ 0 : QM_EQCR_VERB_CMD_ENQUEUE) |
+ (flags & (QM_EQCR_VERB_COLOUR_MASK | QM_EQCR_VERB_INTERRUPT)));
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC
+ if (unlikely((flags & QMAN_ENQUEUE_FLAG_WAIT) &&
+ (flags & QMAN_ENQUEUE_FLAG_WAIT_SYNC))) {
+ if (flags & QMAN_ENQUEUE_FLAG_WAIT_INT)
+ wait_event_interruptible(affine_queue,
+ (p->eqci_owned != fq));
+ else
+ wait_event(affine_queue, (p->eqci_owned != fq));
+ }
+#endif
+ return 0;
+}
+EXPORT_SYMBOL(qman_p_enqueue_orp);
+
+int qman_enqueue_orp(struct qman_fq *fq, const struct qm_fd *fd, u32 flags,
+ struct qman_fq *orp, u16 orp_seqnum)
+{
+ struct qman_portal *p;
+ struct qm_eqcr_entry *eq;
+ unsigned long irqflags __maybe_unused;
+
+#ifdef CONFIG_FSL_DPA_CAN_WAIT
+ if (flags & QMAN_ENQUEUE_FLAG_WAIT)
+ eq = wait_eq_start(&p, &irqflags, fq, fd, flags);
+ else
+#endif
+ eq = try_eq_start(&p, &irqflags, fq, fd, flags);
+ if (!eq)
+ return -EBUSY;
+ /* Process ORP-specifics here */
+ if (flags & QMAN_ENQUEUE_FLAG_NLIS)
+ orp_seqnum |= QM_EQCR_SEQNUM_NLIS;
+ else {
+ orp_seqnum &= ~QM_EQCR_SEQNUM_NLIS;
+ if (flags & QMAN_ENQUEUE_FLAG_NESN)
+ orp_seqnum |= QM_EQCR_SEQNUM_NESN;
+ else
+ /* No need to check 4 QMAN_ENQUEUE_FLAG_HOLE */
+ orp_seqnum &= ~QM_EQCR_SEQNUM_NESN;
+ }
+ eq->seqnum = orp_seqnum;
+ eq->orp = orp->fqid;
+ /* Note: QM_EQCR_VERB_INTERRUPT == QMAN_ENQUEUE_FLAG_WAIT_SYNC */
+ qm_eqcr_pvb_commit(&p->p, QM_EQCR_VERB_ORP |
+ ((flags & (QMAN_ENQUEUE_FLAG_HOLE | QMAN_ENQUEUE_FLAG_NESN)) ?
+ 0 : QM_EQCR_VERB_CMD_ENQUEUE) |
+ (flags & (QM_EQCR_VERB_COLOUR_MASK | QM_EQCR_VERB_INTERRUPT)));
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC
+ if (unlikely((flags & QMAN_ENQUEUE_FLAG_WAIT) &&
+ (flags & QMAN_ENQUEUE_FLAG_WAIT_SYNC))) {
+ if (flags & QMAN_ENQUEUE_FLAG_WAIT_INT)
+ wait_event_interruptible(affine_queue,
+ (p->eqci_owned != fq));
+ else
+ wait_event(affine_queue, (p->eqci_owned != fq));
+ }
+#endif
+ return 0;
+}
+EXPORT_SYMBOL(qman_enqueue_orp);
+
+int qman_p_enqueue_precommit(struct qman_portal *p, struct qman_fq *fq,
+ const struct qm_fd *fd, u32 flags,
+ qman_cb_precommit cb, void *cb_arg)
+{
+ struct qm_eqcr_entry *eq;
+ unsigned long irqflags __maybe_unused;
+
+#ifdef CONFIG_FSL_DPA_CAN_WAIT
+ if (flags & QMAN_ENQUEUE_FLAG_WAIT)
+ eq = wait_p_eq_start(p, &irqflags, fq, fd, flags);
+ else
+#endif
+ eq = try_p_eq_start(p, &irqflags, fq, fd, flags);
+ if (!eq)
+ return -EBUSY;
+ /* invoke user supplied callback function before writing commit verb */
+ if (cb(cb_arg)) {
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ return -EINVAL;
+ }
+ /* Note: QM_EQCR_VERB_INTERRUPT == QMAN_ENQUEUE_FLAG_WAIT_SYNC */
+ qm_eqcr_pvb_commit(&p->p, QM_EQCR_VERB_CMD_ENQUEUE |
+ (flags & (QM_EQCR_VERB_COLOUR_MASK | QM_EQCR_VERB_INTERRUPT)));
+ /* Factor the below out, it's used from qman_enqueue_orp() too */
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC
+ if (unlikely((flags & QMAN_ENQUEUE_FLAG_WAIT) &&
+ (flags & QMAN_ENQUEUE_FLAG_WAIT_SYNC))) {
+ if (flags & QMAN_ENQUEUE_FLAG_WAIT_INT)
+ wait_event_interruptible(affine_queue,
+ (p->eqci_owned != fq));
+ else
+ wait_event(affine_queue, (p->eqci_owned != fq));
+ }
+#endif
+ return 0;
+}
+EXPORT_SYMBOL(qman_p_enqueue_precommit);
+
+int qman_enqueue_precommit(struct qman_fq *fq, const struct qm_fd *fd,
+ u32 flags, qman_cb_precommit cb, void *cb_arg)
+{
+ struct qman_portal *p;
+ struct qm_eqcr_entry *eq;
+ unsigned long irqflags __maybe_unused;
+
+#ifdef CONFIG_FSL_DPA_CAN_WAIT
+ if (flags & QMAN_ENQUEUE_FLAG_WAIT)
+ eq = wait_eq_start(&p, &irqflags, fq, fd, flags);
+ else
+#endif
+ eq = try_eq_start(&p, &irqflags, fq, fd, flags);
+ if (!eq)
+ return -EBUSY;
+ /* invoke user supplied callback function before writing commit verb */
+ if (cb(cb_arg)) {
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ return -EINVAL;
+ }
+ /* Note: QM_EQCR_VERB_INTERRUPT == QMAN_ENQUEUE_FLAG_WAIT_SYNC */
+ qm_eqcr_pvb_commit(&p->p, QM_EQCR_VERB_CMD_ENQUEUE |
+ (flags & (QM_EQCR_VERB_COLOUR_MASK | QM_EQCR_VERB_INTERRUPT)));
+ /* Factor the below out, it's used from qman_enqueue_orp() too */
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+#ifdef CONFIG_FSL_DPA_CAN_WAIT_SYNC
+ if (unlikely((flags & QMAN_ENQUEUE_FLAG_WAIT) &&
+ (flags & QMAN_ENQUEUE_FLAG_WAIT_SYNC))) {
+ if (flags & QMAN_ENQUEUE_FLAG_WAIT_INT)
+ wait_event_interruptible(affine_queue,
+ (p->eqci_owned != fq));
+ else
+ wait_event(affine_queue, (p->eqci_owned != fq));
+ }
+#endif
+ return 0;
+}
+EXPORT_SYMBOL(qman_enqueue_precommit);
+
+int qman_modify_cgr(struct qman_cgr *cgr, u32 flags,
+ struct qm_mcc_initcgr *opts)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p = get_affine_portal();
+ unsigned long irqflags __maybe_unused;
+ u8 res;
+ u8 verb = QM_MCC_VERB_MODIFYCGR;
+
+ PORTAL_IRQ_LOCK(p, irqflags);
+ mcc = qm_mc_start(&p->p);
+ if (opts)
+ mcc->initcgr = *opts;
+ mcc->initcgr.cgid = cgr->cgrid;
+ if (flags & QMAN_CGR_FLAG_USE_INIT)
+ verb = QM_MCC_VERB_INITCGR;
+ qm_mc_commit(&p->p, verb);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == verb);
+ res = mcr->result;
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ return (res == QM_MCR_RESULT_OK) ? 0 : -EIO;
+}
+EXPORT_SYMBOL(qman_modify_cgr);
+
+#define TARG_MASK(n) (0x80000000 >> (n->config->public_cfg.channel - \
+ QM_CHANNEL_SWPORTAL0))
+#define PORTAL_IDX(n) (n->config->public_cfg.channel - QM_CHANNEL_SWPORTAL0)
+
+int qman_create_cgr(struct qman_cgr *cgr, u32 flags,
+ struct qm_mcc_initcgr *opts)
+{
+ unsigned long irqflags __maybe_unused;
+ struct qm_mcr_querycgr cgr_state;
+ struct qm_mcc_initcgr local_opts;
+ int ret;
+ struct qman_portal *p;
+
+ /* We have to check that the provided CGRID is within the limits of the
+ * data-structures, for obvious reasons. However we'll let h/w take
+ * care of determining whether it's within the limits of what exists on
+ * the SoC. */
+ if (cgr->cgrid >= __CGR_NUM)
+ return -EINVAL;
+
+ p = get_affine_portal();
+
+ memset(&local_opts, 0, sizeof(struct qm_mcc_initcgr));
+ cgr->chan = p->config->public_cfg.channel;
+ spin_lock_irqsave(&p->cgr_lock, irqflags);
+
+ /* if no opts specified, just add it to the list */
+ if (!opts)
+ goto add_list;
+
+ ret = qman_query_cgr(cgr, &cgr_state);
+ if (ret)
+ goto release_lock;
+ if (opts)
+ local_opts = *opts;
+ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30)
+ local_opts.cgr.cscn_targ_upd_ctrl =
+ QM_CGR_TARG_UDP_CTRL_WRITE_BIT | PORTAL_IDX(p);
+ else
+ /* Overwrite TARG */
+ local_opts.cgr.cscn_targ = cgr_state.cgr.cscn_targ |
+ TARG_MASK(p);
+ local_opts.we_mask |= QM_CGR_WE_CSCN_TARG;
+
+ /* send init if flags indicate so */
+ if (opts && (flags & QMAN_CGR_FLAG_USE_INIT))
+ ret = qman_modify_cgr(cgr, QMAN_CGR_FLAG_USE_INIT, &local_opts);
+ else
+ ret = qman_modify_cgr(cgr, 0, &local_opts);
+ if (ret)
+ goto release_lock;
+add_list:
+ list_add(&cgr->node, &p->cgr_cbs);
+
+ /* Determine if newly added object requires its callback to be called */
+ ret = qman_query_cgr(cgr, &cgr_state);
+ if (ret) {
+ /* we can't go back, so proceed and return success, but screen
+ * and wail to the log file */
+ pr_crit("CGR HW state partially modified\n");
+ ret = 0;
+ goto release_lock;
+ }
+ if (cgr->cb && cgr_state.cgr.cscn_en && qman_cgrs_get(&p->cgrs[1],
+ cgr->cgrid))
+ cgr->cb(p, cgr, 1);
+release_lock:
+ spin_unlock_irqrestore(&p->cgr_lock, irqflags);
+ put_affine_portal();
+ return ret;
+}
+EXPORT_SYMBOL(qman_create_cgr);
+
+int qman_create_cgr_to_dcp(struct qman_cgr *cgr, u32 flags, u16 dcp_portal,
+ struct qm_mcc_initcgr *opts)
+{
+ unsigned long irqflags __maybe_unused;
+ struct qm_mcc_initcgr local_opts;
+ int ret;
+
+ if ((qman_ip_rev & 0xFF00) < QMAN_REV30) {
+ pr_warn("This QMan version doesn't support to send CSCN to"
+ " DCP portal\n");
+ return -EINVAL;
+ }
+ /* We have to check that the provided CGRID is within the limits of the
+ * data-structures, for obvious reasons. However we'll let h/w take
+ * care of determining whether it's within the limits of what exists on
+ * the SoC.
+ */
+ if (cgr->cgrid >= __CGR_NUM)
+ return -EINVAL;
+
+ memset(&local_opts, 0, sizeof(struct qm_mcc_initcgr));
+ if (opts)
+ local_opts = *opts;
+
+ local_opts.cgr.cscn_targ_upd_ctrl = QM_CGR_TARG_UDP_CTRL_WRITE_BIT |
+ QM_CGR_TARG_UDP_CTRL_DCP | dcp_portal;
+ local_opts.we_mask |= QM_CGR_WE_CSCN_TARG;
+
+ /* send init if flags indicate so */
+ if (opts && (flags & QMAN_CGR_FLAG_USE_INIT))
+ ret = qman_modify_cgr(cgr, QMAN_CGR_FLAG_USE_INIT,
+ &local_opts);
+ else
+ ret = qman_modify_cgr(cgr, 0, &local_opts);
+
+ return ret;
+}
+EXPORT_SYMBOL(qman_create_cgr_to_dcp);
+
+int qman_delete_cgr(struct qman_cgr *cgr)
+{
+ unsigned long irqflags __maybe_unused;
+ struct qm_mcr_querycgr cgr_state;
+ struct qm_mcc_initcgr local_opts;
+ int ret = 0;
+ struct qman_cgr *i;
+ struct qman_portal *p = get_affine_portal();
+
+ if (cgr->chan != p->config->public_cfg.channel) {
+ pr_crit("Attempting to delete cgr from different portal "
+ "than it was create: create 0x%x, delete 0x%x\n",
+ cgr->chan, p->config->public_cfg.channel);
+ ret = -EINVAL;
+ goto put_portal;
+ }
+ memset(&local_opts, 0, sizeof(struct qm_mcc_initcgr));
+ spin_lock_irqsave(&p->cgr_lock, irqflags);
+ list_del(&cgr->node);
+ /*
+ * If there are no other CGR objects for this CGRID in the list, update
+ * CSCN_TARG accordingly
+ */
+ list_for_each_entry(i, &p->cgr_cbs, node)
+ if ((i->cgrid == cgr->cgrid) && i->cb)
+ goto release_lock;
+ ret = qman_query_cgr(cgr, &cgr_state);
+ if (ret) {
+ /* add back to the list */
+ list_add(&cgr->node, &p->cgr_cbs);
+ goto release_lock;
+ }
+ /* Overwrite TARG */
+ local_opts.we_mask = QM_CGR_WE_CSCN_TARG;
+ if ((qman_ip_rev & 0xFF00) >= QMAN_REV30)
+ local_opts.cgr.cscn_targ_upd_ctrl = PORTAL_IDX(p);
+ else
+ local_opts.cgr.cscn_targ = cgr_state.cgr.cscn_targ &
+ ~(TARG_MASK(p));
+ ret = qman_modify_cgr(cgr, 0, &local_opts);
+ if (ret)
+ /* add back to the list */
+ list_add(&cgr->node, &p->cgr_cbs);
+release_lock:
+ spin_unlock_irqrestore(&p->cgr_lock, irqflags);
+put_portal:
+ put_affine_portal();
+ return ret;
+}
+EXPORT_SYMBOL(qman_delete_cgr);
+
+int qm_get_clock(u64 *clock_hz)
+{
+ if (!qman_clk) {
+ pr_warn("Qman clock speed is unknown\n");
+ return -EINVAL;
+ }
+ *clock_hz = (u64)qman_clk;
+ return 0;
+}
+EXPORT_SYMBOL(qm_get_clock);
+
+int qm_set_clock(u64 clock_hz)
+{
+ if (qman_clk)
+ return -1;
+ qman_clk = (u32)clock_hz;
+ return 0;
+}
+EXPORT_SYMBOL(qm_set_clock);
+
+/* CEETM management command */
+static int qman_ceetm_configure_lfqmt(struct qm_mcc_ceetm_lfqmt_config *opts)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p;
+ unsigned long irqflags __maybe_unused;
+ u8 res;
+
+ p = get_affine_portal();
+ PORTAL_IRQ_LOCK(p, irqflags);
+
+ mcc = qm_mc_start(&p->p);
+ mcc->lfqmt_config = *opts;
+ qm_mc_commit(&p->p, QM_CEETM_VERB_LFQMT_CONFIG);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) ==
+ QM_CEETM_VERB_LFQMT_CONFIG);
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+
+ res = mcr->result;
+ if (res != QM_MCR_RESULT_OK) {
+ pr_err("CEETM: CONFIGURE LFQMT failed\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+static int qman_ceetm_query_lfqmt(int lfqid,
+ struct qm_mcr_ceetm_lfqmt_query *lfqmt_query)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p;
+ unsigned long irqflags __maybe_unused;
+ u8 res;
+
+ p = get_affine_portal();
+ PORTAL_IRQ_LOCK(p, irqflags);
+
+ mcc = qm_mc_start(&p->p);
+ mcc->lfqmt_query.lfqid = lfqid;
+ qm_mc_commit(&p->p, QM_CEETM_VERB_LFQMT_QUERY);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_CEETM_VERB_LFQMT_QUERY);
+ res = mcr->result;
+ if (res == QM_MCR_RESULT_OK)
+ *lfqmt_query = mcr->lfqmt_query;
+
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ if (res != QM_MCR_RESULT_OK) {
+ pr_err("CEETM: QUERY LFQMT failed\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+static int qman_ceetm_configure_cq(struct qm_mcc_ceetm_cq_config *opts)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p;
+ unsigned long irqflags __maybe_unused;
+ u8 res;
+
+ p = get_affine_portal();
+ PORTAL_IRQ_LOCK(p, irqflags);
+
+ mcc = qm_mc_start(&p->p);
+ mcc->cq_config = *opts;
+ qm_mc_commit(&p->p, QM_CEETM_VERB_CQ_CONFIG);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ res = mcr->result;
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_CEETM_VERB_CQ_CONFIG);
+
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+
+ if (res != QM_MCR_RESULT_OK) {
+ pr_err("CEETM: CONFIGURE CQ failed\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+int qman_ceetm_query_cq(unsigned int cqid, unsigned int dcpid,
+ struct qm_mcr_ceetm_cq_query *cq_query)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p;
+ unsigned long irqflags __maybe_unused;
+ u8 res;
+
+ p = get_affine_portal();
+ PORTAL_IRQ_LOCK(p, irqflags);
+
+ mcc = qm_mc_start(&p->p);
+ mcc->cq_query.cqid = cqid;
+ mcc->cq_query.dcpid = dcpid;
+ qm_mc_commit(&p->p, QM_CEETM_VERB_CQ_QUERY);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ res = mcr->result;
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_CEETM_VERB_CQ_QUERY);
+
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+
+ if (res != QM_MCR_RESULT_OK) {
+ pr_err("CEETM: QUERY CQ failed\n");
+ return -EIO;
+ }
+
+ *cq_query = mcr->cq_query;
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_query_cq);
+
+static int qman_ceetm_configure_dct(struct qm_mcc_ceetm_dct_config *opts)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p;
+ unsigned long irqflags __maybe_unused;
+ u8 res;
+
+ p = get_affine_portal();
+ PORTAL_IRQ_LOCK(p, irqflags);
+
+ mcc = qm_mc_start(&p->p);
+ mcc->dct_config = *opts;
+ qm_mc_commit(&p->p, QM_CEETM_VERB_DCT_CONFIG);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_CEETM_VERB_DCT_CONFIG);
+ res = mcr->result;
+
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+
+ if (res != QM_MCR_RESULT_OK) {
+ pr_err("CEETM: CONFIGURE DCT failed\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+static int qman_ceetm_query_dct(struct qm_mcc_ceetm_dct_query *opts,
+ struct qm_mcr_ceetm_dct_query *dct_query)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p = get_affine_portal();
+ unsigned long irqflags __maybe_unused;
+ u8 res;
+
+ PORTAL_IRQ_LOCK(p, irqflags);
+
+ mcc = qm_mc_start(&p->p);
+ mcc->dct_query = *opts;
+ qm_mc_commit(&p->p, QM_CEETM_VERB_DCT_QUERY);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_CEETM_VERB_DCT_QUERY);
+ res = mcr->result;
+
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+
+ if (res != QM_MCR_RESULT_OK) {
+ pr_err("CEETM: QUERY DCT failed\n");
+ return -EIO;
+ }
+
+ *dct_query = mcr->dct_query;
+ return 0;
+}
+
+static int qman_ceetm_configure_class_scheduler(
+ struct qm_mcc_ceetm_class_scheduler_config *opts)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p;
+ unsigned long irqflags __maybe_unused;
+ u8 res;
+
+ p = get_affine_portal();
+ PORTAL_IRQ_LOCK(p, irqflags);
+
+ mcc = qm_mc_start(&p->p);
+ mcc->csch_config = *opts;
+ qm_mc_commit(&p->p, QM_CEETM_VERB_CLASS_SCHEDULER_CONFIG);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) ==
+ QM_CEETM_VERB_CLASS_SCHEDULER_CONFIG);
+ res = mcr->result;
+
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+
+ if (res != QM_MCR_RESULT_OK) {
+ pr_err("CEETM: CONFIGURE CLASS SCHEDULER failed\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+static int qman_ceetm_query_class_scheduler(struct qm_ceetm_channel *channel,
+ struct qm_mcr_ceetm_class_scheduler_query *query)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p;
+ unsigned long irqflags __maybe_unused;
+ u8 res;
+
+ p = get_affine_portal();
+ PORTAL_IRQ_LOCK(p, irqflags);
+
+ mcc = qm_mc_start(&p->p);
+ mcc->csch_query.cqcid = channel->idx;
+ mcc->csch_query.dcpid = channel->dcp_idx;
+ qm_mc_commit(&p->p, QM_CEETM_VERB_CLASS_SCHEDULER_QUERY);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) ==
+ QM_CEETM_VERB_CLASS_SCHEDULER_QUERY);
+ res = mcr->result;
+
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+
+ if (res != QM_MCR_RESULT_OK) {
+ pr_err("CEETM: QUERY CLASS SCHEDULER failed\n");
+ return -EIO;
+ }
+ *query = mcr->csch_query;
+ return 0;
+}
+
+static int qman_ceetm_configure_mapping_shaper_tcfc(
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_config *opts)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p;
+ unsigned long irqflags __maybe_unused;
+ u8 res;
+
+ p = get_affine_portal();
+ PORTAL_IRQ_LOCK(p, irqflags);
+
+ mcc = qm_mc_start(&p->p);
+ mcc->mst_config = *opts;
+ qm_mc_commit(&p->p, QM_CEETM_VERB_MAPPING_SHAPER_TCFC_CONFIG);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) ==
+ QM_CEETM_VERB_MAPPING_SHAPER_TCFC_CONFIG);
+ res = mcr->result;
+
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+
+ if (res != QM_MCR_RESULT_OK) {
+ pr_err("CEETM: CONFIGURE CHANNEL MAPPING failed\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+static int qman_ceetm_query_mapping_shaper_tcfc(
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_query *opts,
+ struct qm_mcr_ceetm_mapping_shaper_tcfc_query *response)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p;
+ unsigned long irqflags __maybe_unused;
+ u8 res;
+
+ p = get_affine_portal();
+ PORTAL_IRQ_LOCK(p, irqflags);
+
+ mcc = qm_mc_start(&p->p);
+ mcc->mst_query = *opts;
+ qm_mc_commit(&p->p, QM_CEETM_VERB_MAPPING_SHAPER_TCFC_QUERY);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) ==
+ QM_CEETM_VERB_MAPPING_SHAPER_TCFC_QUERY);
+ res = mcr->result;
+
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+
+ if (res != QM_MCR_RESULT_OK) {
+ pr_err("CEETM: QUERY CHANNEL MAPPING failed\n");
+ return -EIO;
+ }
+
+ *response = mcr->mst_query;
+ return 0;
+}
+
+static int qman_ceetm_configure_ccgr(struct qm_mcc_ceetm_ccgr_config *opts)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p;
+ unsigned long irqflags __maybe_unused;
+ u8 res;
+
+ p = get_affine_portal();
+ PORTAL_IRQ_LOCK(p, irqflags);
+
+ mcc = qm_mc_start(&p->p);
+ mcc->ccgr_config = *opts;
+
+ qm_mc_commit(&p->p, QM_CEETM_VERB_CCGR_CONFIG);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_CEETM_VERB_CCGR_CONFIG);
+
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+
+ res = mcr->result;
+ if (res != QM_MCR_RESULT_OK) {
+ pr_err("CEETM: CONFIGURE CCGR failed\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+int qman_ceetm_query_ccgr(struct qm_mcc_ceetm_ccgr_query *ccgr_query,
+ struct qm_mcr_ceetm_ccgr_query *response)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p;
+ unsigned long irqflags __maybe_unused;
+ u8 res;
+
+ p = get_affine_portal();
+ PORTAL_IRQ_LOCK(p, irqflags);
+
+ mcc = qm_mc_start(&p->p);
+ mcc->ccgr_query = *ccgr_query;
+ qm_mc_commit(&p->p, QM_CEETM_VERB_CCGR_QUERY);
+
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_CEETM_VERB_CCGR_QUERY);
+
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+
+ res = mcr->result;
+ if (res != QM_MCR_RESULT_OK) {
+ pr_err("CEETM: QUERY CCGR failed\n");
+ return -EIO;
+ }
+ *response = mcr->ccgr_query;
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_query_ccgr);
+
+static int qman_ceetm_cq_peek_pop_xsfdrread(struct qm_ceetm_cq *cq,
+ u8 command_type, u16 xsfdr,
+ struct qm_mcr_ceetm_cq_peek_pop_xsfdrread *cq_ppxr)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p;
+ unsigned long irqflags __maybe_unused;
+ u8 res;
+
+ p = get_affine_portal();
+ PORTAL_IRQ_LOCK(p, irqflags);
+
+ mcc = qm_mc_start(&p->p);
+ switch (command_type) {
+ case 0:
+ case 1:
+ mcc->cq_ppxr.cqid = (cq->parent->idx << 4) | cq->idx;
+ break;
+ case 2:
+ mcc->cq_ppxr.xsfdr = xsfdr;
+ break;
+ default:
+ break;
+ }
+ mcc->cq_ppxr.ct = command_type;
+ mcc->cq_ppxr.dcpid = cq->parent->dcp_idx;
+ qm_mc_commit(&p->p, QM_CEETM_VERB_CQ_PEEK_POP_XFDRREAD);
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) ==
+ QM_CEETM_VERB_CQ_PEEK_POP_XFDRREAD);
+
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+
+ res = mcr->result;
+ if (res != QM_MCR_RESULT_OK) {
+ pr_err("CEETM: CQ PEEK/POP/XSFDR READ failed\n");
+ return -EIO;
+ }
+ *cq_ppxr = mcr->cq_ppxr;
+ return 0;
+}
+
+static int qman_ceetm_query_statistics(u16 cid,
+ enum qm_dc_portal dcp_idx,
+ u16 command_type,
+ struct qm_mcr_ceetm_statistics_query *query_result)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p;
+ unsigned long irqflags __maybe_unused;
+ u8 res;
+
+ p = get_affine_portal();
+ PORTAL_IRQ_LOCK(p, irqflags);
+
+ mcc = qm_mc_start(&p->p);
+ mcc->stats_query_write.cid = cid;
+ mcc->stats_query_write.dcpid = dcp_idx;
+ mcc->stats_query_write.ct = command_type;
+ qm_mc_commit(&p->p, QM_CEETM_VERB_STATISTICS_QUERY_WRITE);
+
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) ==
+ QM_CEETM_VERB_STATISTICS_QUERY_WRITE);
+
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+
+ res = mcr->result;
+ if (res != QM_MCR_RESULT_OK) {
+ pr_err("CEETM: STATISTICS QUERY failed\n");
+ return -EIO;
+ }
+ *query_result = mcr->stats_query;
+ return 0;
+}
+
+static int qman_ceetm_write_statistics(u16 cid, enum qm_dc_portal dcp_idx,
+ u16 command_type, u64 frame_count, u64 byte_count)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p;
+ unsigned long irqflags __maybe_unused;
+ u8 res;
+
+ p = get_affine_portal();
+ PORTAL_IRQ_LOCK(p, irqflags);
+
+ mcc = qm_mc_start(&p->p);
+ mcc->stats_query_write.cid = cid;
+ mcc->stats_query_write.dcpid = dcp_idx;
+ mcc->stats_query_write.ct = command_type;
+ mcc->stats_query_write.frm_cnt = frame_count;
+ mcc->stats_query_write.byte_cnt = byte_count;
+ qm_mc_commit(&p->p, QM_CEETM_VERB_STATISTICS_QUERY_WRITE);
+
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) ==
+ QM_CEETM_VERB_STATISTICS_QUERY_WRITE);
+
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+
+ res = mcr->result;
+ if (res != QM_MCR_RESULT_OK) {
+ pr_err("CEETM: STATISTICS WRITE failed\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+int qman_ceetm_bps2tokenrate(u32 bps, struct qm_ceetm_rate *token_rate,
+ int rounding)
+{
+ u16 pres;
+ u64 temp;
+ u64 qman_freq;
+ int ret;
+
+ /* Read PRES from CEET_CFG_PRES register */
+ ret = qman_ceetm_get_prescaler(&pres);
+ if (ret)
+ return -EINVAL;
+
+ ret = qm_get_clock(&qman_freq);
+ if (ret)
+ return -EINVAL;
+
+ /* token-rate = bytes-per-second * update-reference-period
+ *
+ * Where token-rate is N/8192 for a integer N, and
+ * update-reference-period is (2^22)/(PRES*QHz), where PRES
+ * is the prescalar value and QHz is the QMan clock frequency.
+ * So:
+ *
+ * token-rate = (byte-per-second*2^22)/PRES*QHZ)
+ *
+ * Converting to bits-per-second gives;
+ *
+ * token-rate = (bps*2^19) / (PRES*QHZ)
+ * N = (bps*2^32) / (PRES*QHz)
+ *
+ */
+ temp = ROUNDING(((u64)bps << 32), pres, rounding);
+ temp = ROUNDING(temp, qman_freq, rounding);
+ token_rate->whole = temp >> 13;
+ token_rate->fraction = temp & (((u64)1 << 13) - 1);
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_bps2tokenrate);
+
+int qman_ceetm_tokenrate2bps(const struct qm_ceetm_rate *token_rate, u32 *bps,
+ int rounding)
+{
+ u16 pres;
+ u64 temp;
+ u64 qman_freq;
+ int ret;
+
+ /* Read PRES from CEET_CFG_PRES register */
+ ret = qman_ceetm_get_prescaler(&pres);
+ if (ret)
+ return -EINVAL;
+
+ ret = qm_get_clock(&qman_freq);
+ if (ret)
+ return -EINVAL;
+
+ /* bytes-per-second = token-rate / update-reference-period
+ *
+ * where "token-rate" is N/8192 for an integer N, and
+ * "update-reference-period" is (2^22)/(PRES*QHz), where PRES is
+ * the prescalar value and QHz is the QMan clock frequency. So;
+ *
+ * bytes-per-second = (N/8192) / (4194304/PRES*QHz)
+ * = N*PRES*QHz / (4194304*8192)
+ * = N*PRES*QHz / (2^35)
+ *
+ * Converting to bits-per-second gives;
+ *
+ * bps = N*PRES*QHZ / (2^32)
+ *
+ * Note, the numerator has a maximum width of 72 bits! So to
+ * avoid 64-bit overflow errors, we calculate PRES*QHZ (maximum
+ * width 48 bits) divided by 2^9 (reducing to maximum 39 bits), before
+ * multiplying by N (goes to maximum of 63 bits).
+ *
+ * temp = PRES*QHZ / (2^16)
+ * kbps = temp*N / (2^16)
+ */
+ temp = ROUNDING(qman_freq * pres, (u64)1 << 16 , rounding);
+ temp *= ((token_rate->whole << 13) + token_rate->fraction);
+ *bps = ROUNDING(temp, (u64)(1) << 16, rounding);
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_tokenrate2bps);
+
+int qman_ceetm_sp_claim(struct qm_ceetm_sp **sp, enum qm_dc_portal dcp_idx,
+ unsigned int sp_idx)
+{
+ struct qm_ceetm_sp *p;
+
+ DPA_ASSERT((dcp_idx == qm_dc_portal_fman0) ||
+ (dcp_idx == qm_dc_portal_fman1));
+
+ if ((sp_idx < qman_ceetms[dcp_idx].sp_range[0]) ||
+ (sp_idx > (qman_ceetms[dcp_idx].sp_range[0] +
+ qman_ceetms[dcp_idx].sp_range[1]))) {
+ pr_err("Sub-portal index doesn't exist\n");
+ return -EINVAL;
+ }
+
+ list_for_each_entry(p, &qman_ceetms[dcp_idx].sub_portals, node) {
+ if ((p->idx == sp_idx) && (p->is_claimed == 0)) {
+ p->is_claimed = 1;
+ *sp = p;
+ return 0;
+ }
+ }
+ pr_err("The sub-portal#%d is not available!\n", sp_idx);
+ return -ENODEV;
+}
+EXPORT_SYMBOL(qman_ceetm_sp_claim);
+
+int qman_ceetm_sp_release(struct qm_ceetm_sp *sp)
+{
+ struct qm_ceetm_sp *p;
+
+ if (sp->lni->is_claimed == 1) {
+ pr_err("The dependency of sub-portal has not been released!\n");
+ return -EBUSY;
+ }
+
+ list_for_each_entry(p, &qman_ceetms[sp->dcp_idx].sub_portals, node) {
+ if (p->idx == sp->idx) {
+ p->is_claimed = 0;
+ p->lni = NULL;
+ }
+ }
+ /* Disable CEETM mode of this sub-portal */
+ qman_sp_disable_ceetm_mode(sp->dcp_idx, sp->idx);
+
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_sp_release);
+
+int qman_ceetm_lni_claim(struct qm_ceetm_lni **lni, enum qm_dc_portal dcp_idx,
+ unsigned int lni_idx)
+{
+ struct qm_ceetm_lni *p;
+
+ if ((lni_idx < qman_ceetms[dcp_idx].lni_range[0]) ||
+ (lni_idx > (qman_ceetms[dcp_idx].lni_range[0] +
+ qman_ceetms[dcp_idx].lni_range[1]))) {
+ pr_err("The lni index is out of range\n");
+ return -EINVAL;
+ }
+
+ list_for_each_entry(p, &qman_ceetms[dcp_idx].lnis, node) {
+ if ((p->idx == lni_idx) && (p->is_claimed == 0)) {
+ *lni = p;
+ p->is_claimed = 1;
+ return 0;
+ }
+ }
+
+ pr_err("The LNI#%d is not available!\n", lni_idx);
+ return -EINVAL;
+}
+EXPORT_SYMBOL(qman_ceetm_lni_claim);
+
+int qman_ceetm_lni_release(struct qm_ceetm_lni *lni)
+{
+ struct qm_ceetm_lni *p;
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts;
+
+ if (!list_empty(&lni->channels)) {
+ pr_err("The LNI dependencies are not released!\n");
+ return -EBUSY;
+ }
+
+ list_for_each_entry(p, &qman_ceetms[lni->dcp_idx].lnis, node) {
+ if (p->idx == lni->idx) {
+ p->shaper_enable = 0;
+ p->shaper_couple = 0;
+ p->cr_token_rate.whole = 0;
+ p->cr_token_rate.fraction = 0;
+ p->er_token_rate.whole = 0;
+ p->er_token_rate.fraction = 0;
+ p->cr_token_bucket_limit = 0;
+ p->er_token_bucket_limit = 0;
+ p->is_claimed = 0;
+ }
+ }
+ config_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx;
+ config_opts.dcpid = lni->dcp_idx;
+ memset(&config_opts.shaper_config, 0,
+ sizeof(config_opts.shaper_config));
+ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts);
+}
+EXPORT_SYMBOL(qman_ceetm_lni_release);
+
+int qman_ceetm_sp_set_lni(struct qm_ceetm_sp *sp, struct qm_ceetm_lni *lni)
+{
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts;
+
+ config_opts.cid = CEETM_COMMAND_SP_MAPPING | sp->idx;
+ config_opts.dcpid = sp->dcp_idx;
+ config_opts.sp_mapping.map_lni_id = lni->idx;
+ sp->lni = lni;
+
+ if (qman_ceetm_configure_mapping_shaper_tcfc(&config_opts))
+ return -EINVAL;
+
+ /* Enable CEETM mode for this sub-portal */
+ return qman_sp_enable_ceetm_mode(sp->dcp_idx, sp->idx);
+}
+EXPORT_SYMBOL(qman_ceetm_sp_set_lni);
+
+int qman_ceetm_sp_get_lni(struct qm_ceetm_sp *sp, unsigned int *lni_idx)
+{
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts;
+ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result;
+
+ query_opts.cid = CEETM_COMMAND_SP_MAPPING | sp->idx;
+ query_opts.dcpid = sp->dcp_idx;
+ if (qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result)) {
+ pr_err("Can't get SP <-> LNI mapping\n");
+ return -EINVAL;
+ }
+ *lni_idx = query_result.sp_mapping_query.map_lni_id;
+ sp->lni->idx = query_result.sp_mapping_query.map_lni_id;
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_sp_get_lni);
+
+int qman_ceetm_lni_enable_shaper(struct qm_ceetm_lni *lni, int coupled,
+ int oal)
+{
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts;
+
+ if (lni->shaper_enable) {
+ pr_err("The shaper has already been enabled\n");
+ return -EINVAL;
+ }
+
+ lni->shaper_enable = 1;
+ lni->shaper_couple = coupled;
+
+ config_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx;
+ config_opts.dcpid = lni->dcp_idx;
+ config_opts.shaper_config.cpl = (coupled << 7) | oal;
+ config_opts.shaper_config.crtcr = (lni->cr_token_rate.whole << 13) |
+ lni->cr_token_rate.fraction;
+ config_opts.shaper_config.ertcr = (lni->er_token_rate.whole << 13) |
+ lni->er_token_rate.fraction;
+ config_opts.shaper_config.crtbl = lni->cr_token_bucket_limit;
+ config_opts.shaper_config.ertbl = lni->er_token_bucket_limit;
+ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts);
+}
+EXPORT_SYMBOL(qman_ceetm_lni_enable_shaper);
+
+int qman_ceetm_lni_disable_shaper(struct qm_ceetm_lni *lni)
+{
+ if (!lni->shaper_enable) {
+ pr_err("The shaper has been disabled\n");
+ return -EINVAL;
+ }
+
+ lni->shaper_enable = 0;
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_lni_disable_shaper);
+
+int qman_ceetm_lni_set_commit_rate(struct qm_ceetm_lni *lni,
+ const struct qm_ceetm_rate *token_rate,
+ u16 token_limit)
+{
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts;
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts;
+ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result;
+ int ret;
+
+ if (!lni->shaper_enable) {
+ pr_err("The LNI#%d is unshaped, cannot set CR rate\n",
+ lni->idx);
+ return -EINVAL;
+ }
+
+ query_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx;
+ query_opts.dcpid = lni->dcp_idx;
+ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result);
+ if (ret) {
+ pr_err("Fail to get current LNI shaper setting\n");
+ return -EINVAL;
+ }
+
+ lni->cr_token_rate.whole = token_rate->whole;
+ lni->cr_token_rate.fraction = token_rate->fraction;
+ lni->cr_token_bucket_limit = token_limit;
+ config_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx;
+ config_opts.dcpid = lni->dcp_idx;
+ config_opts.shaper_config.crtcr = (token_rate->whole << 13) |
+ (token_rate->fraction);
+ config_opts.shaper_config.crtbl = token_limit;
+ config_opts.shaper_config.cpl = query_result.shaper_query.cpl;
+ config_opts.shaper_config.ertcr = query_result.shaper_query.ertcr;
+ config_opts.shaper_config.ertbl = query_result.shaper_query.ertbl;
+ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts);
+}
+EXPORT_SYMBOL(qman_ceetm_lni_set_commit_rate);
+
+int qman_ceetm_lni_get_commit_rate(struct qm_ceetm_lni *lni,
+ struct qm_ceetm_rate *token_rate,
+ u16 *token_limit)
+{
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts;
+ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result;
+ int ret;
+
+ query_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx;
+ query_opts.dcpid = lni->dcp_idx;
+
+ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result);
+ if (ret | !query_result.shaper_query.crtcr |
+ !query_result.shaper_query.crtbl) {
+ pr_err("The LNI CR rate or limit is not set\n");
+ return -EINVAL;
+ }
+ token_rate->whole = query_result.shaper_query.crtcr >> 13;
+ token_rate->fraction = query_result.shaper_query.crtcr & 0x1FFF;
+ *token_limit = query_result.shaper_query.crtbl;
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_lni_get_commit_rate);
+
+int qman_ceetm_lni_set_excess_rate(struct qm_ceetm_lni *lni,
+ const struct qm_ceetm_rate *token_rate,
+ u16 token_limit)
+{
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts;
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts;
+ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result;
+ int ret;
+
+ if (!lni->shaper_enable) {
+ pr_err("The LIN#%d is unshaped, cannot set ER rate\n",
+ lni->idx);
+ return -EINVAL;
+ }
+
+ query_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx;
+ query_opts.dcpid = lni->dcp_idx;
+ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result);
+ if (ret) {
+ pr_err("Fail to get current LNI shaper setting\n");
+ return -EINVAL;
+ }
+
+ lni->er_token_rate.whole = token_rate->whole;
+ lni->er_token_rate.fraction = token_rate->fraction;
+ lni->er_token_bucket_limit = token_limit;
+ config_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx;
+ config_opts.dcpid = lni->dcp_idx;
+ config_opts.shaper_config.ertcr =
+ (token_rate->whole << 13) | (token_rate->fraction);
+ config_opts.shaper_config.ertbl = token_limit;
+ config_opts.shaper_config.cpl = query_result.shaper_query.cpl;
+ config_opts.shaper_config.crtcr = query_result.shaper_query.crtcr;
+ config_opts.shaper_config.crtbl = query_result.shaper_query.crtbl;
+
+ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts);
+}
+EXPORT_SYMBOL(qman_ceetm_lni_set_excess_rate);
+
+int qman_ceetm_lni_get_excess_rate(struct qm_ceetm_lni *lni,
+ struct qm_ceetm_rate *token_rate,
+ u16 *token_limit)
+{
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts;
+ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result;
+ int ret;
+
+ query_opts.cid = CEETM_COMMAND_LNI_SHAPER | lni->idx;
+ query_opts.dcpid = lni->dcp_idx;
+ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result);
+ if (ret | !query_result.shaper_query.ertcr |
+ !query_result.shaper_query.ertbl) {
+ pr_err("The LNI ER rate or limit is not set\n");
+ return -EINVAL;
+ }
+ token_rate->whole = query_result.shaper_query.ertcr >> 13;
+ token_rate->fraction = query_result.shaper_query.ertcr & 0x1FFF;
+ *token_limit = query_result.shaper_query.ertbl;
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_lni_get_excess_rate);
+
+#define QMAN_CEETM_LNITCFCC_CQ_LEVEL_SHIFT(n) ((15 - n) * 4)
+#define QMAN_CEETM_LNITCFCC_ENABLE 0x8
+int qman_ceetm_lni_set_tcfcc(struct qm_ceetm_lni *lni,
+ unsigned int cq_level,
+ int traffic_class)
+{
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts;
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts;
+ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result;
+ u64 lnitcfcc;
+
+ if ((cq_level > 15) | (traffic_class > 7)) {
+ pr_err("The CQ or traffic class id is out of range\n");
+ return -EINVAL;
+ }
+
+ query_opts.cid = CEETM_COMMAND_TCFC | lni->idx;
+ query_opts.dcpid = lni->dcp_idx;
+ if (qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result)) {
+ pr_err("Fail to query tcfcc\n");
+ return -EINVAL;
+ }
+
+ lnitcfcc = query_result.tcfc_query.lnitcfcc;
+ if (traffic_class == -1) {
+ /* disable tcfc for this CQ */
+ lnitcfcc &= ~((u64)QMAN_CEETM_LNITCFCC_ENABLE <<
+ QMAN_CEETM_LNITCFCC_CQ_LEVEL_SHIFT(cq_level));
+ } else {
+ lnitcfcc &= ~((u64)0xF <<
+ QMAN_CEETM_LNITCFCC_CQ_LEVEL_SHIFT(cq_level));
+ lnitcfcc |= ((u64)(QMAN_CEETM_LNITCFCC_ENABLE |
+ traffic_class)) <<
+ QMAN_CEETM_LNITCFCC_CQ_LEVEL_SHIFT(cq_level);
+ }
+ config_opts.tcfc_config.lnitcfcc = lnitcfcc;
+ config_opts.cid = CEETM_COMMAND_TCFC | lni->idx;
+ config_opts.dcpid = lni->dcp_idx;
+ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts);
+}
+EXPORT_SYMBOL(qman_ceetm_lni_set_tcfcc);
+
+#define QMAN_CEETM_LNITCFCC_TC_MASK 0x7
+int qman_ceetm_lni_get_tcfcc(struct qm_ceetm_lni *lni, unsigned int cq_level,
+ int *traffic_class)
+{
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts;
+ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result;
+ int ret;
+ u8 lnitcfcc;
+
+ if (cq_level > 15) {
+ pr_err("the CQ level is out of range\n");
+ return -EINVAL;
+ }
+
+ query_opts.cid = CEETM_COMMAND_TCFC | lni->idx;
+ query_opts.dcpid = lni->dcp_idx;
+ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result);
+ if (ret)
+ return ret;
+ lnitcfcc = (u8)(query_result.tcfc_query.lnitcfcc >>
+ QMAN_CEETM_LNITCFCC_CQ_LEVEL_SHIFT(cq_level));
+ if (lnitcfcc & QMAN_CEETM_LNITCFCC_ENABLE)
+ *traffic_class = lnitcfcc & QMAN_CEETM_LNITCFCC_TC_MASK;
+ else
+ *traffic_class = -1;
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_lni_get_tcfcc);
+
+#define QMAN_CEETM_ENABLE_CHANNEL_SHAPER 0x80
+int qman_ceetm_channel_claim(struct qm_ceetm_channel **channel,
+ struct qm_ceetm_lni *lni)
+{
+ struct qm_ceetm_channel *p;
+ u32 channel_idx;
+ int ret = 0;
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts;
+ static u8 map;
+
+ if (lni->dcp_idx == qm_dc_portal_fman0)
+ ret = qman_alloc_ceetm0_channel(&channel_idx);
+ if (lni->dcp_idx == qm_dc_portal_fman1)
+ ret = qman_alloc_ceetm1_channel(&channel_idx);
+ if (ret) {
+ pr_err("The is no channel available for LNI#%d\n", lni->idx);
+ return -ENODEV;
+ }
+
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+ p->idx = channel_idx;
+ p->dcp_idx = lni->dcp_idx;
+ list_add_tail(&p->node, &lni->channels);
+ INIT_LIST_HEAD(&p->class_queues);
+ INIT_LIST_HEAD(&p->ccgs);
+ config_opts.cid = CEETM_COMMAND_CHANNEL_MAPPING | channel_idx;
+ config_opts.dcpid = lni->dcp_idx;
+ map = (u8)~QMAN_CEETM_ENABLE_CHANNEL_SHAPER;
+ map &= lni->idx;
+ config_opts.channel_mapping.map = map;
+ if (qman_ceetm_configure_mapping_shaper_tcfc(&config_opts)) {
+ pr_err("Can't map channel#%d for LNI#%d\n",
+ channel_idx, lni->idx);
+ return -EINVAL;
+ }
+ *channel = p;
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_channel_claim);
+
+int qman_ceetm_channel_release(struct qm_ceetm_channel *channel)
+{
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts;
+ if (!list_empty(&channel->class_queues)) {
+ pr_err("CEETM channel#%d has class queue unreleased!\n",
+ channel->idx);
+ return -EBUSY;
+ }
+ if (!list_empty(&channel->ccgs)) {
+ pr_err("CEETM channel#%d has ccg unreleased!\n",
+ channel->idx);
+ return -EBUSY;
+ }
+
+ config_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx;
+ config_opts.dcpid = channel->dcp_idx;
+ memset(&config_opts.shaper_config, 0,
+ sizeof(config_opts.shaper_config));
+ if (qman_ceetm_configure_mapping_shaper_tcfc(&config_opts)) {
+ pr_err("Can't reset channel shapping parameters\n");
+ return -EINVAL;
+ }
+
+ if (channel->dcp_idx == qm_dc_portal_fman0)
+ qman_release_ceetm0_channelid(channel->idx);
+ if (channel->dcp_idx == qm_dc_portal_fman1)
+ qman_release_ceetm1_channelid(channel->idx);
+ list_del(&channel->node);
+ kfree(channel);
+
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_channel_release);
+
+int qman_ceetm_channel_enable_shaper(struct qm_ceetm_channel *channel,
+ int coupled)
+{
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts;
+ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result;
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts;
+ u8 map;
+
+ if (channel->shaper_enable == 1) {
+ pr_err("This channel shaper has been enabled!\n");
+ return -EINVAL;
+ }
+
+ channel->shaper_enable = 1;
+ channel->shaper_couple = coupled;
+
+ query_opts.cid = (u16)(CEETM_COMMAND_CHANNEL_MAPPING | channel->idx);
+ query_opts.dcpid = (u8)channel->dcp_idx;
+
+ if (qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result)) {
+ pr_err("Can't query channel mapping\n");
+ return -EINVAL;
+ }
+
+ map = query_result.channel_mapping_query.map;
+ map |= QMAN_CEETM_ENABLE_CHANNEL_SHAPER;
+
+ config_opts.cid = CEETM_COMMAND_CHANNEL_MAPPING | channel->idx;
+ config_opts.dcpid = channel->dcp_idx;
+ config_opts.channel_mapping.map = map;
+ if (qman_ceetm_configure_mapping_shaper_tcfc(&config_opts)) {
+ pr_err("Can't enable shaper for channel #%d\n",
+ channel->idx);
+ return -EINVAL;
+ }
+
+ config_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx;
+ config_opts.shaper_config.cpl = coupled << 7;
+ config_opts.shaper_config.crtcr = (channel->cr_token_rate.whole << 13) |
+ channel->cr_token_rate.fraction;
+ config_opts.shaper_config.ertcr = (channel->er_token_rate.whole << 13) |
+ channel->er_token_rate.fraction;
+ config_opts.shaper_config.crtbl = channel->cr_token_bucket_limit;
+ config_opts.shaper_config.ertbl = channel->er_token_bucket_limit;
+ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts);
+}
+EXPORT_SYMBOL(qman_ceetm_channel_enable_shaper);
+
+int qman_ceetm_channel_disable_shaper(struct qm_ceetm_channel *channel)
+{
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts;
+ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result;
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts;
+ u8 map;
+
+ if (channel->shaper_enable == 0) {
+ pr_err("This channel shaper has been disabled\n");
+ return -EINVAL;
+ }
+
+ query_opts.cid = CEETM_COMMAND_CHANNEL_MAPPING | channel->idx;
+ query_opts.dcpid = channel->dcp_idx;
+
+ if (qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result)) {
+ pr_err("Can't query channel mapping\n");
+ return -EINVAL;
+ }
+
+ map = query_result.channel_mapping_query.map;
+ map &= ~QMAN_CEETM_ENABLE_CHANNEL_SHAPER;
+
+ config_opts.cid = CEETM_COMMAND_CHANNEL_MAPPING | channel->idx;
+ config_opts.dcpid = channel->dcp_idx;
+ config_opts.channel_mapping.map = map;
+ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts);
+}
+EXPORT_SYMBOL(qman_ceetm_channel_disable_shaper);
+
+int qman_ceetm_channel_set_commit_rate(struct qm_ceetm_channel *channel,
+ const struct qm_ceetm_rate *token_rate,
+ u16 token_limit)
+{
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts;
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts;
+ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result;
+ int ret;
+
+ if (!channel->shaper_enable) {
+ pr_err("This channel is unshaped\n");
+ return -EINVAL;
+ }
+
+ query_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx;
+ query_opts.dcpid = channel->dcp_idx;
+
+ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result);
+ if (ret) {
+ pr_err("Fail to get the current channel shaper setting\n");
+ return -EINVAL;
+ }
+
+ channel->cr_token_rate.whole = token_rate->whole;
+ channel->cr_token_rate.fraction = token_rate->fraction;
+ channel->cr_token_bucket_limit = token_limit;
+ config_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx;
+ config_opts.dcpid = channel->dcp_idx;
+ config_opts.shaper_config.crtcr = (token_rate->whole << 13) |
+ (token_rate->fraction);
+ config_opts.shaper_config.crtbl = token_limit;
+ config_opts.shaper_config.cpl = query_result.shaper_query.cpl;
+ config_opts.shaper_config.ertcr = query_result.shaper_query.ertcr;
+ config_opts.shaper_config.ertbl = query_result.shaper_query.ertbl;
+ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts);
+}
+EXPORT_SYMBOL(qman_ceetm_channel_set_commit_rate);
+
+int qman_ceetm_channel_get_commit_rate(struct qm_ceetm_channel *channel,
+ struct qm_ceetm_rate *token_rate,
+ u16 *token_limit)
+{
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts;
+ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result;
+ int ret;
+
+ query_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx;
+ query_opts.dcpid = channel->dcp_idx;
+
+ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result);
+ if (ret | !query_result.shaper_query.crtcr |
+ !query_result.shaper_query.crtbl) {
+ pr_err("The channel commit rate or limit is not set\n");
+ return -EINVAL;
+ }
+ token_rate->whole = query_result.shaper_query.crtcr >> 13;
+ token_rate->fraction = query_result.shaper_query.crtcr & 0x1FFF;
+ *token_limit = query_result.shaper_query.crtbl;
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_channel_get_commit_rate);
+
+int qman_ceetm_channel_set_excess_rate(struct qm_ceetm_channel *channel,
+ const struct qm_ceetm_rate *token_rate,
+ u16 token_limit)
+{
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts;
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts;
+ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result;
+ int ret;
+
+ if (!channel->shaper_enable) {
+ pr_err("This channel is unshaped\n");
+ return -EINVAL;
+ }
+
+ query_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx;
+ query_opts.dcpid = channel->dcp_idx;
+ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result);
+ if (ret) {
+ pr_err("Fail to get the current channel shaper setting\n");
+ return -EINVAL;
+ }
+
+ channel->er_token_rate.whole = token_rate->whole;
+ channel->er_token_rate.fraction = token_rate->fraction;
+ channel->er_token_bucket_limit = token_limit;
+ config_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx;
+ config_opts.dcpid = channel->dcp_idx;
+ config_opts.shaper_config.ertcr =
+ (token_rate->whole << 13) | (token_rate->fraction);
+ config_opts.shaper_config.ertbl = token_limit;
+ config_opts.shaper_config.cpl = query_result.shaper_query.cpl;
+ config_opts.shaper_config.crtcr = query_result.shaper_query.crtcr;
+ config_opts.shaper_config.crtbl = query_result.shaper_query.crtbl;
+ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts);
+}
+EXPORT_SYMBOL(qman_ceetm_channel_set_excess_rate);
+
+int qman_ceetm_channel_get_excess_rate(struct qm_ceetm_channel *channel,
+ struct qm_ceetm_rate *token_rate,
+ u16 *token_limit)
+{
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts;
+ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result;
+ int ret;
+
+ query_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx;
+ query_opts.dcpid = channel->dcp_idx;
+ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result);
+ if (ret | !query_result.shaper_query.ertcr |
+ !query_result.shaper_query.ertbl) {
+ pr_err("The channel excess rate or limit is not set\n");
+ return -EINVAL;
+ }
+ token_rate->whole = query_result.shaper_query.ertcr >> 13;
+ token_rate->fraction = query_result.shaper_query.ertcr & 0x1FFF;
+ *token_limit = query_result.shaper_query.ertbl;
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_channel_get_excess_rate);
+
+int qman_ceetm_channel_set_weight(struct qm_ceetm_channel *channel,
+ u16 token_limit)
+{
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_config config_opts;
+
+ if (channel->shaper_enable) {
+ pr_err("This channel is a shaped one\n");
+ return -EINVAL;
+ }
+
+ channel->cr_token_bucket_limit = token_limit;
+ config_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx;
+ config_opts.dcpid = channel->dcp_idx;
+ config_opts.shaper_config.crtbl = token_limit;
+ return qman_ceetm_configure_mapping_shaper_tcfc(&config_opts);
+}
+EXPORT_SYMBOL(qman_ceetm_channel_set_weight);
+
+int qman_ceetm_channel_get_weight(struct qm_ceetm_channel *channel,
+ u16 *token_limit)
+{
+ struct qm_mcc_ceetm_mapping_shaper_tcfc_query query_opts;
+ struct qm_mcr_ceetm_mapping_shaper_tcfc_query query_result;
+ int ret;
+
+ query_opts.cid = CEETM_COMMAND_CHANNEL_SHAPER | channel->idx;
+ query_opts.dcpid = channel->dcp_idx;
+ ret = qman_ceetm_query_mapping_shaper_tcfc(&query_opts, &query_result);
+ if (ret | !query_result.shaper_query.crtbl) {
+ pr_err("This unshaped channel's uFQ wight is unavailable\n");
+ return -EINVAL;
+ }
+ *token_limit = query_result.shaper_query.crtbl;
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_channel_get_weight);
+
+int qman_ceetm_channel_set_group(struct qm_ceetm_channel *channel, int group_b,
+ unsigned int prio_a, unsigned int prio_b)
+{
+ struct qm_mcc_ceetm_class_scheduler_config config_opts;
+ struct qm_mcr_ceetm_class_scheduler_query query_result;
+ int i;
+
+ if (!prio_a || (prio_a > 7)) {
+ pr_err("The priority of group A is out of range\n");
+ return -EINVAL;
+ }
+ if ((group_b && !prio_b) || (prio_b > 7)) {
+ pr_err("The priority of group B is out of range\n");
+ return -EINVAL;
+ }
+
+ if (qman_ceetm_query_class_scheduler(channel, &query_result)) {
+ pr_err("Can't query channel#%d's scheduler!\n", channel->idx);
+ return -EINVAL;
+ }
+
+ config_opts.cqcid = channel->idx;
+ config_opts.dcpid = channel->dcp_idx;
+ if (!group_b)
+ config_opts.gpc = (u8)((1 << 6) | prio_a);
+ else
+ config_opts.gpc = (u8)((prio_b << 3) | prio_a);
+
+ for (i = 0; i < 8; i++)
+ config_opts.w[i] = query_result.w[i];
+ config_opts.crem = query_result.crem;
+ config_opts.erem = query_result.erem;
+
+ return qman_ceetm_configure_class_scheduler(&config_opts);
+}
+EXPORT_SYMBOL(qman_ceetm_channel_set_group);
+
+int qman_ceetm_channel_get_group(struct qm_ceetm_channel *channel, int *group_b,
+ unsigned int *prio_a, unsigned int *prio_b)
+{
+ struct qm_mcr_ceetm_class_scheduler_query query_result;
+
+ if (qman_ceetm_query_class_scheduler(channel, &query_result)) {
+ pr_err("Can't query channel#%d's scheduler!\n", channel->idx);
+ return -EINVAL;
+ }
+ *group_b = (query_result.gpc >> 6) & 0x1;
+ *prio_a = query_result.gpc & 0x3;
+ *prio_b = (query_result.gpc >> 3) & 0x3;
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_channel_get_group);
+
+#define GROUP_A_ELIGIBILITY_SET (1 << 8)
+#define GROUP_B_ELIGIBILITY_SET (1 << 9)
+#define CQ_ELIGIBILITY_SET(n) (1 << (7 - n))
+int qman_ceetm_channel_set_group_cr_eligibility(struct qm_ceetm_channel
+ *channel, int group_b, int cre)
+{
+ struct qm_mcc_ceetm_class_scheduler_config csch_config;
+ struct qm_mcr_ceetm_class_scheduler_query csch_query;
+ int i;
+
+ if (qman_ceetm_query_class_scheduler(channel, &csch_query)) {
+ pr_err("Cannot get the channel %d scheduler setting.\n",
+ channel->idx);
+ return -EINVAL;
+ }
+ csch_config.cqcid = channel->idx;
+ csch_config.dcpid = channel->dcp_idx;
+ csch_config.gpc = csch_query.gpc;
+ for (i = 0; i < 8; i++)
+ csch_config.w[i] = csch_query.w[i];
+ csch_config.erem = csch_query.erem;
+ if (group_b)
+ csch_config.crem = (csch_query.crem & ~GROUP_B_ELIGIBILITY_SET)
+ | (cre ? GROUP_B_ELIGIBILITY_SET : 0);
+ else
+ csch_config.crem = (csch_query.crem & ~GROUP_A_ELIGIBILITY_SET)
+ | (cre ? GROUP_A_ELIGIBILITY_SET : 0);
+
+ if (qman_ceetm_configure_class_scheduler(&csch_config)) {
+ pr_err("Cannot config channel %d's scheduler with "
+ "group_%c's cr eligibility\n", channel->idx,
+ group_b ? 'b' : 'a');
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_channel_set_group_cr_eligibility);
+
+int qman_ceetm_channel_set_group_er_eligibility(struct qm_ceetm_channel
+ *channel, int group_b, int ere)
+{
+ struct qm_mcc_ceetm_class_scheduler_config csch_config;
+ struct qm_mcr_ceetm_class_scheduler_query csch_query;
+ int i;
+
+ if (qman_ceetm_query_class_scheduler(channel, &csch_query)) {
+ pr_err("Cannot get the channel %d scheduler setting.\n",
+ channel->idx);
+ return -EINVAL;
+ }
+ csch_config.cqcid = channel->idx;
+ csch_config.dcpid = channel->dcp_idx;
+ csch_config.gpc = csch_query.gpc;
+ for (i = 0; i < 8; i++)
+ csch_config.w[i] = csch_query.w[i];
+ csch_config.crem = csch_query.crem;
+ if (group_b)
+ csch_config.erem = (csch_query.erem & ~GROUP_B_ELIGIBILITY_SET)
+ | (ere ? GROUP_B_ELIGIBILITY_SET : 0);
+ else
+ csch_config.erem = (csch_query.erem & ~GROUP_A_ELIGIBILITY_SET)
+ | (ere ? GROUP_A_ELIGIBILITY_SET : 0);
+
+ if (qman_ceetm_configure_class_scheduler(&csch_config)) {
+ pr_err("Cannot config channel %d's scheduler with "
+ "group_%c's er eligibility\n", channel->idx,
+ group_b ? 'b' : 'a');
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_channel_set_group_er_eligibility);
+
+int qman_ceetm_channel_set_cq_cr_eligibility(struct qm_ceetm_channel *channel,
+ unsigned int idx, int cre)
+{
+ struct qm_mcc_ceetm_class_scheduler_config csch_config;
+ struct qm_mcr_ceetm_class_scheduler_query csch_query;
+ int i;
+
+ if (idx > 7) {
+ pr_err("CQ index is out of range\n");
+ return -EINVAL;
+ }
+ if (qman_ceetm_query_class_scheduler(channel, &csch_query)) {
+ pr_err("Cannot get the channel %d scheduler setting.\n",
+ channel->idx);
+ return -EINVAL;
+ }
+ csch_config.cqcid = channel->idx;
+ csch_config.dcpid = channel->dcp_idx;
+ csch_config.gpc = csch_query.gpc;
+ for (i = 0; i < 8; i++)
+ csch_config.w[i] = csch_query.w[i];
+ csch_config.erem = csch_query.erem;
+ csch_config.crem = (csch_query.crem & ~CQ_ELIGIBILITY_SET(idx)) |
+ (cre ? CQ_ELIGIBILITY_SET(idx) : 0);
+ if (qman_ceetm_configure_class_scheduler(&csch_config)) {
+ pr_err("Cannot config channel scheduler to set "
+ "cr eligibility mask for CQ#%d\n", idx);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_channel_set_cq_cr_eligibility);
+
+int qman_ceetm_channel_set_cq_er_eligibility(struct qm_ceetm_channel *channel,
+ unsigned int idx, int ere)
+{
+ struct qm_mcc_ceetm_class_scheduler_config csch_config;
+ struct qm_mcr_ceetm_class_scheduler_query csch_query;
+ int i;
+
+ if (idx > 7) {
+ pr_err("CQ index is out of range\n");
+ return -EINVAL;
+ }
+ if (qman_ceetm_query_class_scheduler(channel, &csch_query)) {
+ pr_err("Cannot get the channel %d scheduler setting.\n",
+ channel->idx);
+ return -EINVAL;
+ }
+ csch_config.cqcid = channel->idx;
+ csch_config.dcpid = channel->dcp_idx;
+ csch_config.gpc = csch_query.gpc;
+ for (i = 0; i < 8; i++)
+ csch_config.w[i] = csch_query.w[i];
+ csch_config.crem = csch_query.crem;
+ csch_config.erem = (csch_query.erem & ~CQ_ELIGIBILITY_SET(idx)) |
+ (ere ? CQ_ELIGIBILITY_SET(idx) : 0);
+ if (qman_ceetm_configure_class_scheduler(&csch_config)) {
+ pr_err("Cannot config channel scheduler to set "
+ "er eligibility mask for CQ#%d\n", idx);
+ return -EINVAL;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_channel_set_cq_er_eligibility);
+
+int qman_ceetm_cq_claim(struct qm_ceetm_cq **cq,
+ struct qm_ceetm_channel *channel, unsigned int idx,
+ struct qm_ceetm_ccg *ccg)
+{
+ struct qm_ceetm_cq *p;
+ struct qm_mcc_ceetm_cq_config cq_config;
+
+ if (idx > 7) {
+ pr_err("The independent class queue id is out of range\n");
+ return -EINVAL;
+ }
+
+ list_for_each_entry(p, &channel->class_queues, node) {
+ if (p->idx == idx) {
+ pr_err("The CQ#%d has been claimed!\n", idx);
+ return -EINVAL;
+ }
+ }
+
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (!p) {
+ pr_err("Can't allocate memory for CQ#%d!\n", idx);
+ return -ENOMEM;
+ }
+
+ list_add_tail(&p->node, &channel->class_queues);
+ p->idx = idx;
+ p->is_claimed = 1;
+ p->parent = channel;
+ INIT_LIST_HEAD(&p->bound_lfqids);
+
+ if (ccg) {
+ cq_config.cqid = (channel->idx << 4) | idx;
+ cq_config.dcpid = channel->dcp_idx;
+ cq_config.ccgid = ccg->idx;
+ if (qman_ceetm_configure_cq(&cq_config)) {
+ pr_err("Can't configure the CQ#%d with CCGRID#%d\n",
+ idx, ccg->idx);
+ return -EINVAL;
+ }
+ }
+
+ *cq = p;
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_cq_claim);
+
+int qman_ceetm_cq_claim_A(struct qm_ceetm_cq **cq,
+ struct qm_ceetm_channel *channel, unsigned int idx,
+ struct qm_ceetm_ccg *ccg)
+{
+ struct qm_ceetm_cq *p;
+ struct qm_mcc_ceetm_cq_config cq_config;
+
+ if ((idx < 7) || (idx > 15)) {
+ pr_err("This grouped class queue id is out of range\n");
+ return -EINVAL;
+ }
+
+ list_for_each_entry(p, &channel->class_queues, node) {
+ if (p->idx == idx) {
+ pr_err("The CQ#%d has been claimed!\n", idx);
+ return -EINVAL;
+ }
+ }
+
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (!p) {
+ pr_err("Can't allocate memory for CQ#%d!\n", idx);
+ return -ENOMEM;
+ }
+
+ list_add_tail(&p->node, &channel->class_queues);
+ p->idx = idx;
+ p->is_claimed = 1;
+ p->parent = channel;
+ INIT_LIST_HEAD(&p->bound_lfqids);
+
+ if (ccg) {
+ cq_config.cqid = (channel->idx << 4) | idx;
+ cq_config.dcpid = channel->dcp_idx;
+ cq_config.ccgid = ccg->idx;
+ if (qman_ceetm_configure_cq(&cq_config)) {
+ pr_err("Can't configure the CQ#%d with CCGRID#%d\n",
+ idx, ccg->idx);
+ return -EINVAL;
+ }
+ }
+ *cq = p;
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_cq_claim_A);
+
+int qman_ceetm_cq_claim_B(struct qm_ceetm_cq **cq,
+ struct qm_ceetm_channel *channel, unsigned int idx,
+ struct qm_ceetm_ccg *ccg)
+{
+ struct qm_ceetm_cq *p;
+ struct qm_mcc_ceetm_cq_config cq_config;
+
+ if ((idx < 11) || (idx > 15)) {
+ pr_err("This grouped class queue id is out of range\n");
+ return -EINVAL;
+ }
+
+ list_for_each_entry(p, &channel->class_queues, node) {
+ if (p->idx == idx) {
+ pr_err("The CQ#%d has been claimed!\n", idx);
+ return -EINVAL;
+ }
+ }
+
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (!p) {
+ pr_err("Can't allocate memory for CQ#%d!\n", idx);
+ return -ENOMEM;
+ }
+
+ list_add_tail(&p->node, &channel->class_queues);
+ p->idx = idx;
+ p->is_claimed = 1;
+ p->parent = channel;
+ INIT_LIST_HEAD(&p->bound_lfqids);
+
+ if (ccg) {
+ cq_config.cqid = (channel->idx << 4) | idx;
+ cq_config.dcpid = channel->dcp_idx;
+ cq_config.ccgid = ccg->idx;
+ if (qman_ceetm_configure_cq(&cq_config)) {
+ pr_err("Can't configure the CQ#%d with CCGRID#%d\n",
+ idx, ccg->idx);
+ return -EINVAL;
+ }
+ }
+ *cq = p;
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_cq_claim_B);
+
+int qman_ceetm_cq_release(struct qm_ceetm_cq *cq)
+{
+ if (!list_empty(&cq->bound_lfqids)) {
+ pr_err("The CQ#%d has unreleased LFQID\n", cq->idx);
+ return -EBUSY;
+ }
+ list_del(&cq->node);
+ kfree(cq);
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_cq_release);
+
+int qman_ceetm_set_queue_weight(struct qm_ceetm_cq *cq,
+ struct qm_ceetm_weight_code *weight_code)
+{
+ struct qm_mcc_ceetm_class_scheduler_config config_opts;
+ struct qm_mcr_ceetm_class_scheduler_query query_result;
+ int i;
+
+ if (cq->idx < 8) {
+ pr_err("Can not set weight for ungrouped class queue\n");
+ return -EINVAL;
+ }
+
+ if (qman_ceetm_query_class_scheduler(cq->parent, &query_result)) {
+ pr_err("Can't query channel#%d's scheduler!\n",
+ cq->parent->idx);
+ return -EINVAL;
+ }
+
+ config_opts.cqcid = cq->parent->idx;
+ config_opts.dcpid = cq->parent->dcp_idx;
+ config_opts.crem = query_result.crem;
+ config_opts.erem = query_result.erem;
+ config_opts.gpc = query_result.gpc;
+ for (i = 0; i < 8; i++)
+ config_opts.w[i] = query_result.w[i];
+ config_opts.w[cq->idx - 8] = ((weight_code->y << 3) |
+ (weight_code->x & 0x7));
+ return qman_ceetm_configure_class_scheduler(&config_opts);
+}
+EXPORT_SYMBOL(qman_ceetm_set_queue_weight);
+
+int qman_ceetm_get_queue_weight(struct qm_ceetm_cq *cq,
+ struct qm_ceetm_weight_code *weight_code)
+{
+ struct qm_mcr_ceetm_class_scheduler_query query_result;
+
+ if (cq->idx < 8) {
+ pr_err("Can not get weight for ungrouped class queue\n");
+ return -EINVAL;
+ }
+
+ if (qman_ceetm_query_class_scheduler(cq->parent,
+ &query_result)) {
+ pr_err("Can't get the weight code for CQ#%d!\n", cq->idx);
+ return -EINVAL;
+ }
+ weight_code->y = query_result.w[cq->idx - 8] >> 3;
+ weight_code->x = query_result.w[cq->idx - 8] & 0x7;
+
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_get_queue_weight);
+
+/* The WBFS code is represent as {x,y}, the effect wieght can be calculated as:
+ * effective weight = 2^x / (1 - (y/64))
+ * = 2^(x+6) / (64 - y)
+ */
+static void reduce_fraction(u32 *n, u32 *d)
+{
+ u32 factor = 2;
+ u32 lesser = (*n < *d) ? *n : *d;
+ /* If factor exceeds the square-root of the lesser of *n and *d,
+ * then there's no point continuing. Proof: if there was a factor
+ * bigger than the square root, that would imply there exists
+ * another factor smaller than the square-root with which it
+ * multiplies to give 'lesser' - but that's a contradiction
+ * because the other factor would have already been found and
+ * divided out.
+ */
+ while ((factor * factor) <= lesser) {
+ /* If 'factor' is a factor of *n and *d, divide them both
+ * by 'factor' as many times as possible.
+ */
+ while (!(*n % factor) && !(*d % factor)) {
+ *n /= factor;
+ *d /= factor;
+ lesser /= factor;
+ }
+ if (factor == 2)
+ factor = 3;
+ else
+ factor += 2;
+ }
+}
+
+int qman_ceetm_wbfs2ratio(struct qm_ceetm_weight_code *weight_code,
+ u32 *numerator,
+ u32 *denominator)
+{
+ *numerator = (u32) 1 << (weight_code->x + 6);
+ *denominator = 64 - weight_code->y;
+ reduce_fraction(numerator, denominator);
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_wbfs2ratio);
+
+/* For a given x, the weight is between 2^x (inclusive) and 2^(x+1) (exclusive).
+ * So find 'x' by range, and then estimate 'y' using:
+ * 64 - y = 2^(x + 6) / weight
+ * = 2^(x + 6) / (n/d)
+ * = d * 2^(x+6) / n
+ * y = 64 - (d * 2^(x+6) / n)
+ */
+int qman_ceetm_ratio2wbfs(u32 numerator,
+ u32 denominator,
+ struct qm_ceetm_weight_code *weight_code,
+ int rounding)
+{
+ unsigned int y, x = 0;
+ /* search incrementing 'x' until:
+ * weight < 2^(x+1)
+ * n/d < 2^(x+1)
+ * n < d * 2^(x+1)
+ */
+ while ((x < 8) && (numerator >= (denominator << (x + 1))))
+ x++;
+ if (x >= 8)
+ return -ERANGE;
+ /* because of the subtraction, use '-rounding' */
+ y = 64 - ROUNDING(denominator << (x + 6), numerator, -rounding);
+ if (y >= 32)
+ return -ERANGE;
+ weight_code->x = x;
+ weight_code->y = y;
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_ratio2wbfs);
+
+int qman_ceetm_cq_get_dequeue_statistics(struct qm_ceetm_cq *cq, u32 flags,
+ u64 *frame_count, u64 *byte_count)
+{
+ struct qm_mcr_ceetm_statistics_query result;
+ u16 cid, command_type;
+ enum qm_dc_portal dcp_idx;
+ int ret;
+
+ cid = (cq->parent->idx << 4) | cq->idx;
+ dcp_idx = cq->parent->dcp_idx;
+ if (flags == QMAN_CEETM_FLAG_CLEAR_STATISTICS_COUNTER)
+ command_type = CEETM_QUERY_DEQUEUE_CLEAR_STATISTICS;
+ else
+ command_type = CEETM_QUERY_DEQUEUE_STATISTICS;
+
+ ret = qman_ceetm_query_statistics(cid, dcp_idx, command_type, &result);
+ if (ret) {
+ pr_err("Can't query the statistics of CQ#%d!\n", cq->idx);
+ return -EINVAL;
+ }
+
+ *frame_count = result.frm_cnt;
+ *byte_count = result.byte_cnt;
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_cq_get_dequeue_statistics);
+
+#define CEETM_LFQMT_LFQID_MSB 0xF00000
+#define CEETM_LFQMT_LFQID_LSB 0x000FFF
+int qman_ceetm_lfq_claim(struct qm_ceetm_lfq **lfq,
+ struct qm_ceetm_cq *cq)
+{
+ struct qm_ceetm_lfq *p;
+ u32 lfqid;
+ int ret = 0;
+ struct qm_mcc_ceetm_lfqmt_config lfqmt_config;
+
+ if (cq->parent->dcp_idx == qm_dc_portal_fman0)
+ ret = qman_alloc_ceetm0_lfqid(&lfqid);
+ if (cq->parent->dcp_idx == qm_dc_portal_fman1)
+ ret = qman_alloc_ceetm1_lfqid(&lfqid);
+ if (ret) {
+ pr_err("There is no lfqid avalaible for CQ#%d!\n", cq->idx);
+ return -ENODEV;
+ }
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+ p->idx = lfqid;
+ p->dctidx = (u16)(lfqid & CEETM_LFQMT_LFQID_LSB);
+ p->parent = cq->parent;
+ list_add_tail(&p->node, &cq->bound_lfqids);
+
+ lfqmt_config.lfqid = CEETM_LFQMT_LFQID_MSB |
+ (cq->parent->dcp_idx << 16) |
+ (lfqid & CEETM_LFQMT_LFQID_LSB);
+ lfqmt_config.cqid = (cq->parent->idx << 4) | (cq->idx);
+ lfqmt_config.dctidx = p->dctidx;
+ if (qman_ceetm_configure_lfqmt(&lfqmt_config)) {
+ pr_err("Can't configure LFQMT for LFQID#%d @ CQ#%d\n",
+ lfqid, cq->idx);
+ return -EINVAL;
+ }
+ *lfq = p;
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_lfq_claim);
+
+int qman_ceetm_lfq_release(struct qm_ceetm_lfq *lfq)
+{
+ if (lfq->parent->dcp_idx == qm_dc_portal_fman0)
+ qman_release_ceetm0_lfqid(lfq->idx);
+ if (lfq->parent->dcp_idx == qm_dc_portal_fman1)
+ qman_release_ceetm1_lfqid(lfq->idx);
+ list_del(&lfq->node);
+ kfree(lfq);
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_lfq_release);
+
+int qman_ceetm_lfq_set_context(struct qm_ceetm_lfq *lfq, u64 context_a,
+ u32 context_b)
+{
+ struct qm_mcc_ceetm_dct_config dct_config;
+ lfq->context_a = context_a;
+ lfq->context_b = context_b;
+ dct_config.dctidx = (u16)lfq->dctidx;
+ dct_config.dcpid = lfq->parent->dcp_idx;
+ dct_config.context_b = context_b;
+ dct_config.context_a = context_a;
+ return qman_ceetm_configure_dct(&dct_config);
+}
+EXPORT_SYMBOL(qman_ceetm_lfq_set_context);
+
+int qman_ceetm_lfq_get_context(struct qm_ceetm_lfq *lfq, u64 *context_a,
+ u32 *context_b)
+{
+ struct qm_mcc_ceetm_dct_query dct_query;
+ struct qm_mcr_ceetm_dct_query query_result;
+
+ dct_query.dctidx = (u16)lfq->dctidx;
+ dct_query.dcpid = lfq->parent->dcp_idx;
+ if (qman_ceetm_query_dct(&dct_query, &query_result)) {
+ pr_err("Can't query LFQID#%d's context!\n", lfq->idx);
+ return -EINVAL;
+ }
+ *context_a = query_result.context_a;
+ *context_b = query_result.context_b;
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_lfq_get_context);
+
+int qman_ceetm_create_fq(struct qm_ceetm_lfq *lfq, struct qman_fq *fq)
+{
+ spin_lock_init(&fq->fqlock);
+ fq->fqid = lfq->idx;
+ fq->flags = QMAN_FQ_FLAG_NO_MODIFY;
+ if (lfq->ern)
+ fq->cb.ern = lfq->ern;
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+ if (unlikely(find_empty_fq_table_entry(&fq->key, fq)))
+ return -ENOMEM;
+#endif
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_create_fq);
+
+int qman_ceetm_ccg_claim(struct qm_ceetm_ccg **ccg,
+ struct qm_ceetm_channel *channel,
+ unsigned int idx,
+ void (*cscn)(struct qm_ceetm_ccg *,
+ void *cb_ctx,
+ int congested),
+ void *cb_ctx)
+{
+ struct qm_ceetm_ccg *p;
+
+ if ((idx < 0) || (idx > 15)) {
+ pr_err("The given ccg index is out of range\n");
+ return -EINVAL;
+ }
+
+ list_for_each_entry(p, &channel->ccgs, node) {
+ if (p->idx == idx) {
+ pr_err("The CCG#%d has been claimed\n", idx);
+ return -EINVAL;
+ }
+ }
+
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (!p) {
+ pr_err("Can't allocate memory for CCG#%d!\n", idx);
+ return -ENOMEM;
+ }
+
+ list_add_tail(&p->node, &channel->ccgs);
+
+ p->idx = idx;
+ p->parent = channel;
+ p->cb = cscn;
+ p->cb_ctx = cb_ctx;
+
+ *ccg = p;
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_ccg_claim);
+
+int qman_ceetm_ccg_release(struct qm_ceetm_ccg *ccg)
+{
+ unsigned long irqflags __maybe_unused;
+ struct qm_ceetm_ccg *i;
+ struct qm_mcc_ceetm_ccgr_config config_opts;
+ int ret = 0;
+ struct qman_portal *p = get_affine_portal();
+
+ memset(&config_opts, 0, sizeof(struct qm_mcc_ceetm_ccgr_config));
+ spin_lock_irqsave(&p->ccgr_lock, irqflags);
+ list_del(&ccg->cb_node);
+ /*
+ * If there is no other CCG objects for this CCGID, update
+ * CSCN_TARG_UPP_CTR accordingly.
+ */
+ list_for_each_entry(i, &p->ccgr_cbs[ccg->parent->dcp_idx], cb_node)
+ if ((i->idx == ccg->idx) && i->cb)
+ goto release_lock;
+ config_opts.ccgrid = CEETM_CCGR_CM_CONFIGURE |
+ (ccg->parent->idx << 4) | ccg->idx;
+ config_opts.dcpid = ccg->parent->dcp_idx;
+ config_opts.we_mask = QM_CCGR_WE_CSCN_TUPD;
+ config_opts.cm_config.cscn_tupd = PORTAL_IDX(p);
+
+ ret = qman_ceetm_configure_ccgr(&config_opts);
+release_lock:
+ spin_unlock_irqrestore(&p->ccgr_lock, irqflags);
+
+ list_del(&ccg->node);
+ kfree(ccg);
+ return ret;
+}
+EXPORT_SYMBOL(qman_ceetm_ccg_release);
+
+int qman_ceetm_ccg_set(struct qm_ceetm_ccg *ccg, u16 we_mask,
+ const struct qm_ceetm_ccg_params *params)
+{
+ struct qm_mcc_ceetm_ccgr_config config_opts;
+ unsigned long irqflags __maybe_unused;
+ int ret;
+ struct qman_portal *p;
+
+ if (((ccg->parent->idx << 4) | ccg->idx) >= (2 * __CGR_NUM))
+ return -EINVAL;
+
+ p = get_affine_portal();
+
+ memset(&config_opts, 0, sizeof(struct qm_mcc_ceetm_ccgr_config));
+ spin_lock_irqsave(&p->ccgr_lock, irqflags);
+
+ config_opts.ccgrid = CEETM_CCGR_CM_CONFIGURE |
+ (ccg->parent->idx << 4) | ccg->idx;
+ config_opts.dcpid = ccg->parent->dcp_idx;
+ config_opts.we_mask = we_mask;
+ config_opts.we_mask |= QM_CCGR_WE_CSCN_TUPD;
+ config_opts.cm_config.cscn_tupd =
+ QM_CGR_TARG_UDP_CTRL_WRITE_BIT | PORTAL_IDX(p);
+ config_opts.cm_config.ctl = (params->wr_en_g << 6) |
+ (params->wr_en_y << 5) |
+ (params->wr_en_r << 4) |
+ (params->td_en << 3) |
+ (params->td_mode << 2) |
+ (params->cscn_en << 1) |
+ (params->mode);
+ config_opts.cm_config.oal = params->oal;
+ config_opts.cm_config.cs_thres = params->cs_thres_in;
+ config_opts.cm_config.cs_thres_x = params->cs_thres_out;
+ config_opts.cm_config.td_thres = params->td_thres;
+ config_opts.cm_config.wr_parm_g = params->wr_parm_g;
+ config_opts.cm_config.wr_parm_y = params->wr_parm_y;
+ config_opts.cm_config.wr_parm_r = params->wr_parm_r;
+ ret = qman_ceetm_configure_ccgr(&config_opts);
+ if (ret) {
+ pr_err("Configure CCGR CM failed!\n");
+ goto release_lock;
+ }
+
+ list_add(&ccg->cb_node, &p->ccgr_cbs[ccg->parent->dcp_idx]);
+release_lock:
+ spin_unlock_irqrestore(&p->ccgr_lock, irqflags);
+ put_affine_portal();
+ return ret;
+}
+EXPORT_SYMBOL(qman_ceetm_ccg_set);
+
+#define CEETM_CCGR_CTL_MASK 0x01
+int qman_ceetm_ccg_get(struct qm_ceetm_ccg *ccg,
+ struct qm_ceetm_ccg_params *params)
+{
+ struct qm_mcc_ceetm_ccgr_query query_opts;
+ struct qm_mcr_ceetm_ccgr_query query_result;
+
+ query_opts.ccgrid = CEETM_CCGR_CM_QUERY |
+ (ccg->parent->idx << 4) | ccg->idx;
+ query_opts.dcpid = ccg->parent->dcp_idx;
+
+ if (qman_ceetm_query_ccgr(&query_opts, &query_result)) {
+ pr_err("Can't query CCGR#%d\n", ccg->idx);
+ return -EINVAL;
+ }
+
+ params->wr_parm_r = query_result.cm_query.wr_parm_r;
+ params->wr_parm_y = query_result.cm_query.wr_parm_y;
+ params->wr_parm_g = query_result.cm_query.wr_parm_g;
+ params->td_thres = query_result.cm_query.td_thres;
+ params->cs_thres_out = query_result.cm_query.cs_thres_x;
+ params->cs_thres_in = query_result.cm_query.cs_thres;
+ params->oal = query_result.cm_query.oal;
+ params->wr_en_g = (query_result.cm_query.ctl >> 6) &
+ CEETM_CCGR_CTL_MASK;
+ params->wr_en_y = (query_result.cm_query.ctl >> 5) &
+ CEETM_CCGR_CTL_MASK;
+ params->wr_en_r = (query_result.cm_query.ctl >> 4) &
+ CEETM_CCGR_CTL_MASK;
+ params->td_en = (query_result.cm_query.ctl >> 3) &
+ CEETM_CCGR_CTL_MASK;
+ params->td_mode = (query_result.cm_query.ctl >> 2) &
+ CEETM_CCGR_CTL_MASK;
+ params->cscn_en = (query_result.cm_query.ctl >> 1) &
+ CEETM_CCGR_CTL_MASK;
+ params->mode = (query_result.cm_query.ctl & CEETM_CCGR_CTL_MASK);
+
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_ccg_get);
+
+int qman_ceetm_ccg_get_reject_statistics(struct qm_ceetm_ccg *ccg, u32 flags,
+ u64 *frame_count, u64 *byte_count)
+{
+ struct qm_mcr_ceetm_statistics_query result;
+ u16 cid, command_type;
+ enum qm_dc_portal dcp_idx;
+ int ret;
+
+ cid = (ccg->parent->idx << 4) | ccg->idx;
+ dcp_idx = ccg->parent->dcp_idx;
+ if (flags == QMAN_CEETM_FLAG_CLEAR_STATISTICS_COUNTER)
+ command_type = CEETM_QUERY_REJECT_CLEAR_STATISTICS;
+ else
+ command_type = CEETM_QUERY_REJECT_STATISTICS;
+
+ ret = qman_ceetm_query_statistics(cid, dcp_idx, command_type, &result);
+ if (ret) {
+ pr_err("Can't query the statistics of CCG#%d!\n", ccg->idx);
+ return -EINVAL;
+ }
+
+ *frame_count = result.frm_cnt;
+ *byte_count = result.byte_cnt;
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_ccg_get_reject_statistics);
+
+int qman_ceetm_cscn_swp_get(struct qm_ceetm_ccg *ccg,
+ u16 swp_idx,
+ unsigned int *cscn_enabled)
+{
+ struct qm_mcc_ceetm_ccgr_query query_opts;
+ struct qm_mcr_ceetm_ccgr_query query_result;
+ int i;
+
+ DPA_ASSERT(swp_idx < 127);
+ query_opts.ccgrid = CEETM_CCGR_CM_QUERY |
+ (ccg->parent->idx << 4) | ccg->idx;
+ query_opts.dcpid = ccg->parent->dcp_idx;
+
+ if (qman_ceetm_query_ccgr(&query_opts, &query_result)) {
+ pr_err("Can't query CCGR#%d\n", ccg->idx);
+ return -EINVAL;
+ }
+
+ i = swp_idx / 32;
+ i = 3 - i;
+ *cscn_enabled = (query_result.cm_query.cscn_targ_swp[i] >>
+ (31 - swp_idx % 32));
+
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_cscn_swp_get);
+
+int qman_ceetm_cscn_dcp_set(struct qm_ceetm_ccg *ccg,
+ u16 dcp_idx,
+ u8 vcgid,
+ unsigned int cscn_enabled,
+ u16 we_mask,
+ const struct qm_ceetm_ccg_params *params)
+{
+ struct qm_mcc_ceetm_ccgr_config config_opts;
+ int ret;
+
+ config_opts.ccgrid = CEETM_CCGR_CM_CONFIGURE |
+ (ccg->parent->idx << 4) | ccg->idx;
+ config_opts.dcpid = ccg->parent->dcp_idx;
+ config_opts.we_mask = we_mask | QM_CCGR_WE_CSCN_TUPD | QM_CCGR_WE_CDV;
+ config_opts.cm_config.cdv = vcgid;
+ config_opts.cm_config.cscn_tupd = (cscn_enabled << 15) |
+ QM_CGR_TARG_UDP_CTRL_DCP | dcp_idx;
+ config_opts.cm_config.ctl = (params->wr_en_g << 6) |
+ (params->wr_en_y << 5) |
+ (params->wr_en_r << 4) |
+ (params->td_en << 3) |
+ (params->td_mode << 2) |
+ (params->cscn_en << 1) |
+ (params->mode);
+ config_opts.cm_config.cs_thres = params->cs_thres_in;
+ config_opts.cm_config.cs_thres_x = params->cs_thres_out;
+ config_opts.cm_config.td_thres = params->td_thres;
+ config_opts.cm_config.wr_parm_g = params->wr_parm_g;
+ config_opts.cm_config.wr_parm_y = params->wr_parm_y;
+ config_opts.cm_config.wr_parm_r = params->wr_parm_r;
+
+ ret = qman_ceetm_configure_ccgr(&config_opts);
+ if (ret) {
+ pr_err("Configure CSCN_TARG_DCP failed!\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_cscn_dcp_set);
+
+int qman_ceetm_cscn_dcp_get(struct qm_ceetm_ccg *ccg,
+ u16 dcp_idx,
+ u8 *vcgid,
+ unsigned int *cscn_enabled)
+{
+ struct qm_mcc_ceetm_ccgr_query query_opts;
+ struct qm_mcr_ceetm_ccgr_query query_result;
+
+ query_opts.ccgrid = CEETM_CCGR_CM_QUERY |
+ (ccg->parent->idx << 4) | ccg->idx;
+ query_opts.dcpid = ccg->parent->dcp_idx;
+
+ if (qman_ceetm_query_ccgr(&query_opts, &query_result)) {
+ pr_err("Can't query CCGR#%d\n", ccg->idx);
+ return -EINVAL;
+ }
+
+ *vcgid = query_result.cm_query.cdv;
+ *cscn_enabled = (query_result.cm_query.cscn_targ_dcp >>
+ (7 - dcp_idx)) & 0x1;
+ return 0;
+}
+EXPORT_SYMBOL(qman_ceetm_cscn_dcp_get);
+
+int qman_ceetm_querycongestion(struct __qm_mcr_querycongestion *ccg_state,
+ unsigned int dcp_idx)
+{
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ struct qman_portal *p;
+ unsigned long irqflags __maybe_unused;
+ u8 res;
+ int i;
+
+ p = get_affine_portal();
+ PORTAL_IRQ_LOCK(p, irqflags);
+
+ mcc = qm_mc_start(&p->p);
+ for (i = 0; i < 2; i++) {
+ mcc->ccgr_query.ccgrid = CEETM_QUERY_CONGESTION_STATE | i;
+ mcc->ccgr_query.dcpid = dcp_idx;
+ qm_mc_commit(&p->p, QM_CEETM_VERB_CCGR_QUERY);
+
+ while (!(mcr = qm_mc_result(&p->p)))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) ==
+ QM_CEETM_VERB_CCGR_QUERY);
+ res = mcr->result;
+ if (res == QM_MCR_RESULT_OK) {
+ *(ccg_state + i) =
+ mcr->ccgr_query.congestion_state.state;
+ } else {
+ pr_err("QUERY CEETM CONGESTION STATE failed\n");
+ return -EIO;
+ }
+ }
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ return 0;
+}
+
+int qman_set_wpm(int wpm_enable)
+{
+ return qm_set_wpm(wpm_enable);
+}
+EXPORT_SYMBOL(qman_set_wpm);
+
+int qman_get_wpm(int *wpm_enable)
+{
+ return qm_get_wpm(wpm_enable);
+}
+EXPORT_SYMBOL(qman_get_wpm);
+
+int qman_shutdown_fq(u32 fqid)
+{
+ struct qman_portal *p;
+ unsigned long irqflags __maybe_unused;
+ int ret;
+ struct qm_portal *low_p;
+ p = get_affine_portal();
+ PORTAL_IRQ_LOCK(p, irqflags);
+ low_p = &p->p;
+ ret = qm_shutdown_fq(&low_p, 1, fqid);
+ PORTAL_IRQ_UNLOCK(p, irqflags);
+ put_affine_portal();
+ return ret;
+}
+
+const struct qm_portal_config *qman_get_qm_portal_config(
+ struct qman_portal *portal)
+{
+ return portal->sharing_redirect ? NULL : portal->config;
+}
diff --git a/drivers/staging/fsl_qbman/qman_low.h b/drivers/staging/fsl_qbman/qman_low.h
new file mode 100644
index 0000000..5d3e820
--- /dev/null
+++ b/drivers/staging/fsl_qbman/qman_low.h
@@ -0,0 +1,1347 @@
+/* Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "qman_private.h"
+
+/***************************/
+/* Portal register assists */
+/***************************/
+
+/* Cache-inhibited register offsets */
+#define QM_REG_EQCR_PI_CINH 0x0000
+#define QM_REG_EQCR_CI_CINH 0x0004
+#define QM_REG_EQCR_ITR 0x0008
+#define QM_REG_DQRR_PI_CINH 0x0040
+#define QM_REG_DQRR_CI_CINH 0x0044
+#define QM_REG_DQRR_ITR 0x0048
+#define QM_REG_DQRR_DCAP 0x0050
+#define QM_REG_DQRR_SDQCR 0x0054
+#define QM_REG_DQRR_VDQCR 0x0058
+#define QM_REG_DQRR_PDQCR 0x005c
+#define QM_REG_MR_PI_CINH 0x0080
+#define QM_REG_MR_CI_CINH 0x0084
+#define QM_REG_MR_ITR 0x0088
+#define QM_REG_CFG 0x0100
+#define QM_REG_ISR 0x0e00
+#define QM_REG_IIR 0x0e0c
+#define QM_REG_ITPR 0x0e14
+
+/* Cache-enabled register offsets */
+#define QM_CL_EQCR 0x0000
+#define QM_CL_DQRR 0x1000
+#define QM_CL_MR 0x2000
+#define QM_CL_EQCR_PI_CENA 0x3000
+#define QM_CL_EQCR_CI_CENA 0x3100
+#define QM_CL_DQRR_PI_CENA 0x3200
+#define QM_CL_DQRR_CI_CENA 0x3300
+#define QM_CL_MR_PI_CENA 0x3400
+#define QM_CL_MR_CI_CENA 0x3500
+#define QM_CL_CR 0x3800
+#define QM_CL_RR0 0x3900
+#define QM_CL_RR1 0x3940
+
+/* BTW, the drivers (and h/w programming model) already obtain the required
+ * synchronisation for portal accesses via lwsync(), hwsync(), and
+ * data-dependencies. Use of barrier()s or other order-preserving primitives
+ * simply degrade performance. Hence the use of the __raw_*() interfaces, which
+ * simply ensure that the compiler treats the portal registers as volatile (ie.
+ * non-coherent). */
+
+/* Cache-inhibited register access. */
+#define __qm_in(qm, o) __raw_readl((qm)->addr_ci + (o))
+#define __qm_out(qm, o, val) __raw_writel((val), (qm)->addr_ci + (o))
+#define qm_in(reg) __qm_in(&portal->addr, QM_REG_##reg)
+#define qm_out(reg, val) __qm_out(&portal->addr, QM_REG_##reg, val)
+
+/* Cache-enabled (index) register access */
+#define __qm_cl_touch_ro(qm, o) dcbt_ro((qm)->addr_ce + (o))
+#define __qm_cl_touch_rw(qm, o) dcbt_rw((qm)->addr_ce + (o))
+#define __qm_cl_in(qm, o) __raw_readl((qm)->addr_ce + (o))
+#define __qm_cl_out(qm, o, val) \
+ do { \
+ u32 *__tmpclout = (qm)->addr_ce + (o); \
+ __raw_writel((val), __tmpclout); \
+ dcbf(__tmpclout); \
+ } while (0)
+#define __qm_cl_invalidate(qm, o) dcbi((qm)->addr_ce + (o))
+#define qm_cl_touch_ro(reg) __qm_cl_touch_ro(&portal->addr, QM_CL_##reg##_CENA)
+#define qm_cl_touch_rw(reg) __qm_cl_touch_rw(&portal->addr, QM_CL_##reg##_CENA)
+#define qm_cl_in(reg) __qm_cl_in(&portal->addr, QM_CL_##reg##_CENA)
+#define qm_cl_out(reg, val) __qm_cl_out(&portal->addr, QM_CL_##reg##_CENA, val)
+#define qm_cl_invalidate(reg)\
+ __qm_cl_invalidate(&portal->addr, QM_CL_##reg##_CENA)
+
+/* Cache-enabled ring access */
+#define qm_cl(base, idx) ((void *)base + ((idx) << 6))
+
+/* Cyclic helper for rings. FIXME: once we are able to do fine-grain perf
+ * analysis, look at using the "extra" bit in the ring index registers to avoid
+ * cyclic issues. */
+static inline u8 qm_cyc_diff(u8 ringsize, u8 first, u8 last)
+{
+ /* 'first' is included, 'last' is excluded */
+ if (first <= last)
+ return last - first;
+ return ringsize + last - first;
+}
+
+/* Portal modes.
+ * Enum types;
+ * pmode == production mode
+ * cmode == consumption mode,
+ * dmode == h/w dequeue mode.
+ * Enum values use 3 letter codes. First letter matches the portal mode,
+ * remaining two letters indicate;
+ * ci == cache-inhibited portal register
+ * ce == cache-enabled portal register
+ * vb == in-band valid-bit (cache-enabled)
+ * dc == DCA (Discrete Consumption Acknowledgement), DQRR-only
+ * As for "enum qm_dqrr_dmode", it should be self-explanatory.
+ */
+enum qm_eqcr_pmode { /* matches QCSP_CFG::EPM */
+ qm_eqcr_pci = 0, /* PI index, cache-inhibited */
+ qm_eqcr_pce = 1, /* PI index, cache-enabled */
+ qm_eqcr_pvb = 2 /* valid-bit */
+};
+enum qm_dqrr_dmode { /* matches QCSP_CFG::DP */
+ qm_dqrr_dpush = 0, /* SDQCR + VDQCR */
+ qm_dqrr_dpull = 1 /* PDQCR */
+};
+enum qm_dqrr_pmode { /* s/w-only */
+ qm_dqrr_pci, /* reads DQRR_PI_CINH */
+ qm_dqrr_pce, /* reads DQRR_PI_CENA */
+ qm_dqrr_pvb /* reads valid-bit */
+};
+enum qm_dqrr_cmode { /* matches QCSP_CFG::DCM */
+ qm_dqrr_cci = 0, /* CI index, cache-inhibited */
+ qm_dqrr_cce = 1, /* CI index, cache-enabled */
+ qm_dqrr_cdc = 2 /* Discrete Consumption Acknowledgement */
+};
+enum qm_mr_pmode { /* s/w-only */
+ qm_mr_pci, /* reads MR_PI_CINH */
+ qm_mr_pce, /* reads MR_PI_CENA */
+ qm_mr_pvb /* reads valid-bit */
+};
+enum qm_mr_cmode { /* matches QCSP_CFG::MM */
+ qm_mr_cci = 0, /* CI index, cache-inhibited */
+ qm_mr_cce = 1 /* CI index, cache-enabled */
+};
+
+
+/* ------------------------- */
+/* --- Portal structures --- */
+
+#define QM_EQCR_SIZE 8
+#define QM_DQRR_SIZE 16
+#define QM_MR_SIZE 8
+
+struct qm_eqcr {
+ struct qm_eqcr_entry *ring, *cursor;
+ u8 ci, available, ithresh, vbit;
+#ifdef CONFIG_FSL_DPA_CHECKING
+ u32 busy;
+ enum qm_eqcr_pmode pmode;
+#endif
+};
+
+struct qm_dqrr {
+ const struct qm_dqrr_entry *ring, *cursor;
+ u8 pi, ci, fill, ithresh, vbit;
+#ifdef CONFIG_FSL_DPA_CHECKING
+ enum qm_dqrr_dmode dmode;
+ enum qm_dqrr_pmode pmode;
+ enum qm_dqrr_cmode cmode;
+#endif
+};
+
+struct qm_mr {
+ const struct qm_mr_entry *ring, *cursor;
+ u8 pi, ci, fill, ithresh, vbit;
+#ifdef CONFIG_FSL_DPA_CHECKING
+ enum qm_mr_pmode pmode;
+ enum qm_mr_cmode cmode;
+#endif
+};
+
+struct qm_mc {
+ struct qm_mc_command *cr;
+ struct qm_mc_result *rr;
+ u8 rridx, vbit;
+#ifdef CONFIG_FSL_DPA_CHECKING
+ enum {
+ /* Can be _mc_start()ed */
+ qman_mc_idle,
+ /* Can be _mc_commit()ed or _mc_abort()ed */
+ qman_mc_user,
+ /* Can only be _mc_retry()ed */
+ qman_mc_hw
+ } state;
+#endif
+};
+
+#define QM_PORTAL_ALIGNMENT ____cacheline_aligned
+
+struct qm_addr {
+ void __iomem *addr_ce; /* cache-enabled */
+ void __iomem *addr_ci; /* cache-inhibited */
+};
+
+struct qm_portal {
+ /* In the non-CONFIG_FSL_DPA_CHECKING case, the following stuff up to
+ * and including 'mc' fits within a cacheline (yay!). The 'config' part
+ * is setup-only, so isn't a cause for a concern. In other words, don't
+ * rearrange this structure on a whim, there be dragons ... */
+ struct qm_addr addr;
+ struct qm_eqcr eqcr;
+ struct qm_dqrr dqrr;
+ struct qm_mr mr;
+ struct qm_mc mc;
+} QM_PORTAL_ALIGNMENT;
+
+
+/* ---------------- */
+/* --- EQCR API --- */
+
+/* Bit-wise logic to wrap a ring pointer by clearing the "carry bit" */
+#define EQCR_CARRYCLEAR(p) \
+ (void *)((unsigned long)(p) & (~(unsigned long)(QM_EQCR_SIZE << 6)))
+
+/* Bit-wise logic to convert a ring pointer to a ring index */
+static inline u8 EQCR_PTR2IDX(struct qm_eqcr_entry *e)
+{
+ return ((uintptr_t)e >> 6) & (QM_EQCR_SIZE - 1);
+}
+
+/* Increment the 'cursor' ring pointer, taking 'vbit' into account */
+static inline void EQCR_INC(struct qm_eqcr *eqcr)
+{
+ /* NB: this is odd-looking, but experiments show that it generates fast
+ * code with essentially no branching overheads. We increment to the
+ * next EQCR pointer and handle overflow and 'vbit'. */
+ struct qm_eqcr_entry *partial = eqcr->cursor + 1;
+ eqcr->cursor = EQCR_CARRYCLEAR(partial);
+ if (partial != eqcr->cursor)
+ eqcr->vbit ^= QM_EQCR_VERB_VBIT;
+}
+
+static inline int qm_eqcr_init(struct qm_portal *portal,
+ enum qm_eqcr_pmode pmode,
+ unsigned int eq_stash_thresh,
+ int eq_stash_prio)
+{
+ /* This use of 'register', as well as all other occurrences, is because
+ * it has been observed to generate much faster code with gcc than is
+ * otherwise the case. */
+ register struct qm_eqcr *eqcr = &portal->eqcr;
+ u32 cfg;
+ u8 pi;
+
+ eqcr->ring = portal->addr.addr_ce + QM_CL_EQCR;
+ eqcr->ci = qm_in(EQCR_CI_CINH) & (QM_EQCR_SIZE - 1);
+ qm_cl_invalidate(EQCR_CI);
+ pi = qm_in(EQCR_PI_CINH) & (QM_EQCR_SIZE - 1);
+ eqcr->cursor = eqcr->ring + pi;
+ eqcr->vbit = (qm_in(EQCR_PI_CINH) & QM_EQCR_SIZE) ?
+ QM_EQCR_VERB_VBIT : 0;
+ eqcr->available = QM_EQCR_SIZE - 1 -
+ qm_cyc_diff(QM_EQCR_SIZE, eqcr->ci, pi);
+ eqcr->ithresh = qm_in(EQCR_ITR);
+#ifdef CONFIG_FSL_DPA_CHECKING
+ eqcr->busy = 0;
+ eqcr->pmode = pmode;
+#endif
+ cfg = (qm_in(CFG) & 0x00ffffff) |
+ (eq_stash_thresh << 28) | /* QCSP_CFG: EST */
+ (eq_stash_prio << 26) | /* QCSP_CFG: EP */
+ ((pmode & 0x3) << 24); /* QCSP_CFG::EPM */
+ qm_out(CFG, cfg);
+ return 0;
+}
+
+static inline unsigned int qm_eqcr_get_ci_stashing(struct qm_portal *portal)
+{
+ return (qm_in(CFG) >> 28) & 0x7;
+}
+
+static inline void qm_eqcr_finish(struct qm_portal *portal)
+{
+ register struct qm_eqcr *eqcr = &portal->eqcr;
+ u8 pi, ci;
+ u32 cfg;
+
+ /*
+ * Disable EQCI stashing because the QMan only
+ * presents the value it previously stashed to
+ * maintain coherency. Setting the stash threshold
+ * to 1 then 0 ensures that QMan has resyncronized
+ * its internal copy so that the portal is clean
+ * when it is reinitialized in the future
+ */
+ cfg = (qm_in(CFG) & 0x0fffffff) |
+ (1 << 28); /* QCSP_CFG: EST */
+ qm_out(CFG, cfg);
+ cfg &= 0x0fffffff; /* stash threshold = 0 */
+ qm_out(CFG, cfg);
+
+ pi = qm_in(EQCR_PI_CINH) & (QM_EQCR_SIZE - 1);
+ ci = qm_in(EQCR_CI_CINH) & (QM_EQCR_SIZE - 1);
+
+ /* Refresh EQCR CI cache value */
+ qm_cl_invalidate(EQCR_CI);
+ eqcr->ci = qm_cl_in(EQCR_CI) & (QM_EQCR_SIZE - 1);
+
+ DPA_ASSERT(!eqcr->busy);
+ if (pi != EQCR_PTR2IDX(eqcr->cursor))
+ pr_crit("losing uncommited EQCR entries\n");
+ if (ci != eqcr->ci)
+ pr_crit("missing existing EQCR completions\n");
+ if (eqcr->ci != EQCR_PTR2IDX(eqcr->cursor))
+ pr_crit("EQCR destroyed unquiesced\n");
+}
+
+static inline struct qm_eqcr_entry *qm_eqcr_start_no_stash(struct qm_portal
+ *portal)
+{
+ register struct qm_eqcr *eqcr = &portal->eqcr;
+ DPA_ASSERT(!eqcr->busy);
+ if (!eqcr->available)
+ return NULL;
+
+
+#ifdef CONFIG_FSL_DPA_CHECKING
+ eqcr->busy = 1;
+#endif
+ dcbz_64(eqcr->cursor);
+ return eqcr->cursor;
+}
+
+static inline struct qm_eqcr_entry *qm_eqcr_start_stash(struct qm_portal
+ *portal)
+{
+ register struct qm_eqcr *eqcr = &portal->eqcr;
+ u8 diff, old_ci;
+
+ DPA_ASSERT(!eqcr->busy);
+ if (!eqcr->available) {
+ old_ci = eqcr->ci;
+ eqcr->ci = qm_cl_in(EQCR_CI) & (QM_EQCR_SIZE - 1);
+ diff = qm_cyc_diff(QM_EQCR_SIZE, old_ci, eqcr->ci);
+ eqcr->available += diff;
+ if (!diff)
+ return NULL;
+ }
+#ifdef CONFIG_FSL_DPA_CHECKING
+ eqcr->busy = 1;
+#endif
+ dcbz_64(eqcr->cursor);
+ return eqcr->cursor;
+}
+
+static inline void qm_eqcr_abort(struct qm_portal *portal)
+{
+ __maybe_unused register struct qm_eqcr *eqcr = &portal->eqcr;
+ DPA_ASSERT(eqcr->busy);
+#ifdef CONFIG_FSL_DPA_CHECKING
+ eqcr->busy = 0;
+#endif
+}
+
+static inline struct qm_eqcr_entry *qm_eqcr_pend_and_next(
+ struct qm_portal *portal, u8 myverb)
+{
+ register struct qm_eqcr *eqcr = &portal->eqcr;
+ DPA_ASSERT(eqcr->busy);
+ DPA_ASSERT(eqcr->pmode != qm_eqcr_pvb);
+ if (eqcr->available == 1)
+ return NULL;
+ eqcr->cursor->__dont_write_directly__verb = myverb | eqcr->vbit;
+ dcbf(eqcr->cursor);
+ EQCR_INC(eqcr);
+ eqcr->available--;
+ dcbz_64(eqcr->cursor);
+ return eqcr->cursor;
+}
+
+#define EQCR_COMMIT_CHECKS(eqcr) \
+do { \
+ DPA_ASSERT(eqcr->busy); \
+ DPA_ASSERT(eqcr->cursor->orp == (eqcr->cursor->orp & 0x00ffffff)); \
+ DPA_ASSERT(eqcr->cursor->fqid == (eqcr->cursor->fqid & 0x00ffffff)); \
+} while (0)
+
+static inline void qm_eqcr_pci_commit(struct qm_portal *portal, u8 myverb)
+{
+ register struct qm_eqcr *eqcr = &portal->eqcr;
+ EQCR_COMMIT_CHECKS(eqcr);
+ DPA_ASSERT(eqcr->pmode == qm_eqcr_pci);
+ eqcr->cursor->__dont_write_directly__verb = myverb | eqcr->vbit;
+ EQCR_INC(eqcr);
+ eqcr->available--;
+ dcbf(eqcr->cursor);
+ hwsync();
+ qm_out(EQCR_PI_CINH, EQCR_PTR2IDX(eqcr->cursor));
+#ifdef CONFIG_FSL_DPA_CHECKING
+ eqcr->busy = 0;
+#endif
+}
+
+static inline void qm_eqcr_pce_prefetch(struct qm_portal *portal)
+{
+ __maybe_unused register struct qm_eqcr *eqcr = &portal->eqcr;
+ DPA_ASSERT(eqcr->pmode == qm_eqcr_pce);
+ qm_cl_invalidate(EQCR_PI);
+ qm_cl_touch_rw(EQCR_PI);
+}
+
+static inline void qm_eqcr_pce_commit(struct qm_portal *portal, u8 myverb)
+{
+ register struct qm_eqcr *eqcr = &portal->eqcr;
+ EQCR_COMMIT_CHECKS(eqcr);
+ DPA_ASSERT(eqcr->pmode == qm_eqcr_pce);
+ eqcr->cursor->__dont_write_directly__verb = myverb | eqcr->vbit;
+ EQCR_INC(eqcr);
+ eqcr->available--;
+ dcbf(eqcr->cursor);
+ lwsync();
+ qm_cl_out(EQCR_PI, EQCR_PTR2IDX(eqcr->cursor));
+#ifdef CONFIG_FSL_DPA_CHECKING
+ eqcr->busy = 0;
+#endif
+}
+
+static inline void qm_eqcr_pvb_commit(struct qm_portal *portal, u8 myverb)
+{
+ register struct qm_eqcr *eqcr = &portal->eqcr;
+ struct qm_eqcr_entry *eqcursor;
+ EQCR_COMMIT_CHECKS(eqcr);
+ DPA_ASSERT(eqcr->pmode == qm_eqcr_pvb);
+ lwsync();
+ eqcursor = eqcr->cursor;
+ eqcursor->__dont_write_directly__verb = myverb | eqcr->vbit;
+ dcbf(eqcursor);
+ EQCR_INC(eqcr);
+ eqcr->available--;
+#ifdef CONFIG_FSL_DPA_CHECKING
+ eqcr->busy = 0;
+#endif
+}
+
+static inline u8 qm_eqcr_cci_update(struct qm_portal *portal)
+{
+ register struct qm_eqcr *eqcr = &portal->eqcr;
+ u8 diff, old_ci = eqcr->ci;
+ eqcr->ci = qm_in(EQCR_CI_CINH) & (QM_EQCR_SIZE - 1);
+ diff = qm_cyc_diff(QM_EQCR_SIZE, old_ci, eqcr->ci);
+ eqcr->available += diff;
+ return diff;
+}
+
+static inline void qm_eqcr_cce_prefetch(struct qm_portal *portal)
+{
+ __maybe_unused register struct qm_eqcr *eqcr = &portal->eqcr;
+ qm_cl_touch_ro(EQCR_CI);
+}
+
+static inline u8 qm_eqcr_cce_update(struct qm_portal *portal)
+{
+ register struct qm_eqcr *eqcr = &portal->eqcr;
+ u8 diff, old_ci = eqcr->ci;
+ eqcr->ci = qm_cl_in(EQCR_CI) & (QM_EQCR_SIZE - 1);
+ qm_cl_invalidate(EQCR_CI);
+ diff = qm_cyc_diff(QM_EQCR_SIZE, old_ci, eqcr->ci);
+ eqcr->available += diff;
+ return diff;
+}
+
+static inline u8 qm_eqcr_get_ithresh(struct qm_portal *portal)
+{
+ register struct qm_eqcr *eqcr = &portal->eqcr;
+ return eqcr->ithresh;
+}
+
+static inline void qm_eqcr_set_ithresh(struct qm_portal *portal, u8 ithresh)
+{
+ register struct qm_eqcr *eqcr = &portal->eqcr;
+ eqcr->ithresh = ithresh;
+ qm_out(EQCR_ITR, ithresh);
+}
+
+static inline u8 qm_eqcr_get_avail(struct qm_portal *portal)
+{
+ register struct qm_eqcr *eqcr = &portal->eqcr;
+ return eqcr->available;
+}
+
+static inline u8 qm_eqcr_get_fill(struct qm_portal *portal)
+{
+ register struct qm_eqcr *eqcr = &portal->eqcr;
+ return QM_EQCR_SIZE - 1 - eqcr->available;
+}
+
+
+/* ---------------- */
+/* --- DQRR API --- */
+
+/* FIXME: many possible improvements;
+ * - look at changing the API to use pointer rather than index parameters now
+ * that 'cursor' is a pointer,
+ * - consider moving other parameters to pointer if it could help (ci)
+ */
+
+#define DQRR_CARRYCLEAR(p) \
+ (void *)((unsigned long)(p) & (~(unsigned long)(QM_DQRR_SIZE << 6)))
+
+static inline u8 DQRR_PTR2IDX(const struct qm_dqrr_entry *e)
+{
+ return ((uintptr_t)e >> 6) & (QM_DQRR_SIZE - 1);
+}
+
+static inline const struct qm_dqrr_entry *DQRR_INC(
+ const struct qm_dqrr_entry *e)
+{
+ return DQRR_CARRYCLEAR(e + 1);
+}
+
+static inline void qm_dqrr_set_maxfill(struct qm_portal *portal, u8 mf)
+{
+ qm_out(CFG, (qm_in(CFG) & 0xff0fffff) |
+ ((mf & (QM_DQRR_SIZE - 1)) << 20));
+}
+
+static inline void qm_dqrr_cci_consume(struct qm_portal *portal, u8 num)
+{
+ register struct qm_dqrr *dqrr = &portal->dqrr;
+ DPA_ASSERT(dqrr->cmode == qm_dqrr_cci);
+ dqrr->ci = (dqrr->ci + num) & (QM_DQRR_SIZE - 1);
+ qm_out(DQRR_CI_CINH, dqrr->ci);
+}
+
+static inline void qm_dqrr_cce_consume(struct qm_portal *portal, u8 num)
+{
+ register struct qm_dqrr *dqrr = &portal->dqrr;
+ DPA_ASSERT(dqrr->cmode == qm_dqrr_cce);
+ dqrr->ci = (dqrr->ci + num) & (QM_DQRR_SIZE - 1);
+ qm_cl_out(DQRR_CI, dqrr->ci);
+}
+
+static inline void qm_dqrr_cdc_consume_n(struct qm_portal *portal, u16 bitmask)
+{
+ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr;
+ DPA_ASSERT(dqrr->cmode == qm_dqrr_cdc);
+ qm_out(DQRR_DCAP, (1 << 8) | /* DQRR_DCAP::S */
+ ((u32)bitmask << 16)); /* DQRR_DCAP::DCAP_CI */
+}
+
+static inline int qm_dqrr_init(struct qm_portal *portal,
+ const struct qm_portal_config *config,
+ enum qm_dqrr_dmode dmode,
+ __maybe_unused enum qm_dqrr_pmode pmode,
+ enum qm_dqrr_cmode cmode, u8 max_fill)
+{
+ register struct qm_dqrr *dqrr = &portal->dqrr;
+ u32 cfg;
+
+ /* Make sure the DQRR will be idle when we enable */
+ qm_out(DQRR_SDQCR, 0);
+ qm_out(DQRR_VDQCR, 0);
+ qm_out(DQRR_PDQCR, 0);
+ dqrr->ring = portal->addr.addr_ce + QM_CL_DQRR;
+ dqrr->pi = qm_in(DQRR_PI_CINH) & (QM_DQRR_SIZE - 1);
+ dqrr->ci = qm_in(DQRR_CI_CINH) & (QM_DQRR_SIZE - 1);
+ dqrr->cursor = dqrr->ring + dqrr->ci;
+ dqrr->fill = qm_cyc_diff(QM_DQRR_SIZE, dqrr->ci, dqrr->pi);
+ dqrr->vbit = (qm_in(DQRR_PI_CINH) & QM_DQRR_SIZE) ?
+ QM_DQRR_VERB_VBIT : 0;
+ dqrr->ithresh = qm_in(DQRR_ITR);
+
+ /* Free up pending DQRR entries if any as per current DCM */
+ if (dqrr->fill) {
+ enum qm_dqrr_cmode dcm = (qm_in(CFG) >> 16) & 3;
+
+#ifdef CONFIG_FSL_DPA_CHECKING
+ dqrr->cmode = dcm;
+#endif
+ switch (dcm) {
+ case qm_dqrr_cci:
+ qm_dqrr_cci_consume(portal, dqrr->fill);
+ break;
+ case qm_dqrr_cce:
+ qm_dqrr_cce_consume(portal, dqrr->fill);
+ break;
+ case qm_dqrr_cdc:
+ qm_dqrr_cdc_consume_n(portal, (QM_DQRR_SIZE - 1));
+ break;
+ default:
+ DPA_ASSERT(0);
+ }
+ }
+
+#ifdef CONFIG_FSL_DPA_CHECKING
+ dqrr->dmode = dmode;
+ dqrr->pmode = pmode;
+ dqrr->cmode = cmode;
+#endif
+ /* Invalidate every ring entry before beginning */
+ for (cfg = 0; cfg < QM_DQRR_SIZE; cfg++)
+ dcbi(qm_cl(dqrr->ring, cfg));
+ cfg = (qm_in(CFG) & 0xff000f00) |
+ ((max_fill & (QM_DQRR_SIZE - 1)) << 20) | /* DQRR_MF */
+ ((dmode & 1) << 18) | /* DP */
+ ((cmode & 3) << 16) | /* DCM */
+ 0xa0 | /* RE+SE */
+ (0 ? 0x40 : 0) | /* Ignore RP */
+ (0 ? 0x10 : 0); /* Ignore SP */
+ qm_out(CFG, cfg);
+ qm_dqrr_set_maxfill(portal, max_fill);
+ return 0;
+}
+
+static inline void qm_dqrr_finish(struct qm_portal *portal)
+{
+ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr;
+#ifdef CONFIG_FSL_DPA_CHECKING
+ if ((dqrr->cmode != qm_dqrr_cdc) &&
+ (dqrr->ci != DQRR_PTR2IDX(dqrr->cursor)))
+ pr_crit("Ignoring completed DQRR entries\n");
+#endif
+}
+
+static inline const struct qm_dqrr_entry *qm_dqrr_current(
+ struct qm_portal *portal)
+{
+ register struct qm_dqrr *dqrr = &portal->dqrr;
+ if (!dqrr->fill)
+ return NULL;
+ return dqrr->cursor;
+}
+
+static inline u8 qm_dqrr_cursor(struct qm_portal *portal)
+{
+ register struct qm_dqrr *dqrr = &portal->dqrr;
+ return DQRR_PTR2IDX(dqrr->cursor);
+}
+
+static inline u8 qm_dqrr_next(struct qm_portal *portal)
+{
+ register struct qm_dqrr *dqrr = &portal->dqrr;
+ DPA_ASSERT(dqrr->fill);
+ dqrr->cursor = DQRR_INC(dqrr->cursor);
+ return --dqrr->fill;
+}
+
+static inline u8 qm_dqrr_pci_update(struct qm_portal *portal)
+{
+ register struct qm_dqrr *dqrr = &portal->dqrr;
+ u8 diff, old_pi = dqrr->pi;
+ DPA_ASSERT(dqrr->pmode == qm_dqrr_pci);
+ dqrr->pi = qm_in(DQRR_PI_CINH) & (QM_DQRR_SIZE - 1);
+ diff = qm_cyc_diff(QM_DQRR_SIZE, old_pi, dqrr->pi);
+ dqrr->fill += diff;
+ return diff;
+}
+
+static inline void qm_dqrr_pce_prefetch(struct qm_portal *portal)
+{
+ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr;
+ DPA_ASSERT(dqrr->pmode == qm_dqrr_pce);
+ qm_cl_invalidate(DQRR_PI);
+ qm_cl_touch_ro(DQRR_PI);
+}
+
+static inline u8 qm_dqrr_pce_update(struct qm_portal *portal)
+{
+ register struct qm_dqrr *dqrr = &portal->dqrr;
+ u8 diff, old_pi = dqrr->pi;
+ DPA_ASSERT(dqrr->pmode == qm_dqrr_pce);
+ dqrr->pi = qm_cl_in(DQRR_PI) & (QM_DQRR_SIZE - 1);
+ diff = qm_cyc_diff(QM_DQRR_SIZE, old_pi, dqrr->pi);
+ dqrr->fill += diff;
+ return diff;
+}
+
+static inline void qm_dqrr_pvb_update(struct qm_portal *portal)
+{
+ register struct qm_dqrr *dqrr = &portal->dqrr;
+ const struct qm_dqrr_entry *res = qm_cl(dqrr->ring, dqrr->pi);
+ DPA_ASSERT(dqrr->pmode == qm_dqrr_pvb);
+ /* when accessing 'verb', use __raw_readb() to ensure that compiler
+ * inlining doesn't try to optimise out "excess reads". */
+ if ((__raw_readb(&res->verb) & QM_DQRR_VERB_VBIT) == dqrr->vbit) {
+ dqrr->pi = (dqrr->pi + 1) & (QM_DQRR_SIZE - 1);
+ if (!dqrr->pi)
+ dqrr->vbit ^= QM_DQRR_VERB_VBIT;
+ dqrr->fill++;
+ }
+}
+
+
+static inline void qm_dqrr_cci_consume_to_current(struct qm_portal *portal)
+{
+ register struct qm_dqrr *dqrr = &portal->dqrr;
+ DPA_ASSERT(dqrr->cmode == qm_dqrr_cci);
+ dqrr->ci = DQRR_PTR2IDX(dqrr->cursor);
+ qm_out(DQRR_CI_CINH, dqrr->ci);
+}
+
+static inline void qm_dqrr_cce_prefetch(struct qm_portal *portal)
+{
+ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr;
+ DPA_ASSERT(dqrr->cmode == qm_dqrr_cce);
+ qm_cl_invalidate(DQRR_CI);
+ qm_cl_touch_rw(DQRR_CI);
+}
+
+static inline void qm_dqrr_cce_consume_to_current(struct qm_portal *portal)
+{
+ register struct qm_dqrr *dqrr = &portal->dqrr;
+ DPA_ASSERT(dqrr->cmode == qm_dqrr_cce);
+ dqrr->ci = DQRR_PTR2IDX(dqrr->cursor);
+ qm_cl_out(DQRR_CI, dqrr->ci);
+}
+
+static inline void qm_dqrr_cdc_consume_1(struct qm_portal *portal, u8 idx,
+ int park)
+{
+ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr;
+ DPA_ASSERT(dqrr->cmode == qm_dqrr_cdc);
+ DPA_ASSERT(idx < QM_DQRR_SIZE);
+ qm_out(DQRR_DCAP, (0 << 8) | /* S */
+ ((park ? 1 : 0) << 6) | /* PK */
+ idx); /* DCAP_CI */
+}
+
+static inline void qm_dqrr_cdc_consume_1ptr(struct qm_portal *portal,
+ const struct qm_dqrr_entry *dq,
+ int park)
+{
+ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr;
+ u8 idx = DQRR_PTR2IDX(dq);
+ DPA_ASSERT(dqrr->cmode == qm_dqrr_cdc);
+ DPA_ASSERT((dqrr->ring + idx) == dq);
+ DPA_ASSERT(idx < QM_DQRR_SIZE);
+ qm_out(DQRR_DCAP, (0 << 8) | /* DQRR_DCAP::S */
+ ((park ? 1 : 0) << 6) | /* DQRR_DCAP::PK */
+ idx); /* DQRR_DCAP::DCAP_CI */
+}
+
+static inline u8 qm_dqrr_cdc_cci(struct qm_portal *portal)
+{
+ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr;
+ DPA_ASSERT(dqrr->cmode == qm_dqrr_cdc);
+ return qm_in(DQRR_CI_CINH) & (QM_DQRR_SIZE - 1);
+}
+
+static inline void qm_dqrr_cdc_cce_prefetch(struct qm_portal *portal)
+{
+ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr;
+ DPA_ASSERT(dqrr->cmode == qm_dqrr_cdc);
+ qm_cl_invalidate(DQRR_CI);
+ qm_cl_touch_ro(DQRR_CI);
+}
+
+static inline u8 qm_dqrr_cdc_cce(struct qm_portal *portal)
+{
+ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr;
+ DPA_ASSERT(dqrr->cmode == qm_dqrr_cdc);
+ return qm_cl_in(DQRR_CI) & (QM_DQRR_SIZE - 1);
+}
+
+static inline u8 qm_dqrr_get_ci(struct qm_portal *portal)
+{
+ register struct qm_dqrr *dqrr = &portal->dqrr;
+ DPA_ASSERT(dqrr->cmode != qm_dqrr_cdc);
+ return dqrr->ci;
+}
+
+static inline void qm_dqrr_park(struct qm_portal *portal, u8 idx)
+{
+ __maybe_unused register struct qm_dqrr *dqrr = &portal->dqrr;
+ DPA_ASSERT(dqrr->cmode != qm_dqrr_cdc);
+ qm_out(DQRR_DCAP, (0 << 8) | /* S */
+ (1 << 6) | /* PK */
+ (idx & (QM_DQRR_SIZE - 1))); /* DCAP_CI */
+}
+
+static inline void qm_dqrr_park_current(struct qm_portal *portal)
+{
+ register struct qm_dqrr *dqrr = &portal->dqrr;
+ DPA_ASSERT(dqrr->cmode != qm_dqrr_cdc);
+ qm_out(DQRR_DCAP, (0 << 8) | /* S */
+ (1 << 6) | /* PK */
+ DQRR_PTR2IDX(dqrr->cursor)); /* DCAP_CI */
+}
+
+static inline void qm_dqrr_sdqcr_set(struct qm_portal *portal, u32 sdqcr)
+{
+ qm_out(DQRR_SDQCR, sdqcr);
+}
+
+static inline u32 qm_dqrr_sdqcr_get(struct qm_portal *portal)
+{
+ return qm_in(DQRR_SDQCR);
+}
+
+static inline void qm_dqrr_vdqcr_set(struct qm_portal *portal, u32 vdqcr)
+{
+ qm_out(DQRR_VDQCR, vdqcr);
+}
+
+static inline u32 qm_dqrr_vdqcr_get(struct qm_portal *portal)
+{
+ return qm_in(DQRR_VDQCR);
+}
+
+static inline void qm_dqrr_pdqcr_set(struct qm_portal *portal, u32 pdqcr)
+{
+ qm_out(DQRR_PDQCR, pdqcr);
+}
+
+static inline u32 qm_dqrr_pdqcr_get(struct qm_portal *portal)
+{
+ return qm_in(DQRR_PDQCR);
+}
+
+static inline u8 qm_dqrr_get_ithresh(struct qm_portal *portal)
+{
+ register struct qm_dqrr *dqrr = &portal->dqrr;
+ return dqrr->ithresh;
+}
+
+static inline void qm_dqrr_set_ithresh(struct qm_portal *portal, u8 ithresh)
+{
+ qm_out(DQRR_ITR, ithresh);
+}
+
+static inline u8 qm_dqrr_get_maxfill(struct qm_portal *portal)
+{
+ return (qm_in(CFG) & 0x00f00000) >> 20;
+}
+
+
+/* -------------- */
+/* --- MR API --- */
+
+#define MR_CARRYCLEAR(p) \
+ (void *)((unsigned long)(p) & (~(unsigned long)(QM_MR_SIZE << 6)))
+
+static inline u8 MR_PTR2IDX(const struct qm_mr_entry *e)
+{
+ return ((uintptr_t)e >> 6) & (QM_MR_SIZE - 1);
+}
+
+static inline const struct qm_mr_entry *MR_INC(const struct qm_mr_entry *e)
+{
+ return MR_CARRYCLEAR(e + 1);
+}
+
+static inline int qm_mr_init(struct qm_portal *portal, enum qm_mr_pmode pmode,
+ enum qm_mr_cmode cmode)
+{
+ register struct qm_mr *mr = &portal->mr;
+ u32 cfg;
+
+ mr->ring = portal->addr.addr_ce + QM_CL_MR;
+ mr->pi = qm_in(MR_PI_CINH) & (QM_MR_SIZE - 1);
+ mr->ci = qm_in(MR_CI_CINH) & (QM_MR_SIZE - 1);
+ mr->cursor = mr->ring + mr->ci;
+ mr->fill = qm_cyc_diff(QM_MR_SIZE, mr->ci, mr->pi);
+ mr->vbit = (qm_in(MR_PI_CINH) & QM_MR_SIZE) ? QM_MR_VERB_VBIT : 0;
+ mr->ithresh = qm_in(MR_ITR);
+#ifdef CONFIG_FSL_DPA_CHECKING
+ mr->pmode = pmode;
+ mr->cmode = cmode;
+#endif
+ cfg = (qm_in(CFG) & 0xfffff0ff) |
+ ((cmode & 1) << 8); /* QCSP_CFG:MM */
+ qm_out(CFG, cfg);
+ return 0;
+}
+
+static inline void qm_mr_finish(struct qm_portal *portal)
+{
+ register struct qm_mr *mr = &portal->mr;
+ if (mr->ci != MR_PTR2IDX(mr->cursor))
+ pr_crit("Ignoring completed MR entries\n");
+}
+
+static inline const struct qm_mr_entry *qm_mr_current(struct qm_portal *portal)
+{
+ register struct qm_mr *mr = &portal->mr;
+ if (!mr->fill)
+ return NULL;
+ return mr->cursor;
+}
+
+static inline u8 qm_mr_cursor(struct qm_portal *portal)
+{
+ register struct qm_mr *mr = &portal->mr;
+ return MR_PTR2IDX(mr->cursor);
+}
+
+static inline u8 qm_mr_next(struct qm_portal *portal)
+{
+ register struct qm_mr *mr = &portal->mr;
+ DPA_ASSERT(mr->fill);
+ mr->cursor = MR_INC(mr->cursor);
+ return --mr->fill;
+}
+
+static inline u8 qm_mr_pci_update(struct qm_portal *portal)
+{
+ register struct qm_mr *mr = &portal->mr;
+ u8 diff, old_pi = mr->pi;
+ DPA_ASSERT(mr->pmode == qm_mr_pci);
+ mr->pi = qm_in(MR_PI_CINH);
+ diff = qm_cyc_diff(QM_MR_SIZE, old_pi, mr->pi);
+ mr->fill += diff;
+ return diff;
+}
+
+static inline void qm_mr_pce_prefetch(struct qm_portal *portal)
+{
+ __maybe_unused register struct qm_mr *mr = &portal->mr;
+ DPA_ASSERT(mr->pmode == qm_mr_pce);
+ qm_cl_invalidate(MR_PI);
+ qm_cl_touch_ro(MR_PI);
+}
+
+static inline u8 qm_mr_pce_update(struct qm_portal *portal)
+{
+ register struct qm_mr *mr = &portal->mr;
+ u8 diff, old_pi = mr->pi;
+ DPA_ASSERT(mr->pmode == qm_mr_pce);
+ mr->pi = qm_cl_in(MR_PI) & (QM_MR_SIZE - 1);
+ diff = qm_cyc_diff(QM_MR_SIZE, old_pi, mr->pi);
+ mr->fill += diff;
+ return diff;
+}
+
+static inline void qm_mr_pvb_update(struct qm_portal *portal)
+{
+ register struct qm_mr *mr = &portal->mr;
+ const struct qm_mr_entry *res = qm_cl(mr->ring, mr->pi);
+ DPA_ASSERT(mr->pmode == qm_mr_pvb);
+ /* when accessing 'verb', use __raw_readb() to ensure that compiler
+ * inlining doesn't try to optimise out "excess reads". */
+ if ((__raw_readb(&res->verb) & QM_MR_VERB_VBIT) == mr->vbit) {
+ mr->pi = (mr->pi + 1) & (QM_MR_SIZE - 1);
+ if (!mr->pi)
+ mr->vbit ^= QM_MR_VERB_VBIT;
+ mr->fill++;
+ res = MR_INC(res);
+ }
+ dcbit_ro(res);
+}
+
+static inline void qm_mr_cci_consume(struct qm_portal *portal, u8 num)
+{
+ register struct qm_mr *mr = &portal->mr;
+ DPA_ASSERT(mr->cmode == qm_mr_cci);
+ mr->ci = (mr->ci + num) & (QM_MR_SIZE - 1);
+ qm_out(MR_CI_CINH, mr->ci);
+}
+
+static inline void qm_mr_cci_consume_to_current(struct qm_portal *portal)
+{
+ register struct qm_mr *mr = &portal->mr;
+ DPA_ASSERT(mr->cmode == qm_mr_cci);
+ mr->ci = MR_PTR2IDX(mr->cursor);
+ qm_out(MR_CI_CINH, mr->ci);
+}
+
+static inline void qm_mr_cce_prefetch(struct qm_portal *portal)
+{
+ __maybe_unused register struct qm_mr *mr = &portal->mr;
+ DPA_ASSERT(mr->cmode == qm_mr_cce);
+ qm_cl_invalidate(MR_CI);
+ qm_cl_touch_rw(MR_CI);
+}
+
+static inline void qm_mr_cce_consume(struct qm_portal *portal, u8 num)
+{
+ register struct qm_mr *mr = &portal->mr;
+ DPA_ASSERT(mr->cmode == qm_mr_cce);
+ mr->ci = (mr->ci + num) & (QM_MR_SIZE - 1);
+ qm_cl_out(MR_CI, mr->ci);
+}
+
+static inline void qm_mr_cce_consume_to_current(struct qm_portal *portal)
+{
+ register struct qm_mr *mr = &portal->mr;
+ DPA_ASSERT(mr->cmode == qm_mr_cce);
+ mr->ci = MR_PTR2IDX(mr->cursor);
+ qm_cl_out(MR_CI, mr->ci);
+}
+
+static inline u8 qm_mr_get_ci(struct qm_portal *portal)
+{
+ register struct qm_mr *mr = &portal->mr;
+ return mr->ci;
+}
+
+static inline u8 qm_mr_get_ithresh(struct qm_portal *portal)
+{
+ register struct qm_mr *mr = &portal->mr;
+ return mr->ithresh;
+}
+
+static inline void qm_mr_set_ithresh(struct qm_portal *portal, u8 ithresh)
+{
+ qm_out(MR_ITR, ithresh);
+}
+
+
+/* ------------------------------ */
+/* --- Management command API --- */
+
+static inline int qm_mc_init(struct qm_portal *portal)
+{
+ register struct qm_mc *mc = &portal->mc;
+ mc->cr = portal->addr.addr_ce + QM_CL_CR;
+ mc->rr = portal->addr.addr_ce + QM_CL_RR0;
+ mc->rridx = (__raw_readb(&mc->cr->__dont_write_directly__verb) &
+ QM_MCC_VERB_VBIT) ? 0 : 1;
+ mc->vbit = mc->rridx ? QM_MCC_VERB_VBIT : 0;
+#ifdef CONFIG_FSL_DPA_CHECKING
+ mc->state = qman_mc_idle;
+#endif
+ return 0;
+}
+
+static inline void qm_mc_finish(struct qm_portal *portal)
+{
+ __maybe_unused register struct qm_mc *mc = &portal->mc;
+ DPA_ASSERT(mc->state == qman_mc_idle);
+#ifdef CONFIG_FSL_DPA_CHECKING
+ if (mc->state != qman_mc_idle)
+ pr_crit("Losing incomplete MC command\n");
+#endif
+}
+
+static inline struct qm_mc_command *qm_mc_start(struct qm_portal *portal)
+{
+ register struct qm_mc *mc = &portal->mc;
+ DPA_ASSERT(mc->state == qman_mc_idle);
+#ifdef CONFIG_FSL_DPA_CHECKING
+ mc->state = qman_mc_user;
+#endif
+ dcbz_64(mc->cr);
+ return mc->cr;
+}
+
+static inline void qm_mc_abort(struct qm_portal *portal)
+{
+ __maybe_unused register struct qm_mc *mc = &portal->mc;
+ DPA_ASSERT(mc->state == qman_mc_user);
+#ifdef CONFIG_FSL_DPA_CHECKING
+ mc->state = qman_mc_idle;
+#endif
+}
+
+static inline void qm_mc_commit(struct qm_portal *portal, u8 myverb)
+{
+ register struct qm_mc *mc = &portal->mc;
+ struct qm_mc_result *rr = mc->rr + mc->rridx;
+ DPA_ASSERT(mc->state == qman_mc_user);
+ lwsync();
+ mc->cr->__dont_write_directly__verb = myverb | mc->vbit;
+ dcbf(mc->cr);
+ dcbit_ro(rr);
+#ifdef CONFIG_FSL_DPA_CHECKING
+ mc->state = qman_mc_hw;
+#endif
+}
+
+static inline struct qm_mc_result *qm_mc_result(struct qm_portal *portal)
+{
+ register struct qm_mc *mc = &portal->mc;
+ struct qm_mc_result *rr = mc->rr + mc->rridx;
+ DPA_ASSERT(mc->state == qman_mc_hw);
+ /* The inactive response register's verb byte always returns zero until
+ * its command is submitted and completed. This includes the valid-bit,
+ * in case you were wondering... */
+ if (!__raw_readb(&rr->verb)) {
+ dcbit_ro(rr);
+ return NULL;
+ }
+ mc->rridx ^= 1;
+ mc->vbit ^= QM_MCC_VERB_VBIT;
+#ifdef CONFIG_FSL_DPA_CHECKING
+ mc->state = qman_mc_idle;
+#endif
+ return rr;
+}
+
+
+/* ------------------------------------- */
+/* --- Portal interrupt register API --- */
+
+static inline int qm_isr_init(__always_unused struct qm_portal *portal)
+{
+ return 0;
+}
+
+static inline void qm_isr_finish(__always_unused struct qm_portal *portal)
+{
+}
+
+static inline void qm_isr_set_iperiod(struct qm_portal *portal, u16 iperiod)
+{
+ qm_out(ITPR, iperiod);
+}
+
+static inline u32 __qm_isr_read(struct qm_portal *portal, enum qm_isr_reg n)
+{
+ return __qm_in(&portal->addr, QM_REG_ISR + (n << 2));
+}
+
+static inline void __qm_isr_write(struct qm_portal *portal, enum qm_isr_reg n,
+ u32 val)
+{
+ __qm_out(&portal->addr, QM_REG_ISR + (n << 2), val);
+}
+
+/* Cleanup FQs */
+static inline int qm_shutdown_fq(struct qm_portal **portal, int portal_count,
+ u32 fqid)
+{
+
+ struct qm_mc_command *mcc;
+ struct qm_mc_result *mcr;
+ u8 state;
+ int orl_empty, fq_empty, i, drain = 0;
+ u32 result;
+ u32 channel, wq;
+
+ /* Determine the state of the FQID */
+ mcc = qm_mc_start(portal[0]);
+ mcc->queryfq_np.fqid = fqid;
+ qm_mc_commit(portal[0], QM_MCC_VERB_QUERYFQ_NP);
+ while (!(mcr = qm_mc_result(portal[0])))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_QUERYFQ_NP);
+ state = mcr->queryfq_np.state & QM_MCR_NP_STATE_MASK;
+ if (state == QM_MCR_NP_STATE_OOS)
+ return 0; /* Already OOS, no need to do anymore checks */
+
+ /* Query which channel the FQ is using */
+ mcc = qm_mc_start(portal[0]);
+ mcc->queryfq.fqid = fqid;
+ qm_mc_commit(portal[0], QM_MCC_VERB_QUERYFQ);
+ while (!(mcr = qm_mc_result(portal[0])))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) == QM_MCR_VERB_QUERYFQ);
+
+ /* Need to store these since the MCR gets reused */
+ channel = mcr->queryfq.fqd.dest.channel;
+ wq = mcr->queryfq.fqd.dest.wq;
+
+ switch (state) {
+ case QM_MCR_NP_STATE_TEN_SCHED:
+ case QM_MCR_NP_STATE_TRU_SCHED:
+ case QM_MCR_NP_STATE_ACTIVE:
+ case QM_MCR_NP_STATE_PARKED:
+ orl_empty = 0;
+ mcc = qm_mc_start(portal[0]);
+ mcc->alterfq.fqid = fqid;
+ qm_mc_commit(portal[0], QM_MCC_VERB_ALTER_RETIRE);
+ while (!(mcr = qm_mc_result(portal[0])))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) ==
+ QM_MCR_VERB_ALTER_RETIRE);
+ result = mcr->result; /* Make a copy as we reuse MCR below */
+
+ if (result == QM_MCR_RESULT_PENDING) {
+ /* Need to wait for the FQRN in the message ring, which
+ will only occur once the FQ has been drained. In
+ order for the FQ to drain the portal needs to be set
+ to dequeue from the channel the FQ is scheduled on */
+ const struct qm_mr_entry *msg;
+ const struct qm_dqrr_entry *dqrr = NULL;
+ int found_fqrn = 0;
+ u16 dequeue_wq = 0;
+
+ /* Flag that we need to drain FQ */
+ drain = 1;
+
+ if (channel >= qm_channel_pool1 &&
+ channel < (qm_channel_pool1 + 15)) {
+ /* Pool channel, enable the bit in the portal */
+ dequeue_wq = (channel -
+ qm_channel_pool1 + 1)<<4 | wq;
+ } else if (channel < qm_channel_pool1) {
+ /* Dedicated channel */
+ dequeue_wq = wq;
+ } else {
+ pr_info("Cannot recover FQ 0x%x, it is "
+ "scheduled on channel 0x%x",
+ fqid, channel);
+ return -EBUSY;
+ }
+ /* Set the sdqcr to drain this channel */
+ if (channel < qm_channel_pool1)
+ for (i = 0; i < portal_count; i++)
+ qm_dqrr_sdqcr_set(portal[i],
+ QM_SDQCR_TYPE_ACTIVE |
+ QM_SDQCR_CHANNELS_DEDICATED);
+ else
+ for (i = 0; i < portal_count; i++)
+ qm_dqrr_sdqcr_set(
+ portal[i],
+ QM_SDQCR_TYPE_ACTIVE |
+ QM_SDQCR_CHANNELS_POOL_CONV
+ (channel));
+ while (!found_fqrn) {
+ /* Keep draining DQRR while checking the MR*/
+ for (i = 0; i < portal_count; i++) {
+ qm_dqrr_pvb_update(portal[i]);
+ dqrr = qm_dqrr_current(portal[i]);
+ while (dqrr) {
+ qm_dqrr_cdc_consume_1ptr(
+ portal[i], dqrr, 0);
+ qm_dqrr_pvb_update(portal[i]);
+ qm_dqrr_next(portal[i]);
+ dqrr = qm_dqrr_current(
+ portal[i]);
+ }
+ /* Process message ring too */
+ qm_mr_pvb_update(portal[i]);
+ msg = qm_mr_current(portal[i]);
+ while (msg) {
+ if ((msg->verb &
+ QM_MR_VERB_TYPE_MASK)
+ == QM_MR_VERB_FQRN)
+ found_fqrn = 1;
+ qm_mr_next(portal[i]);
+ qm_mr_cci_consume_to_current(
+ portal[i]);
+ qm_mr_pvb_update(portal[i]);
+ msg = qm_mr_current(portal[i]);
+ }
+ cpu_relax();
+ }
+ }
+ }
+ if (result != QM_MCR_RESULT_OK &&
+ result != QM_MCR_RESULT_PENDING) {
+ /* error */
+ pr_err("qman_retire_fq failed on FQ 0x%x, result=0x%x\n",
+ fqid, result);
+ return -1;
+ }
+ if (!(mcr->alterfq.fqs & QM_MCR_FQS_ORLPRESENT)) {
+ /* ORL had no entries, no need to wait until the
+ ERNs come in */
+ orl_empty = 1;
+ }
+ /* Retirement succeeded, check to see if FQ needs
+ to be drained */
+ if (drain || mcr->alterfq.fqs & QM_MCR_FQS_NOTEMPTY) {
+ /* FQ is Not Empty, drain using volatile DQ commands */
+ fq_empty = 0;
+ do {
+ const struct qm_dqrr_entry *dqrr = NULL;
+ u32 vdqcr = fqid | QM_VDQCR_NUMFRAMES_SET(3);
+ qm_dqrr_vdqcr_set(portal[0], vdqcr);
+
+ /* Wait for a dequeue to occur */
+ while (dqrr == NULL) {
+ qm_dqrr_pvb_update(portal[0]);
+ dqrr = qm_dqrr_current(portal[0]);
+ if (!dqrr)
+ cpu_relax();
+ }
+ /* Process the dequeues, making sure to
+ empty the ring completely */
+ while (dqrr) {
+ if (dqrr->fqid == fqid &&
+ dqrr->stat & QM_DQRR_STAT_FQ_EMPTY)
+ fq_empty = 1;
+ qm_dqrr_cdc_consume_1ptr(portal[0],
+ dqrr, 0);
+ qm_dqrr_pvb_update(portal[0]);
+ qm_dqrr_next(portal[0]);
+ dqrr = qm_dqrr_current(portal[0]);
+ }
+ } while (fq_empty == 0);
+ }
+ for (i = 0; i < portal_count; i++)
+ qm_dqrr_sdqcr_set(portal[i], 0);
+
+ /* Wait for the ORL to have been completely drained */
+ while (orl_empty == 0) {
+ const struct qm_mr_entry *msg;
+ qm_mr_pvb_update(portal[0]);
+ msg = qm_mr_current(portal[0]);
+ while (msg) {
+ if ((msg->verb & QM_MR_VERB_TYPE_MASK) ==
+ QM_MR_VERB_FQRL)
+ orl_empty = 1;
+ qm_mr_next(portal[0]);
+ qm_mr_cci_consume_to_current(portal[0]);
+ qm_mr_pvb_update(portal[0]);
+ msg = qm_mr_current(portal[0]);
+ }
+ cpu_relax();
+ }
+ mcc = qm_mc_start(portal[0]);
+ mcc->alterfq.fqid = fqid;
+ qm_mc_commit(portal[0], QM_MCC_VERB_ALTER_OOS);
+ while (!(mcr = qm_mc_result(portal[0])))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) ==
+ QM_MCR_VERB_ALTER_OOS);
+ if (mcr->result != QM_MCR_RESULT_OK) {
+ pr_err("OOS after drain Failed on FQID 0x%x, result 0x%x\n",
+ fqid, mcr->result);
+ return -1;
+ }
+ return 0;
+ case QM_MCR_NP_STATE_RETIRED:
+ /* Send OOS Command */
+ mcc = qm_mc_start(portal[0]);
+ mcc->alterfq.fqid = fqid;
+ qm_mc_commit(portal[0], QM_MCC_VERB_ALTER_OOS);
+ while (!(mcr = qm_mc_result(portal[0])))
+ cpu_relax();
+ DPA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) ==
+ QM_MCR_VERB_ALTER_OOS);
+ if (mcr->result) {
+ pr_err("OOS Failed on FQID 0x%x\n", fqid);
+ return -1;
+ }
+ return 0;
+ case QM_MCR_NP_STATE_OOS:
+ /* Done */
+ return 0;
+ }
+ return -1;
+}
diff --git a/drivers/staging/fsl_qbman/qman_private.h b/drivers/staging/fsl_qbman/qman_private.h
new file mode 100644
index 0000000..b6e7e62
--- /dev/null
+++ b/drivers/staging/fsl_qbman/qman_private.h
@@ -0,0 +1,379 @@
+/* Copyright 2008-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "dpa_sys.h"
+#include <linux/fsl_qman.h>
+#include <linux/iommu.h>
+#include <asm/fsl_pamu_stash.h>
+
+#if !defined(CONFIG_FSL_QMAN_FQ_LOOKUP) && defined(CONFIG_PPC64)
+#error "_PPC64 requires _FSL_QMAN_FQ_LOOKUP"
+#endif
+
+ /* ----------------- */
+ /* Congestion Groups */
+ /* ----------------- */
+/* This wrapper represents a bit-array for the state of the 256 Qman congestion
+ * groups. Is also used as a *mask* for congestion groups, eg. so we ignore
+ * those that don't concern us. We harness the structure and accessor details
+ * already used in the management command to query congestion groups. */
+struct qman_cgrs {
+ struct __qm_mcr_querycongestion q;
+};
+static inline void qman_cgrs_init(struct qman_cgrs *c)
+{
+ memset(c, 0, sizeof(*c));
+}
+static inline void qman_cgrs_fill(struct qman_cgrs *c)
+{
+ memset(c, 0xff, sizeof(*c));
+}
+static inline int qman_cgrs_get(struct qman_cgrs *c, int num)
+{
+ return QM_MCR_QUERYCONGESTION(&c->q, num);
+}
+static inline void qman_cgrs_set(struct qman_cgrs *c, int num)
+{
+ c->q.__state[__CGR_WORD(num)] |= (0x80000000 >> __CGR_SHIFT(num));
+}
+static inline void qman_cgrs_unset(struct qman_cgrs *c, int num)
+{
+ c->q.__state[__CGR_WORD(num)] &= ~(0x80000000 >> __CGR_SHIFT(num));
+}
+static inline int qman_cgrs_next(struct qman_cgrs *c, int num)
+{
+ while ((++num < __CGR_NUM) && !qman_cgrs_get(c, num))
+ ;
+ return num;
+}
+static inline void qman_cgrs_cp(struct qman_cgrs *dest,
+ const struct qman_cgrs *src)
+{
+ *dest = *src;
+}
+static inline void qman_cgrs_and(struct qman_cgrs *dest,
+ const struct qman_cgrs *a, const struct qman_cgrs *b)
+{
+ int ret;
+ u32 *_d = dest->q.__state;
+ const u32 *_a = a->q.__state;
+ const u32 *_b = b->q.__state;
+ for (ret = 0; ret < 8; ret++)
+ *(_d++) = *(_a++) & *(_b++);
+}
+static inline void qman_cgrs_xor(struct qman_cgrs *dest,
+ const struct qman_cgrs *a, const struct qman_cgrs *b)
+{
+ int ret;
+ u32 *_d = dest->q.__state;
+ const u32 *_a = a->q.__state;
+ const u32 *_b = b->q.__state;
+ for (ret = 0; ret < 8; ret++)
+ *(_d++) = *(_a++) ^ *(_b++);
+}
+
+ /* ----------------------- */
+ /* CEETM Congestion Groups */
+ /* ----------------------- */
+/* This wrapper represents a bit-array for the state of the 512 Qman CEETM
+ * congestion groups.
+ */
+struct qman_ccgrs {
+ struct __qm_mcr_querycongestion q[2];
+};
+static inline void qman_ccgrs_init(struct qman_ccgrs *c)
+{
+ memset(c, 0, sizeof(*c));
+}
+static inline void qman_ccgrs_fill(struct qman_ccgrs *c)
+{
+ memset(c, 0xff, sizeof(*c));
+}
+static inline int qman_ccgrs_get(struct qman_ccgrs *c, int num)
+{
+ if (num < __CGR_NUM)
+ return QM_MCR_QUERYCONGESTION(&c->q[0], num);
+ else
+ return QM_MCR_QUERYCONGESTION(&c->q[1], (num - __CGR_NUM));
+}
+static inline int qman_ccgrs_next(struct qman_ccgrs *c, int num)
+{
+ while ((++num < __CGR_NUM) && !qman_ccgrs_get(c, num))
+ ;
+ return num;
+}
+static inline void qman_ccgrs_cp(struct qman_ccgrs *dest,
+ const struct qman_ccgrs *src)
+{
+ *dest = *src;
+}
+static inline void qman_ccgrs_and(struct qman_ccgrs *dest,
+ const struct qman_ccgrs *a, const struct qman_ccgrs *b)
+{
+ int ret, i;
+ u32 *_d;
+ const u32 *_a, *_b;
+ for (i = 0; i < 2; i++) {
+ _d = dest->q[i].__state;
+ _a = a->q[i].__state;
+ _b = b->q[i].__state;
+ for (ret = 0; ret < 8; ret++)
+ *(_d++) = *(_a++) & *(_b++);
+ }
+}
+static inline void qman_ccgrs_xor(struct qman_ccgrs *dest,
+ const struct qman_ccgrs *a, const struct qman_ccgrs *b)
+{
+ int ret, i;
+ u32 *_d;
+ const u32 *_a, *_b;
+ for (i = 0; i < 2; i++) {
+ _d = dest->q[i].__state;
+ _a = a->q[i].__state;
+ _b = b->q[i].__state;
+ for (ret = 0; ret < 8; ret++)
+ *(_d++) = *(_a++) ^ *(_b++);
+ }
+}
+
+/* used by CCSR and portal interrupt code */
+enum qm_isr_reg {
+ qm_isr_status = 0,
+ qm_isr_enable = 1,
+ qm_isr_disable = 2,
+ qm_isr_inhibit = 3
+};
+
+struct qm_portal_config {
+ /* Corenet portal addresses;
+ * [0]==cache-enabled, [1]==cache-inhibited. */
+ __iomem void *addr_virt[2];
+ struct resource addr_phys[2];
+ struct device dev;
+ struct iommu_domain *iommu_domain;
+ /* Allow these to be joined in lists */
+ struct list_head list;
+ /* User-visible portal configuration settings */
+ struct qman_portal_config public_cfg;
+ /* power management saved data */
+ u32 saved_isdr;
+};
+
+/* Revision info (for errata and feature handling) */
+#define QMAN_REV11 0x0101
+#define QMAN_REV12 0x0102
+#define QMAN_REV20 0x0200
+#define QMAN_REV30 0x0300
+#define QMAN_REV31 0x0301
+extern u16 qman_ip_rev; /* 0 if uninitialised, otherwise QMAN_REVx */
+extern u32 qman_clk;
+extern u16 qman_portal_max;
+
+#ifdef CONFIG_FSL_QMAN_CONFIG
+/* Hooks from qman_driver.c to qman_config.c */
+int qman_init_ccsr(struct device_node *node);
+void qman_liodn_fixup(u16 channel);
+int qman_set_sdest(u16 channel, unsigned int cpu_idx);
+#endif
+
+int qm_set_wpm(int wpm);
+int qm_get_wpm(int *wpm);
+
+/* Hooks from qman_driver.c in to qman_high.c */
+struct qman_portal *qman_create_portal(
+ struct qman_portal *portal,
+ const struct qm_portal_config *config,
+ const struct qman_cgrs *cgrs);
+
+struct qman_portal *qman_create_affine_portal(
+ const struct qm_portal_config *config,
+ const struct qman_cgrs *cgrs);
+struct qman_portal *qman_create_affine_slave(struct qman_portal *redirect,
+ int cpu);
+const struct qm_portal_config *qman_destroy_affine_portal(void);
+void qman_destroy_portal(struct qman_portal *qm);
+
+/* Hooks from fsl_usdpaa.c to qman_driver.c */
+struct qm_portal_config *qm_get_unused_portal(void);
+struct qm_portal_config *qm_get_unused_portal_idx(uint32_t idx);
+
+void qm_put_unused_portal(struct qm_portal_config *pcfg);
+void qm_set_liodns(struct qm_portal_config *pcfg);
+
+/* This CGR feature is supported by h/w and required by unit-tests and the
+ * debugfs hooks, so is implemented in the driver. However it allows an explicit
+ * corruption of h/w fields by s/w that are usually incorruptible (because the
+ * counters are usually maintained entirely within h/w). As such, we declare
+ * this API internally. */
+int qman_testwrite_cgr(struct qman_cgr *cgr, u64 i_bcnt,
+ struct qm_mcr_cgrtestwrite *result);
+
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+/* If the fq object pointer is greater than the size of context_b field,
+ * than a lookup table is required. */
+int qman_setup_fq_lookup_table(size_t num_entries);
+#endif
+
+
+/*************************************************/
+/* QMan s/w corenet portal, low-level i/face */
+/*************************************************/
+
+/* Note: most functions are only used by the high-level interface, so are
+ * inlined from qman_low.h. The stuff below is for use by other parts of the
+ * driver. */
+
+/* For qm_dqrr_sdqcr_set(); Choose one SOURCE. Choose one COUNT. Choose one
+ * dequeue TYPE. Choose TOKEN (8-bit).
+ * If SOURCE == CHANNELS,
+ * Choose CHANNELS_DEDICATED and/or CHANNELS_POOL(n).
+ * You can choose DEDICATED_PRECEDENCE if the portal channel should have
+ * priority.
+ * If SOURCE == SPECIFICWQ,
+ * Either select the work-queue ID with SPECIFICWQ_WQ(), or select the
+ * channel (SPECIFICWQ_DEDICATED or SPECIFICWQ_POOL()) and specify the
+ * work-queue priority (0-7) with SPECIFICWQ_WQ() - either way, you get the
+ * same value.
+ */
+#define QM_SDQCR_SOURCE_CHANNELS 0x0
+#define QM_SDQCR_SOURCE_SPECIFICWQ 0x40000000
+#define QM_SDQCR_COUNT_EXACT1 0x0
+#define QM_SDQCR_COUNT_UPTO3 0x20000000
+#define QM_SDQCR_DEDICATED_PRECEDENCE 0x10000000
+#define QM_SDQCR_TYPE_MASK 0x03000000
+#define QM_SDQCR_TYPE_NULL 0x0
+#define QM_SDQCR_TYPE_PRIO_QOS 0x01000000
+#define QM_SDQCR_TYPE_ACTIVE_QOS 0x02000000
+#define QM_SDQCR_TYPE_ACTIVE 0x03000000
+#define QM_SDQCR_TOKEN_MASK 0x00ff0000
+#define QM_SDQCR_TOKEN_SET(v) (((v) & 0xff) << 16)
+#define QM_SDQCR_TOKEN_GET(v) (((v) >> 16) & 0xff)
+#define QM_SDQCR_CHANNELS_DEDICATED 0x00008000
+#define QM_SDQCR_SPECIFICWQ_MASK 0x000000f7
+#define QM_SDQCR_SPECIFICWQ_DEDICATED 0x00000000
+#define QM_SDQCR_SPECIFICWQ_POOL(n) ((n) << 4)
+#define QM_SDQCR_SPECIFICWQ_WQ(n) (n)
+
+/* For qm_dqrr_vdqcr_set(): use FQID(n) to fill in the frame queue ID */
+#define QM_VDQCR_FQID_MASK 0x00ffffff
+#define QM_VDQCR_FQID(n) ((n) & QM_VDQCR_FQID_MASK)
+
+/* For qm_dqrr_pdqcr_set(); Choose one MODE. Choose one COUNT.
+ * If MODE==SCHEDULED
+ * Choose SCHEDULED_CHANNELS or SCHEDULED_SPECIFICWQ. Choose one dequeue TYPE.
+ * If CHANNELS,
+ * Choose CHANNELS_DEDICATED and/or CHANNELS_POOL() channels.
+ * You can choose DEDICATED_PRECEDENCE if the portal channel should have
+ * priority.
+ * If SPECIFICWQ,
+ * Either select the work-queue ID with SPECIFICWQ_WQ(), or select the
+ * channel (SPECIFICWQ_DEDICATED or SPECIFICWQ_POOL()) and specify the
+ * work-queue priority (0-7) with SPECIFICWQ_WQ() - either way, you get the
+ * same value.
+ * If MODE==UNSCHEDULED
+ * Choose FQID().
+ */
+#define QM_PDQCR_MODE_SCHEDULED 0x0
+#define QM_PDQCR_MODE_UNSCHEDULED 0x80000000
+#define QM_PDQCR_SCHEDULED_CHANNELS 0x0
+#define QM_PDQCR_SCHEDULED_SPECIFICWQ 0x40000000
+#define QM_PDQCR_COUNT_EXACT1 0x0
+#define QM_PDQCR_COUNT_UPTO3 0x20000000
+#define QM_PDQCR_DEDICATED_PRECEDENCE 0x10000000
+#define QM_PDQCR_TYPE_MASK 0x03000000
+#define QM_PDQCR_TYPE_NULL 0x0
+#define QM_PDQCR_TYPE_PRIO_QOS 0x01000000
+#define QM_PDQCR_TYPE_ACTIVE_QOS 0x02000000
+#define QM_PDQCR_TYPE_ACTIVE 0x03000000
+#define QM_PDQCR_CHANNELS_DEDICATED 0x00008000
+#define QM_PDQCR_CHANNELS_POOL(n) (0x00008000 >> (n))
+#define QM_PDQCR_SPECIFICWQ_MASK 0x000000f7
+#define QM_PDQCR_SPECIFICWQ_DEDICATED 0x00000000
+#define QM_PDQCR_SPECIFICWQ_POOL(n) ((n) << 4)
+#define QM_PDQCR_SPECIFICWQ_WQ(n) (n)
+#define QM_PDQCR_FQID(n) ((n) & 0xffffff)
+
+/* Used by all portal interrupt registers except 'inhibit'
+ * Channels with frame availability
+ */
+#define QM_PIRQ_DQAVAIL 0x0000ffff
+
+/* The DQAVAIL interrupt fields break down into these bits; */
+#define QM_DQAVAIL_PORTAL 0x8000 /* Portal channel */
+#define QM_DQAVAIL_POOL(n) (0x8000 >> (n)) /* Pool channel, n==[1..15] */
+#define QM_DQAVAIL_MASK 0xffff
+/* This mask contains all the "irqsource" bits visible to API users */
+#define QM_PIRQ_VISIBLE (QM_PIRQ_SLOW | QM_PIRQ_DQRI)
+
+/* These are qm_<reg>_<verb>(). So for example, qm_disable_write() means "write
+ * the disable register" rather than "disable the ability to write". */
+#define qm_isr_status_read(qm) __qm_isr_read(qm, qm_isr_status)
+#define qm_isr_status_clear(qm, m) __qm_isr_write(qm, qm_isr_status, m)
+#define qm_isr_enable_read(qm) __qm_isr_read(qm, qm_isr_enable)
+#define qm_isr_enable_write(qm, v) __qm_isr_write(qm, qm_isr_enable, v)
+#define qm_isr_disable_read(qm) __qm_isr_read(qm, qm_isr_disable)
+#define qm_isr_disable_write(qm, v) __qm_isr_write(qm, qm_isr_disable, v)
+/* TODO: unfortunate name-clash here, reword? */
+#define qm_isr_inhibit(qm) __qm_isr_write(qm, qm_isr_inhibit, 1)
+#define qm_isr_uninhibit(qm) __qm_isr_write(qm, qm_isr_inhibit, 0)
+
+#ifdef CONFIG_FSL_QMAN_CONFIG
+int qman_have_ccsr(void);
+#else
+#define qman_have_ccsr 0
+#endif
+
+__init int qman_init(void);
+__init int qman_resource_init(void);
+
+/* CEETM related */
+#define QMAN_CEETM_MAX 2
+extern u8 num_ceetms;
+extern struct qm_ceetm qman_ceetms[QMAN_CEETM_MAX];
+int qman_sp_enable_ceetm_mode(enum qm_dc_portal portal, u16 sub_portal);
+int qman_sp_disable_ceetm_mode(enum qm_dc_portal portal, u16 sub_portal);
+int qman_ceetm_set_prescaler(enum qm_dc_portal portal);
+int qman_ceetm_get_prescaler(u16 *pres);
+int qman_ceetm_query_cq(unsigned int cqid, unsigned int dcpid,
+ struct qm_mcr_ceetm_cq_query *cq_query);
+int qman_ceetm_query_ccgr(struct qm_mcc_ceetm_ccgr_query *ccgr_query,
+ struct qm_mcr_ceetm_ccgr_query *response);
+int qman_ceetm_get_xsfdr(enum qm_dc_portal portal, unsigned int *num);
+
+extern void *affine_portals[NR_CPUS];
+const struct qm_portal_config *qman_get_qm_portal_config(
+ struct qman_portal *portal);
+
+/* power management */
+#ifdef CONFIG_SUSPEND
+void suspend_unused_qportal(void);
+void resume_unused_qportal(void);
+#endif
diff --git a/drivers/staging/fsl_qbman/qman_test.c b/drivers/staging/fsl_qbman/qman_test.c
new file mode 100644
index 0000000..7995dd8
--- /dev/null
+++ b/drivers/staging/fsl_qbman/qman_test.c
@@ -0,0 +1,57 @@
+/* Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "qman_test.h"
+
+MODULE_AUTHOR("Geoff Thorpe");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("Qman testing");
+
+static int test_init(void)
+{
+ int loop = 1;
+ while (loop--) {
+#ifdef CONFIG_FSL_QMAN_TEST_STASH_POTATO
+ qman_test_hotpotato();
+#endif
+#ifdef CONFIG_FSL_QMAN_TEST_HIGH
+ qman_test_high();
+#endif
+ }
+ return 0;
+}
+
+static void test_exit(void)
+{
+}
+
+module_init(test_init);
+module_exit(test_exit);
diff --git a/drivers/staging/fsl_qbman/qman_test.h b/drivers/staging/fsl_qbman/qman_test.h
new file mode 100644
index 0000000..49c5679
--- /dev/null
+++ b/drivers/staging/fsl_qbman/qman_test.h
@@ -0,0 +1,44 @@
+/* Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <linux/fsl_qman.h>
+
+void qman_test_hotpotato(void);
+void qman_test_high(void);
+
diff --git a/drivers/staging/fsl_qbman/qman_test_high.c b/drivers/staging/fsl_qbman/qman_test_high.c
new file mode 100644
index 0000000..45a459b
--- /dev/null
+++ b/drivers/staging/fsl_qbman/qman_test_high.c
@@ -0,0 +1,213 @@
+/* Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "qman_test.h"
+
+/*************/
+/* constants */
+/*************/
+
+#define CGR_ID 27
+#define POOL_ID 2
+#define FQ_FLAGS QMAN_FQ_FLAG_DYNAMIC_FQID
+#define NUM_ENQUEUES 10
+#define NUM_PARTIAL 4
+#define PORTAL_SDQCR (QM_SDQCR_SOURCE_CHANNELS | \
+ QM_SDQCR_TYPE_PRIO_QOS | \
+ QM_SDQCR_TOKEN_SET(0x98) | \
+ QM_SDQCR_CHANNELS_DEDICATED | \
+ QM_SDQCR_CHANNELS_POOL(POOL_ID))
+#define PORTAL_OPAQUE ((void *)0xf00dbeef)
+#define VDQCR_FLAGS (QMAN_VOLATILE_FLAG_WAIT | QMAN_VOLATILE_FLAG_FINISH)
+
+/*************************************/
+/* Predeclarations (eg. for fq_base) */
+/*************************************/
+
+static enum qman_cb_dqrr_result cb_dqrr(struct qman_portal *,
+ struct qman_fq *,
+ const struct qm_dqrr_entry *);
+static void cb_ern(struct qman_portal *, struct qman_fq *,
+ const struct qm_mr_entry *);
+static void cb_fqs(struct qman_portal *, struct qman_fq *,
+ const struct qm_mr_entry *);
+
+/***************/
+/* global vars */
+/***************/
+
+static struct qm_fd fd, fd_dq;
+static struct qman_fq fq_base = {
+ .cb.dqrr = cb_dqrr,
+ .cb.ern = cb_ern,
+ .cb.fqs = cb_fqs
+};
+static DECLARE_WAIT_QUEUE_HEAD(waitqueue);
+static int retire_complete, sdqcr_complete;
+
+/**********************/
+/* internal functions */
+/**********************/
+
+/* Helpers for initialising and "incrementing" a frame descriptor */
+static void fd_init(struct qm_fd *__fd)
+{
+ qm_fd_addr_set64(__fd, 0xabdeadbeefLLU);
+ __fd->format = qm_fd_contig_big;
+ __fd->length29 = 0x0000ffff;
+ __fd->cmd = 0xfeedf00d;
+}
+
+static void fd_inc(struct qm_fd *__fd)
+{
+ u64 t = qm_fd_addr_get64(__fd);
+ int z = t >> 40;
+ t <<= 1;
+ if (z)
+ t |= 1;
+ qm_fd_addr_set64(__fd, t);
+ __fd->length29--;
+ __fd->cmd++;
+}
+
+/* The only part of the 'fd' we can't memcmp() is the ppid */
+static int fd_cmp(const struct qm_fd *a, const struct qm_fd *b)
+{
+ int r = (qm_fd_addr_get64(a) == qm_fd_addr_get64(b)) ? 0 : -1;
+ if (!r)
+ r = a->format - b->format;
+ if (!r)
+ r = a->opaque - b->opaque;
+ if (!r)
+ r = a->cmd - b->cmd;
+ return r;
+}
+
+/********/
+/* test */
+/********/
+
+static void do_enqueues(struct qman_fq *fq)
+{
+ unsigned int loop;
+ for (loop = 0; loop < NUM_ENQUEUES; loop++) {
+ if (qman_enqueue(fq, &fd, QMAN_ENQUEUE_FLAG_WAIT |
+ (((loop + 1) == NUM_ENQUEUES) ?
+ QMAN_ENQUEUE_FLAG_WAIT_SYNC : 0)))
+ panic("qman_enqueue() failed\n");
+ fd_inc(&fd);
+ }
+}
+
+void qman_test_high(void)
+{
+ unsigned int flags;
+ int res;
+ struct qman_fq *fq = &fq_base;
+
+ pr_info("qman_test_high starting\n");
+ fd_init(&fd);
+ fd_init(&fd_dq);
+
+ /* Initialise (parked) FQ */
+ if (qman_create_fq(0, FQ_FLAGS, fq))
+ panic("qman_create_fq() failed\n");
+ if (qman_init_fq(fq, QMAN_INITFQ_FLAG_LOCAL, NULL))
+ panic("qman_init_fq() failed\n");
+
+ /* Do enqueues + VDQCR, twice. (Parked FQ) */
+ do_enqueues(fq);
+ pr_info("VDQCR (till-empty);\n");
+ if (qman_volatile_dequeue(fq, VDQCR_FLAGS,
+ QM_VDQCR_NUMFRAMES_TILLEMPTY))
+ panic("qman_volatile_dequeue() failed\n");
+ do_enqueues(fq);
+ pr_info("VDQCR (%d of %d);\n", NUM_PARTIAL, NUM_ENQUEUES);
+ if (qman_volatile_dequeue(fq, VDQCR_FLAGS,
+ QM_VDQCR_NUMFRAMES_SET(NUM_PARTIAL)))
+ panic("qman_volatile_dequeue() failed\n");
+ pr_info("VDQCR (%d of %d);\n", NUM_ENQUEUES - NUM_PARTIAL,
+ NUM_ENQUEUES);
+ if (qman_volatile_dequeue(fq, VDQCR_FLAGS,
+ QM_VDQCR_NUMFRAMES_SET(NUM_ENQUEUES - NUM_PARTIAL)))
+ panic("qman_volatile_dequeue() failed\n");
+
+ do_enqueues(fq);
+ pr_info("scheduled dequeue (till-empty)\n");
+ if (qman_schedule_fq(fq))
+ panic("qman_schedule_fq() failed\n");
+ wait_event(waitqueue, sdqcr_complete);
+
+ /* Retire and OOS the FQ */
+ res = qman_retire_fq(fq, &flags);
+ if (res < 0)
+ panic("qman_retire_fq() failed\n");
+ wait_event(waitqueue, retire_complete);
+ if (flags & QMAN_FQ_STATE_BLOCKOOS)
+ panic("leaking frames\n");
+ if (qman_oos_fq(fq))
+ panic("qman_oos_fq() failed\n");
+ qman_destroy_fq(fq, 0);
+ pr_info("qman_test_high finished\n");
+}
+
+static enum qman_cb_dqrr_result cb_dqrr(struct qman_portal *p,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry *dq)
+{
+ if (fd_cmp(&fd_dq, &dq->fd)) {
+ pr_err("BADNESS: dequeued frame doesn't match;\n");
+ BUG();
+ }
+ fd_inc(&fd_dq);
+ if (!(dq->stat & QM_DQRR_STAT_UNSCHEDULED) && !fd_cmp(&fd_dq, &fd)) {
+ sdqcr_complete = 1;
+ wake_up(&waitqueue);
+ }
+ return qman_cb_dqrr_consume;
+}
+
+static void cb_ern(struct qman_portal *p, struct qman_fq *fq,
+ const struct qm_mr_entry *msg)
+{
+ panic("cb_ern() unimplemented");
+}
+
+static void cb_fqs(struct qman_portal *p, struct qman_fq *fq,
+ const struct qm_mr_entry *msg)
+{
+ u8 verb = (msg->verb & QM_MR_VERB_TYPE_MASK);
+ if ((verb != QM_MR_VERB_FQRN) && (verb != QM_MR_VERB_FQRNI))
+ panic("unexpected FQS message");
+ pr_info("Retirement message received\n");
+ retire_complete = 1;
+ wake_up(&waitqueue);
+}
diff --git a/drivers/staging/fsl_qbman/qman_test_hotpotato.c b/drivers/staging/fsl_qbman/qman_test_hotpotato.c
new file mode 100644
index 0000000..05db7ee
--- /dev/null
+++ b/drivers/staging/fsl_qbman/qman_test_hotpotato.c
@@ -0,0 +1,497 @@
+/* Copyright 2009-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/kthread.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include "qman_test.h"
+
+/* Algorithm:
+ *
+ * Each cpu will have HP_PER_CPU "handlers" set up, each of which incorporates
+ * an rx/tx pair of FQ objects (both of which are stashed on dequeue). The
+ * organisation of FQIDs is such that the HP_PER_CPU*NUM_CPUS handlers will
+ * shuttle a "hot potato" frame around them such that every forwarding action
+ * moves it from one cpu to another. (The use of more than one handler per cpu
+ * is to allow enough handlers/FQs to truly test the significance of caching -
+ * ie. when cache-expiries are occurring.)
+ *
+ * The "hot potato" frame content will be HP_NUM_WORDS*4 bytes in size, and the
+ * first and last words of the frame data will undergo a transformation step on
+ * each forwarding action. To achieve this, each handler will be assigned a
+ * 32-bit "mixer", that is produced using a 32-bit LFSR. When a frame is
+ * received by a handler, the mixer of the expected sender is XOR'd into all
+ * words of the entire frame, which is then validated against the original
+ * values. Then, before forwarding, the entire frame is XOR'd with the mixer of
+ * the current handler. Apart from validating that the frame is taking the
+ * expected path, this also provides some quasi-realistic overheads to each
+ * forwarding action - dereferencing *all* the frame data, computation, and
+ * conditional branching. There is a "special" handler designated to act as the
+ * instigator of the test by creating an enqueuing the "hot potato" frame, and
+ * to determine when the test has completed by counting HP_LOOPS iterations.
+ *
+ * Init phases:
+ *
+ * 1. prepare each cpu's 'hp_cpu' struct using on_each_cpu(,,1) and link them
+ * into 'hp_cpu_list'. Specifically, set processor_id, allocate HP_PER_CPU
+ * handlers and link-list them (but do no other handler setup).
+ *
+ * 2. scan over 'hp_cpu_list' HP_PER_CPU times, the first time sets each
+ * hp_cpu's 'iterator' to point to its first handler. With each loop,
+ * allocate rx/tx FQIDs and mixer values to the hp_cpu's iterator handler
+ * and advance the iterator for the next loop. This includes a final fixup,
+ * which connects the last handler to the first (and which is why phase 2
+ * and 3 are separate).
+ *
+ * 3. scan over 'hp_cpu_list' HP_PER_CPU times, the first time sets each
+ * hp_cpu's 'iterator' to point to its first handler. With each loop,
+ * initialise FQ objects and advance the iterator for the next loop.
+ * Moreover, do this initialisation on the cpu it applies to so that Rx FQ
+ * initialisation targets the correct cpu.
+ */
+
+/* helper to run something on all cpus (can't use on_each_cpu(), as that invokes
+ * the fn from irq context, which is too restrictive). */
+struct bstrap {
+ void (*fn)(void);
+ atomic_t started;
+};
+static int bstrap_fn(void *__bstrap)
+{
+ struct bstrap *bstrap = __bstrap;
+ atomic_inc(&bstrap->started);
+ bstrap->fn();
+ while (!kthread_should_stop())
+ msleep(1);
+ return 0;
+}
+static int on_all_cpus(void (*fn)(void))
+{
+ int cpu;
+ for_each_cpu(cpu, cpu_online_mask) {
+ struct bstrap bstrap = {
+ .fn = fn,
+ .started = ATOMIC_INIT(0)
+ };
+ struct task_struct *k = kthread_create(bstrap_fn, &bstrap,
+ "hotpotato%d", cpu);
+ int ret;
+ if (IS_ERR(k))
+ return -ENOMEM;
+ kthread_bind(k, cpu);
+ wake_up_process(k);
+ /* If we call kthread_stop() before the "wake up" has had an
+ * effect, then the thread may exit with -EINTR without ever
+ * running the function. So poll until it's started before
+ * requesting it to stop. */
+ while (!atomic_read(&bstrap.started))
+ msleep(10);
+ ret = kthread_stop(k);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+struct hp_handler {
+
+ /* The following data is stashed when 'rx' is dequeued; */
+ /* -------------- */
+ /* The Rx FQ, dequeues of which will stash the entire hp_handler */
+ struct qman_fq rx;
+ /* The Tx FQ we should forward to */
+ struct qman_fq tx;
+ /* The value we XOR post-dequeue, prior to validating */
+ u32 rx_mixer;
+ /* The value we XOR pre-enqueue, after validating */
+ u32 tx_mixer;
+ /* what the hotpotato address should be on dequeue */
+ dma_addr_t addr;
+ u32 *frame_ptr;
+
+ /* The following data isn't (necessarily) stashed on dequeue; */
+ /* -------------- */
+ u32 fqid_rx, fqid_tx;
+ /* list node for linking us into 'hp_cpu' */
+ struct list_head node;
+ /* Just to check ... */
+ unsigned int processor_id;
+} ____cacheline_aligned;
+
+struct hp_cpu {
+ /* identify the cpu we run on; */
+ unsigned int processor_id;
+ /* root node for the per-cpu list of handlers */
+ struct list_head handlers;
+ /* list node for linking us into 'hp_cpu_list' */
+ struct list_head node;
+ /* when repeatedly scanning 'hp_list', each time linking the n'th
+ * handlers together, this is used as per-cpu iterator state */
+ struct hp_handler *iterator;
+};
+
+/* Each cpu has one of these */
+static DEFINE_PER_CPU(struct hp_cpu, hp_cpus);
+
+/* links together the hp_cpu structs, in first-come first-serve order. */
+static LIST_HEAD(hp_cpu_list);
+static spinlock_t hp_lock = __SPIN_LOCK_UNLOCKED(hp_lock);
+
+static unsigned int hp_cpu_list_length;
+
+/* the "special" handler, that starts and terminates the test. */
+static struct hp_handler *special_handler;
+static int loop_counter;
+
+/* handlers are allocated out of this, so they're properly aligned. */
+static struct kmem_cache *hp_handler_slab;
+
+/* this is the frame data */
+static void *__frame_ptr;
+static u32 *frame_ptr;
+static dma_addr_t frame_dma;
+
+/* the main function waits on this */
+static DECLARE_WAIT_QUEUE_HEAD(queue);
+
+#define HP_PER_CPU 2
+#define HP_LOOPS 8
+/* 80 bytes, like a small ethernet frame, and bleeds into a second cacheline */
+#define HP_NUM_WORDS 80
+/* First word of the LFSR-based frame data */
+#define HP_FIRST_WORD 0xabbaf00d
+
+static inline u32 do_lfsr(u32 prev)
+{
+ return (prev >> 1) ^ (-(prev & 1u) & 0xd0000001u);
+}
+
+static void allocate_frame_data(void)
+{
+ u32 lfsr = HP_FIRST_WORD;
+ int loop;
+ struct platform_device *pdev = platform_device_alloc("foobar", -1);
+ if (!pdev)
+ panic("platform_device_alloc() failed");
+ if (platform_device_add(pdev))
+ panic("platform_device_add() failed");
+ __frame_ptr = kmalloc(4 * HP_NUM_WORDS, GFP_KERNEL);
+ if (!__frame_ptr)
+ panic("kmalloc() failed");
+ frame_ptr = (void *)(((unsigned long)__frame_ptr + 63) &
+ ~(unsigned long)63);
+ for (loop = 0; loop < HP_NUM_WORDS; loop++) {
+ frame_ptr[loop] = lfsr;
+ lfsr = do_lfsr(lfsr);
+ }
+ frame_dma = dma_map_single(&pdev->dev, frame_ptr, 4 * HP_NUM_WORDS,
+ DMA_BIDIRECTIONAL);
+ platform_device_del(pdev);
+ platform_device_put(pdev);
+}
+
+static void deallocate_frame_data(void)
+{
+ kfree(__frame_ptr);
+}
+
+static inline void process_frame_data(struct hp_handler *handler,
+ const struct qm_fd *fd)
+{
+ u32 *p = handler->frame_ptr;
+ u32 lfsr = HP_FIRST_WORD;
+ int loop;
+ if (qm_fd_addr_get64(fd) != handler->addr)
+ panic("bad frame address");
+ for (loop = 0; loop < HP_NUM_WORDS; loop++, p++) {
+ *p ^= handler->rx_mixer;
+ if (*p != lfsr)
+ panic("corrupt frame data");
+ *p ^= handler->tx_mixer;
+ lfsr = do_lfsr(lfsr);
+ }
+}
+
+static enum qman_cb_dqrr_result normal_dqrr(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry *dqrr)
+{
+ struct hp_handler *handler = (struct hp_handler *)fq;
+
+ process_frame_data(handler, &dqrr->fd);
+ if (qman_enqueue(&handler->tx, &dqrr->fd, 0))
+ panic("qman_enqueue() failed");
+ return qman_cb_dqrr_consume;
+}
+
+static enum qman_cb_dqrr_result special_dqrr(struct qman_portal *portal,
+ struct qman_fq *fq,
+ const struct qm_dqrr_entry *dqrr)
+{
+ struct hp_handler *handler = (struct hp_handler *)fq;
+
+ process_frame_data(handler, &dqrr->fd);
+ if (++loop_counter < HP_LOOPS) {
+ if (qman_enqueue(&handler->tx, &dqrr->fd, 0))
+ panic("qman_enqueue() failed");
+ } else {
+ pr_info("Received final (%dth) frame\n", loop_counter);
+ wake_up(&queue);
+ }
+ return qman_cb_dqrr_consume;
+}
+
+static void create_per_cpu_handlers(void)
+{
+ struct hp_handler *handler;
+ int loop;
+ struct hp_cpu *hp_cpu = &__get_cpu_var(hp_cpus);
+
+ hp_cpu->processor_id = smp_processor_id();
+ spin_lock(&hp_lock);
+ list_add_tail(&hp_cpu->node, &hp_cpu_list);
+ hp_cpu_list_length++;
+ spin_unlock(&hp_lock);
+ INIT_LIST_HEAD(&hp_cpu->handlers);
+ for (loop = 0; loop < HP_PER_CPU; loop++) {
+ handler = kmem_cache_alloc(hp_handler_slab, GFP_KERNEL);
+ if (!handler)
+ panic("kmem_cache_alloc() failed");
+ handler->processor_id = hp_cpu->processor_id;
+ handler->addr = frame_dma;
+ handler->frame_ptr = frame_ptr;
+ list_add_tail(&handler->node, &hp_cpu->handlers);
+ }
+}
+
+static void destroy_per_cpu_handlers(void)
+{
+ struct list_head *loop, *tmp;
+ struct hp_cpu *hp_cpu = &__get_cpu_var(hp_cpus);
+
+ spin_lock(&hp_lock);
+ list_del(&hp_cpu->node);
+ spin_unlock(&hp_lock);
+ list_for_each_safe(loop, tmp, &hp_cpu->handlers) {
+ u32 flags;
+ struct hp_handler *handler = list_entry(loop, struct hp_handler,
+ node);
+ if (qman_retire_fq(&handler->rx, &flags))
+ panic("qman_retire_fq(rx) failed");
+ BUG_ON(flags & QMAN_FQ_STATE_BLOCKOOS);
+ if (qman_oos_fq(&handler->rx))
+ panic("qman_oos_fq(rx) failed");
+ qman_destroy_fq(&handler->rx, 0);
+ qman_destroy_fq(&handler->tx, 0);
+ qman_release_fqid(handler->fqid_rx);
+ list_del(&handler->node);
+ kmem_cache_free(hp_handler_slab, handler);
+ }
+}
+
+static inline u8 num_cachelines(u32 offset)
+{
+ u8 res = (offset + (L1_CACHE_BYTES - 1))
+ / (L1_CACHE_BYTES);
+ if (res > 3)
+ return 3;
+ return res;
+}
+#define STASH_DATA_CL \
+ num_cachelines(HP_NUM_WORDS * 4)
+#define STASH_CTX_CL \
+ num_cachelines(offsetof(struct hp_handler, fqid_rx))
+
+static void init_handler(void *__handler)
+{
+ struct qm_mcc_initfq opts;
+ struct hp_handler *handler = __handler;
+ BUG_ON(handler->processor_id != smp_processor_id());
+ /* Set up rx */
+ memset(&handler->rx, 0, sizeof(handler->rx));
+ if (handler == special_handler)
+ handler->rx.cb.dqrr = special_dqrr;
+ else
+ handler->rx.cb.dqrr = normal_dqrr;
+ if (qman_create_fq(handler->fqid_rx, 0, &handler->rx))
+ panic("qman_create_fq(rx) failed");
+ memset(&opts, 0, sizeof(opts));
+ opts.we_mask = QM_INITFQ_WE_FQCTRL | QM_INITFQ_WE_CONTEXTA;
+ opts.fqd.fq_ctrl = QM_FQCTRL_CTXASTASHING;
+ opts.fqd.context_a.stashing.data_cl = STASH_DATA_CL;
+ opts.fqd.context_a.stashing.context_cl = STASH_CTX_CL;
+ if (qman_init_fq(&handler->rx, QMAN_INITFQ_FLAG_SCHED |
+ QMAN_INITFQ_FLAG_LOCAL, &opts))
+ panic("qman_init_fq(rx) failed");
+ /* Set up tx */
+ memset(&handler->tx, 0, sizeof(handler->tx));
+ if (qman_create_fq(handler->fqid_tx, QMAN_FQ_FLAG_NO_MODIFY,
+ &handler->tx))
+ panic("qman_create_fq(tx) failed");
+}
+
+static void init_phase2(void)
+{
+ int loop;
+ u32 fqid = 0;
+ u32 lfsr = 0xdeadbeef;
+ struct hp_cpu *hp_cpu;
+ struct hp_handler *handler;
+
+ for (loop = 0; loop < HP_PER_CPU; loop++) {
+ list_for_each_entry(hp_cpu, &hp_cpu_list, node) {
+ int ret;
+ if (!loop)
+ hp_cpu->iterator = list_first_entry(
+ &hp_cpu->handlers,
+ struct hp_handler, node);
+ else
+ hp_cpu->iterator = list_entry(
+ hp_cpu->iterator->node.next,
+ struct hp_handler, node);
+ /* Rx FQID is the previous handler's Tx FQID */
+ hp_cpu->iterator->fqid_rx = fqid;
+ /* Allocate new FQID for Tx */
+ ret = qman_alloc_fqid(&fqid);
+ if (ret)
+ panic("qman_alloc_fqid() failed");
+ hp_cpu->iterator->fqid_tx = fqid;
+ /* Rx mixer is the previous handler's Tx mixer */
+ hp_cpu->iterator->rx_mixer = lfsr;
+ /* Get new mixer for Tx */
+ lfsr = do_lfsr(lfsr);
+ hp_cpu->iterator->tx_mixer = lfsr;
+ }
+ }
+ /* Fix up the first handler (fqid_rx==0, rx_mixer=0xdeadbeef) */
+ hp_cpu = list_first_entry(&hp_cpu_list, struct hp_cpu, node);
+ handler = list_first_entry(&hp_cpu->handlers, struct hp_handler, node);
+ BUG_ON((handler->fqid_rx != 0) || (handler->rx_mixer != 0xdeadbeef));
+ handler->fqid_rx = fqid;
+ handler->rx_mixer = lfsr;
+ /* and tag it as our "special" handler */
+ special_handler = handler;
+}
+
+static void init_phase3(void)
+{
+ int loop;
+ struct hp_cpu *hp_cpu;
+
+ for (loop = 0; loop < HP_PER_CPU; loop++) {
+ list_for_each_entry(hp_cpu, &hp_cpu_list, node) {
+ if (!loop)
+ hp_cpu->iterator = list_first_entry(
+ &hp_cpu->handlers,
+ struct hp_handler, node);
+ else
+ hp_cpu->iterator = list_entry(
+ hp_cpu->iterator->node.next,
+ struct hp_handler, node);
+ preempt_disable();
+ if (hp_cpu->processor_id == smp_processor_id())
+ init_handler(hp_cpu->iterator);
+ else
+ smp_call_function_single(hp_cpu->processor_id,
+ init_handler, hp_cpu->iterator, 1);
+ preempt_enable();
+ }
+ }
+}
+
+static void send_first_frame(void *ignore)
+{
+ u32 *p = special_handler->frame_ptr;
+ u32 lfsr = HP_FIRST_WORD;
+ int loop;
+ struct qm_fd fd;
+
+ BUG_ON(special_handler->processor_id != smp_processor_id());
+ memset(&fd, 0, sizeof(fd));
+ qm_fd_addr_set64(&fd, special_handler->addr);
+ fd.format = qm_fd_contig_big;
+ fd.length29 = HP_NUM_WORDS * 4;
+ for (loop = 0; loop < HP_NUM_WORDS; loop++, p++) {
+ if (*p != lfsr)
+ panic("corrupt frame data");
+ *p ^= special_handler->tx_mixer;
+ lfsr = do_lfsr(lfsr);
+ }
+ pr_info("Sending first frame\n");
+ if (qman_enqueue(&special_handler->tx, &fd, 0))
+ panic("qman_enqueue() failed");
+}
+
+void qman_test_hotpotato(void)
+{
+ if (cpumask_weight(cpu_online_mask) < 2) {
+ pr_info("qman_test_hotpotato, skip - only 1 CPU\n");
+ return;
+ }
+
+ pr_info("qman_test_hotpotato starting\n");
+
+ hp_cpu_list_length = 0;
+ loop_counter = 0;
+ hp_handler_slab = kmem_cache_create("hp_handler_slab",
+ sizeof(struct hp_handler), L1_CACHE_BYTES,
+ SLAB_HWCACHE_ALIGN, NULL);
+ if (!hp_handler_slab)
+ panic("kmem_cache_create() failed");
+
+ allocate_frame_data();
+
+ /* Init phase 1 */
+ pr_info("Creating %d handlers per cpu...\n", HP_PER_CPU);
+ if (on_all_cpus(create_per_cpu_handlers))
+ panic("on_each_cpu() failed");
+ pr_info("Number of cpus: %d, total of %d handlers\n",
+ hp_cpu_list_length, hp_cpu_list_length * HP_PER_CPU);
+
+ init_phase2();
+
+ init_phase3();
+
+ preempt_disable();
+ if (special_handler->processor_id == smp_processor_id())
+ send_first_frame(NULL);
+ else
+ smp_call_function_single(special_handler->processor_id,
+ send_first_frame, NULL, 1);
+ preempt_enable();
+
+ wait_event(queue, loop_counter == HP_LOOPS);
+ deallocate_frame_data();
+ if (on_all_cpus(destroy_per_cpu_handlers))
+ panic("on_each_cpu() failed");
+ kmem_cache_destroy(hp_handler_slab);
+ pr_info("qman_test_hotpotato finished\n");
+}
diff --git a/drivers/staging/fsl_qbman/qman_utility.c b/drivers/staging/fsl_qbman/qman_utility.c
new file mode 100644
index 0000000..f1e3902
--- /dev/null
+++ b/drivers/staging/fsl_qbman/qman_utility.c
@@ -0,0 +1,129 @@
+/* Copyright 2008-2011 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "qman_private.h"
+
+/* ----------------- */
+/* --- FQID Pool --- */
+
+struct qman_fqid_pool {
+ /* Base and size of the FQID range */
+ u32 fqid_base;
+ u32 total;
+ /* Number of FQIDs currently "allocated" */
+ u32 used;
+ /* Allocation optimisation. When 'used<total', it is the index of an
+ * available FQID. Otherwise there are no available FQIDs, and this
+ * will be set when the next deallocation occurs. */
+ u32 next;
+ /* A bit-field representation of the FQID range. */
+ unsigned long *bits;
+};
+
+#define QLONG_BYTES sizeof(unsigned long)
+#define QLONG_BITS (QLONG_BYTES * 8)
+/* Number of 'longs' required for the given number of bits */
+#define QNUM_LONGS(b) (((b) + QLONG_BITS - 1) / QLONG_BITS)
+/* Shorthand for the number of bytes of same (kmalloc, memset, etc) */
+#define QNUM_BYTES(b) (QNUM_LONGS(b) * QLONG_BYTES)
+/* And in bits */
+#define QNUM_BITS(b) (QNUM_LONGS(b) * QLONG_BITS)
+
+struct qman_fqid_pool *qman_fqid_pool_create(u32 fqid_start, u32 num)
+{
+ struct qman_fqid_pool *pool = kmalloc(sizeof(*pool), GFP_KERNEL);
+ unsigned int i;
+
+ BUG_ON(!num);
+ if (!pool)
+ return NULL;
+ pool->fqid_base = fqid_start;
+ pool->total = num;
+ pool->used = 0;
+ pool->next = 0;
+ pool->bits = kzalloc(QNUM_BYTES(num), GFP_KERNEL);
+ if (!pool->bits) {
+ kfree(pool);
+ return NULL;
+ }
+ /* If num is not an even multiple of QLONG_BITS (or even 8, for
+ * byte-oriented searching) then we fill the trailing bits with 1, to
+ * make them look allocated (permanently). */
+ for (i = num + 1; i < QNUM_BITS(num); i++)
+ set_bit(i, pool->bits);
+ return pool;
+}
+EXPORT_SYMBOL(qman_fqid_pool_create);
+
+int qman_fqid_pool_destroy(struct qman_fqid_pool *pool)
+{
+ int ret = pool->used;
+ kfree(pool->bits);
+ kfree(pool);
+ return ret;
+}
+EXPORT_SYMBOL(qman_fqid_pool_destroy);
+
+int qman_fqid_pool_alloc(struct qman_fqid_pool *pool, u32 *fqid)
+{
+ int ret;
+ if (pool->used == pool->total)
+ return -ENOMEM;
+ *fqid = pool->fqid_base + pool->next;
+ ret = test_and_set_bit(pool->next, pool->bits);
+ BUG_ON(ret);
+ if (++pool->used == pool->total)
+ return 0;
+ pool->next = find_next_zero_bit(pool->bits, pool->total, pool->next);
+ if (pool->next >= pool->total)
+ pool->next = find_first_zero_bit(pool->bits, pool->total);
+ BUG_ON(pool->next >= pool->total);
+ return 0;
+}
+EXPORT_SYMBOL(qman_fqid_pool_alloc);
+
+void qman_fqid_pool_free(struct qman_fqid_pool *pool, u32 fqid)
+{
+ int ret;
+
+ fqid -= pool->fqid_base;
+ ret = test_and_clear_bit(fqid, pool->bits);
+ BUG_ON(!ret);
+ if (pool->used-- == pool->total)
+ pool->next = fqid;
+}
+EXPORT_SYMBOL(qman_fqid_pool_free);
+
+u32 qman_fqid_pool_used(struct qman_fqid_pool *pool)
+{
+ return pool->used;
+}
+EXPORT_SYMBOL(qman_fqid_pool_used);
diff --git a/drivers/staging/fsl_rman/Kconfig b/drivers/staging/fsl_rman/Kconfig
new file mode 100644
index 0000000..9ba0504
--- /dev/null
+++ b/drivers/staging/fsl_rman/Kconfig
@@ -0,0 +1,4 @@
+config FSL_RMAN_UIO
+ bool "Freescale RapidIO Message Manager support"
+ depends on UIO
+ default y
diff --git a/drivers/staging/fsl_rman/Makefile b/drivers/staging/fsl_rman/Makefile
new file mode 100644
index 0000000..6329e96
--- /dev/null
+++ b/drivers/staging/fsl_rman/Makefile
@@ -0,0 +1,2 @@
+# FSL RMan
+obj-$(CONFIG_FSL_RMAN_UIO) += rman_uio_driver.o
diff --git a/drivers/staging/fsl_rman/rman_uio_driver.c b/drivers/staging/fsl_rman/rman_uio_driver.c
new file mode 100644
index 0000000..4859a5f
--- /dev/null
+++ b/drivers/staging/fsl_rman/rman_uio_driver.c
@@ -0,0 +1,349 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Minghuan Lian <Minghuan.Lian@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/uio_driver.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+
+static const char rman_uio_version[] = "RMan UIO driver v1.0";
+
+#define IB_INDEX_OFFSET 12
+#define MMIER 0x0420 /* Message manage Interrupt Enable Register*/
+#define MMEDR 0x0424 /* Message manager error detect register */
+#define MMEDR_CLEAR 0x800000FF
+
+struct rman_uio_info {
+ atomic_t ref; /* exclusive, only one open() at a time */
+ struct uio_info uio;
+ char name[30];
+};
+
+struct rman_dev {
+ u32 revision;
+ int irq;
+ void __iomem *global_regs;
+ struct device *dev;
+ struct rman_uio_info info;
+ struct resource *res;
+ struct list_head ib_list;
+};
+
+struct rman_inbound_block {
+ struct list_head node;
+ u32 index;
+ struct device *dev;
+ struct rman_uio_info info;
+ struct resource *res;
+};
+
+static int rman_uio_open(struct uio_info *info, struct inode *inode)
+{
+ struct rman_uio_info *i = container_of(info, struct rman_uio_info, uio);
+ if (!atomic_dec_and_test(&i->ref)) {
+ pr_err("%s: failing non-exclusive open()\n", i->name);
+ atomic_inc(&i->ref);
+ return -EBUSY;
+ }
+ return 0;
+}
+
+static int rman_uio_release(struct uio_info *info, struct inode *inode)
+{
+ struct rman_uio_info *i = container_of(info, struct rman_uio_info, uio);
+ atomic_inc(&i->ref);
+ return 0;
+}
+
+static irqreturn_t rman_uio_irq_handler(int irq, struct uio_info *dev_info)
+{
+ struct rman_dev *rmdev = dev_info->priv;
+ u32 status;
+
+ status = in_be32(rmdev->global_regs + MMEDR);
+
+ if (status) {
+ /* disable interrupt */
+ out_be32(rmdev->global_regs + MMIER, 0);
+ return IRQ_HANDLED;
+ } else
+ return IRQ_NONE;
+}
+
+static int rman_uio_init(struct rman_dev *rmdev)
+{
+ int ret;
+ struct rman_uio_info *info;
+
+ info = &rmdev->info;
+ atomic_set(&info->ref, 1);
+ info->uio.name = info->name;
+ info->uio.version = rman_uio_version;
+ info->uio.mem[0].name = "rman regs";
+ info->uio.mem[0].addr = rmdev->res->start;
+ info->uio.mem[0].size = rmdev->res->end - rmdev->res->start + 1;
+ info->uio.mem[0].internal_addr = rmdev->global_regs;
+ info->uio.mem[0].memtype = UIO_MEM_PHYS;
+ info->uio.irq = rmdev->irq;
+ info->uio.irq_flags = IRQF_SHARED;
+ info->uio.handler = rman_uio_irq_handler;
+ info->uio.open = rman_uio_open;
+ info->uio.release = rman_uio_release;
+ info->uio.priv = rmdev;
+ ret = uio_register_device(rmdev->dev, &info->uio);
+ if (ret) {
+ pr_err("rman_uio: UIO registration failed\n");
+ return ret;
+ }
+ return 0;
+}
+
+static int rman_ib_uio_init(struct rman_inbound_block *ib)
+{
+ int ret;
+ struct rman_uio_info *info;
+
+ info = &ib->info;
+ atomic_set(&info->ref, 1);
+ info->uio.name = info->name;
+ info->uio.version = rman_uio_version;
+ info->uio.mem[0].name = "rman inbound block regs";
+ info->uio.mem[0].addr = ib->res->start;
+ info->uio.mem[0].size = ib->res->end - ib->res->start + 1;
+ info->uio.mem[0].memtype = UIO_MEM_PHYS;
+ info->uio.open = rman_uio_open;
+ info->uio.release = rman_uio_release;
+ info->uio.priv = ib;
+ ret = uio_register_device(ib->dev, &info->uio);
+ if (ret) {
+ pr_err("rman_ib_uio: UIO registration failed\n");
+ return ret;
+ }
+ return 0;
+}
+
+static int fsl_rman_ib_probe(struct device_node *ib_node,
+ struct rman_dev *rmdev)
+{
+ struct rman_inbound_block *ib;
+ struct resource regs;
+ int err;
+
+ if (!ib_node || !rmdev)
+ return -EINVAL;
+
+ ib = kzalloc(sizeof(*ib), GFP_KERNEL);
+ if (!ib) {
+ dev_err(rmdev->dev, "Can't alloc memory for inbound_block\n");
+ return -ENOMEM;
+ }
+
+ ib->dev = rmdev->dev;
+
+ err = of_address_to_resource(ib_node, 0, &regs);
+ if (unlikely(err < 0)) {
+ dev_err(ib->dev, "Can't get property 'reg'\n");
+ err = -EFAULT;
+ goto _err;
+ }
+
+ ib->index = (regs.start >> IB_INDEX_OFFSET) & 0xf;
+ snprintf(ib->info.name, sizeof(ib->info.name),
+ "rman-inbound-block%d", ib->index);
+
+ ib->res = devm_request_mem_region(rmdev->dev, regs.start,
+ regs.end + 1 - regs.start,
+ ib->info.name);
+ if (unlikely(!ib->res)) {
+ dev_err(ib->dev, "devm_request_mem_region failed\n");
+ err = -ENOMEM;
+ goto _err;
+ }
+ dev_dbg(ib->dev,
+ "inbound block%d reg start 0x%016llx, size 0x%016llx.\n",
+ ib->index, ib->res->start,
+ ib->res->end + 1 - ib->res->start);
+
+ err = rman_ib_uio_init(ib);
+ if (err)
+ goto _err;
+
+ list_add(&ib->node, &rmdev->ib_list);
+ dev_info(ib->dev, "RMan inbound block%d initialized.\n", ib->index);
+ return 0;
+_err:
+ kfree(ib);
+ return err;
+}
+
+static int fsl_rman_ib_remove(struct rman_inbound_block *ib)
+{
+ if (!ib)
+ return 0;
+ uio_unregister_device(&ib->info.uio);
+ kfree(ib);
+ return 0;
+}
+
+static int fsl_rman_probe(struct platform_device *dev)
+{
+ struct resource regs;
+ struct rman_dev *rman_dev;
+ struct device_node *rman_node, *child;
+ struct rman_inbound_block *ib, *tmp;
+ int err;
+
+ rman_node = dev->dev.of_node;
+ if (!rman_node) {
+ dev_err(&dev->dev, "Device OF-Node is NULL");
+ return -EFAULT;
+ }
+ dev_info(&dev->dev, "Of-device %s initialized\n",
+ rman_node->full_name);
+
+ rman_dev = kzalloc(sizeof(struct rman_dev), GFP_KERNEL);
+ if (!rman_dev) {
+ dev_err(&dev->dev, "Can't allocate memory for 'rman_dev'\n");
+ return -ENOMEM;
+ }
+
+ rman_dev->dev = &dev->dev;
+ INIT_LIST_HEAD(&rman_dev->ib_list);
+ platform_set_drvdata(dev, rman_dev);
+
+ for_each_child_of_node(rman_node, child) {
+ if (of_device_is_compatible(child, "fsl,rman-inbound-block"))
+ fsl_rman_ib_probe(child, rman_dev);
+
+ if (of_device_is_compatible(child, "fsl,rman-global-cfg")) {
+ err = of_address_to_resource(child, 0, &regs);
+ if (unlikely(err < 0)) {
+ dev_err(&dev->dev,
+ "Can't get property 'reg'\n");
+ err = -EFAULT;
+ goto _err;
+ }
+ }
+ }
+
+ snprintf(rman_dev->info.name, sizeof(rman_dev->info.name),
+ "rman-uio");
+ rman_dev->res = devm_request_mem_region(&dev->dev, regs.start,
+ regs.end - regs.start + 1,
+ rman_dev->info.name);
+ dev_dbg(&dev->dev, "global regs start 0x%016llx, size 0x%016llx.\n",
+ rman_dev->res->start,
+ rman_dev->res->end + 1 - rman_dev->res->start);
+ if (unlikely(rman_dev->res == NULL)) {
+ dev_err(&dev->dev, "devm_request_mem_region failed\n");
+ err = -ENOMEM;
+ goto _err;
+ }
+
+ rman_dev->global_regs = devm_ioremap(&dev->dev, rman_dev->res->start,
+ rman_dev->res->end - rman_dev->res->start + 1);
+ if (unlikely(rman_dev->global_regs == 0)) {
+ dev_err(&dev->dev, "devm_ioremap failed\n");
+ err = -EIO;
+ goto _err;
+ }
+
+ rman_dev->irq = irq_of_parse_and_map(rman_node, 0);
+ dev_dbg(rman_dev->dev, "errirq: %d\n", rman_dev->irq);
+
+ err = rman_uio_init(rman_dev);
+ if (err)
+ goto _err;
+ return 0;
+
+_err:
+ platform_set_drvdata(dev, NULL);
+ list_for_each_entry_safe(ib, tmp, &rman_dev->ib_list, node) {
+ list_del(&ib->node);
+ fsl_rman_ib_remove(ib);
+ }
+ kfree(rman_dev);
+ return err;
+}
+
+static int fsl_rman_remove(struct platform_device *dev)
+{
+ struct rman_dev *rman_dev = platform_get_drvdata(dev);
+ struct rman_inbound_block *ib, *tmp;
+
+ if (!rman_dev)
+ return -EINVAL;
+
+ list_for_each_entry_safe(ib, tmp, &rman_dev->ib_list, node) {
+ list_del(&ib->node);
+ fsl_rman_ib_remove(ib);
+ }
+
+ uio_unregister_device(&rman_dev->info.uio);
+ platform_set_drvdata(dev, NULL);
+ kfree(rman_dev);
+ return 0;
+}
+
+static const struct of_device_id fsl_of_rman_match[] = {
+ {
+ .compatible = "fsl,rman",
+ },
+ {}
+};
+
+static struct platform_driver fsl_rman_driver = {
+ .driver = {
+ .name = "fsl-of-rman",
+ .owner = THIS_MODULE,
+ .of_match_table = fsl_of_rman_match,
+ },
+ .probe = fsl_rman_probe,
+ .remove = fsl_rman_remove,
+};
+
+static int __init fsl_rman_init(void)
+{
+ int err;
+
+ err = platform_driver_register(&fsl_rman_driver);
+ if (unlikely(err < 0))
+ pr_warn(": %s:%hu:%s(): platform_driver_register() = %d\n",
+ __FILE__, __LINE__, __func__, err);
+
+ return err;
+}
+
+static void __exit fsl_rman_exit(void)
+{
+ platform_driver_unregister(&fsl_rman_driver);
+}
+
+module_init(fsl_rman_init);
+module_exit(fsl_rman_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Minghuan Lian <Minghuan.Lian@freescale.com>");
+MODULE_DESCRIPTION("Freescale RMan UIO driver");
diff --git a/drivers/tdm/Kconfig b/drivers/tdm/Kconfig
new file mode 100644
index 0000000..434ad6e
--- /dev/null
+++ b/drivers/tdm/Kconfig
@@ -0,0 +1,28 @@
+#
+# TDM subsystem configuration
+#
+
+menuconfig TDM
+ tristate "TDM support"
+ ---help---
+ More information is contained in the directory <file:Documentation/tdm/>,
+ especially in the file called "summary" there.
+ If you want TDM support, you should say Y here and also to the
+ specific driver for your bus adapter(s) below.
+
+ This TDM support can also be built as a module. If so, the module
+ will be called tdm-core.
+
+if TDM
+
+config TDM_DEBUG_CORE
+ bool "TDM Core debugging messages"
+ help
+ Say Y here if you want the TDM core to produce a bunch of debug
+ messages to the system log. Select this if you are having a
+ problem with TDM support and want to see more of what is going on.
+
+source drivers/tdm/test/Kconfig
+source drivers/tdm/device/Kconfig
+source drivers/tdm/line_ctrl/Kconfig
+endif # TDM
diff --git a/drivers/tdm/Makefile b/drivers/tdm/Makefile
new file mode 100644
index 0000000..2a2e0a5
--- /dev/null
+++ b/drivers/tdm/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the TDM core.
+#
+
+obj-$(CONFIG_TDM) += tdm-core.o device/ line_ctrl/ test/
+ifeq ($(CONFIG_TDM_DEBUG_CORE),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
diff --git a/drivers/tdm/device/Kconfig b/drivers/tdm/device/Kconfig
new file mode 100644
index 0000000..af6a710
--- /dev/null
+++ b/drivers/tdm/device/Kconfig
@@ -0,0 +1,22 @@
+#
+# TDM device configuration
+#
+
+menu "TDM Device support"
+
+config TDM_FSL
+ tristate "Driver for Freescale TDM controller"
+ depends on FSL_SOC
+ ---help---
+ This is a driver for Freescale TDM controller. The controller
+ is found in various Freescale SOCs viz MPC8315, P1020. The TDM driver
+ basically multiplexes and demultiplexes data from different channels.
+ The TDM can interface SLIC kind of devices.
+
+config FSL_UCC_TDM
+ tristate "UCC TDM driver for Freescale QE engine"
+ depends on FSL_SOC || CONFIG_QE
+ ---help---
+ This is a driver for Freescale QE UCC working with TDM interface.
+
+endmenu
diff --git a/drivers/tdm/device/Makefile b/drivers/tdm/device/Makefile
new file mode 100644
index 0000000..d41d10c
--- /dev/null
+++ b/drivers/tdm/device/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the TDM device drivers.
+#
+
+obj-$(CONFIG_TDM_FSL) += tdm_fsl.o
+obj-$(CONFIG_FSL_UCC_TDM) += fsl_ucc_tdm.o
+#ifeq ($(CONFIG_TDM_DEBUG_BUS),y)
+#EXTRA_CFLAGS += -DDEBUG
+#endif
diff --git a/drivers/tdm/device/fsl_ucc_tdm.c b/drivers/tdm/device/fsl_ucc_tdm.c
new file mode 100644
index 0000000..c9a3338
--- /dev/null
+++ b/drivers/tdm/device/fsl_ucc_tdm.c
@@ -0,0 +1,1211 @@
+/*
+ * Freescale QUICC Engine TDM Device Driver
+ *
+ * Copyright 2011-2012 Freescale Semiconductor, Inc.
+ *
+ * Author: Haiying Wang <Haiying.Wang@freescale.com>
+ * Kai Jiang <Kai.Jiang@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * This driver adds support for TDM devices via Freescale's QUICC Engine.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/tdm.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/dma-mapping.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_soc.h>
+#include <linux/slab.h>
+#include "fsl_ucc_tdm.h"
+
+#define DRV_DESC "Freescale QE UCC TDM Driver"
+#define DRV_NAME "ucc_tdm"
+
+#undef DEBUG
+
+static struct ucc_tdm_info utdm_primary_info = {
+ .uf_info = {
+ .tsa = 1,
+ .cdp = 1,
+ .cds = 1,
+ .ctsp = 1,
+ .ctss = 1,
+ .revd = 0,
+ .urfs = 256,
+ .utfs = 256,
+ .urfet = 128,
+ .urfset = 192,
+ .utfet = 128,
+ .utftt = 0x40,
+ .ufpt = 256,
+ .ttx_trx = UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_TRANSPARENT,
+ .tenc = UCC_FAST_TX_ENCODING_NRZ,
+ .renc = UCC_FAST_RX_ENCODING_NRZ,
+ .tcrc = UCC_FAST_16_BIT_CRC,
+ .synl = UCC_FAST_SYNC_LEN_NOT_USED,
+ },
+
+ .si_info = {
+ .simr_rfsd = 1, /* pq_mds_t1 card need 1 bit delay */
+ .simr_tfsd = 0,
+ .simr_crt = 0,
+ .simr_sl = 0,
+ .simr_ce = 1,
+ .simr_fe = 1,
+ .simr_gm = 0,
+ },
+};
+
+static struct ucc_tdm_info utdm_info[MAX_TDM_NUM];
+static int siram_init_flag;
+
+#ifdef DEBUG
+static void dump_siram(struct ucc_tdm_private *priv)
+{
+ int i;
+ u16 *siram = priv->siram;
+
+ dev_info(priv->dev, "Dump the SI RX RAM\n");
+ for (i = 0; i < priv->num_of_ts; i++) {
+ pr_info("%04x ", siram[priv->siram_entry_id * 32 + i]);
+ if ((i + 1) % 4)
+ pr_info("\n");
+ }
+
+ dev_info(priv->dev, "Dump the SI TX RAM\n");
+ for (i = 0; i < priv->num_of_ts; i++) {
+ pr_info("%04x ", siram[priv->siram_entry_id * 32 + 0x200 + i]);
+ if ((i + 1) % 4)
+ pr_info("\n");
+ }
+}
+
+static void mem_disp(u8 *addr, int size)
+{
+ void *i;
+ int size16_aling = (size >> 4) << 4;
+ int size4_aling = (size >> 2) << 2;
+ int not_align = 0;
+ if (size % 16)
+ not_align = 1;
+
+ for (i = addr; i < addr + size16_aling; i += 16) {
+ u32 *i32 = i;
+
+ pr_info("0x%08p: %08x %08x %08x %08x\r\n",
+ i32, i32[0], i32[1], i32[2], i32[3]);
+ }
+
+ if (not_align == 1)
+ pr_info("0x%08p: ", i);
+ for (; i < addr + size4_aling; i += 4)
+ pr_info("%08x ", *((u32 *) (i)));
+ for (; i < addr + size; i++)
+ pr_info("%02x", *((u8 *) (i)));
+ if (not_align == 1)
+ pr_info("\r\n");
+}
+
+static void dump_ucc(struct ucc_tdm_private *priv)
+{
+ struct ucc_transparent_param *ucc_pram;
+ ucc_pram = priv->ucc_pram;
+
+ dev_info(priv->dev, "DumpiniCC %d Registers\n",
+ priv->ut_info->uf_info.ucc_num);
+ ucc_fast_dump_regs(priv->uccf);
+ dev_info(priv->dev, "Dumping UCC %d Parameter RAM\n",
+ priv->ut_info->uf_info.ucc_num);
+ dev_info(priv->dev, "rbase = 0x%x\n", in_be32(&ucc_pram->rbase));
+ dev_info(priv->dev, "rbptr = 0x%x\n", in_be32(&ucc_pram->rbptr));
+ dev_info(priv->dev, "mrblr = 0x%x\n", in_be16(&ucc_pram->mrblr));
+ dev_info(priv->dev, "rbdlen = 0x%x\n", in_be16(&ucc_pram->rbdlen));
+ dev_info(priv->dev, "rbdstat = 0x%x\n", in_be16(&ucc_pram->rbdstat));
+ dev_info(priv->dev, "rstate = 0x%x\n", in_be32(&ucc_pram->rstate));
+ dev_info(priv->dev, "rdptr = 0x%x\n", in_be32(&ucc_pram->rdptr));
+ dev_info(priv->dev, "riptr = 0x%x\n", in_be16(&ucc_pram->riptr));
+ dev_info(priv->dev, "tbase = 0x%x\n", in_be32(&ucc_pram->tbase));
+ dev_info(priv->dev, "tbptr = 0x%x\n", in_be32(&ucc_pram->tbptr));
+ dev_info(priv->dev, "tbdlen = 0x%x\n", in_be16(&ucc_pram->tbdlen));
+ dev_info(priv->dev, "tbdstat = 0x%x\n", in_be16(&ucc_pram->tbdstat));
+ dev_info(priv->dev, "tstate = 0x%x\n", in_be32(&ucc_pram->tstate));
+ dev_info(priv->dev, "tdptr = 0x%x\n", in_be32(&ucc_pram->tdptr));
+ dev_info(priv->dev, "tiptr = 0x%x\n", in_be16(&ucc_pram->tiptr));
+ dev_info(priv->dev, "rcrc = 0x%x\n", in_be32(&ucc_pram->rcrc));
+ dev_info(priv->dev, "tcrc = 0x%x\n", in_be32(&ucc_pram->tcrc));
+ dev_info(priv->dev, "c_mask = 0x%x\n", in_be32(&ucc_pram->c_mask));
+ dev_info(priv->dev, "c_pers = 0x%x\n", in_be32(&ucc_pram->c_pres));
+ dev_info(priv->dev, "disfc = 0x%x\n", in_be16(&ucc_pram->disfc));
+ dev_info(priv->dev, "crcec = 0x%x\n", in_be16(&ucc_pram->crcec));
+}
+
+static void dump_bds(struct ucc_tdm_private *priv)
+{
+ int length;
+
+ if (priv->tx_bd) {
+ length = sizeof(struct qe_bd) * NUM_OF_BUF;
+ dev_info(priv->dev, " Dump tx BDs\n");
+ mem_disp((u8 *)priv->tx_bd, length);
+ }
+
+ if (priv->rx_bd) {
+ length = sizeof(struct qe_bd) * NUM_OF_BUF;
+ dev_info(priv->dev, " Dump rx BDs\n");
+ mem_disp((u8 *)priv->rx_bd, length);
+ }
+
+}
+
+static void dump_priv(struct ucc_tdm_private *priv)
+{
+ dev_info(priv->dev, "ut_info = 0x%x\n", (u32)priv->ut_info);
+ dev_info(priv->dev, "uccf = 0x%x\n", (u32)priv->uccf);
+ dev_info(priv->dev, "uf_regs = 0x%x\n", (u32)priv->uf_regs);
+ dev_info(priv->dev, "si_regs = 0x%x\n", (u32)priv->si_regs);
+ dev_info(priv->dev, "ucc_pram = 0x%x\n", (u32)priv->ucc_pram);
+ dev_info(priv->dev, "tdm_port = 0x%x\n", (u32)priv->tdm_port);
+ dev_info(priv->dev, "siram_entry_id = 0x%x\n", priv->siram_entry_id);
+ dev_info(priv->dev, "siram = 0x%x\n", (u32)priv->siram);
+ dev_info(priv->dev, "tdm_mode = 0x%x\n", (u32)priv->tdm_mode);
+ dev_info(priv->dev, "tdm_framer_type; = 0x%x\n",
+ (u32)priv->tdm_framer_type);
+ dev_info(priv->dev, "rx_buffer; = 0x%x\n", (u32)priv->rx_buffer);
+ dev_info(priv->dev, "tx_buffer; = 0x%x\n", (u32)priv->tx_buffer);
+ dev_info(priv->dev, "dma_rx_addr; = 0x%x\n", (u32)priv->dma_rx_addr);
+ dev_info(priv->dev, "dma_tx_addr; = 0x%x\n", (u32)priv->dma_tx_addr);
+ dev_info(priv->dev, "tx_bd; = 0x%x\n", (u32)priv->tx_bd);
+ dev_info(priv->dev, "rx_bd; = 0x%x\n", (u32)priv->rx_bd);
+ dev_info(priv->dev, "phase_rx = 0x%x\n", (u32)priv->phase_rx);
+ dev_info(priv->dev, "phase_tx = 0x%x\n", (u32)priv->phase_tx);
+ dev_info(priv->dev, "ucc_pram_offset = 0x%x\n", priv->ucc_pram_offset);
+ dev_info(priv->dev, "tx_bd_offset = 0x%x\n", priv->tx_bd_offset);
+ dev_info(priv->dev, "rx_bd_offset = 0x%x\n", priv->rx_bd_offset);
+
+}
+
+#endif /* DEBUG */
+
+static void init_si(struct ucc_tdm_private *priv)
+{
+ struct si1 __iomem *si_regs;
+ u16 __iomem *siram;
+ u16 siram_entry_valid;
+ u16 siram_entry_closed;
+ u16 ucc_num;
+ u8 csel;
+ u16 sixmr;
+ u16 tdm_port;
+ u32 siram_entry_id;
+ u32 mask;
+ int i;
+
+ si_regs = priv->si_regs;
+ siram = priv->siram;
+ ucc_num = priv->ut_info->uf_info.ucc_num;
+ tdm_port = priv->tdm_port;
+ siram_entry_id = priv->siram_entry_id;
+
+ /* set siram table */
+ csel = (ucc_num < 4) ? ucc_num + 9 : ucc_num - 3;
+
+ siram_entry_valid = SIR_CSEL(csel) | SIR_BYTE | SIR_CNT(0);
+ siram_entry_closed = SIR_IDLE | SIR_BYTE | SIR_CNT(0);
+
+ for (i = 0; i < priv->num_of_ts; i++) {
+ mask = 0x01 << i;
+
+ if (priv->tx_ts_mask & mask)
+ out_be16(&siram[siram_entry_id * 32 + i],
+ siram_entry_valid);
+ else
+ out_be16(&siram[siram_entry_id * 32 + i],
+ siram_entry_closed);
+
+ if (priv->rx_ts_mask & mask)
+ out_be16(&siram[siram_entry_id * 32 + 0x200 + i],
+ siram_entry_valid);
+ else
+ out_be16(&siram[siram_entry_id * 32 + 0x200 + i],
+ siram_entry_closed);
+ }
+
+ setbits16(&siram[(siram_entry_id * 32) + (priv->num_of_ts - 1)],
+ SIR_LAST);
+ setbits16(&siram[(siram_entry_id * 32) + 0x200 + (priv->num_of_ts - 1)],
+ SIR_LAST);
+
+ /* Set SIxMR register */
+ sixmr = SIMR_SAD(siram_entry_id);
+
+ sixmr &= ~SIMR_SDM_MASK;
+
+ if (priv->tdm_mode == TDM_INTERNAL_LOOPBACK)
+ sixmr |= SIMR_SDM_INTERNAL_LOOPBACK;
+ else
+ sixmr |= SIMR_SDM_NORMAL;
+
+ sixmr |= SIMR_RFSD(priv->ut_info->si_info.simr_rfsd) |
+ SIMR_TFSD(priv->ut_info->si_info.simr_tfsd);
+
+ if (priv->ut_info->si_info.simr_crt)
+ sixmr |= SIMR_CRT;
+ if (priv->ut_info->si_info.simr_sl)
+ sixmr |= SIMR_SL;
+ if (priv->ut_info->si_info.simr_ce)
+ sixmr |= SIMR_CE;
+ if (priv->ut_info->si_info.simr_fe)
+ sixmr |= SIMR_FE;
+ if (priv->ut_info->si_info.simr_gm)
+ sixmr |= SIMR_GM;
+
+ switch (tdm_port) {
+ case 0:
+ out_be16(&si_regs->sixmr1[0], sixmr);
+ break;
+ case 1:
+ out_be16(&si_regs->sixmr1[1], sixmr);
+ break;
+ case 2:
+ out_be16(&si_regs->sixmr1[2], sixmr);
+ break;
+ case 3:
+ out_be16(&si_regs->sixmr1[3], sixmr);
+ break;
+ default:
+ dev_err(priv->dev, "can not find tdm sixmr reg\n");
+ break;
+ }
+
+#ifdef DEBUG
+ dump_siram(priv);
+#endif
+
+}
+static int utdm_init(struct ucc_tdm_private *priv)
+{
+ struct ucc_tdm_info *ut_info;
+ struct ucc_fast_info *uf_info;
+ u32 cecr_subblock;
+ u32 bd_status;
+ int ret, i;
+ void *bd_buffer;
+ dma_addr_t bd_dma_addr;
+ u32 riptr;
+ u32 tiptr;
+
+ ut_info = priv->ut_info;
+ uf_info = &ut_info->uf_info;
+
+ if (priv->tdm_framer_type == TDM_FRAMER_T1)
+ priv->num_of_ts = 24;
+ if (priv->tdm_framer_type == TDM_FRAMER_E1)
+ priv->num_of_ts = 32;
+
+ uf_info->uccm_mask = (u32) (UCC_TRANS_UCCE_RXB << 16);
+
+ if (ucc_fast_init(uf_info, &priv->uccf)) {
+ dev_err(priv->dev, "Failed to init uccf.");
+ return -ENOMEM;
+ }
+
+ priv->uf_regs = priv->uccf->uf_regs;
+ ucc_fast_disable(priv->uccf, COMM_DIR_RX | COMM_DIR_TX);
+
+ /* Initialize SI */
+ init_si(priv);
+
+ /* Write to QE CECR, UCCx channel to Stop Transmission */
+ cecr_subblock = ucc_fast_get_qe_cr_subblock(uf_info->ucc_num);
+ ret = qe_issue_cmd(QE_STOP_TX, cecr_subblock,
+ (u8) QE_CR_PROTOCOL_UNSPECIFIED, 0);
+
+ /* Set UPSMR normal mode */
+ out_be32(&priv->uf_regs->upsmr, 0);
+
+ priv->tx_bd = dma_alloc_coherent(priv->dev,
+ NUM_OF_BUF * MAX_RX_BUF_LENGTH,
+ &priv->dma_tx_bd, GFP_KERNEL);
+
+ if (!priv->tx_bd) {
+ dev_err(priv->dev, "Could not allocate buffer descriptors\n");
+ ret = -ENOMEM;
+ goto rxbd_alloc_error;
+ }
+
+ priv->rx_bd = dma_alloc_coherent(priv->dev,
+ NUM_OF_BUF * MAX_RX_BUF_LENGTH,
+ &priv->dma_rx_bd, GFP_KERNEL);
+ if (!priv->rx_bd) {
+ dev_err(priv->dev, "Could not allocate buffer descriptors\n");
+ ret = -ENOMEM;
+ goto txbd_alloc_error;
+ }
+
+ /* Alloc parameter ram for ucc transparent */
+ priv->ucc_pram_offset = qe_muram_alloc(sizeof(*priv->ucc_pram),
+ ALIGNMENT_OF_UCC_TRANS_PRAM);
+
+ if (IS_ERR_VALUE(priv->ucc_pram_offset)) {
+ dev_err(priv->dev, "Can not allocate MURAM for hdlc prameter.\n");
+ ret = -ENOMEM;
+ goto pram_alloc_error;
+ }
+
+ /* init parameter base */
+ cecr_subblock = ucc_fast_get_qe_cr_subblock(uf_info->ucc_num);
+ ret = qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, cecr_subblock,
+ QE_CR_PROTOCOL_UNSPECIFIED, priv->ucc_pram_offset);
+
+ priv->ucc_pram = (struct ucc_transparent_param __iomem *)
+ qe_muram_addr(priv->ucc_pram_offset);
+
+ /* Zero out parameter ram */
+ memset_io(priv->ucc_pram, 0, sizeof(struct ucc_transparent_param));
+
+ /* Alloc riptr, tiptr */
+ riptr = qe_muram_alloc(32, 32);
+ if (IS_ERR_VALUE(riptr)) {
+ dev_err(priv->dev, "Cannot allocate MURAM mem for Receive"
+ " internal temp data pointer\n");
+ ret = -ENOMEM;
+ goto riptr_alloc_error;
+ }
+
+ tiptr = qe_muram_alloc(32, 32);
+ if (IS_ERR_VALUE(tiptr)) {
+ dev_err(priv->dev, "Cannot allocate MURAM mem for transmit"
+ " internal temp data pointer\n");
+ ret = -ENOMEM;
+ goto tiptr_alloc_error;
+ }
+
+ /* Set RIPTR, TIPTR */
+ out_be16(&priv->ucc_pram->riptr, (u16)riptr);
+ out_be16(&priv->ucc_pram->tiptr, (u16)tiptr);
+
+ /* Set MRBLR */
+ out_be16(&priv->ucc_pram->mrblr, (u16)MAX_RX_BUF_LENGTH);
+
+ /* Set RBASE, TBASE */
+ out_be32(&priv->ucc_pram->rbase, (u32)priv->dma_rx_bd);
+ out_be32(&priv->ucc_pram->tbase, (u32)priv->dma_tx_bd);
+
+ /* Set RSTATE, TSTATE */
+ out_be32(&priv->ucc_pram->rstate, 0x30000000);
+ out_be32(&priv->ucc_pram->tstate, 0x30000000);
+
+ /* Set C_MASK, C_PRES for 16bit CRC */
+ out_be32(&priv->ucc_pram->c_mask, 0x0000F0B8);
+ out_be32(&priv->ucc_pram->c_pres, 0x0000FFFF);
+
+ out_be16(&priv->ucc_pram->res0, 0);
+ for (i = 0; i < 4; i++)
+ out_be32(&priv->ucc_pram->res4[i], 0x0);
+
+ /* Get BD buffer */
+ bd_buffer = dma_alloc_coherent(priv->dev,
+ 2 * NUM_OF_BUF * MAX_RX_BUF_LENGTH,
+ &bd_dma_addr, GFP_KERNEL);
+
+ if (!bd_buffer) {
+ dev_err(priv->dev, "Could not allocate buffer descriptors\n");
+ return -ENOMEM;
+ }
+
+ memset(bd_buffer, 0, 2 * NUM_OF_BUF * MAX_RX_BUF_LENGTH);
+
+ priv->rx_buffer = bd_buffer;
+ priv->tx_buffer = bd_buffer + NUM_OF_BUF * MAX_RX_BUF_LENGTH;
+
+ priv->dma_rx_addr = bd_dma_addr;
+ priv->dma_tx_addr = bd_dma_addr + NUM_OF_BUF * MAX_RX_BUF_LENGTH;
+
+ for (i = 0; i < NUM_OF_BUF; i++) {
+ if (i < (NUM_OF_BUF - 1))
+ bd_status = R_E | R_I | R_CM;
+ else
+ bd_status = R_E | R_I | R_W | R_CM;
+
+ out_be32((u32 *)(priv->rx_bd + i), bd_status);
+ out_be32(&priv->rx_bd[i].buf, priv->dma_rx_addr
+ + i * MAX_RX_BUF_LENGTH);
+
+ if (i < (NUM_OF_BUF - 1))
+ bd_status = T_I;
+ else
+ bd_status = T_I | T_W;
+
+ out_be32((u32 *)(priv->tx_bd + i), bd_status);
+ out_be32(&priv->tx_bd[i].buf, priv->dma_tx_addr
+ + i * MAX_RX_BUF_LENGTH);
+ }
+
+ priv->phase_rx = 0;
+ priv->phase_tx = 0;
+
+ return 0;
+
+tiptr_alloc_error:
+ qe_muram_free(riptr);
+riptr_alloc_error:
+ qe_muram_free(priv->ucc_pram_offset);
+pram_alloc_error:
+ dma_free_coherent(priv->dev,
+ NUM_OF_BUF * MAX_RX_BUF_LENGTH,
+ priv->rx_bd, priv->dma_rx_bd);
+txbd_alloc_error:
+ dma_free_coherent(priv->dev,
+ NUM_OF_BUF * MAX_RX_BUF_LENGTH,
+ priv->tx_bd, priv->dma_tx_bd);
+rxbd_alloc_error:
+ ucc_fast_free(priv->uccf);
+
+ return ret;
+}
+
+static int ucc_tdm_read(struct tdm_adapter *adap, u8 *tdm_buffer, u32 len)
+{
+
+ struct ucc_tdm_private *priv = tdm_get_adapdata(adap);
+ u8 phase_rx;
+ u32 byte_copy;
+ u8 *recv_buf;
+
+ wait_event_interruptible(priv->tdm_queue,
+ priv->tdm_queue_flag != false);
+ priv->tdm_queue_flag = false;
+
+ if (priv->phase_rx == 0)
+ phase_rx = NUM_OF_BUF - 1;
+ else
+ phase_rx = priv->phase_rx - 1;
+
+ recv_buf = priv->rx_buffer + phase_rx * MAX_RX_BUF_LENGTH;
+
+ if (len > MAX_RX_BUF_LENGTH)
+ byte_copy = MAX_RX_BUF_LENGTH;
+ else
+ byte_copy = len;
+
+ memcpy(tdm_buffer, recv_buf, byte_copy);
+
+ return byte_copy;
+
+}
+
+
+static int ucc_tdm_write(struct tdm_adapter *adap, u8 *write_buf,
+ unsigned int len)
+{
+ struct ucc_tdm_private *priv = tdm_get_adapdata(adap);
+ struct qe_bd __iomem *bd;
+ u32 bd_stat_len;
+ u8 *tdm_send_buf;
+ u32 copy_len;
+ int i, ret;
+ u32 buf_num;
+
+ buf_num = len / MAX_RX_BUF_LENGTH;
+ if (len % MAX_RX_BUF_LENGTH)
+ buf_num += 1;
+
+ if (buf_num > NUM_OF_BUF)
+ return -EINVAL;
+
+ for (i = 0; i < buf_num; i++) {
+
+ if (priv->phase_tx == NUM_OF_BUF)
+ priv->phase_tx = 0;
+
+ bd = (priv->tx_bd + priv->phase_tx);
+ bd_stat_len = in_be32((u32 __iomem *)bd);
+ tdm_send_buf = priv->tx_buffer +
+ priv->phase_tx * MAX_RX_BUF_LENGTH;
+
+ /* the last buf to copy */
+ if (i == (buf_num - 1))
+ copy_len = len - i * MAX_RX_BUF_LENGTH;
+ else
+ copy_len = MAX_RX_BUF_LENGTH;
+
+ ret = spin_event_timeout(((bd_stat_len =
+ in_be32((u32 __iomem *)bd)) & T_R) != T_R ,
+ 1000000, 500);
+ if (!ret) {
+ dev_err(priv->dev, "TDM write data error!\n");
+ return -EFAULT;
+ }
+
+ memset(tdm_send_buf, 0xff, MAX_RX_BUF_LENGTH);
+
+ memcpy(tdm_send_buf, write_buf, copy_len);
+
+ bd_stat_len &= ~(T_L | BD_LEN_MASK);
+ if (i == (buf_num - 1))
+ out_be32((u32 __iomem *)(bd),
+ bd_stat_len | T_R | T_L | T_I | copy_len);
+ else
+ out_be32((u32 __iomem *)(bd),
+ bd_stat_len | T_R | T_I | copy_len);
+
+ priv->phase_tx++;
+ }
+
+ return 0;
+}
+
+static irqreturn_t ucc_tdm_irq_handler(int irq, void *dev_id)
+{
+ struct ucc_tdm_private *priv = (struct ucc_tdm_private *)dev_id;
+ struct ucc_fast_private *uccf;
+ struct ucc_tdm_info *ut_info;
+ u32 ucce;
+ u32 uccm;
+
+ ut_info = priv->ut_info;
+ uccf = priv->uccf;
+
+ ucce = in_be32(uccf->p_ucce);
+ uccm = in_be32(uccf->p_uccm);
+
+ if ((ucce >> 16) & UCC_TRANS_UCCE_RXB) {
+ if (priv->phase_rx == NUM_OF_BUF - 1)
+ priv->phase_rx = 0;
+ else
+ priv->phase_rx++;
+
+ priv->tdm_queue_flag = true;
+ wake_up_interruptible(&priv->tdm_queue);
+
+ }
+
+ out_be32(uccf->p_ucce, ucce);
+
+ return IRQ_HANDLED;
+
+}
+
+static int utdm_start(struct tdm_adapter *adap)
+{
+ u32 cecr_subblock;
+ struct ucc_tdm_private *priv = tdm_get_adapdata(adap);
+
+ if (priv->tdm_busy != 1) {
+ if (request_irq(priv->ut_info->uf_info.irq, ucc_tdm_irq_handler,
+ 0, "tdm", (void *)priv)) {
+ dev_err(priv->dev, "request_irq for ucc tdm failed\n");
+ return -ENODEV;
+ }
+ cecr_subblock = ucc_fast_get_qe_cr_subblock(
+ priv->ut_info->uf_info.ucc_num);
+
+ qe_issue_cmd(QE_INIT_TX_RX, cecr_subblock,
+ (u8) QE_CR_PROTOCOL_UNSPECIFIED, 0);
+
+ ucc_fast_enable(priv->uccf, COMM_DIR_RX | COMM_DIR_TX);
+
+ /* Enable the TDM port */
+ priv->si_regs->siglmr1_h |= (0x1 << priv->tdm_port);
+ priv->phase_rx = 0;
+ priv->phase_tx = 0;
+ priv->tdm_busy = 1;
+ } else
+ dev_err(priv->dev, "TDM IS RUNNING!\n");
+
+#ifdef DEBUG
+ dump_priv(priv);
+ dump_ucc(priv);
+ dump_bds(priv);
+#endif
+
+ return 0;
+}
+
+static void utdm_memclean(struct ucc_tdm_private *priv)
+{
+ qe_muram_free(priv->ucc_pram->riptr);
+ qe_muram_free(priv->ucc_pram->tiptr);
+
+ if (priv->rx_bd) {
+ dma_free_coherent(priv->dev,
+ NUM_OF_BUF * MAX_RX_BUF_LENGTH,
+ priv->rx_bd, priv->dma_rx_bd);
+ priv->rx_bd = NULL;
+ priv->dma_rx_bd = 0;
+ }
+
+ if (priv->tx_bd) {
+ dma_free_coherent(priv->dev,
+ NUM_OF_BUF * MAX_RX_BUF_LENGTH,
+ priv->tx_bd, priv->dma_tx_bd);
+ priv->tx_bd = NULL;
+ priv->dma_tx_bd = 0;
+ }
+
+ if (priv->ucc_pram) {
+ qe_muram_free(priv->ucc_pram_offset);
+ priv->ucc_pram = NULL;
+ priv->ucc_pram_offset = 0;
+ }
+
+ if (priv->uf_regs) {
+ iounmap(priv->uf_regs);
+ priv->uf_regs = NULL;
+ }
+
+ if (priv->uccf) {
+ ucc_fast_free(priv->uccf);
+ priv->uccf = NULL;
+ }
+
+ if (priv->rx_buffer) {
+ dma_free_coherent(priv->dev,
+ 2 * NUM_OF_BUF * MAX_RX_BUF_LENGTH,
+ priv->rx_buffer, priv->dma_rx_addr);
+ priv->rx_buffer = NULL;
+ priv->dma_rx_addr = 0;
+ }
+}
+
+static int utdm_stop(struct tdm_adapter *adap)
+{
+ struct ucc_tdm_private *priv = tdm_get_adapdata(adap);
+ u32 cecr_subblock;
+
+ cecr_subblock = ucc_fast_get_qe_cr_subblock(
+ priv->ut_info->uf_info.ucc_num);
+
+ qe_issue_cmd(QE_GRACEFUL_STOP_TX, cecr_subblock,
+ (u8) QE_CR_PROTOCOL_UNSPECIFIED, 0);
+ qe_issue_cmd(QE_CLOSE_RX_BD, cecr_subblock,
+ (u8) QE_CR_PROTOCOL_UNSPECIFIED, 0);
+
+ priv->si_regs->siglmr1_h &= ~(0x1 << priv->tdm_port);
+ ucc_fast_disable(priv->uccf, COMM_DIR_RX | COMM_DIR_TX);
+
+ free_irq(priv->ut_info->uf_info.irq, priv);
+ priv->tdm_busy = 0;
+
+ return 0;
+}
+
+static const struct tdm_adapt_algorithm tdm_algo = {
+ .tdm_read_simple = ucc_tdm_read,
+ .tdm_write_simple = ucc_tdm_write,
+ .tdm_enable = utdm_start,
+ .tdm_disable = utdm_stop,
+};
+
+static struct tdm_adapter ucc_tdm_ops = {
+ .owner = THIS_MODULE,
+ .algo = &tdm_algo,
+};
+
+static enum tdm_mode_t set_tdm_mode(const char *tdm_mode_type)
+{
+ if (strcasecmp(tdm_mode_type, "internal-loopback") == 0)
+ return TDM_INTERNAL_LOOPBACK;
+ else
+ return TDM_NORMAL;
+}
+
+
+static enum tdm_framer_t set_tdm_framer(const char *tdm_framer_type)
+{
+ if (strcasecmp(tdm_framer_type, "e1") == 0)
+ return TDM_FRAMER_E1;
+ else
+ return TDM_FRAMER_T1;
+}
+
+static void set_si_param(struct ucc_tdm_private *priv)
+{
+ struct si_mode_info *si_info = &priv->ut_info->si_info;
+
+ if (priv->tdm_mode == TDM_INTERNAL_LOOPBACK) {
+ si_info->simr_crt = 1;
+ si_info->simr_rfsd = 0;
+ }
+}
+
+static int ucc_tdm_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct ucc_tdm_private *utdm_priv = NULL;
+ struct ucc_tdm_info *ut_info;
+ struct resource res;
+ int ucc_num;
+ const unsigned int *prop;
+ const char *sprop;
+ struct device_node *np2;
+ int ret;
+
+ prop = of_get_property(np, "cell-index", NULL);
+ if (!prop) {
+ dev_err(&pdev->dev, "Invalid ucc property\n");
+ return -ENODEV;
+ }
+
+ ucc_num = *prop - 1;
+ if ((ucc_num > 7) || (ucc_num < 0)) {
+ dev_err(&pdev->dev, ": Invalid UCC num\n");
+ return -EINVAL;
+ }
+
+ memcpy(&(utdm_info[ucc_num]), &utdm_primary_info,
+ sizeof(utdm_primary_info));
+
+ ut_info = &utdm_info[ucc_num];
+ ut_info->uf_info.ucc_num = ucc_num;
+
+ sprop = of_get_property(np, "rx-clock-name", NULL);
+ if (sprop) {
+ ut_info->uf_info.rx_clock = qe_clock_source(sprop);
+ if ((ut_info->uf_info.rx_clock < QE_CLK_NONE) ||
+ (ut_info->uf_info.rx_clock > QE_CLK24)) {
+ dev_err(&pdev->dev, "Invalid rx-clock-name property\n");
+ return -EINVAL;
+ }
+ } else {
+ dev_err(&pdev->dev, "Invalid rx-clock-name property\n");
+ return -EINVAL;
+ }
+
+ sprop = of_get_property(np, "tx-clock-name", NULL);
+ if (sprop) {
+ ut_info->uf_info.tx_clock = qe_clock_source(sprop);
+ if ((ut_info->uf_info.tx_clock < QE_CLK_NONE) ||
+ (ut_info->uf_info.tx_clock > QE_CLK24)) {
+ dev_err(&pdev->dev, "Invalid tx-clock-name property\n");
+ return -EINVAL;
+ }
+ } else {
+ dev_err(&pdev->dev, "Invalid tx-clock-name property\n");
+ return -EINVAL;
+ }
+
+ /* use the same clock when work in loopback */
+ if (ut_info->uf_info.rx_clock == ut_info->uf_info.tx_clock)
+ qe_setbrg(ut_info->uf_info.rx_clock, 2000000, 1);
+
+ sprop = of_get_property(np, "fsl,rx-sync-clock", NULL);
+ if (sprop) {
+ ut_info->uf_info.rx_sync = qe_clock_source(sprop);
+ if ((ut_info->uf_info.rx_sync < QE_CLK_NONE) ||
+ (ut_info->uf_info.rx_sync > QE_RSYNC_PIN)) {
+ dev_err(&pdev->dev, "Invalid rx-sync-clock property\n");
+ return -EINVAL;
+ }
+ } else {
+ dev_err(&pdev->dev, "Invalid rx-sync-clock property\n");
+ return -EINVAL;
+ }
+
+ sprop = of_get_property(np, "fsl,tx-sync-clock", NULL);
+ if (sprop) {
+ ut_info->uf_info.tx_sync = qe_clock_source(sprop);
+ if ((ut_info->uf_info.tx_sync < QE_CLK_NONE) ||
+ (ut_info->uf_info.tx_sync > QE_TSYNC_PIN)) {
+ dev_err(&pdev->dev, "Invalid tx-sync-clock property\n");
+ return -EINVAL;
+ }
+ } else {
+ dev_err(&pdev->dev, "Invalid tx-sync-clock property\n");
+ return -EINVAL;
+ }
+
+ ret = of_address_to_resource(np, 0, &res);
+ if (ret)
+ return -EINVAL;
+
+ ut_info->uf_info.regs = res.start;
+ ut_info->uf_info.irq = irq_of_parse_and_map(np, 0);
+
+ utdm_priv = kzalloc(sizeof(struct ucc_tdm_private), GFP_KERNEL);
+ if (!utdm_priv) {
+ ret = -ENOMEM;
+ dev_err(&pdev->dev, "No mem to alloc tdm private data\n");
+ goto err_alloc_priv;
+ }
+
+ dev_set_drvdata(&pdev->dev, utdm_priv);
+ utdm_priv->dev = &pdev->dev;
+
+ prop = of_get_property(np, "fsl,tx-timeslot", NULL);
+ if (!prop) {
+ ret = -EINVAL;
+ dev_err(&pdev->dev, "Invalid tx-timeslot property\n");
+ goto err_miss_property;
+ }
+ utdm_priv->tx_ts_mask = *prop;
+
+ prop = of_get_property(np, "fsl,rx-timeslot", NULL);
+ if (!prop) {
+ ret = -EINVAL;
+ dev_err(&pdev->dev, "Invalid rx-timeslot property\n");
+ goto err_miss_property;
+ }
+ utdm_priv->rx_ts_mask = *prop;
+
+ prop = of_get_property(np, "fsl,tdm-id", NULL);
+ if (!prop) {
+ ret = -EINVAL;
+ dev_err(&pdev->dev, "No fsl,tdm-id property for this UCC\n");
+ goto err_miss_property;
+ }
+ utdm_priv->tdm_port = *prop;
+ ut_info->uf_info.tdm_num = utdm_priv->tdm_port ;
+
+ prop = of_get_property(np, "fsl,tdm-mode", NULL);
+ if (!prop) {
+ ret = -EINVAL;
+ dev_err(&pdev->dev, "No tdm-mode property for UCC\n");
+ goto err_miss_property;
+ }
+ utdm_priv->tdm_mode = set_tdm_mode((const char *)prop);
+
+ prop = of_get_property(np, "fsl,tdm-framer-type", NULL);
+ if (!prop) {
+ ret = -EINVAL;
+ dev_err(&pdev->dev, "No tdm-framer-type property for UCC\n");
+ goto err_miss_property;
+ }
+ utdm_priv->tdm_framer_type = set_tdm_framer((const char *)prop);
+
+ prop = of_get_property(np, "fsl,siram-entry-id", NULL);
+ if (!prop) {
+ ret = -EINVAL;
+ dev_err(&pdev->dev, "No siram entry id for UCC\n");
+ goto err_miss_property;
+ }
+ utdm_priv->siram_entry_id = *(const u32 *)prop;
+
+ np2 = of_find_node_by_name(NULL, "si");
+ if (!np2) {
+ dev_err(&pdev->dev, "No si property\n");
+ goto err_miss_property;
+ }
+ of_address_to_resource(np2, 0, &res);
+ utdm_priv->si_regs = ioremap(res.start, res.end - res.start + 1);
+ of_node_put(np2);
+
+
+ np2 = of_find_node_by_name(NULL, "siram");
+ if (!np2) {
+ ret = -EINVAL;
+ dev_err(&pdev->dev, "No siramproperty\n");
+ goto err_miss_si_property;
+ }
+ of_address_to_resource(np2, 0 , &res);
+ utdm_priv->siram = ioremap(res.start, res.end - res.start + 1);
+ of_node_put(np2);
+
+ if (siram_init_flag == 0) {
+ memset(utdm_priv->siram, 0, res.end - res.start + 1);
+ siram_init_flag = 1;
+ }
+
+ utdm_priv->ut_info = ut_info;
+ set_si_param(utdm_priv);
+
+ sprintf(ucc_tdm_ops.name, "%s%d", "tdm_ucc_", ucc_num + 1);
+ memcpy(&utdm_priv->adap, &ucc_tdm_ops, sizeof(struct tdm_adapter));
+
+ tdm_set_adapdata(&utdm_priv->adap, utdm_priv);
+ utdm_priv->adap.parent = &pdev->dev;
+
+ init_waitqueue_head(&utdm_priv->tdm_queue);
+ utdm_priv->tdm_queue_flag = false;
+
+ ret = utdm_init(utdm_priv);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to init utdm\n");
+ goto err_utdm_init;
+ }
+
+ ret = tdm_add_adapter(&utdm_priv->adap);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to add adapter\n");
+ goto err_utdm_init;
+ }
+
+ spin_lock_init(&utdm_priv->tdmlock);
+
+#ifdef DEBUG
+ dump_priv(utdm_priv);
+ dump_ucc(utdm_priv);
+ dump_bds(utdm_priv);
+ mem_disp((u8 *)utdm_priv->si_regs, 0x20);
+#endif
+
+ return 0;
+
+err_utdm_init:
+ iounmap(utdm_priv->siram);
+err_miss_si_property:
+ iounmap(utdm_priv->si_regs);
+err_miss_property:
+ kfree(utdm_priv);
+err_alloc_priv:
+ return ret;
+
+}
+
+static int ucc_tdm_remove(struct platform_device *pdev)
+{
+ struct ucc_tdm_private *priv = dev_get_drvdata(&pdev->dev);
+
+ utdm_stop(&priv->adap);
+ utdm_memclean(priv);
+
+ if (priv->si_regs) {
+ iounmap(priv->si_regs);
+ priv->si_regs = NULL;
+ }
+
+ if (priv->siram) {
+ iounmap(priv->siram);
+ priv->siram = NULL;
+ }
+ kfree(priv);
+
+ dev_info(&pdev->dev, "UCC based tdm module removed\n");
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static void store_clk_config(struct ucc_tdm_private *utdm_priv)
+{
+ struct qe_mux *qe_mux_reg = &qe_immr->qmx;
+
+ /* store si clk */
+ utdm_priv->cmxsi1cr_h = in_be32(&qe_mux_reg->cmxsi1cr_h);
+ utdm_priv->cmxsi1cr_l = in_be32(&qe_mux_reg->cmxsi1cr_l);
+
+ /* store si sync */
+ utdm_priv->cmxsi1syr = in_be32(&qe_mux_reg->cmxsi1syr);
+
+ /* store ucc clk */
+ memcpy_fromio(utdm_priv->cmxucr, qe_mux_reg->cmxucr, 4 * sizeof(u32));
+}
+
+static void resume_clk_config(struct ucc_tdm_private *utdm_priv)
+{
+ struct qe_mux *qe_mux_reg = &qe_immr->qmx;
+
+ memcpy_toio(qe_mux_reg->cmxucr, utdm_priv->cmxucr, 4 * sizeof(u32));
+
+ out_be32(&qe_mux_reg->cmxsi1cr_h, utdm_priv->cmxsi1cr_h);
+ out_be32(&qe_mux_reg->cmxsi1cr_l, utdm_priv->cmxsi1cr_l);
+
+ out_be32(&qe_mux_reg->cmxsi1syr, utdm_priv->cmxsi1syr);
+
+}
+
+static int ucc_tdm_suspend(struct device *dev)
+{
+ struct ucc_tdm_private *utdm_priv = dev_get_drvdata(dev);
+ struct ucc_tdm_info *ut_info;
+ struct ucc_fast __iomem *uf_regs;
+
+ if (!utdm_priv)
+ return -EINVAL;
+
+ ut_info = utdm_priv->ut_info;
+ uf_regs = utdm_priv->uf_regs;
+
+ /* backup gumr guemr*/
+ utdm_priv->gumr = in_be32(&uf_regs->gumr);
+ utdm_priv->guemr = in_8(&uf_regs->guemr);
+
+ utdm_priv->ucc_pram_bak = kmalloc(sizeof(struct ucc_transparent_param),
+ GFP_KERNEL);
+ if (!utdm_priv->ucc_pram_bak)
+ return -ENOMEM;
+
+ /* backup transparent parameter */
+ memcpy_fromio(utdm_priv->ucc_pram_bak, utdm_priv->ucc_pram,
+ sizeof(struct ucc_transparent_param));
+
+ /* store the clk configuration */
+ store_clk_config(utdm_priv);
+
+ /* save power */
+ ucc_fast_disable(utdm_priv->uccf, COMM_DIR_RX | COMM_DIR_TX);
+
+ dev_dbg(dev, "ucc tdm suspend\n");
+
+ return 0;
+}
+
+static int ucc_tdm_resume(struct device *dev)
+{
+ struct ucc_tdm_private *utdm_priv = dev_get_drvdata(dev);
+ struct ucc_tdm_info *ut_info;
+ struct ucc_fast __iomem *uf_regs;
+ struct ucc_fast_private *uccf;
+ struct ucc_fast_info *uf_info;
+ int ret, i;
+ u32 cecr_subblock, bd_status;
+
+ if (!utdm_priv)
+ return -EINVAL;
+
+ ut_info = utdm_priv->ut_info;
+ uf_info = &ut_info->uf_info;
+ uf_regs = utdm_priv->uf_regs;
+ uccf = utdm_priv->uccf;
+
+ /* restore gumr guemr */
+ out_8(&uf_regs->guemr, utdm_priv->guemr);
+ out_be32(&uf_regs->gumr, utdm_priv->gumr);
+
+ /* Set Virtual Fifo registers */
+ out_be16(&uf_regs->urfs, uf_info->urfs);
+ out_be16(&uf_regs->urfet, uf_info->urfet);
+ out_be16(&uf_regs->urfset, uf_info->urfset);
+ out_be16(&uf_regs->utfs, uf_info->utfs);
+ out_be16(&uf_regs->utfet, uf_info->utfet);
+ out_be16(&uf_regs->utftt, uf_info->utftt);
+ /* utfb, urfb are offsets from MURAM base */
+ out_be32(&uf_regs->utfb, uccf->ucc_fast_tx_virtual_fifo_base_offset);
+ out_be32(&uf_regs->urfb, uccf->ucc_fast_rx_virtual_fifo_base_offset);
+
+ /* tdm Rx Tx and sync clock routing */
+ resume_clk_config(utdm_priv);
+
+ out_be32(&uf_regs->uccm, uf_info->uccm_mask);
+ out_be32(&uf_regs->ucce, 0xffffffff);
+
+ ucc_fast_disable(utdm_priv->uccf, COMM_DIR_RX | COMM_DIR_TX);
+
+ /* rebuild SIRAM */
+ init_si(utdm_priv);
+
+ /* Write to QE CECR, UCCx channel to Stop Transmission */
+ cecr_subblock = ucc_fast_get_qe_cr_subblock(uf_info->ucc_num);
+ ret = qe_issue_cmd(QE_STOP_TX, cecr_subblock,
+ (u8)QE_CR_PROTOCOL_UNSPECIFIED, 0);
+
+ /* Set UPSMR normal mode */
+ out_be32(&uf_regs->upsmr, 0);
+
+ /* init parameter base */
+ cecr_subblock = ucc_fast_get_qe_cr_subblock(uf_info->ucc_num);
+ ret = qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, cecr_subblock,
+ QE_CR_PROTOCOL_UNSPECIFIED, utdm_priv->ucc_pram_offset);
+
+ utdm_priv->ucc_pram = (struct ucc_transparent_param __iomem *)
+ qe_muram_addr(utdm_priv->ucc_pram_offset);
+
+ /* restore ucc parameter */
+ memcpy_toio(utdm_priv->ucc_pram, utdm_priv->ucc_pram_bak,
+ sizeof(struct ucc_transparent_param));
+ kfree(utdm_priv->ucc_pram_bak);
+
+ /* rebuild BD entry */
+ for (i = 0; i < NUM_OF_BUF; i++) {
+ if (i < (NUM_OF_BUF - 1))
+ bd_status = R_E | R_I | R_CM;
+ else
+ bd_status = R_E | R_I | R_W | R_CM;
+
+ out_be32((u32 *)(utdm_priv->rx_bd + i), bd_status);
+ out_be32(&utdm_priv->rx_bd[i].buf, utdm_priv->dma_rx_addr
+ + i * MAX_RX_BUF_LENGTH);
+
+ if (i < (NUM_OF_BUF - 1))
+ bd_status = T_I;
+ else
+ bd_status = T_I | T_W;
+
+ out_be32((u32 *)(utdm_priv->tx_bd + i), bd_status);
+ out_be32(&utdm_priv->tx_bd[i].buf, utdm_priv->dma_tx_addr
+ + i * MAX_RX_BUF_LENGTH);
+ }
+
+ /* if tdm is busy enable TX and RX */
+ if (utdm_priv->tdm_busy == 1) {
+ cecr_subblock = ucc_fast_get_qe_cr_subblock(
+ utdm_priv->ut_info->uf_info.ucc_num);
+
+ qe_issue_cmd(QE_INIT_TX_RX, cecr_subblock,
+ (u8)QE_CR_PROTOCOL_UNSPECIFIED, 0);
+
+ ucc_fast_enable(utdm_priv->uccf, COMM_DIR_RX | COMM_DIR_TX);
+
+ /* Enable the TDM port */
+ utdm_priv->si_regs->siglmr1_h |= (0x1 << utdm_priv->tdm_port);
+ }
+
+ return 0;
+}
+
+SIMPLE_DEV_PM_OPS(ucc_tdm_pm_ops, ucc_tdm_suspend, ucc_tdm_resume);
+#endif
+
+static const struct of_device_id fsl_ucc_tdm_of_match[] = {
+ {
+ .compatible = "fsl,ucc-tdm",
+ },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, fsl_ucc_tdm_of_match);
+
+static struct platform_driver ucc_tdm_driver = {
+ .probe = ucc_tdm_probe,
+ .remove = ucc_tdm_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRV_NAME,
+ .of_match_table = fsl_ucc_tdm_of_match,
+#ifdef CONFIG_PM
+ .pm = &ucc_tdm_pm_ops,
+#endif
+ },
+};
+
+static int __init ucc_tdm_init(void)
+{
+ return platform_driver_register(&ucc_tdm_driver);
+}
+
+static void __exit ucc_tdm_exit(void)
+{
+ platform_driver_unregister(&ucc_tdm_driver);
+}
+
+module_init(ucc_tdm_init);
+module_exit(ucc_tdm_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Freescale Semiconductor Inc.");
+MODULE_DESCRIPTION("Driver For Freescale QE UCC TDM controller");
+MODULE_VERSION("1.0");
diff --git a/drivers/tdm/device/fsl_ucc_tdm.h b/drivers/tdm/device/fsl_ucc_tdm.h
new file mode 100644
index 0000000..1a1b161
--- /dev/null
+++ b/drivers/tdm/device/fsl_ucc_tdm.h
@@ -0,0 +1,173 @@
+/*
+ * Freescale QUICC Engine TDM Device Driver
+ *
+ * Copyright 2011-2012 Freescale Semiconductor, Inc.
+ *
+ * Author: Haiying Wang <Haiying.Wang@freescale.com>
+ * Kai Jiang <Kai.Jiang@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * This driver adds support for TDM devices via Freescale's QUICC Engine.
+ */
+
+
+#ifndef CONFIG_UCC_TDM_H
+#define CONFIG_UCC_TDM_H
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+
+#include <asm/immap_qe.h>
+#include <asm/qe.h>
+
+#include <asm/ucc.h>
+#include <asm/ucc_fast.h>
+
+/* SI RAM entries */
+#define SIR_LAST 0x0001
+#define SIR_BYTE 0x0002
+#define SIR_CNT(x) ((x) << 2)
+#define SIR_CSEL(x) ((x) << 5)
+#define SIR_SGS 0x0200
+#define SIR_SWTR 0x4000
+#define SIR_MCC 0x8000
+#define SIR_IDLE 0
+
+/* SIxMR fields */
+#define SIMR_SAD(x) ((x) << 12)
+#define SIMR_SDM_NORMAL 0x0000
+#define SIMR_SDM_INTERNAL_LOOPBACK 0x0800
+#define SIMR_SDM_MASK 0x0c00
+#define SIMR_CRT 0x0040
+#define SIMR_SL 0x0020
+#define SIMR_CE 0x0010
+#define SIMR_FE 0x0008
+#define SIMR_GM 0x0004
+#define SIMR_TFSD(n) (n)
+#define SIMR_RFSD(n) ((n) << 8)
+
+enum tdm_ts_t {
+ TDM_TX_TS,
+ TDM_RX_TS
+};
+
+
+enum tdm_framer_t {
+ TDM_FRAMER_T1,
+ TDM_FRAMER_E1
+};
+
+enum tdm_mode_t {
+ TDM_INTERNAL_LOOPBACK,
+ TDM_NORMAL
+};
+
+struct ucc_transparent_param {
+ __be16 riptr;
+ __be16 tiptr;
+ __be16 res0;
+ __be16 mrblr;
+ __be32 rstate;
+ __be32 rbase;
+ __be16 rbdstat;
+ __be16 rbdlen;
+ __be32 rdptr;
+ __be32 tstate;
+ __be32 tbase;
+ __be16 tbdstat;
+ __be16 tbdlen;
+ __be32 tdptr;
+ __be32 rbptr;
+ __be32 tbptr;
+ __be32 rcrc;
+ __be32 res1;
+ __be32 tcrc;
+ __be32 res2;
+ __be32 res3;
+ __be32 c_mask;
+ __be32 c_pres;
+ __be16 disfc;
+ __be16 crcec;
+ __be32 res4[4];
+ __be16 ts_tmp;
+ __be16 tmp_mb;
+} __attribute__ ((__packed__));
+
+struct si_mode_info {
+ u8 simr_rfsd;
+ u8 simr_tfsd;
+ u8 simr_crt;
+ u8 simr_sl;
+ u8 simr_ce;
+ u8 simr_fe;
+ u8 simr_gm;
+};
+
+struct ucc_tdm_info {
+ struct ucc_fast_info uf_info;
+ struct si_mode_info si_info;
+};
+
+struct ucc_tdm_private {
+ struct ucc_tdm_info *ut_info;
+ struct ucc_fast_private *uccf;
+ struct device *dev;
+ struct ucc_fast __iomem *uf_regs; /* UCC Fast registers */
+ struct si1 __iomem *si_regs;
+ struct ucc_transparent_param __iomem *ucc_pram;
+ u16 tdm_port; /* port for this tdm:TDMA,TDMB,TDMC,TDMD */
+ u32 siram_entry_id;
+ u16 __iomem *siram;
+ enum tdm_mode_t tdm_mode;
+ enum tdm_framer_t tdm_framer_type;
+ bool tdm_busy;
+ u8 num_of_ts; /* the number of timeslots in this tdm frame */
+ u32 tx_ts_mask; /* tx time slot mask */
+ u32 rx_ts_mask; /*rx time slot mask */
+ u8 *rx_buffer; /* buffer used for Rx by the tdm */
+ u8 *tx_buffer; /* buffer used for Tx by the tdm */
+ dma_addr_t dma_rx_addr; /* dma mapped buffer for TDM Rx */
+ dma_addr_t dma_tx_addr; /* dma mapped buffer for TDM Tx */
+ struct qe_bd *tx_bd;
+ struct qe_bd *rx_bd;
+ u8 phase_rx;
+ u8 phase_tx;
+ u32 ucc_pram_offset;
+ dma_addr_t dma_rx_bd;
+ dma_addr_t dma_tx_bd;
+ spinlock_t tdmlock;
+ wait_queue_head_t tdm_queue;
+ bool tdm_queue_flag;
+ struct tdm_adapter adap;
+#ifdef CONFIG_PM
+ struct ucc_transparent_param *ucc_pram_bak;
+ u32 gumr;
+ u8 guemr;
+ u32 cmxsi1cr_l, cmxsi1cr_h;
+ u32 cmxsi1syr;
+ u32 cmxucr[4];
+#endif
+};
+
+#define NUM_OF_BUF 4
+#define MAX_RX_BUF_LENGTH (72*0x20)
+#define ALIGNMENT_OF_UCC_TRANS_PRAM 64
+#define SI_BANK_SIZE 128
+#define MAX_TDM_NUM 8
+#define BD_LEN_MASK 0xffff
+
+#endif
diff --git a/drivers/tdm/device/tdm_fsl.c b/drivers/tdm/device/tdm_fsl.c
new file mode 100644
index 0000000..8140a06
--- /dev/null
+++ b/drivers/tdm/device/tdm_fsl.c
@@ -0,0 +1,891 @@
+/*
+ * drivers/tdm/tdm_fsl.c
+ *
+ * Copyright (C) 2007-2012 Freescale Semiconductor, Inc, All rights reserved.
+ *
+ * TDM driver for Freescale TDM controller.
+ * This driver can interface with SLIC device to run VOIP kind of
+ * applications.
+ *
+ * Author: P. V. Suresh <pala@freescale.com>
+ * Hemant Agrawal <hemant@freescale.com>
+ * Rajesh Gumasta <rajesh.gumasta@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+ /* Note that this is a complete rewrite of P.V. Suresh's driver code.
+ But we have used so much of his original code and ideas that it seems
+ only fair to recognize him as co-author -- Rajesh & Hemant */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of_platform.h>
+#include <linux/io.h>
+#include <linux/tdm.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/dma-mapping.h>
+#include <linux/spinlock.h>
+#include <sysdev/fsl_soc.h>
+
+#include "tdm_fsl.h"
+
+#define DRV_DESC "Freescale TDM Driver Adapter"
+#define DRV_NAME "fsl_tdm"
+
+int loopback;
+module_param(loopback, int, 0);
+MODULE_PARM_DESC(loopback, "Enable TDM in loopback mode."
+ " Enable=1, Disable=0(default)");
+
+static int tdmen = 1;
+
+module_param(tdmen, int, S_IRUSR);
+MODULE_PARM_DESC(tdmen, "Enable TDM: Enable=1, Disable=0(default)");
+
+/* Initialize the Tx Transmit Control Discriptor parameters*/
+static void tx_tcd_init(struct tdm_priv *priv)
+{
+ int i;
+ u32 iter;
+ u32 offset;
+ dma_addr_t physaddr;
+ struct tdm_adapter *adap;
+ int bytes_in_fifo_per_frame;
+ adap = priv->adap;
+ if (!adap) {
+ pr_err("%s: Invalid handle\n", __func__);
+ return;
+ }
+ bytes_in_fifo_per_frame =
+ ALIGN_SIZE(adap->adapt_cfg.num_ch * adap->adapt_cfg.slot_width, 8);
+
+ iter = (bytes_in_fifo_per_frame / NBYTES) * adap->adapt_cfg.num_frames;
+
+ for (i = 0; i < NUM_OF_TDM_BUF; i++) {
+ offset = i * adap->adapt_cfg.num_frames *
+ bytes_in_fifo_per_frame;
+ /* saddr */
+ priv->dma_tx_tcd[i]->tcd[0] = (u32)priv->dma_output_paddr
+ + offset;
+
+ /* ssize=dsize=64bit, soff=8, smod=dmod=0 */
+ priv->dma_tx_tcd[i]->tcd[1] =
+ DMA_TCD1_SOFF(SOFF_VAL) | DMA_TCD1_SSIZE(SSIZE_64BITS) |
+ DMA_TCD1_DSIZE(SSIZE_64BITS);
+
+ /* number of bytes for minor loop, wide fifo 8bytes for dma */
+ priv->dma_tx_tcd[i]->tcd[2] = NBYTES;
+
+ /* slast = 0 */
+ priv->dma_tx_tcd[i]->tcd[3] = SLAST;
+
+ /* dadr = TX FIFO */
+ priv->dma_tx_tcd[i]->tcd[4] = TDM_TDR_OFFSET + priv->ptdm_base;
+
+ /* channel to channel linking is disabled ,
+ * destination offset is inc destination adr by 8,
+ * current iteration(citer) = number of transfers for frame
+ */
+ priv->dma_tx_tcd[i]->tcd[5] = DMA_TCD5_CITER_DISABLE_LINK(iter);
+
+ /* enable scater gather, interrupt on 1 Frame, */
+ priv->dma_tx_tcd[i]->tcd[7] =
+ DMA_TCD7_BITER_DISABLE_LINK(iter) | DMA_TCD7_E_SG;
+ priv->dma_tx_tcd[i]->tcd[6] = SLAST_SGA;
+ }
+
+ /* Next TCD for SG operation */
+ physaddr = priv->dma_tx_tcd_paddr;
+ priv->dma_tx_tcd[2]->tcd[6] =
+ ALIGN_SIZE(physaddr, ALIGNED_32_BYTES);
+ physaddr += TCD_BUFFER_SIZE;
+ priv->dma_tx_tcd[0]->tcd[6] =
+ ALIGN_SIZE(physaddr, ALIGNED_32_BYTES);
+ physaddr += TCD_BUFFER_SIZE;
+ priv->dma_tx_tcd[1]->tcd[6] =
+ ALIGN_SIZE(physaddr, ALIGNED_32_BYTES);
+}
+
+/* Initialize the Rx Transmit Control Discriptor parameters*/
+static void rx_tcd_init(struct tdm_priv *priv)
+{
+ int i;
+ u32 iter;
+ u32 offset;
+ dma_addr_t physaddr;
+ struct tdm_adapter *adap;
+ int bytes_in_fifo_per_frame;
+ adap = priv->adap;
+ if (!adap) {
+ pr_err("%s: Invalid handle\n", __func__);
+ return;
+ }
+ bytes_in_fifo_per_frame =
+ ALIGN_SIZE(adap->adapt_cfg.num_ch * adap->adapt_cfg.slot_width, 8);
+
+ iter = (bytes_in_fifo_per_frame / NBYTES) * adap->adapt_cfg.num_frames;
+
+ for (i = 0; i < NUM_OF_TDM_BUF; i++) {
+ /* TDM RX fifo address */
+ priv->dma_rx_tcd[i]->tcd[0] = TDM_RDR_OFFSET + priv->ptdm_base;
+
+ /* ssize=dsize=64bit, soff=smod=dmod=0 */
+ priv->dma_rx_tcd[i]->tcd[1] =
+ DMA_TCD1_SSIZE(SSIZE_64BITS) | DMA_TCD1_DSIZE(SSIZE_64BITS);
+
+ /* number of bytes for minor loop, wide fifo 8bytes for dma */
+ priv->dma_rx_tcd[i]->tcd[2] = NBYTES;
+
+ /* slast = 0 */
+ priv->dma_rx_tcd[i]->tcd[3] = SLAST;
+
+ offset = i * adap->adapt_cfg.num_frames *
+ bytes_in_fifo_per_frame;
+
+ /* dadr = rx buffer address */
+ priv->dma_rx_tcd[i]->tcd[4] = (u32)priv->dma_input_paddr
+ + offset;
+
+ /* channel to channel linking is disabled ,
+ * destination offset is inc destination adr by 8,
+ * current iteration(citer) = number of transfers for frame
+ */
+ priv->dma_rx_tcd[i]->tcd[5] =
+ DMA_TCD5_DOFF(DOFF_VAL) | DMA_TCD5_CITER_DISABLE_LINK(iter);
+
+ /* enable scater gather, interrupt on 1 Frame, */
+ priv->dma_rx_tcd[i]->tcd[7] =
+ DMA_TCD7_BITER_DISABLE_LINK(iter) | DMA_TCD7_E_SG |
+ DMA_TCD7_INT_MAJ;
+ priv->dma_rx_tcd[i]->tcd[6] = DLAST_SGA;
+ }
+
+ /* Next TCD for SG operation */
+ physaddr = priv->dma_rx_tcd_paddr;
+ priv->dma_rx_tcd[2]->tcd[6] =
+ ALIGN_SIZE(physaddr, ALIGNED_32_BYTES);
+ physaddr += TCD_BUFFER_SIZE;
+ priv->dma_rx_tcd[0]->tcd[6] =
+ ALIGN_SIZE(physaddr, ALIGNED_32_BYTES);
+ physaddr += TCD_BUFFER_SIZE;
+ priv->dma_rx_tcd[1]->tcd[6] =
+ ALIGN_SIZE(physaddr, ALIGNED_32_BYTES);
+}
+
+static irqreturn_t tdm_err_isr(int irq, void *p)
+{
+ int ret = IRQ_NONE;
+ u32 status, mask, val;
+ u32 dmac_err;
+ struct tdm_priv *priv;
+ u32 ch;
+ priv = p;
+
+ if (!priv) {
+ pr_err("%s: Invalid handle\n", __func__);
+ return -EINVAL;
+ }
+
+ /* transmit errors */
+ status = in_be32(&priv->tdm_regs->ter);
+ mask = in_be32(&priv->tdm_regs->tier);
+ val = status & mask;
+ out_be32(&priv->tdm_regs->ter, val);
+
+ /* Transmit under Run error */
+ if (val & TIER_TUEE)
+ dev_err(priv->device, "TDM::Transmit Under Run error\n");
+
+ /* Transmit Sync Error */
+ if (val & TIER_TSEEE)
+ dev_err(priv->device, "TDM::Transmit Sync error\n");
+
+ if (val)
+ ret = IRQ_HANDLED;
+
+ /* receive errors */
+ status = in_be32(&priv->tdm_regs->rer);
+ mask = in_be32(&priv->tdm_regs->rier);
+ val = status & mask;
+ out_be32(&priv->tdm_regs->rer, val);
+
+ /* Receiver Over run error */
+ if (val & RIER_ROEE)
+ dev_err(priv->device, "TDM::Receive Over Run error\n");
+
+ /* Receive Sync Error */
+ if (val & RIER_RSEEE)
+ dev_err(priv->device, "TDM::Receive Sync error\n");
+
+ if (val)
+ ret = IRQ_HANDLED;
+
+ /* Handling of DMA Errors */
+ dmac_err = in_be32(&priv->dmac_regs->dmaes);
+ if (!(dmac_err & DMAES_VLD))
+ return ret;
+
+ ch = DMAES_ERRCHN(dmac_err);
+
+ if (dmac_err & DMAES_CPE)
+ dev_err(priv->device, "TDM::Channel priority error\n");
+ if (dmac_err & DMAES_GPE)
+ dev_err(priv->device, "TDM::Group priority error\n");
+ if (dmac_err & DMAES_SAE)
+ dev_err(priv->device, "TDM::Source address error\n");
+ if (dmac_err & DMAES_SOE)
+ dev_err(priv->device, "TDM::Source offset error\n");
+ if (dmac_err & DMAES_DAE)
+ dev_err(priv->device, "TDM::Destination address error\n");
+ if (dmac_err & DMAES_DOE)
+ dev_err(priv->device, "TDM::Destination offset error\n");
+ if (dmac_err & DMAES_NCE)
+ dev_err(priv->device, "TDM::Nbytes citer error\n");
+ if (dmac_err & DMAES_SGE)
+ dev_err(priv->device, "TDM::Scatter gather error\n");
+ if (dmac_err & DMAES_DBE)
+ dev_err(priv->device, "TDM::Destination bus error\n");
+ if (dmac_err & DMAES_SBE)
+ dev_err(priv->device, "TDM::Source bus error\n");
+
+ /* Clear the error */
+ out_8(&priv->dmac_regs->dmacerr, (u8)ch);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t dmac_done_isr(int irq, void *p)
+{
+ u32 ch;
+ int ret = IRQ_NONE;
+ struct tdm_priv *priv;
+
+ priv = p;
+ if (!priv) {
+ pr_err("%s: Invalid handle\n", __func__);
+ return -EINVAL;
+ }
+
+ ch = in_be32(&priv->dmac_regs->dmaintl);
+
+ /* clear interrupt */
+ if (ch & DMAC_RX_INT) {
+ out_8(&priv->dmac_regs->dmacint, TDMRX_DMA_CH);
+ ret = IRQ_HANDLED;
+ /* track phases for Rx/Tx */
+ priv->phase_rx += 1;
+ if (priv->phase_rx == NUM_OF_TDM_BUF)
+ priv->phase_rx = 0;
+ }
+ if (ch & DMAC_TX_INT) {
+ out_8(&priv->dmac_regs->dmacint, TDMTX_DMA_CH);
+ ret = IRQ_HANDLED;
+ }
+
+ if (ret == IRQ_HANDLED) {
+ /* set the flag and wake up the thread */
+ priv->adap->tdm_rx_flag = 1;
+
+ /* schedule the tasklet */
+ if (priv->adap->tasklet_conf)
+ tasklet_schedule(&priv->adap->tdm_data_tasklet);
+ }
+ return ret;
+}
+
+static int init_tdm(struct tdm_priv *priv)
+{
+ u8 *buf;
+ int i;
+ int buf_size;
+ dma_addr_t physaddr = 0;
+ int ret = 0;
+ struct tdm_adapter *adap;
+
+ if (!priv) {
+ pr_err("%s: Invalid handle\n", __func__);
+ return -EINVAL;
+ }
+
+ adap = priv->adap;
+
+ /*
+ Allocate memory for Rx/Tx buffer according to active time slots
+ BufferSize = NUM_OF_TDM_BUF * NUM_SAMPLES_PER_FRAME * slot_width *
+ num_ch
+ */
+ /*Allocating Rx Buffer*/
+ buf_size = TDM_BUF_SIZE(adap->adapt_cfg.num_ch,
+ adap->adapt_cfg.slot_width,
+ adap->adapt_cfg.num_frames);
+ buf = dma_alloc_coherent(priv->device, buf_size, &physaddr, GFP_KERNEL);
+ if (!buf) {
+ ret = -ENOMEM;
+ goto err_alloc_ip;
+ }
+ priv->dma_input_paddr = physaddr;
+ priv->dma_input_vaddr = buf;
+ priv->tdm_input_data = ALIGN_ADDRESS(buf, ALIGNED_8_BYTES);
+
+ /*Allocating Tx Buffer*/
+ buf = dma_alloc_coherent(priv->device, buf_size, &physaddr, GFP_KERNEL);
+ if (!buf) {
+ ret = -ENOMEM;
+ goto err_alloc_op;
+ }
+ priv->dma_output_paddr = physaddr;
+ priv->dma_output_vaddr = buf;
+ priv->tdm_output_data = ALIGN_ADDRESS(buf, ALIGNED_8_BYTES);
+
+ /* allocate memory for TCD buffer discriptors */
+ buf = dma_alloc_coherent(priv->device, NUM_OF_TDM_BUF * TCD_BUFFER_SIZE,
+ &physaddr, GFP_KERNEL);
+ if (!buf) {
+ ret = -ENOMEM;
+ goto err_alloc_rx;
+ }
+
+ memset(buf, 0, NUM_OF_TDM_BUF * TCD_BUFFER_SIZE);
+ priv->dma_rx_tcd_paddr = physaddr;
+ priv->dma_rx_tcd_vaddr = buf;
+ for (i = 0; i < NUM_OF_TDM_BUF; i++) {
+ priv->dma_rx_tcd[i] = ALIGN_ADDRESS(buf, ALIGNED_32_BYTES);
+ buf += TCD_BUFFER_SIZE;
+ }
+
+ buf = dma_alloc_coherent(priv->device, 3 * TCD_BUFFER_SIZE, &physaddr,
+ GFP_KERNEL);
+ if (!buf) {
+ ret = -ENOMEM;
+ goto err_alloc_tx;
+ }
+ memset(buf, 0, NUM_OF_TDM_BUF * TCD_BUFFER_SIZE);
+ priv->dma_tx_tcd_paddr = physaddr;
+ priv->dma_tx_tcd_vaddr = buf;
+ for (i = 0; i < NUM_OF_TDM_BUF; i++) {
+ priv->dma_tx_tcd[i] = ALIGN_ADDRESS(buf, ALIGNED_32_BYTES);
+ buf += TCD_BUFFER_SIZE;
+ }
+
+ priv->phase_rx = 0;
+ priv->phase_tx = 0;
+ return 0;
+
+err_alloc_tx:
+ dma_free_coherent(priv->device, NUM_OF_TDM_BUF * TCD_BUFFER_SIZE,
+ priv->dma_rx_tcd_vaddr, priv->dma_rx_tcd_paddr);
+err_alloc_rx:
+ dma_free_coherent(priv->device, buf_size, priv->dma_output_vaddr,
+ priv->dma_output_paddr);
+err_alloc_op:
+ dma_free_coherent(priv->device, buf_size, priv->dma_input_vaddr,
+ priv->dma_input_paddr);
+err_alloc_ip:
+ return ret;
+}
+
+/* TDM register programming */
+static int tdm_fsl_reg_init(struct tdm_priv *priv)
+{
+ int i;
+ int ch_size_type;
+ phys_addr_t base = get_immrbase();
+ struct tdm_adapter *adap;
+ if (!priv) {
+ pr_err("%s: Invalid handle\n", __func__);
+ return -EINVAL;
+ }
+ adap = priv->adap;
+
+ /* channel/group round robin */
+ out_be32(&priv->dmac_regs->dmacr, DMACR_ERGA | DMACR_ERCA);
+ /* Enable error Interrupts for TDM Rx &Tx */
+ out_8(&priv->dmac_regs->dmaseei, TDMTX_DMA_CH);
+ out_8(&priv->dmac_regs->dmaseei, TDMRX_DMA_CH);
+ out_be32(&priv->dmac_regs->dmagpor, DMAGPOR_SNOOP);
+
+ tx_tcd_init(priv);
+ rx_tcd_init(priv);
+
+ adap->adapt_cfg.loopback = loopback;
+
+ /* TDM RD->TD loopback, Share T/R Fsync,Clock */
+ if (adap->adapt_cfg.loopback)
+ out_be32(&priv->tdm_regs->gir, GIR_LPBK | GIR_RTS);
+ else
+ out_be32(&priv->tdm_regs->gir, GIR_RTS);
+
+ /*
+ Rx Water mark 0, FIFO enable, Wide fifo, DMA enable for RX,
+ Receive Sync out, syncwidth = ch width, Rx clk out,zero sync,
+ falling edge , data order
+ */
+
+ out_be32(&priv->tdm_regs->rir,
+ RIR_RFWM(RIR_RFWM_VAL) | RIR_RFEN | RIR_RWEN | RIR_RDMA |
+ RIR_RSL | RIR_RSO | RIR_RCOE | RIR_RRDO |
+ RIR_RFSD(RIR_RFSD_VAL));
+ out_be32(&priv->tdm_regs->tir,
+ TIR_TFWM(TIR_RFWM_VAL) | TIR_TFEN | TIR_TWEN | TIR_TDMA |
+ TIR_TSL | TIR_TSO | TIR_TRDO | TIR_TFSD(TIR_RFSD_VAL));
+
+ /* no of channels ,Channel size-coading */
+ switch (adap->adapt_cfg.ch_size_type) {
+ case CHANNEL_8BIT_LIN:
+ ch_size_type = CHANNEL_8BIT_LIN;
+ break;
+ case CHANNEL_8BIT_ULAW:
+ ch_size_type = CHANNEL_8BIT_ULAW;
+ break;
+ case CHANNEL_8BIT_ALAW:
+ ch_size_type = CHANNEL_8BIT_ALAW;
+ break;
+ case CHANNEL_16BIT_LIN:
+ ch_size_type = CHANNEL_16BIT_LIN;
+ break;
+ default:
+ pr_err("%s:Invalid channel_size_type.\n"
+ "Setting channel to default size: 16 bits", __func__);
+ ch_size_type = CHANNEL_16BIT_LIN;
+
+ }
+ out_be32(&priv->tdm_regs->rfp,
+ RFP_RNCF(adap->adapt_cfg.num_ch) | RFP_RCS(ch_size_type));
+ out_be32(&priv->tdm_regs->tfp,
+ TFP_TNCF(adap->adapt_cfg.num_ch) | TFP_TCS(ch_size_type));
+
+ out_be32(&priv->tdm_regs->rier, 0);
+ out_be32(&priv->tdm_regs->tier, 0);
+
+ /* clear all receive and transmit chs */
+ for (i = 0; i < 4; i++) {
+ out_be32(&priv->tdm_regs->tcma[i], 0);
+ out_be32(&priv->tdm_regs->tcen[i], 0);
+ out_be32(&priv->tdm_regs->rcen[i], 0);
+ }
+
+ return 0;
+
+}
+
+static void tdm_fsl_stop(struct tdm_priv *priv)
+{
+ /* stop the Tx & Rx */
+ out_be32(&priv->tdm_regs->tcr, 0);
+ out_be32(&priv->tdm_regs->rcr, 0);
+
+ /* Clear DMA error Enable Request DMAEEIH/L */
+ out_8(&priv->dmac_regs->dmaceei, TDMTX_DMA_CH);
+ out_8(&priv->dmac_regs->dmaceei, TDMRX_DMA_CH);
+ out_8(&priv->dmac_regs->dmacint, TDMRX_DMA_CH);
+ out_8(&priv->dmac_regs->dmacint, TDMTX_DMA_CH);
+
+ /* disable the dma request */
+ out_8(&priv->dmac_regs->dmacerq, TDMRX_DMA_CH);
+ out_8(&priv->dmac_regs->dmacerq, TDMTX_DMA_CH);
+}
+
+static int tdm_fsl_disable(struct tdm_adapter *adap)
+{
+ struct tdm_priv *priv;
+ if (!adap) {
+ pr_err("%s: Invalid handle\n", __func__);
+ return -EINVAL;
+ }
+ priv = tdm_get_adapdata(adap);
+ if (priv->tdm_active == 0) {
+ dev_warn(priv->device, "already Disabled");
+ return 0;
+ }
+
+ priv->tdm_active = 0;
+
+ return 0;
+}
+
+static int tdm_fsl_enable(struct tdm_adapter *adap)
+{
+ int i;
+ u32 ch_enab[4];
+ unsigned long timeout;
+ struct tdm_priv *priv;
+ u32 ph;
+ if (!adap) {
+ pr_err("%s: Invalid handle\n", __func__);
+ return -EINVAL;
+ }
+ priv = tdm_get_adapdata(adap);
+ ph = priv->phase_tx;
+
+ if (priv->tdm_active == 1) {
+ dev_warn(priv->device, "already Enabled");
+ return 0;
+ }
+
+ /* enable the Channels required 0 to number of ch -1 */
+ for (i = 0; i < NUM_TDMTCEN_REG; i++)
+ ch_enab[i] = 0;
+
+ for (i = 0; i < adap->adapt_cfg.num_ch; i++)
+ ch_enab[i / TDMTCEN_REG_LEN] |= (1 << (i & 0x1F));
+
+ for (i = 0; i < NUM_TDMTCEN_REG; i++) {
+ out_be32(&priv->tdm_regs->rcen[i], ch_enab[i]);
+ out_be32(&priv->tdm_regs->tcen[i], ch_enab[i]);
+ }
+
+ /* Clear the DONE bit */
+ out_8(&priv->dmac_regs->dmacdne, TDMRX_DMA_CH);
+ out_8(&priv->dmac_regs->dmacdne, TDMTX_DMA_CH);
+
+ /* Load the Tx transfer control descriptors */
+ for (i = 0; i < DMA_MAX_TCD; i++)
+ out_be32(&priv->dmac_regs->tcd[TDMTX_DMA_CH].tcd[i],
+ priv->dma_tx_tcd[ph]->tcd[i]);
+
+ /* Load the Rx transfer control descriptors */
+ for (i = 0; i < DMA_MAX_TCD; i++)
+ out_be32(&priv->dmac_regs->tcd[TDMRX_DMA_CH].tcd[i],
+ priv->dma_rx_tcd[ph]->tcd[i]);
+
+ /* enable the dma request */
+ out_8(&priv->dmac_regs->dmaserq, TDMRX_DMA_CH);
+ out_8(&priv->dmac_regs->dmaserq, TDMTX_DMA_CH);
+
+ /* Enable Receiver, transmitter */
+ timeout = jiffies + TDM_ENABLE_TIMEOUT;
+ out_be32(&priv->tdm_regs->tcr, TCR_TEN);
+ while (!(in_be32(&priv->tdm_regs->tsr) & TSR_TENS)) {
+ if (time_after(jiffies, timeout)) {
+ dev_err(priv->device, "timeout to enable TDM Tx\n");
+ return -ETIMEDOUT;
+ }
+ cpu_relax();
+ }
+
+ timeout = jiffies + TDM_ENABLE_TIMEOUT;
+ out_be32(&priv->tdm_regs->rcr, RCR_REN);
+ while (!(in_be32(&priv->tdm_regs->rsr) & RSR_RENS)) {
+ if (time_after(jiffies, timeout)) {
+ dev_err(priv->device, "timeout to enable TDM Rx\n");
+ return -ETIMEDOUT;
+ }
+ cpu_relax();
+
+ }
+
+ priv->tdm_active = 1;
+ return 1;
+}
+static u32 tdm_fsl_read(struct tdm_adapter *adap,
+ u16 **input_tdm_buffer)
+{
+ struct tdm_priv *priv;
+ u32 phase_rx;
+ u32 buf_addr, buf_size;
+ int bytes_in_fifo_per_frame;
+ if (!adap) {
+ pr_err("%s: Invalid handle\n", __func__);
+ return -EINVAL;
+ }
+ /* point to where to start for the current phase data processing */
+ bytes_in_fifo_per_frame =
+ ALIGN_SIZE(adap->adapt_cfg.num_ch * adap->adapt_cfg.slot_width, 8);
+
+ priv = tdm_get_adapdata(adap);
+ if (!priv) {
+ pr_err("%s: Invalid handle\n", __func__);
+ return -EINVAL;
+ }
+
+ if (priv->tdm_active == 0) {
+ dev_warn(priv->device, "TDM is not ready");
+ return 0;
+ }
+
+ if (priv->phase_rx == 0)
+ phase_rx = NUM_OF_TDM_BUF - 1;
+ else
+ phase_rx = priv->phase_rx - 1;
+
+ buf_size = bytes_in_fifo_per_frame * adap->adapt_cfg.num_frames;
+ buf_addr = buf_size * phase_rx;
+ *input_tdm_buffer = (u16 *)(priv->tdm_input_data + buf_addr);
+
+ return buf_size;
+}
+
+static u32 tdm_fsl_get_write_buf(struct tdm_adapter *adap,
+ u16 **output_tdm_buffer)
+{
+ struct tdm_priv *priv;
+ u32 tmp;
+ u32 phase_tx;
+ u32 buf_addr, buf_size;
+ int bytes_in_fifo_per_frame;
+
+ if (!adap) {
+ pr_err("%s: Invalid handle\n", __func__);
+ return -EINVAL;
+ }
+ /* point to where to start for the current phase data processing */
+ bytes_in_fifo_per_frame =
+ ALIGN_SIZE(adap->adapt_cfg.num_ch * adap->adapt_cfg.slot_width, 8);
+
+ priv = tdm_get_adapdata(adap);
+ if (!priv) {
+ pr_err("%s: Invalid handle\n", __func__);
+ return -EINVAL;
+ }
+
+ if (priv->tdm_active == 0) {
+ dev_warn(priv->device, "TDM is not ready");
+ return 0;
+ }
+
+ tmp = in_be32(&priv->dmac_regs->tcd[TDMTX_DMA_CH].tcd[0]);
+
+ tmp -= priv->dma_tx_tcd[0]->tcd[0];
+
+ priv->phase_tx = tmp/(bytes_in_fifo_per_frame *
+ adap->adapt_cfg.num_frames);
+
+ if (priv->phase_tx == 0)
+ phase_tx = NUM_OF_TDM_BUF - 1;
+ else
+ phase_tx = priv->phase_tx - 1;
+
+ buf_size = bytes_in_fifo_per_frame * adap->adapt_cfg.num_frames;
+ buf_addr = buf_size * phase_tx;
+ *output_tdm_buffer = (u16 *)(priv->tdm_output_data + buf_addr);
+
+ return buf_size;
+}
+
+static const struct tdm_adapt_algorithm tdm_algo = {
+ .tdm_read = tdm_fsl_read,
+ .tdm_get_write_buf = tdm_fsl_get_write_buf,
+ .tdm_enable = tdm_fsl_enable,
+ .tdm_disable = tdm_fsl_disable,
+};
+
+static struct tdm_adapter tdm_fsl_ops = {
+ .owner = THIS_MODULE,
+ .name = "fsl_tdm",
+ .algo = &tdm_algo,
+};
+
+static int tdm_fsl_probe(struct platform_device *ofdev)
+{
+ int ret = 0;
+ struct tdm_priv *priv;
+ struct resource res;
+
+ priv = kzalloc(sizeof(struct tdm_priv), GFP_KERNEL);
+ if (!priv) {
+ ret = -ENOMEM;
+ goto err_alloc;
+ }
+
+ dev_set_drvdata(&ofdev->dev, priv);
+ priv->device = &ofdev->dev;
+ ret = of_address_to_resource(ofdev->dev.of_node, 0, &res);
+ if (ret) {
+ ret = -EINVAL;
+ goto err_resource;
+ }
+
+ priv->ptdm_base = (u32)res.start;
+ priv->tdm_regs = of_iomap(ofdev->dev.of_node, 0);
+ if (!priv->tdm_regs) {
+ ret = -ENOMEM;
+ goto err_tdmregs;
+ }
+
+ priv->dmac_regs = of_iomap(ofdev->dev.of_node, 1);
+ if (!priv->dmac_regs) {
+ ret = -ENOMEM;
+ goto err_dmacreg;
+ }
+
+ /* tdmrd tmdtd at immrbar+0x16100 */
+ priv->data_regs =
+ (struct tdm_data *)(TDM_DATAREG_OFFSET + (u8 *)priv->tdm_regs);
+ /* TDMCLK_DIV_VAL_RX/TX at TDMBASE+0x180 */
+ priv->clk_regs =
+ (struct tdm_clock *)(TDM_CLKREG_OFFSET + (u8 *)priv->tdm_regs);
+
+ priv->dmac_done_intr = irq_of_parse_and_map(ofdev->dev.of_node, 0);
+ if (priv->dmac_done_intr == NO_IRQ) {
+ ret = -EINVAL;
+ goto err_dmacdone_irqmap;
+ }
+ ret =
+ request_irq(priv->dmac_done_intr, dmac_done_isr, 0, "dmac_done_isr",
+ priv);
+ if (ret)
+ goto err_dmacdoneisr;
+
+
+ priv->adap = &tdm_fsl_ops;
+
+ /* Wait q initilization */
+ priv->adap->tdm_rx_flag = 0;
+ /* todo - these should be configured by dts or init time */
+ tdm_set_adapdata(priv->adap, priv);
+ priv->adap->parent = &ofdev->dev;
+
+ ret = tdm_add_adapter(priv->adap);
+ if (ret < 0) {
+ dev_err(priv->device, "failed to add adapter\n");
+ goto fail_adapter;
+ }
+
+
+ ret = init_tdm(priv);
+ if (ret)
+ goto err_tdminit;
+
+ ret = tdm_fsl_reg_init(priv);
+ if (ret)
+ goto err_tdminit;
+
+ spin_lock_init(&priv->tdmlock);
+ spin_lock(&priv->tdmlock);
+ priv->tdm_active = 0;
+ spin_unlock(&priv->tdmlock);
+
+ if (tdmen) {
+ ret = tdm_fsl_enable(priv->adap);
+ if (!ret)
+ goto err_tdminit;
+ }
+
+ return 0;
+
+err_tdminit:
+fail_adapter:
+ free_irq(priv->dmac_done_intr, priv);
+err_dmacdoneisr:
+ free_irq(priv->tdm_err_intr, priv);
+err_dmacdone_irqmap:
+ irq_dispose_mapping(priv->dmac_done_intr);
+err_dmacreg:
+ iounmap(priv->dmac_regs);
+err_tdmregs:
+err_resource:
+ dev_set_drvdata(&ofdev->dev, NULL);
+ kfree(priv);
+err_alloc:
+ return ret;
+}
+
+static int tdm_fsl_remove(struct platform_device *ofdev)
+{
+ struct tdm_priv *priv;
+ int buf_size;
+ struct tdm_adapter *adap;
+
+ if (!ofdev) {
+ pr_err("%s: Invalid handle\n", __func__);
+ return -EINVAL;
+ }
+
+ priv = dev_get_drvdata(&ofdev->dev);
+ adap = priv->adap;
+
+ tdm_fsl_disable(priv->adap);
+
+ tdm_fsl_stop(priv);
+
+ tdm_del_adapter(priv->adap);
+ dev_set_drvdata(&ofdev->dev, NULL);
+
+ /* free the irqs and dispose their mapping */
+ free_irq(priv->tdm_err_intr, priv);
+ free_irq(priv->dmac_done_intr, priv);
+ irq_dispose_mapping(priv->tdm_err_intr);
+ irq_dispose_mapping(priv->dmac_done_intr);
+ iounmap(priv->tdm_regs);
+ iounmap(priv->dmac_regs);
+
+ /* free the buffers */
+ buf_size =
+ TDM_BUF_SIZE(adap->adapt_cfg.num_ch, adap->adapt_cfg.slot_width,
+ adap->adapt_cfg.num_frames);
+ dma_free_coherent(priv->device, buf_size, priv->dma_input_vaddr,
+ priv->dma_input_paddr);
+ dma_free_coherent(priv->device, buf_size, priv->dma_output_vaddr,
+ priv->dma_output_paddr);
+
+ /* free the TCDs */
+ dma_free_coherent(priv->device, NUM_OF_TDM_BUF * TCD_BUFFER_SIZE,
+ priv->dma_rx_tcd_vaddr, priv->dma_rx_tcd_paddr);
+ dma_free_coherent(priv->device, NUM_OF_TDM_BUF * TCD_BUFFER_SIZE,
+ priv->dma_tx_tcd_vaddr, priv->dma_tx_tcd_paddr);
+ dev_set_drvdata(&ofdev->dev, NULL);
+ kfree(priv);
+ return 0;
+}
+
+static const struct of_device_id fsl_tdm_match[] = {
+ {
+ .compatible = "fsl,tdm1.0",
+ },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, fsl_tdm_match);
+
+static struct platform_driver tdm_fsl_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRV_NAME,
+ .of_match_table = fsl_tdm_match,
+
+ },
+ .probe = tdm_fsl_probe,
+ .remove = tdm_fsl_remove,
+};
+
+static int __init tdm_fsl_init(void)
+{
+ int ret;
+ pr_info(DRV_NAME ": " DRV_DESC ":Init\n");
+ ret = platform_driver_register(&tdm_fsl_driver);
+ if (ret)
+ pr_err(DRV_NAME
+ "of_register_platform_driver failed (%i)\n", ret);
+ return ret;
+}
+
+static void __exit tdm_fsl_exit(void)
+{
+ pr_info(DRV_NAME ": " DRV_DESC ":Exit\n");
+ platform_driver_unregister(&tdm_fsl_driver);
+}
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("P.V.Suresh, Freescale Semiconductor");
+MODULE_DESCRIPTION("Driver For Freescale TDM controller");
+MODULE_VERSION("1.1");
+
+module_init(tdm_fsl_init);
+module_exit(tdm_fsl_exit);
diff --git a/drivers/tdm/device/tdm_fsl.h b/drivers/tdm/device/tdm_fsl.h
new file mode 100644
index 0000000..a37f7c4
--- /dev/null
+++ b/drivers/tdm/device/tdm_fsl.h
@@ -0,0 +1,444 @@
+/*
+ * drivers/device/fsl_tdm.h
+ *
+ * Copyright (C) 2007-2012 Freescale Semiconductor, Inc, All rights reserved.
+ *
+ * Created by P. V. Suresh <pala@freescale.com>
+ *
+ * Modified by Rajesh Gumasta <rajesh.gumasta@freescale.com>
+ * 1. Modified to support MPC85xx based devices
+ * 2. Modified the priv structure to support Adapter Registeration
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef FSL_TDM_H
+#define FSL_TDM_H
+
+/* enable clock to TDM */
+#ifdef CONFIG_MPC831x_RDB
+
+#define SCCR_OFFSET 0x0A08
+#define SCCR_TDM_MASK 0x000000C0
+#define TDM_CM_01 (0x01<<6)
+
+/* enable tdm in SICR */
+#define SICRL_OFFSET 0x0114
+#define SICRL_TDM_MASK 0xF00F0000
+
+#endif
+
+/* TDM data register offset */
+#define TDM_TDR_OFFSET 0x108
+#define TDM_RDR_OFFSET 0x100
+#define TDM_DATAREG_OFFSET 0x100
+#define TDM_CLKREG_OFFSET 0x180
+
+/* max number of TDM-DMA channels */
+#define DMA_MAX_CHANNELS 4
+
+/* TCD params */
+#define SOFF_VAL 0x08
+#define DOFF_VAL 0x08
+#define NBYTES 0x08 /*Minor Bytes transfer count*/
+#define SLAST 0x00 /* last source addr adjustment*/
+#define SLAST_SGA 0x00
+#define DLAST_SGA 0x00
+
+/* RIR Params*/
+#define RIR_RFSD_VAL 0x01
+#define RIR_RFWM_VAL 0x00
+
+/* TIR Params*/
+#define TIR_RFSD_VAL 0x01
+#define TIR_RFWM_VAL 0x00
+
+/* TDMTCEN */
+#define NUM_TDMTCEN_REG 0x04
+#define TDMTCEN_REG_LEN 32
+
+/* each DMA-ch contains 8 Transfer Control Discriptors */
+#define DMA_MAX_TCD 8
+
+#define DMAC_TX_INT 1
+#define DMAC_RX_INT 2
+
+#define TDM_CHANNEL_8BIT_LIN 0x00000000 /* 8 bit linear */
+#define TDM_CHANNEL_8BIT_ULAW 0x00000001 /* 8 bit Mu-law */
+#define TDM_CHANNEL_8BIT_ALAW 0x00000002 /* 8 bit A-law */
+#define TDM_CHANNEL_16BIT_LIN 0x00000003 /* 16 bit Linear */
+
+/* DMAC TCD structure */
+struct tcd {
+ u32 tcd[DMA_MAX_TCD];
+};
+
+/* DMA Controllor */
+struct dmac_regs {
+ u32 dmacr; /* DMA Control Register */
+ u32 dmaes; /* DMA Error Status Register */
+ u32 dmaerqh; /* DMA Enable Request */
+ u32 dmaerql; /* DMA Enable Request */
+ u32 dmaeeih; /* DMA Enable Error Interrupt */
+ u32 dmaeeil; /* DMA Enable Error Interrupt */
+
+ u8 dmaserq; /* DMA Set Enable Request */
+ u8 dmacerq; /* DMA Clear Enable Request */
+ u8 dmaseei; /* DMA Set Enable Error Interrupt */
+ u8 dmaceei; /* DMA Clear Enable Error Interrupt */
+
+ u8 dmacint; /* DMA Clear Interrupt Request */
+ u8 dmacerr; /* DMA Clear Error */
+ u8 dmassrt; /* DMA Set Start Bit */
+ u8 dmacdne; /* DMA Clear Done Bit */
+
+ u32 dmainth; /* DMA Interrupt Request High */
+ u32 dmaintl; /* DMA Interrupt Request */
+ u32 dmaerrh; /* DMA Error */
+ u32 dmaerrl; /* DMA Error */
+ u32 dmahrsh; /* DMA Hardware Request status */
+ u32 dmahrsl; /* DMA HardWired Request status */
+ u32 dmagpor; /* DMA General Purpose Register */
+ u8 reserved0[0xC4];
+ u8 dchpri[DMA_MAX_CHANNELS]; /* DMA Port Priority */
+ u8 reserved1[0xEFC];
+ struct tcd tcd[DMA_MAX_CHANNELS]; /*Transfer Control Descriptor */
+};
+
+/* DMA GPOR */
+#define DMAGPOR_SNOOP 0x00000040 /* Enable Snooping */
+
+/* DMA Control Register (DMACR) */
+#define DMACR_EMLM 0x00000080 /* Enable Minor loop Mapping */
+#define DMACR_CLM 0x00000040 /* Continuous link mode */
+#define DMACR_HALT 0x00000020 /* Halt DMA */
+#define DMACR_HOE 0x00000010 /* Halt on Error */
+#define DMACR_ERGA 0x00000008 /* Round robin among the groups */
+#define DMACR_ERCA 0x00000004 /* Round robin Port Arbitration */
+#define DMACR_EDBG 0x00000002 /* Debug */
+#define DMACR_EBW 0x00000001 /* Enable Buffer */
+
+/* DMA Error Status DMAES */
+#define DMAES_VLD 0x80000000 /* Logical OR of all DMA errors. */
+#define DMAES_ECX 0x00010000 /* Transfer cancelled */
+#define DMAES_GPE 0x00008000 /* Group priority error */
+#define DMAES_CPE 0x00004000 /* Channel priority error */
+/* errored/cancelled channel */
+#define DMAES_ERRCHN(ERRCH) (((ERRCH) & 0x1F00) >> 8)
+#define DMAES_SAE 0x00000080 /* Source address error */
+#define DMAES_SOE 0x00000040 /* Source offset error */
+#define DMAES_DAE 0x00000020 /* Destination address error */
+#define DMAES_DOE 0x00000010 /* Destination offset error */
+#define DMAES_NCE 0x00000008 /* Nbytes citer error */
+#define DMAES_SGE 0x00000004 /* Scatter gather error */
+#define DMAES_SBE 0x00000002 /* Source bus error */
+#define DMAES_DBE 0x00000001 /* Destination bus error */
+
+/* DMA Enable Request (DMAERQH, DMAERQL) Enable/disable device
+ request for the channel */
+#define DMA_SET_ENABLE_REQUEST(REGS, CH) out_8(((REGS)->dmasreq), CH)
+#define DMA_CLEAR_ENABLE_REQUEST(REGS, CH) out_8(((REGS)->dmacerq), CH)
+
+/* DMA Enable Error Interrupt (DMAEEIH, DMAEEIL) Enable/disable
+ error interrupt for the channel */
+#define DMA_SET_ENABLE_ERROR_INT(REGS, CH) out_8(((REGS)->dmaseei), CH)
+#define DMA_CLEAR_ENABLE_ERROR_INT(REGS, CH) out_8(((REGS)->dmaceei), CH)
+
+/* Clear interrupt/error for the channel */
+#define DMA_CLEAR_INTT_REQUEST(REGS, CH) out_8(((REGS)->dmacint), CH)
+#define DMA_CLEAR_ERROR(REGS, CH) out_8(((REGS)->dmacerr), CH)
+
+/* Clear done bit for the channel */
+#define DMA_CLEAR_DONE_BIT(REGS, CH) out_8(((REGS)->dmacdne), CH)
+/* Set start bit for the channel */
+#define DMA_SET_START_BIT(REGS, CH) out_8(((REGS)->dmassrt), CH)
+
+#define TDMTX_DMA_CH 0 /* TDM Tx uses DMA 0 HardWired */
+#define TDMRX_DMA_CH 1 /* TDM Rx uses DMA 1 Hardwired */
+#define TCD_SIZE 32 /* 32 byte TCD for channel */
+#define TCD_BUFFER_SIZE 64 /* 64 byte buffer for TCD */
+
+/* Source address modulo */
+#define DMA_TCD1_SMOD(SMOD) (((SMOD) & 0x1F) << 27)
+/* Source data transfer size */
+#define DMA_TCD1_SSIZE(SSIZE) (((SSIZE) & 0x7) << 24)
+
+/* Destination address modulo */
+#define DMA_TCD1_DMOD(DMOD) (((DMOD) & 0x1F) << 19)
+/* data transfer size */
+#define DMA_TCD1_DSIZE(DSIZE) (((DSIZE) & 0x7) << 16)
+
+/* Source address signed offset */
+#define DMA_TCD1_SOFF(SOFF) ((SOFF) & 0xFFFF)
+
+/* Enable link to another channel on minor iteration completion. */
+#define DMA_TCD5_E_MINOR_LINK 0x80000000
+/* Link to this channel. */
+#define DMA_TCD5_LINK_CH(CH) (((CH) & 0x3F) << 25)
+/* Current iteration count when linking disnabled */
+#define DMA_TCD5_CITER_DISABLE_LINK(CITER) (((CITER) & 0x7FFF) << 16)
+/* Current iteration count when linking enabled */
+#define DMA_TCD5_CITER_ENABLE_LINK(CITER) (((CITER) & 0x00FF) << 16)
+/* Destination address signed offset */
+#define DMA_TCD5_DOFF(DOFF) ((DOFF) & 0xFFFF)
+
+/* Beginning iteration count when linking disnabled */
+#define DMA_TCD7_BITER_DISABLE_LINK(CITER) (((CITER) & 0x7FFF) << 16)
+/* Beginning iteration count when linking enabled */
+#define DMA_TCD7_BITER_ENABLE_LINK(CITER) (((CITER) & 0x00FF) << 16)
+#define DMA_TCD7_BWC(BW) (((BW)&0x3)<<14) /* BandWidth Control. */
+/* Link channel number */
+#define DMA_TCD7_LINKCH(CH) (((CH) & 0x1F) << 8)
+#define DMA_TCD7_DONE 0x00000080 /* Channel done */
+#define DMA_TCD7_ACTIVE 0x00000040 /* Channel active */
+#define DMA_TCD7_E_MAJOR_LINK 0x00000020 /* channel to channel linking */
+#define DMA_TCD7_E_SG 0x00000010 /* Enable scatter gather */
+#define DMA_TCD7_D_REQ 0x00000008 /* Disable request */
+/* interrupt on half major counter */
+#define DMA_TCD7_INT_HALF 0x00000004
+#define DMA_TCD7_INT_MAJ 0x00000002 /* interrupt on major counter */
+#define DMA_TCD7_START 0x00000001 /* Channel start */
+
+#define SSIZE_08BITS 0x00 /* port 1 byte */
+#define SSIZE_16BITS 0x01
+#define SSIZE_32BITS 0x02
+#define SSIZE_64BITS 0x03
+
+/* TDM Control Registers. */
+struct tdm_regs {
+ u32 gir; /* General Interface Register */
+ u32 rir; /* Receive Interface Register */
+ u32 tir; /* Transmit Interface Register */
+ u32 rfp; /* Receive Frame Parameters */
+ u32 tfp; /* Transmit Frame Parameters */
+ u8 reserved0[0xC];
+ u32 rcen[4]; /* Recieve Channel Enabled */
+ u8 reserved1[0x10];
+ u32 tcen[4]; /* Transmit Channel Enabled */
+ u8 reservedd2[0x10];
+ u32 tcma[4]; /* Transmit Channel Mask */
+ u8 reservederved3[0x10];
+ u32 rcr; /* Receiver Control Register */
+ u32 tcr; /* Transmitter Control Register */
+ u32 rier; /* Receive Interrupt Enable Register */
+ u32 tier; /* Transmit Interrupt Enable Register */
+ u8 reserved4[0x10];
+ u32 rer; /* Receive Event Register */
+ u32 ter; /* Transmit Event Register */
+ u32 rsr; /* Receive Status Register */
+ u32 tsr; /* Transmit Status Register */
+};
+
+struct tdm_data {
+ u64 rdr; /* Receive Data Register */
+ u64 tdr; /* Transmit Dataa Register */
+};
+
+struct tdm_clock {
+ u32 rx; /* Transmit Dataa Register */
+ u32 tx; /* Receive Data Register */
+};
+
+/* TDMGIR General Interface Register */
+#define GIR_LPBK 0x00000004 /* loopback mode */
+#define GIR_CTS 0x00000002 /* Common TDM signals */
+#define GIR_RTS 0x00000001 /* Rx & Tx sharing */
+
+/* TDMRIR Recieve Interface Rgister */
+#define RIR_RFWM_MASK 0x00000003 /* Recieve FIFO Watermark */
+#define RIR_RFWM_SHIFT 16
+#define RIR_RFWM(x) ((x & RIR_RFWM_MASK) << RIR_RFWM_SHIFT)
+#define RIR_RFEN 0x00008000 /* Recieve FIFO Enable */
+#define RIR_RWEN 0x00004000 /* Recieve Wide FIFO Enable */
+#define RIR_RDMA 0x00000040 /* Recieve DMA Enable */
+#define RIR_RFSD_SHIFT 0x00000004 /* Recieve Frame Sync Delay */
+#define RIR_RFSD_MASK 0x00000003
+#define RIR_RFSD(x) ((x & RIR_RFSD_MASK) << RIR_RFSD_SHIFT)
+#define RIR_RSO 0x00002000 /* Recieve sync Out */
+#define RIR_RSL 0x00000800 /* Recieve sync Out Length */
+#define RIR_RSOE 0x00000400 /* Recieve sync Out Edge */
+#define RIR_RCOE 0x00000200 /* Recieve Clock Output Enable */
+#define RIR_RSA 0x00000008 /* Recieve Sync Active */
+#define RIR_RDE 0x00000004 /* Recieve Data Edge */
+#define RIR_RFSE 0x00000002 /* Recieve Frame Sync Edge */
+#define RIR_RRDO 0x00000001 /* Revieve Reversed Data Order */
+
+/* TDMTIR Transmit Interface Rgister */
+#define TIR_TFWM_MASK 0x00000003 /* Transmit FIFO Watermark */
+#define TIR_TFWM_SHIFT 16
+#define TIR_TFWM(x) ((x & TIR_TFWM_MASK) << TIR_TFWM_SHIFT)
+#define TIR_TFEN 0x00008000 /* Transmit FIFO Enable */
+#define TIR_TWEN 0x00004000 /* Transmit Wide FIFO Enable */
+#define TIR_TDMA 0x00000040 /* Transmit DMA Enable */
+#define TIR_TFSD_SHIFT 0x00000004 /* Transmit Frame Sync Delay */
+#define TIR_TFSD_MASK 0x00000003
+#define TIR_TFSD(x) ((x & TIR_TFSD_MASK) << TIR_TFSD_SHIFT)
+#define TIR_TSO 0x00002000 /* Transmit Sync Output */
+#define TIR_TSL 0x00000800 /* Transmit sync Out Length */
+#define TIR_TSOE 0x00000400 /* Transmit sync Out Edge */
+#define TIR_TCOE 0x00000200 /* Transmit Clock Output Enable */
+#define TIR_TSA 0x00000008 /* Transmit Sync Active */
+#define TIR_TDE 0x00000004 /* Transmit Data Edge */
+#define TIR_TFSE 0x00000002 /* Transmit Frame Sync Edge */
+#define TIR_TRDO 0x00000001 /* Transmit Reversed Data Order */
+
+/*TDMRFP Revieve Frame Parameters */
+#define RFP_RNCF_SHIFT 0x00000010 /* Number of Channels in TDM Frame */
+#define RFP_RNCF_MASK 0x000000FF
+#define RFP_RNCF(x) (((x - 1) & RFP_RNCF_MASK) << RFP_RNCF_SHIFT)
+#define RFP_RCS_SHIFT 0x00000004 /* Recieve Channel Size */
+#define RFP_RCS_MASK 0x00000003
+#define RFP_RCS(x) ((x & RFP_RCS_MASK) << RFP_RCS_SHIFT)
+#define RFP_RT1 0x00000002 /* Recieve T1 Frame */
+
+/*TDMTFP Transmit Frame Parameters */
+#define TFP_TNCF_SHIFT 0x00000010 /* Number of Channels in TDM Frame */
+#define TFP_TNCF_MASK 0x000000FF
+#define TFP_TNCF(x) (((x - 1) & TFP_TNCF_MASK) << TFP_TNCF_SHIFT)
+#define TFP_TCS_SHIFT 0x00000004 /* Transmit Channel Size */
+#define TFP_TCS_MASK 0x00000003
+#define TFP_TCS(x) ((x & RFP_RCS_MASK) << RFP_RCS_SHIFT)
+#define TFP_TT1 0x00000002 /* Transmit T1 Frame */
+
+
+/* TDMRCR Recieve Control Register */
+#define RCR_REN 0x00000001 /* Recieve Enable */
+/* TDMTCR Transmit Control Register */
+#define TCR_TEN 0x00000001 /* Transmit Enable */
+
+/* TDMRIER receive interrupt enable register */
+#define RIER_RCEUE 0x00000100 /* Channel Enable Update Enable */
+#define RIER_RLCEE 0x00000080 /* Recieve Last Channel Event Enable */
+#define RIER_RFSEE 0x00000040 /* Recieve Frame Sync Event Enable */
+#define RIER_RFFEE 0x00000020 /* Recieve FIFO Full Event Enable */
+#define RIER_RDREE 0x00000010 /* Recieve Data Ready Event Enable */
+#define RIER_RSEEE 0x00000008 /* Recieve Sync Error Event Enable */
+#define RIER_ROEE 0x00000004 /* Recieve Overrun Event Enable */
+
+/* TDMTIER transmit interrupt enable register */
+#define TIER_TCEUE 0x00000100 /* Channel Enable Update Enable */
+#define TIER_TLCEE 0x00000080 /* Transmit Last Channel Event */
+#define TIER_TFSEE 0x00000040 /* Transmit Frame Sync Event Enable */
+#define TIER_TFFEE 0x00000020 /* Transmit FIFO Full Event Enable */
+#define TIER_TDREE 0x00000010 /* Transmit Data Ready Event Enable */
+#define TIER_TSEEE 0x00000008 /* Transmit Sync Error Event Enable */
+#define TIER_TUEE 0x00000004 /* Transmit Overrun Event Enable */
+
+/* TDMRER Recieve Event Register */
+#define RER_RCEU 0x00000100 /* Recieve Channel Enable Update */
+#define RER_RLCE 0x00000080 /* Recieve Last Channel Event */
+#define RER_RFSE 0x00000040 /* Recieve Frame Sync Event */
+#define RER_RFFE 0x00000020 /* Recieve FIFO Full Event */
+#define RER_RDRE 0x00000010 /* Recieve Data Ready Event */
+#define RER_RSEE 0x00000008 /* Recieve Sync Error Event */
+#define RER_ROE 0x00000004 /* Recieve Overrun Event */
+
+/* TDMTER Transmit Event Register */
+#define TER_TCEU 0x00000100 /* Transmit Channel Enable Update */
+#define TER_TLCE 0x00000080 /* Transmit Last Channel Event */
+#define TER_TFSE 0x00000040 /* Transmit Frame Sync Event */
+#define TER_TFEE 0x00000020 /* Transmit FIFO Full Event */
+#define TER_TDRE 0x00000010 /* Transmit Data Ready Event */
+#define TER_TSEE 0x00000008 /* Transmit Sync Error Event */
+#define TER_TUE 0x00000004 /* Transmit Overrun Event */
+
+/* TDMRSR Recieve Status Register */
+#define RSR_RFCNT 0x00000038 /* Recieve FIFO counter */
+#define RSSS_MASK 0x00000003 /* Recieve SYNC Status */
+#define RSR_RSSS_SHIFT 1
+#define RSR_RSSS(SSS) (((SSS) >> (RSR_RSSS_SHIFT)) & (RSR_RSSS_MASK))
+#define RSR_RENS 0x00000001 /* Recieve Enable Status */
+
+/* TDMTSR Transmit Status Register */
+#define TSR_TFCNT 0x00000038 /* Transmit FIFO counter */
+#define TSR_TSSS_MASK 0x00000003 /* Transmit SYNC Status */
+#define TSR_TSSS_SHIFT 1
+#define TSR_TSSS(SSS) (((SSS) >> (TSR_TSSS_SHIFT)) & TSR_TSSS_MASK)
+#define TSR_TENS 0x00000001 /* Transmit Enable Status */
+
+/* channel width */
+#define CHANNEL_SIZE_1BYTE 1 /* 1 byte channel 8-bit linear */
+#define CHANNEL_SIZE_2BYTE 2 /* 2 bytes */
+
+/* channel parameters */
+#define TDM_ENABLE_TIMEOUT 1000 /* time out for TDM rx, tx enable */
+#define NUM_OF_TDM_BUF 3 /* Number of tdm buffers for startlite
+ DMA */
+#define ALIGNED_2_BYTES 0x02 /* 2-bytes alignment */
+#define ALIGNED_4_BYTES 0x04 /* 4-bytes alignment */
+#define ALIGNED_8_BYTES 0x08 /* 8-bytes alignment */
+#define ALIGNED_16_BYTES 0x10 /* 16-bytes alignment */
+#define ALIGNED_32_BYTES 0x20 /* 32-bytes alignment */
+#define ALIGNED_64_BYTES 0x40 /* 64-bytes alignment */
+
+/* Extend a given size to make it alignable */
+static inline int ALIGNABLE_SIZE(u32 size, u32 alignment)
+{
+ return size + alignment - 1;
+}
+
+/* Align a given address */
+static inline void *ALIGN_ADDRESS(void *address, u32 alignment)
+{
+ return (void *)(((u32) address + alignment - 1) & (~(alignment - 1)));
+}
+
+/* Size of the buffer */
+static inline int TDM_1BUF_SIZE(u32 num_ch, u32 channel_size, u32 frame_size)
+{
+ return frame_size *
+ ALIGN_SIZE(channel_size * num_ch, ALIGNED_8_BYTES);
+}
+
+/* Alignable size of the 3 buffers */
+static inline int TDM_BUF_SIZE(u32 num_ch, u32 channel_size, u32 frame_size)
+{
+ return
+ ALIGNABLE_SIZE((TDM_1BUF_SIZE(num_ch, channel_size, frame_size) *
+ NUM_OF_TDM_BUF), ALIGNED_8_BYTES);
+}
+
+
+struct tdm_priv {
+ struct tdm_regs __iomem *tdm_regs;
+ struct tdm_data __iomem *data_regs;
+ struct dmac_regs __iomem *dmac_regs;
+ struct tdm_clock __iomem *clk_regs;
+ u32 ptdm_base;
+ u8 *tdm_input_data;
+ u8 *tdm_output_data;
+ dma_addr_t dma_input_paddr; /* dma mapped buffer for TDM Rx */
+ dma_addr_t dma_output_paddr; /* dma mapped buffer for TDM Tx */
+ void *dma_input_vaddr;
+ void *dma_output_vaddr;
+ u32 phase_rx;
+ u32 phase_tx;
+ struct tcd *dma_rx_tcd[NUM_OF_TDM_BUF];
+ struct tcd *dma_tx_tcd[NUM_OF_TDM_BUF];
+ dma_addr_t dma_rx_tcd_paddr;
+ dma_addr_t dma_tx_tcd_paddr;
+ void *dma_rx_tcd_vaddr;
+ void *dma_tx_tcd_vaddr;
+ u32 tdm_buffer_size;
+ u32 tdm_err_intr;
+ u32 dmac_err_intr;
+ u32 dmac_done_intr;
+ int tdm_active;
+ struct device *device;
+ spinlock_t tdmlock;
+ struct tdm_adapter *adap;
+};
+
+#endif
diff --git a/drivers/tdm/line_ctrl/Kconfig b/drivers/tdm/line_ctrl/Kconfig
new file mode 100644
index 0000000..7630692
--- /dev/null
+++ b/drivers/tdm/line_ctrl/Kconfig
@@ -0,0 +1,18 @@
+#
+# TDM line control driver config file
+#
+
+menu "Line Control Devices"
+
+config SLIC_ZARLINK
+ tristate "Zarlink Slic intialization Module"
+ default n
+ ---help---
+ This module initialize and configure the zarlink slic
+config FSL_PQ_MDS_T1
+ tristate "FSL PQ MDS T1 CARD SUPPORT"
+ default n
+ ---help---
+ This module initializes and configures the pq-mds-t1 card
+ in T1 or E1 mode.
+endmenu
diff --git a/drivers/tdm/line_ctrl/Makefile b/drivers/tdm/line_ctrl/Makefile
new file mode 100644
index 0000000..8eb88fb
--- /dev/null
+++ b/drivers/tdm/line_ctrl/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the TDM line control drivers.
+#
+
+obj-y += slic_zarlink.o
+obj-$(CONFIG_FSL_PQ_MDS_T1) += pq_mds_t1.o
diff --git a/drivers/tdm/line_ctrl/pq_mds_t1.c b/drivers/tdm/line_ctrl/pq_mds_t1.c
new file mode 100644
index 0000000..641c9e1
--- /dev/null
+++ b/drivers/tdm/line_ctrl/pq_mds_t1.c
@@ -0,0 +1,590 @@
+/*
+ * drivers/tdm/line/pq_mds_t1.c
+ *
+ * Copyright 2011-2012 Freescale Semiconductor, Inc.
+ *
+ * T1/E1 PHY(DS26528) Control Module for Freescale PQ-MDS-T1 card.
+ *
+ * Author: Kai Jiang <Kai.Jiang@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/param.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+
+#include "pq_mds_t1.h"
+
+/* judge if pq-mds-t1 board is connected already */
+static int pq_mds_t1_connected(struct pq_mds_t1 *t1_info)
+{
+ struct pld_mem *pld_base = t1_info->pld_base;
+ u8 brdrev, pldrev;
+
+ brdrev = in_8(&pld_base->brdrev);
+ pldrev = in_8(&pld_base->pldrev);
+
+ if (brdrev != PQ_MDS_8E1T1_BRD_REV ||
+ pldrev != PQ_MDS_8E1T1_PLD_REV) {
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+/* setup pq-mds-t1 board basic clock */
+static void pq_mds_t1_clock_set(struct pq_mds_t1 *pq_mds_t1_info)
+{
+ struct ds26528_mem *ds26528 = pq_mds_t1_info->ds26528_base;
+ struct pld_mem *pld = pq_mds_t1_info->pld_base;
+
+ if (pq_mds_t1_info->card_support == LM_CARD) {
+ /* General clock configuration
+ * Altera register setting: Framer DIGIOEN and TXEN active */
+ out_8(&pld->pinset,
+ PLD_PINSET_DIGIOEN | PLD_PINSET_TXEN);
+ /* Drive MCLK & REFCLKIO with 2.048MHz */
+ out_8(&pld->csr,
+ PLD_CSR_RCSRC_2048KHZ | PLD_CSR_MSRC_2048KHZ);
+ /* Drive TSYSCLK & RSYSCLK with 2.048MHz */
+ out_8(&pld->sysclk_tr,
+ PLD_SYSCLK_RS_2048KHZ | PLD_SYSCLK_TS_2048KHZ);
+ /* Not using transmit-side elastic store,
+ * tri-state - PLD pin connected to TSSYNCIO */
+ out_8(&pld->synctss, PLD_SYNCTSS_TRI_STATE);
+ /* Drive TCLK1..4 with 2.048MHz*/
+ out_8(&pld->tcsr1, PLD_TCSR1_2048KHZ);
+ /* Drive TCLK5..8 with 2.048MHz*/
+ out_8(&pld->tcsr2, PLD_TCSR2_2048KHZ);
+
+ /* Connect tdm port A to LM card */
+ out_8(&pld->gcr, PLD_GCR_LCC_TDMA | PLD_GCR_LCE_LM);
+ /* Framer setting
+ * Select MCLK - 2.048MHz, REFCLKIO - 1.544MHz (GTCCR) */
+ out_8(&ds26528->link[0].gbl.gtccr,
+ DS26528_GTCCR_BPREFSEL_REFCLKIN |
+ DS26528_GTCCR_BFREQSEL_1544KHZ |
+ DS26528_GTCCR_FREQSEL_1544KHZ);
+ udelay(100);
+
+ /* Set TSSYNCIO -> OUTPUT (GTCR2) */
+ out_8(&ds26528->link[0].gbl.gtcr2, DS26528_GTCR2_TSSYNCOUT);
+ /* Select BPCLK=2.048MHz (GFCR) */
+ out_8(&ds26528->link[0].gbl.gfcr, DS26528_GFCR_BPCLK_2048KHZ);
+ } else {
+ if (pq_mds_t1_info->line_rate == LINE_RATE_T1) {
+ /* General clock configuration
+ * Altera register setting: Framer DIGIOEN
+ * and TXEN active */
+ out_8(&pld->pinset,
+ PLD_PINSET_DIGIOEN | PLD_PINSET_TXEN);
+ /* Drive MCLK & REFCLKIO with 1.544MHz */
+ out_8(&pld->csr,
+ PLD_CSR_RCSRC_1544KHZ | PLD_CSR_MSRC_1544KHZ);
+ /* Drive TSYSCLK & RSYSCLK with 1.544MHz */
+ out_8(&pld->sysclk_tr,
+ PLD_SYSCLK_RS_1544KHZ | PLD_SYSCLK_TS_1544KHZ);
+ /* Framer setting
+ * Select MCLK - 1.544MHz,
+ * REFCLKIO - 1.544MHz (GTCCR) */
+ out_8(&ds26528->link[0].gbl.gtccr,
+ DS26528_GTCCR_BPREFSEL_REFCLKIN |
+ DS26528_GTCCR_BFREQSEL_1544KHZ |
+ DS26528_GTCCR_FREQSEL_1544KHZ);
+ udelay(100);
+ /* Set TSSYNCIO -> OUTPUT (GTCR2) */
+ out_8(&ds26528->link[0].gbl.gtcr2,
+ DS26528_GTCR2_TSSYNCOUT);
+ /* Select BPCLK=2.048MHz (GFCR) */
+ out_8(&ds26528->link[0].gbl.gfcr,
+ DS26528_GFCR_BPCLK_2048KHZ);
+ } else {
+ /* General clock configuration
+ * Altera register setting: Framer DIGIOEN
+ * and TXEN active */
+ out_8(&pld->pinset,
+ PLD_PINSET_DIGIOEN | PLD_PINSET_TXEN);
+ /* Drive MCLK & REFCLKIO with 2.048MHz */
+ out_8(&pld->csr,
+ PLD_CSR_RCSRC_2048KHZ | PLD_CSR_MSRC_2048KHZ);
+ /* Drive TSYSCLK & RSYSCLK with 2.048MHz */
+ out_8(&pld->sysclk_tr,
+ PLD_SYSCLK_RS_2048KHZ | PLD_SYSCLK_TS_2048KHZ);
+
+ /* Framer setting
+ * Select MCLK - 2.048MHz,
+ * REFCLKIO - 2.048MHz (GTCCR) */
+ out_8(&ds26528->link[0].gbl.gtccr,
+ DS26528_GTCCR_BPREFSEL_REFCLKIN |
+ DS26528_GTCCR_BFREQSEL_2048KHZ |
+ DS26528_GTCCR_FREQSEL_2048KHZ);
+ udelay(100);
+ /* Set TSSYNCIO -> OUTPUT (GTCR2) */
+ out_8(&ds26528->link[0].gbl.gtcr2,
+ DS26528_GTCR2_TSSYNCOUT);
+ /* Select BPCLK=2.048MHz (GFCR) */
+ out_8(&ds26528->link[0].gbl.gfcr,
+ DS26528_GFCR_BPCLK_2048KHZ);
+ }
+ }
+}
+
+/* setup the TCLK to T1 rate for DS26528 */
+static void card_pld_t1_clk_set(struct pq_mds_t1 *pq_mds_t1_info)
+{
+ struct pld_mem *pld = pq_mds_t1_info->pld_base;
+ /* Drive TCLK1..4 with 1.544MHz*/
+ out_8(&pld->tcsr1, PLD_TCSR1_1544KHZ);
+ /* Drive TCLK5..8 with 1.544MHz*/
+ out_8(&pld->tcsr2, PLD_TCSR2_1544KHZ);
+
+ udelay(100);
+}
+
+/* setup the TCLK to E1 rate for DS26528 */
+static void card_pld_e1_clk_set(struct pq_mds_t1 *pq_mds_t1_info)
+{
+ struct pld_mem *pld = pq_mds_t1_info->pld_base;
+ /* Drive TCLK1..4 with 2.048MHz*/
+ out_8(&pld->tcsr1, PLD_TCSR1_2048KHZ);
+ /* Drive TCLK5..8 with 2.048MHz*/
+ out_8(&pld->tcsr2, PLD_TCSR2_2048KHZ);
+
+ udelay(100);
+}
+
+
+static void ds26528_bulk_write_set(struct pq_mds_t1 *pq_mds_t1_info)
+{
+ /* Select Bulk write for Framer Register Init (GTCR1) */
+ out_8(&(pq_mds_t1_info->ds26528_base->link[0].gbl.gtcr1),
+ DS26528_GTCR1_BWE);
+}
+
+static void ds26528_bulk_write_unset(struct pq_mds_t1 *pq_mds_t1_info)
+{
+ /* Unselect Bulk write for Framer Register Init (GTCR1) */
+ out_8(&(pq_mds_t1_info->ds26528_base->link[0].gbl.gtcr1), 0x00);
+}
+
+/* reset LIU of all channels on ds26528 */
+static void ds26528_gbl_sreset(struct pq_mds_t1 *pq_mds_t1_info)
+{
+ struct ds26528_mem *ds26528 = pq_mds_t1_info->ds26528_base;
+
+ /* Global LIU Software Reset Register (GLSRR) */
+ out_8(&ds26528->link[0].gbl.glsrr, DS26528_GLSRR_Reset);
+ /* Global Framer and BERT Software Reset Register (GFSRR) */
+ out_8(&ds26528->link[0].gbl.gfsrr, DS26528_GFSRR_Reset);
+
+ udelay(100);
+
+ out_8(&ds26528->link[0].gbl.glsrr, DS26528_GLSRR_NORMAL);
+ out_8(&ds26528->link[0].gbl.gfsrr, DS26528_GFSRR_NORMAL);
+}
+
+/* reset recieve and transimt framer for a channel on ds26528 */
+static int ds26528_rx_tx_sreset(struct pq_mds_t1 *pq_mds_t1_info, u8 phy_id)
+{
+ struct ds26528_mem *ds26528 = pq_mds_t1_info->ds26528_base;
+
+ if (phy_id > MAX_NUM_OF_CHANNELS)
+ return -ENODEV;
+
+ /* Perform RX/TX SRESET,Reset receiver (RMMR) */
+ out_8(&ds26528->link[phy_id].rx.rmmr, DS26528_RMMR_SFTRST);
+ /* Reset tranceiver (TMMR) */
+ out_8(&ds26528->link[phy_id].tx.tmmr, DS26528_TMMR_SFTRST);
+
+ udelay(100);
+
+ return 0;
+}
+
+/* clear framer LIU BERT of a channel on ds26528 */
+static void ds26528_frame_regs_clear(struct pq_mds_t1 *pq_mds_t1_info,
+ u8 phy_id)
+{
+ struct ds26528_mem *ds26528 = pq_mds_t1_info->ds26528_base;
+ /* Zero all Framer Registers */
+ memset(&ds26528->link[phy_id].rx, 0, sizeof(struct rx_frame));
+ memset(&ds26528->link[phy_id].tx, 0, sizeof(struct tx_frame));
+ memset(&ds26528->liu[phy_id], 0, sizeof(struct liu_reg));
+ memset(&ds26528->bert[phy_id], 0, sizeof(struct bert_reg));
+}
+
+/* setup the ds26825 mode, loopback or normal */
+static void ds26528_trans_mode_set(struct pq_mds_t1 *pq_mds_t1_info, u8 phy_id)
+{
+ struct ds26528_mem *ds26528 = pq_mds_t1_info->ds26528_base;
+
+ switch (pq_mds_t1_info->trans_mode) {
+ case FRAMER_LB:
+ out_8(&ds26528->link[phy_id].rx.rcr3, DS26528_RCR3_FLB);
+ break;
+ case NORMAL:
+ break;
+ default:
+ dev_err(pq_mds_t1_info->dev, "No such transfer mode\n");
+ }
+}
+
+/* setup ds26528 for T1 specification */
+static void ds26528_t1_spec_config(struct pq_mds_t1 *pq_mds_t1_info, u8 phy_id)
+{
+ struct ds26528_mem *ds26528 = pq_mds_t1_info->ds26528_base;
+ /* Receive T1 Mode (Receive Master Mode Register - RMMR)
+ Framer Disabled */
+ out_8(&ds26528->link[phy_id].rx.rmmr, DS26528_RMMR_T1);
+ /* Transmit T1 Mode (Transmit Master Mode Register - TMMR)
+ Framer Disabled */
+ out_8(&ds26528->link[phy_id].tx.tmmr, DS26528_TMMR_T1);
+ /* Receive T1 Mode Framer Enable (RMMR - Framer Enabled/T1) */
+ out_8(&ds26528->link[phy_id].rx.rmmr,
+ DS26528_RMMR_FRM_EN | DS26528_RMMR_T1);
+ /* Transmit T1 Mode Framer Enable (TMMR - Framer Enabled/T1) */
+ out_8(&ds26528->link[phy_id].tx.tmmr,
+ DS26528_TMMR_FRM_EN | DS26528_TMMR_T1);
+ /* RCR1, receive T1 B8zs & ESF (Receive Control Register 1 - T1 MODE) */
+ out_8(&ds26528->link[phy_id].rx.rcr1,
+ DS26528_RCR1_T1_SYNCT |
+ DS26528_RCR1_T1_RB8ZS |
+ DS26528_RCR1_T1_SYNCC);
+ /* RIOCR (RSYSCLK=1.544MHz, RSYNC-Output) */
+ out_8(&ds26528->link[phy_id].rx.riocr,
+ DS26528_RIOCR_1544KHZ | DS26528_RIOCR_RSIO_OUT);
+ /* TCR1 Transmit T1 b8zs*/
+ out_8(&ds26528->link[phy_id].tx.tcr[0], DS26528_TCR1_TB8ZS);
+ /* TIOCR (TSYSCLK=1.544MHz, TSYNC-Output) */
+ out_8(&ds26528->link[phy_id].tx.tiocr,
+ DS26528_TIOCR_1544KHZ | DS26528_TIOCR_TSIO_OUT);
+ /* Receive T1 Mode Framer Enable & init Done */
+ out_8(&ds26528->link[phy_id].rx.rmmr,
+ DS26528_RMMR_FRM_EN | DS26528_RMMR_INIT_DONE);
+ /* Transmit T1 Mode Framer Enable & init Done */
+ out_8(&ds26528->link[phy_id].tx.tmmr,
+ DS26528_TMMR_FRM_EN | DS26528_TMMR_INIT_DONE);
+ /* Configure LIU (LIU Transmit Receive Control Register
+ - LTRCR. T1 mode) */
+ out_8(&ds26528->liu[phy_id].ltrcr, DS26528_LTRCR_T1);
+ /* T1 Mode default 100 ohm 0db CSU (LIU Transmit Impedance and
+ Pulse Shape Selection Register - LTITSR)*/
+ out_8(&ds26528->liu[phy_id].ltitsr,
+ DS26528_LTITSR_TLIS_100OHM | DS26528_LTITSR_TLIS_0DB_CSU);
+ /* T1 Mode default 100 ohm Long haul (LIU Receive Impedance and
+ Sensitivity Monitor Register - LRISMR)*/
+ out_8(&ds26528->liu[phy_id].lrismr,
+ DS26528_LRISMR_100OHM | DS26528_LRISMR_MAX);
+ /* Enable Transmit output (LIU Maintenance Control Register - LMCR) */
+ out_8(&ds26528->liu[phy_id].lmcr, DS26528_LMCR_TE);
+}
+
+/* setup ds26528 for E1 specification */
+static void ds26528_e1_spec_config(struct pq_mds_t1 *pq_mds_t1_info, u8 phy_id)
+{
+ struct ds26528_mem *ds26528 = pq_mds_t1_info->ds26528_base;
+
+ /* Receive E1 Mode (Receive Master Mode Register - RMMR)
+ Framer Disabled */
+ out_8(&ds26528->link[phy_id].rx.rmmr, DS26528_RMMR_E1);
+ /* Transmit E1 Mode (Transmit Master Mode Register - TMMR)
+ Framer Disabled*/
+ out_8(&ds26528->link[phy_id].tx.tmmr, DS26528_TMMR_E1);
+ /* Receive E1 Mode Framer Enable (RMMR - Framer Enabled/E1)*/
+ out_8(&ds26528->link[phy_id].rx.rmmr,
+ DS26528_RMMR_FRM_EN | DS26528_RMMR_E1);
+ /* Transmit E1 Mode Framer Enable (TMMR - Framer Enabled/E1)*/
+ out_8(&ds26528->link[phy_id].tx.tmmr,
+ DS26528_TMMR_FRM_EN | DS26528_TMMR_E1);
+ /* RCR1, receive E1 B8zs & ESF (Receive Control Register 1 - E1 MODE)*/
+ out_8(&ds26528->link[phy_id].rx.rcr1,
+ DS26528_RCR1_E1_HDB3 | DS26528_RCR1_E1_CCS);
+ /* RIOCR (RSYSCLK=2.048MHz, RSYNC-Output) */
+ out_8(&ds26528->link[phy_id].rx.riocr,
+ DS26528_RIOCR_2048KHZ | DS26528_RIOCR_RSIO_OUT);
+ /* TCR1 Transmit E1 b8zs */
+ out_8(&ds26528->link[phy_id].tx.tcr[0], DS26528_TCR1_TB8ZS);
+ /* TIOCR (TSYSCLK=2.048MHz, TSYNC-Output) */
+ out_8(&ds26528->link[phy_id].tx.tiocr,
+ DS26528_TIOCR_2048KHZ | DS26528_TIOCR_TSIO_OUT);
+ /* Set E1TAF (Transmit Align Frame Register regsiter) */
+ out_8(&ds26528->link[phy_id].tx.e1taf, DS26528_E1TAF_DEFAULT);
+ /* Set E1TNAF register (Transmit Non-Align Frame Register) */
+ out_8(&ds26528->link[phy_id].tx.e1tnaf, DS26528_E1TNAF_DEFAULT);
+ /* Receive E1 Mode Framer Enable & init Done (RMMR) */
+ out_8(&ds26528->link[phy_id].rx.rmmr,
+ DS26528_RMMR_FRM_EN |
+ DS26528_RMMR_INIT_DONE |
+ DS26528_RMMR_E1);
+ /* Transmit E1 Mode Framer Enable & init Done (TMMR) */
+ out_8(&ds26528->link[phy_id].tx.tmmr,
+ DS26528_TMMR_FRM_EN |
+ DS26528_TMMR_INIT_DONE |
+ DS26528_TMMR_E1);
+ /* Configure LIU (LIU Transmit Receive Control Register
+ - LTRCR. E1 mode) */
+ out_8(&ds26528->liu[phy_id].ltrcr, DS26528_LTRCR_E1);
+ /* E1 Mode default 75 ohm w/Transmit Impedance Matlinking
+ (LIU Transmit Impedance and Pulse Shape Selection Register - LTITSR)*/
+ out_8(&ds26528->liu[phy_id].ltitsr,
+ DS26528_LTITSR_TLIS_75OHM | DS26528_LTITSR_LBOS_75OHM);
+ /* E1 Mode default 75 ohm Long Haul w/Receive Impedance Matlinking
+ (LIU Receive Impedance and Sensitivity Monitor Register - LRISMR)*/
+ out_8(&ds26528->liu[phy_id].lrismr,
+ DS26528_LRISMR_75OHM | DS26528_LRISMR_MAX);
+ /* Enable Transmit output (LIU Maintenance Control Register - LMCR) */
+ out_8(&ds26528->liu[phy_id].lmcr, DS26528_LMCR_TE);
+}
+
+int ds26528_t1_e1_config(struct pq_mds_t1 *pq_mds_t1_info, u8 phy_id)
+{
+ struct pq_mds_t1 *card_info = pq_mds_t1_info;
+
+ ds26528_bulk_write_set(card_info);
+ ds26528_gbl_sreset(card_info);
+ switch (card_info->line_rate) {
+ case LINE_RATE_T1:
+ card_pld_t1_clk_set(card_info);
+ break;
+ case LINE_RATE_E1:
+ card_pld_e1_clk_set(card_info);
+ break;
+ default:
+ dev_err(pq_mds_t1_info->dev,
+ "Support E1/T1. Frame mode not support.\n");
+ return -ENODEV;
+ break;
+ }
+ ds26528_rx_tx_sreset(card_info, phy_id);
+ ds26528_frame_regs_clear(card_info, phy_id);
+ ds26528_trans_mode_set(card_info, phy_id);
+
+ switch (card_info->line_rate) {
+ case LINE_RATE_T1:
+ ds26528_t1_spec_config(card_info, phy_id);
+ break;
+ case LINE_RATE_E1:
+ ds26528_e1_spec_config(card_info, phy_id);
+ break;
+ default:
+ dev_err(pq_mds_t1_info->dev,
+ "Support E1/T1. Frame mode not support\n");
+ return -ENODEV;
+ break;
+ }
+ ds26528_bulk_write_unset(card_info);
+
+ return 0;
+}
+
+static enum line_rate_t set_phy_line_rate(const char *line_rate)
+{
+ if (strcasecmp(line_rate, "e1") == 0)
+ return LINE_RATE_E1;
+ else
+ return LINE_RATE_T1;
+}
+
+static enum card_support_type set_card_support_type(const phandle *card_type)
+{
+ struct device_node *np;
+ enum card_support_type type;
+
+ np = of_find_node_by_phandle(*card_type);
+ if (!np)
+ return NO_CARD;
+
+ if (of_device_is_compatible(np, "dallas,ds26528"))
+ type = DS26528_CARD;
+ else
+ type = LM_CARD;
+
+ of_node_put(np);
+
+ return type;
+}
+
+static enum tdm_trans_mode_t set_phy_trans_mode(const char *trans_mode)
+{
+ if (strcasecmp(trans_mode, "framer-loopback") == 0)
+ return FRAMER_LB;
+ else
+ return NORMAL;
+}
+
+static int pq_mds_t1_probe(struct platform_device *pdev)
+{
+ int err = 0;
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *child;
+ struct resource res;
+ struct pq_mds_t1 *t1_info;
+ const unsigned char *prop;
+ const phandle *ph;
+
+ t1_info = kzalloc(sizeof(struct pq_mds_t1), GFP_KERNEL);
+ if (!t1_info) {
+ dev_err(&pdev->dev, "No memory to alloc pq_mds_t1\n");
+ return -ENOMEM;
+ }
+ dev_set_drvdata(&pdev->dev, t1_info);
+ t1_info->dev = &pdev->dev;
+
+ for_each_child_of_node(np, child)
+ if (of_device_is_compatible(child, "fsl,pq-mds-t1-pld"))
+ break;
+ if (!child) {
+ dev_err(&pdev->dev, "Invalid fsl,pq-mds-t1-pld property\n");
+ err = -ENODEV;
+ goto err_miss_pld_property;
+ }
+
+ err = of_address_to_resource(child, 0, &res);
+ if (err) {
+ err = -ENODEV;
+ goto err_miss_pld_property;
+ }
+ t1_info->pld_base = ioremap(res.start, res.end - res.start + 1);
+
+ ph = of_get_property(child, "fsl,card-support", NULL);
+ if (!ph) {
+ err = -ENODEV;
+ dev_err(&pdev->dev, "Invalid card-support property\n");
+ goto err_miss_pld_property;
+ }
+
+ t1_info->card_support = set_card_support_type(ph);
+ if (t1_info->card_support == NO_CARD) {
+ dev_err(&pdev->dev, "Couldn't get tdm phy phandle\n");
+ err = -ENODEV;
+ goto err_miss_pld_property;
+ }
+
+ for_each_child_of_node(np, child)
+ if (of_device_is_compatible(child, "dallas,ds26528"))
+ break;
+
+ if (!child) {
+ dev_err(&pdev->dev, "Invalid dallas,ds26528 property\n");
+ err = -ENODEV;
+ goto err_miss_phy_property;
+
+ }
+
+ err = of_address_to_resource(child, 0, &res);
+ if (err) {
+ err = -ENODEV;
+ goto err_miss_phy_property;
+ }
+
+ t1_info->ds26528_base = ioremap(res.start, res.end - res.start + 1);
+
+ err = pq_mds_t1_connected(t1_info);
+ if (err) {
+ err = -ENODEV;
+ dev_err(&pdev->dev, "No PQ_MDS_T1 CARD\n");
+ goto err_card_unplugin;
+ }
+
+ prop = of_get_property(child, "line-rate", NULL);
+ if (!prop) {
+ err = -ENODEV;
+ dev_err(&pdev->dev, "Invalid line-rate property\n");
+ goto err_card_unplugin;
+ }
+
+ t1_info->line_rate = set_phy_line_rate(prop);
+
+ prop = of_get_property(child, "trans-mode", NULL);
+ if (!prop) {
+ err = -ENODEV;
+ dev_err(&pdev->dev, "Invalid trans-mode property\n");
+ goto err_card_unplugin;
+ }
+ t1_info->trans_mode = set_phy_trans_mode(prop);
+
+ pq_mds_t1_clock_set(t1_info);
+ if (t1_info->card_support == DS26528_CARD)
+ ds26528_t1_e1_config(t1_info, 0);
+
+ dev_info(&pdev->dev, "registed pq-mds-t1 card\n");
+
+ return 0;
+
+err_card_unplugin:
+ iounmap(t1_info->ds26528_base);
+err_miss_phy_property:
+ iounmap(t1_info->pld_base);
+err_miss_pld_property:
+ kfree(t1_info);
+
+ return err;
+}
+
+static int pq_mds_t1_remove(struct platform_device *pdev)
+{
+ struct pq_mds_t1 *t1_info = dev_get_drvdata(&pdev->dev);
+
+ iounmap(t1_info->pld_base);
+ iounmap(t1_info->ds26528_base);
+ kfree(t1_info);
+
+ return 0;
+}
+
+static struct of_device_id pq_mds_t1_of_match[] = {
+ { .compatible = "fsl,pq-mds-t1" },
+ {},
+};
+
+static struct platform_driver pq_mds_t1_driver = {
+ .probe = pq_mds_t1_probe,
+ .remove = pq_mds_t1_remove,
+ .driver = {
+ .name = "pq_mds_t1",
+ .owner = THIS_MODULE,
+ .of_match_table = pq_mds_t1_of_match,
+ },
+};
+
+static int __init pq_mds_t1_init(void)
+{
+ return platform_driver_register(&pq_mds_t1_driver);
+}
+
+static void __exit pq_mds_t1_exit(void)
+{
+ platform_driver_unregister(&pq_mds_t1_driver);
+}
+
+MODULE_AUTHOR("Jiang Kai");
+MODULE_DESCRIPTION("Freescale Developed PQ_MDS_T1CARD Driver");
+MODULE_LICENSE("GPL");
+
+module_init(pq_mds_t1_init);
+module_exit(pq_mds_t1_exit);
diff --git a/drivers/tdm/line_ctrl/pq_mds_t1.h b/drivers/tdm/line_ctrl/pq_mds_t1.h
new file mode 100644
index 0000000..2c1eb82
--- /dev/null
+++ b/drivers/tdm/line_ctrl/pq_mds_t1.h
@@ -0,0 +1,424 @@
+/*
+ * drivers/tdm/line/pq_mds_t1.h
+ *
+ * Copyright 2011-2012 Freescale Semiconductor, Inc.
+ *
+ * Author: Kai Jiang <Kai.Jiang@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#define MAX_NUM_OF_CHANNELS 8
+#define PQ_MDS_8E1T1_BRD_REV 0x00
+#define PQ_MDS_8E1T1_PLD_REV 0x00
+
+#define PLD_PINSET_DIGIOEN 0x01 /* Normal operation */
+#define PLD_PINSET_TXEN 0x02 /* drive TTIP and TRING with data */
+
+#define PLD_CSR_RCSRC_1544KHZ 0x00 /* Drive REFCLKIO with the
+ 1.544MHz clock */
+#define PLD_CSR_MSRC_1544KHZ 0x00 /* Drive MCLK with the 1.544MHz clock */
+#define PLD_CSR_MSRC_2048KHZ 0x01 /* Drive MCLK with the 2.048MHz clock */
+#define PLD_CSR_RCSRC_2048KHZ 0x40 /* DDrive REFCLKIO with the
+ 2.048MHz clock */
+
+#define PLD_SYSCLK_RS_1544KHZ 0x00 /* Drive RSYSCLK with the
+ 1.544MHz clock */
+#define PLD_SYSCLK_TS_1544KHZ 0x00 /* Drive TSYSCLK with the
+ 1.544MHz clock */
+#define PLD_SYSCLK_TS_2048KHZ 0x01 /* Drive TSYSCLK with the
+ 2.048MHz clock */
+#define PLD_SYSCLK_RS_2048KHZ 0x40 /* Drive RSYSCLK with the
+ 2.048MHz clock */
+
+#define PLD_SYNCTSS_TRI_STATE 0x00 /* Not using transmit-side
+ elastic store */
+
+#define PLD_TCSR1_1544KHZ 0x00 /* Drive TCLK1 - TCLK4 with
+ the 1.544MHz clock */
+#define PLD_TCSR2_1544KHZ 0x00 /* Drive TCLK5 - TCLK8 with
+ the 1.544MHz clock */
+#define PLD_TCSR1_2048KHZ 0x55 /* Drive TCLK1 - TCLK4 with
+ the 2.048MHz clock */
+#define PLD_TCSR2_2048KHZ 0x55 /* Drive TCLK5 - TCLK8 with
+ the 2.048MHz clock */
+
+#define PLD_GCR_LCC_TDMA 0x40 /* LM card connected to Host TDM
+ channel A */
+#define PLD_GCR_LCE_LM 0x02 /* Drive Line Module Le71HR0826 with
+ the T1/E1 framer BPCLK signal */
+
+#define DS26528_GTCCR_BPREFSEL_REFCLKIN 0xa0 /* REFCLKIO is an input */
+#define DS26528_GTCCR_BFREQSEL_1544KHZ 0x08 /* Backplane reference clock
+ is 1.544MHz */
+#define DS26528_GTCCR_FREQSEL_1544KHZ 0x04 /* The external master clock
+ is 1.544MHz or multiple
+ thereof */
+#define DS26528_GTCCR_BFREQSEL_2048KHZ 0x00 /* Backplane reference clock
+ is 2.048MHz */
+#define DS26528_GTCCR_FREQSEL_2048KHZ 0x00 /* The external master clock is
+ 2.048MHz or multiple thereof
+ */
+
+#define DS26528_GFCR_BPCLK_2048KHZ 0x00 /* Backplane Clock Select
+ 2.048MHz */
+
+#define DS26528_GTCR2_TSSYNCOUT 0x02 /* the TSSYNCIO is an 8kHz output
+ synchronous to the BPCLK */
+#define DS26528_GTCR1_BWE 0x04 /* a port write to one of the octal
+ ports is mapped into all eight ports
+ */
+
+#define DS26528_GFSRR_Reset 0xff /* Reset framer and BERT */
+#define DS26528_GFSRR_NORMAL 0x00 /* Normal operation */
+
+#define DS26528_GLSRR_Reset 0xff /* Reset LIU */
+#define DS26528_GLSRR_NORMAL 0x00 /* Normal operation */
+
+#define DS26528_RMMR_SFTRST 0x02 /* Level sensitive soft reset */
+#define DS26528_RMMR_FRM_EN 0x80 /* Framer enabled—all features
+ active */
+#define DS26528_RMMR_INIT_DONE 0x40 /* Initialization Done */
+#define DS26528_RMMR_T1 0x00 /* Receiver T1 Mode Select */
+#define DS26528_RMMR_E1 0x01 /* Receiver E1 Mode Select */
+
+#define DS26528_E1TAF_DEFAULT 0x1b /* Transmit Align Frame Register */
+#define DS26528_E1TNAF_DEFAULT 0x40 /* Transmit Non-Align Frame Register */
+
+#define DS26528_TMMR_SFTRST 0x02 /* Level sensitive soft reset */
+#define DS26528_TMMR_FRM_EN 0x80 /* Framer enabled—all features
+ active */
+#define DS26528_TMMR_INIT_DONE 0x40 /* Initialization Done */
+#define DS26528_TMMR_T1 0x00 /* Transmit T1 Mode Select */
+#define DS26528_TMMR_E1 0x01 /* Transmit E1 Mode Select */
+
+#define DS26528_RCR1_T1_SYNCT 0x80 /* qualify 24 bits */
+#define DS26528_RCR1_T1_RB8ZS 0x40 /* B8ZS enabled */
+#define DS26528_RCR1_T1_SYNCC 0x08 /* cross couple Ft and Fs pattern */
+
+#define DS26528_RCR1_E1_HDB3 0x40 /* Receive HDB3 enabled */
+#define DS26528_RCR1_E1_CCS 0x20 /* Receive CCS signaling mode */
+
+#define DS26528_RIOCR_1544KHZ 0x00 /* RSYSCLK Mode Select is 1.544MHz */
+#define DS26528_RIOCR_2048KHZ 0x10 /* RSYSCLK Mode Select is 2.048MHz or
+ IBO enabled */
+#define DS26528_RIOCR_RSIO_OUT 0x00 /* RSYNC is an output */
+
+#define DS26528_RCR3_FLB 0x01 /* Framer Loopback enabled */
+
+#define DS26528_TIOCR_1544KHZ 0x00 /* TSYSCLK is 1.544MHz */
+#define DS26528_TIOCR_2048KHZ 0x10 /* TSYSCLK is 2.048/4.096/8.192MHz or
+ IBO enabled */
+#define DS26528_TIOCR_TSIO_OUT 0x04 /* TSYNC is an output */
+
+#define DS26528_TCR1_TB8ZS 0x04 /* Transmit B8ZS Enable */
+
+#define DS26528_LTRCR_T1 0x02 /* configures the LIU for T1 */
+#define DS26528_LTRCR_E1 0x00 /* configures the LIU for E1 */
+
+#define DS26528_LTITSR_TLIS_75OHM 0x00 /* Transmit Load
+ Impedance 75? */
+#define DS26528_LTITSR_LBOS_75OHM 0x00 /* Transmit Pulse
+ Shape 75? */
+#define DS26528_LTITSR_TLIS_100OHM 0x10 /* Transmit Load
+ Impedance 100? */
+#define DS26528_LTITSR_TLIS_0DB_CSU 0x00 /* DSX-1/0dB CSU,
+ 0ft–133ft ABAM 100? */
+
+#define DS26528_LRISMR_75OHM 0x00 /* Receive Impedance 75? */
+#define DS26528_LRISMR_100OHM 0x10 /* Receive Impedance 100? */
+#define DS26528_LRISMR_MAX 0x03 /* Receive Impedance 120? */
+
+#define DS26528_LMCR_TE 0x01 /* TTIP/TRING outputs enabled */
+
+/*Global register used to configure the Slic Slac in E1 and T1 mode*/
+struct global_reg {
+ /*Occupied addresses from 0F0 to 0FF*/
+ u8 gtcr1; /* 0x0f0 - Global Transceiver Control Reg 1 */
+ u8 gfcr; /* 0x0f1 - Global Framer Control Reg */
+ u8 gtcr2; /* 0x0f2 - Global Transceiver Control Reg 2 */
+ u8 gtccr; /* 0x0f3 - Global Transciever Clock Control Reg */
+ u8 res1; /* 0x0f4 - Reserved */
+ u8 glsrr; /* 0x0f5 - Global LIU Software Reset Reg */
+ u8 gfsrr; /* 0x0f6 - Global Framer and BERT Software Reset Reg */
+ u8 res2; /* 0x0f7 - Reserved */
+ u8 idr; /* 0x0f8 - Device Identification Reg */
+ u8 gfisr; /* 0x0f9 - Global Framers Interrupt Status Reg */
+ u8 gbisr; /* 0x0fa - Global BERT Interrupt Status Reg */
+ u8 glisr; /* 0x0fb - Global LIU Interrupt Status Reg */
+ u8 gfimr; /* 0x0fc - Global Framers Interrupt Mask Reg */
+ u8 gbimr; /* 0x0fd - Global BERT Interrupt Mask Reg */
+ u8 glimr; /* 0x0fe - Global LIU Interrupt Mask Reg */
+ u8 res3; /* 0x0ff - Reseved */
+};
+
+/*Registers that control the Receive Framer in E1 Mode and T1 Mode*/
+struct rx_frame {
+ /*Occupied addresses from 000 to 0EF*/
+ u8 res1[16]; /* 0x000 - 0x00f Reserved */
+ u8 rhc; /* 0x010 - Receive HDLC Control Reg */
+ u8 rhbse; /* 0x011 - Receive HDLC Bit Suppress Reg */
+ u8 rds0sel; /* 0x012 - Receive Channel Monitor Select Reg */
+ u8 rsigc; /* 0x013 - Receive-Signaling Control Reg */
+ u8 rsaimr; /* 0x014 - Receive Control Register 2 (T1 Mode)
+ Receive Sa-Bit Interrupt Mask Register
+ (E1 Mode) */
+ u8 t1rbocc; /* 0x015 - Receive BOC Ccontrol Reg(T1 Mode Only) */
+ u8 res2[10]; /* 0x016 - 0x01f Reserved */
+ u8 ridr[32]; /* 0x020 - 0x03f Receive Idle Definition 32 Reg
+ For E1 framming */
+ u8 rs[16]; /* 0x040 - 0x04f RxSignaling[16] For E1 framming*/
+ u8 lcvcr1; /* 0x050 - Line Code Violation Count Reg 1 */
+ u8 lcvcr2; /* 0x051 - Line Code Violation Count Reg 2 */
+ u8 pcvcr1; /* 0x052 - Path Code Violation Count Reg 1 */
+ u8 pcvcr2; /* 0x053 - Path Code Violation Count Reg 2 */
+ u8 foscr1; /* 0x054 - Frame Out of Sync Count Reg 1 */
+ u8 foscr2; /* 0x055 - Frame Out of Sync Count Reg 2 */
+ u8 e1ebcr1; /* 0x056 - E1-Bit Counter 1(E1 Mode Only) */
+ u8 e1ebcr2; /* 0x057 - E1-Bit Counter 2(E1 Mode Only) */
+ u8 res3[8]; /* 0x058 - 0x05f Reserved */
+ u8 rds0m; /* 0x060 - Receive DS0 Monitor Reg */
+ u8 e1rfrid; /* 0x061 - Receive Firmware Revision ID Register
+ (E1 Mode Only)*/
+ u8 e1rrts7; /* 0x062 - Receive FDL Register (T1 Mode)
+ Receive Real-Time Status Register 7
+ (E1 Mode) */
+ u8 t1rboc; /* 0x063 - Receive BOC Register(T1 Mode) */
+ u8 e1raf; /* 0x064 - Receive SLC-96 Data Link Register 1(T1 Mode)
+ E1 Receive Align Frame Register (E1 Mode) */
+ u8 e1rnaf; /* 0x065 - Receive SLC-96 Data Link Register 2(T1 Mode)
+ E1 Receive Non-Align Frame Register
+ (E1 Mode) */
+ u8 e1rsiaf; /* 0x066 - Receive SLC-96 Data Link Register 3(T1 Mode)
+ E1 Received Si Bits of the Align
+ Frame Register (E1 Mode)*/
+ u8 e1rsinaf; /* 0x067 - Receive Si Bit of Non-Align Frame Reg
+ (E1 Mode) */
+ u8 e1rra; /* 0x068 - Receive Remote Alarm Reg (E1 Mode) */
+ u8 e1rsa[6]; /* 0x069 - 0x06e E1 Receive Sa Bits Reg
+ (E1 Mode Only) */
+ u8 sa6code; /* 0x06f - Received Sa6 Codeword Reg */
+ u8 res5[16]; /* 0x070 - 0x07f Reserved */
+ u8 rmmr; /* 0x080 - Receive Master Mode Reg */
+ u8 rcr1; /* 0x081 - Receive Control Reg 1 */
+ u8 rcr2; /* 0x082 - Receive Control Reg 2 */
+ u8 rcr3; /* 0x083 - Receive Control Reg 3 */
+ u8 riocr; /* 0x084 - Receive I/O Config Reg */
+ u8 rescr; /* 0x085 - Receive Elastic Store Control Reg */
+ u8 ercnt; /* 0x086 - Error-Counter Config Reg */
+ u8 rhfc; /* 0x087 - Receive HDLC FIFO Control Reg */
+ u8 riboc; /* 0x088 - Receive Interleave Bus Operation
+ Control Reg */
+ u8 t1rscc; /* 0x089 - In-Band Receive Spare Control Register
+ (T1 Mode Only)*/
+ u8 rxpc; /* 0x08a - Receive Expansion Port Control Reg */
+ u8 rbpbs; /* 0x08b - Receive BERT Port Bit Suppress Reg */
+ u8 res6[4]; /* 0x08c - 0x08f Reserved */
+ u8 rls[7]; /* 0x090 - 0x096 Receive Latched Status Reg */
+ u8 res8; /* 0x097 - Reserved */
+ u8 rss[4]; /* 0x098 - 0x09b Receive-Signaling Status Reg */
+ u8 t1rscd[2]; /* 0x09c - 0x09d Receive Spare Code Definition Reg
+ (T1 Mode Only) */
+ u8 res9; /* 0x09e - Reserved */
+ u8 riir; /* 0x09f - Receive Interrupt Information Reg */
+ u8 rim[7]; /* 0x0a0 - 0x0a6 Receive Interrupt Mask[7] */
+ u8 res10; /* 0x0a7 - Reserved */
+ u8 rscse[4]; /* 0x0a8 - 0x0ab Receive-Signaling Change of
+ State Enable[4] */
+ u8 t1rupcd[2]; /* 0x0ac - 0x0ad Receive Up Code Definition[2]
+ (T1 mode only) */
+ u8 t1rdncd[2]; /* 0x0ae - 0x0af Receive Down Code Definition[2]
+ (T1 mode only) */
+ u8 rrts1; /* 0x0b0 - Receive Real-Time Status Reg 1 */
+ u8 res11; /* 0x0b1 - Reserved */
+ u8 rrts3; /* 0x0b2 - Receive Real-Time Status Reg 3 */
+ u8 res12; /* 0x0b3 - Reserved */
+ u8 rrts5; /* 0x0b4 - Receive Real-Time Status Reg 5 */
+ u8 rhpba; /* 0x0b5 - Receive HDLC Packet Bytes Available Reg */
+ u8 rhf; /* 0x0b6 - Receive HDLC FIFO Reg */
+ u8 res13[9]; /* 0x0b7 - 0x0bf Reserved */
+ u8 rbcs[4]; /* 0x0c0 - 0x0c3 Receive Blank Channel Select[4] */
+ u8 rcbr[4]; /* 0x0c4 - 0x0c7 Receive Channel Blocking[4] */
+ u8 rsi[4]; /* 0x0c8 - 0x0cb Receive-Signalling Reinsertion[4]
+ Enable Reg */
+ u8 rgccs[4]; /* 0x0cc - 0x0cf Receive Gapped Clock Channel
+ Select[4] Reg */
+ u8 rcice[4]; /* 0x0d0 - 0x0d3 Receive Channel Idle Code
+ Enable[4] Reg */
+ u8 rbpcs[4]; /* 0x0d4 - 0x0d7 Receive BERT Port Channel
+ Select[4] Reg */
+ u8 res14[24]; /* 0x0d8 - 0x0ef Reserved */
+};
+
+struct tx_frame {
+ /*Occupied addresses from 100 to 1FF */
+ u8 res1[16]; /* 0x100 - 0x10f */
+ u8 thc1; /* 0x110 - Transmit HDLC Control Reg 1 */
+ u8 thbse; /* 0x111 - Transmit HDLC Bit Suppress Reg */
+ u8 res2; /* 0x112 - Reserved */
+ u8 thc2; /* 0x113 - Transmit HDLC Control Reg 2 */
+ u8 e1tsacr; /* 0x114 - E1 Transmit Sa-Bit Control Reg (E1 Mode) */
+ u8 res3[3]; /* 0x115 - 0x117 Reserved */
+ u8 ssie[4]; /* 0x118 - 0x11b E1 Transmit Sa-Bit Control Reg
+ (E1 Mode) */
+ u8 res4[4]; /* 0x11c - 0x11f Reserved */
+ u8 tidr[32]; /* 0x120 - 0x13f Transmit Idle Code Definition */
+ u8 ts[16]; /* 0x140 - 0x14f Transmit-Signaling Reg */
+ u8 tcice[4]; /* 0x150 - 0x153 Transmit Channel Idle Code
+ Enable Reg */
+ u8 res5[13]; /* 0x154 - 0x160 Reserved */
+ u8 tfrid; /* 0x161 - Transmit Firmware Revision ID Register*/
+ u8 tfdl; /* 0x162 - Transmit FDL Register (T1 Mode Only) */
+ u8 tboc; /* 0x163 - Transmit BOC Register (T1 Mode Only) */
+ u8 e1taf; /* 0x164 - Transmit SLC-96 Data Link Register 1
+ (T1 Mode)
+ Transmit Align Frame Register (E1 Mode) */
+ u8 e1tnaf; /* 0x165 - Transmit SLC-96 Data Link Register 2
+ (T1 Mode)
+ Transmit Non-Align Frame Register(E1 Mode)*/
+ u8 e1tsiaf; /* 0x166 - Transmit SLC-96 Data Link Register 3(T1 Mode)
+ Transmit Si Bits of the Align Frame Register
+ (E1 Mode) */
+ u8 e1tsinaf; /* 0x167 - Transmit Si Bits of the Non-Align
+ Frame Register (E1 Mode Only) */
+ u8 e1tra; /* 0x168 - Transmit Remote Alarm Register (E1 Mode) */
+ u8 e1tsa[5]; /* 0x169 - 0x16d Transmit Sa Bits Register
+ (E1 Mode Only)*/
+ u8 res6[18]; /* 0x16e - 0x17f Reserved */
+ u8 tmmr; /* 0x180 - Transmit Master Mode Register */
+ u8 tcr[3]; /* 0x181 - 0x183 Transmit Control Register */
+ u8 tiocr; /* 0x184 - Transmit I/O Configuration Register */
+ u8 tescr; /* 0x185 - Transmit Elastic Store Control Register */
+ u8 tcr4; /* 0x186 - Transmit Control Register 4 (T1 Mode Only)*/
+ u8 thfc; /* 0x187 - Transmit HDLC FIFO Control Register */
+ u8 tiboc; /* 0x188 - Transmit Interleave Bus Operation
+ Control Register */
+ u8 tds0sel; /* 0x189 - Transmit DS0 Channel Monitor Select
+ Register */
+ u8 txpc; /* 0x18a - Transmit Expansion Port Control Register */
+ u8 tbpbs; /* 0x18b - Transmit BERT Port Bit Suppress Register */
+ u8 res7[2]; /* 0x18c - 0x18d Reserved */
+ u8 tsyncc; /* 0x18e - Transmit Synchronizer Control Register */
+ u8 res8; /* 0x18f - Reserved */
+ u8 tls[3]; /* 0x190 - 0x192 Transmit Latched Status Register*/
+ u8 res9[12]; /* 0x193 - 0x19e Reserved*/
+ u8 tiir; /* 0x19f - Transmit Interrupt Information Register*/
+ u8 tim[3]; /* 0x1a0 - 0x1a2 Transmit Interrupt Mask Register */
+ u8 res10[9]; /* 0x1a3 - 0x1ab Reserved */
+ u8 titcd[2]; /* 0x1ac - 0x1ad Transmit Code Definition Register */
+ u8 res11[3]; /* 0x1ae - 0x1b0 Reserved */
+ u8 trts2; /* 0x1b1 - Transmit Real-Time Status Register 2(HDLC)*/
+ u8 res12; /* 0x1b2 - Reserved */
+ u8 tfba; /* 0x1b3 - Transmit HDLC FIFO Buffer Available */
+ u8 thf; /* 0x1b4 - Transmit HDLC FIFO Register */
+ u8 res13[6]; /* 0x1b5 - 0x1ba Reserved */
+ u8 tds0m; /* 0x1bb - Transmit DS0 Monitor Register */
+ u8 res14[4]; /* 0x1bc - 0x1bf Reserved */
+ u8 tbcs[4]; /* 0x1c0 - 0x1c3 Transmit Blank Channel
+ Select Register */
+ u8 tcbr[4]; /* 0x1c4 - 0x1c7 Transmit Channel Blocking Register */
+ u8 thscs[4]; /* 0x1c8 - 0x1cb Transmit Hardware-Signaling Channel
+ Select Register */
+ u8 tgccs[4]; /* 0x1cc - 0x1cf Transmit Gapped-Clock Channel
+ Select Register */
+ u8 pcl[4]; /* 0x1d0 - 0x1d3 Per-Channel Loopback Enable Register */
+ u8 tbpcs[4]; /* 0x1d4 - 0x1d7 Transmit BERT Port Channel
+ Select Register */
+ u8 res15[40]; /* 0x1d8 - 0x1ff Reserved */
+};
+
+struct liu_reg {
+ /*Occupied addresses from 1000 to 101F*/
+ u8 ltrcr; /* 0x1000 - LIU Transmit Receive Control Register */
+ u8 ltitsr; /* 0x1001 - LIU Transmit Impedance and Pulse Shape
+ Selection Register */
+ u8 lmcr; /* 0x1002 - LIU Maintenance Control Register */
+ u8 lrsr; /* 0x1003 - LIU Real Status Register */
+ u8 lsimr; /* 0x1004 - LIU Status Interrupt Mask Register */
+ u8 llsr; /* 0x1005 - LIU Latched Status Register */
+ u8 lrsl; /* 0x1006 - LIU Receive Signal Level Register */
+ u8 lrismr; /* 0x1007 - LIU Receive Impedance and Sensitivity
+ Monitor Register */
+ u8 res1[24]; /* 0x1008 - 0x101f Reserved */
+};
+
+struct bert_reg {
+ /*Occupied addresses from 1100 to 110F*/
+ u8 bawc; /* 0x1100 - BERT Alternating Word Count Rate Register*/
+ u8 brp[4]; /* 0x1101 - 0x1104 BERT Repetitive Pattern
+ Set Register */
+ u8 bc[2]; /* 0x1105 - 0x1106 BERT Control Register */
+ u8 bbc[4]; /* 0x1107 - 0x110a BERT Bit Count Register */
+ u8 bec[3]; /* 0x110b - 0x110d BERT Error Count Register */
+ u8 blsr; /* 0x110e - BERT Latched Status Register */
+ u8 bsim; /* 0x110f - BERT Status Interrupt Mask Register */
+};
+
+struct link_frame {
+ struct rx_frame rx; /*Receive Framer Settings*/
+ struct global_reg gbl;
+ struct tx_frame tx; /*Transmit Framer Registers*/
+};
+
+/* Definition of strucute of the framers */
+struct ds26528_mem {
+ struct link_frame link[MAX_NUM_OF_CHANNELS];
+ struct liu_reg liu[MAX_NUM_OF_CHANNELS];
+ struct bert_reg bert[MAX_NUM_OF_CHANNELS];
+};
+
+struct pld_mem {
+ u8 brdid;
+ u8 brdrev;
+ u8 pldrev;
+ u8 pinset;
+ u8 csr;
+ u8 sysclk_tr;
+ u8 synctss;
+ u8 tcsr1;
+ u8 tcsr2;
+ u8 tsyncs1;
+ u8 ds3set;
+ u8 gcr;
+ u8 rsv[4];
+};
+
+enum line_rate_t {
+ LINE_RATE_T1, /* T1 line rate (1.544 Mbps) */
+ LINE_RATE_E1 /* E1 line rate (2.048 Mbps) */
+};
+
+enum tdm_trans_mode_t {
+ NORMAL = 0,
+ FRAMER_LB
+};
+
+enum card_support_type {
+ LM_CARD = 0,
+ DS26528_CARD,
+ NO_CARD
+};
+
+struct pq_mds_t1 {
+ int irq;
+ struct device *dev;
+ struct ds26528_mem *ds26528_base;
+ struct pld_mem *pld_base;
+ enum tdm_trans_mode_t trans_mode;
+ enum line_rate_t line_rate;
+ enum card_support_type card_support;
+};
diff --git a/drivers/tdm/line_ctrl/slic_zarlink.c b/drivers/tdm/line_ctrl/slic_zarlink.c
new file mode 100644
index 0000000..6aa562c0
--- /dev/null
+++ b/drivers/tdm/line_ctrl/slic_zarlink.c
@@ -0,0 +1,679 @@
+/*
+ * drivers/tdm/line_ctrl/slic_zarlink.c
+ *
+ * Copyright (C) 2008-2012 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * SLIC Line Control Module for Zarlink SLICs.
+ * This is a slic control and initialization module.
+ *
+ * Author:Poonam Aggrwal<poonam.aggrwal@freescale.com>
+ * Hemant Agrawal <hemant@freescale.com>
+ * Rajesh Gumasta <rajesh.gumasta@freescale.com>
+ *
+ * Modified by Sandeep Kr Singh <sandeep@freescale.com>
+ * 1. Changed SPI cmnds to restrict transaction length to 1 byte.
+ * 2. Updated probe which now does not relies on modalias.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This driver was created solely by Freescale, without the assistance,
+ * support or intellectual property of Zarlink Semiconductor. No maintenance
+ * or support will be provided by Zarlink Semiconductor regarding this driver
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+ /* Note that this is a complete rewrite of Poonam's slic code.
+ But we have used so much of her original code and ideas that it seems
+ only fair to recognize her as co-author -- Rajesh & Hemant */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+#include <linux/spi/spi.h>
+#include <linux/wait.h>
+#include <linux/param.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include "slic_zarlink.h"
+
+#define DRV_DESC "FREESCALE DEVELOPED ZARLINK SLIC DRIVER"
+#define DRV_NAME "legerity"
+
+#define MAX_NUM_OF_SLICS 10
+#define SLIC_TRANS_LEN 1
+
+#define TESTING_PRODUCT_CODE
+
+static struct spi_device *g_spi;
+struct spi_transfer t;
+
+struct slic_channel {
+ unsigned int ch1_rx_slot, ch1_tx_slot, ch2_rx_slot, ch2_tx_slot;
+};
+struct slic_channel slic_ch[MAX_NUM_OF_SLICS];
+static int num_slics;
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Poonam Aggrwal<poonam.aggrwal@freescale.com>");
+MODULE_DESCRIPTION(DRV_DESC);
+
+static void
+slic_cmd(struct spi_device *spi, unsigned char channel, unsigned char cmd,
+ unsigned char len, unsigned char *cmdData)
+{
+ unsigned char ecCmd = WRITE_CHANNEL_ENABLE;
+ unsigned char cmdLen;
+
+ /* Write EC command */
+ spi_write(spi, &ecCmd, SLIC_TRANS_LEN);
+
+ /* write EC value */
+ spi_write(spi, &channel, SLIC_TRANS_LEN);
+
+ /* write command */
+ spi_write(spi, &cmd, SLIC_TRANS_LEN);
+
+ /* If read command or write command */
+ if (cmd & 0x01) {
+ for (cmdLen = 0; cmdLen < len; cmdLen++)
+ spi_read(spi, &cmdData[cmdLen], SLIC_TRANS_LEN);
+ }
+ else {
+ for (cmdLen = 0; cmdLen < len; cmdLen++)
+ spi_write(spi, &cmdData[cmdLen], SLIC_TRANS_LEN);
+ }
+}
+
+static void get_slic_product_code(struct spi_device *spi)
+{
+ u8 tx = READ_PRODUCT_CODE;
+ u8 rx = 0x00;
+
+ spi_write(spi, &tx, SLIC_TRANS_LEN);
+ spi_read(spi, &rx, SLIC_TRANS_LEN);
+ printk(KERN_INFO "SLIC: product code 1 read is %x\n", rx);
+
+ spi_read(spi, &rx, SLIC_TRANS_LEN);
+ printk(KERN_INFO "SLIC: product code 2 read is %x\n", rx);
+
+ tx = WRITE_CHANNEL_ENABLE;
+ spi_write(spi, &tx, SLIC_TRANS_LEN);
+ spi_read(spi, &rx, SLIC_TRANS_LEN);
+ printk(KERN_INFO "SLIC: config read is %x\n", rx);
+
+ tx = READ_DEVICE_CONFIGURATION;
+ spi_write(spi, &tx, SLIC_TRANS_LEN);
+ spi_read(spi, &rx, SLIC_TRANS_LEN);
+ printk(KERN_INFO "SLIC: config read is %x\n", rx);
+
+ return;
+}
+
+static int slic_init_configure(unsigned char *device_handle,
+ struct spi_device *spi, int slic_id)
+{
+ char temp1 = 0;
+ char temp2[2];
+ char temp3[3];
+ unsigned char cad[4];
+ unsigned char len;
+ unsigned char channel_id;
+
+ temp3[0] = 0x04;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, HW_RESET, len, &temp3[0]);
+
+#ifdef TESTING_PRODUCT_CODE
+ get_slic_product_code(spi);
+#endif
+ temp3[0] = 0x82;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_DEVICE_CFG, len, &temp3[0]);
+
+ temp3[0] = 0x7f;
+ temp3[1] = 0xff;
+ len = 0x02;
+ slic_cmd(spi, CHANNEL1, WRITE_INT_MASK, len, &temp3[0]);
+
+ temp3[0] = 0xff;
+ temp3[1] = 0xff;
+ len = 0x02;
+ slic_cmd(spi, CHANNEL1, WRITE_INT_MASK, len, &temp3[0]);
+
+ temp3[0] = 0x40;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_TXRXCLKSLOT_TXCLKEDGE, len,
+ &temp3[0]);
+
+ temp3[0] = 0x0;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_SYSTEM_STATE, len, &temp3[0]);
+
+ temp3[0] = 0x0;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL2, WRITE_SYSTEM_STATE, len, &temp3[0]);
+
+ /* Put the Switching regulators in disabled mode */
+ temp3[0] = 0x0;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_SWITCH_REGULATOR_CTRL, len,
+ &temp3[0]);
+
+ temp3[0] = 0x0;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_SWITCH_REGULATOR_CTRL, len,
+ &temp3[0]);
+
+ temp3[0] = 0x3;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_SYSTEM_STATE_CFG, len,
+ &temp3[0]);
+
+ temp3[0] = 0x0;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_SYSTEM_STATE, len, &temp3[0]);
+
+ temp3[0] = 0x3;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL2, WRITE_SYSTEM_STATE_CFG, len,
+ &temp3[0]);
+
+ temp3[0] = 0x0;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL2, WRITE_SYSTEM_STATE, len, &temp3[0]);
+
+ temp3[0] = 0x2b;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_SYSTEM_STATE, len, &temp3[0]);
+
+ temp3[0] = 0x80;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_OPERATING_FUNCTION, len,
+ &temp3[0]);
+
+ temp3[0] = 0xe0;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_OPERATING_CONDITIONS, len,
+ &temp3[0]);
+
+ temp3[0] = 0x1;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_CONVERTER_CFG, len, &temp3[0]);
+
+ /* Set Switching Paramenters as for Le88266
+ * 1. BSI[1:0] = 00b (sense pin VBL is SWVSY, VBH is SWVSZ)
+ * 2. SWFS[1:0] = 00b (setting frequency as 384kHz in high power mode)
+ * 3. SWYV[4:0] = 00101b (setting to -25V)
+ * 4. SWZV[4:0] = 00000b (setting to 0V)
+ */
+ temp3[0] = 0x00;
+ temp3[1] = 0x05;
+ temp3[2] = 0x00;
+ len = 0x03;
+ slic_cmd(spi, CHANNEL1, WRITE_SWITCH_REGULATOR_PARAMS, len,
+ &temp3[0]);
+
+ /* Put the Switching regulators in
+ * 1. Regulator Y & Z in low power state
+ * 2. Over voltage protection enabled
+ */
+ temp3[0] = 0x15;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_SWITCH_REGULATOR_CTRL, len,
+ &temp3[0]);
+
+ /* Wait 20ms before switching from low power to high power */
+ mdelay(20);
+
+ temp3[0] = 0x9;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_CONVERTER_CFG, len, &temp3[0]);
+
+ temp3[0] = 0xb;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_CONVERTER_CFG, len, &temp3[0]);
+
+ temp3[0] = 0xb;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_CONVERTER_CFG, len, &temp3[0]);
+
+ temp3[0] = 0x1;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_CONVERTER_CFG, len, &temp3[0]);
+
+ temp3[0] = 0x1;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL2, WRITE_CONVERTER_CFG, len, &temp3[0]);
+
+ temp3[0] = 0x2;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_CONVERTER_CFG, len, &temp3[0]);
+
+ temp3[0] = 0x2;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_CONVERTER_CFG, len, &temp3[0]);
+
+ temp3[0] = 0x3;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_CONVERTER_CFG, len, &temp3[0]);
+
+ temp3[0] = 0x3;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_CONVERTER_CFG, len, &temp3[0]);
+
+ /* Set Switching Paramenters as for Le88266
+ * 1. BSI[1:0] = 00b (sense pin VBL is SWVSY, VBH is SWVSZ)
+ * 2. SWFS[1:0] = 00b (setting frequency as 384kHz in high power mode)
+ * 3. SWYV[4:0] = 00101b (setting to -25V)
+ * 4. SWZV[4:0] = 00000b (setting to 0V)
+ */
+ temp3[0] = 0x00;
+ temp3[1] = 0x05;
+ temp3[2] = 0x00;
+ len = 0x03;
+ slic_cmd(spi, CHANNEL1, WRITE_SWITCH_REGULATOR_PARAMS, len,
+ &temp3[0]);
+
+ /* Put the Switching regulators in
+ * 1. Regulator Y & Z in high power state
+ * 2. Over voltage protection enabled
+ */
+ temp3[0] = 0x1f;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_SWITCH_REGULATOR_CTRL, len,
+ &temp3[0]);
+
+ /* Setting the channel specific parameters */
+ for (channel_id = CHANNEL1; channel_id <= CHANNEL2; channel_id++) {
+
+ /* Set the IO direction to Output - to energise the fxo
+ * relay */
+ temp3[0] = 0x1;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_IO_DIRECTION, len,
+ &temp3[0]);
+
+ temp3[0] = 0x0;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_IO_DATA, len,
+ &temp3[0]);
+
+ temp3[0] = 0x0;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_OPERATING_CONDITIONS,
+ len, &temp3[0]);
+
+ len = sizeof(dataset_cadenceTimer) / sizeof(unsigned char);
+ slic_cmd(spi, channel_id, WRITE_CADENCE_TIMER, len,
+ &dataset_cadenceTimer[0]);
+
+ temp3[0] = 0x2;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_SYSTEM_STATE_CFG,
+ len, &temp3[0]);
+
+ temp3[0] = 0xc0;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_OPERATING_CONDITIONS,
+ len, &temp3[0]);
+
+ temp3[0] = 0x0;
+ temp3[1] = 0x2;
+ len = 0x02;
+ slic_cmd(spi, channel_id, WRITE_DC_CALIBRATION, len,
+ &temp3[0]);
+
+ temp3[0] = 0x0;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_SYSTEM_STATE, len,
+ &temp3[0]);
+
+ len = sizeof(dataset_writeLoopParams) / sizeof(unsigned char);
+ slic_cmd(spi, channel_id,
+ WRITE_LOOP_SUPERVISION_PARAMS, len,
+ &dataset_writeLoopParams[0]);
+
+ temp3[0] = 0x13;
+ temp3[1] = 0x8;
+ len = 0x02;
+ slic_cmd(spi, channel_id, WRITE_DC_FEED_PARAMS, len,
+ &temp3[0]);
+
+ len = sizeof(dataset1_for_nooperation) / sizeof(unsigned char);
+ slic_cmd(spi, channel_id, WRITE_NO_OPERATION, len,
+ &dataset1_for_nooperation[0]);
+
+ temp3[0] = 0x3f;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_OPERATING_FUNCTION,
+ len, &temp3[0]);
+
+ len = sizeof(dataset2_for_nooperation) / sizeof(unsigned char);
+ slic_cmd(spi, channel_id, WRITE_NO_OPERATION, len,
+ &dataset2_for_nooperation[0]);
+
+ temp3[0] = 0x2;
+ len = 0x1;
+ slic_cmd(spi, channel_id, WRITE_SYSTEM_STATE_CFG,
+ len, &temp3[0]);
+
+ len = sizeof(dataset_internalCfgReg3) / sizeof(unsigned char);
+ slic_cmd(spi, channel_id, WRITE_INTERNAL_CFG_REG3 ,
+ len, &dataset_internalCfgReg3[0]);
+
+ len = sizeof(dataset3_for_nooperation) / sizeof(unsigned char);
+ slic_cmd(spi, channel_id, WRITE_NO_OPERATION, len,
+ &dataset3_for_nooperation[0]);
+
+ temp3[0] = 0xbf;
+ len = 0x1;
+ slic_cmd(spi, channel_id, WRITE_OPERATING_FUNCTION,
+ len, &temp3[0]);
+
+ temp3[0] = 0xc0;
+ len = 0x1;
+ slic_cmd(spi, channel_id, WRITE_OPERATING_CONDITIONS,
+ len, &temp3[0]);
+
+ temp3[0] = 0x6;
+ len = 0x1;
+ slic_cmd(spi, channel_id, WRITE_SYSTEM_STATE_CFG,
+ len, &temp3[0]);
+
+ temp3[0] = 0x6;
+ len = 0x1;
+ slic_cmd(spi, channel_id, WRITE_SYSTEM_STATE_CFG,
+ len, &temp3[0]);
+
+ temp3[0] = 0xc0;
+ len = 0x1;
+ slic_cmd(spi, channel_id, WRITE_OPERATING_CONDITIONS,
+ len, &temp3[0]);
+
+ temp3[0] = 0x16;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_SYSTEM_STATE_CFG,
+ len, &temp3[0]);
+
+ temp3[0] = 0xc0;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_OPERATING_CONDITIONS,
+ len, &temp3[0]);
+
+ temp3[0] = 0x16;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_SYSTEM_STATE_CFG,
+ len, &temp3[0]);
+
+ temp3[0] = 0x3f;
+ if (channel_id == CHANNEL1)
+ temp3[1] = 0xff;
+ else
+ temp3[1] = 0xbf;
+ len = 0x02;
+ slic_cmd(spi, channel_id, WRITE_INT_MASK, len,
+ &temp3[0]);
+
+ temp3[0] = 0x16;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_SYSTEM_STATE_CFG,
+ len, &temp3[0]);
+
+ temp3[0] = 0xc0;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_OPERATING_CONDITIONS,
+ len, &temp3[0]);
+
+ temp3[0] = 0x0;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_OPERATING_CONDITIONS,
+ len, &temp3[0]);
+
+ temp3[0] = 0x0;
+ temp3[1] = 0x2;
+ len = 0x02;
+ slic_cmd(spi, channel_id, WRITE_DC_CALIBRATION, len,
+ &temp3[0]);
+
+ temp3[0] = 0x2b;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_SYSTEM_STATE, len,
+ &temp3[0]);
+
+ }
+ /* Reading the Device Configuration register */
+ len = 0x1;
+ slic_cmd(spi, CHANNEL1, READ_DEVICE_CONFIGURATION, len,
+ &temp1);
+ printk(KERN_INFO "DEV reg is %x\n", temp1);
+
+ /* Enabling interrupt by writing into Device Configuration Register */
+ temp1 &= 0x7F;
+ len = 0x01;
+ slic_cmd(spi, CHANNEL1, WRITE_DEVICE_CFG, len, &temp1);
+
+ /* Reading the Device Configuration register */
+ len = 0x1;
+ slic_cmd(spi, CHANNEL1, READ_DEVICE_CONFIGURATION, len,
+ &temp1);
+ printk(KERN_INFO "DEV reg after is %x\n", temp1);
+
+ /* Reading the Mask register */
+ len = 0x2;
+ slic_cmd(spi, CHANNEL1, READ_INT_MASK, len, &temp2[0]);
+ printk(KERN_INFO "Mask reg before setting is %x %x\n",
+ temp2[0], temp2[1]);
+
+ /* Writing into the mask register */
+ temp2[0] = 0xF6;
+ temp2[1] = 0xF6;
+ len = 0x2;
+ slic_cmd(spi, CHANNEL1, WRITE_INT_MASK, len, &temp2[0]);
+
+ /* Reading the Mask register */
+ len = 0x2;
+ slic_cmd(spi, CHANNEL1, READ_INT_MASK, len, &temp2[0]);
+ printk(KERN_INFO "Mask reg after setting is %x %x\n",
+ temp2[0], temp2[1]);
+
+ temp1 = slic_ch[slic_id].ch1_tx_slot;
+ len = 0x1;
+ slic_cmd(spi, CHANNEL1, WRITE_TX_TIME_SLOT, len, &temp1);
+
+ len = 0x1;
+ slic_cmd(spi, CHANNEL1, READ_TX_TIME_SLOT, len, &temp1);
+ printk(KERN_INFO "Read Tx Timeslot for CH1 is %x\n", temp1);
+
+ temp1 = slic_ch[slic_id].ch2_tx_slot;
+ len = 0x1;
+ slic_cmd(spi, CHANNEL2, WRITE_TX_TIME_SLOT, len, &temp1);
+
+ len = 0x1;
+ slic_cmd(spi, CHANNEL2, READ_TX_TIME_SLOT, len, &temp1);
+ printk(KERN_INFO "Read Tx Timeslot for CH2 is %x\n", temp1);
+
+ temp1 = slic_ch[slic_id].ch1_rx_slot;
+ len = 0x1;
+ slic_cmd(spi, CHANNEL1, WRITE_RX_TIME_SLOT, len, &temp1);
+
+ len = 0x1;
+ slic_cmd(spi, CHANNEL1, READ_RX_TIME_SLOT, len, &temp1);
+ printk(KERN_INFO "Read Rx Timeslot for CH1 is %x\n", temp1);
+
+ temp1 = slic_ch[slic_id].ch2_rx_slot;
+ len = 0x1;
+ slic_cmd(spi, CHANNEL2, WRITE_RX_TIME_SLOT, len, &temp1);
+
+ len = 0x1;
+ slic_cmd(spi, CHANNEL2, READ_RX_TIME_SLOT, len, &temp1);
+ printk(KERN_INFO "Read Rx Timeslot for CH2 is %x\n", temp1);
+
+ for (channel_id = CHANNEL1; channel_id <= CHANNEL2; channel_id++) {
+
+ temp1 &= 0xBF;
+ temp1 |= 0x80;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_OPERATING_FUNCTION,
+ len, &temp1);
+
+ len = 0x01;
+ slic_cmd(spi, channel_id, READ_OPERATING_FUNCTION,
+ len, &temp1);
+ printk(KERN_INFO "Operating Fun for channel %d is %x\n",
+ channel_id, temp1);
+
+ /* Install Timers */
+ len = 0x04;
+ slic_cmd(spi, channel_id, READ_CADENCE_TIMER, len,
+ &cad[0]);
+ printk(KERN_INFO "Cadence Timer Reg for CH%d before is %x %x"
+ "%x %x\n", channel_id, cad[0], cad[1], cad[2],
+ cad[3]);
+
+ len = sizeof(set_cadenceTimer) / sizeof(unsigned char);
+ slic_cmd(spi, channel_id, WRITE_CADENCE_TIMER, len,
+ &set_cadenceTimer[0]);
+
+ len = 0x04;
+ slic_cmd(spi, channel_id, READ_CADENCE_TIMER , len,
+ &cad[0]);
+ printk(KERN_INFO "Cadence Timer Reg for CH%d after is %x %x"
+ "%x %x\n", channel_id, cad[0], cad[1], cad[2],
+ cad[3]);
+ temp1 = 0x20;
+ len = 0x01;
+ slic_cmd(spi, channel_id, WRITE_SYSTEM_STATE_CFG,
+ len, &temp1);
+
+ slic_cmd(spi, channel_id, READ_SYSTEM_STATE_CFG,
+ len, &temp1);
+ printk(KERN_INFO "Switching control for channel %d is %x\n",
+ channel_id, temp1);
+ }
+ return 0;
+}
+
+void configure_spi_pdata(struct spi_device *spi)
+{
+ struct slic_platform_data *spi_slic_pdata;
+ const u32 *iprop;
+ struct device_node *np = spi->dev.of_node;
+ static int num_slic;
+
+ spi_slic_pdata = kzalloc(sizeof(*spi_slic_pdata), GFP_KERNEL);
+ if (spi_slic_pdata == NULL)
+ return;
+
+ spi->dev.platform_data = spi_slic_pdata;
+
+ spi_slic_pdata->ch1_rx_slot = CH1_RX_SLOT_NUM + num_slic;
+ spi_slic_pdata->ch1_tx_slot = CH1_TX_SLOT_NUM + num_slic;
+ spi_slic_pdata->ch2_rx_slot = CH2_RX_SLOT_NUM + num_slic;
+ spi_slic_pdata->ch2_tx_slot = CH2_TX_SLOT_NUM + num_slic;
+ pr_info("SLIC config success\n");
+ num_slic = num_slic + SLIC_SLOT_OFFSET;
+
+}
+static int slic_remove(struct spi_device *spi)
+{
+
+ printk(KERN_INFO "SLIC module uninstalled\n");
+ return 0;
+}
+
+static int slic_probe(struct spi_device *spi)
+{
+ int ret = 0;
+ unsigned char *device_handle;
+ struct slic_platform_data *data;
+
+ printk(KERN_INFO "SLIC probed!\n");
+
+ g_spi = spi;
+ spi->bits_per_word = 8;
+
+ if (num_slics >= MAX_NUM_OF_SLICS) {
+ printk(KERN_ERR "Exceeded the max number of slics\n");
+ return ret;
+ }
+
+ /* Initialize the SLIC */
+ configure_spi_pdata(spi);
+ data = spi->dev.platform_data;
+ slic_ch[num_slics].ch1_tx_slot = data->ch1_tx_slot;
+ slic_ch[num_slics].ch1_rx_slot = data->ch1_rx_slot;
+ slic_ch[num_slics].ch2_tx_slot = data->ch2_tx_slot;
+ slic_ch[num_slics].ch2_rx_slot = data->ch2_rx_slot;
+
+ device_handle = 0x0;
+ ret = slic_init_configure(device_handle, spi, num_slics);
+ if (ret == 0) {
+ num_slics++;
+ printk(KERN_INFO "SLIC %d configuration success\n",
+ num_slics);
+ } else {
+ printk(KERN_ERR "%s slic configuration failed\n", __func__);
+ return ret;
+ }
+ return ret;
+}
+
+static const struct of_device_id slic_match[] = {
+ {
+ .compatible = "zarlink,le88266",
+ },
+ {},
+};
+
+static struct spi_driver slic_driver = {
+ .driver = {
+ .name = "legerity",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ .of_match_table = slic_match,
+ },
+ .probe = slic_probe,
+ .remove = slic_remove,
+
+};
+
+static int __init slic_init(void)
+{
+ int ret;
+ printk(KERN_INFO "SLIC: " DRV_DESC "\n");
+ printk(KERN_INFO "####################################################"
+ "\n# This driver was created solely by Freescale, #"
+ "\n# without the assistance, support or intellectual #"
+ "\n# property of Zarlink Semiconductor. No #"
+ "\n# maintenance or support will be provided by #"
+ "\n# Zarlink Semiconductor regarding this driver. #"
+ "\n####################################################"
+ "\n");
+
+ ret = spi_register_driver(&slic_driver);
+ if (ret != 0)
+ printk(KERN_ERR "%s spi_register_driver failed\n",
+ __func__);
+ return ret;
+}
+
+static void __exit slic_exit(void)
+{
+ spi_unregister_driver(&slic_driver);
+}
+
+module_init(slic_init);
+module_exit(slic_exit);
diff --git a/drivers/tdm/line_ctrl/slic_zarlink.h b/drivers/tdm/line_ctrl/slic_zarlink.h
new file mode 100644
index 0000000..1a44590
--- /dev/null
+++ b/drivers/tdm/line_ctrl/slic_zarlink.h
@@ -0,0 +1,131 @@
+/*
+ * drivers/tdm/line/slic_zarlink.h
+ *
+ * Copyright (C) 2009-2012 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * This is the header file for the SLIC Driver Module
+ * drivers/tdm/line/slic_zarlink.c.
+ *
+ * Author: Rajesh Gumasta<rajesh.gumasta@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifndef SLIC_ZARLINK_H
+#define SLIC_ZARLINK_H
+
+struct slic_platform_data {
+ unsigned int ch1_rx_slot;
+ unsigned int ch1_tx_slot;
+ unsigned int ch2_rx_slot;
+ unsigned int ch2_tx_slot;
+};
+
+/* SLIC channel configuration */
+#define CH1_RX_SLOT_NUM 0
+#define CH1_TX_SLOT_NUM 0
+#define CH2_RX_SLOT_NUM 2
+#define CH2_TX_SLOT_NUM 2
+
+#define SLIC_SLOT_OFFSET 2
+
+/* commands to the SLIC */
+#define CHANNEL1 0x01
+#define CHANNEL2 0x02
+#define HW_RESET 0x04
+#define WRITE_NO_OPERATION 0x06
+#define WRITE_TX_TIME_SLOT 0x40
+#define READ_TX_TIME_SLOT 0x41
+#define WRITE_RX_TIME_SLOT 0x42
+#define READ_RX_TIME_SLOT 0x43
+#define WRITE_TXRXCLKSLOT_TXCLKEDGE 0x44
+#define WRITE_DEVICE_CFG 0x46
+#define READ_DEVICE_CONFIGURATION 0x47
+#define WRITE_CHANNEL_ENABLE 0X4A
+#define WRITE_IO_DATA 0x52
+#define WRITE_IO_DIRECTION 0x54
+#define WRITE_SYSTEM_STATE 0x56
+#define WRITE_OPERATING_FUNCTION 0x60
+#define READ_OPERATING_FUNCTION 0x61
+#define WRITE_SYSTEM_STATE_CFG 0x68
+#define READ_SYSTEM_STATE_CFG 0x69
+#define WRITE_INT_MASK 0x6C
+#define READ_INT_MASK 0x6D
+#define WRITE_OPERATING_CONDITIONS 0x70
+#define READ_PRODUCT_CODE 0X73
+#define WRITE_CONVERTER_CFG 0xA6
+#define WRITE_LOOP_SUPERVISION_PARAMS 0xC2
+#define WRITE_DC_FEED_PARAMS 0xC6
+#define WRITE_CADENCE_TIMER 0xE0
+#define READ_CADENCE_TIMER 0xE1
+#define WRITE_SWITCH_REGULATOR_PARAMS 0xE4
+#define WRITE_SWITCH_REGULATOR_CTRL 0xE6
+#define WRITE_INTERNAL_CFG_REG3 0xF2
+#define WRITE_DC_CALIBRATION 0xFC
+
+/* Dataset1 for no operation command */
+static unsigned char dataset1_for_nooperation[] = {
+ 0xca, 0xfa, 0x98, 0xca, 0xb9,
+ 0xa2, 0x4c, 0x2b, 0xa2, 0xa3,
+ 0xa2, 0xae, 0x2b, 0x9a, 0x23,
+ 0xca, 0x26, 0x9f, 0x1, 0x8a,
+ 0x1d, 0x1, 0x1, 0x11, 0x1,
+ 0x90, 0x1, 0x90, 0x1, 0x90,
+ 0x1, 0x90, 0x1, 0x90, 0x88,
+ 0xd8, 0x70, 0x7a, 0x87, 0x23,
+ 0x3f, 0x4a, 0x97, 0x5a, 0xa7,
+ 0x5a, 0xaf, 0x82, 0x22, 0xe0,
+ 0x80, 0x32, 0x10, 0x50, 0x10,
+ 0x86, 0xa2, 0x63, 0x23, 0xbb,
+ 0x2a, 0xa4, 0x29, 0x7d, 0x87,
+ 0x2a, 0xfa, 0x8f, 0x29, 0xf0,
+ 0x96, 0x2e, 0x1
+};
+
+/* Dataset2 for no operation command */
+static unsigned char dataset2_for_nooperation[] = {
+ 0xd2, 0x0, 0x0, 0x0, 0x0,
+ 0x36, 0x36, 0xb9, 0x0, 0x0,
+ 0x0, 0x0, 0x68, 0x0
+};
+
+/* Dataset3 for no operation command */
+static unsigned char dataset3_for_nooperation[] = {
+ 0xc2, 0x1b, 0x84, 0xb4, 0x5,
+ 0xc6, 0x8, 0x8
+};
+
+/* Dataset for internal configuration register 3 command */
+static unsigned char dataset_internalCfgReg3[] = {
+ 0x10, 0x1, 0x0, 0x0
+};
+
+/* Dataset for cadence timer command */
+static unsigned char dataset_cadenceTimer[] = {
+ 0x3f, 0xff, 0x0, 0x0
+};
+
+/* Dataset for Loop parameters command */
+static unsigned char dataset_writeLoopParams[] = {
+ 0x1b, 0x84, 0xb3, 0x5
+};
+
+/* Dataset1 for cadence timer command */
+static unsigned char set_cadenceTimer[] = {
+ 0x01, 0x90, 0x03, 0x20
+};
+
+#endif
diff --git a/drivers/tdm/tdm-core.c b/drivers/tdm/tdm-core.c
new file mode 100644
index 0000000..97bd338
--- /dev/null
+++ b/drivers/tdm/tdm-core.c
@@ -0,0 +1,1190 @@
+/* driver/tdm/tdm-core.c
+ *
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * TDM core is the interface between TDM clients and TDM devices.
+ * It is also intended to serve as an interface for line controld
+ * devices later on.
+ *
+ * Author:Hemant Agrawal <hemant@freescale.com>
+ * Rajesh Gumasta <rajesh.gumasta@freescale.com>
+ *
+ * Modified by Sandeep Kr Singh <sandeep@freescale.com>
+ * Poonam Aggarwal <poonam.aggarwal@freescale.com>
+ * 1. Added framework based initilization of device.
+ * 2. All the init/run time configuration is now done by framework.
+ * 3. Added channel level operations.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* if read write debug required */
+#undef TDM_CORE_DEBUG
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/tdm.h>
+#include <linux/init.h>
+#include <linux/idr.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
+#include <linux/hardirq.h>
+#include <linux/irqflags.h>
+#include <linux/list.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+
+
+static DEFINE_MUTEX(tdm_core_lock);
+static DEFINE_IDR(tdm_adapter_idr);
+/* List of TDM adapters registered with TDM framework */
+LIST_HEAD(adapter_list);
+
+/* List of TDM clients registered with TDM framework */
+LIST_HEAD(driver_list);
+
+/* In case the previous data is not fetched by the client driver, the
+ * de-interleaving function will discard the old data and rewrite the
+ * new data */
+static int use_latest_tdm_data = 1;
+
+/* this tasklet is created for each adapter instance */
+static void tdm_data_tasklet_fn(unsigned long);
+
+/* tries to match client driver with the adapter */
+static int tdm_device_match(struct tdm_driver *driver, struct tdm_adapter *adap)
+{
+ /* match on an id table if there is one */
+ if (driver->id_table && driver->id_table->name[0]) {
+ if (!(strcmp(driver->id_table->name, adap->name)))
+ return (int)driver->id_table;
+ }
+ return TDM_E_OK;
+}
+
+static int tdm_attach_driver_adap(struct tdm_driver *driver,
+ struct tdm_adapter *adap)
+{
+ int ret = TDM_E_OK;
+ /* if driver is already attached to any other adapter, return*/
+ if (driver->adapter && (driver->adapter != adap))
+ return ret;
+
+ driver->adapter = adap;
+
+ if (driver->attach_adapter) {
+ ret = driver->attach_adapter(adap);
+ if (ret < 0) {
+ pr_err("attach_adapter failed for driver [%s] err:%d\n"
+ , driver->name, ret);
+ return ret;
+ }
+ }
+ adap->drv_count++;
+
+ if (!adap->tasklet_conf) {
+ tasklet_init(&adap->tdm_data_tasklet, tdm_data_tasklet_fn,
+ (unsigned long)adap);
+ adap->tasklet_conf = 1;
+ }
+
+ return ret;
+}
+
+/* Detach client driver and adapter */
+static int tdm_detach_driver_adap(struct tdm_driver *driver,
+ struct tdm_adapter *adap)
+{
+ int res = TDM_E_OK;
+
+ if (!driver->adapter || (driver->adapter != adap))
+ return TDM_E_OK;
+
+ if (!driver->detach_adapter)
+ return TDM_E_OK;
+
+ adap->drv_count--;
+
+ /* If no more driver is registed with the adapter*/
+ if (!adap->drv_count && adap->tasklet_conf) {
+ tasklet_disable(&adap->tdm_data_tasklet);
+ tasklet_kill(&adap->tdm_data_tasklet);
+ adap->tasklet_conf = 0;
+ }
+
+ if (driver->detach_adapter) {
+ if (driver->detach_adapter(adap))
+ pr_err("detach_adapter failed for driver [%s]\n",
+ driver->name);
+ }
+
+ driver->adapter = NULL;
+ return res;
+}
+
+/* TDM adapter Registration/De-registration with TDM framework */
+
+static int tdm_register_adapter(struct tdm_adapter *adap)
+{
+ int res = TDM_E_OK;
+ struct tdm_driver *driver, *next;
+
+ if (!adap) {
+ pr_err("%s:Invalid handle\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_init(&adap->adap_lock);
+ INIT_LIST_HEAD(&adap->myports);
+ spin_lock_init(&adap->portlist_lock);
+
+ adap->drv_count = 0;
+ adap->tasklet_conf = 0;
+
+ list_add_tail(&adap->list, &adapter_list);
+
+ /* initialization of driver by framework in default configuration */
+ init_config_adapter(adap);
+
+ /* Notify drivers */
+ pr_info("adapter [%s] registered\n", adap->name);
+ mutex_lock(&tdm_core_lock);
+ list_for_each_entry_safe(driver, next, &driver_list, list) {
+ if (tdm_device_match(driver, adap)) {
+ res = tdm_attach_driver_adap(driver, adap);
+ if (res == TDM_E_OK) {
+ pr_info("Driver(ID=%d) is "
+ "attached with Adapter %s(ID = %d)\n",
+ driver->id, adap->name, adap->id);
+ } else {
+ pr_err("Driver(ID=%d) is unable "
+ "to attach with Adapter %s(ID = %d)\n",
+ driver->id, adap->name, adap->id);
+ }
+ }
+ }
+ mutex_unlock(&tdm_core_lock);
+
+ return res;
+}
+
+/*
+ * tdm_add_adapter - declare tdm adapter, use dynamic device number
+ * @adapter: the adapter to add
+ * Context: can sleep
+ *
+ * This routine is used to declare a TDM adapter
+ * When this returns zero, a new device number will be allocated and stored
+ * in adap->id, and the specified adapter became available for the clients.
+ * Otherwise, a negative errno value is returned.
+ */
+int tdm_add_adapter(struct tdm_adapter *adapter)
+{
+ int id, res = TDM_E_OK;
+ if (!adapter) {
+ pr_err("%s:Invalid handle\n", __func__);
+ return -EINVAL;
+ }
+
+retry:
+ if (idr_pre_get(&tdm_adapter_idr, GFP_KERNEL) == 0)
+ return -ENOMEM;
+
+ mutex_lock(&tdm_core_lock);
+ res = idr_get_new(&tdm_adapter_idr, adapter, &id);
+ mutex_unlock(&tdm_core_lock);
+
+ if (res < 0) {
+ if (res == -EAGAIN)
+ goto retry;
+ return res;
+ }
+
+ adapter->id = id;
+ return tdm_register_adapter(adapter);
+}
+EXPORT_SYMBOL(tdm_add_adapter);
+
+
+/**
+ * tdm_del_adapter - unregister TDM adapter
+ * @adap: the adapter being unregistered
+ *
+ * This unregisters an TDM adapter which was previously registered
+ * by @tdm_add_adapter.
+ */
+int tdm_del_adapter(struct tdm_adapter *adap)
+{
+ int res = TDM_E_OK;
+ struct tdm_adapter *found;
+ struct tdm_driver *driver, *next;
+
+ if (!adap) {
+ pr_err("%s:Invalid handle\n", __func__);
+ return -EINVAL;
+ }
+
+ /* First make sure that this adapter was ever added */
+ mutex_lock(&tdm_core_lock);
+ found = idr_find(&tdm_adapter_idr, adap->id);
+ mutex_unlock(&tdm_core_lock);
+ if (found != adap) {
+ pr_err("tdm-core: attempting to delete unregistered "
+ "adapter [%s]\n", adap->name);
+ return -EINVAL;
+ }
+
+ /*disable and kill the data processing tasklet */
+ if (adap->tasklet_conf) {
+ tasklet_disable(&adap->tdm_data_tasklet);
+ tasklet_kill(&adap->tdm_data_tasklet);
+ adap->tasklet_conf = 0;
+ }
+
+ /* Detach any active ports. This can't fail, thus we do not
+ checking the returned value. */
+ mutex_lock(&tdm_core_lock);
+ list_for_each_entry_safe(driver, next, &driver_list, list) {
+ if (tdm_device_match(driver, adap)) {
+ tdm_detach_driver_adap(driver, adap);
+ pr_info(
+ "Driver(ID=%d) is detached from Adapter %s(ID = %d)\n",
+ driver->id, adap->name, adap->id);
+ }
+ }
+ mutex_unlock(&tdm_core_lock);
+
+ mutex_lock(&tdm_core_lock);
+ idr_remove(&tdm_adapter_idr, adap->id);
+ mutex_unlock(&tdm_core_lock);
+
+ pr_debug("adapter [%s] unregistered\n", adap->name);
+
+ list_del(&adap->list);
+ /* Clear the device structure in case this adapter is ever going to be
+ added again */
+ adap->parent = NULL;
+
+ return res;
+}
+EXPORT_SYMBOL(tdm_del_adapter);
+
+/* TDM Client Drivers Registration/De-registration Functions */
+int tdm_register_driver(struct tdm_driver *driver)
+{
+ int res = TDM_E_OK;
+ struct tdm_adapter *adap, *next;
+
+ list_add_tail(&driver->list, &driver_list);
+
+ mutex_lock(&tdm_core_lock);
+ /* Walk the adapters that are already present */
+ list_for_each_entry_safe(adap, next, &adapter_list, list) {
+ if (tdm_device_match(driver, adap)) {
+ res = tdm_attach_driver_adap(driver, adap);
+ if (res == TDM_E_OK) {
+ pr_info("TDM Driver(ID=%d)is attached with "
+ "Adapter%s(ID = %d) drv_count=%d",
+ driver->id, adap->name, adap->id,
+ adap->drv_count);
+ } else {
+ pr_err("TDM Driver(ID=%d) unable to attach "
+ "to Adapter%s(ID = %d) drv_count=%d",
+ driver->id, adap->name, adap->id,
+ adap->drv_count);
+ }
+ break;
+ }
+ }
+ mutex_unlock(&tdm_core_lock);
+
+ return res;
+}
+EXPORT_SYMBOL(tdm_register_driver);
+
+/*
+ * tdm_unregister_driver - unregister TDM client driver from TDM framework
+ * @driver: the driver being unregistered
+ */
+void tdm_unregister_driver(struct tdm_driver *driver)
+{
+ if (!driver) {
+ pr_err("%s:Invalid handle\n", __func__);
+ return;
+ }
+ /* A driver can register to only one adapter,
+ * so no need to browse the list */
+ mutex_lock(&tdm_core_lock);
+ tdm_detach_driver_adap(driver, driver->adapter);
+ mutex_unlock(&tdm_core_lock);
+
+ list_del(&driver->list);
+
+ pr_debug("tdm-core: driver [%s] unregistered\n", driver->name);
+}
+EXPORT_SYMBOL(tdm_unregister_driver);
+
+/* TDM Framework init and exit */
+static int __init tdm_init(void)
+{
+ pr_info("%s\n", __func__);
+ return TDM_E_OK;
+}
+
+static void __exit tdm_exit(void)
+{
+ pr_info("%s\n", __func__);
+ return;
+}
+
+/* We must initialize early, because some subsystems register tdm drivers
+ * in subsys_initcall() code, but are linked (and initialized) before tdm.
+ */
+postcore_initcall(tdm_init);
+module_exit(tdm_exit);
+
+
+/* Interface to the tdm device/adapter */
+
+/* tdm_read_direct - issue a TDM read
+ * @adap: Handle to TDM device
+ * @buf: Data that will be read from the TDM device
+ * @len: How many bytes to read
+ *
+ * Returns negative errno, or else 0.
+ */
+int tdm_read_direct(struct tdm_adapter *adap, u8 *buf, u32 len)
+{
+ int res;
+
+ if (adap->algo->tdm_read_simple)
+ res = adap->algo->tdm_read_simple(adap, buf, len);
+ else {
+ pr_err("TDM level read not supported\n");
+ return -EOPNOTSUPP;
+ }
+ /* If everything went ok (i.e. frame received), return #bytes
+ transmitted, else error code. */
+
+ return res;
+
+
+}
+EXPORT_SYMBOL(tdm_read_direct);
+
+/* tdm_write_direct - issue a TDM write
+ * @adap: Handle to TDM device
+ * @buf: Data that will be written to the TDM device
+ * @len: How many bytes to write
+ *
+ * Returns negative errno, or else 0.
+ */
+int tdm_write_direct(struct tdm_adapter *adap, u8 *buf, u32 len)
+{
+ int res;
+
+ if (adap->algo->tdm_write_simple)
+ res = adap->algo->tdm_write_simple(adap, buf, len);
+ else {
+ pr_err("TDM level write not supported\n");
+ return -EOPNOTSUPP;
+ }
+
+ return res;
+}
+EXPORT_SYMBOL(tdm_write_direct);
+
+/* tdm_adap_send - issue a TDM write
+ * @adap: Handle to TDM device
+ * @buf: Data that will be written to the TDM device
+ * @count: How many bytes to write
+ *
+ * Returns negative errno, or else the number of bytes written.
+ */
+int tdm_adap_send(struct tdm_adapter *adap, void **buf, int count)
+{
+ int res;
+
+ if ((adap == NULL) || (buf == NULL)) { /* invalid handle*/
+ pr_err("%s: Invalid Handle\n", __func__);
+ return -ENXIO;
+ }
+
+ if (adap->algo->tdm_write)
+ res = adap->algo->tdm_write(adap, buf, count);
+ else {
+ pr_err("TDM level write not supported\n");
+ return -EOPNOTSUPP;
+ }
+
+ /* If everything went ok (i.e. frame transmitted), return #bytes
+ transmitted, else error code. */
+ return (res == 1) ? count : res;
+}
+EXPORT_SYMBOL(tdm_adap_send);
+
+/**
+ * tdm_adap_recv - issue a TDM read
+ * @adap: Handle to TDM device
+ * @buf: Where to store data read from TDM device
+ *
+ * Returns negative errno, or else the number of bytes read.
+ */
+int tdm_adap_recv(struct tdm_adapter *adap, void **buf)
+{
+ int res;
+
+ if (adap->algo->tdm_read)
+ res = adap->algo->tdm_read(adap, (u16 **)buf);
+ else {
+ pr_err("TDM level read not supported\n");
+ return -EOPNOTSUPP;
+ }
+ /* If everything went ok (i.e. frame received), return #bytes
+ transmitted, else error code. */
+ return res;
+}
+
+/**
+ * tdm_adap_get_write_buf - get next write TDM device buffer
+ * @adap: Handle to TDM device
+ * @buf: pointer to TDM device buffer
+ *
+ * Returns negative errno, or else size of the write buffer.
+ */
+int tdm_adap_get_write_buf(struct tdm_adapter *adap, void **buf)
+{
+ int res;
+
+ if (adap->algo->tdm_get_write_buf) {
+ res = adap->algo->tdm_get_write_buf(adap, (u16 **)buf);
+ } else {
+ pr_err("TDM level write buf get not supported\n");
+ return -EOPNOTSUPP;
+ }
+ /* If everything went ok (i.e. 1 msg received), return #bytes
+ transmitted, else error code. */
+ return res;
+}
+EXPORT_SYMBOL(tdm_adap_get_write_buf);
+
+int tdm_adap_enable(struct tdm_driver *drv)
+{
+ int res;
+ struct tdm_adapter *adap;
+ if (drv == NULL) { /* invalid handle*/
+ pr_err("%s: Invalid Handle\n", __func__);
+ return -ENXIO;
+ }
+ adap = drv->adapter;
+
+ if (adap->algo->tdm_enable) {
+ res = adap->algo->tdm_enable(adap);
+ } else {
+ pr_err("TDM level enable not supported\n");
+ return -EOPNOTSUPP;
+ }
+ return res;
+}
+EXPORT_SYMBOL(tdm_adap_enable);
+
+int tdm_adap_disable(struct tdm_driver *drv)
+{
+ int res;
+ struct tdm_adapter *adap;
+ if (drv == NULL) { /* invalid handle*/
+ pr_err("%s: Invalid Handle\n", __func__);
+ return -ENXIO;
+ }
+ adap = drv->adapter;
+
+ if (adap->algo->tdm_disable) {
+ res = adap->algo->tdm_disable(adap);
+ } else {
+ pr_err("TDM level enable not supported\n");
+ return -EOPNOTSUPP;
+ }
+ return res;
+}
+EXPORT_SYMBOL(tdm_adap_disable);
+
+struct tdm_adapter *tdm_get_adapter(int id)
+{
+ struct tdm_adapter *adapter;
+
+ mutex_lock(&tdm_core_lock);
+ adapter = idr_find(&tdm_adapter_idr, id);
+ if (adapter && !try_module_get(adapter->owner))
+ adapter = NULL;
+
+ mutex_unlock(&tdm_core_lock);
+
+ return adapter;
+}
+EXPORT_SYMBOL(tdm_get_adapter);
+
+void tdm_put_adapter(struct tdm_adapter *adap)
+{
+ module_put(adap->owner);
+}
+EXPORT_SYMBOL(tdm_put_adapter);
+
+
+/* Port Level APIs of TDM Framework */
+unsigned int tdm_port_open(struct tdm_driver *driver, void **h_port)
+{
+ struct tdm_port *port;
+ struct tdm_adapter *adap;
+ unsigned long flags;
+ int res = TDM_E_OK;
+
+ if (driver == NULL) {
+ pr_err("driver NULL\n");
+ return -ENODEV;
+ }
+ if (driver->adapter == NULL) {
+ pr_err("adapter NULL\n");
+ return -ENODEV;
+ }
+
+ adap = tdm_get_adapter(driver->adapter->id);
+ if (!adap)
+ return -ENODEV;
+
+ /* This creates an anonymous tdm_port, which may later be
+ * pointed to some slot.
+ *
+ */
+ port = kzalloc(sizeof(*port), GFP_KERNEL);
+ if (!port) {
+ res = -ENOMEM;
+ goto out;
+ }
+
+ port->rx_max_frames = NUM_SAMPLES_PER_FRAME;
+ port->port_cfg.port_mode = e_TDM_PORT_CHANNELIZED;
+
+ port->in_use = 1;
+
+ snprintf(driver->name, TDM_NAME_SIZE, "tdm-dev");
+ port->driver = driver;
+ port->adapter = adap;
+
+ spin_lock_irqsave(&adap->portlist_lock, flags);
+ list_add_tail(&port->list, &adap->myports);
+ spin_unlock_irqrestore(&adap->portlist_lock, flags);
+
+ INIT_LIST_HEAD(&port->mychannels);
+
+ *h_port = port;
+
+out:
+ return res;
+}
+EXPORT_SYMBOL(tdm_port_open);
+
+unsigned int tdm_port_close(void *h_port)
+{
+ struct tdm_adapter *adap;
+ struct tdm_driver *driver;
+ struct tdm_port *port;
+ struct tdm_channel *temp, *channel;
+ unsigned long flags;
+ int res = TDM_E_OK;
+ port = (struct tdm_port *)h_port;
+
+ if (port == NULL) { /* invalid handle*/
+ pr_err("Invalid Handle");
+ return -ENXIO;
+ }
+
+ driver = port->driver;
+
+ if (driver == NULL) {
+ pr_err("driver NULL\n");
+ res = -ENODEV;
+ goto out;
+ }
+ if (driver->adapter == NULL) {
+ pr_err("adapter NULL\n");
+ res = -ENODEV;
+ goto out;
+ }
+
+ list_for_each_entry_safe(channel, temp, &port->mychannels, list) {
+ if (channel)
+ if (channel->in_use) {
+ pr_err("%s: Cannot close port. Channel in use\n",
+ __func__);
+ res = -ENXIO;
+ goto out;
+ }
+ }
+ adap = driver->adapter;
+
+ spin_lock_irqsave(&adap->portlist_lock, flags);
+ list_del(&port->list);
+ spin_unlock_irqrestore(&adap->portlist_lock, flags);
+
+ if (port->p_port_data != NULL) {
+ int i;
+ struct tdm_bd *ch_bd;
+
+ /* If the tdm is in channelised mode,
+ de-allocate the channelised buffer */
+ ch_bd = &(port->p_port_data->rx_data_fifo[0]);
+ for (i = 0; ch_bd && i < TDM_CH_RX_BD_RING_SIZE; i++) {
+ ch_bd->flag = 0;
+ ch_bd++;
+ }
+ ch_bd = &(port->p_port_data->tx_data_fifo[0]);
+ for (i = 0; ch_bd && i < TDM_CH_TX_BD_RING_SIZE; i++) {
+ ch_bd->flag = 0;
+ ch_bd++;
+ }
+ kfree(port->p_port_data);
+ }
+ kfree(port);
+ return res;
+out:
+ if (port)
+ kfree(port->p_port_data);
+ kfree(port);
+ return res;
+}
+EXPORT_SYMBOL(tdm_port_close);
+
+unsigned int tdm_channel_read(void *h_port, void *h_channel,
+ void *p_data, u16 *size)
+{
+ struct tdm_port *port;
+ struct tdm_channel *channel;
+ struct tdm_bd *rx_bd;
+ unsigned long flags;
+ int i, res = TDM_E_OK;
+ unsigned short *buf, *buf1;
+ port = (struct tdm_port *)h_port;
+ channel = (struct tdm_channel *)h_channel;
+
+ if ((port && channel) == 0) { /* invalid handle*/
+ pr_err("%s:Invalid Handle\n", __func__);
+ return -ENXIO;
+ }
+
+ if (!port->in_use)
+ return -EIO;
+ if (!channel->p_ch_data || !channel->in_use)
+ return -EIO;
+
+ spin_lock_irqsave(&channel->p_ch_data->rx_channel_lock, flags);
+ rx_bd = channel->p_ch_data->rx_out_data;
+
+ if (rx_bd->flag) {
+ *size = rx_bd->length;
+ buf = (u16 *) p_data;
+ buf1 = (u16 *)rx_bd->p_data;
+ for (i = 0; i < NUM_SAMPLES_PER_FRAME; i++)
+ buf[i] = buf1[i];
+ rx_bd->flag = 0;
+ rx_bd->offset = 0;
+ channel->p_ch_data->rx_out_data = (rx_bd->wrap) ?
+ channel->p_ch_data->rx_data_fifo : rx_bd + 1;
+
+ } else {
+ spin_unlock_irqrestore(&channel->p_ch_data->rx_channel_lock,
+ flags);
+ pr_info("No Data Available");
+ return -EAGAIN;
+ }
+ spin_unlock_irqrestore(&channel->p_ch_data->rx_channel_lock, flags);
+
+ return res;
+}
+EXPORT_SYMBOL(tdm_channel_read);
+
+
+unsigned int tdm_channel_write(void *h_port, void *h_channel,
+ void *p_data, u16 size)
+{
+ struct tdm_port *port;
+ struct tdm_channel *channel;
+ struct tdm_bd *tx_bd;
+ unsigned long flags;
+ int err = TDM_E_OK;
+ port = (struct tdm_port *)h_port;
+ channel = (struct tdm_channel *)h_channel;
+#ifdef TDM_CORE_DEBUG
+ bool data_flag = 0;
+#endif
+
+ if ((port && channel) == 0) { /* invalid handle*/
+ pr_err("Invalid Handle");
+ return -ENXIO;
+ }
+
+ if (p_data == NULL) { /* invalid data*/
+ pr_err("Invalid Data");
+ return -EFAULT;
+ }
+
+ if (!port->in_use)
+ return -EIO;
+ if (!channel->p_ch_data || !channel->in_use)
+ return -EIO;
+
+ spin_lock_irqsave(&channel->p_ch_data->tx_channel_lock, flags);
+ tx_bd = channel->p_ch_data->tx_in_data;
+
+ if (!tx_bd->flag) {
+ tx_bd->length = size;
+ memcpy(tx_bd->p_data, p_data,
+ size * port->adapter->adapt_cfg.slot_width);
+ tx_bd->flag = 1;
+ tx_bd->offset = 0;
+ channel->p_ch_data->tx_in_data = (tx_bd->wrap) ?
+ channel->p_ch_data->tx_data_fifo : tx_bd+1;
+ port->port_stat.tx_pkt_count++;
+#ifdef TDM_CORE_DEBUG
+ data_flag = 1;
+#endif
+ } else {
+ spin_unlock_irqrestore(&channel->p_ch_data->tx_channel_lock,
+ flags);
+ port->port_stat.tx_pkt_drop_count++;
+ pr_err("E_NO_MEMORY -Failed Transmit");
+ return -ENOMEM;
+ }
+ spin_unlock_irqrestore(&channel->p_ch_data->tx_channel_lock, flags);
+
+#ifdef TDM_CORE_DEBUG
+ if (data_flag) {
+ int k;
+ pr_info("\nTX port:%d - Write - Port TX-%d\n",
+ port->port_id, size);
+ for (k = 0; k < size; k++)
+ pr_info("%x", p_data[k]);
+ pr_info("\n");
+ }
+#endif
+ return err;
+}
+EXPORT_SYMBOL(tdm_channel_write);
+
+/* Driver Function for select and poll. Based on Channel, it sleeps on
+ * waitqueue */
+unsigned int tdm_ch_poll(void *h_channel, unsigned int wait_time)
+{
+ struct tdm_channel *channel;
+ unsigned long timeout = msecs_to_jiffies(wait_time);
+ channel = h_channel;
+
+ if (!channel->p_ch_data || !channel->in_use)
+ return -EIO;
+
+ if (channel->p_ch_data->rx_out_data->flag) {
+ pr_debug("Data Available");
+ return TDM_E_OK;
+ }
+ if (timeout) {
+ wait_event_interruptible_timeout(channel->ch_wait_queue,
+ channel->p_ch_data->rx_out_data->flag,
+ timeout);
+
+ if (channel->p_ch_data->rx_out_data->flag) {
+ pr_debug("Data Available");
+ return TDM_E_OK;
+ }
+ }
+ return -EAGAIN;
+}
+EXPORT_SYMBOL(tdm_ch_poll);
+
+unsigned int tdm_port_get_stats(void *h_port, struct tdm_port_stats *portStat)
+{
+ struct tdm_port *port;
+ int port_num;
+ port = (struct tdm_port *)h_port;
+
+ if (port == NULL || portStat == NULL) { /* invalid handle*/
+ pr_err("Invalid Handle");
+ return -ENXIO;
+ }
+ port_num = port->port_id;
+
+ memcpy(portStat, &port->port_stat, sizeof(struct tdm_port_stats));
+
+ pr_info("TDM Port %d Get Stats", port_num);
+
+ return TDM_E_OK;
+}
+EXPORT_SYMBOL(tdm_port_get_stats);
+
+/* Data handling functions */
+
+static int tdm_data_rx_deinterleave(struct tdm_adapter *adap)
+{
+ struct tdm_port *port, *next;
+ struct tdm_channel *channel, *temp;
+ struct tdm_bd *ch_bd;
+
+ int i, buf_size, ch_data_len;
+ u16 *input_tdm_buffer;
+ u16 *pcm_buffer;
+ int slot_width;
+ int frame_ch_data_size;
+ bool ch_data;
+ int bytes_in_fifo_per_frame;
+ int bytes_slot_offset;
+
+ ch_data_len = NUM_SAMPLES_PER_FRAME;
+ frame_ch_data_size = NUM_SAMPLES_PER_FRAME;
+ ch_data = 0;
+
+ if (!adap) { /* invalid handle*/
+ pr_err("%s: Invalid Handle\n", __func__);
+ return -ENXIO;
+ }
+
+ slot_width = adap->adapt_cfg.slot_width;
+ buf_size = tdm_adap_recv(adap, (void **)&input_tdm_buffer);
+ if (buf_size <= 0 || !input_tdm_buffer)
+ return -EINVAL;
+
+ bytes_in_fifo_per_frame = buf_size/frame_ch_data_size;
+ bytes_slot_offset = bytes_in_fifo_per_frame/slot_width;
+
+ /* de-interleaving for all ports*/
+ list_for_each_entry_safe(port, next, &adap->myports, list) {
+
+ /* if the port is not open */
+ if (!port->in_use)
+ continue;
+
+ list_for_each_entry_safe(channel, temp, &port->mychannels,
+ list) {
+ /* if the channel is not open */
+ if (!channel->in_use || !channel->p_ch_data)
+ continue;
+ ch_bd = channel->p_ch_data->rx_in_data;
+ spin_lock(&channel->p_ch_data->rx_channel_lock);
+ /*if old data is to be discarded */
+ if (use_latest_tdm_data)
+ if (ch_bd->flag) {
+ ch_bd->flag = 0;
+ ch_bd->offset = 0;
+ if (ch_bd == channel->p_ch_data->rx_out_data)
+ channel->p_ch_data->rx_out_data =
+ ch_bd->wrap ?
+ channel->p_ch_data->rx_data_fifo
+ : ch_bd+1;
+ port->port_stat.rx_pkt_drop_count++;
+ }
+ /* if the bd is empty */
+ if (!ch_bd->flag) {
+ if (ch_bd->offset == 0)
+ ch_bd->length = port->rx_max_frames;
+
+ pcm_buffer = ch_bd->p_data + ch_bd->offset;
+ /* De-interleaving the data */
+ for (i = 0; i < ch_data_len; i++) {
+ pcm_buffer[i]
+ = input_tdm_buffer[i*bytes_slot_offset +
+ channel->ch_id];
+ }
+ ch_bd->offset += ch_data_len * slot_width;
+
+ if (ch_bd->offset >=
+ (ch_bd->length - frame_ch_data_size)*
+ (adap->adapt_cfg.slot_width)) {
+ ch_bd->flag = 1;
+ ch_bd->offset = 0;
+ channel->p_ch_data->rx_in_data =
+ ch_bd->wrap ?
+ channel->p_ch_data->rx_data_fifo
+ : ch_bd+1;
+ ch_data = 1;
+ wake_up_interruptible
+ (&channel->ch_wait_queue);
+ }
+ } else {
+ port->port_stat.rx_pkt_drop_count++;
+ }
+ spin_unlock(&channel->p_ch_data->rx_channel_lock);
+ }
+
+ if (ch_data) {
+ /* Wake up the Port Data Poll event */
+#ifdef TDM_CORE_DEBUG
+ pr_info("Port RX-%d-%d\n", channel->ch_id, ch_data_len);
+ for (i = 0; i < ch_data_len; i++)
+ pr_info("%x", pcm_buffer[i]);
+ pr_info("\n");
+#endif
+ port->port_stat.rx_pkt_count++;
+ ch_data = 0;
+ }
+ }
+ return TDM_E_OK;
+}
+
+static int tdm_data_tx_interleave(struct tdm_adapter *adap)
+{
+ struct tdm_port *port, *next;
+ struct tdm_channel *channel, *temp;
+ struct tdm_bd *ch_bd;
+ int i, buf_size, ch_data_len = NUM_SAMPLES_PER_FRAME;
+ bool last_data = 0;
+ u16 *output_tdm_buffer;
+ u16 *pcm_buffer;
+ int frame_ch_data_size = NUM_SAMPLES_PER_FRAME;
+ int bytes_in_fifo_per_frame;
+ int bytes_slot_offset;
+
+#ifdef TDM_CORE_DEBUG
+ u8 data_flag = 0;
+#endif
+
+ if (adap == NULL) { /* invalid handle*/
+ pr_err("%s: Invalid Handle\n", __func__);
+ return -ENXIO;
+ }
+
+ buf_size = tdm_adap_get_write_buf(adap, (void **)&output_tdm_buffer);
+ if (buf_size <= 0 || !output_tdm_buffer)
+ return -EINVAL;
+
+ bytes_in_fifo_per_frame = buf_size/frame_ch_data_size;
+ bytes_slot_offset = bytes_in_fifo_per_frame/adap->adapt_cfg.slot_width;
+
+
+ memset(output_tdm_buffer, 0, sizeof(buf_size));
+
+ list_for_each_entry_safe(port, next, &adap->myports, list) {
+
+ /* check if the port is open */
+ if (!port->in_use)
+ continue;
+
+ list_for_each_entry_safe(channel, temp, &port->mychannels,
+ list) {
+ pr_debug("TX-Tdm %d (slots-)", channel->ch_id);
+
+
+ /* if the channel is open */
+ if (!channel->in_use || !channel->p_ch_data)
+ continue;
+
+ spin_lock(&channel->p_ch_data->tx_channel_lock);
+ if (!channel->in_use || !channel->p_ch_data)
+ continue;
+ ch_bd = channel->p_ch_data->tx_out_data;
+ if (ch_bd->flag) {
+ pcm_buffer = (u16 *)((uint8_t *)ch_bd->p_data +
+ ch_bd->offset);
+ /*if the buffer has less frames than required */
+ if (frame_ch_data_size >=
+ ((ch_bd->length) - (ch_bd->offset/
+ adap->adapt_cfg.slot_width))) {
+ ch_data_len =
+ (ch_bd->length) - (ch_bd->offset/
+ adap->adapt_cfg.slot_width);
+ last_data = 1;
+ } else {
+ ch_data_len = frame_ch_data_size;
+ }
+ /* Interleaving the data */
+ for (i = 0; i < ch_data_len; i++) {
+ /* TODO- need to be genric for any size
+ assignment*/
+ output_tdm_buffer[channel->ch_id +
+ bytes_slot_offset * i] =
+ pcm_buffer[i];
+ }
+ /* If all the data of this buffer is
+ transmitted */
+ if (last_data) {
+ ch_bd->flag = 0;
+ ch_bd->offset = 0;
+ channel->p_ch_data->tx_out_data =
+ ch_bd->wrap ?
+ channel->p_ch_data->tx_data_fifo
+ : ch_bd+1;
+ port->port_stat.tx_pkt_conf_count++;
+ } else {
+ ch_bd->offset += ch_data_len *
+ (adap->adapt_cfg.slot_width);
+ }
+#ifdef TDM_CORE_DEBUG
+ data_flag = 1;
+#endif
+ }
+ spin_unlock(&channel->p_ch_data->tx_channel_lock);
+ }
+ }
+
+#ifdef TDM_CORE_DEBUG
+ if (data_flag) {
+ pr_info("TX-TDM Interleaved Data-\n");
+ for (i = 0; i < 64; i++)
+ pr_info("%x", output_tdm_buffer[i]);
+ pr_info("\n");
+ }
+#endif
+ return TDM_E_OK;
+}
+
+/* Channel Level APIs of TDM Framework */
+int tdm_channel_open(u16 chanid, u16 ch_width, struct tdm_port *port,
+ void **h_channel)
+{
+ struct tdm_channel *channel, *temp;
+ unsigned long flags;
+ struct tdm_ch_data *p_ch_data;
+ int res = TDM_E_OK;
+
+ if (!(port && h_channel)) {
+ pr_err("%s: Invalid handle\n", __func__);
+ return -EINVAL;
+ }
+
+ if (ch_width != 1) {
+ pr_err("%s: Mode not supported\n", __func__);
+ return -EINVAL;
+ }
+
+ list_for_each_entry_safe(channel, temp, &port->mychannels, list) {
+ if (channel->ch_id == chanid) {
+ pr_err("%s: Channel %d already open\n",
+ __func__, chanid);
+ return -EINVAL;
+ }
+ }
+
+ channel = kzalloc(sizeof(*channel), GFP_KERNEL);
+ if (!channel) {
+ res = -ENOMEM;
+ goto out;
+ }
+
+ init_waitqueue_head(&channel->ch_wait_queue);
+ p_ch_data = kzalloc(sizeof(struct tdm_ch_data), GFP_KERNEL);
+ if (!p_ch_data) {
+ res = -ENOMEM;
+ goto outdata;
+ }
+
+ p_ch_data->rx_data_fifo[TDM_CH_RX_BD_RING_SIZE-1].wrap = 1;
+ p_ch_data->tx_data_fifo[TDM_CH_TX_BD_RING_SIZE-1].wrap = 1;
+
+ p_ch_data->rx_in_data = p_ch_data->rx_data_fifo;
+ p_ch_data->rx_out_data = p_ch_data->rx_data_fifo;
+ p_ch_data->tx_in_data = p_ch_data->tx_data_fifo;
+ p_ch_data->tx_out_data = p_ch_data->tx_data_fifo;
+ spin_lock_init(&p_ch_data->rx_channel_lock);
+ spin_lock_init(&p_ch_data->tx_channel_lock);
+
+ channel->p_ch_data = p_ch_data;
+
+ channel->ch_id = chanid;
+ channel->ch_cfg.first_slot = chanid;
+ channel->ch_cfg.num_slots = 1; /* This is 1 for channelized mode and
+ configurable for other modes */
+ channel->port = port;
+ channel->in_use = 1;
+
+ spin_lock_irqsave(&port->ch_list_lock, flags);
+ list_add_tail(&channel->list, &port->mychannels);
+ spin_unlock_irqrestore(&port->ch_list_lock, flags);
+
+ *h_channel = channel;
+
+ return res;
+
+outdata:
+ kfree(channel);
+out:
+ return res;
+}
+EXPORT_SYMBOL(tdm_channel_open);
+
+int tdm_channel_close(u16 chanid, u16 ch_width, struct tdm_port *port,
+ struct tdm_channel *h_channel)
+{
+ struct tdm_channel *channel;
+ unsigned long flags;
+ int res = TDM_E_OK;
+ channel = h_channel;
+
+ if (!(port && channel)) {
+ pr_err("%s: Invalid handle\n", __func__);
+ res = -EINVAL;
+ goto out;
+ }
+
+ if (ch_width != 1) {
+ pr_err("%s: Mode not supported\n", __func__);
+ res = -EINVAL;
+ goto out;
+ }
+
+ spin_lock_irqsave(&port->ch_list_lock, flags);
+ list_del(&channel->list);
+ spin_unlock_irqrestore(&port->ch_list_lock, flags);
+
+out:
+ if (channel)
+ kfree(channel->p_ch_data);
+ kfree(channel);
+ return res;
+}
+EXPORT_SYMBOL(tdm_channel_close);
+
+void init_config_adapter(struct tdm_adapter *adap)
+{
+ struct fsl_tdm_adapt_cfg default_adapt_cfg = {
+ .loopback = e_TDM_PROCESS_NORMAL,
+ .num_ch = NUM_CHANNELS,
+ .ch_size_type = CHANNEL_16BIT_LIN,
+ .frame_len = NUM_SAMPLES_PER_FRAME,
+ .num_frames = NUM_SAMPLES_PER_FRAME,
+ .adap_mode = e_TDM_ADAPTER_MODE_NONE
+ };
+
+ default_adapt_cfg.slot_width = default_adapt_cfg.ch_size_type/3 + 1;
+
+ memcpy(&adap->adapt_cfg, &default_adapt_cfg,
+ sizeof(struct fsl_tdm_adapt_cfg));
+
+ return;
+}
+EXPORT_SYMBOL(init_config_adapter);
+
+static void tdm_data_tasklet_fn(unsigned long data)
+{
+ struct tdm_adapter *adapter;
+ adapter = (struct tdm_adapter *)data;
+ if (adapter != NULL) {
+ tdm_data_tx_interleave(adapter);
+ tdm_data_rx_deinterleave(adapter);
+ }
+}
+
+
+MODULE_AUTHOR("Hemant Agrawal <hemant@freescale.com> and "
+ "Rajesh Gumasta <rajesh.gumasta@freescale.com>");
+MODULE_DESCRIPTION("TDM Driver Framework Core");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tdm/test/Kconfig b/drivers/tdm/test/Kconfig
new file mode 100644
index 0000000..39f9581
--- /dev/null
+++ b/drivers/tdm/test/Kconfig
@@ -0,0 +1,29 @@
+#
+# TDM TEST MODULE
+#
+
+menu "TDM test"
+
+config TDM_TEST
+ tristate "TDM test Module"
+ depends on FSL_SOC
+ ---help---
+ This TDM test module is a small test module which
+ registers with the TDM core(framework) and sets up
+ a TDM Voice path between diff channels of a slic.
+
+config UCC_TDM_TEST
+ tristate "UCC TDM test Module"
+ depends on FSL_SOC || CONFIG_QE
+ ---help---
+ This UCC TDM test module is a small test module to test
+ ucc tdm transfer and receive data via ucc1.
+
+config TDM_LOOPBACK_TEST
+ tristate "TDM Loopback test Module"
+ depends on FSL_SOC
+ ---help---
+ This TDM Loopback test module is a small test module which
+ performs a simple internal loopback testing.
+
+endmenu
diff --git a/drivers/tdm/test/Makefile b/drivers/tdm/test/Makefile
new file mode 100644
index 0000000..47bb4ef
--- /dev/null
+++ b/drivers/tdm/test/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the TDM test module.
+#
+
+obj-$(CONFIG_TDM_TEST) += tdm_test.o
+obj-$(CONFIG_UCC_TDM_TEST) += ucc_tdm_test.o
+obj-$(CONFIG_TDM_LOOPBACK_TEST) += tdm_loopback_test.o
diff --git a/drivers/tdm/test/tdm_loopback_test.c b/drivers/tdm/test/tdm_loopback_test.c
new file mode 100644
index 0000000..49554aa
--- /dev/null
+++ b/drivers/tdm/test/tdm_loopback_test.c
@@ -0,0 +1,251 @@
+/*
+ *
+ * Copyright 2011-2012 Freescale Semiconductor, Inc.
+ *
+ * TDM Loopback Test Module.
+ * This TDM test module is a small test module which registers with the
+ * TDM framework and transfer and receive data in loopback mode and also
+ * compares if the data sent is received correctly.
+ *
+ * Author: Sandeep Kumar Singh <sandeep@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+#include <linux/wait.h>
+#include <linux/param.h>
+#include <linux/tdm.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/tdm.h>
+
+
+#define DRV_DESC "Test Module for Freescale Platforms with TDM support"
+#define DRV_NAME "tdm_test"
+
+
+#define POLL_COUNT 38
+#define TDM_FRAME_LENGTH NUM_SAMPLES_PER_FRAME
+#define TDM_E_OK 0
+#define BUF_COUNT 7
+
+#define DEBUG 0
+
+int poll_count = POLL_COUNT;
+module_param(poll_count, int, 0);
+
+static struct task_struct *tdm_thread_task;
+static struct tdm_driver test_tdmdev_driver;
+struct tdm_port *tdmport;
+int tdm_thread_state;
+
+static int tdm_check_data(unsigned short *tx_data, unsigned short *rx_data)
+{
+ int i, error = 0;
+ static int call_count;
+
+ for (i = 1; i < TDM_FRAME_LENGTH; i++) {
+ if (tx_data[i] != rx_data[i])
+ error++;
+ else
+ continue;
+ }
+
+ pr_info("Iteration: %d\n", ++call_count);
+#if DEBUG
+ pr_info("TX DATA:\n");
+ for (i = 0; i < TDM_FRAME_LENGTH; i++) {
+ pr_info("%5x ", tx_data[i]);
+ if (i%20 == 19)
+ pr_info("\n");
+ }
+ pr_info("RX DATA:\n");
+ for (i = 0; i < TDM_FRAME_LENGTH; i++) {
+ pr_info("%5x ", rx_data[i]);
+ if (i%20 == 19)
+ pr_info("\n");
+ }
+#endif
+ if (error)
+ pr_info("TX and RX buffer do NOT match. Err_count:"
+ "%d\n", error);
+ else
+ pr_info("TX and RX buffer MATCH\n");
+
+ return error;
+}
+
+
+static int tdm_thread(void *ptr)
+{
+ void *h_port;
+ void *h_channel1;
+ int ret = TDM_E_OK;
+ int poll = 0;
+ int i = 0, j = 0;
+ int index = 0;
+ int error_count = 0;
+ int buffer_size;
+ uint16_t size = TDM_FRAME_LENGTH;
+ u16 ch1_id = 0;
+ unsigned short *tx_data[BUF_COUNT];
+ unsigned short *rx_data[BUF_COUNT];
+
+ tdm_thread_state = 1;
+
+ /* Open port */
+ ret = tdm_port_open(&test_tdmdev_driver, &h_port);
+ pr_debug("%s tdm_port_open ret = %d\n", __func__, ret);
+ if ((ret != TDM_E_OK) || (h_port == NULL)) {
+ pr_err("Error in tdm_port_open- ret %x\n", ret);
+ goto port1_failed;
+ }
+ /* Open Channel 1*/
+ ret = tdm_channel_open(ch1_id, 1, h_port, &h_channel1);
+ if ((ret != TDM_E_OK) || (h_channel1 == NULL)) {
+ pr_err("Error in tdm_channel_open(%d)- ret %x\n", ch1_id, ret);
+ goto ch1_failed;
+ }
+
+ buffer_size = sizeof(unsigned short)*BUF_COUNT*TDM_FRAME_LENGTH;
+ tx_data[0] = kmalloc(buffer_size, GFP_KERNEL);
+ rx_data[0] = kmalloc(buffer_size, GFP_KERNEL);
+
+ if ((tx_data[0] == NULL) || (rx_data[0] == NULL)) {
+ pr_err("Failed to get memory for buffer");
+ return 0;
+ }
+ for (i = 0; i < BUF_COUNT-1; i++) {
+ tx_data[i+1] = tx_data[i] + TDM_FRAME_LENGTH;
+ rx_data[i+1] = rx_data[i] + TDM_FRAME_LENGTH;
+ }
+ while ((poll < poll_count) && !kthread_should_stop()) {
+
+ poll++;
+ while (tdm_ch_poll(h_channel1, 10) != TDM_E_OK)
+ continue;
+ for (i = 0; i < TDM_FRAME_LENGTH; i++)
+ tx_data[index][i] = j*TDM_FRAME_LENGTH+i;
+
+ ret = tdm_channel_write(h_port, h_channel1, tx_data[index],
+ size);
+ if (ret != TDM_E_OK)
+ pr_info("Error in tdm_channel_write\n");
+ ret = tdm_channel_read(h_port, h_channel1, rx_data[index],
+ &size);
+ if (ret != TDM_E_OK)
+ pr_info("Error in tdm_channel_read\n");
+ /*
+ * There is a delay of 6 frame between transmitted data and
+ * received data. Hence we compare tx_data[0] with rx data[6]
+ * and so on
+ */
+ if (j++ > BUF_COUNT)
+ error_count += tdm_check_data(tx_data[(index + 1)
+ %BUF_COUNT], rx_data[index]);
+ index++;
+ index = index%BUF_COUNT;
+
+ }
+ pr_info("\nTDM Loppback test completed.\n");
+ if (error_count == 0)
+ pr_info("TDM loopback test PASSED!\n");
+ else
+ pr_info("TDM loopback test FAILED!\n");
+
+ ret = tdm_channel_close(ch1_id, 1, h_port, h_channel1);
+ if (ret != TDM_E_OK) {
+ pr_err("Error in tdm_channel_close(%d)- ret %x\n", ch1_id, ret);
+ ret = -ENXIO;
+ }
+
+ ret = tdm_port_close(h_port);
+ pr_debug("%s tdm_port_close ret = %d\n", __func__, ret);
+ if (ret != TDM_E_OK) {
+ pr_err("Error in tdm_port_close- ret %x\n", ret);
+ ret = -ENXIO;
+ }
+
+ tdm_thread_state = 0;
+
+ return ret;
+
+ch1_failed:
+ tdm_channel_close(ch1_id, 1, h_port, h_channel1);
+port1_failed:
+ tdm_port_close(h_port);
+ return -ENXIO;
+}
+
+static int test_attach_adapter(struct tdm_adapter *adap)
+{
+ tdm_thread_state = 0;
+ tdm_thread_task = kthread_run(tdm_thread, NULL, "tdm_thread");
+
+ return 0;
+}
+
+static int test_detach_adapter(struct tdm_adapter *adap)
+{
+ if (tdm_thread_state)
+ kthread_stop(tdm_thread_task);
+
+ return 0;
+}
+
+static const struct tdm_device_id tdm_loopback_test_id[] = {
+ { "fsl_tdm", 0 },
+ { }
+};
+
+static struct tdm_driver test_tdmdev_driver = {
+ .attach_adapter = test_attach_adapter,
+ .detach_adapter = test_detach_adapter,
+ .id_table = tdm_loopback_test_id,
+};
+
+static int __init tdm_loopback_test_init(void)
+{
+ int ret;
+ pr_info("TDM LOOPBACK TEST: \n");
+ test_tdmdev_driver.id = 1;
+
+ /* create a binding with TDM driver */
+ ret = tdm_add_driver(&test_tdmdev_driver);
+ if (ret == 0)
+ pr_info("TDM LOOPBACK TEST module installed\n");
+ else
+ pr_err("%s tdm_port_init failed\n", __func__);
+ return ret;
+}
+
+static void __exit tdm_loopback_test_exit(void)
+{
+ tdm_unregister_driver(&test_tdmdev_driver);
+ pr_info("TDM LOOPBACK TEST module un-installed\n");
+}
+
+module_init(tdm_loopback_test_init);
+module_exit(tdm_loopback_test_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sandeep Kumar Singh <sandeep@freescale.com>");
+MODULE_DESCRIPTION("Test Loopback Test Module for Freescale Platforms"
+" with TDM support");
diff --git a/drivers/tdm/test/tdm_test.c b/drivers/tdm/test/tdm_test.c
new file mode 100644
index 0000000..40ea699
--- /dev/null
+++ b/drivers/tdm/test/tdm_test.c
@@ -0,0 +1,251 @@
+/*
+ * drivers/tdm/test/tdm_test.c
+ *
+ * Copyright (C) 2008-2012 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * TDM Test Module.
+ * This TDM test module is a small test module which registers with the
+ * TDM framework and sets up a TDM Voice path between Port 0
+ * and Port 1 for each slic.
+ *
+ * Author:Hemant Agrawal <hemant@freescale.com>
+ * Rajesh Gumasta <rajesh.gumasta@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+#include <linux/wait.h>
+#include <linux/param.h>
+#include <linux/tdm.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/tdm.h>
+#include "../device/tdm_fsl.h"
+
+#define DRV_DESC "Test Module for Freescale Platforms with TDM support"
+#define DRV_NAME "tdm_test"
+
+#define TDM_FRAME_LENGTH NUM_SAMPLES_PER_FRAME
+#define TDM_E_OK 0
+#define FRAME_SIZE 0x500
+#define POLL_COUNT 5000
+
+static struct task_struct *tdm_thread_task;
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Hemant Agrawal <hemant@freescale.com> and "
+ "Rajesh Gumasta <rajesh.gumasta@freescale.com>");
+MODULE_DESCRIPTION(DRV_DESC);
+
+static struct tdm_driver test_tdmdev_driver;
+struct tdm_port *tdmport;
+int tdm_thread_state;
+
+static int tdm_thread(void *ptr)
+{
+ int ret = TDM_E_OK;
+ int poll = 0, poll_count = POLL_COUNT;
+ void *h_port;
+ void *h_channel1, *h_channel2, *h_channel3, *h_channel4;
+ unsigned short p_data1[TDM_FRAME_LENGTH];
+ unsigned short p_data2[TDM_FRAME_LENGTH];
+ uint16_t size = TDM_FRAME_LENGTH;
+ u16 ch1_id = 0, ch2_id = 1, ch3_id = 2, ch4_id = 3;
+ tdm_thread_state = 1;
+
+ /* Open port */
+ ret = tdm_port_open(&test_tdmdev_driver, &h_port);
+ pr_debug("%s tdm_port_open ret = %d\n", __func__, ret);
+ if ((ret != TDM_E_OK) || (h_port == NULL)) {
+ pr_err("Error in tdm_port_open- ret %x\n", ret);
+ goto port1_failed;
+ }
+ /* Open Channel 1*/
+ ret = tdm_channel_open(ch1_id, 1, h_port, &h_channel1);
+ if ((ret != TDM_E_OK) || (h_channel1 == NULL)) {
+ pr_err("Error in tdm_channel_open(%d)- ret %x\n", ch1_id, ret);
+ goto ch1_failed;
+ }
+
+ /* Open Channel 2*/
+ ret = tdm_channel_open(ch2_id, 1, h_port, &h_channel2);
+ if ((ret != TDM_E_OK) || (h_channel2 == NULL)) {
+ pr_err("Error in tdm_channel_open(%d)- ret %x\n", ch2_id, ret);
+ goto ch2_failed;
+ }
+
+ /* Open Channel 3*/
+ ret = tdm_channel_open(ch3_id, 1, h_port, &h_channel3);
+ if ((ret != TDM_E_OK) || (h_channel3 == NULL)) {
+ pr_err("Error in tdm_channel_open(%d)- ret %x\n", ch3_id, ret);
+ goto ch3_failed;
+ }
+
+ /* Open Channel 4*/
+ ret = tdm_channel_open(ch4_id, 1, h_port, &h_channel4);
+ if ((ret != TDM_E_OK) || (h_channel4 == NULL)) {
+ pr_err("Error in tdm_channel_open(%d)- ret %x\n", ch4_id, ret);
+ goto ch4_failed;
+ }
+
+ while ((poll < poll_count) && !kthread_should_stop()) {
+
+ poll++;
+ while (tdm_ch_poll(h_channel1, 10) != TDM_E_OK)
+ continue;
+
+ ret = tdm_channel_read(h_port, h_channel1, p_data1, &size);
+ if (ret != TDM_E_OK)
+ pr_info("Error in tdm_channel_read\n");
+
+ ret = tdm_channel_write(h_port, h_channel2, p_data1, size);
+ if (ret != TDM_E_OK)
+ pr_info("Error in tdm_channel_write\n");
+
+ ret = tdm_channel_read(h_port, h_channel2, p_data1, &size);
+ if (ret != TDM_E_OK)
+ pr_info("Error in tdm_channel_read\n");
+
+ ret = tdm_channel_write(h_port, h_channel1, p_data1, size);
+ if (ret != TDM_E_OK)
+ pr_info("Error in tdm_channel_write\n");
+
+ ret = tdm_channel_read(h_port, h_channel3, p_data2, &size);
+ if (ret != TDM_E_OK)
+ pr_info("Error in tdm_channel_read\n");
+
+ ret = tdm_channel_write(h_port, h_channel4, p_data2, size);
+ if (ret != TDM_E_OK)
+ pr_info("Error in tdm_channel_write\n");
+
+ ret = tdm_channel_read(h_port, h_channel4, p_data2, &size);
+ if (ret != TDM_E_OK)
+ pr_info("Error in tdm_channel_read\n");
+
+ ret = tdm_channel_write(h_port, h_channel3, p_data2, size);
+ if (ret != TDM_E_OK)
+ pr_info("Error in tdm_channel_write\n");
+ }
+ pr_info("\n CLOSING THE TDM TEST\n");
+ ret = tdm_channel_close(ch4_id, 1, h_port, h_channel4);
+ if (ret != TDM_E_OK) {
+ pr_err("Error in tdm_channel_close(%d)- ret %x\n", ch4_id, ret);
+ ret = -ENXIO;
+ }
+
+ ret = tdm_channel_close(ch3_id, 1, h_port, h_channel3);
+ if (ret != TDM_E_OK) {
+ pr_err("Error in tdm_channel_close(%d)- ret %x\n", ch3_id, ret);
+ ret = -ENXIO;
+ }
+
+ ret = tdm_channel_close(ch2_id, 1, h_port, h_channel2);
+ if (ret != TDM_E_OK) {
+ pr_err("Error in tdm_channel_close(%d)- ret %x\n", ch2_id, ret);
+ ret = -ENXIO;
+ }
+
+ ret = tdm_channel_close(ch1_id, 1, h_port, h_channel1);
+ if (ret != TDM_E_OK) {
+ pr_err("Error in tdm_channel_close(%d)- ret %x\n", ch4_id, ret);
+ ret = -ENXIO;
+ }
+
+ ret = tdm_port_close(h_port);
+ pr_debug("%s tdm_port_close ret = %d\n", __func__, ret);
+ if (ret != TDM_E_OK) {
+ pr_err("Error in tdm_port_close(%d)- ret %x\n", ch1_id, ret);
+ ret = -ENXIO;
+ }
+
+ tdm_thread_state = 0;
+
+ return ret;
+
+ch4_failed:
+ tdm_channel_close(ch4_id, 1, h_port, h_channel4);
+ch3_failed:
+ tdm_channel_close(ch3_id, 1, h_port, h_channel3);
+ch2_failed:
+ tdm_channel_close(ch2_id, 1, h_port, h_channel2);
+ch1_failed:
+ tdm_channel_close(ch1_id, 1, h_port, h_channel1);
+port1_failed:
+ tdm_port_close(h_port);
+ return -ENXIO;
+}
+
+static int test_attach_adapter(struct tdm_adapter *adap)
+{
+ pr_debug("tdm-dev: adapter [%s] registered as minor %d\n",
+ adap->name, adap->id);
+ tdm_thread_state = 0;
+ tdm_thread_task = kthread_run(tdm_thread, NULL, "tdm_thread");
+
+ return 0;
+}
+
+static int test_detach_adapter(struct tdm_adapter *adap)
+{
+ if (tdm_thread_state)
+ kthread_stop(tdm_thread_task);
+
+ pr_debug("tdm-dev: adapter [%s] unregistered\n", adap->name);
+
+ return 0;
+}
+
+static const struct tdm_device_id test_id[] = {
+ { "fsl_tdm", 0 },
+ { }
+};
+
+static struct tdm_driver test_tdmdev_driver = {
+ .attach_adapter = test_attach_adapter,
+ .detach_adapter = test_detach_adapter,
+ .id_table = test_id,
+};
+
+static int __init tdm_test_init(void)
+{
+ int ret;
+ pr_info("TDM_TEST: " DRV_DESC "\n");
+
+ test_tdmdev_driver.id = 1;
+ /* create a binding with TDM driver */
+ ret = tdm_add_driver(&test_tdmdev_driver);
+ if (ret == 0)
+ pr_info("TDM_TEST module installed\n");
+ else
+ pr_err("%s tdm_port_init failed\n", __func__);
+
+ return ret;
+
+}
+
+static void __exit tdm_test_exit(void)
+{
+ tdm_unregister_driver(&test_tdmdev_driver);
+ pr_info("TDM_TEST module un-installed\n");
+}
+
+module_init(tdm_test_init);
+module_exit(tdm_test_exit);
diff --git a/drivers/tdm/test/ucc_tdm_test.c b/drivers/tdm/test/ucc_tdm_test.c
new file mode 100644
index 0000000..f4112bd
--- /dev/null
+++ b/drivers/tdm/test/ucc_tdm_test.c
@@ -0,0 +1,169 @@
+/*
+ *
+ * Copyright 2011-2012 Freescale Semiconductor, Inc.
+ *
+ * TDM Test Module.
+ * This TDM test module is a small test module which registers with the
+ * TDM framework and transfer and receive data via UCC1.
+ *
+ * Author: Kai Jiang <Kai.Jiang@freescale.com>
+ * Modifier: Jiucheng Xu <Jiucheng.Xu@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+#include <linux/wait.h>
+#include <linux/param.h>
+#include <linux/tdm.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/tdm.h>
+
+#define READ_LEN (72 * 32) /* BD buffer max len */
+#define WRITE_LEN 0x80
+#define READ_COUNT 4 /* BD ring len */
+
+static struct task_struct *tdm_thread_task;
+static struct tdm_driver test_tdmdev_driver;
+static int ucc_num = 1;
+static int forward;
+static u8 *buf;
+
+module_param(ucc_num, int, S_IRUGO);
+module_param(forward, int, S_IRUGO);
+
+static int tdm_check_data(void)
+{
+ int i, j;
+ unsigned long stamp;
+
+ stamp = jiffies + HZ; /* 1 sec for overtime */
+ while (time_before(jiffies, stamp)) {
+ memset(buf, 0xff, READ_LEN);
+ tdm_read_direct(test_tdmdev_driver.adapter, buf, READ_LEN);
+
+ for (i = 0; (i < READ_LEN); i++) {
+ if (buf[i] != 0xff) {
+ for (j = 0; j < WRITE_LEN; j += 4)
+ pr_info("%x\t%x\t%x\t%x\n",
+ buf[i+j], buf[i+j+1],
+ buf[i+j+2], buf[i+j+3]);
+ return 0;
+ }
+ }
+ }
+
+ pr_warn("ucc_tdm_test: check data overtime\n");
+ return 0;
+}
+
+static int tdm_thread(void *ptr)
+{
+ int i;
+
+ tdm_adap_enable(&test_tdmdev_driver);
+
+ if (forward == 1) {
+ /* data forwarding application for zarlink */
+ while (!kthread_should_stop()) {
+ memset(buf, 0, READ_LEN);
+ tdm_read_direct(test_tdmdev_driver.adapter, buf,
+ READ_LEN);
+ tdm_write_direct(test_tdmdev_driver.adapter, buf,
+ READ_LEN);
+ }
+ } else {
+ /* transmit-recieve test with loopback cable */
+ for (i = 0; i < WRITE_LEN; i++)
+ buf[i] = i; /* generate test data */
+
+ tdm_write_direct(test_tdmdev_driver.adapter, buf,
+ WRITE_LEN);
+
+ tdm_check_data();
+ }
+
+ tdm_adap_disable(&test_tdmdev_driver);
+
+ return 0;
+}
+
+static int test_attach_adapter(struct tdm_adapter *adap)
+{
+ buf = kmalloc(READ_LEN, GFP_KERNEL);
+ if (!buf) {
+ dev_err(adap->parent, "No memory for TDM\n");
+ return -ENOMEM;
+ }
+
+ tdm_thread_task = kthread_run(tdm_thread, NULL, "tdm_thread");
+
+ return 0;
+}
+
+static int test_detach_adapter(struct tdm_adapter *adap)
+{
+ if (forward == 1)
+ kthread_stop(tdm_thread_task);
+
+ kfree(buf);
+
+ return 0;
+}
+
+static const struct tdm_device_id test_ucc_tdm_id[] = {
+ { "tdm_ucc_1", 0 },
+ { }
+};
+
+static struct tdm_driver test_tdmdev_driver = {
+ .attach_adapter = test_attach_adapter,
+ .detach_adapter = test_detach_adapter,
+ .id_table = test_ucc_tdm_id,
+};
+
+static int __init tdm_test_init(void)
+{
+ if ((ucc_num < 0) || (ucc_num > 8))
+ pr_warn("ucc_tdm_test: invalid ucc_num %d(1 ~7), "
+ "use the defaut ucc_num = 1\n", ucc_num);
+ else
+ sprintf((char *)test_ucc_tdm_id[0].name, "%s%d",
+ "tdm_ucc_", ucc_num);
+
+ test_tdmdev_driver.id = 1;
+
+ /* create a binding with TDM driver */
+ return tdm_add_driver(&test_tdmdev_driver);
+}
+
+static void __exit tdm_test_exit(void)
+{
+ tdm_unregister_driver(&test_tdmdev_driver);
+}
+
+module_init(tdm_test_init);
+module_exit(tdm_test_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR(" Kai Jiang <Kai.Jiang@freescale.com>");
+MODULE_DESCRIPTION("Test Module for Freescale Platforms with TDM support");
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 4f6e01c..f644226 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -323,6 +323,14 @@ static const struct serial8250_config uart_config[] = {
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO | UART_CAP_AFE,
},
+ [PORT_16550A_FSL64] = {
+ .name = "16550A_FSL64",
+ .fifo_size = 64,
+ .tx_loadsz = 32,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
+ UART_FCR7_64BYTE,
+ .flags = UART_CAP_FIFO,
+ },
};
/* Uart divisor latch read */
@@ -899,7 +907,17 @@ static void autoconfig_16550a(struct uart_8250_port *up)
up->port.type = PORT_16650;
up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
} else {
- DEBUG_AUTOCONF("Motorola 8xxx DUART ");
+ serial_out(up, UART_LCR, 0);
+ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
+ UART_FCR7_64BYTE);
+ status1 = serial_in(up, UART_IIR) >> 5;
+ serial_out(up, UART_FCR, 0);
+ serial_out(up, UART_LCR, 0);
+
+ if (status1 == 7)
+ up->port.type = PORT_16550A_FSL64;
+ else
+ DEBUG_AUTOCONF("Motorola 8xxx DUART ");
}
serial_out(up, UART_EFR, 0);
return;
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index 5a90914..b19f25d 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -122,6 +122,43 @@ config UIO_PRUSS
To compile this driver as a module, choose M here: the module
will be called uio_pruss.
+config UIO_FSL_SRIO
+ tristate "Freescale Serial RapidIO support"
+ depends on RAPIDIO=n
+ default n
+
+config UIO_FSL_RMU
+ tristate "Freescale RapidIO Message Unit support"
+ depends on RAPIDIO=n
+ default n
+ help
+ UIO driver for the Freescale RapidIO Message Unit and Doorbell.
+ This driver will obtain the RMU nodes from DTB structure, and
+ expose the RMU regiter space to user space.
+
+ If you don't know what to do here, say N.
+
+config UIO_FSL_DMA
+ tristate "Freescale DMA support"
+ depends on FSL_DMA=n
+ default n
+
+config UIO_FSL_SEC
+ tristate "Freescale SEC support"
+ depends on CRYPTO_DEV_FSL_CAAM=n
+ default n
+
+config UIO_FSL_SRAM
+ bool "Freescale L2CACHE for SRAM support"
+ depends on FSL_85XX_CACHE_SRAM=n
+ default n
+ help
+ UIO driver for the Freescale SRAM space. This driver will obtain
+ the SRAM nodes from DTB structure, and expose the SRAM space to
+ user space.
+
+ If you don't know what to do here, say N.
+
config UIO_MF624
tristate "Humusoft MF624 DAQ PCI card driver"
depends on PCI
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
index d3218bd..b770d4e 100644
--- a/drivers/uio/Makefile
+++ b/drivers/uio/Makefile
@@ -7,4 +7,9 @@ obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o
obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o
obj-$(CONFIG_UIO_NETX) += uio_netx.o
obj-$(CONFIG_UIO_PRUSS) += uio_pruss.o
+obj-$(CONFIG_UIO_FSL_SRIO) += fsl_srio_uio.o
+obj-$(CONFIG_UIO_FSL_RMU) += fsl_rmu_uio.o
+obj-$(CONFIG_UIO_FSL_DMA) += fsl_dma_uio.o
+obj-$(CONFIG_UIO_FSL_SEC) += fsl_sec_uio.o
+obj-$(CONFIG_UIO_FSL_SRAM) += fsl_sram_uio.o
obj-$(CONFIG_UIO_MF624) += uio_mf624.o
diff --git a/drivers/uio/fsl_dma_uio.c b/drivers/uio/fsl_dma_uio.c
new file mode 100644
index 0000000..fca99bf
--- /dev/null
+++ b/drivers/uio/fsl_dma_uio.c
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2011-2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Kai Jiang <Kai.Jiang@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/module.h>
+#include <linux/uio_driver.h>
+#include <linux/list.h>
+#include <linux/io.h>
+
+static const char dma_uio_version[] = "DMA UIO driver v1.0";
+
+#define DMA_SR 0x4 /* DMA Status Regsiter */
+
+struct dma_uio_info {
+ atomic_t ref; /* exclusive, only one open() at a time */
+ struct uio_info uio;
+ char name[20];
+};
+
+struct dma_chan {
+ struct device *dev;
+ struct resource *res;
+ struct dma_uio_info *info;
+ struct list_head list;
+ void __iomem *regs_win;
+ int irq;
+ u32 dma_id;
+ u32 ch_id;
+};
+
+struct fsldma_device {
+ struct platform_device *dev;
+ struct list_head ch_list;
+ u32 dma_id;
+};
+
+static int dma_uio_open(struct uio_info *info, struct inode *inode)
+{
+ struct dma_uio_info *i = container_of(info, struct dma_uio_info, uio);
+ if (!atomic_dec_and_test(&i->ref)) {
+ pr_err("%s: failing non-exclusive open()\n", i->name);
+ atomic_inc(&i->ref);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int dma_uio_release(struct uio_info *info, struct inode *inode)
+{
+ struct dma_uio_info *i = container_of(info, struct dma_uio_info, uio);
+ atomic_inc(&i->ref);
+
+ return 0;
+}
+
+static irqreturn_t dma_uio_irq_handler(int irq, struct uio_info *dev_info)
+{
+ struct dma_chan *dma_ch = dev_info->priv;
+
+ out_be32((u32 *)((u8 *)dma_ch->regs_win + DMA_SR), ~0);
+
+ return IRQ_HANDLED;
+}
+
+static int __init dma_chan_uio_setup(struct dma_chan *dma_ch)
+{
+ int ret;
+ struct dma_uio_info *info;
+
+ info = devm_kzalloc(dma_ch->dev, sizeof(struct dma_uio_info),
+ GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ dma_ch->info = info;
+
+ atomic_set(&info->ref, 1);
+ snprintf(info->name, sizeof(info->name)-1, "dma-uio%d-%d",
+ dma_ch->dma_id, dma_ch->ch_id);
+ info->uio.name = info->name;
+ info->uio.version = dma_uio_version;
+ info->uio.mem[0].name = "dma regs";
+ info->uio.mem[0].addr = dma_ch->res->start;
+ info->uio.mem[0].size = (dma_ch->res->end - dma_ch->res->start + 1 >
+ PAGE_SIZE) ?
+ dma_ch->res->end - dma_ch->res->start + 1 : PAGE_SIZE;
+ info->uio.mem[0].internal_addr = dma_ch->regs_win;
+ info->uio.mem[0].memtype = UIO_MEM_PHYS;
+
+ info->uio.irq = dma_ch->irq;
+ info->uio.irq_flags = IRQF_SHARED;
+ info->uio.handler = dma_uio_irq_handler;
+ info->uio.open = dma_uio_open;
+ info->uio.release = dma_uio_release;
+ info->uio.priv = dma_ch;
+
+ ret = uio_register_device(dma_ch->dev, &info->uio);
+ if (ret) {
+ dev_err(dma_ch->dev, "dma_uio: UIO registration failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int fsl_dma_chan_probe(struct fsldma_device *fdev,
+ struct device_node *node)
+{
+ struct resource regs;
+ struct dma_chan *dma_ch;
+ struct device_node *dma_node;
+ int err;
+ u32 *cell;
+ struct platform_device *dev = fdev->dev;
+
+ dma_node = node;
+ dev_dbg(&dev->dev, "Of-device full name %s\n", dma_node->full_name);
+
+ dma_ch = devm_kzalloc(&dev->dev, sizeof(struct dma_chan), GFP_KERNEL);
+ if (!dma_ch) {
+ dev_err(&dev->dev, "Can't alloc memory for 'dma_ch'\n");
+ return -ENOMEM;
+ }
+
+ cell = (u32 *)of_get_property(dma_node, "cell-index", NULL);
+ if (!cell) {
+ dev_err(&dev->dev, "Can't get property 'cell-index'\n");
+ return -EFAULT;
+ }
+
+ dma_ch->dma_id = fdev->dma_id;
+ dma_ch->ch_id = *cell;
+ dma_ch->dev = &dev->dev;
+
+ err = of_address_to_resource(dma_node, 0, &regs);
+ if (err < 0) {
+ dev_err(&dev->dev, "Can't get property 'reg'\n");
+ return -EFAULT;
+ }
+
+ dma_ch->res = devm_request_mem_region(&dev->dev, regs.start,
+ regs.end + 1 - regs.start, "dma");
+ if (dma_ch->res == NULL) {
+ dev_err(&dev->dev, "devm_request_mem_region failed\n");
+ return -ENOMEM;
+ }
+
+ dev_dbg(&dev->dev, "reg start 0x%016llx, size 0x%016llx.\n",
+ dma_ch->res->start, dma_ch->res->end + 1 -
+ dma_ch->res->start);
+
+ dma_ch->regs_win = devm_ioremap(&dev->dev, dma_ch->res->start,
+ dma_ch->res->end - dma_ch->res->start + 1);
+ if (dma_ch->regs_win == NULL) {
+ dev_err(&dev->dev, "devm_ioremap failed\n");
+ return -EIO;
+ }
+
+ dma_ch->irq = irq_of_parse_and_map(dma_node, 0);
+ dev_dbg(dma_ch->dev, "dma channel irq: %d\n", dma_ch->irq);
+
+ err = dma_chan_uio_setup(dma_ch);
+ if (err < 0) {
+ dev_err(dma_ch->dev, "dma_chan_uio_setup failed\n");
+ return err;
+ }
+
+ list_add_tail(&dma_ch->list, &fdev->ch_list);
+
+ dev_info(&dev->dev, "dma channel %s initialized\n", dma_ch->info->name);
+
+ return 0;
+}
+
+static void fsl_dma_chan_remove(struct dma_chan *dma_ch)
+{
+ uio_unregister_device(&dma_ch->info->uio);
+}
+
+static int fsl_dma_uio_probe(struct platform_device *dev)
+{
+ struct device_node *child;
+ struct fsldma_device *fdev;
+ u32 *cell;
+
+ cell = (u32 *)of_get_property(dev->dev.of_node, "cell-index", NULL);
+ if (!cell) {
+ dev_err(&dev->dev, "Can't get property 'cell-index'\n");
+ return -ENODEV;
+ }
+
+ fdev = devm_kzalloc(&dev->dev, sizeof(struct fsldma_device),
+ GFP_KERNEL);
+ if (!fdev) {
+ dev_err(&dev->dev, "Can't alloc memory for 'fdev''\n");
+ return -ENOMEM;
+ }
+
+ fdev->dma_id = *cell;
+ fdev->dev = dev;
+ INIT_LIST_HEAD(&fdev->ch_list);
+ dev_set_drvdata(&dev->dev, fdev);
+
+ for_each_child_of_node(dev->dev.of_node, child)
+ if (of_device_is_compatible(child, "fsl,eloplus-dma-channel"))
+ fsl_dma_chan_probe(fdev, child);
+
+ return 0;
+}
+
+static int fsl_dma_uio_remove(struct platform_device *dev)
+{
+ struct fsldma_device *fdev;
+ struct dma_chan *dma_ch, *ch_tmp;
+
+ fdev = dev_get_drvdata(&dev->dev);
+ list_for_each_entry_safe(dma_ch, ch_tmp, &fdev->ch_list, list) {
+ list_del(&dma_ch->list);
+ fsl_dma_chan_remove(dma_ch);
+ }
+
+ return 0;
+}
+
+
+static const struct of_device_id fsl_of_dma_match[] = {
+ {
+ .compatible = "fsl,eloplus-dma",
+ },
+ {}
+};
+
+static struct platform_driver fsl_dma_uio_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "fsl-of-dma",
+ .of_match_table = fsl_of_dma_match,
+ },
+ .probe = fsl_dma_uio_probe,
+ .remove = fsl_dma_uio_remove,
+};
+
+static __init int fsl_dma_uio_init(void)
+{
+ int err;
+
+ err = platform_driver_register(&fsl_dma_uio_driver);
+ if (err < 0)
+ pr_warn(
+ ": %s:%hu:%s(): platform_driver_register() = %d\n",
+ __FILE__, __LINE__, __func__, err);
+
+ return err;
+}
+
+static void __exit fsl_dma_uio_exit(void)
+{
+ platform_driver_unregister(&fsl_dma_uio_driver);
+
+ pr_warn("fsl dma uio driver removed\n");
+}
+
+module_init(fsl_dma_uio_init);
+module_exit(fsl_dma_uio_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/uio/fsl_rmu_uio.c b/drivers/uio/fsl_rmu_uio.c
new file mode 100644
index 0000000..d7255e3
--- /dev/null
+++ b/drivers/uio/fsl_rmu_uio.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/module.h>
+#include <linux/uio_driver.h>
+#include <linux/list.h>
+#include <linux/io.h>
+
+/* rmu unit ID, based on the unit register off-set */
+#define RMU_UNIT_MSG0 0
+#define RMU_UNIT_MSG1 1
+#define RMU_UNIT_DBELL 4
+
+static const char rmu_uio_version[] = "RMU UIO driver v1.0";
+
+struct rmu_uio_info {
+ atomic_t ref; /* exclusive, only one open() at a time */
+ struct uio_info uio;
+ char name[20];
+};
+
+struct rmu_unit {
+ struct device *dev;
+ struct resource *res;
+ struct rmu_uio_info *info;
+ struct list_head list;
+ void __iomem *regs_win;
+ int irq;
+ u32 unit_id;
+};
+
+struct rmu_device {
+ struct platform_device *pdev;
+ struct list_head unit_list;
+};
+
+static int rmu_uio_open(struct uio_info *info, struct inode *inode)
+{
+ struct rmu_uio_info *i = container_of(info, struct rmu_uio_info, uio);
+ struct rmu_unit *unit = info->priv;
+
+ if (!atomic_dec_and_test(&i->ref)) {
+ dev_err(unit->dev,
+ "%s: failing non-exclusive open()\n", i->name);
+ atomic_inc(&i->ref);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int rmu_uio_release(struct uio_info *info, struct inode *inode)
+{
+ struct rmu_uio_info *i = container_of(info, struct rmu_uio_info, uio);
+
+ atomic_inc(&i->ref);
+
+ return 0;
+}
+
+static int __init rmu_unit_uio_setup(struct rmu_unit *unit)
+{
+ int ret;
+ struct rmu_uio_info *info;
+
+ info = devm_kzalloc(unit->dev, sizeof(struct rmu_uio_info),
+ GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ unit->info = info;
+
+ atomic_set(&info->ref, 1);
+ if (unit->unit_id == RMU_UNIT_DBELL)
+ snprintf(info->name, sizeof(info->name), "rmu-uio-doorbell");
+ else
+ snprintf(info->name, sizeof(info->name), "rmu-uio-msg%d",
+ unit->unit_id);
+
+ info->uio.name = info->name;
+ info->uio.version = rmu_uio_version;
+ info->uio.mem[0].name = "rmu regs";
+ info->uio.mem[0].addr = unit->res->start;
+ info->uio.mem[0].size = resource_size(unit->res);
+ info->uio.mem[0].internal_addr = unit->regs_win;
+ info->uio.mem[0].memtype = UIO_MEM_PHYS;
+ info->uio.open = rmu_uio_open;
+ info->uio.release = rmu_uio_release;
+ info->uio.priv = unit;
+
+ ret = uio_register_device(unit->dev, &info->uio);
+ if (ret) {
+ dev_err(unit->dev, "rmu_uio: UIO registration failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int fsl_rmu_unit_probe(struct rmu_device *rmu_dev,
+ struct device_node *node)
+{
+ struct resource regs;
+ struct rmu_unit *unit;
+ struct device_node *unit_node;
+ int err;
+ struct platform_device *pdev = rmu_dev->pdev;
+
+ unit_node = node;
+ dev_dbg(&pdev->dev, "of-device full name %s\n", unit_node->full_name);
+
+ unit = devm_kzalloc(&pdev->dev, sizeof(struct rmu_unit), GFP_KERNEL);
+ if (!unit) {
+ dev_err(&pdev->dev, "Can't alloc memory for 'rmu_unit'\n");
+ return -ENOMEM;
+ }
+
+ unit->dev = &pdev->dev;
+
+ err = of_address_to_resource(unit_node, 0, &regs);
+ if (err < 0) {
+ dev_err(&pdev->dev, "Can't get property 'reg'\n");
+ return -EFAULT;
+ }
+
+ unit->unit_id = (regs.start >> 8) & 0xf;
+ unit->res = devm_request_mem_region(&pdev->dev, regs.start,
+ resource_size(&regs), "rmu");
+ if (!unit->res) {
+ dev_err(&pdev->dev, "devm_request_mem_region failed\n");
+ return -ENOMEM;
+ }
+
+ dev_dbg(&pdev->dev, "reg start 0x%016llx, size 0x%016llx.\n",
+ unit->res->start, resource_size(unit->res));
+
+ unit->regs_win = devm_ioremap(&pdev->dev, unit->res->start,
+ resource_size(unit->res));
+ if (!unit->regs_win) {
+ dev_err(&pdev->dev, "devm_ioremap failed\n");
+ return -EIO;
+ }
+
+ err = rmu_unit_uio_setup(unit);
+ if (err < 0) {
+ dev_err(unit->dev, "rmu_unit_uio_setup failed\n");
+ return err;
+ }
+
+ list_add_tail(&unit->list, &rmu_dev->unit_list);
+
+ dev_info(&pdev->dev, "rmu unit %s initialized\n", unit->info->name);
+
+ return 0;
+}
+
+static void fsl_rmu_unit_remove(struct rmu_unit *unit)
+{
+ uio_unregister_device(&unit->info->uio);
+}
+
+static int fsl_rmu_uio_probe(struct platform_device *pdev)
+{
+ struct device_node *child;
+ struct rmu_device *rmu_dev;
+
+ rmu_dev = devm_kzalloc(&pdev->dev, sizeof(struct rmu_device),
+ GFP_KERNEL);
+ if (!rmu_dev) {
+ dev_err(&pdev->dev, "Can't alloc memory for 'rmu_dev''\n");
+ return -ENOMEM;
+ }
+
+ rmu_dev->pdev = pdev;
+ INIT_LIST_HEAD(&rmu_dev->unit_list);
+ dev_set_drvdata(&pdev->dev, rmu_dev);
+
+ for_each_child_of_node(pdev->dev.of_node, child)
+ if ((of_device_is_compatible(child, "fsl,srio-msg-unit"))
+ || (of_device_is_compatible(child, "fsl,srio-dbell-unit")))
+ fsl_rmu_unit_probe(rmu_dev, child);
+
+ return 0;
+}
+
+static int fsl_rmu_uio_remove(struct platform_device *pdev)
+{
+ struct rmu_device *rmu_dev;
+ struct rmu_unit *unit, *unit_tmp;
+
+ rmu_dev = dev_get_drvdata(&pdev->dev);
+ list_for_each_entry_safe(unit, unit_tmp,
+ &rmu_dev->unit_list, list) {
+ list_del(&unit->list);
+ fsl_rmu_unit_remove(unit);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id fsl_of_rmu_match[] = {
+ {
+ .compatible = "fsl,srio-rmu",
+ },
+ {}
+};
+
+static struct platform_driver fsl_rmu_uio_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "fsl-of-rmu",
+ .of_match_table = fsl_of_rmu_match,
+ },
+ .probe = fsl_rmu_uio_probe,
+ .remove = fsl_rmu_uio_remove,
+};
+
+static __init int fsl_rmu_uio_init(void)
+{
+ int err;
+
+ err = platform_driver_register(&fsl_rmu_uio_driver);
+ if (err < 0)
+ pr_err("fsl-rmu-uio: failed to register platform driver\n");
+
+ return err;
+}
+
+static void __exit fsl_rmu_uio_exit(void)
+{
+ platform_driver_unregister(&fsl_rmu_uio_driver);
+}
+
+module_init(fsl_rmu_uio_init);
+module_exit(fsl_rmu_uio_exit);
+MODULE_AUTHOR("Liu Gang <Gang.Liu@freescale.com>");
+MODULE_DESCRIPTION("UIO driver for Freescale RMU");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/uio/fsl_sec_uio.c b/drivers/uio/fsl_sec_uio.c
new file mode 100644
index 0000000..34f088d
--- /dev/null
+++ b/drivers/uio/fsl_sec_uio.c
@@ -0,0 +1,385 @@
+/*
+ * Copyright 2012-2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Po Liu <po.liu@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/io.h>
+#include <linux/uio_driver.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+
+static const char sec_uio_version[] = "fsl SEC UIO driver v1.0";
+
+#define NAME_LENGTH 30
+#define JR_INDEX_OFFSET 12
+
+static const char uio_device_name[NAME_LENGTH] = "fsl-sec";
+static LIST_HEAD(sec_list);
+
+struct sec_uio_info {
+ atomic_t ref; /* exclusive, only one open() at a time */
+ struct uio_info uio;
+ char name[NAME_LENGTH];
+};
+
+struct sec_dev {
+ u32 revision;
+ u32 index;
+ u32 irq;
+ void __iomem *global_regs;
+ struct device *dev;
+ struct resource res;
+ struct sec_uio_info info;
+ struct list_head node;
+ struct list_head jr_list;
+};
+
+struct sec_job_ring {
+ struct list_head list_node;
+ u32 index;
+ u32 irq;
+ struct device *dev;
+ struct sec_uio_info info;
+ struct resource *res;
+};
+
+static int sec_uio_open(struct uio_info *info, struct inode *inode)
+{
+ struct sec_uio_info *uio_info = container_of(info,
+ struct sec_uio_info, uio);
+
+ if (!atomic_dec_and_test(&uio_info->ref)) {
+ pr_err("%s: failing non-exclusive open()\n", uio_info->name);
+ atomic_inc(&uio_info->ref);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int sec_uio_release(struct uio_info *info, struct inode *inode)
+{
+ struct sec_uio_info *uio_info = container_of(info,
+ struct sec_uio_info, uio);
+ atomic_inc(&uio_info->ref);
+
+ return 0;
+}
+
+static irqreturn_t sec_uio_irq_handler(int irq, struct uio_info *dev_info)
+{
+ return IRQ_NONE;
+}
+
+static int sec_uio_irqcontrol(struct uio_info *dev_info, int irqon)
+{
+ return 0;
+}
+
+static irqreturn_t sec_jr_irq_handler(int irq, struct uio_info *dev_info)
+{
+ return IRQ_NONE;
+}
+
+static int sec_jr_irqcontrol(struct uio_info *dev_info, int irqon)
+{
+ return 0;
+}
+
+static int __init sec_uio_init(struct sec_dev *uio_dev)
+{
+ int ret;
+ struct sec_uio_info *info;
+
+ info = &uio_dev->info;
+ atomic_set(&info->ref, 1);
+ info->uio.version = sec_uio_version;
+ info->uio.name = uio_dev->info.name;
+ info->uio.mem[0].name = "sec config space";
+ info->uio.mem[0].addr = uio_dev->res.start;
+ info->uio.mem[0].size = uio_dev->res.end - uio_dev->res.start + 1;
+ info->uio.mem[0].internal_addr = uio_dev->global_regs;
+ info->uio.mem[0].memtype = UIO_MEM_PHYS;
+ info->uio.irq = uio_dev->irq;
+ info->uio.irq_flags = IRQF_SHARED;
+ info->uio.handler = sec_uio_irq_handler;
+ info->uio.irqcontrol = sec_uio_irqcontrol;
+ info->uio.open = sec_uio_open;
+ info->uio.release = sec_uio_release;
+ info->uio.priv = uio_dev;
+
+ ret = uio_register_device(uio_dev->dev, &info->uio);
+ if (ret) {
+ pr_err("sec_uio: UIO registration failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int __init sec_jr_uio_init(struct sec_job_ring *jr)
+{
+ int ret;
+ struct sec_uio_info *info;
+
+ info = &jr->info;
+ atomic_set(&info->ref, 1);
+ info->uio.version = sec_uio_version;
+ info->uio.name = jr->info.name;
+ info->uio.mem[0].name = "sec job ring";
+ info->uio.mem[0].addr = jr->res->start;
+ info->uio.mem[0].size = jr->res->end - jr->res->start + 1;
+ info->uio.mem[0].memtype = UIO_MEM_PHYS;
+ info->uio.irq = jr->irq;
+ info->uio.irq_flags = IRQF_SHARED;
+ info->uio.handler = sec_jr_irq_handler;
+ info->uio.irqcontrol = sec_jr_irqcontrol;
+ info->uio.open = sec_uio_open;
+ info->uio.release = sec_uio_release;
+ info->uio.priv = jr;
+
+ ret = uio_register_device(jr->dev, &info->uio);
+ if (ret) {
+ pr_err("sec_jr_uio: UIO registration failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int fsl_sec_jr_probe(struct device_node *jr_node,
+ struct sec_dev *scdev)
+{
+ struct sec_job_ring *jr;
+ struct resource regs;
+ int ret;
+
+ if (!jr_node || !scdev)
+ return -EINVAL;
+
+ jr = kzalloc(sizeof(*jr), GFP_KERNEL);
+ if (!jr) {
+ dev_err(scdev->dev, "Can't alloc memory for job ring\n");
+ return -ENOMEM;
+ }
+
+ jr->dev = scdev->dev;
+
+ ret = of_address_to_resource(jr_node, 0, &regs);
+ if (unlikely(ret < 0)) {
+ dev_err(jr->dev, "Can't get property 'reg'\n");
+ ret = -EFAULT;
+ goto abort_jr;
+ }
+
+ jr->index = (regs.start >> JR_INDEX_OFFSET) & 0xf;
+ snprintf(jr->info.name, sizeof(jr->info.name)-1,
+ "sec_job_ring%d-%d", scdev->index, jr->index);
+
+ jr->res = devm_request_mem_region(scdev->dev, regs.start,
+ regs.end + 1 - regs.start,
+ jr->info.name);
+ if (unlikely(!jr->res)) {
+ dev_err(jr->dev, "devm_request_mem_region failed\n");
+ ret = -ENOMEM;
+ goto abort_jr;
+ }
+
+ dev_dbg(jr->dev,
+ "sec_job_ring%d-%d reg start 0x%016llx, size 0x%016llx.\n",
+ scdev->index, jr->index, jr->res->start,
+ jr->res->end + 1 - jr->res->start);
+
+ jr->irq = irq_of_parse_and_map(jr_node, 0);
+ dev_dbg(jr->dev, "errirq: %d\n", jr->irq);
+
+ ret = sec_jr_uio_init(jr);
+ if (ret)
+ goto abort_jr;
+
+ list_add(&jr->list_node, &scdev->jr_list);
+ dev_info(jr->dev, "sec_job_ring%d-%d initialized.\n",
+ scdev->index, jr->index);
+
+ return 0;
+abort_jr:
+ kfree(jr);
+ return ret;
+}
+
+static int fsl_sec_jr_remove(struct sec_job_ring *jr)
+{
+ if (!jr)
+ return 0;
+ uio_unregister_device(&jr->info.uio);
+ kfree(jr);
+
+ return 0;
+}
+
+static const struct of_device_id jr_ids[] = {
+ { .compatible = "fsl,sec-v4.0-job-ring", },
+ { .compatible = "fsl,sec-v4.4-job-ring", },
+ { .compatible = "fsl,sec-v5.0-job-ring", },
+ { .compatible = "fsl,sec-v6.0-job-ring", },
+ {},
+};
+
+static int fsl_sec_probe(struct platform_device *dev)
+{
+ struct resource regs;
+ struct sec_dev *sec_dev;
+ struct device_node *sec_node, *child;
+ struct sec_job_ring *jr, *tmp;
+ int ret, count = 0;
+ struct list_head *p;
+
+ sec_node = dev->dev.of_node;
+ if (!sec_node) {
+ dev_err(&dev->dev, "Device OF-Node is NULL");
+ return -EFAULT;
+ }
+
+ sec_dev = kzalloc(sizeof(struct sec_dev), GFP_KERNEL);
+ if (!sec_dev)
+ return -ENOMEM;
+
+ /* Creat name and index */
+ list_for_each(p, &sec_list) {
+ count++;
+ }
+ sec_dev->index = count;
+
+ snprintf(sec_dev->info.name, sizeof(sec_dev->info.name) - 1,
+ "%s%d", uio_device_name, sec_dev->index);
+
+ sec_dev->dev = &dev->dev;
+ platform_set_drvdata(dev, sec_dev);
+
+ dev_info(sec_dev->dev, "UIO device full name %s initialized\n",
+ sec_dev->info.name);
+
+ /* Create each jr under this sec node */
+ INIT_LIST_HEAD(&sec_dev->jr_list);
+ for_each_child_of_node(sec_node, child) {
+ if (of_match_node(jr_ids, child))
+ fsl_sec_jr_probe(child, sec_dev);
+ }
+
+ /* Get the resource from dtb node */
+ ret = of_address_to_resource(sec_node, 0, &regs);
+ if (unlikely(ret < 0)) {
+ ret = -EFAULT;
+ goto abort;
+ }
+
+ sec_dev->res = regs;
+
+ sec_dev->global_regs = of_iomap(sec_node, 0);
+
+ sec_dev->irq = irq_of_parse_and_map(sec_node, 0);
+ dev_dbg(sec_dev->dev, "errirq: %d\n", sec_dev->irq);
+
+ /* Register UIO */
+ ret = sec_uio_init(sec_dev);
+ if (ret)
+ goto abort_iounmap;
+
+ list_add_tail(&sec_dev->node, &sec_list);
+
+ return 0;
+
+abort_iounmap:
+ iounmap(sec_dev->global_regs);
+abort:
+ list_for_each_entry_safe(jr, tmp, &sec_dev->jr_list, list_node) {
+ list_del(&jr->list_node);
+ fsl_sec_jr_remove(jr);
+ }
+ kfree(sec_dev);
+ return ret;
+}
+
+static int fsl_sec_remove(struct platform_device *dev)
+{
+ struct sec_dev *sec_dev = platform_get_drvdata(dev);
+ struct sec_job_ring *jr, *tmp;
+
+ if (!sec_dev)
+ return 0;
+
+ list_for_each_entry_safe(jr, tmp, &sec_dev->jr_list, list_node) {
+ list_del(&jr->list_node);
+ fsl_sec_jr_remove(jr);
+ }
+
+ list_del(&sec_dev->node);
+ uio_unregister_device(&sec_dev->info.uio);
+ platform_set_drvdata(dev, NULL);
+ iounmap(sec_dev->global_regs);
+ kfree(sec_dev);
+
+ return 0;
+}
+
+static const struct of_device_id sec_ids[] = {
+ { .compatible = "fsl,sec-v4.0", },
+ { .compatible = "fsl,sec-v4.4", },
+ { .compatible = "fsl,sec-v5.0", },
+ { .compatible = "fsl,sec-v6.0", },
+ {},
+};
+
+static struct platform_driver fsl_sec_driver = {
+ .driver = {
+ .name = "fsl-sec-uio",
+ .owner = THIS_MODULE,
+ .of_match_table = sec_ids,
+ },
+ .probe = fsl_sec_probe,
+ .remove = fsl_sec_remove,
+};
+
+static __init int fsl_sec_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&fsl_sec_driver);
+ if (unlikely(ret < 0))
+ pr_warn(": %s:%hu:%s(): platform_driver_register() = %d\n",
+ __FILE__, __LINE__, __func__, ret);
+
+ return ret;
+}
+
+static void __exit fsl_sec_exit(void)
+{
+ platform_driver_unregister(&fsl_sec_driver);
+}
+
+module_init(fsl_sec_init);
+module_exit(fsl_sec_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Liu Po <po.liu@freescale.com>");
+MODULE_DESCRIPTION("FSL SEC UIO Driver");
diff --git a/drivers/uio/fsl_sram_uio.c b/drivers/uio/fsl_sram_uio.c
new file mode 100644
index 0000000..096b68b
--- /dev/null
+++ b/drivers/uio/fsl_sram_uio.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright 2012-2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Po Liu <po.liu@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/io.h>
+#include <linux/uio_driver.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+
+static const char l2sram_uio_version[] = "fsl SRAM UIO driver v1.0";
+
+#define NAME_LENGTH 30
+
+#define L2CR_L2FI 0x40000000 /* L2 flash invalidate */
+#define L2CR_L2IO 0x00200000 /* L2 instruction only */
+#define L2CR_SRAM_ZERO 0x00000000 /* L2SRAM zero size */
+#define L2CR_SRAM_FULL 0x00010000 /* L2SRAM full size */
+#define L2CR_SRAM_HALF 0x00020000 /* L2SRAM half size */
+#define L2CR_SRAM_TWO_HALFS 0x00030000 /* L2SRAM two half sizes */
+#define L2CR_SRAM_QUART 0x00040000 /* L2SRAM one quarter size */
+#define L2CR_SRAM_TWO_QUARTS 0x00050000 /* L2SRAM two quarter size */
+#define L2CR_SRAM_EIGHTH 0x00060000 /* L2SRAM one eighth size */
+#define L2CR_SRAM_TWO_EIGHTH 0x00070000 /* L2SRAM two eighth size */
+
+#define L2SRAM_OPTIMAL_SZ_SHIFT 0x00000003 /* Optimum size for L2SRAM */
+
+#define L2SRAM_BAR_MSK_LO18 0xFFFFC000 /* Lower 18 bits */
+#define L2SRAM_BARE_MSK_HI4 0x0000000F /* Upper 4 bits */
+
+/* 0x000 - L2 control */
+#define L2_CACHE_L2CTL 0x0
+/* 0x100 - SRAM base address 0 */
+#define L2_CACHE_L2SRBAR0 0x100
+/* 0x104 - SRAM base address 0 */
+#define L2_CACHE_L2SRBAEA0 0x104
+
+enum cache_sram_lock_ways {
+ LOCK_WAYS_ZERO,
+ LOCK_WAYS_EIGHTH,
+ LOCK_WAYS_TWO_EIGHTH,
+ LOCK_WAYS_HALF = 4,
+ LOCK_WAYS_FULL = 8,
+};
+
+struct sram_parameters {
+ unsigned int sram_size;
+ uint64_t sram_offset;
+};
+
+static const char uio_device_name[] = "fsl-sram";
+
+static char *cache_sram;
+
+struct l2sram_uio_info {
+ atomic_t ref;
+ struct uio_info uio;
+ char name[NAME_LENGTH];
+};
+
+struct l2sram_dev {
+ u32 revision;
+ int irq;
+ void __iomem *global_regs;
+ struct device *dev;
+ struct resource res;
+ struct sram_parameters sram_para;
+ struct l2sram_uio_info info;
+};
+
+static int l2sram_uio_open(struct uio_info *info, struct inode *inode)
+{
+ struct l2sram_uio_info *i = container_of(info,
+ struct l2sram_uio_info, uio);
+
+ if (!atomic_dec_and_test(&i->ref)) {
+ pr_err("%s: failing non-exclusive open()\n", i->name);
+ atomic_inc(&i->ref);
+ return -EBUSY;
+ }
+ return 0;
+}
+
+static int l2sram_uio_release(struct uio_info *info, struct inode *inode)
+{
+ struct l2sram_uio_info *i = container_of(info,
+ struct l2sram_uio_info, uio);
+ atomic_inc(&i->ref);
+ return 0;
+}
+
+static int __init l2sram_uio_init(struct l2sram_dev *uio_dev)
+{
+ int ret;
+ struct l2sram_uio_info *info;
+
+ info = &uio_dev->info;
+ atomic_set(&info->ref, 1);
+ info->uio.version = l2sram_uio_version;
+ info->uio.mem[0].name = uio_dev->info.name;
+ info->uio.name = uio_dev->info.name;
+ info->uio.mem[0].addr = uio_dev->res.start;
+ info->uio.mem[0].size = uio_dev->res.end - uio_dev->res.start + 1;
+ /* Internal_addr may use other way for user space */
+ info->uio.mem[0].internal_addr = uio_dev->global_regs;
+ info->uio.mem[0].memtype = UIO_MEM_PHYS;
+ info->uio.open = l2sram_uio_open;
+ info->uio.release = l2sram_uio_release;
+ info->uio.priv = &uio_dev->info;
+
+ ret = uio_register_device(uio_dev->dev, &info->uio);
+ if (ret) {
+ pr_err("l2sram_uio: UIO registration failed\n");
+ return ret;
+ }
+ return 0;
+}
+
+static int get_cache_sram_params(struct sram_parameters *sram_params)
+{
+ unsigned long long addr;
+ unsigned int size;
+ char *str;
+
+ if (!cache_sram)
+ return -EINVAL;
+
+ str = strchr(cache_sram, ',');
+ if (!str)
+ return -EINVAL;
+
+ *str = 0;
+ str++;
+
+ if (kstrtouint(str, 0, &size) < 0 ||
+ kstrtoull(cache_sram, 0, &addr) < 0)
+ return -EINVAL;
+
+ sram_params->sram_offset = addr;
+ sram_params->sram_size = size;
+ return 0;
+}
+
+static int __init get_cache_sram_cmdline(char *str)
+{
+ if (!str)
+ return 0;
+
+ cache_sram = str;
+ return 1;
+}
+
+__setup("cache-sram=", get_cache_sram_cmdline);
+
+static int fsl_l2sram_probe(struct platform_device *dev)
+{
+ struct resource regs;
+ struct l2sram_dev *l2sram_dev;
+ struct device_node *l2sram_node;
+ const unsigned int *prop;
+ unsigned int l2cache_size;
+ unsigned int rem;
+ unsigned char ways;
+ int ret;
+
+ l2sram_node = dev->dev.of_node;
+ if (!l2sram_node) {
+ dev_err(&dev->dev, "Device OF-Node is NULL");
+ return -EFAULT;
+ }
+
+ prop = of_get_property(dev->dev.of_node, "cache-size", NULL);
+ if (!prop) {
+ dev_err(&dev->dev, "Missing L2 cache-size\n");
+ return -EINVAL;
+ }
+
+ l2cache_size = *prop;
+
+ dev_info(&dev->dev, "Of-device full name %s initialized\n",
+ l2sram_node->full_name);
+
+ l2sram_dev = kzalloc(sizeof(struct l2sram_dev), GFP_KERNEL);
+ if (!l2sram_dev) {
+ dev_err(&dev->dev, "Can't allocate memory for 'l2sram_dev'\n");
+ return -ENOMEM;
+ }
+
+ l2sram_dev->dev = &dev->dev;
+ platform_set_drvdata(dev, l2sram_dev);
+
+ /* L2CACHE as the global_regs */
+ ret = of_address_to_resource(l2sram_node, 0, &regs);
+ if (unlikely(ret < 0)) {
+ dev_err(&dev->dev,
+ "Can't get property 'reg'\n");
+ ret = -EFAULT;
+ goto abort;
+ }
+
+ l2sram_dev->global_regs = devm_ioremap(&dev->dev, regs.start,
+ regs.end - regs.start + 1);
+ if (unlikely(!l2sram_dev->global_regs)) {
+ dev_err(&dev->dev, "devm_ioremap failed\n");
+ ret = -EIO;
+ goto abort1;
+ }
+
+ if (get_cache_sram_params(&l2sram_dev->sram_para)) {
+ dev_err(&dev->dev,
+ "Entire L2 as cache, provide valid sram address and size\n");
+ return -EINVAL;
+ }
+
+ rem = l2cache_size % l2sram_dev->sram_para.sram_size;
+ ways = LOCK_WAYS_FULL * l2sram_dev->sram_para.sram_size / l2cache_size;
+ if (rem || (ways & (ways - 1))) {
+ dev_err(&dev->dev, "Illegal cache-sram-size in command line\n");
+ ret = -EINVAL;
+ goto abort1;
+ }
+
+ /* Write bits[0-17] to L2_CACHE_L2SRBAR0 */
+ out_be32(l2sram_dev->global_regs + L2_CACHE_L2SRBAR0,
+ l2sram_dev->sram_para.sram_offset & L2SRAM_BAR_MSK_LO18);
+
+ /* Write bits[18-21] to L2_CACHE_L2SRBAEA0 */
+#ifdef CONFIG_PHYS_64BIT
+ out_be32(l2sram_dev->global_regs + L2_CACHE_L2SRBAEA0 , (l2sram_dev->
+ sram_para.sram_offset >> 32) & L2SRAM_BARE_MSK_HI4);
+#endif
+ clrsetbits_be32(l2sram_dev->global_regs
+ + L2_CACHE_L2CTL, L2CR_L2E, L2CR_L2FI);
+
+ switch (ways) {
+ case LOCK_WAYS_EIGHTH:
+ setbits32(l2sram_dev->global_regs + L2_CACHE_L2CTL,
+ L2CR_L2E | L2CR_L2FI | L2CR_SRAM_EIGHTH);
+ break;
+
+ case LOCK_WAYS_TWO_EIGHTH:
+ setbits32(l2sram_dev->global_regs + L2_CACHE_L2CTL,
+ L2CR_L2E | L2CR_L2FI | L2CR_SRAM_QUART);
+ break;
+
+ case LOCK_WAYS_HALF:
+ setbits32(l2sram_dev->global_regs + L2_CACHE_L2CTL,
+ L2CR_L2E | L2CR_L2FI | L2CR_SRAM_HALF);
+ break;
+
+ case LOCK_WAYS_FULL:
+ default:
+ setbits32(l2sram_dev->global_regs + L2_CACHE_L2CTL,
+ L2CR_L2E | L2CR_L2FI | L2CR_SRAM_FULL);
+ break;
+ }
+
+ snprintf(l2sram_dev->info.name, sizeof(l2sram_dev->info.name) - 1,
+ uio_device_name);
+
+ regs.start = l2sram_dev->sram_para.sram_offset;
+ regs.end = l2sram_dev->sram_para.sram_offset
+ + l2sram_dev->sram_para.sram_size - 1;
+ l2sram_dev->res = regs;
+
+ /* Now we can register UIO */
+ ret = l2sram_uio_init(l2sram_dev);
+ if (ret)
+ goto abort1;
+ return 0;
+
+abort1:
+ iounmap(l2sram_dev->global_regs);
+abort:
+ platform_set_drvdata(dev, NULL);
+ kfree(l2sram_dev);
+ return ret;
+}
+
+static int fsl_l2sram_remove(struct platform_device *dev)
+{
+ struct l2sram_dev *l2sram_dev = platform_get_drvdata(dev);
+
+ if (!l2sram_dev)
+ return 0;
+
+ uio_unregister_device(&l2sram_dev->info.uio);
+ platform_set_drvdata(dev, NULL);
+ kfree(l2sram_dev);
+ iounmap(l2sram_dev->global_regs);
+ return 0;
+}
+
+static const struct of_device_id fsl_of_l2sram_match[] = {
+ {
+ .compatible = "fsl,p1010-l2-cache-controller",
+ },
+ {
+ .compatible = "fsl,c293-l2-cache-controller",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, fsl_of_l2sram_match);
+
+static struct platform_driver fsl_l2sram_driver = {
+ .driver = {
+ .name = "fsl-sram-uio",
+ .owner = THIS_MODULE,
+ .of_match_table = fsl_of_l2sram_match,
+ },
+ .probe = fsl_l2sram_probe,
+ .remove = fsl_l2sram_remove,
+};
+
+module_platform_driver(fsl_l2sram_driver);
diff --git a/drivers/uio/fsl_srio_uio.c b/drivers/uio/fsl_srio_uio.c
new file mode 100644
index 0000000..840872b
--- /dev/null
+++ b/drivers/uio/fsl_srio_uio.c
@@ -0,0 +1,426 @@
+/*
+ * Copyright 2011-2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Kai Jiang <Kai.Jiang@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/uio_driver.h>
+#include <linux/list.h>
+
+#define EPWISR 0x10010 /* Error/Port-Write Interrupt Status */
+#define IECSR 0x10130 /* Port Implementation Err Cmd & Status */
+#define ESCSR 0x00158 /* Port Error and Status Cmd & Status */
+#define EDCSR 0x00640 /* Port Error Detect Cmd & Status */
+#define LTLEDCSR 0x00608 /* Logical/Transport Layer Err Detect Cmd & Status */
+#define LTLEECSR 0x0060c /* Logical/Transport Layer Err Enable Cmd & Status */
+#define SRIO_ESCSR_CLEAR 0x07120204
+#define SRIO_IECSR_CLEAR 0x80000000
+
+struct srio_uio_info {
+ atomic_t ref;
+ struct uio_info uio;
+ char name[20];
+};
+
+struct srio_port_info {
+ struct device *dev;
+ struct srio_uio_info *info;
+ struct resource *res;
+ struct list_head list;
+ u32 port_id;
+};
+
+struct srio_regs_info {
+ struct device *dev;
+ struct srio_uio_info *info;
+ struct resource *res;
+ void __iomem *regs_win;
+};
+
+struct srio_dev {
+ struct device *dev;
+ struct srio_regs_info regs;
+ struct list_head port_list;
+ int irq;
+ u32 port_num;
+};
+
+enum srio_uio_init_type {
+ SRIO_REGS,
+ SRIO_PORT
+};
+
+static const char srio_uio_version[] = "SRIO UIO driver v1.0";
+
+static int srio_uio_open(struct uio_info *info, struct inode *inode)
+{
+ struct srio_uio_info *i = container_of(info, struct srio_uio_info, uio);
+
+ if (atomic_dec_return(&i->ref) < 0) {
+ pr_err("%s: failing open()\n", i->name);
+ atomic_inc(&i->ref);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int srio_uio_release(struct uio_info *info, struct inode *inode)
+{
+ struct srio_uio_info *i = container_of(info, struct srio_uio_info, uio);
+
+ atomic_inc(&i->ref);
+
+ return 0;
+}
+
+static irqreturn_t srio_uio_irq_handler(int irq, struct uio_info *dev_info)
+{
+ struct srio_dev *sriodev = dev_info->priv;
+ int i;
+ unsigned int port_bits, ltledcsr;
+
+ ltledcsr = in_be32(sriodev->regs.regs_win + LTLEDCSR);
+ port_bits = in_be32(sriodev->regs.regs_win + EPWISR);
+
+ if (!port_bits && !ltledcsr)
+ return IRQ_NONE;
+
+ if (ltledcsr)
+ /* Disable logical/transport layer error interrupt */
+ out_be32(sriodev->regs.regs_win + LTLEECSR, 0);
+
+ for (i = 0; i < sriodev->port_num; i++) {
+ if (port_bits & (1 << (31 - i))) {
+ /* Clear retry error threshold exceeded */
+ out_be32(sriodev->regs.regs_win + IECSR + 0x80 * i,
+ SRIO_IECSR_CLEAR);
+ /* Clear ESCSR */
+ out_be32(sriodev->regs.regs_win + ESCSR + 0x20 * i,
+ SRIO_ESCSR_CLEAR);
+ /* Clear EDCSR */
+ out_be32(sriodev->regs.regs_win + EDCSR + 0x40 * i,
+ 0);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int __init srio_uio_setup(struct srio_dev *sriodev, u8 type, u32 port_id)
+{
+ int err;
+ struct srio_uio_info *info;
+ struct srio_port_info *srio_port, *port_tmp;
+
+ info = devm_kzalloc(sriodev->dev, sizeof(struct srio_uio_info),
+ GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ if (type == SRIO_REGS) {
+ atomic_set(&info->ref, sriodev->port_num);
+ sriodev->regs.info = info;
+ snprintf(info->name, sizeof(info->name)-1, "srio-uio-regs");
+ info->uio.name = info->name;
+ info->uio.version = srio_uio_version;
+ info->uio.mem[0].name = "srio regs";
+ info->uio.mem[0].addr = sriodev->regs.res->start;
+ info->uio.mem[0].size = sriodev->regs.res->end -
+ sriodev->regs.res->start + 1;
+ info->uio.mem[0].memtype = UIO_MEM_PHYS;
+ info->uio.irq = sriodev->irq;
+
+ } else if (type == SRIO_PORT) {
+ err = -ENODEV;
+ atomic_set(&info->ref, 1);
+ list_for_each_entry_safe(srio_port, port_tmp,
+ &sriodev->port_list, list) {
+
+ if (srio_port->port_id == port_id) {
+ srio_port->info = info;
+ snprintf(info->name, sizeof(info->name)-1,
+ "srio-uio-port%d", port_id);
+ info->uio.name = info->name;
+ info->uio.version = srio_uio_version;
+ info->uio.mem[0].name = "srio window";
+ info->uio.mem[0].addr = srio_port->res->start;
+ info->uio.mem[0].size = srio_port->res->end -
+ srio_port->res->start + 1;
+ info->uio.mem[0].memtype = UIO_MEM_PHYS;
+ err = 0;
+ break;
+ }
+
+ }
+
+ if (err < 0)
+ return err;
+ } else
+ return -ENODEV;
+
+ info->uio.irq_flags = IRQF_SHARED;
+ info->uio.handler = srio_uio_irq_handler;
+ info->uio.open = srio_uio_open;
+ info->uio.release = srio_uio_release;
+ info->uio.priv = sriodev;
+
+ err = uio_register_device(sriodev->dev, &info->uio);
+ if (err) {
+ dev_err(sriodev->dev, "srio_uio: UIO registration failed\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static int srio_uio_init(struct srio_dev *sriodev)
+{
+ struct srio_port_info *srio_port, *port_tmp;
+ int err;
+
+ srio_uio_setup(sriodev, SRIO_REGS, 0);
+ list_for_each_entry_safe(srio_port, port_tmp,
+ &sriodev->port_list, list) {
+ err = srio_uio_setup(sriodev, SRIO_PORT, srio_port->port_id);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static int srio_uio_cleanup(struct srio_dev *sriodev)
+{
+ struct srio_port_info *srio_port, *port_tmp;
+
+ list_for_each_entry_safe(srio_port, port_tmp,
+ &sriodev->port_list, list) {
+ uio_unregister_device(&srio_port->info->uio);
+ list_del(&srio_port->list);
+ }
+
+ uio_unregister_device(&sriodev->regs.info->uio);
+
+ return 0;
+}
+
+static int fsl_srio_port_probe(struct srio_dev *srio_dev,
+ struct device_node *node)
+{
+ struct device_node *srio_node;
+ struct srio_port_info *srio_port;
+ const u32 *dt_range, *cell, *cell_index;
+ u64 law_start, law_size;
+ int paw, aw, sw;
+
+ srio_node = node;
+
+ cell_index = of_get_property(srio_node, "cell-index", NULL);
+ if (!cell_index) {
+ dev_err(srio_dev->dev, "Can't get %s property 'cell-index'\n",
+ srio_node->full_name);
+ return -ENODEV;
+ }
+
+ dt_range = of_get_property(srio_node, "ranges", NULL);
+ if (!dt_range) {
+ dev_err(srio_dev->dev, "Can't get %s property 'ranges'\n",
+ srio_node->full_name);
+ return -ENODEV;
+ }
+
+ /* Get node address wide */
+ cell = of_get_property(srio_node, "#address-cells", NULL);
+ if (!cell) {
+ dev_err(srio_dev->dev,
+ "Can't get %s property '#address-cells'\n",
+ srio_node->full_name);
+ return -ENODEV;
+ }
+ aw = *cell;
+
+ /* Get node size wide */
+ cell = of_get_property(srio_node, "#size-cells", NULL);
+ if (!cell) {
+ dev_err(srio_dev->dev, "Can't get %s property '#size-cells'\n",
+ srio_node->full_name);
+ return -ENODEV;
+ }
+ sw = *cell;
+
+ /* Get parent address wide wide */
+ paw = of_n_addr_cells(srio_node);
+ law_start = of_read_number(dt_range + aw, paw);
+ law_size = of_read_number(dt_range + aw + paw, sw);
+
+ srio_port = devm_kzalloc(srio_dev->dev, sizeof(struct srio_port_info),
+ GFP_KERNEL);
+ srio_port->res = devm_request_mem_region(srio_dev->dev, law_start,
+ law_size, "srio win");
+
+ if (srio_port->res == NULL) {
+ dev_err(srio_dev->dev, "devm_request_mem_region failed\n");
+ return -ENOMEM;
+ }
+
+ dev_dbg(srio_dev->dev, "window start 0x%016llx, size 0x%016llx.\n",
+ srio_port->res->start, srio_port->res->end + 1 -
+ srio_port->res->start);
+
+ srio_port->port_id = *cell_index;
+ srio_port->dev = srio_dev->dev;
+ srio_dev->port_num++;
+ list_add_tail(&srio_port->list, &srio_dev->port_list);
+
+ return 0;
+}
+
+static void fsl_srio_port_remove(struct srio_dev *srio_dev)
+{
+ struct srio_port_info *srio_port, *port_tmp;
+
+ list_for_each_entry_safe(srio_port, port_tmp,
+ &srio_dev->port_list, list)
+ list_del(&srio_port->list);
+}
+
+static int fsl_srio_uio_probe(struct platform_device *dev)
+{
+ struct resource regs;
+ struct srio_dev *srio_dev;
+ struct device_node *srio_node;
+ struct device_node *child;
+ int err;
+
+ srio_node = dev->dev.of_node;
+ dev_dbg(&dev->dev, "Of-device full name %s\n", srio_node->full_name);
+
+ srio_dev = devm_kzalloc(&dev->dev, sizeof(struct srio_dev), GFP_KERNEL);
+ if (!srio_dev) {
+ dev_err(&dev->dev, "Can't alloc memory for 'srio_dev'\n");
+ return -ENOMEM;
+ }
+ srio_dev->dev = &dev->dev;
+ dev_set_drvdata(&dev->dev, srio_dev);
+
+ err = of_address_to_resource(srio_node, 0, &regs);
+ if (err < 0) {
+ dev_err(&dev->dev, "Can't get property 'reg'\n");
+ return -EFAULT;
+ }
+
+ srio_dev->regs.res = devm_request_mem_region(&dev->dev, regs.start,
+ regs.end + 1 - regs.start, "srio regs");
+ if (srio_dev->regs.res == NULL) {
+ dev_err(&dev->dev, "devm_request_mem_region failed\n");
+ return -ENOMEM;
+ }
+
+ dev_dbg(&dev->dev, "reg start 0x%016llx, size 0x%016llx.\n",
+ srio_dev->regs.res->start,
+ srio_dev->regs.res->end + 1 - srio_dev->regs.res->start);
+
+ srio_dev->regs.regs_win = devm_ioremap(&dev->dev,
+ srio_dev->regs.res->start,
+ srio_dev->regs.res->end -
+ srio_dev->regs.res->start + 1);
+ if (srio_dev->regs.regs_win == NULL) {
+ dev_err(&dev->dev, "devm_ioremap failed\n");
+ return -EIO;
+ }
+
+ srio_dev->irq = irq_of_parse_and_map(srio_node, 0);
+ dev_dbg(srio_dev->dev, "err irq: %d\n", srio_dev->irq);
+
+ INIT_LIST_HEAD(&srio_dev->port_list);
+
+ for_each_child_of_node(dev->dev.of_node, child) {
+ err = fsl_srio_port_probe(srio_dev, child);
+ if (err < 0) {
+ fsl_srio_port_remove(srio_dev);
+ return err;
+ }
+ }
+
+ err = srio_uio_init(srio_dev);
+ if (err < 0) {
+ dev_err(srio_dev->dev, "srio_uio_init failed\n");
+ srio_uio_cleanup(srio_dev);
+ return err;
+ }
+
+ dev_info(srio_dev->dev, "Rapidio UIO driver initialized\n");
+
+ return 0;
+}
+
+static int fsl_srio_uio_remove(struct platform_device *dev)
+{
+ struct srio_dev *srio_dev = platform_get_drvdata(dev);
+
+ srio_uio_cleanup(srio_dev);
+
+ return 0;
+}
+
+static const struct of_device_id fsl_srio_uio_match[] = {
+ {
+ .compatible = "fsl,srio",
+ },
+ {}
+};
+
+static struct platform_driver fsl_of_srio_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "fsl-of-srio",
+ .of_match_table = fsl_srio_uio_match,
+ },
+ .probe = fsl_srio_uio_probe,
+ .remove = fsl_srio_uio_remove,
+};
+
+static __init int fsl_srio_uio_init(void)
+{
+ int err;
+
+ err = platform_driver_register(&fsl_of_srio_driver);
+ if (err < 0)
+ pr_warn(
+ ": %s:%hu:%s(): platform_driver_register() = %d\n",
+ __FILE__, __LINE__, __func__, err);
+
+ return err;
+}
+
+static void __exit fsl_srio_uio_exit(void)
+{
+ platform_driver_unregister(&fsl_of_srio_driver);
+
+ pr_warn("fsl srio uio driver removed\n");
+}
+
+module_init(fsl_srio_uio_init);
+module_exit(fsl_srio_uio_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index 0e808cf..47fa38e 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -651,7 +651,11 @@ static int uio_mmap_physical(struct vm_area_struct *vma)
return -EINVAL;
vma->vm_ops = &uio_physical_vm_ops;
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ if (idev->info->set_pgprot)
+ vma->vm_page_prot = idev->info->set_pgprot(idev->info, mi,
+ vma->vm_page_prot);
+ else
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
/*
* We cannot use the vm_iomap_memory() helper here,
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 3670086..19f45e1 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -4044,11 +4044,13 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
else
speed = usb_speed_string(udev->speed);
+#if !defined(CONFIG_FSL_USB2_OTG) && !defined(CONFIG_FSL_USB2_OTG_MODULE)
if (udev->speed != USB_SPEED_SUPER)
dev_info(&udev->dev,
"%s %s USB device number %d using %s\n",
(udev->config) ? "reset" : "new", speed,
devnum, udev->bus->controller->driver->name);
+#endif
/* Set up TT records, if needed */
if (hdev->tt) {
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 36ac7cf..fa27a4c 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -335,7 +335,7 @@ static int dr_controller_setup(struct fsl_udc *udc)
}
#endif
-#if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE)
+#if !defined(CONFIG_NOT_COHERENT_CACHE)
/* Turn on cache snooping hardware, since some PowerPC platforms
* wholly rely on hardware to deal with cache coherent. */
@@ -1219,6 +1219,10 @@ static int fsl_pullup(struct usb_gadget *gadget, int is_on)
struct fsl_udc *udc;
udc = container_of(gadget, struct fsl_udc, gadget);
+
+ if (!udc->vbus_active)
+ return -EOPNOTSUPP;
+
udc->softconnect = (is_on != 0);
if (can_pullup(udc))
fsl_writel((fsl_readl(&dr_regs->usbcmd) | USB_CMD_RUN_STOP),
@@ -2456,6 +2460,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
/* Setup gadget.dev and register with kernel */
dev_set_name(&udc_controller->gadget.dev, "gadget");
udc_controller->gadget.dev.of_node = pdev->dev.of_node;
+ set_dma_ops(&udc_controller->gadget.dev, pdev->dev.archdata.dma_ops);
if (!IS_ERR_OR_NULL(udc_controller->transceiver))
udc_controller->gadget.is_otg = 1;
@@ -2654,6 +2659,8 @@ static const struct platform_device_id fsl_udc_devtype[] = {
}, {
.name = "imx-udc-mx51",
}, {
+ .name = "fsl-usb2-udc",
+ }, {
/* sentinel */
}
};
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index f2407b2..3ef6e26 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -30,9 +30,69 @@
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/fsl_devices.h>
+#include <sysdev/fsl_soc.h>
#include "ehci-fsl.h"
+struct ehci_fsl {
+ struct ehci_hcd ehci;
+
+#ifdef CONFIG_PM
+ /* Saved USB PHY settings, need to restore after deep sleep. */
+ u32 usb_ctrl;
+#endif
+
+ /* store current hcd state for otg;
+ * have_hcd is true when host drv al already part of otg framework,
+ * otherwise false;
+ * hcd_add is true when otg framework wants to add host
+ * drv as part of otg;flase when it wants to remove it
+ */
+ unsigned have_hcd:1;
+ unsigned hcd_add:1;
+};
+
+static bool usb_phy_clk_valid(struct usb_hcd *hcd)
+{
+ void __iomem *non_ehci = hcd->regs;
+ bool ret = true;
+
+ if (!(in_be32(non_ehci + FSL_SOC_USB_CTRL) & PHY_CLK_VALID))
+ ret = false;
+
+ return ret;
+}
+
+static struct ehci_fsl *hcd_to_ehci_fsl(struct usb_hcd *hcd)
+{
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+
+ return container_of(ehci, struct ehci_fsl, ehci);
+}
+
+#if defined(CONFIG_FSL_USB2_OTG) || defined(CONFIG_FSL_USB2_OTG_MODULE)
+static void do_change_hcd(struct work_struct *work)
+{
+ struct ehci_hcd *ehci = container_of(work, struct ehci_hcd,
+ change_hcd_work);
+ struct usb_hcd *hcd = ehci_to_hcd(ehci);
+ struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
+ void __iomem *non_ehci = hcd->regs;
+ int retval;
+
+ if (ehci_fsl->hcd_add && !ehci_fsl->have_hcd) {
+ writel(USBMODE_CM_HOST, non_ehci + FSL_SOC_USB_USBMODE);
+ /* host, gadget and otg share same int line */
+ retval = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
+ if (retval == 0)
+ ehci_fsl->have_hcd = 1;
+ } else if (!ehci_fsl->hcd_add && ehci_fsl->have_hcd) {
+ usb_remove_hcd(hcd);
+ ehci_fsl->have_hcd = 0;
+ }
+}
+#endif
+
/* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */
@@ -133,17 +193,30 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
if (pdata->have_sysif_regs && pdata->controller_ver < FSL_USB_VER_1_6)
setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4);
+ /*
+ * Enable UTMI phy and program PTS field in UTMI mode before asserting
+ * controller reset for USB Controller version 2.5
+ */
+ if (pdata->has_fsl_erratum_a007792) {
+ writel_be(CTRL_UTMI_PHY_EN, hcd->regs + FSL_SOC_USB_CTRL);
+ writel(PORT_PTS_UTMI, hcd->regs + FSL_SOC_USB_PORTSC1);
+ }
+
/* Don't need to set host mode here. It will be done by tdi_reset() */
- retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+ retval = usb_add_hcd(hcd, irq, IRQF_SHARED | IRQF_NO_SUSPEND);
if (retval != 0)
goto err4;
-#ifdef CONFIG_USB_OTG
+#if defined(CONFIG_FSL_USB2_OTG) || defined(CONFIG_FSL_USB2_OTG_MODULE)
if (pdata->operating_mode == FSL_USB2_DR_OTG) {
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+ struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
hcd->phy = usb_get_phy(USB_PHY_TYPE_USB2);
+
+ INIT_WORK(&ehci->change_hcd_work, do_change_hcd);
+
dev_dbg(&pdev->dev, "hcd=0x%p ehci=0x%p, phy=0x%p\n",
hcd, ehci, hcd->phy);
@@ -159,6 +232,11 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
retval = -ENODEV;
goto err4;
}
+
+ ehci_fsl->have_hcd = 1;
+ } else {
+ dev_err(&pdev->dev, "wrong operating mode\n");
+ return -ENODEV;
}
#endif
return retval;
@@ -245,6 +323,20 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
portsc |= PORT_PTS_PTW;
/* fall through */
case FSL_USB2_PHY_UTMI:
+ if (pdata->has_fsl_erratum_a006918) {
+ pr_warn("fsl-ehci: USB PHY clock invalid\n");
+ return -EINVAL;
+ }
+
+ /* PHY_CLK_VALID bit is de-featured from all controller
+ * versions below 2.4 and is to be checked only for
+ * internal UTMI phy */
+ if (pdata->controller_ver > FSL_USB_VER_2_4 &&
+ pdata->have_sysif_regs && !usb_phy_clk_valid(hcd)) {
+ pr_err("fsl-ehci: USB PHY clock invalid\n");
+ return -EINVAL;
+ }
+
if (pdata->have_sysif_regs && pdata->controller_ver) {
/* controller version 1.6 or above */
setbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN);
@@ -261,17 +353,6 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
break;
}
- if (pdata->have_sysif_regs && pdata->controller_ver &&
- (phy_mode == FSL_USB2_PHY_ULPI)) {
- /* check PHY_CLK_VALID to get phy clk valid */
- if (!(spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) &
- PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0) ||
- in_be32(non_ehci + FSL_SOC_USB_PRICTRL))) {
- printk(KERN_WARNING "fsl-ehci: USB PHY clock invalid\n");
- return -EINVAL;
- }
- }
-
ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
if (phy_mode != FSL_USB2_PHY_ULPI && pdata->have_sysif_regs)
@@ -301,6 +382,13 @@ static int ehci_fsl_usb_setup(struct ehci_hcd *ehci)
out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB);
}
+ /* Deal with USB erratum A-005275 */
+ if (pdata->has_fsl_erratum_a005275 == 1)
+ ehci->has_fsl_hs_errata = 1;
+
+ if (pdata->has_fsl_erratum_a005697 == 1)
+ ehci->has_fsl_susp_errata = 1;
+
if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
(pdata->operating_mode == FSL_USB2_DR_OTG))
if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0))
@@ -394,15 +482,6 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
return retval;
}
-struct ehci_fsl {
- struct ehci_hcd ehci;
-
-#ifdef CONFIG_PM
- /* Saved USB PHY settings, need to restore after deep sleep. */
- u32 usb_ctrl;
-#endif
-};
-
#ifdef CONFIG_PM
#ifdef CONFIG_PPC_MPC512x
@@ -550,24 +629,33 @@ static inline int ehci_fsl_mpc512x_drv_resume(struct device *dev)
}
#endif /* CONFIG_PPC_MPC512x */
-static struct ehci_fsl *hcd_to_ehci_fsl(struct usb_hcd *hcd)
-{
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-
- return container_of(ehci, struct ehci_fsl, ehci);
-}
-
static int ehci_fsl_drv_suspend(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
void __iomem *non_ehci = hcd->regs;
+#if defined(CONFIG_FSL_USB2_OTG) || defined(CONFIG_FSL_USB2_OTG_MODULE)
+ struct usb_bus host = hcd->self;
+#endif
if (of_device_is_compatible(dev->parent->of_node,
"fsl,mpc5121-usb2-dr")) {
return ehci_fsl_mpc512x_drv_suspend(dev);
}
+#if defined(CONFIG_FSL_USB2_OTG) || defined(CONFIG_FSL_USB2_OTG_MODULE)
+ if (host.is_otg) {
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+
+ /* remove hcd */
+ ehci_fsl->hcd_add = 0;
+ schedule_work(&ehci->change_hcd_work);
+ host.is_otg = 0;
+ return 0;
+ }
+#endif
+ mpc85xx_pmc_set_wake(dev, true);
+
ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd),
device_may_wakeup(dev));
if (!fsl_deep_sleep())
@@ -583,12 +671,28 @@ static int ehci_fsl_drv_resume(struct device *dev)
struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
void __iomem *non_ehci = hcd->regs;
+#if defined(CONFIG_FSL_USB2_OTG) || defined(CONFIG_FSL_USB2_OTG_MODULE)
+ struct usb_bus host = hcd->self;
+#endif
if (of_device_is_compatible(dev->parent->of_node,
"fsl,mpc5121-usb2-dr")) {
return ehci_fsl_mpc512x_drv_resume(dev);
}
+#if defined(CONFIG_FSL_USB2_OTG) || defined(CONFIG_FSL_USB2_OTG_MODULE)
+ if (host.is_otg) {
+ /* add hcd */
+ ehci_fsl->hcd_add = 1;
+ schedule_work(&ehci->change_hcd_work);
+ usb_hcd_resume_root_hub(hcd);
+ host.is_otg = 0;
+ return 0;
+ }
+#endif
+
+ mpc85xx_pmc_set_wake(dev, false);
+
ehci_prepare_ports_for_controller_resume(ehci);
if (!fsl_deep_sleep())
return 0;
diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
index dbd292e..a032358 100644
--- a/drivers/usb/host/ehci-fsl.h
+++ b/drivers/usb/host/ehci-fsl.h
@@ -62,4 +62,7 @@
#define UTMI_PHY_EN (1<<9)
#define ULPI_PHY_CLK_SEL (1<<10)
#define PHY_CLK_VALID (1<<17)
+
+/* Retry count for checking UTMI PHY CLK validity */
+#define UTMI_PHY_CLK_VALID_CHK_RETRY 5
#endif /* _EHCI_FSL_H */
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 1bb85be..9e00422 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -286,6 +286,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
else if ((t1 & PORT_PE) && !(t1 & PORT_SUSPEND)) {
t2 |= PORT_SUSPEND;
set_bit(port, &ehci->bus_suspended);
+ if (ehci_has_fsl_susp_errata(ehci))
+ usleep_range(10000, 20000);
}
/* enable remote wakeup on all ports, if told to do so */
@@ -1227,6 +1229,13 @@ static int ehci_hub_control (
ehci->reset_done [wIndex] = jiffies
+ msecs_to_jiffies (50);
}
+
+ /* Force full-speed connect for FSL high-speed erratum;
+ * disable HS Chirp by setting PFSC bit
+ */
+ if (ehci_has_fsl_hs_errata(ehci))
+ temp |= (1 << PORTSC_FSL_PFSC);
+
ehci_writel(ehci, temp, status_reg);
break;
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index a7f776a..21a6b13 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -890,7 +890,11 @@ qh_make (
break;
case USB_SPEED_HIGH: /* no TT involved */
- info1 |= QH_HIGH_SPEED;
+ if (!ehci_has_fsl_hs_errata(ehci))
+ info1 |= QH_HIGH_SPEED;
+ else
+ info1 |= QH_FULL_SPEED;
+
if (type == PIPE_CONTROL) {
info1 |= (EHCI_TUNE_RL_HS << 28);
info1 |= 64 << 16; /* usb2 fixed maxpacket */
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 2a1f38d..e748230 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -155,6 +155,9 @@ struct ehci_hcd { /* one per controller */
unsigned periodic_count; /* periodic activity count */
unsigned uframe_periodic_max; /* max periodic time per uframe */
+#if defined(CONFIG_FSL_USB2_OTG) || defined(CONFIG_FSL_USB2_OTG_MODULE)
+ struct work_struct change_hcd_work;
+#endif
/* list of itds & sitds completed while now_frame was still active */
struct list_head cached_itd_list;
@@ -193,6 +196,8 @@ struct ehci_hcd { /* one per controller */
/* SILICON QUIRKS */
unsigned no_selective_suspend:1;
unsigned has_fsl_port_bug:1; /* FreeScale */
+ unsigned has_fsl_hs_errata:1; /* Freescale HS quirk */
+ unsigned has_fsl_susp_errata:1; /*Freescale SUSP quirk*/
unsigned big_endian_mmio:1;
unsigned big_endian_desc:1;
unsigned big_endian_capbase:1;
@@ -626,6 +631,22 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
#define ehci_port_speed(ehci, portsc) USB_PORT_STAT_HIGH_SPEED
#endif
+#define PORTSC_FSL_PFSC 24 /* Port Force Full-Speed Connect */
+
+#if defined(CONFIG_PPC_85xx)
+/* Some Freescale processors have an erratum (USB A-005275) in which
+ * incoming packets get corrupted in HS mode
+ * Some Freescale processors have an erratum (USB A-005697) in which
+ * we need to wait for 10ms for bus to fo into suspend mode after
+ * setting SUSP bit
+ */
+#define ehci_has_fsl_hs_errata(e) ((e)->has_fsl_hs_errata)
+#define ehci_has_fsl_susp_errata(e) ((e)->has_fsl_susp_errata)
+#else
+#define ehci_has_fsl_hs_errata(e) (0)
+#define ehci_has_fsl_susp_errata(e) (0)
+#endif
+
/*-------------------------------------------------------------------------*/
#ifdef CONFIG_PPC_83xx
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index abd5050..c2c58cf 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -17,6 +17,7 @@
#include <linux/of_platform.h>
#include <linux/clk.h>
#include <linux/module.h>
+#include <asm/mpc85xx.h>
struct fsl_usb2_dev_data {
char *dr_mode; /* controller mode */
@@ -119,6 +120,84 @@ error:
static const struct of_device_id fsl_usb2_mph_dr_of_match[];
+static bool has_erratum_a005275(struct device_node *node)
+{
+ unsigned int svr = mfspr(SPRN_SVR);
+ bool flag = false;
+ /* Deal with USB Erratum USB A-005275
+ * Packet corruption in HS mode, default to
+ * FS mode for the following
+ * P3041 and P2041 rev 1.0 and 1.1
+ * P5020 and P5010 rev 1.0 and 2.0
+ * P5040 and P1010 rev 1.0
+ */
+ if ((SVR_SOC_VER(svr) == SVR_P2041) ||
+ (SVR_SOC_VER(svr) == SVR_P3041))
+ flag = (SVR_REV(svr) == 0x10) || (SVR_REV(svr) == 0x11);
+ else if ((SVR_SOC_VER(svr) == SVR_P5010) ||
+ (SVR_SOC_VER(svr) == SVR_P5020))
+ flag = (SVR_REV(svr) == 0x10) || (SVR_REV(svr) == 0x20);
+ else if ((SVR_SOC_VER(svr) == SVR_P5040) ||
+ (SVR_SOC_VER(svr) == SVR_P1010))
+ flag = (SVR_REV(svr) == 0x10);
+
+ return flag;
+}
+
+static bool has_erratum_a005697(void)
+{
+ unsigned int svr = mfspr(SPRN_SVR);
+ bool flag = false;
+
+ switch (SVR_SOC_VER(svr)) {
+ case SVR_P1010:
+ case SVR_P1014:
+ case SVR_T1040:
+ if (SVR_REV(svr) == 0x10)
+ flag = true;
+ break;
+ case SVR_9132:
+ if ((SVR_REV(svr) == 0x10) || (SVR_REV(svr) == 0x11))
+ flag = true;
+ break;
+ case SVR_P5040:
+ case SVR_P5021:
+ if ((SVR_REV(svr) == 0x10) || (SVR_REV(svr) == 0x20) ||
+ (SVR_REV(svr) == 0x21))
+ flag = true;
+ break;
+ case SVR_T4240:
+ case SVR_T4160:
+ case SVR_P5020:
+ case SVR_P5010:
+ if ((SVR_REV(svr) == 0x10) || (SVR_REV(svr) == 0x20))
+ flag = true;
+ break;
+ case SVR_P2040:
+ case SVR_P2041:
+ case SVR_P3041:
+ if ((SVR_REV(svr) == 0x10) || (SVR_REV(svr) == 0x11) ||
+ (SVR_REV(svr) == 0x20))
+ flag = true;
+ break;
+ case SVR_P4080:
+ if ((SVR_REV(svr) == 0x10) || (SVR_REV(svr) == 0x20) ||
+ (SVR_REV(svr) == 0x30))
+ flag = true;
+ break;
+ }
+
+ return flag;
+}
+
+static bool has_erratum_a007792(int controller_ver)
+{
+ if (controller_ver == FSL_USB_VER_2_5)
+ return true;
+ else
+ return false;
+}
+
static int usb_get_ver_info(struct device_node *np)
{
int ver = -1;
@@ -126,6 +205,8 @@ static int usb_get_ver_info(struct device_node *np)
/*
* returns 1 for usb controller version 1.6
* returns 2 for usb controller version 2.2
+ * returns 3 for usb controller version 2.4
+ * returns 4 for usb controller version 2.5
* returns 0 otherwise
*/
if (of_device_is_compatible(np, "fsl-usb2-dr")) {
@@ -135,6 +216,8 @@ static int usb_get_ver_info(struct device_node *np)
ver = FSL_USB_VER_2_2;
else if (of_device_is_compatible(np, "fsl-usb2-dr-v2.4"))
ver = FSL_USB_VER_2_4;
+ else if (of_device_is_compatible(np, "fsl-usb2-dr-v2.5"))
+ ver = FSL_USB_VER_2_5;
else /* for previous controller versions */
ver = FSL_USB_VER_OLD;
@@ -150,6 +233,8 @@ static int usb_get_ver_info(struct device_node *np)
ver = FSL_USB_VER_1_6;
else if (of_device_is_compatible(np, "fsl-usb2-mph-v2.2"))
ver = FSL_USB_VER_2_2;
+ else if (of_device_is_compatible(np, "fsl-usb2-mph-v2.5"))
+ ver = FSL_USB_VER_2_5;
else /* for previous controller versions */
ver = FSL_USB_VER_OLD;
}
@@ -206,6 +291,31 @@ static int fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev)
pdata->phy_mode = determine_usb_phy(prop);
pdata->controller_ver = usb_get_ver_info(np);
+ /* Activate workaround for USB erratum-A005275 if
+ * fsl,no-erratum-a005275 property not defined for
+ * affected socs
+ */
+ if (!of_get_property(np, "fsl,no-erratum-a005275", NULL) &&
+ has_erratum_a005275(np))
+ pdata->has_fsl_erratum_a005275 = 1;
+ else
+ pdata->has_fsl_erratum_a005275 = 0;
+
+ if (has_erratum_a005697())
+ pdata->has_fsl_erratum_a005697 = 1;
+ else
+ pdata->has_fsl_erratum_a005697 = 0;
+
+ if (has_erratum_a007792(pdata->controller_ver))
+ pdata->has_fsl_erratum_a007792 = 1;
+ else
+ pdata->has_fsl_erratum_a007792 = 0;
+
+ if (of_get_property(np, "fsl,erratum_a006918", NULL))
+ pdata->has_fsl_erratum_a006918 = 1;
+ else
+ pdata->has_fsl_erratum_a006918 = 0;
+
if (pdata->have_sysif_regs) {
if (pdata->controller_ver < 0) {
dev_warn(&ofdev->dev, "Could not get controller version\n");
diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c
index fa7c9f9..8d56115 100644
--- a/drivers/usb/phy/phy-fsl-usb.c
+++ b/drivers/usb/phy/phy-fsl-usb.c
@@ -443,6 +443,7 @@ void otg_reset_controller(void)
int fsl_otg_start_host(struct otg_fsm *fsm, int on)
{
struct usb_otg *otg = fsm->otg;
+ struct usb_bus *host = otg->host;
struct device *dev;
struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy);
u32 retval = 0;
@@ -465,6 +466,7 @@ int fsl_otg_start_host(struct otg_fsm *fsm, int on)
otg_reset_controller();
VDBG("host on......\n");
if (dev->driver->pm && dev->driver->pm->resume) {
+ host->is_otg = 1;
retval = dev->driver->pm->resume(dev);
if (fsm->id) {
/* default-b */
@@ -489,8 +491,11 @@ int fsl_otg_start_host(struct otg_fsm *fsm, int on)
else {
VDBG("host off......\n");
if (dev && dev->driver) {
- if (dev->driver->pm && dev->driver->pm->suspend)
+ if (dev->driver->pm &&
+ dev->driver->pm->suspend) {
+ host->is_otg = 1;
retval = dev->driver->pm->suspend(dev);
+ }
if (fsm->id)
/* default-b */
fsl_otg_drv_vbus(0);
@@ -518,8 +523,17 @@ int fsl_otg_start_gadget(struct otg_fsm *fsm, int on)
dev = otg->gadget->dev.parent;
if (on) {
- if (dev->driver->resume)
+ /* Delay gadget resume to synchronize between host and gadget
+ * drivers. Upon role-reversal host drv is shutdown by kernel
+ * worker thread. By the time host drv shuts down, controller
+ * gets programmed for gadget role. Shutting host drv after
+ * this results in controller getting reset, and it stops
+ * responding to otg events
+ */
+ if (dev->driver->resume) {
+ msleep(1000);
dev->driver->resume(dev);
+ }
} else {
if (dev->driver->suspend)
dev->driver->suspend(dev, otg_suspend_state);
@@ -651,6 +665,10 @@ static void fsl_otg_event(struct work_struct *work)
fsl_otg_start_host(fsm, 0);
otg_drv_vbus(fsm, 0);
fsl_otg_start_gadget(fsm, 1);
+ } else {
+ fsl_otg_start_gadget(fsm, 0);
+ otg_drv_vbus(fsm, 1);
+ fsl_otg_start_host(fsm, 1);
}
}
@@ -703,6 +721,7 @@ irqreturn_t fsl_otg_isr(int irq, void *dev_id)
{
struct otg_fsm *fsm = &((struct fsl_otg *)dev_id)->fsm;
struct usb_otg *otg = ((struct fsl_otg *)dev_id)->phy.otg;
+ struct fsl_otg *otg_dev = dev_id;
u32 otg_int_src, otg_sc;
otg_sc = fsl_readl(&usb_dr_regs->otgsc);
@@ -732,18 +751,8 @@ irqreturn_t fsl_otg_isr(int irq, void *dev_id)
otg->gadget->is_a_peripheral = !fsm->id;
VDBG("ID int (ID is %d)\n", fsm->id);
- if (fsm->id) { /* switch to gadget */
- schedule_delayed_work(
- &((struct fsl_otg *)dev_id)->otg_event,
- 100);
- } else { /* switch to host */
- cancel_delayed_work(&
- ((struct fsl_otg *)dev_id)->
- otg_event);
- fsl_otg_start_gadget(fsm, 0);
- otg_drv_vbus(fsm, 1);
- fsl_otg_start_host(fsm, 1);
- }
+ schedule_delayed_work(&otg_dev->otg_event, 100);
+
return IRQ_HANDLED;
}
}
@@ -902,12 +911,32 @@ int usb_otg_start(struct platform_device *pdev)
temp &= ~(PORTSC_PHY_TYPE_SEL | PORTSC_PTW);
switch (pdata->phy_mode) {
case FSL_USB2_PHY_ULPI:
+ if (pdata->controller_ver) {
+ /* controller version 1.6 or above */
+ setbits32(&p_otg->dr_mem_map->control,
+ USB_CTRL_ULPI_PHY_CLK_SEL);
+ /*
+ * Due to controller issue of PHY_CLK_VALID in ULPI
+ * mode, we set USB_CTRL_USB_EN before checking
+ * PHY_CLK_VALID, otherwise PHY_CLK_VALID doesn't work.
+ */
+ clrsetbits_be32(&p_otg->dr_mem_map->control,
+ USB_CTRL_UTMI_PHY_EN, USB_CTRL_IOENB);
+ }
temp |= PORTSC_PTS_ULPI;
break;
case FSL_USB2_PHY_UTMI_WIDE:
temp |= PORTSC_PTW_16BIT;
/* fall through */
case FSL_USB2_PHY_UTMI:
+ if (pdata->controller_ver) {
+ /* controller version 1.6 or above */
+ setbits32(&p_otg->dr_mem_map->control,
+ USB_CTRL_UTMI_PHY_EN);
+ /* Delay for UTMI PHY CLK to become stable - 10ms */
+ mdelay(FSL_UTMI_PHY_DLY);
+ }
+ setbits32(&p_otg->dr_mem_map->control, USB_CTRL_UTMI_PHY_EN);
temp |= PORTSC_PTS_UTMI;
/* fall through */
default:
diff --git a/drivers/usb/phy/phy-fsl-usb.h b/drivers/usb/phy/phy-fsl-usb.h
index e1859b8..e53eff5 100644
--- a/drivers/usb/phy/phy-fsl-usb.h
+++ b/drivers/usb/phy/phy-fsl-usb.h
@@ -199,6 +199,14 @@
/* control Register Bit Masks */
#define USB_CTRL_IOENB (0x1<<2)
#define USB_CTRL_ULPI_INT0EN (0x1<<0)
+#define USB_CTRL_WU_INT_EN (0x1<<1)
+#define USB_CTRL_LINE_STATE_FILTER__EN (0x1<<3)
+#define USB_CTRL_KEEP_OTG_ON (0x1<<4)
+#define USB_CTRL_OTG_PORT (0x1<<5)
+#define USB_CTRL_PLL_RESET (0x1<<8)
+#define USB_CTRL_UTMI_PHY_EN (0x1<<9)
+#define USB_CTRL_ULPI_PHY_CLK_SEL (0x1<<10)
+#define USB_CTRL_PHY_CLK_VALID (0x1<<17)
/* BCSR5 */
#define BCSR5_INT_USB (0x02)
diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
index 26b3d9d..2990cb1 100644
--- a/drivers/vfio/Kconfig
+++ b/drivers/vfio/Kconfig
@@ -3,6 +3,16 @@ config VFIO_IOMMU_TYPE1
depends on VFIO
default n
+config VFIO_IOMMU_FSL_PAMU
+ tristate
+ depends on VFIO
+ default n
+
+config VFIO_IOMMU_DUMMY
+ tristate
+ depends on VFIO
+ default n
+
config VFIO_IOMMU_SPAPR_TCE
tristate
depends on VFIO && SPAPR_TCE_IOMMU
@@ -12,6 +22,8 @@ menuconfig VFIO
tristate "VFIO Non-Privileged userspace driver framework"
depends on IOMMU_API
select VFIO_IOMMU_TYPE1 if X86
+ select VFIO_IOMMU_FSL_PAMU if FSL_PAMU
+ select VFIO_IOMMU_DUMMY if DUMMY_IOMMU
select VFIO_IOMMU_SPAPR_TCE if (PPC_POWERNV || PPC_PSERIES)
help
VFIO provides a framework for secure userspace device drivers.
@@ -20,3 +32,4 @@ menuconfig VFIO
If you don't know what to do here, say N.
source "drivers/vfio/pci/Kconfig"
+source "drivers/vfio/fsl_pci_ep/Kconfig"
diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile
index 72bfabc..d997a16 100644
--- a/drivers/vfio/Makefile
+++ b/drivers/vfio/Makefile
@@ -1,4 +1,7 @@
obj-$(CONFIG_VFIO) += vfio.o
obj-$(CONFIG_VFIO_IOMMU_TYPE1) += vfio_iommu_type1.o
+obj-$(CONFIG_VFIO_IOMMU_FSL_PAMU) += vfio_iommu_fsl_pamu.o
+obj-$(CONFIG_VFIO_IOMMU_DUMMY) += vfio_iommu_dummy.o
obj-$(CONFIG_VFIO_IOMMU_SPAPR_TCE) += vfio_iommu_spapr_tce.o
obj-$(CONFIG_VFIO_PCI) += pci/
+obj-$(CONFIG_VFIO_FSL_PCI_EP) += fsl_pci_ep/
diff --git a/drivers/vfio/fsl_pci_ep/Kconfig b/drivers/vfio/fsl_pci_ep/Kconfig
new file mode 100644
index 0000000..527543b
--- /dev/null
+++ b/drivers/vfio/fsl_pci_ep/Kconfig
@@ -0,0 +1,8 @@
+config VFIO_FSL_PCI_EP
+ tristate "VFIO support for Freescale PCI Endpoint devices"
+ depends on VFIO && EVENTFD
+ help
+ Support for the Freescale PCI EP driver. This is required to make
+ use of PCI EP drivers using the VFIO framework.
+
+ If you don't know what to do here, say N.
diff --git a/drivers/vfio/fsl_pci_ep/Makefile b/drivers/vfio/fsl_pci_ep/Makefile
new file mode 100644
index 0000000..c2103dd
--- /dev/null
+++ b/drivers/vfio/fsl_pci_ep/Makefile
@@ -0,0 +1,2 @@
+fsl-pci-ep-y := fsl_pci_ep.o fsl_pci_ep_vfio.o
+obj-$(CONFIG_VFIO_FSL_PCI_EP) += fsl-pci-ep.o
diff --git a/drivers/vfio/fsl_pci_ep/fsl_pci_ep.c b/drivers/vfio/fsl_pci_ep/fsl_pci_ep.c
new file mode 100644
index 0000000..94a5e05
--- /dev/null
+++ b/drivers/vfio/fsl_pci_ep/fsl_pci_ep.c
@@ -0,0 +1,1661 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Minghuan Lian <Minghuan.Lian@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <sysdev/fsl_pci.h>
+#include <linux/log2.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/device.h>
+#include <linux/eventfd.h>
+#include <linux/interrupt.h>
+#include <linux/iommu.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include "fsl_pci_ep.h"
+
+#define CONFIG_ACCESS_PF_SHIFT 8
+#define CONFIG_ACCESS_VF_SHIFT 12
+#define CONFIG_ACCESS_EXTREG_SHIFT 24
+#define CONFIG_ACCESS_TYPE_SHIFT 29
+#define CONFIG_ACCESS_TYPE_NO_SRIOV 0
+#define CONFIG_ACCESS_TYPE_PF_SRIOV 1
+#define CONFIG_ACCESS_TYPE_VF_SRIOV 3
+#define CONFIG_ACCESS_ENABLE (1 << 31)
+
+#define PCI_ATMU_MIN_SIZE (4 * 1024) /* The smallest window size is 4 Kbytes */
+#define PCI_OB_WIN_MEM_ATTR 0x80044000 /* enable & mem R/W */
+
+static DEFINE_SPINLOCK(pci_ep_spinlock);
+LIST_HEAD(pci_ep_controllers);
+
+static int global_phb_number; /* Global phb counter */
+
+u32 fsl_pci_msix_vector_read(struct pci_ep_dev *ep, int vector, int eidx)
+{
+ struct pcie_utility_regs *putil;
+ int type, vf_idx, addr, data;
+
+ putil = &ep->pf->regs->putil;
+
+ if (ep->type == PCI_EP_TYPE_PF) {
+ type = PAOR_MSIX_PF_TYPE;
+ vf_idx = 0;
+ } else {
+ type = PAOR_MSIX_VF_TYPE;
+ vf_idx = ep->idx - 1;
+ }
+
+ addr = type << PAOR_MSIX_TYPE_SHIFT |
+ ep->pf->idx << PAOR_MSIX_PF_SHIFT |
+ vf_idx << PAOR_MSIX_VF_SHIFT |
+ vector << PAOR_MSIX_ENTRY_IDX_SHIFT |
+ eidx << PAOR_MSIX_ENTRY_EIDX_SHIFT |
+ PAOR_MSIX_VECTOR_MODE;
+
+ iowrite32be(addr, &putil->pex_aor);
+ data = ioread32(&putil->pex_ldr);
+
+ return data;
+}
+
+u32 fsl_pci_msix_pba_read(struct pci_ep_dev *ep, int vector)
+{
+ struct pcie_utility_regs *putil;
+ int type, vf_idx, addr, data;
+
+ putil = &ep->pf->regs->putil;
+
+ if (ep->type == PCI_EP_TYPE_PF) {
+ type = PAOR_MSIX_PF_TYPE;
+ vf_idx = 0;
+ } else {
+ type = PAOR_MSIX_VF_TYPE;
+ vf_idx = ep->idx - 1;
+ }
+
+ addr = type << PAOR_MSIX_TYPE_SHIFT |
+ ep->pf->idx << PAOR_MSIX_PF_SHIFT |
+ vf_idx << PAOR_MSIX_VF_SHIFT |
+ vector << PAOR_MSIX_ENTRY_IDX_SHIFT |
+ (vector / 32) << PAOR_MSIX_ENTRY_EIDX_SHIFT |
+ PAOR_MSIX_PBA_MODE;
+
+ iowrite32be(addr, &putil->pex_aor);
+ data = ioread32(&putil->pex_ldr);
+
+ return data;
+}
+
+static inline size_t attr_to_size(u32 attr)
+{
+ int bits = (attr & 0x3f);
+
+ if (bits == 0)
+ return 0;
+
+ return (size_t)2 << bits;
+}
+
+static int fsl_pci_find_bar_pos(struct pci_dev *dev, int base, int idx)
+{
+ int i, bar32, pos = base;
+
+ if (idx >= FSL_PCI_EP_BAR_NUM)
+ return -EINVAL;
+
+ for (i = 0; i < idx; i++) {
+ pci_read_config_dword(dev, pos, &bar32);
+ if (bar32 & 0x4) /* 64-bit address space */
+ pos += 8;
+ else
+ pos += 4;
+ }
+
+ return pos;
+}
+
+static u64 fsl_pci_read_bar(struct pci_dev *dev, int pos)
+{
+ u64 bar64;
+ u32 bar32;
+
+ pci_read_config_dword(dev, pos, &bar32);
+ bar64 = bar32 & 0xfffffff0;
+ if (bar32 & 0x4) {
+ /* 64-bit address space */
+ pci_read_config_dword(dev, pos + 4, &bar32);
+ bar64 |= (u64)bar32 << 32;
+ }
+
+ return bar64;
+}
+
+static u64 fsl_pci_pf_read_vfbar(struct pci_pf_dev *pf, int idx)
+{
+ struct pci_dev *pdev = pf->pdev;
+ int pos;
+
+ pos = fsl_pci_find_bar_pos(pdev, pf->vf_pos + PCI_SRIOV_BAR, idx);
+ return fsl_pci_read_bar(pdev, pos);
+}
+
+static u64 fsl_pci_pf_read_bar(struct pci_pf_dev *pf, int idx)
+{
+ struct pci_dev *pdev = pf->pdev;
+ int pos;
+
+ pos = fsl_pci_find_bar_pos(pdev, PCI_BASE_ADDRESS_0, idx);
+ return fsl_pci_read_bar(pdev, pos);
+}
+
+static u64 fsl_pci_ep_read_bar(struct pci_ep_dev *ep, int idx)
+{
+ if (idx >= ep->iw_num)
+ return 0;
+
+ if (ep->type == PCI_EP_TYPE_PF)
+ return fsl_pci_pf_read_bar(ep->pf, idx);
+ else
+ return fsl_pci_pf_read_vfbar(ep->pf, idx);
+}
+
+static int fsl_pci_ep_get_ibwin(struct pci_ep_dev *ep,
+ struct pci_ep_win *win)
+{
+ struct pci_pf_dev *pf = ep->pf;
+ struct pci_inbound_window_regs *iw_regs;
+
+ if (win->idx >= ep->iw_num)
+ return -EINVAL;
+
+ if (ep->type == PCI_EP_TYPE_PF) {
+ iw_regs = &pf->regs->piw[ep->iw_num - win->idx - 1];
+
+ spin_lock(&pf->lock);
+ win->cpu_addr =
+ ((u64)in_be32(&iw_regs->pitar)) << 12;
+ win->attr = in_be32(&iw_regs->piwar);
+ spin_unlock(&pf->lock);
+
+ win->size = attr_to_size(win->attr);
+ win->pci_addr = fsl_pci_ep_read_bar(ep, win->idx);
+ } else {
+ /* VF inbound windows */
+ iw_regs = &pf->vf_regs->vfiw[ep->iw_num - win->idx - 1];
+
+ spin_lock(&pf->lock);
+ win->cpu_addr =
+ ((u64)in_be32(&iw_regs->pitar)) << 12;
+ win->attr = in_be32(&iw_regs->piwar);
+ spin_unlock(&pf->lock);
+
+ win->size = attr_to_size(win->attr);
+ win->pci_addr = fsl_pci_ep_read_bar(ep, win->idx);
+ win->cpu_addr += win->size * (ep->idx - 1);
+ win->pci_addr += win->size * (ep->idx - 1);
+ }
+
+ return 0;
+}
+
+static int fsl_pci_ep_get_obwin(struct pci_ep_dev *ep,
+ struct pci_ep_win *win)
+{
+ struct pci_pf_dev *pf = ep->pf;
+ struct pci_outbound_window_regs *ow_regs;
+
+ if (win->idx >= ep->ow_num)
+ return -EINVAL;
+
+ if (ep->type == PCI_EP_TYPE_PF) {
+ ow_regs = &pf->regs->pow[win->idx];
+
+ spin_lock(&pf->lock);
+ win->cpu_addr = ((u64)in_be32(&ow_regs->powbar)) << 12;
+ win->pci_addr =
+ ((u64)in_be32(&ow_regs->potear)) << 44 |
+ ((u64)in_be32(&ow_regs->potar)) << 12;
+ win->attr = in_be32(&ow_regs->powar);
+ spin_unlock(&pf->lock);
+
+ win->size = attr_to_size(win->attr);
+ } else {
+ /* VF outbound windows */
+ struct vf_owta_regs *ta;
+
+ ow_regs = &pf->vf_regs->vfow[win->idx];
+ ta = &pf->vf_regs->vfowta[win->idx][ep->idx - 1];
+
+ spin_lock(&pf->lock);
+ win->cpu_addr = ((u64)in_be32(&ow_regs->powbar)) << 12;
+ win->pci_addr =
+ ((u64)in_be32(&ta->tear)) << 44 |
+ ((u64)in_be32(&ta->tar)) << 12;
+ win->attr = in_be32(&ow_regs->powar);
+ spin_unlock(&pf->lock);
+
+ win->size = attr_to_size(win->attr);
+ win->cpu_addr += win->size * (ep->idx - 1);
+ }
+
+ return 0;
+}
+
+static int fsl_pci_ep_get_msixobwin(struct pci_ep_dev *ep,
+ struct pci_ep_win *win)
+{
+ struct pci_pf_dev *pf = ep->pf;
+ struct pci_outbound_window_regs *ow_regs;
+
+
+ if (ep->type != PCI_EP_TYPE_PF)
+ return -EINVAL;
+
+ ow_regs = &pf->regs->msixow;
+
+ spin_lock(&pf->lock);
+ win->cpu_addr = ((u64)in_be32(&ow_regs->powbar)) << 12;
+ win->pci_addr = 0;
+ win->attr = in_be32(&ow_regs->powar);
+ spin_unlock(&pf->lock);
+
+ win->size = attr_to_size(win->attr);
+
+ return 0;
+}
+
+static int fsl_pci_ep_get_vfibwin(struct pci_ep_dev *ep,
+ struct pci_ep_win *win)
+{
+ struct pci_pf_dev *pf = ep->pf;
+ struct pci_inbound_window_regs *iw_regs;
+
+ if (win->idx >= pf->vf_iw_num)
+ return -EINVAL;
+
+ if (ep->type != PCI_EP_TYPE_PF)
+ return -EINVAL;
+
+ /* VF inbound windows */
+ iw_regs = &pf->vf_regs->vfiw[pf->vf_iw_num - win->idx - 1];
+
+ spin_lock(&pf->lock);
+ win->cpu_addr =
+ ((u64)in_be32(&iw_regs->pitar)) << 12;
+ win->attr = in_be32(&iw_regs->piwar);
+ spin_unlock(&pf->lock);
+
+ win->size = attr_to_size(win->attr);
+ win->pci_addr = fsl_pci_pf_read_vfbar(pf, win->idx);
+
+ return 0;
+}
+
+static int fsl_pci_ep_get_vfobwin(struct pci_ep_dev *ep,
+ struct pci_ep_win *win)
+{
+ struct pci_pf_dev *pf = ep->pf;
+ struct pci_outbound_window_regs *ow_regs;
+ struct vf_owta_regs *ta;
+
+ if (win->idx >= pf->vf_ow_num)
+ return -EINVAL;
+
+ if (ep->type != PCI_EP_TYPE_PF)
+ return -EINVAL;
+
+ ow_regs = &pf->vf_regs->vfow[win->idx];
+ ta = &pf->vf_regs->vfowta[win->idx][0];
+
+ spin_lock(&pf->lock);
+ win->cpu_addr = ((u64)in_be32(&ow_regs->powbar)) << 12;
+ win->pci_addr =
+ ((u64)in_be32(&ta->tear)) << 44 |
+ ((u64)in_be32(&ta->tar)) << 12;
+ win->attr = in_be32(&ow_regs->powar);
+ spin_unlock(&pf->lock);
+
+ win->size = attr_to_size(win->attr);
+
+ return 0;
+}
+
+static int fsl_pci_ep_get_reg_win(struct pci_ep_dev *ep,
+ struct pci_ep_win *win)
+{
+ win->cpu_addr = ep->pf->regs_rs.start;
+ win->size = resource_size(&ep->pf->regs_rs);
+ win->attr = 0x80000000; /* Enabled */
+
+ return 0;
+}
+
+static int fsl_pci_ep_get_mem_win(struct pci_ep_dev *ep,
+ struct pci_ep_win *win)
+{
+ if (ep->type == PCI_EP_TYPE_PF) {
+ if (win->idx != 0)
+ goto _err;
+ win->cpu_addr = ep->pf->mem_resources[win->idx].start;
+ win->size = resource_size(&ep->pf->mem_resources[win->idx]);
+ win->attr = 0x80000000; /* Enabled */
+ }
+
+ return 0;
+_err:
+ win->attr = 0;
+ return -EINVAL;
+}
+
+int fsl_pci_ep_get_win(struct pci_ep_dev *ep, struct pci_ep_win *win)
+{
+ int ret;
+
+ switch (win->type) {
+ case PCI_EP_REGION_IBWIN:
+ ret = fsl_pci_ep_get_ibwin(ep, win);
+ break;
+ case PCI_EP_REGION_OBWIN:
+ ret = fsl_pci_ep_get_obwin(ep, win);
+ break;
+ case PCI_EP_REGION_VF_IBWIN:
+ ret = fsl_pci_ep_get_vfibwin(ep, win);
+ break;
+ case PCI_EP_REGION_VF_OBWIN:
+ ret = fsl_pci_ep_get_vfobwin(ep, win);
+ break;
+ case PCI_EP_REGION_REGS:
+ ret = fsl_pci_ep_get_reg_win(ep, win);
+ break;
+ case PCI_EP_REGION_MEM:
+ ret = fsl_pci_ep_get_mem_win(ep, win);
+ break;
+ case PCI_EP_REGION_MSIX_OBWIN:
+ ret = fsl_pci_ep_get_msixobwin(ep, win);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int fsl_pci_ep_set_ibwin(struct pci_ep_dev *ep,
+ struct pci_ep_win *win)
+{
+ struct pci_pf_dev *pf = ep->pf;
+ struct pci_inbound_window_regs *iw_regs;
+
+ if (win->idx >= ep->iw_num)
+ return -EINVAL;
+
+ if (ep->type == PCI_EP_TYPE_PF) {
+ u32 attr;
+
+ iw_regs = &pf->regs->piw[ep->iw_num - win->idx - 1];
+
+ if (win->size < PCI_ATMU_MIN_SIZE)
+ attr = 0;
+ else
+ attr = PIWAR_EN | PIWAR_PF | PIWAR_TGI_LOCAL |
+ PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP |
+ (ilog2(win->size) - 1);
+
+ /* Setup inbound memory window */
+ spin_lock(&pf->lock);
+ out_be32(&iw_regs->pitar, win->cpu_addr >> 12);
+ if (win->attr) /* use the specific attribute */
+ out_be32(&iw_regs->piwar, win->attr);
+ else /* use the default attribute */
+ out_be32(&iw_regs->piwar, attr);
+ spin_unlock(&pf->lock);
+ } else {
+ /*
+ * All VFs use the common VF inbound windows
+ * So an EP(VF) device can not change VF Inbound windows
+ * Only PF device can call fsl_pci_ep_set_vfibwin() to
+ * change VF's inbound windows
+ */
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int fsl_pci_ep_set_obwin(struct pci_ep_dev *ep,
+ struct pci_ep_win *win)
+{
+ struct pci_pf_dev *pf = ep->pf;
+ struct pci_outbound_window_regs *ow_regs;
+
+ if (win->idx >= ep->iw_num)
+ return -EINVAL;
+
+ ow_regs = &pf->regs->pow[win->idx];
+
+ if (ep->type == PCI_EP_TYPE_PF) {
+ int bits;
+ u32 attr; /* enable & mem R/W */
+
+ if (win->size < PCI_ATMU_MIN_SIZE)
+ attr = 0;
+ else {
+ bits = min(ilog2(win->size),
+ __ffs(win->pci_addr | win->cpu_addr));
+ attr = PCI_OB_WIN_MEM_ATTR | (bits - 1);
+ }
+ spin_lock(&pf->lock);
+ out_be32(&ow_regs->potar, win->pci_addr >> 12);
+ out_be32(&ow_regs->potear, win->pci_addr >> 44);
+ out_be32(&ow_regs->powbar, win->cpu_addr >> 12);
+ if (win->attr) /* use the specific attribute */
+ out_be32(&ow_regs->powar, win->attr);
+ else /* use the default attribute */
+ out_be32(&ow_regs->powar, attr);
+ spin_unlock(&pf->lock);
+ } else {
+ /*
+ * For an outbound window, each VF has a translation
+ * register separately and other registers are shared
+ * by all VFs. So an EP device can only change owtar
+ */
+ struct vf_owta_regs *ta;
+
+ ta = &pf->vf_regs->vfowta[win->idx][ep->idx - 1];
+ out_be32(&ta->tar, win->pci_addr >> 12);
+ out_be32(&ta->tear, win->pci_addr >> 44);
+ }
+
+ return 0;
+}
+
+static int fsl_pci_ep_set_msixobwin(struct pci_ep_dev *ep,
+ struct pci_ep_win *win)
+{
+ struct pci_pf_dev *pf = ep->pf;
+ struct pci_outbound_window_regs *ow_regs;
+ u32 flags = 0x8000400b; /* enable 4K MSIX outbound window */
+
+ ow_regs = &pf->regs->msixow;
+
+ if (ep->type != PCI_EP_TYPE_PF)
+ return -EINVAL;
+
+ if (win->size != FSL_PCI_EP_MSIX_OW_SIZE)
+ return -EINVAL;
+
+ spin_lock(&pf->lock);
+ out_be32(&ow_regs->powbar, win->cpu_addr >> 12);
+ if (win->attr) /* use the specific attribute */
+ out_be32(&ow_regs->powar, win->attr);
+ else /* use the default attribute */
+ out_be32(&ow_regs->powar, flags);
+ spin_unlock(&pf->lock);
+
+ return 0;
+}
+
+static int fsl_pci_ep_set_vfibwin(struct pci_ep_dev *ep,
+ struct pci_ep_win *win)
+{
+ struct pci_pf_dev *pf = ep->pf;
+ struct pci_inbound_window_regs *iw_regs;
+ u32 attr;
+
+ if (win->idx >= ep->iw_num)
+ return -EINVAL;
+
+ /* Only PF can set VF ATMU */
+ if (ep->type != PCI_EP_TYPE_PF)
+ return -EINVAL;
+
+ if (win->size < PCI_ATMU_MIN_SIZE)
+ attr = 0;
+ else
+ attr = PIWAR_EN | PIWAR_PF | PIWAR_TGI_LOCAL |
+ PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP |
+ (ilog2(win->size) - 1);
+
+ iw_regs = &pf->vf_regs->vfiw[ep->iw_num - win->idx - 1];
+
+ /* Setup inbound memory window */
+ spin_lock(&pf->lock);
+ out_be32(&iw_regs->pitar, win->cpu_addr >> 12);
+ if (win->attr) /* use the specified attribute */
+ out_be32(&iw_regs->piwar, win->attr);
+ else /* use the default attribute */
+ out_be32(&iw_regs->piwar, attr);
+ spin_unlock(&pf->lock);
+
+ return 0;
+}
+
+static int fsl_pci_ep_set_vfobwin(struct pci_ep_dev *ep,
+ struct pci_ep_win *win)
+{
+ struct pci_pf_dev *pf = ep->pf;
+ struct pci_outbound_window_regs *ow_regs;
+ int bits;
+ u32 attr;
+
+ if (win->idx >= ep->iw_num)
+ return -EINVAL;
+
+ /* Only PF can set VF ATMU */
+ if (ep->type != PCI_EP_TYPE_PF)
+ return -EINVAL;
+
+ ow_regs = &pf->vf_regs->vfow[win->idx];
+
+ if (win->size < PCI_ATMU_MIN_SIZE)
+ attr = 0;
+ else {
+ bits = min(ilog2(win->size),
+ __ffs(win->pci_addr | win->cpu_addr));
+ attr = PCI_OB_WIN_MEM_ATTR | (bits - 1);
+ }
+
+ spin_lock(&pf->lock);
+ out_be32(&ow_regs->powbar, win->cpu_addr >> 12);
+ if (win->attr) /* use the specified attribute */
+ out_be32(&ow_regs->powar, win->attr);
+ else /* use the default attribute */
+ out_be32(&ow_regs->powar, attr);
+ spin_unlock(&pf->lock);
+
+ return 0;
+}
+
+int fsl_pci_ep_set_win(struct pci_ep_dev *ep, struct pci_ep_win *win)
+{
+ int ret;
+
+ switch (win->type) {
+ case PCI_EP_REGION_IBWIN:
+ ret = fsl_pci_ep_set_ibwin(ep, win);
+ break;
+ case PCI_EP_REGION_OBWIN:
+ ret = fsl_pci_ep_set_obwin(ep, win);
+ break;
+ case PCI_EP_REGION_VF_IBWIN:
+ ret = fsl_pci_ep_set_vfibwin(ep, win);
+ break;
+ case PCI_EP_REGION_VF_OBWIN:
+ ret = fsl_pci_ep_set_vfobwin(ep, win);
+ break;
+ case PCI_EP_REGION_MSIX_OBWIN:
+ ret = fsl_pci_ep_set_msixobwin(ep, win);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static struct pci_ep_dev *
+fsl_pci_ep_find(struct pci_controller *controller, int devfn)
+{
+ struct pci_pf_dev *pf;
+ struct pci_ep_dev *tmp, *ep = NULL;
+ struct list_head *pf_list = controller->private_data;
+
+ list_for_each_entry(pf, pf_list, node)
+ list_for_each_entry(tmp, &pf->ep_list, node)
+ if (tmp->devfn == devfn) {
+ ep = tmp;
+ break;
+ }
+
+ return ep;
+}
+
+static int fsl_pci_ep_read_config(struct pci_bus *bus, unsigned int devfn,
+ int offset, int len, u32 *val)
+{
+ struct pci_controller *hose = pci_bus_to_host(bus);
+ struct pci_ep_dev *ep;
+ volatile void __iomem *cfg_data;
+ u32 type, reg;
+ int real_devfn, pf_idx, vf_idx;
+
+ real_devfn = bus->number << 8 | devfn;
+
+ if (real_devfn < MULTI_FUNCTION_NUM) {
+ /* physical function */
+ pf_idx = real_devfn;
+ vf_idx = 0;
+ type = CONFIG_ACCESS_TYPE_NO_SRIOV;
+ } else {
+ /* virtual function */
+ ep = fsl_pci_ep_find(hose, real_devfn);
+ if (!ep || ep->type != PCI_EP_TYPE_VF)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ pf_idx = ep->pf->idx;
+ vf_idx = ep->idx - 1;
+ type = CONFIG_ACCESS_TYPE_VF_SRIOV;
+ }
+
+ reg = ((offset & 0xf00) << (CONFIG_ACCESS_EXTREG_SHIFT - 8)) |
+ (offset & 0xfc);
+
+ out_be32(hose->cfg_addr, CONFIG_ACCESS_ENABLE | reg |
+ type << CONFIG_ACCESS_TYPE_SHIFT |
+ vf_idx << CONFIG_ACCESS_VF_SHIFT |
+ pf_idx << CONFIG_ACCESS_PF_SHIFT);
+
+ /*
+ * Note: the caller has already checked that offset is
+ * suitably aligned and that len is 1, 2 or 4.
+ */
+ cfg_data = hose->cfg_data + (offset & 3);
+ switch (len) {
+ case 1:
+ *val = in_8(cfg_data);
+ break;
+ case 2:
+ *val = in_le16(cfg_data);
+ break;
+ default:
+ *val = in_le32(cfg_data);
+ break;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int fsl_pci_ep_write_config(struct pci_bus *bus, unsigned int devfn,
+ int offset, int len, u32 val)
+{
+ /* EP should not configure any register on config field */
+ return PCIBIOS_SET_FAILED;
+}
+
+static struct pci_ops fsl_pci_ep_ops = {
+ .read = fsl_pci_ep_read_config,
+ .write = fsl_pci_ep_write_config,
+};
+
+static void fsl_pci_ep_access_create(struct pci_controller *host,
+ resource_size_t cfg_addr,
+ resource_size_t cfg_data, u32 flags)
+{
+ resource_size_t base = cfg_addr & PAGE_MASK;
+ void __iomem *mbase;
+
+ mbase = ioremap(base, PAGE_SIZE);
+ host->cfg_addr = mbase + (cfg_addr & ~PAGE_MASK);
+ if ((cfg_data & PAGE_MASK) != base)
+ mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
+ host->cfg_data = mbase + (cfg_data & ~PAGE_MASK);
+ host->ops = &fsl_pci_ep_ops;
+ host->indirect_type = flags;
+}
+
+static void fsl_pci_ep_access_free(struct pci_controller *host)
+{
+ /* unmap cfg_data & cfg_addr separately if not on same page */
+ if (((unsigned long)host->cfg_data & PAGE_MASK) !=
+ ((unsigned long)host->cfg_addr & PAGE_MASK))
+ iounmap(host->cfg_data);
+ iounmap(host->cfg_addr);
+}
+
+static ssize_t
+inbound_windows_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct pci_ep_dev *ep = container_of(dev, struct pci_ep_dev, dev);
+ struct pci_ep_win win;
+ char *str = buf;
+ int i;
+
+ for (i = 0; i < ep->iw_num; i++) {
+ win.type = PCI_EP_REGION_IBWIN;
+ win.idx = i;
+ fsl_pci_ep_get_ibwin(ep, &win);
+ str += sprintf(str, "Inbound Window%d:\n"
+ "\tcpu_addr:0x%016llx pci_addr:0x%016llx\n"
+ "\twin_size:0x%016llx attribute:0x%08x\n",
+ i,
+ win.cpu_addr,
+ win.pci_addr,
+ win.size,
+ win.attr);
+ }
+
+ if (ep->type == PCI_EP_TYPE_PF) {
+ struct pci_pf_dev *pf = ep->pf;
+
+ if (pf->vf_regs) {
+ for (i = 0; i < pf->vf_iw_num; i++) {
+ win.idx = i;
+ fsl_pci_ep_get_vfibwin(ep, &win);
+ str += sprintf(str, "VF Inbound Window%d:\n"
+ "\tcpu_addr:0x%016llx"
+ " pci_addr:0x%016llx\n"
+ "\twin_size:0x%016llx"
+ " attribute:0x%08x\n",
+ i,
+ win.cpu_addr,
+ win.pci_addr,
+ win.size,
+ win.attr);
+ }
+ }
+ }
+
+ return str - buf;
+}
+
+static ssize_t
+outbound_windows_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct pci_ep_dev *ep = container_of(dev, struct pci_ep_dev, dev);
+ struct pci_ep_win win;
+ char *str = buf;
+ int i;
+
+ for (i = 0; i < ep->ow_num; i++) {
+ win.type = PCI_EP_REGION_OBWIN;
+ win.idx = i;
+ fsl_pci_ep_get_obwin(ep, &win);
+ str += sprintf(str, "Outbound Window%d:\n"
+ "\tcpu_addr:0x%016llx pci_addr:0x%016llx\n"
+ "\twin_size:0x%016llx attribute:0x%08x\n",
+ i,
+ win.cpu_addr,
+ win.pci_addr,
+ win.size,
+ win.attr);
+ }
+
+ if (ep->type == PCI_EP_TYPE_PF) {
+ struct pci_pf_dev *pf = ep->pf;
+ if (pf->msix_enable) {
+ fsl_pci_ep_get_msixobwin(ep, &win);
+ str += sprintf(str, "MSIX Outbound Window:\n"
+ "\tcpu_addr:0x%016llx\n"
+ "\twin_size:0x%016llx"
+ " attribute:0x%08x\n",
+ win.cpu_addr,
+ win.size,
+ win.attr);
+ }
+
+ if (pf->vf_regs) {
+ for (i = 0; i < pf->vf_ow_num; i++) {
+ win.idx = i;
+ fsl_pci_ep_get_vfobwin(ep, &win);
+ str += sprintf(str, "VF Outbound Window%d:\n"
+ "\tcpu_addr:0x%016llx"
+ " pci_addr:0x%016llx\n"
+ "\twin_size:0x%016llx"
+ " attribute:0x%08x\n",
+ i,
+ win.cpu_addr,
+ win.pci_addr,
+ win.size,
+ win.attr);
+ }
+ }
+ }
+
+ return str - buf;
+}
+
+static ssize_t
+pf_idx_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct pci_ep_dev *ep = container_of(dev, struct pci_ep_dev, dev);
+
+ return sprintf(buf, "%d\n", ep->pf->idx);
+}
+
+static ssize_t
+vf_idx_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct pci_ep_dev *ep = container_of(dev, struct pci_ep_dev, dev);
+
+ return sprintf(buf, "%d\n", ep->idx);
+}
+
+static ssize_t
+ep_type_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct pci_ep_dev *ep = container_of(dev, struct pci_ep_dev, dev);
+
+ return sprintf(buf, "%s\n",
+ ep->type == PCI_EP_TYPE_PF ? "PF" : "VF");
+}
+
+static ssize_t
+msix_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct pci_ep_dev *ep = container_of(dev, struct pci_ep_dev, dev);
+ char *str = buf;
+ int i;
+
+ if (!ep->pf->msix_enable) {
+ str += sprintf(str, "Not support MSIX\n");
+ return str - buf;
+ }
+
+ for (i = 0; i < PCIE_MSIX_VECTOR_MAX_NUM; i++) {
+ str += sprintf(str,
+ "MSIX venctor %d:\n"
+ "\tcontrol:0x%x data:0x%08x addr:0x%016llx\n",
+ i,
+ fsl_pci_msix_vector_read(ep, i,
+ PAOR_MSIX_CONTROL_IDX),
+ fsl_pci_msix_vector_read(ep, i,
+ PAOR_MSIX_MSG_DATA_IDX),
+ (u64) fsl_pci_msix_vector_read(ep, i,
+ PAOR_MSIX_MSG_UADDR_IDX) << 32 |
+ fsl_pci_msix_vector_read(ep, i,
+ PAOR_MSIX_MSG_LADDR_IDX));
+ }
+
+ return str - buf;
+}
+
+static DEVICE_ATTR_RO(ep_type);
+static DEVICE_ATTR_RO(pf_idx);
+static DEVICE_ATTR_RO(vf_idx);
+static DEVICE_ATTR_RO(inbound_windows);
+static DEVICE_ATTR_RO(outbound_windows);
+static DEVICE_ATTR_RO(msix);
+
+static struct attribute *pci_ep_attrs[] = {
+ &dev_attr_ep_type.attr,
+ &dev_attr_pf_idx.attr,
+ &dev_attr_vf_idx.attr,
+ &dev_attr_inbound_windows.attr,
+ &dev_attr_outbound_windows.attr,
+ &dev_attr_msix.attr,
+ NULL,
+};
+
+ATTRIBUTE_GROUPS(pci_ep);
+
+static void pci_ep_dev_release(struct device *dev)
+{
+ /* nothing to do */
+}
+
+static void pci_ep_class_release(struct class *cls)
+{
+ /* nothing to do */
+}
+
+static struct class pci_ep_class = {
+ .name = "pci_ep",
+ .dev_groups = pci_ep_groups,
+ .dev_release = pci_ep_dev_release,
+ .class_release = pci_ep_class_release,
+};
+
+static int pci_ep_class_init(void)
+{
+ int ret;
+
+ ret = class_register(&pci_ep_class);
+ if (ret) {
+ pr_err("class_register failed for pci ep\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void pci_ep_class_free(void)
+{
+ class_unregister(&pci_ep_class);
+}
+
+static struct pci_bus *
+create_dummy_pci_bus(void *sysdata, struct pci_ops *ops, int busnum)
+{
+ struct pci_bus *b;
+
+ b = kzalloc(sizeof(*b), GFP_KERNEL);
+ if (!b)
+ return NULL;
+
+ INIT_LIST_HEAD(&b->node);
+ INIT_LIST_HEAD(&b->children);
+ INIT_LIST_HEAD(&b->devices);
+ INIT_LIST_HEAD(&b->slots);
+ INIT_LIST_HEAD(&b->resources);
+ b->max_bus_speed = PCI_SPEED_UNKNOWN;
+ b->cur_bus_speed = PCI_SPEED_UNKNOWN;
+ b->sysdata = sysdata;
+ b->ops = ops;
+ b->number = busnum;
+ dev_set_name(&b->dev, "%04x:%02x", pci_domain_nr(b), busnum);
+
+ return b;
+}
+
+static inline u8 fsl_pci_ep_devfn(struct pci_ep_dev *ep)
+{
+ struct pci_pf_dev *pf = ep->pf;
+
+ if (ep->type == PCI_EP_TYPE_PF)
+ return pf->idx;
+ else
+ return (pf->idx + pf->vf_offset +
+ pf->vf_stride * (ep->idx - 1)) & 0xff;
+}
+
+static inline u8 fsl_pci_ep_bus(struct pci_ep_dev *ep)
+{
+ struct pci_pf_dev *pf = ep->pf;
+
+ if (ep->type == PCI_EP_TYPE_PF)
+ return 0;
+ else
+ return (pf->idx + pf->vf_offset +
+ pf->vf_stride * (ep->idx - 1)) >> 8;
+}
+
+static struct pci_bus *fsl_pci_ep_add_bus(struct pci_bus *bus, int busnr)
+{
+ struct pci_bus *child;
+
+ if (bus->number == busnr)
+ return bus;
+
+ list_for_each_entry(child, &bus->children, children) {
+ if (child->number == busnr)
+ return child;
+ }
+
+ child = create_dummy_pci_bus(bus->sysdata, bus->ops, busnr);
+ if (!child)
+ return NULL;
+
+ child->self = bus->self;
+
+ list_add_tail(&child->children, &bus->children);
+
+ return child;
+}
+
+static void fsl_pci_bus_free(struct pci_bus *bus)
+{
+ struct pci_bus *child, *tmp;
+
+ list_for_each_entry_safe(child, tmp, &bus->children, children) {
+ list_del(&child->children);
+ kfree(child);
+ }
+
+ kfree(bus);
+}
+
+static struct pci_ep_dev *fsl_pci_ep_alloc(struct pci_pf_dev *pf, int idx)
+{
+ struct pci_ep_dev *ep;
+
+ ep = kzalloc(sizeof(*ep), GFP_KERNEL);
+ if (!ep)
+ return NULL;
+
+ ep->idx = idx;
+ ep->pf = pf;
+
+ if (idx == 0) {
+ ep->type = PCI_EP_TYPE_PF;
+ ep->iw_num = pf->iw_num;
+ ep->ow_num = pf->ow_num;
+ ep->devfn = pf->idx;
+ } else {
+ ep->type = PCI_EP_TYPE_VF;
+ ep->iw_num = pf->vf_iw_num;
+ ep->ow_num = pf->vf_ow_num;
+ ep->devfn = pf->idx + pf->vf_offset +
+ pf->vf_stride * (ep->idx - 1);
+ }
+
+ list_add_tail(&ep->node, &pf->ep_list);
+
+ return ep;
+}
+
+static int fsl_pci_ep_setup(struct pci_ep_dev *ep)
+{
+ struct pci_dev *pdev;
+
+ if (!ep || !ep->pf)
+ return -EINVAL;
+
+ if (!ep->pdev) {
+ pdev = alloc_pci_dev();
+ if (!pdev)
+ return -ENOMEM;
+
+ ep->pdev = pdev;
+ pdev->bus = fsl_pci_ep_add_bus(ep->pf->pbus,
+ fsl_pci_ep_bus(ep));
+ if (!pdev->bus)
+ return -ENOMEM;
+
+ pdev->devfn = fsl_pci_ep_devfn(ep);
+ pdev->sysdata = ep;
+ pdev->vendor = ep->pf->pdev->vendor;
+ pdev->device = ep->pf->pdev->device;
+ dev_set_name(&pdev->dev, "%04x:%02x:%02x.%d",
+ pci_domain_nr(pdev->bus),
+ pdev->bus->number, PCI_SLOT(pdev->devfn),
+ PCI_FUNC(pdev->devfn));
+ }
+
+ ep->dev.parent = ep->pf->parent;
+ ep->dev.of_node = ep->dev.parent->of_node;
+ ep->dev.iommu_group = iommu_group_get(ep->pf->parent);
+ ep->dev.bus = NULL;
+ ep->dev.class = &pci_ep_class;
+ if (ep->type == PCI_EP_TYPE_PF)
+ dev_set_name(&ep->dev, "pci%d-pf%d",
+ ep->pf->host->global_number,
+ ep->pf->idx);
+ else
+ dev_set_name(&ep->dev, "pci%d-pf%d-vf%d",
+ ep->pf->host->global_number,
+ ep->pf->idx,
+ ep->idx);
+
+ if (device_register(&ep->dev))
+ return -EINVAL;
+ ep->registered = 1;
+
+ fsl_pci_ep_vfio_init(ep);
+
+ return 0;
+}
+
+static void fsl_pci_ep_free(struct pci_ep_dev *ep)
+{
+ if (!ep)
+ return;
+
+ fsl_pci_ep_vfio_remove(ep);
+
+ kfree(ep->pdev);
+
+ if (ep->registered)
+ device_unregister(&ep->dev);
+
+ list_del(&ep->node);
+
+ kfree(ep);
+}
+
+static void fsl_pci_pf_cfg_ready(struct pci_pf_dev *pf)
+{
+ #define FSL_PCIE_CFG_RDY 0x4b0
+ #define CFG_READY 1
+
+ /* PCIe - set CFG_READY bit of Configuration Ready Register */
+ if (!pf->regs)
+ return;
+
+ if (in_be32(&pf->regs->block_rev1) >= PCIE_IP_REV_3_0)
+ out_be32(&pf->regs->pex_config,
+ in_be32(&pf->regs->pex_config) | CFG_READY);
+ else
+ pci_write_config_byte(pf->pdev, FSL_PCIE_CFG_RDY,
+ CFG_READY);
+}
+
+static int fsl_pci_pf_iov_init(struct pci_pf_dev *pf)
+{
+ int pos;
+ u16 total, offset, stride;
+ struct pci_dev *dev = pf->pdev;
+
+ if (!pci_is_pcie(dev))
+ return -ENODEV;
+
+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV);
+ if (!pos)
+ return 0;
+
+ pci_read_config_word(dev, pos + PCI_SRIOV_TOTAL_VF, &total);
+ if (!total)
+ return 0;
+
+ pci_read_config_word(dev, pos + PCI_SRIOV_VF_OFFSET, &offset);
+ pci_read_config_word(dev, pos + PCI_SRIOV_VF_STRIDE, &stride);
+ if (!offset || (total > 1 && !stride))
+ return -EIO;
+
+ pf->vf_total = total;
+ pf->vf_offset = offset;
+ pf->vf_stride = stride;
+ pf->vf_num = pf->vf_total;
+ pf->vf_iw_num = VF_IW_NUM;
+ pf->vf_ow_num = VF_OW_NUM;
+ pf->vf_pos = pos;
+ pf->vf_regs = (void *)pf->regs + VF_ATMU_OFFSET;
+
+ return pf->vf_num;
+}
+
+static int fsl_pci_pf_atmu_init(struct pci_pf_dev *pf)
+{
+ struct pci_ep_dev *ep = pf->pdev->sysdata;
+ struct pci_ep_win win;
+ int i, bits;
+ int win_idx = 3, start_idx = 1, end_idx = 4;
+ u64 sz, reserve_sz = 0, free_sz;
+
+ if (in_be32(&pf->regs->block_rev1) >= PCIE_IP_REV_2_2) {
+ win_idx = 2;
+ start_idx = 0;
+ end_idx = 3;
+ }
+
+ sz = resource_size(&pf->mem_resources[0]) / (pf->vf_total + 1);
+ bits = ilog2(sz);
+ sz = 1ull << bits;
+
+ if (pf->vf_regs) {
+ /* Disable all VF windows */
+ for (i = 0; i < pf->vf_ow_num; i++)
+ out_be32(&pf->vf_regs->vfow[i].powar, 0);
+ for (i = 0; i < pf->vf_iw_num - 1; i++)
+ out_be32(&pf->vf_regs->vfiw[i].piwar, 0);
+
+ /* Setup VF outbound windows*/
+ win.cpu_addr = pf->mem_resources[0].start;
+ win.pci_addr = win.cpu_addr - pf->mem_offset[0];
+ win.size = sz;
+ win.attr = 0;
+ win.idx = 0;
+ fsl_pci_ep_set_vfobwin(ep, &win);
+
+ /* Setup VF MSIX inbound windows*/
+ if (pf->msix_enable) {
+ win.cpu_addr = 0;
+ win.pci_addr = 0;
+ win.size = FSL_PCI_EP_MSIX_IW_SIZE;
+ win.attr = FSL_PCI_MSIX_IW_ATTR |
+ (ilog2(win.size) - 1);
+ win.idx = PCI_EP_MSI_WIN_INDEX;
+ fsl_pci_ep_set_vfibwin(ep, &win);
+ }
+ }
+
+ /* Disable all PF windows (except powar0 since it's ignored) */
+ for (i = 1; i < pf->ow_num; i++)
+ out_be32(&pf->regs->pow[i].powar, 0);
+ for (i = start_idx; i < end_idx; i++)
+ out_be32(&pf->regs->piw[i].piwar, 0);
+
+ /* Setup PF MSIX outbound windows */
+ if (pf->msix_enable) {
+ win.cpu_addr = pf->mem_resources[0].end -
+ FSL_PCI_EP_MSIX_OW_SIZE + 1;
+ win.size = FSL_PCI_EP_MSIX_OW_SIZE;
+ win.attr = 0;
+ win.idx = 0;
+ fsl_pci_ep_set_msixobwin(ep, &win);
+ reserve_sz = FSL_PCI_EP_MSIX_OW_SIZE;
+ }
+
+ /* Setup PF outbound windows */
+ win.cpu_addr = pf->mem_resources[0].start + pf->vf_total * sz;
+ win.pci_addr = win.cpu_addr - pf->mem_offset[0];
+ free_sz = pf->mem_resources[0].end - win.cpu_addr - reserve_sz + 1;
+ if (free_sz < sz) {
+ bits = ilog2(free_sz);
+ sz = 1ull << bits;
+ }
+ win.size = sz;
+ win.attr = 0;
+ win.idx = 1;
+ fsl_pci_ep_set_obwin(ep, &win);
+
+ /* Setup VF MSIX inbound windows*/
+ if (pf->msix_enable) {
+ win.cpu_addr = 0;
+ win.pci_addr = 0;
+ win.size = FSL_PCI_EP_MSIX_IW_SIZE;
+ win.attr = FSL_PCI_MSIX_IW_ATTR |
+ (ilog2(win.size) - 1);
+ win.idx = PCI_EP_MSI_WIN_INDEX;
+ fsl_pci_ep_set_ibwin(ep, &win);
+ }
+
+ return 0;
+}
+
+struct pci_pf_dev *fsl_pci_pf_alloc(struct pci_dev *pdev,
+ struct list_head *pf_list)
+{
+ struct pci_pf_dev *pf;
+
+ if (!pdev->is_physfn)
+ return NULL;
+
+ pf = kzalloc(sizeof(*pf), GFP_KERNEL);
+ if (!pf)
+ return NULL;
+
+ pf->pbus = pdev->bus;
+ pf->pdev = pdev;
+ pf->host = pci_bus_to_host(pdev->bus);
+ pf->idx = pdev->devfn;
+ pf->ow_num = FSL_PCI_EP_OW_NUM;
+ pf->iw_num = FSL_PCI_EP_BAR_NUM;
+
+ spin_lock_init(&pf->lock);
+ INIT_LIST_HEAD(&pf->ep_list);
+
+ spin_lock(&pci_ep_spinlock);
+ list_add_tail(&pf->node, pf_list);
+ spin_unlock(&pci_ep_spinlock);
+
+ return pf;
+}
+
+void fsl_pci_pf_free(struct pci_pf_dev *pf)
+{
+ struct pci_ep_dev *ep, *tmp;
+
+ if (!pf)
+ return;
+ list_for_each_entry_safe(ep, tmp, &pf->ep_list, node)
+ fsl_pci_ep_free(ep);
+
+ if (pf->regs)
+ iounmap(pf->regs);
+
+ spin_lock(&pci_ep_spinlock);
+ list_del(&pf->node);
+ spin_unlock(&pci_ep_spinlock);
+
+ kfree(pf);
+}
+
+static void fsl_pci_pfs_free(struct list_head *pf_list)
+{
+ struct pci_pf_dev *pf, *tmp;
+
+ list_for_each_entry_safe(pf, tmp, pf_list, node)
+ fsl_pci_pf_free(pf);
+}
+
+int fsl_pci_pf_setup(struct pci_bus *bus, int pf_num)
+{
+ struct pci_controller *host;
+ struct pci_pf_dev *pf;
+ struct pci_ep_dev *ep;
+ struct pci_dev *pdev;
+ struct resource rsrc;
+ struct list_head *pf_list;
+ size_t regs_size, mem_size;
+ int pf_idx, pos, i;
+
+ host = pci_bus_to_host(bus);
+ pf_list = host->private_data;
+
+ /* Fetch host bridge registers address */
+ if (of_address_to_resource(host->dn, 0, &rsrc)) {
+ pr_warn("Can't get pci register base!");
+ return -ENOMEM;
+ }
+
+ if (pf_num > 1)
+ regs_size = PCI_EP_PF_OFFSET;
+ else
+ regs_size = resource_size(&rsrc);
+
+ if (resource_size(&rsrc) < (regs_size * pf_num))
+ return -EINVAL;
+
+ for (pf_idx = 0; pf_idx < pf_num; pf_idx++) {
+ pdev = alloc_pci_dev();
+ if (!pdev)
+ goto _err;
+ pdev->bus = bus;
+ pdev->devfn = pf_idx;
+ pdev->is_physfn = 1;
+ pdev->hdr_type = PCI_HEADER_TYPE_NORMAL;
+ pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ if (pos) {
+ pdev->pcie_cap = pos;
+ pdev->cfg_size = 0x1000;
+ } else
+ pdev->cfg_size = 0x100;
+
+ dev_set_name(&pdev->dev, "%04x:%02x:%02x.%d",
+ pci_domain_nr(pdev->bus),
+ pdev->bus->number, PCI_SLOT(pdev->devfn),
+ PCI_FUNC(pdev->devfn));
+
+ if (!bus->self)
+ bus->self = pdev;
+
+ pf = fsl_pci_pf_alloc(pdev, pf_list);
+ if (!pf)
+ goto _err;
+
+ pf->parent = host->parent;
+
+ ep = fsl_pci_ep_alloc(pf, 0);
+
+ ep->pdev = pdev;
+ pdev->sysdata = ep;
+
+ pf->regs_rs.start = rsrc.start + pf->idx * regs_size;
+ pf->regs_rs.end = pf->regs_rs.start + regs_size - 1;
+
+ pf->regs = ioremap(pf->regs_rs.start, regs_size);
+ if (!pf->regs) {
+ pr_err("Unable to map PF%d ccsr regs\n", pf->idx);
+ goto _err;
+ }
+
+ if (pci_find_capability(pf->pdev, PCI_CAP_ID_MSIX))
+ pf->msix_enable = true;
+
+ for (i = 0; i < 3; i++) {
+ mem_size = resource_size(&host->mem_resources[i]);
+ if (!mem_size)
+ continue;
+ mem_size = mem_size / pf_num;
+ pf->mem_resources[i].start =
+ host->mem_resources[i].start +
+ mem_size * pf->idx;
+ pf->mem_resources[i].end =
+ pf->mem_resources[i].start + mem_size - 1;
+ pf->mem_offset[i] = host->mem_offset[i];
+ }
+
+ fsl_pci_pf_cfg_ready(pf);
+ fsl_pci_pf_iov_init(pf);
+ fsl_pci_pf_atmu_init(pf);
+
+ for (i = 1; i <= pf->vf_num; i++)
+ fsl_pci_ep_alloc(pf, i);
+
+ list_for_each_entry(ep, &pf->ep_list, node)
+ fsl_pci_ep_setup(ep);
+ }
+
+ return 0;
+_err:
+ fsl_pci_pfs_free(pf_list);
+ return -EINVAL;
+}
+
+static void pci_process_of_ranges(struct pci_controller *hose,
+ struct device_node *dev)
+{
+ const u32 *ranges;
+ int rlen;
+ int pna = of_n_addr_cells(dev);
+ int np = pna + 5;
+ int memno = 0;
+ u32 pci_space;
+ unsigned long long pci_addr, cpu_addr, pci_next, cpu_next, size;
+ struct resource *res;
+
+ /* Get ranges property */
+ ranges = of_get_property(dev, "ranges", &rlen);
+ if (ranges == NULL)
+ return;
+
+ /* Parse it */
+ while ((rlen -= np * 4) >= 0) {
+ /* Read next ranges element */
+ pci_space = ranges[0];
+ pci_addr = of_read_number(ranges + 1, 2);
+ cpu_addr = of_translate_address(dev, ranges + 3);
+ size = of_read_number(ranges + pna + 3, 2);
+ ranges += np;
+
+ if (cpu_addr == OF_BAD_ADDR || size == 0)
+ continue;
+
+ /* Now consume following elements while they are contiguous */
+ for (; rlen >= np * sizeof(u32);
+ ranges += np, rlen -= np * 4) {
+ if (ranges[0] != pci_space)
+ break;
+ pci_next = of_read_number(ranges + 1, 2);
+ cpu_next = of_translate_address(dev, ranges + 3);
+ if (pci_next != pci_addr + size ||
+ cpu_next != cpu_addr + size)
+ break;
+ size += of_read_number(ranges + pna + 3, 2);
+ }
+
+ /* Act based on address space type */
+ res = NULL;
+ switch ((pci_space >> 24) & 0x3) {
+ case 1: /* PCI IO space */
+ break;
+ case 2: /* PCI Memory space */
+ case 3: /* PCI 64 bits Memory space */
+ /* We support only 3 memory ranges */
+ if (memno >= 3) {
+ pr_info(" --> Skipped (too many) !\n");
+ continue;
+ }
+
+ hose->mem_offset[memno] = cpu_addr - pci_addr;
+
+ /* Build resource */
+ res = &hose->mem_resources[memno++];
+ res->flags = IORESOURCE_MEM;
+ if (pci_space & 0x40000000)
+ res->flags |= IORESOURCE_PREFETCH;
+ res->start = cpu_addr;
+ break;
+ }
+ if (res != NULL) {
+ res->name = dev->full_name;
+ res->end = res->start + size - 1;
+ res->parent = NULL;
+ res->sibling = NULL;
+ res->child = NULL;
+ }
+ }
+}
+
+static struct pci_controller *
+fsl_pci_ep_controller_alloc(struct device_node *dev)
+{
+ struct pci_controller *host;
+ struct list_head *pf_list;
+
+ host = kzalloc(sizeof(*host), GFP_KERNEL);
+ if (!host)
+ return NULL;
+
+ pf_list = kzalloc(sizeof(*pf_list), GFP_KERNEL);
+ if (!pf_list) {
+ kfree(host);
+ return NULL;
+ }
+ INIT_LIST_HEAD(pf_list);
+ host->private_data = pf_list;
+
+ spin_lock(&pci_ep_spinlock);
+ host->global_number = global_phb_number++;
+ list_add_tail(&host->list_node, &pci_ep_controllers);
+ spin_unlock(&pci_ep_spinlock);
+ host->dn = dev;
+
+ return host;
+}
+
+static void fsl_pci_ep_controller_free(struct pci_controller *host)
+{
+ if (host->private_data) {
+ fsl_pci_pfs_free(host->private_data);
+ kfree(host->private_data);
+ }
+
+ if (host->bus)
+ fsl_pci_bus_free(host->bus);
+
+ if (host->ops)
+ fsl_pci_ep_access_free(host);
+
+ spin_lock(&pci_ep_spinlock);
+ list_del(&host->list_node);
+ spin_unlock(&pci_ep_spinlock);
+
+ kfree(host);
+}
+
+static int fsl_pci_ep_controller_probe(struct platform_device *device)
+{
+ struct device_node *dn;
+ struct pci_controller *host;
+ struct resource rsrc;
+ u8 hdr_type;
+ int pf_num;
+ int err;
+
+ dn = device->dev.of_node;
+ if (!of_device_is_available(dn)) {
+ pr_warn("%s: disabled\n", dn->full_name);
+ return -ENODEV;
+ }
+
+ /* Fetch host bridge registers address */
+ if (of_address_to_resource(dn, 0, &rsrc))
+ return -ENOMEM;
+
+ host = fsl_pci_ep_controller_alloc(dn);
+ if (!host)
+ return -ENOMEM;
+
+ host->parent = &device->dev;
+
+ fsl_pci_ep_access_create(host, rsrc.start, rsrc.start + 0x4, 0);
+
+ host->first_busno = host->last_busno = 0;
+
+ host->bus = create_dummy_pci_bus(host, host->ops, 0);
+ if (!host->bus) {
+ err = -ENOMEM;
+ goto _err;
+ }
+
+ pci_bus_read_config_byte(host->bus, 0, PCI_HEADER_TYPE, &hdr_type);
+ if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_NORMAL) {
+ err = -ENODEV;
+ goto _err;
+ }
+
+ if (hdr_type & 0x80)
+ pf_num = MULTI_FUNCTION_NUM;
+ else
+ pf_num = 1;
+
+ pci_process_of_ranges(host, host->dn);
+
+ fsl_pci_pf_setup(host->bus, pf_num);
+
+ return 0;
+_err:
+ fsl_pci_ep_controller_free(host);
+ return err;
+}
+
+static int fsl_pci_ep_controller_remove(struct platform_device *pdev)
+{
+ struct pci_controller *host, *tmp;
+
+ list_for_each_entry_safe(host, tmp, &pci_ep_controllers, list_node) {
+ /*
+ * Because EADC driver has registered private data to the
+ * device drvdata, so we can not register private host
+ * to the device again, and only identify controller
+ * corresponding to platform device via comparing the
+ * device node pointer.
+ */
+ if (host->dn == pdev->dev.of_node)
+ fsl_pci_ep_controller_free(host);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id pci_ep_ids[] = {
+ { .compatible = "fsl,qoriq-pcie-v2.1", },
+ { .compatible = "fsl,qoriq-pcie-v2.2", },
+ { .compatible = "fsl,qoriq-pcie-v2.3", },
+ { .compatible = "fsl,qoriq-pcie-v2.4", },
+ { .compatible = "fsl,qoriq-pcie-v3.0", },
+ {},
+};
+
+static struct platform_driver fsl_pci_ep_driver = {
+ .driver = {
+ .name = "fsl-pci-ep",
+ .of_match_table = pci_ep_ids,
+ },
+ .probe = fsl_pci_ep_controller_probe,
+ .remove = fsl_pci_ep_controller_remove,
+};
+
+static int __init fsl_pci_ep_controller_init(void)
+{
+ int err;
+
+ err = pci_ep_class_init();
+ if (err)
+ return err;
+
+ err = platform_driver_register(&fsl_pci_ep_driver);
+ if (err) {
+ pr_err("Unable to register platform driver\n");
+ pci_ep_class_free();
+ return err;
+ }
+
+ return 0;
+}
+
+static void __exit fsl_pci_ep_controller_exit(void)
+{
+ platform_driver_unregister(&fsl_pci_ep_driver);
+ pci_ep_class_free();
+}
+
+module_init(fsl_pci_ep_controller_init);
+module_exit(fsl_pci_ep_controller_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Minghuan Lian <Minghuan.Lian@freescale.com>");
+MODULE_DESCRIPTION("Freescale PCI EP driver");
diff --git a/drivers/vfio/fsl_pci_ep/fsl_pci_ep.h b/drivers/vfio/fsl_pci_ep/fsl_pci_ep.h
new file mode 100644
index 0000000..c27942b
--- /dev/null
+++ b/drivers/vfio/fsl_pci_ep/fsl_pci_ep.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Minghuan Lian <Minghuan.Lian@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef _FSL_PCI_EP_H
+#define _FSL_PCI_EP_H
+
+#include <linux/fsl_pci_ep_vfio.h>
+
+#define MULTI_FUNCTION_NUM 2
+#define PCI_EP_PF_OFFSET 0x2000
+#define FSL_PCI_EP_BAR_NUM 4
+#define FSL_PCI_EP_OW_NUM 5
+#define FSL_PCI_EP_MSIX_OW_SIZE (4 * 1024) /* 4k */
+#define FSL_PCI_EP_MSIX_IW_SIZE (8 * 1024) /* 8k */
+#define FSL_PCI_MSIX_IW_ATTR 0x80f44000
+
+#define PCI_EP_WIN_INDEX_SHIFT 36
+#define PCI_EP_WIN_INDEX_MASK 0xf
+#define PCI_EP_WIN_TYPE_SHIFT (PCI_EP_WIN_INDEX_SHIFT + 4)
+
+#define PCI_EP_OFFSET_TO_INDEX(off) \
+ (((off) >> PCI_EP_WIN_INDEX_SHIFT) & PCI_EP_WIN_INDEX_MASK)
+#define PCI_EP_OFFSET_TO_TYPE(off) ((off) >> PCI_EP_WIN_TYPE_SHIFT)
+#define PCI_EP_OFFSET_MASK (((u64)(1) << PCI_EP_WIN_INDEX_SHIFT) - 1)
+
+
+struct pci_ep_dev {
+ struct list_head node;
+ struct pci_dev *pdev;
+ struct pci_pf_dev *pf;
+ struct device dev;
+ int idx;
+ int devfn;
+ int type;
+ spinlock_t irqlock;
+ int irq_type;
+ u8 iw_num;
+ u8 ow_num;
+ atomic_t refcnt;
+ int registered;
+};
+
+struct pci_pf_dev {
+ struct list_head node;
+ struct list_head ep_list;
+ struct pci_controller *host;
+ struct pci_bus *pbus;
+ struct pci_dev *pdev;
+ struct device *parent;
+ spinlock_t lock;
+ int idx;
+ struct resource regs_rs;
+ struct ccsr_pci __iomem *regs;
+ u8 iw_num;
+ u8 ow_num;
+ bool msix_enable;
+ resource_size_t mem_offset[3];
+ struct resource mem_resources[3];
+ /* VF info */
+ int vf_pos;
+ u8 vf_enabled;
+ u8 vf_iw_num;
+ u8 vf_ow_num;
+ u16 vf_total; /* total VFs associated with the PF */
+ u16 vf_initial; /* initial VFs */
+ u16 vf_num; /* number of VFs available */
+ u16 vf_offset; /* first VF Routing ID offset */
+ u16 vf_stride; /* following VF stride */
+ struct vf_atmu_regs __iomem *vf_regs;
+};
+
+int fsl_pci_ep_get_win(struct pci_ep_dev *ep, struct pci_ep_win *win);
+int fsl_pci_ep_set_win(struct pci_ep_dev *ep, struct pci_ep_win *win);
+int fsl_pci_ep_vfio_init(struct pci_ep_dev *ep);
+void fsl_pci_ep_vfio_remove(struct pci_ep_dev *ep);
+
+#endif
diff --git a/drivers/vfio/fsl_pci_ep/fsl_pci_ep_vfio.c b/drivers/vfio/fsl_pci_ep/fsl_pci_ep_vfio.c
new file mode 100644
index 0000000..1218f2d
--- /dev/null
+++ b/drivers/vfio/fsl_pci_ep/fsl_pci_ep_vfio.c
@@ -0,0 +1,372 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Minghuan Lian <Minghuan.Lian@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/eventfd.h>
+#include <linux/interrupt.h>
+#include <linux/iommu.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/uaccess.h>
+#include <linux/vfio.h>
+
+#include "fsl_pci_ep.h"
+
+static void fsl_pci_ep_win_set_offset(struct pci_ep_win *win)
+{
+ win->offset = (u64)win->type << PCI_EP_WIN_TYPE_SHIFT |
+ (u64)win->idx << PCI_EP_WIN_INDEX_SHIFT;
+}
+
+static int fsl_pci_ep_win_is_enbled(struct pci_ep_win *win)
+{
+ return win->attr >> 31;
+}
+
+static void fsl_pci_ep_vfio_release(void *device_data)
+{
+ struct pci_ep_dev *ep = device_data;
+
+ atomic_inc(&ep->refcnt);
+
+ module_put(THIS_MODULE);
+}
+
+static int fsl_pci_ep_vfio_open(void *device_data)
+{
+ struct pci_ep_dev *ep = device_data;
+
+ if (!try_module_get(THIS_MODULE))
+ return -ENODEV;
+
+ if (!atomic_dec_and_test(&ep->refcnt)) {
+ pr_err("%s: failing non-exclusive open()\n",
+ dev_name(&ep->dev));
+ atomic_inc(&ep->refcnt);
+ module_put(THIS_MODULE);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static long fsl_pci_ep_vfio_ioctl(void *device_data,
+ unsigned int cmd, unsigned long arg)
+{
+ struct pci_ep_dev *ep = device_data;
+
+ if (cmd == VFIO_DEVICE_GET_INFO) {
+ struct pci_ep_info info;
+
+ info.iw_num = ep->iw_num;
+ info.ow_num = ep->ow_num;
+ info.type = ep->type;
+ info.pf_idx = ep->pf->idx;
+ info.vf_idx = ep->idx;
+ info.msix_enable = ep->pf->msix_enable;
+ if (ep->type == PCI_EP_TYPE_PF) {
+ info.vf_iw_num = ep->pf->vf_iw_num;
+ info.vf_ow_num = ep->pf->vf_iw_num;
+ } else {
+ info.vf_iw_num = 0;
+ info.vf_ow_num = 0;
+ }
+
+ return copy_to_user((void __user *)arg, &info, sizeof(info));
+ } else if (cmd == VFIO_DEVICE_GET_WIN_INFO) {
+ struct pci_ep_win win;
+
+ if (copy_from_user(&win, (void __user *)arg, sizeof(win)))
+ return -EFAULT;
+
+ fsl_pci_ep_get_win(ep, &win);
+ fsl_pci_ep_win_set_offset(&win);
+ return copy_to_user((void __user *)arg, &win, sizeof(win));
+ } else if (cmd == VFIO_DEVICE_SET_WIN_INFO) {
+ struct pci_ep_win win;
+
+ if (copy_from_user(&win, (void __user *)arg, sizeof(win)))
+ return -EFAULT;
+
+ fsl_pci_ep_set_win(ep, &win);
+ fsl_pci_ep_get_win(ep, &win);
+ return copy_to_user((void __user *)arg, &win, sizeof(win));
+ }
+
+ return -ENOTTY;
+}
+
+static ssize_t fsl_pci_ep_config_rw(struct pci_ep_dev *ep, char __user *buf,
+ size_t count, loff_t *ppos, bool iswrite)
+{
+ struct pci_dev *pdev = ep->pdev;
+ size_t done = 0;
+ int ret = 0;
+ loff_t pos = *ppos;
+
+ pos &= PCI_EP_OFFSET_MASK;
+
+ while (count) {
+ if (count >= 4 && !(pos % 4)) {
+ u32 data;
+ ret = 4;
+ pci_read_config_dword(pdev, pos, &data);
+ if (copy_to_user(buf, &data, ret))
+ return -EFAULT;
+ } else if (count >= 2 && !(pos % 2)) {
+ u16 data;
+ ret = 2;
+ pci_read_config_word(pdev, pos, &data);
+ if (copy_to_user(buf, &data, ret))
+ return -EFAULT;
+ } else {
+ u8 data;
+ ret = 1;
+ pci_read_config_byte(pdev, pos, &data);
+ if (copy_to_user(buf, &data, ret))
+ return -EFAULT;
+ }
+
+ if (ret < 0)
+ return ret;
+
+ count -= ret;
+ done += ret;
+ buf += ret;
+ pos += ret;
+ }
+
+ *ppos += done;
+
+ return done;
+}
+
+static ssize_t fsl_pci_ep_regs_rw(struct pci_ep_dev *ep, char __user *buf,
+ size_t count, loff_t *ppos, bool iswrite)
+{
+ struct pci_pf_dev *pf = ep->pf;
+ u32 data;
+ loff_t pos = *ppos;
+
+ /* only PF can r/w regs */
+ if (ep->type == PCI_EP_TYPE_VF)
+ return -EINVAL;
+
+ pos &= PCI_EP_OFFSET_MASK;
+
+ if (pos > resource_size(&pf->regs_rs))
+ return -EINVAL;
+
+ if (count != 4)
+ return -EINVAL;
+
+ if (iswrite) {
+ if (copy_from_user(&data, buf, count))
+ return -EFAULT;
+ out_be32((u32 *)((u8 *)pf->regs + pos), data);
+ } else {
+ data = in_be32((u32 *)((u8 *)pf->regs + pos));
+ if (copy_to_user(buf, &data, count))
+ return -EFAULT;
+ }
+
+ return count;
+}
+
+static ssize_t fsl_pci_ep_win_rw(struct pci_ep_dev *ep, char __user *buf,
+ size_t count, loff_t *ppos, bool iswrite)
+{
+ loff_t pos = *ppos & PCI_EP_OFFSET_MASK;
+ struct pci_ep_win win;
+ void __iomem *mem;
+ int ret;
+
+ win.idx = PCI_EP_OFFSET_TO_INDEX(*ppos);
+ win.type = PCI_EP_OFFSET_TO_TYPE(*ppos);
+
+ if (fsl_pci_ep_get_win(ep, &win))
+ return -EINVAL;
+
+ if (!fsl_pci_ep_win_is_enbled(&win)) {
+ pr_err("win%d-%d is not enabled\n", win.type, win.idx);
+ return -EINVAL;
+ }
+
+ if (pos > win.size)
+ return -EINVAL;
+
+ count = min(count, (size_t)(win.size - pos));
+
+ mem = ioremap(win.cpu_addr + pos, count);
+
+ if (iswrite)
+ ret = copy_from_user(mem, buf, count);
+ else
+ ret = copy_to_user(buf, mem, count);
+
+ iounmap(mem);
+
+ if (ret)
+ return -EFAULT;
+
+ return count;
+}
+
+static ssize_t fsl_pci_ep_rw(void *device_data, char __user *buf,
+ size_t count, loff_t *ppos, bool iswrite)
+{
+ int type = PCI_EP_OFFSET_TO_TYPE(*ppos);
+ struct pci_ep_dev *ep = device_data;
+
+ switch (type) {
+ case PCI_EP_REGION_IBWIN:
+ if (iswrite)
+ return -EINVAL;
+ return fsl_pci_ep_win_rw(ep, buf, count, ppos, false);
+
+ case PCI_EP_REGION_OBWIN:
+ return fsl_pci_ep_win_rw(ep, buf, count, ppos, iswrite);
+
+ case PCI_EP_REGION_REGS:
+ return fsl_pci_ep_regs_rw(ep, buf, count, ppos, iswrite);
+
+ case PCI_EP_REGION_CONFIG:
+ if (iswrite)
+ return -EINVAL;
+ return fsl_pci_ep_config_rw(ep, buf, count, ppos, iswrite);
+ }
+
+ return -EINVAL;
+}
+
+static ssize_t fsl_pci_ep_vfio_read(void *device_data,
+ char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ if (!count)
+ return 0;
+
+ return fsl_pci_ep_rw(device_data, buf, count, ppos, false);
+}
+
+static ssize_t fsl_pci_ep_vfio_write(void *device_data,
+ const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ if (!count)
+ return 0;
+
+ return fsl_pci_ep_rw(device_data, (char __user *)buf,
+ count, ppos, true);
+}
+
+static int fsl_pci_ep_vfio_mmap(void *device_data,
+ struct vm_area_struct *vma)
+{
+ struct pci_ep_dev *ep = device_data;
+ u64 req_len, pgoff, req_start;
+ struct pci_ep_win win;
+
+ win.idx = PCI_EP_OFFSET_TO_INDEX((u64)vma->vm_pgoff << PAGE_SHIFT);
+ win.type = PCI_EP_OFFSET_TO_TYPE((u64)vma->vm_pgoff << PAGE_SHIFT);
+
+ fsl_pci_ep_get_win(ep, &win);
+
+ if ((win.size == 0) || !fsl_pci_ep_win_is_enbled(&win)) {
+ pr_err("win%d-%d is not enabled\n", win.type, win.idx);
+ return -EINVAL;
+ }
+
+ if (vma->vm_end < vma->vm_start)
+ return -EINVAL;
+
+ if ((vma->vm_flags & VM_SHARED) == 0)
+ return -EINVAL;
+
+ req_len = vma->vm_end - vma->vm_start;
+
+ pgoff = vma->vm_pgoff &
+ ((1U << (PCI_EP_WIN_INDEX_SHIFT - PAGE_SHIFT)) - 1);
+
+ req_start = pgoff << PAGE_SHIFT;
+ if (req_start + req_len > win.size)
+ return -EINVAL;
+
+ vma->vm_private_data = ep;
+ vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_pgoff = (win.cpu_addr >> PAGE_SHIFT) + pgoff;
+
+ return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ req_len, vma->vm_page_prot);
+}
+
+static const struct vfio_device_ops vfio_pci_ops = {
+ .name = "fsl-pci-ep-vfio",
+ .open = fsl_pci_ep_vfio_open,
+ .release = fsl_pci_ep_vfio_release,
+ .ioctl = fsl_pci_ep_vfio_ioctl,
+ .read = fsl_pci_ep_vfio_read,
+ .write = fsl_pci_ep_vfio_write,
+ .mmap = fsl_pci_ep_vfio_mmap,
+};
+
+int fsl_pci_ep_vfio_init(struct pci_ep_dev *ep)
+{
+ struct iommu_group *group;
+ int ret;
+
+ group = iommu_group_get(&ep->dev);
+ if (!group) {
+ group = iommu_group_alloc();
+ if (IS_ERR(group))
+ return PTR_ERR(group);
+ }
+
+ ret = iommu_group_add_device(group, &ep->dev);
+ if (ret)
+ pr_err("failed to add device %s to iommu group\n",
+ dev_name(&ep->dev));
+
+ iommu_group_put(group);
+
+ ret = vfio_add_group_dev(&ep->dev, &vfio_pci_ops, ep);
+ if (ret) {
+ pr_err("failed to add device %s to vfio system\n",
+ dev_name(&ep->dev));
+ iommu_group_put(group);
+ kfree(ep);
+ }
+
+ atomic_set(&ep->refcnt, 1);
+
+ return ret;
+}
+
+void fsl_pci_ep_vfio_remove(struct pci_ep_dev *ep)
+{
+ if (!atomic_dec_and_test(&ep->refcnt))
+ return;
+
+ vfio_del_group_dev(&ep->dev);
+
+ return;
+}
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 1eab4ac..b23e9ff 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -432,7 +432,9 @@ static struct vfio_device *vfio_group_get_device(struct vfio_group *group,
* a device. It's not always practical to leave a device within a group
* driverless as it could get re-bound to something unsafe.
*/
-static const char * const vfio_driver_whitelist[] = { "pci-stub", "pcieport" };
+static const char * const vfio_driver_whitelist[] = {
+ "pci-stub", "pcieport", "fsl-pci-ep"
+};
static bool vfio_whitelisted_driver(struct device_driver *drv)
{
diff --git a/drivers/vfio/vfio_iommu_dummy.c b/drivers/vfio/vfio_iommu_dummy.c
new file mode 100644
index 0000000..865045a
--- /dev/null
+++ b/drivers/vfio/vfio_iommu_dummy.c
@@ -0,0 +1,706 @@
+/*
+ * VFIO: IOMMU DMA mapping support for systems without IOMMU
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Varun Sethi <varun.sethi@freescale.com>
+ *
+ * This file is derived from driver/vfio/vfio_iommu_type1.c and
+ * driver/vfio/vfio_iommu_fsl_pamu.c
+ * This driver is primarily targeted for providing direct device assignment
+ * on platforms that don't have a hardware IOMMU. The driver primarily
+ * pins the pages corresponding to the guest memory. The driver is enabled
+ * via /sys/kernel/vfio_iommu_dummy/enable_iommu_dummy attribute.
+ *
+ */
+
+#include <linux/compat.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/iommu.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/pci.h> /* pci_bus_type */
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/vfio.h>
+#include <linux/workqueue.h>
+#include <linux/hugetlb.h>
+
+struct vfio_iommu {
+ struct mutex lock;
+ struct list_head dma_list;
+ struct list_head group_list;
+};
+
+struct vfio_dma {
+ struct list_head next;
+ dma_addr_t iova; /* Device address */
+ unsigned long vaddr; /* Process virtual addr */
+ long npage; /* Number of pages */
+ int prot; /* IOMMU_READ/WRITE */
+};
+
+struct vfio_group {
+ struct iommu_group *iommu_group;
+ struct list_head next;
+};
+
+#define NPAGE_TO_SIZE(npage) ((size_t)(npage) << PAGE_SHIFT)
+
+struct vwork {
+ struct mm_struct *mm;
+ long npage;
+ struct work_struct work;
+};
+
+static int enable_iommu_dummy;
+
+/* delayed decrement/increment for locked_vm */
+static void vfio_lock_acct_bg(struct work_struct *work)
+{
+ struct vwork *vwork = container_of(work, struct vwork, work);
+ struct mm_struct *mm;
+
+ mm = vwork->mm;
+ down_write(&mm->mmap_sem);
+ mm->locked_vm += vwork->npage;
+ up_write(&mm->mmap_sem);
+ mmput(mm);
+ kfree(vwork);
+}
+
+static void vfio_lock_acct(long npage)
+{
+ struct vwork *vwork;
+ struct mm_struct *mm;
+
+ if (!current->mm)
+ return; /* process exited */
+
+ if (down_write_trylock(&current->mm->mmap_sem)) {
+ current->mm->locked_vm += npage;
+ up_write(&current->mm->mmap_sem);
+ return;
+ }
+
+ /*
+ * Couldn't get mmap_sem lock, so must setup to update
+ * mm->locked_vm later. If locked_vm were atomic, we
+ * wouldn't need this silliness
+ */
+ vwork = kmalloc(sizeof(struct vwork), GFP_KERNEL);
+ if (!vwork)
+ return;
+ mm = get_task_mm(current);
+ if (!mm) {
+ kfree(vwork);
+ return;
+ }
+ INIT_WORK(&vwork->work, vfio_lock_acct_bg);
+ vwork->mm = mm;
+ vwork->npage = npage;
+ schedule_work(&vwork->work);
+}
+
+/*
+ * Some mappings aren't backed by a struct page, for example an mmap'd
+ * MMIO range for our own or another device. These use a different
+ * pfn conversion and shouldn't be tracked as locked pages.
+ */
+static bool is_invalid_reserved_pfn(unsigned long pfn)
+{
+ if (pfn_valid(pfn)) {
+ bool reserved;
+ struct page *tail = pfn_to_page(pfn);
+ struct page *head = compound_trans_head(tail);
+ reserved = !!(PageReserved(head));
+ if (head != tail) {
+ /*
+ * "head" is not a dangling pointer
+ * (compound_trans_head takes care of that)
+ * but the hugepage may have been split
+ * from under us (and we may not hold a
+ * reference count on the head page so it can
+ * be reused before we run PageReferenced), so
+ * we've to check PageTail before returning
+ * what we just read.
+ */
+ smp_rmb();
+ if (PageTail(tail))
+ return reserved;
+ }
+ return PageReserved(tail);
+ }
+
+ return true;
+}
+
+static int put_pfn(unsigned long pfn, int prot)
+{
+ if (!is_invalid_reserved_pfn(pfn)) {
+ struct page *page = pfn_to_page(pfn);
+ if (prot & IOMMU_WRITE)
+ SetPageDirty(page);
+ put_page(page);
+ return 1;
+ }
+ return 0;
+}
+
+static int vaddr_get_pfn(unsigned long vaddr, int prot, unsigned int nr_pages)
+{
+ struct page **pages;
+ int i, ret;
+ long locked = 0;
+
+ pages = kzalloc(sizeof(*pages) * nr_pages, GFP_KERNEL | __GFP_ZERO);
+ ret = get_user_pages_fast(vaddr, nr_pages, !!(prot & IOMMU_WRITE), pages);
+ if (ret != nr_pages)
+ goto error;
+
+ /* All Pages should be contiguous */
+ for (i = 1; i < nr_pages; i++) {
+ if (page_to_pfn(pages[i]) != page_to_pfn(pages[i - 1]) + 1)
+ goto error;
+ if (!is_invalid_reserved_pfn(page_to_pfn(pages[i])))
+ locked++;
+ }
+
+ vfio_lock_acct(locked);
+
+ kfree(pages);
+ return 0;
+error:
+ for (i = 0; i < nr_pages; i++)
+ if (pages[i])
+ put_page(pages[i]);
+ kfree(pages);
+ return -EFAULT;
+}
+
+/* Unmap DMA region */
+static long __vfio_dma_do_unmap(struct vfio_iommu *iommu, dma_addr_t iova,
+ long npage, int prot)
+{
+ long unlocked = 0;
+ unsigned long size;
+ unsigned long pfn;
+ int i;
+
+ /* currently we support at most one huge page mapping */
+ size = npage << PAGE_SHIFT;
+ /* Release the pinned pages */
+ /* one is to one mapping iova = host physical*/
+ pfn = iova >> PAGE_SHIFT;
+ if (pfn) {
+ for (i = 0; i < npage; i++, pfn++)
+ unlocked += put_pfn(pfn, prot);
+ }
+
+
+ return unlocked;
+}
+
+static void vfio_dma_unmap(struct vfio_iommu *iommu, dma_addr_t iova,
+ long npage, int prot)
+{
+ long unlocked;
+
+ unlocked = __vfio_dma_do_unmap(iommu, iova, npage, prot);
+ vfio_lock_acct(-unlocked);
+}
+
+static inline bool ranges_overlap(dma_addr_t start1, size_t size1,
+ dma_addr_t start2, size_t size2)
+{
+ if (start1 < start2)
+ return (start2 - start1 < size1);
+ else if (start2 < start1)
+ return (start1 - start2 < size2);
+ return (size1 > 0 && size2 > 0);
+}
+
+static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu,
+ dma_addr_t start, size_t size)
+{
+ struct vfio_dma *dma;
+
+ list_for_each_entry(dma, &iommu->dma_list, next) {
+ if (ranges_overlap(dma->iova, NPAGE_TO_SIZE(dma->npage),
+ start, size))
+ return dma;
+ }
+ return NULL;
+}
+
+static long vfio_remove_dma_overlap(struct vfio_iommu *iommu, dma_addr_t start,
+ size_t size, struct vfio_dma *dma)
+{
+ struct vfio_dma *split;
+ long npage_lo, npage_hi;
+
+ /* Existing dma region is completely covered, unmap all */
+ if (start <= dma->iova &&
+ start + size >= dma->iova + NPAGE_TO_SIZE(dma->npage)) {
+ vfio_dma_unmap(iommu, dma->iova, dma->npage, dma->prot);
+ list_del(&dma->next);
+ npage_lo = dma->npage;
+ kfree(dma);
+ return npage_lo;
+ }
+
+ /* Overlap low address of existing range */
+ if (start <= dma->iova) {
+ size_t overlap;
+
+ overlap = start + size - dma->iova;
+ npage_lo = overlap >> PAGE_SHIFT;
+
+ vfio_dma_unmap(iommu, dma->iova, npage_lo, dma->prot);
+ dma->iova += overlap;
+ dma->vaddr += overlap;
+ dma->npage -= npage_lo;
+ return npage_lo;
+ }
+
+ /* Overlap high address of existing range */
+ if (start + size >= dma->iova + NPAGE_TO_SIZE(dma->npage)) {
+ size_t overlap;
+
+ overlap = dma->iova + NPAGE_TO_SIZE(dma->npage) - start;
+ npage_hi = overlap >> PAGE_SHIFT;
+
+ vfio_dma_unmap(iommu, start, npage_hi, dma->prot);
+ dma->npage -= npage_hi;
+ return npage_hi;
+ }
+
+ /* Split existing */
+ npage_lo = (start - dma->iova) >> PAGE_SHIFT;
+ npage_hi = dma->npage - (size >> PAGE_SHIFT) - npage_lo;
+
+ split = kzalloc(sizeof(*split), GFP_KERNEL);
+ if (!split)
+ return -ENOMEM;
+
+ vfio_dma_unmap(iommu, start, size >> PAGE_SHIFT, dma->prot);
+
+ dma->npage = npage_lo;
+
+ split->npage = npage_hi;
+ split->iova = start + size;
+ split->vaddr = dma->vaddr + NPAGE_TO_SIZE(npage_lo) + size;
+ split->prot = dma->prot;
+ list_add(&split->next, &iommu->dma_list);
+ return size >> PAGE_SHIFT;
+}
+
+/* Map DMA region */
+static int __vfio_dma_map(struct vfio_iommu *iommu, dma_addr_t iova,
+ unsigned long vaddr, long npage, int prot)
+{
+ int ret;
+
+ /*
+ * XXX We break mappings into pages and use get_user_pages_fast to
+ * pin the pages in memory. It's been suggested that mlock might
+ * provide a more efficient mechanism, but nothing prevents the
+ * user from munlocking the pages, which could then allow the user
+ * access to random host memory. We also have no guarantee from the
+ * IOMMU API that the iommu driver can unmap sub-pages of previous
+ * mappings. This means we might lose an entire range if a single
+ * page within it is unmapped. Single page mappings are inefficient,
+ * but provide the most flexibility for now.
+ */
+ ret = vaddr_get_pfn(vaddr, prot, npage);
+ if (ret) {
+ pr_err("%s unable to map vaddr = %lx\n",
+ __func__, vaddr);
+ __vfio_dma_do_unmap(iommu, iova, npage, prot);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int vfio_dma_do_map(struct vfio_iommu *iommu,
+ struct vfio_iommu_type1_dma_map *map)
+{
+ struct vfio_dma *dma, *pdma = NULL;
+ dma_addr_t iova = map->iova;
+ unsigned long locked, lock_limit, vaddr = map->vaddr;
+ size_t size = map->size;
+ int ret = 0, prot = 0;
+ long npage;
+
+ /* READ/WRITE from device perspective */
+ if (map->flags & VFIO_DMA_MAP_FLAG_WRITE)
+ prot |= IOMMU_WRITE;
+ if (map->flags & VFIO_DMA_MAP_FLAG_READ)
+ prot |= IOMMU_READ;
+
+ if (!prot)
+ return -EINVAL; /* No READ/WRITE? */
+
+ /* Don't allow IOVA wrap */
+ if (iova + size && iova + size < iova)
+ return -EINVAL;
+
+ /* Don't allow virtual address wrap */
+ if (vaddr + size && vaddr + size < vaddr)
+ return -EINVAL;
+
+ npage = size >> PAGE_SHIFT;
+ if (!npage)
+ return -EINVAL;
+
+ mutex_lock(&iommu->lock);
+
+ if (vfio_find_dma(iommu, iova, size)) {
+ ret = -EBUSY;
+ goto out_lock;
+ }
+
+ /* account for locked pages */
+ locked = current->mm->locked_vm + npage;
+ lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
+ if (locked > lock_limit && !capable(CAP_IPC_LOCK)) {
+ pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n",
+ __func__, rlimit(RLIMIT_MEMLOCK));
+ ret = -ENOMEM;
+ goto out_lock;
+ }
+
+ ret = __vfio_dma_map(iommu, iova, vaddr, npage, prot);
+ if (ret)
+ goto out_lock;
+
+ /* Check if we about a region below - nothing below 0 */
+ if (iova) {
+ dma = vfio_find_dma(iommu, iova - 1, 1);
+ if (dma && dma->prot == prot &&
+ dma->vaddr + NPAGE_TO_SIZE(dma->npage) == vaddr) {
+
+ dma->npage += npage;
+ iova = dma->iova;
+ vaddr = dma->vaddr;
+ npage = dma->npage;
+ size = NPAGE_TO_SIZE(npage);
+
+ pdma = dma;
+ }
+ }
+
+ /* Check if we abut a region above - nothing above ~0 + 1 */
+ if (iova + size) {
+ dma = vfio_find_dma(iommu, iova + size, 1);
+ if (dma && dma->prot == prot &&
+ dma->vaddr == vaddr + size) {
+
+ dma->npage += npage;
+ dma->iova = iova;
+ dma->vaddr = vaddr;
+
+ /*
+ * If merged above and below, remove previously
+ * merged entry. New entry covers it.
+ */
+ if (pdma) {
+ list_del(&pdma->next);
+ kfree(pdma);
+ }
+ pdma = dma;
+ }
+ }
+
+ /* Isolated, new region */
+ if (!pdma) {
+ dma = kzalloc(sizeof(*dma), GFP_KERNEL);
+ if (!dma) {
+ ret = -ENOMEM;
+ vfio_dma_unmap(iommu, iova, npage, prot);
+ goto out_lock;
+ }
+
+ dma->npage = npage;
+ dma->iova = iova;
+ dma->vaddr = vaddr;
+ dma->prot = prot;
+ list_add(&dma->next, &iommu->dma_list);
+ }
+
+out_lock:
+ mutex_unlock(&iommu->lock);
+ return ret;
+}
+
+static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
+ struct vfio_iommu_type1_dma_unmap *unmap)
+{
+ long ret = 0, npage = unmap->size >> PAGE_SHIFT;
+ struct vfio_dma *dma, *tmp;
+
+ mutex_lock(&iommu->lock);
+
+ list_for_each_entry_safe(dma, tmp, &iommu->dma_list, next) {
+ if (ranges_overlap(dma->iova, NPAGE_TO_SIZE(dma->npage),
+ unmap->iova, unmap->size)) {
+ ret = vfio_remove_dma_overlap(iommu, unmap->iova,
+ unmap->size, dma);
+ if (ret > 0)
+ npage -= ret;
+ if (ret < 0 || npage == 0)
+ break;
+ }
+ }
+
+ mutex_unlock(&iommu->lock);
+ return ret > 0 ? 0 : (int)ret;
+}
+
+static void *vfio_iommu_dummy_open(unsigned long arg)
+{
+ struct vfio_iommu *iommu;
+
+ if (arg != VFIO_IOMMU_DUMMY)
+ return ERR_PTR(-EINVAL);
+
+ iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
+ if (!iommu)
+ return ERR_PTR(-ENOMEM);
+
+ INIT_LIST_HEAD(&iommu->group_list);
+ INIT_LIST_HEAD(&iommu->dma_list);
+ mutex_init(&iommu->lock);
+
+ return iommu;
+}
+
+static void vfio_iommu_dummy_release(void *iommu_data)
+{
+ struct vfio_iommu *iommu = iommu_data;
+ struct vfio_group *group, *group_tmp;
+ struct vfio_dma *dma, *dma_tmp;
+
+ list_for_each_entry_safe(group, group_tmp, &iommu->group_list, next) {
+ list_del(&group->next);
+ kfree(group);
+ }
+
+ list_for_each_entry_safe(dma, dma_tmp, &iommu->dma_list, next) {
+ vfio_dma_unmap(iommu, dma->iova, dma->npage, dma->prot);
+ list_del(&dma->next);
+ kfree(dma);
+ }
+
+ kfree(iommu);
+}
+
+static long vfio_iommu_dummy_ioctl(void *iommu_data,
+ unsigned int cmd, unsigned long arg)
+{
+ struct vfio_iommu *iommu = iommu_data;
+ unsigned long minsz;
+
+ if (cmd == VFIO_CHECK_EXTENSION) {
+ switch (arg) {
+ case VFIO_IOMMU_DUMMY:
+ return 1;
+ default:
+ return 0;
+ }
+ } else if (cmd == VFIO_IOMMU_MAP_DMA) {
+ struct vfio_iommu_type1_dma_map map;
+ uint32_t mask = VFIO_DMA_MAP_FLAG_READ |
+ VFIO_DMA_MAP_FLAG_WRITE;
+
+ minsz = offsetofend(struct vfio_iommu_type1_dma_map, size);
+
+ if (copy_from_user(&map, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (map.argsz < minsz || map.flags & ~mask)
+ return -EINVAL;
+
+ return vfio_dma_do_map(iommu, &map);
+
+ } else if (cmd == VFIO_IOMMU_UNMAP_DMA) {
+ struct vfio_iommu_type1_dma_unmap unmap;
+
+ minsz = offsetofend(struct vfio_iommu_type1_dma_unmap, size);
+
+ if (copy_from_user(&unmap, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (unmap.argsz < minsz || unmap.flags)
+ return -EINVAL;
+
+ return vfio_dma_do_unmap(iommu, &unmap);
+ }
+
+ return -ENOTTY;
+}
+
+static int vfio_iommu_dummy_attach_group(void *iommu_data,
+ struct iommu_group *iommu_group)
+{
+ struct vfio_iommu *iommu = iommu_data;
+ struct vfio_group *group, *tmp;
+
+ group = kzalloc(sizeof(*group), GFP_KERNEL);
+ if (!group)
+ return -ENOMEM;
+
+ mutex_lock(&iommu->lock);
+
+ list_for_each_entry(tmp, &iommu->group_list, next) {
+ if (tmp->iommu_group == iommu_group) {
+ mutex_unlock(&iommu->lock);
+ kfree(group);
+ return -EINVAL;
+ }
+ }
+
+ group->iommu_group = iommu_group;
+ list_add(&group->next, &iommu->group_list);
+
+ mutex_unlock(&iommu->lock);
+
+ return 0;
+}
+
+static void vfio_iommu_dummy_detach_group(void *iommu_data,
+ struct iommu_group *iommu_group)
+{
+ struct vfio_iommu *iommu = iommu_data;
+ struct vfio_group *group;
+
+ mutex_lock(&iommu->lock);
+
+ list_for_each_entry(group, &iommu->group_list, next) {
+ if (group->iommu_group == iommu_group) {
+ list_del(&group->next);
+ kfree(group);
+ break;
+ }
+ }
+
+ mutex_unlock(&iommu->lock);
+
+}
+
+static const struct vfio_iommu_driver_ops vfio_iommu_driver_ops_dummy = {
+ .name = "vfio-iommu-dummy",
+ .owner = THIS_MODULE,
+ .open = vfio_iommu_dummy_open,
+ .release = vfio_iommu_dummy_release,
+ .ioctl = vfio_iommu_dummy_ioctl,
+ .attach_group = vfio_iommu_dummy_attach_group,
+ .detach_group = vfio_iommu_dummy_detach_group,
+};
+
+static int iommu_dummy_add_device(struct device *dev)
+{
+ struct iommu_group *group;
+ int ret;
+
+ group = iommu_group_get(dev);
+ if (!group) {
+ group = iommu_group_alloc();
+ if (IS_ERR(group))
+ return PTR_ERR(group);
+ }
+
+ ret = iommu_group_add_device(group, dev);
+ iommu_group_put(group);
+
+ return ret;
+}
+
+static struct iommu_ops iommu_dummy_ops = {
+ .add_device = iommu_dummy_add_device,
+};
+
+static ssize_t enable_iommu_dummy_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", enable_iommu_dummy);
+}
+
+static ssize_t enable_iommu_dummy_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ int val;
+
+ sscanf(buf, "%du", &val);
+
+ if (!enable_iommu_dummy && val) {
+ pr_warn("Enabling vfio_iommu_dummy driver, can't be disabled\n");
+ bus_set_iommu(&pci_bus_type, &iommu_dummy_ops);
+ vfio_register_iommu_driver(&vfio_iommu_driver_ops_dummy);
+ enable_iommu_dummy = 1;
+ }
+
+ return count;
+}
+
+static struct kobj_attribute enable_iommu_dummy_attribute =
+ __ATTR(enable_iommu_dummy, 0666, enable_iommu_dummy_show, enable_iommu_dummy_store);
+
+static struct attribute *attrs[] = {
+ &enable_iommu_dummy_attribute.attr,
+ NULL,
+};
+
+static struct attribute_group attr_group = {
+ .attrs = attrs,
+};
+
+static struct kobject *vfio_iommu_dummy_kobj;
+
+static int __init vfio_iommu_dummy_init(void)
+{
+ int retval;
+
+ vfio_iommu_dummy_kobj = kobject_create_and_add("vfio_iommu_dummy", kernel_kobj);
+ if (!vfio_iommu_dummy_kobj)
+ return -ENOMEM;
+
+ /* Create the files associated with vfio_iommu_dummy kobject */
+ retval = sysfs_create_group(vfio_iommu_dummy_kobj, &attr_group);
+ if (retval)
+ kobject_put(vfio_iommu_dummy_kobj);
+
+ return retval;
+}
+
+static void __exit vfio_iommu_dummy_cleanup(void)
+{
+ if (enable_iommu_dummy)
+ vfio_unregister_iommu_driver(&vfio_iommu_driver_ops_dummy);
+
+ kobject_put(vfio_iommu_dummy_kobj);
+}
+
+module_init(vfio_iommu_dummy_init);
+module_exit(vfio_iommu_dummy_cleanup);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Varun Sethi <Varun.Sethi@freescale.com>");
+MODULE_DESCRIPTION("Dummy IOMMU driver for VFIO");
diff --git a/drivers/vfio/vfio_iommu_fsl_pamu.c b/drivers/vfio/vfio_iommu_fsl_pamu.c
new file mode 100644
index 0000000..2672e15
--- /dev/null
+++ b/drivers/vfio/vfio_iommu_fsl_pamu.c
@@ -0,0 +1,1025 @@
+/*
+ * VFIO: IOMMU DMA mapping support for FSL PAMU IOMMU
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright (C) 2013 Freescale Semiconductor, Inc.
+ *
+ * Author: Bharat Bhushan <bharat.bhushan@freescale.com>
+ *
+ * This file is derived from driver/vfio/vfio_iommu_type1.c
+ *
+ * The Freescale PAMU is an aperture-based IOMMU with the following
+ * characteristics. Each device has an entry in a table in memory
+ * describing the iova->phys mapping. The mapping has:
+ * -an overall aperture that is power of 2 sized, and has a start iova that
+ * is naturally aligned
+ * -has 1 or more windows within the aperture
+ * -number of windows must be power of 2, max is 256
+ * -size of each window is determined by aperture size / # of windows
+ * -iova of each window is determined by aperture start iova / # of windows
+ * -the mapped region in each window can be different than
+ * the window size...mapping must power of 2
+ * -physical address of the mapping must be naturally aligned
+ * with the mapping size
+ */
+
+#include <linux/compat.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/iommu.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/pci.h> /* pci_bus_type */
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/vfio.h>
+#include <linux/workqueue.h>
+#include <linux/hugetlb.h>
+#include <linux/msi.h>
+#include <asm/fsl_pamu_stash.h>
+
+#define DRIVER_VERSION "0.1"
+#define DRIVER_AUTHOR "Bharat Bhushan <bharat.bhushan@freescale.com>"
+#define DRIVER_DESC "FSL PAMU IOMMU driver for VFIO"
+
+struct vfio_iommu {
+ struct iommu_domain *domain;
+ struct mutex lock;
+ dma_addr_t aperture_start;
+ dma_addr_t aperture_end;
+ dma_addr_t page_size; /* Maximum mapped Page size */
+ int nsubwindows; /* Number of subwindows */
+ struct list_head dma_list;
+ struct list_head msi_dma_list;
+ struct list_head group_list;
+};
+
+struct vfio_dma {
+ struct list_head next;
+ dma_addr_t iova; /* Device address */
+ unsigned long vaddr; /* Process virtual addr */
+ long npage; /* Number of pages */
+ int prot; /* IOMMU_READ/WRITE */
+};
+
+struct vfio_msi_dma {
+ struct list_head next;
+ dma_addr_t iova; /* Device address */
+ int bank_id;
+ int prot; /* IOMMU_READ/WRITE */
+};
+
+struct vfio_group {
+ struct iommu_group *iommu_group;
+ struct list_head next;
+};
+
+/*
+ * This code handles mapping and unmapping of user data buffers
+ * into DMA'ble space using the IOMMU
+ */
+
+#define NPAGE_TO_SIZE(npage) ((size_t)(npage) << PAGE_SHIFT)
+
+struct vwork {
+ struct mm_struct *mm;
+ long npage;
+ struct work_struct work;
+};
+
+/* delayed decrement/increment for locked_vm */
+static void vfio_lock_acct_bg(struct work_struct *work)
+{
+ struct vwork *vwork = container_of(work, struct vwork, work);
+ struct mm_struct *mm;
+
+ mm = vwork->mm;
+ down_write(&mm->mmap_sem);
+ mm->locked_vm += vwork->npage;
+ up_write(&mm->mmap_sem);
+ mmput(mm);
+ kfree(vwork);
+}
+
+static void vfio_lock_acct(long npage)
+{
+ struct vwork *vwork;
+ struct mm_struct *mm;
+
+ if (!current->mm)
+ return; /* process exited */
+
+ if (down_write_trylock(&current->mm->mmap_sem)) {
+ current->mm->locked_vm += npage;
+ up_write(&current->mm->mmap_sem);
+ return;
+ }
+
+ /*
+ * Couldn't get mmap_sem lock, so must setup to update
+ * mm->locked_vm later. If locked_vm were atomic, we
+ * wouldn't need this silliness
+ */
+ vwork = kmalloc(sizeof(struct vwork), GFP_KERNEL);
+ if (!vwork)
+ return;
+ mm = get_task_mm(current);
+ if (!mm) {
+ kfree(vwork);
+ return;
+ }
+ INIT_WORK(&vwork->work, vfio_lock_acct_bg);
+ vwork->mm = mm;
+ vwork->npage = npage;
+ schedule_work(&vwork->work);
+}
+
+/*
+ * Some mappings aren't backed by a struct page, for example an mmap'd
+ * MMIO range for our own or another device. These use a different
+ * pfn conversion and shouldn't be tracked as locked pages.
+ */
+static bool is_invalid_reserved_pfn(unsigned long pfn)
+{
+ if (pfn_valid(pfn)) {
+ bool reserved;
+ struct page *tail = pfn_to_page(pfn);
+ struct page *head = compound_trans_head(tail);
+ reserved = !!(PageReserved(head));
+ if (head != tail) {
+ /*
+ * "head" is not a dangling pointer
+ * (compound_trans_head takes care of that)
+ * but the hugepage may have been split
+ * from under us (and we may not hold a
+ * reference count on the head page so it can
+ * be reused before we run PageReferenced), so
+ * we've to check PageTail before returning
+ * what we just read.
+ */
+ smp_rmb();
+ if (PageTail(tail))
+ return reserved;
+ }
+ return PageReserved(tail);
+ }
+
+ return true;
+}
+
+static int put_pfn(unsigned long pfn, int prot)
+{
+ if (!is_invalid_reserved_pfn(pfn)) {
+ struct page *page = pfn_to_page(pfn);
+ if (prot & IOMMU_WRITE)
+ SetPageDirty(page);
+ put_page(page);
+ return 1;
+ }
+ return 0;
+}
+
+static int vaddr_get_pfn(unsigned long vaddr, int prot, unsigned long *pfn,
+ unsigned int nr_pages)
+{
+ struct page **pages;
+ int ret = -EFAULT;
+ int i;
+
+ pages = kzalloc(sizeof(*pages) * nr_pages, GFP_KERNEL);
+ ret = get_user_pages_fast(vaddr, nr_pages, !!(prot & IOMMU_WRITE), pages);
+ if (ret != nr_pages)
+ goto error;
+
+ /* All Pages should be contigious */
+ for (i = 1; i < nr_pages; i++) {
+ if (page_to_pfn(pages[i]) != page_to_pfn(pages[i - 1]) + 1)
+ goto error;
+ }
+
+ *pfn = page_to_pfn(pages[0]);
+ kfree(pages);
+ return 0;
+error:
+ for (i = 0; i < nr_pages; i++)
+ put_page(pages[i]);
+ kfree(pages);
+ return -EFAULT;
+}
+
+static int iova_to_win(struct vfio_iommu *iommu, dma_addr_t iova)
+{
+ return (int) ((iova - iommu->aperture_start) / iommu->page_size);
+}
+
+/* Unmap DMA region */
+static long __vfio_dma_do_unmap(struct vfio_iommu *iommu, dma_addr_t iova_start,
+ long npage, int prot)
+{
+ int win, win_start, win_end, i;
+ long unlocked = 0;
+ unsigned long size;
+ unsigned int nr_pages;
+ dma_addr_t iova = iova_start;
+
+ size = npage << PAGE_SHIFT;
+ nr_pages = iommu->page_size / PAGE_SIZE;
+ /* Release the pinned pages */
+ while (size) {
+ unsigned long pfn;
+
+ pfn = iommu_iova_to_phys(iommu->domain, iova) >> PAGE_SHIFT;
+ if (pfn) {
+ for (i = 0; i < nr_pages; i++, pfn++)
+ unlocked += put_pfn(pfn, prot);
+ }
+
+ iova += iommu->page_size;
+ size -= iommu->page_size;
+ }
+
+ /* Disable the subwindows */
+ iova = iova_start;
+ win_start = iova_to_win(iommu, iova);
+ win_end = iova_to_win(iommu, iova + (npage << PAGE_SHIFT) - 1);
+ for (win = win_start; win <= win_end ; win++)
+ iommu_domain_window_disable(iommu->domain, win);
+
+ return unlocked;
+}
+
+static void vfio_dma_unmap(struct vfio_iommu *iommu, dma_addr_t iova,
+ long npage, int prot)
+{
+ long unlocked;
+
+ unlocked = __vfio_dma_do_unmap(iommu, iova, npage, prot);
+ vfio_lock_acct(-unlocked);
+}
+
+static int vfio_disable_iommu_domain(struct vfio_iommu *iommu)
+{
+ int enable = 0;
+ return iommu_domain_set_attr(iommu->domain,
+ DOMAIN_ATTR_FSL_PAMU_ENABLE, &enable);
+}
+
+static int vfio_enable_iommu_domain(struct vfio_iommu *iommu)
+{
+ int enable = 1;
+ return iommu_domain_set_attr(iommu->domain,
+ DOMAIN_ATTR_FSL_PAMU_ENABLE, &enable);
+}
+
+static inline bool ranges_overlap(dma_addr_t start1, size_t size1,
+ dma_addr_t start2, size_t size2)
+{
+ if (start1 < start2)
+ return (start2 - start1 < size1);
+ else if (start2 < start1)
+ return (start1 - start2 < size2);
+ return (size1 > 0 && size2 > 0);
+}
+
+static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu,
+ dma_addr_t start, size_t size)
+{
+ struct vfio_dma *dma;
+
+ list_for_each_entry(dma, &iommu->dma_list, next) {
+ if (ranges_overlap(dma->iova, NPAGE_TO_SIZE(dma->npage),
+ start, size))
+ return dma;
+ }
+ return NULL;
+}
+
+static long vfio_remove_dma_overlap(struct vfio_iommu *iommu, dma_addr_t start,
+ size_t size, struct vfio_dma *dma)
+{
+ struct vfio_dma *split;
+ long npage_lo, npage_hi;
+
+ /* Existing dma region is completely covered, unmap all */
+ if (start <= dma->iova &&
+ start + size >= dma->iova + NPAGE_TO_SIZE(dma->npage)) {
+ vfio_dma_unmap(iommu, dma->iova, dma->npage, dma->prot);
+ list_del(&dma->next);
+ npage_lo = dma->npage;
+ kfree(dma);
+ return npage_lo;
+ }
+
+ /* Overlap low address of existing range */
+ if (start <= dma->iova) {
+ size_t overlap;
+
+ overlap = start + size - dma->iova;
+ npage_lo = overlap >> PAGE_SHIFT;
+
+ vfio_dma_unmap(iommu, dma->iova, npage_lo, dma->prot);
+ dma->iova += overlap;
+ dma->vaddr += overlap;
+ dma->npage -= npage_lo;
+ return npage_lo;
+ }
+
+ /* Overlap high address of existing range */
+ if (start + size >= dma->iova + NPAGE_TO_SIZE(dma->npage)) {
+ size_t overlap;
+
+ overlap = dma->iova + NPAGE_TO_SIZE(dma->npage) - start;
+ npage_hi = overlap >> PAGE_SHIFT;
+
+ vfio_dma_unmap(iommu, start, npage_hi, dma->prot);
+ dma->npage -= npage_hi;
+ return npage_hi;
+ }
+
+ /* Split existing */
+ npage_lo = (start - dma->iova) >> PAGE_SHIFT;
+ npage_hi = dma->npage - (size >> PAGE_SHIFT) - npage_lo;
+
+ split = kzalloc(sizeof(*split), GFP_KERNEL);
+ if (!split)
+ return -ENOMEM;
+
+ vfio_dma_unmap(iommu, start, size >> PAGE_SHIFT, dma->prot);
+
+ dma->npage = npage_lo;
+
+ split->npage = npage_hi;
+ split->iova = start + size;
+ split->vaddr = dma->vaddr + NPAGE_TO_SIZE(npage_lo) + size;
+ split->prot = dma->prot;
+ list_add(&split->next, &iommu->dma_list);
+ return size >> PAGE_SHIFT;
+}
+
+/* Map DMA region */
+static int __vfio_dma_map(struct vfio_iommu *iommu, dma_addr_t iova,
+ unsigned long vaddr, long npage, int prot)
+{
+ dma_addr_t start = iova;
+ long locked = 0;
+ int ret, i;
+ unsigned long size;
+ unsigned int win, nr_subwindows;
+ dma_addr_t iova_map, iova_end;
+
+ /*
+ * XXX We break mappings into pages and use get_user_pages_fast to
+ * pin the pages in memory. It's been suggested that mlock might
+ * provide a more efficient mechanism, but nothing prevents the
+ * user from munlocking the pages, which could then allow the user
+ * access to random host memory. We also have no guarantee from the
+ * IOMMU API that the iommu driver can unmap sub-pages of previous
+ * mappings. This means we might lose an entire range if a single
+ * page within it is unmapped. Single page mappings are inefficient,
+ * but provide the most flexibility for now.
+ */
+ /* total size to be mapped */
+ size = npage << PAGE_SHIFT;
+ nr_subwindows = size / iommu->page_size;
+ iova_map = iova;
+ iova_end = iova + size;
+
+ for (i = 0; i < nr_subwindows; i++) {
+ unsigned long pfn;
+ unsigned long nr_pages;
+ dma_addr_t mapsize;
+
+ win = iova_to_win(iommu, iova_map);
+ if (iova_map != iommu->aperture_start + iommu->page_size * win) {
+ pr_err("%s iova (%llx) not alligned to window size %llx\n",
+ __func__, iova, iommu->page_size);
+ __vfio_dma_do_unmap(iommu, start, npage, prot);
+ return -EINVAL;
+ }
+
+ mapsize = min(iova_end - iova_map, iommu->page_size);
+ if (mapsize < iommu->page_size) {
+ pr_err("%s iova (%llx) not alligned to window size %llx\n",
+ __func__, iova, iommu->page_size);
+ __vfio_dma_do_unmap(iommu, start, npage, prot);
+ return -EINVAL;
+ }
+
+ nr_pages = mapsize >> PAGE_SHIFT;
+ ret = vaddr_get_pfn(vaddr, prot, &pfn, nr_pages);
+ if (ret) {
+ pr_err("%s unable to map vaddr = %lx\n",
+ __func__, vaddr);
+ __vfio_dma_do_unmap(iommu, start, npage, prot);
+ return ret;
+ }
+
+ if (!is_invalid_reserved_pfn(pfn))
+ locked++;
+
+
+ ret = iommu_domain_window_enable(iommu->domain, win,
+ (phys_addr_t)pfn << PAGE_SHIFT,
+ mapsize, prot);
+ if (ret) {
+ pr_err("%s unable to iommu_map()\n", __func__);
+ /* Back out mappings on error */
+ put_pfn(pfn, prot);
+ __vfio_dma_do_unmap(iommu, start, npage, prot);
+ return ret;
+ }
+
+ iova_map += mapsize;
+ vaddr += mapsize;
+ }
+ vfio_enable_iommu_domain(iommu);
+
+ vfio_lock_acct(locked);
+ return 0;
+}
+
+static int vfio_dma_do_map(struct vfio_iommu *iommu,
+ struct vfio_iommu_type1_dma_map *map)
+{
+ struct vfio_dma *dma, *pdma = NULL;
+ dma_addr_t iova = map->iova;
+ unsigned long locked, lock_limit, vaddr = map->vaddr;
+ size_t size = map->size;
+ int ret = 0, prot = 0;
+ long npage;
+
+ /* READ/WRITE from device perspective */
+ if (map->flags & VFIO_DMA_MAP_FLAG_WRITE)
+ prot |= IOMMU_WRITE;
+ if (map->flags & VFIO_DMA_MAP_FLAG_READ)
+ prot |= IOMMU_READ;
+
+ if (!prot)
+ return -EINVAL; /* No READ/WRITE? */
+
+ /* Don't allow IOVA wrap */
+ if (iova + size && iova + size < iova)
+ return -EINVAL;
+
+ /* Don't allow virtual address wrap */
+ if (vaddr + size && vaddr + size < vaddr)
+ return -EINVAL;
+
+ npage = size >> PAGE_SHIFT;
+ if (!npage)
+ return -EINVAL;
+
+ mutex_lock(&iommu->lock);
+
+ if (vfio_find_dma(iommu, iova, size)) {
+ ret = -EBUSY;
+ goto out_lock;
+ }
+
+ /* account for locked pages */
+ locked = current->mm->locked_vm + npage;
+ lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
+ if (locked > lock_limit && !capable(CAP_IPC_LOCK)) {
+ pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n",
+ __func__, rlimit(RLIMIT_MEMLOCK));
+ ret = -ENOMEM;
+ goto out_lock;
+ }
+
+ ret = __vfio_dma_map(iommu, iova, vaddr, npage, prot);
+ if (ret)
+ goto out_lock;
+
+ /* Check if we about a region below - nothing below 0 */
+ if (iova) {
+ dma = vfio_find_dma(iommu, iova - 1, 1);
+ if (dma && dma->prot == prot &&
+ dma->vaddr + NPAGE_TO_SIZE(dma->npage) == vaddr) {
+
+ dma->npage += npage;
+ iova = dma->iova;
+ vaddr = dma->vaddr;
+ npage = dma->npage;
+ size = NPAGE_TO_SIZE(npage);
+
+ pdma = dma;
+ }
+ }
+
+ /* Check if we abut a region above - nothing above ~0 + 1 */
+ if (iova + size) {
+ dma = vfio_find_dma(iommu, iova + size, 1);
+ if (dma && dma->prot == prot &&
+ dma->vaddr == vaddr + size) {
+
+ dma->npage += npage;
+ dma->iova = iova;
+ dma->vaddr = vaddr;
+
+ /*
+ * If merged above and below, remove previously
+ * merged entry. New entry covers it.
+ */
+ if (pdma) {
+ list_del(&pdma->next);
+ kfree(pdma);
+ }
+ pdma = dma;
+ }
+ }
+
+ /* Isolated, new region */
+ if (!pdma) {
+ dma = kzalloc(sizeof(*dma), GFP_KERNEL);
+ if (!dma) {
+ ret = -ENOMEM;
+ vfio_dma_unmap(iommu, iova, npage, prot);
+ goto out_lock;
+ }
+
+ dma->npage = npage;
+ dma->iova = iova;
+ dma->vaddr = vaddr;
+ dma->prot = prot;
+ list_add(&dma->next, &iommu->dma_list);
+ }
+
+out_lock:
+ mutex_unlock(&iommu->lock);
+ return ret;
+}
+
+static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
+ struct vfio_iommu_type1_dma_unmap *unmap)
+{
+ long ret = 0, npage = unmap->size >> PAGE_SHIFT;
+ struct vfio_dma *dma, *tmp;
+
+ mutex_lock(&iommu->lock);
+
+ list_for_each_entry_safe(dma, tmp, &iommu->dma_list, next) {
+ if (ranges_overlap(dma->iova, NPAGE_TO_SIZE(dma->npage),
+ unmap->iova, unmap->size)) {
+ ret = vfio_remove_dma_overlap(iommu, unmap->iova,
+ unmap->size, dma);
+ if (ret > 0)
+ npage -= ret;
+ if (ret < 0 || npage == 0)
+ break;
+ }
+ }
+
+ /* disable iommu if no mapping */
+ if (list_empty(&iommu->dma_list))
+ vfio_disable_iommu_domain(iommu);
+
+ mutex_unlock(&iommu->lock);
+ return ret > 0 ? 0 : (int)ret;
+}
+
+static int vfio_handle_get_attr(struct vfio_iommu *iommu,
+ struct vfio_pamu_attr *pamu_attr)
+{
+ switch (pamu_attr->attribute) {
+ case VFIO_ATTR_GEOMETRY: {
+ struct iommu_domain_geometry geom;
+ if (iommu_domain_get_attr(iommu->domain,
+ DOMAIN_ATTR_GEOMETRY, &geom)) {
+ pr_err("%s Error getting domain geometry\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ pamu_attr->attr_info.attr.aperture_start = geom.aperture_start;
+ pamu_attr->attr_info.attr.aperture_end = geom.aperture_end;
+ break;
+ }
+ case VFIO_ATTR_WINDOWS: {
+ u32 count;
+ if (iommu_domain_get_attr(iommu->domain,
+ DOMAIN_ATTR_WINDOWS, &count)) {
+ pr_err("%s Error getting domain windows\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ pamu_attr->attr_info.windows = count;
+ break;
+ }
+ case VFIO_ATTR_PAMU_STASH: {
+ struct pamu_stash_attribute stash;
+ if (iommu_domain_get_attr(iommu->domain,
+ DOMAIN_ATTR_FSL_PAMU_STASH, &stash)) {
+ pr_err("%s Error getting domain windows\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ pamu_attr->attr_info.stash.cpu = stash.cpu;
+ pamu_attr->attr_info.stash.cache = stash.cache;
+ break;
+ }
+
+ default:
+ pr_err("%s Error: Invalid attribute (%d)\n",
+ __func__, pamu_attr->attribute);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vfio_handle_set_attr(struct vfio_iommu *iommu,
+ struct vfio_pamu_attr *pamu_attr)
+{
+ switch (pamu_attr->attribute) {
+ case VFIO_ATTR_GEOMETRY: {
+ struct iommu_domain_geometry geom;
+
+ geom.aperture_start = pamu_attr->attr_info.attr.aperture_start;
+ geom.aperture_end = pamu_attr->attr_info.attr.aperture_end;
+ iommu->aperture_start = geom.aperture_start;
+ iommu->aperture_end = geom.aperture_end;
+ geom.force_aperture = 1;
+ if (iommu_domain_set_attr(iommu->domain,
+ DOMAIN_ATTR_GEOMETRY, &geom)) {
+ pr_err("%s Error setting domain geometry\n", __func__);
+ return -EFAULT;
+ }
+
+ break;
+ }
+ case VFIO_ATTR_WINDOWS: {
+ u32 count = pamu_attr->attr_info.windows;
+ u64 size;
+ if (count > 256) {
+ pr_err("Number of subwindows requested (%d) is 256\n",
+ count);
+ return -EINVAL;
+ }
+ iommu->nsubwindows = pamu_attr->attr_info.windows;
+ size = iommu->aperture_end - iommu->aperture_start + 1;
+ iommu->page_size = size / count;
+ if (iommu_domain_set_attr(iommu->domain,
+ DOMAIN_ATTR_WINDOWS, &count)) {
+ pr_err("%s Error getting domain windows\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ break;
+ }
+ case VFIO_ATTR_PAMU_STASH: {
+ struct pamu_stash_attribute stash;
+
+ stash.cpu = pamu_attr->attr_info.stash.cpu;
+ stash.cache = pamu_attr->attr_info.stash.cache;
+ if (iommu_domain_set_attr(iommu->domain,
+ DOMAIN_ATTR_FSL_PAMU_STASH, &stash)) {
+ pr_err("%s Error getting domain windows\n",
+ __func__);
+ return -EFAULT;
+ }
+ break;
+ }
+
+ default:
+ pr_err("%s Error: Invalid attribute (%d)\n",
+ __func__, pamu_attr->attribute);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vfio_msi_map(struct vfio_iommu *iommu,
+ struct vfio_pamu_msi_bank_map *msi_map, int prot)
+{
+ struct msi_region region;
+ int window;
+ int ret;
+
+ ret = msi_get_region(msi_map->msi_bank_index, &region);
+ if (ret) {
+ pr_err("%s MSI region (%d) not found\n", __func__,
+ msi_map->msi_bank_index);
+ return ret;
+ }
+
+ window = iova_to_win(iommu, msi_map->iova);
+ ret = iommu_domain_window_enable(iommu->domain, window, region.addr,
+ region.size, prot);
+ if (ret) {
+ pr_err("%s Error: unable to map msi region\n", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int vfio_do_msi_map(struct vfio_iommu *iommu,
+ struct vfio_pamu_msi_bank_map *msi_map)
+{
+ struct vfio_msi_dma *msi_dma;
+ int ret, prot = 0;
+
+ /* READ/WRITE from device perspective */
+ if (msi_map->flags & VFIO_DMA_MAP_FLAG_WRITE)
+ prot |= IOMMU_WRITE;
+ if (msi_map->flags & VFIO_DMA_MAP_FLAG_READ)
+ prot |= IOMMU_READ;
+
+ if (!prot)
+ return -EINVAL; /* No READ/WRITE? */
+
+ ret = vfio_msi_map(iommu, msi_map, prot);
+ if (ret)
+ return ret;
+
+ msi_dma = kzalloc(sizeof(*msi_dma), GFP_KERNEL);
+ if (!msi_dma)
+ return -ENOMEM;
+
+ msi_dma->iova = msi_map->iova;
+ msi_dma->bank_id = msi_map->msi_bank_index;
+ list_add(&msi_dma->next, &iommu->msi_dma_list);
+ return 0;
+}
+
+static void vfio_msi_unmap(struct vfio_iommu *iommu, dma_addr_t iova)
+{
+ int window;
+ window = iova_to_win(iommu, iova);
+ iommu_domain_window_disable(iommu->domain, window);
+}
+
+static int vfio_do_msi_unmap(struct vfio_iommu *iommu,
+ struct vfio_pamu_msi_bank_unmap *msi_unmap)
+{
+ struct vfio_msi_dma *mdma, *mdma_tmp;
+
+ list_for_each_entry_safe(mdma, mdma_tmp, &iommu->msi_dma_list, next) {
+ if (mdma->iova == msi_unmap->iova) {
+ vfio_msi_unmap(iommu, mdma->iova);
+ list_del(&mdma->next);
+ kfree(mdma);
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+static void *vfio_iommu_fsl_pamu_open(unsigned long arg)
+{
+ struct vfio_iommu *iommu;
+
+ if (arg != VFIO_FSL_PAMU_IOMMU)
+ return ERR_PTR(-EINVAL);
+
+ iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
+ if (!iommu)
+ return ERR_PTR(-ENOMEM);
+
+ INIT_LIST_HEAD(&iommu->group_list);
+ INIT_LIST_HEAD(&iommu->dma_list);
+ INIT_LIST_HEAD(&iommu->msi_dma_list);
+ mutex_init(&iommu->lock);
+
+ /*
+ * Wish we didn't have to know about bus_type here.
+ */
+ iommu->domain = iommu_domain_alloc(&pci_bus_type);
+ if (!iommu->domain) {
+ kfree(iommu);
+ return ERR_PTR(-EIO);
+ }
+
+ return iommu;
+}
+
+static void vfio_iommu_fsl_pamu_release(void *iommu_data)
+{
+ struct vfio_iommu *iommu = iommu_data;
+ struct vfio_group *group, *group_tmp;
+ struct vfio_dma *dma, *dma_tmp;
+ struct vfio_msi_dma *mdma, *mdma_tmp;
+
+ list_for_each_entry_safe(group, group_tmp, &iommu->group_list, next) {
+ iommu_detach_group(iommu->domain, group->iommu_group);
+ list_del(&group->next);
+ kfree(group);
+ }
+
+ list_for_each_entry_safe(dma, dma_tmp, &iommu->dma_list, next) {
+ vfio_dma_unmap(iommu, dma->iova, dma->npage, dma->prot);
+ list_del(&dma->next);
+ kfree(dma);
+ }
+
+ list_for_each_entry_safe(mdma, mdma_tmp, &iommu->msi_dma_list, next) {
+ vfio_msi_unmap(iommu, mdma->iova);
+ list_del(&mdma->next);
+ kfree(mdma);
+ }
+
+ iommu_domain_free(iommu->domain);
+ iommu->domain = NULL;
+ kfree(iommu);
+}
+
+static long vfio_iommu_fsl_pamu_ioctl(void *iommu_data,
+ unsigned int cmd, unsigned long arg)
+{
+ struct vfio_iommu *iommu = iommu_data;
+ unsigned long minsz;
+
+ if (cmd == VFIO_CHECK_EXTENSION) {
+ switch (arg) {
+ case VFIO_FSL_PAMU_IOMMU:
+ return 1;
+ default:
+ return 0;
+ }
+ } else if (cmd == VFIO_IOMMU_MAP_DMA) {
+ struct vfio_iommu_type1_dma_map map;
+ uint32_t mask = VFIO_DMA_MAP_FLAG_READ |
+ VFIO_DMA_MAP_FLAG_WRITE;
+
+ minsz = offsetofend(struct vfio_iommu_type1_dma_map, size);
+
+ if (copy_from_user(&map, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (map.argsz < minsz || map.flags & ~mask)
+ return -EINVAL;
+
+ return vfio_dma_do_map(iommu, &map);
+
+ } else if (cmd == VFIO_IOMMU_UNMAP_DMA) {
+ struct vfio_iommu_type1_dma_unmap unmap;
+
+ minsz = offsetofend(struct vfio_iommu_type1_dma_unmap, size);
+
+ if (copy_from_user(&unmap, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (unmap.argsz < minsz || unmap.flags)
+ return -EINVAL;
+
+ return vfio_dma_do_unmap(iommu, &unmap);
+ } else if (cmd == VFIO_IOMMU_PAMU_GET_ATTR) {
+ struct vfio_pamu_attr pamu_attr;
+
+ minsz = offsetofend(struct vfio_pamu_attr, attr_info);
+ if (copy_from_user(&pamu_attr, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (pamu_attr.argsz < minsz)
+ return -EINVAL;
+
+ vfio_handle_get_attr(iommu, &pamu_attr);
+
+ copy_to_user((void __user *)arg, &pamu_attr, minsz);
+ return 0;
+ } else if (cmd == VFIO_IOMMU_PAMU_SET_ATTR) {
+ struct vfio_pamu_attr pamu_attr;
+
+ minsz = offsetofend(struct vfio_pamu_attr, attr_info);
+ if (copy_from_user(&pamu_attr, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (pamu_attr.argsz < minsz)
+ return -EINVAL;
+
+ vfio_handle_set_attr(iommu, &pamu_attr);
+ return 0;
+ } else if (cmd == VFIO_IOMMU_PAMU_GET_MSI_BANK_COUNT) {
+ return msi_get_region_count();
+ } else if (cmd == VFIO_IOMMU_PAMU_MAP_MSI_BANK) {
+ struct vfio_pamu_msi_bank_map msi_map;
+
+ minsz = offsetofend(struct vfio_pamu_msi_bank_map, iova);
+ if (copy_from_user(&msi_map, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (msi_map.argsz < minsz)
+ return -EINVAL;
+ vfio_do_msi_map(iommu, &msi_map);
+ return 0;
+ } else if (cmd == VFIO_IOMMU_PAMU_UNMAP_MSI_BANK) {
+ struct vfio_pamu_msi_bank_unmap msi_unmap;
+
+ minsz = offsetofend(struct vfio_pamu_msi_bank_unmap, iova);
+ if (copy_from_user(&msi_unmap, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (msi_unmap.argsz < minsz)
+ return -EINVAL;
+
+ vfio_do_msi_unmap(iommu, &msi_unmap);
+ return 0;
+
+ }
+
+ return -ENOTTY;
+}
+
+static int vfio_iommu_fsl_pamu_attach_group(void *iommu_data,
+ struct iommu_group *iommu_group)
+{
+ struct vfio_iommu *iommu = iommu_data;
+ struct vfio_group *group, *tmp;
+ int ret;
+
+ group = kzalloc(sizeof(*group), GFP_KERNEL);
+ if (!group)
+ return -ENOMEM;
+
+ mutex_lock(&iommu->lock);
+
+ list_for_each_entry(tmp, &iommu->group_list, next) {
+ if (tmp->iommu_group == iommu_group) {
+ mutex_unlock(&iommu->lock);
+ kfree(group);
+ return -EINVAL;
+ }
+ }
+
+ ret = iommu_attach_group(iommu->domain, iommu_group);
+ if (ret) {
+ mutex_unlock(&iommu->lock);
+ kfree(group);
+ return ret;
+ }
+
+ group->iommu_group = iommu_group;
+ list_add(&group->next, &iommu->group_list);
+
+ mutex_unlock(&iommu->lock);
+
+ return 0;
+}
+
+static void vfio_iommu_fsl_pamu_detach_group(void *iommu_data,
+ struct iommu_group *iommu_group)
+{
+ struct vfio_iommu *iommu = iommu_data;
+ struct vfio_group *group;
+
+ mutex_lock(&iommu->lock);
+
+ list_for_each_entry(group, &iommu->group_list, next) {
+ if (group->iommu_group == iommu_group) {
+ iommu_detach_group(iommu->domain, iommu_group);
+ list_del(&group->next);
+ kfree(group);
+ break;
+ }
+ }
+
+ mutex_unlock(&iommu->lock);
+}
+
+static const struct vfio_iommu_driver_ops vfio_iommu_driver_ops_fsl_pamu = {
+ .name = "vfio-iommu-fsl_pamu",
+ .owner = THIS_MODULE,
+ .open = vfio_iommu_fsl_pamu_open,
+ .release = vfio_iommu_fsl_pamu_release,
+ .ioctl = vfio_iommu_fsl_pamu_ioctl,
+ .attach_group = vfio_iommu_fsl_pamu_attach_group,
+ .detach_group = vfio_iommu_fsl_pamu_detach_group,
+};
+
+static int __init vfio_iommu_fsl_pamu_init(void)
+{
+ if (!iommu_present(&pci_bus_type))
+ return -ENODEV;
+
+ return vfio_register_iommu_driver(&vfio_iommu_driver_ops_fsl_pamu);
+}
+
+static void __exit vfio_iommu_fsl_pamu_cleanup(void)
+{
+ vfio_unregister_iommu_driver(&vfio_iommu_driver_ops_fsl_pamu);
+}
+
+module_init(vfio_iommu_fsl_pamu_init);
+module_exit(vfio_iommu_fsl_pamu_cleanup);
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 84b685f..2a46153 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1976,6 +1976,17 @@ config FB_FSL_DIU
---help---
Framebuffer driver for the Freescale SoC DIU
+config FB_SSD1289
+ tristate "Solomon SSD1289 framebuffer support"
+ depends on FB
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SYS_FOPS
+ help
+ This is a framebuffer device for the Solomon Systek SSD1289
+ controller.
+
config FB_W100
tristate "W100 frame buffer support"
depends on FB && ARCH_PXA
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index e8bae8d..f5ef0ed 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -165,6 +165,7 @@ obj-$(CONFIG_FB_BFIN_7393) += bfin_adv7393fb.o
obj-$(CONFIG_FB_MX3) += mx3fb.o
obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o
obj-$(CONFIG_FB_MXS) += mxsfb.o
+obj-$(CONFIG_FB_SSD1289) += ssd1289fb.o
obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o
obj-$(CONFIG_FB_SIMPLE) += simplefb.o
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index 6dd7225..2673a75 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -48,6 +48,7 @@
#define INT_PARERR 0x08 /* Display parameters error interrupt */
#define INT_LS_BF_VS 0x10 /* Lines before vsync. interrupt */
+#define PIXCLKCR_PXCKEN 0x80000000
/*
* List of supported video modes
*
@@ -370,6 +371,8 @@ struct fsl_diu_data {
unsigned int irq;
enum fsl_diu_monitor_port monitor_port;
struct diu __iomem *diu_reg;
+ void __iomem *pixelclk_reg;
+ u32 pixclkcr[3];
spinlock_t reg_lock;
u8 dummy_aoi[4 * 4 * 4];
struct diu_ad dummy_ad __aligned(8);
@@ -477,7 +480,10 @@ static enum fsl_diu_monitor_port fsl_diu_name_to_port(const char *s)
port = FSL_DIU_PORT_DLVDS;
}
- return diu_ops.valid_monitor_port(port);
+ if (diu_ops.valid_monitor_port)
+ return diu_ops.valid_monitor_port(port);
+
+ return port;
}
/*
@@ -796,6 +802,35 @@ static void set_fix(struct fb_info *info)
fix->ypanstep = 1;
}
+static void set_pixel_clock(struct fsl_diu_data *data, unsigned int pixclock)
+{
+ unsigned long freq;
+ u64 temp;
+ u32 pxclk;
+ u32 pxclkdl_dir, pxckmax, pxclk_delay;
+
+ /* Convert pixclock from a wavelength to a frequency */
+ temp = 1000000000000ULL;
+ do_div(temp, pixclock);
+ freq = temp;
+
+ pxclkdl_dir = data->pixclkcr[0] << 30;
+ pxckmax = data->pixclkcr[1];
+ pxclk_delay = data->pixclkcr[2] << 8;
+
+ /*
+ * 'pxclk' is the ratio of the platform clock to the pixel clock.
+ * This number is programmed into the PIXCLKCR register, and the valid
+ * range of values is 2- pxckmax.
+ */
+ pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq);
+ pxclk = clamp_t(u32, pxclk, 2, pxckmax);
+
+ out_be32(data->pixelclk_reg, 0);
+ out_be32(data->pixelclk_reg, PIXCLKCR_PXCKEN
+ | pxclkdl_dir | (pxclk << 16) | pxclk_delay);
+}
+
static void update_lcdc(struct fb_info *info)
{
struct fb_var_screeninfo *var = &info->var;
@@ -844,7 +879,13 @@ static void update_lcdc(struct fb_info *info)
out_be32(&hw->vsyn_para, temp);
- diu_ops.set_pixel_clock(var->pixclock);
+ /* If the pixel clock setting function can not be used on the platform,
+ * then use the platform one.
+ */
+ if (diu_ops.set_pixel_clock)
+ diu_ops.set_pixel_clock(var->pixclock);
+ else
+ set_pixel_clock(data, var->pixclock);
#ifndef CONFIG_PPC_MPC512x
/*
@@ -1626,9 +1667,15 @@ static int fsl_diu_suspend(struct platform_device *ofdev, pm_message_t state)
static int fsl_diu_resume(struct platform_device *ofdev)
{
struct fsl_diu_data *data;
+ unsigned int i;
data = dev_get_drvdata(&ofdev->dev);
- enable_lcdc(data->fsl_diu_info);
+ fsl_diu_enable_interrupts(data);
+ update_lcdc(data->fsl_diu_info);
+ for (i = 0; i < NUM_AOIS; i++) {
+ if (data->mfb[i].count)
+ fsl_diu_enable_panel(&data->fsl_diu_info[i]);
+ }
return 0;
}
@@ -1744,6 +1791,24 @@ static int fsl_diu_probe(struct platform_device *pdev)
goto error;
}
+ if (!diu_ops.set_pixel_clock) {
+ data->pixelclk_reg = of_iomap(np, 1);
+ if (!data->pixelclk_reg) {
+ dev_err(&pdev->dev,
+ "Cannot map pixelclk register.\n");
+ ret = -EFAULT;
+ goto error;
+ }
+ /*Get the pixclkcr settings: PXCKDLYDIR; MAXPXCK, PXCKDLY*/
+ ret = of_property_read_u32_array(np, "pixclk",
+ data->pixclkcr, 3);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Cannot get pixelclk register information.\n");
+ goto error;
+ }
+ }
+
/* Get the IRQ of the DIU */
data->irq = irq_of_parse_and_map(np, 0);
diff --git a/drivers/video/ssd1289fb.c b/drivers/video/ssd1289fb.c
new file mode 100644
index 0000000..ea4d4bc
--- /dev/null
+++ b/drivers/video/ssd1289fb.c
@@ -0,0 +1,774 @@
+/*
+ * Copyright 2010-2011, 2013 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * Freescale SSD1289 TFT LCD framebuffer driver
+ *
+ * Author: Alison Wang <b18965@freescale.com>
+ * Jason Jin <Jason.jin@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/uaccess.h>
+#include <linux/timer.h>
+#include <linux/kthread.h>
+#include <linux/platform_data/video-twrfb.h>
+
+#ifdef CONFIG_PM
+#include <linux/pm.h>
+#endif
+
+#define SSD1289_REG_OSCILLATION 0x00
+#define SSD1289_REG_DRIVER_OUT_CTRL 0x01
+#define SSD1289_REG_LCD_DRIVE_AC 0x02
+#define SSD1289_REG_POWER_CTRL_1 0x03
+#define SSD1289_REG_COMPARE_1 0x05
+#define SSD1289_REG_COMPARE_2 0x06
+#define SSD1289_REG_DISPLAY_CTRL 0x07
+#define SSD1289_REG_FRAME_CYCLE 0x0b
+#define SSD1289_REG_POWER_CTRL_2 0x0c
+#define SSD1289_REG_POWER_CTRL_3 0x0d
+#define SSD1289_REG_POWER_CTRL_4 0x0e
+#define SSD1289_REG_GATE_SCAN_START 0x0f
+#define SSD1289_REG_SLEEP_MODE 0x10
+#define SSD1289_REG_ENTRY_MODE 0x11
+#define SSD1289_REG_OPT_SPEED_3 0x12
+#define SSD1289_REG_H_PORCH 0x16
+#define SSD1289_REG_V_PORCH 0x17
+#define SSD1289_REG_POWER_CTRL_5 0x1e
+#define SSD1289_REG_GDDRAM_DATA 0x22
+#define SSD1289_REG_WR_DATA_MASK_1 0x23
+#define SSD1289_REG_WR_DATA_MASK_2 0x24
+#define SSD1289_REG_FRAME_FREQUENCY 0x25
+#define SSD1289_REG_OPT_SPEED_1 0x28
+#define SSD1289_REG_OPT_SPEED_2 0x2f
+#define SSD1289_REG_GAMMA_CTRL_1 0x30
+#define SSD1289_REG_GAMMA_CTRL_2 0x31
+#define SSD1289_REG_GAMMA_CTRL_3 0x32
+#define SSD1289_REG_GAMMA_CTRL_4 0x33
+#define SSD1289_REG_GAMMA_CTRL_5 0x34
+#define SSD1289_REG_GAMMA_CTRL_6 0x35
+#define SSD1289_REG_GAMMA_CTRL_7 0x36
+#define SSD1289_REG_GAMMA_CTRL_8 0x37
+#define SSD1289_REG_GAMMA_CTRL_9 0x3a
+#define SSD1289_REG_GAMMA_CTRL_10 0x3b
+#define SSD1289_REG_V_SCROLL_CTRL_1 0x41
+#define SSD1289_REG_V_SCROLL_CTRL_2 0x42
+#define SSD1289_REG_H_RAM_ADR_POS 0x44
+#define SSD1289_REG_V_RAM_ADR_START 0x45
+#define SSD1289_REG_V_RAM_ADR_END 0x46
+#define SSD1289_REG_FIRST_WIN_START 0x48
+#define SSD1289_REG_FIRST_WIN_END 0x49
+#define SSD1289_REG_SECND_WIN_START 0x4a
+#define SSD1289_REG_SECND_WIN_END 0x4b
+#define SSD1289_REG_GDDRAM_X_ADDR 0x4e
+#define SSD1289_REG_GDDRAM_Y_ADDR 0x4f
+
+/* The register value definition */
+#define SSD1289_DEVICE_ID 0x8989
+#define SSD1289_OSC_ENABLE 0x0001
+#define SSD1289_OSC_DISABLE 0x0000
+#define SSD1289_DISPLAY_DISABLE 0x0200
+#define SSD1289_DISPLAY_ENABLE 0x0233
+#define SSD1289_POWER_CTRL1_VALUE 0xaeac
+#define SSD1289_POWER_CTRL2_VALUE 0x0007
+#define SSD1289_POWER_CTRL3_VALUE 0x000f
+#define SSD1289_POWER_CTRL4_VALUE 0x2900
+#define SSD1289_POWER_CTRL5_VALUE 0x00b3
+#define SSD1289_DRIVER_OUT_CTRL_VALUE 0x2b3f
+#define SSD1289_LCD_WAVE_INVERSION 0x0600
+#define SSD1289_SLEEP_MODE_ENABLE 0x0001
+#define SSD1289_SLEEP_MODE_DISABLE 0x0000
+#define SSD1289_ENTRY_MODE_64KCOLOR 0x60a8
+#define SSD1289_COMPARE_DISABLE 0x0000
+#define SSD1289_H_PORCH_VALUE 0xef1c
+#define SSD1289_V_PORCH_VALUE 0x0003
+#define SSD1289_FRAME_CYCLE_VALUE 0x5312
+#define SSD1289_V_SCROLL_LENGTH 0x0000
+#define SSD1289_GAMMA_CTRL1_VALUE 0x0707
+#define SSD1289_GAMMA_CTRL2_VALUE 0x0704
+#define SSD1289_GAMMA_CTRL3_VALUE 0x0204
+#define SSD1289_GAMMA_CTRL4_VALUE 0x0201
+#define SSD1289_GAMMA_CTRL5_VALUE 0x0203
+#define SSD1289_GAMMA_CTRL6_VALUE 0x0204
+#define SSD1289_GAMMA_CTRL7_VALUE 0x0204
+#define SSD1289_GAMMA_CTRL8_VALUE 0x0502
+#define SSD1289_GAMMA_CTRL9_VALUE 0x0302
+#define SSD1289_GAMMA_CTRL10_VALUE 0x0500
+#define SSD1289_FRAME_FREQUENCY_80HZ 0xe000
+#define SSD1289_OPT_SPEED1_VALUE 0x0006
+#define SSD1289_OPT_SPEED2_VALUE 0x12ae
+#define SSD1289_OPT_SPEED3_VALUE 0x6ceb
+#define SSD1289_H_RAM_ADR_POS_VALUE 0xef00
+#define SSD1289_GDDRAM_X_ADDR_VALUE 0x00ef
+#define SSD1289_GDDRAM_Y_ADDR_VALUE 0x0000
+#define SSD1289_WINDOW_Y_SIZE 0x013f
+
+
+struct ssd1289 {
+ unsigned short __iomem *cmd;
+ unsigned short __iomem *data;
+};
+
+struct fsl_ssd1289_fb_info {
+ struct device *dev;
+ struct ssd1289 ssd1289_reg;
+ int openflag;
+ struct spi_device *spidev;
+
+ struct task_struct *task;
+ unsigned long pseudo_palette[16];
+};
+
+static int ssd1289_set_reg(struct fb_info *info, unsigned short reg,
+ unsigned short data)
+{
+ struct fsl_ssd1289_fb_info *fbinfo = info->par;
+ unsigned short __iomem *cmd_addr, *data_addr;
+
+ cmd_addr = fbinfo->ssd1289_reg.cmd;
+ data_addr = fbinfo->ssd1289_reg.data;
+
+ out_be16(cmd_addr, reg);
+ out_be16(data_addr, data);
+
+ return 0;
+}
+
+static int ssd1289_write_data(struct fb_info *info, unsigned short *data,
+ size_t size)
+{
+ struct fsl_ssd1289_fb_info *fbinfo = info->par;
+ unsigned short __iomem *cmd_addr, *data_addr;
+ int i;
+ unsigned short tmp;
+
+ cmd_addr = fbinfo->ssd1289_reg.cmd;
+ data_addr = fbinfo->ssd1289_reg.data;
+
+ out_be16(cmd_addr, SSD1289_REG_GDDRAM_DATA);
+
+ if (data == NULL)
+ return 0;
+ else {
+ for (i = 0; i < size; i += 2) {
+ tmp = ((((*data) & 0x00ff) << 8) |
+ (((*data) & 0xff00) >> 8));
+ out_be16(data_addr, tmp);
+ data++;
+ }
+ }
+
+ return 0;
+}
+
+static void fsl_ssd1289_enable_lcd(struct fb_info *info)
+{
+ int i;
+
+ ssd1289_set_reg(info, SSD1289_REG_DISPLAY_CTRL,
+ SSD1289_DISPLAY_DISABLE);
+
+ ssd1289_set_reg(info, SSD1289_REG_OSCILLATION, SSD1289_OSC_DISABLE);
+
+ mdelay(100);
+
+ /* turn on the oscillator */
+ ssd1289_set_reg(info, SSD1289_REG_OSCILLATION, SSD1289_OSC_ENABLE);
+
+ mdelay(100);
+ /* power control 1 */
+ ssd1289_set_reg(info, SSD1289_REG_POWER_CTRL_1,
+ SSD1289_POWER_CTRL1_VALUE);
+
+ /* power control 2 */
+ ssd1289_set_reg(info, SSD1289_REG_POWER_CTRL_2,
+ SSD1289_POWER_CTRL2_VALUE);
+
+ /* power control 3 */
+ ssd1289_set_reg(info, SSD1289_REG_POWER_CTRL_3,
+ SSD1289_POWER_CTRL3_VALUE);
+
+ /* power control 4 */
+ ssd1289_set_reg(info, SSD1289_REG_POWER_CTRL_4,
+ SSD1289_POWER_CTRL4_VALUE);
+
+ /* power control 5 */
+ ssd1289_set_reg(info, SSD1289_REG_POWER_CTRL_5,
+ SSD1289_POWER_CTRL5_VALUE);
+
+ mdelay(15);
+ /* driver output control */
+ ssd1289_set_reg(info, SSD1289_REG_DRIVER_OUT_CTRL,
+ SSD1289_DRIVER_OUT_CTRL_VALUE);
+
+ /* lcd-driving-waveform control */
+ ssd1289_set_reg(info, SSD1289_REG_LCD_DRIVE_AC,
+ SSD1289_LCD_WAVE_INVERSION);
+
+ /* sleep mode */
+ ssd1289_set_reg(info, SSD1289_REG_SLEEP_MODE,
+ SSD1289_SLEEP_MODE_DISABLE);
+
+ /* entry mode */
+ ssd1289_set_reg(info, SSD1289_REG_ENTRY_MODE,
+ SSD1289_ENTRY_MODE_64KCOLOR);
+
+ mdelay(15);
+ /* compare register */
+ ssd1289_set_reg(info, SSD1289_REG_COMPARE_1,
+ SSD1289_COMPARE_DISABLE);
+
+ ssd1289_set_reg(info, SSD1289_REG_COMPARE_2,
+ SSD1289_COMPARE_DISABLE);
+
+ /* horizontal porch */
+ ssd1289_set_reg(info, SSD1289_REG_H_PORCH, SSD1289_H_PORCH_VALUE);
+
+ /* vertical porch */
+ ssd1289_set_reg(info, SSD1289_REG_V_PORCH, SSD1289_V_PORCH_VALUE);
+
+ /* display control */
+ ssd1289_set_reg(info, SSD1289_REG_DISPLAY_CTRL,
+ SSD1289_DISPLAY_ENABLE);
+
+ /* frame cycle control */
+ ssd1289_set_reg(info, SSD1289_REG_FRAME_CYCLE,
+ SSD1289_FRAME_CYCLE_VALUE);
+
+ /* gate scan position */
+ ssd1289_set_reg(info, SSD1289_REG_GATE_SCAN_START, 0x0000);
+
+ mdelay(20);
+ /* vertical scroll control */
+ ssd1289_set_reg(info, SSD1289_REG_V_SCROLL_CTRL_1,
+ SSD1289_V_SCROLL_LENGTH);
+
+ ssd1289_set_reg(info, SSD1289_REG_V_SCROLL_CTRL_2,
+ SSD1289_V_SCROLL_LENGTH);
+
+ /* 1st screen driving position */
+ ssd1289_set_reg(info, SSD1289_REG_FIRST_WIN_START, 0x0000);
+
+ ssd1289_set_reg(info, SSD1289_REG_FIRST_WIN_END,
+ SSD1289_WINDOW_Y_SIZE);
+
+ /* 2nd screen driving position */
+ ssd1289_set_reg(info, SSD1289_REG_SECND_WIN_START, 0x0000);
+
+ ssd1289_set_reg(info, SSD1289_REG_SECND_WIN_END, 0x0000);
+
+ mdelay(20);
+ /* gamma control */
+ ssd1289_set_reg(info, SSD1289_REG_GAMMA_CTRL_1,
+ SSD1289_GAMMA_CTRL1_VALUE);
+
+ ssd1289_set_reg(info, SSD1289_REG_GAMMA_CTRL_2,
+ SSD1289_GAMMA_CTRL2_VALUE);
+
+ ssd1289_set_reg(info, SSD1289_REG_GAMMA_CTRL_3,
+ SSD1289_GAMMA_CTRL3_VALUE);
+
+ ssd1289_set_reg(info, SSD1289_REG_GAMMA_CTRL_4,
+ SSD1289_GAMMA_CTRL4_VALUE);
+
+ ssd1289_set_reg(info, SSD1289_REG_GAMMA_CTRL_5,
+ SSD1289_GAMMA_CTRL5_VALUE);
+
+ ssd1289_set_reg(info, SSD1289_REG_GAMMA_CTRL_6,
+ SSD1289_GAMMA_CTRL6_VALUE);
+
+ ssd1289_set_reg(info, SSD1289_REG_GAMMA_CTRL_7,
+ SSD1289_GAMMA_CTRL7_VALUE);
+
+ ssd1289_set_reg(info, SSD1289_REG_GAMMA_CTRL_8,
+ SSD1289_GAMMA_CTRL8_VALUE);
+
+ ssd1289_set_reg(info, SSD1289_REG_GAMMA_CTRL_9,
+ SSD1289_GAMMA_CTRL9_VALUE);
+
+ ssd1289_set_reg(info, SSD1289_REG_GAMMA_CTRL_10,
+ SSD1289_GAMMA_CTRL10_VALUE);
+
+ /* ram write data mask */
+ ssd1289_set_reg(info, SSD1289_REG_WR_DATA_MASK_1, 0x0000);
+
+ ssd1289_set_reg(info, SSD1289_REG_WR_DATA_MASK_2, 0x0000);
+
+ /* frame frequency control */
+ ssd1289_set_reg(info, SSD1289_REG_FRAME_FREQUENCY,
+ SSD1289_FRAME_FREQUENCY_80HZ);
+
+ /* optimize data access speed */
+ ssd1289_set_reg(info, SSD1289_REG_OPT_SPEED_1,
+ SSD1289_OPT_SPEED1_VALUE);
+
+ ssd1289_set_reg(info, SSD1289_REG_OPT_SPEED_2,
+ SSD1289_OPT_SPEED2_VALUE);
+
+ ssd1289_set_reg(info, SSD1289_REG_OPT_SPEED_3,
+ SSD1289_OPT_SPEED3_VALUE);
+
+ /* horizontal ram address position */
+ ssd1289_set_reg(info, SSD1289_REG_H_RAM_ADR_POS,
+ SSD1289_H_RAM_ADR_POS_VALUE);
+
+ /* vertical ram address position */
+ ssd1289_set_reg(info, SSD1289_REG_V_RAM_ADR_START, 0x0000);
+
+ ssd1289_set_reg(info, SSD1289_REG_V_RAM_ADR_END,
+ SSD1289_WINDOW_Y_SIZE);
+
+ mdelay(20);
+
+ /* set start address counter */
+ ssd1289_set_reg(info, SSD1289_REG_GDDRAM_X_ADDR,
+ SSD1289_GDDRAM_X_ADDR_VALUE);
+
+ ssd1289_set_reg(info, SSD1289_REG_GDDRAM_Y_ADDR,
+ SSD1289_GDDRAM_Y_ADDR_VALUE);
+
+ for (i = 0; i < info->screen_size; i += 2)
+ ssd1289_set_reg(info, SSD1289_REG_GDDRAM_DATA, 0);
+}
+
+static void fsl_ssd1289_disable_lcd(struct fb_info *info)
+{
+ ssd1289_set_reg(info, SSD1289_REG_DISPLAY_CTRL,
+ SSD1289_DISPLAY_DISABLE);
+
+ ssd1289_set_reg(info, SSD1289_REG_OSCILLATION, SSD1289_OSC_DISABLE);
+}
+
+static int ssd1289fbd(void *arg)
+{
+ struct fb_info *info = arg;
+ unsigned short *buf_p;
+ struct fsl_ssd1289_fb_info *fbinfo = info->par;
+
+ while (!kthread_should_stop()) {
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ if (fbinfo->openflag == 1) {
+ buf_p = (unsigned short *)(info->screen_base);
+ ssd1289_write_data(info, buf_p, info->screen_size);
+ }
+ schedule_timeout(HZ/25);
+ }
+
+ return 0;
+}
+
+static int fsl_ssd1289_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ if (var->xres_virtual < var->xres)
+ var->xres_virtual = var->xres;
+ if (var->yres_virtual < var->yres)
+ var->yres_virtual = var->yres;
+
+ if (var->xoffset < 0)
+ var->xoffset = 0;
+
+ if (var->yoffset < 0)
+ var->yoffset = 0;
+
+ if (var->xoffset + info->var.xres > info->var.xres_virtual)
+ var->xoffset = info->var.xres_virtual - info->var.xres;
+
+ if (var->yoffset + info->var.yres > info->var.yres_virtual)
+ var->yoffset = info->var.yres_virtual - info->var.yres;
+
+ switch (var->bits_per_pixel) {
+ case 8:
+ /* 8 bpp, 332 format */
+ var->red.length = 3;
+ var->red.offset = 5;
+ var->red.msb_right = 0;
+
+ var->green.length = 3;
+ var->green.offset = 2;
+ var->green.msb_right = 0;
+
+ var->blue.length = 2;
+ var->blue.offset = 0;
+ var->blue.msb_right = 0;
+
+ var->transp.length = 0;
+ var->transp.offset = 0;
+ var->transp.msb_right = 0;
+ break;
+ case 16:
+ /* 16 bpp, 565 format */
+ var->red.length = 5;
+ var->red.offset = 11;
+ var->red.msb_right = 0;
+
+ var->green.length = 6;
+ var->green.offset = 5;
+ var->green.msb_right = 0;
+
+ var->blue.length = 5;
+ var->blue.offset = 0;
+ var->blue.msb_right = 0;
+
+ var->transp.length = 0;
+ var->transp.offset = 0;
+ var->transp.msb_right = 0;
+ break;
+ default:
+ printk(KERN_ERR "Depth not supported: %u BPP\n",
+ var->bits_per_pixel);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int fsl_ssd1289_set_par(struct fb_info *info)
+{
+ struct fb_var_screeninfo *var = &info->var;
+
+ switch (var->bits_per_pixel) {
+ case 16:
+ info->fix.visual = FB_VISUAL_TRUECOLOR;
+ break;
+ case 8:
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ break;
+ default:
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ break;
+ }
+
+ return 0;
+}
+
+static inline __u32 CNVT_TOHW(__u32 val, __u32 width)
+{
+ return ((val<<width) + 0x7FFF - val)>>16;
+}
+
+static int fsl_ssd1289_setcolreg(unsigned regno,
+ unsigned red, unsigned green, unsigned blue,
+ unsigned transp, struct fb_info *info)
+{
+ int ret = 1;
+
+ /*
+ * If greyscale is true, then we convert the RGB value
+ * to greyscale no matter what visual we are using.
+ */
+ if (info->var.grayscale)
+ red = green = blue = (19595 * red + 38470 * green +
+ 7471 * blue) >> 16;
+ switch (info->fix.visual) {
+ case FB_VISUAL_TRUECOLOR:
+ if (regno < 16) {
+ u32 *pal = info->pseudo_palette;
+ u32 value;
+
+ red = CNVT_TOHW(red, info->var.red.length);
+ green = CNVT_TOHW(green, info->var.green.length);
+ blue = CNVT_TOHW(blue, info->var.blue.length);
+ transp = CNVT_TOHW(transp, info->var.transp.length);
+
+ value = (red << info->var.red.offset) |
+ (green << info->var.green.offset) |
+ (blue << info->var.blue.offset) |
+ (transp << info->var.transp.offset);
+
+ pal[regno] = value;
+ ret = 0;
+ }
+ break;
+ case FB_VISUAL_STATIC_PSEUDOCOLOR:
+ case FB_VISUAL_PSEUDOCOLOR:
+ break;
+ }
+ return ret;
+}
+
+static int fsl_ssd1289_blank(int blank_mode, struct fb_info *info)
+{
+ if (blank_mode == FB_BLANK_POWERDOWN)
+ fsl_ssd1289_disable_lcd(info);
+ else
+ fsl_ssd1289_enable_lcd(info);
+
+ return 0;
+}
+
+static int fsl_ssd1289_open(struct fb_info *info, int user)
+{
+ struct fsl_ssd1289_fb_info *fbinfo = info->par;
+ struct task_struct *task;
+ int ret;
+
+ if (fbinfo->openflag == 0) {
+ memset(info->screen_base, 0, info->screen_size);
+ fsl_ssd1289_enable_lcd(info);
+
+ task = kthread_run(ssd1289fbd, info, "SSD1289 LCD");
+ if (IS_ERR(task)) {
+ ret = PTR_ERR(task);
+ return ret;
+ }
+ fbinfo->task = task;
+ }
+
+ fbinfo->openflag = 1;
+ return 0;
+}
+
+static int fsl_ssd1289_release(struct fb_info *info, int user)
+{
+ struct fsl_ssd1289_fb_info *fbinfo = info->par;
+
+ fbinfo->openflag = 0;
+ if (fbinfo->task) {
+ struct task_struct *task = fbinfo->task;
+ fbinfo->task = NULL;
+ kthread_stop(task);
+ }
+
+ memset(info->screen_base, 0, info->screen_size);
+ fsl_ssd1289_disable_lcd(info);
+
+ return 0;
+}
+
+static struct fb_ops fsl_ssd1289_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = fsl_ssd1289_check_var,
+ .fb_set_par = fsl_ssd1289_set_par,
+ .fb_setcolreg = fsl_ssd1289_setcolreg,
+ .fb_blank = fsl_ssd1289_blank,
+ .fb_open = fsl_ssd1289_open,
+ .fb_release = fsl_ssd1289_release,
+ .fb_copyarea = cfb_copyarea,
+ .fb_fillrect = cfb_fillrect,
+ .fb_imageblit = cfb_imageblit,
+};
+
+static int fsl_ssd1289_map_video_memory(struct fb_info *info,
+ struct platform_device *pdev)
+{
+ unsigned int map_size = info->fix.smem_len;
+ struct resource *ctrl_res;
+ struct resource *data_res;
+ unsigned short signature;
+ int ret;
+
+ struct fsl_ssd1289_fb_info *fbinfo = info->par;
+
+ ctrl_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!ctrl_res) {
+ printk(KERN_ERR
+ "%s: unable to platform_get_resource for ctrl_res\n",
+ __func__);
+ ret = -ENOENT;
+ return ret;
+ }
+ fbinfo->ssd1289_reg.cmd =
+ ioremap_nocache(ctrl_res->start, 2);
+
+ data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!data_res) {
+ printk(KERN_ERR
+ "%s: unable to platform_get_resource for data_res\n",
+ __func__);
+ ret = -ENOENT;
+ goto out_item1;
+ }
+ fbinfo->ssd1289_reg.data =
+ ioremap_nocache(data_res->start, 2);
+
+ signature = in_be16(fbinfo->ssd1289_reg.cmd);
+ if (signature != SSD1289_DEVICE_ID) {
+ ret = -ENODEV;
+ printk(KERN_ERR
+ "%s: unknown signature 0x%04x\n", __func__, signature);
+ goto out_item2;
+ }
+
+ info->screen_base = kmalloc(map_size, GFP_KERNEL);
+ info->fix.smem_start = virt_to_phys(info->screen_base);
+ info->screen_size = info->fix.smem_len;
+
+ if (info->screen_base)
+ memset(info->screen_base, 0, map_size);
+
+ return info->screen_base ? 0 : -ENOMEM;
+out_item2:
+ iounmap(fbinfo->ssd1289_reg.cmd);
+out_item1:
+ iounmap(fbinfo->ssd1289_reg.data);
+ return ret;
+}
+
+static inline void fsl_ssd1289_unmap_video_memory(struct fb_info *info)
+{
+ struct fsl_ssd1289_fb_info *fbinfo = info->par;
+
+ iounmap(fbinfo->ssd1289_reg.cmd);
+ iounmap(fbinfo->ssd1289_reg.data);
+ kfree(info->screen_base);
+}
+
+static int fsl_ssd1289_probe(struct platform_device *pdev)
+{
+ struct fsl_ssd1289_fb_info *fbinfo;
+ struct fb_info *info;
+ struct fsl_ssd1289_fb_display *display;
+ int ret;
+ unsigned long smem_len;
+
+ info = framebuffer_alloc(sizeof(struct fsl_ssd1289_fb_info),
+ &pdev->dev);
+ if (!info)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, info);
+
+ fbinfo = info->par;
+ fbinfo->dev = &pdev->dev;
+ display = pdev->dev.platform_data;
+
+ fbinfo->openflag = 0;
+ info->fix.type = FB_TYPE_PACKED_PIXELS;
+ info->fix.type_aux = 0;
+ info->fix.xpanstep = 0;
+ info->fix.ypanstep = 0;
+ info->fix.ywrapstep = 0;
+ info->fix.accel = FB_ACCEL_NONE;
+
+ info->var.nonstd = 0;
+ info->var.activate = FB_ACTIVATE_NOW;
+ info->var.accel_flags = 0;
+ info->var.vmode = FB_VMODE_NONINTERLACED;
+
+ info->fbops = &fsl_ssd1289_ops;
+ info->flags = FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT
+ | FBINFO_HWACCEL_COPYAREA;
+ info->pseudo_palette = &fbinfo->pseudo_palette;
+
+ /* find maximum required memory size for display */
+ smem_len = display->xres;
+ smem_len *= display->yres;
+ smem_len *= display->bpp;
+ smem_len >>= 3;
+ if (info->fix.smem_len < smem_len)
+ info->fix.smem_len = smem_len;
+
+ /* Intialize video memory */
+ ret = fsl_ssd1289_map_video_memory(info, pdev);
+ if (ret) {
+ printk(KERN_ERR "Failed to allocate video RAM: %d\n", ret);
+ ret = -ENOMEM;
+ goto dealloc_fb;
+ }
+
+ info->var.xres = display->xres;
+ info->var.yres = display->yres;
+ info->var.bits_per_pixel = display->bpp;
+ info->fix.line_length = (info->var.xres * info->var.bits_per_pixel) / 8;
+
+ fsl_ssd1289_check_var(&info->var, info);
+
+ ret = register_framebuffer(info);
+ if (ret < 0) {
+ printk(KERN_ERR "Failed to register framebuffer device: %d\n",
+ ret);
+ goto free_video_memory;
+ }
+
+ printk(KERN_INFO "fb: SSD1289 TFT LCD Framebuffer Driver\n");
+ return 0;
+
+free_video_memory:
+ fsl_ssd1289_unmap_video_memory(info);
+dealloc_fb:
+ platform_set_drvdata(pdev, NULL);
+ framebuffer_release(info);
+ return ret;
+}
+
+static int fsl_ssd1289_remove(struct platform_device *pdev)
+{
+ struct fb_info *info = platform_get_drvdata(pdev);
+
+ platform_set_drvdata(pdev, NULL);
+ unregister_framebuffer(info);
+ fsl_ssd1289_unmap_video_memory(info);
+ framebuffer_release(info);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int fsl_ssd1289_suspend(struct platform_device *dev, pm_message_t state)
+{
+ struct fb_info *info = platform_get_drvdata(dev);
+
+ /* enter into sleep mode */
+ ssd1289_set_reg(info, SSD1289_REG_SLEEP_MODE,
+ SSD1289_SLEEP_MODE_ENABLE);
+ return 0;
+}
+
+static int fsl_ssd1289_resume(struct platform_device *dev)
+{
+ struct fb_info *info = platform_get_drvdata(dev);
+
+ /* leave sleep mode */
+ ssd1289_set_reg(info, SSD1289_REG_SLEEP_MODE,
+ SSD1289_SLEEP_MODE_DISABLE);
+ return 0;
+}
+#else
+#define fsl_ssd1289_suspend NULL
+#define fsl_ssd1289_resume NULL
+#endif
+
+static struct platform_driver fsl_ssd1289_driver = {
+ .probe = fsl_ssd1289_probe,
+ .remove = fsl_ssd1289_remove,
+ .suspend = fsl_ssd1289_suspend,
+ .resume = fsl_ssd1289_resume,
+ .driver = {
+ .name = "ssd1289",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init fsl_ssd1289_init(void)
+{
+ return platform_driver_register(&fsl_ssd1289_driver);
+}
+
+static void __exit fsl_ssd1289_exit(void)
+{
+ return platform_driver_unregister(&fsl_ssd1289_driver);
+}
+
+module_init(fsl_ssd1289_init);
+module_exit(fsl_ssd1289_exit);
+
+MODULE_AUTHOR("Alison Wang <b18965@freescale.com>");
+MODULE_DESCRIPTION("Freescale SSD1289 TFT LCD Framebuffer Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index d1d53f3..b27b75d 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1169,7 +1169,7 @@ config PIKA_WDT
config BOOKE_WDT
tristate "PowerPC Book-E Watchdog Timer"
- depends on BOOKE || 4xx
+ depends on (BOOKE || 4xx) && !FSL_ERRATUM_A_006184
select WATCHDOG_CORE
---help---
Watchdog driver for PowerPC Book-E chips, such as the Freescale
diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c
index f1b8d55..9a4d02b 100644
--- a/drivers/watchdog/booke_wdt.c
+++ b/drivers/watchdog/booke_wdt.c
@@ -106,6 +106,15 @@ static void __booke_wdt_set(void *data)
val = mfspr(SPRN_TCR);
val &= ~WDTP_MASK;
+
+#ifdef CONFIG_PPC_BOOK3E_64
+ /*
+ * Crit ints are currently broken on PPC64 Book-E, so
+ * just disable them for now.
+ */
+ val &= ~TCR_WIE;
+#endif
+
val |= WDTP(booke_wdt_period);
mtspr(SPRN_TCR, val);
@@ -138,14 +147,6 @@ static void __booke_wdt_enable(void *data)
val &= ~WDTP_MASK;
val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period));
-#ifdef CONFIG_PPC_BOOK3E_64
- /*
- * Crit ints are currently broken on PPC64 Book-E, so
- * just disable them for now.
- */
- val &= ~TCR_WIE;
-#endif
-
mtspr(SPRN_TCR, val);
}